diff options
author | Cy Schubert <cy@FreeBSD.org> | 2013-08-11 14:28:45 +0000 |
---|---|---|
committer | Cy Schubert <cy@FreeBSD.org> | 2013-08-11 14:28:45 +0000 |
commit | 05ddbb8d93073fe6263bb3fff26e1c4c8651352e (patch) | |
tree | 1edb84380ee8d48a5e93a53f33d1b6373e330d5e | |
parent | c63520fcdd8c7ba7a737717520fa3896db69342f (diff) |
Notes
937 files changed, 111223 insertions, 49116 deletions
diff --git a/.cvsignore b/.cvsignore index 616828f4144d5..1e12757928ce5 100644 --- a/.cvsignore +++ b/.cvsignore @@ -1,28 +1,43 @@ -ipf -sparcv7 -sparcv9 -h -ipf-darren -bugs -ipftest -patches -state -cbits CVS -old -new -netinet -import +amd64 bak -streams +bugs +cbits cvs.diff -threads +cvs.diffs +extern glibc +h hp -windows +i86 +import +ipf +ipf-darren +ipfstat +ipftest ipnat -opt_inet6.h ippool ipmon -ip_rules.c +ipscan +ipsyncm +ipsyncs ip_rules.h +ip_rules.c +net +netinet +new +old +opt_bpf.h +opt_inet6.h +opt_pfil.h +patches +sparcv7 +sparcv9 +state +streams +threads +windows +SunOS5/i386-5.10 +*.o +*/*.o +*/*/*.o diff --git a/4bsd/conf.c.diffs b/4bsd/conf.c.diffs new file mode 100644 index 0000000000000..b40324b4d8eb8 --- /dev/null +++ b/4bsd/conf.c.diffs @@ -0,0 +1,41 @@ +*** conf.c.orig Wed May 10 23:38:08 1995 +--- conf.c Thu May 11 00:33:19 1995 +*************** +*** 169,174 **** +--- 169,187 ---- + #endif + cdev_decl(lkm); + ++ /* open, close, read, ioctl */ ++ cdev_decl(ipl); ++ #define cdev_gen_ipf(c,n) { \ ++ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ ++ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ ++ (dev_type_stop((*))) nullop, 0, (dev_type_select((*))) enodev, \ ++ (dev_type_mmap((*))) enodev, 0 } ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + struct cdevsw cdevsw[] = + { + cdev_cn_init(1,cn), /* 0: virtual console */ +*************** +*** 232,238 **** + cdev_notdef(), /* 56 */ + cdev_notdef(), /* 57 */ + cdev_disk_init(NCD,cd), /* 58 SCSI CD-ROM */ +! cdev_notdef(), /* 59 */ + cdev_notdef(), /* 60 */ + cdev_notdef(), /* 61 */ + cdev_notdef(), /* 62 */ +--- 245,251 ---- + cdev_notdef(), /* 56 */ + cdev_notdef(), /* 57 */ + cdev_disk_init(NCD,cd), /* 58 SCSI CD-ROM */ +! cdev_gen_ipf(NIPF,ipl), /* 59 */ + cdev_notdef(), /* 60 */ + cdev_notdef(), /* 61 */ + cdev_notdef(), /* 62 */ diff --git a/4bsd/files.diffs b/4bsd/files.diffs new file mode 100644 index 0000000000000..a09b9c653c219 --- /dev/null +++ b/4bsd/files.diffs @@ -0,0 +1,23 @@ +*** files.orig Sat Apr 29 19:59:31 1995 +--- files Sun Apr 23 17:54:18 1995 +*************** +*** 180,185 **** +--- 180,197 ---- + netinet/tcp_timer.c optional inet + netinet/tcp_usrreq.c optional inet + netinet/udp_usrreq.c optional inet ++ netinet/ip_fil.c optional ipfilter requires inet ++ netinet/fil.c optional ipfilter requires inet ++ netinet/ip_nat.c optional ipfilter requires inet ++ netinet/ip_auth.c optional ipfilter requires inet ++ netinet/ip_frag.c optional ipfilter requires inet ++ netinet/ip_state.c optional ipfilter requires inet ++ netinet/ip_proxy.c optional ipfilter requires inet ++ netinet/ip_log.c optional ipfilter requires inet ++ netinet/ip_scan.c optional ipfilter requires inet ++ netinet/ip_sync.c optional ipfilter requires inet ++ netinet/ip_pool.c optional ipfilter_pool requires inet ++ netinet/ip_rules.c optional ipfilter_compiled requires ipfilter + netiso/clnp_debug.c optional iso + netiso/clnp_er.c optional iso + netiso/clnp_frag.c optional iso diff --git a/4bsd/files.newconf.diffs b/4bsd/files.newconf.diffs new file mode 100644 index 0000000000000..e616cfd95de22 --- /dev/null +++ b/4bsd/files.newconf.diffs @@ -0,0 +1,23 @@ +*** files.newconf.orig Sat Apr 29 20:00:02 1995 +--- files.newconf Sun Apr 23 17:53:58 1995 +*************** +*** 222,227 **** +--- 222,239 ---- + file netinet/tcp_timer.c inet + file netinet/tcp_usrreq.c inet + file netinet/udp_usrreq.c inet ++ file netinet/ip_fil.c ipfilter ++ file netinet/fil.c ipfilter ++ file netinet/ip_nat.c ipfilter ++ file netinet/ip_frag.c ipfilter ++ file netinet/ip_state.c ipfilter ++ file netinet/ip_auth.c ipfilter ++ file netinet/ip_proxy.c ipfilter ++ file netinet/ip_log.c ipfilter ++ file netinet/ip_scan.c ipfilter ++ file netinet/ip_sync.c ipfilter ++ file netinet/ip_pool.c ipfilter_pool ++ file netinet/ip_rules.c ipfilter_compiled + file netiso/clnp_debug.c iso + file netiso/clnp_er.c iso + file netiso/clnp_frag.c iso diff --git a/4bsd/files.oldconf.diffs b/4bsd/files.oldconf.diffs new file mode 100644 index 0000000000000..87614a76d4898 --- /dev/null +++ b/4bsd/files.oldconf.diffs @@ -0,0 +1,23 @@ +*** files.oldconf.orig Sat Apr 29 19:59:31 1995 +--- files.oldconf Sun Apr 23 17:54:18 1995 +*************** +*** 180,185 **** +--- 180,197 ---- + netinet/tcp_timer.c optional inet + netinet/tcp_usrreq.c optional inet + netinet/udp_usrreq.c optional inet ++ netinet/ip_fil.c optional ipfilter requires inet ++ netinet/fil.c optional ipfilter requires inet ++ netinet/ip_nat.c optional ipfilter requires inet ++ netinet/ip_frag.c optional ipfilter requires inet ++ netinet/ip_state.c optional ipfilter requires inet ++ netinet/ip_proxy.c optional ipfilter requires inet ++ netinet/ip_log.c optional ipfilter requires inet ++ netinet/ip_auth.c optional ipfilter requires inet ++ netinet/ip_scan.c optional ipfilter requires inet ++ netinet/ip_sync.c optional ipfilter requires inet ++ netinet/ip_pool.c optional ipfilter_pool requires inet ++ netinet/ip_rules.c optional ipfilter_compiled requires ipfilter + netiso/clnp_debug.c optional iso + netiso/clnp_er.c optional iso + netiso/clnp_frag.c optional iso diff --git a/4bsd/filez.diffs b/4bsd/filez.diffs new file mode 100644 index 0000000000000..de2453ac9c763 --- /dev/null +++ b/4bsd/filez.diffs @@ -0,0 +1,23 @@ +*** files.orig Sat Apr 29 20:00:02 1995 +--- files Sun Apr 23 17:53:58 1995 +*************** +*** 222,227 **** +--- 222,239 ---- + file netinet/tcp_timer.c inet + file netinet/tcp_usrreq.c inet + file netinet/udp_usrreq.c inet ++ file netinet/ip_fil.c ipfilter ++ file netinet/fil.c ipfilter ++ file netinet/ip_nat.c ipfilter ++ file netinet/ip_frag.c ipfilter ++ file netinet/ip_state.c ipfilter ++ file netinet/ip_proxy.c ipfilter ++ file netinet/ip_auth.c ipfilter ++ file netinet/ip_log.c ipfilter ++ file netinet/ip_scan.c ipfilter ++ file netinet/ip_sync.c ipfilter ++ file netinet/ip_pool.c ipfilter_pool ++ file netinet/ip_rules.c ipfilter_compiled + file netiso/clnp_debug.c iso + file netiso/clnp_er.c iso + file netiso/clnp_frag.c iso diff --git a/4bsd/ip_input.c.diffs b/4bsd/ip_input.c.diffs new file mode 100644 index 0000000000000..37044d58971f5 --- /dev/null +++ b/4bsd/ip_input.c.diffs @@ -0,0 +1,38 @@ +*** ip_input.c.orig Sun Apr 23 17:17:05 1995 +--- ip_input.c Sun Apr 23 17:30:03 1995 +*************** +*** 80,85 **** +--- 80,90 ---- + int ipqmaxlen = IFQ_MAXLEN; + struct in_ifaddr *in_ifaddr; /* first inet address */ + struct ifqueue ipintrq; ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ int fr_check __P((struct ip *, int, struct ifnet *, int, struct mbuf *)); ++ int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf *)); ++ #endif + + /* + * We need to save the IP options in case a protocol wants to respond +*************** +*** 225,231 **** +--- 233,252 ---- + m_adj(m, ip->ip_len - m->m_pkthdr.len); + } + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) + /* ++ * Check if we want to allow this packet to be processed. ++ * Consider it to be bad if not. ++ */ ++ if (fr_checkp) { ++ struct mbuf *m1 = m; ++ ++ if ((*fr_checkp)(ip, hlen, m->m_pkthdr.rcvif, 0, &m1) || !m1) ++ goto next; ++ ip = mtod(m = m1, struct ip *); ++ } ++ #endif ++ /* + * Process options and, if not destined for us, + * ship it on. ip_dooptions returns 1 when an + * error was detected (causing an icmp message diff --git a/4bsd/ip_output.c.diffs b/4bsd/ip_output.c.diffs new file mode 100644 index 0000000000000..4b0350a6d6ac1 --- /dev/null +++ b/4bsd/ip_output.c.diffs @@ -0,0 +1,36 @@ +*** ip_output.c.orig Sun Apr 23 17:17:05 1995 +--- ip_output.c Sun Apr 23 17:32:11 1995 +*************** +*** 60,65 **** +--- 60,69 ---- + static struct mbuf *ip_insertoptions __P((struct mbuf *, struct mbuf *, int *)); + static void ip_mloopback + __P((struct ifnet *, struct mbuf *, struct sockaddr_in *)); ++ #if defined(IPFILTER_LKM) || defined(IPFILTER) ++ extern int fr_check __P((struct ip *, int, struct ifnet *, int, struct mbuf *)); ++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf *)); ++ #endif + + /* + * IP output. The packet in mbuf chain m contains a skeletal IP +*************** +*** 277,282 **** +--- 284,303 ---- + } else + m->m_flags &= ~M_BCAST; + + sendit: ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * looks like most checking has been done now...do a filter check ++ */ ++ if (fr_checkp) { ++ struct mbuf *m1 = m; ++ ++ if ((error = (*fr_checkp)(ip, hlen, ifp, 1, &m1)) || !m1) ++ goto done; ++ ip = mtod(m = m1, struct ip *); ++ } ++ #endif + /* + * If small enough for interface, can just send directly. diff --git a/4bsd/kinstall b/4bsd/kinstall new file mode 100755 index 0000000000000..5f97ca0cc2404 --- /dev/null +++ b/4bsd/kinstall @@ -0,0 +1,55 @@ +#!/bin/csh -f +# +set dir=`pwd` +set karch=`uname -m` +set archdir="/sys/arch/$karch" +set confdir="$archdir/conf" + +if ( $dir =~ *fil/4bsd ) cd .. +if ($0 =~ *kinstall) then + echo "Installing ip_fil.c and ip_fil.h" + cp ip_fil.{c,h} /sys/netinet + echo "Patching $archdir/$karch/conf.c" + cat conf.c.diffs | (cd $archdir/$karch; patch) +endif +echo "Patching ip_input.c and ip_output.c" +cat 4bsd/ip_{in,out}put.c.diffs | (cd /sys/netinet; patch) + +if ( -f /sys/conf/files.newconf ) then + echo "Patching /sys/conf/files.newconf" + cat 4bsd/files.newconf.diffs | (cd /sys/conf; patch) + echo "Patching /sys/conf/files" + cat 4bsd/files.diffs | (cd /sys/conf; patch) +endif +if ( -f /sys/conf/files.oldconf ) then + echo "Patching /sys/conf/files.oldconf" + cat 4bsd/files.oldconf.diffs | (cd /sys/conf; patch) + echo "Patching /sys/conf/files" + cat 4bsd/filez.diffs | (cd /sys/conf; patch) +endif + +set config=`/bin/ls -1t $confdir [0-9A-Z_]* | head -1` + +echo -n "Kernel configuration to update [$config] " +set newconfig=$< +if ( "$newconfig" != "" ) then + set config="$confdir/$newconfig" +else + set newconfig=$config +endif +echo "Re-config'ing $newconfig..." +if ( -f $confdir/$newconfig ) then + mv $confdir/$newconfig $confdir/$newconfig.bak +endif +if ( -d $archdir/$newconfig ) then + mv $archdir/$newconfig $archdir/$newconfig.bak +endif +if ($0 =~ *kinstall) then + awk '{print $0;if($2=="INET"){print"options IPFILTER"}}}' \ + $confdir/$newconfig.bak > $confdir/$newconfig +else + awk '{print $0;if($2=="INET"){print"options IPFILTER_LKM"}}' \ + $confdir/$newconfig.bak > $confdir/$newconfig +endif +echo 'You will now need to run "config" and build a new kernel.' +exit 0 diff --git a/AIX/Makefile b/AIX/Makefile new file mode 100644 index 0000000000000..f48c3941bb243 --- /dev/null +++ b/AIX/Makefile @@ -0,0 +1,401 @@ +# +# Copyright (C) 2012 by Darren Reed. +# +# See the IPFILTER.LICENCE file for details on licencing. +# +BINDEST=/usr/sbin +SBINDEST=/sbin +MANDIR=/usr/share/man +CC=cc +CFLAGS=-g -I$(TOP) +DEBUG=-O3 +# +# For AIX 5.3 +# +CPU=`uname -p` +INC=-I/usr/include +DEF=-D$(CPU) -D__$(CPU)__ -DINET -DKERNEL -D_KERNEL $(INC) +LKM=ipf +DLKM= +OBJ=. +TOP=.. +HERE=AIX/$(OSREV) +AIX=`uname -v` +DEST=. +MFLAGS="BINDEST=$(BINDEST)" "SBINDEST=$(SBINDEST)" "MANDIR=$(MANDIR)" \ + 'CFLAGS=$(CFLAGS)' "IPFLKM=$(IPFLKM)" \ + "IPFLOG=$(IPFLOG)" "LOGFAC=$(LOGFAC)" "POLICY=$(POLICY)" \ + "DEBUG=$(DEBUG)" "DCPU=$(CPU)" "CPUDIR=$(CPUDIR)" \ + "LOOKUP=$(LOOKUP)" "XID=$(XID)" "SCAN=$(SCAN)" "ALLOPTS=$(ALLOPTS)" +LIBS=-q$(BITS) -L. -lipf +CCARGS=$(DEBUG) $(CFLAGS) -I. -DAIX=$(AIX) -q$(BITS) +EXTRA=$(ALLOPTS) +MILLI=`../bootbits.sh` +FIXMILLI=-D_H_STRING=1 -Dbzero=bzero$(MILLI) \ +-Dmemcmp=memcmp$(MILLI) \ +-Dmemcpy=memcpy$(MILLI) \ +-Dmemccpy=memccpy$(MILLI) \ +-Dmemset=memset$(MILLI) \ +-Dmemmove=memmove$(MILLI) \ +-Dfill=fill$(MILLI) \ +-Dstrstr=strstr$(MILLI) +# +########## ########## ########## ########## ########## ########## ########## +# +CP=/bin/cp +RM=/bin/rm +CHMOD=/bin/chmod +INSTALL=$(TOP)/bsdinstall +# +MODOBJS=ip_fil.o fil.o md5.o ip_nat.o ip_frag.o ip_state.o ip_nat6.o \ + ip_proxy.o ip_auth.o ip_log.o ip_pool.o ip_htable.o ip_lookup.o \ + ip_sync.o ip_scan.o ip_rules.o +DFLAGS=$(DEBUG) -DAIX=$(AIX) $(IPFLKM) $(IPFLOG) $(DEF) $(CFLAGS) $(DLKM) \ + $(FIXMILLI) $(IPFBPF) $(LOOKUP) $(XID) -I. +IPF=ipf.o ipfcomp.o ipf_y.o ipf_l.o +IPT=ipftest.o fil_u.o ip_frag_u.o ip_state_u.o ip_nat_u.o ip_nat6_u.o \ + ip_proxy_u.o ip_auth_u.o ip_fil_u.o ip_sync_u.o ip_scan_u.o \ + ip_log_u.o ip_pool_u.o ip_htable_u.o ip_lookup_u.o ip_rules_u.o \ + ipf_y.o ipf_l.o ipnat_y.o ipnat_l.o ippool_y.o ippool_l.o \ + md5_u.o radix_ipf_u.o +IPNAT=ipnat.o ipnat_y.o ipnat_l.o +IPMON=ipmon.o ipmon_y.o ipmon_l.o +IPPOOL=ippool_y.o ippool_l.o kmem.o ippool.o +FILS=ipfstat.o +LIBSRC=$(TOP)/lib +RANLIB=ranlib +AROPTS=-X $(BITS) crs +TOOL=$(TOP)/tools + +include $(TOP)/lib/Makefile + +build all: ./libipf.a ipf.exe ipfs ipfstat ipftest ipmon \ + ipnat ippool ipscan ipsyncm ipsyncs cfg_ipf $(LKM) + -sh -c 'for i in ipftest ipmon ippool ipnat ipscan ipsyncm ipsyncs; do /bin/rm -f $(TOP)/$$i; ln -s `pwd`/$$i $(TOP); done' + -ln -s `pwd`/ipf.exe $(TOP)/ipf + +ipfstat: $(FILS) ./libipf.a + $(CC) $(CCARGS) $(STATETOP_CFLAGS) $(STATETOP_INC) $(FILS) \ + -o $@ $(LIBS) $(STATETOP_LIB) + +ipf.exe: $(IPF) ./libipf.a + $(CC) $(CCARGS) $(IPF) -o $@ $(LIBS) $(LIBBPF) + +ipftest: $(IPT) ./libipf.a + $(CC) $(CCARGS) $(IPT) -o $@ $(LIBS) $(LIBBPF) + +ipnat: $(IPNAT) ./libipf.a + $(CC) $(CCARGS) $(IPNAT) -o $@ $(LIBS) + +ipfs: ipfs.o ./libipf.a + $(CC) $(CCARGS) ipfs.o -o $@ $(LIBS) + +ipsyncm: ipsyncm.o ./libipf.a + $(CC) $(CCARGS) ipsyncm.o -o $@ $(LIBS) + +ipsyncs: ipsyncs.o ./libipf.a + $(CC) $(CCARGS) ipsyncs.o -o $@ $(LIBS) + +ipsyncm.o: $(TOOL)/ipsyncm.c $(TOP)/ip_sync.h + $(CC) $(CCARGS) -c $(TOOL)/ipsyncm.c -o $@ + +ipsyncs.o: $(TOOL)/ipsyncs.c $(TOP)/ip_sync.h + $(CC) $(CCARGS) -c $(TOOL)/ipsyncs.c -o $@ + +tests: + (cd test; make ) + +ipfstat.o: $(TOOL)/ipfstat.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_frag.h \ + $(TOP)/ip_compat.h $(TOP)/ip_state.h $(TOP)/ip_nat.h + $(CC) $(CCARGS) $(STATETOP_CFLAGS) $(STATETOP_INC) \ + -c $(TOOL)/ipfstat.c -o $@ + +ipfs.o: $(TOOL)/ipfs.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_state.h \ + $(TOP)/ip_nat.h + $(CC) $(CCARGS) -c $(TOOL)/ipfs.c -o $@ + +fil_u.o: $(TOP)/fil.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) $(FIXRADIX) $(IPFBPF) -c $(TOP)/fil.c -o $@ + +ipf.o: $(TOOL)/ipf.c $(TOP)/ip_fil.h $(TOP)/ipf.h + $(CC) $(CCARGS) -c $(TOOL)/ipf.c -o $@ + +ipf_y.o: ipf_y.c ipf_y.h $(TOP)/ipf.h ipf_l.h + $(CC) $(CCARGS) $(IPFBPF) -c ipf_y.c -o $@ + +ipf_l.o: ipf_l.c ipf_y.h $(TOP)/ipf.h ipf_l.h + $(CC) $(CCARGS) -I. -c ipf_l.c -o $@ + +ipf_y.h ipf_y.c: $(TOOL)/ipf_y.y $(TOP)/ip_pool.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ipf_l.c ipf_l.h: $(TOOL)/lexer.c $(TOP)/ipf.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ipfcomp.o: $(TOOL)/ipfcomp.c $(TOP)/ip_fil.h $(TOP)/ipf.h + $(CC) $(CCARGS) -c $(TOOL)/ipfcomp.c -o $@ + +ipftest.o: $(TOOL)/ipftest.c $(TOP)/ip_fil.h $(TOP)/ipt.h $(TOP)/ipf.h + $(CC) $(CCARGS) -c $(TOOL)/ipftest.c -o $@ + +ipnat.o: $(TOOL)/ipnat.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_nat.h + $(CC) $(CCARGS) -c $(TOOL)/ipnat.c -o $@ + +ipnat_y.o: ipnat_y.c ipnat_y.h $(TOP)/ip_fil.h $(TOP)/ip_compat.h \ + $(TOP)/ipf.h $(TOP)/ip_nat.h ipnat_l.h + $(CC) $(CCARGS) -c ipnat_y.c -o $@ + +ipnat_l.o: ipnat_l.c ipnat_y.h $(TOP)/ip_fil.h $(TOP)/ip_compat.h \ + $(TOP)/ipf.h $(TOP)/ip_nat.h ipnat_l.h + $(CC) $(CCARGS) -I. -c ipnat_l.c -o $@ + +ipnat_y.h ipnat_y.c: $(TOOL)/ipnat_y.y $(TOP)/ip_nat.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ipnat_l.c ipnat_l.h: $(TOOL)/lexer.c $(TOP)/ip_nat.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ip_rules.c: $(TOP)/rules/ip_rules $(TOP)/tools/ipfcomp.c ipf.exe + ./ipf.exe -cc -nf $(TOP)/rules/ip_rules + +$(TOP)/ip_rules.h: ip_rules.c + if [ ! -f $(TOP)/ip_rules.h ] ; then \ + /bin/mv -f ip_rules.h $(TOP); \ + else \ + touch $(TOP)/ip_rules.h; \ + fi + +ip_nat_u.o: $(TOP)/ip_nat.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_nat.c -o $@ + +ip_nat6_u.o: $(TOP)/ip_nat6.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_nat6.c -o $@ + +ip_proxy_u.o: $(TOP)/ip_proxy.c $(TOP)/ip_proxy.h $(TOP)/ip_compat.h \ + $(TOP)/ip_ftp_pxy.c $(TOP)/ip_rcmd_pxy.c $(TOP)/ip_raudio_pxy.c \ + $(TOP)/ip_rpcb_pxy.c $(TOP)/ip_ipsec_pxy.c $(TOP)/ip_nat.h \ + $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_proxy.c -o $@ + +ip_frag_u.o: $(TOP)/ip_frag.c $(TOP)/ip_frag.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_frag.c -o $@ + +ip_state_u.o: $(TOP)/ip_state.c $(TOP)/ip_state.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(TOP)/ip_nat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_state.c -o $@ + +ip_auth_u.o: $(TOP)/ip_auth.c $(TOP)/ip_auth.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_auth.c -o $@ + +ip_fil_u.o: $(TOP)/ip_fil.c $(TOP)/ip_fil.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) $(FIXRADIX) -c $(TOP)/ip_fil.c -o $@ + +ip_scan_u.o: $(TOP)/ip_scan.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_scan.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_scan.c -o $@ + +ip_sync_u.o: $(TOP)/ip_sync.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_sync.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_sync.c -o $@ + +ip_rules_u.o: ip_rules.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(TOP)/ip_rules.h + $(CC) $(CCARGS) $(EXTRA) -c ip_rules.c -o $@ + +ip_log_u.o: $(TOP)/ip_log.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_log.c -o $@ + +ip_pool_u.o: $(TOP)/ip_pool.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_pool.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_pool.c -o $@ + +ip_htable_u.o: $(TOP)/ip_htable.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_htable.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_htable.c -o $@ + +ip_lookup_u.o: $(TOP)/ip_lookup.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_lookup.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_lookup.c -o $@ + +bpf_filter_u.o: $(TOP)/bpf_filter.c $(TOP)/pcap-ipf.h $(TOP)/bpf-ipf.h + $(CC) $(CCARGS) -c $(TOP)/bpf_filter.c -o $@ + +md5_u.o: $(TOP)/md5.c $(TOP)/md5.h + $(CC) $(CCARGS) -c $(TOP)/md5.c -o $@ + +radix_ipf_u.o: $(TOP)/radix_ipf.c $(TOP)/radix_ipf.h + $(CC) $(CCARGS) -c $(TOP)/radix_ipf.c -o $@ + +cfg_ipf: cfg_ipf.o +# ld -o cfg_ipf cfg_ipf.o -L/usr/lib/ia64l32 -L/usr/ccs/lib/ia64l32 \ +# -lodm -lrts -lcfg + $(CC) $(CCARGS) -o cfg_ipf cfg_ipf.o -lodm -lrts -lcfg + +cfg_ipf.o: ../aix_cfg_ipf.c + $(CC) -D_ALL_SOURCE -D_KERNEL $(CCARGS) -c ../aix_cfg_ipf.c -o $@ + +$(LKM): $(MODOBJS) ../ipfkext.exp /lib/kernex.exp /lib/syscalls.exp + ld -G -eipfconfig -bimport:/lib/syscalls.exp -bimport:/lib/kernex.exp \ + -bimport:/lib/kernex.exp -bimport:/lib/netinet.exp \ + -bimport:/lib/statcmd.exp \ + -lcsys -lsys -bexport:../ipfkext.exp -bmap:ipfkext.map \ + $(MODOBJS) -o $(LKM)32 + /bin/rm -f $(LKM) + ar -X $(BITS) cq $(LKM) $(LKM)32 + +fil.o: $(TOP)/fil.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_compat.h $(TOP)/ipl.h + $(CC) $(POLICY) $(DFLAGS) $(IPFBPF) -c $(TOP)/fil.c -o $@ + +ip_nat.o: $(TOP)/ip_nat.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(DFLAGS) -c $(TOP)/ip_nat.c -o $@ + +ip_nat6.o: $(TOP)/ip_nat6.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(DFLAGS) -c $(TOP)/ip_nat6.c -o $@ + +ip_frag.o: $(TOP)/ip_frag.c $(TOP)/ip_frag.h $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(DFLAGS) -c $(TOP)/ip_frag.c -o $@ + +ip_state.o: $(TOP)/ip_state.c $(TOP)/ip_state.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(TOP)/ip_nat.h + $(CC) $(DFLAGS) -DIPSTATE_SIZE=127 -c $(TOP)/ip_state.c -o $@ + +ip_proxy.o: $(TOP)/ip_proxy.c $(TOP)/ip_proxy.h $(TOP)/ip_compat.h \ + $(TOP)/ip_ftp_pxy.c $(TOP)/ip_rcmd_pxy.c $(TOP)/ip_raudio_pxy.c \ + $(TOP)/ip_rpcb_pxy.c $(TOP)/ip_ipsec_pxy.c $(TOP)/ip_nat.h \ + $(TOP)/ip_nat.h $(TOP)/ip_fil.h + $(CC) $(DFLAGS) -c $(TOP)/ip_proxy.c -o $@ + +ip_auth.o: $(TOP)/ip_auth.c $(TOP)/ip_auth.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h + $(CC) $(DFLAGS) -c $(TOP)/ip_auth.c -o $@ + +ip_fil.o: $(TOP)/ip_fil_aix.c $(TOP)/ip_fil.h $(TOP)/ip_compat.h $(TOP)/ip_nat.h + $(CC) $(DFLAGS) $(COMPIPF) -c $(TOP)/ip_fil_aix.c -o $@ + +ip_log.o: $(TOP)/ip_log.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(DFLAGS) -c $(TOP)/ip_log.c -o $@ + +ip_scan.o: $(TOP)/ip_scan.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(TOP)/ip_scan.h + $(CC) $(DFLAGS) -c $(TOP)/ip_scan.c -o $@ + +ip_sync.o: $(TOP)/ip_sync.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(TOP)/ip_sync.h + $(CC) $(DFLAGS) -c $(TOP)/ip_sync.c -o $@ + +radix_ipf.o: $(TOP)/radix_ipf.c $(TOP)/radix_ipf.h + $(CC) $(DFLAGS) -c $(TOP)/radix_ipf.c -o $@ + +ip_pool.o: $(TOP)/ip_pool.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_pool.h $(TOP)/radix_ipf.h + $(CC) $(DFLAGS) $(FIXRADIX) -c $(TOP)/ip_pool.c -o $@ + +ip_htable.o: $(TOP)/ip_htable.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_htable.h + $(CC) $(DFLAGS) -c $(TOP)/ip_htable.c -o $@ + +ip_lookup.o: $(TOP)/ip_lookup.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_lookup.h + $(CC) $(DFLAGS) $(FIXRADIX) -c $(TOP)/ip_lookup.c -o $@ + +ip_rules.o: ip_rules.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(TOP)/ip_rules.h + $(CC) -I. $(DFLAGS) -c ip_rules.c -o $@ + +ip_rulesx.o: ip_rules.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(TOP)/ip_rules.h + $(CC) -I. -DIPFILTER_COMPILED $(DFLAGS) -c ip_rules.c -o $@ + +#aix.o: $(TOP)/aix.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h +# $(CC) $(DFLAGS) -c $(TOP)/aix.c -o $@ + +md5.o: $(TOP)/md5.c $(TOP)/md5.h + $(CC) $(DFLAGS) -c $(TOP)/md5.c -o $@ + +ipmon: $(IPMON) ./libipf.a + $(CC) $(CCARGS) $(LOGFAC) $(IPMON) -o $@ $(LIBS) -ll + +ipmon.o: $(TOOL)/ipmon.c $(TOP)/ipmon.h + $(CC) $(CCARGS) $(LOGFAC) -c $(TOOL)/ipmon.c -o $@ + +ipmon_y.o: ipmon_y.c ipmon_y.h $(TOP)/ipmon.h ipmon_l.h + $(CC) $(CCARGS) -c ipmon_y.c -o $@ + +ipmon_l.o: ipmon_l.c ipmon_y.h $(TOP)/ipmon.h ipmon_l.h + $(CC) $(CCARGS) -I. -c ipmon_l.c -o $@ + +ipmon_y.h ipmon_y.c: $(TOOL)/ipmon_y.y $(TOP)/ipmon.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ipmon_l.c ipmon_l.h: $(TOOL)/lexer.c $(TOP)/ipmon.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ipscan: ipscan_y.o ipscan_l.o + $(CC) $(DEBUG) ipscan_y.o ipscan_l.o -o $@ -ll $(LIBS) + +ipscan_y.o: ipscan_y.c ipscan_y.h $(TOP)/ip_scan.h ipscan_l.h + $(CC) $(CCARGS) -c ipscan_y.c -o $@ + +ipscan_l.o: ipscan_l.c ipscan_y.h $(TOP)/ip_scan.h ipscan_l.h + $(CC) $(CCARGS) -I. -c ipscan_l.c -o $@ + +ipscan_y.h ipscan_y.c: $(TOOL)/ipscan_y.y $(TOP)/ip_scan.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ipscan_l.c ipscan_l.h: $(TOOL)/lexer.c $(TOP)/ip_scan.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ippool: $(IPPOOL) + $(CC) $(DEBUG) -I. $(CFLAGS) $(IPPOOL) -o $@ $(LIBS) -ll + +ippool.o: $(TOOL)/ippool.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_pool.h + $(CC) $(CCARGS) -c $(TOOL)/ippool.c -o $@ + +ippool_y.o: ippool_y.c ippool_y.h $(TOP)/ip_pool.h ippool_l.h + $(CC) $(CCARGS) -c ippool_y.c -o $@ + +ippool_l.o: ippool_l.c ippool_y.h $(TOP)/ip_pool.h ippool_l.h + $(CC) $(CCARGS) -I. -c ippool_l.c -o $@ + +ippool_y.h ippool_y.c: $(TOOL)/ippool_y.y $(TOP)/ip_pool.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ippool_l.c ippool_l.h: $(TOOL)/lexer.c $(TOP)/ip_pool.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +.y.c: + +.l.c: + +clean: + ${RM} -f ../ipf.exe ../ipnat ../ipmon ../ippool ../ipftest + ${RM} -f ../ipscan ../ipsyncm ../ipsyncs cfg_ipf + ${RM} -f *.core *.o *.a *.o.d + ${RM} -f fils ipf.exe ipfstat ipftest ipmon if_ipl ipnat + ${RM} -f $(LKM) ioconf.h *.ko setdef1.c setdef0.c setdefs.h + ${RM} -f ip_fil.c ipf_l.c ipf_y.c ipf_y.h ipf_l.h + ${RM} -f ipscan ipscan_y.c ipscan_y.h ipscan_l.c ipscan_l.h + ${RM} -f ippool ippool_y.c ippool_y.h ippool_l.c ippool_l.h + ${RM} -f ipnat_y.c ipnat_y.h ipnat_l.c ipnat_l.h + ${RM} -f ipmon_y.c ipmon_y.h ipmon_l.c ipmon_l.h + ${RM} -f ipscan ipscan_y.c ipscan_y.h ipscan_l.c y.tab.? lex.yy.c ipfs + ${RM} -f ipsyncm ipsyncs ip_rules.c ip_rules.h + + ${MAKE} -f Makefile.ipsend ${MFLAGS} clean + -(for i in *; do \ + if [ -d $${i} -a -f $${i}/Makefile ] ; then \ + cd $${i}; (make TOP=../.. clean); cd ..; \ + rm $${i}/Makefile $${i}/Makefile.ipsend; \ + rmdir $${i}; \ + fi \ + done) + +install: + cp cfg_ipf /usr/lib/methods + cp $(LKM) /usr/lib/drivers/ipf + -for i in ipfs ipnat ipscan ipfstat; do \ + $(INSTALL) -s -c -g system -m 755 -o root $$i $(SBINDEST); \ + done + $(INSTALL) -s -c -g system -m 755 -o root ipf.exe $(SBINDEST)/ipf + -for i in ipmon ipftest ipsyncs ipsyncm; do \ + $(INSTALL) -s -c -g system -m 755 -o root $$i $(BINDEST); \ + done + (cd $(TOP)/man; make INSTALL=../bsdinstall MANDIR=$(MANDIR) install; cd $(TOP)) + sync diff --git a/AIX/Makefile.ipsend b/AIX/Makefile.ipsend new file mode 100644 index 0000000000000..c7950120c01fb --- /dev/null +++ b/AIX/Makefile.ipsend @@ -0,0 +1,78 @@ +MFLAGS="BINDEST=$(BINDEST)" "SBINDEST=$(SBINDEST)" "MANDIR=$(MANDIR)" \ + "CC=$(CC)" "CFLAGS=$(CFLAGS)" "DEBUG=$(DEBUG)" \ + "IPFLKM=$(IPFLKM)" "IPFLOG=$(IPFLOG)" \ + "LOGFAC=$(LOGFAC)" "POLICY=$(POLICY)" "LOOKUP=$(LOOKUP)" +FIXRADIX=-Dradix_node=ipf_radix_node -Dradix_node_head=ipf_radix_node_head +OBJS=ipsend.o ip.o ipsopt.o iplang_y.o iplang_l.o +IPFTO=ipft_ef.o ipft_hx.o ipft_pc.o ipft_sn.o ipft_td.o ipft_tx.o +ROBJS=ipresend.o ip.o resend.o +TOBJS=iptest.o iptests.o ip.o +UNIXOBJS=dlcommon.o sbpf.o arp.o sock.o +OBJ=. +LIBS=-L$(OBJ) -lipf + +CC=cc +CFLAGS=-g -I$(TOP) +CCARGS=$(DEBUG) $(CFLAGS) -I. + +all nit sunos4 sunos4-nit build : ipsend ipresend iptest + +iplang_y.o: $(TOP)/iplang/iplang_y.y + (cd $(TOP)/iplang; $(MAKE) 'DESTDIR=../AIX/$(OSREV)' ) + +iplang_l.o: $(TOP)/iplang/iplang_l.l + (cd $(TOP)/iplang; $(MAKE) 'DESTDIR=../AIX/$(OSREV)' ) + +.c.o: + $(CC) $(CCARGS) -c $(TOP)/ipsend/$< -o $@ + +ipsend: $(OBJS) $(UNIXOBJS) + $(CC) $(DEBUG) $(OBJS) $(UNIXOBJS) -o $@ $(LIBS) -ll + +ipresend: $(ROBJS) $(UNIXOBJS) + $(CC) $(DEBUG) $(ROBJS) $(UNIXOBJS) -o $@ $(LIBS) + +iptest: $(TOBJS) $(UNIXOBJS) + $(CC) $(DEBUG) $(TOBJS) $(UNIXOBJS) -o $@ $(LIBS) + +clean: + rm -rf *.o core a.out ipsend ipresend iptest iplang_y.* iplang_l.* + +ipsend.o: $(TOP)/ipsend/ipsend.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/ipsend.c -o $@ +ipsopt.o: $(TOP)/ipsend/ipsopt.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/ipsopt.c -o $@ +ipresend.o: $(TOP)/ipsend/ipresend.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/ipresend.c -o $@ +ip.o: $(TOP)/ipsend/ip.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/ip.c -o $@ +resend.o: $(TOP)/ipsend/resend.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/resend.c -o $@ +ipft_sn.o: $(TOP)/ipft_sn.c + $(CC) $(CCARGS) -c $(TOP)/ipft_sn.c -o $@ +ipft_pc.o: $(TOP)/ipft_pc.c + $(CC) $(CCARGS) -c $(TOP)/ipft_pc.c -o $@ +iptest.o: $(TOP)/ipsend/iptest.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/iptest.c -o $@ +iptests.o: $(TOP)/ipsend/iptests.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/iptests.c -o $@ +sbpf.o: $(TOP)/ipsend/sbpf.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/sbpf.c -o $@ +snit.o: $(TOP)/ipsend/snit.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/snit.c -o $@ +sock.o: $(TOP)/ipsend/sock.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/sock.c -o $@ +arp.o: $(TOP)/ipsend/arp.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/arp.c -o $@ +44arp.o: $(TOP)/ipsend/44arp.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/44arp.c -o $@ +lsock.o: $(TOP)/ipsend/lsock.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/lsock.c -o $@ +slinux.o: $(TOP)/ipsend/slinux.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/slinux.c -o $@ +larp.o: $(TOP)/ipsend/larp.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/larp.c -o $@ +dlcommon.o: $(TOP)/ipsend/dlcommon.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/dlcommon.c -o $@ +sdlpi.o: $(TOP)/ipsend/sdlpi.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/sdlpi.c -o $@ diff --git a/AIX/aix_cfg_ipf.c b/AIX/aix_cfg_ipf.c new file mode 100644 index 0000000000000..26807fa629908 --- /dev/null +++ b/AIX/aix_cfg_ipf.c @@ -0,0 +1,257 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ +#include <sys/param.h> +#include <sys/types.h> +#include <sys/file.h> +#include <sys/ldr.h> +/* + * This is a workaround for <sys/uio.h> troubles on FreeBSD, HPUX, OpenBSD. + * Needed here because on some systems <sys/uio.h> gets included by things + * like <sys/socket.h> + */ +#include <sys/uio.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <net/if.h> +#define _TCP_DEBUG_H_ +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/ip_icmp.h> +#include <netinet/tcp.h> +#include <netinet/udp.h> + +#include <arpa/inet.h> + +#include <errno.h> +#include <limits.h> +#include <netdb.h> +#include <stdlib.h> +#include <stddef.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "netinet/ip_compat.h" +#include "netinet/ip_fil.h" + +#ifndef __P +# ifdef __STDC__ +# define __P(x) x +# else +# define __P(x) () +# endif +#endif +#ifndef __STDC__ +# undef const +# define const +#endif + +/* + * AIX requires a specific configure/unconfigure program + */ +#undef ASSERT +#include <sys/device.h> +#include <sys/sysconfig.h> + +void loadipf __P((int major, int minor, dev_t devno, char *)); +void unloadipf __P((int major, int minor, dev_t devno)); +void queryipf __P((int major, int minor, dev_t devno)); +int checkarg __P((int, char *arg)); +void usage __P((char *)); + +static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, + IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME, + IPLOOKUP_NAME, NULL }; + +int +main(int argc, char *argv[]) +{ + int major, minor, action; + dev_t devno; + + action = checkarg(argc, argv[1]); + if (action == -1) + usage(argv[0]); + + if (odm_initialize() == -1) { + fprintf(stderr, "odm_initialize() failed\n"); + exit(1); + } + + major = genmajor("ipf"); + if (major == -1) { + fprintf(stderr, "genmajor(ipf) failed\n"); + exit(1); + } + minor = 0; + + devno = makedev(major, minor); + if (devno == -1) { + fprintf(stderr, "makedev(%d,%d) failed\n", major, minor); + exit(1); + } + printf("Major %d\ndevno %x\n", major, devno); + + switch (action) + { + case 1 : + loadipf(major, minor, devno, argv[2]); + break; + case 2 : + unloadipf(major, minor, devno); + break; + case 3 : + queryipf(major, minor, devno); + break; + } + + odm_terminate(); + + return 0; +} + + +void usage(char *prog) +{ + fprintf(stderr, "Usage:\t%s -l\n\t%s -u\n\t%s -q\n", + prog, prog, prog); + exit(1); +} + + +int checkarg(int argc, char *arg) +{ + if (argc < 2) + return -1; + + if (!strcmp(arg, "-l") && (argc <= 3)) + return 1; + + if (!strcmp(arg, "-u") && (argc == 2)) + return 2; + + if (!strcmp(arg, "-q") && (argc == 2)) + return 3; + + return -1; +} + + +void +loadipf(int major, int minor, dev_t devno, char *path) +{ + struct cfg_dd ipfcfg; + struct cfg_load cfg; + char *buffer[1024]; + char *ipfpath; + int i; + + bzero(buffer, sizeof(buffer)); + if (path != NULL) + ipfpath = path; + else + ipfpath = "/usr/lib/drivers/ipf"; + +#if 0 + bzero((char *)&cfg, sizeof(cfg)); + cfg.path = ipfpath; + cfg.libpath = "/usr/lib/drivers/"; + sysconfig(SYS_SINGLELOAD, &cfg, sizeof(cfg)); + ipfcfg.kmid = cfg.kmid; +#else + ipfcfg.kmid = (mid_t)loadext(ipfpath, TRUE, TRUE); +#endif + if (ipfcfg.kmid == (mid_t)NULL) + { + perror("loadext"); + buffer[0] = "execerror"; + buffer[1] = "ipf"; + loadquery(1, &buffer[2], sizeof(buffer) - sizeof(*buffer)*2); + execvp("/usr/sbin/execerror", buffer); + exit(errno); + } + + ipfcfg.devno = devno; + ipfcfg.cmd = CFG_INIT; + ipfcfg.ddsptr = (caddr_t)NULL; + ipfcfg.ddslen = 0; + + if (sysconfig(SYS_CFGDD, &ipfcfg, sizeof(ipfcfg)) == -1) { + perror("sysconifg(SYS_CFGDD)"); + exit(errno); + } + + for (i = 0; ipf_devfiles[i] != NULL; i++) { + unlink(ipf_devfiles[i]); + if (mknod(ipf_devfiles[i], 0600 | _S_IFCHR, devno) == -1) { + perror("mknod(devfile)"); + exit(errno); + } + } +} + + +void +unloadipf(int major, int minor, dev_t devno) +{ + struct cfg_dd ipfcfg; + struct cfg_load cfg; + int i; + + cfg.path = "/usr/lib/drivers/ipf"; + cfg.kmid = 0; + if (sysconfig(SYS_QUERYLOAD, &cfg, sizeof(cfg)) == -1) { + perror("sysconfig(SYS_QUERYLOAD)"); + exit(errno); + } + + ipfcfg.kmid = cfg.kmid; + ipfcfg.devno = devno; + ipfcfg.cmd = CFG_TERM; + if (sysconfig(SYS_CFGDD, &ipfcfg, sizeof(ipfcfg)) == -1) { + perror("sysconfig(SYS_CFGDD)"); + exit(errno); + } + + for (i = 0; ipf_devfiles[i] != NULL; i++) { + unlink(ipf_devfiles[i]); + } + + if (loadext("ipf", FALSE, FALSE) == NULL) { + perror("loadext"); + exit(errno); + } +} + + +void +queryipf(int major, int minor, dev_t devno) +{ + struct cfg_dd ipfcfg; + struct cfg_load cfg; + int i; + + cfg.path = "/usr/lib/drivers/ipf"; + cfg.kmid = 0; + if (sysconfig(SYS_QUERYLOAD, &cfg, sizeof(cfg)) == -1) { + perror("sysconfig(SYS_QUERYLOAD)"); + exit(errno); + } + + printf("Kernel module ID: %d\n", cfg.kmid); + + ipfcfg.kmid = cfg.kmid; + ipfcfg.devno = devno; + ipfcfg.cmd = CFG_QVPD; + if (sysconfig(SYS_CFGDD, &ipfcfg, sizeof(ipfcfg)) == -1) { + perror("sysconfig(SYS_CFGDD)"); + exit(errno); + } +} + diff --git a/AIX/bootbits.sh b/AIX/bootbits.sh new file mode 100755 index 0000000000000..245a4582a6884 --- /dev/null +++ b/AIX/bootbits.sh @@ -0,0 +1,21 @@ +#!/bin/sh +case `file /unix 2>/dev/null` in +*64*) + bits=64 + ;; +*) + bits=32 + ;; +esac + +case $1 in +milli) + if [ $bits = 64 ] ; then + echo 64 + fi + ;; +*) + echo $bits + ;; +esac +exit 0 diff --git a/AIX/cpurev b/AIX/cpurev new file mode 100755 index 0000000000000..aa5837572fc25 --- /dev/null +++ b/AIX/cpurev @@ -0,0 +1,6 @@ +#!/bin/sh +rev=`uname -r` +build=`uname -v` +model=`uname -M` +echo $rev.$build.$model +exit 0 diff --git a/AIX/ipfkext.exp b/AIX/ipfkext.exp new file mode 100644 index 0000000000000..66a9f6c7c4480 --- /dev/null +++ b/AIX/ipfkext.exp @@ -0,0 +1,2 @@ +#!/unix +* export values from ipfkext diff --git a/FWTK/FWTK.sed b/AIX/ipfkext.map index e69de29bb2d1d..e69de29bb2d1d 100644 --- a/FWTK/FWTK.sed +++ b/AIX/ipfkext.map @@ -67,7 +67,7 @@ facility = "kern" | "user" | "mail" | "daemon" | "auth" | "syslog" | "audit" | "logalert" | "local0" | "local1" | "local2" | "local3" | "local4" | "local5" | "local6" | "local7" . priority = "emerg" | "alert" | "crit" | "err" | "warn" | "notice" | - "info" | "debug" . + "info" | "debug" . hexnumber = "0" "x" hexstring . hexstring = hexdigit [ hexstring ] . diff --git a/BSD/.cvsignore b/BSD/.cvsignore deleted file mode 100644 index c149a0043f450..0000000000000 --- a/BSD/.cvsignore +++ /dev/null @@ -1,22 +0,0 @@ -ipf -ipfs -ipfstat -ipftest -ipmon -ipnat -ipresend -ipsend -iptest -vnode_if.h -if_ipl -i386 -amiga -FreeBSD* -BSDOS* -NetBSD* -OpenBSD* -*_lex_var.h -*_y.c -*_l.c -*_y.h -ip_rules.* diff --git a/BSD/Makefile b/BSD/Makefile index fe8a4d4e567f2..4f2c2b9dcd415 100644 --- a/BSD/Makefile +++ b/BSD/Makefile @@ -1,9 +1,8 @@ # -# Copyright (C) 1993-1998 by Darren Reed. +# Copyright (C) 2012 by Darren Reed. # # See the IPFILTER.LICENCE file for details on licencing. # -TOP=../.. BINDEST=/usr/sbin SBINDEST=/sbin MANDIR=/usr/share/man @@ -17,13 +16,14 @@ CFLAGS=-g -I$(TOP) # DEVFS!=/usr/bin/lsvfs 2>&1 | sed -n 's/.*devfs.*/-DDEVFS/p' CPU!=uname -m -INC=-I/usr/include -I/sys -I/sys/sys -I/sys/arch +COMPDIR!=/bin/ls -1tr /usr/src/sys/arch/${CPU}/compile | tail -1 +INC=-I/usr/include -I/sys -I/sys/sys -I/sys/arch -I/usr/src/sys/arch/${CPU}/compile/${COMPDIR} DEF=-D$(CPU) -D__$(CPU)__ -DINET -DKERNEL -D_KERNEL $(INC) $(DEVFS) -fno-builtin IPDEF=$(DEF) -DGATEWAY -DDIRECTED_BROADCAST VNODESHDIR=/sys/kern MLD=$(ML) ML=mln_ipl.c -LKM=if_ipl.o +LKM=ipflkm.o LKMR=ipfrule.o DLKM= OBJ=. @@ -44,15 +44,15 @@ INSTALL=install # MODOBJS=ip_fil.o fil.o ml_ipl.o ip_nat.o ip_frag.o ip_state.o ip_proxy.o \ ip_auth.o ip_log.o ip_pool.o ip_htable.o ip_lookup.o ip_rules.o \ - ip_scan.o ip_sync.o + ip_scan.o ip_sync.o ip_nat6.o ip_dstlist.o radix_ipf.o # ip_trafcon.o DFLAGS=$(IPFLKM) $(IPFLOG) $(LOOKUP) $(SYNC) $(DEF) $(DLKM) $(IPFBPF) -IPF=ipf.o ipfcomp.o ipf_y.o ipf_l.o bpf_filter_u.o -IPT=ipftest.o fil_u.o ip_frag_u.o ip_state_u.o ip_nat_u.o \ +IPF=ipf.o ipfcomp.o ipf_y.o ipf_l.o +IPT=ipftest.o fil_u.o ip_frag_u.o ip_state_u.o ip_nat_u.o ip_nat6_u.o \ ip_proxy_u.o ip_auth_u.o ip_htable_u.o ip_lookup_u.o ip_pool_u.o \ ip_scan_u.o ip_sync_u.o ip_rules_u.o ip_fil_u.o ip_log_u.o \ ippool_y.o ippool_l.o ipf_y.o ipf_l.o ipnat_y.o ipnat_l.o \ - md5_u.o radix_u.o bpf_filter_u.o + md5_u.o radix_ipf_u.o ip_dstlist_u.o # ip_syn_u.o #ip_trafcon_u.o TOOL=$(TOP)/tools @@ -60,9 +60,9 @@ IPNAT=ipnat.o ipnat_y.o ipnat_l.o IPMON=ipmon.o ipmon_y.o ipmon_l.o IPPOOL=ippool_y.o ippool_l.o kmem.o ippool.o IPTRAFCON=iptrafcon.o -PROXYLIST=$(TOP)/ip_ftp_pxy.c $(TOP)/ip_ipsec_pxy.c $(TOP)/ip_irc_pxy.c \ - $(TOP)/ip_netbios_pxy.c $(TOP)/ip_raudio_pxy.c $(TOP)/ip_rcmd_pxy.c \ - $(TOP)/ip_rpcb_pxy.c $(TOP)/ip_pptp_pxy.c +PROXYLIST=$(TOP)/ip_dns_pxy.c $(TOP)/ip_ftp_pxy.c $(TOP)/ip_ipsec_pxy.c \ + $(TOP)/ip_irc_pxy.c $(TOP)/ip_netbios_pxy.c $(TOP)/ip_raudio_pxy.c \ + $(TOP)/ip_rcmd_pxy.c $(TOP)/ip_rpcb_pxy.c $(TOP)/ip_pptp_pxy.c FILS=ipfstat.o LIBSRC=$(TOP)/lib RANLIB=ranlib @@ -70,6 +70,11 @@ AROPTS=cq HERE!=pwd CCARGS=-I. $(DEBUG) $(CFLAGS) $(UFLAGS) KCARGS=-I. $(DEBUG) $(CFLAGS) +.if ${MACHINE_ARCH} == amd64 +KCARGS+=-mcmodel=kernel -mno-red-zone -fno-omit-frame-pointer \ + -mfpmath=387 -mno-sse -mno-sse2 -mno-mmx -mno-3dnow \ + -msoft-float -fno-asynchronous-unwind-tables +.endif # # Extra is option kernel things we always want in user space. # @@ -77,9 +82,11 @@ EXTRA=$(ALLOPTS) include $(TOP)/lib/Makefile -build all: machine $(OBJ)/libipf.a ipf ipfs ipfstat ipftest ipmon ipnat \ - ippool ipscan ipsyncm ipsyncs $(LKM) $(LKMR) - -sh -c 'for i in ipf ipftest ipmon ippool ipnat ipscan ipsyncm ipsyncs; do /bin/rm -f $(TOP)/$$i; ln -s `pwd`/$$i $(TOP); done' +build all: machine $(OBJ)/libipf.a tools $(LKM) $(LKMR) + +tools: ipf ipfs ipfstat ipftest ipmon ipnat ippool ipscan ipsyncm \ + ipsyncs ipfsyncd + -sh -c 'for i in ipf ipftest ipmon ippool ipnat ipscan ipsyncm ipsyncs ipfsyncd; do /bin/rm -f $(TOP)/$$i; ln -s `pwd`/$$i $(TOP); done' -/bin/rm -f ../tools ./tools -ln -s ../tools . -ln -s ../tools .. @@ -122,12 +129,18 @@ ipsyncm: ipsyncm.o $(OBJ)/libipf.a ipsyncs: ipsyncs.o $(OBJ)/libipf.a $(CC) $(CCARGS) ipsyncs.o -o $@ $(LIBS) +ipfsyncd: ipfsyncd.o $(OBJ)/libipf.a + $(CC) $(CCARGS) ipfsyncd.o -o $@ $(LIBS) + ipsyncm.o: $(TOOL)/ipsyncm.c $(TOP)/ip_sync.h $(CC) $(CCARGS) -c $(TOOL)/ipsyncm.c -o $@ ipsyncs.o: $(TOOL)/ipsyncs.c $(TOP)/ip_sync.h $(CC) $(CCARGS) -c $(TOOL)/ipsyncs.c -o $@ +ipfsyncd.o: $(TOOL)/ipfsyncd.c $(TOP)/ip_sync.h + $(CC) $(CCARGS) -c $(TOOL)/ipfsyncd.c -o $@ + tests: (cd test; make ) @@ -146,7 +159,7 @@ fil_u.o: $(TOP)/fil.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_compat.h \ fil.o: $(TOP)/fil.c $(TOP)/ip_fil.h $(TOP)/ip_compat.h $(TOP)/ipl.h \ $(TOP)/ip_rules.h - $(CC) $(KCARGS) $(POLICY) $(DFLAGS) $(IPFBPF) $(COMPIPF) \ + $(CC) $(KCARGS) $(POLICY) $(DFLAGS) $(IPFBPF) $(COMPIPF) $(COMPATIPF) \ -c $(TOP)/fil.c -o $@ ipf.o: $(TOOL)/ipf.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/opts.h @@ -163,7 +176,7 @@ ipnat.o: $(TOOL)/ipnat.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_nat.h \ $(TOP)/opts.h $(CC) $(CCARGS) -c $(TOOL)/ipnat.c -o $@ -ipnat_y.o: ipnat_y.c ipnat_y.h ipnat_l.h +ipnat_y.o: ipnat_y.c ipnat_y.h ipnat_l.h $(TOP)/ip_fil.h $(TOP)/ip_nat.h $(CC) $(CCARGS) -c ipnat_y.c -o $@ ipnat_l.o: ipnat_l.c ipnat_y.h @@ -183,6 +196,9 @@ ipnat_l.h: $(TOOL)/lexer.h ip_nat_u.o: $(TOP)/ip_nat.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_nat.c -o $@ +ip_nat6_u.o: $(TOP)/ip_nat6.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_nat6.c -o $@ + ip_proxy_u.o: $(TOP)/ip_proxy.c $(TOP)/ip_proxy.h $(TOP)/ip_compat.h \ $(TOP)/ip_fil.h $(PROXYLIST) $(TOP)/ip_nat.h $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_proxy.c -o $@ @@ -222,8 +238,13 @@ ip_htable_u.o: $(TOP)/ip_htable.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ $(TOP)/ip_htable.h $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_htable.c -o $@ +ip_dstlist_u.o: $(TOP)/ip_dstlist.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_dstlist.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_dstlist.c -o $@ + ip_lookup_u.o: $(TOP)/ip_lookup.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ - $(TOP)/ip_lookup.h $(TOP)/ip_pool.h $(TOP)/ip_htable.h + $(TOP)/ip_lookup.h $(TOP)/ip_pool.h $(TOP)/ip_htable.h \ + $(TOP)/ip_dstlist.h $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_lookup.c -o $@ ip_trafcon_u.o: $(TOP)/ip_trafcon.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ @@ -236,19 +257,28 @@ ip_log_u.o: $(TOP)/ip_log.c $(TOP)/ip_fil.h $(TOP)/ip_compat.h md5_u.o: $(TOP)/md5.c $(TOP)/md5.h $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/md5.c -o $@ -radix_u.o: $(TOP)/md5.c $(TOP)/radix_ipf.h - $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/radix.c -o $@ +radix_ipf_u.o: $(TOP)/md5.c $(TOP)/radix_ipf.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/radix_ipf.c -o $@ bpf_filter_u.o: $(TOP)/bpf_filter.c $(TOP)/pcap-ipf.h $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/bpf_filter.c -o $@ -if_ipl.o: $(MODOBJS) +ipflkm.o: $(MODOBJS) ld -r $(MODOBJS) -o $(LKM) - ${RM} -f if_ipl + ${RM} -f ipflkm ipfrule.ko.5: ip_rulesx.o $(MLR) +.if ${MACHINE_ARCH} != amd64 ld -warn-common -r -d -o $(.TARGET:S/.ko/.kld/) ip_rulesx.o $(MLR) - ld -Bshareable -d -warn-common -o $(LKMR:S/.5$//) $(.TARGET:S/.ko/.kld/) + ld -Bshareable -d -warn-common -o $(LKMR:S/.5$//) $(.TARGET:S/.ko/.kld/) +.else + ld -warn-common -r -d -o $(.TARGET:S/.5$//) ip_rulesx.o $(MLR) + nm -g $(.TARGET:S/.5$//) | \ + awk '/^[^[:space:]]+ [^AU] (.*)$$/ { print ($$2=="C" ? "-N" : "-L") $$3 }' | \ + xargs -J% objcopy % $(.TARGET:S/.5$//) + +.endif + ipfrule.ko: ip_rulesx.o $(MLR) gensetdefs ip_rulesx.o $(MLR) $(CC) $(KCARGS) -c setdef0.c @@ -256,10 +286,17 @@ ipfrule.ko: ip_rulesx.o $(MLR) ld -Bshareable -o $@ setdef0.o ip_rulesx.o $(MLR) setdef1.o ipf.ko.5 ipl.ko.5: $(MODOBJS) +.if ${MACHINE_ARCH} != amd64 ld -warn-common -r -d -o $(.TARGET:S/.ko/.kld/) $(MODOBJS) ld -Bshareable -d -warn-common -o $(LKM:S/.5$//) $(.TARGET:S/.ko/.kld/) - -ipf.ko ipl.ko: $(MODOBJS) +.else + ld -warn-common -r -d -o $(.TARGET:S/.5$//) $(MODOBJS) + nm -g $(.TARGET:S/.5$//) | \ + awk '/^[^[:space:]]+ [^AU] (.*)$$/ { print ($$2=="C" ? "-N" : "-L") $$3 }' | \ + xargs -J% objcopy % $(.TARGET:S/.5$//) +.endif + +ipf.ko ipl.ko: $(MODOBJS) gensetdefs $(MODOBJS) $(CC) $(KCARGS) -c setdef0.c $(CC) $(KCARGS) -c setdef1.c @@ -268,6 +305,9 @@ ipf.ko ipl.ko: $(MODOBJS) ip_nat.o: $(TOP)/ip_nat.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(CC) $(KCARGS) $(DFLAGS) -c $(TOP)/ip_nat.c -o $@ +ip_nat6.o: $(TOP)/ip_nat6.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(KCARGS) $(DFLAGS) -c $(TOP)/ip_nat6.c -o $@ + ip_frag.o: $(TOP)/ip_frag.c $(TOP)/ip_frag.h $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(CC) $(KCARGS) $(DFLAGS) -c $(TOP)/ip_frag.c -o $@ @@ -290,6 +330,11 @@ ip_fil.c: ip_fil.o: ip_fil.c $(TOP)/ip_fil.h $(TOP)/ip_compat.h $(TOP)/ip_nat.h $(CC) $(KCARGS) $(DFLAGS) $(COMPIPF) -c ip_fil.c -o $@ +ip_fil_compat.o: $(TOP)/ip_fil_compat.c $(TOP)/ipl.h $(TOP)/ip_fil.h \ + $(TOP)/ip_compat.h $(TOP)/ip_nat.h $(TOP)/ip_state.h + $(CC) $(KCARGS) $(DFLAGS) $(COMPIPF) $(COMPATIPF) \ + -c $(TOP)/ip_fil_compat.c -o $@ + ip_log.o: $(TOP)/ip_log.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(CC) $(KCARGS) $(DFLAGS) -c $(TOP)/ip_log.c -o $@ @@ -307,16 +352,26 @@ ip_htable.o: $(TOP)/ip_htable.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ $(TOP)/ip_lookup.h $(TOP)/ip_htable.h $(CC) $(KCARGS) $(DFLAGS) -c $(TOP)/ip_htable.c -o $@ +ip_dstlist.o: $(TOP)/ip_dstlist.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_lookup.h $(TOP)/ip_dstlist.h + $(CC) $(KCARGS) $(DFLAGS) -c $(TOP)/ip_dstlist.c -o $@ + ip_lookup.o: $(TOP)/ip_lookup.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ - $(TOP)/ip_pool.h $(TOP)/ip_htable.h $(TOP)/ip_lookup.h + $(TOP)/ip_pool.h $(TOP)/ip_htable.h $(TOP)/ip_lookup.h \ + $(TOP)/ip_dstlist.h $(CC) $(KCARGS) $(DFLAGS) -c $(TOP)/ip_lookup.c -o $@ +radix_ipf.o: $(TOP)/md5.c $(TOP)/radix_ipf.h + $(CC) $(KCARGS) $(DFLAGS) -c $(TOP)/radix_ipf.c -o $@ + ip_trafcon.o: $(TOP)/ip_trafcon.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ $(TOP)/ip_trafcon.h $(CC) $(KCARGS) $(DFLAGS) -c $(TOP)/ip_trafcon.c -o $@ vnode_if.h: $(VNODESHDIR)/vnode_if.src mkdir -p ../sys + mkdir -p ../rump/include/rump + mkdir -p ../rump/librump/rumpvfs if [ -f $(VNODESHDIR)/vnode_if.sh ] ; then \ sh $(VNODESHDIR)/vnode_if.sh $(VNODESHDIR)/vnode_if.src; \ fi @@ -325,10 +380,11 @@ vnode_if.h: $(VNODESHDIR)/vnode_if.src fi if [ -f ../sys/vnode_if.h ] ; then mv ../sys/vnode_if.h .; fi rmdir ../sys + rm -rf ../rump ml_ipl.o: vnode_if.h $(TOP)/$(MLD) $(TOP)/ipl.h -/bin/rm -f vnode_if.c - $(CC) -I. $(CFLAGS) $(DFLAGS) -c $(TOP)/$(ML) -o $@ + $(CC) -I. $(KCARGS) $(DFLAGS) -c $(TOP)/$(ML) -o $@ ip_rules.o: ip_rules.c $(TOP)/ip_rules.h $(CC) -I. $(CFLAGS) $(DFLAGS) $(COMPIPF) -c ip_rules.c -o $@ @@ -344,7 +400,7 @@ $(TOP)/ip_rules.h: ip_rules.c fi ip_rulesx.o: ip_rules.c $(TOP)/ip_rules.h - $(CC) -I. $(CFLAGS) $(DFLAGS) -DIPFILTER_COMPILED -c ip_rules.c -o $@ + $(CC) -I. $(KCARGS) $(DFLAGS) -DIPFILTER_COMPILED -c ip_rules.c -o $@ mlf_rule.o: $(TOP)/mlf_rule.c $(TOP)/ip_rules.h $(CC) -I. $(CFLAGS) $(DFLAGS) -c $(TOP)/mlf_rule.c -o $@ @@ -356,7 +412,7 @@ mlo_rule.o: $(TOP)/mlo_rule.c $(TOP)/ip_rules.h $(CC) -I. $(CFLAGS) $(DFLAGS) -c $(TOP)/mlo_rule.c -o $@ mlfk_rule.o: $(TOP)/mlfk_rule.c $(TOP)/ip_rules.h - $(CC) -I. $(CFLAGS) $(DFLAGS) -c $(TOP)/mlfk_rule.c -o $@ + $(CC) -I. $(KCARGS) $(DFLAGS) -c $(TOP)/mlfk_rule.c -o $@ ipf_y.o: ipf_y.c ipf_y.h $(TOP)/ipf.h ipf_l.h $(TOP)/opts.h $(CC) $(CCARGS) $(IPFBPF) -c ipf_y.c -o $@ @@ -427,10 +483,11 @@ ippool_y.o: ippool_y.c ippool_y.h $(TOP)/ip_pool.h ippool_l.h ippool_l.o: ippool_l.c ippool_y.h $(TOP)/ip_pool.h $(CC) $(CCARGS) -I. -c ippool_l.c -o $@ -ippool_y.c: $(TOOL)/ippool_y.y $(TOP)/ip_pool.h ippool_l.h +ippool_y.c: $(TOOL)/ippool_y.y $(TOP)/ip_pool.h ippool_l.h ippool_y.h (cd $(TOOL); make "DEST=$(HERE)" $(HERE)/$@) -ippool_y.h: ippool_y.c +ippool_y.h: $(TOOL)/ippool_y.y + (cd $(TOOL); make "DEST=$(HERE)" $(HERE)/$@) ippool_l.c: $(TOOL)/lexer.c $(TOP)/ip_pool.h (cd $(TOOL); make "DEST=$(HERE)" $(HERE)/$@) @@ -449,10 +506,10 @@ iptrafcon: $(IPTRAFCON) $(OBJ)/libipf.a .l.c: clean: - ${RM} -f ../ipf ../ipnat ../ipmon ../ippool ../ipftest + ${RM} -f ../ipf ../ipnat ../ipmon ../ippool ../ipftest ${RM} -f ../ipscan ../ipsyncm ../ipsyncs ${RM} -f *.core *.o *.a ipt ipfstat ipf ipfstat ipftest ipmon - ${RM} -f if_ipl ipnat ipfrule.ko* ipf.kld* ipfrule.kld* + ${RM} -f ipflkm ipnat ipfrule.ko* ipf.kld* ipfrule.kld* ${RM} -f vnode_if.h $(LKM) ioconf.h *.ko setdef1.c setdef0.c setdefs.h ${RM} -f ip_fil.c ipf_l.c ipf_y.c ipf_y.h ipf_l.h ${RM} -f ipscan ipscan_y.c ipscan_y.h ipscan_l.c ipscan_l.h @@ -481,8 +538,8 @@ install: /bin/cp $(TOP)/$$i /usr/include/netinet/; \ $(CHMOD) 444 /usr/include/netinet/$$i; \ done - -if [ -d /lkm -a -f if_ipl.o ] ; then \ - cp if_ipl.o /lkm; \ + -if [ -d /lkm -a -f ipflkm.o ] ; then \ + cp ipflkm.o /lkm; \ fi -if [ -d /modules -a -f ipf.ko ] ; then \ if [ -f /modules/ipl.ko ] ; then \ @@ -494,6 +551,7 @@ install: -if [ -d /modules -a -f ipfrule.ko ] ; then \ cp ipfrule.ko /modules; \ fi +.if ${MACHINE_ARCH} != amd64 -if [ -d /boot/kernel -a -f ipf.ko ] ; then \ if [ -f /boot/kernel/ipl.ko ] ; then \ cp ipf.ko /boot/kernel/ipl.ko; \ @@ -504,8 +562,29 @@ install: -if [ -d /boot/kernel -a -f ipfrule.ko ] ; then \ cp ipfrule.ko /boot/kernel; \ fi - -if [ -d /usr/lkm -a -f if_ipl.o ] ; then \ - cp if_ipl.o /usr/lkm; \ +.else + -if [ -d /boot/kernel -a -f ipf.ko ] ; then \ + if [ -f /boot/kernel/ipl.ko ] ; then \ + objcopy --only-keep-debug ipf.ko + /boot/kernel/ipl.ko.symbols; \ + objcopy --strip-debug \ + --add-gnu-debuglink=ipl.ko.symbols \ + ipf.ko /boot/kernel/ipl.ko; \ + else \ + objcopy --only-keep-debug ipf.ko \ + /boot/kernel/ipf.ko.symbols; \ + objcopy --strip-debug \ + --add-gnu-debuglink=ipl.ko.symbols \ + ipf.ko /boot/kernel/ipf.ko; \ + fi \ + fi + -if [ -d /boot/kernel -a -f ipfrule.ko ] ; then \ + objcopy --only-keep-debug ipfrule.ko /boot/kernel/ipfrule.ko.symbols; \ + objcopy --strip-debug --add-gnu-debuglink=ipfrule.ko.symbols ipfrule.ko /boot/kernel/ipfrule.ko; \ + fi +.endif + -if [ -d /usr/lkm -a -f ipflkm.o ] ; then \ + cp ipflkm.o /usr/lkm; \ fi -$(INSTALL) -cs -g wheel -m 755 -o root ipscan $(SBINDEST) (cd $(TOP)/man; make INSTALL=$(INSTALL) MANDIR=$(MANDIR) install; cd $(TOP)) @@ -533,8 +612,8 @@ install: (cd $(TOP)/man; make INSTALL=$(INSTALL) MANDIR=$(MANDIR) install; cd $(TOP)) coverage: - ksh -c 'for i in *.da; do j=$${i%%.da}.c; gcov $$j 2>&1 | egrep -v "y.tab.c|Could|Creating|_l\.c|\.h"; done' | sort -k 1n -k 3n > report - sort -k 1n -k 3n report | perl -e 'while(<>) { next if (/^0.00/); s/\%//g; @F=split;$$lc+=$$F[2];$$t += ($$F[0]/100)*$$F[2];} printf "%d of %d = %d%%\n", $$t, $$lc,($$t/$$lc)*100;' >> report + ksh -c 'for i in *.da; do j=$${i%%.da}.c; gcov $$j 2>&1 | egrep -v "y.tab.c|Could|Creating|_l\.c|\.h"; done' | sort -n > report + sort -n report | perl -e 'while(<>) { next if (/^0.00/); s/\%//g; @F=split;$$lc+=$$F[2];$$t += $$F[0]/100*$$F[2];} printf "%d of %d = %d%%\n", $$t, $$lc,$$t/$$lc*100;' >> report clean-coverage: /bin/rm -f *.gcov *.da diff --git a/BSD/Makefile.ipsend b/BSD/Makefile.ipsend index a83de1c6a92c0..68edf1a0c656f 100644 --- a/BSD/Makefile.ipsend +++ b/BSD/Makefile.ipsend @@ -1,5 +1,5 @@ # -# $Id: Makefile.ipsend,v 2.8 2002/05/22 16:15:36 darrenr Exp $ +# $Id$ # BINDEST=/usr/sbin @@ -23,7 +23,8 @@ MFLAGS="BINDEST=$(BINDEST)" "SBINDEST=$(SBINDEST)" "MANDIR=$(MANDIR)" \ "SOLARIS2=$(SOLARIS2)" "DEBUG=$(DEBUG)" "DCPU=$(CPU)" \ "CPUDIR=$(CPUDIR)" "LOOKUP=$(LOOKUP)" # -all build bsd-bpf : ipsend ipresend iptest +build: +all bsd-bpf : ipsend ipresend iptest iplang_y.o: $(TOP)/iplang/iplang_y.y (cd $(TOP)/iplang; $(MAKE) ../BSD/$(CPUDIR)/$@ $(MFLAGS) 'DESTDIR=../BSD/$(CPUDIR)' ) @@ -103,6 +104,6 @@ dlcommon.o: $(TOP)/ipsend/dlcommon.c sdlpi.o: $(TOP)/ipsend/sdlpi.c $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/sdlpi.c -o $@ -install: +install: -$(INSTALL) -cs -g wheel -m 755 -o root ipsend ipresend iptest $(BINDEST) diff --git a/BSD/ipfadm-rcd b/BSD/ipfadm-rcd index 41f62b0223df6..dbbd151b97e3c 100755 --- a/BSD/ipfadm-rcd +++ b/BSD/ipfadm-rcd @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (C) 2006 by Darren Reed. +# Copyright (C) 2012 by Darren Reed. # # See the IPFILTER.LICENCE file for details on licencing. # diff --git a/BSD/kupgrade b/BSD/kupgrade index 04b257d7ca60f..30df4545f2943 100644 --- a/BSD/kupgrade +++ b/BSD/kupgrade @@ -2,7 +2,7 @@ # PATH=/sbin:/usr/sbin:/bin:/usr/bin; export PATH argv0=`basename $0` - + os=`uname -s` rev=`uname -r` maj=`expr $rev : '\([0-9]*\)\.'` @@ -23,6 +23,7 @@ fi if [ -d /sys/dist/ipf ] ; then ipfdir=/sys/dist/ipf/netinet fi +mkdir -m 755 -p $ipfdir/../net confdir="$archdir/conf" if [ -f /dev/ipnat ] ; then major=`ls -l /dev/ipnat | sed -e 's/.* \([0-9]*\),.*/\1/'` @@ -30,7 +31,7 @@ if [ -f /dev/ipnat ] ; then else major=x fi - + if [ ! -f ip_rules.c -o ! -f ip_rules.h ] ; then echo "Trying to build ip_rules.c and ip_rules.h" make ip_rules.c @@ -43,8 +44,9 @@ if [ ! -f ip_rules.c -o ! -f ip_rules.h ] ; then fi fi -echo -n "Installing " -for j in auth frag nat proxy scan state sync pool htable lookup rules; do +echo -n "Installing into $ipfdir" +for j in auth frag nat proxy scan state sync pool dstlist htable lookup rules \ + dstlist; do for i in ip_$j.[ch]; do if [ -f "$i" ] ; then echo -n " $i" @@ -53,6 +55,12 @@ for j in auth frag nat proxy scan state sync pool htable lookup rules; do fi done done +echo -n " net/radix_ipf.h" +cp radix_ipf.h $ipfdir +chmod 644 $ipfdir/radix_ipf.h +echo -n " radix_ipf.c -> $ipfdir/radix_ipf.c" +cp radix_ipf.c $ipfdir/radix_ipf.c +chmod 644 $ipfdir/radix_ipf.c case $os in SunOS) @@ -88,14 +96,16 @@ if [ -f $ipfdir/ip_fil.c ] ; then chmod 644 $ipfdir/ip_fil.c fi -for i in ip_fil.h fil.c ip_log.c ip_compat.h ipl.h ip_*_pxy.c; do +for i in ip_nat6.c ip_fil.h fil.c ip_log.c ip_compat.h ipl.h ip_*_pxy.c \ + ip_fil_compat.c ipf_rb.h; do echo -n " $i" cp $i $ipfdir chmod 644 $ipfdir/$i done echo "" echo -n "Installing into /usr/include/netinet" -for j in auth compat fil frag nat proxy scan state sync pool htable lookup; do +for j in auth compat fil frag nat proxy scan state sync pool htable dstlist \ + lookup; do i=ip_$j.h if [ -f "$i" ] ; then echo -n " $i" @@ -103,7 +113,7 @@ for j in auth compat fil frag nat proxy scan state sync pool htable lookup; do chmod 644 /usr/include/netinet/$i fi done -for j in ipl.h; do +for j in ipl.h ipf_rb.h; do if [ -f "$j" ] ; then echo -n " $j" cp $j /usr/include/netinet/$j @@ -157,15 +167,19 @@ if [ $os = FreeBSD -a -f /sys/conf/files ] ; then mv files files.preipf4 cp -p files.preipf4 files fi - for i in htable pool lookup; do + for i in dstlist htable pool lookup; do grep ip_$i.c files >/dev/null 2>&1 if [ $? -ne 0 ] ; then echo "contrib/ipfilter/netinet/ip_$i.c optional ipfilter inet ipfilter_lookup" >> files fi done + grep ip_fil_compat.c files >/dev/null 2>&1 + if [ $? -ne 0 ] ; then + echo 'contrib/ipfilter/netinet/ip_fil_compat.c optional ipfilter inet ipfilter_compat' >> files + fi grep ip_sync.c files >/dev/null 2>&1 if [ $? -ne 0 ] ; then - echo 'contrib/ipfilter/netinet/ip_sync.c optional ipfilter inet ipfilter_sync' >> files + echo 'contrib/ipfilter/netinet/ip_sync.c optional ipfilter inet' >> files fi grep ip_scan.c files >/dev/null 2>&1 if [ $? -ne 0 ] ; then @@ -177,13 +191,19 @@ if [ $os = FreeBSD -a -f /sys/conf/files ] ; then fi fi if [ $os = NetBSD -a -f /sys/conf/files ] ; then + if [ -f /sys/netinet/files.ipfilter ] ; then + if ! grep -q ip_fil_compat.c /sys/netinet/files.ipfilter; then + echo 'file dist/ipf/netinet/ip_fil_compat.c ipfilter & ipfilter_compat' >> /sys/netinet/files.ipfilter + echo 'defflag opt_ipfilter.h IPFILTER_COMPAT' >> /sys/netinet/files.ipfilter + fi + fi cd /sys/conf if [ ! -f files.preipf4 ] ; then mv files files.preipf4 cp -p files.preipf4 files fi if [ $fullrev -ge 010600 -a $fullrev -lt 020000 ] ; then - for i in htable pool lookup; do + for i in dstlist htable pool lookup; do grep ip_$i.c files >/dev/null 2>&1 if [ $? -ne 0 ] ; then echo "file netinet/ip_$i.c ipfilter & ipfilter_lookup" >> files @@ -191,7 +211,7 @@ if [ $os = NetBSD -a -f /sys/conf/files ] ; then done grep ip_sync.c files >/dev/null 2>&1 if [ $? -ne 0 ] ; then - echo 'file netinet/ip_sync.c ipfilter & ipfilter_sync' >> files + echo 'file netinet/ip_sync.c ipfilter' >> files fi grep ip_scan.c files >/dev/null 2>&1 if [ $? -ne 0 ] ; then @@ -210,15 +230,18 @@ if [ $os = OpenBSD -a -f /sys/conf/files ] ; then cp -p files.preipf4 files fi if [ $fullrev -ge 030400 ] ; then - for i in htable pool lookup; do + for i in dstlist htable pool lookup; do grep ip_$i.c files >/dev/null 2>&1 if [ $? -ne 0 ] ; then echo "file netinet/ip_$i.c ipfilter & ipfilter_lookup" >> files fi done - grep ip_sync.c files >/dev/null 2>&1 + grep ip_fil_compat.c files >/dev/null 2>&1 + if [ $? -ne 0 ] ; then + echo 'file netinet/ip_fil_compat.c ipfilter & ipfilter_compat' >> files + fi if [ $? -ne 0 ] ; then - echo 'file netinet/ip_sync.c ipfilter & ipfilter_sync' >> files + echo 'file netinet/ip_sync.c ipfilter' >> files fi grep ip_scan.c files >/dev/null 2>&1 if [ $? -ne 0 ] ; then @@ -241,7 +264,7 @@ cat | (cd /usr/src/sys/modules/ipfilter; patch) <<__EOF__ KMOD= ipl SRCS= mlfk_ipl.c ip_nat.c ip_frag.c ip_state.c ip_proxy.c ip_auth.c \\ ! ip_log.c ip_fil.c fil.c - + .if !defined(NOINET6) CFLAGS+= -DUSE_INET6 .endif @@ -249,10 +272,10 @@ cat | (cd /usr/src/sys/modules/ipfilter; patch) <<__EOF__ ! CFLAGS+= -DIPFILTER=1 -DIPFILTER_LKM -DIPFILTER_LOG -DPFIL_HOOKS --- 5,15 ---- KMOD= ipl - SRCS= mlfk_ipl.c ip_nat.c ip_frag.c ip_state.c ip_proxy.c ip_auth.c \\ -! ip_log.c ip_fil.c fil.c ip_lookup.c ip_pool.c ip_htable.c \\ -! ip_sync.c ip_scan.c ip_rules.c - + SRCS= mlfk_ipl.c ip_nat.c ip_nat6.c ip_frag.c ip_state.c ip_proxy.c ip_auth.c \\ +! ip_log.c ip_fil.c fil.c ip_lookup.c ip_pool.c ip_dstlist.c ip_htable.c \\ +! ip_sync.c ip_scan.c ip_rules.c ip_fil_compat.c + .if !defined(NOINET6) CFLAGS+= -DUSE_INET6 .endif @@ -261,4 +284,29 @@ cat | (cd /usr/src/sys/modules/ipfilter; patch) <<__EOF__ ! -DIPFILTER_LOOKUP -DIPFILTER_COMPILED __EOF__ fi + +CONF=/sys/netinet/files.ipfilter +if [ -f $CONF -a $os = NetBSD ] ; then + for i in ip_nat6.c ip_dstlist.c radix_ipf.c; do + echo "Checking for $i in $CONF" + grep $i $CONF >/dev/null 2>&1 + if [ $? -ne 0 ] ; then + echo "Adding $i to $CONF" + sed -n -e /ip_nat.c/s/ip_nat.c/$i/p $CONF >> $CONF + fi + done +fi + +CONF=/sys/conf/files +if [ -f $CONF -a $os = FreeBSD ] ; then + for i in ip_nat6.c ip_dstlist.c radix_ipf.c; do + echo "Checking for $i in $CONF" + grep $i $CONF >/dev/null 2>&1 + if [ $? -ne 0 ] ; then + echo "Adding $i to $CONF" + sed -n -e /ip_nat.c/,/NORMAL/p $CONF | \ + sed -e s/ip_nat.c/$i/p >> $CONF + fi + done +fi exit 0 diff --git a/BSD/upgrade b/BSD/upgrade new file mode 100755 index 0000000000000..d5f815438656e --- /dev/null +++ b/BSD/upgrade @@ -0,0 +1,46 @@ +#!/bin/sh +# +PATH=/sbin:/usr/sbin:/bin:/usr/bin; export PATH +argv0=`basename $0` + +case `pwd` in +*BSD) + ;; +*) + cd BSD + ;; +esac +os=`uname -s` +rev=`uname -r` +maj=`expr $rev : '\([0-9]*\)\.'` +min=`expr $rev : '[0-9]*\.\([0-9]*\)'` +sub=`expr $rev : '[0-9]*\.[0-9]*\.\([0-9]*\)'` +plat=`uname -p` +objdir=${os}-${rev}-${plat} + +# try to bomb out fast if anything fails.... +set -e + +for i in ipf ipfstat ipmon ipnat ippool; do + if [ ! -f /sbin/${i}.dist -a -f /sbin/${i} ] ; then + mv /sbin/${i} /sbin/${i}.dist + cp -p /sbin/${i}.dist /sbin/${i} + cp ${objdir}/${i} /sbin/ + fi + if [ ! -f /usr/sbin/${i}.dist -a -f /usr/sbin/${i} ] ; then + mv /usr/sbin/${i} /usr/sbin/${i}.dist + cp -p /usr/sbin/${i}.dist /usr/sbin/${i} + cp ${objdir}/${i} /usr/sbin/ + fi +done +if [ -f /boot/kernel/ipl.ko ] ; then + if [ ! -f /boot/kernel/ipl.ko.dist ] ; then + mv /boot/kernel/ipl.ko /boot/kernel/ipl.ko.dist + cp -p /boot/kernel/ipl.ko.dist /boot/kernel/ipl.ko + fi + if [ ! -f /boot/kernel/ipl.ko.symbols.dist ] ; then + mv /boot/kernel/ipl.ko.symbols /boot/kernel/ipl.ko.symbols.dist + fi + cp ${objdir}/ipf.ko /boot/kernel/ipl.ko +fi +exit 0 diff --git a/BSDOS/files.diffs b/BSDOS/files.diffs new file mode 100644 index 0000000000000..0b34dbc37e9c2 --- /dev/null +++ b/BSDOS/files.diffs @@ -0,0 +1,23 @@ +*** files.orig Tue Mar 19 16:18:21 1996 +--- files Fri Mar 8 14:20:52 1996 +*************** +*** 201,206 **** +--- 201,218 ---- + file netinet/tcp_timer.c inet + file netinet/tcp_usrreq.c inet + file netinet/udp_usrreq.c inet ++ file netinet/ip_fil.c ipfilter ++ file netinet/fil.c ipfilter ++ file netinet/ip_nat.c ipfilter ++ file netinet/ip_frag.c ipfilter ++ file netinet/ip_state.c ipfilter ++ file netinet/ip_auth.c ipfilter ++ file netinet/ip_proxy.c ipfilter ++ file netinet/ip_log.c ipfilter ++ file netinet/ip_scan.c ipfilter ++ file netinet/ip_sync.c ipfilter ++ file netinet/ip_pool.c ipfilter_pool ++ file netinet/ip_rules.c ipfilter_compiled + file netiso/clnp_debug.c iso + file netiso/clnp_er.c iso + file netiso/clnp_frag.c iso diff --git a/BSDOS/ioconf.c.i386.diffs b/BSDOS/ioconf.c.i386.diffs new file mode 100644 index 0000000000000..a7e07f0e591de --- /dev/null +++ b/BSDOS/ioconf.c.i386.diffs @@ -0,0 +1,28 @@ +*** ioconf.c.i386.orig Tue Mar 19 16:20:07 1996 +--- ioconf.c.i386 Fri Mar 8 15:12:59 1996 +*************** +*** 21,26 **** +--- 21,29 ---- + extern struct devsw cnsw, cttysw, mmsw, swapsw, logsw, devfdsw; + extern struct devsw ptssw, ptcsw; + extern struct devsw pcsw, kbdsw; ++ #if defined(IPFILTER) ++ extern struct devsw iplsw; ++ #endif + + %DECLSW + +*************** +*** 62,67 **** +--- 65,75 ---- + %DEVSW(sr), /* 34 = SCSI removeable disks (clone of sd) */ + %DEVSW(rp), /* 35 = Comtrol Rocketport */ + %DEVSW(cy), /* 36 = Cyclades async mux */ ++ #if defined(IPFILTER) ++ &iplsw, /* 37 = IP Filter */ ++ #else ++ NULL, /* 37 = IP Filter */ ++ #endif + }; + #define NDEVSW (sizeof(devsw) / sizeof(*devsw)) + int ndevsw = NDEVSW; diff --git a/BSDOS/ip_input.c.diffs b/BSDOS/ip_input.c.diffs new file mode 100644 index 0000000000000..2829f4edaa448 --- /dev/null +++ b/BSDOS/ip_input.c.diffs @@ -0,0 +1,37 @@ +*** ip_input.c.orig Tue Mar 19 16:19:06 1996 +--- ip_input.c Fri Mar 8 18:31:22 1996 +*************** +*** 77,82 **** +--- 77,86 ---- + int ipqmaxlen = IFQ_MAXLEN; + struct in_ifaddr *in_ifaddr; /* first inet address */ + struct ifqueue ipintrq; ++ #if defined(IPFILTER) ++ extern int fr_check __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif + + /* + * We need to save the IP options in case a protocol wants to respond +*************** +*** 232,237 **** +--- 236,254 ---- + m_adj(m, ip->ip_len - m->m_pkthdr.len); + } + ++ #if defined(IPFILTER) ++ /* ++ * Check if we want to allow this packet to be processed. ++ * Consider it to be bad if not. ++ */ ++ if (fr_checkp) { ++ struct mbuf *m1 = m; ++ ++ if ((*fr_checkp)(ip, hlen, m->m_pkthdr.rcvif, 0, &m1) || !m1) ++ goto next; ++ ip = mtod(m = m1, struct ip *); ++ } ++ #endif + /* + * Process options and, if not destined for us, + * ship it on. ip_dooptions returns 1 when an diff --git a/BSDOS/ip_output.c.diffs b/BSDOS/ip_output.c.diffs new file mode 100644 index 0000000000000..1ee533c9dd0b4 --- /dev/null +++ b/BSDOS/ip_output.c.diffs @@ -0,0 +1,35 @@ +*** ip_output.c.orig Tue Mar 19 16:19:33 1996 +--- ip_output.c Fri Mar 8 14:50:51 1996 +*************** +*** 60,65 **** +--- 60,69 ---- + static struct mbuf *ip_insertoptions __P((struct mbuf *, struct mbuf *, int *)); + static void ip_mloopback + __P((struct ifnet *, struct mbuf *, struct sockaddr_in *)); ++ #if defined(IPFILTER) ++ extern int fr_check __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif + + /* + * IP output. The packet in mbuf chain m contains a skeletal IP +*************** +*** 276,281 **** +--- 280,296 ---- + } else + m->m_flags &= ~M_BCAST; + + sendit: ++ #if defined(IPFILTER) ++ { ++ struct mbuf *m1 = m; ++ /* ++ * looks like most checking has been done now...do a filter check ++ */ ++ if (fr_checkp && ((error = (*fr_checkp)(ip, hlen, ifp, 1, &m1)) || !m1)) ++ goto done; ++ ip = mtod(m = m1, struct ip *); ++ } ++ #endif + /* + * If small enough for interface, can just send directly. diff --git a/BSDOS/kinstall b/BSDOS/kinstall new file mode 100755 index 0000000000000..58417f2795ebf --- /dev/null +++ b/BSDOS/kinstall @@ -0,0 +1,56 @@ +#!/bin/csh -f +# +set dir=`pwd` +set karch=`uname -m` +if ( -d /sys/arch/$karch ) set archdir="/sys/arch/$karch" +if ( -d /sys/$karch ) set archdir="/sys/$karch" +set confdir="$archdir/conf" + +if ( $dir =~ *fil/BSDOS ) cd .. +if ($0 =~ *kinstall) then + foreach i (ip_{auth,fil,frag,nat,proxy,scan,state,sync}.[ch] \ + fil.c ip_compat.h ip_log.c ip_*_pxy.c) + echo -n "$i "; + cp $i /sys/netinet + chmod 664 /sys/netinet/$i + switch ($i) + case *.h: + /bin/cp $i /usr/include/netinet/$i + chmod 644 /usr/include/netinet/$i + breaksw + endsw + end + echo "" + echo "Patching $archdir/$karch/ioconf.c.$karch" + cat ioconf.c.$karch.diffs | (cd $archdir/$karch; patch) +endif +echo "Patching ip_input.c and ip_output.c" +cat BSDOS/ip_{in,out}put.c.diffs | (cd /sys/netinet; patch) + +if ( -f /sys/conf/files ) then + echo "Patching /sys/conf/files" + cat BSDOS/files.diffs | (cd /sys/conf; patch) +endif + +set config=`/bin/ls -1t $confdir [0-9A-Z_]* | head -1` + +echo -n "Kernel configuration to update [$config] " +set newconfig=$< +if ( "$newconfig" != "" ) then + set config="$confdir/$newconfig" +else + set newconfig=$config +endif +echo "Re-config'ing $newconfig..." +if ( -f $confdir/$newconfig ) then + mv $confdir/$newconfig $confdir/$newconfig.bak +endif +if ( -d $archdir/$newconfig ) then + mv $archdir/$newconfig $archdir/$newconfig.bak +endif +if ($0 =~ *kinstall) then + awk '{print $0;if($2=="INET"){print"options IPFILTER"}}' \ + $confdir/$newconfig.bak > $confdir/$newconfig +endif +echo 'You will now need to run "config" and build a new kernel.' +exit 0 diff --git a/BSDOS3/OBJS/README b/BSDOS3/OBJS/README new file mode 100644 index 0000000000000..14346e20dfc73 --- /dev/null +++ b/BSDOS3/OBJS/README @@ -0,0 +1,6 @@ + +If you have any questions or comments relating to the .o files in this +directory, please email Alan Clegg - abc@bsdi.com. + +Cheers, +Darren diff --git a/BSDOS3/OBJS/files b/BSDOS3/OBJS/files new file mode 100644 index 0000000000000..519d581877554 --- /dev/null +++ b/BSDOS3/OBJS/files @@ -0,0 +1,342 @@ +# BSDI $Id$ +# +# @(#)files.newconf 8.9 (Berkeley) 3/31/94 + +# generic attributes +define disk +define tape +define ifnet +define tty + +# net device attributes - we have generic code for ether. +# we should have imp but right now it is a pseudo-device. +define ether +define p2p +define token +define fddi +# define imp +pseudo-device imp + +# scsi driver and associated stuff +define scsi { target = -1 } +device tg at scsi { unit = -1 } +file dev/scsi/scsi_subr.c scsi +file dev/scsi/scsi_spi.c scsi + +# support functions used by low level spi drivers +define spilow +file dev/scsi/scsi_spilow.c spilow + + +device sd at tg: disk +device sr at tg: disk +file dev/scsi/sd.c sd|sr + +device st at tg: tape +file dev/scsi/st.c st + +device sg at tg +file dev/scsi/sg.c sg + +# media indepent interface network layer +define mii { phy = -1 } +file dev/mii/mii_subr.c mii + +# legitimate pseudo-devices +pseudo-device appp: ifnet, p2p +pseudo-device pif +pseudo-device bpfilter +pseudo-device gwscreen +pseudo-device cd: disk +pseudo-device sp: disk +pseudo-device loop +pseudo-device tun +pseudo-device pty: tty +pseudo-device sl: ifnet +pseudo-device vnd: disk +pseudo-device rd: disk + +file dev/disk_subr.c disk +file dev/cd.c cd&!objsrc always-source + +file dev/sp.c sp + +file dev/vnd.c vnd + +file dev/rd.c rd + +# kernel sources +file isofs/cd9660/cd9660_bmap.c cd9660 +file isofs/cd9660/cd9660_lookup.c cd9660 +file isofs/cd9660/cd9660_node.c cd9660 +file isofs/cd9660/cd9660_rrip.c cd9660 +file isofs/cd9660/cd9660_util.c cd9660 +file isofs/cd9660/cd9660_vfsops.c cd9660 +file isofs/cd9660/cd9660_vnops.c cd9660 +file kern/init_main.c +file kern/kern_acct.c +file kern/kern_clock.c +file kern/kern_descrip.c +file kern/kern_exec.c +file kern/kern_exit.c +file kern/kern_fork.c +file kern/kern_ktrace.c ktrace | !source +file kern/kern_lock.c +file kern/kern_malloc.c +file kern/kern_physio.c +file kern/kern_proc.c +file kern/kern_prot.c +file kern/kern_resource.c +file kern/kern_sig.c +file kern/kern_subr.c +file kern/kern_synch.c +file kern/kern_sysctl.c +file kern/kern_license.c +file kern/kern_time.c +file kern/kern_xxx.c +file kern/subr_autoconf.c +file kern/subr_log.c +file kern/subr_prf.c +file kern/subr_prof.c +file kern/subr_rmap.c +file kern/subr_xxx.c +file kern/sys_generic.c +file kern/sys_process.c +file kern/sys_socket.c +file kern/sys_sem.c compat_semaphore +file kern/sysv_ipc.c +file kern/sysv_msg.c +file kern/sysv_sem.c +file kern/sysv_shm.c +file kern/tty.c +file kern/tty_compat.c +file kern/tty_conf.c !objsrc always-source +file kern/tty_pty.c pty +file kern/tty_subr.c +file kern/tty_tb.c tb needs-flag +file kern/tty_tty.c +file kern/uipc_domain.c !objsrc always-source +file kern/uipc_mbuf.c +file kern/uipc_proto.c !objsrc always-source +file kern/uipc_socket.c +file kern/uipc_socket2.c +file kern/uipc_syscalls.c +file kern/uipc_usrreq.c +file kern/vfs_bio.c +file kern/vfs_cache.c +file kern/vfs_cluster.c +file kern/vfs_conf.c !objsrc always-source +file kern/vfs_init.c +file kern/vfs_lookup.c +file kern/vfs_subr.c +file kern/vfs_syscalls.c +file kern/vfs_vnops.c +file miscfs/deadfs/dead_vnops.c +file miscfs/fdesc/fdesc_vfsops.c fdesc +file miscfs/fdesc/fdesc_vnops.c fdesc +file miscfs/fifofs/fifo_vnops.c fifo | !source +file miscfs/kernfs/kernfs_vfsops.c kernfs +file miscfs/kernfs/kernfs_vnops.c kernfs +file miscfs/nullfs/null_subr.c (nullfs | umapfs) +file miscfs/nullfs/null_vfsops.c (nullfs | umapfs) +file miscfs/nullfs/null_vnops.c (nullfs | umapfs) +file miscfs/portal/portal_vfsops.c portal +file miscfs/portal/portal_vnops.c portal +file miscfs/procfs/procfs_subr.c procfs +file miscfs/procfs/procfs_vnops.c procfs +file miscfs/procfs/procfs_vfsops.c procfs +file miscfs/procfs/procfs_note.c procfs +file miscfs/procfs/procfs_mem.c procfs +file miscfs/procfs/procfs_ctl.c procfs +file miscfs/procfs/procfs_status.c procfs +file miscfs/procfs/procfs_regs.c procfs +file miscfs/procfs/procfs_fpregs.c procfs +file miscfs/specfs/spec_vnops.c +file miscfs/umapfs/umap_subr.c umapfs +file miscfs/umapfs/umap_vfsops.c umapfs +file miscfs/umapfs/umap_vnops.c umapfs +file miscfs/union/union_subr.c union +file miscfs/union/union_vfsops.c union +file miscfs/union/union_vnops.c union +file msdosfs/msdosfs_conv.c msdosfs +file msdosfs/msdosfs_denode.c msdosfs +file msdosfs/msdosfs_fat.c msdosfs +file msdosfs/msdosfs_lookup.c msdosfs +file msdosfs/msdosfs_vfsops.c msdosfs +file msdosfs/msdosfs_vnops.c msdosfs +file net/bpf.c bpfilter needs-flag +file net/bpf_filter.c bpfilter needs-flag +file net/gw_screen.c gwscreen&!objsrc always-source +file net/if.c !objsrc always-source +file net/if_appp.c appp needs-flag +file net/if_c_hdlc.c cisco_hdlc +file net/if_ethersubr.c (ether|fddi)&!objsrc always-source +file net/if_link.c +file net/if_loop.c loop&!objsrc always-source +file net/if_tun.c tun +file net/if_media.c (ether|fddi|token) +file net/if_p2pproto.c p2p&!objsrc always-source +file net/if_p2psubr.c p2p&!objsrc always-source +file net/if_ppp.c ppp +file net/if_pppmp.c ppp&pif&!nomultilink +file net/if_pif.c pif +file net/if_sl.c sl needs-flag +file net/if_tokensubr.c token&!objsrc needs-flag always-source +file net/if_fddisubr.c fddi&!objsrc needs-flag always-source +file net/net_proto.c +file net/radix.c +file net/raw_cb.c +file net/raw_usrreq.c +file net/route.c +file net/rtsock.c +file net/slcompress.c sl|ppp +file netccitt/ccitt_proto.c ccitt +file netccitt/llc_input.c llc +file netccitt/llc_output.c llc +file netccitt/llc_subr.c llc +file netccitt/llc_timer.c llc +file netccitt/hd_debug.c hdlc +file netccitt/hd_input.c hdlc +file netccitt/hd_output.c hdlc +file netccitt/hd_subr.c hdlc +file netccitt/hd_timer.c hdlc +file netccitt/if_x25subr.c ccitt&!objsrc always-source +file netccitt/pk_acct.c ccitt +file netccitt/pk_debug.c ccitt +file netccitt/pk_input.c ccitt +file netccitt/pk_llcsubr.c llc|hdlc +file netccitt/pk_output.c ccitt +file netccitt/pk_subr.c ccitt +file netccitt/pk_timer.c ccitt +file netccitt/pk_usrreq.c ccitt +file netimp/if_imp.c imp needs-count +file netimp/if_imphost.c imp needs-count +file netimp/raw_imp.c imp +file netinet/if_ether.c (ether|token|fddi)&!objsrc needs-flag always-source +file netinet/igmp.c inet +file netinet/in.c inet +file netinet/in_pcb.c inet +file netinet/in_proto.c inet&!objsrc always-source +file netinet/ip_icmp.c inet +file netinet/ip_input.c inet +file netinet/ip_mroute.c inet&mrouting +file netinet/ip_output.c inet +file netinet/ip_screen.c gwscreen&!objsrc always-source +file netinet/raw_ip.c inet +file netinet/tcp_debug.c inet +file netinet/tcp_input.c inet +file netinet/tcp_output.c inet +file netinet/tcp_subr.c inet +file netinet/tcp_timer.c inet +file netinet/tcp_usrreq.c inet +file netinet/udp_usrreq.c inet +file netinet/ip_fil.c ipfilter +file netinet/fil.c ipfilter +file netinet/ip_nat.c ipfilter +file netinet/ip_frag.c ipfilter +file netinet/ip_state.c ipfilter +file netinet/ip_auth.c ipfilter +file netinet/ip_proxy.c ipfilter +file netinet/ip_log.c ipfilter +file netiso/clnp_debug.c iso +file netiso/clnp_er.c iso +file netiso/clnp_frag.c iso +file netiso/clnp_input.c iso +file netiso/clnp_options.c iso +file netiso/clnp_output.c iso +file netiso/clnp_raw.c iso +file netiso/clnp_subr.c iso +file netiso/clnp_timer.c iso +file netiso/cltp_usrreq.c iso +file netiso/esis.c iso +file netiso/if_eon.c eon +file netiso/idrp_usrreq.c iso +file netiso/iso.c iso +file netiso/iso_chksum.c iso +file netiso/iso_pcb.c iso +file netiso/iso_proto.c iso&!objsrc always-source +file netiso/iso_snpac.c iso +file netiso/tp_astring.c iso|tpip +file netiso/tp_cons.c iso +file netiso/tp_driver.c iso|tpip +file netiso/tp_emit.c iso|tpip +file netiso/tp_inet.c iso|tpip +file netiso/tp_input.c iso|tpip +file netiso/tp_iso.c iso +file netiso/tp_meas.c iso|tpip +file netiso/tp_output.c iso|tpip +file netiso/tp_pcb.c iso|tpip +file netiso/tp_subr.c iso|tpip +file netiso/tp_subr2.c iso|tpip +file netiso/tp_timer.c iso|tpip +file netiso/tp_trace.c iso|tpip +file netiso/tp_usrreq.c iso|tpip +file netiso/tuba_subr.c iso&tuba +file netiso/tuba_table.c iso&tuba +file netiso/tuba_usrreq.c iso&tuba +file netns/idp_usrreq.c ns&!objsrc always-source +file netns/ns.c ns +file netns/ns_error.c ns +file netns/ns_input.c ns +file netns/ns_ip.c ns +file netns/ns_output.c ns +file netns/ns_pcb.c ns +file netns/ns_proto.c ns&!objsrc always-source +file netns/spp_debug.c ns +file netns/spp_usrreq.c ns +file nfs/nfs_bio.c nfs +file nfs/nfs_node.c nfs +file nfs/nfs_nqlease.c nfs +file nfs/nfs_serv.c nfs +file nfs/nfs_socket.c nfs +file nfs/nfs_srvcache.c nfs +file nfs/nfs_subs.c nfs +file nfs/nfs_syscalls.c nfs +file nfs/nfs_vfsops.c nfs +file nfs/nfs_vnops.c nfs +file ufs/ffs/ffs_alloc.c ffs|mfs +file ufs/ffs/ffs_balloc.c ffs|mfs +file ufs/ffs/ffs_inode.c ffs|mfs +file ufs/ffs/ffs_subr.c ffs|mfs +file ufs/ffs/ffs_tables.c ffs|mfs +file ufs/ffs/ffs_vfsops.c ffs|mfs +file ufs/ffs/ffs_vnops.c ffs|mfs +file ufs/lfs/lfs_alloc.c lfs +file ufs/lfs/lfs_bio.c lfs +file ufs/lfs/lfs_balloc.c lfs +file ufs/lfs/lfs_cksum.c lfs +file ufs/lfs/lfs_debug.c lfs +file ufs/lfs/lfs_inode.c lfs +file ufs/lfs/lfs_segment.c lfs +file ufs/lfs/lfs_subr.c lfs +file ufs/lfs/lfs_syscalls.c lfs +file ufs/lfs/lfs_vfsops.c lfs +file ufs/lfs/lfs_vnops.c lfs +file ufs/mfs/mfs_vfsops.c mfs +file ufs/mfs/mfs_vnops.c mfs +file ufs/ufs/ufs_bmap.c ffs|lfs|mfs +file ufs/ufs/ufs_ihash.c ffs|lfs|mfs +file ufs/ufs/ufs_inode.c ffs|lfs|mfs +file ufs/ufs/ufs_lockf.c ffs|lfs|mfs +file ufs/ufs/ufs_lookup.c ffs|lfs|mfs +file ufs/ufs/ufs_quota.c ffs|lfs|mfs +file ufs/ufs/ufs_vfsops.c ffs|lfs|mfs +file ufs/ufs/ufs_vnops.c ffs|lfs|mfs +file vm/asyncdaemon.c +file vm/device_pager.c +file vm/swap_pager.c +file vm/vm_fault.c +file vm/vm_glue.c +file vm/vm_init.c +file vm/vm_kern.c +file vm/vm_map.c +file vm/vm_meter.c +file vm/vm_mmap.c +file vm/vm_object.c +file vm/vm_page.c +file vm/vm_pageout.c +file vm/vm_pager.c +file vm/vm_swap.c +file vm/vm_unix.c +file vm/vm_user.c +file vm/vnode_pager.c diff --git a/BSDOS3/OBJS/ioconf.c b/BSDOS3/OBJS/ioconf.c new file mode 100644 index 0000000000000..5ec979df2cdad --- /dev/null +++ b/BSDOS3/OBJS/ioconf.c @@ -0,0 +1,644 @@ +/* + * MACHINE GENERATED: DO NOT EDIT + * + * ioconf.c, from "DIALOUT" + */ + +#line 1 "../../i386/conf/ioconf.c.i386" +/*- + * Copyright (c) 1994, 1995, 1996 Berkeley Software Design, Inc. + * All rights reserved. + * The Berkeley Software Design Inc. software License Agreement specifies + * the terms and conditions for redistribution. + * + * BSDI $Id$ + * + * WILDBOAR $Wildboar: ioconf.c.i386,v 1.8 1996/02/13 13:01:15 shigeya Exp $ + * + * Portions or all of this file are Copyright(c) 1994,1995,1996 + * Yoichi Shinoda, Yoshitaka Tokugawa, WIDE Project, Wildboar Project + * and Foretune. All rights reserved. + * + * This code has been contributed to Berkeley Software Design, Inc. + * by the Wildboar Project and its contributors. + */ + +/* template ioconf.c for i386 */ + +#include <sys/param.h> +#include <sys/conf.h> +#include <sys/device.h> +#include <i386/isa/isa.h> +#include <i386/isa/isavar.h> +#include <i386/isa/icu.h> + +extern struct cfdriver tgcd; +extern struct cfdriver sdcd; +extern struct cfdriver srcd; +extern struct cfdriver stcd; +extern struct cfdriver sgcd; +extern struct cfdriver isacd; +extern struct cfdriver pcconscd; +extern struct cfdriver pcauxcd; +extern struct cfdriver comcd; +extern struct cfdriver lpcd; +extern struct cfdriver fdccd; +extern struct cfdriver fdcd; +extern struct cfdriver dptcd; +extern struct cfdriver wdccd; +extern struct cfdriver wdcd; +extern struct cfdriver wdpicd; +extern struct cfdriver mcdcd; +extern struct cfdriver wtcd; +extern struct cfdriver npxcd; +extern struct cfdriver vgacd; +extern struct cfdriver bmscd; +extern struct cfdriver lmscd; +extern struct cfdriver ahacd; +extern struct cfdriver bhacd; +extern struct cfdriver necd; +extern struct cfdriver epcd; +extern struct cfdriver sacd; +extern struct cfdriver ncrcd; +extern struct cfdriver saturncd; +extern struct cfdriver aiccd; +extern struct cfdriver tncd; +extern struct cfdriver hppcd; +extern struct cfdriver recd; +extern struct cfdriver wecd; +extern struct cfdriver tlcd; +extern struct cfdriver ebcd; +extern struct cfdriver efcd; +extern struct cfdriver elcd; +extern struct cfdriver excd; +extern struct cfdriver eahacd; +extern struct cfdriver pciccd; +extern struct cfdriver ccecd; +extern struct cfdriver mzcd; +extern struct cfdriver decd; +extern struct cfdriver expcd; +extern struct cfdriver nsphycd; +extern struct cfdriver ics90pcd; +extern struct cfdriver i555pcd; +extern struct cfdriver tn100acd; + + +/* locators */ +static int loc[395] = { + 0, 0, 0, 0, -1, -1, BUS_EISA, 0, + 0, 0, 0, -1, -1, BUS_PCI, IO_KBD, 0, + 0, 0, -1, -1, BUS_ISA, IO_KBD, 0, 0, + 0, 0xc, -1, BUS_ISA, 0x3e0, 0, 0, 0, + 0xb, -1, BUS_ISA, 0x3e2, 0, 0, 0, 0xa, + -1, BUS_ISA, 0x3e4, 0, 0, 0, 0xa, -1, + BUS_ISA, IO_COM1, 0, 0, 0, -1, -1, BUS_ISA, + IO_COM2, 0, 0, 0, -1, -1, BUS_ISA, 0, + 0, 0, 0, -1, -1, BUS_PCMCIA, 0x378, 0, + 0, 0, 7, -1, BUS_ISA, 0x3bc, 0, 0, + 0, 7, -1, BUS_ISA, IO_FD1, 0, 0, 0, + -1, 2, BUS_ISA, 0x280, 0, 0, 0, -1, + -1, BUS_ISA, 0x2a0, 0, 0, 0, -1, -1, + BUS_ISA, 0x2e0, 0, 0, 0, -1, -1, BUS_ISA, + 0x300, 0, 0, 0, -1, -1, BUS_ISA, 0x310, + 0, 0, 0, -1, -1, BUS_ISA, 0x330, 0, + 0, 0, -1, -1, BUS_ISA, 0x350, 0, 0, + 0, -1, -1, BUS_ISA, 0x250, 0, 0, 0, + -1, -1, BUS_ISA, 0x260, 0, 0, 0, -1, + -1, BUS_ISA, 0x310, 0, 0xd0000, 0x10000, -1, -1, + BUS_ISA, 0, 0, 0, 0, -1, -1, BUS_ANY, + 0x170, 0, 0, 0, -1, 5, BUS_ISA, IO_WD1, + 0, 0, 0, -1, -1, BUS_ISA, IO_WD2, 0, + 0, 0, -1, -1, BUS_ISA, 0x300, 0, 0, + 0, -1, 1, BUS_ISA, IO_NPX, 0, 0, 0, + -1, -1, BUS_ISA, IO_VGA, 0, 0xa0000, 0x10000, -1, + -1, BUS_ISA, 0x23c, 0, 0, 0, 5, -1, + BUS_ISA, 0x334, 0, 0, 0, 9, -1, BUS_ISA, + 0x340, 0, 0, 0, 9, -1, BUS_ISA, 0x334, + 0, 0, 0, -1, -1, BUS_ISA, 0x340, 0, + 0, 0, -1, -1, BUS_ISA, 0x320, 0, 0, + 0, -1, -1, BUS_ISA, 0x360, 0, 0, 0, + -1, -1, BUS_ISA, 0x240, 0, 0, 0, -1, + -1, BUS_ISA, 0x320, 0, 0, 0, -1, 3, + BUS_ISA, 0x340, 0, 0, 0, -1, 3, BUS_ISA, + 0x360, 0, 0, 0, -1, 3, BUS_ISA, 0x300, + 0, 0, 0, -1, 3, BUS_ISA, 0x2c0, 0, + 0xc8000, 0x800, -1, -1, BUS_ISA, 0x300, 0, 0xc8000, + 0x800, -1, -1, BUS_ISA, 0x380, 0, 0, 0, + -1, -1, BUS_ISA, 0x280, 0, 0xd0000, 0x4000, -1, + -1, BUS_ISA, 0x2a0, 0, 0xd0000, 0x4000, -1, -1, + BUS_ISA, 0x2c0, 0, 0xd0000, 0x4000, -1, -1, BUS_ISA, + 0x2e0, 0, 0xd0000, 0x4000, -1, -1, BUS_ISA, 0x300, + 0, 0xd0000, 0x4000, -1, -1, BUS_ISA, 0x320, 0, + 0xd0000, 0x4000, -1, -1, BUS_ISA, 0x340, 0, 0xd0000, + 0x4000, -1, -1, BUS_ISA, 0x360, 0, 0xd0000, 0x4000, + -1, -1, BUS_ISA, 0x380, 0, 0xd0000, 0x4000, -1, + -1, BUS_ISA, 0x3a0, 0, 0xd0000, 0x4000, -1, -1, + BUS_ISA, 0x3e0, 0, 0xd0000, 0x4000, -1, -1, BUS_ISA, + -1, 1, 0, +}; + +/* parent vectors */ +static short pv[48] = { + 17, 19, 18, 25, 39, 40, 41, 42, 45, 43, 46, 44, 47, 48, 49, 50, + 51, 52, 53, 118, 119, 120, -1, 21, 22, 23, 24, -1, 68, 71, 83, 88, + -1, 22, 23, -1, 0, -1, 68, -1, 14, -1, 71, -1, 20, -1, 21, -1, +}; + +#define NORM FSTATE_NOTFOUND +#define STAR FSTATE_STAR + +struct cfdata cfdata[] = { + /* driver unit state loc flags parents ivstubs */ +/* 0: isa0 at root */ + {&isacd, 0, NORM, loc, 0, pv+22, 0}, +/* 1: saturn0 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_PCI */ + {&saturncd, 0, NORM, loc+ 7, 0, pv+36, 0}, +/* 2: pccons0 at isa0 port IO_KBD nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&pcconscd, 0, NORM, loc+ 14, 0, pv+36, 0}, +/* 3: pcaux0 at isa0 port IO_KBD nports 0 iomem 0 iosiz 0 irq 0xc drq -1 bustype BUS_ISA */ + {&pcauxcd, 0, NORM, loc+ 21, 0, pv+36, 0}, +/* 4: pcic0 at isa0 port 0x3e0 nports 0 iomem 0 iosiz 0 irq 0xb drq -1 bustype BUS_ISA */ + {&pciccd, 0, NORM, loc+ 28, 0, pv+36, 0}, +/* 5: pcic1 at isa0 port 0x3e2 nports 0 iomem 0 iosiz 0 irq 0xa drq -1 bustype BUS_ISA */ + {&pciccd, 1, NORM, loc+ 35, 0, pv+36, 0}, +/* 6: pcic1 at isa0 port 0x3e4 nports 0 iomem 0 iosiz 0 irq 0xa drq -1 bustype BUS_ISA */ + {&pciccd, 1, NORM, loc+ 42, 0, pv+36, 0}, +/* 7: com0 at isa0 port IO_COM1 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&comcd, 0, NORM, loc+ 49, 0, pv+36, 0}, +/* 8: com1 at isa0 port IO_COM2 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&comcd, 1, NORM, loc+ 56, 0, pv+36, 0}, +/* 9: com2 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_PCMCIA */ + {&comcd, 2, NORM, loc+ 63, 0, pv+36, 0}, +/* 10: com3 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_PCMCIA */ + {&comcd, 3, NORM, loc+ 63, 0, pv+36, 0}, +/* 11: lp0 at isa0 port 0x378 nports 0 iomem 0 iosiz 0 irq 7 drq -1 bustype BUS_ISA */ + {&lpcd, 0, NORM, loc+ 70, 0x1, pv+36, 0}, +/* 12: lp0 at isa0 port 0x3bc nports 0 iomem 0 iosiz 0 irq 7 drq -1 bustype BUS_ISA */ + {&lpcd, 0, NORM, loc+ 77, 0x1, pv+36, 0}, +/* 13: lp2 at isa0 port 0x3bc nports 0 iomem 0 iosiz 0 irq 7 drq -1 bustype BUS_ISA */ + {&lpcd, 2, NORM, loc+ 77, 0x1, pv+36, 0}, +/* 14: fdc0 at isa0 port IO_FD1 nports 0 iomem 0 iosiz 0 irq -1 drq 2 bustype BUS_ISA */ + {&fdccd, 0, NORM, loc+ 84, 0, pv+36, 0}, +/* 15: fd0 at fdc0 drive 0 */ + {&fdcd, 0, NORM, loc+394, 0, pv+40, 0}, +/* 16: fd1 at fdc0 drive 1 */ + {&fdcd, 1, NORM, loc+393, 0, pv+40, 0}, +/* 17: dpt0 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ANY */ + {&dptcd, 0, NORM, loc+161, 0, pv+36, 0}, +/* 18: dpt* at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ANY */ + {&dptcd, 1, STAR, loc+161, 0, pv+36, 0}, +/* 19: dpt0 at isa0 port 0x170 nports 0 iomem 0 iosiz 0 irq -1 drq 5 bustype BUS_ISA */ + {&dptcd, 0, NORM, loc+168, 0, pv+36, 0}, +/* 20: tg* at dpt0|dpt0|dpt*|wdpi*|ncr0|ncr1|ncr2|aic0|aic0|aic1|aic1|aic2|aic2|bha0|aha0|bha1|aha1|sa0|sa0|eaha0|eaha1|eaha2 target -1 */ + {&tgcd, 0, STAR, loc+392, 0, pv+ 0, 0}, +/* 21: wdc0 at isa0 port IO_WD1 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&wdccd, 0, NORM, loc+175, 0, pv+36, 0}, +/* 22: wdc1 at isa0 port IO_WD2 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&wdccd, 1, NORM, loc+182, 0, pv+36, 0}, +/* 23: wdc1 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_PCMCIA */ + {&wdccd, 1, NORM, loc+ 63, 0, pv+36, 0}, +/* 24: wdc2 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_PCMCIA */ + {&wdccd, 2, NORM, loc+ 63, 0, pv+36, 0}, +/* 25: wdpi* at wdc0|wdc1|wdc1|wdc2 drive -1 */ + {&wdpicd, 0, STAR, loc+392, 0, pv+23, 0}, +/* 26: wd0 at wdc0 drive 0 */ + {&wdcd, 0, NORM, loc+394, 0, pv+46, 0}, +/* 27: wd1 at wdc0 drive 1 */ + {&wdcd, 1, NORM, loc+393, 0, pv+46, 0}, +/* 28: wd2 at wdc1|wdc1 drive 0 */ + {&wdcd, 2, NORM, loc+394, 0, pv+33, 0}, +/* 29: wd3 at wdc1|wdc1 drive 1 */ + {&wdcd, 3, NORM, loc+393, 0, pv+33, 0}, +/* 30: wd4 at wdc2 drive 0 */ + {&wdcd, 4, NORM, loc+394, 0, pv+26, 0}, +/* 31: wd5 at wdc2 drive 1 */ + {&wdcd, 5, NORM, loc+393, 0, pv+26, 0}, +/* 32: wt0 at isa0 port 0x300 nports 0 iomem 0 iosiz 0 irq -1 drq 1 bustype BUS_ISA */ + {&wtcd, 0, NORM, loc+189, 0, pv+36, 0}, +/* 33: npx0 at isa0 port IO_NPX nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&npxcd, 0, NORM, loc+196, 0, pv+36, 0}, +/* 34: vga0 at isa0 port IO_VGA nports 0 iomem 0xa0000 iosiz 0x10000 irq -1 drq -1 bustype BUS_ISA */ + {&vgacd, 0, NORM, loc+203, 0, pv+36, 0}, +/* 35: bms0 at isa0 port 0x23c nports 0 iomem 0 iosiz 0 irq 5 drq -1 bustype BUS_ISA */ + {&bmscd, 0, NORM, loc+210, 0, pv+36, 0}, +/* 36: lms0 at isa0 port 0x23c nports 0 iomem 0 iosiz 0 irq 5 drq -1 bustype BUS_ISA */ + {&lmscd, 0, NORM, loc+210, 0, pv+36, 0}, +/* 37: mcd0 at isa0 port 0x334 nports 0 iomem 0 iosiz 0 irq 9 drq -1 bustype BUS_ISA */ + {&mcdcd, 0, NORM, loc+217, 0, pv+36, 0}, +/* 38: mcd0 at isa0 port 0x340 nports 0 iomem 0 iosiz 0 irq 9 drq -1 bustype BUS_ISA */ + {&mcdcd, 0, NORM, loc+224, 0, pv+36, 0}, +/* 39: ncr0 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_PCI */ + {&ncrcd, 0, NORM, loc+ 7, 0, pv+36, 0}, +/* 40: ncr1 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_PCI */ + {&ncrcd, 1, NORM, loc+ 7, 0, pv+36, 0}, +/* 41: ncr2 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_PCI */ + {&ncrcd, 2, NORM, loc+ 7, 0, pv+36, 0}, +/* 42: aic0 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_PCI */ + {&aiccd, 0, NORM, loc+ 7, 0, pv+36, 0}, +/* 43: aic1 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_PCI */ + {&aiccd, 1, NORM, loc+ 7, 0, pv+36, 0}, +/* 44: aic2 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_PCI */ + {&aiccd, 2, NORM, loc+ 7, 0, pv+36, 0}, +/* 45: aic0 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_EISA */ + {&aiccd, 0, NORM, loc+ 0, 0, pv+36, 0}, +/* 46: aic1 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_EISA */ + {&aiccd, 1, NORM, loc+ 0, 0, pv+36, 0}, +/* 47: aic2 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_EISA */ + {&aiccd, 2, NORM, loc+ 0, 0, pv+36, 0}, +/* 48: bha0 at isa0 port 0x330 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&bhacd, 0, NORM, loc+126, 0, pv+36, 0}, +/* 49: aha0 at isa0 port 0x330 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&ahacd, 0, NORM, loc+126, 0, pv+36, 0}, +/* 50: bha1 at isa0 port 0x334 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&bhacd, 1, NORM, loc+231, 0, pv+36, 0}, +/* 51: aha1 at isa0 port 0x334 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&ahacd, 1, NORM, loc+231, 0, pv+36, 0}, +/* 52: sa0 at isa0 port 0x340 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&sacd, 0, NORM, loc+238, 0, pv+36, 0}, +/* 53: sa0 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_PCMCIA */ + {&sacd, 0, NORM, loc+ 63, 0, pv+36, 0}, +/* 54: sr* at tg* unit -1 */ + {&srcd, 0, STAR, loc+392, 0, pv+44, 0}, +/* 55: sd* at tg* unit -1 */ + {&sdcd, 0, STAR, loc+392, 0, pv+44, 0}, +/* 56: st* at tg* unit -1 */ + {&stcd, 0, STAR, loc+392, 0, pv+44, 0}, +/* 57: sg* at tg* unit -1 */ + {&sgcd, 0, STAR, loc+392, 0, pv+44, 0}, +/* 58: ne0 at isa0 port 0x320 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&necd, 0, NORM, loc+245, 0, pv+36, 0}, +/* 59: ne0 at isa0 port 0x340 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&necd, 0, NORM, loc+238, 0, pv+36, 0}, +/* 60: ne0 at isa0 port 0x360 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&necd, 0, NORM, loc+252, 0, pv+36, 0}, +/* 61: ne0 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_PCMCIA */ + {&necd, 0, NORM, loc+ 63, 0, pv+36, 0}, +/* 62: ep0 at isa0 port 0x240 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&epcd, 0, NORM, loc+259, 0, pv+36, 0}, +/* 63: ep0 at isa0 port 0x320 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&epcd, 0, NORM, loc+245, 0, pv+36, 0}, +/* 64: tn0 at isa0 port 0x320 nports 0 iomem 0 iosiz 0 irq -1 drq 3 bustype BUS_ISA */ + {&tncd, 0, NORM, loc+266, 0, pv+36, 0}, +/* 65: tn0 at isa0 port 0x340 nports 0 iomem 0 iosiz 0 irq -1 drq 3 bustype BUS_ISA */ + {&tncd, 0, NORM, loc+273, 0, pv+36, 0}, +/* 66: tn0 at isa0 port 0x360 nports 0 iomem 0 iosiz 0 irq -1 drq 3 bustype BUS_ISA */ + {&tncd, 0, NORM, loc+280, 0, pv+36, 0}, +/* 67: tn0 at isa0 port 0x300 nports 0 iomem 0 iosiz 0 irq -1 drq 3 bustype BUS_ISA */ + {&tncd, 0, NORM, loc+287, 0, pv+36, 0}, +/* 68: de* at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ANY */ + {&decd, 0, STAR, loc+161, 0, pv+36, 0}, +/* 69: nsphy* at de*|exp*|eb*|tl* phy -1 */ + {&nsphycd, 0, STAR, loc+392, 0, pv+28, 0}, +/* 70: ics90p* at de* phy -1 */ + {&ics90pcd, 0, STAR, loc+392, 0, pv+38, 0}, +/* 71: exp* at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_PCI */ + {&expcd, 0, STAR, loc+ 7, 0, pv+36, 0}, +/* 72: i555p* at exp* phy -1 */ + {&i555pcd, 0, STAR, loc+392, 0, pv+42, 0}, +/* 73: hpp0 at isa0 port 0x2c0 nports 0 iomem 0xc8000 iosiz 0x800 irq -1 drq -1 bustype BUS_ISA */ + {&hppcd, 0, NORM, loc+294, 0, pv+36, 0}, +/* 74: hpp0 at isa0 port 0x300 nports 0 iomem 0xc8000 iosiz 0x800 irq -1 drq -1 bustype BUS_ISA */ + {&hppcd, 0, NORM, loc+301, 0, pv+36, 0}, +/* 75: re0 at isa0 port 0x240 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&recd, 0, NORM, loc+259, 0, pv+36, 0}, +/* 76: re0 at isa0 port 0x260 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&recd, 0, NORM, loc+147, 0, pv+36, 0}, +/* 77: re0 at isa0 port 0x280 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&recd, 0, NORM, loc+ 91, 0, pv+36, 0}, +/* 78: re0 at isa0 port 0x2a0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&recd, 0, NORM, loc+ 98, 0, pv+36, 0}, +/* 79: re0 at isa0 port 0x300 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&recd, 0, NORM, loc+112, 0, pv+36, 0}, +/* 80: re0 at isa0 port 0x320 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&recd, 0, NORM, loc+245, 0, pv+36, 0}, +/* 81: re0 at isa0 port 0x340 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&recd, 0, NORM, loc+238, 0, pv+36, 0}, +/* 82: re0 at isa0 port 0x380 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&recd, 0, NORM, loc+308, 0, pv+36, 0}, +/* 83: eb* at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_PCI */ + {&ebcd, 0, STAR, loc+ 7, 0, pv+36, 0}, +/* 84: ef0 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_PCI */ + {&efcd, 0, NORM, loc+ 7, 0, pv+36, 0}, +/* 85: ef1 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_PCI */ + {&efcd, 1, NORM, loc+ 7, 0, pv+36, 0}, +/* 86: ef* at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_PCI */ + {&efcd, 3, STAR, loc+ 7, 0, pv+36, 0}, +/* 87: ne* at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_PCI */ + {&necd, 1, STAR, loc+ 7, 0, pv+36, 0}, +/* 88: tl* at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_PCI */ + {&tlcd, 0, STAR, loc+ 7, 0, pv+36, 0}, +/* 89: tn100a* at tl* phy -1 */ + {&tn100acd, 0, STAR, loc+392, 0, pv+31, 0}, +/* 90: we0 at isa0 port 0x280 nports 0 iomem 0xd0000 iosiz 0x4000 irq -1 drq -1 bustype BUS_ISA */ + {&wecd, 0, NORM, loc+315, 0, pv+36, 0}, +/* 91: we0 at isa0 port 0x2a0 nports 0 iomem 0xd0000 iosiz 0x4000 irq -1 drq -1 bustype BUS_ISA */ + {&wecd, 0, NORM, loc+322, 0, pv+36, 0}, +/* 92: we0 at isa0 port 0x2c0 nports 0 iomem 0xd0000 iosiz 0x4000 irq -1 drq -1 bustype BUS_ISA */ + {&wecd, 0, NORM, loc+329, 0, pv+36, 0}, +/* 93: we0 at isa0 port 0x2e0 nports 0 iomem 0xd0000 iosiz 0x4000 irq -1 drq -1 bustype BUS_ISA */ + {&wecd, 0, NORM, loc+336, 0, pv+36, 0}, +/* 94: we0 at isa0 port 0x300 nports 0 iomem 0xd0000 iosiz 0x4000 irq -1 drq -1 bustype BUS_ISA */ + {&wecd, 0, NORM, loc+343, 0, pv+36, 0}, +/* 95: we0 at isa0 port 0x320 nports 0 iomem 0xd0000 iosiz 0x4000 irq -1 drq -1 bustype BUS_ISA */ + {&wecd, 0, NORM, loc+350, 0, pv+36, 0}, +/* 96: we0 at isa0 port 0x340 nports 0 iomem 0xd0000 iosiz 0x4000 irq -1 drq -1 bustype BUS_ISA */ + {&wecd, 0, NORM, loc+357, 0, pv+36, 0}, +/* 97: we0 at isa0 port 0x360 nports 0 iomem 0xd0000 iosiz 0x4000 irq -1 drq -1 bustype BUS_ISA */ + {&wecd, 0, NORM, loc+364, 0, pv+36, 0}, +/* 98: we0 at isa0 port 0x380 nports 0 iomem 0xd0000 iosiz 0x4000 irq -1 drq -1 bustype BUS_ISA */ + {&wecd, 0, NORM, loc+371, 0, pv+36, 0}, +/* 99: we0 at isa0 port 0x3a0 nports 0 iomem 0xd0000 iosiz 0x4000 irq -1 drq -1 bustype BUS_ISA */ + {&wecd, 0, NORM, loc+378, 0, pv+36, 0}, +/*100: we0 at isa0 port 0x3e0 nports 0 iomem 0xd0000 iosiz 0x4000 irq -1 drq -1 bustype BUS_ISA */ + {&wecd, 0, NORM, loc+385, 0, pv+36, 0}, +/*101: we0 at isa0 port 0x280 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&wecd, 0, NORM, loc+ 91, 0, pv+36, 0}, +/*102: we0 at isa0 port 0x2a0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&wecd, 0, NORM, loc+ 98, 0, pv+36, 0}, +/*103: we0 at isa0 port 0x2e0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&wecd, 0, NORM, loc+105, 0, pv+36, 0}, +/*104: we0 at isa0 port 0x300 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&wecd, 0, NORM, loc+112, 0, pv+36, 0}, +/*105: we0 at isa0 port 0x310 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&wecd, 0, NORM, loc+119, 0, pv+36, 0}, +/*106: we0 at isa0 port 0x330 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&wecd, 0, NORM, loc+126, 0, pv+36, 0}, +/*107: we0 at isa0 port 0x350 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&wecd, 0, NORM, loc+133, 0, pv+36, 0}, +/*108: ef0 at isa0 port 0x250 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&efcd, 0, NORM, loc+140, 0, pv+36, 0}, +/*109: ef1 at isa0 port 0x260 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&efcd, 1, NORM, loc+147, 0, pv+36, 0}, +/*110: ef0 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_EISA */ + {&efcd, 0, NORM, loc+ 0, 0, pv+36, 0}, +/*111: ef1 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_EISA */ + {&efcd, 1, NORM, loc+ 0, 0, pv+36, 0}, +/*112: ef2 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_EISA */ + {&efcd, 2, NORM, loc+ 0, 0, pv+36, 0}, +/*113: ef0 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_PCMCIA */ + {&efcd, 0, NORM, loc+ 63, 0, pv+36, 0}, +/*114: el0 at isa0 port 0x310 nports 0 iomem 0xd0000 iosiz 0x10000 irq -1 drq -1 bustype BUS_ISA */ + {&elcd, 0, NORM, loc+154, 0, pv+36, 0}, +/*115: ex0 at isa0 port 0x260 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_ISA */ + {&excd, 0, NORM, loc+147, 0, pv+36, 0}, +/*116: cce0 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_PCMCIA */ + {&ccecd, 0, NORM, loc+ 63, 0, pv+36, 0}, +/*117: mz0 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_PCMCIA */ + {&mzcd, 0, NORM, loc+ 63, 0, pv+36, 0}, +/*118: eaha0 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_EISA */ + {&eahacd, 0, NORM, loc+ 0, 0, pv+36, 0}, +/*119: eaha1 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_EISA */ + {&eahacd, 1, NORM, loc+ 0, 0, pv+36, 0}, +/*120: eaha2 at isa0 port 0 nports 0 iomem 0 iosiz 0 irq -1 drq -1 bustype BUS_EISA */ + {&eahacd, 2, NORM, loc+ 0, 0, pv+36, 0}, + {0} +}; + +short cfroots[] = { + 0 /* isa0 */, + -1 +}; + +/* pseudo-devices */ +extern void loopattach __P((int)); +extern void ptyattach __P((int)); +extern void slattach __P((int)); +extern void apppattach __P((int)); +extern void pifattach __P((int)); +extern void bpfilterattach __P((int)); +extern void rdattach __P((int)); +extern void tunattach __P((int)); +extern void apmattach __P((int)); +extern void ssattach __P((int)); +extern void csattach __P((int)); +extern void vndattach __P((int)); + +struct pdevinit pdevinit[] = { + { loopattach, 1 }, + { ptyattach, 1 }, + { slattach, 1 }, + { apppattach, 2 }, + { pifattach, 1 }, + { bpfilterattach, 10 }, + { rdattach, 1 }, + { tunattach, 2 }, + { apmattach, 1 }, + { ssattach, 4 }, + { csattach, 1 }, + { vndattach, 2 }, + { 0, 0 } +}; +#line 28 "../../i386/conf/ioconf.c.i386" + + +extern struct devsw cnsw, cttysw, mmsw, swapsw, logsw, devfdsw; +extern struct devsw ptssw, ptcsw; +extern struct devsw pcsw, kbdsw; +#if defined(IPFILTER) +extern struct devsw iplsw; +#endif + +extern struct devsw tgsw; +extern struct devsw sdsw; +extern struct devsw srsw; +extern struct devsw stsw; +extern struct devsw sgsw; +extern struct devsw apppsw; +extern struct devsw pifsw; +extern struct devsw bpfiltersw; +extern struct devsw loopsw; +extern struct devsw tunsw; +extern struct devsw ptysw; +extern struct devsw slsw; +extern struct devsw vndsw; +extern struct devsw rdsw; +extern struct devsw isasw; +extern struct devsw pcconssw; +extern struct devsw pcauxsw; +extern struct devsw comsw; +extern struct devsw lpsw; +extern struct devsw fdcsw; +extern struct devsw fdsw; +extern struct devsw dptsw; +extern struct devsw wdcsw; +extern struct devsw wdsw; +extern struct devsw wdpisw; +extern struct devsw mcdsw; +extern struct devsw wtsw; +extern struct devsw npxsw; +extern struct devsw vgasw; +extern struct devsw bmssw; +extern struct devsw lmssw; +extern struct devsw ahasw; +extern struct devsw bhasw; +extern struct devsw nesw; +extern struct devsw epsw; +extern struct devsw sasw; +extern struct devsw ncrsw; +extern struct devsw saturnsw; +extern struct devsw aicsw; +extern struct devsw tnsw; +extern struct devsw hppsw; +extern struct devsw resw; +extern struct devsw wesw; +extern struct devsw tlsw; +extern struct devsw ebsw; +extern struct devsw efsw; +extern struct devsw elsw; +extern struct devsw exsw; +extern struct devsw eahasw; +extern struct devsw apmsw; +extern struct devsw sssw; +extern struct devsw cssw; +extern struct devsw pcicsw; +extern struct devsw ccesw; +extern struct devsw mzsw; +extern struct devsw desw; +extern struct devsw expsw; +extern struct devsw nsphysw; +extern struct devsw ics90psw; +extern struct devsw i555psw; +extern struct devsw tn100asw; +#line 37 "../../i386/conf/ioconf.c.i386" + + +struct devsw *devsw[] = { + &cnsw, /* 0 = virtual console */ + &cttysw, /* 1 = controlling terminal */ + &mmsw, /* 2 = /dev/{null,mem,kmem,...} */ + &wdsw, /* 3 = st506/rll/esdi/ide disk */ + &swapsw, /* 4 = /dev/drum (swap pseudo-device) */ + &ptssw, /* 5 = pseudo-tty slave */ + &ptcsw, /* 6 = pseudo-tty master */ + &logsw, /* 7 = /dev/klog */ + &comsw, /* 8 = serial communications ports */ + &fdsw, /* 9 = floppy disk */ + &wtsw, /* 10 = QIC-02/36 cartridge tape */ + NULL, /* 11 = RISCom/N8 async mux */ + &pcsw, /* 12 = vga console */ + &pcauxsw, /* 13 = console/keyboard aux port */ + &bpfiltersw, /* 14 = berkeley packet filter */ + &devfdsw, /* 15 = file descriptor devices */ + &vgasw, /* 16 = VGA display for X */ + &kbdsw, /* 17 = Keyboard device (excl from cn) */ + &sdsw, /* 18 = SCSI disk pseudo-device (sd) */ + &stsw, /* 19 = SCSI tape pseudo-device */ + &lpsw, /* 20 = printer on a parallel port */ + &bmssw, /* 21 = Microsoft Bus Mouse */ + NULL, /* 22 = Midi device (RETIRED) */ + &mcdsw, /* 23 = Mitsumi CD-ROM */ + NULL, /* 24 = Maxpeed Async Mux */ + &lmssw, /* 25 = Logitec Bus Mouse */ + NULL, /* 26 = DigiBoard PC/X[ei] */ + NULL, /* 27 = Specialix multiplexor */ + NULL, /* 28 = SoundBlaster Pro (RETIRED) */ + NULL, /* 29 = Chase IOPRO control driver */ + NULL, /* 30 = Chase IOPRO data driver */ + NULL, /* 31 = Equinox tty */ + NULL, /* 32 = Concatenated disk pseudo-device */ + NULL, /* 33 = Voxware sound system */ + &srsw, /* 34 = SCSI removeable disks (clone of sd) */ + NULL, /* 35 = Comtrol Rocketport */ + NULL, /* 36 = Cyclades async mux */ + NULL, /* 37 = Disk splicing driver */ + &dptsw, /* 38 = DPT config driver */ + &sgsw, /* 39 = SCSI generic driver, catch all */ + NULL, /* 40 = Stallion async mux */ + NULL, /* 41 = Stallion intelligent async mux */ + &vndsw, /* 42 = vnode disk driver */ + NULL, /* 43 = Connectix QuickCam */ + &rdsw, /* 44 = ram disk driver */ + &tunsw, /* 45 = Tunnel Network Interface */ +#if defined(IPFILTER) + &iplsw, /* 46 = IP Filter */ +#else + NULL, /* 46 = (unused) */ +#endif + NULL, /* 47 = (unused) */ + NULL, /* 48 = (unused) */ + NULL, /* 49 = (unused) */ + &apmsw, /* 50 = APM Interface module */ + &cssw, /* 51 = PCMCIA CS Interface module */ + NULL, /* 52 = Focus Video Capture */ + NULL, /* 53 = PCMCIA SRAM Drive */ +}; +#define NDEVSW (sizeof(devsw) / sizeof(*devsw)) +int ndevsw = NDEVSW; + +#ifdef COMPAT_DEV +/* cross-correlation to devsw[] above, from old bdevsw index */ +/* (i.e., devsw[blktodev[i]] is the driver for old block device i) */ +int blktodev[7] = { + 3, /* 0 = wd = 3 */ + 4, /* 1 = swap = 4 */ + 9, /* 2 = floppy = 9 */ + 10, /* 3 = wt = 10 */ + 18, /* 4 = sd = 18 */ + 19, /* 5 = st = 19 */ + 23, /* 6 = mcd = 23 */ +}; +#endif + +/* + * Swapdev is a fake device implemented + * in vm_swap.c used only internally to get to swstrategy. + * It cannot be provided to the users, because the + * swstrategy routine munches the b_dev and b_blkno entries + * before calling the appropriate driver. This would horribly + * confuse, e.g. the hashing routines. Instead, /dev/drum is + * provided as a character (raw) device. + */ +dev_t swapdev = makedev(4, 0); + +/* + * Routine that identifies /dev/mem and /dev/kmem. + * + * A minimal stub routine can always return 0. + */ +iskmemdev(dev) + dev_t dev; +{ + + return (major(dev) == 2 && (minor(dev) == 0 || minor(dev) == 1)); +} + +iszerodev(dev) + dev_t dev; +{ + return (major(dev) == 2 && minor(dev) == 12); +} + +#ifdef COMPAT_DEV +#include <sys/vnode.h> + +int +devcompat(dev, type) + dev_t dev; + int type; +{ + int maj, min, unit = 0; + + if (dev > USHRT_MAX) + return (dev); + maj = dev >> 8; + min = dev & 0xff; + if (type == VBLK && maj < sizeof(blktodev) / sizeof(blktodev[0])) + maj = blktodev[maj]; + switch (maj) { + case 3: /* 0 = wd = 3 */ + case 9: /* 2 = floppy = 9 */ + case 18: /* 4 = sd = 18 */ + case 23: /* 6 = mcd = 23 */ + unit = min >> 3; /* drive */ + min &= 0x7; /* partition */ + break; + + case 10: /* 3 = wt = 10 */ + case 19: /* 5 = st = 19 */ + unit = min & 3; /* unit */ + min >>= 2; /* rewind, density */ + break; + } + return (dv_makedev(maj, unit, min)); +} +#endif diff --git a/BSDOS3/files.diffs b/BSDOS3/files.diffs new file mode 100644 index 0000000000000..bf2f73454e20f --- /dev/null +++ b/BSDOS3/files.diffs @@ -0,0 +1,23 @@ +*** /sys/conf/files.orig Sat Nov 1 05:14:50 1997 +--- /sys/conf/files Sat Nov 1 05:13:12 1997 +*************** +*** 230,235 **** +--- 230,247 ---- + file netinet/tcp_timer.c inet + file netinet/tcp_usrreq.c inet + file netinet/udp_usrreq.c inet ++ file netinet/ip_fil.c ipfilter always-source ++ file netinet/fil.c ipfilter always-source ++ file netinet/ip_nat.c ipfilter always-source ++ file netinet/ip_frag.c ipfilter always-source ++ file netinet/ip_state.c ipfilter always-source ++ file netinet/ip_auth.c ipfilter always-source ++ file netinet/ip_proxy.c ipfilter always-source ++ file netinet/ip_log.c ipfilter always-source ++ file netinet/ip_scan.c ipfilter always-source ++ file netinet/ip_sync.c ipfilter always-source ++ file netinet/ip_pool.c ipfilter_pool always-source ++ file netinet/ip_rules.c ipfilter_compiled always-source + file netiso/clnp_debug.c iso + file netiso/clnp_er.c iso + file netiso/clnp_frag.c iso diff --git a/BSDOS3/in_proto.c.diffs b/BSDOS3/in_proto.c.diffs new file mode 100644 index 0000000000000..406b5f90c459d --- /dev/null +++ b/BSDOS3/in_proto.c.diffs @@ -0,0 +1,16 @@ +*** sys/netinet/in_proto.c-ORIG Wed Apr 24 22:49:02 1996 +--- sys/netinet/in_proto.c Wed Apr 24 22:50:30 1996 +*************** +*** 83,88 **** +--- 83,93 ---- + #include <netinet/ip_mroute.h> + #endif /* MROUTING */ + ++ #ifdef IPFILTER ++ void iplinit(); ++ #define ip_init iplinit ++ #endif ++ + extern struct domain inetdomain; + + struc protosw inetsw[] = { diff --git a/BSDOS3/ioconf.c.i386.diffs b/BSDOS3/ioconf.c.i386.diffs new file mode 100644 index 0000000000000..b8570960dd30e --- /dev/null +++ b/BSDOS3/ioconf.c.i386.diffs @@ -0,0 +1,28 @@ +*** ioconf.c.i386.orig Mon Nov 3 15:50:55 1997 +--- ioconf.c.i386 Mon Nov 3 16:14:36 1997 +*************** +*** 30,35 **** +--- 30,38 ---- + extern struct devsw cnsw, cttysw, mmsw, swapsw, logsw, devfdsw; + extern struct devsw ptssw, ptcsw; + extern struct devsw pcsw, kbdsw; ++ #if defined(IPFILTER) ++ extern struct devsw iplsw; ++ #endif + + %DECLSW + +*************** +*** 80,86 **** +--- 83,93 ---- + %DEVSW(qcam), /* 43 = Connectix QuickCam */ + %DEVSW(rd), /* 44 = ram disk driver */ + %DEVSW(tun), /* 45 = Tunnel Network Interface */ ++ #if defined(IPFILTER) ++ &iplsw, /* 46 = IP Filter */ ++ #else + NULL, /* 46 = (unused) */ ++ #endif + NULL, /* 47 = (unused) */ + NULL, /* 48 = (unused) */ + NULL, /* 49 = (unused) */ diff --git a/BSDOS3/ip_input.c.diffs b/BSDOS3/ip_input.c.diffs new file mode 100644 index 0000000000000..2829f4edaa448 --- /dev/null +++ b/BSDOS3/ip_input.c.diffs @@ -0,0 +1,37 @@ +*** ip_input.c.orig Tue Mar 19 16:19:06 1996 +--- ip_input.c Fri Mar 8 18:31:22 1996 +*************** +*** 77,82 **** +--- 77,86 ---- + int ipqmaxlen = IFQ_MAXLEN; + struct in_ifaddr *in_ifaddr; /* first inet address */ + struct ifqueue ipintrq; ++ #if defined(IPFILTER) ++ extern int fr_check __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif + + /* + * We need to save the IP options in case a protocol wants to respond +*************** +*** 232,237 **** +--- 236,254 ---- + m_adj(m, ip->ip_len - m->m_pkthdr.len); + } + ++ #if defined(IPFILTER) ++ /* ++ * Check if we want to allow this packet to be processed. ++ * Consider it to be bad if not. ++ */ ++ if (fr_checkp) { ++ struct mbuf *m1 = m; ++ ++ if ((*fr_checkp)(ip, hlen, m->m_pkthdr.rcvif, 0, &m1) || !m1) ++ goto next; ++ ip = mtod(m = m1, struct ip *); ++ } ++ #endif + /* + * Process options and, if not destined for us, + * ship it on. ip_dooptions returns 1 when an diff --git a/BSDOS3/ip_output.c.diffs b/BSDOS3/ip_output.c.diffs new file mode 100644 index 0000000000000..d19b865216e50 --- /dev/null +++ b/BSDOS3/ip_output.c.diffs @@ -0,0 +1,33 @@ +*** ip_output.c.orig Sat Nov 1 04:53:02 1997 +--- ip_output.c Sat Nov 1 04:56:47 1997 +*************** +*** 60,65 **** +--- 60,69 ---- + static struct mbuf *ip_insertoptions __P((struct mbuf *, struct mbuf *, int *)); + static void ip_mloopback + __P((struct ifnet *, struct mbuf *, struct sockaddr_in *)); ++ #if defined(IPFILTER) ++ extern int fr_check __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif + + /* + * IP output. The packet in mbuf chain m contains a skeletal IP +*************** +*** 313,318 **** +--- 317,331 ---- + } else + mtu = ifp->if_mtu; + ++ #if defined(IPFILTER) ++ if (fr_checkp) { ++ struct mbuf *m1 = m; ++ ++ if ((error = (*fr_checkp)(ip, hlen, ifp, 1, &m1)) || !m1) ++ goto done; ++ ip = mtod(m = m1, struct ip *); ++ } ++ #endif + /* + * If small enough for route, can just send directly. + */ diff --git a/BSDOS3/kinstall b/BSDOS3/kinstall new file mode 100644 index 0000000000000..7e0c56611798a --- /dev/null +++ b/BSDOS3/kinstall @@ -0,0 +1,77 @@ +#!/bin/csh -f +# +set major=46 +set minor=0 +set dir=`pwd` +set karch=`uname -m` +if ( -d /sys/arch/$karch ) set archdir="/sys/arch/$karch" +if ( -d /sys/$karch ) set archdir="/sys/$karch" +set confdir="$archdir/conf" + +if ( $dir =~ */BSDOS3 ) cd .. +foreach i (ip_fil.[ch] ip_nat.[ch] ip_frag.[ch] ip_state.[ch] fil.c \ + ip_compat.h ip_log.c ip_proxy.[ch] ip_{ftp,rcmd}_pxy.c ip_auth.[ch]) + echo -n "$i "; + cp $i /sys/netinet + chmod 664 /sys/netinet/$i +end +echo "" +echo "Patching $archdir/$karch/ioconf.c.$karch" +cat ioconf.c.$karch.diffs | (cd $archdir/$karch; patch) +if ( -f /sys/netinet/ip_input.c ) then + echo "Patching ip_input.c, ip_output.c, in_proto.c" + cat BSDOS3/ip_{in,out}put.c.diffs BSDOS3/in_proto.c.diffs | \ + (cd /sys/netinet; patch) +else + echo "Patching in_proto.c" + cat BSDOS3/in_proto.c.diffs | (cd /sys/netinet; patch) + echo "Installing new object files ip_input.o, ip_output.o" + foreach i (ip_input.o ip_output.o) + if ( ! -f /sys/$arch/OBJ/$i.preipf ) then + mv /sys/$arch/OBJ/$i /sys/$arch/OBJ/$i.preipf + endif + cp OBJS/$i /sys/$arch/OBJ/$i + chmod 644 /sys/$arch/OBJ/$i + switch ($i) + case *.h: + /bin/cp $i /usr/include/netinet/$i + chmod 644 /usr/include/netinet/$i + breaksw + endsw + end +endif + +echo "Patching /sys/conf/files, /sys/i386/conf/ioconf.c.i386" +cat BSDOS3/files.diffs | (cd /sys/conf; patch) +cat BSDOS3/ioconf.c.i386.diffs | (cd /sys/i386/conf; patch) + +echo "Creating device files..." +foreach i (/dev/ipl /dev/ipnat /dev/ipstate /dev/ipauth /dev/ipsync /dev/ipscan) + if ( -f $i ) then + /bin/rm -f $i + endif + echo "$i - character device major $major, minor $minor" + mknod $i c $major $minor + set minor=`expr $minor + 1` +end + +set config=`/bin/ls -1t $confdir/[0-9A-Z_]* | head -1` + +echo -n "Kernel configuration to update [$config] " +set newconfig=$< +if ( "$newconfig" != "" ) then + set config="$confdir/$newconfig" +else + set newconfig=$config +endif +echo "Re-config'ing $newconfig..." +if ( -f $confdir/$newconfig ) then + mv $confdir/$newconfig $confdir/$newconfig.bak +endif +if ( -d $archdir/$newconfig ) then + mv $archdir/$newconfig $archdir/$newconfig.bak +endif +awk '{print $0;if($2=="INET"){print"options IPFILTER"}}' \ + $confdir/$newconfig.bak > $confdir/$newconfig +echo 'You will now need to run "config" and build a new kernel.' +exit 0 diff --git a/BSDOS3/unkinstall b/BSDOS3/unkinstall new file mode 100644 index 0000000000000..752e8c53bfdff --- /dev/null +++ b/BSDOS3/unkinstall @@ -0,0 +1,55 @@ +#!/bin/csh -f +# +set dir=`pwd` +set karch=`uname -m` +if ( -d /sys/arch/$karch ) set archdir="/sys/arch/$karch" +if ( -d /sys/$karch ) set archdir="/sys/$karch" +set confdir="$archdir/conf" + +if ( $dir =~ */BSDOS3* ) cd .. +echo -n "Uninstalling " +foreach i (ip_fil.[ch] ip_nat.[ch] ip_frag.[ch] ip_state.[ch] fil.c \ + ip_auth.[ch] ip_proxy.[ch] ip_ftp_pxy.c ip_compat.h ip_log.c \ + mlf_ipl.c ipl.h) + echo -n "$i "; + /bin/rm -f /sys/netinet/$i +end +echo "" +if ( -f /sys/netinet/ip_input.c ) then + echo "Unpatching ip_input.c, ip_output.c and in_proto.c" + cat BSDOS3/ip_{in,out}put.c.diffs BSDOS3/in_proto.c.diffs | \ + (cd /sys/netinet; patch -R) +else + echo "Unpatching in_proto.c" + cat BSDOS3/in_proto.c.diffs | (cd /sys/netinet; patch -R) + foreach i (ip_input.o ip_output.o) + /bin/mv -f $archdir/OBJ/$i.preipf $archdir/OBJ/$i.preipf + end +endif + +echo "Unpatching /sys/conf/files" +cat BSDOS3/files.diffs | (cd /sys/conf; patch -R) + +set config=`(cd $confdir; /bin/ls -1t [0-9A-Z_]*) | head -1` +echo -n "Kernel configuration to update [$config] " +set newconfig=$< +if ( "$newconfig" != "" ) then + set config="$confdir/$newconfig" +else + set newconfig=$config +endif +if ( -f $confdir/$newconfig ) then + mv $confdir/$newconfig $confdir/$newconfig.bak +endif +if ( -d $archdir/../compile/$newconfig ) then + set bak=".bak" + set dot=0 + while ( -d $archdir/../compile/${newconfig}.${bak} ) + set bak=".bak.$dot" + set dot=`expr 1 + $dot` + end + mv $archdir/../compile/$newconfig $archdir/../compile/${newconfig}.${bak} +endif +egrep -v IPFILTER $confdir/$newconfig.bak > $confdir/$newconfig +echo 'You will now need to run "config" and build a new kernel.' +exit 0 diff --git a/BSDOS4/files.diffs b/BSDOS4/files.diffs new file mode 100644 index 0000000000000..b0306dcc1720c --- /dev/null +++ b/BSDOS4/files.diffs @@ -0,0 +1,23 @@ +*** /sys/conf/files.orig Fri Aug 28 11:24:52 1998 +--- /sys/conf/files Fri Aug 28 11:26:31 1998 +*************** +*** 254,259 **** +--- 254,261 ---- + file netinet/tcp_timer.c inet + file netinet/tcp_usrreq.c inet + file netinet/udp_usrreq.c inet ++ file netinet/ip_fil.c ipfilter always-source ++ file netinet/fil.c ipfilter always-source ++ file netinet/ip_nat.c ipfilter always-source ++ file netinet/ip_frag.c ipfilter always-source ++ file netinet/ip_state.c ipfilter always-source ++ file netinet/ip_auth.c ipfilter always-source ++ file netinet/ip_proxy.c ipfilter always-source ++ file netinet/ip_log.c ipfilter always-source ++ file netinet/ip_scan.c ipfilter always-source ++ file netinet/ip_sync.c ipfilter always-source ++ file netinet/ip_pool.c ipfilter_pool always-source ++ file netinet/ip_rules.c ipfilter_compiled always-source + + # Additions for IPv6 and IPsec extension files. + # See the NRL Copyright notice for conditions on this modification. diff --git a/BSDOS4/in_proto.c.diffs b/BSDOS4/in_proto.c.diffs new file mode 100644 index 0000000000000..d954400df49e0 --- /dev/null +++ b/BSDOS4/in_proto.c.diffs @@ -0,0 +1,16 @@ +*** /sys/netinet/in_proto.c.orig Fri Aug 28 11:28:56 1998 +--- /sys/netinet/in_proto.c Fri Aug 28 11:30:16 1998 +*************** +*** 131,136 **** +--- 131,141 ---- + #endif /* IPSEC_ESP */ + #endif /* IPSEC */ + ++ #ifdef IPFILTER ++ void iplinit(); ++ #define ip_init iplinit ++ #endif ++ + extern struct domain inetdomain; + + struct protosw inetsw[] = { diff --git a/BSDOS4/ioconf.c.i386.diffs b/BSDOS4/ioconf.c.i386.diffs new file mode 100644 index 0000000000000..0279d4f1437f2 --- /dev/null +++ b/BSDOS4/ioconf.c.i386.diffs @@ -0,0 +1,28 @@ +*** /sys/i386/conf/ioconf.c.i386.orig Fri Aug 28 11:31:07 1998 +--- /sys/i386/conf/ioconf.c.i386 Fri Aug 28 11:32:27 1998 +*************** +*** 30,35 **** +--- 30,38 ---- + extern struct devsw cnsw, cttysw, mmsw, swapsw, logsw, devfdsw; + extern struct devsw ptssw, ptcsw; + extern struct devsw pcsw, kbdsw; ++ #if defined(IPFILTER) ++ extern struct devsw iplsw; ++ #endif + + %DECLSW + +*************** +*** 81,87 **** +--- 84,94 ---- + %DEVSW(rd), /* 44 = ram disk driver */ + %DEVSW(tun), /* 45 = Tunnel Network Interface */ + %DEVSW(cr), /* 46 = SMART 2 Driver */ ++ #if defined(IPFILTER) ++ &iplsw, /* 47 = IP Filter */ ++ #else + NULL, /* 47 = (unused) */ ++ #endif + NULL, /* 48 = (unused) */ + NULL, /* 49 = (unused) */ + %DEVSW(apm), /* 50 = APM Interface module */ diff --git a/BSDOS4/ip_input.c.diffs b/BSDOS4/ip_input.c.diffs new file mode 100644 index 0000000000000..4f292d7de1091 --- /dev/null +++ b/BSDOS4/ip_input.c.diffs @@ -0,0 +1,38 @@ +*** /sys/netinet/ip_input.c.orig Fri Aug 28 11:33:27 1998 +--- /sys/netinet/ip_input.c Fri Aug 28 13:49:37 1998 +*************** +*** 107,112 **** +--- 107,116 ---- + int ipqmaxlen; + struct in_ifaddr *in_ifaddr; /* first inet address */ + struct ifqueue ipintrq; ++ #if defined(IPFILTER) ++ extern int fr_check __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif + + /* + * We need to save the IP options in case a protocol wants to respond +*************** +*** 406,411 **** +--- 410,429 ---- + } else + m_adj(m, ip->ip_len - m->m_pkthdr.len); + } ++ ++ #if defined(IPFILTER) ++ /* ++ * Check if we want to allow this packet to be processed. ++ * Consider it to be bad if not. ++ */ ++ if (fr_checkp) { ++ struct mbuf *m1 = m; ++ ++ if ((*fr_checkp)(ip, hlen, m->m_pkthdr.rcvif, 0, &m1) || !m1) ++ goto next; ++ ip = mtod(m = m1, struct ip *); ++ } ++ #endif + + /* + * Process options and, if not destined for us, diff --git a/BSDOS4/ip_output.c.diffs b/BSDOS4/ip_output.c.diffs new file mode 100644 index 0000000000000..9aeeef7ef1b88 --- /dev/null +++ b/BSDOS4/ip_output.c.diffs @@ -0,0 +1,35 @@ +*** /sys/netinet/ip_output.c.orig Fri Aug 28 13:49:46 1998 +--- /sys/netinet/ip_output.c Fri Aug 28 13:53:05 1998 +*************** +*** 99,104 **** +--- 99,109 ---- + static struct mbuf *ip_insertoptions __P((struct mbuf *, struct mbuf *, int *)); + static void ip_mloopback + __P((struct ifnet *, struct mbuf *, struct sockaddr_in *)); ++ #if defined(IPFILTER) ++ extern int fr_check __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif ++ + + /* + * IP output. The packet in mbuf chain m contains a skeletal IP +*************** +*** 447,452 **** +--- 452,467 ---- + + if (mtu > IP_MAXPACKET) + mtu = IP_MAXPACKET; ++ ++ #if defined(IPFILTER) ++ if (fr_checkp) { ++ struct mbuf *m1 = m; ++ ++ if ((error = (*fr_checkp)(ip, hlen, ifp, 1, &m1)) || !m1) ++ goto done; ++ ip = mtod(m = m1, struct ip *); ++ } ++ #endif + + #ifdef IPFW + if (ipfw_output.filter && diff --git a/BSDOS4/kinstall b/BSDOS4/kinstall new file mode 100644 index 0000000000000..bccb3fbd9976c --- /dev/null +++ b/BSDOS4/kinstall @@ -0,0 +1,80 @@ +#!/bin/csh -f +# +set major=47 +set minor=0 +set dir=`pwd` +set karch=`uname -m` +if ( -d /sys/arch/$karch ) set archdir="/sys/arch/$karch" +if ( -d /sys/$karch ) set archdir="/sys/$karch" +set confdir="$archdir/conf" + +if ( $dir =~ */BSDOS4 ) cd .. +foreach i (ip_{auth,fil,frag,nat,proxy,scan,state,sync}.[ch] fil.c ipl.h \ + ip_compat.h ip_log.c ip_*_pxy.c ) + echo -n "$i "; + cp $i /sys/netinet + chmod 664 /sys/netinet/$i + switch ($i) + case *.h: + /bin/cp $i /usr/include/netinet/$i + chmod 644 /usr/include/netinet/$i + breaksw + endsw +end +echo "" +if ( -f /sys/netinet/ip_input.c ) then + echo "Patching ip_input.c, ip_output.c, in_proto.c" + cat BSDOS4/ip_{in,out}put.c.diffs BSDOS4/in_proto.c.diffs | \ + (cd /sys/netinet; patch) +else + echo "Patching in_proto.c" + cat BSDOS4/in_proto.c.diffs | (cd /sys/netinet; patch) + echo "Installing new object files ip_input.o, ip_output.o" + foreach i (ip_input.o ip_output.o) + if ( ! -f $archdir/OBJ/$i.preipf ) then + mv $archdir/OBJ/$i $archdir/OBJ/$i.preipf + endif + cp -p BSDOS4/OBJS/$i $archdir/OBJ/$i + chmod 644 $archdir/OBJ/$i + end +endif + +echo "Patching /sys/conf/files, $archdir/conf/ioconf.c.i386" +cat BSDOS4/files.diffs | (cd /sys/conf; patch) +cat BSDOS4/ioconf.c.i386.diffs | (cd $archdir/conf; patch) + +echo "Creating device files..." +foreach i (/dev/ipl /dev/ipnat /dev/ipstate /dev/ipauth /dev/ipsync /dev/ipscan) + if ( -f $i ) then + /bin/rm -f $i + endif + echo "$i - character device major $major, minor $minor" + mknod $i c $major $minor + set minor=`expr $minor + 1` +end + +set confpath=`/bin/ls -1t $confdir/[0-9A-Z_]* | head -1` +set config=`basename $confpath` + +echo -n "Kernel configuration to update [$config] " +set newconfig=$< +if ( "$newconfig" != "" ) then + set config="$confdir/$newconfig" +else + set newconfig=$config +endif +echo "Re-config'ing $newconfig..." +if ( -f $confdir/$newconfig ) then + mv $confdir/$newconfig $confdir/$newconfig.bak +endif +if ( -d $archdir/$newconfig ) then + mv $archdir/$newconfig $archdir/$newconfig.bak +endif +awk '{ print $0; if($2=="INET") \ + { \ + print "options \tIPFILTER\t\t# IP Filtering"; \ + print "# options \tIPFILTER_LOG\t\t# IP Filter logging"; \ + } \ + }' $confdir/$newconfig.bak > $confdir/$newconfig +echo 'You will now need to run "config" and build a new kernel.' +exit 0 diff --git a/BSDOS4/unkinstall b/BSDOS4/unkinstall new file mode 100644 index 0000000000000..9eed477f99135 --- /dev/null +++ b/BSDOS4/unkinstall @@ -0,0 +1,55 @@ +#!/bin/csh -f +# +set dir=`pwd` +set karch=`uname -m` +if ( -d /sys/arch/$karch ) set archdir="/sys/arch/$karch" +if ( -d /sys/$karch ) set archdir="/sys/$karch" +set confdir="$archdir/conf" + +if ( $dir =~ */BSDOS4* ) cd .. +echo -n "Uninstalling " +foreach i (ip_fil.[ch] ip_nat.[ch] ip_frag.[ch] ip_state.[ch] fil.c \ + ip_auth.[ch] ip_proxy.[ch] ip_ftp_pxy.c ip_compat.h ip_log.c \ + mlf_ipl.c ipl.h) + echo -n "$i "; + /bin/rm -f /sys/netinet/$i +end +echo "" +if ( -f /sys/netinet/ip_input.c ) then + echo "Unpatching ip_input.c, ip_output.c and in_proto.c" + cat BSDOS4/ip_{in,out}put.c.diffs BSDOS4/in_proto.c.diffs | \ + (cd /sys/netinet; patch -R) +else + echo "Unpatching in_proto.c" + cat BSDOS4/in_proto.c.diffs | (cd /sys/netinet; patch -R) + foreach i (ip_input.o ip_output.o) + /bin/mv -f $archdir/OBJ/$i.preipf $archdir/OBJ/$i.preipf + end +endif + +echo "Unpatching /sys/conf/files" +cat BSDOS4/files.diffs | (cd /sys/conf; patch -R) + +set config=`(cd $confdir; /bin/ls -1t [0-9A-Z_]*) | head -1` +echo -n "Kernel configuration to update [$config] " +set newconfig=$< +if ( "$newconfig" != "" ) then + set config="$confdir/$newconfig" +else + set newconfig=$config +endif +if ( -f $confdir/$newconfig ) then + mv $confdir/$newconfig $confdir/$newconfig.bak +endif +if ( -d $archdir/../compile/$newconfig ) then + set bak=".bak" + set dot=0 + while ( -d $archdir/../compile/${newconfig}.${bak} ) + set bak=".bak.$dot" + set dot=`expr 1 + $dot` + end + mv $archdir/../compile/$newconfig $archdir/../compile/${newconfig}.${bak} +endif +egrep -v IPFILTER $confdir/$newconfig.bak > $confdir/$newconfig +echo 'You will now need to run "config" and build a new kernel.' +exit 0 diff --git a/FAQ.FreeBSD b/FAQ.FreeBSD index 3b069c9f4b535..6539b4fc61be8 100644 --- a/FAQ.FreeBSD +++ b/FAQ.FreeBSD @@ -1,4 +1,4 @@ -These are Instructions for Configuring A FreeBSD Box For NAT +These are Instructions for Configuring A FreeBSD Box For NAT After you have installed IP-Filter. You will need to change three files: @@ -54,7 +54,7 @@ fpx0 is the interface with the real internet address. /32 is the subnet mask 255.255.255.255, ie only use this ip address. -portmap tcp/udp 10000:65000 +portmap tcp/udp 10000:65000 tells it to use the ports to redirect the tcp/udp calls through @@ -67,7 +67,7 @@ reboots. In your /etc/rc.local put the line: -ipnat -f /etc/natrules +ipnat -f /etc/natrules To check and see if it is loaded, as root type ipnat -ls diff --git a/FWTK/ftp-gw.diff b/FWTK/ftp-gw.diff index be613423c86f1..a47eba05e719b 100644 --- a/FWTK/ftp-gw.diff +++ b/FWTK/ftp-gw.diff @@ -4,7 +4,7 @@ *** 11,31 **** --- 11,41 ---- */ - static char RcsId[] = "$Header: /devel/CVS/IP-Filter/FWTK/ftp-gw.diff,v 2.1 1999/08/04 17:30:30 darrenr Exp $"; + static char RcsId[] = "$Header$"; + /* + * Patches for IP Filter NAT extensions written by Darren Reed, 7/7/96 diff --git a/FWTK/fwtk-2.1-transparency.txt b/FWTK/fwtk-2.1-transparency.txt deleted file mode 100644 index 2e719383f32be..0000000000000 --- a/FWTK/fwtk-2.1-transparency.txt +++ /dev/null @@ -1,707 +0,0 @@ -diff -c -r ./ftp-gw/ftp-gw.c ../../fwtk-2.1-violated/fwtk/ftp-gw/ftp-gw.c -*** ./ftp-gw/ftp-gw.c Thu Feb 5 19:05:43 1998 ---- ../../fwtk-2.1-violated/fwtk/ftp-gw/ftp-gw.c Thu May 21 17:36:09 1998 -*************** -*** 44,49 **** ---- 44,51 ---- - - extern char *optarg; - -+ char *getdsthost(); -+ - #include "firewall.h" - - -*************** -*** 88,93 **** ---- 90,97 ---- - static int cmdcnt = 0; - static int timeout = PROXY_TIMEOUT; - -+ static int do_transparent = 0; -+ - - static int cmd_user(); - static int cmd_authorize(); -*************** -*** 101,106 **** ---- 105,111 ---- - static int cmd_passthru(); - static void saveline(); - static void flushsaved(); -+ static int connectdest(); - - #define OP_CONN 001 /* only valid if connected */ - #define OP_WCON 002 /* writethrough if connected */ -*************** -*** 173,178 **** ---- 178,184 ---- - char xuf[1024]; - char huf[512]; - char *passuser = (char *)0; /* passed user as av */ -+ char *psychic, *hotline; - - #ifndef LOG_DAEMON - openlog("ftp-gw",LOG_PID); -*************** -*** 317,322 **** ---- 323,332 ---- - } else - timeout = PROXY_TIMEOUT; - -+ psychic = getdsthost(0, NULL); -+ if (psychic) -+ do_transparent++; -+ - /* display a welcome file or message */ - if(passuser == (char *)0) { - if((cf = cfg_get("welcome-msg",confp)) != (Cfg *)0) { -*************** -*** 324,329 **** ---- 334,345 ---- - syslog(LLEV,"fwtkcfgerr: welcome-msg must have one parameter, line %d",cf->ln); - exit(1); - } -+ if (do_transparent) { -+ if (sayfile2(0, cf->argv[0], 220)) { -+ syslog(LLEV,"fwtksyserr: cannot display welcome %.512s: %m",cf->argv[0]); -+ exit(1); -+ } -+ } else - if(sayfile(0,cf->argv[0],220)) { - syslog(LLEV,"fwtksyserr: cannot display welcome %.512s: %m",cf->argv[0]); - exit(1); -*************** -*** 336,341 **** ---- 352,360 ---- - if(say(0,"220-Proxy first requires authentication")) - exit(1); - -+ if (do_transparent) -+ sprintf(xuf, "220-%s FTP proxy (Version %s) ready.",huf, FWTK_VERSION_MINOR); -+ else - sprintf(xuf, "220 %s FTP proxy (Version %s) ready.",huf, FWTK_VERSION_MINOR); - if(say(0,xuf)) - exit(1); -*************** -*** 357,362 **** ---- 376,384 ---- - exit(1); - } - -+ if (do_transparent) -+ connectdest(psychic, 21); -+ - /* main loop */ - while(1) { - FD_ZERO(&rdy); -*************** -*** 653,658 **** ---- 675,696 ---- - return(sayn(0,noad,sizeof(noad)-1)); - } - -+ if (do_transparent) { -+ if((rfd == (-1)) && (x = connectdest(dest,port))) -+ return x; -+ -+ sprintf(buf,"USER %s",user); -+ -+ if (say(rfd, buf)) -+ return(1); -+ -+ x = getresp(rfd, buf, sizeof(buf), 1); -+ if (sendsaved(0, x)) -+ return(1); -+ -+ return(say(0, buf)); -+ } -+ - if(*dest == '\0') - dest = "localhost"; - -*************** -*** 694,705 **** - char ebuf[512]; - - strcpy(ebuf,buf); -! sprintf(buf,"521 %s: %s",dest,ebuf); - rfd = -1; - return(say(0,buf)); - } -! sprintf(buf,"----GATEWAY CONNECTED TO %s----",dest); -! saveline(buf); - - /* we are now connected and need to try the autologin thing */ - x = getresp(rfd,buf,sizeof(buf),1); ---- 732,748 ---- - char ebuf[512]; - - strcpy(ebuf,buf); -! if (do_transparent) -! sprintf(buf, "521 %s,%d: %s", dest, ntohs(port), ebuf); -! else -! sprintf(buf,"521 %s: %s",dest,ebuf); - rfd = -1; - return(say(0,buf)); - } -! if (!do_transparent) { -! sprintf(buf,"----GATEWAY CONNECTED TO %s----",dest); -! saveline(buf); -! } - - /* we are now connected and need to try the autologin thing */ - x = getresp(rfd,buf,sizeof(buf),1); -*************** -*** 1889,1891 **** ---- 1932,2050 ---- - dup(nread); - } - #endif -+ -+ static int connectdest(dest, port) -+ char *dest; -+ short port; -+ { -+ char buf[1024], mbuf[512]; -+ int msg_int, x; -+ -+ if(*dest == '\0') -+ dest = "localhost"; -+ -+ if(validests != (char **)0) { -+ char **xp; -+ int x; -+ -+ for(xp = validests; *xp != (char *)0; xp++) { -+ if(**xp == '!' && hostmatch(*xp + 1,dest)) { -+ return(baddest(0,dest)); -+ } else { -+ if(hostmatch(*xp,dest)) -+ break; -+ } -+ } -+ if(*xp == (char *)0) -+ return(baddest(0,dest)); -+ } -+ -+ /* Extended permissions processing goes in here for destination */ -+ if(extendperm) { -+ msg_int = auth_perm(confp, authuser, "ftp-gw", dest,(char *)0); -+ if(msg_int == 1) { -+ sprintf(mbuf,"Permission denied for user %s to connect to %s",authuser,dest); -+ syslog(LLEV,"deny host=%s/%s connect to %s user=%s",rladdr,riaddr,dest,authuser); -+ say(0,mbuf); -+ return(1); -+ } else { -+ if(msg_int == -1) { -+ sprintf(mbuf,"No match in netperm-table for %s to ftp to %s",authuser,dest); -+ say(0,mbuf); -+ return(1); -+ } -+ } -+ } -+ -+ syslog(LLEV,"permit host=%s/%s connect to %s",rladdr,riaddr,dest); -+ -+ if((rfd = conn_server(dest,port,0,buf)) < 0) { -+ char ebuf[512]; -+ -+ strcpy(ebuf,buf); -+ if (do_transparent) -+ sprintf(buf,"521 %s,%d: %s",dest,ntohs(port),ebuf); -+ else -+ sprintf(buf,"521 %s: %s",dest,ebuf); -+ rfd = -1; -+ return(say(0,buf)); -+ } -+ if (!do_transparent) { -+ sprintf(buf,"----GATEWAY CONNECTED TO %s----",dest); -+ saveline(buf); -+ } -+ -+ /* we are now connected and need to try the autologin thing */ -+ x = getresp(rfd,buf,sizeof(buf),1); -+ if(x / 100 != COMPLETE) { -+ sendsaved(0,-1); -+ return(say(0,buf)); -+ } -+ saveline(buf); -+ -+ sendsaved(0,-1); -+ return 0; -+ } -+ -+ /* quick hack */ -+ sayfile2(fd,fn,code) -+ int fd; -+ char *fn; -+ int code; -+ { -+ FILE *f; -+ char buf[BUFSIZ]; -+ char yuf[BUFSIZ]; -+ char *c; -+ int x; -+ int saidsomething = 0; -+ -+ if((f = fopen(fn,"r")) == (FILE *)0) -+ return(1); -+ while(fgets(buf,sizeof(buf),f) != (char *)0) { -+ if((c = index(buf,'\n')) != (char *)0) -+ *c = '\0'; -+ x = fgetc(f); -+ if(feof(f)) -+ sprintf(yuf,"%3.3d-%s",code,buf); -+ else { -+ sprintf(yuf,"%3.3d-%s",code,buf); -+ ungetc(x,f); -+ } -+ if(say(fd,yuf)) { -+ fclose(f); -+ return(1); -+ } -+ saidsomething++; -+ } -+ fclose(f); -+ if (!saidsomething) { -+ syslog(LLEV,"fwtkcfgerr: sayfile for %d is empty",code); -+ sprintf(yuf, "%3.3d The file to display is empty",code); -+ if(say(fd,yuf)) { -+ fclose(f); -+ return(1); -+ } -+ } -+ return(0); -+ } -diff -c -r ./http-gw/http-gw.c ../../fwtk-2.1-violated/fwtk/http-gw/http-gw.c -*** ./http-gw/http-gw.c Fri Feb 6 18:32:25 1998 ---- ../../fwtk-2.1-violated/fwtk/http-gw/http-gw.c Thu May 21 17:00:47 1998 -*************** -*** 27,32 **** ---- 27,35 ---- - static char http_buffer[8192]; - static char reason[8192]; - static int checkBrowserType = 1; -+ static int do_transparent = 0; -+ -+ char * getdsthost(); - - static void do_logging() - { char *proto = "GOPHER"; -*************** -*** 473,478 **** ---- 476,490 ---- - /*(NOT A SPECIAL FORM)*/ - - if((rem_type & TYPE_LOCAL)== 0){ -+ char * psychic = getdsthost(sockfd, &def_port); -+ if (psychic) { -+ if (strlen(psychic) <= MAXHOSTNAMELEN) { -+ do_transparent ++; -+ strncpy(def_httpd, psychic, strlen(psychic)); -+ strncpy(def_server, psychic, strlen(psychic)); -+ } -+ } -+ - /* See if it can be forwarded */ - - if( can_forward(buf)){ -*************** -*** 1564,1570 **** - parse_vec[0], - parse_vec[1], - ourname, ourport); -! }else{ - sprintf(new_reply,"%s\tgopher://%s:%s/%c%s\t%s\t%u", - parse_vec[0], parse_vec[2], - parse_vec[3], chk_type_ch, ---- 1576,1589 ---- - parse_vec[0], - parse_vec[1], - ourname, ourport); -! } -! else -! if (do_transparent) { -! sprintf(new_reply, "%s\t%s\t%s\t%s", -! parse_vec[0], parse_vec[1], -! parse_vec[2],parse_vec[3]); -! } -! else { - sprintf(new_reply,"%s\tgopher://%s:%s/%c%s\t%s\t%u", - parse_vec[0], parse_vec[2], - parse_vec[3], chk_type_ch, -diff -c -r ./lib/hnam.c ../../fwtk-2.1-violated/fwtk/lib/hnam.c -*** ./lib/hnam.c Tue Dec 10 13:08:48 1996 ---- ../../fwtk-2.1-violated/fwtk/lib/hnam.c Thu May 21 17:10:00 1998 -*************** -*** 23,28 **** ---- 23,33 ---- - - #include "firewall.h" - -+ #ifdef __FreeBSD__ /* or OpenBSD, NetBSD, BSDI, etc. Fix this for your system. */ -+ #include <net/if.h> -+ #include "ip_nat.h" -+ #endif /* __FreeBSD__ */ -+ - - char * - maphostname(name) -*************** -*** 49,52 **** ---- 54,132 ---- - } - bcopy(hp->h_addr,&sin.sin_addr,hp->h_length); - return(inet_ntoa(sin.sin_addr)); -+ } -+ -+ char *getdsthost(fd, ptr) -+ int fd; -+ int *ptr; -+ { -+ struct sockaddr_in sin; -+ struct hostent * hp; -+ int sl = sizeof(struct sockaddr_in), err = 0, local_h = 0, i = 0; -+ char buf[255], hostbuf[255]; -+ #ifdef __FreeBSD__ -+ struct sockaddr_in rsin; -+ struct natlookup natlookup; -+ #endif -+ -+ #ifdef linux -+ if (!(err = getsockname(0, &sin, &sl))) { -+ if(ptr) -+ * ptr = ntohs(sin.sin_port); -+ -+ sprintf(buf, "%s", inet_ntoa(sin.sin_addr)); -+ gethostname(hostbuf, 254); -+ hp = gethostbyname(hostbuf); -+ while (hp->h_addr_list[i]) { -+ bzero(&sin, &sl); -+ memcpy(&sin.sin_addr, hp->h_addr_list[i++], -+ sizeof(hp->h_addr_list[i++])); -+ -+ if (!strcmp(buf, inet_ntoa(sin.sin_addr))) -+ local_h++; -+ } -+ -+ if(local_h) -+ return(NULL); -+ else -+ return(buf); -+ } -+ #endif -+ -+ #ifdef __FreeBSD__ -+ /* The basis for this block of code is Darren Reed's -+ * patches to the TIS ftwk's ftp-gw. -+ */ -+ bzero((char*)&sin, sizeof(sin)); -+ bzero((char*)&rsin, sizeof(rsin)); -+ -+ if (getsockname(fd, (struct sockaddr*)&sin, &sl) < 0) -+ return NULL; -+ -+ sl = sizeof(rsin); -+ -+ if(getpeername(fd, (struct sockaddr*)&rsin, &sl) < 0) -+ return NULL; -+ -+ natlookup.nl_inport=sin.sin_port; -+ natlookup.nl_outport=rsin.sin_port; -+ natlookup.nl_inip=sin.sin_addr; -+ natlookup.nl_outip=rsin.sin_addr; -+ -+ if ((natfd = open("/dev/ipl",O_RDONLY)) < 0) -+ return NULL; -+ -+ if (ioctl(natfd, SIOCGNATL,&natlookup) == (-1)) -+ return NULL; -+ -+ close(natfd); -+ -+ if (ptr) -+ *ptr = ntohs(natlookup.nl_inport); -+ -+ sprintf(buf, "%s", inet_ntoa(natlookup.nl_inip)); -+ #endif -+ -+ /* No transparent proxy support */ -+ return(NULL); - } -diff -c -r ./plug-gw/plug-gw.c ../../fwtk-2.1-violated/fwtk/plug-gw/plug-gw.c -*** ./plug-gw/plug-gw.c Thu Feb 5 19:07:35 1998 ---- ../../fwtk-2.1-violated/fwtk/plug-gw/plug-gw.c Thu May 21 17:29:01 1998 -*************** -*** 43,48 **** ---- 43,50 ---- - static char **validdests = (char **)0; - static int net_write(); - -+ static int do_transparent = 0; -+ - main(ac,av) - int ac; - char *av[]; -*************** -*** 198,206 **** ---- 200,220 ---- - char *ptr; - int state = 0; - int ssl_plug = 0; -+ char * getdsthost(); -+ int pport = 0; - - struct timeval timo; - -+ /* Transparent plug-gw is probably a bad idea, but then, plug-gw is a bad -+ * idea .. -+ */ -+ dhost = getdsthost(0, &pport); -+ if (dhost) { -+ do_transparent++; -+ portid = pport; -+ } -+ -+ - if(c->flags & PERM_DENY) { - if (p == -1) - syslog(LLEV,"deny host=%.512s/%.20s port=any",rhost,raddr); -*************** -*** 220,226 **** - syslog(LLEV,"fwtkcfgerr: -plug-to takes an argument, line %d",c->ln); - exit (1); - } -! dhost = av[x]; - continue; - } - ---- 234,241 ---- - syslog(LLEV,"fwtkcfgerr: -plug-to takes an argument, line %d",c->ln); - exit (1); - } -! if (!dhost) -! dhost = av[x]; - continue; - } - -diff -c -r ./rlogin-gw/rlogin-gw.c ../../fwtk-2.1-violated/fwtk/rlogin-gw/rlogin-gw.c -*** ./rlogin-gw/rlogin-gw.c Thu Feb 5 19:08:38 1998 ---- ../../fwtk-2.1-violated/fwtk/rlogin-gw/rlogin-gw.c Thu May 21 17:20:25 1998 -*************** -*** 103,108 **** ---- 103,111 ---- - static int trusted = 0; - static int doX = 0; - static char *prompt; -+ static int do_transparent = 0; -+ -+ char * getdsthost(); - - main(ac,av) - int ac; -*************** -*** 123,128 **** ---- 126,132 ---- - static char *tokav[56]; - int tokac; - struct timeval timo; -+ char * psychic; - - #ifndef LOG_NDELAY - openlog("rlogin-gw",LOG_PID); -*************** -*** 188,194 **** - xforwarder = cf->argv[0]; - } - -! - - if((cf = cfg_get("directory",confp)) != (Cfg *)0) { - if(cf->argc != 1) { ---- 192,203 ---- - xforwarder = cf->argv[0]; - } - -! psychic = getdsthost(0, NULL); -! if (psychic) { -! do_transparent++; -! strncpy(dest, psychic, 511); -! dest[511] = '\0'; -! } - - if((cf = cfg_get("directory",confp)) != (Cfg *)0) { - if(cf->argc != 1) { -*************** -*** 266,271 **** ---- 275,281 ---- - if((p = index(rusername,'@')) != (char *)0) { - char *namp; - -+ dest[0] = '\0'; - *p++ = '\0'; - if(*p == '\0') - p = "localhost"; -*************** -*** 297,302 **** ---- 307,326 ---- - - if(dest[0] != '\0') { - /* Setup connection directly to remote machine */ -+ if ((cf = cfg_get("welcome-msg",confp)) != (Cfg *)0) { -+ if (cf->argc != 1) { -+ syslog(LLEV,"fwtkcfgerr: welcome-msg must have one parameter, line %d",cf->ln); -+ exit(1); -+ } -+ -+ if (sayfile(0, cf->argv[0])) { -+ syslog(LLEV,"fwtksyserr: cannot display welcome %s: %m",cf->argv[0]); -+ exit(1); -+ } -+ } -+ -+ /* Hey fwtk developer people -- this connect_dest thing is *nasty!* */ -+ - sprintf(buf,"connect %.1000s",dest); - tokac = enargv(buf, tokav, 56, tokbuf, sizeof(tokbuf)); - if (cmd_connect(tokac, tokav, buf) != 2) -*************** -*** 535,548 **** - char ebuf[512]; - - syslog(LLEV,"permit host=%.512s/%.20s connect to %.512s",rhost,raddr,namp); -! if(strlen(namp) > 20) -! namp[20] = '\0'; -! if(rusername[0] != '\0') -! sprintf(ebuf,"Trying %s@%s...",rusername,namp); -! else -! sprintf(ebuf,"Trying %s...",namp); -! if(say(0,ebuf)) -! return(1); - } else - syslog(LLEV,"permit host=%.512s/%.20s connect to %.512s",rhost,raddr,av[1]); - if((serfd = conn_server(av[1],RLOGINPORT,1,buf)) < 0) { ---- 559,574 ---- - char ebuf[512]; - - syslog(LLEV,"permit host=%.512s/%.20s connect to %.512s",rhost,raddr,namp); -! if (!do_transparent) { -! if(strlen(namp) > 20) -! namp[20] = '\0'; -! if(rusername[0] != '\0') -! sprintf(ebuf,"Trying %s@%s...",rusername,namp); -! else -! sprintf(ebuf,"Trying %s...",namp); -! if(say(0,ebuf)) -! return(1); -! } - } else - syslog(LLEV,"permit host=%.512s/%.20s connect to %.512s",rhost,raddr,av[1]); - if((serfd = conn_server(av[1],RLOGINPORT,1,buf)) < 0) { -diff -c -r ./tn-gw/tn-gw.c ../../fwtk-2.1-violated/fwtk/tn-gw/tn-gw.c -*** ./tn-gw/tn-gw.c Thu Feb 5 19:11:36 1998 ---- ../../fwtk-2.1-violated/fwtk/tn-gw/tn-gw.c Thu May 21 17:25:06 1998 -*************** -*** 91,96 **** ---- 91,100 ---- - static int cmd_xforward(); - static int cmd_timeout(); - -+ char * getdsthost(); -+ -+ static int do_transparent = 0; -+ - static int tn3270 = 1; /* don't do tn3270 stuff */ - static int doX; - -*************** -*** 144,149 **** ---- 148,155 ---- - char tokbuf[BSIZ]; - char *tokav[56]; - int tokac; -+ int port; -+ char * psychic; - - #ifndef LOG_DAEMON - openlog("tn-gw",LOG_PID); -*************** -*** 325,330 **** ---- 331,362 ---- - } - } - -+ psychic = getdsthost(0, &port); -+ if (psychic) { -+ if ((strlen(psychic) + 10) < 510) { -+ do_transparent++; -+ if (port) -+ sprintf(dest, "%s:%d", psychic, port); -+ else -+ sprintf(dest, "%s", psychic); -+ -+ if (!welcomedone) -+ if ((cf = cfg_get("welcome-msg", confp)) != (Cfg *)0) { -+ if (cf->argc != 1) { -+ syslog(LLEV,"fwtkcfgerr: welcome-msg must have one parameter, line %d",cf->ln); -+ exit(1); -+ } -+ -+ if (sayfile(0, cf->argv[0])) { -+ syslog(LLEV,"fwtksyserr: cannot display welcome %s:%m",cf->argv[0]); -+ exit(1); -+ } -+ -+ welcomedone = 1; -+ } -+ } -+ } -+ - while (argc > 1) { - argc--; - argv++; -*************** -*** 947,955 **** - char ebuf[512]; - - syslog(LLEV,"permit host=%.512s/%.20s destination=%.512s",rladdr,riaddr,namp); -! sprintf(ebuf,"Trying %.100s port %d...",namp,port); -! if(say(0,ebuf)) -! return(1); - } else - syslog(LLEV,"permit host=%.512s/%.20s destination=%.512s",rladdr,riaddr,av[1]); - ---- 979,989 ---- - char ebuf[512]; - - syslog(LLEV,"permit host=%.512s/%.20s destination=%.512s",rladdr,riaddr,namp); -! if (!do_transparent) { -! sprintf(ebuf,"Trying %.100s port %d...",namp,port); -! if(say(0,ebuf)) -! return(1); -! } - } else - syslog(LLEV,"permit host=%.512s/%.20s destination=%.512s",rladdr,riaddr,av[1]); - -*************** -*** 991,998 **** - - syslog(LLEV,"connected host=%.512s/%.20s destination=%.512s",rladdr,riaddr,av[1]); - strncpy(dest,av[1], 511); -! sprintf(buf, "Connected to %.512s.", dest); -! say(0, buf); - return(2); - } - ---- 1025,1034 ---- - - syslog(LLEV,"connected host=%.512s/%.20s destination=%.512s",rladdr,riaddr,av[1]); - strncpy(dest,av[1], 511); -! if (!do_transparent) { -! sprintf(buf, "Connected to %.512s.", dest); -! say(0, buf); -! } - return(2); - } - diff --git a/FWTK/fwtk_transparent.diff b/FWTK/fwtk_transparent.diff index a6c21fa1f1d10..8f0aeb46e123c 100644 --- a/FWTK/fwtk_transparent.diff +++ b/FWTK/fwtk_transparent.diff @@ -124,7 +124,7 @@ diff -cr ../TIS.orig/fwtk/Makefile.config.solaris fwtk/Makefile.config.solaris *************** *** 11,30 **** # - # RcsId: "$Header: /devel/CVS/IP-Filter/FWTK/fwtk_transparent.diff,v 2.2 2001/02/28 09:36:06 darrenr Exp $" + # RcsId: "$Header$" # Your C compiler (eg, "cc" or "gcc") @@ -145,7 +145,7 @@ diff -cr ../TIS.orig/fwtk/Makefile.config.solaris fwtk/Makefile.config.solaris -Dgethostbyaddr=res_gethostbyaddr -Dgetnetbyname=res_getnetbyname \ --- 11,34 ---- # - # RcsId: "$Header: /devel/CVS/IP-Filter/FWTK/fwtk_transparent.diff,v 2.2 2001/02/28 09:36:06 darrenr Exp $" + # RcsId: "$Header$" + # + # Path to sources of ip_filter (ip_nat.h required in lib/hnam.c) diff --git a/FWTK/tproxy.diff b/FWTK/tproxy.diff deleted file mode 100644 index 234404bf23645..0000000000000 --- a/FWTK/tproxy.diff +++ /dev/null @@ -1,82 +0,0 @@ -*** tproxy.c.orig Fri Dec 20 10:53:24 1996 ---- tproxy.c Sun Jan 3 11:33:55 1999 -*************** -*** 135,140 **** ---- 135,144 ---- - #include <netinet/in.h> - #include <sys/signal.h> - #include <syslog.h> -+ #include <unistd.h> -+ #include <fcntl.h> -+ #include <sys/ioctl.h> -+ #include <net/if.h> - #include "tproxy.h" - - #ifdef AIX -*************** -*** 147,152 **** ---- 151,159 ---- - #define bzero(buf,size) memset(buf, '\0', size); - #endif /* SYSV */ - -+ #include "ip_compat.h" -+ #include "ip_fil.h" -+ #include "ip_nat.h" - - - /* socket to audio server */ -*************** -*** 324,329 **** ---- 331,369 ---- - char localbuf[2048]; - void timeout(); - extern int errno; -+ /* -+ * IP-Filter block -+ */ -+ struct sockaddr_in laddr, faddr; -+ struct natlookup natlookup; -+ int slen, natfd; -+ -+ bzero((char *)&laddr, sizeof(laddr)); -+ bzero((char *)&faddr, sizeof(faddr)); -+ slen = sizeof(laddr); -+ if (getsockname(0, (struct sockaddr *)&laddr, &slen) < 0) -+ return -1; -+ slen = sizeof(faddr); -+ if (getpeername(0, (struct sockaddr *)&faddr, &slen) < 0) -+ return -1; -+ natlookup.nl_inport = laddr.sin_port; -+ natlookup.nl_outport = faddr.sin_port; -+ natlookup.nl_inip = laddr.sin_addr; -+ natlookup.nl_outip = faddr.sin_addr; -+ natlookup.nl_flags = IPN_TCP; -+ if ((natfd = open(IPL_NAT, O_RDONLY)) < 0) -+ return -1; -+ if (ioctl(natfd, SIOCGNATL, &natlookup) == -1) { -+ syslog(LOG_ERR, "SIOCGNATL failed: %m\n"); -+ close(natfd); -+ return -1; -+ } -+ close(natfd); -+ strcpy(hostname, inet_ntoa(natlookup.nl_realip)); -+ serverport = ntohs(natlookup.nl_realport); -+ /* -+ * End of IP-Filter block -+ */ - - /* setup a timeout in case dialog doesn't finish */ - signal(SIGALRM, timeout); -*************** -*** 337,344 **** ---- 377,386 ---- - * and modify the call to (and subroutine) serverconnect() as - * appropriate. - */ -+ #if 0 - strcpy(hostname, "randomhostname"); - serverport = 7070; -+ #endif - /* Can we connect to the server */ - if ( (serverfd = serverconnect(hostname, serverport)) < 0 ) { - /* errno may still be set from previous call */ diff --git a/FreeBSD-2.2/kinstall b/FreeBSD-2.2/kinstall index 5a4368eba1222..421681fc00818 100755 --- a/FreeBSD-2.2/kinstall +++ b/FreeBSD-2.2/kinstall @@ -17,8 +17,8 @@ foreach i (ip_{auth,fil,frag,nat,pool,proxy,scan,state,sync}.[ch] fil.c \ case *.h: /bin/cp $i /usr/include/netinet/$i chmod 644 /usr/include/netinet/$i - breaksw - endsw + breaksw + endsw end echo "" echo "Copying /usr/include/osreldate.h to /sys/sys" diff --git a/FreeBSD-3/INST.FreeBSD-3 b/FreeBSD-3/INST.FreeBSD-3 index 5c30b57821f2f..5b9de7ca0afbb 100644 --- a/FreeBSD-3/INST.FreeBSD-3 +++ b/FreeBSD-3/INST.FreeBSD-3 @@ -10,7 +10,7 @@ To build a kernel with the IP filter, follow these seven steps: 4. build a new kernel 5. install the new kernel - + 6. If not using DEVFS, create devices for IP Filter as follows: mknod /dev/ipl c 79 0 mknod /dev/ipnat c 79 1 @@ -18,7 +18,7 @@ To build a kernel with the IP filter, follow these seven steps: mknod /dev/ipauth c 79 3 mknod /dev/ipsync c 79 4 mknod /dev/ipscan c 79 5 - + 7. reboot diff --git a/FreeBSD-3/kinstall b/FreeBSD-3/kinstall index 20f0369d6eaf5..294e795ee4b5e 100755 --- a/FreeBSD-3/kinstall +++ b/FreeBSD-3/kinstall @@ -18,8 +18,8 @@ foreach i (ip_fil.[ch] ip_nat.[ch] ip_frag.[ch] ip_state.[ch] fil.c \ case *.h: /bin/cp $i /usr/include/netinet/$i chmod 644 /usr/include/netinet/$i - breaksw - endsw + breaksw + endsw end echo "" echo "Linking /usr/include/osreldate.h to /sys/sys/osreldate.h" diff --git a/FreeBSD-4.0/INST.FreeBSD-4 b/FreeBSD-4.0/INST.FreeBSD-4 index 7d1b7a2b8f4c4..e69de29bb2d1d 100644 --- a/FreeBSD-4.0/INST.FreeBSD-4 +++ b/FreeBSD-4.0/INST.FreeBSD-4 @@ -1,24 +0,0 @@ -To build a kernel with the IP filter, follow these seven steps: - - 1. do "make freebsd4" - - 2. do "make install-bsd" - (probably has to be done as root) - - 3. run "FreeBSD-4.0/kinstall" as root - - 4. build a new kernel - - 5. install the new kernel - - 6. If not using DEVFS, create devices for IP Filter as follows: - mknod /dev/ipl c 79 0 - mknod /dev/ipnat c 79 1 - mknod /dev/ipstate c 79 2 - mknod /dev/ipauth c 79 3 - - 7. reboot - - -Darren Reed -darrenr@pobox.com diff --git a/FreeBSD-4.0/ipv6-patch b/FreeBSD-4.0/ipv6-patch deleted file mode 100755 index c232b2c159722..0000000000000 --- a/FreeBSD-4.0/ipv6-patch +++ /dev/null @@ -1,61 +0,0 @@ -*** 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/FreeBSD-4.0/kinstall b/FreeBSD-4.0/kinstall index ebd6e2e8a0751..9233199215bfa 100755 --- a/FreeBSD-4.0/kinstall +++ b/FreeBSD-4.0/kinstall @@ -20,8 +20,8 @@ foreach i (ip_{auth,fil,nat,pool,proxy,scan,state,sync}.[ch] fil.c \ case *.h: /bin/cp $i /usr/include/netinet/$i chmod 644 /usr/include/netinet/$i - breaksw - endsw + breaksw + endsw end echo "" echo "Linking /usr/include/osreldate.h to /sys/sys/osreldate.h" diff --git a/FreeBSD/kinstall b/FreeBSD/kinstall index 2b67b9ad995c4..7d08503ed9892 100755 --- a/FreeBSD/kinstall +++ b/FreeBSD/kinstall @@ -17,8 +17,8 @@ foreach i (ip_{auth,fil,frag,nat,pool,proxy,scan,state,sync}.[ch] fil.c \ case *.h: /bin/cp $i /usr/include/netinet/$i chmod 644 /usr/include/netinet/$i - breaksw - endsw + breaksw + endsw end echo "" grep iplopen $archdir/$karch/conf.c >& /dev/null @@ -10,745 +10,268 @@ # and especially those who have found the time to port IP Filter to new # platforms. # -4.1.28 - Release 16 October 2007 - -backout changes (B1) & (B2) as they've caused NAT entries to persist for -too long and possibly other side effects. - -Still need to compile in our own radix.c for Solaris as the one in S10U4 -has a different alignment of structure members (causes panic) - -keep state doesn't work with multicast/broadcast packets (makes UPnP easier) - -ippool -l may only lists every 2nd pool's contents - -4.1.27 - Released 29 September 2007 - -SunOS5/replace script does not deal with i386 systems that have the -i86/amd64 directory pair. - -make BSD/kupgrade try to build ip_rules.[ch] before complaining - -Need to look for ipl.ko LKM on FreeBSD, not just ipf.ko - -Cleanup SunOS5 Makefile pieces, removing CPU, sunos5x86; buildsunos needs -to drive 32bit cc builds differently for sparc/i386 now. - -Update instructions for rebuilding FreeBSD kernels - -Make the target "freebsd" work for building ipfilter - -destroying NAT entries for blocked packets can lead to NAT table entry leak, -provide a counter of orphan'd NAT entries to track this problem. - -4.1.26 - Released 24 September 2007 - -Fix build problem for Solaris prior to S10U4 - -4.1.25 - Released 20 September 2007 - -stepping through structures with ioctls can lead to the wrong things -being free'd and panics - -if a NAT entry (such as an rdr) is created but the packet ends up being -blocked, tear down the NAT entry. - -fix fragment cache preventing keep state from functioning - -fix handling of \ to indicate a continued line in .conf files - -include port ranges in the allowed input for ipf when using "port = ()" - -only advance TCP state for packets on the leading edge of the window. (B1) - -using ipnat -l can lead to memory corruption in high stress situations - -track TCP sequence numbers with NAT so that it can do timeout advances -correctly inline with state - -ICMP checksums for some redirect'd packets are not adjusted correctly. - -IPv6 address components need to be explicitly cast to a 32bit pointer -boundary so that compilers don't try to access them as two 64bit -pieces (no guarantee is made that an Ipv6 address is on a 64bit -aligned address) - -filling up the ipauth packet queue can lead to no more packets being -processed. - -locking used to deref a nat entry causes a significant performance hit - -m_pulldown isn't properly handled, leading to possible panics with ICMPv6 -packets - -IPv6 fragment handling doesn't allow for "keep frag" to work - -build on Solaris10 Update4 with pfhooks in the kernel - -logging of Ipv6 packets with extension headers fix - Miroslaw Luc - -4.1.24 - Released 8 July 2007 - -patch from Stuart Remphrey to address recursive mutex lock with TCP state - -add hash table bucket stats display to ipnat -s - -give ASSERT some teeth for user compiles - -initialising ipf_global, ipf_frcache, ipf_mutex should all be done very -early on - -do some caddr_t cleanup, where possible - -fr_ref no longer tracks the number of children rules in a group for head rules - -make sure all BCOPY* have a value assigned to something - -fix possible use of icmp pointer after pullup makes it invalid - -resolve compile problems related to FreeBSD tree - -4.1.23 - Released 31 May 2007 - -NAT was not always correctly fixing ICMP headers for errors - -some TCP state steps when closing do not update timeouts, leading to -them being removed prematurely. (B2) - -fix compilation problems for netbsd 4.99 - -protect enumeration of lists in the kernel from callout interrupts on -BSD without locking - -fix various problems with IPv6 header checks: TCP/UDP checksum validation -was not being done, fragmentation header parsed dangerously and routing -header prevented others from being seen - -fix gcc 4.2 compiler warnings - -fix TCP/UDP checksum calculation for IPv6 - -fix reference after free'ing ipftoken memory - -4.1.22 - Released 13 May 2007 - -fix endless loop when flushing state/NAT by idle time - -4.1.21 - Released 12 May 2007 - -show the number of states created against a rule with "-v" for ipfstat - -fix build problems with FreeBSD - -make it possible to flush the state table by idle time and TCP state - -fix flushing out idle connections when state/NAT tables fill - -print out the TCP state population with ipfstat/ipnat - -stop creation of state table orphans via return-*/fastroute - -fix printing out of rule groups - they now only appear once - -4.1.20 - Released 30 April 2007 - -adjust TCP state numbers, making 11 closed (was 0) to better facilitate -detecting closing connections that we can wipe out when a SYN arrives -that matches the old - -make it compile on Solaris10 Update3 - -structures used for ipf command ioctls weren't being freed in timeout -fashion on solairs - -use NL_EXPIRE, not ISL_EXPIRE, for expiring NAT sessions - -adjust TCP timeout values and introduce a time-wait specifc timeout -to get a better TCP FSM emulation and one that can hopefully do a better -job of cleaning up in a speedy fashion than previous - -refactor the automatic flushing of TCP state entries when we fill up, -but use the same algorithm as before but now it hopefully works - -only 2 out of 4 interface names were being changed by ipfs when -interface renaming was being used for state entries - -add ipf_proxy_debug to ipf-T - -matching of last fragments that had a number of bytes that wasn't a -multiple of 8 failed - -some combinations of TCP flags are considered bad aren't picked up as such, -but these may be possible with T/TCP - -4.1.19 - Released 22 February 2007 - -Fix up compilation problems with NetBSD and Solaris. - -4.1.18 - Released 18 February 2007 - -fix compiling on Tru64 - -fix listing out filter rules with ipfstat (delete token at end of -the list and detect zero rule being returned.) - -fix extended flushing of NAT tables (was clearing out state tables) - -fix null-pointer deref in hash table lookup - -fix NAT and stateful filtering with to/reply-to on destination interface - -4.1.17 - Released 20 January 2007 - -make flushing pools that are still in use mark them for deletion and -have attempting to recreate them clear the delete flag - -walking through the NAT tables with ioctls caused lock recursion - -fix tracking TCP window scaling in the state code - -4.1.16 - Released 20 December 2006 - -allow rdr rules to only differ on the new port number - -when creating state entry orphans, leave them on the linked list but not -attached to the hash table and mark them visible as orphans in "ipfstat -sl" - -log state removed when unloading differently to allow visible cues - -return ipf ticks via SIOCGETGS for /dev/ipnat so "ipnat -l" can display ttl - -abort logging a packet if the mbuf pointer is null when ipflog is called - -Some NetBSD's have a selinfo.h instead of select.h - -SIOCIPFFL was using copyoutptr and should have been using bcopy for /dev/ipauth - -listing accounting rules using ioctl interface wasn't possible - -fix leakage of state entries due to packets not matching up with NAT - -improve ICMP error packet matching with state/NAT - -fix problems with parsing and printing "-" as an interface name in ipnat.conf - -4.1.15 - Released 03 November 2006 - -Add in automatic flushing of NAT, like state, table if it fills up too much - -Update comments in the code for NAT checksum adjustments - -Fix compiling on FreeBSD 5.4 and 6.0 - -prevent panics from read/write IOs trying to use uninitialised structures - -Newer NetBSD should use malloc() instead of MALLOC() in the kernel where -the size is not staticly defined - -Some gcc warning message cleanup from NetBSD - -Missing include for <sys/filio.h> on Solaris for poll work - -NetBSD now uses opt_ipfilter.h, not opt_ipfilter_log.h - -4.1.14 - Released 04 October 2006 - -rewrite checksum alteration for ICMP packets being NAT'd to use a sane -algorithm that can be understood...now it needs better comments - -fix 1 byte error in checksum validation perl script - -remove unused files in lib directory - -ipftest will say "bad-packet" if it has been freed rather than just "blocked" - -make it possible to load IP address pools from external files in ippool.conf - -update copyright messages in tools directory - -consolidate ioctl hanlding source code into fil.c - -make ipfstat, ippool, ipnat retrieve information via ioctls rather than /dev/kmem - -4.1.13 - Released 4 April 2006 - -fix bug where null pointers introduced by proxies could cause a crash - -pass out the rule flags with SIOCAUTHW - -force loading NAT rules with bad proxy labels to cause an error - -nat_state is used unsafely in calls to fr_addstate - -make return-rst and return-icmp* work with auth rules - -4.1.12 - Released 28 March 2006 - -poll support on FreeBSD/NetBSD needs to use selrecord/selwakeup - -make the fastroute code used by ipftest invoke state/NAT - -move verbose/debug macros out of fil.c and into ip_fil.h (for wider use) - -remove unused code in fr_fastroute - -fix NAT with rules that specify forward and reverise interfaces - -add missing ipfsync_canread() and ipfsync_canwrite() - -behaviour of \ on the end of a line in ipf.conf does not match older behaviour - -remove duplicate statistics line output with "ipfstat -s" - -4.1.11 - Released 19 March 2006 - -Patch for NAT with ipfsync from N. Ersen (SESCI) - www.enderunix.org - -NetBSD coverity report fixes (from run 5) - -Possible to reacquire ipf_auth without releasing it in some circumstances - -Locking in FreeBSD's iplioctl for ipf_global isn't present like it shoudl be - -Add poll support for platforms I can build on: NetBSD, FreeBSD, Solaris, Linux - -Using auth rules to return "keep state" got broken with pushing fr_addstate -call into fr_firewall - -all use of '!' in map/rdr rules to match use in ipf configs - -add -L command line option to ipmon to set the default syslog facility - -looking up a port number is more complex than needed in ipft_tx.c - -allow lib/getport to work when neither tcp or udp are specified in a rule - -remove some dead code from lib/addicmpc, lib/facpri.c, lib/icmpcode.c - -program in some more cases where TCP packets fail an initial in-window -check but should be allowed to match - -filter rule added with NAT/state handling of SIOCSTPUT doesn't properly -initialise all fields, making it possible to panic - -simplify NAT ICMP error handling where it updates checksums - -rename "min" variables to "xmin" on NetBSD to avoid problems with the -macro "min" - -#ifdef's for NetBSD compile incorrect for pfil interface - -support select/poll on NetBSD - -copying out a packet with an auth rule fails (EFAULT) because the wrong -pointer is passed to copyoutptr - -ip_len/ip_off where byte swapped twice instead of once for packets -going to be stored on the auth queue - -change timeout queue manipulation functions to make fewer mutex calls - -fix use of skip rules with groups -fix coding problems discovered by the coverity project for FreeBSD - -update BPF program validation with FreeBSD changes - -4.1.10 - Released 6 December 2005 - -Expand regression testing to cover more features - -Add "coverage" build target for BSD - -Fix building 64bit sparc target for Solaris - -Add IPv6 mobility header to list of accepted keywords for V6 headers - -Resolve locking problems on Solaris when sending RST/icmp packets - -#ifdef's for IPFILTER_BPF need to check if words are defined before -using them in comparisons - -Add checking for SACK permitted option in TCP SYN packets - -Fix loading anonymous pools from inline rule configuration groups - -Add -C command line option to ipftest - -Include extra "const" from NetBSD - -Don't require SIOCKSTLCK for SIOCSTPUT - -Fix some use of "sticky" on NAT rules - -Fix statistical counting of deleting state for TCP connections - -Fix compile problems caused by changes to is_opt/is_optmsk in ip_sync.c - -Fix TCP out-of-window (OOW) problems: -- window scaling turned off if one chose for its scale factor -- Microsoft Windows TCP sends the "next packet" to the right of the window - when using SACK and filling in a hole - -4.1.9 - Released 13 August 2005 - -make ipfilter fix IPv4 header checksums for outgoing packets if BRIDGE_IPF -is defined when compiled. - -move the definition of SIOCPROXY from ip_nat.h to ip_proxy.h - -make the BSD/upgrade script more instructive about the requiements for -ip_rules.[ch] when it is run - -register for interface events on FreeBSD (>5.2.1) and NetBSD so that -"ipf -y" is not not requried to tell ipfilter about interface changes. - -for "quick" rules that do "keep state", move the state adding into the rule -evaluation so that we can detect it failing as rules are evaluated and -continue on to the next rather than wait until we're done and it's too late -to recover for more rule processing. - -mark ICMP packets advertising an MTU that's too small as being bad - -rework ipv6 header parsing to get better code reuse and fix logic errors -in dealing with ipv6 packets containing fragment headers. Also, where a -protocol handler was doing both v4 & v6, make a seperate function for each. - -build for both amd64 and i86pc (32bit) on Solaris10 and later, if possible - -include start of work to get IPFilter working on AIX 5.3 - -Use FI_ICMPERR flag rather than try to compute its equivalent all the time - -Rewrork IPv6 extension header parsing to get better code reuse - -Add missing timeout on Linux - -Fix for locking when reading from ipsync (Frank Volf) - -Fix insertion/appending of rules that use a collection number - -Somehow turning up the spl knob to splnet disappeared on platforms that still -use the spl interface. - -fix problems with "ipf -T" not listing multiple variables properly - -4.1.8 - Released 29 March 2005 - -include path from Phil Dibowitz for sorting ipfstat -t output by source or -destination port. - -fix a bug in printing rules where interface names could not be printed, -even if they're in the rule structure. - -fix BSD/kupgrade to correctly change ipfilter lkm Makefile for FreeBSD - -add 2 new features to SIOCGNATL: -- if IPN_FINDFORWARD is set, check if the respective MAP is already - present in the outbound table -- if IPN_IN is set, search for a matching MAP entry instead of RDR - (Peter Potsma) - -turn off function inlining for freebsd 5.3+ - -UDP doesn't pullup enough data which can sometimes cause a panic. -Fix other protocols, as required, where a similar problem may exist. - -overhaul the timeout queue management, especially that for user defined queues -which are now only freed in an orderly manner. - -4.1.7 - Released 13 March 2005 - -Using the GRE call field is almost impossible because it is unbalanced and -both call fields are not present in each v1 header. - -Fix a problem where it was possible to load duplicate rules into ipf - -patch from John Wehle to address problems with fastroute on solaris - -Copying data out for ipf -z failed because it tried to copy out to an address -that is a kernel pointer in user space. - -add "ip" timeout for both NAT & state that's for non-TCP/UDP/ICMP - -synch up with NetBSD's changes - -fix problems parsing long lines of text in the ftp proxy where they would not -be parsed properly and stop the session from working - -enhance the PPTP proxy so that it tries to decode messages in the TCP stream -so it knows when to create and destroy the state/nat sessions for GRE. There -are also 4 new regression tests for it, testing map/rdr rules. - -impose some limits on the size of data that can be moved with SIOCSTPUT in -the NAT code and also prevent a duplicate session entry from being created -using this method. - -add a new flag (IPN_FINDFORWARD) to NAT code that can be used with SIOCGNATL -to check if it is possible to create an outgoing transparent NAT mapping to -compliment the redirect being investigated. - -Linux requires that the checksums in the IP header get adjusted - -only resolve unknown interfaces in fr_stinsert, and nuke all interface pointers -in SIOCSTPUT to prevent bad data being loaded from userspace. - -make the byte counting for state correct (was counting data from ICMP packet -twice) - -print out the keyword "frag-body" if the flag is set. - -fix ipfs loading/restoring NAT sessions - -patch from Frank to correctly format IP addresses in ipfstat -t output - -parsing port numbers in ipf/ipnat was confusing as the port number was returned -in an int that was also overloaded to be the suceess/failure. instead, change -the port using pass by reference and only use the return value for indicating -success or failure. - -4.1.6 - Released 19 February 2005 - -add a new timeout number to NAT (fr_defnatipage) that is used for all -non-TCP/UDP/ICMP protocols - default 60 seconds. - -buffer leak with bad nat - David Gueluy - -fix memory leak with state entries created by proxies - -eliminate copying too much data into a scan buffer - -allow a trailing protocol name for map rules as well as rdr ones - -fix bug in parsing of <= and > for NAT rules (two were crossed over) - -FreeBSD's iplwrite hasn't kept pace with iplread's prototype - -expand documention on the karma of using "auto" in ipnat map rules - -add matching on IP protocol to ipnat map rules - -allow ippool definitions to contain no addresses to start with - -Linux NAT needs to modify the IP header checksum as it gets called after it -has been computed by IP. - -UDP was missing a pullup for packet header information before examining -the header - -4.1.5 - Released 9 January 2005 - -all rules were being converted into "dup-to" rules in the kernel - -fix two ftp proxy problems: 1st, buffer needs to be bigger for fitting in -complete RETR/CWD commands, 2nd is () use in 227 messages isn't copied -over correctly. - -response to CWDs -revert ip_off back to network byte order in the ICMP error packet that -gets generated. - -4.1.4 - Released 9 January 2005 - -force NAT rules to only match ipv4 NAT rules (which all are, currently, -by default) - -include state synchronisation fixes from Frank Volf - -make the maximum log size for internally buffered log entries accessible -via "ipf -T" - -redesign start of fr_check() to avoid putting duplicate information in -ipfilter about how much data needs to be pulled up for a protocol to be -properly filtered. - -tidy up sending ICMP error messages - some bad inputs could result in -data not being freed and/or no error returned. - -make the maximum size of the log buffer run-time tunable - -fix bug in parsing TCP header when looking for MSS option that could make -the system hang - -change pool lookups that fail to find a match to return "no match" -rather than fail. - -add run-time tunable debugging for proxy support code and FTP proxy. - -fix state table updates for entries where the first packet as an ICMPv6 -multicast message - -fix hang when flushing state for v4/v6 and other (v6/v4) entries are present -too - -attaching filtering to ipv6 pfil hook wasn't present for solaris - -don't allow rules with "keep state" and "with oow" - -move a bunch of userland only code from fil.c to ip_fil.c - -make fr_coalesce() more resiliant to bad input, just returning an error -instead of crashing, making calling it easier in many places - -When m_pulldown doesn't return NULL, it doesn't necessarily return a pointer -to the same mbuf passed in as the first arg. - -remove fr_unreach and use ENETUNREACH by default. - -printing out of tag data in ipf rules doesn't match input syntax - -ipftest(1) man page update - -ipfs command line option parsing still rejects some valid syntaxes - -SIGHUP handling by ipmon was not as safe as it could be - -fix various parsing regressions, including "<thishost>", "tcpudp", ordering -of "keep" options - -patches from Frank Volk: add udp_acktimeout to sysctl list for FreeBSD, -ICMP packet length not calculated correctly in send_icmp_err, reply-to -not printed by ipfstat, keep state with icmp passing (mtrr) - -patches for return-rst and return-icmp from Attila Fueloep -(lichtscheu@gesindel.org) - -4.1.3 - Released 18 July 2004 - -do some more fine tuning on NAT checksum adjustments - -correct IP address byte order in proxy setup for ipsec/pptp - -man page updates - -fix numerous problems with ipfs operation - -complete new syntax for ipmon.conf in its parser and update the sample file - -assign error value consistantly in fastroute code - -rewrite allocation of mbufs in send_reset/send_icmp_err to better use -mbuf clusters and size calculations - -resolve problem with linux panic'ing because the wrong flag was being -passed to skb_clone/skb_alloc - -enable use of shared/exclusive locks on freebsd5 and above - -do not rely on m_pkthdr.len to be valid all the time for mbufs on modern BSD -and so use mbufchainlen to get the mbuf length instead - -replace lots of COPYIN/COPYOUT with BCOPYIN/BCOPYOUT where the data is -going to be on the stack and not in userland - -packet buffer pointers were not refreshed & used properly in fr_check() - -include extra bits for OpenBSD 3.4 & 3.5. - -fix ipf/ipnat parsing regression problems with v3.4 - -4.1.2 - RELEASED - 27 May 2004 - -add state top for ipv6 - -fix numerous parsing regressions - -change sample proxies to use SIOCGNATL with the new API - -allow macro names to contain underscores (_) - -split the parser into a collection of dictionaries so that keywords do -not interfere with resolving hostnames and portnames - -fix ipfrule LKM loading on freebsd - -support mapping a fixed range of ports to a single port - -fix timeout queue use by proxies with private queues - -handle space-led ftp server replies properly - -fix timeout queue management - -fix fastroute, generation of RST & ICMP packets and operation with to/fastroute - -resolve further linux compatibility problems - -replace the use of COPYIN with BCOPYIN for platforms that provide ioctl -args on the stack - -allow flushing of ipv6 rules independant of ipv4 rules - -correct internal ipv6 checksum calculations - -if a 'keep state' rule fails to create state, block the packet rather -than let it through - -correct all checksums in regression tests and correct NAT code to adjust -checksums correctly. - -fix ipfs -R/-W - -4.1.1 - RELEASED - 24 March 2004 - -allow new connections with the same port numbers as an existing one -in the state table if the creating packet is a SYN - -timeout values have drifted, incorrectly, from what they were in 3.4 - -FreeBSD - compatibility changes for 5.2 - -don't match on sequence number (as well) for ICMO ECHO/REPLY, just the -ICMP Id. field as otherwise thre is a state/NAT entry per packet pair -rather than per "flow" - -fr_cksum() returned the wrong answer for ICMP - -Linux: -- get return-rst and return-icmp working -- treat the interface name the same as if_xname on BSD - -adjust expectations for TCP urgent bits based on observed traffic in the -wild - -openbsd3.4 has ip_len/ip_off in network byte order when ipfilter is called - -fix flushing of hash pool gorups (ippool -F) as well as displaying them -(ippool -l) - -passing of pointers to interface structures wrong for HP-UX/Solaris with -return-* rules. - -Make the solaris boot script able to run on 2.5.1 - -ippool related files missing from Solaris packages - -The name /dev/ippool should be /dev/iplookup - -add regression testing for parsing long interface names in nat rules, -along with mssclamp and tags. Also add test for mssclamp operation. - -ttl displayed for "ipfstat -t" is wrong because ttl is not computed. - -parse logical interface names (Sun) - -unloading LKMs was only working if they were enabled. - -sync'ing up NAT sessions when NICs change should cause NAT rules to -re-lookup name->pointer mappings - -not all of the ippool ioctl's are IOWR and they should be because they -use the ipfobj_t for passing information in/out of the kernel. leave the -old values defined and handle them, for compatibility. - -pool stats wrong: ippoolstate used where ipoolstat should be, hash table - statistics not reported at all - -fr_running not set correctly for OpenBSD when compiled into the kernel - -Allow SIOCGETFF while disabled - -Fix mssclamp with NAT (pasing and printing of the word, plus wrong bytes -altered. How do you say "untested" ?) +5.1.2 - RELEASED - 22 Jul 2012 + +3546266 macro letters could be more consistent +3546265 not all of the state statistics are displayed +3546261 scripts for updating BSD environment out of date +3546260 compiler warnings about non-integer array subscript +3546259 asserting numdereflists == 0 is not correct +3546258 expression matching does not see IPF_EXP_END +3544317 ipnat/ipfstat are not using ipfexp_t +3545324 proxy checksum calculation is not hardware aware +3545321 FTP sequence number adjustment incorrectly applied +3545320 EPSV is not recognised +3545319 move nat rule creation to ip_proxy.c +3545317 better feedback of checksum requirements for proxies +3545314 ftp proxy levels do not make sense +3545312 EPRT is not supported by ftp proxy +3544318 ipnat.conf parsing ignores LHS address family +3545309 non-ipv6 safe proxies do not fail with ipv6 +3545323 NAT updates the source port twice +3545322 ipv6 nat rules cannot start proxies +3544314 bucket copyout tries to copy too much data +3544313 remove nat encap feature +3546248 compat rule pointer type mismatch +3546247 UDP hardware checksum offload not recognised +3545311 ifp_ifaddr does not find the first set address +3545310 ipmon needs ipl_sec on 64bit boundary +3545326 reference count changes made without lock +3544315 stateful matching does not use ipfexp_t +3543493 tokens are not flushed when disabled +3543487 NAT rules do not always release lookup objects +3543491 function comments in ip_state.c are old +3543404 ipnat.conf parsing uses family/ip version badly +3543403 incorrect line number printed in ipnat parsing errors +3543402 Not all NAT statistics are printed +3542979 NAT session list management is too simple +3542978 ipv4 and ipv6 nat insert have common hash insertion +3542977 ipnat_t refence tracking incomplete +3542975 proxies must use ipnat_t separately +3542980 printing ipv6 expressions is wrong +3542983 ippool cannot handle more than one ipv6 address +3543018 mask array shifted incorrectly. +3542974 reason for dropping packet is lost +3542982 line numbers not recorded/displayed correctly by ipf +3542981 exclamation mark cuases trouble with pools +3541655 test suite checksums incorrect +3541653 display proxy fail status correctly +3540993 IP header offset excluded in pullup calculations +3540994 pullupmsg does not work as required +3540992 pointer to ipv6 frag header not updated on pullup +3541645 netmask management adds /32 for /0 +3541637 ipnat parser does not zero port fields for non-port protocol +3541635 pool names cannot by numbers +3540995 IPv6 fragment tracking does not always work +3540996 printing of nextip for ipv6 nat rules is wrong +3540999 ipnat.conf parsing has trouble with icmpidmap for ipv6 +3540825 whois output parsing error for ipv6 +3540814 ipfd_lock serves no purpose +3540810 lookup objects need tail pointers +3540809 refactor hash table lookups for nat +3540819 radix tree does not work with ipv6 +3540820 mutex emulation should be logged +3540828 ipfstat filtering with -m fails tests +3536480 ippool could be more like the others +3536477 pool printing not uniform +3536483 flushing empty destination lists causes panic +3536481 more use of bzero after KMALLOC required +3536479 ipnat.conf line numbers not stored +3536484 Makefile missing dependency for ippool +3536199 TFTP proxy requires something extra +3536198 ICMP checksum out by one +3536203 ipnat does not return an error +3536201 ipf.conf parsing too address friendly +3536200 printing of bytes/packets not indented +3497941 ipv4 multicast detection incorrect on little endian +3535361 to interfaces printed out of order +3535363 ipf parser is inconsistent +3532306 deleting ipnat rules does not work +3532054 new error required for ipf_rx_create +3532053 icmp6 checksums wrong +3532052 icmpv6 state check with incorrect length +3531871 checksum verification wants too many icmp6 bytes +3531870 ipnat.conf parsing needs to support inet6 +3532048 error in ipf group parsing +3531868 ICMPV6 checksum not validated +3531893 ipftest exits without error for bad input +3531890 whois pool parsing builds bad structures +3531891 icmpv6 text parsing ignorant of icmp types +3531653 rewrite with icmp does not work +3530563 NAT operations fail with EPERM +3530544 first pass at gcc -Wextra cleanup +3530540 lookup create functions do not set error properly +3530539 ipf_main_soft_destroy doesn't need 2nd arg +3530541 reorder structure for better packing +3530543 ipnat purge needs documentation +3530515 BSD upgrade script required +3528029 ipmon bad-mutex panic +3530247 loading address pools light on input validation +3530255 radix tree delete uses wrong lookup +3530254 radix tree allocation support wrong +3530264 ipmon prints qd for some 64bit numbers +3530260 decapsulate rules not printed correctly. +3530266 ipfstat -v/-d flags confused +2939220 why a packet is blocked is not discernable +2939218 output interface not recorded +2941850 use of destination lists with to/dup-to beneficial +3457747 build errors introduced with radix change +3535360 timeout groups leak +3535359 memory leak with tokens +3535358 listing rules in groups requires tracking groups +3535357 rule head removal is problematic +3530259 not all ioctl error checked wth SIOCIPFINTERROR +3530258 error routine that uses fd required +3530253 inadequate function comment blocks +3530249 walking lookup tables leaks memory +3530241 extra lock padding required for freebsd +3529901 ipf returns 0 when rules fail to load +3529491 checksum validation could be better +3529486 tcp checksum wrong for ipv6 +3533779 ipv6 nat rules missing inet6 keyword +3532693 ipnat.conf rejects some ipv6 addresses +3532691 ipv4 should not be forced for icmp +3532689 ipv6 nat rules do not print inet6 +3532688 ipv6 address always printed with "to <if>" +3532687 with v6hdrs not supported like with ipopts +3532686 ipf expressions do not work with ipv6 +3540825 whois output parsing error for ipv6 +3540818 NAT for certain IPv6 ICMP packets should not be allowed +3540815 memory leak with destination lists +3540814 ipfd_lock serves no purpose +3540810 lookup objects need tail pointers +3540809 refactor hash table lookups for nat +3540808 completed tokens do not stop iteration +3530492 address hash table name not used +3528029 ipmon bad-mutex panic +3530256 hook memory leaked +3530271 pools parsing produces badly formed address structures +3488061 cleanup for illumos build +3484434 SIOCIPFINTERROR must work for all devices +3484067 mandoc -Tlint warnings to be fixed +3483343 compile warning in ipfcomp.c +3482893 building without IPFILTER_LOG fails +3482765 building netbsd kernel without inet6 fails +3482116 ipf_check frees packet from ipftest +3481663 does not compile on solaris 11 + +5.1.1 - RELEASED - 9 May 2012 + +3481322 ip_fil_compat.c needs a cleanup +3481211 add user errors to dtrace +3481152 compatibility for 4.1 needs more work +3481153 PRIu64 problems on FreeBSD +3481155 ipnat listing incorrect +3480543 change leads to compat problems +3480538 compiler errors from earlier patch +3480537 ipf_instance_destroy is incomplete +3480536 _fini order leads to panic +3479991 compiler warnings about size mismatches +3479974 copyright dates are wrong (fix) +3479464 add support for leaks testing +3479457 %qu is not the prefered way +3479451 iterators leak memory +3479453 nat rules with pools leak +3479454 memory leak in hostmap table +3479461 load_hash uses memory after free +3479462 printpool leaks memory +3479452 missing FREE_MB_T to freembt leaks +3479450 ipfdetach is called when detached +3479448 group mapping rules memory leak +3479455 memory leak from tuning +3479458 ipf must be running in global zone +3479460 driver replace is wrong +3479459 radix tree tries to free null pointer +3479463 rwlock emulation does not free memory +3479465 parser leaks memory +3475959 hardware checksum not correctly used +3475426 ip pseudo checksum wrong +3473566 radix tree does not delete dups right +3472987 compile is not clean +3472337 not everything is zero'd +3472344 interface setup needs to be after insert +3472340 wildcard counter drops twice +3472338 change fastroute interface +3472335 kernel lock defines not placed correctly +3472324 ICMP INFOREQ/REPLY not handled +3472330 multicast packets tagged by address +3472333 ipf_deliverlocal called incorrectly +3472345 mutex debug could be more granular +3472761 building i19 regression is flawed +3456457 use of bsd tree.h needs to be removed +3460522 code cleanup required for building on freebsd +3459734 trade some cpu for memory +3457747 build errors introduced with radix change +3457804 build errors from removal of pcap-int,h +3440163 rewrite radix tree +3428004 snoop, tcpdump, etherfind readers are unused +3439495 ipf_rand_push never called (fix brackets) +3437732 getnattype does not need to use ipnat_t (fix variable name) +3437696 fr_cksum is a nightmare +3439061 ipf_send_ip doesn't need 3rd arg +3439059 ipid needs to be file local +3437740 complete buildout of fnew +3438575 add dtrace probes to block events +3438347 comment blocks missing softc +3437687 description of ipf_makefrip wrong +3438340 more stats as dtrace probes +3438316 free on nat structure uses fixed size +3437745 nat iterator using the wrong size +3437710 fail checksum verification if packet is short +3437696 fr_cksum is a nightmare +3437732 getnattype does not need to use ipnat_t +3437735 rename ipf_allocmbt to allocmbt +3437697 fr_family to version assignment is wrong +3437746 ap_session_t has unused fields +3437747 move softc structure to .h file (ip_state.c) +3437704 there is no DTRACE_PROBE5 +3437748 wrong interface in qpktinfo_t +3437729 create function to hexdump mb_t +3438273 msgdsize should be easier to read +3437683 object direction not set for 32bit +3433767 calling ip_cksum could be easier +3433764 left over locking +3428015 printing proxy data size is useless +3428013 add M_ADJ to hide adjmsg/m_adj +3428012 interface name is not always returned correctly +3428002 ip_ttl is too low +3427997 ipft readers do not set buffer length +3426558 resistence is futile +3424495 various copy-paste errors +1826936 shall we allow ipf to be as dumb as its admin +3424477 specfuncs needs to go +3424484 missing fr_checkv6sum +3424478 one entry at a time +2998760 auth rules do not mix well with to/dup-to/fastroute +3424195 add ctfmerge to sunos5 makefile +3424132 some dtrace probes to start with +3423812 makefile needs ip_frag.h for some files +3423817 reference count useful in verbose output +3423800 walking lists does not drop reference +3423805 fragmentation stats not reported correclty +3423808 ip addresses reportied incorrectly with ipfstat -f +3423821 track packets and bytes for fragmentation +3423803 attempt to double free rule +3423805 fragmentation stats not reported correctly +3422712 system panic with ipfstat -f +3422619 pullup counter bumped for every packet +3422608 dummy rtentry required to build +3422018 frflush next to ipf_fini_all is redundant +3422012 instance cleanup is not clean +3421845 instance name not set +3005622 ip_fil5.1.0 does not load on Solaris 10 U8 +2976332 stateful filtering is incompatible with ipv4 options +3387509 ipftest needs help construction ip packets with options +2998746 passp can never be null +3064034 mbuf clobbering problem with ipv6 +3105725 ipnat divide by zero panic +2998750 ipf_htent_insert can leak memory +3064034 mbuf clobbering problem with ipv6 +3105725 ipnat divie by zero panic + +5.1 - RELEASED - 9 May 2010 + +* See WhatsNew50.txt 4.1 - RELEASED - 12 February 2004 @@ -1744,7 +1267,7 @@ loop forms in frag cache table - Yury Pshenychny <yura@rd.zgik.zaporizhzhe.ua> should use SPLNET/SPLX around expire routines in NAT/frag/state code. -redeclared malloc in 44arp.c - +redeclared malloc in 44arp.c - 3.1.7 8/2/97 - Released diff --git a/HPUX/INSTALL.TXT b/HPUX/INSTALL.TXT new file mode 100644 index 0000000000000..dada2c981d939 --- /dev/null +++ b/HPUX/INSTALL.TXT @@ -0,0 +1,45 @@ +Installation instructions: +========================= + +1. Update HP-UX Kernel +---------------------- +General instructions on preparation for installing and proceeding with an +installation of IPFilter on HP-UX can be found at: +http://coombs.anu.edu.au/~avalon/ipf-mentat.html + +You are required to at least install the latest jumbo patches from HP, +for HP-UX 11. A summary of those that I used can be found at: +At http://coombs.anu.edu.au/~avalon/ipf-hp11.html + +I do not recommend using anything less than as many of these as will apply +to your own system. + +2. Build and Install pfil +------------------------- +Next, you need to download and install "pfil". This is a STREAMS interface +for packet filtering that removes the need for packet filtering code to be +written as a STREAMS module. This can be downloaded from + +http://coombs.anu.edu.au/~avalon/pfil-2.1.1.tar.gz + +Unpack this and type "make" in the pfil directory. Once compelte, type +"make install" to kick off the installation. + +3. Build and Install IP Filter +------------------------------ +Having got this far, you now need to download the latest IP Filter package +and compile/install that. The source code for IP Filter can be obtained +from: +http://coombs.anu.edu.au/~avalon/ip-filter.html + +Download the latest version that is 4.1 or greater. + +This should be unpacked into the same directory as "pfil" is. The +directory layout will look like this: + +/directory/ip_fil4.* +/directory/pfil + +This complete, do a "make hpux" in the ip_fil4.* directory, followed +by a "make install". You will need to reboot for it to become active. + diff --git a/HPUX/IPF-ALL/checkinstall b/HPUX/IPF-ALL/checkinstall new file mode 100755 index 0000000000000..714cb965344c2 --- /dev/null +++ b/HPUX/IPF-ALL/checkinstall @@ -0,0 +1,29 @@ +#! /sbin/sh +######## +# Product: IP Filter +# Fileset: IPF-ALL +# checkinstall +######## +# +# (c) Copyright (C) 2012 by Darren Reed. +# +######## + +CONTRIBDIR=/usr/contrib/ipf +######## +# Source control script environment +######## + +UTILS="/usr/lbin/sw/control_utils" +if [[ ! -f $UTILS ]] ; then + echo "ERROR: Cannot find $UTILS" + exit 1 +fi +. $UTILS +exitval=$SUCCESS + +######## +# Make sure that the header files exist +######## + +exit $exitval diff --git a/HPUX/IPF-ALL/checkremove b/HPUX/IPF-ALL/checkremove new file mode 100755 index 0000000000000..a954e3a3609f5 --- /dev/null +++ b/HPUX/IPF-ALL/checkremove @@ -0,0 +1,28 @@ +#! /sbin/sh +######## +# Product: IP Filter +# Fileset: IPF-ALL +# checkremove +######## +# +# (c) Copyright (C) 2012 by Darren Reed. +# +######## + +######## +# Source control script environment +######## + +UTILS="/usr/lbin/sw/control_utils" +if [[ ! -f $UTILS ]] ; then + echo "ERROR: Cannot find $UTILS" + exit 1 +fi +. $UTILS +exitval=$SUCCESS + +######## +# +######## + +exit $exitval diff --git a/HPUX/IPF-ALL/description b/HPUX/IPF-ALL/description new file mode 100755 index 0000000000000..2afee1d516bb6 --- /dev/null +++ b/HPUX/IPF-ALL/description @@ -0,0 +1,6 @@ +Vendor Name IP Filter + +Product Name IP Filter +Fileset Name IPF-ALL + +This is the IP Filter package. diff --git a/HPUX/IPF-ALL/postinstall b/HPUX/IPF-ALL/postinstall new file mode 100755 index 0000000000000..7f08ee016e750 --- /dev/null +++ b/HPUX/IPF-ALL/postinstall @@ -0,0 +1,70 @@ +#!/usr/bin/sh +######## +# Product: IP Fitler +# Fileset: IPF-ALL +# postinstall +######## +# +# (c) Copyright (C) 2012 by Darren Reed. +# +######## +PATH=/usr/bin:/usr/sbin:/bin:/sbin +export PATH +######## +# Source control script environment +######## +ETCDIR=/etc/opt/ipf + +UTILS="/usr/lbin/sw/control_utils" +if [[ ! -f $UTILS ]] ; then + echo "ERROR: Cannot find $UTILS" + exit 1 +fi +. $UTILS +exitval=$SUCCESS + +######## +# Restore original header files +# The script checkremove has verified that it exists. +######## + +# exit $GLOBAL_ERROR + +for i in ipf.conf ipnat.conf; do + /bin/touch ${ETCDIR}/$i + /bin/chmod 444 ${ETCDIR}/$i +done +(kmadmin -U ipf) +(kminstall -d ipf) + +cd ${SW_ROOT_DIRECTORY}var/tmp/build + +kminstall -u ipf +if [[ $? -ne 0 ]] ; then + exit 1 +fi +config -M ipf -u +if [[ $? -ne 0 ]] ; then + exit 1 +fi +kmadmin -L ipf +kmadmin -Q ipf +if [[ $? -ne 0 ]] ; then + exit 1 +fi +input=`kmadmin -Q ipf | grep 'Character Major'` +set $input +major=$3 +j=0 +for i in ipl ipnat ipstate ipauth ipsync ipscan; do + /bin/rm -f /dev/$i + mknod /dev/$i c $major $j + j=$((j + 1)) +done +ln -s /sbin/init.d/ipfboot /sbin/rc2.d/S020ipfboot + +. /usr/lbin/sw/control_utils +mod_pathfile -a MP /opt/ipf/man +mod_pathfile -a P /opt/ipf/bin + +exit $exitval diff --git a/HPUX/IPF-ALL/postremove b/HPUX/IPF-ALL/postremove new file mode 100755 index 0000000000000..11e9030e12ce1 --- /dev/null +++ b/HPUX/IPF-ALL/postremove @@ -0,0 +1,31 @@ +#! /sbin/sh +######## +# Product: IP Filter +# Fileset: IPF-ALL +# postremove +######## +# +# (c) Copyright (C) 2012 by Darren Reed. +# +######## + +######## +# Source control script environment +######## + +UTILS="/usr/lbin/sw/control_utils" +if [[ ! -f $UTILS ]] ; then + echo "ERROR: Cannot find $UTILS" + exit 1 +fi +. $UTILS +exitval=$SUCCESS + +######## +# Restore original header files +# The script checkremove has verified that it exists. +######## + +# exit $GLOBAL_ERROR + +exit $exitval diff --git a/HPUX/IPF-ALL/preinstall b/HPUX/IPF-ALL/preinstall new file mode 100755 index 0000000000000..a1cdd069dbcaf --- /dev/null +++ b/HPUX/IPF-ALL/preinstall @@ -0,0 +1,50 @@ +#! /sbin/sh +######## +# Product: IP Filter +# Fileset: IPF-ALL +# preinstall +######## +# +# (c) Copyright (C) 2012 by Darren Reed. +# +######## + +######## +# Source control script environment +######## + +UTILS="/usr/lbin/sw/control_utils" +if [[ ! -f $UTILS ]] ; then + echo "ERROR: Cannot find $UTILS" + exit 1 +fi +. $UTILS +exitval=$SUCCESS + +CONTRIBDIR=/usr/contrib/ipf +ETCDIR=/etc/opt/ipf + +######## +# Create directories so that installation can take place +######## + +if [[ ! -d ${ETCDIR} ]]; then + mkdir -m 755 -p ${ETCDIR} +fi + +for i in ipf.conf ipnat.conf; do + touch ${ETCDIR}/$i + chmod 444 ${ETCDIR}/$i +done + +if [[ ! -d ${CONTRIBDIR} ]]; then + mkdir -m 755 -p ${CONTRIBDIR} +fi + +for i in bin man include examples; do + if [[ ! -d ${CONTRIBDIR}/$i ]]; then + mkdir -m 755 -p ${CONTRIBDIR}/$i + fi +done + +exit $exitval diff --git a/HPUX/IPF-ALL/preremove b/HPUX/IPF-ALL/preremove new file mode 100755 index 0000000000000..65cd7e4d29535 --- /dev/null +++ b/HPUX/IPF-ALL/preremove @@ -0,0 +1,29 @@ +#! /sbin/sh +######## +# Product: IP Filter +# Fileset: IPF-ALL +# preremove +######## +# +# (c) Copyright (C) 2012 by Darren Reed. +# +######## + +######## +# Source control script environment +######## + +UTILS="/usr/lbin/sw/control_utils" +if [[ ! -f $UTILS ]] ; then + echo "ERROR: Cannot find $UTILS" + exit 1 +fi +. $UTILS +exitval=$SUCCESS + +######## +# Kill off inetd first +######## + +kmadmin -U ipf +exit $exitval diff --git a/HPUX/IPF-ALL/verify b/HPUX/IPF-ALL/verify new file mode 100755 index 0000000000000..39248a4fb7bec --- /dev/null +++ b/HPUX/IPF-ALL/verify @@ -0,0 +1,28 @@ +#! /sbin/sh +######## +# Product: IP Filter +# Fileset: IPF-ALL +# verify +######## +# +# (c) Copyright (C) 2012 by Darren Reed. +# +######## + +######## +# Source control script environment +######## + +UTILS="/usr/lbin/sw/control_utils" +if [[ ! -f $UTILS ]] ; then + echo "ERROR: Cannot find $UTILS" + exit 1 +fi +. $UTILS +exitval=$SUCCESS + +######## +# Make sure that the header files exist +######## + +exit $exitval diff --git a/HPUX/Makefile b/HPUX/Makefile new file mode 100644 index 0000000000000..deb3e83e80446 --- /dev/null +++ b/HPUX/Makefile @@ -0,0 +1,464 @@ +# +# Copyright (C) 2012 by Darren Reed. +# +# See the IPFILTER.LICENCE file for details on licencing. +# +SHELL=/bin/sh +DEPOT=IPF.v4.1.depot +DEPOTDIR=/var/spool/sw +DEST=/opt/ipf +SBINDEST=/sbin +MANDIR=${DEST}/man +BINDEST=${DEST}/bin +EXTRADIR=${DEST}/examples +INCDIR=${DEST}/include +ETCDIR=/etc/opt/ipf +RCDIR=/sbin/init.d +#CFLAGS=-I$(TOP) +# +OBJ=. +HERE=HPUX/$(CPUDIR) +DEST=. +TOP=.. +TOOL=$(TOP)/tools +TMP=/tmp +# +HPUXREV=`uname -r | sed -e 's/^[A-Z]\.\([0-9]*\)\.\([0-9]\)/\1\2/'` +#BITS=`getconf KERNEL_BITS` +ABI=+DD${BITS} +KFLAGS=-Ae +ES1.Xindirect_calls -U__hp9000s700 \ + -D__STDC_EXT__ -D_XPG4_EXTENDED -D_HPUX_SOURCE -D__hp9000s800 -D_KERNEL \ + -DKERNEL +Xidu +ESlit -Wp,-H300000 +Hx0 +R500 -Wl,-a,archive +ESsfc -q +ESssf +DEBUG=-g +LIBS=-lnsl -lelf -L. -lipf +DEF=-D_KERNEL +ATON=-DNEED_INET_ATON +HPINC=-I/usr/conf/h +#SPU=-Dspustate_t=u_long +HFLAGS=$(KFLAGS) $(SPU) $(HPINC) +CC=cc $(ABI) -DHPUXREV=$(HPUXREV) -I$(TOP)/../pfil -I/usr/conf -I. +# +MFLAGS="BINDEST=$(BINDEST)" "SBINDEST=$(SBINDEST)" "MANDIR=$(MANDIR)" \ + 'CFLAGS=$(CFLAGS) $(ARCHINC)' "IPFLKM=$(IPFLKM)" \ + "IPFLOG=$(IPFLOG)" "LOGFAC=$(LOGFAC)" "POLICY=$(POLICY)" \ + "DEBUG=$(DEBUG)" "CPUDIR=$(CPUDIR)" "HPUXREV=$(HPUXREV)" \ + "LOOKUP=$(LOOKUP)" "XID=$(XID)" +# +O2=+O2 +#O2=-g +O3=+O3 +#O3=-g +# +########## ########## ########## ########## ########## ########## ########## +# +CP=/bin/cp +RM=/bin/rm +CHMOD=/bin/chmod +INSTALL=$(TOP)/bsdinstall +# +DFLAGS=$(IPFLKM) $(IPFLOG) $(DEF) $(IPFBPF) $(LOOKUP) $(XID) +#-DIPFDEBUG +MODOBJS=ip_fil.o fil.o ip_state.o ip_frag.o \ + ip_nat.o ip_proxy.o ip_auth.o ip_log.o \ + ip_pool.o ip_htable.o ip_lookup.o \ + ip_sync.o ip_scan.o ip_rules.o hpux.o $(BPFILTER) md5.o radix_ipf.o +# ip_trafcon.o +IPF=ipf.o ipfcomp.o ipf_y.o ipf_l.o +IPT=ipftest.o fil_u.o ip_state_u.o ip_frag_u.o \ + ip_nat_u.o ip_fil_u.o ip_proxy_u.o ip_sync_u.o ip_scan_u.o \ + ip_auth_u.o ip_pool_u.o ip_rules_u.o ip_log_u.o \ + ip_htable_u.o ip_lookup_u.o \ + ipf_y.o ipf_l.o ipnat_y.o ipnat_l.o ippool_y.o ippool_l.o \ + md5_u.o radix_ipf_u.o +# ip_trafcon_u.o +IPMON=ipmon.o ipmon_y.o ipmon_l.o +IPPOOL=ippool_y.o ippool_l.o ippool.o +IPNAT=ipnat.o ipnat_y.o ipnat_l.o +IPTRAFCON=iptrafcon.o +FILS=ipfstat.o +LIBSRC=$(TOP)/lib +RANLIB=ranlib +AROPTS=cq +CCARGS=$(DEBUG) $(CFLAGS) -I$(TOP)/../pfil/HP-UX +EXTRA=$(ALLOPTS) +# +include $(TOP)/lib/Makefile + +build: $(DEST)/libipf.a ipf ipfstat ipftest ipmon ipnat ippool \ + ipfs ipscan ipsyncm ipsyncs mod.o + -sh -c 'for i in ipf ipftest ipmon ippool ipnat ipscan ipsyncm ipsyncs; do /bin/rm -f $(TOP)/$$i; ln -s `pwd`/$$i $(TOP); done' + +.y.c: + +.l.c: + +pkg: ipf.pkg + +ipfstat: $(FILS) $(DEST)/libipf.a + $(CC) $(CCARGS) $(FILS) -o $@ $(LIBS) + +ipf: $(IPF) $(DEST)/libipf.a + $(CC) $(CCARGS) $(IPF) -o $@ $(LIBS) $(LLIB) $(LIBBPF) + +ipftest: $(IPT) $(DEST)/libipf.a + $(CC) $(CCARGS) $(IPT) -o $@ $(LIBS) $(LIBBPF) + +ipnat: $(IPNAT) $(DEST)/libipf.a + $(CC) $(CFLAGS) $(IPNAT) -o $@ $(LIBS) $(LLIB) + +ipfs: ipfs.o $(DEST)/libipf.a + $(CC) $(CCARGS) ipfs.o -o $@ $(LIBS) + +ipsyncm: ipsyncm.o $(DEST)/libipf.a + $(CC) $(CCARGS) ipsyncm.o -o $@ $(LIBS) + +ipsyncs: ipsyncs.o $(DEST)/libipf.a + $(CC) $(CCARGS) ipsyncs.o -o $@ $(LIBS) + +ipsyncm.o: $(TOOL)/ipsyncm.c $(TOP)/ip_sync.h + $(CC) $(CCARGS) -c $(TOOL)/ipsyncm.c -o $@ + +ipsyncs.o: $(TOOL)/ipsyncs.c $(TOP)/ip_sync.h + $(CC) $(CCARGS) -c $(TOOL)/ipsyncs.c -o $@ + +ipscan: ipscan_y.o ipscan_l.o $(DEST)/libipf.a + $(CC) $(DEBUG) ipscan_y.o ipscan_l.o -o $@ $(LLIB) $(LIBS) + +ipscan_y.h ipscan_y.c: $(TOOL)/ipscan_y.y $(TOP)/ip_scan.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ipscan_l.c: $(TOOL)/lexer.c $(TOP)/ip_scan.h + (cd $(TOOL); $(MAKE) "DEST=../$(HERE)" ../$(HERE)/$@) + +ipscan_l.h: $(TOOL)/lexer.h + (cd $(TOOL); $(MAKE) "DEST=../$(HERE)" ../$(HERE)/$@) + +ipscan_y.o: ipscan_y.c ipscan_y.h ipscan_l.h $(TOP)/ip_scan.h + $(CC) $(CCARGS) -c ipscan_y.c -o $@ + +ipscan_l.o: ipscan_l.c ipscan_y.h ipscan_l.h $(TOP)/ip_scan.h + $(CC) $(CCARGS) -I. -c ipscan_l.c -o $@ + +tests: + (cd test; $(MAKE) ) + +ipfstat.o: $(TOOL)/ipfstat.c $(TOP)/ip_fil.h $(TOP)/ipf.h + $(CC) $(CCARGS) $(HPINC) -c $(TOOL)/ipfstat.c -o $@ + +ipfs.o: $(TOOL)/ipfs.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_state.h \ + $(TOP)/ip_nat.h + $(CC) $(CCARGS) -c $(TOOL)/ipfs.c -o $@ + +fil_u.o: $(TOP)/fil.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_rules.h + $(CC) $(CCARGS) $(EXTRA) $(FIXRADIX) $(IPFBPF) -c $(TOP)/fil.c -o $@ + +fil.o: $(TOP)/fil.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_compat.h \ + $(TOP)/ipl.h $(TOP)/ip_rules.h + $(CC) -I$(TOP) $(POLICY) $(DFLAGS) $(HFLAGS) $(IPFBPF) \ + $(O2) -c $(TOP)/fil.c -o $@ + +ipf.o: $(TOOL)/ipf.c $(TOP)/ip_fil.h $(TOP)/ipf.h + $(CC) $(CCARGS) -c $(TOOL)/ipf.c -o $@ + +ipfcomp.o: $(TOOL)/ipfcomp.c $(TOP)/ip_fil.h $(TOP)/ipf.h + $(CC) $(CCARGS) -c $(TOOL)/ipfcomp.c -o $@ + +ipf_y.o: ipf_y.c $(TOP)/ip_fil.h $(TOP)/ipf.h ipf_y.h ipf_l.h + $(CC) $(CCARGS) $(IPFBPF) -c ipf_y.c -o $@ + +ipf_l.o: ipf_l.c $(TOP)/ip_fil.h $(TOP)/ipf.h ipf_y.h + $(CC) $(CCARGS) -I. -I$(TOP)/tools -c ipf_l.c -o $@ + +ipf_y.h ipf_y.c: $(TOOL)/ipf_y.y $(TOP)/ipf.h $(TOP)/ip_fil.h + (cd $(TOOL); $(MAKE) "DEST=../$(HERE)" ../$(HERE)/$@) + +ipf_l.c: $(TOOL)/lexer.c $(TOP)/ipf.h $(TOP)/ip_fil.h $(TOOL)/lexer.h + (cd $(TOOL); $(MAKE) "DEST=../$(HERE)" ../$(HERE)/$@) + +ipf_l.h: $(TOOL)/lexer.h + (cd $(TOOL); $(MAKE) "DEST=../$(HERE)" ../$(HERE)/$@) + +ipftest.o: $(TOOL)/ipftest.c $(TOP)/ip_fil.h $(TOP)/ipt.h $(TOP)/ipf.h + $(CC) $(CCARGS) -c $(TOOL)/ipftest.c -o $@ + +ipnat.o: $(TOOL)/ipnat.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_nat.h + $(CC) $(CCARGS) -c $(TOOL)/ipnat.c -o $@ + +ipnat_y.o: ipnat_y.c ipnat_y.h $(TOP)/ip_nat.h ipnat_l.h + $(CC) $(CCARGS) -c ipnat_y.c -o $@ + +ipnat_l.o: ipnat_l.c ipnat_y.h $(TOP)/ip_nat.h + $(CC) $(CCARGS) -I. -c ipnat_l.c -o $@ + +ipnat_y.h ipnat_y.c: $(TOOL)/ipnat_y.y $(TOP)/ip_nat.h + (cd $(TOOL); $(MAKE) "DEST=../$(HERE)" ../$(HERE)/$@) + +ipnat_l.c: $(TOOL)/lexer.c $(TOP)/ip_nat.h + (cd $(TOOL); $(MAKE) "DEST=../$(HERE)" ../$(HERE)/$@) + +ipnat_l.h: $(TOOL)/lexer.h + (cd $(TOOL); $(MAKE) "DEST=../$(HERE)" ../$(HERE)/$@) + +mod.o: $(MODOBJS) + -if [ "$(BITS)" = "64" ] ; then \ + /bin/rm -f libmilli.a; \ + ln -s /usr/lib/pa20_64/milli.a libmilli.a; \ + ld -r $(MODOBJS) -L. -lmilli -o $@; \ + else \ + /bin/rm -f libmilli.a; \ + ln -s /usr/lib/milli.a libmilli.a; \ + ld -r $(MODOBJS) -L. -lmilli -o $@; \ + fi + +ip_rules.c: $(TOP)/rules/ip_rules $(TOP)/tools/ipfcomp.c ipf + ./ipf -cc -nf $(TOP)/rules/ip_rules + +$(TOP)/ip_rules.h: ip_rules.c + if [ ! -f $(TOP)/ip_rules.h ] ; then \ + /bin/mv -f ip_rules.h $(TOP); \ + else \ + touch $(TOP)/ip_rules.h; \ + fi + +ip_rules.o: ip_rules.c $(TOP)/ip_rules.h + $(CC) -I$(TOP) $(DFLAGS) $(HFLAGS) $(O3) -c ip_rules.c -o $@ + +ip_nat.o: $(TOP)/ip_nat.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h + $(CC) -I$(TOP) $(DFLAGS) $(HFLAGS) $(O3) -c $(TOP)/ip_nat.c -o $@ + +ip_state.o: $(TOP)/ip_state.c $(TOP)/ip_state.h $(TOP)/ip_compat.h + $(CC) -I$(TOP) $(DFLAGS) $(HFLAGS) $(O3) -c $(TOP)/ip_state.c -o $@ + +ip_proxy.o: $(TOP)/ip_proxy.c $(TOP)/ip_proxy.h $(TOP)/ip_compat.h \ + $(TOP)/ip_h323_pxy.c $(TOP)/ip_irc_pxy.c $(TOP)/ip_ipsec_pxy.c \ + $(TOP)/ip_ftp_pxy.c $(TOP)/ip_raudio_pxy.c $(TOP)/ip_rpcb_pxy.c \ + $(TOP)/ip_nat.h $(TOP)/ip_fil.h + $(CC) -I$(TOP) $(DFLAGS) $(HFLAGS) $(O2) -c $(TOP)/ip_proxy.c -o $@ + +ip_frag.o: $(TOP)/ip_frag.c $(TOP)/ip_frag.h $(TOP)/ip_compat.h + $(CC) -I$(TOP) $(DFLAGS) $(HFLAGS) $(O3) -c $(TOP)/ip_frag.c -o $@ + +ip_auth.o: $(TOP)/ip_auth.c $(TOP)/ip_auth.h $(TOP)/ip_compat.h + $(CC) -I$(TOP) $(DFLAGS) $(HFLAGS) $(O2) -c $(TOP)/ip_auth.c -o $@ + +ip_scan.o: $(TOP)/ip_scan.c $(TOP)/ip_scan.h $(TOP)/ip_compat.h + $(CC) -I$(TOP) $(DFLAGS) $(HFLAGS) $(O2) -c $(TOP)/ip_scan.c -o $@ + +ip_sync.o: $(TOP)/ip_sync.c $(TOP)/ip_sync.h $(TOP)/ip_compat.h + $(CC) -I$(TOP) $(DFLAGS) $(HFLAGS) $(O2) -c $(TOP)/ip_sync.c -o $@ + +ip_trafcon.o: $(TOP)/ip_trafcon.c $(TOP)/ip_trafcon.h $(TOP)/ip_compat.h + $(CC) -I$(TOP) $(DFLAGS) $(HFLAGS) -c $(TOP)/ip_trafcon.c -o $@ + +radix_ipf.o: $(TOP)/radix_ipf.c $(TOP)/radix_ipf.h + $(CC) -I$(TOP) $(DFLAGS) $(HFLAGS) $(O2) -c $(TOP)/radix_ipf.c -o $@ + +ip_pool.o: $(TOP)/ip_pool.c $(TOP)/ip_pool.h $(TOP)/ip_compat.h radix_ipf.h + $(CC) -I$(TOP) $(DFLAGS) $(HFLAGS) $(FIXRADIX) $(O2) \ + -c $(TOP)/ip_pool.c -o $@ + +ip_htable.o: $(TOP)/ip_htable.c $(TOP)/ip_htable.h $(TOP)/ip_compat.h + $(CC) -I$(TOP) $(DFLAGS) $(HFLAGS) $(O2) -c $(TOP)/ip_htable.c -o $@ + +ip_lookup.o: $(TOP)/ip_lookup.c $(TOP)/ip_lookup.h $(TOP)/ip_compat.h + $(CC) -I$(TOP) $(DFLAGS) $(HFLAGS) $(FIXRADIX) $(O2) \ + -c $(TOP)/ip_lookup.c -o $@ + +ip_nat_u.o: $(TOP)/ip_nat.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_nat.c -o $@ + +ip_frag_u.o: $(TOP)/ip_frag.c $(TOP)/ip_frag.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_frag.c -o $@ + +ip_state_u.o: $(TOP)/ip_state.c $(TOP)/ip_state.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_state.c -o $@ + +ip_auth_u.o: $(TOP)/ip_auth.c $(TOP)/ip_auth.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_auth.c -o $@ + +ip_proxy_u.o: $(TOP)/ip_proxy.c $(TOP)/ip_proxy.h $(TOP)/ip_compat.h \ + $(TOP)/ip_h323_pxy.c $(TOP)/ip_irc_pxy.c $(TOP)/ip_ipsec_pxy.c \ + $(TOP)/ip_ftp_pxy.c $(TOP)/ip_raudio_pxy.c $(TOP)/ip_rpcb_pxy.c \ + $(TOP)/ip_nat.h $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_proxy.c -o $@ + +ip_log_u.o: $(TOP)/ip_log.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_nat.h $(TOP)/ip_frag.h $(TOP)/ip_state.h \ + $(TOP)/ip_auth.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_log.c -o $@ + +ip_fil_u.o: $(TOP)/ip_fil.c $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) $(FIXRADIX) -c $(TOP)/ip_fil.c -o $@ + +ip_scan_u.o: $(TOP)/ip_scan.c $(TOP)/ip_scan.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_scan.c -o $@ + +ip_sync_u.o: $(TOP)/ip_sync.c $(TOP)/ip_sync.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_sync.c -o $@ + +ip_rules_u.o: ip_rules.c $(TOP)/ip_rules.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) -c ip_rules.c -o $@ + +ip_pool_u.o: $(TOP)/ip_pool.c $(TOP)/ip_pool.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_pool.c -o $@ + +ip_htable_u.o: $(TOP)/ip_htable.c $(TOP)/ip_htable.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_htable.c -o $@ + +ip_lookup_u.o: $(TOP)/ip_lookup.c $(TOP)/ip_lookup.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_lookup.c -o $@ + +ip_trafcon_u.o: $(TOP)/ip_trafcon.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_trafcon.h + $(CC) $(CCARGS) -c $(TOP)/ip_trafcon.c -o $@ + +ip_fil.o: $(TOP)/ip_fil_hpux.c $(TOP)/ip_fil.h $(TOP)/ip_compat.h + $(CC) -I$(TOP) $(DFLAGS) $(HFLAGS) $(O2) \ + $(COMPIPF) -c $(TOP)/ip_fil_hpux.c -o $@ + +ip_log.o: $(TOP)/ip_log.c $(TOP)/ip_fil.h $(TOP)/ip_compat.h + $(CC) -I$(TOP) $(DFLAGS) $(HFLAGS) $(O2) -c $(TOP)/ip_log.c -o $@ + +hpux.o: $(TOP)/hpux.c $(TOP)/ipl.h $(TOP)/ip_compat.h + $(CC) -I$(TOP) $(DFLAGS) $(HFLAGS) $(O2) -c $(TOP)/hpux.c -o $@ + +bpf_filter_u.o: $(TOP)/bpf_filter.c $(TOP)/bpf-ipf.h $(TOP)/pcap-ipf.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/bpf_filter.c -o $@ + +bpf_filter.o: $(TOP)/bpf_filter.c + $(CC) -I$(TOP) $(DFLAGS) $(HFLAGS) $(O2) -c $(TOP)/bpf_filter.c -o $@ + +md5_u.o: $(TOP)/md5.c $(TOP)/md5.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/md5.c -o $@ + +md5.o: $(TOP)/md5.c $(TOP)/md5.h + $(CC) -I$(TOP) $(DFLAGS) $(HFLAGS) $(O3) $(SPU) -c $(TOP)/md5.c -o $@ + +radix_ipf_u.o: $(TOP)/radix_ipf.c $(TOP)/radix_ipf.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/radix_ipf.c -o $@ + +ipmon: $(IPMON) $(DEST)/libipf.a + $(CC) $(CCARGS) $(LOGFAC) $(IPMON) -o $@ $(LIBS) $(LLIB) + +$(TOP)/ipmon.c: + +ipmon_y.c ipmon_y.h: $(TOOL)/ipmon_y.y $(TOP)/ipmon.h + (cd $(TOOL); $(MAKE) "DEST=../$(HERE)" ../$(HERE)/$@) + +ipmon_l.c: $(TOOL)/lexer.c $(TOP)/ipmon.h + (cd $(TOOL); $(MAKE) "DEST=../$(HERE)" ../$(HERE)/$@) + +ipmon_l.h: $(TOOL)/lexer.h + (cd $(TOOL); $(MAKE) "DEST=../$(HERE)" ../$(HERE)/$@) + +ipmon.o: $(TOOL)/ipmon.c + $(CC) $(CCARGS) $(LOGFAC) -c $(TOOL)/ipmon.c -o $@ + +ipmon_y.o: ipmon_y.c $(TOP)/ipmon.h ipmon_l.h + $(CC) $(CCARGS) -c ipmon_y.c -o $@ + +ipmon_l.o: ipmon_l.c $(TOP)/ipmon.h + $(CC) $(CCARGS) -I. -c ipmon_l.c -o $@ + +ippool: $(IPPOOL) + $(CC) $(DEBUG) -I. $(CFLAGS) $(IPPOOL) -o $@ $(LIBS) $(LLIB) + +ippool.o: $(TOOL)/ippool.c $(TOP)/ipf.h $(TOP)/ip_pool.h + $(CC) $(CCARGS) -c $(TOOL)/ippool.c -o $@ + +ippool_y.o: ippool_y.c ippool_y.h $(TOP)/ip_pool.h ippool_l.h + $(CC) $(CCARGS) -c ippool_y.c -o $@ + +ippool_l.o: ippool_l.c ippool_y.h $(TOP)/ip_pool.h + $(CC) $(CCARGS) -I. -c ippool_l.c -o $@ + +ippool_y.h ippool_y.c: $(TOOL)/ippool_y.y $(TOP)/ip_pool.h + (cd $(TOOL); $(MAKE) "DEST=../$(HERE)" ../$(HERE)/$@) + +ippool_l.c: $(TOOL)/lexer.c $(TOP)/ip_pool.h + (cd $(TOOL); $(MAKE) "DEST=../$(HERE)" ../$(HERE)/$@) + +ippool_l.h: $(TOOL)/lexer.h + (cd $(TOOL); $(MAKE) "DEST=../$(HERE)" ../$(HERE)/$@) + +iptrafcon.o: $(TOP)/iptrafcon.c + $(CC) $(CCARGS) -c $(TOP)/iptrafcon.c -o $@ + +iptrafcon: $(IPTRAFCON) libipf.a + $(CC) $(CCARGS) $(IPTRAFCON) -o $@ $(LIBS) + +clean: + ${RM} -f ../ipf ../ipnat ../ipmon ../ippool ../ipftest + ${RM} -f ../ipscan ../ipsyncm ../ipsyncs + ${RM} -f core *.o *.a ipt ipfstat ipf ipfstat ipftest ipmon + ${RM} -f if_ipl ipnat $(LKM) libmilli.a ipf.psf + ${RM} -f ip_fil.c ipf_l.c ipf_y.c ipf_y.h ipf_l.h + ${RM} -f ipscan ipscan_y.c ipscan_y.h ipscan_l.c ipscan_l.h + ${RM} -f ippool ippool_y.c ippool_y.h ippool_l.c ippool_l.h + ${RM} -f ipnat_y.c ipnat_y.h ipnat_l.c ipnat_l.h + ${RM} -f ipmon_y.c ipmon_y.h ipmon_l.c ipmon_l.h + ${RM} -f ipsyncm ipsyncs ipfs ip_rules.c ip_rules.h + ${RM} -f ipnat.5 ipnat.4 ipnat.8 ipfilter.4 ipfilter.5 + ${MAKE} -f Makefile.ipsend clean + -(for i in *; do \ + if [ -d $${i} -a -h $${i}/Makefile ] ; then \ + cd $${i}; (make TOP=../.. clean); cd ..; \ + rm $${i}/Makefile $${i}/Makefile.ipsend; \ + rmdir $${i}; \ + fi \ + done) + +ipf.pkg: + sed -e "s/HPREV/`uname -r`/g" ../ipf.psf.dist > ipf.psf + swpackage -x media_type=tape -s ipf.psf @ /tmp/${DEPOT} + mv /tmp/${DEPOT} ipf.pkg + +install: + sed -e "s/HPREV/`uname -r`/g" ../ipf.psf.dist > ipf.psf + swpackage -s ipf.psf @ ${DEPOTDIR}/${DEPOT} + swreg -l depot ${DEPOTDIR}/${DEPOT} + @echo now do: + @echo swinstall -s ${DEPOTDIR}/${DEPOT} -x reinstall=true IPF-RUN + +manualinstall: + mkdir -p -m 755 ${DEST} ${MANDIR} ${BINDEST} ${EXTRADIR} ${INCDIR} + mkdir -p -m 700 ${ETCDIR} + -$(INSTALL) -c -s ipftest $(BINDEST)/ipftest + -$(INSTALL) -c -s ipmon $(BINDEST)/ipmon + -$(INSTALL) -c -s ipsend $(BINDEST)/ipsend + -$(INSTALL) -c -s ipresend $(BINDEST)/ipresend + -$(INSTALL) -c $(TOP)/mkfilters $(BINDEST)/mkfilters + -$(INSTALL) -c -s ipfs $(SBINDEST)/ipfs + -$(INSTALL) -c -s ipnat $(SBINDEST)/ipnat + -$(INSTALL) -c -s ipf $(SBINDEST)/ipf + -$(INSTALL) -c -s ipfstat $(SBINDEST)/ipfstat + -$(INSTALL) -c ipfboot $(RCDIR) + -cp $(TOP)/man/*.[0-9] . + -$(INSTALL) ipf.8 $(MANDIR)/man8 + -$(INSTALL) ipfs.8 $(MANDIR)/man8 + -$(INSTALL) ipnat.8 $(MANDIR)/man8 + -$(INSTALL) ipftest.1 $(MANDIR)/man1 + -$(INSTALL) mkfilters.1 $(MANDIR)/man1 + -$(INSTALL) ipf.4 $(MANDIR)/man4 + -$(INSTALL) ipfilter.4 $(MANDIR)/man4 + -$(INSTALL) ipnat.4 $(MANDIR)/man4 + -$(INSTALL) ipl.4 $(MANDIR)/man4 + -$(INSTALL) ipf.5 $(MANDIR)/man5 + -$(INSTALL) ipnat.5 $(MANDIR)/man5 + -$(INSTALL) ipfilter.5 $(MANDIR)/man5 + -$(INSTALL) ipfstat.8 $(MANDIR)/man8 + -$(INSTALL) ipmon.8 $(MANDIR)/man8 + -$(INSTALL) ipmon.5 $(MANDIR)/man5 + -$(INSTALL) ippool.8 $(MANDIR)/man8 + -$(INSTALL) ippool.5 $(MANDIR)/man5 + -$(INSTALL) ipscan.8 $(MANDIR)/man8 + -$(INSTALL) ipscan.5 $(MANDIR)/man5 + -cp $(TOP)/rules/* $(EXTRADIR) + -$(INSTALL) -m 644 -c $(TOP)/ip_fil.h $(INCDIR) + -$(INSTALL) -m 644 -c $(TOP)/ip_compat.h $(INCDIR) + -$(INSTALL) -m 644 -c $(TOP)/ip_state.h $(INCDIR) + -$(INSTALL) -m 644 -c $(TOP)/ip_nat.h $(INCDIR) + -$(INSTALL) -m 644 -c $(TOP)/ip_frag.h $(INCDIR) + -$(INSTALL) -m 644 -c $(TOP)/ip_proxy.h $(INCDIR) + -$(INSTALL) -m 644 -c $(TOP)/ip_auth.h $(INCDIR) + -touch ${ETCDIR}/ipf.conf ${ETCDIR}/ipnat.conf diff --git a/HPUX/Makefile.ipsend b/HPUX/Makefile.ipsend new file mode 100644 index 0000000000000..632f0779e4880 --- /dev/null +++ b/HPUX/Makefile.ipsend @@ -0,0 +1,65 @@ +OBJS=ipsend.o ip.o ipsopt.o iplang_y.o iplang_l.o ethers.o +IPFTO=ipft_ef.o ipft_hx.o ipft_pc.o ipft_sn.o ipft_td.o ipft_tx.o ethers.o +ROBJS=ipresend.o ip.o resend.o ethers.o +TOBJS=iptest.o iptests.o ip.o ethers.o +UNIXOBJS=dlcommon.o sdlpi.o arp.o ethers.o +HPUX=hpux.o sock.o arp.o ethers.o +ABI=+DD${BITS} -I$(TOP)/../pfil -I/usr/conf -I. +CC=cc $(ABI) -DHPUXREV=$(HPUXREV) +OBJ=. +LIBS=-lnsl -L$(OBJ) -lipf + +CFLAGS=-g -I$$(TOP) -Dhpux + +all build dlpi hpux : ipsend ipresend iptest + +.c.o: + $(CC) $(ABI) $(DEBUG) $(CFLAGS) -c $< -o $@ + +ethers.o: ../ethers.c + $(CC) $(ABI) $(DEBUG) $(CFLAGS) -c ../ethers.c -o $@ + +iplang_y.o: $(TOP)/iplang/iplang_y.y + (cd $(TOP)/iplang; $(MAKE) "DESTDIR=../HPUX/$(CPUDIR)" 'CFLAGS=$(CFLAGS) $(ABI)') + +iplang_l.o: $(TOP)/iplang/iplang_l.l + (cd $(TOP)/iplang; $(MAKE) "DESTDIR=../HPUX/$(CPUDIR)" 'CFLAGS=$(CFLAGS) $(ABI)') + +ipsend: $(OBJS) $(UNIXOBJS) + $(CC) $(ABI) $(DEBUG) $(OBJS) $(UNIXOBJS) -o $@ $(LIBS) -ll + +ipresend: $(ROBJS) $(UNIXOBJS) + $(CC) $(ABI) $(DEBUG) $(ROBJS) $(UNIXOBJS) -o $@ $(LIBS) + +iptest: $(TOBJS) $(UNIXOBJS) + $(CC) $(ABI) $(DEBUG) $(TOBJS) $(UNIXOBJS) -o $@ $(LIBS) + +clean: + rm -rf *.o core a.out ipsend ipresend iptest iplang_l.* iplang_y.* + +ipsend.o: $(TOP)/ipsend/ipsend.c + $(CC) $(ABI) $(DEBUG) $(CFLAGS) $(SPU) -c $(TOP)/ipsend/ipsend.c -o $@ +ipsopt.o: $(TOP)/ipsend/ipsopt.c + $(CC) $(ABI) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/ipsopt.c -o $@ +ipresend.o: $(TOP)/ipsend/ipresend.c + $(CC) $(ABI) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/ipresend.c -o $@ +ip.o: $(TOP)/ipsend/ip.c + $(CC) $(ABI) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/ip.c -o $@ +resend.o: $(TOP)/ipsend/resend.c + $(CC) $(ABI) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/resend.c -o $@ +ipft_sn.o: $(TOP)/ipft_sn.c + $(CC) $(ABI) $(DEBUG) $(CFLAGS) -c $(TOP)/ipft_sn.c -o $@ +ipft_pc.o: $(TOP)/ipft_pc.c + $(CC) $(ABI) $(DEBUG) $(CFLAGS) -c $(TOP)/ipft_pc.c -o $@ +iptest.o: $(TOP)/ipsend/iptest.c + $(CC) $(ABI) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/iptest.c -o $@ +iptests.o: $(TOP)/ipsend/iptests.c + $(CC) $(ABI) $(HPREV) $(DEBUG) $(CFLAGS) -Dhpux -c $(TOP)/ipsend/iptests.c -o $@ +sock.o: $(TOP)/ipsend/sock.c + $(CC) $(ABI) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/sock.c -o $@ +arp.o: $(TOP)/ipsend/arp.c + $(CC) $(ABI) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/arp.c -o $@ +dlcommon.o: $(TOP)/ipsend/dlcommon.c + $(CC) $(ABI) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/dlcommon.c -o $@ +sdlpi.o: $(TOP)/ipsend/sdlpi.c + $(CC) $(ABI) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/sdlpi.c -o $@ diff --git a/HPUX/cpurev b/HPUX/cpurev new file mode 100755 index 0000000000000..5cc37ba568984 --- /dev/null +++ b/HPUX/cpurev @@ -0,0 +1,6 @@ +#!/bin/sh +bits=`getconf KERNEL_BITS` +rev=`uname -r` +model=`uname -m|sed -e 's!/!.!'` +echo $rev.$model.$bits +exit 0 diff --git a/HPUX/ethers.c b/HPUX/ethers.c new file mode 100644 index 0000000000000..ffe7c4e8eed30 --- /dev/null +++ b/HPUX/ethers.c @@ -0,0 +1,124 @@ +/* $NetBSD: ethers.c,v 1.17 2000/01/22 22:19:14 mycroft Exp $ */ + +/* + * ethers(3N) a la Sun. + * + * Written by Roland McGrath <roland@frob.com> 10/14/93. + * Public domain. + */ + +#if defined(__hpux) && (HPUXREV >= 1111) && !defined(_KERNEL) +# include <sys/kern_svcs.h> +#endif +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <net/if_arp.h> + +#include <stdio.h> +#include <errno.h> + +#include "ip_compat.h" + + +struct ether_addr * +ether_aton(s) + const char *s; +{ + static struct ether_addr n; + u_int i[6]; + + if (sscanf(s, " %x:%x:%x:%x:%x:%x ", &i[0], &i[1], + &i[2], &i[3], &i[4], &i[5]) == 6) { + n.ether_addr_octet[0] = (u_char)i[0]; + n.ether_addr_octet[1] = (u_char)i[1]; + n.ether_addr_octet[2] = (u_char)i[2]; + n.ether_addr_octet[3] = (u_char)i[3]; + n.ether_addr_octet[4] = (u_char)i[4]; + n.ether_addr_octet[5] = (u_char)i[5]; + return &n; + } + return NULL; +} + + +int +ether_hostton(hostname, e) + const char *hostname; + struct ether_addr *e; +{ + FILE *f; + char *p; + size_t len; + char try[MAXHOSTNAMELEN + 1]; + char line[512]; +#ifdef YP + int hostlen = strlen(hostname); +#endif + + f = fopen("/etc/ethers", "r"); + if (f==NULL) + return -1; + + while ((p = fgets(line, sizeof(line), f)) != NULL) { + if (p[len - 1] != '\n') + continue; /* skip lines w/o \n */ + p[--len] = '\0'; +#ifdef YP + /* A + in the file means try YP now. */ + if (len == 1 && *p == '+') { + char *ypbuf, *ypdom; + int ypbuflen; + + if (yp_get_default_domain(&ypdom)) + continue; + if (yp_match(ypdom, "ethers.byname", hostname, hostlen, + &ypbuf, &ypbuflen)) + continue; + if (ether_line(ypbuf, e, try) == 0) { + free(ypbuf); + (void)fclose(f); + return 0; + } + free(ypbuf); + continue; + } +#endif + if (ether_line(p, e, try) == 0 && strcmp(hostname, try) == 0) { + (void)fclose(f); + return 0; + } + } + (void)fclose(f); + errno = ENOENT; + return -1; +} + + +int +ether_line(l, e, hostname) + const char *l; + struct ether_addr *e; + char *hostname; +{ + u_int i[6]; + static char buf[sizeof " %x:%x:%x:%x:%x:%x %s\\n" + 21]; + /* XXX: 21 == strlen (ASCII representation of 2^64) */ + + if (! buf[0]) + snprintf(buf, sizeof buf, " %%x:%%x:%%x:%%x:%%x:%%x %%%ds\\n", + MAXHOSTNAMELEN); + if (sscanf(l, buf, + &i[0], &i[1], &i[2], &i[3], &i[4], &i[5], hostname) == 7) { + e->ether_addr_octet[0] = (u_char)i[0]; + e->ether_addr_octet[1] = (u_char)i[1]; + e->ether_addr_octet[2] = (u_char)i[2]; + e->ether_addr_octet[3] = (u_char)i[3]; + e->ether_addr_octet[4] = (u_char)i[4]; + e->ether_addr_octet[5] = (u_char)i[5]; + return 0; + } + errno = EINVAL; + return -1; +} diff --git a/HPUX/installmod b/HPUX/installmod new file mode 100755 index 0000000000000..eb7215e807989 --- /dev/null +++ b/HPUX/installmod @@ -0,0 +1,27 @@ +#!/bin/ksh +(kmadmin -U ipf) +(kminstall -d ipf) +kminstall -u ipf +if [[ $? -ne 0 ]] ; then + exit 1 +fi +config -M ipf -u +if [[ $? -ne 0 ]] ; then + exit 1 +fi +kmadmin -L ipf +kmadmin -Q ipf +if [[ $? -ne 0 ]] ; then + exit 1 +fi +input=`kmadmin -Q ipf | grep 'Character Major'` +set $input +major=$3 +/bin/rm -f /dev/ipl /dev/ipnat /dev/ipstate /dev/ipauth +mknod /dev/ipl c $major 0 +mknod /dev/ipnat c $major 1 +mknod /dev/ipstate c $major 2 +mknod /dev/ipauth c $major 3 +mknod /dev/ipsync c $major 4 +mknod /dev/ipscan c $major 5 +exit 0 diff --git a/HPUX/ipf.psf.dist b/HPUX/ipf.psf.dist new file mode 100644 index 0000000000000..529741023d8ca --- /dev/null +++ b/HPUX/ipf.psf.dist @@ -0,0 +1,161 @@ +# File: psf +# +# Purpose: IP Filter Product Specification File (PSF) for swpackage +# +# Copyright (C) 2012 by Darren Reed. +# +# Description: PSF for IP FIlter 5.1.0 +# +# $Id$ + + +# The vendor definition here applies to all subsequently defined products. +vendor + tag IPFilter + title IPFilter Products + description Firewall/NAT Products +end + +category + tag HPUXAdditions + title IP Filter +end + +# Bundle definition(s): +bundle + tag IPF + title IP Filter 5.1.0 + description Firewall/NAT + revision A.05.01.00 + architecture HP-UX_HPREV_32/64 + machine_type 9000/[678]??:* + os_name HP-UX + os_release HPREV + os_version * + category_tag HPUXAdditions + is_protected false + is_reference false + vendor_tag IPFilter + hp_srdo swtype=O;user=B;bundle_type=O + contents IPF-RUN,r=A.05.01.00,a=HP-UX_HPREV_32/64,v=IPFilter +end # bundle IPF + +# Product definition(s): +product + tag IPF-RUN + title IP Filter 5.1.0 + description Firewall/NAT + copyright < ../../SunOS5/copyright + revision A.05.01.00 + architecture HP-UX_HPREV_32/64 + machine_type 9000/[678]??:* + os_name HP-UX + os_release HPREV + os_version * + directory / + is_locatable false + vendor_tag IPFilter + +# configure doc/configure +# unconfigure doc/unconfigure + + ######################################################################## + # # + # The following filesets already exist on the system. # + # # + ######################################################################## + + # InternetSrvcs.IPF-ALL + fileset + tag IPF-ALL + title IP Filter 5.1.0 : IPF-ALL + description < ../IPF-ALL/description + revision A.05.01.00 + architecture HP-UX_HPREV_32/64 + machine_type 9000/[678]??:* + os_name HP-UX + os_release HPREV + os_version * + is_kernel false + is_reboot false + +# prerequisites PHKL_18543.NET-KRN,a=HP-UX_HPREV_32/64,v=HP + + checkinstall ../IPF-ALL/checkinstall + preinstall ../IPF-ALL/preinstall + postinstall ../IPF-ALL/postinstall + verify ../IPF-ALL/verify + checkremove ../IPF-ALL/checkremove + preremove ../IPF-ALL/preremove + postremove ../IPF-ALL/postremove + + directory . = / + file_permissions -m 555 -o bin -g bin + file mod.o var/tmp/build/mod.o + file ../master var/tmp/build/master + file ../system var/tmp/build/system + file ../space.h var/tmp/build/space.h + file ../ipfboot sbin/init.d/ipfboot + file ../ipfconf etc/rc.config.d/ipfconf + file ipf sbin/ipf + file ipfs sbin/ipfs + file ipnat sbin/ipnat + file ipfstat sbin/ipfstat + file ipmon opt/ipf/bin/ipmon + file ipsend opt/ipf/bin/ipsend + file ipftest opt/ipf/bin/ipftest + file ipresend opt/ipf/bin/ipresend +# file ipscan opt/ipf/bin/ipscan +# file ipsyncs opt/ipf/bin/ipsyncs +# file ipsyncm opt/ipf/bin/ipsyncm + file ../../mkfilters opt/ipf/bin/mkfilters + file_permissions -m 444 -o bin -g bin + file ../../ip_fil.h opt/ipf/include/ip_fil.h + file ../../ip_nat.h opt/ipf/include/ip_nat.h + file ../../ip_state.h opt/ipf/include/ip_state.h + file ../../ip_compat.h opt/ipf/include/ip_compat.h + file ../../ip_proxy.h opt/ipf/include/ip_proxy.h + file ../../ip_frag.h opt/ipf/include/ip_frag.h + file ../../ip_auth.h opt/ipf/include/ip_auth.h + file ../../man/ipf.8 opt/ipf/man/man8/ipf.8 + file ../../man/ipnat.8 opt/ipf/man/man1/ipnat.8 + file ../../man/ipmon.8 opt/ipf/man/man8/ipmon.8 + file ../../man/ipfstat.8 opt/ipf/man/man8/ipfstat.8 + file ../../man/ipftest.1 opt/ipf/man/man1/ipftest.1 + file ../../man/ipfs.8 opt/ipf/man/man8/ipfs.8 + file ../../man/mkfilters.1 opt/ipf/man/man1/mkfilters.1 + file ../../man/ipf.4 opt/ipf/man/man4/ipf.4 + file ../../man/ipfilter.4 opt/ipf/man/man4/ipfilter.4 + file ../../man/ipl.4 opt/ipf/man/man4/ipl.4 + file ../../man/ipnat.4 opt/ipf/man/man4/ipnat.4 + file ../../man/ipf.5 opt/ipf/man/man5/ipf.5 + file ../../man/ipfilter.5 opt/ipf/man/man4/ipfilter.5 + file ../../man/ipnat.5 opt/ipf/man/man5/ipnat.5 + file ../../rules/example.1 opt/ipf/examples/example.1 + file ../../rules/example.2 opt/ipf/examples/example.2 + file ../../rules/example.3 opt/ipf/examples/example.3 + file ../../rules/example.4 opt/ipf/examples/example.4 + file ../../rules/example.5 opt/ipf/examples/example.5 + file ../../rules/example.6 opt/ipf/examples/example.6 + file ../../rules/example.7 opt/ipf/examples/example.7 + file ../../rules/example.8 opt/ipf/examples/example.8 + file ../../rules/example.9 opt/ipf/examples/example.9 + file ../../rules/example.10 opt/ipf/examples/example.10 + file ../../rules/example.11 opt/ipf/examples/example.11 + file ../../rules/example.12 opt/ipf/examples/example.12 + file ../../rules/example.13 opt/ipf/examples/example.13 + file ../../rules/example.sr opt/ipf/examples/example.sr + file ../../rules/nat.eg opt/ipf/examples/nat.eg + file ../../rules/server opt/ipf/examples/server + file ../../rules/tcpstate opt/ipf/examples/tcpstate + file ../../rules/BASIC.NAT opt/ipf/examples/BASIC.NAT + file ../../rules/BASIC_1.FW opt/ipf/examples/BASIC_1.FW + file ../../rules/BASIC_2.FW opt/ipf/examples/BASIC_2.FW + file ../../rules/firewall opt/ipf/examples/firewall + file ../../rules/ftp-proxy opt/ipf/examples/ftp-proxy + file ../../rules/ftppxy opt/ipf/examples/ftppxy + file ../../rules/nat-setup opt/ipf/examples/nat-setup + end # fileset IPF-ALL + +end # product IPF-RUN + diff --git a/HPUX/ipfboot b/HPUX/ipfboot new file mode 100644 index 0000000000000..b31b4b105f3b8 --- /dev/null +++ b/HPUX/ipfboot @@ -0,0 +1,115 @@ +#!/sbin/sh +# +PATH=/sbin:/usr/bin:/usr/sbin:/opt/ipf/bin +# +pid=`ps -e | grep ipmon | awk ' { print $1 } ' -` +. /etc/rc.config + +block_default_workaround() { + ipf -F a + echo "constructing minimal name resolution rules..." + NAMESERVERS=`cat /etc/resolv.conf | awk '/nameserver/ {printf "%s ", $2}'` + for NS in $NAMESERVERS + do + IF_TO_NS=`/usr/sbin/route -n get $NS | awk '/interface/ {print $NF}'` + IP_TO_NS=any + echo "pass out quick proto udp from $IP_TO_NS to $NS port = 53 keep state" | \ + ipf -f - + done +} + +set_device_files() { + input=`kmadmin -Q ipf | grep 'Character Major'` + set $input + major=$3 + /bin/rm -f /dev/ipl /dev/ipnat /dev/ipstate /dev/ipauth + /bin/rm -f /dev/ipsync /dev/ipscan /dev/iplookup + mknod /dev/ipl c $major 0 + mknod /dev/ipnat c $major 1 + mknod /dev/ipstate c $major 2 + mknod /dev/ipauth c $major 3 + mknod /dev/ipsync c $major 4 + mknod /dev/ipscan c $major 5 + mknod /dev/iplookup c $major 6 +} + +case "$1" in + start_msg) + echo "Starting IP Filter" + ;; + + stop_msg) + echo "Stopping IP Filter" + ;; + + start) + if [ ${IPF_START} -eq 1 ] ; then + if [ x$pid != x ] ; then + kill -TERM $pid + fi + kmadmin -L ipf + set_device_files + ipf -E + if [ -r ${IPF_CONF} ]; then + BLOCK_DEFAULT=`/sbin/ipf -V | grep Default | \ + awk '{print $2}'` + if [ x$BLOCK_DEFAULT = "xblock" ] ; then + block_default_workaround + fi + ipf -IFa -f ${IPF_CONF} + if [ $? != 0 ]; then + echo "$0: load of ${IPF_CONF} into alternate set failed" + else + ipf -s + fi + fi + if [ -r ${IPNAT_CONF} ]; then + ipnat -CF -f ${IPNAT_CONF} + if [ $? != 0 ]; then + echo "$0: load of ${IPNAT_CONF} failed" + fi + fi + if [ ${IPMON_START} -eq 1 ] ; then + ipmon ${IPMON_FLAGS} + fi + else + exit 2 + fi + ;; + + stop) + if [ x$pid != x ] ; then + kill -TERM $pid + fi + ipf -D + kmadmin -U ipf + ;; + + reload) + if [ -r ${IPF_CONF} ]; then + ipf -I -Fa -f ${IPF_CONF} + if [ $? != 0 ]; then + echo "$0: reload of ${IPF_CONF} into alternate set failed" + else + ipf -s + fi + fi + if [ -r ${IPNAT_CONF} ]; then + ipnat -CF -f ${IPNAT_CONF} + if [ $? != 0 ]; then + echo "$0: reload of ${IPNAT_CONF} failed" + fi + fi + ;; + + setdevs) + set_device_files + ;; + + *) + echo "Usage: $0 (start|stop|reload)" >&2 + exit 1 + ;; + +esac +exit 0 diff --git a/HPUX/ipfconf b/HPUX/ipfconf new file mode 100644 index 0000000000000..26dc093a717de --- /dev/null +++ b/HPUX/ipfconf @@ -0,0 +1,26 @@ +# +# Directory where IP Filter configuration files are kept +# +IPF_CONFDIR=/etc/opt/ipf +# +# Packet filtering configuration file +# +IPF_CONF=${IPF_CONFDIR}/ipf.conf +# +# Network address translation configuration file +# +IPNAT_CONF=${IPF_CONFDIR}/ipnat.conf +# +# Load the ipfilter module ? +# 1 = Start, 0 = Do not start +# +IPF_START=1 +# +# Start ipmon ? +# 1 = Start, 0 = Do not start +# +IPMON_START=1 +# +# Options to start ipmon with +# +IPMON_FLAGS=-sD diff --git a/HPUX/makeargs b/HPUX/makeargs new file mode 100755 index 0000000000000..f6b9c5606f6f3 --- /dev/null +++ b/HPUX/makeargs @@ -0,0 +1,10 @@ +#!/bin/ksh +dir=${0%makeargs} +hprev=`uname -r | sed -e 's/^[A-Z]\.\([0-9]*\)\.\([0-9]\)/\1\2/'` +if [ $hprev -lt 1111 ] ; then + lib=' LLIB=-ll' + dcpu=' SPU="-Dspustate_t=u_long"' +fi +cpu=`$dir/cpurev` +echo 'CPUDIR='$cpu' HPUXREV='$hprev''$lib$dcpu +exit 0 diff --git a/HPUX/master b/HPUX/master new file mode 100644 index 0000000000000..26718d0f2c016 --- /dev/null +++ b/HPUX/master @@ -0,0 +1,33 @@ +* +* master file for "ipf" module +* + +$VERSION +* Should start from 1, currently only 1 is correct value +1 +$$$ + +$DRIVER_INSTALL +* +* Driver Block major Char major required for minimal system +* +ipf -1 -1 +$$$ + +$LOADABLE +$$$ + +$INTERFACE +base +$$$ + +$DRIVER_DEPENDENCY +ipf pfil +$$$ + +$TYPE +ipf wsio_class pseudo cpmi -1 -1 +$$$ + +$TUNABLE +$$$ diff --git a/HPUX/space.h b/HPUX/space.h new file mode 100644 index 0000000000000..fe7f45da12e3b --- /dev/null +++ b/HPUX/space.h @@ -0,0 +1,3 @@ +/* + * Tunable parameters for "ipf" module + */ diff --git a/HPUX/system b/HPUX/system new file mode 100644 index 0000000000000..8bad230b24235 --- /dev/null +++ b/HPUX/system @@ -0,0 +1,8 @@ +* +* system file for "ipf" module +* +$VERSION 1 +$CONFIGURE Y +$LOADABLE Y +$TUNABLE +$$$ diff --git a/INSTALL.FreeBSD b/INSTALL.FreeBSD index a4a787ac42be2..2a16942c15f03 100644 --- a/INSTALL.FreeBSD +++ b/INSTALL.FreeBSD @@ -1,8 +1,11 @@ -This file is for use with FreeBSD 4.x and 5.x only. +Thi file is for use with FreeBSD 4.x and 5.x only. To build a kernel for use with the loadable kernel module, follow these steps: + 0. Run "config GENERIC" or similar in /sys/i386/conf or the + appropriate directory for your kernel. + 1. For FreeBSD version: 4.* do make freebsd4 5.* do make freebsd5 @@ -16,10 +19,12 @@ steps: 5. install and reboot with the new kernel - 6. use modload(8) to load the packet filter with: + 6. use modload(8)/kldload(8) to load the packet filter with: modload if_ipl.o + kldload ipf.ko - 7. do "modstat" to confirm that it has been loaded successfully. + 7. do "modstat" or "kldstat" to confirm that it has been loaded + successfully. There is no need to use mknod to create the device in /dev; - upon loading the module, it will create itself with the correct values, diff --git a/INSTALL.IRIX b/INSTALL.IRIX index b64d4349879bd..779ccf64c50f9 100644 --- a/INSTALL.IRIX +++ b/INSTALL.IRIX @@ -1,7 +1,7 @@ -IP Filter has been mostly tested under IRIX 6.2. It should work under IRIX 6.3 -as well. Under IRIX 5.3, it has been successfully compiled and linked in the -kernel, but not tested. Compilation under IRIX >= 6.4 is not yet supported. +IP Filter has been mostly tested under IRIX 6.2 and 6.5. +Under IRIX 5.3, it has been successfully compiled and linked in the kernel, +but not tested. To build a kernel with the IP filter and install it on your system, follow these steps: @@ -17,13 +17,6 @@ follow these steps: CC=gcc to CC=cc - b) enable full optimization - This means changing the lines reading: - DEBUG=-g - CFLAGS=-I$$(TOP) - to - DEBUG= - CFLAGS=-O2 -I$$(TOP) 1. do "make irix" (Warning: GNU make is not supported, so if it has been installed on your system, verify your path and/or do "which make" @@ -80,11 +73,10 @@ ADDITIONAL NOTES: the same major device number. - We have not tested IP Filter on a multiprocessor machine yet. - However, feel free to try it and send your experiences/patches - back to marc@CAM.ORG. SGI prescribes that kernel code be built on such - systems with -D_MP_NETLOCKS -DMP. Therefore, these flags should - probably be uncommented on the DFLAGS line of IRIX/Makefile if your - machine has more than one processor. + SGI prescribes that kernel code be built on such systems with + -D_MP_NETLOCKS -DMP. Therefore, these flags should probably be + uncommented on the DFLAGS line of IRIX/Makefile if your machine + has more than one processor. - It is also possible to build IP Filter as a dynamically loadable kernel module (by retaining the IPFLKM=-DIPFILTER_LKM definition in the @@ -95,7 +87,6 @@ ADDITIONAL NOTES: with IP22 CPU boards and can sometime cause panics during loading due to a potential race condition. - CREDITS: IP Filter was ported to IRIX by Marc Boucher <marc@CAM.ORG> diff --git a/INSTALL.Linux b/INSTALL.Linux index 1a5d15b59f02e..b25f39782f953 100644 --- a/INSTALL.Linux +++ b/INSTALL.Linux @@ -1,50 +1,43 @@ -IP-Filter on Linux 2.0.31 -------------------------- -NOTE: I have *ONLY* compiled and created patches for using IP Filter on - Linux 2.0.31. Any other kernel revision may need seprate patches. - Also, I've only tested on a x86 CPU so I can't make any guarantees - about it working on Sparc/Mac/Amiga. +The Linux 2.4 and 2.6 series of kernels are supported by this software. -First, you should do a sanity check of your system to make sure it will -compile IP Filter. You will need a "libfl" and a "libelf". If you don't -have these, install them before proceeding. +Building has been tested on RedHat 9 and SUSE 9.x, although your results +may vary. -The installation and compiliation process assumes that Linux 2.0.31 -will be in the /usr/src/linux directory and that all the symbolic links -in /usr/include match. /usr/src/linux may be a symbolic link too, but -it must point to a 2.0.31 kernel source tree. +In general, you will need to have your kernel source in /usr/src/linux +to build IPFilter but different Linux projects may differ. See below. -The first step is to make the IP Filter binaries. Do this with a -"make linux" from the ip_fil3.2.x directory. If this completes with -no errors, install IP Filter with a "make install-linux". +Projects +======== -Now that the user part of it is complete, it is time to work on the kernel. -To start this off, run "Linux/minstall". This will configure the devices -you will need for the IP Filter. Then run "Linux/kinstall". This will -patch your kernel source code and configuration files so you can enabled IP -Filter. You must now go to /usr/src/linux and configure your kernel using one -of the available interfaces to enable IP Filter. IP Filter will be presented -as a three way choice "y/m/n" - select "m" to enable it. Save your kernel -configuration file, rebuild, install and reboot with the new kernel. +Fedora +------ +For Fedora, point your web browser at this URL and follow the instructions: +http://fedoraproject.org/wiki/Building_a_custom_kernel -When you've rebooted with the new kernel, you should be able to load -IP Filter with the command "insmod if_ipl". All going will, you will -see a message like this on your console: +For me, following the instructions put all of the kernel source code (for +Fedora 11) in $HOME/rpmbuild. As an example of the directory I used, see +BUILDROOT in Makefile. -IP Filter: initialized. Default = pass all, Logging = enabled -indicating that IP Filter has successfully been loaded into the kernel -and is awaiting. +Building IPFilter +================= +The steps required are as follows: -Darren +1. Create the binaries + +make linux + +2. Create the RPM file -Features Not Available on Linux, yet: +make install-linux -- compiled into the kernel -"<action> in on <if> to <if> ..." -"<action> in on <if> dup-to <if> ..." -"<action> in on <if> fastroute ..." -"block return-rst ..." -"map ... proxy ..." (Linux's masquerading is better at present) +3. In an ideal world, this step wouldn't be required. At this point you +need to locate the actual RPM file as the rpmbuild failed in the previous +step. Now run: +rpm -i /path/to/ipfilter.rpm + +At this point IPFilter should be installed and ready to use. + +Darren diff --git a/INSTALL.Sol2 b/INSTALL.Sol2 index 5ba84b9319856..fffa97caa362a 100644 --- a/INSTALL.Sol2 +++ b/INSTALL.Sol2 @@ -2,6 +2,11 @@ For those running Solaris 2.5 or later, please read COMPILE.2.5 before building IP Filter. +Download, build and install the pfil package. +A pointer to this can be found at: + +http://coombs.anu.edu.au/~avalon/ipf-mentat.html + Type "make solaris" to build all the required binaries. DO NOT USE THE GNU make!!! @@ -12,15 +17,15 @@ directory to SunOS5 and enter the following command: make package -This will build the package into SunOS5/<arch>/root, copy that to -/var/spool/pkg as a package and then start the installation using -pkgadd. +This will build the package into SunOS5/<arch>/root, create a package +file called "ipf.pkg" in the SunOS5 directory and then start the +installation using pkgadd. As part of the postinstall script, it will install loadable kernel module as part of Solaris 2 (using add_drv) making it available for immeadiate use. -IP Filter will be installed into /opt/CYBSipf (programs, manual pages and -examples) and create a directory /etc/opt/CYBSipf with a null body file +IP Filter will be installed into /opt/ipf (programs, manual pages and +examples) and create a directory /etc/opt/ipf with a null body file called "ipf.conf" using touch. The rc scripts have been written to look for the configuration file here, using the installed binaries in /sbin. diff --git a/INSTALL.Tru64 b/INSTALL.Tru64 new file mode 100644 index 0000000000000..08cfca0cbb53b --- /dev/null +++ b/INSTALL.Tru64 @@ -0,0 +1,18 @@ + +Versions of Tru64 (aka OSF1) earlier than 5.1 aren't supported since +the relevant interfaces don't exist. Tru64 5.1 and 5.1a have been +tested. + + 1. do a "make tru64" (or "make osf") in this directory + + 2. run "make install-osf", in the same directory, to install + +To enable IPFilter, you then need to do: +sysconfig -c ipfilter + +Tru64 checkpoints: +- enable ipforwarding and ipgateway with "iprsetup -s" + +Darren Reed +darrenr@pobox.com + diff --git a/IRIX/Makefile b/IRIX/Makefile new file mode 100644 index 0000000000000..d08d9087a0908 --- /dev/null +++ b/IRIX/Makefile @@ -0,0 +1,81 @@ +#!smake +# +# Copyright (C) 2012 by Darren Reed. +# Copyright (C) 1997 by Marc Boucher. +# +# See the IPFILTER.LICENCE file for details on licencing. +# +# For IRIX +# +# Automatically determine compiler switches and defines for kernel compilation +# based on our current CPU: +# +DCPU=`uname -m` +# workaround minor Makefile.kernio IP22 bug +#if defined(DCPU) && ( $(DCPU) == "IP22" ) +CMODELWRKAROUND="COMPILATION_MODEL=32" +#else +CMODELWRKAROUND= +#endif +KFLAGS != smake -d v -n \ + -f $(ROOT)/var/sysgen/Makefile.kernio \ + CPUBOARD=$(DCPU) $(CMODELWRKAROUND) 2>/dev/null \ + | sed -n -e '/^Global:CFLAGS =/h' -e '$$g' -e '$$s/Global:CFLAGS =//' \ + -e '$$s/ -G *8 / /' -e '$$p' -e 's/-fullwarn//' +WOFF=-woff 1172,1174,1196,1233,1412,1413,1498,1506,1692 +# +SGIREV=-DIRIX=$(SGI) +BINDEST=/usr/sbin +SBINDEST=/sbin +MANDIR=/usr/share/man/local +INCDEST=/usr/include/netinet +LKMDEST=/var/sysgen/boot +HERE=IRIX/$(CPUDIR) +CPUDIR=`uname -s|sed -e 's@/@@g'`-`uname -R`-`uname -m` +RANLIB=echo +AROPTS=crs +OBJ=. +DEST=. +TOP=.. +TOOL=$(TOP)/tools +LIBS=-L. -lipf +#CC=cc -Wall -Wuninitialized -Wstrict-prototypes -Werror -O +CC=cc -common +CFLAGS=-g -I$(TOP) -I. +# +ML=mli_ipl.c +MLD=$(ML) +#if defined(IPFLKM) && !empty(IPFLKM) +MLFLAGS= -G 0 +LKM=ipflkm.o +#else +MLFLAGS= -G 8 +LKM=ipfilter.o +#endif +MFLAGS="BINDEST=$(BINDEST)" "SBINDEST=$(SBINDEST)" "MANDIR=$(MANDIR)" \ + 'CFLAGS=$(CFLAGS) $(SOLARIS2)' "IPFLKM=$(IPFLKM)" \ + "IPFLOG=$(IPFLOG)" "LOGFAC=$(LOGFAC)" "POLICY=$(POLICY)" \ + "SOLARIS2=$(SOLARIS2)" "DEBUG=$(DEBUG)" "DCPU=$(CPU)" \ + "CPUDIR=$(CPUDIR)" "LOOKUP=$(LOOKUP)" "XID=$(XID)" +CCARGS=$(DEBUG) $(CFLAGS) -D_KMEMUSER -DIPFILTER_LOG +# +########## ########## ########## ########## ########## ########## ########## +# +CP=/bin/cp +RM=/bin/rm +CHMOD=/bin/chmod +INSTALL=/sbin/install +LIBSRC=$(TOP)/lib +# +DFLAGS=$(WOFF) $(IPFLKM) $(IPFLOG) $(KFLAGS) $(MLFLAGS) -jalr $(SGIREV) \ + $(LOOKUP) $(XID) #-D_MP_NETLOCKS -DMP + +include $(TOP)/lib/Makefile + +include Makefile.common + +#if !defined(IPFLKM) || empty(IPFLKM) + -${RM} -f $(LKMDEST)/ipflkm.o + /etc/autoconfig +#endif + diff --git a/IRIX/Makefile.common b/IRIX/Makefile.common new file mode 100644 index 0000000000000..3379d19daf35a --- /dev/null +++ b/IRIX/Makefile.common @@ -0,0 +1,380 @@ +MODOBJS=ip_fil.o fil.o ml_ipl.o ip_nat.o ip_frag.o ip_state.o ip_proxy.o \ + ip_auth.o ip_log.o ip_scan.o ip_sync.o md5.o radix.o ip_nat6.o \ + ip_lookup.o ip_htable.o ip_pool.o +IPF=ipf.o ipfcomp.o ipf_y.o ipf_l.o +IPFTEST=ipftest.o fil_u.o ip_frag_u.o ip_state_u.o ip_nat_u.o ip_proxy_u.o \ + ip_auth_u.o ip_fil_u.o ip_log_u.o ip_scan_u.o ip_sync_u.o \ + ip_lookup_u.o ip_htable_u.o ip_pool_u.o ip_rules_u.o ip_nat6_u.o \ + ipf_y.o ipf_l.o ipnat_y.o ipnat_l.o ippool_y.o ippool_l.o \ + bpf_filter_u.o md5_u.o radix_u.o +IPNAT=ipnat.o ipnat_y.o ipnat_l.o +IPMON=ipmon.o ipmon_y.o ipmon_l.o +IPPOOL=ippool_y.o ippool_l.o ippool.o +IPFSTAT=ipfstat.o +EXTRA=-DIPFILTER_LOG -DIPFILTER_LOOKUP +#FIXRADIX=-Dradix_node=ipf_radix_node -Dradix_node_head=ipf_radix_node_head \ +# -Drn_inithead=ipf_rn_inithead -Drn_walktree=ipf_rn_walktree +FIXRADIX=-D__NET_RADIX_H_ + +build all: radix_ipf_local.h $(DEST)/libipf.a ipf ipfs ipfstat ipftest ipmon ipnat \ + ippool ipscan ipsyncm ipsyncs $(LKM) + -sh -c 'for i in ipf ipftest ipmon ippool ipnat ipscan ipsyncm ipsyncs; do /bin/rm -f $(TOP)/$$i; ln -s `pwd`/$$i $(TOP); done' + +ipfstat: $(IPFSTAT) $(DEST)/libipf.a + $(CC) $(CCARGS) $(STATETOP_CFLAGS) $(STATETOP_INC) \ + $(IPFSTAT) -o $@ $(LIBS) $(STATETOP_LIB) -lelf + +ipf: $(IPF) $(DEST)/libipf.a + $(CC) $(CCARGS) $(IPF) -o $@ $(LIBS) $(LIBBPF) + +ipftest: $(IPFTEST) $(DEST)/libipf.a + $(CC) $(CCARGS) $(IPFTEST) -o $@ $(LIBS) $(LIBBPF) + +ipnat: $(IPNAT) $(DEST)/libipf.a + $(CC) $(CCARGS) $(IPNAT) -o $@ $(LIBS) -lelf + +ipnat.o: $(TOOL)/ipnat.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_nat.h + $(CC) $(CCARGS) -c $(TOOL)/ipnat.c -o $@ + +ipnat_y.o: ipnat_y.c ipnat_y.h $(TOP)/ip_nat.h ipnat_l.h + $(CC) $(CCARGS) -c ipnat_y.c -o $@ + +ipnat_y.c ipnat_y.h: $(TOOL)/ipnat_y.y $(TOP)/ip_nat.h + (cd $(TOOL); make DEST=../$(HERE) ../$(HERE)/$@) + +ipnat_l.o: ipnat_l.c ipnat_l.h $(TOP)/ip_nat.h ipnat_y.h + $(CC) $(CCARGS) -c ipnat_l.c -o $@ + +ipnat_l.c: $(TOOL)/lexer.c ipnat_y.h + (cd $(TOOL); make DEST=../$(HERE) ../$(HERE)/$@) + +ipnat_l.h: $(TOOL)/lexer.h + (cd $(TOOL); make DEST=../$(HERE) ../$(HERE)/$@) + +tests: + (cd test; make ) + +ipfstat.o: $(TOOL)/ipfstat.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_frag.h \ + $(TOP)/ip_compat.h $(TOP)/ip_state.h $(TOP)/ip_nat.h + $(CC) $(CCARGS) $(STATETOP_CFLAGS) $(STATETOP_INC) \ + -c $(TOOL)/ipfstat.c -o $@ + +fil_u.o: $(TOP)/fil.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_compat.h \ + $(TOP)/ipl.h radix_ipf_local.h + $(CC) $(CCARGS) $(EXTRA) $(IPFBPF) -I. -c $(TOP)/fil.c -o $@ + +fil.o: $(TOP)/fil.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_compat.h \ + $(TOP)/ipl.h + $(CC) $(CCARGS) $(POLICY) $(DFLAGS) $(IPFBPF) -c $(TOP)/fil.c -o $@ + +ipf.o: $(TOOL)/ipf.c $(TOP)/ip_fil.h $(TOP)/ipf.h + $(CC) $(CCARGS) -c $(TOOL)/ipf.c -o $@ + +ipfcomp.o: $(TOOL)/ipfcomp.c $(TOP)/ip_fil.h $(TOP)/ipf.h + $(CC) $(CCARGS) -c $(TOOL)/ipfcomp.c -o $@ + +ipftest.o: $(TOOL)/ipftest.c $(TOP)/ip_fil.h $(TOP)/ipt.h $(TOP)/ipf.h + $(CC) $(SGIREV) $(CCARGS) -c $(TOOL)/ipftest.c -o $@ + +ip_nat_u.o: $(TOP)/ip_nat.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_nat.c -o $@ + +ip_nat6_u.o: $(TOP)/ip_nat6.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_nat6.c -o $@ + +ip_proxy_u.o: $(TOP)/ip_proxy.c $(TOP)/ip_proxy.h $(TOP)/ip_compat.h \ + $(TOP)/ip_ftp_pxy.c $(TOP)/ip_rcmd_pxy.c $(TOP)/ip_raudio_pxy.c \ + $(TOP)/ip_rpcb_pxy.c $(TOP)/ip_ipsec_pxy.c $(TOP)/ip_nat.h \ + $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_proxy.c -o $@ + +ip_frag_u.o: $(TOP)/ip_frag.c $(TOP)/ip_frag.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_frag.c -o $@ + +ip_state_u.o: $(TOP)/ip_state.c $(TOP)/ip_state.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(TOP)/ip_nat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_state.c -o $@ + +ip_auth_u.o: $(TOP)/ip_auth.c $(TOP)/ip_auth.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_auth.c -o $@ + +ip_rules_u.o: ip_rules.c $(TOP)/ip_rules.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) -c ip_rules.c -o $@ + +ip_pool_u.o: $(TOP)/ip_pool.c $(TOP)/ip_pool.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(TOP)/ip_lookup.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_pool.c -o $@ + +ip_scan_u.o: $(TOP)/ip_scan.c $(TOP)/ip_scan.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(TOP)/ip_lookup.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_scan.c -o $@ + +ip_sync_u.o: $(TOP)/ip_sync.c $(TOP)/ip_sync.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(TOP)/ip_lookup.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_sync.c -o $@ + +ip_lookup_u.o: $(TOP)/ip_lookup.c $(TOP)/ip_lookup.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_lookup.c -o $@ + +ip_htable_u.o: $(TOP)/ip_htable.c $(TOP)/ip_htable.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(TOP)/ip_lookup.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_htable.c -o $@ + +ip_fil_u.o: $(TOP)/ip_fil.c $(TOP)/ip_fil.h $(TOP)/ip_compat.h radix_ipf_local.h + $(CC) $(CCARGS) $(EXTRA) -I. -c $(TOP)/ip_fil.c -o $@ + +bpf_filter_u.o: $(TOP)/bpf_filter.c + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/bpf_filter.c -o $@ + +md5_u.o: $(TOP)/md5.c + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/md5.c -o $@ + +radix_u.o: $(TOP)/radix.c $(TOP)/radix_ipf.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/radix.c -o $@ + +ipfs: ipfs.o + $(CC) $(CCARGS) ipfs.o -o $@ + +ipfs.o: $(TOOL)/ipfs.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_state.h \ + $(TOP)/ip_nat.h + $(CC) $(CCARGS) -c $(TOOL)/ipfs.c -o $@ + +ipsyncm: ipsyncm.o $(DEST)/libipf.a + $(CC) $(CCARGS) ipsyncm.o -o $@ $(LIBS) + +ipsyncs: ipsyncs.o $(DEST)/libipf.a + $(CC) $(CCARGS) ipsyncs.o -o $@ $(LIBS) + +ipsyncm.o: $(TOOL)/ipsyncm.c $(TOP)/ip_sync.h + $(CC) $(CCARGS) -c $(TOOL)/ipsyncm.c -o $@ + +ipsyncs.o: $(TOOL)/ipsyncs.c $(TOP)/ip_sync.h + $(CC) $(CCARGS) -c $(TOOL)/ipsyncs.c -o $@ + +ip_log_u.o: $(TOP)/ip_log.c $(TOP)/ip_fil.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_log.c -o $@ + +ip_rules.c: $(TOP)/rules/ip_rules $(TOP)/tools/ipfcomp.c ipf + ./ipf -cc -nf $(TOP)/rules/ip_rules + +$(TOP)/ip_rules.h: ip_rules.c + if [ ! -f $(TOP)/ip_rules.h ] ; then \ + /bin/mv -f ip_rules.h $(TOP); \ + else \ + touch $(TOP)/ip_rules.h; \ + fi + +$(LKM): $(MODOBJS) + ld $(MLFLAGS) -r -d $(MODOBJS) -o $(LKM) + +ip_nat.o: $(TOP)/ip_nat.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_nat.c -o $@ + +ip_nat6.o: $(TOP)/ip_nat6.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_nat6.c -o $@ + +ip_frag.o: $(TOP)/ip_frag.c $(TOP)/ip_frag.h $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_frag.c -o $@ + +ip_state.o: $(TOP)/ip_state.c $(TOP)/ip_state.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(TOP)/ip_nat.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_state.c -o $@ + +ip_proxy.o: $(TOP)/ip_proxy.c $(TOP)/ip_proxy.h $(TOP)/ip_compat.h \ + $(TOP)/ip_ftp_pxy.c $(TOP)/ip_rcmd_pxy.c $(TOP)/ip_raudio_pxy.c \ + $(TOP)/ip_rpcb_pxy.c $(TOP)/ip_ipsec_pxy.c $(TOP)/ip_nat.h \ + $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_proxy.c -o $@ + +ip_auth.o: $(TOP)/ip_auth.c $(TOP)/ip_auth.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_auth.c -o $@ + +ip_pool.o: $(TOP)/ip_pool.c $(TOP)/ip_pool.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(TOP)/ip_lookup.h radix_ipf_local.h + $(CC) $(CCARGS) $(DFLAGS) $(FIXRADIX) -I. -c $(TOP)/ip_pool.c -o $@ + +ip_scan.o: $(TOP)/ip_scan.c $(TOP)/ip_scan.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(TOP)/ip_lookup.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_scan.c -o $@ + +ip_sync.o: $(TOP)/ip_sync.c $(TOP)/ip_sync.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(TOP)/ip_lookup.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_sync.c -o $@ + +radix.o: $(TOP)/radix.c $(TOP)/radix_ipf.h + $(CC) $(CCARGS) $(DFLAGS) $(FIXRADIX) -c $(TOP)/radix.c -o $@ + +ip_lookup.o: $(TOP)/ip_lookup.c $(TOP)/ip_lookup.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h radix_ipf_local.h + $(CC) $(CCARGS) $(DFLAGS) $(FIXRADIX) -I. -c $(TOP)/ip_lookup.c -o $@ + +ip_htable.o: $(TOP)/ip_htable.c $(TOP)/ip_htable.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(TOP)/ip_lookup.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_htable.c -o $@ + +ip_fil.o: $(TOP)/ip_fil_irix.c $(TOP)/ip_fil.h $(TOP)/ip_compat.h \ + $(TOP)/ip_nat.h + $(CC) $(CCARGS) $(DFLAGS) $(COMPIPF) -c $(TOP)/ip_fil_irix.c -o $@ + +ip_log.o: $(TOP)/ip_log.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_log.c -o $@ + +md5.o: $(TOP)/md5.c $(TOP)/md5.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/md5.c -o $@ + +ml_ipl.o: $(TOP)/$(MLD) $(TOP)/ipl.h + $(CC) -I. $(CFLAGS) $(DFLAGS) -c $(TOP)/$(ML) -o $@ + +ipf_y.o: ipf_y.c $(TOP)/ip_fil.h $(TOP)/ipf.h ipf_y.h ipf_l.h + $(CC) $(CCARGS) $(IPFBPF) -c ipf_y.c -o $@ + +ipf_l.o: ipf_l.c $(TOP)/ip_fil.h $(TOP)/ipf.h ipf_y.h ipf_l.h + $(CC) $(CCARGS) -c ipf_l.c -o $@ + +ipf_y.c ipf_y.h: $(TOOL)/ipf_y.y $(TOP)/ipf.h + (cd $(TOOL); make DEST=../$(HERE) ../$(HERE)/$@) + +ipf_l.c: $(TOOL)/lexer.c $(TOP)/ipf.h + (cd $(TOOL); make DEST=../$(HERE) ../$(HERE)/$@) + +ipf_l.h: $(TOOL)/lexer.h + (cd $(TOOL); make DEST=../$(HERE) ../$(HERE)/$@) + +ipmon: $(IPMON) $(DEST)/libipf.a + $(CC) $(CCARGS) $(LOGFAC) $(IPMON) -o $@ $(LIBS) + +ipmon.o: $(TOOL)/ipmon.c $(TOP)/ipmon.h + $(CC) $(CCARGS) $(LOGFAC) -c $(TOOL)/ipmon.c -o $@ + +ipmon_y.o: ipmon_y.c ipmon_y.h $(TOP)/ipmon.h ipmon_l.h + $(CC) $(CCARGS) -c ipmon_y.c -o $@ + +ipmon_y.c ipmon_y.h: $(TOOL)/ipmon_y.y $(TOP)/ipmon.h + (cd $(TOOL); make DEST=../$(HERE) ../$(HERE)/$@) + +ipmon_l.o: ipmon_l.c ipmon_y.h $(TOP)/ipmon.h ipmon_l.h + $(CC) $(CCARGS) -c ipmon_l.c -o $@ + +ipmon_l.c: $(TOOL)/lexer.c $(TOP)/ipmon.h + (cd $(TOOL); make DEST=../$(HERE) ../$(HERE)/$@) + +ipmon_l.h: $(TOOL)/lexer.h + (cd $(TOOL); make DEST=../$(HERE) ../$(HERE)/$@) + +ipscan: ipscan_y.o ipscan_l.o $(DEST)/libipf.a + $(CC) $(DEBUG) ipscan_y.o ipscan_l.o -o $@ $(LIBS) + +ipscan_y.o: ipscan_y.c ipscan_y.h $(TOP)/ip_scan.h ipscan_l.h + $(CC) $(CCARGS) -c ipscan_y.c -o $@ + +ipscan_l.o: ipscan_l.c ipscan_y.h $(TOP)/ip_scan.h ipscan_l.h + $(CC) $(CCARGS) -I. -c ipscan_l.c -o $@ + +ipscan_y.h ipscan_y.c: $(TOOL)/ipscan_y.y $(TOP)/ip_scan.h + (cd $(TOOL); make DEST=../$(HERE) ../$(HERE)/$@) + +ipscan_l.c: $(TOOL)/lexer.c $(TOP)/ip_scan.h + (cd $(TOOL); make DEST=../$(HERE) ../$(HERE)/$@) + +ipscan_l.h: $(TOOL)/lexer.h + (cd $(TOOL); make DEST=../$(HERE) ../$(HERE)/$@) + +ippool: $(IPPOOL) + $(CC) $(CCARGS) -I. $(IPPOOL) -o $@ $(LIBS) + +ippool.o: $(TOOL)/ippool.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_pool.h + $(CC) $(CCARGS) -c $(TOOL)/ippool.c -o $@ + +ippool_y.o: ippool_y.c ippool_y.h $(TOP)/ip_pool.h ippool_l.h + $(CC) $(CCARGS) -c ippool_y.c -o $@ + +ippool_l.o: ippool_l.c ippool_y.h $(TOP)/ip_pool.h ippool_l.h + $(CC) $(CCARGS) -I. -c ippool_l.c -o $@ + +ippool_y.h ippool_y.c: $(TOOL)/ippool_y.y $(TOP)/ip_pool.h + (cd $(TOOL); make DEST=../$(HERE) ../$(HERE)/$@) + +ippool_l.c: $(TOOL)/lexer.c $(TOP)/ip_pool.h + (cd $(TOOL); make DEST=../$(HERE) ../$(HERE)/$@) + +ippool_l.h: $(TOOL)/lexer.h + (cd $(TOOL); make DEST=../$(HERE) ../$(HERE)/$@) + +radix_ipf_local.h: $(TOP)/radix_ipf.h + +radix_ipf_local.h radix_ipf.h: $(TOP)/radix_ipf.h Makefile + cat $(TOP)/radix_ipf.h > $@ +# sed -e 's/radix_node/ipf_radix_node/g' \ +# -e 's/radix_mask/ipf_radix_mask/g' \ +# $(TOP)/radix_ipf.h > $@ + +.y.c: + +.l.c: + +clean: + ${RM} -f ../ipf ../ipmon ../ipnat ../ippool ../ipftest + ${RM} -f ../ipscan ../ipsyncm ../ipsyncs + ${RM} -f core *.o *.a ipt ipfstat ipf ipfstat ipftest ipmon + ${RM} -f if_ipl ipnat $(LKM) + ${RM} -f ip_fil.c ipf_l.c ipf_y.c ipf_y.h ipf_l.h + ${RM} -f ipscan ipscan_y.c ipscan_y.h ipscan_l.c ipscan_l.h + ${RM} -f ippool ippool_y.c ippool_y.h ippool_l.c ippool_l.h + ${RM} -f ipnat_y.c ipnat_y.h ipnat_l.c ipnat_l.h + ${RM} -f ipmon_y.c ipmon_y.h ipmon_l.c ipmon_l.h + ${RM} -f ipsyncm ipsyncs ipfs ip_rules.c ip_rules.h + ${MAKE} -f Makefile.ipsend ${MFLAGS} TOP=$(TOP) clean + -(for i in *; do \ + if [ -d $${i} -a -f $${i}/Makefile ] ; then \ + cd $${i}; ($(MAKE) clean TOP=../..); cd ..; \ + ${RM} $${i}/Makefile $${i}/Makefile.ipsend; \ + ${RM} $${i}/Makefile.common; \ + rmdir $${i}; \ + fi \ + done) + +install: + -$(INSTALL) -F $(SBINDEST) -m 755 -src $(CPUDIR)/ipf -O ipf + -$(INSTALL) -F $(SBINDEST) -m 755 -src $(CPUDIR)/ipfstat -O ipfstat + -$(INSTALL) -F $(SBINDEST) -m 755 -src $(CPUDIR)/ipnat -O ipnat + + -$(INSTALL) -F $(SBINDEST) -m 755 -src $(CPUDIR)/ipmon -O ipmon + -$(INSTALL) -F $(BINDEST) -m 755 -src $(CPUDIR)/ipftest -O ipftest + -$(INSTALL) -F $(BINDEST) -m 755 -src $(CPUDIR)/ipsend -O ipsend +# -$(INSTALL) -F $(BINDEST) -m 755 -src $(CPUDIR)/ipsyncs -O ipsyncs +# -$(INSTALL) -F $(BINDEST) -m 755 -src $(CPUDIR)/ipsyncm -O ipsyncm + -$(INSTALL) -F $(BINDEST) -m 755 -src $(CPUDIR)/ipresend -O ipresend + -if [ -r $(LKMDEST)/$(LKM) -a ! -r $(LKMDEST)/$(LKM).DIST ]; then \ + cp -p $(LKMDEST)/$(LKM) $(LKMDEST)/$(LKM).DIST; \ + fi + -$(INSTALL) -F /var/sysgen/master.d -m 644 ipl + -$(INSTALL) -F $(LKMDEST) -m 444 -src $(CPUDIR)/$(LKM) -O $(LKM) + -$(INSTALL) -F $(INCDEST) -m 444 -src $(TOP)/ip_fil.h -O ip_fil.h + -$(INSTALL) -F $(INCDEST) -m 444 -src $(TOP)/ip_nat.h -O ip_nat.h + -$(INSTALL) -F $(MANDIR)/man1 -m 444 -src $(TOP)/ipsend/ipsend.1 -O ipsend.1 + -$(INSTALL) -F $(MANDIR)/man1 -m 444 -src $(TOP)/ipsend/ipresend.1 -O ipresend.1 + -$(INSTALL) -F $(MANDIR)/man1 -m 444 -src $(TOP)/ipsend/iptest.1 -O iptest.1 + -$(INSTALL) -F $(MANDIR)/man5 -m 444 -src $(TOP)/ipsend/ipsend.5 -O ipsend.5 + -$(INSTALL) -F $(MANDIR)/man8 -m 444 -src $(TOP)/man/ipnat.8 -O ipnat.8 + -$(INSTALL) -F $(MANDIR)/man1 -m 444 -src $(TOP)/man/ipftest.1 -O ipftest.1 + -$(INSTALL) -F $(MANDIR)/man4 -m 444 -src $(TOP)/man/ipf.4 -O ipf.4 + -$(INSTALL) -F $(MANDIR)/man4 -m 444 -src $(TOP)/man/ipfilter.4 -O ipfilter.4 + -$(INSTALL) -F $(MANDIR)/man4 -m 444 -src $(TOP)/man/ipl.4 -O ipl.4 + -$(INSTALL) -F $(MANDIR)/man4 -m 444 -src $(TOP)/man/ipnat.4 -O ipnat.4 + -$(INSTALL) -F $(MANDIR)/man5 -m 444 -src $(TOP)/man/ipf.5 -O ipf.5 + -$(INSTALL) -F $(MANDIR)/man5 -m 444 -src $(TOP)/man/ipnat.5 -O ipnat.5 + -$(INSTALL) -F $(MANDIR)/man5 -m 444 -src $(TOP)/man/ipfilter.5 -O ipfilter.5 + -$(INSTALL) -F $(MANDIR)/man8 -m 444 -src $(TOP)/man/ipf.8 -O ipf.8 + -$(INSTALL) -F $(MANDIR)/man8 -m 444 -src $(TOP)/man/ipfs.8 -O ipfs.8 + -$(INSTALL) -F $(MANDIR)/man8 -m 444 -src $(TOP)/man/ipfstat.8 -O ipfstat.8 + -$(INSTALL) -F $(MANDIR)/man8 -m 444 -src $(TOP)/man/ipmon.8 -O ipmon.8 + -$(INSTALL) -F /etc/init.d -m 755 -src ipfboot -O ipf +#if !defined(IPFLKM) || empty(IPFLKM) + -${RM} -f $(LKMDEST)/ipflkm.o + /etc/autoconfig +#endif diff --git a/IRIX/Makefile.ipsend b/IRIX/Makefile.ipsend new file mode 100644 index 0000000000000..fe9e4afb94518 --- /dev/null +++ b/IRIX/Makefile.ipsend @@ -0,0 +1,68 @@ +IOBJS=ipsend.o ip.o ipsopt.o iplang_y.o iplang_l.o +ROBJS=ipresend.o ip.o resend.o +TOBJS=iptest.o iptests.o ip.o +UNIXOBJS=sirix.o arp.o +OBJ=. +LIBSRC=../../lib +DEST=. +TOP=../.. +LIBS=-L$(OBJ) -lipf + +CC=cc +CFLAGS=-g -I$(TOP) + +include $(TOP)/lib/Makefile + +all build irix : libipf.a ipsend ipresend iptest + +.c.o: + $(CC) $(DEBUG) $(CFLAGS) -c $< -o $@ + +iplang_y.o: $(TOP)/iplang/iplang_y.y + (cd $(TOP)/iplang; $(MAKE) 'CFLAGS=$(CFLAGS)' 'DESTDIR=../IRIX/$(CPUDIR)' ) + +iplang_l.o: $(TOP)/iplang/iplang_l.l + (cd $(TOP)/iplang; $(MAKE) 'DESTDIR=../IRIX/$(CPUDIR)' ) + +ipsend: $(IOBJS) $(UNIXOBJS) + $(CC) $(DEBUG) $(IOBJS) $(UNIXOBJS) -o $@ $(LIBS) -ll + +ipresend: $(ROBJS) $(UNIXOBJS) + $(CC) $(DEBUG) $(ROBJS) $(UNIXOBJS) -o $@ $(LIBS) + +iptest: $(TOBJS) $(UNIXOBJS) + $(CC) $(DEBUG) $(TOBJS) $(UNIXOBJS) -o $@ $(LIBS) + +clean: + rm -rf *.o core a.out ipsend ipresend iptest + rm -rf iplany_y.c iplang_l.c iplang_y.h iplang_y.c + +ipsend.o: $(TOP)/ipsend/ipsend.c + $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/ipsend.c -o $@ + +ipsopt.o: $(TOP)/ipsend/ipsopt.c + $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/ipsopt.c -o $@ + +ipresend.o: $(TOP)/ipsend/ipresend.c + $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/ipresend.c -o $@ + +ip.o: $(TOP)/ipsend/ip.c + $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/ip.c -o $@ + +resend.o: $(TOP)/ipsend/resend.c + $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/resend.c -o $@ + +iptest.o: $(TOP)/ipsend/iptest.c + $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/iptest.c -o $@ + +iptests.o: $(TOP)/ipsend/iptests.c + $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/iptests.c -o $@ + +sock.o: $(TOP)/ipsend/sock.c + $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/sock.c -o $@ + +arp.o: $(TOP)/ipsend/arp.c + $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/arp.c -o $@ + +sirix.o: $(TOP)/ipsend/sirix.c + $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/sirix.c -o $@ diff --git a/ipsd/ipsd.sed b/IRIX/Makefile.ipsend.std index e69de29bb2d1d..e69de29bb2d1d 100644 --- a/ipsd/ipsd.sed +++ b/IRIX/Makefile.ipsend.std diff --git a/IRIX/Makefile.std b/IRIX/Makefile.std new file mode 100644 index 0000000000000..5c9e3cf1b1e66 --- /dev/null +++ b/IRIX/Makefile.std @@ -0,0 +1,66 @@ +#!smake +# +# Copyright (C) 2012 by Darren Reed. +# Copyright (C) 1997 by Marc Boucher. +# +# Redistribution and use in source and binary forms are permitted +# provided that this notice is preserved and due credit is given +# to the original authors and the contributors. +# +# For IRIX +# +# Automatically determine compiler switches and defines for kernel compilation +# based on our current CPU: +# +DCPU=`uname -m` +KFLAGS=`$(TOP)/IRIX/getkflags` +# +BINDEST=/usr/sbin +SBINDEST=/sbin +MANDIR=/usr/share/man/local +INCDEST=/usr/include/netinet +LKMDEST=/var/sysgen/boot +HERE=IRIX/$(CPUDIR) +CPUDIR=`uname -s|sed -e 's@/@@g'`-`uname -r`-`uname -m` +RANLIB=echo +AROPTS=crs +OBJ=. +DEST=. +TOP=.. +TOOL=$(TOP)/tools +LIBS=-L. -lipf +#CC=cc -Wall -Wuninitialized -Wstrict-prototypes -Werror -O +CFLAGS=-g -I$(TOP) +# +ML=mli_ipl.c +MLD=$(ML) +#if defined(IPFLKM) && !empty(IPFLKM) +MLFLAGS= -G 0 +LKM=ipflkm.o +#else +MLFLAGS= -G 8 +LKM=ipfilter.o +#endif +MFLAGS="BINDEST=$(BINDEST)" "SBINDEST=$(SBINDEST)" "MANDIR=$(MANDIR)" \ + 'CFLAGS=$(CFLAGS) $(SOLARIS2)' "IPFLKM=$(IPFLKM)" \ + "IPFLOG=$(IPFLOG)" "LOGFAC=$(LOGFAC)" "POLICY=$(POLICY)" \ + "SOLARIS2=$(SOLARIS2)" "DEBUG=$(DEBUG)" "DCPU=$(CPU)" \ + "CPUDIR=$(CPUDIR)" "LOOKUP=$(LOOKUP)" +# +CCARGS=-D_STANDALONE $(DEBUG) $(CFLAGS) -D_KMEMUSER -DIPFILTER_LOG +# +########## ########## ########## ########## ########## ########## ########## +# +CP=/bin/cp +RM=/bin/rm +CHMOD=/bin/chmod +INSTALL=/sbin/install +LIBSRC=$(TOP)/lib +# +DFLAGS=$(IPFLKM) $(IPFLOG) $(KFLAGS) $(MLFLAGS) -jalr #-D_MP_NETLOCKS -DMP \ + $(LOOKUP) + +include $(TOP)/lib/Makefile + +include Makefile.common + diff --git a/IRIX/cpurev b/IRIX/cpurev new file mode 100755 index 0000000000000..0f5b322e46bcd --- /dev/null +++ b/IRIX/cpurev @@ -0,0 +1,10 @@ +#!/bin/sh +rev=`uname -R 2>/dev/null` +if [ $? -eq 0 ] ; then + rev=`echo $rev | awk ' { print $NF; } ' -` +else + rev=`uname -r` +fi +model=`uname -m|sed -e 's!/!.!'` +echo $rev.$model +exit 0 diff --git a/test/expected/expected.sed b/IRIX/getkflags index e69de29bb2d1d..e69de29bb2d1d 100644..100755 --- a/test/expected/expected.sed +++ b/IRIX/getkflags diff --git a/IRIX/getrev b/IRIX/getrev new file mode 100755 index 0000000000000..69b5f6556c2f0 --- /dev/null +++ b/IRIX/getrev @@ -0,0 +1,13 @@ +#!/bin/sh +uname -R 2>/dev/null >/dev/null +if [ $? -eq 0 ] ; then + osrev=`uname -R| awk ' { print $NF; } ' -` + sub=`expr $osrev : '[0-9]*\.[0-9]*\.\([0-9]*\).*'` +else + osrev=`uname -r` + sub=0 +fi +major=`expr $osrev : '\([0-9]\)\..*'` +minor=`expr $osrev : '[0-9]*\.\([0-9]*\).*'` +printf '%d%02d%02d' $major $minor $sub +exit 0 diff --git a/IRIX/ipfboot b/IRIX/ipfboot new file mode 100644 index 0000000000000..e5ad146436702 --- /dev/null +++ b/IRIX/ipfboot @@ -0,0 +1,85 @@ +#!/bin/sh +# +# Major device number definition from /dev/MAKEDEV: +C_IPL=79 # IP packet filtering device +# +PATH=/sbin:/usr/etc:/usr/sbin:${PATH} +if [ -r /var/sysgen/boot/ipflkm.o ]; then + ipflkm=true +else + ipflkm=false +fi +id=`ml list | grep ipl | awk ' { print $2; } ' -` +pid=`ps -e | grep ipmon | awk ' { print $1 } ' -` + +IPFILCONF=/etc/ipf.conf +IPNATCONF=/etc/ipnat.conf + +case "$1" in + start) + if [ x$pid != x ] ; then + kill -TERM $pid + fi + if [ x$id != x ] ; then + /sbin/ml unld $id + fi + if ${ipflkm}; then + /sbin/ml ld -v -c /var/sysgen/boot/ipflkm.o -p ipl -s $C_IPL + fi + (cd /dev && rm -f ipf ipl ipnat ipstate ipauth) + (cd /dev && rm -f ipsync ipscan iplookup) + mknod /dev/ipf c $C_IPL 0 + mknod /dev/ipl c $C_IPL 0 + mknod /dev/ipnat c $C_IPL 1 + mknod /dev/ipstate c $C_IPL 2 + mknod /dev/ipauth c $C_IPL 3 + mknod /dev/ipsync c $C_IPL 4 + mknod /dev/ipscan c $C_IPL 5 + mknod /dev/iplookup c $C_IPL 7 + (cd /dev && chmod 600 ipf ipl ipnat ipstate ipauth) + (cd /dev && chmod 600 ipsync ipscan iplookup) + ipf -E + [ -r ${IPFILCONF} ] && ipf -Fa -f ${IPFILCONF} + [ -r ${IPNATCONF} ] && ipnat -CF -f ${IPNATCONF} + ipmon -sn </dev/null >/dev/null 2>&1 & + ;; + + stop) + if [ "x$pid" != "x" ] ; then + kill -TERM $pid + fi + if ${ipflkm}; then + if [ x$id != x ] ; then + /sbin/ml unld $id && \ + (cd /dev && rm -f ipf ipl ipnat ipstate ipauth) + (cd /dev && rm -f ipsync ipscan iplookup) + fi + else + ipf -D + fi + ;; + + reload) + if [ -r ${IPFILCONF} ]; then + ipf -I -Fa -f ${IPFILCONF} + if [ $? != 0 ]; then + echo "$0: reload of ${IPFILCONF} into alternate set failed" + else + ipf -s + fi + fi + if [ -r ${IPNATCONF} ]; then + ipnat -CF -f ${IPNATCONF} + if [ $? != 0 ]; then + echo "$0: reload of ${IPNATCONF} failed" + fi + fi + ;; + + *) + echo "Usage: $0 (start|stop|reload)" >&2 + exit 1 + ;; + +esac +exit 0 diff --git a/IRIX/ipl b/IRIX/ipl new file mode 100644 index 0000000000000..b461e85134202 --- /dev/null +++ b/IRIX/ipl @@ -0,0 +1,3 @@ +*FLAG PREFIX SOFT #DEV DEPENDENCIES +codns ipl 79 - +$$$ diff --git a/Linux/Makefile b/Linux/Makefile new file mode 100644 index 0000000000000..033b5cb25ff77 --- /dev/null +++ b/Linux/Makefile @@ -0,0 +1,540 @@ +# +# Copyright (C) 2012 by Darren Reed. +# +# See the IPFILTER.LICENCE file for details on licencing. +# +#gcc -D__KERNEL__ -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 +#-fomit-frame-pointer -fno-strength-reduce -pipe -m486 -malign-loops=2 +#-malign-jumps=2 -malign-functions=2 -DCPU=586 -c -o ip_input.o ip_input.c + +SPECFILE=ipfilter.spec +ROOTDIR=/usr/src/redhat/BUILD/ipfilter/ +BINDEST=/usr/bin +SBINDEST=/sbin +MANDIR=/usr/share/man +#CC=cc -Wall -Wuninitialized -Wstrict-prototypes -Werror -O +CFLAGS=-g -I$(TOP) +# +# For Linux +# +CPUTYPE:=`uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/` +ARCH:=$(shell uname -i) +OBJ=. +TOP=.. +TOOL=$(TOP)/tools +CPU:=$(shell uname -i) +KREV:=$(shell uname -r) +MODEXT:=$(shell modprobe -l | head -n 1 | sed -e 's/.*\.\([^\.]*\)$$/\1/') +MODDIR=/lib/modules/$(KREV) +IPV4DIR=$(MODDIR)/kernel/net/ipv4/ +CPUDIR=$(shell uname -s|sed -e 's@/@@g')-$(KREV)-$(ARCH) +HERE=Linux +#LEXLIB=-ll +DEST=$(OBJ) +DEBUG=-g +LINUXKERNEL=/usr/src/linux +LIBS=-L$(OBJ) -lipf $(LIBBPF) +INC=-nostdinc -I$(TOP) -I$(LINUXKERNEL)/include/ +DEF=-D$(CPU) -D__$(CPU)__ -DINET -D__KERNEL__ -DCONFIG_NETFILTER -DMODULE +KCFLAGS=-Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -Wno-trigraphs \ + -fno-strict-aliasing -fno-common -DLINUX=$(LINUX) -I/usr/src/linux/asm/${mcore} +IPDEF=$(DEF) -DGATEWAY -DDIRECTED_BROADCAST +IPFILC=ip_lfil.c +XCFLAGS=-DLINUX=$(LINUX) -I.. -I`pwd`/.. -I`pwd`/../.. $(LOOKUP) $(XID) $(IPFLOG) -O2 +EXTRA_CFLAGS += $(XCFLAGS) +# +MFLAGS="BINDEST=$(BINDEST)" "SBINDEST=$(SBINDEST)" "MANDIR=$(MANDIR)" \ + 'CFLAGS=$(CFLAGS)' "IPFLKM=$(IPFLKM)" \ + "IPFLOG=$(IPFLOG)" "LOGFAC=$(LOGFAC)" "POLICY=$(POLICY)" \ + "DEBUG=$(DEBUG)" "DCPU=$(CPU)" "CPUDIR=$(CPUDIR)" +# +########## ########## ########## ########## ########## ########## ########## +# +CP=/bin/cp +RM=/bin/rm +CHMOD=/bin/chmod +INSTALL=install +INSTALL=$(TOP)/bsdinstall +LIBSRC=$(TOP)/lib +RANLIB=ranlib +AROPTS=crs +# +MODOBJS=$(OBJ)/linux.o $(OBJ)/ip_fil.o $(OBJ)/fil.o $(OBJ)/ip_nat.o \ + $(OBJ)/ip_frag.o $(OBJ)/ip_scan.o $(OBJ)/ip_sync.o $(OBJ)/ip_nat6.o \ + $(OBJ)/ip_state.o $(OBJ)/ip_proxy.o $(OBJ)/ip_auth.o \ + $(OBJ)/ip_lookup.o $(OBJ)/ip_pool.o $(OBJ)/ip_htable.o \ + $(OBJ)/ip_dstlist.o $(OBJ)/ip_log.o $(OBJ)/radix_ipf.o $(OBJ)/md5.o +KCCARGS=$(KCFLAGS) -D_BSD_SOURCE=1 $(IPFLKM) $(DEF) $(DLKM) -march=$(ARCH) \ + $(INC) -iwithprefix include -I. $(LOOKUP) $(XID) $(IPFLOG) +IPF=$(OBJ)/ipf.o $(OBJ)/ipfcomp.o $(OBJ)/ipf_y.o $(OBJ)/ipf_l.o +IPT=$(OBJ)/ipftest.o $(OBJ)/ip_fil_u.o $(OBJ)/ip_state_u.o \ + $(OBJ)/ip_frag_u.o $(OBJ)/ip_nat_u.o $(OBJ)/fil_u.o $(OBJ)/ip_nat6_u.o \ + $(OBJ)/ip_pool_u.o $(OBJ)/ip_htable_u.o $(OBJ)/ip_lookup_u.o \ + $(OBJ)/ip_proxy_u.o $(OBJ)/ip_auth_u.o $(OBJ)/ip_log_u.o \ + $(OBJ)/ippool_y.o $(OBJ)/ippool_l.o $(OBJ)/ipnat_y.o $(OBJ)/ipnat_l.o \ + $(OBJ)/ipf_y.o $(OBJ)/ipf_l.o $(OBJ)/radix_ipf_u.o $(OBJ)/md5_u.o \ + $(OBJ)/ip_dstlist_u.o $(OBJ)/ip_scan_u.o $(OBJ)/ip_sync_u.o +# $(OBJ)/ip_trafcon_u.o +IPNAT=$(OBJ)/ipnat.o $(OBJ)/ipnat_y.o $(OBJ)/ipnat_l.o +IPMON=$(OBJ)/ipmon.o $(OBJ)/ipmon_y.o $(OBJ)/ipmon_l.o +IPPOOL=$(OBJ)/ippool_y.o $(OBJ)/ippool_l.o $(OBJ)/kmem.o $(OBJ)/ippool.o +IPTRAFCON=$(OBJ)/iptrafcon.o +FILS=$(OBJ)/ipfstat.o +# +CCARGS=-I. -I$(CPUDIR) $(DEBUG) $(CFLAGS) $(LOOKUP) $(XID) $(IPFLOG) -DLINUX=$(LINUX) +EXTRA=-DIPFILTER_LOG -DIPFILTER_LOOKUP + +include $(TOP)/lib/Makefile + +$(OBJ): + @if [ ! -d $(OBJ) ] ; then \ + mkdir $(OBJ) ; \ + if [ $(LINUX) -ge 20600 ] ; then \ + ln -s ../Makefile.kbuild $(OBJ)/Makefile ; \ + fi ; \ + ln -s ../Makefile.ipsend $(OBJ) ; \ + fi + +build all: $(OBJ) $(OBJ)/ipf $(OBJ)/ipfs $(OBJ)/ipfstat $(OBJ)/ipftest \ + $(OBJ)/ipmon $(OBJ)/ipnat $(OBJ)/ippool + -sh -c 'for i in ipf ipftest ipmon ippool ipnat ipscan ipsyncm ipsyncs; do /bin/rm -f $(TOP)/$$i; ln -s `pwd`/$(OBJ)/$$i $(TOP); done' + +ipflkm: + if [ $(LINUX) -lt 20499 ] ; then \ + make $(OBJ)/ipfilter.o; \ + else \ + (cd $(OBJ); pwd; unset MAKEFLAGS; make -C "$(MODDIR)/build" SUBDIRS="`pwd`" TOP="../.." CPUDIR="$(CPUDIR)" EXTRA_CFLAGS="$(EXTRA_CFLAGS)" OBJ= modules); \ + fi + +$(OBJ)/ipfstat: $(FILS) $(OBJ)/libipf.a $(TOP)/ip_fil.h $(TOP)/ipf.h \ + $(TOP)/ip_frag.h $(TOP)/ip_compat.h $(TOP)/ip_state.h \ + $(TOP)/ip_nat.h + -if [ ! -f /usr/lib/libelf.so ] ; then \ + (cd /usr/lib; a=`echo libelf.so.*|head -n 1`; \ + if [ "$$a" != "" ] ; then ln -s $$a libelf.so; fi) \ + fi + $(CC) $(CCARGS) $(FILS) -o $@ -lelf $(LIBS) $(STATETOP_LIB) + +$(OBJ)/ipf: $(IPF) $(OBJ)/libipf.a + $(CC) $(CCARGS) $(IPF) -o $@ $(LIBS) $(LEXLIB) $(LIBBPF) + +$(OBJ)/ipftest: $(IPT) $(OBJ)/libipf.a + $(CC) $(CCARGS) $(IPT) -o $@ $(LIBS) $(LEXLIB) $(LIBBPF) + /bin/rm -f $(TOP)/ipftest + ln -s `pwd`/ipftest $(TOP) + +$(OBJ)/ipnat: $(IPNAT) $(OBJ)/libipf.a + -if [ ! -f /usr/lib/libelf.so ] ; then \ + (cd /usr/lib; a=`echo libelf.so.*|head -n 1`; \ + if [ "$$a" != "" ] ; then ln -s $$a libelf.so; fi) \ + fi + $(CC) $(CCARGS) $(IPNAT) -o $@ $(LIBS) -lelf $(LEXLIB) + +$(OBJ)/ipfs: $(OBJ)/ipfs.o $(OBJ)/libipf.a + $(CC) $(CCARGS) $(OBJ)/ipfs.o -o $@ $(LIBS) + +$(OBJ)/ipsyncm: ipsyncm.o $(OBJ)/libipf.a + $(CC) $(CCARGS) ipsyncm.o -o $@ + +$(OBJ)/ipsyncs: ipsyncs.o $(OBJ)/ibipf.a + $(CC) $(CCARGS) ipsyncs.o -o $@ + +tests: + (cd test; make ) + +$(OBJ)/ipfstat.o: $(TOOL)/ipfstat.c $(TOP)/ip_fil.h $(TOP)/ipf.h + $(CC) $(CCARGS) $(STATETOP_CFLAGS) -c $(TOOL)/ipfstat.c -o $@ + +$(OBJ)/ipfs.o: $(TOOL)/ipfs.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_state.h \ + $(TOP)/ip_nat.h + $(CC) $(CCARGS) -c $(TOOL)/ipfs.c -o $@ + +$(OBJ)/fil_u.o: $(TOP)/fil.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(IPFBPF) -c $(TOP)/fil.c -o $@ + +$(OBJ)/fil.o: fil.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_compat.h ipf-linux.h + $(CC) $(KCCARGS) $(POLICY) $(IPFBPF) -c fil.c -o $@ + +fil.c: $(TOP)/fil.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +$(OBJ)/ipf.o: $(TOOL)/ipf.c $(TOP)/ip_fil.h $(TOP)/ipf.h + $(CC) $(CCARGS) -c $(TOOL)/ipf.c -o $@ + +$(OBJ)/ipfcomp.o: $(TOOL)/ipfcomp.c $(TOP)/ip_fil.h $(TOP)/ipf.h + $(CC) $(CCARGS) -c $(TOOL)/ipfcomp.c -o $@ + +$(OBJ)/ipf_y.o: $(OBJ)/ipf_y.c $(TOP)/ip_fil.h $(TOP)/ipf.h \ + $(OBJ)/ipf_y.h $(OBJ)/ipf_l.h + $(CC) $(CCARGS) $(IPFBPF) -c $(OBJ)/ipf_y.c -o $@ + +$(OBJ)/ipf_l.o: $(OBJ)/ipf_l.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(OBJ)/ipf_y.h \ + $(OBJ)/ipf_l.h + $(CC) $(CCARGS) -I. -I$(TOP)/tools -c $(OBJ)/ipf_l.c -o $@ + +$(OBJ)/ipf_y.h $(OBJ)/ipf_y.c: $(TOOL)/ipf_y.y $(TOP)/ipf.h $(TOP)/ip_fil.h + (cd $(TOOL); make "DEST=../$(HERE)/$(OBJ)" ../$(HERE)/$@) + mv $(OBJ)/ipf_y.c $(OBJ)/ipf_y.c.NP + sed -e 's/int ipf_yygrowstack();/int ipf_yygrowstack(void);/' \ + $(OBJ)/ipf_y.c.NP > $(OBJ)/ipf_y.c + +$(OBJ)/ipf_l.c: $(TOOL)/lexer.c $(TOP)/ipf.h $(TOP)/ip_fil.h + (cd $(TOOL); make "DEST=../$(HERE)/$(OBJ)" ../$(HERE)/$@) + +$(OBJ)/ipf_l.h: $(TOOL)/lexer.h + (cd $(TOOL); make "DEST=../$(HERE)/$(OBJ)" ../$(HERE)/$@) + +$(OBJ)/ippool_y.o: $(OBJ)/ippool_y.c $(TOP)/ip_fil.h $(TOP)/ipf.h \ + $(OBJ)/ippool_y.h $(OBJ)/ippool_l.h + $(CC) $(CCARGS) -c $(OBJ)/ippool_y.c -o $@ + +$(OBJ)/ippool_l.o: $(OBJ)/ippool_l.c $(TOP)/ip_fil.h $(TOP)/ipf.h \ + $(OBJ)/ippool_y.h $(OBJ)/ippool_l.h + $(CC) $(CCARGS) -I. -I$(TOP)/tools -c $(OBJ)/ippool_l.c -o $@ + +$(OBJ)/ippool_y.h $(OBJ)/ippool_y.c: $(TOOL)/ippool_y.y $(TOP)/ipf.h \ + $(TOP)/ip_fil.h + (cd $(TOOL); make "DEST=../$(HERE)/$(OBJ)" ../$(HERE)/$@) + mv $(OBJ)/ippool_y.c $(OBJ)/ippool_y.c.NP + sed -e 's/int ippool_yygrowstack();/int ippool_yygrowstack(void);/' \ + $(OBJ)/ippool_y.c.NP > $(OBJ)/ippool_y.c + +$(OBJ)/ippool_l.c: $(TOOL)/lexer.c $(TOP)/ipf.h $(TOP)/ip_fil.h + (cd $(TOOL); make "DEST=../$(HERE)/$(OBJ)" ../$(HERE)/$@) + +$(OBJ)/ippool_l.h: $(TOOL)/lexer.h + (cd $(TOOL); make "DEST=../$(HERE)/$(OBJ)" ../$(HERE)/$@) + +$(OBJ)/ippool.o: $(TOOL)/ippool.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_pool.h + $(CC) $(CCARGS) -c $(TOOL)/ippool.c -o $@ + +$(OBJ)/ippool: $(IPPOOL) $(OBJ)/libipf.a + $(CC) $(CCARGS) $(IPPOOL) -o $@ $(LIBS) -lelf $(LEXLIB) + +$(OBJ)/ipnat_y.o: $(OBJ)/ipnat_y.c $(TOP)/ip_fil.h $(TOP)/ipf.h \ + $(OBJ)/ipnat_y.h $(OBJ)/ipnat_l.h + $(CC) $(CCARGS) -c $(OBJ)/ipnat_y.c -o $@ + +$(OBJ)/ipnat_l.o: $(OBJ)/ipnat_l.c $(TOP)/ip_fil.h $(TOP)/ipf.h \ + $(OBJ)/ipnat_y.h $(OBJ)/ipnat_l.h + $(CC) $(CCARGS) -I. -I$(TOP)/tools -c $(OBJ)/ipnat_l.c -o $@ + +$(OBJ)/ipnat_y.h $(OBJ)/ipnat_y.c: $(TOOL)/ipnat_y.y $(TOP)/ipf.h \ + $(TOP)/ip_fil.h + (cd $(TOOL); make "DEST=../$(HERE)/$(OBJ)" ../$(HERE)/$@) + mv $(OBJ)/ipnat_y.c $(OBJ)/ipnat_y.c.NP + sed -e 's/int ipnat_yygrowstack();/int ipnat_yygrowstack(void);/' \ + $(OBJ)/ipnat_y.c.NP > $(OBJ)/ipnat_y.c + +$(OBJ)/ipnat_l.c: $(TOOL)/lexer.c $(TOP)/ipf.h $(TOP)/ip_fil.h + (cd $(TOOL); make "DEST=../$(HERE)/$(OBJ)" ../$(HERE)/$@) + +$(OBJ)/ipnat_l.h: $(TOOL)/lexer.h + (cd $(TOOL); make "DEST=../$(HERE)/$(OBJ)" ../$(HERE)/$@) + +$(OBJ)/ipftest.o: $(TOOL)/ipftest.c $(TOP)/ip_fil.h $(TOP)/ipt.h $(TOP)/ipf.h + $(CC) $(CCARGS) -c $(TOOL)/ipftest.c -o $@ + +$(OBJ)/ipnat.o: $(TOOL)/ipnat.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_nat.h + $(CC) $(CCARGS) -c $(TOOL)/ipnat.c -o $@ + +$(OBJ)/md5_u.o: $(TOP)/md5.c $(TOP)/md5.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/md5.c -o $@ + +$(OBJ)/radix_ipf_u.o: $(TOP)/radix_ipf.c $(TOP)/radix_ipf.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/radix_ipf.c -o $@ + +$(OBJ)/ip_nat_u.o: $(TOP)/ip_nat.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h + $(CC) $(CCARGS) -c $(TOP)/ip_nat.c -o $@ + +$(OBJ)/ip_nat6_u.o: $(TOP)/ip_nat6.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h + $(CC) $(CCARGS) -c $(TOP)/ip_nat6.c -o $@ + +$(OBJ)/ip_proxy_u.o: $(TOP)/ip_proxy.c $(TOP)/ip_proxy.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h + $(CC) $(CCARGS) -c $(TOP)/ip_proxy.c -o $@ + +$(OBJ)/ip_frag_u.o: $(TOP)/ip_frag.c $(TOP)/ip_frag.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h + $(CC) $(CCARGS) -c $(TOP)/ip_frag.c -o $@ + +$(OBJ)/ip_scan_u.o: $(TOP)/ip_scan.c $(TOP)/ip_scan.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h + $(CC) $(CCARGS) -c $(TOP)/ip_scan.c -o $@ + +$(OBJ)/ip_sync_u.o: $(TOP)/ip_sync.c $(TOP)/ip_sync.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h + $(CC) $(CCARGS) -c $(TOP)/ip_sync.c -o $@ + +$(OBJ)/ip_state_u.o: $(TOP)/ip_state.c $(TOP)/ip_state.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(TOP)/ip_nat.h + $(CC) $(CCARGS) -c $(TOP)/ip_state.c -o $@ + +$(OBJ)/ip_auth_u.o: $(TOP)/ip_auth.c $(TOP)/ip_auth.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h + $(CC) $(CCARGS) -c $(TOP)/ip_auth.c -o $@ + +$(OBJ)/ip_pool_u.o: $(TOP)/ip_pool.c $(TOP)/ip_pool.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h + $(CC) $(CCARGS) -c $(TOP)/ip_pool.c -o $@ + +$(OBJ)/ip_htable_u.o: $(TOP)/ip_htable.c $(TOP)/ip_htable.h \ + $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(CCARGS) -c $(TOP)/ip_htable.c -o $@ + +$(OBJ)/ip_dstlist_u.o: $(TOP)/ip_dstlist.c $(TOP)/ip_dstlist.h \ + $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(CCARGS) -c $(TOP)/ip_dstlist.c -o $@ + +$(OBJ)/ip_lookup_u.o: $(TOP)/ip_lookup.c $(TOP)/ip_lookup.h \ + $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(CCARGS) -c $(TOP)/ip_lookup.c -o $@ + +$(OBJ)/ip_fil_u.o: $(TOP)/ip_fil.c $(TOP)/ip_fil.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) -c $(TOP)/ip_fil.c -o $@ + +$(OBJ)/ip_log_u.o: $(TOP)/ip_log.c $(TOP)/ip_fil.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) -c $(TOP)/ip_log.c -o $@ + +$(OBJ)/ipfilter.o: $(MODOBJS) + ld -r $(MODOBJS) -o $(OBJ)/ipfilter.o + ${RM} -f $(OBJ)/ipfilter + +$(OBJ)/ip_nat.o: ip_nat.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h ipf-linux.h + $(CC) $(KCCARGS) -c ip_nat.c -o $@ + +$(OBJ)/ip_nat6.o: ip_nat6.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h ipf-linux.h + $(CC) $(KCCARGS) -c ip_nat6.c -o $@ + +ip_nat.c: $(TOP)/ip_nat.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +$(OBJ)/ip_frag.o: ip_frag.c $(TOP)/ip_frag.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h ipf-linux.h + $(CC) $(KCCARGS) -c ip_frag.c -o $@ + +ip_frag.c: $(TOP)/ip_frag.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +$(OBJ)/ip_state.o: ip_state.c $(TOP)/ip_state.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(TOP)/ip_nat.h ipf-linux.h + $(CC) $(KCCARGS) -c ip_state.c -o $@ + +ip_state.c: $(TOP)/ip_state.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +$(OBJ)/ip_proxy.o: ip_proxy.c $(TOP)/ip_proxy.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h ipf-linux.h + $(CC) $(KCCARGS) -c ip_proxy.c -o $@ + +ip_proxy.c: $(TOP)/ip_proxy.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +$(OBJ)/ip_auth.o: ip_auth.c $(TOP)/ip_auth.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h ipf-linux.h + $(CC) $(KCCARGS) -c ip_auth.c -o $@ + +ip_auth.c: $(TOP)/ip_auth.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +$(OBJ)/ip_lookup.o: ip_lookup.c $(TOP)/ip_lookup.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h ipf-linux.h + $(CC) $(KCCARGS) -c ip_lookup.c -o $@ + +ip_lookup.c: $(TOP)/ip_lookup.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +$(OBJ)/ip_htable.o: ip_htable.c $(TOP)/ip_htable.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h ipf-linux.h + $(CC) $(KCCARGS) -c ip_htable.c -o $@ + +ip_htable.c: $(TOP)/ip_htable.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +$(OBJ)/ip_dstlist.o: ip_dstlist.c $(TOP)/ip_dstlist.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h ipf-linux.h + $(CC) $(KCCARGS) -c ip_dstlist.c -o $@ + +ip_dstlist.c: $(TOP)/ip_dstlist.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +$(OBJ)/ip_pool.o: ip_pool.c $(TOP)/ip_pool.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h ipf-linux.h + $(CC) $(KCCARGS) -c ip_pool.c -o $@ + +ip_pool.c: $(TOP)/ip_pool.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +$(OBJ)/ip_scan.o: ip_scan.c $(TOP)/ip_scan.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h ipf-linux.h + $(CC) $(KCCARGS) -c ip_scan.c -o $@ + +ip_scan.c: $(TOP)/ip_scan.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +$(OBJ)/ip_sync.o: ip_sync.c $(TOP)/ip_sync.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h ipf-linux.h + $(CC) $(KCCARGS) -c ip_sync.c -o $@ + +ip_sync.c: $(TOP)/ip_sync.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +$(OBJ)/ip_log.o: ip_log.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h ipf-linux.h + $(CC) $(KCCARGS) -c ip_log.c -o $@ + +ip_log.c: $(TOP)/ip_log.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +$(OBJ)/radix_ipf.o: radix_ipf.c $(TOP)/radix_ipf.h ipf-linux.h + $(CC) $(KCCARGS) -c radix_ipf.c -o $@ + +$(OBJ)/md5.o: $(TOP)/md5.c $(TOP)/md5.h + $(CC) $(KCCARGS) -c $(TOP)/md5.c -o $@ + +radix_ipf.c: $(TOP)/radix_ipf.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +ip_rules.c: $(TOP)/rules/ip_rules $(TOP)/tools/ipfcomp.o $(OBJ)/ipf + $(OBJ)/ipf -cc -nf $(TOP)/rules/ip_rules + +$(TOP)/ip_rules.h: ip_rules.c + if [ ! -f $(TOP)/ip_rules.h ] ; then \ + /bin/mv -f ip_rules.h $(TOP); \ + else \ + touch $(TOP)/ip_rules.h; \ + fi + +$(OBJ)/linux.o: $(TOP)/linux.c $(TOP)/radix_ipf.h ipf-linux.h + $(CC) $(KCCARGS) -DMODVERSIONS -D__GENKSYMS__ -DEXPORT_SYMTAB -c $(TOP)/linux.c -o $@ + +$(OBJ)/ip_fil.o: $(TOP)/ip_fil_linux.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + ipf-linux.h + $(CC) $(KCCARGS) -c $(TOP)/ip_fil_linux.c -o $@ + +$(OBJ)/ipmon: $(IPMON) $(OBJ)/libipf.a + $(CC) $(CCARGS) $(IPMON) -o $@ $(LIBS) $(LEXLIB) -ldl + +$(OBJ)/ipmon.o: $(TOOL)/ipmon.c $(TOP)/ipmon.h + $(CC) $(CCARGS) $(LOGFAC) -c $(TOOL)/ipmon.c -o $@ + +$(OBJ)/ipmon_y.o: $(OBJ)/ipmon_y.c $(TOP)/ip_fil.h $(TOP)/ipf.h \ + $(OBJ)/ipmon_y.h $(OBJ)/ipmon_l.h + $(CC) $(CCARGS) -c $(OBJ)/ipmon_y.c -o $@ + +$(OBJ)/ipmon_l.o: $(OBJ)/ipmon_l.c $(TOP)/ip_fil.h $(TOP)/ipf.h \ + $(OBJ)/ipmon_y.h $(OBJ)/ipmon_l.h + $(CC) $(CCARGS) -I. -I$(TOP)/tools -c $(OBJ)/ipmon_l.c -o $@ + +$(OBJ)/ipmon_y.h $(OBJ)/ipmon_y.c: $(TOOL)/ipmon_y.y $(TOP)/ipf.h \ + $(TOP)/ip_fil.h + (cd $(TOOL); make "DEST=../$(HERE)/$(OBJ)" ../$(HERE)/$@) + mv $(OBJ)/ipmon_y.c $(OBJ)/ipmon_y.c.NP + sed -e 's/int ipmon_yygrowstack();/int ipmon_yygrowstack(void);/' \ + $(OBJ)/ipmon_y.c.NP > $(OBJ)/ipmon_y.c + +$(OBJ)/ipmon_l.c: $(TOOL)/lexer.c $(TOP)/ipf.h $(TOP)/ip_fil.h + (cd $(TOOL); make "DEST=../$(HERE)/$(OBJ)" ../$(HERE)/$@) + +$(OBJ)/ipmon_l.h: $(TOOL)/lexer.h + (cd $(TOOL); make "DEST=../$(HERE)/$(OBJ)" ../$(HERE)/$@) + +clean: + ${RM} -f $(TOP)/ipf $(TOP)/ipnat $(TOP)/ipmon $(TOP)/ippool + ${RM} -f $(TOP)/ipftest $(TOP)/ipscan $(TOP)/ipsyncm $(TOP)/ipsyncs + ${RM} -f *.core *.o ipt fils ipf ipfstat ipftest ipmon ippool ipnat \ + ipfilter.o + ${RM} -f fil.c ip_auth.c ip_frag.c ip_htable.c ip_lookup.c ip_log.c + ${RM} -f ip_lookup.c ip_nat.c ip_pool.c ip_proxy.c ip_scan.c + ${RM} -f ip_state.c ip_sync.c radix_ipf.c ip_rules.c ip_rules.h + ${MAKE} -f Makefile.ipsend ${MFLAGS} clean + -(for i in Linux*; do \ + if [ -d $${i} ] ; then \ + /bin/rm -rf $${i}; \ + fi \ + done) + +install: $(CPUDIR)/$(SPECFILE) $(CPUDIR)/ipfilter + mkdir -p $(ROOTDIR) $(ROOTDIR)/usr/include/netinet + mkdir -p $(ROOTDIR)$(SBINDEST) $(ROOTDIR)$(BINDEST) + mkdir -p $(ROOTDIR)$(IPV4DIR) + mkdir -p $(ROOTDIR)/etc/init.d + mkdir -p $(ROOTDIR)/etc/sysconfig + mkdir -p $(ROOTDIR)$(MANDIR)/man1 + mkdir -p $(ROOTDIR)$(MANDIR)/man4 + mkdir -p $(ROOTDIR)$(MANDIR)/man5 + mkdir -p $(ROOTDIR)$(MANDIR)/man8 + mkdir -p $(ROOTDIR)/usr/share/ipfilter/examples + touch $(ROOTDIR)/etc/sysconfig/ipfilter + for i in fil nat compat state sync scan frag auth lookup pool htable proxy; do \ + $(CP) $(TOP)/ip_$$i.h $(ROOTDIR)/usr/include/netinet/ip_$$i.h; \ + $(CHMOD) 444 $(ROOTDIR)/usr/include/netinet/ip_$$i.h; \ + done + $(CP) $(TOP)/ipl.h $(ROOTDIR)/usr/include/netinet/ipl.h + -if [ -d $(IPV4DIR) ] ; then \ + if [ -f $(CPUDIR)/ipfilter.$(MODEXT) ] ; then \ + cp $(CPUDIR)/ipfilter.$(MODEXT) $(ROOTDIR)$(IPV4DIR)/ipfilter.$(MODEXT); \ + else \ + cp $(CPUDIR)/ipfilter.o $(ROOTDIR)$(IPV4DIR)/ipfilter.$(MODEXT); \ + fi \ + fi + (for i in ipfstat ipf ipnat ippool ipfs; do \ + (cd $(CPUDIR); ../$(INSTALL) -c -s -g wheel -m 755 -o root $$i $(ROOTDIR)$(SBINDEST)); \ + done;) + (for i in ipmon ipftest; do \ + (cd $(CPUDIR); ../$(INSTALL) -c -s -g wheel -m 755 -o root $$i $(ROOTDIR)$(BINDEST)); \ + done;) + (cd $(CPUDIR); ../$(INSTALL) -c -g wheel -m 755 -o root ipfilter $(ROOTDIR)/etc/init.d) + (cd $(TOP)/man; make INSTALL=../bsdinstall MANDIR=$(ROOTDIR)$(MANDIR) install; cd $(TOP)) + for i in BASIC_1.FW BASIC_2.FW BASIC.NAT example.1 example.2 \ + example.3 example.4 example.5 example.6 example.7 \ + example.8 example.9 example.10 example.11 example.12 \ + example.13 example.sr firewall ftp-proxy ftppxy ipmon.conf \ + ip_rules nat.eg nat-setup pool.conf server tcpstate; do \ + $(CP) $(TOP)/rules/$$i $(ROOTDIR)/usr/share/ipfilter/examples; \ + $(CHMOD) 444 $(ROOTDIR)/usr/share/ipfilter/examples/$$i; \ + chown root:root $(ROOTDIR)/usr/share/ipfilter/examples/$$i; \ + done + rpmbuild -bb $(CPUDIR)/$(SPECFILE) + rpm -i ipfilter + +$(CPUDIR)/$(SPECFILE): $(SPECFILE).dist + sed -e "s/KERNELBUILD/$(KREV)/" \ + -e "s/MODEXT/$(MODEXT)/" \ + -e "s/TURNONIPFILTER/`./howchkconfig`/" \ + $< > $@ + +$(CPUDIR)/ipfilter: + ./mkinit `pwd`/$(CPUDIR) + diff --git a/Linux/Makefile.ipsend b/Linux/Makefile.ipsend new file mode 100644 index 0000000000000..5dd7f345763d9 --- /dev/null +++ b/Linux/Makefile.ipsend @@ -0,0 +1,79 @@ +OBJS=ipsend.o ip.o ipsopt.o iplang_y.o iplang_l.o +IPFTO=ipft_ef.o ipft_hx.o ipft_pc.o ipft_sn.o ipft_td.o ipft_tx.o +ROBJS=ipresend.o ip.o resend.o $(IPFTO) opt.o +TOBJS=iptest.o iptests.o ip.o +UNIXOBJS=lsock.o slinux.o larp.o +INC=-I/usr/include -I/usr/src/linux/include + +CC=cc +#-Wuninitialized -Wstrict-prototypes -O +CFLAGS=-g -I$(TOP) +# +MFLAGS="BINDEST=$(BINDEST)" "SBINDEST=$(SBINDEST)" "MANDIR=$(MANDIR)" \ + 'CFLAGS=$(CFLAGS) $(SOLARIS2)' "IPFLKM=$(IPFLKM)" \ + "IPFLOG=$(IPFLOG)" "LOGFAC=$(LOGFAC)" "POLICY=$(POLICY)" \ + "SOLARIS2=$(SOLARIS2)" "DEBUG=$(DEBUG)" "DCPU=$(CPU)" \ + "CPUDIR=$(CPUDIR)" +# +all build bsd-bpf : ipsend ipresend iptest + +iplang_y.o: $(TOP)/iplang/iplang_y.y + (cd $(TOP)/iplang; $(MAKE) ../Linux/$(CPUDIR)/iplang_y.o $(MFLAGS) "LINUX=$(INC) $(LINUXK)" 'DESTDIR=../Linux/$(CPUDIR)' ) + +iplang_l.o: $(TOP)/iplang/iplang_l.l + (cd $(TOP)/iplang; $(MAKE) ../Linux/$(CPUDIR)/iplang_l.o $(MFLAGS) "LINUX=$(INC) $(LINUXK)" 'DESTDIR=../Linux/$(CPUDIR)' ) + +.c.o: + $(CC) $(DEBUG) $(CFLAGS) $(INC) $(LINUXK) -c $< -o $@ + +ipsend: $(OBJS) $(UNIXOBJS) + $(CC) $(DEBUG) $(OBJS) $(UNIXOBJS) -o $@ $(LIBS) -lfl -lelf + +ipresend: $(ROBJS) $(UNIXOBJS) + $(CC) $(DEBUG) $(ROBJS) $(UNIXOBJS) -o $@ $(LIBS) -lfl -lelf + +iptest: $(TOBJS) $(UNIXOBJS) + $(CC) $(DEBUG) $(TOBJS) $(UNIXOBJS) -o $@ $(LIBS) -lfl -lelf + +clean: + rm -rf $(TOBJS) $(OBJS) $(ROBJS) $(UNIXOBJS) core a.out ipsend ipresend iptest + +ipsend.o: $(TOP)/ipsend/ipsend.c + $(CC) $(DEBUG) $(CFLAGS) $(INC) $(LINUXK) -c $(TOP)/ipsend/ipsend.c -o $@ + +ipsopt.o: $(TOP)/ipsend/ipsopt.c + $(CC) $(DEBUG) $(CFLAGS) $(INC) $(LINUXK) -c $(TOP)/ipsend/ipsopt.c -o $@ + +ipresend.o: $(TOP)/ipsend/ipresend.c + $(CC) $(DEBUG) $(CFLAGS) $(INC) $(LINUXK) -c $(TOP)/ipsend/ipresend.c -o $@ + +ip.o: $(TOP)/ipsend/ip.c + $(CC) $(DEBUG) $(CFLAGS) $(INC) $(LINUXK) -c $(TOP)/ipsend/ip.c -o $@ + +resend.o: $(TOP)/ipsend/resend.c + $(CC) $(DEBUG) $(CFLAGS) $(INC) $(LINUXK) -c $(TOP)/ipsend/resend.c -o $@ + +ipft_sn.o: $(TOP)/ipft_sn.c + $(CC) $(DEBUG) $(CFLAGS) $(INC) $(LINUXK) -c $(TOP)/ipft_sn.c -o $@ + +ipft_pc.o: $(TOP)/ipft_pc.c + $(CC) $(DEBUG) $(CFLAGS) $(INC) $(LINUXK) -c $(TOP)/ipft_pc.c -o $@ + +iptest.o: $(TOP)/ipsend/iptest.c + $(CC) $(DEBUG) $(CFLAGS) $(INC) $(LINUXK) -c $(TOP)/ipsend/iptest.c -o $@ + +iptests.o: $(TOP)/ipsend/iptests.c + $(CC) $(DEBUG) $(CFLAGS) $(INC) $(LINUXK) -c $(TOP)/ipsend/iptests.c -o $@ + +lsock.o: $(TOP)/ipsend/lsock.c + $(CC) $(DEBUG) $(CFLAGS) $(INC) $(LINUXK) -c $(TOP)/ipsend/lsock.c -o $@ + +slinux.o: $(TOP)/ipsend/slinux.c + $(CC) $(DEBUG) $(CFLAGS) $(INC) $(LINUXK) -c $(TOP)/ipsend/slinux.c -o $@ + +larp.o: $(TOP)/ipsend/larp.c + $(CC) $(DEBUG) $(CFLAGS) $(INC) $(LINUXK) -c $(TOP)/ipsend/larp.c -o $@ + +install: + -$(INSTALL) -cs -g wheel -m 755 -o root ipsend ipresend iptest $(BINDEST) + diff --git a/Linux/Makefile.kbuild b/Linux/Makefile.kbuild new file mode 100644 index 0000000000000..bab8df0a99159 --- /dev/null +++ b/Linux/Makefile.kbuild @@ -0,0 +1,198 @@ +# +# Copyright (C) 2012 by Darren Reed. +# +# See the IPFILTER.LICENCE file for details on licencing. +# +CONFIG_IPFILTER=m +# +# For Linux +# +CPUTYPE:=$(shell uname -m | sed -e 's/i.86/i386/' -e 's/sun4u/sparc64/' -e 's/arm.*/arm/' -e 's/sa110/arm/') +ARCH:=$(shell uname -m | sed -e 's/i.86/i386/') +OBJ=. +TOP=../.. +CPU:=$(shell uname -i) +KREV:=$(shell uname -r) +MODDIR=/lib/modules/$(KREV) +IPV4DIR=$(MODDIR)/kernel/net/ipv4/ +CPUDIR= +DEBUG=-g +# +########## ########## ########## ########## ########## ########## ########## +# +# +MODOBJS=$(OBJ)/linuxm.o $(OBJ)/ip_film.o $(OBJ)/fil.o $(OBJ)/ip_nat.o \ + $(OBJ)/ip_frag.o $(OBJ)/ip_scan.o $(OBJ)/ip_sync.o \ + $(OBJ)/ip_state.o $(OBJ)/ip_proxy.o $(OBJ)/ip_auth.o \ + $(OBJ)/ip_lookup.o $(OBJ)/ip_pool.o $(OBJ)/ip_htable.o \ + $(OBJ)/ip_dstlist.o $(OBJ)/ip_log.o $(OBJ)/radix.o $(OBJ)/md5.o + +obj-$(CONFIG_IPFILTER) += ipfilter.o +ipfilter-objs =$(MODOBJS) + +all: ipflkm + +ipflkm: + if [ $(LINUX) -lt 20499 ] ; then \ + make $(OBJ)/ipfilter.o ; \ + else \ + make $(OBJ)/ipflkm.o ; \ + fi + +$(OBJ)/ipfilter.o: $(MODOBJS) + ld -r $(MODOBJS) -o $(OBJ)/ipfilter.o + ${RM} -f $(OBJ)/ipfilter + + +fil.c $(obj)//fil.c: $(TOP)/fil.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +ip_nat.c $(obj)//ip_nat.c: $(TOP)/ip_nat.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +ip_frag.c $(obj)//ip_frag.c: $(TOP)/ip_frag.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +ip_state.c $(obj)//ip_state.c: $(TOP)/ip_state.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +ip_proxy.c $(obj)//ip_proxy.c: $(TOP)/ip_proxy.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +ip_auth.c $(obj)//ip_auth.c: $(TOP)/ip_auth.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +ip_lookup.c $(obj)//ip_lookup.c: $(TOP)/ip_lookup.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +ip_htable.c $(obj)//ip_htable.c: $(TOP)/ip_htable.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +ip_dstlist.c $(obj)//ip_dstlist.c: $(TOP)/ip_dstlist.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +ip_pool.c $(obj)//ip_pool.c: $(TOP)/ip_pool.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +ip_scan.c $(obj)//ip_scan.c: $(TOP)/ip_scan.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +ip_sync.c $(obj)//ip_sync.c: $(TOP)/ip_sync.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +ip_log.c $(obj)//ip_log.c: $(TOP)/ip_log.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +radix.c $(obj)//radix.c: $(TOP)/radix.c Makefile + sed -e '/^#/,$$d' $< > $@ + echo '#include "ipf-linux.h"' >> $@ + sed -ne '/END OF INCLUDES/,$$p' $< >> $@ + +ip_rules.c: $(TOP)/rules/ip_rules $(TOP)/tools/ipfcomp.o $(OBJ)/ipf + $(OBJ)/ipf -cc -nf $(TOP)/rules/ip_rules + +md5.c $(obj)//md5.c: $(TOP)/md5.c Makefile + /bin/rm -f md5.c + cp $< $(obj)//md5.c + +$(TOP)/ip_rules.h: ip_rules.c + if [ ! -f $(TOP)/ip_rules.h ] ; then \ + /bin/mv -f ip_rules.h $(TOP); \ + else \ + touch $(TOP)/ip_rules.h; \ + fi + +$(OBJ)/ip_log.o: ip_log.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(obj)/../ipf-linux.h +$(obj)//linuxm.o: $(obj)/linuxm.c +$(obj)//fil.o: $(obj)/fil.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_compat.h \ + $(obj)/../ipf-linux.h +$(obj)//ip_auth.o: $(obj)/ip_auth.c $(TOP)/ip_auth.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(obj)/../ipf-linux.h +$(obj)//ip_film.o: $(obj)/ip_film.c +$(obj)//ip_frag.o: $(obj)/ip_frag.c $(TOP)/ip_frag.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(obj)/../ipf-linux.h +$(obj)//ip_htable.o: $(obj)/ip_htable.c $(TOP)/ip_htable.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(obj)/../ipf-linux.h +$(obj)//ip_dstlist.o: $(obj)/ip_dstlist.c $(TOP)/ip_dstlist.h \ + $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(obj)/../ipf-linux.h +$(obj)//ip_lookup.o: $(obj)/ip_lookup.c $(TOP)/ip_lookup.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(obj)/../ipf-linux.h +$(obj)//ip_nat.o: $(obj)/ip_nat.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(obj)/../ipf-linux.h +$(obj)//ip_pool.o: $(obj)/ip_pool.c $(TOP)/ip_pool.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(obj)/../ipf-linux.h +$(obj)//ip_proxy.o: $(obj)/ip_proxy.c $(TOP)/ip_proxy.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(obj)/../ipf-linux.h +$(obj)//ip_scan.o: $(obj)/ip_scan.c $(TOP)/ip_scan.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(obj)/../ipf-linux.h +$(obj)//ip_state.o: $(obj)/ip_state.c $(TOP)/ip_state.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(TOP)/ip_nat.h $(obj)/../ipf-linux.h +$(obj)//ip_sync.o: $(obj)/ip_sync.c $(TOP)/ip_sync.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(obj)/../ipf-linux.h +$(obj)//radix.o: $(obj)/radix.c $(TOP)/radix_ipf.h $(obj)/../ipf-linux.h +$(obj)//md5.o: md5.c $(TOP)/md5.h +$(obj)/$(CPUDIR)/linux.o: $(obj)/$(CPUDIR)/linux.c +$(obj)/$(CPUDIR)/fil.o: $(obj)/$(CPUDIR)/fil.c $(TOP)/ip_fil.h $(TOP)/ipf.h \ + $(TOP)/ip_compat.h $(obj)/../ipf-linux.h +$(obj)/$(CPUDIR)/ip_auth.o: $(obj)/$(CPUDIR)/ip_auth.c $(TOP)/ip_auth.h \ + $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(obj)/../ipf-linux.h +$(obj)/$(CPUDIR)/ip_film.o: $(obj)/$(CPUDIR)/ip_film.c +$(obj)/$(CPUDIR)/ip_frag.o: $(obj)/$(CPUDIR)/ip_frag.c $(TOP)/ip_frag.h \ + $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(obj)/../ipf-linux.h +$(obj)/$(CPUDIR)/ip_htable.o: $(obj)/$(CPUDIR)/ip_htable.c $(TOP)/ip_htable.h \ + $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(obj)/../ipf-linux.h +$(obj)/$(CPUDIR)/ip_dstlist.o: $(obj)/$(CPUDIR)/ip_dstlist.c \ + $(TOP)/ip_dstlist.h $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(obj)/../ipf-linux.h +$(obj)/$(CPUDIR)/ip_lookup.o: $(obj)/$(CPUDIR)/ip_lookup.c $(TOP)/ip_lookup.h \ + $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(obj)/../ipf-linux.h +$(obj)/$(CPUDIR)/ip_nat.o: $(obj)/$(CPUDIR)/ip_nat.c $(TOP)/ip_nat.h \ + $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(obj)/../ipf-linux.h +$(obj)/$(CPUDIR)/ip_pool.o: $(obj)/$(CPUDIR)/ip_pool.c $(TOP)/ip_pool.h \ + $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(obj)/../ipf-linux.h +$(obj)/$(CPUDIR)/ip_proxy.o: $(obj)/$(CPUDIR)/ip_proxy.c $(TOP)/ip_proxy.h \ + $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(obj)/../ipf-linux.h +$(obj)/$(CPUDIR)/ip_scan.o: $(obj)/$(CPUDIR)/ip_scan.c $(TOP)/ip_scan.h \ + $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(obj)/../ipf-linux.h +$(obj)/$(CPUDIR)/ip_state.o: $(obj)/$(CPUDIR)/ip_state.c $(TOP)/ip_state.h \ + $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(TOP)/ip_nat.h \ + $(obj)/../ipf-linux.h +$(obj)/$(CPUDIR)/ip_sync.o: $(obj)/$(CPUDIR)/ip_sync.c $(TOP)/ip_sync.h \ + $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(obj)/../ipf-linux.h +$(obj)/$(CPUDIR)/radix.o: $(obj)/$(CPUDIR)/radix.c $(TOP)/radix_ipf.h \ + ipf-linux.h +$(obj)/$(CPUDIR)/md5.o: md5.c $(TOP)/md5.h + +$(obj)/$(CPUDIR)/linuxm.c $(obj)//linuxm.c: $(TOP)/linux.c + @if [ ! -h $@ ] ; then ln -s $< $@; fi + +$(obj)/$(CPUDIR)/ip_film.c $(obj)//ip_film.c: $(TOP)/ip_fil_linux.c + @if [ ! -h $@ ] ; then ln -s $< $@; fi + diff --git a/Linux/Tips_SuSE91.txt b/Linux/Tips_SuSE91.txt new file mode 100644 index 0000000000000..ea338b8b8aa83 --- /dev/null +++ b/Linux/Tips_SuSE91.txt @@ -0,0 +1,5 @@ +cd /usr/src/linux +make mrproper +cp /boot/config-* .config +make oldconfig +make prepare-all diff --git a/Linux/howchkconfig b/Linux/howchkconfig new file mode 100755 index 0000000000000..3b2a5d3cb61c6 --- /dev/null +++ b/Linux/howchkconfig @@ -0,0 +1,8 @@ +#!/bin/sh +level=`/sbin/chkconfig --help 2>& 1 | grep level` +if [ "$level" = "" ] ; then + echo '-s ipfilter 2345' +else + echo '--level 2345 ipfilter on' +fi +exit 0 diff --git a/Linux/initscript b/Linux/initscript new file mode 100644 index 0000000000000..a9a3124c91cab --- /dev/null +++ b/Linux/initscript @@ -0,0 +1,8 @@ +#!/bin/sh +if [ -f /etc/SuSE-release ] ; then + echo ipfilter-suse +fi +if [ -f /etc/redhat-release ] ; then + echo ipfilter-redhat +fi +exit 0 diff --git a/Linux/ipf-linux.h b/Linux/ipf-linux.h new file mode 100644 index 0000000000000..08b1de9cf3503 --- /dev/null +++ b/Linux/ipf-linux.h @@ -0,0 +1,187 @@ +#ifndef __IPF_LINUX_H__ +#define __IPF_LINUX_H__ + +#include <linux/version.h> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) +# include <linux/autoconf.h> +# include <linux/poll.h> +#else +# include <linux/config.h> +#endif +#ifndef CONFIG_NETFILTER +# define CONFIG_NETFILTER +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +# define __irq_h 1 /* stop it being included! */ +# include <linux/mtd/compatmac.h> +#else +# include <linux/compatmac.h> +# include <linux/version.h> +#endif +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/types.h> +#include <linux/time.h> +#include <linux/string.h> +#include <linux/slab.h> +#include <linux/socket.h> +#include <linux/netdevice.h> +#include <linux/inetdevice.h> +#include <linux/skbuff.h> +#include <linux/in.h> +#include <linux/ip.h> +#include <net/ip.h> /* IP_DF */ +#include <linux/icmp.h> +#include <linux/rtnetlink.h> +#include <linux/netfilter.h> +#include <linux/netfilter_ipv4.h> +#include <linux/netfilter_ipv6.h> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +# include <asm/ioctls.h> +#else +# define ipftcphdr tcphdr +# define ipfudphdr udphdr +#endif + +struct ipftcphdr { + __u16 th_sport; + __u16 th_dport; + __u32 th_seq; + __u32 th_ack; +# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\ + defined(__vax__) || defined(__x86_64__) + __u8 th_res:4; + __u8 th_off:4; +#else + __u8 th_off:4; + __u8 th_res:4; +#endif + __u8 th_flags; + __u16 th_win; + __u16 th_sum; + __u16 th_urp; +}; + +typedef __u32 tcp_seq; + +struct ipfudphdr { + __u16 uh_sport; + __u16 uh_dport; + __u16 uh_ulen; + __u16 uh_sum; +}; + +struct ip { +# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\ + defined(__vax__) + __u8 ip_hl:4; + __u8 ip_v:4; +# else + __u8 ip_v:4; + __u8 ip_hl:4; +# endif + __u8 ip_tos; + __u16 ip_len; + __u16 ip_id; + __u16 ip_off; + __u8 ip_ttl; + __u8 ip_p; + __u16 ip_sum; + struct in_addr ip_src; + struct in_addr ip_dst; +}; + +/* + * Structure of an icmp header. + */ +struct icmp { + __u8 icmp_type; /* type of message, see below */ + __u8 icmp_code; /* type sub code */ + __u16 icmp_cksum; /* ones complement cksum of struct */ + union { + __u8 ih_pptr; /* ICMP_PARAMPROB */ + struct in_addr ih_gwaddr; /* ICMP_REDIRECT */ + struct ih_idseq { + __u16 icd_id; + __u16 icd_seq; + } ih_idseq; + __u32 ih_void; + struct ih_pmtu { + __u16 ipm_void; + __u16 ipm_nextmtu; + } ih_pmtu; + } icmp_hun; +# define icmp_pptr icmp_hun.ih_pptr +# define icmp_gwaddr icmp_hun.ih_gwaddr +# define icmp_id icmp_hun.ih_idseq.icd_id +# define icmp_seq icmp_hun.ih_idseq.icd_seq +# define icmp_void icmp_hun.ih_void +# define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu + union { + struct id_ts { + __u32 its_otime; + __u32 its_rtime; + __u32 its_ttime; + } id_ts; + struct id_ip { + struct ip idi_ip; + /* options and then 64 bits of data */ + } id_ip; + u_long id_mask; + char id_data[1]; + } icmp_dun; +# define icmp_otime icmp_dun.id_ts.its_otime +# define icmp_rtime icmp_dun.id_ts.its_rtime +# define icmp_ttime icmp_dun.id_ts.its_ttime +# define icmp_ip icmp_dun.id_ip.idi_ip +# define icmp_mask icmp_dun.id_mask +# define icmp_data icmp_dun.id_data +}; + +# ifndef LINUX_IPOVLY +# define LINUX_IPOVLY +struct ipovly { + caddr_t ih_next, ih_prev; /* for protocol sequence q's */ + u_char ih_x1; /* (unused) */ + u_char ih_pr; /* protocol */ + short ih_len; /* protocol length */ + struct in_addr ih_src; /* source internet address */ + struct in_addr ih_dst; /* destination internet address */ +}; +# endif + +struct ether_header { + __u8 ether_dhost[6]; + __u8 ether_shost[6]; + __u16 ether_type; +}; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +typedef struct ipftcphdr tcphdr_t; +typedef struct ipfudphdr udphdr_t; +#endif + +#include "ip_compat.h" +#include "ip_fil.h" +#include "ip_auth.h" +#include "ip_state.h" +#include "ip_nat.h" +#include "ip_proxy.h" +#include "ip_sync.h" +#include "ip_frag.h" +#include "ip_lookup.h" +#include "ip_dstlist.h" +#include "ip_pool.h" +#include "ip_htable.h" +#ifdef IPFILTER_SYNC +# include "netinet/ip_sync.h" +#endif +#ifdef IPFILTER_SCAN +# include "netinet/ip_scan.h" +#endif +#ifdef IPFILTER_COMPILED +# include "netinet/ip_rules.h" +#endif +#include "ipl.h" + +#endif /* __IPF_LINUX_H__ */ diff --git a/test/input/input.sed b/Linux/ipfilter index e69de29bb2d1d..e69de29bb2d1d 100644..100755 --- a/test/input/input.sed +++ b/Linux/ipfilter diff --git a/Linux/ipfilter-redhat b/Linux/ipfilter-redhat new file mode 100755 index 0000000000000..1d4aa4cb4ac12 --- /dev/null +++ b/Linux/ipfilter-redhat @@ -0,0 +1,108 @@ +#!/bin/sh +# +# chkconfig: 2345 26 74 +# description: ipfilter +# processname: ipfilter +# config: /etc/sysconfig/ipfilter + +CONFIG=/etc/sysconfig/ipfilter +LOGPRI=user.info +IPFCONF=/etc/ipf.conf +IPNATCONF=/etc/ipnat.conf +IPPOOLCONF=/etc/ippool.conf + +# Source function library. +. /etc/init.d/functions +if [ ! -f /etc/ipf.conf -a ! -f /etc/ipnat.conf ] ; then + exit 0 +fi +RETVAL=0 + +logit() { + if [ $1 -ne 0 ] ; then + logger -t $2 -p $LOGPRI "$3" + fi +} + +start() { + modprobe ipfilter + echo -n $"Starting IPFilter: " + + minor=0 + ipfdev=`awk ' /ipf/ { print $1; } ' /proc/devices` + for i in ipl ipnat ipstate ipauth ipsync ipscan iplookup; do + /bin/rm -f /dev/$i + mknod /dev/$i c $ipfdev $minor + minor=`expr $minor + 1` + done + msg=`/sbin/ipf -E 2>&1` + RETVAL=$? + logit $RETVAL ipf "$msg" + if [ $RETVAL -eq 0 -a -f $IPFCONF ] ; then + msg=`/sbin/ipf -f $IPFCONF 2>&1` + RETVAL=$? + logit $RETVAL ipf "$msg" + fi + if [ $RETVAL -eq 0 -a -f $IPNATCONF ] ; then + msg=`/sbin/ipnat -f $IPNATCONF 2>&1` + RETVAL=$? + logit $RETVAL ipnat "$msg" + fi + if [ $RETVAL -eq 0 -a -f $IPPOOLCONF ] ; then + msg=`/sbin/ippool -f $IPPOOLCONF 2>&1` + RETVAL=$? + logit $RETVAL ippool "$msg" + fi + if [ $RETVAL -eq 0 ] ; then + /usr/bin/ipmon -Das + RETVAL=$? + fi + if [ $RETVAL -eq 0 ] ; then + echo_success + else + echo_failure + fi + echo + return $RETVAL +} + +stop() { + echo -n $"Shutting down IPFilter: " + killproc ipmon + RETVAL=$? + [ $RETVAL -eq 0 ] && /sbin/ipf -D && /sbin/modprobe -r ipfilter 2>&1 >/dev/null + echo + return $RETVAL +} + +dostatus() { + status ipmon + RETVAL=$? +} + +restart() { + stop + start + RETVAL=$? +} + +# See how we were called. +case "$1" in + start) + start + ;; + stop) + stop + ;; + status) + dostatus + ;; + restart|reload) + restart + ;; + *) + echo "Usage: ipfilter {start|stop|status|restart|reload}" + RETVAL=1 +esac + +exit $? diff --git a/Linux/ipfilter-suse b/Linux/ipfilter-suse new file mode 100755 index 0000000000000..6a1fb495c47d2 --- /dev/null +++ b/Linux/ipfilter-suse @@ -0,0 +1,106 @@ +#!/bin/sh +# +# chkconfig: 2345 26 74 +# description: ipfilter +# processname: ipfilter +# config: /etc/sysconfig/ipfilter + +CONFIG=/etc/sysconfig/ipfilter +LOGPRI=user.info +IPFCONF=/etc/ipf.conf +IPNATCONF=/etc/ipnat.conf +IPPOOLCONF=/etc/ippool.conf + +# Source function library. +. /etc/rc.status +if [ ! -f /etc/ipf.conf -a ! -f /etc/ipnat.conf ] ; then + exit 0 +fi +rc_reset +rc=0 + +logit() { + if [ $1 -ne 0 ] ; then + logger -t $2 -p $LOGPRI "$3" + fi +} + +start() { + modprobe ipfilter + rc=$? + if [ ${rc} -ne 0 ] ; then + rc_status -v + exit $rc + fi + echo -n $"Starting IPFilter: " + + minor=0 + ipfdev=`awk ' /ipf/ { print $1; } ' /proc/devices` + for i in ipl ipnat ipstate ipauth ipsync ipscan iplookup; do + /bin/rm -f /dev/$i + mknod /dev/$i c $ipfdev $minor + minor=`expr $minor + 1` + done + /sbin/ipf -E + if [ -f $IPFCONF ] ; then + msg=`/sbin/ipf -f $IPFCONF 2>&1` + rc=$? + logit $rc ipf "$msg" + fi + if [ $rc -eq 0 -a -f $IPNATCONF ] ; then + msg=`/sbin/ipnat -f $IPNATCONF 2>&1` + rc=$? + logit $rc ipnat "$msg" + fi + if [ $rc -eq 0 -a -f $IPPOOLCONF ] ; then + msg=`/sbin/ippool -f $IPPOOLCONF 2>&1` + rc=$? + logit $rc ippool "$msg" + fi + if [ $rc -eq 0 ] ; then + /usr/bin/ipmon -Das + rc=$? + fi + rc_status -v + return $rc +} + +stop() { + echo -n $"Shutting down IPFilter: " + killproc ipmon + rc=$? + [ $rc -eq 0 ] && /sbin/modprobe -r ipfilter 2>&1 >/dev/null + rc_status -v +} + +dostatus() { +# status ipmon + rc=$? +} + +restart() { + stop + start + rc=$? +} + +# See how we were called. +case "$1" in + start) + start + ;; + stop) + stop + ;; + status) + dostatus + ;; + restart|reload) + restart + ;; + *) + echo "Usage: ipfilter {start|stop|status|restart|reload}" + rc=1 +esac +rc_status -v +exit $? diff --git a/Linux/ipfilter.spec.dist b/Linux/ipfilter.spec.dist new file mode 100644 index 0000000000000..5eabd1ac890b5 --- /dev/null +++ b/Linux/ipfilter.spec.dist @@ -0,0 +1,98 @@ +Summary: IP Filter Software +Name: ipfilter +Version: 5.1.2 +Release: 1 +License: GPLv2 +Group: System Environment/Base +BuildRoot: /usr/src/redhat/BUILD/ipfilter + +%description +Packet Filtering and NAT for firewall applications + +%files +%defattr(-,root,root) + +/lib/modules/KERNELBUILD/kernel/net/ipv4/ipfilter.MODEXT +/etc/init.d/ipfilter +/etc/sysconfig/ipfilter +/sbin/ipf +/sbin/ipfs +/sbin/ipnat +/sbin/ippool +/sbin/ipfstat +/usr/bin/ipmon +/usr/bin/ipftest +/usr/share/man/man1/ipftest.1 +/usr/share/man/man4/ipfilter.4 +/usr/share/man/man4/ipf.4 +/usr/share/man/man4/ipl.4 +/usr/share/man/man4/ipnat.4 +/usr/share/man/man5/ipf.5 +/usr/share/man/man5/ipnat.5 +/usr/share/man/man5/ipfilter.5 +/usr/share/man/man5/ipmon.5 +/usr/share/man/man5/ippool.5 +/usr/share/man/man5/ipscan.5 +/usr/share/man/man8/ipscan.8 +/usr/share/man/man8/ipf.8 +/usr/share/man/man8/ipfs.8 +/usr/share/man/man8/ipmon.8 +/usr/share/man/man8/ipnat.8 +/usr/share/man/man8/ippool.8 +/usr/share/man/man8/ipfstat.8 +/usr/include/netinet/ip_fil.h +/usr/include/netinet/ip_nat.h +/usr/include/netinet/ip_frag.h +/usr/include/netinet/ip_auth.h +/usr/include/netinet/ip_pool.h +/usr/include/netinet/ip_proxy.h +/usr/include/netinet/ip_state.h +/usr/include/netinet/ip_compat.h +/usr/include/netinet/ip_htable.h +/usr/include/netinet/ip_lookup.h +/usr/include/netinet/ip_scan.h +/usr/include/netinet/ip_sync.h +/usr/include/netinet/ipl.h +/usr/share/ipfilter/examples/ip_rules +/usr/share/ipfilter/examples/ipmon.conf +/usr/share/ipfilter/examples/pool.conf +/usr/share/ipfilter/examples/example.1 +/usr/share/ipfilter/examples/example.2 +/usr/share/ipfilter/examples/example.3 +/usr/share/ipfilter/examples/example.4 +/usr/share/ipfilter/examples/example.5 +/usr/share/ipfilter/examples/example.6 +/usr/share/ipfilter/examples/example.7 +/usr/share/ipfilter/examples/example.8 +/usr/share/ipfilter/examples/example.9 +/usr/share/ipfilter/examples/example.10 +/usr/share/ipfilter/examples/example.11 +/usr/share/ipfilter/examples/example.12 +/usr/share/ipfilter/examples/example.13 +/usr/share/ipfilter/examples/example.sr +/usr/share/ipfilter/examples/nat.eg +/usr/share/ipfilter/examples/server +/usr/share/ipfilter/examples/tcpstate +/usr/share/ipfilter/examples/BASIC.NAT +/usr/share/ipfilter/examples/BASIC_1.FW +/usr/share/ipfilter/examples/BASIC_2.FW +/usr/share/ipfilter/examples/firewall +/usr/share/ipfilter/examples/ftp-proxy +/usr/share/ipfilter/examples/ftppxy +/usr/share/ipfilter/examples/nat-setup + +%pre +if [ -f /etc/init.d/ipfilter ] ; then + /sbin/chkconfig --del ipfilter +fi + +%post +/sbin/chkconfig --add ipfilter +/sbin/chkconfig TURNONIPFILTER +/sbin/depmod -A + +%preun +/etc/init.d/ipfilter stop +/sbin/chkconfig --del ipfilter + +%changelog diff --git a/Linux/linuxversion b/Linux/linuxversion new file mode 100755 index 0000000000000..7daee92be2709 --- /dev/null +++ b/Linux/linuxversion @@ -0,0 +1,3 @@ +#!/bin/sh +uname -r | perl -e '$_=<>;@F=split(/\./);printf "%02d%02d\n",$F[0],$F[1];'; +exit 0 diff --git a/Linux/minstall b/Linux/minstall new file mode 100755 index 0000000000000..c6a39bcbb817d --- /dev/null +++ b/Linux/minstall @@ -0,0 +1,18 @@ +#!/bin/sh + +dir=`pwd` +karch=`uname -m` + +if [ `basename $dir` = Linux ] ; then cd ..; fi +echo "Creating device files..." + +minor=0 +major=`awk ' /ipf/ { print $1; } ' /proc/devices` + +for i in ipl ipnat ipstate ipauth ipsync ipscan iplookup; do + echo ".../dev/$i" + mknod /dev/$i c $major $minor + minor=`expr $minor + 1` +done + +exit 0 diff --git a/Linux/mkinit b/Linux/mkinit new file mode 100755 index 0000000000000..3e188e0fb125d --- /dev/null +++ b/Linux/mkinit @@ -0,0 +1,10 @@ +#!/bin/sh +if [ -f /etc/SuSE-release ] ; then + cp ipfilter-suse $1/ipfilter + exit 0 +fi +if [ -f /etc/redhat-release ] ; then + cp ipfilter-redhat $1/ipfilter + exit 0 +fi +exit 1 diff --git a/Makefile b/Makefile index 1b2f8f5618a55..cfbd5e6e88a79 100644 --- a/Makefile +++ b/Makefile @@ -1,19 +1,18 @@ # -# Copyright (C) 1993-2001 by Darren Reed. +# Copyright (C) 2012 by Darren Reed. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and due credit is given # to the original author and the contributors. # -# $Id: Makefile,v 2.76.2.24 2007/09/26 10:04:03 darrenr Exp $ +# $Id$ # SHELL=/bin/sh BINDEST=/usr/local/bin SBINDEST=/sbin MANDIR=/usr/local/man #To test prototyping -#CC=gcc -Wstrict-prototypes -Wmissing-prototypes -# -Wunused -Wuninitialized +CC=gcc -Wstrict-prototypes -Wmissing-prototypes -Wunused -Wuninitialized #CC=gcc #CC=cc -Dconst= DEBUG=-g @@ -35,13 +34,13 @@ IPFLOG=-DIPFILTER_LOG # #COMPIPF=-DIPFILTER_COMPILED # -# To enable synchronisation between IPFilter hosts +# To enable IPFilter compatibility with older CLI utilities # -#SYNC=-DIPFILTER_SYNC +#COMPATIPF=-DIPFILTER_COMPAT # -# To enable extended IPFilter functionality +# To enable synchronisation between IPFilter hosts # -LOOKUP=-DIPFILTER_LOOKUP -DIPFILTER_SCAN +#SYNC=-DIPFILTER_SYNC # # The facility you wish to log messages from ipmon to syslogd with. # @@ -64,22 +63,27 @@ LOGFAC=-DLOGFAC=LOG_LOCAL0 # By default IPFilter looks for /usr/src/linux, but you may have to change # it to /usr/src/linux-2.4 or similar. # -LINUXKERNEL=/usr/src/linux +LINUXKERNEL=/usr/src/kernels/2.6.29.5-191.fc11.i586 LINUX=`uname -r | awk -F. ' { printf"%d",$$1;for(i=1;i<NF&&i<3;i++){printf("%02d",$$(i+1));}}'` +# +# +# +#BUILDROOT=/usr/src/redhat/BUILD/ipfilter +BUILDROOT=${HOME}/rpmbuild/BUILDROOT/ipfilter-4.1.32-1.i386 # # All of the compile-time options are here, used for compiling the userland # tools for regression testing. Well, all except for IPFILTER_LKM, of course. # ALLOPTS=-DIPFILTER_LOG -DIPFILTER_LOOKUP \ - -DIPFILTER_SCAN -DIPFILTER_SYNC -DIPFILTER_CKSUM + -DIPFILTER_SYNC -DIPFILTER_CKSUM # # Uncomment the next 3 lines if you want to view the state table a la top(1) # (requires that you have installed ncurses). #STATETOP_CFLAGS=-DSTATETOP # -# Where to find the ncurses include files (if not in default path), +# Where to find the ncurses include files (if not in default path), # #STATETOP_INC= #STATETOP_INC=-I/usr/local/include @@ -92,7 +96,7 @@ ALLOPTS=-DIPFILTER_LOG -DIPFILTER_LOOKUP \ # # Uncomment this when building IPv6 capability. # -#INET6=-DUSE_INET6 +INET6=-DUSE_INET6 # # For packets which don't match any pass rules or any block rules, set either # FR_PASS or FR_BLOCK (respectively). It defaults to FR_PASS if left @@ -109,6 +113,7 @@ MFLAGS1='CFLAGS=$(CFLAGS) $(ARCHINC) $(SOLARIS2) $(SGIREV) $(INET6)' \ 'STATETOP_CFLAGS=$(STATETOP_CFLAGS)' "BPFILTER=$(BPFILTER)" \ 'STATETOP_INC=$(STATETOP_INC)' 'STATETOP_LIB=$(STATETOP_LIB)' \ "BITS=$(BITS)" "OBJ=$(OBJ)" "LOOKUP=$(LOOKUP)" "COMPIPF=$(COMPIPF)" \ + "COMPATIPF=$(COMPATIPF)" \ 'SYNC=$(SYNC)' 'ALLOPTS=$(ALLOPTS)' 'LIBBPF=$(LIBBPF)' MFLAGS=$(MFLAGS1) "IPFLKM=$(IPFLKM)" MACHASSERT=`/bin/ls -1 /usr/sys/*/mach_assert.h | head -1` @@ -155,10 +160,6 @@ include: touch netinet/done; \ fi -(cd netinet; ln -s ../ip_rules.h ip_rules.h) - if [ ! -f net/done ] ; then \ - (cd net; ln -s ../radix_ipf.h .; ); \ - touch net/done; \ - fi sunos solaris: include MAKE="$(MAKE)" MAKEFLAGS="$(MAKEFLAGS)" BPFILTER=$(BPFILTER) \ @@ -188,7 +189,7 @@ freebsd22: include fi make freebsd20 -freebsd5 freebsd6 freebsd7: include +freebsd5 freebsd6 freebsd7 freebsd8: include if [ x$(INET6) = x ] ; then \ echo "#undef INET6" > opt_inet6.h; \ else \ @@ -211,7 +212,7 @@ freebsd5 freebsd6 freebsd7: include make setup "TARGOS=BSD" "CPUDIR=$(CPUDIR)" (cd BSD/$(CPUDIR); make build TOP=../.. $(MFLAGS) "ML=mlfk_ipl.c" "MLD=mlfk_ipl.c" "LKM=ipf.ko.5" "LKMR=ipfrule.ko.5" "DLKM=-DKLD_MODULE" "MLR=mlfk_rule.o"; cd ..) - (cd BSD/$(CPUDIR); make -f Makefile.ipsend build TOP=../.. $(MFLAGS1); cd ..) +# (cd BSD/$(CPUDIR); make -f Makefile.ipsend build TOP=../.. $(MFLAGS1); cd ..) freebsd4 : include if [ x$(INET6) = x ] ; then \ @@ -240,7 +241,7 @@ netbsd: include exit 1; \ fi (cd BSD/$(CPUDIR); make build TOP=../.. $(MFLAGS) 'DLKM=-D_LKM' "ML=mln_ipl.c" LKMR= "MLR=mln_rule.o"; cd ..) - (cd BSD/$(CPUDIR); make -f Makefile.ipsend build TOP=../.. $(MFLAGS); cd ..) +# (cd BSD/$(CPUDIR); make -f Makefile.ipsend build TOP=../.. $(MFLAGS); cd ..) openbsd: include make setup "TARGOS=BSD" "CPUDIR=$(CPUDIR)" @@ -293,7 +294,7 @@ setup: clean: clean-include /bin/rm -rf h y.output - ${RM} -f core *.o ipt fils ipf ipfstat ipftest ipmon if_ipl \ + ${RM} -f core *.o ipt fils ipf ipfstat ipftest ipmon if_ipl ipflkm \ vnode_if.h $(LKM) *~ /bin/rm -rf sparcv7 sparcv9 mdbgen_build (cd SunOS4; $(MAKE) TOP=.. clean) @@ -351,7 +352,7 @@ sunos4 solaris1: (cd SunOS4; make -f Makefile.ipsend build "CC=$(CC)" TOP=.. $(DEST) $(MFLAGS); cd ..) sunos5 solaris2: null - (cd SunOS5/$(CPUDIR); $(MAKE) build TOP=../.. "CC=$(CC)" $(DEST) $(MFLAGS) "SOLARIS2=$(SOLARIS2)"; cd ..) + (cd SunOS5/$(CPUDIR); $(MAKE) build TOP=../.. "CC=$(CC)" $(DEST) $(MFLAGS) "SOLARIS2=$(SOLARIS2)" INSTANCE=$(INSTANCE); cd ..) (cd SunOS5/$(CPUDIR); $(MAKE) -f Makefile.ipsend build TOP=../.. "CC=$(CC)" $(DEST) $(MFLAGS); cd ..) linux: include @@ -360,7 +361,7 @@ linux: include # (cd Linux; make -f Makefile.ipsend build LINUX=$(LINUX) TOP=.. "CC=$(CC)" $(MFLAGS); cd ..) install-linux: linux - (cd Linux/; make LINUX=$(LINUX) TOP=.. "DEBUG=-g" "CC=$(CC)" $(MFLAGS) OBJ=$(CPUDIR) install ; cd ..) + (cd Linux/; make LINUX=$(LINUX) TOP=.. "DEBUG=-g" "CC=$(CC)" $(MFLAGS) OBJ=$(CPUDIR) ROOTDIR=$(BUILDROOT) install ; cd ..) install-bsd: (cd BSD/$(CPUDIR); make install "TOP=../.." $(MFLAGS); cd ..) @@ -406,4 +407,3 @@ mdb: -DIPFILTER_SCAN -DIPFILTER_LKM -DSOLARIS2=10 -n ipf_mdb -k \ -I/home/dr146992/pfil -I/home/dr146992/ipf -f \ /usr/include/netinet/in_systm.h,/usr/include/sys/ethernet.h,/usr/include/netinet/in.h,/usr/include/netinet/ip.h,/usr/include/netinet/ip_var.h,/usr/include/netinet/tcp.h,/usr/include/netinet/tcpip.h,/usr/include/netinet/ip_icmp.h,/usr/include/netinet/udp.h,ip_compat.h,ip_fil.h,ip_nat.h,ip_state.h,ip_proxy.h,ip_scan.h - diff --git a/NAT.FreeBSD b/NAT.FreeBSD index 8a7e95262f7c8..4a1a7ede543ce 100644 --- a/NAT.FreeBSD +++ b/NAT.FreeBSD @@ -1,4 +1,4 @@ -These are Instructions for Configuring A FreeBSD Box For NAT +These are Instructions for Configuring A FreeBSD Box For NAT After you have installed IpFilter. You will need to change three files: @@ -54,7 +54,7 @@ fpx0 is the interface with the real internet address. /32 is the subnet mask 255.255.255.255, ie only use this ip address. -portmap tcp/udp 10000:65000 +portmap tcp/udp 10000:65000 tells it to use the ports to redirect the tcp/udp calls through @@ -67,7 +67,7 @@ reboots. In your /etc/rc.local put the line: -ipnat -f /etc/natrules +ipnat -f /etc/natrules To check and see if it is loaded, as root type ipnat -ls diff --git a/NetBSD-1.2/conf.c-PATCH b/NetBSD-1.2/conf.c-PATCH new file mode 100644 index 0000000000000..8cd97a6880770 --- /dev/null +++ b/NetBSD-1.2/conf.c-PATCH @@ -0,0 +1,52 @@ +*** sys/arch/i386/i386/conf.c-ORIG Mon May 27 11:14:49 1996 +--- sys/arch/i386/i386/conf.c Mon May 27 16:29:25 1996 +*************** +*** 179,184 **** +--- 179,210 ---- + #include "joy.h" + cdev_decl(joy); + ++ cdev_decl(ipl); ++ ++ #ifdef IPFILTER_LOG ++ /* open, close, read, ioctl */ ++ # define cdev_ipf_init(c,n) { \ ++ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ ++ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ ++ (dev_type_stop((*))) nullop, 0, (dev_type_select((*))) enodev, \ ++ (dev_type_mmap((*))) enodev, 0 } ++ #else /* IPFILTER_LOG */ ++ /* XXX same as cdev_ch_init */ ++ /* open, close, ioctl */ ++ # define cdev_ipf_init(c,n) { \ ++ dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ ++ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ ++ (dev_type_stop((*))) nullop, 0, (dev_type_select((*))) enodev, \ ++ (dev_type_mmap((*))) enodev, 0 } ++ #endif /* IPFILTER_LOG */ ++ ++ /* make up for missing "ipl.h" */ ++ #ifdef IPFILTER ++ # define NIPF 1 ++ #else ++ # define NIPF 0 ++ #endif ++ + struct cdevsw cdevsw[] = + { + cdev_cn_init(1,cn), /* 0: virtual console */ +*************** +*** 229,234 **** +--- 255,266 ---- + #else + cdev_notdef(), /* 43 */ + #endif ++ cdev_notdef(), /* 44 */ ++ cdev_notdef(), /* 45 */ ++ cdev_notdef(), /* 46 */ ++ cdev_notdef(), /* 47 */ ++ cdev_notdef(), /* 48 */ ++ cdev_ipf_init(NIPF,ipl), /* 49 */ + }; + int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]); + diff --git a/NetBSD-1.2/files-PATCH b/NetBSD-1.2/files-PATCH new file mode 100644 index 0000000000000..75a38fb8e6716 --- /dev/null +++ b/NetBSD-1.2/files-PATCH @@ -0,0 +1,21 @@ +*** sys/conf/files-ORIG Mon May 20 08:03:42 1996 +--- sys/conf/files Mon May 27 13:44:27 1996 +*************** +*** 257,262 **** +--- 257,272 ---- + file netinet/tcp_timer.c inet + file netinet/tcp_usrreq.c inet + file netinet/udp_usrreq.c inet ++ file netinet/ip_fil.c ipfilter ++ file netinet/fil.c ipfilter ++ file netinet/ip_nat.c ipfilter ++ file netinet/ip_frag.c ipfilter ++ file netinet/ip_state.c ipfilter ++ file netinet/ip_proxy.c ipfilter ++ file netinet/ip_auth.c ipfilter ++ file netinet/ip_log.c ipfilter ++ file netinet/ip_scan.c ipfilter ++ file netinet/ip_sync.c ipfilter + file netiso/clnp_debug.c iso + file netiso/clnp_er.c iso + file netiso/clnp_frag.c iso diff --git a/NetBSD-1.2/files.oldconf-PATCH b/NetBSD-1.2/files.oldconf-PATCH new file mode 100644 index 0000000000000..4ccca9f6229f9 --- /dev/null +++ b/NetBSD-1.2/files.oldconf-PATCH @@ -0,0 +1,21 @@ +*** sys/conf/files.oldconf-ORIG Sun May 26 07:40:50 1996 +--- sys/conf/files.oldconf Mon May 27 15:23:35 1996 +*************** +*** 184,189 **** +--- 184,199 ---- + netinet/tcp_timer.c optional inet + netinet/tcp_usrreq.c optional inet + netinet/udp_usrreq.c optional inet ++ netinet/ip_fil.c optional ipfilter ++ netinet/fil.c optional ipfilter ++ netinet/ip_nat.c optional ipfilter ++ netinet/ip_frag.c optional ipfilter ++ netinet/ip_state.c optional ipfilter ++ netinet/ip_proxy.c optional ipfilter ++ netinet/ip_auth.c optional ipfilter ++ netinet/ip_log.c optional ipfilter ++ netinet/ip_scan.c optional ipfilter ++ netinet/ip_sync.c optional ipfilter + netiso/clnp_debug.c optional iso + netiso/clnp_er.c optional iso + netiso/clnp_frag.c optional iso diff --git a/NetBSD-1.2/in_proto.c-PATCH b/NetBSD-1.2/in_proto.c-PATCH new file mode 100644 index 0000000000000..406b5f90c459d --- /dev/null +++ b/NetBSD-1.2/in_proto.c-PATCH @@ -0,0 +1,16 @@ +*** sys/netinet/in_proto.c-ORIG Wed Apr 24 22:49:02 1996 +--- sys/netinet/in_proto.c Wed Apr 24 22:50:30 1996 +*************** +*** 83,88 **** +--- 83,93 ---- + #include <netinet/ip_mroute.h> + #endif /* MROUTING */ + ++ #ifdef IPFILTER ++ void iplinit(); ++ #define ip_init iplinit ++ #endif ++ + extern struct domain inetdomain; + + struc protosw inetsw[] = { diff --git a/NetBSD-1.2/ip_input.c-PATCH b/NetBSD-1.2/ip_input.c-PATCH new file mode 100644 index 0000000000000..80e3149940773 --- /dev/null +++ b/NetBSD-1.2/ip_input.c-PATCH @@ -0,0 +1,37 @@ +*** sys/netinet/ip_input.c-ORIG Sun Mar 17 07:29:08 1996 +--- sys/netinet/ip_input.c Wed Apr 24 22:45:05 1996 +*************** +*** 100,105 **** +--- 100,109 ---- + int ipqmaxlen = IFQ_MAXLEN; + struct in_ifaddrhead in_ifaddr; + struct ifqueue ipintrq; ++ #if defined(IPFILTER_LKM) || defined(IPFILTER) ++ int fr_check __P((struct ip *, int, struct ifnet *, int, struct mbuf *)); ++ int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)) = NULL; ++ #endif + + /* + * We need to save the IP options in case a protocol wants to respond +*************** +*** 237,242 **** +--- 241,259 ---- + m_adj(m, ip->ip_len - m->m_pkthdr.len); + } + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * Check if we want to allow this packet to be processed. ++ * Consider it to be bad if not. ++ */ ++ { ++ struct mbuf *m0 = m; ++ if (fr_checkp && (*fr_checkp)(ip, hlen, m->m_pkthdr.rcvif, 0, &m0)) ++ goto next; ++ else ++ ip = mtod(m = m0, struct ip *); ++ } ++ #endif + /* + * Process options and, if not destined for us, + * ship it on. ip_dooptions returns 1 when an diff --git a/NetBSD-1.2/ip_output.c-PATCH b/NetBSD-1.2/ip_output.c-PATCH new file mode 100644 index 0000000000000..8d9b910a46238 --- /dev/null +++ b/NetBSD-1.2/ip_output.c-PATCH @@ -0,0 +1,37 @@ +*** sys/netinet/ip_output.c-ORIG Tue Feb 27 07:27:02 1996 +--- sys/netinet/ip_output.c Wed Apr 24 22:45:05 1996 +*************** +*** 63,68 **** +--- 63,72 ---- + static struct mbuf *ip_insertoptions __P((struct mbuf *, struct mbuf *, int *)); + static void ip_mloopback + __P((struct ifnet *, struct mbuf *, struct sockaddr_in *)); ++ #if defined(IPFILTER_LKM) || defined(IPFILTER) ++ extern int fr_check __P((struct ip *, int, struct ifnet *, int, struct mbuf *)); ++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif + + /* + * IP output. The packet in mbuf chain m contains a skeletal IP +*************** +*** 293,298 **** +--- 297,315 ---- + } else + m->m_flags &= ~M_BCAST; + + sendit: ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ { ++ struct mbuf *m0 = m; ++ /* ++ * looks like most checking has been done now...do a filter check ++ */ ++ if (fr_checkp && (error = (*fr_checkp)(ip, hlen, ifp, 1, &m0)) || !m0) ++ { ++ goto done; ++ } else ++ ip = mtod(m = m0, struct ip *); ++ } ++ #endif + /* + * If small enough for interface, can just send directly. diff --git a/NetBSD-1.2/kinstall b/NetBSD-1.2/kinstall new file mode 100755 index 0000000000000..135ef2793bfed --- /dev/null +++ b/NetBSD-1.2/kinstall @@ -0,0 +1,135 @@ +#! /bin/sh -e +# $Id$ +# install ip-filter & patches to kernel sources +# +# Heavily hacked by vax@linkdead.paranoia.com (VaX-n8) +# NOTE: There is an "-e" option on the first line; bomb out quickly if errors +# WARNING: This script should be run exactly once on a virgin system. +# NOTE: Once you have configured a kernel with this device, it will default +# to being enabled. Use "ipf -D" in /etc/netstart (before configuring +# interfaces) to disable it. +# +PATH=/sbin:/usr/sbin:/bin:/usr/bin; export PATH + +# there's some brain damage in ash that won't handle non-argument flags, +# so I have a -m which should really be a boolean here +export optstring="d:c:a:m:" +export supparches="i386" +export argv0=$(basename "$0") +export destdir="" # assume $destdir/sys is a symlink to the src tree +export architecture=$(uname -m) # take a good guess at architecture +# do some rather tedious guesswork at the kernel config location +kconfull="$(IFS=:; set -- $(uname -v); eval echo \"\$$#\")" +export kconfull +if [ -n "$kconfull" ]; then + kconfdir=$(dirname $(dirname "$kconfull"))/conf + export newconfig="$(basename "$kconfull")" +else + kconfdir="/sys/arch/${architecture}/conf" +fi +export kconfdir +while getopts "$optstring" name; do + # ash is broken; case statements don't work right, calls * every time + # seems ash requires quotes on the patterns -- strange + case "$name" in + #( root of the source tree, a la DESTDIR in NetBSD Makefiles + 'd') destdir="$OPTARG";; + #( name of new config file + 'c') newconfig="$OPTARG";; + #( name of architecture + 'a') architecture="$OPTARG";; + #( if we want it as a loadable kernel module or not + 'm') modload="_LKM";; + #( default... bad arg, missing option, etc + *) + export OLDIFS="$IFS" # save IFS + echo -n "Usage: $argv0 [-" + # I would use IFS="."; echo "$@" except ash screws it up + # I have submitted a send-pr to fix it. Until then... + IFS=":" + set -- $optstring + while [ "$#" -gt 0 ]; do echo -n "$1"; shift; done; echo "]" + IFS="$OLDIFS" + expln="\ +OPT:ARG:DEFAULT:MEANING:\ +-d:destdir:\"$destdir\":parent dir of \"sys\", no slash:\ +-c:configfile:\"$newconfig\":kernel config filename, no dir:\ +-k:kconfdir:\"$kconfdir\":kernel config directory:\ +-a:arch:\"$architecture\":architecture, e.g. $supparches:\ +-m:boolean:\"$modload\":install as loadable module:\ +-?:::this help screen" + IFS=$(printf ":\012\015"); set -- $expln; IFS="$OLDIFS" + for i in 1 2 3; do eval "maxsz$i=0"; done + while [ "$#" -ge 4 ]; do for i in 1 2 3; do + eval j=\"\$$i\ \" \; len=\${#j} \; \ + if test \"\$maxsz$i\" -lt \"\$len\" \; then \ + maxsz$i=\"\$len\" \; fi + done; shift 4; done + IFS=$(printf ":\012\015"); set -- $expln; IFS="$OLDIFS" + while [ "$#" -ge 4 ]; do for i in 1 2 3; do + eval j=\"\$$i\ \" \; printf \"%-\${maxsz$i}s\" \"\$j\" + done; echo "$4"; shift 4; done + exit 127 ;; + esac +done + +archdir="$destdir/sys/arch/$architecture" + +case "$architecture" in +i386) + echo "Patching $archdir/$architecture/conf.c" + (cd "$archdir/$architecture" && patch) < conf.c-PATCH + ;; +*) + echo "$argv0: target architecture not supported: $architecture" 1>&2 + exit 2 + ;; +esac + +(cd .. +files="ip_nat.[ch] ip_fil.[ch] ip_frag.[ch] ip_state.[ch] fil.c ip_compat.h ip_proxy.[ch] ip_auth.[ch] ip_{ftp,rcmd}_pxy.c ip_log.c" +echo "Installing $files" +install -c -m 644 $files "$destdir/sys/netinet" +) + +set -- i*.c-PATCH +echo "Patching $(echo "$@" | sed -n 's/\([a-zA-Z]*\)-PATCH/\1/gp')" +while [ -n "$1" ]; do + (cd "$destdir/sys/netinet" && patch) < "$1" + shift +done + +set -- files*-PATCH +echo "Patching $(echo "$@" | sed -n 's/\([a-zA-Z]*\)-PATCH/\1/gp')" +while [ -n "$1" ]; do + (cd "$destdir/" && patch) < "$1" + shift +done + +# get this kernel's name from uname version string as a good guess for kconfig +set -- $(uname -v | sed -n '/.*(\([^ ][^ ]*\)).*/s//\1/p; 1q') "GENERIC" +while [ ! -f "$kconfdir/$newconfig" ]; do + eval ${newconfig:+"echo $kconfdir/$newconfig not found 1>&2"} + read -p "Kernel configuration to update [$1] " newconfig junk + : ${newconfig:=$1} # set to default if not set +done + +if tmp=`grep IPFILTER "$kconfdir/$newconfig"`; then + echo "$newconfig already contains \"$tmp\"..." + echo 'You will now need to build a new kernel.' +else + echo "Saving $newconfig as $newconfig.bak" + mv -i "$kconfdir/$newconfig" "$kconfdir/$newconfig.bak" + compdir="$archdir/compile" + if [ -d "$compdir/$newconfig" ]; then + echo "Saving $compdir/$newconfig as $compdir/$newconfig.bak" + mv -i "$compdir/$newconfig" "$compdir/$newconfig.bak" + fi + modload="options IPFILTER${modload}" + echo "Modifying $newconfig, adding $modload" + awk "{print \$0} \$2==\"INET\"{print \"$modload\"}" \ + "$kconfdir/$newconfig.bak" > "$kconfdir/$newconfig" + echo 'You will now need to run "config" and build a new kernel.' +fi + +exit 0 diff --git a/NetBSD-1.2/minstall b/NetBSD-1.2/minstall new file mode 100755 index 0000000000000..34f148820960d --- /dev/null +++ b/NetBSD-1.2/minstall @@ -0,0 +1,135 @@ +#! /bin/sh -e +# $Id$ +# install ip-filter & patches to kernel sources +# +# Heavily hacked by vax@linkdead.paranoia.com (VaX-n8) +# NOTE: There is an "-e" option on the first line; bomb out quickly if errors +# WARNING: This script should be run exactly once on a virgin system. +# NOTE: Once you have configured a kernel with this device, it will default +# to being enabled. Use "ipf -D" in /etc/netstart (before configuring +# interfaces) to disable it. +# +PATH=/sbin:/usr/sbin:/bin:/usr/bin; export PATH + +# there's some brain damage in ash that won't handle non-argument flags, +# so I have a -m which should really be a boolean here +export optstring="d:c:a:m:" +export supparches="i386" +export argv0=$(basename "$0") +export destdir="" # assume $destdir/sys is a symlink to the src tree +export architecture=$(uname -m) # take a good guess at architecture +# do some rather tedious guesswork at the kernel config location +kconfull="$(IFS=:; set -- $(uname -v); eval echo \"\$$#\")" +export kconfull +if [ -n "$kconfull" ]; then + kconfdir=$(dirname $(dirname "$kconfull"))/conf + export newconfig="$(basename "$kconfull")" +else + kconfdir="/sys/arch/${architecture}/conf" +fi +export kconfdir +while getopts "$optstring" name; do + # ash is broken; case statements don't work right, calls * every time + # seems ash requires quotes on the patterns -- strange + case "$name" in + #( root of the source tree, a la DESTDIR in NetBSD Makefiles + 'd') destdir="$OPTARG";; + #( name of new config file + 'c') newconfig="$OPTARG";; + #( name of architecture + 'a') architecture="$OPTARG";; + #( if we want it as a loadable kernel module or not + 'm') modload="_LKM";; + #( default... bad arg, missing option, etc + *) + export OLDIFS="$IFS" # save IFS + echo -n "Usage: $argv0 [-" + # I would use IFS="."; echo "$@" except ash screws it up + # I have submitted a send-pr to fix it. Until then... + IFS=":" + set -- $optstring + while [ "$#" -gt 0 ]; do echo -n "$1"; shift; done; echo "]" + IFS="$OLDIFS" + expln="\ +OPT:ARG:DEFAULT:MEANING:\ +-d:destdir:\"$destdir\":parent dir of \"sys\", no slash:\ +-c:configfile:\"$newconfig\":kernel config filename, no dir:\ +-k:kconfdir:\"$kconfdir\":kernel config directory:\ +-a:arch:\"$architecture\":architecture, e.g. $supparches:\ +-m:boolean:\"$modload\":install as loadable module:\ +-?:::this help screen" + IFS=$(printf ":\012\015"); set -- $expln; IFS="$OLDIFS" + for i in 1 2 3; do eval "maxsz$i=0"; done + while [ "$#" -ge 4 ]; do for i in 1 2 3; do + eval j=\"\$$i\ \" \; len=\${#j} \; \ + if test \"\$maxsz$i\" -lt \"\$len\" \; then \ + maxsz$i=\"\$len\" \; fi + done; shift 4; done + IFS=$(printf ":\012\015"); set -- $expln; IFS="$OLDIFS" + while [ "$#" -ge 4 ]; do for i in 1 2 3; do + eval j=\"\$$i\ \" \; printf \"%-\${maxsz$i}s\" \"\$j\" + done; echo "$4"; shift 4; done + exit 127 ;; + esac +done + +archdir="$destdir/sys/arch/$architecture" + +case "$architecture" in +i386) + echo "Patching $archdir/$architecture/conf.c" + (cd "$archdir/$architecture" && patch) < conf.c-PATCH + ;; +*) + echo "$argv0: target architecture not supported: $architecture" 1>&2 + exit 2 + ;; +esac + +(cd .. +files="ip_nat.[ch] ip_fil.[ch] ip_frag.[ch] ip_state.[ch] fil.c ip_compat.h" +echo "Installing $files" +install -c -m 644 $files "$destdir/sys/netinet" +) + +set -- i*.c-PATCH +echo "Patching $(echo "$@" | sed -n 's/\([a-zA-Z]*\)-PATCH/\1/gp')" +while [ -n "$1" ]; do + (cd "$destdir/sys/netinet" && patch) < "$1" + shift +done + +set -- files*-PATCH +echo "Patching $(echo "$@" | sed -n 's/\([a-zA-Z]*\)-PATCH/\1/gp')" +while [ -n "$1" ]; do + (cd "$destdir/" && patch) < "$1" + shift +done + +# get this kernel's name from uname version string as a good guess for kconfig +set -- $(uname -v | sed -n '/.*(\([^ ][^ ]*\)).*/s//\1/p; 1q') "GENERIC" +while [ ! -f "$kconfdir/$newconfig" ]; do + eval ${newconfig:+"echo $kconfdir/$newconfig not found 1>&2"} + read -p "Kernel configuration to update [$1] " newconfig junk + : ${newconfig:=$1} # set to default if not set +done + +if tmp=`grep IPFILTER "$kconfdir/$newconfig"`; then + echo "$newconfig already contains \"$tmp\"..." + echo 'You will now need to build a new kernel.' +else + echo "Saving $newconfig as $newconfig.bak" + mv -i "$kconfdir/$newconfig" "$kconfdir/$newconfig.bak" + compdir="$archdir/compile" + if [ -d "$compdir/$newconfig" ]; then + echo "Saving $compdir/$newconfig as $compdir/$newconfig.bak" + mv -i "$compdir/$newconfig" "$compdir/$newconfig.bak" + fi + modload="options IPFILTER${modload}" + echo "Modifying $newconfig, adding $modload" + awk "{print \$0} \$2==\"INET\"{print \"$modload\"}" \ + "$kconfdir/$newconfig.bak" > "$kconfdir/$newconfig" + echo 'You will now need to run "config" and build a new kernel.' +fi + +exit 0 diff --git a/NetBSD/conf.c.diffs b/NetBSD/conf.c.diffs new file mode 100644 index 0000000000000..fb8985063ee0e --- /dev/null +++ b/NetBSD/conf.c.diffs @@ -0,0 +1,39 @@ +*** conf.c.orig Mon Oct 28 11:24:52 1996 +--- conf.c Mon Oct 28 11:36:17 1996 +*************** +*** 175,180 **** +--- 175,193 ---- + cdev_decl(svr4_net); + cdev_decl(ccd); + ++ /* open, close, read, ioctl */ ++ cdev_decl(ipl); ++ #define cdev_gen_ipf(c,n) { \ ++ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ ++ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ ++ (dev_type_stop((*))) nullop, 0, (dev_type_select((*))) enodev, \ ++ (dev_type_mmap((*))) enodev, 0 } ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + struct cdevsw cdevsw[] = + { + cdev_cn_init(1,cn), /* 0: virtual console */ +*************** +*** 204,209 **** + cdev_fd_init(1,fd), /* 22: file descriptor pseudo-device */ + cdev_bpftun_init(NBPFILTER,bpf),/* 23: Berkeley packet filter */ +! cdev_notdef(), /* 24 */ + cdev_notdef(), /* 25 */ + cdev_notdef(), /* 26 */ + cdev_spkr_init(NSPEAKER,spkr), /* 27: PC speaker */ +--- 217,222 ---- + cdev_fd_init(1,fd), /* 22: file descriptor pseudo-device */ + cdev_bpftun_init(NBPFILTER,bpf),/* 23: Berkeley packet filter */ +! cdev_notdef(NIPF,ipl), /* 24 */ + cdev_notdef(), /* 25 */ + cdev_notdef(), /* 26 */ + cdev_spkr_init(NSPEAKER,spkr), /* 27: PC speaker */ diff --git a/NetBSD/conf.c.old.diffs b/NetBSD/conf.c.old.diffs new file mode 100644 index 0000000000000..5f9591a52dc29 --- /dev/null +++ b/NetBSD/conf.c.old.diffs @@ -0,0 +1,39 @@ +*** conf.c.orig Wed May 10 23:38:08 1995 +--- conf.c Thu May 11 00:33:19 1995 +*************** +*** 169,174 **** +--- 169,187 ---- + #endif + cdev_decl(lkm); + ++ /* open, close, read, ioctl */ ++ cdev_decl(ipl); ++ #define cdev_gen_ipf(c,n) { \ ++ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ ++ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ ++ (dev_type_stop((*))) nullop, 0, (dev_type_select((*))) enodev, \ ++ (dev_type_mmap((*))) enodev, 0 } ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + struct cdevsw cdevsw[] = + { + cdev_cn_init(1,cn), /* 0: virtual console */ +*************** +*** 233,238 **** + cdev_notdef(), /* 57 */ + cdev_disk_init(NCD,cd), /* 58 SCSI CD-ROM */ +! cdev_notdef(), /* 59 */ + cdev_notdef(), /* 60 */ + cdev_notdef(), /* 61 */ + cdev_notdef(), /* 62 */ +--- 246,251 ---- + cdev_notdef(), /* 57 */ + cdev_disk_init(NCD,cd), /* 58 SCSI CD-ROM */ +! cdev_gen_ipf(NIPF,ipl), /* 59 */ + cdev_notdef(), /* 60 */ + cdev_notdef(), /* 61 */ + cdev_notdef(), /* 62 */ diff --git a/NetBSD/files.diffs b/NetBSD/files.diffs new file mode 100644 index 0000000000000..f015740f7257a --- /dev/null +++ b/NetBSD/files.diffs @@ -0,0 +1,23 @@ +*** files.orig Sat Apr 29 19:59:31 1995 +--- files Sun Apr 23 17:54:18 1995 +*************** +*** 180,185 **** +--- 180,197 ---- + netinet/tcp_timer.c optional inet + netinet/tcp_usrreq.c optional inet + netinet/udp_usrreq.c optional inet ++ netinet/ip_fil.c optional ipfilter ++ netinet/fil.c optional ipfilter ++ netinet/ip_nat.c optional ipfilter ++ netinet/ip_frag.c optional ipfilter ++ netinet/ip_state.c optional ipfilter ++ netinet/ip_proxy.c optional ipfilter ++ netinet/ip_auth.c optional ipfilter ++ netinet/ip_log.c optional ipfilter ++ netinet/ip_scan.c optional ipfilter ++ netinet/ip_sync.c optional ipfilter ++ netinet/ip_pool.c optional ipfilter_pool ++ netinet/ip_rules.c optional ipfilter_compiled + netiso/clnp_debug.c optional iso + netiso/clnp_er.c optional iso + netiso/clnp_frag.c optional iso diff --git a/NetBSD/files.newconf.diffs b/NetBSD/files.newconf.diffs new file mode 100644 index 0000000000000..9e5c43a5931bb --- /dev/null +++ b/NetBSD/files.newconf.diffs @@ -0,0 +1,23 @@ +*** files.newconf.orig Sat Apr 29 20:00:02 1995 +--- files.newconf Sun Apr 23 17:53:58 1995 +*************** +*** 222,227 **** +--- 222,239 ---- + file netinet/tcp_timer.c inet + file netinet/tcp_usrreq.c inet + file netinet/udp_usrreq.c inet ++ file netinet/ip_fil.c ipfilter ++ file netinet/fil.c ipfilter ++ file netinet/ip_nat.c ipfilter ++ file netinet/ip_frag.c ipfilter ++ file netinet/ip_state.c ipfilter ++ file netinet/ip_proxy.c ipfilter ++ file netinet/ip_auth.c ipfilter ++ file netinet/ip_log.c ipfilter ++ file netinet/ip_scan.c ipfilter ++ file netinet/ip_sync.c ipfilter ++ file netinet/ip_pool.c ipfilter_pool ++ file netinet/ip_rules.c ipfilter_compiled + file netiso/clnp_debug.c iso + file netiso/clnp_er.c iso + file netiso/clnp_frag.c iso diff --git a/NetBSD/files.oldconf.diffs b/NetBSD/files.oldconf.diffs new file mode 100644 index 0000000000000..c74b707c429a0 --- /dev/null +++ b/NetBSD/files.oldconf.diffs @@ -0,0 +1,23 @@ +*** files.oldconf.orig Sat Apr 29 19:59:31 1995 +--- files.oldconf Sun Apr 23 17:54:18 1995 +*************** +*** 180,185 **** +--- 180,197 ---- + netinet/tcp_timer.c optional inet + netinet/tcp_usrreq.c optional inet + netinet/udp_usrreq.c optional inet ++ netinet/ip_fil.c optional ipfilter ++ netinet/fil.c optional ipfilter ++ netinet/ip_nat.c optional ipfilter ++ netinet/ip_frag.c optional ipfilter ++ netinet/ip_state.c optional ipfilter ++ netinet/ip_proxy.c optional ipfilter ++ netinet/ip_auth.c optional ipfilter ++ netinet/ip_log.c optional ipfilter ++ netinet/ip_scan.c optional ipfilter ++ netinet/ip_sync.c optional ipfilter ++ netinet/ip_pool.c optional ipfilter_pool ++ netinet/ip_rules.c optional ipfilter_compiled + netiso/clnp_debug.c optional iso + netiso/clnp_er.c optional iso + netiso/clnp_frag.c optional iso diff --git a/NetBSD/filez.diffs b/NetBSD/filez.diffs new file mode 100644 index 0000000000000..b8409fda1db68 --- /dev/null +++ b/NetBSD/filez.diffs @@ -0,0 +1,23 @@ +*** files.orig Sat Apr 29 20:00:02 1995 +--- files Sun Apr 23 17:53:58 1995 +*************** +*** 224,229 **** +--- 224,241 ---- + file netinet/tcp_timer.c inet + file netinet/tcp_usrreq.c inet + file netinet/udp_usrreq.c inet ++ file netinet/ip_fil.c ipfilter ++ file netinet/fil.c ipfilter ++ file netinet/ip_nat.c ipfilter ++ file netinet/ip_frag.c ipfilter ++ file netinet/ip_state.c ipfilter ++ file netinet/ip_proxy.c ipfilter ++ file netinet/ip_auth.c ipfilter ++ file netinet/ip_log.c ipfilter ++ file netinet/ip_scan.c ipfilter ++ file netinet/ip_sync.c ipfilter ++ file netinet/ip_pool.c ipfilter_pool ++ file netinet/ip_rules.c ipfilter_compiled + file netiso/clnp_debug.c iso + file netiso/clnp_er.c iso + file netiso/clnp_frag.c iso diff --git a/NetBSD/in_proto.c.diffs b/NetBSD/in_proto.c.diffs new file mode 100644 index 0000000000000..e91f01677d438 --- /dev/null +++ b/NetBSD/in_proto.c.diffs @@ -0,0 +1,16 @@ +*** in_proto.c.orig Mon Oct 28 11:58:19 1996 +--- in_proto.c Mon Oct 28 12:00:02 1996 +*************** +*** 82,87 **** +--- 82,92 ---- + void ipip_input(); + #endif /* MROUTING */ + ++ #ifdef IPFILTER ++ void iplinit(); ++ #define ip_init iplinit ++ #endif ++ + extern struct domain inetdomain; + + struct protosw inetsw[] = { diff --git a/NetBSD/in_proto.c.old.diffs b/NetBSD/in_proto.c.old.diffs new file mode 100644 index 0000000000000..052dd514ee18d --- /dev/null +++ b/NetBSD/in_proto.c.old.diffs @@ -0,0 +1,16 @@ +*** in_proto.c.orig Wed Sep 6 20:31:34 1995 +--- in_proto.c Mon Mar 11 22:40:03 1996 +*************** +*** 81,86 **** +--- 81,91 ---- + void eoninput(), eonctlinput(), eonprotoinit(); + #endif /* EON */ + ++ #ifdef IPFILTER ++ void iplinit(); ++ #define ip_init iplinit ++ #endif ++ + void rsvp_input(struct mbuf *, int); + void ipip_input(struct mbuf *, int); + diff --git a/NetBSD/ip_input.c.diffs b/NetBSD/ip_input.c.diffs new file mode 100644 index 0000000000000..b5ef509db3206 --- /dev/null +++ b/NetBSD/ip_input.c.diffs @@ -0,0 +1,37 @@ +*** /sys/netinet/ip_input.c.orig Sat Oct 14 12:51:10 1995 +--- /sys/netinet/ip_input.c Tue Feb 18 21:32:33 1997 +*************** +*** 80,85 **** +--- 80,89 ---- + int ipqmaxlen = IFQ_MAXLEN; + struct in_ifaddrhead in_ifaddr; + struct ifqueue ipintrq; ++ #if defined(IPFILTER_LKM) || defined(IPFILTER) ++ int fr_check __P((struct ip *, int, struct ifnet *, int, struct mbuf *)); ++ int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif + + /* + * We need to save the IP options in case a protocol wants to respond +*************** +*** 216,221 **** +--- 220,238 ---- + m_adj(m, ip->ip_len - m->m_pkthdr.len); + } + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * Check if we want to allow this packet to be processed. ++ * Consider it to be bad if not. ++ */ ++ if (fr_checkp) { ++ struct mbuf *m1 = m; ++ ++ if ((*fr_checkp)(ip, hlen, m->m_pkthdr.rcvif, 0, &m1) || !m1) ++ goto next; ++ ip = mtod(m = m1, struct ip *); ++ } ++ #endif + /* + * Process options and, if not destined for us, + * ship it on. ip_dooptions returns 1 when an diff --git a/NetBSD/ip_output.c.diffs b/NetBSD/ip_output.c.diffs new file mode 100644 index 0000000000000..d45841865a8f0 --- /dev/null +++ b/NetBSD/ip_output.c.diffs @@ -0,0 +1,36 @@ +*** /sys/netinet/ip_output.c.orig Sat Oct 14 12:51:15 1995 +--- /sys/netinet/ip_output.c Tue Feb 18 21:36:10 1997 +*************** +*** 60,65 **** +--- 60,69 ---- + static struct mbuf *ip_insertoptions __P((struct mbuf *, struct mbuf *, int *)); + static void ip_mloopback + __P((struct ifnet *, struct mbuf *, struct sockaddr_in *)); ++ #if defined(IPFILTER_LKM) || defined(IPFILTER) ++ extern int fr_check __P((struct ip *, int, struct ifnet *, int, struct mbuf *)); ++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif + + /* + * IP output. The packet in mbuf chain m contains a skeletal IP +*************** +*** 277,282 **** +--- 281,298 ---- + m->m_flags &= ~M_BCAST; + + sendit: ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * looks like most checking has been done now...do a filter check ++ */ ++ if (fr_checkp) { ++ struct mbuf *m1 = m; ++ ++ if ((error = (*fr_checkp)(ip, hlen, ifp, 1, &m1)) || !m1) ++ goto done; ++ ip = mtod(m = m1, struct ip *); ++ } ++ #endif + /* + * If small enough for interface, can just send directly. + */ diff --git a/NetBSD/kinstall b/NetBSD/kinstall new file mode 100755 index 0000000000000..fa9e3674b469e --- /dev/null +++ b/NetBSD/kinstall @@ -0,0 +1,88 @@ +#! /bin/sh +# +# kinstall/minstall - install patches to kernel sources +# +# WARNING: This script should be run exactly once on a virgin system +# +PATH=/sbin:/usr/sbin:/bin:/usr/bin; export PATH + +# try to bomb out fast if anything fails.... +set -e + +argv0=`basename $0` +dir=`pwd` +karch=`uname -m` +archdir="/sys/arch/$karch" +confdir="$archdir/conf" + +case "$dir" in +*/NetBSD ) + cd .. + ;; +esac + +echo -n "Installing " +for i in ip_fil.[ch] ip_nat.[ch] ip_frag.[ch] ip_state.[ch] fil.c ip_compat.h ip_proxy.[ch] ip_{ftp,rcmd}_pxy.c ip_auth.[ch] ip_log.c; do + echo -n "$i " + cp $i /sys/netinet/ + chmod 644 /sys/netinet/$i + switch ($i) + case *.h: + /bin/cp $i /usr/include/netinet/$i + chmod 644 /usr/include/netinet/$i + breaksw + endsw +done +echo +echo "Patching ip_input.c, ip_output.c and in_proto.c ..." +cat NetBSD/ip*.c.diffs | (cd /sys/netinet; patch) + +if [ -f /sys/conf/files.newconf ]; then + echo "Patching in_proto.c ..." + cat NetBSD/in_proto.c.old.diffs | (cd /sys/netinet; patch) + echo "Patching $archdir/$karch/conf.c" + cat NetBSD/conf.c.old.diffs | (cd $archdir/$karch; patch) + echo "Patching /sys/conf/files.newconf ..." + cat NetBSD/files.newconf.diffs | (cd /sys/conf; patch) + echo "Patching /sys/conf/files ..." + cat NetBSD/files.diffs | (cd /sys/conf; patch) +fi +if [ -f /sys/conf/files.oldconf ]; then + echo "Patching in_proto.c ..." + cat NetBSD/in_proto.c.diffs | (cd /sys/netinet; patch) + echo "Patching $archdir/$karch/conf.c" + cat NetBSD/conf.c.diffs | (cd $archdir/$karch; patch) + echo "Patching /sys/conf/files.oldconf ..." + cat NetBSD/files.oldconf.diffs | (cd /sys/conf; patch) + echo "Patching /sys/conf/files ..." + cat NetBSD/filez.diffs | (cd /sys/conf; patch) +fi + +echo -n "Kernel configuration to update [GENERIC] " +read newconfig junk + +if [ -n "$newconfig" ] ; then + config="$confdir/$newconfig" +else + newconfig="$confdir/GENERIC" +fi + +if egrep 'options.*IPFILTER' $confdir/$newconfig > /dev/null 2>&1 ; then + echo "$newconfig already contains proper options statement..." + echo 'You will now need to build a new kernel.' +else + echo "Backing up $newconfig to .bak and adding IPFILTER options..." + if [ -f $confdir/$newconfig ]; then + mv $confdir/$newconfig $confdir/$newconfig.bak + fi + if [ -d $archdir/compile/$newconfig ]; then + mv $archdir/compile/$newconfig $archdir/compile/$newconfig.bak + fi + awk '{print $0} $2=="INET"{print "options IPFILTER"}' \ + $confdir/$newconfig.bak > $confdir/$newconfig + + echo 'You will now need to run "config" and build a new kernel.' +fi + +exit 0 + diff --git a/NetBSD/minstall b/NetBSD/minstall new file mode 100755 index 0000000000000..b94d2a1dea34e --- /dev/null +++ b/NetBSD/minstall @@ -0,0 +1,67 @@ +#! /bin/sh +# +# kinstall/minstall - install patches to kernel sources +# +# WARNING: This script should be run exactly once on a virgin system +# +PATH=/sbin:/usr/sbin:/bin:/usr/bin; export PATH + +# try to bomb out fast if anything fails.... +set -e + +argv0=`basename $0` +dir=`pwd` +karch=`uname -m` +archdir="/sys/arch/$karch" +confdir="$archdir/conf" + +case "$dir" in +*/NetBSD ) + cd .. + ;; +esac + +echo "Patching ip_input.c, ip_output.c and in_proto.c ..." +cat NetBSD/i*.c.diffs | (cd /sys/netinet; patch) + +if [ -f /sys/conf/files.newconf ]; then + echo "Patching /sys/conf/files.newconf ..." + cat NetBSD/files.newconf.diffs | (cd /sys/conf; patch) + echo "Patching /sys/conf/files ..." + cat NetBSD/files.diffs | (cd /sys/conf; patch) +fi +if [ -f /sys/conf/files.oldconf ]; then + echo "Patching /sys/conf/files.oldconf ..." + cat NetBSD/files.oldconf.diffs | (cd /sys/conf; patch) + echo "Patching /sys/conf/files ..." + cat NetBSD/filez.diffs | (cd /sys/conf; patch) +fi + +echo -n "Kernel configuration to update [GENERIC] " +read newconfig junk + +if [ -n "$newconfig" ] ; then + config="$confdir/$newconfig" +else + newconfig="$confdir/GENERIC" +fi + +if egrep '^options.*IPFILTER_LKM' $confdir/$newconfig > /dev/null 2>&1 ; then + echo "$newconfig already contains proper options statement..." + echo 'You will now need to build a new kernel.' +else + echo "Backing up $newconfig to .bak and adding IPFILTER options..." + if [ -f $confdir/$newconfig ]; then + mv $confdir/$newconfig $confdir/$newconfig.bak + fi + if [ -d $archdir/compile/$newconfig ]; then + mv $archdir/compile/$newconfig $archdir/compile/$newconfig.bak + fi + grep -v IPFILTER $confdir/$newconfig.bak | \ + awk '{print $0} $2=="INET"{print "options IPFILTER_LKM"}' \ + > $confdir/$newconfig + + echo 'You will now need to run "config" and build a new kernel.' +fi + +exit 0 diff --git a/NetBSD/unkinstall b/NetBSD/unkinstall new file mode 100755 index 0000000000000..349ee88ed558d --- /dev/null +++ b/NetBSD/unkinstall @@ -0,0 +1,68 @@ +#! /bin/sh +# +# kinstall/minstall - install patches to kernel sources +# +# WARNING: This script should be run exactly once on a virgin system +# +PATH=/sbin:/usr/sbin:/bin:/usr/bin; export PATH + +# try to bomb out fast if anything fails.... +set -e + +argv0=`basename $0` +dir=`pwd` +karch=`uname -m` +archdir="/sys/arch/$karch" +confdir="$archdir/conf" + +case "$dir" in +*/NetBSD ) + cd .. + ;; +esac + +echo -n "Removing " +for i in ip_fil.[ch] ip_nat.[ch] ip_frag.[ch] ip_state.[ch] fil.c ip_compat.h ip_proxy.[ch] ip_ftp_pxy.c ip_auth.[ch] ip_log.c +do + echo -n "/sys/netinet/$i " + /bin/rm -f /sys/netinet/$i +done +echo + +echo "Unpatching ip_input.c and ip_output.c ..." +cat NetBSD/ip*.c.diffs | (cd /sys/netinet; patch -R) + +if [ -f /sys/conf/files.newconf ]; then + echo "Unpatching in_proto.c ..." + cat NetBSD/in_proto.c.old.diffs | (cd /sys/netinet; patch -R) + echo "Unpatching $archdir/$karch/conf.c" + cat NetBSD/conf.c.old.diffs | (cd $archdir/$karch; patch -R) + echo "Unpatching /sys/conf/files.newconf ..." + cat NetBSD/files.newconf.diffs | (cd /sys/conf; patch -R) + echo "Unpatching /sys/conf/files ..." + cat NetBSD/files.diffs | (cd /sys/conf; patch -R) +fi +if [ -f /sys/conf/files.oldconf ]; then + echo "Unpatching in_proto.c ..." + cat NetBSD/in_proto.c.diffs | (cd /sys/netinet; patch -R) + echo "Unpatching $archdir/$karch/conf.c" + cat NetBSD/conf.c.diffs | (cd $archdir/$karch; patch -R) + echo "Unpatching /sys/conf/files.oldconf ..." + cat NetBSD/files.oldconf.diffs | (cd /sys/conf; patch -R) + echo "Unpatching /sys/conf/files ..." + cat NetBSD/filez.diffs | (cd /sys/conf; patch -R) +fi + +echo -n "Kernel configuration to update [GENERIC] " +read newconfig junk + +if [ -n "$newconfig" ] ; then + config="$confdir/$newconfig" +else + newconfig="$confdir/GENERIC" +fi + +mv $archdir/compile/$newconfig $archdir/compile/$newconfig.bak +egrep -v 'IPFILTER' $confdir/$newconfig.bak > $confdir/$newconfig +echo 'You will now need to run "config" and build a new kernel.' +exit 0 diff --git a/NetBSD/unminstall b/NetBSD/unminstall new file mode 100755 index 0000000000000..866b7392bfc45 --- /dev/null +++ b/NetBSD/unminstall @@ -0,0 +1,52 @@ +#! /bin/sh +# +# kinstall/minstall - install patch -Res to kernel sources +# +# WARNING: This script should be run exactly once on a virgin system +# +PATH=/sbin:/usr/sbin:/bin:/usr/bin; export PATH + +# try to bomb out fast if anything fails.... +set -e + +argv0=`basename $0` +dir=`pwd` +karch=`uname -m` +archdir="/sys/arch/$karch" +confdir="$archdir/conf" + +case "$dir" in +*/NetBSD ) + cd .. + ;; +esac + +echo "Unpatching ip_input.c, ip_output.c and in_proto.c ..." +cat NetBSD/i*.c.diffs | (cd /sys/netinet; patch -R) + +if [ -f /sys/conf/files.newconf ]; then + echo "Unpatching /sys/conf/files.newconf ..." + cat NetBSD/files.newconf.diffs | (cd /sys/conf; patch -R) + echo "Unpatching /sys/conf/files ..." + cat NetBSD/files.diffs | (cd /sys/conf; patch -R) +fi +if [ -f /sys/conf/files.oldconf ]; then + echo "Unpatching /sys/conf/files.oldconf ..." + cat NetBSD/files.oldconf.diffs | (cd /sys/conf; patch -R) + echo "Unpatching /sys/conf/files ..." + cat NetBSD/filez.diffs | (cd /sys/conf; patch -R) +fi + +echo -n "Kernel configuration to update [GENERIC] " +read newconfig junk + +if [ -n "$newconfig" ] ; then + config="$confdir/$newconfig" +else + newconfig="$confdir/GENERIC" +fi + +mv $confdir/$newconfig $confdir/$newconfig.bak +egrep -v IPFILTER $confdir/$newconfig > $confdir/$newconfig +echo 'You will now need to run "config" and build a new kernel.' +exit 0 diff --git a/OSF/Makefile b/OSF/Makefile new file mode 100644 index 0000000000000..c9bfcc37ae306 --- /dev/null +++ b/OSF/Makefile @@ -0,0 +1,409 @@ +# +# Copyright (C) 2012 by Darren Reed. +# +# See the IPFILTER.LICENCE file for details on licencing. +# +BINDEST=/usr/sbin +SBINDEST=/sbin +MANDIR=/usr/share/man +CC=cc -std1 -msg_disable expandeddefined +#\ -msg_disable bitnotint,expandeddefined,intrinsicdecl,ptrmismatch,subscrbounds +CFLAGS=-g -I$(TOP) +# +# For Tru64 5.1 +# +CPU=`uname -m` +MACHASSERT=`/bin/ls -1 /usr/sys/*/mach_assert.h -print | head -1` +KDIR=`dirname ${MACHASSERT}` +INC=-I/usr/include -I$(KDIR) -I/usr/sys/include +DEFX=-DLANGUAGE_C -DUERF -DOSF -DMACH -DRT_SEM -DKERNEL -D_KERNEL -D_BSD -D_USE_KERNEL_PROTOS -compress -MD -no_excpt -nointrinsics -Wg,-unroll,1 -Wb,-static -Wco,-nofloat -msg_enable cvtdiftypes,warnimplfunc,macroredef,lvaluecast,uselesstyped -msg_inform cvtdiftypes,warnimplfunc,macroredef,lvaluecast,uselesstyped -msg_enable uninit1,falloffend,intrinsicint,outtoomany,outtoofew,questcompare,storclsdcl,tentredef -msg_warn uninit1,falloffend,intrinsicint,outtoomany,outtoofew,questcompare,storclsdcl,tentredef -msg_enable othermember -msg_error othermember -Umips -UMIPS -U__intel__ -D__alpha -D__digital__ -D__arch64__ -DUNIX_LOCKS=1 +DEF=-D$(CPU) -D__$(CPU)__ -DINET -DKERNEL -D_KERNEL $(INC) $(DEFX) +IPDEF=$(DEF) -DGATEWAY -DDIRECTED_BROADCAST +VNODESHDIR=/sys/kern +LKM=if_ipl.o +DLKM= +OBJ=. +TOP=.. +HERE=OSF/$(OSREV) +TRU64=`uname -v` +DEST=. +MFLAGS="BINDEST=$(BINDEST)" "SBINDEST=$(SBINDEST)" "MANDIR=$(MANDIR)" \ + 'CFLAGS=$(CFLAGS)' "IPFLKM=$(IPFLKM)" \ + "IPFLOG=$(IPFLOG)" "LOGFAC=$(LOGFAC)" "POLICY=$(POLICY)" \ + "DEBUG=$(DEBUG)" "DCPU=$(CPU)" "CPUDIR=$(CPUDIR)" \ + "LOOKUP=$(LOOKUP)" "XID=$(XID)" "SCAN=$(SCAN)" "ALLOPTS=$(ALLOPTS)" +LIBS=-L. -lipf +CCARGS=$(DEBUG) $(CFLAGS) -I. -DTRU64=$(TRU64) +EXTRA=$(ALLOPTS) +# +########## ########## ########## ########## ########## ########## ########## +# +CP=/bin/cp +RM=/bin/rm +CHMOD=/bin/chmod +INSTALL=$(TOP)/bsdinstall +# +MODOBJS=md5.o arc4random.o tru64.o radix_ipf.o \ + ip_fil.o fil.o ip_nat.o ip_frag.o ip_state.o ip_nat6.o \ + ip_proxy.o ip_auth.o ip_log.o ip_pool.o ip_htable.o ip_lookup.o \ + ip_dstlist.o ip_sync.o ip_scan.o ip_rules.o +DFLAGS=$(DEBUG) -DTRU64=$(TRU64) $(IPFLKM) $(IPFLOG) $(DEF) $(CFLAGS) $(DLKM) \ + $(IPFBPF) $(LOOKUP) $(XID) -I. +IPF=ipf.o ipfcomp.o ipf_y.o ipf_l.o +IPT=ipftest.o fil_u.o ip_frag_u.o ip_state_u.o ip_nat_u.o ip_nat6_u.o \ + ip_proxy_u.o ip_auth_u.o ip_fil_u.o ip_sync_u.o ip_scan_u.o \ + ip_log_u.o ip_pool_u.o ip_htable_u.o ip_lookup_u.o ip_rules_u.o \ + ipf_y.o ipf_l.o ipnat_y.o ipnat_l.o ippool_y.o ippool_l.o \ + md5_u.o radix_ipf_u.o ip_dstlist_u.o +IPNAT=ipnat.o ipnat_y.o ipnat_l.o +IPMON=ipmon.o ipmon_y.o ipmon_l.o +IPPOOL=ippool_y.o ippool_l.o kmem.o ippool.o +FILS=ipfstat.o +LIBSRC=$(TOP)/lib +RANLIB=ranlib +AROPTS=crs +TOOL=$(TOP)/tools + +include $(TOP)/lib/Makefile + +build all: ./libipf.a ipf ipfs ipfstat ipftest ipmon ipnat \ + ippool ipscan ipsyncm ipsyncs $(LKM) + -sh -c 'for i in ipf ipftest ipmon ippool ipnat ipscan ipsyncm ipsyncs; do /bin/rm -f $(TOP)/$$i; ln -s `pwd`/$$i $(TOP); done' + +ipfstat: $(FILS) ./libipf.a + $(CC) $(CCARGS) $(STATETOP_CFLAGS) $(STATETOP_INC) $(FILS) \ + -o $@ $(LIBS) $(STATETOP_LIB) + +ipf: $(IPF) ./libipf.a + $(CC) $(CCARGS) $(IPF) -o $@ $(LIBS) $(LIBBPF) + +ipftest: $(IPT) ./libipf.a + $(CC) $(CCARGS) $(IPT) -o $@ $(LIBS) $(LIBBPF) + +ipnat: $(IPNAT) ./libipf.a + $(CC) $(CCARGS) $(IPNAT) -o $@ $(LIBS) + +ipfs: ipfs.o ./libipf.a + $(CC) $(CCARGS) ipfs.o -o $@ $(LIBS) + +ipsyncm: ipsyncm.o ./libipf.a + $(CC) $(CCARGS) ipsyncm.o -o $@ $(LIBS) + +ipsyncs: ipsyncs.o ./libipf.a + $(CC) $(CCARGS) ipsyncs.o -o $@ $(LIBS) + +ipsyncm.o: $(TOOL)/ipsyncm.c $(TOP)/ip_sync.h + $(CC) $(CCARGS) -c $(TOOL)/ipsyncm.c -o $@ + +ipsyncs.o: $(TOOL)/ipsyncs.c $(TOP)/ip_sync.h + $(CC) $(CCARGS) -c $(TOOL)/ipsyncs.c -o $@ + +tests: + (cd test; make ) + +ipfstat.o: $(TOOL)/ipfstat.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_frag.h \ + $(TOP)/ip_compat.h $(TOP)/ip_state.h $(TOP)/ip_nat.h + $(CC) $(CCARGS) $(STATETOP_CFLAGS) $(STATETOP_INC) \ + -c $(TOOL)/ipfstat.c -o $@ + +ipfs.o: $(TOOL)/ipfs.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_state.h \ + $(TOP)/ip_nat.h + $(CC) $(CCARGS) -c $(TOOL)/ipfs.c -o $@ + +fil_u.o: $(TOP)/fil.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) $(FIXRADIX) $(IPFBPF) -c $(TOP)/fil.c -o $@ + +ipf.o: $(TOOL)/ipf.c $(TOP)/ip_fil.h $(TOP)/ipf.h + $(CC) $(CCARGS) -c $(TOOL)/ipf.c -o $@ + +ipf_y.o: ipf_y.c ipf_y.h $(TOP)/ipf.h ipf_l.h + $(CC) $(CCARGS) $(IPFBPF) -c ipf_y.c -o $@ + +ipf_l.o: ipf_l.c ipf_y.h $(TOP)/ipf.h ipf_l.h + $(CC) $(CCARGS) -I. -c ipf_l.c -o $@ + +ipf_y.h ipf_y.c: $(TOOL)/ipf_y.y $(TOP)/ip_pool.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ipf_l.c ipf_l.h: $(TOOL)/lexer.c $(TOP)/ipf.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ipfcomp.o: $(TOOL)/ipfcomp.c $(TOP)/ip_fil.h $(TOP)/ipf.h + $(CC) $(CCARGS) -c $(TOOL)/ipfcomp.c -o $@ + +ipftest.o: $(TOOL)/ipftest.c $(TOP)/ip_fil.h $(TOP)/ipt.h $(TOP)/ipf.h + $(CC) $(CCARGS) -c $(TOOL)/ipftest.c -o $@ + +ipnat.o: $(TOOL)/ipnat.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_nat.h + $(CC) $(CCARGS) -c $(TOOL)/ipnat.c -o $@ + +ipnat_y.o: ipnat_y.c ipnat_y.h $(TOP)/ip_fil.h $(TOP)/ip_compat.h \ + $(TOP)/ipf.h $(TOP)/ip_nat.h ipnat_l.h + $(CC) $(CCARGS) -c ipnat_y.c -o $@ + +ipnat_l.o: ipnat_l.c ipnat_y.h $(TOP)/ip_fil.h $(TOP)/ip_compat.h \ + $(TOP)/ipf.h $(TOP)/ip_nat.h ipnat_l.h + $(CC) $(CCARGS) -I. -c ipnat_l.c -o $@ + +ipnat_y.h ipnat_y.c: $(TOOL)/ipnat_y.y $(TOP)/ip_nat.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ipnat_l.c ipnat_l.h: $(TOOL)/lexer.c $(TOP)/ip_nat.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ip_rules.c: $(TOP)/rules/ip_rules $(TOP)/tools/ipfcomp.c ipf + ./ipf -cc -nf $(TOP)/rules/ip_rules + +$(TOP)/ip_rules.h: ip_rules.c + if [ ! -f $(TOP)/ip_rules.h ] ; then \ + /bin/mv -f ip_rules.h $(TOP); \ + else \ + touch $(TOP)/ip_rules.h; \ + fi + +ip_nat_u.o: $(TOP)/ip_nat.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_nat.c -o $@ + +ip_nat6_u.o: $(TOP)/ip_nat6.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_nat6.c -o $@ + +ip_proxy_u.o: $(TOP)/ip_proxy.c $(TOP)/ip_proxy.h $(TOP)/ip_compat.h \ + $(TOP)/ip_ftp_pxy.c $(TOP)/ip_rcmd_pxy.c $(TOP)/ip_raudio_pxy.c \ + $(TOP)/ip_rpcb_pxy.c $(TOP)/ip_ipsec_pxy.c $(TOP)/ip_nat.h \ + $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_proxy.c -o $@ + +ip_frag_u.o: $(TOP)/ip_frag.c $(TOP)/ip_frag.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_frag.c -o $@ + +ip_state_u.o: $(TOP)/ip_state.c $(TOP)/ip_state.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(TOP)/ip_nat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_state.c -o $@ + +ip_auth_u.o: $(TOP)/ip_auth.c $(TOP)/ip_auth.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_auth.c -o $@ + +ip_fil_u.o: $(TOP)/ip_fil.c $(TOP)/ip_fil.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) $(FIXRADIX) -c $(TOP)/ip_fil.c -o $@ + +ip_scan_u.o: $(TOP)/ip_scan.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_scan.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_scan.c -o $@ + +ip_sync_u.o: $(TOP)/ip_sync.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_sync.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_sync.c -o $@ + +ip_rules_u.o: ip_rules.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(TOP)/ip_rules.h + $(CC) $(CCARGS) $(EXTRA) -c ip_rules.c -o $@ + +ip_log_u.o: $(TOP)/ip_log.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_log.c -o $@ + +ip_pool_u.o: $(TOP)/ip_pool.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_pool.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_pool.c -o $@ + +ip_htable_u.o: $(TOP)/ip_htable.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_htable.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_htable.c -o $@ + +ip_dstlist_u.o: $(TOP)/ip_dstlist.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_dstlist.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_dstlist.c -o $@ + +ip_lookup_u.o: $(TOP)/ip_lookup.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_lookup.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_lookup.c -o $@ + +bpf_filter_u.o: $(TOP)/bpf_filter.c $(TOP)/pcap-ipf.h $(TOP)/bpf-ipf.h + $(CC) $(CCARGS) -c $(TOP)/bpf_filter.c -o $@ + +md5_u.o: $(TOP)/md5.c $(TOP)/md5.h + $(CC) $(CCARGS) -c $(TOP)/md5.c -o $@ + +radix_ipf_u.o: $(TOP)/radix_ipf.c $(TOP)/radix_ipf.h + $(CC) $(CCARGS) -c $(TOP)/radix_ipf.c -o $@ + +if_ipl.o: $(MODOBJS) + ld -r -dc $(MODOBJS) -o $(LKM) + ${RM} -f if_ipl + +fil.o: $(TOP)/fil.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_compat.h $(TOP)/ipl.h + $(CC) $(POLICY) $(DFLAGS) $(IPFBPF) -c $(TOP)/fil.c -o $@ + +ip_nat.o: $(TOP)/ip_nat.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(DFLAGS) -c $(TOP)/ip_nat.c -o $@ + +ip_nat6.o: $(TOP)/ip_nat6.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(DFLAGS) -c $(TOP)/ip_nat6.c -o $@ + +ip_frag.o: $(TOP)/ip_frag.c $(TOP)/ip_frag.h $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(DFLAGS) -c $(TOP)/ip_frag.c -o $@ + +ip_state.o: $(TOP)/ip_state.c $(TOP)/ip_state.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(TOP)/ip_nat.h + $(CC) $(DFLAGS) -DIPSTATE_SIZE=127 -c $(TOP)/ip_state.c -o $@ + +ip_proxy.o: $(TOP)/ip_proxy.c $(TOP)/ip_proxy.h $(TOP)/ip_compat.h \ + $(TOP)/ip_ftp_pxy.c $(TOP)/ip_rcmd_pxy.c $(TOP)/ip_raudio_pxy.c \ + $(TOP)/ip_rpcb_pxy.c $(TOP)/ip_ipsec_pxy.c $(TOP)/ip_nat.h \ + $(TOP)/ip_nat.h $(TOP)/ip_fil.h + $(CC) $(DFLAGS) -c $(TOP)/ip_proxy.c -o $@ + +ip_auth.o: $(TOP)/ip_auth.c $(TOP)/ip_auth.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h + $(CC) $(DFLAGS) -c $(TOP)/ip_auth.c -o $@ + +ip_fil.o: $(TOP)/ip_fil_osf.c $(TOP)/ip_fil.h $(TOP)/ip_compat.h $(TOP)/ip_nat.h + $(CC) $(DFLAGS) $(COMPIPF) -c $(TOP)/ip_fil_osf.c -o $@ + +ip_log.o: $(TOP)/ip_log.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(DFLAGS) -c $(TOP)/ip_log.c -o $@ + +ip_scan.o: $(TOP)/ip_scan.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(TOP)/ip_scan.h + $(CC) $(DFLAGS) -c $(TOP)/ip_scan.c -o $@ + +ip_sync.o: $(TOP)/ip_sync.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(TOP)/ip_sync.h + $(CC) $(DFLAGS) -c $(TOP)/ip_sync.c -o $@ + +radix_ipf.o: $(TOP)/radix_ipf.c $(TOP)/radix_ipf.h + $(CC) $(DFLAGS) -c $(TOP)/radix_ipf.c -o $@ + +ip_pool.o: $(TOP)/ip_pool.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_pool.h $(TOP)/radix_ipf.h + $(CC) $(DFLAGS) $(FIXRADIX) -c $(TOP)/ip_pool.c -o $@ + +ip_htable.o: $(TOP)/ip_htable.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_htable.h + $(CC) $(DFLAGS) -c $(TOP)/ip_htable.c -o $@ + +ip_dstlist.o: $(TOP)/ip_dstlist.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_dstlist.h + $(CC) $(DFLAGS) -c $(TOP)/ip_dstlist.c -o $@ + +ip_lookup.o: $(TOP)/ip_lookup.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_lookup.h + $(CC) $(DFLAGS) $(FIXRADIX) -c $(TOP)/ip_lookup.c -o $@ + +ip_rules.o: ip_rules.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(TOP)/ip_rules.h + $(CC) -I. $(DFLAGS) -c ip_rules.c -o $@ + +ip_rulesx.o: ip_rules.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(TOP)/ip_rules.h + $(CC) -I. -DIPFILTER_COMPILED $(DFLAGS) -c ip_rules.c -o $@ + +tru64.o: $(TOP)/tru64.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h + $(CC) $(DFLAGS) -c $(TOP)/tru64.c -o $@ + +md5.o: $(TOP)/md5.c $(TOP)/md5.h + $(CC) $(DFLAGS) -c $(TOP)/md5.c -o $@ + +arc4random.o: $(TOP)/arc4random.c $(TOP)/md5.h + $(CC) $(DFLAGS) -DNEED_LOCAL_RAND=1 -c $(TOP)/arc4random.c -o $@ + +ipmon: $(IPMON) ./libipf.a + $(CC) $(CCARGS) $(LOGFAC) $(IPMON) -o $@ $(LIBS) -ll + +ipmon.o: $(TOOL)/ipmon.c $(TOP)/ipmon.h + $(CC) $(CCARGS) $(LOGFAC) -c $(TOOL)/ipmon.c -o $@ + +ipmon_y.o: ipmon_y.c ipmon_y.h $(TOP)/ipmon.h ipmon_l.h + $(CC) $(CCARGS) -c ipmon_y.c -o $@ + +ipmon_l.o: ipmon_l.c ipmon_y.h $(TOP)/ipmon.h ipmon_l.h + $(CC) $(CCARGS) -I. -c ipmon_l.c -o $@ + +ipmon_y.h ipmon_y.c: $(TOOL)/ipmon_y.y $(TOP)/ipmon.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ipmon_l.c ipmon_l.h: $(TOOL)/lexer.c $(TOP)/ipmon.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ipscan: ipscan_y.o ipscan_l.o + $(CC) $(DEBUG) ipscan_y.o ipscan_l.o -o $@ -ll $(LIBS) + +ipscan_y.o: ipscan_y.c ipscan_y.h $(TOP)/ip_scan.h ipscan_l.h + $(CC) $(CCARGS) -c ipscan_y.c -o $@ + +ipscan_l.o: ipscan_l.c ipscan_y.h $(TOP)/ip_scan.h ipscan_l.h + $(CC) $(CCARGS) -I. -c ipscan_l.c -o $@ + +ipscan_y.h ipscan_y.c: $(TOOL)/ipscan_y.y $(TOP)/ip_scan.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ipscan_l.c ipscan_l.h: $(TOOL)/lexer.c $(TOP)/ip_scan.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ippool: $(IPPOOL) + $(CC) $(DEBUG) -I. $(CFLAGS) $(IPPOOL) -o $@ $(LIBS) -ll + +ippool.o: $(TOOL)/ippool.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_pool.h + $(CC) $(CCARGS) -c $(TOOL)/ippool.c -o $@ + +ippool_y.o: ippool_y.c ippool_y.h $(TOP)/ip_pool.h ippool_l.h + $(CC) $(CCARGS) -c ippool_y.c -o $@ + +ippool_l.o: ippool_l.c ippool_y.h $(TOP)/ip_pool.h ippool_l.h + $(CC) $(CCARGS) -I. -c ippool_l.c -o $@ + +ippool_y.h ippool_y.c: $(TOOL)/ippool_y.y $(TOP)/ip_pool.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ippool_l.c ippool_l.h: $(TOOL)/lexer.c $(TOP)/ip_pool.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +.y.c: + +.l.c: + +clean: + ${RM} -f ../ipf ../ipnat ../ipmon ../ippool ../ipftest + ${RM} -f ../ipscan ../ipsyncm ../ipsyncs + ${RM} -f *.core *.o *.a *.o.d + ${RM} -f fils ipf ipfstat ipftest ipmon if_ipl ipnat + ${RM} -f $(LKM) ioconf.h *.ko setdef1.c setdef0.c setdefs.h + ${RM} -f ip_fil.c ipf_l.c ipf_y.c ipf_y.h ipf_l.h + ${RM} -f ipscan ipscan_y.c ipscan_y.h ipscan_l.c ipscan_l.h + ${RM} -f ippool ippool_y.c ippool_y.h ippool_l.c ippool_l.h + ${RM} -f ipnat_y.c ipnat_y.h ipnat_l.c ipnat_l.h + ${RM} -f ipmon_y.c ipmon_y.h ipmon_l.c ipmon_l.h + ${RM} -f ipscan ipscan_y.c ipscan_y.h ipscan_l.c y.tab.? lex.yy.c ipfs + ${RM} -f ipsyncm ipsyncs ip_rules.c ip_rules.h + -if [ -h sysconfigtab ] ; then /bin/rm -f sysconfigtab; fi + + ${MAKE} -f Makefile.ipsend ${MFLAGS} clean + -(for i in *; do \ + if [ -d $${i} -a -f $${i}/Makefile ] ; then \ + cd $${i}; (make TOP=../.. clean); cd ..; \ + rm $${i}/Makefile $${i}/Makefile.ipsend; \ + rmdir $${i}; \ + fi \ + done) + +install: + -$(CP) $(TOP)/ip_fil.h /usr/include/netinet/ip_fil.h + -$(CHMOD) 444 /usr/include/netinet/ip_fil.h + -mkdir -m 755 -p /usr/sys/io/ipfilter/ + echo /usr/sys/io/ipfilter: > /usr/sys/conf/ipfilter.list + /bin/rm -f /var/subsys/ipfilter.mth + ln -s ../../../subsys/device.mth /var/subsys/ipfilter.mth + -$(INSTALL) -c -g system -m 755 -o root if_ipl.o /sys/BINARY/ipfilter.mod + /bin/rm -f /var/subsys/ipfilter.mod + ln -s ../../../sys/BINARY/ipfilter.mod /var/subsys/ipfilter.mod + mkdir -p /usr/sys/io/ipfilter + chmod 755 /usr/sys/io/ipfilter + /bin/rm -f sysconfigtab + /bin/ln -s ../sysconfigtab . + -$(INSTALL) -c -g system -m 755 -o root sysconfigtab /usr/sys/io/ipfilter/ + -for i in ipf ipfs ipnat ipscan ipfstat; do \ + $(INSTALL) -s -c -g system -m 755 -o root $$i $(SBINDEST); \ + done + -for i in ipmon ipftest ipsyncs ipsyncm; do \ + $(INSTALL) -s -c -g system -m 755 -o root $$i $(BINDEST); \ + done + (cd $(TOP)/man; make INSTALL=../bsdinstall MANDIR=$(MANDIR) install; cd $(TOP)) + sync + -sysconfigdb -d ipfilter + sysconfigdb -f /usr/sys/io/ipfilter/sysconfigtab -a ipfilter diff --git a/OSF/Makefile.ipsend b/OSF/Makefile.ipsend new file mode 100644 index 0000000000000..09dc0ea57ecc8 --- /dev/null +++ b/OSF/Makefile.ipsend @@ -0,0 +1,78 @@ +MFLAGS="BINDEST=$(BINDEST)" "SBINDEST=$(SBINDEST)" "MANDIR=$(MANDIR)" \ + "CC=$(CC)" "CFLAGS=$(CFLAGS)" "DEBUG=$(DEBUG)" \ + "IPFLKM=$(IPFLKM)" "IPFLOG=$(IPFLOG)" \ + "LOGFAC=$(LOGFAC)" "POLICY=$(POLICY)" "LOOKUP=$(LOOKUP)" +FIXRADIX=-Dradix_node=ipf_radix_node -Dradix_node_head=ipf_radix_node_head +OBJS=ipsend.o ip.o ipsopt.o iplang_y.o iplang_l.o +IPFTO=ipft_ef.o ipft_hx.o ipft_pc.o ipft_sn.o ipft_td.o ipft_tx.o +ROBJS=ipresend.o ip.o resend.o +TOBJS=iptest.o iptests.o ip.o +UNIXOBJS=dlcommon.o sdlpi.o arp.o +OBJ=. +LIBS=-L$(OBJ) -lipf + +CC=cc -std1 -msg_disable expandeddefined,badsubscript +CFLAGS=-g -I$(TOP) +CCARGS=$(DEBUG) $(CFLAGS) -I. + +all nit sunos4 sunos4-nit build : ipsend ipresend iptest + +iplang_y.o: $(TOP)/iplang/iplang_y.y + (cd $(TOP)/iplang; $(MAKE) 'DESTDIR=../OSF/$(OSREV)' ) + +iplang_l.o: $(TOP)/iplang/iplang_l.l + (cd $(TOP)/iplang; $(MAKE) 'DESTDIR=../OSF/$(OSREV)' ) + +.c.o: + $(CC) $(CCARGS) -c $(TOP)/ipsend/$< -o $@ + +ipsend: $(OBJS) $(UNIXOBJS) + $(CC) $(DEBUG) $(OBJS) $(UNIXOBJS) -o $@ $(LIBS) -ll + +ipresend: $(ROBJS) $(UNIXOBJS) + $(CC) $(DEBUG) $(ROBJS) $(UNIXOBJS) -o $@ $(LIBS) + +iptest: $(TOBJS) $(UNIXOBJS) + $(CC) $(DEBUG) $(TOBJS) $(UNIXOBJS) -o $@ $(LIBS) + +clean: + rm -rf *.o core a.out ipsend ipresend iptest iplang_y.* iplang_l.* + +ipsend.o: $(TOP)/ipsend/ipsend.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/ipsend.c -o $@ +ipsopt.o: $(TOP)/ipsend/ipsopt.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/ipsopt.c -o $@ +ipresend.o: $(TOP)/ipsend/ipresend.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/ipresend.c -o $@ +ip.o: $(TOP)/ipsend/ip.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/ip.c -o $@ +resend.o: $(TOP)/ipsend/resend.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/resend.c -o $@ +ipft_sn.o: $(TOP)/ipft_sn.c + $(CC) $(CCARGS) -c $(TOP)/ipft_sn.c -o $@ +ipft_pc.o: $(TOP)/ipft_pc.c + $(CC) $(CCARGS) -c $(TOP)/ipft_pc.c -o $@ +iptest.o: $(TOP)/ipsend/iptest.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/iptest.c -o $@ +iptests.o: $(TOP)/ipsend/iptests.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/iptests.c -o $@ +sbpf.o: $(TOP)/ipsend/sbpf.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/sbpf.c -o $@ +snit.o: $(TOP)/ipsend/snit.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/snit.c -o $@ +sock.o: $(TOP)/ipsend/sock.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/sock.c -o $@ +arp.o: $(TOP)/ipsend/arp.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/arp.c -o $@ +44arp.o: $(TOP)/ipsend/44arp.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/44arp.c -o $@ +lsock.o: $(TOP)/ipsend/lsock.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/lsock.c -o $@ +slinux.o: $(TOP)/ipsend/slinux.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/slinux.c -o $@ +larp.o: $(TOP)/ipsend/larp.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/larp.c -o $@ +dlcommon.o: $(TOP)/ipsend/dlcommon.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/dlcommon.c -o $@ +sdlpi.o: $(TOP)/ipsend/sdlpi.c + $(CC) $(CCARGS) -c $(TOP)/ipsend/sdlpi.c -o $@ diff --git a/OSF/cpurev b/OSF/cpurev new file mode 100755 index 0000000000000..fc6cbbb0d10fb --- /dev/null +++ b/OSF/cpurev @@ -0,0 +1,6 @@ +#!/bin/sh +rev=`uname -r` +build=`uname -v` +model=`uname -m` +echo $rev.$build.$model +exit 0 diff --git a/OSF/ipfboot b/OSF/ipfboot new file mode 100644 index 0000000000000..e81f18fe5d313 --- /dev/null +++ b/OSF/ipfboot @@ -0,0 +1,181 @@ +#!/bin/sh +# +IPFBASE=/etc + +PATH=/bin:/sbin:/usr/sbin:${PATH} +IPFILCONF=${IPFBASE}/ipf.conf +IP6FILCONF=${IPFBASE}/ipf6.conf +IPNATCONF=${IPFBASE}/ipnat.conf +IPPOOLCONF=${IPFBASE}/ippool.conf +PFILCHECKED=no +if [ -d /var/run ] ; then + PIDFILE=/var/run/ipmon.pid +else + PIDFILE=${IPFBASE}/ipmon.pid +fi + + +logmsg() +{ + logger -p local0.emerg -t ipfilter "$1" + echo "$1" >&2 +} + + +getids() +{ + if [ -f $PIDFILE ] ; then + pid=`cat $PIDFILE 2>/dev/null` + else + pid=`pgrep ipmon` + fi +} + + +block_default_workaround() { + ipf -F a + echo "constructing minimal name resolution rules..." + NAMESERVERS=`cat /etc/resolv.conf 2>/dev/null| \ + nawk '/nameserver/ {printf "%s ", $2}' 2>/dev/null` + if [ -z "$NAMESERVERS" ] ; then + return + fi + for NS in $NAMESERVERS ; do + IF_TO_NS=`route -n get $NS 2>/dev/null| \ + nawk '$1 == "interface:" { print $NF ; exit }' \ + 2>/dev/null` + if [ -z "$IF_TO_NS" ] ; then + continue + fi + IP_TO_NS=`ifconfig $IF_TO_NS 2>/dev/null| \ + nawk 'NR == "2" { print $2 ; exit }' 2>/dev/null` + if [ -z "$IP_TO_NS" ] ; then + continue + fi + echo "pass out quick on $IF_TO_NS proto udp from $IP_TO_NS to $NS port = 53 keep state" | \ + ipf -f - + done +} + + +load_ipf_config() { + bad=0 + if [ -r ${IPFILCONF} ]; then + if `ipf -V | \ + nawk '$1 == "Default:" && $2 == "pass" { exit 1 }'` ; then + block_default_workaround + fi + ipf -IFa -f ${IPFILCONF} + if [ $? != 0 ]; then + echo "$0: load of ${IPFILCONF} into alternate set failed" + bad=1 + fi + fi + if [ -r ${IP6FILCONF} ]; then + ipf -6IFa -f ${IP6FILCONF} + if [ $? != 0 ]; then + echo "$0: load of ${IPFILCONF} into alternate set failed" + bad=1 + fi + fi + if [ $bad -eq 0 ] ; then + ipf -s -y + else + echo Not switching config due to load error. + fi +} + + +load_ipnat_config() { + if [ -r ${IPNATCONF} ]; then + ipnat -CF -f ${IPNATCONF} + if [ $? != 0 ]; then + echo "$0: load of ${IPNATCONF} failed" + else + ipf -y + fi + fi +} + + +load_ippool_config() { + if [ -r ${IPPOOLCONF} ]; then + ippool -F + ippool -f ${IPPOOLCONF} + if [ $? != 0 ]; then + echo "$0: load of ${IPPOOLCONF} failed" + fi + fi +} + + +case "$1" in + start) + getids + [ -n "$pid" ] && kill -TERM $pid 2>/dev/null +# [ -n "$ipfruleid" ] && modunload -i $ipfruleid 2>/dev/null +# [ -n "$ipfid" ] && modunload -i $ipfid 2>/dev/null + /sbin/sysconfig -c ipfilter + ipf -E + load_ippool_config + load_ipf_config + load_ipnat_config + ipmon -Ds + ;; + + stop) + getids + [ -n "$pid" ] && kill -TERM $pid + /bin/rm -f $PIDFILE + ipf -D +# [ -n "$ipfruleid" ] && modunload -i $ipfruleid 2>/dev/null +# [ -n "$ipfid" ] && modunload -i $ipfid + ;; + + pause) + getids + ipfs -l + ipfs -NS -w + ipf -D + if [ -f $PIDFILE ] ; then + if kill -0 $pid; then + kill -TERM $pid + else + cp /dev/null $PIDFILE + fi + fi + ;; + + resume) + getids + ipf -E + ipfs -R + load_ippool_config + load_ipf_config + load_ipnat_config + if [ -f $PIDFILE -a x$pid != x ] ; then + ipmon -Ds + fi + ;; + + reload) + load_ippool_config + load_ipf_config + load_ipnat_config + ;; + + reipf) + load_ipf_config + ;; + + reipnat) + load_ipnat_config + ;; + + *) + echo "Usage: $0 (start|stop|reload|reipf|reipnat|pause|resume)" >&2 + exit 1 + ;; + +esac +exit 0 diff --git a/OSF/sysconfigtab b/OSF/sysconfigtab new file mode 100644 index 0000000000000..813fbc6b50ec5 --- /dev/null +++ b/OSF/sysconfigtab @@ -0,0 +1,15 @@ +# /usr/sys/io/IPFILTER/sysconfigtab +# sysconfigtab file fragment for ipfilter driver +# +# Merge with /etc/sysconfigtab using sysconfigdb -a -f [this file] ipfilter + +ipfilter: + Module_Config_Name = ipfilter + Subsystem_Description = IPFilter driver + Device_User = root + Device_Group = 0 + Device_Major_Req = Same + Device_Char_Major = ANY + Device_Char_Files = ipl,ipnat,ipstate,ipauth,ipsync,ipscan,ippool,ipcount + Device_Char_Minor = 0,[1-6],7 + Device_Mode = 600 diff --git a/OpenBSD-2/2.9-IPv6.diffs b/OpenBSD-2/2.9-IPv6.diffs new file mode 100644 index 0000000000000..f04a7a13ff1c3 --- /dev/null +++ b/OpenBSD-2/2.9-IPv6.diffs @@ -0,0 +1,86 @@ +*** ip6_input.c.orig Sun Sep 2 12:51:02 2001 +--- ip6_input.c Mon Sep 3 22:25:23 2001 +*************** +*** 130,135 **** +--- 130,138 ---- + #ifdef PULLDOWN_TEST + static struct mbuf *ip6_pullexthdr __P((struct mbuf *, size_t, int)); + #endif ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif + + /* + * IP6 initialization: fill in IP6 protocol switch table. +*************** +*** 274,279 **** +--- 277,302 ---- + in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); + goto bad; + } ++ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * Check if we want to allow this packet to be processed. ++ * Consider it to be bad if not. ++ */ ++ if (fr_checkp != NULL) { ++ struct mbuf *m0 = m; ++ ++ if ((*fr_checkp)((struct ip *)ip6, sizeof(*ip6), ++ m->m_pkthdr.rcvif, 0, &m0)) { ++ return; ++ } ++ m = m0; ++ if (m == 0) { /* in case of 'fastroute' */ ++ return; ++ } ++ ip6 = mtod(m, struct ip6_hdr *); ++ } ++ #endif + + ip6stat.ip6s_nxthist[ip6->ip6_nxt]++; + +*** ip6_output.c.orig Sun Sep 2 12:51:21 2001 +--- ip6_output.c Mon Sep 3 22:27:46 2001 +*************** +*** 113,118 **** +--- 113,122 ---- + struct mbuf *ip6e_dest2; + }; + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif ++ + static int ip6_pcbopts __P((struct ip6_pktopts **, struct mbuf *, + struct socket *)); + static int ip6_setmoptions __P((int, struct ip6_moptions **, struct mbuf *)); +*************** +*** 910,915 **** +--- 914,938 ---- + m->m_pkthdr.rcvif = NULL; + } + ++ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * looks like most checking has been done now...do a filter check ++ */ ++ if (fr_checkp != NULL) { ++ struct mbuf *m1 = m; ++ if ((*fr_checkp)((struct ip *)ip6, sizeof(*ip6), ifp, 1, &m1)) { ++ error = EHOSTUNREACH; ++ goto done; ++ } ++ m = m1; ++ if (m1 == 0) { /* in case of 'fastroute' */ ++ error = 0; ++ goto done; ++ } ++ ip6 = mtod(m, struct ip6_hdr *); ++ } ++ #endif + /* + * Send the packet to the outgoing interface. + * If necessary, do IPv6 fragmentation before sending. diff --git a/OpenBSD-2/files.diffs b/OpenBSD-2/files.diffs new file mode 100644 index 0000000000000..a114acf709285 --- /dev/null +++ b/OpenBSD-2/files.diffs @@ -0,0 +1,14 @@ +*** files.FCS Thu May 1 06:21:14 1997 +--- files Mon Oct 27 14:08:53 1997 +*************** +*** 299,304 **** +--- 299,307 ---- + file netinet/ip_nat.c ipfilter + file netinet/ip_frag.c ipfilter + file netinet/ip_state.c ipfilter ++ file netinet/ip_proxy.c ipfilter ++ file netinet/ip_auth.c ipfilter ++ file netinet/ip_log.c ipfilter + file netinet/ip_ah.c inet & ipsec + file netinet/ip_esp.c inet & ipsec + file netinet/ip_espdes.c inet & ipsec diff --git a/test/regress/regress.sed b/OpenBSD-2/ipf-fastroute.patch-2.7 index e69de29bb2d1d..e69de29bb2d1d 100644 --- a/test/regress/regress.sed +++ b/OpenBSD-2/ipf-fastroute.patch-2.7 diff --git a/OpenBSD-2/kinstall b/OpenBSD-2/kinstall new file mode 100755 index 0000000000000..1835dec2b8a47 --- /dev/null +++ b/OpenBSD-2/kinstall @@ -0,0 +1,88 @@ +#! /bin/sh +# +# kinstall/minstall - install patches to kernel sources +# +# WARNING: This script should be run exactly once on a virgin system +# +PATH=/sbin:/usr/sbin:/bin:/usr/bin; export PATH + +argv0=`basename $0` +dir=`pwd` +karch=`uname -m` +archdir="/sys/arch/$karch" +confdir="$archdir/conf" + +case "$dir" in +*/OpenBSD-2 ) + cd .. + ;; +esac + +echo -n "Backing up existing kernel sources ..." +backup="" +for i in fil.c ip_fil.[ch] ip_frag.[ch] ip_nat.[ch] ip_state.[ch] ip_fil_compat.h; do + if [ -e /sys/netinet/$i ] ; then + backup="${backup} ${i}" + fi +done +if [ -n "$backup" ] ; then + ( cd /sys/netinet ; tar cf ipfbackup.tar $backup ) +fi +echo + +echo -n "Installing " +for i in ip_fil.[ch] fil.c ip_nat.[ch] ip_frag.[ch] ip_state.[ch] ip_proxy.[ch] ip_auth.[ch] ip_log.c ip_compat.h ipl.h ip_*_pxy.c; do + echo -n "$i " + cp $i /sys/netinet/ + chmod 644 /sys/netinet/$i + case $i in + *.h) + /bin/cp $i /usr/include/netinet/$i + chmod 644 /usr/include/netinet/$i + ;; + esac +done +echo + +if [ -f /sys/conf/files ] ; then + echo "Patching /sys/conf/files ..." + cat OpenBSD-2/files.diffs | (cd /sys/conf; patch) + ip_files=`egrep '^file.*ipfilter' /sys/conf/files | wc -l` + if [ $ip_files -lt 8 ] ; then + echo "Patching /sys/conf/files ..." + cat OpenBSD-2/files.diffs | (cd /sys/conf; patch) + fi +fi +if [ -f /sys/netinet/ip_fil_compat.h ] ; then + echo "Linking /sys/netinet/ip_compat.h to /sys/netinet/ip_fil_compat.h" + rm /sys/netinet/ip_fil_compat.h + ln -s /sys/netinet/ip_compat.h /sys/netinet/ip_fil_compat.h +fi + +echo -n "Kernel configuration to update [GENERIC] " +read newconfig junk + +if [ -n "$newconfig" ] ; then + config="$confdir/$newconfig" +else + newconfig="$confdir/GENERIC" +fi + +if egrep 'option.*IPFILTER' $confdir/$newconfig > /dev/null 2>&1 ; then + echo "$newconfig already contains proper options statement..." + echo 'You will now need to build a new kernel.' +else + echo "Backing up $newconfig to .bak and adding IPFILTER options..." + if [ -f $confdir/$newconfig ]; then + mv $confdir/$newconfig $confdir/$newconfig.bak + fi + if [ -d $archdir/compile/$newconfig ]; then + mv $archdir/compile/$newconfig $archdir/compile/$newconfig.bak + fi + awk '{print $0} $2=="INET"{print "options IPFILTER"}' \ + $confdir/$newconfig.bak > $confdir/$newconfig + + echo 'You will now need to run "config" and build a new kernel.' +fi + +exit 0 diff --git a/OpenBSD-2/mknewipf.sh b/OpenBSD-2/mknewipf.sh new file mode 100644 index 0000000000000..8f81719d92bb0 --- /dev/null +++ b/OpenBSD-2/mknewipf.sh @@ -0,0 +1,21 @@ +#!/bin/sh +# documented from +# http://www.tfsb.org/ipf-openbsd/ +ARCH=sparc +KERNEL=MULAN +IPF=ip-fil3.4.17 +rm -rf $IPF +tar zxf $IPF.tar.gz +cd $IPF +perl -pi -e "s/#STATETOP_CFLAGS=/STATETOP_CFLAGS=/" Makefile +perl -pi -e "s/#STATETOP_INC=$/STATETOP_INC=/" Makefile +perl -pi -e "s/#STATETOP_LIB=-lncurses/STATETOP_LIB=-lcurses/" Makefile +perl -pi -e "s/#INET6/INET6/" Makefile +make openbsd +make install-bsd +cd OpenBSD-2 +echo $KERNEL | ./kinstall >/dev/null 2>&1 +cd /usr/src/sys/arch/$ARCH/conf +config $KERNEL +cd /usr/src/sys/arch/$ARCH/compile/$KERNEL +make clean && make depend && make && mv /bsd /bsd.old && mv bsd /bsd && reboot diff --git a/OpenBSD-2/patch.1 b/OpenBSD-2/patch.1 new file mode 100644 index 0000000000000..29d088ac127e6 --- /dev/null +++ b/OpenBSD-2/patch.1 @@ -0,0 +1,21 @@ +*** net/if_bridge.c.orig Sat Mar 20 07:47:33 1999 +--- net/if_bridge.c Wed Sep 15 22:44:16 1999 +*************** +*** 55,62 **** + #include <netinet/in_var.h> + #include <netinet/ip.h> + #include <netinet/if_ether.h> +! #ifdef IPFILTER +! #include <netinet/ip_fil_compat.h> + #include <netinet/ip_fil.h> + #endif + #endif +--- 55,62 ---- + #include <netinet/in_var.h> + #include <netinet/ip.h> + #include <netinet/if_ether.h> +! #if (defined(IPFILTER) || defined(IPFILTER_LKM)) +! #include <netinet/ip_compat.h> + #include <netinet/ip_fil.h> + #endif + #endif diff --git a/OpenBSD-2/unkinstall b/OpenBSD-2/unkinstall new file mode 100644 index 0000000000000..a624dafc3a52c --- /dev/null +++ b/OpenBSD-2/unkinstall @@ -0,0 +1,53 @@ +#! /bin/sh +# +# kinstall/minstall - install patches to kernel sources +# +# WARNING: This script should be run exactly once on a virgin system +# +PATH=/sbin:/usr/sbin:/bin:/usr/bin; export PATH + +# try to bomb out fast if anything fails.... +set -e + +argv0=`basename $0` +dir=`pwd` +karch=`uname -m` +archdir="/sys/arch/$karch" +confdir="$archdir/conf" + +case "$dir" in +*/OpenBSD-2 ) + cd .. + ;; +esac + +echo -n "Removing " +for i in ip_fil.[ch] ip_nat.[ch] ip_frag.[ch] ip_state.[ch] fil.c ip_compat.h ip_proxy.[ch] ip_ftp_pxy.c ip_auth.[ch] ip_log.c +do + echo -n "/sys/netinet/$i " + /bin/rm -f /sys/netinet/$i +done +echo + +if [ -f /sys/netinet/ipfbackup.tar ] ; then + echo -n "Restoring old kernel sources" + ( cd /sys/netinet ; tar xpf ipfbackup.tar ) +fi +echo + +echo "Unpatching /sys/conf/files ..." +cat OpenBSD-2/files.diffs | (cd /sys/conf; patch -R) + +echo -n "Kernel configuration to update [GENERIC] " +read newconfig junk + +if [ -n "$newconfig" ] ; then + config="$confdir/$newconfig" +else + newconfig="$confdir/GENERIC" +fi + +mv $archdir/compile/$newconfig $archdir/compile/$newconfig.bak +egrep -v 'IPFILTER' $confdir/$newconfig.bak > $confdir/$newconfig +echo 'You will now need to run "config" and build a new kernel.' +exit 0 diff --git a/OpenBSD-3/3.0-MAKEDEV-diffs b/OpenBSD-3/3.0-MAKEDEV-diffs new file mode 100644 index 0000000000000..a371b2dc5c19f --- /dev/null +++ b/OpenBSD-3/3.0-MAKEDEV-diffs @@ -0,0 +1,612 @@ +diff -cr src.30/etc/etc.alpha/MAKEDEV src/etc/etc.alpha/MAKEDEV +*** src.30/etc/etc.alpha/MAKEDEV Thu Jul 5 12:54:06 2001 +--- src/etc/etc.alpha/MAKEDEV Fri Dec 28 12:43:16 2001 +*************** +*** 83,88 **** +--- 83,89 ---- + # *random inkernal random data source + # uk* SCSI Unknown device + # ss* SCSI scanners ++ # ipl IP filter log + # altq ALTQ control interface + # iop I2O controller device + +*************** +*** 161,167 **** + sh $this bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 + sh $this pf audio0 tun0 tun1 tun2 tun3 + sh $this ttyB0 ttyB1 tty00 tty01 lkm +! sh $this mmclock lpa0 lpt0 random + sh $this uk0 uk1 ss0 ss1 + sh $this ttyc0 ttyc1 ttyc2 ttyc3 ttyc4 ttyc5 ttyc6 ttyc7 + sh $this local xfs0 altq +--- 162,168 ---- + sh $this bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 + sh $this pf audio0 tun0 tun1 tun2 tun3 + sh $this ttyB0 ttyB1 tty00 tty01 lkm +! sh $this mmclock lpa0 lpt0 random ipl + sh $this uk0 uk1 ss0 ss1 + sh $this ttyc0 ttyc1 ttyc2 ttyc3 ttyc4 ttyc5 ttyc6 ttyc7 + sh $this local xfs0 altq +*************** +*** 495,500 **** +--- 496,513 ---- + mknod pf c 35 0 + chown root.wheel pf + chmod 600 pf ++ ;; ++ ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 37 0 ++ mknod ipnat c 37 1 ++ mknod ipstate c 37 2 ++ mknod ipauth c 37 3 ++ mknod ipsync c 37 4 ++ mknod ipscan c 37 5 ++ mknod iplookup c 37 6 ++ chown root.wheel ipl ipnat ipstate ipauth + ;; + + tun*) +diff -cr src.30/etc/etc.amiga/MAKEDEV src/etc/etc.amiga/MAKEDEV +*** src.30/etc/etc.amiga/MAKEDEV Thu Jun 28 12:58:53 2001 +--- src/etc/etc.amiga/MAKEDEV Fri Dec 28 12:45:25 2001 +*************** +*** 86,91 **** +--- 86,92 ---- + # lkm loadable kernel modules interface + # bpf* Berkeley Packet Filter + # tun* network tunnel driver ++ # ipf IP filter + # ss* SCSI scanners + # uk* SCSI Unknown device + # *random inkernal random data source +*************** +*** 168,174 **** + sh $this vnd0 vnd1 vnd2 vnd3 vnd4 vnd5 vnd6 cd0 cd1 fd0 fd1 fd2 fd3 + sh $this bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 + sh $this view00 view01 view02 view03 view04 view05 pty0 pty1 +! sh $this lpa0 lpa1 lpt0 lpt1 lpt2 + sh $this ccd0 ccd1 ccd2 ccd3 wd0 wd1 ch0 uk0 uk1 + sh $this pf tun0 tun1 par0 lkm ss0 random audio0 xfs0 altq local + ;; +--- 169,175 ---- + sh $this vnd0 vnd1 vnd2 vnd3 vnd4 vnd5 vnd6 cd0 cd1 fd0 fd1 fd2 fd3 + sh $this bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 + sh $this view00 view01 view02 view03 view04 view05 pty0 pty1 +! sh $this lpa0 lpa1 lpt0 lpt1 lpt2 ipl + sh $this ccd0 ccd1 ccd2 ccd3 wd0 wd1 ch0 uk0 uk1 + sh $this pf tun0 tun1 par0 lkm ss0 random audio0 xfs0 altq local + ;; +*************** +*** 182,188 **** + + std) + rm -f console drum kmem mem reload null zero tty +! rm -f klog stdin stdout stderr ksyms + mknod console c 0 0 + mknod drum c 3 0 ; chmod 640 drum ; chown root.kmem drum + mknod kmem c 2 1 ; chmod 640 kmem ; chown root.kmem kmem +--- 183,189 ---- + + std) + rm -f console drum kmem mem reload null zero tty +! rm -f klog stdin stdout stderr ipf ksyms + mknod console c 0 0 + mknod drum c 3 0 ; chmod 640 drum ; chown root.kmem drum + mknod kmem c 2 1 ; chmod 640 kmem ; chown root.kmem kmem +*************** +*** 195,200 **** +--- 196,202 ---- + mknod stdin c 21 0 ; chmod 666 stdin + mknod stdout c 21 1 ; chmod 666 stdout + mknod stderr c 21 2 ; chmod 666 stderr ++ mknod ipf c 35 0 ; chmod 444 ipf + mknod ksyms c 42 0 ; chmod 640 ksyms ; chown root.kmem ksyms + ;; + +*************** +*** 602,607 **** +--- 604,621 ---- + rm -f $name$unit + mknod $name$unit c 33 `expr $unit + $flags` + chown root.wheel $name$unit ++ ;; ++ ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 38 0 ++ mknod ipnat c 38 1 ++ mknod ipstate c 38 2 ++ mknod ipauth c 38 3 ++ mknod ipsync c 38 4 ++ mknod ipscan c 38 5 ++ mknod iplookup c 38 6 ++ chown root.wheel ipl ipnat ipstate ipauth + ;; + + tun*) +diff -cr src.30/etc/etc.hp300/MAKEDEV src/etc/etc.hp300/MAKEDEV +*** src.30/etc/etc.hp300/MAKEDEV Thu Jun 28 12:58:53 2001 +--- src/etc/etc.hp300/MAKEDEV Fri Dec 28 12:47:17 2001 +*************** +*** 103,109 **** + sh MAKEDEV sd0 sd1 sd2 rd0 rd1 pty0 vnd0 vnd1 vnd2 vnd3 + sh MAKEDEV hil grf0 apci0 ppi0 ite0 dca0 dcm0 dcm1 dcm2 dcm3 + sh MAKEDEV bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 +! sh MAKEDEV pf tun0 tun1 tun2 tun3 lkm random xfs0 altq + sh MAKEDEV local + ;; + +--- 103,109 ---- + sh MAKEDEV sd0 sd1 sd2 rd0 rd1 pty0 vnd0 vnd1 vnd2 vnd3 + sh MAKEDEV hil grf0 apci0 ppi0 ite0 dca0 dcm0 dcm1 dcm2 dcm3 + sh MAKEDEV bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 +! sh MAKEDEV ipl pf tun0 tun1 tun2 tun3 lkm random xfs0 altq + sh MAKEDEV local + ;; + +*************** +*** 195,200 **** +--- 195,212 ---- + mknod pf c 33 0 + chown root.wheel pf + chmod 600 pf ++ ;; ++ ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 37 0 ++ mknod ipnat c 37 1 ++ mknod ipstate c 37 2 ++ mknod ipauth c 37 3 ++ mknod ipsync c 37 4 ++ mknod ipscan c 37 5 ++ mknod iplookup c 37 6 ++ chown root.wheel ipl ipnat ipstate ipauth + ;; + + tun*) +diff -cr src.30/etc/etc.hppa/MAKEDEV src/etc/etc.hppa/MAKEDEV +*** src.30/etc/etc.hppa/MAKEDEV Fri Sep 7 05:40:21 2001 +--- src/etc/etc.hppa/MAKEDEV Fri Dec 28 12:49:46 2001 +*************** +*** 106,112 **** + sh MAKEDEV sd0 sd1 sd2 rd0 rd1 pty0 vnd0 vnd1 vnd2 vnd3 + sh MAKEDEV tty00 tty01 tty02 tty03 + sh MAKEDEV bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 +! sh MAKEDEV pf tun0 tun1 tun2 tun3 lkm random xfs0 altq + sh MAKEDEV local + ;; + +--- 106,112 ---- + sh MAKEDEV sd0 sd1 sd2 rd0 rd1 pty0 vnd0 vnd1 vnd2 vnd3 + sh MAKEDEV tty00 tty01 tty02 tty03 + sh MAKEDEV bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 +! sh MAKEDEV ipl pf tun0 tun1 tun2 tun3 lkm random xfs0 altq + sh MAKEDEV local + ;; + +*************** +*** 187,192 **** +--- 187,204 ---- + mknod pf c 21 0 + chown root.wheel pf + chmod 600 pf ++ ;; ++ ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 34 0 ++ mknod ipnat c 34 1 ++ mknod ipstate c 34 2 ++ mknod ipauth c 34 3 ++ mknod ipsync c 34 4 ++ mknod ipscan c 34 5 ++ mknod iplookup c 34 6 ++ chown root.wheel ipl ipnat ipstate ipauth + ;; + + tun*) +diff -cr src.30/etc/etc.i386/MAKEDEV src/etc/etc.i386/MAKEDEV +*** src.30/etc/etc.i386/MAKEDEV Fri Oct 5 08:38:13 2001 +--- src/etc/etc.i386/MAKEDEV Fri Dec 28 12:50:50 2001 +*************** +*** 193,199 **** + sh $this ttyC0 ttyC1 ttyC2 ttyC3 ttyC4 ttyC5 ttyC6 ttyC7 ttyC8 ttyC9 + sh $this ttyCa ttyCb + sh $this wscons +! sh $this pf tun0 tun1 tun2 + sh $this bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 + sh $this speaker lkm audio0 radio0 joy0 joy1 apm local + sh $this random ses0 uk0 uk1 ss0 ss1 pctr bktr0 tuner0 wdt0 +--- 193,199 ---- + sh $this ttyC0 ttyC1 ttyC2 ttyC3 ttyC4 ttyC5 ttyC6 ttyC7 ttyC8 ttyC9 + sh $this ttyCa ttyCb + sh $this wscons +! sh $this pf ipl tun0 tun1 tun2 + sh $this bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 + sh $this speaker lkm audio0 radio0 joy0 joy1 apm local + sh $this random ses0 uk0 uk1 ss0 ss1 pctr bktr0 tuner0 wdt0 +*************** +*** 587,592 **** +--- 587,604 ---- + mknod pf c 73 0 + chown root.wheel pf + chmod 600 pf ++ ;; ++ ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 77 0 ++ mknod ipnat c 77 1 ++ mknod ipstate c 77 2 ++ mknod ipauth c 77 3 ++ mknod ipauth c 77 3 ++ mknod ipsync c 77 4 ++ mknod ipscan c 77 5 ++ mknod iplookup c 77 6 ++ chown root.wheel ipl ipnat ipstate ipauth + ;; + + speaker) # (XXX - installed) +diff -cr src.30/etc/etc.mac68k/MAKEDEV src/etc/etc.mac68k/MAKEDEV +*** src.30/etc/etc.mac68k/MAKEDEV Thu Jun 28 12:58:54 2001 +--- src/etc/etc.mac68k/MAKEDEV Fri Dec 28 12:52:19 2001 +*************** +*** 140,145 **** +--- 140,146 ---- + sh $this adb asc0 grf0 grf1 grf2 grf3 ttye0 + sh $this tty00 tty01 pty0 + sh $this bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 ++ sh $this ipl + sh $this pf tun0 tun1 tun2 tun3 + sh $this lkm + sh $this random +*************** +*** 427,432 **** +--- 428,445 ---- + mknod pf c 35 0 + chown root.wheel pf + chmod 600 pf ++ ;; ++ ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 38 0 ++ mknod ipnat c 38 1 ++ mknod ipstate c 38 2 ++ mknod ipauth c 38 3 ++ mknod ipsync c 38 4 ++ mknod ipscan c 38 5 ++ mknod iplookup c 38 6 ++ chown root.wheel ipl ipnat ipstate ipauth + ;; + + tun*) +diff -cr src.30/etc/etc.macppc/MAKEDEV src/etc/etc.macppc/MAKEDEV +*** src.30/etc/etc.macppc/MAKEDEV Thu Oct 4 00:50:38 2001 +--- src/etc/etc.macppc/MAKEDEV Fri Dec 28 12:53:20 2001 +*************** +*** 160,166 **** + sh $this ttyC0 ttyCcfg + sh $this tty00 tty01 tty02 tty03 pty0 pty1 + sh $this bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 +! sh $this pf tun0 tun1 tun2 tun3 + sh $this audio0 + sh $this random uk0 uk1 ss0 ss1 + sh $this wscons +--- 160,166 ---- + sh $this ttyC0 ttyCcfg + sh $this tty00 tty01 tty02 tty03 pty0 pty1 + sh $this bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 +! sh $this ipl pf tun0 tun1 tun2 tun3 + sh $this audio0 + sh $this random uk0 uk1 ss0 ss1 + sh $this wscons +*************** +*** 551,556 **** +--- 551,568 ---- + mknod pf c 39 0 + chown root.wheel pf + chmod 600 pf ++ ;; ++ ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 45 0 ++ mknod ipnat c 45 1 ++ mknod ipstate c 45 2 ++ mknod ipauth c 45 3 ++ mknod ipsync c 45 4 ++ mknod ipscan c 45 5 ++ mknod iplookup c 45 6 ++ chown root.wheel ipl ipnat ipstate ipauth + ;; + + tun*) +diff -cr src.30/etc/etc.mvme68k/MAKEDEV src/etc/etc.mvme68k/MAKEDEV +*** src.30/etc/etc.mvme68k/MAKEDEV Thu Jun 28 12:58:55 2001 +--- src/etc/etc.mvme68k/MAKEDEV Fri Dec 28 12:55:33 2001 +*************** +*** 91,97 **** + sh MAKEDEV tty00 tty01 tty02 tty03 + sh MAKEDEV ttyw0 + sh MAKEDEV sd0 sd1 sd2 sd3 sd4 sd5 sd6 sd7 sd8 sd9 +! sh MAKEDEV vnd0 vnd1 pty0 cd0 + sh MAKEDEV bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 + #sh MAKEDEV ccd0 ccd1 ccd2 ccd3 + sh MAKEDEV pf tun0 tun1 lkm local +--- 91,97 ---- + sh MAKEDEV tty00 tty01 tty02 tty03 + sh MAKEDEV ttyw0 + sh MAKEDEV sd0 sd1 sd2 sd3 sd4 sd5 sd6 sd7 sd8 sd9 +! sh MAKEDEV vnd0 vnd1 pty0 cd0 ipl + sh MAKEDEV bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 + #sh MAKEDEV ccd0 ccd1 ccd2 ccd3 + sh MAKEDEV pf tun0 tun1 lkm local +*************** +*** 431,436 **** +--- 431,448 ---- + chown root.kmem lkm + chmod 640 lkm + ;; ++ ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 44 0 ++ mknod ipnat c 44 1 ++ mknod ipstate c 44 2 ++ mknod ipauth c 44 3 ++ mknod ipsync c 44 4 ++ mknod ipscan c 44 5 ++ mknod iplookup c 44 6 ++ chown root.wheel ipl ipnat ipstate ipauth ++ ;; + + sram*|nvram*|flash*|vmel*|vmes*) + rm -f $i +diff -cr src.30/etc/etc.mvme88k/MAKEDEV src/etc/etc.mvme88k/MAKEDEV +*** src.30/etc/etc.mvme88k/MAKEDEV Thu Jun 28 12:58:55 2001 +--- src/etc/etc.mvme88k/MAKEDEV Fri Dec 28 12:29:24 2001 +*************** +*** 78,84 **** + sh $this tty00 tty01 tty02 tty03 + sh $this ttyw0 + sh $this sd0 sd1 sd2 sd3 sd4 sd5 sd6 sd7 sd8 sd9 +! sh $this vnd0 vnd1 pty0 cd0 + sh $this bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 + #sh $this ccd0 ccd1 ccd2 ccd3 + sh $this pf tun0 tun1 lkm local +--- 78,84 ---- + sh $this tty00 tty01 tty02 tty03 + sh $this ttyw0 + sh $this sd0 sd1 sd2 sd3 sd4 sd5 sd6 sd7 sd8 sd9 +! sh $this vnd0 vnd1 pty0 cd0 ipl + sh $this bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 + #sh $this ccd0 ccd1 ccd2 ccd3 + sh $this pf tun0 tun1 lkm local +*************** +*** 293,298 **** +--- 293,310 ---- + mknod pf c 39 0 + chown root.wheel pf + chmod 600 pf ++ ;; ++ ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 41 0 ++ mknod ipnat c 41 1 ++ mknod ipstate c 41 2 ++ mknod ipauth c 41 3 ++ mknod ipsync c 41 4 ++ mknod ipscan c 41 5 ++ mknod iplookup c 41 6 ++ chown root.wheel ipl ipnat ipstate ipauth + ;; + + bpf*|tun*) +diff -cr src.30/etc/etc.mvmeppc/MAKEDEV src/etc/etc.mvmeppc/MAKEDEV +*** src.30/etc/etc.mvmeppc/MAKEDEV Mon Jul 2 12:37:13 2001 +--- src/etc/etc.mvmeppc/MAKEDEV Fri Dec 28 12:57:54 2001 +*************** +*** 158,164 **** + sh $this ttyC0 ttyCcfg + sh $this tty00 tty01 tty02 tty03 pty0 pty1 + sh $this bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 +! sh $this pf tun0 tun1 tun2 tun3 + sh $this audio0 + sh $this random uk0 uk1 ss0 ss1 + sh $this wscons +--- 158,164 ---- + sh $this ttyC0 ttyCcfg + sh $this tty00 tty01 tty02 tty03 pty0 pty1 + sh $this bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 +! sh $this ipl pf tun0 tun1 tun2 tun3 + sh $this audio0 + sh $this random uk0 uk1 ss0 ss1 + sh $this wscons +*************** +*** 532,537 **** +--- 532,549 ---- + mknod pf c 39 0 + chown root.wheel pf + chmod 600 pf ++ ;; ++ ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 44 0 ++ mknod ipnat c 44 1 ++ mknod ipstate c 44 2 ++ mknod ipauth c 44 3 ++ mknod ipsync c 44 4 ++ mknod ipscan c 44 5 ++ mknod iplookup c 44 6 ++ chown root.wheel ipl ipnat ipstate ipauth + ;; + + tun*) +diff -cr src.30/etc/etc.sparc/MAKEDEV src/etc/etc.sparc/MAKEDEV +*** src.30/etc/etc.sparc/MAKEDEV Fri Sep 7 05:45:34 2001 +--- src/etc/etc.sparc/MAKEDEV Fri Dec 28 12:30:46 2001 +*************** +*** 86,91 **** +--- 86,92 ---- + # spif* spif card (makes 8 tty and 1 bpp) + # bpp* bpp + # xfs* XFS filesystem devices ++ # ipl IP filter log + # altq ALTQ control interface + + PATH=/sbin:/bin:/usr/bin:/usr/sbin +*************** +*** 206,211 **** +--- 207,213 ---- + sh $this ccd0 ccd1 ccd2 ccd3 + sh $this raid0 raid1 raid2 raid3 + sh $this bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 ++ sh $this ipl + sh $this bwtwo0 cgtwo0 cgthree0 cgfour0 cgsix0 + sh $this cgeight0 cgfourteen0 tcx0 + sh $this lkm random local +*************** +*** 341,346 **** +--- 343,360 ---- + mknod pf c 59 0 + chown root.wheel pf + chmod 600 pf ++ ;; ++ ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 60 0 ++ mknod ipnat c 60 1 ++ mknod ipstate c 60 2 ++ mknod ipauth c 60 3 ++ mknod ipsync c 60 4 ++ mknod ipscan c 60 5 ++ mknod iplookup c 60 6 ++ chown root.wheel ipl ipnat ipstate ipauth + ;; + + tun*) +diff -cr src.30/etc/etc.sparc64/MAKEDEV src/etc/etc.sparc64/MAKEDEV +*** src.30/etc/etc.sparc64/MAKEDEV Sat Sep 22 03:58:56 2001 +--- src/etc/etc.sparc64/MAKEDEV Fri Dec 28 12:33:35 2001 +*************** +*** 188,194 **** + R vnd0 vnd1 ccd0 ccd1 ccd2 ccd3 + R raid0 raid1 raid2 raid3 + R bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 +! R pf altq tun0 tun1 tun2 random ses0 uk0 uk1 ss0 ss1 + R fd0 fd0B fd0C fd0D fd0E fd0F fd0G fd0H + R fd1 fd1B fd1C fd1D fd1E fd1F fd1G fd1H + R xfs0 tcx0 lkm audio0 local +--- 188,194 ---- + R vnd0 vnd1 ccd0 ccd1 ccd2 ccd3 + R raid0 raid1 raid2 raid3 + R bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 +! R ipl pf altq tun0 tun1 tun2 random ses0 uk0 uk1 ss0 ss1 + R fd0 fd0B fd0C fd0D fd0E fd0F fd0G fd0H + R fd1 fd1B fd1C fd1D fd1E fd1F fd1G fd1H + R xfs0 tcx0 lkm audio0 local +*************** +*** 243,248 **** +--- 243,256 ---- + U=$(($U+1)) + done;; + pf*)M pf c 73 0 600;; ++ ipl*)M ipl c 75 0 600 root.wheel ++ M ipnat c 75 1 root.wheel ++ M ipstate c 75 2 root.wheel ++ M ipauth c 75 3 root.wheel ++ M ipsync c 75 4 root.wheel ++ M ipscan c 75 5 root.wheel ++ M iplookup c 75 6 root.wheel ++ ;; + cgsix*)M cgsix$U c 67 $U 666;; + audio*)M sound$U c 69 $U + M mixer$U c 69 $(($U+16)) +diff -cr src.30/etc/etc.sun3/MAKEDEV src/etc/etc.sun3/MAKEDEV +*** src.30/etc/etc.sun3/MAKEDEV Fri Sep 7 05:45:34 2001 +--- src/etc/etc.sun3/MAKEDEV Fri Dec 28 13:01:23 2001 +*************** +*** 70,75 **** +--- 70,76 ---- + # tun* network tunnel driver + # *random inkernal random data source + # xfs* XFS filesystem devices ++ # ipl IP filter log + # altq ALTQ control interface + + PATH=/sbin:/bin:/usr/bin:/usr/sbin +*************** +*** 187,192 **** +--- 188,194 ---- + sh $this pty0 vnd0 vnd1 vnd2 vnd3 pf tun0 tun1 tun2 tun3 + sh $this ccd0 ccd1 ccd2 ccd3 + sh $this bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 ++ sh $this ipl + sh $this bwtwo0 cgtwo0 cgfour0 + sh $this random local + sh $this xfs0 altq +*************** +*** 277,282 **** +--- 279,296 ---- + mknod pf c 75 0 + chown root.wheel pf + chmod 600 pf ++ ;; ++ ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 86 0 ++ mknod ipnat c 86 1 ++ mknod ipstate c 86 2 ++ mknod ipauth c 86 3 ++ mknod ipsync c 86 4 ++ mknod ipscan c 86 5 ++ mknod iplookup c 86 6 ++ chown root.wheel ipl ipnat ipstate ipauth + ;; + + tun*) +diff -cr src.30/etc/etc.vax/MAKEDEV src/etc/etc.vax/MAKEDEV +*** src.30/etc/etc.vax/MAKEDEV Fri Jul 13 10:06:30 2001 +--- src/etc/etc.vax/MAKEDEV Fri Dec 28 13:02:17 2001 +*************** +*** 93,99 **** + std) + rm -f console drum floppy crl csa1 csa2 tu0 tu1 + rm -f kUmem kmem mem null zero tty klog ttyg[0-3] +! rm -f stdin stdout stderr ksyms + mknod console c 0 0 + mknod ttyg0 c 25 0 + mknod ttyg1 c 25 1 +--- 93,99 ---- + std) + rm -f console drum floppy crl csa1 csa2 tu0 tu1 + rm -f kUmem kmem mem null zero tty klog ttyg[0-3] +! rm -f stdin stdout stderr ksyms ipl ipnat ipstate ipauth + mknod console c 0 0 + mknod ttyg0 c 25 0 + mknod ttyg1 c 25 1 +*************** +*** 117,122 **** +--- 117,129 ---- + mknod stdout c 53 1 ; chmod 666 stdout + mknod stderr c 53 2 ; chmod 666 stderr + mknod ksyms c 50 0 ; chmod 640 ksyms ; chown root.kmem ksyms ++ mknod ipl c 47 0 ; chmod 600 ipl ++ mknod ipnat c 47 1 ; chmod 600 ipnat ++ mknod ipstate c 47 2 ; chmod 600 ipstate ++ mknod ipauth c 47 3 ; chmod 600 ipauth ++ mknod ipsync c 47 4 ; chmod 600 ipsync ++ mknod ipscan c 47 5 ; chmod 600 ipscan ++ mknod iplookup c 47 6 ; chmod 600 iplookup + ;; + + fd) diff --git a/OpenBSD-3/3.0-rc-diffs b/OpenBSD-3/3.0-rc-diffs new file mode 100644 index 0000000000000..53fa9482785d9 --- /dev/null +++ b/OpenBSD-3/3.0-rc-diffs @@ -0,0 +1,83 @@ +diff -cr src.30/etc/netstart src/etc/netstart +*** src.30/etc/netstart Tue Jul 31 18:27:35 2001 +--- src/etc/netstart Wed Jan 2 10:02:01 2002 +*************** +*** 27,32 **** +--- 27,42 ---- + domainname `cat /etc/defaultdomain` + fi + ++ # Configure the IP filter before configuring network interfaces ++ if [ X"${ipfilter}" = X"YES" -a -f "${ipfilter_rules}" ]; then ++ echo 'configuring IP filter' ++ ipf -Fa -f ${ipfilter_rules} ++ ipfresync="ipf -y" ++ else ++ ipfilter=NO ++ ipfresync=NO ++ fi ++ + # set the address for the loopback interface + # it will also initialize IPv6 address for lo0 (::1 and others). + ifconfig lo0 inet localhost +*************** +*** 273,275 **** +--- 283,298 ---- + route -n add -net 224.0.0.0/4 -interface 127.0.0.1 -reject > /dev/null + ;; + esac ++ ++ # Configure NAT after configuring network interfaces ++ if [ "${ipnat}" = "YES" -a "${ipfilter}" = "YES" -a -f "${ipnat_rules}" ]; then ++ echo 'configuring NAT' ++ ipnat -CF -f ${ipnat_rules} ++ else ++ ipnat=NO ++ fi ++ ++ # Interfaces have come up so we should do an ipf -y if we're using IP filter. ++ if [ "${ipfresync}" != "NO" ]; then ++ ${ipfresync} ++ fi +diff -cr src.30/etc/rc src/etc/rc +*** src.30/etc/rc Wed Oct 10 04:44:17 2001 +--- src/etc/rc Wed Jan 2 09:55:31 2002 +*************** +*** 213,218 **** +--- 213,222 ---- + echo 'starting named'; named $named_flags + fi + ++ if [ X"${ipfilter}" = X"YES" -a X"${ipmon_flags}" != X"NO" ]; then ++ echo 'starting ipmon'; ipmon ${ipmon_flags} ++ fi ++ + # $photurisd_flags is imported from /etc/rc.conf; + # If $photurisd_flags == NO or /etc/photuris/photuris.conf doesn't exist, then + # photurisd isn't run. +diff -cr src.30/etc/rc.conf src/etc/rc.conf +*** src.30/etc/rc.conf Sat Oct 13 08:40:58 2001 +--- src/etc/rc.conf Wed Jan 2 10:04:35 2002 +*************** +*** 53,58 **** +--- 53,60 ---- + lockd=NO + gated=NO + amd=NO ++ ipfilter=NO # To enable ipfilter, set to YES ++ ipnat=NO # for "YES", ipfilter must also be "YES" + pf=NO # Packet filter / NAT + portmap=YES # almost always needed + inetd=YES # almost always needed +*************** +*** 78,83 **** +--- 80,88 ---- + nfsd_flags="-tun 4" # Crank the 4 for a busy NFS fileserver + amd_dir=/tmp_mnt # AMD's mount directory + amd_master=/etc/amd/master # AMD 'master' map ++ ipfilter_rules=/etc/ipf.rules # Rules for IP packet filtering with IP Filter ++ ipnat_rules=/etc/ipnat.rules # Rules for Network Address Translation ++ ipmon_flags=-Ds # To disable logging, use ipmon_flags=NO + syslogd_flags= # add more flags, ie. "-u -a /chroot/dev/log" + named_user=named # Named should not run as root unless necessary + named_chroot=/var/named # Where to chroot named if not empty diff --git a/OpenBSD-3/3.0-sys-diffs b/OpenBSD-3/3.0-sys-diffs new file mode 100644 index 0000000000000..45d4aa6b30517 --- /dev/null +++ b/OpenBSD-3/3.0-sys-diffs @@ -0,0 +1,986 @@ +diff -cr sys.30/arch/alpha/alpha/conf.c sys/arch/alpha/alpha/conf.c +*** sys.30/arch/alpha/alpha/conf.c Fri Sep 28 13:33:39 2001 +--- sys/arch/alpha/alpha/conf.c Fri Dec 28 12:42:32 2001 +*************** +*** 104,109 **** +--- 104,114 ---- + #include "lpt.h" + cdev_decl(lpt); + cdev_decl(prom); /* XXX XXX XXX */ ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif + cdev_decl(wd); + #include "cy.h" + cdev_decl(cy); +*************** +*** 174,180 **** + cdev_random_init(1,random), /* 34: random data source */ + cdev_pf_init(NPF, pf), /* 35: packet filter */ + cdev_disk_init(NWD,wd), /* 36: ST506/ESDI/IDE disk */ +! cdev_notdef(), /* 37 */ + cdev_tty_init(NCY,cy), /* 38: Cyclom serial port */ + cdev_ksyms_init(NKSYMS,ksyms), /* 39: Kernel symbols device */ + cdev_notdef(), /* 40 */ +--- 179,185 ---- + cdev_random_init(1,random), /* 34: random data source */ + cdev_pf_init(NPF, pf), /* 35: packet filter */ + cdev_disk_init(NWD,wd), /* 36: ST506/ESDI/IDE disk */ +! cdev_gen_ipf(NIPF,ipl), /* 37: IP filter log */ + cdev_tty_init(NCY,cy), /* 38: Cyclom serial port */ + cdev_ksyms_init(NKSYMS,ksyms), /* 39: Kernel symbols device */ + cdev_notdef(), /* 40 */ +diff -cr sys.30/arch/amiga/amiga/conf.c sys/arch/amiga/amiga/conf.c +*** sys.30/arch/amiga/amiga/conf.c Fri Sep 28 12:53:13 2001 +--- sys/arch/amiga/amiga/conf.c Fri Dec 28 12:45:04 2001 +*************** +*** 160,166 **** + cdev_random_init(1,random), /* 35: random data source */ + cdev_uk_init(NUK,uk), /* 36: unknown SCSI */ + cdev_disk_init(NWD,wd), /* 37: ST506/ESDI/IDE disk */ +! cdev_notdef(), /* 38 */ + cdev_audio_init(NAUDIO,audio), /* 39: cc audio interface */ + cdev_ch_init(NCH,ch), /* 40: SCSI autochanger */ + cdev_disk_init(NRD,rd), /* 41: RAM disk */ +--- 160,166 ---- + cdev_random_init(1,random), /* 35: random data source */ + cdev_uk_init(NUK,uk), /* 36: unknown SCSI */ + cdev_disk_init(NWD,wd), /* 37: ST506/ESDI/IDE disk */ +! cdev_gen_ipf(NIPF,ipl), /* 38: IP filter log */ + cdev_audio_init(NAUDIO,audio), /* 39: cc audio interface */ + cdev_ch_init(NCH,ch), /* 40: SCSI autochanger */ + cdev_disk_init(NRD,rd), /* 41: RAM disk */ +diff -cr sys.30/arch/hp300/hp300/conf.c sys/arch/hp300/hp300/conf.c +*** sys.30/arch/hp300/hp300/conf.c Fri Sep 28 12:53:13 2001 +--- sys/arch/hp300/hp300/conf.c Fri Dec 28 12:48:02 2001 +*************** +*** 150,155 **** +--- 150,161 ---- + cdev_decl(xfs_dev); + #endif + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 174,181 **** + cdev_tty_init(NDCM,dcm), /* 15: 4-port serial */ + cdev_tape_init(NMT,mt), /* 16: magnetic reel tape */ + cdev_disk_init(NCCD,ccd), /* 17: concatenated disk */ +- cdev_notdef(), /* 18 */ + cdev_disk_init(NVND,vnd), /* 19: vnode disk driver */ + cdev_tape_init(NST,st), /* 20: SCSI tape */ + cdev_fd_init(1,filedesc), /* 21: file descriptor pseudo-device */ + cdev_bpftun_init(NBPFILTER,bpf),/* 22: Berkeley packet filter */ +--- 180,187 ---- + cdev_tty_init(NDCM,dcm), /* 15: 4-port serial */ + cdev_tape_init(NMT,mt), /* 16: magnetic reel tape */ + cdev_disk_init(NCCD,ccd), /* 17: concatenated disk */ + cdev_disk_init(NVND,vnd), /* 19: vnode disk driver */ ++ cdev_notdef(), /* 18 */ + cdev_tape_init(NST,st), /* 20: SCSI tape */ + cdev_fd_init(1,filedesc), /* 21: file descriptor pseudo-device */ + cdev_bpftun_init(NBPFILTER,bpf),/* 22: Berkeley packet filter */ +*************** +*** 193,199 **** + cdev_disk_init(NRD,rd), /* 34: RAM disk */ + cdev_tty_init(NAPCI,apci), /* 35: Apollo APCI UARTs */ + cdev_ksyms_init(NKSYMS,ksyms), /* 36: Kernel symbols device */ +! cdev_notdef(), /* 37 */ + cdev_notdef(), /* 38 */ + cdev_notdef(), /* 39 */ + cdev_notdef(), /* 40 */ +--- 199,205 ---- + cdev_disk_init(NRD,rd), /* 34: RAM disk */ + cdev_tty_init(NAPCI,apci), /* 35: Apollo APCI UARTs */ + cdev_ksyms_init(NKSYMS,ksyms), /* 36: Kernel symbols device */ +! cdev_pf_init(NIPF,ipl), /* 37: packet filter */ + cdev_notdef(), /* 38 */ + cdev_notdef(), /* 39 */ + cdev_notdef(), /* 40 */ +diff -cr sys.30/arch/hppa/hppa/conf.c sys/arch/hppa/hppa/conf.c +*** sys.30/arch/hppa/hppa/conf.c Fri Sep 28 12:53:13 2001 +--- sys/arch/hppa/hppa/conf.c Fri Dec 28 12:48:49 2001 +*************** +*** 113,118 **** +--- 113,124 ---- + #include "com.h" + cdev_decl(com); + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 158,163 **** +--- 164,170 ---- + cdev_notdef(), /* 32 */ + #endif + cdev_altq_init(NALTQ,altq), /* 33: ALTQ control interface */ ++ cdev_gen_ipf(NIPF,ipl), /* 34: ip filtering */ + cdev_lkm_dummy(), + cdev_lkm_dummy(), + cdev_lkm_dummy(), +diff -cr sys.30/arch/i386/i386/conf.c sys/arch/i386/i386/conf.c +*** sys.30/arch/i386/i386/conf.c Fri Oct 5 07:46:03 2001 +--- sys/arch/i386/i386/conf.c Fri Dec 28 12:50:34 2001 +*************** +*** 221,226 **** +--- 221,232 ---- + #include "radio.h" + cdev_decl(radio); + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + /* XXX -- this needs to be supported by config(8)! */ + #if (NCOM > 0) && (NPCCOM > 0) + #error com and pccom are mutually exclusive. Sorry. +*************** +*** 348,353 **** +--- 354,360 ---- + cdev_altq_init(NALTQ,altq), /* 74: ALTQ control interface */ + cdev_iop_init(NIOP,iop), /* 75: I2O IOP control interface */ + cdev_radio_init(NRADIO, radio), /* 76: generic radio I/O */ ++ cdev_gen_ipf(NIPF,ipl), /* 77: ip filtering */ + }; + int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]); + +diff -cr sys.30/arch/mac68k/mac68k/conf.c sys/arch/mac68k/mac68k/conf.c +*** sys.30/arch/mac68k/mac68k/conf.c Fri Sep 28 12:53:13 2001 +--- sys/arch/mac68k/mac68k/conf.c Fri Dec 28 12:51:45 2001 +*************** +*** 117,122 **** +--- 117,128 ---- + cdev_decl(xfs_dev); + #endif + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 161,167 **** + cdev_pf_init(NPF,pf), /* 35: packet filter */ + cdev_audio_init(NASC,asc), /* 36: ASC audio device */ + cdev_ksyms_init(NKSYMS,ksyms), /* 37: Kernel symbols device */ +! cdev_notdef(), /* 38 */ + cdev_notdef(), /* 39 */ + cdev_notdef(), /* 40 */ + cdev_notdef(), /* 41 */ +--- 167,173 ---- + cdev_pf_init(NPF,pf), /* 35: packet filter */ + cdev_audio_init(NASC,asc), /* 36: ASC audio device */ + cdev_ksyms_init(NKSYMS,ksyms), /* 37: Kernel symbols device */ +! cdev_gen_ipf(NIPF,ipl), /* 38: IP filter log */ + cdev_notdef(), /* 39 */ + cdev_notdef(), /* 40 */ + cdev_notdef(), /* 41 */ +diff -cr sys.30/arch/macppc/macppc/conf.c sys/arch/macppc/macppc/conf.c +*** sys.30/arch/macppc/macppc/conf.c Thu Oct 4 00:45:37 2001 +--- sys/arch/macppc/macppc/conf.c Fri Dec 28 12:53:03 2001 +*************** +*** 105,110 **** +--- 105,116 ---- + + #include "tun.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #ifdef XFS + #include <xfs/nxfs.h> + cdev_decl(xfs_dev); +*************** +*** 195,201 **** + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ + cdev_audio_init(NAUDIO,audio), /* 44: generic audio I/O */ +! cdev_notdef(), /* 45 */ + cdev_notdef(), /* 46 */ + cdev_notdef(), /* 47 */ + cdev_notdef(), /* 48 */ +--- 201,207 ---- + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ + cdev_audio_init(NAUDIO,audio), /* 44: generic audio I/O */ +! cdev_gen_ipf(NIPF,ipl), /* 45: IP filter */ + cdev_notdef(), /* 46 */ + cdev_notdef(), /* 47 */ + cdev_notdef(), /* 48 */ +diff -cr sys.30/arch/mvme68k/mvme68k/conf.c sys/arch/mvme68k/mvme68k/conf.c +*** sys.30/arch/mvme68k/mvme68k/conf.c Fri Sep 28 12:53:13 2001 +--- sys/arch/mvme68k/mvme68k/conf.c Fri Dec 28 12:55:36 2001 +*************** +*** 176,181 **** +--- 176,187 ---- + + #include "tun.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 226,232 **** + cdev_uk_init(NUK,uk), /* 41: unknown SCSI */ + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ +! cdev_lkm_dummy(), /* 44 */ + cdev_lkm_dummy(), /* 45 */ + cdev_lkm_dummy(), /* 46 */ + cdev_lkm_dummy(), /* 47 */ +--- 232,238 ---- + cdev_uk_init(NUK,uk), /* 41: unknown SCSI */ + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ +! cdev_gen_ipf(NIPF,ipl), /* 44: IP filter */ + cdev_lkm_dummy(), /* 45 */ + cdev_lkm_dummy(), /* 46 */ + cdev_lkm_dummy(), /* 47 */ +diff -cr sys.30/arch/mvme88k/mvme88k/conf.c sys/arch/mvme88k/mvme88k/conf.c +*** sys.30/arch/mvme88k/mvme88k/conf.c Fri Sep 28 12:53:13 2001 +--- sys/arch/mvme88k/mvme88k/conf.c Fri Dec 28 12:56:20 2001 +*************** +*** 113,118 **** +--- 113,124 ---- + cdev_decl(lptwo); + #endif /* notyet */ + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 199,205 **** + cdev_lkm_dummy(), /* 38 */ + cdev_pf_init(NPF,pf), /* 39: packet filter */ + cdev_random_init(1,random), /* 40: random data source */ +! cdev_notdef(), /* 41 */ + cdev_notdef(), /* 42 */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ + cdev_notdef(), /* 44 */ +--- 205,211 ---- + cdev_lkm_dummy(), /* 38 */ + cdev_pf_init(NPF,pf), /* 39: packet filter */ + cdev_random_init(1,random), /* 40: random data source */ +! cdev_gen_ipf(NIPF,ipl), /* 41: IP filter */ + cdev_notdef(), /* 42 */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ + cdev_notdef(), /* 44 */ +diff -cr sys.30/arch/mvmeppc/mvmeppc/conf.c sys/arch/mvmeppc/mvmeppc/conf.c +*** sys.30/arch/mvmeppc/mvmeppc/conf.c Fri Sep 28 12:53:13 2001 +--- sys/arch/mvmeppc/mvmeppc/conf.c Fri Dec 28 12:57:20 2001 +*************** +*** 147,152 **** +--- 147,158 ---- + #include "ksyms.h" + cdev_decl(ksyms); + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 200,206 **** + cdev_uk_init(NUK,uk), /* 41: unknown SCSI */ + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ +! cdev_notdef(), /* 44 */ + cdev_notdef(), /* 45 */ + cdev_notdef(), /* 46 */ + cdev_notdef(), /* 47 */ +--- 206,212 ---- + cdev_uk_init(NUK,uk), /* 41: unknown SCSI */ + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ +! cdev_gen_ipf(NIPF,ipl), /* 44: IP filter */ + cdev_notdef(), /* 45 */ + cdev_notdef(), /* 46 */ + cdev_notdef(), /* 47 */ +diff -cr sys.30/arch/sparc/sparc/conf.c sys/arch/sparc/sparc/conf.c +*** sys.30/arch/sparc/sparc/conf.c Fri Sep 28 12:53:13 2001 +--- sys/arch/sparc/sparc/conf.c Fri Dec 28 12:59:25 2001 +*************** +*** 128,133 **** +--- 128,139 ---- + }; + int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]); + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 202,208 **** + cdev_notdef(), /* 57 */ + cdev_disk_init(NCD,cd), /* 58: SCSI CD-ROM */ + cdev_pf_init(NPF,pf), /* 59: packet filter */ +! cdev_notdef(), /* 60 */ + cdev_notdef(), /* 61 */ + cdev_notdef(), /* 62 */ + cdev_notdef(), /* 63 */ +--- 208,214 ---- + cdev_notdef(), /* 57 */ + cdev_disk_init(NCD,cd), /* 58: SCSI CD-ROM */ + cdev_pf_init(NPF,pf), /* 59: packet filter */ +! cdev_gen_ipf(NIPF,ipl), /* 60: ip filtering log */ + cdev_notdef(), /* 61 */ + cdev_notdef(), /* 62 */ + cdev_notdef(), /* 63 */ +diff -cr sys.30/arch/sparc64/sparc64/conf.c sys/arch/sparc64/sparc64/conf.c +*** sys.30/arch/sparc64/sparc64/conf.c Fri Sep 28 12:53:14 2001 +--- sys/arch/sparc64/sparc64/conf.c Fri Dec 28 12:59:59 2001 +*************** +*** 116,121 **** +--- 116,127 ---- + #include "ses.h" + cdev_decl(ses); + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 239,245 **** + cdev_notdef(), /* 72 */ + cdev_pf_init(NPF,pf), /* 73: packet filter */ + cdev_altq_init(NALTQ,altq), /* 74: ALTQ control interface */ +! cdev_notdef(), /* 75 */ + cdev_ksyms_init(NKSYMS,ksyms), /* 76 *: Kernel symbols device */ + cdev_notdef(), /* 77 */ + cdev_notdef(), /* 78 */ +--- 245,251 ---- + cdev_notdef(), /* 72 */ + cdev_pf_init(NPF,pf), /* 73: packet filter */ + cdev_altq_init(NALTQ,altq), /* 74: ALTQ control interface */ +! cdev_gen_ipf(NIPF,ipl), /* 75: IP filter */ + cdev_ksyms_init(NKSYMS,ksyms), /* 76 *: Kernel symbols device */ + cdev_notdef(), /* 77 */ + cdev_notdef(), /* 78 */ +diff -cr sys.30/arch/sun3/sun3/conf.c sys/arch/sun3/sun3/conf.c +*** sys.30/arch/sun3/sun3/conf.c Fri Sep 28 12:53:14 2001 +--- sys/arch/sun3/sun3/conf.c Fri Dec 28 13:00:59 2001 +*************** +*** 111,116 **** +--- 111,122 ---- + }; + int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]); + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 207,212 **** +--- 213,219 ---- + cdev_ch_init(NCH,ch), /* 83: SCSI autochanger */ + cdev_ses_init(NSES,ses), /* 84: SCSI SES or SAF-TE device */ + cdev_altq_init(NALTQ,altq), /* 85: ALTQ control interface */ ++ cdev_gen_ipf(NIPF,ipl), /* 86: IP filter */ + }; + int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]); + +diff -cr sys.30/arch/vax/vax/conf.c sys/arch/vax/vax/conf.c +*** sys.30/arch/vax/vax/conf.c Fri Sep 28 12:53:14 2001 +--- sys/arch/vax/vax/conf.c Fri Dec 28 13:01:58 2001 +*************** +*** 432,437 **** +--- 432,443 ---- + #include "wskbd.h" + #include "wsmouse.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 485,491 **** + cdev_notdef(), /* 44 was Datakit */ + cdev_notdef(), /* 45 was Datakit */ + cdev_notdef(), /* 46 was Datakit */ +! cdev_notdef(), /* 47 */ + cdev_notdef(), /* 48 */ + cdev_notdef(), /* 49 */ + cdev_ksyms_init(NKSYMS,ksyms), /* 50: Kernel symbols device */ +--- 491,497 ---- + cdev_notdef(), /* 44 was Datakit */ + cdev_notdef(), /* 45 was Datakit */ + cdev_notdef(), /* 46 was Datakit */ +! cdev_gen_ipf(NIPF,ipl), /* 47: IP filter */ + cdev_notdef(), /* 48 */ + cdev_notdef(), /* 49 */ + cdev_ksyms_init(NKSYMS,ksyms), /* 50: Kernel symbols device */ +diff -cr sys.30/conf/GENERIC sys/conf/GENERIC +*** sys.30/conf/GENERIC Tue Sep 18 03:04:27 2001 +--- sys/conf/GENERIC Fri Dec 28 11:37:49 2001 +*************** +*** 71,76 **** +--- 71,79 ---- + #option EON # OSI tunneling over IP + #option NETATALK # AppleTalk + #option CCITT,LLC,HDLC # X.25 ++ option IPFILTER # IP packet filter for security ++ option IPFILTER_LOG # use /dev/ipl to log IPF ++ #option IPFILTER_LOOKUP # use /dev/iplookup for IP pools + option PPP_BSDCOMP # PPP BSD compression + option PPP_DEFLATE + #option MROUTING # Multicast router +diff -cr sys.30/conf/files sys/conf/files +*** sys.30/conf/files Fri Oct 5 07:43:37 2001 +--- sys/conf/files Fri Dec 28 12:02:08 2001 +*************** +*** 652,657 **** +--- 652,668 ---- + file netinet/tcp_usrreq.c inet + file netinet/udp_usrreq.c inet + file netinet/ip_gre.c inet ++ file netinet/ip_fil.c ipfilter ++ file netinet/fil.c ipfilter ++ file netinet/ip_nat.c ipfilter ++ file netinet/ip_frag.c ipfilter ++ file netinet/ip_state.c ipfilter ++ file netinet/ip_proxy.c ipfilter ++ file netinet/ip_auth.c ipfilter ++ file netinet/ip_log.c ipfilter ++ file netinet/ip_pool.c ipfilter & ipfilter_lookup ++ file netinet/ip_htable.c ipfilter & ipfilter_lookup ++ file netinet/ip_lookup.c ipfilter & ipfilter_lookup + file netinet/ip_ipsp.c (inet | inet6) & (ipsec | tcp_signature) + file netinet/ip_spd.c (inet | inet6) & (ipsec | tcp_signature) + file netinet/ip_ipip.c inet | inet6 +diff -cr sys.30/net/bridgestp.c sys/net/bridgestp.c +*** sys.30/net/bridgestp.c Wed Jun 27 16:07:37 2001 +--- sys/net/bridgestp.c Fri Dec 28 12:01:56 2001 +*************** +*** 63,68 **** +--- 63,73 ---- + #include <netinet/in_var.h> + #include <netinet/ip.h> + #include <netinet/if_ether.h> ++ ++ #ifdef IPFILTER ++ #include <netinet/ip_compat.h> ++ #include <netinet/ip_fil.h> ++ #endif + #endif + + #if NBPFILTER > 0 +diff -cr sys.30/net/if.c sys/net/if.c +*** sys.30/net/if.c Sat Jun 30 08:46:05 2001 +--- sys/net/if.c Fri Dec 28 12:02:21 2001 +*************** +*** 99,104 **** +--- 99,110 ---- + #include <netinet6/in6_ifattach.h> + #endif + ++ #ifdef IPFILTER ++ #include <netinet/ip_compat.h> ++ #include <netinet/ip_fil.h> ++ #include <netinet/ip_nat.h> ++ #endif ++ + #if NBPFILTER > 0 + #include <net/bpf.h> + #endif +*************** +*** 381,386 **** +--- 387,397 ---- + + /* Remove the interface from the list of all interfaces. */ + TAILQ_REMOVE(&ifnet, ifp, if_list); ++ ++ #ifdef IPFILTER ++ /* XXX More ipf & ipnat cleanup needed. */ ++ frsync(ifp); ++ #endif + + /* Deallocate private resources. */ + for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa; +diff -cr sys.30/net/if_bridge.c sys/net/if_bridge.c +*** sys.30/net/if_bridge.c Wed Aug 22 01:18:20 2001 +--- sys/net/if_bridge.c Sun Dec 30 05:29:37 2001 +*************** +*** 61,67 **** + #include <netinet/ip_ipsp.h> + + #include <net/if_enc.h> +! #endif + + #if NPF > 0 + #include <net/pfvar.h> +--- 61,71 ---- + #include <netinet/ip_ipsp.h> + + #include <net/if_enc.h> +! # if (defined(IPFILTER) || defined(IPFILTER_LKM)) +! #include <netinet/ip_compat.h> +! #include <netinet/ip_fil.h> +! # endif +! #endif /* INET */ + + #if NPF > 0 + #include <net/pfvar.h> +*************** +*** 139,145 **** + int bridge_flushrule __P((struct bridge_iflist *)); + int bridge_brlconf __P((struct bridge_softc *, struct ifbrlconf *)); + u_int8_t bridge_filterrule __P((struct brl_head *, struct ether_header *)); +! #if NPF > 0 + struct mbuf *bridge_filter __P((struct bridge_softc *, int, struct ifnet *, + struct ether_header *, struct mbuf *m)); + #endif +--- 143,149 ---- + int bridge_flushrule __P((struct bridge_iflist *)); + int bridge_brlconf __P((struct bridge_softc *, struct ifbrlconf *)); + u_int8_t bridge_filterrule __P((struct brl_head *, struct ether_header *)); +! #if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + struct mbuf *bridge_filter __P((struct bridge_softc *, int, struct ifnet *, + struct ether_header *, struct mbuf *m)); + #endif +*************** +*** 1043,1049 **** + m_freem(m); + return; + } +! #if NPF > 0 + m = bridge_filter(sc, BRIDGE_IN, src_if, &eh, m); + if (m == NULL) + return; +--- 1047,1053 ---- + m_freem(m); + return; + } +! #if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + m = bridge_filter(sc, BRIDGE_IN, src_if, &eh, m); + if (m == NULL) + return; +*************** +*** 1086,1092 **** + m_freem(m); + return; + } +! #if NPF > 0 + m = bridge_filter(sc, BRIDGE_OUT, dst_if, &eh, m); + if (m == NULL) + return; +--- 1090,1096 ---- + m_freem(m); + return; + } +! #if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + m = bridge_filter(sc, BRIDGE_OUT, dst_if, &eh, m); + if (m == NULL) + return; +*************** +*** 1328,1334 **** + } + } + +! #if NPF > 0 + mc = bridge_filter(sc, BRIDGE_OUT, dst_if, eh, mc); + if (mc == NULL) + continue; +--- 1332,1338 ---- + } + } + +! #if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + mc = bridge_filter(sc, BRIDGE_OUT, dst_if, eh, mc); + if (mc == NULL) + continue; +*************** +*** 1911,1917 **** + return (0); + } + +! #if NPF > 0 + /* + * Filter IP packets by peeking into the ethernet frame. This violates + * the ISO model, but allows us to act as a IP filter at the data link +--- 1915,1921 ---- + return (0); + } + +! #if (NPF > 0) || defined(IPFILTER) || defined(IPFILTER_LKM) + /* + * Filter IP packets by peeking into the ethernet frame. This violates + * the ISO model, but allows us to act as a IP filter at the data link +*************** +*** 1926,1932 **** + struct ether_header *eh; + struct mbuf *m; + { +! #if NPF == 0 + return (m); + #else + struct llc llc; +--- 1930,1936 ---- + struct ether_header *eh; + struct mbuf *m; + { +! #if defined(NPF) && (NPF == 0) && !defined(IPFILTER) && !defined(IPFILTER_LKM) + return (m); + #else + struct llc llc; +*************** +*** 1934,1939 **** +--- 1938,1947 ---- + struct ip *ip; + int hlen; + ++ # if (defined(IPFILTER) || defined(IPFILTER_LKM)) && defined(NPF) && (NPF == 0) ++ if (fr_checkp == NULL) ++ return (m); ++ # endif + if (eh->ether_type != htons(ETHERTYPE_IP)) { + if (eh->ether_type > ETHERMTU || + m->m_pkthdr.len < (LLC_SNAPFRAMELEN + +*************** +*** 2000,2007 **** +--- 2008,2023 ---- + + /* Finally, we get to filter the packet! */ + m->m_pkthdr.rcvif = ifp; ++ #if NPF > 0 + if (pf_test(dir, ifp, &m) != PF_PASS) + goto dropit; ++ #endif ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, dir, &m)) ++ goto dropit; ++ if (m == NULL) /* in case of 'fastroute' */ ++ goto dropit; ++ #endif + + /* Rebuild the IP header */ + if (m->m_len < hlen && ((m = m_pullup(m, hlen)) == NULL)) +*************** +*** 2035,2040 **** + if (m != NULL) + m_freem(m); + return (NULL); +! #endif /* NPF == 0 */ + } + #endif +--- 2051,2056 ---- + if (m != NULL) + m_freem(m); + return (NULL); +! #endif /* (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) */ + } + #endif +diff -cr sys.30/netinet/in_proto.c sys/netinet/in_proto.c +*** sys.30/netinet/in_proto.c Thu Aug 9 01:07:04 2001 +--- sys/netinet/in_proto.c Fri Dec 28 12:05:44 2001 +*************** +*** 163,168 **** +--- 163,173 ---- + #include <netinet/ip_mroute.h> + #endif /* MROUTING */ + ++ #ifdef IPFILTER ++ void iplinit __P((void)); ++ #define ip_init iplinit ++ #endif ++ + #ifdef INET6 + #include <netinet6/ip6_var.h> + #endif /* INET6 */ +diff -cr sys.30/netinet/ip_input.c sys/netinet/ip_input.c +*** sys.30/netinet/ip_input.c Wed Sep 19 01:24:32 2001 +--- sys/netinet/ip_input.c Fri Dec 28 12:05:55 2001 +*************** +*** 149,154 **** +--- 149,159 ---- + struct in_ifaddrhead in_ifaddr; + struct ifqueue ipintrq; + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, ++ struct mbuf **)); ++ #endif ++ + int ipq_locked; + static __inline int ipq_lock_try __P((void)); + static __inline void ipq_unlock __P((void)); +*************** +*** 398,403 **** +--- 403,425 ---- + + ip = mtod(m, struct ip *); + hlen = ip->ip_hl << 2; ++ #endif ++ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * Check if we want to allow this packet to be processed. ++ * Consider it to be bad if not. ++ */ ++ { ++ struct mbuf *m0 = m; ++ if (fr_checkp && (*fr_checkp)(ip, hlen, m->m_pkthdr.rcvif, 0, &m0)) { ++ return; ++ } ++ if (m0 == 0) { /* in case of 'fastroute' */ ++ return; ++ } ++ ip = mtod(m = m0, struct ip *); ++ } + #endif + + #ifdef ALTQ +diff -cr sys.30/netinet/ip_output.c sys/netinet/ip_output.c +*** sys.30/netinet/ip_output.c Mon Aug 27 07:12:06 2001 +--- sys/netinet/ip_output.c Fri Dec 28 12:10:52 2001 +*************** +*** 91,96 **** +--- 91,100 ---- + static void ip_mloopback + __P((struct ifnet *, struct mbuf *, struct sockaddr_in *)); + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif ++ + /* + * IP output. The packet in mbuf chain m contains a skeletal IP + * header (with len, off, ttl, proto, tos, src, dst). +*************** +*** 535,540 **** +--- 539,568 ---- + if (sproto != 0) { + s = splnet(); + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (fr_checkp) { ++ /* ++ * Ok, it's time for a simple round-trip to the IPF/NAT ++ * code with the enc0 interface. ++ */ ++ struct mbuf *m1 = m; ++ void *ifp = (void *)&encif[0].sc_if; ++ ++ if ((*fr_checkp)(ip, hlen, ifp, 1, &m1)) { ++ error = EHOSTUNREACH; ++ splx(s); ++ goto done; ++ } ++ if (m1 == 0) { /* in case of 'fastroute' */ ++ error = 0; ++ splx(s); ++ goto done; ++ } ++ ip = mtod(m = m1, struct ip *); ++ hlen = ip->ip_hl << 2; ++ } ++ #endif /* IPFILTER */ ++ + /* + * Packet filter + */ +*************** +*** 636,641 **** +--- 664,688 ---- + m->m_pkthdr.csum &= ~M_UDPV4_CSUM_OUT; /* Clear */ + } + } ++ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * looks like most checking has been done now...do a filter check ++ */ ++ { ++ struct mbuf *m1 = m; ++ ++ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 1, &m1)) { ++ error = EHOSTUNREACH; ++ goto done; ++ } ++ if (m1 == 0) { /* in case of 'fastroute' */ ++ error = 0; ++ goto done; ++ } ++ ip = mtod(m = m1, struct ip *); ++ } ++ #endif + + /* + * Packet filter +diff -cr sys.30/netinet6/ip6_input.c sys/netinet6/ip6_input.c +*** sys.30/netinet6/ip6_input.c Sat Sep 15 13:54:40 2001 +--- sys/netinet6/ip6_input.c Sat Dec 29 21:57:26 2001 +*************** +*** 134,139 **** +--- 134,142 ---- + #ifdef PULLDOWN_TEST + static struct mbuf *ip6_pullexthdr __P((struct mbuf *, size_t, int)); + #endif ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif + + /* + * IP6 initialization: fill in IP6 protocol switch table. +*************** +*** 286,291 **** +--- 289,314 ---- + in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); + goto bad; + } ++ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * Check if we want to allow this packet to be processed. ++ * Consider it to be bad if not. ++ */ ++ if (fr_checkp != NULL) { ++ struct mbuf *m0 = m; ++ ++ if ((*fr_checkp)((struct ip *)ip6, sizeof(*ip6), ++ m->m_pkthdr.rcvif, 0, &m0)) { ++ return; ++ } ++ m = m0; ++ if (m == 0) { /* in case of 'fastroute' */ ++ return; ++ } ++ ip6 = mtod(m, struct ip6_hdr *); ++ } ++ #endif + + ip6stat.ip6s_nxthist[ip6->ip6_nxt]++; + +diff -cr sys.30/netinet6/ip6_output.c sys/netinet6/ip6_output.c +*** sys.30/netinet6/ip6_output.c Tue Oct 2 02:03:09 2001 +--- sys/netinet6/ip6_output.c Sat Dec 29 21:57:26 2001 +*************** +*** 118,123 **** +--- 118,127 ---- + struct mbuf *ip6e_dest2; + }; + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif ++ + static int ip6_pcbopts __P((struct ip6_pktopts **, struct mbuf *, + struct socket *)); + static int ip6_setmoptions __P((int, struct ip6_moptions **, struct mbuf *)); +*************** +*** 889,894 **** +--- 893,917 ---- + ip6 = mtod(m, struct ip6_hdr *); + #endif + ++ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * looks like most checking has been done now...do a filter check ++ */ ++ if (fr_checkp != NULL) { ++ struct mbuf *m1 = m; ++ if ((*fr_checkp)((struct ip *)ip6, sizeof(*ip6), ifp, 1, &m1)) { ++ error = EHOSTUNREACH; ++ goto done; ++ } ++ m = m1; ++ if (m1 == 0) { /* in case of 'fastroute' */ ++ error = 0; ++ goto done; ++ } ++ ip6 = mtod(m, struct ip6_hdr *); ++ } ++ #endif + /* + * Send the packet to the outgoing interface. + * If necessary, do IPv6 fragmentation before sending. +diff -cr sys.30/sys/conf.h sys/sys/conf.h +*** sys.30/sys/conf.h Fri Oct 5 07:46:03 2001 +--- sys/sys/conf.h Fri Dec 28 13:45:33 2001 +*************** +*** 351,356 **** +--- 351,363 ---- + (dev_type_ioctl((*))) enodev, (dev_type_stop((*))) nullop, \ + 0, (dev_type_select((*))) enodev, (dev_type_mmap((*))) enodev } + ++ /* open, close, read, ioctl */ ++ #define cdev_gen_ipf(c, n) { \ ++ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ ++ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ ++ (dev_type_stop((*))) enodev, 0, (dev_type_select((*))) enodev, \ ++ (dev_type_mmap((*))) enodev } ++ + /* open, close, read, write, ioctl, select */ + #define cdev_xfs_init(c, n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ +*************** +*** 537,542 **** +--- 544,550 ---- + + cdev_decl(bpf); + ++ cdev_decl(ipl); + cdev_decl(pf); + + cdev_decl(tun); diff --git a/OpenBSD-3/3.1-MAKEDEV-diffs b/OpenBSD-3/3.1-MAKEDEV-diffs new file mode 100644 index 0000000000000..0ea712472102a --- /dev/null +++ b/OpenBSD-3/3.1-MAKEDEV-diffs @@ -0,0 +1,349 @@ +diff -r -c -d /tmp/etc/MAKEDEV.mi etc/MAKEDEV.mi +*** /tmp/etc/MAKEDEV.mi Thu Apr 11 13:28:49 2002 +--- etc/MAKEDEV.mi Mon Apr 29 05:09:27 2002 +*************** +*** 153,158 **** +--- 153,162 ---- + target(all, pctr0)dnl + target(all, altq)dnl + target(all, pf)dnl ++ target(all, ipl)dnl ++ target(all, ipnat)dnl ++ target(all, ipstate)dnl ++ target(all, ipauth)dnl + twrget(all, cry, crypto)dnl + target(all, apm)dnl + twrget(all, tth, ttyh, 0, 1)dnl +*************** +*** 1029,1034 **** +--- 1033,1052 ---- + _mkdev(cry, crypto, {-M crypto c major_cry_c-} 0)dnl + __devitem(pf, pf*, Packet Filter)dnl + _mkdev(pf, {-pf*-}, {-M pf c major_pf_c 0 600-})dnl ++ __devitem(ipl, ipl*, Packet Filter log)dnl ++ _mkdev(ipl, {-ipl*-}, {-M ipl c major_ipl_c 0 600-})dnl ++ __devitem(ipnat, ipnat*, Packet Filter NAT)dnl ++ _mkdev(ipnat, {-ipnat*-}, {-M ipnat c major_ipnat_c 1 600-})dnl ++ __devitem(ipstate, ipstate*, Packet Filter state)dnl ++ _mkdev(ipstate, {-ipstate*-}, {-M ipstate c major_ipstate_c 2 600-})dnl ++ __devitem(ipauth, ipauth*, Packet Filter auth)dnl ++ _mkdev(ipauth, {-ipauth*-}, {-M ipauth c major_ipauth_c 3 600-})dnl ++ __devitem(ipauth, ipauth*, Packet Filter auth)dnl ++ _mkdev(ipsync, {-ipsync*-}, {-M ipsync c major_ipsync_c 4 600-})dnl ++ __devitem(ipsync, ipsync*, Packet Filter sync)dnl ++ _mkdev(ipscan, {-ipscan*-}, {-M ipscan c major_ipscan_c 5 600-})dnl ++ __devitem(ipscan, ipscan*, Packet Filter scan)dnl ++ _mkdev(iplookup, {-iplookup*-}, {-M iplookup c major_iplookup_c 6 600-})dnl + __devitem(bpf, bpf*, Berkeley Packet Filter)dnl + _mkdev(bpf, {-bpf*-}, {-M bpf$U c major_bpf_c $U 600-}, 600)dnl + _mkdev(tun, {-tun*-}, {-M tun$U c major_tun_c $U 600-}, 600)dnl +diff -r -c -d /tmp/etc/etc.alpha/MAKEDEV.md etc/etc.alpha/MAKEDEV.md +*** /tmp/etc/etc.alpha/MAKEDEV.md Tue Apr 9 23:09:43 2002 +--- etc/etc.alpha/MAKEDEV.md Mon Apr 29 05:21:18 2002 +*************** +*** 66,71 **** +--- 66,78 ---- + _TITLE(spec) + _DEV(ch, 14) + _DEV(pf, 35) ++ _DEV(ipl, 44) ++ _DEV(ipnat, 44) ++ _DEV(ipstate, 44) ++ _DEV(ipauth, 44) ++ _DEV(ipscan, 44) ++ _DEV(ipsync, 44) ++ _DEV(iplookup, 44) + _DEV(bpf, 11) + _DEV(altq, 53) + _DEV(iop, 54) +diff -r -c -d /tmp/etc/etc.amiga/MAKEDEV.md etc/etc.amiga/MAKEDEV.md +*** /tmp/etc/etc.amiga/MAKEDEV.md Thu Feb 21 10:36:55 2002 +--- etc/etc.amiga/MAKEDEV.md Mon Apr 29 05:21:45 2002 +*************** +*** 65,70 **** +--- 65,77 ---- + _DEV(bpf, 22) + _DEV(tun, 23) + _DEV(pf, 34) ++ _DEV(ipl, 38) ++ _DEV(ipnat, 38) ++ _DEV(ipstate, 38) ++ _DEV(ipauth, 38) ++ _DEV(ipsync, 38) ++ _DEV(ipscan, 38) ++ _DEV(iplookup, 38) + _DEV(ss, 25) + _DEV(uk, 36) + _DEV(rnd, 35) +diff -r -c -d /tmp/etc/etc.hp300/MAKEDEV.md etc/etc.hp300/MAKEDEV.md +*** /tmp/etc/etc.hp300/MAKEDEV.md Sun Apr 14 16:26:45 2002 +--- etc/etc.hp300/MAKEDEV.md Mon Apr 29 05:22:05 2002 +*************** +*** 57,62 **** +--- 57,69 ---- + _DEV(bpf, 22) + _DEV(tun, 23) + _DEV(pf, 33) ++ _DEV(ipl, 37) ++ _DEV(ipnat, 37) ++ _DEV(ipstate, 37) ++ _DEV(ipauth, 37) ++ _DEV(ipsync, 37) ++ _DEV(ipscan, 37) ++ _DEV(iplookup, 37) + _DEV(lkm, 24) + _DEV(rnd, 32) + _DEV(xfs, 51) +diff -r -c -d /tmp/etc/etc.hppa/MAKEDEV.md etc/etc.hppa/MAKEDEV.md +*** /tmp/etc/etc.hppa/MAKEDEV.md Mon Feb 25 11:46:36 2002 +--- etc/etc.hppa/MAKEDEV.md Mon Apr 29 05:22:24 2002 +*************** +*** 51,56 **** +--- 51,63 ---- + _DEV(bpf, 17) + _DEV(tun, 18) + _DEV(pf, 21) ++ _DEV(ipl, 34) ++ _DEV(ipnat, 34) ++ _DEV(ipstate, 34) ++ _DEV(ipauth, 34) ++ _DEV(ipsync, 34) ++ _DEV(ipscan, 34) ++ _DEV(iplookup, 34) + _DEV(lkm, 19) + _DEV(altq, 33) + _DEV(rnd, 20) +diff -r -c -d /tmp/etc/etc.i386/MAKEDEV.md etc/etc.i386/MAKEDEV.md +*** /tmp/etc/etc.i386/MAKEDEV.md Thu Apr 11 19:13:21 2002 +--- etc/etc.i386/MAKEDEV.md Mon Apr 29 05:09:51 2002 +*************** +*** 74,79 **** +--- 74,86 ---- + _DEV(fdesc, 22) + _DEV(cry, 70) + _DEV(pf, 73) ++ _DEV(ipl, 78) ++ _DEV(ipnat, 78) ++ _DEV(ipstate, 78) ++ _DEV(ipauth, 78) ++ _DEV(ipsync, 78) ++ _DEV(ipscan, 78) ++ _DEV(iplookup, 78) + _DEV(bpf, 23) + _DEV(speak, 27) + _DEV(lkm, 28) +diff -r -c -d /tmp/etc/etc.mac68k/MAKEDEV.md etc/etc.mac68k/MAKEDEV.md +*** /tmp/etc/etc.mac68k/MAKEDEV.md Thu Feb 14 05:29:20 2002 +--- etc/etc.mac68k/MAKEDEV.md Mon Apr 29 05:24:15 2002 +*************** +*** 49,54 **** +--- 49,61 ---- + _DEV(bpf, 22) + _DEV(tun, 24) + _DEV(pf, 35) ++ _DEV(ipl, 38) ++ _DEV(ipnat, 38) ++ _DEV(ipstate, 38) ++ _DEV(ipauth, 38) ++ _DEV(ipsync, 38) ++ _DEV(ipscan, 38) ++ _DEV(iplookup, 38) + _DEV(altq, 52) + _DEV(lkm, 25) + _DEV(rnd, 32) +diff -r -c -d /tmp/etc/etc.macppc/MAKEDEV.md etc/etc.macppc/MAKEDEV.md +*** /tmp/etc/etc.macppc/MAKEDEV.md Sat Feb 23 09:02:03 2002 +--- etc/etc.macppc/MAKEDEV.md Mon Apr 29 05:24:41 2002 +*************** +*** 75,80 **** +--- 75,87 ---- + _DEV(altq, 72) + _DEV(iop, 73) + _DEV(pf, 39) ++ _DEV(ipl, 45) ++ _DEV(ipnat, 45) ++ _DEV(ipstate, 45) ++ _DEV(ipauth, 45) ++ _DEV(ipsync, 45) ++ _DEV(ipscan, 45) ++ _DEV(iplookup, 45) + _DEV(cry, 47) + _DEV(usbs) + _DEV(pci, 71) +diff -r -c -d /tmp/etc/etc.mvme68k/MAKEDEV.md etc/etc.mvme68k/MAKEDEV.md +*** /tmp/etc/etc.mvme68k/MAKEDEV.md Sat Feb 9 08:59:50 2002 +--- etc/etc.mvme68k/MAKEDEV.md Mon Apr 29 05:29:52 2002 +*************** +*** 94,100 **** + sh MAKEDEV vnd0 vnd1 pty0 cd0 + sh MAKEDEV bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 + #sh MAKEDEV ccd0 ccd1 ccd2 ccd3 +! sh MAKEDEV pf tun0 tun1 lkm local + sh MAKEDEV sram0 nvram0 flash0 vmel0 vmes0 + #sh MAKEDEV lp0 lptwo0 + sh MAKEDEV random +--- 94,100 ---- + sh MAKEDEV vnd0 vnd1 pty0 cd0 + sh MAKEDEV bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 + #sh MAKEDEV ccd0 ccd1 ccd2 ccd3 +! sh MAKEDEV ipl pf tun0 tun1 lkm local + sh MAKEDEV sram0 nvram0 flash0 vmel0 vmes0 + #sh MAKEDEV lp0 lptwo0 + sh MAKEDEV random +*************** +*** 406,411 **** +--- 406,423 ---- + chown root.wheel pf + chmod 600 pf + ;; ++ ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 44 0 ++ mknod ipnat c 44 1 ++ mknod ipstate c 44 2 ++ mknod ipauth c 44 3 ++ mknod ipsync c 44 4 ++ mknod ipscan c 44 5 ++ mknod iplookup c 44 6 ++ chown root.wheel ipl ipnat ipstate ipauth ipsync ipscan iplookup ++ ;; + + tun*) + unit=`expr $i : 'tun\(.*\)'` +diff -r -c -d /tmp/etc/etc.mvme88k/MAKEDEV.md etc/etc.mvme88k/MAKEDEV.md +*** /tmp/etc/etc.mvme88k/MAKEDEV.md Sat Feb 9 08:59:50 2002 +--- etc/etc.mvme88k/MAKEDEV.md Mon Apr 29 05:30:58 2002 +*************** +*** 81,87 **** + sh $this vnd0 vnd1 pty0 cd0 + sh $this bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 + #sh $this ccd0 ccd1 ccd2 ccd3 +! sh $this pf tun0 tun1 lkm local + sh $this sram0 nvram0 flash0 vmel0 vmes0 + #sh $this lp0 lptwo0 + sh $this random +--- 81,87 ---- + sh $this vnd0 vnd1 pty0 cd0 + sh $this bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 + #sh $this ccd0 ccd1 ccd2 ccd3 +! sh $this ipl pf tun0 tun1 lkm local + sh $this sram0 nvram0 flash0 vmel0 vmes0 + #sh $this lp0 lptwo0 + sh $this random +*************** +*** 285,290 **** +--- 285,302 ---- + chown root.wheel pf + chmod 600 pf + ;; ++ ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 41 0 ++ mknod ipnat c 41 1 ++ mknod ipstate c 41 2 ++ mknod ipauth c 41 3 ++ mknod ipsync c 41 4 ++ mknod ipscan c 41 5 ++ mknod iplookup c 41 6 ++ chown root.wheel ipl ipnat ipstate ipauth ipsync ipscan iplookup ++ ;; + + bpf*|tun*) + case $i in +diff -r -c -d /tmp/etc/etc.mvmeppc/MAKEDEV.md etc/etc.mvmeppc/MAKEDEV.md +*** /tmp/etc/etc.mvmeppc/MAKEDEV.md Thu Apr 11 13:29:42 2002 +--- etc/etc.mvmeppc/MAKEDEV.md Mon Apr 29 05:25:43 2002 +*************** +*** 68,73 **** +--- 68,80 ---- + _DEV(rnd) + _DEV(altq) + _DEV(pf, 39) ++ _DEV(ipl, 44) ++ _DEV(ipnat, 44) ++ _DEV(ipstate, 44) ++ _DEV(ipauth, 44) ++ _DEV(ipsync, 44) ++ _DEV(ipscan, 44) ++ _DEV(iplookup, 44) + _DEV(usbs) + # + dnl +diff -r -c -d /tmp/etc/etc.sparc/MAKEDEV.md etc/etc.sparc/MAKEDEV.md +*** /tmp/etc/etc.sparc/MAKEDEV.md Sun Apr 14 16:20:55 2002 +--- etc/etc.sparc/MAKEDEV.md Mon Apr 29 05:26:11 2002 +*************** +*** 63,68 **** +--- 63,75 ---- + _DEV(tcx, 109) + _DEV(bpf, 105) + _DEV(pf, 59) ++ _DEV(ipl, 60) ++ _DEV(ipnat, 60) ++ _DEV(ipstate, 60) ++ _DEV(ipauth, 60) ++ _DEV(ipsync, 60) ++ _DEV(ipscan, 60) ++ _DEV(iplookup, 60) + _DEV(altq, 125) + _DEV(lkm, 112) + _DEV(tun, 111) +diff -r -c -d /tmp/etc/etc.sparc64/MAKEDEV.md etc/etc.sparc64/MAKEDEV.md +*** /tmp/etc/etc.sparc64/MAKEDEV.md Tue Apr 9 23:09:43 2002 +--- etc/etc.sparc64/MAKEDEV.md Mon Apr 29 05:26:30 2002 +*************** +*** 82,87 **** +--- 82,94 ---- + _DEV(uk, 60) + _DEV(au, 69) + _DEV(pf, 73) ++ _DEV(ipl, 82) ++ _DEV(ipnat, 82) ++ _DEV(ipstate, 82) ++ _DEV(ipauth, 82) ++ _DEV(ipsync, 82) ++ _DEV(ipscan, 82) ++ _DEV(iplookup, 82) + _DEV(altq, 74) + _DEV(bpf, 105) + _DEV(tun, 111) +diff -r -c -d /tmp/etc/etc.sun3/MAKEDEV.md etc/etc.sun3/MAKEDEV.md +*** /tmp/etc/etc.sun3/MAKEDEV.md Sun Apr 14 16:26:46 2002 +--- etc/etc.sun3/MAKEDEV.md Mon Apr 29 05:27:01 2002 +*************** +*** 52,57 **** +--- 52,64 ---- + _DEV(cfr, 39) + _DEV(bpf, 36) + _DEV(pf, 75) ++ _DEV(ipl, 86) ++ _DEV(ipnat, 86) ++ _DEV(ipstate, 86) ++ _DEV(ipauth, 86) ++ _DEV(ipsync, 86) ++ _DEV(ipscan, 86) ++ _DEV(iplookup, 86) + _DEV(tun, 24) + _DEV(rd, 52, 13) + _DEV(rnd, 72) +diff -r -c -d /tmp/etc/etc.vax/MAKEDEV.md etc/etc.vax/MAKEDEV.md +*** /tmp/etc/etc.vax/MAKEDEV.md Thu Feb 21 10:36:55 2002 +--- etc/etc.vax/MAKEDEV.md Mon Apr 29 05:27:21 2002 +*************** +*** 70,75 **** +--- 70,82 ---- + _DEV(oppr) + _DEV(bpf, 56) + _DEV(pf, 42) ++ _DEV(ipl, 47) ++ _DEV(ipnat, 47) ++ _DEV(ipstate, 47) ++ _DEV(ipauth, 47) ++ _DEV(ipsync, 47) ++ _DEV(ipscan, 47) ++ _DEV(iplookup, 47) + _DEV(altq, 75) + _DEV(lkm, 28) + _DEV(tun, 57) diff --git a/OpenBSD-3/3.1-rc-diffs b/OpenBSD-3/3.1-rc-diffs new file mode 100644 index 0000000000000..aaa1f78d4fbb4 --- /dev/null +++ b/OpenBSD-3/3.1-rc-diffs @@ -0,0 +1,89 @@ +diff -d -c -r tmp/etc/netstart etc/netstart +*** tmp/etc/netstart Sun Apr 21 22:16:44 2002 +--- etc/netstart Thu Apr 25 04:33:59 2002 +*************** +*** 181,186 **** +--- 181,196 ---- + domainname `cat /etc/defaultdomain` + fi + ++ # Configure the IP filter before configuring network interfaces ++ if [ X"${ipfilter}" = X"YES" -a -f "${ipfilter_rules}" ]; then ++ echo 'configuring IP filter' ++ ipf -Fa -f ${ipfilter_rules} ++ ipfresync="ipf -y" ++ else ++ ipfilter=NO ++ ipfresync=NO ++ fi ++ + # Set the address for the loopback interface. + # It will also initialize IPv6 address for lo0 (::1 and others). + ifconfig lo0 inet localhost +*************** +*** 333,335 **** +--- 343,358 ---- + + bridgestart $if + done ++ ++ # Configure NAT after configuring network interfaces ++ if [ "${ipnat}" = "YES" -a "${ipfilter}" = "YES" -a -f "${ipnat_rules}" ]; then ++ echo 'configuring NAT' ++ ipnat -CF -f ${ipnat_rules} ++ else ++ ipnat=NO ++ fi ++ ++ # Interfaces have come up so we should do an ipf -y if we're using IP filter. ++ if [ "${ipfresync}" != "NO" ]; then ++ ${ipfresync} ++ fi +diff -d -c -r tmp/etc/rc etc/rc +*** tmp/etc/rc Sun Apr 21 22:16:44 2002 +--- etc/rc Thu Apr 25 04:34:44 2002 +*************** +*** 215,220 **** +--- 215,224 ---- + echo 'starting named'; named $named_flags + fi + ++ if [ X"${ipfilter}" = X"YES" -a X"${ipmon_flags}" != X"NO" ]; then ++ echo 'starting ipmon'; ipmon ${ipmon_flags} ++ fi ++ + # $photurisd_flags is imported from /etc/rc.conf; + # If $photurisd_flags == NO or /etc/photuris/photuris.conf doesn't exist, then + # photurisd isn't run. +diff -d -c -r tmp/etc/rc.conf etc/rc.conf +*** tmp/etc/rc.conf Sun Apr 21 22:16:44 2002 +--- etc/rc.conf Thu Apr 25 04:35:43 2002 +*************** +*** 53,58 **** + lockd=NO + gated=NO + amd=NO +! pf=NO # Packet filter / NAT + portmap=YES # almost always needed + inetd=YES # almost always needed +--- 53,60 ---- + lockd=NO + gated=NO + amd=NO ++ ipfilter=NO # To enable ipfilter, set to YES ++ ipnat=NO # for "YES", ipfilter must also be "YES" +! pf=NO # Enable pf(4) Packet filter / NAT + portmap=YES # almost always needed + inetd=YES # almost always needed +*************** +*** 79,84 **** +--- 81,89 ---- + nfsd_flags="-tun 4" # Crank the 4 for a busy NFS fileserver + amd_dir=/tmp_mnt # AMD's mount directory + amd_master=/etc/amd/master # AMD 'master' map ++ ipfilter_rules=/etc/ipf.rules # Rules for IP packet filtering with IP Filter ++ ipnat_rules=/etc/ipnat.rules # Rules for Network Address Translation ++ ipmon_flags=-Ds # To disable logging, use ipmon_flags=NO + syslogd_flags= # add more flags, ie. "-u -a /chroot/dev/log" + named_user=named # Named should not run as root unless necessary + named_chroot=/var/named # Where to chroot named if not empty diff --git a/OpenBSD-3/3.1-sys-diffs b/OpenBSD-3/3.1-sys-diffs new file mode 100644 index 0000000000000..d2c2f483f4e0a --- /dev/null +++ b/OpenBSD-3/3.1-sys-diffs @@ -0,0 +1,918 @@ +diff -d -c -r /tmp/sys/arch/alpha/alpha/conf.c sys/arch/alpha/alpha/conf.c +*** /tmp/sys/arch/alpha/alpha/conf.c Tue Jan 22 21:21:03 2002 +--- sys/arch/alpha/alpha/conf.c Thu Apr 25 03:43:26 2002 +*************** +*** 113,118 **** +--- 113,123 ---- + #include "lpt.h" + cdev_decl(lpt); + cdev_decl(prom); /* XXX XXX XXX */ ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif + cdev_decl(wd); + cdev_decl(fd); + #include "cy.h" +*************** +*** 191,197 **** + cdev_midi_init(NMIDI,midi), /* 41: MIDI I/O */ + cdev_midi_init(NSEQUENCER,sequencer), /* 42: sequencer I/O */ + cdev_disk_init(NRAID,raid), /* 43: RAIDframe disk driver */ +! cdev_notdef(), /* 44 */ + cdev_usb_init(NUSB,usb), /* 45: USB controller */ + cdev_usbdev_init(NUHID,uhid), /* 46: USB generic HID */ + cdev_lpt_init(NULPT,ulpt), /* 47: USB printer */ +--- 196,202 ---- + cdev_midi_init(NMIDI,midi), /* 41: MIDI I/O */ + cdev_midi_init(NSEQUENCER,sequencer), /* 42: sequencer I/O */ + cdev_disk_init(NRAID,raid), /* 43: RAIDframe disk driver */ +! cdev_gen_ipf(NIPF,ipl), /* 44: IP filter log */ + cdev_usb_init(NUSB,usb), /* 45: USB controller */ + cdev_usbdev_init(NUHID,uhid), /* 46: USB generic HID */ + cdev_lpt_init(NULPT,ulpt), /* 47: USB printer */ +diff -d -c -r /tmp/sys/arch/amiga/amiga/conf.c sys/arch/amiga/amiga/conf.c +*** /tmp/sys/arch/amiga/amiga/conf.c Wed Mar 13 17:26:28 2002 +--- sys/arch/amiga/amiga/conf.c Thu Apr 25 03:44:01 2002 +*************** +*** 158,164 **** + cdev_random_init(1,random), /* 35: random data source */ + cdev_uk_init(NUK,uk), /* 36: unknown SCSI */ + cdev_disk_init(NWD,wd), /* 37: ST506/ESDI/IDE disk */ +! cdev_notdef(), /* 38 */ + cdev_audio_init(NAUDIO,audio), /* 39: cc audio interface */ + cdev_ch_init(NCH,ch), /* 40: SCSI autochanger */ + cdev_disk_init(NRD,rd), /* 41: RAM disk */ +--- 158,164 ---- + cdev_random_init(1,random), /* 35: random data source */ + cdev_uk_init(NUK,uk), /* 36: unknown SCSI */ + cdev_disk_init(NWD,wd), /* 37: ST506/ESDI/IDE disk */ +! cdev_gen_ipf(NIPF,ipl), /* 38: IP filter log */ + cdev_audio_init(NAUDIO,audio), /* 39: cc audio interface */ + cdev_ch_init(NCH,ch), /* 40: SCSI autochanger */ + cdev_disk_init(NRD,rd), /* 41: RAM disk */ +diff -d -c -r /tmp/sys/arch/hp300/hp300/conf.c sys/arch/hp300/hp300/conf.c +*** /tmp/sys/arch/hp300/hp300/conf.c Tue Dec 11 15:19:02 2001 +--- sys/arch/hp300/hp300/conf.c Thu Apr 25 03:45:58 2002 +*************** +*** 127,132 **** +--- 127,138 ---- + cdev_decl(xfs_dev); + #endif + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 170,176 **** + cdev_disk_init(NRD,rd), /* 34: RAM disk */ + cdev_tty_init(NAPCI,apci), /* 35: Apollo APCI UARTs */ + cdev_ksyms_init(NKSYMS,ksyms), /* 36: Kernel symbols device */ +! cdev_notdef(), /* 37 */ + cdev_notdef(), /* 38 */ + cdev_notdef(), /* 39 */ + cdev_notdef(), /* 40 */ +--- 176,182 ---- + cdev_disk_init(NRD,rd), /* 34: RAM disk */ + cdev_tty_init(NAPCI,apci), /* 35: Apollo APCI UARTs */ + cdev_ksyms_init(NKSYMS,ksyms), /* 36: Kernel symbols device */ +! cdev_pf_init(NIPF,ipl), /* 37: packet filter */ + cdev_notdef(), /* 38 */ + cdev_notdef(), /* 39 */ + cdev_notdef(), /* 40 */ +diff -d -c -r /tmp/sys/arch/hppa/hppa/conf.c sys/arch/hppa/hppa/conf.c +*** /tmp/sys/arch/hppa/hppa/conf.c Fri Mar 15 16:34:56 2002 +--- sys/arch/hppa/hppa/conf.c Thu Apr 25 03:48:20 2002 +*************** +*** 110,115 **** +--- 110,121 ---- + #include "com.h" + cdev_decl(com); + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 155,160 **** +--- 161,167 ---- + cdev_notdef(), /* 32 */ + #endif + cdev_altq_init(NALTQ,altq), /* 33: ALTQ control interface */ ++ cdev_gen_ipf(NIPF,ipl), /* 34: ip filtering */ + cdev_lkm_dummy(), + cdev_lkm_dummy(), + cdev_lkm_dummy(), +diff -d -c -r /tmp/sys/arch/i386/i386/conf.c sys/arch/i386/i386/conf.c +*** /tmp/sys/arch/i386/i386/conf.c Wed Mar 13 17:26:32 2002 +--- sys/arch/i386/i386/conf.c Thu Apr 25 03:50:28 2002 +*************** +*** 210,215 **** +--- 210,221 ---- + cdev_decl(cztty); + #include "radio.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + /* XXX -- this needs to be supported by config(8)! */ + #if (NCOM > 0) && (NPCCOM > 0) + #error com and pccom are mutually exclusive. Sorry. +*************** +*** 337,342 **** +--- 343,349 ---- + cdev_iop_init(NIOP,iop), /* 75: I2O IOP control interface */ + cdev_radio_init(NRADIO, radio), /* 76: generic radio I/O */ + cdev_ugen_init(NUSCANNER,uscanner), /* 77: USB scanners */ ++ cdev_gen_ipf(NIPF,ipl), /* 78: ip filtering */ + }; + int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]); + +diff -d -c -r /tmp/sys/arch/mac68k/mac68k/conf.c sys/arch/mac68k/mac68k/conf.c +*** /tmp/sys/arch/mac68k/mac68k/conf.c Tue Dec 11 15:19:02 2001 +--- sys/arch/mac68k/mac68k/conf.c Thu Apr 25 03:51:20 2002 +*************** +*** 109,114 **** +--- 109,120 ---- + cdev_decl(xfs_dev); + #endif + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 153,159 **** + cdev_pf_init(NPF,pf), /* 35: packet filter */ + cdev_audio_init(NASC,asc), /* 36: ASC audio device */ + cdev_ksyms_init(NKSYMS,ksyms), /* 37: Kernel symbols device */ +! cdev_notdef(), /* 38 */ + cdev_notdef(), /* 39 */ + cdev_notdef(), /* 40 */ + cdev_notdef(), /* 41 */ +--- 159,165 ---- + cdev_pf_init(NPF,pf), /* 35: packet filter */ + cdev_audio_init(NASC,asc), /* 36: ASC audio device */ + cdev_ksyms_init(NKSYMS,ksyms), /* 37: Kernel symbols device */ +! cdev_gen_ipf(NIPF,ipl), /* 38: IP filter log */ + cdev_notdef(), /* 39 */ + cdev_notdef(), /* 40 */ + cdev_notdef(), /* 41 */ +diff -d -c -r /tmp/sys/arch/macppc/macppc/conf.c sys/arch/macppc/macppc/conf.c +*** /tmp/sys/arch/macppc/macppc/conf.c Wed Dec 12 11:19:17 2001 +--- sys/arch/macppc/macppc/conf.c Thu Apr 25 03:52:12 2002 +*************** +*** 105,110 **** +--- 105,116 ---- + + #include "tun.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #ifdef XFS + #include <xfs/nxfs.h> + cdev_decl(xfs_dev); +*************** +*** 197,203 **** + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ + cdev_audio_init(NAUDIO,audio), /* 44: generic audio I/O */ +! cdev_notdef(), /* 45 */ + cdev_notdef(), /* 46 */ + cdev_crypto_init(NCRYPTO,crypto), /* 47: /dev/crypto */ + cdev_notdef(), /* 48 */ +--- 203,209 ---- + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ + cdev_audio_init(NAUDIO,audio), /* 44: generic audio I/O */ +! cdev_gen_ipf(NIPF,ipl), /* 45: IP filter */ + cdev_notdef(), /* 46 */ + cdev_crypto_init(NCRYPTO,crypto), /* 47: /dev/crypto */ + cdev_notdef(), /* 48 */ +diff -d -c -r /tmp/sys/arch/mvme68k/mvme68k/conf.c sys/arch/mvme68k/mvme68k/conf.c +*** /tmp/sys/arch/mvme68k/mvme68k/conf.c Tue Dec 11 15:19:02 2001 +--- sys/arch/mvme68k/mvme68k/conf.c Thu Apr 25 03:53:06 2002 +*************** +*** 169,174 **** +--- 169,180 ---- + #include "bpfilter.h" + #include "tun.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 219,225 **** + cdev_uk_init(NUK,uk), /* 41: unknown SCSI */ + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ +! cdev_lkm_dummy(), /* 44 */ + cdev_lkm_dummy(), /* 45 */ + cdev_lkm_dummy(), /* 46 */ + cdev_lkm_dummy(), /* 47 */ +--- 225,231 ---- + cdev_uk_init(NUK,uk), /* 41: unknown SCSI */ + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ +! cdev_gen_ipf(NIPF,ipl), /* 44: IP filter */ + cdev_lkm_dummy(), /* 45 */ + cdev_lkm_dummy(), /* 46 */ + cdev_lkm_dummy(), /* 47 */ +diff -d -c -r /tmp/sys/arch/mvme88k/mvme88k/conf.c sys/arch/mvme88k/mvme88k/conf.c +*** /tmp/sys/arch/mvme88k/mvme88k/conf.c Thu Sep 27 19:53:13 2001 +--- sys/arch/mvme88k/mvme88k/conf.c Thu Apr 25 03:54:32 2002 +*************** +*** 113,118 **** +--- 113,124 ---- + cdev_decl(lptwo); + #endif /* notyet */ + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 199,205 **** + cdev_lkm_dummy(), /* 38 */ + cdev_pf_init(NPF,pf), /* 39: packet filter */ + cdev_random_init(1,random), /* 40: random data source */ +! cdev_notdef(), /* 41 */ + cdev_notdef(), /* 42 */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ + cdev_notdef(), /* 44 */ +--- 205,211 ---- + cdev_lkm_dummy(), /* 38 */ + cdev_pf_init(NPF,pf), /* 39: packet filter */ + cdev_random_init(1,random), /* 40: random data source */ +! cdev_gen_ipf(NIPF,ipl), /* 41: IP filter */ + cdev_notdef(), /* 42 */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ + cdev_notdef(), /* 44 */ +diff -d -c -r /tmp/sys/arch/mvmeppc/mvmeppc/conf.c sys/arch/mvmeppc/mvmeppc/conf.c +*** /tmp/sys/arch/mvmeppc/mvmeppc/conf.c Tue Dec 11 15:19:02 2001 +--- sys/arch/mvmeppc/mvmeppc/conf.c Thu Apr 25 03:55:20 2002 +*************** +*** 117,122 **** +--- 117,128 ---- + #include "ksyms.h" + cdev_decl(ksyms); + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 170,176 **** + cdev_uk_init(NUK,uk), /* 41: unknown SCSI */ + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ +! cdev_notdef(), /* 44 */ + cdev_notdef(), /* 45 */ + cdev_notdef(), /* 46 */ + cdev_notdef(), /* 47 */ +--- 176,182 ---- + cdev_uk_init(NUK,uk), /* 41: unknown SCSI */ + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ +! cdev_gen_ipf(NIPF,ipl), /* 44: IP filter */ + cdev_notdef(), /* 45 */ + cdev_notdef(), /* 46 */ + cdev_notdef(), /* 47 */ +diff -d -c -r /tmp/sys/arch/sparc/sparc/conf.c sys/arch/sparc/sparc/conf.c +*** /tmp/sys/arch/sparc/sparc/conf.c Tue Dec 11 15:19:02 2001 +--- sys/arch/sparc/sparc/conf.c Thu Apr 25 03:56:03 2002 +*************** +*** 128,133 **** +--- 128,139 ---- + }; + int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]); + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 202,208 **** + cdev_notdef(), /* 57 */ + cdev_disk_init(NCD,cd), /* 58: SCSI CD-ROM */ + cdev_pf_init(NPF,pf), /* 59: packet filter */ +! cdev_notdef(), /* 60 */ + cdev_notdef(), /* 61 */ + cdev_notdef(), /* 62 */ + cdev_notdef(), /* 63 */ +--- 208,214 ---- + cdev_notdef(), /* 57 */ + cdev_disk_init(NCD,cd), /* 58: SCSI CD-ROM */ + cdev_pf_init(NPF,pf), /* 59: packet filter */ +! cdev_gen_ipf(NIPF,ipl), /* 60: ip filtering log */ + cdev_notdef(), /* 61 */ + cdev_notdef(), /* 62 */ + cdev_notdef(), /* 63 */ +diff -d -c -r /tmp/sys/arch/sparc64/sparc64/conf.c sys/arch/sparc64/sparc64/conf.c +*** /tmp/sys/arch/sparc64/sparc64/conf.c Fri Mar 15 12:46:11 2002 +--- sys/arch/sparc64/sparc64/conf.c Thu Apr 25 03:57:39 2002 +*************** +*** 120,125 **** +--- 120,131 ---- + #include "ucom.h" + #include "uscanner.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 256,262 **** + cdev_mouse_init(NWSKBD, wskbd), /* 79: keyboards */ + cdev_mouse_init(NWSMOUSE, wsmouse), /* 80: mice */ + cdev_mouse_init(NWSMUX, wsmux), /* 81: ws multiplexor */ +! cdev_notdef(), /* 82 */ + cdev_notdef(), /* 83 */ + cdev_notdef(), /* 84 */ + cdev_notdef(), /* 85 */ +--- 262,268 ---- + cdev_mouse_init(NWSKBD, wskbd), /* 79: keyboards */ + cdev_mouse_init(NWSMOUSE, wsmouse), /* 80: mice */ + cdev_mouse_init(NWSMUX, wsmux), /* 81: ws multiplexor */ +! cdev_gen_ipf(NIPF,ipl), /* 82: IP filter */ + cdev_notdef(), /* 83 */ + cdev_notdef(), /* 84 */ + cdev_notdef(), /* 85 */ +diff -d -c -r /tmp/sys/arch/sun3/sun3/conf.c sys/arch/sun3/sun3/conf.c +*** /tmp/sys/arch/sun3/sun3/conf.c Tue Dec 11 15:19:02 2001 +--- sys/arch/sun3/sun3/conf.c Thu Apr 25 03:58:26 2002 +*************** +*** 109,114 **** +--- 109,120 ---- + }; + int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]); + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 205,210 **** +--- 211,217 ---- + cdev_ch_init(NCH,ch), /* 83: SCSI autochanger */ + cdev_ses_init(NSES,ses), /* 84: SCSI SES or SAF-TE device */ + cdev_altq_init(NALTQ,altq), /* 85: ALTQ control interface */ ++ cdev_gen_ipf(NIPF,ipl), /* 86: IP filter */ + }; + int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]); + +diff -d -c -r /tmp/sys/arch/vax/vax/conf.c sys/arch/vax/vax/conf.c +*** /tmp/sys/arch/vax/vax/conf.c Wed Mar 13 17:26:48 2002 +--- sys/arch/vax/vax/conf.c Thu Apr 25 03:59:16 2002 +*************** +*** 400,405 **** +--- 400,411 ---- + #include "wskbd.h" + #include "wsmouse.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 453,459 **** + cdev_notdef(), /* 44 was Datakit */ + cdev_notdef(), /* 45 was Datakit */ + cdev_notdef(), /* 46 was Datakit */ +! cdev_notdef(), /* 47 */ + cdev_notdef(), /* 48 */ + cdev_notdef(), /* 49 */ + cdev_ksyms_init(NKSYMS,ksyms), /* 50: Kernel symbols device */ +--- 459,465 ---- + cdev_notdef(), /* 44 was Datakit */ + cdev_notdef(), /* 45 was Datakit */ + cdev_notdef(), /* 46 was Datakit */ +! cdev_gen_ipf(NIPF,ipl), /* 47: IP filter */ + cdev_notdef(), /* 48 */ + cdev_notdef(), /* 49 */ + cdev_ksyms_init(NKSYMS,ksyms), /* 50: Kernel symbols device */ +diff -d -c -r /tmp/sys/conf/GENERIC sys/conf/GENERIC +*** /tmp/sys/conf/GENERIC Wed Mar 13 16:42:25 2002 +--- sys/conf/GENERIC Thu Apr 25 04:00:29 2002 +*************** +*** 72,77 **** +--- 72,79 ---- + #option EON # OSI tunneling over IP + #option NETATALK # AppleTalk + #option CCITT,LLC,HDLC # X.25 ++ option IPFILTER # IP packet filter for security ++ option IPFILTER_LOG # use /dev/ipl to log IPF + option PPP_BSDCOMP # PPP BSD compression + option PPP_DEFLATE + #option MROUTING # Multicast router +diff -d -c -r /tmp/sys/conf/files sys/conf/files +*** /tmp/sys/conf/files Thu Mar 28 10:23:07 2002 +--- sys/conf/files Thu Apr 25 04:01:15 2002 +*************** +*** 657,662 **** +--- 657,673 ---- + file netinet/tcp_usrreq.c inet + file netinet/udp_usrreq.c inet + file netinet/ip_gre.c inet ++ file netinet/ip_fil.c ipfilter ++ file netinet/fil.c ipfilter ++ file netinet/ip_nat.c ipfilter ++ file netinet/ip_frag.c ipfilter ++ file netinet/ip_state.c ipfilter ++ file netinet/ip_proxy.c ipfilter ++ file netinet/ip_auth.c ipfilter ++ file netinet/ip_log.c ipfilter ++ file netinet/ip_lookup.c ipfilter & ipfilter_lookup ++ file netinet/ip_pool.c ipfilter & ipfilter_lookup ++ file netinet/ip_htable.c ipfilter & ipfilter_lookup + file netinet/ip_ipsp.c (inet | inet6) & (ipsec | tcp_signature) + file netinet/ip_spd.c (inet | inet6) & (ipsec | tcp_signature) + file netinet/ip_ipip.c inet | inet6 +diff -d -c -r /tmp/sys/net/bridgestp.c sys/net/bridgestp.c +*** /tmp/sys/net/bridgestp.c Wed Mar 13 17:27:09 2002 +--- sys/net/bridgestp.c Thu Apr 25 04:01:51 2002 +*************** +*** 63,68 **** +--- 63,73 ---- + #include <netinet/in_var.h> + #include <netinet/ip.h> + #include <netinet/if_ether.h> ++ ++ #ifdef IPFILTER ++ #include <netinet/ip_compat.h> ++ #include <netinet/ip_fil.h> ++ #endif + #endif + + #if NBPFILTER > 0 +diff -d -c -r /tmp/sys/net/if.c sys/net/if.c +*** /tmp/sys/net/if.c Wed Mar 13 17:27:09 2002 +--- sys/net/if.c Thu Apr 25 04:02:42 2002 +*************** +*** 99,104 **** +--- 99,110 ---- + #include <netinet6/in6_ifattach.h> + #endif + ++ #ifdef IPFILTER ++ #include <netinet/ip_compat.h> ++ #include <netinet/ip_fil.h> ++ #include <netinet/ip_nat.h> ++ #endif ++ + #if NBPFILTER > 0 + #include <net/bpf.h> + #endif +*************** +*** 381,386 **** +--- 387,397 ---- + + /* Remove the interface from the list of all interfaces. */ + TAILQ_REMOVE(&ifnet, ifp, if_list); ++ ++ #ifdef IPFILTER ++ /* XXX More ipf & ipnat cleanup needed. */ ++ frsync(ifp); ++ #endif + + /* Deallocate private resources. */ + for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa; +diff -d -c -r /tmp/sys/net/if_bridge.c sys/net/if_bridge.c +*** /tmp/sys/net/if_bridge.c Mon Apr 8 10:49:42 2002 +--- sys/net/if_bridge.c Thu Apr 25 04:13:30 2002 +*************** +*** 67,72 **** +--- 67,76 ---- + #include <netinet/ip_ipsp.h> + + #include <net/if_enc.h> ++ #if (defined(IPFILTER) || defined(IPFILTER_LKM)) ++ #include <netinet/ip_compat.h> ++ #include <netinet/ip_fil.h> ++ #endif + #endif + + #ifdef INET6 +*************** +*** 152,158 **** + int bridge_flushrule(struct bridge_iflist *); + int bridge_brlconf(struct bridge_softc *, struct ifbrlconf *); + u_int8_t bridge_filterrule(struct brl_head *, struct ether_header *); +! #if NPF > 0 + struct mbuf *bridge_filter(struct bridge_softc *, int, struct ifnet *, + struct ether_header *, struct mbuf *m); + #endif +--- 156,162 ---- + int bridge_flushrule(struct bridge_iflist *); + int bridge_brlconf(struct bridge_softc *, struct ifbrlconf *); + u_int8_t bridge_filterrule(struct brl_head *, struct ether_header *); +! #if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + struct mbuf *bridge_filter(struct bridge_softc *, int, struct ifnet *, + struct ether_header *, struct mbuf *m); + #endif +*************** +*** 1167,1173 **** + m_freem(m); + return; + } +! #if NPF > 0 + m = bridge_filter(sc, BRIDGE_IN, src_if, &eh, m); + if (m == NULL) + return; +--- 1171,1177 ---- + m_freem(m); + return; + } +! #if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + m = bridge_filter(sc, BRIDGE_IN, src_if, &eh, m); + if (m == NULL) + return; +*************** +*** 1210,1216 **** + m_freem(m); + return; + } +! #if NPF > 0 + m = bridge_filter(sc, BRIDGE_OUT, dst_if, &eh, m); + if (m == NULL) + return; +--- 1214,1220 ---- + m_freem(m); + return; + } +! #if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + m = bridge_filter(sc, BRIDGE_OUT, dst_if, &eh, m); + if (m == NULL) + return; +*************** +*** 1477,1483 **** + mc = m1; + } + +! #if NPF > 0 + mc = bridge_filter(sc, BRIDGE_OUT, dst_if, eh, mc); + if (mc == NULL) + continue; +--- 1481,1487 ---- + mc = m1; + } + +! #if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + mc = bridge_filter(sc, BRIDGE_OUT, dst_if, eh, mc); + if (mc == NULL) + continue; +*************** +*** 2127,2133 **** + return (0); + } + +! #if NPF > 0 + /* + * Filter IP packets by peeking into the ethernet frame. This violates + * the ISO model, but allows us to act as a IP filter at the data link +--- 2131,2137 ---- + return (0); + } + +! #if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + /* + * Filter IP packets by peeking into the ethernet frame. This violates + * the ISO model, but allows us to act as a IP filter at the data link +*************** +*** 2234,2239 **** +--- 2238,2247 ---- + m->m_pkthdr.rcvif = ifp; + if (pf_test(dir, ifp, &m) != PF_PASS) + goto dropit; ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, dir, &m)) ++ goto dropit; ++ #endif + if (m == NULL) + goto dropit; + +*************** +*** 2306,2309 **** + m_freem(m); + return (NULL); + } +! #endif /* NPF > 0 */ +--- 2314,2317 ---- + m_freem(m); + return (NULL); + } +! #endif /* (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) */ +diff -d -c -r /tmp/sys/netinet/in_proto.c sys/netinet/in_proto.c +*** /tmp/sys/netinet/in_proto.c Fri Mar 1 14:29:29 2002 +--- sys/netinet/in_proto.c Thu Apr 25 04:14:34 2002 +*************** +*** 163,168 **** +--- 163,173 ---- + #include <netinet/ip_mroute.h> + #endif /* MROUTING */ + ++ #ifdef IPFILTER ++ void iplinit __P((void)); ++ #define ip_init iplinit ++ #endif ++ + #ifdef INET6 + #include <netinet6/ip6_var.h> + #endif /* INET6 */ +diff -d -c -r /tmp/sys/netinet/ip_input.c sys/netinet/ip_input.c +*** /tmp/sys/netinet/ip_input.c Wed Mar 13 17:27:11 2002 +--- sys/netinet/ip_input.c Thu Apr 25 04:16:39 2002 +*************** +*** 149,154 **** +--- 149,158 ---- + struct in_ifaddrhead in_ifaddr; + struct ifqueue ipintrq; + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif ++ + int ipq_locked; + static __inline int ipq_lock_try(void); + static __inline void ipq_unlock(void); +*************** +*** 397,402 **** +--- 401,423 ---- + + ip = mtod(m, struct ip *); + hlen = ip->ip_hl << 2; ++ #endif ++ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * Check if we want to allow this packet to be processed. ++ * Consider it to be bad if not. ++ */ ++ { ++ struct mbuf *m0 = m; ++ if (fr_checkp && (*fr_checkp)(ip, hlen, m->m_pkthdr.rcvif, 0, &m0)) { ++ return; ++ } ++ if (m0 == 0) { /* in case of 'fastroute' */ ++ return; ++ } ++ ip = mtod(m = m0, struct ip *); ++ } + #endif + + #ifdef ALTQ +diff -d -c -r /tmp/sys/netinet/ip_output.c sys/netinet/ip_output.c +*** /tmp/sys/netinet/ip_output.c Fri Mar 15 10:19:52 2002 +--- sys/netinet/ip_output.c Thu Apr 25 04:19:54 2002 +*************** +*** 90,95 **** +--- 90,99 ---- + static struct mbuf *ip_insertoptions(struct mbuf *, struct mbuf *, int *); + static void ip_mloopback(struct ifnet *, struct mbuf *, struct sockaddr_in *); + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif ++ + /* + * IP output. The packet in mbuf chain m contains a skeletal IP + * header (with len, off, ttl, proto, tos, src, dst). +*************** +*** 536,541 **** +--- 540,569 ---- + if (sproto != 0) { + s = splnet(); + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (fr_checkp) { ++ /* ++ * Ok, it's time for a simple round-trip to the IPF/NAT ++ * code with the enc0 interface. ++ */ ++ struct mbuf *m1 = m; ++ void *ifp = (void *)&encif[0].sc_if; ++ ++ if ((*fr_checkp)(ip, hlen, ifp, 1, &m1)) { ++ error = EHOSTUNREACH; ++ splx(s); ++ goto done; ++ } ++ if (m1 == 0) { /* in case of 'fastroute' */ ++ error = 0; ++ splx(s); ++ goto done; ++ } ++ ip = mtod(m = m1, struct ip *); ++ hlen = ip->ip_hl << 2; ++ } ++ #endif /* IPFILTER */ ++ + /* + * Packet filter + */ +*************** +*** 641,646 **** +--- 669,693 ---- + m->m_pkthdr.csum &= ~M_UDPV4_CSUM_OUT; /* Clear */ + } + } ++ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * looks like most checking has been done now...do a filter check ++ */ ++ { ++ struct mbuf *m1 = m; ++ ++ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 1, &m1)) { ++ error = EHOSTUNREACH; ++ goto done; ++ } ++ if (m1 == 0) { /* in case of 'fastroute' */ ++ error = 0; ++ goto done; ++ } ++ ip = mtod(m = m1, struct ip *); ++ } ++ #endif + + /* + * Packet filter +diff -d -c -r /tmp/sys/netinet6/ip6_input.c sys/netinet6/ip6_input.c +*** /tmp/sys/netinet6/ip6_input.c Wed Mar 13 17:27:12 2002 +--- sys/netinet6/ip6_input.c Thu Apr 25 04:22:32 2002 +*************** +*** 135,140 **** +--- 135,144 ---- + static struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int); + #endif + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif ++ + /* + * IP6 initialization: fill in IP6 protocol switch table. + * All protocols not implemented in kernel go to raw IP6 protocol handler. +*************** +*** 267,272 **** +--- 271,296 ---- + in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); + goto bad; + } ++ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * Check if we want to allow this packet to be processed. ++ * Consider it to be bad if not. ++ */ ++ if (fr_checkp != NULL) { ++ struct mbuf *m0 = m; ++ ++ if ((*fr_checkp)((struct ip *)ip6, sizeof(*ip6), ++ m->m_pkthdr.rcvif, 0, &m0)) { ++ return; ++ } ++ m = m0; ++ if (m == 0) { /* in case of 'fastroute' */ ++ return; ++ } ++ ip6 = mtod(m, struct ip6_hdr *); ++ } ++ #endif + + #if NPF > 0 + /* +diff -d -c -r /tmp/sys/netinet6/ip6_output.c sys/netinet6/ip6_output.c +*** /tmp/sys/netinet6/ip6_output.c Wed Mar 13 17:27:12 2002 +--- sys/netinet6/ip6_output.c Thu Apr 25 04:25:17 2002 +*************** +*** 118,123 **** +--- 118,127 ---- + struct mbuf *ip6e_dest2; + }; + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif ++ + static int ip6_pcbopts(struct ip6_pktopts **, struct mbuf *, + struct socket *); + static int ip6_setmoptions(int, struct ip6_moptions **, struct mbuf *); +*************** +*** 834,839 **** +--- 838,862 ---- + goto done; + ip6 = mtod(m, struct ip6_hdr *); + #endif ++ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * looks like most checking has been done now...do a filter check ++ */ ++ if (fr_checkp != NULL) { ++ struct mbuf *m1 = m; ++ if ((*fr_checkp)((struct ip *)ip6, sizeof(*ip6), ifp, 1, &m1)) { ++ error = EHOSTUNREACH; ++ goto done; ++ } ++ m = m1; ++ if (m1 == 0) { /* in case of 'fastroute' */ ++ error = 0; ++ goto done; ++ } ++ ip6 = mtod(m, struct ip6_hdr *); ++ } ++ #endif + + /* + * Send the packet to the outgoing interface. +diff -d -c -r /tmp/sys/sys/conf.h sys/sys/conf.h +*** /tmp/sys/sys/conf.h Wed Mar 13 17:27:13 2002 +--- sys/sys/conf.h Thu Apr 25 04:26:03 2002 +*************** +*** 351,356 **** +--- 351,363 ---- + (dev_type_ioctl((*))) enodev, (dev_type_stop((*))) nullop, \ + 0, (dev_type_select((*))) enodev, (dev_type_mmap((*))) enodev } + ++ /* open, close, read, ioctl */ ++ #define cdev_gen_ipf(c, n) { \ ++ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ ++ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ ++ (dev_type_stop((*))) enodev, 0, (dev_type_select((*))) enodev, \ ++ (dev_type_mmap((*))) enodev } ++ + /* open, close, read, write, ioctl, select */ + #define cdev_xfs_init(c, n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ +*************** +*** 543,548 **** +--- 550,556 ---- + + cdev_decl(bpf); + ++ cdev_decl(ipl); + cdev_decl(pf); + + cdev_decl(tun); diff --git a/OpenBSD-3/3.2-MAKEDEV-diffs b/OpenBSD-3/3.2-MAKEDEV-diffs new file mode 100644 index 0000000000000..c9804e5297768 --- /dev/null +++ b/OpenBSD-3/3.2-MAKEDEV-diffs @@ -0,0 +1,818 @@ +diff -cr etc/MAKEDEV.mi.orig etc/MAKEDEV.mi +*** etc/MAKEDEV.mi.orig Fri Aug 30 09:43:16 2002 +--- etc/MAKEDEV.mi Wed Nov 13 12:02:53 2002 +*************** +*** 153,158 **** +--- 153,162 ---- + target(all, pctr0)dnl + target(all, altq)dnl + target(all, pf)dnl ++ target(all, ipl)dnl ++ target(all, ipnat)dnl ++ target(all, ipstate)dnl ++ target(all, ipauth)dnl + twrget(all, cry, crypto)dnl + target(all, apm)dnl + twrget(all, tth, ttyh, 0, 1)dnl +*************** +*** 1037,1042 **** +--- 1041,1054 ---- + _mkdev(cry, crypto, {-M crypto c major_cry_c-} 0)dnl + __devitem(pf, pf*, Packet Filter)dnl + _mkdev(pf, {-pf*-}, {-M pf c major_pf_c 0 600-})dnl ++ __devitem(ipl, ipl*, Packet Filter log)dnl ++ _mkdev(ipl, {-ipl*-}, {-M ipl c major_ipl_c 0 600-})dnl ++ __devitem(ipnat, ipnat*, Packet Filter NAT)dnl ++ _mkdev(ipnat, {-ipnat*-}, {-M ipnat c major_ipnat_c 1 600-})dnl ++ __devitem(ipstate, ipstate*, Packet Filter state)dnl ++ _mkdev(ipstate, {-ipstate*-}, {-M ipstate c major_ipstate_c 2 600-})dnl ++ __devitem(ipauth, ipauth*, Packet Filter auth)dnl ++ _mkdev(ipauth, {-ipauth*-}, {-M ipauth c major_ipauth_c 3 600-})dnl + __devitem(bpf, bpf*, Berkeley Packet Filter)dnl + _mkdev(bpf, {-bpf*-}, {-M bpf$U c major_bpf_c $U 600-}, 600)dnl + _mkdev(tun, {-tun*-}, {-M tun$U c major_tun_c $U 600-}, 600)dnl +diff -cr etc/etc.alpha/MAKEDEV.orig etc/etc.alpha/MAKEDEV +*** etc/etc.alpha/MAKEDEV.orig Sun Aug 25 03:25:28 2002 +--- etc/etc.alpha/MAKEDEV Wed Nov 13 12:04:34 2002 +*************** +*** 71,76 **** +--- 71,77 ---- + # utty* Serial ports + # Special purpose devices: + # ch* SCSI media changer ++ # ipl IP Filter + # pf* Packet Filter + # bpf* Berkeley Packet Filter + # altq/ ALTQ control interface +*************** +*** 339,344 **** +--- 340,352 ---- + M bpf$U c 11 $U 600 + ;; + ++ ipl) ++ M ipl c 44 0 600 ++ M ipnat c 44 1 600 ++ M ipstate c 44 2 600 ++ M ipauth c 44 2 600 ++ ;; ++ + pf*) + M pf c 35 0 600 + ;; +*************** +*** 503,509 **** + R tty00 tty01 tty02 tty03 ttyc0 ttyc1 ttyc2 ttyc3 ttyc4 ttyc5 + R ttyc6 ttyc7 ttyB0 ttyB1 ttyB2 ttyB3 ttyB4 ttyB5 pf altq + R systrace wd0 wd1 wd2 wd3 raid0 raid1 raid2 raid3 std st0 st1 +! R fd + ;; + + wd*|sd*|raid*|ccd*) +--- 511,517 ---- + R tty00 tty01 tty02 tty03 ttyc0 ttyc1 ttyc2 ttyc3 ttyc4 ttyc5 + R ttyc6 ttyc7 ttyB0 ttyB1 ttyB2 ttyB3 ttyB4 ttyB5 pf altq + R systrace wd0 wd1 wd2 wd3 raid0 raid1 raid2 raid3 std st0 st1 +! R fd ipl + ;; + + wd*|sd*|raid*|ccd*) +diff -cr etc/etc.alpha/MAKEDEV.md.orig etc/etc.alpha/MAKEDEV.md +*** etc/etc.alpha/MAKEDEV.md.orig Sun Aug 25 03:21:44 2002 +--- etc/etc.alpha/MAKEDEV.md Wed Nov 13 12:02:53 2002 +*************** +*** 66,71 **** +--- 66,75 ---- + _TITLE(spec) + _DEV(ch, 14) + _DEV(pf, 35) ++ _DEV(ipl, 44) ++ _DEV(ipnat, 44) ++ _DEV(ipstate, 44) ++ _DEV(ipauth, 44) + _DEV(bpf, 11) + _DEV(altq, 53) + _DEV(iop, 54) +diff -cr etc/etc.amiga/MAKEDEV.orig etc/etc.amiga/MAKEDEV +*** etc/etc.amiga/MAKEDEV.orig Tue Jun 18 10:56:04 2002 +--- etc/etc.amiga/MAKEDEV Wed Nov 13 12:05:12 2002 +*************** +*** 70,75 **** +--- 70,76 ---- + # lkm loadable kernel modules interface + # bpf* Berkeley Packet Filter + # tun* network tunnel driver ++ # ipl IP Filter + # pf* Packet Filter + # ss* SCSI scanners + # uk* SCSI Unknown device +*************** +*** 351,356 **** +--- 352,364 ---- + MKlist="$MKlist;umask 77;ln -s ss$U scan$U" + ;; + ++ ipl) ++ M ipl c 38 0 600 ++ M ipnat c 38 1 600 ++ M ipstate c 38 2 600 ++ M ipauth c 38 3 600 ++ ;; ++ + pf*) + M pf c 34 0 600 + ;; +*************** +*** 453,458 **** +--- 461,467 ---- + R ttye6 tty00 tty01 tty02 tty03 ttyB0 ttyB1 ttyB2 ttyB3 ttyB4 + R ttyA0 ttyA1 pf altq systrace fd0 fd1 fd2 fd3 wd0 wd1 wd2 wd3 + R std st0 st1 fd ++ R ipl + ;; + + wd*|sd*|ccd*) +diff -cr etc/etc.amiga/MAKEDEV.md.orig etc/etc.amiga/MAKEDEV.md +*** etc/etc.amiga/MAKEDEV.md.orig Sun Jun 9 16:15:14 2002 +--- etc/etc.amiga/MAKEDEV.md Wed Nov 13 12:02:53 2002 +*************** +*** 65,70 **** +--- 65,74 ---- + _DEV(bpf, 22) + _DEV(tun, 23) + _DEV(pf, 34) ++ _DEV(ipl, 38) ++ _DEV(ipnat, 38) ++ _DEV(ipstate, 38) ++ _DEV(ipauth, 38) + _DEV(ss, 25) + _DEV(uk, 36) + _DEV(rnd, 35) +diff -cr etc/etc.hp300/MAKEDEV.orig etc/etc.hp300/MAKEDEV +*** etc/etc.hp300/MAKEDEV.orig Sat Sep 7 07:48:48 2002 +--- etc/etc.hp300/MAKEDEV Wed Nov 13 12:06:09 2002 +*************** +*** 61,66 **** +--- 61,67 ---- + # ite* terminal emulator interface to HP300 graphics devices + # hil HP300 HIL input devices + # bpf* Berkeley Packet Filter ++ # ipl IP Filter + # tun* network tunnel driver + # pf* Packet Filter + # lkm loadable kernel modules interface +*************** +*** 325,330 **** +--- 326,338 ---- + M lkm c 24 0 640 kmem + ;; + ++ ipl) ++ M ipl c 37 0 600 ++ M ipnat c 37 1 600 ++ M ipstate c 37 2 600 ++ M ipauth c 37 3 600 ++ ;; ++ + pf*) + M pf c 33 0 600 + ;; +*************** +*** 404,409 **** +--- 412,418 ---- + R sd2 sd3 sd4 rd0 tun0 tun1 tun2 tun3 bpf0 bpf1 bpf2 bpf3 bpf4 + R bpf5 bpf6 bpf7 bpf8 bpf9 pty0 pty1 pty2 xfs0 local ppi0 + R apci0 random lkm pf altq systrace std fd ++ R ipl + ;; + + sd*|hd*|ccd*) +diff -cr etc/etc.hp300/MAKEDEV.md.orig etc/etc.hp300/MAKEDEV.md +*** etc/etc.hp300/MAKEDEV.md.orig Sat Sep 7 07:48:34 2002 +--- etc/etc.hp300/MAKEDEV.md Wed Nov 13 12:02:54 2002 +*************** +*** 57,62 **** +--- 57,66 ---- + _DEV(bpf, 22) + _DEV(tun, 23) + _DEV(pf, 33) ++ _DEV(ipl, 37) ++ _DEV(ipnat, 37) ++ _DEV(ipstate, 37) ++ _DEV(ipauth, 37) + _DEV(lkm, 24) + _DEV(rnd, 32) + _DEV(xfs, 51) +diff -cr etc/etc.hppa/MAKEDEV.orig etc/etc.hppa/MAKEDEV +*** etc/etc.hppa/MAKEDEV.orig Wed Oct 2 11:33:04 2002 +--- etc/etc.hppa/MAKEDEV Wed Nov 13 12:06:15 2002 +*************** +*** 55,60 **** +--- 55,61 ---- + # Special purpose devices: + # fd makes fd/* for the fdescfs + # bpf* Berkeley Packet Filter ++ # ipl IP Filter + # tun* network tunnel driver + # pf* Packet Filter + # lkm loadable kernel modules interface +*************** +*** 268,273 **** +--- 269,281 ---- + M lkm c 19 0 640 kmem + ;; + ++ ipl) ++ M ipl c 38 0 600 ++ M ipnat c 38 1 600 ++ M ipstate c 38 2 600 ++ M ipauth c 38 3 600 ++ ;; ++ + pf*) + M pf c 21 0 600 + ;; +*************** +*** 380,385 **** +--- 388,394 ---- + R xfs0 ss0 ss1 ch0 ses0 audio0 uk0 random lpa0 lpa1 lpa2 lpt0 + R lpt1 lpt2 lkm tty00 tty01 tty02 tty03 crypto pf altq + R systrace std st0 st1 fd ++ R ipl + ;; + + sd*|ccd*) +diff -cr etc/etc.hppa/MAKEDEV.md.orig etc/etc.hppa/MAKEDEV.md +*** etc/etc.hppa/MAKEDEV.md.orig Wed Oct 2 11:33:04 2002 +--- etc/etc.hppa/MAKEDEV.md Wed Nov 13 12:02:54 2002 +*************** +*** 51,56 **** +--- 51,60 ---- + _DEV(bpf, 17) + _DEV(tun, 18) + _DEV(pf, 21) ++ _DEV(ipl, 38) ++ _DEV(ipnat, 38) ++ _DEV(ipstate, 38) ++ _DEV(ipauth, 38) + _DEV(lkm, 19) + _DEV(altq, 33) + _DEV(rnd, 20) +diff -cr etc/etc.i386/MAKEDEV.orig etc/etc.i386/MAKEDEV +*** etc/etc.i386/MAKEDEV.orig Tue Jun 18 10:56:04 2002 +--- etc/etc.i386/MAKEDEV Wed Nov 13 12:06:31 2002 +*************** +*** 79,84 **** +--- 79,85 ---- + # Special purpose devices: + # fd makes fd/* for the fdescfs + # crypto hardware crypto access driver ++ # ipl IP Filter + # pf* Packet Filter + # bpf* Berkeley Packet Filter + # speaker pc speaker +*************** +*** 382,387 **** +--- 383,395 ---- + M bpf$U c 23 $U 600 + ;; + ++ ipl) ++ M ipl c 81 0 600 ++ M ipnat c 81 1 600 ++ M ipstate c 81 2 600 ++ M ipauth c 81 3 600 ++ ;; ++ + pf*) + M pf c 73 0 600 + ;; +*************** +*** 578,583 **** +--- 586,592 ---- + R tty03 ttyc0 ttyc1 ttyc2 ttyc3 ttyc4 ttyc5 ttyc6 ttyc7 apm + R crypto pf altq pctr systrace wd0 wd1 wd2 wd3 raid0 raid1 + R raid2 raid3 std st0 st1 fd mcd0 ++ R ipl + ;; + + wd*|sd*|raid*|ccd*) +diff -cr etc/etc.i386/MAKEDEV.md.orig etc/etc.i386/MAKEDEV.md +*** etc/etc.i386/MAKEDEV.md.orig Tue Jun 18 10:33:00 2002 +--- etc/etc.i386/MAKEDEV.md Wed Nov 13 12:02:54 2002 +*************** +*** 74,79 **** +--- 74,83 ---- + _DEV(fdesc, 22) + _DEV(cry, 70) + _DEV(pf, 73) ++ _DEV(ipl, 81) ++ _DEV(ipnat, 81) ++ _DEV(ipstate, 81) ++ _DEV(ipauth, 81) + _DEV(bpf, 23) + _DEV(speak, 27) + _DEV(lkm, 28) +diff -cr etc/etc.mac68k/MAKEDEV.orig etc/etc.mac68k/MAKEDEV +*** etc/etc.mac68k/MAKEDEV.orig Tue Jun 18 10:56:04 2002 +--- etc/etc.mac68k/MAKEDEV Wed Nov 13 12:06:50 2002 +*************** +*** 56,61 **** +--- 56,62 ---- + # CyberVision 64 (grf5) + # Special purpose devices: + # bpf* Berkeley Packet Filter ++ # ipl IP Filter + # tun* network tunnel driver + # pf* Packet Filter + # altq/ ALTQ control interface +*************** +*** 286,291 **** +--- 287,299 ---- + done + ;; + ++ ipl) ++ M ipl c 38 0 600 ++ M ipnat c 38 1 600 ++ M ipstate c 38 2 600 ++ M ipauth c 38 3 600 ++ ;; ++ + pf*) + M pf c 35 0 600 + ;; +*************** +*** 364,369 **** +--- 372,378 ---- + R xfs0 ss0 ss1 ch0 vnd0 vnd1 vnd2 vnd3 sd0 sd1 sd2 sd3 sd4 + R local grf0 grf1 grf2 grf3 adb asc0 uk0 random lkm ttye0 + R tty00 tty01 pf altq systrace std st0 st1 fd ++ R ipl + ;; + + sd*|ccd*) +diff -cr etc/etc.mac68k/MAKEDEV.md.orig etc/etc.mac68k/MAKEDEV.md +*** etc/etc.mac68k/MAKEDEV.md.orig Fri May 17 07:11:20 2002 +--- etc/etc.mac68k/MAKEDEV.md Wed Nov 13 12:02:54 2002 +*************** +*** 50,55 **** +--- 50,59 ---- + _DEV(bpf, 22) + _DEV(tun, 24) + _DEV(pf, 35) ++ _DEV(ipl, 38) ++ _DEV(ipnat, 38) ++ _DEV(ipstate, 38) ++ _DEV(ipauth, 38) + _DEV(altq, 52) + _DEV(lkm, 25) + _DEV(rnd, 32) +diff -cr etc/etc.macppc/MAKEDEV.orig etc/etc.macppc/MAKEDEV +*** etc/etc.macppc/MAKEDEV.orig Tue Jun 18 10:56:04 2002 +--- etc/etc.macppc/MAKEDEV Wed Nov 13 12:07:02 2002 +*************** +*** 72,77 **** +--- 72,78 ---- + # audio* audio device + # apm power management device + # bpf* Berkeley Packet Filter ++ # ipl IP Filter + # tun* network tunnel driver + # lkm loadable kernel modules interface + # *random inkernel random data source +*************** +*** 241,246 **** +--- 242,254 ---- + M crypto c 47 0 + ;; + ++ ipl) ++ M ipl c 45 0 600 ++ M ipnat c 45 1 600 ++ M ipstate c 45 2 600 ++ M ipauth c 45 3 600 ++ ;; ++ + pf*) + M pf c 39 0 600 + ;; +*************** +*** 449,454 **** +--- 457,463 ---- + R local wscons pci iop0 iop1 usbs audio0 uk0 random lkm tty00 + R tty01 tty02 tty03 apm crypto pf altq systrace wd0 wd1 wd2 + R wd3 raid0 raid1 raid2 raid3 std st0 st1 fd ++ R ipl + ;; + + wd*|sd*|raid*|ccd*) +diff -cr etc/etc.macppc/MAKEDEV.md.orig etc/etc.macppc/MAKEDEV.md +*** etc/etc.macppc/MAKEDEV.md.orig Fri May 17 07:11:20 2002 +--- etc/etc.macppc/MAKEDEV.md Wed Nov 13 12:02:54 2002 +*************** +*** 75,80 **** +--- 75,84 ---- + _DEV(altq, 72) + _DEV(iop, 73) + _DEV(pf, 39) ++ _DEV(ipl, 45) ++ _DEV(ipnat, 45) ++ _DEV(ipstate, 45) ++ _DEV(ipauth, 45) + _DEV(cry, 47) + _DEV(usbs) + _DEV(pci, 71) +diff -cr etc/etc.mvme68k/MAKEDEV.orig etc/etc.mvme68k/MAKEDEV +*** etc/etc.mvme68k/MAKEDEV.orig Thu Aug 22 08:08:01 2002 +--- etc/etc.mvme68k/MAKEDEV Wed Nov 13 12:13:20 2002 +*************** +*** 60,65 **** +--- 60,66 ---- + # fd makes fd/* for the fdescfs + # bpf* Berkeley Packet Filter + # tun* network tunnel driver ++ # ipl IP Packet Filter + # pf* Packet Filter + # lkm loadable kernel modules interface + # *random inkernel random data source +*************** +*** 262,267 **** +--- 263,275 ---- + M bpf$U c 22 $U 600 + ;; + ++ ipl) ++ M ipl c 44 0 600 ++ M ipnat c 44 1 600 ++ M ipstate c 44 2 600 ++ M ipauth c 44 3 600 ++ ;; ++ + fd) + RMlist="mkdir -p fd;$RMlist" n=0 + while [ $n -lt 64 ];do M fd/$n c 21 $n;n=$(($n+1));done +*************** +*** 398,403 **** +--- 406,412 ---- + R tun3 bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 pty0 + R pty1 pty2 xfs0 ss0 ss1 vmel0 vmes0 flash0 nvram0 sram0 uk0 + R random lkm pf altq systrace std st0 st1 fd ++ R ipl + ;; + + sd*|ccd*) +diff -cr etc/etc.mvme68k/MAKEDEV.md.orig etc/etc.mvme68k/MAKEDEV.md +*** etc/etc.mvme68k/MAKEDEV.md.orig Thu Aug 22 08:07:43 2002 +--- etc/etc.mvme68k/MAKEDEV.md Wed Nov 13 12:02:54 2002 +*************** +*** 176,178 **** +--- 176,187 ---- + _std(1, 2, 43, 3, 6) + ;; + ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 44 0 ++ mknod ipnat c 44 1 ++ mknod ipstate c 44 2 ++ mknod ipauth c 44 3 ++ chown root.wheel ipl ipnat ipstate ipauth ++ ;; ++ +diff -cr etc/etc.mvme88k/MAKEDEV.orig etc/etc.mvme88k/MAKEDEV +*** etc/etc.mvme88k/MAKEDEV.orig Thu Aug 22 08:08:03 2002 +--- etc/etc.mvme88k/MAKEDEV Wed Nov 13 12:23:17 2002 +*************** +*** 55,60 **** +--- 55,61 ---- + # fd makes fd/* for the fdescfs + # bpf* Berkeley Packet Filter + # tun* network tunnel driver ++ # ipl IP Packet Filter + # pf* Packet Filter + # lkm loadable kernel modules interface + # *random inkernel random data source +*************** +*** 252,257 **** +--- 253,265 ---- + M bpf$U c 22 $U 600 + ;; + ++ ipl) ++ M ipl c 41 0 600 ++ M ipnat c 41 1 600 ++ M ipstate c 41 2 600 ++ M ipauth c 41 3 600 ++ ;; ++ + fd) + RMlist="mkdir -p fd;$RMlist" n=0 + while [ $n -lt 64 ];do M fd/$n c 21 $n;n=$(($n+1));done +*************** +*** 354,359 **** +--- 362,368 ---- + R tun2 tun3 bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 + R pty0 pty1 pty2 xfs0 vmel0 vmes0 nvram0 sram0 random lkm pf + R altq systrace std st0 st1 fd ++ R ipl + ;; + + sd*|ccd*) +diff -cr etc/etc.mvme88k/MAKEDEV.md.orig etc/etc.mvme88k/MAKEDEV.md +*** etc/etc.mvme88k/MAKEDEV.md.orig Thu Aug 22 08:07:44 2002 +--- etc/etc.mvme88k/MAKEDEV.md Wed Nov 13 12:02:54 2002 +*************** +*** 145,147 **** +--- 145,156 ---- + _std(1, 2, 43, 3, 6) + ;; + ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 41 0 ++ mknod ipnat c 41 1 ++ mknod ipstate c 41 2 ++ mknod ipauth c 41 3 ++ chown root.wheel ipl ipnat ipstate ipauth ++ ;; ++ +diff -cr etc/etc.mvmeppc/MAKEDEV.orig etc/etc.mvmeppc/MAKEDEV +*** etc/etc.mvmeppc/MAKEDEV.orig Sun Jun 9 15:58:39 2002 +--- etc/etc.mvmeppc/MAKEDEV Wed Nov 13 12:15:06 2002 +*************** +*** 73,78 **** +--- 73,79 ---- + # audio* audio + # ch* SCSI media changer + # bpf* Berkeley Packet Filter ++ # ipl IP Filter + # tun* network tunnel driver + # lkm loadable kernel modules interface + # *random inkernal random data source +*************** +*** 157,163 **** + sh $this ttyC0 ttyCcfg + sh $this tty00 tty01 tty02 tty03 pty0 pty1 + sh $this bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 +! sh $this pf tun0 tun1 tun2 tun3 + sh $this audio0 + sh $this random uk0 uk1 ss0 ss1 + sh $this wscons +--- 158,164 ---- + sh $this ttyC0 ttyCcfg + sh $this tty00 tty01 tty02 tty03 pty0 pty1 + sh $this bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 +! sh $this ipl pf tun0 tun1 tun2 tun3 + sh $this audio0 + sh $this random uk0 uk1 ss0 ss1 + sh $this wscons +*************** +*** 523,528 **** +--- 524,539 ---- + rm -f bpf${unit} + mknod bpf${unit} c 22 ${unit} + chown root.wheel bpf${unit} ++ ;; ++ ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 44 0 ++ mknod ipnat c 44 1 ++ mknod ipstate c 44 2 ++ mknod ipauth c 44 3 ++ chown root.wheel ipl ipnat ipstate ipauth ++ chmod 600 ipl ipnat ipstate ipauth + ;; + + pf) +diff -cr etc/etc.sparc/MAKEDEV.orig etc/etc.sparc/MAKEDEV +*** etc/etc.sparc/MAKEDEV.orig Fri Aug 30 09:43:41 2002 +--- etc/etc.sparc/MAKEDEV Wed Nov 13 12:15:27 2002 +*************** +*** 67,72 **** +--- 67,73 ---- + # audio* audio device + # openprom + # bpf* Berkeley Packet Filter ++ # ipl IP Filter + # pf* Packet Filter + # altq/ ALTQ control interface + # lkm loadable kernel modules interface +*************** +*** 297,302 **** +--- 298,310 ---- + done + ;; + ++ ipl) ++ M ipl c 60 0 600 ++ M ipnat c 60 1 600 ++ M ipstate c 60 2 600 ++ M ipauth c 60 3 600 ++ ;; ++ + pf*) + M pf c 59 0 600 + ;; +*************** +*** 483,489 **** + R fd1F fd1G fd1H fd0 fd0B fd0C fd0D fd0E fd0F fd0G fd0H xfs0 + R ss0 ss1 ch0 ses0 wscons audio0 uk0 random lkm pf altq + R systrace xd0 xd1 xd2 xd3 raid0 raid1 raid2 raid3 std st0 st1 +! R fd + ;; + + xd*|xy*|sd*|raid*|ccd*) +--- 491,497 ---- + R fd1F fd1G fd1H fd0 fd0B fd0C fd0D fd0E fd0F fd0G fd0H xfs0 + R ss0 ss1 ch0 ses0 wscons audio0 uk0 random lkm pf altq + R systrace xd0 xd1 xd2 xd3 raid0 raid1 raid2 raid3 std st0 st1 +! R ipl fd + ;; + + xd*|xy*|sd*|raid*|ccd*) +diff -cr etc/etc.sparc/MAKEDEV.md.orig etc/etc.sparc/MAKEDEV.md +*** etc/etc.sparc/MAKEDEV.md.orig Mon Aug 12 20:45:06 2002 +--- etc/etc.sparc/MAKEDEV.md Wed Nov 13 12:02:54 2002 +*************** +*** 94,99 **** +--- 94,103 ---- + _DEV(oppr) + _DEV(bpf, 105) + _DEV(pf, 59) ++ _DEV(ipl, 60) ++ _DEV(ipnat, 60) ++ _DEV(ipstate, 60) ++ _DEV(ipauth, 60) + _DEV(altq, 125) + _DEV(lkm, 112) + _DEV(tun, 111) +diff -cr etc/etc.sparc64/MAKEDEV.orig etc/etc.sparc64/MAKEDEV +*** etc/etc.sparc64/MAKEDEV.orig Fri Aug 30 09:43:41 2002 +--- etc/etc.sparc64/MAKEDEV Wed Nov 13 12:15:43 2002 +*************** +*** 84,89 **** +--- 84,90 ---- + # ss* SCSI scanners + # uk* SCSI Unknown device + # audio* audio device ++ # ipl IP Filter + # pf* Packet Filter + # altq/ ALTQ control interface + # bpf* Berkeley Packet Filter +*************** +*** 326,331 **** +--- 327,339 ---- + done + ;; + ++ ipl) ++ M ipl c 82 0 600 ++ M ipnat c 82 1 600 ++ M ipstate c 82 2 600 ++ M ipauth c 82 3 600 ++ ;; ++ + pf*) + M pf c 73 0 600 + ;; +*************** +*** 571,576 **** +--- 579,585 ---- + R lpt1 lpt2 lkm tty00 tty01 tty02 tty03 ttyh0 ttyh1 crypto pf + R altq systrace wd0 wd1 wd2 wd3 raid0 raid1 raid2 raid3 std + R st0 st1 fd ++ R ipl + ;; + + wd*|sd*|raid*|ccd*) +diff -cr etc/etc.sparc64/MAKEDEV.md.orig etc/etc.sparc64/MAKEDEV.md +*** etc/etc.sparc64/MAKEDEV.md.orig Thu Aug 1 02:47:50 2002 +--- etc/etc.sparc64/MAKEDEV.md Wed Nov 13 12:02:54 2002 +*************** +*** 82,87 **** +--- 82,91 ---- + _DEV(uk, 60) + _DEV(au, 69) + _DEV(pf, 73) ++ _DEV(ipl, 82) ++ _DEV(ipnat, 82) ++ _DEV(ipstate, 82) ++ _DEV(ipauth, 82) + _DEV(altq, 74) + _DEV(bpf, 105) + _DEV(tun, 111) +diff -cr etc/etc.sun3/MAKEDEV.orig etc/etc.sun3/MAKEDEV +*** etc/etc.sun3/MAKEDEV.orig Tue Jun 18 10:56:04 2002 +--- etc/etc.sun3/MAKEDEV Wed Nov 13 12:15:55 2002 +*************** +*** 57,62 **** +--- 57,63 ---- + # cgtwo* + # cgfour* + # bpf* Berkeley Packet Filter ++ # ipl IP Filter + # pf* Packet Filter + # tun* network tunnel driver + # rd* "rd" pseudo-disks +*************** +*** 267,272 **** +--- 268,280 ---- + M tun$U c 24 $U 600 + ;; + ++ ipl) ++ M ipl c 87 0 600 ++ M ipnat c 87 1 600 ++ M ipstate c 87 2 600 ++ M ipauth c 87 3 600 ++ ;; ++ + pf*) + M pf c 75 0 600 + ;; +*************** +*** 346,351 **** +--- 354,360 ---- + R bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 pty0 pty1 pty2 xfs0 + R ss0 ss1 local cgfour0 cgtwo0 bwtwo0 uk0 random ttya ttyb + R ttyc ttyd pf altq systrace xd0 xd1 xd2 xd3 std st0 st1 fd ++ R ipl + ;; + + xd*|xy*|sd*|ccd*) +diff -cr etc/etc.sun3/MAKEDEV.md.orig etc/etc.sun3/MAKEDEV.md +*** etc/etc.sun3/MAKEDEV.md.orig Sun Jun 9 16:15:15 2002 +--- etc/etc.sun3/MAKEDEV.md Wed Nov 13 12:02:55 2002 +*************** +*** 52,57 **** +--- 52,61 ---- + _DEV(cfr, 39) + _DEV(bpf, 36) + _DEV(pf, 75) ++ _DEV(ipl, 87) ++ _DEV(ipnat, 87) ++ _DEV(ipstate, 87) ++ _DEV(ipauth, 87) + _DEV(tun, 24) + _DEV(rd, 52, 13) + _DEV(rnd, 72) +diff -cr etc/etc.vax/MAKEDEV.orig etc/etc.vax/MAKEDEV +*** etc/etc.vax/MAKEDEV.orig Mon Jun 24 20:43:31 2002 +--- etc/etc.vax/MAKEDEV Wed Nov 13 12:16:11 2002 +*************** +*** 56,61 **** +--- 56,62 ---- + # qv* qvss (microvax) display + # lkm loadable kernel modules + # bpf* berkeley packet filter ++ # ipl IP Filter + # tun* network tunnel device + # ss* SCSI scanner + # uk* SCSI unknown +*************** +*** 79,84 **** +--- 80,86 ---- + sh $0 dz0 dl0 dhu0 rx0 rx1 raid0 raid1 raid2 raid3 + sh $0 ttyg0 ttyg1 ttyg2 ttyg3 + sh $0 crl std-extra systrace ++ sh $0 ipl + ;; + + floppy) +*************** +*** 616,621 **** +--- 618,633 ---- + mknod bpf$unit c 56 $unit + chmod 600 bpf$unit + chown root.wheel bpf$unit ++ ;; ++ ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 47 0 ++ mknod ipnat c 47 1 ++ mknod ipstate c 47 2 ++ mknod ipauth c 47 3 ++ chown root.wheel ipl ipnat ipstate ipauth ++ chmod 600 ipl ipnat ipstate ipauth + ;; + + qd*) +diff -cr etc/etc.vax/MAKEDEV.md.orig etc/etc.vax/MAKEDEV.md +*** etc/etc.vax/MAKEDEV.md.orig Fri May 17 07:11:21 2002 +--- etc/etc.vax/MAKEDEV.md Wed Nov 13 12:02:55 2002 +*************** +*** 70,75 **** +--- 70,79 ---- + _DEV(oppr) + _DEV(bpf, 56) + _DEV(pf, 42) ++ _DEV(ipl, 47) ++ _DEV(ipnat, 47) ++ _DEV(ipstate, 47) ++ _DEV(ipauth, 47) + _DEV(altq, 75) + _DEV(lkm, 28) + _DEV(tun, 57) diff --git a/OpenBSD-3/3.2-rc-diffs b/OpenBSD-3/3.2-rc-diffs new file mode 100644 index 0000000000000..721ba4f31d543 --- /dev/null +++ b/OpenBSD-3/3.2-rc-diffs @@ -0,0 +1,91 @@ +diff -d -c -r tmp/etc/netstart etc/netstart +*** tmp/etc/netstart Fri Oct 4 03:33:53 2002 +--- etc/netstart Sun Nov 3 14:36:17 2002 +*************** +*** 181,186 **** +--- 181,196 ---- + domainname `cat /etc/defaultdomain` + fi + ++ # Configure the IP filter before configuring network interfaces ++ if [ X"${ipfilter}" = X"YES" -a -f "${ipfilter_rules}" ]; then ++ echo 'configuring IP filter' ++ ipf -Fa -f ${ipfilter_rules} ++ ipfresync="ipf -y" ++ else ++ ipfilter=NO ++ ipfresync=NO ++ fi ++ + # Set the address for the loopback interface. + # It will also initialize IPv6 address for lo0 (::1 and others). + ifconfig lo0 inet localhost +*************** +*** 336,338 **** +--- 346,361 ---- + + bridgestart $if + done ++ ++ # Configure NAT after configuring network interfaces ++ if [ "${ipnat}" = "YES" -a "${ipfilter}" = "YES" -a -f "${ipnat_rules}" ]; then ++ echo 'configuring NAT' ++ ipnat -CF -f ${ipnat_rules} ++ else ++ ipnat=NO ++ fi ++ ++ # Interfaces have come up so we should do an ipf -y if we're using IP filter. ++ if [ "${ipfresync}" != "NO" ]; then ++ ${ipfresync} ++ fi +diff -d -c -r tmp/etc/rc etc/rc +*** tmp/etc/rc Fri Oct 4 03:33:53 2002 +--- etc/rc Sun Nov 3 14:38:35 2002 +*************** +*** 208,213 **** +--- 208,217 ---- + echo 'starting named'; named $named_flags + fi + ++ if [ X"${ipfilter}" = X"YES" -a X"${ipmon_flags}" != X"NO" ]; then ++ echo 'starting ipmon'; ipmon ${ipmon_flags} ++ fi ++ + # $isakmpd_flags is imported from /etc/rc.conf; + # If $isakmpd_flags == NO or /etc/isakmpd/isakmpd.policy doesn't exist, then + # isakmpd isn't run. +diff -d -c -r tmp/etc/rc.conf etc/rc.conf +*** tmp/etc/rc.conf Fri Oct 4 03:33:53 2002 +--- etc/rc.conf Sun Nov 3 14:36:17 2002 +*************** +*** 54,60 **** + lockd=NO + gated=NO + amd=NO +! pf=NO # Packet filter / NAT + portmap=NO # Note: inetd(8) rpc services need portmap too + inetd=YES # almost always needed + check_quotas=YES # NO may be desirable in some YP environments +--- 54,62 ---- + lockd=NO + gated=NO + amd=NO +! ipfilter=NO # To enable ipfilter, set to YES +! ipnat=NO # for "YES", ipfilter must also be "YES" +! pf=NO # Enable pf(4) Packet filter / NAT + portmap=NO # Note: inetd(8) rpc services need portmap too + inetd=YES # almost always needed + check_quotas=YES # NO may be desirable in some YP environments +*************** +*** 78,83 **** +--- 80,88 ---- + nfsd_flags="-tun 4" # Crank the 4 for a busy NFS fileserver + amd_dir=/tmp_mnt # AMD's mount directory + amd_master=/etc/amd/master # AMD 'master' map ++ ipfilter_rules=/etc/ipf.rules # Rules for IP packet filtering with IP Filter ++ ipnat_rules=/etc/ipnat.rules # Rules for Network Address Translation ++ ipmon_flags=-Ds # To disable logging, use ipmon_flags=NO + syslogd_flags= # add more flags, ie. "-u -a /chroot/dev/log" + named_user=named # Named should not run as root unless necessary + named_chroot=/var/named # Where to chroot named if not empty diff --git a/OpenBSD-3/3.2-sys-diffs b/OpenBSD-3/3.2-sys-diffs new file mode 100644 index 0000000000000..705bfcf2cab98 --- /dev/null +++ b/OpenBSD-3/3.2-sys-diffs @@ -0,0 +1,1056 @@ +diff -d -c -r /tmp/sys/arch/alpha/alpha/conf.c sys/arch/alpha/alpha/conf.c +*** /tmp/sys/arch/alpha/alpha/conf.c Thu Jul 11 00:08:47 2002 +--- sys/arch/alpha/alpha/conf.c Sat Nov 2 12:10:33 2002 +*************** +*** 107,112 **** +--- 107,117 ---- + #include "lpt.h" + cdev_decl(lpt); + cdev_decl(prom); /* XXX XXX XXX */ ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif + cdev_decl(wd); + cdev_decl(fd); + #include "cy.h" +*************** +*** 179,185 **** + cdev_midi_init(NMIDI,midi), /* 41: MIDI I/O */ + cdev_midi_init(NSEQUENCER,sequencer), /* 42: sequencer I/O */ + cdev_disk_init(NRAID,raid), /* 43: RAIDframe disk driver */ +! cdev_notdef(), /* 44 */ + cdev_usb_init(NUSB,usb), /* 45: USB controller */ + cdev_usbdev_init(NUHID,uhid), /* 46: USB generic HID */ + cdev_ulpt_init(NULPT,ulpt), /* 47: USB printer */ +--- 184,190 ---- + cdev_midi_init(NMIDI,midi), /* 41: MIDI I/O */ + cdev_midi_init(NSEQUENCER,sequencer), /* 42: sequencer I/O */ + cdev_disk_init(NRAID,raid), /* 43: RAIDframe disk driver */ +! cdev_gen_ipf(NIPF,ipl), /* 44: IP filter log */ + cdev_usb_init(NUSB,usb), /* 45: USB controller */ + cdev_usbdev_init(NUHID,uhid), /* 46: USB generic HID */ + cdev_ulpt_init(NULPT,ulpt), /* 47: USB printer */ +diff -d -c -r /tmp/sys/arch/amiga/amiga/conf.c sys/arch/amiga/amiga/conf.c +*** /tmp/sys/arch/amiga/amiga/conf.c Tue Jun 11 05:25:30 2002 +--- sys/arch/amiga/amiga/conf.c Sat Nov 2 12:10:34 2002 +*************** +*** 159,165 **** + cdev_random_init(1,random), /* 35: random data source */ + cdev_uk_init(NUK,uk), /* 36: unknown SCSI */ + cdev_disk_init(NWD,wd), /* 37: ST506/ESDI/IDE disk */ +! cdev_notdef(), /* 38 */ + cdev_audio_init(NAUDIO,audio), /* 39: cc audio interface */ + cdev_ch_init(NCH,ch), /* 40: SCSI autochanger */ + cdev_disk_init(NRD,rd), /* 41: RAM disk */ +--- 159,165 ---- + cdev_random_init(1,random), /* 35: random data source */ + cdev_uk_init(NUK,uk), /* 36: unknown SCSI */ + cdev_disk_init(NWD,wd), /* 37: ST506/ESDI/IDE disk */ +! cdev_gen_ipf(NIPF,ipl), /* 38: IP filter log */ + cdev_audio_init(NAUDIO,audio), /* 39: cc audio interface */ + cdev_ch_init(NCH,ch), /* 40: SCSI autochanger */ + cdev_disk_init(NRD,rd), /* 41: RAM disk */ +diff -d -c -r /tmp/sys/arch/hp300/hp300/conf.c sys/arch/hp300/hp300/conf.c +*** /tmp/sys/arch/hp300/hp300/conf.c Thu Jul 11 00:08:47 2002 +--- sys/arch/hp300/hp300/conf.c Sat Nov 2 12:10:34 2002 +*************** +*** 126,131 **** +--- 126,137 ---- + cdev_decl(xfs_dev); + #endif + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 171,177 **** + cdev_disk_init(NRD,rd), /* 34: RAM disk */ + cdev_tty_init(NAPCI,apci), /* 35: Apollo APCI UARTs */ + cdev_ksyms_init(NKSYMS,ksyms), /* 36: Kernel symbols device */ +! cdev_notdef(), /* 37 */ + cdev_notdef(), /* 38 */ + cdev_notdef(), /* 39 */ + cdev_notdef(), /* 40 */ +--- 177,183 ---- + cdev_disk_init(NRD,rd), /* 34: RAM disk */ + cdev_tty_init(NAPCI,apci), /* 35: Apollo APCI UARTs */ + cdev_ksyms_init(NKSYMS,ksyms), /* 36: Kernel symbols device */ +! cdev_pf_init(NIPF,ipl), /* 37: packet filter */ + cdev_notdef(), /* 38 */ + cdev_notdef(), /* 39 */ + cdev_notdef(), /* 40 */ +diff -d -c -r /tmp/sys/arch/hppa/hppa/conf.c sys/arch/hppa/hppa/conf.c +*** /tmp/sys/arch/hppa/hppa/conf.c Wed Oct 2 03:42:11 2002 +--- sys/arch/hppa/hppa/conf.c Sun Nov 3 08:07:21 2002 +*************** +*** 107,112 **** +--- 107,118 ---- + #include "com.h" + cdev_decl(com); + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 158,163 **** +--- 164,170 ---- + cdev_audio_init(NAUDIO,audio), /* 35: /dev/audio */ + cdev_crypto_init(NCRYPTO,crypto), /* 36: /dev/crypto */ + cdev_ses_init(NSES,ses), /* 37: SCSI SES/SAF-TE */ ++ cdev_gen_ipf(NIPF,ipl), /* 38: ip filtering */ + cdev_lkm_dummy(), + cdev_lkm_dummy(), + cdev_lkm_dummy(), +diff -d -c -r /tmp/sys/arch/i386/i386/conf.c sys/arch/i386/i386/conf.c +*** /tmp/sys/arch/i386/i386/conf.c Thu Jul 11 00:21:30 2002 +--- sys/arch/i386/i386/conf.c Sun Nov 3 13:49:00 2002 +*************** +*** 196,201 **** +--- 196,207 ---- + #include "radio.h" + #include "gpr.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + /* XXX -- this needs to be supported by config(8)! */ + #if (NCOM > 0) && (NPCCOM > 0) + #error com and pccom are mutually exclusive. Sorry. +*************** +*** 321,327 **** + cdev_usbdev_init(NUSCANNER,uscanner), /* 77: USB scanners */ + cdev_systrace_init(NSYSTRACE,systrace), /* 78: system call tracing */ + cdev_oci_init(NBIO,bio), /* 79: ioctl tunnel */ +! cdev_ch_init(NGPR,gpr) /* 80: GPR400 SmartCard reader */ + }; + int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]); + +--- 327,335 ---- + cdev_usbdev_init(NUSCANNER,uscanner), /* 77: USB scanners */ + cdev_systrace_init(NSYSTRACE,systrace), /* 78: system call tracing */ + cdev_oci_init(NBIO,bio), /* 79: ioctl tunnel */ +! cdev_ch_init(NGPR,gpr), /* 80: GPR400 SmartCard reader */ +! cdev_gen_ipf(NIPF,ipl) /* 81: ip filtering */ +! + }; + int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]); + +diff -d -c -r /tmp/sys/arch/mac68k/mac68k/conf.c sys/arch/mac68k/mac68k/conf.c +*** /tmp/sys/arch/mac68k/mac68k/conf.c Thu Jul 11 00:08:47 2002 +--- sys/arch/mac68k/mac68k/conf.c Sat Nov 2 12:10:35 2002 +*************** +*** 108,113 **** +--- 108,119 ---- + cdev_decl(xfs_dev); + #endif + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 154,160 **** + cdev_pf_init(NPF,pf), /* 35: packet filter */ + cdev_audio_init(NASC,asc), /* 36: ASC audio device */ + cdev_ksyms_init(NKSYMS,ksyms), /* 37: Kernel symbols device */ +! cdev_notdef(), /* 38 */ + cdev_notdef(), /* 39 */ + cdev_notdef(), /* 40 */ + cdev_notdef(), /* 41 */ +--- 160,166 ---- + cdev_pf_init(NPF,pf), /* 35: packet filter */ + cdev_audio_init(NASC,asc), /* 36: ASC audio device */ + cdev_ksyms_init(NKSYMS,ksyms), /* 37: Kernel symbols device */ +! cdev_gen_ipf(NIPF,ipl), /* 38: IP filter log */ + cdev_notdef(), /* 39 */ + cdev_notdef(), /* 40 */ + cdev_notdef(), /* 41 */ +diff -d -c -r /tmp/sys/arch/macppc/macppc/conf.c sys/arch/macppc/macppc/conf.c +*** /tmp/sys/arch/macppc/macppc/conf.c Sun Sep 15 11:01:58 2002 +--- sys/arch/macppc/macppc/conf.c Sat Nov 2 12:10:35 2002 +*************** +*** 105,110 **** +--- 105,116 ---- + + #include "tun.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #ifdef XFS + #include <xfs/nxfs.h> + cdev_decl(xfs_dev); +*************** +*** 190,196 **** + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ + cdev_audio_init(NAUDIO,audio), /* 44: generic audio I/O */ +! cdev_notdef(), /* 45 */ + cdev_notdef(), /* 46 */ + cdev_crypto_init(NCRYPTO,crypto), /* 47: /dev/crypto */ + cdev_notdef(), /* 48 */ +--- 196,202 ---- + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ + cdev_audio_init(NAUDIO,audio), /* 44: generic audio I/O */ +! cdev_gen_ipf(NIPF,ipl), /* 45: IP filter */ + cdev_notdef(), /* 46 */ + cdev_crypto_init(NCRYPTO,crypto), /* 47: /dev/crypto */ + cdev_notdef(), /* 48 */ +diff -d -c -r /tmp/sys/arch/mvme68k/mvme68k/conf.c sys/arch/mvme68k/mvme68k/conf.c +*** /tmp/sys/arch/mvme68k/mvme68k/conf.c Thu Jul 11 00:08:47 2002 +--- sys/arch/mvme68k/mvme68k/conf.c Sat Nov 2 12:10:35 2002 +*************** +*** 158,163 **** +--- 158,169 ---- + #include "bpfilter.h" + #include "tun.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 214,220 **** + cdev_uk_init(NUK,uk), /* 41: unknown SCSI */ + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ +! cdev_lkm_dummy(), /* 44 */ + cdev_lkm_dummy(), /* 45 */ + cdev_lkm_dummy(), /* 46 */ + cdev_lkm_dummy(), /* 47 */ +--- 220,226 ---- + cdev_uk_init(NUK,uk), /* 41: unknown SCSI */ + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ +! cdev_gen_ipf(NIPF,ipl), /* 44: IP filter */ + cdev_lkm_dummy(), /* 45 */ + cdev_lkm_dummy(), /* 46 */ + cdev_lkm_dummy(), /* 47 */ +diff -d -c -r /tmp/sys/arch/mvme88k/mvme88k/conf.c sys/arch/mvme88k/mvme88k/conf.c +*** /tmp/sys/arch/mvme88k/mvme88k/conf.c Thu Jul 11 00:08:47 2002 +--- sys/arch/mvme88k/mvme88k/conf.c Sat Nov 2 12:10:35 2002 +*************** +*** 101,106 **** +--- 101,112 ---- + cdev_decl(lptwo); + #endif /* notyet */ + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 189,195 **** + cdev_lkm_dummy(), /* 38 */ + cdev_pf_init(NPF,pf), /* 39: packet filter */ + cdev_random_init(1,random), /* 40: random data source */ +! cdev_notdef(), /* 41 */ + cdev_notdef(), /* 42 */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ + cdev_notdef(), /* 44 */ +--- 195,201 ---- + cdev_lkm_dummy(), /* 38 */ + cdev_pf_init(NPF,pf), /* 39: packet filter */ + cdev_random_init(1,random), /* 40: random data source */ +! cdev_gen_ipf(NIPF,ipl), /* 41: IP filter */ + cdev_notdef(), /* 42 */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ + cdev_notdef(), /* 44 */ +diff -d -c -r /tmp/sys/arch/mvmeppc/mvmeppc/conf.c sys/arch/mvmeppc/mvmeppc/conf.c +*** /tmp/sys/arch/mvmeppc/mvmeppc/conf.c Thu Jul 11 00:08:47 2002 +--- sys/arch/mvmeppc/mvmeppc/conf.c Sat Nov 2 12:10:36 2002 +*************** +*** 114,119 **** +--- 114,125 ---- + + #include "ksyms.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 169,175 **** + cdev_uk_init(NUK,uk), /* 41: unknown SCSI */ + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ +! cdev_notdef(), /* 44 */ + cdev_notdef(), /* 45 */ + cdev_notdef(), /* 46 */ + cdev_notdef(), /* 47 */ +--- 175,181 ---- + cdev_uk_init(NUK,uk), /* 41: unknown SCSI */ + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ +! cdev_gen_ipf(NIPF,ipl), /* 44: IP filter */ + cdev_notdef(), /* 45 */ + cdev_notdef(), /* 46 */ + cdev_notdef(), /* 47 */ +diff -d -c -r /tmp/sys/arch/sparc/sparc/conf.c sys/arch/sparc/sparc/conf.c +*** /tmp/sys/arch/sparc/sparc/conf.c Mon Aug 12 12:44:04 2002 +--- sys/arch/sparc/sparc/conf.c Sat Nov 2 12:10:36 2002 +*************** +*** 126,131 **** +--- 126,137 ---- + }; + int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]); + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 198,204 **** + cdev_notdef(), /* 57 */ + cdev_disk_init(NCD,cd), /* 58: SCSI CD-ROM */ + cdev_pf_init(NPF,pf), /* 59: packet filter */ +! cdev_notdef(), /* 60 */ + cdev_notdef(), /* 61 */ + cdev_notdef(), /* 62 */ + cdev_notdef(), /* 63 */ +--- 204,210 ---- + cdev_notdef(), /* 57 */ + cdev_disk_init(NCD,cd), /* 58: SCSI CD-ROM */ + cdev_pf_init(NPF,pf), /* 59: packet filter */ +! cdev_gen_ipf(NIPF,ipl), /* 60: ip filtering log */ + cdev_notdef(), /* 61 */ + cdev_notdef(), /* 62 */ + cdev_notdef(), /* 63 */ +diff -d -c -r /tmp/sys/arch/sparc64/sparc64/conf.c sys/arch/sparc64/sparc64/conf.c +*** /tmp/sys/arch/sparc64/sparc64/conf.c Wed Jun 19 04:52:24 2002 +--- sys/arch/sparc64/sparc64/conf.c Sat Nov 2 12:10:36 2002 +*************** +*** 114,119 **** +--- 114,125 ---- + #include "ucom.h" + #include "uscanner.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 252,258 **** + cdev_mouse_init(NWSKBD, wskbd), /* 79: keyboards */ + cdev_mouse_init(NWSMOUSE, wsmouse), /* 80: mice */ + cdev_mouse_init(NWSMUX, wsmux), /* 81: ws multiplexor */ +! cdev_notdef(), /* 82 */ + cdev_notdef(), /* 83 */ + cdev_notdef(), /* 84 */ + cdev_notdef(), /* 85 */ +--- 258,264 ---- + cdev_mouse_init(NWSKBD, wskbd), /* 79: keyboards */ + cdev_mouse_init(NWSMOUSE, wsmouse), /* 80: mice */ + cdev_mouse_init(NWSMUX, wsmux), /* 81: ws multiplexor */ +! cdev_gen_ipf(NIPF,ipl), /* 82: IP filter */ + cdev_notdef(), /* 83 */ + cdev_notdef(), /* 84 */ + cdev_notdef(), /* 85 */ +diff -d -c -r /tmp/sys/arch/sun3/sun3/conf.c sys/arch/sun3/sun3/conf.c +*** /tmp/sys/arch/sun3/sun3/conf.c Thu May 16 23:11:18 2002 +--- sys/arch/sun3/sun3/conf.c Sun Nov 3 08:09:08 2002 +*************** +*** 109,114 **** +--- 109,120 ---- + }; + int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]); + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 208,213 **** +--- 214,220 ---- + cdev_ses_init(NSES,ses), /* 84: SCSI SES or SAF-TE device */ + cdev_altq_init(NALTQ,altq), /* 85: ALTQ control interface */ + cdev_systrace_init(NSYSTRACE,systrace), /* 86: system call tracing */ ++ cdev_gen_ipf(NIPF,ipl), /* 87: IP filter */ + }; + int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]); + +diff -d -c -r /tmp/sys/arch/vax/vax/conf.c sys/arch/vax/vax/conf.c +*** /tmp/sys/arch/vax/vax/conf.c Thu Jul 11 00:08:47 2002 +--- sys/arch/vax/vax/conf.c Sat Nov 2 12:10:37 2002 +*************** +*** 357,362 **** +--- 357,368 ---- + #include "wskbd.h" + #include "wsmouse.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include <altq/altqconf.h> +*************** +*** 412,418 **** + cdev_notdef(), /* 44 was Datakit */ + cdev_notdef(), /* 45 was Datakit */ + cdev_notdef(), /* 46 was Datakit */ +! cdev_notdef(), /* 47 */ + cdev_notdef(), /* 48 */ + cdev_systrace_init(NSYSTRACE,systrace), /* 49: system call tracing */ + cdev_ksyms_init(NKSYMS,ksyms), /* 50: Kernel symbols device */ +--- 418,424 ---- + cdev_notdef(), /* 44 was Datakit */ + cdev_notdef(), /* 45 was Datakit */ + cdev_notdef(), /* 46 was Datakit */ +! cdev_gen_ipf(NIPF,ipl), /* 47: IP filter */ + cdev_notdef(), /* 48 */ + cdev_systrace_init(NSYSTRACE,systrace), /* 49: system call tracing */ + cdev_ksyms_init(NKSYMS,ksyms), /* 50: Kernel symbols device */ +diff -d -c -r /tmp/sys/conf/GENERIC sys/conf/GENERIC +*** /tmp/sys/conf/GENERIC Thu Sep 26 23:53:11 2002 +--- sys/conf/GENERIC Sat Nov 2 12:10:37 2002 +*************** +*** 71,76 **** +--- 71,78 ---- + #option EON # OSI tunneling over IP + #option NETATALK # AppleTalk + #option CCITT,LLC,HDLC # X.25 ++ option IPFILTER # IP packet filter for security ++ option IPFILTER_LOG # use /dev/ipl to log IPF + option PPP_BSDCOMP # PPP BSD compression + option PPP_DEFLATE + #option MROUTING # Multicast router +diff -d -c -r /tmp/sys/conf/files sys/conf/files +*** /tmp/sys/conf/files Tue Sep 3 18:30:54 2002 +--- sys/conf/files Sat Nov 2 12:10:37 2002 +*************** +*** 688,693 **** +--- 688,701 ---- + file netinet/tcp_usrreq.c inet + file netinet/udp_usrreq.c inet + file netinet/ip_gre.c inet ++ file netinet/ip_fil.c ipfilter ++ file netinet/fil.c ipfilter ++ file netinet/ip_nat.c ipfilter ++ file netinet/ip_frag.c ipfilter ++ file netinet/ip_state.c ipfilter ++ file netinet/ip_proxy.c ipfilter ++ file netinet/ip_auth.c ipfilter ++ file netinet/ip_log.c ipfilter + file netinet/ip_ipsp.c (inet | inet6) & (ipsec | tcp_signature) + file netinet/ip_spd.c (inet | inet6) & (ipsec | tcp_signature) + file netinet/ip_ipip.c inet | inet6 +diff -d -c -r /tmp/sys/net/bridgestp.c sys/net/bridgestp.c +*** /tmp/sys/net/bridgestp.c Tue Sep 24 21:52:20 2002 +--- sys/net/bridgestp.c Sat Nov 2 12:10:37 2002 +*************** +*** 63,68 **** +--- 63,73 ---- + #include <netinet/in_var.h> + #include <netinet/ip.h> + #include <netinet/if_ether.h> ++ ++ #ifdef IPFILTER ++ #include <netinet/ip_compat.h> ++ #include <netinet/ip_fil.h> ++ #endif + #endif + + #if NBPFILTER > 0 +diff -d -c -r /tmp/sys/net/if.c sys/net/if.c +*** /tmp/sys/net/if.c Wed Sep 11 07:38:47 2002 +--- sys/net/if.c Sat Nov 2 12:10:37 2002 +*************** +*** 101,106 **** +--- 101,112 ---- + #include <netinet6/nd6.h> + #endif + ++ #ifdef IPFILTER ++ #include <netinet/ip_compat.h> ++ #include <netinet/ip_fil.h> ++ #include <netinet/ip_nat.h> ++ #endif ++ + #if NBPFILTER > 0 + #include <net/bpf.h> + #endif +*************** +*** 468,473 **** +--- 474,484 ---- + + /* Remove the interface from the list of all interfaces. */ + TAILQ_REMOVE(&ifnet, ifp, if_list); ++ ++ #ifdef IPFILTER ++ /* XXX More ipf & ipnat cleanup needed. */ ++ frsync(ifp); ++ #endif + + /* + * Deallocate private resources. +diff -d -c -r /tmp/sys/net/if_bridge.c sys/net/if_bridge.c +*** /tmp/sys/net/if_bridge.c Wed Aug 7 20:44:39 2002 +--- sys/net/if_bridge.c Sat Nov 2 12:10:37 2002 +*************** +*** 70,75 **** +--- 70,79 ---- + #include <netinet/ip_ipsp.h> + + #include <net/if_enc.h> ++ #if (defined(IPFILTER) || defined(IPFILTER_LKM)) ++ #include <netinet/ip_compat.h> ++ #include <netinet/ip_fil.h> ++ #endif + #endif + + #ifdef INET6 +*************** +*** 155,161 **** + int bridge_flushrule(struct bridge_iflist *); + int bridge_brlconf(struct bridge_softc *, struct ifbrlconf *); + u_int8_t bridge_filterrule(struct brl_head *, struct ether_header *); +! #if NPF > 0 + struct mbuf *bridge_filter(struct bridge_softc *, int, struct ifnet *, + struct ether_header *, struct mbuf *m); + #endif +--- 159,165 ---- + int bridge_flushrule(struct bridge_iflist *); + int bridge_brlconf(struct bridge_softc *, struct ifbrlconf *); + u_int8_t bridge_filterrule(struct brl_head *, struct ether_header *); +! #if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + struct mbuf *bridge_filter(struct bridge_softc *, int, struct ifnet *, + struct ether_header *, struct mbuf *m); + #endif +*************** +*** 1144,1150 **** + m_freem(m); + return; + } +! #if NPF > 0 + m = bridge_filter(sc, BRIDGE_IN, src_if, &eh, m); + if (m == NULL) + return; +--- 1148,1154 ---- + m_freem(m); + return; + } +! #if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + m = bridge_filter(sc, BRIDGE_IN, src_if, &eh, m); + if (m == NULL) + return; +*************** +*** 1187,1193 **** + m_freem(m); + return; + } +! #if NPF > 0 + m = bridge_filter(sc, BRIDGE_OUT, dst_if, &eh, m); + if (m == NULL) + return; +--- 1191,1197 ---- + m_freem(m); + return; + } +! #if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + m = bridge_filter(sc, BRIDGE_OUT, dst_if, &eh, m); + if (m == NULL) + return; +*************** +*** 1441,1447 **** + mc = m1; + } + +! #if NPF > 0 + mc = bridge_filter(sc, BRIDGE_OUT, dst_if, eh, mc); + if (mc == NULL) + continue; +--- 1445,1451 ---- + mc = m1; + } + +! #if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + mc = bridge_filter(sc, BRIDGE_OUT, dst_if, eh, mc); + if (mc == NULL) + continue; +*************** +*** 2220,2226 **** + * We don't need to do loop detection, the + * bridge will do that for us. + */ +! #if NFP > 0 + switch (af) { + #ifdef INET + case AF_INET: +--- 2224,2236 ---- + * We don't need to do loop detection, the + * bridge will do that for us. + */ +! #if defined(IPFILTER) || defined(IPFILTER_LKM) +! if (dir == BRIDGE_OUT && fr_checkp && +! ((*fr_checkp)(ip, hlen, &encif[0].sc_if, +! dir, &m) || !m)) +! return 1; +! #endif +! #if NPF > 0 + switch (af) { + #ifdef INET + case AF_INET: +*************** +*** 2244,2249 **** +--- 2254,2265 ---- + if (m == NULL) + return (1); + #endif /* NPF */ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (dir == BRIDGE_IN && fr_checkp && ++ ((*fr_checkp)(ip, hlen, &encif[0].sc_if, ++ dir, &m) || !m)) ++ return 1; ++ #endif + #ifdef INET + if (af == AF_INET) { + ip = mtod(m, struct ip *); +*************** +*** 2262,2268 **** + } + #endif /* IPSEC */ + +! #if NPF > 0 + /* + * Filter IP packets by peeking into the ethernet frame. This violates + * the ISO model, but allows us to act as a IP filter at the data link +--- 2278,2284 ---- + } + #endif /* IPSEC */ + +! #if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + /* + * Filter IP packets by peeking into the ethernet frame. This violates + * the ISO model, but allows us to act as a IP filter at the data link +*************** +*** 2372,2377 **** +--- 2388,2401 ---- + return (NULL); + #endif /* IPSEC */ + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (dir == BRIDGE_OUT) { ++ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, dir, &m)) ++ goto dropit; ++ if (m == NULL) ++ goto dropit; ++ } ++ #endif + #if NPF > 0 + /* Finally, we get to filter the packet! */ + m->m_pkthdr.rcvif = ifp; +*************** +*** 2380,2385 **** +--- 2404,2417 ---- + if (m == NULL) + goto dropit; + #endif /* NPF */ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (dir == BRIDGE_IN) { ++ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, dir, &m)) ++ goto dropit; ++ if (m == NULL) ++ goto dropit; ++ } ++ #endif + + /* Rebuild the IP header */ + if (m->m_len < hlen && ((m = m_pullup(m, hlen)) == NULL)) +*************** +*** 2423,2434 **** +--- 2455,2482 ---- + return (NULL); + #endif /* IPSEC */ + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (dir == BRIDGE_OUT) { ++ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, dir, &m)) ++ goto dropit; ++ if (m == NULL) ++ return (NULL); ++ } ++ #endif + #if NPF > 0 + if (pf_test6(dir, ifp, &m) != PF_PASS) + goto dropit; + if (m == NULL) + return (NULL); + #endif /* NPF */ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (dir == BRIDGE_IN) { ++ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, dir, &m)) ++ goto dropit; ++ if (m == NULL) ++ return (NULL); ++ } ++ #endif + + break; + } +*************** +*** 2460,2466 **** + m_freem(m); + return (NULL); + } +! #endif /* NPF > 0 */ + + void + bridge_fragment(sc, ifp, eh, m) +--- 2508,2514 ---- + m_freem(m); + return (NULL); + } +! #endif /* (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) */ + + void + bridge_fragment(sc, ifp, eh, m) +diff -d -c -r /tmp/sys/netinet/in_proto.c sys/netinet/in_proto.c +*** /tmp/sys/netinet/in_proto.c Sun Jun 9 18:26:10 2002 +--- sys/netinet/in_proto.c Sat Nov 2 12:10:38 2002 +*************** +*** 163,168 **** +--- 163,173 ---- + #include <netinet/ip_mroute.h> + #endif /* MROUTING */ + ++ #ifdef IPFILTER ++ void iplinit __P((void)); ++ #define ip_init iplinit ++ #endif ++ + #ifdef INET6 + #include <netinet6/ip6_var.h> + #endif /* INET6 */ +diff -d -c -r /tmp/sys/netinet/ip_input.c sys/netinet/ip_input.c +*** /tmp/sys/netinet/ip_input.c Wed Sep 4 21:04:38 2002 +--- sys/netinet/ip_input.c Sat Nov 2 12:10:38 2002 +*************** +*** 149,154 **** +--- 149,158 ---- + struct in_ifaddrhead in_ifaddr; + struct ifqueue ipintrq; + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif ++ + int ipq_locked; + static __inline int ipq_lock_try(void); + static __inline void ipq_unlock(void); +*************** +*** 399,404 **** +--- 403,425 ---- + + ip = mtod(m, struct ip *); + hlen = ip->ip_hl << 2; ++ #endif ++ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * Check if we want to allow this packet to be processed. ++ * Consider it to be bad if not. ++ */ ++ { ++ struct mbuf *m0 = m; ++ if (fr_checkp && (*fr_checkp)(ip, hlen, m->m_pkthdr.rcvif, 0, &m0)) { ++ return; ++ } ++ if (m0 == 0) { /* in case of 'fastroute' */ ++ return; ++ } ++ ip = mtod(m = m0, struct ip *); ++ } + #endif + + #ifdef ALTQ +diff -d -c -r /tmp/sys/netinet/ip_output.c sys/netinet/ip_output.c +*** /tmp/sys/netinet/ip_output.c Tue Jun 25 01:57:28 2002 +--- sys/netinet/ip_output.c Sat Nov 2 12:10:38 2002 +*************** +*** 90,95 **** +--- 90,99 ---- + static struct mbuf *ip_insertoptions(struct mbuf *, struct mbuf *, int *); + static void ip_mloopback(struct ifnet *, struct mbuf *, struct sockaddr_in *); + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif ++ + /* + * IP output. The packet in mbuf chain m contains a skeletal IP + * header (with len, off, ttl, proto, tos, src, dst). +*************** +*** 563,568 **** +--- 567,596 ---- + if (sproto != 0) { + s = splnet(); + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (fr_checkp) { ++ /* ++ * Ok, it's time for a simple round-trip to the IPF/NAT ++ * code with the enc0 interface. ++ */ ++ struct mbuf *m1 = m; ++ void *ifp = (void *)&encif[0].sc_if; ++ ++ if ((*fr_checkp)(ip, hlen, ifp, 1, &m1)) { ++ error = EHOSTUNREACH; ++ splx(s); ++ goto done; ++ } ++ if (m1 == 0) { /* in case of 'fastroute' */ ++ error = 0; ++ splx(s); ++ goto done; ++ } ++ ip = mtod(m = m1, struct ip *); ++ hlen = ip->ip_hl << 2; ++ } ++ #endif /* IPFILTER */ ++ + /* + * Packet filter + */ +*************** +*** 665,670 **** +--- 693,717 ---- + m->m_pkthdr.csum &= ~M_UDPV4_CSUM_OUT; /* Clear */ + } + } ++ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * looks like most checking has been done now...do a filter check ++ */ ++ { ++ struct mbuf *m1 = m; ++ ++ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 1, &m1)) { ++ error = EHOSTUNREACH; ++ goto done; ++ } ++ if (m1 == 0) { /* in case of 'fastroute' */ ++ error = 0; ++ goto done; ++ } ++ ip = mtod(m = m1, struct ip *); ++ } ++ #endif + + /* + * Packet filter +diff -d -c -r /tmp/sys/netinet6/ip6_input.c sys/netinet6/ip6_input.c +*** /tmp/sys/netinet6/ip6_input.c Wed Sep 11 05:27:30 2002 +--- sys/netinet6/ip6_input.c Sat Nov 2 12:10:38 2002 +*************** +*** 134,139 **** +--- 134,143 ---- + static struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int); + #endif + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif ++ + /* + * IP6 initialization: fill in IP6 protocol switch table. + * All protocols not implemented in kernel go to raw IP6 protocol handler. +*************** +*** 251,256 **** +--- 255,280 ---- + in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); + goto bad; + } ++ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * Check if we want to allow this packet to be processed. ++ * Consider it to be bad if not. ++ */ ++ if (fr_checkp != NULL) { ++ struct mbuf *m0 = m; ++ ++ if ((*fr_checkp)((struct ip *)ip6, sizeof(*ip6), ++ m->m_pkthdr.rcvif, 0, &m0)) { ++ return; ++ } ++ m = m0; ++ if (m == 0) { /* in case of 'fastroute' */ ++ return; ++ } ++ ip6 = mtod(m, struct ip6_hdr *); ++ } ++ #endif + + #if NPF > 0 + /* +diff -d -c -r /tmp/sys/netinet6/ip6_output.c sys/netinet6/ip6_output.c +*** /tmp/sys/netinet6/ip6_output.c Tue Sep 24 01:03:31 2002 +--- sys/netinet6/ip6_output.c Sun Nov 3 08:14:44 2002 +*************** +*** 120,132 **** + + static int ip6_pcbopts(struct ip6_pktopts **, struct mbuf *, struct socket *); + static int ip6_setmoptions(int, struct ip6_moptions **, struct mbuf *); + static int ip6_getmoptions(int, struct ip6_moptions *, struct mbuf **); + static int ip6_copyexthdr(struct mbuf **, caddr_t, int); + static int ip6_insertfraghdr(struct mbuf *, struct mbuf *, int, + struct ip6_frag **); + static int ip6_insert_jumboopt(struct ip6_exthdrs *, u_int32_t); + static int ip6_splithdr(struct mbuf *, struct ip6_exthdrs *); +! static int ip6_getpmtu(struct route_in6 *, struct route_in6 *, + struct ifnet *, struct in6_addr *, u_long *); + + /* +--- 120,135 ---- + + static int ip6_pcbopts(struct ip6_pktopts **, struct mbuf *, struct socket *); + static int ip6_setmoptions(int, struct ip6_moptions **, struct mbuf *); ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif + static int ip6_getmoptions(int, struct ip6_moptions *, struct mbuf **); + static int ip6_copyexthdr(struct mbuf **, caddr_t, int); + static int ip6_insertfraghdr(struct mbuf *, struct mbuf *, int, + struct ip6_frag **); + static int ip6_insert_jumboopt(struct ip6_exthdrs *, u_int32_t); + static int ip6_splithdr(struct mbuf *, struct ip6_exthdrs *); +! int ip6_getpmtu(struct route_in6 *, struct route_in6 *, + struct ifnet *, struct in6_addr *, u_long *); + + /* +*************** +*** 796,801 **** +--- 799,823 ---- + goto done; + ip6 = mtod(m, struct ip6_hdr *); + #endif ++ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * looks like most checking has been done now...do a filter check ++ */ ++ if (fr_checkp != NULL) { ++ struct mbuf *m1 = m; ++ if ((*fr_checkp)((struct ip *)ip6, sizeof(*ip6), ifp, 1, &m1)) { ++ error = EHOSTUNREACH; ++ goto done; ++ } ++ m = m1; ++ if (m1 == 0) { /* in case of 'fastroute' */ ++ error = 0; ++ goto done; ++ } ++ ip6 = mtod(m, struct ip6_hdr *); ++ } ++ #endif + + /* + * Send the packet to the outgoing interface. +*************** +*** 1120,1126 **** + return (0); + } + +! static int + ip6_getpmtu(ro_pmtu, ro, ifp, dst, mtup) + struct route_in6 *ro_pmtu, *ro; + struct ifnet *ifp; +--- 1142,1148 ---- + return (0); + } + +! int + ip6_getpmtu(ro_pmtu, ro, ifp, dst, mtup) + struct route_in6 *ro_pmtu, *ro; + struct ifnet *ifp; +diff -d -c -r /tmp/sys/sys/conf.h sys/sys/conf.h +*** /tmp/sys/sys/conf.h Thu Jul 11 00:21:30 2002 +--- sys/sys/conf.h Sun Nov 3 08:17:26 2002 +*************** +*** 358,363 **** +--- 358,370 ---- + (dev_type_ioctl((*))) enodev, (dev_type_stop((*))) nullop, \ + 0, (dev_type_select((*))) enodev, (dev_type_mmap((*))) enodev } + ++ /* open, close, read, ioctl */ ++ #define cdev_gen_ipf(c, n) { \ ++ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ ++ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ ++ (dev_type_stop((*))) enodev, 0, (dev_type_select((*))) enodev, \ ++ (dev_type_mmap((*))) enodev } ++ + /* open, close, read, write, ioctl, select, nokqfilter */ + #define cdev_xfs_init(c, n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ +*************** +*** 560,565 **** +--- 567,573 ---- + + cdev_decl(bpf); + ++ cdev_decl(ipl); + cdev_decl(pf); + + cdev_decl(tun); diff --git a/OpenBSD-3/3.3-MAKEDEV-diffs b/OpenBSD-3/3.3-MAKEDEV-diffs new file mode 100644 index 0000000000000..5d08117c3421e --- /dev/null +++ b/OpenBSD-3/3.3-MAKEDEV-diffs @@ -0,0 +1,797 @@ +Index: etc/MAKEDEV.mi +=================================================================== +RCS file: /cvs/src/etc/MAKEDEV.mi,v +retrieving revision 1.57 +diff -c -r1.57 MAKEDEV.mi +*** etc/MAKEDEV.mi 16 Mar 2003 13:15:53 -0000 1.57 +--- etc/MAKEDEV.mi 8 Jun 2003 07:40:20 -0000 +*************** +*** 152,157 **** +--- 152,161 ---- + target(all, pctr)dnl + target(all, pctr0)dnl + target(all, pf)dnl ++ target(all, ipl)dnl ++ target(all, ipnat)dnl ++ target(all, ipstate)dnl ++ target(all, ipauth)dnl + twrget(all, cry, crypto)dnl + target(all, apm)dnl + twrget(all, tth, ttyh, 0, 1)dnl +*************** +*** 558,563 **** +--- 562,575 ---- + _mkdev(cry, crypto, {-M crypto c major_cry_c-} 0)dnl + __devitem(pf, pf*, Packet Filter)dnl + _mkdev(pf, {-pf*-}, {-M pf c major_pf_c 0 600-})dnl ++ __devitem(ipl, ipl*, Packet Filter log)dnl ++ _mkdev(ipl, {-ipl*-}, {-M ipl c major_ipl_c 0 600-})dnl ++ __devitem(ipnat, ipnat*, Packet Filter NAT)dnl ++ _mkdev(ipnat, {-ipnat*-}, {-M ipnat c major_ipnat_c 1 600-})dnl ++ __devitem(ipstate, ipstate*, Packet Filter state)dnl ++ _mkdev(ipstate, {-ipstate*-}, {-M ipstate c major_ipstate_c 2 600-})dnl ++ __devitem(ipauth, ipauth*, Packet Filter auth)dnl ++ _mkdev(ipauth, {-ipauth*-}, {-M ipauth c major_ipauth_c 3 600-})dnl + __devitem(bpf, bpf*, Berkeley Packet Filter)dnl + _mkdev(bpf, {-bpf*-}, {-M bpf$U c major_bpf_c $U 600-}, 600)dnl + _mkdev(tun, {-tun*-}, {-M tun$U c major_tun_c $U 600-}, 600)dnl +Index: etc/etc.alpha/MAKEDEV +=================================================================== +RCS file: /cvs/src/etc/etc.alpha/MAKEDEV,v +retrieving revision 1.95 +diff -c -r1.95 MAKEDEV +*** etc/etc.alpha/MAKEDEV 6 Jan 2003 17:19:59 -0000 1.95 +--- etc/etc.alpha/MAKEDEV 8 Jun 2003 07:40:24 -0000 +*************** +*** 71,76 **** +--- 71,77 ---- + # utty* Serial ports + # Special purpose devices: + # ch* SCSI media changer ++ # ipl IP Filter + # pf* Packet Filter + # bpf* Berkeley Packet Filter + # iop* I2O controller device +*************** +*** 330,335 **** +--- 331,343 ---- + M bpf$U c 11 $U 600 + ;; + ++ ipl) ++ M ipl c 44 0 600 ++ M ipnat c 44 1 600 ++ M ipstate c 44 2 600 ++ M ipauth c 44 2 600 ++ ;; ++ + pf*) + M pf c 35 0 600 + ;; +*************** +*** 494,499 **** +--- 502,508 ---- + R tty00 tty01 tty02 tty03 ttyc0 ttyc1 ttyc2 ttyc3 ttyc4 ttyc5 + R ttyc6 ttyc7 ttyB0 ttyB1 ttyB2 ttyB3 ttyB4 ttyB5 pf systrace + R wd0 wd1 wd2 wd3 raid0 raid1 raid2 raid3 std st0 st1 fd ++ R ipl + ;; + + wd*|sd*|raid*|ccd*) +Index: etc/etc.alpha/MAKEDEV.md +=================================================================== +RCS file: /cvs/src/etc/etc.alpha/MAKEDEV.md,v +retrieving revision 1.15 +diff -c -r1.15 MAKEDEV.md +*** etc/etc.alpha/MAKEDEV.md 5 Dec 2002 04:30:21 -0000 1.15 +--- etc/etc.alpha/MAKEDEV.md 8 Jun 2003 07:40:25 -0000 +*************** +*** 66,71 **** +--- 66,75 ---- + _TITLE(spec) + _DEV(ch, 14) + _DEV(pf, 35) ++ _DEV(ipl, 44) ++ _DEV(ipnat, 44) ++ _DEV(ipstate, 44) ++ _DEV(ipauth, 44) + _DEV(bpf, 11) + _DEV(iop, 54) + _DEV(pci, 52) +Index: etc/etc.hp300/MAKEDEV +=================================================================== +RCS file: /cvs/src/etc/etc.hp300/MAKEDEV,v +retrieving revision 1.63 +diff -c -r1.63 MAKEDEV +*** etc/etc.hp300/MAKEDEV 6 Jan 2003 17:19:59 -0000 1.63 +--- etc/etc.hp300/MAKEDEV 8 Jun 2003 07:40:25 -0000 +*************** +*** 61,66 **** +--- 61,67 ---- + # ite* terminal emulator interface to HP300 graphics devices + # hil HP300 HIL input devices + # bpf* Berkeley Packet Filter ++ # ipl IP Filter + # tun* network tunnel driver + # pf* Packet Filter + # lkm loadable kernel modules interface +*************** +*** 316,321 **** +--- 317,329 ---- + M lkm c 24 0 640 _lkm + ;; + ++ ipl) ++ M ipl c 37 0 600 ++ M ipnat c 37 1 600 ++ M ipstate c 37 2 600 ++ M ipauth c 37 3 600 ++ ;; ++ + pf*) + M pf c 33 0 600 + ;; +*************** +*** 395,400 **** +--- 403,409 ---- + R sd2 sd3 sd4 rd0 tun0 tun1 tun2 tun3 bpf0 bpf1 bpf2 bpf3 bpf4 + R bpf5 bpf6 bpf7 bpf8 bpf9 pty0 pty1 pty2 xfs0 local ppi0 + R apci0 random lkm pf systrace std fd ++ R ipl + ;; + + sd*|hd*|ccd*) +Index: etc/etc.hp300/MAKEDEV.md +=================================================================== +RCS file: /cvs/src/etc/etc.hp300/MAKEDEV.md,v +retrieving revision 1.12 +diff -c -r1.12 MAKEDEV.md +*** etc/etc.hp300/MAKEDEV.md 25 Dec 2002 20:20:20 -0000 1.12 +--- etc/etc.hp300/MAKEDEV.md 8 Jun 2003 07:40:26 -0000 +*************** +*** 84,89 **** +--- 84,93 ---- + _DEV(bpf, 22) + _DEV(tun, 23) + _DEV(pf, 33) ++ _DEV(ipl, 37) ++ _DEV(ipnat, 37) ++ _DEV(ipstate, 37) ++ _DEV(ipauth, 37) + _DEV(lkm, 24) + _DEV(rnd, 32) + _DEV(xfs, 51) +Index: etc/etc.hppa/MAKEDEV +=================================================================== +RCS file: /cvs/src/etc/etc.hppa/MAKEDEV,v +retrieving revision 1.34 +diff -c -r1.34 MAKEDEV +*** etc/etc.hppa/MAKEDEV 5 Feb 2003 20:18:36 -0000 1.34 +--- etc/etc.hppa/MAKEDEV 8 Jun 2003 07:40:26 -0000 +*************** +*** 62,67 **** +--- 62,68 ---- + # Special purpose devices: + # fd makes fd/* for the fdescfs + # bpf* Berkeley Packet Filter ++ # ipl IP Filter + # tun* network tunnel driver + # pf* Packet Filter + # lkm loadable kernel modules interface +*************** +*** 266,271 **** +--- 267,279 ---- + M lkm c 19 0 640 _lkm + ;; + ++ ipl) ++ M ipl c 38 0 600 ++ M ipnat c 38 1 600 ++ M ipstate c 38 2 600 ++ M ipauth c 38 3 600 ++ ;; ++ + pf*) + M pf c 21 0 600 + ;; +*************** +*** 412,417 **** +--- 420,426 ---- + R xfs0 ss0 ss1 ch0 ses0 wscons audio0 uk0 random lpa0 lpa1 + R lpa2 lpt0 lpt1 lpt2 lkm tty00 tty01 tty02 tty03 crypto pf + R systrace std st0 st1 fd ++ R ipl + ;; + + sd*|ccd*) +Index: etc/etc.hppa/MAKEDEV.md +=================================================================== +RCS file: /cvs/src/etc/etc.hppa/MAKEDEV.md,v +retrieving revision 1.13 +diff -c -r1.13 MAKEDEV.md +*** etc/etc.hppa/MAKEDEV.md 5 Feb 2003 20:17:38 -0000 1.13 +--- etc/etc.hppa/MAKEDEV.md 8 Jun 2003 07:40:26 -0000 +*************** +*** 58,63 **** +--- 58,67 ---- + _DEV(bpf, 17) + _DEV(tun, 18) + _DEV(pf, 21) ++ _DEV(ipl, 38) ++ _DEV(ipnat, 38) ++ _DEV(ipstate, 38) ++ _DEV(ipauth, 38) + _DEV(lkm, 19) + _DEV(rnd, 20) + _DEV(xfs, 31) +Index: etc/etc.i386/MAKEDEV +=================================================================== +RCS file: /cvs/src/etc/etc.i386/MAKEDEV,v +retrieving revision 1.139 +diff -c -r1.139 MAKEDEV +*** etc/etc.i386/MAKEDEV 6 Jan 2003 17:19:59 -0000 1.139 +--- etc/etc.i386/MAKEDEV 8 Jun 2003 07:40:27 -0000 +*************** +*** 79,84 **** +--- 79,85 ---- + # Special purpose devices: + # fd makes fd/* for the fdescfs + # crypto hardware crypto access driver ++ # ipl IP Filter + # pf* Packet Filter + # bpf* Berkeley Packet Filter + # speaker pc speaker +*************** +*** 373,378 **** +--- 374,386 ---- + M bpf$U c 23 $U 600 + ;; + ++ ipl) ++ M ipl c 81 0 600 ++ M ipnat c 81 1 600 ++ M ipstate c 81 2 600 ++ M ipauth c 81 3 600 ++ ;; ++ + pf*) + M pf c 73 0 600 + ;; +*************** +*** 569,574 **** +--- 577,583 ---- + R tty03 ttyc0 ttyc1 ttyc2 ttyc3 ttyc4 ttyc5 ttyc6 ttyc7 apm + R crypto pf pctr systrace wd0 wd1 wd2 wd3 raid0 raid1 raid2 + R raid3 std st0 st1 fd mcd0 ++ R ipl + ;; + + wd*|sd*|raid*|ccd*) +Index: etc/etc.i386/MAKEDEV.md +=================================================================== +RCS file: /cvs/src/etc/etc.i386/MAKEDEV.md,v +retrieving revision 1.16 +diff -c -r1.16 MAKEDEV.md +*** etc/etc.i386/MAKEDEV.md 5 Dec 2002 04:30:21 -0000 1.16 +--- etc/etc.i386/MAKEDEV.md 8 Jun 2003 07:40:27 -0000 +*************** +*** 74,79 **** +--- 74,83 ---- + _DEV(fdesc, 22) + _DEV(cry, 70) + _DEV(pf, 73) ++ _DEV(ipl, 81) ++ _DEV(ipnat, 81) ++ _DEV(ipstate, 81) ++ _DEV(ipauth, 81) + _DEV(bpf, 23) + _DEV(speak, 27) + _DEV(lkm, 28) +Index: etc/etc.mac68k/MAKEDEV +=================================================================== +RCS file: /cvs/src/etc/etc.mac68k/MAKEDEV,v +retrieving revision 1.65 +diff -c -r1.65 MAKEDEV +*** etc/etc.mac68k/MAKEDEV 6 Jan 2003 17:19:59 -0000 1.65 +--- etc/etc.mac68k/MAKEDEV 8 Jun 2003 07:40:29 -0000 +*************** +*** 56,61 **** +--- 56,62 ---- + # CyberVision 64 (grf5) + # Special purpose devices: + # bpf* Berkeley Packet Filter ++ # ipl IP Filter + # tun* network tunnel driver + # pf* Packet Filter + # lkm loadable kernel modules interface +*************** +*** 277,282 **** +--- 278,290 ---- + M lkm c 25 0 640 _lkm + ;; + ++ ipl) ++ M ipl c 38 0 600 ++ M ipnat c 38 1 600 ++ M ipstate c 38 2 600 ++ M ipauth c 38 3 600 ++ ;; ++ + pf*) + M pf c 35 0 600 + ;; +*************** +*** 355,360 **** +--- 363,369 ---- + R xfs0 ss0 ss1 ch0 vnd0 vnd1 vnd2 vnd3 sd0 sd1 sd2 sd3 sd4 + R local grf0 grf1 grf2 grf3 adb asc0 uk0 random lkm ttye0 + R tty00 tty01 pf systrace std st0 st1 fd ++ R ipl + ;; + + sd*|ccd*) +Index: etc/etc.mac68k/MAKEDEV.md +=================================================================== +RCS file: /cvs/src/etc/etc.mac68k/MAKEDEV.md,v +retrieving revision 1.10 +diff -c -r1.10 MAKEDEV.md +*** etc/etc.mac68k/MAKEDEV.md 5 Dec 2002 04:30:21 -0000 1.10 +--- etc/etc.mac68k/MAKEDEV.md 8 Jun 2003 07:40:29 -0000 +*************** +*** 50,55 **** +--- 50,59 ---- + _DEV(bpf, 22) + _DEV(tun, 24) + _DEV(pf, 35) ++ _DEV(ipl, 38) ++ _DEV(ipnat, 38) ++ _DEV(ipstate, 38) ++ _DEV(ipauth, 38) + _DEV(lkm, 25) + _DEV(rnd, 32) + _DEV(uk, 34) +Index: etc/etc.macppc/MAKEDEV +=================================================================== +RCS file: /cvs/src/etc/etc.macppc/MAKEDEV,v +retrieving revision 1.37 +diff -c -r1.37 MAKEDEV +*** etc/etc.macppc/MAKEDEV 6 Jan 2003 17:19:59 -0000 1.37 +--- etc/etc.macppc/MAKEDEV 8 Jun 2003 07:40:30 -0000 +*************** +*** 72,77 **** +--- 72,78 ---- + # audio* audio device + # apm power management device + # bpf* Berkeley Packet Filter ++ # ipl IP Filter + # tun* network tunnel driver + # lkm loadable kernel modules interface + # *random inkernel random data source +*************** +*** 256,261 **** +--- 257,269 ---- + M crypto c 47 0 + ;; + ++ ipl) ++ M ipl c 45 0 600 ++ M ipnat c 45 1 600 ++ M ipstate c 45 2 600 ++ M ipauth c 45 3 600 ++ ;; ++ + pf*) + M pf c 39 0 600 + ;; +*************** +*** 456,461 **** +--- 464,470 ---- + R local wscons pci iop0 iop1 usbs tuner0 radio0 audio0 uk0 + R random lkm tty00 tty01 tty02 tty03 apm crypto pf systrace + R wd0 wd1 wd2 wd3 raid0 raid1 raid2 raid3 std st0 st1 fd ++ R ipl + ;; + + wd*|sd*|raid*|ccd*) +Index: etc/etc.macppc/MAKEDEV.md +=================================================================== +RCS file: /cvs/src/etc/etc.macppc/MAKEDEV.md,v +retrieving revision 1.10 +diff -c -r1.10 MAKEDEV.md +*** etc/etc.macppc/MAKEDEV.md 5 Dec 2002 04:30:21 -0000 1.10 +--- etc/etc.macppc/MAKEDEV.md 8 Jun 2003 07:40:30 -0000 +*************** +*** 74,79 **** +--- 74,83 ---- + _DEV(xfs, 51) + _DEV(iop, 73) + _DEV(pf, 39) ++ _DEV(ipl, 45) ++ _DEV(ipnat, 45) ++ _DEV(ipstate, 45) ++ _DEV(ipauth, 45) + _DEV(cry, 47) + _DEV(usbs) + _DEV(pci, 71) +Index: etc/etc.mvme68k/MAKEDEV +=================================================================== +RCS file: /cvs/src/etc/etc.mvme68k/MAKEDEV,v +retrieving revision 1.51 +diff -c -r1.51 MAKEDEV +*** etc/etc.mvme68k/MAKEDEV 6 Jan 2003 17:19:59 -0000 1.51 +--- etc/etc.mvme68k/MAKEDEV 8 Jun 2003 07:40:30 -0000 +*************** +*** 60,65 **** +--- 60,66 ---- + # fd makes fd/* for the fdescfs + # bpf* Berkeley Packet Filter + # tun* network tunnel driver ++ # ipl IP Packet Filter + # pf* Packet Filter + # lkm loadable kernel modules interface + # *random inkernel random data source +*************** +*** 253,258 **** +--- 254,266 ---- + M bpf$U c 22 $U 600 + ;; + ++ ipl) ++ M ipl c 44 0 600 ++ M ipnat c 44 1 600 ++ M ipstate c 44 2 600 ++ M ipauth c 44 3 600 ++ ;; ++ + fd) + RMlist="mkdir -p fd;$RMlist" n=0 + while [ $n -lt 64 ];do M fd/$n c 21 $n;n=$(($n+1));done +*************** +*** 389,394 **** +--- 397,403 ---- + R tun3 bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 pty0 + R pty1 pty2 xfs0 ss0 ss1 vmel0 vmes0 flash0 nvram0 sram0 uk0 + R random lkm pf systrace std st0 st1 fd ++ R ipl + ;; + + sd*|ccd*) +Index: etc/etc.mvme68k/MAKEDEV.md +=================================================================== +RCS file: /cvs/src/etc/etc.mvme68k/MAKEDEV.md,v +retrieving revision 1.7 +diff -c -r1.7 MAKEDEV.md +*** etc/etc.mvme68k/MAKEDEV.md 5 Dec 2002 04:30:21 -0000 1.7 +--- etc/etc.mvme68k/MAKEDEV.md 8 Jun 2003 07:40:31 -0000 +*************** +*** 175,177 **** +--- 175,186 ---- + _std(1, 2, 43, 3, 6) + ;; + ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 44 0 ++ mknod ipnat c 44 1 ++ mknod ipstate c 44 2 ++ mknod ipauth c 44 3 ++ chown root.wheel ipl ipnat ipstate ipauth ++ ;; ++ +Index: etc/etc.mvme88k/MAKEDEV +=================================================================== +RCS file: /cvs/src/etc/etc.mvme88k/MAKEDEV,v +retrieving revision 1.28 +diff -c -r1.28 MAKEDEV +*** etc/etc.mvme88k/MAKEDEV 6 Jan 2003 17:19:59 -0000 1.28 +--- etc/etc.mvme88k/MAKEDEV 8 Jun 2003 07:40:31 -0000 +*************** +*** 55,60 **** +--- 55,61 ---- + # fd makes fd/* for the fdescfs + # bpf* Berkeley Packet Filter + # tun* network tunnel driver ++ # ipl IP Packet Filter + # pf* Packet Filter + # lkm loadable kernel modules interface + # *random inkernel random data source +*************** +*** 243,248 **** +--- 244,256 ---- + M bpf$U c 22 $U 600 + ;; + ++ ipl) ++ M ipl c 41 0 600 ++ M ipnat c 41 1 600 ++ M ipstate c 41 2 600 ++ M ipauth c 41 3 600 ++ ;; ++ + fd) + RMlist="mkdir -p fd;$RMlist" n=0 + while [ $n -lt 64 ];do M fd/$n c 21 $n;n=$(($n+1));done +*************** +*** 345,350 **** +--- 353,359 ---- + R tun2 tun3 bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 + R pty0 pty1 pty2 xfs0 vmel0 vmes0 nvram0 sram0 random lkm pf + R systrace std st0 st1 fd ++ R ipl + ;; + + sd*|ccd*) +Index: etc/etc.mvme88k/MAKEDEV.md +=================================================================== +RCS file: /cvs/src/etc/etc.mvme88k/MAKEDEV.md,v +retrieving revision 1.6 +diff -c -r1.6 MAKEDEV.md +*** etc/etc.mvme88k/MAKEDEV.md 5 Dec 2002 04:30:21 -0000 1.6 +--- etc/etc.mvme88k/MAKEDEV.md 8 Jun 2003 07:40:32 -0000 +*************** +*** 144,146 **** +--- 144,155 ---- + _std(1, 2, 43, 3, 6) + ;; + ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 41 0 ++ mknod ipnat c 41 1 ++ mknod ipstate c 41 2 ++ mknod ipauth c 41 3 ++ chown root.wheel ipl ipnat ipstate ipauth ++ ;; ++ +Index: etc/etc.mvmeppc/MAKEDEV +=================================================================== +RCS file: /cvs/src/etc/etc.mvmeppc/MAKEDEV,v +retrieving revision 1.10 +diff -c -r1.10 MAKEDEV +*** etc/etc.mvmeppc/MAKEDEV 6 Jan 2003 05:57:39 -0000 1.10 +--- etc/etc.mvmeppc/MAKEDEV 8 Jun 2003 07:40:34 -0000 +*************** +*** 73,78 **** +--- 73,79 ---- + # audio* audio + # ch* SCSI media changer + # bpf* Berkeley Packet Filter ++ # ipl IP Filter + # tun* network tunnel driver + # lkm loadable kernel modules interface + # *random inkernal random data source +*************** +*** 156,162 **** + sh $this ttyC0 ttyCcfg + sh $this tty00 tty01 tty02 tty03 pty0 pty1 + sh $this bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 +! sh $this pf tun0 tun1 tun2 tun3 + sh $this audio0 + sh $this random uk0 uk1 ss0 ss1 + sh $this wscons +--- 157,163 ---- + sh $this ttyC0 ttyCcfg + sh $this tty00 tty01 tty02 tty03 pty0 pty1 + sh $this bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 +! sh $this ipl pf tun0 tun1 tun2 tun3 + sh $this audio0 + sh $this random uk0 uk1 ss0 ss1 + sh $this wscons +*************** +*** 522,527 **** +--- 523,538 ---- + rm -f bpf${unit} + mknod bpf${unit} c 22 ${unit} + chown root.wheel bpf${unit} ++ ;; ++ ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 44 0 ++ mknod ipnat c 44 1 ++ mknod ipstate c 44 2 ++ mknod ipauth c 44 3 ++ chown root.wheel ipl ipnat ipstate ipauth ++ chmod 600 ipl ipnat ipstate ipauth + ;; + + pf) +Index: etc/etc.sparc/MAKEDEV +=================================================================== +RCS file: /cvs/src/etc/etc.sparc/MAKEDEV,v +retrieving revision 1.106 +diff -c -r1.106 MAKEDEV +*** etc/etc.sparc/MAKEDEV 6 Jan 2003 17:19:59 -0000 1.106 +--- etc/etc.sparc/MAKEDEV 8 Jun 2003 07:40:34 -0000 +*************** +*** 67,72 **** +--- 67,73 ---- + # audio* audio device + # openprom + # bpf* Berkeley Packet Filter ++ # ipl IP Filter + # pf* Packet Filter + # lkm loadable kernel modules interface + # tun* network tunnel driver +*************** +*** 288,293 **** +--- 289,301 ---- + M lkm c 112 0 640 _lkm + ;; + ++ ipl) ++ M ipl c 60 0 600 ++ M ipnat c 60 1 600 ++ M ipstate c 60 2 600 ++ M ipauth c 60 3 600 ++ ;; ++ + pf*) + M pf c 59 0 600 + ;; +*************** +*** 474,479 **** +--- 482,488 ---- + R fd0F fd0G fd0H xfs0 ss0 ss1 ch0 ses0 cuaa cuab cuac cuad + R ttya ttyb ttyc ttyd wscons audio0 uk0 random lkm pf systrace + R xd0 xd1 xd2 xd3 raid0 raid1 raid2 raid3 std st0 st1 fd ++ R ipl + ;; + + xd*|xy*|sd*|raid*|ccd*) +Index: etc/etc.sparc/MAKEDEV.md +=================================================================== +RCS file: /cvs/src/etc/etc.sparc/MAKEDEV.md,v +retrieving revision 1.16 +diff -c -r1.16 MAKEDEV.md +*** etc/etc.sparc/MAKEDEV.md 5 Dec 2002 04:30:21 -0000 1.16 +--- etc/etc.sparc/MAKEDEV.md 8 Jun 2003 07:40:34 -0000 +*************** +*** 92,97 **** +--- 92,101 ---- + _DEV(oppr) + _DEV(bpf, 105) + _DEV(pf, 59) ++ _DEV(ipl, 60) ++ _DEV(ipnat, 60) ++ _DEV(ipstate, 60) ++ _DEV(ipauth, 60) + _DEV(lkm, 112) + _DEV(tun, 111) + _DEV(rnd, 119) +Index: etc/etc.sparc64/MAKEDEV +=================================================================== +RCS file: /cvs/src/etc/etc.sparc64/MAKEDEV,v +retrieving revision 1.78 +diff -c -r1.78 MAKEDEV +*** etc/etc.sparc64/MAKEDEV 6 Jan 2003 17:19:59 -0000 1.78 +--- etc/etc.sparc64/MAKEDEV 8 Jun 2003 07:40:35 -0000 +*************** +*** 84,89 **** +--- 84,90 ---- + # ss* SCSI scanners + # uk* SCSI Unknown device + # audio* audio device ++ # ipl IP Filter + # pf* Packet Filter + # bpf* Berkeley Packet Filter + # tun* network tunnel driver +*************** +*** 317,322 **** +--- 318,330 ---- + M bpf$U c 105 $U 600 + ;; + ++ ipl) ++ M ipl c 82 0 600 ++ M ipnat c 82 1 600 ++ M ipstate c 82 2 600 ++ M ipauth c 82 3 600 ++ ;; ++ + pf*) + M pf c 73 0 600 + ;; +*************** +*** 561,567 **** + R ccd3 wscons pci usbs audio0 uk0 random lpa0 lpa1 lpa2 lpt0 + R lpt1 lpt2 lkm tty00 tty01 tty02 tty03 ttyh0 ttyh1 crypto pf + R systrace wd0 wd1 wd2 wd3 raid0 raid1 raid2 raid3 std st0 st1 +! R fd + ;; + + wd*|sd*|raid*|ccd*) +--- 569,575 ---- + R ccd3 wscons pci usbs audio0 uk0 random lpa0 lpa1 lpa2 lpt0 + R lpt1 lpt2 lkm tty00 tty01 tty02 tty03 ttyh0 ttyh1 crypto pf + R systrace wd0 wd1 wd2 wd3 raid0 raid1 raid2 raid3 std st0 st1 +! R ipl fd + ;; + + wd*|sd*|raid*|ccd*) +Index: etc/etc.sparc64/MAKEDEV.md +=================================================================== +RCS file: /cvs/src/etc/etc.sparc64/MAKEDEV.md,v +retrieving revision 1.25 +diff -c -r1.25 MAKEDEV.md +*** etc/etc.sparc64/MAKEDEV.md 5 Dec 2002 04:30:21 -0000 1.25 +--- etc/etc.sparc64/MAKEDEV.md 8 Jun 2003 07:40:36 -0000 +*************** +*** 104,109 **** +--- 104,113 ---- + _DEV(uk, 60) + _DEV(au, 69) + _DEV(pf, 73) ++ _DEV(ipl, 82) ++ _DEV(ipstate, 82) ++ _DEV(ipnat, 82) ++ _DEV(ipauth, 82) + _DEV(bpf, 105) + _DEV(tun, 111) + _DEV(lkm, 112) +Index: etc/etc.vax/MAKEDEV +=================================================================== +RCS file: /cvs/src/etc/etc.vax/MAKEDEV,v +retrieving revision 1.50 +diff -c -r1.50 MAKEDEV +*** etc/etc.vax/MAKEDEV 6 Jan 2003 05:57:40 -0000 1.50 +--- etc/etc.vax/MAKEDEV 8 Jun 2003 07:40:37 -0000 +*************** +*** 56,61 **** +--- 56,62 ---- + # qv* qvss (microvax) display + # lkm loadable kernel modules + # bpf* berkeley packet filter ++ # ipl IP Filter + # tun* network tunnel device + # ss* SCSI scanner + # uk* SCSI unknown +*************** +*** 78,83 **** +--- 79,85 ---- + sh $0 dz0 dl0 dhu0 rx0 rx1 raid0 raid1 raid2 raid3 + sh $0 ttyg0 ttyg1 ttyg2 ttyg3 + sh $0 crl std-extra systrace ++ sh $0 ipl + ;; + + floppy) +*************** +*** 615,620 **** +--- 617,632 ---- + mknod bpf$unit c 56 $unit + chmod 600 bpf$unit + chown root.wheel bpf$unit ++ ;; ++ ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 47 0 ++ mknod ipnat c 47 1 ++ mknod ipstate c 47 2 ++ mknod ipauth c 47 3 ++ chown root.wheel ipl ipnat ipstate ipauth ++ chmod 600 ipl ipnat ipstate ipauth + ;; + + qd*) +Index: etc/etc.vax/MAKEDEV.md +=================================================================== +RCS file: /cvs/src/etc/etc.vax/MAKEDEV.md,v +retrieving revision 1.12 +diff -c -r1.12 MAKEDEV.md +*** etc/etc.vax/MAKEDEV.md 5 Dec 2002 04:30:21 -0000 1.12 +--- etc/etc.vax/MAKEDEV.md 8 Jun 2003 07:40:37 -0000 +*************** +*** 151,156 **** +--- 151,160 ---- + _DEV(oppr) + _DEV(bpf, 56) + _DEV(pf, 42) ++ _DEV(ipl, 47) ++ _DEV(ipstate, 47) ++ _DEV(ipnat, 47) ++ _DEV(ipauth, 47) + _DEV(lkm, 28) + _DEV(tun, 57) + _DEV(rnd, 67) diff --git a/OpenBSD-3/3.3-rc-diffs b/OpenBSD-3/3.3-rc-diffs new file mode 100644 index 0000000000000..415642b449838 --- /dev/null +++ b/OpenBSD-3/3.3-rc-diffs @@ -0,0 +1,91 @@ +diff -c tmp/etc/netstart etc/netstart +*** tmp/etc/netstart 16 Feb 2003 23:25:40 -0000 1.86 +--- etc/netstart 8 Jun 2003 07:40:21 -0000 +*************** +*** 181,186 **** +--- 181,196 ---- + domainname `cat /etc/defaultdomain` + fi + ++ # Configure the IP filter before configuring network interfaces ++ if [ X"${ipfilter}" = X"YES" -a -f "${ipfilter_rules}" ]; then ++ echo 'configuring IP filter' ++ ipf -Fa -f ${ipfilter_rules} ++ ipfresync="ipf -y" ++ else ++ ipfilter=NO ++ ipfresync=NO ++ fi ++ + # Set the address for the loopback interface. + # It will also initialize IPv6 address for lo0 (::1 and others). + ifconfig lo0 inet localhost +*************** +*** 337,339 **** +--- 347,362 ---- + + bridgestart $if + done ++ ++ # Configure NAT after configuring network interfaces ++ if [ "${ipnat}" = "YES" -a "${ipfilter}" = "YES" -a -f "${ipnat_rules}" ]; then ++ echo 'configuring NAT' ++ ipnat -CF -f ${ipnat_rules} ++ else ++ ipnat=NO ++ fi ++ ++ # Interfaces have come up so we should do an ipf -y if we're using IP filter. ++ if [ "${ipfresync}" != "NO" ]; then ++ ${ipfresync} ++ fi +diff -c tmp/etc/rc etc/rc +*** tmp/etc/rc 23 Mar 2003 18:45:34 -0000 1.225 +--- etc/rc 8 Jun 2003 07:40:22 -0000 +*************** +*** 220,225 **** +--- 220,229 ---- + echo 'starting named'; named $named_flags + fi + ++ if [ X"${ipfilter}" = X"YES" -a X"${ipmon_flags}" != X"NO" ]; then ++ echo 'starting ipmon'; ipmon ${ipmon_flags} ++ fi ++ + # $isakmpd_flags is imported from /etc/rc.conf; + # If $isakmpd_flags == NO or /etc/isakmpd/isakmpd.policy doesn't exist, then + # isakmpd isn't run. +diff -c tmp/etc/rc.conf etc/rc.conf +*** tmp/etc/rc.conf 10 Mar 2003 01:05:28 -0000 1.86 +--- etc/rc.conf 8 Jun 2003 07:40:24 -0000 +*************** +*** 52,58 **** + lockd=NO + gated=NO + amd=NO +! pf=NO # Packet filter / NAT + portmap=NO # Note: inetd(8) rpc services need portmap too + inetd=YES # almost always needed + check_quotas=YES # NO may be desirable in some YP environments +--- 52,60 ---- + lockd=NO + gated=NO + amd=NO +! ipfilter=NO # To enable ipfilter, set to YES +! ipnat=NO # for "YES", ipfilter must also be "YES" +! pf=NO # Enable pf(4) Packet filter / NAT + portmap=NO # Note: inetd(8) rpc services need portmap too + inetd=YES # almost always needed + check_quotas=YES # NO may be desirable in some YP environments +*************** +*** 76,81 **** +--- 78,86 ---- + nfsd_flags="-tun 4" # Crank the 4 for a busy NFS fileserver + amd_dir=/tmp_mnt # AMD's mount directory + amd_master=/etc/amd/master # AMD 'master' map ++ ipfilter_rules=/etc/ipf.rules # Rules for IP packet filtering with IP Filter ++ ipnat_rules=/etc/ipnat.rules # Rules for Network Address Translation ++ ipmon_flags=-Ds # To disable logging, use ipmon_flags=NO + syslogd_flags= # add more flags, ie. "-u -a /chroot/dev/log" + pf_rules=/etc/pf.conf # Packet filter rules file + pflogd_flags= # add more flags, ie. "-s 256" diff --git a/OpenBSD-3/3.3-sys-diffs b/OpenBSD-3/3.3-sys-diffs new file mode 100644 index 0000000000000..691225b9b7b4f --- /dev/null +++ b/OpenBSD-3/3.3-sys-diffs @@ -0,0 +1,1015 @@ +diff -cr sys/arch/alpha/alpha/conf.c sys.ipf/arch/alpha/alpha/conf.c +*** sys/arch/alpha/alpha/conf.c Thu Dec 5 13:49:55 2002 +--- sys.ipf/arch/alpha/alpha/conf.c Thu May 1 15:38:04 2003 +*************** +*** 107,112 **** +--- 107,117 ---- + #include "lpt.h" + cdev_decl(lpt); + cdev_decl(prom); /* XXX XXX XXX */ ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif + cdev_decl(wd); + cdev_decl(fd); + #include "cy.h" +*************** +*** 177,183 **** + cdev_midi_init(NMIDI,midi), /* 41: MIDI I/O */ + cdev_midi_init(NSEQUENCER,sequencer), /* 42: sequencer I/O */ + cdev_disk_init(NRAID,raid), /* 43: RAIDframe disk driver */ +! cdev_notdef(), /* 44 */ + cdev_usb_init(NUSB,usb), /* 45: USB controller */ + cdev_usbdev_init(NUHID,uhid), /* 46: USB generic HID */ + cdev_ulpt_init(NULPT,ulpt), /* 47: USB printer */ +--- 182,188 ---- + cdev_midi_init(NMIDI,midi), /* 41: MIDI I/O */ + cdev_midi_init(NSEQUENCER,sequencer), /* 42: sequencer I/O */ + cdev_disk_init(NRAID,raid), /* 43: RAIDframe disk driver */ +! cdev_gen_ipf(NIPF,ipl), /* 44: IP filter log */ + cdev_usb_init(NUSB,usb), /* 45: USB controller */ + cdev_usbdev_init(NUHID,uhid), /* 46: USB generic HID */ + cdev_ulpt_init(NULPT,ulpt), /* 47: USB printer */ +diff -cr sys/arch/hp300/hp300/conf.c sys.ipf/arch/hp300/hp300/conf.c +*** sys/arch/hp300/hp300/conf.c Thu Dec 5 13:49:55 2002 +--- sys.ipf/arch/hp300/hp300/conf.c Thu May 1 15:38:23 2003 +*************** +*** 126,131 **** +--- 126,137 ---- + cdev_decl(xfs_dev); + #endif + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include "systrace.h" +*************** +*** 169,175 **** + cdev_disk_init(NRD,rd), /* 34: RAM disk */ + cdev_tty_init(NAPCI,apci), /* 35: Apollo APCI UARTs */ + cdev_ksyms_init(NKSYMS,ksyms), /* 36: Kernel symbols device */ +! cdev_notdef(), /* 37 */ + cdev_notdef(), /* 38 */ + cdev_notdef(), /* 39 */ + cdev_notdef(), /* 40 */ +--- 175,181 ---- + cdev_disk_init(NRD,rd), /* 34: RAM disk */ + cdev_tty_init(NAPCI,apci), /* 35: Apollo APCI UARTs */ + cdev_ksyms_init(NKSYMS,ksyms), /* 36: Kernel symbols device */ +! cdev_pf_init(NIPF,ipl), /* 37: packet filter */ + cdev_notdef(), /* 38 */ + cdev_notdef(), /* 39 */ + cdev_notdef(), /* 40 */ +diff -cr sys/arch/hppa/hppa/conf.c sys.ipf/arch/hppa/hppa/conf.c +*** sys/arch/hppa/hppa/conf.c Sat Feb 8 23:34:27 2003 +--- sys.ipf/arch/hppa/hppa/conf.c Thu May 1 15:38:24 2003 +*************** +*** 111,116 **** +--- 111,122 ---- + #include "com.h" + cdev_decl(com); + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include "systrace.h" +*************** +*** 161,166 **** +--- 167,173 ---- + cdev_audio_init(NAUDIO,audio), /* 35: /dev/audio */ + cdev_crypto_init(NCRYPTO,crypto), /* 36: /dev/crypto */ + cdev_ses_init(NSES,ses), /* 37: SCSI SES/SAF-TE */ ++ cdev_gen_ipf(NIPF,ipl), /* 38: ip filtering */ + cdev_lkm_dummy(), + cdev_lkm_dummy(), + cdev_lkm_dummy(), +diff -cr sys/arch/i386/i386/conf.c sys.ipf/arch/i386/i386/conf.c +*** sys/arch/i386/i386/conf.c Thu Dec 5 13:49:55 2002 +--- sys.ipf/arch/i386/i386/conf.c Thu May 1 15:38:24 2003 +*************** +*** 188,193 **** +--- 188,199 ---- + #include "radio.h" + #include "gpr.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + /* XXX -- this needs to be supported by config(8)! */ + #if (NCOM > 0) && (NPCCOM > 0) + #error com and pccom are mutually exclusive. Sorry. +*************** +*** 311,317 **** + cdev_usbdev_init(NUSCANNER,uscanner), /* 77: USB scanners */ + cdev_systrace_init(NSYSTRACE,systrace), /* 78: system call tracing */ + cdev_oci_init(NBIO,bio), /* 79: ioctl tunnel */ +! cdev_ch_init(NGPR,gpr) /* 80: GPR400 SmartCard reader */ + }; + int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]); + +--- 317,325 ---- + cdev_usbdev_init(NUSCANNER,uscanner), /* 77: USB scanners */ + cdev_systrace_init(NSYSTRACE,systrace), /* 78: system call tracing */ + cdev_oci_init(NBIO,bio), /* 79: ioctl tunnel */ +! cdev_ch_init(NGPR,gpr), /* 80: GPR400 SmartCard reader */ +! cdev_gen_ipf(NIPF,ipl) /* 81: ip filtering */ +! + }; + int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]); + +diff -cr sys/arch/mac68k/mac68k/conf.c sys.ipf/arch/mac68k/mac68k/conf.c +*** sys/arch/mac68k/mac68k/conf.c Thu Dec 5 13:49:55 2002 +--- sys.ipf/arch/mac68k/mac68k/conf.c Thu May 1 15:38:24 2003 +*************** +*** 108,113 **** +--- 108,119 ---- + cdev_decl(xfs_dev); + #endif + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include "systrace.h" +*************** +*** 152,158 **** + cdev_pf_init(NPF,pf), /* 35: packet filter */ + cdev_audio_init(NASC,asc), /* 36: ASC audio device */ + cdev_ksyms_init(NKSYMS,ksyms), /* 37: Kernel symbols device */ +! cdev_notdef(), /* 38 */ + cdev_notdef(), /* 39 */ + cdev_notdef(), /* 40 */ + cdev_notdef(), /* 41 */ +--- 158,164 ---- + cdev_pf_init(NPF,pf), /* 35: packet filter */ + cdev_audio_init(NASC,asc), /* 36: ASC audio device */ + cdev_ksyms_init(NKSYMS,ksyms), /* 37: Kernel symbols device */ +! cdev_gen_ipf(NIPF,ipl), /* 38: IP filter log */ + cdev_notdef(), /* 39 */ + cdev_notdef(), /* 40 */ + cdev_notdef(), /* 41 */ +diff -cr sys/arch/macppc/macppc/conf.c sys.ipf/arch/macppc/macppc/conf.c +*** sys/arch/macppc/macppc/conf.c Thu Dec 5 13:49:55 2002 +--- sys.ipf/arch/macppc/macppc/conf.c Thu May 1 15:38:24 2003 +*************** +*** 105,110 **** +--- 105,116 ---- + + #include "tun.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #ifdef XFS + #include <xfs/nxfs.h> + cdev_decl(xfs_dev); +*************** +*** 191,197 **** + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ + cdev_audio_init(NAUDIO,audio), /* 44: generic audio I/O */ +! cdev_notdef(), /* 45 */ + cdev_notdef(), /* 46 */ + cdev_crypto_init(NCRYPTO,crypto), /* 47: /dev/crypto */ + cdev_notdef(), /* 48 */ +--- 197,203 ---- + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ + cdev_audio_init(NAUDIO,audio), /* 44: generic audio I/O */ +! cdev_gen_ipf(NIPF,ipl), /* 45: IP filter */ + cdev_notdef(), /* 46 */ + cdev_crypto_init(NCRYPTO,crypto), /* 47: /dev/crypto */ + cdev_notdef(), /* 48 */ +diff -cr sys/arch/mvme68k/mvme68k/conf.c sys.ipf/arch/mvme68k/mvme68k/conf.c +*** sys/arch/mvme68k/mvme68k/conf.c Thu Dec 5 13:49:55 2002 +--- sys.ipf/arch/mvme68k/mvme68k/conf.c Thu May 1 15:38:24 2003 +*************** +*** 158,163 **** +--- 158,169 ---- + #include "bpfilter.h" + #include "tun.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include "systrace.h" +*************** +*** 212,218 **** + cdev_uk_init(NUK,uk), /* 41: unknown SCSI */ + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ +! cdev_lkm_dummy(), /* 44 */ + cdev_lkm_dummy(), /* 45 */ + cdev_lkm_dummy(), /* 46 */ + cdev_lkm_dummy(), /* 47 */ +--- 218,224 ---- + cdev_uk_init(NUK,uk), /* 41: unknown SCSI */ + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ +! cdev_gen_ipf(NIPF,ipl), /* 44: IP filter */ + cdev_lkm_dummy(), /* 45 */ + cdev_lkm_dummy(), /* 46 */ + cdev_lkm_dummy(), /* 47 */ +diff -cr sys/arch/mvme88k/mvme88k/conf.c sys.ipf/arch/mvme88k/mvme88k/conf.c +*** sys/arch/mvme88k/mvme88k/conf.c Thu Dec 5 13:49:55 2002 +--- sys.ipf/arch/mvme88k/mvme88k/conf.c Thu May 1 15:38:25 2003 +*************** +*** 101,106 **** +--- 101,112 ---- + cdev_decl(lptwo); + #endif /* notyet */ + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include "systrace.h" +*************** +*** 187,193 **** + cdev_lkm_dummy(), /* 38 */ + cdev_pf_init(NPF,pf), /* 39: packet filter */ + cdev_random_init(1,random), /* 40: random data source */ +! cdev_notdef(), /* 41 */ + cdev_notdef(), /* 42 */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ + cdev_notdef(), /* 44 */ +--- 193,199 ---- + cdev_lkm_dummy(), /* 38 */ + cdev_pf_init(NPF,pf), /* 39: packet filter */ + cdev_random_init(1,random), /* 40: random data source */ +! cdev_gen_ipf(NIPF,ipl), /* 41: IP filter */ + cdev_notdef(), /* 42 */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ + cdev_notdef(), /* 44 */ +diff -cr sys/arch/mvmeppc/mvmeppc/conf.c sys.ipf/arch/mvmeppc/mvmeppc/conf.c +*** sys/arch/mvmeppc/mvmeppc/conf.c Thu Dec 5 13:49:55 2002 +--- sys.ipf/arch/mvmeppc/mvmeppc/conf.c Thu May 1 15:38:25 2003 +*************** +*** 114,119 **** +--- 114,125 ---- + + #include "ksyms.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include "systrace.h" +*************** +*** 167,173 **** + cdev_uk_init(NUK,uk), /* 41: unknown SCSI */ + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ +! cdev_notdef(), /* 44 */ + cdev_notdef(), /* 45 */ + cdev_notdef(), /* 46 */ + cdev_notdef(), /* 47 */ +--- 173,179 ---- + cdev_uk_init(NUK,uk), /* 41: unknown SCSI */ + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ +! cdev_gen_ipf(NIPF,ipl), /* 44: IP filter */ + cdev_notdef(), /* 45 */ + cdev_notdef(), /* 46 */ + cdev_notdef(), /* 47 */ +diff -cr sys/arch/sparc/sparc/conf.c sys.ipf/arch/sparc/sparc/conf.c +*** sys/arch/sparc/sparc/conf.c Thu Dec 5 13:49:55 2002 +--- sys.ipf/arch/sparc/sparc/conf.c Thu May 1 15:38:25 2003 +*************** +*** 126,131 **** +--- 126,137 ---- + }; + int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]); + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include "systrace.h" +*************** +*** 196,202 **** + cdev_notdef(), /* 57 */ + cdev_disk_init(NCD,cd), /* 58: SCSI CD-ROM */ + cdev_pf_init(NPF,pf), /* 59: packet filter */ +! cdev_notdef(), /* 60 */ + cdev_notdef(), /* 61 */ + cdev_notdef(), /* 62 */ + cdev_notdef(), /* 63 */ +--- 202,208 ---- + cdev_notdef(), /* 57 */ + cdev_disk_init(NCD,cd), /* 58: SCSI CD-ROM */ + cdev_pf_init(NPF,pf), /* 59: packet filter */ +! cdev_gen_ipf(NIPF,ipl), /* 60: ip filtering log */ + cdev_notdef(), /* 61 */ + cdev_notdef(), /* 62 */ + cdev_notdef(), /* 63 */ +diff -cr sys/arch/sparc64/sparc64/conf.c sys.ipf/arch/sparc64/sparc64/conf.c +*** sys/arch/sparc64/sparc64/conf.c Thu Dec 5 13:49:55 2002 +--- sys.ipf/arch/sparc64/sparc64/conf.c Thu May 1 15:38:25 2003 +*************** +*** 114,119 **** +--- 114,125 ---- + #include "ucom.h" + #include "uscanner.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #ifdef XFS +*************** +*** 250,256 **** + cdev_mouse_init(NWSKBD, wskbd), /* 79: keyboards */ + cdev_mouse_init(NWSMOUSE, wsmouse), /* 80: mice */ + cdev_mouse_init(NWSMUX, wsmux), /* 81: ws multiplexor */ +! cdev_notdef(), /* 82 */ + cdev_notdef(), /* 83 */ + cdev_notdef(), /* 84 */ + cdev_notdef(), /* 85 */ +--- 256,262 ---- + cdev_mouse_init(NWSKBD, wskbd), /* 79: keyboards */ + cdev_mouse_init(NWSMOUSE, wsmouse), /* 80: mice */ + cdev_mouse_init(NWSMUX, wsmux), /* 81: ws multiplexor */ +! cdev_gen_ipf(NIPF,ipl), /* 82: IP filter */ + cdev_notdef(), /* 83 */ + cdev_notdef(), /* 84 */ + cdev_notdef(), /* 85 */ +diff -cr sys/arch/vax/vax/conf.c sys.ipf/arch/vax/vax/conf.c +*** sys/arch/vax/vax/conf.c Thu Dec 5 13:49:55 2002 +--- sys.ipf/arch/vax/vax/conf.c Thu May 1 15:38:28 2003 +*************** +*** 357,362 **** +--- 357,368 ---- + #include "wskbd.h" + #include "wsmouse.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include "systrace.h" +*************** +*** 410,416 **** + cdev_notdef(), /* 44 was Datakit */ + cdev_notdef(), /* 45 was Datakit */ + cdev_notdef(), /* 46 was Datakit */ +! cdev_notdef(), /* 47 */ + cdev_notdef(), /* 48 */ + cdev_systrace_init(NSYSTRACE,systrace), /* 49: system call tracing */ + cdev_ksyms_init(NKSYMS,ksyms), /* 50: Kernel symbols device */ +--- 416,422 ---- + cdev_notdef(), /* 44 was Datakit */ + cdev_notdef(), /* 45 was Datakit */ + cdev_notdef(), /* 46 was Datakit */ +! cdev_gen_ipf(NIPF,ipl), /* 47: IP filter */ + cdev_notdef(), /* 48 */ + cdev_systrace_init(NSYSTRACE,systrace), /* 49: system call tracing */ + cdev_ksyms_init(NKSYMS,ksyms), /* 50: Kernel symbols device */ +diff -cr sys/conf/GENERIC sys.ipf/conf/GENERIC +*** sys/conf/GENERIC Sat Mar 1 10:44:46 2003 +--- sys.ipf/conf/GENERIC Thu May 1 15:38:28 2003 +*************** +*** 72,77 **** +--- 72,79 ---- + #option EON # OSI tunneling over IP + #option NETATALK # AppleTalk + #option CCITT,LLC,HDLC # X.25 ++ option IPFILTER # IP packet filter for security ++ option IPFILTER_LOG # use /dev/ipl to log IPF + option PPP_BSDCOMP # PPP BSD compression + option PPP_DEFLATE + #option MROUTING # Multicast router +diff -cr sys/conf/files sys.ipf/conf/files +*** sys/conf/files Thu Feb 27 07:25:49 2003 +--- sys.ipf/conf/files Thu May 1 15:38:28 2003 +*************** +*** 678,683 **** +--- 678,691 ---- + file netinet/tcp_usrreq.c inet + file netinet/udp_usrreq.c inet + file netinet/ip_gre.c inet ++ file netinet/ip_fil.c ipfilter ++ file netinet/fil.c ipfilter ++ file netinet/ip_nat.c ipfilter ++ file netinet/ip_frag.c ipfilter ++ file netinet/ip_state.c ipfilter ++ file netinet/ip_proxy.c ipfilter ++ file netinet/ip_auth.c ipfilter ++ file netinet/ip_log.c ipfilter + file netinet/ip_ipsp.c (inet | inet6) & (ipsec | tcp_signature) + file netinet/ip_spd.c (inet | inet6) & (ipsec | tcp_signature) + file netinet/ip_ipip.c inet | inet6 +diff -cr sys/net/bridgestp.c sys.ipf/net/bridgestp.c +*** sys/net/bridgestp.c Wed Dec 11 00:22:55 2002 +--- sys.ipf/net/bridgestp.c Thu May 1 15:38:29 2003 +*************** +*** 63,68 **** +--- 63,73 ---- + #include <netinet/in_var.h> + #include <netinet/ip.h> + #include <netinet/if_ether.h> ++ ++ #ifdef IPFILTER ++ #include <netinet/ip_compat.h> ++ #include <netinet/ip_fil.h> ++ #endif + #endif + + #if NBPFILTER > 0 +diff -cr sys/net/if.c sys.ipf/net/if.c +*** sys/net/if.c Wed Sep 11 15:38:47 2002 +--- sys.ipf/net/if.c Thu May 1 15:38:29 2003 +*************** +*** 101,106 **** +--- 101,112 ---- + #include <netinet6/nd6.h> + #endif + ++ #ifdef IPFILTER ++ #include <netinet/ip_compat.h> ++ #include <netinet/ip_fil.h> ++ #include <netinet/ip_nat.h> ++ #endif ++ + #if NBPFILTER > 0 + #include <net/bpf.h> + #endif +*************** +*** 468,473 **** +--- 474,484 ---- + + /* Remove the interface from the list of all interfaces. */ + TAILQ_REMOVE(&ifnet, ifp, if_list); ++ ++ #ifdef IPFILTER ++ /* XXX More ipf & ipnat cleanup needed. */ ++ frsync(ifp); ++ #endif + + /* + * Deallocate private resources. +diff -cr sys/net/if_bridge.c sys.ipf/net/if_bridge.c +*** sys/net/if_bridge.c 11 Mar 2003 16:06:25 -0000 +--- sys.ipf/net/if_bridge.c 18 Jun 2003 13:01:48 -0000 +*************** +*** 71,76 **** +--- 71,80 ---- + #include <netinet/ip_ipsp.h> + + #include <net/if_enc.h> ++ #if (defined(IPFILTER) || defined(IPFILTER_LKM)) ++ #include <netinet/ip_compat.h> ++ #include <netinet/ip_fil.h> ++ #endif + #endif + + #ifdef INET6 +*************** +*** 159,165 **** + int bridge_flushrule(struct bridge_iflist *); + int bridge_brlconf(struct bridge_softc *, struct ifbrlconf *); + u_int8_t bridge_filterrule(struct brl_head *, struct ether_header *); +! #if NPF > 0 + struct mbuf *bridge_filter(struct bridge_softc *, int, struct ifnet *, + struct ether_header *, struct mbuf *m); + #endif +--- 163,169 ---- + int bridge_flushrule(struct bridge_iflist *); + int bridge_brlconf(struct bridge_softc *, struct ifbrlconf *); + u_int8_t bridge_filterrule(struct brl_head *, struct ether_header *); +! #if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + struct mbuf *bridge_filter(struct bridge_softc *, int, struct ifnet *, + struct ether_header *, struct mbuf *m); + #endif +*************** +*** 1175,1181 **** + m_freem(m); + return; + } +! #if NPF > 0 + m = bridge_filter(sc, BRIDGE_IN, src_if, &eh, m); + if (m == NULL) + return; +--- 1179,1185 ---- + m_freem(m); + return; + } +! #if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + m = bridge_filter(sc, BRIDGE_IN, src_if, &eh, m); + if (m == NULL) + return; +*************** +*** 1218,1224 **** + m_freem(m); + return; + } +! #if NPF > 0 + m = bridge_filter(sc, BRIDGE_OUT, dst_if, &eh, m); + if (m == NULL) + return; +--- 1222,1228 ---- + m_freem(m); + return; + } +! #if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + m = bridge_filter(sc, BRIDGE_OUT, dst_if, &eh, m); + if (m == NULL) + return; +*************** +*** 1472,1478 **** + mc = m1; + } + +! #if NPF > 0 + mc = bridge_filter(sc, BRIDGE_OUT, dst_if, eh, mc); + if (mc == NULL) + continue; +--- 1476,1482 ---- + mc = m1; + } + +! #if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + mc = bridge_filter(sc, BRIDGE_OUT, dst_if, eh, mc); + if (mc == NULL) + continue; +*************** +*** 2260,2265 **** +--- 2264,2275 ---- + * We don't need to do loop detection, the + * bridge will do that for us. + */ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (dir == BRIDGE_OUT && fr_checkp && ++ ((*fr_checkp)(ip, hlen, &encif[0].sc_if, ++ 1, &m) || !m)) ++ return 1; ++ #endif + #if NPF > 0 + switch (af) { + #ifdef INET +*************** +*** 2284,2289 **** +--- 2294,2305 ---- + if (m == NULL) + return (1); + #endif /* NPF */ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (dir == BRIDGE_IN && fr_checkp && ++ ((*fr_checkp)(ip, hlen, &encif[0].sc_if, ++ 0, &m) || !m)) ++ return 1; ++ #endif + #ifdef INET + if (af == AF_INET) { + ip = mtod(m, struct ip *); +*************** +*** 2302,2308 **** + } + #endif /* IPSEC */ + +! #if NPF > 0 + /* + * Filter IP packets by peeking into the ethernet frame. This violates + * the ISO model, but allows us to act as a IP filter at the data link +--- 2318,2324 ---- + } + #endif /* IPSEC */ + +! #if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + /* + * Filter IP packets by peeking into the ethernet frame. This violates + * the ISO model, but allows us to act as a IP filter at the data link +*************** +*** 2412,2425 **** + return (NULL); + #endif /* IPSEC */ + +! #if NPF > 0 + /* Finally, we get to filter the packet! */ + m->m_pkthdr.rcvif = ifp; + if (pf_test(dir, ifp, &m) != PF_PASS) + goto dropit; + if (m == NULL) + goto dropit; + #endif /* NPF */ + + /* Rebuild the IP header */ + if (m->m_len < hlen && ((m = m_pullup(m, hlen)) == NULL)) +--- 2428,2459 ---- + return (NULL); + #endif /* IPSEC */ + +! #if defined(IPFILTER) || defined(IPFILTER_LKM) || (NPF > 0) + /* Finally, we get to filter the packet! */ + m->m_pkthdr.rcvif = ifp; ++ #endif ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (dir == BRIDGE_OUT) { ++ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 1, &m)) ++ goto dropit; ++ if (m == NULL) ++ goto dropit; ++ } ++ #endif ++ #if NPF > 0 + if (pf_test(dir, ifp, &m) != PF_PASS) + goto dropit; + if (m == NULL) + goto dropit; + #endif /* NPF */ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (dir == BRIDGE_IN) { ++ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 0, &m)) ++ goto dropit; ++ if (m == NULL) ++ goto dropit; ++ } ++ #endif + + /* Rebuild the IP header */ + if (m->m_len < hlen && ((m = m_pullup(m, hlen)) == NULL)) +*************** +*** 2463,2474 **** +--- 2497,2524 ---- + return (NULL); + #endif /* IPSEC */ + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (dir == BRIDGE_OUT) { ++ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 1, &m)) ++ goto dropit; ++ if (m == NULL) ++ return (NULL); ++ } ++ #endif + #if NPF > 0 + if (pf_test6(dir, ifp, &m) != PF_PASS) + goto dropit; + if (m == NULL) + return (NULL); + #endif /* NPF */ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (dir == BRIDGE_IN) { ++ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 0, &m)) ++ goto dropit; ++ if (m == NULL) ++ return (NULL); ++ } ++ #endif + + break; + } +*************** +*** 2500,2506 **** + m_freem(m); + return (NULL); + } +! #endif /* NPF > 0 */ + + void + bridge_fragment(sc, ifp, eh, m) +--- 2550,2556 ---- + m_freem(m); + return (NULL); + } +! #endif /* (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) */ + + void + bridge_fragment(sc, ifp, eh, m) +diff -cr sys/netinet/in_proto.c sys.ipf/netinet/in_proto.c +*** sys/netinet/in_proto.c Mon Jun 10 02:26:10 2002 +--- sys.ipf/netinet/in_proto.c Thu May 1 15:38:29 2003 +*************** +*** 163,168 **** +--- 163,173 ---- + #include <netinet/ip_mroute.h> + #endif /* MROUTING */ + ++ #ifdef IPFILTER ++ void iplinit __P((void)); ++ #define ip_init iplinit ++ #endif ++ + #ifdef INET6 + #include <netinet6/ip6_var.h> + #endif /* INET6 */ +diff -cr sys/netinet/ip_input.c sys.ipf/netinet/ip_input.c +*** sys/netinet/ip_input.c Thu Feb 13 01:41:07 2003 +--- sys.ipf/netinet/ip_input.c Thu May 1 15:42:00 2003 +*************** +*** 151,156 **** +--- 151,160 ---- + struct in_ifaddrhead in_ifaddr; + struct ifqueue ipintrq; + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif ++ + int ipq_locked; + static __inline int ipq_lock_try(void); + static __inline void ipq_unlock(void); +*************** +*** 404,409 **** +--- 408,430 ---- + ip = mtod(m, struct ip *); + hlen = ip->ip_hl << 2; + pfrdr = (pfrdr != ip->ip_dst.s_addr); ++ #endif ++ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * Check if we want to allow this packet to be processed. ++ * Consider it to be bad if not. ++ */ ++ { ++ struct mbuf *m0 = m; ++ if (fr_checkp && (*fr_checkp)(ip, hlen, m->m_pkthdr.rcvif, 0, &m0)) { ++ return; ++ } ++ if (m0 == 0) { /* in case of 'fastroute' */ ++ return; ++ } ++ ip = mtod(m = m0, struct ip *); ++ } + #endif + + /* +diff -cr sys/netinet/ip_output.c sys.ipf/netinet/ip_output.c +*** sys/netinet/ip_output.c Sat Mar 15 06:08:02 2003 +--- sys.ipf/netinet/ip_output.c Thu May 1 15:38:30 2003 +*************** +*** 86,91 **** +--- 86,95 ---- + static struct mbuf *ip_insertoptions(struct mbuf *, struct mbuf *, int *); + static void ip_mloopback(struct ifnet *, struct mbuf *, struct sockaddr_in *); + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif ++ + /* + * IP output. The packet in mbuf chain m contains a skeletal IP + * header (with len, off, ttl, proto, tos, src, dst). +*************** +*** 559,564 **** +--- 563,592 ---- + if (sproto != 0) { + s = splnet(); + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (fr_checkp) { ++ /* ++ * Ok, it's time for a simple round-trip to the IPF/NAT ++ * code with the enc0 interface. ++ */ ++ struct mbuf *m1 = m; ++ void *ifp = (void *)&encif[0].sc_if; ++ ++ if ((*fr_checkp)(ip, hlen, ifp, 1, &m1)) { ++ error = EHOSTUNREACH; ++ splx(s); ++ goto done; ++ } ++ if (m1 == 0) { /* in case of 'fastroute' */ ++ error = 0; ++ splx(s); ++ goto done; ++ } ++ ip = mtod(m = m1, struct ip *); ++ hlen = ip->ip_hl << 2; ++ } ++ #endif /* IPFILTER */ ++ + /* + * Packet filter + */ +*************** +*** 661,666 **** +--- 689,713 ---- + m->m_pkthdr.csum &= ~M_UDPV4_CSUM_OUT; /* Clear */ + } + } ++ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * looks like most checking has been done now...do a filter check ++ */ ++ { ++ struct mbuf *m1 = m; ++ ++ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 1, &m1)) { ++ error = EHOSTUNREACH; ++ goto done; ++ } ++ if (m1 == 0) { /* in case of 'fastroute' */ ++ error = 0; ++ goto done; ++ } ++ ip = mtod(m = m1, struct ip *); ++ } ++ #endif + + /* + * Packet filter +diff -cr sys/netinet6/ip6_input.c sys.ipf/netinet6/ip6_input.c +*** sys/netinet6/ip6_input.c Tue Jan 7 20:00:34 2003 +--- sys.ipf/netinet6/ip6_input.c Thu May 1 15:38:30 2003 +*************** +*** 134,139 **** +--- 134,143 ---- + static struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int); + #endif + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif ++ + /* + * IP6 initialization: fill in IP6 protocol switch table. + * All protocols not implemented in kernel go to raw IP6 protocol handler. +*************** +*** 251,256 **** +--- 255,280 ---- + in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); + goto bad; + } ++ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * Check if we want to allow this packet to be processed. ++ * Consider it to be bad if not. ++ */ ++ if (fr_checkp != NULL) { ++ struct mbuf *m0 = m; ++ ++ if ((*fr_checkp)((struct ip *)ip6, sizeof(*ip6), ++ m->m_pkthdr.rcvif, 0, &m0)) { ++ return; ++ } ++ m = m0; ++ if (m == 0) { /* in case of 'fastroute' */ ++ return; ++ } ++ ip6 = mtod(m, struct ip6_hdr *); ++ } ++ #endif + + #if NPF > 0 + /* +diff -cr sys/netinet6/ip6_output.c sys.ipf/netinet6/ip6_output.c +*** sys/netinet6/ip6_output.c Fri Nov 1 05:02:27 2002 +--- sys.ipf/netinet6/ip6_output.c Thu May 1 15:38:30 2003 +*************** +*** 120,132 **** + + static int ip6_pcbopts(struct ip6_pktopts **, struct mbuf *, struct socket *); + static int ip6_setmoptions(int, struct ip6_moptions **, struct mbuf *); + static int ip6_getmoptions(int, struct ip6_moptions *, struct mbuf **); + static int ip6_copyexthdr(struct mbuf **, caddr_t, int); + static int ip6_insertfraghdr(struct mbuf *, struct mbuf *, int, + struct ip6_frag **); + static int ip6_insert_jumboopt(struct ip6_exthdrs *, u_int32_t); + static int ip6_splithdr(struct mbuf *, struct ip6_exthdrs *); +! static int ip6_getpmtu(struct route_in6 *, struct route_in6 *, + struct ifnet *, struct in6_addr *, u_long *); + + /* +--- 120,135 ---- + + static int ip6_pcbopts(struct ip6_pktopts **, struct mbuf *, struct socket *); + static int ip6_setmoptions(int, struct ip6_moptions **, struct mbuf *); ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif + static int ip6_getmoptions(int, struct ip6_moptions *, struct mbuf **); + static int ip6_copyexthdr(struct mbuf **, caddr_t, int); + static int ip6_insertfraghdr(struct mbuf *, struct mbuf *, int, + struct ip6_frag **); + static int ip6_insert_jumboopt(struct ip6_exthdrs *, u_int32_t); + static int ip6_splithdr(struct mbuf *, struct ip6_exthdrs *); +! int ip6_getpmtu(struct route_in6 *, struct route_in6 *, + struct ifnet *, struct in6_addr *, u_long *); + + /* +*************** +*** 796,801 **** +--- 799,823 ---- + goto done; + ip6 = mtod(m, struct ip6_hdr *); + #endif ++ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * looks like most checking has been done now...do a filter check ++ */ ++ if (fr_checkp != NULL) { ++ struct mbuf *m1 = m; ++ if ((*fr_checkp)((struct ip *)ip6, sizeof(*ip6), ifp, 1, &m1)) { ++ error = EHOSTUNREACH; ++ goto done; ++ } ++ m = m1; ++ if (m1 == 0) { /* in case of 'fastroute' */ ++ error = 0; ++ goto done; ++ } ++ ip6 = mtod(m, struct ip6_hdr *); ++ } ++ #endif + + /* + * Send the packet to the outgoing interface. +*************** +*** 1120,1126 **** + return (0); + } + +! static int + ip6_getpmtu(ro_pmtu, ro, ifp, dst, mtup) + struct route_in6 *ro_pmtu, *ro; + struct ifnet *ifp; +--- 1142,1148 ---- + return (0); + } + +! int + ip6_getpmtu(ro_pmtu, ro, ifp, dst, mtup) + struct route_in6 *ro_pmtu, *ro; + struct ifnet *ifp; +diff -cr sys/sys/conf.h sys.ipf/sys/conf.h +*** sys/sys/conf.h Sat Nov 9 06:00:37 2002 +--- sys.ipf/sys/conf.h Thu May 1 15:38:30 2003 +*************** +*** 362,367 **** +--- 362,374 ---- + (dev_type_ioctl((*))) enodev, (dev_type_stop((*))) nullop, \ + 0, (dev_type_select((*))) enodev, (dev_type_mmap((*))) enodev } + ++ /* open, close, read, ioctl */ ++ #define cdev_gen_ipf(c, n) { \ ++ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ ++ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ ++ (dev_type_stop((*))) enodev, 0, (dev_type_select((*))) enodev, \ ++ (dev_type_mmap((*))) enodev } ++ + /* open, close, read, write, ioctl, select, nokqfilter */ + #define cdev_xfs_init(c, n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ +*************** +*** 571,576 **** +--- 578,584 ---- + + cdev_decl(bpf); + ++ cdev_decl(ipl); + cdev_decl(pf); + + cdev_decl(tun); diff --git a/OpenBSD-3/3.4-MAKEDEV-diffs b/OpenBSD-3/3.4-MAKEDEV-diffs new file mode 100644 index 0000000000000..5d08117c3421e --- /dev/null +++ b/OpenBSD-3/3.4-MAKEDEV-diffs @@ -0,0 +1,797 @@ +Index: etc/MAKEDEV.mi +=================================================================== +RCS file: /cvs/src/etc/MAKEDEV.mi,v +retrieving revision 1.57 +diff -c -r1.57 MAKEDEV.mi +*** etc/MAKEDEV.mi 16 Mar 2003 13:15:53 -0000 1.57 +--- etc/MAKEDEV.mi 8 Jun 2003 07:40:20 -0000 +*************** +*** 152,157 **** +--- 152,161 ---- + target(all, pctr)dnl + target(all, pctr0)dnl + target(all, pf)dnl ++ target(all, ipl)dnl ++ target(all, ipnat)dnl ++ target(all, ipstate)dnl ++ target(all, ipauth)dnl + twrget(all, cry, crypto)dnl + target(all, apm)dnl + twrget(all, tth, ttyh, 0, 1)dnl +*************** +*** 558,563 **** +--- 562,575 ---- + _mkdev(cry, crypto, {-M crypto c major_cry_c-} 0)dnl + __devitem(pf, pf*, Packet Filter)dnl + _mkdev(pf, {-pf*-}, {-M pf c major_pf_c 0 600-})dnl ++ __devitem(ipl, ipl*, Packet Filter log)dnl ++ _mkdev(ipl, {-ipl*-}, {-M ipl c major_ipl_c 0 600-})dnl ++ __devitem(ipnat, ipnat*, Packet Filter NAT)dnl ++ _mkdev(ipnat, {-ipnat*-}, {-M ipnat c major_ipnat_c 1 600-})dnl ++ __devitem(ipstate, ipstate*, Packet Filter state)dnl ++ _mkdev(ipstate, {-ipstate*-}, {-M ipstate c major_ipstate_c 2 600-})dnl ++ __devitem(ipauth, ipauth*, Packet Filter auth)dnl ++ _mkdev(ipauth, {-ipauth*-}, {-M ipauth c major_ipauth_c 3 600-})dnl + __devitem(bpf, bpf*, Berkeley Packet Filter)dnl + _mkdev(bpf, {-bpf*-}, {-M bpf$U c major_bpf_c $U 600-}, 600)dnl + _mkdev(tun, {-tun*-}, {-M tun$U c major_tun_c $U 600-}, 600)dnl +Index: etc/etc.alpha/MAKEDEV +=================================================================== +RCS file: /cvs/src/etc/etc.alpha/MAKEDEV,v +retrieving revision 1.95 +diff -c -r1.95 MAKEDEV +*** etc/etc.alpha/MAKEDEV 6 Jan 2003 17:19:59 -0000 1.95 +--- etc/etc.alpha/MAKEDEV 8 Jun 2003 07:40:24 -0000 +*************** +*** 71,76 **** +--- 71,77 ---- + # utty* Serial ports + # Special purpose devices: + # ch* SCSI media changer ++ # ipl IP Filter + # pf* Packet Filter + # bpf* Berkeley Packet Filter + # iop* I2O controller device +*************** +*** 330,335 **** +--- 331,343 ---- + M bpf$U c 11 $U 600 + ;; + ++ ipl) ++ M ipl c 44 0 600 ++ M ipnat c 44 1 600 ++ M ipstate c 44 2 600 ++ M ipauth c 44 2 600 ++ ;; ++ + pf*) + M pf c 35 0 600 + ;; +*************** +*** 494,499 **** +--- 502,508 ---- + R tty00 tty01 tty02 tty03 ttyc0 ttyc1 ttyc2 ttyc3 ttyc4 ttyc5 + R ttyc6 ttyc7 ttyB0 ttyB1 ttyB2 ttyB3 ttyB4 ttyB5 pf systrace + R wd0 wd1 wd2 wd3 raid0 raid1 raid2 raid3 std st0 st1 fd ++ R ipl + ;; + + wd*|sd*|raid*|ccd*) +Index: etc/etc.alpha/MAKEDEV.md +=================================================================== +RCS file: /cvs/src/etc/etc.alpha/MAKEDEV.md,v +retrieving revision 1.15 +diff -c -r1.15 MAKEDEV.md +*** etc/etc.alpha/MAKEDEV.md 5 Dec 2002 04:30:21 -0000 1.15 +--- etc/etc.alpha/MAKEDEV.md 8 Jun 2003 07:40:25 -0000 +*************** +*** 66,71 **** +--- 66,75 ---- + _TITLE(spec) + _DEV(ch, 14) + _DEV(pf, 35) ++ _DEV(ipl, 44) ++ _DEV(ipnat, 44) ++ _DEV(ipstate, 44) ++ _DEV(ipauth, 44) + _DEV(bpf, 11) + _DEV(iop, 54) + _DEV(pci, 52) +Index: etc/etc.hp300/MAKEDEV +=================================================================== +RCS file: /cvs/src/etc/etc.hp300/MAKEDEV,v +retrieving revision 1.63 +diff -c -r1.63 MAKEDEV +*** etc/etc.hp300/MAKEDEV 6 Jan 2003 17:19:59 -0000 1.63 +--- etc/etc.hp300/MAKEDEV 8 Jun 2003 07:40:25 -0000 +*************** +*** 61,66 **** +--- 61,67 ---- + # ite* terminal emulator interface to HP300 graphics devices + # hil HP300 HIL input devices + # bpf* Berkeley Packet Filter ++ # ipl IP Filter + # tun* network tunnel driver + # pf* Packet Filter + # lkm loadable kernel modules interface +*************** +*** 316,321 **** +--- 317,329 ---- + M lkm c 24 0 640 _lkm + ;; + ++ ipl) ++ M ipl c 37 0 600 ++ M ipnat c 37 1 600 ++ M ipstate c 37 2 600 ++ M ipauth c 37 3 600 ++ ;; ++ + pf*) + M pf c 33 0 600 + ;; +*************** +*** 395,400 **** +--- 403,409 ---- + R sd2 sd3 sd4 rd0 tun0 tun1 tun2 tun3 bpf0 bpf1 bpf2 bpf3 bpf4 + R bpf5 bpf6 bpf7 bpf8 bpf9 pty0 pty1 pty2 xfs0 local ppi0 + R apci0 random lkm pf systrace std fd ++ R ipl + ;; + + sd*|hd*|ccd*) +Index: etc/etc.hp300/MAKEDEV.md +=================================================================== +RCS file: /cvs/src/etc/etc.hp300/MAKEDEV.md,v +retrieving revision 1.12 +diff -c -r1.12 MAKEDEV.md +*** etc/etc.hp300/MAKEDEV.md 25 Dec 2002 20:20:20 -0000 1.12 +--- etc/etc.hp300/MAKEDEV.md 8 Jun 2003 07:40:26 -0000 +*************** +*** 84,89 **** +--- 84,93 ---- + _DEV(bpf, 22) + _DEV(tun, 23) + _DEV(pf, 33) ++ _DEV(ipl, 37) ++ _DEV(ipnat, 37) ++ _DEV(ipstate, 37) ++ _DEV(ipauth, 37) + _DEV(lkm, 24) + _DEV(rnd, 32) + _DEV(xfs, 51) +Index: etc/etc.hppa/MAKEDEV +=================================================================== +RCS file: /cvs/src/etc/etc.hppa/MAKEDEV,v +retrieving revision 1.34 +diff -c -r1.34 MAKEDEV +*** etc/etc.hppa/MAKEDEV 5 Feb 2003 20:18:36 -0000 1.34 +--- etc/etc.hppa/MAKEDEV 8 Jun 2003 07:40:26 -0000 +*************** +*** 62,67 **** +--- 62,68 ---- + # Special purpose devices: + # fd makes fd/* for the fdescfs + # bpf* Berkeley Packet Filter ++ # ipl IP Filter + # tun* network tunnel driver + # pf* Packet Filter + # lkm loadable kernel modules interface +*************** +*** 266,271 **** +--- 267,279 ---- + M lkm c 19 0 640 _lkm + ;; + ++ ipl) ++ M ipl c 38 0 600 ++ M ipnat c 38 1 600 ++ M ipstate c 38 2 600 ++ M ipauth c 38 3 600 ++ ;; ++ + pf*) + M pf c 21 0 600 + ;; +*************** +*** 412,417 **** +--- 420,426 ---- + R xfs0 ss0 ss1 ch0 ses0 wscons audio0 uk0 random lpa0 lpa1 + R lpa2 lpt0 lpt1 lpt2 lkm tty00 tty01 tty02 tty03 crypto pf + R systrace std st0 st1 fd ++ R ipl + ;; + + sd*|ccd*) +Index: etc/etc.hppa/MAKEDEV.md +=================================================================== +RCS file: /cvs/src/etc/etc.hppa/MAKEDEV.md,v +retrieving revision 1.13 +diff -c -r1.13 MAKEDEV.md +*** etc/etc.hppa/MAKEDEV.md 5 Feb 2003 20:17:38 -0000 1.13 +--- etc/etc.hppa/MAKEDEV.md 8 Jun 2003 07:40:26 -0000 +*************** +*** 58,63 **** +--- 58,67 ---- + _DEV(bpf, 17) + _DEV(tun, 18) + _DEV(pf, 21) ++ _DEV(ipl, 38) ++ _DEV(ipnat, 38) ++ _DEV(ipstate, 38) ++ _DEV(ipauth, 38) + _DEV(lkm, 19) + _DEV(rnd, 20) + _DEV(xfs, 31) +Index: etc/etc.i386/MAKEDEV +=================================================================== +RCS file: /cvs/src/etc/etc.i386/MAKEDEV,v +retrieving revision 1.139 +diff -c -r1.139 MAKEDEV +*** etc/etc.i386/MAKEDEV 6 Jan 2003 17:19:59 -0000 1.139 +--- etc/etc.i386/MAKEDEV 8 Jun 2003 07:40:27 -0000 +*************** +*** 79,84 **** +--- 79,85 ---- + # Special purpose devices: + # fd makes fd/* for the fdescfs + # crypto hardware crypto access driver ++ # ipl IP Filter + # pf* Packet Filter + # bpf* Berkeley Packet Filter + # speaker pc speaker +*************** +*** 373,378 **** +--- 374,386 ---- + M bpf$U c 23 $U 600 + ;; + ++ ipl) ++ M ipl c 81 0 600 ++ M ipnat c 81 1 600 ++ M ipstate c 81 2 600 ++ M ipauth c 81 3 600 ++ ;; ++ + pf*) + M pf c 73 0 600 + ;; +*************** +*** 569,574 **** +--- 577,583 ---- + R tty03 ttyc0 ttyc1 ttyc2 ttyc3 ttyc4 ttyc5 ttyc6 ttyc7 apm + R crypto pf pctr systrace wd0 wd1 wd2 wd3 raid0 raid1 raid2 + R raid3 std st0 st1 fd mcd0 ++ R ipl + ;; + + wd*|sd*|raid*|ccd*) +Index: etc/etc.i386/MAKEDEV.md +=================================================================== +RCS file: /cvs/src/etc/etc.i386/MAKEDEV.md,v +retrieving revision 1.16 +diff -c -r1.16 MAKEDEV.md +*** etc/etc.i386/MAKEDEV.md 5 Dec 2002 04:30:21 -0000 1.16 +--- etc/etc.i386/MAKEDEV.md 8 Jun 2003 07:40:27 -0000 +*************** +*** 74,79 **** +--- 74,83 ---- + _DEV(fdesc, 22) + _DEV(cry, 70) + _DEV(pf, 73) ++ _DEV(ipl, 81) ++ _DEV(ipnat, 81) ++ _DEV(ipstate, 81) ++ _DEV(ipauth, 81) + _DEV(bpf, 23) + _DEV(speak, 27) + _DEV(lkm, 28) +Index: etc/etc.mac68k/MAKEDEV +=================================================================== +RCS file: /cvs/src/etc/etc.mac68k/MAKEDEV,v +retrieving revision 1.65 +diff -c -r1.65 MAKEDEV +*** etc/etc.mac68k/MAKEDEV 6 Jan 2003 17:19:59 -0000 1.65 +--- etc/etc.mac68k/MAKEDEV 8 Jun 2003 07:40:29 -0000 +*************** +*** 56,61 **** +--- 56,62 ---- + # CyberVision 64 (grf5) + # Special purpose devices: + # bpf* Berkeley Packet Filter ++ # ipl IP Filter + # tun* network tunnel driver + # pf* Packet Filter + # lkm loadable kernel modules interface +*************** +*** 277,282 **** +--- 278,290 ---- + M lkm c 25 0 640 _lkm + ;; + ++ ipl) ++ M ipl c 38 0 600 ++ M ipnat c 38 1 600 ++ M ipstate c 38 2 600 ++ M ipauth c 38 3 600 ++ ;; ++ + pf*) + M pf c 35 0 600 + ;; +*************** +*** 355,360 **** +--- 363,369 ---- + R xfs0 ss0 ss1 ch0 vnd0 vnd1 vnd2 vnd3 sd0 sd1 sd2 sd3 sd4 + R local grf0 grf1 grf2 grf3 adb asc0 uk0 random lkm ttye0 + R tty00 tty01 pf systrace std st0 st1 fd ++ R ipl + ;; + + sd*|ccd*) +Index: etc/etc.mac68k/MAKEDEV.md +=================================================================== +RCS file: /cvs/src/etc/etc.mac68k/MAKEDEV.md,v +retrieving revision 1.10 +diff -c -r1.10 MAKEDEV.md +*** etc/etc.mac68k/MAKEDEV.md 5 Dec 2002 04:30:21 -0000 1.10 +--- etc/etc.mac68k/MAKEDEV.md 8 Jun 2003 07:40:29 -0000 +*************** +*** 50,55 **** +--- 50,59 ---- + _DEV(bpf, 22) + _DEV(tun, 24) + _DEV(pf, 35) ++ _DEV(ipl, 38) ++ _DEV(ipnat, 38) ++ _DEV(ipstate, 38) ++ _DEV(ipauth, 38) + _DEV(lkm, 25) + _DEV(rnd, 32) + _DEV(uk, 34) +Index: etc/etc.macppc/MAKEDEV +=================================================================== +RCS file: /cvs/src/etc/etc.macppc/MAKEDEV,v +retrieving revision 1.37 +diff -c -r1.37 MAKEDEV +*** etc/etc.macppc/MAKEDEV 6 Jan 2003 17:19:59 -0000 1.37 +--- etc/etc.macppc/MAKEDEV 8 Jun 2003 07:40:30 -0000 +*************** +*** 72,77 **** +--- 72,78 ---- + # audio* audio device + # apm power management device + # bpf* Berkeley Packet Filter ++ # ipl IP Filter + # tun* network tunnel driver + # lkm loadable kernel modules interface + # *random inkernel random data source +*************** +*** 256,261 **** +--- 257,269 ---- + M crypto c 47 0 + ;; + ++ ipl) ++ M ipl c 45 0 600 ++ M ipnat c 45 1 600 ++ M ipstate c 45 2 600 ++ M ipauth c 45 3 600 ++ ;; ++ + pf*) + M pf c 39 0 600 + ;; +*************** +*** 456,461 **** +--- 464,470 ---- + R local wscons pci iop0 iop1 usbs tuner0 radio0 audio0 uk0 + R random lkm tty00 tty01 tty02 tty03 apm crypto pf systrace + R wd0 wd1 wd2 wd3 raid0 raid1 raid2 raid3 std st0 st1 fd ++ R ipl + ;; + + wd*|sd*|raid*|ccd*) +Index: etc/etc.macppc/MAKEDEV.md +=================================================================== +RCS file: /cvs/src/etc/etc.macppc/MAKEDEV.md,v +retrieving revision 1.10 +diff -c -r1.10 MAKEDEV.md +*** etc/etc.macppc/MAKEDEV.md 5 Dec 2002 04:30:21 -0000 1.10 +--- etc/etc.macppc/MAKEDEV.md 8 Jun 2003 07:40:30 -0000 +*************** +*** 74,79 **** +--- 74,83 ---- + _DEV(xfs, 51) + _DEV(iop, 73) + _DEV(pf, 39) ++ _DEV(ipl, 45) ++ _DEV(ipnat, 45) ++ _DEV(ipstate, 45) ++ _DEV(ipauth, 45) + _DEV(cry, 47) + _DEV(usbs) + _DEV(pci, 71) +Index: etc/etc.mvme68k/MAKEDEV +=================================================================== +RCS file: /cvs/src/etc/etc.mvme68k/MAKEDEV,v +retrieving revision 1.51 +diff -c -r1.51 MAKEDEV +*** etc/etc.mvme68k/MAKEDEV 6 Jan 2003 17:19:59 -0000 1.51 +--- etc/etc.mvme68k/MAKEDEV 8 Jun 2003 07:40:30 -0000 +*************** +*** 60,65 **** +--- 60,66 ---- + # fd makes fd/* for the fdescfs + # bpf* Berkeley Packet Filter + # tun* network tunnel driver ++ # ipl IP Packet Filter + # pf* Packet Filter + # lkm loadable kernel modules interface + # *random inkernel random data source +*************** +*** 253,258 **** +--- 254,266 ---- + M bpf$U c 22 $U 600 + ;; + ++ ipl) ++ M ipl c 44 0 600 ++ M ipnat c 44 1 600 ++ M ipstate c 44 2 600 ++ M ipauth c 44 3 600 ++ ;; ++ + fd) + RMlist="mkdir -p fd;$RMlist" n=0 + while [ $n -lt 64 ];do M fd/$n c 21 $n;n=$(($n+1));done +*************** +*** 389,394 **** +--- 397,403 ---- + R tun3 bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 pty0 + R pty1 pty2 xfs0 ss0 ss1 vmel0 vmes0 flash0 nvram0 sram0 uk0 + R random lkm pf systrace std st0 st1 fd ++ R ipl + ;; + + sd*|ccd*) +Index: etc/etc.mvme68k/MAKEDEV.md +=================================================================== +RCS file: /cvs/src/etc/etc.mvme68k/MAKEDEV.md,v +retrieving revision 1.7 +diff -c -r1.7 MAKEDEV.md +*** etc/etc.mvme68k/MAKEDEV.md 5 Dec 2002 04:30:21 -0000 1.7 +--- etc/etc.mvme68k/MAKEDEV.md 8 Jun 2003 07:40:31 -0000 +*************** +*** 175,177 **** +--- 175,186 ---- + _std(1, 2, 43, 3, 6) + ;; + ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 44 0 ++ mknod ipnat c 44 1 ++ mknod ipstate c 44 2 ++ mknod ipauth c 44 3 ++ chown root.wheel ipl ipnat ipstate ipauth ++ ;; ++ +Index: etc/etc.mvme88k/MAKEDEV +=================================================================== +RCS file: /cvs/src/etc/etc.mvme88k/MAKEDEV,v +retrieving revision 1.28 +diff -c -r1.28 MAKEDEV +*** etc/etc.mvme88k/MAKEDEV 6 Jan 2003 17:19:59 -0000 1.28 +--- etc/etc.mvme88k/MAKEDEV 8 Jun 2003 07:40:31 -0000 +*************** +*** 55,60 **** +--- 55,61 ---- + # fd makes fd/* for the fdescfs + # bpf* Berkeley Packet Filter + # tun* network tunnel driver ++ # ipl IP Packet Filter + # pf* Packet Filter + # lkm loadable kernel modules interface + # *random inkernel random data source +*************** +*** 243,248 **** +--- 244,256 ---- + M bpf$U c 22 $U 600 + ;; + ++ ipl) ++ M ipl c 41 0 600 ++ M ipnat c 41 1 600 ++ M ipstate c 41 2 600 ++ M ipauth c 41 3 600 ++ ;; ++ + fd) + RMlist="mkdir -p fd;$RMlist" n=0 + while [ $n -lt 64 ];do M fd/$n c 21 $n;n=$(($n+1));done +*************** +*** 345,350 **** +--- 353,359 ---- + R tun2 tun3 bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 + R pty0 pty1 pty2 xfs0 vmel0 vmes0 nvram0 sram0 random lkm pf + R systrace std st0 st1 fd ++ R ipl + ;; + + sd*|ccd*) +Index: etc/etc.mvme88k/MAKEDEV.md +=================================================================== +RCS file: /cvs/src/etc/etc.mvme88k/MAKEDEV.md,v +retrieving revision 1.6 +diff -c -r1.6 MAKEDEV.md +*** etc/etc.mvme88k/MAKEDEV.md 5 Dec 2002 04:30:21 -0000 1.6 +--- etc/etc.mvme88k/MAKEDEV.md 8 Jun 2003 07:40:32 -0000 +*************** +*** 144,146 **** +--- 144,155 ---- + _std(1, 2, 43, 3, 6) + ;; + ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 41 0 ++ mknod ipnat c 41 1 ++ mknod ipstate c 41 2 ++ mknod ipauth c 41 3 ++ chown root.wheel ipl ipnat ipstate ipauth ++ ;; ++ +Index: etc/etc.mvmeppc/MAKEDEV +=================================================================== +RCS file: /cvs/src/etc/etc.mvmeppc/MAKEDEV,v +retrieving revision 1.10 +diff -c -r1.10 MAKEDEV +*** etc/etc.mvmeppc/MAKEDEV 6 Jan 2003 05:57:39 -0000 1.10 +--- etc/etc.mvmeppc/MAKEDEV 8 Jun 2003 07:40:34 -0000 +*************** +*** 73,78 **** +--- 73,79 ---- + # audio* audio + # ch* SCSI media changer + # bpf* Berkeley Packet Filter ++ # ipl IP Filter + # tun* network tunnel driver + # lkm loadable kernel modules interface + # *random inkernal random data source +*************** +*** 156,162 **** + sh $this ttyC0 ttyCcfg + sh $this tty00 tty01 tty02 tty03 pty0 pty1 + sh $this bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 +! sh $this pf tun0 tun1 tun2 tun3 + sh $this audio0 + sh $this random uk0 uk1 ss0 ss1 + sh $this wscons +--- 157,163 ---- + sh $this ttyC0 ttyCcfg + sh $this tty00 tty01 tty02 tty03 pty0 pty1 + sh $this bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 +! sh $this ipl pf tun0 tun1 tun2 tun3 + sh $this audio0 + sh $this random uk0 uk1 ss0 ss1 + sh $this wscons +*************** +*** 522,527 **** +--- 523,538 ---- + rm -f bpf${unit} + mknod bpf${unit} c 22 ${unit} + chown root.wheel bpf${unit} ++ ;; ++ ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 44 0 ++ mknod ipnat c 44 1 ++ mknod ipstate c 44 2 ++ mknod ipauth c 44 3 ++ chown root.wheel ipl ipnat ipstate ipauth ++ chmod 600 ipl ipnat ipstate ipauth + ;; + + pf) +Index: etc/etc.sparc/MAKEDEV +=================================================================== +RCS file: /cvs/src/etc/etc.sparc/MAKEDEV,v +retrieving revision 1.106 +diff -c -r1.106 MAKEDEV +*** etc/etc.sparc/MAKEDEV 6 Jan 2003 17:19:59 -0000 1.106 +--- etc/etc.sparc/MAKEDEV 8 Jun 2003 07:40:34 -0000 +*************** +*** 67,72 **** +--- 67,73 ---- + # audio* audio device + # openprom + # bpf* Berkeley Packet Filter ++ # ipl IP Filter + # pf* Packet Filter + # lkm loadable kernel modules interface + # tun* network tunnel driver +*************** +*** 288,293 **** +--- 289,301 ---- + M lkm c 112 0 640 _lkm + ;; + ++ ipl) ++ M ipl c 60 0 600 ++ M ipnat c 60 1 600 ++ M ipstate c 60 2 600 ++ M ipauth c 60 3 600 ++ ;; ++ + pf*) + M pf c 59 0 600 + ;; +*************** +*** 474,479 **** +--- 482,488 ---- + R fd0F fd0G fd0H xfs0 ss0 ss1 ch0 ses0 cuaa cuab cuac cuad + R ttya ttyb ttyc ttyd wscons audio0 uk0 random lkm pf systrace + R xd0 xd1 xd2 xd3 raid0 raid1 raid2 raid3 std st0 st1 fd ++ R ipl + ;; + + xd*|xy*|sd*|raid*|ccd*) +Index: etc/etc.sparc/MAKEDEV.md +=================================================================== +RCS file: /cvs/src/etc/etc.sparc/MAKEDEV.md,v +retrieving revision 1.16 +diff -c -r1.16 MAKEDEV.md +*** etc/etc.sparc/MAKEDEV.md 5 Dec 2002 04:30:21 -0000 1.16 +--- etc/etc.sparc/MAKEDEV.md 8 Jun 2003 07:40:34 -0000 +*************** +*** 92,97 **** +--- 92,101 ---- + _DEV(oppr) + _DEV(bpf, 105) + _DEV(pf, 59) ++ _DEV(ipl, 60) ++ _DEV(ipnat, 60) ++ _DEV(ipstate, 60) ++ _DEV(ipauth, 60) + _DEV(lkm, 112) + _DEV(tun, 111) + _DEV(rnd, 119) +Index: etc/etc.sparc64/MAKEDEV +=================================================================== +RCS file: /cvs/src/etc/etc.sparc64/MAKEDEV,v +retrieving revision 1.78 +diff -c -r1.78 MAKEDEV +*** etc/etc.sparc64/MAKEDEV 6 Jan 2003 17:19:59 -0000 1.78 +--- etc/etc.sparc64/MAKEDEV 8 Jun 2003 07:40:35 -0000 +*************** +*** 84,89 **** +--- 84,90 ---- + # ss* SCSI scanners + # uk* SCSI Unknown device + # audio* audio device ++ # ipl IP Filter + # pf* Packet Filter + # bpf* Berkeley Packet Filter + # tun* network tunnel driver +*************** +*** 317,322 **** +--- 318,330 ---- + M bpf$U c 105 $U 600 + ;; + ++ ipl) ++ M ipl c 82 0 600 ++ M ipnat c 82 1 600 ++ M ipstate c 82 2 600 ++ M ipauth c 82 3 600 ++ ;; ++ + pf*) + M pf c 73 0 600 + ;; +*************** +*** 561,567 **** + R ccd3 wscons pci usbs audio0 uk0 random lpa0 lpa1 lpa2 lpt0 + R lpt1 lpt2 lkm tty00 tty01 tty02 tty03 ttyh0 ttyh1 crypto pf + R systrace wd0 wd1 wd2 wd3 raid0 raid1 raid2 raid3 std st0 st1 +! R fd + ;; + + wd*|sd*|raid*|ccd*) +--- 569,575 ---- + R ccd3 wscons pci usbs audio0 uk0 random lpa0 lpa1 lpa2 lpt0 + R lpt1 lpt2 lkm tty00 tty01 tty02 tty03 ttyh0 ttyh1 crypto pf + R systrace wd0 wd1 wd2 wd3 raid0 raid1 raid2 raid3 std st0 st1 +! R ipl fd + ;; + + wd*|sd*|raid*|ccd*) +Index: etc/etc.sparc64/MAKEDEV.md +=================================================================== +RCS file: /cvs/src/etc/etc.sparc64/MAKEDEV.md,v +retrieving revision 1.25 +diff -c -r1.25 MAKEDEV.md +*** etc/etc.sparc64/MAKEDEV.md 5 Dec 2002 04:30:21 -0000 1.25 +--- etc/etc.sparc64/MAKEDEV.md 8 Jun 2003 07:40:36 -0000 +*************** +*** 104,109 **** +--- 104,113 ---- + _DEV(uk, 60) + _DEV(au, 69) + _DEV(pf, 73) ++ _DEV(ipl, 82) ++ _DEV(ipstate, 82) ++ _DEV(ipnat, 82) ++ _DEV(ipauth, 82) + _DEV(bpf, 105) + _DEV(tun, 111) + _DEV(lkm, 112) +Index: etc/etc.vax/MAKEDEV +=================================================================== +RCS file: /cvs/src/etc/etc.vax/MAKEDEV,v +retrieving revision 1.50 +diff -c -r1.50 MAKEDEV +*** etc/etc.vax/MAKEDEV 6 Jan 2003 05:57:40 -0000 1.50 +--- etc/etc.vax/MAKEDEV 8 Jun 2003 07:40:37 -0000 +*************** +*** 56,61 **** +--- 56,62 ---- + # qv* qvss (microvax) display + # lkm loadable kernel modules + # bpf* berkeley packet filter ++ # ipl IP Filter + # tun* network tunnel device + # ss* SCSI scanner + # uk* SCSI unknown +*************** +*** 78,83 **** +--- 79,85 ---- + sh $0 dz0 dl0 dhu0 rx0 rx1 raid0 raid1 raid2 raid3 + sh $0 ttyg0 ttyg1 ttyg2 ttyg3 + sh $0 crl std-extra systrace ++ sh $0 ipl + ;; + + floppy) +*************** +*** 615,620 **** +--- 617,632 ---- + mknod bpf$unit c 56 $unit + chmod 600 bpf$unit + chown root.wheel bpf$unit ++ ;; ++ ++ ipl) ++ rm -f ipl ipnat ipstate ipauth ++ mknod ipl c 47 0 ++ mknod ipnat c 47 1 ++ mknod ipstate c 47 2 ++ mknod ipauth c 47 3 ++ chown root.wheel ipl ipnat ipstate ipauth ++ chmod 600 ipl ipnat ipstate ipauth + ;; + + qd*) +Index: etc/etc.vax/MAKEDEV.md +=================================================================== +RCS file: /cvs/src/etc/etc.vax/MAKEDEV.md,v +retrieving revision 1.12 +diff -c -r1.12 MAKEDEV.md +*** etc/etc.vax/MAKEDEV.md 5 Dec 2002 04:30:21 -0000 1.12 +--- etc/etc.vax/MAKEDEV.md 8 Jun 2003 07:40:37 -0000 +*************** +*** 151,156 **** +--- 151,160 ---- + _DEV(oppr) + _DEV(bpf, 56) + _DEV(pf, 42) ++ _DEV(ipl, 47) ++ _DEV(ipstate, 47) ++ _DEV(ipnat, 47) ++ _DEV(ipauth, 47) + _DEV(lkm, 28) + _DEV(tun, 57) + _DEV(rnd, 67) diff --git a/OpenBSD-3/3.4-rc-diffs b/OpenBSD-3/3.4-rc-diffs new file mode 100644 index 0000000000000..415642b449838 --- /dev/null +++ b/OpenBSD-3/3.4-rc-diffs @@ -0,0 +1,91 @@ +diff -c tmp/etc/netstart etc/netstart +*** tmp/etc/netstart 16 Feb 2003 23:25:40 -0000 1.86 +--- etc/netstart 8 Jun 2003 07:40:21 -0000 +*************** +*** 181,186 **** +--- 181,196 ---- + domainname `cat /etc/defaultdomain` + fi + ++ # Configure the IP filter before configuring network interfaces ++ if [ X"${ipfilter}" = X"YES" -a -f "${ipfilter_rules}" ]; then ++ echo 'configuring IP filter' ++ ipf -Fa -f ${ipfilter_rules} ++ ipfresync="ipf -y" ++ else ++ ipfilter=NO ++ ipfresync=NO ++ fi ++ + # Set the address for the loopback interface. + # It will also initialize IPv6 address for lo0 (::1 and others). + ifconfig lo0 inet localhost +*************** +*** 337,339 **** +--- 347,362 ---- + + bridgestart $if + done ++ ++ # Configure NAT after configuring network interfaces ++ if [ "${ipnat}" = "YES" -a "${ipfilter}" = "YES" -a -f "${ipnat_rules}" ]; then ++ echo 'configuring NAT' ++ ipnat -CF -f ${ipnat_rules} ++ else ++ ipnat=NO ++ fi ++ ++ # Interfaces have come up so we should do an ipf -y if we're using IP filter. ++ if [ "${ipfresync}" != "NO" ]; then ++ ${ipfresync} ++ fi +diff -c tmp/etc/rc etc/rc +*** tmp/etc/rc 23 Mar 2003 18:45:34 -0000 1.225 +--- etc/rc 8 Jun 2003 07:40:22 -0000 +*************** +*** 220,225 **** +--- 220,229 ---- + echo 'starting named'; named $named_flags + fi + ++ if [ X"${ipfilter}" = X"YES" -a X"${ipmon_flags}" != X"NO" ]; then ++ echo 'starting ipmon'; ipmon ${ipmon_flags} ++ fi ++ + # $isakmpd_flags is imported from /etc/rc.conf; + # If $isakmpd_flags == NO or /etc/isakmpd/isakmpd.policy doesn't exist, then + # isakmpd isn't run. +diff -c tmp/etc/rc.conf etc/rc.conf +*** tmp/etc/rc.conf 10 Mar 2003 01:05:28 -0000 1.86 +--- etc/rc.conf 8 Jun 2003 07:40:24 -0000 +*************** +*** 52,58 **** + lockd=NO + gated=NO + amd=NO +! pf=NO # Packet filter / NAT + portmap=NO # Note: inetd(8) rpc services need portmap too + inetd=YES # almost always needed + check_quotas=YES # NO may be desirable in some YP environments +--- 52,60 ---- + lockd=NO + gated=NO + amd=NO +! ipfilter=NO # To enable ipfilter, set to YES +! ipnat=NO # for "YES", ipfilter must also be "YES" +! pf=NO # Enable pf(4) Packet filter / NAT + portmap=NO # Note: inetd(8) rpc services need portmap too + inetd=YES # almost always needed + check_quotas=YES # NO may be desirable in some YP environments +*************** +*** 76,81 **** +--- 78,86 ---- + nfsd_flags="-tun 4" # Crank the 4 for a busy NFS fileserver + amd_dir=/tmp_mnt # AMD's mount directory + amd_master=/etc/amd/master # AMD 'master' map ++ ipfilter_rules=/etc/ipf.rules # Rules for IP packet filtering with IP Filter ++ ipnat_rules=/etc/ipnat.rules # Rules for Network Address Translation ++ ipmon_flags=-Ds # To disable logging, use ipmon_flags=NO + syslogd_flags= # add more flags, ie. "-u -a /chroot/dev/log" + pf_rules=/etc/pf.conf # Packet filter rules file + pflogd_flags= # add more flags, ie. "-s 256" diff --git a/OpenBSD-3/3.4-sys-diffs b/OpenBSD-3/3.4-sys-diffs new file mode 100644 index 0000000000000..c5b8acc7f7fa6 --- /dev/null +++ b/OpenBSD-3/3.4-sys-diffs @@ -0,0 +1,1017 @@ +diff sys/arch/alpha/alpha/conf.c sys.ipf/arch/alpha/alpha/conf.c +*** sys/arch/alpha/alpha/conf.c Tue Jun 3 09:27:43 2003 +--- sys.ipf/arch/alpha/alpha/conf.c Mon Jun 21 22:20:42 2004 +*************** +*** 103,108 **** +--- 103,113 ---- + #include "lpt.h" + cdev_decl(lpt); + cdev_decl(prom); /* XXX XXX XXX */ ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif + cdev_decl(wd); + cdev_decl(fd); + #include "cy.h" +*************** +*** 173,179 **** + cdev_midi_init(NMIDI,midi), /* 41: MIDI I/O */ + cdev_midi_init(NSEQUENCER,sequencer), /* 42: sequencer I/O */ + cdev_disk_init(NRAID,raid), /* 43: RAIDframe disk driver */ +! cdev_notdef(), /* 44 */ + cdev_usb_init(NUSB,usb), /* 45: USB controller */ + cdev_usbdev_init(NUHID,uhid), /* 46: USB generic HID */ + cdev_ulpt_init(NULPT,ulpt), /* 47: USB printer */ +--- 178,184 ---- + cdev_midi_init(NMIDI,midi), /* 41: MIDI I/O */ + cdev_midi_init(NSEQUENCER,sequencer), /* 42: sequencer I/O */ + cdev_disk_init(NRAID,raid), /* 43: RAIDframe disk driver */ +! cdev_gen_ipf(NIPF,ipl), /* 44: IP filter log */ + cdev_usb_init(NUSB,usb), /* 45: USB controller */ + cdev_usbdev_init(NUHID,uhid), /* 46: USB generic HID */ + cdev_ulpt_init(NULPT,ulpt), /* 47: USB printer */ +diff sys/arch/hp300/hp300/conf.c sys.ipf/arch/hp300/hp300/conf.c +*** sys/arch/hp300/hp300/conf.c Tue Jun 3 09:27:45 2003 +--- sys.ipf/arch/hp300/hp300/conf.c Mon Jun 21 22:20:43 2004 +*************** +*** 122,127 **** +--- 122,133 ---- + cdev_decl(xfs_dev); + #endif + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include "systrace.h" +*************** +*** 165,171 **** + cdev_disk_init(NRD,rd), /* 34: RAM disk */ + cdev_tty_init(NAPCI,apci), /* 35: Apollo APCI UARTs */ + cdev_ksyms_init(NKSYMS,ksyms), /* 36: Kernel symbols device */ +! cdev_notdef(), /* 37 */ + cdev_notdef(), /* 38 */ + cdev_notdef(), /* 39 */ + cdev_notdef(), /* 40 */ +--- 171,177 ---- + cdev_disk_init(NRD,rd), /* 34: RAM disk */ + cdev_tty_init(NAPCI,apci), /* 35: Apollo APCI UARTs */ + cdev_ksyms_init(NKSYMS,ksyms), /* 36: Kernel symbols device */ +! cdev_pf_init(NIPF,ipl), /* 37: packet filter */ + cdev_notdef(), /* 38 */ + cdev_notdef(), /* 39 */ + cdev_notdef(), /* 40 */ +diff sys/arch/hppa/hppa/conf.c sys.ipf/arch/hppa/hppa/conf.c +*** sys/arch/hppa/hppa/conf.c Tue Jun 3 09:27:46 2003 +--- sys.ipf/arch/hppa/hppa/conf.c Mon Jun 21 22:20:43 2004 +*************** +*** 107,112 **** +--- 107,118 ---- + #include "com.h" + cdev_decl(com); + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include "systrace.h" +*************** +*** 157,162 **** +--- 163,169 ---- + cdev_audio_init(NAUDIO,audio), /* 35: /dev/audio */ + cdev_crypto_init(NCRYPTO,crypto), /* 36: /dev/crypto */ + cdev_ses_init(NSES,ses), /* 37: SCSI SES/SAF-TE */ ++ cdev_gen_ipf(NIPF,ipl), /* 38: ip filtering */ + cdev_lkm_dummy(), + cdev_lkm_dummy(), + cdev_lkm_dummy(), +diff sys/arch/i386/i386/conf.c sys.ipf/arch/i386/i386/conf.c +*** sys/arch/i386/i386/conf.c Sat Jun 28 02:57:14 2003 +--- sys.ipf/arch/i386/i386/conf.c Mon Jun 21 22:20:43 2004 +*************** +*** 188,193 **** +--- 188,199 ---- + #include "radio.h" + #include "gpr.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + /* XXX -- this needs to be supported by config(8)! */ + #if (NCOM > 0) && (NPCCOM > 0) + #error com and pccom are mutually exclusive. Sorry. +*************** +*** 311,317 **** + cdev_usbdev_init(NUSCANNER,uscanner), /* 77: USB scanners */ + cdev_systrace_init(NSYSTRACE,systrace), /* 78: system call tracing */ + cdev_oci_init(NBIO,bio), /* 79: ioctl tunnel */ +! cdev_ch_init(NGPR,gpr) /* 80: GPR400 SmartCard reader */ + }; + int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]); + +--- 317,325 ---- + cdev_usbdev_init(NUSCANNER,uscanner), /* 77: USB scanners */ + cdev_systrace_init(NSYSTRACE,systrace), /* 78: system call tracing */ + cdev_oci_init(NBIO,bio), /* 79: ioctl tunnel */ +! cdev_ch_init(NGPR,gpr), /* 80: GPR400 SmartCard reader */ +! cdev_gen_ipf(NIPF,ipl) /* 81: ip filtering */ +! + }; + int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]); + +diff sys/arch/mac68k/mac68k/conf.c sys.ipf/arch/mac68k/mac68k/conf.c +*** sys/arch/mac68k/mac68k/conf.c Tue Jun 3 09:27:49 2003 +--- sys.ipf/arch/mac68k/mac68k/conf.c Mon Jun 21 22:20:43 2004 +*************** +*** 104,109 **** +--- 104,115 ---- + cdev_decl(xfs_dev); + #endif + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include "systrace.h" +*************** +*** 148,154 **** + cdev_pf_init(NPF,pf), /* 35: packet filter */ + cdev_audio_init(NASC,asc), /* 36: ASC audio device */ + cdev_ksyms_init(NKSYMS,ksyms), /* 37: Kernel symbols device */ +! cdev_notdef(), /* 38 */ + cdev_notdef(), /* 39 */ + cdev_notdef(), /* 40 */ + cdev_notdef(), /* 41 */ +--- 154,160 ---- + cdev_pf_init(NPF,pf), /* 35: packet filter */ + cdev_audio_init(NASC,asc), /* 36: ASC audio device */ + cdev_ksyms_init(NKSYMS,ksyms), /* 37: Kernel symbols device */ +! cdev_gen_ipf(NIPF,ipl), /* 38: IP filter log */ + cdev_notdef(), /* 39 */ + cdev_notdef(), /* 40 */ + cdev_notdef(), /* 41 */ +diff sys/arch/macppc/macppc/conf.c sys.ipf/arch/macppc/macppc/conf.c +*** sys/arch/macppc/macppc/conf.c Sat Jun 28 02:57:14 2003 +--- sys.ipf/arch/macppc/macppc/conf.c Mon Jun 21 22:20:43 2004 +*************** +*** 105,110 **** +--- 105,116 ---- + + #include "tun.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #ifdef XFS + #include <xfs/nxfs.h> + cdev_decl(xfs_dev); +*************** +*** 191,197 **** + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ + cdev_audio_init(NAUDIO,audio), /* 44: generic audio I/O */ +! cdev_notdef(), /* 45 */ + cdev_notdef(), /* 46 */ + cdev_crypto_init(NCRYPTO,crypto), /* 47: /dev/crypto */ + cdev_notdef(), /* 48 */ +--- 197,203 ---- + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ + cdev_audio_init(NAUDIO,audio), /* 44: generic audio I/O */ +! cdev_gen_ipf(NIPF,ipl), /* 45: IP filter */ + cdev_notdef(), /* 46 */ + cdev_crypto_init(NCRYPTO,crypto), /* 47: /dev/crypto */ + cdev_notdef(), /* 48 */ +diff sys/arch/mvme68k/mvme68k/conf.c sys.ipf/arch/mvme68k/mvme68k/conf.c +*** sys/arch/mvme68k/mvme68k/conf.c Tue Jun 3 09:27:50 2003 +--- sys.ipf/arch/mvme68k/mvme68k/conf.c Mon Jun 21 22:20:43 2004 +*************** +*** 148,153 **** +--- 148,159 ---- + #include "bpfilter.h" + #include "tun.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include "systrace.h" +*************** +*** 202,208 **** + cdev_uk_init(NUK,uk), /* 41: unknown SCSI */ + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ +! cdev_lkm_dummy(), /* 44 */ + cdev_lkm_dummy(), /* 45 */ + cdev_lkm_dummy(), /* 46 */ + cdev_lkm_dummy(), /* 47 */ +--- 208,214 ---- + cdev_uk_init(NUK,uk), /* 41: unknown SCSI */ + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ +! cdev_gen_ipf(NIPF,ipl), /* 44: IP filter */ + cdev_lkm_dummy(), /* 45 */ + cdev_lkm_dummy(), /* 46 */ + cdev_lkm_dummy(), /* 47 */ +diff sys/arch/mvme88k/mvme88k/conf.c sys.ipf/arch/mvme88k/mvme88k/conf.c +*** sys/arch/mvme88k/mvme88k/conf.c Tue Jun 3 09:27:52 2003 +--- sys.ipf/arch/mvme88k/mvme88k/conf.c Mon Jun 21 22:20:43 2004 +*************** +*** 97,102 **** +--- 97,108 ---- + cdev_decl(lptwo); + #endif /* notyet */ + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include "systrace.h" +*************** +*** 183,189 **** + cdev_lkm_dummy(), /* 38 */ + cdev_pf_init(NPF,pf), /* 39: packet filter */ + cdev_random_init(1,random), /* 40: random data source */ +! cdev_notdef(), /* 41 */ + cdev_notdef(), /* 42 */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ + cdev_notdef(), /* 44 */ +--- 189,195 ---- + cdev_lkm_dummy(), /* 38 */ + cdev_pf_init(NPF,pf), /* 39: packet filter */ + cdev_random_init(1,random), /* 40: random data source */ +! cdev_gen_ipf(NIPF,ipl), /* 41: IP filter */ + cdev_notdef(), /* 42 */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ + cdev_notdef(), /* 44 */ +diff sys/arch/mvmeppc/mvmeppc/conf.c sys.ipf/arch/mvmeppc/mvmeppc/conf.c +*** sys/arch/mvmeppc/mvmeppc/conf.c Wed May 14 10:20:37 2003 +--- sys.ipf/arch/mvmeppc/mvmeppc/conf.c Mon Jun 21 22:20:43 2004 +*************** +*** 114,119 **** +--- 114,125 ---- + + #include "ksyms.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include "systrace.h" +*************** +*** 167,173 **** + cdev_uk_init(NUK,uk), /* 41: unknown SCSI */ + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ +! cdev_notdef(), /* 44 */ + cdev_notdef(), /* 45 */ + cdev_notdef(), /* 46 */ + cdev_notdef(), /* 47 */ +--- 173,179 ---- + cdev_uk_init(NUK,uk), /* 41: unknown SCSI */ + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ +! cdev_gen_ipf(NIPF,ipl), /* 44: IP filter */ + cdev_notdef(), /* 45 */ + cdev_notdef(), /* 46 */ + cdev_notdef(), /* 47 */ +diff sys/arch/sparc/sparc/conf.c sys.ipf/arch/sparc/sparc/conf.c +*** sys/arch/sparc/sparc/conf.c Tue Jun 3 09:27:55 2003 +--- sys.ipf/arch/sparc/sparc/conf.c Mon Jun 21 22:20:43 2004 +*************** +*** 124,129 **** +--- 124,135 ---- + }; + int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]); + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include "systrace.h" +*************** +*** 194,200 **** + cdev_notdef(), /* 57 */ + cdev_disk_init(NCD,cd), /* 58: SCSI CD-ROM */ + cdev_pf_init(NPF,pf), /* 59: packet filter */ +! cdev_notdef(), /* 60 */ + cdev_notdef(), /* 61 */ + cdev_notdef(), /* 62 */ + cdev_notdef(), /* 63 */ +--- 200,206 ---- + cdev_notdef(), /* 57 */ + cdev_disk_init(NCD,cd), /* 58: SCSI CD-ROM */ + cdev_pf_init(NPF,pf), /* 59: packet filter */ +! cdev_gen_ipf(NIPF,ipl), /* 60: ip filtering log */ + cdev_notdef(), /* 61 */ + cdev_notdef(), /* 62 */ + cdev_notdef(), /* 63 */ +diff sys/arch/sparc64/sparc64/conf.c sys.ipf/arch/sparc64/sparc64/conf.c +*** sys/arch/sparc64/sparc64/conf.c Sat Jun 28 02:57:14 2003 +--- sys.ipf/arch/sparc64/sparc64/conf.c Mon Jun 21 22:20:44 2004 +*************** +*** 110,115 **** +--- 110,121 ---- + #include "ucom.h" + #include "uscanner.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #ifdef XFS +*************** +*** 246,252 **** + cdev_mouse_init(NWSKBD, wskbd), /* 79: keyboards */ + cdev_mouse_init(NWSMOUSE, wsmouse), /* 80: mice */ + cdev_mouse_init(NWSMUX, wsmux), /* 81: ws multiplexor */ +! cdev_notdef(), /* 82 */ + cdev_notdef(), /* 83 */ + cdev_notdef(), /* 84 */ + cdev_notdef(), /* 85 */ +--- 252,258 ---- + cdev_mouse_init(NWSKBD, wskbd), /* 79: keyboards */ + cdev_mouse_init(NWSMOUSE, wsmouse), /* 80: mice */ + cdev_mouse_init(NWSMUX, wsmux), /* 81: ws multiplexor */ +! cdev_gen_ipf(NIPF,ipl), /* 82: IP filter */ + cdev_notdef(), /* 83 */ + cdev_notdef(), /* 84 */ + cdev_notdef(), /* 85 */ +diff sys/arch/vax/vax/conf.c sys.ipf/arch/vax/vax/conf.c +*** sys/arch/vax/vax/conf.c Thu Jun 26 23:06:26 2003 +--- sys.ipf/arch/vax/vax/conf.c Mon Jun 21 22:20:44 2004 +*************** +*** 353,358 **** +--- 353,364 ---- + #include "wskbd.h" + #include "wsmouse.h" + ++ #ifdef IPFILTER ++ #define NIPF 1 ++ #else ++ #define NIPF 0 ++ #endif ++ + #include "pf.h" + + #include "systrace.h" +*************** +*** 406,412 **** + cdev_notdef(), /* 44 was Datakit */ + cdev_notdef(), /* 45 was Datakit */ + cdev_notdef(), /* 46 was Datakit */ +! cdev_notdef(), /* 47 */ + cdev_notdef(), /* 48 */ + cdev_systrace_init(NSYSTRACE,systrace), /* 49: system call tracing */ + cdev_ksyms_init(NKSYMS,ksyms), /* 50: Kernel symbols device */ +--- 412,418 ---- + cdev_notdef(), /* 44 was Datakit */ + cdev_notdef(), /* 45 was Datakit */ + cdev_notdef(), /* 46 was Datakit */ +! cdev_gen_ipf(NIPF,ipl), /* 47: IP filter */ + cdev_notdef(), /* 48 */ + cdev_systrace_init(NSYSTRACE,systrace), /* 49: system call tracing */ + cdev_ksyms_init(NKSYMS,ksyms), /* 50: Kernel symbols device */ +diff sys/conf/GENERIC sys.ipf/conf/GENERIC +*** sys/conf/GENERIC Thu May 15 00:24:43 2003 +--- sys.ipf/conf/GENERIC Mon Jun 21 22:20:44 2004 +*************** +*** 71,76 **** +--- 71,78 ---- + #option EON # OSI tunneling over IP + #option NETATALK # AppleTalk + #option CCITT,LLC,HDLC # X.25 ++ option IPFILTER # IP packet filter for security ++ option IPFILTER_LOG # use /dev/ipl to log IPF + option PPP_BSDCOMP # PPP BSD compression + option PPP_DEFLATE + #option MROUTING # Multicast router +diff sys/conf/files sys.ipf/conf/files +*** sys/conf/files Fri Aug 22 05:12:07 2003 +--- sys.ipf/conf/files Mon Jun 21 22:20:44 2004 +*************** +*** 702,707 **** +--- 702,715 ---- + file netinet/tcp_usrreq.c inet + file netinet/udp_usrreq.c inet + file netinet/ip_gre.c inet ++ file netinet/ip_fil.c ipfilter ++ file netinet/fil.c ipfilter ++ file netinet/ip_nat.c ipfilter ++ file netinet/ip_frag.c ipfilter ++ file netinet/ip_state.c ipfilter ++ file netinet/ip_proxy.c ipfilter ++ file netinet/ip_auth.c ipfilter ++ file netinet/ip_log.c ipfilter + file netinet/ip_ipsp.c (inet | inet6) & (ipsec | tcp_signature) + file netinet/ip_spd.c (inet | inet6) & (ipsec | tcp_signature) + file netinet/ip_ipip.c inet | inet6 +diff sys/net/bridgestp.c sys.ipf/net/bridgestp.c +*** sys/net/bridgestp.c Tue Jun 3 04:42:56 2003 +--- sys.ipf/net/bridgestp.c Mon Jun 21 22:20:44 2004 +*************** +*** 58,63 **** +--- 58,68 ---- + #include <netinet/in_var.h> + #include <netinet/ip.h> + #include <netinet/if_ether.h> ++ ++ #ifdef IPFILTER ++ #include <netinet/ip_compat.h> ++ #include <netinet/ip_fil.h> ++ #endif + #endif + + #if NBPFILTER > 0 +diff sys/net/if.c sys.ipf/net/if.c +*** sys/net/if.c Wed Aug 27 10:33:34 2003 +--- sys.ipf/net/if.c Mon Jun 21 22:20:44 2004 +*************** +*** 97,102 **** +--- 97,108 ---- + #include <netinet6/nd6.h> + #endif + ++ #ifdef IPFILTER ++ #include <netinet/ip_compat.h> ++ #include <netinet/ip_fil.h> ++ #include <netinet/ip_nat.h> ++ #endif ++ + #if NBPFILTER > 0 + #include <net/bpf.h> + #endif +*************** +*** 480,485 **** +--- 486,496 ---- + + /* Remove the interface from the list of all interfaces. */ + TAILQ_REMOVE(&ifnet, ifp, if_list); ++ ++ #ifdef IPFILTER ++ /* XXX More ipf & ipnat cleanup needed. */ ++ frsync(ifp); ++ #endif + + /* + * Deallocate private resources. +diff sys/net/if_bridge.c sys.ipf/net/if_bridge.c +*** sys/net/if_bridge.c Sat Aug 16 06:32:19 2003 +--- sys.ipf/net/if_bridge.c Mon Jun 21 22:23:56 2004 +*************** +*** 66,72 **** +--- 66,76 ---- + #include <netinet/ip_ipsp.h> + + #include <net/if_enc.h> ++ #if (defined(IPFILTER) || defined(IPFILTER_LKM)) ++ #include <netinet/ip_compat.h> ++ #include <netinet/ip_fil.h> + #endif ++ #endif + + #ifdef INET6 + #include <netinet/ip6.h> +*************** +*** 155,161 **** + int bridge_brlconf(struct bridge_softc *, struct ifbrlconf *); + u_int8_t bridge_filterrule(struct brl_head *, struct ether_header *, + struct mbuf *); +! #if NPF > 0 + struct mbuf *bridge_filter(struct bridge_softc *, int, struct ifnet *, + struct ether_header *, struct mbuf *m); + #endif +--- 159,165 ---- + int bridge_brlconf(struct bridge_softc *, struct ifbrlconf *); + u_int8_t bridge_filterrule(struct brl_head *, struct ether_header *, + struct mbuf *); +! #if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + struct mbuf *bridge_filter(struct bridge_softc *, int, struct ifnet *, + struct ether_header *, struct mbuf *m); + #endif +*************** +*** 1168,1174 **** + m_freem(m); + return; + } +! #if NPF > 0 + m = bridge_filter(sc, BRIDGE_IN, src_if, &eh, m); + if (m == NULL) + return; +--- 1172,1178 ---- + m_freem(m); + return; + } +! #if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + m = bridge_filter(sc, BRIDGE_IN, src_if, &eh, m); + if (m == NULL) + return; +*************** +*** 1211,1217 **** + m_freem(m); + return; + } +! #if NPF > 0 + m = bridge_filter(sc, BRIDGE_OUT, dst_if, &eh, m); + if (m == NULL) + return; +--- 1215,1221 ---- + m_freem(m); + return; + } +! #if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + m = bridge_filter(sc, BRIDGE_OUT, dst_if, &eh, m); + if (m == NULL) + return; +*************** +*** 1459,1465 **** + mc = m1; + } + +! #if NPF > 0 + mc = bridge_filter(sc, BRIDGE_OUT, dst_if, eh, mc); + if (mc == NULL) + continue; +--- 1463,1469 ---- + mc = m1; + } + +! #if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + mc = bridge_filter(sc, BRIDGE_OUT, dst_if, eh, mc); + if (mc == NULL) + continue; +*************** +*** 2235,2240 **** +--- 2239,2250 ---- + * We don't need to do loop detection, the + * bridge will do that for us. + */ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (dir == BRIDGE_OUT && fr_checkp && ++ ((*fr_checkp)(ip, hlen, &encif[0].sc_if, ++ 1, &m) || !m)) ++ return 1; ++ #endif + #if NPF > 0 + switch (af) { + #ifdef INET +*************** +*** 2259,2264 **** +--- 2269,2280 ---- + if (m == NULL) + return (1); + #endif /* NPF */ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (dir == BRIDGE_IN && fr_checkp && ++ ((*fr_checkp)(ip, hlen, &encif[0].sc_if, ++ 0, &m) || !m)) ++ return 1; ++ #endif + error = ipsp_process_packet(m, tdb, af, 0); + return (1); + } else +*************** +*** 2269,2275 **** + } + #endif /* IPSEC */ + +! #if NPF > 0 + /* + * Filter IP packets by peeking into the ethernet frame. This violates + * the ISO model, but allows us to act as a IP filter at the data link +--- 2285,2291 ---- + } + #endif /* IPSEC */ + +! #if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + /* + * Filter IP packets by peeking into the ethernet frame. This violates + * the ISO model, but allows us to act as a IP filter at the data link +*************** +*** 2372,2385 **** + return (NULL); + #endif /* IPSEC */ + +! #if NPF > 0 + /* Finally, we get to filter the packet! */ + m->m_pkthdr.rcvif = ifp; + if (pf_test(dir, ifp, &m) != PF_PASS) + goto dropit; + if (m == NULL) + goto dropit; + #endif /* NPF */ + + /* Rebuild the IP header */ + if (m->m_len < hlen && ((m = m_pullup(m, hlen)) == NULL)) +--- 2388,2419 ---- + return (NULL); + #endif /* IPSEC */ + +! #if defined(IPFILTER) || defined(IPFILTER_LKM) || (NPF > 0) + /* Finally, we get to filter the packet! */ + m->m_pkthdr.rcvif = ifp; ++ #endif ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (dir == BRIDGE_OUT) { ++ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 1, &m)) ++ goto dropit; ++ if (m == NULL) ++ goto dropit; ++ } ++ #endif ++ #if NPF > 0 + if (pf_test(dir, ifp, &m) != PF_PASS) + goto dropit; + if (m == NULL) + goto dropit; + #endif /* NPF */ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (dir == BRIDGE_IN) { ++ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 0, &m)) ++ goto dropit; ++ if (m == NULL) ++ goto dropit; ++ } ++ #endif + + /* Rebuild the IP header */ + if (m->m_len < hlen && ((m = m_pullup(m, hlen)) == NULL)) +*************** +*** 2420,2425 **** +--- 2454,2467 ---- + return (NULL); + #endif /* IPSEC */ + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (dir == BRIDGE_OUT) { ++ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 1, &m)) ++ goto dropit; ++ if (m == NULL) ++ return (NULL); ++ } ++ #endif + #if NPF > 0 + if (pf_test6(dir, ifp, &m) != PF_PASS) + goto dropit; +*************** +*** 2426,2431 **** +--- 2468,2481 ---- + if (m == NULL) + return (NULL); + #endif /* NPF */ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (dir == BRIDGE_IN) { ++ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 0, &m)) ++ goto dropit; ++ if (m == NULL) ++ return (NULL); ++ } ++ #endif + + break; + } +*************** +*** 2457,2463 **** + m_freem(m); + return (NULL); + } +! #endif /* NPF > 0 */ + + void + bridge_fragment(struct bridge_softc *sc, struct ifnet *ifp, +--- 2507,2513 ---- + m_freem(m); + return (NULL); + } +! #endif /* (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) */ + + void + bridge_fragment(struct bridge_softc *sc, struct ifnet *ifp, +diff sys/netinet/in_proto.c sys.ipf/netinet/in_proto.c +*** sys/netinet/in_proto.c Tue Jun 3 09:28:14 2003 +--- sys.ipf/netinet/in_proto.c Mon Jun 21 22:20:44 2004 +*************** +*** 159,164 **** +--- 159,169 ---- + #include <netinet/ip_mroute.h> + #endif /* MROUTING */ + ++ #ifdef IPFILTER ++ void iplinit __P((void)); ++ #define ip_init iplinit ++ #endif ++ + #ifdef INET6 + #include <netinet6/ip6_var.h> + #endif /* INET6 */ +diff sys/netinet/ip_input.c sys.ipf/netinet/ip_input.c +*** sys/netinet/ip_input.c Tue Jul 29 13:21:57 2003 +--- sys.ipf/netinet/ip_input.c Mon Jun 21 22:20:45 2004 +*************** +*** 147,152 **** +--- 147,156 ---- + struct in_ifaddrhead in_ifaddr; + struct ifqueue ipintrq; + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif ++ + int ipq_locked; + static __inline int ipq_lock_try(void); + static __inline void ipq_unlock(void); +*************** +*** 402,407 **** +--- 406,428 ---- + ip = mtod(m, struct ip *); + hlen = ip->ip_hl << 2; + pfrdr = (pfrdr != ip->ip_dst.s_addr); ++ #endif ++ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * Check if we want to allow this packet to be processed. ++ * Consider it to be bad if not. ++ */ ++ { ++ struct mbuf *m0 = m; ++ if (fr_checkp && (*fr_checkp)(ip, hlen, m->m_pkthdr.rcvif, 0, &m0)) { ++ return; ++ } ++ if (m0 == 0) { /* in case of 'fastroute' */ ++ return; ++ } ++ ip = mtod(m = m0, struct ip *); ++ } + #endif + + /* +diff sys/netinet/ip_output.c sys.ipf/netinet/ip_output.c +*** sys/netinet/ip_output.c Sat Aug 16 06:32:20 2003 +--- sys.ipf/netinet/ip_output.c Mon Jun 21 22:20:45 2004 +*************** +*** 82,87 **** +--- 82,91 ---- + static struct mbuf *ip_insertoptions(struct mbuf *, struct mbuf *, int *); + static void ip_mloopback(struct ifnet *, struct mbuf *, struct sockaddr_in *); + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif ++ + /* + * IP output. The packet in mbuf chain m contains a skeletal IP + * header (with len, off, ttl, proto, tos, src, dst). +*************** +*** 555,561 **** +--- 559,589 ---- + if (sproto != 0) { + s = splnet(); + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (fr_checkp) { + /* ++ * Ok, it's time for a simple round-trip to the IPF/NAT ++ * code with the enc0 interface. ++ */ ++ struct mbuf *m1 = m; ++ void *ifp = (void *)&encif[0].sc_if; ++ ++ if ((*fr_checkp)(ip, hlen, ifp, 1, &m1)) { ++ error = EHOSTUNREACH; ++ splx(s); ++ goto done; ++ } ++ if (m1 == 0) { /* in case of 'fastroute' */ ++ error = 0; ++ splx(s); ++ goto done; ++ } ++ ip = mtod(m = m1, struct ip *); ++ hlen = ip->ip_hl << 2; ++ } ++ #endif /* IPFILTER */ ++ ++ /* + * Packet filter + */ + #if NPF > 0 +*************** +*** 653,658 **** +--- 681,705 ---- + m->m_pkthdr.csum &= ~M_UDPV4_CSUM_OUT; /* Clear */ + } + } ++ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * looks like most checking has been done now...do a filter check ++ */ ++ { ++ struct mbuf *m1 = m; ++ ++ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 1, &m1)) { ++ error = EHOSTUNREACH; ++ goto done; ++ } ++ if (m1 == 0) { /* in case of 'fastroute' */ ++ error = 0; ++ goto done; ++ } ++ ip = mtod(m = m1, struct ip *); ++ } ++ #endif + + /* + * Packet filter +diff sys/netinet6/ip6_input.c sys.ipf/netinet6/ip6_input.c +*** sys/netinet6/ip6_input.c Mon Jun 30 20:30:23 2003 +--- sys.ipf/netinet6/ip6_input.c Mon Jun 21 22:20:45 2004 +*************** +*** 128,133 **** +--- 128,137 ---- + static int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *); + static struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int); + ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif ++ + /* + * IP6 initialization: fill in IP6 protocol switch table. + * All protocols not implemented in kernel go to raw IP6 protocol handler. +*************** +*** 244,249 **** +--- 248,273 ---- + in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); + goto bad; + } ++ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * Check if we want to allow this packet to be processed. ++ * Consider it to be bad if not. ++ */ ++ if (fr_checkp != NULL) { ++ struct mbuf *m0 = m; ++ ++ if ((*fr_checkp)((struct ip *)ip6, sizeof(*ip6), ++ m->m_pkthdr.rcvif, 0, &m0)) { ++ return; ++ } ++ m = m0; ++ if (m == 0) { /* in case of 'fastroute' */ ++ return; ++ } ++ ip6 = mtod(m, struct ip6_hdr *); ++ } ++ #endif + + #if NPF > 0 + /* +diff sys/netinet6/ip6_output.c sys.ipf/netinet6/ip6_output.c +*** sys/netinet6/ip6_output.c Sat Aug 16 06:32:20 2003 +--- sys.ipf/netinet6/ip6_output.c Mon Jun 21 22:20:45 2004 +*************** +*** 116,121 **** +--- 116,124 ---- + + static int ip6_pcbopts(struct ip6_pktopts **, struct mbuf *, struct socket *); + static int ip6_setmoptions(int, struct ip6_moptions **, struct mbuf *); ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif + static int ip6_getmoptions(int, struct ip6_moptions *, struct mbuf **); + static int ip6_copyexthdr(struct mbuf **, caddr_t, int); + static int ip6_insertfraghdr(struct mbuf *, struct mbuf *, int, +*************** +*** 122,128 **** + struct ip6_frag **); + static int ip6_insert_jumboopt(struct ip6_exthdrs *, u_int32_t); + static int ip6_splithdr(struct mbuf *, struct ip6_exthdrs *); +! static int ip6_getpmtu(struct route_in6 *, struct route_in6 *, + struct ifnet *, struct in6_addr *, u_long *); + + /* +--- 125,131 ---- + struct ip6_frag **); + static int ip6_insert_jumboopt(struct ip6_exthdrs *, u_int32_t); + static int ip6_splithdr(struct mbuf *, struct ip6_exthdrs *); +! int ip6_getpmtu(struct route_in6 *, struct route_in6 *, + struct ifnet *, struct in6_addr *, u_long *); + + /* +*************** +*** 793,798 **** +--- 796,820 ---- + goto done; + ip6 = mtod(m, struct ip6_hdr *); + #endif ++ ++ #if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * looks like most checking has been done now...do a filter check ++ */ ++ if (fr_checkp != NULL) { ++ struct mbuf *m1 = m; ++ if ((*fr_checkp)((struct ip *)ip6, sizeof(*ip6), ifp, 1, &m1)) { ++ error = EHOSTUNREACH; ++ goto done; ++ } ++ m = m1; ++ if (m1 == 0) { /* in case of 'fastroute' */ ++ error = 0; ++ goto done; ++ } ++ ip6 = mtod(m, struct ip6_hdr *); ++ } ++ #endif + + /* + * Send the packet to the outgoing interface. +*************** +*** 1117,1123 **** + return (0); + } + +! static int + ip6_getpmtu(ro_pmtu, ro, ifp, dst, mtup) + struct route_in6 *ro_pmtu, *ro; + struct ifnet *ifp; +--- 1139,1145 ---- + return (0); + } + +! int + ip6_getpmtu(ro_pmtu, ro, ifp, dst, mtup) + struct route_in6 *ro_pmtu, *ro; + struct ifnet *ifp; +diff sys/sys/conf.h sys.ipf/sys/conf.h +*** sys/sys/conf.h Sat Jun 28 02:57:14 2003 +--- sys.ipf/sys/conf.h Mon Jun 21 22:20:45 2004 +*************** +*** 358,363 **** +--- 358,370 ---- + (dev_type_ioctl((*))) enodev, (dev_type_stop((*))) nullop, \ + 0, (dev_type_select((*))) enodev, (dev_type_mmap((*))) enodev } + ++ /* open, close, read, ioctl */ ++ #define cdev_gen_ipf(c, n) { \ ++ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ ++ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ ++ (dev_type_stop((*))) enodev, 0, (dev_type_select((*))) enodev, \ ++ (dev_type_mmap((*))) enodev } ++ + /* open, close, read, write, ioctl, select, nokqfilter */ + #define cdev_xfs_init(c, n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ +*************** +*** 578,583 **** +--- 585,591 ---- + + cdev_decl(bpf); + ++ cdev_decl(ipl); + cdev_decl(pf); + + cdev_decl(tun); diff --git a/OpenBSD-3/3.5-MAKEDEV-diffs b/OpenBSD-3/3.5-MAKEDEV-diffs new file mode 100644 index 0000000000000..e3c0a099fec7a --- /dev/null +++ b/OpenBSD-3/3.5-MAKEDEV-diffs @@ -0,0 +1,615 @@ +--- ./etc/etc.alpha/MAKEDEV Sat Jul 10 12:47:18 2004 ++++ ./etc/etc.alpha/MAKEDEV.orig Sun Mar 14 05:38:04 2004 +@@ -75,7 +75,6 @@ + # music* MIDI devices + # pci PCI bus device + # pf* Packet Filter +-# ipl IP Filter + # rmidi* Raw MIDI devices + # *random In-kernel random data source + # speaker PC speaker +@@ -287,16 +286,6 @@ + M rmidi$U c 41 $U 666 + ;; + +-ipl) +- M ipl c 44 0 600 +- M ipnat c 44 1 600 +- M ipstate c 44 2 600 +- M ipauth c 44 3 600 +- M ipsync c 44 4 600 +- M ipscan c 44 5 600 +- M iplookup c 44 6 600 +- ;; +- + pf*) + M pf c 35 0 600 + ;; +@@ -514,7 +503,6 @@ + R tty00 tty01 tty02 tty03 ttyc0 ttyc1 ttyc2 ttyc3 ttyc4 ttyc5 + R ttyc6 ttyc7 ttyB0 ttyB1 ttyB2 ttyB3 ttyB4 ttyB5 pf systrace + R wd0 wd1 wd2 wd3 raid0 raid1 raid2 raid3 std st0 st1 fd +- R ipl + ;; + + wd*|sd*|raid*|ccd*) +--- ./etc/etc.alpha/MAKEDEV.md Sat Jul 10 12:42:14 2004 ++++ ./etc/etc.alpha/MAKEDEV.md.orig Sun Mar 14 05:38:04 2004 +@@ -64,17 +64,10 @@ + _DEV(bpf, 11) + _DEV(fdesc, 10) + _DEV(iop, 54) +-_DEV(ipl, 44) + _DEV(lkm, 16) + _DEV(music, 42) + _DEV(pci, 52) + _DEV(pf, 35) +-_DEV(ipnat, 44) +-_DEV(ipstate, 44) +-_DEV(ipauth, 44) +-_DEV(ipsync, 44) +-_DEV(ipscan, 44) +-_DEV(iplookup, 44) + _DEV(rmidi, 41) + _DEV(rnd, 34) + _DEV(speak, 40) +--- ./etc/etc.hp300/MAKEDEV Sat Jul 10 12:48:22 2004 ++++ ./etc/etc.hp300/MAKEDEV.orig Sun Mar 14 05:38:05 2004 +@@ -55,7 +55,6 @@ + # Special purpose devices: + # bpf* Berkeley Packet Filter + # fd fd/* nodes for fdescfs +-# ipl IP Filter + # hil HP-HIL input devices + # lkm Loadable kernel modules interface + # pf* Packet Filter +@@ -329,16 +328,6 @@ + done + ;; + +-ipl) +- M ipl c 37 0 600 +- M ipnat c 37 1 600 +- M ipstate c 37 2 600 +- M ipauth c 37 3 600 +- M ipsync c 37 4 600 +- M ipscan c 37 5 600 +- M iplookup c 37 6 600 +- ;; +- + pf*) + M pf c 33 0 600 + ;; +@@ -422,7 +411,6 @@ + R sd2 sd3 sd4 rd0 tun0 tun1 tun2 tun3 bpf0 bpf1 bpf2 bpf3 bpf4 + R bpf5 bpf6 bpf7 bpf8 bpf9 pty0 pty1 pty2 xfs0 ptm local ppi0 + R apci0 random lkm pf systrace std fd +- R ipl + ;; + + sd*|hd*|ccd*) +--- ./etc/etc.hp300/MAKEDEV.md Sat Jul 10 12:42:23 2004 ++++ ./etc/etc.hp300/MAKEDEV.md.orig Sun Mar 14 05:38:05 2004 +@@ -79,7 +79,6 @@ + _DEV(bpf, 22) + _DEV(fdesc, 21) + _DEV(hil, 14) +-_DEV(ipl, 37) + _DEV(lkm, 24) + _DEV(pf, 33) + _DEV(rnd, 32) +--- ./etc/etc.hppa/MAKEDEV Sat Jul 10 13:00:06 2004 ++++ ./etc/etc.hppa/MAKEDEV.orig Sun Mar 14 05:38:05 2004 +@@ -59,7 +59,6 @@ + # bpf* Berkeley Packet Filter + # crypto Hardware crypto access driver + # fd fd/* nodes for fdescfs +-# ipl IP Filter + # lkm Loadable kernel modules interface + # pci PCI bus device + # pdc PDC device +@@ -259,16 +258,6 @@ + done + ;; + +-ipl) +- M ipl c 39 0 600 +- M ipnat c 39 1 600 +- M ipstate c 39 2 600 +- M ipauth c 39 3 600 +- M ipsync c 39 4 600 +- M ipscan c 39 5 600 +- M iplookup c 39 6 600 +- ;; +- + pf*) + M pf c 21 0 600 + ;; +@@ -443,7 +432,7 @@ + R fd1E fd1F fd1G fd1H fd0 fd0B fd0C fd0D fd0E fd0F fd0G fd0H + R xfs0 ss0 ss1 ch0 ses0 ptm local wscons pci audio0 uk0 random + R lpa0 lpa1 lpa2 lpt0 lpt1 lpt2 lkm tty00 tty01 tty02 tty03 +- R crypto pf systrace std st0 st1 fd ipl ++ R crypto pf systrace std st0 st1 fd + ;; + + sd*|ccd*) +--- ./etc/etc.hppa/MAKEDEV.md Sat Jul 10 12:42:27 2004 ++++ ./etc/etc.hppa/MAKEDEV.md.orig Sat Feb 21 15:05:04 2004 +@@ -53,7 +53,6 @@ + _DEV(bpf, 17) + _DEV(cry, 36) + _DEV(fdesc, 16) +-_DEV(ipl, 39) + _DEV(lkm, 19) + _DEV(pci, 31) + _DEV(pdc, 22) +--- ./etc/etc.i386/MAKEDEV Sat Jul 10 12:50:08 2004 ++++ ./etc/etc.i386/MAKEDEV.orig Sun Mar 14 05:38:05 2004 +@@ -80,7 +80,6 @@ + # fd fd/* nodes for fdescfs + # gpr* GPR400 smartcard reader + # iop* I2O controller devices +-# ipl IP Filter + # joy* Joystick driver + # lkm Loadable kernel modules interface + # music* MIDI devices +@@ -309,16 +308,6 @@ + MKlist="$MKlist;[ -e radio ] || ln -s radio$U radio" + ;; + +-ipl) +- M ipl c 82 0 600 +- M ipnat c 82 1 600 +- M ipstate c 82 2 600 +- M ipauth c 82 3 600 +- M ipsync c 82 4 600 +- M ipscan c 82 5 600 +- M iplookup c 82 6 600 +- ;; +- + pf*) + M pf c 73 0 600 + ;; +@@ -586,7 +575,7 @@ + R random joy0 joy1 lpa0 lpa1 lpa2 lpt0 lpt1 lpt2 lkm tty00 + R tty01 tty02 tty03 ttyc0 ttyc1 ttyc2 ttyc3 ttyc4 ttyc5 ttyc6 + R ttyc7 apm crypto pf pctr systrace wd0 wd1 wd2 wd3 raid0 +- R raid1 raid2 raid3 std st0 st1 fd mcd0 ipl ++ R raid1 raid2 raid3 std st0 st1 fd mcd0 + ;; + + wd*|sd*|raid*|ccd*) +--- ./etc/etc.i386/MAKEDEV.md Sat Jul 10 12:42:30 2004 ++++ ./etc/etc.i386/MAKEDEV.md.orig Sun Mar 14 05:38:05 2004 +@@ -73,7 +73,6 @@ + _DEV(fdesc, 22) + _DEV(gpr, 80) + _DEV(iop, 75) +-_DEV(ipl, 82) + _DEV(joy, 26) + _DEV(lkm, 28) + _DEV(music, 53) +--- ./etc/etc.mac68k/MAKEDEV Sat Jul 10 12:50:48 2004 ++++ ./etc/etc.mac68k/MAKEDEV.orig Sun Mar 14 05:38:06 2004 +@@ -52,7 +52,6 @@ + # asc* ASC Audio device + # bpf* Berkeley Packet Filter + # fd fd/* nodes for fdescfs +-# ipl IP Filter + # lkm Loadable kernel modules interface + # pf* Packet Filter + # *random In-kernel random data source +@@ -281,16 +280,6 @@ + done + ;; + +-ipl) +- M ipl c 38 0 600 +- M ipnat c 38 1 600 +- M ipstate c 38 2 600 +- M ipauth c 38 3 600 +- M ipsync c 38 4 600 +- M ipscan c 38 5 600 +- M iplookup c 38 6 600 +- ;; +- + pf*) + M pf c 35 0 600 + ;; +@@ -381,7 +370,6 @@ + R pty2 xfs0 ss0 ss1 ch0 vnd0 vnd1 vnd2 vnd3 sd0 sd1 sd2 sd3 + R sd4 ptm local grf0 grf1 grf2 grf3 adb asc0 uk0 random lkm + R tty00 tty01 pf systrace std st0 st1 fd +- R ipl + ;; + + sd*|ccd*) +--- ./etc/etc.mac68k/MAKEDEV.md Sat Jul 10 12:42:34 2004 ++++ ./etc/etc.mac68k/MAKEDEV.md.orig Sat Feb 21 15:05:05 2004 +@@ -50,7 +50,6 @@ + _DEV(asc, 36) + _DEV(bpf, 22) + _DEV(fdesc, 21) +-_DEV(ipl, 38) + _DEV(lkm, 25) + _DEV(pf, 35) + _DEV(rnd, 32) +--- ./etc/etc.macppc/MAKEDEV Sat Jul 10 12:51:17 2004 ++++ ./etc/etc.macppc/MAKEDEV.orig Sun Mar 14 05:38:06 2004 +@@ -70,7 +70,6 @@ + # crypto Hardware crypto access driver + # fd fd/* nodes for fdescfs + # iop* I2O controller devices +-# ipl IP Filter + # lkm Loadable kernel modules interface + # pci PCI bus device + # pf* Packet Filter +@@ -273,16 +272,6 @@ + MKlist="$MKlist;[ -e radio ] || ln -s radio$U radio" + ;; + +-ipl) +- M ipl c 45 0 600 +- M ipnat c 45 1 600 +- M ipstate c 45 2 600 +- M ipauth c 45 3 600 +- M ipsync c 45 4 600 +- M ipscan c 45 5 600 +- M iplookup c 45 6 600 +- ;; +- + pf*) + M pf c 39 0 600 + ;; +@@ -479,7 +468,6 @@ + R local wscons pci iop0 iop1 uall tuner0 radio0 audio0 uk0 + R random lkm tty00 tty01 tty02 tty03 apm crypto pf systrace + R wd0 wd1 wd2 wd3 raid0 raid1 raid2 raid3 std st0 st1 fd +- R ipl + ;; + + wd*|sd*|raid*|ccd*) +--- ./etc/etc.macppc/MAKEDEV.md Sat Jul 10 12:38:34 2004 ++++ ./etc/etc.macppc/MAKEDEV.md.orig Sun Mar 14 05:38:06 2004 +@@ -66,7 +66,6 @@ + _DEV(lkm, 24) + _DEV(pci, 71) + _DEV(pf, 39) +-_DEV(mapppc, 45) + _DEV(radio, 76) + _DEV(rnd, 40) + _DEV(ss, 42) +--- ./etc/etc.mvme68k/MAKEDEV Sat Jul 10 13:00:11 2004 ++++ ./etc/etc.mvme68k/MAKEDEV.orig Sun Mar 14 05:38:06 2004 +@@ -53,7 +53,6 @@ + # bpf* Berkeley Packet Filter + # fd fd/* nodes for fdescfs + # flash0 On-board flash memory +-# ipl IP Filter + # lkm Loadable kernel modules interface + # nvram0 On-board non-volatile memory + # pf* Packet Filter +@@ -274,16 +273,6 @@ + M flash0 c 11 0 640 kmem + ;; + +-ipl) +- M ipl c 45 0 600 +- M ipnat c 45 1 600 +- M ipstate c 45 2 600 +- M ipauth c 45 3 600 +- M ipsync c 45 4 600 +- M ipscan c 45 5 600 +- M iplookup c 45 6 600 +- ;; +- + fd) + RMlist="mkdir -p fd;$RMlist" n=0 + while [ $n -lt 64 ];do M fd/$n c 21 $n;n=$(($n+1));done +@@ -419,7 +408,7 @@ + R vnd2 vnd3 sd0 sd1 sd2 sd3 sd4 cd0 cd1 rd0 tun0 tun1 tun2 + R tun3 bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 pty0 + R pty1 pty2 xfs0 ss0 ss1 ch0 vmel0 vmes0 flash0 nvram0 sram0 +- R ptm local uk0 random lkm pf systrace std st0 st1 fd ipl ++ R ptm local uk0 random lkm pf systrace std st0 st1 fd + ;; + + sd*|ccd*) +--- ./etc/etc.mvme68k/MAKEDEV.md Sat Jul 10 12:42:39 2004 ++++ ./etc/etc.mvme68k/MAKEDEV.md.orig Sat Feb 21 15:05:05 2004 +@@ -151,7 +151,6 @@ + _DEV(bpf, 22) + _DEV(fdesc, 21) + _DEV(flash, 11) +-_DEV(ipl, 45) + _DEV(lkm, 24) + _DEV(nvram, 10) + _DEV(pf, 39) +@@ -169,13 +168,4 @@ + dnl + _std(1, 2, 43, 3, 6) + ;; +- +-ipl) +- rm -f ipl ipnat ipstate ipauth +- mknod ipl c 44 0 +- mknod ipnat c 44 1 +- mknod ipstate c 44 2 +- mknod ipauth c 44 3 +- chown root.wheel ipl ipnat ipstate ipauth +- ;; + +--- ./etc/etc.mvme88k/MAKEDEV Sat Jul 10 13:00:13 2004 ++++ ./etc/etc.mvme88k/MAKEDEV.orig Sun Mar 14 05:38:06 2004 +@@ -49,7 +49,6 @@ + # Special purpose devices: + # bpf* Berkeley Packet Filter + # fd fd/* nodes for fdescfs +-# ipl IP Filter + # lkm Loadable kernel modules interface + # nvram0 On-board non-volatile memory + # pf* Packet Filter +@@ -266,16 +265,6 @@ + M lkm c 24 0 640 _lkm + ;; + +-ipl) +- M ipl c 45 0 600 +- M ipnat c 45 1 600 +- M ipstate c 45 2 600 +- M ipauth c 45 3 600 +- M ipsync c 45 4 600 +- M ipscan c 45 5 600 +- M iplookup c 45 6 600 +- ;; +- + fd) + RMlist="mkdir -p fd;$RMlist" n=0 + while [ $n -lt 64 ];do M fd/$n c 21 $n;n=$(($n+1));done +@@ -388,7 +377,6 @@ + R tun0 tun1 tun2 tun3 bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 + R bpf8 bpf9 pty0 pty1 pty2 xfs0 ss0 ch0 vmel0 vmes0 nvram0 + R sram0 ptm local uk0 random lkm pf systrace std st0 st1 fd +- R ipl + ;; + + sd*|ccd*) +--- ./etc/etc.mvme88k/MAKEDEV.md Sat Jul 10 12:42:42 2004 ++++ ./etc/etc.mvme88k/MAKEDEV.md.orig Sat Feb 21 15:05:05 2004 +@@ -122,7 +122,6 @@ + _TITLE(spec) + _DEV(bpf, 22) + _DEV(fdesc, 21) +-_DEV(ipl, 45) + _DEV(lkm, 24) + _DEV(nvram, 10) + _DEV(pf, 39) +@@ -140,13 +139,4 @@ + dnl + _std(1, 2, 43, 3, 6) + ;; +- +-ipl) +- rm -f ipl ipnat ipstate ipauth +- mknod ipl c 41 0 +- mknod ipnat c 41 1 +- mknod ipstate c 41 2 +- mknod ipauth c 41 3 +- chown root.wheel ipl ipnat ipstate ipauth +- ;; + +--- ./etc/etc.mvmeppc/MAKEDEV Sat Jul 10 12:58:40 2004 ++++ ./etc/etc.mvmeppc/MAKEDEV.orig Sun Oct 26 10:29:33 2003 +@@ -73,7 +73,6 @@ + # audio* audio + # ch* SCSI media changer + # bpf* Berkeley Packet Filter +-# ipl IP Filter + # tun* network tunnel driver + # lkm loadable kernel modules interface + # *random inkernal random data source +@@ -157,7 +156,7 @@ + sh $this ttyC0 ttyCcfg + sh $this tty00 tty01 tty02 tty03 pty0 pty1 + sh $this bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 bpf7 bpf8 bpf9 +- sh $this ipl pf tun0 tun1 tun2 tun3 ++ sh $this pf tun0 tun1 tun2 tun3 + sh $this audio0 + sh $this random uk0 uk1 ss0 ss1 + sh $this wscons +@@ -523,19 +522,6 @@ + rm -f bpf${unit} + mknod bpf${unit} c 22 ${unit} + chown root.wheel bpf${unit} +- ;; +- +-ipl) +- rm -f ipl ipnat ipstate ipauth +- mknod ipl c 44 0 +- mknod ipnat c 44 1 +- mknod ipstate c 44 2 +- mknod ipauth c 44 3 +- mknod ipsync c 44 4 +- mknod ipscan c 44 5 +- mknod iplookup c 44 6 +- chown root:wheel ipl ipnat ipstate ipauth ipsync ipscan iplookup +- chmod 600 ipl ipnat ipstate ipauth ipsync ipscan iplookup + ;; + + pf) +--- ./etc/etc.sparc/MAKEDEV Sat Jul 10 13:00:16 2004 ++++ ./etc/etc.sparc/MAKEDEV.orig Sun Mar 14 05:38:07 2004 +@@ -64,7 +64,6 @@ + # bppmag[mno] Magma parallel port + # bpp[jkl] "spif" parallel port + # fd fd/* nodes for fdescfs +-# ipl IP Filter + # lkm Loadable kernel modules interface + # openprom + # magma* Magma multiport cards +@@ -285,16 +284,6 @@ + done + ;; + +-ipl) +- M ipl c 60 0 600 +- M ipnat c 60 1 600 +- M ipstate c 60 2 600 +- M ipauth c 60 3 600 +- M ipsync c 60 4 600 +- M ipscan c 60 5 600 +- M iplookup c 60 6 600 +- ;; +- + pf*) + M pf c 59 0 600 + ;; +@@ -506,7 +495,7 @@ + R fd0C fd0D fd0E fd0F fd0G fd0H xfs0 ss0 ss1 ch0 ses0 cuaa + R cuab cuac cuad ttya ttyb ttyc ttyd ptm local wscons audio0 + R uk0 random lkm pf systrace xd0 xd1 xd2 xd3 raid0 raid1 raid2 +- R raid3 std st0 st1 fd ipl ++ R raid3 std st0 st1 fd + ;; + + presto*|xd*|xy*|sd*|raid*|ccd*) +--- ./etc/etc.sparc/MAKEDEV.md Sat Jul 10 12:42:51 2004 ++++ ./etc/etc.sparc/MAKEDEV.md.orig Sat Feb 21 15:05:06 2004 +@@ -90,7 +90,6 @@ + _DEV(bppmag, 101) + _DEV(bppsp, 103) + _DEV(fdesc, 24) +-_DEV(ipl, 60) + _DEV(lkm, 112) + _DEV(oppr) + _DEV(mag, 100) +--- ./etc/etc.sparc64/MAKEDEV Sat Jul 10 12:59:31 2004 ++++ ./etc/etc.sparc64/MAKEDEV.orig Sun Mar 14 05:38:07 2004 +@@ -78,7 +78,6 @@ + # bpp[jkl] "spif" parallel port + # crypto Hardware crypto access driver + # fd fd/* nodes for fdescfs +-# ipl IP Filter + # lkm Loadable kernel modules interface + # magma* Magma multiport cards + # pci PCI bus device +@@ -303,16 +302,6 @@ + done + ;; + +-ipl) +- M ipl c 82 0 600 +- M ipnat c 82 1 600 +- M ipstate c 82 2 600 +- M ipauth c 82 3 600 +- M ipsync c 82 4 600 +- M ipscan c 82 5 600 +- M iplookup c 82 6 600 +- ;; +- + pf*) + M pf c 73 0 600 + ;; +@@ -584,7 +573,7 @@ + R ccd2 ccd3 ptm local wscons pci uall audio0 uk0 random lpa0 + R lpa1 lpa2 lpt0 lpt1 lpt2 lkm tty00 tty01 tty02 tty03 ttyh0 + R ttyh1 crypto pf systrace wd0 wd1 wd2 wd3 raid0 raid1 raid2 +- R raid3 std st0 st1 fd ipl ++ R raid3 std st0 st1 fd + ;; + + wd*|sd*|raid*|ccd*) +--- ./etc/etc.sparc64/MAKEDEV.md Sat Jul 10 12:42:57 2004 ++++ ./etc/etc.sparc64/MAKEDEV.md.orig Sun Mar 14 05:38:07 2004 +@@ -96,7 +96,6 @@ + _DEV(bppsp, 109) + _DEV(cry, 75) + _DEV(fdesc, 24) +--DEV(ipl, 82) + _DEV(lkm, 112) + _DEV(mag, 71) + _DEV(pci, 52) +--- ./etc/etc.vax/MAKEDEV Sat Jul 10 13:00:00 2004 ++++ ./etc/etc.vax/MAKEDEV.orig Sun Mar 14 05:38:07 2004 +@@ -68,7 +68,6 @@ + # Special purpose devices: + # bpf* Berkeley Packet Filter + # fd fd/* nodes for fdescfs +-# ipl IP Filter + # lkm Loadable kernel modules interface + # pf* Packet Filter + # *random In-kernel random data source +@@ -316,16 +315,6 @@ + done + ;; + +-ipl) +- M ipl c 47 0 600 +- M ipnat c 47 1 600 +- M ipstate c 47 2 600 +- M ipauth c 47 3 600 +- M ipsync c 47 4 600 +- M ipscan c 47 5 600 +- M iplookup c 47 6 600 +- ;; +- + pf*) + M pf c 42 0 600 + ;; +@@ -503,7 +492,7 @@ + R sd1 sd2 sd3 cd0 tun0 tun1 bpf0 bpf1 bpf2 bpf3 bpf4 bpf5 bpf6 + R bpf7 pty0 pty1 ss0 ptm local uk0 random lkm pf systrace rx0 + R rx1 ra0 ra1 ra2 ra3 hp0 hp1 hp2 hp3 raid0 raid1 raid2 raid3 +- R std st0 st1 fd ipl ++ R std st0 st1 fd + ;; + + up*|sd*|rx*|rl*|rb*|raid*|ra*|hp*|hk*|hd*|ccd*) +--- ./etc/etc.vax/MAKEDEV.md Sat Jul 10 12:41:58 2004 ++++ ./etc/etc.vax/MAKEDEV.md.orig Sat Feb 21 15:05:07 2004 +@@ -144,7 +144,6 @@ + _TITLE(spec) + _DEV(bpf, 56) + _DEV(fdesc, 53) +-_DEV(ipl, 47) + _DEV(lkm, 28) + _DEV(pf, 42) + _DEV(rnd, 67) +--- ./etc/MAKEDEV.common Sat Jul 10 12:19:30 2004 ++++ ./etc/MAKEDEV.common.orig Sat Jul 10 12:28:18 2004 +@@ -123,13 +123,6 @@ + target(all, pctr)dnl + target(all, pctr0)dnl + target(all, pf)dnl +-target(all, ipl)dnl +-target(all, ipnat)dnl +-target(all, ipstate)dnl +-target(all, ipauth)dnl +-target(all, ipsync)dnl +-target(all, ipscan)dnl +-target(all, iplookup)dnl + twrget(all, cry, crypto)dnl + target(all, apm)dnl + twrget(all, tth, ttyh, 0, 1)dnl +@@ -479,20 +472,6 @@ + _mkdev(cry, crypto, {-M crypto c major_cry_c-} 0)dnl + __devitem(pf, pf*, Packet Filter)dnl + _mkdev(pf, {-pf*-}, {-M pf c major_pf_c 0 600-})dnl +-__devitem(ipl, ipl*, Packet Filter log)dnl +-_mkdev(ipl, {-ipl*-}, {-M ipl c major_ipl_c 0 600-})dnl +-__devitem(ipnat, ipnat*, Packet Filter NAT)dnl +-_mkdev(ipnat, {-ipnat*-}, {-M ipnat c major_ipnat_c 1 600-})dnl +-__devitem(ipstate, ipstate*, Packet Filter state)dnl +-_mkdev(ipstate, {-ipstate*-}, {-M ipstate c major_ipstate_c 2 600-})dnl +-__devitem(ipauth, ipauth*, Packet Filter auth)dnl +-_mkdev(ipauth, {-ipauth*-}, {-M ipauth c major_ipauth_c 3 600-})dnl +-__devitem(ipsync, ipsync*, Packet Filter auth)dnl +-_mkdev(ipsync, {-ipsync*-}, {-M ipsync c major_ipsync_c 4 600-})dnl +-__devitem(ipscan, ipscan*, Packet Filter auth)dnl +-_mkdev(ipscan, {-ipscan*-}, {-M ipscan c major_ipscan_c 5 600-})dnl +-__devitem(iplookup, iplookup*, Packet Filter auth)dnl +-_mkdev(iplookup, {-iplookup*-}, {-M iplookup c major_iplookup_c 6 600-})dnl + __devitem(bpf, bpf*, Berkeley Packet Filter)dnl + _mkdev(bpf, {-bpf*-}, {-M bpf$U c major_bpf_c $U 600-}, 600)dnl + _mkdev(tun, {-tun*-}, {-M tun$U c major_tun_c $U 600-}, 600)dnl diff --git a/OpenBSD-3/3.5-rc-diffs b/OpenBSD-3/3.5-rc-diffs new file mode 100644 index 0000000000000..bac3d790e33e7 --- /dev/null +++ b/OpenBSD-3/3.5-rc-diffs @@ -0,0 +1,91 @@ +diff -c tmp/etc/netstart etc/netstart +*** etc/netstart.orig Tue Mar 23 10:15:38 2004 +--- etc/netstart Sat Jul 10 11:56:56 2004 +*************** +*** 194,199 **** +--- 194,209 ---- + domainname `cat /etc/defaultdomain` + fi + ++ # Configure the IP filter before configuring network interfaces ++ if [ X"${ipfilter}" = X"YES" -a -f "${ipfilter_rules}" ]; then ++ echo 'configuring IP filter' ++ ipf -Fa -f ${ipfilter_rules} ++ ipfresync="ipf -y" ++ else ++ ipfilter=NO ++ ipfresync=NO ++ fi ++ + # Set the address for the loopback interface. Bringing the + # interface up, automatically invokes the IPv6 address ::1) + ifconfig lo0 inet 127.0.0.1 +*************** +*** 354,356 **** +--- 364,379 ---- + + bridgestart $if + done ++ ++ # Configure NAT after configuring network interfaces ++ if [ "${ipnat}" = "YES" -a "${ipfilter}" = "YES" -a -f "${ipnat_rules}" ]; then ++ echo 'configuring NAT' ++ ipnat -CF -f ${ipnat_rules} ++ else ++ ipnat=NO ++ fi ++ ++ # Interfaces have come up so we should do an ipf -y if we're using IP filter. ++ if [ "${ipfresync}" != "NO" ]; then ++ ${ipfresync} ++ fi +diff -c tmp/etc/rc etc/rc +*** tmp/etc/rc 23 Mar 2003 18:45:34 -0000 1.225 +--- etc/rc 8 Jun 2003 07:40:22 -0000 +*************** +*** 220,225 **** +--- 220,229 ---- + echo 'starting named'; named $named_flags + fi + ++ if [ X"${ipfilter}" = X"YES" -a X"${ipmon_flags}" != X"NO" ]; then ++ echo 'starting ipmon'; ipmon ${ipmon_flags} ++ fi ++ + # $isakmpd_flags is imported from /etc/rc.conf; + # If $isakmpd_flags == NO or /etc/isakmpd/isakmpd.policy doesn't exist, then + # isakmpd isn't run. +diff -c tmp/etc/rc.conf etc/rc.conf +*** tmp/etc/rc.conf 10 Mar 2003 01:05:28 -0000 1.86 +--- etc/rc.conf 8 Jun 2003 07:40:24 -0000 +*************** +*** 52,58 **** + lockd=NO + gated=NO + amd=NO +! pf=NO # Packet filter / NAT + portmap=NO # Note: inetd(8) rpc services need portmap too + inetd=YES # almost always needed + check_quotas=YES # NO may be desirable in some YP environments +--- 52,60 ---- + lockd=NO + gated=NO + amd=NO +! ipfilter=NO # To enable ipfilter, set to YES +! ipnat=NO # for "YES", ipfilter must also be "YES" +! pf=NO # Enable pf(4) Packet filter / NAT + portmap=NO # Note: inetd(8) rpc services need portmap too + inetd=YES # almost always needed + check_quotas=YES # NO may be desirable in some YP environments +*************** +*** 76,81 **** +--- 78,86 ---- + nfsd_flags="-tun 4" # Crank the 4 for a busy NFS fileserver + amd_dir=/tmp_mnt # AMD's mount directory + amd_master=/etc/amd/master # AMD 'master' map ++ ipfilter_rules=/etc/ipf.rules # Rules for IP packet filtering with IP Filter ++ ipnat_rules=/etc/ipnat.rules # Rules for Network Address Translation ++ ipmon_flags=-Ds # To disable logging, use ipmon_flags=NO + syslogd_flags= # add more flags, ie. "-u -a /chroot/dev/log" + pf_rules=/etc/pf.conf # Packet filter rules file + pflogd_flags= # add more flags, ie. "-s 256" diff --git a/OpenBSD-3/3.5-sys-diffs b/OpenBSD-3/3.5-sys-diffs new file mode 100644 index 0000000000000..9b0a0291aa299 --- /dev/null +++ b/OpenBSD-3/3.5-sys-diffs @@ -0,0 +1,778 @@ +--- sys/arch/alpha/alpha/conf.c.orig Sat Feb 21 15:09:52 2004 ++++ sys/arch/alpha/alpha/conf.c Thu Jul 8 14:04:39 2004 +@@ -103,6 +103,11 @@ + #include "lpt.h" + cdev_decl(lpt); + cdev_decl(prom); /* XXX XXX XXX */ ++#ifdef IPFILTER ++#define NIPF 1 ++#else ++#define NIPF 0 ++#endif + cdev_decl(wd); + cdev_decl(fd); + #include "cy.h" +@@ -173,7 +178,7 @@ + cdev_midi_init(NMIDI,midi), /* 41: MIDI I/O */ + cdev_midi_init(NSEQUENCER,sequencer), /* 42: sequencer I/O */ + cdev_disk_init(NRAID,raid), /* 43: RAIDframe disk driver */ +- cdev_notdef(), /* 44 */ ++ cdev_gen_ipf(NIPF,ipl), /* 44: IP filter log */ + cdev_usb_init(NUSB,usb), /* 45: USB controller */ + cdev_usbdev_init(NUHID,uhid), /* 46: USB generic HID */ + cdev_ulpt_init(NULPT,ulpt), /* 47: USB printer */ +--- sys/arch/hp300/hp300/conf.c.orig Sat Feb 21 15:10:07 2004 ++++ sys/arch/hp300/hp300/conf.c Thu Jul 8 14:04:40 2004 +@@ -122,6 +122,12 @@ + cdev_decl(xfs_dev); + #endif + ++#ifdef IPFILTER ++#define NIPF 1 ++#else ++#define NIPF 0 ++#endif ++ + #include "pf.h" + + #include "systrace.h" +@@ -165,7 +171,7 @@ + cdev_disk_init(NRD,rd), /* 34: RAM disk */ + cdev_tty_init(NAPCI,apci), /* 35: Apollo APCI UARTs */ + cdev_ksyms_init(NKSYMS,ksyms), /* 36: Kernel symbols device */ +- cdev_notdef(), /* 37 */ ++ cdev_pf_init(NIPF,ipl), /* 37: packet filter */ + cdev_notdef(), /* 38 */ + cdev_notdef(), /* 39 */ + cdev_notdef(), /* 40 */ +--- sys/arch/hppa/hppa/conf.c.orig Sat Feb 21 15:10:10 2004 ++++ sys/arch/hppa/hppa/conf.c Thu Jul 8 14:07:09 2004 +@@ -107,6 +107,12 @@ + #include "com.h" + cdev_decl(com); + ++#ifdef IPFILTER ++#define NIPF 1 ++#else ++#define NIPF 0 ++#endif ++ + #include "pf.h" + + #include "systrace.h" +@@ -166,7 +172,7 @@ + cdev_crypto_init(NCRYPTO,crypto), /* 36: /dev/crypto */ + cdev_ses_init(NSES,ses), /* 37: SCSI SES/SAF-TE */ + cdev_ptm_init(NPTY,ptm), /* 38: pseudo-tty ptm device */ +- cdev_lkm_dummy(), ++ cdev_gen_ipf(NIPF,ipl), /* 39: ip filtering */ + cdev_lkm_dummy(), + cdev_lkm_dummy(), + cdev_lkm_dummy(), +--- sys/arch/i386/i386/conf.c.orig Sat Feb 21 15:10:12 2004 ++++ sys/arch/i386/i386/conf.c Thu Jul 8 14:07:28 2004 +@@ -185,6 +185,12 @@ + #include "radio.h" + #include "gpr.h" + ++#ifdef IPFILTER ++#define NIPF 1 ++#else ++#define NIPF 0 ++#endif ++ + /* XXX -- this needs to be supported by config(8)! */ + #if (NCOM > 0) && (NPCCOM > 0) + #error com and pccom are mutually exclusive. Sorry. +@@ -310,6 +316,7 @@ + cdev_oci_init(NBIO,bio), /* 79: ioctl tunnel */ + cdev_ch_init(NGPR,gpr), /* 80: GPR400 SmartCard reader */ + cdev_ptm_init(NPTY,ptm), /* 81: pseudo-tty ptm device */ ++ cdev_gen_ipf(NIPF,ipl), /* 82: ip filtering */ + }; + int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]); + +--- sys/arch/mac68k/mac68k/conf.c.orig Sat Feb 21 15:10:19 2004 ++++ sys/arch/mac68k/mac68k/conf.c Thu Jul 8 14:04:40 2004 +@@ -104,6 +104,12 @@ + cdev_decl(xfs_dev); + #endif + ++#ifdef IPFILTER ++#define NIPF 1 ++#else ++#define NIPF 0 ++#endif ++ + #include "pf.h" + + #include "systrace.h" +@@ -148,7 +154,7 @@ + cdev_pf_init(NPF,pf), /* 35: packet filter */ + cdev_audio_init(NASC,asc), /* 36: ASC audio device */ + cdev_ksyms_init(NKSYMS,ksyms), /* 37: Kernel symbols device */ +- cdev_notdef(), /* 38 */ ++ cdev_gen_ipf(NIPF,ipl), /* 38: IP filter log */ + cdev_notdef(), /* 39 */ + cdev_notdef(), /* 40 */ + cdev_notdef(), /* 41 */ +--- sys/arch/macppc/macppc/conf.c.orig Sat Feb 21 15:10:20 2004 ++++ sys/arch/macppc/macppc/conf.c Thu Jul 8 14:04:40 2004 +@@ -105,6 +105,12 @@ + + #include "tun.h" + ++#ifdef IPFILTER ++#define NIPF 1 ++#else ++#define NIPF 0 ++#endif ++ + #ifdef XFS + #include <xfs/nxfs.h> + cdev_decl(xfs_dev); +@@ -191,7 +197,7 @@ + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ + cdev_audio_init(NAUDIO,audio), /* 44: generic audio I/O */ +- cdev_notdef(), /* 45 */ ++ cdev_gen_ipf(NIPF,ipl), /* 45: IP filter */ + cdev_notdef(), /* 46 */ + cdev_crypto_init(NCRYPTO,crypto), /* 47: /dev/crypto */ + cdev_notdef(), /* 48 */ +--- sys/arch/mvme68k/mvme68k/conf.c.orig Sat Feb 21 15:10:21 2004 ++++ sys/arch/mvme68k/mvme68k/conf.c Thu Jul 8 14:08:04 2004 +@@ -148,6 +148,12 @@ + #include "bpfilter.h" + #include "tun.h" + ++#ifdef IPFILTER ++#define NIPF 1 ++#else ++#define NIPF 0 ++#endif ++ + #include "pf.h" + + #include "systrace.h" +@@ -203,7 +209,7 @@ + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ + cdev_ch_init(NCH,ch), /* 44: SCSI autochanger */ +- cdev_lkm_dummy(), /* 45 */ ++ cdev_gen_ipf(NIPF,ipl), /* 45: IP filter */ + cdev_lkm_dummy(), /* 46 */ + cdev_lkm_dummy(), /* 47 */ + cdev_lkm_dummy(), /* 48 */ +--- sys/arch/mvme88k/mvme88k/conf.c.orig Sat Feb 21 15:10:24 2004 ++++ sys/arch/mvme88k/mvme88k/conf.c Thu Jul 8 14:09:53 2004 +@@ -99,6 +99,12 @@ + cdev_decl(lptwo); + #endif /* notyet */ + ++#ifdef IPFILTER ++#define NIPF 1 ++#else ++#define NIPF 0 ++#endif ++ + #include "pf.h" + + #include "systrace.h" +@@ -189,7 +195,7 @@ + cdev_ss_init(NSS,ss), /* 42 */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ + cdev_ch_init(NCH,ch), /* 44: SCSI autochanger */ +- cdev_notdef(), /* 45 */ ++ cdev_gen_ipf(NIPF,ipl), /* 45: IP filter */ + cdev_notdef(), /* 46 */ + cdev_notdef(), /* 47 */ + cdev_notdef(), /* 48 */ +--- sys/arch/mvmeppc/mvmeppc/conf.c.orig Sat Feb 21 15:10:29 2004 ++++ sys/arch/mvmeppc/mvmeppc/conf.c Thu Jul 8 14:04:41 2004 +@@ -112,6 +112,12 @@ + + #include "ksyms.h" + ++#ifdef IPFILTER ++#define NIPF 1 ++#else ++#define NIPF 0 ++#endif ++ + #include "pf.h" + + #include "systrace.h" +@@ -165,7 +171,7 @@ + cdev_uk_init(NUK,uk), /* 41: unknown SCSI */ + cdev_ss_init(NSS,ss), /* 42: SCSI scanner */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ +- cdev_notdef(), /* 44 */ ++ cdev_gen_ipf(NIPF,ipl), /* 44: IP filter */ + cdev_notdef(), /* 45 */ + cdev_notdef(), /* 46 */ + cdev_notdef(), /* 47 */ +--- sys/arch/sparc/sparc/conf.c.orig Sat Feb 21 15:10:36 2004 ++++ sys/arch/sparc/sparc/conf.c Thu Jul 8 14:04:41 2004 +@@ -124,6 +124,12 @@ + }; + int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]); + ++#ifdef IPFILTER ++#define NIPF 1 ++#else ++#define NIPF 0 ++#endif ++ + #include "pf.h" + + #include "systrace.h" +@@ -194,7 +200,7 @@ + cdev_notdef(), /* 57 */ + cdev_disk_init(NCD,cd), /* 58: SCSI CD-ROM */ + cdev_pf_init(NPF,pf), /* 59: packet filter */ +- cdev_notdef(), /* 60 */ ++ cdev_gen_ipf(NIPF,ipl), /* 60: ip filtering log */ + cdev_notdef(), /* 61 */ + cdev_notdef(), /* 62 */ + cdev_notdef(), /* 63 */ +--- sys/arch/sparc64/sparc64/conf.c.orig Sat Feb 21 15:10:38 2004 ++++ sys/arch/sparc64/sparc64/conf.c Thu Jul 8 14:04:41 2004 +@@ -110,6 +110,12 @@ + #include "ucom.h" + #include "uscanner.h" + ++#ifdef IPFILTER ++#define NIPF 1 ++#else ++#define NIPF 0 ++#endif ++ + #include "pf.h" + + #ifdef XFS +@@ -246,7 +252,7 @@ + cdev_mouse_init(NWSKBD, wskbd), /* 79: keyboards */ + cdev_mouse_init(NWSMOUSE, wsmouse), /* 80: mice */ + cdev_mouse_init(NWSMUX, wsmux), /* 81: ws multiplexor */ +- cdev_notdef(), /* 82 */ ++ cdev_gen_ipf(NIPF,ipl), /* 82: IP filter */ + cdev_notdef(), /* 83 */ + cdev_notdef(), /* 84 */ + cdev_notdef(), /* 85 */ +--- sys/arch/vax/vax/conf.c.orig Sat Feb 21 15:10:41 2004 ++++ sys/arch/vax/vax/conf.c Thu Jul 8 14:04:41 2004 +@@ -353,6 +353,12 @@ + #include "wskbd.h" + #include "wsmouse.h" + ++#ifdef IPFILTER ++#define NIPF 1 ++#else ++#define NIPF 0 ++#endif ++ + #include "pf.h" + + #include "systrace.h" +@@ -406,7 +412,7 @@ + cdev_notdef(), /* 44 was Datakit */ + cdev_notdef(), /* 45 was Datakit */ + cdev_notdef(), /* 46 was Datakit */ +- cdev_notdef(), /* 47 */ ++ cdev_gen_ipf(NIPF,ipl), /* 47: IP filter */ + cdev_notdef(), /* 48 */ + cdev_systrace_init(NSYSTRACE,systrace), /* 49: system call tracing */ + cdev_ksyms_init(NKSYMS,ksyms), /* 50: Kernel symbols device */ +--- sys/arch/amd64/amd64/conf.c.orig Thu Feb 26 06:22:12 2004 ++++ sys/arch/amd64/amd64/conf.c Sat Jul 10 12:31:46 2004 +@@ -191,6 +191,12 @@ + + #include "pf.h" + ++#ifdef IPFILTER ++#define NIPF 1 ++#else ++#define NIPF 0 ++#endif ++ + struct cdevsw cdevsw[] = + { + cdev_cn_init(1,cn), /* 0: virtual console */ +@@ -295,6 +301,7 @@ + cdev_oci_init(NBIO,bio), /* 79: ioctl tunnel */ + cdev_notdef(), /* 80: gpr? XXX */ + cdev_ptm_init(NPTY,ptm), /* 81: pseudo-tty ptm device */ ++ cdev_gen_ipf(NIPF, ipl), /* 82: IP Filtering */ + }; + int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]); + +--- sys/conf/GENERIC.orig Wed Mar 3 08:23:46 2004 ++++ sys/conf/GENERIC Thu Jul 8 14:04:41 2004 +@@ -72,6 +72,8 @@ + #option EON # OSI tunneling over IP + #option NETATALK # AppleTalk + #option CCITT,LLC,HDLC # X.25 ++option IPFILTER # IP packet filter for security ++option IPFILTER_LOG # use /dev/ipl to log IPF + option PPP_BSDCOMP # PPP BSD compression + option PPP_DEFLATE + #option MROUTING # Multicast router +--- sys/conf/files.orig Sun Mar 14 05:44:13 2004 ++++ sys/conf/files Thu Jul 8 14:04:41 2004 +@@ -719,6 +719,14 @@ + file netinet/tcp_usrreq.c inet + file netinet/udp_usrreq.c inet + file netinet/ip_gre.c inet ++file netinet/ip_fil.c ipfilter ++file netinet/fil.c ipfilter ++file netinet/ip_nat.c ipfilter ++file netinet/ip_frag.c ipfilter ++file netinet/ip_state.c ipfilter ++file netinet/ip_proxy.c ipfilter ++file netinet/ip_auth.c ipfilter ++file netinet/ip_log.c ipfilter + file netinet/ip_ipsp.c (inet | inet6) & (ipsec | tcp_signature) + file netinet/ip_spd.c (inet | inet6) & (ipsec | tcp_signature) + file netinet/ip_ipip.c inet | inet6 +--- sys/net/bridgestp.c.orig Wed Dec 3 09:00:10 2003 ++++ sys/net/bridgestp.c Thu Jul 8 14:04:42 2004 +@@ -58,6 +58,11 @@ + #include <netinet/in_var.h> + #include <netinet/ip.h> + #include <netinet/if_ether.h> ++ ++#ifdef IPFILTER ++#include <netinet/ip_compat.h> ++#include <netinet/ip_fil.h> ++#endif + #endif + + #if NBPFILTER > 0 +--- sys/net/if.c.orig Sun Feb 29 05:34:01 2004 ++++ sys/net/if.c Thu Jul 8 14:04:42 2004 +@@ -99,6 +99,12 @@ + #include <netinet6/nd6.h> + #endif + ++#ifdef IPFILTER ++#include <netinet/ip_compat.h> ++#include <netinet/ip_fil.h> ++#include <netinet/ip_nat.h> ++#endif ++ + #if NBPFILTER > 0 + #include <net/bpf.h> + #endif +@@ -556,6 +562,11 @@ + + /* Remove the interface from the list of all interfaces. */ + TAILQ_REMOVE(&ifnet, ifp, if_list); ++ ++#ifdef IPFILTER ++ /* XXX More ipf & ipnat cleanup needed. */ ++ frsync(ifp); ++#endif + + /* + * Deallocate private resources. +--- sys/net/if_bridge.c.orig Sat Feb 21 15:11:02 2004 ++++ sys/net/if_bridge.c Thu Jul 8 14:04:42 2004 +@@ -66,7 +66,11 @@ + #include <netinet/ip_ipsp.h> + + #include <net/if_enc.h> ++#if (defined(IPFILTER) || defined(IPFILTER_LKM)) ++#include <netinet/ip_compat.h> ++#include <netinet/ip_fil.h> + #endif ++#endif + + #ifdef INET6 + #include <netinet/ip6.h> +@@ -152,7 +156,7 @@ + int bridge_brlconf(struct bridge_softc *, struct ifbrlconf *); + u_int8_t bridge_filterrule(struct brl_head *, struct ether_header *, + struct mbuf *); +-#if NPF > 0 ++#if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + struct mbuf *bridge_filter(struct bridge_softc *, int, struct ifnet *, + struct ether_header *, struct mbuf *m); + #endif +@@ -1218,7 +1222,7 @@ + m_freem(m); + return; + } +-#if NPF > 0 ++#if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + m = bridge_filter(sc, BRIDGE_IN, src_if, &eh, m); + if (m == NULL) + return; +@@ -1261,7 +1265,7 @@ + m_freem(m); + return; + } +-#if NPF > 0 ++#if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + m = bridge_filter(sc, BRIDGE_OUT, dst_if, &eh, m); + if (m == NULL) + return; +@@ -1509,7 +1513,7 @@ + mc = m1; + } + +-#if NPF > 0 ++#if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + mc = bridge_filter(sc, BRIDGE_OUT, dst_if, eh, mc); + if (mc == NULL) + continue; +@@ -2287,6 +2291,12 @@ + * We don't need to do loop detection, the + * bridge will do that for us. + */ ++#if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (dir == BRIDGE_OUT && fr_checkp && ++ ((*fr_checkp)(ip, hlen, &encif[0].sc_if, ++ 1, &m) || !m)) ++ return 1; ++#endif + #if NPF > 0 + switch (af) { + #ifdef INET +@@ -2311,6 +2321,12 @@ + if (m == NULL) + return (1); + #endif /* NPF */ ++#if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (dir == BRIDGE_IN && fr_checkp && ++ ((*fr_checkp)(ip, hlen, &encif[0].sc_if, ++ 0, &m) || !m)) ++ return 1; ++#endif + error = ipsp_process_packet(m, tdb, af, 0); + return (1); + } else +@@ -2321,7 +2337,7 @@ + } + #endif /* IPSEC */ + +-#if NPF > 0 ++#if (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) + /* + * Filter IP packets by peeking into the ethernet frame. This violates + * the ISO model, but allows us to act as a IP filter at the data link +@@ -2424,14 +2440,32 @@ + return (NULL); + #endif /* IPSEC */ + +-#if NPF > 0 ++#if defined(IPFILTER) || defined(IPFILTER_LKM) || (NPF > 0) + /* Finally, we get to filter the packet! */ + m->m_pkthdr.rcvif = ifp; ++#endif ++#if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (dir == BRIDGE_OUT) { ++ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 1, &m)) ++ goto dropit; ++ if (m == NULL) ++ goto dropit; ++ } ++#endif ++#if NPF > 0 + if (pf_test(dir, ifp, &m) != PF_PASS) + goto dropit; + if (m == NULL) + goto dropit; + #endif /* NPF */ ++#if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (dir == BRIDGE_IN) { ++ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 0, &m)) ++ goto dropit; ++ if (m == NULL) ++ goto dropit; ++ } ++#endif + + /* Rebuild the IP header */ + if (m->m_len < hlen && ((m = m_pullup(m, hlen)) == NULL)) +@@ -2472,6 +2506,14 @@ + return (NULL); + #endif /* IPSEC */ + ++#if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (dir == BRIDGE_OUT) { ++ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 1, &m)) ++ goto dropit; ++ if (m == NULL) ++ return (NULL); ++ } ++#endif + #if NPF > 0 + if (pf_test6(dir, ifp, &m) != PF_PASS) + goto dropit; +@@ -2478,6 +2520,14 @@ + if (m == NULL) + return (NULL); + #endif /* NPF */ ++#if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (dir == BRIDGE_IN) { ++ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 0, &m)) ++ goto dropit; ++ if (m == NULL) ++ return (NULL); ++ } ++#endif + + break; + } +@@ -2509,7 +2559,7 @@ + m_freem(m); + return (NULL); + } +-#endif /* NPF > 0 */ ++#endif /* (NPF > 0) || (defined(IPFILTER) || defined(IPFILTER_LKM)) */ + + void + bridge_fragment(struct bridge_softc *sc, struct ifnet *ifp, +--- sys/netinet/in_proto.c.orig Tue Dec 16 15:33:09 2003 ++++ sys/netinet/in_proto.c Thu Jul 8 14:04:42 2004 +@@ -159,6 +159,11 @@ + #include <netinet/ip_mroute.h> + #endif /* MROUTING */ + ++#ifdef IPFILTER ++void iplinit __P((void)); ++#define ip_init iplinit ++#endif ++ + #ifdef INET6 + #include <netinet6/ip6_var.h> + #endif /* INET6 */ +--- sys/netinet/ip_input.c.orig Tue Mar 16 10:36:27 2004 ++++ sys/netinet/ip_input.c Thu Jul 8 14:04:42 2004 +@@ -149,6 +149,10 @@ + struct in_ifaddrhead in_ifaddr; + struct ifqueue ipintrq; + ++#if defined(IPFILTER) || defined(IPFILTER_LKM) ++int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++#endif ++ + int ipq_locked; + static __inline int ipq_lock_try(void); + static __inline void ipq_unlock(void); +@@ -404,6 +408,23 @@ + ip = mtod(m, struct ip *); + hlen = ip->ip_hl << 2; + pfrdr = (pfrdr != ip->ip_dst.s_addr); ++#endif ++ ++#if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * Check if we want to allow this packet to be processed. ++ * Consider it to be bad if not. ++ */ ++ { ++ struct mbuf *m0 = m; ++ if (fr_checkp && (*fr_checkp)(ip, hlen, m->m_pkthdr.rcvif, 0, &m0)) { ++ return; ++ } ++ if (m0 == 0) { /* in case of 'fastroute' */ ++ return; ++ } ++ ip = mtod(m = m0, struct ip *); ++ } + #endif + + /* +--- sys/netinet/ip_output.c.orig Sat Feb 21 15:11:04 2004 ++++ sys/netinet/ip_output.c Thu Jul 8 14:04:42 2004 +@@ -82,6 +82,10 @@ + static struct mbuf *ip_insertoptions(struct mbuf *, struct mbuf *, int *); + static void ip_mloopback(struct ifnet *, struct mbuf *, struct sockaddr_in *); + ++#if defined(IPFILTER) || defined(IPFILTER_LKM) ++extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++#endif ++ + /* + * IP output. The packet in mbuf chain m contains a skeletal IP + * header (with len, off, ttl, proto, tos, src, dst). +@@ -555,7 +559,31 @@ + if (sproto != 0) { + s = splnet(); + ++#if defined(IPFILTER) || defined(IPFILTER_LKM) ++ if (fr_checkp) { + /* ++ * Ok, it's time for a simple round-trip to the IPF/NAT ++ * code with the enc0 interface. ++ */ ++ struct mbuf *m1 = m; ++ void *ifp = (void *)&encif[0].sc_if; ++ ++ if ((*fr_checkp)(ip, hlen, ifp, 1, &m1)) { ++ error = EHOSTUNREACH; ++ splx(s); ++ goto done; ++ } ++ if (m1 == 0) { /* in case of 'fastroute' */ ++ error = 0; ++ splx(s); ++ goto done; ++ } ++ ip = mtod(m = m1, struct ip *); ++ hlen = ip->ip_hl << 2; ++ } ++#endif /* IPFILTER */ ++ ++ /* + * Packet filter + */ + #if NPF > 0 +@@ -653,6 +681,25 @@ + m->m_pkthdr.csum &= ~M_UDPV4_CSUM_OUT; /* Clear */ + } + } ++ ++#if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * looks like most checking has been done now...do a filter check ++ */ ++ { ++ struct mbuf *m1 = m; ++ ++ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 1, &m1)) { ++ error = EHOSTUNREACH; ++ goto done; ++ } ++ if (m1 == 0) { /* in case of 'fastroute' */ ++ error = 0; ++ goto done; ++ } ++ ip = mtod(m = m1, struct ip *); ++ } ++#endif + + /* + * Packet filter +--- sys/netinet6/ip6_input.c.orig Sat Feb 21 15:11:05 2004 ++++ sys/netinet6/ip6_input.c Thu Jul 8 14:04:42 2004 +@@ -128,6 +128,10 @@ + static int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *); + static struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int); + ++#if defined(IPFILTER) || defined(IPFILTER_LKM) ++extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++#endif ++ + /* + * IP6 initialization: fill in IP6 protocol switch table. + * All protocols not implemented in kernel go to raw IP6 protocol handler. +@@ -244,6 +248,26 @@ + in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); + goto bad; + } ++ ++#if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * Check if we want to allow this packet to be processed. ++ * Consider it to be bad if not. ++ */ ++ if (fr_checkp != NULL) { ++ struct mbuf *m0 = m; ++ ++ if ((*fr_checkp)((struct ip *)ip6, sizeof(*ip6), ++ m->m_pkthdr.rcvif, 0, &m0)) { ++ return; ++ } ++ m = m0; ++ if (m == 0) { /* in case of 'fastroute' */ ++ return; ++ } ++ ip6 = mtod(m, struct ip6_hdr *); ++ } ++#endif + + ip6stat.ip6s_nxthist[ip6->ip6_nxt]++; + +--- sys/netinet6/ip6_output.c.orig Thu Feb 5 08:11:17 2004 ++++ sys/netinet6/ip6_output.c Thu Jul 8 14:11:07 2004 +@@ -118,6 +118,9 @@ + + static int ip6_pcbopts(struct ip6_pktopts **, struct mbuf *, struct socket *); + static int ip6_setmoptions(int, struct ip6_moptions **, struct mbuf *); ++#if defined(IPFILTER) || defined(IPFILTER_LKM) ++extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++#endif + static int ip6_getmoptions(int, struct ip6_moptions *, struct mbuf **); + static int ip6_copyexthdr(struct mbuf **, caddr_t, int); + static int ip6_insertfraghdr(struct mbuf *, struct mbuf *, int, +@@ -124,7 +127,7 @@ + struct ip6_frag **); + static int ip6_insert_jumboopt(struct ip6_exthdrs *, u_int32_t); + static int ip6_splithdr(struct mbuf *, struct ip6_exthdrs *); +-static int ip6_getpmtu(struct route_in6 *, struct route_in6 *, ++int ip6_getpmtu(struct route_in6 *, struct route_in6 *, + struct ifnet *, struct in6_addr *, u_long *, int *); + + /* +@@ -797,6 +800,25 @@ + goto done; + ip6 = mtod(m, struct ip6_hdr *); + #endif ++ ++#if defined(IPFILTER) || defined(IPFILTER_LKM) ++ /* ++ * looks like most checking has been done now...do a filter check ++ */ ++ if (fr_checkp != NULL) { ++ struct mbuf *m1 = m; ++ if ((*fr_checkp)((struct ip *)ip6, sizeof(*ip6), ifp, 1, &m1)) { ++ error = EHOSTUNREACH; ++ goto done; ++ } ++ m = m1; ++ if (m1 == 0) { /* in case of 'fastroute' */ ++ error = 0; ++ goto done; ++ } ++ ip6 = mtod(m, struct ip6_hdr *); ++ } ++#endif + + /* + * Send the packet to the outgoing interface. +@@ -1192,7 +1214,7 @@ + return (0); + } + +-static int ++int + ip6_getpmtu(ro_pmtu, ro, ifp, dst, mtup, alwaysfragp) + struct route_in6 *ro_pmtu, *ro; + struct ifnet *ifp; +--- sys/sys/conf.h.orig Sat Feb 21 15:11:07 2004 ++++ sys/sys/conf.h Thu Jul 8 15:11:14 2004 +@@ -406,6 +406,13 @@ + dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \ + 0, (dev_type_poll((*))) enodev, (dev_type_mmap((*))) enodev } + ++/* open, close, read, ioctl */ ++#define cdev_gen_ipf(c, n) { \ ++dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ ++ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ ++ (dev_type_stop((*))) enodev, 0, (dev_type_poll((*))) enodev, \ ++ (dev_type_mmap((*))) enodev } ++ + /* open, close, ioctl */ + #define cdev_pf_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ +@@ -586,6 +593,7 @@ + + cdev_decl(bpf); + ++cdev_decl(ipl); + cdev_decl(pf); + + cdev_decl(tun); diff --git a/OpenBSD-3/README.3_0 b/OpenBSD-3/README.3_0 new file mode 100644 index 0000000000000..5535ec7c8887e --- /dev/null +++ b/OpenBSD-3/README.3_0 @@ -0,0 +1,75 @@ + +Installing IPFilter into OpenBSD 3.0 Kernel +=========================================== +The installation of IPFilter should be as easy as following the steps +below. In cases where "i386" is mentioned, if you are working on a +different platform, substitute that name there and it should work equally +as well. The patches include enabling IPFilter for IPv4 filtering, IPv6 +filtering and bridge filtering. + +The commands given below are intended as guides rather than exact matches +on what needs to be typed. In many cases, paths to files or directories +may bear little resemblence to what is presented below. + +You may encounter difficulties with step 7 if you have made changes to the +rc files which cause "patch" to not be able to work out how to apply the +changes correctly. + +If the below steps are followed with no problems then it should be safe to +perform step 8 and reboot with the new kernel. Of course if you are not +using GENERIC then substitute GENERIC for your kernel name. If your kernel +config file includes the "GENERIC" one then you will not need to add explicit +options for IPFilter. + +1. Extract your source tree into /usr/src, creating /usr/src/sys. + +cd /usr/src +gunzip -c sys.tar.gz | tar xpf - + +2. Unpack IPFilter and apply the patches to the kernel source + +cd ~ +gunzip -c ip_fil4next.tar.gz | tar xpf - +cd /usr/src +patch < ~/ip_fil4.1.14/OpenBSD-3/3.0-sys-diffs + +3. Add IPFilter to the source code tree: + +cd ~/ip_fil4next +BSD/kupgrade + +4. Build a new OpenBSD kernel + +/bin/rm -rf /sys/arch/i386/compile/GENERIC +cd /sys/arch/i386/conf +config GENERIC +cd ../compile/GENERIC +make depend && make +cp bsd /bsd + +5. Build and install IPFilter + +cd ip_fil4next +make openbsd +make install-bsd +OpenBSD-3/makedevs-3.0 + +6. Patch rc scripts in /etc + +cd /etc +patch < ~/ip_fil4.1.14/OpenBSD-3/3.0-rc-diffs + +7. Reboot + + +IPFilter device files +===================== +Patches to include making IPFilter devices can be found in the file +3.0-MAKEDEV-diffs. These diffs are generally only of interested if +you are going to be building a distribution for others and want the +correct MAKEDEV scripts to be built. You may also wish to use this +to patch /dev/MAKEDEV on your machine to be correct. Pre-fab'd MAKEDEV +scripts (or individual patches) for each architecture are not provided. +You will need to have extracted "./etc" from src.tar.gz to use these +patches. + diff --git a/OpenBSD-3/README.3_1 b/OpenBSD-3/README.3_1 new file mode 100644 index 0000000000000..d92f2208ea652 --- /dev/null +++ b/OpenBSD-3/README.3_1 @@ -0,0 +1,86 @@ + +Installing IPFilter into OpenBSD 3.1 Kernel +=========================================== +The installation of IPFilter should be as easy as following the steps +below. In cases where "i386" is mentioned, if you are working on a +different platform, substitute that name there and it should work equally +as well. The patches include enabling IPFilter for IPv4 filtering, IPv6 +filtering and bridge filtering. + +The commands given below are intended as guides rather than exact matches +on what needs to be typed. In many cases, paths to files or directories +may bear little resemblence to what is presented below. + +You may encounter difficulties with step 7 if you have made changes to the +rc files which cause "patch" to not be able to work out how to apply the +changes correctly. + +If the below steps are followed with no problems then it should be safe to +perform step 8 and reboot with the new kernel. Of course if you are not +using GENERIC then substitute GENERIC for your kernel name. If your kernel +config file includes the "GENERIC" one then you will not need to add explicit +options for IPFilter. + +1. Extract your source tree into /usr/src, creating /usr/src/sys. + +cd /usr/src +gunzip -c sys.tar.gz | tar xpf - + +2. Unpack IPFilter and apply the patches to the kernel source + +cd ~ +gunzip -c ip_fil4next.tar.gz | tar xpf - +cd /usr/src +patch < ~/ip_fil4.1.14/OpenBSD-3/3.1-sys-diffs + +3. Add IPFilter to the source code tree: + +cd ~/ip_fil4next +BSD/kupgrade + +If you want to build a new release with IPFilter, stop here and goto +the section below titled "Building a Release". + +4. Build a new OpenBSD kernel + +/bin/rm -rf /sys/arch/i386/compile/GENERIC +cd /sys/arch/i386/conf +config GENERIC +cd ../compile/GENERIC +make depend && make +cp bsd /bsd + +5. Build and install IPFilter + +cd ip_fil4next +make openbsd +make install-bsd +OpenBSD-3/makedevs-3.1 + +6. Patch rc scripts in /etc + +cd /etc +patch < ~/ip_fil4.1.14/OpenBSD-3/3.1-rc-diffs + +7. Reboot + + +IPFilter device files +===================== +Patches to include making IPFilter devices can be found in the file +3.1-MAKEDEV-diffs. These diffs are generally only of interested if +you are going to be building a distribution for others and want the +correct MAKEDEV scripts to be built. You may also wish to use this +to patch /dev/MAKEDEV on your machine to be correct. Pre-fab'd MAKEDEV +scripts (or individual patches) for each architecture are not provided. +You will need to have extracted "./etc" from src.tar.gz to use these +patches. + +Building a Release +================== +cd /usr/src +patch < ~/ip_fil4.1.14/OpenBSD-3/3.1-rc-diffs +patch < ~/ip_fil4.1.14/OpenBSD-3/3.1-MAKEDEV-diffs +cd ~/ip_fil4next +./OpenBSD-3/fixdist-3.0 + diff --git a/OpenBSD-3/README.3_2 b/OpenBSD-3/README.3_2 new file mode 100644 index 0000000000000..c9f587873e629 --- /dev/null +++ b/OpenBSD-3/README.3_2 @@ -0,0 +1,86 @@ + +Installing IPFilter into OpenBSD 3.2 Kernel +=========================================== +The installation of IPFilter should be as easy as following the steps +below. In cases where "i386" is mentioned, if you are working on a +different platform, substitute that name there and it should work equally +as well. The patches include enabling IPFilter for IPv4 filtering, IPv6 +filtering and bridge filtering. + +The commands given below are intended as guides rather than exact matches +on what needs to be typed. In many cases, paths to files or directories +may bear little resemblence to what is presented below. + +You may encounter difficulties with step 7 if you have made changes to the +rc files which cause "patch" to not be able to work out how to apply the +changes correctly. + +If the below steps are followed with no problems then it should be safe to +perform step 8 and reboot with the new kernel. Of course if you are not +using GENERIC then substitute GENERIC for your kernel name. If your kernel +config file includes the "GENERIC" one then you will not need to add explicit +options for IPFilter. + +1. Extract your source tree into /usr/src, creating /usr/src/sys. + +cd /usr/src +gunzip -c sys.tar.gz | tar xpf - + +2. Unpack IPFilter and apply the patches to the kernel source + +cd ~ +gunzip -c ip_fil4next.tar.gz | tar xpf - +cd /usr/src +patch < ~/ip_fil4.1.14/OpenBSD-3/3.2-sys-diffs + +3. Add IPFilter to the source code tree: + +cd ~/ip_fil4next +BSD/kupgrade + +If you want to build a new release with IPFilter, stop here and goto +the section below titled "Building a Release". + +4. Build a new OpenBSD kernel + +/bin/rm -rf /sys/arch/i386/compile/GENERIC +cd /sys/arch/i386/conf +config GENERIC +cd ../compile/GENERIC +make depend && make +cp bsd /bsd + +5. Build and install IPFilter + +cd ip_fil4next +make openbsd +make install-bsd +OpenBSD-3/makedevs-3.2 + +6. Patch rc scripts in /etc + +cd /etc +patch < ~/ip_fil4.1.14/OpenBSD-3/3.2-rc-diffs + +7. Reboot + + +IPFilter device files +===================== +Patches to include making IPFilter devices can be found in the file +3.2-MAKEDEV-diffs. These diffs are generally only of interested if +you are going to be building a distribution for others and want the +correct MAKEDEV scripts to be built. You may also wish to use this +to patch /dev/MAKEDEV on your machine to be correct. Pre-fab'd MAKEDEV +scripts (or individual patches) for each architecture are not provided. +You will need to have extracted "./etc" from src.tar.gz to use these +patches. + +Building a Release +================== +cd /usr/src +patch < ~/ip_fil4.1.14/OpenBSD-3/3.2-rc-diffs +patch < ~/ip_fil4.1.14/OpenBSD-3/3.2-MAKEDEV-diffs +cd ~/ip_fil4next +./OpenBSD-3/fixdist-3.2 + diff --git a/OpenBSD-3/README.3_3 b/OpenBSD-3/README.3_3 new file mode 100644 index 0000000000000..c0b188f1b370c --- /dev/null +++ b/OpenBSD-3/README.3_3 @@ -0,0 +1,86 @@ + +Installing IPFilter into OpenBSD 3.3 Kernel +=========================================== +The installation of IPFilter should be as easy as following the steps +below. In cases where "i386" is mentioned, if you are working on a +different platform, substitute that name there and it should work equally +as well. The patches include enabling IPFilter for IPv4 filtering, IPv6 +filtering and bridge filtering. + +The commands given below are intended as guides rather than exact matches +on what needs to be typed. In many cases, paths to files or directories +may bear little resemblence to what is presented below. + +You may encounter difficulties with step 7 if you have made changes to the +rc files which cause "patch" to not be able to work out how to apply the +changes correctly. + +If the below steps are followed with no problems then it should be safe to +perform step 8 and reboot with the new kernel. Of course if you are not +using GENERIC then substitute GENERIC for your kernel name. If your kernel +config file includes the "GENERIC" one then you will not need to add explicit +options for IPFilter. + +1. Extract your source tree into /usr/src, creating /usr/src/sys. + +cd /usr/src +gunzip -c sys.tar.gz | tar xpf - + +2. Unpack IPFilter and apply the patches to the kernel source + +cd ~ +gunzip -c ip_fil4next.tar.gz | tar xpf - +cd /usr/src +patch < ~/ip_fil4.1.14/OpenBSD-3/3.3-sys-diffs + +3. Add IPFilter to the source code tree: + +cd ~/ip_fil4next +BSD/kupgrade + +If you want to build a new release with IPFilter, stop here and goto +the section below titled "Building a Release". + +4. Build a new OpenBSD kernel + +/bin/rm -rf /sys/arch/i386/compile/GENERIC +cd /sys/arch/i386/conf +config GENERIC +cd ../compile/GENERIC +make depend && make +cp bsd /bsd + +5. Build and install IPFilter + +cd ip_fil4next +make openbsd +make install-bsd +OpenBSD-3/makedevs-3.2 + +6. Patch rc scripts in /etc + +cd /etc +patch < ~/ip_fil4.1.14/OpenBSD-3/3.3-rc-diffs + +7. Reboot + + +IPFilter device files +===================== +Patches to include making IPFilter devices can be found in the file +3.3-MAKEDEV-diffs. These diffs are generally only of interested if +you are going to be building a distribution for others and want the +correct MAKEDEV scripts to be built. You may also wish to use this +to patch /dev/MAKEDEV on your machine to be correct. Pre-fab'd MAKEDEV +scripts (or individual patches) for each architecture are not provided. +You will need to have extracted "./etc" from src.tar.gz to use these +patches. + +Building a Release +================== +cd /usr/src +patch < ~/ip_fil4.1.14/OpenBSD-3/3.3-rc-diffs +patch < ~/ip_fil4.1.14/OpenBSD-3/3.3-MAKEDEV-diffs +cd ~/ip_fil4next +./OpenBSD-3/fixdist-3.2 + diff --git a/OpenBSD-3/README.3_4 b/OpenBSD-3/README.3_4 new file mode 100644 index 0000000000000..c6ca93d9c050a --- /dev/null +++ b/OpenBSD-3/README.3_4 @@ -0,0 +1,86 @@ + +Installing IPFilter into OpenBSD 3.4 Kernel +=========================================== +The installation of IPFilter should be as easy as following the steps +below. In cases where "i386" is mentioned, if you are working on a +different platform, substitute that name there and it should work equally +as well. The patches include enabling IPFilter for IPv4 filtering, IPv6 +filtering and bridge filtering. + +The commands given below are intended as guides rather than exact matches +on what needs to be typed. In many cases, paths to files or directories +may bear little resemblence to what is presented below. + +You may encounter difficulties with step 7 if you have made changes to the +rc files which cause "patch" to not be able to work out how to apply the +changes correctly. + +If the below steps are followed with no problems then it should be safe to +perform step 8 and reboot with the new kernel. Of course if you are not +using GENERIC then substitute GENERIC for your kernel name. If your kernel +config file includes the "GENERIC" one then you will not need to add explicit +options for IPFilter. + +1. Extract your source tree into /usr/src, creating /usr/src/sys. + +cd /usr/src +gunzip -c sys.tar.gz | tar xpf - + +2. Unpack IPFilter and apply the patches to the kernel source + +cd ~ +gunzip -c ip_fil4next.tar.gz | tar xpf - +cd /usr/src +patch < ~/ip_fil4.1.14/OpenBSD-3/3.4-sys-diffs + +3. Add IPFilter to the source code tree: + +cd ~/ip_fil4next +BSD/kupgrade + +If you want to build a new release with IPFilter, stop here and goto +the section below titled "Building a Release". + +4. Build a new OpenBSD kernel + +/bin/rm -rf /sys/arch/i386/compile/GENERIC +cd /sys/arch/i386/conf +config GENERIC +cd ../compile/GENERIC +make depend && make +cp bsd /bsd + +5. Build and install IPFilter + +cd ip_fil4next +make openbsd +make install-bsd +OpenBSD-3/makedevs-3.4 + +6. Patch rc scripts in /etc + +cd /etc +patch < ~/ip_fil4.1.14/OpenBSD-3/3.4-rc-diffs + +7. Reboot + + +IPFilter device files +===================== +Patches to include making IPFilter devices can be found in the file +3.4-MAKEDEV-diffs. These diffs are generally only of interested if +you are going to be building a distribution for others and want the +correct MAKEDEV scripts to be built. You may also wish to use this +to patch /dev/MAKEDEV on your machine to be correct. Pre-fab'd MAKEDEV +scripts (or individual patches) for each architecture are not provided. +You will need to have extracted "./etc" from src.tar.gz to use these +patches. + +Building a Release +================== +cd /usr/src +patch < ~/ip_fil4.1.14/OpenBSD-3/3.4-rc-diffs +patch < ~/ip_fil4.1.14/OpenBSD-3/3.4-MAKEDEV-diffs +cd ~/ip_fil4next +./OpenBSD-3/fixdist-3.4 + diff --git a/OpenBSD-3/README.3_5 b/OpenBSD-3/README.3_5 new file mode 100644 index 0000000000000..62a97cc4fddaf --- /dev/null +++ b/OpenBSD-3/README.3_5 @@ -0,0 +1,86 @@ + +Installing IPFilter into OpenBSD 3.5 Kernel +=========================================== +The installation of IPFilter should be as easy as following the steps +below. In cases where "i386" is mentioned, if you are working on a +different platform, substitute that name there and it should work equally +as well. The patches include enabling IPFilter for IPv4 filtering, IPv6 +filtering and bridge filtering. + +The commands given below are intended as guides rather than exact matches +on what needs to be typed. In many cases, paths to files or directories +may bear little resemblence to what is presented below. + +You may encounter difficulties with step 7 if you have made changes to the +rc files which cause "patch" to not be able to work out how to apply the +changes correctly. + +If the below steps are followed with no problems then it should be safe to +perform step 8 and reboot with the new kernel. Of course if you are not +using GENERIC then substitute GENERIC for your kernel name. If your kernel +config file includes the "GENERIC" one then you will not need to add explicit +options for IPFilter. + +1. Extract your source tree into /usr/src, creating /usr/src/sys. + +cd /usr/src +gunzip -c sys.tar.gz | tar xpf - + +2. Unpack IPFilter and apply the patches to the kernel source + +cd ~ +gunzip -c ip_fil4next.tar.gz | tar xpf - +cd /usr/src +patch < ~/ip_fil4.1.14/OpenBSD-3/3.5-sys-diffs + +3. Add IPFilter to the source code tree: + +cd ~/ip_fil4next +BSD/kupgrade + +If you want to build a new release with IPFilter, stop here and goto +the section below titled "Building a Release". + +4. Build a new OpenBSD kernel + +/bin/rm -rf /sys/arch/i386/compile/GENERIC +cd /sys/arch/i386/conf +config GENERIC +cd ../compile/GENERIC +make depend && make +cp bsd /bsd + +5. Build and install IPFilter + +cd ip_fil4next +make openbsd +make install-bsd +OpenBSD-3/makedevs-3.5 + +6. Patch rc scripts in /etc + +cd /etc +patch < ~/ip_fil4.1.14/OpenBSD-3/3.5-rc-diffs + +7. Reboot + + +IPFilter device files +===================== +Patches to include making IPFilter devices can be found in the file +3.5-MAKEDEV-diffs. These diffs are generally only of interested if +you are going to be building a distribution for others and want the +correct MAKEDEV scripts to be built. You may also wish to use this +to patch /dev/MAKEDEV on your machine to be correct. Pre-fab'd MAKEDEV +scripts (or individual patches) for each architecture are not provided. +You will need to have extracted "./etc" from src.tar.gz to use these +patches. + +Building a Release +================== +cd /usr/src +patch < ~/ip_fil4.1.14/OpenBSD-3/3.5-rc-diffs +patch < ~/ip_fil4.1.14/OpenBSD-3/3.5-MAKEDEV-diffs +cd ~/ip_fil4next +./OpenBSD-3/fixdist-3.5 + diff --git a/OpenBSD-3/fixdist-3.0 b/OpenBSD-3/fixdist-3.0 new file mode 100755 index 0000000000000..339e7c3c62b23 --- /dev/null +++ b/OpenBSD-3/fixdist-3.0 @@ -0,0 +1,495 @@ +#!/bin/sh +# +# Install IPFilter into the source tree of OpenBSD 3.0 +# + +if [ $# -eq 1 ] ; then + if [ "$1" = "-d" ] ; then + debug=echo + fi +fi + +copyfiles() { + while [ $# -gt 0 ] ; do + if [ X"$1" = X"\\" ] ; then + : + elif [ -f $IPFDIR/$1 ] ; then + $debug cp -p $IPFDIR/$1 . + elif [ -f $IPFDIR/man/$1 ] ; then + $debug cp -p $IPFDIR/man/$1 . + elif [ -f $IPFDIR/iplang/$1 ] ; then + $debug cp -p $IPFDIR/iplang/$1 . + elif [ -f $IPFDIR/ipsend/$1 ] ; then + $debug cp -p $IPFDIR/ipsend/$1 . + else + echo "Could not find $IPFDIR/$1" + fi + shift + done +} + +prep() { + $debug mkdir $1 + $debug cd $1 +} + +IPFDIR=`pwd` +SRC=/usr/src + +# +# 3 Programs into /sbin: ipf, ipfstat, ipnat +# +cd $SRC/sbin +/bin/rm -rf ipf ipfstat ipnat + +prep ipf +MFILES="ipf.8 ipf.4 ipf.5 ipl.4" +SFILES="ipf.c parse.c opt.c facpri.c common.c" +IFILES="ipf.h facpri.h" +if [ X$debug = X ] ; then + OFILE=Makefile +else + OFILE=/dev/tty +fi +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.10 2001/01/17 05:00:57 fgsch Exp $ + +PROG= ipf +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sys/netinet + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + +# +# Setup ipfstat(8) +# +prep ../ipfstat +MFILES=ipfstat.8 +SFILES="fils.c parse.c opt.c kmem.c facpri.c common.c printstate.c" +IFILES=kmem.h +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.8 2001/02/13 01:12:33 fgsch Exp $ + +PROG= ipfstat +MAN= ${MFILES} +SRCS= ${SFILES} +.PATH: \${.CURDIR}/../../sbin/ipf +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sbin/ipf -DSTATETOP \\ + -I\${.CURDIR}/../../sys/netinet +DPADD= \${LIBCURSES} +LDADD= -lcurses -lkvm + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + +# +# Setup ipnat(8) +# +prep ../ipnat +MFILES="ipnat.8 ipnat.4 ipnat.5" +SFILES="ipnat.c kmem.c natparse.c common.c printnat.c" +IFILES= +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.10 2001/01/17 05:01:01 fgsch Exp $ + +PROG= ipnat +MAN= ${MFILES} +SRCS= ${SFILES} +.PATH: \${.CURDIR}/../ipfstat \${.CURDIR}/../ipf +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sbin/ipfstat -I\${.CURDIR}/../ipf \\ + -I\${.CURDIR}/../../sys/netinet +LDADD= -lkvm + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES +echo "`pwd` done" + +# +# Now fix up the top level Makefile +# +cd $SRC/sbin +grep -q ipf Makefile +if [ $? -ne 0 ] ; then + cat <<__EOF__ | patch +*** Makefile.orig Tue Jan 1 15:01:51 2002 +--- Makefile Mon Jan 7 20:31:56 2002 +*************** +*** 34,37 **** +--- 34,40 ---- + # Man pages (and manpages to do) + SUBDIR+= fdisk pdisk ancontrol wicontrol wsconsctl + ++ # IPFilter ++ SUBDIR+= ipf ipfstat ipnat ++ + .include <bsd.subdir.mk> +__EOF__ +fi + + +# +# 3 Programs into /usr/sbin: ipfs, ipfstat, ipmon +# Also, include ipsend suite of tools. +# +cd $SRC/usr.sbin +/bin/rm -rf ipfs ipftest ipmon ipsend + +# +# Create directory for ipftest +# +prep ipftest +MFILES=ipftest.1 +SFILES="ipt.c fil.c ipft_hx.c ipft_sn.c ipft_ef.c ipft_td.c ipft_pc.c \\ + ipft_tx.c misc.c parse.c opt.c ip_frag.c ip_nat.c ip_state.c \\ + ip_auth.c ip_fil.c ip_proxy.c facpri.c natparse.c common.c \\ + printnat.c printstate.c ip_log.c" +IFILES="ipt.h pcap.h snoop.h kmem.h" +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.9 2001/01/17 06:01:21 fgsch Exp $ + +PROG= ipftest +MAN= ${MFILES} +SRCS= ${SFILES} + +.PATH: \${.CURDIR}/../../sbin/ipf \${.CURDIR}/../../sbin/ipfstat \\ + \${.CURDIR}/../../sys/netinet \${.CURDIR}/../../sbin/ipnat + +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sbin/ipf -DIPFILTER_LOG \\ + -I\${.CURDIR}/../../sys/netinet -I\${.CURDIR}/../../sys -I\${.CURDIR} + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# Create directory for ipfs +# +prep ../ipfs +MFILES=ipfs.8 +SFILES=ipfs.c +IFILES= +cat > ${OFILE} << __EOF__ +# \$OpenBSD: Makefile,v 1.1 2001/01/17 06:31:06 fgsch Exp \$ + +PROG= ipfs +MAN= ${MFILES} +SRCS= ${SFILES} + +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sbin/ipf \\ + -I\${.CURDIR}/../../sys/netinet + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# +# +prep ../ipmon +MFILES=ipmon.8 +SFILES=ipmon.c +IFILES= +cat > ${OFILE} << __EOF__ +# \$OpenBSD: Makefile,v 1.4 1998/09/15 10:01:38 pattonme Exp \$ + +PROG= ipmon +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sys/netinet + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# Create top level directories for ipsend +# +prep ../ipsend +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.4 1997/09/21 11:43:47 deraadt Exp $ + +SUBDIR= ipsend ipresend iptest + +.include <bsd.subdir.mk> +__EOF__ +echo "`pwd` done" + +prep iplang +copyfiles iplang.h + +# +# 1st ipsend program - ipsend itself +# +prep ../ipsend +MFILES="ipsend.1 ipsend.5" +SFILES="ipsend.c ip.c ipsopt.c sbpf.c sock.c 44arp.c iplang_y.y iplang_l.l" +IFILES="ipsend.h iplang.h" +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.3 1998/01/26 19:46:23 weingart Exp $ + +PROG= ipsend +BINDIR= /usr/sbin +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+= -DDOSOCKET -I\${.CURDIR}/../common -I\${.CURDIR}/../../ipftest \\ + -I\${.CURDIR}/../../../sbin/ipf -I\${.CURDIR}/../../../sys/netinet \\ + -I\${.CURDIR}/.. -I\${.OBJDIR} + +LDADD= -lfl +CLEANFILES+=y.tab.h + +.PATH: \${.CURDIR}/../common + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# 2nd ipsend program - ipresend +# +prep ../ipresend +MFILES=ipresend.1 +SFILES="ipresend.c resend.c \\ + ipft_ef.c ipft_hx.c ipft_pc.c ipft_sn.c ipft_td.c ipft_tx.c opt.c \\ + sock.c 44arp.c sbpf.c ip.c" +IFILES="ipsend.h" +cat > ${OFILE} << __EOF__ +# \$OpenBSD: Makefile,v 1.4 1999/02/21 23:11:05 tholo Exp \$ + +PROG= ipresend +BINDIR= /usr/sbin +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+=-DDOSOCKET -I\${.CURDIR}/../common -I\${.CURDIR}/../../ipftest \\ + -I\${.CURDIR}/../../../sbin/ipf \\ + -I\${.CURDIR}/../../../sys/netinet -I\${.CURDIR}/.. +.PATH: \${.CURDIR}/../common \${.CURDIR}/../../ipftest \\ + \${.CURDIR}/../../../sbin/ipf + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# 3rd ipsend program - iptest +# +prep ../iptest +MFILES=iptest.1 +SFILES="iptest.c iptests.c ip.c sbpf.c sock.c 44arp.c" +IFILES="ipsend.h" +cat > ${OFILE} << __EOF__ +# \$OpenBSD: Makefile,v 1.2 1998/01/26 04:17:08 dgregor Exp \$ + +PROG= iptest +BINDIR= /usr/sbin +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+=-DDOSOCKET -I\${.CURDIR}/../common -I\${.CURDIR}/../../ipftest \\ + -I\${.CURDIR}/../../../sys/netinet \\ + -I\${.CURDIR}/../../../sbin/ipf -I\${.CURDIR}/.. +.PATH: \${.CURDIR}/../common + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + +cd $SRC/usr.sbin +grep -q ipmon Makefile +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** Makefile.orig Tue Jan 1 15:06:30 2002 +--- Makefile Mon Jan 7 20:34:05 2002 +*************** +*** 36,39 **** +--- 36,42 ---- + SUBDIR+=ypbind yppoll ypset ypserv + .endif + ++ # IPFilter ++ SUBDIR+=ipftest ipfs ipmon ipsend ++ + .include <bsd.subdir.mk> +__EOF__ +fi + +echo "Patching base install set" +cd $SRC +cd distrib/sets/lists/base +grep -q ipfstat mi +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** mi.orig Sat Oct 6 03:30:51 2001 +--- mi Tue Jan 8 05:45:39 2002 +*************** +*** 89,94 **** +--- 89,97 ---- + ./sbin/halt + ./sbin/ifconfig + ./sbin/init ++ ./sbin/ipf ++ ./sbin/ipfstat ++ ./sbin/ipnat + ./sbin/ipsecadm + ./sbin/isakmpd + ./sbin/kbd +*************** +*** 1276,1281 **** +--- 1279,1290 ---- + ./usr/sbin/ifmcstat + ./usr/sbin/inetd + ./usr/sbin/iostat ++ ./usr/sbin/ipfs ++ ./usr/sbin/ipftest ++ ./usr/sbin/ipmon ++ ./usr/sbin/ipresend ++ ./usr/sbin/ipsend ++ ./usr/sbin/iptest + ./usr/sbin/kadmin + ./usr/sbin/kdb_destroy + ./usr/sbin/kdb_edit +__EOF__ +fi + +echo "Patching etc Makefile" +cd $SRC +cd etc +grep -q ipf.conf Makefile +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** Makefile.orig Tue May 28 15:08:50 2002 +--- Makefile Tue May 28 15:09:19 2002 +*************** +*** 14,20 **** + BINGRP= wheel + BIN1= bootptab changelist ccd.conf csh.cshrc csh.login csh.logout \\ + daily dhcpd.conf dhcpd.interfaces dm.conf exports ftpusers \\ +! ftpchroot gettytab group hosts hosts.lpd inetd.conf \\ + ksh.kshrc locate.rc man.conf monthly motd mrouted.conf \\ + myname netstart networks newsyslog.conf pf.conf nat.conf \\ + phones printcap protocols rbootd.conf rc rc.conf rc.local \\ +--- 14,20 ---- + BINGRP= wheel + BIN1= bootptab changelist ccd.conf csh.cshrc csh.login csh.logout \\ + daily dhcpd.conf dhcpd.interfaces dm.conf exports ftpusers \\ +! ftpchroot gettytab group hosts hosts.lpd inetd.conf ipf.conf \\ + ksh.kshrc locate.rc man.conf monthly motd mrouted.conf \\ + myname netstart networks newsyslog.conf pf.conf nat.conf \\ + phones printcap protocols rbootd.conf rc rc.conf rc.local \\ +__EOF__ +fi + +echo "Patching etc mi install set" +cd $SRC +cd distrib/sets/lists/etc +grep -q ipf.conf mi +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** mi.orig Sat Oct 6 03:30:51 2001 +--- mi Tue Jan 8 05:45:39 2002 +*************** +*** 30,35 **** +--- 30,36 ---- + ./etc/hosts.equiv + ./etc/hosts.lpd + ./etc/inetd.conf ++ ./etc/ipf.conf + ./etc/kerberosIV/README + ./etc/kerberosIV/krb.conf + ./etc/kerberosIV/krb.equiv +__EOF__ +fi + +echo "Patching man install set" +cd $SRC +cd distrib/sets/lists/man +grep -q ipfstat mi +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** mi.orig Wed Oct 10 03:28:42 2001 +--- mi Tue Jan 8 19:37:54 2002 +*************** +*** 319,324 **** +--- 319,328 ---- + ./usr/share/man/cat1/intro.0 + ./usr/share/man/cat1/ipcrm.0 + ./usr/share/man/cat1/ipcs.0 ++ ./usr/share/man/cat1/ipftest.0 ++ ./usr/share/man/cat1/ipresend.0 ++ ./usr/share/man/cat1/ipsend.0 ++ ./usr/share/man/cat1/iptest.0 + ./usr/share/man/cat1/jobs.0 + ./usr/share/man/cat1/join.0 + ./usr/share/man/cat1/jot.0 +*************** +*** 1054,1059 **** +--- 1058,1066 ---- + ./usr/share/man/cat4/ip.0 + ./usr/share/man/cat4/ip6.0 + ./usr/share/man/cat4/ipcomp.0 ++ ./usr/share/man/cat4/ipf.0 ++ ./usr/share/man/cat4/ipl.0 ++ ./usr/share/man/cat4/ipnat.0 + ./usr/share/man/cat4/ipsec.0 + ./usr/share/man/cat4/isa.0 + ./usr/share/man/cat4/isapnp.0 +*************** +*** 1414,1419 **** +--- 1421,1429 ---- + ./usr/share/man/cat5/info.0 + ./usr/share/man/cat5/inode.0 + ./usr/share/man/cat5/intro.0 ++ ./usr/share/man/cat5/ipf.0 ++ ./usr/share/man/cat5/ipnat.0 ++ ./usr/share/man/cat5/ipsend.0 + ./usr/share/man/cat5/isakmpd.conf.0 + ./usr/share/man/cat5/isakmpd.policy.0 + ./usr/share/man/cat5/keynote.0 +*************** +*** 1657,1662 **** +--- 1667,1677 ---- + ./usr/share/man/cat8/intro.0 + ./usr/share/man/cat8/iopctl.0 + ./usr/share/man/cat8/iostat.0 ++ ./usr/share/man/cat8/ipf.0 ++ ./usr/share/man/cat8/ipfs.0 ++ ./usr/share/man/cat8/ipfstat.0 ++ ./usr/share/man/cat8/ipmon.0 ++ ./usr/share/man/cat8/ipnat.0 + ./usr/share/man/cat8/ipsecadm.0 + ./usr/share/man/cat8/isakmpd.0 + ./usr/share/man/cat8/kadmin.0 +__EOF__ +fi + +echo Creating etc/ipf.conf +cd $SRC +cd etc +if [ ! -f ipf.conf ] ; then + cat > ipf.conf << __EOF__ +# +# See ipf(5) for syntax and examples. +# +# Pass all packets in and out (these are the implicit first two rules.) +# pass in all +# pass out all +__EOF__ +fi +exit 0 diff --git a/OpenBSD-3/fixdist-3.2 b/OpenBSD-3/fixdist-3.2 new file mode 100755 index 0000000000000..29d3bcd93ac2d --- /dev/null +++ b/OpenBSD-3/fixdist-3.2 @@ -0,0 +1,495 @@ +#!/bin/sh +# +# Install IPFilter into the source tree of OpenBSD 3.2 +# + +if [ $# -eq 1 ] ; then + if [ "$1" = "-d" ] ; then + debug=echo + fi +fi + +copyfiles() { + while [ $# -gt 0 ] ; do + if [ X"$1" = X"\\" ] ; then + : + elif [ -f $IPFDIR/$1 ] ; then + $debug cp -p $IPFDIR/$1 . + elif [ -f $IPFDIR/man/$1 ] ; then + $debug cp -p $IPFDIR/man/$1 . + elif [ -f $IPFDIR/iplang/$1 ] ; then + $debug cp -p $IPFDIR/iplang/$1 . + elif [ -f $IPFDIR/ipsend/$1 ] ; then + $debug cp -p $IPFDIR/ipsend/$1 . + else + echo "Could not find $IPFDIR/$1" + fi + shift + done +} + +prep() { + $debug mkdir $1 + $debug cd $1 +} + +IPFDIR=`pwd` +SRC=/usr/src + +# +# 3 Programs into /sbin: ipf, ipfstat, ipnat +# +cd $SRC/sbin +/bin/rm -rf ipf ipfstat ipnat + +prep ipf +MFILES="ipf.8 ipf.4 ipf.5 ipl.4" +SFILES="ipf.c parse.c opt.c facpri.c common.c" +IFILES="ipf.h facpri.h" +if [ X$debug = X ] ; then + OFILE=Makefile +else + OFILE=/dev/tty +fi +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.10 2001/01/17 05:00:57 fgsch Exp $ + +PROG= ipf +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sys/netinet + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + +# +# Setup ipfstat(8) +# +prep ../ipfstat +MFILES=ipfstat.8 +SFILES="fils.c parse.c opt.c kmem.c facpri.c common.c printstate.c" +IFILES=kmem.h +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.8 2001/02/13 01:12:33 fgsch Exp $ + +PROG= ipfstat +MAN= ${MFILES} +SRCS= ${SFILES} +.PATH: \${.CURDIR}/../../sbin/ipf +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sbin/ipf -DSTATETOP \\ + -I\${.CURDIR}/../../sys/netinet +DPADD= \${LIBCURSES} +LDADD= -lcurses -lkvm + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + +# +# Setup ipnat(8) +# +prep ../ipnat +MFILES="ipnat.8 ipnat.4 ipnat.5" +SFILES="ipnat.c kmem.c natparse.c common.c printnat.c" +IFILES= +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.10 2001/01/17 05:01:01 fgsch Exp $ + +PROG= ipnat +MAN= ${MFILES} +SRCS= ${SFILES} +.PATH: \${.CURDIR}/../ipfstat \${.CURDIR}/../ipf +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sbin/ipfstat -I\${.CURDIR}/../ipf \\ + -I\${.CURDIR}/../../sys/netinet +LDADD= -lkvm + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES +echo "`pwd` done" + +# +# Now fix up the top level Makefile +# +cd $SRC/sbin +grep -q ipf Makefile +if [ $? -ne 0 ] ; then + cat <<__EOF__ | patch +*** Makefile.orig Sat Sep 7 07:15:55 2002 +--- Makefile Wed Nov 13 12:33:36 2002 +*************** +*** 33,36 **** +--- 33,39 ---- + # Man pages (and manpages to do) + SUBDIR+= fdisk pdisk ancontrol wicontrol wsconsctl + ++ # IPFilter ++ SUBDIR+= ipf ipfstat ipnat ++ + .include <bsd.subdir.mk> +__EOF__ +fi + + +# +# 3 Programs into /usr/sbin: ipfs, ipfstat, ipmon +# Also, include ipsend suite of tools. +# +cd $SRC/usr.sbin +/bin/rm -rf ipfs ipftest ipmon ipsend + +# +# Create directory for ipftest +# +prep ipftest +MFILES=ipftest.1 +SFILES="ipt.c fil.c ipft_hx.c ipft_sn.c ipft_ef.c ipft_td.c ipft_pc.c \\ + ipft_tx.c misc.c parse.c opt.c ip_frag.c ip_nat.c ip_state.c \\ + ip_auth.c ip_fil.c ip_proxy.c facpri.c natparse.c common.c \\ + printnat.c printstate.c ip_log.c" +IFILES="ipt.h pcap.h snoop.h kmem.h bpf.h" +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.9 2001/01/17 06:01:21 fgsch Exp $ + +PROG= ipftest +MAN= ${MFILES} +SRCS= ${SFILES} + +.PATH: \${.CURDIR}/../../sbin/ipf \${.CURDIR}/../../sbin/ipfstat \\ + \${.CURDIR}/../../sys/netinet \${.CURDIR}/../../sbin/ipnat + +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sbin/ipf -DIPFILTER_LOG \\ + -I\${.CURDIR}/../../sys/netinet -I\${.CURDIR}/../../sys -I\${.CURDIR} + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# Create directory for ipfs +# +prep ../ipfs +MFILES=ipfs.8 +SFILES=ipfs.c +IFILES= +cat > ${OFILE} << __EOF__ +# \$OpenBSD: Makefile,v 1.1 2001/01/17 06:31:06 fgsch Exp \$ + +PROG= ipfs +MAN= ${MFILES} +SRCS= ${SFILES} + +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sbin/ipf \\ + -I\${.CURDIR}/../../sys/netinet + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# +# +prep ../ipmon +MFILES=ipmon.8 +SFILES=ipmon.c +IFILES= +cat > ${OFILE} << __EOF__ +# \$OpenBSD: Makefile,v 1.4 1998/09/15 10:01:38 pattonme Exp \$ + +PROG= ipmon +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sys/netinet + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# Create top level directories for ipsend +# +prep ../ipsend +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.4 1997/09/21 11:43:47 deraadt Exp $ + +SUBDIR= ipsend ipresend iptest + +.include <bsd.subdir.mk> +__EOF__ +echo "`pwd` done" + +prep iplang +copyfiles iplang.h + +# +# 1st ipsend program - ipsend itself +# +prep ../ipsend +MFILES="ipsend.1 ipsend.5" +SFILES="ipsend.c ip.c ipsopt.c sbpf.c sock.c 44arp.c iplang_y.y iplang_l.l" +IFILES="ipsend.h iplang.h" +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.3 1998/01/26 19:46:23 weingart Exp $ + +PROG= ipsend +BINDIR= /usr/sbin +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+= -DDOSOCKET -I\${.CURDIR}/../common -I\${.CURDIR}/../../ipftest \\ + -I\${.CURDIR}/../../../sbin/ipf -I\${.CURDIR}/../../../sys/netinet \\ + -I\${.CURDIR}/.. -I\${.OBJDIR} + +LDADD= -lfl +CLEANFILES+=y.tab.h + +.PATH: \${.CURDIR}/../common + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# 2nd ipsend program - ipresend +# +prep ../ipresend +MFILES=ipresend.1 +SFILES="ipresend.c resend.c \\ + ipft_ef.c ipft_hx.c ipft_pc.c ipft_sn.c ipft_td.c ipft_tx.c opt.c \\ + sock.c 44arp.c sbpf.c ip.c" +IFILES="ipsend.h bpf.h" +cat > ${OFILE} << __EOF__ +# \$OpenBSD: Makefile,v 1.4 1999/02/21 23:11:05 tholo Exp \$ + +PROG= ipresend +BINDIR= /usr/sbin +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+=-DDOSOCKET -I\${.CURDIR}/../common -I\${.CURDIR}/../../ipftest \\ + -I\${.CURDIR}/../../../sbin/ipf \\ + -I\${.CURDIR}/../../../sys/netinet -I\${.CURDIR}/.. +.PATH: \${.CURDIR}/../common \${.CURDIR}/../../ipftest \\ + \${.CURDIR}/../../../sbin/ipf + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# 3rd ipsend program - iptest +# +prep ../iptest +MFILES=iptest.1 +SFILES="iptest.c iptests.c ip.c sbpf.c sock.c 44arp.c" +IFILES="ipsend.h" +cat > ${OFILE} << __EOF__ +# \$OpenBSD: Makefile,v 1.2 1998/01/26 04:17:08 dgregor Exp \$ + +PROG= iptest +BINDIR= /usr/sbin +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+=-DDOSOCKET -I\${.CURDIR}/../common -I\${.CURDIR}/../../ipftest \\ + -I\${.CURDIR}/../../../sys/netinet \\ + -I\${.CURDIR}/../../../sbin/ipf -I\${.CURDIR}/.. +.PATH: \${.CURDIR}/../common + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + +cd $SRC/usr.sbin +grep -q ipmon Makefile +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** Makefile.orig Fri Jun 21 16:22:20 2002 +--- Makefile Wed Nov 13 12:33:43 2002 +*************** +*** 40,43 **** +--- 40,46 ---- + SUBDIR+=ypbind yppoll ypset ypserv + .endif + ++ # IPFilter ++ SUBDIR+=ipftest ipfs ipmon ipsend ++ + .include <bsd.subdir.mk> +__EOF__ +fi + +echo "Patching base install set" +cd $SRC +cd distrib/sets/lists/base +grep -q ipfstat mi +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** mi.orig Mon Sep 30 04:28:45 2002 +--- mi Wed Nov 13 12:33:44 2002 +*************** +*** 90,95 **** +--- 90,98 ---- + ./sbin/halt + ./sbin/ifconfig + ./sbin/init ++ ./sbin/ipf ++ ./sbin/ipfstat ++ ./sbin/ipnat + ./sbin/ipsecadm + ./sbin/isakmpd + ./sbin/lmccontrol +*************** +*** 1273,1278 **** +--- 1276,1287 ---- + ./usr/sbin/httpd + ./usr/sbin/inetd + ./usr/sbin/iostat ++ ./usr/sbin/ipfs ++ ./usr/sbin/ipftest ++ ./usr/sbin/ipmon ++ ./usr/sbin/ipresend ++ ./usr/sbin/ipsend ++ ./usr/sbin/iptest + ./usr/sbin/kadmin + ./usr/sbin/kdb_destroy + ./usr/sbin/kdb_edit +__EOF__ +fi + +echo "Patching etc Makefile" +cd $SRC +cd etc +grep -q ipf.conf Makefile +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** Makefile.orig Sat Sep 7 07:30:22 2002 +--- Makefile Wed Nov 13 12:38:44 2002 +*************** +*** 14,20 **** + BINGRP= wheel + BIN1= bootptab changelist ccd.conf csh.cshrc csh.login csh.logout \\ + daily dhcpd.conf dhcpd.interfaces exports ftpusers \\ +! ftpchroot gettytab group hosts hosts.lpd inetd.conf \\ + ksh.kshrc locate.rc man.conf monthly motd mrouted.conf \\ + myname netstart networks newsyslog.conf pf.conf \\ + phones printcap protocols rbootd.conf rc rc.conf rc.local \\ +--- 14,20 ---- + BINGRP= wheel + BIN1= bootptab changelist ccd.conf csh.cshrc csh.login csh.logout \\ + daily dhcpd.conf dhcpd.interfaces exports ftpusers \\ +! ftpchroot gettytab group hosts hosts.lpd inetd.conf ipf.conf \\ + ksh.kshrc locate.rc man.conf monthly motd mrouted.conf \\ + myname netstart networks newsyslog.conf pf.conf \\ + phones printcap protocols rbootd.conf rc rc.conf rc.local \\ +__EOF__ +fi + +echo "Patching etc mi install set" +cd $SRC +cd distrib/sets/lists/etc +grep -q ipf.conf mi +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** mi.orig Sat Sep 28 20:23:13 2002 +--- mi Wed Nov 13 12:33:44 2002 +*************** +*** 29,34 **** +--- 29,35 ---- + ./etc/hosts.equiv + ./etc/hosts.lpd + ./etc/inetd.conf ++ ./etc/ipf.conf + ./etc/kerberosIV/README + ./etc/kerberosIV/krb.conf + ./etc/kerberosIV/krb.equiv +__EOF__ +fi + +echo "Patching man install set" +cd $SRC +cd distrib/sets/lists/man +grep -q ipfstat mi +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** mi.orig Thu Oct 3 09:49:02 2002 +--- mi Wed Nov 13 12:33:45 2002 +*************** +*** 322,327 **** +--- 322,331 ---- + ./usr/share/man/cat1/intro.0 + ./usr/share/man/cat1/ipcrm.0 + ./usr/share/man/cat1/ipcs.0 ++ ./usr/share/man/cat1/ipftest.0 ++ ./usr/share/man/cat1/ipresend.0 ++ ./usr/share/man/cat1/ipsend.0 ++ ./usr/share/man/cat1/iptest.0 + ./usr/share/man/cat1/jobs.0 + ./usr/share/man/cat1/join.0 + ./usr/share/man/cat1/jot.0 +*************** +*** 1063,1068 **** +--- 1067,1075 ---- + ./usr/share/man/cat4/ip.0 + ./usr/share/man/cat4/ip6.0 + ./usr/share/man/cat4/ipcomp.0 ++ ./usr/share/man/cat4/ipf.0 ++ ./usr/share/man/cat4/ipl.0 ++ ./usr/share/man/cat4/ipnat.0 + ./usr/share/man/cat4/ipsec.0 + ./usr/share/man/cat4/isa.0 + ./usr/share/man/cat4/isapnp.0 +*************** +*** 1434,1439 **** +--- 1441,1449 ---- + ./usr/share/man/cat5/info.0 + ./usr/share/man/cat5/inode.0 + ./usr/share/man/cat5/intro.0 ++ ./usr/share/man/cat5/ipf.0 ++ ./usr/share/man/cat5/ipnat.0 ++ ./usr/share/man/cat5/ipsend.0 + ./usr/share/man/cat5/isakmpd.conf.0 + ./usr/share/man/cat5/isakmpd.policy.0 + ./usr/share/man/cat5/keynote.0 +*************** +*** 1681,1686 **** +--- 1691,1701 ---- + ./usr/share/man/cat8/intro.0 + ./usr/share/man/cat8/iopctl.0 + ./usr/share/man/cat8/iostat.0 ++ ./usr/share/man/cat8/ipf.0 ++ ./usr/share/man/cat8/ipfs.0 ++ ./usr/share/man/cat8/ipfstat.0 ++ ./usr/share/man/cat8/ipmon.0 ++ ./usr/share/man/cat8/ipnat.0 + ./usr/share/man/cat8/ipsecadm.0 + ./usr/share/man/cat8/isakmpd.0 + ./usr/share/man/cat8/kadmin.0 +__EOF__ +fi + +echo Creating etc/ipf.conf +cd $SRC +cd etc +if [ ! -f ipf.conf ] ; then + cat > ipf.conf << __EOF__ +# +# See ipf(5) for syntax and examples. +# +# Pass all packets in and out (these are the implicit first two rules.) +# pass in all +# pass out all +__EOF__ +fi +exit 0 diff --git a/OpenBSD-3/fixdist-3.3 b/OpenBSD-3/fixdist-3.3 new file mode 100755 index 0000000000000..b6bf29672e58f --- /dev/null +++ b/OpenBSD-3/fixdist-3.3 @@ -0,0 +1,495 @@ +#!/bin/sh +# +# Install IPFilter into the source tree of OpenBSD 3.3 +# + +if [ $# -eq 1 ] ; then + if [ "$1" = "-d" ] ; then + debug=echo + fi +fi + +copyfiles() { + while [ $# -gt 0 ] ; do + if [ X"$1" = X"\\" ] ; then + : + elif [ -f $IPFDIR/$1 ] ; then + $debug cp -p $IPFDIR/$1 . + elif [ -f $IPFDIR/man/$1 ] ; then + $debug cp -p $IPFDIR/man/$1 . + elif [ -f $IPFDIR/iplang/$1 ] ; then + $debug cp -p $IPFDIR/iplang/$1 . + elif [ -f $IPFDIR/ipsend/$1 ] ; then + $debug cp -p $IPFDIR/ipsend/$1 . + else + echo "Could not find $IPFDIR/$1" + fi + shift + done +} + +prep() { + $debug mkdir $1 + $debug cd $1 +} + +IPFDIR=`pwd` +SRC=/usr/src + +# +# 3 Programs into /sbin: ipf, ipfstat, ipnat +# +cd $SRC/sbin +/bin/rm -rf ipf ipfstat ipnat + +prep ipf +MFILES="ipf.8 ipf.4 ipf.5 ipl.4" +SFILES="ipf.c parse.c opt.c facpri.c common.c" +IFILES="ipf.h facpri.h" +if [ X$debug = X ] ; then + OFILE=Makefile +else + OFILE=/dev/tty +fi +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.10 2001/01/17 05:00:57 fgsch Exp $ + +PROG= ipf +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sys/netinet + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + +# +# Setup ipfstat(8) +# +prep ../ipfstat +MFILES=ipfstat.8 +SFILES="fils.c parse.c opt.c kmem.c facpri.c common.c printstate.c" +IFILES=kmem.h +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.8 2001/02/13 01:12:33 fgsch Exp $ + +PROG= ipfstat +MAN= ${MFILES} +SRCS= ${SFILES} +.PATH: \${.CURDIR}/../../sbin/ipf +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sbin/ipf -DSTATETOP \\ + -I\${.CURDIR}/../../sys/netinet +DPADD= \${LIBCURSES} +LDADD= -lcurses -lkvm + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + +# +# Setup ipnat(8) +# +prep ../ipnat +MFILES="ipnat.8 ipnat.4 ipnat.5" +SFILES="ipnat.c kmem.c natparse.c common.c printnat.c" +IFILES= +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.10 2001/01/17 05:01:01 fgsch Exp $ + +PROG= ipnat +MAN= ${MFILES} +SRCS= ${SFILES} +.PATH: \${.CURDIR}/../ipfstat \${.CURDIR}/../ipf +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sbin/ipfstat -I\${.CURDIR}/../ipf \\ + -I\${.CURDIR}/../../sys/netinet +LDADD= -lkvm + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES +echo "`pwd` done" + +# +# Now fix up the top level Makefile +# +cd $SRC/sbin +grep -q ipf Makefile +if [ $? -ne 0 ] ; then + cat <<__EOF__ | patch +*** Makefile.orig Sat Sep 7 07:15:55 2002 +--- Makefile Wed Nov 13 12:33:36 2002 +*************** +*** 33,36 **** +--- 33,39 ---- + # Man pages (and manpages to do) + SUBDIR+= fdisk pdisk ancontrol wicontrol wsconsctl + ++ # IPFilter ++ SUBDIR+= ipf ipfstat ipnat ++ + .include <bsd.subdir.mk> +__EOF__ +fi + + +# +# 3 Programs into /usr/sbin: ipfs, ipfstat, ipmon +# Also, include ipsend suite of tools. +# +cd $SRC/usr.sbin +/bin/rm -rf ipfs ipftest ipmon ipsend + +# +# Create directory for ipftest +# +prep ipftest +MFILES=ipftest.1 +SFILES="ipt.c fil.c ipft_hx.c ipft_sn.c ipft_ef.c ipft_td.c ipft_pc.c \\ + ipft_tx.c misc.c parse.c opt.c ip_frag.c ip_nat.c ip_state.c \\ + ip_auth.c ip_fil.c ip_proxy.c facpri.c natparse.c common.c \\ + printnat.c printstate.c ip_log.c" +IFILES="ipt.h pcap.h snoop.h kmem.h bpf.h" +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.9 2001/01/17 06:01:21 fgsch Exp $ + +PROG= ipftest +MAN= ${MFILES} +SRCS= ${SFILES} + +.PATH: \${.CURDIR}/../../sbin/ipf \${.CURDIR}/../../sbin/ipfstat \\ + \${.CURDIR}/../../sys/netinet \${.CURDIR}/../../sbin/ipnat + +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sbin/ipf -DIPFILTER_LOG \\ + -I\${.CURDIR}/../../sys/netinet -I\${.CURDIR}/../../sys -I\${.CURDIR} + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# Create directory for ipfs +# +prep ../ipfs +MFILES=ipfs.8 +SFILES=ipfs.c +IFILES= +cat > ${OFILE} << __EOF__ +# \$OpenBSD: Makefile,v 1.1 2001/01/17 06:31:06 fgsch Exp \$ + +PROG= ipfs +MAN= ${MFILES} +SRCS= ${SFILES} + +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sbin/ipf \\ + -I\${.CURDIR}/../../sys/netinet + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# +# +prep ../ipmon +MFILES=ipmon.8 +SFILES=ipmon.c +IFILES= +cat > ${OFILE} << __EOF__ +# \$OpenBSD: Makefile,v 1.4 1998/09/15 10:01:38 pattonme Exp \$ + +PROG= ipmon +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sys/netinet + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# Create top level directories for ipsend +# +prep ../ipsend +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.4 1997/09/21 11:43:47 deraadt Exp $ + +SUBDIR= ipsend ipresend iptest + +.include <bsd.subdir.mk> +__EOF__ +echo "`pwd` done" + +prep iplang +copyfiles iplang.h + +# +# 1st ipsend program - ipsend itself +# +prep ../ipsend +MFILES="ipsend.1 ipsend.5" +SFILES="ipsend.c ip.c ipsopt.c sbpf.c sock.c 44arp.c iplang_y.y iplang_l.l" +IFILES="ipsend.h iplang.h" +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.3 1998/01/26 19:46:23 weingart Exp $ + +PROG= ipsend +BINDIR= /usr/sbin +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+= -DDOSOCKET -I\${.CURDIR}/../common -I\${.CURDIR}/../../ipftest \\ + -I\${.CURDIR}/../../../sbin/ipf -I\${.CURDIR}/../../../sys/netinet \\ + -I\${.CURDIR}/.. -I\${.OBJDIR} + +LDADD= -lfl +CLEANFILES+=y.tab.h + +.PATH: \${.CURDIR}/../common + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# 2nd ipsend program - ipresend +# +prep ../ipresend +MFILES=ipresend.1 +SFILES="ipresend.c resend.c \\ + ipft_ef.c ipft_hx.c ipft_pc.c ipft_sn.c ipft_td.c ipft_tx.c opt.c \\ + sock.c 44arp.c sbpf.c ip.c" +IFILES="ipsend.h bpf.h" +cat > ${OFILE} << __EOF__ +# \$OpenBSD: Makefile,v 1.4 1999/02/21 23:11:05 tholo Exp \$ + +PROG= ipresend +BINDIR= /usr/sbin +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+=-DDOSOCKET -I\${.CURDIR}/../common -I\${.CURDIR}/../../ipftest \\ + -I\${.CURDIR}/../../../sbin/ipf \\ + -I\${.CURDIR}/../../../sys/netinet -I\${.CURDIR}/.. +.PATH: \${.CURDIR}/../common \${.CURDIR}/../../ipftest \\ + \${.CURDIR}/../../../sbin/ipf + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# 3rd ipsend program - iptest +# +prep ../iptest +MFILES=iptest.1 +SFILES="iptest.c iptests.c ip.c sbpf.c sock.c 44arp.c" +IFILES="ipsend.h" +cat > ${OFILE} << __EOF__ +# \$OpenBSD: Makefile,v 1.2 1998/01/26 04:17:08 dgregor Exp \$ + +PROG= iptest +BINDIR= /usr/sbin +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+=-DDOSOCKET -I\${.CURDIR}/../common -I\${.CURDIR}/../../ipftest \\ + -I\${.CURDIR}/../../../sys/netinet \\ + -I\${.CURDIR}/../../../sbin/ipf -I\${.CURDIR}/.. +.PATH: \${.CURDIR}/../common + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + +cd $SRC/usr.sbin +grep -q ipmon Makefile +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** Makefile.orig Fri Jun 21 16:22:20 2002 +--- Makefile Wed Nov 13 12:33:43 2002 +*************** +*** 40,43 **** +--- 40,46 ---- + SUBDIR+=ypbind yppoll ypset ypserv + .endif + ++ # IPFilter ++ SUBDIR+=ipftest ipfs ipmon ipsend ++ + .include <bsd.subdir.mk> +__EOF__ +fi + +echo "Patching base install set" +cd $SRC +cd distrib/sets/lists/base +grep -q ipfstat mi +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** mi.orig Mon Sep 30 04:28:45 2002 +--- mi Wed Nov 13 12:33:44 2002 +*************** +*** 90,95 **** +--- 90,98 ---- + ./sbin/halt + ./sbin/ifconfig + ./sbin/init ++ ./sbin/ipf ++ ./sbin/ipfstat ++ ./sbin/ipnat + ./sbin/ipsecadm + ./sbin/isakmpd + ./sbin/lmccontrol +*************** +*** 1273,1278 **** +--- 1276,1287 ---- + ./usr/sbin/httpd + ./usr/sbin/inetd + ./usr/sbin/iostat ++ ./usr/sbin/ipfs ++ ./usr/sbin/ipftest ++ ./usr/sbin/ipmon ++ ./usr/sbin/ipresend ++ ./usr/sbin/ipsend ++ ./usr/sbin/iptest + ./usr/sbin/kadmin + ./usr/sbin/kdb_destroy + ./usr/sbin/kdb_edit +__EOF__ +fi + +echo "Patching etc Makefile" +cd $SRC +cd etc +grep -q ipf.conf Makefile +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** Makefile.orig Sat Sep 7 07:30:22 2002 +--- Makefile Wed Nov 13 12:38:44 2002 +*************** +*** 14,20 **** + BINGRP= wheel + BIN1= bootptab changelist ccd.conf csh.cshrc csh.login csh.logout \\ + daily dhcpd.conf dhcpd.interfaces exports ftpusers \\ +! ftpchroot gettytab group hosts hosts.lpd inetd.conf \\ + ksh.kshrc locate.rc man.conf monthly motd mrouted.conf \\ + myname netstart networks newsyslog.conf pf.conf \\ + phones printcap protocols rbootd.conf rc rc.conf rc.local \\ +--- 14,20 ---- + BINGRP= wheel + BIN1= bootptab changelist ccd.conf csh.cshrc csh.login csh.logout \\ + daily dhcpd.conf dhcpd.interfaces exports ftpusers \\ +! ftpchroot gettytab group hosts hosts.lpd inetd.conf ipf.conf \\ + ksh.kshrc locate.rc man.conf monthly motd mrouted.conf \\ + myname netstart networks newsyslog.conf pf.conf \\ + phones printcap protocols rbootd.conf rc rc.conf rc.local \\ +__EOF__ +fi + +echo "Patching etc mi install set" +cd $SRC +cd distrib/sets/lists/etc +grep -q ipf.conf mi +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** mi.orig Sat Sep 28 20:23:13 2002 +--- mi Wed Nov 13 12:33:44 2002 +*************** +*** 29,34 **** +--- 29,35 ---- + ./etc/hosts.equiv + ./etc/hosts.lpd + ./etc/inetd.conf ++ ./etc/ipf.conf + ./etc/kerberosIV/README + ./etc/kerberosIV/krb.conf + ./etc/kerberosIV/krb.equiv +__EOF__ +fi + +echo "Patching man install set" +cd $SRC +cd distrib/sets/lists/man +grep -q ipfstat mi +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** mi.orig Thu Oct 3 09:49:02 2002 +--- mi Wed Nov 13 12:33:45 2002 +*************** +*** 322,327 **** +--- 322,331 ---- + ./usr/share/man/cat1/intro.0 + ./usr/share/man/cat1/ipcrm.0 + ./usr/share/man/cat1/ipcs.0 ++ ./usr/share/man/cat1/ipftest.0 ++ ./usr/share/man/cat1/ipresend.0 ++ ./usr/share/man/cat1/ipsend.0 ++ ./usr/share/man/cat1/iptest.0 + ./usr/share/man/cat1/jobs.0 + ./usr/share/man/cat1/join.0 + ./usr/share/man/cat1/jot.0 +*************** +*** 1063,1068 **** +--- 1067,1075 ---- + ./usr/share/man/cat4/ip.0 + ./usr/share/man/cat4/ip6.0 + ./usr/share/man/cat4/ipcomp.0 ++ ./usr/share/man/cat4/ipf.0 ++ ./usr/share/man/cat4/ipl.0 ++ ./usr/share/man/cat4/ipnat.0 + ./usr/share/man/cat4/ipsec.0 + ./usr/share/man/cat4/isa.0 + ./usr/share/man/cat4/isapnp.0 +*************** +*** 1434,1439 **** +--- 1441,1449 ---- + ./usr/share/man/cat5/info.0 + ./usr/share/man/cat5/inode.0 + ./usr/share/man/cat5/intro.0 ++ ./usr/share/man/cat5/ipf.0 ++ ./usr/share/man/cat5/ipnat.0 ++ ./usr/share/man/cat5/ipsend.0 + ./usr/share/man/cat5/isakmpd.conf.0 + ./usr/share/man/cat5/isakmpd.policy.0 + ./usr/share/man/cat5/keynote.0 +*************** +*** 1681,1686 **** +--- 1691,1701 ---- + ./usr/share/man/cat8/intro.0 + ./usr/share/man/cat8/iopctl.0 + ./usr/share/man/cat8/iostat.0 ++ ./usr/share/man/cat8/ipf.0 ++ ./usr/share/man/cat8/ipfs.0 ++ ./usr/share/man/cat8/ipfstat.0 ++ ./usr/share/man/cat8/ipmon.0 ++ ./usr/share/man/cat8/ipnat.0 + ./usr/share/man/cat8/ipsecadm.0 + ./usr/share/man/cat8/isakmpd.0 + ./usr/share/man/cat8/kadmin.0 +__EOF__ +fi + +echo Creating etc/ipf.conf +cd $SRC +cd etc +if [ ! -f ipf.conf ] ; then + cat > ipf.conf << __EOF__ +# +# See ipf(5) for syntax and examples. +# +# Pass all packets in and out (these are the implicit first two rules.) +# pass in all +# pass out all +__EOF__ +fi +exit 0 diff --git a/OpenBSD-3/fixdist-3.4 b/OpenBSD-3/fixdist-3.4 new file mode 100755 index 0000000000000..b6bf29672e58f --- /dev/null +++ b/OpenBSD-3/fixdist-3.4 @@ -0,0 +1,495 @@ +#!/bin/sh +# +# Install IPFilter into the source tree of OpenBSD 3.3 +# + +if [ $# -eq 1 ] ; then + if [ "$1" = "-d" ] ; then + debug=echo + fi +fi + +copyfiles() { + while [ $# -gt 0 ] ; do + if [ X"$1" = X"\\" ] ; then + : + elif [ -f $IPFDIR/$1 ] ; then + $debug cp -p $IPFDIR/$1 . + elif [ -f $IPFDIR/man/$1 ] ; then + $debug cp -p $IPFDIR/man/$1 . + elif [ -f $IPFDIR/iplang/$1 ] ; then + $debug cp -p $IPFDIR/iplang/$1 . + elif [ -f $IPFDIR/ipsend/$1 ] ; then + $debug cp -p $IPFDIR/ipsend/$1 . + else + echo "Could not find $IPFDIR/$1" + fi + shift + done +} + +prep() { + $debug mkdir $1 + $debug cd $1 +} + +IPFDIR=`pwd` +SRC=/usr/src + +# +# 3 Programs into /sbin: ipf, ipfstat, ipnat +# +cd $SRC/sbin +/bin/rm -rf ipf ipfstat ipnat + +prep ipf +MFILES="ipf.8 ipf.4 ipf.5 ipl.4" +SFILES="ipf.c parse.c opt.c facpri.c common.c" +IFILES="ipf.h facpri.h" +if [ X$debug = X ] ; then + OFILE=Makefile +else + OFILE=/dev/tty +fi +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.10 2001/01/17 05:00:57 fgsch Exp $ + +PROG= ipf +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sys/netinet + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + +# +# Setup ipfstat(8) +# +prep ../ipfstat +MFILES=ipfstat.8 +SFILES="fils.c parse.c opt.c kmem.c facpri.c common.c printstate.c" +IFILES=kmem.h +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.8 2001/02/13 01:12:33 fgsch Exp $ + +PROG= ipfstat +MAN= ${MFILES} +SRCS= ${SFILES} +.PATH: \${.CURDIR}/../../sbin/ipf +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sbin/ipf -DSTATETOP \\ + -I\${.CURDIR}/../../sys/netinet +DPADD= \${LIBCURSES} +LDADD= -lcurses -lkvm + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + +# +# Setup ipnat(8) +# +prep ../ipnat +MFILES="ipnat.8 ipnat.4 ipnat.5" +SFILES="ipnat.c kmem.c natparse.c common.c printnat.c" +IFILES= +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.10 2001/01/17 05:01:01 fgsch Exp $ + +PROG= ipnat +MAN= ${MFILES} +SRCS= ${SFILES} +.PATH: \${.CURDIR}/../ipfstat \${.CURDIR}/../ipf +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sbin/ipfstat -I\${.CURDIR}/../ipf \\ + -I\${.CURDIR}/../../sys/netinet +LDADD= -lkvm + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES +echo "`pwd` done" + +# +# Now fix up the top level Makefile +# +cd $SRC/sbin +grep -q ipf Makefile +if [ $? -ne 0 ] ; then + cat <<__EOF__ | patch +*** Makefile.orig Sat Sep 7 07:15:55 2002 +--- Makefile Wed Nov 13 12:33:36 2002 +*************** +*** 33,36 **** +--- 33,39 ---- + # Man pages (and manpages to do) + SUBDIR+= fdisk pdisk ancontrol wicontrol wsconsctl + ++ # IPFilter ++ SUBDIR+= ipf ipfstat ipnat ++ + .include <bsd.subdir.mk> +__EOF__ +fi + + +# +# 3 Programs into /usr/sbin: ipfs, ipfstat, ipmon +# Also, include ipsend suite of tools. +# +cd $SRC/usr.sbin +/bin/rm -rf ipfs ipftest ipmon ipsend + +# +# Create directory for ipftest +# +prep ipftest +MFILES=ipftest.1 +SFILES="ipt.c fil.c ipft_hx.c ipft_sn.c ipft_ef.c ipft_td.c ipft_pc.c \\ + ipft_tx.c misc.c parse.c opt.c ip_frag.c ip_nat.c ip_state.c \\ + ip_auth.c ip_fil.c ip_proxy.c facpri.c natparse.c common.c \\ + printnat.c printstate.c ip_log.c" +IFILES="ipt.h pcap.h snoop.h kmem.h bpf.h" +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.9 2001/01/17 06:01:21 fgsch Exp $ + +PROG= ipftest +MAN= ${MFILES} +SRCS= ${SFILES} + +.PATH: \${.CURDIR}/../../sbin/ipf \${.CURDIR}/../../sbin/ipfstat \\ + \${.CURDIR}/../../sys/netinet \${.CURDIR}/../../sbin/ipnat + +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sbin/ipf -DIPFILTER_LOG \\ + -I\${.CURDIR}/../../sys/netinet -I\${.CURDIR}/../../sys -I\${.CURDIR} + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# Create directory for ipfs +# +prep ../ipfs +MFILES=ipfs.8 +SFILES=ipfs.c +IFILES= +cat > ${OFILE} << __EOF__ +# \$OpenBSD: Makefile,v 1.1 2001/01/17 06:31:06 fgsch Exp \$ + +PROG= ipfs +MAN= ${MFILES} +SRCS= ${SFILES} + +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sbin/ipf \\ + -I\${.CURDIR}/../../sys/netinet + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# +# +prep ../ipmon +MFILES=ipmon.8 +SFILES=ipmon.c +IFILES= +cat > ${OFILE} << __EOF__ +# \$OpenBSD: Makefile,v 1.4 1998/09/15 10:01:38 pattonme Exp \$ + +PROG= ipmon +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sys/netinet + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# Create top level directories for ipsend +# +prep ../ipsend +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.4 1997/09/21 11:43:47 deraadt Exp $ + +SUBDIR= ipsend ipresend iptest + +.include <bsd.subdir.mk> +__EOF__ +echo "`pwd` done" + +prep iplang +copyfiles iplang.h + +# +# 1st ipsend program - ipsend itself +# +prep ../ipsend +MFILES="ipsend.1 ipsend.5" +SFILES="ipsend.c ip.c ipsopt.c sbpf.c sock.c 44arp.c iplang_y.y iplang_l.l" +IFILES="ipsend.h iplang.h" +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.3 1998/01/26 19:46:23 weingart Exp $ + +PROG= ipsend +BINDIR= /usr/sbin +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+= -DDOSOCKET -I\${.CURDIR}/../common -I\${.CURDIR}/../../ipftest \\ + -I\${.CURDIR}/../../../sbin/ipf -I\${.CURDIR}/../../../sys/netinet \\ + -I\${.CURDIR}/.. -I\${.OBJDIR} + +LDADD= -lfl +CLEANFILES+=y.tab.h + +.PATH: \${.CURDIR}/../common + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# 2nd ipsend program - ipresend +# +prep ../ipresend +MFILES=ipresend.1 +SFILES="ipresend.c resend.c \\ + ipft_ef.c ipft_hx.c ipft_pc.c ipft_sn.c ipft_td.c ipft_tx.c opt.c \\ + sock.c 44arp.c sbpf.c ip.c" +IFILES="ipsend.h bpf.h" +cat > ${OFILE} << __EOF__ +# \$OpenBSD: Makefile,v 1.4 1999/02/21 23:11:05 tholo Exp \$ + +PROG= ipresend +BINDIR= /usr/sbin +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+=-DDOSOCKET -I\${.CURDIR}/../common -I\${.CURDIR}/../../ipftest \\ + -I\${.CURDIR}/../../../sbin/ipf \\ + -I\${.CURDIR}/../../../sys/netinet -I\${.CURDIR}/.. +.PATH: \${.CURDIR}/../common \${.CURDIR}/../../ipftest \\ + \${.CURDIR}/../../../sbin/ipf + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# 3rd ipsend program - iptest +# +prep ../iptest +MFILES=iptest.1 +SFILES="iptest.c iptests.c ip.c sbpf.c sock.c 44arp.c" +IFILES="ipsend.h" +cat > ${OFILE} << __EOF__ +# \$OpenBSD: Makefile,v 1.2 1998/01/26 04:17:08 dgregor Exp \$ + +PROG= iptest +BINDIR= /usr/sbin +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+=-DDOSOCKET -I\${.CURDIR}/../common -I\${.CURDIR}/../../ipftest \\ + -I\${.CURDIR}/../../../sys/netinet \\ + -I\${.CURDIR}/../../../sbin/ipf -I\${.CURDIR}/.. +.PATH: \${.CURDIR}/../common + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + +cd $SRC/usr.sbin +grep -q ipmon Makefile +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** Makefile.orig Fri Jun 21 16:22:20 2002 +--- Makefile Wed Nov 13 12:33:43 2002 +*************** +*** 40,43 **** +--- 40,46 ---- + SUBDIR+=ypbind yppoll ypset ypserv + .endif + ++ # IPFilter ++ SUBDIR+=ipftest ipfs ipmon ipsend ++ + .include <bsd.subdir.mk> +__EOF__ +fi + +echo "Patching base install set" +cd $SRC +cd distrib/sets/lists/base +grep -q ipfstat mi +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** mi.orig Mon Sep 30 04:28:45 2002 +--- mi Wed Nov 13 12:33:44 2002 +*************** +*** 90,95 **** +--- 90,98 ---- + ./sbin/halt + ./sbin/ifconfig + ./sbin/init ++ ./sbin/ipf ++ ./sbin/ipfstat ++ ./sbin/ipnat + ./sbin/ipsecadm + ./sbin/isakmpd + ./sbin/lmccontrol +*************** +*** 1273,1278 **** +--- 1276,1287 ---- + ./usr/sbin/httpd + ./usr/sbin/inetd + ./usr/sbin/iostat ++ ./usr/sbin/ipfs ++ ./usr/sbin/ipftest ++ ./usr/sbin/ipmon ++ ./usr/sbin/ipresend ++ ./usr/sbin/ipsend ++ ./usr/sbin/iptest + ./usr/sbin/kadmin + ./usr/sbin/kdb_destroy + ./usr/sbin/kdb_edit +__EOF__ +fi + +echo "Patching etc Makefile" +cd $SRC +cd etc +grep -q ipf.conf Makefile +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** Makefile.orig Sat Sep 7 07:30:22 2002 +--- Makefile Wed Nov 13 12:38:44 2002 +*************** +*** 14,20 **** + BINGRP= wheel + BIN1= bootptab changelist ccd.conf csh.cshrc csh.login csh.logout \\ + daily dhcpd.conf dhcpd.interfaces exports ftpusers \\ +! ftpchroot gettytab group hosts hosts.lpd inetd.conf \\ + ksh.kshrc locate.rc man.conf monthly motd mrouted.conf \\ + myname netstart networks newsyslog.conf pf.conf \\ + phones printcap protocols rbootd.conf rc rc.conf rc.local \\ +--- 14,20 ---- + BINGRP= wheel + BIN1= bootptab changelist ccd.conf csh.cshrc csh.login csh.logout \\ + daily dhcpd.conf dhcpd.interfaces exports ftpusers \\ +! ftpchroot gettytab group hosts hosts.lpd inetd.conf ipf.conf \\ + ksh.kshrc locate.rc man.conf monthly motd mrouted.conf \\ + myname netstart networks newsyslog.conf pf.conf \\ + phones printcap protocols rbootd.conf rc rc.conf rc.local \\ +__EOF__ +fi + +echo "Patching etc mi install set" +cd $SRC +cd distrib/sets/lists/etc +grep -q ipf.conf mi +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** mi.orig Sat Sep 28 20:23:13 2002 +--- mi Wed Nov 13 12:33:44 2002 +*************** +*** 29,34 **** +--- 29,35 ---- + ./etc/hosts.equiv + ./etc/hosts.lpd + ./etc/inetd.conf ++ ./etc/ipf.conf + ./etc/kerberosIV/README + ./etc/kerberosIV/krb.conf + ./etc/kerberosIV/krb.equiv +__EOF__ +fi + +echo "Patching man install set" +cd $SRC +cd distrib/sets/lists/man +grep -q ipfstat mi +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** mi.orig Thu Oct 3 09:49:02 2002 +--- mi Wed Nov 13 12:33:45 2002 +*************** +*** 322,327 **** +--- 322,331 ---- + ./usr/share/man/cat1/intro.0 + ./usr/share/man/cat1/ipcrm.0 + ./usr/share/man/cat1/ipcs.0 ++ ./usr/share/man/cat1/ipftest.0 ++ ./usr/share/man/cat1/ipresend.0 ++ ./usr/share/man/cat1/ipsend.0 ++ ./usr/share/man/cat1/iptest.0 + ./usr/share/man/cat1/jobs.0 + ./usr/share/man/cat1/join.0 + ./usr/share/man/cat1/jot.0 +*************** +*** 1063,1068 **** +--- 1067,1075 ---- + ./usr/share/man/cat4/ip.0 + ./usr/share/man/cat4/ip6.0 + ./usr/share/man/cat4/ipcomp.0 ++ ./usr/share/man/cat4/ipf.0 ++ ./usr/share/man/cat4/ipl.0 ++ ./usr/share/man/cat4/ipnat.0 + ./usr/share/man/cat4/ipsec.0 + ./usr/share/man/cat4/isa.0 + ./usr/share/man/cat4/isapnp.0 +*************** +*** 1434,1439 **** +--- 1441,1449 ---- + ./usr/share/man/cat5/info.0 + ./usr/share/man/cat5/inode.0 + ./usr/share/man/cat5/intro.0 ++ ./usr/share/man/cat5/ipf.0 ++ ./usr/share/man/cat5/ipnat.0 ++ ./usr/share/man/cat5/ipsend.0 + ./usr/share/man/cat5/isakmpd.conf.0 + ./usr/share/man/cat5/isakmpd.policy.0 + ./usr/share/man/cat5/keynote.0 +*************** +*** 1681,1686 **** +--- 1691,1701 ---- + ./usr/share/man/cat8/intro.0 + ./usr/share/man/cat8/iopctl.0 + ./usr/share/man/cat8/iostat.0 ++ ./usr/share/man/cat8/ipf.0 ++ ./usr/share/man/cat8/ipfs.0 ++ ./usr/share/man/cat8/ipfstat.0 ++ ./usr/share/man/cat8/ipmon.0 ++ ./usr/share/man/cat8/ipnat.0 + ./usr/share/man/cat8/ipsecadm.0 + ./usr/share/man/cat8/isakmpd.0 + ./usr/share/man/cat8/kadmin.0 +__EOF__ +fi + +echo Creating etc/ipf.conf +cd $SRC +cd etc +if [ ! -f ipf.conf ] ; then + cat > ipf.conf << __EOF__ +# +# See ipf(5) for syntax and examples. +# +# Pass all packets in and out (these are the implicit first two rules.) +# pass in all +# pass out all +__EOF__ +fi +exit 0 diff --git a/OpenBSD-3/fixdist-3.5 b/OpenBSD-3/fixdist-3.5 new file mode 100755 index 0000000000000..b6bf29672e58f --- /dev/null +++ b/OpenBSD-3/fixdist-3.5 @@ -0,0 +1,495 @@ +#!/bin/sh +# +# Install IPFilter into the source tree of OpenBSD 3.3 +# + +if [ $# -eq 1 ] ; then + if [ "$1" = "-d" ] ; then + debug=echo + fi +fi + +copyfiles() { + while [ $# -gt 0 ] ; do + if [ X"$1" = X"\\" ] ; then + : + elif [ -f $IPFDIR/$1 ] ; then + $debug cp -p $IPFDIR/$1 . + elif [ -f $IPFDIR/man/$1 ] ; then + $debug cp -p $IPFDIR/man/$1 . + elif [ -f $IPFDIR/iplang/$1 ] ; then + $debug cp -p $IPFDIR/iplang/$1 . + elif [ -f $IPFDIR/ipsend/$1 ] ; then + $debug cp -p $IPFDIR/ipsend/$1 . + else + echo "Could not find $IPFDIR/$1" + fi + shift + done +} + +prep() { + $debug mkdir $1 + $debug cd $1 +} + +IPFDIR=`pwd` +SRC=/usr/src + +# +# 3 Programs into /sbin: ipf, ipfstat, ipnat +# +cd $SRC/sbin +/bin/rm -rf ipf ipfstat ipnat + +prep ipf +MFILES="ipf.8 ipf.4 ipf.5 ipl.4" +SFILES="ipf.c parse.c opt.c facpri.c common.c" +IFILES="ipf.h facpri.h" +if [ X$debug = X ] ; then + OFILE=Makefile +else + OFILE=/dev/tty +fi +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.10 2001/01/17 05:00:57 fgsch Exp $ + +PROG= ipf +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sys/netinet + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + +# +# Setup ipfstat(8) +# +prep ../ipfstat +MFILES=ipfstat.8 +SFILES="fils.c parse.c opt.c kmem.c facpri.c common.c printstate.c" +IFILES=kmem.h +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.8 2001/02/13 01:12:33 fgsch Exp $ + +PROG= ipfstat +MAN= ${MFILES} +SRCS= ${SFILES} +.PATH: \${.CURDIR}/../../sbin/ipf +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sbin/ipf -DSTATETOP \\ + -I\${.CURDIR}/../../sys/netinet +DPADD= \${LIBCURSES} +LDADD= -lcurses -lkvm + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + +# +# Setup ipnat(8) +# +prep ../ipnat +MFILES="ipnat.8 ipnat.4 ipnat.5" +SFILES="ipnat.c kmem.c natparse.c common.c printnat.c" +IFILES= +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.10 2001/01/17 05:01:01 fgsch Exp $ + +PROG= ipnat +MAN= ${MFILES} +SRCS= ${SFILES} +.PATH: \${.CURDIR}/../ipfstat \${.CURDIR}/../ipf +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sbin/ipfstat -I\${.CURDIR}/../ipf \\ + -I\${.CURDIR}/../../sys/netinet +LDADD= -lkvm + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES +echo "`pwd` done" + +# +# Now fix up the top level Makefile +# +cd $SRC/sbin +grep -q ipf Makefile +if [ $? -ne 0 ] ; then + cat <<__EOF__ | patch +*** Makefile.orig Sat Sep 7 07:15:55 2002 +--- Makefile Wed Nov 13 12:33:36 2002 +*************** +*** 33,36 **** +--- 33,39 ---- + # Man pages (and manpages to do) + SUBDIR+= fdisk pdisk ancontrol wicontrol wsconsctl + ++ # IPFilter ++ SUBDIR+= ipf ipfstat ipnat ++ + .include <bsd.subdir.mk> +__EOF__ +fi + + +# +# 3 Programs into /usr/sbin: ipfs, ipfstat, ipmon +# Also, include ipsend suite of tools. +# +cd $SRC/usr.sbin +/bin/rm -rf ipfs ipftest ipmon ipsend + +# +# Create directory for ipftest +# +prep ipftest +MFILES=ipftest.1 +SFILES="ipt.c fil.c ipft_hx.c ipft_sn.c ipft_ef.c ipft_td.c ipft_pc.c \\ + ipft_tx.c misc.c parse.c opt.c ip_frag.c ip_nat.c ip_state.c \\ + ip_auth.c ip_fil.c ip_proxy.c facpri.c natparse.c common.c \\ + printnat.c printstate.c ip_log.c" +IFILES="ipt.h pcap.h snoop.h kmem.h bpf.h" +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.9 2001/01/17 06:01:21 fgsch Exp $ + +PROG= ipftest +MAN= ${MFILES} +SRCS= ${SFILES} + +.PATH: \${.CURDIR}/../../sbin/ipf \${.CURDIR}/../../sbin/ipfstat \\ + \${.CURDIR}/../../sys/netinet \${.CURDIR}/../../sbin/ipnat + +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sbin/ipf -DIPFILTER_LOG \\ + -I\${.CURDIR}/../../sys/netinet -I\${.CURDIR}/../../sys -I\${.CURDIR} + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# Create directory for ipfs +# +prep ../ipfs +MFILES=ipfs.8 +SFILES=ipfs.c +IFILES= +cat > ${OFILE} << __EOF__ +# \$OpenBSD: Makefile,v 1.1 2001/01/17 06:31:06 fgsch Exp \$ + +PROG= ipfs +MAN= ${MFILES} +SRCS= ${SFILES} + +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sbin/ipf \\ + -I\${.CURDIR}/../../sys/netinet + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# +# +prep ../ipmon +MFILES=ipmon.8 +SFILES=ipmon.c +IFILES= +cat > ${OFILE} << __EOF__ +# \$OpenBSD: Makefile,v 1.4 1998/09/15 10:01:38 pattonme Exp \$ + +PROG= ipmon +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+=-DUSE_INET6 -I\${.CURDIR}/../../sys/netinet + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# Create top level directories for ipsend +# +prep ../ipsend +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.4 1997/09/21 11:43:47 deraadt Exp $ + +SUBDIR= ipsend ipresend iptest + +.include <bsd.subdir.mk> +__EOF__ +echo "`pwd` done" + +prep iplang +copyfiles iplang.h + +# +# 1st ipsend program - ipsend itself +# +prep ../ipsend +MFILES="ipsend.1 ipsend.5" +SFILES="ipsend.c ip.c ipsopt.c sbpf.c sock.c 44arp.c iplang_y.y iplang_l.l" +IFILES="ipsend.h iplang.h" +cat > ${OFILE} << __EOF__ +# $OpenBSD: Makefile,v 1.3 1998/01/26 19:46:23 weingart Exp $ + +PROG= ipsend +BINDIR= /usr/sbin +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+= -DDOSOCKET -I\${.CURDIR}/../common -I\${.CURDIR}/../../ipftest \\ + -I\${.CURDIR}/../../../sbin/ipf -I\${.CURDIR}/../../../sys/netinet \\ + -I\${.CURDIR}/.. -I\${.OBJDIR} + +LDADD= -lfl +CLEANFILES+=y.tab.h + +.PATH: \${.CURDIR}/../common + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# 2nd ipsend program - ipresend +# +prep ../ipresend +MFILES=ipresend.1 +SFILES="ipresend.c resend.c \\ + ipft_ef.c ipft_hx.c ipft_pc.c ipft_sn.c ipft_td.c ipft_tx.c opt.c \\ + sock.c 44arp.c sbpf.c ip.c" +IFILES="ipsend.h bpf.h" +cat > ${OFILE} << __EOF__ +# \$OpenBSD: Makefile,v 1.4 1999/02/21 23:11:05 tholo Exp \$ + +PROG= ipresend +BINDIR= /usr/sbin +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+=-DDOSOCKET -I\${.CURDIR}/../common -I\${.CURDIR}/../../ipftest \\ + -I\${.CURDIR}/../../../sbin/ipf \\ + -I\${.CURDIR}/../../../sys/netinet -I\${.CURDIR}/.. +.PATH: \${.CURDIR}/../common \${.CURDIR}/../../ipftest \\ + \${.CURDIR}/../../../sbin/ipf + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + + +# +# 3rd ipsend program - iptest +# +prep ../iptest +MFILES=iptest.1 +SFILES="iptest.c iptests.c ip.c sbpf.c sock.c 44arp.c" +IFILES="ipsend.h" +cat > ${OFILE} << __EOF__ +# \$OpenBSD: Makefile,v 1.2 1998/01/26 04:17:08 dgregor Exp \$ + +PROG= iptest +BINDIR= /usr/sbin +MAN= ${MFILES} +SRCS= ${SFILES} +CFLAGS+=-DDOSOCKET -I\${.CURDIR}/../common -I\${.CURDIR}/../../ipftest \\ + -I\${.CURDIR}/../../../sys/netinet \\ + -I\${.CURDIR}/../../../sbin/ipf -I\${.CURDIR}/.. +.PATH: \${.CURDIR}/../common + +.include <bsd.prog.mk> +__EOF__ +copyfiles $MFILES $SFILES $IFILES +echo "`pwd` done" + +cd $SRC/usr.sbin +grep -q ipmon Makefile +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** Makefile.orig Fri Jun 21 16:22:20 2002 +--- Makefile Wed Nov 13 12:33:43 2002 +*************** +*** 40,43 **** +--- 40,46 ---- + SUBDIR+=ypbind yppoll ypset ypserv + .endif + ++ # IPFilter ++ SUBDIR+=ipftest ipfs ipmon ipsend ++ + .include <bsd.subdir.mk> +__EOF__ +fi + +echo "Patching base install set" +cd $SRC +cd distrib/sets/lists/base +grep -q ipfstat mi +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** mi.orig Mon Sep 30 04:28:45 2002 +--- mi Wed Nov 13 12:33:44 2002 +*************** +*** 90,95 **** +--- 90,98 ---- + ./sbin/halt + ./sbin/ifconfig + ./sbin/init ++ ./sbin/ipf ++ ./sbin/ipfstat ++ ./sbin/ipnat + ./sbin/ipsecadm + ./sbin/isakmpd + ./sbin/lmccontrol +*************** +*** 1273,1278 **** +--- 1276,1287 ---- + ./usr/sbin/httpd + ./usr/sbin/inetd + ./usr/sbin/iostat ++ ./usr/sbin/ipfs ++ ./usr/sbin/ipftest ++ ./usr/sbin/ipmon ++ ./usr/sbin/ipresend ++ ./usr/sbin/ipsend ++ ./usr/sbin/iptest + ./usr/sbin/kadmin + ./usr/sbin/kdb_destroy + ./usr/sbin/kdb_edit +__EOF__ +fi + +echo "Patching etc Makefile" +cd $SRC +cd etc +grep -q ipf.conf Makefile +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** Makefile.orig Sat Sep 7 07:30:22 2002 +--- Makefile Wed Nov 13 12:38:44 2002 +*************** +*** 14,20 **** + BINGRP= wheel + BIN1= bootptab changelist ccd.conf csh.cshrc csh.login csh.logout \\ + daily dhcpd.conf dhcpd.interfaces exports ftpusers \\ +! ftpchroot gettytab group hosts hosts.lpd inetd.conf \\ + ksh.kshrc locate.rc man.conf monthly motd mrouted.conf \\ + myname netstart networks newsyslog.conf pf.conf \\ + phones printcap protocols rbootd.conf rc rc.conf rc.local \\ +--- 14,20 ---- + BINGRP= wheel + BIN1= bootptab changelist ccd.conf csh.cshrc csh.login csh.logout \\ + daily dhcpd.conf dhcpd.interfaces exports ftpusers \\ +! ftpchroot gettytab group hosts hosts.lpd inetd.conf ipf.conf \\ + ksh.kshrc locate.rc man.conf monthly motd mrouted.conf \\ + myname netstart networks newsyslog.conf pf.conf \\ + phones printcap protocols rbootd.conf rc rc.conf rc.local \\ +__EOF__ +fi + +echo "Patching etc mi install set" +cd $SRC +cd distrib/sets/lists/etc +grep -q ipf.conf mi +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** mi.orig Sat Sep 28 20:23:13 2002 +--- mi Wed Nov 13 12:33:44 2002 +*************** +*** 29,34 **** +--- 29,35 ---- + ./etc/hosts.equiv + ./etc/hosts.lpd + ./etc/inetd.conf ++ ./etc/ipf.conf + ./etc/kerberosIV/README + ./etc/kerberosIV/krb.conf + ./etc/kerberosIV/krb.equiv +__EOF__ +fi + +echo "Patching man install set" +cd $SRC +cd distrib/sets/lists/man +grep -q ipfstat mi +if [ $? -ne 0 ] ; then + cat << __EOF__ | patch +*** mi.orig Thu Oct 3 09:49:02 2002 +--- mi Wed Nov 13 12:33:45 2002 +*************** +*** 322,327 **** +--- 322,331 ---- + ./usr/share/man/cat1/intro.0 + ./usr/share/man/cat1/ipcrm.0 + ./usr/share/man/cat1/ipcs.0 ++ ./usr/share/man/cat1/ipftest.0 ++ ./usr/share/man/cat1/ipresend.0 ++ ./usr/share/man/cat1/ipsend.0 ++ ./usr/share/man/cat1/iptest.0 + ./usr/share/man/cat1/jobs.0 + ./usr/share/man/cat1/join.0 + ./usr/share/man/cat1/jot.0 +*************** +*** 1063,1068 **** +--- 1067,1075 ---- + ./usr/share/man/cat4/ip.0 + ./usr/share/man/cat4/ip6.0 + ./usr/share/man/cat4/ipcomp.0 ++ ./usr/share/man/cat4/ipf.0 ++ ./usr/share/man/cat4/ipl.0 ++ ./usr/share/man/cat4/ipnat.0 + ./usr/share/man/cat4/ipsec.0 + ./usr/share/man/cat4/isa.0 + ./usr/share/man/cat4/isapnp.0 +*************** +*** 1434,1439 **** +--- 1441,1449 ---- + ./usr/share/man/cat5/info.0 + ./usr/share/man/cat5/inode.0 + ./usr/share/man/cat5/intro.0 ++ ./usr/share/man/cat5/ipf.0 ++ ./usr/share/man/cat5/ipnat.0 ++ ./usr/share/man/cat5/ipsend.0 + ./usr/share/man/cat5/isakmpd.conf.0 + ./usr/share/man/cat5/isakmpd.policy.0 + ./usr/share/man/cat5/keynote.0 +*************** +*** 1681,1686 **** +--- 1691,1701 ---- + ./usr/share/man/cat8/intro.0 + ./usr/share/man/cat8/iopctl.0 + ./usr/share/man/cat8/iostat.0 ++ ./usr/share/man/cat8/ipf.0 ++ ./usr/share/man/cat8/ipfs.0 ++ ./usr/share/man/cat8/ipfstat.0 ++ ./usr/share/man/cat8/ipmon.0 ++ ./usr/share/man/cat8/ipnat.0 + ./usr/share/man/cat8/ipsecadm.0 + ./usr/share/man/cat8/isakmpd.0 + ./usr/share/man/cat8/kadmin.0 +__EOF__ +fi + +echo Creating etc/ipf.conf +cd $SRC +cd etc +if [ ! -f ipf.conf ] ; then + cat > ipf.conf << __EOF__ +# +# See ipf(5) for syntax and examples. +# +# Pass all packets in and out (these are the implicit first two rules.) +# pass in all +# pass out all +__EOF__ +fi +exit 0 diff --git a/OpenBSD-3/makedevs-3.0 b/OpenBSD-3/makedevs-3.0 new file mode 100755 index 0000000000000..59dffd1eb36f4 --- /dev/null +++ b/OpenBSD-3/makedevs-3.0 @@ -0,0 +1,70 @@ +#!/bin/sh + +platform=`uname -m` + +case $platform in + alpha) + major=37 + ;; + amiga) + major=38 + ;; + hp300) + major=37 + ;; + hppa) + major=34 + ;; + i386) + major=77 + ;; + mac68k) + major=38 + ;; + macppc) + major=45 + ;; + mvme68k) + major=44 + ;; + mvme88k) + major=41 + ;; + mvmeppc) + major=44 + ;; + sparc) + major=60 + ;; + sparc64) + major=75 + ;; + sun3) + major=86 + ;; + vax) + major=47 + ;; + *) + echo "Unrecognised platform $platform" + exit 1 + ;; +esac + +minor=0 +echo +echo "Creating IPFilter device files in /dev." +echo +echo -n "Platform $platform Major Number $major: " +for i in ipl ipnat ipstate ipauth ipsync ipscan iplookup; do + /bin/rm -f /dev/$i + mknod /dev/$i c $major $minor + chown root.wheel /dev/$i + chmod 600 /dev/$i + echo -n "$i($minor) " + minor=`expr $minor + 1` +done +echo +echo Done. +echo +exit 0 diff --git a/OpenBSD-3/makedevs-3.1 b/OpenBSD-3/makedevs-3.1 new file mode 100755 index 0000000000000..493fa0a9c97ee --- /dev/null +++ b/OpenBSD-3/makedevs-3.1 @@ -0,0 +1,70 @@ +#!/bin/sh + +platform=`uname -m` + +case $platform in + alpha) + major=44 + ;; + amiga) + major=38 + ;; + hp300) + major=37 + ;; + hppa) + major=34 + ;; + i386) + major=78 + ;; + mac68k) + major=38 + ;; + macppc) + major=45 + ;; + mvme68k) + major=44 + ;; + mvme88k) + major=41 + ;; + mvmeppc) + major=44 + ;; + sparc) + major=60 + ;; + sparc64) + major=82 + ;; + sun3) + major=86 + ;; + vax) + major=47 + ;; + *) + echo "Unrecognised platform $platform" + exit 1 + ;; +esac + +minor=0 +echo +echo "Creating IPFilter device files in /dev." +echo +echo -n "Platform $platform Major Number $major: " +for i in ipl ipnat ipstate ipauth ipsync ipscan iplookup; do + /bin/rm -f /dev/$i + mknod /dev/$i c $major $minor + chown root.wheel /dev/$i + chmod 600 /dev/$i + echo -n "$i($minor) " + minor=`expr $minor + 1` +done +echo +echo Done. +echo +exit 0 diff --git a/OpenBSD-3/makedevs-3.2 b/OpenBSD-3/makedevs-3.2 new file mode 100755 index 0000000000000..9c598d364b895 --- /dev/null +++ b/OpenBSD-3/makedevs-3.2 @@ -0,0 +1,70 @@ +#!/bin/sh + +platform=`uname -m` + +case $platform in + alpha) + major=44 + ;; + amiga) + major=38 + ;; + hp300) + major=37 + ;; + hppa) + major=38 + ;; + i386) + major=81 + ;; + mac68k) + major=38 + ;; + macppc) + major=45 + ;; + mvme68k) + major=44 + ;; + mvme88k) + major=41 + ;; + mvmeppc) + major=44 + ;; + sparc) + major=60 + ;; + sparc64) + major=82 + ;; + sun3) + major=87 + ;; + vax) + major=47 + ;; + *) + echo "Unrecognised platform $platform" + exit 1 + ;; +esac + +minor=0 +echo +echo "Creating IPFilter device files in /dev." +echo +echo -n "Platform $platform Major Number $major: " +for i in ipl ipnat ipstate ipauth ipsync ipscan ippool; do + /bin/rm -f /dev/$i + mknod /dev/$i c $major $minor + chown root.wheel /dev/$i + chmod 600 /dev/$i + echo -n "$i($minor) " + minor=`expr $minor + 1` +done +echo +echo Done. +echo +exit 0 diff --git a/OpenBSD-3/makedevs-3.3 b/OpenBSD-3/makedevs-3.3 new file mode 100755 index 0000000000000..9c598d364b895 --- /dev/null +++ b/OpenBSD-3/makedevs-3.3 @@ -0,0 +1,70 @@ +#!/bin/sh + +platform=`uname -m` + +case $platform in + alpha) + major=44 + ;; + amiga) + major=38 + ;; + hp300) + major=37 + ;; + hppa) + major=38 + ;; + i386) + major=81 + ;; + mac68k) + major=38 + ;; + macppc) + major=45 + ;; + mvme68k) + major=44 + ;; + mvme88k) + major=41 + ;; + mvmeppc) + major=44 + ;; + sparc) + major=60 + ;; + sparc64) + major=82 + ;; + sun3) + major=87 + ;; + vax) + major=47 + ;; + *) + echo "Unrecognised platform $platform" + exit 1 + ;; +esac + +minor=0 +echo +echo "Creating IPFilter device files in /dev." +echo +echo -n "Platform $platform Major Number $major: " +for i in ipl ipnat ipstate ipauth ipsync ipscan ippool; do + /bin/rm -f /dev/$i + mknod /dev/$i c $major $minor + chown root.wheel /dev/$i + chmod 600 /dev/$i + echo -n "$i($minor) " + minor=`expr $minor + 1` +done +echo +echo Done. +echo +exit 0 diff --git a/OpenBSD-3/makedevs-3.4 b/OpenBSD-3/makedevs-3.4 new file mode 100755 index 0000000000000..9c598d364b895 --- /dev/null +++ b/OpenBSD-3/makedevs-3.4 @@ -0,0 +1,70 @@ +#!/bin/sh + +platform=`uname -m` + +case $platform in + alpha) + major=44 + ;; + amiga) + major=38 + ;; + hp300) + major=37 + ;; + hppa) + major=38 + ;; + i386) + major=81 + ;; + mac68k) + major=38 + ;; + macppc) + major=45 + ;; + mvme68k) + major=44 + ;; + mvme88k) + major=41 + ;; + mvmeppc) + major=44 + ;; + sparc) + major=60 + ;; + sparc64) + major=82 + ;; + sun3) + major=87 + ;; + vax) + major=47 + ;; + *) + echo "Unrecognised platform $platform" + exit 1 + ;; +esac + +minor=0 +echo +echo "Creating IPFilter device files in /dev." +echo +echo -n "Platform $platform Major Number $major: " +for i in ipl ipnat ipstate ipauth ipsync ipscan ippool; do + /bin/rm -f /dev/$i + mknod /dev/$i c $major $minor + chown root.wheel /dev/$i + chmod 600 /dev/$i + echo -n "$i($minor) " + minor=`expr $minor + 1` +done +echo +echo Done. +echo +exit 0 diff --git a/OpenBSD-3/makedevs-3.5 b/OpenBSD-3/makedevs-3.5 new file mode 100755 index 0000000000000..e2abdd12cdd7e --- /dev/null +++ b/OpenBSD-3/makedevs-3.5 @@ -0,0 +1,70 @@ +#!/bin/sh + +platform=`uname -m` + +case $platform in + alpha) + major=44 + ;; + amiga) + major=38 + ;; + hp300) + major=37 + ;; + hppa) + major=39 + ;; + i386) + major=82 + ;; + mac68k) + major=38 + ;; + macppc) + major=45 + ;; + mvme68k) + major=45 + ;; + mvme88k) + major=45 + ;; + mvmeppc) + major=44 + ;; + sparc) + major=60 + ;; + sparc64) + major=82 + ;; + sun3) + major=87 + ;; + vax) + major=47 + ;; + *) + echo "Unrecognised platform $platform" + exit 1 + ;; +esac + +minor=0 +echo +echo "Creating IPFilter device files in /dev." +echo +echo -n "Platform $platform Major Number $major: " +for i in ipl ipnat ipstate ipauth ipsync ipscan iplookup; do + /bin/rm -f /dev/$i + mknod /dev/$i c $major $minor + chown root.wheel /dev/$i + chmod 600 /dev/$i + echo -n "$i($minor) " + minor=`expr $minor + 1` +done +echo +echo Done. +echo +exit 0 diff --git a/OpenBSD/files.diffs b/OpenBSD/files.diffs new file mode 100644 index 0000000000000..878f2e0752be3 --- /dev/null +++ b/OpenBSD/files.diffs @@ -0,0 +1,18 @@ +*** files.FCS Thu May 1 06:21:14 1997 +--- files Mon Oct 27 14:08:53 1997 +*************** +*** 299,304 **** +--- 299,311 ---- + file netinet/ip_nat.c ipfilter + file netinet/ip_frag.c ipfilter + file netinet/ip_state.c ipfilter ++ file netinet/ip_proxy.c ipfilter ++ file netinet/ip_auth.c ipfilter ++ file netinet/ip_log.c ipfilter ++ file netinet/ip_scan.c ipfilter ++ file netinet/ip_sync.c ipfilter ++ file netinet/ip_pool.c ipfilter_pool ++ file netinet/ip_rules.c ipfilter_compiled + file netinet/ip_ah.c inet & ipsec + file netinet/ip_esp.c inet & ipsec + file netinet/ip_espdes.c inet & ipsec diff --git a/OpenBSD/kinstall b/OpenBSD/kinstall new file mode 100755 index 0000000000000..9be50d2a4784a --- /dev/null +++ b/OpenBSD/kinstall @@ -0,0 +1,82 @@ +#! /bin/sh +# +# kinstall/minstall - install patches to kernel sources +# +# WARNING: This script should be run exactly once on a virgin system +# +PATH=/sbin:/usr/sbin:/bin:/usr/bin; export PATH + +argv0=`basename $0` +dir=`pwd` +karch=`uname -m` +archdir="/sys/arch/$karch" +confdir="$archdir/conf" + +case "$dir" in +*/OpenBSD ) + cd .. + ;; +esac + +echo -n "Backing up existing kernel sources ..." +backup="" +for i in fil.c ip_fil.[ch] ip_frag.[ch] ip_nat.[ch] ip_state.[ch] ip_fil_compat.h; do + if [ -e /sys/netinet/$i ] ; then + backup="${backup} ${i}" + fi +done +if [ -n "$backup" ] ; then + ( cd /sys/netinet ; tar cf ipfbackup.tar $backup ) +fi +echo + +echo -n "Installing " +for i in ip_fil.[ch] fil.c ip_nat.[ch] ip_frag.[ch] ip_state.[ch] ip_proxy.[ch] ip_auth.[ch] ip_log.c ip_compat.h ipl.h ip_ftp_pxy.c ip_rcmd_pxy.c ip_raudio_pxy.c; do + echo -n "$i " + cp $i /sys/netinet/ + chmod 644 /sys/netinet/$i +done +echo + +if [ -f /sys/conf/files ] ; then + echo "Patching /sys/conf/files ..." + cat OpenBSD/files.diffs | (cd /sys/conf; patch) + ip_files=`egrep '^file.*ipfilter' /sys/conf/files | wc -l` + if [ $ip_files -lt 8 ] ; then + echo "Patching /sys/conf/files ..." + cat OpenBSD/files.diffs | (cd /sys/conf; patch) + fi +fi +if [ -f /sys/netinet/ip_fil_compat.h ] ; then + echo "Linking /sys/netinet/ip_compat.h to /sys/netinet/ip_fil_compat.h" + rm /sys/netinet/ip_fil_compat.h + ln -s /sys/netinet/ip_compat.h /sys/netinet/ip_fil_compat.h +fi + +echo -n "Kernel configuration to update [GENERIC] " +read newconfig junk + +if [ -n "$newconfig" ] ; then + config="$confdir/$newconfig" +else + newconfig="$confdir/GENERIC" +fi + +if egrep 'option.*IPFILTER' $confdir/$newconfig > /dev/null 2>&1 ; then + echo "$newconfig already contains proper options statement..." + echo 'You will now need to build a new kernel.' +else + echo "Backing up $newconfig to .bak and adding IPFILTER options..." + if [ -f $confdir/$newconfig ]; then + mv $confdir/$newconfig $confdir/$newconfig.bak + fi + if [ -d $archdir/compile/$newconfig ]; then + mv $archdir/compile/$newconfig $archdir/compile/$newconfig.bak + fi + awk '{print $0} $2=="INET"{print "options IPFILTER"}' \ + $confdir/$newconfig.bak > $confdir/$newconfig + + echo 'You will now need to run "config" and build a new kernel.' +fi + +exit 0 diff --git a/OpenBSD/mknewipf.sh b/OpenBSD/mknewipf.sh new file mode 100644 index 0000000000000..5a493da752b51 --- /dev/null +++ b/OpenBSD/mknewipf.sh @@ -0,0 +1,21 @@ +#!/bin/sh +# documented from +# http://www.tfsb.org/ipf-openbsd/ +ARCH=sparc +KERNEL=MULAN +IPF=ip-fil3.4.17 +rm -rf $IPF +tar zxf $IPF.tar.gz +cd $IPF +perl -pi -e "s/#STATETOP_CFLAGS=/STATETOP_CFLAGS=/" Makefile +perl -pi -e "s/#STATETOP_INC=$/STATETOP_INC=/" Makefile +perl -pi -e "s/#STATETOP_LIB=-lncurses/STATETOP_LIB=-lcurses/" Makefile +perl -pi -e "s/#INET6/INET6/" Makefile +make openbsd +make install-bsd +cd OpenBSD +echo $KERNEL | ./kinstall >/dev/null 2>&1 +cd /usr/src/sys/arch/$ARCH/conf +config $KERNEL +cd /usr/src/sys/arch/$ARCH/compile/$KERNEL +make clean && make depend && make && mv /bsd /bsd.old && mv bsd /bsd && reboot diff --git a/OpenBSD/patch.1 b/OpenBSD/patch.1 new file mode 100644 index 0000000000000..29d088ac127e6 --- /dev/null +++ b/OpenBSD/patch.1 @@ -0,0 +1,21 @@ +*** net/if_bridge.c.orig Sat Mar 20 07:47:33 1999 +--- net/if_bridge.c Wed Sep 15 22:44:16 1999 +*************** +*** 55,62 **** + #include <netinet/in_var.h> + #include <netinet/ip.h> + #include <netinet/if_ether.h> +! #ifdef IPFILTER +! #include <netinet/ip_fil_compat.h> + #include <netinet/ip_fil.h> + #endif + #endif +--- 55,62 ---- + #include <netinet/in_var.h> + #include <netinet/ip.h> + #include <netinet/if_ether.h> +! #if (defined(IPFILTER) || defined(IPFILTER_LKM)) +! #include <netinet/ip_compat.h> + #include <netinet/ip_fil.h> + #endif + #endif diff --git a/OpenBSD/unkinstall b/OpenBSD/unkinstall new file mode 100644 index 0000000000000..c4f77f7a64411 --- /dev/null +++ b/OpenBSD/unkinstall @@ -0,0 +1,53 @@ +#! /bin/sh +# +# kinstall/minstall - install patches to kernel sources +# +# WARNING: This script should be run exactly once on a virgin system +# +PATH=/sbin:/usr/sbin:/bin:/usr/bin; export PATH + +# try to bomb out fast if anything fails.... +set -e + +argv0=`basename $0` +dir=`pwd` +karch=`uname -m` +archdir="/sys/arch/$karch" +confdir="$archdir/conf" + +case "$dir" in +*/OpenBSD ) + cd .. + ;; +esac + +echo -n "Removing " +for i in ip_fil.[ch] ip_nat.[ch] ip_frag.[ch] ip_state.[ch] fil.c ip_compat.h ip_proxy.[ch] ip_ftp_pxy.c ip_auth.[ch] ip_log.c +do + echo -n "/sys/netinet/$i " + /bin/rm -f /sys/netinet/$i +done +echo + +if [ -f /sys/netinet/ipfbackup.tar ] ; then + echo -n "Restoring old kernel sources" + ( cd /sys/netinet ; tar xpf ipfbackup.tar ) +fi +echo + +echo "Unpatching /sys/conf/files ..." +cat OpenBSD/files.diffs | (cd /sys/conf; patch -R) + +echo -n "Kernel configuration to update [GENERIC] " +read newconfig junk + +if [ -n "$newconfig" ] ; then + config="$confdir/$newconfig" +else + newconfig="$confdir/GENERIC" +fi + +mv $archdir/compile/$newconfig $archdir/compile/$newconfig.bak +egrep -v 'IPFILTER' $confdir/$newconfig.bak > $confdir/$newconfig +echo 'You will now need to run "config" and build a new kernel.' +exit 0 diff --git a/QNX_OCL.txt b/QNX_OCL.txt deleted file mode 100644 index 6aa33eaf6b060..0000000000000 --- a/QNX_OCL.txt +++ /dev/null @@ -1,275 +0,0 @@ - End User License Certificate (EULA) End User License Certificate - (EULA) - Support Support - QNX Source Licenses QNX Source Licenses - License of the month - Confidential Source License - Version 1.0 - -QNX Open Community License Version 1.0 - - THIS QNX OPEN COMMUNITY LICENSE ( "THE OCL", OR "THIS AGREEMENT") - APPLIES TO PROGRAMS THAT QNX SOFTWARE SYSTEMS LTD. ("QSS") EXPRESSLY - ELECTS TO LICENSE UNDER THE OCL TERMS. IT ALSO APPLIES TO DERIVATIVE - WORKS CREATED UNDER THIS AGREEMENT THAT CREATORS ELECT TO LICENSE TO - OTHERS IN SOURCE CODE FORM. ANY USE, REPRODUCTION, MODIFICATION OR - DISTRIBUTION OF SUCH PROGRAMS CONSTITUTES RECIPIENT'S ACCEPTANCE OF - THE OCL. THE LICENSE RIGHTS GRANTED BELOW ARE CONDITIONAL UPON - RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT AND THE FORMATION OF A - BINDING CONTRACT. NOTHING ELSE GRANTS PERMISSION TO USE, REPRODUCE, - MODIFY OR DISTRIBUTE SUCH PROGRAMS OR THEIR DERIVATIVE WORKS. THESE - ACTIONS ARE OTHERWISE PROHIBITED. CONTACT QSS IF OTHER STEPS ARE - REQUIRED LOCALLY TO CREATE A BINDING CONTRACT. - - The OCL is intended to promote the development, use and distribution - of derivative works created from QSS source code. This includes - commercial distribution of object code versions under the terms of - Recipient's own license agreement and, at Recipient's option, sharing - of source code modifications within the QNX developer's community. The - license granted under the OCL is royalty free. Recipient is entitled - to charge royalties for object code versions of derivative works that - originate with Recipient. If Recipient elects to license source code - for its derivative works to others, then it must be licensed under the - OCL. The terms of the OCL are as follows: - -1. DEFINITIONS - - "Contribution" means: - - a. in the case of QSS: (i) the Original Program, where the Original - Program originates from QSS, (ii) changes and/or additions to - Unrestricted Open Source, where the Original Program originates - from Unrestricted Open Source and where such changes and/or - additions originate from QSS, and (iii) changes and/or additions - to the Program where such changes and/or additions originate from - QSS. - b. in the case of each Contributor, changes and/or additions to the - Program, where such changes and/or additions originate from and - are distributed by that particular Contributor. - - A Contribution 'originates' from a Contributor if it was added to the - Program by such Contributor itself or anyone acting on such - Contributor's behalf. Contributions do not include additions to the - Program which: (i) are separate modules of software distributed in - conjunction with the Program under their own license agreement, and - (ii) are not derivative works of the Program. - - "Contributor" means QSS and any other entity that distributes the - Program. - - "Licensed Patents " mean patent claims licensable by Contributor to - others, which are necessarily infringed by the use or sale of its - Contribution alone or when combined with the Program. - - "Unrestricted Open Source" means published source code that is - licensed for free use and distribution under an unrestricted licensing - and distribution model, such as the Berkley Software Design ("BSD") - and "BSD-like" licenses. It specifically excludes any source code - licensed under any version of the GNU General Public License (GPL) or - the GNU Lesser/Library GPL. All "Unrestricted Open Source" license - terms appear or are clearly identified in the header of any affected - source code for the Original Program. - - "Original Program" means the original version of the software - accompanying this Agreement as released by QSS, including source code, - object code and documentation, if any. - - "Program" means the Original Program and Contributions. - - "Recipient" means anyone who receives the Program under this - Agreement, including all Contributors. - -2. GRANT OF RIGHTS - - a. Subject to the terms of this Agreement, each Contributor hereby - grants Recipient a non-exclusive, worldwide, royalty-free - copyright license to reproduce, prepare derivative works of, - publicly display, publicly perform, and directly and indirectly - sublicense and distribute the Contribution of such Contributor, if - any, and such derivative works, in source code and object code - form. - b. Subject to the terms of this Agreement, each Contributor hereby - grants Recipient a non-exclusive, worldwide, royalty-free patent - license under Licensed Patents to make, use, sell, offer to sell, - import and otherwise transfer the Contribution of such - Contributor, if any, in source code and object code form. This - patent license shall apply to the combination of the Contribution - and the Program if, at the time the Contribution is added by the - Contributor, such addition of the Contribution causes such - combination to be covered by the Licensed Patents. The patent - license shall not apply to any other combinations which include - the Contribution. - c. Recipient understands that although each Contributor grants the - licenses to its Contributions set forth herein, no assurances are - provided by any Contributor that the Program does not infringe the - patent or other intellectual property rights of any other entity. - Each Contributor disclaims any liability to Recipient for claims - brought by any other entity based on infringement of intellectual - property rights or otherwise. As a condition to exercising the - rights and licenses granted hereunder, each Recipient hereby - assumes sole responsibility to secure any other intellectual - property rights needed, if any. For example, if a third party - patent license is required to allow Recipient to distribute the - Program, it is Recipient's responsibility to acquire that license - before distributing the Program. - d. Each Contributor represents that to its knowledge it has - sufficient copyright rights in its Contribution, if any, to grant - the copyright license set forth in this Agreement. - - 3. REQUIREMENTS - - A Contributor may choose to distribute the Program in object code form - under its own license agreement, provided that: - - a. it complies with the terms and conditions of this Agreement; and - b. its license agreement: - i. effectively disclaims on behalf of all Contributors all - warranties and conditions, express and implied, including - warranties or conditions of title and non-infringement, and - implied warranties or conditions of merchantability and - fitness for a particular purpose; - ii. effectively excludes on behalf of all Contributors all - liability for damages, including direct, indirect, special, - incidental and consequential damages, such as lost profits; - and - iii. states that any provisions which differ from this Agreement - are offered by that Contributor alone and not by any other - party. - - If the Program is made available in source code form: - - a. it must be made available under this Agreement; and - b. a copy of this Agreement must be included with each copy of the - Program. Each Contributor must include the following in a - conspicuous location in the Program along with any other copyright - or attribution statements required by the terms of any applicable - Unrestricted Open Source license: - Copyright {date here}, QNX Software Systems Ltd. and others. All - Rights Reserved. - - In addition, each Contributor must identify itself as the originator - of its Contribution, if any, in a manner that reasonably allows - subsequent Recipients to identify the originator of the Contribution. - - 4. COMMERCIAL DISTRIBUTION - - Commercial distributors of software may accept certain - responsibilities with respect to end users, business partners and the - like. While this license is intended to facilitate the commercial use - of the Program, the Contributor who includes the Program in a - commercial product offering should do so in a manner which does not - create potential liability for other Contributors. Therefore, if a - Contributor includes the Program in a commercial product offering, - such Contributor ("Commercial Contributor") hereby agrees to defend - and indemnify every other Contributor ("Indemnified Contributor") - against any losses, damages and costs (collectively "Losses") arising - from claims, lawsuits and other legal actions brought by a third party - against the Indemnified Contributor to the extent caused by the acts - or omissions of such Commercial Contributor in connection with its - distribution of the Program in a commercial product offering. The - obligations in this section do not apply to any claims or Losses - relating to any actual or alleged intellectual property infringement. - In order to qualify, an Indemnified Contributor must: a) promptly - notify the Commercial Contributor in writing of such claim, and b) - allow the Commercial Contributor to control, and cooperate with the - Commercial Contributor in, the defense and any related settlement - negotiations. The Indemnified Contributor may participate in any such - claim at its own expense. - - For example, a Contributor might include the Program in a commercial - product offering, Product X. That Contributor is then a Commercial - Contributor. If that Commercial Contributor then makes performance - claims, or offers warranties related to Product X, those performance - claims and warranties are such Commercial Contributor's responsibility - alone. Under this section, the Commercial Contributor would have to - defend claims against the other Contributors related to those - performance claims and warranties, and if a court requires any other - Contributor to pay any damages as a result, the Commercial Contributor - must pay those damages. - - 5. NO WARRANTY - - Recipient acknowledges that there may be errors or bugs in the Program - and that it is imperative that Recipient conduct thorough testing to - identify and correct any problems prior to the productive use or - commercial release of any products that use the Program, and prior to - the release of any modifications, updates or enhancements thereto. - - EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS - PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY - WARRANTIES OR CONDITIONS OF TITLE, NON- INFRINGEMENT, MERCHANTABILITY - OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely - responsible for determining the appropriateness of using and - distributing the Program and assumes all risks associated with its - exercise of rights under this Agreement, including but not limited to - the risks and costs of program errors, compliance with applicable - laws, damage to or loss of data, programs or equipment, and - unavailability or interruption of operations. - - 6. DISCLAIMER OF LIABILITY - - EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR - ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING - WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR - DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - - 7. GENERAL - - If any provision of this Agreement is invalid or unenforceable under - applicable law, it shall not affect the validity or enforceability of - the remainder of the terms of this Agreement, and without further - action by the parties hereto, such provision shall be reformed to the - minimum extent necessary to make such provision valid and enforceable. - - If Recipient institutes patent litigation against a Contributor with - respect to a patent applicable to software (including a cross-claim or - counterclaim in a lawsuit), then any patent licenses granted by that - Contributor to such recipient under this Agreement shall terminate as - of the date such litigation is filed. In addition, If Recipient - institutes patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Program - itself (excluding combinations of the Program with other software or - hardware) infringes such Recipient's patent(s), then such Recipient's - rights granted under Section 2(b) shall terminate as of the date such - litigation is filed. - - All Recipient's rights under this Agreement shall terminate if it - fails to comply with any of the material terms or conditions of this - Agreement and does not cure such failure in a reasonable period of - time after becoming aware of such noncompliance. If all Recipient's - rights under this Agreement terminate, Recipient agrees to cease use - and distribution of the Program as soon as reasonably practicable. - However, Recipient's obligations under this Agreement and any licenses - granted by Recipient relating to the Program shall continue and - survive. - - QSS may publish new versions (including revisions) of this Agreement - from time to time. Each new version of the Agreement will be given a - distinguishing version number. The Program (including Contributions) - may always be distributed subject to the version of the Agreement - under which it was received. In addition, after a new version of the - Agreement is published, Contributor may elect to distribute the - Program (including its Contributions) under the new version. No one - other than QSS has the right to modify this Agreement. Except as - expressly stated in Sections 2(a) and 2(b) above, Recipient receives - no rights or licenses to the intellectual property of any Contributor - under this Agreement, whether expressly, by implication, estoppel or - otherwise. All rights in the Program not expressly granted under this - Agreement are reserved. - - This Agreement is governed by the laws in force in the Province of - Ontario, Canada without regard to the conflict of law provisions - therein. The parties expressly disclaim the provisions of the United - Nations Convention on Contracts for the International Sale of Goods. - No party to this Agreement will bring a legal action under this - Agreement more than one year after the cause of action arose. Each - party waives its rights to a jury trial in any resulting litigation. - - * QNX is a registered trademark of QNX Software Systems Ltd. - - Document Version: ocl1_00 diff --git a/SunOS4/Makefile b/SunOS4/Makefile new file mode 100644 index 0000000000000..bb17d0fd5299c --- /dev/null +++ b/SunOS4/Makefile @@ -0,0 +1,391 @@ +# +# Copyright (C) 2012 by Darren Reed. +# +# See the IPFILTER.LICENCE file for details on licencing. +# +BINDEST=/usr/local/bin +SBINDEST=/sbin +MANDIR=/usr/share/man +CC=/usr/5bin/cc +CFLAGS=-I.. +TOP=.. +# +# For SunOS 4.1.x +# +DCPU=$(shell uname -m) +DCPU:sh=uname -m +DEF=-D$(DCPU) -D__$(DCPU)__ -DINET -DKERNEL -D_KERNEL -Dsun $(CPU) +IPDEF=$(DEF) -DGATEWAY -DDIRECTED_BROADCAST +ATON=-DNEED_INET_ATON +DEBUG=-g +# For the LKM: +LKM=if_ipl.o +LOGFAC=-DLOGFAC=LOG_LOCAL0 +OBJ=. +DEST=. +TOP=.. +# +MFLAGS="BINDEST=$(BINDEST)" "SBINDEST=$(SBINDEST)" "MANDIR=$(MANDIR)" \ + 'CFLAGS=$(CFLAGS) $(SOLARIS2)' "IPFLKM=$(IPFLKM)" "IPFLOG=$(IPFLOG)" \ + "LOGFAC=$(LOGFAC)" "POLICY=$(POLICY)" "SOLARIS2=$(SOLARIS2)" \ + "DEBUG=$(DEBUG)" "DCPU=$(CPU)" "CPUDIR=$(CPUDIR)" \ + "LOOKUP=$(LOOKUP)" "XID=$(XID)" "SYNC=$(SYNC)" "ALLOPTS=$(ALLOPTS)" +LIBS=-L. -lipf +# +########## ########## ########## ########## ########## ########## ########## +# +CP=/bin/cp +RM=/bin/rm +CHMOD=/bin/chmod +INSTALL=install +# +MODOBJS=ip_fil.o fil.o mls_ipl.o ip_nat.o ip_state.o ip_frag.o ip_proxy.o \ + ip_auth.o ip_log.o ip_pool.o ip_htable.o ip_lookup.o ip_scan.o \ + ip_sync.o ip_rules.o \ + radix_ipf.o md5.o +# ip_trafcon.o +DFLAGS=$(IPFLKM) $(IPFLOG) $(DEF) $(LOOKUP) $(XID) $(SYNC) +IPF=ipf.o ipfcomp.o ipf_y.o ipf_l.o +IPFTEST=ipftest.o fil_u.o ip_nat_u.o ip_frag_u.o ip_state_u.o ip_fil_u.o \ + ip_proxy_u.o ip_auth_u.o ip_pool_u.o ip_htable_u.o ip_lookup_u.o \ + ip_scan_u.o ip_sync_u.o ip_rules_u.o ip_log_u.o \ + ippool_y.o ippool_l.o ipf_y.o ipf_l.o ipnat_y.o ipnat_l.o \ + md5_u.o radix_ipf_u.o +# ip_trafcon_u.o +IPNAT=ipnat.o ipnat_y.o ipnat_l.o +IPMON=ipmon.o ipmon_y.o ipmon_l.o +IPPOOL=ippool_y.o ippool_l.o kmem.o ippool.o +IPTRAFCON=iptrafcon.o +IPFSTAT=ipfstat.o +LIBSRC=$(TOP)/lib +TOOL=$(TOP)/tools +RANLIB=ranlib +AROPTS=cq +HERE=SunOS4 +CCARGS=-I. $(DEBUG) $(CFLAGS) +EXTRA=-DIPFILTER_LOG -DIPFILTER_LOOKUP + +include $(TOP)/lib/Makefile + +build all: libipf.a ipf ipfstat ipftest ipmon ipnat ipfs ippool ipscan \ + ipsyncm ipsyncs if_ipl.o + -sh -c 'for i in ipf ipftest ipmon ippool ipnat ipscan ipsyncm ipsyncs; do /bin/rm -f $(TOP)/$$i; ln -s `pwd`/$$i $(TOP); done' + +ipfstat: $(IPFSTAT) libipf.a + $(CC) $(CCARGS) $(STATETOP_CFLAGS) $(STATETOP_INC) $(IPFSTAT) \ + -o $@ $(LIBS) $(STATETOP_LIB) -lkvm + +ipf: $(IPF) libipf.a + $(CC) $(CCARGS) $(IPF) -o $@ $(LIBS) -ll -lkvm $(LIBBPF) + +ipfs: ipfs.o + $(CC) $(CCARGS) ipfs.o -o $@ + +ipsyncm: ipsyncm.o libipf.a + $(CC) $(CCARGS) ipsyncm.o -o $@ $(LIBS) + +ipsyncs: ipsyncs.o libipf.a + $(CC) $(CCARGS) ipsyncs.o -o $@ $(LIBS) + +ipsyncm.o: $(TOOL)/ipsyncm.c $(TOP)/ip_sync.h + $(CC) -DIPFILTER_SYNC $(CCARGS) -c $(TOOL)/ipsyncm.c -o $@ + +ipsyncs.o: $(TOOL)/ipsyncs.c $(TOP)/ip_sync.h + $(CC) -DIPFILTER_SYNC $(CCARGS) -c $(TOOL)/ipsyncs.c -o $@ + +ipftest: $(IPFTEST) libipf.a + $(CC) $(CCARGS) $(IPFTEST) -o $@ $(LIBS) -ll -L. $(LIBBPF) + +ipnat: $(IPNAT) libipf.a + $(CC) $(CCARGS) $(IPNAT) -o $@ $(LIBS) -lkvm -ll + +tests: + (cd test; make ) + +ipfs.o: $(TOOL)/ipfs.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_state.h $(TOP)/ip_nat.h + $(CC) $(CCARGS) -c $(TOOL)/ipfs.c -o $@ + +ipfstat.o: $(TOOL)/ipfstat.c $(TOP)/ip_fil.h $(TOP)/ipf.h + $(CC) $(CCARGS) $(STATETOP_CFLAGS) $(STATETOP_INC) \ + -c $(TOOL)/ipfstat.c -o $@ + +fil_u.o: $(TOP)/fil.c $(TOP)/ip_fil.h $(TOP)/ipf.h + $(CC) $(CCARGS) $(EXTRA) $(IPFBPF) -c $(TOP)/fil.c -o $@ + +fil.o: $(TOP)/fil.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ipl.h + $(CC) $(CCARGS) $(POLICY) $(DFLAGS) $(IPFBPF) -c $(TOP)/fil.c -o $@ + +ipf.o: $(TOOL)/ipf.c $(TOP)/ip_fil.h $(TOP)/ipf.h + $(CC) $(CCARGS) -c $(TOOL)/ipf.c -o $@ + +md5.o: $(TOP)/md5.c $(TOP)/md5.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/md5.c -o $@ + +radix_ipf.o: $(TOP)/radix_ipf.c $(TOP)/radix_ipf.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/radix_ipf.c -o $@ + +bpf_filter_u.o: $(TOP)/bpf_filter.c + $(CC) $(CCARGS) -c $(TOP)/bpf_filter.c -o $@ + +md5_u.o: $(TOP)/md5.c $(TOP)/md5.h + $(CC) $(CCARGS) -c $(TOP)/md5.c -o $@ + +radix_ipf_u.o: $(TOP)/radix_ipf.c $(TOP)/radix_ipf.h + $(CC) $(CCARGS) -c $(TOP)/radix_ipf.c -o $@ + +ipfcomp.o: $(TOOL)/ipfcomp.c $(TOP)/ip_fil.h $(TOP)/ipf.h + $(CC) $(CCARGS) -c $(TOOL)/ipfcomp.c -o $@ + +ipftest.o: $(TOOL)/ipftest.c $(TOP)/ip_fil.h $(TOP)/ipt.h $(TOP)/ipf.h \ + $(TOP)/ip_lookup.h $(TOP)/ip_pool.h $(TOP)/ip_htable.h + $(CC) $(CCARGS) -c $(TOOL)/ipftest.c -o $@ + +ipnat.o: $(TOOL)/ipnat.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_nat.h + $(CC) $(CCARGS) -c $(TOOL)/ipnat.c -o $@ + +if_ipl.o: $(MODOBJS) + ld -r $(MODOBJS) -o $(LKM) + ${RM} -f if_ipl + +ip_nat.o: $(TOP)/ip_nat.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_nat.c -o $@ + +ip_frag.o: $(TOP)/ip_frag.c $(TOP)/ip_frag.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_frag.c -o $@ + +ip_state.o: $(TOP)/ip_state.c $(TOP)/ip_state.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_state.c -o $@ + +ip_scan.o: $(TOP)/ip_scan.c $(TOP)/ip_scan.h $(TOP)/ip_compat.h + $(CC) -DIPFILTER_SCAN $(CCARGS) $(DFLAGS) -c $(TOP)/ip_scan.c -o $@ + +ip_sync.o: $(TOP)/ip_sync.c $(TOP)/ip_sync.h $(TOP)/ip_compat.h + $(CC) -DIPFILTER_SYNC $(CCARGS) $(DFLAGS) -c $(TOP)/ip_sync.c -o $@ + +ip_pool.o: $(TOP)/ip_pool.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(TOP)/ip_pool.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_pool.c -o $@ + +ip_htable.o: $(TOP)/ip_htable.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_htable.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_htable.c -o $@ + +ip_lookup.o: $(TOP)/ip_pool.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_pool.h $(TOP)/ip_htable.h $(TOP)/ip_lookup.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_lookup.c -o $@ + +ip_trafcon.o: $(TOP)/ip_trafcon.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_trafcon.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_trafcon.c -o $@ + +ip_rules.c: ipf $(TOP)/tools/ipfcomp.c $(TOP)/rules/ip_rules + ./ipf -cc -nf $(TOP)/rules/ip_rules + +$(TOP)/ip_rules.h: ip_rules.c + if [ ! -f $(TOP)/ip_rules.h ] ; then \ + /bin/mv -f ip_rules.h $(TOP); \ + else \ + touch $(TOP)/ip_rules.h; \ + fi + +ip_rules.o: ip_rules.c $(TOP)/ip_rules.h + $(CC) -I. $(CFLAGS) $(DFLAGS) -c ip_rules.c -o $@ + +ip_proxy.o: $(TOP)/ip_proxy.c $(TOP)/ip_proxy.h $(TOP)/ip_compat.h \ + $(TOP)/ip_ftp_pxy.c $(TOP)/ip_rcmd_pxy.c $(TOP)/ip_raudio_pxy.c \ + $(TOP)/ip_rpcb_pxy.c $(TOP)/ip_nat.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_proxy.c -o $@ + +ip_auth.o: $(TOP)/ip_auth.c $(TOP)/ip_auth.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_auth.c -o $@ + +ip_nat_u.o: $(TOP)/ip_nat.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_nat.c -o $@ + +ip_frag_u.o: $(TOP)/ip_frag.c $(TOP)/ip_frag.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_frag.c -o $@ + +ip_rules_u.o: ip_rules.c $(TOP)/ip_rules.h $(TOP)/ip_compat.h + $(CC) -DIPFILTER_SCAN $(CCARGS) $(EXTRA) -c ip_rules.c -o $@ + +ip_state_u.o: $(TOP)/ip_state.c $(TOP)/ip_state.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_state.c -o $@ + +ip_scan_u.o: $(TOP)/ip_scan.c $(TOP)/ip_scan.h $(TOP)/ip_compat.h + $(CC) -DIPFILTER_SCAN $(CCARGS) $(EXTRA) -c $(TOP)/ip_scan.c -o $@ + +ip_sync_u.o: $(TOP)/ip_sync.c $(TOP)/ip_sync.h $(TOP)/ip_compat.h + $(CC) -DIPFILTER_SYNC $(CCARGS) $(EXTRA) -c $(TOP)/ip_sync.c -o $@ + +ip_pool_u.o: $(TOP)/ip_pool.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_pool.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_pool.c -o $@ + +ip_htable_u.o: $(TOP)/ip_htable.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_htable.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_htable.c -o $@ + +ip_lookup_u.o: $(TOP)/ip_lookup.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_pool.h $(TOP)/ip_htable.h $(TOP)/ip_lookup.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_lookup.c -o $@ + +ip_trafcon_u.o: $(TOP)/ip_trafcon.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_trafcon.h + $(CC) $(CCARGS) -c $(TOP)/ip_trafcon.c -o $@ + + +ip_proxy_u.o: $(TOP)/ip_proxy.c $(TOP)/ip_proxy.h $(TOP)/ip_compat.h \ + $(TOP)/ip_ftp_pxy.c $(TOP)/ip_rcmd_pxy.c $(TOP)/ip_raudio_pxy.c \ + $(TOP)/ip_rpcb_pxy.c $(TOP)/ip_ipsec_pxy.c $(TOP)/ip_nat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_proxy.c -o $@ + +ip_auth_u.o: $(TOP)/ip_auth.c $(TOP)/ip_auth.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_auth.c -o $@ + +ip_log_u.o: $(TOP)/ip_log.c $(TOP)/ip_fil.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_log.c -o $@ + +ip_fil.o: $(TOP)/ip_fil_sunos4.c $(TOP)/ip_fil.h $(TOP)/ip_compat.h \ + $(TOP)/ip_nat.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_fil_sunos4.c -o $@ + +ip_log.o: $(TOP)/ip_log.c $(TOP)/ip_fil.h $(TOP)/ip_compat.h $(TOP)/ip_nat.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_log.c -o $@ + +ip_fil_u.o: $(TOP)/ip_fil.c $(TOP)/ip_fil.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_fil.c -o $@ + +ip_input.o: $(TOP)/ip_input.c $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(IPDEF) -c $(TOP)/ip_input.c -o $@ + +ip_output.o: $(TOP)/ip_output.c $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(IPDEF) -c $(TOP)/ip_output.c -o $@ + +mls_ipl.o: $(TOP)/mls_ipl.c $(TOP)/ipl.h + -/bin/rm -f $(TOP)/vnode_if.c + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/mls_ipl.c -o $@ + +ipf_y.o: ipf_y.c ipf_y.h $(TOP)/ipf.h ipf_l.h + $(CC) $(CCARGS) $(IPFBPF) -c ipf_y.c -o $@ + +ipf_l.o: ipf_l.c ipf_y.h $(TOP)/ipf.h + $(CC) $(CCARGS) -I. -I$(TOP)/tools -c ipf_l.c -o $@ + +ipf_y.h ipf_y.c: $(TOOL)/ipf_y.y $(TOP)/ipf.h + (cd $(TOOL); make "DEST=$(TOP)/$(HERE)" $(TOP)/$(HERE)/$@) + +ipf_l.c: $(TOOL)/lexer.c $(TOP)/ipf.h + (cd $(TOOL); make "DEST=$(TOP)/$(HERE)" $(TOP)/$(HERE)/$@) + +ipf_l.h: $(TOOL)/lexer.h + (cd $(TOOL); make "DEST=$(TOP)/$(HERE)" $(TOP)/$(HERE)/$@); + +ipmon: $(IPMON) libipf.a + $(CC) $(CCARGS) $(IPMON) -o $@ $(LIBS) -ll + +ipmon.o: $(TOOL)/ipmon.c $(TOP)/ipmon.h $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(LOGFAC) -c $(TOOL)/ipmon.c -o $@ + +ipmon_y.o: ipmon_y.c ipmon_y.h $(TOP)/ipmon.h ipmon_l.h + $(CC) $(CCARGS) -c ipmon_y.c -o $@ + +ipmon_l.o: ipmon_l.c ipmon_y.h $(TOP)/ipmon.h ipmon_l.h + $(CC) $(CCARGS) -I. -I$(TOP)/tools -c ipmon_l.c -o $@ + +ipmon_y.h ipmon_y.c: $(TOOL)/ipmon_y.y $(TOP)/ipmon.h + (cd $(TOOL); make "DEST=$(TOP)/$(HERE)" $(TOP)/$(HERE)/$@) + +ipmon_l.c: $(TOOL)/lexer.c $(TOP)/ipmon.h + (cd $(TOOL); make "DEST=$(TOP)/$(HERE)" $(TOP)/$(HERE)/$@) + +ipmon_l.h: $(TOOL)/lexer.h + (cd $(TOOL); make "DEST=$(TOP)/$(HERE)" $(TOP)/$(HERE)/$@) + +ipscan: ipscan_y.o ipscan_l.o + $(CC) $(DEBUG) ipscan_y.o ipscan_l.o -o $@ -ll $(LIBS) -lkvm + +ipscan_y.o: ipscan_y.c ipscan_y.h $(TOP)/ip_scan.h ipscan_l.h + $(CC) -DIPFILTER_SCAN $(CCARGS) -c ipscan_y.c -o $@ + +ipscan_l.o: ipscan_l.c ipscan_y.h $(TOP)/ip_scan.h ipscan_l.h + $(CC) -DIPFILTER_SCAN $(CCARGS) -I. -I$(TOP)/tools -c ipscan_l.c -o $@ + +ipscan_y.h ipscan_y.c: $(TOOL)/ipscan_y.y $(TOP)/ip_scan.h + (cd $(TOOL); make "DEST=$(TOP)/$(HERE)" ) + +ipscan_l.c: $(TOOL)/lexer.c $(TOP)/ip_scan.h + (cd $(TOOL); make "DEST=$(TOP)/$(HERE)" $(TOP)/$(HERE)/$@) + +ipscan_l.h: $(TOOL)/lexer.h + (cd $(TOOL); make "DEST=$(TOP)/$(HERE)" $(TOP)/$(HERE)/$@) + +ippool: $(IPPOOL) libipf.a + $(CC) $(DEBUG) -I. $(CFLAGS) $(IPPOOL) -o $@ -ll -lkvm $(LIBS) + +ippool.o: $(TOOL)/ippool.c $(TOP)/ip_pool.h + $(CC) $(CCARGS) -c $(TOOL)/ippool.c -o $@ + +ippool_y.o: ippool_y.c ippool_y.h $(TOP)/ip_pool.h ippool_l.h + $(CC) $(CCARGS) -c ippool_y.c -o $@ + +ippool_l.o: ippool_l.c ippool_y.h $(TOP)/ip_pool.h + $(CC) $(CCARGS) -I. -I$(TOP)/tools -c ippool_l.c -o $@ + +ippool_y.h ippool_y.c: $(TOOL)/ippool_y.y $(TOP)/ip_pool.h + (cd $(TOOL); make "DEST=$(TOP)/$(HERE)" $(TOP)/$(HERE)/$@) + +ippool_l.c: $(TOOL)/lexer.c $(TOP)/ip_pool.h + (cd $(TOOL); make "DEST=$(TOP)/$(HERE)" $(TOP)/$(HERE)/$@) + +ippool_l.h: $(TOOL)/lexer.h + (cd $(TOOL); make "DEST=$(TOP)/$(HERE)" $(TOP)/$(HERE)/$@) + +ipnat_y.o: ipnat_y.c ipnat_y.h $(TOP)/ip_nat.h ipnat_l.h + $(CC) $(CCARGS) -c ipnat_y.c -o $@ + +ipnat_l.o: ipnat_l.c ipnat_y.h $(TOP)/ip_nat.h ipnat_l.h + $(CC) $(CCARGS) -I. -I$(TOP)/tools -c ipnat_l.c -o $@ + +ipnat_y.h ipnat_y.c: $(TOOL)/ipnat_y.y $(TOP)/ip_nat.h + (cd $(TOOL); make "DEST=$(TOP)/$(HERE)" $(TOP)/$(HERE)/$@) + +ipnat_l.c: $(TOOL)/lexer.c $(TOP)/ip_nat.h + (cd $(TOOL); make "DEST=$(TOP)/$(HERE)" $(TOP)/$(HERE)/$@) + +ipnat_l.h: $(TOOL)/lexer.h + (cd $(TOOL); make "DEST=$(TOP)/$(HERE)" $(TOP)/$(HERE)/$@); + +iptrafcon.o: $(TOP)/iptrafcon.c + $(CC) $(CCARGS) -c $(TOP)/iptrafcon.c -o $@ + +iptrafcon: $(IPTRAFCON) $(OBJ)/libipf.a + $(CC) $(CCARGS) $(IPTRAFCON) -o $@ $(LIBS) + +.y.c: + +.l.c: + +clean: + ${RM} -f ../ipf ../ipnat ../ipmon ../ippool ../ipftest + ${RM} -f ../ipscan ../ipsyncm ../ipsyncs + ${RM} -f core *.o *.a ipt ipfstat ipf ipfstat ipftest ipmon + ${RM} -f if_ipl ipnat $(LKM) + ${RM} -f ip_fil.c ipf_l.c ipf_y.c ipf_y.h ipf_l.h + ${RM} -f ipscan ipscan_y.c ipscan_y.h ipscan_l.c ipscan_l.h + ${RM} -f ippool ippool_y.c ippool_y.h ippool_l.c ippool_l.h + ${RM} -f ipnat_y.c ipnat_y.h ipnat_l.c ipnat_l.h + ${RM} -f ipmon_y.c ipmon_y.h ipmon_l.c ipmon_l.h + ${RM} -f ipsyncm ipsyncs ipfs ip_rules.c ip_rules.h + ${MAKE} TOP=.. -f Makefile.ipsend clean + + +install: all $(TOP)/ip_fil.h + -$(CP) $(TOP)/ip_fil.h /usr/include/netinet/ip_fil.h + -$(CHMOD) 444 /usr/include/netinet/ip_fil.h + -$(INSTALL) -cs -g wheel -m 755 -o root ipf $(SBINDEST) + -$(INSTALL) -cs -g wheel -m 755 -o root ipfs $(SBINDEST) + -$(INSTALL) -cs -g wheel -m 755 -o root ipnat $(SBINDEST) + -$(INSTALL) -cs -g wheel -m 755 -o root ipftest $(BINDEST) + -$(INSTALL) -cs -g wheel -m 755 -o root ipfstat $(SBINDEST) + -$(INSTALL) -cs -g wheel -m 755 -o root ipmon $(BINDEST) + -$(INSTALL) -cs -g wheel -m 755 -o root ipscan $(BINDEST) + (cd $(TOP)/man; make INSTALL=$(INSTALL) MANDIR=$(MANDIR) install; cd ..) diff --git a/SunOS4/Makefile.ipsend b/SunOS4/Makefile.ipsend new file mode 100644 index 0000000000000..dff4eb65b5c65 --- /dev/null +++ b/SunOS4/Makefile.ipsend @@ -0,0 +1,77 @@ +MFLAGS="BINDEST=$(BINDEST)" "SBINDEST=$(SBINDEST)" "MANDIR=$(MANDIR)" \ + "CC=$(CC)" "CFLAGS=$(CFLAGS)" "DEBUG=$(DEBUG)" \ + "IPFLKM=$(IPFLKM)" "IPFLOG=$(IPFLOG)" "LOOKUP=$(LOOKUP)" \ + "LOGFAC=$(LOGFAC)" "POLICY=$(POLICY)" + +OBJS=ipsend.o ip.o ipsopt.o iplang_y.o iplang_l.o +ROBJS=ipresend.o ip.o resend.o +TOBJS=iptest.o iptests.o ip.o +BPF=sbpf.o +UNIXOBJS=snit.o sock.o arp.o +OBJ=. +DEST=. +LIBSRC=../lib +LIBS=-L$(OBJ) -lipf + +CC=/usr/5bin/cc +CFLAGS=-g -I.. + +include $(TOP)/lib/Makefile + +all nit build sunos4 sunos4-nit : libipf.a ipsend ipresend iptest + +iplang_y.o: $(TOP)/iplang/iplang_y.y + (cd $(TOP)/iplang; $(MAKE) 'DESTDIR=../SunOS4' ) + +iplang_l.o: $(TOP)/iplang/iplang_l.l + (cd $(TOP)/iplang; $(MAKE) 'DESTDIR=../SunOS4' ) + +.c.o: + $(CC) $(DEBUG) $(CFLAGS) -c ../ipsend/$< -o $@ + +ipsend: $(OBJS) $(UNIXOBJS) + $(CC) $(DEBUG) $(OBJS) $(UNIXOBJS) -o $@ $(LIBS) -ll + +ipresend: $(ROBJS) $(UNIXOBJS) + $(CC) $(DEBUG) $(ROBJS) $(UNIXOBJS) -o $@ $(LIBS) + +iptest: $(TOBJS) $(UNIXOBJS) + $(CC) $(DEBUG) $(TOBJS) $(UNIXOBJS) -o $@ $(LIBS) + +clean: + rm -rf *.o core a.out ipsend ipresend iptest iplang_l.* iplang_y.* + +ipsend.o: ../ipsend/ipsend.c + $(CC) $(DEBUG) $(CFLAGS) -c ../ipsend/ipsend.c -o $@ +ipsopt.o: ../ipsend/ipsopt.c + $(CC) $(DEBUG) $(CFLAGS) -c ../ipsend/ipsopt.c -o $@ +ipresend.o: ../ipsend/ipresend.c + $(CC) $(DEBUG) $(CFLAGS) -c ../ipsend/ipresend.c -o $@ +ip.o: ../ipsend/ip.c + $(CC) $(DEBUG) $(CFLAGS) -c ../ipsend/ip.c -o $@ +resend.o: ../ipsend/resend.c + $(CC) $(DEBUG) $(CFLAGS) -c ../ipsend/resend.c -o $@ +iptest.o: ../ipsend/iptest.c + $(CC) $(DEBUG) $(CFLAGS) -c ../ipsend/iptest.c -o $@ +iptests.o: ../ipsend/iptests.c + $(CC) $(DEBUG) $(CFLAGS) -c ../ipsend/iptests.c -o $@ +sbpf.o: ../ipsend/sbpf.c + $(CC) $(DEBUG) $(CFLAGS) -c ../ipsend/sbpf.c -o $@ +snit.o: ../ipsend/snit.c + $(CC) $(DEBUG) $(CFLAGS) -c ../ipsend/snit.c -o $@ +sock.o: ../ipsend/sock.c + $(CC) $(DEBUG) $(CFLAGS) -c ../ipsend/sock.c -o $@ +arp.o: ../ipsend/arp.c + $(CC) $(DEBUG) $(CFLAGS) -c ../ipsend/arp.c -o $@ +44arp.o: ../ipsend/44arp.c + $(CC) $(DEBUG) $(CFLAGS) -c ../ipsend/44arp.c -o $@ +lsock.o: ../ipsend/lsock.c + $(CC) $(DEBUG) $(CFLAGS) -c ../ipsend/lsock.c -o $@ +slinux.o: ../ipsend/slinux.c + $(CC) $(DEBUG) $(CFLAGS) -c ../ipsend/slinux.c -o $@ +larp.o: ../ipsend/larp.c + $(CC) $(DEBUG) $(CFLAGS) -c ../ipsend/larp.c -o $@ +dlcommon.o: ../ipsend/dlcommon.c + $(CC) $(DEBUG) $(CFLAGS) -c ../ipsend/dlcommon.c -o $@ +sdlpi.o: ../ipsend/sdlpi.c + $(CC) $(DEBUG) $(CFLAGS) -c ../ipsend/sdlpi.c -o $@ diff --git a/SunOS4/conf.c.diff b/SunOS4/conf.c.diff new file mode 100644 index 0000000000000..a120ed409f1fc --- /dev/null +++ b/SunOS4/conf.c.diff @@ -0,0 +1,45 @@ +*** conf.c.orig Thu Oct 7 10:16:27 1993 +--- conf.c Tue Aug 8 11:53:10 1995 +*************** +*** 823,828 **** +--- 823,843 ---- + #define lightpentab 0 + #endif + ++ #ifdef IPFILTER ++ # ifdef IPFILTER_LOG ++ extern int iplopen(), iplclose(), iplread(), iplioctl(); ++ # else ++ extern int iplopen(), iplclose(), iplioctl(); ++ # define iplread vd_unuseddev ++ # endif ++ #else ++ #define iplopen vd_unuseddev ++ #define iplclose vd_unuseddev ++ #define iplread vd_unuseddev ++ #define iplioctl vd_unuseddev ++ #endif ++ ++ + extern int seltrue(); + + struct cdevsw cdevsw[] = +*************** +*** 1123,1130 **** + 0, 0, + }, + { +! vd_unuseddev, vd_unuseddev, vd_unuseddev, vd_unuseddev, /*59*/ +! vd_unuseddev, vd_unuseddev, vd_unuseddev, 0, + 0, 0, + }, + { +--- 1138,1145 ---- + 0, 0, + }, + { +! iplopen, iplclose, iplread, nulldev, /*59*/ +! iplioctl, nulldev, nulldev, 0, + 0, 0, + }, + { diff --git a/SunOS4/files.cmn.diff b/SunOS4/files.cmn.diff new file mode 100644 index 0000000000000..be9e5b373a601 --- /dev/null +++ b/SunOS4/files.cmn.diff @@ -0,0 +1,25 @@ +*** files.cmn.orig Sun Apr 23 18:34:17 1995 +--- files.cmn Sun Apr 23 18:34:08 1995 +*************** +*** 59,64 **** +--- 59,78 ---- + netinet/tcp_timer.c optional INET + netinet/tcp_usrreq.c optional INET + netinet/udp_usrreq.c optional INET ++ netinet/ip_fil.c optional INET IPFILTER ++ netinet/fil.c optional INET IPFILTER ++ netinet/ip_nat.c optional INET IPFILTER ++ netinet/ip_frag.c optional INET IPFILTER ++ netinet/ip_state.c optional INET IPFILTER ++ netinet/ip_proxy.c optional INET IPFILTER ++ netinet/ip_auth.c optional INET IPFILTER ++ netinet/ip_log.c optional INET IPFILTER IPFILTER_LOG ++ netinet/ip_scan.c optional INET IPFILTER IPFILTER_SCAN ++ netinet/ip_sync.c optional INET IPFILTER IPFILTER_SYNC ++ netinet/ip_pool.c optional INET IPFILTER ++ netinet/ip_htable.c optional INET IPFILTER ++ netinet/ip_lookup.c optional INET IPFILTER ++ netinet/ip_rules.c optional INET IPFILTER IPFILTER_COMPILED + netns/idp_usrreq.c optional xns + netns/ns_error.c optional xns + netns/ns_ether.c optional xns diff --git a/SunOS4/in_proto.c.diffs b/SunOS4/in_proto.c.diffs new file mode 100644 index 0000000000000..c1e9a64f383e9 --- /dev/null +++ b/SunOS4/in_proto.c.diffs @@ -0,0 +1,16 @@ +*** in_proto.c.prog Fri Oct 14 06:23:23 1994 +--- in_proto.c Mon Mar 11 22:45:29 1996 +*************** +*** 41,46 **** +--- 41,51 ---- + int idpip_input(), nsip_ctlinput(); + #endif + ++ #ifdef IPFILTER ++ extern int iplinit(); ++ #define ip_init iplinit ++ #endif ++ + extern struct domain inetdomain; + + struct protosw inetsw[] = { diff --git a/SunOS4/kinstall b/SunOS4/kinstall new file mode 100755 index 0000000000000..f1b096fc4c567 --- /dev/null +++ b/SunOS4/kinstall @@ -0,0 +1,60 @@ +#!/bin/csh -f +# +set dir=`pwd` +if ($dir =~ */SunOS4) cd .. +echo -n "Installing " +foreach i (ip_fil.h ip_nat.[ch] ip_frag.[ch] ip_state.[ch] ip_auth.[ch] \ + ip_proxy.[ch] ip_sync.[ch] ip_scan.[ch] ip_pool.[ch] ip_*_pxy.c \ + ip_lookup.[ch] ip_htable.[ch] fil.c ip_compat.h ip_log.c ipl.h) + echo -n "$i " + cp $i /sys/netinet + chmod 644 /sys/netinet/$i + switch ($i) + case *.h: + /bin/cp $i /usr/include/netinet/$i + chmod 644 /usr/include/netinet/$i + breaksw + endsw +end +cp ip_fil_sunos4.c /sys/netinet/ip_fil.c +chmod 644 /sys/netinet/ip_fil.c +echo "ip_fil.c(ip_fil_sunos4.c)"; + +echo "Installing ip_input.c and ip_output.c" +cp SunOS4/{ip_input.c,ip_output.c} /sys/netinet +chmod 644 /sys/netinet/{ip_input.c,ip_output.c} + +echo "Patching /sys/sun/conf.c" +cat SunOS4/conf.c.diff | (cd /sys/sun; patch) +echo "Patching /sys/conf.common/files.cmn" +cat SunOS4/files.cmn.diff | (cd /sys/conf.common; patch) +echo "Patching /sys/netinet/in_proto.c" +cat SunOS4/in_proto.c.diffs | (cd /sys/netinet; patch) + +set karch=`/bin/arch -k` +set confdir="/sys/$karch/conf" +set config=`/bin/ls -1t $confdir | head -1` + +echo -n "Kernel configuration to update [$config] " +set newconfig=$< +if ( "$newconfig" == "" ) then + set newconfig=$config +endif +echo "Updating $newconfig..." +if ( -d /sys/$karch/$newconfig ) then + mv /sys/$karch/$newconfig /sys/$karch/$newconfig.bak +endif +mv $confdir/$newconfig $confdir/$newconfig.bak +awk '{print $0;if($2=="INET"){print"options IPFILTER\noptions IPFILTER_LOG"}}' \ + $confdir/$newconfig.bak > $confdir/$newconfig +echo "Running config $newconfig" +cd $confdir +config $newconfig +echo "Building a new kernel" +cd ../$newconfig +make +if ($status == 0) then + echo "New kernel is: /sys/$karch/$newconfig/vmunix" + ls -ls /sys/$karch/$newconfig/vmunix +endif +exit 0 diff --git a/SunOS4/minstall b/SunOS4/minstall new file mode 100755 index 0000000000000..073091bdb1510 --- /dev/null +++ b/SunOS4/minstall @@ -0,0 +1,35 @@ +#!/bin/csh -f +# +set dir=`pwd` +if ($dir =~ */SunOS4) cd .. +echo "Installing ip_input.c and ip_output.c" +cp SunOS4/{ip_input.c,ip_output.c} /sys/netinet +chmod 644 /sys/netinet/{ip_input.c,ip_output.c} + +set karch=`/bin/arch -k` +set confdir="/sys/$karch/conf" +set config=`/bin/ls -1t $confdir | head -1` + +echo -n "Kernel configuration to update [$config] " +set newconfig=$< +if ( "$newconfig" == "" ) then + set newconfig=$config +endif +echo "Updating $newconfig..." +if ( -d /sys/$karch/$newconfig ) then + mv /sys/$karch/$newconfig /sys/$karch/$newconfig.bak +endif +mv $confdir/$newconfig $confdir/$newconfig.bak +awk '{print $0;if($2=="INET"){print"options IPFILTER_LKM"}}' \ + $confdir/$newconfig.bak > $confdir/$newconfig +echo "Running config $newconfig" +cd $confdir +config $newconfig +echo "Building a new kernel" +cd ../$newconfig +make +if ($status == 0) then + echo "New kernel is: /sys/$karch/$newconfig/vmunix" + ls -ls /sys/$karch/$newconfig/vmunix +endif +exit 0 diff --git a/SunOS4/mkroutes b/SunOS4/mkroutes new file mode 100755 index 0000000000000..bdcf25800e229 --- /dev/null +++ b/SunOS4/mkroutes @@ -0,0 +1,35 @@ +#!/usr/local/bin/perl +# for best results, bring up all your interfaces before running this +open(I, "ifconfig -a|") || die $!; +while (<I>) { + chop; + if (/^[a-zA-Z]+\d+:/) { + ($iface = $_) =~ s/^([a-zA-Z]+\d+).*/$1/; + $ifaces{$iface} = $iface; + next; + } + if (/inet/) { + if (/\-\-\>/) { # PPP, (SLIP?) + ($inet{$iface} = $_) =~ s/.*inet ([^ ]+) \-\-\> ([^ ]+).*/$1/; + ($ppp{$iface} = $_) =~ s/.*inet ([^ ]+) \-\-\> ([^ ]+).*/$2/; + } else { + ($inet{$iface} = $_) =~ s/.*inet ([^ ]+).*/$1/; + } + } + if (/netmask/) { + ($mask = $_) =~ s/.*netmask ([^ ]+).*/$1/; + $mask =~ s/^/0x/ if ($mask =~ /^[0-9a-f]*$/); + $netmask{$iface} = $mask; + } + if (/broadcast/) { + ($bcast{$iface} = $_) =~ s/.*broadcast ([^ ]+).*/$1/; + } +} +foreach $i (keys %ifaces) { + $net{$i} = $inet{$i}."/".$netmask{$i} if (defined($inet{$i})); +} +foreach $i (keys %ifaces) { + next if (($i =~ /lo/) || !defined($net{$i})); +# 8/25/97; removed || defined($ppp{$i}) + system("route add $inet{$i} localhost 0"); +} diff --git a/SunOS4/rc.ipf b/SunOS4/rc.ipf new file mode 100755 index 0000000000000..cc8d856b5dee1 --- /dev/null +++ b/SunOS4/rc.ipf @@ -0,0 +1,41 @@ +#!/bin/sh +# $Id$ + +cd /usr/local/ip_fil || exit 1 + +umask 022 + +#SYM='-sym' + +if /usr/etc/modstat | grep -s 'IP Filter'; then + echo ip filter module already loaded +else + if [ ! -f if_ipl.o ]; then + echo missing if_ipl.o + exit 1 + fi + if modload $SYM if_ipl.o; then + echo loaded if_ipl + else + echo if_ipl load failed + exit 1 + fi + + echo starting ipmon + # syslog any logged packets + /usr/local/bin/ipmon -s & +fi + +# allow me to run ipfstat as myself (i'm in group kmem) +chmod 640 /dev/ipl /dev/ipauth /dev/ipnat /dev/ipstate +chgrp kmem /dev/ipl /dev/ipauth /dev/ipnat /dev/ipstate + +# create loopback routes for all interface addrs +echo adding loopback routes +./mkroutes + +echo loading filters +./reload + +# pass reload status: +exit $? diff --git a/SunOS4/reload b/SunOS4/reload new file mode 100755 index 0000000000000..e7d9c1f854ded --- /dev/null +++ b/SunOS4/reload @@ -0,0 +1,21 @@ +#!/bin/sh +# $Id$ + +DIR=/usr/local/ip_fil + +if [ -f $DIR/mkroutes ]; then + $DIR/mkroutes >/dev/null 2>&1 +fi + +#LOG=none +LOG=nomatch + +# perform changes to inactive filter set +# clear all filters +# load filters +# select log flags +# swap filter sets +/usr/local/etc/ipf -I -Fa -f $DIR/filters -l $LOG -s + +# load ip translations +/usr/local/etc/ipnat -Cf $DIR/trans diff --git a/SunOS4/unkinstall b/SunOS4/unkinstall new file mode 100755 index 0000000000000..336ae38651daa --- /dev/null +++ b/SunOS4/unkinstall @@ -0,0 +1,47 @@ +#!/bin/csh -f +# +set dir=`pwd` +if ($dir =~ */SunOS4) cd .. +echo -n "Uninstalling " +foreach i (ip_fil.[ch] ip_nat.[ch] ip_frag.[ch] ip_state.[ch] ip_auth.[ch] \ + ip_proxy.[ch] ip_sync.[ch] ip_scan.[ch] ip_pool.[ch] ip_*_pxy.c \ + ip_lookup.[ch] ip_htable.[ch] fil.c ip_compat.h ip_log.c ipl.h) + echo -n "$i " + /bin/rm /sys/netinet/$i +end +echo "Uninstalling ip_input.c and ip_output.c" +/bin/rm /sys/netinet/{ip_input.c,ip_output.c} + +echo "Unpatching /sys/sun/conf.c" +cat SunOS4/conf.c.diff | (cd /sys/sun; patch -R) +echo "Unpatching /sys/conf.common/files.cmn" +cat SunOS4/files.cmn.diff | (cd /sys/conf.common; patch -R) +echo "Unpatching /sys/netinet/in_proto.c" +cat SunOS4/in_proto.c.diffs | (cd /sys/netinet; patch -R) + +set karch=`/bin/arch -k` +set confdir="/sys/$karch/conf" +set config=`/bin/ls -1t $confdir | head -1` + +echo -n "Kernel configuration to update [$config] " +set newconfig=$< +if ( "$newconfig" == "" ) then + set newconfig=$config +endif +echo "Updating $newconfig..." +if ( -d /sys/$karch/$newconfig ) then + mv /sys/$karch/$newconfig /sys/$karch/$newconfig.bak +endif +mv $confdir/$newconfig $confdir/$newconfig.bak +egrep -v 'options.*IPFILTER' $confdir/$newconfig.bak > $confdir/$newconfig +echo "Running config $newconfig" +cd $confdir +config $newconfig +echo "Building a new kernel" +cd ../$newconfig +make +if ($status == 0) then + echo "New kernel is: /sys/$karch/$newconfig/vmunix" + ls -ls /sys/$karch/$newconfig/vmunix +endif +exit 0 diff --git a/SunOS4/unminstall b/SunOS4/unminstall new file mode 100755 index 0000000000000..f800ca1e0ca58 --- /dev/null +++ b/SunOS4/unminstall @@ -0,0 +1,33 @@ +#!/bin/csh -f +# +set dir=`pwd` +if ($dir =~ */SunOS4) cd .. +echo "De-installing ip_input.c and ip_output.c" +/bin/rm -f /sys/netinet/{ip_input.c,ip_output.c} + +set karch=`/bin/arch -k` +set confdir="/sys/$karch/conf" +set config=`/bin/ls -1t $confdir | head -1` + +echo -n "Kernel configuration to update [$config] " +set newconfig=$< +if ( "$newconfig" == "" ) then + set newconfig=$config +endif +echo "Updating $newconfig..." +if ( -d /sys/$karch/$newconfig ) then + mv /sys/$karch/$newconfig /sys/$karch/$newconfig.bak +endif +mv $confdir/$newconfig $confdir/$newconfig.bak +egrep -v 'options.*IPFILTER' $confdir/$newconfig.bak > $confdir/$newconfig +echo "Running config $newconfig" +cd $confdir +config $newconfig +echo "Building a new kernel" +cd ../$newconfig +make +if ($status == 0) then + echo "New kernel is: /sys/$karch/$newconfig/vmunix" + ls -ls /sys/$karch/$newconfig/vmunix +endif +exit 0 diff --git a/SunOS5/Makefile b/SunOS5/Makefile new file mode 100644 index 0000000000000..3989d8b12b4fc --- /dev/null +++ b/SunOS5/Makefile @@ -0,0 +1,617 @@ +# +# Copyright (C) 2012 by Darren Reed. +# +# See the IPFILTER.LICENCE file for details on licencing. +# +TOP=$(shell echo `pwd`/..) +TOP:sh=echo `pwd`/.. +BINDEST=/usr/local/bin +SBINDEST=/sbin/$(OBJ) +MANDIR=/usr/share/man +CC=cc +CFLAGS=-I$(TOP) +# +# For SunOS 5.x +# +CPUDIR=$(shell echo `uname -p`-`uname -r`) +CPUDIR:sh=echo `uname -p`-`uname -r` +ROOT=$(CPUDIR)/root +PKGDIR=$(ROOT)/opt/ipf +PKGMAN=$(PKGDIR)/man +PKGBIN=$(PKGDIR)/bin/$(OBJ) +#CTFCONVERT=ctfconvert -i -l IPF +CTFCONVERT=echo +#CTFMERGE=ctfmerge -l IPF -o +CTFMERGE=echo +# +DEST=$(OBJ) +TOOL=$(TOP)/tools +#CPU=$(shell uname -p) +#REV=$(shell uname -v) +#CPU:sh=uname -p +#REV:sh=uname -r +HERE=SunOS5/$(CPUDIR) +BITS=$(shell if optisa amd64 sparcv9 >/dev/null 2>&1; then echo "64"; else echo "32"; fi) +BITS:sh=if optisa amd64 sparcv9 >/dev/null 2>&1; then echo "64"; else echo "32"; fi +ARCH=$(shell uname -p) +ARCH:sh=uname -p + +OBJ32_i386=i86 +OBJ64_i386=amd64 +OBJ32_sparc=sparcv7 +OBJ64_sparc=sparcv9 +OBJ32=$(OBJ32_$(ARCH)) +OBJ64=$(OBJ64_$(ARCH)) + +PROTO32_i386=prototype_ia32 +PROTO64_i386=prototype_amd64 +PROTO32_sparc=prototype32 +PROTO64_sparc=prototype64 +PROTO32=$(PROTO32_$(ARCH)) +PROTO64=$(PROTO64_$(ARCH)) + +CC=gcc -Wall +DEBUG=-g +LIBS=-lsocket -lnsl -lelf -L$(OBJ) -lipf $(LIBBPF) +DEF=-I$(TOP)/../pfil -D_KERNEL -DSUNDDI $(IPFBPF) $(INSTANCE) -gdwarf-2 +OBJ=. +PKG=ipf +PROTO=prototype +BITTYPE=`if [ "$(BITS)" = 64 ];then echo ' (64-bit)'; fi` +OBJDIR=$(CPUDIR)/$(OBJ) +TMP=/tmp/ipfpkgs +ATON=-DNEED_INET_ATON +ROOTINC=$(ROOT)/usr/include +# +MFLAGS="BINDEST=$(BINDEST)" "SBINDEST=$(SBINDEST)" "MANDIR=$(MANDIR)" \ + 'CFLAGS=$(CFLAGS) $(ARCHINC) $(SOLARIS2)' "IPFLKM=$(IPFLKM)" \ + "IPFLOG=$(IPFLOG)" "LOGFAC=$(LOGFAC)" "POLICY=$(POLICY)" \ + "SOLARIS2=$(SOLARIS2)" "DEBUG=$(DEBUG)" "CPUDIR=$(CPUDIR)" \ + "BITS=$(BITS)" "OBJ=$(OBJ)" "LOOKUP=$(LOOKUP)" "SYNC=$(SYNC)" \ + "XID=$(XID)" "ALLOPTS=$(ALLOPTS)" +# +########## ########## ########## ########## ########## ########## ########## +# +CP=/bin/cp +RM=/bin/rm +CHMOD=/bin/chmod +INSTALL=$(TOP)/bsdinstall +LIBSRC=$(TOP)/lib +RANLIB=echo +AROPTS=crs +# +DFLAGS=$(IPFLKM) $(DEF) $(SOLARIS2) $(IPFLOG) $(LOOKUP) $(SYNC) $(XID) +#-DIPFDEBUG +MODOBJS=$(OBJ)/ip_fil.o $(OBJ)/fil.o $(OBJ)/solaris.o $(OBJ)/ip_state.o \ + $(OBJ)/ip_frag.o $(OBJ)/ip_nat.o $(OBJ)/ip_proxy.o $(OBJ)/ip_auth.o \ + $(OBJ)/ip_pool.o $(OBJ)/ip_htable.o $(OBJ)/ip_lookup.o $(OBJ)/ip_log.o \ + $(OBJ)/ip_scan.o $(OBJ)/ip_sync.o $(OBJ)/radix_ipf.o $(OBJ)/md5.o \ + $(OBJ)/ip_nat6.o $(OBJ)/ip_dstlist.o $(OBJ)/ip_fil_compat.o \ + $(OBJ)/arc4random.o $(OBJ)/mblk_misc.o $(BPFILTER) +# $(OBJ)/ip_trafcon.o +IPF=$(OBJ)/ipf.o $(OBJ)/ipfcomp.o $(OBJ)/ipf_y.o $(OBJ)/ipf_l.o +IPT=$(OBJ)/ipftest.o $(OBJ)/ip_fil_u.o $(OBJ)/ip_state_u.o \ + $(OBJ)/ip_frag_u.o $(OBJ)/ip_nat_u.o $(OBJ)/fil_u.o \ + $(OBJ)/ip_scan_u.o $(OBJ)/ip_sync_u.o $(OBJ)/ip_pool_u.o \ + $(OBJ)/ip_htable_u.o $(OBJ)/ip_lookup_u.o $(OBJ)/ip_proxy_u.o \ + $(OBJ)/ip_auth_u.o $(OBJ)/ip_log_u.o $(OBJ)/ip_rules_u.o\ + $(OBJ)/ippool_y.o $(OBJ)/ippool_l.o $(OBJ)/ipnat_y.o $(OBJ)/ipnat_l.o \ + $(OBJ)/ipf_y.o $(OBJ)/ipf_l.o $(OBJ)/radix_ipf_u.o $(OBJ)/md5_u.o \ + $(OBJ)/ip_nat6_u.o $(OBJ)/ip_dstlist_u.o +# $(OBJ)/ip_trafcon_u.o +IPNAT=$(OBJ)/ipnat.o $(OBJ)/ipnat_y.o $(OBJ)/ipnat_l.o +IPMON=$(OBJ)/ipmon.o $(OBJ)/ipmon_y.o $(OBJ)/ipmon_l.o +IPPOOL=$(OBJ)/ippool_y.o $(OBJ)/ippool_l.o $(OBJ)/kmem.o $(OBJ)/ippool.o +IPTRAFCON=$(OBJ)/iptrafcon.o +FILS=$(OBJ)/ipfstat.o +# +CCARGS=-I. $(DEBUG) $(CFLAGS) +EXTRA=$(ALLOPTS) + +include $(TOP)/lib/Makefile + +$(OBJ): + @if [ ! -d $(OBJ) ]; then mkdir $(OBJ); fi + + +sunos5 solaris2 build: $(OBJ) $(OBJ)/libipf.a $(OBJ)/ipf.exe $(OBJ)/ipfstat \ + $(OBJ)/ipftest $(OBJ)/ipmon $(OBJ)/ipnat $(OBJ)/ipf $(OBJ)/ipfs \ + $(OBJ)/ippool $(OBJ)/ipfrule + /bin/rm -f $(TOP)/ipf $(TOP)/$(OBJ)/ipf + if [ -f /usr/lib/isaexec -a "$(OBJ)" != . ] ; then \ + mkdir -p $(TOP)/$(OBJ); \ + cp /usr/lib/isaexec $(TOP)/ipf; \ + fi + ln -s `pwd`/$(OBJ)/ipf.exe $(TOP)/$(OBJ)/ipf + -(for i in ipftest ipmon ippool ipnat ipscan ipsyncm ipsyncs; do \ + /bin/rm -f $(TOP)/$$i $(TOP)/$(OBJ)/$$i; \ + if [ -f /usr/lib/isaexec -a "$(OBJ)" != "." ] ; then \ + ln $(TOP)/ipf $(TOP)/$$i; \ + fi; \ + ln -s `pwd`/$(OBJ)/$$i $(TOP)/$(OBJ)/$$i; \ + done;\ + ) + +pkg: $(CPUDIR)/ipf.pkg + +$(OBJ)/ipfstat: $(FILS) $(OBJ)/libipf.a + $(CC) $(CCARGS) $(FILS) -o $@ $(LIBS) $(STATETOP_LIB) -lkvm + +$(OBJ)/ipf.exe: $(IPF) $(OBJ)/libipf.a + $(CC) $(CCARGS) $(IPF) -o $@ $(LIBS) -ll $(LIBBPF) + +# Magic dependency on ipf.exe creates the $(TOP)/$(OBJ{32,64}) directories. +$(OBJ)/ipftest: $(IPT) $(OBJ)/ipf.exe $(OBJ)/libipf.a + $(CC) $(CCARGS) $(IPT) -o $@ $(LIBS) -ll $(LIBBPF) + +$(OBJ)/ipnat: $(IPNAT) $(OBJ)/libipf.a + $(CC) $(CFLAGS) $(IPNAT) -o $@ $(LIBS) -lkvm -ll + +$(OBJ)/ipfs: $(OBJ)/ipfs.o + $(CC) $(CCARGS) $(OBJ)/ipfs.o -o $@ + +$(OBJ)/ipsyncm: $(OBJ)/ipsyncm.o $(OBJ)/libipf.a + $(CC) $(CCARGS) $(OBJ)/ipsyncm.o -o $@ $(LIBS) + +$(OBJ)/ipsyncs: $(OBJ)/ipsyncs.o $(OBJ)/libipf.a + $(CC) $(CCARGS) $(OBJ)/ipsyncs.o -o $@ $(LIBS) + +$(OBJ)/ipsyncm.o: $(TOOL)/ipsyncm.c $(TOP)/ip_sync.h + $(CC) $(CCARGS) -c $(TOOL)/ipsyncm.c -o $@ + +$(OBJ)/ipsyncs.o: $(TOOL)/ipsyncs.c $(TOP)/ip_sync.h + $(CC) $(CCARGS) -c $(TOOL)/ipsyncs.c -o $@ + +tests: + (cd test; make ) + +$(OBJ)/ipfstat.o: $(TOOL)/ipfstat.c $(TOP)/ip_fil.h $(TOP)/ipf.h \ + $(TOP)/ip_state.h $(TOP)/ip_frag.h + $(CC) $(CCARGS) $(STATETOP_CFLAGS) $(STATETOP_INC) \ + -c $(TOOL)/ipfstat.c -o $@ + +$(OBJ)/ipfs.o: $(TOOL)/ipfs.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_state.h \ + $(TOP)/ip_nat.h + $(CC) $(CCARGS) -c $(TOOL)/ipfs.c -o $@ + +$(OBJ)/fil_u.o: $(TOP)/fil.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_nat.h + $(CC) $(CCARGS) $(EXTRA) $(IPFBPF) -c $(TOP)/fil.c -o $@ + +$(OBJ)/fil.o: $(TOP)/fil.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_nat.h + $(CC) -I$(TOP) $(POLICY) $(DFLAGS) $(IPFBPF) $(COMPATIPF) \ + -c $(TOP)/fil.c -o $@ + $(CTFCONVERT) $@ + +$(OBJ)/ipf.o: $(TOOL)/ipf.c $(TOP)/ip_fil.h $(TOP)/ipf.h + $(CC) $(CCARGS) -c $(TOOL)/ipf.c -o $@ + +$(OBJ)/ipfcomp.o: $(TOOL)/ipfcomp.c $(TOP)/ip_fil.h $(TOP)/ipf.h + $(CC) $(CCARGS) -c $(TOOL)/ipfcomp.c -o $@ + +$(OBJ)/ipf_y.o: ipf_y.c $(TOP)/ip_fil.h $(TOP)/ipf.h ipf_y.h ipf_l.h + $(CC) $(CCARGS) $(IPFBPF) -c ipf_y.c -o $@ + +$(OBJ)/ipf_l.o: ipf_l.c $(TOP)/ip_fil.h $(TOP)/ipf.h ipf_y.h ipf_l.h + $(CC) $(CCARGS) -I. -I$(TOP)/tools -c ipf_l.c -o $@ + +ipf_y.h ipf_y.c: $(TOOL)/ipf_y.y $(TOP)/ipf.h $(TOP)/ip_fil.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ipf_l.c: $(TOOL)/lexer.c $(TOP)/ipf.h $(TOP)/ip_fil.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ipf_l.h: $(TOOL)/lexer.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +$(OBJ)/ipftest.o: $(TOOL)/ipftest.c $(TOP)/ip_fil.h $(TOP)/ipt.h $(TOP)/ipf.h + $(CC) $(CCARGS) -c $(TOOL)/ipftest.c -o $@ + +$(OBJ)/ipnat.o: $(TOOL)/ipnat.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_nat.h + $(CC) $(CCARGS) -c $(TOOL)/ipnat.c -o $@ + +$(OBJ)/ipnat_y.o: ipnat_y.c ipnat_y.h $(TOP)/ip_nat.h ipnat_l.h + $(CC) $(CCARGS) -c ipnat_y.c -o $@ + +$(OBJ)/ipnat_l.o: ipnat_l.c ipnat_y.h $(TOP)/ip_nat.h ipnat_l.h + $(CC) $(CCARGS) -I. -I$(TOP)/tools -c ipnat_l.c -o $@ + +ipnat_y.h ipnat_y.c: $(TOOL)/ipnat_y.y $(TOP)/ip_nat.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ipnat_l.c: $(TOOL)/lexer.c $(TOP)/ip_nat.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ipnat_l.h: $(TOOL)/lexer.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +$(OBJ)/mlso_rule.o: $(TOP)/mlso_rule.c + $(CC) -I$(TOP) $(DFLAGS) -c $(TOP)/mlso_rule.c -o $@ + +$(OBJ)/ip_rules.o: $(OBJ)/ip_rules.c $(TOP)/ip_rules.h + $(CC) -I$(TOP) $(DFLAGS) -c $(OBJ)/ip_rules.c -o $@ + $(CTFCONVERT) $@ + +$(OBJ)/ip_rulesx.o: $(OBJ)/ip_rules.c $(TOP)/ip_rules.h + $(CC) -I$(TOP) -DIPFILTER_COMPILED $(DFLAGS) -c $(OBJ)/ip_rules.c -o $@ + +$(OBJ)/ipfrule: $(OBJ)/ip_rulesx.o $(OBJ)/mlso_rule.o + ld -r $(OBJ)/ip_rulesx.o $(OBJ)/mlso_rule.o -o $@ + +$(OBJ)/ipf: $(MODOBJS) + if [ -f /kernel/misc/sparcv9/neti -o -f /kernel/misc/neti ] ; then \ + ld -dy -Nmisc/hook -Nmisc/neti -Nmisc/md5 -Ndrv/ip -r $(MODOBJS) -o $@; \ + else \ + ld -dy -Ndrv/ip -Ndrv/pfil -Nmisc/md5 -r $(MODOBJS) -o $@; \ + fi + $(CTFMERGE) $@ $(MODOBJS) + +$(OBJ)/md5.o: $(TOP)/md5.c $(TOP)/md5.h + $(CC) -I$(TOP) $(DFLAGS) -c $(TOP)/md5.c -o $@ + $(CTFCONVERT) $@ + +$(OBJ)/radix_ipf.o: $(TOP)/md5.c $(TOP)/radix_ipf.h $(TOP)/radix_ipf.c + $(CC) -I$(TOP) $(DFLAGS) -c $(TOP)/radix_ipf.c -o $@ + $(CTFCONVERT) $@ + +$(OBJ)/ip_nat.o: $(TOP)/ip_nat.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h + $(CC) -I$(TOP) $(DFLAGS) -c $(TOP)/ip_nat.c -o $@ + $(CTFCONVERT) $@ + +$(OBJ)/ip_nat6.o: $(TOP)/ip_nat6.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h + $(CC) -I$(TOP) $(DFLAGS) -c $(TOP)/ip_nat6.c -o $@ + $(CTFCONVERT) $@ + +$(OBJ)/ip_state.o: $(TOP)/ip_state.c $(TOP)/ip_state.h $(TOP)/ip_compat.h + $(CC) -I$(TOP) $(DFLAGS) -c $(TOP)/ip_state.c -o $@ + $(CTFCONVERT) $@ + +$(OBJ)/ip_scan.o: $(TOP)/ip_scan.c $(TOP)/ip_scan.h $(TOP)/ip_compat.h + $(CC) -I$(TOP) $(DFLAGS) -c $(TOP)/ip_scan.c -o $@ + $(CTFCONVERT) $@ + +$(OBJ)/ip_sync.o: $(TOP)/ip_sync.c $(TOP)/ip_sync.h $(TOP)/ip_compat.h + $(CC) -I$(TOP) $(DFLAGS) -c $(TOP)/ip_sync.c -o $@ + $(CTFCONVERT) $@ + +$(OBJ)/ip_proxy.o: $(TOP)/ip_proxy.c $(TOP)/ip_proxy.h $(TOP)/ip_compat.h \ + $(TOP)/ip_ftp_pxy.c $(TOP)/ip_rcmd_pxy.c $(TOP)/ip_raudio_pxy.c \ + $(TOP)/ip_rpcb_pxy.c $(TOP)/ip_ipsec_pxy.c $(TOP)/ip_dns_pxy.c \ + $(TOP)/ip_tftp_pxy.c $(TOP)/ip_nat.h $(TOP)/ip_pptp_pxy.c \ + $(TOP)/ip_fil.h + $(CC) -I$(TOP) $(DFLAGS) -c $(TOP)/ip_proxy.c -o $@ + $(CTFCONVERT) $@ + +$(OBJ)/ip_frag.o: $(TOP)/ip_frag.c $(TOP)/ip_frag.h $(TOP)/ip_compat.h + $(CC) -I$(TOP) $(DFLAGS) -c $(TOP)/ip_frag.c -o $@ + $(CTFCONVERT) $@ + +$(OBJ)/ip_auth.o: $(TOP)/ip_auth.c $(TOP)/ip_auth.h $(TOP)/ip_compat.h + $(CC) -I$(TOP) $(DFLAGS) -c $(TOP)/ip_auth.c -o $@ + $(CTFCONVERT) $@ + +$(OBJ)/ip_pool.o: $(TOP)/ip_pool.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_pool.h $(TOP)/ip_lookup.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_pool.c -o $@ + $(CTFCONVERT) $@ + +$(OBJ)/ip_htable.o: $(TOP)/ip_htable.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_htable.h $(TOP)/ip_lookup.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_htable.c -o $@ + $(CTFCONVERT) $@ + +$(OBJ)/ip_dstlist.o: $(TOP)/ip_dstlist.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_dstlist.h $(TOP)/ip_lookup.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_dstlist.c -o $@ + $(CTFCONVERT) $@ + +$(OBJ)/ip_fil_compat.o: $(TOP)/ip_fil_compat.c $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(TOP)/ip_state.h $(TOP)/ip_nat.h + $(CC) $(CCARGS) $(DFLAGS) $(COMPATIPF) -c $(TOP)/ip_fil_compat.c -o $@ + $(CTFCONVERT) $@ + +$(OBJ)/ip_lookup.o: $(TOP)/ip_lookup.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_pool.h $(TOP)/ip_htable.h $(TOP)/ip_lookup.h \ + $(TOP)/ip_dstlist.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_lookup.c -o $@ + $(CTFCONVERT) $@ + +$(OBJ)/arc4random.o: $(TOP)/arc4random.c + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/arc4random.c -o $@ + $(CTFCONVERT) $@ + +$(OBJ)/mblk_misc.o: $(TOP)/SunOS5/mblk_misc.c + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/SunOS5/mblk_misc.c -o $@ + $(CTFCONVERT) $@ + +$(OBJ)/ip_trafcon.o: $(TOP)/ip_trafcon.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_trafcon.h + $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_trafcon.c -o $@ + +$(OBJ)/bpf_filter.o: $(TOP)/bpf_filter.c $(TOP)/bpf-ipf.h $(TOP)/pcap-ipf.h + $(CC) -I$(TOP) $(DFLAGS) -c $(TOP)/bpf_filter.c -o $@ + $(CTFCONVERT) $@ + +$(OBJ)/bpf_filter_u.o: $(TOP)/bpf_filter.c + $(CC) -I$(TOP) $(DFLAGS) -c $(TOP)/bpf_filter.c -o $@ + +$(OBJ)/md5_u.o: $(TOP)/md5.c $(TOP)/md5.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/md5.c -o $@ + +$(OBJ)/radix_ipf_u.o: $(TOP)/radix_ipf.c $(TOP)/radix_ipf.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/radix_ipf.c -o $@ + +$(OBJ)/ip_nat_u.o: $(TOP)/ip_nat.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_nat.c -o $@ + +$(OBJ)/ip_nat6_u.o: $(TOP)/ip_nat6.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_nat6.c -o $@ + +$(OBJ)/ip_frag_u.o: $(TOP)/ip_frag.c $(TOP)/ip_frag.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_frag.c -o $@ + +$(OBJ)/ip_state_u.o: $(TOP)/ip_state.c $(TOP)/ip_state.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_state.c -o $@ + +$(OBJ)/ip_scan_u.o: $(TOP)/ip_scan.c $(TOP)/ip_scan.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_scan.c -o $@ + +$(OBJ)/ip_sync_u.o: $(TOP)/ip_sync.c $(TOP)/ip_sync.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_sync.c -o $@ + +$(OBJ)/ip_pool_u.o: $(TOP)/ip_pool.c $(TOP)/ip_pool.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(TOP)/ip_lookup.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_pool.c -o $@ + +$(OBJ)/ip_htable_u.o: $(TOP)/ip_htable.c $(TOP)/ip_htable.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(TOP)/ip_lookup.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_htable.c -o $@ + +$(OBJ)/ip_dstlist_u.o: $(TOP)/ip_dstlist.c $(TOP)/ip_dstlist.h \ + $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(TOP)/ip_lookup.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_dstlist.c -o $@ + +$(OBJ)/ip_lookup_u.o: $(TOP)/ip_lookup.c $(TOP)/ip_lookup.h $(TOP)/ip_compat.h \ + $(TOP)/ip_fil.h $(TOP)/ip_lookup.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_lookup.c -o $@ + +$(OBJ)/ip_trafcon_u.o: $(TOP)/ip_trafcon.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \ + $(TOP)/ip_trafcon.h + $(CC) $(CCARGS) -c $(TOP)/ip_trafcon.c -o $@ + +$(OBJ)/ip_auth_u.o: $(TOP)/ip_auth.c $(TOP)/ip_auth.h $(TOP)/ip_compat.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_auth.c -o $@ + +$(OBJ)/ip_proxy_u.o: $(TOP)/ip_proxy.c $(TOP)/ip_proxy.h $(TOP)/ip_compat.h \ + $(TOP)/ip_ftp_pxy.c $(TOP)/ip_rcmd_pxy.c $(TOP)/ip_raudio_pxy.c \ + $(TOP)/ip_rpcb_pxy.c $(TOP)/ip_ipsec_pxy.c $(TOP)/ip_dns_pxy.c \ + $(TOP)/ip_tftp_pxy.c $(TOP)/ip_pptp_pxy.c $(TOP)/ip_nat.h \ + $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_proxy.c -o $@ + +$(OBJ)/ip_rules.c: $(OBJ)/ipf.exe $(TOP)/tools/ipfcomp.c $(TOP)/rules/ip_rules + $(OBJ)/ipf.exe -cc -nf $(TOP)/rules/ip_rules + -/bin/mv -f ip_rules.c $(OBJ) + +$(TOP)/ip_rules.h: $(OBJ)/ip_rules.c + if [ -f ip_rules.h ] ; then \ + /bin/mv -f ip_rules.h $(TOP) ; \ + fi + +$(OBJ)/ip_rules_u.o: $(OBJ)/ip_rules.c $(TOP)/ip_fil.h $(TOP)/ip_rules.h + $(CC) $(CCARGS) $(EXTRA) -c $(OBJ)/ip_rules.c -o $@ + +$(OBJ)/ip_fil_u.o: $(TOP)/ip_fil.c $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_fil.c -o $@ + +$(OBJ)/ip_fil.o: $(TOP)/ip_fil_solaris.c $(TOP)/ip_fil.h + $(CC) -I$(TOP) $(DFLAGS) $(COMPIPF) -c $(TOP)/ip_fil_solaris.c -o $@ + $(CTFCONVERT) $@ + +$(OBJ)/ip_log_u.o: $(TOP)/ip_log.c $(TOP)/ip_fil.h + $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_log.c -o $@ + +$(OBJ)/ip_log.o: $(TOP)/ip_log.c $(TOP)/ip_fil.h + $(CC) -I$(TOP) $(DFLAGS) -c $(TOP)/ip_log.c -o $@ + $(CTFCONVERT) $@ + +$(OBJ)/solaris.o: $(TOP)/solaris.c $(TOP)/ipl.h + $(CC) -I$(TOP) $(DFLAGS) -c $(TOP)/solaris.c -o $@ + $(CTFCONVERT) $@ + +$(OBJ)/ipmon: $(IPMON) $(OBJ)/libipf.a + $(CC) $(CCARGS) $(LOGFAC) $(IPMON) -o $@ $(LIBS) -ll -ldl + +$(OBJ)/ipmon.o: $(TOOL)/ipmon.c $(TOP)/ipmon.h + $(CC) $(CCARGS) $(LOGFAC) -c $(TOOL)/ipmon.c -o $@ + +$(OBJ)/ipmon_y.o: ipmon_y.c $(TOP)/ipmon.h ipmon_y.h ipmon_l.h + $(CC) $(CCARGS) -c ipmon_y.c -o $@ + +$(OBJ)/ipmon_l.o: ipmon_l.c $(TOP)/ipmon.h ipmon_y.h ipmon_l.h + $(CC) $(CCARGS) -I. -I$(TOP)/tools -c ipmon_l.c -o $@ + +ipmon_y.c $(OBJ)/ipmon_y.h: $(TOOL)/ipmon_y.y $(TOP)/ipmon.h + (cd $(TOOL); make DEST=../$(HERE) ../$(HERE)/$@) + mv ipmon_y.c y.tab.c + sed -e 's/extern [a-z]* .*();//' \ + -e 's/^\(static [a-z]* .*\)();/\1(void);/' y.tab.c > $@ + /bin/rm -f y.tab.c + +ipmon_l.c: $(TOOL)/lexer.c $(TOP)/ipmon.h + (cd $(TOOL); make DEST=../$(HERE) ../$(HERE)/$@) + +ipmon_l.h: $(TOOL)/lexer.h + (cd $(TOOL); make DEST=../$(HERE) ../$(HERE)/$@) + +$(OBJ)/ipscan: $(OBJ)/ipscan_y.o $(OBJ)/ipscan_l.o $(OBJ)/libipf.a + $(CC) $(DEBUG) $(OBJ)/ipscan_y.o $(OBJ)/ipscan_l.o -o $@ -ll $(LIBS) + +$(OBJ)/ipscan_y.o: ipscan_y.c ipscan_y.h $(TOP)/ip_scan.h + $(CC) $(CCARGS) -c ipscan_y.c -o $@ + +$(OBJ)/ipscan_l.o: ipscan_l.c ipscan_y.h $(TOP)/ip_scan.h ipscan_l.h + $(CC) $(CCARGS) -I. -I$(TOP)/tools -c ipscan_l.c -o $@ + +ipscan_y.h ipscan_y.c: $(TOOL)/ipscan_y.y $(TOP)/ip_scan.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ipscan_l.c: $(TOOL)/lexer.c $(TOP)/ip_scan.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ipscan_l.h: $(TOOL)/lexer.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +$(OBJ)/ippool: $(IPPOOL) $(OBJ)/libipf.a + $(CC) $(CCARGS) -I. $(IPPOOL) -o $@ $(LIBS) -ll -lkvm + +$(OBJ)/ippool.o: $(TOOL)/ippool.c $(TOP)/ip_pool.h $(TOP)/ip_htable.h \ + $(TOP)/ip_dstlist.h + $(CC) $(CCARGS) -c $(TOOL)/ippool.c -o $@ + +$(OBJ)/ippool_y.o: ippool_y.c ippool_y.h $(TOP)/ip_pool.h ippool_l.h \ + $(TOP)/ip_htable.h $(TOP)/ip_dstlist.h + $(CC) $(CCARGS) -c ippool_y.c -o $@ + +$(OBJ)/ippool_l.o: ippool_l.c ippool_y.h $(TOP)/ip_pool.h ippool_l.h + $(CC) $(CCARGS) -I. -I$(TOP)/tools -c ippool_l.c -o $@ + +ippool_y.h ippool_y.c: $(TOOL)/ippool_y.y $(TOP)/ip_pool.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ippool_l.c: $(TOOL)/lexer.c $(TOP)/ip_pool.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +ippool_l.h: $(TOOL)/lexer.h + (cd $(TOOL); make "DEST=../$(HERE)" ../$(HERE)/$@) + +$(OBJ)/iptrafcon.o: $(TOP)/iptrafcon.c + $(CC) $(CCARGS) -c $(TOP)/iptrafcon.c -o $@ + +$(OBJ)/iptrafcon: $(IPTRAFCON) $(OBJ)/libipf.a + $(CC) $(CCARGS) $(IPTRAFCON) -o $@ $(LIBS) + +.y.c: + +.l.c: + +clean: + ${RM} -f $(TOP)/ipf $(TOP)/ipnat $(TOP)/ipmon $(TOP)/ippool + ${RM} -f $(TOP)/ipftest $(TOP)/ipscan $(TOP)/ipsyncm $(TOP)/ipsyncs + if [ `basename \`pwd\`` != SunOS5 ] ; then \ + ${RM} -f core *.o ipfrule ipf ipfstat ipftest ipmon ipnat ; \ + ${RM} -f ipf.exe ipfs ipsyncm ipsyncs libipf.a; \ + ${RM} -f ipnat.5 ipnat.4 ipnat.8 ipfilter.4 ipfilter.5; \ + ${RM} -f ippool.8 ippool.5 ipscan.8 ipscan.5 ipmon.5; \ + ${RM} -f prototype pkginfo postinstall postremove copyright; \ + ${RM} -f ip_fil.c ipf_l.c ipf_y.c ipf_y.h ipf_l.h; \ + ${RM} -f ipscan ipscan_y.c ipscan_y.h ipscan_l.c; \ + ${RM} -f ippool ippool_y.c ippool_y.h ippool_l.c; \ + ${RM} -f ipscan_l.h ippool_l.h ip_rules.c ip_rules.h; \ + ${RM} -f ipnat_y.c ipnat_y.h ipnat_l.c ipnat_l.h; \ + ${RM} -f ipmon_y.c ipmon_y.h ipmon_l.c ipmon_l.h; \ + ${RM} -f ipsyncm ipsyncs ipfs; \ + fi + /bin/rm -rf */root ipf.pkg* $(OBJ32) $(OBJ64) + make -f Makefile.ipsend clean "TOP=${TOP}" + -(for i in *; do \ + if [ -d $${i} -a -h $${i}/Makefile ] ; then \ + (cd $${i}; make TOP=`cd ..; cd $(TOP); pwd` clean); \ + rm $${i}/Makefile $${i}/Makefile.ipsend; \ + rmdir $${i}; \ + fi \ + done) + +$(CPUDIR)/ipf.pkg: $(CPUDIR)/ipf.pkg.common + if [ -d $(CPUDIR)/$(OBJ32) ]; then \ + $(MAKE) PROTO=$(PROTO32) PKG=ipf OBJ=$(OBJ32) \ + BITS=32 TOP=$(TOP) ipf.pkg.bin; \ + $(MAKE) PROTO=$(PROTO64) PKG=ipfx OBJ=$(OBJ64) \ + BITS=64 TOP=$(TOP) ipf.pkg.bin; \ + else \ + ($(MAKE) PROTO=prototype OBJ=. BITS=${BITS} \ + TOP=$(TOP) ipf.pkg.bin) \ + fi + touch $(CPUDIR)/ipf.pkg + pkgtrans -s $(TMP) $(CPUDIR)/ipf.pkg `ls $(TMP)` + /bin/rm -f ipf.pkg + rm -rf $(TMP)/ipf* + +$(CPUDIR)/ipf.pkg.common: + mkdir -p $(ROOTINC)/ipfilter $(PKGDIR)/examples $(ROOT)/usr/kernel/drv + mkdir -p $(ROOT)/etc/init.d $(TMP) + mkdir -p $(PKGMAN)/man1 $(PKGMAN)/man4 $(PKGMAN)/man5 $(PKGMAN)/man8 + -$(INSTALL) -c ipfboot $(ROOT)/etc/init.d + -cp $(TOP)/man/*.[0-9] . + -$(INSTALL) -c ipf.conf $(ROOT)/usr/kernel/drv + -$(INSTALL) ipf.8 $(PKGMAN)/man8 + -$(INSTALL) ipfs.8 $(PKGMAN)/man8 + -$(INSTALL) ipnat.8 $(PKGMAN)/man8 + -$(INSTALL) ipftest.1 $(PKGMAN)/man1 + -$(INSTALL) mkfilters.1 $(PKGMAN)/man1 + -$(INSTALL) ipf.4 $(PKGMAN)/man4 + -$(INSTALL) ipfilter.4 $(PKGMAN)/man4 + -$(INSTALL) ipnat.4 $(PKGMAN)/man4 + -$(INSTALL) ipl.4 $(PKGMAN)/man4 + -$(INSTALL) ipf.5 $(PKGMAN)/man5 + -$(INSTALL) ipnat.5 $(PKGMAN)/man5 + -$(INSTALL) ippool.5 $(PKGMAN)/man5 + -$(INSTALL) ipfilter.5 $(PKGMAN)/man5 + -$(INSTALL) ipfstat.8 $(PKGMAN)/man8 + -$(INSTALL) ipmon.8 $(PKGMAN)/man8 + -$(INSTALL) ippool.8 $(PKGMAN)/man8 + -cp $(TOP)/rules/* $(PKGDIR)/examples + -cp $(TOP)/ip_fil.h $(TOP)/ip_compat.h $(TOP)/ip_state.h . + -cp $(TOP)/ip_nat.h $(TOP)/ip_frag.h $(TOP)/ip_proxy.h . + -cp $(TOP)/ip_auth.h $(TOP)/ip_htable.h $(TOP)/ip_pool.h . + -cp $(TOP)/ip_lookup.h $(TOP)/ip_dstlist.h . + -$(INSTALL) ip_fil.h $(ROOTINC)/ipfilter + -$(INSTALL) ip_compat.h $(ROOTINC)/ipfilter + -$(INSTALL) ip_state.h $(ROOTINC)/ipfilter + -$(INSTALL) ip_nat.h $(ROOTINC)/ipfilter + -$(INSTALL) ip_frag.h $(ROOTINC)/ipfilter + -$(INSTALL) ip_htable.h $(ROOTINC)/ipfilter + -$(INSTALL) ip_dstlist.h $(ROOTINC)/ipfilter + -$(INSTALL) ip_lookup.h $(ROOTINC)/ipfilter + -$(INSTALL) ip_pool.h $(ROOTINC)/ipfilter + -$(INSTALL) ip_proxy.h $(ROOTINC)/ipfilter + -$(INSTALL) ip_auth.h $(ROOTINC)/ipfilter + touch $@ + +# +# For 64 bit Solaris, we build 32 and 64 bit packages, but the 64 bit package +# is smaller and only contains the 64 bit specific and not the common stuff. +# +ipf.pkg.bin: + mkdir -p $(PKGBIN) $(ROOT)/$(SBINDEST) $(ROOT)/usr/kernel/drv/$(OBJ) + -$(INSTALL) -c -s $(OBJDIR)/ipftest $(PKGBIN)/ipftest + -$(INSTALL) -c -s $(OBJDIR)/ipmon $(PKGBIN)/ipmon + -$(INSTALL) -c -s $(OBJDIR)/ipsend $(PKGBIN)/ipsend + -$(INSTALL) -c -s $(OBJDIR)/ipresend $(PKGBIN)/ipresend + -$(INSTALL) -c $(TOP)/mkfilters $(PKGBIN)/mkfilters + -$(INSTALL) -c $(OBJDIR)/ipf $(ROOT)/usr/kernel/drv/$(OBJ)/ipf + -$(INSTALL) -c -s $(OBJDIR)/ipnat $(ROOT)/$(SBINDEST)/ipnat + -$(INSTALL) -c -s $(OBJDIR)/ippool $(ROOT)/$(SBINDEST)/ippool + -$(INSTALL) -c -s $(OBJDIR)/ipf.exe $(ROOT)/$(SBINDEST)/ipf + -$(INSTALL) -c -s $(OBJDIR)/ipfs $(ROOT)/$(SBINDEST)/ipfs + -$(INSTALL) -c -s $(OBJDIR)/ipfstat $(ROOT)/$(SBINDEST)/ipfstat +# -(cd $(CPUDIR); rm -f copyright post* prototype pkginfo) + -(cd $(CPUDIR); rm -f prototype) +# -(cd $(CPUDIR); ln -s ../copyright ../postinstall ../postremove .) + -(cd $(CPUDIR); ln -s ../$(PROTO) prototype) + -sed -e 's/ipf/$(PKG)/' -e "s/NAME=.*/&$(BITTYPE)/" \ + -e "s/ARCH=.*/ARCH=`uname -p` (${BITS}-bit)/" \ + < pkginfo > $(CPUDIR)/pkginfo + -if [ "$(BITS)" = 64 ]; then echo 'SUNW_ISA=$(OBJ64)' >> $(CPUDIR)/pkginfo; fi + (cd $(CPUDIR); pkgmk -a `uname -p` -o -d $(TMP)) + + +package install: $(CPUDIR)/ipf.pkg + /bin/rm -f ipf.pkg + ln -s $(CPUDIR)/ipf.pkg ipf.pkg + @if [ `id|sed -e 's/^.[^(]*(\([^)]*\)).*/\1/'` != root ] ; then \ + echo "Can only install if root"; \ + exit 1; \ + fi +# Must add ipfx before ipf or driver attach fails. + -[ -d $(CPUDIR)/$(OBJ64) ] && pkgadd -d ipf.pkg ipfx + -pkgadd -d ipf.pkg ipf diff --git a/SunOS5/Makefile.ipsend b/SunOS5/Makefile.ipsend new file mode 100644 index 0000000000000..a9d09da586186 --- /dev/null +++ b/SunOS5/Makefile.ipsend @@ -0,0 +1,62 @@ +OBJ=. +DEST=. +BITS=32 +IOBJS=$(OBJ)/ipsend.o $(OBJ)/ip.o $(OBJ)/ipsopt.o $(OBJ)/iplang_y.o \ + $(OBJ)/iplang_l.o +ROBJS=$(OBJ)/ipresend.o $(OBJ)/ip.o $(OBJ)/resend.o $(IPFTO) +TOBJS=$(OBJ)/iptest.o $(OBJ)/iptests.o $(OBJ)/ip.o +UNIXOBJS=$(OBJ)/dlcommon.o $(OBJ)/sdlpi.o $(OBJ)/arp.o +LIBS=-lsocket -lnsl -L$(OBJ) -lipf +LIBSRC=$(TOP)/lib + +CC=gcc +CFLAGS=-g -I$$(TOP) -Dsolaris + +include $(TOP)/lib/Makefile + +all build dlpi sunos5 : $(OBJ)/ipsend $(OBJ)/ipresend $(OBJ)/iptest \ + $(OBJ)/libipf.a + +.c.o: + $(CC) $(DEBUG) $(CFLAGS) -c $< -o $@ + +$(OBJ)/iplang_y.o: $(TOP)/iplang/iplang_y.y + (cd $(TOP)/iplang; $(MAKE) ../SunOS5/$(CPUDIR)/$@ 'DESTDIR=../SunOS5/$(CPUDIR)/$(OBJ)' 'CFLAGS=$(CFLAGS)' 'OBJ=$(OBJ)') + +$(OBJ)/iplang_l.o: $(TOP)/iplang/iplang_l.l + (cd $(TOP)/iplang; $(MAKE) ../SunOS5/$(CPUDIR)/$@ 'DESTDIR=../SunOS5/$(CPUDIR)/$(OBJ)' 'CFLAGS=$(CFLAGS)' 'OBJ=$(OBJ)') + +$(OBJ)/ipsend: $(IOBJS) $(UNIXOBJS) $(OBJ)/libipf.a + $(CC) $(DEBUG) $(IOBJS) $(UNIXOBJS) -o $@ $(LIBS) -ll + +$(OBJ)/ipresend: $(ROBJS) $(UNIXOBJS) $(OBJ)/libipf.a + $(CC) $(DEBUG) $(ROBJS) $(UNIXOBJS) -o $@ $(LIBS) + +$(OBJ)/iptest: $(TOBJS) $(UNIXOBJS) $(OBJ)/libipf.a + $(CC) $(DEBUG) $(TOBJS) $(UNIXOBJS) -o $@ $(LIBS) + +clean: + rm -rf *.o core a.out ipsend ipresend iptest iplang_l.* iplang_y.* + +$(OBJ)/ipsend.o: $(TOP)/ipsend/ipsend.c + $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/ipsend.c -o $@ +$(OBJ)/ipsopt.o: $(TOP)/ipsend/ipsopt.c + $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/ipsopt.c -o $@ +$(OBJ)/ipresend.o: $(TOP)/ipsend/ipresend.c + $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/ipresend.c -o $@ +$(OBJ)/ip.o: $(TOP)/ipsend/ip.c + $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/ip.c -o $@ +$(OBJ)/resend.o: $(TOP)/ipsend/resend.c + $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/resend.c -o $@ +$(OBJ)/iptest.o: $(TOP)/ipsend/iptest.c + $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/iptest.c -o $@ +$(OBJ)/iptests.o: $(TOP)/ipsend/iptests.c + $(CC) $(DEBUG) $(CFLAGS) -Dsolaris -c $(TOP)/ipsend/iptests.c -o $@ +$(OBJ)/sock.o: $(TOP)/ipsend/sock.c + $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/sock.c -o $@ +$(OBJ)/arp.o: $(TOP)/ipsend/arp.c + $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/arp.c -o $@ +$(OBJ)/dlcommon.o: $(TOP)/ipsend/dlcommon.c + $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/dlcommon.c -o $@ +$(OBJ)/sdlpi.o: $(TOP)/ipsend/sdlpi.c + $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/sdlpi.c -o $@ diff --git a/SunOS5/copyright b/SunOS5/copyright new file mode 100644 index 0000000000000..00c9883d727c8 --- /dev/null +++ b/SunOS5/copyright @@ -0,0 +1,16 @@ + +Copyright (C) 2012 by Darren Reed. + +The author accepts no responsibility for the use of this software and +provides it on an ``as is'' basis without express or implied warranty. + +Redistribution and use in source and binary forms are permitted +provided that this notice is preserved and due credit is given +to the original author and the contributors. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +I hate legaleese, don't you ? + diff --git a/SunOS5/depend b/SunOS5/depend new file mode 100644 index 0000000000000..8ded3f22f6928 --- /dev/null +++ b/SunOS5/depend @@ -0,0 +1,2 @@ +# +# P pfil pfil interface for Solaris diff --git a/SunOS5/ipf.conf b/SunOS5/ipf.conf new file mode 100644 index 0000000000000..6b36f9fdbf4de --- /dev/null +++ b/SunOS5/ipf.conf @@ -0,0 +1,3 @@ +# +# +name="ipf" parent="pseudo" instance=0; diff --git a/SunOS5/ipfboot b/SunOS5/ipfboot new file mode 100644 index 0000000000000..4f4115c04ca75 --- /dev/null +++ b/SunOS5/ipfboot @@ -0,0 +1,233 @@ +#!/bin/sh +# +IPFBASE=/etc/opt/ipf + +PATH=/bin:/sbin:/usr/sbin:${PATH}:/opt/ipf/bin +IPFILCONF=${IPFBASE}/ipf.conf +IP6FILCONF=${IPFBASE}/ipf6.conf +IPNATCONF=${IPFBASE}/ipnat.conf +IPPOOLCONF=${IPFBASE}/ippool.conf +if [ -f /kernel/misc/neti -o -f /kernel/misc/sparcv9/neti ] ; then + PFILCHECKED=yes +else + PFILCHECKED=no +fi +if [ -d /var/run ] ; then + PIDFILE=/var/run/ipmon.pid +else + PIDFILE=${IPFBASE}/ipmon.pid +fi + + +getpid() +{ + if [ -f /usr/bin/pgrep ] ; then + rval=`pgrep $1` + else + rval=`ps -ef | awk "/$1/ { print \\$2; } " -` + fi + + return $rval +} + +logmsg() +{ + logger -p local0.emerg -t ipfilter "$1" + echo "$1" >&2 +} + + +checkpfil() +{ + if [ $PFILCHECKED = yes ] ; then + return + fi + if [ -z "`ndd /dev/pfil qif_status 2>/dev/null`" ] ; then + logmsg "pfil not available to support ipfilter" + exit 1 + fi + if [ `uname -r|cut -d. -f2` -gt 7 ] ; then + realnic=`/sbin/ifconfig -a modlist 2>/dev/null | grep -c pfil` + else + for i in `ifconfig -a | cut -d: -f1 | egrep -v '[ ]|^lo'` + do + if strconf -m pfil < /dev/$i >/dev/null 2>&1 ; then + realnic=1; + break; + fi + done + fi + if [ $realnic -eq 0 ] ; then + logmsg "pfil not configured for firewall/NAT operation" + fi + PFILCHECKED=yes +} + + +getids() +{ + ipfid=`modinfo 2>&1 | awk '/ipf / { print $1 } ' - 2>/dev/null` + ipfruleid=`modinfo 2>&1 | awk '/ipfrule/ { print $1 } ' - 2>/dev/null` + if [ -f $PIDFILE ] ; then + pid=`cat $PIDFILE 2>/dev/null` + else + getpid ipmon + pid=$? + fi +} + + +block_default_workaround() { + ipf -F a + echo "constructing minimal name resolution rules..." + NAMESERVERS=`cat /etc/resolv.conf 2>/dev/null| \ + nawk '/nameserver/ {printf "%s ", $2}' 2>/dev/null` + if [ -z "$NAMESERVERS" ] ; then + return + fi + for NS in $NAMESERVERS ; do + IF_TO_NS=`route -n get $NS 2>/dev/null| \ + nawk '$1 == "interface:" { print $NF ; exit }' \ + 2>/dev/null` + if [ -z "$IF_TO_NS" ] ; then + continue + fi + IP_TO_NS=`ifconfig $IF_TO_NS 2>/dev/null| \ + nawk 'NR == "2" { print $2 ; exit }' 2>/dev/null` + if [ -z "$IP_TO_NS" ] ; then + continue + fi + echo "pass out quick on $IF_TO_NS proto udp from $IP_TO_NS to $NS port = 53 keep state" | \ + ipf -f - + done +} + + +load_ipf_config() { + bad=0 + if [ -r ${IPFILCONF} ]; then + checkpfil + if `ipf -V | \ + nawk '$1 == "Default:" && $2 == "pass" { exit 1 }'` ; then + block_default_workaround + fi + ipf -IFa -f ${IPFILCONF} + if [ $? != 0 ]; then + echo "$0: load of ${IPFILCONF} into alternate set failed" + bad=1 + fi + fi + if [ -r ${IP6FILCONF} ]; then + checkpfil + ipf -6IFa -f ${IP6FILCONF} + if [ $? != 0 ]; then + echo "$0: load of ${IPFILCONF} into alternate set failed" + bad=1 + fi + fi + if [ $bad -eq 0 ] ; then + ipf -s -y + else + echo Not switching config due to load error. + fi +} + + +load_ipnat_config() { + if [ -r ${IPNATCONF} ]; then + checkpfil + ipnat -CF -f ${IPNATCONF} + if [ $? != 0 ]; then + echo "$0: load of ${IPNATCONF} failed" + else + ipf -y + fi + fi +} + + +load_ippool_config() { + if [ -r ${IPPOOLCONF} ]; then + checkpfil + ippool -F + ippool -f ${IPPOOLCONF} + if [ $? != 0 ]; then + echo "$0: load of ${IPPOOLCONF} failed" + fi + fi +} + + +case "$1" in + start) + getids + [ -n "$pid" ] && kill -TERM $pid 2>/dev/null + [ -n "$ipfruleid" ] && modunload -i $ipfruleid 2>/dev/null + [ -n "$ipfid" ] && modunload -i $ipfid 2>/dev/null + modload /usr/kernel/drv/ipf + if [ -f /usr/kernel/drv/ipfrule ] ; then + modload /usr/kernel/drv/ipfrule + fi + ipf -E + load_ippool_config + load_ipf_config + load_ipnat_config + ipmon -Ds + ;; + + stop) + getids + [ -n "$pid" ] && kill -TERM $pid + /bin/rm -f $PIDFILE + ipf -D + [ -n "$ipfruleid" ] && modunload -i $ipfruleid 2>/dev/null + [ -n "$ipfid" ] && modunload -i $ipfid + ;; + + pause) + getids + ipfs -l + ipfs -NS -w + ipf -D + if [ -f $PIDFILE ] ; then + if kill -0 $pid; then + kill -TERM $pid + else + cp /dev/null $PIDFILE + fi + fi + ;; + + resume) + getids + ipf -E + ipfs -R + load_ippool_config + load_ipf_config + load_ipnat_config + if [ -f $PIDFILE -a x$pid != x ] ; then + ipmon -Ds + fi + ;; + + reload) + load_ippool_config + load_ipf_config + load_ipnat_config + ;; + + reipf) + load_ipf_config + ;; + + reipnat) + load_ipnat_config + ;; + + *) + echo "Usage: $0 (start|stop|reload|reipf|reipnat|pause|resume)" >&2 + exit 1 + ;; + +esac +exit 0 diff --git a/SunOS5/makeargs b/SunOS5/makeargs new file mode 100755 index 0000000000000..f6b9c5606f6f3 --- /dev/null +++ b/SunOS5/makeargs @@ -0,0 +1,10 @@ +#!/bin/ksh +dir=${0%makeargs} +hprev=`uname -r | sed -e 's/^[A-Z]\.\([0-9]*\)\.\([0-9]\)/\1\2/'` +if [ $hprev -lt 1111 ] ; then + lib=' LLIB=-ll' + dcpu=' SPU="-Dspustate_t=u_long"' +fi +cpu=`$dir/cpurev` +echo 'CPUDIR='$cpu' HPUXREV='$hprev''$lib$dcpu +exit 0 diff --git a/SunOS5/mblk_misc.c b/SunOS5/mblk_misc.c new file mode 100644 index 0000000000000..85acff8b35514 --- /dev/null +++ b/SunOS5/mblk_misc.c @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ +#ifndef __hpux +#pragma ident "@(#)$Id: mblk_misc.c,v 1.1.2.2 2012/07/22 08:04:24 darren_r Exp $" +#else +struct uio; +#endif + +#include <sys/systm.h> +#include <sys/types.h> +#include <sys/stream.h> + +#ifndef MTYPE +# define MTYPE(m) ((m)->b_datap->db_type) +#endif + +#ifndef MIN +# define MIN(a,b) (((a)<(b))?(a):(b)) +#endif + +#ifdef __hpux +# define BCOPY(a,b,c) bcopy((caddr_t)a, (caddr_t)b, c) +#endif +#ifdef sun +# define BCOPY(a,b,c) bcopy((char *)a, (char *)b, c) +#endif + +void m_copydata(min, off, len, buf) +mblk_t *min; +size_t off, len; +char *buf; +{ + u_char *s, *bp = (u_char *)buf; + size_t mlen, olen, clen; + mblk_t *m; + + for (m = min; (m != NULL) && (len > 0); m = m->b_cont) { + if (MTYPE(m) != M_DATA) + continue; + s = m->b_rptr; + mlen = m->b_wptr - s; + olen = MIN(off, mlen); + if ((olen == mlen) || (olen < off)) { + off -= olen; + continue; + } else if (olen) { + off -= olen; + s += olen; + mlen -= olen; + } + clen = MIN(mlen, len); + BCOPY(s, bp, clen); + len -= clen; + bp += clen; + } +} + + +void m_copyback(min, off, len, buf) +mblk_t *min; +size_t off, len; +char *buf; +{ + u_char *s, *bp = (u_char *)buf; + size_t mlen, olen, clen; + mblk_t *m, *mp; + + for (m = min, mp = NULL; (m != NULL) && (len > 0); m = m->b_cont) { + mp = m; + if (MTYPE(m) != M_DATA) + continue; + + s = m->b_rptr; + mlen = m->b_wptr - s; + olen = MIN(off, mlen); + if ((olen == mlen) || (olen < off)) { + off -= olen; + continue; + } else if (olen) { + off -= olen; + s += olen; + mlen -= olen; + } + clen = MIN(mlen, len); + BCOPY(bp, s, clen); + len -= clen; + bp += clen; + } + + if ((m == NULL) && (mp != NULL)) { + if (len > 0) { + mlen = mp->b_datap->db_lim - mp->b_wptr; + if (mlen > 0) { + if (mlen > len) + mlen = len; + bcopy((char *)bp, (char *)mp->b_wptr, mlen); + bp += mlen; + len -= mlen; + mp->b_wptr += mlen; +#ifdef STRUIO_IP +# if SOLARIS2 < 10 + mp->b_datap->db_struiolim = mp->b_wptr; +# endif + mp->b_datap->db_struioflag &= ~STRUIO_IP; +#endif + } + } + + if (len > 0) { + m = allocb(len, BPRI_MED); + if (m != NULL) { + bcopy((char *)bp, (char *)m->b_wptr, len); + m->b_band = mp->b_band; + m->b_wptr += len; + linkb(mp, m); + } + } + } +} diff --git a/SunOS5/pkginfo b/SunOS5/pkginfo new file mode 100644 index 0000000000000..d6b689cd13e20 --- /dev/null +++ b/SunOS5/pkginfo @@ -0,0 +1,18 @@ +CLASSES=none save restore +BASEDIR=/ +TZ=EST +PATH=/sbin:/usr/sbin:/usr/bin:/usr/sadm/install/bin +PKG=ipf +NAME=IP Filter +ARCH=ARCH_updated_by_sed_when_package_is_built +VERSION=5.1.2 +CATEGORY=system +DESC=This package contains tools for building a firewall +VENDOR=Darren Reed +HOTLINE= +EMAIL=darrenr@pobox.com +VSTOCK= +PSTAMP= +PKGINST=ipf +PKGSAV=/var/sadm/pkg/ipf/save +INSTDATE= diff --git a/SunOS5/postinstall b/SunOS5/postinstall new file mode 100755 index 0000000000000..b366ade076005 --- /dev/null +++ b/SunOS5/postinstall @@ -0,0 +1,40 @@ +#!/bin/sh +DEVLINK=${BASEDIR}/etc/devlink.tab +PATH=${PATH}:/sbin:/usr/sbin:/usr/ucb +if [ x"`grep minor=ipf ${DEVLINK}`" = x ] ; then + echo "type=ddi_pseudo;name=ipf;minor=ipf \M0" >> ${DEVLINK} +fi +if [ x"`grep 'minor=ipf ipl' ${DEVLINK}`" = x ] ; then + echo "type=ddi_pseudo;name=ipf;minor=ipf ipl" >> ${DEVLINK} +fi +if [ x"`grep minor=ipnat ${DEVLINK}`" = x ] ; then + echo "type=ddi_pseudo;name=ipf;minor=ipnat \M0" >> ${DEVLINK} +fi +if [ x"`grep minor=ipstate ${DEVLINK}`" = x ] ; then + echo "type=ddi_pseudo;name=ipf;minor=ipstate \M0" >> ${DEVLINK} +fi +if [ x"`grep minor=ipauth ${DEVLINK}`" = x ] ; then + echo "type=ddi_pseudo;name=ipf;minor=ipauth \M0" >> ${DEVLINK} +fi +if [ x"`grep minor=iplookup ${DEVLINK}`" = x ] ; then + echo "type=ddi_pseudo;name=ipf;minor=iplookup \M0" >> ${DEVLINK} +fi +if [ x"`grep minor=ipsync ${DEVLINK}`" = x ] ; then + echo "type=ddi_pseudo;name=ipf;minor=ipsync \M0" >> ${DEVLINK} +fi +if [ x"`grep minor=ipscan ${DEVLINK}`" = x ] ; then + echo "type=ddi_pseudo;name=ipf;minor=ipscan \M0" >> ${DEVLINK} +fi +if [ x${BASEDIR} = x -o x${BASEDIR} = x/ ] ; then + add_drv -m '* 0600 root root' ipf +else + add_drv -m '* 0600 root root' -b ${BASEDIR:-/} ipf +fi +/usr/sbin/devlinks -r ${BASEDIR:-/} +if [ -d /usr/ucb -a -f /usr/ucb/ucblinks ] ; then + /usr/ucb/ucblinks -r ${BASEDIR:-/} +fi +if [ ! -f ${BASEDIR}/etc/opt/ipf/ipf.conf ] ; then + touch ${BASEDIR}/etc/opt/ipf/ipf.conf +fi +exit 0 diff --git a/SunOS5/postremove b/SunOS5/postremove new file mode 100755 index 0000000000000..aa8a38cc57b5f --- /dev/null +++ b/SunOS5/postremove @@ -0,0 +1,12 @@ +#!/bin/sh +# +rem_drv -b ${BASEDIR:-/} ipf +egrep -v 'name=ipf' ${BASEDIR}/etc/devlink.tab > ${BASEDIR}/etc/devlink.tab.new +mv ${BASEDIR}/etc/devlink.tab ${BASEDIR}/etc/devlink.tab.bak +cp -p ${BASEDIR}/etc/devlink.tab.bak ${BASEDIR}/etc/devlink.tab +cp ${BASEDIR}/etc/devlink.tab.new ${BASEDIR}/etc/devlink.tab +/usr/sbin/devlinks -r ${BASEDIR:-/} +if [ -d /usr/ucb -a -f /usr/ucb/ucblinks ] ; then + /usr/ucb/ucblinks -r ${BASEDIR:-/} +fi +exit 0 diff --git a/SunOS5/preremove b/SunOS5/preremove new file mode 100755 index 0000000000000..15d99441c668d --- /dev/null +++ b/SunOS5/preremove @@ -0,0 +1,10 @@ +#!/bin/sh + +pid=`ps -e | awk ' { if ($4 == "ipmon") { print $1; } } ' -` + +while [ "$pid" != "" ] ; do + echo "Stopping ipmon..." + kill $pid + pid=`ps -e | awk ' { if ($4 == "ipmon") { print $1; } } ' -` +done +exit 0 diff --git a/SunOS5/prototype b/SunOS5/prototype new file mode 100644 index 0000000000000..2e44b4a59d029 --- /dev/null +++ b/SunOS5/prototype @@ -0,0 +1,100 @@ +i pkginfo +i depend=../depend +i copyright=../copyright +!default 0755 root root +i postinstall=../postinstall +i preremove=../preremove +i postremove=../postremove +d none /opt +d none /opt/ipf +d none /opt/ipf/man +d none /opt/ipf/man/man1 +d none /opt/ipf/man/man1m +d none /opt/ipf/man/man4 +d none /opt/ipf/man/man5 +d none /opt/ipf/man/man8 +d none /opt/ipf/bin +f none /opt/ipf/bin/ipftest=root/opt/ipf/bin/ipftest +f none /opt/ipf/bin/ipmon=root/opt/ipf/bin/ipmon +f none /opt/ipf/bin/ipsend=root/opt/ipf/bin/ipsend +f none /opt/ipf/bin/ipresend=root/opt/ipf/bin/ipresend +f none /opt/ipf/bin/mkfilters=root/opt/ipf/bin/mkfilters +d none /opt/ipf/examples +d none /var +d none /var/db +d none /var/db/ipf 700 root sys +d none /usr +d none /usr/include +d none /usr/include/ipfilter +d none /usr/kernel +d none /usr/kernel/drv +f none /usr/kernel/drv/ipf=root/usr/kernel/drv/ipf +d none /sbin +s none /sbin/ipfs=../usr/sbin/ipfs +s none /sbin/ipfstat=../usr/sbin/ipfstat +s none /sbin/ipf=../usr/sbin/ipf +s none /sbin/ipnat=../usr/sbin/ipnat +s none /sbin/ippool=../usr/sbin/ippool +f none /usr/sbin/ipfs=root/sbin/ipfs +f none /usr/sbin/ipfstat=root/sbin/ipfstat +f none /usr/sbin/ipf=root/sbin/ipf +f none /usr/sbin/ipnat=root/sbin/ipnat +f none /usr/sbin/ippool=root/sbin/ippool +d none /etc +d none /etc/init.d +f none /etc/init.d/ipfboot=root/etc/init.d/ipfboot +d none /etc/rc2.d +l none /etc/rc2.d/S65ipfboot=/etc/init.d/ipfboot +d none /etc/opt +d none /etc/opt/ipf 755 root sys +!default 0444 root root +f none /opt/ipf/man/man8/ipfstat.8=root/opt/ipf/man/man8/ipfstat.8 +f none /opt/ipf/man/man8/ipmon.8=root/opt/ipf/man/man8/ipmon.8 +f none /opt/ipf/man/man8/ipf.8=root/opt/ipf/man/man8/ipf.8 +f none /opt/ipf/man/man8/ipfs.8=root/opt/ipf/man/man8/ipfs.8 +f none /opt/ipf/man/man8/ipnat.8=root/opt/ipf/man/man8/ipnat.8 +f none /opt/ipf/man/man8/ippool.8=root/opt/ipf/man/man8/ippool.8 +f none /opt/ipf/man/man1/ipftest.1=root/opt/ipf/man/man1/ipftest.1 +f none /opt/ipf/man/man1/mkfilters.1=root/opt/ipf/man/man1/mkfilters.1 +f none /opt/ipf/man/man4/ipf.4=root/opt/ipf/man/man4/ipf.4 +f none /opt/ipf/man/man4/ipl.4=root/opt/ipf/man/man4/ipl.4 +f none /opt/ipf/man/man4/ipnat.4=root/opt/ipf/man/man4/ipnat.4 +f none /opt/ipf/man/man5/ipf.5=root/opt/ipf/man/man5/ipf.5 +f none /opt/ipf/man/man5/ipnat.5=root/opt/ipf/man/man5/ipnat.5 +f none /opt/ipf/man/man5/ippool.5=root/opt/ipf/man/man5/ippool.5 +f none /usr/kernel/drv/ipf.conf=root/usr/kernel/drv/ipf.conf +f none /usr/include/ipfilter/ip_fil.h=root/usr/include/ipfilter/ip_fil.h +f none /usr/include/ipfilter/ip_auth.h=root/usr/include/ipfilter/ip_auth.h +f none /usr/include/ipfilter/ip_compat.h=root/usr/include/ipfilter/ip_compat.h +f none /usr/include/ipfilter/ip_frag.h=root/usr/include/ipfilter/ip_frag.h +f none /usr/include/ipfilter/ip_nat.h=root/usr/include/ipfilter/ip_nat.h +f none /usr/include/ipfilter/ip_proxy.h=root/usr/include/ipfilter/ip_proxy.h +f none /usr/include/ipfilter/ip_state.h=root/usr/include/ipfilter/ip_state.h +f none /usr/include/ipfilter/ip_htable.h=root/usr/include/ipfilter/ip_htable.h +f none /usr/include/ipfilter/ip_dstlist.h=root/usr/include/ipfilter/ip_dstlist.h +f none /usr/include/ipfilter/ip_lookup.h=root/usr/include/ipfilter/ip_lookup.h +f none /usr/include/ipfilter/ip_pool.h=root/usr/include/ipfilter/ip_pool.h +f none /opt/ipf/examples/example.1=root/opt/ipf/examples/example.1 +f none /opt/ipf/examples/example.2=root/opt/ipf/examples/example.2 +f none /opt/ipf/examples/example.3=root/opt/ipf/examples/example.3 +f none /opt/ipf/examples/example.4=root/opt/ipf/examples/example.4 +f none /opt/ipf/examples/example.5=root/opt/ipf/examples/example.5 +f none /opt/ipf/examples/example.6=root/opt/ipf/examples/example.6 +f none /opt/ipf/examples/example.7=root/opt/ipf/examples/example.7 +f none /opt/ipf/examples/example.8=root/opt/ipf/examples/example.8 +f none /opt/ipf/examples/example.9=root/opt/ipf/examples/example.9 +f none /opt/ipf/examples/example.10=root/opt/ipf/examples/example.10 +f none /opt/ipf/examples/example.11=root/opt/ipf/examples/example.11 +f none /opt/ipf/examples/example.12=root/opt/ipf/examples/example.12 +f none /opt/ipf/examples/example.13=root/opt/ipf/examples/example.13 +f none /opt/ipf/examples/example.sr=root/opt/ipf/examples/example.sr +f none /opt/ipf/examples/nat.eg=root/opt/ipf/examples/nat.eg +f none /opt/ipf/examples/server=root/opt/ipf/examples/server +f none /opt/ipf/examples/tcpstate=root/opt/ipf/examples/tcpstate +f none /opt/ipf/examples/BASIC.NAT=root/opt/ipf/examples/BASIC.NAT +f none /opt/ipf/examples/BASIC_1.FW=root/opt/ipf/examples/BASIC_1.FW +f none /opt/ipf/examples/BASIC_2.FW=root/opt/ipf/examples/BASIC_2.FW +f none /opt/ipf/examples/firewall=root/opt/ipf/examples/firewall +f none /opt/ipf/examples/ftp-proxy=root/opt/ipf/examples/ftp-proxy +f none /opt/ipf/examples/ftppxy=root/opt/ipf/examples/ftppxy +f none /opt/ipf/examples/nat-setup=root/opt/ipf/examples/nat-setup diff --git a/SunOS5/prototype32 b/SunOS5/prototype32 new file mode 100644 index 0000000000000..c6a0a4536487c --- /dev/null +++ b/SunOS5/prototype32 @@ -0,0 +1,112 @@ +i pkginfo +i copyright=../copyright +i postinstall=../postinstall +i depend=../depend +!default 0755 root root +#i preinstall=../preinstall +i preremove=../preremove +i postremove=../postremove +d none /opt ? ? ? +d none /opt/ipf +d none /opt/ipf/man +d none /opt/ipf/man/man1 +d none /opt/ipf/man/man1m +d none /opt/ipf/man/man4 +d none /opt/ipf/man/man5 +d none /opt/ipf/man/man8 +d none /opt/ipf/bin +# Moved so we can hardlink against isaexec +s none /opt/ipf/bin/ipmon=../../../usr/sbin/ipmon +f none /opt/ipf/bin/ipftest=root/opt/ipf/bin/sparcv7/ipftest +f none /opt/ipf/bin/ipsend=root/opt/ipf/bin/sparcv7/ipsend +f none /opt/ipf/bin/ipresend=root/opt/ipf/bin/sparcv7/ipresend +f none /opt/ipf/bin/mkfilters=root/opt/ipf/bin/sparcv7/mkfilters +d none /opt/ipf/examples +d none /var ? ? ? +d none /var/db 700 root sys +d none /var/db/ipf 700 root sys +d none /usr ? ? ? +d none /usr/include ? ? ? +d none /usr/include/ipfilter 755 root bin +d none /usr/kernel ? ? ? +d none /usr/kernel/drv ? ? ? +f none /usr/kernel/drv/ipf=root/usr/kernel/drv/sparcv7/ipf +d none /sbin ? ? ? +# Moved so we can hardlink against isaexec +s none /sbin/ipfs=../usr/sbin/ipfs +s none /sbin/ipfstat=../usr/sbin/ipfstat +s none /sbin/ipf=../usr/sbin/ipf +s none /sbin/ipnat=../usr/sbin/ipnat +s none /sbin/ippool=../usr/sbin/ippool +l none /usr/sbin/ipfs=../../usr/lib/isaexec +l none /usr/sbin/ipfstat=../../usr/lib/isaexec +l none /usr/sbin/ipf=../../usr/lib/isaexec +l none /usr/sbin/ipnat=../../usr/lib/isaexec +l none /usr/sbin/ippool=../../usr/lib/isaexec +l none /usr/sbin/ipmon=../../usr/lib/isaexec +d none /usr/sbin ? ? ? +d none /usr/sbin/sparcv7 ? ? ? +f none /usr/sbin/sparcv7/ipfs=root/sbin/sparcv7/ipfs +f none /usr/sbin/sparcv7/ipfstat=root/sbin/sparcv7/ipfstat +f none /usr/sbin/sparcv7/ipf=root/sbin/sparcv7/ipf +f none /usr/sbin/sparcv7/ipnat=root/sbin/sparcv7/ipnat +f none /usr/sbin/sparcv7/ippool=root/sbin/sparcv7/ippool +f none /usr/sbin/sparcv7/ipmon=root/opt/ipf/bin/sparcv7/ipmon +d none /etc ? ? ? +d none /etc/init.d ? ? ? +f none /etc/init.d/ipfboot=root/etc/init.d/ipfboot +d none /etc/rc2.d ? ? ? +l none /etc/rc2.d/S65ipfboot=/etc/init.d/ipfboot +d none /etc/opt ? ? ? +d none /etc/opt/ipf 755 root sys +!default 0444 root root +f none /opt/ipf/man/man8/ipfstat.8=root/opt/ipf/man/man8/ipfstat.8 +f none /opt/ipf/man/man8/ipmon.8=root/opt/ipf/man/man8/ipmon.8 +f none /opt/ipf/man/man8/ipf.8=root/opt/ipf/man/man8/ipf.8 +f none /opt/ipf/man/man8/ipfs.8=root/opt/ipf/man/man8/ipfs.8 +f none /opt/ipf/man/man8/ipnat.8=root/opt/ipf/man/man8/ipnat.8 +f none /opt/ipf/man/man8/ippool.8=root/opt/ipf/man/man8/ippool.8 +f none /opt/ipf/man/man1/ipftest.1=root/opt/ipf/man/man1/ipftest.1 +f none /opt/ipf/man/man1/mkfilters.1=root/opt/ipf/man/man1/mkfilters.1 +f none /opt/ipf/man/man4/ipf.4=root/opt/ipf/man/man4/ipf.4 +f none /opt/ipf/man/man4/ipl.4=root/opt/ipf/man/man4/ipl.4 +f none /opt/ipf/man/man4/ipnat.4=root/opt/ipf/man/man4/ipnat.4 +f none /opt/ipf/man/man5/ipf.5=root/opt/ipf/man/man5/ipf.5 +f none /opt/ipf/man/man5/ipnat.5=root/opt/ipf/man/man5/ipnat.5 +f none /opt/ipf/man/man5/ippool.5=root/opt/ipf/man/man5/ippool.5 +f none /usr/kernel/drv/ipf.conf=root/usr/kernel/drv/ipf.conf +f none /usr/include/ipfilter/ip_fil.h=root/usr/include/ipfilter/ip_fil.h +f none /usr/include/ipfilter/ip_auth.h=root/usr/include/ipfilter/ip_auth.h +f none /usr/include/ipfilter/ip_compat.h=root/usr/include/ipfilter/ip_compat.h +f none /usr/include/ipfilter/ip_frag.h=root/usr/include/ipfilter/ip_frag.h +f none /usr/include/ipfilter/ip_htable.h=root/usr/include/ipfilter/ip_htable.h +f none /usr/include/ipfilter/ip_dstlist.h=root/usr/include/ipfilter/ip_dstlist.h +f none /usr/include/ipfilter/ip_lookup.h=root/usr/include/ipfilter/ip_lookup.h +f none /usr/include/ipfilter/ip_nat.h=root/usr/include/ipfilter/ip_nat.h +f none /usr/include/ipfilter/ip_pool.h=root/usr/include/ipfilter/ip_pool.h +f none /usr/include/ipfilter/ip_proxy.h=root/usr/include/ipfilter/ip_proxy.h +f none /usr/include/ipfilter/ip_state.h=root/usr/include/ipfilter/ip_state.h +f none /opt/ipf/examples/example.1=root/opt/ipf/examples/example.1 +f none /opt/ipf/examples/example.2=root/opt/ipf/examples/example.2 +f none /opt/ipf/examples/example.3=root/opt/ipf/examples/example.3 +f none /opt/ipf/examples/example.4=root/opt/ipf/examples/example.4 +f none /opt/ipf/examples/example.5=root/opt/ipf/examples/example.5 +f none /opt/ipf/examples/example.6=root/opt/ipf/examples/example.6 +f none /opt/ipf/examples/example.7=root/opt/ipf/examples/example.7 +f none /opt/ipf/examples/example.8=root/opt/ipf/examples/example.8 +f none /opt/ipf/examples/example.9=root/opt/ipf/examples/example.9 +f none /opt/ipf/examples/example.10=root/opt/ipf/examples/example.10 +f none /opt/ipf/examples/example.11=root/opt/ipf/examples/example.11 +f none /opt/ipf/examples/example.12=root/opt/ipf/examples/example.12 +f none /opt/ipf/examples/example.13=root/opt/ipf/examples/example.13 +f none /opt/ipf/examples/example.sr=root/opt/ipf/examples/example.sr +f none /opt/ipf/examples/nat.eg=root/opt/ipf/examples/nat.eg +f none /opt/ipf/examples/server=root/opt/ipf/examples/server +f none /opt/ipf/examples/tcpstate=root/opt/ipf/examples/tcpstate +f none /opt/ipf/examples/BASIC.NAT=root/opt/ipf/examples/BASIC.NAT +f none /opt/ipf/examples/BASIC_1.FW=root/opt/ipf/examples/BASIC_1.FW +f none /opt/ipf/examples/BASIC_2.FW=root/opt/ipf/examples/BASIC_2.FW +f none /opt/ipf/examples/firewall=root/opt/ipf/examples/firewall +f none /opt/ipf/examples/ftp-proxy=root/opt/ipf/examples/ftp-proxy +f none /opt/ipf/examples/ftppxy=root/opt/ipf/examples/ftppxy +f none /opt/ipf/examples/nat-setup=root/opt/ipf/examples/nat-setup diff --git a/SunOS5/prototype64 b/SunOS5/prototype64 new file mode 100644 index 0000000000000..f6db67a50a84e --- /dev/null +++ b/SunOS5/prototype64 @@ -0,0 +1,16 @@ +i pkginfo +i copyright=../copyright +!default 0755 root root +d none /usr ? ? ? +d none /usr/kernel ? ? ? +d none /usr/kernel/drv ? ? ? +d none /usr/kernel/drv/sparcv9 ? ? ? +f none /usr/kernel/drv/sparcv9/ipf=root/usr/kernel/drv/sparcv9/ipf +d none /usr/sbin ? ? ? +d none /usr/sbin/sparcv9 ? ? ? +f none /usr/sbin/sparcv9/ipfstat=root/sbin/sparcv9/ipfstat +f none /usr/sbin/sparcv9/ipf=root/sbin/sparcv9/ipf +f none /usr/sbin/sparcv9/ipfs=root/sbin/sparcv9/ipfs +f none /usr/sbin/sparcv9/ipnat=root/sbin/sparcv9/ipnat +f none /usr/sbin/sparcv9/ippool=root/sbin/sparcv9/ippool +f none /usr/sbin/sparcv9/ipmon=root/opt/ipf/bin/sparcv9/ipmon diff --git a/SunOS5/prototype_amd64 b/SunOS5/prototype_amd64 new file mode 100644 index 0000000000000..c741b4d7fee56 --- /dev/null +++ b/SunOS5/prototype_amd64 @@ -0,0 +1,16 @@ +i pkginfo +i copyright=../copyright +!default 0755 root root +d none /usr ? ? ? +d none /usr/kernel ? ? ? +d none /usr/kernel/drv ? ? ? +d none /usr/kernel/drv/amd64 ? ? ? +f none /usr/kernel/drv/amd64/ipf=root/usr/kernel/drv/amd64/ipf +d none /usr/sbin ? ? ? +d none /usr/sbin/amd64 ? ? ? +f none /usr/sbin/amd64/ipfstat=root/sbin/amd64/ipfstat +f none /usr/sbin/amd64/ipf=root/sbin/amd64/ipf +f none /usr/sbin/amd64/ipfs=root/sbin/amd64/ipfs +f none /usr/sbin/amd64/ipnat=root/sbin/amd64/ipnat +f none /usr/sbin/amd64/ippool=root/sbin/amd64/ippool +f none /usr/sbin/amd64/ipmon=root/opt/ipf/bin/amd64/ipmon diff --git a/SunOS5/prototype_ia32 b/SunOS5/prototype_ia32 new file mode 100644 index 0000000000000..a7649385884dd --- /dev/null +++ b/SunOS5/prototype_ia32 @@ -0,0 +1,112 @@ +i pkginfo +i copyright=../copyright +i postinstall=../postinstall +i depend=../depend +!default 0755 root root +#i preinstall=../preinstall +i preremove=../preremove +i postremove=../postremove +d none /opt ? ? ? +d none /opt/ipf +d none /opt/ipf/man +d none /opt/ipf/man/man1 +d none /opt/ipf/man/man1m +d none /opt/ipf/man/man4 +d none /opt/ipf/man/man5 +d none /opt/ipf/man/man8 +d none /opt/ipf/bin +# Moved so we can hardlink against isaexec +s none /opt/ipf/bin/ipmon=../../../usr/sbin/ipmon +f none /opt/ipf/bin/ipftest=root/opt/ipf/bin/i86/ipftest +f none /opt/ipf/bin/ipsend=root/opt/ipf/bin/i86/ipsend +f none /opt/ipf/bin/ipresend=root/opt/ipf/bin/i86/ipresend +f none /opt/ipf/bin/mkfilters=root/opt/ipf/bin/i86/mkfilters +d none /opt/ipf/examples +d none /var ? ? ? +d none /var/db 700 root sys +d none /var/db/ipf 700 root sys +d none /usr ? ? ? +d none /usr/include ? ? ? +d none /usr/include/ipfilter 755 root bin +d none /usr/kernel ? ? ? +d none /usr/kernel/drv ? ? ? +f none /usr/kernel/drv/ipf=root/usr/kernel/drv/i86/ipf +d none /sbin ? ? ? +# Moved so we can hardlink against isaexec +s none /sbin/ipfs=../usr/sbin/ipfs +s none /sbin/ipfstat=../usr/sbin/ipfstat +s none /sbin/ipf=../usr/sbin/ipf +s none /sbin/ipnat=../usr/sbin/ipnat +s none /sbin/ippool=../usr/sbin/ippool +l none /usr/sbin/ipfs=../../usr/lib/isaexec +l none /usr/sbin/ipfstat=../../usr/lib/isaexec +l none /usr/sbin/ipf=../../usr/lib/isaexec +l none /usr/sbin/ipnat=../../usr/lib/isaexec +l none /usr/sbin/ippool=../../usr/lib/isaexec +l none /usr/sbin/ipmon=../../usr/lib/isaexec +d none /usr/sbin ? ? ? +d none /usr/sbin/i86 ? ? ? +f none /usr/sbin/i86/ipfs=root/sbin/i86/ipfs +f none /usr/sbin/i86/ipfstat=root/sbin/i86/ipfstat +f none /usr/sbin/i86/ipf=root/sbin/i86/ipf +f none /usr/sbin/i86/ipnat=root/sbin/i86/ipnat +f none /usr/sbin/i86/ippool=root/sbin/i86/ippool +f none /usr/sbin/i86/ipmon=root/opt/ipf/bin/i86/ipmon +d none /etc ? ? ? +d none /etc/init.d ? ? ? +f none /etc/init.d/ipfboot=root/etc/init.d/ipfboot +d none /etc/rc2.d ? ? ? +l none /etc/rc2.d/S65ipfboot=/etc/init.d/ipfboot +d none /etc/opt ? ? ? +d none /etc/opt/ipf 755 root sys +!default 0444 root root +f none /opt/ipf/man/man8/ipfstat.8=root/opt/ipf/man/man8/ipfstat.8 +f none /opt/ipf/man/man8/ipmon.8=root/opt/ipf/man/man8/ipmon.8 +f none /opt/ipf/man/man8/ipf.8=root/opt/ipf/man/man8/ipf.8 +f none /opt/ipf/man/man8/ipfs.8=root/opt/ipf/man/man8/ipfs.8 +f none /opt/ipf/man/man8/ipnat.8=root/opt/ipf/man/man8/ipnat.8 +f none /opt/ipf/man/man8/ippool.8=root/opt/ipf/man/man8/ippool.8 +f none /opt/ipf/man/man1/ipftest.1=root/opt/ipf/man/man1/ipftest.1 +f none /opt/ipf/man/man1/mkfilters.1=root/opt/ipf/man/man1/mkfilters.1 +f none /opt/ipf/man/man4/ipf.4=root/opt/ipf/man/man4/ipf.4 +f none /opt/ipf/man/man4/ipl.4=root/opt/ipf/man/man4/ipl.4 +f none /opt/ipf/man/man4/ipnat.4=root/opt/ipf/man/man4/ipnat.4 +f none /opt/ipf/man/man5/ipf.5=root/opt/ipf/man/man5/ipf.5 +f none /opt/ipf/man/man5/ipnat.5=root/opt/ipf/man/man5/ipnat.5 +f none /opt/ipf/man/man5/ippool.5=root/opt/ipf/man/man5/ippool.5 +f none /usr/kernel/drv/ipf.conf=root/usr/kernel/drv/ipf.conf +f none /usr/include/ipfilter/ip_fil.h=root/usr/include/ipfilter/ip_fil.h +f none /usr/include/ipfilter/ip_auth.h=root/usr/include/ipfilter/ip_auth.h +f none /usr/include/ipfilter/ip_compat.h=root/usr/include/ipfilter/ip_compat.h +f none /usr/include/ipfilter/ip_frag.h=root/usr/include/ipfilter/ip_frag.h +f none /usr/include/ipfilter/ip_htable.h=root/usr/include/ipfilter/ip_htable.h +f none /usr/include/ipfilter/ip_dstlist.h=root/usr/include/ipfilter/ip_dstlist.h +f none /usr/include/ipfilter/ip_lookup.h=root/usr/include/ipfilter/ip_lookup.h +f none /usr/include/ipfilter/ip_nat.h=root/usr/include/ipfilter/ip_nat.h +f none /usr/include/ipfilter/ip_pool.h=root/usr/include/ipfilter/ip_pool.h +f none /usr/include/ipfilter/ip_proxy.h=root/usr/include/ipfilter/ip_proxy.h +f none /usr/include/ipfilter/ip_state.h=root/usr/include/ipfilter/ip_state.h +f none /opt/ipf/examples/example.1=root/opt/ipf/examples/example.1 +f none /opt/ipf/examples/example.2=root/opt/ipf/examples/example.2 +f none /opt/ipf/examples/example.3=root/opt/ipf/examples/example.3 +f none /opt/ipf/examples/example.4=root/opt/ipf/examples/example.4 +f none /opt/ipf/examples/example.5=root/opt/ipf/examples/example.5 +f none /opt/ipf/examples/example.6=root/opt/ipf/examples/example.6 +f none /opt/ipf/examples/example.7=root/opt/ipf/examples/example.7 +f none /opt/ipf/examples/example.8=root/opt/ipf/examples/example.8 +f none /opt/ipf/examples/example.9=root/opt/ipf/examples/example.9 +f none /opt/ipf/examples/example.10=root/opt/ipf/examples/example.10 +f none /opt/ipf/examples/example.11=root/opt/ipf/examples/example.11 +f none /opt/ipf/examples/example.12=root/opt/ipf/examples/example.12 +f none /opt/ipf/examples/example.13=root/opt/ipf/examples/example.13 +f none /opt/ipf/examples/example.sr=root/opt/ipf/examples/example.sr +f none /opt/ipf/examples/nat.eg=root/opt/ipf/examples/nat.eg +f none /opt/ipf/examples/server=root/opt/ipf/examples/server +f none /opt/ipf/examples/tcpstate=root/opt/ipf/examples/tcpstate +f none /opt/ipf/examples/BASIC.NAT=root/opt/ipf/examples/BASIC.NAT +f none /opt/ipf/examples/BASIC_1.FW=root/opt/ipf/examples/BASIC_1.FW +f none /opt/ipf/examples/BASIC_2.FW=root/opt/ipf/examples/BASIC_2.FW +f none /opt/ipf/examples/firewall=root/opt/ipf/examples/firewall +f none /opt/ipf/examples/ftp-proxy=root/opt/ipf/examples/ftp-proxy +f none /opt/ipf/examples/ftppxy=root/opt/ipf/examples/ftppxy +f none /opt/ipf/examples/nat-setup=root/opt/ipf/examples/nat-setup diff --git a/SunOS5/replace b/SunOS5/replace new file mode 100755 index 0000000000000..e903894ce769c --- /dev/null +++ b/SunOS5/replace @@ -0,0 +1,137 @@ +#!/bin/ksh +SBIN=/usr/sbin +debug=echo +undo=0 + +update() { + echo "UPDATE $1 $2 $3" + base=$1 + dir=$2 + file=$3 + Z=$IFS + IFS=: + set $file + if [[ -z $2 ]] ; then + o=$1 + n=$1 + else + o=$1 + n=$2 + fi + set $dir + sdir=$1 + ddir=$2 + IFS=$Z + + if [[ -z ${sdir} && ! -d ${base}/${ddir} ]] ; then + ddir= + fi + + sprog=${cpudir}/${sdir}/${n} + dprog=${base}/${ddir}/${o} + + if [[ $undo -eq 0 ]] ; then + if [[ -d ${base}/${ddir} ]] ; then + if [[ ! -f ${dprog}.dist ]] ; then + $debug /bin/mv ${dprog} ${dprog}.dist + $debug /bin/cp -p ${dprog}.dist ${dprog} + fi + $debug /bin/cp ${sprog} ${dprog} + else + links=$(/bin/ls -dl ${dprog} | awk ' { print $2; } ' -) + if [[ $links -eq 1 ]] ; then + if [[ ! -f ${dprog}.dist ]] ; then + $debug /bin/mv ${dprog} ${dprog}.dist + $debug /bin/cp -p ${dprog}.dist ${dprog} + fi + $debug /bin/cp ${sprog} ${dprog} + fi + fi + else + if [[ -f ${dprog}.dist ]] ; then + $debug /bin/mv -f ${dprog}.dist ${dprog} + fi + fi +} + +while [[ $# -gt 0 ]] ; do + case $1 in + undo) + undo=1 + ;; + -f) + debug= + ;; + -d) + debug=echo + ;; + esac + shift +done + +case $(pwd) in +*/SunOS5) + ;; +*/SunOS5/*) + exit 1 + ;; +*) + cd SunOS5 + ;; +esac +cpu=`uname -p` +cpudir=${cpu}-`uname -r` + +if [[ -d ${cpudir}/amd64 ]] ; then + big=amd64 +fi +if [[ -d ${cpudir}/sparcv9 ]] ; then + big=sparcv9 +fi +if [[ -d ${cpudir}/i86 ]] ; then + small=i86 +fi +if [[ -d ${cpudir}/sparc ]] ; then + small=sparc +fi +echo "$cpudir.$big.$small." + +if [[ -n ${big} ]] ; then + for i in ipf:ipf.exe ipfs ipfstat ipmon ipnat ippool; do + update $SBIN ${big}:${big} $i + done + update /usr/lib/ipf ${big}:${big} ipftest + update /usr/kernel/drv ${big}:${big} ipf +fi +if [[ -n ${small} ]] ; then + for i in ipf:ipf.exe ipfs ipfstat ipmon ipnat ippool; do + update $SBIN ${small}:${small} $i + done + update /usr/lib/ipf ${small}:${small} ipftest + update /usr/kernel/drv "${small}:" ipf +fi +if [[ -z ${small} && -z ${big} ]] ; then + if [[ -z ${small} ]] ; then + case ${cpu} in + i386) + small=i86 + ;; + sparc) + small=sparc + ;; + esac + fi + for i in ipf:ipf.exe ipfs ipfstat ipmon ipnat ippool; do + update $SBIN :${small} $i + done + update /usr/lib/ipf :${small} ipftest + update /usr/kernel/drv :${small} ipf +fi + +cpudir=.. +for i in ip_compat.h ip_fil.h ipl.h ip_nat.h ip_state.h ip_sync.h ip_scan.h \ + ip_pool.h ip_lookup.h; do + update /usr/include/netinet : $i + update /usr/sfw/lib/gcc/i386-pc-solaris2.10/3.4.3/include/netinet/ : $i +done +exit 0 diff --git a/SunOS5/solinstall b/SunOS5/solinstall new file mode 100755 index 0000000000000..ccf968804d8ea --- /dev/null +++ b/SunOS5/solinstall @@ -0,0 +1,48 @@ +#!/bin/csh -f +# +echo "This script should not be used" +# +exit 0 +# +set dir=`pwd` +umask 077 +if ( $dir =~ */SunOS5 ) cd .. +echo "Creating directory /opt/ipf" +mkdir -p /opt/ipf +echo "Copying files to /opt/ipf..." +cp rules/example.sr /opt/ipf/ipf.rules.eg +cp -p SunOS5/ipfboot /opt/ipf/ipfboot +cp -p SunOS5/ipf.conf /opt/ipf/ipf.conf +cp SunOS5/ipf /opt/ipf/ipf.lkm +echo "Copying ipf and ipf.conf to /usr/kernel/drv"... +cp SunOS5/ipf /usr/kernel/drv/ipf +cp SunOS5/ipf.conf /usr/kernel/drv/ipf.conf +echo "Running add_drv..." +add_drv -m '* 0600 root root' ipf +sync +echo "Installing ipf bootstrap into /etc/init.d/ipfboot...." +cp -p SunOS5/ipfboot /etc/init.d/ipfboot +echo "linking to /etc/rc1.d/S90ipfboot...." +ln /etc/init.d/ipfboot /etc/rc1.d/S90ipfboot +echo "linking to /etc/rcS.d/S90ipfboot." +ln /etc/init.d/ipfboot /etc/rcS.d/S90ipfboot +echo "installing ipf into /sbin and /opt/ipf" +/bin/cp SunOS5/ipf.exe /sbin/ipf +strip /sbin/ipf +chmod 711 /sbin/ipf +/bin/cp SunOS5/ipf.exe /opt/ipf/ipf +strip /opt/ipf/ipf +chmod 711 /opt/ipf/ipf +echo "Adding /dev/ipf to /etc/devlink.tab" +if ( x"`grep name=ipf /etc/devlink.tab`" == x) then + echo "type=ddi_pseudo;name=ipf;minor=ipf \M0" >>/etc/devlink.tab +endif +if ( x"`grep name=ipnat /etc/devlink.tab`" == x) then + echo "type=ddi_pseudo;name=ipnat;minor=ipnat \M0" >>/etc/devlink.tab +endif +if ( x"`grep name=ipstate /etc/devlink.tab`" == x) then + echo "type=ddi_pseudo;name=ipstate;minor=ipstate \M0" >>/etc/devlink.tab +endif +echo "Running devlinks..." +/usr/sbin/devlinks +/usr/ucb/ucblinks diff --git a/SunOS5/uninstall b/SunOS5/uninstall new file mode 100755 index 0000000000000..c53026f070f38 --- /dev/null +++ b/SunOS5/uninstall @@ -0,0 +1,13 @@ +#!/bin/csh -f +# +set dir=`pwd` +umask 077 +if ( $dir =~ */Solaris ) cd .. +/bin/rm -f /usr/kernel/drv/ipf.conf +/bin/rm -f /usr/kernel/drv/ipf +(rem_drv ipf) +sync +/bin/rm -f /etc/rc1.d/S06ipfboot +/bin/rm -f /etc/rcS.d/S06ipfboot +/bin/rm -f /sbin/ipf +/bin/rm -rf /opt/ipf diff --git a/UPGRADE_NOTICE b/UPGRADE_NOTICE deleted file mode 100644 index 8b4476072b274..0000000000000 --- a/UPGRADE_NOTICE +++ /dev/null @@ -1,10 +0,0 @@ - -NOTE: To all those upgrading from versions prior to 3.2.11 who used NAT - AND setup ACL's to allow untranslated address through from outside, - - THIS HAS BEEN FIXED - - so your ACL's will now be `broken'. Please correct your ACL's to - match the the untranslated addresses (the way it was meant to work). - -Darren diff --git a/WhatsNew50.txt b/WhatsNew50.txt new file mode 100644 index 0000000000000..adbf0a99b4e03 --- /dev/null +++ b/WhatsNew50.txt @@ -0,0 +1,83 @@ +What's new in 5.1 +================= + +General +------- +* all of the tuneables can now be set at any time, not just whilst disabled + or prior to loading rules; + +* group identifiers may now be a number or name (universal); + +* man pages rewritten + +* tunables can now be set via ipf.conf; + +Logging +------- +* ipmon.conf can now be used to generate SNMPv1 and SNMPv2 traps using + information from log entries from the kernel; + +NAT changes +----------- +* DNS proxy for the kernel that can block queries based on domain names; + +* FTP proxy can be configured to limit data connections to one or many + connections per client; + +* NAT on IPv6 is now supported; + +* rewrite command allows changing both the source and destination address + in a single NAT rule; + +* simple encapsulation can now be configured with ipnat.conf, + +* TFTP proxy now included; + +Packet Filtering +---------------- +* acceptance of ICMP packets for "keep state" rules can be refined through + the use of filtering rules; + +* alternative form for writing rules using simple filtering expressions; + +* CIPSO headers now recognised and analysed for filtering on DOI; + +* comments can now be a part of a rule and loaded into the kernel and + thus displayed with ipfstat; + +* decapsulation rules allow filtering on inner headers, providing they + are not encrypted; + +* interface names, aside from that the packet is on, can be present in + filter rules; + +* internally now a single list of filter rules, there is no longer an + IPv4 and IPv6 list; + +* rules can now be added with an expiration time, allowing for their + automatic removal after some period of time; + +* single file, ipf.conf, can now be used for both IPv4 and IPv6 rules; + +* stateful filtering now allows for limits to be placed on the number + of distinct hosts allowed per rule; + +Pools +----- +* addresses added to a pool via the command line (only!) can be given + an expiration timeout; + +* destination lists are a new type of address pool, primarily for use with + NAT rdr rules, supporting newer algorithms for target selection; + +* raw whois information saved to a file can be used to populate a pool; + +Solaris +------- +* support for use in zones with exclusive IP instances fully supported. + +Tools +----- +* use of matching expressions allows for refining what is displayed or + flushed; + diff --git a/arc4random.c b/arc4random.c new file mode 100644 index 0000000000000..04b0797c78f83 --- /dev/null +++ b/arc4random.c @@ -0,0 +1,277 @@ +/*- + * THE BEER-WARE LICENSE + * + * <dan@FreeBSD.ORG> wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you + * think this stuff is worth it, you can buy me a beer in return. + * + * Dan Moschuk + */ +#if !defined(SOLARIS2) && !defined(__osf__) +# include <sys/cdefs.h> +#endif + +#include <sys/types.h> +#include <sys/param.h> +#ifdef __FreeBSD__ +# include <sys/kernel.h> +#endif +#if !defined(__osf__) +# include <sys/random.h> +#endif +#ifdef __FreeBSD__ +# include <sys/libkern.h> +#endif +#include <sys/lock.h> +#ifndef __osf__ +# include <sys/mutex.h> +#endif +#include <sys/time.h> + +#if defined(SOLARIS2) && (SOLARIS2 < 9) +# include <netinet/in_systm.h> +#endif +#include <sys/socket.h> +#include <net/if.h> +#ifdef __osf__ +# include <net/route.h> +#endif +#include <netinet/in.h> +#include <netinet/ip.h> +#include "netinet/ip_compat.h" +#ifdef HAS_SYS_MD5_H +# include <sys/md5.h> +#else +# include "md5.h" +#endif + +#ifdef NEED_LOCAL_RAND +#if !defined(__GNUC__) +# define __inline +#endif + +#define ARC4_RESEED_BYTES 65536 +#define ARC4_RESEED_SECONDS 300 +#define ARC4_KEYBYTES (256 / 8) + +static u_int8_t arc4_i, arc4_j; +static int arc4_numruns = 0; +static u_int8_t arc4_sbox[256]; +static time_t arc4_t_reseed; +static ipfmutex_t arc4_mtx; +static MD5_CTX md5ctx; + +static u_int8_t arc4_randbyte(void); +static int ipf_read_random(void *dest, int length); + +static __inline void +arc4_swap(u_int8_t *a, u_int8_t *b) +{ + u_int8_t c; + + c = *a; + *a = *b; + *b = c; +} + +/* + * Stir our S-box. + */ +static void +arc4_randomstir (void) +{ + u_int8_t key[256]; + int r, n; + struct timeval tv_now; + + /* + * XXX read_random() returns unsafe numbers if the entropy + * device is not loaded -- MarkM. + */ + r = ipf_read_random(key, ARC4_KEYBYTES); + GETKTIME(&tv_now); + MUTEX_ENTER(&arc4_mtx); + /* If r == 0 || -1, just use what was on the stack. */ + if (r > 0) { + for (n = r; n < sizeof(key); n++) + key[n] = key[n % r]; + } + + for (n = 0; n < 256; n++) { + arc4_j = (arc4_j + arc4_sbox[n] + key[n]) % 256; + arc4_swap(&arc4_sbox[n], &arc4_sbox[arc4_j]); + } + + /* Reset for next reseed cycle. */ + arc4_t_reseed = tv_now.tv_sec + ARC4_RESEED_SECONDS; + arc4_numruns = 0; + + /* + * Throw away the first N words of output, as suggested in the + * paper "Weaknesses in the Key Scheduling Algorithm of RC4" + * by Fluher, Mantin, and Shamir. (N = 256 in our case.) + */ + for (n = 0; n < 256*4; n++) + arc4_randbyte(); + MUTEX_EXIT(&arc4_mtx); +} + +/* + * Initialize our S-box to its beginning defaults. + */ +static void +arc4_init(void) +{ + int n; + + MD5Init(&md5ctx); + + MUTEX_INIT(&arc4_mtx, "arc4_mtx"); + arc4_i = arc4_j = 0; + for (n = 0; n < 256; n++) + arc4_sbox[n] = (u_int8_t) n; + + arc4_t_reseed = 0; +} + + +/* + * Generate a random byte. + */ +static u_int8_t +arc4_randbyte(void) +{ + u_int8_t arc4_t; + + arc4_i = (arc4_i + 1) % 256; + arc4_j = (arc4_j + arc4_sbox[arc4_i]) % 256; + + arc4_swap(&arc4_sbox[arc4_i], &arc4_sbox[arc4_j]); + + arc4_t = (arc4_sbox[arc4_i] + arc4_sbox[arc4_j]) % 256; + return arc4_sbox[arc4_t]; +} + +/* + * MPSAFE + */ +void +arc4rand(void *ptr, u_int len, int reseed) +{ + u_int8_t *p; + struct timeval tv; + + GETKTIME(&tv); + if (reseed || + (arc4_numruns > ARC4_RESEED_BYTES) || + (tv.tv_sec > arc4_t_reseed)) + arc4_randomstir(); + + MUTEX_ENTER(&arc4_mtx); + arc4_numruns += len; + p = ptr; + while (len--) + *p++ = arc4_randbyte(); + MUTEX_EXIT(&arc4_mtx); +} + +uint32_t +ipf_random(void) +{ + uint32_t ret; + + arc4rand(&ret, sizeof ret, 0); + return ret; +} + + +static u_char pot[ARC4_RESEED_BYTES]; +static u_char *pothead = pot, *pottail = pot; +static int inpot = 0; + +/* + * This is not very strong, and this is understood, but the aim isn't to + * be cryptographically strong - it is just to make up something that is + * pseudo random. + */ +void +ipf_rand_push(void *src, int length) +{ + static int arc4_inited = 0; + u_char *nsrc; + int mylen; + + if (arc4_inited == 0) { + arc4_init(); + arc4_inited = 1; + } + + if (length < 64) { + MD5Update(&md5ctx, src, length); + return; + } + + nsrc = src; + mylen = length; + +#if defined(_SYS_MD5_H) && defined(SOLARIS2) +# define buf buf_un.buf8 +#endif + MUTEX_ENTER(&arc4_mtx); + while ((mylen > 64) && (sizeof(pot) - inpot > sizeof(md5ctx.buf))) { + MD5Update(&md5ctx, nsrc, 64); + mylen -= 64; + nsrc += 64; + if (pottail + sizeof(md5ctx.buf) > pot + sizeof(pot)) { + int left, numbytes; + + numbytes = pot + sizeof(pot) - pottail; + bcopy(md5ctx.buf, pottail, numbytes); + left = sizeof(md5ctx.buf) - numbytes; + pottail = pot; + bcopy(md5ctx.buf + sizeof(md5ctx.buf) - left, + pottail, left); + pottail += left; + } else { + bcopy(md5ctx.buf, pottail, sizeof(md5ctx.buf)); + pottail += sizeof(md5ctx.buf); + } + inpot += 64; + } + MUTEX_EXIT(&arc4_mtx); +#if defined(_SYS_MD5_H) && defined(SOLARIS2) +# undef buf +#endif +} + + +static int +ipf_read_random(void *dest, int length) +{ + if (length > inpot) + return 0; + + MUTEX_ENTER(&arc4_mtx); + if (pothead + length > pot + sizeof(pot)) { + int left, numbytes; + + left = length; + numbytes = pot + sizeof(pot) - pothead; + bcopy(pothead, dest, numbytes); + left -= numbytes; + pothead = pot; + bcopy(pothead, dest + length - left, left); + pothead += left; + } else { + bcopy(pothead, dest, length); + pothead += length; + } + inpot -= length; + if (inpot == 0) + pothead = pottail = pot; + MUTEX_EXIT(&arc4_mtx); + + return length; +} + +#endif /* NEED_LOCAL_RAND */ diff --git a/bpf-ipf.h b/bpf-ipf.h deleted file mode 100644 index 544455e5ff391..0000000000000 --- a/bpf-ipf.h +++ /dev/null @@ -1,450 +0,0 @@ -/*- - * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from the Stanford/CMU enet packet filter, - * (net/enet.c) distributed as part of 4.3BSD, and code contributed - * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence - * Berkeley Laboratory. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)bpf.h 7.1 (Berkeley) 5/7/91 - * - * @(#) $Header: /devel/CVS/IP-Filter/bpf-ipf.h,v 2.1 2002/10/26 12:14:26 darrenr Exp $ (LBL) - */ - -#ifndef BPF_MAJOR_VERSION - -#ifdef __cplusplus -extern "C" { -#endif - -/* BSD style release date */ -#define BPF_RELEASE 199606 - -typedef int bpf_int32; -typedef u_int bpf_u_int32; - -/* - * Alignment macros. BPF_WORDALIGN rounds up to the next - * even multiple of BPF_ALIGNMENT. - */ -#ifndef __NetBSD__ -#define BPF_ALIGNMENT sizeof(bpf_int32) -#else -#define BPF_ALIGNMENT sizeof(long) -#endif -#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1)) - -#define BPF_MAXINSNS 512 -#define BPF_MAXBUFSIZE 0x8000 -#define BPF_MINBUFSIZE 32 - -/* - * Structure for BIOCSETF. - */ -struct bpf_program { - u_int bf_len; - struct bpf_insn *bf_insns; -}; - -/* - * Struct returned by BIOCGSTATS. - */ -struct bpf_stat { - u_int bs_recv; /* number of packets received */ - u_int bs_drop; /* number of packets dropped */ -}; - -/* - * Struct return by BIOCVERSION. This represents the version number of - * the filter language described by the instruction encodings below. - * bpf understands a program iff kernel_major == filter_major && - * kernel_minor >= filter_minor, that is, if the value returned by the - * running kernel has the same major number and a minor number equal - * equal to or less than the filter being downloaded. Otherwise, the - * results are undefined, meaning an error may be returned or packets - * may be accepted haphazardly. - * It has nothing to do with the source code version. - */ -struct bpf_version { - u_short bv_major; - u_short bv_minor; -}; -/* Current version number of filter architecture. */ -#define BPF_MAJOR_VERSION 1 -#define BPF_MINOR_VERSION 1 - -/* - * BPF ioctls - * - * The first set is for compatibility with Sun's pcc style - * header files. If your using gcc, we assume that you - * have run fixincludes so the latter set should work. - */ -#if (defined(sun) || defined(ibm032)) && !defined(__GNUC__) -#define BIOCGBLEN _IOR(B,102, u_int) -#define BIOCSBLEN _IOWR(B,102, u_int) -#define BIOCSETF _IOW(B,103, struct bpf_program) -#define BIOCFLUSH _IO(B,104) -#define BIOCPROMISC _IO(B,105) -#define BIOCGDLT _IOR(B,106, u_int) -#define BIOCGETIF _IOR(B,107, struct ifreq) -#define BIOCSETIF _IOW(B,108, struct ifreq) -#define BIOCSRTIMEOUT _IOW(B,109, struct timeval) -#define BIOCGRTIMEOUT _IOR(B,110, struct timeval) -#define BIOCGSTATS _IOR(B,111, struct bpf_stat) -#define BIOCIMMEDIATE _IOW(B,112, u_int) -#define BIOCVERSION _IOR(B,113, struct bpf_version) -#define BIOCSTCPF _IOW(B,114, struct bpf_program) -#define BIOCSUDPF _IOW(B,115, struct bpf_program) -#else -#define BIOCGBLEN _IOR('B',102, u_int) -#define BIOCSBLEN _IOWR('B',102, u_int) -#define BIOCSETF _IOW('B',103, struct bpf_program) -#define BIOCFLUSH _IO('B',104) -#define BIOCPROMISC _IO('B',105) -#define BIOCGDLT _IOR('B',106, u_int) -#define BIOCGETIF _IOR('B',107, struct ifreq) -#define BIOCSETIF _IOW('B',108, struct ifreq) -#define BIOCSRTIMEOUT _IOW('B',109, struct timeval) -#define BIOCGRTIMEOUT _IOR('B',110, struct timeval) -#define BIOCGSTATS _IOR('B',111, struct bpf_stat) -#define BIOCIMMEDIATE _IOW('B',112, u_int) -#define BIOCVERSION _IOR('B',113, struct bpf_version) -#define BIOCSTCPF _IOW('B',114, struct bpf_program) -#define BIOCSUDPF _IOW('B',115, struct bpf_program) -#endif - -/* - * Structure prepended to each packet. - */ -struct bpf_hdr { - struct timeval bh_tstamp; /* time stamp */ - bpf_u_int32 bh_caplen; /* length of captured portion */ - bpf_u_int32 bh_datalen; /* original length of packet */ - u_short bh_hdrlen; /* length of bpf header (this struct - plus alignment padding) */ -}; -/* - * Because the structure above is not a multiple of 4 bytes, some compilers - * will insist on inserting padding; hence, sizeof(struct bpf_hdr) won't work. - * Only the kernel needs to know about it; applications use bh_hdrlen. - */ -#if defined(KERNEL) || defined(_KERNEL) -#define SIZEOF_BPF_HDR 18 -#endif - -/* - * Data-link level type codes. - */ - -/* - * These are the types that are the same on all platforms; on other - * platforms, a <net/bpf.h> should be supplied that defines the additional - * DLT_* codes appropriately for that platform (the BSDs, for example, - * should not just pick up this version of "bpf.h"; they should also define - * the additional DLT_* codes used by their kernels, as well as the values - * defined here - and, if the values they use for particular DLT_ types - * differ from those here, they should use their values, not the ones - * here). - */ -#define DLT_NULL 0 /* no link-layer encapsulation */ -#define DLT_EN10MB 1 /* Ethernet (10Mb) */ -#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */ -#define DLT_AX25 3 /* Amateur Radio AX.25 */ -#define DLT_PRONET 4 /* Proteon ProNET Token Ring */ -#define DLT_CHAOS 5 /* Chaos */ -#define DLT_IEEE802 6 /* IEEE 802 Networks */ -#define DLT_ARCNET 7 /* ARCNET */ -#define DLT_SLIP 8 /* Serial Line IP */ -#define DLT_PPP 9 /* Point-to-point Protocol */ -#define DLT_FDDI 10 /* FDDI */ - -/* - * These are values from the traditional libpcap "bpf.h". - * Ports of this to particular platforms should replace these definitions - * with the ones appropriate to that platform, if the values are - * different on that platform. - */ -#define DLT_ATM_RFC1483 11 /* LLC/SNAP encapsulated atm */ -#define DLT_RAW 12 /* raw IP */ - -/* - * These are values from BSD/OS's "bpf.h". - * These are not the same as the values from the traditional libpcap - * "bpf.h"; however, these values shouldn't be generated by any - * OS other than BSD/OS, so the correct values to use here are the - * BSD/OS values. - * - * Platforms that have already assigned these values to other - * DLT_ codes, however, should give these codes the values - * from that platform, so that programs that use these codes will - * continue to compile - even though they won't correctly read - * files of these types. - */ -#ifdef __NetBSD__ -#ifndef DLT_SLIP_BSDOS -#define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */ -#define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */ -#endif -#else -#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */ -#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */ -#endif - -#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */ - -/* - * These values are defined by NetBSD; other platforms should refrain from - * using them for other purposes, so that NetBSD savefiles with link - * types of 50 or 51 can be read as this type on all platforms. - */ -#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */ -#define DLT_PPP_ETHER 51 /* PPP over Ethernet */ - -/* - * Values between 100 and 103 are used in capture file headers as - * link-layer types corresponding to DLT_ types that differ - * between platforms; don't use those values for new DLT_ new types. - */ - -/* - * This value was defined by libpcap 0.5; platforms that have defined - * it with a different value should define it here with that value - - * a link type of 104 in a save file will be mapped to DLT_C_HDLC, - * whatever value that happens to be, so programs will correctly - * handle files with that link type regardless of the value of - * DLT_C_HDLC. - * - * The name DLT_C_HDLC was used by BSD/OS; we use that name for source - * compatibility with programs written for BSD/OS. - * - * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well, - * for source compatibility with programs written for libpcap 0.5. - */ -#define DLT_C_HDLC 104 /* Cisco HDLC */ -#define DLT_CHDLC DLT_C_HDLC - -#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */ - -/* - * Values between 106 and 107 are used in capture file headers as - * link-layer types corresponding to DLT_ types that might differ - * between platforms; don't use those values for new DLT_ new types. - */ - -/* - * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except - * that the AF_ type in the link-layer header is in network byte order. - * - * OpenBSD defines it as 12, but that collides with DLT_RAW, so we - * define it as 108 here. If OpenBSD picks up this file, it should - * define DLT_LOOP as 12 in its version, as per the comment above - - * and should not use 108 as a DLT_ value. - */ -#define DLT_LOOP 108 - -/* - * Values between 109 and 112 are used in capture file headers as - * link-layer types corresponding to DLT_ types that might differ - * between platforms; don't use those values for new DLT_ types - * other than the corresponding DLT_ types. - */ - -/* - * This is for Linux cooked sockets. - */ -#define DLT_LINUX_SLL 113 - -/* - * Apple LocalTalk hardware. - */ -#define DLT_LTALK 114 - -/* - * Acorn Econet. - */ -#define DLT_ECONET 115 - -/* - * Reserved for use with OpenBSD ipfilter. - */ -#define DLT_IPFILTER 116 - -/* - * Reserved for use in capture-file headers as a link-layer type - * corresponding to OpenBSD DLT_PFLOG; DLT_PFLOG is 17 in OpenBSD, - * but that's DLT_LANE8023 in SuSE 6.3, so we can't use 17 for it - * in capture-file headers. - */ -#define DLT_PFLOG 117 - -/* - * Registered for Cisco-internal use. - */ -#define DLT_CISCO_IOS 118 - -/* - * Reserved for 802.11 cards using the Prism II chips, with a link-layer - * header including Prism monitor mode information plus an 802.11 - * header. - */ -#define DLT_PRISM_HEADER 119 - -/* - * Reserved for Aironet 802.11 cards, with an Aironet link-layer header - * (see Doug Ambrisko's FreeBSD patches). - */ -#define DLT_AIRONET_HEADER 120 - -/* - * Reserved for Siemens HiPath HDLC. - */ -#define DLT_HHDLC 121 - -/* - * Reserved for RFC 2625 IP-over-Fibre Channel, as per a request from - * Don Lee <donlee@cray.com>. - * - * This is not for use with raw Fibre Channel, where the link-layer - * header starts with a Fibre Channel frame header; it's for IP-over-FC, - * where the link-layer header starts with an RFC 2625 Network_Header - * field. - */ -#define DLT_IP_OVER_FC 122 - -/* - * The instruction encodings. - */ -/* instruction classes */ -#define BPF_CLASS(code) ((code) & 0x07) -#define BPF_LD 0x00 -#define BPF_LDX 0x01 -#define BPF_ST 0x02 -#define BPF_STX 0x03 -#define BPF_ALU 0x04 -#define BPF_JMP 0x05 -#define BPF_RET 0x06 -#define BPF_MISC 0x07 - -/* ld/ldx fields */ -#define BPF_SIZE(code) ((code) & 0x18) -#define BPF_W 0x00 -#define BPF_H 0x08 -#define BPF_B 0x10 -#define BPF_MODE(code) ((code) & 0xe0) -#define BPF_IMM 0x00 -#define BPF_ABS 0x20 -#define BPF_IND 0x40 -#define BPF_MEM 0x60 -#define BPF_LEN 0x80 -#define BPF_MSH 0xa0 - -/* alu/jmp fields */ -#define BPF_OP(code) ((code) & 0xf0) -#define BPF_ADD 0x00 -#define BPF_SUB 0x10 -#define BPF_MUL 0x20 -#define BPF_DIV 0x30 -#define BPF_OR 0x40 -#define BPF_AND 0x50 -#define BPF_LSH 0x60 -#define BPF_RSH 0x70 -#define BPF_NEG 0x80 -#define BPF_JA 0x00 -#define BPF_JEQ 0x10 -#define BPF_JGT 0x20 -#define BPF_JGE 0x30 -#define BPF_JSET 0x40 -#define BPF_SRC(code) ((code) & 0x08) -#define BPF_K 0x00 -#define BPF_X 0x08 - -/* ret - BPF_K and BPF_X also apply */ -#define BPF_RVAL(code) ((code) & 0x18) -#define BPF_A 0x10 - -/* misc */ -#define BPF_MISCOP(code) ((code) & 0xf8) -#define BPF_TAX 0x00 -#define BPF_TXA 0x80 - -/* - * The instruction data structure. - */ -struct bpf_insn { - u_short code; - u_char jt; - u_char jf; - bpf_int32 k; -}; - -/* - * Macros for insn array initializers. - */ -#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k } -#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k } - -#if defined(BSD) && (defined(KERNEL) || defined(_KERNEL)) -/* - * Systems based on non-BSD kernels don't have ifnet's (or they don't mean - * anything if it is in <net/if.h>) and won't work like this. - */ -# if __STDC__ -extern void bpf_tap(struct ifnet *, u_char *, u_int); -extern void bpf_mtap(struct ifnet *, struct mbuf *); -extern void bpfattach(struct ifnet *, u_int, u_int); -extern void bpfilterattach(int); -# else -extern void bpf_tap(); -extern void bpf_mtap(); -extern void bpfattach(); -extern void bpfilterattach(); -# endif /* __STDC__ */ -#endif /* BSD && (_KERNEL || KERNEL) */ -#if __STDC__ || defined(__cplusplus) -extern int bpf_validate(struct bpf_insn *, int); -extern u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int); -#else -extern int bpf_validate(); -extern u_int bpf_filter(); -#endif - -/* - * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST). - */ -#define BPF_MEMWORDS 16 - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/bpf.h b/bpf.h deleted file mode 100644 index 715c79a8d173a..0000000000000 --- a/bpf.h +++ /dev/null @@ -1,450 +0,0 @@ -/*- - * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from the Stanford/CMU enet packet filter, - * (net/enet.c) distributed as part of 4.3BSD, and code contributed - * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence - * Berkeley Laboratory. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)bpf.h 7.1 (Berkeley) 5/7/91 - * - * @(#) $Header: /devel/CVS/IP-Filter/Attic/bpf.h,v 1.1.2.1 2002/11/07 13:18:35 darrenr Exp $ (LBL) - */ - -#ifndef BPF_MAJOR_VERSION - -#ifdef __cplusplus -extern "C" { -#endif - -/* BSD style release date */ -#define BPF_RELEASE 199606 - -typedef int bpf_int32; -typedef u_int bpf_u_int32; - -/* - * Alignment macros. BPF_WORDALIGN rounds up to the next - * even multiple of BPF_ALIGNMENT. - */ -#ifndef __NetBSD__ -#define BPF_ALIGNMENT sizeof(bpf_int32) -#else -#define BPF_ALIGNMENT sizeof(long) -#endif -#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1)) - -#define BPF_MAXINSNS 512 -#define BPF_MAXBUFSIZE 0x8000 -#define BPF_MINBUFSIZE 32 - -/* - * Structure for BIOCSETF. - */ -struct bpf_program { - u_int bf_len; - struct bpf_insn *bf_insns; -}; - -/* - * Struct returned by BIOCGSTATS. - */ -struct bpf_stat { - u_int bs_recv; /* number of packets received */ - u_int bs_drop; /* number of packets dropped */ -}; - -/* - * Struct return by BIOCVERSION. This represents the version number of - * the filter language described by the instruction encodings below. - * bpf understands a program iff kernel_major == filter_major && - * kernel_minor >= filter_minor, that is, if the value returned by the - * running kernel has the same major number and a minor number equal - * equal to or less than the filter being downloaded. Otherwise, the - * results are undefined, meaning an error may be returned or packets - * may be accepted haphazardly. - * It has nothing to do with the source code version. - */ -struct bpf_version { - u_short bv_major; - u_short bv_minor; -}; -/* Current version number of filter architecture. */ -#define BPF_MAJOR_VERSION 1 -#define BPF_MINOR_VERSION 1 - -/* - * BPF ioctls - * - * The first set is for compatibility with Sun's pcc style - * header files. If your using gcc, we assume that you - * have run fixincludes so the latter set should work. - */ -#if (defined(sun) || defined(ibm032)) && !defined(__GNUC__) -#define BIOCGBLEN _IOR(B,102, u_int) -#define BIOCSBLEN _IOWR(B,102, u_int) -#define BIOCSETF _IOW(B,103, struct bpf_program) -#define BIOCFLUSH _IO(B,104) -#define BIOCPROMISC _IO(B,105) -#define BIOCGDLT _IOR(B,106, u_int) -#define BIOCGETIF _IOR(B,107, struct ifreq) -#define BIOCSETIF _IOW(B,108, struct ifreq) -#define BIOCSRTIMEOUT _IOW(B,109, struct timeval) -#define BIOCGRTIMEOUT _IOR(B,110, struct timeval) -#define BIOCGSTATS _IOR(B,111, struct bpf_stat) -#define BIOCIMMEDIATE _IOW(B,112, u_int) -#define BIOCVERSION _IOR(B,113, struct bpf_version) -#define BIOCSTCPF _IOW(B,114, struct bpf_program) -#define BIOCSUDPF _IOW(B,115, struct bpf_program) -#else -#define BIOCGBLEN _IOR('B',102, u_int) -#define BIOCSBLEN _IOWR('B',102, u_int) -#define BIOCSETF _IOW('B',103, struct bpf_program) -#define BIOCFLUSH _IO('B',104) -#define BIOCPROMISC _IO('B',105) -#define BIOCGDLT _IOR('B',106, u_int) -#define BIOCGETIF _IOR('B',107, struct ifreq) -#define BIOCSETIF _IOW('B',108, struct ifreq) -#define BIOCSRTIMEOUT _IOW('B',109, struct timeval) -#define BIOCGRTIMEOUT _IOR('B',110, struct timeval) -#define BIOCGSTATS _IOR('B',111, struct bpf_stat) -#define BIOCIMMEDIATE _IOW('B',112, u_int) -#define BIOCVERSION _IOR('B',113, struct bpf_version) -#define BIOCSTCPF _IOW('B',114, struct bpf_program) -#define BIOCSUDPF _IOW('B',115, struct bpf_program) -#endif - -/* - * Structure prepended to each packet. - */ -struct bpf_hdr { - struct timeval bh_tstamp; /* time stamp */ - bpf_u_int32 bh_caplen; /* length of captured portion */ - bpf_u_int32 bh_datalen; /* original length of packet */ - u_short bh_hdrlen; /* length of bpf header (this struct - plus alignment padding) */ -}; -/* - * Because the structure above is not a multiple of 4 bytes, some compilers - * will insist on inserting padding; hence, sizeof(struct bpf_hdr) won't work. - * Only the kernel needs to know about it; applications use bh_hdrlen. - */ -#if defined(KERNEL) || defined(_KERNEL) -#define SIZEOF_BPF_HDR 18 -#endif - -/* - * Data-link level type codes. - */ - -/* - * These are the types that are the same on all platforms; on other - * platforms, a <net/bpf.h> should be supplied that defines the additional - * DLT_* codes appropriately for that platform (the BSDs, for example, - * should not just pick up this version of "bpf.h"; they should also define - * the additional DLT_* codes used by their kernels, as well as the values - * defined here - and, if the values they use for particular DLT_ types - * differ from those here, they should use their values, not the ones - * here). - */ -#define DLT_NULL 0 /* no link-layer encapsulation */ -#define DLT_EN10MB 1 /* Ethernet (10Mb) */ -#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */ -#define DLT_AX25 3 /* Amateur Radio AX.25 */ -#define DLT_PRONET 4 /* Proteon ProNET Token Ring */ -#define DLT_CHAOS 5 /* Chaos */ -#define DLT_IEEE802 6 /* IEEE 802 Networks */ -#define DLT_ARCNET 7 /* ARCNET */ -#define DLT_SLIP 8 /* Serial Line IP */ -#define DLT_PPP 9 /* Point-to-point Protocol */ -#define DLT_FDDI 10 /* FDDI */ - -/* - * These are values from the traditional libpcap "bpf.h". - * Ports of this to particular platforms should replace these definitions - * with the ones appropriate to that platform, if the values are - * different on that platform. - */ -#define DLT_ATM_RFC1483 11 /* LLC/SNAP encapsulated atm */ -#define DLT_RAW 12 /* raw IP */ - -/* - * These are values from BSD/OS's "bpf.h". - * These are not the same as the values from the traditional libpcap - * "bpf.h"; however, these values shouldn't be generated by any - * OS other than BSD/OS, so the correct values to use here are the - * BSD/OS values. - * - * Platforms that have already assigned these values to other - * DLT_ codes, however, should give these codes the values - * from that platform, so that programs that use these codes will - * continue to compile - even though they won't correctly read - * files of these types. - */ -#ifdef __NetBSD__ -#ifndef DLT_SLIP_BSDOS -#define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */ -#define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */ -#endif -#else -#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */ -#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */ -#endif - -#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */ - -/* - * These values are defined by NetBSD; other platforms should refrain from - * using them for other purposes, so that NetBSD savefiles with link - * types of 50 or 51 can be read as this type on all platforms. - */ -#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */ -#define DLT_PPP_ETHER 51 /* PPP over Ethernet */ - -/* - * Values between 100 and 103 are used in capture file headers as - * link-layer types corresponding to DLT_ types that differ - * between platforms; don't use those values for new DLT_ new types. - */ - -/* - * This value was defined by libpcap 0.5; platforms that have defined - * it with a different value should define it here with that value - - * a link type of 104 in a save file will be mapped to DLT_C_HDLC, - * whatever value that happens to be, so programs will correctly - * handle files with that link type regardless of the value of - * DLT_C_HDLC. - * - * The name DLT_C_HDLC was used by BSD/OS; we use that name for source - * compatibility with programs written for BSD/OS. - * - * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well, - * for source compatibility with programs written for libpcap 0.5. - */ -#define DLT_C_HDLC 104 /* Cisco HDLC */ -#define DLT_CHDLC DLT_C_HDLC - -#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */ - -/* - * Values between 106 and 107 are used in capture file headers as - * link-layer types corresponding to DLT_ types that might differ - * between platforms; don't use those values for new DLT_ new types. - */ - -/* - * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except - * that the AF_ type in the link-layer header is in network byte order. - * - * OpenBSD defines it as 12, but that collides with DLT_RAW, so we - * define it as 108 here. If OpenBSD picks up this file, it should - * define DLT_LOOP as 12 in its version, as per the comment above - - * and should not use 108 as a DLT_ value. - */ -#define DLT_LOOP 108 - -/* - * Values between 109 and 112 are used in capture file headers as - * link-layer types corresponding to DLT_ types that might differ - * between platforms; don't use those values for new DLT_ types - * other than the corresponding DLT_ types. - */ - -/* - * This is for Linux cooked sockets. - */ -#define DLT_LINUX_SLL 113 - -/* - * Apple LocalTalk hardware. - */ -#define DLT_LTALK 114 - -/* - * Acorn Econet. - */ -#define DLT_ECONET 115 - -/* - * Reserved for use with OpenBSD ipfilter. - */ -#define DLT_IPFILTER 116 - -/* - * Reserved for use in capture-file headers as a link-layer type - * corresponding to OpenBSD DLT_PFLOG; DLT_PFLOG is 17 in OpenBSD, - * but that's DLT_LANE8023 in SuSE 6.3, so we can't use 17 for it - * in capture-file headers. - */ -#define DLT_PFLOG 117 - -/* - * Registered for Cisco-internal use. - */ -#define DLT_CISCO_IOS 118 - -/* - * Reserved for 802.11 cards using the Prism II chips, with a link-layer - * header including Prism monitor mode information plus an 802.11 - * header. - */ -#define DLT_PRISM_HEADER 119 - -/* - * Reserved for Aironet 802.11 cards, with an Aironet link-layer header - * (see Doug Ambrisko's FreeBSD patches). - */ -#define DLT_AIRONET_HEADER 120 - -/* - * Reserved for Siemens HiPath HDLC. - */ -#define DLT_HHDLC 121 - -/* - * Reserved for RFC 2625 IP-over-Fibre Channel, as per a request from - * Don Lee <donlee@cray.com>. - * - * This is not for use with raw Fibre Channel, where the link-layer - * header starts with a Fibre Channel frame header; it's for IP-over-FC, - * where the link-layer header starts with an RFC 2625 Network_Header - * field. - */ -#define DLT_IP_OVER_FC 122 - -/* - * The instruction encodings. - */ -/* instruction classes */ -#define BPF_CLASS(code) ((code) & 0x07) -#define BPF_LD 0x00 -#define BPF_LDX 0x01 -#define BPF_ST 0x02 -#define BPF_STX 0x03 -#define BPF_ALU 0x04 -#define BPF_JMP 0x05 -#define BPF_RET 0x06 -#define BPF_MISC 0x07 - -/* ld/ldx fields */ -#define BPF_SIZE(code) ((code) & 0x18) -#define BPF_W 0x00 -#define BPF_H 0x08 -#define BPF_B 0x10 -#define BPF_MODE(code) ((code) & 0xe0) -#define BPF_IMM 0x00 -#define BPF_ABS 0x20 -#define BPF_IND 0x40 -#define BPF_MEM 0x60 -#define BPF_LEN 0x80 -#define BPF_MSH 0xa0 - -/* alu/jmp fields */ -#define BPF_OP(code) ((code) & 0xf0) -#define BPF_ADD 0x00 -#define BPF_SUB 0x10 -#define BPF_MUL 0x20 -#define BPF_DIV 0x30 -#define BPF_OR 0x40 -#define BPF_AND 0x50 -#define BPF_LSH 0x60 -#define BPF_RSH 0x70 -#define BPF_NEG 0x80 -#define BPF_JA 0x00 -#define BPF_JEQ 0x10 -#define BPF_JGT 0x20 -#define BPF_JGE 0x30 -#define BPF_JSET 0x40 -#define BPF_SRC(code) ((code) & 0x08) -#define BPF_K 0x00 -#define BPF_X 0x08 - -/* ret - BPF_K and BPF_X also apply */ -#define BPF_RVAL(code) ((code) & 0x18) -#define BPF_A 0x10 - -/* misc */ -#define BPF_MISCOP(code) ((code) & 0xf8) -#define BPF_TAX 0x00 -#define BPF_TXA 0x80 - -/* - * The instruction data structure. - */ -struct bpf_insn { - u_short code; - u_char jt; - u_char jf; - bpf_int32 k; -}; - -/* - * Macros for insn array initializers. - */ -#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k } -#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k } - -#if defined(BSD) && (defined(KERNEL) || defined(_KERNEL)) -/* - * Systems based on non-BSD kernels don't have ifnet's (or they don't mean - * anything if it is in <net/if.h>) and won't work like this. - */ -# if __STDC__ -extern void bpf_tap(struct ifnet *, u_char *, u_int); -extern void bpf_mtap(struct ifnet *, struct mbuf *); -extern void bpfattach(struct ifnet *, u_int, u_int); -extern void bpfilterattach(int); -# else -extern void bpf_tap(); -extern void bpf_mtap(); -extern void bpfattach(); -extern void bpfilterattach(); -# endif /* __STDC__ */ -#endif /* BSD && (_KERNEL || KERNEL) */ -#if __STDC__ || defined(__cplusplus) -extern int bpf_validate(struct bpf_insn *, int); -extern u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int); -#else -extern int bpf_validate(); -extern u_int bpf_filter(); -#endif - -/* - * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST). - */ -#define BPF_MEMWORDS 16 - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/bpf_filter.c b/bpf_filter.c deleted file mode 100644 index a254f650488a0..0000000000000 --- a/bpf_filter.c +++ /dev/null @@ -1,593 +0,0 @@ -/*- - * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from the Stanford/CMU enet packet filter, - * (net/enet.c) distributed as part of 4.3BSD, and code contributed - * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence - * Berkeley Laboratory. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)bpf.c 7.5 (Berkeley) 7/15/91 - */ - -#if !(defined(lint) || defined(KERNEL) || defined(_KERNEL)) -static const char rcsid[] = - "@(#) $Header: /devel/CVS/IP-Filter/bpf_filter.c,v 2.2.2.3 2006/10/03 11:25:56 darrenr Exp $ (LBL)"; -#endif - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/time.h> -#include <sys/socket.h> - -#include <netinet/in.h> -#include <net/if.h> - -#include "netinet/ip_compat.h" -#include "bpf-ipf.h" - - -#if (defined(__hpux) || SOLARIS) && (defined(_KERNEL) || defined(KERNEL)) -# include <sys/sysmacros.h> -# include <sys/stream.h> -#endif - -#include "pcap-ipf.h" - -#if !defined(KERNEL) && !defined(_KERNEL) -#include <stdlib.h> -#endif - -#define int32 bpf_int32 -#define u_int32 bpf_u_int32 - -static int m_xword __P((mb_t *, int, int *)); -static int m_xhalf __P((mb_t *, int, int *)); - -#ifndef LBL_ALIGN -/* - * XXX - IA-64? If not, this probably won't work on Win64 IA-64 - * systems, unless LBL_ALIGN is defined elsewhere for them. - * XXX - SuperH? If not, this probably won't work on WinCE SuperH - * systems, unless LBL_ALIGN is defined elsewhere for them. - */ -#if defined(sparc) || defined(__sparc__) || defined(mips) || \ - defined(ibm032) || defined(__alpha) || defined(__hpux) || \ - defined(__arm__) -#define LBL_ALIGN -#endif -#endif - -#ifndef LBL_ALIGN - -#define EXTRACT_SHORT(p) ((u_short)ntohs(*(u_short *)p)) -#define EXTRACT_LONG(p) (ntohl(*(u_int32 *)p)) -#else -#define EXTRACT_SHORT(p)\ - ((u_short)\ - ((u_short)*((u_char *)p+0)<<8|\ - (u_short)*((u_char *)p+1)<<0)) -#define EXTRACT_LONG(p)\ - ((u_int32)*((u_char *)p+0)<<24|\ - (u_int32)*((u_char *)p+1)<<16|\ - (u_int32)*((u_char *)p+2)<<8|\ - (u_int32)*((u_char *)p+3)<<0) -#endif - -#define MINDEX(len, _m, _k) \ -{ \ - len = M_LEN(m); \ - while ((_k) >= len) { \ - (_k) -= len; \ - (_m) = (_m)->m_next; \ - if ((_m) == 0) \ - return 0; \ - len = M_LEN(m); \ - } \ -} - -static int -m_xword(m, k, err) - register mb_t *m; - register int k, *err; -{ - register int len; - register u_char *cp, *np; - register mb_t *m0; - - MINDEX(len, m, k); - cp = MTOD(m, u_char *) + k; - if (len - k >= 4) { - *err = 0; - return EXTRACT_LONG(cp); - } - m0 = m->m_next; - if (m0 == 0 || M_LEN(m0) + len - k < 4) - goto bad; - *err = 0; - np = MTOD(m0, u_char *); - switch (len - k) { - - case 1: - return (cp[0] << 24) | (np[0] << 16) | (np[1] << 8) | np[2]; - - case 2: - return (cp[0] << 24) | (cp[1] << 16) | (np[0] << 8) | np[1]; - - default: - return (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | np[0]; - } - bad: - *err = 1; - return 0; -} - -static int -m_xhalf(m, k, err) - register mb_t *m; - register int k, *err; -{ - register int len; - register u_char *cp; - register mb_t *m0; - - MINDEX(len, m, k); - cp = MTOD(m, u_char *) + k; - if (len - k >= 2) { - *err = 0; - return EXTRACT_SHORT(cp); - } - m0 = m->m_next; - if (m0 == 0) - goto bad; - *err = 0; - return (cp[0] << 8) | MTOD(m0, u_char *)[0]; - bad: - *err = 1; - return 0; -} - -/* - * Execute the filter program starting at pc on the packet p - * wirelen is the length of the original packet - * buflen is the amount of data present - * For the kernel, p is assumed to be a pointer to an mbuf if buflen is 0, - * in all other cases, p is a pointer to a buffer and buflen is its size. - */ -u_int -bpf_filter(pc, p, wirelen, buflen) - register struct bpf_insn *pc; - register u_char *p; - u_int wirelen; - register u_int buflen; -{ - register u_int32 A, X; - register int k; - int32 mem[BPF_MEMWORDS]; - mb_t *m, *n; - int merr = 0; /* XXX: GCC */ - int len; - - if (buflen == 0) { - m = (mb_t *)p; - p = MTOD(m, u_char *); - buflen = M_LEN(m); - } else - m = NULL; - - if (pc == 0) - /* - * No filter means accept all. - */ - return (u_int)-1; - A = 0; - X = 0; - --pc; - while (1) { - ++pc; - switch (pc->code) { - - default: - return 0; - case BPF_RET|BPF_K: - return (u_int)pc->k; - - case BPF_RET|BPF_A: - return (u_int)A; - - case BPF_LD|BPF_W|BPF_ABS: - k = pc->k; - if (k + sizeof(int32) > buflen) { - if (m == NULL) - return 0; - A = m_xword(m, k, &merr); - if (merr != 0) - return 0; - continue; - } - A = EXTRACT_LONG(&p[k]); - continue; - - case BPF_LD|BPF_H|BPF_ABS: - k = pc->k; - if (k + sizeof(short) > buflen) { - if (m == NULL) - return 0; - A = m_xhalf(m, k, &merr); - if (merr != 0) - return 0; - continue; - } - A = EXTRACT_SHORT(&p[k]); - continue; - - case BPF_LD|BPF_B|BPF_ABS: - k = pc->k; - if (k >= buflen) { - if (m == NULL) - return 0; - n = m; - MINDEX(len, n, k); - A = MTOD(n, u_char *)[k]; - continue; - } - A = p[k]; - continue; - - case BPF_LD|BPF_W|BPF_LEN: - A = wirelen; - continue; - - case BPF_LDX|BPF_W|BPF_LEN: - X = wirelen; - continue; - - case BPF_LD|BPF_W|BPF_IND: - k = X + pc->k; - if (k + sizeof(int32) > buflen) { - if (m == NULL) - return 0; - A = m_xword(m, k, &merr); - if (merr != 0) - return 0; - continue; - } - A = EXTRACT_LONG(&p[k]); - continue; - - case BPF_LD|BPF_H|BPF_IND: - k = X + pc->k; - if (k + sizeof(short) > buflen) { - if (m == NULL) - return 0; - A = m_xhalf(m, k, &merr); - if (merr != 0) - return 0; - continue; - } - A = EXTRACT_SHORT(&p[k]); - continue; - - case BPF_LD|BPF_B|BPF_IND: - k = X + pc->k; - if (k >= buflen) { - if (m == NULL) - return 0; - n = m; - MINDEX(len, n, k); - A = MTOD(n, u_char *)[k]; - continue; - } - A = p[k]; - continue; - - case BPF_LDX|BPF_MSH|BPF_B: - k = pc->k; - if (k >= buflen) { - if (m == NULL) - return 0; - n = m; - MINDEX(len, n, k); - X = (MTOD(n, char *)[k] & 0xf) << 2; - continue; - } - X = (p[pc->k] & 0xf) << 2; - continue; - - case BPF_LD|BPF_IMM: - A = pc->k; - continue; - - case BPF_LDX|BPF_IMM: - X = pc->k; - continue; - - case BPF_LD|BPF_MEM: - A = mem[pc->k]; - continue; - - case BPF_LDX|BPF_MEM: - X = mem[pc->k]; - continue; - - case BPF_ST: - mem[pc->k] = A; - continue; - - case BPF_STX: - mem[pc->k] = X; - continue; - - case BPF_JMP|BPF_JA: - pc += pc->k; - continue; - - case BPF_JMP|BPF_JGT|BPF_K: - pc += (A > pc->k) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JGE|BPF_K: - pc += (A >= pc->k) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JEQ|BPF_K: - pc += (A == pc->k) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JSET|BPF_K: - pc += (A & pc->k) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JGT|BPF_X: - pc += (A > X) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JGE|BPF_X: - pc += (A >= X) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JEQ|BPF_X: - pc += (A == X) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JSET|BPF_X: - pc += (A & X) ? pc->jt : pc->jf; - continue; - - case BPF_ALU|BPF_ADD|BPF_X: - A += X; - continue; - - case BPF_ALU|BPF_SUB|BPF_X: - A -= X; - continue; - - case BPF_ALU|BPF_MUL|BPF_X: - A *= X; - continue; - - case BPF_ALU|BPF_DIV|BPF_X: - if (X == 0) - return 0; - A /= X; - continue; - - case BPF_ALU|BPF_AND|BPF_X: - A &= X; - continue; - - case BPF_ALU|BPF_OR|BPF_X: - A |= X; - continue; - - case BPF_ALU|BPF_LSH|BPF_X: - A <<= X; - continue; - - case BPF_ALU|BPF_RSH|BPF_X: - A >>= X; - continue; - - case BPF_ALU|BPF_ADD|BPF_K: - A += pc->k; - continue; - - case BPF_ALU|BPF_SUB|BPF_K: - A -= pc->k; - continue; - - case BPF_ALU|BPF_MUL|BPF_K: - A *= pc->k; - continue; - - case BPF_ALU|BPF_DIV|BPF_K: - A /= pc->k; - continue; - - case BPF_ALU|BPF_AND|BPF_K: - A &= pc->k; - continue; - - case BPF_ALU|BPF_OR|BPF_K: - A |= pc->k; - continue; - - case BPF_ALU|BPF_LSH|BPF_K: - A <<= pc->k; - continue; - - case BPF_ALU|BPF_RSH|BPF_K: - A >>= pc->k; - continue; - - case BPF_ALU|BPF_NEG: - A = -A; - continue; - - case BPF_MISC|BPF_TAX: - X = A; - continue; - - case BPF_MISC|BPF_TXA: - A = X; - continue; - } - } -} - - -/* - * Return true if the 'fcode' is a valid filter program. - * The constraints are that each jump be forward and to a valid - * code, that memory accesses are within valid ranges (to the - * extent that this can be checked statically; loads of packet - * data have to be, and are, also checked at run time), and that - * the code terminates with either an accept or reject. - * - * The kernel needs to be able to verify an application's filter code. - * Otherwise, a bogus program could easily crash the system. - */ -int -bpf_validate(f, len) - struct bpf_insn *f; - int len; -{ - u_int i, from; - const struct bpf_insn *p; - - if (len == 0) - return 1; - - if (len < 1 || len > BPF_MAXINSNS) - return 0; - - for (i = 0; i < len; ++i) { - p = &f[i]; - switch (BPF_CLASS(p->code)) { - /* - * Check that memory operations use valid addresses. - */ - case BPF_LD: - case BPF_LDX: - switch (BPF_MODE(p->code)) { - case BPF_IMM: - break; - case BPF_ABS: - case BPF_IND: - case BPF_MSH: - /* - * More strict check with actual packet length - * is done runtime. - */ -#if 0 - if (p->k >= bpf_maxbufsize) - return 0; -#endif - break; - case BPF_MEM: - if (p->k >= BPF_MEMWORDS) - return 0; - break; - case BPF_LEN: - break; - default: - return 0; - } - break; - case BPF_ST: - case BPF_STX: - if (p->k >= BPF_MEMWORDS) - return 0; - break; - case BPF_ALU: - switch (BPF_OP(p->code)) { - case BPF_ADD: - case BPF_SUB: - case BPF_OR: - case BPF_AND: - case BPF_LSH: - case BPF_RSH: - case BPF_NEG: - break; - case BPF_DIV: - /* - * Check for constant division by 0. - */ - if (BPF_RVAL(p->code) == BPF_K && p->k == 0) - return 0; - default: - return 0; - } - break; - case BPF_JMP: - /* - * Check that jumps are within the code block, - * and that unconditional branches don't go - * backwards as a result of an overflow. - * Unconditional branches have a 32-bit offset, - * so they could overflow; we check to make - * sure they don't. Conditional branches have - * an 8-bit offset, and the from address is <= - * BPF_MAXINSNS, and we assume that BPF_MAXINSNS - * is sufficiently small that adding 255 to it - * won't overflow. - * - * We know that len is <= BPF_MAXINSNS, and we - * assume that BPF_MAXINSNS is < the maximum size - * of a u_int, so that i + 1 doesn't overflow. - */ - from = i + 1; - switch (BPF_OP(p->code)) { - case BPF_JA: - if (from + p->k < from || from + p->k >= len) - return 0; - break; - case BPF_JEQ: - case BPF_JGT: - case BPF_JGE: - case BPF_JSET: - if (from + p->jt >= len || from + p->jf >= len) - return 0; - break; - default: - return 0; - } - break; - case BPF_RET: - break; - case BPF_MISC: - break; - default: - return 0; - } - } - return BPF_CLASS(f[len - 1].code) == BPF_RET; -} diff --git a/buildlinux b/buildlinux deleted file mode 100755 index 7ce043fc6e6aa..0000000000000 --- a/buildlinux +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh -LINUX=`uname -r | perl -e '$_=<>;@F=split(/\./);printf "%02d%02d\n",$F[0],$F[1];';` - -case ${LINUX} in - 0200) - make linuxrev "LINUXK=-DLINUX=${LINUX}" - ;; - 0201) - make linuxrev "LINUXK=-DLINUX=${LINUX}" - ;; - *) - echo "invalid linux version $LINUX" - exit 1; - ;; -esac -exit 0 diff --git a/buildsunos b/buildsunos index 5e857e77953cc..ce42e39f750ec 100755 --- a/buildsunos +++ b/buildsunos @@ -3,7 +3,7 @@ if [ ! -f netinet/done ] ; then echo "Do NOT run this script directly, do 'make solaris'!" exit 1 fi -# Id: buildsunos,v 2.20 2004/02/07 18:08:46 darrenr Exp +# $Id$ : rev=`uname -r | sed -e 's/^\([^\.]*\)\..*/\1/'` if [ -d /usr/ccs/bin ] ; then @@ -11,8 +11,21 @@ if [ -d /usr/ccs/bin ] ; then export PATH fi +testcc() +{ + if echo '' | $1 -E - >/dev/null 2>&1 ; then + CC=$1 + return 0 + fi + return 1 +} + +if [ -f /usr/include/sys/neti.h ] ; then + INST='-DINSTANCES=1' +fi + if [ $rev = 5 ] ; then - if [ ! -d ../pfil ] ; then + if [ ! -f /usr/include/sys/neti.h -a ! -d ../pfil ] ; then cat << __EOF__ pfil directory in .. missing, please download pfil package and extract that into the parent directory. @@ -42,43 +55,79 @@ __EOF__ # Default C compiler is "cc", override on make commandline # if [ "x$CC" = "x" ] ; then - if echo '' | cc -E - >/dev/null 2>&1 ; then - CC=cc - else - if echo '' | gcc -E - >/dev/null 2>&1 ; then - CC=gcc - else - echo "No working compiler found" + testcc cc + if [ $? -ne 0 ] ; then + testcc gcc + if [ $? -ne 0 ] ; then + echo 'No working compiler found' exit 1 fi fi + else + testcc $CC + if [ $? -ne 0 ] ; then + case $CC in + *gcc*) + echo 'No working compiler found' + exit 1 + ;; + *) + testcc gcc + if [ $? -ne 0 ] ; then + echo 'No working compiler found' + exit 1 + fi + ;; + esac + fi fi - v=`echo '__GNUC__' | 2>&1 ${CC} -E - | 2>&1 sed -ne '/^[0-9]* *$/p'` + v=`echo '__GNUC__' 2>&1 | ${CC} -E - 2>&1 | sed -ne '/^[0-9]* *$/p'` if [ x$v != x ] ; then CC=gcc fi case "$CC" in *gcc*) # gcc - XARCH32="" - XARCH64="-m64 -mcmodel=medlow" + XARCH32_i386="" + XARCH32_sparc="" + XARCH64_sparc="-m64 -mcmodel=medlow" + XARCH64_i386="-m64 -mcmodel=kernel -mno-red-zone -ffreestanding" ;; *) # Sun C - XARCH32="-Xa -xildoff" - XARCH64="$XARCH32 -xarch=v9 -xchip=ultra -dalign -xcode=abs32" + XARCH32_i386="-Xa -xildoff" + XARCH32_sparc="-Xa -xildoff -xarch=v8 -xmemalign=8s" + if [ `cc -xarch=amd64 -xarch=v9 2>&1 | grep -c deprec` -eq 1 ] ; then + XARCH64_sparc="-Xa -xildoff -m64 -xmemalign=8s" + XARCH64_i386="$XARCH32 -m64" + else + XARCH64_sparc="-Xa -xildoff -xarch=v9 -xchip=ultra -xmemalign=8s -xcode=abs32" + XARCH64_i386="$XARCH32 -xarch=amd64 -xcode=abs32" + fi ;; esac + XARCH32="`eval echo '$XARCH32_'$cpu`" + XARCH64="`eval echo '$XARCH64_'$cpu`" + OBJ32_sparc=sparcv7 + OBJ64_sparc=sparcv9 + OBJ32_i386=i86 + OBJ64_i386=amd64 export CC ISABITS=32 - OBJ32=sparcv7 + OBJ32=`eval echo '$OBJ32_'$cpu` + OBJ64=`eval echo '$OBJ64_'$cpu` ARCHINC32= - OBJ64=sparcv9 - ARCHINC64="-I/usr/include/v9" + ARCHINC64_sparc="-I/usr/include/v9" + ARCHINC64_i386="" + ARCHINC64="`eval echo '$ARCHINC_'$cpu`" - if [ $solrev -ge 7 ] && /bin/optisa sparcv8plus > /dev/null + if [ $solrev -ge 10 ] && /bin/optisa sparcv8plus amd64 > /dev/null + then + # Introducing amd64 + BUILDBOTH=true + elif [ $solrev -ge 7 ] && /bin/optisa sparcv8plus > /dev/null then # We run Solaris 7+ on 64 bit capable hardware. BUILDBOTH=true @@ -143,11 +192,11 @@ fi # Default $MAKE to make : ${MAKE:=make} -if [ $cpu = i386 ] ; then +if [ $cpu = i386 -a $solrev -lt 10 ] ; then if [ -n "$BPFILTER" ] ; then BPF="BPFILTER=./$BPFILTER" fi - $MAKE $MAKEFLAGS ${1+"$@"} sunos5x86 SOLARIS2="-DSOLARIS2=$solrev" CPU= CPUDIR=${cpudir} CC="$CC $XARCH32" XARCH="$XARCH32" ARCHINC="$ARCHINC32" BITS=32 OBJ=. $BPF + $MAKE $MAKEFLAGS ${1+"$@"} sunos5 SOLARIS2="-DSOLARIS2=$solrev" CPU= CPUDIR=${cpudir} CC="$CC $XARCH32" XARCH="$XARCH32" ARCHINC="$ARCHINC32" BITS=32 OBJ=. $BPF exit $? fi if [ x$solrev = x ] ; then @@ -156,13 +205,14 @@ if [ x$solrev = x ] ; then fi for b in $ISABITS do - echo build $b bit binaries. - for v in OBJ ARCHINC XARCH - do - eval $v=\"\$$v$b\" - done - if [ -n "$BPFILTER" ] ; then - BPF="BPFILTER=$OBJ/$BPFILTER" - fi - $MAKE $MAKEFLAGS ${1+"$@"} sunos$rev SOLARIS2="-DSOLARIS2=$solrev" CPU= CPUDIR=${cpudir} CC="$CC $XARCH" XARCH="$XARCH" ARCHINC="$ARCHINC" BITS=$b OBJ=$OBJ $BPF || exit $? + echo build $b bit binaries. + for v in OBJ ARCHINC XARCH + do + eval $v=\"\$$v$b\" + done + eval B=\"\$OBJ${b}_`uname -p`\" + if [ -n "$BPFILTER" ] ; then + BPF="BPFILTER=$OBJ/$BPFILTER" + fi + $MAKE $MAKEFLAGS ${1+"$@"} sunos$rev SOLARIS2="-DSOLARIS2=$solrev" CPU= CPUDIR=${cpudir} CC="$CC $XARCH" XARCH="$XARCH" INSTANCE="$INST" ARCHINC="$ARCHINC" BITS=$b OBJ=$B $BPF || exit $? done diff --git a/common.c b/common.c deleted file mode 100644 index fa21fc97b5746..0000000000000 --- a/common.c +++ /dev/null @@ -1,610 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - */ -#if defined(__sgi) && (IRIX > 602) -# include <sys/ptimers.h> -#endif -#include <sys/types.h> -#if !defined(__SVR4) && !defined(__svr4__) -#include <strings.h> -#else -#include <sys/byteorder.h> -#endif -#include <sys/param.h> -#include <sys/time.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/tcp.h> -#include <net/if.h> -#if __FreeBSD_version >= 300000 -# include <net/if_var.h> -#endif -#include <stdio.h> -#include <string.h> -#include <limits.h> -#include <stdlib.h> -#include <unistd.h> -#include <stddef.h> -#include <netdb.h> -#include <arpa/nameser.h> -#include <arpa/inet.h> -#include <resolv.h> -#include <ctype.h> -#include <syslog.h> -#include "ip_compat.h" -#include "ip_fil.h" -#include "ipf.h" -#include "facpri.h" - -#if !defined(lint) -static const char sccsid[] = "@(#)parse.c 1.44 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$IPFilter: parse.c,v 2.8 1999/12/28 10:49:46 darrenr Exp $"; -#endif - -extern struct ipopt_names ionames[], secclass[]; -extern int opts; -extern int use_inet6; - - -char *proto = NULL; -char flagset[] = "FSRPAUEC"; -u_char flags[] = { TH_FIN, TH_SYN, TH_RST, TH_PUSH, TH_ACK, TH_URG, - TH_ECN, TH_CWR }; - -void fill6bits __P((int, u_32_t *)); -int count6bits __P((u_32_t *)); - -static char thishost[MAXHOSTNAMELEN]; - - -void initparse() -{ - gethostname(thishost, sizeof(thishost)); - thishost[sizeof(thishost) - 1] = '\0'; -} - - -int genmask(msk, mskp) -char *msk; -u_32_t *mskp; -{ - char *endptr = NULL; -#ifdef USE_INET6 - u_32_t addr; -#endif - int bits; - - if (index(msk, '.') || index(msk, 'x') || index(msk, ':')) { - /* possibly of the form xxx.xxx.xxx.xxx - * or 0xYYYYYYYY */ -#ifdef USE_INET6 - if (use_inet6) { - if (inet_pton(AF_INET6, msk, &addr) != 1) - return -1; - } else -#endif - if (inet_aton(msk, (struct in_addr *)mskp) == 0) - return -1; - } else { - /* - * set x most significant bits - */ - bits = (int)strtol(msk, &endptr, 0); - if ((*endptr != '\0') || - ((bits > 32) && !use_inet6) || (bits < 0) || - ((bits > 128) && use_inet6)) - return -1; - if (use_inet6) - fill6bits(bits, mskp); - else { - if (bits == 0) - *mskp = 0; - else - *mskp = htonl(0xffffffff << (32 - bits)); - } - } - return 0; -} - - - -void fill6bits(bits, msk) -int bits; -u_32_t *msk; -{ - int i; - - for (i = 0; bits >= 32 && i < 4 ; ++i, bits -= 32) - msk[i] = 0xffffffff; - - if (bits > 0 && i < 4) - msk[i++] = htonl(0xffffffff << (32 - bits)); - - while (i < 4) - msk[i++] = 0; -} - - -/* - * returns -1 if neither "hostmask/num" or "hostmask mask addr" are - * found in the line segments, there is an error processing this information, - * or there is an error processing ports information. - */ -int hostmask(seg, sa, msk, pp, cp, tp, linenum) -char ***seg; -u_32_t *sa, *msk; -u_short *pp, *tp; -int *cp; -int linenum; -{ - struct in_addr maskaddr; - char *s; - - /* - * is it possibly hostname/num ? - */ - if ((s = index(**seg, '/')) || - ((s = index(**seg, ':')) && !index(s + 1, ':'))) { - *s++ = '\0'; - if (genmask(s, msk) == -1) { - fprintf(stderr, "%d: bad mask (%s)\n", linenum, s); - return -1; - } - if (hostnum(sa, **seg, linenum) == -1) { - fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg); - return -1; - } - *sa &= *msk; - (*seg)++; - return ports(seg, pp, cp, tp, linenum); - } - - /* - * look for extra segments if "mask" found in right spot - */ - if (*(*seg+1) && *(*seg+2) && !strcasecmp(*(*seg+1), "mask")) { - if (hostnum(sa, **seg, linenum) == -1) { - fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg); - return -1; - } - (*seg)++; - (*seg)++; - if (inet_aton(**seg, &maskaddr) == 0) { - fprintf(stderr, "%d: bad mask (%s)\n", linenum, **seg); - return -1; - } - *msk = maskaddr.s_addr; - (*seg)++; - *sa &= *msk; - return ports(seg, pp, cp, tp, linenum); - } - - if (**seg) { - if (hostnum(sa, **seg, linenum) == -1) { - fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg); - return -1; - } - (*seg)++; - if (use_inet6) { - u_32_t k = 0; - if (sa[0] || sa[1] || sa[2] || sa[3]) - k = 0xffffffff; - msk[0] = msk[1] = msk[2] = msk[3] = k; - } - else - *msk = *sa ? 0xffffffff : 0; - return ports(seg, pp, cp, tp, linenum); - } - fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg); - return -1; -} - -/* - * returns an ip address as a long var as a result of either a DNS lookup or - * straight inet_addr() call - */ -int hostnum(ipa, host, linenum) -u_32_t *ipa; -char *host; -int linenum; -{ - struct hostent *hp; - struct netent *np; - struct in_addr ip; - - if (!strcasecmp("any", host)) - return 0; -#ifdef USE_INET6 - if (use_inet6) { - if (inet_pton(AF_INET6, host, ipa) == 1) - return 0; - else - return -1; - } -#endif - if (isdigit(*host) && inet_aton(host, &ip)) { - *ipa = ip.s_addr; - return 0; - } - - if (!strcasecmp("<thishost>", host)) - host = thishost; - - if (!(hp = gethostbyname(host))) { - if (!(np = getnetbyname(host))) { - fprintf(stderr, "%d: can't resolve hostname: %s\n", - linenum, host); - return -1; - } - *ipa = htonl(np->n_net); - return 0; - } - *ipa = *(u_32_t *)hp->h_addr; - return 0; -} - - -/* - * check for possible presence of the port fields in the line - */ -int ports(seg, pp, cp, tp, linenum) -char ***seg; -u_short *pp, *tp; -int *cp; -int linenum; -{ - int comp = -1; - - if (!*seg || !**seg || !***seg) - return 0; - if (!strcasecmp(**seg, "port") && *(*seg + 1) && *(*seg + 2)) { - (*seg)++; - if (!strcmp(**seg, "=") || !strcasecmp(**seg, "eq")) - comp = FR_EQUAL; - else if (!strcmp(**seg, "!=") || !strcasecmp(**seg, "ne")) - comp = FR_NEQUAL; - else if (!strcmp(**seg, "<") || !strcasecmp(**seg, "lt")) - comp = FR_LESST; - else if (!strcmp(**seg, ">") || !strcasecmp(**seg, "gt")) - comp = FR_GREATERT; - else if (!strcmp(**seg, "<=") || !strcasecmp(**seg, "le")) - comp = FR_LESSTE; - else if (!strcmp(**seg, ">=") || !strcasecmp(**seg, "ge")) - comp = FR_GREATERTE; - else if (isalnum(***seg) && *(*seg + 2)) { - if (portnum(**seg, pp, linenum) == 0) - return -1; - (*seg)++; - if (!strcmp(**seg, "<>")) - comp = FR_OUTRANGE; - else if (!strcmp(**seg, "><")) - comp = FR_INRANGE; - else { - fprintf(stderr, - "%d: unknown range operator (%s)\n", - linenum, **seg); - return -1; - } - (*seg)++; - if (**seg == NULL) { - fprintf(stderr, "%d: missing 2nd port value\n", - linenum); - return -1; - } - if (portnum(**seg, tp, linenum) == 0) - return -1; - } else { - fprintf(stderr, "%d: unknown comparator (%s)\n", - linenum, **seg); - return -1; - } - if (comp != FR_OUTRANGE && comp != FR_INRANGE) { - (*seg)++; - if (portnum(**seg, pp, linenum) == 0) - return -1; - } - *cp = comp; - (*seg)++; - } - return 0; -} - - -/* - * find the port number given by the name, either from getservbyname() or - * straight atoi(). Return 1 on success, 0 on failure - */ -int portnum(name, port, linenum) -char *name; -u_short *port; -int linenum; -{ - struct servent *sp, *sp2; - u_short p1 = 0; - int i; - - if (isdigit(*name)) { - if (ratoi(name, &i, 0, USHRT_MAX)) { - *port = (u_short)i; - return 1; - } - fprintf(stderr, "%d: unknown port \"%s\"\n", linenum, name); - return 0; - } - if (proto != NULL && strcasecmp(proto, "tcp/udp") != 0) { - sp = getservbyname(name, proto); - if (sp) { - *port = ntohs(sp->s_port); - return 1; - } - fprintf(stderr, "%d: unknown service \"%s\".\n", linenum, name); - return 0; - } - sp = getservbyname(name, "tcp"); - if (sp) - p1 = sp->s_port; - sp2 = getservbyname(name, "udp"); - if (!sp || !sp2) { - fprintf(stderr, "%d: unknown tcp/udp service \"%s\".\n", - linenum, name); - return 0; - } - if (p1 != sp2->s_port) { - fprintf(stderr, "%d: %s %d/tcp is a different port to ", - linenum, name, p1); - fprintf(stderr, "%d: %s %d/udp\n", linenum, name, sp->s_port); - return 0; - } - *port = ntohs(p1); - return 1; -} - - -u_char tcp_flags(flgs, mask, linenum) -char *flgs; -u_char *mask; -int linenum; -{ - u_char tcpf = 0, tcpfm = 0, *fp = &tcpf; - char *s, *t; - - if (*flgs == '0') { - s = strchr(flgs, '/'); - if (s) - *s++ = '\0'; - tcpf = strtol(flgs, NULL, 0); - fp = &tcpfm; - } else - s = flgs; - - for (; *s; s++) { - if (*s == '/' && fp == &tcpf) { - fp = &tcpfm; - if (*(s + 1) == '0') - break; - continue; - } - if (!(t = index(flagset, *s))) { - fprintf(stderr, "%d: unknown flag (%c)\n", linenum, *s); - return 0; - } - *fp |= flags[t - flagset]; - } - - if (s && *s == '0') - tcpfm = strtol(s, NULL, 0); - - if (!tcpfm) { - if (tcpf == TH_SYN) - tcpfm = 0xff & ~(TH_ECN|TH_CWR); - else - tcpfm = 0xff & ~(TH_ECN); - } - *mask = tcpfm; - return tcpf; -} - - -/* - * count consecutive 1's in bit mask. If the mask generated by counting - * consecutive 1's is different to that passed, return -1, else return # - * of bits. - */ -int countbits(ip) -u_32_t ip; -{ - u_32_t ipn; - int cnt = 0, i, j; - - ip = ipn = ntohl(ip); - for (i = 32; i; i--, ipn *= 2) - if (ipn & 0x80000000) - cnt++; - else - break; - ipn = 0; - for (i = 32, j = cnt; i; i--, j--) { - ipn *= 2; - if (j > 0) - ipn++; - } - if (ipn == ip) - return cnt; - return -1; -} - - -int count6bits(msk) -u_32_t *msk; -{ - int i = 0, k; - u_32_t j; - - for (k = 3; k >= 0; k--) - if (msk[k] == 0xffffffff) - i += 32; - else { - for (j = msk[k]; j; j <<= 1) - if (j & 0x80000000) - i++; - } - return i; -} - - -char *portname(pr, port) -int pr, port; -{ - static char buf[32]; - struct protoent *p = NULL; - struct servent *sv = NULL, *sv1 = NULL; - - if (pr == -1) { - if ((sv = getservbyport(htons(port), "tcp"))) { - strncpy(buf, sv->s_name, sizeof(buf)-1); - buf[sizeof(buf)-1] = '\0'; - sv1 = getservbyport(htons(port), "udp"); - sv = strncasecmp(buf, sv->s_name, strlen(buf)) ? - NULL : sv1; - } - if (sv) - return buf; - } else if (pr && (p = getprotobynumber(pr))) { - if ((sv = getservbyport(htons(port), p->p_name))) { - strncpy(buf, sv->s_name, sizeof(buf)-1); - buf[sizeof(buf)-1] = '\0'; - return buf; - } - } - - (void) sprintf(buf, "%d", port); - return buf; -} - - -int ratoi(ps, pi, min, max) -char *ps; -int *pi, min, max; -{ - int i; - char *pe; - - i = (int)strtol(ps, &pe, 0); - if (*pe != '\0' || i < min || i > max) - return 0; - *pi = i; - return 1; -} - - -int ratoui(ps, pi, min, max) -char *ps; -u_int *pi, min, max; -{ - u_int i; - char *pe; - - i = (u_int)strtol(ps, &pe, 0); - if (*pe != '\0' || i < min || i > max) - return 0; - *pi = i; - return 1; -} - - -void printhostmask(v, addr, mask) -int v; -u_32_t *addr, *mask; -{ - struct in_addr ipa; - int ones; - -#ifdef USE_INET6 - if (v == 6) { - ones = count6bits(mask); - if (ones == 0 && !addr[0] && !addr[1] && !addr[2] && !addr[3]) - printf("any"); - else { - char ipbuf[64]; - printf("%s/%d", - inet_ntop(AF_INET6, addr, ipbuf, sizeof(ipbuf)), - ones); - } - } - else -#endif - if (!*addr && !*mask) - printf("any"); - else { - ipa.s_addr = *addr; - printf("%s", inet_ntoa(ipa)); - if ((ones = countbits(*mask)) == -1) { - ipa.s_addr = *mask; - printf("/%s", inet_ntoa(ipa)); - } else - printf("/%d", ones); - } -} - - -void printportcmp(pr, frp) -int pr; -frpcmp_t *frp; -{ - static char *pcmp1[] = { "*", "=", "!=", "<", ">", "<=", ">=", - "<>", "><"}; - - if (frp->frp_cmp == FR_INRANGE || frp->frp_cmp == FR_OUTRANGE) - printf(" port %d %s %d", frp->frp_port, - pcmp1[frp->frp_cmp], frp->frp_top); - else - printf(" port %s %s", pcmp1[frp->frp_cmp], - portname(pr, frp->frp_port)); -} - - -void printbuf(buf, len, zend) -char *buf; -int len, zend; -{ - char *s, c; - int i; - - for (s = buf, i = len; i; i--) { - c = *s++; - if (isprint(c)) - putchar(c); - else - printf("\\%03o", c); - if ((c == '\0') && zend) - break; - } -} - - - -char *hostname(v, ip) -int v; -void *ip; -{ -#ifdef USE_INET6 - static char hostbuf[MAXHOSTNAMELEN+1]; -#endif - struct in_addr ipa; - - if (v == 4) { - ipa.s_addr = *(u_32_t *)ip; - return inet_ntoa(ipa); - } -#ifdef USE_INET6 - (void) inet_ntop(AF_INET6, ip, hostbuf, sizeof(hostbuf) - 1); - hostbuf[MAXHOSTNAMELEN] = '\0'; - return hostbuf; -#else - return "IPv6"; -#endif -} diff --git a/etc/etc.sed b/etc/etc.sed deleted file mode 100644 index b14fc74851d7f..0000000000000 --- a/etc/etc.sed +++ /dev/null @@ -1,2 +0,0 @@ - Æ. Ä..'!CVS - protocols diff --git a/etc/protocols b/etc/protocols index 30c5b7647f171..dec8fb9f62325 100644 --- a/etc/protocols +++ b/etc/protocols @@ -101,4 +101,4 @@ any 99 any # private encryption scheme gmtp 100 GMTP # GMTP pim 103 PIM # Protocol Independant Multicast ipcomp 108 IPCOMP # IP Payload Compression Protocol -reserved 255 Reserved # +reserved 255 Reserved # diff --git a/etc/services b/etc/services index d8aa0d5ae2230..ad83348caf26e 100644 --- a/etc/services +++ b/etc/services @@ -228,7 +228,7 @@ qmtp 209/tcp # The Quick Mail Transfer Protocol qmtp 209/udp # The Quick Mail Transfer Protocol anet 212/tcp # ATEXSSTR anet 212/udp # ATEXSSTR -ipx 213/tcp # IPX +ipx 213/tcp # IPX ipx 213/udp # IPX vmpwscs 214/tcp # VM PWSCS vmpwscs 214/udp # VM PWSCS @@ -1104,8 +1104,8 @@ shockwave 1626/tcp # Shockwave shockwave 1626/udp # Shockwave oraclenet8cman 1630/tcp # Oracle Net8 Cman oraclenet8cman 1630/udp # Oracle Net8 Cman -visitview 1631/tcp # Visit view -visitview 1631/udp # Visit view +visitview 1631/tcp # Visit view +visitview 1631/udp # Visit view pammratc 1632/tcp # PAMMRATC pammratc 1632/udp # PAMMRATC pammrpc 1633/tcp # PAMMRPC diff --git a/facpri.c b/facpri.c deleted file mode 100644 index 79afdd214729b..0000000000000 --- a/facpri.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - */ -#include <stdio.h> -#include <string.h> -#include <limits.h> -#include <sys/types.h> -#if !defined(__SVR4) && !defined(__svr4__) -#include <strings.h> -#endif -#include <stdlib.h> -#include <unistd.h> -#include <stddef.h> -#include <syslog.h> -#include "facpri.h" - -#ifndef __STDC__ -# define const -#endif - -#if !defined(lint) -static const char rcsid[] = "@(#)$Id: facpri.c,v 1.3.2.4 2001/07/15 22:06:12 darrenr Exp $"; -#endif - -typedef struct table { - char *name; - int value; -} table_t; - -table_t facs[] = { - { "kern", LOG_KERN }, { "user", LOG_USER }, - { "mail", LOG_MAIL }, { "daemon", LOG_DAEMON }, - { "auth", LOG_AUTH }, { "syslog", LOG_SYSLOG }, - { "lpr", LOG_LPR }, { "news", LOG_NEWS }, - { "uucp", LOG_UUCP }, -#if LOG_CRON == LOG_CRON2 - { "cron2", LOG_CRON1 }, -#else - { "cron", LOG_CRON1 }, -#endif -#ifdef LOG_FTP - { "ftp", LOG_FTP }, -#endif -#ifdef LOG_AUTHPRIV - { "authpriv", LOG_AUTHPRIV }, -#endif -#ifdef LOG_AUDIT - { "audit", LOG_AUDIT }, -#endif -#ifdef LOG_LFMT - { "logalert", LOG_LFMT }, -#endif -#if LOG_CRON == LOG_CRON1 - { "cron", LOG_CRON2 }, -#else - { "cron2", LOG_CRON2 }, -#endif -#ifdef LOG_SECURITY - { "security", LOG_SECURITY }, -#endif - { "local0", LOG_LOCAL0 }, { "local1", LOG_LOCAL1 }, - { "local2", LOG_LOCAL2 }, { "local3", LOG_LOCAL3 }, - { "local4", LOG_LOCAL4 }, { "local5", LOG_LOCAL5 }, - { "local6", LOG_LOCAL6 }, { "local7", LOG_LOCAL7 }, - { NULL, 0 } -}; - - -/* - * map a facility number to its name - */ -char * -fac_toname(facpri) - int facpri; -{ - int i, j, fac; - - fac = facpri & LOG_FACMASK; - j = fac >> 3; - if (j < 24) { - if (facs[j].value == fac) - return facs[j].name; - for (i = 0; facs[i].name; i++) - if (fac == facs[i].value) - return facs[i].name; - } - - return NULL; -} - - -/* - * map a facility name to its number - */ -int -fac_findname(name) - char *name; -{ - int i; - - for (i = 0; facs[i].name; i++) - if (!strcmp(facs[i].name, name)) - return facs[i].value; - return -1; -} - - -table_t pris[] = { - { "emerg", LOG_EMERG }, { "alert", LOG_ALERT }, - { "crit", LOG_CRIT }, { "err", LOG_ERR }, - { "warn", LOG_WARNING }, { "notice", LOG_NOTICE }, - { "info", LOG_INFO }, { "debug", LOG_DEBUG }, - { NULL, 0 } -}; - - -/* - * map a priority name to its number - */ -int -pri_findname(name) - char *name; -{ - int i; - - for (i = 0; pris[i].name; i++) - if (!strcmp(pris[i].name, name)) - return pris[i].value; - return -1; -} - - -/* - * map a priority number to its name - */ -char * -pri_toname(facpri) - int facpri; -{ - int i, pri; - - pri = facpri & LOG_PRIMASK; - if (pris[pri].value == pri) - return pris[pri].name; - for (i = 0; pris[i].name; i++) - if (pri == pris[i].value) - return pris[i].name; - return NULL; -} diff --git a/facpri.h b/facpri.h deleted file mode 100644 index 7b80377d112ed..0000000000000 --- a/facpri.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 1999-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * $Id: facpri.h,v 1.3.2.1 2001/06/26 10:43:11 darrenr Exp $ - */ - -#ifndef __FACPRI_H__ -#define __FACPRI_H__ - -#ifndef __P -# define P_DEF -# ifdef __STDC__ -# define __P(x) x -# else -# define __P(x) () -# endif -#endif - -extern char *fac_toname __P((int)); -extern int fac_findname __P((char *)); - -extern char *pri_toname __P((int)); -extern int pri_findname __P((char *)); - -#ifdef P_DEF -# undef __P -# undef P_DEF -#endif - -#if LOG_CRON == (9<<3) -# define LOG_CRON1 LOG_CRON -# define LOG_CRON2 (15<<3) -#endif -#if LOG_CRON == (15<<3) -# define LOG_CRON1 (9<<3) -# define LOG_CRON2 LOG_CRON -#endif - -#endif /* __FACPRI_H__ */ @@ -1,9 +1,12 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1993-2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. + * + * Copyright 2008 Sun Microsystems. + * + * $Id$ + * */ #if defined(KERNEL) || defined(_KERNEL) # undef KERNEL @@ -15,11 +18,6 @@ #include <sys/types.h> #include <sys/param.h> #include <sys/time.h> -#if defined(__NetBSD__) -# if (NetBSD >= 199905) && !defined(IPFILTER_LKM) && defined(_KERNEL) -# include "opt_ipfilter_log.h" -# endif -#endif #if defined(_KERNEL) && defined(__FreeBSD_version) && \ (__FreeBSD_version >= 220000) # if (__FreeBSD_version >= 400000) @@ -34,7 +32,12 @@ #else # include <sys/ioctl.h> #endif -#include <sys/fcntl.h> +#if (defined(__SVR4) || defined(__svr4__)) && defined(sun) +# include <sys/filio.h> +#endif +#if !defined(_AIX51) +# include <sys/fcntl.h> +#endif #if defined(_KERNEL) # include <sys/systm.h> # include <sys/file.h> @@ -73,28 +76,24 @@ struct file; #ifdef sun # include <net/af.h> #endif -#if !defined(_KERNEL) && defined(__FreeBSD__) -# include "radix_ipf.h" -#endif -#include <net/route.h> #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> -#if !defined(linux) -# include <netinet/ip_var.h> -#endif #if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */ # include <sys/hashing.h> # include <netinet/in_var.h> #endif #include <netinet/tcp.h> -#if !defined(__sgi) || defined(_KERNEL) +#if (!defined(__sgi) && !defined(AIX)) || defined(_KERNEL) # include <netinet/udp.h> # include <netinet/ip_icmp.h> #endif #ifdef __hpux # undef _NET_ROUTE_INCLUDED #endif +#ifdef __osf__ +# undef _RADIX_H_ +#endif #include "netinet/ip_compat.h" #ifdef USE_INET6 # include <netinet/icmp6.h> @@ -102,7 +101,6 @@ struct file; # include <netinet6/in6_var.h> # endif #endif -#include <netinet/tcpip.h> #include "netinet/ip_fil.h" #include "netinet/ip_nat.h" #include "netinet/ip_frag.h" @@ -112,9 +110,8 @@ struct file; #ifdef IPFILTER_SCAN # include "netinet/ip_scan.h" #endif -#ifdef IPFILTER_SYNC -# include "netinet/ip_sync.h" -#endif +#include "netinet/ip_sync.h" +#include "netinet/ip_lookup.h" #include "netinet/ip_pool.h" #include "netinet/ip_htable.h" #ifdef IPFILTER_COMPILED @@ -125,117 +122,101 @@ struct file; #endif #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) # include <sys/malloc.h> -# if defined(_KERNEL) && !defined(IPFILTER_LKM) -# include "opt_ipfilter.h" -# endif #endif #include "netinet/ipl.h" + +#if defined(__NetBSD__) && (__NetBSD_Version__ >= 104230000) +# include <sys/callout.h> +extern struct callout ipf_slowtimer_ch; +#endif +#if defined(__OpenBSD__) +# include <sys/timeout.h> +extern struct timeout ipf_slowtimer_ch; +#endif /* END OF INCLUDES */ #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.243.2.57 2005/03/28 10:47:50 darrenr Exp"; +static const char rcsid[] = "@(#)$Id$"; #endif #ifndef _KERNEL # include "ipf.h" # include "ipt.h" -# include "bpf-ipf.h" extern int opts; - -# define FR_VERBOSE(verb_pr) verbose verb_pr -# define FR_DEBUG(verb_pr) debug verb_pr -#else /* #ifndef _KERNEL */ -# define FR_VERBOSE(verb_pr) -# define FR_DEBUG(verb_pr) +extern int blockreason; #endif /* _KERNEL */ +#define LBUMP(x) softc->x++ +#define LBUMPD(x, y) do { softc->x.y++; DT(y); } while (0) -fr_info_t frcache[2][8]; -struct filterstats frstats[2] = { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 } }; -struct frentry *ipfilter[2][2] = { { NULL, NULL }, { NULL, NULL } }, - *ipfilter6[2][2] = { { NULL, NULL }, { NULL, NULL } }, - *ipacct6[2][2] = { { NULL, NULL }, { NULL, NULL } }, - *ipacct[2][2] = { { NULL, NULL }, { NULL, NULL } }, - *ipnatrules[2][2] = { { NULL, NULL }, { NULL, NULL } }; -struct frgroup *ipfgroups[IPL_LOGSIZE][2]; -char ipfilter_version[] = IPL_VERSION; -int fr_refcnt = 0; -/* - * For fr_running: - * 0 == loading, 1 = running, -1 = disabled, -2 = unloading - */ -int fr_running = 0; -int fr_flags = IPF_LOGGING; -int fr_active = 0; -int fr_control_forwarding = 0; -int fr_update_ipid = 0; -u_short fr_ip_id = 0; -int fr_chksrc = 0; /* causes a system crash if enabled */ -int fr_minttl = 4; -u_long fr_frouteok[2] = {0, 0}; -u_long fr_userifqs = 0; -u_long fr_badcoalesces[2] = {0, 0}; -u_char ipf_iss_secret[32]; -#if defined(IPFILTER_DEFAULT_BLOCK) -int fr_pass = FR_BLOCK|FR_NOMATCH; -#else -int fr_pass = (IPF_DEFAULT_PASS)|FR_NOMATCH; -#endif -int fr_features = 0 -#ifdef IPFILTER_LKM - | IPF_FEAT_LKM -#endif -#ifdef IPFILTER_LOG - | IPF_FEAT_LOG -#endif -#ifdef IPFILTER_LOOKUP - | IPF_FEAT_LOOKUP -#endif -#ifdef IPFILTER_BPF - | IPF_FEAT_BPF -#endif -#ifdef IPFILTER_COMPILED - | IPF_FEAT_COMPILED -#endif -#ifdef IPFILTER_CKSUM - | IPF_FEAT_CKSUM -#endif -#ifdef IPFILTER_SYNC - | IPF_FEAT_SYNC -#endif -#ifdef IPFILTER_SCAN - | IPF_FEAT_SCAN +static INLINE int ipf_check_ipf __P((fr_info_t *, frentry_t *, int)); +static u_32_t ipf_checkcipso __P((fr_info_t *, u_char *, int)); +static u_32_t ipf_checkripso __P((u_char *)); +static u_32_t ipf_decaps __P((fr_info_t *, u_32_t, int)); +#ifdef IPFILTER_LOG +static frentry_t *ipf_dolog __P((fr_info_t *, u_32_t *)); #endif -#ifdef USE_INET6 - | IPF_FEAT_IPV6 +static int ipf_flushlist __P((ipf_main_softc_t *, int *, + frentry_t **)); +static int ipf_flush_groups __P((ipf_main_softc_t *, frgroup_t **, + int)); +static ipfunc_t ipf_findfunc __P((ipfunc_t)); +static void *ipf_findlookup __P((ipf_main_softc_t *, int, + frentry_t *, + i6addr_t *, i6addr_t *)); +static frentry_t *ipf_firewall __P((fr_info_t *, u_32_t *)); +static int ipf_fr_matcharray __P((fr_info_t *, int *)); +static int ipf_frruleiter __P((ipf_main_softc_t *, void *, int, + void *)); +static void ipf_funcfini __P((ipf_main_softc_t *, frentry_t *)); +static int ipf_funcinit __P((ipf_main_softc_t *, frentry_t *)); +static int ipf_geniter __P((ipf_main_softc_t *, ipftoken_t *, + ipfgeniter_t *)); +static void ipf_getstat __P((ipf_main_softc_t *, + struct friostat *, int)); +static int ipf_group_flush __P((ipf_main_softc_t *, frgroup_t *)); +static void ipf_group_free __P((frgroup_t *)); +static int ipf_grpmapfini __P((struct ipf_main_softc_s *, + frentry_t *)); +static int ipf_grpmapinit __P((struct ipf_main_softc_s *, + frentry_t *)); +static frentry_t *ipf_nextrule __P((ipf_main_softc_t *, int, int, + frentry_t *, int)); +static int ipf_portcheck __P((frpcmp_t *, u_32_t)); +static INLINE int ipf_pr_ah __P((fr_info_t *)); +static INLINE void ipf_pr_esp __P((fr_info_t *)); +static INLINE void ipf_pr_gre __P((fr_info_t *)); +static INLINE void ipf_pr_udp __P((fr_info_t *)); +static INLINE void ipf_pr_tcp __P((fr_info_t *)); +static INLINE void ipf_pr_icmp __P((fr_info_t *)); +static INLINE void ipf_pr_ipv4hdr __P((fr_info_t *)); +static INLINE void ipf_pr_short __P((fr_info_t *, int)); +static INLINE int ipf_pr_tcpcommon __P((fr_info_t *)); +static INLINE int ipf_pr_udpcommon __P((fr_info_t *)); +static void ipf_rule_delete __P((ipf_main_softc_t *, frentry_t *f, + int, int)); +static void ipf_rule_expire_insert __P((ipf_main_softc_t *, + frentry_t *, int)); +static int ipf_synclist __P((ipf_main_softc_t *, frentry_t *, + void *)); +static void ipf_token_flush __P((ipf_main_softc_t *)); +static void ipf_token_unlink __P((ipf_main_softc_t *, + ipftoken_t *)); +static ipftuneable_t *ipf_tune_findbyname __P((ipftuneable_t *, + const char *)); +static ipftuneable_t *ipf_tune_findbycookie __P((ipftuneable_t **, void *, + void **)); +static int ipf_updateipid __P((fr_info_t *)); +static int ipf_settimeout __P((struct ipf_main_softc_s *, + struct ipftuneable *, + ipftuneval_t *)); +#if !defined(_KERNEL) || (!defined(__NetBSD__) && !defined(__OpenBSD__) && \ + !defined(__FreeBSD__)) || \ + FREEBSD_LT_REV(501000) || NETBSD_LT_REV(105000000) || \ + OPENBSD_LT_REV(200006) +static int ppsratecheck(struct timeval *, int *, int); #endif - ; - -static INLINE int fr_ipfcheck __P((fr_info_t *, frentry_t *, int)); -static int fr_portcheck __P((frpcmp_t *, u_short *)); -static int frflushlist __P((int, minor_t, int *, frentry_t **)); -static ipfunc_t fr_findfunc __P((ipfunc_t)); -static frentry_t *fr_firewall __P((fr_info_t *, u_32_t *)); -static int fr_funcinit __P((frentry_t *fr)); -static INLINE void frpr_esp __P((fr_info_t *)); -static INLINE void frpr_gre __P((fr_info_t *)); -static INLINE void frpr_udp __P((fr_info_t *)); -static INLINE void frpr_tcp __P((fr_info_t *)); -static INLINE void frpr_icmp __P((fr_info_t *)); -static INLINE void frpr_ipv4hdr __P((fr_info_t *)); -static INLINE int frpr_pullup __P((fr_info_t *, int)); -static INLINE void frpr_short __P((fr_info_t *, int)); -static INLINE void frpr_tcpcommon __P((fr_info_t *)); -static INLINE void frpr_udpcommon __P((fr_info_t *)); -static INLINE int fr_updateipid __P((fr_info_t *)); -#ifdef IPFILTER_LOOKUP -static int fr_grpmapinit __P((frentry_t *fr)); -static INLINE void *fr_resolvelookup __P((u_int, u_int, lookupfunc_t *)); -#endif -static void frsynclist __P((frentry_t *, void *)); -static ipftuneable_t *fr_findtunebyname __P((char *)); -static ipftuneable_t *fr_findtunebycookie __P((void *, void **)); /* @@ -244,7 +225,7 @@ static ipftuneable_t *fr_findtunebycookie __P((void *, void **)); * hand side to allow for binary searching of the array and include a trailer * with a 0 for the bitmask for linear searches to easily find the end with. */ -const struct optlist ipopts[20] = { +static const struct optlist ipopts[20] = { { IPOPT_NOP, 0x000001 }, { IPOPT_RR, 0x000002 }, { IPOPT_ZSU, 0x000004 }, @@ -268,7 +249,7 @@ const struct optlist ipopts[20] = { }; #ifdef USE_INET6 -struct optlist ip6exthdr[] = { +static struct optlist ip6exthdr[] = { { IPPROTO_HOPOPTS, 0x000001 }, { IPPROTO_IPV6, 0x000002 }, { IPPROTO_ROUTING, 0x000004 }, @@ -277,24 +258,15 @@ struct optlist ip6exthdr[] = { { IPPROTO_AH, 0x000020 }, { IPPROTO_NONE, 0x000040 }, { IPPROTO_DSTOPTS, 0x000080 }, + { IPPROTO_MOBILITY, 0x000100 }, { 0, 0 } }; #endif -struct optlist tcpopts[] = { - { TCPOPT_NOP, 0x000001 }, - { TCPOPT_MAXSEG, 0x000002 }, - { TCPOPT_WINDOW, 0x000004 }, - { TCPOPT_SACK_PERMITTED, 0x000008 }, - { TCPOPT_SACK, 0x000010 }, - { TCPOPT_TIMESTAMP, 0x000020 }, - { 0, 0x000000 } -}; - /* * bit values for identifying presence of individual IP security options */ -const struct optlist secopt[8] = { +static const struct optlist secopt[8] = { { IPSO_CLASS_RES4, 0x01 }, { IPSO_CLASS_TOPS, 0x02 }, { IPSO_CLASS_SECR, 0x04 }, @@ -305,16 +277,143 @@ const struct optlist secopt[8] = { { IPSO_CLASS_RES1, 0x80 } }; +char ipfilter_version[] = IPL_VERSION; + +int ipf_features = 0 +#ifdef IPFILTER_LKM + | IPF_FEAT_LKM +#endif +#ifdef IPFILTER_LOG + | IPF_FEAT_LOG +#endif + | IPF_FEAT_LOOKUP +#ifdef IPFILTER_BPF + | IPF_FEAT_BPF +#endif +#ifdef IPFILTER_COMPILED + | IPF_FEAT_COMPILED +#endif +#ifdef IPFILTER_CKSUM + | IPF_FEAT_CKSUM +#endif + | IPF_FEAT_SYNC +#ifdef IPFILTER_SCAN + | IPF_FEAT_SCAN +#endif +#ifdef USE_INET6 + | IPF_FEAT_IPV6 +#endif + ; + /* * Table of functions available for use with call rules. */ -static ipfunc_resolve_t fr_availfuncs[] = { -#ifdef IPFILTER_LOOKUP - { "fr_srcgrpmap", fr_srcgrpmap, fr_grpmapinit }, - { "fr_dstgrpmap", fr_dstgrpmap, fr_grpmapinit }, +static ipfunc_resolve_t ipf_availfuncs[] = { + { "srcgrpmap", ipf_srcgrpmap, ipf_grpmapinit, ipf_grpmapfini }, + { "dstgrpmap", ipf_dstgrpmap, ipf_grpmapinit, ipf_grpmapfini }, + { "", NULL, NULL, NULL } +}; + +static ipftuneable_t ipf_main_tuneables[] = { + { { (void *)offsetof(struct ipf_main_softc_s, ipf_flags) }, + "ipf_flags", 0, 0xffffffff, + stsizeof(ipf_main_softc_t, ipf_flags), + 0, NULL, NULL }, + { { (void *)offsetof(struct ipf_main_softc_s, ipf_active) }, + "active", 0, 0, + stsizeof(ipf_main_softc_t, ipf_active), + IPFT_RDONLY, NULL, NULL }, + { { (void *)offsetof(ipf_main_softc_t, ipf_control_forwarding) }, + "control_forwarding", 0, 1, + stsizeof(ipf_main_softc_t, ipf_control_forwarding), + 0, NULL, NULL }, + { { (void *)offsetof(ipf_main_softc_t, ipf_update_ipid) }, + "update_ipid", 0, 1, + stsizeof(ipf_main_softc_t, ipf_update_ipid), + 0, NULL, NULL }, + { { (void *)offsetof(ipf_main_softc_t, ipf_chksrc) }, + "chksrc", 0, 1, + stsizeof(ipf_main_softc_t, ipf_chksrc), + 0, NULL, NULL }, + { { (void *)offsetof(ipf_main_softc_t, ipf_minttl) }, + "min_ttl", 0, 1, + stsizeof(ipf_main_softc_t, ipf_minttl), + 0, NULL, NULL }, + { { (void *)offsetof(ipf_main_softc_t, ipf_icmpminfragmtu) }, + "icmp_minfragmtu", 0, 1, + stsizeof(ipf_main_softc_t, ipf_icmpminfragmtu), + 0, NULL, NULL }, + { { (void *)offsetof(ipf_main_softc_t, ipf_pass) }, + "default_pass", 0, 0xffffffff, + stsizeof(ipf_main_softc_t, ipf_pass), + 0, NULL, NULL }, + { { (void *)offsetof(ipf_main_softc_t, ipf_tcpidletimeout) }, + "tcp_idle_timeout", 1, 0x7fffffff, + stsizeof(ipf_main_softc_t, ipf_tcpidletimeout), + 0, NULL, ipf_settimeout }, + { { (void *)offsetof(ipf_main_softc_t, ipf_tcpclosewait) }, + "tcp_close_wait", 1, 0x7fffffff, + stsizeof(ipf_main_softc_t, ipf_tcpclosewait), + 0, NULL, ipf_settimeout }, + { { (void *)offsetof(ipf_main_softc_t, ipf_tcplastack) }, + "tcp_last_ack", 1, 0x7fffffff, + stsizeof(ipf_main_softc_t, ipf_tcplastack), + 0, NULL, ipf_settimeout }, + { { (void *)offsetof(ipf_main_softc_t, ipf_tcptimeout) }, + "tcp_timeout", 1, 0x7fffffff, + stsizeof(ipf_main_softc_t, ipf_tcptimeout), + 0, NULL, ipf_settimeout }, + { { (void *)offsetof(ipf_main_softc_t, ipf_tcpsynsent) }, + "tcp_syn_sent", 1, 0x7fffffff, + stsizeof(ipf_main_softc_t, ipf_tcpsynsent), + 0, NULL, ipf_settimeout }, + { { (void *)offsetof(ipf_main_softc_t, ipf_tcpsynrecv) }, + "tcp_syn_received", 1, 0x7fffffff, + stsizeof(ipf_main_softc_t, ipf_tcpsynrecv), + 0, NULL, ipf_settimeout }, + { { (void *)offsetof(ipf_main_softc_t, ipf_tcpclosed) }, + "tcp_closed", 1, 0x7fffffff, + stsizeof(ipf_main_softc_t, ipf_tcpclosed), + 0, NULL, ipf_settimeout }, + { { (void *)offsetof(ipf_main_softc_t, ipf_tcphalfclosed) }, + "tcp_half_closed", 1, 0x7fffffff, + stsizeof(ipf_main_softc_t, ipf_tcphalfclosed), + 0, NULL, ipf_settimeout }, + { { (void *)offsetof(ipf_main_softc_t, ipf_tcptimewait) }, + "tcp_time_wait", 1, 0x7fffffff, + stsizeof(ipf_main_softc_t, ipf_tcptimewait), + 0, NULL, ipf_settimeout }, + { { (void *)offsetof(ipf_main_softc_t, ipf_udptimeout) }, + "udp_timeout", 1, 0x7fffffff, + stsizeof(ipf_main_softc_t, ipf_udptimeout), + 0, NULL, ipf_settimeout }, + { { (void *)offsetof(ipf_main_softc_t, ipf_udpacktimeout) }, + "udp_ack_timeout", 1, 0x7fffffff, + stsizeof(ipf_main_softc_t, ipf_udpacktimeout), + 0, NULL, ipf_settimeout }, + { { (void *)offsetof(ipf_main_softc_t, ipf_icmptimeout) }, + "icmp_timeout", 1, 0x7fffffff, + stsizeof(ipf_main_softc_t, ipf_icmptimeout), + 0, NULL, ipf_settimeout }, + { { (void *)offsetof(ipf_main_softc_t, ipf_icmpacktimeout) }, + "icmp_ack_timeout", 1, 0x7fffffff, + stsizeof(ipf_main_softc_t, ipf_icmpacktimeout), + 0, NULL, ipf_settimeout }, + { { (void *)offsetof(ipf_main_softc_t, ipf_iptimeout) }, + "ip_timeout", 1, 0x7fffffff, + stsizeof(ipf_main_softc_t, ipf_iptimeout), + 0, NULL, ipf_settimeout }, +#if defined(INSTANCES) && defined(_KERNEL) + { { (void *)offsetof(ipf_main_softc_t, ipf_get_loopback) }, + "intercept_loopback", 0, 1, + stsizeof(ipf_main_softc_t, ipf_get_loopback), + 0, NULL, ipf_set_loopback }, #endif - { "", NULL } + { { 0 }, + NULL, 0, 0, + 0, + 0, NULL, NULL } }; @@ -324,62 +423,65 @@ static ipfunc_resolve_t fr_availfuncs[] = { * current packet. There are different routines for the same protocol * for each of IPv4 and IPv6. Adding a new protocol, for which there * will "special" inspection for setup, is now more easily done by adding - * a new routine and expanding the frpr_ipinit*() function rather than by + * a new routine and expanding the ipf_pr_ipinit*() function rather than by * adding more code to a growing switch statement. */ #ifdef USE_INET6 -static INLINE void frpr_udp6 __P((fr_info_t *)); -static INLINE void frpr_tcp6 __P((fr_info_t *)); -static INLINE void frpr_icmp6 __P((fr_info_t *)); -static INLINE void frpr_ipv6hdr __P((fr_info_t *)); -static INLINE void frpr_short6 __P((fr_info_t *, int)); -static INLINE int frpr_hopopts6 __P((fr_info_t *)); -static INLINE int frpr_routing6 __P((fr_info_t *)); -static INLINE int frpr_dstopts6 __P((fr_info_t *)); -static INLINE int frpr_fragment6 __P((fr_info_t *)); - - -/* ------------------------------------------------------------------------ */ -/* Function: frpr_short6 */ +static INLINE int ipf_pr_ah6 __P((fr_info_t *)); +static INLINE void ipf_pr_esp6 __P((fr_info_t *)); +static INLINE void ipf_pr_gre6 __P((fr_info_t *)); +static INLINE void ipf_pr_udp6 __P((fr_info_t *)); +static INLINE void ipf_pr_tcp6 __P((fr_info_t *)); +static INLINE void ipf_pr_icmp6 __P((fr_info_t *)); +static INLINE void ipf_pr_ipv6hdr __P((fr_info_t *)); +static INLINE void ipf_pr_short6 __P((fr_info_t *, int)); +static INLINE int ipf_pr_hopopts6 __P((fr_info_t *)); +static INLINE int ipf_pr_mobility6 __P((fr_info_t *)); +static INLINE int ipf_pr_routing6 __P((fr_info_t *)); +static INLINE int ipf_pr_dstopts6 __P((fr_info_t *)); +static INLINE int ipf_pr_fragment6 __P((fr_info_t *)); +static INLINE struct ip6_ext *ipf_pr_ipv6exthdr __P((fr_info_t *, int, int)); + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pr_short6 */ /* Returns: void */ -/* Parameters: fin(I) - pointer to packet information */ +/* Parameters: fin(I) - pointer to packet information */ +/* xmin(I) - minimum header size */ /* */ /* IPv6 Only */ /* This is function enforces the 'is a packet too short to be legit' rule */ /* for IPv6 and marks the packet with FI_SHORT if so. See function comment */ -/* for frpr_short() for more details. */ +/* for ipf_pr_short() for more details. */ /* ------------------------------------------------------------------------ */ -static INLINE void frpr_short6(fin, min) -fr_info_t *fin; -int min; +static INLINE void +ipf_pr_short6(fin, xmin) + fr_info_t *fin; + int xmin; { - fr_ip_t *fi = &fin->fin_fi; - int off; - off = fin->fin_off; - if (off == 0) { - if (fin->fin_plen < fin->fin_hlen + min) - fi->fi_flx |= FI_SHORT; - } else if (off < min) { - fi->fi_flx |= FI_SHORT; - } + if (fin->fin_dlen < xmin) + fin->fin_flx |= FI_SHORT; } /* ------------------------------------------------------------------------ */ -/* Function: frpr_ipv6hdr */ +/* Function: ipf_pr_ipv6hdr */ /* Returns: void */ /* Parameters: fin(I) - pointer to packet information */ /* */ /* IPv6 Only */ /* Copy values from the IPv6 header into the fr_info_t struct and call the */ -/* per-protocol analyzer if it exists. */ +/* per-protocol analyzer if it exists. In validating the packet, a protocol*/ +/* analyzer may pullup or free the packet itself so we need to be vigiliant */ +/* of that possibility arising. */ /* ------------------------------------------------------------------------ */ -static INLINE void frpr_ipv6hdr(fin) -fr_info_t *fin; +static INLINE void +ipf_pr_ipv6hdr(fin) + fr_info_t *fin; { - int p, go = 1, i, hdrcount, coalesced; ip6_t *ip6 = (ip6_t *)fin->fin_ip; + int p, go = 1, i, hdrcount; fr_ip_t *fi = &fin->fin_fi; fin->fin_off = 0; @@ -389,75 +491,72 @@ fr_info_t *fin; fi->fi_secmsk = 0; fi->fi_auth = 0; - coalesced = (fin->fin_flx & FI_COALESCE) ? 1 : 0; p = ip6->ip6_nxt; + fin->fin_crc = p; fi->fi_ttl = ip6->ip6_hlim; fi->fi_src.in6 = ip6->ip6_src; + fin->fin_crc += fi->fi_src.i6[0]; + fin->fin_crc += fi->fi_src.i6[1]; + fin->fin_crc += fi->fi_src.i6[2]; + fin->fin_crc += fi->fi_src.i6[3]; fi->fi_dst.in6 = ip6->ip6_dst; - fin->fin_id = (u_short)(ip6->ip6_flow & 0xffff); + fin->fin_crc += fi->fi_dst.i6[0]; + fin->fin_crc += fi->fi_dst.i6[1]; + fin->fin_crc += fi->fi_dst.i6[2]; + fin->fin_crc += fi->fi_dst.i6[3]; + fin->fin_id = 0; + if (IN6_IS_ADDR_MULTICAST(&fi->fi_dst.in6)) + fin->fin_flx |= FI_MULTICAST|FI_MBCAST; hdrcount = 0; - while (go && !(fin->fin_flx & (FI_BAD|FI_SHORT))) { + while (go && !(fin->fin_flx & FI_SHORT)) { switch (p) { case IPPROTO_UDP : - frpr_udp6(fin); + ipf_pr_udp6(fin); go = 0; break; case IPPROTO_TCP : - frpr_tcp6(fin); + ipf_pr_tcp6(fin); go = 0; break; case IPPROTO_ICMPV6 : - frpr_icmp6(fin); + ipf_pr_icmp6(fin); go = 0; break; case IPPROTO_GRE : - frpr_gre(fin); + ipf_pr_gre6(fin); go = 0; break; case IPPROTO_HOPOPTS : - /* - * Actually, hop by hop header is only allowed right - * after IPv6 header! - */ - if (hdrcount != 0) - fin->fin_flx |= FI_BAD; + p = ipf_pr_hopopts6(fin); + break; - if (coalesced == 0) { - coalesced = fr_coalesce(fin); - if (coalesced != 1) - return; - } - p = frpr_hopopts6(fin); + case IPPROTO_MOBILITY : + p = ipf_pr_mobility6(fin); break; case IPPROTO_DSTOPTS : - if (coalesced == 0) { - coalesced = fr_coalesce(fin); - if (coalesced != 1) - return; - } - p = frpr_dstopts6(fin); + p = ipf_pr_dstopts6(fin); break; case IPPROTO_ROUTING : - if (coalesced == 0) { - coalesced = fr_coalesce(fin); - if (coalesced != 1) - return; - } - p = frpr_routing6(fin); + p = ipf_pr_routing6(fin); break; - case IPPROTO_ESP : - frpr_esp(fin); - /*FALLTHROUGH*/ case IPPROTO_AH : + p = ipf_pr_ah6(fin); + break; + + case IPPROTO_ESP : + ipf_pr_esp6(fin); + go = 0; + break; + case IPPROTO_IPV6 : for (i = 0; ip6exthdr[i].ol_bit != 0; i++) if (ip6exthdr[i].ol_val == p) { @@ -472,12 +571,15 @@ fr_info_t *fin; break; case IPPROTO_FRAGMENT : - if (coalesced == 0) { - coalesced = fr_coalesce(fin); - if (coalesced != 1) - return; - } - p = frpr_fragment6(fin); + p = ipf_pr_fragment6(fin); + /* + * Given that the only fragments we want to let through + * (where fin_off != 0) are those where the non-first + * fragments only have data, we can safely stop looking + * at headers if this is a non-leading fragment. + */ + if (fin->fin_off != 0) + go = 0; break; default : @@ -491,31 +593,66 @@ fr_info_t *fin; * extension headers (go != 0), the entire header may not have * been pulled up when the code gets to this point. This is * only done for "go != 0" because the other header handlers - * will all pullup their complete header and the other - * indicator of an incomplete header is that this eas just an - * extension header. + * will all pullup their complete header. The other indicator + * of an incomplete packet is that this was just an extension + * header. */ if ((go != 0) && (p != IPPROTO_NONE) && - (frpr_pullup(fin, 0) == -1)) { + (ipf_pr_pullup(fin, 0) == -1)) { p = IPPROTO_NONE; - go = 0; + break; } } + + /* + * Some of the above functions, like ipf_pr_esp6(), can call ipf_pullup + * and destroy whatever packet was here. The caller of this function + * expects us to return if there is a problem with ipf_pullup. + */ + if (fin->fin_m == NULL) { + ipf_main_softc_t *softc = fin->fin_main_soft; + + LBUMPD(ipf_stats[fin->fin_out], fr_v6_bad); + return; + } + fi->fi_p = p; + + /* + * IPv6 fragment case 1 - see comment for ipf_pr_fragment6(). + * "go != 0" imples the above loop hasn't arrived at a layer 4 header. + */ + if ((go != 0) && (fin->fin_flx & FI_FRAG) && (fin->fin_off == 0)) { + ipf_main_softc_t *softc = fin->fin_main_soft; + + fin->fin_flx |= FI_BAD; + LBUMPD(ipf_stats[fin->fin_out], fr_v6_badfrag); + LBUMP(ipf_stats[fin->fin_out].fr_v6_bad); + } } /* ------------------------------------------------------------------------ */ -/* Function: frpr_hopopts6 */ -/* Returns: int - value of the next header or IPPROTO_NONE if error */ -/* Parameters: fin(I) - pointer to packet information */ +/* Function: ipf_pr_ipv6exthdr */ +/* Returns: struct ip6_ext * - pointer to the start of the next header */ +/* or NULL if there is a prolblem. */ +/* Parameters: fin(I) - pointer to packet information */ +/* multiple(I) - flag indicating yes/no if multiple occurances */ +/* of this extension header are allowed. */ +/* proto(I) - protocol number for this extension header */ /* */ /* IPv6 Only */ -/* This is function checks pending hop by hop options extension header */ -/* ------------------------------------------------------------------------ */ -static INLINE int frpr_hopopts6(fin) -fr_info_t *fin; +/* This function embodies a number of common checks that all IPv6 extension */ +/* headers must be subjected to. For example, making sure the packet is */ +/* big enough for it to be in, checking if it is repeated and setting a */ +/* flag to indicate its presence. */ +/* ------------------------------------------------------------------------ */ +static INLINE struct ip6_ext * +ipf_pr_ipv6exthdr(fin, multiple, proto) + fr_info_t *fin; + int multiple, proto; { + ipf_main_softc_t *softc = fin->fin_main_soft; struct ip6_ext *hdr; u_short shift; int i; @@ -525,195 +662,246 @@ fr_info_t *fin; /* 8 is default length of extension hdr */ if ((fin->fin_dlen - 8) < 0) { fin->fin_flx |= FI_SHORT; - return IPPROTO_NONE; + LBUMPD(ipf_stats[fin->fin_out], fr_v6_ext_short); + return NULL; } - if (frpr_pullup(fin, 8) == -1) - return IPPROTO_NONE; + if (ipf_pr_pullup(fin, 8) == -1) { + LBUMPD(ipf_stats[fin->fin_out], fr_v6_ext_pullup); + return NULL; + } hdr = fin->fin_dp; - shift = 8 + (hdr->ip6e_len << 3); + switch (proto) + { + case IPPROTO_FRAGMENT : + shift = 8; + break; + default : + shift = 8 + (hdr->ip6e_len << 3); + break; + } + if (shift > fin->fin_dlen) { /* Nasty extension header length? */ fin->fin_flx |= FI_BAD; - return IPPROTO_NONE; + LBUMPD(ipf_stats[fin->fin_out], fr_v6_ext_hlen); + return NULL; } + fin->fin_dp = (char *)fin->fin_dp + shift; + fin->fin_dlen -= shift; + + /* + * If we have seen a fragment header, do not set any flags to indicate + * the presence of this extension header as it has no impact on the + * end result until after it has been defragmented. + */ + if (fin->fin_flx & FI_FRAG) + return hdr; + for (i = 0; ip6exthdr[i].ol_bit != 0; i++) - if (ip6exthdr[i].ol_val == IPPROTO_HOPOPTS) { - fin->fin_optmsk |= ip6exthdr[i].ol_bit; + if (ip6exthdr[i].ol_val == proto) { + /* + * Most IPv6 extension headers are only allowed once. + */ + if ((multiple == 0) && + ((fin->fin_optmsk & ip6exthdr[i].ol_bit) != 0)) + fin->fin_flx |= FI_BAD; + else + fin->fin_optmsk |= ip6exthdr[i].ol_bit; break; } - fin->fin_dp = (char *)fin->fin_dp + shift; - fin->fin_dlen -= shift; - - return hdr->ip6e_nxt; + return hdr; } /* ------------------------------------------------------------------------ */ -/* Function: frpr_routing6 */ +/* Function: ipf_pr_hopopts6 */ /* Returns: int - value of the next header or IPPROTO_NONE if error */ /* Parameters: fin(I) - pointer to packet information */ /* */ /* IPv6 Only */ -/* This is function checks pending routing extension header */ +/* This is function checks pending hop by hop options extension header */ /* ------------------------------------------------------------------------ */ -static INLINE int frpr_routing6(fin) -fr_info_t *fin; +static INLINE int +ipf_pr_hopopts6(fin) + fr_info_t *fin; { struct ip6_ext *hdr; - u_short shift; - int i; - - fin->fin_flx |= FI_V6EXTHDR; - /* 8 is default length of extension hdr */ - if ((fin->fin_dlen - 8) < 0) { - fin->fin_flx |= FI_SHORT; - return IPPROTO_NONE; - } - - if (frpr_pullup(fin, 8) == -1) - return IPPROTO_NONE; - hdr = fin->fin_dp; - - shift = 8 + (hdr->ip6e_len << 3); - /* - * Nasty extension header length? - */ - if ((shift > fin->fin_dlen) || (shift < sizeof(struct ip6_hdr)) || - ((shift - sizeof(struct ip6_hdr)) & 15)) { - fin->fin_flx |= FI_BAD; + hdr = ipf_pr_ipv6exthdr(fin, 0, IPPROTO_HOPOPTS); + if (hdr == NULL) return IPPROTO_NONE; - } + return hdr->ip6e_nxt; +} - for (i = 0; ip6exthdr[i].ol_bit != 0; i++) - if (ip6exthdr[i].ol_val == IPPROTO_ROUTING) { - fin->fin_optmsk |= ip6exthdr[i].ol_bit; - break; - } - fin->fin_dp = (char *)fin->fin_dp + shift; - fin->fin_dlen -= shift; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pr_mobility6 */ +/* Returns: int - value of the next header or IPPROTO_NONE if error */ +/* Parameters: fin(I) - pointer to packet information */ +/* */ +/* IPv6 Only */ +/* This is function checks the IPv6 mobility extension header */ +/* ------------------------------------------------------------------------ */ +static INLINE int +ipf_pr_mobility6(fin) + fr_info_t *fin; +{ + struct ip6_ext *hdr; + hdr = ipf_pr_ipv6exthdr(fin, 0, IPPROTO_MOBILITY); + if (hdr == NULL) + return IPPROTO_NONE; return hdr->ip6e_nxt; } /* ------------------------------------------------------------------------ */ -/* Function: frpr_fragment6 */ +/* Function: ipf_pr_routing6 */ /* Returns: int - value of the next header or IPPROTO_NONE if error */ /* Parameters: fin(I) - pointer to packet information */ /* */ /* IPv6 Only */ -/* Examine the IPv6 fragment header and extract fragment offset information.*/ +/* This is function checks pending routing extension header */ /* ------------------------------------------------------------------------ */ -static INLINE int frpr_fragment6(fin) -fr_info_t *fin; +static INLINE int +ipf_pr_routing6(fin) + fr_info_t *fin; { - struct ip6_frag *frag; - struct ip6_ext *hdr; - int i; + struct ip6_routing *hdr; - fin->fin_flx |= (FI_FRAG|FI_V6EXTHDR); - - /* 8 is default length of extension hdr */ - if ((fin->fin_dlen - 8) < 0) { - fin->fin_flx |= FI_SHORT; + hdr = (struct ip6_routing *)ipf_pr_ipv6exthdr(fin, 0, IPPROTO_ROUTING); + if (hdr == NULL) return IPPROTO_NONE; - } - /* - * Only one frgament header is allowed per IPv6 packet but it need - * not be the first nor last (not possible in some cases.) - */ - for (i = 0; ip6exthdr[i].ol_bit != 0; i++) - if (ip6exthdr[i].ol_val == IPPROTO_FRAGMENT) - break; + switch (hdr->ip6r_type) + { + case 0 : + /* + * Nasty extension header length? + */ + if (((hdr->ip6r_len >> 1) < hdr->ip6r_segleft) || + (hdr->ip6r_segleft && (hdr->ip6r_len & 1))) { + ipf_main_softc_t *softc = fin->fin_main_soft; - if (fin->fin_optmsk & ip6exthdr[i].ol_bit) { - fin->fin_flx |= FI_BAD; - return IPPROTO_NONE; + fin->fin_flx |= FI_BAD; + LBUMPD(ipf_stats[fin->fin_out], fr_v6_rh_bad); + return IPPROTO_NONE; + } + break; + + default : + break; } - fin->fin_optmsk |= ip6exthdr[i].ol_bit; + return hdr->ip6r_nxt; +} - if (frpr_pullup(fin, sizeof(*frag)) == -1) - return IPPROTO_NONE; - hdr = fin->fin_dp; - /* - * Length must be zero, i.e. it has no length. - */ - if (hdr->ip6e_len != 0) { - fin->fin_flx |= FI_BAD; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pr_fragment6 */ +/* Returns: int - value of the next header or IPPROTO_NONE if error */ +/* Parameters: fin(I) - pointer to packet information */ +/* */ +/* IPv6 Only */ +/* Examine the IPv6 fragment header and extract fragment offset information.*/ +/* */ +/* Fragments in IPv6 are extraordinarily difficult to deal with - much more */ +/* so than in IPv4. There are 5 cases of fragments with IPv6 that all */ +/* packets with a fragment header can fit into. They are as follows: */ +/* */ +/* 1. [IPv6][0-n EH][FH][0-n EH] (no L4HDR present) */ +/* 2. [IPV6][0-n EH][FH][0-n EH][L4HDR part] (short) */ +/* 3. [IPV6][0-n EH][FH][L4HDR part][0-n data] (short) */ +/* 4. [IPV6][0-n EH][FH][0-n EH][L4HDR][0-n data] */ +/* 5. [IPV6][0-n EH][FH][data] */ +/* */ +/* IPV6 = IPv6 header, FH = Fragment Header, */ +/* 0-n EH = 0 or more extension headers, 0-n data = 0 or more bytes of data */ +/* */ +/* Packets that match 1, 2, 3 will be dropped as the only reasonable */ +/* scenario in which they happen is in extreme circumstances that are most */ +/* likely to be an indication of an attack rather than normal traffic. */ +/* A type 3 packet may be sent by an attacked after a type 4 packet. There */ +/* are two rules that can be used to guard against type 3 packets: L4 */ +/* headers must always be in a packet that has the offset field set to 0 */ +/* and no packet is allowed to overlay that where offset = 0. */ +/* ------------------------------------------------------------------------ */ +static INLINE int +ipf_pr_fragment6(fin) + fr_info_t *fin; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + struct ip6_frag *frag; + + fin->fin_flx |= FI_FRAG; + + frag = (struct ip6_frag *)ipf_pr_ipv6exthdr(fin, 0, IPPROTO_FRAGMENT); + if (frag == NULL) { + LBUMPD(ipf_stats[fin->fin_out], fr_v6_frag_bad); return IPPROTO_NONE; } - if ((int)(fin->fin_dlen - sizeof(*frag)) < 0) { - fin->fin_flx |= FI_SHORT; - return IPPROTO_NONE; + if ((frag->ip6f_offlg & IP6F_MORE_FRAG) != 0) { + /* + * Any fragment that isn't the last fragment must have its + * length as a multiple of 8. + */ + if ((fin->fin_plen & 7) != 0) + fin->fin_flx |= FI_BAD; } - frag = fin->fin_dp; - fin->fin_off = frag->ip6f_offlg & IP6F_OFF_MASK; - fin->fin_off <<= 3; + fin->fin_fraghdr = frag; + fin->fin_id = frag->ip6f_ident; + fin->fin_off = ntohs(frag->ip6f_offlg & IP6F_OFF_MASK); if (fin->fin_off != 0) fin->fin_flx |= FI_FRAGBODY; - fin->fin_dp = (char *)fin->fin_dp + sizeof(*frag); - fin->fin_dlen -= sizeof(*frag); + /* + * Jumbograms aren't handled, so the max. length is 64k + */ + if ((fin->fin_off << 3) + fin->fin_dlen > 65535) + fin->fin_flx |= FI_BAD; + /* + * We don't know where the transport layer header (or whatever is next + * is), as it could be behind destination options (amongst others) so + * return the fragment header as the type of packet this is. Note that + * this effectively disables the fragment cache for > 1 protocol at a + * time. + */ return frag->ip6f_nxt; } /* ------------------------------------------------------------------------ */ -/* Function: frpr_dstopts6 */ +/* Function: ipf_pr_dstopts6 */ /* Returns: int - value of the next header or IPPROTO_NONE if error */ /* Parameters: fin(I) - pointer to packet information */ -/* nextheader(I) - stores next header value */ /* */ /* IPv6 Only */ /* This is function checks pending destination options extension header */ /* ------------------------------------------------------------------------ */ -static INLINE int frpr_dstopts6(fin) -fr_info_t *fin; +static INLINE int +ipf_pr_dstopts6(fin) + fr_info_t *fin; { + ipf_main_softc_t *softc = fin->fin_main_soft; struct ip6_ext *hdr; - u_short shift; - int i; - - /* 8 is default length of extension hdr */ - if ((fin->fin_dlen - 8) < 0) { - fin->fin_flx |= FI_SHORT; - return IPPROTO_NONE; - } - if (frpr_pullup(fin, 8) == -1) - return IPPROTO_NONE; - hdr = fin->fin_dp; - - shift = 8 + (hdr->ip6e_len << 3); - if (shift > fin->fin_dlen) { /* Nasty extension header length? */ - fin->fin_flx |= FI_BAD; + hdr = ipf_pr_ipv6exthdr(fin, 0, IPPROTO_DSTOPTS); + if (hdr == NULL) { + LBUMPD(ipf_stats[fin->fin_out], fr_v6_dst_bad); return IPPROTO_NONE; } - - for (i = 0; ip6exthdr[i].ol_bit != 0; i++) - if (ip6exthdr[i].ol_val == IPPROTO_DSTOPTS) - break; - fin->fin_optmsk |= ip6exthdr[i].ol_bit; - fin->fin_dp = (char *)fin->fin_dp + shift; - fin->fin_dlen -= shift; - return hdr->ip6e_nxt; } /* ------------------------------------------------------------------------ */ -/* Function: frpr_icmp6 */ +/* Function: ipf_pr_icmp6 */ /* Returns: void */ /* Parameters: fin(I) - pointer to packet information */ /* */ @@ -721,228 +909,421 @@ fr_info_t *fin; /* This routine is mainly concerned with determining the minimum valid size */ /* for an ICMPv6 packet. */ /* ------------------------------------------------------------------------ */ -static INLINE void frpr_icmp6(fin) -fr_info_t *fin; +static INLINE void +ipf_pr_icmp6(fin) + fr_info_t *fin; { int minicmpsz = sizeof(struct icmp6_hdr); struct icmp6_hdr *icmp6; - if (frpr_pullup(fin, ICMP6ERR_MINPKTLEN + 8 - sizeof(ip6_t)) == -1) + if (ipf_pr_pullup(fin, ICMP6ERR_MINPKTLEN - sizeof(ip6_t)) == -1) { + ipf_main_softc_t *softc = fin->fin_main_soft; + + LBUMPD(ipf_stats[fin->fin_out], fr_v6_icmp6_pullup); return; + } if (fin->fin_dlen > 1) { + ip6_t *ip6; + icmp6 = fin->fin_dp; fin->fin_data[0] = *(u_short *)icmp6; + if ((icmp6->icmp6_type & ICMP6_INFOMSG_MASK) != 0) + fin->fin_flx |= FI_ICMPQUERY; + switch (icmp6->icmp6_type) { case ICMP6_ECHO_REPLY : case ICMP6_ECHO_REQUEST : + if (fin->fin_dlen >= 6) + fin->fin_data[1] = icmp6->icmp6_id; minicmpsz = ICMP6ERR_MINPKTLEN - sizeof(ip6_t); break; + case ICMP6_DST_UNREACH : case ICMP6_PACKET_TOO_BIG : case ICMP6_TIME_EXCEEDED : case ICMP6_PARAM_PROB : - if ((fin->fin_m != NULL) && - (M_LEN(fin->fin_m) < fin->fin_plen)) { - if (fr_coalesce(fin) != 1) - return; - } fin->fin_flx |= FI_ICMPERR; minicmpsz = ICMP6ERR_IPICMPHLEN - sizeof(ip6_t); + if (fin->fin_plen < ICMP6ERR_IPICMPHLEN) + break; + + if (M_LEN(fin->fin_m) < fin->fin_plen) { + if (ipf_coalesce(fin) != 1) + return; + } + + if (ipf_pr_pullup(fin, ICMP6ERR_MINPKTLEN) == -1) + return; + + /* + * If the destination of this packet doesn't match the + * source of the original packet then this packet is + * not correct. + */ + icmp6 = fin->fin_dp; + ip6 = (ip6_t *)((char *)icmp6 + ICMPERR_ICMPHLEN); + if (IP6_NEQ(&fin->fin_fi.fi_dst, + (i6addr_t *)&ip6->ip6_src)) + fin->fin_flx |= FI_BAD; break; default : break; } } - frpr_short(fin, minicmpsz); + ipf_pr_short6(fin, minicmpsz); + if ((fin->fin_flx & (FI_SHORT|FI_BAD)) == 0) { + u_char p = fin->fin_p; + + fin->fin_p = IPPROTO_ICMPV6; + ipf_checkv6sum(fin); + fin->fin_p = p; + } } /* ------------------------------------------------------------------------ */ -/* Function: frpr_udp6 */ +/* Function: ipf_pr_udp6 */ /* Returns: void */ /* Parameters: fin(I) - pointer to packet information */ /* */ /* IPv6 Only */ /* Analyse the packet for IPv6/UDP properties. */ +/* Is not expected to be called for fragmented packets. */ /* ------------------------------------------------------------------------ */ -static INLINE void frpr_udp6(fin) -fr_info_t *fin; +static INLINE void +ipf_pr_udp6(fin) + fr_info_t *fin; { - fr_checkv6sum(fin); - - frpr_short(fin, sizeof(struct udphdr)); + if (ipf_pr_udpcommon(fin) == 0) { + u_char p = fin->fin_p; - frpr_udpcommon(fin); + fin->fin_p = IPPROTO_UDP; + ipf_checkv6sum(fin); + fin->fin_p = p; + } } /* ------------------------------------------------------------------------ */ -/* Function: frpr_tcp6 */ +/* Function: ipf_pr_tcp6 */ /* Returns: void */ /* Parameters: fin(I) - pointer to packet information */ /* */ /* IPv6 Only */ /* Analyse the packet for IPv6/TCP properties. */ +/* Is not expected to be called for fragmented packets. */ +/* ------------------------------------------------------------------------ */ +static INLINE void +ipf_pr_tcp6(fin) + fr_info_t *fin; +{ + + if (ipf_pr_tcpcommon(fin) == 0) { + u_char p = fin->fin_p; + + fin->fin_p = IPPROTO_TCP; + ipf_checkv6sum(fin); + fin->fin_p = p; + } +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pr_esp6 */ +/* Returns: void */ +/* Parameters: fin(I) - pointer to packet information */ +/* */ +/* IPv6 Only */ +/* Analyse the packet for ESP properties. */ +/* The minimum length is taken to be the SPI (32bits) plus a tail (32bits) */ +/* even though the newer ESP packets must also have a sequence number that */ +/* is 32bits as well, it is not possible(?) to determine the version from a */ +/* simple packet header. */ +/* ------------------------------------------------------------------------ */ +static INLINE void +ipf_pr_esp6(fin) + fr_info_t *fin; +{ + + if ((fin->fin_off == 0) && (ipf_pr_pullup(fin, 8) == -1)) { + ipf_main_softc_t *softc = fin->fin_main_soft; + + LBUMPD(ipf_stats[fin->fin_out], fr_v6_esp_pullup); + return; + } +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pr_ah6 */ +/* Returns: int - value of the next header or IPPROTO_NONE if error */ +/* Parameters: fin(I) - pointer to packet information */ +/* */ +/* IPv6 Only */ +/* Analyse the packet for AH properties. */ +/* The minimum length is taken to be the combination of all fields in the */ +/* header being present and no authentication data (null algorithm used.) */ +/* ------------------------------------------------------------------------ */ +static INLINE int +ipf_pr_ah6(fin) + fr_info_t *fin; +{ + authhdr_t *ah; + + fin->fin_flx |= FI_AH; + + ah = (authhdr_t *)ipf_pr_ipv6exthdr(fin, 0, IPPROTO_HOPOPTS); + if (ah == NULL) { + ipf_main_softc_t *softc = fin->fin_main_soft; + + LBUMPD(ipf_stats[fin->fin_out], fr_v6_ah_bad); + return IPPROTO_NONE; + } + + ipf_pr_short6(fin, sizeof(*ah)); + + /* + * No need for another pullup, ipf_pr_ipv6exthdr() will pullup + * enough data to satisfy ah_next (the very first one.) + */ + return ah->ah_next; +} + + /* ------------------------------------------------------------------------ */ -static INLINE void frpr_tcp6(fin) -fr_info_t *fin; +/* Function: ipf_pr_gre6 */ +/* Returns: void */ +/* Parameters: fin(I) - pointer to packet information */ +/* */ +/* Analyse the packet for GRE properties. */ +/* ------------------------------------------------------------------------ */ +static INLINE void +ipf_pr_gre6(fin) + fr_info_t *fin; { + grehdr_t *gre; - fr_checkv6sum(fin); + if (ipf_pr_pullup(fin, sizeof(grehdr_t)) == -1) { + ipf_main_softc_t *softc = fin->fin_main_soft; - frpr_short(fin, sizeof(struct tcphdr)); + LBUMPD(ipf_stats[fin->fin_out], fr_v6_gre_pullup); + return; + } - frpr_tcpcommon(fin); + gre = fin->fin_dp; + if (GRE_REV(gre->gr_flags) == 1) + fin->fin_data[0] = gre->gr_call; } #endif /* USE_INET6 */ /* ------------------------------------------------------------------------ */ -/* Function: frpr_pullup */ +/* Function: ipf_pr_pullup */ /* Returns: int - 0 == pullup succeeded, -1 == failure */ /* Parameters: fin(I) - pointer to packet information */ /* plen(I) - length (excluding L3 header) to pullup */ /* */ /* Short inline function to cut down on code duplication to perform a call */ -/* to fr_pullup to ensure there is the required amount of data, */ +/* to ipf_pullup to ensure there is the required amount of data, */ /* consecutively in the packet buffer. */ +/* */ +/* This function pulls up 'extra' data at the location of fin_dp. fin_dp */ +/* points to the first byte after the complete layer 3 header, which will */ +/* include all of the known extension headers for IPv6 or options for IPv4. */ +/* */ +/* Since fr_pullup() expects the total length of bytes to be pulled up, it */ +/* is necessary to add those we can already assume to be pulled up (fin_dp */ +/* - fin_ip) to what is passed through. */ /* ------------------------------------------------------------------------ */ -static INLINE int frpr_pullup(fin, plen) -fr_info_t *fin; -int plen; +int +ipf_pr_pullup(fin, plen) + fr_info_t *fin; + int plen; { -#if defined(_KERNEL) + ipf_main_softc_t *softc = fin->fin_main_soft; + if (fin->fin_m != NULL) { if (fin->fin_dp != NULL) plen += (char *)fin->fin_dp - ((char *)fin->fin_ip + fin->fin_hlen); plen += fin->fin_hlen; - if (M_LEN(fin->fin_m) < plen) { - if (fr_pullup(fin->fin_m, fin, plen) == NULL) + if (M_LEN(fin->fin_m) < plen + fin->fin_ipoff) { +#if defined(_KERNEL) + if (ipf_pullup(fin->fin_m, fin, plen) == NULL) { + DT(ipf_pullup_fail); + LBUMP(ipf_stats[fin->fin_out].fr_pull[1]); return -1; + } + LBUMP(ipf_stats[fin->fin_out].fr_pull[0]); +#else + LBUMP(ipf_stats[fin->fin_out].fr_pull[1]); + /* + * Fake ipf_pullup failing + */ + fin->fin_reason = FRB_PULLUP; + *fin->fin_mp = NULL; + fin->fin_m = NULL; + fin->fin_ip = NULL; + return -1; +#endif } } -#endif return 0; } /* ------------------------------------------------------------------------ */ -/* Function: frpr_short */ +/* Function: ipf_pr_short */ /* Returns: void */ -/* Parameters: fin(I) - pointer to packet information */ -/* min(I) - minimum header size */ +/* Parameters: fin(I) - pointer to packet information */ +/* xmin(I) - minimum header size */ /* */ -/* Check if a packet is "short" as defined by min. The rule we are */ +/* Check if a packet is "short" as defined by xmin. The rule we are */ /* applying here is that the packet must not be fragmented within the layer */ /* 4 header. That is, it must not be a fragment that has its offset set to */ /* start within the layer 4 header (hdrmin) or if it is at offset 0, the */ /* entire layer 4 header must be present (min). */ /* ------------------------------------------------------------------------ */ -static INLINE void frpr_short(fin, min) -fr_info_t *fin; -int min; +static INLINE void +ipf_pr_short(fin, xmin) + fr_info_t *fin; + int xmin; { - fr_ip_t *fi = &fin->fin_fi; - int off; - off = fin->fin_off; - if (off == 0) { - if (fin->fin_plen < fin->fin_hlen + min) - fi->fi_flx |= FI_SHORT; - } else if (off < min) { - fi->fi_flx |= FI_SHORT; + if (fin->fin_off == 0) { + if (fin->fin_dlen < xmin) + fin->fin_flx |= FI_SHORT; + } else if (fin->fin_off < xmin) { + fin->fin_flx |= FI_SHORT; } } /* ------------------------------------------------------------------------ */ -/* Function: frpr_icmp */ +/* Function: ipf_pr_icmp */ /* Returns: void */ /* Parameters: fin(I) - pointer to packet information */ /* */ /* IPv4 Only */ /* Do a sanity check on the packet for ICMP (v4). In nearly all cases, */ /* except extrememly bad packets, both type and code will be present. */ -/* The expected minimum size of an ICMP packet is very much dependant on */ +/* The expected minimum size of an ICMP packet is very much dependent on */ /* the type of it. */ /* */ /* XXX - other ICMP sanity checks? */ /* ------------------------------------------------------------------------ */ -static INLINE void frpr_icmp(fin) -fr_info_t *fin; +static INLINE void +ipf_pr_icmp(fin) + fr_info_t *fin; { + ipf_main_softc_t *softc = fin->fin_main_soft; int minicmpsz = sizeof(struct icmp); icmphdr_t *icmp; + ip_t *oip; + + ipf_pr_short(fin, ICMPERR_ICMPHLEN); - if (frpr_pullup(fin, ICMPERR_ICMPHLEN) == -1) + if (fin->fin_off != 0) { + LBUMPD(ipf_stats[fin->fin_out], fr_v4_icmp_frag); return; + } - fr_checkv4sum(fin); + if (ipf_pr_pullup(fin, ICMPERR_ICMPHLEN) == -1) { + LBUMPD(ipf_stats[fin->fin_out], fr_v4_icmp_pullup); + return; + } - if (!fin->fin_off && (fin->fin_dlen > 1)) { - icmp = fin->fin_dp; + icmp = fin->fin_dp; - fin->fin_data[0] = *(u_short *)icmp; + fin->fin_data[0] = *(u_short *)icmp; + fin->fin_data[1] = icmp->icmp_id; + + switch (icmp->icmp_type) + { + case ICMP_ECHOREPLY : + case ICMP_ECHO : + /* Router discovery messaes - RFC 1256 */ + case ICMP_ROUTERADVERT : + case ICMP_ROUTERSOLICIT : + fin->fin_flx |= FI_ICMPQUERY; + minicmpsz = ICMP_MINLEN; + break; + /* + * type(1) + code(1) + cksum(2) + id(2) seq(2) + + * 3 * timestamp(3 * 4) + */ + case ICMP_TSTAMP : + case ICMP_TSTAMPREPLY : + fin->fin_flx |= FI_ICMPQUERY; + minicmpsz = 20; + break; + /* + * type(1) + code(1) + cksum(2) + id(2) seq(2) + + * mask(4) + */ + case ICMP_IREQ : + case ICMP_IREQREPLY : + case ICMP_MASKREQ : + case ICMP_MASKREPLY : + fin->fin_flx |= FI_ICMPQUERY; + minicmpsz = 12; + break; + /* + * type(1) + code(1) + cksum(2) + id(2) seq(2) + ip(20+) + */ + case ICMP_UNREACH : +#ifdef icmp_nextmtu + if (icmp->icmp_code == ICMP_UNREACH_NEEDFRAG) { + if (icmp->icmp_nextmtu < softc->ipf_icmpminfragmtu) + fin->fin_flx |= FI_BAD; + } +#endif + case ICMP_SOURCEQUENCH : + case ICMP_REDIRECT : + case ICMP_TIMXCEED : + case ICMP_PARAMPROB : + fin->fin_flx |= FI_ICMPERR; + if (ipf_coalesce(fin) != 1) { + LBUMPD(ipf_stats[fin->fin_out], fr_icmp_coalesce); + return; + } - switch (icmp->icmp_type) - { - case ICMP_ECHOREPLY : - case ICMP_ECHO : - /* Router discovery messaes - RFC 1256 */ - case ICMP_ROUTERADVERT : - case ICMP_ROUTERSOLICIT : - minicmpsz = ICMP_MINLEN; - break; - /* - * type(1) + code(1) + cksum(2) + id(2) seq(2) + - * 3 * timestamp(3 * 4) - */ - case ICMP_TSTAMP : - case ICMP_TSTAMPREPLY : - minicmpsz = 20; - break; /* - * type(1) + code(1) + cksum(2) + id(2) seq(2) + - * mask(4) + * ICMP error packets should not be generated for IP + * packets that are a fragment that isn't the first + * fragment. */ - case ICMP_MASKREQ : - case ICMP_MASKREPLY : - minicmpsz = 12; - break; + oip = (ip_t *)((char *)fin->fin_dp + ICMPERR_ICMPHLEN); + if ((ntohs(oip->ip_off) & IP_OFFMASK) != 0) + fin->fin_flx |= FI_BAD; + /* - * type(1) + code(1) + cksum(2) + id(2) seq(2) + ip(20+) + * If the destination of this packet doesn't match the + * source of the original packet then this packet is + * not correct. */ - case ICMP_UNREACH : - case ICMP_SOURCEQUENCH : - case ICMP_REDIRECT : - case ICMP_TIMXCEED : - case ICMP_PARAMPROB : - if (fr_coalesce(fin) != 1) - return; - fin->fin_flx |= FI_ICMPERR; - break; - default : - break; - } - - if (fin->fin_dlen >= 6) /* ID field */ - fin->fin_data[1] = icmp->icmp_id; + if (oip->ip_src.s_addr != fin->fin_daddr) + fin->fin_flx |= FI_BAD; + break; + default : + break; } - frpr_short(fin, minicmpsz); + ipf_pr_short(fin, minicmpsz); + + ipf_checkv4sum(fin); } /* ------------------------------------------------------------------------ */ -/* Function: frpr_tcpcommon */ -/* Returns: void */ +/* Function: ipf_pr_tcpcommon */ +/* Returns: int - 0 = header ok, 1 = bad packet, -1 = buffer error */ /* Parameters: fin(I) - pointer to packet information */ /* */ /* TCP header sanity checking. Look for bad combinations of TCP flags, */ @@ -950,29 +1331,35 @@ fr_info_t *fin; /* If compiled with IPFILTER_CKSUM, check to see if the TCP checksum is */ /* valid and mark the packet as bad if not. */ /* ------------------------------------------------------------------------ */ -static INLINE void frpr_tcpcommon(fin) -fr_info_t *fin; +static INLINE int +ipf_pr_tcpcommon(fin) + fr_info_t *fin; { + ipf_main_softc_t *softc = fin->fin_main_soft; int flags, tlen; tcphdr_t *tcp; - fr_ip_t *fi; - fi = &fin->fin_fi; - fi->fi_flx |= FI_TCPUDP; - if (fin->fin_off != 0) - return; + fin->fin_flx |= FI_TCPUDP; + if (fin->fin_off != 0) { + LBUMPD(ipf_stats[fin->fin_out], fr_tcp_frag); + return 0; + } - if (frpr_pullup(fin, sizeof(*tcp)) == -1) - return; - tcp = fin->fin_dp; + if (ipf_pr_pullup(fin, sizeof(*tcp)) == -1) { + LBUMPD(ipf_stats[fin->fin_out], fr_tcp_pullup); + return -1; + } + tcp = fin->fin_dp; if (fin->fin_dlen > 3) { fin->fin_sport = ntohs(tcp->th_sport); fin->fin_dport = ntohs(tcp->th_dport); } - if ((fi->fi_flx & FI_SHORT) != 0) - return; + if ((fin->fin_flx & FI_SHORT) != 0) { + LBUMPD(ipf_stats[fin->fin_out], fr_tcp_short); + return 1; + } /* * Use of the TCP data offset *must* result in a value that is at @@ -980,8 +1367,9 @@ fr_info_t *fin; */ tlen = TCP_OFF(tcp) << 2; if (tlen < sizeof(tcphdr_t)) { + LBUMPD(ipf_stats[fin->fin_out], fr_tcp_small); fin->fin_flx |= FI_BAD; - return; + return 1; } flags = tcp->th_flags; @@ -994,14 +1382,27 @@ fr_info_t *fin; */ if ((flags & TH_URG) != 0 && (tcp->th_urp == 0)) { fin->fin_flx |= FI_BAD; +#if 0 } else if ((flags & TH_URG) == 0 && (tcp->th_urp != 0)) { - /* Ignore this case, it shows up in "real" traffic with */ - /* bogus values in the urgent pointer field. */ - ; + /* + * Ignore this case (#if 0) as it shows up in "real" + * traffic with bogus values in the urgent pointer field. + */ + fin->fin_flx |= FI_BAD; +#endif } else if (((flags & (TH_SYN|TH_FIN)) != 0) && ((flags & (TH_RST|TH_ACK)) == TH_RST)) { /* TH_FIN|TH_RST|TH_ACK seems to appear "naturally" */ fin->fin_flx |= FI_BAD; +#if 1 + } else if (((flags & TH_SYN) != 0) && + ((flags & (TH_URG|TH_PUSH)) != 0)) { + /* + * SYN with URG and PUSH set is not for normal TCP but it is + * possible(?) with T/TCP...but who uses T/TCP? + */ + fin->fin_flx |= FI_BAD; +#endif } else if (!(flags & TH_ACK)) { /* * If the ack bit isn't set, then either the SYN or @@ -1025,6 +1426,10 @@ fr_info_t *fin; fin->fin_flx |= FI_BAD; } } + if (fin->fin_flx & FI_BAD) { + LBUMPD(ipf_stats[fin->fin_out], fr_tcp_bad_flags); + return 1; + } /* * At this point, it's not exactly clear what is to be gained by @@ -1034,13 +1439,17 @@ fr_info_t *fin; * Now if we were to analyse the header for passive fingerprinting, * then that might add some weight to adding this... */ - if (tlen == sizeof(tcphdr_t)) - return; + if (tlen == sizeof(tcphdr_t)) { + return 0; + } - if (frpr_pullup(fin, tlen) == -1) - return; + if (ipf_pr_pullup(fin, tlen) == -1) { + LBUMPD(ipf_stats[fin->fin_out], fr_tcp_pullup); + return -1; + } #if 0 + tcp = fin->fin_dp; ip = fin->fin_ip; s = (u_char *)(tcp + 1); off = IP_HL(ip) << 2; @@ -1077,31 +1486,35 @@ fr_info_t *fin; s += ol; } #endif /* 0 */ + + return 0; } /* ------------------------------------------------------------------------ */ -/* Function: frpr_udpcommon */ -/* Returns: void */ +/* Function: ipf_pr_udpcommon */ +/* Returns: int - 0 = header ok, 1 = bad packet */ /* Parameters: fin(I) - pointer to packet information */ /* */ /* Extract the UDP source and destination ports, if present. If compiled */ /* with IPFILTER_CKSUM, check to see if the UDP checksum is valid. */ /* ------------------------------------------------------------------------ */ -static INLINE void frpr_udpcommon(fin) -fr_info_t *fin; +static INLINE int +ipf_pr_udpcommon(fin) + fr_info_t *fin; { udphdr_t *udp; - fr_ip_t *fi; - fi = &fin->fin_fi; - fi->fi_flx |= FI_TCPUDP; + fin->fin_flx |= FI_TCPUDP; if (!fin->fin_off && (fin->fin_dlen > 3)) { - if (frpr_pullup(fin, sizeof(*udp)) == -1) { - fi->fi_flx |= FI_SHORT; - return; + if (ipf_pr_pullup(fin, sizeof(*udp)) == -1) { + ipf_main_softc_t *softc = fin->fin_main_soft; + + fin->fin_flx |= FI_SHORT; + LBUMPD(ipf_stats[fin->fin_out], fr_udp_pullup); + return 1; } udp = fin->fin_dp; @@ -1109,51 +1522,53 @@ fr_info_t *fin; fin->fin_sport = ntohs(udp->uh_sport); fin->fin_dport = ntohs(udp->uh_dport); } + + return 0; } /* ------------------------------------------------------------------------ */ -/* Function: frpr_tcp */ +/* Function: ipf_pr_tcp */ /* Returns: void */ /* Parameters: fin(I) - pointer to packet information */ /* */ /* IPv4 Only */ /* Analyse the packet for IPv4/TCP properties. */ /* ------------------------------------------------------------------------ */ -static INLINE void frpr_tcp(fin) -fr_info_t *fin; +static INLINE void +ipf_pr_tcp(fin) + fr_info_t *fin; { - fr_checkv4sum(fin); - - frpr_short(fin, sizeof(tcphdr_t)); + ipf_pr_short(fin, sizeof(tcphdr_t)); - frpr_tcpcommon(fin); + if (ipf_pr_tcpcommon(fin) == 0) + ipf_checkv4sum(fin); } /* ------------------------------------------------------------------------ */ -/* Function: frpr_udp */ +/* Function: ipf_pr_udp */ /* Returns: void */ /* Parameters: fin(I) - pointer to packet information */ /* */ /* IPv4 Only */ /* Analyse the packet for IPv4/UDP properties. */ /* ------------------------------------------------------------------------ */ -static INLINE void frpr_udp(fin) -fr_info_t *fin; +static INLINE void +ipf_pr_udp(fin) + fr_info_t *fin; { - fr_checkv4sum(fin); - - frpr_short(fin, sizeof(udphdr_t)); + ipf_pr_short(fin, sizeof(udphdr_t)); - frpr_udpcommon(fin); + if (ipf_pr_udpcommon(fin) == 0) + ipf_checkv4sum(fin); } /* ------------------------------------------------------------------------ */ -/* Function: frpr_esp */ +/* Function: ipf_pr_esp */ /* Returns: void */ /* Parameters: fin(I) - pointer to packet information */ /* */ @@ -1163,42 +1578,99 @@ fr_info_t *fin; /* is 32bits as well, it is not possible(?) to determine the version from a */ /* simple packet header. */ /* ------------------------------------------------------------------------ */ -static INLINE void frpr_esp(fin) -fr_info_t *fin; +static INLINE void +ipf_pr_esp(fin) + fr_info_t *fin; { - if (frpr_pullup(fin, 8) == -1) - return; - if (fin->fin_v == 4) - frpr_short(fin, 8); -#ifdef USE_INET6 - else if (fin->fin_v == 6) - frpr_short6(fin, sizeof(grehdr_t)); -#endif + if (fin->fin_off == 0) { + ipf_pr_short(fin, 8); + if (ipf_pr_pullup(fin, 8) == -1) { + ipf_main_softc_t *softc = fin->fin_main_soft; + + LBUMPD(ipf_stats[fin->fin_out], fr_v4_esp_pullup); + } + } +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pr_ah */ +/* Returns: int - value of the next header or IPPROTO_NONE if error */ +/* Parameters: fin(I) - pointer to packet information */ +/* */ +/* Analyse the packet for AH properties. */ +/* The minimum length is taken to be the combination of all fields in the */ +/* header being present and no authentication data (null algorithm used.) */ +/* ------------------------------------------------------------------------ */ +static INLINE int +ipf_pr_ah(fin) + fr_info_t *fin; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + authhdr_t *ah; + int len; + + fin->fin_flx |= FI_AH; + ipf_pr_short(fin, sizeof(*ah)); + + if (((fin->fin_flx & FI_SHORT) != 0) || (fin->fin_off != 0)) { + LBUMPD(ipf_stats[fin->fin_out], fr_v4_ah_bad); + return IPPROTO_NONE; + } + + if (ipf_pr_pullup(fin, sizeof(*ah)) == -1) { + DT(fr_v4_ah_pullup_1); + LBUMP(ipf_stats[fin->fin_out].fr_v4_ah_pullup); + return IPPROTO_NONE; + } + + ah = (authhdr_t *)fin->fin_dp; + + len = (ah->ah_plen + 2) << 2; + ipf_pr_short(fin, len); + if (ipf_pr_pullup(fin, len) == -1) { + DT(fr_v4_ah_pullup_2); + LBUMP(ipf_stats[fin->fin_out].fr_v4_ah_pullup); + return IPPROTO_NONE; + } + + /* + * Adjust fin_dp and fin_dlen for skipping over the authentication + * header. + */ + fin->fin_dp = (char *)fin->fin_dp + len; + fin->fin_dlen -= len; + return ah->ah_next; } /* ------------------------------------------------------------------------ */ -/* Function: frpr_gre */ +/* Function: ipf_pr_gre */ /* Returns: void */ /* Parameters: fin(I) - pointer to packet information */ /* */ /* Analyse the packet for GRE properties. */ /* ------------------------------------------------------------------------ */ -static INLINE void frpr_gre(fin) -fr_info_t *fin; +static INLINE void +ipf_pr_gre(fin) + fr_info_t *fin; { + ipf_main_softc_t *softc = fin->fin_main_soft; grehdr_t *gre; - if (frpr_pullup(fin, sizeof(grehdr_t)) == -1) + ipf_pr_short(fin, sizeof(grehdr_t)); + + if (fin->fin_off != 0) { + LBUMPD(ipf_stats[fin->fin_out], fr_v4_gre_frag); return; + } + + if (ipf_pr_pullup(fin, sizeof(grehdr_t)) == -1) { + LBUMPD(ipf_stats[fin->fin_out], fr_v4_gre_pullup); + return; + } - if (fin->fin_v == 4) - frpr_short(fin, sizeof(grehdr_t)); -#ifdef USE_INET6 - else if (fin->fin_v == 6) - frpr_short6(fin, sizeof(grehdr_t)); -#endif gre = fin->fin_dp; if (GRE_REV(gre->gr_flags) == 1) fin->fin_data[0] = gre->gr_call; @@ -1206,7 +1678,7 @@ fr_info_t *fin; /* ------------------------------------------------------------------------ */ -/* Function: frpr_ipv4hdr */ +/* Function: ipf_pr_ipv4hdr */ /* Returns: void */ /* Parameters: fin(I) - pointer to packet information */ /* */ @@ -1214,8 +1686,9 @@ fr_info_t *fin; /* Analyze the IPv4 header and set fields in the fr_info_t structure. */ /* Check all options present and flag their presence if any exist. */ /* ------------------------------------------------------------------------ */ -static INLINE void frpr_ipv4hdr(fin) -fr_info_t *fin; +static INLINE void +ipf_pr_ipv4hdr(fin) + fr_info_t *fin; { u_short optmsk = 0, secmsk = 0, auth = 0; int hlen, ol, mv, p, i; @@ -1231,16 +1704,14 @@ fr_info_t *fin; ip = fin->fin_ip; p = ip->ip_p; fi->fi_p = p; + fin->fin_crc = p; fi->fi_tos = ip->ip_tos; fin->fin_id = ip->ip_id; - off = ip->ip_off; + off = ntohs(ip->ip_off); /* Get both TTL and protocol */ fi->fi_p = ip->ip_p; fi->fi_ttl = ip->ip_ttl; -#if 0 - (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4)); -#endif /* Zero out bits not used in IPv6 address */ fi->fi_src.i6[1] = 0; @@ -1251,26 +1722,37 @@ fr_info_t *fin; fi->fi_dst.i6[3] = 0; fi->fi_saddr = ip->ip_src.s_addr; + fin->fin_crc += fi->fi_saddr; fi->fi_daddr = ip->ip_dst.s_addr; + fin->fin_crc += fi->fi_daddr; + if (IN_CLASSD(ntohl(fi->fi_daddr))) + fin->fin_flx |= FI_MULTICAST|FI_MBCAST; /* * set packet attribute flags based on the offset and * calculate the byte offset that it represents. */ - if ((off & IP_MF) != 0) { - fi->fi_flx |= FI_FRAG; - if (fin->fin_dlen == 0) - fi->fi_flx |= FI_BAD; - } - off &= IP_MF|IP_OFFMASK; if (off != 0) { + int morefrag = off & IP_MF; + fi->fi_flx |= FI_FRAG; off &= IP_OFFMASK; if (off != 0) { fin->fin_flx |= FI_FRAGBODY; off <<= 3; - if (off + fin->fin_dlen > 0xffff) { + if ((off + fin->fin_dlen > 65535) || + (fin->fin_dlen == 0) || + ((morefrag != 0) && ((fin->fin_dlen & 7) != 0))) { + /* + * The length of the packet, starting at its + * offset cannot exceed 65535 (0xffff) as the + * length of an IP packet is only 16 bits. + * + * Any fragment that isn't the last fragment + * must have a length greater than 0 and it + * must be an even multiple of 8. + */ fi->fi_flx |= FI_BAD; } } @@ -1280,22 +1762,30 @@ fr_info_t *fin; /* * Call per-protocol setup and checking */ + if (p == IPPROTO_AH) { + /* + * Treat AH differently because we expect there to be another + * layer 4 header after it. + */ + p = ipf_pr_ah(fin); + } + switch (p) { case IPPROTO_UDP : - frpr_udp(fin); + ipf_pr_udp(fin); break; case IPPROTO_TCP : - frpr_tcp(fin); + ipf_pr_tcp(fin); break; case IPPROTO_ICMP : - frpr_icmp(fin); + ipf_pr_icmp(fin); break; case IPPROTO_ESP : - frpr_esp(fin); + ipf_pr_esp(fin); break; case IPPROTO_GRE : - frpr_gre(fin); + ipf_pr_gre(fin); break; } @@ -1338,32 +1828,37 @@ fr_info_t *fin; } for (i = 9, mv = 4; mv >= 0; ) { op = ipopts + i; + if ((opt == (u_char)op->ol_val) && (ol > 4)) { - optmsk |= op->ol_bit; - if (opt == IPOPT_SECURITY) { - const struct optlist *sp; - u_char sec; - int j, m; - - sec = *(s + 2); /* classification */ - for (j = 3, m = 2; m >= 0; ) { - sp = secopt + j; - if (sec == sp->ol_val) { - secmsk |= sp->ol_bit; - auth = *(s + 3); - auth *= 256; - auth += *(s + 4); - break; - } - if (sec < sp->ol_val) - j -= m; - else - j += m; - m--; + u_32_t doi; + + switch (opt) + { + case IPOPT_SECURITY : + if (optmsk & op->ol_bit) { + fin->fin_flx |= FI_BAD; + } else { + doi = ipf_checkripso(s); + secmsk = doi >> 16; + auth = doi & 0xffff; } + break; + + case IPOPT_CIPSO : + + if (optmsk & op->ol_bit) { + fin->fin_flx |= FI_BAD; + } else { + doi = ipf_checkcipso(fin, + s, ol); + secmsk = doi >> 16; + auth = doi & 0xffff; + } + break; } - break; + optmsk |= op->ol_bit; } + if (opt < op->ol_val) i -= mv; else @@ -1386,8 +1881,142 @@ fr_info_t *fin; /* ------------------------------------------------------------------------ */ -/* Function: fr_makefrip */ +/* Function: ipf_checkripso */ /* Returns: void */ +/* Parameters: s(I) - pointer to start of RIPSO option */ +/* */ +/* ------------------------------------------------------------------------ */ +static u_32_t +ipf_checkripso(s) + u_char *s; +{ + const struct optlist *sp; + u_short secmsk = 0, auth = 0; + u_char sec; + int j, m; + + sec = *(s + 2); /* classification */ + for (j = 3, m = 2; m >= 0; ) { + sp = secopt + j; + if (sec == sp->ol_val) { + secmsk |= sp->ol_bit; + auth = *(s + 3); + auth *= 256; + auth += *(s + 4); + break; + } + if (sec < sp->ol_val) + j -= m; + else + j += m; + m--; + } + + return (secmsk << 16) | auth; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_checkcipso */ +/* Returns: u_32_t - 0 = failure, else the doi from the header */ +/* Parameters: fin(IO) - pointer to packet information */ +/* s(I) - pointer to start of CIPSO option */ +/* ol(I) - length of CIPSO option field */ +/* */ +/* This function returns the domain of integrity (DOI) field from the CIPSO */ +/* header and returns that whilst also storing the highest sensitivity */ +/* value found in the fr_info_t structure. */ +/* */ +/* No attempt is made to extract the category bitmaps as these are defined */ +/* by the user (rather than the protocol) and can be rather numerous on the */ +/* end nodes. */ +/* ------------------------------------------------------------------------ */ +static u_32_t +ipf_checkcipso(fin, s, ol) + fr_info_t *fin; + u_char *s; + int ol; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + fr_ip_t *fi; + u_32_t doi; + u_char *t, tag, tlen, sensitivity; + int len; + + if (ol < 6 || ol > 40) { + LBUMPD(ipf_stats[fin->fin_out], fr_v4_cipso_bad); + fin->fin_flx |= FI_BAD; + return 0; + } + + fi = &fin->fin_fi; + fi->fi_sensitivity = 0; + /* + * The DOI field MUST be there. + */ + bcopy(s + 2, &doi, sizeof(doi)); + + t = (u_char *)s + 6; + for (len = ol - 6; len >= 2; len -= tlen, t+= tlen) { + tag = *t; + tlen = *(t + 1); + if (tlen > len || tlen < 4 || tlen > 34) { + LBUMPD(ipf_stats[fin->fin_out], fr_v4_cipso_tlen); + fin->fin_flx |= FI_BAD; + return 0; + } + + sensitivity = 0; + /* + * Tag numbers 0, 1, 2, 5 are laid out in the CIPSO Internet + * draft (16 July 1992) that has expired. + */ + if (tag == 0) { + fin->fin_flx |= FI_BAD; + continue; + } else if (tag == 1) { + if (*(t + 2) != 0) { + fin->fin_flx |= FI_BAD; + continue; + } + sensitivity = *(t + 3); + /* Category bitmap for categories 0-239 */ + + } else if (tag == 4) { + if (*(t + 2) != 0) { + fin->fin_flx |= FI_BAD; + continue; + } + sensitivity = *(t + 3); + /* Enumerated categories, 16bits each, upto 15 */ + + } else if (tag == 5) { + if (*(t + 2) != 0) { + fin->fin_flx |= FI_BAD; + continue; + } + sensitivity = *(t + 3); + /* Range of categories (2*16bits), up to 7 pairs */ + + } else if (tag > 127) { + /* Custom defined DOI */ + ; + } else { + fin->fin_flx |= FI_BAD; + continue; + } + + if (sensitivity > fi->fi_sensitivity) + fi->fi_sensitivity = sensitivity; + } + + return doi; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_makefrip */ +/* Returns: int - 0 == packet ok, -1 == packet freed */ /* Parameters: hlen(I) - length of IP packet header */ /* ip(I) - pointer to the IP header */ /* fin(IO) - pointer to packet information */ @@ -1397,54 +2026,62 @@ fr_info_t *fin; /* in the fr_info_t structure pointer to by fin. At present, it is assumed */ /* this function will be called with either an IPv4 or IPv6 packet. */ /* ------------------------------------------------------------------------ */ -int fr_makefrip(hlen, ip, fin) -int hlen; -ip_t *ip; -fr_info_t *fin; +int +ipf_makefrip(hlen, ip, fin) + int hlen; + ip_t *ip; + fr_info_t *fin; { + ipf_main_softc_t *softc = fin->fin_main_soft; int v; - fin->fin_nat = NULL; - fin->fin_state = NULL; fin->fin_depth = 0; fin->fin_hlen = (u_short)hlen; fin->fin_ip = ip; fin->fin_rule = 0xffffffff; fin->fin_group[0] = -1; fin->fin_group[1] = '\0'; - fin->fin_dlen = fin->fin_plen - hlen; fin->fin_dp = (char *)ip + hlen; v = fin->fin_v; - if (v == 4) - frpr_ipv4hdr(fin); + if (v == 4) { + fin->fin_plen = ntohs(ip->ip_len); + fin->fin_dlen = fin->fin_plen - hlen; + ipf_pr_ipv4hdr(fin); #ifdef USE_INET6 - else if (v == 6) - frpr_ipv6hdr(fin); + } else if (v == 6) { + fin->fin_plen = ntohs(((ip6_t *)ip)->ip6_plen); + fin->fin_dlen = fin->fin_plen; + fin->fin_plen += hlen; + + ipf_pr_ipv6hdr(fin); #endif - if (fin->fin_ip == NULL) + } + if (fin->fin_ip == NULL) { + LBUMP(ipf_stats[fin->fin_out].fr_ip_freed); return -1; + } return 0; } /* ------------------------------------------------------------------------ */ -/* Function: fr_portcheck */ +/* Function: ipf_portcheck */ /* Returns: int - 1 == port matched, 0 == port match failed */ /* Parameters: frp(I) - pointer to port check `expression' */ -/* pop(I) - pointer to port number to evaluate */ +/* pop(I) - port number to evaluate */ /* */ /* Perform a comparison of a port number against some other(s), using a */ /* structure with compare information stored in it. */ /* ------------------------------------------------------------------------ */ -static INLINE int fr_portcheck(frp, pop) -frpcmp_t *frp; -u_short *pop; +static INLINE int +ipf_portcheck(frp, pop) + frpcmp_t *frp; + u_32_t pop; { - u_short tup, po; int err = 1; + u_32_t po; - tup = *pop; po = frp->frp_port; /* @@ -1453,39 +2090,39 @@ u_short *pop; switch (frp->frp_cmp) { case FR_EQUAL : - if (tup != po) /* EQUAL */ + if (pop != po) /* EQUAL */ err = 0; break; case FR_NEQUAL : - if (tup == po) /* NOTEQUAL */ + if (pop == po) /* NOTEQUAL */ err = 0; break; case FR_LESST : - if (tup >= po) /* LESSTHAN */ + if (pop >= po) /* LESSTHAN */ err = 0; break; case FR_GREATERT : - if (tup <= po) /* GREATERTHAN */ + if (pop <= po) /* GREATERTHAN */ err = 0; break; case FR_LESSTE : - if (tup > po) /* LT or EQ */ + if (pop > po) /* LT or EQ */ err = 0; break; case FR_GREATERTE : - if (tup < po) /* GT or EQ */ + if (pop < po) /* GT or EQ */ err = 0; break; case FR_OUTRANGE : - if (tup >= po && tup <= frp->frp_top) /* Out of range */ + if (pop >= po && pop <= frp->frp_top) /* Out of range */ err = 0; break; case FR_INRANGE : - if (tup <= po || tup >= frp->frp_top) /* In range */ + if (pop <= po || pop >= frp->frp_top) /* In range */ err = 0; break; case FR_INCRANGE : - if (tup < po || tup > frp->frp_top) /* Inclusive range */ + if (pop < po || pop > frp->frp_top) /* Inclusive range */ err = 0; break; default : @@ -1496,17 +2133,18 @@ u_short *pop; /* ------------------------------------------------------------------------ */ -/* Function: fr_tcpudpchk */ +/* Function: ipf_tcpudpchk */ /* Returns: int - 1 == protocol matched, 0 == check failed */ -/* Parameters: fin(I) - pointer to packet information */ +/* Parameters: fda(I) - pointer to packet information */ /* ft(I) - pointer to structure with comparison data */ /* */ /* Compares the current pcket (assuming it is TCP/UDP) information with a */ /* structure containing information that we want to match against. */ /* ------------------------------------------------------------------------ */ -int fr_tcpudpchk(fin, ft) -fr_info_t *fin; -frtuc_t *ft; +int +ipf_tcpudpchk(fi, ft) + fr_ip_t *fi; + frtuc_t *ft; { int err = 1; @@ -1517,13 +2155,13 @@ frtuc_t *ft; * compare destination ports */ if (ft->ftu_dcmp) - err = fr_portcheck(&ft->ftu_dst, &fin->fin_dport); + err = ipf_portcheck(&ft->ftu_dst, fi->fi_ports[1]); /* * compare source ports */ if (err && ft->ftu_scmp) - err = fr_portcheck(&ft->ftu_src, &fin->fin_sport); + err = ipf_portcheck(&ft->ftu_src, fi->fi_ports[0]); /* * If we don't have all the TCP/UDP header, then how can we @@ -1531,15 +2169,15 @@ frtuc_t *ft; * TCP flags, then NO match. If not, then match (which should * satisfy the "short" class too). */ - if (err && (fin->fin_p == IPPROTO_TCP)) { - if (fin->fin_flx & FI_SHORT) + if (err && (fi->fi_p == IPPROTO_TCP)) { + if (fi->fi_flx & FI_SHORT) return !(ft->ftu_tcpf | ft->ftu_tcpfm); /* * Match the flags ? If not, abort this match. */ if (ft->ftu_tcpfm && - ft->ftu_tcpf != (fin->fin_tcpf & ft->ftu_tcpfm)) { - FR_DEBUG(("f. %#x & %#x != %#x\n", fin->fin_tcpf, + ft->ftu_tcpf != (fi->fi_tcpf & ft->ftu_tcpfm)) { + FR_DEBUG(("f. %#x & %#x != %#x\n", fi->fi_tcpf, ft->ftu_tcpfm, ft->ftu_tcpf)); err = 0; } @@ -1549,8 +2187,8 @@ frtuc_t *ft; /* ------------------------------------------------------------------------ */ -/* Function: fr_ipfcheck */ -/* Returns: int - 0 == match, 1 == no match */ +/* Function: ipf_check_ipf */ +/* Returns: int - 0 == match, else no match */ /* Parameters: fin(I) - pointer to packet information */ /* fr(I) - pointer to filter rule */ /* portcmp(I) - flag indicating whether to attempt matching on */ @@ -1560,10 +2198,11 @@ frtuc_t *ft; /* port numbers, etc, for "standard" IPFilter rules are all orchestrated in */ /* this function. */ /* ------------------------------------------------------------------------ */ -static INLINE int fr_ipfcheck(fin, fr, portcmp) -fr_info_t *fin; -frentry_t *fr; -int portcmp; +static INLINE int +ipf_check_ipf(fin, fr, portcmp) + fr_info_t *fin; + frentry_t *fr; + int portcmp; { u_32_t *ld, *lm, *lip; fripf_t *fri; @@ -1582,7 +2221,7 @@ int portcmp; */ i = ((*lip & *lm) != *ld); FR_DEBUG(("0. %#08x & %#08x != %#08x\n", - *lip, *lm, *ld)); + ntohl(*lip), ntohl(*lm), ntohl(*ld))); if (i) return 1; @@ -1591,10 +2230,10 @@ int portcmp; * are present (if any) in this packet. */ lip++, lm++, ld++; - i |= ((*lip & *lm) != *ld); + i = ((*lip & *lm) != *ld); FR_DEBUG(("1. %#08x & %#08x != %#08x\n", - *lip, *lm, *ld)); - if (i) + ntohl(*lip), ntohl(*lm), ntohl(*ld))); + if (i != 0) return 1; lip++, lm++, ld++; @@ -1604,101 +2243,93 @@ int portcmp; /* * Check the source address. */ -#ifdef IPFILTER_LOOKUP if (fr->fr_satype == FRI_LOOKUP) { - i = (*fr->fr_srcfunc)(fr->fr_srcptr, fi->fi_v, lip); + i = (*fr->fr_srcfunc)(fin->fin_main_soft, fr->fr_srcptr, + fi->fi_v, lip, fin->fin_plen); if (i == -1) return 1; lip += 3; lm += 3; ld += 3; } else { -#endif i = ((*lip & *lm) != *ld); FR_DEBUG(("2a. %#08x & %#08x != %#08x\n", - *lip, *lm, *ld)); + ntohl(*lip), ntohl(*lm), ntohl(*ld))); if (fi->fi_v == 6) { lip++, lm++, ld++; i |= ((*lip & *lm) != *ld); FR_DEBUG(("2b. %#08x & %#08x != %#08x\n", - *lip, *lm, *ld)); + ntohl(*lip), ntohl(*lm), ntohl(*ld))); lip++, lm++, ld++; i |= ((*lip & *lm) != *ld); FR_DEBUG(("2c. %#08x & %#08x != %#08x\n", - *lip, *lm, *ld)); + ntohl(*lip), ntohl(*lm), ntohl(*ld))); lip++, lm++, ld++; i |= ((*lip & *lm) != *ld); FR_DEBUG(("2d. %#08x & %#08x != %#08x\n", - *lip, *lm, *ld)); + ntohl(*lip), ntohl(*lm), ntohl(*ld))); } else { lip += 3; lm += 3; ld += 3; } -#ifdef IPFILTER_LOOKUP } -#endif i ^= (fr->fr_flags & FR_NOTSRCIP) >> 6; - if (i) + if (i != 0) return 1; /* * Check the destination address. */ lip++, lm++, ld++; -#ifdef IPFILTER_LOOKUP if (fr->fr_datype == FRI_LOOKUP) { - i = (*fr->fr_dstfunc)(fr->fr_dstptr, fi->fi_v, lip); + i = (*fr->fr_dstfunc)(fin->fin_main_soft, fr->fr_dstptr, + fi->fi_v, lip, fin->fin_plen); if (i == -1) return 1; lip += 3; lm += 3; ld += 3; } else { -#endif i = ((*lip & *lm) != *ld); FR_DEBUG(("3a. %#08x & %#08x != %#08x\n", - *lip, *lm, *ld)); + ntohl(*lip), ntohl(*lm), ntohl(*ld))); if (fi->fi_v == 6) { lip++, lm++, ld++; i |= ((*lip & *lm) != *ld); FR_DEBUG(("3b. %#08x & %#08x != %#08x\n", - *lip, *lm, *ld)); + ntohl(*lip), ntohl(*lm), ntohl(*ld))); lip++, lm++, ld++; i |= ((*lip & *lm) != *ld); FR_DEBUG(("3c. %#08x & %#08x != %#08x\n", - *lip, *lm, *ld)); + ntohl(*lip), ntohl(*lm), ntohl(*ld))); lip++, lm++, ld++; i |= ((*lip & *lm) != *ld); FR_DEBUG(("3d. %#08x & %#08x != %#08x\n", - *lip, *lm, *ld)); + ntohl(*lip), ntohl(*lm), ntohl(*ld))); } else { lip += 3; lm += 3; ld += 3; } -#ifdef IPFILTER_LOOKUP } -#endif i ^= (fr->fr_flags & FR_NOTDSTIP) >> 7; - if (i) + if (i != 0) return 1; /* * IP addresses matched. The next 32bits contains: * mast of old IP header security & authentication bits. */ lip++, lm++, ld++; - i |= ((*lip & *lm) != *ld); - FR_DEBUG(("4. %#08x & %#08x != %#08x\n", - *lip, *lm, *ld)); + i = (*ld - (*lip & *lm)); + FR_DEBUG(("4. %#08x & %#08x != %#08x\n", *lip, *lm, *ld)); /* * Next we have 32 bits of packet flags. */ lip++, lm++, ld++; - i |= ((*lip & *lm) != *ld); - FR_DEBUG(("5. %#08x & %#08x != %#08x\n", - *lip, *lm, *ld)); + i |= (*ld - (*lip & *lm)); + FR_DEBUG(("5. %#08x & %#08x != %#08x\n", *lip, *lm, *ld)); if (i == 0) { /* @@ -1706,7 +2337,7 @@ int portcmp; * looking for here... */ if (portcmp) { - if (!fr_tcpudpchk(fin, &fr->fr_tuc)) + if (!ipf_tcpudpchk(&fin->fin_fi, &fr->fr_tuc)) i = 1; } else { if (fr->fr_dcmp || fr->fr_scmp || @@ -1732,7 +2363,7 @@ int portcmp; /* ------------------------------------------------------------------------ */ -/* Function: fr_scanlist */ +/* Function: ipf_scanlist */ /* Returns: int - result flags of scanning filter list */ /* Parameters: fin(I) - pointer to packet information */ /* pass(I) - default result to return for filtering */ @@ -1747,13 +2378,15 @@ int portcmp; /* Could be per interface, but this gets real nasty when you don't have, */ /* or can't easily change, the kernel source code to . */ /* ------------------------------------------------------------------------ */ -int fr_scanlist(fin, pass) -fr_info_t *fin; -u_32_t pass; +int +ipf_scanlist(fin, pass) + fr_info_t *fin; + u_32_t pass; { - int rulen, portcmp, off, logged, skip; + ipf_main_softc_t *softc = fin->fin_main_soft; + int rulen, portcmp, off, skip; struct frentry *fr, *fnext; - u_32_t passt; + u_32_t passt, passo; /* * Do not allow nesting deeper than 16 levels. @@ -1770,7 +2403,6 @@ u_32_t pass; return pass; skip = 0; - logged = 0; portcmp = 0; fin->fin_depth++; fin->fin_fr = NULL; @@ -1782,7 +2414,7 @@ u_32_t pass; for (rulen = 0; fr; fr = fnext, rulen++) { fnext = fr->fr_next; if (skip != 0) { - FR_VERBOSE(("%d (%#x)\n", skip, fr->fr_flags)); + FR_VERBOSE(("SKIP %d (%#x)\n", skip, fr->fr_flags)); skip--; continue; } @@ -1812,20 +2444,20 @@ u_32_t pass; switch (fr->fr_type) { case FR_T_IPF : - case FR_T_IPF|FR_T_BUILTIN : - if (fr_ipfcheck(fin, fr, portcmp)) + case FR_T_IPF_BUILTIN : + if (ipf_check_ipf(fin, fr, portcmp)) continue; break; #if defined(IPFILTER_BPF) case FR_T_BPFOPC : - case FR_T_BPFOPC|FR_T_BUILTIN : + case FR_T_BPFOPC_BUILTIN : { u_char *mc; int wlen; if (*fin->fin_mp == NULL) continue; - if (fin->fin_v != fr->fr_v) + if (fin->fin_family != fr->fr_family) continue; mc = (u_char *)fin->fin_m; wlen = fin->fin_dlen + fin->fin_hlen; @@ -1834,7 +2466,7 @@ u_32_t pass; break; } #endif - case FR_T_CALLFUNC|FR_T_BUILTIN : + case FR_T_CALLFUNC_BUILTIN : { frentry_t *f; @@ -1845,6 +2477,15 @@ u_32_t pass; continue; break; } + + case FR_T_IPFEXPR : + case FR_T_IPFEXPR_BUILTIN : + if (fin->fin_family != fr->fr_family) + continue; + if (ipf_fr_matcharray(fin, fr->fr_data) == 0) + continue; + break; + default : break; } @@ -1852,99 +2493,136 @@ u_32_t pass; if ((fin->fin_out == 0) && (fr->fr_nattag.ipt_num[0] != 0)) { if (fin->fin_nattag == NULL) continue; - if (fr_matchtag(&fr->fr_nattag, fin->fin_nattag) == 0) + if (ipf_matchtag(&fr->fr_nattag, fin->fin_nattag) == 0) continue; } - FR_VERBOSE(("=%s.%d *", fr->fr_group, rulen)); + FR_VERBOSE(("=%d/%d.%d *", fr->fr_grhead, fr->fr_group, rulen)); passt = fr->fr_flags; /* - * Allowing a rule with the "keep state" flag set to match - * packets that have been tagged "out of window" by the TCP - * state tracking is foolish as the attempt to add a new - * state entry to the table will fail. - */ - if ((passt & FR_KEEPSTATE) && (fin->fin_flx & FI_OOW)) - continue; - - /* * If the rule is a "call now" rule, then call the function * in the rule, if it exists and use the results from that. * If the function pointer is bad, just make like we ignore * it, except for increasing the hit counter. */ if ((passt & FR_CALLNOW) != 0) { + frentry_t *frs; + ATOMIC_INC64(fr->fr_hits); - if ((fr->fr_func != NULL) && - (fr->fr_func != (ipfunc_t)-1)) { - frentry_t *frs; + if ((fr->fr_func == NULL) || + (fr->fr_func == (ipfunc_t)-1)) + continue; - frs = fin->fin_fr; - fin->fin_fr = fr; - fr = (*fr->fr_func)(fin, &passt); - if (fr == NULL) { - fin->fin_fr = frs; - continue; - } - passt = fr->fr_flags; - fin->fin_fr = fr; - } - } else { + frs = fin->fin_fr; fin->fin_fr = fr; + fr = (*fr->fr_func)(fin, &passt); + if (fr == NULL) { + fin->fin_fr = frs; + continue; + } + passt = fr->fr_flags; } + fin->fin_fr = fr; #ifdef IPFILTER_LOG /* * Just log this packet... */ if ((passt & FR_LOGMASK) == FR_LOG) { - if (ipflog(fin, passt) == -1) { + if (ipf_log_pkt(fin, passt) == -1) { if (passt & FR_LOGORBLOCK) { + DT(frb_logfail); passt &= ~FR_CMDMASK; passt |= FR_BLOCK|FR_QUICK; + fin->fin_reason = FRB_LOGFAIL; } - ATOMIC_INCL(frstats[fin->fin_out].fr_skip); } - ATOMIC_INCL(frstats[fin->fin_out].fr_pkl); - logged = 1; } #endif /* IPFILTER_LOG */ + + MUTEX_ENTER(&fr->fr_lock); fr->fr_bytes += (U_QUAD_T)fin->fin_plen; - if (FR_ISSKIP(passt)) + fr->fr_hits++; + MUTEX_EXIT(&fr->fr_lock); + fin->fin_rule = rulen; + + passo = pass; + if (FR_ISSKIP(passt)) { skip = fr->fr_arg; - else if ((passt & FR_LOGMASK) != FR_LOG) + continue; + } else if (((passt & FR_LOGMASK) != FR_LOG) && + ((passt & FR_LOGMASK) != FR_DECAPSULATE)) { pass = passt; + } + if (passt & (FR_RETICMP|FR_FAKEICMP)) fin->fin_icode = fr->fr_icode; - FR_DEBUG(("pass %#x\n", pass)); - ATOMIC_INC64(fr->fr_hits); - fin->fin_rule = rulen; - (void) strncpy(fin->fin_group, fr->fr_group, FR_GROUPLEN); - if (fr->fr_grp != NULL) { - fin->fin_fr = *fr->fr_grp; - pass = fr_scanlist(fin, pass); + + if (fr->fr_group != -1) { + (void) strncpy(fin->fin_group, + FR_NAME(fr, fr_group), + strlen(FR_NAME(fr, fr_group))); + } else { + fin->fin_group[0] = '\0'; + } + + FR_DEBUG(("pass %#x/%#x/%x\n", passo, pass, passt)); + + if (fr->fr_grphead != NULL) { + fin->fin_fr = fr->fr_grphead->fg_start; + FR_VERBOSE(("group %s\n", FR_NAME(fr, fr_grhead))); + + if (FR_ISDECAPS(passt)) + passt = ipf_decaps(fin, pass, fr->fr_icode); + else + passt = ipf_scanlist(fin, pass); + if (fin->fin_fr == NULL) { fin->fin_rule = rulen; - (void) strncpy(fin->fin_group, fr->fr_group, - FR_GROUPLEN); + if (fr->fr_group != -1) + (void) strncpy(fin->fin_group, + fr->fr_names + + fr->fr_group, + strlen(fr->fr_names + + fr->fr_group)); fin->fin_fr = fr; + passt = pass; } - if (fin->fin_flx & FI_DONTCACHE) - logged = 1; + pass = passt; } - if (pass & FR_QUICK) + + if (pass & FR_QUICK) { + /* + * Finally, if we've asked to track state for this + * packet, set it up. Add state for "quick" rules + * here so that if the action fails we can consider + * the rule to "not match" and keep on processing + * filter rules. + */ + if ((pass & FR_KEEPSTATE) && !FR_ISAUTH(pass) && + !(fin->fin_flx & FI_STATE)) { + int out = fin->fin_out; + + fin->fin_fr = fr; + if (ipf_state_add(softc, fin, NULL, 0) == 0) { + LBUMPD(ipf_stats[out], fr_ads); + } else { + LBUMPD(ipf_stats[out], fr_bads); + pass = passo; + continue; + } + } break; + } } - if (logged) - fin->fin_flx |= FI_DONTCACHE; fin->fin_depth--; return pass; } /* ------------------------------------------------------------------------ */ -/* Function: fr_acctpkt */ +/* Function: ipf_acctpkt */ /* Returns: frentry_t* - always returns NULL */ /* Parameters: fin(I) - pointer to packet information */ /* passp(IO) - pointer to current/new filter decision (unused) */ @@ -1953,32 +2631,29 @@ u_32_t pass; /* IP protocol version. */ /* */ /* N.B.: this function returns NULL to match the prototype used by other */ -/* functions called from the IPFilter "mainline" in fr_check(). */ +/* functions called from the IPFilter "mainline" in ipf_check(). */ /* ------------------------------------------------------------------------ */ -frentry_t *fr_acctpkt(fin, passp) -fr_info_t *fin; -u_32_t *passp; +frentry_t * +ipf_acctpkt(fin, passp) + fr_info_t *fin; + u_32_t *passp; { + ipf_main_softc_t *softc = fin->fin_main_soft; char group[FR_GROUPLEN]; frentry_t *fr, *frsave; u_32_t pass, rulen; passp = passp; -#ifdef USE_INET6 - if (fin->fin_v == 6) - fr = ipacct6[fin->fin_out][fr_active]; - else -#endif - fr = ipacct[fin->fin_out][fr_active]; + fr = softc->ipf_acct[fin->fin_out][softc->ipf_active]; if (fr != NULL) { frsave = fin->fin_fr; bcopy(fin->fin_group, group, FR_GROUPLEN); rulen = fin->fin_rule; fin->fin_fr = fr; - pass = fr_scanlist(fin, FR_NOMATCH); + pass = ipf_scanlist(fin, FR_NOMATCH); if (FR_ISACCOUNT(pass)) { - ATOMIC_INCL(frstats[0].fr_acct); + LBUMPD(ipf_stats[0], fr_acct); } fin->fin_fr = frsave; bcopy(group, fin->fin_group, FR_GROUPLEN); @@ -1989,7 +2664,7 @@ u_32_t *passp; /* ------------------------------------------------------------------------ */ -/* Function: fr_firewall */ +/* Function: ipf_firewall */ /* Returns: frentry_t* - returns pointer to matched rule, if no matches */ /* were found, returns NULL. */ /* Parameters: fin(I) - pointer to packet information */ @@ -2001,12 +2676,13 @@ u_32_t *passp; /* matching rule is found, take any appropriate actions as defined by the */ /* rule - except logging. */ /* ------------------------------------------------------------------------ */ -static frentry_t *fr_firewall(fin, passp) -fr_info_t *fin; -u_32_t *passp; +static frentry_t * +ipf_firewall(fin, passp) + fr_info_t *fin; + u_32_t *passp; { + ipf_main_softc_t *softc = fin->fin_main_soft; frentry_t *fr; - fr_info_t *fc; u_32_t pass; int out; @@ -2014,48 +2690,28 @@ u_32_t *passp; pass = *passp; /* - * If a packet is found in the auth table, then skip checking - * the access lists for permission but we do need to consider - * the result as if it were from the ACL's. + * This rule cache will only affect packets that are not being + * statefully filtered. */ - fc = &frcache[out][CACHE_HASH(fin)]; - if (!bcmp((char *)fin, (char *)fc, FI_CSIZE)) { - /* - * copy cached data so we can unlock the mutex - * earlier. - */ - bcopy((char *)fc, (char *)fin, FI_COPYSIZE); - ATOMIC_INCL(frstats[out].fr_chit); - if ((fr = fin->fin_fr) != NULL) { - ATOMIC_INC64(fr->fr_hits); - pass = fr->fr_flags; - } - } else { -#ifdef USE_INET6 - if (fin->fin_v == 6) - fin->fin_fr = ipfilter6[out][fr_active]; - else -#endif - fin->fin_fr = ipfilter[out][fr_active]; - if (fin->fin_fr != NULL) - pass = fr_scanlist(fin, fr_pass); - if (((pass & FR_KEEPSTATE) == 0) && - ((fin->fin_flx & FI_DONTCACHE) == 0)) - bcopy((char *)fin, (char *)fc, FI_COPYSIZE); - if ((pass & FR_NOMATCH)) { - ATOMIC_INCL(frstats[out].fr_nom); - } - fr = fin->fin_fr; + fin->fin_fr = softc->ipf_rules[out][softc->ipf_active]; + if (fin->fin_fr != NULL) + pass = ipf_scanlist(fin, softc->ipf_pass); + + if ((pass & FR_NOMATCH)) { + LBUMPD(ipf_stats[out], fr_nom); } + fr = fin->fin_fr; /* * Apply packets per second rate-limiting to a rule as required. */ if ((fr != NULL) && (fr->fr_pps != 0) && !ppsratecheck(&fr->fr_lastpkt, &fr->fr_curpps, fr->fr_pps)) { - pass &= ~(FR_CMDMASK|FR_DUP|FR_RETICMP|FR_RETRST); + DT2(frb_ppsrate, fr_info_t *, fin, frentry_t *, fr); + pass &= ~(FR_CMDMASK|FR_RETICMP|FR_RETRST); pass |= FR_BLOCK; - ATOMIC_INCL(frstats[out].fr_ppshit); + LBUMPD(ipf_stats[out], fr_ppshit); + fin->fin_reason = FRB_PPSRATE; } /* @@ -2064,15 +2720,15 @@ u_32_t *passp; * we've dropped it already. */ if (FR_ISAUTH(pass)) { - if (fr_newauth(fin->fin_m, fin) != 0) { -#ifdef _KERNEL + if (ipf_auth_new(fin->fin_m, fin) != 0) { + DT1(frb_authnew, fr_info_t *, fin); fin->fin_m = *fin->fin_mp = NULL; -#else - ; -#endif + fin->fin_reason = FRB_AUTHNEW; fin->fin_error = 0; - } else + } else { + IPFERROR(1); fin->fin_error = ENOSPC; + } } if ((fr != NULL) && (fr->fr_func != NULL) && @@ -2086,8 +2742,7 @@ u_32_t *passp; * is treated as "not a pass", hence the packet is blocked. */ if (FR_ISPREAUTH(pass)) { - if ((fin->fin_fr = ipauth) != NULL) - pass = fr_scanlist(fin, fr_pass); + pass = ipf_auth_pre_scanlist(softc, fin, pass); } /* @@ -2096,47 +2751,30 @@ u_32_t *passp; */ if ((pass & (FR_KEEPFRAG|FR_KEEPSTATE)) == FR_KEEPFRAG) { if (fin->fin_flx & FI_FRAG) { - if (fr_newfrag(fin, pass) == -1) { - ATOMIC_INCL(frstats[out].fr_bnfr); + if (ipf_frag_new(softc, fin, pass) == -1) { + LBUMP(ipf_stats[out].fr_bnfr); } else { - ATOMIC_INCL(frstats[out].fr_nfr); + LBUMP(ipf_stats[out].fr_nfr); } } else { - ATOMIC_INCL(frstats[out].fr_cfr); - } - } - - /* - * Finally, if we've asked to track state for this packet, set it up. - */ - if ((pass & FR_KEEPSTATE) && !(fin->fin_flx & FI_STATE)) { - if (fr_addstate(fin, NULL, 0) != NULL) { - ATOMIC_INCL(frstats[out].fr_ads); - } else { - ATOMIC_INCL(frstats[out].fr_bads); - if (FR_ISPASS(pass)) { - pass &= ~FR_CMDMASK; - pass |= FR_BLOCK; - } + LBUMP(ipf_stats[out].fr_cfr); } } fr = fin->fin_fr; - - if (passp != NULL) - *passp = pass; + *passp = pass; return fr; } /* ------------------------------------------------------------------------ */ -/* Function: fr_check */ +/* Function: ipf_check */ /* Returns: int - 0 == packet allowed through, */ /* User space: */ /* -1 == packet blocked */ /* 1 == packet not matched */ -/* -2 == requires authantication */ +/* -2 == requires authentication */ /* Kernel: */ /* > 0 == filter error # for packet */ /* Parameters: ip(I) - pointer to start of IPv4/6 packet */ @@ -2149,7 +2787,7 @@ u_32_t *passp; /* qpi(I) - pointer to STREAMS queue information for this */ /* interface & direction. */ /* */ -/* fr_check() is the master function for all IPFilter packet processing. */ +/* ipf_check() is the master function for all IPFilter packet processing. */ /* It orchestrates: Network Address Translation (NAT), checking for packet */ /* authorisation (or pre-authorisation), presence of related state info., */ /* generating log entries, IP packet accounting, routing of packets as */ @@ -2160,35 +2798,34 @@ u_32_t *passp; /* freed. Packets passed may be returned with the pointer pointed to by */ /* by "mp" changed to a new buffer. */ /* ------------------------------------------------------------------------ */ -int fr_check(ip, hlen, ifp, out +int +ipf_check(ctx, ip, hlen, ifp, out #if defined(_KERNEL) && defined(MENTAT) -, qif, mp) -void *qif; + , qif, mp) + void *qif; #else -, mp) + , mp) #endif -mb_t **mp; -ip_t *ip; -int hlen; -void *ifp; -int out; + mb_t **mp; + ip_t *ip; + int hlen; + void *ifp; + int out; + void *ctx; { /* * The above really sucks, but short of writing a diff */ + ipf_main_softc_t *softc = ctx; fr_info_t frinfo; fr_info_t *fin = &frinfo; - u_32_t pass = fr_pass; + u_32_t pass = softc->ipf_pass; frentry_t *fr = NULL; int v = IP_V(ip); mb_t *mc = NULL; mb_t *m; -#ifdef USE_INET6 - ip6_t *ip6; -#endif - /* - * The first part of fr_check() deals with making sure that what goes + * The first part of ipf_check() deals with making sure that what goes * into the filtering engine makes some sense. Information about the * the packet is distilled, collected into a fr_info_t structure and * the an attempt to ensure the buffer the packet is in is big enough @@ -2198,22 +2835,25 @@ int out; # ifdef MENTAT qpktinfo_t *qpi = qif; +# ifdef __sparc if ((u_int)ip & 0x3) return 2; +# endif +# else + SPL_INT(s); # endif - READ_ENTER(&ipf_global); - - if (fr_running <= 0) { - RWLOCK_EXIT(&ipf_global); + if (softc->ipf_running <= 0) { return 0; } bzero((char *)fin, sizeof(*fin)); # ifdef MENTAT - if (qpi->qpi_flags & QF_GROUP) - fin->fin_flx |= FI_MBCAST; + if (qpi->qpi_flags & QF_BROADCAST) + fin->fin_flx |= FI_MBCAST|FI_BROADCAST; + if (qpi->qpi_flags & QF_MULTICAST) + fin->fin_flx |= FI_MBCAST|FI_MULTICAST; m = qpi->qpi_m; fin->fin_qfm = m; fin->fin_qpi = qpi; @@ -2225,6 +2865,10 @@ int out; if ((m->m_flags & M_MCAST) != 0) fin->fin_flx |= FI_MBCAST|FI_MULTICAST; # endif +# if defined(M_MLOOP) + if ((m->m_flags & M_MLOOP) != 0) + fin->fin_flx |= FI_MBCAST|FI_MULTICAST; +# endif # if defined(M_BCAST) if ((m->m_flags & M_BCAST) != 0) fin->fin_flx |= FI_MBCAST|FI_BROADCAST; @@ -2237,7 +2881,8 @@ int out; */ m->m_flags &= ~M_CANFASTFWD; # endif /* M_CANFASTFWD */ -# ifdef CSUM_DELAY_DATA +# if defined(CSUM_DELAY_DATA) && (!defined(__FreeBSD_version) || \ + (__FreeBSD_version < 501108)) /* * disable delayed checksums. */ @@ -2248,10 +2893,20 @@ int out; # endif /* CSUM_DELAY_DATA */ # endif /* MENTAT */ #else - READ_ENTER(&ipf_global); - bzero((char *)fin, sizeof(*fin)); m = *mp; +# if defined(M_MCAST) + if ((m->m_flags & M_MCAST) != 0) + fin->fin_flx |= FI_MBCAST|FI_MULTICAST; +# endif +# if defined(M_MLOOP) + if ((m->m_flags & M_MLOOP) != 0) + fin->fin_flx |= FI_MBCAST|FI_MULTICAST; +# endif +# if defined(M_BCAST) + if ((m->m_flags & M_BCAST) != 0) + fin->fin_flx |= FI_MBCAST|FI_BROADCAST; +# endif #endif /* _KERNEL */ fin->fin_v = v; @@ -2261,38 +2916,41 @@ int out; fin->fin_out = out; fin->fin_ifp = ifp; fin->fin_error = ENETUNREACH; - fin->fin_hlen = (u_short )hlen; + fin->fin_hlen = (u_short)hlen; fin->fin_dp = (char *)ip + hlen; + fin->fin_main_soft = softc; fin->fin_ipoff = (char *)ip - MTOD(m, char *); + SPL_NET(s); + #ifdef USE_INET6 if (v == 6) { - ATOMIC_INCL(frstats[out].fr_ipv6); + LBUMP(ipf_stats[out].fr_ipv6); /* * Jumbo grams are quite likely too big for internal buffer * structures to handle comfortably, for now, so just drop * them. */ - ip6 = (ip6_t *)ip; - fin->fin_plen = ntohs(ip6->ip6_plen); - if (fin->fin_plen == 0) { + if (((ip6_t *)ip)->ip6_plen == 0) { + DT1(frb_jumbo, ip6_t *, (ip6_t *)ip); pass = FR_BLOCK|FR_NOMATCH; - goto filtered; + fin->fin_reason = FRB_JUMBO; + goto finished; } - fin->fin_plen += sizeof(ip6_t); + fin->fin_family = AF_INET6; } else #endif { -#if (OpenBSD >= 200311) && defined(_KERNEL) - ip->ip_len = ntohs(ip->ip_len); - ip->ip_off = ntohs(ip->ip_off); -#endif - fin->fin_plen = ip->ip_len; + fin->fin_family = AF_INET; } - if (fr_makefrip(hlen, ip, fin) == -1) + if (ipf_makefrip(hlen, ip, fin) == -1) { + DT1(frb_makefrip, fr_info_t *, fin); + pass = FR_BLOCK|FR_NOMATCH; + fin->fin_reason = FRB_MAKEFRIP; goto finished; + } /* * For at least IPv6 packets, if a m_pullup() fails then this pointer @@ -2303,22 +2961,19 @@ int out; if (!out) { if (v == 4) { -#ifdef _KERNEL - if (fr_chksrc && !fr_verifysrc(fin)) { - ATOMIC_INCL(frstats[0].fr_badsrc); + if (softc->ipf_chksrc && !ipf_verifysrc(fin)) { + LBUMPD(ipf_stats[0], fr_v4_badsrc); fin->fin_flx |= FI_BADSRC; } -#endif - if (fin->fin_ip->ip_ttl < fr_minttl) { - ATOMIC_INCL(frstats[0].fr_badttl); + if (fin->fin_ip->ip_ttl < softc->ipf_minttl) { + LBUMPD(ipf_stats[0], fr_v4_badttl); fin->fin_flx |= FI_LOWTTL; } } #ifdef USE_INET6 else if (v == 6) { - ip6 = (ip6_t *)ip; - if (ip6->ip6_hlim < fr_minttl) { - ATOMIC_INCL(frstats[0].fr_badttl); + if (((ip6_t *)ip)->ip6_hlim < softc->ipf_minttl) { + LBUMPD(ipf_stats[0], fr_v6_badttl); fin->fin_flx |= FI_LOWTTL; } } @@ -2326,90 +2981,153 @@ int out; } if (fin->fin_flx & FI_SHORT) { - ATOMIC_INCL(frstats[out].fr_short); + LBUMPD(ipf_stats[out], fr_short); } - READ_ENTER(&ipf_mutex); + READ_ENTER(&softc->ipf_mutex); - /* - * Check auth now. This, combined with the check below to see if apass - * is 0 is to ensure that we don't count the packet twice, which can - * otherwise occur when we reprocess it. As it is, we only count it - * after it has no auth. table matchup. This also stops NAT from - * occuring until after the packet has been auth'd. - */ - fr = fr_checkauth(fin, &pass); if (!out) { - if (fr_checknatin(fin, &pass) == -1) { - RWLOCK_EXIT(&ipf_mutex); - goto finished; + switch (fin->fin_v) + { + case 4 : + if (ipf_nat_checkin(fin, &pass) == -1) { + goto filterdone; + } + break; +#ifdef USE_INET6 + case 6 : + if (ipf_nat6_checkin(fin, &pass) == -1) { + goto filterdone; + } + break; +#endif + default : + break; } } - if (!out) - (void) fr_acctpkt(fin, NULL); + /* + * Check auth now. + * If a packet is found in the auth table, then skip checking + * the access lists for permission but we do need to consider + * the result as if it were from the ACL's. In addition, being + * found in the auth table means it has been seen before, so do + * not pass it through accounting (again), lest it be counted twice. + */ + fr = ipf_auth_check(fin, &pass); + if (!out && (fr == NULL)) + (void) ipf_acctpkt(fin, NULL); - if (fr == NULL) - if ((fin->fin_flx & (FI_FRAG|FI_BAD)) == FI_FRAG) - fr = fr_knownfrag(fin, &pass); - if (fr == NULL) - fr = fr_checkstate(fin, &pass); + if (fr == NULL) { + if ((fin->fin_flx & FI_FRAG) != 0) + fr = ipf_frag_known(fin, &pass); + + if (fr == NULL) + fr = ipf_state_check(fin, &pass); + } if ((pass & FR_NOMATCH) || (fr == NULL)) - fr = fr_firewall(fin, &pass); + fr = ipf_firewall(fin, &pass); + + /* + * If we've asked to track state for this packet, set it up. + * Here rather than ipf_firewall because ipf_checkauth may decide + * to return a packet for "keep state" + */ + if ((pass & FR_KEEPSTATE) && (fin->fin_m != NULL) && + !(fin->fin_flx & FI_STATE)) { + if (ipf_state_add(softc, fin, NULL, 0) == 0) { + LBUMP(ipf_stats[out].fr_ads); + } else { + LBUMP(ipf_stats[out].fr_bads); + if (FR_ISPASS(pass)) { + DT(frb_stateadd); + pass &= ~FR_CMDMASK; + pass |= FR_BLOCK; + fin->fin_reason = FRB_STATEADD; + } + } + } fin->fin_fr = fr; + if ((fr != NULL) && !(fin->fin_flx & FI_STATE)) { + fin->fin_dif = &fr->fr_dif; + fin->fin_tif = &fr->fr_tifs[fin->fin_rev]; + } /* * Only count/translate packets which will be passed on, out the * interface. */ if (out && FR_ISPASS(pass)) { - (void) fr_acctpkt(fin, NULL); + (void) ipf_acctpkt(fin, NULL); - if (fr_checknatout(fin, &pass) == -1) { - RWLOCK_EXIT(&ipf_mutex); - goto finished; - } else if ((fr_update_ipid != 0) && (v == 4)) { - if (fr_updateipid(fin) == -1) { - ATOMIC_INCL(frstats[1].fr_ipud); - pass &= ~FR_CMDMASK; - pass |= FR_BLOCK; - } else { - ATOMIC_INCL(frstats[0].fr_ipud); + switch (fin->fin_v) + { + case 4 : + if (ipf_nat_checkout(fin, &pass) == -1) { + ; + } else if ((softc->ipf_update_ipid != 0) && (v == 4)) { + if (ipf_updateipid(fin) == -1) { + DT(frb_updateipid); + LBUMP(ipf_stats[1].fr_ipud); + pass &= ~FR_CMDMASK; + pass |= FR_BLOCK; + fin->fin_reason = FRB_UPDATEIPID; + } else { + LBUMP(ipf_stats[0].fr_ipud); + } } + break; +#ifdef USE_INET6 + case 6 : + (void) ipf_nat6_checkout(fin, &pass); + break; +#endif + default : + break; } } +filterdone: #ifdef IPFILTER_LOG - if ((fr_flags & FF_LOGGING) || (pass & FR_LOGMASK)) { - (void) fr_dolog(fin, &pass); + if ((softc->ipf_flags & FF_LOGGING) || (pass & FR_LOGMASK)) { + (void) ipf_dolog(fin, &pass); } #endif - if (fin->fin_state != NULL) - fr_statederef(fin, (ipstate_t **)&fin->fin_state); - - if (fin->fin_nat != NULL) - fr_natderef((nat_t **)&fin->fin_nat); + /* + * The FI_STATE flag is cleared here so that calling ipf_state_check + * will work when called from inside of fr_fastroute. Although + * there is a similar flag, FI_NATED, for NAT, it does have the same + * impact on code execution. + */ + fin->fin_flx &= ~FI_STATE; +#if defined(FASTROUTE_RECURSION) /* - * Only allow FR_DUP to work if a rule matched - it makes no sense to - * set FR_DUP as a "default" as there are no instructions about where - * to send the packet. Use fin_m here because it may have changed - * (without an update of 'm') in prior processing. + * Up the reference on fr_lock and exit ipf_mutex. The generation of + * a packet below can sometimes cause a recursive call into IPFilter. + * On those platforms where that does happen, we need to hang onto + * the filter rule just in case someone decides to remove or flush it + * in the meantime. */ - if ((fr != NULL) && (pass & FR_DUP)) { - mc = M_DUPLICATE(fin->fin_m); + if (fr != NULL) { + MUTEX_ENTER(&fr->fr_lock); + fr->fr_ref++; + MUTEX_EXIT(&fr->fr_lock); } - if (pass & (FR_RETRST|FR_RETICMP)) { + RWLOCK_EXIT(&softc->ipf_mutex); +#endif + + if ((pass & FR_RETMASK) != 0) { /* * Should we return an ICMP packet to indicate error * status passing through the packet filter ? * WARNING: ICMP error packets AND TCP RST packets should - * ONLY be sent in repsonse to incoming packets. Sending them - * in response to outbound packets can result in a panic on - * some operating systems. + * ONLY be sent in repsonse to incoming packets. Sending + * them in response to outbound packets can result in a + * panic on some operating systems. */ if (!out) { if (pass & FR_RETICMP) { @@ -2419,95 +3137,120 @@ int out; dst = 1; else dst = 0; - (void) fr_send_icmp_err(ICMP_UNREACH, fin, dst); - ATOMIC_INCL(frstats[0].fr_ret); + (void) ipf_send_icmp_err(ICMP_UNREACH, fin, + dst); + LBUMP(ipf_stats[0].fr_ret); } else if (((pass & FR_RETMASK) == FR_RETRST) && !(fin->fin_flx & FI_SHORT)) { - if (fr_send_reset(fin) == 0) { - ATOMIC_INCL(frstats[1].fr_ret); + if (((fin->fin_flx & FI_OOW) != 0) || + (ipf_send_reset(fin) == 0)) { + LBUMP(ipf_stats[1].fr_ret); } } + + /* + * When using return-* with auth rules, the auth code + * takes over disposing of this packet. + */ + if (FR_ISAUTH(pass) && (fin->fin_m != NULL)) { + DT1(frb_authcapture, fr_info_t *, fin); + fin->fin_m = *fin->fin_mp = NULL; + fin->fin_reason = FRB_AUTHCAPTURE; + m = NULL; + } } else { - if (pass & FR_RETRST) + if (pass & FR_RETRST) { fin->fin_error = ECONNRESET; + } } } /* + * After the above so that ICMP unreachables and TCP RSTs get + * created properly. + */ + if (FR_ISBLOCK(pass) && (fin->fin_flx & FI_NEWNAT)) + ipf_nat_uncreate(fin); + + /* * If we didn't drop off the bottom of the list of rules (and thus * the 'current' rule fr is not NULL), then we may have some extra * instructions about what to do with a packet. * Once we're finished return to our caller, freeing the packet if - * we are dropping it (* BSD ONLY *). - * Reassign m from fin_m as we may have a new buffer, now. + * we are dropping it. */ -#if defined(USE_INET6) || (defined(__sgi) && defined(_KERNEL)) -filtered: -#endif - m = fin->fin_m; - if (fr != NULL) { frdest_t *fdp; - fdp = &fr->fr_tifs[fin->fin_rev]; + /* + * Generate a duplicated packet first because ipf_fastroute + * can lead to fin_m being free'd... not good. + */ + fdp = fin->fin_dif; + if ((fdp != NULL) && (fdp->fd_ptr != NULL) && + (fdp->fd_ptr != (void *)-1)) { + mc = M_COPY(fin->fin_m); + if (mc != NULL) + ipf_fastroute(mc, &mc, fin, fdp); + } + fdp = fin->fin_tif; if (!out && (pass & FR_FASTROUTE)) { /* - * For fastroute rule, no destioation interface defined + * For fastroute rule, no destination interface defined * so pass NULL as the frdest_t parameter */ - (void) fr_fastroute(m, mp, fin, NULL); + (void) ipf_fastroute(fin->fin_m, mp, fin, NULL); m = *mp = NULL; - } else if ((fdp->fd_ifp != NULL) && - (fdp->fd_ifp != (struct ifnet *)-1)) { + } else if ((fdp != NULL) && (fdp->fd_ptr != NULL) && + (fdp->fd_ptr != (struct ifnet *)-1)) { /* this is for to rules: */ - (void) fr_fastroute(m, mp, fin, fdp); + ipf_fastroute(fin->fin_m, mp, fin, fdp); m = *mp = NULL; } - /* - * Generate a duplicated packet. - */ - if (mc != NULL) - (void) fr_fastroute(mc, &mc, fin, &fr->fr_dif); +#if defined(FASTROUTE_RECURSION) + (void) ipf_derefrule(softc, &fr); +#endif } - - /* - * This late because the likes of fr_fastroute() use fin_fr. - */ - RWLOCK_EXIT(&ipf_mutex); +#if !defined(FASTROUTE_RECURSION) + RWLOCK_EXIT(&softc->ipf_mutex); +#endif finished: if (!FR_ISPASS(pass)) { - ATOMIC_INCL(frstats[out].fr_block); + LBUMP(ipf_stats[out].fr_block); if (*mp != NULL) { +#ifdef _KERNEL FREE_MB_T(*mp); +#endif m = *mp = NULL; } } else { - ATOMIC_INCL(frstats[out].fr_pass); + LBUMP(ipf_stats[out].fr_pass); #if defined(_KERNEL) && defined(__sgi) if ((fin->fin_hbuf != NULL) && (mtod(fin->fin_m, struct ip *) != fin->fin_ip)) { - COPYBACK(m, 0, fin->fin_plen, fin->fin_hbuf); + COPYBACK(fin->fin_m, 0, fin->fin_plen, fin->fin_hbuf); } #endif } - RWLOCK_EXIT(&ipf_global); + SPL_X(s); + #ifdef _KERNEL -# if OpenBSD >= 200311 - if (FR_ISPASS(pass) && (v == 4)) { - ip = fin->fin_ip; - ip->ip_len = ntohs(ip->ip_len); - ip->ip_off = ntohs(ip->ip_off); - } -# endif - return (FR_ISPASS(pass)) ? 0 : fin->fin_error; + if (FR_ISPASS(pass)) + return 0; + LBUMP(ipf_stats[out].fr_blocked[fin->fin_reason]); + return fin->fin_error; #else /* _KERNEL */ + if (*mp != NULL) + (*mp)->mb_ifp = fin->fin_ifp; + blockreason = fin->fin_reason; FR_VERBOSE(("fin_flx %#x pass %#x ", fin->fin_flx, pass)); - if ((pass & FR_NOMATCH) != 0) - return 1; + /*if ((pass & FR_CMDMASK) == (softc->ipf_pass & FR_CMDMASK))*/ + if ((pass & FR_NOMATCH) != 0) + return 1; if ((pass & FR_RETMASK) != 0) switch (pass & FR_RETMASK) @@ -2540,7 +3283,7 @@ finished: #ifdef IPFILTER_LOG /* ------------------------------------------------------------------------ */ -/* Function: fr_dolog */ +/* Function: ipf_dolog */ /* Returns: frentry_t* - returns contents of fin_fr (no change made) */ /* Parameters: fin(I) - pointer to packet information */ /* passp(IO) - pointer to current/new filter decision (unused) */ @@ -2548,43 +3291,47 @@ finished: /* Checks flags set to see how a packet should be logged, if it is to be */ /* logged. Adjust statistics based on its success or not. */ /* ------------------------------------------------------------------------ */ -frentry_t *fr_dolog(fin, passp) -fr_info_t *fin; -u_32_t *passp; +frentry_t * +ipf_dolog(fin, passp) + fr_info_t *fin; + u_32_t *passp; { + ipf_main_softc_t *softc = fin->fin_main_soft; u_32_t pass; int out; out = fin->fin_out; pass = *passp; - if ((fr_flags & FF_LOGNOMATCH) && (pass & FR_NOMATCH)) { + if ((softc->ipf_flags & FF_LOGNOMATCH) && (pass & FR_NOMATCH)) { pass |= FF_LOGNOMATCH; - ATOMIC_INCL(frstats[out].fr_npkl); + LBUMPD(ipf_stats[out], fr_npkl); goto logit; + } else if (((pass & FR_LOGMASK) == FR_LOGP) || - (FR_ISPASS(pass) && (fr_flags & FF_LOGPASS))) { + (FR_ISPASS(pass) && (softc->ipf_flags & FF_LOGPASS))) { if ((pass & FR_LOGMASK) != FR_LOGP) pass |= FF_LOGPASS; - ATOMIC_INCL(frstats[out].fr_ppkl); + LBUMPD(ipf_stats[out], fr_ppkl); goto logit; + } else if (((pass & FR_LOGMASK) == FR_LOGB) || - (FR_ISBLOCK(pass) && (fr_flags & FF_LOGBLOCK))) { + (FR_ISBLOCK(pass) && (softc->ipf_flags & FF_LOGBLOCK))) { if ((pass & FR_LOGMASK) != FR_LOGB) pass |= FF_LOGBLOCK; - ATOMIC_INCL(frstats[out].fr_bpkl); -logit: - if (ipflog(fin, pass) == -1) { - ATOMIC_INCL(frstats[out].fr_skip); + LBUMPD(ipf_stats[out], fr_bpkl); +logit: + if (ipf_log_pkt(fin, pass) == -1) { /* * If the "or-block" option has been used then * block the packet if we failed to log it. */ - if ((pass & FR_LOGORBLOCK) && - FR_ISPASS(pass)) { + if ((pass & FR_LOGORBLOCK) && FR_ISPASS(pass)) { + DT1(frb_logfail2, u_int, pass); pass &= ~FR_CMDMASK; pass |= FR_BLOCK; + fin->fin_reason = FRB_LOGFAIL2; } } *passp = pass; @@ -2605,9 +3352,10 @@ logit: /* */ /* N.B.: addr should be 16bit aligned. */ /* ------------------------------------------------------------------------ */ -u_short ipf_cksum(addr, len) -u_short *addr; -int len; +u_short +ipf_cksum(addr, len) + u_short *addr; + int len; { u_32_t sum = 0; @@ -2630,7 +3378,7 @@ int len; /* ------------------------------------------------------------------------ */ /* Function: fr_cksum */ /* Returns: u_short - layer 4 checksum */ -/* Parameters: m(I ) - pointer to buffer holding packet */ +/* Parameters: fin(I) - pointer to packet information */ /* ip(I) - pointer to IP header */ /* l4proto(I) - protocol to caclulate checksum for */ /* l4hdr(I) - pointer to layer 4 header */ @@ -2642,29 +3390,31 @@ int len; /* and the TCP header. We also assume that data blocks aren't allocated in */ /* odd sizes. */ /* */ -/* Expects ip_len to be in host byte order when called. */ +/* Expects ip_len and ip_off to be in network byte order when called. */ /* ------------------------------------------------------------------------ */ -u_short fr_cksum(m, ip, l4proto, l4hdr) -mb_t *m; -ip_t *ip; -int l4proto; -void *l4hdr; +u_short +fr_cksum(fin, ip, l4proto, l4hdr) + fr_info_t *fin; + ip_t *ip; + int l4proto; + void *l4hdr; { - u_short *sp, slen, sumsave, l4hlen, *csump; + u_short *sp, slen, sumsave, *csump; u_int sum, sum2; int hlen; + int off; #ifdef USE_INET6 ip6_t *ip6; #endif csump = NULL; sumsave = 0; - l4hlen = 0; sp = NULL; slen = 0; hlen = 0; sum = 0; + sum = htons((u_short)l4proto); /* * Add up IP Header portion */ @@ -2672,9 +3422,7 @@ void *l4hdr; if (IP_V(ip) == 4) { #endif hlen = IP_HL(ip) << 2; - slen = ip->ip_len - hlen; - sum = htons((u_short)l4proto); - sum += htons(slen); + off = hlen; sp = (u_short *)&ip->ip_src; sum += *sp++; /* ip_src */ sum += *sp++; @@ -2684,9 +3432,7 @@ void *l4hdr; } else if (IP_V(ip) == 6) { ip6 = (ip6_t *)ip; hlen = sizeof(*ip6); - slen = ntohs(ip6->ip6_plen); - sum = htons((u_short)l4proto); - sum += htons(slen); + off = ((char *)fin->fin_dp - (char *)fin->fin_ip); sp = (u_short *)&ip6->ip6_src; sum += *sp++; /* ip6_src */ sum += *sp++; @@ -2696,6 +3442,7 @@ void *l4hdr; sum += *sp++; sum += *sp++; sum += *sp++; + /* This needs to be routing header aware. */ sum += *sp++; /* ip6_dst */ sum += *sp++; sum += *sp++; @@ -2704,25 +3451,31 @@ void *l4hdr; sum += *sp++; sum += *sp++; sum += *sp++; + } else { + return 0xffff; } #endif + slen = fin->fin_plen - off; + sum += htons(slen); switch (l4proto) { case IPPROTO_UDP : csump = &((udphdr_t *)l4hdr)->uh_sum; - l4hlen = sizeof(udphdr_t); break; case IPPROTO_TCP : csump = &((tcphdr_t *)l4hdr)->th_sum; - l4hlen = sizeof(tcphdr_t); break; case IPPROTO_ICMP : csump = &((icmphdr_t *)l4hdr)->icmp_cksum; - l4hlen = 4; - sum = 0; + sum = 0; /* Pseudo-checksum is not included */ + break; +#ifdef USE_INET6 + case IPPROTO_ICMPV6 : + csump = &((struct icmp6_hdr *)l4hdr)->icmp6_cksum; break; +#endif default : break; } @@ -2732,292 +3485,18 @@ void *l4hdr; *csump = 0; } - l4hlen = l4hlen; /* LINT */ - -#ifdef _KERNEL -# ifdef MENTAT - { - void *rp = m->b_rptr; - - if ((unsigned char *)ip > m->b_rptr && (unsigned char *)ip < m->b_wptr) - m->b_rptr = (u_char *)ip; - sum2 = ip_cksum(m, hlen, sum); /* hlen == offset */ - m->b_rptr = rp; - sum2 = (u_short)(~sum2 & 0xffff); - } -# else /* MENTAT */ -# if defined(BSD) || defined(sun) -# if BSD >= 199103 - m->m_data += hlen; -# else - m->m_off += hlen; -# endif - m->m_len -= hlen; - sum2 = in_cksum(m, slen); - m->m_len += hlen; -# if BSD >= 199103 - m->m_data -= hlen; -# else - m->m_off -= hlen; -# endif - /* - * Both sum and sum2 are partial sums, so combine them together. - */ - sum += ~sum2 & 0xffff; - while (sum > 0xffff) - sum = (sum & 0xffff) + (sum >> 16); - sum2 = ~sum & 0xffff; -# else /* defined(BSD) || defined(sun) */ -{ - union { - u_char c[2]; - u_short s; - } bytes; - u_short len = ip->ip_len; -# if defined(__sgi) - int add; -# endif - - /* - * Add up IP Header portion - */ - if (sp != (u_short *)l4hdr) - sp = (u_short *)l4hdr; - - switch (l4proto) - { - case IPPROTO_UDP : - sum += *sp++; /* sport */ - sum += *sp++; /* dport */ - sum += *sp++; /* udp length */ - sum += *sp++; /* checksum */ - break; - - case IPPROTO_TCP : - sum += *sp++; /* sport */ - sum += *sp++; /* dport */ - sum += *sp++; /* seq */ - sum += *sp++; - sum += *sp++; /* ack */ - sum += *sp++; - sum += *sp++; /* off */ - sum += *sp++; /* win */ - sum += *sp++; /* checksum */ - sum += *sp++; /* urp */ - break; - case IPPROTO_ICMP : - sum = *sp++; /* type/code */ - sum += *sp++; /* checksum */ - break; - } - -# ifdef __sgi - /* - * In case we had to copy the IP & TCP header out of mbufs, - * skip over the mbuf bits which are the header - */ - if ((caddr_t)ip != mtod(m, caddr_t)) { - hlen = (caddr_t)sp - (caddr_t)ip; - while (hlen) { - add = MIN(hlen, m->m_len); - sp = (u_short *)(mtod(m, caddr_t) + add); - hlen -= add; - if (add == m->m_len) { - m = m->m_next; - if (!hlen) { - if (!m) - break; - sp = mtod(m, u_short *); - } - PANIC((!m),("fr_cksum(1): not enough data")); - } - } - } -# endif - - len -= (l4hlen + hlen); - if (len <= 0) - goto nodata; - - while (len > 1) { - if (((caddr_t)sp - mtod(m, caddr_t)) >= m->m_len) { - m = m->m_next; - PANIC((!m),("fr_cksum(2): not enough data")); - sp = mtod(m, u_short *); - } - if (((caddr_t)(sp + 1) - mtod(m, caddr_t)) > m->m_len) { - bytes.c[0] = *(u_char *)sp; - m = m->m_next; - PANIC((!m),("fr_cksum(3): not enough data")); - sp = mtod(m, u_short *); - bytes.c[1] = *(u_char *)sp; - sum += bytes.s; - sp = (u_short *)((u_char *)sp + 1); - } - if ((u_long)sp & 1) { - bcopy((char *)sp++, (char *)&bytes.s, sizeof(bytes.s)); - sum += bytes.s; - } else - sum += *sp++; - len -= 2; - } - - if (len != 0) - sum += ntohs(*(u_char *)sp << 8); -nodata: - while (sum > 0xffff) - sum = (sum & 0xffff) + (sum >> 16); - sum2 = (u_short)(~sum & 0xffff); -} -# endif /* defined(BSD) || defined(sun) */ -# endif /* MENTAT */ -#else /* _KERNEL */ - for (; slen > 1; slen -= 2) - sum += *sp++; - if (slen) - sum += ntohs(*(u_char *)sp << 8); - while (sum > 0xffff) - sum = (sum & 0xffff) + (sum >> 16); - sum2 = (u_short)(~sum & 0xffff); -#endif /* _KERNEL */ + sum2 = ipf_pcksum(fin, off, sum); if (csump != NULL) *csump = sumsave; return sum2; } -#if defined(_KERNEL) && ( ((BSD < 199103) && !defined(MENTAT)) || \ - defined(__sgi) ) && !defined(linux) -/* - * Copyright (c) 1982, 1986, 1988, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 - * Id: fil.c,v 2.243.2.57 2005/03/28 10:47:50 darrenr Exp - */ -/* - * Copy data from an mbuf chain starting "off" bytes from the beginning, - * continuing for "len" bytes, into the indicated buffer. - */ -void -m_copydata(m, off, len, cp) - mb_t *m; - int off; - int len; - caddr_t cp; -{ - unsigned count; - - if (off < 0 || len < 0) - panic("m_copydata"); - while (off > 0) { - if (m == 0) - panic("m_copydata"); - if (off < m->m_len) - break; - off -= m->m_len; - m = m->m_next; - } - while (len > 0) { - if (m == 0) - panic("m_copydata"); - count = MIN(m->m_len - off, len); - bcopy(mtod(m, caddr_t) + off, cp, count); - len -= count; - cp += count; - off = 0; - m = m->m_next; - } -} - - -/* - * Copy data from a buffer back into the indicated mbuf chain, - * starting "off" bytes from the beginning, extending the mbuf - * chain if necessary. - */ -void -m_copyback(m0, off, len, cp) - struct mbuf *m0; - int off; - int len; - caddr_t cp; -{ - int mlen; - struct mbuf *m = m0, *n; - int totlen = 0; - - if (m0 == 0) - return; - while (off > (mlen = m->m_len)) { - off -= mlen; - totlen += mlen; - if (m->m_next == 0) { - n = m_getclr(M_DONTWAIT, m->m_type); - if (n == 0) - goto out; - n->m_len = min(MLEN, len + off); - m->m_next = n; - } - m = m->m_next; - } - while (len > 0) { - mlen = min (m->m_len - off, len); - bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen); - cp += mlen; - len -= mlen; - mlen += off; - off = 0; - totlen += mlen; - if (len == 0) - break; - if (m->m_next == 0) { - n = m_get(M_DONTWAIT, m->m_type); - if (n == 0) - break; - n->m_len = min(MLEN, len); - m->m_next = n; - } - m = m->m_next; - } -out: -#if 0 - if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen)) - m->m_pkthdr.len = totlen; -#endif - return; -} -#endif /* (_KERNEL) && ( ((BSD < 199103) && !MENTAT) || __sgi) */ - - /* ------------------------------------------------------------------------ */ -/* Function: fr_findgroup */ +/* Function: ipf_findgroup */ /* Returns: frgroup_t * - NULL = group not found, else pointer to group */ -/* Parameters: group(I) - group name to search for */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* group(I) - group name to search for */ /* unit(I) - device to which this group belongs */ /* set(I) - which set of rules (inactive/inactive) this is */ /* fgpp(O) - pointer to place to store pointer to the pointer */ @@ -3026,19 +3505,21 @@ out: /* */ /* Search amongst the defined groups for a particular group number. */ /* ------------------------------------------------------------------------ */ -frgroup_t *fr_findgroup(group, unit, set, fgpp) -char *group; -minor_t unit; -int set; -frgroup_t ***fgpp; +frgroup_t * +ipf_findgroup(softc, group, unit, set, fgpp) + ipf_main_softc_t *softc; + char *group; + minor_t unit; + int set; + frgroup_t ***fgpp; { frgroup_t *fg, **fgp; /* - * Which list of groups to search in is dependant on which list of + * Which list of groups to search in is dependent on which list of * rules are being operated on. */ - fgp = &ipfgroups[unit][set]; + fgp = &softc->ipf_groups[unit][set]; while ((fg = *fgp) != NULL) { if (strncmp(group, fg->fg_name, FR_GROUPLEN) == 0) @@ -3053,10 +3534,11 @@ frgroup_t ***fgpp; /* ------------------------------------------------------------------------ */ -/* Function: fr_addgroup */ +/* Function: ipf_group_add */ /* Returns: frgroup_t * - NULL == did not create group, */ /* != NULL == pointer to the group */ -/* Parameters: num(I) - group number to add */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* num(I) - group number to add */ /* head(I) - rule pointer that is using this as the head */ /* flags(I) - rule flags which describe the type of rule it is */ /* unit(I) - device to which this group will belong to */ @@ -3066,12 +3548,14 @@ frgroup_t ***fgpp; /* Add a new group head, or if it already exists, increase the reference */ /* count to it. */ /* ------------------------------------------------------------------------ */ -frgroup_t *fr_addgroup(group, head, flags, unit, set) -char *group; -void *head; -u_32_t flags; -minor_t unit; -int set; +frgroup_t * +ipf_group_add(softc, group, head, flags, unit, set) + ipf_main_softc_t *softc; + char *group; + void *head; + u_32_t flags; + minor_t unit; + int set; { frgroup_t *fg, **fgp; u_32_t gflags; @@ -3085,8 +3569,10 @@ int set; fgp = NULL; gflags = flags & FR_INOUT; - fg = fr_findgroup(group, unit, set, &fgp); + fg = ipf_findgroup(softc, group, unit, set, &fgp); if (fg != NULL) { + if (fg->fg_head == NULL && head != NULL) + fg->fg_head = head; if (fg->fg_flags == 0) fg->fg_flags = gflags; else if (gflags != fg->fg_flags) @@ -3094,14 +3580,16 @@ int set; fg->fg_ref++; return fg; } + KMALLOC(fg, frgroup_t *); if (fg != NULL) { fg->fg_head = head; fg->fg_start = NULL; fg->fg_next = *fgp; - bcopy(group, fg->fg_name, FR_GROUPLEN); + bcopy(group, fg->fg_name, strlen(group) + 1); fg->fg_flags = gflags; fg->fg_ref = 1; + fg->fg_set = &softc->ipf_groups[unit][set]; *fgp = fg; } return fg; @@ -3109,38 +3597,82 @@ int set; /* ------------------------------------------------------------------------ */ -/* Function: fr_delgroup */ -/* Returns: Nil */ -/* Parameters: group(I) - group name to delete */ -/* unit(I) - device to which this group belongs */ -/* set(I) - which set of rules (inactive/inactive) this is */ +/* Function: ipf_group_del */ +/* Returns: int - number of rules deleted */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* group(I) - group name to delete */ +/* fr(I) - filter rule from which group is referenced */ /* Write Locks: ipf_mutex */ /* */ -/* Attempt to delete a group head. */ -/* Only do this when its reference count reaches 0. */ +/* This function is called whenever a reference to a group is to be dropped */ +/* and thus its reference count needs to be lowered and the group free'd if */ +/* the reference count reaches zero. Passing in fr is really for the sole */ +/* purpose of knowing when the head rule is being deleted. */ /* ------------------------------------------------------------------------ */ -void fr_delgroup(group, unit, set) -char *group; -minor_t unit; -int set; +void +ipf_group_del(softc, group, fr) + ipf_main_softc_t *softc; + frgroup_t *group; + frentry_t *fr; { - frgroup_t *fg, **fgp; - fg = fr_findgroup(group, unit, set, &fgp); - if (fg == NULL) - return; + if (group->fg_head == fr) + group->fg_head = NULL; + + group->fg_ref--; + if ((group->fg_ref == 0) && (group->fg_start == NULL)) + ipf_group_free(group); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_group_free */ +/* Returns: Nil */ +/* Parameters: group(I) - pointer to filter rule group */ +/* */ +/* Remove the group from the list of groups and free it. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_group_free(group) + frgroup_t *group; +{ + frgroup_t **gp; - fg->fg_ref--; - if (fg->fg_ref == 0) { - *fgp = fg->fg_next; - KFREE(fg); + for (gp = group->fg_set; *gp != NULL; gp = &(*gp)->fg_next) { + if (*gp == group) { + *gp = group->fg_next; + break; + } } + KFREE(group); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_group_flush */ +/* Returns: int - number of rules flush from group */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* Parameters: group(I) - pointer to filter rule group */ +/* */ +/* Remove all of the rules that currently are listed under the given group. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_group_flush(softc, group) + ipf_main_softc_t *softc; + frgroup_t *group; +{ + int gone = 0; + + (void) ipf_flushlist(softc, &gone, &group->fg_start); + + return gone; } /* ------------------------------------------------------------------------ */ -/* Function: fr_getrulen */ +/* Function: ipf_getrulen */ /* Returns: frentry_t * - NULL == not found, else pointer to rule n */ +/* Parameters: softc(I) - pointer to soft context main structure */ /* Parameters: unit(I) - device for which to count the rule's number */ /* flags(I) - which set of rules to find the rule in */ /* group(I) - group name */ @@ -3149,18 +3681,20 @@ int set; /* Find rule # n in group # g and return a pointer to it. Return NULl if */ /* group # g doesn't exist or there are less than n rules in the group. */ /* ------------------------------------------------------------------------ */ -frentry_t *fr_getrulen(unit, group, n) -int unit; -char *group; -u_32_t n; +frentry_t * +ipf_getrulen(softc, unit, group, n) + ipf_main_softc_t *softc; + int unit; + char *group; + u_32_t n; { frentry_t *fr; frgroup_t *fg; - fg = fr_findgroup(group, unit, fr_active, NULL); + fg = ipf_findgroup(softc, group, unit, softc->ipf_active, NULL); if (fg == NULL) return NULL; - for (fr = fg->fg_head; fr && n; fr = fr->fr_next, n--) + for (fr = fg->fg_start; fr && n; fr = fr->fr_next, n--) ; if (n != 0) return NULL; @@ -3169,41 +3703,9 @@ u_32_t n; /* ------------------------------------------------------------------------ */ -/* Function: fr_rulen */ -/* Returns: int - >= 0 - rule number, -1 == search failed */ -/* Parameters: unit(I) - device for which to count the rule's number */ -/* fr(I) - pointer to rule to match */ -/* */ -/* Return the number for a rule on a specific filtering device. */ -/* ------------------------------------------------------------------------ */ -int fr_rulen(unit, fr) -int unit; -frentry_t *fr; -{ - frentry_t *fh; - frgroup_t *fg; - u_32_t n = 0; - - if (fr == NULL) - return -1; - fg = fr_findgroup(fr->fr_group, unit, fr_active, NULL); - if (fg == NULL) - return -1; - for (fh = fg->fg_head; fh; n++, fh = fh->fr_next) - if (fh == fr) - break; - if (fh == NULL) - return -1; - return n; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: frflushlist */ +/* Function: ipf_flushlist */ /* Returns: int - >= 0 - number of flushed rules */ -/* Parameters: set(I) - which set of rules (inactive/inactive) this is */ -/* unit(I) - device for which to flush rules */ -/* flags(I) - which set of rules to flush */ +/* Parameters: softc(I) - pointer to soft context main structure */ /* nfreedp(O) - pointer to int where flush count is stored */ /* listp(I) - pointer to list to flush pointer */ /* Write Locks: ipf_mutex */ @@ -3217,13 +3719,13 @@ frentry_t *fr; /* */ /* NOTE: Rules not loaded from user space cannot be flushed. */ /* ------------------------------------------------------------------------ */ -static int frflushlist(set, unit, nfreedp, listp) -int set; -minor_t unit; -int *nfreedp; -frentry_t **listp; +static int +ipf_flushlist(softc, nfreedp, listp) + ipf_main_softc_t *softc; + int *nfreedp; + frentry_t **listp; { - int freed = 0, i; + int freed = 0; frentry_t *fp; while ((fp = *listp) != NULL) { @@ -3233,19 +3735,27 @@ frentry_t **listp; continue; } *listp = fp->fr_next; - if (fp->fr_grp != NULL) { - i = frflushlist(set, unit, nfreedp, fp->fr_grp); - fp->fr_ref -= i; + if (fp->fr_next != NULL) + fp->fr_next->fr_pnext = fp->fr_pnext; + fp->fr_pnext = NULL; + + if (fp->fr_grphead != NULL) { + freed += ipf_group_flush(softc, fp->fr_grphead); + fp->fr_names[fp->fr_grhead] = '\0'; } - if (fp->fr_grhead != NULL) { - fr_delgroup(fp->fr_grhead, unit, set); - *fp->fr_grhead = '\0'; + if (fp->fr_icmpgrp != NULL) { + freed += ipf_group_flush(softc, fp->fr_icmpgrp); + fp->fr_names[fp->fr_icmphead] = '\0'; } - ASSERT(fp->fr_ref > 0); + if (fp->fr_srctrack.ht_max_nodes) + ipf_rb_ht_flush(&fp->fr_srctrack); + fp->fr_next = NULL; - if (fr_derefrule(&fp) == 0) + + ASSERT(fp->fr_ref > 0); + if (ipf_derefrule(softc, &fp) == 0) freed++; } *nfreedp += freed; @@ -3254,61 +3764,47 @@ frentry_t **listp; /* ------------------------------------------------------------------------ */ -/* Function: frflush */ +/* Function: ipf_flush */ /* Returns: int - >= 0 - number of flushed rules */ -/* Parameters: unit(I) - device for which to flush rules */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* unit(I) - device for which to flush rules */ /* flags(I) - which set of rules to flush */ /* */ /* Calls flushlist() for all filter rules (accounting, firewall - both IPv4 */ /* and IPv6) as defined by the value of flags. */ /* ------------------------------------------------------------------------ */ -int frflush(unit, proto, flags) -minor_t unit; -int proto, flags; +int +ipf_flush(softc, unit, flags) + ipf_main_softc_t *softc; + minor_t unit; + int flags; { int flushed = 0, set; - WRITE_ENTER(&ipf_mutex); - bzero((char *)frcache, sizeof(frcache)); + WRITE_ENTER(&softc->ipf_mutex); - set = fr_active; + set = softc->ipf_active; if ((flags & FR_INACTIVE) == FR_INACTIVE) set = 1 - set; if (flags & FR_OUTQUE) { - if (proto == 0 || proto == 6) { - (void) frflushlist(set, unit, - &flushed, &ipfilter6[1][set]); - (void) frflushlist(set, unit, - &flushed, &ipacct6[1][set]); - } - if (proto == 0 || proto == 4) { - (void) frflushlist(set, unit, - &flushed, &ipfilter[1][set]); - (void) frflushlist(set, unit, - &flushed, &ipacct[1][set]); - } + ipf_flushlist(softc, &flushed, &softc->ipf_rules[1][set]); + ipf_flushlist(softc, &flushed, &softc->ipf_acct[1][set]); } if (flags & FR_INQUE) { - if (proto == 0 || proto == 6) { - (void) frflushlist(set, unit, - &flushed, &ipfilter6[0][set]); - (void) frflushlist(set, unit, - &flushed, &ipacct6[0][set]); - } - if (proto == 0 || proto == 4) { - (void) frflushlist(set, unit, - &flushed, &ipfilter[0][set]); - (void) frflushlist(set, unit, - &flushed, &ipacct[0][set]); - } + ipf_flushlist(softc, &flushed, &softc->ipf_rules[0][set]); + ipf_flushlist(softc, &flushed, &softc->ipf_acct[0][set]); } - RWLOCK_EXIT(&ipf_mutex); + + flushed += ipf_flush_groups(softc, &softc->ipf_groups[unit][set], + flags & (FR_INQUE|FR_OUTQUE)); + + RWLOCK_EXIT(&softc->ipf_mutex); if (unit == IPL_LOGIPF) { int tmp; - tmp = frflush(IPL_LOGCOUNT, proto, flags); + tmp = ipf_flush(softc, IPL_LOGCOUNT, flags); if (tmp >= 0) flushed += tmp; } @@ -3317,6 +3813,59 @@ int proto, flags; /* ------------------------------------------------------------------------ */ +/* Function: ipf_flush_groups */ +/* Returns: int - >= 0 - number of flushed rules */ +/* Parameters: softc(I) - soft context pointerto work with */ +/* grhead(I) - pointer to the start of the group list to flush */ +/* flags(I) - which set of rules to flush */ +/* */ +/* Walk through all of the groups under the given group head and remove all */ +/* of those that match the flags passed in. The for loop here is bit more */ +/* complicated than usual because the removal of a rule with ipf_derefrule */ +/* may end up removing not only the structure pointed to by "fg" but also */ +/* what is fg_next and fg_next after that. So if a filter rule is actually */ +/* removed from the group then it is necessary to start again. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_flush_groups(softc, grhead, flags) + ipf_main_softc_t *softc; + frgroup_t **grhead; + int flags; +{ + frentry_t *fr, **frp; + frgroup_t *fg, **fgp; + int flushed = 0; + int removed = 0; + + for (fgp = grhead; (fg = *fgp) != NULL; ) { + while ((fg != NULL) && ((fg->fg_flags & flags) == 0)) + fg = fg->fg_next; + if (fg == NULL) + break; + removed = 0; + frp = &fg->fg_start; + while ((removed == 0) && ((fr = *frp) != NULL)) { + if ((fr->fr_flags & flags) == 0) { + frp = &fr->fr_next; + } else { + if (fr->fr_next != NULL) + fr->fr_next->fr_pnext = fr->fr_pnext; + *frp = fr->fr_next; + fr->fr_pnext = NULL; + fr->fr_next = NULL; + (void) ipf_derefrule(softc, &fr); + flushed++; + removed++; + } + } + if (removed == 0) + fgp = &fg->fg_next; + } + return flushed; +} + + +/* ------------------------------------------------------------------------ */ /* Function: memstr */ /* Returns: char * - NULL if failed, != NULL pointer to matching bytes */ /* Parameters: src(I) - pointer to byte sequence to match */ @@ -3327,9 +3876,11 @@ int proto, flags; /* Search dst for a sequence of bytes matching those at src and extend for */ /* slen bytes. */ /* ------------------------------------------------------------------------ */ -char *memstr(src, dst, slen, dlen) -char *src, *dst; -int slen, dlen; +char * +memstr(src, dst, slen, dlen) + const char *src; + char *dst; + size_t slen, dlen; { char *s = NULL; @@ -3344,7 +3895,7 @@ int slen, dlen; return s; } /* ------------------------------------------------------------------------ */ -/* Function: fr_fixskip */ +/* Function: ipf_fixskip */ /* Returns: Nil */ /* Parameters: listp(IO) - pointer to start of list with skip rule */ /* rp(I) - rule added/removed with skip in it. */ @@ -3355,9 +3906,10 @@ int slen, dlen; /* Adjust all the rules in a list which would have skip'd past the position */ /* where we are inserting to skip to the right place given the change. */ /* ------------------------------------------------------------------------ */ -void fr_fixskip(listp, rp, addremove) -frentry_t **listp, *rp; -int addremove; +void +ipf_fixskip(listp, rp, addremove) + frentry_t **listp, *rp; + int addremove; { int rules, rn; frentry_t *fp; @@ -3386,8 +3938,9 @@ int addremove; /* consecutive 1's is different to that passed, return -1, else return # */ /* of bits. */ /* ------------------------------------------------------------------------ */ -int count4bits(ip) -u_32_t ip; +int +count4bits(ip) + u_32_t ip; { u_32_t ipn; int cnt = 0, i, j; @@ -3410,7 +3963,6 @@ u_32_t ip; } -# if 0 /* ------------------------------------------------------------------------ */ /* Function: count6bits */ /* Returns: int - >= 0 - number of consecutive bits in input */ @@ -3419,8 +3971,10 @@ u_32_t ip; /* IPv6 ONLY */ /* count consecutive 1's in bit mask. */ /* ------------------------------------------------------------------------ */ -int count6bits(msk) -u_32_t *msk; +# ifdef USE_INET6 +int +count6bits(msk) + u_32_t *msk; { int i = 0, k; u_32_t j; @@ -3440,8 +3994,8 @@ u_32_t *msk; /* ------------------------------------------------------------------------ */ -/* Function: frsynclist */ -/* Returns: void */ +/* Function: ipf_synclist */ +/* Returns: int - 0 = no failures, else indication of first failure */ /* Parameters: fr(I) - start of filter list to sync interface names for */ /* ifp(I) - interface pointer for limiting sync lookups */ /* Write Locks: ipf_mutex */ @@ -3450,16 +4004,33 @@ u_32_t *msk; /* pointers. Where dynamic addresses are used, also update the IP address */ /* used in the rule. The interface pointer is used to limit the lookups to */ /* a specific set of matching names if it is non-NULL. */ -/* ------------------------------------------------------------------------ */ -static void frsynclist(fr, ifp) -frentry_t *fr; -void *ifp; +/* Errors can occur when resolving the destination name of to/dup-to fields */ +/* when the name points to a pool and that pool doest not exist. If this */ +/* does happen then it is necessary to check if there are any lookup refs */ +/* that need to be dropped before returning with an error. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_synclist(softc, fr, ifp) + ipf_main_softc_t *softc; + frentry_t *fr; + void *ifp; { + frentry_t *frt, *start = fr; frdest_t *fdp; + char *name; + int error; + void *ifa; int v, i; + error = 0; + for (; fr; fr = fr->fr_next) { - v = fr->fr_v; + if (fr->fr_family == AF_INET) + v = 4; + else if (fr->fr_family == AF_INET6) + v = 6; + else + v = 0; /* * Lookup all the interface names that are part of the rule. @@ -3467,100 +4038,124 @@ void *ifp; for (i = 0; i < 4; i++) { if ((ifp != NULL) && (fr->fr_ifas[i] != ifp)) continue; - fr->fr_ifas[i] = fr_resolvenic(fr->fr_ifnames[i], v); + if (fr->fr_ifnames[i] == -1) + continue; + name = FR_NAME(fr, fr_ifnames[i]); + fr->fr_ifas[i] = ipf_resolvenic(softc, name, v); } - if (fr->fr_type == FR_T_IPF) { + if ((fr->fr_type & ~FR_T_BUILTIN) == FR_T_IPF) { if (fr->fr_satype != FRI_NORMAL && fr->fr_satype != FRI_LOOKUP) { - (void)fr_ifpaddr(v, fr->fr_satype, - fr->fr_ifas[fr->fr_sifpidx], - &fr->fr_src, &fr->fr_smsk); + ifa = ipf_resolvenic(softc, fr->fr_names + + fr->fr_sifpidx, v); + ipf_ifpaddr(softc, v, fr->fr_satype, ifa, + &fr->fr_src6, &fr->fr_smsk6); } if (fr->fr_datype != FRI_NORMAL && fr->fr_datype != FRI_LOOKUP) { - (void)fr_ifpaddr(v, fr->fr_datype, - fr->fr_ifas[fr->fr_difpidx], - &fr->fr_dst, &fr->fr_dmsk); + ifa = ipf_resolvenic(softc, fr->fr_names + + fr->fr_sifpidx, v); + ipf_ifpaddr(softc, v, fr->fr_datype, ifa, + &fr->fr_dst6, &fr->fr_dmsk6); } } fdp = &fr->fr_tifs[0]; - if ((ifp == NULL) || (fdp->fd_ifp == ifp)) - fr_resolvedest(fdp, v); + if ((ifp == NULL) || (fdp->fd_ptr == ifp)) { + error = ipf_resolvedest(softc, fr->fr_names, fdp, v); + if (error != 0) + goto unwind; + } fdp = &fr->fr_tifs[1]; - if ((ifp == NULL) || (fdp->fd_ifp == ifp)) - fr_resolvedest(fdp, v); + if ((ifp == NULL) || (fdp->fd_ptr == ifp)) { + error = ipf_resolvedest(softc, fr->fr_names, fdp, v); + if (error != 0) + goto unwind; + } fdp = &fr->fr_dif; - if ((ifp == NULL) || (fdp->fd_ifp == ifp)) { - fr_resolvedest(fdp, v); - - fr->fr_flags &= ~FR_DUP; - if ((fdp->fd_ifp != (void *)-1) && - (fdp->fd_ifp != NULL)) - fr->fr_flags |= FR_DUP; + if ((ifp == NULL) || (fdp->fd_ptr == ifp)) { + error = ipf_resolvedest(softc, fr->fr_names, fdp, v); + if (error != 0) + goto unwind; } -#ifdef IPFILTER_LOOKUP - if (fr->fr_type == FR_T_IPF && fr->fr_satype == FRI_LOOKUP && - fr->fr_srcptr == NULL) { - fr->fr_srcptr = fr_resolvelookup(fr->fr_srctype, - fr->fr_srcnum, - &fr->fr_srcfunc); + if (((fr->fr_type & ~FR_T_BUILTIN) == FR_T_IPF) && + (fr->fr_satype == FRI_LOOKUP) && (fr->fr_srcptr == NULL)) { + fr->fr_srcptr = ipf_lookup_res_num(softc, + fr->fr_srctype, + IPL_LOGIPF, + fr->fr_srcnum, + &fr->fr_srcfunc); } - if (fr->fr_type == FR_T_IPF && fr->fr_datype == FRI_LOOKUP && - fr->fr_dstptr == NULL) { - fr->fr_dstptr = fr_resolvelookup(fr->fr_dsttype, - fr->fr_dstnum, - &fr->fr_dstfunc); + if (((fr->fr_type & ~FR_T_BUILTIN) == FR_T_IPF) && + (fr->fr_datype == FRI_LOOKUP) && (fr->fr_dstptr == NULL)) { + fr->fr_dstptr = ipf_lookup_res_num(softc, + fr->fr_dsttype, + IPL_LOGIPF, + fr->fr_dstnum, + &fr->fr_dstfunc); } -#endif } + return 0; + +unwind: + for (frt = start; frt != fr; fr = fr->fr_next) { + if (((frt->fr_type & ~FR_T_BUILTIN) == FR_T_IPF) && + (frt->fr_satype == FRI_LOOKUP) && (frt->fr_srcptr != NULL)) + ipf_lookup_deref(softc, frt->fr_srctype, + frt->fr_srcptr); + if (((frt->fr_type & ~FR_T_BUILTIN) == FR_T_IPF) && + (frt->fr_datype == FRI_LOOKUP) && (frt->fr_dstptr != NULL)) + ipf_lookup_deref(softc, frt->fr_dsttype, + frt->fr_dstptr); + } + return error; } -#ifdef _KERNEL /* ------------------------------------------------------------------------ */ -/* Function: frsync */ +/* Function: ipf_sync */ /* Returns: void */ /* Parameters: Nil */ /* */ -/* frsync() is called when we suspect that the interface list or */ +/* ipf_sync() is called when we suspect that the interface list or */ /* information about interfaces (like IP#) has changed. Go through all */ /* filter rules, NAT entries and the state table and check if anything */ /* needs to be changed/updated. */ /* ------------------------------------------------------------------------ */ -void frsync(ifp) -void *ifp; +int +ipf_sync(softc, ifp) + ipf_main_softc_t *softc; + void *ifp; { int i; # if !SOLARIS - fr_natsync(ifp); - fr_statesync(ifp); + ipf_nat_sync(softc, ifp); + ipf_state_sync(softc, ifp); + ipf_lookup_sync(softc, ifp); # endif - WRITE_ENTER(&ipf_mutex); - frsynclist(ipacct[0][fr_active], ifp); - frsynclist(ipacct[1][fr_active], ifp); - frsynclist(ipfilter[0][fr_active], ifp); - frsynclist(ipfilter[1][fr_active], ifp); - frsynclist(ipacct6[0][fr_active], ifp); - frsynclist(ipacct6[1][fr_active], ifp); - frsynclist(ipfilter6[0][fr_active], ifp); - frsynclist(ipfilter6[1][fr_active], ifp); + WRITE_ENTER(&softc->ipf_mutex); + (void) ipf_synclist(softc, softc->ipf_acct[0][softc->ipf_active], ifp); + (void) ipf_synclist(softc, softc->ipf_acct[1][softc->ipf_active], ifp); + (void) ipf_synclist(softc, softc->ipf_rules[0][softc->ipf_active], ifp); + (void) ipf_synclist(softc, softc->ipf_rules[1][softc->ipf_active], ifp); for (i = 0; i < IPL_LOGSIZE; i++) { frgroup_t *g; - for (g = ipfgroups[i][0]; g != NULL; g = g->fg_next) - frsynclist(g->fg_start, ifp); - for (g = ipfgroups[i][1]; g != NULL; g = g->fg_next) - frsynclist(g->fg_start, ifp); + for (g = softc->ipf_groups[i][0]; g != NULL; g = g->fg_next) + (void) ipf_synclist(softc, g->fg_start, ifp); + for (g = softc->ipf_groups[i][1]; g != NULL; g = g->fg_next) + (void) ipf_synclist(softc, g->fg_start, ifp); } - RWLOCK_EXIT(&ipf_mutex); + RWLOCK_EXIT(&softc->ipf_mutex); + + return 0; } @@ -3580,22 +4175,28 @@ void *ifp; /* to start copying from (src) and a pointer to where to store it (dst). */ /* NB: src - pointer to user space pointer, dst - kernel space pointer */ /* ------------------------------------------------------------------------ */ -int copyinptr(src, dst, size) -void *src, *dst; -size_t size; +int +copyinptr(softc, src, dst, size) + ipf_main_softc_t *softc; + void *src, *dst; + size_t size; { caddr_t ca; - int err; + int error; # if SOLARIS - err = COPYIN(src, (caddr_t)&ca, sizeof(ca)); - if (err != 0) - return err; + error = COPYIN(src, &ca, sizeof(ca)); + if (error != 0) + return error; # else bcopy(src, (caddr_t)&ca, sizeof(ca)); # endif - err = COPYIN(ca, dst, size); - return err; + error = COPYIN(ca, dst, size); + if (error != 0) { + IPFERROR(3); + error = EFAULT; + } + return error; } @@ -3610,93 +4211,127 @@ size_t size; /* to start copying from (src) and a pointer to where to store it (dst). */ /* NB: src - kernel space pointer, dst - pointer to user space pointer. */ /* ------------------------------------------------------------------------ */ -int copyoutptr(src, dst, size) -void *src, *dst; -size_t size; +int +copyoutptr(softc, src, dst, size) + ipf_main_softc_t *softc; + void *src, *dst; + size_t size; { caddr_t ca; - int err; + int error; -# if SOLARIS - err = COPYIN(dst, (caddr_t)&ca, sizeof(ca)); - if (err != 0) - return err; -# else bcopy(dst, (caddr_t)&ca, sizeof(ca)); -# endif - err = COPYOUT(src, ca, size); - return err; + error = COPYOUT(src, ca, size); + if (error != 0) { + IPFERROR(4); + error = EFAULT; + } + return error; } +#ifdef _KERNEL #endif /* ------------------------------------------------------------------------ */ -/* Function: fr_lock */ -/* Returns: (void) */ +/* Function: ipf_lock */ +/* Returns: int - 0 = success, else error */ /* Parameters: data(I) - pointer to lock value to set */ /* lockp(O) - pointer to location to store old lock value */ /* */ /* Get the new value for the lock integer, set it and return the old value */ /* in *lockp. */ /* ------------------------------------------------------------------------ */ -void fr_lock(data, lockp) -caddr_t data; -int *lockp; +int +ipf_lock(data, lockp) + caddr_t data; + int *lockp; { - int arg; + int arg, err; - BCOPYIN(data, (caddr_t)&arg, sizeof(arg)); - BCOPYOUT((caddr_t)lockp, data, sizeof(*lockp)); + err = BCOPYIN(data, &arg, sizeof(arg)); + if (err != 0) + return EFAULT; + err = BCOPYOUT(lockp, data, sizeof(*lockp)); + if (err != 0) + return EFAULT; *lockp = arg; + return 0; } /* ------------------------------------------------------------------------ */ -/* Function: fr_getstat */ +/* Function: ipf_getstat */ /* Returns: Nil */ -/* Parameters: fiop(I) - pointer to ipfilter stats structure */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* fiop(I) - pointer to ipfilter stats structure */ +/* rev(I) - version claim by program doing ioctl */ /* */ /* Stores a copy of current pointers, counters, etc, in the friostat */ /* structure. */ -/* ------------------------------------------------------------------------ */ -void fr_getstat(fiop) -friostat_t *fiop; +/* If IPFILTER_COMPAT is compiled, we pretend to be whatever version the */ +/* program is looking for. This ensure that validation of the version it */ +/* expects will always succeed. Thus kernels with IPFILTER_COMPAT will */ +/* allow older binaries to work but kernels without it will not. */ +/* ------------------------------------------------------------------------ */ +/*ARGSUSED*/ +static void +ipf_getstat(softc, fiop, rev) + ipf_main_softc_t *softc; + friostat_t *fiop; + int rev; { - int i, j; - - bcopy((char *)frstats, (char *)fiop->f_st, sizeof(filterstats_t) * 2); - fiop->f_locks[IPL_LOGSTATE] = fr_state_lock; - fiop->f_locks[IPL_LOGNAT] = fr_nat_lock; - fiop->f_locks[IPL_LOGIPF] = fr_frag_lock; - fiop->f_locks[IPL_LOGAUTH] = fr_auth_lock; - - for (i = 0; i < 2; i++) - for (j = 0; j < 2; j++) { - fiop->f_ipf[i][j] = ipfilter[i][j]; - fiop->f_acct[i][j] = ipacct[i][j]; - fiop->f_ipf6[i][j] = ipfilter6[i][j]; - fiop->f_acct6[i][j] = ipacct6[i][j]; - } - - fiop->f_ticks = fr_ticks; - fiop->f_active = fr_active; - fiop->f_froute[0] = fr_frouteok[0]; - fiop->f_froute[1] = fr_frouteok[1]; + int i; - fiop->f_running = fr_running; + bcopy((char *)softc->ipf_stats, (char *)fiop->f_st, + sizeof(ipf_statistics_t) * 2); + fiop->f_locks[IPL_LOGSTATE] = -1; + fiop->f_locks[IPL_LOGNAT] = -1; + fiop->f_locks[IPL_LOGIPF] = -1; + fiop->f_locks[IPL_LOGAUTH] = -1; + + fiop->f_ipf[0][0] = softc->ipf_rules[0][0]; + fiop->f_acct[0][0] = softc->ipf_acct[0][0]; + fiop->f_ipf[0][1] = softc->ipf_rules[0][1]; + fiop->f_acct[0][1] = softc->ipf_acct[0][1]; + fiop->f_ipf[1][0] = softc->ipf_rules[1][0]; + fiop->f_acct[1][0] = softc->ipf_acct[1][0]; + fiop->f_ipf[1][1] = softc->ipf_rules[1][1]; + fiop->f_acct[1][1] = softc->ipf_acct[1][1]; + + fiop->f_ticks = softc->ipf_ticks; + fiop->f_active = softc->ipf_active; + fiop->f_froute[0] = softc->ipf_frouteok[0]; + fiop->f_froute[1] = softc->ipf_frouteok[1]; + fiop->f_rb_no_mem = softc->ipf_rb_no_mem; + fiop->f_rb_node_max = softc->ipf_rb_node_max; + + fiop->f_running = softc->ipf_running; for (i = 0; i < IPL_LOGSIZE; i++) { - fiop->f_groups[i][0] = ipfgroups[i][0]; - fiop->f_groups[i][1] = ipfgroups[i][1]; + fiop->f_groups[i][0] = softc->ipf_groups[i][0]; + fiop->f_groups[i][1] = softc->ipf_groups[i][1]; } #ifdef IPFILTER_LOG + fiop->f_log_ok = ipf_log_logok(softc, IPL_LOGIPF); + fiop->f_log_fail = ipf_log_failures(softc, IPL_LOGIPF); fiop->f_logging = 1; #else + fiop->f_log_ok = 0; + fiop->f_log_fail = 0; fiop->f_logging = 0; #endif - fiop->f_defpass = fr_pass; - fiop->f_features = fr_features; + fiop->f_defpass = softc->ipf_pass; + fiop->f_features = ipf_features; + +#ifdef IPFILTER_COMPAT + sprintf(fiop->f_version, "IP Filter: v%d.%d.%d", + (rev / 1000000) % 100, + (rev / 10000) % 100, + (rev / 100) % 100); +#else + rev = rev; (void) strncpy(fiop->f_version, ipfilter_version, sizeof(fiop->f_version)); +#endif } @@ -3747,7 +4382,7 @@ int icmpreplytype4[ICMP_MAXTYPE + 1]; /* ------------------------------------------------------------------------ */ -/* Function: fr_matchicmpqueryreply */ +/* Function: ipf_matchicmpqueryreply */ /* Returns: int - 1 if "icmp" is a valid reply to "ic" else 0. */ /* Parameters: v(I) - IP protocol version (4 or 6) */ /* ic(I) - ICMP information */ @@ -3758,11 +4393,12 @@ int icmpreplytype4[ICMP_MAXTYPE + 1]; /* reply to one as described by what's in ic. If it is a match, return 1, */ /* else return 0 for no match. */ /* ------------------------------------------------------------------------ */ -int fr_matchicmpqueryreply(v, ic, icmp, rev) -int v; -icmpinfo_t *ic; -icmphdr_t *icmp; -int rev; +int +ipf_matchicmpqueryreply(v, ic, icmp, rev) + int v; + icmpinfo_t *ic; + icmphdr_t *icmp; + int rev; { int ictype; @@ -3796,72 +4432,6 @@ int rev; } -#ifdef IPFILTER_LOOKUP -/* ------------------------------------------------------------------------ */ -/* Function: fr_resolvelookup */ -/* Returns: void * - NULL = failure, else success. */ -/* Parameters: type(I) - type of lookup these parameters are for. */ -/* number(I) - table number to use when searching */ -/* funcptr(IO) - pointer to pointer for storing IP address */ -/* searching function. */ -/* */ -/* Search for the "table" number passed in amongst those configured for */ -/* that particular type. If the type is recognised then the function to */ -/* call to do the IP address search will be change, regardless of whether */ -/* or not the "table" number exists. */ -/* ------------------------------------------------------------------------ */ -static void *fr_resolvelookup(type, number, funcptr) -u_int type, number; -lookupfunc_t *funcptr; -{ - char name[FR_GROUPLEN]; - iphtable_t *iph; - ip_pool_t *ipo; - void *ptr; - -#if defined(SNPRINTF) && defined(_KERNEL) - SNPRINTF(name, sizeof(name), "%u", number); -#else - (void) sprintf(name, "%u", number); -#endif - - READ_ENTER(&ip_poolrw); - - switch (type) - { - case IPLT_POOL : -# if (defined(__osf__) && defined(_KERNEL)) - ptr = NULL; - *funcptr = NULL; -# else - ipo = ip_pool_find(IPL_LOGIPF, name); - ptr = ipo; - if (ipo != NULL) { - ATOMIC_INC32(ipo->ipo_ref); - } - *funcptr = ip_pool_search; -# endif - break; - case IPLT_HASH : - iph = fr_findhtable(IPL_LOGIPF, name); - ptr = iph; - if (iph != NULL) { - ATOMIC_INC32(iph->iph_ref); - } - *funcptr = fr_iphmfindip; - break; - default: - ptr = NULL; - *funcptr = NULL; - break; - } - RWLOCK_EXIT(&ip_poolrw); - - return ptr; -} -#endif - - /* ------------------------------------------------------------------------ */ /* Function: frrequest */ /* Returns: int - 0 == success, > 0 == errno value */ @@ -3879,54 +4449,98 @@ lookupfunc_t *funcptr; /* of the rule structure being loaded. If a rule has user defined timeouts */ /* then make sure they are created and initialised before exiting. */ /* ------------------------------------------------------------------------ */ -int frrequest(unit, req, data, set, makecopy) -int unit; -ioctlcmd_t req; -int set, makecopy; -caddr_t data; +int +frrequest(softc, unit, req, data, set, makecopy) + ipf_main_softc_t *softc; + int unit; + ioctlcmd_t req; + int set, makecopy; + caddr_t data; { + int error = 0, in, family, addrem, need_free = 0; frentry_t frd, *fp, *f, **fprev, **ftail; - int error = 0, in, v; - void *ptr, *uptr; + void *ptr, *uptr, *cptr; u_int *p, *pp; frgroup_t *fg; char *group; + ptr = NULL; + cptr = NULL; fg = NULL; fp = &frd; if (makecopy != 0) { - error = fr_inobj(data, fp, IPFOBJ_FRENTRY); - if (error) - return EFAULT; - if ((fp->fr_flags & FR_T_BUILTIN) != 0) + bzero(fp, sizeof(frd)); + error = ipf_inobj(softc, data, NULL, fp, IPFOBJ_FRENTRY); + if (error) { + return error; + } + if ((fp->fr_type & FR_T_BUILTIN) != 0) { + IPFERROR(6); return EINVAL; + } + KMALLOCS(f, frentry_t *, fp->fr_size); + if (f == NULL) { + IPFERROR(131); + return ENOMEM; + } + bzero(f, fp->fr_size); + error = ipf_inobjsz(softc, data, f, IPFOBJ_FRENTRY, + fp->fr_size); + if (error) { + KFREES(f, fp->fr_size); + return error; + } + + fp = f; + f = NULL; + fp->fr_dnext = NULL; fp->fr_ref = 0; fp->fr_flags |= FR_COPIED; } else { fp = (frentry_t *)data; - if ((fp->fr_type & FR_T_BUILTIN) == 0) + if ((fp->fr_type & FR_T_BUILTIN) == 0) { + IPFERROR(7); return EINVAL; + } fp->fr_flags &= ~FR_COPIED; } if (((fp->fr_dsize == 0) && (fp->fr_data != NULL)) || - ((fp->fr_dsize != 0) && (fp->fr_data == NULL))) - return EINVAL; + ((fp->fr_dsize != 0) && (fp->fr_data == NULL))) { + IPFERROR(8); + error = EINVAL; + goto donenolock; + } - v = fp->fr_v; + family = fp->fr_family; uptr = fp->fr_data; + if (req == (ioctlcmd_t)SIOCINAFR || req == (ioctlcmd_t)SIOCINIFR || + req == (ioctlcmd_t)SIOCADAFR || req == (ioctlcmd_t)SIOCADIFR) + addrem = 0; + else if (req == (ioctlcmd_t)SIOCRMAFR || req == (ioctlcmd_t)SIOCRMIFR) + addrem = 1; + else if (req == (ioctlcmd_t)SIOCZRLST) + addrem = 2; + else { + IPFERROR(9); + error = EINVAL; + goto donenolock; + } + /* * Only filter rules for IPv4 or IPv6 are accepted. */ - if (v == 4) + if (family == AF_INET) { /*EMPTY*/; #ifdef USE_INET6 - else if (v == 6) + } else if (family == AF_INET6) { /*EMPTY*/; #endif - else { - return EINVAL; + } else if (family != 0) { + IPFERROR(10); + error = EINVAL; + goto donenolock; } /* @@ -3935,37 +4549,110 @@ caddr_t data; * rule. */ if ((makecopy == 1) && (fp->fr_func != NULL)) { - if (fr_findfunc(fp->fr_func) == NULL) - return ESRCH; - error = fr_funcinit(fp); - if (error != 0) - return error; + if (ipf_findfunc(fp->fr_func) == NULL) { + IPFERROR(11); + error = ESRCH; + goto donenolock; + } + + if (addrem == 0) { + error = ipf_funcinit(softc, fp); + if (error != 0) + goto donenolock; + } + } + if ((fp->fr_flags & FR_CALLNOW) && + ((fp->fr_func == NULL) || (fp->fr_func == (ipfunc_t)-1))) { + IPFERROR(142); + error = ESRCH; + goto donenolock; + } + if (((fp->fr_flags & FR_CMDMASK) == FR_CALL) && + ((fp->fr_func == NULL) || (fp->fr_func == (ipfunc_t)-1))) { + IPFERROR(143); + error = ESRCH; + goto donenolock; } ptr = NULL; - /* - * Check that the group number does exist and that its use (in/out) - * matches what the rule is. - */ - if (!strncmp(fp->fr_grhead, "0", FR_GROUPLEN)) - *fp->fr_grhead = '\0'; - group = fp->fr_group; - if (!strncmp(group, "0", FR_GROUPLEN)) - *group = '\0'; + cptr = NULL; if (FR_ISACCOUNT(fp->fr_flags)) unit = IPL_LOGCOUNT; - if ((req != (int)SIOCZRLST) && (*group != '\0')) { - fg = fr_findgroup(group, unit, set, NULL); - if (fg == NULL) - return ESRCH; - if (fg->fg_flags == 0) - fg->fg_flags = fp->fr_flags & FR_INOUT; - else if (fg->fg_flags != (fp->fr_flags & FR_INOUT)) - return ESRCH; + /* + * Check that each group name in the rule has a start index that + * is valid. + */ + if (fp->fr_icmphead != -1) { + if ((fp->fr_icmphead < 0) || + (fp->fr_icmphead >= fp->fr_namelen)) { + IPFERROR(136); + error = EINVAL; + goto donenolock; + } + if (!strcmp(FR_NAME(fp, fr_icmphead), "0")) + fp->fr_names[fp->fr_icmphead] = '\0'; + } + + if (fp->fr_grhead != -1) { + if ((fp->fr_grhead < 0) || + (fp->fr_grhead >= fp->fr_namelen)) { + IPFERROR(137); + error = EINVAL; + goto donenolock; + } + if (!strcmp(FR_NAME(fp, fr_grhead), "0")) + fp->fr_names[fp->fr_grhead] = '\0'; } + if (fp->fr_group != -1) { + if ((fp->fr_group < 0) || + (fp->fr_group >= fp->fr_namelen)) { + IPFERROR(138); + error = EINVAL; + goto donenolock; + } + if ((req != (int)SIOCZRLST) && (fp->fr_group != -1)) { + /* + * Allow loading rules that are in groups to cause + * them to be created if they don't already exit. + */ + group = FR_NAME(fp, fr_group); + if (addrem == 0) { + fg = ipf_group_add(softc, group, NULL, + fp->fr_flags, unit, set); + fp->fr_grp = fg; + } else { + fg = ipf_findgroup(softc, group, unit, + set, NULL); + if (fg == NULL) { + IPFERROR(12); + error = ESRCH; + goto donenolock; + } + } + + if (fg->fg_flags == 0) { + fg->fg_flags = fp->fr_flags & FR_INOUT; + } else if (fg->fg_flags != (fp->fr_flags & FR_INOUT)) { + IPFERROR(13); + error = ESRCH; + goto donenolock; + } + } + } else { + /* + * If a rule is going to be part of a group then it does + * not matter whether it is an in or out rule, but if it + * isn't in a group, then it does... + */ + if ((fp->fr_flags & (FR_INQUE|FR_OUTQUE)) == 0) { + IPFERROR(14); + error = EINVAL; + goto donenolock; + } + } in = (fp->fr_flags & FR_INQUE) ? 0 : 1; /* @@ -3973,32 +4660,30 @@ caddr_t data; */ ftail = NULL; fprev = NULL; - if (unit == IPL_LOGAUTH) - fprev = &ipauth; - else if (v == 4) { - if (FR_ISACCOUNT(fp->fr_flags)) - fprev = &ipacct[in][set]; - else if ((fp->fr_flags & (FR_OUTQUE|FR_INQUE)) != 0) - fprev = &ipfilter[in][set]; - } else if (v == 6) { + if (unit == IPL_LOGAUTH) { + if ((fp->fr_tifs[0].fd_ptr != NULL) || + (fp->fr_tifs[1].fd_ptr != NULL) || + (fp->fr_dif.fd_ptr != NULL) || + (fp->fr_flags & FR_FASTROUTE)) { + softc->ipf_interror = 145; + error = EINVAL; + goto donenolock; + } + fprev = ipf_auth_rulehead(softc); + } else { if (FR_ISACCOUNT(fp->fr_flags)) - fprev = &ipacct6[in][set]; + fprev = &softc->ipf_acct[in][set]; else if ((fp->fr_flags & (FR_OUTQUE|FR_INQUE)) != 0) - fprev = &ipfilter6[in][set]; + fprev = &softc->ipf_rules[in][set]; } - if (fprev == NULL) - return ESRCH; - - if (*group != '\0') { - if (!fg && !(fg = fr_findgroup(group, unit, set, NULL))) - return ESRCH; - fprev = &fg->fg_start; + if (fprev == NULL) { + IPFERROR(15); + error = ESRCH; + goto donenolock; } - for (f = *fprev; (f = *fprev) != NULL; fprev = &f->fr_next) - if (fp->fr_collect <= f->fr_collect) - break; - ftail = fprev; + if (fg != NULL) + fprev = &fg->fg_start; /* * Copy in extra data for the rule. @@ -4006,49 +4691,82 @@ caddr_t data; if (fp->fr_dsize != 0) { if (makecopy != 0) { KMALLOCS(ptr, void *, fp->fr_dsize); - if (!ptr) - return ENOMEM; - error = COPYIN(uptr, ptr, fp->fr_dsize); + if (ptr == NULL) { + IPFERROR(16); + error = ENOMEM; + goto donenolock; + } + + /* + * The bcopy case is for when the data is appended + * to the rule by ipf_in_compat(). + */ + if (uptr >= (void *)fp && + uptr < (void *)((char *)fp + fp->fr_size)) { + bcopy(uptr, ptr, fp->fr_dsize); + error = 0; + } else { + error = COPYIN(uptr, ptr, fp->fr_dsize); + if (error != 0) { + IPFERROR(17); + error = EFAULT; + goto donenolock; + } + } } else { ptr = uptr; - error = 0; - } - if (error != 0) { - KFREES(ptr, fp->fr_dsize); - return ENOMEM; } fp->fr_data = ptr; - } else + } else { fp->fr_data = NULL; + } /* * Perform per-rule type sanity checks of their members. + * All code after this needs to be aware that allocated memory + * may need to be free'd before exiting. */ switch (fp->fr_type & ~FR_T_BUILTIN) { #if defined(IPFILTER_BPF) case FR_T_BPFOPC : - if (fp->fr_dsize == 0) - return EINVAL; + if (fp->fr_dsize == 0) { + IPFERROR(19); + error = EINVAL; + break; + } if (!bpf_validate(ptr, fp->fr_dsize/sizeof(struct bpf_insn))) { - if (makecopy && fp->fr_data != NULL) { - KFREES(fp->fr_data, fp->fr_dsize); - } - return EINVAL; + IPFERROR(20); + error = EINVAL; + break; } break; #endif case FR_T_IPF : - if (fp->fr_dsize != sizeof(fripf_t)) - return EINVAL; + /* + * Preparation for error case at the bottom of this function. + */ + if (fp->fr_datype == FRI_LOOKUP) + fp->fr_dstptr = NULL; + if (fp->fr_satype == FRI_LOOKUP) + fp->fr_srcptr = NULL; + + if (fp->fr_dsize != sizeof(fripf_t)) { + IPFERROR(21); + error = EINVAL; + break; + } /* * Allowing a rule with both "keep state" and "with oow" is * pointless because adding a state entry to the table will * fail with the out of window (oow) flag set. */ - if ((fp->fr_flags & FR_KEEPSTATE) && (fp->fr_flx & FI_OOW)) - return EINVAL; + if ((fp->fr_flags & FR_KEEPSTATE) && (fp->fr_flx & FI_OOW)) { + IPFERROR(22); + error = EINVAL; + break; + } switch (fp->fr_satype) { @@ -4057,23 +4775,30 @@ caddr_t data; case FRI_NETWORK : case FRI_NETMASKED : case FRI_PEERADDR : - if (fp->fr_sifpidx < 0 || fp->fr_sifpidx > 3) { - if (makecopy && fp->fr_data != NULL) { - KFREES(fp->fr_data, fp->fr_dsize); - } - return EINVAL; + if (fp->fr_sifpidx < 0) { + IPFERROR(23); + error = EINVAL; } break; -#ifdef IPFILTER_LOOKUP case FRI_LOOKUP : - fp->fr_srcptr = fr_resolvelookup(fp->fr_srctype, - fp->fr_srcnum, - &fp->fr_srcfunc); + fp->fr_srcptr = ipf_findlookup(softc, unit, fp, + &fp->fr_src6, + &fp->fr_smsk6); + if (fp->fr_srcfunc == NULL) { + IPFERROR(132); + error = ESRCH; + break; + } + break; + case FRI_NORMAL : break; -#endif default : + IPFERROR(133); + error = EINVAL; break; } + if (error != 0) + break; switch (fp->fr_datype) { @@ -4082,43 +4807,84 @@ caddr_t data; case FRI_NETWORK : case FRI_NETMASKED : case FRI_PEERADDR : - if (fp->fr_difpidx < 0 || fp->fr_difpidx > 3) { - if (makecopy && fp->fr_data != NULL) { - KFREES(fp->fr_data, fp->fr_dsize); - } - return EINVAL; + if (fp->fr_difpidx < 0) { + IPFERROR(24); + error = EINVAL; } break; -#ifdef IPFILTER_LOOKUP case FRI_LOOKUP : - fp->fr_dstptr = fr_resolvelookup(fp->fr_dsttype, - fp->fr_dstnum, - &fp->fr_dstfunc); + fp->fr_dstptr = ipf_findlookup(softc, unit, fp, + &fp->fr_dst6, + &fp->fr_dmsk6); + if (fp->fr_dstfunc == NULL) { + IPFERROR(134); + error = ESRCH; + } break; -#endif - default : - + case FRI_NORMAL : break; + default : + IPFERROR(135); + error = EINVAL; } break; + case FR_T_NONE : - break; case FR_T_CALLFUNC : - break; case FR_T_COMPIPF : break; + + case FR_T_IPFEXPR : + if (ipf_matcharray_verify(fp->fr_data, fp->fr_dsize) == -1) { + IPFERROR(25); + error = EINVAL; + } + break; + default : - if (makecopy && fp->fr_data != NULL) { - KFREES(fp->fr_data, fp->fr_dsize); + IPFERROR(26); + error = EINVAL; + break; + } + if (error != 0) + goto donenolock; + + if (fp->fr_tif.fd_name != -1) { + if ((fp->fr_tif.fd_name < 0) || + (fp->fr_tif.fd_name >= fp->fr_namelen)) { + IPFERROR(139); + error = EINVAL; + goto donenolock; + } + } + + if (fp->fr_dif.fd_name != -1) { + if ((fp->fr_dif.fd_name < 0) || + (fp->fr_dif.fd_name >= fp->fr_namelen)) { + IPFERROR(140); + error = EINVAL; + goto donenolock; + } + } + + if (fp->fr_rif.fd_name != -1) { + if ((fp->fr_rif.fd_name < 0) || + (fp->fr_rif.fd_name >= fp->fr_namelen)) { + IPFERROR(141); + error = EINVAL; + goto donenolock; } - return EINVAL; } /* * Lookup all the interface names that are part of the rule. */ - frsynclist(fp, NULL); + error = ipf_synclist(softc, fp, NULL); + if (error != 0) + goto donenolock; fp->fr_statecnt = 0; + if (fp->fr_srctrack.ht_max_nodes != 0) + ipf_rb_ht_init(&fp->fr_srctrack); /* * Look for an existing matching filter rule, but don't include the @@ -4134,25 +4900,45 @@ caddr_t data; for (p = (u_int *)fp->fr_data; p < pp; p++) fp->fr_cksum += *p; - WRITE_ENTER(&ipf_mutex); - bzero((char *)frcache, sizeof(frcache)); + WRITE_ENTER(&softc->ipf_mutex); + + /* + * Now that the filter rule lists are locked, we can walk the + * chain of them without fear. + */ + ftail = fprev; + for (f = *ftail; (f = *ftail) != NULL; ftail = &f->fr_next) { + if (fp->fr_collect <= f->fr_collect) { + ftail = fprev; + f = NULL; + break; + } + fprev = ftail; + } - for (; (f = *ftail) != NULL; ftail = &f->fr_next) - if ((fp->fr_cksum == f->fr_cksum) && - (f->fr_dsize == fp->fr_dsize) && - !bcmp((char *)&f->fr_func, - (char *)&fp->fr_func, FR_CMPSIZ) && - (!ptr || !f->fr_data || + for (; (f = *ftail) != NULL; ftail = &f->fr_next) { + DT2(rule_cmp, frentry_t *, fp, frentry_t *, f); + if ((fp->fr_cksum != f->fr_cksum) || + (fp->fr_size != f->fr_size) || + (f->fr_dsize != fp->fr_dsize)) + continue; + if (bcmp((char *)&f->fr_func, (char *)&fp->fr_func, + fp->fr_size - offsetof(struct frentry, fr_func)) != 0) + continue; + if ((!ptr && !f->fr_data) || + (ptr && f->fr_data && !bcmp((char *)ptr, (char *)f->fr_data, f->fr_dsize))) break; + } /* * If zero'ing statistics, copy current to caller and zero. */ - if (req == (ioctlcmd_t)SIOCZRLST) { - if (f == NULL) + if (addrem == 2) { + if (f == NULL) { + IPFERROR(27); error = ESRCH; - else { + } else { /* * Copy and reduce lock because of impending copyout. * Well we should, but if we do then the atomicity of @@ -4161,20 +4947,24 @@ caddr_t data; * only resets them to 0 if they are successfully * copied out into user space. */ - bcopy((char *)f, (char *)fp, sizeof(*f)); - /* MUTEX_DOWNGRADE(&ipf_mutex); */ + bcopy((char *)f, (char *)fp, f->fr_size); + /* MUTEX_DOWNGRADE(&softc->ipf_mutex); */ /* * When we copy this rule back out, set the data * pointer to be what it was in user space. */ fp->fr_data = uptr; - error = fr_outobj(data, fp, IPFOBJ_FRENTRY); + error = ipf_outobj(softc, data, fp, IPFOBJ_FRENTRY); if (error == 0) { if ((f->fr_dsize != 0) && (uptr != NULL)) error = COPYOUT(f->fr_data, uptr, f->fr_dsize); + if (error != 0) { + IPFERROR(28); + error = EFAULT; + } if (error == 0) { f->fr_hits = 0; f->fr_bytes = 0; @@ -4182,147 +4972,338 @@ caddr_t data; } } - if ((ptr != NULL) && (makecopy != 0)) { - KFREES(ptr, fp->fr_dsize); + if (makecopy != 0) { + if (ptr != NULL) { + KFREES(ptr, fp->fr_dsize); + } + KFREES(fp, fp->fr_size); } - RWLOCK_EXIT(&ipf_mutex); + RWLOCK_EXIT(&softc->ipf_mutex); return error; } - if (!f) { - if (req == (ioctlcmd_t)SIOCINAFR || - req == (ioctlcmd_t)SIOCINIFR) { - ftail = fprev; - if (fp->fr_hits != 0) { - while (--fp->fr_hits && (f = *ftail)) - ftail = &f->fr_next; + if (!f) { + /* + * At the end of this, ftail must point to the place where the + * new rule is to be saved/inserted/added. + * For SIOCAD*FR, this should be the last rule in the group of + * rules that have equal fr_collect fields. + * For SIOCIN*FR, ... + */ + if (req == (ioctlcmd_t)SIOCADAFR || + req == (ioctlcmd_t)SIOCADIFR) { + + for (ftail = fprev; (f = *ftail) != NULL; ) { + if (f->fr_collect > fp->fr_collect) + break; + ftail = &f->fr_next; } f = NULL; ptr = NULL; - error = 0; + } else if (req == (ioctlcmd_t)SIOCINAFR || + req == (ioctlcmd_t)SIOCINIFR) { + while ((f = *fprev) != NULL) { + if (f->fr_collect >= fp->fr_collect) + break; + fprev = &f->fr_next; + } + ftail = fprev; + if (fp->fr_hits != 0) { + while (fp->fr_hits && (f = *ftail)) { + if (f->fr_collect != fp->fr_collect) + break; + fprev = ftail; + ftail = &f->fr_next; + fp->fr_hits--; + } + } + f = NULL; + ptr = NULL; } } /* * Request to remove a rule. */ - if (req == (ioctlcmd_t)SIOCRMAFR || req == (ioctlcmd_t)SIOCRMIFR) { - if (!f) + if (addrem == 1) { + if (!f) { + IPFERROR(29); error = ESRCH; - else { + } else { /* * Do not allow activity from user space to interfere * with rules not loaded that way. */ if ((makecopy == 1) && !(f->fr_flags & FR_COPIED)) { + IPFERROR(30); error = EPERM; goto done; } /* * Return EBUSY if the rule is being reference by - * something else (eg state information. + * something else (eg state information.) */ if (f->fr_ref > 1) { + IPFERROR(31); error = EBUSY; goto done; } #ifdef IPFILTER_SCAN - if (f->fr_isctag[0] != '\0' && + if (f->fr_isctag != -1 && (f->fr_isc != (struct ipscan *)-1)) - ipsc_detachfr(f); + ipf_scan_detachfr(f); #endif - if ((fg != NULL) && (fg->fg_head != NULL)) - fg->fg_head->fr_ref--; + if (unit == IPL_LOGAUTH) { - error = fr_preauthcmd(req, f, ftail); + error = ipf_auth_precmd(softc, req, f, ftail); goto done; } - if (*f->fr_grhead != '\0') - fr_delgroup(f->fr_grhead, unit, set); - fr_fixskip(fprev, f, -1); - *ftail = f->fr_next; - f->fr_next = NULL; - (void)fr_derefrule(&f); + + ipf_rule_delete(softc, f, unit, set); + + need_free = makecopy; } } else { /* * Not removing, so we must be adding/inserting a rule. */ - if (f) + if (f != NULL) { + IPFERROR(32); error = EEXIST; - else { - if (unit == IPL_LOGAUTH) { - error = fr_preauthcmd(req, fp, ftail); - goto done; - } - if (makecopy) { - KMALLOC(f, frentry_t *); - } else - f = fp; - if (f != NULL) { - if (fg != NULL && fg->fg_head!= NULL ) - fg->fg_head->fr_ref++; - if (fp != f) - bcopy((char *)fp, (char *)f, - sizeof(*f)); - MUTEX_NUKE(&f->fr_lock); - MUTEX_INIT(&f->fr_lock, "filter rule lock"); -#ifdef IPFILTER_SCAN - if (f->fr_isctag[0] != '\0' && - ipsc_attachfr(f)) - f->fr_isc = (struct ipscan *)-1; -#endif - f->fr_hits = 0; - if (makecopy != 0) - f->fr_ref = 1; - f->fr_next = *ftail; - *ftail = f; - if (req == (ioctlcmd_t)SIOCINIFR || - req == (ioctlcmd_t)SIOCINAFR) - fr_fixskip(fprev, f, 1); - f->fr_grp = NULL; - group = f->fr_grhead; - if (*group != '\0') { - fg = fr_addgroup(group, f, f->fr_flags, - unit, set); - if (fg != NULL) - f->fr_grp = &fg->fg_start; - } - } else - error = ENOMEM; + goto done; + } + if (unit == IPL_LOGAUTH) { + error = ipf_auth_precmd(softc, req, fp, ftail); + goto done; + } + + MUTEX_NUKE(&fp->fr_lock); + MUTEX_INIT(&fp->fr_lock, "filter rule lock"); + if (fp->fr_die != 0) + ipf_rule_expire_insert(softc, fp, set); + + fp->fr_hits = 0; + if (makecopy != 0) + fp->fr_ref = 1; + fp->fr_pnext = ftail; + fp->fr_next = *ftail; + *ftail = fp; + if (addrem == 0) + ipf_fixskip(ftail, fp, 1); + + fp->fr_icmpgrp = NULL; + if (fp->fr_icmphead != -1) { + group = FR_NAME(fp, fr_icmphead); + fg = ipf_group_add(softc, group, fp, 0, unit, set); + fp->fr_icmpgrp = fg; + } + + fp->fr_grphead = NULL; + if (fp->fr_grhead != -1) { + group = FR_NAME(fp, fr_grhead); + fg = ipf_group_add(softc, group, fp, fp->fr_flags, + unit, set); + fp->fr_grphead = fg; } } done: - RWLOCK_EXIT(&ipf_mutex); - if ((ptr != NULL) && (error != 0) && (makecopy != 0)) { - KFREES(ptr, fp->fr_dsize); + RWLOCK_EXIT(&softc->ipf_mutex); +donenolock: + if (need_free || (error != 0)) { + if ((fp->fr_type & ~FR_T_BUILTIN) == FR_T_IPF) { + if ((fp->fr_satype == FRI_LOOKUP) && + (fp->fr_srcptr != NULL)) + ipf_lookup_deref(softc, fp->fr_srctype, + fp->fr_srcptr); + if ((fp->fr_datype == FRI_LOOKUP) && + (fp->fr_dstptr != NULL)) + ipf_lookup_deref(softc, fp->fr_dsttype, + fp->fr_dstptr); + } + if (fp->fr_grp != NULL) { + WRITE_ENTER(&softc->ipf_mutex); + ipf_group_del(softc, fp->fr_grp, fp); + RWLOCK_EXIT(&softc->ipf_mutex); + } + if ((ptr != NULL) && (makecopy != 0)) { + KFREES(ptr, fp->fr_dsize); + } + KFREES(fp, fp->fr_size); } return (error); } /* ------------------------------------------------------------------------ */ -/* Function: fr_funcinit */ +/* Function: ipf_rule_delete */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* f(I) - pointer to the rule being deleted */ +/* ftail(I) - pointer to the pointer to f */ +/* unit(I) - device for which this is for */ +/* set(I) - 1 or 0 (filter set) */ +/* */ +/* This function attempts to do what it can to delete a filter rule: remove */ +/* it from any linked lists and remove any groups it is responsible for. */ +/* But in the end, removing a rule can only drop the reference count - we */ +/* must use that as the guide for whether or not it can be freed. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_rule_delete(softc, f, unit, set) + ipf_main_softc_t *softc; + frentry_t *f; + int unit, set; +{ + + /* + * If fr_pdnext is set, then the rule is on the expire list, so + * remove it from there. + */ + if (f->fr_pdnext != NULL) { + *f->fr_pdnext = f->fr_dnext; + if (f->fr_dnext != NULL) + f->fr_dnext->fr_pdnext = f->fr_pdnext; + f->fr_pdnext = NULL; + f->fr_dnext = NULL; + } + + ipf_fixskip(f->fr_pnext, f, -1); + if (f->fr_pnext != NULL) + *f->fr_pnext = f->fr_next; + if (f->fr_next != NULL) + f->fr_next->fr_pnext = f->fr_pnext; + f->fr_pnext = NULL; + f->fr_next = NULL; + + (void) ipf_derefrule(softc, &f); +} + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_rule_expire_insert */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* f(I) - pointer to rule to be added to expire list */ +/* set(I) - 1 or 0 (filter set) */ +/* */ +/* If the new rule has a given expiration time, insert it into the list of */ +/* expiring rules with the ones to be removed first added to the front of */ +/* the list. The insertion is O(n) but it is kept sorted for quick scans at */ +/* expiration interval checks. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_rule_expire_insert(softc, f, set) + ipf_main_softc_t *softc; + frentry_t *f; + int set; +{ + frentry_t *fr; + + /* + */ + + f->fr_die = softc->ipf_ticks + IPF_TTLVAL(f->fr_die); + for (fr = softc->ipf_rule_explist[set]; fr != NULL; + fr = fr->fr_dnext) { + if (f->fr_die < fr->fr_die) + break; + if (fr->fr_dnext == NULL) { + /* + * We've got to the last rule and everything + * wanted to be expired before this new node, + * so we have to tack it on the end... + */ + fr->fr_dnext = f; + f->fr_pdnext = &fr->fr_dnext; + fr = NULL; + break; + } + } + + if (softc->ipf_rule_explist[set] == NULL) { + softc->ipf_rule_explist[set] = f; + f->fr_pdnext = &softc->ipf_rule_explist[set]; + } else if (fr != NULL) { + f->fr_dnext = fr; + f->fr_pdnext = fr->fr_pdnext; + fr->fr_pdnext = &f->fr_dnext; + } +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_findlookup */ +/* Returns: NULL = failure, else success */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* unit(I) - ipf device we want to find match for */ +/* fp(I) - rule for which lookup is for */ +/* addrp(I) - pointer to lookup information in address struct */ +/* maskp(O) - pointer to lookup information for storage */ +/* */ +/* When using pools and hash tables to store addresses for matching in */ +/* rules, it is necessary to resolve both the object referred to by the */ +/* name or address (and return that pointer) and also provide the means by */ +/* which to determine if an address belongs to that object to make the */ +/* packet matching quicker. */ +/* ------------------------------------------------------------------------ */ +static void * +ipf_findlookup(softc, unit, fr, addrp, maskp) + ipf_main_softc_t *softc; + int unit; + frentry_t *fr; + i6addr_t *addrp, *maskp; +{ + void *ptr = NULL; + + switch (addrp->iplookupsubtype) + { + case 0 : + ptr = ipf_lookup_res_num(softc, unit, addrp->iplookuptype, + addrp->iplookupnum, + &maskp->iplookupfunc); + break; + case 1 : + if (addrp->iplookupname < 0) + break; + if (addrp->iplookupname >= fr->fr_namelen) + break; + ptr = ipf_lookup_res_name(softc, unit, addrp->iplookuptype, + fr->fr_names + addrp->iplookupname, + &maskp->iplookupfunc); + break; + default : + break; + } + + return ptr; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_funcinit */ /* Returns: int - 0 == success, else ESRCH: cannot resolve rule details */ -/* Parameters: fr(I) - pointer to filter rule */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* fr(I) - pointer to filter rule */ /* */ /* If a rule is a call rule, then check if the function it points to needs */ /* an init function to be called now the rule has been loaded. */ /* ------------------------------------------------------------------------ */ -static int fr_funcinit(fr) -frentry_t *fr; +static int +ipf_funcinit(softc, fr) + ipf_main_softc_t *softc; + frentry_t *fr; { ipfunc_resolve_t *ft; int err; + IPFERROR(34); err = ESRCH; - for (ft = fr_availfuncs; ft->ipfu_addr != NULL; ft++) + for (ft = ipf_availfuncs; ft->ipfu_addr != NULL; ft++) if (ft->ipfu_addr == fr->fr_func) { err = 0; if (ft->ipfu_init != NULL) - err = (*ft->ipfu_init)(fr); + err = (*ft->ipfu_init)(softc, fr); break; } return err; @@ -4330,18 +5311,45 @@ frentry_t *fr; /* ------------------------------------------------------------------------ */ -/* Function: fr_findfunc */ +/* Function: ipf_funcfini */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* fr(I) - pointer to filter rule */ +/* */ +/* For a given filter rule, call the matching "fini" function if the rule */ +/* is using a known function that would have resulted in the "init" being */ +/* called for ealier. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_funcfini(softc, fr) + ipf_main_softc_t *softc; + frentry_t *fr; +{ + ipfunc_resolve_t *ft; + + for (ft = ipf_availfuncs; ft->ipfu_addr != NULL; ft++) + if (ft->ipfu_addr == fr->fr_func) { + if (ft->ipfu_fini != NULL) + (void) (*ft->ipfu_fini)(softc, fr); + break; + } +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_findfunc */ /* Returns: ipfunc_t - pointer to function if found, else NULL */ /* Parameters: funcptr(I) - function pointer to lookup */ /* */ /* Look for a function in the table of known functions. */ /* ------------------------------------------------------------------------ */ -static ipfunc_t fr_findfunc(funcptr) -ipfunc_t funcptr; +static ipfunc_t +ipf_findfunc(funcptr) + ipfunc_t funcptr; { ipfunc_resolve_t *ft; - for (ft = fr_availfuncs; ft->ipfu_addr != NULL; ft++) + for (ft = ipf_availfuncs; ft->ipfu_addr != NULL; ft++) if (ft->ipfu_addr == funcptr) return funcptr; return NULL; @@ -4349,7 +5357,7 @@ ipfunc_t funcptr; /* ------------------------------------------------------------------------ */ -/* Function: fr_resolvefunc */ +/* Function: ipf_resolvefunc */ /* Returns: int - 0 == success, else error */ /* Parameters: data(IO) - ioctl data pointer to ipfunc_resolve_t struct */ /* */ @@ -4358,43 +5366,55 @@ ipfunc_t funcptr; /* function pointer if the name is set. When found, fill in the other one */ /* so that the entire, complete, structure can be copied back to user space.*/ /* ------------------------------------------------------------------------ */ -int fr_resolvefunc(data) -void *data; +int +ipf_resolvefunc(softc, data) + ipf_main_softc_t *softc; + void *data; { ipfunc_resolve_t res, *ft; + int error; - BCOPYIN(data, &res, sizeof(res)); + error = BCOPYIN(data, &res, sizeof(res)); + if (error != 0) { + IPFERROR(123); + return EFAULT; + } if (res.ipfu_addr == NULL && res.ipfu_name[0] != '\0') { - for (ft = fr_availfuncs; ft->ipfu_addr != NULL; ft++) + for (ft = ipf_availfuncs; ft->ipfu_addr != NULL; ft++) if (strncmp(res.ipfu_name, ft->ipfu_name, sizeof(res.ipfu_name)) == 0) { res.ipfu_addr = ft->ipfu_addr; res.ipfu_init = ft->ipfu_init; - if (COPYOUT(&res, data, sizeof(res)) != 0) + if (COPYOUT(&res, data, sizeof(res)) != 0) { + IPFERROR(35); return EFAULT; + } return 0; } } if (res.ipfu_addr != NULL && res.ipfu_name[0] == '\0') { - for (ft = fr_availfuncs; ft->ipfu_addr != NULL; ft++) + for (ft = ipf_availfuncs; ft->ipfu_addr != NULL; ft++) if (ft->ipfu_addr == res.ipfu_addr) { (void) strncpy(res.ipfu_name, ft->ipfu_name, sizeof(res.ipfu_name)); res.ipfu_init = ft->ipfu_init; - if (COPYOUT(&res, data, sizeof(res)) != 0) + if (COPYOUT(&res, data, sizeof(res)) != 0) { + IPFERROR(36); return EFAULT; + } return 0; } } + IPFERROR(37); return ESRCH; } -#if !defined(_KERNEL) || (!defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__FreeBSD__)) || \ - (defined(__FreeBSD__) && (__FreeBSD_version < 490000)) || \ - (defined(__NetBSD__) && (__NetBSD_Version__ < 105000000)) || \ - (defined(__OpenBSD__) && (OpenBSD < 200006)) +#if !defined(_KERNEL) || (!defined(__NetBSD__) && !defined(__OpenBSD__) && \ + !defined(__FreeBSD__)) || \ + FREEBSD_LT_REV(501000) || NETBSD_LT_REV(105000000) || \ + OPENBSD_LT_REV(200006) /* * From: NetBSD * ppsratecheck(): packets (or events) per second limitation. @@ -4444,19 +5464,23 @@ ppsratecheck(lasttime, curpps, maxpps) /* ------------------------------------------------------------------------ */ -/* Function: fr_derefrule */ +/* Function: ipf_derefrule */ /* Returns: int - 0 == rule freed up, else rule not freed */ /* Parameters: fr(I) - pointer to filter rule */ /* */ /* Decrement the reference counter to a rule by one. If it reaches zero, */ /* free it and any associated storage space being used by it. */ /* ------------------------------------------------------------------------ */ -int fr_derefrule(frp) -frentry_t **frp; +int +ipf_derefrule(softc, frp) + ipf_main_softc_t *softc; + frentry_t **frp; { frentry_t *fr; + frdest_t *fdp; fr = *frp; + *frp = NULL; MUTEX_ENTER(&fr->fr_lock); fr->fr_ref--; @@ -4464,40 +5488,63 @@ frentry_t **frp; MUTEX_EXIT(&fr->fr_lock); MUTEX_DESTROY(&fr->fr_lock); -#ifdef IPFILTER_LOOKUP - if (fr->fr_type == FR_T_IPF && fr->fr_satype == FRI_LOOKUP) - ip_lookup_deref(fr->fr_srctype, fr->fr_srcptr); - if (fr->fr_type == FR_T_IPF && fr->fr_datype == FRI_LOOKUP) - ip_lookup_deref(fr->fr_dsttype, fr->fr_dstptr); -#endif + ipf_funcfini(softc, fr); + + fdp = &fr->fr_tif; + if (fdp->fd_type == FRD_DSTLIST) + ipf_lookup_deref(softc, IPLT_DSTLIST, fdp->fd_ptr); + + fdp = &fr->fr_rif; + if (fdp->fd_type == FRD_DSTLIST) + ipf_lookup_deref(softc, IPLT_DSTLIST, fdp->fd_ptr); + + fdp = &fr->fr_dif; + if (fdp->fd_type == FRD_DSTLIST) + ipf_lookup_deref(softc, IPLT_DSTLIST, fdp->fd_ptr); + + if ((fr->fr_type & ~FR_T_BUILTIN) == FR_T_IPF && + fr->fr_satype == FRI_LOOKUP) + ipf_lookup_deref(softc, fr->fr_srctype, fr->fr_srcptr); + if ((fr->fr_type & ~FR_T_BUILTIN) == FR_T_IPF && + fr->fr_datype == FRI_LOOKUP) + ipf_lookup_deref(softc, fr->fr_dsttype, fr->fr_dstptr); + + if (fr->fr_grp != NULL) + ipf_group_del(softc, fr->fr_grp, fr); + + if (fr->fr_grphead != NULL) + ipf_group_del(softc, fr->fr_grphead, fr); + + if (fr->fr_icmpgrp != NULL) + ipf_group_del(softc, fr->fr_icmpgrp, fr); - if (fr->fr_dsize) { - KFREES(fr->fr_data, fr->fr_dsize); - } if ((fr->fr_flags & FR_COPIED) != 0) { - KFREE(fr); + if (fr->fr_dsize) { + KFREES(fr->fr_data, fr->fr_dsize); + } + KFREES(fr, fr->fr_size); return 0; } return 1; } else { MUTEX_EXIT(&fr->fr_lock); } - *frp = NULL; return -1; } -#ifdef IPFILTER_LOOKUP /* ------------------------------------------------------------------------ */ -/* Function: fr_grpmapinit */ +/* Function: ipf_grpmapinit */ /* Returns: int - 0 == success, else ESRCH because table entry not found*/ /* Parameters: fr(I) - pointer to rule to find hash table for */ /* */ /* Looks for group hash table fr_arg and stores a pointer to it in fr_ptr. */ -/* fr_ptr is later used by fr_srcgrpmap and fr_dstgrpmap. */ +/* fr_ptr is later used by ipf_srcgrpmap and ipf_dstgrpmap. */ /* ------------------------------------------------------------------------ */ -static int fr_grpmapinit(fr) -frentry_t *fr; +static int +ipf_grpmapinit(softc, fr) + ipf_main_softc_t *softc; + frentry_t *fr; { char name[FR_GROUPLEN]; iphtable_t *iph; @@ -4507,18 +5554,45 @@ frentry_t *fr; #else (void) sprintf(name, "%d", fr->fr_arg); #endif - iph = fr_findhtable(IPL_LOGIPF, name); - if (iph == NULL) + iph = ipf_lookup_find_htable(softc, IPL_LOGIPF, name); + if (iph == NULL) { + IPFERROR(38); return ESRCH; - if ((iph->iph_flags & FR_INOUT) != (fr->fr_flags & FR_INOUT)) + } + if ((iph->iph_flags & FR_INOUT) != (fr->fr_flags & FR_INOUT)) { + IPFERROR(39); return ESRCH; + } + iph->iph_ref++; fr->fr_ptr = iph; return 0; } /* ------------------------------------------------------------------------ */ -/* Function: fr_srcgrpmap */ +/* Function: ipf_grpmapfini */ +/* Returns: int - 0 == success, else ESRCH because table entry not found*/ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* fr(I) - pointer to rule to release hash table for */ +/* */ +/* For rules that have had ipf_grpmapinit called, ipf_lookup_deref needs to */ +/* be called to undo what ipf_grpmapinit caused to be done. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_grpmapfini(softc, fr) + ipf_main_softc_t *softc; + frentry_t *fr; +{ + iphtable_t *iph; + iph = fr->fr_ptr; + if (iph != NULL) + ipf_lookup_deref(softc, IPLT_HASH, iph); + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_srcgrpmap */ /* Returns: frentry_t * - pointer to "new last matching" rule or NULL */ /* Parameters: fin(I) - pointer to packet information */ /* passp(IO) - pointer to current/new filter decision (unused) */ @@ -4527,26 +5601,28 @@ frentry_t *fr; /* the key, and descend into that group and continue matching rules against */ /* the packet. */ /* ------------------------------------------------------------------------ */ -frentry_t *fr_srcgrpmap(fin, passp) -fr_info_t *fin; -u_32_t *passp; +frentry_t * +ipf_srcgrpmap(fin, passp) + fr_info_t *fin; + u_32_t *passp; { frgroup_t *fg; void *rval; - rval = fr_iphmfindgroup(fin->fin_fr->fr_ptr, &fin->fin_src); + rval = ipf_iphmfindgroup(fin->fin_main_soft, fin->fin_fr->fr_ptr, + &fin->fin_src); if (rval == NULL) return NULL; fg = rval; fin->fin_fr = fg->fg_start; - (void) fr_scanlist(fin, *passp); + (void) ipf_scanlist(fin, *passp); return fin->fin_fr; } /* ------------------------------------------------------------------------ */ -/* Function: fr_dstgrpmap */ +/* Function: ipf_dstgrpmap */ /* Returns: frentry_t * - pointer to "new last matching" rule or NULL */ /* Parameters: fin(I) - pointer to packet information */ /* passp(IO) - pointer to current/new filter decision (unused) */ @@ -4555,37 +5631,39 @@ u_32_t *passp; /* address as the key, and descend into that group and continue matching */ /* rules against the packet. */ /* ------------------------------------------------------------------------ */ -frentry_t *fr_dstgrpmap(fin, passp) -fr_info_t *fin; -u_32_t *passp; +frentry_t * +ipf_dstgrpmap(fin, passp) + fr_info_t *fin; + u_32_t *passp; { frgroup_t *fg; void *rval; - rval = fr_iphmfindgroup(fin->fin_fr->fr_ptr, &fin->fin_dst); + rval = ipf_iphmfindgroup(fin->fin_main_soft, fin->fin_fr->fr_ptr, + &fin->fin_dst); if (rval == NULL) return NULL; fg = rval; fin->fin_fr = fg->fg_start; - (void) fr_scanlist(fin, *passp); + (void) ipf_scanlist(fin, *passp); return fin->fin_fr; } -#endif /* IPFILTER_LOOKUP */ /* * Queue functions * =============== - * These functions manage objects on queues for efficient timeouts. There are - * a number of system defined queues as well as user defined timeouts. It is - * expected that a lock is held in the domain in which the queue belongs - * (i.e. either state or NAT) when calling any of these functions that prevents - * fr_freetimeoutqueue() from being called at the same time as any other. + * These functions manage objects on queues for efficient timeouts. There + * are a number of system defined queues as well as user defined timeouts. + * It is expected that a lock is held in the domain in which the queue + * belongs (i.e. either state or NAT) when calling any of these functions + * that prevents ipf_freetimeoutqueue() from being called at the same time + * as any other. */ /* ------------------------------------------------------------------------ */ -/* Function: fr_addtimeoutqueue */ +/* Function: ipf_addtimeoutqueue */ /* Returns: struct ifqtq * - NULL if malloc fails, else pointer to */ /* timeout queue with given interval. */ /* Parameters: parent(I) - pointer to pointer to parent node of this list */ @@ -4601,16 +5679,18 @@ u_32_t *passp; /* It is assumed that the caller of this function has an appropriate lock */ /* held (exclusively) in the domain that encompases 'parent'. */ /* ------------------------------------------------------------------------ */ -ipftq_t *fr_addtimeoutqueue(parent, seconds) -ipftq_t **parent; -u_int seconds; +ipftq_t * +ipf_addtimeoutqueue(softc, parent, seconds) + ipf_main_softc_t *softc; + ipftq_t **parent; + u_int seconds; { ipftq_t *ifq; u_int period; period = seconds * IPF_HZ_DIVIDE; - MUTEX_ENTER(&ipf_timeoutlock); + MUTEX_ENTER(&softc->ipf_timeoutlock); for (ifq = *parent; ifq != NULL; ifq = ifq->ifq_next) { if (ifq->ifq_ttl == period) { /* @@ -4621,7 +5701,7 @@ u_int seconds; ifq->ifq_flags &= ~IFQF_DELETE; ifq->ifq_ref++; MUTEX_EXIT(&ifq->ifq_lock); - MUTEX_EXIT(&ipf_timeoutlock); + MUTEX_EXIT(&softc->ipf_timeoutlock); return ifq; } @@ -4629,25 +5709,22 @@ u_int seconds; KMALLOC(ifq, ipftq_t *); if (ifq != NULL) { - ifq->ifq_ttl = period; - ifq->ifq_head = NULL; - ifq->ifq_tail = &ifq->ifq_head; + MUTEX_NUKE(&ifq->ifq_lock); + IPFTQ_INIT(ifq, period, "ipftq mutex"); ifq->ifq_next = *parent; ifq->ifq_pnext = parent; - ifq->ifq_ref = 1; ifq->ifq_flags = IFQF_USER; + ifq->ifq_ref++; *parent = ifq; - fr_userifqs++; - MUTEX_NUKE(&ifq->ifq_lock); - MUTEX_INIT(&ifq->ifq_lock, "ipftq mutex"); + softc->ipf_userifqs++; } - MUTEX_EXIT(&ipf_timeoutlock); + MUTEX_EXIT(&softc->ipf_timeoutlock); return ifq; } /* ------------------------------------------------------------------------ */ -/* Function: fr_deletetimeoutqueue */ +/* Function: ipf_deletetimeoutqueue */ /* Returns: int - new reference count value of the timeout queue */ /* Parameters: ifq(I) - timeout queue which is losing a reference. */ /* Locks: ifq->ifq_lock */ @@ -4661,8 +5738,9 @@ u_int seconds; /* way because the locking may not be sufficient to safely do a free when */ /* this function is called. */ /* ------------------------------------------------------------------------ */ -int fr_deletetimeoutqueue(ifq) -ipftq_t *ifq; +int +ipf_deletetimeoutqueue(ifq) + ipftq_t *ifq; { ifq->ifq_ref--; @@ -4675,7 +5753,7 @@ ipftq_t *ifq; /* ------------------------------------------------------------------------ */ -/* Function: fr_freetimeoutqueue */ +/* Function: ipf_freetimeoutqueue */ /* Parameters: ifq(I) - timeout queue which is losing a reference. */ /* Returns: Nil */ /* */ @@ -4684,17 +5762,18 @@ ipftq_t *ifq; /* held (exclusively) in the domain that encompases the callers "domain". */ /* The ifq_lock for this structure should not be held. */ /* */ -/* Remove a user definde timeout queue from the list of queues it is in and */ +/* Remove a user defined timeout queue from the list of queues it is in and */ /* tidy up after this is done. */ /* ------------------------------------------------------------------------ */ -void fr_freetimeoutqueue(ifq) -ipftq_t *ifq; +void +ipf_freetimeoutqueue(softc, ifq) + ipf_main_softc_t *softc; + ipftq_t *ifq; { - if (((ifq->ifq_flags & IFQF_DELETE) == 0) || (ifq->ifq_ref != 0) || ((ifq->ifq_flags & IFQF_USER) == 0)) { - printf("fr_freetimeoutqueue(%lx) flags 0x%x ttl %d ref %d\n", + printf("ipf_freetimeoutqueue(%lx) flags 0x%x ttl %d ref %d\n", (u_long)ifq, ifq->ifq_flags, ifq->ifq_ttl, ifq->ifq_ref); return; @@ -4706,32 +5785,32 @@ ipftq_t *ifq; *ifq->ifq_pnext = ifq->ifq_next; if (ifq->ifq_next != NULL) ifq->ifq_next->ifq_pnext = ifq->ifq_pnext; + ifq->ifq_next = NULL; + ifq->ifq_pnext = NULL; MUTEX_DESTROY(&ifq->ifq_lock); - fr_userifqs--; + ATOMIC_DEC(softc->ipf_userifqs); KFREE(ifq); } /* ------------------------------------------------------------------------ */ -/* Function: fr_deletequeueentry */ +/* Function: ipf_deletequeueentry */ /* Returns: Nil */ /* Parameters: tqe(I) - timeout queue entry to delete */ -/* ifq(I) - timeout queue to remove entry from */ /* */ /* Remove a tail queue entry from its queue and make it an orphan. */ -/* fr_deletetimeoutqueue is called to make sure the reference count on the */ -/* queue is correct. We can't, however, call fr_freetimeoutqueue because */ +/* ipf_deletetimeoutqueue is called to make sure the reference count on the */ +/* queue is correct. We can't, however, call ipf_freetimeoutqueue because */ /* the correct lock(s) may not be held that would make it safe to do so. */ /* ------------------------------------------------------------------------ */ -void fr_deletequeueentry(tqe) -ipftqent_t *tqe; +void +ipf_deletequeueentry(tqe) + ipftqent_t *tqe; { ipftq_t *ifq; ifq = tqe->tqe_ifq; - if (ifq == NULL) - return; MUTEX_ENTER(&ifq->ifq_lock); @@ -4746,21 +5825,23 @@ ipftqent_t *tqe; tqe->tqe_ifq = NULL; } - (void) fr_deletetimeoutqueue(ifq); + (void) ipf_deletetimeoutqueue(ifq); + ASSERT(ifq->ifq_ref > 0); MUTEX_EXIT(&ifq->ifq_lock); } /* ------------------------------------------------------------------------ */ -/* Function: fr_queuefront */ +/* Function: ipf_queuefront */ /* Returns: Nil */ /* Parameters: tqe(I) - pointer to timeout queue entry */ /* */ /* Move a queue entry to the front of the queue, if it isn't already there. */ /* ------------------------------------------------------------------------ */ -void fr_queuefront(tqe) -ipftqent_t *tqe; +void +ipf_queuefront(tqe) + ipftqent_t *tqe; { ipftq_t *ifq; @@ -4786,58 +5867,66 @@ ipftqent_t *tqe; /* ------------------------------------------------------------------------ */ -/* Function: fr_queueback */ +/* Function: ipf_queueback */ /* Returns: Nil */ -/* Parameters: tqe(I) - pointer to timeout queue entry */ +/* Parameters: ticks(I) - ipf tick time to use with this call */ +/* tqe(I) - pointer to timeout queue entry */ /* */ /* Move a queue entry to the back of the queue, if it isn't already there. */ +/* We use use ticks to calculate the expiration and mark for when we last */ +/* touched the structure. */ /* ------------------------------------------------------------------------ */ -void fr_queueback(tqe) -ipftqent_t *tqe; +void +ipf_queueback(ticks, tqe) + u_long ticks; + ipftqent_t *tqe; { ipftq_t *ifq; ifq = tqe->tqe_ifq; if (ifq == NULL) return; - tqe->tqe_die = fr_ticks + ifq->ifq_ttl; + tqe->tqe_die = ticks + ifq->ifq_ttl; + tqe->tqe_touched = ticks; MUTEX_ENTER(&ifq->ifq_lock); - if (tqe->tqe_next == NULL) { /* at the end already ? */ - MUTEX_EXIT(&ifq->ifq_lock); - return; - } - - /* - * Remove from list - */ - *tqe->tqe_pnext = tqe->tqe_next; - tqe->tqe_next->tqe_pnext = tqe->tqe_pnext; + if (tqe->tqe_next != NULL) { /* at the end already ? */ + /* + * Remove from list + */ + *tqe->tqe_pnext = tqe->tqe_next; + tqe->tqe_next->tqe_pnext = tqe->tqe_pnext; - /* - * Make it the last entry. - */ - tqe->tqe_next = NULL; - tqe->tqe_pnext = ifq->ifq_tail; - *ifq->ifq_tail = tqe; - ifq->ifq_tail = &tqe->tqe_next; + /* + * Make it the last entry. + */ + tqe->tqe_next = NULL; + tqe->tqe_pnext = ifq->ifq_tail; + *ifq->ifq_tail = tqe; + ifq->ifq_tail = &tqe->tqe_next; + } MUTEX_EXIT(&ifq->ifq_lock); } /* ------------------------------------------------------------------------ */ -/* Function: fr_queueappend */ +/* Function: ipf_queueappend */ /* Returns: Nil */ -/* Parameters: tqe(I) - pointer to timeout queue entry */ +/* Parameters: ticks(I) - ipf tick time to use with this call */ +/* tqe(I) - pointer to timeout queue entry */ /* ifq(I) - pointer to timeout queue */ /* parent(I) - owing object pointer */ /* */ /* Add a new item to this queue and put it on the very end. */ +/* We use use ticks to calculate the expiration and mark for when we last */ +/* touched the structure. */ /* ------------------------------------------------------------------------ */ -void fr_queueappend(tqe, ifq, parent) -ipftqent_t *tqe; -ipftq_t *ifq; -void *parent; +void +ipf_queueappend(ticks, tqe, ifq, parent) + u_long ticks; + ipftqent_t *tqe; + ipftq_t *ifq; + void *parent; { MUTEX_ENTER(&ifq->ifq_lock); @@ -4847,14 +5936,15 @@ void *parent; ifq->ifq_tail = &tqe->tqe_next; tqe->tqe_next = NULL; tqe->tqe_ifq = ifq; - tqe->tqe_die = fr_ticks + ifq->ifq_ttl; + tqe->tqe_die = ticks + ifq->ifq_ttl; + tqe->tqe_touched = ticks; ifq->ifq_ref++; MUTEX_EXIT(&ifq->ifq_lock); } /* ------------------------------------------------------------------------ */ -/* Function: fr_movequeue */ +/* Function: ipf_movequeue */ /* Returns: Nil */ /* Parameters: tq(I) - pointer to timeout queue information */ /* oifp(I) - old timeout queue entry was on */ @@ -4864,17 +5954,39 @@ void *parent; /* If it notices that the current entry is already last and does not need */ /* to move queue, the return. */ /* ------------------------------------------------------------------------ */ -void fr_movequeue(tqe, oifq, nifq) -ipftqent_t *tqe; -ipftq_t *oifq, *nifq; +void +ipf_movequeue(ticks, tqe, oifq, nifq) + u_long ticks; + ipftqent_t *tqe; + ipftq_t *oifq, *nifq; { + /* - * Is the operation here going to be a no-op ? + * If the queue hasn't changed and we last touched this entry at the + * same ipf time, then we're not going to achieve anything by either + * changing the ttl or moving it on the queue. */ - MUTEX_ENTER(&oifq->ifq_lock); - if (oifq == nifq && *oifq->ifq_tail == tqe) { - MUTEX_EXIT(&oifq->ifq_lock); + if (oifq == nifq && tqe->tqe_touched == ticks) return; + + /* + * For any of this to be outside the lock, there is a risk that two + * packets entering simultaneously, with one changing to a different + * queue and one not, could end up with things in a bizarre state. + */ + MUTEX_ENTER(&oifq->ifq_lock); + + tqe->tqe_touched = ticks; + tqe->tqe_die = ticks + nifq->ifq_ttl; + /* + * Is the operation here going to be a no-op ? + */ + if (oifq == nifq) { + if ((tqe->tqe_next == NULL) || + (tqe->tqe_next->tqe_die == tqe->tqe_die)) { + MUTEX_EXIT(&oifq->ifq_lock); + return; + } } /* @@ -4888,14 +6000,15 @@ ipftq_t *oifq, *nifq; tqe->tqe_next = NULL; /* - * If we're moving from one queue to another, release the lock on the - * old queue and get a lock on the new queue. For user defined queues, - * if we're moving off it, call delete in case it can now be freed. + * If we're moving from one queue to another, release the + * lock on the old queue and get a lock on the new queue. + * For user defined queues, if we're moving off it, call + * delete in case it can now be freed. */ if (oifq != nifq) { tqe->tqe_ifq = NULL; - (void) fr_deletetimeoutqueue(oifq); + (void) ipf_deletetimeoutqueue(oifq); MUTEX_EXIT(&oifq->ifq_lock); @@ -4908,7 +6021,6 @@ ipftq_t *oifq, *nifq; /* * Add to the bottom of the new queue */ - tqe->tqe_die = fr_ticks + nifq->ifq_ttl; tqe->tqe_pnext = nifq->ifq_tail; *nifq->ifq_tail = tqe; nifq->ifq_tail = &tqe->tqe_next; @@ -4917,7 +6029,7 @@ ipftq_t *oifq, *nifq; /* ------------------------------------------------------------------------ */ -/* Function: fr_updateipid */ +/* Function: ipf_updateipid */ /* Returns: int - 0 == success, -1 == error (packet should be droppped) */ /* Parameters: fin(I) - pointer to packet information */ /* */ @@ -4928,23 +6040,24 @@ ipftq_t *oifq, *nifq; /* the fragment cache for non-leading fragments. If a non-leading fragment */ /* has no match in the cache, return an error. */ /* ------------------------------------------------------------------------ */ -static INLINE int fr_updateipid(fin) -fr_info_t *fin; +static int +ipf_updateipid(fin) + fr_info_t *fin; { u_short id, ido, sums; u_32_t sumd, sum; ip_t *ip; if (fin->fin_off != 0) { - sum = fr_ipid_knownfrag(fin); + sum = ipf_frag_ipidknown(fin); if (sum == 0xffffffff) return -1; sum &= 0xffff; id = (u_short)sum; } else { - id = fr_nextipid(fin); + id = ipf_nextipid(fin); if (fin->fin_off == 0 && (fin->fin_flx & FI_FRAG) != 0) - (void) fr_ipid_newfrag(fin, (u_32_t)id); + (void) ipf_frag_ipidnew(fin, (u_32_t)id); } ip = fin->fin_ip; @@ -4965,7 +6078,7 @@ fr_info_t *fin; #ifdef NEED_FRGETIFNAME /* ------------------------------------------------------------------------ */ -/* Function: fr_getifname */ +/* Function: ipf_getifname */ /* Returns: char * - pointer to interface name */ /* Parameters: ifp(I) - pointer to network interface */ /* buffer(O) - pointer to where to store interface name */ @@ -4974,13 +6087,14 @@ fr_info_t *fin; /* expected to be at least LIFNAMSIZ in bytes big. If buffer is passed in */ /* as a NULL pointer then return a pointer to a static array. */ /* ------------------------------------------------------------------------ */ -char *fr_getifname(ifp, buffer) -struct ifnet *ifp; -char *buffer; +char * +ipf_getifname(ifp, buffer) + struct ifnet *ifp; + char *buffer; { static char namebuf[LIFNAMSIZ]; # if defined(MENTAT) || defined(__FreeBSD__) || defined(__osf__) || \ - defined(__sgi) || defined(linux) || \ + defined(__sgi) || defined(linux) || defined(_AIX51) || \ (defined(sun) && !defined(__SVR4) && !defined(__svr4__)) int unit, space; char temp[20]; @@ -4992,13 +6106,13 @@ char *buffer; (void) strncpy(buffer, ifp->if_name, LIFNAMSIZ); buffer[LIFNAMSIZ - 1] = '\0'; # if defined(MENTAT) || defined(__FreeBSD__) || defined(__osf__) || \ - defined(__sgi) || \ + defined(__sgi) || defined(_AIX51) || \ (defined(sun) && !defined(__SVR4) && !defined(__svr4__)) for (s = buffer; *s; s++) ; unit = ifp->if_unit; space = LIFNAMSIZ - (s - buffer); - if (space > 0) { + if ((space > 0) && (unit >= 0)) { # if defined(SNPRINTF) && defined(_KERNEL) SNPRINTF(temp, sizeof(temp), "%d", unit); # else @@ -5013,82 +6127,110 @@ char *buffer; /* ------------------------------------------------------------------------ */ -/* Function: fr_ioctlswitch */ +/* Function: ipf_ioctlswitch */ /* Returns: int - -1 continue processing, else ioctl return value */ /* Parameters: unit(I) - device unit opened */ /* data(I) - pointer to ioctl data */ /* cmd(I) - ioctl command */ /* mode(I) - mode value */ +/* uid(I) - uid making the ioctl call */ +/* ctx(I) - pointer to context data */ /* */ /* Based on the value of unit, call the appropriate ioctl handler or return */ /* EIO if ipfilter is not running. Also checks if write perms are req'd */ -/* for the device in order to execute the ioctl. */ +/* for the device in order to execute the ioctl. A special case is made */ +/* SIOCIPFINTERROR so that the same code isn't required in every handler. */ +/* The context data pointer is passed through as this is used as the key */ +/* for locating a matching token for continued access for walking lists, */ +/* etc. */ /* ------------------------------------------------------------------------ */ -int fr_ioctlswitch(unit, data, cmd, mode) -int unit, mode; -ioctlcmd_t cmd; -void *data; +int +ipf_ioctlswitch(softc, unit, data, cmd, mode, uid, ctx) + ipf_main_softc_t *softc; + int unit, mode, uid; + ioctlcmd_t cmd; + void *data, *ctx; { int error = 0; + switch (cmd) + { + case SIOCIPFINTERROR : + error = BCOPYOUT(&softc->ipf_interror, data, + sizeof(softc->ipf_interror)); + if (error != 0) { + IPFERROR(40); + error = EFAULT; + } + return error; + default : + break; + } + switch (unit) { case IPL_LOGIPF : - error = -1; + error = ipf_ipf_ioctl(softc, data, cmd, mode, uid, ctx); break; case IPL_LOGNAT : - if (fr_running > 0) - error = fr_nat_ioctl(data, cmd, mode); - else + if (softc->ipf_running > 0) { + error = ipf_nat_ioctl(softc, data, cmd, mode, + uid, ctx); + } else { + IPFERROR(42); error = EIO; + } break; case IPL_LOGSTATE : - if (fr_running > 0) - error = fr_state_ioctl(data, cmd, mode); - else + if (softc->ipf_running > 0) { + error = ipf_state_ioctl(softc, data, cmd, mode, + uid, ctx); + } else { + IPFERROR(43); error = EIO; + } break; case IPL_LOGAUTH : - if (fr_running > 0) { - if ((cmd == (ioctlcmd_t)SIOCADAFR) || - (cmd == (ioctlcmd_t)SIOCRMAFR)) { - if (!(mode & FWRITE)) { - error = EPERM; - } else { - error = frrequest(unit, cmd, data, - fr_active, 1); - } - } else { - error = fr_auth_ioctl(data, cmd, mode); - } - } else + if (softc->ipf_running > 0) { + error = ipf_auth_ioctl(softc, data, cmd, mode, + uid, ctx); + } else { + IPFERROR(44); error = EIO; + } break; case IPL_LOGSYNC : -#ifdef IPFILTER_SYNC - if (fr_running > 0) - error = fr_sync_ioctl(data, cmd, mode); - else -#endif + if (softc->ipf_running > 0) { + error = ipf_sync_ioctl(softc, data, cmd, mode, + uid, ctx); + } else { error = EIO; + IPFERROR(45); + } break; case IPL_LOGSCAN : #ifdef IPFILTER_SCAN - if (fr_running > 0) - error = fr_scan_ioctl(data, cmd, mode); + if (softc->ipf_running > 0) + error = ipf_scan_ioctl(softc, data, cmd, mode, + uid, ctx); else #endif + { error = EIO; + IPFERROR(46); + } break; case IPL_LOGLOOKUP : -#ifdef IPFILTER_LOOKUP - if (fr_running > 0) - error = ip_lookup_ioctl(data, cmd, mode); - else -#endif + if (softc->ipf_running > 0) { + error = ipf_lookup_ioctl(softc, data, cmd, mode, + uid, ctx); + } else { error = EIO; + IPFERROR(47); + } break; default : + IPFERROR(48); error = EIO; break; } @@ -5099,185 +6241,244 @@ void *data; /* * This array defines the expected size of objects coming into the kernel - * for the various recognised object types. + * for the various recognised object types. The first column is flags (see + * below), 2nd column is current size, 3rd column is the version number of + * when the current size became current. + * Flags: + * 1 = minimum size, not absolute size */ -#define NUM_OBJ_TYPES 14 - -static int fr_objbytes[NUM_OBJ_TYPES][2] = { - { 1, sizeof(struct frentry) }, /* frentry */ - { 0, sizeof(struct friostat) }, - { 0, sizeof(struct fr_info) }, - { 0, sizeof(struct fr_authstat) }, - { 0, sizeof(struct ipfrstat) }, - { 0, sizeof(struct ipnat) }, - { 0, sizeof(struct natstat) }, - { 0, sizeof(struct ipstate_save) }, - { 1, sizeof(struct nat_save) }, /* nat_save */ - { 0, sizeof(struct natlookup) }, - { 1, sizeof(struct ipstate) }, /* ipstate */ - { 0, sizeof(struct ips_stat) }, - { 0, sizeof(struct frauth) }, - { 0, sizeof(struct ipftune) } +static int ipf_objbytes[IPFOBJ_COUNT][3] = { + { 1, sizeof(struct frentry), 5010000 }, /* 0 */ + { 1, sizeof(struct friostat), 5010000 }, + { 0, sizeof(struct fr_info), 5010000 }, + { 0, sizeof(struct ipf_authstat), 4010100 }, + { 0, sizeof(struct ipfrstat), 5010000 }, + { 1, sizeof(struct ipnat), 5010000 }, /* 5 */ + { 0, sizeof(struct natstat), 5010000 }, + { 0, sizeof(struct ipstate_save), 5010000 }, + { 1, sizeof(struct nat_save), 5010000 }, + { 0, sizeof(struct natlookup), 5010000 }, + { 1, sizeof(struct ipstate), 5010000 }, /* 10 */ + { 0, sizeof(struct ips_stat), 5010000 }, + { 0, sizeof(struct frauth), 5010000 }, + { 0, sizeof(struct ipftune), 4010100 }, + { 0, sizeof(struct nat), 5010000 }, + { 0, sizeof(struct ipfruleiter), 4011400 }, /* 15 */ + { 0, sizeof(struct ipfgeniter), 4011400 }, + { 0, sizeof(struct ipftable), 4011400 }, + { 0, sizeof(struct ipflookupiter), 4011400 }, + { 0, sizeof(struct ipftq) * IPF_TCP_NSTATES }, + { 1, 0, 0 }, /* IPFEXPR */ + { 0, 0, 0 }, /* PROXYCTL */ + { 0, sizeof (struct fripf), 5010000 } }; /* ------------------------------------------------------------------------ */ -/* Function: fr_inobj */ +/* Function: ipf_inobj */ /* Returns: int - 0 = success, else failure */ -/* Parameters: data(I) - pointer to ioctl data */ -/* ptr(I) - pointer to store real data in */ -/* type(I) - type of structure being moved */ +/* Parameters: softc(I) - soft context pointerto work with */ +/* data(I) - pointer to ioctl data */ +/* objp(O) - where to store ipfobj structure */ +/* ptr(I) - pointer to data to copy out */ +/* type(I) - type of structure being moved */ /* */ /* Copy in the contents of what the ipfobj_t points to. In future, we */ /* add things to check for version numbers, sizes, etc, to make it backward */ /* compatible at the ABI for user land. */ +/* If objp is not NULL then we assume that the caller wants to see what is */ +/* in the ipfobj_t structure being copied in. As an example, this can tell */ +/* the caller what version of ipfilter the ioctl program was written to. */ /* ------------------------------------------------------------------------ */ -int fr_inobj(data, ptr, type) -void *data; -void *ptr; -int type; +int +ipf_inobj(softc, data, objp, ptr, type) + ipf_main_softc_t *softc; + void *data; + ipfobj_t *objp; + void *ptr; + int type; { ipfobj_t obj; - int error = 0; + int error; + int size; - if ((type < 0) || (type > NUM_OBJ_TYPES-1)) + if ((type < 0) || (type >= IPFOBJ_COUNT)) { + IPFERROR(49); return EINVAL; + } - BCOPYIN((caddr_t)data, (caddr_t)&obj, sizeof(obj)); + if (objp == NULL) + objp = &obj; + error = BCOPYIN(data, objp, sizeof(*objp)); + if (error != 0) { + IPFERROR(124); + return EFAULT; + } - if (obj.ipfo_type != type) + if (objp->ipfo_type != type) { + IPFERROR(50); return EINVAL; + } -#ifndef IPFILTER_COMPAT - if ((fr_objbytes[type][0] & 1) != 0) { - if (obj.ipfo_size < fr_objbytes[type][1]) + if (objp->ipfo_rev >= ipf_objbytes[type][2]) { + if ((ipf_objbytes[type][0] & 1) != 0) { + if (objp->ipfo_size < ipf_objbytes[type][1]) { + IPFERROR(51); + return EINVAL; + } + size = ipf_objbytes[type][1]; + } else if (objp->ipfo_size == ipf_objbytes[type][1]) { + size = objp->ipfo_size; + } else { + IPFERROR(52); return EINVAL; - } else if (obj.ipfo_size != fr_objbytes[type][1]) - return EINVAL; + } + error = COPYIN(objp->ipfo_ptr, ptr, size); + if (error != 0) { + IPFERROR(55); + error = EFAULT; + } + } else { +#ifdef IPFILTER_COMPAT + error = ipf_in_compat(softc, objp, ptr, 0); #else - if (obj.ipfo_rev != IPFILTER_VERSION) - /* XXX compatibility hook here */ - ; - if ((fr_objbytes[type][0] & 1) != 0) { - if (obj.ipfo_size < fr_objbytes[type][1]) - /* XXX compatibility hook here */ - return EINVAL; - } else if (obj.ipfo_size != fr_objbytes[type][1]) - /* XXX compatibility hook here */ - return EINVAL; + IPFERROR(54); + error = EINVAL; #endif - - if ((fr_objbytes[type][0] & 1) != 0) { - error = COPYIN((caddr_t)obj.ipfo_ptr, (caddr_t)ptr, - fr_objbytes[type][1]); - } else { - error = COPYIN((caddr_t)obj.ipfo_ptr, (caddr_t)ptr, - obj.ipfo_size); } return error; } /* ------------------------------------------------------------------------ */ -/* Function: fr_inobjsz */ +/* Function: ipf_inobjsz */ /* Returns: int - 0 = success, else failure */ -/* Parameters: data(I) - pointer to ioctl data */ -/* ptr(I) - pointer to store real data in */ -/* type(I) - type of structure being moved */ -/* sz(I) - size of data to copy */ +/* Parameters: softc(I) - soft context pointerto work with */ +/* data(I) - pointer to ioctl data */ +/* ptr(I) - pointer to store real data in */ +/* type(I) - type of structure being moved */ +/* sz(I) - size of data to copy */ /* */ -/* As per fr_inobj, except the size of the object to copy in is passed in */ +/* As per ipf_inobj, except the size of the object to copy in is passed in */ /* but it must not be smaller than the size defined for the type and the */ /* type must allow for varied sized objects. The extra requirement here is */ /* that sz must match the size of the object being passed in - this is not */ -/* not possible nor required in fr_inobj(). */ +/* not possible nor required in ipf_inobj(). */ /* ------------------------------------------------------------------------ */ -int fr_inobjsz(data, ptr, type, sz) -void *data; -void *ptr; -int type, sz; +int +ipf_inobjsz(softc, data, ptr, type, sz) + ipf_main_softc_t *softc; + void *data; + void *ptr; + int type, sz; { ipfobj_t obj; int error; - if ((type < 0) || (type > NUM_OBJ_TYPES-1)) - return EINVAL; - if (((fr_objbytes[type][0] & 1) == 0) || (sz < fr_objbytes[type][1])) + if ((type < 0) || (type >= IPFOBJ_COUNT)) { + IPFERROR(56); return EINVAL; + } - BCOPYIN((caddr_t)data, (caddr_t)&obj, sizeof(obj)); + error = BCOPYIN(data, &obj, sizeof(obj)); + if (error != 0) { + IPFERROR(125); + return EFAULT; + } - if (obj.ipfo_type != type) + if (obj.ipfo_type != type) { + IPFERROR(58); return EINVAL; + } -#ifndef IPFILTER_COMPAT - if (obj.ipfo_size != sz) - return EINVAL; + if (obj.ipfo_rev >= ipf_objbytes[type][2]) { + if (((ipf_objbytes[type][0] & 1) == 0) || + (sz < ipf_objbytes[type][1])) { + IPFERROR(57); + return EINVAL; + } + error = COPYIN(obj.ipfo_ptr, ptr, sz); + if (error != 0) { + IPFERROR(61); + error = EFAULT; + } + } else { +#ifdef IPFILTER_COMPAT + error = ipf_in_compat(softc, &obj, ptr, sz); #else - if (obj.ipfo_rev != IPFILTER_VERSION) - /* XXX compatibility hook here */ - ; - if (obj.ipfo_size != sz) - /* XXX compatibility hook here */ - return EINVAL; + IPFERROR(60); + error = EINVAL; #endif - - error = COPYIN((caddr_t)obj.ipfo_ptr, (caddr_t)ptr, sz); + } return error; } /* ------------------------------------------------------------------------ */ -/* Function: fr_outobjsz */ +/* Function: ipf_outobjsz */ /* Returns: int - 0 = success, else failure */ /* Parameters: data(I) - pointer to ioctl data */ /* ptr(I) - pointer to store real data in */ /* type(I) - type of structure being moved */ /* sz(I) - size of data to copy */ /* */ -/* As per fr_outobj, except the size of the object to copy out is passed in */ +/* As per ipf_outobj, except the size of the object to copy out is passed in*/ /* but it must not be smaller than the size defined for the type and the */ /* type must allow for varied sized objects. The extra requirement here is */ /* that sz must match the size of the object being passed in - this is not */ -/* not possible nor required in fr_outobj(). */ +/* not possible nor required in ipf_outobj(). */ /* ------------------------------------------------------------------------ */ -int fr_outobjsz(data, ptr, type, sz) -void *data; -void *ptr; -int type, sz; +int +ipf_outobjsz(softc, data, ptr, type, sz) + ipf_main_softc_t *softc; + void *data; + void *ptr; + int type, sz; { ipfobj_t obj; int error; - if ((type < 0) || (type > NUM_OBJ_TYPES-1) || - ((fr_objbytes[type][0] & 1) == 0) || - (sz < fr_objbytes[type][1])) + if ((type < 0) || (type >= IPFOBJ_COUNT)) { + IPFERROR(62); return EINVAL; + } - BCOPYIN((caddr_t)data, (caddr_t)&obj, sizeof(obj)); + error = BCOPYIN(data, &obj, sizeof(obj)); + if (error != 0) { + IPFERROR(127); + return EFAULT; + } - if (obj.ipfo_type != type) + if (obj.ipfo_type != type) { + IPFERROR(63); return EINVAL; + } -#ifndef IPFILTER_COMPAT - if (obj.ipfo_size != sz) - return EINVAL; + if (obj.ipfo_rev >= ipf_objbytes[type][2]) { + if (((ipf_objbytes[type][0] & 1) == 0) || + (sz < ipf_objbytes[type][1])) { + IPFERROR(146); + return EINVAL; + } + error = COPYOUT(ptr, obj.ipfo_ptr, sz); + if (error != 0) { + IPFERROR(66); + error = EFAULT; + } + } else { +#ifdef IPFILTER_COMPAT + error = ipf_out_compat(softc, &obj, ptr); #else - if (obj.ipfo_rev != IPFILTER_VERSION) - /* XXX compatibility hook here */ - ; - if (obj.ipfo_size != sz) - /* XXX compatibility hook here */ - return EINVAL; + IPFERROR(65); + error = EINVAL; #endif - - error = COPYOUT((caddr_t)ptr, (caddr_t)obj.ipfo_ptr, sz); + } return error; } /* ------------------------------------------------------------------------ */ -/* Function: fr_outobj */ +/* Function: ipf_outobj */ /* Returns: int - 0 = success, else failure */ /* Parameters: data(I) - pointer to ioctl data */ /* ptr(I) - pointer to store real data in */ @@ -5287,65 +6488,134 @@ int type, sz; /* future, we add things to check for version numbers, sizes, etc, to make */ /* it backward compatible at the ABI for user land. */ /* ------------------------------------------------------------------------ */ -int fr_outobj(data, ptr, type) -void *data; -void *ptr; -int type; +int +ipf_outobj(softc, data, ptr, type) + ipf_main_softc_t *softc; + void *data; + void *ptr; + int type; { ipfobj_t obj; int error; - if ((type < 0) || (type > NUM_OBJ_TYPES-1)) + if ((type < 0) || (type >= IPFOBJ_COUNT)) { + IPFERROR(67); return EINVAL; + } - BCOPYIN((caddr_t)data, (caddr_t)&obj, sizeof(obj)); + error = BCOPYIN(data, &obj, sizeof(obj)); + if (error != 0) { + IPFERROR(126); + return EFAULT; + } - if (obj.ipfo_type != type) + if (obj.ipfo_type != type) { + IPFERROR(68); return EINVAL; + } -#ifndef IPFILTER_COMPAT - if ((fr_objbytes[type][0] & 1) != 0) { - if (obj.ipfo_size < fr_objbytes[type][1]) + if (obj.ipfo_rev >= ipf_objbytes[type][2]) { + if ((ipf_objbytes[type][0] & 1) != 0) { + if (obj.ipfo_size < ipf_objbytes[type][1]) { + IPFERROR(69); + return EINVAL; + } + } else if (obj.ipfo_size != ipf_objbytes[type][1]) { + IPFERROR(70); return EINVAL; - } else if (obj.ipfo_size != fr_objbytes[type][1]) - return EINVAL; + } + + error = COPYOUT(ptr, obj.ipfo_ptr, obj.ipfo_size); + if (error != 0) { + IPFERROR(73); + error = EFAULT; + } + } else { +#ifdef IPFILTER_COMPAT + error = ipf_out_compat(softc, &obj, ptr); #else - if (obj.ipfo_rev != IPFILTER_VERSION) - /* XXX compatibility hook here */ - ; - if ((fr_objbytes[type][0] & 1) != 0) { - if (obj.ipfo_size < fr_objbytes[type][1]) - /* XXX compatibility hook here */ - return EINVAL; - } else if (obj.ipfo_size != fr_objbytes[type][1]) - /* XXX compatibility hook here */ - return EINVAL; + IPFERROR(72); + error = EINVAL; #endif + } + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_outobjk */ +/* Returns: int - 0 = success, else failure */ +/* Parameters: obj(I) - pointer to data description structure */ +/* ptr(I) - pointer to kernel data to copy out */ +/* */ +/* In the above functions, the ipfobj_t structure is copied into the kernel,*/ +/* telling ipfilter how to copy out data. In this instance, the ipfobj_t is */ +/* already populated with information and now we just need to use it. */ +/* There is no need for this function to have a "type" parameter as there */ +/* is no point in validating information that comes from the kernel with */ +/* itself. */ +/* ------------------------------------------------------------------------ */ +int +ipf_outobjk(softc, obj, ptr) + ipf_main_softc_t *softc; + ipfobj_t *obj; + void *ptr; +{ + int type = obj->ipfo_type; + int error; + + if ((type < 0) || (type >= IPFOBJ_COUNT)) { + IPFERROR(147); + return EINVAL; + } + + if (obj->ipfo_rev >= ipf_objbytes[type][2]) { + if ((ipf_objbytes[type][0] & 1) != 0) { + if (obj->ipfo_size < ipf_objbytes[type][1]) { + IPFERROR(148); + return EINVAL; + } + + } else if (obj->ipfo_size != ipf_objbytes[type][1]) { + IPFERROR(149); + return EINVAL; + } - error = COPYOUT((caddr_t)ptr, (caddr_t)obj.ipfo_ptr, obj.ipfo_size); + error = COPYOUT(ptr, obj->ipfo_ptr, obj->ipfo_size); + if (error != 0) { + IPFERROR(150); + error = EFAULT; + } + } else { +#ifdef IPFILTER_COMPAT + error = ipf_out_compat(softc, obj, ptr); +#else + IPFERROR(151); + error = EINVAL; +#endif + } return error; } /* ------------------------------------------------------------------------ */ -/* Function: fr_checkl4sum */ +/* Function: ipf_checkl4sum */ /* Returns: int - 0 = good, -1 = bad, 1 = cannot check */ /* Parameters: fin(I) - pointer to packet information */ /* */ /* If possible, calculate the layer 4 checksum for the packet. If this is */ /* not possible, return without indicating a failure or success but in a */ -/* way that is ditinguishable. */ +/* way that is ditinguishable. This function should only be called by the */ +/* ipf_checkv6sum() for each platform. */ /* ------------------------------------------------------------------------ */ -int fr_checkl4sum(fin) -fr_info_t *fin; +INLINE int +ipf_checkl4sum(fin) + fr_info_t *fin; { u_short sum, hdrsum, *csump; udphdr_t *udp; int dosum; - if ((fin->fin_flx & FI_NOCKSUM) != 0) - return 0; - /* * If the TCP packet isn't a fragment, isn't too short and otherwise * isn't already considered "bad", then validate the checksum. If @@ -5359,46 +6629,44 @@ fr_info_t *fin; dosum = 0; sum = 0; -#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) && defined(ICK_VALID) - if (dohwcksum && ((*fin->fin_mp)->b_ick_flag == ICK_VALID)) { - hdrsum = 0; - sum = 0; - } else { -#endif - switch (fin->fin_p) - { - case IPPROTO_TCP : - csump = &((tcphdr_t *)fin->fin_dp)->th_sum; + switch (fin->fin_p) + { + case IPPROTO_TCP : + csump = &((tcphdr_t *)fin->fin_dp)->th_sum; + dosum = 1; + break; + + case IPPROTO_UDP : + udp = fin->fin_dp; + if (udp->uh_sum != 0) { + csump = &udp->uh_sum; dosum = 1; - break; + } + break; - case IPPROTO_UDP : - udp = fin->fin_dp; - if (udp->uh_sum != 0) { - csump = &udp->uh_sum; - dosum = 1; - } - break; +#ifdef USE_INET6 + case IPPROTO_ICMPV6 : + csump = &((struct icmp6_hdr *)fin->fin_dp)->icmp6_cksum; + dosum = 1; + break; +#endif - case IPPROTO_ICMP : - csump = &((struct icmp *)fin->fin_dp)->icmp_cksum; - dosum = 1; - break; + case IPPROTO_ICMP : + csump = &((struct icmp *)fin->fin_dp)->icmp_cksum; + dosum = 1; + break; - default : - return 1; - /*NOTREACHED*/ - } + default : + return 1; + /*NOTREACHED*/ + } - if (csump != NULL) - hdrsum = *csump; + if (csump != NULL) + hdrsum = *csump; - if (dosum) - sum = fr_cksum(fin->fin_m, fin->fin_ip, - fin->fin_p, fin->fin_dp); -#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) && defined(ICK_VALID) + if (dosum) { + sum = fr_cksum(fin, fin->fin_ip, fin->fin_p, fin->fin_dp); } -#endif #if !defined(_KERNEL) if (sum == hdrsum) { FR_DEBUG(("checkl4sum: %hx == %hx\n", sum, hdrsum)); @@ -5406,14 +6674,18 @@ fr_info_t *fin; FR_DEBUG(("checkl4sum: %hx != %hx\n", sum, hdrsum)); } #endif - if (hdrsum == sum) + DT2(l4sums, u_short, hdrsum, u_short, sum); + if (hdrsum == sum) { + fin->fin_cksum = FI_CK_SUMOK; return 0; + } + fin->fin_cksum = FI_CK_BAD; return -1; } /* ------------------------------------------------------------------------ */ -/* Function: fr_ifpfillv4addr */ +/* Function: ipf_ifpfillv4addr */ /* Returns: int - 0 = address update, -1 = address not updated */ /* Parameters: atype(I) - type of network address update to perform */ /* sin(I) - pointer to source of address information */ @@ -5428,10 +6700,11 @@ fr_info_t *fin; /* FRI_NETMASKED, if inpmask is non-NULL then the mask is set to an all 1s */ /* value. */ /* ------------------------------------------------------------------------ */ -int fr_ifpfillv4addr(atype, sin, mask, inp, inpmask) -int atype; -struct sockaddr_in *sin, *mask; -struct in_addr *inp, *inpmask; +int +ipf_ifpfillv4addr(atype, sin, mask, inp, inpmask) + int atype; + struct sockaddr_in *sin, *mask; + struct in_addr *inp, *inpmask; { if (inpmask != NULL && atype != FRI_NETMASKED) inpmask->s_addr = 0xffffffff; @@ -5452,7 +6725,7 @@ struct in_addr *inp, *inpmask; #ifdef USE_INET6 /* ------------------------------------------------------------------------ */ -/* Function: fr_ifpfillv6addr */ +/* Function: ipf_ifpfillv6addr */ /* Returns: int - 0 = address update, -1 = address not updated */ /* Parameters: atype(I) - type of network address update to perform */ /* sin(I) - pointer to source of address information */ @@ -5467,44 +6740,43 @@ struct in_addr *inp, *inpmask; /* FRI_NETMASKED, if inpmask is non-NULL then the mask is set to an all 1s */ /* value. */ /* ------------------------------------------------------------------------ */ -int fr_ifpfillv6addr(atype, sin, mask, inp, inpmask) -int atype; -struct sockaddr_in6 *sin, *mask; -struct in_addr *inp, *inpmask; +int +ipf_ifpfillv6addr(atype, sin, mask, inp, inpmask) + int atype; + struct sockaddr_in6 *sin, *mask; + i6addr_t *inp, *inpmask; { - i6addr_t *src, *dst, *and, *dmask; + i6addr_t *src, *and; src = (i6addr_t *)&sin->sin6_addr; and = (i6addr_t *)&mask->sin6_addr; - dst = (i6addr_t *)inp; - dmask = (i6addr_t *)inpmask; if (inpmask != NULL && atype != FRI_NETMASKED) { - dmask->i6[0] = 0xffffffff; - dmask->i6[1] = 0xffffffff; - dmask->i6[2] = 0xffffffff; - dmask->i6[3] = 0xffffffff; + inpmask->i6[0] = 0xffffffff; + inpmask->i6[1] = 0xffffffff; + inpmask->i6[2] = 0xffffffff; + inpmask->i6[3] = 0xffffffff; } if (atype == FRI_NETWORK || atype == FRI_NETMASKED) { if (atype == FRI_NETMASKED) { if (inpmask == NULL) return -1; - dmask->i6[0] = and->i6[0]; - dmask->i6[1] = and->i6[1]; - dmask->i6[2] = and->i6[2]; - dmask->i6[3] = and->i6[3]; + inpmask->i6[0] = and->i6[0]; + inpmask->i6[1] = and->i6[1]; + inpmask->i6[2] = and->i6[2]; + inpmask->i6[3] = and->i6[3]; } - dst->i6[0] = src->i6[0] & and->i6[0]; - dst->i6[1] = src->i6[1] & and->i6[1]; - dst->i6[2] = src->i6[2] & and->i6[2]; - dst->i6[3] = src->i6[3] & and->i6[3]; + inp->i6[0] = src->i6[0] & and->i6[0]; + inp->i6[1] = src->i6[1] & and->i6[1]; + inp->i6[2] = src->i6[2] & and->i6[2]; + inp->i6[3] = src->i6[3] & and->i6[3]; } else { - dst->i6[0] = src->i6[0]; - dst->i6[1] = src->i6[1]; - dst->i6[2] = src->i6[2]; - dst->i6[3] = src->i6[3]; + inp->i6[0] = src->i6[0]; + inp->i6[1] = src->i6[1]; + inp->i6[2] = src->i6[2]; + inp->i6[3] = src->i6[3]; } return 0; } @@ -5512,7 +6784,7 @@ struct in_addr *inp, *inpmask; /* ------------------------------------------------------------------------ */ -/* Function: fr_matchtag */ +/* Function: ipf_matchtag */ /* Returns: 0 == mismatch, 1 == match. */ /* Parameters: tag1(I) - pointer to first tag to compare */ /* tag2(I) - pointer to second tag to compare */ @@ -5524,8 +6796,9 @@ struct in_addr *inp, *inpmask; /* comparison. This function should only be called with both tag1 and tag2 */ /* as non-NULL pointers. */ /* ------------------------------------------------------------------------ */ -int fr_matchtag(tag1, tag2) -ipftag_t *tag1, *tag2; +int +ipf_matchtag(tag1, tag2) + ipftag_t *tag1, *tag2; { if (tag1 == tag2) return 1; @@ -5543,16 +6816,18 @@ ipftag_t *tag1, *tag2; /* ------------------------------------------------------------------------ */ -/* Function: fr_coalesce */ +/* Function: ipf_coalesce */ /* Returns: 1 == success, -1 == failure, 0 == no change */ /* Parameters: fin(I) - pointer to packet information */ /* */ /* Attempt to get all of the packet data into a single, contiguous buffer. */ /* If this call returns a failure then the buffers have also been freed. */ /* ------------------------------------------------------------------------ */ -int fr_coalesce(fin) -fr_info_t *fin; +int +ipf_coalesce(fin) + fr_info_t *fin; { + if ((fin->fin_flx & FI_COALESCE) != 0) return 1; @@ -5564,11 +6839,15 @@ fr_info_t *fin; return 0; #if defined(_KERNEL) - if (fr_pullup(fin->fin_m, fin, fin->fin_plen) == NULL) { - ATOMIC_INCL(fr_badcoalesces[fin->fin_out]); + if (ipf_pullup(fin->fin_m, fin, fin->fin_plen) == NULL) { + ipf_main_softc_t *softc = fin->fin_main_soft; + + DT1(frb_coalesce, fr_info_t *, fin); + LBUMP(ipf_stats[fin->fin_out].fr_badcoalesces); # ifdef MENTAT FREE_MB_T(*fin->fin_mp); # endif + fin->fin_reason = FRB_COALESCE; *fin->fin_mp = NULL; fin->fin_m = NULL; return -1; @@ -5593,106 +6872,10 @@ fr_info_t *fin; * The obvious implication is if neither of these are set then the value can be * changed at any time without harm. */ -ipftuneable_t ipf_tuneables[] = { - /* filtering */ - { { &fr_flags }, "fr_flags", 0, 0xffffffff, - sizeof(fr_flags), 0 }, - { { &fr_active }, "fr_active", 0, 0, - sizeof(fr_active), IPFT_RDONLY }, - { { &fr_control_forwarding }, "fr_control_forwarding", 0, 1, - sizeof(fr_control_forwarding), 0 }, - { { &fr_update_ipid }, "fr_update_ipid", 0, 1, - sizeof(fr_update_ipid), 0 }, - { { &fr_chksrc }, "fr_chksrc", 0, 1, - sizeof(fr_chksrc), 0 }, - { { &fr_pass }, "fr_pass", 0, 0xffffffff, - sizeof(fr_pass), 0 }, - /* state */ - { { &fr_tcpidletimeout }, "fr_tcpidletimeout", 1, 0x7fffffff, - sizeof(fr_tcpidletimeout), IPFT_WRDISABLED }, - { { &fr_tcpclosewait }, "fr_tcpclosewait", 1, 0x7fffffff, - sizeof(fr_tcpclosewait), IPFT_WRDISABLED }, - { { &fr_tcplastack }, "fr_tcplastack", 1, 0x7fffffff, - sizeof(fr_tcplastack), IPFT_WRDISABLED }, - { { &fr_tcptimeout }, "fr_tcptimeout", 1, 0x7fffffff, - sizeof(fr_tcptimeout), IPFT_WRDISABLED }, - { { &fr_tcpclosed }, "fr_tcpclosed", 1, 0x7fffffff, - sizeof(fr_tcpclosed), IPFT_WRDISABLED }, - { { &fr_tcphalfclosed }, "fr_tcphalfclosed", 1, 0x7fffffff, - sizeof(fr_tcphalfclosed), IPFT_WRDISABLED }, - { { &fr_udptimeout }, "fr_udptimeout", 1, 0x7fffffff, - sizeof(fr_udptimeout), IPFT_WRDISABLED }, - { { &fr_udpacktimeout }, "fr_udpacktimeout", 1, 0x7fffffff, - sizeof(fr_udpacktimeout), IPFT_WRDISABLED }, - { { &fr_icmptimeout }, "fr_icmptimeout", 1, 0x7fffffff, - sizeof(fr_icmptimeout), IPFT_WRDISABLED }, - { { &fr_icmpacktimeout }, "fr_icmpacktimeout", 1, 0x7fffffff, - sizeof(fr_icmpacktimeout), IPFT_WRDISABLED }, - { { &fr_iptimeout }, "fr_iptimeout", 1, 0x7fffffff, - sizeof(fr_iptimeout), IPFT_WRDISABLED }, - { { &fr_statemax }, "fr_statemax", 1, 0x7fffffff, - sizeof(fr_statemax), 0 }, - { { &fr_statesize }, "fr_statesize", 1, 0x7fffffff, - sizeof(fr_statesize), IPFT_WRDISABLED }, - { { &fr_state_lock }, "fr_state_lock", 0, 1, - sizeof(fr_state_lock), IPFT_RDONLY }, - { { &fr_state_maxbucket }, "fr_state_maxbucket", 1, 0x7fffffff, - sizeof(fr_state_maxbucket), IPFT_WRDISABLED }, - { { &fr_state_maxbucket_reset }, "fr_state_maxbucket_reset", 0, 1, - sizeof(fr_state_maxbucket_reset), IPFT_WRDISABLED }, - { { &ipstate_logging }, "ipstate_logging", 0, 1, - sizeof(ipstate_logging), 0 }, - /* nat */ - { { &fr_nat_lock }, "fr_nat_lock", 0, 1, - sizeof(fr_nat_lock), IPFT_RDONLY }, - { { &ipf_nattable_sz }, "ipf_nattable_sz", 1, 0x7fffffff, - sizeof(ipf_nattable_sz), IPFT_WRDISABLED }, - { { &ipf_nattable_max }, "ipf_nattable_max", 1, 0x7fffffff, - sizeof(ipf_nattable_max), 0 }, - { { &ipf_natrules_sz }, "ipf_natrules_sz", 1, 0x7fffffff, - sizeof(ipf_natrules_sz), IPFT_WRDISABLED }, - { { &ipf_rdrrules_sz }, "ipf_rdrrules_sz", 1, 0x7fffffff, - sizeof(ipf_rdrrules_sz), IPFT_WRDISABLED }, - { { &ipf_hostmap_sz }, "ipf_hostmap_sz", 1, 0x7fffffff, - sizeof(ipf_hostmap_sz), IPFT_WRDISABLED }, - { { &fr_nat_maxbucket }, "fr_nat_maxbucket", 1, 0x7fffffff, - sizeof(fr_nat_maxbucket), IPFT_WRDISABLED }, - { { &fr_nat_maxbucket_reset }, "fr_nat_maxbucket_reset", 0, 1, - sizeof(fr_nat_maxbucket_reset), IPFT_WRDISABLED }, - { { &nat_logging }, "nat_logging", 0, 1, - sizeof(nat_logging), 0 }, - { { &fr_defnatage }, "fr_defnatage", 1, 0x7fffffff, - sizeof(fr_defnatage), IPFT_WRDISABLED }, - { { &fr_defnatipage }, "fr_defnatipage", 1, 0x7fffffff, - sizeof(fr_defnatipage), IPFT_WRDISABLED }, - { { &fr_defnaticmpage }, "fr_defnaticmpage", 1, 0x7fffffff, - sizeof(fr_defnaticmpage), IPFT_WRDISABLED }, - /* frag */ - { { &ipfr_size }, "ipfr_size", 1, 0x7fffffff, - sizeof(ipfr_size), IPFT_WRDISABLED }, - { { &fr_ipfrttl }, "fr_ipfrttl", 1, 0x7fffffff, - sizeof(fr_ipfrttl), IPFT_WRDISABLED }, -#ifdef IPFILTER_LOG - /* log */ - { { &ipl_suppress }, "ipl_suppress", 0, 1, - sizeof(ipl_suppress), 0 }, - { { &ipl_buffer_sz }, "ipl_buffer_sz", 0, 0, - sizeof(ipl_buffer_sz), IPFT_RDONLY }, - { { &ipl_logmax }, "ipl_logmax", 0, 0x7fffffff, - sizeof(ipl_logmax), IPFT_WRDISABLED }, - { { &ipl_logall }, "ipl_logall", 0, 1, - sizeof(ipl_logall), 0 }, - { { &ipl_logsize }, "ipl_logsize", 0, 0x80000, - sizeof(ipl_logsize), 0 }, -#endif - { { NULL }, NULL, 0, 0 } -}; - -static ipftuneable_t *ipf_tunelist = NULL; /* ------------------------------------------------------------------------ */ -/* Function: fr_findtunebycookie */ +/* Function: ipf_tune_findbycookie */ /* Returns: NULL = search failed, else pointer to tune struct */ /* Parameters: cookie(I) - cookie value to search for amongst tuneables */ /* next(O) - pointer to place to store the cookie for the */ @@ -5703,12 +6886,14 @@ static ipftuneable_t *ipf_tunelist = NULL; /* a matching value for "cookie" - ie its address. When returning a match, */ /* the next one to be found may be returned inside next. */ /* ------------------------------------------------------------------------ */ -static ipftuneable_t *fr_findtunebycookie(cookie, next) -void *cookie, **next; +static ipftuneable_t * +ipf_tune_findbycookie(ptop, cookie, next) + ipftuneable_t **ptop; + void *cookie, **next; { ipftuneable_t *ta, **tap; - for (ta = ipf_tuneables; ta->ipft_name != NULL; ta++) + for (ta = *ptop; ta->ipft_name != NULL; ta++) if (ta == cookie) { if (next != NULL) { /* @@ -5722,12 +6907,12 @@ void *cookie, **next; if ((ta + 1)->ipft_name != NULL) *next = ta + 1; else - *next = &ipf_tunelist; + *next = ptop; } return ta; } - for (tap = &ipf_tunelist; (ta = *tap) != NULL; tap = &ta->ipft_next) + for (tap = ptop; (ta = *tap) != NULL; tap = &ta->ipft_next) if (tap == cookie) { if (next != NULL) *next = &ta->ipft_next; @@ -5741,7 +6926,7 @@ void *cookie, **next; /* ------------------------------------------------------------------------ */ -/* Function: fr_findtunebyname */ +/* Function: ipf_tune_findbyname */ /* Returns: NULL = search failed, else pointer to tune struct */ /* Parameters: name(I) - name of the tuneable entry to find. */ /* */ @@ -5749,44 +6934,192 @@ void *cookie, **next; /* for an entry with a matching name. If we can find one, return a pointer */ /* to the matching structure. */ /* ------------------------------------------------------------------------ */ -static ipftuneable_t *fr_findtunebyname(name) -char *name; +static ipftuneable_t * +ipf_tune_findbyname(top, name) + ipftuneable_t *top; + const char *name; { ipftuneable_t *ta; - for (ta = ipf_tuneables; ta->ipft_name != NULL; ta++) + for (ta = top; ta != NULL; ta = ta->ipft_next) if (!strcmp(ta->ipft_name, name)) { return ta; } - for (ta = ipf_tunelist; ta != NULL; ta = ta->ipft_next) - if (!strcmp(ta->ipft_name, name)) { - return ta; + return NULL; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_tune_add_array */ +/* Returns: int - 0 == success, else failure */ +/* Parameters: newtune - pointer to new tune array to add to tuneables */ +/* */ +/* Appends tune structures from the array passed in (newtune) to the end of */ +/* the current list of "dynamic" tuneable parameters. */ +/* If any entry to be added is already present (by name) then the operation */ +/* is aborted - entries that have been added are removed before returning. */ +/* An entry with no name (NULL) is used as the indication that the end of */ +/* the array has been reached. */ +/* ------------------------------------------------------------------------ */ +int +ipf_tune_add_array(softc, newtune) + ipf_main_softc_t *softc; + ipftuneable_t *newtune; +{ + ipftuneable_t *nt, *dt; + int error = 0; + + for (nt = newtune; nt->ipft_name != NULL; nt++) { + error = ipf_tune_add(softc, nt); + if (error != 0) { + for (dt = newtune; dt != nt; dt++) { + (void) ipf_tune_del(softc, dt); + } } + } - return NULL; + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_tune_array_link */ +/* Returns: 0 == success, -1 == failure */ +/* Parameters: softc(I) - soft context pointerto work with */ +/* array(I) - pointer to an array of tuneables */ +/* */ +/* Given an array of tunables (array), append them to the current list of */ +/* tuneables for this context (softc->ipf_tuners.) To properly prepare the */ +/* the array for being appended to the list, initialise all of the next */ +/* pointers so we don't need to walk parts of it with ++ and others with */ +/* next. The array is expected to have an entry with a NULL name as the */ +/* terminator. Trying to add an array with no non-NULL names will return as */ +/* a failure. */ +/* ------------------------------------------------------------------------ */ +int +ipf_tune_array_link(softc, array) + ipf_main_softc_t *softc; + ipftuneable_t *array; +{ + ipftuneable_t *t, **p; + + t = array; + if (t->ipft_name == NULL) + return -1; + + for (; t[1].ipft_name != NULL; t++) + t[0].ipft_next = &t[1]; + t->ipft_next = NULL; + + /* + * Since a pointer to the last entry isn't kept, we need to find it + * each time we want to add new variables to the list. + */ + for (p = &softc->ipf_tuners; (t = *p) != NULL; p = &t->ipft_next) + if (t->ipft_name == NULL) + break; + *p = array; + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_tune_array_unlink */ +/* Returns: 0 == success, -1 == failure */ +/* Parameters: softc(I) - soft context pointerto work with */ +/* array(I) - pointer to an array of tuneables */ +/* */ +/* ------------------------------------------------------------------------ */ +int +ipf_tune_array_unlink(softc, array) + ipf_main_softc_t *softc; + ipftuneable_t *array; +{ + ipftuneable_t *t, **p; + + for (p = &softc->ipf_tuners; (t = *p) != NULL; p = &t->ipft_next) + if (t == array) + break; + if (t == NULL) + return -1; + + for (; t[1].ipft_name != NULL; t++) + ; + + *p = t->ipft_next; + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_tune_array_copy */ +/* Returns: NULL = failure, else pointer to new array */ +/* Parameters: base(I) - pointer to structure base */ +/* size(I) - size of the array at template */ +/* template(I) - original array to copy */ +/* */ +/* Allocate memory for a new set of tuneable values and copy everything */ +/* from template into the new region of memory. The new region is full of */ +/* uninitialised pointers (ipft_next) so set them up. Now, ipftp_offset... */ +/* */ +/* NOTE: the following assumes that sizeof(long) == sizeof(void *) */ +/* In the array template, ipftp_offset is the offset (in bytes) of the */ +/* location of the tuneable value inside the structure pointed to by base. */ +/* As ipftp_offset is a union over the pointers to the tuneable values, if */ +/* we add base to the copy's ipftp_offset, copy ends up with a pointer in */ +/* ipftp_void that points to the stored value. */ +/* ------------------------------------------------------------------------ */ +ipftuneable_t * +ipf_tune_array_copy(base, size, template) + void *base; + size_t size; + ipftuneable_t *template; +{ + ipftuneable_t *copy; + int i; + + + KMALLOCS(copy, ipftuneable_t *, size); + if (copy == NULL) { + return NULL; + } + bcopy(template, copy, size); + + for (i = 0; copy[i].ipft_name; i++) { + copy[i].ipft_una.ipftp_offset += (u_long)base; + copy[i].ipft_next = copy + i + 1; + } + + return copy; } /* ------------------------------------------------------------------------ */ -/* Function: fr_addipftune */ +/* Function: ipf_tune_add */ /* Returns: int - 0 == success, else failure */ -/* Parameters: newtune - pointer to new tune struct to add to tuneables */ +/* Parameters: newtune - pointer to new tune entry to add to tuneables */ /* */ -/* Appends the tune structure pointer to by "newtune" to the end of the */ -/* current list of "dynamic" tuneable parameters. Once added, the owner */ -/* of the object is not expected to ever change "ipft_next". */ +/* Appends tune structures from the array passed in (newtune) to the end of */ +/* the current list of "dynamic" tuneable parameters. Once added, the */ +/* owner of the object is not expected to ever change "ipft_next". */ /* ------------------------------------------------------------------------ */ -int fr_addipftune(newtune) -ipftuneable_t *newtune; +int +ipf_tune_add(softc, newtune) + ipf_main_softc_t *softc; + ipftuneable_t *newtune; { ipftuneable_t *ta, **tap; - ta = fr_findtunebyname(newtune->ipft_name); - if (ta != NULL) + ta = ipf_tune_findbyname(softc->ipf_tuners, newtune->ipft_name); + if (ta != NULL) { + IPFERROR(74); return EEXIST; + } - for (tap = &ipf_tunelist; *tap != NULL; tap = &(*tap)->ipft_next) + for (tap = &softc->ipf_tuners; *tap != NULL; tap = &(*tap)->ipft_next) ; newtune->ipft_next = NULL; @@ -5796,33 +7129,72 @@ ipftuneable_t *newtune; /* ------------------------------------------------------------------------ */ -/* Function: fr_delipftune */ +/* Function: ipf_tune_del */ /* Returns: int - 0 == success, else failure */ -/* Parameters: oldtune - pointer to tune struct to remove from the list of */ +/* Parameters: oldtune - pointer to tune entry to remove from the list of */ /* current dynamic tuneables */ /* */ /* Search for the tune structure, by pointer, in the list of those that are */ /* dynamically added at run time. If found, adjust the list so that this */ /* structure is no longer part of it. */ /* ------------------------------------------------------------------------ */ -int fr_delipftune(oldtune) -ipftuneable_t *oldtune; +int +ipf_tune_del(softc, oldtune) + ipf_main_softc_t *softc; + ipftuneable_t *oldtune; { ipftuneable_t *ta, **tap; + int error = 0; - for (tap = &ipf_tunelist; (ta = *tap) != NULL; tap = &ta->ipft_next) + for (tap = &softc->ipf_tuners; (ta = *tap) != NULL; + tap = &ta->ipft_next) { if (ta == oldtune) { *tap = oldtune->ipft_next; oldtune->ipft_next = NULL; - return 0; + break; } + } + + if (ta == NULL) { + error = ESRCH; + IPFERROR(75); + } + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_tune_del_array */ +/* Returns: int - 0 == success, else failure */ +/* Parameters: oldtune - pointer to tuneables array */ +/* */ +/* Remove each tuneable entry in the array from the list of "dynamic" */ +/* tunables. If one entry should fail to be found, an error will be */ +/* returned and no further ones removed. */ +/* An entry with a NULL name is used as the indicator of the last entry in */ +/* the array. */ +/* ------------------------------------------------------------------------ */ +int +ipf_tune_del_array(softc, oldtune) + ipf_main_softc_t *softc; + ipftuneable_t *oldtune; +{ + ipftuneable_t *ot; + int error = 0; + + for (ot = oldtune; ot->ipft_name != NULL; ot++) { + error = ipf_tune_del(softc, ot); + if (error != 0) + break; + } + + return error; - return ESRCH; } /* ------------------------------------------------------------------------ */ -/* Function: fr_ipftune */ +/* Function: ipf_tune */ /* Returns: int - 0 == success, else failure */ /* Parameters: cmd(I) - ioctl command number */ /* data(I) - pointer to ioctl data structure */ @@ -5834,16 +7206,18 @@ ipftuneable_t *oldtune; /* and 'destruction' routines of the various components of ipfilter are all */ /* each responsible for handling their own values being too big. */ /* ------------------------------------------------------------------------ */ -int fr_ipftune(cmd, data) -ioctlcmd_t cmd; -void *data; +int +ipf_ipftune(softc, cmd, data) + ipf_main_softc_t *softc; + ioctlcmd_t cmd; + void *data; { ipftuneable_t *ta; ipftune_t tu; void *cookie; int error; - error = fr_inobj(data, &tu, IPFOBJ_TUNEABLE); + error = ipf_inobj(softc, data, NULL, &tu, IPFOBJ_TUNEABLE); if (error != 0) return error; @@ -5864,9 +7238,10 @@ void *data; * at the front of the list. */ if (cookie != NULL) { - ta = fr_findtunebycookie(cookie, &tu.ipft_cookie); + ta = ipf_tune_findbycookie(&softc->ipf_tuners, + cookie, &tu.ipft_cookie); } else { - ta = ipf_tuneables; + ta = softc->ipf_tuners; tu.ipft_cookie = ta + 1; } if (ta != NULL) { @@ -5874,8 +7249,10 @@ void *data; * Entry found, but does the data pointed to by that * row fit in what we can return? */ - if (ta->ipft_sz > sizeof(tu.ipft_un)) + if (ta->ipft_sz > sizeof(tu.ipft_un)) { + IPFERROR(76); return EINVAL; + } tu.ipft_vlong = 0; if (ta->ipft_sz == sizeof(u_long)) @@ -5895,7 +7272,7 @@ void *data; MIN(sizeof(tu.ipft_name), strlen(ta->ipft_name) + 1)); } - error = fr_outobj(data, &tu, IPFOBJ_TUNEABLE); + error = ipf_outobj(softc, data, &tu, IPFOBJ_TUNEABLE); break; case SIOCIPFGET : @@ -5904,13 +7281,16 @@ void *data; * Search by name or by cookie value for a particular entry * in the tuning paramter table. */ + IPFERROR(77); error = ESRCH; if (cookie != NULL) { - ta = fr_findtunebycookie(cookie, NULL); + ta = ipf_tune_findbycookie(&softc->ipf_tuners, + cookie, NULL); if (ta != NULL) error = 0; } else if (tu.ipft_name[0] != '\0') { - ta = fr_findtunebyname(tu.ipft_name); + ta = ipf_tune_findbyname(softc->ipf_tuners, + tu.ipft_name); if (ta != NULL) error = 0; } @@ -5930,11 +7310,12 @@ void *data; tu.ipft_vshort = *ta->ipft_pshort; else if (ta->ipft_sz == sizeof(u_char)) tu.ipft_vchar = *ta->ipft_pchar; + tu.ipft_cookie = ta; tu.ipft_sz = ta->ipft_sz; tu.ipft_min = ta->ipft_min; tu.ipft_max = ta->ipft_max; tu.ipft_flags = ta->ipft_flags; - error = fr_outobj(data, &tu, IPFOBJ_TUNEABLE); + error = ipf_outobj(softc, data, &tu, IPFOBJ_TUNEABLE); } else if (cmd == (ioctlcmd_t)SIOCIPFSET) { /* @@ -5945,35 +7326,49 @@ void *data; u_long in; if (((ta->ipft_flags & IPFT_WRDISABLED) != 0) && - (fr_running > 0)) { + (softc->ipf_running > 0)) { + IPFERROR(78); error = EBUSY; break; } in = tu.ipft_vlong; if (in < ta->ipft_min || in > ta->ipft_max) { + IPFERROR(79); error = EINVAL; break; } - if (ta->ipft_sz == sizeof(u_long)) { + if (ta->ipft_func != NULL) { + SPL_INT(s); + + SPL_NET(s); + error = (*ta->ipft_func)(softc, ta, + &tu.ipft_un); + SPL_X(s); + + } else if (ta->ipft_sz == sizeof(u_long)) { tu.ipft_vlong = *ta->ipft_plong; *ta->ipft_plong = in; + } else if (ta->ipft_sz == sizeof(u_int)) { tu.ipft_vint = *ta->ipft_pint; *ta->ipft_pint = (u_int)(in & 0xffffffff); + } else if (ta->ipft_sz == sizeof(u_short)) { tu.ipft_vshort = *ta->ipft_pshort; *ta->ipft_pshort = (u_short)(in & 0xffff); + } else if (ta->ipft_sz == sizeof(u_char)) { tu.ipft_vchar = *ta->ipft_pchar; *ta->ipft_pchar = (u_char)(in & 0xff); } - error = fr_outobj(data, &tu, IPFOBJ_TUNEABLE); + error = ipf_outobj(softc, data, &tu, IPFOBJ_TUNEABLE); } break; default : + IPFERROR(80); error = EINVAL; break; } @@ -5983,227 +7378,2835 @@ void *data; /* ------------------------------------------------------------------------ */ -/* Function: fr_initialise */ -/* Returns: int - 0 == success, < 0 == failure */ -/* Parameters: None. */ +/* Function: ipf_zerostats */ +/* Returns: int - 0 = success, else failure */ +/* Parameters: data(O) - pointer to pointer for copying data back to */ /* */ -/* Call of the initialise functions for all the various subsystems inside */ -/* of IPFilter. If any of them should fail, return immeadiately a failure */ -/* BUT do not try to recover from the error here. */ +/* Copies the current statistics out to userspace and then zero's the */ +/* current ones in the kernel. The lock is only held across the bzero() as */ +/* the copyout may result in paging (ie network activity.) */ /* ------------------------------------------------------------------------ */ -int fr_initialise() +int +ipf_zerostats(softc, data) + ipf_main_softc_t *softc; + caddr_t data; { - int i; + friostat_t fio; + ipfobj_t obj; + int error; -#ifdef IPFILTER_LOG - i = fr_loginit(); - if (i < 0) - return -10 + i; + error = ipf_inobj(softc, data, &obj, &fio, IPFOBJ_IPFSTAT); + if (error != 0) + return error; + ipf_getstat(softc, &fio, obj.ipfo_rev); + error = ipf_outobj(softc, data, &fio, IPFOBJ_IPFSTAT); + if (error != 0) + return error; + + WRITE_ENTER(&softc->ipf_mutex); + bzero(&softc->ipf_stats, sizeof(softc->ipf_stats)); + RWLOCK_EXIT(&softc->ipf_mutex); + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_resolvedest */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* base(I) - where strings are stored */ +/* fdp(IO) - pointer to destination information to resolve */ +/* v(I) - IP protocol version to match */ +/* */ +/* Looks up an interface name in the frdest structure pointed to by fdp and */ +/* if a matching name can be found for the particular IP protocol version */ +/* then store the interface pointer in the frdest struct. If no match is */ +/* found, then set the interface pointer to be -1 as NULL is considered to */ +/* indicate there is no information at all in the structure. */ +/* ------------------------------------------------------------------------ */ +int +ipf_resolvedest(softc, base, fdp, v) + ipf_main_softc_t *softc; + char *base; + frdest_t *fdp; + int v; +{ + int errval = 0; + void *ifp; + + ifp = NULL; + + if (fdp->fd_name != -1) { + if (fdp->fd_type == FRD_DSTLIST) { + ifp = ipf_lookup_res_name(softc, IPL_LOGIPF, + IPLT_DSTLIST, + base + fdp->fd_name, + NULL); + if (ifp == NULL) { + IPFERROR(144); + errval = ESRCH; + } + } else { + ifp = GETIFP(base + fdp->fd_name, v); + if (ifp == NULL) + ifp = (void *)-1; + } + } + fdp->fd_ptr = ifp; + + if ((ifp != NULL) && (ifp != (void *)-1)) { + fdp->fd_local = ipf_deliverlocal(softc, v, ifp, &fdp->fd_ip6); + } + + return errval; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_resolvenic */ +/* Returns: void* - NULL = wildcard name, -1 = failed to find NIC, else */ +/* pointer to interface structure for NIC */ +/* Parameters: softc(I)- pointer to soft context main structure */ +/* name(I) - complete interface name */ +/* v(I) - IP protocol version */ +/* */ +/* Look for a network interface structure that firstly has a matching name */ +/* to that passed in and that is also being used for that IP protocol */ +/* version (necessary on some platforms where there are separate listings */ +/* for both IPv4 and IPv6 on the same physical NIC. */ +/* ------------------------------------------------------------------------ */ +void * +ipf_resolvenic(softc, name, v) + ipf_main_softc_t *softc; + char *name; + int v; +{ + void *nic; + + softc = softc; /* gcc -Wextra */ + if (name[0] == '\0') + return NULL; + + if ((name[1] == '\0') && ((name[0] == '-') || (name[0] == '*'))) { + return NULL; + } + + nic = GETIFP(name, v); + if (nic == NULL) + nic = (void *)-1; + return nic; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_token_expire */ +/* Returns: None. */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* */ +/* This function is run every ipf tick to see if there are any tokens that */ +/* have been held for too long and need to be freed up. */ +/* ------------------------------------------------------------------------ */ +void +ipf_token_expire(softc) + ipf_main_softc_t *softc; +{ + ipftoken_t *it; + + WRITE_ENTER(&softc->ipf_tokens); + while ((it = softc->ipf_token_head) != NULL) { + if (it->ipt_die > softc->ipf_ticks) + break; + + ipf_token_deref(softc, it); + } + RWLOCK_EXIT(&softc->ipf_tokens); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_token_flush */ +/* Returns: None. */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* */ +/* Loop through all of the existing tokens and call deref to see if they */ +/* can be freed. Normally a function like this might just loop on */ +/* ipf_token_head but there is a chance that a token might have a ref count */ +/* of greater than one and in that case the the reference would drop twice */ +/* by code that is only entitled to drop it once. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_token_flush(softc) + ipf_main_softc_t *softc; +{ + ipftoken_t *it, *next; + + WRITE_ENTER(&softc->ipf_tokens); + for (it = softc->ipf_token_head; it != NULL; it = next) { + next = it->ipt_next; + (void) ipf_token_deref(softc, it); + } + RWLOCK_EXIT(&softc->ipf_tokens); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_token_del */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I)- pointer to soft context main structure */ +/* type(I) - the token type to match */ +/* uid(I) - uid owning the token */ +/* ptr(I) - context pointer for the token */ +/* */ +/* This function looks for a a token in the current list that matches up */ +/* the fields (type, uid, ptr). If none is found, ESRCH is returned, else */ +/* call ipf_token_dewref() to remove it from the list. In the event that */ +/* the token has a reference held elsewhere, setting ipt_complete to 2 */ +/* enables debugging to distinguish between the two paths that ultimately */ +/* lead to a token to be deleted. */ +/* ------------------------------------------------------------------------ */ +int +ipf_token_del(softc, type, uid, ptr) + ipf_main_softc_t *softc; + int type, uid; + void *ptr; +{ + ipftoken_t *it; + int error; + + IPFERROR(82); + error = ESRCH; + + WRITE_ENTER(&softc->ipf_tokens); + for (it = softc->ipf_token_head; it != NULL; it = it->ipt_next) { + if (ptr == it->ipt_ctx && type == it->ipt_type && + uid == it->ipt_uid) { + it->ipt_complete = 2; + ipf_token_deref(softc, it); + error = 0; + break; + } + } + RWLOCK_EXIT(&softc->ipf_tokens); + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_token_mark_complete */ +/* Returns: None. */ +/* Parameters: token(I) - pointer to token structure */ +/* */ +/* Mark a token as being ineligable for being found with ipf_token_find. */ +/* ------------------------------------------------------------------------ */ +void +ipf_token_mark_complete(token) + ipftoken_t *token; +{ + if (token->ipt_complete == 0) + token->ipt_complete = 1; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_token_find */ +/* Returns: ipftoken_t * - NULL if no memory, else pointer to token */ +/* Parameters: softc(I)- pointer to soft context main structure */ +/* type(I) - the token type to match */ +/* uid(I) - uid owning the token */ +/* ptr(I) - context pointer for the token */ +/* */ +/* This function looks for a live token in the list of current tokens that */ +/* matches the tuple (type, uid, ptr). If one cannot be found then one is */ +/* allocated. If one is found then it is moved to the top of the list of */ +/* currently active tokens. */ +/* ------------------------------------------------------------------------ */ +ipftoken_t * +ipf_token_find(softc, type, uid, ptr) + ipf_main_softc_t *softc; + int type, uid; + void *ptr; +{ + ipftoken_t *it, *new; + + KMALLOC(new, ipftoken_t *); + if (new != NULL) + bzero((char *)new, sizeof(*new)); + + WRITE_ENTER(&softc->ipf_tokens); + for (it = softc->ipf_token_head; it != NULL; it = it->ipt_next) { + if ((ptr == it->ipt_ctx) && (type == it->ipt_type) && + (uid == it->ipt_uid) && (it->ipt_complete < 2)) + break; + } + + if (it == NULL) { + it = new; + new = NULL; + if (it == NULL) { + RWLOCK_EXIT(&softc->ipf_tokens); + return NULL; + } + it->ipt_ctx = ptr; + it->ipt_uid = uid; + it->ipt_type = type; + it->ipt_ref = 1; + } else { + if (new != NULL) { + KFREE(new); + new = NULL; + } + + if (it->ipt_complete > 0) + it = NULL; + else + ipf_token_unlink(softc, it); + } + + if (it != NULL) { + it->ipt_pnext = softc->ipf_token_tail; + *softc->ipf_token_tail = it; + softc->ipf_token_tail = &it->ipt_next; + it->ipt_next = NULL; + it->ipt_ref++; + + it->ipt_die = softc->ipf_ticks + 20; + } + + RWLOCK_EXIT(&softc->ipf_tokens); + + return it; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_token_unlink */ +/* Returns: None. */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* token(I) - pointer to token structure */ +/* Write Locks: ipf_tokens */ +/* */ +/* This function unlinks a token structure from the linked list of tokens */ +/* that "own" it. The head pointer never needs to be explicitly adjusted */ +/* but the tail does due to the linked list implementation. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_token_unlink(softc, token) + ipf_main_softc_t *softc; + ipftoken_t *token; +{ + + if (softc->ipf_token_tail == &token->ipt_next) + softc->ipf_token_tail = token->ipt_pnext; + + *token->ipt_pnext = token->ipt_next; + if (token->ipt_next != NULL) + token->ipt_next->ipt_pnext = token->ipt_pnext; + token->ipt_next = NULL; + token->ipt_pnext = NULL; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_token_deref */ +/* Returns: int - 0 == token freed, else reference count */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* token(I) - pointer to token structure */ +/* Write Locks: ipf_tokens */ +/* */ +/* Drop the reference count on the token structure and if it drops to zero, */ +/* call the dereference function for the token type because it is then */ +/* possible to free the token data structure. */ +/* ------------------------------------------------------------------------ */ +int +ipf_token_deref(softc, token) + ipf_main_softc_t *softc; + ipftoken_t *token; +{ + void *data, **datap; + + ASSERT(token->ipt_ref > 0); + token->ipt_ref--; + if (token->ipt_ref > 0) + return token->ipt_ref; + + data = token->ipt_data; + datap = &data; + + if ((data != NULL) && (data != (void *)-1)) { + switch (token->ipt_type) + { + case IPFGENITER_IPF : + (void) ipf_derefrule(softc, (frentry_t **)datap); + break; + case IPFGENITER_IPNAT : + WRITE_ENTER(&softc->ipf_nat); + ipf_nat_rule_deref(softc, (ipnat_t **)datap); + RWLOCK_EXIT(&softc->ipf_nat); + break; + case IPFGENITER_NAT : + ipf_nat_deref(softc, (nat_t **)datap); + break; + case IPFGENITER_STATE : + ipf_state_deref(softc, (ipstate_t **)datap); + break; + case IPFGENITER_FRAG : + ipf_frag_pkt_deref(softc, (ipfr_t **)datap); + break; + case IPFGENITER_NATFRAG : + ipf_frag_nat_deref(softc, (ipfr_t **)datap); + break; + case IPFGENITER_HOSTMAP : + WRITE_ENTER(&softc->ipf_nat); + ipf_nat_hostmapdel(softc, (hostmap_t **)datap); + RWLOCK_EXIT(&softc->ipf_nat); + break; + default : + ipf_lookup_iterderef(softc, token->ipt_type, data); + break; + } + } + + ipf_token_unlink(softc, token); + KFREE(token); + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nextrule */ +/* Returns: frentry_t * - NULL == no more rules, else pointer to next */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* fr(I) - pointer to filter rule */ +/* out(I) - 1 == out rules, 0 == input rules */ +/* */ +/* Starting with "fr", find the next rule to visit. This includes visiting */ +/* the list of rule groups if either fr is NULL (empty list) or it is the */ +/* last rule in the list. When walking rule lists, it is either input or */ +/* output rules that are returned, never both. */ +/* ------------------------------------------------------------------------ */ +static frentry_t * +ipf_nextrule(softc, active, unit, fr, out) + ipf_main_softc_t *softc; + int active, unit; + frentry_t *fr; + int out; +{ + frentry_t *next; + frgroup_t *fg; + + if (fr != NULL && fr->fr_group != -1) { + fg = ipf_findgroup(softc, fr->fr_names + fr->fr_group, + unit, active, NULL); + if (fg != NULL) + fg = fg->fg_next; + } else { + fg = softc->ipf_groups[unit][active]; + } + + while (fg != NULL) { + next = fg->fg_start; + while (next != NULL) { + if (out) { + if (next->fr_flags & FR_OUTQUE) + return next; + } else if (next->fr_flags & FR_INQUE) { + return next; + } + next = next->fr_next; + } + if (next == NULL) + fg = fg->fg_next; + } + + return NULL; +} + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_getnextrule */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I)- pointer to soft context main structure */ +/* t(I) - pointer to destination information to resolve */ +/* ptr(I) - pointer to ipfobj_t to copyin from user space */ +/* */ +/* This function's first job is to bring in the ipfruleiter_t structure via */ +/* the ipfobj_t structure to determine what should be the next rule to */ +/* return. Once the ipfruleiter_t has been brought in, it then tries to */ +/* find the 'next rule'. This may include searching rule group lists or */ +/* just be as simple as looking at the 'next' field in the rule structure. */ +/* When we have found the rule to return, increase its reference count and */ +/* if we used an existing rule to get here, decrease its reference count. */ +/* ------------------------------------------------------------------------ */ +int +ipf_getnextrule(softc, t, ptr) + ipf_main_softc_t *softc; + ipftoken_t *t; + void *ptr; +{ + frentry_t *fr, *next, zero; + ipfruleiter_t it; + int error, out; + frgroup_t *fg; + ipfobj_t obj; + int predict; + char *dst; + int unit; + + if (t == NULL || ptr == NULL) { + IPFERROR(84); + return EFAULT; + } + + error = ipf_inobj(softc, ptr, &obj, &it, IPFOBJ_IPFITER); + if (error != 0) + return error; + + if ((it.iri_inout < 0) || (it.iri_inout > 3)) { + IPFERROR(85); + return EINVAL; + } + if ((it.iri_active != 0) && (it.iri_active != 1)) { + IPFERROR(86); + return EINVAL; + } + if (it.iri_nrules == 0) { + IPFERROR(87); + return ENOSPC; + } + if (it.iri_rule == NULL) { + IPFERROR(88); + return EFAULT; + } + + fg = NULL; + fr = t->ipt_data; + if ((it.iri_inout & F_OUT) != 0) + out = 1; + else + out = 0; + if ((it.iri_inout & F_ACIN) != 0) + unit = IPL_LOGCOUNT; + else + unit = IPL_LOGIPF; + + READ_ENTER(&softc->ipf_mutex); + if (fr == NULL) { + if (*it.iri_group == '\0') { + if (unit == IPL_LOGCOUNT) { + next = softc->ipf_acct[out][it.iri_active]; + } else { + next = softc->ipf_rules[out][it.iri_active]; + } + if (next == NULL) + next = ipf_nextrule(softc, it.iri_active, + unit, NULL, out); + } else { + fg = ipf_findgroup(softc, it.iri_group, unit, + it.iri_active, NULL); + if (fg != NULL) + next = fg->fg_start; + else + next = NULL; + } + } else { + next = fr->fr_next; + if (next == NULL) + next = ipf_nextrule(softc, it.iri_active, unit, + fr, out); + } + + if (next != NULL && next->fr_next != NULL) + predict = 1; + else if (ipf_nextrule(softc, it.iri_active, unit, next, out) != NULL) + predict = 1; + else + predict = 0; + + if (fr != NULL) + (void) ipf_derefrule(softc, &fr); + + obj.ipfo_type = IPFOBJ_FRENTRY; + dst = (char *)it.iri_rule; + + if (next != NULL) { + obj.ipfo_size = next->fr_size; + MUTEX_ENTER(&next->fr_lock); + next->fr_ref++; + MUTEX_EXIT(&next->fr_lock); + t->ipt_data = next; + } else { + obj.ipfo_size = sizeof(frentry_t); + bzero(&zero, sizeof(zero)); + next = &zero; + t->ipt_data = NULL; + } + it.iri_rule = predict ? next : NULL; + if (predict == 0) + ipf_token_mark_complete(t); + + RWLOCK_EXIT(&softc->ipf_mutex); + + obj.ipfo_ptr = dst; + error = ipf_outobjk(softc, &obj, next); + if (error == 0 && t->ipt_data != NULL) { + dst += obj.ipfo_size; + if (next->fr_data != NULL) { + ipfobj_t dobj; + + if (next->fr_type == FR_T_IPFEXPR) + dobj.ipfo_type = IPFOBJ_IPFEXPR; + else + dobj.ipfo_type = IPFOBJ_FRIPF; + dobj.ipfo_size = next->fr_dsize; + dobj.ipfo_rev = obj.ipfo_rev; + dobj.ipfo_ptr = dst; + error = ipf_outobjk(softc, &dobj, next->fr_data); + } + } + + if ((fr != NULL) && (next == &zero)) + (void) ipf_derefrule(softc, &fr); + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_frruleiter */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I)- pointer to soft context main structure */ +/* data(I) - the token type to match */ +/* uid(I) - uid owning the token */ +/* ptr(I) - context pointer for the token */ +/* */ +/* This function serves as a stepping stone between ipf_ipf_ioctl and */ +/* ipf_getnextrule. It's role is to find the right token in the kernel for */ +/* the process doing the ioctl and use that to ask for the next rule. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_frruleiter(softc, data, uid, ctx) + ipf_main_softc_t *softc; + void *data, *ctx; + int uid; +{ + ipftoken_t *token; + ipfruleiter_t it; + ipfobj_t obj; + int error; + + token = ipf_token_find(softc, IPFGENITER_IPF, uid, ctx); + if (token != NULL) { + error = ipf_getnextrule(softc, token, data); + WRITE_ENTER(&softc->ipf_tokens); + ipf_token_deref(softc, token); + RWLOCK_EXIT(&softc->ipf_tokens); + } else { + error = ipf_inobj(softc, data, &obj, &it, IPFOBJ_IPFITER); + if (error != 0) + return error; + it.iri_rule = NULL; + error = ipf_outobj(softc, data, &it, IPFOBJ_IPFITER); + } + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_geniter */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* token(I) - pointer to ipftoken_t structure */ +/* itp(I) - pointer to iterator data */ +/* */ +/* Decide which iterator function to call using information passed through */ +/* the ipfgeniter_t structure at itp. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_geniter(softc, token, itp) + ipf_main_softc_t *softc; + ipftoken_t *token; + ipfgeniter_t *itp; +{ + int error; + + switch (itp->igi_type) + { + case IPFGENITER_FRAG : + error = ipf_frag_pkt_next(softc, token, itp); + break; + default : + IPFERROR(92); + error = EINVAL; + break; + } + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_genericiter */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I)- pointer to soft context main structure */ +/* data(I) - the token type to match */ +/* uid(I) - uid owning the token */ +/* ptr(I) - context pointer for the token */ +/* */ +/* Handle the SIOCGENITER ioctl for the ipfilter device. The primary role */ +/* ------------------------------------------------------------------------ */ +int +ipf_genericiter(softc, data, uid, ctx) + ipf_main_softc_t *softc; + void *data, *ctx; + int uid; +{ + ipftoken_t *token; + ipfgeniter_t iter; + int error; + + error = ipf_inobj(softc, data, NULL, &iter, IPFOBJ_GENITER); + if (error != 0) + return error; + + token = ipf_token_find(softc, iter.igi_type, uid, ctx); + if (token != NULL) { + token->ipt_subtype = iter.igi_type; + error = ipf_geniter(softc, token, &iter); + WRITE_ENTER(&softc->ipf_tokens); + ipf_token_deref(softc, token); + RWLOCK_EXIT(&softc->ipf_tokens); + } else { + IPFERROR(93); + error = 0; + } + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_ipf_ioctl */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I)- pointer to soft context main structure */ +/* data(I) - the token type to match */ +/* cmd(I) - the ioctl command number */ +/* mode(I) - mode flags for the ioctl */ +/* uid(I) - uid owning the token */ +/* ptr(I) - context pointer for the token */ +/* */ +/* This function handles all of the ioctl command that are actually isssued */ +/* to the /dev/ipl device. */ +/* ------------------------------------------------------------------------ */ +int +ipf_ipf_ioctl(softc, data, cmd, mode, uid, ctx) + ipf_main_softc_t *softc; + caddr_t data; + ioctlcmd_t cmd; + int mode, uid; + void *ctx; +{ + friostat_t fio; + int error, tmp; + ipfobj_t obj; + SPL_INT(s); + + switch (cmd) + { + case SIOCFRENB : + if (!(mode & FWRITE)) { + IPFERROR(94); + error = EPERM; + } else { + error = BCOPYIN(data, &tmp, sizeof(tmp)); + if (error != 0) { + IPFERROR(95); + error = EFAULT; + break; + } + + WRITE_ENTER(&softc->ipf_global); + if (tmp) { + if (softc->ipf_running > 0) + error = 0; + else + error = ipfattach(softc); + if (error == 0) + softc->ipf_running = 1; + else + (void) ipfdetach(softc); + } else { + if (softc->ipf_running == 1) + error = ipfdetach(softc); + else + error = 0; + if (error == 0) + softc->ipf_running = -1; + } + RWLOCK_EXIT(&softc->ipf_global); + } + break; + + case SIOCIPFSET : + if (!(mode & FWRITE)) { + IPFERROR(96); + error = EPERM; + break; + } + /* FALLTHRU */ + case SIOCIPFGETNEXT : + case SIOCIPFGET : + error = ipf_ipftune(softc, cmd, (void *)data); + break; + + case SIOCSETFF : + if (!(mode & FWRITE)) { + IPFERROR(97); + error = EPERM; + } else { + error = BCOPYIN(data, &softc->ipf_flags, + sizeof(softc->ipf_flags)); + if (error != 0) { + IPFERROR(98); + error = EFAULT; + } + } + break; + + case SIOCGETFF : + error = BCOPYOUT(&softc->ipf_flags, data, + sizeof(softc->ipf_flags)); + if (error != 0) { + IPFERROR(99); + error = EFAULT; + } + break; + + case SIOCFUNCL : + error = ipf_resolvefunc(softc, (void *)data); + break; + + case SIOCINAFR : + case SIOCRMAFR : + case SIOCADAFR : + case SIOCZRLST : + if (!(mode & FWRITE)) { + IPFERROR(100); + error = EPERM; + } else { + error = frrequest(softc, IPL_LOGIPF, cmd, (caddr_t)data, + softc->ipf_active, 1); + } + break; + + case SIOCINIFR : + case SIOCRMIFR : + case SIOCADIFR : + if (!(mode & FWRITE)) { + IPFERROR(101); + error = EPERM; + } else { + error = frrequest(softc, IPL_LOGIPF, cmd, (caddr_t)data, + 1 - softc->ipf_active, 1); + } + break; + + case SIOCSWAPA : + if (!(mode & FWRITE)) { + IPFERROR(102); + error = EPERM; + } else { + WRITE_ENTER(&softc->ipf_mutex); + error = BCOPYOUT(&softc->ipf_active, data, + sizeof(softc->ipf_active)); + if (error != 0) { + IPFERROR(103); + error = EFAULT; + } else { + softc->ipf_active = 1 - softc->ipf_active; + } + RWLOCK_EXIT(&softc->ipf_mutex); + } + break; + + case SIOCGETFS : + error = ipf_inobj(softc, (void *)data, &obj, &fio, + IPFOBJ_IPFSTAT); + if (error != 0) + break; + ipf_getstat(softc, &fio, obj.ipfo_rev); + error = ipf_outobj(softc, (void *)data, &fio, IPFOBJ_IPFSTAT); + break; + + case SIOCFRZST : + if (!(mode & FWRITE)) { + IPFERROR(104); + error = EPERM; + } else + error = ipf_zerostats(softc, (caddr_t)data); + break; + + case SIOCIPFFL : + if (!(mode & FWRITE)) { + IPFERROR(105); + error = EPERM; + } else { + error = BCOPYIN(data, &tmp, sizeof(tmp)); + if (!error) { + tmp = ipf_flush(softc, IPL_LOGIPF, tmp); + error = BCOPYOUT(&tmp, data, sizeof(tmp)); + if (error != 0) { + IPFERROR(106); + error = EFAULT; + } + } else { + IPFERROR(107); + error = EFAULT; + } + } + break; + +#ifdef USE_INET6 + case SIOCIPFL6 : + if (!(mode & FWRITE)) { + IPFERROR(108); + error = EPERM; + } else { + error = BCOPYIN(data, &tmp, sizeof(tmp)); + if (!error) { + tmp = ipf_flush(softc, IPL_LOGIPF, tmp); + error = BCOPYOUT(&tmp, data, sizeof(tmp)); + if (error != 0) { + IPFERROR(109); + error = EFAULT; + } + } else { + IPFERROR(110); + error = EFAULT; + } + } + break; +#endif + + case SIOCSTLCK : + if (!(mode & FWRITE)) { + IPFERROR(122); + error = EPERM; + } else { + error = BCOPYIN(data, &tmp, sizeof(tmp)); + if (error == 0) { + ipf_state_setlock(softc->ipf_state_soft, tmp); + ipf_nat_setlock(softc->ipf_nat_soft, tmp); + ipf_frag_setlock(softc->ipf_frag_soft, tmp); + ipf_auth_setlock(softc->ipf_auth_soft, tmp); + } else { + IPFERROR(111); + error = EFAULT; + } + } + break; + +#ifdef IPFILTER_LOG + case SIOCIPFFB : + if (!(mode & FWRITE)) { + IPFERROR(112); + error = EPERM; + } else { + tmp = ipf_log_clear(softc, IPL_LOGIPF); + error = BCOPYOUT(&tmp, data, sizeof(tmp)); + if (error) { + IPFERROR(113); + error = EFAULT; + } + } + break; +#endif /* IPFILTER_LOG */ + + case SIOCFRSYN : + if (!(mode & FWRITE)) { + IPFERROR(114); + error = EPERM; + } else { + WRITE_ENTER(&softc->ipf_global); +#if (defined(MENTAT) && defined(_KERNEL)) && !defined(INSTANCES) + error = ipfsync(); +#else + ipf_sync(softc, NULL); + error = 0; #endif - i = fr_natinit(); - if (i < 0) - return -20 + i; - - i = fr_stateinit(); - if (i < 0) - return -30 + i; - - i = fr_authinit(); - if (i < 0) - return -40 + i; - - i = fr_fraginit(); - if (i < 0) - return -50 + i; - - i = appr_init(); - if (i < 0) - return -60 + i; - -#ifdef IPFILTER_SYNC - i = ipfsync_init(); - if (i < 0) - return -70 + i; + RWLOCK_EXIT(&softc->ipf_global); + + } + break; + + case SIOCGFRST : + error = ipf_outobj(softc, (void *)data, + ipf_frag_stats(softc->ipf_frag_soft), + IPFOBJ_FRAGSTAT); + break; + +#ifdef IPFILTER_LOG + case FIONREAD : + tmp = ipf_log_bytesused(softc, IPL_LOGIPF); + error = BCOPYOUT(&tmp, data, sizeof(tmp)); + break; #endif -#ifdef IPFILTER_SCAN - i = ipsc_init(); - if (i < 0) - return -80 + i; + + case SIOCIPFITER : + SPL_SCHED(s); + error = ipf_frruleiter(softc, data, uid, ctx); + SPL_X(s); + break; + + case SIOCGENITER : + SPL_SCHED(s); + error = ipf_genericiter(softc, data, uid, ctx); + SPL_X(s); + break; + + case SIOCIPFDELTOK : + error = BCOPYIN(data, &tmp, sizeof(tmp)); + if (error == 0) { + SPL_SCHED(s); + error = ipf_token_del(softc, tmp, uid, ctx); + SPL_X(s); + } + break; + + default : + IPFERROR(115); + error = EINVAL; + break; + } + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_decaps */ +/* Returns: int - -1 == decapsulation failed, else bit mask of */ +/* flags indicating packet filtering decision. */ +/* Parameters: fin(I) - pointer to packet information */ +/* pass(I) - IP protocol version to match */ +/* l5proto(I) - layer 5 protocol to decode UDP data as. */ +/* */ +/* This function is called for packets that are wrapt up in other packets, */ +/* for example, an IP packet that is the entire data segment for another IP */ +/* packet. If the basic constraints for this are satisfied, change the */ +/* buffer to point to the start of the inner packet and start processing */ +/* rules belonging to the head group this rule specifies. */ +/* ------------------------------------------------------------------------ */ +u_32_t +ipf_decaps(fin, pass, l5proto) + fr_info_t *fin; + u_32_t pass; + int l5proto; +{ + fr_info_t fin2, *fino = NULL; + int elen, hlen, nh; + grehdr_t gre; + ip_t *ip; + mb_t *m; + + if ((fin->fin_flx & FI_COALESCE) == 0) + if (ipf_coalesce(fin) == -1) + goto cantdecaps; + + m = fin->fin_m; + hlen = fin->fin_hlen; + + switch (fin->fin_p) + { + case IPPROTO_UDP : + /* + * In this case, the specific protocol being decapsulated + * inside UDP frames comes from the rule. + */ + nh = fin->fin_fr->fr_icode; + break; + + case IPPROTO_GRE : /* 47 */ + bcopy(fin->fin_dp, (char *)&gre, sizeof(gre)); + hlen += sizeof(grehdr_t); + if (gre.gr_R|gre.gr_s) + goto cantdecaps; + if (gre.gr_C) + hlen += 4; + if (gre.gr_K) + hlen += 4; + if (gre.gr_S) + hlen += 4; + + nh = IPPROTO_IP; + + /* + * If the routing options flag is set, validate that it is + * there and bounce over it. + */ +#if 0 + /* This is really heavy weight and lots of room for error, */ + /* so for now, put it off and get the simple stuff right. */ + if (gre.gr_R) { + u_char off, len, *s; + u_short af; + int end; + + end = 0; + s = fin->fin_dp; + s += hlen; + aplen = fin->fin_plen - hlen; + while (aplen > 3) { + af = (s[0] << 8) | s[1]; + off = s[2]; + len = s[3]; + aplen -= 4; + s += 4; + if (af == 0 && len == 0) { + end = 1; + break; + } + if (aplen < len) + break; + s += len; + aplen -= len; + } + if (end != 1) + goto cantdecaps; + hlen = s - (u_char *)fin->fin_dp; + } #endif -#ifdef IPFILTER_LOOKUP - i = ip_lookup_init(); - if (i < 0) - return -90 + i; + break; + +#ifdef IPPROTO_IPIP + case IPPROTO_IPIP : /* 4 */ #endif -#ifdef IPFILTER_COMPILED - ipfrule_add(); + nh = IPPROTO_IP; + break; + + default : /* Includes ESP, AH is special for IPv4 */ + goto cantdecaps; + } + + switch (nh) + { + case IPPROTO_IP : + case IPPROTO_IPV6 : + break; + default : + goto cantdecaps; + } + + bcopy((char *)fin, (char *)&fin2, sizeof(fin2)); + fino = fin; + fin = &fin2; + elen = hlen; +#if defined(MENTAT) && defined(_KERNEL) + m->b_rptr += elen; +#else + m->m_data += elen; + m->m_len -= elen; +#endif + fin->fin_plen -= elen; + + ip = (ip_t *)((char *)fin->fin_ip + elen); + + /* + * Make sure we have at least enough data for the network layer + * header. + */ + if (IP_V(ip) == 4) + hlen = IP_HL(ip) << 2; +#ifdef USE_INET6 + else if (IP_V(ip) == 6) + hlen = sizeof(ip6_t); +#endif + else + goto cantdecaps2; + + if (fin->fin_plen < hlen) + goto cantdecaps2; + + fin->fin_dp = (char *)ip + hlen; + + if (IP_V(ip) == 4) { + /* + * Perform IPv4 header checksum validation. + */ + if (ipf_cksum((u_short *)ip, hlen)) + goto cantdecaps2; + } + + if (ipf_makefrip(hlen, ip, fin) == -1) { +cantdecaps2: + if (m != NULL) { +#if defined(MENTAT) && defined(_KERNEL) + m->b_rptr -= elen; +#else + m->m_data -= elen; + m->m_len += elen; #endif + } +cantdecaps: + DT1(frb_decapfrip, fr_info_t *, fin); + pass &= ~FR_CMDMASK; + pass |= FR_BLOCK|FR_QUICK; + fin->fin_reason = FRB_DECAPFRIP; + return -1; + } + + pass = ipf_scanlist(fin, pass); + + /* + * Copy the packet filter "result" fields out of the fr_info_t struct + * that is local to the decapsulation processing and back into the + * one we were called with. + */ + fino->fin_flx = fin->fin_flx; + fino->fin_rev = fin->fin_rev; + fino->fin_icode = fin->fin_icode; + fino->fin_rule = fin->fin_rule; + (void) strncpy(fino->fin_group, fin->fin_group, FR_GROUPLEN); + fino->fin_fr = fin->fin_fr; + fino->fin_error = fin->fin_error; + fino->fin_mp = fin->fin_mp; + fino->fin_m = fin->fin_m; + m = fin->fin_m; + if (m != NULL) { +#if defined(MENTAT) && defined(_KERNEL) + m->b_rptr -= elen; +#else + m->m_data -= elen; + m->m_len += elen; +#endif + } + return pass; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_matcharray_load */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* data(I) - pointer to ioctl data */ +/* objp(I) - ipfobj_t structure to load data into */ +/* arrayptr(I) - pointer to location to store array pointer */ +/* */ +/* This function loads in a mathing array through the ipfobj_t struct that */ +/* describes it. Sanity checking and array size limitations are enforced */ +/* in this function to prevent userspace from trying to load in something */ +/* that is insanely big. Once the size of the array is known, the memory */ +/* required is malloc'd and returned through changing *arrayptr. The */ +/* contents of the array are verified before returning. Only in the event */ +/* of a successful call is the caller required to free up the malloc area. */ +/* ------------------------------------------------------------------------ */ +int +ipf_matcharray_load(softc, data, objp, arrayptr) + ipf_main_softc_t *softc; + caddr_t data; + ipfobj_t *objp; + int **arrayptr; +{ + int arraysize, *array, error; + + *arrayptr = NULL; + + error = BCOPYIN(data, objp, sizeof(*objp)); + if (error != 0) { + IPFERROR(116); + return EFAULT; + } + + if (objp->ipfo_type != IPFOBJ_IPFEXPR) { + IPFERROR(117); + return EINVAL; + } + + if (((objp->ipfo_size & 3) != 0) || (objp->ipfo_size == 0) || + (objp->ipfo_size > 1024)) { + IPFERROR(118); + return EINVAL; + } + + arraysize = objp->ipfo_size * sizeof(*array); + KMALLOCS(array, int *, arraysize); + if (array == NULL) { + IPFERROR(119); + return ENOMEM; + } + + error = COPYIN(objp->ipfo_ptr, array, arraysize); + if (error != 0) { + KFREES(array, arraysize); + IPFERROR(120); + return EFAULT; + } + + if (ipf_matcharray_verify(array, arraysize) != 0) { + KFREES(array, arraysize); + IPFERROR(121); + return EINVAL; + } + + *arrayptr = array; return 0; } /* ------------------------------------------------------------------------ */ -/* Function: fr_deinitialise */ -/* Returns: None. */ -/* Parameters: None. */ +/* Function: ipf_matcharray_verify */ +/* Returns: Nil */ +/* Parameters: array(I) - pointer to matching array */ +/* arraysize(I) - number of elements in the array */ /* */ -/* Call all the various subsystem cleanup routines to deallocate memory or */ -/* destroy locks or whatever they've done that they need to now undo. */ -/* The order here IS important as there are some cross references of */ -/* internal data structures. */ +/* Verify the contents of a matching array by stepping through each element */ +/* in it. The actual commands in the array are not verified for */ +/* correctness, only that all of the sizes are correctly within limits. */ /* ------------------------------------------------------------------------ */ -void fr_deinitialise() +int +ipf_matcharray_verify(array, arraysize) + int *array, arraysize; { - fr_fragunload(); - fr_authunload(); - fr_natunload(); - fr_stateunload(); -#ifdef IPFILTER_SCAN - fr_scanunload(); + int i, nelem, maxidx; + ipfexp_t *e; + + nelem = arraysize / sizeof(*array); + + /* + * Currently, it makes no sense to have an array less than 6 + * elements long - the initial size at the from, a single operation + * (minimum 4 in length) and a trailer, for a total of 6. + */ + if ((array[0] < 6) || (arraysize < 24) || (arraysize > 4096)) { + return -1; + } + + /* + * Verify the size of data pointed to by array with how long + * the array claims to be itself. + */ + if (array[0] * sizeof(*array) != arraysize) { + return -1; + } + + maxidx = nelem - 1; + /* + * The last opcode in this array should be an IPF_EXP_END. + */ + if (array[maxidx] != IPF_EXP_END) { + return -1; + } + + for (i = 1; i < maxidx; ) { + e = (ipfexp_t *)(array + i); + + /* + * The length of the bits to check must be at least 1 + * (or else there is nothing to comapre with!) and it + * cannot exceed the length of the data present. + */ + if ((e->ipfe_size < 1 ) || + (e->ipfe_size + i > maxidx)) { + return -1; + } + i += e->ipfe_size; + } + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_fr_matcharray */ +/* Returns: int - 0 = match failed, else positive match */ +/* Parameters: fin(I) - pointer to packet information */ +/* array(I) - pointer to matching array */ +/* */ +/* This function is used to apply a matching array against a packet and */ +/* return an indication of whether or not the packet successfully matches */ +/* all of the commands in it. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_fr_matcharray(fin, array) + fr_info_t *fin; + int *array; +{ + int i, n, *x, rv, p; + ipfexp_t *e; + + rv = 0; + n = array[0]; + x = array + 1; + + for (; n > 0; x += 3 + x[3], rv = 0) { + e = (ipfexp_t *)x; + if (e->ipfe_cmd == IPF_EXP_END) + break; + n -= e->ipfe_size; + + /* + * The upper 16 bits currently store the protocol value. + * This is currently used with TCP and UDP port compares and + * allows "tcp.port = 80" without requiring an explicit + " "ip.pr = tcp" first. + */ + p = e->ipfe_cmd >> 16; + if ((p != 0) && (p != fin->fin_p)) + break; + + switch (e->ipfe_cmd) + { + case IPF_EXP_IP_PR : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (fin->fin_p == e->ipfe_arg0[i]); + } + break; + + case IPF_EXP_IP_SRCADDR : + if (fin->fin_v != 4) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= ((fin->fin_saddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]); + } + break; + + case IPF_EXP_IP_DSTADDR : + if (fin->fin_v != 4) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= ((fin->fin_daddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]); + } + break; + + case IPF_EXP_IP_ADDR : + if (fin->fin_v != 4) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= ((fin->fin_saddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]) || + ((fin->fin_daddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]); + } + break; + +#ifdef USE_INET6 + case IPF_EXP_IP6_SRCADDR : + if (fin->fin_v != 6) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= IP6_MASKEQ(&fin->fin_src6, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]); + } + break; + + case IPF_EXP_IP6_DSTADDR : + if (fin->fin_v != 6) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= IP6_MASKEQ(&fin->fin_dst6, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]); + } + break; + + case IPF_EXP_IP6_ADDR : + if (fin->fin_v != 6) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= IP6_MASKEQ(&fin->fin_src6, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]) || + IP6_MASKEQ(&fin->fin_dst6, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]); + } + break; #endif - appr_unload(); -#ifdef IPFILTER_COMPILED - ipfrule_remove(); + case IPF_EXP_UDP_PORT : + case IPF_EXP_TCP_PORT : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (fin->fin_sport == e->ipfe_arg0[i]) || + (fin->fin_dport == e->ipfe_arg0[i]); + } + break; + + case IPF_EXP_UDP_SPORT : + case IPF_EXP_TCP_SPORT : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (fin->fin_sport == e->ipfe_arg0[i]); + } + break; + + case IPF_EXP_UDP_DPORT : + case IPF_EXP_TCP_DPORT : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (fin->fin_dport == e->ipfe_arg0[i]); + } + break; + + case IPF_EXP_TCP_FLAGS : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= ((fin->fin_tcpf & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]); + } + break; + } + rv ^= e->ipfe_not; + + if (rv == 0) + break; + } + + return rv; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_queueflush */ +/* Returns: int - number of entries flushed (0 = none) */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* deletefn(I) - function to call to delete entry */ +/* ipfqs(I) - top of the list of ipf internal queues */ +/* userqs(I) - top of the list of user defined timeouts */ +/* */ +/* This fucntion gets called when the state/NAT hash tables fill up and we */ +/* need to try a bit harder to free up some space. The algorithm used here */ +/* split into two parts but both halves have the same goal: to reduce the */ +/* number of connections considered to be "active" to the low watermark. */ +/* There are two steps in doing this: */ +/* 1) Remove any TCP connections that are already considered to be "closed" */ +/* but have not yet been removed from the state table. The two states */ +/* TCPS_TIME_WAIT and TCPS_CLOSED are considered to be the perfect */ +/* candidates for this style of removal. If freeing up entries in */ +/* CLOSED or both CLOSED and TIME_WAIT brings us to the low watermark, */ +/* we do not go on to step 2. */ +/* */ +/* 2) Look for the oldest entries on each timeout queue and free them if */ +/* they are within the given window we are considering. Where the */ +/* window starts and the steps taken to increase its size depend upon */ +/* how long ipf has been running (ipf_ticks.) Anything modified in the */ +/* last 30 seconds is not touched. */ +/* touched */ +/* die ipf_ticks 30*1.5 1800*1.5 | 43200*1.5 */ +/* | | | | | | */ +/* future <--+----------+--------+-----------+-----+-----+-----------> past */ +/* now \_int=30s_/ \_int=1hr_/ \_int=12hr */ +/* */ +/* Points to note: */ +/* - tqe_die is the time, in the future, when entries die. */ +/* - tqe_die - ipf_ticks is how long left the connection has to live in ipf */ +/* ticks. */ +/* - tqe_touched is when the entry was last used by NAT/state */ +/* - the closer tqe_touched is to ipf_ticks, the further tqe_die will be */ +/* ipf_ticks any given timeout queue and vice versa. */ +/* - both tqe_die and tqe_touched increase over time */ +/* - timeout queues are sorted with the highest value of tqe_die at the */ +/* bottom and therefore the smallest values of each are at the top */ +/* - the pointer passed in as ipfqs should point to an array of timeout */ +/* queues representing each of the TCP states */ +/* */ +/* We start by setting up a maximum range to scan for things to move of */ +/* iend (newest) to istart (oldest) in chunks of "interval". If nothing is */ +/* found in that range, "interval" is adjusted (so long as it isn't 30) and */ +/* we start again with a new value for "iend" and "istart". This is */ +/* continued until we either finish the scan of 30 second intervals or the */ +/* low water mark is reached. */ +/* ------------------------------------------------------------------------ */ +int +ipf_queueflush(softc, deletefn, ipfqs, userqs, activep, size, low) + ipf_main_softc_t *softc; + ipftq_delete_fn_t deletefn; + ipftq_t *ipfqs, *userqs; + u_int *activep; + int size, low; +{ + u_long interval, istart, iend; + ipftq_t *ifq, *ifqnext; + ipftqent_t *tqe, *tqn; + int removed = 0; + + for (tqn = ipfqs[IPF_TCPS_CLOSED].ifq_head; ((tqe = tqn) != NULL); ) { + tqn = tqe->tqe_next; + if ((*deletefn)(softc, tqe->tqe_parent) == 0) + removed++; + } + if ((*activep * 100 / size) > low) { + for (tqn = ipfqs[IPF_TCPS_TIME_WAIT].ifq_head; + ((tqe = tqn) != NULL); ) { + tqn = tqe->tqe_next; + if ((*deletefn)(softc, tqe->tqe_parent) == 0) + removed++; + } + } + + if ((*activep * 100 / size) <= low) { + return removed; + } + + /* + * NOTE: Use of "* 15 / 10" is required here because if "* 1.5" is + * used then the operations are upgraded to floating point + * and kernels don't like floating point... + */ + if (softc->ipf_ticks > IPF_TTLVAL(43200 * 15 / 10)) { + istart = IPF_TTLVAL(86400 * 4); + interval = IPF_TTLVAL(43200); + } else if (softc->ipf_ticks > IPF_TTLVAL(1800 * 15 / 10)) { + istart = IPF_TTLVAL(43200); + interval = IPF_TTLVAL(1800); + } else if (softc->ipf_ticks > IPF_TTLVAL(30 * 15 / 10)) { + istart = IPF_TTLVAL(1800); + interval = IPF_TTLVAL(30); + } else { + return 0; + } + if (istart > softc->ipf_ticks) { + if (softc->ipf_ticks - interval < interval) + istart = interval; + else + istart = (softc->ipf_ticks / interval) * interval; + } + + iend = softc->ipf_ticks - interval; + + while ((*activep * 100 / size) > low) { + u_long try; + + try = softc->ipf_ticks - istart; + + for (ifq = ipfqs; ifq != NULL; ifq = ifq->ifq_next) { + for (tqn = ifq->ifq_head; ((tqe = tqn) != NULL); ) { + if (try < tqe->tqe_touched) + break; + tqn = tqe->tqe_next; + if ((*deletefn)(softc, tqe->tqe_parent) == 0) + removed++; + } + } + + for (ifq = userqs; ifq != NULL; ifq = ifqnext) { + ifqnext = ifq->ifq_next; + + for (tqn = ifq->ifq_head; ((tqe = tqn) != NULL); ) { + if (try < tqe->tqe_touched) + break; + tqn = tqe->tqe_next; + if ((*deletefn)(softc, tqe->tqe_parent) == 0) + removed++; + } + } + + if (try >= iend) { + if (interval == IPF_TTLVAL(43200)) { + interval = IPF_TTLVAL(1800); + } else if (interval == IPF_TTLVAL(1800)) { + interval = IPF_TTLVAL(30); + } else { + break; + } + if (interval >= softc->ipf_ticks) + break; + + iend = softc->ipf_ticks - interval; + } + istart -= interval; + } + + return removed; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_deliverlocal */ +/* Returns: int - 1 = local address, 0 = non-local address */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* ipversion(I) - IP protocol version (4 or 6) */ +/* ifp(I) - network interface pointer */ +/* ipaddr(I) - IPv4/6 destination address */ +/* */ +/* This fucntion is used to determine in the address "ipaddr" belongs to */ +/* the network interface represented by ifp. */ +/* ------------------------------------------------------------------------ */ +int +ipf_deliverlocal(softc, ipversion, ifp, ipaddr) + ipf_main_softc_t *softc; + int ipversion; + void *ifp; + i6addr_t *ipaddr; +{ + i6addr_t addr; + int islocal = 0; + + if (ipversion == 4) { + if (ipf_ifpaddr(softc, 4, FRI_NORMAL, ifp, &addr, NULL) == 0) { + if (addr.in4.s_addr == ipaddr->in4.s_addr) + islocal = 1; + } + +#ifdef USE_INET6 + } else if (ipversion == 6) { + if (ipf_ifpaddr(softc, 6, FRI_NORMAL, ifp, &addr, NULL) == 0) { + if (IP6_EQ(&addr, ipaddr)) + islocal = 1; + } +#endif + } + + return islocal; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_settimeout */ +/* Returns: int - 0 = success, -1 = failure */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* t(I) - pointer to tuneable array entry */ +/* p(I) - pointer to values passed in to apply */ +/* */ +/* This function is called to set the timeout values for each distinct */ +/* queue timeout that is available. When called, it calls into both the */ +/* state and NAT code, telling them to update their timeout queues. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_settimeout(softc, t, p) + struct ipf_main_softc_s *softc; + ipftuneable_t *t; + ipftuneval_t *p; +{ + + /* + * ipf_interror should be set by the functions called here, not + * by this function - it's just a middle man. + */ + if (ipf_state_settimeout(softc, t, p) == -1) + return -1; + if (ipf_nat_settimeout(softc, t, p) == -1) + return -1; + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_apply_timeout */ +/* Returns: int - 0 = success, -1 = failure */ +/* Parameters: head(I) - pointer to tuneable array entry */ +/* seconds(I) - pointer to values passed in to apply */ +/* */ +/* This function applies a timeout of "seconds" to the timeout queue that */ +/* is pointed to by "head". All entries on this list have an expiration */ +/* set to be the current tick value of ipf plus the ttl. Given that this */ +/* function should only be called when the delta is non-zero, the task is */ +/* to walk the entire list and apply the change. The sort order will not */ +/* change. The only catch is that this is O(n) across the list, so if the */ +/* queue has lots of entries (10s of thousands or 100s of thousands), it */ +/* could take a relatively long time to work through them all. */ +/* ------------------------------------------------------------------------ */ +void +ipf_apply_timeout(head, seconds) + ipftq_t *head; + u_int seconds; +{ + u_int oldtimeout, newtimeout; + ipftqent_t *tqe; + int delta; + + MUTEX_ENTER(&head->ifq_lock); + oldtimeout = head->ifq_ttl; + newtimeout = IPF_TTLVAL(seconds); + delta = oldtimeout - newtimeout; + + head->ifq_ttl = newtimeout; + + for (tqe = head->ifq_head; tqe != NULL; tqe = tqe->tqe_next) { + tqe->tqe_die += delta; + } + MUTEX_EXIT(&head->ifq_lock); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_settimeout_tcp */ +/* Returns: int - 0 = successfully applied, -1 = failed */ +/* Parameters: t(I) - pointer to tuneable to change */ +/* p(I) - pointer to new timeout information */ +/* tab(I) - pointer to table of TCP queues */ +/* */ +/* This function applies the new timeout (p) to the TCP tunable (t) and */ +/* updates all of the entries on the relevant timeout queue by calling */ +/* ipf_apply_timeout(). */ +/* ------------------------------------------------------------------------ */ +int +ipf_settimeout_tcp(t, p, tab) + ipftuneable_t *t; + ipftuneval_t *p; + ipftq_t *tab; +{ + if (!strcmp(t->ipft_name, "tcp_idle_timeout") || + !strcmp(t->ipft_name, "tcp_established")) { + ipf_apply_timeout(&tab[IPF_TCPS_ESTABLISHED], p->ipftu_int); + } else if (!strcmp(t->ipft_name, "tcp_close_wait")) { + ipf_apply_timeout(&tab[IPF_TCPS_CLOSE_WAIT], p->ipftu_int); + } else if (!strcmp(t->ipft_name, "tcp_last_ack")) { + ipf_apply_timeout(&tab[IPF_TCPS_LAST_ACK], p->ipftu_int); + } else if (!strcmp(t->ipft_name, "tcp_timeout")) { + ipf_apply_timeout(&tab[IPF_TCPS_LISTEN], p->ipftu_int); + ipf_apply_timeout(&tab[IPF_TCPS_HALF_ESTAB], p->ipftu_int); + ipf_apply_timeout(&tab[IPF_TCPS_CLOSING], p->ipftu_int); + } else if (!strcmp(t->ipft_name, "tcp_listen")) { + ipf_apply_timeout(&tab[IPF_TCPS_LISTEN], p->ipftu_int); + } else if (!strcmp(t->ipft_name, "tcp_half_established")) { + ipf_apply_timeout(&tab[IPF_TCPS_HALF_ESTAB], p->ipftu_int); + } else if (!strcmp(t->ipft_name, "tcp_closing")) { + ipf_apply_timeout(&tab[IPF_TCPS_CLOSING], p->ipftu_int); + } else if (!strcmp(t->ipft_name, "tcp_syn_received")) { + ipf_apply_timeout(&tab[IPF_TCPS_SYN_RECEIVED], p->ipftu_int); + } else if (!strcmp(t->ipft_name, "tcp_syn_sent")) { + ipf_apply_timeout(&tab[IPF_TCPS_SYN_SENT], p->ipftu_int); + } else if (!strcmp(t->ipft_name, "tcp_closed")) { + ipf_apply_timeout(&tab[IPF_TCPS_CLOSED], p->ipftu_int); + } else if (!strcmp(t->ipft_name, "tcp_half_closed")) { + ipf_apply_timeout(&tab[IPF_TCPS_CLOSED], p->ipftu_int); + } else if (!strcmp(t->ipft_name, "tcp_time_wait")) { + ipf_apply_timeout(&tab[IPF_TCPS_TIME_WAIT], p->ipftu_int); + } else { + /* + * ipf_interror isn't set here because it should be set + * by whatever called this function. + */ + return -1; + } + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_main_soft_create */ +/* Returns: NULL = failure, else success */ +/* Parameters: arg(I) - pointer to soft context structure if already allocd */ +/* */ +/* Create the foundation soft context structure. In circumstances where it */ +/* is not required to dynamically allocate the context, a pointer can be */ +/* passed in (rather than NULL) to a structure to be initialised. */ +/* The main thing of interest is that a number of locks are initialised */ +/* here instead of in the where might be expected - in the relevant create */ +/* function elsewhere. This is done because the current locking design has */ +/* some areas where these locks are used outside of their module. */ +/* Possibly the most important exercise that is done here is setting of all */ +/* the timeout values, allowing them to be changed before init(). */ +/* ------------------------------------------------------------------------ */ +void * +ipf_main_soft_create(arg) + void *arg; +{ + ipf_main_softc_t *softc; + + if (arg == NULL) { + KMALLOC(softc, ipf_main_softc_t *); + if (softc == NULL) + return NULL; + } else { + softc = arg; + } + + bzero((char *)softc, sizeof(*softc)); + + /* + * This serves as a flag as to whether or not the softc should be + * free'd when _destroy is called. + */ + softc->ipf_dynamic_softc = (arg == NULL) ? 1 : 0; + + softc->ipf_tuners = ipf_tune_array_copy(softc, + sizeof(ipf_main_tuneables), + ipf_main_tuneables); + if (softc->ipf_tuners == NULL) { + ipf_main_soft_destroy(softc); + return NULL; + } + + MUTEX_INIT(&softc->ipf_rw, "ipf rw mutex"); + MUTEX_INIT(&softc->ipf_timeoutlock, "ipf timeout lock"); + RWLOCK_INIT(&softc->ipf_global, "ipf filter load/unload mutex"); + RWLOCK_INIT(&softc->ipf_mutex, "ipf filter rwlock"); + RWLOCK_INIT(&softc->ipf_tokens, "ipf token rwlock"); + RWLOCK_INIT(&softc->ipf_state, "ipf state rwlock"); + RWLOCK_INIT(&softc->ipf_nat, "ipf IP NAT rwlock"); + RWLOCK_INIT(&softc->ipf_poolrw, "ipf pool rwlock"); + RWLOCK_INIT(&softc->ipf_frag, "ipf frag rwlock"); + + softc->ipf_token_head = NULL; + softc->ipf_token_tail = &softc->ipf_token_head; + + softc->ipf_tcpidletimeout = FIVE_DAYS; + softc->ipf_tcpclosewait = IPF_TTLVAL(2 * TCP_MSL); + softc->ipf_tcplastack = IPF_TTLVAL(30); + softc->ipf_tcptimewait = IPF_TTLVAL(2 * TCP_MSL); + softc->ipf_tcptimeout = IPF_TTLVAL(2 * TCP_MSL); + softc->ipf_tcpsynsent = IPF_TTLVAL(2 * TCP_MSL); + softc->ipf_tcpsynrecv = IPF_TTLVAL(2 * TCP_MSL); + softc->ipf_tcpclosed = IPF_TTLVAL(30); + softc->ipf_tcphalfclosed = IPF_TTLVAL(2 * 3600); + softc->ipf_udptimeout = IPF_TTLVAL(120); + softc->ipf_udpacktimeout = IPF_TTLVAL(12); + softc->ipf_icmptimeout = IPF_TTLVAL(60); + softc->ipf_icmpacktimeout = IPF_TTLVAL(6); + softc->ipf_iptimeout = IPF_TTLVAL(60); + +#if defined(IPFILTER_DEFAULT_BLOCK) + softc->ipf_pass = FR_BLOCK|FR_NOMATCH; +#else + softc->ipf_pass = (IPF_DEFAULT_PASS)|FR_NOMATCH; +#endif + softc->ipf_minttl = 4; + softc->ipf_icmpminfragmtu = 68; + softc->ipf_flags = IPF_LOGGING; + + return softc; +} + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_main_soft_init */ +/* Returns: 0 = success, -1 = failure */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* */ +/* A null-op function that exists as a placeholder so that the flow in */ +/* other functions is obvious. */ +/* ------------------------------------------------------------------------ */ +/*ARGSUSED*/ +int +ipf_main_soft_init(softc) + ipf_main_softc_t *softc; +{ + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_main_soft_destroy */ +/* Returns: void */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* */ +/* Undo everything that we did in ipf_main_soft_create. */ +/* */ +/* The most important check that needs to be made here is whether or not */ +/* the structure was allocated by ipf_main_soft_create() by checking what */ +/* value is stored in ipf_dynamic_main. */ +/* ------------------------------------------------------------------------ */ +/*ARGSUSED*/ +void +ipf_main_soft_destroy(softc) + ipf_main_softc_t *softc; +{ + + RW_DESTROY(&softc->ipf_frag); + RW_DESTROY(&softc->ipf_poolrw); + RW_DESTROY(&softc->ipf_nat); + RW_DESTROY(&softc->ipf_state); + RW_DESTROY(&softc->ipf_tokens); + RW_DESTROY(&softc->ipf_mutex); + RW_DESTROY(&softc->ipf_global); + MUTEX_DESTROY(&softc->ipf_timeoutlock); + MUTEX_DESTROY(&softc->ipf_rw); + + if (softc->ipf_tuners != NULL) { + KFREES(softc->ipf_tuners, sizeof(ipf_main_tuneables)); + } + if (softc->ipf_dynamic_softc == 1) { + KFREE(softc); + } +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_main_soft_fini */ +/* Returns: 0 = success, -1 = failure */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* */ +/* Clean out the rules which have been added since _init was last called, */ +/* the only dynamic part of the mainline. */ +/* ------------------------------------------------------------------------ */ +int +ipf_main_soft_fini(softc) + ipf_main_softc_t *softc; +{ + (void) ipf_flush(softc, IPL_LOGIPF, FR_INQUE|FR_OUTQUE|FR_INACTIVE); + (void) ipf_flush(softc, IPL_LOGIPF, FR_INQUE|FR_OUTQUE); + (void) ipf_flush(softc, IPL_LOGCOUNT, FR_INQUE|FR_OUTQUE|FR_INACTIVE); + (void) ipf_flush(softc, IPL_LOGCOUNT, FR_INQUE|FR_OUTQUE); + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_main_load */ +/* Returns: 0 = success, -1 = failure */ +/* Parameters: none */ +/* */ +/* Handle global initialisation that needs to be done for the base part of */ +/* IPFilter. At present this just amounts to initialising some ICMP lookup */ +/* arrays that get used by the state/NAT code. */ +/* ------------------------------------------------------------------------ */ +int +ipf_main_load() +{ + int i; + + /* fill icmp reply type table */ + for (i = 0; i <= ICMP_MAXTYPE; i++) + icmpreplytype4[i] = -1; + icmpreplytype4[ICMP_ECHO] = ICMP_ECHOREPLY; + icmpreplytype4[ICMP_TSTAMP] = ICMP_TSTAMPREPLY; + icmpreplytype4[ICMP_IREQ] = ICMP_IREQREPLY; + icmpreplytype4[ICMP_MASKREQ] = ICMP_MASKREPLY; + +#ifdef USE_INET6 + /* fill icmp reply type table */ + for (i = 0; i <= ICMP6_MAXTYPE; i++) + icmpreplytype6[i] = -1; + icmpreplytype6[ICMP6_ECHO_REQUEST] = ICMP6_ECHO_REPLY; + icmpreplytype6[ICMP6_MEMBERSHIP_QUERY] = ICMP6_MEMBERSHIP_REPORT; + icmpreplytype6[ICMP6_NI_QUERY] = ICMP6_NI_REPLY; + icmpreplytype6[ND_ROUTER_SOLICIT] = ND_ROUTER_ADVERT; + icmpreplytype6[ND_NEIGHBOR_SOLICIT] = ND_NEIGHBOR_ADVERT; +#endif + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_main_unload */ +/* Returns: 0 = success, -1 = failure */ +/* Parameters: none */ +/* */ +/* A null-op function that exists as a placeholder so that the flow in */ +/* other functions is obvious. */ +/* ------------------------------------------------------------------------ */ +int +ipf_main_unload() +{ + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_load_all */ +/* Returns: 0 = success, -1 = failure */ +/* Parameters: none */ +/* */ +/* Work through all of the subsystems inside IPFilter and call the load */ +/* function for each in an order that won't lead to a crash :) */ +/* ------------------------------------------------------------------------ */ +int +ipf_load_all() +{ + if (ipf_main_load() == -1) + return -1; + + if (ipf_state_main_load() == -1) + return -1; + + if (ipf_nat_main_load() == -1) + return -1; + + if (ipf_frag_main_load() == -1) + return -1; + + if (ipf_auth_main_load() == -1) + return -1; + + if (ipf_proxy_main_load() == -1) + return -1; + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_unload_all */ +/* Returns: 0 = success, -1 = failure */ +/* Parameters: none */ +/* */ +/* Work through all of the subsystems inside IPFilter and call the unload */ +/* function for each in an order that won't lead to a crash :) */ +/* ------------------------------------------------------------------------ */ +int +ipf_unload_all() +{ + if (ipf_proxy_main_unload() == -1) + return -1; + + if (ipf_auth_main_unload() == -1) + return -1; + + if (ipf_frag_main_unload() == -1) + return -1; + + if (ipf_nat_main_unload() == -1) + return -1; + + if (ipf_state_main_unload() == -1) + return -1; + + if (ipf_main_unload() == -1) + return -1; + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_create_all */ +/* Returns: NULL = failure, else success */ +/* Parameters: arg(I) - pointer to soft context main structure */ +/* */ +/* Work through all of the subsystems inside IPFilter and call the create */ +/* function for each in an order that won't lead to a crash :) */ +/* ------------------------------------------------------------------------ */ +ipf_main_softc_t * +ipf_create_all(arg) + void *arg; +{ + ipf_main_softc_t *softc; + + softc = ipf_main_soft_create(arg); + if (softc == NULL) + return NULL; + +#ifdef IPFILTER_LOG + softc->ipf_log_soft = ipf_log_soft_create(softc); + if (softc->ipf_log_soft == NULL) { + ipf_destroy_all(softc); + return NULL; + } #endif - (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE|FR_INACTIVE); - (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE); - (void) frflush(IPL_LOGCOUNT, 0, FR_INQUE|FR_OUTQUE|FR_INACTIVE); - (void) frflush(IPL_LOGCOUNT, 0, FR_INQUE|FR_OUTQUE); + softc->ipf_lookup_soft = ipf_lookup_soft_create(softc); + if (softc->ipf_lookup_soft == NULL) { + ipf_destroy_all(softc); + return NULL; + } + + softc->ipf_sync_soft = ipf_sync_soft_create(softc); + if (softc->ipf_sync_soft == NULL) { + ipf_destroy_all(softc); + return NULL; + } + + softc->ipf_state_soft = ipf_state_soft_create(softc); + if (softc->ipf_state_soft == NULL) { + ipf_destroy_all(softc); + return NULL; + } + + softc->ipf_nat_soft = ipf_nat_soft_create(softc); + if (softc->ipf_nat_soft == NULL) { + ipf_destroy_all(softc); + return NULL; + } + + softc->ipf_frag_soft = ipf_frag_soft_create(softc); + if (softc->ipf_frag_soft == NULL) { + ipf_destroy_all(softc); + return NULL; + } + + softc->ipf_auth_soft = ipf_auth_soft_create(softc); + if (softc->ipf_auth_soft == NULL) { + ipf_destroy_all(softc); + return NULL; + } + + softc->ipf_proxy_soft = ipf_proxy_soft_create(softc); + if (softc->ipf_proxy_soft == NULL) { + ipf_destroy_all(softc); + return NULL; + } + + return softc; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_destroy_all */ +/* Returns: void */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* */ +/* Work through all of the subsystems inside IPFilter and call the destroy */ +/* function for each in an order that won't lead to a crash :) */ +/* */ +/* Every one of these functions is expected to succeed, so there is no */ +/* checking of return values. */ +/* ------------------------------------------------------------------------ */ +void +ipf_destroy_all(softc) + ipf_main_softc_t *softc; +{ + + if (softc->ipf_state_soft != NULL) { + ipf_state_soft_destroy(softc, softc->ipf_state_soft); + softc->ipf_state_soft = NULL; + } + + if (softc->ipf_nat_soft != NULL) { + ipf_nat_soft_destroy(softc, softc->ipf_nat_soft); + softc->ipf_nat_soft = NULL; + } + + if (softc->ipf_frag_soft != NULL) { + ipf_frag_soft_destroy(softc, softc->ipf_frag_soft); + softc->ipf_frag_soft = NULL; + } -#ifdef IPFILTER_LOOKUP - ip_lookup_unload(); + if (softc->ipf_auth_soft != NULL) { + ipf_auth_soft_destroy(softc, softc->ipf_auth_soft); + softc->ipf_auth_soft = NULL; + } + + if (softc->ipf_proxy_soft != NULL) { + ipf_proxy_soft_destroy(softc, softc->ipf_proxy_soft); + softc->ipf_proxy_soft = NULL; + } + + if (softc->ipf_sync_soft != NULL) { + ipf_sync_soft_destroy(softc, softc->ipf_sync_soft); + softc->ipf_sync_soft = NULL; + } + + if (softc->ipf_lookup_soft != NULL) { + ipf_lookup_soft_destroy(softc, softc->ipf_lookup_soft); + softc->ipf_lookup_soft = NULL; + } + +#ifdef IPFILTER_LOG + if (softc->ipf_log_soft != NULL) { + ipf_log_soft_destroy(softc, softc->ipf_log_soft); + softc->ipf_log_soft = NULL; + } #endif + ipf_main_soft_destroy(softc); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_init_all */ +/* Returns: 0 = success, -1 = failure */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* */ +/* Work through all of the subsystems inside IPFilter and call the init */ +/* function for each in an order that won't lead to a crash :) */ +/* ------------------------------------------------------------------------ */ +int +ipf_init_all(softc) + ipf_main_softc_t *softc; +{ + + if (ipf_main_soft_init(softc) == -1) + return -1; + #ifdef IPFILTER_LOG - fr_logunload(); + if (ipf_log_soft_init(softc, softc->ipf_log_soft) == -1) + return -1; #endif + + if (ipf_lookup_soft_init(softc, softc->ipf_lookup_soft) == -1) + return -1; + + if (ipf_sync_soft_init(softc, softc->ipf_sync_soft) == -1) + return -1; + + if (ipf_state_soft_init(softc, softc->ipf_state_soft) == -1) + return -1; + + if (ipf_nat_soft_init(softc, softc->ipf_nat_soft) == -1) + return -1; + + if (ipf_frag_soft_init(softc, softc->ipf_frag_soft) == -1) + return -1; + + if (ipf_auth_soft_init(softc, softc->ipf_auth_soft) == -1) + return -1; + + if (ipf_proxy_soft_init(softc, softc->ipf_proxy_soft) == -1) + return -1; + + return 0; } /* ------------------------------------------------------------------------ */ -/* Function: fr_zerostats */ -/* Returns: int - 0 = success, else failure */ -/* Parameters: data(O) - pointer to pointer for copying data back to */ +/* Function: ipf_fini_all */ +/* Returns: 0 = success, -1 = failure */ +/* Parameters: softc(I) - pointer to soft context main structure */ /* */ -/* Copies the current statistics out to userspace and then zero's the */ -/* current ones in the kernel. The lock is only held across the bzero() as */ -/* the copyout may result in paging (ie network activity.) */ +/* Work through all of the subsystems inside IPFilter and call the fini */ +/* function for each in an order that won't lead to a crash :) */ /* ------------------------------------------------------------------------ */ -int fr_zerostats(data) -caddr_t data; +int +ipf_fini_all(softc) + ipf_main_softc_t *softc; { - friostat_t fio; - int error; - fr_getstat(&fio); - error = copyoutptr(&fio, data, sizeof(fio)); - if (error) - return EFAULT; + ipf_token_flush(softc); + + if (ipf_proxy_soft_fini(softc, softc->ipf_proxy_soft) == -1) + return -1; - WRITE_ENTER(&ipf_mutex); - bzero((char *)frstats, sizeof(*frstats) * 2); - RWLOCK_EXIT(&ipf_mutex); + if (ipf_auth_soft_fini(softc, softc->ipf_auth_soft) == -1) + return -1; + + if (ipf_frag_soft_fini(softc, softc->ipf_frag_soft) == -1) + return -1; + + if (ipf_nat_soft_fini(softc, softc->ipf_nat_soft) == -1) + return -1; + + if (ipf_state_soft_fini(softc, softc->ipf_state_soft) == -1) + return -1; + + if (ipf_sync_soft_fini(softc, softc->ipf_sync_soft) == -1) + return -1; + + if (ipf_lookup_soft_fini(softc, softc->ipf_lookup_soft) == -1) + return -1; + +#ifdef IPFILTER_LOG + if (ipf_log_soft_fini(softc, softc->ipf_log_soft) == -1) + return -1; +#endif + + if (ipf_main_soft_fini(softc) == -1) + return -1; return 0; } /* ------------------------------------------------------------------------ */ -/* Function: fr_resolvedest */ +/* Function: ipf_rule_expire */ /* Returns: Nil */ -/* Parameters: fdp(IO) - pointer to destination information to resolve */ -/* v(I) - IP protocol version to match */ +/* Parameters: softc(I) - pointer to soft context main structure */ /* */ -/* Looks up an interface name in the frdest structure pointed to by fdp and */ -/* if a matching name can be found for the particular IP protocol version */ -/* then store the interface pointer in the frdest struct. If no match is */ -/* found, then set the interface pointer to be -1 as NULL is considered to */ -/* indicate there is no information at all in the structure. */ +/* At present this function exists just to support temporary addition of */ +/* firewall rules. Both inactive and active lists are scanned for items to */ +/* purge, as by rights, the expiration is computed as soon as the rule is */ +/* loaded in. */ /* ------------------------------------------------------------------------ */ -void fr_resolvedest(fdp, v) -frdest_t *fdp; -int v; +void +ipf_rule_expire(softc) + ipf_main_softc_t *softc; { - void *ifp; + frentry_t *fr; - ifp = NULL; - v = v; /* LINT */ + if ((softc->ipf_rule_explist[0] == NULL) && + (softc->ipf_rule_explist[1] == NULL)) + return; + + WRITE_ENTER(&softc->ipf_mutex); + + while ((fr = softc->ipf_rule_explist[0]) != NULL) { + /* + * Because the list is kept sorted on insertion, the fist + * one that dies in the future means no more work to do. + */ + if (fr->fr_die > softc->ipf_ticks) + break; + ipf_rule_delete(softc, fr, IPL_LOGIPF, 0); + } - if (*fdp->fd_ifname != '\0') { - ifp = GETIFP(fdp->fd_ifname, v); - if (ifp == NULL) - ifp = (void *)-1; + while ((fr = softc->ipf_rule_explist[1]) != NULL) { + /* + * Because the list is kept sorted on insertion, the fist + * one that dies in the future means no more work to do. + */ + if (fr->fr_die > softc->ipf_ticks) + break; + ipf_rule_delete(softc, fr, IPL_LOGIPF, 1); } - fdp->fd_ifp = ifp; + + RWLOCK_EXIT(&softc->ipf_mutex); } +static int ipf_ht_node_cmp __P((struct host_node_s *, struct host_node_s *)); +static void ipf_ht_node_make_key __P((host_track_t *, host_node_t *, int, + i6addr_t *)); + +host_node_t RBI_ZERO(ipf_rb); +RBI_CODE(ipf_rb, host_node_t, hn_entry, ipf_ht_node_cmp) + + /* ------------------------------------------------------------------------ */ -/* Function: fr_icmp4errortype */ -/* Returns: int - 1 == success, 0 == failure */ -/* Parameters: icmptype(I) - ICMP type number */ +/* Function: ipf_ht_node_cmp */ +/* Returns: int - 0 == nodes are the same, .. */ +/* Parameters: k1(I) - pointer to first key to compare */ +/* k2(I) - pointer to second key to compare */ +/* */ +/* The "key" for the node is a combination of two fields: the address */ +/* family and the address itself. */ +/* */ +/* Because we're not actually interpreting the address data, it isn't */ +/* necessary to convert them to/from network/host byte order. The mask is */ +/* just used to remove bits that aren't significant - it doesn't matter */ +/* where they are, as long as they're always in the same place. */ /* */ -/* Tests to see if the ICMP type number passed is an error type or not. */ +/* As with IP6_EQ, comparing IPv6 addresses starts at the bottom because */ +/* this is where individual ones will differ the most - but not true for */ +/* for /48's, etc. */ /* ------------------------------------------------------------------------ */ -int fr_icmp4errortype(icmptype) -int icmptype; +static int +ipf_ht_node_cmp(k1, k2) + struct host_node_s *k1, *k2; { + int i; - switch (icmptype) - { - case ICMP_SOURCEQUENCH : - case ICMP_PARAMPROB : - case ICMP_REDIRECT : - case ICMP_TIMXCEED : - case ICMP_UNREACH : - return 1; - default: - return 0; + i = (k2->hn_addr.adf_family - k1->hn_addr.adf_family); + if (i != 0) + return i; + + if (k1->hn_addr.adf_family == AF_INET) + return (k2->hn_addr.adf_addr.in4.s_addr - + k1->hn_addr.adf_addr.in4.s_addr); + + i = k2->hn_addr.adf_addr.i6[3] - k1->hn_addr.adf_addr.i6[3]; + if (i != 0) + return i; + i = k2->hn_addr.adf_addr.i6[2] - k1->hn_addr.adf_addr.i6[2]; + if (i != 0) + return i; + i = k2->hn_addr.adf_addr.i6[1] - k1->hn_addr.adf_addr.i6[1]; + if (i != 0) + return i; + i = k2->hn_addr.adf_addr.i6[0] - k1->hn_addr.adf_addr.i6[0]; + return i; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_ht_node_make_key */ +/* Returns: Nil */ +/* parameters: htp(I) - pointer to address tracking structure */ +/* key(I) - where to store masked address for lookup */ +/* family(I) - protocol family of address */ +/* addr(I) - pointer to network address */ +/* */ +/* Using the "netmask" (number of bits) stored parent host tracking struct, */ +/* copy the address passed in into the key structure whilst masking out the */ +/* bits that we don't want. */ +/* */ +/* Because the parser will set ht_netmask to 128 if there is no protocol */ +/* specified (the parser doesn't know if it should be a v4 or v6 rule), we */ +/* have to be wary of that and not allow 32-128 to happen. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_ht_node_make_key(htp, key, family, addr) + host_track_t *htp; + host_node_t *key; + int family; + i6addr_t *addr; +{ + key->hn_addr.adf_family = family; + if (family == AF_INET) { + u_32_t mask; + int bits; + + key->hn_addr.adf_len = sizeof(key->hn_addr.adf_addr.in4); + bits = htp->ht_netmask; + if (bits >= 32) { + mask = 0xffffffff; + } else { + mask = htonl(0xffffffff << (32 - bits)); + } + key->hn_addr.adf_addr.in4.s_addr = addr->in4.s_addr & mask; +#ifdef USE_INET6 + } else { + int bits = htp->ht_netmask; + + key->hn_addr.adf_len = sizeof(key->hn_addr.adf_addr.in6); + if (bits > 96) { + key->hn_addr.adf_addr.i6[3] = addr->i6[3] & + htonl(0xffffffff << (128 - bits)); + key->hn_addr.adf_addr.i6[2] = addr->i6[2]; + key->hn_addr.adf_addr.i6[1] = addr->i6[2]; + key->hn_addr.adf_addr.i6[0] = addr->i6[2]; + } else if (bits > 64) { + key->hn_addr.adf_addr.i6[3] = 0; + key->hn_addr.adf_addr.i6[2] = addr->i6[2] & + htonl(0xffffffff << (96 - bits)); + key->hn_addr.adf_addr.i6[1] = addr->i6[1]; + key->hn_addr.adf_addr.i6[0] = addr->i6[0]; + } else if (bits > 32) { + key->hn_addr.adf_addr.i6[3] = 0; + key->hn_addr.adf_addr.i6[2] = 0; + key->hn_addr.adf_addr.i6[1] = addr->i6[1] & + htonl(0xffffffff << (64 - bits)); + key->hn_addr.adf_addr.i6[0] = addr->i6[0]; + } else { + key->hn_addr.adf_addr.i6[3] = 0; + key->hn_addr.adf_addr.i6[2] = 0; + key->hn_addr.adf_addr.i6[1] = 0; + key->hn_addr.adf_addr.i6[0] = addr->i6[0] & + htonl(0xffffffff << (32 - bits)); + } } +#endif } /* ------------------------------------------------------------------------ */ -/* Function: fr_resolvenic */ -/* Returns: void* - NULL = wildcard name, -1 = failed to find NIC, else */ -/* pointer to interface structure for NIC */ -/* Parameters: name(I) - complete interface name */ -/* v(I) - IP protocol version */ +/* Function: ipf_ht_node_add */ +/* Returns: int - 0 == success, -1 == failure */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* htp(I) - pointer to address tracking structure */ +/* family(I) - protocol family of address */ +/* addr(I) - pointer to network address */ /* */ -/* Look for a network interface structure that firstly has a matching name */ -/* to that passed in and that is also being used for that IP protocol */ -/* version (necessary on some platforms where there are separate listings */ -/* for both IPv4 and IPv6 on the same physical NIC. */ +/* NOTE: THIS FUNCTION MUST BE CALLED WITH AN EXCLUSIVE LOCK THAT PREVENTS */ +/* ipf_ht_node_del FROM RUNNING CONCURRENTLY ON THE SAME htp. */ +/* */ +/* After preparing the key with the address information to find, look in */ +/* the red-black tree to see if the address is known. A successful call to */ +/* this function can mean one of two things: a new node was added to the */ +/* tree or a matching node exists and we're able to bump up its activity. */ +/* ------------------------------------------------------------------------ */ +int +ipf_ht_node_add(softc, htp, family, addr) + ipf_main_softc_t *softc; + host_track_t *htp; + int family; + i6addr_t *addr; +{ + host_node_t *h; + host_node_t k; + + ipf_ht_node_make_key(htp, &k, family, addr); + + h = RBI_SEARCH(ipf_rb, &htp->ht_root, &k); + if (h == NULL) { + if (htp->ht_cur_nodes >= htp->ht_max_nodes) + return -1; + KMALLOC(h, host_node_t *); + if (h == NULL) { + DT(ipf_rb_no_mem); + LBUMP(ipf_rb_no_mem); + return -1; + } + + /* + * If there was a macro to initialise the RB node then that + * would get used here, but there isn't... + */ + bzero((char *)h, sizeof(*h)); + h->hn_addr = k.hn_addr; + h->hn_addr.adf_family = k.hn_addr.adf_family; + RBI_INSERT(ipf_rb, &htp->ht_root, h); + htp->ht_cur_nodes++; + } else { + if ((htp->ht_max_per_node != 0) && + (h->hn_active >= htp->ht_max_per_node)) { + DT(ipf_rb_node_max); + LBUMP(ipf_rb_node_max); + return -1; + } + } + + h->hn_active++; + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_ht_node_del */ +/* Returns: int - 0 == success, -1 == failure */ +/* parameters: htp(I) - pointer to address tracking structure */ +/* family(I) - protocol family of address */ +/* addr(I) - pointer to network address */ /* */ -/* One might wonder why name gets terminated with a \0 byte in here. The */ -/* reason is an interface name could get into the kernel structures of ipf */ -/* in any number of ways and so long as they all use the same sized array */ -/* to put the name in, it makes sense to ensure it gets null terminated */ -/* before it is used for its intended purpose - finding its match in the */ -/* kernel's list of configured interfaces. */ +/* NOTE: THIS FUNCTION MUST BE CALLED WITH AN EXCLUSIVE LOCK THAT PREVENTS */ +/* ipf_ht_node_add FROM RUNNING CONCURRENTLY ON THE SAME htp. */ /* */ -/* NOTE: This SHOULD ONLY be used with IPFilter structures that have an */ -/* array for the name that is LIFNAMSIZ bytes (at least) in length. */ +/* Try and find the address passed in amongst the leavese on this tree to */ +/* be friend. If found then drop the active account for that node drops by */ +/* one. If that count reaches 0, it is time to free it all up. */ /* ------------------------------------------------------------------------ */ -void *fr_resolvenic(name, v) -char *name; -int v; +int +ipf_ht_node_del(htp, family, addr) + host_track_t *htp; + int family; + i6addr_t *addr; { - void *nic; + host_node_t *h; + host_node_t k; - if (name[0] == '\0') - return NULL; + ipf_ht_node_make_key(htp, &k, family, addr); - if ((name[1] == '\0') && ((name[0] == '-') || (name[0] == '*'))) { - return NULL; + h = RBI_SEARCH(ipf_rb, &htp->ht_root, &k); + if (h == NULL) { + return -1; + } else { + h->hn_active--; + if (h->hn_active == 0) { + (void) RBI_DELETE(ipf_rb, &htp->ht_root, h); + htp->ht_cur_nodes--; + KFREE(h); + } } - name[LIFNAMSIZ - 1] = '\0'; + return 0; +} - nic = GETIFP(name, v); - if (nic == NULL) - nic = (void *)-1; - return nic; + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_rb_ht_init */ +/* Returns: Nil */ +/* Parameters: head(I) - pointer to host tracking structure */ +/* */ +/* Initialise the host tracking structure to be ready for use above. */ +/* ------------------------------------------------------------------------ */ +void +ipf_rb_ht_init(head) + host_track_t *head; +{ + RBI_INIT(ipf_rb, &head->ht_root); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_rb_ht_freenode */ +/* Returns: Nil */ +/* Parameters: head(I) - pointer to host tracking structure */ +/* arg(I) - additional argument from walk caller */ +/* */ +/* Free an actual host_node_t structure. */ +/* ------------------------------------------------------------------------ */ +void +ipf_rb_ht_freenode(node, arg) + host_node_t *node; + void *arg; +{ + KFREE(node); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_rb_ht_flush */ +/* Returns: Nil */ +/* Parameters: head(I) - pointer to host tracking structure */ +/* */ +/* Remove all of the nodes in the tree tracking hosts by calling a walker */ +/* and free'ing each one. */ +/* ------------------------------------------------------------------------ */ +void +ipf_rb_ht_flush(head) + host_track_t *head; +{ + RBI_WALK(ipf_rb, &head->ht_root, ipf_rb_ht_freenode, NULL); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_slowtimer */ +/* Returns: Nil */ +/* Parameters: ptr(I) - pointer to main ipf soft context structure */ +/* */ +/* Slowly expire held state for fragments. Timeouts are set * in */ +/* expectation of this being called twice per second. */ +/* ------------------------------------------------------------------------ */ +void +ipf_slowtimer(softc) + ipf_main_softc_t *softc; +{ + + ipf_token_expire(softc); + ipf_frag_expire(softc); + ipf_state_expire(softc); + ipf_nat_expire(softc); + ipf_auth_expire(softc); + ipf_lookup_expire(softc); + ipf_rule_expire(softc); + ipf_sync_expire(softc); + softc->ipf_ticks++; +# if defined(__OpenBSD__) + timeout_add(&ipf_slowtimer_ch, hz/2); +# endif +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_inet_mask_add */ +/* Returns: Nil */ +/* Parameters: bits(I) - pointer to nat context information */ +/* mtab(I) - pointer to mask hash table structure */ +/* */ +/* When called, bits represents the mask of a new NAT rule that has just */ +/* been added. This function inserts a bitmask into the array of masks to */ +/* search when searching for a matching NAT rule for a packet. */ +/* Prevention of duplicate masks is achieved by checking the use count for */ +/* a given netmask. */ +/* ------------------------------------------------------------------------ */ +void +ipf_inet_mask_add(bits, mtab) + int bits; + ipf_v4_masktab_t *mtab; +{ + u_32_t mask; + int i, j; + + mtab->imt4_masks[bits]++; + if (mtab->imt4_masks[bits] > 1) + return; + + if (bits == 0) + mask = 0; + else + mask = 0xffffffff << (32 - bits); + + for (i = 0; i < 33; i++) { + if (ntohl(mtab->imt4_active[i]) < mask) { + for (j = 32; j > i; j--) + mtab->imt4_active[j] = mtab->imt4_active[j - 1]; + mtab->imt4_active[i] = htonl(mask); + break; + } + } + mtab->imt4_max++; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_inet_mask_del */ +/* Returns: Nil */ +/* Parameters: bits(I) - number of bits set in the netmask */ +/* mtab(I) - pointer to mask hash table structure */ +/* */ +/* Remove the 32bit bitmask represented by "bits" from the collection of */ +/* netmasks stored inside of mtab. */ +/* ------------------------------------------------------------------------ */ +void +ipf_inet_mask_del(bits, mtab) + int bits; + ipf_v4_masktab_t *mtab; +{ + u_32_t mask; + int i, j; + + mtab->imt4_masks[bits]--; + if (mtab->imt4_masks[bits] > 0) + return; + + mask = htonl(0xffffffff << (32 - bits)); + for (i = 0; i < 33; i++) { + if (mtab->imt4_active[i] == mask) { + for (j = i + 1; j < 33; j++) + mtab->imt4_active[j - 1] = mtab->imt4_active[j]; + break; + } + } + mtab->imt4_max--; + ASSERT(mtab->imt4_max >= 0); +} + + +#ifdef USE_INET6 +/* ------------------------------------------------------------------------ */ +/* Function: ipf_inet6_mask_add */ +/* Returns: Nil */ +/* Parameters: bits(I) - number of bits set in mask */ +/* mask(I) - pointer to mask to add */ +/* mtab(I) - pointer to mask hash table structure */ +/* */ +/* When called, bitcount represents the mask of a IPv6 NAT map rule that */ +/* has just been added. This function inserts a bitmask into the array of */ +/* masks to search when searching for a matching NAT rule for a packet. */ +/* Prevention of duplicate masks is achieved by checking the use count for */ +/* a given netmask. */ +/* ------------------------------------------------------------------------ */ +void +ipf_inet6_mask_add(bits, mask, mtab) + int bits; + i6addr_t *mask; + ipf_v6_masktab_t *mtab; +{ + i6addr_t zero; + int i, j; + + mtab->imt6_masks[bits]++; + if (mtab->imt6_masks[bits] > 1) + return; + + if (bits == 0) { + mask = &zero; + zero.i6[0] = 0; + zero.i6[1] = 0; + zero.i6[2] = 0; + zero.i6[3] = 0; + } + + for (i = 0; i < 129; i++) { + if (IP6_LT(&mtab->imt6_active[i], mask)) { + for (j = 128; j > i; j--) + mtab->imt6_active[j] = mtab->imt6_active[j - 1]; + mtab->imt6_active[i] = *mask; + break; + } + } + mtab->imt6_max++; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_inet6_mask_del */ +/* Returns: Nil */ +/* Parameters: bits(I) - number of bits set in mask */ +/* mask(I) - pointer to mask to remove */ +/* mtab(I) - pointer to mask hash table structure */ +/* */ +/* Remove the 128bit bitmask represented by "bits" from the collection of */ +/* netmasks stored inside of mtab. */ +/* ------------------------------------------------------------------------ */ +void +ipf_inet6_mask_del(bits, mask, mtab) + int bits; + i6addr_t *mask; + ipf_v6_masktab_t *mtab; +{ + i6addr_t zero; + int i, j; + + mtab->imt6_masks[bits]--; + if (mtab->imt6_masks[bits] > 0) + return; + + if (bits == 0) + mask = &zero; + zero.i6[0] = 0; + zero.i6[1] = 0; + zero.i6[2] = 0; + zero.i6[3] = 0; + + for (i = 0; i < 129; i++) { + if (IP6_EQ(&mtab->imt6_active[i], mask)) { + for (j = i + 1; j < 129; j++) { + mtab->imt6_active[j - 1] = mtab->imt6_active[j]; + if (IP6_EQ(&mtab->imt6_active[j - 1], &zero)) + break; + } + break; + } + } + mtab->imt6_max--; + ASSERT(mtab->imt6_max >= 0); } +#endif diff --git a/fils.c b/fils.c deleted file mode 100644 index e21af892a577b..0000000000000 --- a/fils.c +++ /dev/null @@ -1,1536 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - */ -#ifdef __FreeBSD__ -# ifndef __FreeBSD_cc_version -# include <osreldate.h> -# else -# if __FreeBSD_cc_version < 430000 -# include <osreldate.h> -# endif -# endif -#endif -#if defined(__sgi) && (IRIX > 602) -# include <sys/ptimers.h> -#endif -#include <stdio.h> -#include <string.h> -#if !defined(__SVR4) && !defined(__svr4__) -# include <strings.h> -#endif -#include <sys/types.h> -#include <sys/time.h> -#include <sys/param.h> -#include <sys/file.h> -#if defined(STATETOP) -# if defined(_BSDI_VERSION) -# undef STATETOP) -# endif -# if defined(__FreeBSD__) && \ - (!defined(__FreeBSD_version) || (__FreeBSD_version < 430000)) -# undef STATETOP -# endif -# if defined(__NetBSD_Version__) -# if (__NetBSD_Version__ < 105000000) -# undef STATETOP -# else -# include <poll.h> -# define USE_POLL -# endif -# endif -# if defined(sun) -# if defined(__svr4__) || defined(__SVR4) -# include <sys/select.h> -# else -# undef STATETOP /* NOT supported on SunOS4 */ -# endif -# endif -#endif -#include <stdlib.h> -#include <unistd.h> -#include <fcntl.h> -#include <stddef.h> -#include <nlist.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <net/if.h> -#if __FreeBSD_version >= 300000 -# include <net/if_var.h> -#endif -#include <netdb.h> -#include <arpa/nameser.h> -#include <resolv.h> -#include <netinet/tcp.h> -#if defined(STATETOP) && !defined(linux) -# include <netinet/ip_var.h> -# include <netinet/tcp_fsm.h> -#endif -#include "netinet/ip_compat.h" -#include "netinet/ip_fil.h" -#include "ipf.h" -#include "netinet/ip_nat.h" -#include "netinet/ip_frag.h" -#include "netinet/ip_state.h" -#include "netinet/ip_proxy.h" -#include "netinet/ip_auth.h" -#ifdef STATETOP -# include "netinet/ipl.h" -# include <ctype.h> -# if SOLARIS || defined(__NetBSD__) || defined(_BSDI_VERSION) || \ - defined(__sgi) -# ifdef ERR -# undef ERR -# endif -# include <curses.h> -# else /* SOLARIS */ -# include <ncurses.h> -# endif /* SOLARIS */ -#endif /* STATETOP */ -#include "kmem.h" -#if defined(__NetBSD__) || (__OpenBSD__) -# include <paths.h> -#endif - -#if !defined(lint) -static const char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: fils.c,v 2.21.2.45 2004/04/10 11:45:48 darrenr Exp $"; -#endif - -extern char *optarg; -extern int optind; - -#define PRINTF (void)printf -#define FPRINTF (void)fprintf -#define F_IN 0 -#define F_OUT 1 -#define F_ACIN 2 -#define F_ACOUT 3 -static char *filters[4] = { "ipfilter(in)", "ipfilter(out)", - "ipacct(in)", "ipacct(out)" }; - -int opts = 0; -int use_inet6 = 0; -int live_kernel = 1; -int state_fd = -1; -int auth_fd = -1; -int ipf_fd = -1; - -#ifdef STATETOP -#define STSTRSIZE 80 -#define STGROWSIZE 16 -#define HOSTNMLEN 40 - -#define STSORT_PR 0 -#define STSORT_PKTS 1 -#define STSORT_BYTES 2 -#define STSORT_TTL 3 -#define STSORT_SRCIP 4 -#define STSORT_DSTIP 5 -#define STSORT_MAX STSORT_DSTIP -#define STSORT_DEFAULT STSORT_BYTES - - -typedef struct statetop { - union i6addr st_src; - union i6addr st_dst; - u_short st_sport; - u_short st_dport; - u_char st_p; - u_char st_state[2]; - U_QUAD_T st_pkts; - U_QUAD_T st_bytes; - u_long st_age; -} statetop_t; -#endif - -extern int main __P((int, char *[])); -static void showstats __P((friostat_t *, u_32_t)); -static void showfrstates __P((ipfrstat_t *)); -static void showlist __P((friostat_t *)); -static void showipstates __P((ips_stat_t *)); -static void showauthstates __P((fr_authstat_t *)); -static void showgroups __P((friostat_t *)); -static void Usage __P((char *)); -static void printlist __P((frentry_t *)); -static void parse_ipportstr __P((const char *, struct in_addr *, int *)); -static int ipfstate_live __P((char *, friostat_t **, ips_stat_t **, - ipfrstat_t **, fr_authstat_t **, u_32_t *)); -static void ipfstate_dead __P((char *, friostat_t **, ips_stat_t **, - ipfrstat_t **, fr_authstat_t **, u_32_t *)); -#ifdef STATETOP -static void topipstates __P((struct in_addr, struct in_addr, int, int, int, int, int)); -static char *ttl_to_string __P((long)); -static int sort_p __P((const void *, const void *)); -static int sort_pkts __P((const void *, const void *)); -static int sort_bytes __P((const void *, const void *)); -static int sort_ttl __P((const void *, const void *)); -static int sort_srcip __P((const void *, const void *)); -static int sort_dstip __P((const void *, const void *)); -#endif -#if SOLARIS -void showqiflist __P((char *)); -#endif - - -static void Usage(name) -char *name; -{ -#ifdef USE_INET6 - fprintf(stderr, "Usage: %s [-6aAfhIinosv] [-d <device>]\n", name); -#else - fprintf(stderr, "Usage: %s [-aAfhIinosv] [-d <device>]\n", name); -#endif - fprintf(stderr, "\t\t[-M corefile] [-N symbol-list]\n"); - fprintf(stderr, " %s -t [-S source address] [-D destination address] [-P protocol] [-T refreshtime] [-C] [-d <device>]\n", name); - exit(1); -} - - -int main(argc,argv) -int argc; -char *argv[]; -{ - fr_authstat_t frauthst; - fr_authstat_t *frauthstp = &frauthst; - friostat_t fio; - friostat_t *fiop = &fio; - ips_stat_t ipsst; - ips_stat_t *ipsstp = &ipsst; - ipfrstat_t ifrst; - ipfrstat_t *ifrstp = &ifrst; - char *device = IPL_NAME, *memf = NULL; - char *kern = NULL; - int c, myoptind; - struct protoent *proto; - - int protocol = -1; /* -1 = wild card for any protocol */ - int refreshtime = 1; /* default update time */ - int sport = -1; /* -1 = wild card for any source port */ - int dport = -1; /* -1 = wild card for any dest port */ - int topclosed = 0; /* do not show closed tcp sessions */ - struct in_addr saddr, daddr; - u_32_t frf; - - saddr.s_addr = INADDR_ANY; /* default any source addr */ - daddr.s_addr = INADDR_ANY; /* default any dest addr */ - - /* - * Parse these two arguments now lest there be any buffer overflows - * in the parsing of the rest. - */ - myoptind = optind; - while ((c = getopt(argc, argv, "6aACfghIilnoqstvd:D:M:N:P:S:T:")) != -1) - switch (c) - { - case 'M' : - memf = optarg; - live_kernel = 0; - break; - case 'N' : - kern = optarg; - live_kernel = 0; - break; - } - optind = myoptind; - - if (live_kernel == 1) { - if ((state_fd = open(IPL_STATE, O_RDONLY)) == -1) { - perror("open"); - exit(-1); - } - if ((auth_fd = open(IPL_AUTH, O_RDONLY)) == -1) { - perror("open"); - exit(-1); - } - if ((ipf_fd = open(device, O_RDONLY)) == -1) { - perror("open"); - exit(-1); - } - } - - if (kern != NULL || memf != NULL) - { - (void)setuid(getuid()); - (void)setgid(getgid()); - } - - if (openkmem(kern, memf) == -1) - exit(-1); - - (void)setuid(getuid()); - (void)setgid(getgid()); - - while ((c = getopt(argc, argv, "6aACfghIilnoqstvd:D:M:N:P:S:T:")) != -1) - { - switch (c) - { -#ifdef USE_INET6 - case '6' : - use_inet6 = 1; - break; -#endif - case 'a' : - opts |= OPT_ACCNT|OPT_SHOWLIST; - break; - case 'A' : - device = IPAUTH_NAME; - opts |= OPT_AUTHSTATS; - break; - case 'C' : - topclosed = 1; - break; - case 'd' : - device = optarg; - break; - case 'D' : - parse_ipportstr(optarg, &daddr, &dport); - break; - case 'f' : - opts |= OPT_FRSTATES; - break; - case 'g' : - opts |= OPT_GROUPS; - break; - case 'h' : - opts |= OPT_HITS; - break; - case 'i' : - opts |= OPT_INQUE|OPT_SHOWLIST; - break; - case 'I' : - opts |= OPT_INACTIVE; - break; - case 'l' : - opts |= OPT_SHOWLIST; - break; - case 'M' : - break; - case 'N' : - break; - case 'n' : - opts |= OPT_SHOWLINENO; - break; - case 'o' : - opts |= OPT_OUTQUE|OPT_SHOWLIST; - break; - case 'P' : - if ((proto = getprotobyname(optarg)) != NULL) { - protocol = proto->p_proto; - } else if (!sscanf(optarg, "%ud", &protocol) || - (protocol < 0)) { - fprintf(stderr, "%s : Invalid protocol: %s\n", - argv[0], optarg); - exit(-2); - } - break; - case 'q' : -#if SOLARIS - showqiflist(kern); - exit(0); - break; -#else - fprintf(stderr, "-q only availble on Solaris\n"); - exit(1); - break; -#endif - case 's' : - opts |= OPT_IPSTATES; - break; - case 'S' : - parse_ipportstr(optarg, &saddr, &sport); - break; - case 't' : -#ifdef STATETOP - opts |= OPT_STATETOP; - break; -#else - fprintf(stderr, - "%s : state top facility not compiled in\n", - argv[0]); - exit(-2); -#endif - case 'T' : - if (!sscanf(optarg, "%d", &refreshtime) || - (refreshtime <= 0)) { - fprintf(stderr, - "%s : Invalid refreshtime < 1 : %s\n", - argv[0], optarg); - exit(-2); - } - break; - case 'v' : - opts |= OPT_VERBOSE; - break; - default : - Usage(argv[0]); - break; - } - } - - if (live_kernel == 1) { - bzero((char *)&fio, sizeof(fio)); - bzero((char *)&ipsst, sizeof(ipsst)); - bzero((char *)&ifrst, sizeof(ifrst)); - - ipfstate_live(device, &fiop, &ipsstp, &ifrstp, - &frauthstp, &frf); - } else - ipfstate_dead(kern, &fiop, &ipsstp, &ifrstp, &frauthstp, &frf); - - if (opts & OPT_IPSTATES) { - showipstates(ipsstp); - } else if (opts & OPT_SHOWLIST) { - showlist(fiop); - if ((opts & OPT_OUTQUE) && (opts & OPT_INQUE)){ - opts &= ~OPT_OUTQUE; - showlist(fiop); - } - } else { - if (opts & OPT_FRSTATES) - showfrstates(ifrstp); -#ifdef STATETOP - else if (opts & OPT_STATETOP) - topipstates(saddr, daddr, sport, dport, - protocol, refreshtime, topclosed); -#endif - else if (opts & OPT_AUTHSTATS) - showauthstates(frauthstp); - else if (opts & OPT_GROUPS) - showgroups(fiop); - else - showstats(fiop, frf); - } - return 0; -} - - -/* - * Fill in the stats structures from the live kernel, using a combination - * of ioctl's and copying directly from kernel memory. - */ -int ipfstate_live(device, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp) -char *device; -friostat_t **fiopp; -ips_stat_t **ipsstpp; -ipfrstat_t **ifrstpp; -fr_authstat_t **frauthstpp; -u_32_t *frfp; -{ - - if (!(opts & OPT_AUTHSTATS) && ioctl(ipf_fd, SIOCGETFS, fiopp) == -1) { - perror("ioctl(ipf:SIOCGETFS)"); - exit(-1); - } - - if ((opts & OPT_IPSTATES)) { - if ((ioctl(state_fd, SIOCGETFS, ipsstpp) == -1)) { - perror("ioctl(state:SIOCGETFS)"); - exit(-1); - } - } - if ((opts & OPT_FRSTATES) && - (ioctl(ipf_fd, SIOCGFRST, ifrstpp) == -1)) { - perror("ioctl(SIOCGFRST)"); - exit(-1); - } - - if (opts & OPT_VERBOSE) - PRINTF("opts %#x name %s\n", opts, device); - - if ((opts & OPT_AUTHSTATS) && - (ioctl(auth_fd, SIOCATHST, frauthstpp) == -1)) { - perror("ioctl(SIOCATHST)"); - exit(-1); - } - - if (ioctl(ipf_fd, SIOCGETFF, frfp) == -1) - perror("ioctl(SIOCGETFF)"); - - return ipf_fd; -} - - -/* - * Build up the stats structures from data held in the "core" memory. - * This is mainly useful when looking at data in crash dumps and ioctl's - * just won't work any more. - */ -void ipfstate_dead(kernel, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp) -char *kernel; -friostat_t **fiopp; -ips_stat_t **ipsstpp; -ipfrstat_t **ifrstpp; -fr_authstat_t **frauthstpp; -u_32_t *frfp; -{ - static fr_authstat_t frauthst, *frauthstp; - static ips_stat_t ipsst, *ipsstp; - static ipfrstat_t ifrst, *ifrstp; - static friostat_t fio, *fiop; - - void *rules[2][2]; - struct nlist deadlist[42] = { - { "fr_authstats" }, /* 0 */ - { "fae_list" }, - { "ipauth" }, - { "fr_authlist" }, - { "fr_authstart" }, - { "fr_authend" }, /* 5 */ - { "fr_authnext" }, - { "fr_auth" }, - { "fr_authused" }, - { "fr_authsize" }, - { "fr_defaultauthage" }, /* 10 */ - { "fr_authpkts" }, - { "fr_auth_lock" }, - { "frstats" }, - { "ips_stats" }, - { "ips_num" }, /* 15 */ - { "ips_wild" }, - { "ips_list" }, - { "ips_table" }, - { "fr_statemax" }, - { "fr_statesize" }, /* 20 */ - { "fr_state_doflush" }, - { "fr_state_lock" }, - { "ipfr_heads" }, - { "ipfr_nattab" }, - { "ipfr_stats" }, /* 25 */ - { "ipfr_inuse" }, - { "fr_ipfrttl" }, - { "fr_frag_lock" }, - { "ipfr_timer_id" }, - { "fr_nat_lock" }, /* 30 */ - { "ipfilter" }, - { "ipfilter6" }, - { "ipacct" }, - { "ipacct6" }, - { "ipl_frouteok" }, /* 35 */ - { "fr_running" }, - { "ipfgroups" }, - { "fr_active" }, - { "fr_pass" }, - { "fr_flags" }, /* 40 */ - { NULL } - }; - - - frauthstp = &frauthst; - ipsstp = &ipsst; - ifrstp = &ifrst; - fiop = &fio; - - *frfp = 0; - *fiopp = fiop; - *ipsstpp = ipsstp; - *ifrstpp = ifrstp; - *frauthstpp = frauthstp; - - bzero((char *)fiop, sizeof(*fiop)); - bzero((char *)ipsstp, sizeof(*ipsstp)); - bzero((char *)ifrstp, sizeof(*ifrstp)); - bzero((char *)frauthstp, sizeof(*frauthstp)); - - if (nlist(kernel, deadlist) == -1) { - fprintf(stderr, "nlist error\n"); - return; - } - - /* - * This is for SIOCGETFF. - */ - kmemcpy((char *)frfp, (u_long)deadlist[40].n_value, sizeof(*frfp)); - - /* - * f_locks is a combination of the lock variable from each part of - * ipfilter (state, auth, nat, fragments). - */ - kmemcpy((char *)fiop, (u_long)deadlist[13].n_value, sizeof(*fiop)); - kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[22].n_value, - sizeof(fiop->f_locks[0])); - kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[30].n_value, - sizeof(fiop->f_locks[1])); - kmemcpy((char *)&fiop->f_locks[2], (u_long)deadlist[28].n_value, - sizeof(fiop->f_locks[2])); - kmemcpy((char *)&fiop->f_locks[3], (u_long)deadlist[12].n_value, - sizeof(fiop->f_locks[3])); - - /* - * Get pointers to each list of rules (active, inactive, in, out) - */ - kmemcpy((char *)&rules, (u_long)deadlist[31].n_value, sizeof(rules)); - fiop->f_fin[0] = rules[0][0]; - fiop->f_fin[1] = rules[0][1]; - fiop->f_fout[0] = rules[1][0]; - fiop->f_fout[1] = rules[1][1]; - - /* - * Same for IPv6, except make them null if support for it is not - * being compiled in. - */ -#ifdef USE_INET6 - kmemcpy((char *)&rules, (u_long)deadlist[32].n_value, sizeof(rules)); - fiop->f_fin6[0] = rules[0][0]; - fiop->f_fin6[1] = rules[0][1]; - fiop->f_fout6[0] = rules[1][0]; - fiop->f_fout6[1] = rules[1][1]; -#else - fiop->f_fin6[0] = NULL; - fiop->f_fin6[1] = NULL; - fiop->f_fout6[0] = NULL; - fiop->f_fout6[1] = NULL; -#endif - - /* - * Now get accounting rules pointers. - */ - kmemcpy((char *)&rules, (u_long)deadlist[33].n_value, sizeof(rules)); - fiop->f_acctin[0] = rules[0][0]; - fiop->f_acctin[1] = rules[0][1]; - fiop->f_acctout[0] = rules[1][0]; - fiop->f_acctout[1] = rules[1][1]; - -#ifdef USE_INET6 - kmemcpy((char *)&rules, (u_long)deadlist[34].n_value, sizeof(rules)); - fiop->f_acctin6[0] = rules[0][0]; - fiop->f_acctin6[1] = rules[0][1]; - fiop->f_acctout6[0] = rules[1][0]; - fiop->f_acctout6[1] = rules[1][1]; -#else - fiop->f_acctin6[0] = NULL; - fiop->f_acctin6[1] = NULL; - fiop->f_acctout6[0] = NULL; - fiop->f_acctout6[1] = NULL; -#endif - - /* - * A collection of "global" variables used inside the kernel which - * are all collected in friostat_t via ioctl. - */ - kmemcpy((char *)&fiop->f_froute, (u_long)deadlist[35].n_value, - sizeof(fiop->f_froute)); - kmemcpy((char *)&fiop->f_running, (u_long)deadlist[36].n_value, - sizeof(fiop->f_running)); - kmemcpy((char *)&fiop->f_groups, (u_long)deadlist[37].n_value, - sizeof(fiop->f_groups)); - kmemcpy((char *)&fiop->f_active, (u_long)deadlist[38].n_value, - sizeof(fiop->f_active)); - kmemcpy((char *)&fiop->f_defpass, (u_long)deadlist[39].n_value, - sizeof(fiop->f_defpass)); - - /* - * Build up the state information stats structure. - */ - kmemcpy((char *)ipsstp, (u_long)deadlist[14].n_value, sizeof(*ipsstp)); - kmemcpy((char *)&ipsstp->iss_active, (u_long)deadlist[15].n_value, - sizeof(ipsstp->iss_active)); - ipsstp->iss_table = (void *)deadlist[18].n_value; - ipsstp->iss_list = (void *)deadlist[17].n_value; - - /* - * Build up the authentiation information stats structure. - */ - kmemcpy((char *)frauthstp, (u_long)deadlist[0].n_value, - sizeof(*frauthstp)); - frauthstp->fas_faelist = (void *)deadlist[1].n_value; - - /* - * Build up the fragment information stats structure. - */ - kmemcpy((char *)ifrstp, (u_long)deadlist[25].n_value, - sizeof(*ifrstp)); - ifrstp->ifs_table = (void *)deadlist[23].n_value; - ifrstp->ifs_nattab = (void *)deadlist[24].n_value; - kmemcpy((char *)&ifrstp->ifs_inuse, (u_long)deadlist[26].n_value, - sizeof(ifrstp->ifs_inuse)); -} - - -/* - * Display the kernel stats for packets blocked and passed and other - * associated running totals which are kept. - */ -static void showstats(fp, frf) -struct friostat *fp; -u_32_t frf; -{ - -#if SOLARIS - PRINTF("dropped packets:\tin %lu\tout %lu\n", - fp->f_st[0].fr_drop, fp->f_st[1].fr_drop); - PRINTF("non-data packets:\tin %lu\tout %lu\n", - fp->f_st[0].fr_notdata, fp->f_st[1].fr_notdata); - PRINTF("no-data packets:\tin %lu\tout %lu\n", - fp->f_st[0].fr_nodata, fp->f_st[1].fr_nodata); - PRINTF("non-ip packets:\t\tin %lu\tout %lu\n", - fp->f_st[0].fr_notip, fp->f_st[1].fr_notip); - PRINTF(" bad packets:\t\tin %lu\tout %lu\n", - fp->f_st[0].fr_bad, fp->f_st[1].fr_bad); - PRINTF("copied messages:\tin %lu\tout %lu\n", - fp->f_st[0].fr_copy, fp->f_st[1].fr_copy); -#endif -#ifdef USE_INET6 - PRINTF(" IPv6 packets:\t\tin %lu out %lu\n", - fp->f_st[0].fr_ipv6[0], fp->f_st[0].fr_ipv6[1]); -#endif - PRINTF(" input packets:\t\tblocked %lu passed %lu nomatch %lu", - fp->f_st[0].fr_block, fp->f_st[0].fr_pass, - fp->f_st[0].fr_nom); - PRINTF(" counted %lu short %lu\n", - fp->f_st[0].fr_acct, fp->f_st[0].fr_short); - PRINTF("output packets:\t\tblocked %lu passed %lu nomatch %lu", - fp->f_st[1].fr_block, fp->f_st[1].fr_pass, - fp->f_st[1].fr_nom); - PRINTF(" counted %lu short %lu\n", - fp->f_st[1].fr_acct, fp->f_st[1].fr_short); - PRINTF(" input packets logged:\tblocked %lu passed %lu\n", - fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl); - PRINTF("output packets logged:\tblocked %lu passed %lu\n", - fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl); - PRINTF(" packets logged:\tinput %lu output %lu\n", - fp->f_st[0].fr_pkl, fp->f_st[1].fr_pkl); - PRINTF(" log failures:\t\tinput %lu output %lu\n", - fp->f_st[0].fr_skip, fp->f_st[1].fr_skip); - PRINTF("fragment state(in):\tkept %lu\tlost %lu\tnot fragmented %lu\n", - fp->f_st[0].fr_nfr, fp->f_st[0].fr_bnfr, fp->f_st[0].fr_cfr); - PRINTF("fragment state(out):\tkept %lu\tlost %lu\tnot fragmented %lu\n", - fp->f_st[1].fr_nfr, fp->f_st[1].fr_bnfr, fp->f_st[1].fr_cfr); - PRINTF("packet state(in):\tkept %lu\tlost %lu\n", - fp->f_st[0].fr_ads, fp->f_st[0].fr_bads); - PRINTF("packet state(out):\tkept %lu\tlost %lu\n", - fp->f_st[1].fr_ads, fp->f_st[1].fr_bads); - PRINTF("ICMP replies:\t%lu\tTCP RSTs sent:\t%lu\n", - fp->f_st[0].fr_ret, fp->f_st[1].fr_ret); - PRINTF("Invalid source(in):\t%lu\n", fp->f_st[0].fr_badsrc); - PRINTF("Result cache hits(in):\t%lu\t(out):\t%lu\n", - fp->f_st[0].fr_chit, fp->f_st[1].fr_chit); - PRINTF("IN Pullups succeeded:\t%lu\tfailed:\t%lu\n", - fp->f_st[0].fr_pull[0], fp->f_st[0].fr_pull[1]); - PRINTF("OUT Pullups succeeded:\t%lu\tfailed:\t%lu\n", - fp->f_st[1].fr_pull[0], fp->f_st[1].fr_pull[1]); - PRINTF("Fastroute successes:\t%lu\tfailures:\t%lu\n", - fp->f_froute[0], fp->f_froute[1]); - PRINTF("TCP cksum fails(in):\t%lu\t(out):\t%lu\n", - fp->f_st[0].fr_tcpbad, fp->f_st[1].fr_tcpbad); - - PRINTF("Packet log flags set: (%#x)\n", frf); - if (frf & FF_LOGPASS) - PRINTF("\tpackets passed through filter\n"); - if (frf & FF_LOGBLOCK) - PRINTF("\tpackets blocked by filter\n"); - if (frf & FF_LOGNOMATCH) - PRINTF("\tpackets not matched by filter\n"); - if (!frf) - PRINTF("\tnone\n"); -} - - -/* - * Print out a list of rules from the kernel, starting at the one passed. - */ -static void printlist(fp) -frentry_t *fp; -{ - struct frentry fb; - int n; - - for (n = 1; fp; n++) { - if (kmemcpy((char *)&fb, (u_long)fp, sizeof(fb)) == -1) { - perror("kmemcpy"); - return; - } - fp = &fb; - if (opts & OPT_OUTQUE) - fp->fr_flags |= FR_OUTQUE; - if (opts & (OPT_HITS|OPT_VERBOSE)) -#ifdef USE_QUAD_T - PRINTF("%qu ", (unsigned long long) fp->fr_hits); -#else - PRINTF("%lu ", fp->fr_hits); -#endif - if (opts & (OPT_ACCNT|OPT_VERBOSE)) -#ifdef USE_QUAD_T - PRINTF("%qu ", (unsigned long long) fp->fr_bytes); -#else - PRINTF("%lu ", fp->fr_bytes); -#endif - if (opts & OPT_SHOWLINENO) - PRINTF("@%d ", n); - printfr(fp); - if (opts & OPT_VERBOSE) - binprint(fp); - if (fp->fr_grp) - printlist(fp->fr_grp); - fp = fp->fr_next; - } -} - -/* - * print out all of the asked for rule sets, using the stats struct as - * the base from which to get the pointers. - */ -static void showlist(fiop) -struct friostat *fiop; -{ - struct frentry *fp = NULL; - int i, set; - - set = fiop->f_active; - if (opts & OPT_INACTIVE) - set = 1 - set; - if (opts & OPT_ACCNT) { -#ifdef USE_INET6 - if ((use_inet6) && (opts & OPT_OUTQUE)) { - i = F_ACOUT; - fp = (struct frentry *)fiop->f_acctout6[set]; - } else if ((use_inet6) && (opts & OPT_INQUE)) { - i = F_ACIN; - fp = (struct frentry *)fiop->f_acctin6[set]; - } else -#endif - if (opts & OPT_OUTQUE) { - i = F_ACOUT; - fp = (struct frentry *)fiop->f_acctout[set]; - } else if (opts & OPT_INQUE) { - i = F_ACIN; - fp = (struct frentry *)fiop->f_acctin[set]; - } else { - FPRINTF(stderr, "No -i or -o given with -a\n"); - return; - } - } else { -#ifdef USE_INET6 - if ((use_inet6) && (opts & OPT_OUTQUE)) { - i = F_OUT; - fp = (struct frentry *)fiop->f_fout6[set]; - } else if ((use_inet6) && (opts & OPT_INQUE)) { - i = F_IN; - fp = (struct frentry *)fiop->f_fin6[set]; - } else -#endif - if (opts & OPT_OUTQUE) { - i = F_OUT; - fp = (struct frentry *)fiop->f_fout[set]; - } else if (opts & OPT_INQUE) { - i = F_IN; - fp = (struct frentry *)fiop->f_fin[set]; - } else - return; - } - if (opts & OPT_VERBOSE) - FPRINTF(stderr, "showlist:opts %#x i %d\n", opts, i); - - if (opts & OPT_VERBOSE) - PRINTF("fp %p set %d\n", fp, set); - if (fp == NULL) { - FPRINTF(stderr, "empty list for %s%s\n", - (opts & OPT_INACTIVE) ? "inactive " : "", filters[i]); - return; - } - printlist(fp); -} - - -/* - * Display ipfilter stateful filtering information - */ -static void showipstates(ipsp) -ips_stat_t *ipsp; -{ - ipstate_t *istab[IPSTATE_SIZE]; - - /* - * If a list of states hasn't been asked for, only print out stats - */ - if (!(opts & OPT_SHOWLIST)) { - PRINTF("IP states added:\n\t%lu TCP\n\t%lu UDP\n\t%lu ICMP\n", - ipsp->iss_tcp, ipsp->iss_udp, ipsp->iss_icmp); - PRINTF("\t%lu hits\n\t%lu misses\n", ipsp->iss_hits, - ipsp->iss_miss); - PRINTF("\t%lu maximum\n\t%lu no memory\n\t%lu bkts in use\n", - ipsp->iss_max, ipsp->iss_nomem, ipsp->iss_inuse); - PRINTF("\t%lu logged\n\t%lu log failures\n", - ipsp->iss_logged, ipsp->iss_logfail); - PRINTF("\t%lu active\n\t%lu expired\n\t%lu closed\n", - ipsp->iss_active, ipsp->iss_expire, ipsp->iss_fin); - return; - } - - if (kmemcpy((char *)istab, (u_long)ipsp->iss_table, sizeof(istab))) - return; - - /* - * Print out all the state information currently held in the kernel. - */ - while (ipsp->iss_list != NULL) { - ipsp->iss_list = printstate(ipsp->iss_list, opts); - } -} - - -#if SOLARIS -/* - * Displays the list of interfaces of which IPFilter has taken control in - * Solaris. - */ -void showqiflist(kern) -char *kern; -{ - struct nlist qifnlist[2] = { - { "_qif_head" }, - { NULL } - }; - qif_t qif, *qf; - ill_t ill; - - if (kern == NULL) - kern = "/dev/ksyms"; - - if (nlist(kern, qifnlist) == -1) { - fprintf(stderr, "nlist error\n"); - return; - } - - printf("List of interfaces bound by IPFilter:\n"); - if (kmemcpy((char *)&qf, (u_long)qifnlist[0].n_value, sizeof(qf))) - return; - while (qf) { - if (kmemcpy((char *)&qif, (u_long)qf, sizeof(qif))) - break; - if (kmemcpy((char *)&ill, (u_long)qif.qf_ill, sizeof(ill))) - ill.ill_ppa = -1; - printf("Name: %-8s Header Length: %2d SAP: %s (%04x) PPA %d", - qif.qf_name, qif.qf_hl, -#ifdef IP6_DL_SAP - (qif.qf_sap == IP6_DL_SAP) ? "IPv6" : "IPv4" -#else - "IPv4" -#endif - , qif.qf_sap, ill.ill_ppa); - printf(" %ld %ld", qif.qf_incnt, qif.qf_outcnt); - qf = qif.qf_next; - putchar('\n'); - } -} -#endif - - -#ifdef STATETOP -static void topipstates(saddr, daddr, sport, dport, protocol, - refreshtime, topclosed) -struct in_addr saddr; -struct in_addr daddr; -int sport; -int dport; -int protocol; -int refreshtime; -int topclosed; -{ - char str1[STSTRSIZE], str2[STSTRSIZE], str3[STSTRSIZE], str4[STSTRSIZE]; - int maxtsentries = 0, reverse = 0, sorting = STSORT_DEFAULT; - int i, j, winx, tsentry, maxx, maxy, redraw = 0; - ipstate_t *istab[IPSTATE_SIZE], ips; - ips_stat_t ipsst, *ipsstp = &ipsst; - statetop_t *tstable = NULL, *tp; - char hostnm[HOSTNMLEN]; - struct protoent *proto; - int c = 0; - time_t t; -#ifdef USE_POLL - struct pollfd set[1]; -#else - struct timeval selecttimeout; - fd_set readfd; -#endif - - /* init ncurses stuff */ - initscr(); - cbreak(); - noecho(); - - /* init hostname */ - gethostname(hostnm, sizeof(hostnm) - 1); - hostnm[sizeof(hostnm) - 1] = '\0'; - - /* repeat until user aborts */ - while ( 1 ) { - - /* get state table */ - bzero((char *)&ipsst, sizeof(&ipsst)); - if ((ioctl(state_fd, SIOCGETFS, &ipsstp) == -1)) { - perror("ioctl(SIOCGETFS)"); - exit(-1); - } - if (kmemcpy((char *)istab, (u_long)ipsstp->iss_table, - sizeof(ips))) - return; - - /* clear the history */ - tsentry = -1; - - /* read the state table and store in tstable */ - while (ipsstp->iss_list) { - if (kmemcpy((char *)&ips, (u_long)ipsstp->iss_list, - sizeof(ips))) - break; - ipsstp->iss_list = ips.is_next; - - if (((saddr.s_addr == INADDR_ANY) || - (saddr.s_addr == ips.is_saddr)) && - ((daddr.s_addr == INADDR_ANY) || - (daddr.s_addr == ips.is_daddr)) && - ((protocol < 0) || (protocol == ips.is_p)) && - (((ips.is_p != IPPROTO_TCP) && - (ips.is_p != IPPROTO_UDP)) || - (((sport < 0) || - (htons(sport) == ips.is_sport)) && - ((dport < 0) || - (htons(dport) == ips.is_dport)))) && - (topclosed || (ips.is_p != IPPROTO_TCP) || - (ips.is_state[0] < TCPS_LAST_ACK) || - (ips.is_state[1] < TCPS_LAST_ACK))) { - /* - * if necessary make room for this state - * entry - */ - tsentry++; - if (!maxtsentries || - (tsentry == maxtsentries)) { - - maxtsentries += STGROWSIZE; - tstable = realloc(tstable, maxtsentries * sizeof(statetop_t)); - if (!tstable) { - perror("malloc"); - exit(-1); - } - } - - /* fill structure */ - tp = tstable + tsentry; - tp->st_src = ips.is_src; - tp->st_dst = ips.is_dst; - tp->st_p = ips.is_p; - tp->st_state[0] = ips.is_state[0]; - tp->st_state[1] = ips.is_state[1]; - tp->st_pkts = ips.is_pkts; - tp->st_bytes = ips.is_bytes; - tp->st_age = ips.is_age; - if ((ips.is_p == IPPROTO_TCP) || - (ips.is_p == IPPROTO_UDP)) { - tp->st_sport = ips.is_sport; - tp->st_dport = ips.is_dport; - } - - } - } - - - /* sort the array */ - if (tsentry != -1) - switch (sorting) - { - case STSORT_PR: - qsort(tstable, tsentry + 1, - sizeof(statetop_t), sort_p); - break; - case STSORT_PKTS: - qsort(tstable, tsentry + 1, - sizeof(statetop_t), sort_pkts); - break; - case STSORT_BYTES: - qsort(tstable, tsentry + 1, - sizeof(statetop_t), sort_bytes); - break; - case STSORT_TTL: - qsort(tstable, tsentry + 1, - sizeof(statetop_t), sort_ttl); - break; - case STSORT_SRCIP: - qsort(tstable, tsentry + 1, - sizeof(statetop_t), sort_srcip); - break; - case STSORT_DSTIP: - qsort(tstable, tsentry + 1, - sizeof(statetop_t), sort_dstip); - break; - default: - break; - } - - /* print title */ - erase(); - getmaxyx(stdscr, maxy, maxx); - attron(A_BOLD); - winx = 0; - move(winx,0); - sprintf(str1, "%s - %s - state top", hostnm, IPL_VERSION); - for (j = 0 ; j < (maxx - 8 - strlen(str1)) / 2; j++) - printw(" "); - printw("%s", str1); - attroff(A_BOLD); - - /* just for fun add a clock */ - move(winx, maxx - 8); - t = time(NULL); - strftime(str1, 80, "%T", localtime(&t)); - printw("%s\n", str1); - - /* - * print the display filters, this is placed in the loop, - * because someday I might add code for changing these - * while the programming is running :-) - */ - if (sport >= 0) - sprintf(str1, "%s,%d", inet_ntoa(saddr), sport); - else - sprintf(str1, "%s", inet_ntoa(saddr)); - - if (dport >= 0) - sprintf(str2, "%s,%d", inet_ntoa(daddr), dport); - else - sprintf(str2, "%s", inet_ntoa(daddr)); - - if (protocol < 0) - strcpy(str3, "any"); - else if ((proto = getprotobynumber(protocol)) != NULL) - sprintf(str3, "%s", proto->p_name); - else - sprintf(str3, "%d", protocol); - - switch (sorting) - { - case STSORT_PR: - sprintf(str4, "proto"); - break; - case STSORT_PKTS: - sprintf(str4, "# pkts"); - break; - case STSORT_BYTES: - sprintf(str4, "# bytes"); - break; - case STSORT_TTL: - sprintf(str4, "ttl"); - break; - case STSORT_SRCIP: - sprintf(str4, "srcip"); - break; - case STSORT_DSTIP: - sprintf(str4, "dstip"); - break; - default: - sprintf(str4, "unknown"); - break; - } - - if (reverse) - strcat(str4, " (reverse)"); - - winx += 2; - move(winx,0); - printw("Src = %s Dest = %s Proto = %s Sorted by = %s\n\n", - str1, str2, str3, str4); - - /* print column description */ - winx += 2; - move(winx,0); - attron(A_BOLD); - printw("%-21s %-21s %3s %4s %7s %9s %9s\n", "Source IP", - "Destination IP", "ST", "PR", "#pkts", "#bytes", "ttl"); - attroff(A_BOLD); - - /* print all the entries */ - tp = tstable; - if (reverse) - tp += tsentry; - - if (tsentry > maxy - 6) - tsentry = maxy - 6; - for (i = 0; i <= tsentry; i++) { - /* print src/dest and port */ - if ((tp->st_p == IPPROTO_TCP) || - (tp->st_p == IPPROTO_UDP)) { - sprintf(str1, "%s,%hu", - inet_ntoa(tp->st_src.in4), - ntohs(tp->st_sport)); - sprintf(str2, "%s,%hu", - inet_ntoa(tp->st_dst.in4), - ntohs(tp->st_dport)); - } else { - sprintf(str1, "%s", inet_ntoa(tp->st_src.in4)); - sprintf(str2, "%s", inet_ntoa(tp->st_dst.in4)); - } - winx++; - move(winx, 0); - printw("%-21s %-21s", str1, str2); - - /* print state */ - sprintf(str1, "%X/%X", tp->st_state[0], - tp->st_state[1]); - printw(" %3s", str1); - - /* print proto */ - proto = getprotobynumber(tp->st_p); - if (proto) { - strncpy(str1, proto->p_name, 4); - str1[4] = '\0'; - } else { - sprintf(str1, "%d", tp->st_p); - } - printw(" %4s", str1); - /* print #pkt/#bytes */ -#ifdef USE_QUAD_T - printw(" %7qu %9qu", (unsigned long long) tp->st_pkts, - (unsigned long long) tp->st_bytes); -#else - printw(" %7lu %9lu", tp->st_pkts, tp->st_bytes); -#endif - printw(" %9s", ttl_to_string(tp->st_age)); - - if (reverse) - tp--; - else - tp++; - } - - /* screen data structure is filled, now update the screen */ - if (redraw) - clearok(stdscr,1); - - refresh(); - if (redraw) { - clearok(stdscr,0); - redraw = 0; - } - - /* wait for key press or a 1 second time out period */ -#ifdef USE_POLL - set[0].fd = 0; - set[0].events = POLLIN; - poll(set, 1, refreshtime * 1000); - - /* if key pressed, read all waiting keys */ - if (set[0].revents & POLLIN) -#else - selecttimeout.tv_sec = refreshtime; - selecttimeout.tv_usec = 0; - FD_ZERO(&readfd); - FD_SET(0, &readfd); - select(1, &readfd, NULL, NULL, &selecttimeout); - - /* if key pressed, read all waiting keys */ - if (FD_ISSET(0, &readfd)) -#endif - - { - c = wgetch(stdscr); - if (c == ERR) - continue; - - if (isalpha(c) && isupper(c)) - c = tolower(c); - if (c == 'l') { - redraw = 1; - } else if (c == 'q') { - break; /* exits while() loop */ - } else if (c == 'r') { - reverse = !reverse; - } else if (c == 's') { - sorting++; - if (sorting > STSORT_MAX) - sorting = 0; - } - } - } /* while */ - - printw("\n"); - nocbreak(); - endwin(); -} -#endif - - -/* - * Show fragment cache information that's held in the kernel. - */ -static void showfrstates(ifsp) -ipfrstat_t *ifsp; -{ - struct ipfr *ipfrtab[IPFT_SIZE], ifr; - frentry_t fr; - int i; - - /* - * print out the numeric statistics - */ - PRINTF("IP fragment states:\n\t%lu new\n\t%lu expired\n\t%lu hits\n", - ifsp->ifs_new, ifsp->ifs_expire, ifsp->ifs_hits); - PRINTF("\t%lu no memory\n\t%lu already exist\n", - ifsp->ifs_nomem, ifsp->ifs_exists); - PRINTF("\t%lu inuse\n", ifsp->ifs_inuse); - if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_table, sizeof(ipfrtab))) - return; - - /* - * Print out the contents (if any) of the fragment cache table. - */ - PRINTF("\n"); - for (i = 0; i < IPFT_SIZE; i++) - while (ipfrtab[i]) { - if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], - sizeof(ifr)) == -1) - break; - PRINTF("%s -> ", hostname(4, &ifr.ipfr_src)); - if (kmemcpy((char *)&fr, (u_long)ifr.ipfr_rule, - sizeof(fr)) == -1) - break; - PRINTF("%s id %d ttl %d pr %d seen0 %d ifp %p tos %#02x = fl %#x\n", - hostname(4, &ifr.ipfr_dst), ntohs(ifr.ipfr_id), - ifr.ipfr_ttl, ifr.ipfr_p, ifr.ipfr_seen0, - ifr.ipfr_ifp, ifr.ipfr_tos, fr.fr_flags); - ipfrtab[i] = ifr.ipfr_next; - } - if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_nattab,sizeof(ipfrtab))) - return; - for (i = 0; i < IPFT_SIZE; i++) - while (ipfrtab[i]) { - if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], - sizeof(ifr)) == -1) - break; - PRINTF("NAT: %s -> ", hostname(4, &ifr.ipfr_src)); - if (kmemcpy((char *)&fr, (u_long)ifr.ipfr_rule, - sizeof(fr)) == -1) - break; - PRINTF("%s %d %d %d %#02x = %#x\n", - hostname(4, &ifr.ipfr_dst), ifr.ipfr_id, - ifr.ipfr_ttl, ifr.ipfr_p, ifr.ipfr_tos, - fr.fr_flags); - ipfrtab[i] = ifr.ipfr_next; - } -} - - -/* - * Show stats on how auth within IPFilter has been used - */ -static void showauthstates(asp) -fr_authstat_t *asp; -{ - frauthent_t *frap, fra; - -#ifdef USE_QUAD_T - printf("Authorisation hits: %qu\tmisses %qu\n", - (unsigned long long) asp->fas_hits, - (unsigned long long) asp->fas_miss); -#else - printf("Authorisation hits: %ld\tmisses %ld\n", asp->fas_hits, - asp->fas_miss); -#endif - printf("nospace %ld\nadded %ld\nsendfail %ld\nsendok %ld\n", - asp->fas_nospace, asp->fas_added, asp->fas_sendfail, - asp->fas_sendok); - printf("queok %ld\nquefail %ld\nexpire %ld\n", - asp->fas_queok, asp->fas_quefail, asp->fas_expire); - - frap = asp->fas_faelist; - while (frap) { - if (kmemcpy((char *)&fra, (u_long)frap, sizeof(fra)) == -1) - break; - - printf("age %ld\t", fra.fae_age); - printfr(&fra.fae_fr); - frap = fra.fae_next; - } -} - - -/* - * Display groups used for each of filter rules, accounting rules and - * authentication, separately. - */ -static void showgroups(fiop) -struct friostat *fiop; -{ - static char *gnames[3] = { "Filter", "Accounting", "Authentication" }; - frgroup_t *fp, grp; - int on, off, i; - - on = fiop->f_active; - off = 1 - on; - - for (i = 0; i < 3; i++) { - printf("%s groups (active):\n", gnames[i]); - for (fp = fiop->f_groups[i][on]; fp; fp = grp.fg_next) - if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp))) - break; - else - printf("%hu\n", grp.fg_num); - printf("%s groups (inactive):\n", gnames[i]); - for (fp = fiop->f_groups[i][off]; fp; fp = grp.fg_next) - if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp))) - break; - else - printf("%hu\n", grp.fg_num); - } -} - -static void parse_ipportstr(argument, ip, port) -const char *argument; -struct in_addr *ip; -int *port; -{ - - char *s, *comma; - - /* make working copy of argument, Theoretically you must be able - * to write to optarg, but that seems very ugly to me.... - */ - if ((s = malloc(strlen(argument) + 1)) == NULL) - perror("malloc"); - strcpy(s, argument); - - /* get port */ - if ((comma = strchr(s, ',')) != NULL) { - if (!strcasecmp(s, "any")) { - *port = -1; - } else if (!sscanf(comma + 1, "%d", port) || - (*port < 0) || (*port > 65535)) { - fprintf(stderr, "Invalid port specfication in %s\n", - argument); - exit(-2); - } - *comma = '\0'; - } - - - /* get ip address */ - if (!strcasecmp(s, "any")) { - ip->s_addr = INADDR_ANY; - } else if (!inet_aton(s, ip)) { - fprintf(stderr, "Invalid IP address: %s\n", s); - exit(-2); - } - - /* free allocated memory */ - free(s); -} - - -#ifdef STATETOP -static char ttlbuf[STSTRSIZE]; - -static char *ttl_to_string(ttl) -long int ttl; -{ - - int hours, minutes, seconds; - - /* ttl is in half seconds */ - ttl /= 2; - - hours = ttl / 3600; - ttl = ttl % 3600; - minutes = ttl / 60; - seconds = ttl % 60; - - if (hours > 0 ) - sprintf(ttlbuf, "%2d:%02d:%02d", hours, minutes, seconds); - else - sprintf(ttlbuf, "%2d:%02d", minutes, seconds); - return ttlbuf; -} - - -static int sort_pkts(a, b) -const void *a; -const void *b; -{ - - register const statetop_t *ap = a; - register const statetop_t *bp = b; - - if (ap->st_pkts == bp->st_pkts) - return 0; - else if (ap->st_pkts < bp->st_pkts) - return 1; - return -1; -} - - -static int sort_bytes(a, b) -const void *a; -const void *b; -{ - register const statetop_t *ap = a; - register const statetop_t *bp = b; - - if (ap->st_bytes == bp->st_bytes) - return 0; - else if (ap->st_bytes < bp->st_bytes) - return 1; - return -1; -} - - -static int sort_p(a, b) -const void *a; -const void *b; -{ - register const statetop_t *ap = a; - register const statetop_t *bp = b; - - if (ap->st_p == bp->st_p) - return 0; - else if (ap->st_p < bp->st_p) - return 1; - return -1; -} - - -static int sort_ttl(a, b) -const void *a; -const void *b; -{ - register const statetop_t *ap = a; - register const statetop_t *bp = b; - - if (ap->st_age == bp->st_age) - return 0; - else if (ap->st_age < bp->st_age) - return 1; - return -1; -} - -static int sort_srcip(a, b) -const void *a; -const void *b; -{ - register const statetop_t *ap = a; - register const statetop_t *bp = b; - - if (ntohl(ap->st_src.in4.s_addr) == ntohl(bp->st_src.in4.s_addr)) - return 0; - else if (ntohl(ap->st_src.in4.s_addr) > ntohl(bp->st_src.in4.s_addr)) - return 1; - return -1; -} - -static int sort_dstip(a, b) -const void *a; -const void *b; -{ - register const statetop_t *ap = a; - register const statetop_t *bp = b; - - if (ntohl(ap->st_dst.in4.s_addr) == ntohl(bp->st_dst.in4.s_addr)) - return 0; - else if (ntohl(ap->st_dst.in4.s_addr) > ntohl(bp->st_dst.in4.s_addr)) - return 1; - return -1; -} -#endif diff --git a/hpux.c b/hpux.c new file mode 100644 index 0000000000000..88e9ca437f06e --- /dev/null +++ b/hpux.c @@ -0,0 +1,651 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ +/* #pragma ident "@(#)solaris.c 1.12 6/5/96 (C) 1995 Darren Reed"*/ + +/*typedef unsigned int spustate_t;*/ +struct uio; + +#include <sys/types.h> +#include <sys/cmn_err.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/malloc.h> +#include <sys/conf.h> +#include <sys/callout.h> +#include <sys/moddefs.h> +#include <sys/spinlock.h> /* HNT */ +#include <sys/io.h> +#include <sys/wsio.h> +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/byteorder.h> +#include <sys/socket.h> +#include <sys/stropts.h> +#include <net/if.h> +#include <net/af.h> +#include <net/route.h> +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/if_ether.h> +#include <netinet/ip.h> +#include <netinet/ip_var.h> +#include <netinet/tcp.h> +#include <netinet/udp.h> +#include <netinet/tcpip.h> +#include <netinet/ip_icmp.h> + +#include "ip_compat.h" +#include "ip_fil.h" +#include "ip_nat.h" +#include "ipl.h" + +#undef untimeout +#undef IPFDEBUG + +extern int ipf_running; +extern int ipf_flags; +extern int ipf_check __P(()); + +extern ipnat_t *nat_list; + +static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, + IPAUTH_NAME, IPSYNC_NAME, IPLOOKUP_NAME, + NULL }; +static int (*ipf_ip_inp) __P((queue_t *, mblk_t *)) = NULL; + + +static int ipf_slowtimer __P((void)); +struct callout *ipf_timer_id = NULL; +struct callout *synctimeoutid = NULL; +#ifdef IPFDEBUG +void printiri __P((irinfo_t *)); +#endif /* IPFDEBUG */ + +static int ipf_install(void); /* Install Routine - Biswajit */ +static int ipf_load(void *); +static int ipf_unload(void *); +static int ipf_write(dev_t, struct uio *); + +static int ipf_attach(void); +static int ipf_detach(void); +static int ipf_qifsync(ip_t *, int, void *, int, qif_t *, mblk_t **); + + +/* + * Local functions for static linking - Biswajit + */ +static void ipf_linked_init(void); +static int (*ipf_saved_init)(); /* Used in ipf_install() - Biswajit */ + +/* + * While linking statically, PFIL needs to be installed + * before IPF is installed. + */ +int pfil_install (void); + +/* + * Driver Header + */ +static drv_info_t ipf_drv_info = { + IPL_VERSION, /* type */ + "pseudo", /* class */ + DRV_CHAR|DRV_PSEUDO|DRV_SAVE_CONF|DRV_MP_SAFE, /* flags */ + -1, /* b_major */ + -1, /* c_major */ + NULL, /* cdio */ + NULL, /* gio_private */ + NULL, /* cdio_private */ +}; + + +static drv_ops_t ipf_drv_ops = { + ipfopen, + ipfclose, + NULL, /* strategy */ + NULL, /* dump */ + NULL, /* psize */ + NULL, /* mount */ + ipfread, + ipfwrite, /* write */ + ipfioctl, /* ioctl */ +#ifdef IPL_SELECT + ipfselect, /* select */ +#else + NULL, /* select */ +#endif + NULL, /* option1 */ + NULL, /* reserved1 */ + NULL, /* reserved2 */ + NULL, /* reserved3 */ + NULL, /* reserved4 */ + 0, /* flags */ +}; + + +static wsio_drv_data_t ipf_wsio_data = { + "pseudo_ipf", /* drv_path */ + T_DEVICE, /* drv_type */ + DRV_CONVERGED, /* drv_flags */ + NULL, /* drv_minor_build - field not used */ + NULL, /* drv_major_build - field not used */ +}; + +extern struct mod_operations gio_mod_ops; +static drv_info_t ipf_drv_info; +extern struct mod_conf_data ipf_conf_data; + +static struct mod_type_data ipf_drv_link = { + IPL_VERSION, (void *)NULL +}; + +static struct modlink ipf_mod_link[] = { + { &gio_mod_ops, (void *)&ipf_drv_link }, + { NULL, (void *)NULL } +}; + +struct modwrapper ipf_wrapper = { + MODREV, + ipf_load, + ipf_unload, + (void (*)())NULL, + (void *)&ipf_conf_data, + ipf_mod_link +}; + +static wsio_drv_info_t ipf_wsio_info = { + &ipf_drv_info, + &ipf_drv_ops, + &ipf_wsio_data +}; + + +static int ipf_load(void *arg) +{ + int ipfinst; + +#ifdef IPFDEBUG + printf("IP Filter: ipf_load(%lx)\n", arg); +#endif + /* Use drv_info passed to us instead of static version */ + ipf_wsio_info.drv_info = (drv_info_t *)arg; + + ipfinst = wsio_install_driver(&ipf_wsio_info); + if (ipfinst == 0) { + cmn_err(CE_CONT, + "IP Filter: wsio_install_driver(%lx) failed: %d\n", + &ipf_wsio_info, ipfinst); + return ENXIO; + } else { + ipfinst = ipf_attach(); +#ifdef IPFDEBUG + printf("IP Filter: ipf_attach() = %d\n", ipfinst); +#endif + } +#ifdef IPFDEBUG + printf("IP Filter: ipf_load() = %d\n", ipfinst); +#endif + return ipfinst; +} + + +static int ipf_unload(void *arg) +{ + int ipfinst; + + ipfinst = wsio_uninstall_driver(&ipf_wsio_info); + if (ipfinst != 0) { + cmn_err(CE_CONT, + "IP Filter: wsio_uninstall_driver(%lx) failed: %d\n", + &ipf_wsio_info, ipfinst); + return ENXIO; + } else { + ipfinst = ipf_detach(); +#ifdef IPFDEBUG + printf("IP Filter: ipf_detach() = %d\n", ipfinst); +#endif + } +#ifdef IPFDEBUG + printf("IP Filter: ipf_unload() = %d\n", ipfinst); + + /* HP Port: We don't want this to come to the cosole on boot up */ + cmn_err(CE_CONT, "IP Filter: Unloaded\n"); +#endif + return 0; +} + + +/* + * INSTALL + * Following routine is called when the dlkm module is + * being linked statically with the kernel + * - Biswajit + */ + +static int ipf_install(void) +{ + extern int (*dev_init) (void); + int ipfinst; + + /* + * Make sure PFIL module is installed before + * installing IPF + */ + + if (pfilinterface != PFIL_INTERFACE) { + printf("pfilinterface(%d) != %d\n", pfilinterface, + PFIL_INTERFACE); + return EINVAL; + } + + /* + * Link my init function into the chain + */ + ipf_saved_init = dev_init; + dev_init = (int (*) ()) &ipf_linked_init; + + /* + * Register driver with WSIO + */ + ipfinst = wsio_install_driver(&ipf_wsio_info); + return (ipfinst); +} + +/* + * Device Initialization Link + * Called only for statically linked drivers to link + * init routine into list + * - Biswajit + */ +static void ipf_linked_init (void) +{ + /* + * Perform driver specific initialization + */ + (void) ipf_attach (); + + /* + * Call next init function in chain + */ + (void) (*ipf_saved_init) (); +} + + +static int ipf_write(dev_t dev, struct uio *uio) +{ +#ifdef IPFDEBUG + printf("IP Filter: ipf_write(%x,%lx)\n", dev, uio); +#endif + return 0; +} + + +static int ipf_attach() +{ + char *defpass; + + RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex"); + RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock"); + RWLOCK_INIT(&ipf_frcache, "ipf cache rwlock"); + + sync(); + /* + * Initialize mutex's + */ + if (ipfattach() == -1) + goto attachfailed; + + /* + * Lock people out while we set things up. + */ + WRITE_ENTER(&ipf_global); + + if (pfil_add_hook(ipf_check, PFIL_IN|PFIL_OUT, &pfh_inet4)) + cmn_err(CE_WARN, "IP Filter: pfil_add_hook(pfh_inet4) failed"); + if (pfil_add_hook(ipf_qifsync, PFIL_IN|PFIL_OUT, &pfh_sync)) + cmn_err(CE_WARN, "IP Filter: pfil_add_hook(pfh_sync) failed"); + /* + * Release lock + */ + RWLOCK_EXIT(&ipf_global); + + if (FR_ISPASS(ipf_pass)) + defpass = "pass"; + else if (FR_ISBLOCK(ipf_pass)) + defpass = "block"; + else + defpass = "no-match -> block"; + +#ifdef IPFDEBUG + /* HP Port: We don't want this to come to the cosole on boot up */ + cmn_err(CE_CONT, "%s initialized. Default = %s all, Logging = %s\n", + ipfilter_version, defpass, +# ifdef IPFILTER_LOG + "enabled"); +# else + "disabled"); +# endif +#endif + sync(); + if (ipf_running == 0) + ipf_running = 1; + if (ipf_timer_id == NULL) + ipf_timer_id = mp_timeout(ipf_slowtimer, NULL, hz/2); + if (ipf_running == 1) + return 0; +attachfailed: + RW_DESTROY(&ipf_global); + RW_DESTROY(&ipf_mutex); + RW_DESTROY(&ipf_frcache); + return -1; +} + + +static int ipf_detach() +{ + int i; + + if (ipf_refcnt) + return EBUSY; + + /* + * Make sure we're the only one's modifying things. With + * this lock others should just fall out of the loop. + */ + MUTEX_ENTER(&ipf_rw); + if (ipf_running <= 0) { + MUTEX_EXIT(&ipf_rw); + return -1; + } + if (ipf_timer_id) { + untimeout(ipf_slowtimer, NULL); + ipf_timer_id = 0; + } + ipf_running = -1; + MUTEX_EXIT(&ipf_rw); + + /* + * Undo what we did in ipf_attach, freeing resources + * and removing things we installed. The system + * framework guarantees we are not active with this devinfo + * node in any other entry points at this time. + */ + sync(); + + if (pfil_remove_hook(ipf_check, PFIL_IN|PFIL_OUT, &pfh_inet4)) + cmn_err(CE_WARN, + "IP Filter: pfil_remove_hook(pfh_inet4) failed"); + if (pfil_remove_hook(ipf_qifsync, PFIL_IN|PFIL_OUT, &pfh_sync)) + cmn_err(CE_WARN, + "IP Filter: pfil_remove_hook(pfh_sync) failed"); + while (ipf_timer_id != NULL) + sched_yield(); + i = ipfdetach(); + + if (i == 0) { + RW_DESTROY(&ipf_global); + RW_DESTROY(&ipf_mutex); + RW_DESTROY(&ipf_frcache); + } +#ifdef IPFDEBUG + printf("IP Filter: ipfdetach() = %d\n", i); +#endif + return i; +} + + +#if 0 +/* + * OK, this is pretty scrappy code, but then it's essentially just here for + * debug purposes and that's it. Packets should not normally come through + * here, and if they do, well, we would like to see as much information as + * possible about them and what they claim to hold. + */ +void ipf_donotip(out, qif, q, m, mt, ip, off) + int out; + qif_t *qif; + queue_t *q; + mblk_t *m, *mt; + ip_t *ip; + size_t off; +{ + u_char *s, outb[256], *t; + int i, j; + + outb[0] = '\0'; + outb[1] = '\0'; + outb[2] = '\0'; + outb[3] = '\0'; + s = ip ? (u_char *)ip : outb; + if (!ip && (m == mt) && m->b_cont && (MTYPE(m) != M_DATA)) + m = m->b_cont; + + printf(" !IP %s:%d %d %p %p %p %d %p/%d %p/%d %p %d %d %p\n", + qif ? qif->qf_name : "?", out, qif->qf_hl, q, + q ? q->q_ptr : NULL, q ? q->q_qinfo : NULL, + mt->b_wptr - mt->b_rptr, m, MTYPE(m), mt, MTYPE(mt), m->b_rptr, + m->b_wptr - m->b_rptr, off, ip); + printf("%02x%02x%02x%02x\n", *s, *(s+1), *(s+2), *(s+3)); + while (m != mt) { + i = 0; + j = 256; + t = outb; + s = mt->b_rptr; + sprintf((char *)t, j, "%d:", MTYPE(mt)); + t += strlen((char *)t); + j -= strlen((char *)t); + for (; (j > 0) && (i < 100) && (s < mt->b_wptr); i++) { + sprintf((char *)t, j, "%02x%s", *s++, + ((i & 3) == 3) ? " " : ""); + t += ((i & 3) == 3) ? 3 : 2; + j -= ((i & 3) == 3) ? 3 : 2; + } + *t++ = '\n'; + *t = '\0'; + printf("%s", outb); + mt = mt->b_cont; + } + i = 0; + j = 256; + t = outb; + s = m->b_rptr; + sprintf((char *)t, j, "%d:", MTYPE(m)); + t += strlen((char *)t); + j -= strlen((char *)t); + for (; (j > 0) && (i < 100) && (s < m->b_wptr); i++) { + sprintf((char *)t, j, "%02x%s", *s++, + ((i & 3) == 3) ? " " : ""); + t += ((i & 3) == 3) ? 3 : 2; + j -= ((i & 3) == 3) ? 3 : 2; + } + *t++ = '\n'; + *t = '\0'; + printf("%s", outb); +} +#endif + + +/* + * look for bad consistancies between the list of interfaces the filter knows + * about and those which are currently configured. + */ +static int ipf_qifsync(ip, hlen, il, out, qif, mp) + ip_t *ip; + int hlen; + void *il; + int out; + qif_t *qif; + mblk_t **mp; +{ + register struct frentry *f; + register ipnat_t *np; + + ipfsync(&ipfmain, NULL); + return 0; +} + + +#ifdef IPFDEBUG +void printiri(iri) + irinfo_t *iri; +{ + printf("iri: ll_hdr_mp %p rfq %p stq %p\n", + iri->ir_ll_hdr_mp, iri->ir_rfq, iri->ir_stq); + printf("iri: ll_hdr_length %d ir_ill %p\n", + iri->ir_ll_hdr_length, iri->ir_ill); +} +#endif + + +int ipfsync() +{ + char name[8]; + qif_t *qif; + int i; + + for (i = 0; i < 10; i++) { + sprintf(name, sizeof(name), "lan%d", i); + spinlock(&pfil_rw); + qif = qif_iflookup(name, 0); + if (qif != NULL) + ipf_qifsync(NULL, 0, qif->qf_ill, -1, qif, NULL); + spinunlock(&pfil_rw); + } + return 0; +} + + +static int ipf_slowtimer() +{ + if (ipf_running <= 0) { + ipf_timer_id = NULL; + return; + } + + READ_ENTER(&ipf_global); + + ipf_frag_expire(); + ipf_state_expire(); + ipf_nat_expire(); + ipf_auth_expire(); + ipf_lookup_expire(); + ipf_rule_expire(); + ipf_ticks++; + ipf_timer_id = NULL; + if (ipf_running <= 0) { + RWLOCK_EXIT(&ipf_global); + return; + } + ipf_timer_id = mp_timeout(ipf_slowtimer, NULL, hz/2); + RWLOCK_EXIT(&ipf_global); +} + + +/* + * routines below for saving IP headers to buffer + */ +int ipfopen(dev, flag, dummy, mode) + dev_t dev; + int flag; + intptr_t dummy; + int mode; +{ + minor_t unit = getminor(dev); + int error; + +#ifdef IPFDEBUG + cmn_err(CE_CONT, "ipfopen(%x,%x,%x,%x)\n", dev, flag, dummy, mode); +#endif + if (IPL_LOGMAX < unit) { + error = ENXIO; + } else { + switch (unit) + { + case IPL_LOGIPF : + case IPL_LOGNAT : + case IPL_LOGSTATE : + case IPL_LOGAUTH : + case IPL_LOGLOOKUP : + case IPL_LOGSYNC : +#ifdef IPFILTER_SCAN + case IPL_LOGSCAN : +#endif + error = 0; + break; + default : + error = ENXIO; + break; + } + } + return error; +} + + +int ipfclose(dev, flag, mode) + dev_t dev; + int flag; + int mode; +{ + minor_t unit = getminor(dev); + +#ifdef IPFDEBUG + cmn_err(CE_CONT, "ipfclose(%x,%x,%x)\n", dev, flag, mode); +#endif + + if (ipf_running < 1) + return EIO; + + unit = (IPL_LOGMAX < unit) ? ENXIO : 0; + return unit; +} + + +#ifdef IPFILTER_LOG +/* + * ipfread/ipflog + * both of these must operate with at least splnet() lest they be + * called during packet processing and cause an inconsistancy to appear in + * the filter lists. + */ +int ipfread(dev, uio) + dev_t dev; + register struct uio *uio; +{ +#ifdef IPFDEBUG + cmn_err(CE_CONT, "ipfread(%x,%x)\n", dev, uio); +#endif + + if (ipf_running < 1) + return EIO; + + return ipflog_read(getminor(dev), uio); +} +#endif /* IPFILTER_LOG */ + + +#if 0 +/* + * ipfread/ipflog + * both of these must operate with at least splnet() lest they be + * called during packet processing and cause an inconsistancy to appear in + * the filter lists. + */ +int ipfwrite(dev, uio, cp) + dev_t dev; + register struct uio *uio; + cred_t *cp; +{ +#ifdef IPFDEBUG + cmn_err(CE_CONT, "ipfwrite(%x,%x,%x)\n", dev, uio, cp); +#endif + + if (ipf_running < 1) + return EIO; + + if (getminor(dev) != IPL_LOGSYNC) + return ENXIO; + return ipfsync_write(uio); +} +#endif /* IPFILTER_SYNC */ diff --git a/inet_addr.c b/inet_addr.c deleted file mode 100644 index e940280a280af..0000000000000 --- a/inet_addr.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * ++Copyright++ 1983, 1990, 1993 - * - - * Copyright (c) 1983, 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies, and that - * the name of Digital Equipment Corporation not be used in advertising or - * publicity pertaining to distribution of the document or software without - * specific, written prior permission. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT - * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - * - - * --Copyright-- - */ -#ifdef __STDC__ -# ifndef __P -# define __P(x) x -# endif -#else -# undef __P -# define __P(x) () -# undef const -# define const -#endif - -#if !defined(lint) -static const char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93"; -static const char rcsid[] = "@(#)$Id: inet_addr.c,v 2.1.4.2 2002/02/22 15:32:46 darrenr Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/param.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <ctype.h> - -int inet_aton __P((const char *, struct in_addr *)); - -/* - * Check whether "cp" is a valid ascii representation - * of an Internet address and convert to a binary address. - * Returns 1 if the address is valid, 0 if not. - * This replaces inet_addr, the return value from which - * cannot distinguish between failure and a local broadcast address. - */ -int -inet_aton(cp, addr) - register const char *cp; - struct in_addr *addr; -{ - register u_long val; - register int base, n; - register char c; - u_int parts[4]; - register u_int *pp = parts; - - c = *cp; - for (;;) { - /* - * Collect number up to ``.''. - * Values are specified as for C: - * 0x=hex, 0=octal, isdigit=decimal. - */ - if (!isdigit(c)) - return (0); - val = 0; base = 10; - if (c == '0') { - c = *++cp; - if (c == 'x' || c == 'X') - base = 16, c = *++cp; - else - base = 8; - } - for (;;) { - if (isascii(c) && isdigit(c)) { - val = (val * base) + (c - '0'); - c = *++cp; - } else if (base == 16 && isascii(c) && isxdigit(c)) { - val = (val << 4) | - (c + 10 - (islower(c) ? 'a' : 'A')); - c = *++cp; - } else - break; - } - if (c == '.') { - /* - * Internet format: - * a.b.c.d - * a.b.c (with c treated as 16 bits) - * a.b (with b treated as 24 bits) - */ - if (pp >= parts + 3) - return (0); - *pp++ = val; - c = *++cp; - } else - break; - } - /* - * Check for trailing characters. - */ - if (c != '\0' && (!isascii(c) || !isspace(c))) - return (0); - /* - * Concoct the address according to - * the number of parts specified. - */ - n = pp - parts + 1; - switch (n) { - - case 0: - return (0); /* initial nondigit */ - - case 1: /* a -- 32 bits */ - break; - - case 2: /* a.b -- 8.24 bits */ - if (val > 0xffffff) - return (0); - val |= parts[0] << 24; - break; - - case 3: /* a.b.c -- 8.8.16 bits */ - if (val > 0xffff) - return (0); - val |= (parts[0] << 24) | (parts[1] << 16); - break; - - case 4: /* a.b.c.d -- 8.8.8.8 bits */ - if (val > 0xff) - return (0); - val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); - break; - } - if (addr) - addr->s_addr = htonl(val); - return (1); -} - -/* these are compatibility routines, not needed on recent BSD releases */ - -/* - * Ascii internet address interpretation routine. - * The value returned is in network order. - */ -#if (defined(SOLARIS2) && (SOLARIS2 > 5)) || \ - (defined(IRIX) && (IRIX >= 605)) -in_addr_t -#else -u_long -#endif -inet_addr(cp) - register const char *cp; -{ - struct in_addr val; - - if (inet_aton(cp, &val)) - return (val.s_addr); - return (0xffffffff); -} diff --git a/ip_auth.c b/ip_auth.c index b91c2e6245c04..62cda7f6809ec 100644 --- a/ip_auth.c +++ b/ip_auth.c @@ -1,7 +1,5 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1998-2003 by Darren Reed & Guido van Rooij. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -19,6 +17,9 @@ #if !defined(_KERNEL) # include <stdio.h> # include <stdlib.h> +# ifdef _STDC_C99 +# include <stdbool.h> +# endif # include <string.h> # define _KERNEL # ifdef __OpenBSD__ @@ -52,7 +53,8 @@ struct file; # include <sys/stream.h> # include <sys/kmem.h> #endif -#if (_BSDI_VERSION >= 199802) || (__FreeBSD_version >= 400000) +#if (defined(_BSDI_VERSION) && (_BSDI_VERSION >= 199802)) || \ + (defined(__FreeBSD_version) &&(__FreeBSD_version >= 400000)) # include <sys/queue.h> #endif #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(bsdi) @@ -61,11 +63,14 @@ struct file; #if defined(_KERNEL) && defined(__NetBSD__) && (__NetBSD_Version__ >= 104000000) # include <sys/proc.h> #endif +#if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 400000) && \ + !defined(_KERNEL) +# include <stdbool.h> +#endif #include <net/if.h> #ifdef sun # include <net/af.h> #endif -#include <net/route.h> #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> @@ -119,69 +124,268 @@ extern struct ifqueue ipintrq; /* ip packet input queue */ /* END OF INCLUDES */ #if !defined(lint) -static const char rcsid[] = "@(#)Id: ip_auth.c,v 2.73.2.3 2004/08/26 11:25:21 darrenr Exp"; +static const char rcsid[] = "@(#)$Id$"; #endif -#if SOLARIS -extern kcondvar_t ipfauthwait; + +typedef struct ipf_auth_softc_s { +#if SOLARIS && defined(_KERNEL) + kcondvar_t ipf_auth_wait; #endif /* SOLARIS */ #if defined(linux) && defined(_KERNEL) -wait_queue_head_t fr_authnext_linux; + wait_queue_head_t ipf_auth_next_linux; #endif + ipfrwlock_t ipf_authlk; + ipfmutex_t ipf_auth_mx; + int ipf_auth_size; + int ipf_auth_used; + int ipf_auth_replies; + int ipf_auth_defaultage; + int ipf_auth_lock; + ipf_authstat_t ipf_auth_stats; + frauth_t *ipf_auth; + mb_t **ipf_auth_pkts; + int ipf_auth_start; + int ipf_auth_end; + int ipf_auth_next; + frauthent_t *ipf_auth_entries; + frentry_t *ipf_auth_ip; + frentry_t *ipf_auth_rules; +} ipf_auth_softc_t; + -int fr_authsize = FR_NUMAUTH; -int fr_authused = 0; -int fr_defaultauthage = 600; -int fr_auth_lock = 0; -int fr_auth_init = 0; -fr_authstat_t fr_authstats; -static frauth_t *fr_auth = NULL; -mb_t **fr_authpkts = NULL; -int fr_authstart = 0, fr_authend = 0, fr_authnext = 0; -frauthent_t *fae_list = NULL; -frentry_t *ipauth = NULL, - *fr_authlist = NULL; - - -int fr_authinit() +static void ipf_auth_deref __P((frauthent_t **)); +static void ipf_auth_deref_unlocked __P((ipf_auth_softc_t *, frauthent_t **)); +static int ipf_auth_geniter __P((ipf_main_softc_t *, ipftoken_t *, + ipfgeniter_t *, ipfobj_t *)); +static int ipf_auth_reply __P((ipf_main_softc_t *, ipf_auth_softc_t *, char *)); +static int ipf_auth_wait __P((ipf_main_softc_t *, ipf_auth_softc_t *, char *)); +static int ipf_auth_flush __P((void *)); + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_auth_main_load */ +/* Returns: int - 0 == success, else error */ +/* Parameters: None */ +/* */ +/* A null-op function that exists as a placeholder so that the flow in */ +/* other functions is obvious. */ +/* ------------------------------------------------------------------------ */ +int +ipf_auth_main_load() { - KMALLOCS(fr_auth, frauth_t *, fr_authsize * sizeof(*fr_auth)); - if (fr_auth != NULL) - bzero((char *)fr_auth, fr_authsize * sizeof(*fr_auth)); - else - return -1; + return 0; +} - KMALLOCS(fr_authpkts, mb_t **, fr_authsize * sizeof(*fr_authpkts)); - if (fr_authpkts != NULL) - bzero((char *)fr_authpkts, fr_authsize * sizeof(*fr_authpkts)); - else - return -2; - MUTEX_INIT(&ipf_authmx, "ipf auth log mutex"); - RWLOCK_INIT(&ipf_auth, "ipf IP User-Auth rwlock"); +/* ------------------------------------------------------------------------ */ +/* Function: ipf_auth_main_unload */ +/* Returns: int - 0 == success, else error */ +/* Parameters: None */ +/* */ +/* A null-op function that exists as a placeholder so that the flow in */ +/* other functions is obvious. */ +/* ------------------------------------------------------------------------ */ +int +ipf_auth_main_unload() +{ + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_auth_soft_create */ +/* Returns: int - NULL = failure, else success */ +/* Parameters: softc(I) - pointer to soft context data */ +/* */ +/* Create a structre to store all of the run-time data for packet auth in */ +/* and initialise some fields to their defaults. */ +/* ------------------------------------------------------------------------ */ +void * +ipf_auth_soft_create(softc) + ipf_main_softc_t *softc; +{ + ipf_auth_softc_t *softa; + + KMALLOC(softa, ipf_auth_softc_t *); + if (softa == NULL) + return NULL; + + bzero((char *)softa, sizeof(*softa)); + + softa->ipf_auth_size = FR_NUMAUTH; + softa->ipf_auth_defaultage = 600; + + RWLOCK_INIT(&softa->ipf_authlk, "ipf IP User-Auth rwlock"); + MUTEX_INIT(&softa->ipf_auth_mx, "ipf auth log mutex"); #if SOLARIS && defined(_KERNEL) - cv_init(&ipfauthwait, "ipf auth condvar", CV_DRIVER, NULL); + cv_init(&softa->ipf_auth_wait, "ipf auth condvar", CV_DRIVER, NULL); #endif + + return softa; +} + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_auth_soft_init */ +/* Returns: int - 0 == success, else error */ +/* Parameters: softc(I) - pointer to soft context data */ +/* arg(I) - opaque pointer to auth context data */ +/* */ +/* Allocate memory and initialise data structures used in handling auth */ +/* rules. */ +/* ------------------------------------------------------------------------ */ +int +ipf_auth_soft_init(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_auth_softc_t *softa = arg; + + KMALLOCS(softa->ipf_auth, frauth_t *, + softa->ipf_auth_size * sizeof(*softa->ipf_auth)); + if (softa->ipf_auth == NULL) + return -1; + bzero((char *)softa->ipf_auth, + softa->ipf_auth_size * sizeof(*softa->ipf_auth)); + + KMALLOCS(softa->ipf_auth_pkts, mb_t **, + softa->ipf_auth_size * sizeof(*softa->ipf_auth_pkts)); + if (softa->ipf_auth_pkts == NULL) + return -2; + bzero((char *)softa->ipf_auth_pkts, + softa->ipf_auth_size * sizeof(*softa->ipf_auth_pkts)); + #if defined(linux) && defined(_KERNEL) - init_waitqueue_head(&fr_authnext_linux); + init_waitqueue_head(&softa->ipf_auth_next_linux); #endif - fr_auth_init = 1; + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_auth_soft_fini */ +/* Returns: int - 0 == success, else error */ +/* Parameters: softc(I) - pointer to soft context data */ +/* arg(I) - opaque pointer to auth context data */ +/* */ +/* Free all network buffer memory used to keep saved packets that have been */ +/* connectedd to the soft soft context structure *but* do not free that: it */ +/* is free'd by _destroy(). */ +/* ------------------------------------------------------------------------ */ +int +ipf_auth_soft_fini(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_auth_softc_t *softa = arg; + frauthent_t *fae, **faep; + frentry_t *fr, **frp; + mb_t *m; + int i; + + if (softa->ipf_auth != NULL) { + KFREES(softa->ipf_auth, + softa->ipf_auth_size * sizeof(*softa->ipf_auth)); + softa->ipf_auth = NULL; + } + + if (softa->ipf_auth_pkts != NULL) { + for (i = 0; i < softa->ipf_auth_size; i++) { + m = softa->ipf_auth_pkts[i]; + if (m != NULL) { + FREE_MB_T(m); + softa->ipf_auth_pkts[i] = NULL; + } + } + KFREES(softa->ipf_auth_pkts, + softa->ipf_auth_size * sizeof(*softa->ipf_auth_pkts)); + softa->ipf_auth_pkts = NULL; + } + + faep = &softa->ipf_auth_entries; + while ((fae = *faep) != NULL) { + *faep = fae->fae_next; + KFREE(fae); + } + softa->ipf_auth_ip = NULL; + + if (softa->ipf_auth_rules != NULL) { + for (frp = &softa->ipf_auth_rules; ((fr = *frp) != NULL); ) { + if (fr->fr_ref == 1) { + *frp = fr->fr_next; + MUTEX_DESTROY(&fr->fr_lock); + KFREE(fr); + } else + frp = &fr->fr_next; + } + } return 0; } -/* - * Check if a packet has authorization. If the packet is found to match an - * authorization result and that would result in a feedback loop (i.e. it - * will end up returning FR_AUTH) then return FR_BLOCK instead. - */ -frentry_t *fr_checkauth(fin, passp) -fr_info_t *fin; -u_32_t *passp; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_auth_soft_destroy */ +/* Returns: void */ +/* Parameters: softc(I) - pointer to soft context data */ +/* arg(I) - opaque pointer to auth context data */ +/* */ +/* Undo what was done in _create() - i.e. free the soft context data. */ +/* ------------------------------------------------------------------------ */ +void +ipf_auth_soft_destroy(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_auth_softc_t *softa = arg; + +# if SOLARIS && defined(_KERNEL) + cv_destroy(&softa->ipf_auth_wait); +# endif + MUTEX_DESTROY(&softa->ipf_auth_mx); + RW_DESTROY(&softa->ipf_authlk); + + KFREE(softa); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_auth_setlock */ +/* Returns: void */ +/* Paramters: arg(I) - pointer to soft context data */ +/* tmp(I) - value to assign to auth lock */ +/* */ +/* ------------------------------------------------------------------------ */ +void +ipf_auth_setlock(arg, tmp) + void *arg; + int tmp; +{ + ipf_auth_softc_t *softa = arg; + + softa->ipf_auth_lock = tmp; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_auth_check */ +/* Returns: frentry_t* - pointer to ipf rule if match found, else NULL */ +/* Parameters: fin(I) - pointer to ipftoken structure */ +/* passp(I) - pointer to ipfgeniter structure */ +/* */ +/* Check if a packet has authorization. If the packet is found to match an */ +/* authorization result and that would result in a feedback loop (i.e. it */ +/* will end up returning FR_AUTH) then return FR_BLOCK instead. */ +/* ------------------------------------------------------------------------ */ +frentry_t * +ipf_auth_check(fin, passp) + fr_info_t *fin; + u_32_t *passp; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_auth_softc_t *softa = softc->ipf_auth_soft; frentry_t *fr; frauth_t *fra; u_32_t pass; @@ -189,27 +393,29 @@ u_32_t *passp; ip_t *ip; int i; - if (fr_auth_lock || !fr_authused) + if (softa->ipf_auth_lock || !softa->ipf_auth_used) return NULL; ip = fin->fin_ip; id = ip->ip_id; - READ_ENTER(&ipf_auth); - for (i = fr_authstart; i != fr_authend; ) { + READ_ENTER(&softa->ipf_authlk); + for (i = softa->ipf_auth_start; i != softa->ipf_auth_end; ) { /* * index becomes -2 only after an SIOCAUTHW. Check this in * case the same packet gets sent again and it hasn't yet been * auth'd. */ - fra = fr_auth + i; + fra = softa->ipf_auth + i; if ((fra->fra_index == -2) && (id == fra->fra_info.fin_id) && !bcmp((char *)fin, (char *)&fra->fra_info, FI_CSIZE)) { /* * Avoid feedback loop. */ - if (!(pass = fra->fra_pass) || (FR_ISAUTH(pass))) + if (!(pass = fra->fra_pass) || (FR_ISAUTH(pass))) { pass = FR_BLOCK; + fin->fin_reason = FRB_AUTHFEEDBACK; + } /* * Create a dummy rule for the stateful checking to * use and return. Zero out any values we don't @@ -229,62 +435,80 @@ u_32_t *passp; fr->fr_ifas[1] = NULL; fr->fr_ifas[2] = NULL; fr->fr_ifas[3] = NULL; + MUTEX_INIT(&fr->fr_lock, + "ipf auth rule"); } } else fr = fra->fra_info.fin_fr; fin->fin_fr = fr; - RWLOCK_EXIT(&ipf_auth); - WRITE_ENTER(&ipf_auth); + fin->fin_flx |= fra->fra_flx; + RWLOCK_EXIT(&softa->ipf_authlk); + + WRITE_ENTER(&softa->ipf_authlk); + /* + * ipf_auth_rules is populated with the rules malloc'd + * above and only those. + */ if ((fr != NULL) && (fr != fra->fra_info.fin_fr)) { - fr->fr_next = fr_authlist; - fr_authlist = fr; + fr->fr_next = softa->ipf_auth_rules; + softa->ipf_auth_rules = fr; } - fr_authstats.fas_hits++; + softa->ipf_auth_stats.fas_hits++; fra->fra_index = -1; - fr_authused--; - if (i == fr_authstart) { + softa->ipf_auth_used--; + softa->ipf_auth_replies--; + if (i == softa->ipf_auth_start) { while (fra->fra_index == -1) { i++; fra++; - if (i == fr_authsize) { + if (i == softa->ipf_auth_size) { i = 0; - fra = fr_auth; + fra = softa->ipf_auth; } - fr_authstart = i; - if (i == fr_authend) + softa->ipf_auth_start = i; + if (i == softa->ipf_auth_end) break; } - if (fr_authstart == fr_authend) { - fr_authnext = 0; - fr_authstart = fr_authend = 0; + if (softa->ipf_auth_start == + softa->ipf_auth_end) { + softa->ipf_auth_next = 0; + softa->ipf_auth_start = 0; + softa->ipf_auth_end = 0; } } - RWLOCK_EXIT(&ipf_auth); + RWLOCK_EXIT(&softa->ipf_authlk); if (passp != NULL) *passp = pass; - ATOMIC_INC64(fr_authstats.fas_hits); + softa->ipf_auth_stats.fas_hits++; return fr; } i++; - if (i == fr_authsize) + if (i == softa->ipf_auth_size) i = 0; } - fr_authstats.fas_miss++; - RWLOCK_EXIT(&ipf_auth); - ATOMIC_INC64(fr_authstats.fas_miss); + RWLOCK_EXIT(&softa->ipf_authlk); + softa->ipf_auth_stats.fas_miss++; return NULL; } -/* - * Check if we have room in the auth array to hold details for another packet. - * If we do, store it and wake up any user programs which are waiting to - * hear about these events. - */ -int fr_newauth(m, fin) -mb_t *m; -fr_info_t *fin; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_auth_new */ +/* Returns: int - 1 == success, 0 = did not put packet on auth queue */ +/* Parameters: m(I) - pointer to mb_t with packet in it */ +/* fin(I) - pointer to packet information */ +/* */ +/* Check if we have room in the auth array to hold details for another */ +/* packet. If we do, store it and wake up any user programs which are */ +/* waiting to hear about these events. */ +/* ------------------------------------------------------------------------ */ +int +ipf_auth_new(m, fin) + mb_t *m; + fr_info_t *fin; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_auth_softc_t *softa = softc->ipf_auth_soft; #if defined(_KERNEL) && defined(MENTAT) qpktinfo_t *qpi = fin->fin_qpi; #endif @@ -294,34 +518,33 @@ fr_info_t *fin; #endif int i; - if (fr_auth_lock) + if (softa->ipf_auth_lock) return 0; - WRITE_ENTER(&ipf_auth); - if (fr_authstart > fr_authend) { - fr_authstats.fas_nospace++; - RWLOCK_EXIT(&ipf_auth); + WRITE_ENTER(&softa->ipf_authlk); + if (((softa->ipf_auth_end + 1) % softa->ipf_auth_size) == + softa->ipf_auth_start) { + softa->ipf_auth_stats.fas_nospace++; + RWLOCK_EXIT(&softa->ipf_authlk); return 0; - } else { - if (fr_authused == fr_authsize) { - fr_authstats.fas_nospace++; - RWLOCK_EXIT(&ipf_auth); - return 0; - } } - fr_authstats.fas_added++; - fr_authused++; - i = fr_authend++; - if (fr_authend == fr_authsize) - fr_authend = 0; - RWLOCK_EXIT(&ipf_auth); + softa->ipf_auth_stats.fas_added++; + softa->ipf_auth_used++; + i = softa->ipf_auth_end++; + if (softa->ipf_auth_end == softa->ipf_auth_size) + softa->ipf_auth_end = 0; - fra = fr_auth + i; + fra = softa->ipf_auth + i; fra->fra_index = i; - fra->fra_pass = 0; - fra->fra_age = fr_defaultauthage; + if (fin->fin_fr != NULL) + fra->fra_pass = fin->fin_fr->fr_flags; + else + fra->fra_pass = 0; + fra->fra_age = softa->ipf_auth_defaultage; bcopy((char *)fin, (char *)&fra->fra_info, sizeof(*fin)); + fra->fra_flx = fra->fra_info.fin_flx & (FI_STATE|FI_NATED); + fra->fra_info.fin_flx &= ~(FI_STATE|FI_NATED); #if !defined(sparc) && !defined(m68k) /* * No need to copyback here as we want to undo the changes, not keep @@ -341,254 +564,124 @@ fr_info_t *fin; } #endif #if SOLARIS && defined(_KERNEL) + COPYIFNAME(fin->fin_v, fin->fin_ifp, fra->fra_info.fin_ifname); m->b_rptr -= qpi->qpi_off; - fr_authpkts[i] = *(mblk_t **)fin->fin_mp; fra->fra_q = qpi->qpi_q; /* The queue can disappear! */ - cv_signal(&ipfauthwait); + fra->fra_m = *fin->fin_mp; + fra->fra_info.fin_mp = &fra->fra_m; + softa->ipf_auth_pkts[i] = *(mblk_t **)fin->fin_mp; + RWLOCK_EXIT(&softa->ipf_authlk); + cv_signal(&softa->ipf_auth_wait); + pollwakeup(&softc->ipf_poll_head[IPL_LOGAUTH], POLLIN|POLLRDNORM); #else -# if defined(BSD) && !defined(sparc) && (BSD >= 199306) - if (!fin->fin_out) { - ip->ip_len = htons(ip->ip_len); - ip->ip_off = htons(ip->ip_off); - } -# endif - fr_authpkts[i] = m; - WAKEUP(&fr_authnext,0); + softa->ipf_auth_pkts[i] = m; + RWLOCK_EXIT(&softa->ipf_authlk); + WAKEUP(&softa->ipf_auth_next, 0); #endif return 1; } -int fr_auth_ioctl(data, cmd, mode) -caddr_t data; -ioctlcmd_t cmd; -int mode; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_auth_ioctl */ +/* Returns: int - 0 == success, else error */ +/* Parameters: data(IO) - pointer to ioctl data */ +/* cmd(I) - ioctl command */ +/* mode(I) - mode flags associated with open descriptor */ +/* uid(I) - uid associatd with application making the call */ +/* ctx(I) - pointer for context */ +/* */ +/* This function handles all of the ioctls recognised by the auth component */ +/* in IPFilter - ie ioctls called on an open fd for /dev/ipf_auth */ +/* ------------------------------------------------------------------------ */ +int +ipf_auth_ioctl(softc, data, cmd, mode, uid, ctx) + ipf_main_softc_t *softc; + caddr_t data; + ioctlcmd_t cmd; + int mode, uid; + void *ctx; { - mb_t *m; -#if defined(_KERNEL) && !defined(MENTAT) && !defined(linux) && \ - (!defined(__FreeBSD_version) || (__FreeBSD_version < 501000)) - struct ifqueue *ifq; -# ifdef USE_SPL - int s; -# endif /* USE_SPL */ -#endif - frauth_t auth, *au = &auth, *fra; - int i, error = 0, len; - char *t; + ipf_auth_softc_t *softa = softc->ipf_auth_soft; + int error = 0, i; + SPL_INT(s); switch (cmd) { + case SIOCGENITER : + { + ipftoken_t *token; + ipfgeniter_t iter; + ipfobj_t obj; + + error = ipf_inobj(softc, data, &obj, &iter, IPFOBJ_GENITER); + if (error != 0) + break; + + SPL_SCHED(s); + token = ipf_token_find(softc, IPFGENITER_AUTH, uid, ctx); + if (token != NULL) + error = ipf_auth_geniter(softc, token, &iter, &obj); + else { + WRITE_ENTER(&softc->ipf_tokens); + ipf_token_deref(softc, token); + RWLOCK_EXIT(&softc->ipf_tokens); + IPFERROR(10001); + error = ESRCH; + } + SPL_X(s); + + break; + } + + case SIOCADAFR : + case SIOCRMAFR : + if (!(mode & FWRITE)) { + IPFERROR(10002); + error = EPERM; + } else + error = frrequest(softc, IPL_LOGAUTH, cmd, data, + softc->ipf_active, 1); + break; + case SIOCSTLCK : if (!(mode & FWRITE)) { + IPFERROR(10003); error = EPERM; - break; + } else { + error = ipf_lock(data, &softa->ipf_auth_lock); } - fr_lock(data, &fr_auth_lock); break; case SIOCATHST: - fr_authstats.fas_faelist = fae_list; - error = fr_outobj(data, &fr_authstats, IPFOBJ_AUTHSTAT); + softa->ipf_auth_stats.fas_faelist = softa->ipf_auth_entries; + error = ipf_outobj(softc, data, &softa->ipf_auth_stats, + IPFOBJ_AUTHSTAT); break; case SIOCIPFFL: SPL_NET(s); - WRITE_ENTER(&ipf_auth); - i = fr_authflush(); - RWLOCK_EXIT(&ipf_auth); + WRITE_ENTER(&softa->ipf_authlk); + i = ipf_auth_flush(softa); + RWLOCK_EXIT(&softa->ipf_authlk); SPL_X(s); - error = copyoutptr((char *)&i, data, sizeof(i)); + error = BCOPYOUT(&i, data, sizeof(i)); + if (error != 0) { + IPFERROR(10004); + error = EFAULT; + } break; case SIOCAUTHW: -fr_authioctlloop: - error = fr_inobj(data, au, IPFOBJ_FRAUTH); - READ_ENTER(&ipf_auth); - if ((fr_authnext != fr_authend) && fr_authpkts[fr_authnext]) { - error = fr_outobj(data, &fr_auth[fr_authnext], - IPFOBJ_FRAUTH); - if (auth.fra_len != 0 && auth.fra_buf != NULL) { - /* - * Copy packet contents out to user space if - * requested. Bail on an error. - */ - m = fr_authpkts[fr_authnext]; - len = MSGDSIZE(m); - if (len > auth.fra_len) - len = auth.fra_len; - auth.fra_len = len; - for (t = auth.fra_buf; m && (len > 0); ) { - i = MIN(M_LEN(m), len); - error = copyoutptr(MTOD(m, char *), - t, i); - len -= i; - t += i; - if (error != 0) - break; - } - } - RWLOCK_EXIT(&ipf_auth); - if (error != 0) - break; - SPL_NET(s); - WRITE_ENTER(&ipf_auth); - fr_authnext++; - if (fr_authnext == fr_authsize) - fr_authnext = 0; - RWLOCK_EXIT(&ipf_auth); - SPL_X(s); - return 0; - } - RWLOCK_EXIT(&ipf_auth); - /* - * We exit ipf_global here because a program that enters in - * here will have a lock on it and goto sleep having this lock. - * If someone were to do an 'ipf -D' the system would then - * deadlock. The catch with releasing it here is that the - * caller of this function expects it to be held when we - * return so we have to reacquire it in here. - */ - RWLOCK_EXIT(&ipf_global); - - MUTEX_ENTER(&ipf_authmx); -#ifdef _KERNEL -# if SOLARIS - error = 0; - if (!cv_wait_sig(&ipfauthwait, &ipf_authmx.ipf_lk)) - error = EINTR; -# else /* SOLARIS */ -# ifdef __hpux - { - lock_t *l; - - l = get_sleep_lock(&fr_authnext); - error = sleep(&fr_authnext, PZERO+1); - spinunlock(l); - } -# else -# ifdef __osf__ - error = mpsleep(&fr_authnext, PSUSP|PCATCH, "fr_authnext", 0, - &ipf_authmx, MS_LOCK_SIMPLE); -# else - error = SLEEP(&fr_authnext, "fr_authnext"); -# endif /* __osf__ */ -# endif /* __hpux */ -# endif /* SOLARIS */ -#endif - MUTEX_EXIT(&ipf_authmx); - READ_ENTER(&ipf_global); - if (error == 0) { - READ_ENTER(&ipf_auth); - goto fr_authioctlloop; - } + error = ipf_auth_wait(softc, softa, data); break; case SIOCAUTHR: - error = fr_inobj(data, &auth, IPFOBJ_FRAUTH); - if (error != 0) - return error; - SPL_NET(s); - WRITE_ENTER(&ipf_auth); - i = au->fra_index; - fra = fr_auth + i; - if ((i < 0) || (i >= fr_authsize) || - (fra->fra_info.fin_id != au->fra_info.fin_id)) { - RWLOCK_EXIT(&ipf_auth); - SPL_X(s); - return ESRCH; - } - m = fr_authpkts[i]; - fra->fra_index = -2; - fra->fra_pass = au->fra_pass; - fr_authpkts[i] = NULL; - RWLOCK_EXIT(&ipf_auth); -#ifdef _KERNEL - if ((m != NULL) && (au->fra_info.fin_out != 0)) { -# ifdef MENTAT - error = !putq(fra->fra_q, m); -# else /* MENTAT */ -# ifdef linux -# else -# if (_BSDI_VERSION >= 199802) || defined(__OpenBSD__) || \ - (defined(__sgi) && (IRIX >= 60500) || \ - (defined(__FreeBSD__) && (__FreeBSD_version >= 470102))) - error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL, - NULL); -# else - error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL); -# endif -# endif /* Linux */ -# endif /* MENTAT */ - if (error != 0) - fr_authstats.fas_sendfail++; - else - fr_authstats.fas_sendok++; - } else if (m) { -# ifdef MENTAT - error = !putq(fra->fra_q, m); -# else /* MENTAT */ -# ifdef linux -# else -# if __FreeBSD_version >= 501000 - netisr_dispatch(NETISR_IP, m); -# else -# if IRIX >= 60516 - ifq = &((struct ifnet *)fra->fra_info.fin_ifp)->if_snd; -# else - ifq = &ipintrq; -# endif - if (IF_QFULL(ifq)) { - IF_DROP(ifq); - FREE_MB_T(m); - error = ENOBUFS; - } else { - IF_ENQUEUE(ifq, m); -# if IRIX < 60500 - schednetisr(NETISR_IP); -# endif - } -# endif -# endif /* Linux */ -# endif /* MENTAT */ - if (error != 0) - fr_authstats.fas_quefail++; - else - fr_authstats.fas_queok++; - } else - error = EINVAL; -# ifdef MENTAT - if (error != 0) - error = EINVAL; -# else /* MENTAT */ - /* - * If we experience an error which will result in the packet - * not being processed, make sure we advance to the next one. - */ - if (error == ENOBUFS) { - fr_authused--; - fra->fra_index = -1; - fra->fra_pass = 0; - if (i == fr_authstart) { - while (fra->fra_index == -1) { - i++; - if (i == fr_authsize) - i = 0; - fr_authstart = i; - if (i == fr_authend) - break; - } - if (fr_authstart == fr_authend) { - fr_authnext = 0; - fr_authstart = fr_authend = 0; - } - } - } -# endif /* MENTAT */ -#endif /* _KERNEL */ - SPL_X(s); + error = ipf_auth_reply(softc, softa, data); break; default : + IPFERROR(10005); error = EINVAL; break; } @@ -596,132 +689,101 @@ fr_authioctlloop: } -/* - * Free all network buffer memory used to keep saved packets. - */ -void fr_authunload() +/* ------------------------------------------------------------------------ */ +/* Function: ipf_auth_expire */ +/* Returns: None */ +/* Parameters: None */ +/* */ +/* Slowly expire held auth records. Timeouts are set in expectation of */ +/* this being called twice per second. */ +/* ------------------------------------------------------------------------ */ +void +ipf_auth_expire(softc) + ipf_main_softc_t *softc; { - register int i; - register frauthent_t *fae, **faep; + ipf_auth_softc_t *softa = softc->ipf_auth_soft; + frauthent_t *fae, **faep; frentry_t *fr, **frp; + frauth_t *fra; mb_t *m; + int i; + SPL_INT(s); - if (fr_auth != NULL) { - KFREES(fr_auth, fr_authsize * sizeof(*fr_auth)); - fr_auth = NULL; - } - - if (fr_authpkts != NULL) { - for (i = 0; i < fr_authsize; i++) { - m = fr_authpkts[i]; - if (m != NULL) { - FREE_MB_T(m); - fr_authpkts[i] = NULL; - } - } - KFREES(fr_authpkts, fr_authsize * sizeof(*fr_authpkts)); - fr_authpkts = NULL; - } - - faep = &fae_list; - while ((fae = *faep) != NULL) { - *faep = fae->fae_next; - KFREE(fae); - } - ipauth = NULL; - - if (fr_authlist != NULL) { - for (frp = &fr_authlist; ((fr = *frp) != NULL); ) { - if (fr->fr_ref == 1) { - *frp = fr->fr_next; - KFREE(fr); - } else - frp = &fr->fr_next; - } - } - - if (fr_auth_init == 1) { -# if SOLARIS && defined(_KERNEL) - cv_destroy(&ipfauthwait); -# endif - MUTEX_DESTROY(&ipf_authmx); - RW_DESTROY(&ipf_auth); - - fr_auth_init = 0; - } -} - - -/* - * Slowly expire held auth records. Timeouts are set - * in expectation of this being called twice per second. - */ -void fr_authexpire() -{ - register int i; - register frauth_t *fra; - register frauthent_t *fae, **faep; - register frentry_t *fr, **frp; - mb_t *m; -# if !defined(MENAT) && defined(_KERNEL) && defined(USE_SPL) - int s; -# endif - - if (fr_auth_lock) + if (softa->ipf_auth_lock) return; - SPL_NET(s); - WRITE_ENTER(&ipf_auth); - for (i = 0, fra = fr_auth; i < fr_authsize; i++, fra++) { + WRITE_ENTER(&softa->ipf_authlk); + for (i = 0, fra = softa->ipf_auth; i < softa->ipf_auth_size; + i++, fra++) { fra->fra_age--; - if ((fra->fra_age == 0) && (m = fr_authpkts[i])) { - FREE_MB_T(m); - fr_authpkts[i] = NULL; - fr_auth[i].fra_index = -1; - fr_authstats.fas_expire++; - fr_authused--; + if ((fra->fra_age == 0) && + (softa->ipf_auth[i].fra_index != -1)) { + if ((m = softa->ipf_auth_pkts[i]) != NULL) { + FREE_MB_T(m); + softa->ipf_auth_pkts[i] = NULL; + } else if (softa->ipf_auth[i].fra_index == -2) { + softa->ipf_auth_replies--; + } + softa->ipf_auth[i].fra_index = -1; + softa->ipf_auth_stats.fas_expire++; + softa->ipf_auth_used--; } } - for (faep = &fae_list; ((fae = *faep) != NULL); ) { + /* + * Expire pre-auth rules + */ + for (faep = &softa->ipf_auth_entries; ((fae = *faep) != NULL); ) { fae->fae_age--; if (fae->fae_age == 0) { - *faep = fae->fae_next; - KFREE(fae); - fr_authstats.fas_expire++; + ipf_auth_deref(&fae); + softa->ipf_auth_stats.fas_expire++; } else faep = &fae->fae_next; } - if (fae_list != NULL) - ipauth = &fae_list->fae_fr; + if (softa->ipf_auth_entries != NULL) + softa->ipf_auth_ip = &softa->ipf_auth_entries->fae_fr; else - ipauth = NULL; + softa->ipf_auth_ip = NULL; - for (frp = &fr_authlist; ((fr = *frp) != NULL); ) { + for (frp = &softa->ipf_auth_rules; ((fr = *frp) != NULL); ) { if (fr->fr_ref == 1) { *frp = fr->fr_next; + MUTEX_DESTROY(&fr->fr_lock); KFREE(fr); } else frp = &fr->fr_next; } - RWLOCK_EXIT(&ipf_auth); + RWLOCK_EXIT(&softa->ipf_authlk); SPL_X(s); } -int fr_preauthcmd(cmd, fr, frptr) -ioctlcmd_t cmd; -frentry_t *fr, **frptr; + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_auth_precmd */ +/* Returns: int - 0 == success, else error */ +/* Parameters: cmd(I) - ioctl command for rule */ +/* fr(I) - pointer to ipf rule */ +/* fptr(I) - pointer to caller's 'fr' */ +/* */ +/* ------------------------------------------------------------------------ */ +int +ipf_auth_precmd(softc, cmd, fr, frptr) + ipf_main_softc_t *softc; + ioctlcmd_t cmd; + frentry_t *fr, **frptr; { + ipf_auth_softc_t *softa = softc->ipf_auth_soft; frauthent_t *fae, **faep; int error = 0; -# if !defined(MENAT) && defined(_KERNEL) && defined(USE_SPL) - int s; -#endif + SPL_INT(s); - if ((cmd != SIOCADAFR) && (cmd != SIOCRMAFR)) + if ((cmd != SIOCADAFR) && (cmd != SIOCRMAFR)) { + IPFERROR(10006); return EIO; - - for (faep = &fae_list; ((fae = *faep) != NULL); ) { + } + + for (faep = &softa->ipf_auth_entries; ((fae = *faep) != NULL); ) { if (&fae->fae_fr == fr) break; else @@ -729,17 +791,22 @@ frentry_t *fr, **frptr; } if (cmd == (ioctlcmd_t)SIOCRMAFR) { - if (fr == NULL || frptr == NULL) + if (fr == NULL || frptr == NULL) { + IPFERROR(10007); error = EINVAL; - else if (fae == NULL) + + } else if (fae == NULL) { + IPFERROR(10008); error = ESRCH; - else { + + } else { SPL_NET(s); - WRITE_ENTER(&ipf_auth); + WRITE_ENTER(&softa->ipf_authlk); *faep = fae->fae_next; - if (ipauth == &fae->fae_fr) - ipauth = fae_list ? &fae_list->fae_fr : NULL; - RWLOCK_EXIT(&ipf_auth); + if (softa->ipf_auth_ip == &fae->fae_fr) + softa->ipf_auth_ip = softa->ipf_auth_entries ? + &softa->ipf_auth_entries->fae_fr : NULL; + RWLOCK_EXIT(&softa->ipf_authlk); SPL_X(s); KFREE(fae); @@ -750,55 +817,488 @@ frentry_t *fr, **frptr; bcopy((char *)fr, (char *)&fae->fae_fr, sizeof(*fr)); SPL_NET(s); - WRITE_ENTER(&ipf_auth); - fae->fae_age = fr_defaultauthage; + WRITE_ENTER(&softa->ipf_authlk); + fae->fae_age = softa->ipf_auth_defaultage; fae->fae_fr.fr_hits = 0; fae->fae_fr.fr_next = *frptr; + fae->fae_ref = 1; *frptr = &fae->fae_fr; fae->fae_next = *faep; *faep = fae; - ipauth = &fae_list->fae_fr; - RWLOCK_EXIT(&ipf_auth); + softa->ipf_auth_ip = &softa->ipf_auth_entries->fae_fr; + RWLOCK_EXIT(&softa->ipf_authlk); SPL_X(s); - } else + } else { + IPFERROR(10009); error = ENOMEM; - } else + } + } else { + IPFERROR(10010); error = EINVAL; + } return error; } -/* - * Flush held packets. - * Must already be properly SPL'ed and Locked on &ipf_auth. - * - */ -int fr_authflush() +/* ------------------------------------------------------------------------ */ +/* Function: ipf_auth_flush */ +/* Returns: int - number of auth entries flushed */ +/* Parameters: None */ +/* Locks: WRITE(ipf_authlk) */ +/* */ +/* This function flushs the ipf_auth_pkts array of any packet data with */ +/* references still there. */ +/* It is expected that the caller has already acquired the correct locks or */ +/* set the priority level correctly for this to block out other code paths */ +/* into these data structures. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_auth_flush(arg) + void *arg; { - register int i, num_flushed; + ipf_auth_softc_t *softa = arg; + int i, num_flushed; mb_t *m; - if (fr_auth_lock) + if (softa->ipf_auth_lock) return -1; num_flushed = 0; - for (i = 0 ; i < fr_authsize; i++) { - m = fr_authpkts[i]; - if (m != NULL) { - FREE_MB_T(m); - fr_authpkts[i] = NULL; - fr_auth[i].fra_index = -1; + for (i = 0 ; i < softa->ipf_auth_size; i++) { + if (softa->ipf_auth[i].fra_index != -1) { + m = softa->ipf_auth_pkts[i]; + if (m != NULL) { + FREE_MB_T(m); + softa->ipf_auth_pkts[i] = NULL; + } + + softa->ipf_auth[i].fra_index = -1; /* perhaps add & use a flush counter inst.*/ - fr_authstats.fas_expire++; - fr_authused--; + softa->ipf_auth_stats.fas_expire++; num_flushed++; } } - fr_authstart = 0; - fr_authend = 0; - fr_authnext = 0; + softa->ipf_auth_start = 0; + softa->ipf_auth_end = 0; + softa->ipf_auth_next = 0; + softa->ipf_auth_used = 0; + softa->ipf_auth_replies = 0; return num_flushed; } + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_auth_waiting */ +/* Returns: int - number of packets in the auth queue */ +/* Parameters: None */ +/* */ +/* Simple truth check to see if there are any packets waiting in the auth */ +/* queue. */ +/* ------------------------------------------------------------------------ */ +int +ipf_auth_waiting(softc) + ipf_main_softc_t *softc; +{ + ipf_auth_softc_t *softa = softc->ipf_auth_soft; + + return (softa->ipf_auth_used != 0); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_auth_geniter */ +/* Returns: int - 0 == success, else error */ +/* Parameters: token(I) - pointer to ipftoken structure */ +/* itp(I) - pointer to ipfgeniter structure */ +/* objp(I) - pointer to ipf object destription */ +/* */ +/* Iterate through the list of entries in the auth queue list. */ +/* objp is used here to get the location of where to do the copy out to. */ +/* Stomping over various fields with new information will not harm anything */ +/* ------------------------------------------------------------------------ */ +static int +ipf_auth_geniter(softc, token, itp, objp) + ipf_main_softc_t *softc; + ipftoken_t *token; + ipfgeniter_t *itp; + ipfobj_t *objp; +{ + ipf_auth_softc_t *softa = softc->ipf_auth_soft; + frauthent_t *fae, *next, zero; + int error; + + if (itp->igi_data == NULL) { + IPFERROR(10011); + return EFAULT; + } + + if (itp->igi_type != IPFGENITER_AUTH) { + IPFERROR(10012); + return EINVAL; + } + + objp->ipfo_type = IPFOBJ_FRAUTH; + objp->ipfo_ptr = itp->igi_data; + objp->ipfo_size = sizeof(frauth_t); + + READ_ENTER(&softa->ipf_authlk); + + fae = token->ipt_data; + if (fae == NULL) { + next = softa->ipf_auth_entries; + } else { + next = fae->fae_next; + } + + /* + * If we found an auth entry to use, bump its reference count + * so that it can be used for is_next when we come back. + */ + if (next != NULL) { + ATOMIC_INC(next->fae_ref); + token->ipt_data = next; + } else { + bzero(&zero, sizeof(zero)); + next = &zero; + token->ipt_data = NULL; + } + + RWLOCK_EXIT(&softa->ipf_authlk); + + error = ipf_outobjk(softc, objp, next); + if (fae != NULL) + ipf_auth_deref_unlocked(softa, &fae); + + if (next->fae_next == NULL) + ipf_token_mark_complete(token); + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_auth_deref_unlocked */ +/* Returns: None */ +/* Parameters: faep(IO) - pointer to caller's frauthent_t pointer */ +/* */ +/* Wrapper for ipf_auth_deref for when a write lock on ipf_authlk is not */ +/* held. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_auth_deref_unlocked(softa, faep) + ipf_auth_softc_t *softa; + frauthent_t **faep; +{ + WRITE_ENTER(&softa->ipf_authlk); + ipf_auth_deref(faep); + RWLOCK_EXIT(&softa->ipf_authlk); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_auth_deref */ +/* Returns: None */ +/* Parameters: faep(IO) - pointer to caller's frauthent_t pointer */ +/* Locks: WRITE(ipf_authlk) */ +/* */ +/* This function unconditionally sets the pointer in the caller to NULL, */ +/* to make it clear that it should no longer use that pointer, and drops */ +/* the reference count on the structure by 1. If it reaches 0, free it up. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_auth_deref(faep) + frauthent_t **faep; +{ + frauthent_t *fae; + + fae = *faep; + *faep = NULL; + + fae->fae_ref--; + if (fae->fae_ref == 0) { + KFREE(fae); + } +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_auth_wait_pkt */ +/* Returns: int - 0 == success, else error */ +/* Parameters: data(I) - pointer to data from ioctl call */ +/* */ +/* This function is called when an application is waiting for a packet to */ +/* match an "auth" rule by issuing an SIOCAUTHW ioctl. If there is already */ +/* a packet waiting on the queue then we will return that _one_ immediately.*/ +/* If there are no packets present in the queue (ipf_auth_pkts) then we go */ +/* to sleep. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_auth_wait(softc, softa, data) + ipf_main_softc_t *softc; + ipf_auth_softc_t *softa; + char *data; +{ + frauth_t auth, *au = &auth; + int error, len, i; + mb_t *m; + char *t; + SPL_INT(s); + +ipf_auth_ioctlloop: + error = ipf_inobj(softc, data, NULL, au, IPFOBJ_FRAUTH); + if (error != 0) + return error; + + /* + * XXX Locks are held below over calls to copyout...a better + * solution needs to be found so this isn't necessary. The situation + * we are trying to guard against here is an error in the copyout + * steps should not cause the packet to "disappear" from the queue. + */ + SPL_NET(s); + READ_ENTER(&softa->ipf_authlk); + + /* + * If ipf_auth_next is not equal to ipf_auth_end it will be because + * there is a packet waiting to be delt with in the ipf_auth_pkts + * array. We copy as much of that out to user space as requested. + */ + if (softa->ipf_auth_used > 0) { + while (softa->ipf_auth_pkts[softa->ipf_auth_next] == NULL) { + softa->ipf_auth_next++; + if (softa->ipf_auth_next == softa->ipf_auth_size) + softa->ipf_auth_next = 0; + } + + error = ipf_outobj(softc, data, + &softa->ipf_auth[softa->ipf_auth_next], + IPFOBJ_FRAUTH); + if (error != 0) { + RWLOCK_EXIT(&softa->ipf_authlk); + SPL_X(s); + return error; + } + + if (auth.fra_len != 0 && auth.fra_buf != NULL) { + /* + * Copy packet contents out to user space if + * requested. Bail on an error. + */ + m = softa->ipf_auth_pkts[softa->ipf_auth_next]; + len = MSGDSIZE(m); + if (len > auth.fra_len) + len = auth.fra_len; + auth.fra_len = len; + + for (t = auth.fra_buf; m && (len > 0); ) { + i = MIN(M_LEN(m), len); + error = copyoutptr(softc, MTOD(m, char *), + &t, i); + len -= i; + t += i; + if (error != 0) { + RWLOCK_EXIT(&softa->ipf_authlk); + SPL_X(s); + return error; + } + m = m->m_next; + } + } + RWLOCK_EXIT(&softa->ipf_authlk); + + SPL_NET(s); + WRITE_ENTER(&softa->ipf_authlk); + softa->ipf_auth_next++; + if (softa->ipf_auth_next == softa->ipf_auth_size) + softa->ipf_auth_next = 0; + RWLOCK_EXIT(&softa->ipf_authlk); + SPL_X(s); + + return 0; + } + RWLOCK_EXIT(&softa->ipf_authlk); + SPL_X(s); + + MUTEX_ENTER(&softa->ipf_auth_mx); +#ifdef _KERNEL +# if SOLARIS + error = 0; + if (!cv_wait_sig(&softa->ipf_auth_wait, &softa->ipf_auth_mx.ipf_lk)) { + IPFERROR(10014); + error = EINTR; + } +# else /* SOLARIS */ +# ifdef __hpux + { + lock_t *l; + + l = get_sleep_lock(&softa->ipf_auth_next); + error = sleep(&softa->ipf_auth_next, PZERO+1); + spinunlock(l); + } +# else +# ifdef __osf__ + error = mpsleep(&softa->ipf_auth_next, PSUSP|PCATCH, "ipf_auth_next", + 0, &softa->ipf_auth_mx, MS_LOCK_SIMPLE); +# else + error = SLEEP(&softa->ipf_auth_next, "ipf_auth_next"); +# endif /* __osf__ */ +# endif /* __hpux */ +# endif /* SOLARIS */ +#endif + MUTEX_EXIT(&softa->ipf_auth_mx); + if (error == 0) + goto ipf_auth_ioctlloop; + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_auth_reply */ +/* Returns: int - 0 == success, else error */ +/* Parameters: data(I) - pointer to data from ioctl call */ +/* */ +/* This function is called by an application when it wants to return a */ +/* decision on a packet using the SIOCAUTHR ioctl. This is after it has */ +/* received information using an SIOCAUTHW. The decision returned in the */ +/* form of flags, the same as those used in each rule. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_auth_reply(softc, softa, data) + ipf_main_softc_t *softc; + ipf_auth_softc_t *softa; + char *data; +{ + frauth_t auth, *au = &auth, *fra; + fr_info_t fin; + int error, i; + mb_t *m; + SPL_INT(s); + + error = ipf_inobj(softc, data, NULL, &auth, IPFOBJ_FRAUTH); + if (error != 0) + return error; + + SPL_NET(s); + WRITE_ENTER(&softa->ipf_authlk); + + i = au->fra_index; + fra = softa->ipf_auth + i; + error = 0; + + /* + * Check the validity of the information being returned with two simple + * checks. First, the auth index value should be within the size of + * the array and second the packet id being returned should also match. + */ + if ((i < 0) || (i >= softa->ipf_auth_size)) { + RWLOCK_EXIT(&softa->ipf_authlk); + SPL_X(s); + IPFERROR(10015); + return ESRCH; + } + if (fra->fra_info.fin_id != au->fra_info.fin_id) { + RWLOCK_EXIT(&softa->ipf_authlk); + SPL_X(s); + IPFERROR(10019); + return ESRCH; + } + + m = softa->ipf_auth_pkts[i]; + fra->fra_index = -2; + fra->fra_pass = au->fra_pass; + softa->ipf_auth_pkts[i] = NULL; + softa->ipf_auth_replies++; + bcopy(&fra->fra_info, &fin, sizeof(fin)); + + RWLOCK_EXIT(&softa->ipf_authlk); + + /* + * Re-insert the packet back into the packet stream flowing through + * the kernel in a manner that will mean IPFilter sees the packet + * again. This is not the same as is done with fastroute, + * deliberately, as we want to resume the normal packet processing + * path for it. + */ +#ifdef _KERNEL + if ((m != NULL) && (au->fra_info.fin_out != 0)) { + error = ipf_inject(&fin, m); + if (error != 0) { + IPFERROR(10016); + error = ENOBUFS; + softa->ipf_auth_stats.fas_sendfail++; + } else { + softa->ipf_auth_stats.fas_sendok++; + } + } else if (m) { + error = ipf_inject(&fin, m); + if (error != 0) { + IPFERROR(10017); + error = ENOBUFS; + softa->ipf_auth_stats.fas_quefail++; + } else { + softa->ipf_auth_stats.fas_queok++; + } + } else { + IPFERROR(10018); + error = EINVAL; + } + + /* + * If we experience an error which will result in the packet + * not being processed, make sure we advance to the next one. + */ + if (error == ENOBUFS) { + WRITE_ENTER(&softa->ipf_authlk); + softa->ipf_auth_used--; + fra->fra_index = -1; + fra->fra_pass = 0; + if (i == softa->ipf_auth_start) { + while (fra->fra_index == -1) { + i++; + if (i == softa->ipf_auth_size) + i = 0; + softa->ipf_auth_start = i; + if (i == softa->ipf_auth_end) + break; + } + if (softa->ipf_auth_start == softa->ipf_auth_end) { + softa->ipf_auth_next = 0; + softa->ipf_auth_start = 0; + softa->ipf_auth_end = 0; + } + } + RWLOCK_EXIT(&softa->ipf_authlk); + } +#endif /* _KERNEL */ + SPL_X(s); + + return 0; +} + + +u_32_t +ipf_auth_pre_scanlist(softc, fin, pass) + ipf_main_softc_t *softc; + fr_info_t *fin; + u_32_t pass; +{ + ipf_auth_softc_t *softa = softc->ipf_auth_soft; + + if (softa->ipf_auth_ip != NULL) + return ipf_scanlist(fin, softc->ipf_pass); + + return pass; +} + + +frentry_t ** +ipf_auth_rulehead(softc) + ipf_main_softc_t *softc; +{ + ipf_auth_softc_t *softa = softc->ipf_auth_soft; + + return &softa->ipf_auth_ip; +} diff --git a/ip_auth.h b/ip_auth.h index a39e7fd823f11..6792cdaf2c62b 100644 --- a/ip_auth.h +++ b/ip_auth.h @@ -1,11 +1,9 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1997-2001 by Darren Reed & Guido Van Rooij. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * Id: ip_auth.h,v 2.16 2003/07/25 12:29:56 darrenr Exp + * $Id$ * */ #ifndef __IP_AUTH_H__ @@ -20,18 +18,22 @@ typedef struct frauth { u_32_t fra_pass; fr_info_t fra_info; char *fra_buf; + u_32_t fra_flx; #ifdef MENTAT queue_t *fra_q; + mb_t *fra_m; #endif } frauth_t; typedef struct frauthent { struct frentry fae_fr; struct frauthent *fae_next; + struct frauthent **fae_pnext; u_long fae_age; + int fae_ref; } frauthent_t; -typedef struct fr_authstat { +typedef struct ipf_authstat { U_QUAD_T fas_hits; U_QUAD_T fas_miss; u_long fas_nospace; @@ -42,25 +44,28 @@ typedef struct fr_authstat { u_long fas_quefail; u_long fas_expire; frauthent_t *fas_faelist; -} fr_authstat_t; +} ipf_authstat_t; -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; -extern frentry_t *fr_checkauth __P((fr_info_t *, u_32_t *)); -extern void fr_authexpire __P((void)); -extern int fr_authinit __P((void)); -extern void fr_authunload __P((void)); -extern int fr_authflush __P((void)); -extern mb_t **fr_authpkts; -extern int fr_newauth __P((mb_t *, fr_info_t *)); -extern int fr_preauthcmd __P((ioctlcmd_t, frentry_t *, frentry_t **)); -extern int fr_auth_ioctl __P((caddr_t, ioctlcmd_t, int)); +extern frentry_t *ipf_auth_check __P((fr_info_t *, u_32_t *)); +extern void ipf_auth_expire __P((ipf_main_softc_t *)); +extern int ipf_auth_ioctl __P((ipf_main_softc_t *, caddr_t, ioctlcmd_t, + int, int, void *)); +extern int ipf_auth_init __P((void)); +extern int ipf_auth_main_load __P((void)); +extern int ipf_auth_main_unload __P((void)); +extern void ipf_auth_soft_destroy __P((ipf_main_softc_t *, void *)); +extern void *ipf_auth_soft_create __P((ipf_main_softc_t *)); +extern int ipf_auth_new __P((mb_t *, fr_info_t *)); +extern int ipf_auth_precmd __P((ipf_main_softc_t *, ioctlcmd_t, + frentry_t *, frentry_t **)); +extern void ipf_auth_unload __P((ipf_main_softc_t *)); +extern int ipf_auth_waiting __P((ipf_main_softc_t *)); +extern void ipf_auth_setlock __P((void *, int)); +extern int ipf_auth_soft_init __P((ipf_main_softc_t *, void *)); +extern int ipf_auth_soft_fini __P((ipf_main_softc_t *, void *)); +extern u_32_t ipf_auth_pre_scanlist __P((ipf_main_softc_t *, fr_info_t *, + u_32_t)); +extern frentry_t **ipf_auth_rulehead __P((ipf_main_softc_t *)); #endif /* __IP_AUTH_H__ */ diff --git a/ip_compat.h b/ip_compat.h index 6ea3f709a5581..675f1d5d62144 100644 --- a/ip_compat.h +++ b/ip_compat.h @@ -1,12 +1,10 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1993-2001, 2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_compat.h 1.8 1/14/96 - * Id: ip_compat.h,v 2.142.2.25 2005/03/28 09:33:36 darrenr Exp + * $Id$ */ #ifndef __IP_COMPAT_H__ @@ -36,7 +34,7 @@ #ifndef SOLARIS #define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) #endif -#if SOLARIS2 >= 8 +#if (defined(SOLARIS2) && (SOLARIS2 >= 8)) # ifndef USE_INET6 # define USE_INET6 # endif @@ -48,20 +46,26 @@ #if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105000000) && \ !defined(_KERNEL) && !defined(USE_INET6) # define USE_INET6 +#endif +#if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 106140000) && \ + defined(_KERNEL) && \ + (!defined(IPFILTER_LKM) || (__NetBSD_Version__ >= 399000100)) # define IPFILTER_M_IPFILTER #endif -#if defined(OpenBSD) && (OpenBSD >= 200206) && \ +#if !defined(USE_INET6) +# if defined(OpenBSD) && (OpenBSD >= 200206) && \ !defined(_KERNEL) && !defined(USE_INET6) -# define USE_INET6 -#endif -#if defined(__osf__) -# define USE_INET6 -#endif -#if defined(linux) && (!defined(_KERNEL) || defined(CONFIG_IPV6)) -# define USE_INET6 -#endif -#if defined(HPUXREV) && (HPUXREV >= 1111) -# define USE_INET6 +# define USE_INET6 +# endif +# if defined(__osf__) +# define USE_INET6 1 +# endif +# if defined(linux) && (!defined(_KERNEL) || defined(CONFIG_IPV6)) +# define USE_INET6 +# endif +# if defined(HPUXREV) && (HPUXREV >= 1111) +# define USE_INET6 +# endif #endif #if defined(BSD) && (BSD < 199103) && defined(__osf__) @@ -129,6 +133,31 @@ struct file; # endif #endif +#define NETBSD_GE_REV(x) (defined(__NetBSD_Version__) && \ + (__NetBSD_Version__ >= (x))) +#define NETBSD_GT_REV(x) (defined(__NetBSD_Version__) && \ + (__NetBSD_Version__ > (x))) +#define NETBSD_LT_REV(x) (defined(__NetBSD_Version__) && \ + (__NetBSD_Version__ < (x))) +#define FREEBSD_GE_REV(x) (defined(__FreeBSD_version) && \ + (__FreeBSD_version >= (x))) +#define FREEBSD_GT_REV(x) (defined(__FreeBSD_version) && \ + (__FreeBSD_version > (x))) +#define FREEBSD_LT_REV(x) (defined(__FreeBSD_version) && \ + (__FreeBSD_version < (x))) +#define BSDOS_GE_REV(x) (defined(_BSDI_VERSION) && \ + (_BSDI_VERSION >= (x))) +#define BSDOS_GT_REV(x) (defined(_BSDI_VERSION) && \ + (_BSDI_VERSION > (x))) +#define BSDOS_LT_REV(x) (defined(_BSDI_VERSION) && \ + (_BSDI_VERSION < (x))) +#define OPENBSD_GE_REV(x) (defined(OpenBSD) && (OpenBSD >= (x))) +#define OPENBSD_GT_REV(x) (defined(OpenBSD) && (OpenBSD > (x))) +#define OPENBSD_LT_REV(x) (defined(OpenBSD) && (OpenBSD < (x))) +#define BSD_GE_YEAR(x) (defined(BSD) && (BSD >= (x))) +#define BSD_GT_YEAR(x) (defined(BSD) && (BSD > (x))) +#define BSD_LT_YEAR(x) (defined(BSD) && (BSD < (x))) + /* ----------------------------------------------------------------------- */ /* S O L A R I S */ @@ -146,11 +175,13 @@ struct file; # include <sys/proc.h> # include <sys/devops.h> # include <sys/ddi_impldefs.h> +# include <sys/sdt.h> # endif /* * because Solaris 2 defines these in two places :-/ */ -# ifndef KERNEL +# ifndef _KERNEL +# define ADD_KERNEL # define _KERNEL # undef RES_INIT # endif /* _KERNEL */ @@ -170,11 +201,14 @@ struct file; # ifdef i386 # define _SYS_PROMIF_H # endif +# ifdef ADD_KERNEL +# undef _KERNEL +# endif +# include <inet/mib2.h> # include <inet/ip.h> # undef COPYOUT -# include <inet/ip_ire.h> -# ifndef KERNEL -# undef _KERNEL +# if !defined(_SYS_NETI_H) +# include <inet/ip_ire.h> # endif # if SOLARIS2 >= 8 # define SNPRINTF snprintf @@ -193,17 +227,27 @@ struct ip6_ext { # if SOLARIS2 >= 6 # include <sys/atomic.h> +typedef uint8_t u_int8_t; typedef uint32_t u_32_t; # else +typedef unsigned char u_int8_t; typedef unsigned int u_32_t; # endif # define U_32_T 1 +# if SOLARIS2 >= 7 +# define USE_QUAD_T 1 +# define U_QUAD_T uint64_t +# define QUAD_T int64_t +# endif # ifdef _KERNEL +# define NEED_LOCAL_RAND 1 # define KRWLOCK_T krwlock_t # define KMUTEX_T kmutex_t -# include "qif.h" -# include "pfil.h" +# if !defined(FW_HOOKS) +# include "qif.h" +# include "pfil.h" +# endif # if SOLARIS2 >= 6 # if SOLARIS2 == 6 # define ATOMIC_INCL(x) atomic_add_long((uint32_t*)&(x), 1) @@ -214,15 +258,13 @@ typedef unsigned int u_32_t; # endif /* SOLARIS2 == 6 */ # define ATOMIC_INC64(x) atomic_add_64((uint64_t*)&(x), 1) # define ATOMIC_INC32(x) atomic_add_32((uint32_t*)&(x), 1) -# define ATOMIC_INC16(x) atomic_add_16((uint16_t*)&(x), 1) # define ATOMIC_DEC64(x) atomic_add_64((uint64_t*)&(x), -1) # define ATOMIC_DEC32(x) atomic_add_32((uint32_t*)&(x), -1) -# define ATOMIC_DEC16(x) atomic_add_16((uint16_t*)&(x), -1) # else -# define ATOMIC_INC(x) { mutex_enter(&ipf_rw); (x)++; \ - mutex_exit(&ipf_rw); } -# define ATOMIC_DEC(x) { mutex_enter(&ipf_rw); (x)--; \ - mutex_exit(&ipf_rw); } +# define ATOMIC_INC(x) { mutex_enter(&softc->ipf_rw); (x)++; \ + mutex_exit(&softc->ipf_rw); } +# define ATOMIC_DEC(x) { mutex_enter(&softc->ipf_rw); (x)--; \ + mutex_exit(&softc->ipf_rw); } # endif /* SOLARIS2 >= 6 */ # define USE_MUTEXES # define MUTEX_ENTER(x) mutex_enter(&(x)->ipf_lk) @@ -240,11 +282,12 @@ typedef unsigned int u_32_t; # define MUTEX_EXIT(x) mutex_exit(&(x)->ipf_lk) # define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c)) # define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c)) -# define BCOPYIN(a,b,c) (void) copyin((caddr_t)(a), (caddr_t)(b), (c)) -# define BCOPYOUT(a,b,c) (void) copyout((caddr_t)(a), (caddr_t)(b), (c)) +# define BCOPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c)) +# define BCOPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c)) # define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,c,d) # define KFREE(x) kmem_free((char *)(x), sizeof(*(x))) # define KFREES(x,s) kmem_free((char *)(x), (s)) +# define SPL_SCHED(x) ; # define SPL_NET(x) ; # define SPL_IMP(x) ; # undef SPL_X @@ -258,23 +301,73 @@ typedef unsigned int u_32_t; # define KMALLOC(a,b) (a) = (b)kmem_alloc(sizeof(*(a)), KM_NOSLEEP) # define KMALLOCS(a,b,c) (a) = (b)kmem_alloc((c), KM_NOSLEEP) # define GET_MINOR(x) getminor(x) -extern void *get_unit __P((char *, int)); -# define GETIFP(n, v) get_unit(n, v) -# define IFNAME(x) ((qif_t *)x)->qf_name -# define COPYIFNAME(x, b) \ +extern void *get_unit __P((void *, char *, int)); +# define GETIFP(n, v) get_unit(softc, n, v) +# if defined(INSTANCES) +# include <sys/hook.h> +# include <sys/neti.h> +typedef struct qpktinfo { + void *qpi_real; /* the real one on the STREAM */ + void *qpi_ill; /* COPIED */ + mblk_t *qpi_m; + queue_t *qpi_q; + void *qpi_data; /* where layer 3 header starts */ + size_t qpi_off; + int qpi_flags; /* COPIED */ +} qpktinfo_t; + +#define QF_MULTICAST 0x0001 +#define QF_BROADCAST 0x0002 + +typedef struct qifpkt { + struct qifpkt *qp_next; + char qp_ifname[LIFNAMSIZ]; + int qp_sap; + mblk_t *qp_mb; + int qp_inout; +} qifpkt_t; + +# define COPYIFNAME(v, x,b) \ + do { \ + if ((v) == 4) { \ + net_getifname(softc->ipf_nd_v4, \ + (phy_if_t)x, b, \ + sizeof(b)); \ + } else { \ + net_getifname(softc->ipf_nd_v6, \ + (phy_if_t)x, b, \ + sizeof(b)); \ + } \ + } while (0) +# define GETIFMTU_4(x) net_getmtu(softc->ipf_nd_v4, (phy_if_t)x, 0) +# define GETIFMTU_6(x) net_getmtu(softc->ipf_nd_v6, (phy_if_t)x, 0) +# define GET_SOFTC(x) ipf_find_softc(x) +# else +# define FASTROUTE_RECURSION 1 +# define GET_SOFTC(x) &ipfmain +# define GETIFMTU_4(x) ((qif_t *)x)->qf_max_frag +# define GETIFMTU_6(x) ((qif_t *)x)->qf_max_frag +# define IFNAME(x) ((qif_t *)x)->qf_name +# define COPYIFNAME(v, x, b) \ (void) strncpy(b, ((qif_t *)x)->qf_name, \ LIFNAMSIZ) +# endif # define GETKTIME(x) uniqtime((struct timeval *)x) -# define MSGDSIZE(x) msgdsize(x) -# define M_LEN(x) ((x)->b_wptr - (x)->b_rptr) -# define M_DUPLICATE(x) dupmsg((x)) +# define MSGDSIZE(m) msgdsize(m) +# define M_LEN(m) ((m)->b_wptr - (m)->b_rptr) +# define M_ADJ(m,x) adjmsg(m, x) +# define M_COPY(x) dupmsg((x)) # define MTOD(m,t) ((t)((m)->b_rptr)) # define MTYPE(m) ((m)->b_datap->db_type) # define FREE_MB_T(m) freemsg(m) +# define ALLOC_MB_T(m,l) (m) = allocmbt(l) +# define PREP_MB_T(f,m) ipf_prependmbt(f, m) +# define M_DUP(m) copymsg(m) # define m_next b_cont -# define CACHE_HASH(x) (((qpktinfo_t *)(x)->fin_qpi)->qpi_num & 7) # define IPF_PANIC(x,y) if (x) { printf y; cmn_err(CE_PANIC, "ipf_panic"); } typedef mblk_t mb_t; +extern void mb_copydata __P((mblk_t *, size_t, size_t, char *)); +extern void mb_copyback __P((mblk_t *, size_t, size_t, char *)); # endif /* _KERNEL */ # if (SOLARIS2 >= 7) @@ -313,6 +406,7 @@ typedef struct ip6_hdr ip6_t; # endif # ifdef _KERNEL +# define FASTROUTE_RECURSION 1 # define SNPRINTF sprintf # if (HPUXREV >= 1111) # define IPL_SELECT @@ -348,35 +442,33 @@ typedef struct iplog_select_s { */ # if 1 # ifdef __LP64__ -# define ATOMIC_INCL(x) lock_and_incr_int64(&ipf_rw.ipf_lk, &(x), 1) -# define ATOMIC_DECL(x) lock_and_incr_int64(&ipf_rw.ipf_lk, &(x), -1) +# define ATOMIC_INCL(x) lock_and_incr_int64(&softc->ipf_rw.ipf_lk, &(x), 1) +# define ATOMIC_DECL(x) lock_and_incr_int64(&softc->ipf_rw.ipf_lk, &(x), -1) # else -# define ATOMIC_INCL(x) lock_and_incr_int32(&ipf_rw.ipf_lk, &(x), 1) -# define ATOMIC_DECL(x) lock_and_incr_int32(&ipf_rw.ipf_lk, &(x), -1) +# define ATOMIC_INCL(x) lock_and_incr_int32(&softc->ipf_rw.ipf_lk, &(x), 1) +# define ATOMIC_DECL(x) lock_and_incr_int32(&softc->ipf_rw.ipf_lk, &(x), -1) # endif -# define ATOMIC_INC64(x) lock_and_incr_int64(&ipf_rw.ipf_lk, &(x), 1) -# define ATOMIC_INC32(x) lock_and_incr_int32(&ipf_rw.ipf_lk, &(x), 1) -# define ATOMIC_INC16(x) lock_and_incr_int16(&ipf_rw.ipf_lk, &(x), 1) -# define ATOMIC_DEC64(x) lock_and_incr_int64(&ipf_rw.ipf_lk, &(x), -1) -# define ATOMIC_DEC32(x) lock_and_incr_int32(&ipf_rw.ipf_lk, &(x), -1) -# define ATOMIC_DEC16(x) lock_and_incr_int16(&ipf_rw.ipf_lk, &(x), -1) +# define ATOMIC_INC64(x) lock_and_incr_int64(&softc->ipf_rw.ipf_lk, &(x), 1) +# define ATOMIC_INC32(x) lock_and_incr_int32(&softc->ipf_rw.ipf_lk, &(x), 1) +# define ATOMIC_DEC64(x) lock_and_incr_int64(&softc->ipf_rw.ipf_lk, &(x), -1) +# define ATOMIC_DEC32(x) lock_and_incr_int32(&softc->ipf_rw.ipf_lk, &(x), -1) # else /* 0 */ -# define ATOMIC_INC64(x) { MUTEX_ENTER(&ipf_rw); (x)++; \ - MUTEX_EXIT(&ipf_rw); } -# define ATOMIC_DEC64(x) { MUTEX_ENTER(&ipf_rw); (x)--; \ - MUTEX_EXIT(&ipf_rw); } -# define ATOMIC_INC32(x) { MUTEX_ENTER(&ipf_rw); (x)++; \ - MUTEX_EXIT(&ipf_rw); } -# define ATOMIC_DEC32(x) { MUTEX_ENTER(&ipf_rw); (x)--; \ - MUTEX_EXIT(&ipf_rw); } -# define ATOMIC_INCL(x) { MUTEX_ENTER(&ipf_rw); (x)++; \ - MUTEX_EXIT(&ipf_rw); } -# define ATOMIC_DECL(x) { MUTEX_ENTER(&ipf_rw); (x)--; \ - MUTEX_EXIT(&ipf_rw); } -# define ATOMIC_INC(x) { MUTEX_ENTER(&ipf_rw); (x)++; \ - MUTEX_EXIT(&ipf_rw); } -# define ATOMIC_DEC(x) { MUTEX_ENTER(&ipf_rw); (x)--; \ - MUTEX_EXIT(&ipf_rw); } +# define ATOMIC_INC64(x) { MUTEX_ENTER(&softc->ipf_rw); (x)++; \ + MUTEX_EXIT(&softc->ipf_rw); } +# define ATOMIC_DEC64(x) { MUTEX_ENTER(&softc->ipf_rw); (x)--; \ + MUTEX_EXIT(&softc->ipf_rw); } +# define ATOMIC_INC32(x) { MUTEX_ENTER(&softc->ipf_rw); (x)++; \ + MUTEX_EXIT(&softc->ipf_rw); } +# define ATOMIC_DEC32(x) { MUTEX_ENTER(&softc->ipf_rw); (x)--; \ + MUTEX_EXIT(&softc->ipf_rw); } +# define ATOMIC_INCL(x) { MUTEX_ENTER(&softc->ipf_rw); (x)++; \ + MUTEX_EXIT(&softc->ipf_rw); } +# define ATOMIC_DECL(x) { MUTEX_ENTER(&softc->ipf_rw); (x)--; \ + MUTEX_EXIT(&softc->ipf_rw); } +# define ATOMIC_INC(x) { MUTEX_ENTER(&softc->ipf_rw); (x)++; \ + MUTEX_EXIT(&softc->ipf_rw); } +# define ATOMIC_DEC(x) { MUTEX_ENTER(&softc->ipf_rw); (x)--; \ + MUTEX_EXIT(&softc->ipf_rw); } # endif # define ip_cksum ip_csuma # define memcpy(a,b,c) bcopy((caddr_t)b, (caddr_t)a, c) @@ -417,21 +509,17 @@ typedef struct iplog_select_s { # define RW_DESTROY(x) # define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c)) # define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c)) -# if HPUXREV >= 1111 -# define BCOPYIN(a,b,c) 0; bcopy((caddr_t)(a), (caddr_t)(b), (c)) -# define BCOPYOUT(a,b,c) 0; bcopy((caddr_t)(a), (caddr_t)(b), (c)) -# else -# define BCOPYIN(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) -# define BCOPYOUT(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) -# endif +# define SPL_SCHED(x) ; # define SPL_NET(x) ; # define SPL_IMP(x) ; # undef SPL_X # define SPL_X(x) ; extern void *get_unit __P((char *, int)); # define GETIFP(n, v) get_unit(n, v) +# define GETIFMTU_4(x) ((ill_t *)x)->ill_mtu +# define GETIFMTU_6(x) ((ill_t *)x)->ill_mtu # define IFNAME(x, b) ((ill_t *)x)->ill_name -# define COPYIFNAME(x, b) \ +# define COPYIFNAME(v, x, b) \ (void) strncpy(b, ((qif_t *)x)->qf_name, \ LIFNAMSIZ) # define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,c,d) @@ -443,13 +531,16 @@ extern void *get_unit __P((char *, int)); wakeup(id + x); \ spinunlock(_l); \ } +# define POLLWAKEUP(x) ; # define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), M_IOSYS, M_NOWAIT) # define KMALLOCS(a, b, c) MALLOC((a), b, (c), M_IOSYS, M_NOWAIT) # define KFREE(x) kmem_free((char *)(x), sizeof(*(x))) # define KFREES(x,s) kmem_free((char *)(x), (s)) -# define MSGDSIZE(x) msgdsize(x) -# define M_LEN(x) ((x)->b_wptr - (x)->b_rptr) -# define M_DUPLICATE(x) dupmsg((x)) +# define MSGDSIZE(m) msgdsize(m) +# define M_ADJ(m,x) adjmsg(m, x) +# define M_LEN(m) ((m)->b_wptr - (m)->b_rptr) +# define M_COPY(m) copymsg((m)) +# define M_DUP(m) dupmsg(m) # define MTOD(m,t) ((t)((m)->b_rptr)) # define MTYPE(m) ((m)->b_datap->db_type) # define FREE_MB_T(m) freemsg(m) @@ -457,8 +548,6 @@ extern void *get_unit __P((char *, int)); # define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); } typedef mblk_t mb_t; -# define CACHE_HASH(x) (((qpktinfo_t *)(x)->fin_qpi)->qpi_num & 7) - # include "qif.h" # include "pfil.h" @@ -527,21 +616,20 @@ typedef struct { # endif # ifdef _KERNEL -# define ATOMIC_INC(x) { MUTEX_ENTER(&ipf_rw); \ - (x)++; MUTEX_EXIT(&ipf_rw); } -# define ATOMIC_DEC(x) { MUTEX_ENTER(&ipf_rw); \ - (x)--; MUTEX_EXIT(&ipf_rw); } +# define NEED_LOCAL_RAND 1 +# define ATOMIC_INC(x) { MUTEX_ENTER(&softc->ipf_rw); \ + (x)++; MUTEX_EXIT(&softc->ipf_rw); } +# define ATOMIC_DEC(x) { MUTEX_ENTER(&softc->ipf_rw); \ + (x)--; MUTEX_EXIT(&softc->ipf_rw); } # define USE_MUTEXES # ifdef MUTEX_INIT # include <sys/atomic_ops.h> # define ATOMIC_INCL(x) atomicAddUlong(&(x), 1) # define ATOMIC_INC64(x) atomicAddUint64(&(x), 1) # define ATOMIC_INC32(x) atomicAddUint(&(x), 1) -# define ATOMIC_INC16 ATOMIC_INC # define ATOMIC_DECL(x) atomicAddUlong(&(x), -1) # define ATOMIC_DEC64(x) atomicAddUint64(&(x), -1) # define ATOMIC_DEC32(x) atomicAddUint(&(x), -1) -# define ATOMIC_DEC16 ATOMIC_DEC # undef MUTEX_INIT # define MUTEX_INIT(x, y) mutex_init(&(x)->ipf_lk, \ MUTEX_DEFAULT, y) @@ -575,14 +663,15 @@ typedef struct { # define MTOD(m,t) mtod(m,t) # define COPYIN(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0) # define COPYOUT(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0) -# define BCOPYIN(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0) -# define BCOPYOUT(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0) # define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,c,d) # define SLEEP(id, n) sleep((id), PZERO+1) # define WAKEUP(id,x) wakeup(id+x) +# define POLLWAKEUP(x) ; # define KFREE(x) kmem_free((char *)(x), sizeof(*(x))) # define KFREES(x,s) kmem_free((char *)(x), (s)) # define GETIFP(n,v) ifunit(n) +# define GETIFMTU_4(x) ((struct ifnet *)x)->if_mtu +# define GETIFMTU_6(x) ((struct ifnet *)x)->if_mtu # include <sys/kmem.h> # include <sys/ddi.h> # define KMALLOC(a,b) (a) = (b)kmem_alloc(sizeof(*(a)), KM_NOSLEEP) @@ -591,15 +680,16 @@ typedef struct { # define USE_SPL 1 # define SPL_IMP(x) (x) = splimp() # define SPL_NET(x) (x) = splnet() +# define SPL_SCHED(x) (x) = splsched() # define SPL_X(x) (void) splx(x) extern void m_copydata __P((struct mbuf *, int, int, caddr_t)); extern void m_copyback __P((struct mbuf *, int, int, caddr_t)); -# define MSGDSIZE(x) mbufchainlen(x) +# define MSGDSIZE(m) mbufchainlen(m) +# define M_ADJ(m,x) m_adj(m, x) # define M_LEN(x) (x)->m_len -# define M_DUPLICATE(x) m_copy((x), 0, M_COPYALL) +# define M_COPY(m) m_copy((m), 0, M_COPYALL) # define GETKTIME(x) microtime((struct timeval *)x) -# define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ - ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) +# define IFNAME(x) ((struct ifnet *)x)->if_name # define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); } typedef struct mbuf mb_t; # else @@ -622,6 +712,7 @@ typedef struct mbuf mb_t; # include <sys/sysmacros.h> # ifdef _KERNEL +# define NEED_LOCAL_RAND 1 # define KMUTEX_T simple_lock_data_t # define KRWLOCK_T lock_data_t # include <net/net_globals.h> @@ -641,16 +732,13 @@ typedef struct mbuf mb_t; # define ATOMIC_DEC64(x) atomic_decq((uint64_t*)&(x)) # define ATOMIC_INC32(x) atomic_incl((uint32_t*)&(x)) # define ATOMIC_DEC32(x) atomic_decl((uint32_t*)&(x)) -# define ATOMIC_INC16(x) { simple_lock(&ipf_rw); (x)++; \ - simple_unlock(&ipf_rw); } -# define ATOMIC_DEC16(x) { simple_lock(&ipf_rw); (x)--; \ - simple_unlock(&ipf_rw); } # define ATOMIC_INCL(x) atomic_incl((uint32_t*)&(x)) # define ATOMIC_DECL(x) atomic_decl((uint32_t*)&(x)) -# define ATOMIC_INC(x) { simple_lock(&ipf_rw); (x)++; \ - simple_unlock(&ipf_rw); } -# define ATOMIC_DEC(x) { simple_lock(&ipf_rw); (x)--; \ - simple_unlock(&ipf_rw); } +# define ATOMIC_INC(x) { simple_lock(&softc->ipf_rw); (x)++; \ + simple_unlock(&softc->ipf_rw); } +# define ATOMIC_DEC(x) { simple_lock(&softc->ipf_rw); (x)--; \ + simple_unlock(&softc->ipf_rw); } +# define SPL_SCHED(x) ; # define SPL_NET(x) ; # define SPL_IMP(x) ; # undef SPL_X @@ -659,24 +747,27 @@ typedef struct mbuf mb_t; # define FREE_MB_T(m) m_freem(m) # define MTOD(m,t) mtod(m,t) # define GETIFP(n, v) ifunit(n) +# define GETIFMTU_4(x) ((struct ifnet *)x)->if_mtu +# define GETIFMTU_6(x) ((struct ifnet *)x)->if_mtu # define GET_MINOR getminor # define WAKEUP(id,x) wakeup(id + x) +# define POLLWAKEUP(x) ; # define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c)) # define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c)) -# define BCOPYIN(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) -# define BCOPYOUT(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) # define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), M_PFILT, M_NOWAIT) # define KMALLOCS(a, b, c) MALLOC((a), b, (c), M_PFILT, \ ((c) > 4096) ? M_WAITOK : M_NOWAIT) # define KFREE(x) FREE((x), M_PFILT) # define KFREES(x,s) FREE((x), M_PFILT) -# define MSGDSIZE(x) mbufchainlen(x) -# define M_LEN(x) (x)->m_len -# define M_DUPLICATE(x) m_copy((x), 0, M_COPYALL) +# define MSGDSIZE(m) mbufchainlen(m) +# define M_LEN(m) (m)->m_len +# define M_ADJ(m,x) m_adj(m, x) +# define M_COPY(m) m_copy((m), 0, M_COPYALL) +# define M_DUP(m) m_copy((m), 0, M_COPYALL) # define GETKTIME(x) microtime((struct timeval *)x) -# define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ - ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) +# define IFNAME(x) ((struct ifnet *)x)->if_name # define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); } +# define selinfo sel_queue typedef struct mbuf mb_t; # endif /* _KERNEL */ @@ -690,6 +781,9 @@ typedef struct mbuf mb_t; # define TCP_OFF(x) ((x)->th_xoff >> 4) # define TCP_OFF_A(x,y) (x)->th_xoff |= (((y) << 4) & 0xf0) # endif +# if TRU64 <= 1885 +# define ip6_vfc ip6_vcf +# endif /* * These are from's Solaris' #defines for little endian. @@ -703,7 +797,7 @@ struct ip6_ext { u_char ip6e_len; }; -typedef int ioctlcmd_t; +typedef int ioctlcmd_t; /* * Really, any arch where sizeof(long) != sizeof(int). */ @@ -717,6 +811,24 @@ typedef unsigned int u_32_t; /* N E T B S D */ /* ----------------------------------------------------------------------- */ #ifdef __NetBSD__ +# define HAS_SYS_MD5_H 1 +# if (NetBSD >= 199905) && !defined(IPFILTER_LKM) && defined(_KERNEL) +# if (__NetBSD_Version__ < 399001400) +# include "opt_ipfilter_log.h" +# else +# include "opt_ipfilter.h" +# endif +# endif +# if defined(_KERNEL) +# include <sys/systm.h> +# include <sys/malloc.h> +# if (__NetBSD_Version__ > 500000000) +# include <sys/kauth.h> +# endif +# else +# include <stddef.h> +# include <stdbool.h> +# endif # if defined(_KERNEL) && !defined(IPFILTER_LKM) # include "bpfilter.h" # if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 104110000) @@ -730,32 +842,68 @@ typedef unsigned int u_32_t; # endif # endif +# if (__NetBSD_Version__ >= 499000000) +typedef char * caddr_t; +# ifdef _KERNEL +# include <sys/rwlock.h> +# define USE_MUTEXES 1 +# define KMUTEX_T kmutex_t +# define KRWLOCK_T krwlock_t +# define MUTEX_DESTROY(x) mutex_destroy(&(x)->ipf_lk) +# define MUTEX_DOWNGRADE(x) rw_downgrade(&(x)->ipf_lk) +# define MUTEX_ENTER(x) mutex_enter(&(x)->ipf_lk) +# define MUTEX_EXIT(x) mutex_exit(&(x)->ipf_lk) +# define MUTEX_INIT(x,y) mutex_init(&(x)->ipf_lk, MUTEX_DRIVER,\ + IPL_SOFTNET) +# define MUTEX_NUKE(x) bzero((x), sizeof(*(x))) +# define READ_ENTER(x) rw_enter(&(x)->ipf_lk, RW_READER) +# define RWLOCK_INIT(x, y) rw_init(&(x)->ipf_lk) +# define RWLOCK_EXIT(x) rw_exit(&(x)->ipf_lk) +# define RW_DESTROY(x) rw_destroy(&(x)->ipf_lk) +# define WRITE_ENTER(x) rw_enter(&(x)->ipf_lk, RW_WRITER) +# define SPL_SCHED(x) ; +# define SPL_NET(x) ; +# define SPL_IMP(x) ; +# define SPL_X(x) ; +# endif +# endif + # ifdef _KERNEL -# define MSGDSIZE(x) mbufchainlen(x) -# define M_LEN(x) (x)->m_len -# define M_DUPLICATE(x) m_copy((x), 0, M_COPYALL) +# if (__NetBSD_Version__ >= 399001400) +# include <sys/selinfo.h> /* Not in NetBSD 3.1 */ +# define PROC_T struct lwp +# define KFREE(a) free((a), _M_IPF) +# define KFREES(a, b) free((a), _M_IPF) +# define KMALLOC(a, b) (a) = (b)malloc(sizeof (*(a)), \ + _M_IPF, M_NOWAIT) +# define KMALLOCS(a, b, c) (a) = (b)malloc((c), _M_IPF, M_NOWAIT) +# else +# define PROC_T struct proc +# endif +# define MSGDSIZE(m) mbufchainlen(m) +# define M_LEN(m) (m)->m_len +# define M_ADJ(m,x) m_adj(m, x) +# define M_COPY(x) m_copy((x), 0, M_COPYALL) # define GETKTIME(x) microtime((struct timeval *)x) # define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); } # define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c)) # define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c)) -# define BCOPYIN(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) -# define BCOPYOUT(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) +# if (defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 499004900)) +# define POLLWAKEUP(x) selnotify(softc->ipf_selwait+x, 0, 0) +# endif typedef struct mbuf mb_t; # endif /* _KERNEL */ # if (NetBSD <= 1991011) && (NetBSD >= 199606) # define IFNAME(x) ((struct ifnet *)x)->if_xname -# define COPYIFNAME(x, b) \ +# define COPYIFNAME(v, x, b) \ (void) strncpy(b, \ ((struct ifnet *)x)->if_xname, \ LIFNAMSIZ) -# define CACHE_HASH(x) ((((struct ifnet *)fin->fin_ifp)->if_index)&7) # else -# define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ - ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) +# define IFNAME(x) ((struct ifnet *)x)->if_name # endif - typedef struct uio uio_t; -typedef u_long ioctlcmd_t; +typedef u_long ioctlcmd_t; typedef int minor_t; typedef u_int32_t u_32_t; # define U_32_T 1 @@ -768,13 +916,14 @@ typedef u_int32_t u_32_t; /* F R E E B S D */ /* ----------------------------------------------------------------------- */ #ifdef __FreeBSD__ -# if defined(_KERNEL) && !defined(IPFILTER_LKM) && !defined(KLD_MODULE) -# if (__FreeBSD_version >= 500000) +# if (__FreeBSD_version < 400000) +# define NEED_LOCAL_RAND 1 +# endif +# if defined(_KERNEL) +# if (__FreeBSD_version >= 500000) # include "opt_bpf.h" -# else -# include "bpf.h" # endif -# if defined(__FreeBSD_version) && (__FreeBSD_version >= 400000) +# if defined(__FreeBSD_version) && (__FreeBSD_version >= 500000) # include "opt_inet6.h" # endif # if defined(INET6) && !defined(USE_INET6) @@ -783,6 +932,19 @@ typedef u_int32_t u_32_t; # endif # if defined(_KERNEL) +# include <netinet/ip_var.h> +# if (__FreeBSD_version >= 500024) +# if (__FreeBSD_version >= 500043) +# define p_cred td_ucred +# define p_uid td_ucred->cr_ruid +# else +# define p_cred t_proc->p_cred +# define p_uid t_proc->p_cred->p_ruid +# endif +# else +# define p_uid p_cred->p_ruid +# endif /* __FreeBSD_version >= 500024 */ + # if (__FreeBSD_version >= 400000) /* * When #define'd, the 5.2.1 kernel panics when used with the ftp proxy. @@ -795,43 +957,92 @@ typedef u_int32_t u_32_t; # endif # define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c)) # define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c)) -# define BCOPYIN(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) -# define BCOPYOUT(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) # if (__FreeBSD_version >= 500043) # define NETBSD_PF # endif +# else +# include <inttypes.h> # endif /* _KERNEL */ +# if (__FreeBSD_version >= 700000) +# include <sys/selinfo.h> +# endif # if (__FreeBSD_version >= 500043) # include <sys/mutex.h> -# include <sys/sx.h> +# if (__FreeBSD_version >= 700014) +# define KRWLOCK_FILL_SZ 36 +# define KMUTEX_FILL_SZ 24 +# include <sys/rwlock.h> +# ifdef _KERNEL +# define KMUTEX_T struct mtx +# define KRWLOCK_T struct rwlock +# define READ_ENTER(x) rw_rlock(&(x)->ipf_lk) +# define WRITE_ENTER(x) rw_wlock(&(x)->ipf_lk) +# define MUTEX_DOWNGRADE(x) rw_downgrade(&(x)->ipf_lk) +# define RWLOCK_INIT(x,y) rw_init(&(x)->ipf_lk, (y)) +# define RW_DESTROY(x) rw_destroy(&(x)->ipf_lk) +# define RWLOCK_EXIT(x) do { \ + if (rw_wowned(&(x)->ipf_lk)) \ + rw_wunlock(&(x)->ipf_lk); \ + else \ + rw_runlock(&(x)->ipf_lk); \ + } while (0) +# endif +# else +# include <sys/sx.h> /* * Whilst the sx(9) locks on FreeBSD have the right semantics and interface * for what we want to use them for, despite testing showing they work - * with a WITNESS kernel, it generates LOR messages. */ -# define KMUTEX_T struct mtx -# if 1 -# define KRWLOCK_T struct mtx -# else -# define KRWLOCK_T struct sx +# if (__FreeBSD_version < 700000) +# ifdef _KERNEL +# define KMUTEX_T struct mtx +# define KRWLOCK_T struct mtx +# define READ_ENTER(x) mtx_lock(&(x)->ipf_lk) +# define WRITE_ENTER(x) mtx_lock(&(x)->ipf_lk) +# define RWLOCK_EXIT(x) mtx_unlock(&(x)->ipf_lk) +# define MUTEX_DOWNGRADE(x) ; +# define RWLOCK_INIT(x,y) mtx_init(&(x)->ipf_lk, (y), NULL,\ + MTX_DEF) +# define RW_DESTROY(x) mtx_destroy(&(x)->ipf_lk) +# endif +# else +# ifdef _KERNEL +# define KRWLOCK_T struct sx +# define KMUTEX_T struct mtx +# define READ_ENTER(x) sx_slock(&(x)->ipf_lk) +# define WRITE_ENTER(x) sx_xlock(&(x)->ipf_lk) +# define MUTEX_DOWNGRADE(x) sx_downgrade(&(x)->ipf_lk) +# define RWLOCK_INIT(x, y) sx_init(&(x)->ipf_lk, (y)) +# define RW_DESTROY(x) sx_destroy(&(x)->ipf_lk) +# ifdef sx_unlock +# define RWLOCK_EXIT(x) sx_unlock(&(x)->ipf_lk) +# else +# define RWLOCK_EXIT(x) do { \ + if ((x)->ipf_lk.sx_cnt < 0) \ + sx_xunlock(&(x)->ipf_lk); \ + else \ + sx_sunlock(&(x)->ipf_lk); \ + } while (0) +# endif +# endif +# endif # endif # endif # if (__FreeBSD_version >= 501113) # include <net/if_var.h> # define IFNAME(x) ((struct ifnet *)x)->if_xname -# define COPYIFNAME(x, b) \ +# define COPYIFNAME(v, x, b) \ (void) strncpy(b, \ ((struct ifnet *)x)->if_xname, \ LIFNAMSIZ) # endif # if (__FreeBSD_version >= 500043) -# define CACHE_HASH(x) ((((struct ifnet *)fin->fin_ifp)->if_index) & 7) # else -# define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ - ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) +# define IFNAME(x) ((struct ifnet *)x)->if_name # endif # ifdef _KERNEL @@ -856,52 +1067,33 @@ typedef u_int32_t u_32_t; * for what we want to use them for, despite testing showing they work - * with a WITNESS kernel, it generates LOR messages. */ -# if 1 -# define READ_ENTER(x) mtx_lock(&(x)->ipf_lk) -# define WRITE_ENTER(x) mtx_lock(&(x)->ipf_lk) -# define RWLOCK_EXIT(x) mtx_unlock(&(x)->ipf_lk) -# define MUTEX_DOWNGRADE(x) ; -# define RWLOCK_INIT(x,y) mtx_init(&(x)->ipf_lk, (y), NULL,\ - MTX_DEF) -# define RW_DESTROY(x) mtx_destroy(&(x)->ipf_lk) -# else -# define READ_ENTER(x) sx_slock(&(x)->ipf_lk) -# define WRITE_ENTER(x) sx_xlock(&(x)->ipf_lk) -# define MUTEX_DOWNGRADE(x) sx_downgrade(&(x)->ipf_lk) -# define RWLOCK_INIT(x, y) sx_init(&(x)->ipf_lk, (y)) -# define RW_DESTROY(x) sx_destroy(&(x)->ipf_lk) -# ifdef sx_unlock -# define RWLOCK_EXIT(x) sx_unlock(x) -# else -# define RWLOCK_EXIT(x) do { \ - if ((x)->ipf_lk.sx_cnt < 0) \ - sx_xunlock(&(x)->ipf_lk); \ - else \ - sx_sunlock(&(x)->ipf_lk); \ - } while (0) -# endif -# endif # include <machine/atomic.h> -# define ATOMIC_INC(x) { mtx_lock(&ipf_rw.ipf_lk); (x)++; \ - mtx_unlock(&ipf_rw.ipf_lk); } -# define ATOMIC_DEC(x) { mtx_lock(&ipf_rw.ipf_lk); (x)--; \ - mtx_unlock(&ipf_rw.ipf_lk); } +# define ATOMIC_INC(x) { mtx_lock(&softc->ipf_rw.ipf_lk); (x)++; \ + mtx_unlock(&softc->ipf_rw.ipf_lk); } +# define ATOMIC_DEC(x) { mtx_lock(&softc->ipf_rw.ipf_lk); (x)--; \ + mtx_unlock(&softc->ipf_rw.ipf_lk); } # define ATOMIC_INCL(x) atomic_add_long(&(x), 1) # define ATOMIC_INC64(x) ATOMIC_INC(x) -# define ATOMIC_INC32(x) atomic_add_32(&(x), 1) -# define ATOMIC_INC16(x) atomic_add_16(&(x), 1) +# define ATOMIC_INC32(x) atomic_add_32((u_int *)&(x), 1) # define ATOMIC_DECL(x) atomic_add_long(&(x), -1) # define ATOMIC_DEC64(x) ATOMIC_DEC(x) -# define ATOMIC_DEC32(x) atomic_add_32(&(x), -1) -# define ATOMIC_DEC16(x) atomic_add_16(&(x), -1) +# define ATOMIC_DEC32(x) atomic_add_32((u_int *)&(x), -1) # define SPL_X(x) ; # define SPL_NET(x) ; # define SPL_IMP(x) ; +# define SPL_SCHED(x) ; extern int in_cksum __P((struct mbuf *, int)); +# else +# define SPL_SCHED(x) x = splhigh() # endif /* __FreeBSD_version >= 500043 */ -# define MSGDSIZE(x) mbufchainlen(x) -# define M_LEN(x) (x)->m_len -# define M_DUPLICATE(x) m_copy((x), 0, M_COPYALL) +# if (__FreeBSD_version >= 500024) +# define GET_MINOR dev2unit +# endif +# define MSGDSIZE(m) mbufchainlen(m) +# define M_LEN(m) (m)->m_len +# define M_ADJ(m,x) m_adj(m, x) +# define M_COPY(x) m_copy((x), 0, M_COPYALL) +# define M_DUP(m) m_dup(m, M_NOWAIT) # define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); } typedef struct mbuf mb_t; # endif /* _KERNEL */ @@ -954,29 +1146,25 @@ typedef u_int32_t u_32_t; # endif # define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c)) # define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c)) -# define BCOPYIN(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) -# define BCOPYOUT(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) # define GETKTIME(x) microtime((struct timeval *)x) -# define MSGDSIZE(x) mbufchainlen(x) -# define M_LEN(x) (x)->m_len -# define M_DUPLICATE(x) m_copy((x), 0, M_COPYALL) +# define MSGDSIZE(m) mbufchainlen(m) +# define M_LEN(m) (m)->m_len +# define M_ADJ(m,x) m_adj(m, x) +# define M_COPY(m) m_copy((m), 0, M_COPYALL) # define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); } typedef struct mbuf mb_t; # endif /* _KERNEL */ # if (OpenBSD >= 199603) # define IFNAME(x, b) ((struct ifnet *)x)->if_xname -# define COPYIFNAME(x, b) \ +# define COPYIFNAME(v, x, b) \ (void) strncpy(b, \ ((struct ifnet *)x)->if_xname, \ LIFNAMSIZ) -# define CACHE_HASH(x) ((((struct ifnet *)fin->fin_ifp)->if_index)&7) # else -# define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ - ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) +# define IFNAME(x) ((struct ifnet *)x)->if_name # endif - typedef struct uio uio_t; -typedef u_long ioctlcmd_t; +typedef u_long ioctlcmd_t; typedef int minor_t; typedef u_int32_t u_32_t; # define U_32_T 1 @@ -995,11 +1183,11 @@ typedef u_int32_t u_32_t; # ifdef _KERNEL # define GETKTIME(x) microtime((struct timeval *)x) -# define MSGDSIZE(x) mbufchainlen(x) -# define M_LEN(x) (x)->m_len -# define M_DUPLICATE(x) m_copy((x), 0, M_COPYALL) -# define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ - ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) +# define MSGDSIZE(m) mbufchainlen(m) +# define M_LEN(m) (m)->m_len +# define M_ADJ(m,x) m_adj(m, x) +# define M_COPY(m) m_copy((m), 0, M_COPYALL) +# define IFNAME(x) ((struct ifnet *)x)->if_name typedef struct mbuf mb_t; # endif /* _KERNEL */ @@ -1021,16 +1209,18 @@ typedef u_int32_t u_32_t; # ifdef _KERNEL # include <sys/kmem_alloc.h> # define GETKTIME(x) uniqtime((struct timeval *)x) -# define MSGDSIZE(x) mbufchainlen(x) -# define M_LEN(x) (x)->m_len -# define M_DUPLICATE(x) m_copy((x), 0, M_COPYALL) -# define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ - ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) +# define MSGDSIZE(m) mbufchainlen(m) +# define M_LEN(m) (m)->m_len +# define M_ADJ(m,x) m_adj(m, x) +# define M_COPY(m) m_copy((m), 0, M_COPYALL) +# define IFNAME(x) ((struct ifnet *)x)->if_name # define GETIFP(n, v) ifunit(n, IFNAMSIZ) +# define GETIFMTU_4(x) ((struct ifnet *)x)->if_mtu # define KFREE(x) kmem_free((char *)(x), sizeof(*(x))) # define KFREES(x,s) kmem_free((char *)(x), (s)) # define SLEEP(id, n) sleep((id), PZERO+1) # define WAKEUP(id,x) wakeup(id + x) +# define POLLWAKEUP(x) ; # define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,c,d) # define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); } @@ -1041,7 +1231,7 @@ typedef struct mbuf mb_t; # endif typedef struct uio uio_t; -typedef int ioctlcmd_t; +typedef int ioctlcmd_t; typedef int minor_t; typedef unsigned int u_32_t; # define U_32_T 1 @@ -1054,9 +1244,8 @@ typedef unsigned int u_32_t; /* L I N U X */ /* ----------------------------------------------------------------------- */ #if defined(linux) && !defined(OS_RECOGNISED) -#include <linux/config.h> -#include <linux/version.h> -# if LINUX >= 20600 +# include <linux/version.h> +# if (LINUX >= 20600) && defined(_KERNEL) # define HDR_T_PRIVATE 1 # endif # undef USE_INET6 @@ -1068,52 +1257,67 @@ struct ip6_ext { # endif # ifdef _KERNEL +# include <asm/byteorder.h> +# ifdef __LITTLE_ENDIAN +# define BIG_ENDIAN 0 +# define LITTLE_ENDIAN 1 +# define BYTE_ORDER LITTLE_ENDIAN +# else +# define BIG_ENDIAN 1 +# define LITTLE_ENDIAN 0 +# define BYTE_ORDER BIG_ENDIAN +# endif # define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); } -# define BCOPYIN(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) -# define BCOPYOUT(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) # define COPYIN(a,b,c) copy_from_user((caddr_t)(b), (caddr_t)(a), (c)) # define COPYOUT(a,b,c) copy_to_user((caddr_t)(b), (caddr_t)(a), (c)) # define FREE_MB_T(m) kfree_skb(m) # define GETKTIME(x) do_gettimeofday((struct timeval *)x) -# define SLEEP(x,s) 0, interruptible_sleep_on(x##_linux) -# define WAKEUP(x,y) wake_up(x##_linux + y) -# define UIOMOVE(a,b,c,d) uiomove(a,b,c,d) +# define POLLWAKEUP(x) ; +# ifdef wait_event_interruptible +# define SLEEP(x,s) wait_event_interruptible((*(x##_linux)), 0) +# else +# define SLEEP(x,s) 0, interruptible_sleep_on(x##_linux) +# endif +# define WAKEUP(x,y) wake_up(x##_linux + y) +# define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,c,d) # define USE_MUTEXES # define KRWLOCK_T rwlock_t # define KMUTEX_T spinlock_t # define MUTEX_INIT(x,y) spin_lock_init(&(x)->ipf_lk) -# define MUTEX_ENTER(x) spin_lock(&(x)->ipf_lk) -# define MUTEX_EXIT(x) spin_unlock(&(x)->ipf_lk) +# define MUTEX_ENTER(x) spin_lock_bh(&(x)->ipf_lk) +# define MUTEX_EXIT(x) spin_unlock_bh(&(x)->ipf_lk) # define MUTEX_DESTROY(x) do { } while (0) # define MUTEX_NUKE(x) bzero(&(x)->ipf_lk, sizeof((x)->ipf_lk)) # define READ_ENTER(x) ipf_read_enter(x) # define WRITE_ENTER(x) ipf_write_enter(x) -# define RWLOCK_INIT(x,y) rwlock_init(&(x)->ipf_lk) +# define RWLOCK_INIT(x,y) ipf_rw_init(x, y) # define RW_DESTROY(x) do { } while (0) # define RWLOCK_EXIT(x) ipf_rw_exit(x) # define MUTEX_DOWNGRADE(x) ipf_rw_downgrade(x) -# define ATOMIC_INCL(x) MUTEX_ENTER(&ipf_rw); (x)++; \ - MUTEX_EXIT(&ipf_rw) -# define ATOMIC_DECL(x) MUTEX_ENTER(&ipf_rw); (x)--; \ - MUTEX_EXIT(&ipf_rw) -# define ATOMIC_INC64(x) MUTEX_ENTER(&ipf_rw); (x)++; \ - MUTEX_EXIT(&ipf_rw) -# define ATOMIC_INC32(x) MUTEX_ENTER(&ipf_rw); (x)++; \ - MUTEX_EXIT(&ipf_rw) -# define ATOMIC_INC16(x) MUTEX_ENTER(&ipf_rw); (x)++; \ - MUTEX_EXIT(&ipf_rw) -# define ATOMIC_DEC64(x) MUTEX_ENTER(&ipf_rw); (x)--; \ - MUTEX_EXIT(&ipf_rw) -# define ATOMIC_DEC32(x) MUTEX_ENTER(&ipf_rw); (x)--; \ - MUTEX_EXIT(&ipf_rw) -# define ATOMIC_DEC16(x) MUTEX_ENTER(&ipf_rw); (x)--; \ - MUTEX_EXIT(&ipf_rw) +# define ATOMIC_INCL(x) atomic_long_inc((atomic_long_t *)&(x)) +# define ATOMIC_DECL(x) atomic_long_dec((atomic_long_t *)&(x)) +# define ATOMIC_INC32(x) atomic_inc((atomic_t *)&(x)) +# define ATOMIC_DEC32(x) atomic_dec((atomic_t *)&(x)) +# ifdef CONFIG_X86_32 +# define ATOMIC_INC64(x) do { MUTEX_ENTER(&softc->ipf_rw); \ + (x)++; \ + MUTEX_EXIT(&softc->ipf_rw); \ + } while (0) +# define ATOMIC_DEC64(x) do { MUTEX_ENTER(&softc->ipf_rw); \ + (x)--; \ + MUTEX_EXIT(&softc->ipf_rw); \ + } while (0) +# else +# define ATOMIC_INC64(x) atomic64_inc((atomic64_t *)&(x)) +# define ATOMIC_DEC64(x) atomic64_dec((atomic64_t *)&(x)) +# endif +# define U_QUAD_T u_int64_t +# define QUAD_T int64_t +# define SPL_SCHED(x) do { } while (0) # define SPL_IMP(x) do { } while (0) # define SPL_NET(x) do { } while (0) # define SPL_X(x) do { } while (0) # define IFNAME(x) ((struct net_device*)x)->name -# define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ - ((struct net_device *)fin->fin_ifp)->ifindex) & 7) typedef struct sk_buff mb_t; extern void m_copydata __P((mb_t *, int, int, caddr_t)); extern void m_copyback __P((mb_t *, int, int, caddr_t)); @@ -1122,22 +1326,43 @@ extern mb_t *m_pullup __P((mb_t *, int)); # define mbuf sk_buff # define mtod(m, t) ((t)(m)->data) +# define m_adj(m, x) skb_trim((m), (m)->len + (x)) +# define m_data data # define m_len len # define m_next next -# define M_DUPLICATE(m) skb_clone((m), in_interrupt() ? GFP_ATOMIC : \ +# define M_COPY(m) skb_clone((m), in_interrupt() ? GFP_ATOMIC : \ GFP_KERNEL) # define MSGDSIZE(m) (m)->len # define M_LEN(m) (m)->len +# define M_ADJ(m,x) m_adj(m, x) +# define M_DUP(m) skb_copy((m), in_interrupt() ? GFP_ATOMIC : \ + GFP_KERNEL) +# define PREP_MB_T(f, m) do { \ + (m)->next = *(f)->fin_mp; \ + *(fin)->fin_mp = (m); \ + (f)->fin_m = (m); \ + } while (0) +# define ALLOC_MB_T(m,l) (m) = alloc_skb((l), \ + in_interrupt() ? GFP_ATOMIC : \ + GFP_KERNEL) # define splnet(x) ; # define printf printk # define bcopy(s,d,z) memmove(d, s, z) # define bzero(s,z) memset(s, 0, z) # define bcmp(a,b,z) memcmp(a, b, z) +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) +# define ipf_random random32 +# define arc4random random32 +# else +# include <linux/random.h> +# define ipf_random get_random_int +# define arc4random get_random_int +# endif # define ifnet net_device # define if_xname name -# define if_unit ifindex +# define if_unit ifindex # define KMALLOC(x,t) (x) = (t)kmalloc(sizeof(*(x)), \ in_interrupt() ? GFP_ATOMIC : GFP_KERNEL) @@ -1146,7 +1371,14 @@ extern mb_t *m_pullup __P((mb_t *, int)); in_interrupt() ? GFP_ATOMIC : GFP_KERNEL) # define KFREES(x,s) kfree(x) -# define GETIFP(n,v) dev_get_by_name(n) +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) +# define f_uid f_owner.uid +# define GETIFP(n,v) dev_get_by_name(&init_net, n) +# else +# define GETIFP(n,v) dev_get_by_name(n) +# endif +# define GETIFMTU_4(x) ((struct net_device *)x)->mtu +# define GETIFMTU_6(x) ((struct net_device *)x)->mtu # else # include <net/ethernet.h> @@ -1169,7 +1401,7 @@ struct ifnet { # endif /* _KERNEL */ -# define COPYIFNAME(x, b) \ +# define COPYIFNAME(v, x, b) \ (void) strncpy(b, \ ((struct ifnet *)x)->if_xname, \ LIFNAMSIZ) @@ -1196,6 +1428,10 @@ extern int uiomove __P((caddr_t, size_t, int, struct uio *)); # define UIO_READ 1 # define UIO_WRITE 2 +# if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)) && !defined(_KERNEL) +typedef int fmode_t; +# endif + typedef u_long ioctlcmd_t; typedef int minor_t; typedef u_int32_t u_32_t; @@ -1206,6 +1442,116 @@ typedef u_int32_t u_32_t; #endif +/* ----------------------------------------------------------------------- */ +/* A I X */ +/* ----------------------------------------------------------------------- */ +#if defined(_AIX51) +# undef MENTAT + +# include <sys/lock.h> +# include <sys/sysmacros.h> + +# ifdef _KERNEL +# define rw_read_locked(x) 0 +# include <net/net_globals.h> +# include <net/net_malloc.h> +# define KMUTEX_T simple_lock_t +# define KRWLOCK_T complex_lock_t +# define USE_MUTEXES 1 +# define USE_SPL 1 +# define READ_ENTER(x) lock_read((x)->ipf_lk) +# define WRITE_ENTER(x) lock_write((x)->ipf_lk) +# define MUTEX_DOWNGRADE(x) lock_write_to_read((x)->ipf_lk) +# define RWLOCK_INIT(x, y) lock_alloc(&(x)->ipf_lk, \ + LOCK_ALLOC_PIN, \ + (u_short)y, 0); \ + lock_init((x)->ipf_lk, TRUE) +# define RWLOCK_EXIT(x) lock_done((x)->ipf_lk) +# define RW_DESTROY(x) lock_free(&(x)->ipf_lk) +# define MUTEX_ENTER(x) simple_lock((x)->ipf_lk) +# define MUTEX_INIT(x, y) lock_alloc(&(x)->ipf_lk, \ + LOCK_ALLOC_PIN, \ + (u_short)y, 0); \ + simple_lock_init((x)->ipf_lk) +# define MUTEX_DESTROY(x) lock_free(&(x)->ipf_lk) +# define MUTEX_EXIT(x) simple_unlock((x)->ipf_lk) +# define MUTEX_NUKE(x) bzero(&(x)->ipf_lk, sizeof((x)->ipf_lk)) +# define ATOMIC_INC64(x) { MUTEX_ENTER(&softc->ipf_rw); (x)++; \ + MUTEX_EXIT(&softc->ipf_rw); } +# define ATOMIC_DEC64(x) { MUTEX_ENTER(&softc->ipf_rw); (x)--; \ + MUTEX_EXIT(&softc->ipf_rw); } +# define ATOMIC_INC32(x) { MUTEX_ENTER(&softc->ipf_rw); (x)++; \ + MUTEX_EXIT(&softc->ipf_rw); } +# define ATOMIC_DEC32(x) { MUTEX_ENTER(&softc->ipf_rw); (x)--; \ + MUTEX_EXIT(&softc->ipf_rw); } +# define ATOMIC_INCL(x) { MUTEX_ENTER(&softc->ipf_rw); (x)++; \ + MUTEX_EXIT(&softc->ipf_rw); } +# define ATOMIC_DECL(x) { MUTEX_ENTER(&softc->ipf_rw); (x)--; \ + MUTEX_EXIT(&softc->ipf_rw); } +# define ATOMIC_INC(x) { MUTEX_ENTER(&softc->ipf_rw); (x)++; \ + MUTEX_EXIT(&softc->ipf_rw); } +# define ATOMIC_DEC(x) { MUTEX_ENTER(&softc->ipf_rw); (x)--; \ + MUTEX_EXIT(&softc->ipf_rw); } +# define SPL_SCHED(x) x = splsched() +# define SPL_NET(x) x = splnet() +# define SPL_IMP(x) x = splimp() +# undef SPL_X +# define SPL_X(x) splx(x) +# define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,c,d) +extern void* getifp __P((char *, int)); +# define GETIFP(n, v) getifp(n, v) +# define GETIFMTU_4(x) ((struct ifnet *)x)->if_mtu +# define GETIFMTU_6(x) ((struct ifnet *)x)->if_mtu +# define GET_MINOR minor +# define SLEEP(id, n) sleepx((id), PZERO+1, 0) +# define WAKEUP(id,x) wakeup(id) +# define POLLWAKEUP(x) ; +# define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c)) +# define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c)) +# define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), M_TEMP, M_NOWAIT) +# define KMALLOCS(a, b, c) MALLOC((a), b, (c), M_TEMP, \ + ((c) > 4096) ? M_WAITOK : M_NOWAIT) +# define KFREE(x) FREE((x), M_TEMP) +# define KFREES(x,s) FREE((x), M_TEMP) +# define MSGDSIZE(m) mbufchainlen(m) +# define M_LEN(m) (m)->m_len +# define M_ADJ(m,x) m_adj(m, x) +# define M_COPY(m) m_copy((m), 0, M_COPYALL) +# define GETKTIME(x) +# define IPF_PANIC(x,y) +typedef struct mbuf mb_t; +# endif /* _KERNEL */ + +/* + * These are from's Solaris' #defines for little endian. + */ +#if !defined(IP6F_MORE_FRAG) +# define IP6F_MORE_FRAG 0x0100 +#endif +#if !defined(IP6F_RESERVED_MASK) +# define IP6F_RESERVED_MASK 0x0600 +#endif +#if !defined(IP6F_OFF_MASK) +# define IP6F_OFF_MASK 0xf8ff +#endif + +struct ip6_ext { + u_char ip6e_nxt; + u_char ip6e_len; +}; + +typedef int ioctlcmd_t; +typedef int minor_t; +/* + * Really, any arch where sizeof(long) != sizeof(int). + */ +typedef unsigned int u_32_t; +# define U_32_T 1 + +# define OS_RECOGNISED 1 +#endif /* _AIX51 */ + + #ifndef OS_RECOGNISED #error ip_compat.h does not recognise this platform/OS. #endif @@ -1221,22 +1567,29 @@ typedef u_int32_t u_32_t; * For BSD kernels, if bpf is in the kernel, enable ipfilter to use bpf in * filter rules. */ -#if !defined(IPFILTER_BPF) && ((NBPF > 0) || (NBPFILTER > 0)) -# define IPFILTER_BPF +#if !defined(IPFILTER_BPF) +# if (defined(NBPF) && (NBPF > 0)) || (defined(DEV_BPF) && (DEV_BPF > 0)) || \ + (defined(NBPFILTER) && (NBPFILTER > 0)) +# define IPFILTER_BPF +# endif #endif /* * Userland locking primitives */ +#if !defined(KMUTEX_FILL_SZ) +# define KMUTEX_FILL_SZ 1 +#endif +#if !defined(KRWLOCK_FILL_SZ) +# define KRWLOCK_FILL_SZ 1 +#endif + typedef struct { char *eMm_owner; char *eMm_heldin; u_int eMm_magic; int eMm_held; int eMm_heldat; -#ifdef __hpux - char eMm_fill[8]; -#endif } eMmutex_t; typedef struct { @@ -1246,26 +1599,25 @@ typedef struct { short eMrw_read; short eMrw_write; int eMrw_heldat; -#ifdef __hpux - char eMm_fill[24]; -#endif } eMrwlock_t; typedef union { + char _fill[KMUTEX_FILL_SZ]; #ifdef KMUTEX_T struct { KMUTEX_T ipf_slk; - char *ipf_lname; + const char *ipf_lname; } ipf_lkun_s; #endif eMmutex_t ipf_emu; } ipfmutex_t; typedef union { + char _fill[KRWLOCK_FILL_SZ]; #ifdef KRWLOCK_T struct { KRWLOCK_T ipf_slk; - char *ipf_lname; + const char *ipf_lname; int ipf_sr; int ipf_sw; u_int ipf_magic; @@ -1290,10 +1642,11 @@ typedef union { #endif #if defined(linux) && defined(_KERNEL) -extern INLINE void ipf_read_enter __P((ipfrwlock_t *)); -extern INLINE void ipf_write_enter __P((ipfrwlock_t *)); -extern INLINE void ipf_rw_exit __P((ipfrwlock_t *)); -extern INLINE void ipf_rw_downgrade __P((ipfrwlock_t *)); +extern void ipf_read_enter __P((ipfrwlock_t *)); +extern void ipf_write_enter __P((ipfrwlock_t *)); +extern void ipf_rw_exit __P((ipfrwlock_t *)); +extern void ipf_rw_init __P((ipfrwlock_t *, char *)); +extern void ipf_rw_downgrade __P((ipfrwlock_t *)); #endif /* @@ -1304,21 +1657,46 @@ extern INLINE void ipf_rw_downgrade __P((ipfrwlock_t *)); #ifndef _KERNEL typedef struct mb_s { struct mb_s *mb_next; + char *mb_data; + void *mb_ifp; int mb_len; + int mb_flags; u_long mb_buf[2048]; } mb_t; # undef m_next # define m_next mb_next -# define MSGDSIZE(x) (x)->mb_len /* XXX - from ipt.c */ -# define M_LEN(x) (x)->mb_len -# define M_DUPLICATE(x) (x) +# undef m_len +# define m_len mb_len +# undef m_flags +# define m_flags mb_flags +# undef m_data +# define m_data mb_data +# undef M_MCAST +# define M_MCAST 0x01 +# undef M_BCAST +# define M_BCAST 0x02 +# undef M_MBCAST +# define M_MBCAST 0x04 +# define MSGDSIZE(m) msgdsize(m) +# define M_LEN(m) (m)->mb_len +# define M_ADJ(m,x) (m)->mb_len += x +# define M_COPY(m) dupmbt(m) +# define M_DUP(m) dupmbt(m) # define GETKTIME(x) gettimeofday((struct timeval *)(x), NULL) -# define MTOD(m, t) ((t)(m)->mb_buf) -# define FREE_MB_T(x) +# define MTOD(m, t) ((t)(m)->mb_data) +# define FREE_MB_T(m) freembt(m) +# define ALLOC_MB_T(m,l) (m) = allocmbt(l) +# define PREP_MB_T(f, m) do { \ + (m)->mb_next = *(f)->fin_mp; \ + *(fin)->fin_mp = (m); \ + (f)->fin_m = (m); \ + } while (0) # define SLEEP(x,y) 1; # define WAKEUP(x,y) ; +# define POLLWAKEUP(y) ; # define IPF_PANIC(x,y) ; # define PANIC(x,y) ; +# define SPL_SCHED(x) ; # define SPL_NET(x) ; # define SPL_IMP(x) ; # define SPL_X(x) ; @@ -1327,28 +1705,31 @@ typedef struct mb_s { # define KFREE(x) free(x) # define KFREES(x,s) free(x) # define GETIFP(x, v) get_unit(x,v) -# define COPYIN(a,b,c) (bcopy((a), (b), (c)), 0) -# define COPYOUT(a,b,c) (bcopy((a), (b), (c)), 0) -# define BCOPYIN(a,b,c) (bcopy((a), (b), (c)), 0) -# define BCOPYOUT(a,b,c) (bcopy((a), (b), (c)), 0) +# define GETIFMTU_4(x) 2048 +# define GETIFMTU_6(x) 2048 +# define COPYIN(a,b,c) bcopywrap((a), (b), (c)) +# define COPYOUT(a,b,c) bcopywrap((a), (b), (c)) # define COPYDATA(m, o, l, b) bcopy(MTOD((mb_t *)m, char *) + (o), \ (b), (l)) # define COPYBACK(m, o, l, b) bcopy((b), \ MTOD((mb_t *)m, char *) + (o), \ (l)) -# define UIOMOVE(a,b,c,d) ipfuiomove(a,b,c,d) +# define UIOMOVE(a,b,c,d) ipfuiomove((caddr_t)a,b,c,d) extern void m_copydata __P((mb_t *, int, int, caddr_t)); extern int ipfuiomove __P((caddr_t, int, int, struct uio *)); -# ifndef CACHE_HASH -# define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ - ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) -# endif +extern int bcopywrap __P((void *, void *, size_t)); +extern mb_t *allocmbt __P((size_t)); +extern mb_t *dupmbt __P((mb_t *)); +extern void freembt __P((mb_t *)); -# define MUTEX_DESTROY(x) eMmutex_destroy(&(x)->ipf_emu) +# define MUTEX_DESTROY(x) eMmutex_destroy(&(x)->ipf_emu, \ + __FILE__, __LINE__) # define MUTEX_ENTER(x) eMmutex_enter(&(x)->ipf_emu, \ __FILE__, __LINE__) -# define MUTEX_EXIT(x) eMmutex_exit(&(x)->ipf_emu) -# define MUTEX_INIT(x,y) eMmutex_init(&(x)->ipf_emu, y) +# define MUTEX_EXIT(x) eMmutex_exit(&(x)->ipf_emu, \ + __FILE__, __LINE__) +# define MUTEX_INIT(x,y) eMmutex_init(&(x)->ipf_emu, y, \ + __FILE__, __LINE__) # define MUTEX_NUKE(x) bzero((x), sizeof(*(x))) # define MUTEX_DOWNGRADE(x) eMrwlock_downgrade(&(x)->ipf_emu, \ @@ -1364,10 +1745,10 @@ extern int ipfuiomove __P((caddr_t, int, int, struct uio *)); # define USE_MUTEXES 1 -extern void eMmutex_destroy __P((eMmutex_t *)); +extern void eMmutex_destroy __P((eMmutex_t *, char *, int)); extern void eMmutex_enter __P((eMmutex_t *, char *, int)); -extern void eMmutex_exit __P((eMmutex_t *)); -extern void eMmutex_init __P((eMmutex_t *, char *)); +extern void eMmutex_exit __P((eMmutex_t *, char *, int)); +extern void eMmutex_init __P((eMmutex_t *, char *, char *, int)); extern void eMrwlock_destroy __P((eMrwlock_t *)); extern void eMrwlock_exit __P((eMrwlock_t *)); extern void eMrwlock_init __P((eMrwlock_t *, char *)); @@ -1377,6 +1758,8 @@ extern void eMrwlock_downgrade __P((eMrwlock_t *, char *, int)); #endif +extern mb_t *allocmbt(size_t); + #define MAX_IPV4HDR ((0xf << 2) + sizeof(struct icmp) + sizeof(ip_t) + 8) #ifndef IP_OFFMASK @@ -1388,13 +1771,15 @@ extern void eMrwlock_downgrade __P((eMrwlock_t *, char *, int)); * On BSD's use quad_t as a guarantee for getting at least a 64bit sized * object. */ -#if BSD > 199306 +#if !defined(__amd64__) && BSD_GT_YEAR(199306) # define USE_QUAD_T # define U_QUAD_T u_quad_t # define QUAD_T quad_t #else /* BSD > 199306 */ -# define U_QUAD_T u_long -# define QUAD_T long +# if !defined(U_QUAD_T) +# define U_QUAD_T u_long +# define QUAD_T long +# endif #endif /* BSD > 199306 */ @@ -1417,23 +1802,21 @@ typedef struct ip6_hdr ip6_t; #endif #if defined(_KERNEL) -# ifdef MENTAT +# if defined(MENTAT) && !defined(INSTANCES) # define COPYDATA mb_copydata # define COPYBACK mb_copyback # else # define COPYDATA m_copydata # define COPYBACK m_copyback # endif -# if (BSD >= 199306) || defined(__FreeBSD__) +# if BSD_GE_YEAR(199306) || defined(__FreeBSD__) # if (defined(__NetBSD_Version__) && (__NetBSD_Version__ < 105180000)) || \ defined(__FreeBSD__) || (defined(OpenBSD) && (OpenBSD < 200206)) || \ defined(_BSDI_VERSION) # include <vm/vm.h> # endif -# if !defined(__FreeBSD__) || (defined (__FreeBSD_version) && \ - (__FreeBSD_version >= 300000)) -# if (defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105180000)) || \ - (defined(OpenBSD) && (OpenBSD >= 200111)) +# if !defined(__FreeBSD__) || FREEBSD_GE_REV(300000) +# if NETBSD_GE_REV(105180000) || OPENBSD_GE_REV(200111) # include <uvm/uvm_extern.h> # else # include <vm/vm_extern.h> @@ -1459,30 +1842,85 @@ MALLOC_DECLARE(M_IPFILTER); # endif /* M_IPFILTER */ # endif /* M_PFIL */ # endif /* IPFILTER_M_IPFILTER */ -# define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), _M_IPF, M_NOWAIT) -# define KMALLOCS(a, b, c) MALLOC((a), b, (c), _M_IPF, M_NOWAIT) -# define KFREE(x) FREE((x), _M_IPF) +# if !defined(KMALLOC) +# define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), _M_IPF, M_NOWAIT) +# endif +# if !defined(KMALLOCS) +# define KMALLOCS(a, b, c) MALLOC((a), b, (c), _M_IPF, M_NOWAIT) +# endif +# if !defined(KFREE) +# define KFREE(x) FREE((x), _M_IPF) +# endif +# if !defined(KFREES) # define KFREES(x,s) FREE((x), _M_IPF) -# define UIOMOVE(a,b,c,d) uiomove(a,b,d) +# endif +# define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,d) # define SLEEP(id, n) tsleep((id), PPAUSE|PCATCH, n, 0) # define WAKEUP(id,x) wakeup(id+x) +# if !defined(POLLWAKEUP) +# define POLLWAKEUP(x) selwakeup(softc->ipf_selwait+x) +# endif # define GETIFP(n, v) ifunit(n) +# define GETIFMTU_4(x) ((struct ifnet *)x)->if_mtu +# define GETIFMTU_6(x) ((struct ifnet *)x)->if_mtu # endif /* (Free)BSD */ # if !defined(USE_MUTEXES) && !defined(SPL_NET) # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199407)) || \ - (defined(OpenBSD) && (OpenBSD >= 200006)) + OPENBSD_GE_REV(200006) # define SPL_NET(x) x = splsoftnet() # else # define SPL_IMP(x) x = splimp() # define SPL_NET(x) x = splnet() # endif /* NetBSD && (NetBSD <= 1991011) && (NetBSD >= 199407) */ +# if !defined(SPL_SCHED) +# define SPL_SCHED(x) x = splsched() +# endif # define SPL_X(x) (void) splx(x) # endif /* !USE_MUTEXES */ # ifndef FREE_MB_T # define FREE_MB_T(m) m_freem(m) # endif +# ifndef ALLOC_MB_T +# ifdef MGETHDR +# define ALLOC_MB_T(m,l) do { \ + MGETHDR((m), M_DONTWAIT, MT_HEADER); \ + if ((m) != NULL) { \ + (m)->m_len = (l); \ + (m)->m_pkthdr.len = (l); \ + } \ + } while (0) +# else +# define ALLOC_MB_T(m,l) do { \ + MGET((m), M_DONTWAIT, MT_HEADER); \ + if ((m) != NULL) { \ + (m)->m_len = (l); \ + (m)->m_pkthdr.len = (l); \ + } \ + } while (0) +# endif +# endif +# ifndef PREP_MB_T +# define PREP_MB_T(f, m) do { \ + mb_t *_o = *(f)->fin_mp; \ + (m)->m_next = _o; \ + *(fin)->fin_mp = (m); \ + if (_o->m_flags & M_PKTHDR) { \ + (m)->m_pkthdr.len += \ + _o->m_pkthdr.len; \ + (m)->m_pkthdr.rcvif = \ + _o->m_pkthdr.rcvif; \ + } \ + } while (0) +# endif +# ifndef M_DUP +# ifdef M_COPYALL +# define M_DUP(m) m_dup(m, 0, M_COPYALL, 0) +# else +# define M_DUP(m) m_dup(m) +# endif +# endif # ifndef MTOD # define MTOD(m,t) mtod(m,t) @@ -1491,8 +1929,6 @@ MALLOC_DECLARE(M_IPFILTER); # ifndef COPYIN # define COPYIN(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0) # define COPYOUT(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0) -# define BCOPYIN(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0) -# define BCOPYOUT(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0) # endif # ifndef KMALLOC @@ -1507,18 +1943,27 @@ MALLOC_DECLARE(M_IPFILTER); # define PANIC(x,y) if (x) panic y #endif /* _KERNEL */ -#ifndef IFNAME -# define IFNAME(x) ((struct ifnet *)x)->if_name +#if !defined(IFNAME) && !defined(_KERNEL) +# define IFNAME(x) get_ifname((struct ifnet *)x) #endif #ifndef COPYIFNAME # define NEED_FRGETIFNAME -extern char *fr_getifname __P((struct ifnet *, char *)); -# define COPYIFNAME(x, b) \ - fr_getifname((struct ifnet *)x, b) +extern char *ipf_getifname __P((struct ifnet *, char *)); +# define COPYIFNAME(v, x, b) \ + ipf_getifname((struct ifnet *)x, b) #endif #ifndef ASSERT -# define ASSERT(x) +# ifdef _KERNEL +# define ASSERT(x) +# else +# define ASSERT(x) do { if (!(x)) abort(); } while (0) +# endif +#endif + +#ifndef BCOPYIN +# define BCOPYIN(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0) +# define BCOPYOUT(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0) #endif /* @@ -1527,9 +1972,7 @@ extern char *fr_getifname __P((struct ifnet *, char *)); */ #define ISALNUM(x) isalnum((u_char)(x)) #define ISALPHA(x) isalpha((u_char)(x)) -#define ISASCII(x) isascii((u_char)(x)) #define ISDIGIT(x) isdigit((u_char)(x)) -#define ISPRINT(x) isprint((u_char)(x)) #define ISSPACE(x) isspace((u_char)(x)) #define ISUPPER(x) isupper((u_char)(x)) #define ISXDIGIT(x) isxdigit((u_char)(x)) @@ -1563,6 +2006,12 @@ extern char *fr_getifname __P((struct ifnet *, char *)); # define ATOMIC_DEC(x) (x)-- #endif +#if defined(USE_SPL) && defined(_KERNEL) +# define SPL_INT(x) int x +#else +# define SPL_INT(x) +#endif + /* * If there are no atomic operations for bit sizes defined, define them to all * use a generic one that works for all sizes. @@ -1571,11 +2020,9 @@ extern char *fr_getifname __P((struct ifnet *, char *)); # define ATOMIC_INCL ATOMIC_INC # define ATOMIC_INC64 ATOMIC_INC # define ATOMIC_INC32 ATOMIC_INC -# define ATOMIC_INC16 ATOMIC_INC # define ATOMIC_DECL ATOMIC_DEC # define ATOMIC_DEC64 ATOMIC_DEC # define ATOMIC_DEC32 ATOMIC_DEC -# define ATOMIC_DEC16 ATOMIC_DEC #endif #ifndef HDR_T_PRIVATE @@ -1591,11 +2038,11 @@ typedef struct tcpiphdr tcpiphdr_t; # define FR_GROUPLEN 16 #endif -#ifdef offsetof -# undef offsetof -#endif #ifndef offsetof -# define offsetof(t,m) (int)((&((t *)0L)->m)) +# define offsetof(t,m) (size_t)((&((t *)0L)->m)) +#endif +#ifndef stsizeof +# define stsizeof(t,m) sizeof(((t *)0L)->m) #endif /* @@ -1613,7 +2060,7 @@ typedef struct tcpiphdr tcpiphdr_t; # define IP_HL(x) (x)->ip_hl #endif #ifndef IP_HL_A -# define IP_HL_A(x,y) (x)->ip_hl = (y) +# define IP_HL_A(x,y) (x)->ip_hl = ((y) & 0xf) #endif #ifndef TCP_X2 # define TCP_X2(x) (x)->th_x2 @@ -1642,9 +2089,9 @@ typedef struct tcpiphdr tcpiphdr_t; #define TCPF_ALL (TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG|\ TH_ECN|TH_CWR) -#if (BSD >= 199306) && !defined(m_act) +#if BSD_GE_YEAR(199306) && !defined(m_act) # define m_act m_nextpkt -#endif +#endif /* * Security Options for Intenet Protocol (IPSO) as defined in RFC 1108. @@ -1681,7 +2128,7 @@ typedef struct tcpiphdr tcpiphdr_t; * IP option #defines */ #undef IPOPT_RR -#define IPOPT_RR 7 +#define IPOPT_RR 7 #undef IPOPT_ZSU #define IPOPT_ZSU 10 /* ZSU */ #undef IPOPT_MTUP @@ -1729,6 +2176,8 @@ typedef struct tcpiphdr tcpiphdr_t; #define IPOPT_UMP 152 #undef IPOPT_FINN #define IPOPT_FINN 205 /* FINN */ +#undef IPOPT_AH +#define IPOPT_AH 256+IPPROTO_AH #ifndef TCPOPT_EOL # define TCPOPT_EOL 0 @@ -2007,8 +2456,11 @@ typedef struct tcpiphdr tcpiphdr_t; #ifndef IPPROTO_HOPOPTS # define IPPROTO_HOPOPTS 0 #endif +#ifndef IPPROTO_IPIP +# define IPPROTO_IPIP 4 +#endif #ifndef IPPROTO_ENCAP -# define IPPROTO_ENCAP 4 +# define IPPROTO_ENCAP 98 #endif #ifndef IPPROTO_IPV6 # define IPPROTO_IPV6 41 @@ -2037,9 +2489,10 @@ typedef struct tcpiphdr tcpiphdr_t; #ifndef IPPROTO_DSTOPTS # define IPPROTO_DSTOPTS 60 #endif -#ifndef IPPROTO_FRAGMENT -# define IPPROTO_FRAGMENT 44 +#ifndef IPPROTO_MOBILITY +# define IPPROTO_MOBILITY 135 #endif + #ifndef ICMP_ROUTERADVERT # define ICMP_ROUTERADVERT 9 #endif @@ -2206,6 +2659,38 @@ typedef struct tcpiphdr tcpiphdr_t; # define ICMP6_NI_SUBJ_IPV4 2 #endif +#ifndef MLD_MTRACE_RESP +# define MLD_MTRACE_RESP 200 +#endif +#ifndef MLD_MTRACE +# define MLD_MTRACE 201 +#endif +#ifndef MLD6_MTRACE_RESP +# define MLD6_MTRACE_RESP MLD_MTRACE_RESP +#endif +#ifndef MLD6_MTRACE +# define MLD6_MTRACE MLD_MTRACE +#endif + +#if !defined(IPV6_FLOWINFO_MASK) +# if (BYTE_ORDER == BIG_ENDIAN) || defined(_BIG_ENDIAN) +# define IPV6_FLOWINFO_MASK 0x0fffffff /* flow info (28 bits) */ +# else +# if(BYTE_ORDER == LITTLE_ENDIAN) || !defined(_BIG_ENDIAN) +# define IPV6_FLOWINFO_MASK 0xffffff0f /* flow info (28 bits) */ +# endif /* LITTLE_ENDIAN */ +# endif +#endif +#if !defined(IPV6_FLOWLABEL_MASK) +# if (BYTE_ORDER == BIG_ENDIAN) || defined(_BIG_ENDIAN) +# define IPV6_FLOWLABEL_MASK 0x000fffff /* flow label (20 bits) */ +# else +# if (BYTE_ORDER == LITTLE_ENDIAN) || !defined(_BIG_ENDIAN) +# define IPV6_FLOWLABEL_MASK 0xffff0f00 /* flow label (20 bits) */ +# endif /* LITTLE_ENDIAN */ +# endif +#endif + /* * ECN is a new addition to TCP - RFC 2481 */ @@ -2220,21 +2705,21 @@ typedef struct tcpiphdr tcpiphdr_t; /* * TCP States */ -#define IPF_TCPS_CLOSED 0 /* closed */ -#define IPF_TCPS_LISTEN 1 /* listening for connection */ -#define IPF_TCPS_SYN_SENT 2 /* active, have sent syn */ -#define IPF_TCPS_SYN_RECEIVED 3 /* have send and received syn */ -#define IPF_TCPS_HALF_ESTAB 4 /* for connections not fully "up" */ +#define IPF_TCPS_LISTEN 0 /* listening for connection */ +#define IPF_TCPS_SYN_SENT 1 /* active, have sent syn */ +#define IPF_TCPS_SYN_RECEIVED 2 /* have send and received syn */ +#define IPF_TCPS_HALF_ESTAB 3 /* for connections not fully "up" */ /* states < IPF_TCPS_ESTABLISHED are those where connections not established */ -#define IPF_TCPS_ESTABLISHED 5 /* established */ -#define IPF_TCPS_CLOSE_WAIT 6 /* rcvd fin, waiting for close */ +#define IPF_TCPS_ESTABLISHED 4 /* established */ +#define IPF_TCPS_CLOSE_WAIT 5 /* rcvd fin, waiting for close */ /* states > IPF_TCPS_CLOSE_WAIT are those where user has closed */ -#define IPF_TCPS_FIN_WAIT_1 7 /* have closed, sent fin */ -#define IPF_TCPS_CLOSING 8 /* closed xchd FIN; await FIN ACK */ -#define IPF_TCPS_LAST_ACK 9 /* had fin and close; await FIN ACK */ +#define IPF_TCPS_FIN_WAIT_1 6 /* have closed, sent fin */ +#define IPF_TCPS_CLOSING 7 /* closed xchd FIN; await FIN ACK */ +#define IPF_TCPS_LAST_ACK 8 /* had fin and close; await FIN ACK */ /* states > IPF_TCPS_CLOSE_WAIT && < IPF_TCPS_FIN_WAIT_2 await ACK of FIN */ -#define IPF_TCPS_FIN_WAIT_2 10 /* have closed, fin is acked */ -#define IPF_TCPS_TIME_WAIT 11 /* in 2*msl quiet wait after close */ +#define IPF_TCPS_FIN_WAIT_2 9 /* have closed, fin is acked */ +#define IPF_TCPS_TIME_WAIT 10 /* in 2*msl quiet wait after close */ +#define IPF_TCPS_CLOSED 11 /* closed */ #define IPF_TCP_NSTATES 12 #define TCP_MSL 120 @@ -2273,7 +2758,7 @@ typedef struct tcpiphdr tcpiphdr_t; /* * ICMP error replies have an IP header (20 bytes), 8 bytes of ICMP data, * another IP header and then 64 bits of data, totalling 56. Of course, - * the last 64 bits is dependant on that being available. + * the last 64 bits is dependent on that being available. */ #define ICMPERR_ICMPHLEN 8 #define ICMPERR_IPICMPHLEN (20 + 8) @@ -2286,10 +2771,50 @@ typedef struct tcpiphdr tcpiphdr_t; # define MIN(a,b) (((a)<(b))?(a):(b)) #endif +#ifdef RESCUE +# undef IPFILTER_BPF +#endif + #ifdef IPF_DEBUG # define DPRINT(x) printf x #else # define DPRINT(x) #endif +#ifndef AF_INET6 +# define AF_INET6 26 +#endif + +#ifdef DTRACE_PROBE +# ifdef _KERNEL +# define DT(_n) DTRACE_PROBE(_n) +# define DT1(_n,_a,_b) DTRACE_PROBE1(_n,_a,_b) +# define DT2(_n,_a,_b,_c,_d) DTRACE_PROBE2(_n,_a,_b,_c,_d) +# define DT3(_n,_a,_b,_c,_d,_e,_f) \ + DTRACE_PROBE3(_n,_a,_b,_c,_d,_e,_f) +# define DT4(_n,_a,_b,_c,_d,_e,_f,_g,_h) \ + DTRACE_PROBE4(_n,_a,_b,_c,_d,_e,_f,_g,_h) +# else +# define DT(_n) +# define DT1(_n,_a,_b) +# define DT2(_n,_a,_b,_c,_d) +# define DT3(_n,_a,_b,_c,_d,_e,_f) +# define DT4(_n,_a,_b,_c,_d,_e,_f,_g,_h) +# endif +#else +# define DT(_n) +# define DT1(_n,_a,_b) +# define DT2(_n,_a,_b,_c,_d) +# define DT3(_n,_a,_b,_c,_d,_e,_f) +# define DT4(_n,_a,_b,_c,_d,_e,_f,_g,_h) +#endif + +struct ip6_routing { + u_char ip6r_nxt; /* next header */ + u_char ip6r_len; /* length in units of 8 octets */ + u_char ip6r_type; /* always zero */ + u_char ip6r_segleft; /* segments left */ + u_32_t ip6r_reserved; /* reserved field */ +}; + #endif /* __IP_COMPAT_H__ */ diff --git a/ip_dns_pxy.c b/ip_dns_pxy.c new file mode 100644 index 0000000000000..df863b8f6fb6b --- /dev/null +++ b/ip_dns_pxy.c @@ -0,0 +1,402 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: ip_dns_pxy.c,v 1.1.2.10 2012/07/22 08:04:23 darren_r Exp $ + */ + +#define IPF_DNS_PROXY + +/* + * map ... proxy port dns/udp 53 { block .cnn.com; } + */ +typedef struct ipf_dns_filter { + struct ipf_dns_filter *idns_next; + char *idns_name; + int idns_namelen; + int idns_pass; +} ipf_dns_filter_t; + + +typedef struct ipf_dns_softc_s { + ipf_dns_filter_t *ipf_p_dns_list; + ipfrwlock_t ipf_p_dns_rwlock; + u_long ipf_p_dns_compress; + u_long ipf_p_dns_toolong; + u_long ipf_p_dns_nospace; +} ipf_dns_softc_t; + +int ipf_p_dns_allow_query __P((ipf_dns_softc_t *, dnsinfo_t *)); +int ipf_p_dns_ctl __P((ipf_main_softc_t *, void *, ap_ctl_t *)); +int ipf_p_dns_del __P((ipf_main_softc_t *, ap_session_t *)); +int ipf_p_dns_get_name __P((ipf_dns_softc_t *, char *, int, char *, int)); +int ipf_p_dns_inout __P((void *, fr_info_t *, ap_session_t *, nat_t *)); +int ipf_p_dns_match __P((fr_info_t *, ap_session_t *, nat_t *)); +int ipf_p_dns_match_names __P((ipf_dns_filter_t *, char *, int)); +int ipf_p_dns_new __P((void *, fr_info_t *, ap_session_t *, nat_t *)); +void *ipf_p_dns_soft_create __P((ipf_main_softc_t *)); +void ipf_p_dns_soft_destroy __P((ipf_main_softc_t *, void *)); + +typedef struct { + u_char dns_id[2]; + u_short dns_ctlword; + u_short dns_qdcount; + u_short dns_ancount; + u_short dns_nscount; + u_short dns_arcount; +} ipf_dns_hdr_t; + +#define DNS_QR(x) ((ntohs(x) & 0x8000) >> 15) +#define DNS_OPCODE(x) ((ntohs(x) & 0x7800) >> 11) +#define DNS_AA(x) ((ntohs(x) & 0x0400) >> 10) +#define DNS_TC(x) ((ntohs(x) & 0x0200) >> 9) +#define DNS_RD(x) ((ntohs(x) & 0x0100) >> 8) +#define DNS_RA(x) ((ntohs(x) & 0x0080) >> 7) +#define DNS_Z(x) ((ntohs(x) & 0x0070) >> 4) +#define DNS_RCODE(x) ((ntohs(x) & 0x000f) >> 0) + + +void * +ipf_p_dns_soft_create(softc) + ipf_main_softc_t *softc; +{ + ipf_dns_softc_t *softd; + + KMALLOC(softd, ipf_dns_softc_t *); + if (softd == NULL) + return NULL; + + bzero((char *)softd, sizeof(*softd)); + RWLOCK_INIT(&softd->ipf_p_dns_rwlock, "ipf dns rwlock"); + + return softd; +} + + +void +ipf_p_dns_soft_destroy(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_dns_softc_t *softd = arg; + ipf_dns_filter_t *idns; + + while ((idns = softd->ipf_p_dns_list) != NULL) { + KFREES(idns->idns_name, idns->idns_namelen); + idns->idns_name = NULL; + idns->idns_namelen = 0; + softd->ipf_p_dns_list = idns->idns_next; + KFREE(idns); + } + RW_DESTROY(&softd->ipf_p_dns_rwlock); + + KFREE(softd); +} + + +int +ipf_p_dns_ctl(softc, arg, ctl) + ipf_main_softc_t *softc; + void *arg; + ap_ctl_t *ctl; +{ + ipf_dns_softc_t *softd = arg; + ipf_dns_filter_t *tmp, *idns, **idnsp; + int error = 0; + + /* + * To make locking easier. + */ + KMALLOC(tmp, ipf_dns_filter_t *); + + WRITE_ENTER(&softd->ipf_p_dns_rwlock); + for (idnsp = &softd->ipf_p_dns_list; (idns = *idnsp) != NULL; + idnsp = &idns->idns_next) { + if (idns->idns_namelen != ctl->apc_dsize) + continue; + if (!strncmp(ctl->apc_data, idns->idns_name, + idns->idns_namelen)) + break; + } + + switch (ctl->apc_cmd) + { + case APC_CMD_DEL : + if (idns == NULL) { + IPFERROR(80006); + error = ESRCH; + break; + } + *idnsp = idns->idns_next; + idns->idns_next = NULL; + KFREES(idns->idns_name, idns->idns_namelen); + idns->idns_name = NULL; + idns->idns_namelen = 0; + KFREE(idns); + break; + case APC_CMD_ADD : + if (idns != NULL) { + IPFERROR(80007); + error = EEXIST; + break; + } + if (tmp == NULL) { + IPFERROR(80008); + error = ENOMEM; + break; + } + idns = tmp; + tmp = NULL; + idns->idns_namelen = ctl->apc_dsize; + idns->idns_name = ctl->apc_data; + idns->idns_pass = ctl->apc_arg; + idns->idns_next = NULL; + *idnsp = idns; + ctl->apc_data = NULL; + ctl->apc_dsize = 0; + break; + default : + IPFERROR(80009); + error = EINVAL; + break; + } + RWLOCK_EXIT(&softd->ipf_p_dns_rwlock); + + if (tmp != NULL) { + KFREE(tmp); + tmp = NULL; + } + + return error; +} + + +/* ARGSUSED */ +int +ipf_p_dns_new(arg, fin, aps, nat) + void *arg; + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; +{ + dnsinfo_t *di; + int dlen; + + if (fin->fin_v != 4) + return -1; + + dlen = fin->fin_dlen - sizeof(udphdr_t); + if (dlen < sizeof(ipf_dns_hdr_t)) { + /* + * No real DNS packet is smaller than that. + */ + return -1; + } + + aps->aps_psiz = sizeof(dnsinfo_t); + KMALLOCS(di, dnsinfo_t *, sizeof(dnsinfo_t)); + if (di == NULL) { + printf("ipf_dns_new:KMALLOCS(%d) failed\n", sizeof(*di)); + return -1; + } + + MUTEX_INIT(&di->dnsi_lock, "dns lock"); + + aps->aps_data = di; + + dlen = fin->fin_dlen - sizeof(udphdr_t); + COPYDATA(fin->fin_m, fin->fin_hlen + sizeof(udphdr_t), + MIN(dlen, sizeof(di->dnsi_buffer)), di->dnsi_buffer); + di->dnsi_id = (di->dnsi_buffer[0] << 8) | di->dnsi_buffer[1]; + return 0; +} + + +/* ARGSUSED */ +int +ipf_p_dns_del(softc, aps) + ipf_main_softc_t *softc; + ap_session_t *aps; +{ +#ifdef USE_MUTEXES + dnsinfo_t *di = aps->aps_data; + + MUTEX_DESTROY(&di->dnsi_lock); +#endif + KFREES(aps->aps_data, aps->aps_psiz); + aps->aps_data = NULL; + aps->aps_psiz = 0; + return 0; +} + + +/* + * Tries to match the base string (in our ACL) with the query from a packet. + */ +int +ipf_p_dns_match_names(idns, query, qlen) + ipf_dns_filter_t *idns; + char *query; + int qlen; +{ + int blen; + char *base; + + blen = idns->idns_namelen; + base = idns->idns_name; + + if (blen > qlen) + return 1; + + if (blen == qlen) + return strncasecmp(base, query, qlen); + + /* + * If the base string string is shorter than the query, allow the + * tail of the base to match the same length tail of the query *if*: + * - the base string starts with a '*' (*cnn.com) + * - the base string represents a domain (.cnn.com) + * as otherwise it would not be possible to block just "cnn.com" + * without also impacting "foocnn.com", etc. + */ + if (*base == '*') { + base++; + blen--; + } else if (*base != '.') + return 1; + + return strncasecmp(base, query + qlen - blen, blen); +} + + +int +ipf_p_dns_get_name(softd, start, len, buffer, buflen) + ipf_dns_softc_t *softd; + char *start; + int len; + char *buffer; + int buflen; +{ + char *s, *t, clen; + int slen, blen; + + s = start; + t = buffer; + slen = len; + blen = buflen - 1; /* Always make room for trailing \0 */ + + while (*s != '\0') { + clen = *s; + if ((clen & 0xc0) == 0xc0) { /* Doesn't do compression */ + softd->ipf_p_dns_compress++; + return 0; + } + if (clen > slen) { + softd->ipf_p_dns_toolong++; + return 0; /* Does the name run off the end? */ + } + if ((clen + 1) > blen) { + softd->ipf_p_dns_nospace++; + return 0; /* Enough room for name+.? */ + } + s++; + bcopy(s, t, clen); + t += clen; + s += clen; + *t++ = '.'; + slen -= clen; + blen -= (clen + 1); + } + + *(t - 1) = '\0'; + return s - start; +} + + +int +ipf_p_dns_allow_query(softd, dnsi) + ipf_dns_softc_t *softd; + dnsinfo_t *dnsi; +{ + ipf_dns_filter_t *idns; + int len; + + len = strlen(dnsi->dnsi_buffer); + + for (idns = softd->ipf_p_dns_list; idns != NULL; idns = idns->idns_next) + if (ipf_p_dns_match_names(idns, dnsi->dnsi_buffer, len) == 0) + return idns->idns_pass; + return 0; +} + + +/* ARGSUSED */ +int +ipf_p_dns_inout(arg, fin, aps, nat) + void *arg; + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; +{ + ipf_dns_softc_t *softd = arg; + ipf_dns_hdr_t *dns; + dnsinfo_t *di; + char *data; + int dlen, q, rc = 0; + + if (fin->fin_dlen < sizeof(*dns)) + return APR_ERR(1); + + dns = (ipf_dns_hdr_t *)((char *)fin->fin_dp + sizeof(udphdr_t)); + + q = dns->dns_qdcount; + + data = (char *)(dns + 1); + dlen = fin->fin_dlen - sizeof(*dns) - sizeof(udphdr_t); + + di = aps->aps_data; + + READ_ENTER(&softd->ipf_p_dns_rwlock); + MUTEX_ENTER(&di->dnsi_lock); + + for (; (dlen > 0) && (q > 0); q--) { + int len; + + len = ipf_p_dns_get_name(softd, data, dlen, di->dnsi_buffer, + sizeof(di->dnsi_buffer)); + if (len == 0) { + rc = 1; + break; + } + rc = ipf_p_dns_allow_query(softd, di); + if (rc != 0) + break; + data += len; + dlen -= len; + } + MUTEX_EXIT(&di->dnsi_lock); + RWLOCK_EXIT(&softd->ipf_p_dns_rwlock); + + return APR_ERR(rc); +} + + +/* ARGSUSED */ +int +ipf_p_dns_match(fin, aps, nat) + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; +{ + dnsinfo_t *di = aps->aps_data; + ipf_dns_hdr_t *dnh; + + if ((fin->fin_dlen < sizeof(u_short)) || (fin->fin_flx & FI_FRAG)) + return -1; + + dnh = (ipf_dns_hdr_t *)((char *)fin->fin_dp + sizeof(udphdr_t)); + if (((dnh->dns_id[0] << 8) | dnh->dns_id[1]) != di->dnsi_id) + return -1; + return 0; +} diff --git a/ip_dstlist.c b/ip_dstlist.c new file mode 100644 index 0000000000000..ce2e72e8130f2 --- /dev/null +++ b/ip_dstlist.c @@ -0,0 +1,1351 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ +#if defined(KERNEL) || defined(_KERNEL) +# undef KERNEL +# undef _KERNEL +# define KERNEL 1 +# define _KERNEL 1 +#endif +#if defined(__osf__) +# define _PROTO_NET_H_ +#endif +#include <sys/errno.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/file.h> +#if !defined(_KERNEL) && !defined(__KERNEL__) +# include <stdio.h> +# include <stdlib.h> +# include <string.h> +# define _KERNEL +# ifdef __OpenBSD__ +struct file; +# endif +# include <sys/uio.h> +# undef _KERNEL +#else +# include <sys/systm.h> +# if defined(NetBSD) && (__NetBSD_Version__ >= 104000000) +# include <sys/proc.h> +# endif +#endif +#include <sys/time.h> +#if !defined(linux) +# include <sys/protosw.h> +#endif +#include <sys/socket.h> +#if defined(_KERNEL) && (!defined(__SVR4) && !defined(__svr4__)) +# include <sys/mbuf.h> +#endif +#if defined(__SVR4) || defined(__svr4__) +# include <sys/filio.h> +# include <sys/byteorder.h> +# ifdef _KERNEL +# include <sys/dditypes.h> +# endif +# include <sys/stream.h> +# include <sys/kmem.h> +#endif +#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) +# include <sys/malloc.h> +#endif + +#include <net/if.h> +#include <netinet/in.h> + +#include "netinet/ip_compat.h" +#include "netinet/ip_fil.h" +#include "netinet/ip_nat.h" +#include "netinet/ip_lookup.h" +#include "netinet/ip_dstlist.h" + +/* END OF INCLUDES */ + +#ifdef HAS_SYS_MD5_H +# include <sys/md5.h> +#else +# include "md5.h" +#endif + +#if !defined(lint) +static const char rcsid[] = "@(#)$Id: ip_dstlist.c,v 1.13.2.12 2012/07/20 08:40:19 darren_r Exp $"; +#endif + +typedef struct ipf_dstl_softc_s { + ippool_dst_t *dstlist[LOOKUP_POOL_SZ]; + ippool_dst_t **tails[LOOKUP_POOL_SZ]; + ipf_dstl_stat_t stats; +} ipf_dstl_softc_t; + + +static void *ipf_dstlist_soft_create __P((ipf_main_softc_t *)); +static void ipf_dstlist_soft_destroy __P((ipf_main_softc_t *, void *)); +static int ipf_dstlist_soft_init __P((ipf_main_softc_t *, void *)); +static void ipf_dstlist_soft_fini __P((ipf_main_softc_t *, void *)); +static int ipf_dstlist_addr_find __P((ipf_main_softc_t *, void *, int, + void *, u_int)); +static size_t ipf_dstlist_flush __P((ipf_main_softc_t *, void *, + iplookupflush_t *)); +static int ipf_dstlist_iter_deref __P((ipf_main_softc_t *, void *, int, int, + void *)); +static int ipf_dstlist_iter_next __P((ipf_main_softc_t *, void *, ipftoken_t *, + ipflookupiter_t *)); +static int ipf_dstlist_node_add __P((ipf_main_softc_t *, void *, + iplookupop_t *, int)); +static int ipf_dstlist_node_del __P((ipf_main_softc_t *, void *, + iplookupop_t *, int)); +static int ipf_dstlist_stats_get __P((ipf_main_softc_t *, void *, + iplookupop_t *)); +static int ipf_dstlist_table_add __P((ipf_main_softc_t *, void *, + iplookupop_t *)); +static int ipf_dstlist_table_del __P((ipf_main_softc_t *, void *, + iplookupop_t *)); +static int ipf_dstlist_table_deref __P((ipf_main_softc_t *, void *, void *)); +static void *ipf_dstlist_table_find __P((void *, int, char *)); +static void ipf_dstlist_table_free __P((ipf_dstl_softc_t *, ippool_dst_t *)); +static void ipf_dstlist_table_remove __P((ipf_main_softc_t *, + ipf_dstl_softc_t *, ippool_dst_t *)); +static void ipf_dstlist_table_clearnodes __P((ipf_dstl_softc_t *, + ippool_dst_t *)); +static ipf_dstnode_t *ipf_dstlist_select __P((fr_info_t *, ippool_dst_t *)); +static void *ipf_dstlist_select_ref __P((void *, int, char *)); +static void ipf_dstlist_node_free __P((ipf_dstl_softc_t *, ippool_dst_t *, ipf_dstnode_t *)); +static int ipf_dstlist_node_deref __P((void *, ipf_dstnode_t *)); +static void ipf_dstlist_expire __P((ipf_main_softc_t *, void *)); +static void ipf_dstlist_sync __P((ipf_main_softc_t *, void *)); + +ipf_lookup_t ipf_dstlist_backend = { + IPLT_DSTLIST, + ipf_dstlist_soft_create, + ipf_dstlist_soft_destroy, + ipf_dstlist_soft_init, + ipf_dstlist_soft_fini, + ipf_dstlist_addr_find, + ipf_dstlist_flush, + ipf_dstlist_iter_deref, + ipf_dstlist_iter_next, + ipf_dstlist_node_add, + ipf_dstlist_node_del, + ipf_dstlist_stats_get, + ipf_dstlist_table_add, + ipf_dstlist_table_del, + ipf_dstlist_table_deref, + ipf_dstlist_table_find, + ipf_dstlist_select_ref, + ipf_dstlist_select_node, + ipf_dstlist_expire, + ipf_dstlist_sync +}; + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_soft_create */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* */ +/* Allocating a chunk of memory filled with 0's is enough for the current */ +/* soft context used with destination lists. */ +/* ------------------------------------------------------------------------ */ +static void * +ipf_dstlist_soft_create(softc) + ipf_main_softc_t *softc; +{ + ipf_dstl_softc_t *softd; + int i; + + KMALLOC(softd, ipf_dstl_softc_t *); + if (softd == NULL) { + IPFERROR(120028); + return NULL; + } + + bzero((char *)softd, sizeof(*softd)); + for (i = 0; i <= IPL_LOGMAX; i++) + softd->tails[i] = &softd->dstlist[i]; + + return softd; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_soft_destroy */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* */ +/* For destination lists, the only thing we have to do when destroying the */ +/* soft context is free it! */ +/* ------------------------------------------------------------------------ */ +static void +ipf_dstlist_soft_destroy(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_dstl_softc_t *softd = arg; + + KFREE(softd); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_soft_init */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* */ +/* There is currently no soft context for destination list management. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_dstlist_soft_init(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_soft_fini */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* */ +/* There is currently no soft context for destination list management. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_dstlist_soft_fini(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_dstl_softc_t *softd = arg; + int i; + + for (i = -1; i <= IPL_LOGMAX; i++) { + while (softd->dstlist[i + 1] != NULL) { + ipf_dstlist_table_remove(softc, softd, + softd->dstlist[i + 1]); + } + } + + ASSERT(softd->stats.ipls_numderefnodes == 0); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_addr_find */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg1(I) - pointer to local context to use */ +/* arg2(I) - pointer to local context to use */ +/* arg3(I) - pointer to local context to use */ +/* arg4(I) - pointer to local context to use */ +/* */ +/* There is currently no such thing as searching a destination list for an */ +/* address so this function becomes a no-op. Its presence is required as */ +/* ipf_lookup_res_name() stores the "addr_find" function pointer in the */ +/* pointer passed in to it as funcptr, although it could be a generic null- */ +/* op function rather than a specific one. */ +/* ------------------------------------------------------------------------ */ +/*ARGSUSED*/ +static int +ipf_dstlist_addr_find(softc, arg1, arg2, arg3, arg4) + ipf_main_softc_t *softc; + void *arg1, *arg3; + int arg2; + u_int arg4; +{ + return -1; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_flush */ +/* Returns: int - number of objects deleted */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* fop(I) - pointer to lookup flush operation data */ +/* */ +/* Flush all of the destination tables that match the data passed in with */ +/* the iplookupflush_t. There are two ways to match objects: the device for */ +/* which they are to be used with and their name. */ +/* ------------------------------------------------------------------------ */ +static size_t +ipf_dstlist_flush(softc, arg, fop) + ipf_main_softc_t *softc; + void *arg; + iplookupflush_t *fop; +{ + ipf_dstl_softc_t *softd = arg; + ippool_dst_t *node, *next; + int n, i; + + for (n = 0, i = -1; i <= IPL_LOGMAX; i++) { + if (fop->iplf_unit != IPLT_ALL && fop->iplf_unit != i) + continue; + for (node = softd->dstlist[i + 1]; node != NULL; node = next) { + next = node->ipld_next; + + if ((*fop->iplf_name != '\0') && + strncmp(fop->iplf_name, node->ipld_name, + FR_GROUPLEN)) + continue; + + ipf_dstlist_table_remove(softc, softd, node); + n++; + } + } + return n; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_iter_deref */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* otype(I) - type of data structure to iterate through */ +/* unit(I) - device we are working with */ +/* data(I) - address of object in kernel space */ +/* */ +/* This function is called when the iteration token is being free'd and is */ +/* responsible for dropping the reference count of the structure it points */ +/* to. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_dstlist_iter_deref(softc, arg, otype, unit, data) + ipf_main_softc_t *softc; + void *arg; + int otype, unit; + void *data; +{ + if (data == NULL) { + IPFERROR(120001); + return EINVAL; + } + + if (unit < -1 || unit > IPL_LOGMAX) { + IPFERROR(120002); + return EINVAL; + } + + switch (otype) + { + case IPFLOOKUPITER_LIST : + ipf_dstlist_table_deref(softc, arg, (ippool_dst_t *)data); + break; + + case IPFLOOKUPITER_NODE : + ipf_dstlist_node_deref(arg, (ipf_dstnode_t *)data); + break; + } + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_iter_next */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* op(I) - pointer to lookup operation data */ +/* uid(I) - uid of process doing the ioctl */ +/* */ +/* This function is responsible for either selecting the next destination */ +/* list or node on a destination list to be returned as a user process */ +/* iterates through the list of destination lists or nodes. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_dstlist_iter_next(softc, arg, token, iter) + ipf_main_softc_t *softc; + void *arg; + ipftoken_t *token; + ipflookupiter_t *iter; +{ + ipf_dstnode_t zn, *nextnode = NULL, *node = NULL; + ippool_dst_t zero, *next = NULL, *dsttab = NULL; + ipf_dstl_softc_t *softd = arg; + int err = 0; + void *hint; + + switch (iter->ili_otype) + { + case IPFLOOKUPITER_LIST : + dsttab = token->ipt_data; + if (dsttab == NULL) { + next = softd->dstlist[(int)iter->ili_unit + 1]; + } else { + next = dsttab->ipld_next; + } + + if (next != NULL) { + ATOMIC_INC32(next->ipld_ref); + token->ipt_data = next; + hint = next->ipld_next; + } else { + bzero((char *)&zero, sizeof(zero)); + next = &zero; + token->ipt_data = NULL; + hint = NULL; + } + break; + + case IPFLOOKUPITER_NODE : + node = token->ipt_data; + if (node == NULL) { + dsttab = ipf_dstlist_table_find(arg, iter->ili_unit, + iter->ili_name); + if (dsttab == NULL) { + IPFERROR(120004); + err = ESRCH; + nextnode = NULL; + } else { + if (dsttab->ipld_dests == NULL) + nextnode = NULL; + else + nextnode = *dsttab->ipld_dests; + dsttab = NULL; + } + } else { + nextnode = node->ipfd_next; + } + + if (nextnode != NULL) { + MUTEX_ENTER(&nextnode->ipfd_lock); + nextnode->ipfd_ref++; + MUTEX_EXIT(&nextnode->ipfd_lock); + token->ipt_data = nextnode; + hint = nextnode->ipfd_next; + } else { + bzero((char *)&zn, sizeof(zn)); + nextnode = &zn; + token->ipt_data = NULL; + hint = NULL; + } + break; + default : + IPFERROR(120003); + err = EINVAL; + break; + } + + if (err != 0) + return err; + + switch (iter->ili_otype) + { + case IPFLOOKUPITER_LIST : + if (dsttab != NULL) + ipf_dstlist_table_deref(softc, arg, dsttab); + err = COPYOUT(next, iter->ili_data, sizeof(*next)); + if (err != 0) { + IPFERROR(120005); + err = EFAULT; + } + break; + + case IPFLOOKUPITER_NODE : + if (node != NULL) + ipf_dstlist_node_deref(arg, node); + err = COPYOUT(nextnode, iter->ili_data, sizeof(*nextnode)); + if (err != 0) { + IPFERROR(120006); + err = EFAULT; + } + break; + } + + if (hint == NULL) + ipf_token_mark_complete(token); + + return err; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_node_add */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* op(I) - pointer to lookup operation data */ +/* uid(I) - uid of process doing the ioctl */ +/* Locks: WRITE(ipf_poolrw) */ +/* */ +/* Add a new node to a destination list. To do this, we only copy in the */ +/* frdest_t structure because that contains the only data required from the */ +/* application to create a new node. The frdest_t doesn't contain the name */ +/* itself. When loading filter rules, fd_name is a 'pointer' to the name. */ +/* In this case, the 'pointer' does not work, instead it is the length of */ +/* the name and the name is immediately following the frdest_t structure. */ +/* fd_name must include the trailing \0, so it should be strlen(str) + 1. */ +/* For simple sanity checking, an upper bound on the size of fd_name is */ +/* imposed - 128. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_dstlist_node_add(softc, arg, op, uid) + ipf_main_softc_t *softc; + void *arg; + iplookupop_t *op; + int uid; +{ + ipf_dstl_softc_t *softd = arg; + ipf_dstnode_t *node, **nodes; + ippool_dst_t *d; + frdest_t dest; + int err; + + if (op->iplo_size < sizeof(frdest_t)) { + IPFERROR(120007); + return EINVAL; + } + + err = COPYIN(op->iplo_struct, &dest, sizeof(dest)); + if (err != 0) { + IPFERROR(120009); + return EFAULT; + } + + d = ipf_dstlist_table_find(arg, op->iplo_unit, op->iplo_name); + if (d == NULL) { + IPFERROR(120010); + return ESRCH; + } + + switch (dest.fd_addr.adf_family) + { + case AF_INET : + case AF_INET6 : + break; + default : + IPFERROR(120019); + return EINVAL; + } + + if (dest.fd_name < -1 || dest.fd_name > 128) { + IPFERROR(120018); + return EINVAL; + } + + KMALLOCS(node, ipf_dstnode_t *, sizeof(*node) + dest.fd_name); + if (node == NULL) { + softd->stats.ipls_nomem++; + IPFERROR(120008); + return ENOMEM; + } + bzero((char *)node, sizeof(*node) + dest.fd_name); + + bcopy(&dest, &node->ipfd_dest, sizeof(dest)); + node->ipfd_size = sizeof(*node) + dest.fd_name; + + if (dest.fd_name > 0) { + /* + * fd_name starts out as the length of the string to copy + * in (including \0) and ends up being the offset from + * fd_names (0). + */ + err = COPYIN((char *)op->iplo_struct + sizeof(dest), + node->ipfd_names, dest.fd_name); + if (err != 0) { + IPFERROR(120017); + KFREES(node, node->ipfd_size); + return EFAULT; + } + node->ipfd_dest.fd_name = 0; + } else { + node->ipfd_dest.fd_name = -1; + } + + if (d->ipld_nodes == d->ipld_maxnodes) { + KMALLOCS(nodes, ipf_dstnode_t **, + sizeof(*nodes) * (d->ipld_maxnodes + 1)); + if (nodes == NULL) { + softd->stats.ipls_nomem++; + IPFERROR(120022); + KFREES(node, node->ipfd_size); + return ENOMEM; + } + if (d->ipld_dests != NULL) { + bcopy(d->ipld_dests, nodes, + sizeof(*nodes) * d->ipld_maxnodes); + KFREES(d->ipld_dests, sizeof(*nodes) * d->ipld_nodes); + nodes[0]->ipfd_pnext = nodes; + } + d->ipld_dests = nodes; + d->ipld_maxnodes++; + } + d->ipld_dests[d->ipld_nodes] = node; + d->ipld_nodes++; + + if (d->ipld_nodes == 1) { + node->ipfd_pnext = d->ipld_dests; + } else if (d->ipld_nodes > 1) { + node->ipfd_pnext = &d->ipld_dests[d->ipld_nodes - 2]->ipfd_next; + } + *node->ipfd_pnext = node; + + MUTEX_INIT(&node->ipfd_lock, "ipf dst node lock"); + node->ipfd_uid = uid; + node->ipfd_ref = 1; + if (node->ipfd_dest.fd_name == 0) + (void) ipf_resolvedest(softc, node->ipfd_names, + &node->ipfd_dest, AF_INET); +#ifdef USE_INET6 + if (node->ipfd_dest.fd_name == 0 && + node->ipfd_dest.fd_ptr == (void *)-1) + (void) ipf_resolvedest(softc, node->ipfd_names, + &node->ipfd_dest, AF_INET6); +#endif + + softd->stats.ipls_numnodes++; + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_node_deref */ +/* Returns: int - 0 = success, else error */ +/* Parameters: arg(I) - pointer to local context to use */ +/* node(I) - pointer to destionation node to free */ +/* */ +/* Dereference the use count by one. If it drops to zero then we can assume */ +/* that it has been removed from any lists/tables and is ripe for freeing. */ +/* The pointer to context is required for the purpose of maintaining */ +/* statistics. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_dstlist_node_deref(arg, node) + void *arg; + ipf_dstnode_t *node; +{ + ipf_dstl_softc_t *softd = arg; + int ref; + + MUTEX_ENTER(&node->ipfd_lock); + ref = --node->ipfd_ref; + MUTEX_EXIT(&node->ipfd_lock); + + if (ref > 0) + return 0; + + if ((node->ipfd_flags & IPDST_DELETE) != 0) + softd->stats.ipls_numderefnodes--; + MUTEX_DESTROY(&node->ipfd_lock); + KFREES(node, node->ipfd_size); + softd->stats.ipls_numnodes--; + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_node_del */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* op(I) - pointer to lookup operation data */ +/* uid(I) - uid of process doing the ioctl */ +/* */ +/* Look for a matching destination node on the named table and free it if */ +/* found. Because the name embedded in the frdest_t is variable in length, */ +/* it is necessary to allocate some memory locally, to complete this op. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_dstlist_node_del(softc, arg, op, uid) + ipf_main_softc_t *softc; + void *arg; + iplookupop_t *op; + int uid; +{ + ipf_dstl_softc_t *softd = arg; + ipf_dstnode_t *node; + frdest_t frd, *temp; + ippool_dst_t *d; + size_t size; + int err; + + d = ipf_dstlist_table_find(arg, op->iplo_unit, op->iplo_name); + if (d == NULL) { + IPFERROR(120012); + return ESRCH; + } + + err = COPYIN(op->iplo_struct, &frd, sizeof(frd)); + if (err != 0) { + IPFERROR(120011); + return EFAULT; + } + + size = sizeof(*temp) + frd.fd_name; + KMALLOCS(temp, frdest_t *, size); + if (temp == NULL) { + softd->stats.ipls_nomem++; + IPFERROR(120026); + return ENOMEM; + } + + err = COPYIN(op->iplo_struct, temp, size); + if (err != 0) { + IPFERROR(120027); + return EFAULT; + } + + MUTEX_ENTER(&d->ipld_lock); + for (node = *d->ipld_dests; node != NULL; node = node->ipfd_next) { + if ((uid != 0) && (node->ipfd_uid != uid)) + continue; + if (node->ipfd_size != size) + continue; + if (!bcmp(&node->ipfd_dest.fd_ip6, &frd.fd_ip6, + size - offsetof(frdest_t, fd_ip6))) { + ipf_dstlist_node_free(softd, d, node); + MUTEX_EXIT(&d->ipld_lock); + KFREES(temp, size); + return 0; + } + } + MUTEX_EXIT(&d->ipld_lock); + KFREES(temp, size); + + return ESRCH; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_node_free */ +/* Returns: Nil */ +/* Parameters: softd(I) - pointer to the destination list context */ +/* d(I) - pointer to destination list */ +/* node(I) - pointer to node to free */ +/* Locks: MUTEX(ipld_lock) or WRITE(ipf_poolrw) */ +/* */ +/* Free the destination node by first removing it from any lists and then */ +/* checking if this was the last reference held to the object. While the */ +/* array of pointers to nodes is compacted, its size isn't reduced (by way */ +/* of allocating a new smaller one and copying) because the belief is that */ +/* it is likely the array will again reach that size. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_dstlist_node_free(softd, d, node) + ipf_dstl_softc_t *softd; + ippool_dst_t *d; + ipf_dstnode_t *node; +{ + int i; + + /* + * Compact the array of pointers to nodes. + */ + for (i = 0; i < d->ipld_nodes; i++) + if (d->ipld_dests[i] == node) + break; + if (d->ipld_nodes - i > 1) { + bcopy(&d->ipld_dests[i + 1], &d->ipld_dests[i], + sizeof(*d->ipld_dests) * (d->ipld_nodes - i - 1)); + } + d->ipld_nodes--; + + if (node->ipfd_pnext != NULL) + *node->ipfd_pnext = node->ipfd_next; + if (node->ipfd_next != NULL) + node->ipfd_next->ipfd_pnext = node->ipfd_pnext; + node->ipfd_pnext = NULL; + node->ipfd_next = NULL; + + if ((node->ipfd_flags & IPDST_DELETE) == 0) { + softd->stats.ipls_numderefnodes++; + node->ipfd_flags |= IPDST_DELETE; + } + + ipf_dstlist_node_deref(softd, node); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_stats_get */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* op(I) - pointer to lookup operation data */ +/* */ +/* Return the current statistics for destination lists. This may be for all */ +/* of them or just information pertaining to a particular table. */ +/* ------------------------------------------------------------------------ */ +/*ARGSUSED*/ +static int +ipf_dstlist_stats_get(softc, arg, op) + ipf_main_softc_t *softc; + void *arg; + iplookupop_t *op; +{ + ipf_dstl_softc_t *softd = arg; + ipf_dstl_stat_t stats; + int unit, i, err = 0; + + if (op->iplo_size != sizeof(ipf_dstl_stat_t)) { + IPFERROR(120023); + return EINVAL; + } + + stats = softd->stats; + unit = op->iplo_unit; + if (unit == IPL_LOGALL) { + for (i = 0; i <= IPL_LOGMAX; i++) + stats.ipls_list[i] = softd->dstlist[i]; + } else if (unit >= 0 && unit <= IPL_LOGMAX) { + void *ptr; + + if (op->iplo_name[0] != '\0') + ptr = ipf_dstlist_table_find(softd, unit, + op->iplo_name); + else + ptr = softd->dstlist[unit + 1]; + stats.ipls_list[unit] = ptr; + } else { + IPFERROR(120024); + err = EINVAL; + } + + if (err == 0) { + err = COPYOUT(&stats, op->iplo_struct, sizeof(stats)); + if (err != 0) { + IPFERROR(120025); + return EFAULT; + } + } + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_table_add */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* op(I) - pointer to lookup operation data */ +/* */ +/* Add a new destination table to the list of those available for the given */ +/* device. Because we seldom operate on these objects (find/add/delete), */ +/* they are just kept in a simple linked list. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_dstlist_table_add(softc, arg, op) + ipf_main_softc_t *softc; + void *arg; + iplookupop_t *op; +{ + ipf_dstl_softc_t *softd = arg; + ippool_dst_t user, *d, *new; + int unit, err; + + d = ipf_dstlist_table_find(arg, op->iplo_unit, op->iplo_name); + if (d != NULL) { + IPFERROR(120013); + return EEXIST; + } + + err = COPYIN(op->iplo_struct, &user, sizeof(user)); + if (err != 0) { + IPFERROR(120021); + return EFAULT; + } + + KMALLOC(new, ippool_dst_t *); + if (new == NULL) { + softd->stats.ipls_nomem++; + IPFERROR(120014); + return ENOMEM; + } + bzero((char *)new, sizeof(*new)); + + MUTEX_INIT(&new->ipld_lock, "ipf dst table lock"); + + strncpy(new->ipld_name, op->iplo_name, FR_GROUPLEN); + unit = op->iplo_unit; + new->ipld_unit = unit; + new->ipld_policy = user.ipld_policy; + new->ipld_seed = ipf_random(); + new->ipld_ref = 1; + + new->ipld_pnext = softd->tails[unit + 1]; + *softd->tails[unit + 1] = new; + softd->tails[unit + 1] = &new->ipld_next; + softd->stats.ipls_numlists++; + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_table_del */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* op(I) - pointer to lookup operation data */ +/* */ +/* Find a named destinstion list table and delete it. If there are other */ +/* references to it, the caller isn't told. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_dstlist_table_del(softc, arg, op) + ipf_main_softc_t *softc; + void *arg; + iplookupop_t *op; +{ + ippool_dst_t *d; + + d = ipf_dstlist_table_find(arg, op->iplo_unit, op->iplo_name); + if (d == NULL) { + IPFERROR(120015); + return ESRCH; + } + + if (d->ipld_dests != NULL) { + IPFERROR(120016); + return EBUSY; + } + + ipf_dstlist_table_remove(softc, arg, d); + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_table_remove */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* softd(I) - pointer to the destination list context */ +/* d(I) - pointer to destination list */ +/* */ +/* Remove a given destination list from existance. While the IPDST_DELETE */ +/* flag is set every time we call this function and the reference count is */ +/* non-zero, the "numdereflists" counter is always incremented because the */ +/* decision about whether it will be freed or not is not made here. This */ +/* means that the only action the code can take here is to treat it as if */ +/* it will become a detached. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_dstlist_table_remove(softc, softd, d) + ipf_main_softc_t *softc; + ipf_dstl_softc_t *softd; + ippool_dst_t *d; +{ + + if (softd->tails[d->ipld_unit + 1] == &d->ipld_next) + softd->tails[d->ipld_unit + 1] = d->ipld_pnext; + + if (d->ipld_pnext != NULL) + *d->ipld_pnext = d->ipld_next; + if (d->ipld_next != NULL) + d->ipld_next->ipld_pnext = d->ipld_pnext; + d->ipld_pnext = NULL; + d->ipld_next = NULL; + + ipf_dstlist_table_clearnodes(softd, d); + + softd->stats.ipls_numdereflists++; + d->ipld_flags |= IPDST_DELETE; + + ipf_dstlist_table_deref(softc, softd, d); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_table_free */ +/* Returns: Nil */ +/* Parameters: softd(I) - pointer to the destination list context */ +/* d(I) - pointer to destination list */ +/* */ +/* Free up a destination list data structure and any other memory that was */ +/* directly allocated as part of creating it. Individual destination list */ +/* nodes are not freed. It is assumed the caller will have already emptied */ +/* the destination list. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_dstlist_table_free(softd, d) + ipf_dstl_softc_t *softd; + ippool_dst_t *d; +{ + MUTEX_DESTROY(&d->ipld_lock); + + if ((d->ipld_flags & IPDST_DELETE) != 0) + softd->stats.ipls_numdereflists--; + softd->stats.ipls_numlists--; + + if (d->ipld_dests != NULL) { + KFREES(d->ipld_dests, + d->ipld_maxnodes * sizeof(*d->ipld_dests)); + } + + KFREE(d); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_table_deref */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* op(I) - pointer to lookup operation data */ +/* */ +/* Drops the reference count on a destination list table object and free's */ +/* it if 0 has been reached. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_dstlist_table_deref(softc, arg, table) + ipf_main_softc_t *softc; + void *arg; + void *table; +{ + ippool_dst_t *d = table; + + d->ipld_ref--; + if (d->ipld_ref > 0) + return d->ipld_ref; + + ipf_dstlist_table_free(arg, d); + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_table_clearnodes */ +/* Returns: Nil */ +/* Parameters: softd(I) - pointer to the destination list context */ +/* dst(I) - pointer to destination list */ +/* */ +/* Free all of the destination nodes attached to the given table. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_dstlist_table_clearnodes(softd, dst) + ipf_dstl_softc_t *softd; + ippool_dst_t *dst; +{ + ipf_dstnode_t *node; + + if (dst->ipld_dests == NULL) + return; + + while ((node = *dst->ipld_dests) != NULL) { + ipf_dstlist_node_free(softd, dst, node); + } +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_table_find */ +/* Returns: int - 0 = success, else error */ +/* Parameters: arg(I) - pointer to local context to use */ +/* unit(I) - device we are working with */ +/* name(I) - destination table name to find */ +/* */ +/* Return a pointer to a destination table that matches the unit+name that */ +/* is passed in. */ +/* ------------------------------------------------------------------------ */ +static void * +ipf_dstlist_table_find(arg, unit, name) + void *arg; + int unit; + char *name; +{ + ipf_dstl_softc_t *softd = arg; + ippool_dst_t *d; + + for (d = softd->dstlist[unit + 1]; d != NULL; d = d->ipld_next) { + if ((d->ipld_unit == unit) && + !strncmp(d->ipld_name, name, FR_GROUPLEN)) { + return d; + } + } + + return NULL; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_select_ref */ +/* Returns: void * - NULL = failure, else pointer to table */ +/* Parameters: arg(I) - pointer to local context to use */ +/* unit(I) - device we are working with */ +/* name(I) - destination table name to find */ +/* */ +/* Attempt to find a destination table that matches the name passed in and */ +/* if successful, bump up the reference count on it because we intend to */ +/* store the pointer to it somewhere else. */ +/* ------------------------------------------------------------------------ */ +static void * +ipf_dstlist_select_ref(arg, unit, name) + void *arg; + int unit; + char *name; +{ + ippool_dst_t *d; + + d = ipf_dstlist_table_find(arg, unit, name); + if (d != NULL) { + MUTEX_ENTER(&d->ipld_lock); + d->ipld_ref++; + MUTEX_EXIT(&d->ipld_lock); + } + return d; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_select */ +/* Returns: void * - NULL = failure, else pointer to table */ +/* Parameters: fin(I) - pointer to packet information */ +/* d(I) - pointer to destination list */ +/* */ +/* Find the next node in the destination list to be used according to the */ +/* defined policy. Of these, "connection" is the most expensive policy to */ +/* implement as it always looks for the node with the least number of */ +/* connections associated with it. */ +/* */ +/* The hashes exclude the port numbers so that all protocols map to the */ +/* same destination. Otherwise, someone doing a ping would target a */ +/* different server than their TCP connection, etc. MD-5 is used to */ +/* transform the addressese into something random that the other end could */ +/* not easily guess and use in an attack. ipld_seed introduces an unknown */ +/* into the hash calculation to increase the difficult of an attacker */ +/* guessing the bucket. */ +/* */ +/* One final comment: mixing different address families in a single pool */ +/* will currently result in failures as the address family of the node is */ +/* only matched up with that in the packet as the last step. While this can */ +/* be coded around for the weighted connection and round-robin models, it */ +/* cannot be supported for the hash/random models as they do not search and */ +/* nor is the algorithm conducive to searching. */ +/* ------------------------------------------------------------------------ */ +static ipf_dstnode_t * +ipf_dstlist_select(fin, d) + fr_info_t *fin; + ippool_dst_t *d; +{ + ipf_dstnode_t *node, *sel; + int connects; + u_32_t hash[4]; + MD5_CTX ctx; + int family; + int x; + + if (d->ipld_dests == NULL || *d->ipld_dests == NULL) + return NULL; + + family = fin->fin_family; + + MUTEX_ENTER(&d->ipld_lock); + + switch (d->ipld_policy) + { + case IPLDP_ROUNDROBIN: + sel = d->ipld_selected; + if (sel == NULL) { + sel = *d->ipld_dests; + } else { + sel = sel->ipfd_next; + if (sel == NULL) + sel = *d->ipld_dests; + } + break; + + case IPLDP_CONNECTION: + if (d->ipld_selected == NULL) { + sel = *d->ipld_dests; + break; + } + + sel = d->ipld_selected; + connects = 0x7fffffff; + node = sel->ipfd_next; + if (node == NULL) + node = *d->ipld_dests; + while (node != d->ipld_selected) { + if (node->ipfd_states == 0) { + sel = node; + break; + } + if (node->ipfd_states < connects) { + sel = node; + connects = node->ipfd_states; + } + node = node->ipfd_next; + if (node == NULL) + node = *d->ipld_dests; + } + break; + + case IPLDP_RANDOM : + x = ipf_random() % d->ipld_nodes; + sel = d->ipld_dests[x]; + break; + + case IPLDP_HASHED : + MD5Init(&ctx); + MD5Update(&ctx, (u_char *)&d->ipld_seed, sizeof(d->ipld_seed)); + MD5Update(&ctx, (u_char *)&fin->fin_src6, + sizeof(fin->fin_src6)); + MD5Update(&ctx, (u_char *)&fin->fin_dst6, + sizeof(fin->fin_dst6)); + MD5Final((u_char *)hash, &ctx); + x = hash[0] % d->ipld_nodes; + sel = d->ipld_dests[x]; + break; + + case IPLDP_SRCHASH : + MD5Init(&ctx); + MD5Update(&ctx, (u_char *)&d->ipld_seed, sizeof(d->ipld_seed)); + MD5Update(&ctx, (u_char *)&fin->fin_src6, + sizeof(fin->fin_src6)); + MD5Final((u_char *)hash, &ctx); + x = hash[0] % d->ipld_nodes; + sel = d->ipld_dests[x]; + break; + + case IPLDP_DSTHASH : + MD5Init(&ctx); + MD5Update(&ctx, (u_char *)&d->ipld_seed, sizeof(d->ipld_seed)); + MD5Update(&ctx, (u_char *)&fin->fin_dst6, + sizeof(fin->fin_dst6)); + MD5Final((u_char *)hash, &ctx); + x = hash[0] % d->ipld_nodes; + sel = d->ipld_dests[x]; + break; + + default : + sel = NULL; + break; + } + + if (sel->ipfd_dest.fd_addr.adf_family != family) + sel = NULL; + d->ipld_selected = sel; + + MUTEX_EXIT(&d->ipld_lock); + + return sel; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_select_node */ +/* Returns: int - -1 == failure, 0 == success */ +/* Parameters: fin(I) - pointer to packet information */ +/* group(I) - destination pool to search */ +/* addr(I) - pointer to store selected address */ +/* pfdp(O) - pointer to storage for selected destination node */ +/* */ +/* This function is only responsible for obtaining the next IP address for */ +/* use and storing it in the caller's address space (addr). "addr" is only */ +/* used for storage if pfdp is NULL. No permanent reference is currently */ +/* kept on the node. */ +/* ------------------------------------------------------------------------ */ +int +ipf_dstlist_select_node(fin, group, addr, pfdp) + fr_info_t *fin; + void *group; + u_32_t *addr; + frdest_t *pfdp; +{ +#ifdef USE_MUTEXES + ipf_main_softc_t *softc = fin->fin_main_soft; +#endif + ippool_dst_t *d = group; + ipf_dstnode_t *node; + frdest_t *fdp; + + READ_ENTER(&softc->ipf_poolrw); + + node = ipf_dstlist_select(fin, d); + if (node == NULL) { + RWLOCK_EXIT(&softc->ipf_poolrw); + return -1; + } + + if (pfdp != NULL) { + bcopy(&node->ipfd_dest, pfdp, sizeof(*pfdp)); + } else { + if (fin->fin_family == AF_INET) { + addr[0] = node->ipfd_dest.fd_addr.adf_addr.i6[0]; + } else if (fin->fin_family == AF_INET6) { + addr[0] = node->ipfd_dest.fd_addr.adf_addr.i6[0]; + addr[1] = node->ipfd_dest.fd_addr.adf_addr.i6[1]; + addr[2] = node->ipfd_dest.fd_addr.adf_addr.i6[2]; + addr[3] = node->ipfd_dest.fd_addr.adf_addr.i6[3]; + } + } + + fdp = &node->ipfd_dest; + if (fdp->fd_ptr == NULL) + fdp->fd_ptr = fin->fin_ifp; + + MUTEX_ENTER(&node->ipfd_lock); + node->ipfd_states++; + MUTEX_EXIT(&node->ipfd_lock); + + RWLOCK_EXIT(&softc->ipf_poolrw); + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_expire */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* */ +/* There are currently no objects to expire in destination lists. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_dstlist_expire(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + return; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_dstlist_sync */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* */ +/* When a network interface appears or disappears, we need to revalidate */ +/* all of the network interface names that have been configured as a target */ +/* in a destination list. */ +/* ------------------------------------------------------------------------ */ +void +ipf_dstlist_sync(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_dstl_softc_t *softd = arg; + ipf_dstnode_t *node; + ippool_dst_t *list; + int i; + int j; + + for (i = 0; i < IPL_LOGMAX; i++) { + for (list = softd->dstlist[i]; list != NULL; + list = list->ipld_next) { + for (j = 0; j < list->ipld_maxnodes; j++) { + node = list->ipld_dests[j]; + if (node == NULL) + continue; + if (node->ipfd_dest.fd_name == -1) + continue; + (void) ipf_resolvedest(softc, + node->ipfd_names, + &node->ipfd_dest, + AF_INET); + } + } + } +} diff --git a/ip_dstlist.h b/ip_dstlist.h new file mode 100644 index 0000000000000..e2885e5c47ad6 --- /dev/null +++ b/ip_dstlist.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: ip_dstlist.h,v 1.5.2.6 2012/07/22 08:04:23 darren_r Exp $ + */ + +#ifndef __IP_DSTLIST_H__ +#define __IP_DSTLIST_H__ + +typedef struct ipf_dstnode { + struct ipf_dstnode *ipfd_next; + struct ipf_dstnode **ipfd_pnext; + ipfmutex_t ipfd_lock; + frdest_t ipfd_dest; + u_long ipfd_syncat; + int ipfd_flags; + int ipfd_size; + int ipfd_states; + int ipfd_ref; + int ipfd_uid; + char ipfd_names[1]; +} ipf_dstnode_t; + +typedef enum ippool_policy_e { + IPLDP_NONE = 0, + IPLDP_ROUNDROBIN, + IPLDP_CONNECTION, + IPLDP_RANDOM, + IPLDP_HASHED, + IPLDP_SRCHASH, + IPLDP_DSTHASH +} ippool_policy_t; + +typedef struct ippool_dst { + struct ippool_dst *ipld_next; + struct ippool_dst **ipld_pnext; + ipfmutex_t ipld_lock; + int ipld_seed; + int ipld_unit; + int ipld_ref; + int ipld_flags; + int ipld_nodes; + int ipld_maxnodes; + ippool_policy_t ipld_policy; + ipf_dstnode_t **ipld_dests; + ipf_dstnode_t *ipld_selected; + char ipld_name[FR_GROUPLEN]; +} ippool_dst_t; + +#define IPDST_DELETE 0x01 + +typedef struct dstlist_stat_s { + void *ipls_list[LOOKUP_POOL_SZ]; + int ipls_numlists; + u_long ipls_nomem; + int ipls_numnodes; + int ipls_numdereflists; + int ipls_numderefnodes; +} ipf_dstl_stat_t; + +extern ipf_lookup_t ipf_dstlist_backend; + +extern int ipf_dstlist_select_node __P((fr_info_t *, void *, u_32_t *, + frdest_t *)); + +#endif /* __IP_DSTLIST_H__ */ diff --git a/ip_fil.c b/ip_fil.c index f2006e9c805e6..c085af2798a34 100644 --- a/ip_fil.c +++ b/ip_fil.c @@ -1,152 +1,27 @@ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ */ #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.133.2.18 2007/09/09 11:32:05 darrenr Exp $"; -#endif - -#ifndef SOLARIS -#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) -#endif - -#include <sys/param.h> -#if defined(__FreeBSD__) && !defined(__FreeBSD_version) -# if defined(IPFILTER_LKM) -# ifndef __FreeBSD_cc_version -# include <osreldate.h> -# else -# if __FreeBSD_cc_version < 430000 -# include <osreldate.h> -# endif -# endif -# endif -#endif -#include <sys/errno.h> -#if defined(__hpux) && (HPUXREV >= 1111) && !defined(_KERNEL) -# include <sys/kern_svcs.h> -#endif -#include <sys/types.h> -#define _KERNEL -#define KERNEL -#ifdef __OpenBSD__ -struct file; -#endif -#include <sys/uio.h> -#undef _KERNEL -#undef KERNEL -#include <sys/file.h> -#include <sys/ioctl.h> -#ifdef __sgi -# include <sys/ptimers.h> -#endif -#include <sys/time.h> -#if !SOLARIS -# if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000) -# include <sys/dirent.h> -# else -# include <sys/dir.h> -# endif -#else -# include <sys/filio.h> -#endif -#ifndef linux -# include <sys/protosw.h> +static const char rcsid[] = "@(#)$Id$"; #endif -#include <sys/socket.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <ctype.h> -#include <fcntl.h> - -#ifdef __hpux -# define _NET_ROUTE_INCLUDED -#endif -#include <net/if.h> -#ifdef sun -# include <net/af.h> -#endif -#if __FreeBSD_version >= 300000 -# include <net/if_var.h> -#endif -#ifdef __sgi -#include <sys/debug.h> -# ifdef IFF_DRVRLOCK /* IRIX6 */ -#include <sys/hashing.h> -# endif -#endif -#if defined(__FreeBSD__) || defined(SOLARIS2) -# include "radix_ipf.h" -#endif -#ifndef __osf__ -# include <net/route.h> -#endif -#include <netinet/in.h> -#if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */ && \ - !defined(__hpux) && !defined(linux) -# include <netinet/in_var.h> -#endif -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#if !defined(linux) -# include <netinet/ip_var.h> -#endif -#include <netinet/tcp.h> -#if defined(__osf__) -# include <netinet/tcp_timer.h> -#endif -#if defined(__osf__) || defined(__hpux) || defined(__sgi) -# include "radix_ipf_local.h" -# define _RADIX_H_ -#endif -#include <netinet/udp.h> -#include <netinet/tcpip.h> -#include <netinet/ip_icmp.h> -#include <unistd.h> -#include <syslog.h> -#include <arpa/inet.h> -#ifdef __hpux -# undef _NET_ROUTE_INCLUDED -#endif -#include "netinet/ip_compat.h" -#include "netinet/ip_fil.h" -#include "netinet/ip_nat.h" -#include "netinet/ip_frag.h" -#include "netinet/ip_state.h" -#include "netinet/ip_proxy.h" -#include "netinet/ip_auth.h" -#ifdef IPFILTER_SYNC -#include "netinet/ip_sync.h" -#endif -#ifdef IPFILTER_SCAN -#include "netinet/ip_scan.h" -#endif -#include "netinet/ip_pool.h" -#ifdef IPFILTER_COMPILED -# include "netinet/ip_rules.h" -#endif -#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) -# include <sys/malloc.h> -#endif -#ifdef __hpux -struct rtentry; -#endif +#include "ipf.h" #include "md5.h" +#include "ipt.h" +ipf_main_softc_t ipfmain; -#if !defined(__osf__) && !defined(__linux__) -extern struct protosw inetsw[]; -#endif - -#include "ipt.h" static struct ifnet **ifneta = NULL; static int nifs = 0; -static void fr_setifpaddr __P((struct ifnet *, char *)); +struct rtentry; + +static void ipf_setifpaddr __P((struct ifnet *, char *)); void init_ifp __P((void)); #if defined(__sgi) && (IRIX < 60500) static int no_output __P((struct ifnet *, struct mbuf *, @@ -168,16 +43,18 @@ static int write_output __P((struct ifnet *, struct mbuf *, #endif -int ipfattach() +int +ipfattach(softc) + ipf_main_softc_t *softc; { - fr_running = 1; return 0; } -int ipfdetach() +int +ipfdetach(softc) + ipf_main_softc_t *softc; { - fr_running = -1; return 0; } @@ -185,101 +62,96 @@ int ipfdetach() /* * Filter ioctl interface. */ -int iplioctl(dev, cmd, data, mode) -int dev; -ioctlcmd_t cmd; -caddr_t data; -int mode; +int +ipfioctl(softc, dev, cmd, data, mode) + ipf_main_softc_t *softc; + int dev; + ioctlcmd_t cmd; + caddr_t data; + int mode; { int error = 0, unit = 0, uid; - SPL_INT(s); uid = getuid(); unit = dev; SPL_NET(s); - error = fr_ioctlswitch(unit, data, cmd, mode, uid, NULL); + error = ipf_ioctlswitch(softc, unit, data, cmd, mode, uid, NULL); if (error != -1) { SPL_X(s); return error; } - SPL_X(s); return error; } -void fr_forgetifp(ifp) -void *ifp; +void +ipf_forgetifp(softc, ifp) + ipf_main_softc_t *softc; + void *ifp; { register frentry_t *f; - WRITE_ENTER(&ipf_mutex); - for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next) + WRITE_ENTER(&softc->ipf_mutex); + for (f = softc->ipf_acct[0][softc->ipf_active]; (f != NULL); + f = f->fr_next) if (f->fr_ifa == ifp) f->fr_ifa = (void *)-1; - for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next) + for (f = softc->ipf_acct[1][softc->ipf_active]; (f != NULL); + f = f->fr_next) if (f->fr_ifa == ifp) f->fr_ifa = (void *)-1; - for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next) + for (f = softc->ipf_rules[0][softc->ipf_active]; (f != NULL); + f = f->fr_next) if (f->fr_ifa == ifp) f->fr_ifa = (void *)-1; - for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next) + for (f = softc->ipf_rules[1][softc->ipf_active]; (f != NULL); + f = f->fr_next) if (f->fr_ifa == ifp) f->fr_ifa = (void *)-1; -#ifdef USE_INET6 - for (f = ipacct6[0][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; - for (f = ipacct6[1][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; - for (f = ipfilter6[0][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; - for (f = ipfilter6[1][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; -#endif - RWLOCK_EXIT(&ipf_mutex); - fr_natsync(ifp); + RWLOCK_EXIT(&softc->ipf_mutex); + ipf_nat_sync(softc, ifp); + ipf_lookup_sync(softc, ifp); } +static int #if defined(__sgi) && (IRIX < 60500) -static int no_output(ifp, m, s) +no_output(ifp, m, s) #else # if TRU64 >= 1885 -static int no_output (ifp, m, s, rt, cp) -char *cp; +no_output (ifp, m, s, rt, cp) + char *cp; # else -static int no_output(ifp, m, s, rt) +no_output(ifp, m, s, rt) # endif -struct rtentry *rt; + struct rtentry *rt; #endif -struct ifnet *ifp; -struct mbuf *m; -struct sockaddr *s; + struct ifnet *ifp; + struct mbuf *m; + struct sockaddr *s; { return 0; } +static int #if defined(__sgi) && (IRIX < 60500) -static int write_output(ifp, m, s) +write_output(ifp, m, s) #else # if TRU64 >= 1885 -static int write_output (ifp, m, s, rt, cp) -char *cp; +write_output (ifp, m, s, rt, cp) + char *cp; # else -static int write_output(ifp, m, s, rt) +write_output(ifp, m, s, rt) # endif -struct rtentry *rt; + struct rtentry *rt; #endif -struct ifnet *ifp; -struct mbuf *m; -struct sockaddr *s; + struct ifnet *ifp; + struct mbuf *m; + struct sockaddr *s; { char fname[32]; mb_t *mb; @@ -307,9 +179,10 @@ struct sockaddr *s; } -static void fr_setifpaddr(ifp, addr) -struct ifnet *ifp; -char *addr; +static void +ipf_setifpaddr(ifp, addr) + struct ifnet *ifp; + char *addr; { #ifdef __sgi struct in_ifaddr *ifa; @@ -347,15 +220,28 @@ char *addr; #else sin = (struct sockaddr_in *)&ifa->ifa_addr; #endif - sin->sin_addr.s_addr = inet_addr(addr); - if (sin->sin_addr.s_addr == 0) - abort(); +#ifdef USE_INET6 + if (index(addr, ':') != NULL) { + struct sockaddr_in6 *sin6; + + sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr; + sin6->sin6_family = AF_INET6; + inet_pton(AF_INET6, addr, &sin6->sin6_addr); + } else +#endif + { + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = inet_addr(addr); + if (sin->sin_addr.s_addr == 0) + abort(); + } } } -struct ifnet *get_unit(name, v) -char *name; -int v; +struct ifnet * +get_unit(name, family) + char *name; + int family; { struct ifnet *ifp, **ifpp, **old_ifneta; char *addr; @@ -363,6 +249,9 @@ int v; (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) + if (!*name) + return NULL; + if (name == NULL) name = "anon0"; @@ -373,7 +262,7 @@ int v; for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { if (!strcmp(name, ifp->if_xname)) { if (addr != NULL) - fr_setifpaddr(ifp, addr); + ipf_setifpaddr(ifp, addr); return ifp; } } @@ -388,10 +277,10 @@ int v; *addr++ = '\0'; for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { - COPYIFNAME(v, ifp, ifname); + COPYIFNAME(family, ifp, ifname); if (!strcmp(name, ifname)) { if (addr != NULL) - fr_setifpaddr(ifp, addr); + ipf_setifpaddr(ifp, addr); return ifp; } } @@ -435,9 +324,15 @@ int v; (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) (void) strncpy(ifp->if_xname, name, sizeof(ifp->if_xname)); #else - for (s = name; *s && !ISDIGIT(*s); s++) - ; - if (*s && ISDIGIT(*s)) { + s = name + strlen(name) - 1; + for (; s > name; s--) { + if (!ISDIGIT(*s)) { + s++; + break; + } + } + + if ((s > name) && (*s != 0) && ISDIGIT(*s)) { ifp->if_unit = atoi(s); ifp->if_name = (char *)malloc(s - name + 1); (void) strncpy(ifp->if_name, name, s - name); @@ -450,15 +345,16 @@ int v; ifp->if_output = (void *)no_output; if (addr != NULL) { - fr_setifpaddr(ifp, addr); + ipf_setifpaddr(ifp, addr); } return ifp; } -char *get_ifname(ifp) -struct ifnet *ifp; +char * +get_ifname(ifp) + struct ifnet *ifp; { static char ifname[LIFNAMSIZ]; @@ -466,14 +362,18 @@ struct ifnet *ifp; (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) sprintf(ifname, "%s", ifp->if_xname); #else - sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit); + if (ifp->if_unit != -1) + sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit); + else + strcpy(ifname, ifp->if_name); #endif return ifname; } -void init_ifp() +void +init_ifp() { struct ifnet *ifp, **ifpp; char fname[32]; @@ -494,7 +394,7 @@ void init_ifp() #else for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { - ifp->if_output = write_output; + ifp->if_output = (void *)write_output; sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); if (fd == -1) @@ -506,36 +406,48 @@ void init_ifp() } -int fr_fastroute(m, mpp, fin, fdp) -mb_t *m, **mpp; -fr_info_t *fin; -frdest_t *fdp; +int +ipf_fastroute(m, mpp, fin, fdp) + mb_t *m, **mpp; + fr_info_t *fin; + frdest_t *fdp; { - struct ifnet *ifp = fdp->fd_ifp; + struct ifnet *ifp; ip_t *ip = fin->fin_ip; + frdest_t node; int error = 0; frentry_t *fr; void *sifp; + int sout; - if (!ifp) - return 0; /* no routing table out here */ - + sifp = fin->fin_ifp; + sout = fin->fin_out; fr = fin->fin_fr; ip->ip_sum = 0; + if (!(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) && + (fdp->fd_type == FRD_DSTLIST)) { + bzero(&node, sizeof(node)); + ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node); + fdp = &node; + } + ifp = fdp->fd_ptr; + + if (ifp == NULL) + return 0; /* no routing table out here */ + if (fin->fin_out == 0) { - sifp = fin->fin_ifp; fin->fin_ifp = ifp; fin->fin_out = 1; - (void) fr_acctpkt(fin, NULL); + (void) ipf_acctpkt(fin, NULL); fin->fin_fr = NULL; if (!fr || !(fr->fr_flags & FR_RETMASK)) { u_32_t pass; - (void) fr_checkstate(fin, &pass); + (void) ipf_state_check(fin, &pass); } - switch (fr_checknatout(fin, NULL)) + switch (ipf_nat_checkout(fin, NULL)) { case 0 : break; @@ -548,10 +460,11 @@ frdest_t *fdp; break; } - fin->fin_ifp = sifp; - fin->fin_out = 0; } + m->mb_ifp = ifp; + printpacket(fin->fin_out, m); + #if defined(__sgi) && (IRIX < 60500) (*ifp->if_output)(ifp, (void *)ip, NULL); # if TRU64 >= 1885 @@ -561,55 +474,55 @@ frdest_t *fdp; # endif #endif done: + fin->fin_ifp = sifp; + fin->fin_out = sout; return error; } -int fr_send_reset(fin) -fr_info_t *fin; +int +ipf_send_reset(fin) + fr_info_t *fin; { - verbose("- TCP RST sent\n"); + ipfkverbose("- TCP RST sent\n"); return 0; } -int fr_send_icmp_err(type, fin, dst) -int type; -fr_info_t *fin; -int dst; +int +ipf_send_icmp_err(type, fin, dst) + int type; + fr_info_t *fin; + int dst; { - verbose("- ICMP unreachable sent\n"); + ipfkverbose("- ICMP unreachable sent\n"); return 0; } -void frsync(ifp) -void *ifp; +void +m_freem(m) + mb_t *m; { return; } -void m_freem(m) -mb_t *m; -{ - return; -} - - -void m_copydata(m, off, len, cp) -mb_t *m; -int off, len; -caddr_t cp; +void +m_copydata(m, off, len, cp) + mb_t *m; + int off, len; + caddr_t cp; { bcopy((char *)m + off, cp, len); } -int ipfuiomove(buf, len, rwflag, uio) -caddr_t buf; -int len, rwflag; -struct uio *uio; +int +ipfuiomove(buf, len, rwflag, uio) + caddr_t buf; + int len, rwflag; + struct uio *uio; { int left, ioc, num, offset; struct iovec *io; @@ -646,8 +559,9 @@ struct uio *uio; } -u_32_t fr_newisn(fin) -fr_info_t *fin; +u_32_t +ipf_newisn(fin) + fr_info_t *fin; { static int iss_seq_off = 0; u_char hash[16]; @@ -686,50 +600,76 @@ fr_info_t *fin; /* ------------------------------------------------------------------------ */ -/* Function: fr_nextipid */ +/* Function: ipf_nextipid */ /* Returns: int - 0 == success, -1 == error (packet should be droppped) */ /* Parameters: fin(I) - pointer to packet information */ /* */ /* Returns the next IPv4 ID to use for this packet. */ /* ------------------------------------------------------------------------ */ -INLINE u_short fr_nextipid(fin) -fr_info_t *fin; +INLINE u_short +ipf_nextipid(fin) + fr_info_t *fin; { static u_short ipid = 0; + ipf_main_softc_t *softc = fin->fin_main_soft; u_short id; - MUTEX_ENTER(&ipf_rw); - id = ipid++; - MUTEX_EXIT(&ipf_rw); + MUTEX_ENTER(&softc->ipf_rw); + if (fin->fin_pktnum != 0) { + /* + * The -1 is for aligned test results. + */ + id = (fin->fin_pktnum - 1) & 0xffff; + } else { + } + id = ipid++; + MUTEX_EXIT(&softc->ipf_rw); return id; } -INLINE void fr_checkv4sum(fin) -fr_info_t *fin; +INLINE int +ipf_checkv4sum(fin) + fr_info_t *fin; { - if (fr_checkl4sum(fin) == -1) + + if (fin->fin_flx & FI_SHORT) + return 1; + + if (ipf_checkl4sum(fin) == -1) { fin->fin_flx |= FI_BAD; + return -1; + } + return 0; } #ifdef USE_INET6 -INLINE void fr_checkv6sum(fin) -fr_info_t *fin; +INLINE int +ipf_checkv6sum(fin) + fr_info_t *fin; { - if (fr_checkl4sum(fin) == -1) + if (fin->fin_flx & FI_SHORT) + return 1; + + if (ipf_checkl4sum(fin) == -1) { fin->fin_flx |= FI_BAD; + return -1; + } + return 0; } #endif +#if 0 /* * See above for description, except that all addressing is in user space. */ -int copyoutptr(src, dst, size) -void *src, *dst; -size_t size; +int +copyoutptr(softc, src, dst, size) + void *src, *dst; + size_t size; { caddr_t ca; @@ -742,9 +682,10 @@ size_t size; /* * See above for description, except that all addressing is in user space. */ -int copyinptr(src, dst, size) -void *src, *dst; -size_t size; +int +copyinptr(src, dst, size) + void *src, *dst; + size_t size; { caddr_t ca; @@ -752,15 +693,18 @@ size_t size; bcopy(ca, dst, size); return 0; } +#endif /* * return the first IP Address associated with an interface */ -int fr_ifpaddr(v, atype, ifptr, inp, inpmask) -int v, atype; -void *ifptr; -struct in_addr *inp, *inpmask; +int +ipf_ifpaddr(softc, v, atype, ifptr, inp, inpmask) + ipf_main_softc_t *softc; + int v, atype; + void *ifptr; + i6addr_t *inp, *inpmask; { struct ifnet *ifp = ifptr; #ifdef __sgi @@ -779,23 +723,145 @@ struct in_addr *inp, *inpmask; # endif #endif if (ifa != NULL) { - struct sockaddr_in *sin, mask; + if (v == 4) { + struct sockaddr_in *sin, mask; - mask.sin_addr.s_addr = 0xffffffff; + mask.sin_addr.s_addr = 0xffffffff; #ifdef __sgi - sin = (struct sockaddr_in *)&ifa->ia_addr; + sin = (struct sockaddr_in *)&ifa->ia_addr; #else - sin = (struct sockaddr_in *)&ifa->ifa_addr; + sin = (struct sockaddr_in *)&ifa->ifa_addr; #endif - return fr_ifpfillv4addr(atype, sin, &mask, inp, inpmask); + return ipf_ifpfillv4addr(atype, sin, &mask, + &inp->in4, &inpmask->in4); + } +#ifdef USE_INET6 + if (v == 6) { + struct sockaddr_in6 *sin6, mask; + + sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr; + ((i6addr_t *)&mask.sin6_addr)->i6[0] = 0xffffffff; + ((i6addr_t *)&mask.sin6_addr)->i6[1] = 0xffffffff; + ((i6addr_t *)&mask.sin6_addr)->i6[2] = 0xffffffff; + ((i6addr_t *)&mask.sin6_addr)->i6[3] = 0xffffffff; + return ipf_ifpfillv6addr(atype, sin6, &mask, + inp, inpmask); + } +#endif } return 0; } -int ipfsync() +/* + * This function is not meant to be random, rather just produce a + * sequence of numbers that isn't linear to show "randomness". + */ +u_32_t +ipf_random() { + static unsigned int last = 0xa5a5a5a5; + static int calls = 0; + int number; + + calls++; + + /* + * These are deliberately chosen to ensure that there is some + * attempt to test whether the output covers the range in test n18. + */ + switch (calls) + { + case 1 : + number = 0; + break; + case 2 : + number = 4; + break; + case 3 : + number = 3999; + break; + case 4 : + number = 4000; + break; + case 5 : + number = 48999; + break; + case 6 : + number = 49000; + break; + default : + number = last; + last *= calls; + last++; + number ^= last; + break; + } + return number; +} + + +int +ipf_verifysrc(fin) + fr_info_t *fin; +{ + return 1; +} + + +int +ipf_inject(fin, m) + fr_info_t *fin; + mb_t *m; +{ + FREE_MB_T(m); + return 0; } + + +u_int +ipf_pcksum(fin, hlen, sum) + fr_info_t *fin; + int hlen; + u_int sum; +{ + u_short *sp; + u_int sum2; + int slen; + + slen = fin->fin_plen - hlen; + sp = (u_short *)((u_char *)fin->fin_ip + hlen); + + for (; slen > 1; slen -= 2) + sum += *sp++; + if (slen) + sum += ntohs(*(u_char *)sp << 8); + while (sum > 0xffff) + sum = (sum & 0xffff) + (sum >> 16); + sum2 = (u_short)(~sum & 0xffff); + + return sum2; +} + + +void * +ipf_pullup(m, fin, plen) + mb_t *m; + fr_info_t *fin; + int plen; +{ + if (M_LEN(m) >= plen) + return fin->fin_ip; + + /* + * Fake ipf_pullup failing + */ + fin->fin_reason = FRB_PULLUP; + *fin->fin_mp = NULL; + fin->fin_m = NULL; + fin->fin_ip = NULL; + return NULL; +} diff --git a/ip_fil.h b/ip_fil.h index 2aacb3f0af78a..4a888d391df63 100644 --- a/ip_fil.h +++ b/ip_fil.h @@ -1,17 +1,32 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1993-2001, 2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_fil.h 1.35 6/5/96 - * Id: ip_fil.h,v 2.170.2.18 2005/03/28 10:47:52 darrenr Exp + * $Id$ */ #ifndef __IP_FIL_H__ #define __IP_FIL_H__ +#include "netinet/ip_compat.h" +#include "netinet/ipf_rb.h" +#if NETBSD_GE_REV(104040000) +# include <sys/callout.h> +#endif +#if defined(BSD) && defined(_KERNEL) +# if NETBSD_LT_REV(399000000) || defined(__osf__) || FREEBSD_LT_REV(500043) +# include <sys/select.h> +# else +# include <sys/selinfo.h> +# endif +#endif + +#if !defined(linux) || !defined(_KERNEL) +# include <netinet/in.h> +#endif + #ifndef SOLARIS # define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) #endif @@ -24,7 +39,7 @@ # endif #endif -#if defined(__STDC__) || defined(__GNUC__) +#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51) # define SIOCADAFR _IOW('r', 60, struct ipfobj) # define SIOCRMAFR _IOW('r', 61, struct ipfobj) # define SIOCSETFF _IOW('r', 62, u_int) @@ -43,12 +58,12 @@ # define SIOCZRLST _IOWR('r', 75, struct ipfobj) # define SIOCAUTHW _IOWR('r', 76, struct ipfobj) # define SIOCAUTHR _IOWR('r', 77, struct ipfobj) -# define SIOCATHST _IOWR('r', 78, struct ipfobj) +# define SIOCSTAT1 _IOWR('r', 78, struct ipfobj) # define SIOCSTLCK _IOWR('r', 79, u_int) # define SIOCSTPUT _IOWR('r', 80, struct ipfobj) # define SIOCSTGET _IOWR('r', 81, struct ipfobj) # define SIOCSTGSZ _IOWR('r', 82, struct ipfobj) -# define SIOCGFRST _IOWR('r', 83, struct ipfobj) +# define SIOCSTAT2 _IOWR('r', 83, struct ipfobj) # define SIOCSETLG _IOWR('r', 84, int) # define SIOCGETLG _IOWR('r', 85, int) # define SIOCFUNCL _IOWR('r', 86, struct ipfunc_resolve) @@ -56,6 +71,14 @@ # define SIOCIPFGET _IOWR('r', 88, struct ipfobj) # define SIOCIPFSET _IOWR('r', 89, struct ipfobj) # define SIOCIPFL6 _IOWR('r', 90, int) +# define SIOCIPFITER _IOWR('r', 91, struct ipfobj) +# define SIOCGENITER _IOWR('r', 92, struct ipfobj) +# define SIOCGTABL _IOWR('r', 93, struct ipfobj) +# define SIOCIPFDELTOK _IOWR('r', 94, int) +# define SIOCLOOKUPITER _IOWR('r', 95, struct ipfobj) +# define SIOCGTQTAB _IOWR('r', 96, struct ipfobj) +# define SIOCMATCHFLUSH _IOWR('r', 97, struct ipfobj) +# define SIOCIPFINTERROR _IOR('r', 98, int) #else # define SIOCADAFR _IOW(r, 60, struct ipfobj) # define SIOCRMAFR _IOW(r, 61, struct ipfobj) @@ -75,12 +98,12 @@ # define SIOCZRLST _IOWR(r, 75, struct ipfobj) # define SIOCAUTHW _IOWR(r, 76, struct ipfobj) # define SIOCAUTHR _IOWR(r, 77, struct ipfobj) -# define SIOCATHST _IOWR(r, 78, struct ipfobj) +# define SIOCSTAT1 _IOWR(r, 78, struct ipfobj) # define SIOCSTLCK _IOWR(r, 79, u_int) # define SIOCSTPUT _IOWR(r, 80, struct ipfobj) # define SIOCSTGET _IOWR(r, 81, struct ipfobj) # define SIOCSTGSZ _IOWR(r, 82, struct ipfobj) -# define SIOCGFRST _IOWR(r, 83, struct ipfobj) +# define SIOCSTAT2 _IOWR(r, 83, struct ipfobj) # define SIOCSETLG _IOWR(r, 84, int) # define SIOCGETLG _IOWR(r, 85, int) # define SIOCFUNCL _IOWR(r, 86, struct ipfunc_resolve) @@ -88,17 +111,28 @@ # define SIOCIPFGET _IOWR(r, 88, struct ipfobj) # define SIOCIPFSET _IOWR(r, 89, struct ipfobj) # define SIOCIPFL6 _IOWR(r, 90, int) +# define SIOCIPFITER _IOWR(r, 91, struct ipfobj) +# define SIOCGENITER _IOWR(r, 92, struct ipfobj) +# define SIOCGTABL _IOWR(r, 93, struct ipfobj) +# define SIOCIPFDELTOK _IOWR(r, 94, int) +# define SIOCLOOKUPITER _IOWR(r, 95, struct ipfobj) +# define SIOCGTQTAB _IOWR(r, 96, struct ipfobj) +# define SIOCMATCHFLUSH _IOWR(r, 97, struct ipfobj) +# define SIOCIPFINTERROR _IOR(r, 98, int) #endif #define SIOCADDFR SIOCADAFR #define SIOCDELFR SIOCRMAFR #define SIOCINSFR SIOCINAFR +#define SIOCATHST SIOCSTAT1 +#define SIOCGFRST SIOCSTAT2 struct ipscan; struct ifnet; +struct ipf_main_softc_s; - -typedef int (* lookupfunc_t) __P((void *, int, void *)); +typedef int (* lookupfunc_t) __P((struct ipf_main_softc_s *, void *, + int, void *, u_int)); /* * i6addr is used as a container for both IPv4 and IPv6 addresses, as well @@ -111,6 +145,11 @@ typedef union i6addr { struct in6_addr in6; void *vptr[2]; lookupfunc_t lptr[2]; + struct { + u_short type; + u_short subtype; + int name; + } i6un; } i6addr_t; #else typedef union i6addr { @@ -118,26 +157,33 @@ typedef union i6addr { struct in_addr in4; void *vptr[2]; lookupfunc_t lptr[2]; + struct { + u_short type; + u_short subtype; + int name; + } i6un; } i6addr_t; #endif #define in4_addr in4.s_addr -#define iplookupnum i6[0] -#define iplookuptype i6[1] +#define iplookupnum i6[1] +#define iplookupname i6un.name +#define iplookuptype i6un.type +#define iplookupsubtype i6un.subtype /* * NOTE: These DO overlap the above on 64bit systems and this IS recognised. */ #define iplookupptr vptr[0] #define iplookupfunc lptr[1] -#define I60(x) (((i6addr_t *)(x))->i6[0]) -#define I61(x) (((i6addr_t *)(x))->i6[1]) -#define I62(x) (((i6addr_t *)(x))->i6[2]) -#define I63(x) (((i6addr_t *)(x))->i6[3]) -#define HI60(x) ntohl(((i6addr_t *)(x))->i6[0]) -#define HI61(x) ntohl(((i6addr_t *)(x))->i6[1]) -#define HI62(x) ntohl(((i6addr_t *)(x))->i6[2]) -#define HI63(x) ntohl(((i6addr_t *)(x))->i6[3]) +#define I60(x) (((u_32_t *)(x))[0]) +#define I61(x) (((u_32_t *)(x))[1]) +#define I62(x) (((u_32_t *)(x))[2]) +#define I63(x) (((u_32_t *)(x))[3]) +#define HI60(x) ntohl(((u_32_t *)(x))[0]) +#define HI61(x) ntohl(((u_32_t *)(x))[1]) +#define HI62(x) ntohl(((u_32_t *)(x))[2]) +#define HI63(x) ntohl(((u_32_t *)(x))[3]) #define IP6_EQ(a,b) ((I63(a) == I63(b)) && (I62(a) == I62(b)) && \ (I61(a) == I61(b)) && (I60(a) == I60(b))) @@ -145,30 +191,38 @@ typedef union i6addr { (I61(a) != I61(b)) || (I60(a) != I60(b))) #define IP6_ISZERO(a) ((I60(a) | I61(a) | I62(a) | I63(a)) == 0) #define IP6_NOTZERO(a) ((I60(a) | I61(a) | I62(a) | I63(a)) != 0) -#define IP6_GT(a,b) (HI60(a) > HI60(b) || (HI60(a) == HI60(b) && \ - (HI61(a) > HI61(b) || (HI61(a) == HI61(b) && \ - (HI62(a) > HI62(b) || (HI62(a) == HI62(b) && \ - HI63(a) > HI63(b))))))) -#define IP6_LT(a,b) (HI60(a) < HI60(b) || (HI60(a) == HI60(b) && \ - (HI61(a) < HI61(b) || (HI61(a) == HI61(b) && \ - (HI62(a) < HI62(b) || (HI62(a) == HI62(b) && \ - HI63(a) < HI63(b))))))) +#define IP6_ISONES(a) ((I63(a) == 0xffffffff) && (I62(a) == 0xffffffff) && \ + (I61(a) == 0xffffffff) && (I60(a) == 0xffffffff)) +#define IP6_GT(a,b) (ntohl(HI60(a)) > ntohl(HI60(b)) || \ + (HI60(a) == HI60(b) && \ + (ntohl(HI61(a)) > ntohl(HI61(b)) || \ + (HI61(a) == HI61(b) && \ + (ntohl(HI62(a)) > ntohl(HI62(b)) || \ + (HI62(a) == HI62(b) && \ + ntohl(HI63(a)) > ntohl(HI63(b)))))))) +#define IP6_LT(a,b) (ntohl(HI60(a)) < ntohl(HI60(b)) || \ + (HI60(a) == HI60(b) && \ + (ntohl(HI61(a)) < ntohl(HI61(b)) || \ + (HI61(a) == HI61(b) && \ + (ntohl(HI62(a)) < ntohl(HI62(b)) || \ + (HI62(a) == HI62(b) && \ + ntohl(HI63(a)) < ntohl(HI63(b)))))))) #define NLADD(n,x) htonl(ntohl(n) + (x)) #define IP6_INC(a) \ - { i6addr_t *_i6 = (i6addr_t *)(a); \ - _i6->i6[0] = NLADD(_i6->i6[0], 1); \ - if (_i6->i6[0] == 0) { \ - _i6->i6[0] = NLADD(_i6->i6[1], 1); \ - if (_i6->i6[1] == 0) { \ - _i6->i6[0] = NLADD(_i6->i6[2], 1); \ - if (_i6->i6[2] == 0) { \ - _i6->i6[0] = NLADD(_i6->i6[3], 1); \ + do { u_32_t *_i6 = (u_32_t *)(a); \ + _i6[3] = NLADD(_i6[3], 1); \ + if (_i6[3] == 0) { \ + _i6[2] = NLADD(_i6[2], 1); \ + if (_i6[2] == 0) { \ + _i6[1] = NLADD(_i6[1], 1); \ + if (_i6[1] == 0) { \ + _i6[0] = NLADD(_i6[0], 1); \ } \ } \ } \ - } + } while (0) #define IP6_ADD(a,x,d) \ - { i6addr_t *_s = (i6addr_t *)(a); \ + do { i6addr_t *_s = (i6addr_t *)(a); \ i6addr_t *_d = (i6addr_t *)(d); \ _d->i6[0] = NLADD(_s->i6[0], x); \ if (ntohl(_d->i6[0]) < ntohl(_s->i6[0])) { \ @@ -180,26 +234,65 @@ typedef union i6addr { } \ } \ } \ - } -#define IP6_AND(a,b,d) { i6addr_t *_s1 = (i6addr_t *)(a); \ - i6addr_t *_s2 = (i6addr_t *)(d); \ + } while (0) +#define IP6_AND(a,b,d) do { i6addr_t *_s1 = (i6addr_t *)(a); \ + i6addr_t *_s2 = (i6addr_t *)(b); \ i6addr_t *_d = (i6addr_t *)(d); \ _d->i6[0] = _s1->i6[0] & _s2->i6[0]; \ _d->i6[1] = _s1->i6[1] & _s2->i6[1]; \ _d->i6[2] = _s1->i6[2] & _s2->i6[2]; \ _d->i6[3] = _s1->i6[3] & _s2->i6[3]; \ - } + } while (0) +#define IP6_ANDASSIGN(a,m) \ + do { i6addr_t *_d = (i6addr_t *)(a); \ + i6addr_t *_m = (i6addr_t *)(m); \ + _d->i6[0] &= _m->i6[0]; \ + _d->i6[1] &= _m->i6[1]; \ + _d->i6[2] &= _m->i6[2]; \ + _d->i6[3] &= _m->i6[3]; \ + } while (0) +#define IP6_MASKEQ(a,m,b) \ + (((I60(a) & I60(m)) == I60(b)) && \ + ((I61(a) & I61(m)) == I61(b)) && \ + ((I62(a) & I62(m)) == I62(b)) && \ + ((I63(a) & I63(m)) == I63(b))) +#define IP6_MASKNEQ(a,m,b) \ + (((I60(a) & I60(m)) != I60(b)) || \ + ((I61(a) & I61(m)) != I61(b)) || \ + ((I62(a) & I62(m)) != I62(b)) || \ + ((I63(a) & I63(m)) != I63(b))) #define IP6_MERGE(a,b,c) \ - { i6addr_t *_d, *_s1, *_s2; \ + do { i6addr_t *_d, *_s1, *_s2; \ _d = (i6addr_t *)(a); \ _s1 = (i6addr_t *)(b); \ _s2 = (i6addr_t *)(c); \ _d->i6[0] |= _s1->i6[0] & ~_s2->i6[0]; \ _d->i6[1] |= _s1->i6[1] & ~_s2->i6[1]; \ _d->i6[2] |= _s1->i6[2] & ~_s2->i6[2]; \ - _d->i6[2] |= _s1->i6[3] & ~_s2->i6[3]; \ - } - + _d->i6[3] |= _s1->i6[3] & ~_s2->i6[3]; \ + } while (0) +#define IP6_MASK(a,b,c) \ + do { i6addr_t *_d, *_s1, *_s2; \ + _d = (i6addr_t *)(a); \ + _s1 = (i6addr_t *)(b); \ + _s2 = (i6addr_t *)(c); \ + _d->i6[0] = _s1->i6[0] & ~_s2->i6[0]; \ + _d->i6[1] = _s1->i6[1] & ~_s2->i6[1]; \ + _d->i6[2] = _s1->i6[2] & ~_s2->i6[2]; \ + _d->i6[3] = _s1->i6[3] & ~_s2->i6[3]; \ + } while (0) +#define IP6_SETONES(a) \ + do { i6addr_t *_d = (i6addr_t *)(a); \ + _d->i6[0] = 0xffffffff; \ + _d->i6[1] = 0xffffffff; \ + _d->i6[2] = 0xffffffff; \ + _d->i6[3] = 0xffffffff; \ + } while (0) + +typedef union ipso_u { + u_short ipso_ripso[2]; + u_32_t ipso_doi; +} ipso_t; typedef struct fr_ip { u_32_t fi_v:4; /* IP version */ @@ -210,11 +303,13 @@ typedef struct fr_ip { u_32_t fi_optmsk; /* bitmask composed from IP options */ i6addr_t fi_src; /* source address from packet */ i6addr_t fi_dst; /* destination address from packet */ - u_short fi_secmsk; /* bitmask composed from IP security options */ - u_short fi_auth; /* authentication code from IP sec. options */ + ipso_t fi_ipso; /* IP security options */ u_32_t fi_flx; /* packet flags */ u_32_t fi_tcpmsk; /* TCP options set/reset */ - u_32_t fi_res1; /* RESERVED */ + u_32_t fi_ports[2]; /* TCP ports */ + u_char fi_tcpf; /* TCP flags */ + u_char fi_sensitivity; + u_char fi_xxx[2]; /* pad */ } fr_ip_t; /* @@ -236,21 +331,33 @@ typedef struct fr_ip { #define FI_FRAGBODY 0x2000 #define FI_BADSRC 0x4000 #define FI_LOWTTL 0x8000 -#define FI_CMP 0xcfe3 /* Not FI_FRAG,FI_NATED,FI_FRAGTAIL */ +#define FI_CMP 0x5cfe3 /* Not FI_FRAG,FI_NATED,FI_FRAGTAIL */ #define FI_ICMPCMP 0x0003 /* Flags we can check for ICMP error packets */ -#define FI_WITH 0xeffe /* Not FI_TCPUDP */ +#define FI_WITH 0x5effe /* Not FI_TCPUDP */ #define FI_V6EXTHDR 0x10000 #define FI_COALESCE 0x20000 +#define FI_NEWNAT 0x40000 +#define FI_ICMPQUERY 0x80000 +#define FI_ENCAP 0x100000 /* encap/decap with NAT */ +#define FI_AH 0x200000 /* AH header present */ +#define FI_DOCKSUM 0x10000000 /* Proxy wants L4 recalculation */ #define FI_NOCKSUM 0x20000000 /* don't do a L4 checksum validation */ -#define FI_DONTCACHE 0x40000000 /* don't cache the result */ +#define FI_NOWILD 0x40000000 /* Do not do wildcard searches */ #define FI_IGNORE 0x80000000 +#define fi_secmsk fi_ipso.ipso_ripso[0] +#define fi_auth fi_ipso.ipso_ripso[1] +#define fi_doi fi_ipso.ipso_doi #define fi_saddr fi_src.in4.s_addr #define fi_daddr fi_dst.in4.s_addr #define fi_srcnum fi_src.iplookupnum #define fi_dstnum fi_dst.iplookupnum +#define fi_srcname fi_src.iplookupname +#define fi_dstname fi_dst.iplookupname #define fi_srctype fi_src.iplookuptype #define fi_dsttype fi_dst.iplookuptype +#define fi_srcsubtype fi_src.iplookupsubtype +#define fi_dstsubtype fi_dst.iplookupsubtype #define fi_srcptr fi_src.iplookupptr #define fi_dstptr fi_dst.iplookupptr #define fi_srcfunc fi_src.iplookupfunc @@ -271,73 +378,133 @@ typedef struct fr_ip { #define SI_NEWFR 0x00001000 #define SI_CLONE 0x00002000 #define SI_CLONED 0x00004000 - +#define SI_NEWCLONE 0x00008000 + +typedef struct { + u_short fda_ports[2]; + u_char fda_tcpf; /* TCP header flags (SYN, ACK, etc) */ +} frdat_t; + +typedef enum fr_breasons_e { + FRB_BLOCKED = 0, + FRB_LOGFAIL = 1, + FRB_PPSRATE = 2, + FRB_JUMBO = 3, + FRB_MAKEFRIP = 4, + FRB_STATEADD = 5, + FRB_UPDATEIPID = 6, + FRB_LOGFAIL2 = 7, + FRB_DECAPFRIP = 8, + FRB_AUTHNEW = 9, + FRB_AUTHCAPTURE = 10, + FRB_COALESCE = 11, + FRB_PULLUP = 12, + FRB_AUTHFEEDBACK = 13, + FRB_BADFRAG = 14, + FRB_NATV4 = 15, + FRB_NATV6 = 16, +} fr_breason_t; + +#define FRB_MAX_VALUE 16 + +typedef enum ipf_cksum_e { + FI_CK_BAD = -1, + FI_CK_NEEDED = 0, + FI_CK_SUMOK = 1, + FI_CK_L4PART = 2, + FI_CK_L4FULL = 4 +} ipf_cksum_t; typedef struct fr_info { + void *fin_main_soft; void *fin_ifp; /* interface packet is `on' */ - fr_ip_t fin_fi; /* IP Packet summary */ - union { - u_short fid_16[2]; /* TCP/UDP ports, ICMP code/type */ - u_32_t fid_32; - } fin_dat; + struct frentry *fin_fr; /* last matching rule */ int fin_out; /* in or out ? 1 == out, 0 == in */ - int fin_rev; /* state only: 1 = reverse */ - u_short fin_hlen; /* length of IP header in bytes */ - u_char fin_tcpf; /* TCP header flags (SYN, ACK, etc) */ - u_char fin_icode; /* ICMP error to return */ + fr_ip_t fin_fi; /* IP Packet summary */ + frdat_t fin_dat; /* TCP/UDP ports, ICMP code/type */ + int fin_dlen; /* length of data portion of packet */ + int fin_plen; u_32_t fin_rule; /* rule # last matched */ + u_short fin_hlen; /* length of IP header in bytes */ char fin_group[FR_GROUPLEN]; /* group number, -1 for none */ - struct frentry *fin_fr; /* last matching rule */ void *fin_dp; /* start of data past IP header */ - int fin_dlen; /* length of data portion of packet */ - int fin_plen; + /* + * Fields after fin_dp aren't used for compression of log records. + * fin_fi contains the IP version (fin_family) + * fin_rule isn't included because adding a new rule can change it but + * not change fin_fr. fin_rule is the rule number reported. + * It isn't necessary to include fin_crc because that is checked + * for explicitly, before calling bcmp. + */ + u_32_t fin_crc; /* Simple calculation for logging */ + int fin_family; /* AF_INET, etc. */ + int fin_icode; /* ICMP error to return */ + int fin_mtu; /* MTU input for ICMP need-frag */ + int fin_rev; /* state only: 1 = reverse */ int fin_ipoff; /* # bytes from buffer start to hdr */ - u_short fin_id; /* IP packet id field */ + u_32_t fin_id; /* IP packet id field */ + u_short fin_l4hlen; /* length of L4 header, if known */ u_short fin_off; int fin_depth; /* Group nesting depth */ int fin_error; /* Error code to return */ - void *fin_nat; - void *fin_state; + ipf_cksum_t fin_cksum; /* -1 = bad, 1 = good, 0 = not done */ + fr_breason_t fin_reason; /* why auto blocked */ + u_int fin_pktnum; void *fin_nattag; - ip_t *fin_ip; + struct frdest *fin_dif; + struct frdest *fin_tif; + union { + ip_t *fip_ip; +#ifdef USE_INET6 + ip6_t *fip_ip6; +#endif + } fin_ipu; mb_t **fin_mp; /* pointer to pointer to mbuf */ mb_t *fin_m; /* pointer to mbuf */ #ifdef MENTAT mb_t *fin_qfm; /* pointer to mblk where pkt starts */ void *fin_qpi; + char fin_ifname[LIFNAMSIZ]; #endif #ifdef __sgi void *fin_hbuf; #endif + void *fin_fraghdr; /* pointer to start of ipv6 frag hdr */ } fr_info_t; +#define fin_ip fin_ipu.fip_ip +#define fin_ip6 fin_ipu.fip_ip6 #define fin_v fin_fi.fi_v #define fin_p fin_fi.fi_p #define fin_flx fin_fi.fi_flx #define fin_optmsk fin_fi.fi_optmsk #define fin_secmsk fin_fi.fi_secmsk +#define fin_doi fin_fi.fi_doi #define fin_auth fin_fi.fi_auth #define fin_src fin_fi.fi_src.in4 -#define fin_src6 fin_fi.fi_src.in6 #define fin_saddr fin_fi.fi_saddr #define fin_dst fin_fi.fi_dst.in4 -#define fin_dst6 fin_fi.fi_dst.in6 #define fin_daddr fin_fi.fi_daddr -#define fin_data fin_dat.fid_16 -#define fin_sport fin_dat.fid_16[0] -#define fin_dport fin_dat.fid_16[1] -#define fin_ports fin_dat.fid_32 - -#define IPF_IN 0 -#define IPF_OUT 1 +#define fin_data fin_fi.fi_ports +#define fin_sport fin_fi.fi_ports[0] +#define fin_dport fin_fi.fi_ports[1] +#define fin_tcpf fin_fi.fi_tcpf +#define fin_src6 fin_fi.fi_src +#define fin_dst6 fin_fi.fi_dst +#define fin_srcip6 fin_fi.fi_src.in6 +#define fin_dstip6 fin_fi.fi_dst.in6 + +#define IPF_IN 0 +#define IPF_OUT 1 typedef struct frentry *(*ipfunc_t) __P((fr_info_t *, u_32_t *)); -typedef int (*ipfuncinit_t) __P((struct frentry *)); +typedef int (*ipfuncinit_t) __P((struct ipf_main_softc_s *, struct frentry *)); typedef struct ipfunc_resolve { char ipfu_name[32]; ipfunc_t ipfu_addr; ipfuncinit_t ipfu_init; + ipfuncinit_t ipfu_fini; } ipfunc_resolve_t; /* @@ -366,39 +533,78 @@ typedef struct { #define ipt_tag ipt_un.iptu_tag #define ipt_num ipt_un.iptu_num +/* + * Structure to define address for pool lookups. + */ +typedef struct { + u_char adf_len; + sa_family_t adf_family; + u_char adf_xxx[2]; + i6addr_t adf_addr; +} addrfamily_t; + +RBI_LINK(ipf_rb, host_node_s); + +typedef struct host_node_s { + RBI_FIELD(ipf_rb) hn_entry; + addrfamily_t hn_addr; + int hn_active; +} host_node_t; + +typedef RBI_HEAD(ipf_rb, host_node_s) ipf_rb_head_t; + +typedef struct host_track_s { + ipf_rb_head_t ht_root; + int ht_max_nodes; + int ht_max_per_node; + int ht_netmask; + int ht_cur_nodes; +} host_track_t; + + +typedef enum fr_dtypes_e { + FRD_NORMAL = 0, + FRD_DSTLIST +} fr_dtypes_t; /* * This structure is used to hold information about the next hop for where * to forward a packet. */ typedef struct frdest { - void *fd_ifp; - i6addr_t fd_ip6; - char fd_ifname[LIFNAMSIZ]; + void *fd_ptr; + addrfamily_t fd_addr; + fr_dtypes_t fd_type; + int fd_name; + int fd_local; } frdest_t; +#define fd_ip6 fd_addr.adf_addr #define fd_ip fd_ip6.in4 +typedef enum fr_ctypes_e { + FR_NONE = 0, + FR_EQUAL, + FR_NEQUAL, + FR_LESST, + FR_GREATERT, + FR_LESSTE, + FR_GREATERTE, + FR_OUTRANGE, + FR_INRANGE, + FR_INCRANGE +} fr_ctypes_t; + /* * This structure holds information about a port comparison. */ typedef struct frpcmp { - int frp_cmp; /* data for port comparisons */ - u_short frp_port; /* top port for <> and >< */ - u_short frp_top; /* top port for <> and >< */ + fr_ctypes_t frp_cmp; /* data for port comparisons */ + u_32_t frp_port; /* top port for <> and >< */ + u_32_t frp_top; /* top port for <> and >< */ } frpcmp_t; -#define FR_NONE 0 -#define FR_EQUAL 1 -#define FR_NEQUAL 2 -#define FR_LESST 3 -#define FR_GREATERT 4 -#define FR_LESSTE 5 -#define FR_GREATERTE 6 -#define FR_OUTRANGE 7 -#define FR_INRANGE 8 -#define FR_INCRANGE 9 /* * Structure containing all the relevant TCP things that can be checked in @@ -420,52 +626,91 @@ typedef struct frtuc { #define FR_TCPFMAX 0x3f +typedef enum fr_atypes_e { + FRI_NONE = -1, /* For LHS of NAT */ + FRI_NORMAL = 0, /* Normal address */ + FRI_DYNAMIC, /* dynamic address */ + FRI_LOOKUP, /* address is a pool # */ + FRI_RANGE, /* address/mask is a range */ + FRI_NETWORK, /* network address from if */ + FRI_BROADCAST, /* broadcast address from if */ + FRI_PEERADDR, /* Peer address for P-to-P */ + FRI_NETMASKED, /* network address with netmask from if */ + FRI_SPLIT, /* For NAT compatibility */ + FRI_INTERFACE /* address is based on interface name */ +} fr_atypes_t; + /* * This structure makes up what is considered to be the IPFilter specific * matching components of a filter rule, as opposed to the data structures * used to define the result which are in frentry_t and not here. */ typedef struct fripf { - fr_ip_t fri_ip; - fr_ip_t fri_mip; /* mask structure */ + fr_ip_t fri_ip; + fr_ip_t fri_mip; /* mask structure */ - u_short fri_icmpm; /* data for ICMP packets (mask) */ - u_short fri_icmp; + u_short fri_icmpm; /* data for ICMP packets (mask) */ + u_short fri_icmp; - frtuc_t fri_tuc; - int fri_satype; /* addres type */ - int fri_datype; /* addres type */ - int fri_sifpidx; /* doing dynamic addressing */ - int fri_difpidx; /* index into fr_ifps[] to use when */ + frtuc_t fri_tuc; + fr_atypes_t fri_satype; /* addres type */ + fr_atypes_t fri_datype; /* addres type */ + int fri_sifpidx; /* doing dynamic addressing */ + int fri_difpidx; /* index into fr_ifps[] to use when */ } fripf_t; -#define fri_dstnum fri_ip.fi_dstnum +#define fri_dlookup fri_mip.fi_dst +#define fri_slookup fri_mip.fi_src +#define fri_dstnum fri_mip.fi_dstnum #define fri_srcnum fri_mip.fi_srcnum -#define fri_dstptr fri_ip.fi_dstptr +#define fri_dstname fri_mip.fi_dstname +#define fri_srcname fri_mip.fi_srcname +#define fri_dstptr fri_mip.fi_dstptr #define fri_srcptr fri_mip.fi_srcptr -#define FRI_NORMAL 0 /* Normal address */ -#define FRI_DYNAMIC 1 /* dynamic address */ -#define FRI_LOOKUP 2 /* address is a pool # */ -#define FRI_RANGE 3 /* address/mask is a range */ -#define FRI_NETWORK 4 /* network address from if */ -#define FRI_BROADCAST 5 /* broadcast address from if */ -#define FRI_PEERADDR 6 /* Peer address for P-to-P */ -#define FRI_NETMASKED 7 /* network address with netmask from if */ +typedef enum fr_rtypes_e { + FR_T_NONE = 0, + FR_T_IPF, /* IPF structures */ + FR_T_BPFOPC, /* BPF opcode */ + FR_T_CALLFUNC, /* callout to function in fr_func only */ + FR_T_COMPIPF, /* compiled C code */ + FR_T_IPFEXPR, /* IPF expression */ + FR_T_BUILTIN = 0x40000000, /* rule is in kernel space */ + FR_T_IPF_BUILTIN, + FR_T_BPFOPC_BUILTIN, + FR_T_CALLFUNC_BUILTIN, + FR_T_COMPIPF_BUILTIN, + FR_T_IPFEXPR_BUILTIN +} fr_rtypes_t; typedef struct frentry * (* frentfunc_t) __P((fr_info_t *)); typedef struct frentry { ipfmutex_t fr_lock; struct frentry *fr_next; - struct frentry **fr_grp; + struct frentry **fr_pnext; + struct frgroup *fr_grp; + struct frgroup *fr_grphead; + struct frgroup *fr_icmpgrp; struct ipscan *fr_isc; + struct frentry *fr_dnext; /* 2 fr_die linked list pointers */ + struct frentry **fr_pdnext; void *fr_ifas[4]; void *fr_ptr; /* for use with fr_arg */ - char *fr_comment; /* text comment for rule */ - int fr_ref; /* reference count - for grouping */ + int fr_comment; /* text comment for rule */ + int fr_size; /* size of this structure */ + int fr_ref; /* reference count */ int fr_statecnt; /* state count - for limit rules */ + u_32_t fr_die; /* only used on loading the rule */ + u_int fr_cksum; /* checksum on filter rules for performance */ + /* + * The line number from a file is here because we need to be able to + * match the rule generated with ``grep rule ipf.conf | ipf -rf -'' + * with the rule loaded using ``ipf -f ipf.conf'' - thus it can't be + * on the other side of fr_func. + */ + int fr_flineno; /* line number from conf file */ /* * These are only incremented when a packet matches this rule and * it is the last match @@ -475,13 +720,18 @@ typedef struct frentry { /* * For PPS rate limiting + * fr_lpu is used to always have the same size for this field, + * allocating 64bits for seconds and 32bits for milliseconds. */ - struct timeval fr_lastpkt; + union { + struct timeval frp_lastpkt; + char frp_bytes[12]; + } fr_lpu; int fr_curpps; union { void *fru_data; - caddr_t fru_caddr; + char *fru_caddr; fripf_t *fru_ipf; frentfunc_t fru_func; } fr_dun; @@ -492,30 +742,38 @@ typedef struct frentry { ipfunc_t fr_func; /* call this function */ int fr_dsize; int fr_pps; - int fr_statemax; /* max reference count */ - int fr_flineno; /* line number from conf file */ - u_32_t fr_type; + fr_rtypes_t fr_type; u_32_t fr_flags; /* per-rule flags && options (see below) */ u_32_t fr_logtag; /* user defined log tag # */ u_32_t fr_collect; /* collection number */ - u_int fr_arg; /* misc. numeric arg for rule */ + u_int fr_arg; /* misc. numeric arg for rule */ u_int fr_loglevel; /* syslog log facility + priority */ - u_int fr_age[2]; /* non-TCP timeouts */ - u_char fr_v; + u_char fr_family; u_char fr_icode; /* return ICMP code */ - char fr_group[FR_GROUPLEN]; /* group to which this rule belongs */ - char fr_grhead[FR_GROUPLEN]; /* group # which this rule starts */ + int fr_group; /* group to which this rule belongs */ + int fr_grhead; /* group # which this rule starts */ + int fr_ifnames[4]; + int fr_isctag; + int fr_rpc; /* XID Filtering */ ipftag_t fr_nattag; - char fr_ifnames[4][LIFNAMSIZ]; - char fr_isctag[16]; frdest_t fr_tifs[2]; /* "to"/"reply-to" interface */ frdest_t fr_dif; /* duplicate packet interface */ /* - * This must be last and will change after loaded into the kernel. + * These are all options related to stateful filtering */ - u_int fr_cksum; /* checksum on filter rules for performance */ + host_track_t fr_srctrack; + int fr_nostatelog; + int fr_statemax; /* max reference count */ + int fr_icmphead; /* ICMP group for state options */ + u_int fr_age[2]; /* non-TCP state timeouts */ + /* + * How big is the name buffer at the end? + */ + int fr_namelen; + char fr_names[1]; } frentry_t; +#define fr_lastpkt fr_lpu.frp_lastpkt #define fr_caddr fr_dun.fru_caddr #define fr_data fr_dun.fru_data #define fr_dfunc fr_dun.fru_func @@ -544,17 +802,27 @@ typedef struct frentry { #define fr_stop fr_tuc.ftu_stop #define fr_dtop fr_tuc.ftu_dtop #define fr_dst fr_ip.fi_dst.in4 +#define fr_dst6 fr_ip.fi_dst #define fr_daddr fr_ip.fi_dst.in4.s_addr #define fr_src fr_ip.fi_src.in4 +#define fr_src6 fr_ip.fi_src #define fr_saddr fr_ip.fi_src.in4.s_addr #define fr_dmsk fr_mip.fi_dst.in4 +#define fr_dmsk6 fr_mip.fi_dst #define fr_dmask fr_mip.fi_dst.in4.s_addr #define fr_smsk fr_mip.fi_src.in4 +#define fr_smsk6 fr_mip.fi_src #define fr_smask fr_mip.fi_src.in4.s_addr #define fr_dstnum fr_ip.fi_dstnum #define fr_srcnum fr_ip.fi_srcnum +#define fr_dlookup fr_ip.fi_dst +#define fr_slookup fr_ip.fi_src +#define fr_dstname fr_ip.fi_dstname +#define fr_srcname fr_ip.fi_srcname #define fr_dsttype fr_ip.fi_dsttype #define fr_srctype fr_ip.fi_srctype +#define fr_dstsubtype fr_ip.fi_dstsubtype +#define fr_srcsubtype fr_ip.fi_srcsubtype #define fr_dstptr fr_mip.fi_dstptr #define fr_srcptr fr_mip.fi_srcptr #define fr_dstfunc fr_mip.fi_dstfunc @@ -565,10 +833,10 @@ typedef struct frentry { #define fr_secmask fr_mip.fi_secmsk #define fr_authbits fr_ip.fi_auth #define fr_authmask fr_mip.fi_auth +#define fr_doi fr_ip.fi_doi +#define fr_doimask fr_mip.fi_doi #define fr_flx fr_ip.fi_flx #define fr_mflx fr_mip.fi_flx -#define fr_ifname fr_ifnames[0] -#define fr_oifname fr_ifnames[2] #define fr_ifa fr_ifas[0] #define fr_oifa fr_ifas[2] #define fr_tif fr_tifs[0] @@ -576,33 +844,22 @@ typedef struct frentry { #define FR_NOLOGTAG 0 -#ifndef offsetof -#define offsetof(t,m) (int)((&((t *)0L)->m)) -#endif #define FR_CMPSIZ (sizeof(struct frentry) - \ offsetof(struct frentry, fr_func)) +#define FR_NAME(_f, _n) (_f)->fr_names + (_f)->_n -/* - * fr_type - */ -#define FR_T_NONE 0 -#define FR_T_IPF 1 /* IPF structures */ -#define FR_T_BPFOPC 2 /* BPF opcode */ -#define FR_T_CALLFUNC 3 /* callout to function in fr_func only */ -#define FR_T_COMPIPF 4 /* compiled C code */ -#define FR_T_BUILTIN 0x80000000 /* rule is in kernel space */ /* * fr_flags */ -#define FR_CALL 0x00000 /* call rule */ #define FR_BLOCK 0x00001 /* do not allow packet to pass */ #define FR_PASS 0x00002 /* allow packet to pass */ #define FR_AUTH 0x00003 /* use authentication */ #define FR_PREAUTH 0x00004 /* require preauthentication */ #define FR_ACCOUNT 0x00005 /* Accounting rule */ #define FR_SKIP 0x00006 /* skip rule */ -#define FR_DIVERT 0x00007 /* divert rule */ +#define FR_DECAPSULATE 0x00008 /* decapsulate rule */ +#define FR_CALL 0x00009 /* call rule */ #define FR_CMDMASK 0x0000f #define FR_LOG 0x00010 /* Log */ #define FR_LOGB 0x00011 /* Log-fail */ @@ -623,19 +880,19 @@ typedef struct frentry { #define FR_LOGBODY 0x10000 /* Log the body */ #define FR_LOGFIRST 0x20000 /* Log the first byte if state held */ #define FR_LOGORBLOCK 0x40000 /* block the packet if it can't be logged */ -#define FR_DUP 0x80000 /* duplicate packet */ +#define FR_STLOOSE 0x80000 /* loose state checking */ #define FR_FRSTRICT 0x100000 /* strict frag. cache */ #define FR_STSTRICT 0x200000 /* strict keep state */ #define FR_NEWISN 0x400000 /* new ISN for outgoing TCP */ #define FR_NOICMPERR 0x800000 /* do not match ICMP errors in state */ #define FR_STATESYNC 0x1000000 /* synchronize state to slave */ +#define FR_COPIED 0x2000000 /* copied from user space */ +#define FR_INACTIVE 0x4000000 /* only used when flush'ing rules */ #define FR_NOMATCH 0x8000000 /* no match occured */ /* 0x10000000 FF_LOGPASS */ /* 0x20000000 FF_LOGBLOCK */ /* 0x40000000 FF_LOGNOMATCH */ /* 0x80000000 FF_BLOCKNONIP */ -#define FR_COPIED 0x40000000 /* copied from user space */ -#define FR_INACTIVE 0x80000000 /* only used when flush'ing rules */ #define FR_RETMASK (FR_RETICMP|FR_RETRST|FR_FAKEICMP) #define FR_ISBLOCK(x) (((x) & FR_CMDMASK) == FR_BLOCK) @@ -644,6 +901,7 @@ typedef struct frentry { #define FR_ISPREAUTH(x) (((x) & FR_CMDMASK) == FR_PREAUTH) #define FR_ISACCOUNT(x) (((x) & FR_CMDMASK) == FR_ACCOUNT) #define FR_ISSKIP(x) (((x) & FR_CMDMASK) == FR_SKIP) +#define FR_ISDECAPS(x) (((x) & FR_CMDMASK) == FR_DECAPSULATE) #define FR_ISNOMATCH(x) ((x) & FR_NOMATCH) #define FR_INOUT (FR_INQUE|FR_OUTQUE) @@ -661,8 +919,8 @@ typedef struct frentry { * Structure that passes information on what/how to flush to the kernel. */ typedef struct ipfflush { - int ipflu_how; - int ipflu_arg; + int ipflu_how; + int ipflu_arg; } ipfflush_t; @@ -670,12 +928,12 @@ typedef struct ipfflush { * */ typedef struct ipfgetctl { - u_int ipfg_min; /* min value */ - u_int ipfg_current; /* current value */ - u_int ipfg_max; /* max value */ - u_int ipfg_default; /* default value */ - u_int ipfg_steps; /* value increments */ - char ipfg_name[40]; /* tag name for this control */ + u_int ipfg_min; /* min value */ + u_int ipfg_current; /* current value */ + u_int ipfg_max; /* max value */ + u_int ipfg_default; /* default value */ + u_int ipfg_steps; /* value increments */ + char ipfg_name[40]; /* tag name for this control */ } ipfgetctl_t; typedef struct ipfsetctl { @@ -690,7 +948,43 @@ typedef struct ipfsetctl { * in this single structure so that they can all easily be collected and * copied back as required. */ -typedef struct filterstats { +typedef struct ipf_statistics { + u_long fr_icmp_coalesce; + u_long fr_tcp_frag; + u_long fr_tcp_pullup; + u_long fr_tcp_short; + u_long fr_tcp_small; + u_long fr_tcp_bad_flags; + u_long fr_udp_pullup; + u_long fr_ip_freed; + u_long fr_v6_ah_bad; + u_long fr_v6_bad; + u_long fr_v6_badfrag; + u_long fr_v6_dst_bad; + u_long fr_v6_esp_pullup; + u_long fr_v6_ext_short; + u_long fr_v6_ext_pullup; + u_long fr_v6_ext_hlen; + u_long fr_v6_frag_bad; + u_long fr_v6_frag_pullup; + u_long fr_v6_frag_size; + u_long fr_v6_gre_pullup; + u_long fr_v6_icmp6_pullup; + u_long fr_v6_rh_bad; + u_long fr_v6_badttl; /* TTL in packet doesn't reach minimum */ + u_long fr_v4_ah_bad; + u_long fr_v4_ah_pullup; + u_long fr_v4_esp_pullup; + u_long fr_v4_cipso_bad; + u_long fr_v4_cipso_tlen; + u_long fr_v4_gre_frag; + u_long fr_v4_gre_pullup; + u_long fr_v4_icmp_frag; + u_long fr_v4_icmp_pullup; + u_long fr_v4_badttl; /* TTL in packet doesn't reach minimum */ + u_long fr_v4_badsrc; /* source received doesn't match route */ + u_long fr_l4_badcksum; /* layer 4 header checksum failure */ + u_long fr_badcoalesces; u_long fr_pass; /* packets allowed */ u_long fr_block; /* packets denied */ u_long fr_nom; /* packets which don't match any rule */ @@ -698,8 +992,6 @@ typedef struct filterstats { u_long fr_ppkl; /* packets allowed and logged */ u_long fr_bpkl; /* packets denied and logged */ u_long fr_npkl; /* packets unmatched and logged */ - u_long fr_pkl; /* packets logged */ - u_long fr_skip; /* packets to be logged but buffer full */ u_long fr_ret; /* packets for which a return is sent */ u_long fr_acct; /* packets for which counting was performed */ u_long fr_bnfr; /* bad attempts to allocate fragment state */ @@ -708,15 +1000,15 @@ typedef struct filterstats { u_long fr_bads; /* bad attempts to allocate packet state */ u_long fr_ads; /* new packet state kept */ u_long fr_chit; /* cached hit */ + u_long fr_cmiss; /* cached miss */ u_long fr_tcpbad; /* TCP checksum check failures */ u_long fr_pull[2]; /* good and bad pullup attempts */ - u_long fr_badsrc; /* source received doesn't match route */ - u_long fr_badttl; /* TTL in packet doesn't reach minimum */ u_long fr_bad; /* bad IP packets to the filter */ u_long fr_ipv6; /* IPv6 packets in/out */ u_long fr_ppshit; /* dropped because of pps ceiling */ u_long fr_ipud; /* IP id update failures */ -} filterstats_t; + u_long fr_blocked[FRB_MAX_VALUE + 1]; +} ipf_statistics_t; /* * Log structure. Each packet header logged is prepended by one of these. @@ -726,6 +1018,7 @@ typedef struct filterstats { typedef struct iplog { u_32_t ipl_magic; u_int ipl_count; + u_32_t ipl_seqnum; struct timeval ipl_time; size_t ipl_dsize; struct iplog *ipl_next; @@ -745,18 +1038,19 @@ typedef struct ipflog { #else u_int fl_unit; #endif - u_32_t fl_rule; - u_32_t fl_flags; - u_32_t fl_lflags; - u_32_t fl_logtag; + u_32_t fl_rule; + u_32_t fl_flags; + u_32_t fl_lflags; + u_32_t fl_logtag; ipftag_t fl_nattag; - u_short fl_plen; /* extra data after hlen */ - u_short fl_loglevel; /* syslog log level */ - char fl_group[FR_GROUPLEN]; - u_char fl_hlen; /* length of IP headers saved */ - u_char fl_dir; - u_char fl_xxx[2]; /* pad */ - char fl_ifname[LIFNAMSIZ]; + u_short fl_plen; /* extra data after hlen */ + u_short fl_loglevel; /* syslog log level */ + char fl_group[FR_GROUPLEN]; + u_char fl_hlen; /* length of IP headers saved */ + u_char fl_dir; + u_char fl_breason; /* from fin_reason */ + u_char fl_family; /* address family of packet logged */ + char fl_ifname[LIFNAMSIZ]; } ipflog_t; #ifndef IPF_LOGGING @@ -766,12 +1060,12 @@ typedef struct ipflog { # define IPF_DEFAULT_PASS FR_PASS #endif -#define DEFAULT_IPFLOGSIZE 8192 +#define DEFAULT_IPFLOGSIZE 32768 #ifndef IPFILTER_LOGSIZE # define IPFILTER_LOGSIZE DEFAULT_IPFLOGSIZE #else -# if IPFILTER_LOGSIZE < DEFAULT_IPFLOGSIZE -# error IPFILTER_LOGSIZE too small. Must be >= DEFAULT_IPFLOGSIZE +# if IPFILTER_LOGSIZE < 8192 +# error IPFILTER_LOGSIZE too small. Must be >= 8192 # endif #endif @@ -816,34 +1110,30 @@ typedef struct ipflog { * For SIOCGETFS */ typedef struct friostat { - struct filterstats f_st[2]; - struct frentry *f_ipf[2][2]; - struct frentry *f_acct[2][2]; - struct frentry *f_ipf6[2][2]; - struct frentry *f_acct6[2][2]; - struct frentry *f_auth; - struct frgroup *f_groups[IPL_LOGSIZE][2]; - u_long f_froute[2]; - u_long f_ticks; - int f_locks[IPL_LOGMAX]; - size_t f_kmutex_sz; - size_t f_krwlock_sz; - int f_defpass; /* default pass - from fr_pass */ - int f_active; /* 1 or 0 - active rule set */ - int f_running; /* 1 if running, else 0 */ - int f_logging; /* 1 if enabled, else 0 */ - int f_features; - char f_version[32]; /* version string */ + ipf_statistics_t f_st[2]; + frentry_t *f_ipf[2][2]; + frentry_t *f_acct[2][2]; + frentry_t *f_auth; + struct frgroup *f_groups[IPL_LOGSIZE][2]; + u_long f_froute[2]; + u_long f_log_ok; + u_long f_log_fail; + u_long f_rb_no_mem; + u_long f_rb_node_max; + u_32_t f_ticks; + int f_locks[IPL_LOGSIZE]; + int f_defpass; /* default pass - from fr_pass */ + int f_active; /* 1 or 0 - active rule set */ + int f_running; /* 1 if running, else 0 */ + int f_logging; /* 1 if enabled, else 0 */ + int f_features; + char f_version[32]; /* version string */ } friostat_t; #define f_fin f_ipf[0] -#define f_fin6 f_ipf6[0] #define f_fout f_ipf[1] -#define f_fout6 f_ipf6[1] #define f_acctin f_acct[0] -#define f_acctin6 f_acct6[0] #define f_acctout f_acct[1] -#define f_acctout6 f_acct6[1] #define IPF_FEAT_LKM 0x001 #define IPF_FEAT_LOG 0x002 @@ -865,12 +1155,13 @@ typedef struct optlist { * Group list structure. */ typedef struct frgroup { - struct frgroup *fg_next; - struct frentry *fg_head; - struct frentry *fg_start; - u_32_t fg_flags; - int fg_ref; - char fg_name[FR_GROUPLEN]; + struct frgroup *fg_next; + struct frentry *fg_head; + struct frentry *fg_start; + struct frgroup **fg_set; + u_32_t fg_flags; + int fg_ref; + char fg_name[FR_GROUPLEN]; } frgroup_t; #define FG_NAME(g) (*(g)->fg_name == '\0' ? "" : (g)->fg_name) @@ -880,50 +1171,66 @@ typedef struct frgroup { * Used by state and NAT tables */ typedef struct icmpinfo { - u_short ici_id; - u_short ici_seq; - u_char ici_type; + u_short ici_id; + u_short ici_seq; + u_char ici_type; } icmpinfo_t; typedef struct udpinfo { - u_short us_sport; - u_short us_dport; + u_short us_sport; + u_short us_dport; } udpinfo_t; typedef struct tcpdata { - u_32_t td_end; - u_32_t td_maxend; - u_32_t td_maxwin; - u_32_t td_winscale; - u_32_t td_maxseg; - int td_winflags; + u_32_t td_end; + u_32_t td_maxend; + u_32_t td_maxwin; + u_32_t td_winscale; + u_32_t td_maxseg; + int td_winflags; } tcpdata_t; #define TCP_WSCALE_MAX 14 #define TCP_WSCALE_SEEN 0x00000001 #define TCP_WSCALE_FIRST 0x00000002 +#define TCP_SACK_PERMIT 0x00000004 typedef struct tcpinfo { - u_short ts_sport; - u_short ts_dport; - tcpdata_t ts_data[2]; + u_32_t ts_sport; + u_32_t ts_dport; + tcpdata_t ts_data[2]; } tcpinfo_t; +/* + * Structures to define a GRE header as seen in a packet. + */ struct grebits { - u_32_t grb_C:1; - u_32_t grb_R:1; - u_32_t grb_K:1; - u_32_t grb_S:1; - u_32_t grb_s:1; - u_32_t grb_recur:1; - u_32_t grb_A:1; - u_32_t grb_flags:3; - u_32_t grb_ver:3; - u_short grb_ptype; +#if defined(sparc) + u_32_t grb_ver:3; + u_32_t grb_flags:3; + u_32_t grb_A:1; + u_32_t grb_recur:1; + u_32_t grb_s:1; + u_32_t grb_S:1; + u_32_t grb_K:1; + u_32_t grb_R:1; + u_32_t grb_C:1; +#else + u_32_t grb_C:1; + u_32_t grb_R:1; + u_32_t grb_K:1; + u_32_t grb_S:1; + u_32_t grb_s:1; + u_32_t grb_recur:1; + u_32_t grb_A:1; + u_32_t grb_flags:3; + u_32_t grb_ver:3; +#endif + u_short grb_ptype; }; typedef struct grehdr { @@ -931,8 +1238,8 @@ typedef struct grehdr { struct grebits gru_bits; u_short gru_flags; } gr_un; - u_short gr_len; - u_short gr_call; + u_short gr_len; + u_short gr_call; } grehdr_t; #define gr_flags gr_un.gru_flags @@ -947,31 +1254,48 @@ typedef struct grehdr { #define gr_A gr_bits.grb_A #define gr_ver gr_bits.grb_ver - +/* + * GRE information tracked by "keep state" + */ typedef struct greinfo { - u_short gs_call[2]; - u_short gs_flags; - u_short gs_ptype; + u_short gs_call[2]; + u_short gs_flags; + u_short gs_ptype; } greinfo_t; #define GRE_REV(x) ((ntohs(x) >> 13) & 7) /* + * Format of an Authentication header + */ +typedef struct authhdr { + u_char ah_next; + u_char ah_plen; + u_short ah_reserved; + u_32_t ah_spi; + u_32_t ah_seq; + /* Following the sequence number field is 0 or more bytes of */ + /* authentication data, as specified by ah_plen - RFC 2402. */ +} authhdr_t; + + +/* * Timeout tail queue list member */ typedef struct ipftqent { struct ipftqent **tqe_pnext; struct ipftqent *tqe_next; struct ipftq *tqe_ifq; - void *tqe_parent; /* pointer back to NAT/state struct */ - u_long tqe_die; /* when this entriy is to die */ - u_long tqe_touched; - int tqe_flags; - int tqe_state[2]; /* current state of this entry */ + void *tqe_parent; /* pointer back to NAT/state struct */ + u_32_t tqe_die; /* when this entriy is to die */ + u_32_t tqe_touched; + int tqe_flags; + int tqe_state[2]; /* current state of this entry */ } ipftqent_t; #define TQE_RULEBASED 0x00000001 +#define TQE_DELETE 0x00000002 /* @@ -979,43 +1303,46 @@ typedef struct ipftqent { */ typedef struct ipftq { ipfmutex_t ifq_lock; - u_int ifq_ttl; + u_int ifq_ttl; ipftqent_t *ifq_head; ipftqent_t **ifq_tail; - struct ipftq *ifq_next; - struct ipftq **ifq_pnext; - int ifq_ref; - u_int ifq_flags; + struct ipftq *ifq_next; + struct ipftq **ifq_pnext; + int ifq_ref; + u_int ifq_flags; } ipftq_t; #define IFQF_USER 0x01 /* User defined aging */ #define IFQF_DELETE 0x02 /* Marked for deletion */ #define IFQF_PROXY 0x04 /* Timeout queue in use by a proxy */ +#define IPFTQ_INIT(x,y,z) do { \ + (x)->ifq_ttl = (y); \ + (x)->ifq_head = NULL; \ + (x)->ifq_ref = 1; \ + (x)->ifq_tail = &(x)->ifq_head; \ + MUTEX_INIT(&(x)->ifq_lock, (z)); \ + } while (0) + #define IPF_HZ_MULT 1 #define IPF_HZ_DIVIDE 2 /* How many times a second ipfilter */ /* checks its timeout queues. */ #define IPF_TTLVAL(x) (((x) / IPF_HZ_MULT) * IPF_HZ_DIVIDE) -/* - * Structure to define address for pool lookups. - */ -typedef struct { - u_char adf_len; - i6addr_t adf_addr; -} addrfamily_t; +typedef int (*ipftq_delete_fn_t)(struct ipf_main_softc_s *, void *); /* * Object structure description. For passing through in ioctls. */ typedef struct ipfobj { - u_32_t ipfo_rev; /* IPFilter version number */ - u_32_t ipfo_size; /* size of object at ipfo_ptr */ - void *ipfo_ptr; /* pointer to object */ - int ipfo_type; /* type of object being pointed to */ - int ipfo_offset; /* bytes from ipfo_ptr where to start */ - u_char ipfo_xxxpad[32]; /* reserved for future use */ + u_32_t ipfo_rev; /* IPFilter version number */ + u_32_t ipfo_size; /* size of object at ipfo_ptr */ + void *ipfo_ptr; /* pointer to object */ + int ipfo_type; /* type of object being pointed to */ + int ipfo_offset; /* bytes from ipfo_ptr where to start */ + int ipfo_retval; /* return value */ + u_char ipfo_xxxpad[28]; /* reserved for future use */ } ipfobj_t; #define IPFOBJ_FRENTRY 0 /* struct frentry */ @@ -1032,24 +1359,46 @@ typedef struct ipfobj { #define IPFOBJ_STATESTAT 11 /* struct ips_stat */ #define IPFOBJ_FRAUTH 12 /* struct frauth */ #define IPFOBJ_TUNEABLE 13 /* struct ipftune */ +#define IPFOBJ_NAT 14 /* struct nat */ +#define IPFOBJ_IPFITER 15 /* struct ipfruleiter */ +#define IPFOBJ_GENITER 16 /* struct ipfgeniter */ +#define IPFOBJ_GTABLE 17 /* struct ipftable */ +#define IPFOBJ_LOOKUPITER 18 /* struct ipflookupiter */ +#define IPFOBJ_STATETQTAB 19 /* struct ipftq * NSTATES */ +#define IPFOBJ_IPFEXPR 20 +#define IPFOBJ_PROXYCTL 21 /* strct ap_ctl */ +#define IPFOBJ_FRIPF 22 /* structfripf */ +#define IPFOBJ_COUNT 23 /* How many #defines are above this? */ typedef union ipftunevalptr { - void *ipftp_void; - u_long *ipftp_long; - u_int *ipftp_int; - u_short *ipftp_short; - u_char *ipftp_char; + void *ipftp_void; + u_long *ipftp_long; + u_int *ipftp_int; + u_short *ipftp_short; + u_char *ipftp_char; + u_long ipftp_offset; } ipftunevalptr_t; +typedef union ipftuneval { + u_long ipftu_long; + u_int ipftu_int; + u_short ipftu_short; + u_char ipftu_char; +} ipftuneval_t; + +struct ipftuneable; +typedef int (* ipftunefunc_t) __P((struct ipf_main_softc_s *, struct ipftuneable *, ipftuneval_t *)); + typedef struct ipftuneable { ipftunevalptr_t ipft_una; - char *ipft_name; + const char *ipft_name; u_long ipft_min; u_long ipft_max; int ipft_sz; int ipft_flags; struct ipftuneable *ipft_next; + ipftunefunc_t ipft_func; } ipftuneable_t; #define ipft_addr ipft_una.ipftp_void @@ -1061,13 +1410,6 @@ typedef struct ipftuneable { #define IPFT_RDONLY 1 /* read-only */ #define IPFT_WRDISABLED 2 /* write when disabled only */ -typedef union ipftuneval { - u_long ipftu_long; - u_int ipftu_int; - u_short ipftu_short; - u_char ipftu_char; -} ipftuneval_t; - typedef struct ipftune { void *ipft_cookie; ipftuneval_t ipft_un; @@ -1083,6 +1425,13 @@ typedef struct ipftune { #define ipft_vshort ipft_un.ipftu_short #define ipft_vchar ipft_un.ipftu_char +/* + * Hash table header + */ +#define IPFHASH(x,y) typedef struct { \ + ipfrwlock_t ipfh_lock; \ + struct x *ipfh_head; \ + } y /* ** HPUX Port @@ -1113,21 +1462,261 @@ typedef struct ipftune { # endif #endif +#ifdef _KERNEL +# define FR_VERBOSE(verb_pr) +# define FR_DEBUG(verb_pr) +#else +extern void ipfkdebug __P((char *, ...)); +extern void ipfkverbose __P((char *, ...)); +# define FR_VERBOSE(verb_pr) ipfkverbose verb_pr +# define FR_DEBUG(verb_pr) ipfkdebug verb_pr +#endif + +/* + * + */ +typedef struct ipfruleiter { + int iri_inout; + char iri_group[FR_GROUPLEN]; + int iri_active; + int iri_nrules; + int iri_v; /* No longer used (compatibility) */ + frentry_t *iri_rule; +} ipfruleiter_t; + +/* + * Values for iri_inout + */ +#define F_IN 0 +#define F_OUT 1 +#define F_ACIN 2 +#define F_ACOUT 3 + + +typedef struct ipfgeniter { + int igi_type; + int igi_nitems; + void *igi_data; +} ipfgeniter_t; + +#define IPFGENITER_IPF 0 +#define IPFGENITER_NAT 1 +#define IPFGENITER_IPNAT 2 +#define IPFGENITER_FRAG 3 +#define IPFGENITER_AUTH 4 +#define IPFGENITER_STATE 5 +#define IPFGENITER_NATFRAG 6 +#define IPFGENITER_HOSTMAP 7 +#define IPFGENITER_LOOKUP 8 + +typedef struct ipftable { + int ita_type; + void *ita_table; +} ipftable_t; + +#define IPFTABLE_BUCKETS 1 +#define IPFTABLE_BUCKETS_NATIN 2 +#define IPFTABLE_BUCKETS_NATOUT 3 + + +typedef struct ipf_v4_masktab_s { + u_32_t imt4_active[33]; + int imt4_masks[33]; + int imt4_max; +} ipf_v4_masktab_t; + +typedef struct ipf_v6_masktab_s { + i6addr_t imt6_active[129]; + int imt6_masks[129]; + int imt6_max; +} ipf_v6_masktab_t; + + +/* + * + */ +typedef struct ipftoken { + struct ipftoken *ipt_next; + struct ipftoken **ipt_pnext; + void *ipt_ctx; + void *ipt_data; + u_long ipt_die; + int ipt_type; + int ipt_uid; + int ipt_subtype; + int ipt_ref; + int ipt_complete; +} ipftoken_t; + + +/* + * + */ +typedef struct ipfexp { + int ipfe_cmd; + int ipfe_not; + int ipfe_narg; + int ipfe_size; + int ipfe_arg0[1]; +} ipfexp_t; + +/* + * Currently support commands (ipfe_cmd) + * 32bits is split up follows: + * aabbcccc + * aa = 0 = packet matching, 1 = meta data matching + * bb = IP protocol number + * cccc = command + */ +#define IPF_EXP_IP_PR 0x00000001 +#define IPF_EXP_IP_ADDR 0x00000002 +#define IPF_EXP_IP_SRCADDR 0x00000003 +#define IPF_EXP_IP_DSTADDR 0x00000004 +#define IPF_EXP_IP6_ADDR 0x00000005 +#define IPF_EXP_IP6_SRCADDR 0x00000006 +#define IPF_EXP_IP6_DSTADDR 0x00000007 +#define IPF_EXP_TCP_FLAGS 0x00060001 +#define IPF_EXP_TCP_PORT 0x00060002 +#define IPF_EXP_TCP_SPORT 0x00060003 +#define IPF_EXP_TCP_DPORT 0x00060004 +#define IPF_EXP_UDP_PORT 0x00110002 +#define IPF_EXP_UDP_SPORT 0x00110003 +#define IPF_EXP_UDP_DPORT 0x00110004 +#define IPF_EXP_IDLE_GT 0x01000001 +#define IPF_EXP_TCP_STATE 0x01060002 +#define IPF_EXP_END 0xffffffff + +#define ONE_DAY IPF_TTLVAL(1 * 86400) /* 1 day */ +#define FIVE_DAYS (5 * ONE_DAY) + +typedef struct ipf_main_softc_s { + struct ipf_main_softc_s *ipf_next; + ipfmutex_t ipf_rw; + ipfmutex_t ipf_timeoutlock; + ipfrwlock_t ipf_mutex; + ipfrwlock_t ipf_frag; + ipfrwlock_t ipf_global; + ipfrwlock_t ipf_tokens; + ipfrwlock_t ipf_state; + ipfrwlock_t ipf_nat; + ipfrwlock_t ipf_natfrag; + ipfrwlock_t ipf_poolrw; + int ipf_dynamic_softc; + int ipf_refcnt; + int ipf_running; + int ipf_flags; + int ipf_active; + int ipf_control_forwarding; + int ipf_update_ipid; + int ipf_chksrc; /* causes a system crash if enabled */ + int ipf_pass; + int ipf_minttl; + int ipf_icmpminfragmtu; + int ipf_interror; /* Should be in a struct that is per */ + /* thread or process. Does not belong */ + /* here but there's a lot more work */ + /* in doing that properly. For now, */ + /* it is squatting. */ + u_int ipf_tcpidletimeout; + u_int ipf_tcpclosewait; + u_int ipf_tcplastack; + u_int ipf_tcptimewait; + u_int ipf_tcptimeout; + u_int ipf_tcpsynsent; + u_int ipf_tcpsynrecv; + u_int ipf_tcpclosed; + u_int ipf_tcphalfclosed; + u_int ipf_udptimeout; + u_int ipf_udpacktimeout; + u_int ipf_icmptimeout; + u_int ipf_icmpacktimeout; + u_int ipf_iptimeout; + u_long ipf_ticks; + u_long ipf_userifqs; + u_long ipf_rb_no_mem; + u_long ipf_rb_node_max; + u_long ipf_frouteok[2]; + ipftuneable_t *ipf_tuners; + void *ipf_frag_soft; + void *ipf_nat_soft; + void *ipf_state_soft; + void *ipf_auth_soft; + void *ipf_proxy_soft; + void *ipf_sync_soft; + void *ipf_lookup_soft; + void *ipf_log_soft; + struct frgroup *ipf_groups[IPL_LOGSIZE][2]; + frentry_t *ipf_rules[2][2]; + frentry_t *ipf_acct[2][2]; + frentry_t *ipf_rule_explist[2]; + ipftoken_t *ipf_token_head; + ipftoken_t **ipf_token_tail; +#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) && \ + defined(_KERNEL) + struct callout_handle ipf_slow_ch; +#endif +#if defined(linux) && defined(_KERNEL) + struct timer_list ipf_timer; +#endif +#if NETBSD_GE_REV(104040000) + struct callout ipf_slow_ch; +#endif +#if SOLARIS +# if SOLARIS2 >= 7 + timeout_id_t ipf_slow_ch; +# else + int ipf_slow_ch; +# endif +#endif +#if defined(_KERNEL) +# if SOLARIS + struct pollhead ipf_poll_head[IPL_LOGSIZE]; + void *ipf_dip; +# if defined(INSTANCES) + int ipf_get_loopback; + u_long ipf_idnum; + net_handle_t ipf_nd_v4; + net_handle_t ipf_nd_v6; + hook_t *ipf_hk_v4_in; + hook_t *ipf_hk_v4_out; + hook_t *ipf_hk_v4_nic; + hook_t *ipf_hk_v6_in; + hook_t *ipf_hk_v6_out; + hook_t *ipf_hk_v6_nic; + hook_t *ipf_hk_loop_v4_in; + hook_t *ipf_hk_loop_v4_out; + hook_t *ipf_hk_loop_v6_in; + hook_t *ipf_hk_loop_v6_out; +# endif +# else +# if defined(linux) && defined(_KERNEL) + struct poll_table_struct ipf_selwait[IPL_LOGSIZE]; + wait_queue_head_t iplh_linux[IPL_LOGSIZE]; +# else + struct selinfo ipf_selwait[IPL_LOGSIZE]; +# endif +# endif +#endif + void *ipf_slow; + ipf_statistics_t ipf_stats[2]; + u_char ipf_iss_secret[32]; + u_short ipf_ip_id; +} ipf_main_softc_t; + +#define IPFERROR(_e) do { softc->ipf_interror = (_e); \ + DT1(user_error, int, _e); \ + } while (0) + #ifndef _KERNEL -extern int fr_check __P((struct ip *, int, void *, int, mb_t **)); -extern int (*fr_checkp) __P((ip_t *, int, void *, int, mb_t **)); -extern int ipf_log __P((void)); +extern int ipf_check __P((void *, struct ip *, int, void *, int, mb_t **)); +extern int (*ipf_checkp) __P((ip_t *, int, void *, int, mb_t **)); extern struct ifnet *get_unit __P((char *, int)); extern char *get_ifname __P((struct ifnet *)); -# if defined(__NetBSD__) || defined(__OpenBSD__) || \ - (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) -extern int iplioctl __P((int, ioctlcmd_t, caddr_t, int)); -# else -extern int iplioctl __P((int, ioctlcmd_t, caddr_t, int)); -# endif -extern int iplopen __P((dev_t, int)); -extern int iplclose __P((dev_t, int)); +extern int ipfioctl __P((ipf_main_softc_t *, int, ioctlcmd_t, + caddr_t, int)); extern void m_freem __P((mb_t *)); +extern size_t msgdsize __P((mb_t *)); +extern int bcopywrap __P((void *, void *, size_t)); #else /* #ifndef _KERNEL */ # if defined(__NetBSD__) && defined(PFIL_HOOKS) extern void ipfilterattach __P((int)); @@ -1135,234 +1724,277 @@ extern void ipfilterattach __P((int)); extern int ipl_enable __P((void)); extern int ipl_disable __P((void)); # ifdef MENTAT -extern int fr_check __P((struct ip *, int, void *, int, void *, - mblk_t **)); +extern int ipf_check __P((void *, struct ip *, int, void *, int, void *, + mblk_t **)); # if SOLARIS +extern void ipf_prependmbt(fr_info_t *, mblk_t *); # if SOLARIS2 >= 7 -extern int iplioctl __P((dev_t, int, intptr_t, int, cred_t *, int *)); +extern int ipfioctl __P((dev_t, int, intptr_t, int, cred_t *, int *)); # else -extern int iplioctl __P((dev_t, int, int *, int, cred_t *, int *)); +extern int ipfioctl __P((dev_t, int, int *, int, cred_t *, int *)); # endif -extern int iplopen __P((dev_t *, int, int, cred_t *)); -extern int iplclose __P((dev_t, int, int, cred_t *)); -extern int iplread __P((dev_t, uio_t *, cred_t *)); -extern int iplwrite __P((dev_t, uio_t *, cred_t *)); # endif # ifdef __hpux -extern int iplopen __P((dev_t, int, intptr_t, int)); -extern int iplclose __P((dev_t, int, int)); -extern int iplioctl __P((dev_t, int, caddr_t, int)); -extern int iplread __P((dev_t, uio_t *)); -extern int iplwrite __P((dev_t, uio_t *)); -extern int iplselect __P((dev_t, int)); +extern int ipfioctl __P((dev_t, int, caddr_t, int)); +extern int ipf_select __P((dev_t, int)); # endif -extern int ipfsync __P((void)); -extern int fr_qout __P((queue_t *, mblk_t *)); +extern int ipf_qout __P((queue_t *, mblk_t *)); # else /* MENTAT */ -extern int fr_check __P((struct ip *, int, void *, int, mb_t **)); +extern int ipf_check __P((void *, struct ip *, int, void *, int, mb_t **)); extern int (*fr_checkp) __P((ip_t *, int, void *, int, mb_t **)); extern size_t mbufchainlen __P((mb_t *)); # ifdef __sgi # include <sys/cred.h> -extern int iplioctl __P((dev_t, int, caddr_t, int, cred_t *, int *)); -extern int iplopen __P((dev_t *, int, int, cred_t *)); -extern int iplclose __P((dev_t, int, int, cred_t *)); -extern int iplread __P((dev_t, uio_t *, cred_t *)); -extern int iplwrite __P((dev_t, uio_t *, cred_t *)); -extern int ipfsync __P((void)); +extern int ipfioctl __P((dev_t, int, caddr_t, int, cred_t *, int *)); extern int ipfilter_sgi_attach __P((void)); extern void ipfilter_sgi_detach __P((void)); extern void ipfilter_sgi_intfsync __P((void)); # else # ifdef IPFILTER_LKM -extern int iplidentify __P((char *)); +extern int ipf_identify __P((char *)); # endif -# if (_BSDI_VERSION >= 199510) || (__FreeBSD_version >= 220000) || \ - (NetBSD >= 199511) || defined(__OpenBSD__) -# if defined(__NetBSD__) || (_BSDI_VERSION >= 199701) || \ - defined(__OpenBSD__) || (__FreeBSD_version >= 300000) +# if BSDOS_GE_REV(199510) || FREEBSD_GE_REV(220000) || \ + (defined(NetBSD) && (NetBSD >= 199511)) || defined(__OpenBSD__) +# if defined(__NetBSD__) || BSDOS_GE_REV(199701) || \ + defined(__OpenBSD__) || FREEBSD_GE_REV(300000) # if (__FreeBSD_version >= 500024) # if (__FreeBSD_version >= 502116) -extern int iplioctl __P((struct cdev*, u_long, caddr_t, int, struct thread *)); +extern int ipfioctl __P((struct cdev*, u_long, caddr_t, int, struct thread *)); # else -extern int iplioctl __P((dev_t, u_long, caddr_t, int, struct thread *)); +extern int ipfioctl __P((dev_t, u_long, caddr_t, int, struct thread *)); # endif /* __FreeBSD_version >= 502116 */ # else -extern int iplioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); +# if NETBSD_GE_REV(499001000) +extern int ipfioctl __P((dev_t, u_long, void *, int, struct lwp *)); +# else +# if NETBSD_GE_REV(399001400) +extern int ipfioctl __P((dev_t, u_long, caddr_t, int, struct lwp *)); +# else +extern int ipfioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); +# endif +# endif # endif /* __FreeBSD_version >= 500024 */ # else -extern int iplioctl __P((dev_t, int, caddr_t, int, struct proc *)); +extern int ipfioctl __P((dev_t, int, caddr_t, int, struct proc *)); # endif -# if (__FreeBSD_version >= 500024) -# if (__FreeBSD_version >= 502116) -extern int iplopen __P((struct cdev*, int, int, struct thread *)); -extern int iplclose __P((struct cdev*, int, int, struct thread *)); -# else -extern int iplopen __P((dev_t, int, int, struct thread *)); -extern int iplclose __P((dev_t, int, int, struct thread *)); -# endif /* __FreeBSD_version >= 502116 */ -# else -extern int iplopen __P((dev_t, int, int, struct proc *)); -extern int iplclose __P((dev_t, int, int, struct proc *)); -# endif /* __FreeBSD_version >= 500024 */ # else # ifdef linux -extern int iplioctl __P((struct inode *, struct file *, u_int, u_long)); +extern int ipfioctl __P((struct inode *, struct file *, u_int, u_long)); # else -extern int iplopen __P((dev_t, int)); -extern int iplclose __P((dev_t, int)); -extern int iplioctl __P((dev_t, int, caddr_t, int)); +extern int ipfioctl __P((dev_t, int, caddr_t, int)); # endif # endif /* (_BSDI_VERSION >= 199510) */ -# if BSD >= 199306 -# if (__FreeBSD_version >= 502116) -extern int iplread __P((struct cdev*, struct uio *, int)); -extern int iplwrite __P((struct cdev*, struct uio *, int)); -# else -extern int iplread __P((dev_t, struct uio *, int)); -extern int iplwrite __P((dev_t, struct uio *, int)); -# endif /* __FreeBSD_version >= 502116 */ -# else -# ifndef linux -extern int iplread __P((dev_t, struct uio *)); -extern int iplwrite __P((dev_t, struct uio *)); -# endif -# endif /* BSD >= 199306 */ # endif /* __ sgi */ # endif /* MENTAT */ -#endif /* #ifndef _KERNEL */ +# if defined(__FreeBSD_version) +extern int ipf_pfil_hook __P((void)); +extern int ipf_pfil_unhook __P((void)); +extern void ipf_event_reg __P((void)); +extern void ipf_event_dereg __P((void)); +# endif + +# if defined(INSTANCES) +extern ipf_main_softc_t *ipf_find_softc __P((u_long)); +extern int ipf_set_loopback __P((ipf_main_softc_t *, ipftuneable_t *, + ipftuneval_t *)); +# endif -extern ipfmutex_t ipl_mutex, ipf_authmx, ipf_rw, ipf_hostmap; -extern ipfmutex_t ipf_timeoutlock, ipf_stinsert, ipf_natio, ipf_nat_new; -extern ipfrwlock_t ipf_mutex, ipf_global, ip_poolrw, ipf_ipidfrag; -extern ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth; +#endif /* #ifndef _KERNEL */ -extern char *memstr __P((char *, char *, int, int)); +extern char *memstr __P((const char *, char *, size_t, size_t)); extern int count4bits __P((u_32_t)); -extern int frrequest __P((int, ioctlcmd_t, caddr_t, int, int)); +#ifdef USE_INET6 +extern int count6bits __P((u_32_t *)); +#endif +extern int frrequest __P((ipf_main_softc_t *, int, ioctlcmd_t, caddr_t, + int, int)); extern char *getifname __P((struct ifnet *)); -extern int iplattach __P((void)); -extern int ipldetach __P((void)); +extern int ipfattach __P((ipf_main_softc_t *)); +extern int ipfdetach __P((ipf_main_softc_t *)); extern u_short ipf_cksum __P((u_short *, int)); -extern int copyinptr __P((void *, void *, size_t)); -extern int copyoutptr __P((void *, void *, size_t)); -extern int fr_fastroute __P((mb_t *, mb_t **, fr_info_t *, frdest_t *)); -extern int fr_inobj __P((void *, void *, int)); -extern int fr_inobjsz __P((void *, void *, int, int)); -extern int fr_ioctlswitch __P((int, void *, ioctlcmd_t, int)); -extern int fr_ipftune __P((ioctlcmd_t, void *)); -extern int fr_outobj __P((void *, void *, int)); -extern int fr_outobjsz __P((void *, void *, int, int)); -extern void *fr_pullup __P((mb_t *, fr_info_t *, int)); -extern void fr_resolvedest __P((struct frdest *, int)); -extern int fr_resolvefunc __P((void *)); -extern void *fr_resolvenic __P((char *, int)); -extern int fr_send_icmp_err __P((int, fr_info_t *, int)); -extern int fr_send_reset __P((fr_info_t *)); -#if (__FreeBSD_version < 490000) || !defined(_KERNEL) -extern int ppsratecheck __P((struct timeval *, int *, int)); +extern int copyinptr __P((ipf_main_softc_t *, void *, void *, size_t)); +extern int copyoutptr __P((ipf_main_softc_t *, void *, void *, size_t)); +extern int ipf_fastroute __P((mb_t *, mb_t **, fr_info_t *, frdest_t *)); +extern int ipf_inject __P((fr_info_t *, mb_t *)); +extern int ipf_inobj __P((ipf_main_softc_t *, void *, ipfobj_t *, + void *, int)); +extern int ipf_inobjsz __P((ipf_main_softc_t *, void *, void *, + int , int)); +extern int ipf_ioctlswitch __P((ipf_main_softc_t *, int, void *, + ioctlcmd_t, int, int, void *)); +extern int ipf_ipf_ioctl __P((ipf_main_softc_t *, caddr_t, ioctlcmd_t, + int, int, void *)); +extern int ipf_ipftune __P((ipf_main_softc_t *, ioctlcmd_t, void *)); +extern int ipf_matcharray_load __P((ipf_main_softc_t *, caddr_t, + ipfobj_t *, int **)); +extern int ipf_matcharray_verify __P((int *, int)); +extern int ipf_outobj __P((ipf_main_softc_t *, void *, void *, int)); +extern int ipf_outobjk __P((ipf_main_softc_t *, ipfobj_t *, void *)); +extern int ipf_outobjsz __P((ipf_main_softc_t *, void *, void *, + int, int)); +extern void *ipf_pullup __P((mb_t *, fr_info_t *, int)); +extern int ipf_resolvedest __P((ipf_main_softc_t *, char *, + struct frdest *, int)); +extern int ipf_resolvefunc __P((ipf_main_softc_t *, void *)); +extern void *ipf_resolvenic __P((ipf_main_softc_t *, char *, int)); +extern int ipf_send_icmp_err __P((int, fr_info_t *, int)); +extern int ipf_send_reset __P((fr_info_t *)); +#if (defined(__FreeBSD_version) && (__FreeBSD_version < 501000)) || \ + !defined(_KERNEL) || defined(linux) #endif -extern ipftq_t *fr_addtimeoutqueue __P((ipftq_t **, u_int)); -extern void fr_deletequeueentry __P((ipftqent_t *)); -extern int fr_deletetimeoutqueue __P((ipftq_t *)); -extern void fr_freetimeoutqueue __P((ipftq_t *)); -extern void fr_movequeue __P((ipftqent_t *, ipftq_t *, ipftq_t *)); -extern void fr_queueappend __P((ipftqent_t *, ipftq_t *, void *)); -extern void fr_queueback __P((ipftqent_t *)); -extern void fr_queuefront __P((ipftqent_t *)); -extern void fr_checkv4sum __P((fr_info_t *)); -extern int fr_checkl4sum __P((fr_info_t *)); -extern int fr_ifpfillv4addr __P((int, struct sockaddr_in *, +extern void ipf_apply_timeout __P((ipftq_t *, u_int)); +extern ipftq_t *ipf_addtimeoutqueue __P((ipf_main_softc_t *, ipftq_t **, + u_int)); +extern void ipf_deletequeueentry __P((ipftqent_t *)); +extern int ipf_deletetimeoutqueue __P((ipftq_t *)); +extern void ipf_freetimeoutqueue __P((ipf_main_softc_t *, ipftq_t *)); +extern void ipf_movequeue __P((u_long, ipftqent_t *, ipftq_t *, + ipftq_t *)); +extern void ipf_queueappend __P((u_long, ipftqent_t *, ipftq_t *, void *)); +extern void ipf_queueback __P((u_long, ipftqent_t *)); +extern int ipf_queueflush __P((ipf_main_softc_t *, ipftq_delete_fn_t, + ipftq_t *, ipftq_t *, u_int *, int, int)); +extern void ipf_queuefront __P((ipftqent_t *)); +extern int ipf_settimeout_tcp __P((ipftuneable_t *, ipftuneval_t *, + ipftq_t *)); +extern int ipf_checkv4sum __P((fr_info_t *)); +extern int ipf_checkl4sum __P((fr_info_t *)); +extern int ipf_ifpfillv4addr __P((int, struct sockaddr_in *, struct sockaddr_in *, struct in_addr *, struct in_addr *)); -extern int fr_coalesce __P((fr_info_t *)); +extern int ipf_coalesce __P((fr_info_t *)); #ifdef USE_INET6 -extern void fr_checkv6sum __P((fr_info_t *)); -extern int fr_ifpfillv6addr __P((int, struct sockaddr_in6 *, - struct sockaddr_in6 *, struct in_addr *, - struct in_addr *)); +extern int ipf_checkv6sum __P((fr_info_t *)); +extern int ipf_ifpfillv6addr __P((int, struct sockaddr_in6 *, + struct sockaddr_in6 *, i6addr_t *, + i6addr_t *)); #endif -extern int fr_addipftune __P((ipftuneable_t *)); -extern int fr_delipftune __P((ipftuneable_t *)); - -extern int frflush __P((minor_t, int, int)); -extern void frsync __P((void *)); -extern frgroup_t *fr_addgroup __P((char *, void *, u_32_t, minor_t, int)); -extern int fr_derefrule __P((frentry_t **)); -extern void fr_delgroup __P((char *, minor_t, int)); -extern frgroup_t *fr_findgroup __P((char *, minor_t, int, frgroup_t ***)); - -extern int fr_loginit __P((void)); -extern int ipflog_clear __P((minor_t)); -extern int ipflog_read __P((minor_t, uio_t *)); -extern int ipflog __P((fr_info_t *, u_int)); -extern int ipllog __P((int, fr_info_t *, void **, size_t *, int *, int)); -extern void fr_logunload __P((void)); - -extern frentry_t *fr_acctpkt __P((fr_info_t *, u_32_t *)); -extern int fr_copytolog __P((int, char *, int)); -extern u_short fr_cksum __P((mb_t *, ip_t *, int, void *)); -extern void fr_deinitialise __P((void)); -extern frentry_t *fr_dolog __P((fr_info_t *, u_32_t *)); -extern frentry_t *fr_dstgrpmap __P((fr_info_t *, u_32_t *)); -extern void fr_fixskip __P((frentry_t **, frentry_t *, int)); -extern void fr_forgetifp __P((void *)); -extern frentry_t *fr_getrulen __P((int, char *, u_32_t)); -extern void fr_getstat __P((struct friostat *)); -extern int fr_icmp4errortype __P((int)); -extern int fr_ifpaddr __P((int, int, void *, - struct in_addr *, struct in_addr *)); -extern int fr_initialise __P((void)); -extern void fr_lock __P((caddr_t, int *)); -extern int fr_makefrip __P((int, ip_t *, fr_info_t *)); -extern int fr_matchtag __P((ipftag_t *, ipftag_t *)); -extern int fr_matchicmpqueryreply __P((int, icmpinfo_t *, - struct icmp *, int)); -extern u_32_t fr_newisn __P((fr_info_t *)); -extern u_short fr_nextipid __P((fr_info_t *)); -extern int fr_rulen __P((int, frentry_t *)); -extern int fr_scanlist __P((fr_info_t *, u_32_t)); -extern frentry_t *fr_srcgrpmap __P((fr_info_t *, u_32_t *)); -extern int fr_tcpudpchk __P((fr_info_t *, frtuc_t *)); -extern int fr_verifysrc __P((fr_info_t *fin)); -extern int fr_zerostats __P((char *)); - -extern int fr_running; -extern u_long fr_frouteok[2]; -extern int fr_pass; -extern int fr_flags; -extern int fr_active; -extern int fr_chksrc; -extern int fr_minttl; -extern int fr_refcnt; -extern int fr_control_forwarding; -extern int fr_update_ipid; -extern int nat_logging; -extern int ipstate_logging; -extern int ipl_suppress; -extern int ipl_buffer_sz; -extern int ipl_logmax; -extern int ipl_logall; -extern int ipl_logsize; -extern u_long fr_ticks; -extern fr_info_t frcache[2][8]; +extern int ipf_tune_add __P((ipf_main_softc_t *, ipftuneable_t *)); +extern int ipf_tune_add_array __P((ipf_main_softc_t *, ipftuneable_t *)); +extern int ipf_tune_del __P((ipf_main_softc_t *, ipftuneable_t *)); +extern int ipf_tune_del_array __P((ipf_main_softc_t *, ipftuneable_t *)); +extern int ipf_tune_array_link __P((ipf_main_softc_t *, ipftuneable_t *)); +extern int ipf_tune_array_unlink __P((ipf_main_softc_t *, + ipftuneable_t *)); +extern ipftuneable_t *ipf_tune_array_copy __P((void *, size_t, + ipftuneable_t *)); + +extern int ipf_pr_pullup __P((fr_info_t *, int)); + +extern int ipf_flush __P((ipf_main_softc_t *, minor_t, int)); +extern frgroup_t *ipf_group_add __P((ipf_main_softc_t *, char *, void *, + u_32_t, minor_t, int)); +extern void ipf_group_del __P((ipf_main_softc_t *, frgroup_t *, + frentry_t *)); +extern int ipf_derefrule __P((ipf_main_softc_t *, frentry_t **)); +extern frgroup_t *ipf_findgroup __P((ipf_main_softc_t *, char *, minor_t, + int, frgroup_t ***)); + +extern int ipf_log_init __P((void)); +extern int ipf_log_bytesused __P((ipf_main_softc_t *, int)); +extern int ipf_log_canread __P((ipf_main_softc_t *, int)); +extern int ipf_log_clear __P((ipf_main_softc_t *, minor_t)); +extern u_long ipf_log_failures __P((ipf_main_softc_t *, int)); +extern int ipf_log_read __P((ipf_main_softc_t *, minor_t, uio_t *)); +extern int ipf_log_items __P((ipf_main_softc_t *, int, fr_info_t *, + void **, size_t *, int *, int)); +extern u_long ipf_log_logok __P((ipf_main_softc_t *, int)); +extern void ipf_log_unload __P((ipf_main_softc_t *)); +extern int ipf_log_pkt __P((fr_info_t *, u_int)); +extern int ipf_log_pkt __P((fr_info_t *, u_int)); + +extern frentry_t *ipf_acctpkt __P((fr_info_t *, u_32_t *)); +extern u_short fr_cksum __P((fr_info_t *, ip_t *, int, void *)); +extern void ipf_deinitialise __P((ipf_main_softc_t *)); +extern int ipf_deliverlocal __P((ipf_main_softc_t *, int, void *, + i6addr_t *)); +extern frentry_t *ipf_dstgrpmap __P((fr_info_t *, u_32_t *)); +extern void ipf_fixskip __P((frentry_t **, frentry_t *, int)); +extern void ipf_forgetifp __P((ipf_main_softc_t *, void *)); +extern frentry_t *ipf_getrulen __P((ipf_main_softc_t *, int, char *, + u_32_t)); +extern int ipf_ifpaddr __P((ipf_main_softc_t *, int, int, void *, + i6addr_t *, i6addr_t *)); +extern void ipf_inet_mask_add __P((int, ipf_v4_masktab_t *)); +extern void ipf_inet_mask_del __P((int, ipf_v4_masktab_t *)); +#ifdef USE_INET6 +extern void ipf_inet6_mask_add __P((int, i6addr_t *, + ipf_v6_masktab_t *)); +extern void ipf_inet6_mask_del __P((int, i6addr_t *, + ipf_v6_masktab_t *)); +#endif +extern int ipf_initialise __P((void)); +extern int ipf_lock __P((caddr_t, int *)); +extern int ipf_makefrip __P((int, ip_t *, fr_info_t *)); +extern int ipf_matchtag __P((ipftag_t *, ipftag_t *)); +extern int ipf_matchicmpqueryreply __P((int, icmpinfo_t *, + struct icmp *, int)); +extern u_32_t ipf_newisn __P((fr_info_t *)); +extern u_short ipf_nextipid __P((fr_info_t *)); +extern u_int ipf_pcksum __P((fr_info_t *, int, u_int)); +extern void ipf_rule_expire __P((ipf_main_softc_t *)); +extern int ipf_scanlist __P((fr_info_t *, u_32_t)); +extern frentry_t *ipf_srcgrpmap __P((fr_info_t *, u_32_t *)); +extern int ipf_tcpudpchk __P((fr_ip_t *, frtuc_t *)); +extern int ipf_verifysrc __P((fr_info_t *fin)); +extern int ipf_zerostats __P((ipf_main_softc_t *, char *)); +extern int ipf_getnextrule __P((ipf_main_softc_t *, ipftoken_t *, + void *)); +extern int ipf_sync __P((ipf_main_softc_t *, void *)); +extern int ipf_token_deref __P((ipf_main_softc_t *, ipftoken_t *)); +extern void ipf_token_expire __P((ipf_main_softc_t *)); +extern ipftoken_t *ipf_token_find __P((ipf_main_softc_t *, int, int, + void *)); +extern int ipf_token_del __P((ipf_main_softc_t *, int, int, + void *)); +extern void ipf_token_mark_complete __P((ipftoken_t *)); +extern int ipf_genericiter __P((ipf_main_softc_t *, void *, + int, void *)); +#ifdef IPFILTER_LOOKUP +extern void *ipf_resolvelookup __P((int, u_int, u_int, + lookupfunc_t *)); +#endif +extern u_32_t ipf_random __P((void)); + +extern int ipf_main_load __P((void)); +extern void *ipf_main_soft_create __P((void *)); +extern void ipf_main_soft_destroy __P((ipf_main_softc_t *)); +extern int ipf_main_soft_init __P((ipf_main_softc_t *)); +extern int ipf_main_soft_fini __P((ipf_main_softc_t *)); +extern int ipf_main_unload __P((void)); +extern int ipf_load_all __P((void)); +extern int ipf_unload_all __P((void)); +extern void ipf_destroy_all __P((ipf_main_softc_t *)); +extern ipf_main_softc_t *ipf_create_all __P((void *)); +extern int ipf_init_all __P((ipf_main_softc_t *)); +extern int ipf_fini_all __P((ipf_main_softc_t *)); +extern void ipf_log_soft_destroy __P((ipf_main_softc_t *, void *)); +extern void *ipf_log_soft_create __P((ipf_main_softc_t *)); +extern int ipf_log_soft_init __P((ipf_main_softc_t *, void *)); +extern int ipf_log_soft_fini __P((ipf_main_softc_t *, void *)); +extern int ipf_log_main_load __P((void)); +extern int ipf_log_main_unload __P((void)); + + extern char ipfilter_version[]; -extern iplog_t **iplh[IPL_LOGMAX+1], *iplt[IPL_LOGMAX+1]; -extern int iplused[IPL_LOGMAX + 1]; -extern struct frentry *ipfilter[2][2], *ipacct[2][2]; #ifdef USE_INET6 -extern struct frentry *ipfilter6[2][2], *ipacct6[2][2]; extern int icmptoicmp6types[ICMP_MAXTYPE+1]; extern int icmptoicmp6unreach[ICMP_MAX_UNREACH]; extern int icmpreplytype6[ICMP6_MAXTYPE + 1]; #endif +#ifdef IPFILTER_COMPAT +extern int ipf_in_compat __P((ipf_main_softc_t *, ipfobj_t *, void *,int)); +extern int ipf_out_compat __P((ipf_main_softc_t *, ipfobj_t *, void *)); +#endif extern int icmpreplytype4[ICMP_MAXTYPE + 1]; -extern struct frgroup *ipfgroups[IPL_LOGSIZE][2]; -extern struct filterstats frstats[]; -extern frentry_t *ipfrule_match __P((fr_info_t *)); -extern u_char ipf_iss_secret[32]; -extern ipftuneable_t ipf_tuneables[]; + +extern int ipf_ht_node_add __P((ipf_main_softc_t *, host_track_t *, + int, i6addr_t *)); +extern int ipf_ht_node_del __P((host_track_t *, int, i6addr_t *)); +extern void ipf_rb_ht_flush __P((host_track_t *)); +extern void ipf_rb_ht_freenode __P((host_node_t *, void *)); +extern void ipf_rb_ht_init __P((host_track_t *)); #endif /* __IP_FIL_H__ */ diff --git a/ip_fil_aix.c b/ip_fil_aix.c new file mode 100644 index 0000000000000..b019441b71f60 --- /dev/null +++ b/ip_fil_aix.c @@ -0,0 +1,1706 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ +#define __FULL_PROTO +#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$"; +#endif + +#if defined(KERNEL) || defined(_KERNEL) +# undef KERNEL +# undef _KERNEL +# define KERNEL 1 +# define _KERNEL 1 +#endif +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/types.h> +#include <sys/file.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/systm.h> +#include <sys/dir.h> +#include <sys/mbuf.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/device.h> + +#include <net/if.h> +#include <net/route.h> +#include <netinet/in.h> +#include <netinet/in_var.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/ip_var.h> +#include <netinet/tcp.h> +#include <netinet/tcp_var.h> +#include <netinet/udp.h> +#include <netinet/tcpip.h> +#include <netinet/ip_icmp.h> +#include "netinet/ip_compat.h" +#ifdef USE_INET6 +# include <netinet/icmp6.h> +#endif +#include "netinet/ip_fil.h" +#include "netinet/ip_nat.h" +#include "netinet/ip_frag.h" +#include "netinet/ip_state.h" +#include "netinet/ip_proxy.h" +#include "netinet/ip_auth.h" +#include "netinet/ip_sync.h" +#include "netinet/ip_lookup.h" +#include "netinet/ip_dstlist.h" +#ifdef IPFILTER_SCAN +#include "netinet/ip_scan.h" +#endif +#include "netinet/ip_pool.h" +#ifdef INET +extern int ip_optcopy __P((struct ip *, struct ip *)); +#endif + +/* +ipstat +inbound_fw +nethsque +rw_read_locked +ip_output +netisr_dispatch +ipforwarding +ip_output_post_fw +ipintr_noqueue_post_fw +max_linkhdr +in_localaddr +ip_optcopy +outbound_fw +*/ + + +static u_short ipid = 0; +static int (*fr_savep) __P((ip_t *, int, void *, int, struct mbuf **)); +static int fr_send_ip __P((fr_info_t *, mb_t *)); +#ifdef KMUTEX_T +extern ipfmutex_t ipf_rw; +extern ipfrwlock_t ipf_mutex; +#endif +#ifdef USE_INET6 +static int ipfr_fastroute6 __P((struct mbuf *, struct mbuf **, + fr_info_t *, frdest_t *)); +#endif + +#include <sys/conf.h> +#include <sys/device.h> + +void ipf_check_inbound __P((struct ifnet *, struct mbuf *, inbound_fw_args_t *)); +int ipf_check_outbound __P((struct ifnet *, struct mbuf *, outbound_fw_args_t *)); + +int ipfopen __P((dev_t, u_long, chan_t, int)); +int ipfclose __P((dev_t, chan_t)); +int ipfread __P((dev_t, struct uio *, chan_t, int)); +int ipfwrite __P((dev_t, struct uio *, chan_t, int)); +int ipfioctl __P((dev_t, int, caddr_t, int)); +int ipfconfig __P((dev_t, int, struct uio *)); + +ipfmutex_t ipl_mutex, ipf_auth_mx, ipf_rw, ipf_stinsert; +ipfmutex_t ipf_nat_new, ipf_natio, ipf_timeoutlock; +ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag, ipf_tokens; +ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_authlk; +int ipf_locks_done = 0; + +const struct devsw ipfdevsw = { + ipfopen, /* d_open entry point for open routine */ + ipfclose, /* d_close entry point for close routine */ + ipfread, /* d_read entry point for read routine */ + ipfwrite, /* d_write entry point for write routine */ + ipfioctl, /* d_ioctl entry point for ioctl routine */ + nodev, /* d_strategy entry point for strategy routine */ + NULL, /* d_ttys pointer to tty device structure */ + nodev, /* d_select entry point for select routine */ + ipfconfig, /* d_config entry point for config routine */ + nodev, /* d_print entry point for print routine */ + nodev, /* d_dump entry point for dump routine */ + nodev, /* d_mpx entry point for mpx routine */ + nodev, /* d_revoke entry point for revoke routine */ + NULL, /* d_dsdptr pointer to device specific data */ + 0, /* d_selptr ptr to outstanding select cntl blks */ +#ifdef _IA64 + DEV_MPSAFE | DEV_64BIT +#else + 0 /* d_opts internal device switch control field */ +#endif + +}; + + +int +ipfconfig(devno, cmd, uiop) + dev_t devno; + int cmd; + struct uio *uiop; +{ + int error = EINVAL; + + printf("ipfconfig(%u,%x,%p)\n", devno,cmd,uiop); + + switch (cmd) + { + case CFG_INIT : + error = devswadd(devno, &ipfdevsw); + if (error == 0) { + ipf_load_all(); + ipf_create_all(&ipfmain); + error = ipfattach(&ipfmain); + } + break; + case CFG_TERM : + error = devswdel(devno); + break; + case CFG_QVPD : + error = 0; + break; + default : + return EINVAL; + } + + return 0; +} + + +int +ipfattach(softc) + ipf_main_softc_t *softc; +{ + int s; + + SPL_NET(s); + if ((ipf_running > 0) || (inbound_fw == ipf_check_inbound)) { + printf("IP Filter: already initialized\n"); + SPL_X(s); + return EBUSY; + } + + inbound_fw = ipf_check_inbound; + outbound_fw = ipf_check_outbound; + + if (fr_control_forwarding & 1) + ipforwarding = 1; + + ipid = 0; + + ipf_init_all(softc); + + SPL_X(s); + + return 0; +} + + +/* + * Disable the filter by removing the hooks from the IP input/output + * stream. + */ +int +ipfdetach(softc) + ipf_main_softc_t *softc; +{ + int s; + + SPL_NET(s); + + inbound_fw = NULL; + outbound_fw = NULL; + (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE|FR_INACTIVE); + (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE); + + if (fr_control_forwarding & 2) + ipforwarding = 0; + + ipf_fini_all(softc); + + SPL_X(s); + return 0; +} + + +/* + * explicit inbound hook to call ipf_check from + */ +void +ipf_check_inbound(ifp, m, args) + struct ifnet *ifp; + struct mbuf *m; + inbound_fw_args_t *args; +{ + ip_t *ip; + + if (ipf_check_mbuf(&m) == -1) { + if (m != NULL) { + FREE_MB_T(m); + } + return; + } + + ip = mtod(m, ip_t *); + + switch (ipf_check(ip, ip->ip_hl << 2, ifp, 0, &m)) + { + case 0 : + ipintr_noqueue_post_fw(ifp, m, args); + break; + default : + if (m != NULL) { + FREE_MB_T(m); + } + break; + } + + return; +} + + +/* + * explicit outbound hook to call ipf_check from + */ +int +ipf_check_outbound(ifp, m, args) + struct ifnet *ifp; + struct mbuf *m; + outbound_fw_args_t *args; +{ + ip_t *ip; + + if (ipf_check_mbuf(&m) == -1) { + if (m != NULL) { + FREE_MB_T(m); + } + return 1; /* FIREWALL_NOTOK */ + } + + ip = mtod(m, ip_t *); + + switch (ipf_check(ip, ip->ip_hl << 2, ifp, 1, &m)) + { + case 0 : + ip_output_post_fw(ifp, m, args); + return 0; /* FIREWALL_OK */ + default : + break; + } + + if (m != NULL) { + FREE_MB_T(m); + } + return 1; /* FIREWALL_NOTOK */ +} + +int +ipf_check_mbuf(mp) + struct mbuf **mp; +{ + struct mbuf *m, *m0; + int i, hlen; + ip_t *ip; + + m = *mp; + + if ((m->m_len < sizeof (struct ip)) && + (m = m_pullup(m, sizeof (struct ip))) == 0) { + *mp = m; + ipstat.ips_toosmall++; + return -1; + } + ip = mtod(m, struct ip *); + + switch (ip->ip_v) + { + case 4 : + hlen = ip->ip_hl << 2; + if (hlen < sizeof(struct ip)) { /* minimum header length */ + ipstat.ips_badhlen++; + return -1; + } + if ((hlen > sizeof(struct ip)) && (hlen > m->m_len)) { + if ((m = m_pullup(m, hlen)) == 0) { + *mp = m; + ipstat.ips_badhlen++; + return -2; + } + ip = mtod(m, struct ip *); + } + if (ip->ip_sum = in_cksum(m, hlen)) { + ipstat.ips_badsum++; + return -1; + } + + /* + * Convert fields to host representation. + * XXX - no need for NTOHS on big endian (sparc) + */ + NTOHS(ip->ip_len); + if (ip->ip_len < hlen) { + ipstat.ips_badlen++; + return -1; + } + NTOHS(ip->ip_id); + NTOHS(ip->ip_off); + + /* + * Check that the amount of data in the buffers + * is as at least much as the IP header would have us expect. + * Trim mbufs if longer than we expect. + * Drop packet if shorter than we expect. + */ + i = -(u_short)ip->ip_len; + m0 = m; + for (;;) { + i += m->m_len; + if (m->m_next == 0) + break; + m = m->m_next; + } + if (i != 0) { + if (i < 0) { + ipstat.ips_tooshort++; + m = m0; + return -1; + } + if (i <= m->m_len) + m->m_len -= i; + else + m_adj(m0, -i); + } + break; +#ifdef USE_INET6 + case 6 : + break; +#endif + default : + return -1; + } + return 0; +} + + +/* + * Filter ioctl interface. + */ +int +ipfioctl(dev, cmd, data, mode) + dev_t dev; + int cmd; + caddr_t data; + int mode; +{ + int error = 0, unit = 0; + SPL_INT(s); + + unit = GET_MINOR(dev); + if ((IPL_LOGMAX < unit) || (unit < 0)) { + ipfmain.ipf_interror = 130002; + return ENXIO; + } + + if (ipf_running <= 0) { + if (unit != IPL_LOGIPF && cmd != SIOCIPFINTERROR) { + ipfmain.ipf_interror = 130003; + return EIO; + } + if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET && + cmd != SIOCIPFSET && cmd != SIOCFRENB && + cmd != SIOCGETFS && cmd != SIOCGETFF && + cmd != SIOCIPFINTERROR) { + ipfmain.ipf_interror = 130004; + return EIO; + } + } + + SPL_NET(s); + + error = ipf_ioctlswitch(unit, data, cmd, mode, curproc->p_uid, curproc); + if (error != -1) { + SPL_X(s); + return error; + } + + SPL_X(s); + return error; +} + + +/* + * routines below for saving IP headers to buffer + */ +int +ipfopen(dev_t dev, u_long flags, chan_t chan, int ext) +{ + u_int unit = GET_MINOR(dev); + int error; + + if (IPL_LOGMAX < unit) + error = ENXIO; + else { + switch (unit) + { + case IPL_LOGIPF : + case IPL_LOGNAT : + case IPL_LOGSTATE : + case IPL_LOGAUTH : + case IPL_LOGLOOKUP : + case IPL_LOGSYNC : +#ifdef IPFILTER_SCAN + case IPL_LOGSCAN : +#endif + error = 0; + break; + default : + error = ENXIO; + break; + } + } + return error; +} + + +int +ipfclose(dev_t dev, chan_t chan) +{ + u_int unit = GET_MINOR(dev); + + if (IPL_LOGMAX < unit) + unit = ENXIO; + else + unit = 0; + return unit; +} + +/* + * ipfread/ipllog + * both of these must operate with at least splnet() lest they be + * called during packet processing and cause an inconsistancy to appear in + * the filter lists. + */ +int +ipfread(dev_t dev, struct uio *uio, chan_t chan, int ext) +{ + + if (ipf_running < 1) { + ipfmain.ipf_interror = 130006; + return EIO; + } + + if (GET_MINOR(dev) == IPL_LOGSYNC) + return ipfsync_read(uio); + +#ifdef IPFILTER_LOG + return ipflog_read(GET_MINOR(dev), uio); +#else + ipfmain.ipf_interror = 130007; + return ENXIO; +#endif +} + + +/* + * ipfwrite + * both of these must operate with at least splnet() lest they be + * called during packet processing and cause an inconsistancy to appear in + * the filter lists. + */ +int +ipfwrite(dev_t dev, struct uio *uio, chan_t chan, int ext) +{ + + if (GET_MINOR(dev) == IPL_LOGSYNC) + return ipfsync_write(uio); + ipfmain.ipf_interror = 130009; + return ENXIO; +} + + +/* + * ipf_send_reset - this could conceivably be a call to tcp_respond(), but that + * requires a large amount of setting up and isn't any more efficient. + */ +int +ipf_send_reset(fin) + fr_info_t *fin; +{ + struct tcphdr *tcp, *tcp2; + int tlen = 0, hlen; + struct mbuf *m; +#ifdef USE_INET6 + ip6_t *ip6; +#endif + ip_t *ip; + + tcp = fin->fin_dp; + if (tcp->th_flags & TH_RST) + return -1; /* feedback loop */ + + if (ipf_checkl4sum(fin) == -1) + return -1; + + tlen = fin->fin_dlen - (TCP_OFF(tcp) << 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 + hlen = sizeof(ip_t); +#endif +#ifdef MGETHDR + MGETHDR(m, M_DONTWAIT, MT_HEADER); +#else + MGET(m, M_DONTWAIT, MT_HEADER); +#endif + if (m == NULL) + return -1; + if (sizeof(*tcp2) + hlen > MHLEN) { + MCLGET(m, M_DONTWAIT); + if (m == NULL) + return -1; + if ((m->m_flags & M_EXT) == 0) { + FREE_MB_T(m); + return -1; + } + } + + m->m_len = sizeof(*tcp2) + hlen; + m->m_data += max_linkhdr; + m->m_pkthdr.len = m->m_len; + m->m_pkthdr.rcvif = (struct ifnet *)0; + ip = mtod(m, struct ip *); + bzero((char *)ip, hlen); +#ifdef USE_INET6 + ip6 = (ip6_t *)ip; +#endif + bzero((char *)ip, sizeof(*tcp2) + hlen); + tcp2 = (struct tcphdr *)((char *)ip + hlen); + tcp2->th_sport = tcp->th_dport; + tcp2->th_dport = tcp->th_sport; + + if (tcp->th_flags & TH_ACK) { + tcp2->th_seq = tcp->th_ack; + tcp2->th_flags = TH_RST; + tcp2->th_ack = 0; + } else { + tcp2->th_seq = 0; + 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_x2 = 0; + TCP_OFF_A(tcp2, sizeof(*tcp2) >> 2); + tcp2->th_win = tcp->th_win; + tcp2->th_sum = 0; + tcp2->th_urp = 0; + +#ifdef USE_INET6 + if (fin->fin_v == 6) { + ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; + ip6->ip6_plen = htons(sizeof(struct tcphdr)); + ip6->ip6_nxt = IPPROTO_TCP; + ip6->ip6_hlim = 0; + ip6->ip6_src = fin->fin_dst6; + ip6->ip6_dst = fin->fin_src6; + tcp2->th_sum = in6_cksum(m, IPPROTO_TCP, + sizeof(*ip6), sizeof(*tcp2)); + return ipf_send_ip(fin, m); + } +#endif +#ifdef INET + ip->ip_p = IPPROTO_TCP; + ip->ip_len = htons(sizeof(struct tcphdr)); + ip->ip_src.s_addr = fin->fin_daddr; + ip->ip_dst.s_addr = fin->fin_saddr; + tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2)); + ip->ip_len = hlen + sizeof(*tcp2); + return ipf_send_ip(fin, m); +#else + return 0; +#endif +} + + +static int +ipf_send_ip(fin, m) + fr_info_t *fin; + mb_t *m; +{ + fr_info_t fnew; +#ifdef INET + ip_t *oip; +#endif + ip_t *ip; + int hlen; + + ip = mtod(m, ip_t *); + bzero((char *)&fnew, sizeof(fnew)); + fnew.fin_main_soft = fin->fin_main_soft; + + IP_V_A(ip, fin->fin_v); + switch (fin->fin_v) + { +#ifdef INET + case 4 : + oip = fin->fin_ip; + hlen = sizeof(*oip); + fnew.fin_v = 4; + fnew.fin_p = ip->ip_p; + fnew.fin_plen = ntohs(ip->ip_len); + IP_HL_A(ip, sizeof(*oip) >> 2); + ip->ip_tos = oip->ip_tos; + ip->ip_id = ipf_nextipid(fin); + ip->ip_off = 0; + ip->ip_ttl = IPDEFTTL; + ip->ip_sum = 0; + break; +#endif +#ifdef USE_INET6 + case 6 : + { + ip6_t *ip6 = (ip6_t *)ip; + + ip6->ip6_vfc = 0x60; + ip6->ip6_hlim = IPDEFTTL; + + hlen = sizeof(*ip6); + fnew.fin_p = ip6->ip6_nxt; + fnew.fin_v = 6; + fnew.fin_plen = ntohs(ip6->ip6_plen) + hlen; + break; + } +#endif + default : + return EINVAL; + } +#ifdef IPSEC + m->m_pkthdr.rcvif = NULL; +#endif + + fnew.fin_ifp = fin->fin_ifp; + fnew.fin_flx = FI_NOCKSUM; + fnew.fin_m = m; + fnew.fin_ip = ip; + fnew.fin_mp = &m; + fnew.fin_hlen = hlen; + fnew.fin_dp = (char *)ip + hlen; + (void) ipf_makefrip(hlen, ip, &fnew); + + return ipf_fastroute(m, &m, &fnew, NULL); +} + + +int +ipf_send_icmp_err(type, fin, dst) + int type; + fr_info_t *fin; + int dst; +{ + int err, hlen, xtra, iclen, ohlen, avail, code; + struct in_addr dst4; + struct icmp *icmp; + struct mbuf *m; + void *ifp; +#ifdef USE_INET6 + ip6_t *ip6; + struct in6_addr dst6; +#endif + ip_t *ip, *ip2; + + if ((type < 0) || (type > ICMP_MAXTYPE)) + return -1; + + code = fin->fin_icode; +#ifdef USE_INET6 + if ((code < 0) || (code > sizeof(icmptoicmp6unreach)/sizeof(int))) + return -1; +#endif + + if (ipf_checkl4sum(fin) == -1) + return -1; +#ifdef MGETHDR + MGETHDR(m, M_DONTWAIT, MT_HEADER); +#else + MGET(m, M_DONTWAIT, MT_HEADER); +#endif + if (m == NULL) + return -1; + avail = MHLEN; + + xtra = 0; + hlen = 0; + ohlen = 0; + ifp = fin->fin_ifp; + if (fin->fin_v == 4) { + if ((fin->fin_p == IPPROTO_ICMP) && !(fin->fin_flx & FI_SHORT)) + switch (ntohs(fin->fin_data[0]) >> 8) + { + case ICMP_ECHO : + case ICMP_TSTAMP : + case ICMP_IREQ : + case ICMP_MASKREQ : + break; + default : + FREE_MB_T(m); + return 0; + } + + if (dst == 0) { + if (fr_ifpaddr(softc, 4, FRI_NORMAL, ifp, + &dst4, NULL) == -1) { + FREE_MB_T(m); + return -1; + } + } else + dst4.s_addr = fin->fin_daddr; + + hlen = sizeof(ip_t); + ohlen = fin->fin_hlen; + if (fin->fin_hlen < fin->fin_plen) + xtra = MIN(fin->fin_dlen, 8); + else + xtra = 0; + } + +#ifdef USE_INET6 + else if (fin->fin_v == 6) { + hlen = sizeof(ip6_t); + ohlen = sizeof(ip6_t); + type = icmptoicmp6types[type]; + if (type == ICMP6_DST_UNREACH) + code = icmptoicmp6unreach[code]; + + if (hlen + sizeof(*icmp) + max_linkhdr + + fin->fin_plen > avail) { + MCLGET(m, M_DONTWAIT); + if (m == NULL) + return -1; + if ((m->m_flags & M_EXT) == 0) { + FREE_MB_T(m); + return -1; + } + avail = MCLBYTES; + } + xtra = MIN(fin->fin_plen, + avail - hlen - sizeof(*icmp) - max_linkhdr); + if (dst == 0) { + if (fr_ifpaddr(softc, 6, FRI_NORMAL, ifp, + (struct in_addr *)&dst6, NULL) == -1) { + FREE_MB_T(m); + return -1; + } + } else + dst6 = fin->fin_dst6; + } +#endif + else { + FREE_MB_T(m); + return -1; + } + + iclen = hlen + sizeof(*icmp); + avail -= (max_linkhdr + iclen); + if (avail < 0) { + FREE_MB_T(m); + return -1; + } + if (xtra > avail) + xtra = avail; + iclen += xtra; + m->m_data += max_linkhdr; + m->m_pkthdr.rcvif = (struct ifnet *)0; + m->m_pkthdr.len = iclen; + m->m_len = iclen; + ip = mtod(m, ip_t *); + icmp = (struct icmp *)((char *)ip + hlen); + ip2 = (ip_t *)&icmp->icmp_ip; + + 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) { + if (fin->fin_mtu != 0) { + icmp->icmp_nextmtu = htons(fin->fin_mtu); + + } else if (ifp != NULL) { + icmp->icmp_nextmtu = htons(GETIFMTU_4(ifp)); + + } else { /* make up a number... */ + icmp->icmp_nextmtu = htons(fin->fin_plen - 20); + } + } +#endif + + bcopy((char *)fin->fin_ip, (char *)ip2, ohlen); + +#if defined(M_CSUM_IPv4) + /* + * Clear any in-bound checksum flags for this packet. + */ + m->m_pkthdr.csuminfo = 0; +#endif /* __NetBSD__ && M_CSUM_IPv4 */ + +#ifdef USE_INET6 + ip6 = (ip6_t *)ip; + if (fin->fin_v == 6) { + ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; + ip6->ip6_plen = htons(iclen - hlen); + ip6->ip6_nxt = IPPROTO_ICMPV6; + ip6->ip6_hlim = 0; + ip6->ip6_src = dst6; + ip6->ip6_dst = fin->fin_src6; + if (xtra > 0) + bcopy((char *)fin->fin_ip + ohlen, + (char *)&icmp->icmp_ip + ohlen, xtra); + icmp->icmp_cksum = in6_cksum(m, IPPROTO_ICMPV6, + sizeof(*ip6), iclen - hlen); + } else +#endif + { + ip2->ip_len = htons(ip2->ip_len); + ip2->ip_off = htons(ip2->ip_off); + ip->ip_p = IPPROTO_ICMP; + ip->ip_src.s_addr = dst4.s_addr; + ip->ip_dst.s_addr = fin->fin_saddr; + + if (xtra > 0) + bcopy((char *)fin->fin_ip + ohlen, + (char *)&icmp->icmp_ip + ohlen, xtra); + icmp->icmp_cksum = ipf_cksum((u_short *)icmp, + sizeof(*icmp) + 8); + ip->ip_len = iclen; + ip->ip_p = IPPROTO_ICMP; + } + err = ipf_send_ip(fin, m); + return err; +} + + +/* + * m0 - pointer to mbuf where the IP packet starts + * mpp - pointer to the mbuf pointer that is the start of the mbuf chain + */ +int +ipf_fastroute(m0, mpp, fin, fdp) + mb_t *m0, **mpp; + fr_info_t *fin; + frdest_t *fdp; +{ + register struct ip *ip, *mhip; + register struct mbuf *m = *mpp; + register struct route *ro; + int len, off, error = 0, hlen, code; + struct ifnet *ifp, *sifp; + struct sockaddr_in *dst; + struct route iproute; + u_short ip_off; + frdest_t node; + frentry_t *fr; + + if (fin->fin_v == 6) { +#ifdef USE_INET6 + error = ipfr_fastroute6(m0, mpp, fin, fdp); +#else + error = EPROTONOSUPPORT; +#endif + if ((error != 0) && (*mpp != NULL)) { + FREE_MB_T(*mpp); + } + return error; + } +#ifndef INET + FREE_MB_T(*mpp); + return EPROTONOSUPPORT; +#else + + hlen = fin->fin_hlen; + ip = mtod(m0, struct ip *); + +# if defined(M_CSUM_IPv4) + /* + * Clear any in-bound checksum flags for this packet. + */ + m0->m_pkthdr.csuminfo = 0; +# endif /* __NetBSD__ && M_CSUM_IPv4 */ + + /* + * Route packet. + */ + ro = &iproute; + bzero((caddr_t)ro, sizeof (*ro)); + dst = (struct sockaddr_in *)&ro->ro_dst; + dst->sin_family = AF_INET; + dst->sin_addr = ip->ip_dst; + ifp = NULL; + + fr = fin->fin_fr; + if ((fr == NULL) || !(fr->fr_flags & FR_FASTROUTE))) { + error = -2; + goto bad; + } + if ((fr != NULL) && !(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) && + (fdp->fd_type == FRD_DSTLIST)) { + if (ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node) == 0) + fdp = &node; + } + if (fdp != NULL) + ifp = fdp->fd_ptr; + else + ifp = fin->fin_ifp; + + if (ifp == NULL) { + error = -2; + goto bad; + } + + if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0)) + dst->sin_addr = fdp->fd_ip; + + dst->sin_len = sizeof(*dst); + rtalloc(ro); + + if ((ifp == NULL) && (ro->ro_rt != NULL)) + ifp = ro->ro_rt->rt_ifp; + + if ((ro->ro_rt == NULL) || (ifp == NULL)) { + if (in_localaddr(ip->ip_dst)) + error = EHOSTUNREACH; + else + error = ENETUNREACH; + goto bad; + } + if (ro->ro_rt->rt_flags & RTF_GATEWAY) + dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway; + if (ro->ro_rt) + ro->ro_rt->rt_use++; + + /* + * For input packets which are being "fastrouted", they won't + * go back through output filtering and miss their chance to get + * NAT'd and counted. Duplicated packets aren't considered to be + * part of the normal packet stream, so do not NAT them or pass + * them through stateful checking, etc. + */ + if ((fdp != &fr->fr_dif) && (fin->fin_out == 0)) { + sifp = fin->fin_ifp; + fin->fin_ifp = ifp; + fin->fin_out = 1; + (void) ipf_acctpkt(fin, NULL); + fin->fin_fr = NULL; + if (!fr || !(fr->fr_flags & FR_RETMASK)) { + u_32_t pass; + + (void) ipf_state_check(fin, &pass); + } + + switch (ipf_nat_checkout(fin, NULL)) + { + case 0 : + break; + case 1 : + ip->ip_sum = 0; + break; + case -1 : + error = -1; + goto bad; + break; + } + + fin->fin_ifp = sifp; + fin->fin_out = 0; + } else + ip->ip_sum = 0; + /* + * If small enough for interface, can just send directly. + */ + if (ip->ip_len <= ifp->if_mtu) { + int i = 0; + + if (m->m_flags & M_EXT) + i = 1; + + ip->ip_len = htons(ip->ip_len); + ip->ip_off = htons(ip->ip_off); +# if defined(M_CSUM_IPv4) +# if (__NetBSD_Version__ >= 105009999) + if (ifp->if_csum_flags_tx & M_CSUM_IPv4) + m->m_pkthdr.csuminfo |= M_CSUM_IPv4; +# else + if (ifp->if_capabilities & IFCAP_CSUM_IPv4) + m->m_pkthdr.csuminfo |= M_CSUM_IPv4; +# endif /* (__NetBSD_Version__ >= 105009999) */ + else if (ip->ip_sum == 0) + ip->ip_sum = in_cksum(m, hlen); +# else + if (!ip->ip_sum) + ip->ip_sum = in_cksum(m, hlen); +# endif /* M_CSUM_IPv4 */ + error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, + ro->ro_rt); + if (i) { + ip->ip_len = ntohs(ip->ip_len); + ip->ip_off = ntohs(ip->ip_off); + } + goto done; + } + + /* + * Too large for interface; fragment if possible. + * Must be able to put at least 8 bytes per fragment. + */ + ip_off = ip->ip_off; + if (ip_off & IP_DF) { + error = EMSGSIZE; + goto bad; + } + len = (ifp->if_mtu - hlen) &~ 7; + if (len < 8) { + error = EMSGSIZE; + goto bad; + } + + { + int mhlen, firstlen = len; + struct mbuf **mnext = &m->m_act; + + /* + * Loop through length of segment after first fragment, + * make new header and copy data of each part and link onto chain. + */ + m0 = m; + mhlen = sizeof (struct ip); + for (off = hlen + len; off < ip->ip_len; off += len) { +# ifdef MGETHDR + MGETHDR(m, M_DONTWAIT, MT_HEADER); +# else + MGET(m, M_DONTWAIT, MT_HEADER); +# endif + if (m == 0) { + m = m0; + error = ENOBUFS; + goto bad; + } + m->m_data += max_linkhdr; + mhip = mtod(m, struct ip *); + bcopy((char *)ip, (char *)mhip, sizeof(*ip)); + if (hlen > sizeof (struct ip)) { + mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); + IP_HL_A(mhip, mhlen >> 2); + } + m->m_len = mhlen; + mhip->ip_off = ((off - hlen) >> 3) + ip_off; + if (off + len >= ip->ip_len) + len = ip->ip_len - off; + else + mhip->ip_off |= IP_MF; + mhip->ip_len = htons((u_short)(len + mhlen)); + m->m_next = m_copy(m0, off, len); + if (m->m_next == 0) { + error = ENOBUFS; /* ??? */ + goto sendorfree; + } + m->m_pkthdr.len = mhlen + len; + m->m_pkthdr.rcvif = NULL; + mhip->ip_off = htons((u_short)mhip->ip_off); + mhip->ip_sum = 0; + mhip->ip_sum = in_cksum(m, mhlen); + *mnext = m; + mnext = &m->m_act; + } + /* + * Update first fragment by trimming what's been copied out + * and updating header, then send each fragment (in order). + */ + m_adj(m0, hlen + firstlen - ip->ip_len); + ip->ip_len = htons((u_short)(hlen + firstlen)); + ip->ip_off = htons((u_short)IP_MF); + ip->ip_sum = 0; + ip->ip_sum = in_cksum(m0, hlen); +sendorfree: + for (m = m0; m; m = m0) { + m0 = m->m_act; + m->m_act = 0; + if (error == 0) + error = (*ifp->if_output)(ifp, m, + (struct sockaddr *)dst, ro->ro_rt); + else + FREE_MB_T(m); + } + } +done: + if (!error) + ipf_frouteok[0]++; + else + ipf_frouteok[1]++; + + if (ro->ro_rt) { + RTFREE(ro->ro_rt); + } + return error; +bad: + if (error == EMSGSIZE) { + sifp = fin->fin_ifp; + code = fin->fin_icode; + fin->fin_icode = ICMP_UNREACH_NEEDFRAG; + fin->fin_ifp = ifp; + (void) ipf_send_icmp_err(ICMP_UNREACH, fin, 1); + fin->fin_ifp = sifp; + fin->fin_icode = code; + } + FREE_MB_T(m); + goto done; +#endif /* INET */ +} + + +#if defined(USE_INET6) +/* + * This is the IPv6 specific fastroute code. It doesn't clean up the mbuf's + * or ensure that it is an IPv6 packet that is being forwarded, those are + * expected to be done by the called (ipf_fastroute). + */ +static int +ipf_fastroute6(m0, mpp, fin, fdp) + struct mbuf *m0, **mpp; + fr_info_t *fin; + frdest_t *fdp; +{ + struct route_in6 ip6route; + struct sockaddr_in6 *dst6; + struct route_in6 *ro; + struct rtentry *rt; + struct ifnet *ifp; + frentry_t *fr; + u_long mtu; + int error; + + ro = &ip6route; + fr = fin->fin_fr; + bzero((caddr_t)ro, sizeof(*ro)); + dst6 = (struct sockaddr_in6 *)&ro->ro_dst; + dst6->sin6_family = AF_INET6; + dst6->sin6_len = sizeof(struct sockaddr_in6); + dst6->sin6_addr = fin->fin_fi.fi_dst.in6; + + if (fdp != NULL) + ifp = fdp->fd_ifp; + else + ifp = fin->fin_ifp; + + if (fdp != NULL) { + if (IP6_NOTZERO(&fdp->fd_ip6)) + dst6->sin6_addr = fdp->fd_ip6.in6; + } + + rtalloc((struct route *)ro); + + if ((ifp == NULL) && (ro->ro_rt != NULL)) + ifp = ro->ro_rt->rt_ifp; + + if ((ro->ro_rt == NULL) || (ifp == NULL)) { + error = EHOSTUNREACH; + goto bad; + } + + rt = fdp ? NULL : ro->ro_rt; + + /* KAME */ + if (IN6_IS_ADDR_LINKLOCAL(&dst6->sin6_addr)) + dst6->sin6_addr.s6_addr16[1] = htons(ifp->if_index); + + { + if (ro->ro_rt->rt_flags & RTF_GATEWAY) + dst6 = (struct sockaddr_in6 *)ro->ro_rt->rt_gateway; + ro->ro_rt->rt_use++; + + error = ip6_getpmtu(ro, ro, ifp, &finaldst, &mtu, &frag); + if ((error == 0) && (m0->m_pkthdr.len <= mtu)) { + error = nd6_output(ifp, ifp, *mpp, dst6, rt); + } else { + error = EMSGSIZE; + } + } +bad: + if (ro->ro_rt != NULL) { + RTFREE(ro->ro_rt); + } + return error; +} +#endif + + +int +ipf_verifysrc(fin) + fr_info_t *fin; +{ + struct sockaddr_in *dst; + struct route iproute; + + bzero((char *)&iproute, sizeof(iproute)); + dst = (struct sockaddr_in *)&iproute.ro_dst; + dst->sin_len = sizeof(*dst); + dst->sin_family = AF_INET; + dst->sin_addr = fin->fin_src; + rtalloc(&iproute); + if (iproute.ro_rt == NULL) + return 0; + return (fin->fin_ifp == iproute.ro_rt->rt_ifp); +} + + +/* + * return the first IP Address associated with an interface + */ +int +ipf_ifpaddr(softc, v, atype, ifptr, inp, inpmask) + ipf_main_softc_t *softc; + int v, atype; + void *ifptr; + struct in_addr *inp, *inpmask; +{ +#ifdef USE_INET6 + struct in6_addr *inp6 = NULL; +#endif + struct sockaddr *sock, *mask; + struct sockaddr_in *sin; + struct ifaddr *ifa; + struct ifnet *ifp; + + if ((ifptr == NULL) || (ifptr == (void *)-1)) + return -1; + + ifp = ifptr; + mask = NULL; + + if (v == 4) + inp->s_addr = 0; +#ifdef USE_INET6 + else if (v == 6) + bzero((char *)inp, sizeof(struct in6_addr)); +#endif + + ifa = ifp->if_addrlist; + sock = ifa->ifa_addr; + while (sock != NULL && ifa != NULL) { + sin = (struct sockaddr_in *)sock; + if ((v == 4) && (sin->sin_family == AF_INET)) + break; +#ifdef USE_INET6 + if ((v == 6) && (sin->sin_family == AF_INET6)) { + inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr; + if (!IN6_IS_ADDR_LINKLOCAL(inp6) && + !IN6_IS_ADDR_LOOPBACK(inp6)) + break; + } +#endif + ifa = ifa->ifa_next; + if (ifa != NULL) + sock = ifa->ifa_addr; + } + if (ifa == NULL || sock == NULL) + return -1; + + mask = ifa->ifa_netmask; + if (atype == FRI_BROADCAST) + sock = ifa->ifa_broadaddr; + else if (atype == FRI_PEERADDR) + sock = ifa->ifa_dstaddr; + +#ifdef USE_INET6 + if (v == 6) + return ipf_ifpfillv6addr(atype, (struct sockaddr_in6 *)sock, + (struct sockaddr_in6 *)mask, + inp, inpmask); +#endif + return ipf_ifpfillv4addr(atype, (struct sockaddr_in *)sock, + (struct sockaddr_in *)mask, inp, inpmask); +} + + +u_32_t +ipf_newisn(fin) + fr_info_t *fin; +{ + u_32_t newiss; +#if 0 + static int iss_seq_off = 0; + u_char hash[16]; + MD5_CTX ctx; + + /* + * Compute the base value of the ISS. It is a hash + * of (saddr, sport, daddr, dport, secret). + */ + MD5Init(&ctx); + + MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, + sizeof(fin->fin_fi.fi_src)); + MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, + sizeof(fin->fin_fi.fi_dst)); + MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); + + MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); + + MD5Final(hash, &ctx); + + memcpy(&newiss, hash, sizeof(newiss)); + + /* + * Now increment our "timer", and add it in to + * the computed value. + * + * XXX Use `addin'? + * XXX TCP_ISSINCR too large to use? + */ + iss_seq_off += 0x00010000; + newiss += iss_seq_off; +#endif + return newiss; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nextipid */ +/* Returns: int - 0 == success, -1 == error (packet should be droppped) */ +/* Parameters: fin(I) - pointer to packet information */ +/* */ +/* Returns the next IPv4 ID to use for this packet. */ +/* ------------------------------------------------------------------------ */ +u_short +ipf_nextipid(fin) + fr_info_t *fin; +{ + u_short id; + + MUTEX_ENTER(&ipf_rw); + id = ipid++; + MUTEX_EXIT(&ipf_rw); + + return id; +} + + +INLINE int +ipf_checkv4sum(fin) + fr_info_t *fin; +{ +#ifdef M_CSUM_TCP_UDP_BAD + int manual, pflag, cflags, active; + mb_t *m; + + if ((fin->fin_flx & FI_NOCKSUM) != 0) + return 0; + + if ((fin->fin_flx & FI_SHORT) != 0) + return 1; + + if (fin->fin_cksum != FI_CK_NEEDED) + return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; + + manual = 0; + m = fin->fin_m; + if (m == NULL) { + manual = 1; + goto skipauto; + } + + switch (fin->fin_p) + { + case IPPROTO_UDP : + pflag = M_CSUM_UDPv4; + break; + case IPPROTO_TCP : + pflag = M_CSUM_TCPv4; + break; + default : + pflag = 0; + manual = 1; + break; + } + + active = ((struct ifnet *)fin->fin_ifp)->if_csum_flags_rx & pflag; + active |= M_CSUM_TCP_UDP_BAD | M_CSUM_DATA; + cflags = m->m_pkthdr.csum_flags & active; + + if (pflag != 0) { + if (cflags == (pflag | M_CSUM_TCP_UDP_BAD)) { + fin->fin_flx |= FI_BAD; + fin->fin_cksum = FI_CK_BAD; + } else if (cflags == (pflag | M_CSUM_DATA)) { + if ((m->m_pkthdr.csum_data ^ 0xffff) != 0) { + fin->fin_flx |= FI_BAD; + fin->fin_cksum = FI_CK_BAD; + } else { + fin->fin_cksum = FI_CK_SUMOK; + } + } else if (cflags == pflag) { + fin->fin_cksum = FI_CK_SUMOK; + } else { + manual = 1; + } + } +skipauto: + if (manual != 0) { + if (ipf_checkl4sum(fin) == -1) { + fin->fin_flx |= FI_BAD; + return -1; + } + } +#else + if (ipf_checkl4sum(fin) == -1) { + fin->fin_flx |= FI_BAD; + return -1; + } +#endif + return 0; +} + + +#ifdef USE_INET6 +INLINE int +ipf_checkv6sum(fin) + fr_info_t *fin; +{ +# ifdef M_CSUM_TCP_UDP_BAD + int manual, pflag, cflags, active; + mb_t *m; + + if ((fin->fin_flx & FI_NOCKSUM) != 0) + return 0; + + if ((fin->fin_flx & FI_SHORT) != 0) + return 1; + + if (fin->fin_cksum != FI_CK_NEEDED) + return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; + + + manual = 0; + m = fin->fin_m; + + switch (fin->fin_p) + { + case IPPROTO_UDP : + pflag = M_CSUM_UDPv6; + break; + case IPPROTO_TCP : + pflag = M_CSUM_TCPv6; + break; + default : + pflag = 0; + manual = 1; + break; + } + + active = ((struct ifnet *)fin->fin_ifp)->if_csum_flags_rx & pflag; + active |= M_CSUM_TCP_UDP_BAD | M_CSUM_DATA; + cflags = m->m_pkthdr.csum_flags & active; + + if (pflag != 0) { + if (cflags == (pflag | M_CSUM_TCP_UDP_BAD)) { + fin->fin_flx |= FI_BAD; + fin->fin_cksum = FI_CK_BAD; + } else if (cflags == (pflag | M_CSUM_DATA)) { + if ((m->m_pkthdr.csum_data ^ 0xffff) != 0) { + fin->fin_flx |= FI_BAD; + fin->fin_cksum = FI_CK_BAD; + } else { + fin->fin_cksum = FI_CK_SUMOK; + } + } else if (cflags == pflag) { + fin->fin_cksum = FI_CK_SUMOK; + } else { + manual = 1; + } + } + if (manual != 0) + if (ipf_checkl4sum(fin) == -1) { + fin->fin_flx |= FI_BAD; + return -1; + } +# else + if (ipf_checkl4sum(fin) == -1) { + fin->fin_flx |= FI_BAD; + return -1; + } +# endif + return 0; +} +#endif /* USE_INET6 */ + + +size_t mbufchainlen(m0) + struct mbuf *m0; +{ + size_t len; + + if ((m0->m_flags & M_PKTHDR) != 0) { + len = m0->m_pkthdr.len; + } else { + struct mbuf *m; + + for (m = m0, len = 0; m != NULL; m = m->m_next) + len += m->m_len; + } + return len; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pullup */ +/* Returns: NULL == pullup failed, else pointer to protocol header */ +/* Parameters: xmin(I)- pointer to buffer where data packet starts */ +/* fin(I) - pointer to packet information */ +/* len(I) - number of bytes to pullup */ +/* */ +/* Attempt to move at least len bytes (from the start of the buffer) into a */ +/* single buffer for ease of access. Operating system native functions are */ +/* used to manage buffers - if necessary. If the entire packet ends up in */ +/* a single buffer, set the FI_COALESCE flag even though ipf_coalesce() has */ +/* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */ +/* and ONLY if the pullup succeeds. */ +/* */ +/* We assume that 'xmin' is a pointer to a buffer that is part of the chain */ +/* of buffers that starts at *fin->fin_mp. */ +/* ------------------------------------------------------------------------ */ +void * +ipf_pullup(xmin, fin, len) + mb_t *xmin; + fr_info_t *fin; + int len; +{ + int out = fin->fin_out, dpoff, ipoff; + mb_t *m = xmin; + char *ip; + + if (m == NULL) + return NULL; + + ip = (char *)fin->fin_ip; + if ((fin->fin_flx & FI_COALESCE) != 0) + return ip; + + ipoff = fin->fin_ipoff; + if (fin->fin_dp != NULL) + dpoff = (char *)fin->fin_dp - (char *)ip; + else + dpoff = 0; + + if (M_LEN(m) < len) { + mb_t *n = *fin->fin_mp; + /* + * Assume that M_PKTHDR is set and just work with what is left + * rather than check.. + * Should not make any real difference, anyway. + */ + if (m != n) { + /* + * Record the mbuf that points to the mbuf that we're + * about to go to work on so that we can update the + * m_next appropriately later. + */ + for (; n->m_next != m; n = n->m_next) + ; + } else { + n = NULL; + } + +#ifdef MHLEN + if (len > MHLEN) +#else + if (len > MLEN) +#endif + { + FREE_MB_T(*fin->fin_mp); + m = NULL; + } else + { + m = m_pullup(m, len); + } + if (n != NULL) + n->m_next = m; + if (m == NULL) { + /* + * When n is non-NULL, it indicates that m pointed to + * a sub-chain (tail) of the mbuf and that the head + * of this chain has not yet been free'd. + */ + if (n != NULL) { + FREE_MB_T(*fin->fin_mp); + } + *fin->fin_mp = NULL; + fin->fin_m = NULL; + return NULL; + } + + if (n == NULL) + *fin->fin_mp = m; + while (M_LEN(m) == 0) { + m = m->m_next; + } + fin->fin_m = m; + ip = MTOD(m, char *) + ipoff; + + fin->fin_ip = (ip_t *)ip; + if (fin->fin_dp != NULL) + fin->fin_dp = (char *)fin->fin_ip + dpoff; + if (fin->fin_fraghdr != NULL) + fin->fin_fraghdr = (char *)ip + + ((char *)fin->fin_fraghdr - + (char *)fin->fin_ip); + } + + if (len == fin->fin_plen) + fin->fin_flx |= FI_COALESCE; + return ip; +} + + +void * +getifp(name, v) + char *name; + int v; +{ + return NULL; +} + + +int +ipf_inject(fin, m) + fr_info_t *fin; + mb_t *m; +{ + + FREE_MB_T(m); + + fin->fin_m = NULL; + fin->fin_ip = NULL; + + return EINVAL; +} + + +/* + * In the face of no kernel random function, this is implemented...it is + * not meant to be random, just a fill in. + */ +int +ipf_random() +{ + static int last = 0; + static int calls = 0; + struct timeval tv; + int number; + + GETKTIME(&tv); + last *= tv.tv_usec + calls++; + last += (int)&range * ipf_ticks; + number = last + tv.tv_sec; + return number; +} diff --git a/ip_fil_compat.c b/ip_fil_compat.c new file mode 100644 index 0000000000000..d0b356f76904f --- /dev/null +++ b/ip_fil_compat.c @@ -0,0 +1,4854 @@ +/* + * Copyright (C) 2002-2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ +#if defined(KERNEL) || defined(_KERNEL) +# undef KERNEL +# undef _KERNEL +# define KERNEL 1 +# define _KERNEL 1 +#endif +#if defined(__osf__) +# define _PROTO_NET_H_ +#endif +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/file.h> +#if __FreeBSD_version >= 220000 && defined(_KERNEL) +# include <sys/fcntl.h> +# include <sys/filio.h> +#else +# include <sys/ioctl.h> +#endif +#if !defined(_KERNEL) +# include <string.h> +# define _KERNEL +# ifdef __OpenBSD__ +struct file; +# endif +# include <sys/uio.h> +# undef _KERNEL +#endif +#include <sys/socket.h> +#if (defined(__osf__) || defined(AIX) || defined(__hpux) || defined(__sgi)) && defined(_KERNEL) +# include "radix_ipf_local.h" +# define _RADIX_H_ +#endif +#include <net/if.h> +#if defined(__FreeBSD__) +# include <sys/cdefs.h> +# include <sys/proc.h> +#endif +#if defined(_KERNEL) +# include <sys/systm.h> +# if !defined(__SVR4) && !defined(__svr4__) +# include <sys/mbuf.h> +# endif +#endif +#include <netinet/in.h> + +#include "netinet/ip_compat.h" +#include "netinet/ip_fil.h" +#include "netinet/ip_pool.h" +#include "netinet/ip_htable.h" +#include "netinet/ip_lookup.h" +#include "netinet/ip_nat.h" +#include "netinet/ip_state.h" +#include "netinet/ip_proxy.h" +#include "netinet/ip_auth.h" +/* END OF INCLUDES */ + +/* + * NetBSD has moved to 64bit time_t for all architectures. + * For some, such as sparc64, there is no change because long is already + * 64bit, but for others (i386), there is... + */ +#ifdef IPFILTER_COMPAT + +# ifdef __NetBSD__ +typedef struct timeval_l { + long tv_sec; + long tv_usec; +} timeval_l_t; +# endif + +/* ------------------------------------------------------------------------ */ + +typedef struct tcpinfo4 { + u_short ts_sport; + u_short ts_dport; + tcpdata_t ts_data[2]; +} tcpinfo4_t; + +static void ipf_v5tcpinfoto4 __P((tcpinfo_t *, tcpinfo4_t *)); + +static void +ipf_v5tcpinfoto4(v5, v4) + tcpinfo_t *v5; + tcpinfo4_t *v4; +{ + v4->ts_sport = v5->ts_sport; + v4->ts_dport = v5->ts_dport; + v4->ts_data[0] = v5->ts_data[0]; + v4->ts_data[1] = v5->ts_data[1]; +} + +typedef struct fr_ip4 { + u_32_t fi_v:4; + u_32_t fi_xx:4; + u_32_t fi_tos:8; + u_32_t fi_ttl:8; + u_32_t fi_p:8; + u_32_t fi_optmsk; + i6addr_t fi_src; + i6addr_t fi_dst; + u_short ofi_secmsk; + u_short ofi_auth; + u_32_t fi_flx; + u_32_t fi_tcpmsk; + u_32_t fi_res1; +} frip4_t; + +typedef struct frpcmp4 { + int frp_cmp; + u_short frp_port; + u_short frp_top; +} frpcmp4_t; + +typedef struct frtuc4 { + u_char ftu_tcpfm; + u_char ftu_tcpf; + frpcmp4_t ftu_src; + frpcmp4_t ftu_dst; +} frtuc4_t; + +typedef struct fripf4 { + frip4_t fri_ip; + frip4_t fri_mip; + + u_short fri_icmpm; + u_short fri_icmp; + + frtuc4_t fri_tuc; + int fri_satype; + int fri_datype; + int fri_sifpidx; + int fri_difpidx; +} fripf4_t; + +typedef struct frdest_4 { + void *fd_ifp; + i6addr_t ofd_ip6; + char fd_ifname[LIFNAMSIZ]; +} frdest_4_t; + +/* ------------------------------------------------------------------------ */ + +/* 5.1.0 new release (current) + * 4.1.34 changed the size of the time structure used for pps + * 4.1.16 moved the location of fr_flineno + * 4.1.0 base version + */ +typedef struct frentry_4_1_34 { + ipfmutex_t fr_lock; + struct frentry *fr_next; + struct frentry **fr_grp; + struct ipscan *fr_isc; + void *fr_ifas[4]; + void *fr_ptr; /* for use with fr_arg */ + char *fr_comment; /* text comment for rule */ + int fr_ref; /* reference count - for grouping */ + int fr_statecnt; /* state count - for limit rules */ + int fr_flineno; /* line number from conf file */ + U_QUAD_T fr_hits; + U_QUAD_T fr_bytes; + union { + struct timeval frp_lastpkt; + char frp_bytes[12]; + } fr_lpu; + int fr_curpps; + union { + void *fru_data; + char *fru_caddr; + fripf4_t *fru_ipf; + frentfunc_t fru_func; + } fr_dun; + ipfunc_t fr_func; /* call this function */ + int fr_dsize; + int fr_pps; + int fr_statemax; /* max reference count */ + u_32_t fr_type; + u_32_t fr_flags; /* per-rule flags && options (see below) */ + u_32_t fr_logtag; /* user defined log tag # */ + u_32_t fr_collect; /* collection number */ + u_int fr_arg; /* misc. numeric arg for rule */ + u_int fr_loglevel; /* syslog log facility + priority */ + u_int fr_age[2]; /* non-TCP timeouts */ + u_char fr_v; + u_char fr_icode; /* return ICMP code */ + char fr_group[FR_GROUPLEN]; /* group to which this rule belongs */ + char fr_grhead[FR_GROUPLEN]; /* group # which this rule starts */ + ipftag_t fr_nattag; + char fr_ifnames[4][LIFNAMSIZ]; + char fr_isctag[16]; + frdest_4_t fr_tifs[2]; /* "to"/"reply-to" interface */ + frdest_4_t fr_dif; /* duplicate packet interface */ + u_int fr_cksum; /* checksum on filter rules for performance */ +} frentry_4_1_34_t; + +typedef struct frentry_4_1_16 { + ipfmutex_t fr_lock; + struct frentry *fr_next; + struct frentry **fr_grp; + struct ipscan *fr_isc; + void *fr_ifas[4]; + void *fr_ptr; + char *fr_comment; + int fr_ref; + int fr_statecnt; + int fr_flineno; + U_QUAD_T fr_hits; + U_QUAD_T fr_bytes; + union { +#ifdef __NetBSD__ + timeval_l_t frp_lastpkt; +#else + struct timeval frp_lastpkt; +#endif + } fr_lpu; + int fr_curpps; + union { + void *fru_data; + caddr_t fru_caddr; + fripf4_t *fru_ipf; + frentfunc_t fru_func; + } fr_dun; + ipfunc_t fr_func; + int fr_dsize; + int fr_pps; + int fr_statemax; + u_32_t fr_type; + u_32_t fr_flags; + u_32_t fr_logtag; + u_32_t fr_collect; + u_int fr_arg; + u_int fr_loglevel; + u_int fr_age[2]; + u_char fr_v; + u_char fr_icode; + char fr_group[FR_GROUPLEN]; + char fr_grhead[FR_GROUPLEN]; + ipftag_t fr_nattag; + char fr_ifnames[4][LIFNAMSIZ]; + char fr_isctag[16]; + frdest_4_t fr_tifs[2]; + frdest_4_t fr_dif; + u_int fr_cksum; +} frentry_4_1_16_t; + +typedef struct frentry_4_1_0 { + ipfmutex_t fr_lock; + struct frentry *fr_next; + struct frentry **fr_grp; + struct ipscan *fr_isc; + void *fr_ifas[4]; + void *fr_ptr; + char *fr_comment; + int fr_ref; + int fr_statecnt; + U_QUAD_T fr_hits; + U_QUAD_T fr_bytes; + union { +#ifdef __NetBSD__ + timeval_l_t frp_lastpkt; +#else + struct timeval frp_lastpkt; +#endif + } fr_lpu; + int fr_curpps; + + union { + void *fru_data; + caddr_t fru_caddr; + fripf4_t *fru_ipf; + frentfunc_t fru_func; + } fr_dun; + /* + * Fields after this may not change whilst in the kernel. + */ + ipfunc_t fr_func; + int fr_dsize; + int fr_pps; + int fr_statemax; + int fr_flineno; + u_32_t fr_type; + u_32_t fr_flags; + u_32_t fr_logtag; + u_32_t fr_collect; + u_int fr_arg; + u_int fr_loglevel; + u_int fr_age[2]; + u_char fr_v; + u_char fr_icode; + char fr_group[FR_GROUPLEN]; + char fr_grhead[FR_GROUPLEN]; + ipftag_t fr_nattag; + char fr_ifnames[4][LIFNAMSIZ]; + char fr_isctag[16]; + frdest_4_t fr_tifs[2]; + frdest_4_t fr_dif; + u_int fr_cksum; +} frentry_4_1_0_t; + +/* ------------------------------------------------------------------------ */ + +/* + * 5.1.0 new release (current) + * 4.1.32 removed both fin_state and fin_nat, added fin_pktnum + * 4.1.24 added fin_cksum + * 4.1.23 added fin_exthdr + * 4.1.11 added fin_ifname + * 4.1.4 added fin_hbuf + */ +typedef struct fr_info_4_1_32 { + void *fin_ifp; /* interface packet is `on' */ + frip4_t fin_fi; /* IP Packet summary */ + union { + u_short fid_16[2]; /* TCP/UDP ports, ICMP code/type */ + u_32_t fid_32; + } fin_dat; + int fin_out; /* in or out ? 1 == out, 0 == in */ + int fin_rev; /* state only: 1 = reverse */ + u_short fin_hlen; /* length of IP header in bytes */ + u_char ofin_tcpf; /* TCP header flags (SYN, ACK, etc) */ + u_char fin_icode; /* ICMP error to return */ + u_32_t fin_rule; /* rule # last matched */ + char fin_group[FR_GROUPLEN]; /* group number, -1 for none */ + struct frentry *fin_fr; /* last matching rule */ + void *fin_dp; /* start of data past IP header */ + int fin_dlen; /* length of data portion of packet */ + int fin_plen; + int fin_ipoff; /* # bytes from buffer start to hdr */ + u_short fin_id; /* IP packet id field */ + u_short fin_off; + int fin_depth; /* Group nesting depth */ + int fin_error; /* Error code to return */ + int fin_cksum; /* -1 bad, 1 good, 0 not done */ + u_int fin_pktnum; + void *fin_nattag; + void *fin_exthdr; + ip_t *ofin_ip; + mb_t **fin_mp; /* pointer to pointer to mbuf */ + mb_t *fin_m; /* pointer to mbuf */ +#ifdef MENTAT + mb_t *fin_qfm; /* pointer to mblk where pkt starts */ + void *fin_qpi; + char fin_ifname[LIFNAMSIZ]; +#endif +#ifdef __sgi + void *fin_hbuf; +#endif +} fr_info_4_1_32_t; + +typedef struct fr_info_4_1_24 { + void *fin_ifp; + frip4_t fin_fi; + union { + u_short fid_16[2]; + u_32_t fid_32; + } fin_dat; + int fin_out; + int fin_rev; + u_short fin_hlen; + u_char ofin_tcpf; + u_char fin_icode; + u_32_t fin_rule; + char fin_group[FR_GROUPLEN]; + struct frentry *fin_fr; + void *fin_dp; + int fin_dlen; + int fin_plen; + int fin_ipoff; + u_short fin_id; + u_short fin_off; + int fin_depth; + int fin_error; + int fin_cksum; + void *fin_state; + void *fin_nat; + void *fin_nattag; + void *fin_exthdr; + ip_t *ofin_ip; + mb_t **fin_mp; + mb_t *fin_m; +#ifdef MENTAT + mb_t *fin_qfm; + void *fin_qpi; + char fin_ifname[LIFNAMSIZ]; +#endif +#ifdef __sgi + void *fin_hbuf; +#endif +} fr_info_4_1_24_t; + +typedef struct fr_info_4_1_23 { + void *fin_ifp; + frip4_t fin_fi; + union { + u_short fid_16[2]; + u_32_t fid_32; + } fin_dat; + int fin_out; + int fin_rev; + u_short fin_hlen; + u_char ofin_tcpf; + u_char fin_icode; + u_32_t fin_rule; + char fin_group[FR_GROUPLEN]; + struct frentry *fin_fr; + void *fin_dp; + int fin_dlen; + int fin_plen; + int fin_ipoff; + u_short fin_id; + u_short fin_off; + int fin_depth; + int fin_error; + void *fin_state; + void *fin_nat; + void *fin_nattag; + void *fin_exthdr; + ip_t *ofin_ip; + mb_t **fin_mp; + mb_t *fin_m; +#ifdef MENTAT + mb_t *fin_qfm; + void *fin_qpi; + char fin_ifname[LIFNAMSIZ]; +#endif +#ifdef __sgi + void *fin_hbuf; +#endif +} fr_info_4_1_23_t; + +typedef struct fr_info_4_1_11 { + void *fin_ifp; + frip4_t fin_fi; + union { + u_short fid_16[2]; + u_32_t fid_32; + } fin_dat; + int fin_out; + int fin_rev; + u_short fin_hlen; + u_char ofin_tcpf; + u_char fin_icode; + u_32_t fin_rule; + char fin_group[FR_GROUPLEN]; + struct frentry *fin_fr; + void *fin_dp; + int fin_dlen; + int fin_plen; + int fin_ipoff; + u_short fin_id; + u_short fin_off; + int fin_depth; + int fin_error; + void *fin_state; + void *fin_nat; + void *fin_nattag; + ip_t *ofin_ip; + mb_t **fin_mp; + mb_t *fin_m; +#ifdef MENTAT + mb_t *fin_qfm; + void *fin_qpi; + char fin_ifname[LIFNAMSIZ]; +#endif +#ifdef __sgi + void *fin_hbuf; +#endif +} fr_info_4_1_11_t; + +/* ------------------------------------------------------------------------ */ + +typedef struct filterstats_4_1 { + u_long fr_pass; /* packets allowed */ + u_long fr_block; /* packets denied */ + u_long fr_nom; /* packets which don't match any rule */ + u_long fr_short; /* packets which are short */ + u_long fr_ppkl; /* packets allowed and logged */ + u_long fr_bpkl; /* packets denied and logged */ + u_long fr_npkl; /* packets unmatched and logged */ + u_long fr_pkl; /* packets logged */ + u_long fr_skip; /* packets to be logged but buffer full */ + u_long fr_ret; /* packets for which a return is sent */ + u_long fr_acct; /* packets for which counting was performed */ + u_long fr_bnfr; /* bad attempts to allocate fragment state */ + u_long fr_nfr; /* new fragment state kept */ + u_long fr_cfr; /* add new fragment state but complete pkt */ + u_long fr_bads; /* bad attempts to allocate packet state */ + u_long fr_ads; /* new packet state kept */ + u_long fr_chit; /* cached hit */ + u_long fr_tcpbad; /* TCP checksum check failures */ + u_long fr_pull[2]; /* good and bad pullup attempts */ + u_long fr_badsrc; /* source received doesn't match route */ + u_long fr_badttl; /* TTL in packet doesn't reach minimum */ + u_long fr_bad; /* bad IP packets to the filter */ + u_long fr_ipv6; /* IPv6 packets in/out */ + u_long fr_ppshit; /* dropped because of pps ceiling */ + u_long fr_ipud; /* IP id update failures */ +} filterstats_4_1_t; + +/* + * 5.1.0 new release (current) + * 4.1.33 changed the size of f_locks from IPL_LOGMAX to IPL_LOGSIZE + */ +typedef struct friostat_4_1_33 { + struct filterstats_4_1 of_st[2]; + struct frentry *f_ipf[2][2]; + struct frentry *f_acct[2][2]; + struct frentry *f_ipf6[2][2]; + struct frentry *f_acct6[2][2]; + struct frentry *f_auth; + struct frgroup *f_groups[IPL_LOGSIZE][2]; + u_long f_froute[2]; + u_long f_ticks; + int f_locks[IPL_LOGSIZE]; + size_t f_kmutex_sz; + size_t f_krwlock_sz; + int f_defpass; /* default pass - from fr_pass */ + int f_active; /* 1 or 0 - active rule set */ + int f_running; /* 1 if running, else 0 */ + int f_logging; /* 1 if enabled, else 0 */ + int f_features; + char f_version[32]; /* version string */ +} friostat_4_1_33_t; + +typedef struct friostat_4_1_0 { + struct filterstats_4_1 of_st[2]; + struct frentry *f_ipf[2][2]; + struct frentry *f_acct[2][2]; + struct frentry *f_ipf6[2][2]; + struct frentry *f_acct6[2][2]; + struct frentry *f_auth; + struct frgroup *f_groups[IPL_LOGSIZE][2]; + u_long f_froute[2]; + u_long f_ticks; + int f_locks[IPL_LOGMAX]; + size_t f_kmutex_sz; + size_t f_krwlock_sz; + int f_defpass; + int f_active; + int f_running; + int f_logging; + int f_features; + char f_version[32]; +} friostat_4_1_0_t; + +/* ------------------------------------------------------------------------ */ + +/* + * 5.1.0 new release (current) + * 4.1.14 added in_lock + */ +typedef struct ipnat_4_1_14 { + ipfmutex_t in_lock; + struct ipnat *in_next; /* NAT rule list next */ + struct ipnat *in_rnext; /* rdr rule hash next */ + struct ipnat **in_prnext; /* prior rdr next ptr */ + struct ipnat *in_mnext; /* map rule hash next */ + struct ipnat **in_pmnext; /* prior map next ptr */ + struct ipftq *in_tqehead[2]; + void *in_ifps[2]; + void *in_apr; + char *in_comment; + i6addr_t in_next6; + u_long in_space; + u_long in_hits; + u_int in_use; + u_int in_hv; + int in_flineno; /* conf. file line number */ + u_short in_pnext; + u_char in_v; + u_char in_xxx; + /* From here to the end is covered by IPN_CMPSIZ */ + u_32_t in_flags; + u_32_t in_mssclamp; /* if != 0 clamp MSS to this */ + u_int in_age[2]; + int in_redir; /* see below for values */ + int in_p; /* protocol. */ + i6addr_t in_in[2]; + i6addr_t in_out[2]; + i6addr_t in_src[2]; + frtuc4_t in_tuc; + u_short in_port[2]; + u_short in_ppip; /* ports per IP. */ + u_short in_ippip; /* IP #'s per IP# */ + char in_ifnames[2][LIFNAMSIZ]; + char in_plabel[APR_LABELLEN]; /* proxy label. */ + ipftag_t in_tag; +} ipnat_4_1_14_t; + +typedef struct ipnat_4_1_0 { + struct ipnat *in_next; + struct ipnat *in_rnext; + struct ipnat **in_prnext; + struct ipnat *in_mnext; + struct ipnat **in_pmnext; + struct ipftq *in_tqehead[2]; + void *in_ifps[2]; + void *in_apr; + char *in_comment; + i6addr_t in_next6; + u_long in_space; + u_long in_hits; + u_int in_use; + u_int in_hv; + int in_flineno; + u_short in_pnext; + u_char in_v; + u_char in_xxx; + u_32_t in_flags; + u_32_t in_mssclamp; + u_int in_age[2]; + int in_redir; + int in_p; + i6addr_t in_in[2]; + i6addr_t in_out[2]; + i6addr_t in_src[2]; + frtuc4_t in_tuc; + u_short in_port[2]; + u_short in_ppip; + u_short in_ippip; + char in_ifnames[2][LIFNAMSIZ]; + char in_plabel[APR_LABELLEN]; + ipftag_t in_tag; +} ipnat_4_1_0_t; + +/* ------------------------------------------------------------------------ */ + +typedef struct natlookup_4_1_1 { + struct in_addr onl_inip; + struct in_addr onl_outip; + struct in_addr onl_realip; + int nl_flags; + u_short nl_inport; + u_short nl_outport; + u_short nl_realport; +} natlookup_4_1_1_t; + +/* ------------------------------------------------------------------------ */ + +/* + * 4.1.25 added nat_seqnext (current) + * 4.1.14 added nat_redir + * 4.1.3 moved nat_rev + * 4.1.2 added nat_rev + */ +typedef struct nat_4_1_25 { + ipfmutex_t nat_lock; + struct nat_4_1_25 *nat_next; + struct nat_4_1_25 **nat_pnext; + struct nat_4_1_25 *nat_hnext[2]; + struct nat_4_1_25 **nat_phnext[2]; + struct hostmap *nat_hm; + void *nat_data; + struct nat_4_1_25 **nat_me; + struct ipstate *nat_state; + struct ap_session *nat_aps; + frentry_t *nat_fr; + struct ipnat_4_1_14 *nat_ptr; + void *nat_ifps[2]; + void *nat_sync; + ipftqent_t nat_tqe; + u_32_t nat_flags; + u_32_t nat_sumd[2]; + u_32_t nat_ipsumd; + u_32_t nat_mssclamp; + i6addr_t nat_inip6; + i6addr_t nat_outip6; + i6addr_t nat_oip6; + U_QUAD_T nat_pkts[2]; + U_QUAD_T nat_bytes[2]; + union { + udpinfo_t nat_unu; + tcpinfo4_t nat_unt; + icmpinfo_t nat_uni; + greinfo_t nat_ugre; + } nat_un; + u_short nat_oport; + u_short nat_use; + u_char nat_p; + int nat_dir; + int nat_ref; + int nat_hv[2]; + char nat_ifnames[2][LIFNAMSIZ]; + int nat_rev; + int nat_redir; + u_32_t nat_seqnext[2]; +} nat_4_1_25_t; + +typedef struct nat_4_1_14 { + ipfmutex_t nat_lock; + struct nat *nat_next; + struct nat **nat_pnext; + struct nat *nat_hnext[2]; + struct nat **nat_phnext[2]; + struct hostmap *nat_hm; + void *nat_data; + struct nat **nat_me; + struct ipstate *nat_state; + struct ap_session *nat_aps; + frentry_t *nat_fr; + struct ipnat *nat_ptr; + void *nat_ifps[2]; + void *nat_sync; + ipftqent_t nat_tqe; + u_32_t nat_flags; + u_32_t nat_sumd[2]; + u_32_t nat_ipsumd; + u_32_t nat_mssclamp; + i6addr_t nat_inip6; + i6addr_t nat_outip6; + i6addr_t nat_oip6; + U_QUAD_T nat_pkts[2]; + U_QUAD_T nat_bytes[2]; + union { + udpinfo_t nat_unu; + tcpinfo4_t nat_unt; + icmpinfo_t nat_uni; + greinfo_t nat_ugre; + } nat_un; + u_short nat_oport; + u_short nat_use; + u_char nat_p; + int nat_dir; + int nat_ref; + int nat_hv[2]; + char nat_ifnames[2][LIFNAMSIZ]; + int nat_rev; + int nat_redir; +} nat_4_1_14_t; + +typedef struct nat_4_1_3 { + ipfmutex_t nat_lock; + struct nat *nat_next; + struct nat **nat_pnext; + struct nat *nat_hnext[2]; + struct nat **nat_phnext[2]; + struct hostmap *nat_hm; + void *nat_data; + struct nat **nat_me; + struct ipstate *nat_state; + struct ap_session *nat_aps; + frentry_t *nat_fr; + struct ipnat *nat_ptr; + void *nat_ifps[2]; + void *nat_sync; + ipftqent_t nat_tqe; + u_32_t nat_flags; + u_32_t nat_sumd[2]; + u_32_t nat_ipsumd; + u_32_t nat_mssclamp; + i6addr_t nat_inip6; + i6addr_t nat_outip6; + i6addr_t nat_oip6; + U_QUAD_T nat_pkts[2]; + U_QUAD_T nat_bytes[2]; + union { + udpinfo_t nat_unu; + tcpinfo4_t nat_unt; + icmpinfo_t nat_uni; + greinfo_t nat_ugre; + } nat_un; + u_short nat_oport; + u_short nat_use; + u_char nat_p; + int nat_dir; + int nat_ref; + int nat_hv[2]; + char nat_ifnames[2][LIFNAMSIZ]; + int nat_rev; +} nat_4_1_3_t; + + + +typedef struct nat_save_4_1_34 { + void *ipn_next; + struct nat_4_1_25 ipn_nat; + struct ipnat_4_1_14 ipn_ipnat; + struct frentry_4_1_34 ipn_fr; + int ipn_dsize; + char ipn_data[4]; +} nat_save_4_1_34_t; + +typedef struct nat_save_4_1_16 { + void *ipn_next; + nat_4_1_14_t ipn_nat; + ipnat_t ipn_ipnat; + frentry_4_1_16_t ipn_fr; + int ipn_dsize; + char ipn_data[4]; +} nat_save_4_1_16_t; + +typedef struct nat_save_4_1_14 { + void *ipn_next; + nat_4_1_14_t ipn_nat; + ipnat_t ipn_ipnat; + frentry_4_1_0_t ipn_fr; + int ipn_dsize; + char ipn_data[4]; +} nat_save_4_1_14_t; + +typedef struct nat_save_4_1_3 { + void *ipn_next; + nat_4_1_3_t ipn_nat; + ipnat_4_1_0_t ipn_ipnat; + frentry_4_1_0_t ipn_fr; + int ipn_dsize; + char ipn_data[4]; +} nat_save_4_1_3_t; + +/* ------------------------------------------------------------------------ */ + +/* + * 5.1.0 new release (current) + * 4.1.32 added ns_uncreate + * 4.1.27 added ns_orphans + * 4.1.16 added ns_ticks + */ +typedef struct natstat_4_1_32 { + u_long ns_mapped[2]; + u_long ns_rules; + u_long ns_added; + u_long ns_expire; + u_long ns_inuse; + u_long ns_logged; + u_long ns_logfail; + u_long ns_memfail; + u_long ns_badnat; + u_long ns_addtrpnt; + nat_t **ns_table[2]; + hostmap_t **ns_maptable; + ipnat_t *ns_list; + void *ns_apslist; + u_int ns_wilds; + u_int ns_nattab_sz; + u_int ns_nattab_max; + u_int ns_rultab_sz; + u_int ns_rdrtab_sz; + u_int ns_trpntab_sz; + u_int ns_hostmap_sz; + nat_t *ns_instances; + hostmap_t *ns_maplist; + u_long *ns_bucketlen[2]; + u_long ns_ticks; + u_int ns_orphans; + u_long ns_uncreate[2][2]; +} natstat_4_1_32_t; + +typedef struct natstat_4_1_27 { + u_long ns_mapped[2]; + u_long ns_rules; + u_long ns_added; + u_long ns_expire; + u_long ns_inuse; + u_long ns_logged; + u_long ns_logfail; + u_long ns_memfail; + u_long ns_badnat; + u_long ns_addtrpnt; + nat_t **ns_table[2]; + hostmap_t **ns_maptable; + ipnat_t *ns_list; + void *ns_apslist; + u_int ns_wilds; + u_int ns_nattab_sz; + u_int ns_nattab_max; + u_int ns_rultab_sz; + u_int ns_rdrtab_sz; + u_int ns_trpntab_sz; + u_int ns_hostmap_sz; + nat_t *ns_instances; + hostmap_t *ns_maplist; + u_long *ns_bucketlen[2]; + u_long ns_ticks; + u_int ns_orphans; +} natstat_4_1_27_t; + +typedef struct natstat_4_1_16 { + u_long ns_mapped[2]; + u_long ns_rules; + u_long ns_added; + u_long ns_expire; + u_long ns_inuse; + u_long ns_logged; + u_long ns_logfail; + u_long ns_memfail; + u_long ns_badnat; + u_long ns_addtrpnt; + nat_t **ns_table[2]; + hostmap_t **ns_maptable; + ipnat_t *ns_list; + void *ns_apslist; + u_int ns_wilds; + u_int ns_nattab_sz; + u_int ns_nattab_max; + u_int ns_rultab_sz; + u_int ns_rdrtab_sz; + u_int ns_trpntab_sz; + u_int ns_hostmap_sz; + nat_t *ns_instances; + hostmap_t *ns_maplist; + u_long *ns_bucketlen[2]; + u_long ns_ticks; +} natstat_4_1_16_t; + +typedef struct natstat_4_1_0 { + u_long ns_mapped[2]; + u_long ns_rules; + u_long ns_added; + u_long ns_expire; + u_long ns_inuse; + u_long ns_logged; + u_long ns_logfail; + u_long ns_memfail; + u_long ns_badnat; + u_long ns_addtrpnt; + nat_t **ns_table[2]; + hostmap_t **ns_maptable; + ipnat_t *ns_list; + void *ns_apslist; + u_int ns_wilds; + u_int ns_nattab_sz; + u_int ns_nattab_max; + u_int ns_rultab_sz; + u_int ns_rdrtab_sz; + u_int ns_trpntab_sz; + u_int ns_hostmap_sz; + nat_t *ns_instances; + hostmap_t *ns_maplist; + u_long *ns_bucketlen[2]; +} natstat_4_1_0_t; + +/* ------------------------------------------------------------------------ */ + +/* + * 5.1.0 new release (current) + * 4.1.32 fra_info:removed both fin_state & fin_nat, added fin_pktnum + * 4.1.29 added fra_flx + * 4.1.24 fra_info:added fin_cksum + * 4.1.23 fra_info:added fin_exthdr + * 4.1.11 fra_info:added fin_ifname + * 4.1.4 fra_info:added fin_hbuf + */ + +typedef struct frauth_4_1_32 { + int fra_age; + int fra_len; + int fra_index; + u_32_t fra_pass; + fr_info_4_1_32_t fra_info; + char *fra_buf; + u_32_t fra_flx; +#ifdef MENTAT + queue_t *fra_q; + mb_t *fra_m; +#endif +} frauth_4_1_32_t; + +typedef struct frauth_4_1_29 { + int fra_age; + int fra_len; + int fra_index; + u_32_t fra_pass; + fr_info_4_1_24_t fra_info; + char *fra_buf; + u_32_t fra_flx; +#ifdef MENTAT + queue_t *fra_q; + mb_t *fra_m; +#endif +} frauth_4_1_29_t; + +typedef struct frauth_4_1_24 { + int fra_age; + int fra_len; + int fra_index; + u_32_t fra_pass; + fr_info_4_1_24_t fra_info; + char *fra_buf; +#ifdef MENTAT + queue_t *fra_q; + mb_t *fra_m; +#endif +} frauth_4_1_24_t; + +typedef struct frauth_4_1_23 { + int fra_age; + int fra_len; + int fra_index; + u_32_t fra_pass; + fr_info_4_1_23_t fra_info; + char *fra_buf; +#ifdef MENTAT + queue_t *fra_q; + mb_t *fra_m; +#endif +} frauth_4_1_23_t; + +typedef struct frauth_4_1_11 { + int fra_age; + int fra_len; + int fra_index; + u_32_t fra_pass; + fr_info_4_1_11_t fra_info; + char *fra_buf; +#ifdef MENTAT + queue_t *fra_q; + mb_t *fra_m; +#endif +} frauth_4_1_11_t; + +/* ------------------------------------------------------------------------ */ + +/* + * 5.1.0 new release (current) + * 4.1.16 removed is_nat + */ +typedef struct ipstate_4_1_16 { + ipfmutex_t is_lock; + struct ipstate *is_next; + struct ipstate **is_pnext; + struct ipstate *is_hnext; + struct ipstate **is_phnext; + struct ipstate **is_me; + void *is_ifp[4]; + void *is_sync; + frentry_t *is_rule; + struct ipftq *is_tqehead[2]; + struct ipscan *is_isc; + U_QUAD_T is_pkts[4]; + U_QUAD_T is_bytes[4]; + U_QUAD_T is_icmppkts[4]; + struct ipftqent is_sti; + u_int is_frage[2]; + int is_ref; /* reference count */ + int is_isninc[2]; + u_short is_sumd[2]; + i6addr_t is_src; + i6addr_t is_dst; + u_int is_pass; + u_char is_p; /* Protocol */ + u_char is_v; + u_32_t is_hv; + u_32_t is_tag; + u_32_t is_opt[2]; /* packet options set */ + u_32_t is_optmsk[2]; /* " " mask */ + u_short is_sec; /* security options set */ + u_short is_secmsk; /* " " mask */ + u_short is_auth; /* authentication options set */ + u_short is_authmsk; /* " " mask */ + union { + icmpinfo_t is_ics; + tcpinfo4_t is_ts; + udpinfo_t is_us; + greinfo_t is_ug; + } is_ps; + u_32_t is_flags; + int is_flx[2][2]; + u_32_t is_rulen; /* rule number when created */ + u_32_t is_s0[2]; + u_short is_smsk[2]; + char is_group[FR_GROUPLEN]; + char is_sbuf[2][16]; + char is_ifname[4][LIFNAMSIZ]; +} ipstate_4_1_16_t; + +typedef struct ipstate_4_1_0 { + ipfmutex_t is_lock; + struct ipstate *is_next; + struct ipstate **is_pnext; + struct ipstate *is_hnext; + struct ipstate **is_phnext; + struct ipstate **is_me; + void *is_ifp[4]; + void *is_sync; + void *is_nat[2]; + frentry_t *is_rule; + struct ipftq *is_tqehead[2]; + struct ipscan *is_isc; + U_QUAD_T is_pkts[4]; + U_QUAD_T is_bytes[4]; + U_QUAD_T is_icmppkts[4]; + struct ipftqent is_sti; + u_int is_frage[2]; + int is_ref; + int is_isninc[2]; + u_short is_sumd[2]; + i6addr_t is_src; + i6addr_t is_dst; + u_int is_pass; + u_char is_p; + u_char is_v; + u_32_t is_hv; + u_32_t is_tag; + u_32_t is_opt[2]; + u_32_t is_optmsk[2]; + u_short is_sec; + u_short is_secmsk; + u_short is_auth; + u_short is_authmsk; + union { + icmpinfo_t is_ics; + tcpinfo4_t is_ts; + udpinfo_t is_us; + greinfo_t is_ug; + } is_ps; + u_32_t is_flags; + int is_flx[2][2]; + u_32_t is_rulen; + u_32_t is_s0[2]; + u_short is_smsk[2]; + char is_group[FR_GROUPLEN]; + char is_sbuf[2][16]; + char is_ifname[4][LIFNAMSIZ]; +} ipstate_4_1_0_t; + +typedef struct ipstate_save_4_1_34 { + void *ips_next; + struct ipstate_4_1_16 ips_is; + struct frentry_4_1_34 ips_fr; +} ipstate_save_4_1_34_t; + +typedef struct ipstate_save_4_1_16 { + void *ips_next; + ipstate_4_1_0_t ips_is; + frentry_4_1_16_t ips_fr; +} ipstate_save_4_1_16_t; + +typedef struct ipstate_save_4_1_0 { + void *ips_next; + ipstate_4_1_0_t ips_is; + frentry_4_1_0_t ips_fr; +} ipstate_save_4_1_0_t; + +/* ------------------------------------------------------------------------ */ + +/* + * 5.1.0 new release (current) + * 4.1.21 added iss_tcptab + */ +typedef struct ips_stat_4_1_21 { + u_long iss_hits; + u_long iss_miss; + u_long iss_max; + u_long iss_maxref; + u_long iss_tcp; + u_long iss_udp; + u_long iss_icmp; + u_long iss_nomem; + u_long iss_expire; + u_long iss_fin; + u_long iss_active; + u_long iss_logged; + u_long iss_logfail; + u_long iss_inuse; + u_long iss_wild; + u_long iss_killed; + u_long iss_ticks; + u_long iss_bucketfull; + int iss_statesize; + int iss_statemax; + ipstate_t **iss_table; + ipstate_t *iss_list; + u_long *iss_bucketlen; + ipftq_t *iss_tcptab; +} ips_stat_4_1_21_t; + +typedef struct ips_stat_4_1_0 { + u_long iss_hits; + u_long iss_miss; + u_long iss_max; + u_long iss_maxref; + u_long iss_tcp; + u_long iss_udp; + u_long iss_icmp; + u_long iss_nomem; + u_long iss_expire; + u_long iss_fin; + u_long iss_active; + u_long iss_logged; + u_long iss_logfail; + u_long iss_inuse; + u_long iss_wild; + u_long iss_killed; + u_long iss_ticks; + u_long iss_bucketfull; + int iss_statesize; + int iss_statemax; + ipstate_t **iss_table; + ipstate_t *iss_list; + u_long *iss_bucketlen; +} ips_stat_4_1_0_t; + +/* ------------------------------------------------------------------------ */ + +typedef struct ipfrstat_4_1_1 { + u_long ifs_exists; /* add & already exists */ + u_long ifs_nomem; + u_long ifs_new; + u_long ifs_hits; + u_long ifs_expire; + u_long ifs_inuse; + u_long ifs_retrans0; + u_long ifs_short; + struct ipfr **ifs_table; + struct ipfr **ifs_nattab; +} ipfrstat_4_1_1_t; + +/* ------------------------------------------------------------------------ */ +static int ipf_addfrstr __P((char *, int, char *, int)); +static void ipf_v4iptov5 __P((frip4_t *, fr_ip_t *)); +static void ipf_v5iptov4 __P((fr_ip_t *, frip4_t *)); +static void ipfv4tuctov5 __P((frtuc4_t *, frtuc_t *)); +static void ipfv5tuctov4 __P((frtuc_t *, frtuc4_t *)); +static int ipf_v4fripftov5 __P((fripf4_t *, char *)); +static void ipf_v5fripftov4 __P((fripf_t *, fripf4_t *)); +static int fr_frflags4to5 __P((u_32_t)); +static int fr_frflags5to4 __P((u_32_t)); + +static void friostat_current_to_4_1_0 __P((void *, friostat_4_1_0_t *, int)); +static void friostat_current_to_4_1_33 __P((void *, friostat_4_1_33_t *, int)); +static void ipstate_current_to_4_1_0 __P((void *, ipstate_4_1_0_t *)); +static void ipstate_current_to_4_1_16 __P((void *, ipstate_4_1_16_t *)); +static void ipnat_current_to_4_1_0 __P((void *, ipnat_4_1_0_t *)); +static void ipnat_current_to_4_1_14 __P((void *, ipnat_4_1_14_t *)); +static void frauth_current_to_4_1_11 __P((void *, frauth_4_1_11_t *)); +static void frauth_current_to_4_1_23 __P((void *, frauth_4_1_23_t *)); +static void frauth_current_to_4_1_24 __P((void *, frauth_4_1_24_t *)); +static void frauth_current_to_4_1_29 __P((void *, frauth_4_1_29_t *)); +static void frentry_current_to_4_1_0 __P((void *, frentry_4_1_0_t *)); +static void frentry_current_to_4_1_16 __P((void *, frentry_4_1_16_t *)); +static void frentry_current_to_4_1_34 __P((void *, frentry_4_1_34_t *)); +static void fr_info_current_to_4_1_11 __P((void *, fr_info_4_1_11_t *)); +static void fr_info_current_to_4_1_23 __P((void *, fr_info_4_1_23_t *)); +static void fr_info_current_to_4_1_24 __P((void *, fr_info_4_1_24_t *)); +static void nat_save_current_to_4_1_3 __P((void *, nat_save_4_1_3_t *)); +static void nat_save_current_to_4_1_14 __P((void *, nat_save_4_1_14_t *)); +static void nat_save_current_to_4_1_16 __P((void *, nat_save_4_1_16_t *)); +static void ipstate_save_current_to_4_1_0 __P((void *, ipstate_save_4_1_0_t *)); +static void ipstate_save_current_to_4_1_16 __P((void *, ipstate_save_4_1_16_t *)); +static void ips_stat_current_to_4_1_0 __P((void *, ips_stat_4_1_0_t *)); +static void ips_stat_current_to_4_1_21 __P((void *, ips_stat_4_1_21_t *)); +static void natstat_current_to_4_1_0 __P((void *, natstat_4_1_0_t *)); +static void natstat_current_to_4_1_16 __P((void *, natstat_4_1_16_t *)); +static void natstat_current_to_4_1_27 __P((void *, natstat_4_1_27_t *)); +static void natstat_current_to_4_1_32 __P((void *, natstat_4_1_32_t *)); +static void nat_current_to_4_1_3 __P((void *, nat_4_1_3_t *)); +static void nat_current_to_4_1_14 __P((void *, nat_4_1_14_t *)); +static void nat_current_to_4_1_25 __P((void *, nat_4_1_25_t *)); + +static void friostat_4_1_0_to_current __P((friostat_4_1_0_t *, void *)); +static void friostat_4_1_33_to_current __P((friostat_4_1_33_t *, void *)); +static void ipnat_4_1_0_to_current __P((ipnat_4_1_0_t *, void *, int)); +static void ipnat_4_1_14_to_current __P((ipnat_4_1_14_t *, void *, int)); +static void frauth_4_1_11_to_current __P((frauth_4_1_11_t *, void *)); +static void frauth_4_1_23_to_current __P((frauth_4_1_23_t *, void *)); +static void frauth_4_1_24_to_current __P((frauth_4_1_24_t *, void *)); +static void frauth_4_1_29_to_current __P((frauth_4_1_29_t *, void *)); +static void frauth_4_1_32_to_current __P((frauth_4_1_32_t *, void *)); +static void frentry_4_1_0_to_current __P((ipf_main_softc_t *, frentry_4_1_0_t *, void *, int)); +static void frentry_4_1_16_to_current __P((ipf_main_softc_t *, frentry_4_1_16_t *, void *, int)); +static void frentry_4_1_34_to_current __P((ipf_main_softc_t *, frentry_4_1_34_t *, void *, int)); +static void fr_info_4_1_11_to_current __P((fr_info_4_1_11_t *, void *)); +static void fr_info_4_1_23_to_current __P((fr_info_4_1_23_t *, void *)); +static void fr_info_4_1_24_to_current __P((fr_info_4_1_24_t *, void *)); +static void fr_info_4_1_32_to_current __P((fr_info_4_1_32_t *, void *)); +static void nat_save_4_1_3_to_current __P((ipf_main_softc_t *, nat_save_4_1_3_t *, void *)); +static void nat_save_4_1_14_to_current __P((ipf_main_softc_t *, nat_save_4_1_14_t *, void *)); +static void nat_save_4_1_16_to_current __P((ipf_main_softc_t *, nat_save_4_1_16_t *, void *)); + +/* ------------------------------------------------------------------------ */ +/* In this section is a series of short routines that deal with translating */ +/* the smaller data structures used above as their internal changes make */ +/* them inappropriate for simple assignment. */ +/* ------------------------------------------------------------------------ */ + + +static int +ipf_addfrstr(char *names, int namelen, char *str, int maxlen) +{ + char *t; + int i; + + for (i = maxlen, t = str; (*t != '\0') && (i > 0); i--) { + names[namelen++] = *t++; + } + names[namelen++] = '\0'; + return namelen; +} + + +static void +ipf_v4iptov5(v4, v5) + frip4_t *v4; + fr_ip_t *v5; +{ + v5->fi_v = v4->fi_v; + v5->fi_p = v4->fi_p; + v5->fi_xx = v4->fi_xx; + v5->fi_tos = v4->fi_tos; + v5->fi_ttl = v4->fi_ttl; + v5->fi_p = v4->fi_p; + v5->fi_optmsk = v4->fi_optmsk; + v5->fi_src = v4->fi_src; + v5->fi_dst = v4->fi_dst; + v5->fi_secmsk = v4->ofi_secmsk; + v5->fi_auth = v4->ofi_auth; + v5->fi_flx = v4->fi_flx; + v5->fi_tcpmsk = v4->fi_tcpmsk; +} + +static void +ipf_v5iptov4(v5, v4) + fr_ip_t *v5; + frip4_t *v4; +{ + v4->fi_v = v5->fi_v; + v4->fi_p = v5->fi_p; + v4->fi_xx = v5->fi_xx; + v4->fi_tos = v5->fi_tos; + v4->fi_ttl = v5->fi_ttl; + v4->fi_p = v5->fi_p; + v4->fi_optmsk = v5->fi_optmsk; + v4->fi_src = v5->fi_src; + v4->fi_dst = v5->fi_dst; + v4->ofi_secmsk = v5->fi_secmsk; + v4->ofi_auth = v5->fi_auth; + v4->fi_flx = v5->fi_flx; + v4->fi_tcpmsk = v5->fi_tcpmsk; +} + + +static void +ipfv4tuctov5(v4, v5) + frtuc4_t *v4; + frtuc_t *v5; +{ + v5->ftu_src.frp_cmp = v4->ftu_src.frp_cmp; + v5->ftu_src.frp_port = v4->ftu_src.frp_port; + v5->ftu_src.frp_top = v4->ftu_src.frp_top; + v5->ftu_dst.frp_cmp = v4->ftu_dst.frp_cmp; + v5->ftu_dst.frp_port = v4->ftu_dst.frp_port; + v5->ftu_dst.frp_top = v4->ftu_dst.frp_top; +} + + +static void +ipfv5tuctov4(v5, v4) + frtuc_t *v5; + frtuc4_t *v4; +{ + v4->ftu_src.frp_cmp = v5->ftu_src.frp_cmp; + v4->ftu_src.frp_port = v5->ftu_src.frp_port; + v4->ftu_src.frp_top = v5->ftu_src.frp_top; + v4->ftu_dst.frp_cmp = v5->ftu_dst.frp_cmp; + v4->ftu_dst.frp_port = v5->ftu_dst.frp_port; + v4->ftu_dst.frp_top = v5->ftu_dst.frp_top; +} + + +static int +ipf_v4fripftov5(frp4, dst) + fripf4_t *frp4; + char *dst; +{ + fripf_t *frp; + + frp = (fripf_t *)dst; + + ipf_v4iptov5(&frp4->fri_ip, &frp->fri_ip); + ipf_v4iptov5(&frp4->fri_mip, &frp->fri_mip); + frp->fri_icmpm = frp4->fri_icmpm; + frp->fri_icmp = frp4->fri_icmp; + frp->fri_tuc.ftu_tcpfm = frp4->fri_tuc.ftu_tcpfm; + frp->fri_tuc.ftu_tcpf = frp4->fri_tuc.ftu_tcpf; + ipfv4tuctov5(&frp4->fri_tuc, &frp->fri_tuc); + frp->fri_satype = frp4->fri_satype; + frp->fri_datype = frp4->fri_datype; + frp->fri_sifpidx = frp4->fri_sifpidx; + frp->fri_difpidx = frp4->fri_difpidx; + return 0; +} + + +static void +ipf_v5fripftov4(frp, frp4) + fripf_t *frp; + fripf4_t *frp4; +{ + + ipf_v5iptov4(&frp->fri_ip, &frp4->fri_ip); + ipf_v5iptov4(&frp->fri_mip, &frp4->fri_mip); + frp4->fri_icmpm = frp->fri_icmpm; + frp4->fri_icmp = frp->fri_icmp; + frp4->fri_tuc.ftu_tcpfm = frp->fri_tuc.ftu_tcpfm; + frp4->fri_tuc.ftu_tcpf = frp->fri_tuc.ftu_tcpf; + ipfv5tuctov4(&frp->fri_tuc, &frp4->fri_tuc); + frp4->fri_satype = frp->fri_satype; + frp4->fri_datype = frp->fri_datype; + frp4->fri_sifpidx = frp->fri_sifpidx; + frp4->fri_difpidx = frp->fri_difpidx; +} + + +/* ------------------------------------------------------------------------ */ +/* ipf_in_compat is the first of two service routines. It is responsible for*/ +/* converting data structures from user space into what's required by the */ +/* kernel module. */ +/* ------------------------------------------------------------------------ */ +int +ipf_in_compat(softc, obj, ptr, size) + ipf_main_softc_t *softc; + ipfobj_t *obj; + void *ptr; + int size; +{ + int error; + int sz; + + IPFERROR(140000); + error = EINVAL; + + switch (obj->ipfo_type) + { + default : + break; + + case IPFOBJ_FRENTRY : + if (obj->ipfo_rev >= 4013400) { + frentry_4_1_34_t *old; + + KMALLOC(old, frentry_4_1_34_t *); + if (old == NULL) { + IPFERROR(140001); + error = ENOMEM; + break; + } + error = COPYIN(obj->ipfo_ptr, old, sizeof(*old)); + if (error == 0) { + if (old->fr_type != FR_T_NONE && + old->fr_type != FR_T_IPF) { + IPFERROR(140002); + error = EINVAL; + KFREE(old); + break; + } + frentry_4_1_34_to_current(softc, old, + ptr, size); + } else { + IPFERROR(140003); + } + KFREE(old); + } else if (obj->ipfo_rev >= 4011600) { + frentry_4_1_16_t *old; + + KMALLOC(old, frentry_4_1_16_t *); + if (old == NULL) { + IPFERROR(140004); + error = ENOMEM; + break; + } + error = COPYIN(obj->ipfo_ptr, old, sizeof(*old)); + if (error == 0) { + if (old->fr_type != FR_T_NONE && + old->fr_type != FR_T_IPF) { + IPFERROR(140005); + error = EINVAL; + KFREE(old); + break; + } + frentry_4_1_16_to_current(softc, old, + ptr, size); + } else { + IPFERROR(140006); + } + KFREE(old); + } else { + frentry_4_1_0_t *old; + + KMALLOC(old, frentry_4_1_0_t *); + if (old == NULL) { + IPFERROR(140007); + error = ENOMEM; + break; + } + error = COPYIN(obj->ipfo_ptr, old, sizeof(*old)); + if (error == 0) { + if (old->fr_type != FR_T_NONE && + old->fr_type != FR_T_IPF) { + IPFERROR(140008); + error = EINVAL; + KFREE(old); + break; + } + frentry_4_1_0_to_current(softc, old, ptr, size); + } else { + IPFERROR(140009); + } + KFREE(old); + } + break; + + case IPFOBJ_IPFSTAT : + if (obj->ipfo_rev >= 4013300) { + friostat_4_1_33_t *old; + + KMALLOC(old, friostat_4_1_33_t *); + if (old == NULL) { + IPFERROR(140010); + error = ENOMEM; + break; + } + error = COPYIN(obj->ipfo_ptr, old, sizeof(*old)); + if (error == 0) { + friostat_4_1_33_to_current(old, ptr); + } else { + IPFERROR(140011); + } + } else { + friostat_4_1_0_t *old; + + KMALLOC(old, friostat_4_1_0_t *); + if (old == NULL) { + IPFERROR(140012); + error = ENOMEM; + break; + } + error = COPYIN(obj->ipfo_ptr, old, sizeof(*old)); + if (error == 0) { + friostat_4_1_0_to_current(old, ptr); + } else { + IPFERROR(140013); + } + } + break; + + case IPFOBJ_IPFINFO : /* unused */ + break; + + case IPFOBJ_IPNAT : + if (obj->ipfo_rev >= 4011400) { + ipnat_4_1_14_t *old; + + KMALLOC(old, ipnat_4_1_14_t *); + if (old == NULL) { + IPFERROR(140014); + error = ENOMEM; + break; + } + error = COPYIN(obj->ipfo_ptr, old, sizeof(*old)); + if (error == 0) { + ipnat_4_1_14_to_current(old, ptr, size); + } else { + IPFERROR(140015); + } + KFREE(old); + } else { + ipnat_4_1_0_t *old; + + KMALLOC(old, ipnat_4_1_0_t *); + if (old == NULL) { + IPFERROR(140016); + error = ENOMEM; + break; + } + error = COPYIN(obj->ipfo_ptr, old, sizeof(*old)); + if (error == 0) { + ipnat_4_1_0_to_current(old, ptr, size); + } else { + IPFERROR(140017); + } + KFREE(old); + } + break; + + case IPFOBJ_NATSTAT : + /* + * Statistics are not copied in. + */ + break; + + case IPFOBJ_NATSAVE : + if (obj->ipfo_rev >= 4011600) { + nat_save_4_1_16_t *old16; + + KMALLOC(old16, nat_save_4_1_16_t *); + if (old16 == NULL) { + IPFERROR(140018); + error = ENOMEM; + break; + } + error = COPYIN(obj->ipfo_ptr, old16, sizeof(*old16)); + if (error == 0) { + nat_save_4_1_16_to_current(softc, old16, ptr); + } else { + IPFERROR(140019); + } + KFREE(old16); + } else if (obj->ipfo_rev >= 4011400) { + nat_save_4_1_14_t *old14; + + KMALLOC(old14, nat_save_4_1_14_t *); + if (old14 == NULL) { + IPFERROR(140020); + error = ENOMEM; + break; + } + error = COPYIN(obj->ipfo_ptr, old14, sizeof(*old14)); + if (error == 0) { + nat_save_4_1_14_to_current(softc, old14, ptr); + } else { + IPFERROR(140021); + } + KFREE(old14); + } else if (obj->ipfo_rev >= 4010300) { + nat_save_4_1_3_t *old3; + + KMALLOC(old3, nat_save_4_1_3_t *); + if (old3 == NULL) { + IPFERROR(140022); + error = ENOMEM; + break; + } + error = COPYIN(obj->ipfo_ptr, old3, sizeof(*old3)); + if (error == 0) { + nat_save_4_1_3_to_current(softc, old3, ptr); + } else { + IPFERROR(140023); + } + KFREE(old3); + } + break; + + case IPFOBJ_STATESAVE : + if (obj->ipfo_rev >= 4013400) { + ipstate_save_4_1_34_t *old; + + KMALLOC(old, ipstate_save_4_1_34_t *); + if (old == NULL) { + IPFERROR(140024); + error = ENOMEM; + break; + } + error = COPYIN(obj->ipfo_ptr, old, sizeof(*old)); + if (error != 0) { + IPFERROR(140025); + } + KFREE(old); + } else if (obj->ipfo_rev >= 4011600) { + ipstate_save_4_1_16_t *old; + + KMALLOC(old, ipstate_save_4_1_16_t *); + if (old == NULL) { + IPFERROR(140026); + error = ENOMEM; + break; + } + error = COPYIN(obj->ipfo_ptr, old, sizeof(*old)); + if (error != 0) { + IPFERROR(140027); + } + KFREE(old); + } else { + ipstate_save_4_1_0_t *old; + + KMALLOC(old, ipstate_save_4_1_0_t *); + if (old == NULL) { + IPFERROR(140028); + error = ENOMEM; + break; + } + error = COPYIN(obj->ipfo_ptr, old, sizeof(*old)); + if (error != 0) { + IPFERROR(140029); + } + KFREE(old); + } + break; + + case IPFOBJ_IPSTATE : + /* + * This structure is not copied in by itself. + */ + break; + + case IPFOBJ_STATESTAT : + /* + * Statistics are not copied in. + */ + break; + + case IPFOBJ_FRAUTH : + if (obj->ipfo_rev >= 4013200) { + frauth_4_1_32_t *old32; + + KMALLOC(old32, frauth_4_1_32_t *); + if (old32 == NULL) { + IPFERROR(140030); + error = ENOMEM; + break; + } + error = COPYIN(obj->ipfo_ptr, old32, sizeof(*old32)); + if (error == 0) { + frauth_4_1_32_to_current(old32, ptr); + } else { + IPFERROR(140031); + } + KFREE(old32); + } else if (obj->ipfo_rev >= 4012900) { + frauth_4_1_29_t *old29; + + KMALLOC(old29, frauth_4_1_29_t *); + if (old29 == NULL) { + IPFERROR(140032); + error = ENOMEM; + break; + } + error = COPYIN(obj->ipfo_ptr, old29, sizeof(*old29)); + if (error == 0) { + frauth_4_1_29_to_current(old29, ptr); + } else { + IPFERROR(140033); + } + KFREE(old29); + } else if (obj->ipfo_rev >= 4012400) { + frauth_4_1_24_t *old24; + + KMALLOC(old24, frauth_4_1_24_t *); + if (old24 == NULL) { + IPFERROR(140034); + error = ENOMEM; + break; + } + error = COPYIN(obj->ipfo_ptr, old24, sizeof(*old24)); + if (error == 0) { + frauth_4_1_24_to_current(old24, ptr); + } else { + IPFERROR(140035); + } + KFREE(old24); + } else if (obj->ipfo_rev >= 4012300) { + frauth_4_1_23_t *old23; + + KMALLOC(old23, frauth_4_1_23_t *); + if (old23 == NULL) { + IPFERROR(140036); + error = ENOMEM; + break; + } + error = COPYIN(obj->ipfo_ptr, old23, sizeof(*old23)); + if (error == 0) + frauth_4_1_23_to_current(old23, ptr); + KFREE(old23); + } else if (obj->ipfo_rev >= 4011100) { + frauth_4_1_11_t *old11; + + KMALLOC(old11, frauth_4_1_11_t *); + if (old11 == NULL) { + IPFERROR(140037); + error = ENOMEM; + break; + } + error = COPYIN(obj->ipfo_ptr, old11, sizeof(*old11)); + if (error == 0) { + frauth_4_1_11_to_current(old11, ptr); + } else { + IPFERROR(140038); + } + KFREE(old11); + } + break; + + case IPFOBJ_NAT : + if (obj->ipfo_rev >= 4011400) { + sz = sizeof(nat_4_1_14_t); + } else if (obj->ipfo_rev >= 4010300) { + sz = sizeof(nat_4_1_3_t); + } else { + break; + } + bzero(ptr, sizeof(nat_t)); + error = COPYIN(obj->ipfo_ptr, ptr, sz); + if (error != 0) { + IPFERROR(140039); + } + break; + + case IPFOBJ_FRIPF : + if (obj->ipfo_rev < 5000000) { + fripf4_t *old; + + KMALLOC(old, fripf4_t *); + if (old == NULL) { + IPFERROR(140040); + error = ENOMEM; + break; + } + error = COPYIN(obj->ipfo_ptr, old, sizeof(*old)); + if (error == 0) { + ipf_v4fripftov5(old, ptr); + } else { + IPFERROR(140041); + } + KFREE(old); + } + break; + } + + return error; +} +/* ------------------------------------------------------------------------ */ + + +/* + * flags is v4 flags, returns v5 flags. + */ +static int +fr_frflags4to5(flags) + u_32_t flags; +{ + u_32_t nflags = 0; + + switch (flags & 0xf) { + case 0x0 : + nflags |= FR_CALL; + break; + case 0x1 : + nflags |= FR_BLOCK; + break; + case 0x2 : + nflags |= FR_PASS; + break; + case 0x3 : + nflags |= FR_AUTH; + break; + case 0x4 : + nflags |= FR_PREAUTH; + break; + case 0x5 : + nflags |= FR_ACCOUNT; + break; + case 0x6 : + nflags |= FR_SKIP; + break; + default : + break; + } + + if (flags & 0x00010) + nflags |= FR_LOG; + if (flags & 0x00020) + nflags |= FR_CALLNOW; + if (flags & 0x00080) + nflags |= FR_NOTSRCIP; + if (flags & 0x00040) + nflags |= FR_NOTDSTIP; + if (flags & 0x00100) + nflags |= FR_QUICK; + if (flags & 0x00200) + nflags |= FR_KEEPFRAG; + if (flags & 0x00400) + nflags |= FR_KEEPSTATE; + if (flags & 0x00800) + nflags |= FR_FASTROUTE; + if (flags & 0x01000) + nflags |= FR_RETRST; + if (flags & 0x02000) + nflags |= FR_RETICMP; + if (flags & 0x03000) + nflags |= FR_FAKEICMP; + if (flags & 0x04000) + nflags |= FR_OUTQUE; + if (flags & 0x08000) + nflags |= FR_INQUE; + if (flags & 0x10000) + nflags |= FR_LOGBODY; + if (flags & 0x20000) + nflags |= FR_LOGFIRST; + if (flags & 0x40000) + nflags |= FR_LOGORBLOCK; + if (flags & 0x100000) + nflags |= FR_FRSTRICT; + if (flags & 0x200000) + nflags |= FR_STSTRICT; + if (flags & 0x400000) + nflags |= FR_NEWISN; + if (flags & 0x800000) + nflags |= FR_NOICMPERR; + if (flags & 0x1000000) + nflags |= FR_STATESYNC; + if (flags & 0x8000000) + nflags |= FR_NOMATCH; + if (flags & 0x40000000) + nflags |= FR_COPIED; + if (flags & 0x80000000) + nflags |= FR_INACTIVE; + + return nflags; +} + +static void +frentry_4_1_34_to_current(softc, old, current, size) + ipf_main_softc_t *softc; + frentry_4_1_34_t *old; + void *current; + int size; +{ + frentry_t *fr = (frentry_t *)current; + + fr->fr_comment = -1; + fr->fr_ref = old->fr_ref; + fr->fr_statecnt = old->fr_statecnt; + fr->fr_hits = old->fr_hits; + fr->fr_bytes = old->fr_bytes; + fr->fr_lastpkt.tv_sec = old->fr_lastpkt.tv_sec; + fr->fr_lastpkt.tv_usec = old->fr_lastpkt.tv_usec; + bcopy(&old->fr_dun, &fr->fr_dun, sizeof(old->fr_dun)); + fr->fr_func = old->fr_func; + fr->fr_dsize = old->fr_dsize; + fr->fr_pps = old->fr_pps; + fr->fr_statemax = old->fr_statemax; + fr->fr_flineno = old->fr_flineno; + fr->fr_type = old->fr_type; + fr->fr_flags = fr_frflags4to5(old->fr_flags); + fr->fr_logtag = old->fr_logtag; + fr->fr_collect = old->fr_collect; + fr->fr_arg = old->fr_arg; + fr->fr_loglevel = old->fr_loglevel; + fr->fr_age[0] = old->fr_age[0]; + fr->fr_age[1] = old->fr_age[1]; + fr->fr_tifs[0].fd_ip6 = old->fr_tifs[0].ofd_ip6; + fr->fr_tifs[0].fd_type = FRD_NORMAL; + fr->fr_tifs[1].fd_ip6 = old->fr_tifs[1].ofd_ip6; + fr->fr_tifs[1].fd_type = FRD_NORMAL; + fr->fr_dif.fd_ip6 = old->fr_dif.ofd_ip6; + fr->fr_dif.fd_type = FRD_NORMAL; + if (old->fr_v == 4) + fr->fr_family = AF_INET; + if (old->fr_v == 6) + fr->fr_family = AF_INET6; + fr->fr_icode = old->fr_icode; + fr->fr_cksum = old->fr_cksum; + fr->fr_namelen = 0; + fr->fr_ifnames[0] = -1; + fr->fr_ifnames[1] = -1; + fr->fr_ifnames[2] = -1; + fr->fr_ifnames[3] = -1; + fr->fr_dif.fd_name = -1; + fr->fr_tifs[0].fd_name = -1; + fr->fr_tifs[1].fd_name = -1; + fr->fr_group = -1; + fr->fr_grhead = -1; + fr->fr_icmphead = -1; + if (size == 0) { + fr->fr_size = sizeof(*fr) + LIFNAMSIZ * 7 + FR_GROUPLEN * 2; + fr->fr_size += sizeof(fripf_t) + 16; + fr->fr_size += 9; /* room for \0's */ + } else { + char *names = fr->fr_names; + int nlen = fr->fr_namelen; + + fr->fr_size = size; + if (old->fr_ifnames[0][0] != '\0') { + fr->fr_ifnames[0] = nlen; + nlen = ipf_addfrstr(names, nlen, old->fr_ifnames[0], + LIFNAMSIZ); + } + if (old->fr_ifnames[1][0] != '\0') { + fr->fr_ifnames[1] = nlen; + nlen = ipf_addfrstr(names, nlen, old->fr_ifnames[1], + LIFNAMSIZ); + } + if (old->fr_ifnames[2][0] != '\0') { + fr->fr_ifnames[2] = nlen; + nlen = ipf_addfrstr(names, nlen, old->fr_ifnames[2], + LIFNAMSIZ); + } + if (old->fr_ifnames[3][0] != '\0') { + fr->fr_ifnames[3] = nlen; + nlen = ipf_addfrstr(names, nlen, old->fr_ifnames[3], + LIFNAMSIZ); + } + if (old->fr_tifs[0].fd_ifname[0] != '\0') { + fr->fr_tifs[0].fd_name = nlen; + nlen = ipf_addfrstr(names, nlen, + old->fr_tifs[0].fd_ifname, + LIFNAMSIZ); + } + if (old->fr_tifs[1].fd_ifname[0] != '\0') { + fr->fr_tifs[1].fd_name = nlen; + nlen = ipf_addfrstr(names, nlen, + old->fr_tifs[1].fd_ifname, + LIFNAMSIZ); + } + if (old->fr_dif.fd_ifname[0] != '\0') { + fr->fr_dif.fd_name = nlen; + nlen = ipf_addfrstr(names, nlen, + old->fr_dif.fd_ifname, LIFNAMSIZ); + } + if (old->fr_group[0] != '\0') { + fr->fr_group = nlen; + nlen = ipf_addfrstr(names, nlen, + old->fr_group, LIFNAMSIZ); + } + if (old->fr_grhead[0] != '\0') { + fr->fr_grhead = nlen; + nlen = ipf_addfrstr(names, nlen, + old->fr_grhead, LIFNAMSIZ); + } + fr->fr_namelen = nlen; + + if (old->fr_type == FR_T_IPF) { + int offset = fr->fr_namelen; + ipfobj_t obj; + int error; + + obj.ipfo_type = IPFOBJ_FRIPF; + obj.ipfo_rev = 4010100; + obj.ipfo_ptr = old->fr_data; + + if ((offset & 7) != 0) + offset += 8 - (offset & 7); + error = ipf_in_compat(softc, &obj, + fr->fr_names + offset, 0); + if (error == 0) { + fr->fr_data = fr->fr_names + offset; + fr->fr_dsize = sizeof(fripf_t); + } + } + } +} + +static void +frentry_4_1_16_to_current(softc, old, current, size) + ipf_main_softc_t *softc; + frentry_4_1_16_t *old; + void *current; + int size; +{ + frentry_t *fr = (frentry_t *)current; + + fr->fr_comment = -1; + fr->fr_ref = old->fr_ref; + fr->fr_statecnt = old->fr_statecnt; + fr->fr_hits = old->fr_hits; + fr->fr_bytes = old->fr_bytes; + fr->fr_lastpkt.tv_sec = old->fr_lastpkt.tv_sec; + fr->fr_lastpkt.tv_usec = old->fr_lastpkt.tv_usec; + bcopy(&old->fr_dun, &fr->fr_dun, sizeof(old->fr_dun)); + fr->fr_func = old->fr_func; + fr->fr_dsize = old->fr_dsize; + fr->fr_pps = old->fr_pps; + fr->fr_statemax = old->fr_statemax; + fr->fr_flineno = old->fr_flineno; + fr->fr_type = old->fr_type; + fr->fr_flags = fr_frflags4to5(old->fr_flags); + fr->fr_logtag = old->fr_logtag; + fr->fr_collect = old->fr_collect; + fr->fr_arg = old->fr_arg; + fr->fr_loglevel = old->fr_loglevel; + fr->fr_age[0] = old->fr_age[0]; + fr->fr_age[1] = old->fr_age[1]; + fr->fr_tifs[0].fd_ip6 = old->fr_tifs[0].ofd_ip6; + fr->fr_tifs[0].fd_type = FRD_NORMAL; + fr->fr_tifs[1].fd_ip6 = old->fr_tifs[1].ofd_ip6; + fr->fr_tifs[1].fd_type = FRD_NORMAL; + fr->fr_dif.fd_ip6 = old->fr_dif.ofd_ip6; + fr->fr_dif.fd_type = FRD_NORMAL; + if (old->fr_v == 4) + fr->fr_family = AF_INET; + if (old->fr_v == 6) + fr->fr_family = AF_INET6; + fr->fr_icode = old->fr_icode; + fr->fr_cksum = old->fr_cksum; + fr->fr_namelen = 0; + fr->fr_ifnames[0] = -1; + fr->fr_ifnames[1] = -1; + fr->fr_ifnames[2] = -1; + fr->fr_ifnames[3] = -1; + fr->fr_dif.fd_name = -1; + fr->fr_tifs[0].fd_name = -1; + fr->fr_tifs[1].fd_name = -1; + fr->fr_group = -1; + fr->fr_grhead = -1; + fr->fr_icmphead = -1; + if (size == 0) { + fr->fr_size = sizeof(*fr) + LIFNAMSIZ * 7 + FR_GROUPLEN * 2; + fr->fr_size += 9; /* room for \0's */ + } else { + char *names = fr->fr_names; + int nlen = fr->fr_namelen; + + fr->fr_size = size; + if (old->fr_ifnames[0][0] != '\0') { + fr->fr_ifnames[0] = nlen; + nlen = ipf_addfrstr(names, nlen, old->fr_ifnames[0], + LIFNAMSIZ); + } + if (old->fr_ifnames[1][0] != '\0') { + fr->fr_ifnames[1] = nlen; + nlen = ipf_addfrstr(names, nlen, old->fr_ifnames[1], + LIFNAMSIZ); + } + if (old->fr_ifnames[2][0] != '\0') { + fr->fr_ifnames[2] = nlen; + nlen = ipf_addfrstr(names, nlen, old->fr_ifnames[2], + LIFNAMSIZ); + } + if (old->fr_ifnames[3][0] != '\0') { + fr->fr_ifnames[3] = nlen; + nlen = ipf_addfrstr(names, nlen, old->fr_ifnames[3], + LIFNAMSIZ); + } + if (old->fr_tifs[0].fd_ifname[0] != '\0') { + fr->fr_tifs[0].fd_name = nlen; + nlen = ipf_addfrstr(names, nlen, + old->fr_tifs[0].fd_ifname, + LIFNAMSIZ); + } + if (old->fr_tifs[1].fd_ifname[0] != '\0') { + fr->fr_tifs[1].fd_name = nlen; + nlen = ipf_addfrstr(names, nlen, + old->fr_tifs[1].fd_ifname, + LIFNAMSIZ); + } + if (old->fr_dif.fd_ifname[0] != '\0') { + fr->fr_dif.fd_name = nlen; + nlen = ipf_addfrstr(names, nlen, + old->fr_dif.fd_ifname, LIFNAMSIZ); + } + if (old->fr_group[0] != '\0') { + fr->fr_group = nlen; + nlen = ipf_addfrstr(names, nlen, + old->fr_group, LIFNAMSIZ); + } + if (old->fr_grhead[0] != '\0') { + fr->fr_grhead = nlen; + nlen = ipf_addfrstr(names, nlen, + old->fr_grhead, LIFNAMSIZ); + } + fr->fr_namelen = nlen; + + if (old->fr_type == FR_T_IPF) { + int offset = fr->fr_namelen; + ipfobj_t obj; + int error; + + obj.ipfo_type = IPFOBJ_FRIPF; + obj.ipfo_rev = 4010100; + obj.ipfo_ptr = old->fr_data; + + if ((offset & 7) != 0) + offset += 8 - (offset & 7); + error = ipf_in_compat(softc, &obj, + fr->fr_names + offset, 0); + if (error == 0) { + fr->fr_data = fr->fr_names + offset; + fr->fr_dsize = sizeof(fripf_t); + } + } + } +} + + +static void +frentry_4_1_0_to_current(softc, old, current, size) + ipf_main_softc_t *softc; + frentry_4_1_0_t *old; + void *current; + int size; +{ + frentry_t *fr = (frentry_t *)current; + + fr->fr_size = sizeof(*fr); + fr->fr_comment = -1; + fr->fr_ref = old->fr_ref; + fr->fr_statecnt = old->fr_statecnt; + fr->fr_hits = old->fr_hits; + fr->fr_bytes = old->fr_bytes; + fr->fr_lastpkt.tv_sec = old->fr_lastpkt.tv_sec; + fr->fr_lastpkt.tv_usec = old->fr_lastpkt.tv_usec; + bcopy(&old->fr_dun, &fr->fr_dun, sizeof(old->fr_dun)); + fr->fr_func = old->fr_func; + fr->fr_dsize = old->fr_dsize; + fr->fr_pps = old->fr_pps; + fr->fr_statemax = old->fr_statemax; + fr->fr_flineno = old->fr_flineno; + fr->fr_type = old->fr_type; + fr->fr_flags = fr_frflags4to5(old->fr_flags); + fr->fr_logtag = old->fr_logtag; + fr->fr_collect = old->fr_collect; + fr->fr_arg = old->fr_arg; + fr->fr_loglevel = old->fr_loglevel; + fr->fr_age[0] = old->fr_age[0]; + fr->fr_age[1] = old->fr_age[1]; + fr->fr_tifs[0].fd_ip6 = old->fr_tifs[0].ofd_ip6; + fr->fr_tifs[0].fd_type = FRD_NORMAL; + fr->fr_tifs[1].fd_ip6 = old->fr_tifs[1].ofd_ip6; + fr->fr_tifs[1].fd_type = FRD_NORMAL; + fr->fr_dif.fd_ip6 = old->fr_dif.ofd_ip6; + fr->fr_dif.fd_type = FRD_NORMAL; + if (old->fr_v == 4) + fr->fr_family = AF_INET; + if (old->fr_v == 6) + fr->fr_family = AF_INET6; + fr->fr_icode = old->fr_icode; + fr->fr_cksum = old->fr_cksum; + fr->fr_namelen = 0; + fr->fr_ifnames[0] = -1; + fr->fr_ifnames[1] = -1; + fr->fr_ifnames[2] = -1; + fr->fr_ifnames[3] = -1; + fr->fr_dif.fd_name = -1; + fr->fr_tifs[0].fd_name = -1; + fr->fr_tifs[1].fd_name = -1; + fr->fr_group = -1; + fr->fr_grhead = -1; + fr->fr_icmphead = -1; + if (size == 0) { + fr->fr_size = sizeof(*fr) + LIFNAMSIZ * 7 + FR_GROUPLEN * 2; + fr->fr_size += 9; /* room for \0's */ + } else { + char *names = fr->fr_names; + int nlen = fr->fr_namelen; + + fr->fr_size = size; + if (old->fr_ifnames[0][0] != '\0') { + fr->fr_ifnames[0] = nlen; + nlen = ipf_addfrstr(names, nlen, old->fr_ifnames[0], + LIFNAMSIZ); + } + if (old->fr_ifnames[1][0] != '\0') { + fr->fr_ifnames[1] = nlen; + nlen = ipf_addfrstr(names, nlen, old->fr_ifnames[1], + LIFNAMSIZ); + } + if (old->fr_ifnames[2][0] != '\0') { + fr->fr_ifnames[2] = nlen; + nlen = ipf_addfrstr(names, nlen, old->fr_ifnames[2], + LIFNAMSIZ); + } + if (old->fr_ifnames[3][0] != '\0') { + fr->fr_ifnames[3] = nlen; + nlen = ipf_addfrstr(names, nlen, old->fr_ifnames[3], + LIFNAMSIZ); + } + if (old->fr_tifs[0].fd_ifname[0] != '\0') { + fr->fr_tifs[0].fd_name = nlen; + nlen = ipf_addfrstr(names, nlen, + old->fr_tifs[0].fd_ifname, + LIFNAMSIZ); + } + if (old->fr_tifs[1].fd_ifname[0] != '\0') { + fr->fr_tifs[1].fd_name = nlen; + nlen = ipf_addfrstr(names, nlen, + old->fr_tifs[1].fd_ifname, + LIFNAMSIZ); + } + if (old->fr_dif.fd_ifname[0] != '\0') { + fr->fr_dif.fd_name = nlen; + nlen = ipf_addfrstr(names, nlen, + old->fr_dif.fd_ifname, LIFNAMSIZ); + } + if (old->fr_group[0] != '\0') { + fr->fr_group = nlen; + nlen = ipf_addfrstr(names, nlen, + old->fr_group, LIFNAMSIZ); + } + if (old->fr_grhead[0] != '\0') { + fr->fr_grhead = nlen; + nlen = ipf_addfrstr(names, nlen, + old->fr_grhead, LIFNAMSIZ); + } + fr->fr_namelen = nlen; + + if (old->fr_type == FR_T_IPF) { + int offset = fr->fr_namelen; + ipfobj_t obj; + int error; + + obj.ipfo_type = IPFOBJ_FRIPF; + obj.ipfo_rev = 4010100; + obj.ipfo_ptr = old->fr_data; + + if ((offset & 7) != 0) + offset += 8 - (offset & 7); + offset += 8 - (offset & 7); + error = ipf_in_compat(softc, &obj, + fr->fr_names + offset, 0); + if (error == 0) { + fr->fr_data = fr->fr_names + offset; + fr->fr_dsize = sizeof(fripf_t); + } + } + } +} + + +static void +friostat_4_1_33_to_current(old, current) + friostat_4_1_33_t *old; + void *current; +{ + friostat_t *fiop = (friostat_t *)current; + + bcopy(&old->of_st[0], &fiop->f_st[0].fr_pass, sizeof(old->of_st[0])); + bcopy(&old->of_st[1], &fiop->f_st[1].fr_pass, sizeof(old->of_st[1])); + + fiop->f_ipf[0][0] = old->f_ipf[0][0]; + fiop->f_ipf[0][1] = old->f_ipf[0][1]; + fiop->f_ipf[1][0] = old->f_ipf[1][0]; + fiop->f_ipf[1][1] = old->f_ipf[1][1]; + fiop->f_acct[0][0] = old->f_acct[0][0]; + fiop->f_acct[0][1] = old->f_acct[0][1]; + fiop->f_acct[1][0] = old->f_acct[1][0]; + fiop->f_acct[1][1] = old->f_acct[1][1]; + fiop->f_auth = fiop->f_auth; + bcopy(&old->f_groups, &fiop->f_groups, sizeof(old->f_groups)); + bcopy(&old->f_froute, &fiop->f_froute, sizeof(old->f_froute)); + fiop->f_ticks = old->f_ticks; + bcopy(&old->f_locks, &fiop->f_locks, sizeof(old->f_locks)); + fiop->f_defpass = old->f_defpass; + fiop->f_active = old->f_active; + fiop->f_running = old->f_running; + fiop->f_logging = old->f_logging; + fiop->f_features = old->f_features; + bcopy(old->f_version, fiop->f_version, sizeof(old->f_version)); +} + + +static void +friostat_4_1_0_to_current(old, current) + friostat_4_1_0_t *old; + void *current; +{ + friostat_t *fiop = (friostat_t *)current; + + bcopy(&old->of_st[0], &fiop->f_st[0].fr_pass, sizeof(old->of_st[0])); + bcopy(&old->of_st[1], &fiop->f_st[1].fr_pass, sizeof(old->of_st[1])); + + fiop->f_ipf[0][0] = old->f_ipf[0][0]; + fiop->f_ipf[0][1] = old->f_ipf[0][1]; + fiop->f_ipf[1][0] = old->f_ipf[1][0]; + fiop->f_ipf[1][1] = old->f_ipf[1][1]; + fiop->f_acct[0][0] = old->f_acct[0][0]; + fiop->f_acct[0][1] = old->f_acct[0][1]; + fiop->f_acct[1][0] = old->f_acct[1][0]; + fiop->f_acct[1][1] = old->f_acct[1][1]; + fiop->f_auth = fiop->f_auth; + bcopy(&old->f_groups, &fiop->f_groups, sizeof(old->f_groups)); + bcopy(&old->f_froute, &fiop->f_froute, sizeof(old->f_froute)); + fiop->f_ticks = old->f_ticks; + bcopy(&old->f_locks, &fiop->f_locks, sizeof(old->f_locks)); + fiop->f_defpass = old->f_defpass; + fiop->f_active = old->f_active; + fiop->f_running = old->f_running; + fiop->f_logging = old->f_logging; + fiop->f_features = old->f_features; + bcopy(old->f_version, fiop->f_version, sizeof(old->f_version)); +} + + +static void +ipnat_4_1_14_to_current(old, current, size) + ipnat_4_1_14_t *old; + void *current; + int size; +{ + ipnat_t *np = (ipnat_t *)current; + + np->in_space = old->in_space; + np->in_hv[0] = old->in_hv; + np->in_hv[1] = old->in_hv; + np->in_flineno = old->in_flineno; + if (old->in_redir == NAT_REDIRECT) + np->in_dpnext = old->in_pnext; + else + np->in_spnext = old->in_pnext; + np->in_v[0] = old->in_v; + np->in_v[1] = old->in_v; + np->in_flags = old->in_flags; + np->in_mssclamp = old->in_mssclamp; + np->in_age[0] = old->in_age[0]; + np->in_age[1] = old->in_age[1]; + np->in_redir = old->in_redir; + np->in_pr[0] = old->in_p; + np->in_pr[1] = old->in_p; + if (np->in_redir == NAT_REDIRECT) { + np->in_ndst.na_nextaddr = old->in_next6; + np->in_ndst.na_addr[0] = old->in_in[0]; + np->in_ndst.na_addr[1] = old->in_in[1]; + np->in_ndst.na_atype = FRI_NORMAL; + np->in_odst.na_addr[0] = old->in_out[0]; + np->in_odst.na_addr[1] = old->in_out[1]; + np->in_odst.na_atype = FRI_NORMAL; + np->in_osrc.na_addr[0] = old->in_src[0]; + np->in_osrc.na_addr[1] = old->in_src[1]; + np->in_osrc.na_atype = FRI_NORMAL; + } else { + np->in_nsrc.na_nextaddr = old->in_next6; + np->in_nsrc.na_addr[0] = old->in_out[0]; + np->in_nsrc.na_addr[1] = old->in_out[1]; + np->in_nsrc.na_atype = FRI_NORMAL; + np->in_osrc.na_addr[0] = old->in_in[0]; + np->in_osrc.na_addr[1] = old->in_in[1]; + np->in_osrc.na_atype = FRI_NORMAL; + np->in_odst.na_addr[0] = old->in_src[0]; + np->in_odst.na_addr[1] = old->in_src[1]; + np->in_odst.na_atype = FRI_NORMAL; + } + ipfv4tuctov5(&old->in_tuc, &np->in_tuc); + if (np->in_redir == NAT_REDIRECT) { + np->in_dpmin = old->in_port[0]; + np->in_dpmax = old->in_port[1]; + } else { + np->in_spmin = old->in_port[0]; + np->in_spmax = old->in_port[1]; + } + np->in_ppip = old->in_ppip; + np->in_ippip = old->in_ippip; + np->in_tag = old->in_tag; + + np->in_namelen = 0; + np->in_plabel = -1; + np->in_ifnames[0] = -1; + np->in_ifnames[1] = -1; + + if (size == 0) { + np->in_size = sizeof(*np); + np->in_size += LIFNAMSIZ * 2 + APR_LABELLEN; + np->in_size += 3; + } else { + int nlen = np->in_namelen; + char *names = np->in_names; + + if (old->in_ifnames[0][0] != '\0') { + np->in_ifnames[0] = nlen; + nlen = ipf_addfrstr(names, nlen, old->in_ifnames[0], + LIFNAMSIZ); + } + if (old->in_ifnames[1][0] != '\0') { + np->in_ifnames[0] = nlen; + nlen = ipf_addfrstr(names, nlen, old->in_ifnames[1], + LIFNAMSIZ); + } + if (old->in_plabel[0] != '\0') { + np->in_plabel = nlen; + nlen = ipf_addfrstr(names, nlen, old->in_plabel, + LIFNAMSIZ); + } + np->in_namelen = nlen; + np->in_size = size; + } +} + + +static void +ipnat_4_1_0_to_current(old, current, size) + ipnat_4_1_0_t *old; + void *current; + int size; +{ + ipnat_t *np = (ipnat_t *)current; + + np->in_space = old->in_space; + np->in_hv[0] = old->in_hv; + np->in_hv[1] = old->in_hv; + np->in_flineno = old->in_flineno; + if (old->in_redir == NAT_REDIRECT) + np->in_dpnext = old->in_pnext; + else + np->in_spnext = old->in_pnext; + np->in_v[0] = old->in_v; + np->in_v[1] = old->in_v; + np->in_flags = old->in_flags; + np->in_mssclamp = old->in_mssclamp; + np->in_age[0] = old->in_age[0]; + np->in_age[1] = old->in_age[1]; + np->in_redir = old->in_redir; + np->in_pr[0] = old->in_p; + np->in_pr[1] = old->in_p; + if (np->in_redir == NAT_REDIRECT) { + np->in_ndst.na_nextaddr = old->in_next6; + bcopy(&old->in_in, &np->in_ndst.na_addr, sizeof(old->in_in)); + bcopy(&old->in_out, &np->in_odst.na_addr, sizeof(old->in_out)); + bcopy(&old->in_src, &np->in_osrc.na_addr, sizeof(old->in_src)); + } else { + np->in_nsrc.na_nextaddr = old->in_next6; + bcopy(&old->in_in, &np->in_osrc.na_addr, sizeof(old->in_in)); + bcopy(&old->in_out, &np->in_nsrc.na_addr, sizeof(old->in_out)); + bcopy(&old->in_src, &np->in_odst.na_addr, sizeof(old->in_src)); + } + ipfv4tuctov5(&old->in_tuc, &np->in_tuc); + if (np->in_redir == NAT_REDIRECT) { + np->in_dpmin = old->in_port[0]; + np->in_dpmax = old->in_port[1]; + } else { + np->in_spmin = old->in_port[0]; + np->in_spmax = old->in_port[1]; + } + np->in_ppip = old->in_ppip; + np->in_ippip = old->in_ippip; + bcopy(&old->in_tag, &np->in_tag, sizeof(np->in_tag)); + + np->in_namelen = 0; + np->in_plabel = -1; + np->in_ifnames[0] = -1; + np->in_ifnames[1] = -1; + + if (size == 0) { + np->in_size = sizeof(*np); + np->in_size += LIFNAMSIZ * 2 + APR_LABELLEN; + np->in_size += 3; + } else { + int nlen = np->in_namelen; + char *names = np->in_names; + + if (old->in_ifnames[0][0] != '\0') { + np->in_ifnames[0] = nlen; + nlen = ipf_addfrstr(names, nlen, old->in_ifnames[0], + LIFNAMSIZ); + } + if (old->in_ifnames[1][0] != '\0') { + np->in_ifnames[0] = nlen; + nlen = ipf_addfrstr(names, nlen, old->in_ifnames[1], + LIFNAMSIZ); + } + if (old->in_plabel[0] != '\0') { + np->in_plabel = nlen; + nlen = ipf_addfrstr(names, nlen, old->in_plabel, + LIFNAMSIZ); + } + np->in_namelen = nlen; + np->in_size = size; + } +} + + +static void +frauth_4_1_32_to_current(old, current) + frauth_4_1_32_t *old; + void *current; +{ + frauth_t *fra = (frauth_t *)current; + + fra->fra_age = old->fra_age; + fra->fra_len = old->fra_len; + fra->fra_index = old->fra_index; + fra->fra_pass = old->fra_pass; + fr_info_4_1_32_to_current(&old->fra_info, &fra->fra_info); + fra->fra_buf = old->fra_buf; + fra->fra_flx = old->fra_flx; +#ifdef MENTAT + fra->fra_q = old->fra_q; + fra->fra_m = old->fra_m; +#endif +} + + +static void +frauth_4_1_29_to_current(old, current) + frauth_4_1_29_t *old; + void *current; +{ + frauth_t *fra = (frauth_t *)current; + + fra->fra_age = old->fra_age; + fra->fra_len = old->fra_len; + fra->fra_index = old->fra_index; + fra->fra_pass = old->fra_pass; + fr_info_4_1_24_to_current(&old->fra_info, &fra->fra_info); + fra->fra_buf = old->fra_buf; + fra->fra_flx = old->fra_flx; +#ifdef MENTAT + fra->fra_q = old->fra_q; + fra->fra_m = old->fra_m; +#endif +} + + +static void +frauth_4_1_24_to_current(old, current) + frauth_4_1_24_t *old; + void *current; +{ + frauth_t *fra = (frauth_t *)current; + + fra->fra_age = old->fra_age; + fra->fra_len = old->fra_len; + fra->fra_index = old->fra_index; + fra->fra_pass = old->fra_pass; + fr_info_4_1_24_to_current(&old->fra_info, &fra->fra_info); + fra->fra_buf = old->fra_buf; +#ifdef MENTAT + fra->fra_q = old->fra_q; + fra->fra_m = old->fra_m; +#endif +} + + +static void +frauth_4_1_23_to_current(old, current) + frauth_4_1_23_t *old; + void *current; +{ + frauth_t *fra = (frauth_t *)current; + + fra->fra_age = old->fra_age; + fra->fra_len = old->fra_len; + fra->fra_index = old->fra_index; + fra->fra_pass = old->fra_pass; + fr_info_4_1_23_to_current(&old->fra_info, &fra->fra_info); + fra->fra_buf = old->fra_buf; +#ifdef MENTAT + fra->fra_q = old->fra_q; + fra->fra_m = old->fra_m; +#endif +} + + +static void +frauth_4_1_11_to_current(old, current) + frauth_4_1_11_t *old; + void *current; +{ + frauth_t *fra = (frauth_t *)current; + + fra->fra_age = old->fra_age; + fra->fra_len = old->fra_len; + fra->fra_index = old->fra_index; + fra->fra_pass = old->fra_pass; + fr_info_4_1_11_to_current(&old->fra_info, &fra->fra_info); + fra->fra_buf = old->fra_buf; +#ifdef MENTAT + fra->fra_q = old->fra_q; + fra->fra_m = old->fra_m; +#endif +} + + +static void +fr_info_4_1_32_to_current(old, current) + fr_info_4_1_32_t *old; + void *current; +{ + fr_info_t *fin = (fr_info_t *)current; + + fin->fin_ifp = old->fin_ifp; + ipf_v4iptov5(&old->fin_fi, &fin->fin_fi); + bcopy(&old->fin_dat, &fin->fin_dat, sizeof(old->fin_dat)); + fin->fin_out = old->fin_out; + fin->fin_rev = old->fin_rev; + fin->fin_hlen = old->fin_hlen; + fin->fin_tcpf = old->ofin_tcpf; + fin->fin_icode = old->fin_icode; + fin->fin_rule = old->fin_rule; + bcopy(old->fin_group, fin->fin_group, sizeof(old->fin_group)); + fin->fin_fr = old->fin_fr; + fin->fin_dp = old->fin_dp; + fin->fin_dlen = old->fin_dlen; + fin->fin_plen = old->fin_plen; + fin->fin_ipoff = old->fin_ipoff; + fin->fin_id = old->fin_id; + fin->fin_off = old->fin_off; + fin->fin_depth = old->fin_depth; + fin->fin_error = old->fin_error; + fin->fin_cksum = old->fin_cksum; + fin->fin_nattag = old->fin_nattag; + fin->fin_ip = old->ofin_ip; + fin->fin_mp = old->fin_mp; + fin->fin_m = old->fin_m; +#ifdef MENTAT + fin->fin_qfm = old->fin_qfm; + fin->fin_qpi = old->fin_qpi; +#endif +#ifdef __sgi + fin->fin_hbuf = old->fin_hbuf; +#endif +} + + +static void +fr_info_4_1_24_to_current(old, current) + fr_info_4_1_24_t *old; + void *current; +{ + fr_info_t *fin = (fr_info_t *)current; + + fin->fin_ifp = old->fin_ifp; + ipf_v4iptov5(&old->fin_fi, &fin->fin_fi); + bcopy(&old->fin_dat, &fin->fin_dat, sizeof(old->fin_dat)); + fin->fin_out = old->fin_out; + fin->fin_rev = old->fin_rev; + fin->fin_hlen = old->fin_hlen; + fin->fin_tcpf = old->ofin_tcpf; + fin->fin_icode = old->fin_icode; + fin->fin_rule = old->fin_rule; + bcopy(old->fin_group, fin->fin_group, sizeof(old->fin_group)); + fin->fin_fr = old->fin_fr; + fin->fin_dp = old->fin_dp; + fin->fin_dlen = old->fin_dlen; + fin->fin_plen = old->fin_plen; + fin->fin_ipoff = old->fin_ipoff; + fin->fin_id = old->fin_id; + fin->fin_off = old->fin_off; + fin->fin_depth = old->fin_depth; + fin->fin_error = old->fin_error; + fin->fin_cksum = old->fin_cksum; + fin->fin_nattag = old->fin_nattag; + fin->fin_ip = old->ofin_ip; + fin->fin_mp = old->fin_mp; + fin->fin_m = old->fin_m; +#ifdef MENTAT + fin->fin_qfm = old->fin_qfm; + fin->fin_qpi = old->fin_qpi; +#endif +#ifdef __sgi + fin->fin_hbuf = old->fin_hbuf; +#endif +} + + +static void +fr_info_4_1_23_to_current(old, current) + fr_info_4_1_23_t *old; + void *current; +{ + fr_info_t *fin = (fr_info_t *)current; + + fin->fin_ifp = old->fin_ifp; + ipf_v4iptov5(&old->fin_fi, &fin->fin_fi); + bcopy(&old->fin_dat, &fin->fin_dat, sizeof(old->fin_dat)); + fin->fin_out = old->fin_out; + fin->fin_rev = old->fin_rev; + fin->fin_hlen = old->fin_hlen; + fin->fin_tcpf = old->ofin_tcpf; + fin->fin_icode = old->fin_icode; + fin->fin_rule = old->fin_rule; + bcopy(old->fin_group, fin->fin_group, sizeof(old->fin_group)); + fin->fin_fr = old->fin_fr; + fin->fin_dp = old->fin_dp; + fin->fin_dlen = old->fin_dlen; + fin->fin_plen = old->fin_plen; + fin->fin_ipoff = old->fin_ipoff; + fin->fin_id = old->fin_id; + fin->fin_off = old->fin_off; + fin->fin_depth = old->fin_depth; + fin->fin_error = old->fin_error; + fin->fin_nattag = old->fin_nattag; + fin->fin_ip = old->ofin_ip; + fin->fin_mp = old->fin_mp; + fin->fin_m = old->fin_m; +#ifdef MENTAT + fin->fin_qfm = old->fin_qfm; + fin->fin_qpi = old->fin_qpi; +#endif +#ifdef __sgi + fin->fin_hbuf = fin->fin_hbuf; +#endif +} + + +static void +fr_info_4_1_11_to_current(old, current) + fr_info_4_1_11_t *old; + void *current; +{ + fr_info_t *fin = (fr_info_t *)current; + + fin->fin_ifp = old->fin_ifp; + ipf_v4iptov5(&old->fin_fi, &fin->fin_fi); + bcopy(&old->fin_dat, &fin->fin_dat, sizeof(old->fin_dat)); + fin->fin_out = old->fin_out; + fin->fin_rev = old->fin_rev; + fin->fin_hlen = old->fin_hlen; + fin->fin_tcpf = old->ofin_tcpf; + fin->fin_icode = old->fin_icode; + fin->fin_rule = old->fin_rule; + bcopy(old->fin_group, fin->fin_group, sizeof(old->fin_group)); + fin->fin_fr = old->fin_fr; + fin->fin_dp = old->fin_dp; + fin->fin_dlen = old->fin_dlen; + fin->fin_plen = old->fin_plen; + fin->fin_ipoff = old->fin_ipoff; + fin->fin_id = old->fin_id; + fin->fin_off = old->fin_off; + fin->fin_depth = old->fin_depth; + fin->fin_error = old->fin_error; + fin->fin_nattag = old->fin_nattag; + fin->fin_ip = old->ofin_ip; + fin->fin_mp = old->fin_mp; + fin->fin_m = old->fin_m; +#ifdef MENTAT + fin->fin_qfm = old->fin_qfm; + fin->fin_qpi = old->fin_qpi; +#endif +#ifdef __sgi + fin->fin_hbuf = fin->fin_hbuf; +#endif +} + + +static void +nat_4_1_3_to_current(nat_4_1_3_t *old, nat_t *current) +{ + bzero((void *)current, sizeof(*current)); + bcopy((void *)old, (void *)current, sizeof(*old)); +} + + +static void +nat_4_1_14_to_current(nat_4_1_14_t *old, nat_t *current) +{ + bzero((void *)current, sizeof(*current)); + bcopy((void *)old, (void *)current, sizeof(*old)); +} + + +static void +nat_save_4_1_16_to_current(softc, old, current) + ipf_main_softc_t *softc; + nat_save_4_1_16_t *old; + void *current; +{ + nat_save_t *nats = (nat_save_t *)current; + + nats->ipn_next = old->ipn_next; + nat_4_1_14_to_current(&old->ipn_nat, &nats->ipn_nat); + bcopy(&old->ipn_ipnat, &nats->ipn_ipnat, sizeof(old->ipn_ipnat)); + frentry_4_1_16_to_current(softc, &old->ipn_fr, &nats->ipn_fr, 0); + nats->ipn_dsize = old->ipn_dsize; + bcopy(old->ipn_data, nats->ipn_data, sizeof(nats->ipn_data)); +} + + +static void +nat_save_4_1_14_to_current(softc, old, current) + ipf_main_softc_t *softc; + nat_save_4_1_14_t *old; + void *current; +{ + nat_save_t *nats = (nat_save_t *)current; + + nats->ipn_next = old->ipn_next; + nat_4_1_14_to_current(&old->ipn_nat, &nats->ipn_nat); + bcopy(&old->ipn_ipnat, &nats->ipn_ipnat, sizeof(old->ipn_ipnat)); + frentry_4_1_0_to_current(softc, &old->ipn_fr, &nats->ipn_fr, 0); + nats->ipn_dsize = old->ipn_dsize; + bcopy(old->ipn_data, nats->ipn_data, sizeof(nats->ipn_data)); +} + + +static void +nat_save_4_1_3_to_current(softc, old, current) + ipf_main_softc_t *softc; + nat_save_4_1_3_t *old; + void *current; +{ + nat_save_t *nats = (nat_save_t *)current; + + nats->ipn_next = old->ipn_next; + nat_4_1_3_to_current(&old->ipn_nat, &nats->ipn_nat); + ipnat_4_1_0_to_current(&old->ipn_ipnat, &nats->ipn_ipnat, 0); + frentry_4_1_0_to_current(softc, &old->ipn_fr, &nats->ipn_fr, 0); + nats->ipn_dsize = old->ipn_dsize; + bcopy(old->ipn_data, nats->ipn_data, sizeof(nats->ipn_data)); +} + + +static void +natstat_current_to_4_1_32(current, old) + void *current; + natstat_4_1_32_t *old; +{ + natstat_t *ns = (natstat_t *)current; + + old->ns_mapped[0] = ns->ns_side[0].ns_translated; + old->ns_mapped[1] = ns->ns_side[1].ns_translated; + old->ns_rules = ns->ns_side[0].ns_inuse + ns->ns_side[1].ns_inuse; + old->ns_added = ns->ns_side[0].ns_added + ns->ns_side[1].ns_added; + old->ns_expire = ns->ns_expire; + old->ns_inuse = ns->ns_side[0].ns_inuse + ns->ns_side[1].ns_inuse; + old->ns_logged = ns->ns_log_ok; + old->ns_logfail = ns->ns_log_fail; + old->ns_memfail = ns->ns_side[0].ns_memfail + ns->ns_side[1].ns_memfail; + old->ns_badnat = ns->ns_side[0].ns_badnat + ns->ns_side[1].ns_badnat; + old->ns_addtrpnt = ns->ns_addtrpnt; + old->ns_table[0] = ns->ns_side[0].ns_table; + old->ns_table[1] = ns->ns_side[1].ns_table; + old->ns_maptable = NULL; + old->ns_list = ns->ns_list; + old->ns_apslist = NULL; + old->ns_wilds = ns->ns_wilds; + old->ns_nattab_sz = ns->ns_nattab_sz; + old->ns_nattab_max = ns->ns_nattab_max; + old->ns_rultab_sz = ns->ns_rultab_sz; + old->ns_rdrtab_sz = ns->ns_rdrtab_sz; + old->ns_trpntab_sz = ns->ns_trpntab_sz; + old->ns_hostmap_sz = 0; + old->ns_instances = ns->ns_instances; + old->ns_maplist = ns->ns_maplist; + old->ns_bucketlen[0] = (u_long *)ns->ns_side[0].ns_bucketlen; + old->ns_bucketlen[1] = (u_long *)ns->ns_side[1].ns_bucketlen; + old->ns_ticks = ns->ns_ticks; + old->ns_orphans = ns->ns_orphans; + old->ns_uncreate[0][0] = ns->ns_side[0].ns_uncreate[0]; + old->ns_uncreate[0][1] = ns->ns_side[0].ns_uncreate[1]; + old->ns_uncreate[1][0] = ns->ns_side[1].ns_uncreate[0]; + old->ns_uncreate[1][1] = ns->ns_side[1].ns_uncreate[1]; +} + + +static void +natstat_current_to_4_1_27(current, old) + void *current; + natstat_4_1_27_t *old; +{ + natstat_t *ns = (natstat_t *)current; + + old->ns_mapped[0] = ns->ns_side[0].ns_translated; + old->ns_mapped[1] = ns->ns_side[1].ns_translated; + old->ns_rules = ns->ns_side[0].ns_inuse + ns->ns_side[1].ns_inuse; + old->ns_added = ns->ns_side[0].ns_added + ns->ns_side[1].ns_added; + old->ns_expire = ns->ns_expire; + old->ns_inuse = ns->ns_side[0].ns_inuse + ns->ns_side[1].ns_inuse; + old->ns_logged = ns->ns_log_ok; + old->ns_logfail = ns->ns_log_fail; + old->ns_memfail = ns->ns_side[0].ns_memfail + ns->ns_side[1].ns_memfail; + old->ns_badnat = ns->ns_side[0].ns_badnat + ns->ns_side[1].ns_badnat; + old->ns_addtrpnt = ns->ns_addtrpnt; + old->ns_table[0] = ns->ns_side[0].ns_table; + old->ns_table[1] = ns->ns_side[1].ns_table; + old->ns_maptable = NULL; + old->ns_list = ns->ns_list; + old->ns_apslist = NULL; + old->ns_wilds = ns->ns_wilds; + old->ns_nattab_sz = ns->ns_nattab_sz; + old->ns_nattab_max = ns->ns_nattab_max; + old->ns_rultab_sz = ns->ns_rultab_sz; + old->ns_rdrtab_sz = ns->ns_rdrtab_sz; + old->ns_trpntab_sz = ns->ns_trpntab_sz; + old->ns_hostmap_sz = 0; + old->ns_instances = ns->ns_instances; + old->ns_maplist = ns->ns_maplist; + old->ns_bucketlen[0] = (u_long *)ns->ns_side[0].ns_bucketlen; + old->ns_bucketlen[1] = (u_long *)ns->ns_side[1].ns_bucketlen; + old->ns_ticks = ns->ns_ticks; + old->ns_orphans = ns->ns_orphans; +} + + +static void +natstat_current_to_4_1_16(current, old) + void *current; + natstat_4_1_16_t *old; +{ + natstat_t *ns = (natstat_t *)current; + + old->ns_mapped[0] = ns->ns_side[0].ns_translated; + old->ns_mapped[1] = ns->ns_side[1].ns_translated; + old->ns_rules = ns->ns_side[0].ns_inuse + ns->ns_side[1].ns_inuse; + old->ns_added = ns->ns_side[0].ns_added + ns->ns_side[1].ns_added; + old->ns_expire = ns->ns_expire; + old->ns_inuse = ns->ns_side[0].ns_inuse + ns->ns_side[1].ns_inuse; + old->ns_logged = ns->ns_log_ok; + old->ns_logfail = ns->ns_log_fail; + old->ns_memfail = ns->ns_side[0].ns_memfail + ns->ns_side[1].ns_memfail; + old->ns_badnat = ns->ns_side[0].ns_badnat + ns->ns_side[1].ns_badnat; + old->ns_addtrpnt = ns->ns_addtrpnt; + old->ns_table[0] = ns->ns_side[0].ns_table; + old->ns_table[1] = ns->ns_side[1].ns_table; + old->ns_maptable = NULL; + old->ns_list = ns->ns_list; + old->ns_apslist = NULL; + old->ns_wilds = ns->ns_wilds; + old->ns_nattab_sz = ns->ns_nattab_sz; + old->ns_nattab_max = ns->ns_nattab_max; + old->ns_rultab_sz = ns->ns_rultab_sz; + old->ns_rdrtab_sz = ns->ns_rdrtab_sz; + old->ns_trpntab_sz = ns->ns_trpntab_sz; + old->ns_hostmap_sz = 0; + old->ns_instances = ns->ns_instances; + old->ns_maplist = ns->ns_maplist; + old->ns_bucketlen[0] = (u_long *)ns->ns_side[0].ns_bucketlen; + old->ns_bucketlen[1] = (u_long *)ns->ns_side[1].ns_bucketlen; + old->ns_ticks = ns->ns_ticks; +} + + +static void +natstat_current_to_4_1_0(current, old) + void *current; + natstat_4_1_0_t *old; +{ + natstat_t *ns = (natstat_t *)current; + + old->ns_mapped[0] = ns->ns_side[0].ns_translated; + old->ns_mapped[1] = ns->ns_side[1].ns_translated; + old->ns_rules = ns->ns_side[0].ns_inuse + ns->ns_side[1].ns_inuse; + old->ns_added = ns->ns_side[0].ns_added + ns->ns_side[1].ns_added; + old->ns_expire = ns->ns_expire; + old->ns_inuse = ns->ns_side[0].ns_inuse + ns->ns_side[1].ns_inuse; + old->ns_logged = ns->ns_log_ok; + old->ns_logfail = ns->ns_log_fail; + old->ns_memfail = ns->ns_side[0].ns_memfail + ns->ns_side[1].ns_memfail; + old->ns_badnat = ns->ns_side[0].ns_badnat + ns->ns_side[1].ns_badnat; + old->ns_addtrpnt = ns->ns_addtrpnt; + old->ns_table[0] = ns->ns_side[0].ns_table; + old->ns_table[1] = ns->ns_side[1].ns_table; + old->ns_maptable = NULL; + old->ns_list = ns->ns_list; + old->ns_apslist = NULL; + old->ns_wilds = ns->ns_wilds; + old->ns_nattab_sz = ns->ns_nattab_sz; + old->ns_nattab_max = ns->ns_nattab_max; + old->ns_rultab_sz = ns->ns_rultab_sz; + old->ns_rdrtab_sz = ns->ns_rdrtab_sz; + old->ns_trpntab_sz = ns->ns_trpntab_sz; + old->ns_hostmap_sz = 0; + old->ns_instances = ns->ns_instances; + old->ns_maplist = ns->ns_maplist; + old->ns_bucketlen[0] = (u_long *)ns->ns_side[0].ns_bucketlen; + old->ns_bucketlen[1] = (u_long *)ns->ns_side[1].ns_bucketlen; +} + + +static void +ipstate_save_current_to_4_1_16(current, old) + void *current; + ipstate_save_4_1_16_t *old; +{ + ipstate_save_t *ips = (ipstate_save_t *)current; + + old->ips_next = ips->ips_next; + ipstate_current_to_4_1_0(&ips->ips_is, &old->ips_is); + frentry_current_to_4_1_16(&ips->ips_fr, &old->ips_fr); +} + + +static void +ipstate_save_current_to_4_1_0(current, old) + void *current; + ipstate_save_4_1_0_t *old; +{ + ipstate_save_t *ips = (ipstate_save_t *)current; + + old->ips_next = ips->ips_next; + ipstate_current_to_4_1_0(&ips->ips_is, &old->ips_is); + frentry_current_to_4_1_0(&ips->ips_fr, &old->ips_fr); +} + + +int +ipf_out_compat(softc, obj, ptr) + ipf_main_softc_t *softc; + ipfobj_t *obj; + void *ptr; +{ + frentry_t *fr; + int error; + + IPFERROR(140042); + error = EINVAL; + + switch (obj->ipfo_type) + { + default : + break; + + case IPFOBJ_FRENTRY : + if (obj->ipfo_rev >= 4013400) { + frentry_4_1_34_t *old; + + KMALLOC(old, frentry_4_1_34_t *); + if (old == NULL) { + IPFERROR(140043); + error = ENOMEM; + break; + } + frentry_current_to_4_1_34(ptr, old); + error = COPYOUT(old, obj->ipfo_ptr, sizeof(*old)); + if (error == 0 && old->fr_dsize > 0) { + char *dst = obj->ipfo_ptr; + + fr = ptr; + dst += sizeof(*old); + error = COPYOUT(fr->fr_data, dst, + old->fr_dsize); + if (error != 0) { + IPFERROR(140044); + } + } + KFREE(old); + obj->ipfo_size = sizeof(*old); + } else if (obj->ipfo_rev >= 4011600) { + frentry_4_1_16_t *old; + + KMALLOC(old, frentry_4_1_16_t *); + if (old == NULL) { + IPFERROR(140045); + error = ENOMEM; + break; + } + frentry_current_to_4_1_16(ptr, old); + error = COPYOUT(old, obj->ipfo_ptr, sizeof(*old)); + if (error != 0) { + IPFERROR(140046); + } + KFREE(old); + obj->ipfo_size = sizeof(*old); + } else { + frentry_4_1_0_t *old; + + KMALLOC(old, frentry_4_1_0_t *); + if (old == NULL) { + IPFERROR(140047); + error = ENOMEM; + break; + } + frentry_current_to_4_1_0(ptr, old); + error = COPYOUT(old, obj->ipfo_ptr, sizeof(*old)); + if (error != 0) { + IPFERROR(140048); + } + KFREE(old); + obj->ipfo_size = sizeof(*old); + } + break; + + case IPFOBJ_IPFSTAT : + if (obj->ipfo_rev >= 4013300) { + friostat_4_1_33_t *old; + + KMALLOC(old, friostat_4_1_33_t *); + if (old == NULL) { + IPFERROR(140049); + error = ENOMEM; + break; + } + friostat_current_to_4_1_33(ptr, old, obj->ipfo_rev); + error = COPYOUT(old, obj->ipfo_ptr, sizeof(*old)); + if (error != 0) { + IPFERROR(140050); + } + KFREE(old); + } else { + friostat_4_1_0_t *old; + + KMALLOC(old, friostat_4_1_0_t *); + if (old == NULL) { + IPFERROR(140051); + error = ENOMEM; + break; + } + friostat_current_to_4_1_0(ptr, old, obj->ipfo_rev); + error = COPYOUT(old, obj->ipfo_ptr, sizeof(*old)); + if (error != 0) { + IPFERROR(140052); + } + KFREE(old); + } + break; + + case IPFOBJ_IPFINFO : /* unused */ + break; + + case IPFOBJ_IPNAT : + if (obj->ipfo_rev >= 4011400) { + ipnat_4_1_14_t *old; + + KMALLOC(old, ipnat_4_1_14_t *); + if (old == NULL) { + IPFERROR(140053); + error = ENOMEM; + break; + } + ipnat_current_to_4_1_14(ptr, old); + error = COPYOUT(old, obj->ipfo_ptr, sizeof(*old)); + if (error != 0) { + IPFERROR(140054); + } + KFREE(old); + } else { + ipnat_4_1_0_t *old; + + KMALLOC(old, ipnat_4_1_0_t *); + if (old == NULL) { + IPFERROR(140055); + error = ENOMEM; + break; + } + ipnat_current_to_4_1_0(ptr, old); + error = COPYOUT(old, obj->ipfo_ptr, sizeof(*old)); + if (error != 0) { + IPFERROR(140056); + } + KFREE(old); + } + break; + + case IPFOBJ_NATSTAT : + if (obj->ipfo_rev >= 4013200) { + natstat_4_1_32_t *old; + + KMALLOC(old, natstat_4_1_32_t *); + if (old == NULL) { + IPFERROR(140057); + error = ENOMEM; + break; + } + natstat_current_to_4_1_32(ptr, old); + error = COPYOUT(old, obj->ipfo_ptr, sizeof(*old)); + if (error != 0) { + IPFERROR(140058); + } + KFREE(old); + } else if (obj->ipfo_rev >= 4012700) { + natstat_4_1_27_t *old; + + KMALLOC(old, natstat_4_1_27_t *); + if (old == NULL) { + IPFERROR(140059); + error = ENOMEM; + break; + } + natstat_current_to_4_1_27(ptr, old); + error = COPYOUT(old, obj->ipfo_ptr, sizeof(*old)); + if (error != 0) { + IPFERROR(140060); + } + KFREE(old); + } else if (obj->ipfo_rev >= 4011600) { + natstat_4_1_16_t *old; + + KMALLOC(old, natstat_4_1_16_t *); + if (old == NULL) { + IPFERROR(140061); + error = ENOMEM; + break; + } + natstat_current_to_4_1_16(ptr, old); + error = COPYOUT(old, obj->ipfo_ptr, sizeof(*old)); + if (error != 0) { + IPFERROR(140062); + } + KFREE(old); + } else { + natstat_4_1_0_t *old; + + KMALLOC(old, natstat_4_1_0_t *); + if (old == NULL) { + IPFERROR(140063); + error = ENOMEM; + break; + } + natstat_current_to_4_1_0(ptr, old); + error = COPYOUT(old, obj->ipfo_ptr, sizeof(*old)); + if (error != 0) { + IPFERROR(140064); + } + KFREE(old); + } + break; + + case IPFOBJ_STATESAVE : + if (obj->ipfo_rev >= 4011600) { + ipstate_save_4_1_16_t *old; + + KMALLOC(old, ipstate_save_4_1_16_t *); + if (old == NULL) { + IPFERROR(140065); + error = ENOMEM; + break; + } + ipstate_save_current_to_4_1_16(ptr, old); + error = COPYOUT(old, obj->ipfo_ptr, sizeof(*old)); + if (error != 0) { + IPFERROR(140066); + } + KFREE(old); + } else { + ipstate_save_4_1_0_t *old; + + KMALLOC(old, ipstate_save_4_1_0_t *); + if (old == NULL) { + IPFERROR(140067); + error = ENOMEM; + break; + } + ipstate_save_current_to_4_1_0(ptr, old); + error = COPYOUT(old, obj->ipfo_ptr, sizeof(*old)); + if (error != 0) { + IPFERROR(140068); + } + KFREE(old); + } + break; + + case IPFOBJ_NATSAVE : + if (obj->ipfo_rev >= 4011600) { + nat_save_4_1_16_t *old16; + + KMALLOC(old16, nat_save_4_1_16_t *); + if (old16 == NULL) { + IPFERROR(140069); + error = ENOMEM; + break; + } + nat_save_current_to_4_1_16(ptr, old16); + error = COPYOUT(&old16, obj->ipfo_ptr, sizeof(*old16)); + if (error != 0) { + IPFERROR(140070); + } + KFREE(old16); + } else if (obj->ipfo_rev >= 4011400) { + nat_save_4_1_14_t *old14; + + KMALLOC(old14, nat_save_4_1_14_t *); + if (old14 == NULL) { + IPFERROR(140071); + error = ENOMEM; + break; + } + nat_save_current_to_4_1_14(ptr, old14); + error = COPYOUT(&old14, obj->ipfo_ptr, sizeof(*old14)); + if (error != 0) { + IPFERROR(140072); + } + KFREE(old14); + } else if (obj->ipfo_rev >= 4010300) { + nat_save_4_1_3_t *old3; + + KMALLOC(old3, nat_save_4_1_3_t *); + if (old3 == NULL) { + IPFERROR(140073); + error = ENOMEM; + break; + } + nat_save_current_to_4_1_3(ptr, old3); + error = COPYOUT(&old3, obj->ipfo_ptr, sizeof(*old3)); + if (error != 0) { + IPFERROR(140074); + } + KFREE(old3); + } + break; + + case IPFOBJ_IPSTATE : + if (obj->ipfo_rev >= 4011600) { + ipstate_4_1_16_t *old; + + KMALLOC(old, ipstate_4_1_16_t *); + if (old == NULL) { + IPFERROR(140075); + error = ENOMEM; + break; + } + ipstate_current_to_4_1_16(ptr, old); + error = COPYOUT(old, obj->ipfo_ptr, sizeof(*old)); + if (error != 0) { + IPFERROR(140076); + } + KFREE(old); + } else { + ipstate_4_1_0_t *old; + + KMALLOC(old, ipstate_4_1_0_t *); + if (old == NULL) { + IPFERROR(140077); + error = ENOMEM; + break; + } + ipstate_current_to_4_1_0(ptr, old); + error = COPYOUT(old, obj->ipfo_ptr, sizeof(*old)); + if (error != 0) { + IPFERROR(140078); + } + KFREE(old); + } + break; + + case IPFOBJ_STATESTAT : + if (obj->ipfo_rev >= 4012100) { + ips_stat_4_1_21_t *old; + + KMALLOC(old, ips_stat_4_1_21_t *); + if (old == NULL) { + IPFERROR(140079); + error = ENOMEM; + break; + } + ips_stat_current_to_4_1_21(ptr, old); + error = COPYOUT(old, obj->ipfo_ptr, sizeof(*old)); + if (error != 0) { + IPFERROR(140080); + } + KFREE(old); + } else { + ips_stat_4_1_0_t *old; + + KMALLOC(old, ips_stat_4_1_0_t *); + if (old == NULL) { + IPFERROR(140081); + error = ENOMEM; + break; + } + ips_stat_current_to_4_1_0(ptr, old); + error = COPYOUT(old, obj->ipfo_ptr, sizeof(*old)); + if (error != 0) { + IPFERROR(140082); + } + KFREE(old); + } + break; + + case IPFOBJ_FRAUTH : + if (obj->ipfo_rev >= 4012900) { + frauth_4_1_29_t *old29; + + KMALLOC(old29, frauth_4_1_29_t *); + if (old29 == NULL) { + IPFERROR(140083); + error = ENOMEM; + break; + } + frauth_current_to_4_1_29(ptr, old29); + error = COPYOUT(old29, obj->ipfo_ptr, sizeof(*old29)); + if (error != 0) { + IPFERROR(140084); + } + KFREE(old29); + } else if (obj->ipfo_rev >= 4012400) { + frauth_4_1_24_t *old24; + + KMALLOC(old24, frauth_4_1_24_t *); + if (old24 == NULL) { + IPFERROR(140085); + error = ENOMEM; + break; + } + frauth_current_to_4_1_24(ptr, old24); + error = COPYOUT(old24, obj->ipfo_ptr, sizeof(*old24)); + if (error != 0) { + IPFERROR(140086); + } + KFREE(old24); + } else if (obj->ipfo_rev >= 4012300) { + frauth_4_1_23_t *old23; + + KMALLOC(old23, frauth_4_1_23_t *); + if (old23 == NULL) { + IPFERROR(140087); + error = ENOMEM; + break; + } + frauth_current_to_4_1_23(ptr, old23); + error = COPYOUT(old23, obj->ipfo_ptr, sizeof(*old23)); + if (error != 0) { + IPFERROR(140088); + } + KFREE(old23); + } else if (obj->ipfo_rev >= 4011100) { + frauth_4_1_11_t *old11; + + KMALLOC(old11, frauth_4_1_11_t *); + if (old11 == NULL) { + IPFERROR(140089); + error = ENOMEM; + break; + } + frauth_current_to_4_1_11(ptr, old11); + error = COPYOUT(old11, obj->ipfo_ptr, sizeof(*old11)); + if (error != 0) { + IPFERROR(140090); + } + KFREE(old11); + } + break; + + case IPFOBJ_NAT : + if (obj->ipfo_rev >= 4012500) { + nat_4_1_25_t *old; + + KMALLOC(old, nat_4_1_25_t *); + if (old == NULL) { + IPFERROR(140091); + error = ENOMEM; + break; + } + nat_current_to_4_1_25(ptr, old); + error = COPYOUT(old, obj->ipfo_ptr, sizeof(*old)); + if (error != 0) { + IPFERROR(140092); + } + KFREE(old); + } else if (obj->ipfo_rev >= 4011400) { + nat_4_1_14_t *old; + + KMALLOC(old, nat_4_1_14_t *); + if (old == NULL) { + IPFERROR(140093); + error = ENOMEM; + break; + } + nat_current_to_4_1_14(ptr, old); + error = COPYOUT(old, obj->ipfo_ptr, sizeof(*old)); + if (error != 0) { + IPFERROR(140094); + } + KFREE(old); + } else if (obj->ipfo_rev >= 4010300) { + nat_4_1_3_t *old; + + KMALLOC(old, nat_4_1_3_t *); + if (old == NULL) { + IPFERROR(140095); + error = ENOMEM; + break; + } + nat_current_to_4_1_3(ptr, old); + error = COPYOUT(old, obj->ipfo_ptr, sizeof(*old)); + if (error != 0) { + IPFERROR(140096); + } + KFREE(old); + } + break; + + case IPFOBJ_FRIPF : + if (obj->ipfo_rev < 5000000) { + fripf4_t *old; + + KMALLOC(old, fripf4_t *); + if (old == NULL) { + IPFERROR(140097); + error = ENOMEM; + break; + } + ipf_v5fripftov4(ptr, old); + error = COPYOUT(old, obj->ipfo_ptr, sizeof(*old)); + if (error != 0) { + IPFERROR(140098); + } + KFREE(old); + } + break; + } + return error; +} + + +static void +friostat_current_to_4_1_33(current, old, rev) + void *current; + friostat_4_1_33_t *old; + int rev; +{ + friostat_t *fiop = (friostat_t *)current; + + bcopy(&fiop->f_st[0].fr_pass, &old->of_st[0], sizeof(old->of_st[0])); + bcopy(&fiop->f_st[1].fr_pass, &old->of_st[1], sizeof(old->of_st[1])); + + old->f_ipf[0][0] = fiop->f_ipf[0][0]; + old->f_ipf[0][1] = fiop->f_ipf[0][1]; + old->f_ipf[1][0] = fiop->f_ipf[1][0]; + old->f_ipf[1][1] = fiop->f_ipf[1][1]; + old->f_acct[0][0] = fiop->f_acct[0][0]; + old->f_acct[0][1] = fiop->f_acct[0][1]; + old->f_acct[1][0] = fiop->f_acct[1][0]; + old->f_acct[1][1] = fiop->f_acct[1][1]; + old->f_ipf6[0][0] = NULL; + old->f_ipf6[0][1] = NULL; + old->f_ipf6[1][0] = NULL; + old->f_ipf6[1][1] = NULL; + old->f_acct6[0][0] = NULL; + old->f_acct6[0][1] = NULL; + old->f_acct6[1][0] = NULL; + old->f_acct6[1][1] = NULL; + old->f_auth = fiop->f_auth; + bcopy(&fiop->f_groups, &old->f_groups, sizeof(old->f_groups)); + bcopy(&fiop->f_froute, &old->f_froute, sizeof(old->f_froute)); + old->f_ticks = fiop->f_ticks; + bcopy(&fiop->f_locks, &old->f_locks, sizeof(old->f_locks)); + old->f_kmutex_sz = 0; + old->f_krwlock_sz = 0; + old->f_defpass = fiop->f_defpass; + old->f_active = fiop->f_active; + old->f_running = fiop->f_running; + old->f_logging = fiop->f_logging; + old->f_features = fiop->f_features; + sprintf(old->f_version, "IP Filter: v%d.%d.%d", + (rev / 1000000) % 100, + (rev / 10000) % 100, + (rev / 100) % 100); +} + + +static void +friostat_current_to_4_1_0(current, old, rev) + void *current; + friostat_4_1_0_t *old; + int rev; +{ + friostat_t *fiop = (friostat_t *)current; + + bcopy(&fiop->f_st[0].fr_pass, &old->of_st[0], sizeof(old->of_st[0])); + bcopy(&fiop->f_st[1].fr_pass, &old->of_st[1], sizeof(old->of_st[1])); + + old->f_ipf[0][0] = fiop->f_ipf[0][0]; + old->f_ipf[0][1] = fiop->f_ipf[0][1]; + old->f_ipf[1][0] = fiop->f_ipf[1][0]; + old->f_ipf[1][1] = fiop->f_ipf[1][1]; + old->f_acct[0][0] = fiop->f_acct[0][0]; + old->f_acct[0][1] = fiop->f_acct[0][1]; + old->f_acct[1][0] = fiop->f_acct[1][0]; + old->f_acct[1][1] = fiop->f_acct[1][1]; + old->f_ipf6[0][0] = NULL; + old->f_ipf6[0][1] = NULL; + old->f_ipf6[1][0] = NULL; + old->f_ipf6[1][1] = NULL; + old->f_acct6[0][0] = NULL; + old->f_acct6[0][1] = NULL; + old->f_acct6[1][0] = NULL; + old->f_acct6[1][1] = NULL; + old->f_auth = fiop->f_auth; + bcopy(&fiop->f_groups, &old->f_groups, sizeof(old->f_groups)); + bcopy(&fiop->f_froute, &old->f_froute, sizeof(old->f_froute)); + old->f_ticks = fiop->f_ticks; + old->f_ipf[0][0] = fiop->f_ipf[0][0]; + old->f_ipf[0][1] = fiop->f_ipf[0][1]; + old->f_ipf[1][0] = fiop->f_ipf[1][0]; + old->f_ipf[1][1] = fiop->f_ipf[1][1]; + old->f_acct[0][0] = fiop->f_acct[0][0]; + old->f_acct[0][1] = fiop->f_acct[0][1]; + old->f_acct[1][0] = fiop->f_acct[1][0]; + old->f_acct[1][1] = fiop->f_acct[1][1]; + old->f_ipf6[0][0] = NULL; + old->f_ipf6[0][1] = NULL; + old->f_ipf6[1][0] = NULL; + old->f_ipf6[1][1] = NULL; + old->f_acct6[0][0] = NULL; + old->f_acct6[0][1] = NULL; + old->f_acct6[1][0] = NULL; + old->f_acct6[1][1] = NULL; + old->f_auth = fiop->f_auth; + bcopy(&fiop->f_groups, &old->f_groups, sizeof(old->f_groups)); + bcopy(&fiop->f_froute, &old->f_froute, sizeof(old->f_froute)); + old->f_ticks = fiop->f_ticks; + bcopy(&fiop->f_locks, &old->f_locks, sizeof(old->f_locks)); + old->f_kmutex_sz = 0; + old->f_krwlock_sz = 0; + old->f_defpass = fiop->f_defpass; + old->f_active = fiop->f_active; + old->f_running = fiop->f_running; + old->f_logging = fiop->f_logging; + old->f_features = fiop->f_features; + sprintf(old->f_version, "IP Filter: v%d.%d.%d", + (rev / 1000000) % 100, + (rev / 10000) % 100, + (rev / 100) % 100); +} + + +/* + * nflags is v5 flags, returns v4 flags. + */ +static int +fr_frflags5to4(nflags) + u_32_t nflags; +{ + u_32_t oflags = 0; + + switch (nflags & FR_CMDMASK) { + case FR_CALL : + oflags = 0x0; + break; + case FR_BLOCK : + oflags = 0x1; + break; + case FR_PASS : + oflags = 0x2; + break; + case FR_AUTH : + oflags = 0x3; + break; + case FR_PREAUTH : + oflags = 0x4; + break; + case FR_ACCOUNT : + oflags = 0x5; + break; + case FR_SKIP : + oflags = 0x6; + break; + default : + break; + } + + if (nflags & FR_LOG) + oflags |= 0x00010; + if (nflags & FR_CALLNOW) + oflags |= 0x00020; + if (nflags & FR_NOTSRCIP) + oflags |= 0x00080; + if (nflags & FR_NOTDSTIP) + oflags |= 0x00040; + if (nflags & FR_QUICK) + oflags |= 0x00100; + if (nflags & FR_KEEPFRAG) + oflags |= 0x00200; + if (nflags & FR_KEEPSTATE) + oflags |= 0x00400; + if (nflags & FR_FASTROUTE) + oflags |= 0x00800; + if (nflags & FR_RETRST) + oflags |= 0x01000; + if (nflags & FR_RETICMP) + oflags |= 0x02000; + if (nflags & FR_FAKEICMP) + oflags |= 0x03000; + if (nflags & FR_OUTQUE) + oflags |= 0x04000; + if (nflags & FR_INQUE) + oflags |= 0x08000; + if (nflags & FR_LOGBODY) + oflags |= 0x10000; + if (nflags & FR_LOGFIRST) + oflags |= 0x20000; + if (nflags & FR_LOGORBLOCK) + oflags |= 0x40000; + if (nflags & FR_FRSTRICT) + oflags |= 0x100000; + if (nflags & FR_STSTRICT) + oflags |= 0x200000; + if (nflags & FR_NEWISN) + oflags |= 0x400000; + if (nflags & FR_NOICMPERR) + oflags |= 0x800000; + if (nflags & FR_STATESYNC) + oflags |= 0x1000000; + if (nflags & FR_NOMATCH) + oflags |= 0x8000000; + if (nflags & FR_COPIED) + oflags |= 0x40000000; + if (nflags & FR_INACTIVE) + oflags |= 0x80000000; + + return oflags; +} + + +static void +frentry_current_to_4_1_34(current, old) + void *current; + frentry_4_1_34_t *old; +{ + frentry_t *fr = (frentry_t *)current; + + old->fr_lock = fr->fr_lock; + old->fr_next = fr->fr_next; + old->fr_grp = (void *)fr->fr_grp; + old->fr_isc = fr->fr_isc; + old->fr_ifas[0] = fr->fr_ifas[0]; + old->fr_ifas[1] = fr->fr_ifas[1]; + old->fr_ifas[2] = fr->fr_ifas[2]; + old->fr_ifas[3] = fr->fr_ifas[3]; + old->fr_ptr = fr->fr_ptr; + old->fr_comment = NULL; + old->fr_ref = fr->fr_ref; + old->fr_statecnt = fr->fr_statecnt; + old->fr_hits = fr->fr_hits; + old->fr_bytes = fr->fr_bytes; + old->fr_lastpkt.tv_sec = fr->fr_lastpkt.tv_sec; + old->fr_lastpkt.tv_usec = fr->fr_lastpkt.tv_usec; + old->fr_curpps = fr->fr_curpps; + old->fr_dun.fru_data = fr->fr_dun.fru_data; + old->fr_func = fr->fr_func; + old->fr_dsize = fr->fr_dsize; + old->fr_pps = fr->fr_pps; + old->fr_statemax = fr->fr_statemax; + old->fr_flineno = fr->fr_flineno; + old->fr_type = fr->fr_type; + old->fr_flags = fr_frflags5to4(fr->fr_flags); + old->fr_logtag = fr->fr_logtag; + old->fr_collect = fr->fr_collect; + old->fr_arg = fr->fr_arg; + old->fr_loglevel = fr->fr_loglevel; + old->fr_age[0] = fr->fr_age[0]; + old->fr_age[1] = fr->fr_age[1]; + if (fr->fr_family == AF_INET) + old->fr_v = 4; + if (fr->fr_family == AF_INET6) + old->fr_v = 6; + old->fr_icode = fr->fr_icode; + old->fr_cksum = fr->fr_cksum; + old->fr_tifs[0].ofd_ip6 = fr->fr_tifs[0].fd_ip6; + old->fr_tifs[1].ofd_ip6 = fr->fr_tifs[0].fd_ip6; + old->fr_dif.ofd_ip6 = fr->fr_dif.fd_ip6; + if (fr->fr_ifnames[0] >= 0) { + strncpy(old->fr_ifnames[0], fr->fr_names + fr->fr_ifnames[0], + LIFNAMSIZ); + old->fr_ifnames[0][LIFNAMSIZ - 1] = '\0'; + } + if (fr->fr_ifnames[1] >= 0) { + strncpy(old->fr_ifnames[1], fr->fr_names + fr->fr_ifnames[1], + LIFNAMSIZ); + old->fr_ifnames[1][LIFNAMSIZ - 1] = '\0'; + } + if (fr->fr_ifnames[2] >= 0) { + strncpy(old->fr_ifnames[2], fr->fr_names + fr->fr_ifnames[2], + LIFNAMSIZ); + old->fr_ifnames[2][LIFNAMSIZ - 1] = '\0'; + } + if (fr->fr_ifnames[3] >= 0) { + strncpy(old->fr_ifnames[3], fr->fr_names + fr->fr_ifnames[3], + LIFNAMSIZ); + old->fr_ifnames[3][LIFNAMSIZ - 1] = '\0'; + } + if (fr->fr_tifs[0].fd_name >= 0) { + strncpy(old->fr_tifs[0].fd_ifname, + fr->fr_names + fr->fr_tifs[0].fd_name, LIFNAMSIZ); + old->fr_tifs[0].fd_ifname[LIFNAMSIZ - 1] = '\0'; + } + if (fr->fr_tifs[1].fd_name >= 0) { + strncpy(old->fr_tifs[1].fd_ifname, + fr->fr_names + fr->fr_tifs[1].fd_name, LIFNAMSIZ); + old->fr_tifs[1].fd_ifname[LIFNAMSIZ - 1] = '\0'; + } + if (fr->fr_dif.fd_name >= 0) { + strncpy(old->fr_dif.fd_ifname, + fr->fr_names + fr->fr_dif.fd_name, LIFNAMSIZ); + old->fr_dif.fd_ifname[LIFNAMSIZ - 1] = '\0'; + } + if (fr->fr_group >= 0) { + strncpy(old->fr_group, fr->fr_names + fr->fr_group, + FR_GROUPLEN); + old->fr_group[FR_GROUPLEN - 1] = '\0'; + } + if (fr->fr_grhead >= 0) { + strncpy(old->fr_grhead, fr->fr_names + fr->fr_grhead, + FR_GROUPLEN); + old->fr_grhead[FR_GROUPLEN - 1] = '\0'; + } +} + + +static void +frentry_current_to_4_1_16(current, old) + void *current; + frentry_4_1_16_t *old; +{ + frentry_t *fr = (frentry_t *)current; + + old->fr_lock = fr->fr_lock; + old->fr_next = fr->fr_next; + old->fr_grp = (void *)fr->fr_grp; + old->fr_isc = fr->fr_isc; + old->fr_ifas[0] = fr->fr_ifas[0]; + old->fr_ifas[1] = fr->fr_ifas[1]; + old->fr_ifas[2] = fr->fr_ifas[2]; + old->fr_ifas[3] = fr->fr_ifas[3]; + old->fr_ptr = fr->fr_ptr; + old->fr_comment = NULL; + old->fr_ref = fr->fr_ref; + old->fr_statecnt = fr->fr_statecnt; + old->fr_hits = fr->fr_hits; + old->fr_bytes = fr->fr_bytes; + old->fr_lastpkt.tv_sec = fr->fr_lastpkt.tv_sec; + old->fr_lastpkt.tv_usec = fr->fr_lastpkt.tv_usec; + old->fr_curpps = fr->fr_curpps; + old->fr_dun.fru_data = fr->fr_dun.fru_data; + old->fr_func = fr->fr_func; + old->fr_dsize = fr->fr_dsize; + old->fr_pps = fr->fr_pps; + old->fr_statemax = fr->fr_statemax; + old->fr_flineno = fr->fr_flineno; + old->fr_type = fr->fr_type; + old->fr_flags = fr_frflags5to4(fr->fr_flags); + old->fr_logtag = fr->fr_logtag; + old->fr_collect = fr->fr_collect; + old->fr_arg = fr->fr_arg; + old->fr_loglevel = fr->fr_loglevel; + old->fr_age[0] = fr->fr_age[0]; + old->fr_age[1] = fr->fr_age[1]; + if (old->fr_v == 4) + fr->fr_family = AF_INET; + if (old->fr_v == 6) + fr->fr_family = AF_INET6; + old->fr_icode = fr->fr_icode; + old->fr_cksum = fr->fr_cksum; + old->fr_tifs[0].ofd_ip6 = fr->fr_tifs[0].fd_ip6; + old->fr_tifs[1].ofd_ip6 = fr->fr_tifs[0].fd_ip6; + old->fr_dif.ofd_ip6 = fr->fr_dif.fd_ip6; + if (fr->fr_ifnames[0] >= 0) { + strncpy(old->fr_ifnames[0], fr->fr_names + fr->fr_ifnames[0], + LIFNAMSIZ); + old->fr_ifnames[0][LIFNAMSIZ - 1] = '\0'; + } + if (fr->fr_ifnames[1] >= 0) { + strncpy(old->fr_ifnames[1], fr->fr_names + fr->fr_ifnames[1], + LIFNAMSIZ); + old->fr_ifnames[1][LIFNAMSIZ - 1] = '\0'; + } + if (fr->fr_ifnames[2] >= 0) { + strncpy(old->fr_ifnames[2], fr->fr_names + fr->fr_ifnames[2], + LIFNAMSIZ); + old->fr_ifnames[2][LIFNAMSIZ - 1] = '\0'; + } + if (fr->fr_ifnames[3] >= 0) { + strncpy(old->fr_ifnames[3], fr->fr_names + fr->fr_ifnames[3], + LIFNAMSIZ); + old->fr_ifnames[3][LIFNAMSIZ - 1] = '\0'; + } + if (fr->fr_tifs[0].fd_name >= 0) { + strncpy(old->fr_tifs[0].fd_ifname, + fr->fr_names + fr->fr_tifs[0].fd_name, LIFNAMSIZ); + old->fr_tifs[0].fd_ifname[LIFNAMSIZ - 1] = '\0'; + } + if (fr->fr_tifs[1].fd_name >= 0) { + strncpy(old->fr_tifs[1].fd_ifname, + fr->fr_names + fr->fr_tifs[1].fd_name, LIFNAMSIZ); + old->fr_tifs[1].fd_ifname[LIFNAMSIZ - 1] = '\0'; + } + if (fr->fr_dif.fd_name >= 0) { + strncpy(old->fr_dif.fd_ifname, + fr->fr_names + fr->fr_dif.fd_name, LIFNAMSIZ); + old->fr_dif.fd_ifname[LIFNAMSIZ - 1] = '\0'; + } + if (fr->fr_group >= 0) { + strncpy(old->fr_group, fr->fr_names + fr->fr_group, + FR_GROUPLEN); + old->fr_group[FR_GROUPLEN - 1] = '\0'; + } + if (fr->fr_grhead >= 0) { + strncpy(old->fr_grhead, fr->fr_names + fr->fr_grhead, + FR_GROUPLEN); + old->fr_grhead[FR_GROUPLEN - 1] = '\0'; + } +} + + +static void +frentry_current_to_4_1_0(current, old) + void *current; + frentry_4_1_0_t *old; +{ + frentry_t *fr = (frentry_t *)current; + + old->fr_lock = fr->fr_lock; + old->fr_next = fr->fr_next; + old->fr_grp = (void *)fr->fr_grp; + old->fr_isc = fr->fr_isc; + old->fr_ifas[0] = fr->fr_ifas[0]; + old->fr_ifas[1] = fr->fr_ifas[1]; + old->fr_ifas[2] = fr->fr_ifas[2]; + old->fr_ifas[3] = fr->fr_ifas[3]; + old->fr_ptr = fr->fr_ptr; + old->fr_comment = NULL; + old->fr_ref = fr->fr_ref; + old->fr_statecnt = fr->fr_statecnt; + old->fr_hits = fr->fr_hits; + old->fr_bytes = fr->fr_bytes; + old->fr_lastpkt.tv_sec = fr->fr_lastpkt.tv_sec; + old->fr_lastpkt.tv_usec = fr->fr_lastpkt.tv_usec; + old->fr_curpps = fr->fr_curpps; + old->fr_dun.fru_data = fr->fr_dun.fru_data; + old->fr_func = fr->fr_func; + old->fr_dsize = fr->fr_dsize; + old->fr_pps = fr->fr_pps; + old->fr_statemax = fr->fr_statemax; + old->fr_flineno = fr->fr_flineno; + old->fr_type = fr->fr_type; + old->fr_flags = fr_frflags5to4(fr->fr_flags); + old->fr_logtag = fr->fr_logtag; + old->fr_collect = fr->fr_collect; + old->fr_arg = fr->fr_arg; + old->fr_loglevel = fr->fr_loglevel; + old->fr_age[0] = fr->fr_age[0]; + old->fr_age[1] = fr->fr_age[1]; + if (old->fr_v == 4) + fr->fr_family = AF_INET; + if (old->fr_v == 6) + fr->fr_family = AF_INET6; + old->fr_icode = fr->fr_icode; + old->fr_cksum = fr->fr_cksum; + old->fr_tifs[0].ofd_ip6 = fr->fr_tifs[0].fd_ip6; + old->fr_tifs[1].ofd_ip6 = fr->fr_tifs[0].fd_ip6; + old->fr_dif.ofd_ip6 = fr->fr_dif.fd_ip6; + if (fr->fr_ifnames[0] >= 0) { + strncpy(old->fr_ifnames[0], fr->fr_names + fr->fr_ifnames[0], + LIFNAMSIZ); + old->fr_ifnames[0][LIFNAMSIZ - 1] = '\0'; + } + if (fr->fr_ifnames[1] >= 0) { + strncpy(old->fr_ifnames[1], fr->fr_names + fr->fr_ifnames[1], + LIFNAMSIZ); + old->fr_ifnames[1][LIFNAMSIZ - 1] = '\0'; + } + if (fr->fr_ifnames[2] >= 0) { + strncpy(old->fr_ifnames[2], fr->fr_names + fr->fr_ifnames[2], + LIFNAMSIZ); + old->fr_ifnames[2][LIFNAMSIZ - 1] = '\0'; + } + if (fr->fr_ifnames[3] >= 0) { + strncpy(old->fr_ifnames[3], fr->fr_names + fr->fr_ifnames[3], + LIFNAMSIZ); + old->fr_ifnames[3][LIFNAMSIZ - 1] = '\0'; + } + if (fr->fr_tifs[0].fd_name >= 0) { + strncpy(old->fr_tifs[0].fd_ifname, + fr->fr_names + fr->fr_tifs[0].fd_name, LIFNAMSIZ); + old->fr_tifs[0].fd_ifname[LIFNAMSIZ - 1] = '\0'; + } + if (fr->fr_tifs[1].fd_name >= 0) { + strncpy(old->fr_tifs[1].fd_ifname, + fr->fr_names + fr->fr_tifs[1].fd_name, LIFNAMSIZ); + old->fr_tifs[1].fd_ifname[LIFNAMSIZ - 1] = '\0'; + } + if (fr->fr_dif.fd_name >= 0) { + strncpy(old->fr_dif.fd_ifname, + fr->fr_names + fr->fr_dif.fd_name, LIFNAMSIZ); + old->fr_dif.fd_ifname[LIFNAMSIZ - 1] = '\0'; + } + if (fr->fr_group >= 0) { + strncpy(old->fr_group, fr->fr_names + fr->fr_group, + FR_GROUPLEN); + old->fr_group[FR_GROUPLEN - 1] = '\0'; + } + if (fr->fr_grhead >= 0) { + strncpy(old->fr_grhead, fr->fr_names + fr->fr_grhead, + FR_GROUPLEN); + old->fr_grhead[FR_GROUPLEN - 1] = '\0'; + } +} + + +static void +fr_info_current_to_4_1_24(current, old) + void *current; + fr_info_4_1_24_t *old; +{ + fr_info_t *fin = (fr_info_t *)current; + + old->fin_ifp = fin->fin_ifp; + ipf_v5iptov4(&fin->fin_fi, &old->fin_fi); + bcopy(&fin->fin_dat, &old->fin_dat, sizeof(fin->fin_dat)); + old->fin_out = fin->fin_out; + old->fin_rev = fin->fin_rev; + old->fin_hlen = fin->fin_hlen; + old->ofin_tcpf = fin->fin_tcpf; + old->fin_icode = fin->fin_icode; + old->fin_rule = fin->fin_rule; + bcopy(fin->fin_group, old->fin_group, sizeof(fin->fin_group)); + old->fin_fr = fin->fin_fr; + old->fin_dp = fin->fin_dp; + old->fin_dlen = fin->fin_dlen; + old->fin_plen = fin->fin_plen; + old->fin_ipoff = fin->fin_ipoff; + old->fin_id = fin->fin_id; + old->fin_off = fin->fin_off; + old->fin_depth = fin->fin_depth; + old->fin_error = fin->fin_error; + old->fin_cksum = fin->fin_cksum; + old->fin_state = NULL; + old->fin_nat = NULL; + old->fin_nattag = fin->fin_nattag; + old->fin_exthdr = NULL; + old->ofin_ip = fin->fin_ip; + old->fin_mp = fin->fin_mp; + old->fin_m = fin->fin_m; +#ifdef MENTAT + old->fin_qfm = fin->fin_qfm; + old->fin_qpi = fin->fin_qpi; + old->fin_ifname[0] = '\0'; +#endif +#ifdef __sgi + old->fin_hbuf = fin->fin_hbuf; +#endif +} + + +static void +fr_info_current_to_4_1_23(current, old) + void *current; + fr_info_4_1_23_t *old; +{ + fr_info_t *fin = (fr_info_t *)current; + + old->fin_ifp = fin->fin_ifp; + ipf_v5iptov4(&fin->fin_fi, &old->fin_fi); + bcopy(&fin->fin_dat, &old->fin_dat, sizeof(fin->fin_dat)); + old->fin_out = fin->fin_out; + old->fin_rev = fin->fin_rev; + old->fin_hlen = fin->fin_hlen; + old->ofin_tcpf = fin->fin_tcpf; + old->fin_icode = fin->fin_icode; + old->fin_rule = fin->fin_rule; + bcopy(fin->fin_group, old->fin_group, sizeof(fin->fin_group)); + old->fin_fr = fin->fin_fr; + old->fin_dp = fin->fin_dp; + old->fin_dlen = fin->fin_dlen; + old->fin_plen = fin->fin_plen; + old->fin_ipoff = fin->fin_ipoff; + old->fin_id = fin->fin_id; + old->fin_off = fin->fin_off; + old->fin_depth = fin->fin_depth; + old->fin_error = fin->fin_error; + old->fin_state = NULL; + old->fin_nat = NULL; + old->fin_nattag = fin->fin_nattag; + old->ofin_ip = fin->fin_ip; + old->fin_mp = fin->fin_mp; + old->fin_m = fin->fin_m; +#ifdef MENTAT + old->fin_qfm = fin->fin_qfm; + old->fin_qpi = fin->fin_qpi; + old->fin_ifname[0] = '\0'; +#endif +#ifdef __sgi + old->fin_hbuf = fin->fin_hbuf; +#endif +} + + +static void +fr_info_current_to_4_1_11(current, old) + void *current; + fr_info_4_1_11_t *old; +{ + fr_info_t *fin = (fr_info_t *)current; + + old->fin_ifp = fin->fin_ifp; + ipf_v5iptov4(&fin->fin_fi, &old->fin_fi); + bcopy(&fin->fin_dat, &old->fin_dat, sizeof(fin->fin_dat)); + old->fin_out = fin->fin_out; + old->fin_rev = fin->fin_rev; + old->fin_hlen = fin->fin_hlen; + old->ofin_tcpf = fin->fin_tcpf; + old->fin_icode = fin->fin_icode; + old->fin_rule = fin->fin_rule; + bcopy(fin->fin_group, old->fin_group, sizeof(fin->fin_group)); + old->fin_fr = fin->fin_fr; + old->fin_dp = fin->fin_dp; + old->fin_dlen = fin->fin_dlen; + old->fin_plen = fin->fin_plen; + old->fin_ipoff = fin->fin_ipoff; + old->fin_id = fin->fin_id; + old->fin_off = fin->fin_off; + old->fin_depth = fin->fin_depth; + old->fin_error = fin->fin_error; + old->fin_state = NULL; + old->fin_nat = NULL; + old->fin_nattag = fin->fin_nattag; + old->ofin_ip = fin->fin_ip; + old->fin_mp = fin->fin_mp; + old->fin_m = fin->fin_m; +#ifdef MENTAT + old->fin_qfm = fin->fin_qfm; + old->fin_qpi = fin->fin_qpi; + old->fin_ifname[0] = '\0'; +#endif +#ifdef __sgi + old->fin_hbuf = fin->fin_hbuf; +#endif +} + + +static void +frauth_current_to_4_1_29(current, old) + void *current; + frauth_4_1_29_t *old; +{ + frauth_t *fra = (frauth_t *)current; + + old->fra_age = fra->fra_age; + old->fra_len = fra->fra_len; + old->fra_index = fra->fra_index; + old->fra_pass = fra->fra_pass; + fr_info_current_to_4_1_24(&fra->fra_info, &old->fra_info); + old->fra_buf = fra->fra_buf; + old->fra_flx = fra->fra_flx; +#ifdef MENTAT + old->fra_q = fra->fra_q; + old->fra_m = fra->fra_m; +#endif +} + + +static void +frauth_current_to_4_1_24(current, old) + void *current; + frauth_4_1_24_t *old; +{ + frauth_t *fra = (frauth_t *)current; + + old->fra_age = fra->fra_age; + old->fra_len = fra->fra_len; + old->fra_index = fra->fra_index; + old->fra_pass = fra->fra_pass; + fr_info_current_to_4_1_24(&fra->fra_info, &old->fra_info); + old->fra_buf = fra->fra_buf; +#ifdef MENTAT + old->fra_q = fra->fra_q; + old->fra_m = fra->fra_m; +#endif +} + + +static void +frauth_current_to_4_1_23(current, old) + void *current; + frauth_4_1_23_t *old; +{ + frauth_t *fra = (frauth_t *)current; + + old->fra_age = fra->fra_age; + old->fra_len = fra->fra_len; + old->fra_index = fra->fra_index; + old->fra_pass = fra->fra_pass; + fr_info_current_to_4_1_23(&fra->fra_info, &old->fra_info); + old->fra_buf = fra->fra_buf; +#ifdef MENTAT + old->fra_q = fra->fra_q; + old->fra_m = fra->fra_m; +#endif +} + + +static void +frauth_current_to_4_1_11(current, old) + void *current; + frauth_4_1_11_t *old; +{ + frauth_t *fra = (frauth_t *)current; + + old->fra_age = fra->fra_age; + old->fra_len = fra->fra_len; + old->fra_index = fra->fra_index; + old->fra_pass = fra->fra_pass; + fr_info_current_to_4_1_11(&fra->fra_info, &old->fra_info); + old->fra_buf = fra->fra_buf; +#ifdef MENTAT + old->fra_q = fra->fra_q; + old->fra_m = fra->fra_m; +#endif +} + + +static void +ipnat_current_to_4_1_14(current, old) + void *current; + ipnat_4_1_14_t *old; +{ + ipnat_t *np = (ipnat_t *)current; + + old->in_next = np->in_next; + old->in_rnext = np->in_rnext; + old->in_prnext = np->in_prnext; + old->in_mnext = np->in_mnext; + old->in_pmnext = np->in_pmnext; + old->in_tqehead[0] = np->in_tqehead[0]; + old->in_tqehead[1] = np->in_tqehead[1]; + old->in_ifps[0] = np->in_ifps[0]; + old->in_ifps[1] = np->in_ifps[1]; + old->in_apr = np->in_apr; + old->in_comment = np->in_comment; + old->in_space = np->in_space; + old->in_hits = np->in_hits; + old->in_use = np->in_use; + old->in_hv = np->in_hv[0]; + old->in_flineno = np->in_flineno; + if (old->in_redir == NAT_REDIRECT) + old->in_pnext = np->in_dpnext; + else + old->in_pnext = np->in_spnext; + old->in_v = np->in_v[0]; + old->in_flags = np->in_flags; + old->in_mssclamp = np->in_mssclamp; + old->in_age[0] = np->in_age[0]; + old->in_age[1] = np->in_age[1]; + old->in_redir = np->in_redir; + old->in_p = np->in_pr[0]; + if (np->in_redir == NAT_REDIRECT) { + old->in_next6 = np->in_ndst.na_nextaddr; + old->in_in[0] = np->in_ndst.na_addr[0]; + old->in_in[1] = np->in_ndst.na_addr[1]; + old->in_out[0] = np->in_odst.na_addr[0]; + old->in_out[1] = np->in_odst.na_addr[1]; + old->in_src[0] = np->in_osrc.na_addr[0]; + old->in_src[1] = np->in_osrc.na_addr[1]; + } else { + old->in_next6 = np->in_nsrc.na_nextaddr; + old->in_out[0] = np->in_nsrc.na_addr[0]; + old->in_out[1] = np->in_nsrc.na_addr[1]; + old->in_in[0] = np->in_osrc.na_addr[0]; + old->in_in[1] = np->in_osrc.na_addr[1]; + old->in_src[0] = np->in_odst.na_addr[0]; + old->in_src[1] = np->in_odst.na_addr[1]; + } + ipfv5tuctov4(&np->in_tuc, &old->in_tuc); + if (np->in_redir == NAT_REDIRECT) { + old->in_port[0] = np->in_dpmin; + old->in_port[1] = np->in_dpmax; + } else { + old->in_port[0] = np->in_spmin; + old->in_port[1] = np->in_spmax; + } + old->in_ppip = np->in_ppip; + old->in_ippip = np->in_ippip; + bcopy(&np->in_tag, &old->in_tag, sizeof(np->in_tag)); + + if (np->in_ifnames[0] >= 0) { + strncpy(old->in_ifnames[0], np->in_names + np->in_ifnames[0], + LIFNAMSIZ); + old->in_ifnames[0][LIFNAMSIZ - 1] = '\0'; + } + if (np->in_ifnames[1] >= 0) { + strncpy(old->in_ifnames[1], np->in_names + np->in_ifnames[1], + LIFNAMSIZ); + old->in_ifnames[1][LIFNAMSIZ - 1] = '\0'; + } + if (np->in_plabel >= 0) { + strncpy(old->in_plabel, np->in_names + np->in_plabel, + APR_LABELLEN); + old->in_plabel[APR_LABELLEN - 1] = '\0'; + } +} + + +static void +ipnat_current_to_4_1_0(current, old) + void *current; + ipnat_4_1_0_t *old; +{ + ipnat_t *np = (ipnat_t *)current; + + old->in_next = np->in_next; + old->in_rnext = np->in_rnext; + old->in_prnext = np->in_prnext; + old->in_mnext = np->in_mnext; + old->in_pmnext = np->in_pmnext; + old->in_tqehead[0] = np->in_tqehead[0]; + old->in_tqehead[1] = np->in_tqehead[1]; + old->in_ifps[0] = np->in_ifps[0]; + old->in_ifps[1] = np->in_ifps[1]; + old->in_apr = np->in_apr; + old->in_comment = np->in_comment; + old->in_space = np->in_space; + old->in_hits = np->in_hits; + old->in_use = np->in_use; + old->in_hv = np->in_hv[0]; + old->in_flineno = np->in_flineno; + if (old->in_redir == NAT_REDIRECT) + old->in_pnext = np->in_dpnext; + else + old->in_pnext = np->in_spnext; + old->in_v = np->in_v[0]; + old->in_flags = np->in_flags; + old->in_mssclamp = np->in_mssclamp; + old->in_age[0] = np->in_age[0]; + old->in_age[1] = np->in_age[1]; + old->in_redir = np->in_redir; + old->in_p = np->in_pr[0]; + if (np->in_redir == NAT_REDIRECT) { + old->in_next6 = np->in_ndst.na_nextaddr; + old->in_in[0] = np->in_ndst.na_addr[0]; + old->in_in[1] = np->in_ndst.na_addr[1]; + old->in_out[0] = np->in_odst.na_addr[0]; + old->in_out[1] = np->in_odst.na_addr[1]; + old->in_src[0] = np->in_osrc.na_addr[0]; + old->in_src[1] = np->in_osrc.na_addr[1]; + } else { + old->in_next6 = np->in_nsrc.na_nextaddr; + old->in_out[0] = np->in_nsrc.na_addr[0]; + old->in_out[1] = np->in_nsrc.na_addr[1]; + old->in_in[0] = np->in_osrc.na_addr[0]; + old->in_in[1] = np->in_osrc.na_addr[1]; + old->in_src[0] = np->in_odst.na_addr[0]; + old->in_src[1] = np->in_odst.na_addr[1]; + } + ipfv5tuctov4(&np->in_tuc, &old->in_tuc); + if (np->in_redir == NAT_REDIRECT) { + old->in_port[0] = np->in_dpmin; + old->in_port[1] = np->in_dpmax; + } else { + old->in_port[0] = np->in_spmin; + old->in_port[1] = np->in_spmax; + } + old->in_ppip = np->in_ppip; + old->in_ippip = np->in_ippip; + bcopy(&np->in_tag, &old->in_tag, sizeof(np->in_tag)); + + if (np->in_ifnames[0] >= 0) { + strncpy(old->in_ifnames[0], np->in_names + np->in_ifnames[0], + LIFNAMSIZ); + old->in_ifnames[0][LIFNAMSIZ - 1] = '\0'; + } + if (np->in_ifnames[1] >= 0) { + strncpy(old->in_ifnames[1], np->in_names + np->in_ifnames[1], + LIFNAMSIZ); + old->in_ifnames[1][LIFNAMSIZ - 1] = '\0'; + } + if (np->in_plabel >= 0) { + strncpy(old->in_plabel, np->in_names + np->in_plabel, + APR_LABELLEN); + old->in_plabel[APR_LABELLEN - 1] = '\0'; + } +} + + +static void +ipstate_current_to_4_1_16(current, old) + void *current; + ipstate_4_1_16_t *old; +{ + ipstate_t *is = (ipstate_t *)current; + + old->is_lock = is->is_lock; + old->is_next = is->is_next; + old->is_pnext = is->is_pnext; + old->is_hnext = is->is_hnext; + old->is_phnext = is->is_phnext; + old->is_me = is->is_me; + old->is_ifp[0] = is->is_ifp[0]; + old->is_ifp[1] = is->is_ifp[1]; + old->is_sync = is->is_sync; + old->is_rule = is->is_rule; + old->is_tqehead[0] = is->is_tqehead[0]; + old->is_tqehead[1] = is->is_tqehead[1]; + old->is_isc = is->is_isc; + old->is_pkts[0] = is->is_pkts[0]; + old->is_pkts[1] = is->is_pkts[1]; + old->is_pkts[2] = is->is_pkts[2]; + old->is_pkts[3] = is->is_pkts[3]; + old->is_bytes[0] = is->is_bytes[0]; + old->is_bytes[1] = is->is_bytes[1]; + old->is_bytes[2] = is->is_bytes[2]; + old->is_bytes[3] = is->is_bytes[3]; + old->is_icmppkts[0] = is->is_icmppkts[0]; + old->is_icmppkts[1] = is->is_icmppkts[1]; + old->is_icmppkts[2] = is->is_icmppkts[2]; + old->is_icmppkts[3] = is->is_icmppkts[3]; + old->is_sti = is->is_sti; + old->is_frage[0] = is->is_frage[0]; + old->is_frage[1] = is->is_frage[1]; + old->is_ref = is->is_ref; + old->is_isninc[0] = is->is_isninc[0]; + old->is_isninc[1] = is->is_isninc[1]; + old->is_sumd[0] = is->is_sumd[0]; + old->is_sumd[1] = is->is_sumd[1]; + old->is_src = is->is_src; + old->is_dst = is->is_dst; + old->is_pass = is->is_pass; + old->is_p = is->is_p; + old->is_v = is->is_v; + old->is_hv = is->is_hv; + old->is_tag = is->is_tag; + old->is_opt[0] = is->is_opt[0]; + old->is_opt[1] = is->is_opt[1]; + old->is_optmsk[0] = is->is_optmsk[0]; + old->is_optmsk[1] = is->is_optmsk[1]; + old->is_sec = is->is_sec; + old->is_secmsk = is->is_secmsk; + old->is_auth = is->is_auth; + old->is_authmsk = is->is_authmsk; + ipf_v5tcpinfoto4(&is->is_tcp, &old->is_tcp); + old->is_flags = is->is_flags; + old->is_flx[0][0] = is->is_flx[0][0]; + old->is_flx[0][1] = is->is_flx[0][1]; + old->is_flx[1][0] = is->is_flx[1][0]; + old->is_flx[1][1] = is->is_flx[1][1]; + old->is_rulen = is->is_rulen; + old->is_s0[0] = is->is_s0[0]; + old->is_s0[1] = is->is_s0[1]; + old->is_smsk[0] = is->is_smsk[0]; + old->is_smsk[1] = is->is_smsk[1]; + bcopy(is->is_group, old->is_group, sizeof(is->is_group)); + bcopy(is->is_sbuf, old->is_sbuf, sizeof(is->is_sbuf)); + bcopy(is->is_ifname, old->is_ifname, sizeof(is->is_ifname)); +} + + +static void +ipstate_current_to_4_1_0(current, old) + void *current; + ipstate_4_1_0_t *old; +{ + ipstate_t *is = (ipstate_t *)current; + + old->is_lock = is->is_lock; + old->is_next = is->is_next; + old->is_pnext = is->is_pnext; + old->is_hnext = is->is_hnext; + old->is_phnext = is->is_phnext; + old->is_me = is->is_me; + old->is_ifp[0] = is->is_ifp[0]; + old->is_ifp[1] = is->is_ifp[1]; + old->is_sync = is->is_sync; + bzero(&old->is_nat, sizeof(old->is_nat)); + old->is_rule = is->is_rule; + old->is_tqehead[0] = is->is_tqehead[0]; + old->is_tqehead[1] = is->is_tqehead[1]; + old->is_isc = is->is_isc; + old->is_pkts[0] = is->is_pkts[0]; + old->is_pkts[1] = is->is_pkts[1]; + old->is_pkts[2] = is->is_pkts[2]; + old->is_pkts[3] = is->is_pkts[3]; + old->is_bytes[0] = is->is_bytes[0]; + old->is_bytes[1] = is->is_bytes[1]; + old->is_bytes[2] = is->is_bytes[2]; + old->is_bytes[3] = is->is_bytes[3]; + old->is_icmppkts[0] = is->is_icmppkts[0]; + old->is_icmppkts[1] = is->is_icmppkts[1]; + old->is_icmppkts[2] = is->is_icmppkts[2]; + old->is_icmppkts[3] = is->is_icmppkts[3]; + old->is_sti = is->is_sti; + old->is_frage[0] = is->is_frage[0]; + old->is_frage[1] = is->is_frage[1]; + old->is_ref = is->is_ref; + old->is_isninc[0] = is->is_isninc[0]; + old->is_isninc[1] = is->is_isninc[1]; + old->is_sumd[0] = is->is_sumd[0]; + old->is_sumd[1] = is->is_sumd[1]; + old->is_src = is->is_src; + old->is_dst = is->is_dst; + old->is_pass = is->is_pass; + old->is_p = is->is_p; + old->is_v = is->is_v; + old->is_hv = is->is_hv; + old->is_tag = is->is_tag; + old->is_opt[0] = is->is_opt[0]; + old->is_opt[1] = is->is_opt[1]; + old->is_optmsk[0] = is->is_optmsk[0]; + old->is_optmsk[1] = is->is_optmsk[1]; + old->is_sec = is->is_sec; + old->is_secmsk = is->is_secmsk; + old->is_auth = is->is_auth; + old->is_authmsk = is->is_authmsk; + ipf_v5tcpinfoto4(&is->is_tcp, &old->is_tcp); + old->is_flags = is->is_flags; + old->is_flx[0][0] = is->is_flx[0][0]; + old->is_flx[0][1] = is->is_flx[0][1]; + old->is_flx[1][0] = is->is_flx[1][0]; + old->is_flx[1][1] = is->is_flx[1][1]; + old->is_rulen = is->is_rulen; + old->is_s0[0] = is->is_s0[0]; + old->is_s0[1] = is->is_s0[1]; + old->is_smsk[0] = is->is_smsk[0]; + old->is_smsk[1] = is->is_smsk[1]; + bcopy(is->is_group, old->is_group, sizeof(is->is_group)); + bcopy(is->is_sbuf, old->is_sbuf, sizeof(is->is_sbuf)); + bcopy(is->is_ifname, old->is_ifname, sizeof(is->is_ifname)); +} + + +static void +ips_stat_current_to_4_1_21(current, old) + void *current; + ips_stat_4_1_21_t *old; +{ + ips_stat_t *st = (ips_stat_t *)current; + + old->iss_hits = st->iss_hits; + old->iss_miss = st->iss_check_miss; + old->iss_max = st->iss_max; + old->iss_maxref = st->iss_max_ref; + old->iss_tcp = st->iss_proto[IPPROTO_TCP]; + old->iss_udp = st->iss_proto[IPPROTO_UDP]; + old->iss_icmp = st->iss_proto[IPPROTO_ICMP]; + old->iss_nomem = st->iss_nomem; + old->iss_expire = st->iss_expire; + old->iss_fin = st->iss_fin; + old->iss_active = st->iss_active; + old->iss_logged = st->iss_log_ok; + old->iss_logfail = st->iss_log_fail; + old->iss_inuse = st->iss_inuse; + old->iss_wild = st->iss_wild; + old->iss_ticks = st->iss_ticks; + old->iss_bucketfull = st->iss_bucket_full; + old->iss_statesize = st->iss_state_size; + old->iss_statemax = st->iss_state_max; + old->iss_table = st->iss_table; + old->iss_list = st->iss_list; + old->iss_bucketlen = (void *)st->iss_bucketlen; + old->iss_tcptab = st->iss_tcptab; +} + + +static void +ips_stat_current_to_4_1_0(current, old) + void *current; + ips_stat_4_1_0_t *old; +{ + ips_stat_t *st = (ips_stat_t *)current; + + old->iss_hits = st->iss_hits; + old->iss_miss = st->iss_check_miss; + old->iss_max = st->iss_max; + old->iss_maxref = st->iss_max_ref; + old->iss_tcp = st->iss_proto[IPPROTO_TCP]; + old->iss_udp = st->iss_proto[IPPROTO_UDP]; + old->iss_icmp = st->iss_proto[IPPROTO_ICMP]; + old->iss_nomem = st->iss_nomem; + old->iss_expire = st->iss_expire; + old->iss_fin = st->iss_fin; + old->iss_active = st->iss_active; + old->iss_logged = st->iss_log_ok; + old->iss_logfail = st->iss_log_fail; + old->iss_inuse = st->iss_inuse; + old->iss_wild = st->iss_wild; + old->iss_ticks = st->iss_ticks; + old->iss_bucketfull = st->iss_bucket_full; + old->iss_statesize = st->iss_state_size; + old->iss_statemax = st->iss_state_max; + old->iss_table = st->iss_table; + old->iss_list = st->iss_list; + old->iss_bucketlen = (void *)st->iss_bucketlen; +} + + +static void +nat_save_current_to_4_1_16(current, old) + void *current; + nat_save_4_1_16_t *old; +{ + nat_save_t *nats = (nat_save_t *)current; + + old->ipn_next = nats->ipn_next; + bcopy(&nats->ipn_nat, &old->ipn_nat, sizeof(old->ipn_nat)); + bcopy(&nats->ipn_ipnat, &old->ipn_ipnat, sizeof(old->ipn_ipnat)); + frentry_current_to_4_1_16(&nats->ipn_fr, &old->ipn_fr); + old->ipn_dsize = nats->ipn_dsize; + bcopy(nats->ipn_data, old->ipn_data, sizeof(nats->ipn_data)); +} + + +static void +nat_save_current_to_4_1_14(current, old) + void *current; + nat_save_4_1_14_t *old; +{ + nat_save_t *nats = (nat_save_t *)current; + + old->ipn_next = nats->ipn_next; + bcopy(&nats->ipn_nat, &old->ipn_nat, sizeof(old->ipn_nat)); + bcopy(&nats->ipn_ipnat, &old->ipn_ipnat, sizeof(old->ipn_ipnat)); + frentry_current_to_4_1_0(&nats->ipn_fr, &old->ipn_fr); + old->ipn_dsize = nats->ipn_dsize; + bcopy(nats->ipn_data, old->ipn_data, sizeof(nats->ipn_data)); +} + + +static void +nat_save_current_to_4_1_3(current, old) + void *current; + nat_save_4_1_3_t *old; +{ + nat_save_t *nats = (nat_save_t *)current; + + old->ipn_next = nats->ipn_next; + bcopy(&nats->ipn_nat, &old->ipn_nat, sizeof(old->ipn_nat)); + bcopy(&nats->ipn_ipnat, &old->ipn_ipnat, sizeof(old->ipn_ipnat)); + frentry_current_to_4_1_0(&nats->ipn_fr, &old->ipn_fr); + old->ipn_dsize = nats->ipn_dsize; + bcopy(nats->ipn_data, old->ipn_data, sizeof(nats->ipn_data)); +} + + +static void +nat_current_to_4_1_25(current, old) + void *current; + nat_4_1_25_t *old; +{ + nat_t *nat = (nat_t *)current; + + old->nat_lock = nat->nat_lock; + old->nat_next = (void *)nat->nat_next; + old->nat_pnext = (void *)nat->nat_pnext; + old->nat_hnext[0] = (void *)nat->nat_hnext[0]; + old->nat_hnext[1] = (void *)nat->nat_hnext[1]; + old->nat_phnext[0] = (void *)nat->nat_phnext[0]; + old->nat_phnext[1] = (void *)nat->nat_phnext[1]; + old->nat_hm = nat->nat_hm; + old->nat_data = nat->nat_data; + old->nat_me = (void *)nat->nat_me; + old->nat_state = nat->nat_state; + old->nat_aps = nat->nat_aps; + old->nat_fr = nat->nat_fr; + old->nat_ptr = (void *)nat->nat_ptr; + old->nat_ifps[0] = nat->nat_ifps[0]; + old->nat_ifps[1] = nat->nat_ifps[1]; + old->nat_sync = nat->nat_sync; + old->nat_tqe = nat->nat_tqe; + old->nat_flags = nat->nat_flags; + old->nat_sumd[0] = nat->nat_sumd[0]; + old->nat_sumd[1] = nat->nat_sumd[1]; + old->nat_ipsumd = nat->nat_ipsumd; + old->nat_mssclamp = nat->nat_mssclamp; + old->nat_pkts[0] = nat->nat_pkts[0]; + old->nat_pkts[1] = nat->nat_pkts[1]; + old->nat_bytes[0] = nat->nat_bytes[0]; + old->nat_bytes[1] = nat->nat_bytes[1]; + old->nat_ref = nat->nat_ref; + old->nat_dir = nat->nat_dir; + old->nat_p = nat->nat_pr[0]; + old->nat_use = nat->nat_use; + old->nat_hv[0] = nat->nat_hv[0]; + old->nat_hv[1] = nat->nat_hv[1]; + old->nat_rev = nat->nat_rev; + old->nat_redir = nat->nat_redir; + bcopy(nat->nat_ifnames[0], old->nat_ifnames[0], LIFNAMSIZ); + bcopy(nat->nat_ifnames[1], old->nat_ifnames[1], LIFNAMSIZ); + + if (nat->nat_redir == NAT_REDIRECT) { + old->nat_inip6 = nat->nat_ndst6; + old->nat_outip6 = nat->nat_odst6; + old->nat_oip6 = nat->nat_osrc6; + old->nat_un.nat_unt.ts_sport = nat->nat_ndport; + old->nat_un.nat_unt.ts_dport = nat->nat_odport; + } else { + old->nat_inip6 = nat->nat_osrc6; + old->nat_outip6 = nat->nat_nsrc6; + old->nat_oip6 = nat->nat_odst6; + old->nat_un.nat_unt.ts_sport = nat->nat_osport; + old->nat_un.nat_unt.ts_dport = nat->nat_nsport; + } +} + + +static void +nat_current_to_4_1_14(current, old) + void *current; + nat_4_1_14_t *old; +{ + nat_t *nat = (nat_t *)current; + + old->nat_lock = nat->nat_lock; + old->nat_next = nat->nat_next; + old->nat_pnext = NULL; + old->nat_hnext[0] = NULL; + old->nat_hnext[1] = NULL; + old->nat_phnext[0] = NULL; + old->nat_phnext[1] = NULL; + old->nat_hm = nat->nat_hm; + old->nat_data = nat->nat_data; + old->nat_me = (void *)nat->nat_me; + old->nat_state = nat->nat_state; + old->nat_aps = nat->nat_aps; + old->nat_fr = nat->nat_fr; + old->nat_ptr = nat->nat_ptr; + old->nat_ifps[0] = nat->nat_ifps[0]; + old->nat_ifps[1] = nat->nat_ifps[1]; + old->nat_sync = nat->nat_sync; + old->nat_tqe = nat->nat_tqe; + old->nat_flags = nat->nat_flags; + old->nat_sumd[0] = nat->nat_sumd[0]; + old->nat_sumd[1] = nat->nat_sumd[1]; + old->nat_ipsumd = nat->nat_ipsumd; + old->nat_mssclamp = nat->nat_mssclamp; + old->nat_pkts[0] = nat->nat_pkts[0]; + old->nat_pkts[1] = nat->nat_pkts[1]; + old->nat_bytes[0] = nat->nat_bytes[0]; + old->nat_bytes[1] = nat->nat_bytes[1]; + old->nat_ref = nat->nat_ref; + old->nat_dir = nat->nat_dir; + old->nat_p = nat->nat_pr[0]; + old->nat_use = nat->nat_use; + old->nat_hv[0] = nat->nat_hv[0]; + old->nat_hv[1] = nat->nat_hv[1]; + old->nat_rev = nat->nat_rev; + bcopy(nat->nat_ifnames[0], old->nat_ifnames[0], LIFNAMSIZ); + bcopy(nat->nat_ifnames[1], old->nat_ifnames[1], LIFNAMSIZ); + + if (nat->nat_redir == NAT_REDIRECT) { + old->nat_inip6 = nat->nat_ndst6; + old->nat_outip6 = nat->nat_odst6; + old->nat_oip6 = nat->nat_osrc6; + old->nat_un.nat_unt.ts_sport = nat->nat_ndport; + old->nat_un.nat_unt.ts_dport = nat->nat_odport; + } else { + old->nat_inip6 = nat->nat_osrc6; + old->nat_outip6 = nat->nat_nsrc6; + old->nat_oip6 = nat->nat_odst6; + old->nat_un.nat_unt.ts_sport = nat->nat_osport; + old->nat_un.nat_unt.ts_dport = nat->nat_nsport; + } +} + + +static void +nat_current_to_4_1_3(current, old) + void *current; + nat_4_1_3_t *old; +{ + nat_t *nat = (nat_t *)current; + + old->nat_lock = nat->nat_lock; + old->nat_next = nat->nat_next; + old->nat_pnext = NULL; + old->nat_hnext[0] = NULL; + old->nat_hnext[1] = NULL; + old->nat_phnext[0] = NULL; + old->nat_phnext[1] = NULL; + old->nat_hm = nat->nat_hm; + old->nat_data = nat->nat_data; + old->nat_me = (void *)nat->nat_me; + old->nat_state = nat->nat_state; + old->nat_aps = nat->nat_aps; + old->nat_fr = nat->nat_fr; + old->nat_ptr = nat->nat_ptr; + old->nat_ifps[0] = nat->nat_ifps[0]; + old->nat_ifps[1] = nat->nat_ifps[1]; + old->nat_sync = nat->nat_sync; + old->nat_tqe = nat->nat_tqe; + old->nat_flags = nat->nat_flags; + old->nat_sumd[0] = nat->nat_sumd[0]; + old->nat_sumd[1] = nat->nat_sumd[1]; + old->nat_ipsumd = nat->nat_ipsumd; + old->nat_mssclamp = nat->nat_mssclamp; + old->nat_pkts[0] = nat->nat_pkts[0]; + old->nat_pkts[1] = nat->nat_pkts[1]; + old->nat_bytes[0] = nat->nat_bytes[0]; + old->nat_bytes[1] = nat->nat_bytes[1]; + old->nat_ref = nat->nat_ref; + old->nat_dir = nat->nat_dir; + old->nat_p = nat->nat_pr[0]; + old->nat_use = nat->nat_use; + old->nat_hv[0] = nat->nat_hv[0]; + old->nat_hv[1] = nat->nat_hv[1]; + old->nat_rev = nat->nat_rev; + bcopy(nat->nat_ifnames[0], old->nat_ifnames[0], LIFNAMSIZ); + bcopy(nat->nat_ifnames[1], old->nat_ifnames[1], LIFNAMSIZ); + + if (nat->nat_redir == NAT_REDIRECT) { + old->nat_inip6 = nat->nat_ndst6; + old->nat_outip6 = nat->nat_odst6; + old->nat_oip6 = nat->nat_osrc6; + old->nat_un.nat_unt.ts_sport = nat->nat_ndport; + old->nat_un.nat_unt.ts_dport = nat->nat_odport; + } else { + old->nat_inip6 = nat->nat_osrc6; + old->nat_outip6 = nat->nat_nsrc6; + old->nat_oip6 = nat->nat_odst6; + old->nat_un.nat_unt.ts_sport = nat->nat_osport; + old->nat_un.nat_unt.ts_dport = nat->nat_nsport; + } +} + +#endif /* IPFILTER_COMPAT */ diff --git a/ip_fil_freebsd.c b/ip_fil_freebsd.c index 3b36b93117a81..740ab8f996699 100644 --- a/ip_fil_freebsd.c +++ b/ip_fil_freebsd.c @@ -1,13 +1,11 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1993-2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #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_freebsd.c,v 2.53.2.25 2005/02/01 03:15:56 darrenr Exp"; +static const char rcsid[] = "@(#)$Id$"; #endif #if defined(KERNEL) || defined(_KERNEL) @@ -55,14 +53,21 @@ static const char rcsid[] = "@(#)Id: ip_fil_freebsd.c,v 2.53.2.25 2005/02/01 03: #if !defined(__hpux) # include <sys/mbuf.h> #endif -#include <sys/protosw.h> +#if (__FreeBSD_version < 800000) +# include <netinet/ipprotosw.h> +#endif #include <sys/socket.h> +#if __FreeBSD_version >= 500043 +# include <sys/selinfo.h> +#else +# include <sys/select.h> +#endif #include <net/if.h> #if __FreeBSD_version >= 300000 # include <net/if_var.h> -# if !defined(IPFILTER_LKM) -# include "opt_ipfilter.h" +# if __FreeBSD_version >= 500043 +# include <net/netisr.h> # endif #endif #include <net/route.h> @@ -78,9 +83,6 @@ static const char rcsid[] = "@(#)Id: ip_fil_freebsd.c,v 2.53.2.25 2005/02/01 03: #include <netinet/udp.h> #include <netinet/tcpip.h> #include <netinet/ip_icmp.h> -#ifndef _KERNEL -# include "netinet/ipf.h" -#endif #include "netinet/ip_compat.h" #ifdef USE_INET6 # include <netinet/icmp6.h> @@ -91,9 +93,9 @@ static const char rcsid[] = "@(#)Id: ip_fil_freebsd.c,v 2.53.2.25 2005/02/01 03: #include "netinet/ip_state.h" #include "netinet/ip_proxy.h" #include "netinet/ip_auth.h" -#ifdef IPFILTER_SYNC #include "netinet/ip_sync.h" -#endif +#include "netinet/ip_lookup.h" +#include "netinet/ip_dstlist.h" #ifdef IPFILTER_SCAN #include "netinet/ip_scan.h" #endif @@ -116,60 +118,76 @@ MALLOC_DEFINE(M_IPFILTER, "IP Filter", "IP Filter packet filter data structures" # endif -#if !defined(__osf__) -extern struct protosw inetsw[]; -#endif - -static int (*fr_savep) __P((ip_t *, int, void *, int, struct mbuf **)); -static int fr_send_ip __P((fr_info_t *, mb_t *, mb_t **)); -# ifdef USE_MUTEXES -ipfmutex_t ipl_mutex, ipf_authmx, ipf_rw, ipf_stinsert; -ipfmutex_t ipf_nat_new, ipf_natio, ipf_timeoutlock; -ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag; -ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth; -# endif +static u_short ipid = 0; +static int (*ipf_savep) __P((void *, ip_t *, int, void *, int, struct mbuf **)); +static int ipf_send_ip __P((fr_info_t *, mb_t *)); +static void ipf_timer_func __P((void *arg)); int ipf_locks_done = 0; -#if (__FreeBSD_version >= 300000) -struct callout_handle fr_slowtimer_ch; -#endif +ipf_main_softc_t ipfmain; #if (__FreeBSD_version >= 500011) # include <sys/conf.h> # if defined(NETBSD_PF) # include <net/pfil.h> -# include <netinet/ipprotosw.h> -/* - * We provide the fr_checkp name just to minimize changes later. - */ -int (*fr_checkp) __P((ip_t *ip, int hlen, void *ifp, int out, mb_t **mp)); # endif /* NETBSD_PF */ #endif /* __FreeBSD_version >= 500011 */ +/* + * We provide the ipf_checkp name just to minimize changes later. + */ +int (*ipf_checkp) __P((void *, ip_t *ip, int hlen, void *ifp, int out, mb_t **mp)); -#if (__FreeBSD_version >= 501108) && defined(_KERNEL) +#if (__FreeBSD_version >= 502103) +static eventhandler_tag ipf_arrivetag, ipf_departtag, ipf_clonetag; + +static void ipf_ifevent(void *arg); + +static void ipf_ifevent(arg) + void *arg; +{ + ipf_sync(arg, NULL); +} +#endif + + +#if (__FreeBSD_version >= 501108) static int -fr_check_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir) +ipf_check_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir) { struct ip *ip = mtod(*mp, struct ip *); - return fr_check(ip, ip->ip_hl << 2, ifp, (dir == PFIL_OUT), mp); + int rv; + + /* + * IPFilter expects evreything in network byte order + */ + ip->ip_len = htons(ip->ip_len); + ip->ip_off = htons(ip->ip_off); + rv = ipf_check(&ipfmain, ip, ip->ip_hl << 2, ifp, (dir == PFIL_OUT), + mp); + if ((rv == 0) && (*mp != NULL)) { + ip = mtod(*mp, struct ip *); + ip->ip_len = ntohs(ip->ip_len); + ip->ip_off = ntohs(ip->ip_off); + } + return rv; } # ifdef USE_INET6 # include <netinet/ip6.h> static int -fr_check_wrapper6(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir) +ipf_check_wrapper6(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir) { - return (fr_check(mtod(*mp, struct ip *), sizeof(struct ip6_hdr), - ifp, (dir == PFIL_OUT), mp)); + return (ipf_check(&ipfmain, mtod(*mp, struct ip *), + sizeof(struct ip6_hdr), ifp, (dir == PFIL_OUT), mp)); } # endif #endif /* __FreeBSD_version >= 501108 */ #if defined(IPFILTER_LKM) -int iplidentify(s) -char *s; +int ipf_identify(s) + char *s; { if (strcmp(s, "ipl") == 0) return 1; @@ -178,116 +196,70 @@ char *s; #endif /* IPFILTER_LKM */ -int iplattach() +static void +ipf_timer_func(arg) + void *arg; +{ + ipf_main_softc_t *softc = arg; + SPL_INT(s); + + SPL_NET(s); + READ_ENTER(&softc->ipf_global); + + if (softc->ipf_running > 0) + ipf_slowtimer(softc); + + if (softc->ipf_running == -1 || softc->ipf_running == 1) { +#if FREEBSD_GE_REV(300000) + softc->ipf_slow_ch = timeout(ipf_timer_func, softc, hz/2); +#else + timeout(ipf_timer_func, softc, hz/2); +#endif + } + RWLOCK_EXIT(&softc->ipf_global); + SPL_X(s); +} + + +int +ipfattach(softc) + ipf_main_softc_t *softc; { #ifdef USE_SPL int s; #endif -#if defined(NETBSD_PF) && (__FreeBSD_version >= 500011) - int error = 0; -# if __FreeBSD_version >= 501108 - struct pfil_head *ph_inet; -# ifdef USE_INET6 - struct pfil_head *ph_inet6; -# endif -# endif -#endif SPL_NET(s); - if (fr_running > 0) { + if (softc->ipf_running > 0) { SPL_X(s); return EBUSY; } - MUTEX_INIT(&ipf_rw, "ipf rw mutex"); - RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex"); - MUTEX_INIT(&ipf_timeoutlock, "ipf timeout queue mutex"); - RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock"); - RWLOCK_INIT(&ipf_ipidfrag, "ipf IP NAT-Frag rwlock"); - ipf_locks_done = 1; - - if (fr_initialise() < 0) { + if (ipf_init_all(softc) < 0) { SPL_X(s); return EIO; } -# ifdef NETBSD_PF -# if __FreeBSD_version >= 500011 -# if __FreeBSD_version >= 501108 - ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); -# ifdef USE_INET6 - ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); -# endif - if (ph_inet == NULL -# ifdef USE_INET6 - && ph_inet6 == NULL -# endif - ) - return ENODEV; - - if (ph_inet != NULL) - error = pfil_add_hook((void *)fr_check_wrapper, NULL, - PFIL_IN|PFIL_OUT, ph_inet); - else - error = 0; -# else - error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); -# endif - if (error) { -# ifdef USE_INET6 - goto pfil_error; -# else - fr_deinitialise(); - SPL_X(s); - return error; -# endif - } -# else - pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT); -# endif -# ifdef USE_INET6 -# if __FreeBSD_version >= 501108 - if (ph_inet6 != NULL) - error = pfil_add_hook((void *)fr_check_wrapper6, NULL, - PFIL_IN|PFIL_OUT, ph_inet6); - else - error = 0; - if (error) { - pfil_remove_hook((void *)fr_check_wrapper6, NULL, - PFIL_IN|PFIL_OUT, ph_inet6); -# else - error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh); - if (error) { - pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); -# endif -pfil_error: - fr_deinitialise(); - SPL_X(s); - return error; - } -# endif -# endif - if (fr_checkp != fr_check) { - fr_savep = fr_checkp; - fr_checkp = fr_check; + if (ipf_checkp != ipf_check) { + ipf_savep = ipf_checkp; + ipf_checkp = ipf_check; } - bzero((char *)frcache, sizeof(frcache)); - fr_running = 1; + bzero((char *)ipfmain.ipf_selwait, sizeof(ipfmain.ipf_selwait)); + softc->ipf_running = 1; - if (fr_control_forwarding & 1) + if (softc->ipf_control_forwarding & 1) ipforwarding = 1; + ipid = 0; + SPL_X(s); #if (__FreeBSD_version >= 300000) - fr_slowtimer_ch = timeout(fr_slowtimer, NULL, - (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT); + softc->ipf_slow_ch = timeout(ipf_timer_func, softc, + (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT); #else - timeout(fr_slowtimer, NULL, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT); + timeout(ipf_timer_func, softc, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT); #endif return 0; } @@ -297,93 +269,36 @@ pfil_error: * Disable the filter by removing the hooks from the IP input/output * stream. */ -int ipldetach() +int +ipfdetach(softc) + ipf_main_softc_t *softc; { #ifdef USE_SPL int s; #endif -#if defined(NETBSD_PF) && (__FreeBSD_version >= 500011) - int error = 0; -# if __FreeBSD_version >= 501108 - struct pfil_head *ph_inet; -# ifdef USE_INET6 - struct pfil_head *ph_inet6; -# endif -# endif -#endif - if (fr_control_forwarding & 2) + if (softc->ipf_control_forwarding & 2) ipforwarding = 0; SPL_NET(s); #if (__FreeBSD_version >= 300000) - if (fr_slowtimer_ch.callout != NULL) - untimeout(fr_slowtimer, NULL, fr_slowtimer_ch); - bzero(&fr_slowtimer_ch, sizeof(fr_slowtimer_ch)); + if (softc->ipf_slow_ch.callout != NULL) + untimeout(ipf_timer_func, softc, softc->ipf_slow_ch); + bzero(&softc->ipf_slow, sizeof(softc->ipf_slow)); #else - untimeout(fr_slowtimer, NULL); + untimeout(ipf_timer_func, softc); #endif /* FreeBSD */ #ifndef NETBSD_PF - if (fr_checkp != NULL) - fr_checkp = fr_savep; - fr_savep = NULL; + if (ipf_checkp != NULL) + ipf_checkp = ipf_savep; + ipf_savep = NULL; #endif -#ifdef NETBSD_PF -# if (__FreeBSD_version >= 500011) -# if (__FreeBSD_version >= 501108) - ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); - if (ph_inet != NULL) - error = pfil_remove_hook((void *)fr_check_wrapper, NULL, - PFIL_IN|PFIL_OUT, ph_inet); - else - error = 0; -# else - error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); -# endif - if (error) { - SPL_X(s); - return error; - } -# else - pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT); -# endif -# ifdef USE_INET6 -# if (__FreeBSD_version >= 501108) - ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); - if (ph_inet6 != NULL) - error = pfil_remove_hook((void *)fr_check_wrapper6, NULL, - PFIL_IN|PFIL_OUT, ph_inet6); - else - error = 0; -# else - error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh); -# endif - if (error) { - SPL_X(s); - return error; - } -# endif -#endif - fr_deinitialise(); - - fr_running = -2; + ipf_fini_all(softc); - (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE|FR_INACTIVE); - (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE); - - if (ipf_locks_done == 1) { - MUTEX_DESTROY(&ipf_timeoutlock); - MUTEX_DESTROY(&ipf_rw); - RW_DESTROY(&ipf_mutex); - RW_DESTROY(&ipf_ipidfrag); - RW_DESTROY(&ipf_global); - ipf_locks_done = 0; - } + softc->ipf_running = -2; SPL_X(s); @@ -394,365 +309,89 @@ int ipldetach() /* * Filter ioctl interface. */ -int iplioctl(dev, cmd, data, mode -# if defined(_KERNEL) && ((BSD >= 199506) || (__FreeBSD_version >= 220000)) +int +ipfioctl(dev, cmd, data, mode +# if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) , p) # if (__FreeBSD_version >= 500024) -struct thread *p; + struct thread *p; +# if (__FreeBSD_version >= 500043) +# define p_uid td_ucred->cr_ruid +# else +# define p_uid t_proc->p_cred->p_ruid +# endif # else -struct proc *p; + struct proc *p; +# define p_uid p_cred->p_ruid # endif /* __FreeBSD_version >= 500024 */ # else ) # endif -#if defined(_KERNEL) && (__FreeBSD_version >= 502116) -struct cdev *dev; +#if (__FreeBSD_version >= 502116) + struct cdev *dev; #else -dev_t dev; + dev_t dev; #endif -ioctlcmd_t cmd; -caddr_t data; -int mode; + ioctlcmd_t cmd; + caddr_t data; + int mode; { -#ifdef USE_SPL - int s; -#endif - int error = 0, unit = 0, tmp; - friostat_t fio; + int error = 0, unit = 0; + SPL_INT(s); -#if (BSD >= 199306) && defined(_KERNEL) - if ((securelevel >= 2) && (mode & FWRITE)) +#if (BSD >= 199306) +# if (__FreeBSD_version >= 500034) + if (securelevel_ge(p->p_cred, 3) && (mode & FWRITE)) +# else + if ((securelevel >= 3) && (mode & FWRITE)) +# endif + { + ipfmain.ipf_interror = 130001; return EPERM; + } #endif unit = GET_MINOR(dev); - if ((IPL_LOGMAX < unit) || (unit < 0)) + if ((IPL_LOGMAX < unit) || (unit < 0)) { + ipfmain.ipf_interror = 130002; return ENXIO; + } - if (fr_running <= 0) { - if (unit != IPL_LOGIPF) + if (ipfmain.ipf_running <= 0) { + if (unit != IPL_LOGIPF && cmd != SIOCIPFINTERROR) { + ipfmain.ipf_interror = 130003; return EIO; + } if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET && - cmd != SIOCIPFSET && cmd != SIOCFRENB && - cmd != SIOCGETFS && cmd != SIOCGETFF) + cmd != SIOCIPFSET && cmd != SIOCFRENB && + cmd != SIOCGETFS && cmd != SIOCGETFF && + cmd != SIOCIPFINTERROR) { + ipfmain.ipf_interror = 130004; return EIO; + } } SPL_NET(s); - error = fr_ioctlswitch(unit, data, cmd, mode); + error = ipf_ioctlswitch(&ipfmain, unit, data, cmd, mode, p->p_uid, p); if (error != -1) { SPL_X(s); return error; } - error = 0; - switch (cmd) - { - case FIONREAD : -#ifdef IPFILTER_LOG - BCOPYOUT(&iplused[IPL_LOGIPF], (caddr_t)data, - sizeof(iplused[IPL_LOGIPF])); -#endif - break; - case SIOCFRENB : - if (!(mode & FWRITE)) - error = EPERM; - else { - BCOPYIN(data, &tmp, sizeof(tmp)); - if (tmp) { - if (fr_running > 0) - error = 0; - else - error = iplattach(); - if (error == 0) - fr_running = 1; - else - (void) ipldetach(); - } else { - error = ipldetach(); - if (error == 0) - fr_running = -1; - } - } - break; - case SIOCIPFSET : - if (!(mode & FWRITE)) { - error = EPERM; - break; - } - case SIOCIPFGETNEXT : - case SIOCIPFGET : - error = fr_ipftune(cmd, data); - break; - case SIOCSETFF : - if (!(mode & FWRITE)) - error = EPERM; - else - BCOPYIN(data, &fr_flags, sizeof(fr_flags)); - break; - case SIOCGETFF : - BCOPYOUT(&fr_flags, data, sizeof(fr_flags)); - break; - case SIOCFUNCL : - error = fr_resolvefunc(data); - break; - case SIOCINAFR : - case SIOCRMAFR : - case SIOCADAFR : - case SIOCZRLST : - if (!(mode & FWRITE)) - error = EPERM; - else - error = frrequest(unit, cmd, data, fr_active, 1); - break; - case SIOCINIFR : - case SIOCRMIFR : - case SIOCADIFR : - if (!(mode & FWRITE)) - error = EPERM; - else - error = frrequest(unit, cmd, data, 1 - fr_active, 1); - break; - case SIOCSWAPA : - if (!(mode & FWRITE)) - error = EPERM; - else { - bzero((char *)frcache, sizeof(frcache[0]) * 2); - *(u_int *)data = fr_active; - fr_active = 1 - fr_active; - } - break; - case SIOCGETFS : - fr_getstat(&fio); - error = fr_outobj(data, &fio, IPFOBJ_IPFSTAT); - break; - case SIOCFRZST : - if (!(mode & FWRITE)) - error = EPERM; - else - error = fr_zerostats(data); - break; - case SIOCIPFFL : - if (!(mode & FWRITE)) - error = EPERM; - else { - BCOPYIN(data, &tmp, sizeof(tmp)); - tmp = frflush(unit, 4, tmp); - BCOPYOUT(&tmp, data, sizeof(tmp)); - } - break; -#ifdef USE_INET6 - case SIOCIPFL6 : - if (!(mode & FWRITE)) - error = EPERM; - else { - BCOPYIN(data, &tmp, sizeof(tmp)); - tmp = frflush(unit, 6, tmp); - BCOPYOUT(&tmp, data, sizeof(tmp)); - } - break; -#endif - case SIOCSTLCK : - BCOPYIN(data, &tmp, sizeof(tmp)); - fr_state_lock = tmp; - fr_nat_lock = tmp; - fr_frag_lock = tmp; - fr_auth_lock = tmp; - break; -#ifdef IPFILTER_LOG - case SIOCIPFFB : - if (!(mode & FWRITE)) - error = EPERM; - else - *(int *)data = ipflog_clear(unit); - break; -#endif /* IPFILTER_LOG */ - case SIOCGFRST : - error = fr_outobj(data, fr_fragstats(), IPFOBJ_FRAGSTAT); - break; - case SIOCFRSYN : - if (!(mode & FWRITE)) - error = EPERM; - else { - frsync(NULL); - } - break; - default : - error = EINVAL; - break; - } SPL_X(s); - return error; -} - - -#if 0 -void fr_forgetifp(ifp) -void *ifp; -{ - register frentry_t *f; - - WRITE_ENTER(&ipf_mutex); - for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; - for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; - for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; - for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; -#ifdef USE_INET6 - for (f = ipacct6[0][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; - for (f = ipacct6[1][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; - for (f = ipfilter6[0][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; - for (f = ipfilter6[1][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; -#endif - RWLOCK_EXIT(&ipf_mutex); - fr_natsync(ifp); -} -#endif - - -/* - * routines below for saving IP headers to buffer - */ -int iplopen(dev, flags -#if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) && defined(_KERNEL) -, devtype, p) -int devtype; -# if (__FreeBSD_version >= 500024) -struct thread *p; -# else -struct proc *p; -# endif /* __FreeBSD_version >= 500024 */ -#else -) -#endif -#if defined(_KERNEL) && (__FreeBSD_version >= 502116) -struct cdev *dev; -#else -dev_t dev; -#endif -int flags; -{ - u_int min = GET_MINOR(dev); - - if (IPL_LOGMAX < min) - min = ENXIO; - else - min = 0; - return min; -} - - -int iplclose(dev, flags -#if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) && defined(_KERNEL) -, devtype, p) -int devtype; -# if (__FreeBSD_version >= 500024) -struct thread *p; -# else -struct proc *p; -# endif /* __FreeBSD_version >= 500024 */ -#else -) -#endif -#if defined(_KERNEL) && (__FreeBSD_version >= 502116) -struct cdev *dev; -#else -dev_t dev; -#endif -int flags; -{ - u_int min = GET_MINOR(dev); - - if (IPL_LOGMAX < min) - min = ENXIO; - else - min = 0; - return min; -} - -/* - * iplread/ipllog - * both of these must operate with at least splnet() lest they be - * called during packet processing and cause an inconsistancy to appear in - * the filter lists. - */ -#if (BSD >= 199306) -int iplread(dev, uio, ioflag) -int ioflag; -#else -int iplread(dev, uio) -#endif -#if defined(_KERNEL) && (__FreeBSD_version >= 502116) -struct cdev *dev; -#else -dev_t dev; -#endif -register struct uio *uio; -{ - -# ifdef IPFILTER_SYNC - if (GET_MINOR(dev) == IPL_LOGSYNC) - return ipfsync_read(uio); -# endif - -#ifdef IPFILTER_LOG - return ipflog_read(GET_MINOR(dev), uio); -#else - return ENXIO; -#endif -} - - -/* - * iplwrite - * both of these must operate with at least splnet() lest they be - * called during packet processing and cause an inconsistancy to appear in - * the filter lists. - */ -#if (BSD >= 199306) -int iplwrite(dev, uio, ioflag) -int ioflag; -#else -int iplwrite(dev, uio) -#endif -#if defined(_KERNEL) && (__FreeBSD_version >= 502116) -struct cdev *dev; -#else -dev_t dev; -#endif -register struct uio *uio; -{ -#ifdef IPFILTER_SYNC - if (GET_MINOR(dev) == IPL_LOGSYNC) - return ipfsync_write(uio); -#endif - return ENXIO; + return error; } /* - * fr_send_reset - this could conceivably be a call to tcp_respond(), but that + * ipf_send_reset - this could conceivably be a call to tcp_respond(), but that * requires a large amount of setting up and isn't any more efficient. */ -int fr_send_reset(fin) -fr_info_t *fin; +int +ipf_send_reset(fin) + fr_info_t *fin; { struct tcphdr *tcp, *tcp2; int tlen = 0, hlen; @@ -766,10 +405,8 @@ fr_info_t *fin; if (tcp->th_flags & TH_RST) return -1; /* feedback loop */ -#ifndef IPFILTER_CKSUM - if (fr_checkl4sum(fin) == -1) + if (ipf_checkl4sum(fin) == -1) return -1; -#endif tlen = fin->fin_dlen - (TCP_OFF(tcp) << 2) + ((tcp->th_flags & TH_SYN) ? 1 : 0) + @@ -833,11 +470,11 @@ fr_info_t *fin; ip6->ip6_plen = htons(sizeof(struct tcphdr)); ip6->ip6_nxt = IPPROTO_TCP; ip6->ip6_hlim = 0; - ip6->ip6_src = fin->fin_dst6; - ip6->ip6_dst = fin->fin_src6; + ip6->ip6_src = fin->fin_dst6.in6; + ip6->ip6_dst = fin->fin_src6.in6; tcp2->th_sum = in6_cksum(m, IPPROTO_TCP, sizeof(*ip6), sizeof(*tcp2)); - return fr_send_ip(fin, m, &m); + return ipf_send_ip(fin, m); } #endif ip->ip_p = IPPROTO_TCP; @@ -845,14 +482,18 @@ fr_info_t *fin; ip->ip_src.s_addr = fin->fin_daddr; ip->ip_dst.s_addr = fin->fin_saddr; tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2)); - ip->ip_len = hlen + sizeof(*tcp2); - return fr_send_ip(fin, m, &m); + ip->ip_len = htons(hlen + sizeof(*tcp2)); + return ipf_send_ip(fin, m); } -static int fr_send_ip(fin, m, mpp) -fr_info_t *fin; -mb_t *m, **mpp; +/* + * ip_len must be in network byte order when called. + */ +static int +ipf_send_ip(fin, m) + fr_info_t *fin; + mb_t *m; { fr_info_t fnew; ip_t *ip, *oip; @@ -860,24 +501,27 @@ mb_t *m, **mpp; ip = mtod(m, ip_t *); bzero((char *)&fnew, sizeof(fnew)); + fnew.fin_main_soft = fin->fin_main_soft; IP_V_A(ip, fin->fin_v); switch (fin->fin_v) { case 4 : - fnew.fin_v = 4; oip = fin->fin_ip; + hlen = sizeof(*oip); + fnew.fin_v = 4; + fnew.fin_p = ip->ip_p; + fnew.fin_plen = ntohs(ip->ip_len); IP_HL_A(ip, sizeof(*oip) >> 2); ip->ip_tos = oip->ip_tos; ip->ip_id = fin->fin_ip->ip_id; #if (__FreeBSD_version > 460000) - ip->ip_off = path_mtu_discovery ? IP_DF : 0; + ip->ip_off = htons(path_mtu_discovery ? IP_DF : 0); #else ip->ip_off = 0; #endif ip->ip_ttl = ip_defttl; ip->ip_sum = 0; - hlen = sizeof(*oip); break; #ifdef USE_INET6 case 6 : @@ -887,8 +531,10 @@ mb_t *m, **mpp; ip6->ip6_vfc = 0x60; ip6->ip6_hlim = IPDEFTTL; - fnew.fin_v = 6; hlen = sizeof(*ip6); + fnew.fin_p = ip6->ip6_nxt; + fnew.fin_v = 6; + fnew.fin_plen = ntohs(ip6->ip6_plen) + hlen; break; } #endif @@ -903,32 +549,33 @@ mb_t *m, **mpp; fnew.fin_flx = FI_NOCKSUM; fnew.fin_m = m; fnew.fin_ip = ip; - fnew.fin_mp = mpp; + fnew.fin_mp = &m; fnew.fin_hlen = hlen; fnew.fin_dp = (char *)ip + hlen; - (void) fr_makefrip(hlen, ip, &fnew); + (void) ipf_makefrip(hlen, ip, &fnew); - return fr_fastroute(m, mpp, &fnew, NULL); + return ipf_fastroute(m, &m, &fnew, NULL); } -int fr_send_icmp_err(type, fin, dst) -int type; -fr_info_t *fin; -int dst; +int +ipf_send_icmp_err(type, fin, dst) + int type; + fr_info_t *fin; + int dst; { int err, hlen, xtra, iclen, ohlen, avail, code; struct in_addr dst4; struct icmp *icmp; struct mbuf *m; + i6addr_t dst6; void *ifp; #ifdef USE_INET6 ip6_t *ip6; - struct in6_addr dst6; #endif ip_t *ip, *ip2; - if ((type < 0) || (type > ICMP_MAXTYPE)) + if ((type < 0) || (type >= ICMP_MAXTYPE)) return -1; code = fin->fin_icode; @@ -937,10 +584,8 @@ int dst; return -1; #endif -#ifndef IPFILTER_CKSUM - if (fr_checkl4sum(fin) == -1) + if (ipf_checkl4sum(fin) == -1) return -1; -#endif #ifdef MGETHDR MGETHDR(m, M_DONTWAIT, MT_HEADER); #else @@ -953,10 +598,10 @@ int dst; xtra = 0; hlen = 0; ohlen = 0; + dst4.s_addr = 0; ifp = fin->fin_ifp; if (fin->fin_v == 4) { - if ((fin->fin_p == IPPROTO_ICMP) && - !(fin->fin_flx & FI_SHORT)) + if ((fin->fin_p == IPPROTO_ICMP) && !(fin->fin_flx & FI_SHORT)) switch (ntohs(fin->fin_data[0]) >> 8) { case ICMP_ECHO : @@ -970,16 +615,18 @@ int dst; } if (dst == 0) { - if (fr_ifpaddr(4, FRI_NORMAL, ifp, - &dst4, NULL) == -1) { + if (ipf_ifpaddr(&ipfmain, 4, FRI_NORMAL, ifp, + &dst6, NULL) == -1) { FREE_MB_T(m); return -1; } + dst4 = dst6.in4; } else dst4.s_addr = fin->fin_daddr; hlen = sizeof(ip_t); ohlen = fin->fin_hlen; + iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen; if (fin->fin_hlen < fin->fin_plen) xtra = MIN(fin->fin_dlen, 8); else @@ -990,12 +637,12 @@ int dst; else if (fin->fin_v == 6) { hlen = sizeof(ip6_t); ohlen = sizeof(ip6_t); + iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen; type = icmptoicmp6types[type]; if (type == ICMP6_DST_UNREACH) code = icmptoicmp6unreach[code]; - if (hlen + sizeof(*icmp) + max_linkhdr + - fin->fin_plen > avail) { + if (iclen + max_linkhdr + fin->fin_plen > avail) { MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { FREE_MB_T(m); @@ -1003,11 +650,11 @@ int dst; } avail = MCLBYTES; } - xtra = MIN(fin->fin_plen, - avail - hlen - sizeof(*icmp) - max_linkhdr); + xtra = MIN(fin->fin_plen, avail - iclen - max_linkhdr); + xtra = MIN(xtra, IPV6_MMTU - iclen); if (dst == 0) { - if (fr_ifpaddr(6, FRI_NORMAL, ifp, - (struct in_addr *)&dst6, NULL) == -1) { + if (ipf_ifpaddr(&ipfmain, 6, FRI_NORMAL, ifp, + &dst6, NULL) == -1) { FREE_MB_T(m); return -1; } @@ -1020,7 +667,6 @@ int dst; return -1; } - iclen = hlen + sizeof(*icmp); avail -= (max_linkhdr + iclen); if (avail < 0) { FREE_MB_T(m); @@ -1041,9 +687,17 @@ int dst; 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); + if (type == ICMP_UNREACH && fin->fin_icode == ICMP_UNREACH_NEEDFRAG) { + if (fin->fin_mtu != 0) { + icmp->icmp_nextmtu = htons(fin->fin_mtu); + + } else if (ifp != NULL) { + icmp->icmp_nextmtu = htons(GETIFMTU_4(ifp)); + + } else { /* make up a number... */ + icmp->icmp_nextmtu = htons(fin->fin_plen - 20); + } + } #endif bcopy((char *)fin->fin_ip, (char *)ip2, ohlen); @@ -1055,8 +709,8 @@ int dst; ip6->ip6_plen = htons(iclen - hlen); ip6->ip6_nxt = IPPROTO_ICMPV6; ip6->ip6_hlim = 0; - ip6->ip6_src = dst6; - ip6->ip6_dst = fin->fin_src6; + ip6->ip6_src = dst6.in6; + ip6->ip6_dst = fin->fin_src6.in6; if (xtra > 0) bcopy((char *)fin->fin_ip + ohlen, (char *)&icmp->icmp_ip + ohlen, xtra); @@ -1065,8 +719,6 @@ int dst; } else #endif { - ip2->ip_len = htons(ip2->ip_len); - ip2->ip_off = htons(ip2->ip_off); ip->ip_p = IPPROTO_ICMP; ip->ip_src.s_addr = dst4.s_addr; ip->ip_dst.s_addr = fin->fin_saddr; @@ -1076,10 +728,10 @@ int dst; (char *)&icmp->icmp_ip + ohlen, xtra); icmp->icmp_cksum = ipf_cksum((u_short *)icmp, sizeof(*icmp) + 8); - ip->ip_len = iclen; + ip->ip_len = htons(iclen); ip->ip_p = IPPROTO_ICMP; } - err = fr_send_ip(fin, m, &m); + err = ipf_send_ip(fin, m); return err; } @@ -1096,28 +748,36 @@ void # endif iplinit() { - if (iplattach() != 0) + if (ipfattach() != 0) printf("IP Filter failed to attach\n"); ip_init(); } #endif /* __FreeBSD_version < 300000 */ -int fr_fastroute(m0, mpp, fin, fdp) -mb_t *m0, **mpp; -fr_info_t *fin; -frdest_t *fdp; +/* + * m0 - pointer to mbuf where the IP packet starts + * mpp - pointer to the mbuf pointer that is the start of the mbuf chain + */ +int +ipf_fastroute(m0, mpp, fin, fdp) + mb_t *m0, **mpp; + fr_info_t *fin; + frdest_t *fdp; { register struct ip *ip, *mhip; - register struct mbuf *m = m0; + register struct mbuf *m = *mpp; register struct route *ro; int len, off, error = 0, hlen, code; struct ifnet *ifp, *sifp; struct sockaddr_in *dst; struct route iproute; u_short ip_off; + frdest_t node; frentry_t *fr; + ro = NULL; + #ifdef M_WRITABLE /* * HOT FIX/KLUDGE: @@ -1131,15 +791,15 @@ frdest_t *fdp; * problem. */ if (M_WRITABLE(m) == 0) { - if ((m0 = m_dup(m, M_DONTWAIT)) != 0) { + m0 = m_dup(m, M_DONTWAIT); + if (m0 != 0) { FREE_MB_T(m); m = m0; *mpp = m; } else { error = ENOBUFS; FREE_MB_T(m); - *mpp = NULL; - fr_frouteok[1]++; + goto done; } } #endif @@ -1151,48 +811,45 @@ frdest_t *fdp; * for IPv6 */ #if (__FreeBSD_version >= 490000) - return ip6_output(m0, NULL, NULL, 0, NULL, NULL, NULL); + return ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL); #else - return ip6_output(m0, NULL, NULL, 0, NULL, NULL); + return ip6_output(m, NULL, NULL, 0, NULL, NULL); #endif } #endif hlen = fin->fin_hlen; ip = mtod(m0, struct ip *); + ifp = NULL; /* * Route packet. */ ro = &iproute; - bzero((caddr_t)ro, sizeof (*ro)); + bzero(ro, sizeof (*ro)); dst = (struct sockaddr_in *)&ro->ro_dst; dst->sin_family = AF_INET; dst->sin_addr = ip->ip_dst; fr = fin->fin_fr; + if ((fr != NULL) && !(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) && + (fdp->fd_type == FRD_DSTLIST)) { + if (ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node) == 0) + fdp = &node; + } + if (fdp != NULL) - ifp = fdp->fd_ifp; + ifp = fdp->fd_ptr; else ifp = fin->fin_ifp; - if ((ifp == NULL) && (!fr || !(fr->fr_flags & FR_FASTROUTE))) { + if ((ifp == NULL) && ((fr == NULL) || !(fr->fr_flags & FR_FASTROUTE))) { error = -2; goto bad; } - /* - * In case we're here due to "to <if>" being used with "keep state", - * check that we're going in the correct direction. - */ - if ((fr != NULL) && (fin->fin_rev != 0)) { - if ((ifp != NULL) && (fdp == &fr->fr_tif)) - return -1; - } - if (fdp != NULL) { - if (fdp->fd_ip.s_addr != 0) - dst->sin_addr = fdp->fd_ip; - } + if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0)) + dst->sin_addr = fdp->fd_ip; dst->sin_len = sizeof(*dst); rtalloc(ro); @@ -1215,21 +872,23 @@ frdest_t *fdp; /* * For input packets which are being "fastrouted", they won't * go back through output filtering and miss their chance to get - * NAT'd and counted. + * NAT'd and counted. Duplicated packets aren't considered to be + * part of the normal packet stream, so do not NAT them or pass + * them through stateful checking, etc. */ - if (fin->fin_out == 0) { + if ((fdp != &fr->fr_dif) && (fin->fin_out == 0)) { sifp = fin->fin_ifp; fin->fin_ifp = ifp; fin->fin_out = 1; - (void) fr_acctpkt(fin, NULL); + (void) ipf_acctpkt(fin, NULL); fin->fin_fr = NULL; if (!fr || !(fr->fr_flags & FR_RETMASK)) { u_32_t pass; - (void) fr_checkstate(fin, &pass); + (void) ipf_state_check(fin, &pass); } - switch (fr_checknatout(fin, NULL)) + switch (ipf_nat_checkout(fin, NULL)) { case 0 : break; @@ -1238,7 +897,7 @@ frdest_t *fdp; break; case -1 : error = -1; - goto done; + goto bad; break; } @@ -1249,14 +908,17 @@ frdest_t *fdp; /* * If small enough for interface, can just send directly. */ - if (ip->ip_len <= ifp->if_mtu) { - ip->ip_len = htons(ip->ip_len); - ip->ip_off = htons(ip->ip_off); + if (ntohs(ip->ip_len) <= ifp->if_mtu) { if (!ip->ip_sum) ip->ip_sum = in_cksum(m, hlen); error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, - ro->ro_rt); +#if (__FreeBSD_version < 800000) + ro->ro_rt +#else + ro +#endif + ); goto done; } /* @@ -1284,7 +946,7 @@ frdest_t *fdp; */ m0 = m; mhlen = sizeof (struct ip); - for (off = hlen + len; off < ip->ip_len; off += len) { + for (off = hlen + len; off < ntohs(ip->ip_len); off += len) { #ifdef MGETHDR MGETHDR(m, M_DONTWAIT, MT_HEADER); #else @@ -1304,11 +966,12 @@ frdest_t *fdp; } m->m_len = mhlen; mhip->ip_off = ((off - hlen) >> 3) + ip_off; - if (off + len >= ip->ip_len) - len = ip->ip_len - off; + if (off + len >= ntohs(ip->ip_len)) + len = ntohs(ip->ip_len) - off; else mhip->ip_off |= IP_MF; mhip->ip_len = htons((u_short)(len + mhlen)); + *mnext = m; m->m_next = m_copy(m0, off, len); if (m->m_next == 0) { error = ENOBUFS; /* ??? */ @@ -1319,7 +982,6 @@ frdest_t *fdp; mhip->ip_off = htons((u_short)mhip->ip_off); mhip->ip_sum = 0; mhip->ip_sum = in_cksum(m, mhlen); - *mnext = m; mnext = &m->m_act; } /* @@ -1337,21 +999,26 @@ sendorfree: m->m_act = 0; if (error == 0) error = (*ifp->if_output)(ifp, m, - (struct sockaddr *)dst, ro->ro_rt); + (struct sockaddr *)dst, +#if (__FreeBSD_version < 800000) + ro->ro_rt +#else + ro +#endif + ); else FREE_MB_T(m); } - } + } done: if (!error) - fr_frouteok[0]++; + ipfmain.ipf_frouteok[0]++; else - fr_frouteok[1]++; + ipfmain.ipf_frouteok[1]++; - if (ro->ro_rt) { + if ((ro != NULL) && (ro->ro_rt != NULL)) { RTFREE(ro->ro_rt); } - *mpp = NULL; return 0; bad: if (error == EMSGSIZE) { @@ -1359,7 +1026,7 @@ bad: code = fin->fin_icode; fin->fin_icode = ICMP_UNREACH_NEEDFRAG; fin->fin_ifp = ifp; - (void) fr_send_icmp_err(ICMP_UNREACH, fin, 1); + (void) ipf_send_icmp_err(ICMP_UNREACH, fin, 1); fin->fin_ifp = sifp; fin->fin_icode = code; } @@ -1368,8 +1035,9 @@ bad: } -int fr_verifysrc(fin) -fr_info_t *fin; +int +ipf_verifysrc(fin) + fr_info_t *fin; { struct sockaddr_in *dst; struct route iproute; @@ -1389,10 +1057,12 @@ fr_info_t *fin; /* * return the first IP Address associated with an interface */ -int fr_ifpaddr(v, atype, ifptr, inp, inpmask) -int v, atype; -void *ifptr; -struct in_addr *inp, *inpmask; +int +ipf_ifpaddr(softc, v, atype, ifptr, inp, inpmask) + ipf_main_softc_t *softc; + int v, atype; + void *ifptr; + i6addr_t *inp, *inpmask; { #ifdef USE_INET6 struct in6_addr *inp6 = NULL; @@ -1409,10 +1079,10 @@ struct in_addr *inp, *inpmask; ifp = ifptr; if (v == 4) - inp->s_addr = 0; + inp->in4.s_addr = 0; #ifdef USE_INET6 else if (v == 6) - bzero((char *)inp, sizeof(struct in6_addr)); + bzero((char *)inp, sizeof(*inp)); #endif #if (__FreeBSD_version >= 300000) ifa = TAILQ_FIRST(&ifp->if_addrhead); @@ -1451,20 +1121,25 @@ struct in_addr *inp, *inpmask; else if (atype == FRI_PEERADDR) sock = ifa->ifa_dstaddr; + if (sock == NULL) + return -1; + #ifdef USE_INET6 if (v == 6) { - return fr_ifpfillv6addr(atype, (struct sockaddr_in6 *)sock, - (struct sockaddr_in6 *)mask, - inp, inpmask); + return ipf_ifpfillv6addr(atype, (struct sockaddr_in6 *)sock, + (struct sockaddr_in6 *)mask, + inp, inpmask); } #endif - return fr_ifpfillv4addr(atype, (struct sockaddr_in *)sock, - (struct sockaddr_in *)mask, inp, inpmask); + return ipf_ifpfillv4addr(atype, (struct sockaddr_in *)sock, + (struct sockaddr_in *)mask, + &inp->in4, &inpmask->in4); } -u_32_t fr_newisn(fin) -fr_info_t *fin; +u_32_t +ipf_newisn(fin) + fr_info_t *fin; { u_32_t newiss; #if (__FreeBSD_version >= 400000) @@ -1507,25 +1182,23 @@ fr_info_t *fin; /* ------------------------------------------------------------------------ */ -/* Function: fr_nextipid */ +/* Function: ipf_nextipid */ /* Returns: int - 0 == success, -1 == error (packet should be droppped) */ /* Parameters: fin(I) - pointer to packet information */ /* */ /* Returns the next IPv4 ID to use for this packet. */ /* ------------------------------------------------------------------------ */ -u_short fr_nextipid(fin) -fr_info_t *fin; +u_short +ipf_nextipid(fin) + fr_info_t *fin; { -#ifndef RANDOM_IP_ID - static u_short ipid = 0; u_short id; - MUTEX_ENTER(&ipf_rw); +#ifndef RANDOM_IP_ID + MUTEX_ENTER(&ipfmain.ipf_rw); id = ipid++; - MUTEX_EXIT(&ipf_rw); + MUTEX_EXIT(&ipfmain.ipf_rw); #else - u_short id; - id = ip_randomid(); #endif @@ -1533,8 +1206,9 @@ fr_info_t *fin; } -INLINE void fr_checkv4sum(fin) -fr_info_t *fin; +INLINE int +ipf_checkv4sum(fin) + fr_info_t *fin; { #ifdef CSUM_DATA_VALID int manual = 0; @@ -1543,7 +1217,13 @@ fr_info_t *fin; mb_t *m; if ((fin->fin_flx & FI_NOCKSUM) != 0) - return; + return 0; + + if ((fin->fin_flx & FI_SHORT) != 0) + return 1; + + if (fin->fin_cksum != FI_CK_NEEDED) + return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; m = fin->fin_m; if (m == NULL) { @@ -1552,50 +1232,88 @@ fr_info_t *fin; } ip = fin->fin_ip; + if ((m->m_pkthdr.csum_flags & (CSUM_IP_CHECKED|CSUM_IP_VALID)) == + CSUM_IP_CHECKED) { + fin->fin_cksum = FI_CK_BAD; + fin->fin_flx |= FI_BAD; + return -1; + } if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) { if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) sum = m->m_pkthdr.csum_data; else sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, htonl(m->m_pkthdr.csum_data + - fin->fin_ip->ip_len + fin->fin_p)); + fin->fin_ip->ip_len - + (fin->fin_ip->ip_hl << 2) + + fin->fin_p)); sum ^= 0xffff; - if (sum != 0) + if (sum != 0) { + fin->fin_cksum = FI_CK_BAD; fin->fin_flx |= FI_BAD; - } else - manual = 1; + } else { + fin->fin_cksum = FI_CK_SUMOK; + return 0; + } + } else { + if (m->m_pkthdr.csum_flags == CSUM_DELAY_DATA) { + fin->fin_cksum = FI_CK_L4FULL; + return 0; + } else if (m->m_pkthdr.csum_flags == CSUM_TCP || + m->m_pkthdr.csum_flags == CSUM_UDP) { + fin->fin_cksum = FI_CK_L4PART; + return 0; + } else if (m->m_pkthdr.csum_flags == CSUM_IP) { + fin->fin_cksum = FI_CK_L4PART; + return 0; + } else { + manual = 1; + } + } skipauto: -# ifdef IPFILTER_CKSUM - if (manual != 0) - if (fr_checkl4sum(fin) == -1) + if (manual != 0) { + if (ipf_checkl4sum(fin) == -1) { fin->fin_flx |= FI_BAD; -# else - ; -# endif + return -1; + } + } #else -# ifdef IPFILTER_CKSUM - if (fr_checkl4sum(fin) == -1) + if (ipf_checkl4sum(fin) == -1) { fin->fin_flx |= FI_BAD; -# endif + return -1; + } #endif + return 0; } #ifdef USE_INET6 -INLINE void fr_checkv6sum(fin) -fr_info_t *fin; +INLINE int +ipf_checkv6sum(fin) + fr_info_t *fin; { -# ifdef IPFILTER_CKSUM - if (fr_checkl4sum(fin) == -1) + if ((fin->fin_flx & FI_NOCKSUM) != 0) + return 0; + + if ((fin->fin_flx & FI_SHORT) != 0) + return 1; + + if (fin->fin_cksum != FI_CK_NEEDED) + return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; + + if (ipf_checkl4sum(fin) == -1) { fin->fin_flx |= FI_BAD; -# endif + return -1; + } + return 0; } #endif /* USE_INET6 */ -size_t mbufchainlen(m0) -struct mbuf *m0; -{ +size_t +mbufchainlen(m0) + struct mbuf *m0; + { size_t len; if ((m0->m_flags & M_PKTHDR) != 0) { @@ -1611,29 +1329,30 @@ struct mbuf *m0; /* ------------------------------------------------------------------------ */ -/* Function: fr_pullup */ +/* Function: ipf_pullup */ /* Returns: NULL == pullup failed, else pointer to protocol header */ -/* Parameters: m(I) - pointer to buffer where data packet starts */ +/* Parameters: xmin(I)- pointer to buffer where data packet starts */ /* fin(I) - pointer to packet information */ /* len(I) - number of bytes to pullup */ /* */ /* Attempt to move at least len bytes (from the start of the buffer) into a */ /* single buffer for ease of access. Operating system native functions are */ /* used to manage buffers - if necessary. If the entire packet ends up in */ -/* a single buffer, set the FI_COALESCE flag even though fr_coalesce() has */ +/* a single buffer, set the FI_COALESCE flag even though ipf_coalesce() has */ /* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */ /* and ONLY if the pullup succeeds. */ /* */ -/* We assume that 'min' is a pointer to a buffer that is part of the chain */ +/* We assume that 'xmin' is a pointer to a buffer that is part of the chain */ /* of buffers that starts at *fin->fin_mp. */ /* ------------------------------------------------------------------------ */ -void *fr_pullup(min, fin, len) -mb_t *min; -fr_info_t *fin; -int len; +void * +ipf_pullup(xmin, fin, len) + mb_t *xmin; + fr_info_t *fin; + int len; { - int out = fin->fin_out, dpoff, ipoff; - mb_t *m = min; + int dpoff, ipoff; + mb_t *m = xmin; char *ip; if (m == NULL) @@ -1650,12 +1369,25 @@ int len; dpoff = 0; if (M_LEN(m) < len) { -#ifdef MHLEN + mb_t *n = *fin->fin_mp; /* * Assume that M_PKTHDR is set and just work with what is left * rather than check.. * Should not make any real difference, anyway. */ + if (m != n) { + /* + * Record the mbuf that points to the mbuf that we're + * about to go to work on so that we can update the + * m_next appropriately later. + */ + for (; n->m_next != m; n = n->m_next) + ; + } else { + n = NULL; + } + +#ifdef MHLEN if (len > MHLEN) #else if (len > MLEN) @@ -1667,26 +1399,250 @@ int len; #else FREE_MB_T(*fin->fin_mp); m = NULL; + n = NULL; #endif } else { m = m_pullup(m, len); } - *fin->fin_mp = m; - fin->fin_m = m; + if (n != NULL) + n->m_next = m; if (m == NULL) { - ATOMIC_INCL(frstats[out].fr_pull[1]); + /* + * When n is non-NULL, it indicates that m pointed to + * a sub-chain (tail) of the mbuf and that the head + * of this chain has not yet been free'd. + */ + if (n != NULL) { + FREE_MB_T(*fin->fin_mp); + } + + *fin->fin_mp = NULL; + fin->fin_m = NULL; return NULL; } + + if (n == NULL) + *fin->fin_mp = m; + + while (M_LEN(m) == 0) { + m = m->m_next; + } + fin->fin_m = m; ip = MTOD(m, char *) + ipoff; - } - ATOMIC_INCL(frstats[out].fr_pull[0]); - fin->fin_ip = (ip_t *)ip; - if (fin->fin_dp != NULL) - fin->fin_dp = (char *)fin->fin_ip + dpoff; + fin->fin_ip = (ip_t *)ip; + if (fin->fin_dp != NULL) + fin->fin_dp = (char *)fin->fin_ip + dpoff; + if (fin->fin_fraghdr != NULL) + fin->fin_fraghdr = (char *)ip + + ((char *)fin->fin_fraghdr - + (char *)fin->fin_ip); + } if (len == fin->fin_plen) fin->fin_flx |= FI_COALESCE; return ip; } + + +int +ipf_inject(fin, m) + fr_info_t *fin; + mb_t *m; +{ + int error = 0; + + if (fin->fin_out == 0) { +#if (__FreeBSD_version >= 501000) + netisr_dispatch(NETISR_IP, m); +#else + struct ifqueue *ifq; + + ifq = &ipintrq; + +# ifdef _IF_QFULL + if (_IF_QFULL(ifq)) +# else + if (IF_QFULL(ifq)) +# endif + { +# ifdef _IF_DROP + _IF_DROP(ifq); +# else + IF_DROP(ifq); +# endif + FREE_MB_T(m); + error = ENOBUFS; + } else { + IF_ENQUEUE(ifq, m); + } +#endif + } else { + fin->fin_ip->ip_len = ntohs(fin->fin_ip->ip_len); + fin->fin_ip->ip_off = ntohs(fin->fin_ip->ip_off); +#if (__FreeBSD_version >= 470102) + error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL); +#else + error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL); +#endif + } + + return error; +} + +int ipf_pfil_unhook(void) { +#if defined(NETBSD_PF) && (__FreeBSD_version >= 500011) +# if __FreeBSD_version >= 501108 + struct pfil_head *ph_inet; +# ifdef USE_INET6 + struct pfil_head *ph_inet6; +# endif +# endif +#endif + +#ifdef NETBSD_PF +# if (__FreeBSD_version >= 500011) +# if (__FreeBSD_version >= 501108) + ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); + if (ph_inet != NULL) + pfil_remove_hook((void *)ipf_check_wrapper, NULL, + PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet); +# else + pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK, + &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); +# endif +# else + pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK); +# endif +# ifdef USE_INET6 +# if (__FreeBSD_version >= 501108) + ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); + if (ph_inet6 != NULL) + pfil_remove_hook((void *)ipf_check_wrapper6, NULL, + PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet6); +# else + pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK, + &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh); +# endif +# endif +#endif + + return (0); +} + +int ipf_pfil_hook(void) { +#if defined(NETBSD_PF) && (__FreeBSD_version >= 500011) +# if __FreeBSD_version >= 501108 + struct pfil_head *ph_inet; +# ifdef USE_INET6 + struct pfil_head *ph_inet6; +# endif +# endif +#endif + +# ifdef NETBSD_PF +# if __FreeBSD_version >= 500011 +# if __FreeBSD_version >= 501108 + ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); +# ifdef USE_INET6 + ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); +# endif + if (ph_inet == NULL +# ifdef USE_INET6 + && ph_inet6 == NULL +# endif + ) { + return ENODEV; + } + + if (ph_inet != NULL) + pfil_add_hook((void *)ipf_check_wrapper, NULL, + PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet); +# else + pfil_add_hook((void *)ipf_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK, + &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); +# endif +# else + pfil_add_hook((void *)ipf_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK); +# endif +# ifdef USE_INET6 +# if __FreeBSD_version >= 501108 + if (ph_inet6 != NULL) + pfil_add_hook((void *)ipf_check_wrapper6, NULL, + PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet6); +# else + pfil_add_hook((void *)ipf_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK, + &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh); +# endif +# endif +# endif + return (0); +} + +void +ipf_event_reg(void) +{ +#if (__FreeBSD_version >= 502103) + ipf_arrivetag = EVENTHANDLER_REGISTER(ifnet_arrival_event, \ + ipf_ifevent, &ipfmain, \ + EVENTHANDLER_PRI_ANY); + ipf_departtag = EVENTHANDLER_REGISTER(ifnet_departure_event, \ + ipf_ifevent, &ipfmain, \ + EVENTHANDLER_PRI_ANY); + ipf_clonetag = EVENTHANDLER_REGISTER(if_clone_event, ipf_ifevent, \ + NULL, EVENTHANDLER_PRI_ANY); +#endif +} + +void +ipf_event_dereg(void) +{ +#if (__FreeBSD_version >= 502103) + if (ipf_arrivetag != NULL) { + EVENTHANDLER_DEREGISTER(ifnet_arrival_event, ipf_arrivetag); + } + if (ipf_departtag != NULL) { + EVENTHANDLER_DEREGISTER(ifnet_departure_event, ipf_departtag); + } + if (ipf_clonetag != NULL) { + EVENTHANDLER_DEREGISTER(if_clone_event, ipf_clonetag); + } +#endif +} + + +u_32_t +ipf_random() +{ + return arc4random(); +} + + +u_int +ipf_pcksum(fin, hlen, sum) + fr_info_t *fin; + int hlen; + u_int sum; +{ + struct mbuf *m; + u_int sum2; + int off; + + m = fin->fin_m; + off = (char *)fin->fin_dp - (char *)fin->fin_ip; + m->m_data += hlen; + m->m_len -= hlen; + sum2 = in_cksum(fin->fin_m, fin->fin_plen - off); + m->m_len += hlen; + m->m_data -= hlen; + + /* + * Both sum and sum2 are partial sums, so combine them together. + */ + sum += ~sum2 & 0xffff; + while (sum > 0xffff) + sum = (sum & 0xffff) + (sum >> 16); + sum2 = ~sum & 0xffff; + return sum2; +} diff --git a/ip_fil_hpux.c b/ip_fil_hpux.c new file mode 100644 index 0000000000000..3e0a485ee69de --- /dev/null +++ b/ip_fil_hpux.c @@ -0,0 +1,923 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ +#if !defined(lint) +static const char sccsid[] = "%W% %G% (C) 1993-2000 Darren Reed"; +static const char rcsid[] = "@(#)$Id$"; +#endif + +#include <sys/types.h> +#include <sys/errno.h> +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/systm.h> +#include <sys/socket.h> +#include <sys/cmn_err.h> +#include <sys/kernel.h> +#include <sys/callout.h> +#include <net/if.h> +#include <net/af.h> +#include <net/route.h> +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/ip_var.h> +#include <netinet/tcp.h> +#include <netinet/udp.h> +#include <netinet/tcpip.h> +#include <netinet/ip_icmp.h> +#include "ip_compat.h" +#ifdef USE_INET6 +# include <netinet/icmp6.h> +#endif +#include "ip_fil.h" +#include "ip_state.h" +#include "ip_nat.h" +#include "ip_frag.h" +#include "ip_auth.h" +#include "ip_lookup.h" +#include "ip_dstlist.h" + +#include "md5.h" + +/* + * From Solaris <inet/ip.h>, except HP-UX uses int. + */ +typedef struct ipparam_s { + int ip_param_min; + int ip_param_max; + int ip_param_value; + char *ip_param_name; +} ipparam_t; +extern ipparam_t *ip_param_arr; + +#undef IPFDEBUG +extern int ipf_flags, ipf_active; +extern struct callout *ipf_timer_id; + +static int ipf_send_ip(fr_info_t *, mblk_t *); +ipfmutex_t ipl_mutex, ipf_auth_mx, ipf_rw, ipf_stinsert; +ipfmutex_t ipf_nat_new, ipf_natio, ipf_timeoutlock; +ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag, ipf_frcache, ipf_tokens; +ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_authlk; +int *ip_ttl_ptr; +int *ip_mtudisc; +int *ip_forwarding; + +static u_short ipid = 0; + +int +ipfdetach() +{ + + if (ipf_control_forwarding & 2) + ip_forwarding = 0; +#ifdef IPFDEBUG + cmn_err(CE_CONT, "ipfdetach()\n"); +#endif + ipf_deinitialise(); + + (void) frflush(IPL_LOGIPF, FR_INQUE|FR_OUTQUE|FR_INACTIVE); + (void) frflush(IPL_LOGIPF, FR_INQUE|FR_OUTQUE); + + RW_DESTROY(&ipf_tokens); + RW_DESTROY(&ipf_ipidfrag); + MUTEX_DESTROY(&ipf_timeoutlock); + MUTEX_DESTROY(&ipf_rw); + + return 0; +} + + +int +ipfattach __P((void)) +{ + int i; + +#ifdef IPFDEBUG + cmn_err(CE_CONT, "ipfattach()\n"); +#endif + bzero((char *)ipf_cache, sizeof(ipf_cache)); + MUTEX_INIT(&ipf_rw, "ipf_rw"); + MUTEX_INIT(&ipf_timeoutlock, "ipf_timeoutlock"); + RWLOCK_INIT(&ipf_ipidfrag, "ipf IP NAT-Frag rwlock"); + RWLOCK_INIT(&ipf_tokens, "ipf token rwlock"); + + if (ipf_initialise() < 0) + return -1; + + /* + * XXX - There is no terminator for this array, so it is not possible + * to tell if what we are looking for is missing and go off the end + * of the array. + */ + for (i = 0; ; i++) { + if (!strcmp(ip_param_arr[i].ip_param_name, "ip_def_ttl")) { + ip_ttl_ptr = &ip_param_arr[i].ip_param_value; + } else if (!strcmp(ip_param_arr[i].ip_param_name, + "ip_pmtu_strategy")) { + ip_mtudisc = &ip_param_arr[i].ip_param_value; + } else if (!strcmp(ip_param_arr[i].ip_param_name, + "ip_forwarding")) { + ip_forwarding = &ip_param_arr[i].ip_param_value; + } + + if (ip_mtudisc != NULL && ip_ttl_ptr != NULL && + ip_forwarding != NULL) + break; + } + +#ifdef IPFDEBUG + cmn_err(CE_CONT, "ipfattach() - success!\n"); +#endif + if (ipf_control_forwarding & 1) + *ip_forwarding = 1; + + ipid = 0; + + return 0; +} + + +/* + * Filter ioctl interface. + */ +int +ipfioctl(dev, cmd, data, flags) + dev_t dev; + int cmd; + caddr_t data; + int flags; +{ + int error = 0; + minor_t unit; + +#ifdef IPFDEBUG + cmn_err(CE_CONT, "ipfioctl(%x,%x,%x,%x)\n", + dev, cmd, data, flags); +#endif + + unit = getminor(dev); + if (IPL_LOGMAX < unit) + return ENXIO; + + if (ipf_running <= 0) { + if (unit != IPL_LOGIPF && cmd != SIOCIPFINTERROR) + return EIO; + if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET && + cmd != SIOCIPFSET && cmd != SIOCFRENB && + cmd != SIOCGETFS && cmd != SIOCGETFF && + cmd != SIOCIPFINTERROR) + return EIO; + } + + error = ipf_ioctlswitch(unit, data, cmd, flags, curproc->p_uid, + curproc); + if (error != -1) { + return error; + } + + return error; +} + + +void * +get_unit(name, family) + char *name; + int family; +{ + size_t len = strlen(name) + 1; /* includes \0 */ + qif_t *qf; + int sap; + + if (family == 4) + sap = 0x0800; + else if (family == 6) + return NULL; + spinlock(&pfil_rw); + qf = qif_iflookup(name, sap); + spinunlock(&pfil_rw); + return qf; +} + + +/* + * ipf_send_reset - this could conceivably be a call to tcp_respond(), but that + * requires a large amount of setting up and isn't any more efficient. + */ +int +ipf_send_reset(fin) + fr_info_t *fin; +{ + tcphdr_t *tcp, *tcp2; + int tlen, hlen; + mblk_t *m; +#ifdef USE_INET6 + ip6_t *ip6; +#endif + ip_t *ip; + + tcp = fin->fin_dp; + if (tcp->th_flags & TH_RST) + return -1; + + if (ipf_checkl4sum(fin) == -1) + return -1; + + tlen = (tcp->th_flags & (TH_SYN|TH_FIN)) ? 1 : 0; +#ifdef USE_INET6 + if (fin->fin_v == 6) + hlen = sizeof(ip6_t); + else +#endif + hlen = sizeof(ip_t); + hlen += sizeof(*tcp2); + if ((m = (mblk_t *)allocb(hlen + 16, BPRI_HI)) == NULL) + return -1; + + m->b_rptr += 16; + MTYPE(m) = M_DATA; + m->b_wptr = m->b_rptr + hlen; + bzero((char *)m->b_rptr, hlen); + ip = (ip_t *)m->b_rptr; + bzero((char *)ip, hlen); + ip->ip_v = fin->fin_v; + tcp2 = (struct tcphdr *)(m->b_rptr + hlen - sizeof(*tcp2)); + tcp2->th_dport = tcp->th_sport; + tcp2->th_sport = tcp->th_dport; + 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(struct tcphdr) >> 2; + + /* + * This is to get around a bug in the Solaris 2.4/2.5 TCP checksum + * computation that is done by their put routine. + */ +#ifdef USE_INET6 + if (fin->fin_v == 6) { + ip6 = (ip6_t *)m->b_rptr; + ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; + ip6->ip6_src = fin->fin_dst6; + ip6->ip6_dst = fin->fin_src6; + ip6->ip6_plen = htons(sizeof(*tcp)); + ip6->ip6_nxt = IPPROTO_TCP; + } else +#endif + { + ip->ip_src.s_addr = fin->fin_daddr; + ip->ip_dst.s_addr = fin->fin_saddr; + ip->ip_id = ipf_nextipid(fin); + ip->ip_hl = sizeof(*ip) >> 2; + ip->ip_p = IPPROTO_TCP; + ip->ip_len = htons(sizeof(*ip) + sizeof(*tcp)); + ip->ip_tos = fin->fin_ip->ip_tos; + tcp2->th_sum = ipf_cksum(m, ip, IPPROTO_TCP, tcp2, + ntohs(ip->ip_len)); + } + return ipf_send_ip(fin, m); +} + + +/* + * On input, ip_len is in network byte order. + */ +static int +ipf_send_ip(fr_info_t *fin, mblk_t *m) +{ + int i; + + RWLOCK_EXIT(&ipf_global); +#ifdef USE_INET6 + if (fin->fin_v == 6) { + ip6_t *ip6; + + ip6 = (ip6_t *)m->b_rptr; + ip6->ip6_vfc = 0x60; + ip6->ip6_hlim = 127; + } else +#endif + { + ip_t *ip; + + ip = (ip_t *)m->b_rptr; + ip->ip_v = IPVERSION; + ip->ip_ttl = *ip_ttl_ptr; + ip->ip_off = htons(*ip_mtudisc == 1 ? IP_DF : 0); + ip->ip_sum = ipf_cksum((u_short *)ip, sizeof(*ip)); + } + i = pfil_sendbuf(m); + READ_ENTER(&ipf_global); + return i; +} + + +int +ipf_send_icmp_err(type, fin, dst) + int type; + fr_info_t *fin; + int dst; +{ + struct in_addr dst4; + struct icmp *icmp; + mblk_t *m, *mb; + int hlen, code; + qpktinfo_t *qpi; + i6addr_t dst6; + u_short sz; +#ifdef USE_INET6 + ip6_t *ip6; +#endif + ip_t *ip; + + if ((type < 0) || (type > ICMP_MAXTYPE)) + return -1; + + code = fin->fin_icode; +#ifdef USE_INET6 + if ((code < 0) || (code > sizeof(icmptoicmp6unreach)/sizeof(int))) + return -1; +#endif + + if (ipf_checkl4sum(fin) == -1) + return -1; + + qpi = fin->fin_qpi; + mb = fin->fin_qfm; + +#ifdef USE_INET6 + if (fin->fin_v == 6) { + sz = sizeof(ip6_t); + sz += MIN(mb->b_wptr - mb->b_rptr, 512); + hlen = sizeof(ip6_t); + type = icmptoicmp6types[type]; + if (type == ICMP6_DST_UNREACH) + code = icmptoicmp6unreach[code]; + } else +#endif + { + if ((fin->fin_p == IPPROTO_ICMP) && !(fin->fin_flx & FI_SHORT)) + switch (ntohs(fin->fin_data[0]) >> 8) + { + case ICMP_ECHO : + case ICMP_TSTAMP : + case ICMP_IREQ : + case ICMP_MASKREQ : + break; + default : + return 0; + } + + sz = sizeof(ip_t) * 2; + sz += 8; /* 64 bits of data */ + hlen = sizeof(ip_t); + } + + sz += offsetof(struct icmp, icmp_ip); + if ((m = (mblk_t *)allocb((size_t)sz + 16, BPRI_HI)) == NULL) + return -1; + MTYPE(m) = M_DATA; + m->b_rptr += 16; + m->b_wptr = m->b_rptr + sz; + bzero((char *)m->b_rptr, (size_t)sz); + ip = (ip_t *)m->b_rptr; + ip->ip_v = fin->fin_v; + icmp = (struct icmp *)(m->b_rptr + hlen); + icmp->icmp_type = type; + icmp->icmp_code = code; + +#ifdef USE_INET6 + if (fin->fin_v == 6) { + int csz; + + if (dst == 0) { + if (ipf_ifpaddr(softc, 6, FRI_NORMAL, qpi->qpi_real, + &dst6, NULL) == -1) { + FREE_MB_T(m); + return -1; + } + } else + dst6 = fin->fin_dst6; + + csz = sz; + sz -= sizeof(ip6_t); + ip6 = (ip6_t *)m->b_rptr; + ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; + ip6->ip6_plen = htons((u_short)sz); + ip6->ip6_nxt = IPPROTO_ICMPV6; + ip6->ip6_src = dst6; + ip6->ip6_dst = fin->fin_src6; + sz -= offsetof(struct icmp, icmp_ip); + bcopy((char *)mb->b_rptr, (char *)&icmp->icmp_ip, sz); + icmp->icmp_cksum = csz - sizeof(ip6_t); + } else +#endif + { + ip->ip_hl = sizeof(*ip) >> 2; + ip->ip_p = IPPROTO_ICMP; + ip->ip_id = fin->fin_ip->ip_id; + ip->ip_tos = fin->fin_ip->ip_tos; + ip->ip_len = (u_short)sz; + if (dst == 0) { + if (ipf_ifpaddr(softc, 4, FRI_NORMAL, qpi->qpi_real, + &dst6, NULL) == -1) { + FREE_MB_T(m); + return -1; + } + dst4 = dst6.in4; + } else + dst4 = fin->fin_dst; + ip->ip_src = dst4; + ip->ip_dst = fin->fin_src; + bcopy((char *)fin->fin_ip, (char *)&icmp->icmp_ip, + sizeof(*fin->fin_ip)); + bcopy((char *)fin->fin_ip + fin->fin_hlen, + (char *)&icmp->icmp_ip + sizeof(*fin->fin_ip), 8); + icmp->icmp_cksum = ipf_cksum((u_short *)icmp, + sz - sizeof(ip_t)); + } + + /* + * Need to exit out of these so we don't recursively call rw_enter + * from fr_qout. + */ + return ipf_send_ip(fin, m); +} + + +/* + * return the first IP Address associated with an interface + */ +int +ipf_ifpaddr(softc, v, atype, qifptr, inp, inpmask) + ipf_main_softc_t *softc; + int v, atype; + void *qifptr; + i6addr_t *inp, *inpmask; +{ +#ifdef USE_INET6 + struct sockaddr_in6 sin6, mask6; +#endif + struct sockaddr_in sin, mask; + qif_t *qif = qifptr; + + if ((qifptr == NULL) || (qifptr == (void *)-1)) + return -1; + +#ifdef USE_INET6 + if (v == 6) { + return ENOTSUP; + } +#endif + + switch (atype) + { + case FRI_BROADCAST : + sin.sin_addr.s_addr = QF_V4_BROADCAST(qif); + break; + case FRI_PEERADDR : + sin.sin_addr.s_addr = QF_V4_PEERADDR(qif); + break; + default : + sin.sin_addr.s_addr = QF_V4_ADDR(qif); + break; + } + mask.sin_addr.s_addr = QF_V4_NETMASK(qif); + + return ipf_ifpfillv4addr(atype, &sin, &mask, &inp->in4, &inpmask->in4); +} + + +#ifdef IPL_SELECT +extern iplog_select_t iplog_ss[IPL_LOGSIZE]; +extern int selwait; + +/* + * iplog_input_ready and ipflog_select are both submissions from HP. + */ +void +iplog_input_ready(unit) + minor_t unit; +{ + if (iplog_ss[unit].read_waiter) { + selwakeup(iplog_ss[unit].read_waiter, + iplog_ss[unit].state & READ_COLLISION); + iplog_ss[unit].read_waiter = 0; + iplog_ss[unit].state &= READ_COLLISION; + } +} + + +int +iplselect(unit, flag) + minor_t unit; + int flag; +{ + kthread_t * t; + + MUTEX_ENTER(&ipl_mutex); + switch (flag) + { + case FREAD: + if (softc->ipf_iplused[unit]) { + MUTEX_EXIT(&ipl_mutex); + return 1; + } + if ((t = iplog_ss[unit].read_waiter) && +# if HPUXREV >= 1111 + waiting_in_select(t) +# else + (kt_wchan(t) == (caddr_t)&selwait) +# endif + ) { + iplog_ss[unit].state |= READ_COLLISION; + } else { + iplog_ss[unit].read_waiter = u.u_kthreadp; + } + break; + } + MUTEX_EXIT(&ipl_mutex); + return 0; +} +#endif + + +u_32_t +ipf_newisn(fin) + fr_info_t *fin; +{ + static iss_seq_off = 0; + u_char hash[16]; + u_32_t newiss; + MD5_CTX ctx; + + /* + * Compute the base value of the ISS. It is a hash + * of (saddr, sport, daddr, dport, secret). + */ + MD5Init(&ctx); + + MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, + sizeof(fin->fin_fi.fi_src)); + MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, + sizeof(fin->fin_fi.fi_dst)); + MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); + + MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); + + MD5Final(hash, &ctx); + + memcpy(&newiss, hash, sizeof(newiss)); + + /* + * Now increment our "timer", and add it in to + * the computed value. + * + * XXX Use `addin'? + * XXX TCP_ISSINCR too large to use? + */ + iss_seq_off += 0x00010000; + newiss += iss_seq_off; + return newiss; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nextipid */ +/* Returns: int - 0 == success, -1 == error (packet should be droppped) */ +/* Parameters: fin(I) - pointer to packet information */ +/* */ +/* Returns the next IPv4 ID to use for this packet. */ +/* ------------------------------------------------------------------------ */ +INLINE u_short +ipf_nextipid(fin) + fr_info_t *fin; +{ + u_short id; + + MUTEX_ENTER(&ipf_rw); + id = ipid++; + MUTEX_EXIT(&ipf_rw); + + return id; +} + + +INLINE int +ipf_checkv4sum(fin) + fr_info_t *fin; +{ + if ((fin->fin_flx & FI_NOCKSUM) != 0) + return 0; + + if ((fin->fin_flx & FI_SHORT) != 0) + return 1; + + if (fin->fin_cksum != FI_CK_NEEDED) + return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; + + if (ipf_checkl4sum(fin) == -1) { + fin->fin_flx |= FI_BAD; + return -1; + } + return 0; +} + + +#ifdef USE_INET6 +INLINE int +ipf_checkv6sum(fin) + fr_info_t *fin; +{ + if ((fin->fin_flx & FI_NOCKSUM) != 0) + return 0; + + if ((fin->fin_flx & FI_SHORT) != 0) + return 1; + + if (fin->fin_cksum != FI_CK_NEEDED) + return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; + + if (ipf_checkl4sum(fin) == -1) { + fin->fin_flx |= FI_BAD; + return -1; + } + return 0; +} +#endif /* USE_INET6 */ + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pullup */ +/* Returns: NULL == pullup failed, else pointer to protocol header */ +/* Parameters: xmin(I)- pointer to buffer where data packet starts */ +/* fin(I) - pointer to packet information */ +/* len(I) - number of bytes to pullup */ +/* */ +/* Attempt to move at least len bytes (from the start of the buffer) into a */ +/* single buffer for ease of access. Operating system native functions are */ +/* used to manage buffers - if necessary. If the entire packet ends up in */ +/* a single buffer, set the FI_COALESCE flag even though ipf_coalesce() has */ +/* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */ +/* and ONLY if the pullup succeeds. */ +/* */ +/* We assume that 'xmin' is a pointer to a buffer that is part of the chain */ +/* of buffers that starts at *fin->fin_mp. */ +/* ------------------------------------------------------------------------ */ +void * +ipf_pullup(xmin, fin, len) + mb_t *xmin; + fr_info_t *fin; + int len; +{ + qpktinfo_t *qpi = fin->fin_qpi; + int out = fin->fin_out, dpoff, ipoff; + mb_t *m = xmin; + char *ip; + + if (m == NULL) + return NULL; + + ip = (char *)fin->fin_ip; + if ((fin->fin_flx & FI_COALESCE) != 0) + return ip; + + ipoff = fin->fin_ipoff; + if (fin->fin_dp != NULL) + dpoff = (char *)fin->fin_dp - (char *)ip; + else + dpoff = 0; + + if (M_LEN(m) < len) { + int inc = 0; + + if (ipoff > 0) { + if ((ipoff & 3) != 0) { + inc = 4 - (ipoff & 3); + if (m->b_rptr - inc >= m->b_datap->db_base) + m->b_rptr -= inc; + else + inc = 0; + } + } + m = msgpullup(xmin, len + ipoff + inc); + if (m == NULL) { + FREE_MB_T(*fin->fin_mp); + *fin->fin_mp = NULL; + fin->fin_m = NULL; + return NULL; + } + + /* + * Because msgpullup allocates a new mblk, we need to delink + * (and free) the old one and link on the new one. + */ + if (xmin == *fin->fin_mp) { /* easy case 1st */ + FREE_MB_T(*fin->fin_mp); + *fin->fin_mp = m; + } else { + mb_t *m2; + + for (m2 = *fin->fin_mp; m2 != NULL; m2 = m2->b_next) + if (m2->b_next == xmin) + break; + if (m2 == NULL) { + FREE_MB_T(*fin->fin_mp); + FREE_MB_T(m); + return NULL; + } + FREE_MB_T(xmin); + m2->b_next = m; + } + + fin->fin_m = m; + m->b_rptr += inc; + ip = MTOD(m, char *) + ipoff; + qpi->qpi_data = ip; + + fin->fin_ip = (ip_t *)ip; + if (fin->fin_dp != NULL) + fin->fin_dp = (char *)fin->fin_ip + dpoff; + if (fin->fin_fraghdr != NULL) + fin->fin_fraghdr = (char *)ip + + ((char *)fin->fin_fraghdr - + (char *)fin->fin_ip); + } + + if (len == fin->fin_plen) + fin->fin_flx |= FI_COALESCE; + return ip; +} + + +/* + * m0 - pointer to mbuf where the IP packet starts + * mpp - pointer to the mbuf pointer that is the start of the mbuf chain + */ +int +ipf_fastroute(mb, mpp, fin, fdp) + mblk_t *mb, **mpp; + fr_info_t *fin; + frdest_t *fdp; +{ +#ifdef USE_INET6 + ip6_t *ip6 = (ip6_t *)fin->fin_ip; +#endif + struct in_addr dst, src; + ifinfo_t *ifp, *sifp; + mblk_t *mp, **mps; + size_t hlen = 0; + qpktinfo_t *qpi; + frdest_t node; + frentry_t *fr; + irinfo_t ir; + queue_t *q; + u_char *s; + ip_t *ip; + int p, i; + + fr = fin->fin_fr; + ip = fin->fin_ip; + qpi = fin->fin_qpi; + /* + * If this is a duplicate mblk then we want ip to point at that + * data, not the original, if and only if it is already pointing at + * the current mblk data. + */ + if (ip == (ip_t *)qpi->qpi_m->b_rptr && qpi->qpi_m != mb) + ip = (ip_t *)mb->b_rptr; + + /* + * If there is another M_PROTO, we don't want it + */ + if (*mpp != mb) { + mp = *mpp; + (void) unlinkb(mp); + mp = (*mpp)->b_cont; + (*mpp)->b_cont = NULL; + (*mpp)->b_prev = NULL; + freemsg(*mpp); + *mpp = mp; + } + + if ((fr != NULL) && !(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) && + (fdp->fd_type == FRD_DSTLIST)) { + if (ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node) == 0) + fdp = &node; + } + ifp = (ifinfo_t *)fdp->fd_ptr; + if (fdp && fdp->fd_ip.s_addr) + dst = fdp->fd_ip; + else + dst.s_addr = fin->fin_fi.fi_daddr; + + src.s_addr = 0; + bzero((char *)&ir, sizeof(ir)); + i = ir_lookup(&ir, &dst.s_addr, &src.s_addr, + ~(IR_ROUTE|IR_ROUTE_ASSOC|IR_ROUTE_REDIRECT), 4); + mp = ir.ir_ll_hdr_mp; + hlen = ir.ir_ll_hdr_length; + if (!mp || !hlen || (i == 0)) + goto bad_fastroute; + + if ((ifp || (fr && (fr->fr_flags & FR_FASTROUTE)))) { + if (ifp && (ir_to_ill(&ir) != ifp)) + goto bad_fastroute; + + if (fin->fin_out == 0) { + sifp = fin->fin_ifp; + fin->fin_ifp = ir_to_ill(&ir); + fin->fin_out = 1; + (void) ipf_acctpkt(fin, NULL); + fin->fin_fr = NULL; + if (!fr || !(fr->fr_flags & FR_RETMASK)) { + u_32_t pass; + + fin->fin_flx &= ~FI_STATE; + (void) ipf_state_check(fin, &pass); + } + + switch (ipf_nat_checkout(fin, NULL)) + { + case 0 : + break; + case 1 : + break; + case -1 : + goto bad_fastroute; + break; + } + + fin->fin_out = 0; + fin->fin_ifp = sifp; + } + + s = mb->b_rptr; + if ((hlen && (s - mb->b_datap->db_base) >= hlen)) { + s -= hlen; + mb->b_rptr = (u_char *)s; + bcopy((char *)mp->b_rptr, (char *)s, hlen); + freeb(mp); + mp = NULL; + } else { + mblk_t *mp2; + + linkb(mp, *mpp); + *mpp = mp; + mb = mp; + mp = NULL; + } + + q = NULL; + if (ir.ir_stq) + q = ir.ir_stq; + else if (ir.ir_rfq) + q = WR(ir.ir_rfq); + if (q) + q = q->q_next; + if (q) { + mb->b_prev = NULL; + RWLOCK_EXIT(&ipf_global); + putnext(q, mb); + READ_ENTER(&ipf_global); + ipf_frouteok[0]++; + return 0; + } + } +bad_fastroute: + if (mp) + freeb(mp); + mb->b_prev = NULL; + freemsg(*mpp); + ipf_frouteok[1]++; + return -1; +} + + +int +ipf_verifysrc(fin) + fr_info_t *fin; +{ + struct in_addr ips, ipa; + irinfo_t ir, *dir, *gw; + qif_t *qif; + int i; + + ips.s_addr = 0; + ipa = fin->fin_src; + + if (ir_lookup(&ir, (uint32_t *)&ipa, (uint32_t *)&ips, 0, 4) == 0) + return 1; + i = (ir_to_ill(&ir) == fin->fin_ifp); + if (ir.ir_ll_hdr_mp) + freeb(ir.ir_ll_hdr_mp); + return i; +} diff --git a/ip_fil_irix.c b/ip_fil_irix.c new file mode 100644 index 0000000000000..2237fc3b81cab --- /dev/null +++ b/ip_fil_irix.c @@ -0,0 +1,1369 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ +#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$"; +#endif + +#if defined(KERNEL) || defined(_KERNEL) +# undef KERNEL +# undef _KERNEL +# define KERNEL 1 +# define _KERNEL 1 +#endif +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/types.h> +#include <sys/file.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/systm.h> +#include <sys/dir.h> +#include <sys/mbuf.h> +#include <sys/protosw.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <net/if.h> +#include <sys/debug.h> +#ifdef IFF_DRVRLOCK /* IRIX6 */ +# include <sys/hashing.h> +#endif +#include <net/route.h> +#include <netinet/in.h> +#if !defined(IFF_DRVRLOCK) /* IRIX < 6 */ +# include <netinet/in_var.h> +#endif +#include <netinet/in_systm.h> +#include <netinet/in_var.h> +#include <netinet/ip.h> +#include <netinet/ip_var.h> +#include <netinet/tcp.h> +#include <netinet/tcp_timer.h> +#include <netinet/udp.h> +#include <netinet/tcpip.h> +#include <netinet/ip_icmp.h> +#include "netinet/ip_compat.h" +#ifdef USE_INET6 +# include <netinet/icmp6.h> +#endif +#include "netinet/ip_fil.h" +#include "netinet/ip_nat.h" +#include "netinet/ip_frag.h" +#include "netinet/ip_state.h" +#include "netinet/ip_proxy.h" +#include "netinet/ip_auth.h" +#include "netinet/ip_sync.h" +#include "netinet/ip_lookup.h" +#include "netinet/ip_dstlist.h" +#ifdef IPFILTER_SCAN +#include "netinet/ip_scan.h" +#endif + +#include "md5.h" + +extern int tcp_mtudisc; +extern int ipforwarding; +extern struct protosw inetsw[]; +extern int tcp_ttl; +#if IRIX >= 60500 +extern toid_t ipf_timer_id; +#endif + +static u_short ipid = 0; +static int (*ipf_savep) __P((ip_t *, int, void *, int, struct mbuf **)); +static int ipf_send_ip __P((fr_info_t *, struct mbuf *)); +static int ipfopen __P((dev_t *, int, int, cred_t *)); +static int ipfclose __P((dev_t *, int, int, cred_t *)); +static int ipfread __P((dev_t, struct uio *, cred_t *)); + + +int +ipf_attach() +{ + int error = 0, s; + + SPL_NET(s); + if (ipf_running > 0) { + SPL_X(s); + return EBUSY; + } + + if (ipf_initialise() < 0) + return -1; + + error = ipf_ipfilter_attach(); + if (error) { + ipf_deinitialise(); + SPL_X(s); + return error; + } + + if (ipf_checkp != ipf_check) { + ipf_savep = ipf_checkp; + ipf_checkp = ipf_check; + } + + if (ipf_control_forwarding & 1) + ipforwarding = 1; + + ipid = 0; + + SPL_X(s); + +#if IRIX >= 60500 + ipf_timer_id = timeout(ipf_slowtimer, &ipfmain, hz/2); +#else + timeout(ipf_slowtimer, &ipfmain, hz/2); +#endif + return 0; +} + + +/* + * Disable the filter by removing the hooks from the IP input/output + * stream. + */ +int +ipf_detach() +{ + int s, error = 0; + + SPL_NET(s); + +#if IRIX >= 60500 + if (ipf_timer_id != 0) { + /* error = untimeout(ipf_timer_id); XXX - does not work with */ + /* timeout() return value, only itimeout() and dtimeout(). */ + ipf_timer_id = 0; + } +#else + untimeout(ipf_slowtimer); +#endif + + if (ipf_control_forwarding & 2) + ipforwarding = 0; + + ipf_deinitialise(); + + if (ipf_savep != NULL) + ipf_checkp = ipf_savep; + ipf_savep = NULL; + (void) frflush(&ipfmain, IPL_LOGIPF, FR_INQUE|FR_OUTQUE|FR_INACTIVE); + (void) frflush(&ipfmain, IPL_LOGIPF, FR_INQUE|FR_OUTQUE); + + ipf_ipfilter_detach(); + + SPL_X(s); + return 0; +} + + +/* + * Filter ioctl interface. + */ +int +ipfioctl(dev, cmd, data, mode, cp, rp) + dev_t dev; + int cmd; + caddr_t data; + int mode; + cred_t *cp; + int *rp; +{ + int error = 0, unit = 0; + SPL_INT(s); + + unit = GET_MINOR(dev); + if ((IPL_LOGMAX < unit) || (unit < 0)) { + ipfmain.ipf_interror = 130002; + return ENXIO; + } + + if (ipf_running <= 0) { + if (unit != IPL_LOGIPF && cmd != SIOCIPFINTERROR) { + ipfmain.ipf_interror = 130003; + return EIO; + } + if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET && + cmd != SIOCIPFSET && cmd != SIOCFRENB && + cmd != SIOCGETFS && cmd != SIOCGETFF && + cmd != SIOCIPFINTERROR) { + ipfmain.ipf_interror = 130004; + return EIO; + } + } + + SPL_NET(s); + + error = ipf_ioctlswitch(&ipfmain, unit, data, cmd, mode, + cp->cr_uid, curproc); + if (error != -1) { + SPL_X(s); + return error; + } + error = 0; + + SPL_X(s); + return error; +} + + +/* + * routines below for saving IP headers to buffer + */ +static int +ipfopen(pdev, flags, devtype, cp) + dev_t *pdev; + int flags, devtype; + cred_t *cp; +{ + u_int unit = geteminor(*pdev); + int error; + + if (IPL_LOGMAX < unit) { + error = ENXIO; + } else { + switch (unit) + { + case IPL_LOGIPF : + case IPL_LOGNAT : + case IPL_LOGSTATE : + case IPL_LOGAUTH : + case IPL_LOGLOOKUP : + case IPL_LOGSYNC : +#ifdef IPFILTER_SCAN + case IPL_LOGSCAN : +#endif + error = 0; + break; + default : + error = ENXIO; + break; + } + } + return error; +} + + +static int +ipfclose(dev, flags, devtype, cp) + dev_t dev; + int flags, devtype; + cred_t *cp; +{ + u_int unit = GET_MINOR(dev); + + if (IPL_LOGMAX < unit) + unit = ENXIO; + else + unit = 0; + return unit; +} + +/* + * ipfread/ipflog + * both of these must operate with at least splnet() lest they be + * called during packet processing and cause an inconsistancy to appear in + * the filter lists. + */ +static int +ipfread(dev, uio, crp) + dev_t dev; + register struct uio *uio; + cred_t *crp; +{ + if (ipf_running < 1) { + ipfmain.ipf_interror = 130006; + return EIO; + } + +#ifdef IPFILTER_LOG + return ipflog_read(GET_MINOR(dev), uio); +#else + ipfmain.ipf_interror = 130007; + return ENXIO; +#endif +} + + +/* + * ipf_send_reset - this could conceivably be a call to tcp_respond(), but that + * requires a large amount of setting up and isn't any more efficient. + */ +int +ipf_send_reset(fin) + fr_info_t *fin; +{ + struct tcphdr *tcp, *tcp2; + int tlen = 0, hlen; + struct mbuf *m; +#ifdef USE_INET6 + ip6_t *ip6; +#endif + ip_t *ip; + + tcp = fin->fin_dp; + if (tcp->th_flags & TH_RST) + return -1; /* feedback loop */ + + if (ipf_checkl4sum(fin) == -1) + return -1; + + m = m_get(M_DONTWAIT, MT_HEADER); + if (m == NULL) + return -1; + + tlen = fin->fin_dlen - (TCP_OFF(tcp) << 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 + hlen = sizeof(ip_t); +#endif + m->m_len = sizeof(*tcp2) + hlen; +# if (BSD >= 199103) + m->m_data += max_linkhdr; + m->m_pkthdr.len = m->m_len; + m->m_pkthdr.rcvif = (struct ifnet *)0; +# endif + ip = mtod(m, struct ip *); + bzero((char *)ip, hlen); +# ifdef USE_INET6 + ip6 = (ip6_t *)ip; +# endif + tcp2 = (struct tcphdr *)((char *)ip + hlen); + tcp2->th_sport = tcp->th_dport; + tcp2->th_dport = tcp->th_sport; + + if (tcp->th_flags & TH_ACK) { + tcp2->th_seq = tcp->th_ack; + tcp2->th_flags = TH_RST; + tcp2->th_ack = 0; + } else { + tcp2->th_seq = 0; + 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; + } + TCP_X2_A(tcp2, 0); + TCP_OFF_A(tcp2, sizeof(*tcp2) >> 2); + tcp2->th_win = tcp->th_win; + tcp->th_sum = 0; + tcp->th_urp = 0; + +# ifdef USE_INET6 + if (fin->fin_v == 6) { + ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; + ip6->ip6_plen = htons(sizeof(struct tcphdr)); + ip6->ip6_nxt = IPPROTO_TCP; + ip6->ip6_hlim = 0; + ip6->ip6_src = fin->fin_dst6; + ip6->ip6_dst = fin->fin_src6; + tcp2->th_sum = in6_cksum(m, IPPROTO_TCP, + sizeof(*ip6), sizeof(*tcp2)); + return ipf_send_ip(fin, m); + } +# endif + ip->ip_p = IPPROTO_TCP; + ip->ip_len = htons(sizeof(struct tcphdr)); + ip->ip_src.s_addr = fin->fin_daddr; + ip->ip_dst.s_addr = fin->fin_saddr; + tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2)); + ip->ip_len = hlen + sizeof(*tcp2); + return ipf_send_ip(fin, m); +} + + +static int +ipf_send_ip(fin, m) + fr_info_t *fin; + struct mbuf *m; +{ + fr_info_t fnew; + ip_t *oip; + ip_t *ip; + int hlen; + + ip = mtod(m, ip_t *); + bzero((char *)&fnew, sizeof(fnew)); + fnew.fin_main_soft = fin->fin_main_soft; + + IP_V_A(ip, fin->fin_v); + switch (fin->fin_v) + { + case 4 : + oip = fin->fin_ip; + hlen = sizeof(*oip); + fnew.fin_v = 4; + fnew.fin_p = ip->ip_p; + fnew.fin_plen = ip->ip_len; + IP_HL_A(ip, sizeof(*oip) >> 2); + ip->ip_tos = oip->ip_tos; + ip->ip_id = fin->fin_ip->ip_id; + if (ip->ip_p == IPPROTO_TCP && tcp_mtudisc != 0) + ip->ip_off = htons(IP_DF); + ip->ip_ttl = tcp_ttl; + ip->ip_sum = 0; + ip->ip_len = htons(ip->ip_len); + break; +#ifdef USE_INET6 + case 6 : + { + ip6_t *ip6 = (ip6_t *)ip; + + ip6->ip6_hlim = 127; + m = *mpp; + + return ip6_output(m, NULL, NULL, 0, NULL, NULL); + } +#endif + default : + return EINVAL; + } +#ifdef IPSEC + m->m_pkthdr.rcvif = NULL; +#endif + + fnew.fin_ifp = fin->fin_ifp; + fnew.fin_flx = FI_NOCKSUM; + fnew.fin_m = m; + fnew.fin_ip = ip; + fnew.fin_mp = &m; + fnew.fin_hlen = hlen; + fnew.fin_dp = (char *)ip + hlen; + (void) ipf_makefrip(hlen, ip, &fnew); + + return ipf_fastroute(m, &m, &fnew, NULL); +} + + +int +ipf_send_icmp_err(type, fin, dst) + int type; + fr_info_t *fin; + int dst; +{ + int err, hlen = 0, xtra = 0, iclen, ohlen = 0, avail; + struct in_addr dst4; + struct icmp *icmp; + struct mbuf *m; + i6addr_t dst6; + void *ifp; +#ifdef USE_INET6 + ip6_t *ip6, *ip62; + int code; +#endif + ip_t *ip, *ip2; + + if ((type < 0) || (type > ICMP_MAXTYPE)) + return -1; + +#ifdef USE_INET6 + code = fin->fin_icode; + if ((code < 0) || (code > sizeof(icmptoicmp6unreach)/sizeof(int))) + return -1; +#endif + + if (ipf_checkl4sum(fin) == -1) + return -1; + + avail = 0; + ifp = fin->fin_ifp; + if (fin->fin_v == 4) { + if ((fin->fin_p == IPPROTO_ICMP) && !(fin->fin_flx & FI_SHORT)) + switch (ntohs(fin->fin_data[0]) >> 8) + { + case ICMP_ECHO : + case ICMP_TSTAMP : + case ICMP_IREQ : + case ICMP_MASKREQ : + break; + default : + return 0; + } + + avail = MLEN; + m = m_get(M_DONTWAIT, MT_HEADER); + if (m == NULL) + return -1; + + if (dst == 0) { + if (ipf_ifpaddr(softc, 4, FRI_NORMAL, ifp, + &dst6, NULL) == -1) { + FREE_MB_T(m); + return -1; + } + dst4 = dst6.in4; + } else + dst4.s_addr = fin->fin_daddr; + + hlen = sizeof(ip_t); + if (fin->fin_hlen < fin->fin_plen) + xtra = MIN(fin->fin_dlen, 8); + else + xtra = 0; + } + +#ifdef USE_INET6 + else if (fin->fin_v == 6) { + hlen = sizeof(ip6_t); + ohlen = sizeof(ip6_t); + type = icmptoicmp6types[type]; + if (type == ICMP6_DST_UNREACH) + code = icmptoicmp6unreach[code]; + + MGETHDR(m, M_DONTWAIT, MT_HEADER); + if (m == NULL) + return -1; + + MCLGET(m, M_DONTWAIT); + if (m == NULL) + return -1; + avail = (m->m_flags & M_EXT) ? MCLBYTES : MHLEN; + xtra = MIN(fin->fin_plen, + avail - hlen - sizeof(*icmp) - max_linkhdr); + if (dst == 0) { + if (ipf_ifpaddr(softc, 6, FRI_NORMAL, ifp, + &dst6, NULL) == -1) { + FREE_MB_T(m); + return -1; + } + } else + dst6 = fin->fin_dst6; + } +#endif + else { + FREE_MB_T(m); + return -1; + } + + iclen = hlen + sizeof(*icmp); +# if (BSD >= 199103) + avail -= (max_linkhdr + iclen); + if (avail < 0) { + FREE_MB_T(m); + return -1; + } + m->m_data += max_linkhdr; + m->m_pkthdr.rcvif = (struct ifnet *)0; + iclen += xtra; + m->m_pkthdr.len = iclen; +#else + avail -= (m->m_off + iclen); + if (avail < 0) { + FREE_MB_T(m); + return -1; + } + iclen += xtra; +#endif + m->m_len = iclen; + ip = mtod(m, ip_t *); + icmp = (struct icmp *)((char *)ip + hlen); + ip2 = (ip_t *)&icmp->icmp_ip; + + 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) { + if (fin->fin_mtu != 0) { + icmp->icmp_nextmtu = htons(fin->fin_mtu); + + } else if (ifp != NULL) { + icmp->icmp_nextmtu = htons(GETIFMTU_4(ifp)); + + } else { /* make up a number... */ + icmp->icmp_nextmtu = htons(fin->fin_plen - 20); + } + } +#endif + + bcopy((char *)fin->fin_ip, (char *)ip2, ohlen); + +#ifdef USE_INET6 + ip6 = (ip6_t *)ip; + if (fin->fin_v == 6) { + ip62 = (ip6_t *)ip2; + + ip62->ip6_plen = htons(ip62->ip6_plen); + ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; + ip6->ip6_plen = htons(iclen - hlen); + ip6->ip6_nxt = IPPROTO_ICMPV6; + ip6->ip6_hlim = 0; + ip6->ip6_src = dst6; + ip6->ip6_dst = fin->fin_src6; + if (xtra > 0) + bcopy((char *)fin->fin_ip + fin->fin_hlen, + (char *)&icmp->icmp_ip + fin->fin_hlen, xtra); + icmp->icmp_cksum = in6_cksum(m, IPPROTO_ICMPV6, + sizeof(*ip6), iclen - hlen); + } else +#endif + { + ip->ip_p = IPPROTO_ICMP; + ip->ip_src.s_addr = dst4.s_addr; + ip->ip_dst.s_addr = fin->fin_saddr; + + if (xtra > 0) + bcopy((char *)fin->fin_ip + fin->fin_hlen, + (char *)&icmp->icmp_ip + fin->fin_hlen, xtra); + icmp->icmp_cksum = ipf_cksum((u_short *)icmp, + sizeof(*icmp) + 8); + ip->ip_len = iclen; + ip->ip_p = IPPROTO_ICMP; + } + err = ipf_send_ip(fin, m); + return err; +} + + +void +ipfinit(void) +{ + int i; + + for (i = 0; i < 256; i++) + if (cdevsw[i].d_open == ipfopen) { + printf("ipfinit:ipfilter @%d\n", i); break; + } + if (i == 256) + printf("ipfinit:ipfilter not found\n"); + + if (ipf_attach() != 0) + printf("IP Filter failed to attach\n"); + else + ip_init(); +} + + +int +ipfattach(void) +{ + int i; + + for (i = 0; i < 256; i++) + if (cdevsw[i].d_open == ipfopen) { + printf("ipfattach:ipfilter @%d\n", i); break; + } + if (i == 256) + printf("ipfattach:ipfilter not found\n"); + return 0; +} + +void +ipfstart(void) +{ + int i; + + for (i = 0; i < 256; i++) + if (cdevsw[i].d_open == ipfopen) { + printf("ipfstart:ipfilter @%d\n", i); + break; + } + if (i==256) + printf("ipfstart:ipfilter not found\n"); +} + + +size_t +mbufchainlen(m0) + register struct mbuf *m0; +{ + register size_t len = 0; + + for (; m0; m0 = m0->m_next) + len += m0->m_len; + return len; +} + + +/* + * m0 - pointer to mbuf where the IP packet starts + * mpp - pointer to the mbuf pointer that is the start of the mbuf chain + */ +int +ipf_fastroute(m0, mpp, fin, fdp) + struct mbuf *m0, **mpp; + fr_info_t *fin; + frdest_t *fdp; +{ + register struct ip *ip, *mhip; + register struct mbuf *m = *mpp; + register struct route *ro; + int len, off, error = 0, hlen, code; + struct ifnet *ifp, *sifp; + struct sockaddr_in *dst; + struct route iproute; + frdest_t node; + frentry_t *fr; + + hlen = fin->fin_hlen; + ip = mtod(m0, struct ip *); + +#ifdef USE_INET6 + if (fin->fin_v == 6) { + /* + * currently "to <if>" and "to <if>:ip#" are not supported + * for IPv6 + */ + return ip6_output(m0, NULL, NULL, 0, NULL, NULL); + } +#endif + /* + * Route packet. + */ + ROUTE_RDLOCK(); + + ro = &iproute; + bzero((caddr_t)ro, sizeof (*ro)); + dst = (struct sockaddr_in *)&ro->ro_dst; + dst->sin_family = AF_INET; + dst->sin_addr = ip->ip_dst; + + fr = fin->fin_fr; + if ((fr != NULL) && !(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) && + (fdp->fd_type == FRD_DSTLIST)) { + if (ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node) == 0) + fdp = &node; + } + + if (fdp != NULL) + ifp = fdp->fd_ptr; + else + ifp = fin->fin_ifp; + + if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0)) + dst->sin_addr = fdp->fd_ip.s_addr; + + rtalloc(ro); + + ROUTE_UNLOCK(); + + if (!ifp) { + if (!fr || !(fr->fr_flags & FR_FASTROUTE)) { + error = -2; + goto bad; + } + if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) { + if (in_localaddr(ip->ip_dst)) + error = EHOSTUNREACH; + else + error = ENETUNREACH; + goto bad; + } + if (ro->ro_rt->rt_flags & RTF_GATEWAY) + dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway; + } + if (ro->ro_rt) + ro->ro_rt->rt_use++; + + /* + * For input packets which are being "fastrouted", they won't + * go back through output filtering and miss their chance to get + * NAT'd and counted. Duplicated packets aren't considered to be + * part of the normal packet stream, so do not NAT them or pass + * them through stateful checking, etc. + */ + if ((fdp != &fr->fr_dif) && (fin->fin_out == 0)) { + sifp = fin->fin_ifp; + fin->fin_ifp = ifp; + fin->fin_out = 1; + (void) ipf_acctpkt(fin, NULL); + fin->fin_fr = NULL; + if (!fr || !(fr->fr_flags & FR_RETMASK)) { + u_32_t pass; + + (void) ipf_state_check(fin, &pass); + } + + switch (ipf_nat_checkout(fin, NULL)) + { + case 0 : + break; + case 1 : + ip->ip_sum = 0; + break; + case -1 : + error = -1; + goto bad; + break; + } + + fin->fin_ifp = sifp; + fin->fin_out = 0; + } else + ip->ip_sum = 0; + /* + * If small enough for interface, can just send directly. + */ + if (ntohs(ip->ip_len) <= ifp->if_mtu) { + if (!ip->ip_sum) + ip->ip_sum = in_cksum(m, hlen); +#if IRIX >= 60500 + error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, + NULL); +#else + error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst); +#endif + goto done; + } + /* + * Too large for interface; fragment if possible. + * Must be able to put at least 8 bytes per fragment. + */ + if (ip->ip_off & htons(IP_DF)) { + error = EMSGSIZE; + goto bad; + } + len = (ifp->if_mtu - hlen) &~ 7; + if (len < 8) { + error = EMSGSIZE; + goto bad; + } + + { + int mhlen, firstlen = len; + struct mbuf **mnext = &m->m_act; + + /* + * Loop through length of segment after first fragment, + * make new header and copy data of each part and link onto chain. + */ + m0 = m; + mhlen = sizeof (struct ip); + for (off = hlen + len; off < ntohs(ip->ip_len); off += len) { + u_short ipoff, iplen; + +#ifdef MGETHDR + MGETHDR(m, M_DONTWAIT, MT_HEADER); +#else + MGET(m, M_DONTWAIT, MT_HEADER); +#endif + if (m == 0) { + error = ENOBUFS; + goto bad; + } +#if (BSD >= 199103) + m->m_data += max_linkhdr; +#else + m->m_off = MMAXOFF - hlen; +#endif + mhip = mtod(m, struct ip *); + bcopy((char *)ip, (char *)mhip, sizeof(*ip)); + if (hlen > sizeof (struct ip)) { + mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); + IP_HL_A(mhip, mhlen >> 2); + } + + m->m_len = mhlen; + ipoff = ntohs(ip->ip_off); + iplen = ntohs(ip->ip_len); + + mhip->ip_off = ((off - hlen) >> 3) + (ipoff & ~IP_MF); + if (ipoff & IP_MF) + mhip->ip_off |= IP_MF; + if (off + len >= iplen) + len = iplen - off; + else + mhip->ip_off |= IP_MF; + + mhip->ip_len = htons((u_short)(len + mhlen)); + m->m_next = m_copy(m0, off, len); + if (m->m_next == 0) { + error = ENOBUFS; /* ??? */ + goto sendorfree; + } +#if (BSD >= 199103) + m->m_pkthdr.len = mhlen + len; + m->m_pkthdr.rcvif = NULL; +#endif + mhip->ip_off = htons((u_short)mhip->ip_off); + mhip->ip_sum = 0; + mhip->ip_sum = in_cksum(m, mhlen); + *mnext = m; + mnext = &m->m_act; + } + /* + * Update first fragment by trimming what's been copied out + * and updating header, then send each fragment (in order). + */ + m_adj(m0, hlen + firstlen - ntohs(ip->ip_len)); + ip->ip_len = htons((u_short)(hlen + firstlen)); + ip->ip_off = htons(IP_MF); + ip->ip_sum = 0; + ip->ip_sum = in_cksum(m0, hlen); +sendorfree: + for (m = m0; m; m = m0) { + m0 = m->m_act; + m->m_act = 0; + if (error == 0) +#if IRIX >= 60500 + error = (*ifp->if_output)(ifp, m, + (struct sockaddr *)dst, ro->ro_rt); +#else + error = (*ifp->if_output)(ifp, m, + (struct sockaddr *)dst); +#endif + else + m_freem(m); + } + } +done: + if (!error) + ipf_frouteok[0]++; + else + ipf_frouteok[1]++; + + if (ro->ro_rt) + RTFREE(ro->ro_rt); + return 0; +bad: + if (error == EMSGSIZE) { + sifp = fin->fin_ifp; + code = fin->fin_icode; + fin->fin_icode = ICMP_UNREACH_NEEDFRAG; + fin->fin_ifp = ifp; + (void) ipf_send_icmp_err(ICMP_UNREACH, fin, 1); + fin->fin_ifp = sifp; + fin->fin_icode = code; + } + m_freem(m); + goto done; +} + + +int +ipf_verifysrc(fin) + fr_info_t *fin; +{ + struct sockaddr_in *dst; + struct route iproute; + + bzero((char *)&iproute, sizeof(iproute)); + dst = (struct sockaddr_in *)&iproute.ro_dst; + dst->sin_family = AF_INET; + dst->sin_addr.s_addr = fin->fin_saddr; + rtalloc(&iproute); + if (iproute.ro_rt == NULL) + return 0; + return (fin->fin_ifp == iproute.ro_rt->rt_ifp); +} + + +/* + * return the first IP Address associated with an interface + */ +int +ipf_ifpaddr(softc, v, atype, ifptr, inp, inpmask) + ipf_main_softc_t *softc; + int v, atype; + void *ifptr; + i6addr_t *inp, *inpmask; +{ +#ifdef USE_INET6 + struct in6_addr *inp6 = NULL; +#endif + struct sockaddr_in *sin, *mask; + struct ifaddr *ifa; + struct in_addr in; + struct ifnet *ifp; + + if ((ifptr == NULL) || (ifptr == (void *)-1)) + return -1; + + mask = NULL; + ifp = ifptr; + + if (v == 4) + inp->s_addr = 0; +#ifdef USE_INET6 + else if (v == 6) + bzero((char *)inp, sizeof(*inp)); +#endif + +#if defined(IFF_DRVRLOCK) /* IRIX 6 */ + ifa = &((struct in_ifaddr *)ifp->in_ifaddr)->ia_ifa; +#else + ifa = ifp->if_addrlist; +#endif + + sin = (struct sockaddr_in *)ifa->ifa_addr; + while (sin && ifa) { + if ((v == 4) && (sin->sin_family == AF_INET)) + break; +# ifdef USE_INET6 + if ((v == 6) && (sin->sin_family == AF_INET6)) { + inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr; + if (!IN6_IS_ADDR_LINKLOCAL(inp6) && + !IN6_IS_ADDR_LOOPBACK(inp6)) + break; + } +# endif + ifa = ifa->ifa_next; + if (ifa != NULL) + sin = (struct sockaddr_in *)ifa->ifa_addr; + } + if (ifa == NULL || sin == NULL) + return -1; + + mask = (struct sockaddr_in *)ifa->ifa_netmask; + if (atype == FRI_BROADCAST) + sin = (struct sockaddr_in *)ifa->ifa_broadaddr; + else if (atype == FRI_PEERADDR) + sin = (struct sockaddr_in *)ifa->ifa_dstaddr; + +#ifdef USE_INET6 + if (v == 6) + return ipf_ifpfillv6addr(atype, (struct sockaddr_in6 *)sin, + (struct sockaddr_in6 *)mask, + inp, inpmask); +#endif + return ipf_ifpfillv4addr(atype, sin, mask, &inp->in4, &inpmask->in4); +} + + +void +#if IRIX >= 60500 +ipf_slowtimer(void *arg) +#else +ipf_slowtimer() +#endif +{ + if (ipf_running <= 0) { +#if IRIX >= 60500 + ipf_timer_id = 0; +#endif + return; + } + + READ_ENTER(&ipf_global); + if (ipf_running <= 0) { +#if IRIX >= 60500 + ipf_timer_id = 0; +#endif + RWLOCK_EXIT(&ipf_global); + return; + } + + ipf_ipfilter_intfsync(); + ipf_expiretokens(&ipfmain); + ipf_frag_expire(&ipfmain); + ipf_state_expire(&ipfmain); + ipf_nat_expire(&ipfmain); + ipf_auth_expire(&ipfmain); + ipf_lookup_expire(&ipfmain); + ipf_rule_expire(&ipfmain); + ipf_ticks++; + +#if IRIX >= 60500 + ipf_timer_id = timeout(ipf_slowtimer, NULL, hz/2); +#else + timeout(ipf_slowtimer, NULL, hz/2); +#endif + RWLOCK_EXIT(&ipf_global); +} + + +u_32_t +ipf_newisn(fin) + fr_info_t *fin; +{ + static iss_seq_off = 0; + u_char hash[16]; + u_32_t newiss; + MD5_CTX ctx; + + /* + * Compute the base value of the ISS. It is a hash + * of (saddr, sport, daddr, dport, secret). + */ + MD5Init(&ctx); + + MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, + sizeof(fin->fin_fi.fi_src)); + MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, + sizeof(fin->fin_fi.fi_dst)); + MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); + + MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); + + MD5Final(hash, &ctx); + + bcopy(hash, &newiss, sizeof(newiss)); + + /* + * Now increment our "timer", and add it in to + * the computed value. + * + * XXX Use `addin'? + * XXX TCP_ISSINCR too large to use? + */ + iss_seq_off += 0x00010000; + newiss += iss_seq_off; + return newiss; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nextipid */ +/* Returns: int - 0 == success, -1 == error (packet should be droppped) */ +/* Parameters: fin(I) - pointer to packet information */ +/* */ +/* Returns the next IPv4 ID to use for this packet. */ +/* ------------------------------------------------------------------------ */ +u_short +ipf_nextipid(fin) + fr_info_t *fin; +{ + u_short id; + + MUTEX_ENTER(&ipf_rw); + id = ipid++; + MUTEX_EXIT(&ipf_rw); + + return id; +} + + +int +ipf_checkv4sum(fin) + fr_info_t *fin; +{ + if ((fin->fin_flx & FI_NOCKSUM) != 0) + return 0; + + if ((fin->fin_flx & FI_SHORT) != 0) + return 1; + + if (fin->fin_cksum != FI_CK_NEEDED) + return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; + + if (ipf_checkl4sum(fin) == -1) { + fin->fin_flx |= FI_BAD; + return -1; + } + return 0; +} + + +#ifdef USE_INET6 +INLINE int +ipf_checkv6sum(fin) + fr_info_t *fin; +{ + if ((fin->fin_flx & FI_NOCKSUM) != 0) + return 0; + + if ((fin->fin_flx & FI_SHORT) != 0) + return 1; + + if (fin->fin_cksum != FI_CK_NEEDED) + return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; + + + if (ipf_checkl4sum(fin) == -1) { + fin->fin_flx |= FI_BAD; + return -1; + } + return 0; +} +#endif /* USE_INET6 */ + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pullup */ +/* Returns: NULL == pullup failed, else pointer to protocol header */ +/* Parameters: xmin(I)- pointer to buffer where data packet starts */ +/* fin(I) - pointer to packet information */ +/* len(I) - number of bytes to pullup */ +/* */ +/* Attempt to move at least len bytes (from the start of the buffer) into a */ +/* single buffer for ease of access. Operating system native functions are */ +/* used to manage buffers - if necessary. If the entire packet ends up in */ +/* a single buffer, set the FI_COALESCE flag even though ipf_coalesce() has */ +/* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */ +/* and ONLY if the pullup succeeds. */ +/* */ +/* We assume that 'min' is a pointer to a buffer that is part of the chain */ +/* of buffers that starts at *fin->fin_mp. */ +/* ------------------------------------------------------------------------ */ +void * +ipf_pullup(xmin, fin, len) + mb_t *xmin; + fr_info_t *fin; + int len; +{ + int out = fin->fin_out, dpoff; + mb_t *m = xmin, *n; + char *ip; + + if (m == NULL) + return NULL; + + ip = (char *)fin->fin_ip; + if ((fin->fin_flx & FI_COALESCE) != 0) + return ip; + + if (fin->fin_dp != NULL) + dpoff = (char *)fin->fin_dp - (char *)ip; + else + dpoff = 0; + + if (M_LEN(m) < len) { + KMALLOCS(fin->fin_hbuf, void *, fin->fin_plen); + if (fin->fin_hbuf == NULL) { + return NULL; + } + m_copydata(m, 0, fin->fin_plen, fin->fin_hbuf); + ip = fin->fin_hbuf; + fin->fin_flx |= FI_COALESCE; + } else if (len == fin->fin_plen) { + fin->fin_flx |= FI_COALESCE; + } + + fin->fin_ip = (ip_t *)ip; + if (fin->fin_dp != NULL) + fin->fin_dp = (char *)fin->fin_ip + dpoff; + if (fin->fin_fraghdr != NULL) + fin->fin_fraghdr = (char *)ip + + ((char *)fin->fin_fraghdr - + (char *)fin->fin_ip); + return ip; +} + + +int +ipf_inject(fin, m) + fr_info_t *fin; + mb_t *m; +{ + int error; + + if (fin->fin_out == 0) { + struct ifqueue *ifq; + +#if (IRIX >= 60516) + ifq = &((struct ifnet *)fin->fin_ifp)->if_snd; +#else + ifq = &ipintrq; +#endif + + if (IF_QFULL(ifq)) { + IF_DROP(ifq); + FREE_MB_T(m); + error = ENOBUFS; + } else { + IF_ENQUEUE(ifq, m); +#if IRIX < 60500 + schednetisr(NETISR_IP); +#endif + error = 0; + } + } else { +#if IRIX >= 60500 + error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL); +#else + error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL); +#endif + } + + return error; +} + + +/* + * In the face of no kernel random function, this is implemented...it is + * not meant to be random, just a fill in. + */ +int +ipf_random() +{ + static int last = 0; + static int calls = 0; + struct timeval tv; + int number; + + GETKTIME(&tv); + last *= tv.tv_usec + calls++; + last += (int)&range * ipf_ticks; + number = last + tv.tv_sec; + return number; +} + +u_int +ipf_pcksum(fin, hlen, sum) + fr_info_t *fin; + int hlen; + u_int sum; +{ + union { + u_char c[2]; + u_short s; + } bytes; + int add; + + /* + * In case we had to copy the IP & TCP header out of mbufs, + * skip over the mbuf bits which are the header + */ + if ((char *)ip != mtod(m, char *)) { + hlen = (char *)sp - (char *)ip; + while (hlen) { + add = MIN(hlen, m->m_len); + sp = (u_short *)(mtod(m, char *) + add); + hlen -= add; + if (add == m->m_len) { + m = m->m_next; + if (!hlen) { + if (!m) + break; + sp = mtod(m, u_short *); + } + PANIC((!m),("fr_cksum(1): not enough data")); + } + } + } + + l4hlen =; + len -= (l4hlen + hlen); + if (len <= 0) + goto nodata; + + while (len > 1) { + if (((char *)sp - mtod(m, char *)) >= m->m_len) { + m = m->m_next; + PANIC((!m),("fr_cksum(2): not enough data")); + sp = mtod(m, u_short *); + } + if (((char *)(sp + 1) - mtod(m, char *)) > m->m_len) { + bytes.c[0] = *(u_char *)sp; + m = m->m_next; + PANIC((!m),("fr_cksum(3): not enough data")); + sp = mtod(m, u_short *); + bytes.c[1] = *(u_char *)sp; + sum += bytes.s; + sp = (u_short *)((u_char *)sp + 1); + } + if ((u_long)sp & 1) { + bcopy((char *)sp++, (char *)&bytes.s, sizeof(bytes.s)); + sum += bytes.s; + } else + sum += *sp++; + len -= 2; + } + + if (len != 0) + sum += ntohs(*(u_char *)sp << 8); + nodata: + while (sum > 0xffff) + sum = (sum & 0xffff) + (sum >> 16); + sum2 = (u_short)(~sum & 0xffff); + return sum2; +} diff --git a/ip_fil_linux.c b/ip_fil_linux.c new file mode 100644 index 0000000000000..b9b91a9522cc8 --- /dev/null +++ b/ip_fil_linux.c @@ -0,0 +1,1169 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include <linux/version.h> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +# define __irq_h 1 /* stop it being included! */ +#else +# define _LINUX_TCP_H +#endif +#include <net/ip.h> + +#include "ipf-linux.h" + +#include <net/checksum.h> +#include <net/route.h> + +#include <linux/random.h> +#include <asm/ioctls.h> + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) +extern int sysctl_ip_default_ttl; +#endif + +extern ipf_main_softc_t ipfmain; + +static u_short ipid = 0; + +static void ipf_timer_func(unsigned long); +static int ipf_send_ip __P((fr_info_t *, struct sk_buff *)); + +ipfmutex_t ipl_mutex, ipf_auth_mx, ipf_rw, ipf_stinsert; +ipfmutex_t ipf_nat_new, ipf_natio, ipf_timeoutlock; +ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag, ipf_frcache, ipf_tokens; +ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_authlk; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) +extern int ip_finish_output(struct sk_buff *); +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) +static u_int ipf_linux_inout __P((u_int, struct sk_buff *, const struct net_device *, const struct net_device *, int (*okfn)(struct sk_buff *))); +#else +static u_int ipf_linux_inout __P((u_int, struct sk_buff **, const struct net_device *, const struct net_device *, int (*okfn)(struct sk_buff *))); +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +static struct nf_hook_ops ipf_hooks[] = { + { + .hook = ipf_linux_inout, + .owner = THIS_MODULE, + .pf = PF_INET, +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) + .hooknum = NF_INET_PRE_ROUTING, +# else + .hooknum = NF_IP_PRE_ROUTING, +# endif + .priority = 200, + }, + { + .hook = ipf_linux_inout, + .owner = THIS_MODULE, + .pf = PF_INET, +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) + .hooknum = NF_INET_POST_ROUTING, +# else + .hooknum = NF_IP_POST_ROUTING, +# endif + .priority = 200, + }, +# ifdef USE_INET6 + { + .hook = ipf_linux_inout, + .owner = THIS_MODULE, + .pf = PF_INET6, +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) + .hooknum = NF_INET_PRE_ROUTING, +# else + .hooknum = NF_IP_PRE_ROUTING, +# endif + .priority = 200, + }, + { + .hook = ipf_linux_inout, + .owner = THIS_MODULE, + .pf = PF_INET6, +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) + .hooknum = NF_INET_POST_ROUTING, +# else + .hooknum = NF_IP_POST_ROUTING, +# endif + .priority = 200, + } +# endif +}; +#else +static struct nf_hook_ops ipf_hooks[] = { + { + { NULL, NULL }, /* list */ + ipf_linux_inout, /* hook */ + PF_INET, /* pf */ + NF_IP_PRE_ROUTING, /* hooknum */ + 200 /* priority */ + }, + { + { NULL, NULL}, /* list */ + ipf_linux_inout, /* hook */ + PF_INET, /* pf */ + NF_IP_POST_ROUTING, /* hooknum */ + 200 /* priority */ + }, +# ifdef USE_INET6 + { + { NULL, NULL }, /* list */ + ipf_linux_inout, /* hook */ + PF_INET6, /* pf */ + NF_IP_PRE_ROUTING, /* hooknum */ + 200 /* priority */ + }, + { + { NULL, NULL}, /* list */ + ipf_linux_inout, /* hook */ + PF_INET6, /* pf */ + NF_IP_POST_ROUTING, /* hooknum */ + 200 /* priority */ + } +# endif +}; +#endif + + +/* + * Filter ioctl interface. + */ +int +ipf_ioctl(struct inode *in, struct file *fp, u_int cmd, u_long arg) +{ + int error = 0, unit = 0; + caddr_t data; + mode_t mode; + + unit = MINOR(in->i_rdev); + if (unit < 0 || unit > IPL_LOGMAX) + return -ENXIO; + + if (ipfmain.ipf_running <= 0) { + if (unit != IPL_LOGIPF && cmd != SIOCIPFINTERROR) + return -EIO; + if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET && + cmd != SIOCIPFSET && cmd != SIOCFRENB && + cmd != SIOCGETFS && cmd != SIOCGETFF && + cmd != SIOCIPFINTERROR) + return -EIO; + } + + mode = fp->f_mode; + data = (caddr_t)arg; + + error = ipf_ioctlswitch(&ipfmain, unit, data, cmd, mode, fp->f_uid, fp); + if (error != -1) { + SPL_X(s); + if (error > 0) + error = -error; + return error; + } + SPL_X(s); + + if (error > 0) + error = -error; + return error; +} + + +u_32_t +ipf_newisn(fr_info_t *fin) +{ + u_32_t isn; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) + i6addr_t dst, src; + + bcopy(&fin->fin_dst, &dst, sizeof(dst)); + bcopy(&fin->fin_src, &src, sizeof(src)); + + isn = secure_tcpv6_sequence_number(&dst.in4.s_addr, &src.in4.s_addr, + fin->fin_dport, fin->fin_sport); +#else + isn = secure_tcp_sequence_number(fin->fin_daddr, fin->fin_saddr, + fin->fin_dport, fin->fin_sport); +#endif + return isn; +} + + +int +ipf_send_reset(fr_info_t *fin) +{ + tcphdr_t *tcp, *tcp2; + int tlen, hlen; +#ifdef USE_INET6 + ip6_t *ip6; +#endif + ip_t *ip; + mb_t *m; + + tcp = fin->fin_dp; + if (tcp->th_flags & TH_RST) + return -1; + + if (ipf_checkl4sum(fin) == -1) + return -1; + + m = skb_copy(fin->fin_m, GFP_ATOMIC); + if (m == NULL) + return -1; + + tlen = (tcp->th_flags & (TH_SYN|TH_FIN)) ? 1 : 0; +#ifdef USE_INET6 + if (fin->fin_v == 6) + hlen = sizeof(ip6_t); + else +#endif + hlen = sizeof(ip_t); + hlen += sizeof(*tcp2); + skb_trim(m, hlen); + + bzero(MTOD(m, char *), hlen); + ip = MTOD(m, ip_t *); + bzero((char *)ip, hlen); + ip->ip_v = fin->fin_v; + tcp2 = (tcphdr_t *)((char *)ip + hlen - sizeof(*tcp2)); + tcp2->th_dport = tcp->th_sport; + tcp2->th_sport = tcp->th_dport; + 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; + +#ifdef USE_INET6 + if (fin->fin_v == 6) { + ip6 = (ip6_t *)ip; + ip6->ip6_src = fin->fin_dst6; + ip6->ip6_dst = fin->fin_src6; + ip6->ip6_plen = htons(sizeof(*tcp)); + ip6->ip6_nxt = IPPROTO_TCP; + } else +#endif + { + ip->ip_hl = sizeof(*ip) >> 2; + ip->ip_src.s_addr = fin->fin_daddr; + ip->ip_dst.s_addr = fin->fin_saddr; + ip->ip_p = IPPROTO_TCP; + ip->ip_len = htons(sizeof(*ip) + sizeof(*tcp)); + tcp2->th_sum = fr_cksum(fin, ip, IPPROTO_TCP, tcp2); + } + return ipf_send_ip(fin, m); +} + + +/* + * On input, ip_len is in network byte order + */ +static int +ipf_send_ip(fr_info_t *fin, struct sk_buff *sk) +{ + fr_info_t fnew; + ip_t *ip, *oip; + int hlen; + + ip = MTOD(sk, ip_t *); + bzero((char *)&fnew, sizeof(fnew)); + fnew.fin_main_soft = fin->fin_main_soft; + oip = fin->fin_ip; + + switch (fin->fin_v) + { + case 4 : + fnew.fin_v = 4; + fnew.fin_p = ip->ip_p; + fnew.fin_plen = ntohs(ip->ip_len); + ip->ip_hl = sizeof(*oip) >> 2; + ip->ip_tos = oip->ip_tos; + ip->ip_id = 0; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) + ip->ip_ttl = sysctl_ip_default_ttl; +#else + ip->ip_ttl = IPDEFTTL; +#endif + ip->ip_sum = 0; + ip->ip_off = 0x4000; /* IP_DF */ + hlen = sizeof(*ip); + break; + default : + return EINVAL; + } + + fnew.fin_ifp = fin->fin_ifp; + fnew.fin_flx = FI_NOCKSUM; + fnew.fin_m = sk; + fnew.fin_ip = ip; + fnew.fin_mp = &sk; + fnew.fin_hlen = hlen; + fnew.fin_dp = (char *)ip + hlen; + (void) ipf_makefrip(hlen, ip, &fnew); + + return ipf_fastroute(sk, &sk, &fnew, NULL); +} + + +int +ipf_send_icmp_err(int type, fr_info_t *fin, int isdst) +{ + int hlen, code, leader, dlen; + struct net_device *ifp; + struct in_addr dst4; + struct icmp *icmp; + i6addr_t dst6; + u_short sz; +#ifdef USE_INET6 + ip6_t *ip6; + mb_t *mb; +#endif + ip_t *ip; + mb_t *m, *m0; + + if ((type < 0) || (type > ICMP_MAXTYPE)) + return -1; + + code = fin->fin_icode; + +#ifdef USE_INET6 + if ((code < 0) || (code > sizeof(icmptoicmp6unreach)/sizeof(int))) + return -1; +#endif + + if (ipf_checkl4sum(fin) == -1) + return -1; + + m0 = fin->fin_m; +#ifdef USE_INET6 + if (fin->fin_v == 6) { + sz = sizeof(ip6_t); + dlen = MIN(M_LEN(m0), 512); + sz += dlen; + hlen = sizeof(ip6_t); + type = icmptoicmp6types[type]; + if (type == ICMP6_DST_UNREACH) + code = icmptoicmp6unreach[code]; + } else +#endif + { + if ((fin->fin_p == IPPROTO_ICMP) && !(fin->fin_flx & FI_SHORT)) + switch (ntohs(fin->fin_data[0]) >> 8) + { + case ICMP_ECHO : + case ICMP_TSTAMP : + case ICMP_IREQ : + case ICMP_MASKREQ : + break; + default : + return 0; + } + + sz = sizeof(ip_t) * 2 + 4; + dlen = 8; /* 64 bits of data */ + sz += dlen; + hlen = sizeof(ip_t); + } + + leader = m0->data - m0->head; + if ((leader & 15) != 0) + leader += 16 - (leader & 15); + m = alloc_skb(sz + leader, GFP_ATOMIC); + if (m == NULL) + return -1; + + /* Set the data pointer */ + skb_reserve(m, leader); + + bzero(MTOD(m, char *), (size_t)sz); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) + skb_put(m, hlen); + skb_set_network_header(m,hlen); + ip = (ip_t *)ip_hdr(m); +#else + m->nh.iph = (struct iphdr *)skb_put(m, hlen); + ip = (ip_t *)m->nh.iph; +#endif + ip->ip_v = fin->fin_v; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) + skb_put(m, hlen + 4 + dlen); + skb_set_transport_header(m, hlen + 4 + dlen); + icmp = (icmphdr_t *)icmp_hdr(m); +#else + m->h.icmph = (struct icmphdr *)skb_put(m, hlen + 4 + dlen); + icmp = (icmphdr_t *)m->h.icmph; +#endif + icmp->icmp_type = type & 0xff; + icmp->icmp_code = code & 0xff; +#ifdef icmp_nextmtu + ifp = fin->fin_ifp; + if (type == ICMP_UNREACH && fin->fin_icode == ICMP_UNREACH_NEEDFRAG) { + if (fin->fin_mtu != 0) { + icmp->icmp_nextmtu = htons(fin->fin_mtu); + + } else if (ifp->mtu != 0) { + icmp->icmp_nextmtu = htons(ifp->mtu); + + } else { + icmp->icmp_nextmtu = htons(fin->fin_plen - 20); + } + } +#endif + +#ifdef USE_INET6 + if (fin->fin_v == 6) { + int csz; + + if (isdst == 0) { + if (ipf_ifpaddr(&ipfmain, 6, FRI_NORMAL, fin->fin_ifp, + &dst6, NULL) == -1) { + FREE_MB_T(m); + return -1; + } + } else + dst6 = fin->fin_dst6; + + csz = sz; + sz -= sizeof(ip6_t); + ip6 = (ip6_t *)ip; + ip6->ip6_plen = htons((u_short)sz); + ip6->ip6_nxt = IPPROTO_ICMPV6; + ip6->ip6_src = dst6; + ip6->ip6_dst = fin->fin_src6; + sz -= offsetof(struct icmp, icmp_ip); + bcopy((char *)fin->fin_ip, (char *)&icmp->icmp_ip, sz); + icmp->icmp_cksum = csz - sizeof(ip6_t); + } else +#endif + { + ip = MTOD(m, ip_t *); + ip->ip_hl = sizeof(*ip) >> 2; + ip->ip_p = IPPROTO_ICMP; + ip->ip_len = (u_short)sz; + if (isdst == 0) { + if (ipf_ifpaddr(&ipfmain, 4, FRI_NORMAL, fin->fin_ifp, + &dst6, NULL) == -1) { + FREE_MB_T(m); + return -1; + } + dst4 = dst6.in4; + } else + dst4 = fin->fin_dst; + ip->ip_src = dst4; + ip->ip_dst = fin->fin_src; + bcopy((char *)fin->fin_ip, (char *)&icmp->icmp_ip, + sizeof(*fin->fin_ip)); + bcopy((char *)fin->fin_ip + fin->fin_hlen, + (char *)&icmp->icmp_ip + sizeof(*fin->fin_ip), 8); + icmp->icmp_cksum = ip_compute_csum((u_char *)icmp, + sz - sizeof(ip_t)); + ip->ip_len = htons(sz); + } + + /* + * Need to exit out of these so we don't recursively call rw_enter + * from fr_qout. + */ + return ipf_send_ip(fin, m); +} + + +int +ipf_verifysrc(fr_info_t *fin) +{ + return 0; +} + + +int +ipf_checkv4sum(fr_info_t *fin) +{ + if ((fin->fin_flx & FI_NOCKSUM) != 0) + return 0; + + if ((fin->fin_flx & FI_SHORT) != 0) + return 1; + + if (fin->fin_cksum != FI_CK_NEEDED) + return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; + + /* + * Linux 2.4.20-8smp (RedHat 9) + * Because ip_input() on linux clears the checksum flag in the sk_buff + * before calling the netfilter hook, it is not possible to take + * advantage of the work already done by the hardware. + */ + if (ipf_checkl4sum(fin) == -1) { + fin->fin_flx |= FI_BAD; + return -1; + } + return 0; +} + + +u_short +ipf_nextipid(fr_info_t *fin) +{ +#if 1 + return ipid++; +#else + ip_t ip; + + __ip_select_ident(&ip, NULL); + return ip.ip_id; +#endif +} + + +/* + * xmin - pointer to mbuf where the IP packet starts + * mpp - pointer to the mbuf pointer that is the start of the mbuf chain + */ +/*ARGSUSED*/ +int +ipf_fastroute(mb_t *xmin, mb_t **mpp, fr_info_t *fin, frdest_t *fdp) +{ + struct net_device *ifp, *sifp; + struct in_addr dip; + struct rtable *rt; + frdest_t node; + frentry_t *fr; + int err, sout; + ip_t *ip; + + rt = NULL; + fr = fin->fin_fr; + ip = MTOD(xmin, ip_t *); + dip = ip->ip_dst; + + if ((fr != NULL) && !(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) && + (fdp->fd_type == FRD_DSTLIST)) { + if (ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node) == 0) + fdp = &node; + } + if (fdp != NULL) + ifp = fdp->fd_ifp; + else + ifp = fin->fin_ifp; + + if ((ifp == NULL) && ((fr == NULL) || !(fr->fr_flags & FR_FASTROUTE))) { + err = ENETUNREACH; + goto bad; + } + + if ((fdp != NULL) && (fdp->fd_ip.s_addr)) + dip = fdp->fd_ip; + + switch (fin->fin_v) + { + case 4 : +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + err = ip_route_output(&rt, dip.s_addr, 0, + RT_TOS(ip->ip_tos) | RTO_CONN, 0); +#else + err = 1; +#endif + if (err != 0 || rt == NULL) + goto bad; + + if (rt->u.dst.dev == NULL) { + err = EHOSTUNREACH; + goto bad; + } + break; + default : + err = EINVAL; + goto bad; + } + + if (fin->fin_out == 0) { + sifp = fin->fin_ifp; + sout = fin->fin_out; + fin->fin_ifp = ifp; + fin->fin_out = 1; + (void) ipf_acctpkt(fin, NULL); + fin->fin_fr = NULL; + if (!fr || !(fr->fr_flags & FR_RETMASK)) { + u_32_t pass; + + (void) ipf_state_check(fin, &pass); + } + + switch (ipf_nat_checkout(fin, NULL)) + { + case 0 : + break; + case 1 : + ip->ip_sum = 0; + break; + case -1 : + err = EINVAL; + goto bad; + break; + } + + fin->fin_ifp = sifp; + fin->fin_out = sout; + } + ip->ip_sum = 0; + + + if (xmin->dst != NULL) { + dst_release(xmin->dst); + xmin->dst = NULL; + } + + xmin->dst = &rt->u.dst; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,21) + if (xmin->len > xmin->dst->pmtu) { + err = EMSGSIZE; + goto bad; + } +#endif + + switch (fin->fin_v) + { + case 4 : + ip->ip_sum = ip_fast_csum((u_char *)ip, ip->ip_hl); + + NF_HOOK(PF_INET, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) + NF_INET_LOCAL_OUT, +#else + NF_IP_LOCAL_OUT, +#endif + xmin, NULL, ifp, ip_finish_output); + err = 0; + break; + + default : + err = EINVAL; + break; + } + + if (err == 0) + return 0; +bad: + if (xmin != NULL) + kfree_skb(xmin); + return err; +} + + +int +ipf_ifpaddr(ipf_main_softc_t *softc, int v, int atype, void *ifptr, + i6addr_t *inp, i6addr_t *inpmask) +{ + struct sockaddr_in sin, sinmask; + struct net_device *dev; + struct in_ifaddr *ifa; + struct in_device *ifp; + + if ((ifptr == NULL) || (ifptr == (void *)-1)) + return -1; + + dev = ifptr; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) + ifp = __in_dev_get_rtnl(dev); +#else + ifp = __in_dev_get(dev); +#endif + + if (v == 4) + inp->in4.s_addr = 0; +#ifdef USE_INET6 + else if (v == 6) + return -1; +#endif + + ifa = ifp->ifa_list; + while (ifa != NULL) { + if (ifa->ifa_flags & IFA_F_SECONDARY) + continue; + break; + } + + if (ifa == NULL) + return -1; + + sin.sin_family = AF_INET; + sinmask.sin_addr.s_addr = ifa->ifa_mask; + if (atype == FRI_BROADCAST) + sin.sin_addr.s_addr = ifa->ifa_broadcast; + else if (atype == FRI_PEERADDR) + sin.sin_addr.s_addr = ifa->ifa_address; + else + sin.sin_addr.s_addr = ifa->ifa_local; + + return ipf_ifpfillv4addr(atype, (struct sockaddr_in *)&sin, + (struct sockaddr_in *)&sinmask, + &inp->in4, &inpmask->in4); +} + + +void +m_copydata(mb_t *m, int off, int len, caddr_t cp) +{ + bcopy(MTOD(m, char *) + off, cp, len); +} + + +int ipfattach(ipf_main_softc_t *softc) +{ + int err, i; + + SPL_NET(s); + if (softc->ipf_running > 0) { + SPL_X(s); + return -EBUSY; + } + + MUTEX_INIT(&softc->ipf_rw, "ipf rw mutex"); + MUTEX_INIT(&softc->ipf_timeoutlock, "ipf timeout lock mutex"); + RWLOCK_INIT(&softc->ipf_tokens, "ipf token rwlock"); + + for (i = 0; i < sizeof(ipf_hooks)/sizeof(ipf_hooks[0]); i++) { + err = nf_register_hook(&ipf_hooks[i]); + if (err != 0) + return err; + } + + if (ipf_init_all(softc) < 0) { + for (i = 0; i < sizeof(ipf_hooks)/sizeof(ipf_hooks[0]); i++) + nf_unregister_hook(&ipf_hooks[i]); + SPL_X(s); + return -EIO; + } + +#ifdef notyet + if (ipf_control_forwarding & 1) + ipv4_devconf.forwarding = 1; +#endif + + ipid = 0; + + SPL_X(s); + + init_timer(&softc->ipf_timer); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) + softc->ipf_timer.function = ipf_timer_func; + softc->ipf_timer.data = (unsigned long)softc; +#else + softc->ipf_timer.function = ipf_timer_func; + softc->ipf_timer.data = softc; +#endif + softc->ipf_timer.expires = (HZ / IPF_HZ_DIVIDE) * IPF_HZ_MULT; + add_timer(&softc->ipf_timer); + mod_timer(&softc->ipf_timer, HZ/2 + jiffies); + + return 0; +} + +int ipfdetach(ipf_main_softc_t *softc) +{ + int i; + + del_timer(&softc->ipf_timer); + + SPL_NET(s); + + for (i = 0; i < sizeof(ipf_hooks)/sizeof(ipf_hooks[0]); i++) + nf_unregister_hook(&ipf_hooks[i]); + +#ifdef notyet + if (ipf_control_forwarding & 2) + ipv4_devconf.forwarding = 0; +#endif + + ipf_fini_all(softc); + + MUTEX_DESTROY(&softc->ipf_timeoutlock); + MUTEX_DESTROY(&softc->ipf_rw); + RW_DESTROY(&softc->ipf_tokens); + + SPL_X(s); + + return 0; +} + + +static u_int +ipf_linux_inout(hooknum, skbp, inifp, outifp, okfn) + u_int hooknum; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) + struct sk_buff *skbp; +#else + struct sk_buff **skbp; +#endif + const struct net_device *inifp, *outifp; + int (*okfn)(struct sk_buff *); +{ + int result, hlen, dir; + void *ifp; + ip_t *ip; + mb_t *sk; + + if (inifp == NULL && outifp != NULL) { + dir = IPF_OUT; + ifp = (void *)outifp; + } else if (inifp != NULL && outifp == NULL) { + dir = IPF_IN; + ifp = (void *)inifp; + } else + return NF_DROP; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) + sk = skbp; +#else + sk = *skbp; +#endif + ip = MTOD(sk, ip_t *); + if (ip->ip_v == 4) { + hlen = ip->ip_hl << 2; +#ifdef USE_INET6 + } else if (ip->ip_v == 6) { + hlen = sizeof(ip6_t); +#endif + } else + return NF_DROP; + result = ipf_check(&ipfmain, ip, hlen, (struct net_device *)ifp, dir, &sk); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) + *skbp = sk; +#endif + /* + * This is kind of not always right...*skbp == NULL might really be + * a drop but Linux expects *skbp != NULL for NF_DROP. + */ + if (sk == NULL) + return NF_STOLEN; + + if (result != 0) + return NF_DROP; + + return NF_ACCEPT; +} + + +INLINE void +ipf_read_enter(ipfrwlock_t *rwlk) +{ +#if defined(IPFDEBUG) && !defined(_KERNEL) + if (rwlk->ipf_magic != 0x97dd8b3a) { + printk("ipf_read_enter:rwlk %p ipf_magic 0x%x\n", + rwlk, rwlk->ipf_magic); + rwlk->ipf_magic = 0; + *((int *)rwlk->ipf_magic) = 1; + } +#endif + read_lock_bh(&rwlk->ipf_lk); + ATOMIC_INC32(rwlk->ipf_isr); +} + + +INLINE void +ipf_write_enter(ipfrwlock_t *rwlk) +{ +#if defined(IPFDEBUG) && !defined(_KERNEL) + if (rwlk->ipf_magic != 0x97dd8b3a) { + printk("ipf_write_enter:rwlk %p ipf_magic 0x%x\n", + rwlk, rwlk->ipf_magic); + rwlk->ipf_magic = 0; + *((int *)rwlk->ipf_magic) = 1; + } +#endif + write_lock_bh(&rwlk->ipf_lk); + rwlk->ipf_isw = 1; +} + + +INLINE void +ipf_rw_exit(ipfrwlock_t *rwlk) +{ +#if defined(IPFDEBUG) && !defined(_KERNEL) + if (rwlk->ipf_magic != 0x97dd8b3a) { + printk("ipf_rw_exit:rwlk %p ipf_magic 0x%x\n", + rwlk, rwlk->ipf_magic); + rwlk->ipf_magic = 0; + *((int *)rwlk->ipf_magic) = 1; + } +#endif + if (rwlk->ipf_isw > 0) { + rwlk->ipf_isw = 0; + write_unlock_bh(&rwlk->ipf_lk); + } else if (rwlk->ipf_isr > 0) { + ATOMIC_DEC32(rwlk->ipf_isr); + read_unlock_bh(&rwlk->ipf_lk); + } else { + panic("rwlk->ipf_isw %d isr %d rwlk %p name [%s]\n", + rwlk->ipf_isw, rwlk->ipf_isr, rwlk, rwlk->ipf_lname); + } +} + + +/* + * This is not a perfect solution for a downgrade because we can lose the lock + * on the object of desire. + */ +INLINE void +ipf_rw_downgrade(ipfrwlock_t *rwlk) +{ + ipf_rw_exit(rwlk); + ipf_read_enter(rwlk); +} + +void ipf_rw_init(rwlck, name) +ipfrwlock_t *rwlck; +char *name; +{ + memset(rwlck, 0, sizeof(*rwlck)); + rwlck->ipf_lname = name; + rwlock_init(&rwlck->ipf_lk); +} + +#if 0 +void dumpskbuff(sk) + struct sk_buff *sk; +{ + char line[80], *t; + u_char *s1, *s2; + int len, i; + u_char c; + + while (sk != NULL) { + len = sk->end - sk->data; + + for (s1 = MTOD(sk, char *); len > 0; ) { + t = line; + s2 = s1; + for (i = 0; i < len && i < 16; i++) { + c = *s2++; + sprintf(t, "%02x", c); + t += 2; + if (i &1) + *t++ = ' '; + } + *t++ = ' '; + *t++ = ' '; + for (i = 0; i < len && i < 16; i++) { + c = *s1++; + *t++ = (c >= 32 && c < 127) ? c : '.'; + } + *t = '\0'; + printf("%p@%03d %s\n", sk, s1 - MTOD(sk, u_char *), line); + if (len > 16) { + len -= 16; + s1 += 16; + } else + len = 0; + } + sk = sk->next; + } +} +#endif + + +mb_t * +m_pullup(mb_t *m, int len) +{ + if (len <= M_LEN(m)) + return m; + kfree_skb(m); + return NULL; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pullup */ +/* Returns: NULL == pullup failed, else pointer to protocol header */ +/* Parameters: xmin(I)- pointer to buffer where data packet starts */ +/* fin(I) - pointer to packet information */ +/* len(I) - number of bytes to pullup */ +/* */ +/* Attempt to move at least len bytes (from the start of the buffer) into a */ +/* single buffer for ease of access. Operating system native functions are */ +/* used to manage buffers - if necessary. If the entire packet ends up in */ +/* a single buffer, set the FI_COALESCE flag even though ipf_coalesce() has */ +/* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */ +/* and ONLY if the pullup succeeds. */ +/* */ +/* We assume that 'min' is a pointer to a buffer that is part of the chain */ +/* of buffers that starts at *fin->fin_mp. */ +/* ------------------------------------------------------------------------ */ +void * +ipf_pullup(mb_t *xmin, fr_info_t *fin, int len) +{ + int dpoff, ipoff; + mb_t *m = xmin; + char *ip; + + if (m == NULL) + return NULL; + + ip = (char *)fin->fin_ip; + if ((fin->fin_flx & FI_COALESCE) != 0) + return ip; + + ipoff = fin->fin_ipoff; + if (fin->fin_dp != NULL) + dpoff = (char *)fin->fin_dp - (char *)ip; + else + dpoff = 0; + + if (M_LEN(m) < len) { + m = m_pullup(m, len); + *fin->fin_mp = m; + fin->fin_m = m; + if (m == NULL) { + return NULL; + } + ip = MTOD(m, char *) + ipoff; + } + + fin->fin_ip = (ip_t *)ip; + if (fin->fin_dp != NULL) + fin->fin_dp = (char *)fin->fin_ip + dpoff; + if (fin->fin_fraghdr != NULL) + fin->fin_fraghdr = (char *)ip + + ((char *)fin->fin_fraghdr - + (char *)fin->fin_ip); + + if (len == fin->fin_plen) + fin->fin_flx |= FI_COALESCE; + return ip; +} + + +#ifndef ipf_random +/* + * In the face of no kernel random function, this is implemented...it is + * not meant to be random, just a fill in. + */ +int +ipf_random() +{ + static int last = 0; + static int calls = 0; + struct timeval tv; + int number; + + GETKTIME(&tv); + last *= tv.tv_usec + calls++; + last += (int)&range * ipfmain.ipf_ticks; + number = last + tv.tv_sec; + return number; +} +#endif + + +int ipf_inject(fin, m) +fr_info_t *fin; +mb_t *m; +{ + FREE_MB_T(m); + + fin->fin_m = NULL; + fin->fin_ip = NULL; + + return EINVAL; +} + + +/* + * Copy data from a buffer back into the indicated mbuf chain, + * starting "off" bytes from the beginning, extending the mbuf + * chain if necessary. + */ +void +m_copyback(m0, off0, len0, cp) + mb_t *m0; + int off0; + int len0; + caddr_t cp; +{ + mb_t *m = m0, *n; + int totlen = 0; + int mlen; + int off = off0; + int len = len0; + + if (m0 == 0) + return; + while (off > (mlen = m->len)) { + off -= mlen; + totlen += mlen; + if (m->next == 0) { + n = alloc_skb(off, in_interrupt() ? GFP_ATOMIC : + GFP_KERNEL); + if (n == 0) + return; + n->len = off; + m->next = n; + } + m = m->next; + } + while (len > 0) { + mlen = MIN(m->len - off, len); + bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen); + cp += mlen; + len -= mlen; + mlen += off; + off = 0; + totlen += mlen; + if (len == 0) + break; + if (m->next == 0) { + n = alloc_skb(len, in_interrupt() ? GFP_ATOMIC : + GFP_KERNEL); + if (n == 0) + return; + n->len = len; + m->next = n; + } + m = m->next; + } +} + + +static void +ipf_timer_func(unsigned long value) +{ + ipf_main_softc_t *softc = (ipf_main_softc_t *)value; + + READ_ENTER(&softc->ipf_global); + + if (softc->ipf_running > 0) + ipf_slowtimer(softc); + + if (softc->ipf_running == -1 || softc->ipf_running == 1) + mod_timer(&softc->ipf_timer, HZ/2 + jiffies); + + RWLOCK_EXIT(&softc->ipf_global); +} + + +#ifdef USE_INET6 +INLINE void +ipf_checkv6sum(fin) + fr_info_t *fin; +{ +# ifdef IPFILTER_CKSUM + if (fr_checkl4sum(fin) == -1) + fin->fin_flx |= FI_BAD; +# endif +} +#endif diff --git a/ip_fil_netbsd.c b/ip_fil_netbsd.c new file mode 100644 index 0000000000000..9016d299dbb84 --- /dev/null +++ b/ip_fil_netbsd.c @@ -0,0 +1,2127 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ +#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$"; +#endif + +#if defined(KERNEL) || defined(_KERNEL) +# undef KERNEL +# undef _KERNEL +# define KERNEL 1 +# define _KERNEL 1 +#endif +#include <sys/param.h> +#if (NetBSD >= 199905) && !defined(IPFILTER_LKM) +# include "opt_pfil_hooks.h" +# include "opt_ipsec.h" +#endif +#include <sys/errno.h> +#include <sys/types.h> +#include <sys/file.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/systm.h> +#include <sys/select.h> +#if (NetBSD > 199609) +# include <sys/dirent.h> +#else +# include <sys/dir.h> +#endif +#if (__NetBSD_Version__ >= 599005900) +# include <sys/cprng.h> +#endif +#include <sys/mbuf.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/poll.h> +#if (__NetBSD_Version__ >= 399002000) +# include <sys/kauth.h> +#endif + +#include <net/if.h> +#include <net/route.h> +#include <netinet/in.h> +#include <netinet/in_var.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/ip_var.h> +#include <netinet/tcp.h> +#if __NetBSD_Version__ >= 105190000 /* 1.5T */ +# include <netinet/tcp_timer.h> +# include <netinet/tcp_var.h> +#endif +#include <netinet/udp.h> +#include <netinet/tcpip.h> +#include <netinet/ip_icmp.h> +#include "netinet/ip_compat.h" +#ifdef USE_INET6 +# include <netinet/icmp6.h> +# if (__NetBSD_Version__ >= 106000000) +# include <netinet6/nd6.h> +# endif +#endif +#include "netinet/ip_fil.h" +#include "netinet/ip_nat.h" +#include "netinet/ip_frag.h" +#include "netinet/ip_state.h" +#include "netinet/ip_proxy.h" +#include "netinet/ip_auth.h" +#include "netinet/ip_sync.h" +#include "netinet/ip_lookup.h" +#include "netinet/ip_dstlist.h" +#ifdef IPFILTER_SCAN +#include "netinet/ip_scan.h" +#endif +#include <sys/md5.h> +#include <sys/kernel.h> +#include <sys/conf.h> +#ifdef INET +extern int ip_optcopy __P((struct ip *, struct ip *)); +#endif + +#ifdef IPFILTER_M_IPFILTER +MALLOC_DEFINE(M_IPFILTER, "IP Filter", "IP Filter packet filter data structures"); +#endif + +#if __NetBSD_Version__ >= 105009999 +# define csuminfo csum_flags +#endif + +#if __NetBSD_Version__ < 200000000 +extern struct protosw inetsw[]; +#endif +#if (NetBSD >= 199511) +static int ipfopen(dev_t dev, int flags, int devtype, PROC_T *p); +static int ipfclose(dev_t dev, int flags, int devtype, PROC_T *p); +#else +# if (__NetBSD_Version__ >= 399001400) +static int ipfopen(dev_t dev, int flags, struct lwp *); +static int ipfclose(dev_t dev, int flags, struct lwp *); +# else +static int ipfopen(dev_t dev, int flags); +static int ipfclose(dev_t dev, int flags); +# endif /* __NetBSD_Version__ >= 399001400 */ +#endif +static int ipfread(dev_t, struct uio *, int ioflag); +static int ipfwrite(dev_t, struct uio *, int ioflag); +static int ipfpoll(dev_t, int events, PROC_T *); +static void ipf_timer_func __P((void *ptr)); + +const struct cdevsw ipl_cdevsw = { + ipfopen, ipfclose, ipfread, ipfwrite, ipfioctl, + nostop, notty, ipfpoll, nommap, +#if (__NetBSD_Version__ >= 200000000) + nokqfilter, +#endif +#ifdef D_OTHER + D_OTHER, +#endif +}; + +ipf_main_softc_t ipfmain; + +static u_short ipid = 0; +static int (*ipf_savep) __P((void *, ip_t *, int, void *, int, struct mbuf **)); +static int ipf_send_ip __P((fr_info_t *, mb_t *)); +#ifdef USE_INET6 +static int ipf_fastroute6 __P((struct mbuf *, struct mbuf **, + fr_info_t *, frdest_t *)); +#endif + +#if defined(NETBSD_PF) +# include <net/pfil.h> +/* + * We provide the ipf_checkp name just to minimize changes later. + */ +int (*ipf_checkp) __P((void *, ip_t *ip, int hlen, void *ifp, int out, mb_t **mp)); +#endif /* NETBSD_PF */ + +#if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000) +# include <net/pfil.h> + +static int ipf_check_wrapper(void *, struct mbuf **, struct ifnet *, int ); + +static int +ipf_check_wrapper(arg, mp, ifp, dir) + void *arg; + struct mbuf **mp; + struct ifnet *ifp; + int dir; +{ + struct ip *ip; + int rv, hlen; + +#if __NetBSD_Version__ >= 200080000 + /* + * ensure that mbufs are writable beforehand + * as it's assumed by ipf code. + * XXX inefficient + */ + int error = m_makewritable(mp, 0, M_COPYALL, M_DONTWAIT); + + if (error) { + m_freem(*mp); + *mp = NULL; + return error; + } +#endif + ip = mtod(*mp, struct ip *); + hlen = ip->ip_hl << 2; + +#ifdef INET +#if defined(M_CSUM_TCPv4) + /* + * If the packet is out-bound, we can't delay checksums + * here. For in-bound, the checksum has already been + * validated. + */ + if (dir == PFIL_OUT) { + if ((*mp)->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_UDPv4)) { + in_delayed_cksum(*mp); + (*mp)->m_pkthdr.csum_flags &= + ~(M_CSUM_TCPv4|M_CSUM_UDPv4); + } + } +#endif /* M_CSUM_TCPv4 */ +#endif /* INET */ + + /* + * Note, we don't need to update the checksum, because + * it has already been verified. + */ + rv = ipf_check(&ipfmain, ip, hlen, ifp, (dir == PFIL_OUT), mp); + + return (rv); +} + +# ifdef USE_INET6 +# include <netinet/ip6.h> + +static int ipf_check_wrapper6(void *, struct mbuf **, struct ifnet *, int ); + +static int +ipf_check_wrapper6(arg, mp, ifp, dir) + void *arg; + struct mbuf **mp; + struct ifnet *ifp; + int dir; +{ +# if defined(M_CSUM_TCPv6) && (__NetBSD_Version__ > 200000000) + /* + * If the packet is out-bound, we can't delay checksums + * here. For in-bound, the checksum has already been + * validated. + */ + if (dir == PFIL_OUT) { + if ((*mp)->m_pkthdr.csum_flags & (M_CSUM_TCPv6|M_CSUM_UDPv6)) { +# if (__NetBSD_Version__ > 399000600) + in6_delayed_cksum(*mp); +# endif + (*mp)->m_pkthdr.csum_flags &= ~(M_CSUM_TCPv6| + M_CSUM_UDPv6); + } + } +# endif + + return (ipf_check(&ipfmain, mtod(*mp, struct ip *), sizeof(struct ip6_hdr), + ifp, (dir == PFIL_OUT), mp)); +} +# endif + + +# if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET) +static int ipf_pfilsync(void *, struct mbuf **, struct ifnet *, int); + +static int +ipf_pfilsync(hdr, mp, ifp, dir) + void *hdr; + struct mbuf **mp; + struct ifnet *ifp; + int dir; +{ + /* + * The interface pointer is useless for create (we have nothing to + * compare it to) and at detach, the interface name is still in the + * list of active NICs (albeit, down, but that's not any real + * indicator) and doing ifunit() on the name will still return the + * pointer, so it's not much use then, either. + */ + ipf_sync(&ipfmain, NULL); + return 0; +} +# endif + +#endif /* __NetBSD_Version__ >= 105110000 */ + + +#if defined(IPFILTER_LKM) +int +ipf_identify(s) + char *s; +{ + if (strcmp(s, "ipl") == 0) + return 1; + return 0; +} +#endif /* IPFILTER_LKM */ + + +/* + * Try to detect the case when compiling for NetBSD with pseudo-device + */ +void +ipfilterattach(count) + int count; +{ + if (ipf_load_all() == 0) + (void) ipf_create_all(&ipfmain); +} + + +int +ipfattach(softc) + ipf_main_softc_t *softc; +{ + SPL_INT(s); +#if (__NetBSD_Version__ >= 499005500) + int i; +#endif +#if defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000) + int error = 0; +# if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000) + struct pfil_head *ph_inet; +# ifdef USE_INET6 + struct pfil_head *ph_inet6; +# endif +# if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET) + struct pfil_head *ph_ifsync; +# endif +# endif +#endif + + SPL_NET(s); + if ((softc->ipf_running > 0) || (ipf_checkp == ipf_check)) { + printf("IP Filter: already initialized\n"); + SPL_X(s); + IPFERROR(130017); + return EBUSY; + } + + if (ipf_init_all(softc) < 0) { + SPL_X(s); + IPFERROR(130015); + return EIO; + } + +#ifdef NETBSD_PF +# if (__NetBSD_Version__ >= 104200000) +# if __NetBSD_Version__ >= 105110000 + ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); +# ifdef USE_INET6 + ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); +# endif +# if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET) + ph_ifsync = pfil_head_get(PFIL_TYPE_IFNET, 0); +# endif + + if (ph_inet == NULL +# ifdef USE_INET6 + && ph_inet6 == NULL +# endif +# if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET) + && ph_ifsync == NULL +# endif + ) { + SPL_X(s); + IPFERROR(130016); + return ENODEV; + } + + if (ph_inet != NULL) + error = pfil_add_hook((void *)ipf_check_wrapper, NULL, + PFIL_IN|PFIL_OUT, ph_inet); + else + error = 0; +# else + error = pfil_add_hook((void *)ipf_check, PFIL_IN|PFIL_OUT, + &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); +# endif + if (error) { + IPFERROR(130013); + goto pfil_error; + } +# else + pfil_add_hook((void *)ipf_check, PFIL_IN|PFIL_OUT); +# endif + +# ifdef USE_INET6 +# if __NetBSD_Version__ >= 105110000 + if (ph_inet6 != NULL) + error = pfil_add_hook((void *)ipf_check_wrapper6, NULL, + PFIL_IN|PFIL_OUT, ph_inet6); + else + error = 0; + if (error) { + pfil_remove_hook((void *)ipf_check_wrapper6, NULL, + PFIL_IN|PFIL_OUT, ph_inet6); + ipfmain.ipf_interror = 130014; + goto pfil_error; + } +# else + error = pfil_add_hook((void *)ipf_check, PFIL_IN|PFIL_OUT, + &inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh); + if (error) { + pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT, + &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); + IPFERROR(130014); + goto pfil_error; + } +# endif +# endif + +# if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET) + if (ph_ifsync != NULL) + (void) pfil_add_hook((void *)ipf_pfilsync, NULL, + PFIL_IFNET, ph_ifsync); +# endif +#endif + +#if (__NetBSD_Version__ >= 499005500) + for (i = 0; i < IPL_LOGSIZE; i++) + selinit(&ipfmain.ipf_selwait[i]); +#else + bzero((char *)ipfmain.ipf_selwait, sizeof(ipfmain.ipf_selwait)); +#endif + ipf_savep = ipf_checkp; + ipf_checkp = ipf_check; + +#ifdef INET + if (softc->ipf_control_forwarding & 1) + ipforwarding = 1; +#endif + + ipid = 0; + + SPL_X(s); + +#if (__NetBSD_Version__ >= 104010000) +# if (__NetBSD_Version__ >= 499002000) + callout_init(&softc->ipf_slow_ch, 0); +# else + callout_init(&softc->ipf_slow_ch); +# endif + callout_reset(&softc->ipf_slow_ch, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT, + ipf_timer_func, softc); +#else + timeout(ipf_timer_func, softc, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT); +#endif + return 0; + +#if __NetBSD_Version__ >= 105110000 +pfil_error: + SPL_X(s); + ipf_fini_all(softc); + return error; +#endif +} + +static void +ipf_timer_func(ptr) + void *ptr; +{ + ipf_main_softc_t *softc = ptr; + SPL_INT(s); + + SPL_NET(s); + READ_ENTER(&softc->ipf_global); + + if (softc->ipf_running > 0) + ipf_slowtimer(softc); + + if (softc->ipf_running == -1 || softc->ipf_running == 1) { +#if NETBSD_GE_REV(104240000) + callout_reset(&softc->ipf_slow_ch, hz / 2, + ipf_timer_func, softc); +#else + timeout(ipf_timer_func, softc, + (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT); +#endif + } + RWLOCK_EXIT(&softc->ipf_global); + SPL_X(s); +} + + +/* + * Disable the filter by removing the hooks from the IP input/output + * stream. + */ +int +ipfdetach(softc) + ipf_main_softc_t *softc; +{ + SPL_INT(s); +#if (__NetBSD_Version__ >= 499005500) + int i; +#endif +#if defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000) + int error = 0; +# if __NetBSD_Version__ >= 105150000 + struct pfil_head *ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); +# ifdef USE_INET6 + struct pfil_head *ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); +# endif +# if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET) + struct pfil_head *ph_ifsync = pfil_head_get(PFIL_TYPE_IFNET, 0); +# endif +# endif +#endif + + SPL_NET(s); + +#if (__NetBSD_Version__ >= 104010000) + if (softc->ipf_running > 0) + callout_stop(&softc->ipf_slow_ch); +#else + untimeout(ipf_slowtimer, NULL); +#endif /* NetBSD */ + + ipf_checkp = ipf_savep; + (void) ipf_flush(softc, IPL_LOGIPF, FR_INQUE|FR_OUTQUE|FR_INACTIVE); + (void) ipf_flush(softc, IPL_LOGIPF, FR_INQUE|FR_OUTQUE); + +#ifdef INET + if (softc->ipf_control_forwarding & 2) + ipforwarding = 0; +#endif + +#ifdef NETBSD_PF +# if (__NetBSD_Version__ >= 104200000) +# if __NetBSD_Version__ >= 105110000 +# if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET) + (void) pfil_remove_hook((void *)ipf_pfilsync, NULL, + PFIL_IFNET, ph_ifsync); +# endif + + if (ph_inet != NULL) + error = pfil_remove_hook((void *)ipf_check_wrapper, NULL, + PFIL_IN|PFIL_OUT, ph_inet); + else + error = 0; +# else + error = pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT, + &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); +# endif + if (error) { + SPL_X(s); + IPFERROR(130011); + return error; + } +# else + pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT); +# endif +# ifdef USE_INET6 +# if __NetBSD_Version__ >= 105110000 + if (ph_inet6 != NULL) + error = pfil_remove_hook((void *)ipf_check_wrapper6, NULL, + PFIL_IN|PFIL_OUT, ph_inet6); + else + error = 0; +# else + error = pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT, + &inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh); +# endif + if (error) { + SPL_X(s); + IPFERROR(130012); + return error; + } +# endif +#endif + SPL_X(s); + +#if (__NetBSD_Version__ >= 499005500) + for (i = 0; i < IPL_LOGSIZE; i++) + seldestroy(&ipfmain.ipf_selwait[i]); +#endif + + ipf_fini_all(softc); + + return 0; +} + + +/* + * Filter ioctl interface. + */ +int +ipfioctl(dev, cmd, data, mode +#if (NetBSD >= 199511) +, p) +# if (__NetBSD_Version__ >= 399001400) + struct lwp *p; +# if (__NetBSD_Version__ >= 399002000) +# define UID(l) kauth_cred_getuid((l)->l_cred) +# else +# define UID(l) ((l)->l_proc->p_cred->p_ruid) +# endif +# else + struct proc *p; +# define UID(p) ((p)->p_cred->p_ruid) +# endif +#else +) +#endif + dev_t dev; + u_long cmd; +#if (__NetBSD_Version__ >= 499001000) + void *data; +#else + caddr_t data; +#endif + int mode; +{ + int error = 0, unit = 0; + SPL_INT(s); + +#if (__NetBSD_Version__ >= 399002000) + if ((mode & FWRITE) && + kauth_authorize_network(p->l_cred, KAUTH_NETWORK_FIREWALL, + KAUTH_REQ_NETWORK_FIREWALL_FW, NULL, + NULL, NULL)) { + ipfmain.ipf_interror = 130005; + return EPERM; + } +#else + if ((securelevel >= 2) && (mode & FWRITE)) { + ipfmain.ipf_interror = 130001; + return EPERM; + } +#endif + + unit = GET_MINOR(dev); + if ((IPL_LOGMAX < unit) || (unit < 0)) { + ipfmain.ipf_interror = 130002; + return ENXIO; + } + + if (ipfmain.ipf_running <= 0) { + if (unit != IPL_LOGIPF && cmd != SIOCIPFINTERROR) { + ipfmain.ipf_interror = 130003; + return EIO; + } + if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET && + cmd != SIOCIPFSET && cmd != SIOCFRENB && + cmd != SIOCGETFS && cmd != SIOCGETFF && + cmd != SIOCIPFINTERROR) { + ipfmain.ipf_interror = 130004; + return EIO; + } + } + + SPL_NET(s); + + error = ipf_ioctlswitch(&ipfmain, unit, data, cmd, mode, UID(p), p); + if (error != -1) { + SPL_X(s); + return error; + } + + SPL_X(s); + return error; +} + + +/* + * ipf_send_reset - this could conceivably be a call to tcp_respond(), but that + * requires a large amount of setting up and isn't any more efficient. + */ +int +ipf_send_reset(fin) + fr_info_t *fin; +{ + struct tcphdr *tcp, *tcp2; + int tlen = 0, hlen; + struct mbuf *m; +#ifdef USE_INET6 + ip6_t *ip6; +#endif + ip_t *ip; + + tcp = fin->fin_dp; + if (tcp->th_flags & TH_RST) + return -1; /* feedback loop */ + + if (ipf_checkl4sum(fin) == -1) + return -1; + + tlen = fin->fin_dlen - (TCP_OFF(tcp) << 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 + hlen = sizeof(ip_t); +#endif +#ifdef MGETHDR + MGETHDR(m, M_DONTWAIT, MT_HEADER); +#else + MGET(m, M_DONTWAIT, MT_HEADER); +#endif + if (m == NULL) + return -1; + if (sizeof(*tcp2) + hlen > MHLEN) { + MCLGET(m, M_DONTWAIT); + if (m == NULL) + return -1; + if ((m->m_flags & M_EXT) == 0) { + FREE_MB_T(m); + return -1; + } + } + + m->m_len = sizeof(*tcp2) + hlen; + m->m_data += max_linkhdr; + m->m_pkthdr.len = m->m_len; + m->m_pkthdr.rcvif = (struct ifnet *)0; + ip = mtod(m, struct ip *); + bzero((char *)ip, hlen); +#ifdef USE_INET6 + ip6 = (ip6_t *)ip; +#endif + bzero((char *)ip, sizeof(*tcp2) + hlen); + tcp2 = (struct tcphdr *)((char *)ip + hlen); + tcp2->th_sport = tcp->th_dport; + tcp2->th_dport = tcp->th_sport; + + if (tcp->th_flags & TH_ACK) { + tcp2->th_seq = tcp->th_ack; + tcp2->th_flags = TH_RST; + tcp2->th_ack = 0; + } else { + tcp2->th_seq = 0; + 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_x2 = 0; + TCP_OFF_A(tcp2, sizeof(*tcp2) >> 2); + tcp2->th_win = tcp->th_win; + tcp2->th_sum = 0; + tcp2->th_urp = 0; + +#ifdef USE_INET6 + if (fin->fin_v == 6) { + ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; + ip6->ip6_plen = htons(sizeof(struct tcphdr)); + ip6->ip6_nxt = IPPROTO_TCP; + ip6->ip6_hlim = 0; + ip6->ip6_src = fin->fin_dst6.in6; + ip6->ip6_dst = fin->fin_src6.in6; + tcp2->th_sum = in6_cksum(m, IPPROTO_TCP, + sizeof(*ip6), sizeof(*tcp2)); + return ipf_send_ip(fin, m); + } +#endif +#ifdef INET + ip->ip_p = IPPROTO_TCP; + ip->ip_len = htons(sizeof(struct tcphdr)); + ip->ip_src.s_addr = fin->fin_daddr; + ip->ip_dst.s_addr = fin->fin_saddr; + tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2)); + ip->ip_len = hlen + sizeof(*tcp2); + return ipf_send_ip(fin, m); +#else + return 0; +#endif +} + + +/* + * Expects ip_len to be in host byte order when called. + */ +static int +ipf_send_ip(fin, m) + fr_info_t *fin; + mb_t *m; +{ + fr_info_t fnew; +#ifdef INET + ip_t *oip; +#endif + ip_t *ip; + int hlen; + + ip = mtod(m, ip_t *); + bzero((char *)&fnew, sizeof(fnew)); + fnew.fin_main_soft = fin->fin_main_soft; + + IP_V_A(ip, fin->fin_v); + switch (fin->fin_v) + { +#ifdef INET + case 4 : + oip = fin->fin_ip; + hlen = sizeof(*oip); + fnew.fin_v = 4; + fnew.fin_p = ip->ip_p; + fnew.fin_plen = ntohs(ip->ip_len); + HTONS(ip->ip_len); + IP_HL_A(ip, sizeof(*oip) >> 2); + ip->ip_tos = oip->ip_tos; + ip->ip_id = ipf_nextipid(fin); + ip->ip_off = htons(ip_mtudisc ? IP_DF : 0); + ip->ip_ttl = ip_defttl; + ip->ip_sum = 0; + break; +#endif +#ifdef USE_INET6 + case 6 : + { + ip6_t *ip6 = (ip6_t *)ip; + + ip6->ip6_vfc = 0x60; + ip6->ip6_hlim = IPDEFTTL; + + hlen = sizeof(*ip6); + fnew.fin_p = ip6->ip6_nxt; + fnew.fin_v = 6; + fnew.fin_plen = ntohs(ip6->ip6_plen) + hlen; + break; + } +#endif + default : + return EINVAL; + } +#ifdef IPSEC + m->m_pkthdr.rcvif = NULL; +#endif + + fnew.fin_ifp = fin->fin_ifp; + fnew.fin_flx = FI_NOCKSUM; + fnew.fin_m = m; + fnew.fin_ip = ip; + fnew.fin_mp = &m; + fnew.fin_hlen = hlen; + fnew.fin_dp = (char *)ip + hlen; + (void) ipf_makefrip(hlen, ip, &fnew); + + return ipf_fastroute(m, &m, &fnew, NULL); +} + + +int +ipf_send_icmp_err(type, fin, dst) + int type; + fr_info_t *fin; + int dst; +{ + int err, hlen, xtra, iclen, ohlen, avail, code; + struct in_addr dst4; + struct icmp *icmp; + struct mbuf *m; + i6addr_t dst6; + void *ifp; +#ifdef USE_INET6 + ip6_t *ip6; +#endif + ip_t *ip, *ip2; + + if ((type < 0) || (type > ICMP_MAXTYPE)) + return -1; + + code = fin->fin_icode; +#ifdef USE_INET6 + if ((code < 0) || (code > sizeof(icmptoicmp6unreach)/sizeof(int))) + return -1; +#endif + + if (ipf_checkl4sum(fin) == -1) + return -1; +#ifdef MGETHDR + MGETHDR(m, M_DONTWAIT, MT_HEADER); +#else + MGET(m, M_DONTWAIT, MT_HEADER); +#endif + if (m == NULL) + return -1; + avail = MHLEN; + + xtra = 0; + hlen = 0; + ohlen = 0; + dst4.s_addr = 0; + ifp = fin->fin_ifp; + if (fin->fin_v == 4) { + if ((fin->fin_p == IPPROTO_ICMP) && !(fin->fin_flx & FI_SHORT)) + switch (ntohs(fin->fin_data[0]) >> 8) + { + case ICMP_ECHO : + case ICMP_TSTAMP : + case ICMP_IREQ : + case ICMP_MASKREQ : + break; + default : + FREE_MB_T(m); + return 0; + } + + if (dst == 0) { + if (ipf_ifpaddr(&ipfmain, 4, FRI_NORMAL, ifp, + &dst6, NULL) == -1) { + FREE_MB_T(m); + return -1; + } + dst4 = dst6.in4; + } else + dst4.s_addr = fin->fin_daddr; + + hlen = sizeof(ip_t); + ohlen = fin->fin_hlen; + iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen; + if (fin->fin_hlen < fin->fin_plen) + xtra = MIN(fin->fin_dlen, 8); + else + xtra = 0; + } + +#ifdef USE_INET6 + else if (fin->fin_v == 6) { + hlen = sizeof(ip6_t); + ohlen = sizeof(ip6_t); + iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen; + type = icmptoicmp6types[type]; + if (type == ICMP6_DST_UNREACH) + code = icmptoicmp6unreach[code]; + + if (iclen + max_linkhdr + fin->fin_plen > avail) { + MCLGET(m, M_DONTWAIT); + if (m == NULL) + return -1; + if ((m->m_flags & M_EXT) == 0) { + FREE_MB_T(m); + return -1; + } + avail = MCLBYTES; + } + xtra = MIN(fin->fin_plen, avail - iclen - max_linkhdr); + xtra = MIN(xtra, IPV6_MMTU - iclen); + if (dst == 0) { + if (ipf_ifpaddr(&ipfmain, 6, FRI_NORMAL, ifp, + &dst6, NULL) == -1) { + FREE_MB_T(m); + return -1; + } + } else + dst6 = fin->fin_dst6; + } +#endif + else { + FREE_MB_T(m); + return -1; + } + + avail -= (max_linkhdr + iclen); + if (avail < 0) { + FREE_MB_T(m); + return -1; + } + if (xtra > avail) + xtra = avail; + iclen += xtra; + m->m_data += max_linkhdr; + m->m_pkthdr.rcvif = (struct ifnet *)0; + m->m_pkthdr.len = iclen; + m->m_len = iclen; + ip = mtod(m, ip_t *); + icmp = (struct icmp *)((char *)ip + hlen); + ip2 = (ip_t *)&icmp->icmp_ip; + + 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) { + if (fin->fin_mtu != 0) { + icmp->icmp_nextmtu = htons(fin->fin_mtu); + + } else if (ifp != NULL) { + icmp->icmp_nextmtu = htons(GETIFMTU_4(ifp)); + + } else { /* make up a number... */ + icmp->icmp_nextmtu = htons(fin->fin_plen - 20); + } + } +#endif + + bcopy((char *)fin->fin_ip, (char *)ip2, ohlen); + +#if defined(M_CSUM_IPv4) + /* + * Clear any in-bound checksum flags for this packet. + */ + m->m_pkthdr.csuminfo = 0; +#endif /* __NetBSD__ && M_CSUM_IPv4 */ + +#ifdef USE_INET6 + ip6 = (ip6_t *)ip; + if (fin->fin_v == 6) { + ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; + ip6->ip6_plen = htons(iclen - hlen); + ip6->ip6_nxt = IPPROTO_ICMPV6; + ip6->ip6_hlim = 0; + ip6->ip6_src = dst6.in6; + ip6->ip6_dst = fin->fin_src6.in6; + if (xtra > 0) + bcopy((char *)fin->fin_ip + ohlen, + (char *)&icmp->icmp_ip + ohlen, xtra); + icmp->icmp_cksum = in6_cksum(m, IPPROTO_ICMPV6, + sizeof(*ip6), iclen - hlen); + } else +#endif + { + ip->ip_p = IPPROTO_ICMP; + ip->ip_src.s_addr = dst4.s_addr; + ip->ip_dst.s_addr = fin->fin_saddr; + + if (xtra > 0) + bcopy((char *)fin->fin_ip + ohlen, + (char *)&icmp->icmp_ip + ohlen, xtra); + icmp->icmp_cksum = ipf_cksum((u_short *)icmp, + sizeof(*icmp) + 8); + ip->ip_len = iclen; + ip->ip_p = IPPROTO_ICMP; + } + err = ipf_send_ip(fin, m); + return err; +} + + +/* + * m0 - pointer to mbuf where the IP packet starts + * mpp - pointer to the mbuf pointer that is the start of the mbuf chain + */ +int +ipf_fastroute(m0, mpp, fin, fdp) + mb_t *m0, **mpp; + fr_info_t *fin; + frdest_t *fdp; +{ + register struct ip *ip, *mhip; + register struct mbuf *m = *mpp; + register struct route *ro; + int len, off, error = 0, hlen, code; + struct ifnet *ifp, *sifp; + ipf_main_softc_t *softc; +#if __NetBSD_Version__ >= 499001100 + union { + struct sockaddr dst; + struct sockaddr_in dst4; + } u; +#else + struct sockaddr_in *dst4; +#endif + struct sockaddr *dst; + u_short ip_off, ip_len; + struct route iproute; + struct rtentry *rt; + frdest_t node; + frentry_t *fr; + + if (fin->fin_v == 6) { +#ifdef USE_INET6 + error = ipf_fastroute6(m0, mpp, fin, fdp); +#else + error = EPROTONOSUPPORT; +#endif + if ((error != 0) && (*mpp != NULL)) + FREE_MB_T(*mpp); + return error; + } +#ifndef INET + FREE_MB_T(*mpp); + return EPROTONOSUPPORT; +#else + + hlen = fin->fin_hlen; + ip = mtod(m0, struct ip *); + softc = fin->fin_main_soft; + rt = NULL; + ifp = NULL; + +# if defined(M_CSUM_IPv4) + /* + * Clear any in-bound checksum flags for this packet. + */ + m0->m_pkthdr.csuminfo = 0; +# endif /* __NetBSD__ && M_CSUM_IPv4 */ + + /* + * Route packet. + */ + ro = &iproute; + bzero(ro, sizeof (*ro)); + fr = fin->fin_fr; + + if ((fr != NULL) && !(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) && + (fdp->fd_type == FRD_DSTLIST)) { + if (ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node) == 0) + fdp = &node; + } + if (fdp != NULL) + ifp = fdp->fd_ptr; + else + ifp = fin->fin_ifp; + + if ((ifp == NULL) && ((fr == NULL) || !(fr->fr_flags & FR_FASTROUTE))) { + error = -2; + goto bad; + } + +# if __NetBSD_Version__ >= 499001100 + if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0)) + sockaddr_in_init(&u.dst4, &fdp->fd_ip, 0); + else + sockaddr_in_init(&u.dst4, &ip->ip_dst, 0); + dst = &u.dst; + rtcache_setdst(ro, dst); + rt = rtcache_init(ro); +# else + dst4 = (struct sockaddr_in *)&ro->ro_dst; + dst = (struct sockaddr *)dst4; + dst4->sin_family = AF_INET; + dst4->sin_addr = ip->ip_dst; + + if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0)) + dst4->sin_addr = fdp->fd_ip; + + dst4->sin_len = sizeof(*dst); + rtalloc(ro); + rt = ro->ro_rt; +# endif + if ((ifp == NULL) && (rt != NULL)) + ifp = rt->rt_ifp; + if ((rt == NULL) || (ifp == NULL)) { + if (in_localaddr(ip->ip_dst)) + error = EHOSTUNREACH; + else + error = ENETUNREACH; + goto bad; + } + + + if (rt->rt_flags & RTF_GATEWAY) + dst = rt->rt_gateway; + + rt->rt_use++; + + /* + * For input packets which are being "fastrouted", they won't + * go back through output filtering and miss their chance to get + * NAT'd and counted. Duplicated packets aren't considered to be + * part of the normal packet stream, so do not NAT them or pass + * them through stateful checking, etc. + */ + if ((fdp != &fr->fr_dif) && (fin->fin_out == 0)) { + sifp = fin->fin_ifp; + fin->fin_ifp = ifp; + fin->fin_out = 1; + (void) ipf_acctpkt(fin, NULL); + fin->fin_fr = NULL; + if (!fr || !(fr->fr_flags & FR_RETMASK)) { + u_32_t pass; + + (void) ipf_state_check(fin, &pass); + } + + switch (ipf_nat_checkout(fin, NULL)) + { + case 0 : + break; + case 1 : + ip->ip_sum = 0; + break; + case -1 : + error = -1; + goto bad; + break; + } + + fin->fin_ifp = sifp; + fin->fin_out = 0; + } else + ip->ip_sum = 0; + /* + * If small enough for interface, can just send directly. + */ + m->m_pkthdr.rcvif = ifp; + + ip_len = ntohs(ip->ip_len); + if (ip_len <= ifp->if_mtu) { +# if defined(M_CSUM_IPv4) +# if (__NetBSD_Version__ >= 105009999) + if (ifp->if_csum_flags_tx & M_CSUM_IPv4) + m->m_pkthdr.csuminfo |= M_CSUM_IPv4; +# else + if (ifp->if_capabilities & IFCAP_CSUM_IPv4) + m->m_pkthdr.csuminfo |= M_CSUM_IPv4; +# endif /* (__NetBSD_Version__ >= 105009999) */ + else if (ip->ip_sum == 0) + ip->ip_sum = in_cksum(m, hlen); +# else + if (!ip->ip_sum) + ip->ip_sum = in_cksum(m, hlen); +# endif /* M_CSUM_IPv4 */ + + error = (*ifp->if_output)(ifp, m, dst, rt); + goto done; + } + + /* + * Too large for interface; fragment if possible. + * Must be able to put at least 8 bytes per fragment. + */ + ip_off = ntohs(ip->ip_off); + if (ip_off & IP_DF) { + error = EMSGSIZE; + goto bad; + } + len = (ifp->if_mtu - hlen) &~ 7; + if (len < 8) { + error = EMSGSIZE; + goto bad; + } + + { + int mhlen, firstlen = len; + struct mbuf **mnext = &m->m_act; + + /* + * Loop through length of segment after first fragment, + * make new header and copy data of each part and link onto chain. + */ + m0 = m; + mhlen = sizeof (struct ip); + for (off = hlen + len; off < ip_len; off += len) { +# ifdef MGETHDR + MGETHDR(m, M_DONTWAIT, MT_HEADER); +# else + MGET(m, M_DONTWAIT, MT_HEADER); +# endif + if (m == 0) { + m = m0; + error = ENOBUFS; + goto bad; + } + m->m_data += max_linkhdr; + mhip = mtod(m, struct ip *); + bcopy((char *)ip, (char *)mhip, sizeof(*ip)); + if (hlen > sizeof (struct ip)) { + mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); + IP_HL_A(mhip, mhlen >> 2); + } + m->m_len = mhlen; + mhip->ip_off = ((off - hlen) >> 3) + ip_off; + if (off + len >= ip_len) + len = ip_len - off; + else + mhip->ip_off |= IP_MF; + mhip->ip_len = htons((u_short)(len + mhlen)); + m->m_next = m_copy(m0, off, len); + if (m->m_next == 0) { + error = ENOBUFS; /* ??? */ + goto sendorfree; + } + m->m_pkthdr.len = mhlen + len; + m->m_pkthdr.rcvif = NULL; + mhip->ip_off = htons((u_short)mhip->ip_off); + mhip->ip_sum = 0; + mhip->ip_sum = in_cksum(m, mhlen); + *mnext = m; + mnext = &m->m_act; + } + /* + * Update first fragment by trimming what's been copied out + * and updating header, then send each fragment (in order). + */ + m_adj(m0, hlen + firstlen - ip_len); + ip->ip_len = htons((u_short)(hlen + firstlen)); + ip->ip_off = htons((u_short)IP_MF); + ip->ip_sum = 0; + ip->ip_sum = in_cksum(m0, hlen); +sendorfree: + for (m = m0; m; m = m0) { + m0 = m->m_act; + m->m_act = 0; + if (error == 0) { + error = (*ifp->if_output)(ifp, m, dst, rt); + } else { + FREE_MB_T(m); + } + } + } +done: + if (!error) + softc->ipf_frouteok[0]++; + else + softc->ipf_frouteok[1]++; + +# if __NetBSD_Version__ >= 499001100 + rtcache_free(ro); +# else + if (rt) { + RTFREE(rt); + } +# endif + return error; +bad: + if (error == EMSGSIZE) { + sifp = fin->fin_ifp; + code = fin->fin_icode; + fin->fin_icode = ICMP_UNREACH_NEEDFRAG; + fin->fin_ifp = ifp; + (void) ipf_send_icmp_err(ICMP_UNREACH, fin, 1); + fin->fin_ifp = sifp; + fin->fin_icode = code; + } + FREE_MB_T(m); + goto done; +#endif /* INET */ +} + + +#if defined(USE_INET6) +/* + * This is the IPv6 specific fastroute code. It doesn't clean up the mbuf's + * or ensure that it is an IPv6 packet that is being forwarded, those are + * expected to be done by the called (ipf_fastroute). + */ +static int +ipf_fastroute6(m0, mpp, fin, fdp) + struct mbuf *m0, **mpp; + fr_info_t *fin; + frdest_t *fdp; +{ +# if __NetBSD_Version__ >= 499001100 + struct route ip6route; + const struct sockaddr *dst; + union { + struct sockaddr dst; + struct sockaddr_in6 dst6; + } u; + struct route *ro; +# else + struct route_in6 ip6route; + struct sockaddr_in6 *dst6; + struct route_in6 *ro; +# endif + struct rtentry *rt; + struct ifnet *ifp; + frentry_t *fr; + u_long mtu; + int error; + + error = 0; + ro = &ip6route; + fr = fin->fin_fr; + + if (fdp != NULL) + ifp = fdp->fd_ptr; + else + ifp = fin->fin_ifp; + bzero(ro, sizeof(*ro)); +# if __NetBSD_Version__ >= 499001100 + if (fdp != NULL && IP6_NOTZERO(&fdp->fd_ip6)) + sockaddr_in6_init(&u.dst6, &fdp->fd_ip6.in6, 0, 0, 0); + else + sockaddr_in6_init(&u.dst6, &fin->fin_fi.fi_dst.in6, 0, 0, 0); + dst = &u.dst; + rtcache_setdst(ro, dst); + + rt = rtcache_init(ro); + if ((ifp == NULL) && (rt != NULL)) + ifp = rt->rt_ifp; +# else + dst6 = (struct sockaddr_in6 *)&ro->ro_dst; + dst6->sin6_family = AF_INET6; + dst6->sin6_len = sizeof(struct sockaddr_in6); + dst6->sin6_addr = fin->fin_fi.fi_dst.in6; + + if (fdp != NULL) { + if (IP6_NOTZERO(&fdp->fd_ip6)) + dst6->sin6_addr = fdp->fd_ip6.in6; + } + + rtalloc((struct route *)ro); + + if ((ifp == NULL) && (ro->ro_rt != NULL)) + ifp = ro->ro_rt->rt_ifp; + rt = ro->ro_rt; +# endif + if ((rt == NULL) || (ifp == NULL)) { + + error = EHOSTUNREACH; + goto bad; + } + + /* KAME */ +# if __NetBSD_Version__ >= 499001100 + if (IN6_IS_ADDR_LINKLOCAL(&u.dst6.sin6_addr)) + u.dst6.sin6_addr.s6_addr16[1] = htons(ifp->if_index); +# else + if (IN6_IS_ADDR_LINKLOCAL(&dst6->sin6_addr)) + dst6->sin6_addr.s6_addr16[1] = htons(ifp->if_index); +# endif + + { +# if (__NetBSD_Version__ >= 106010000) + struct in6_ifextra *ife; +# endif + if (rt->rt_flags & RTF_GATEWAY) +# if __NetBSD_Version__ >= 499001100 + dst = rt->rt_gateway; +# else + dst6 = (struct sockaddr_in6 *)rt->rt_gateway; +# endif + rt->rt_use++; + + /* Determine path MTU. */ +# if (__NetBSD_Version__ <= 106009999) + mtu = nd_ifinfo[ifp->if_index].linkmtu; +# else + ife = (struct in6_ifextra *)(ifp)->if_afdata[AF_INET6]; +# ifdef IN6_LINKMTU + mtu = IN6_LINKMTU(ifp); +# else + mtu = ife->nd_ifinfo[ifp->if_index].linkmtu; +# endif +# endif + if ((error == 0) && (m0->m_pkthdr.len <= mtu)) { +# if __NetBSD_Version__ >= 499001100 + error = nd6_output(ifp, ifp, *mpp, satocsin6(dst), rt); +# else + error = nd6_output(ifp, ifp, *mpp, dst6, rt); +# endif + } else { + error = EMSGSIZE; + } + } +bad: +# if __NetBSD_Version__ >= 499001100 + rtcache_free(ro); +# else + if (ro->ro_rt != NULL) { + RTFREE(((struct route *)ro)->ro_rt); + } +# endif + return error; +} +#endif /* INET6 */ + + +int +ipf_verifysrc(fin) + fr_info_t *fin; +{ +#if __NetBSD_Version__ >= 499001100 + union { + struct sockaddr dst; + struct sockaddr_in dst4; + } u; + struct rtentry *rt; +#else + struct sockaddr_in *dst; +#endif + struct route iproute; + int rc; + +#if __NetBSD_Version__ >= 499001100 + sockaddr_in_init(&u.dst4, &fin->fin_src, 0); + rtcache_setdst(&iproute, &u.dst); + rt = rtcache_init(&iproute); + if (rt == NULL) + rc = 0; + else + rc = (fin->fin_ifp == rt->rt_ifp); + rtcache_free(&iproute); +#else + dst = (struct sockaddr_in *)&iproute.ro_dst; + dst->sin_len = sizeof(*dst); + dst->sin_family = AF_INET; + dst->sin_addr = fin->fin_src; + rtalloc(&iproute); + if (iproute.ro_rt == NULL) + return 0; + rc = (fin->fin_ifp == iproute.ro_rt->rt_ifp); + RTFREE(iproute.ro_rt); +#endif + return rc; +} + + +/* + * return the first IP Address associated with an interface + */ +int +ipf_ifpaddr(softc, v, atype, ifptr, inp, inpmask) + ipf_main_softc_t *softc; + int v, atype; + void *ifptr; + i6addr_t *inp, *inpmask; +{ +#ifdef USE_INET6 + struct in6_addr *inp6 = NULL; +#endif + struct sockaddr *sock, *mask; + struct sockaddr_in *sin; + struct ifaddr *ifa; + struct ifnet *ifp; + + if ((ifptr == NULL) || (ifptr == (void *)-1)) + return -1; + + ifp = ifptr; + mask = NULL; + + if (v == 4) + inp->in4.s_addr = 0; +#ifdef USE_INET6 + else if (v == 6) + bzero((char *)inp, sizeof(*inp)); +#endif + + ifa = ifp->if_addrlist.tqh_first; + sock = ifa->ifa_addr; + while (sock != NULL && ifa != NULL) { + sin = (struct sockaddr_in *)sock; + if ((v == 4) && (sin->sin_family == AF_INET)) + break; +#ifdef USE_INET6 + if ((v == 6) && (sin->sin_family == AF_INET6)) { + inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr; + if (!IN6_IS_ADDR_LINKLOCAL(inp6) && + !IN6_IS_ADDR_LOOPBACK(inp6)) + break; + } +#endif + ifa = ifa->ifa_list.tqe_next; + if (ifa != NULL) + sock = ifa->ifa_addr; + } + if (ifa == NULL || sock == NULL) + return -1; + + mask = ifa->ifa_netmask; + if (atype == FRI_BROADCAST) + sock = ifa->ifa_broadaddr; + else if (atype == FRI_PEERADDR) + sock = ifa->ifa_dstaddr; + +#ifdef USE_INET6 + if (v == 6) + return ipf_ifpfillv6addr(atype, (struct sockaddr_in6 *)sock, + (struct sockaddr_in6 *)mask, + inp, inpmask); +#endif + return ipf_ifpfillv4addr(atype, (struct sockaddr_in *)sock, + (struct sockaddr_in *)mask, + &inp->in4, &inpmask->in4); +} + + +u_32_t +ipf_newisn(fin) + fr_info_t *fin; +{ +#if __NetBSD_Version__ >= 105190000 /* 1.5T */ + size_t asz; + + if (fin->fin_v == 4) + asz = sizeof(struct in_addr); + else if (fin->fin_v == 6) + asz = sizeof(fin->fin_src); + else /* XXX: no way to return error */ + return 0; + return tcp_new_iss1((void *)&fin->fin_src, (void *)&fin->fin_dst, + fin->fin_sport, fin->fin_dport, asz, 0); +#else + static int iss_seq_off = 0; + u_char hash[16]; + u_32_t newiss; + MD5_CTX ctx; + + /* + * Compute the base value of the ISS. It is a hash + * of (saddr, sport, daddr, dport, secret). + */ + MD5Init(&ctx); + + MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, + sizeof(fin->fin_fi.fi_src)); + MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, + sizeof(fin->fin_fi.fi_dst)); + MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); + + MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); + + MD5Final(hash, &ctx); + + memcpy(&newiss, hash, sizeof(newiss)); + + /* + * Now increment our "timer", and add it in to + * the computed value. + * + * XXX Use `addin'? + * XXX TCP_ISSINCR too large to use? + */ + iss_seq_off += 0x00010000; + newiss += iss_seq_off; + return newiss; +#endif +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nextipid */ +/* Returns: int - 0 == success, -1 == error (packet should be droppped) */ +/* Parameters: fin(I) - pointer to packet information */ +/* */ +/* Returns the next IPv4 ID to use for this packet. */ +/* ------------------------------------------------------------------------ */ +u_short +ipf_nextipid(fin) + fr_info_t *fin; +{ +#ifdef USE_MUTEXES + ipf_main_softc_t *softc = fin->fin_main_soft; +#endif + u_short id; + + MUTEX_ENTER(&softc->ipf_rw); + id = ipid++; + MUTEX_EXIT(&softc->ipf_rw); + + return id; +} + + +INLINE int +ipf_checkv4sum(fin) + fr_info_t *fin; +{ +#ifdef M_CSUM_TCP_UDP_BAD + int manual, pflag, cflags, active; + mb_t *m; + + if ((fin->fin_flx & FI_NOCKSUM) != 0) + return 0; + + if ((fin->fin_flx & FI_SHORT) != 0) + return 1; + + if (fin->fin_cksum != FI_CK_NEEDED) + return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; + + manual = 0; + m = fin->fin_m; + if (m == NULL) { + manual = 1; + goto skipauto; + } + + switch (fin->fin_p) + { + case IPPROTO_UDP : + pflag = M_CSUM_UDPv4; + break; + case IPPROTO_TCP : + pflag = M_CSUM_TCPv4; + break; + default : + pflag = 0; + manual = 1; + break; + } + + active = ((struct ifnet *)fin->fin_ifp)->if_csum_flags_rx & pflag; + active |= M_CSUM_TCP_UDP_BAD | M_CSUM_DATA; + cflags = m->m_pkthdr.csum_flags & active; + + if (pflag != 0) { + if (cflags == (pflag | M_CSUM_TCP_UDP_BAD)) { + fin->fin_flx |= FI_BAD; + fin->fin_cksum = FI_CK_BAD; + } else if (cflags == (pflag | M_CSUM_DATA)) { + if ((m->m_pkthdr.csum_data ^ 0xffff) != 0) { + fin->fin_flx |= FI_BAD; + fin->fin_cksum = FI_CK_BAD; + } else { + fin->fin_cksum = FI_CK_SUMOK; + } + } else if (cflags == pflag) { + fin->fin_cksum = FI_CK_SUMOK; + } else { + manual = 1; + } + } +skipauto: + if (manual != 0) { + if (ipf_checkl4sum(fin) == -1) { + fin->fin_flx |= FI_BAD; + return -1; + } + } +#else + if (ipf_checkl4sum(fin) == -1) { + fin->fin_flx |= FI_BAD; + return -1; + } +#endif + return 0; +} + + +#ifdef USE_INET6 +INLINE int +ipf_checkv6sum(fin) + fr_info_t *fin; +{ +# ifdef M_CSUM_TCP_UDP_BAD + int manual, pflag, cflags, active; + mb_t *m; + + if ((fin->fin_flx & FI_NOCKSUM) != 0) + return 0; + + if ((fin->fin_flx & FI_SHORT) != 0) + return 1; + + if (fin->fin_cksum != FI_CK_SUMOK) + return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; + + + manual = 0; + m = fin->fin_m; + + switch (fin->fin_p) + { + case IPPROTO_UDP : + pflag = M_CSUM_UDPv6; + break; + case IPPROTO_TCP : + pflag = M_CSUM_TCPv6; + break; + default : + pflag = 0; + manual = 1; + break; + } + + active = ((struct ifnet *)fin->fin_ifp)->if_csum_flags_rx & pflag; + active |= M_CSUM_TCP_UDP_BAD | M_CSUM_DATA; + cflags = m->m_pkthdr.csum_flags & active; + + if (pflag != 0) { + if (cflags == (pflag | M_CSUM_TCP_UDP_BAD)) { + fin->fin_flx |= FI_BAD; + } else if (cflags == (pflag | M_CSUM_DATA)) { + if ((m->m_pkthdr.csum_data ^ 0xffff) != 0) + fin->fin_flx |= FI_BAD; + } else if (cflags == pflag) { + ; + } else { + manual = 1; + } + } + if (manual != 0) { + if (ipf_checkl4sum(fin) == -1) { + fin->fin_flx |= FI_BAD; + return -1; + } + } +# else + if (ipf_checkl4sum(fin) == -1) { + fin->fin_flx |= FI_BAD; + return -1; + } +# endif + return 0; +} +#endif /* USE_INET6 */ + + +size_t +mbufchainlen(m0) + struct mbuf *m0; +{ + size_t len; + + if ((m0->m_flags & M_PKTHDR) != 0) { + len = m0->m_pkthdr.len; + } else { + struct mbuf *m; + + for (m = m0, len = 0; m != NULL; m = m->m_next) + len += m->m_len; + } + return len; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pullup */ +/* Returns: NULL == pullup failed, else pointer to protocol header */ +/* Parameters: xmin(I)- pointer to buffer where data packet starts */ +/* fin(I) - pointer to packet information */ +/* len(I) - number of bytes to pullup */ +/* */ +/* Attempt to move at least len bytes (from the start of the buffer) into a */ +/* single buffer for ease of access. Operating system native functions are */ +/* used to manage buffers - if necessary. If the entire packet ends up in */ +/* a single buffer, set the FI_COALESCE flag even though ipf_coalesce() has */ +/* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */ +/* and ONLY if the pullup succeeds. */ +/* */ +/* We assume that 'xmin' is a pointer to a buffer that is part of the chain */ +/* of buffers that starts at *fin->fin_mp. */ +/* ------------------------------------------------------------------------ */ +void * +ipf_pullup(xmin, fin, len) + mb_t *xmin; + fr_info_t *fin; + int len; +{ + int dpoff, ipoff; + mb_t *m = xmin; + char *ip; + + if (m == NULL) + return NULL; + + ip = (char *)fin->fin_ip; + if ((fin->fin_flx & FI_COALESCE) != 0) + return ip; + + ipoff = fin->fin_ipoff; + if (fin->fin_dp != NULL) + dpoff = (char *)fin->fin_dp - (char *)ip; + else + dpoff = 0; + + if (M_LEN(m) < len) { + mb_t *n = *fin->fin_mp; + /* + * Assume that M_PKTHDR is set and just work with what is left + * rather than check.. + * Should not make any real difference, anyway. + */ + if (m != n) { + /* + * Record the mbuf that points to the mbuf that we're + * about to go to work on so that we can update the + * m_next appropriately later. + */ + for (; n->m_next != m; n = n->m_next) + ; + } else { + n = NULL; + } + +#ifdef MHLEN + if (len > MHLEN) +#else + if (len > MLEN) +#endif + { +#ifdef HAVE_M_PULLDOWN + if (m_pulldown(m, 0, len, NULL) == NULL) + m = NULL; +#else + FREE_MB_T(*fin->fin_mp); + m = NULL; + n = NULL; +#endif + } else + { + m = m_pullup(m, len); + } + if (n != NULL) + n->m_next = m; + if (m == NULL) { + /* + * When n is non-NULL, it indicates that m pointed to + * a sub-chain (tail) of the mbuf and that the head + * of this chain has not yet been free'd. + */ + if (n != NULL) { + FREE_MB_T(*fin->fin_mp); + } + + *fin->fin_mp = NULL; + fin->fin_m = NULL; + return NULL; + } + + if (n == NULL) + *fin->fin_mp = m; + + while (M_LEN(m) == 0) { + m = m->m_next; + } + fin->fin_m = m; + ip = MTOD(m, char *) + ipoff; + + fin->fin_ip = (ip_t *)ip; + if (fin->fin_dp != NULL) + fin->fin_dp = (char *)fin->fin_ip + dpoff; + if (fin->fin_fraghdr != NULL) + fin->fin_fraghdr = (char *)ip + + ((char *)fin->fin_fraghdr - + (char *)fin->fin_ip); + } + + if (len == fin->fin_plen) + fin->fin_flx |= FI_COALESCE; + return ip; +} + + +int +ipf_inject(fin, m) + fr_info_t *fin; + mb_t *m; +{ + int error; + + if (fin->fin_out == 0) { + struct ifqueue *ifq; + + ifq = &ipintrq; + + if (IF_QFULL(ifq)) { + IF_DROP(ifq); + FREE_MB_T(m); + error = ENOBUFS; + } else { + IF_ENQUEUE(ifq, m); + error = 0; + } + } else { + error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL); + } + + return error; +} + + +u_32_t +ipf_random() +{ + int number; + +#ifdef _CPRNG_H + number = cprng_fast32(); +#else + number = arc4random(); +#endif + return number; +} + + +/* + * routines below for saving IP headers to buffer + */ +static int ipfopen(dev, flags +#if (NetBSD >= 199511) +, devtype, p) + int devtype; + PROC_T *p; +#else +) +#endif + dev_t dev; + int flags; +{ + u_int unit = GET_MINOR(dev); + int error; + + if (IPL_LOGMAX < unit) { + error = ENXIO; + } else { + switch (unit) + { + case IPL_LOGIPF : + case IPL_LOGNAT : + case IPL_LOGSTATE : + case IPL_LOGAUTH : + case IPL_LOGLOOKUP : + case IPL_LOGSYNC : +#ifdef IPFILTER_SCAN + case IPL_LOGSCAN : +#endif + error = 0; + break; + default : + error = ENXIO; + break; + } + } + return error; +} + + +static int ipfclose(dev, flags +#if (NetBSD >= 199511) +, devtype, p) + int devtype; + PROC_T *p; +#else +) +#endif + dev_t dev; + int flags; +{ + u_int unit = GET_MINOR(dev); + + if (IPL_LOGMAX < unit) + unit = ENXIO; + else + unit = 0; + return unit; +} + +/* + * ipfread/ipflog + * both of these must operate with at least splnet() lest they be + * called during packet processing and cause an inconsistancy to appear in + * the filter lists. + */ +static int ipfread(dev, uio, ioflag) + int ioflag; + dev_t dev; + register struct uio *uio; +{ + + if (ipfmain.ipf_running < 1) { + ipfmain.ipf_interror = 130006; + return EIO; + } + + if (GET_MINOR(dev) == IPL_LOGSYNC) + return ipf_sync_read(&ipfmain, uio); + +#ifdef IPFILTER_LOG + return ipf_log_read(&ipfmain, GET_MINOR(dev), uio); +#else + ipfmain.ipf_interror = 130007; + return ENXIO; +#endif +} + + +/* + * ipfwrite + * both of these must operate with at least splnet() lest they be + * called during packet processing and cause an inconsistancy to appear in + * the filter lists. + */ +static int ipfwrite(dev, uio, ioflag) + int ioflag; + dev_t dev; + register struct uio *uio; +{ + + if (ipfmain.ipf_running < 1) { + ipfmain.ipf_interror = 130008; + return EIO; + } + + if (GET_MINOR(dev) == IPL_LOGSYNC) + return ipf_sync_write(&ipfmain, uio); + ipfmain.ipf_interror = 130009; + return ENXIO; +} + + +static int ipfpoll(dev, events, p) + dev_t dev; + int events; + PROC_T *p; +{ + u_int unit = GET_MINOR(dev); + int revents = 0; + + if (IPL_LOGMAX < unit) { + ipfmain.ipf_interror = 130010; + return ENXIO; + } + + switch (unit) + { + case IPL_LOGIPF : + case IPL_LOGNAT : + case IPL_LOGSTATE : +#ifdef IPFILTER_LOG + if ((events & (POLLIN | POLLRDNORM)) && + ipf_log_canread(&ipfmain, unit)) + revents |= events & (POLLIN | POLLRDNORM); +#endif + break; + case IPL_LOGAUTH : + if ((events & (POLLIN | POLLRDNORM)) && + ipf_auth_waiting(&ipfmain)) + revents |= events & (POLLIN | POLLRDNORM); + break; + case IPL_LOGSYNC : + if ((events & (POLLIN | POLLRDNORM)) && + ipf_sync_canread(&ipfmain)) + revents |= events & (POLLIN | POLLRDNORM); + if ((events & (POLLOUT | POLLWRNORM)) && + ipf_sync_canwrite(&ipfmain)) + revents |= events & (POLLOUT | POLLWRNORM); + break; + case IPL_LOGSCAN : + case IPL_LOGLOOKUP : + default : + break; + } + + if ((revents == 0) && (((events & (POLLIN|POLLRDNORM)) != 0))) + selrecord(p, &ipfmain.ipf_selwait[unit]); + return revents; +} + +u_int +ipf_pcksum(fin, hlen, sum) + fr_info_t *fin; + int hlen; + u_int sum; +{ + struct mbuf *m; + u_int sum2; + int off; + + m = fin->fin_m; + off = (char *)fin->fin_dp - (char *)fin->fin_ip; + m->m_data += hlen; + m->m_len -= hlen; + sum2 = in_cksum(fin->fin_m, fin->fin_plen - off); + m->m_len += hlen; + m->m_data -= hlen; + + /* + * Both sum and sum2 are partial sums, so combine them together. + */ + sum += ~sum2 & 0xffff; + while (sum > 0xffff) + sum = (sum & 0xffff) + (sum >> 16); + sum2 = ~sum & 0xffff; + return sum2; +} diff --git a/ip_fil_openbsd.c b/ip_fil_openbsd.c new file mode 100644 index 0000000000000..52a402e9820ee --- /dev/null +++ b/ip_fil_openbsd.c @@ -0,0 +1,1306 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ +#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$"; +#endif + +#if defined(KERNEL) || defined(_KERNEL) +# undef KERNEL +# undef _KERNEL +# define KERNEL 1 +# define _KERNEL 1 +#endif +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/types.h> +#include <sys/file.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/systm.h> +#include <sys/dirent.h> +#include <sys/mbuf.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/timeout.h> + +#include <net/if.h> +#include <net/route.h> +#include <netinet/in.h> +#include <netinet/in_var.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/ip_var.h> +#include <netinet/tcp.h> +#include <netinet/tcp_timer.h> +#include <netinet/tcp_var.h> +#include <netinet/udp.h> +#include <netinet/tcpip.h> +#include <netinet/ip_icmp.h> +#include "netinet/ip_compat.h" +#ifdef USE_INET6 +# include <netinet/icmp6.h> +#endif +#include "netinet/ip_fil.h" +#include "netinet/ip_nat.h" +#include "netinet/ip_frag.h" +#include "netinet/ip_state.h" +#include "netinet/ip_proxy.h" +#include "netinet/ip_auth.h" +#include "netinet/ip_sync.h" +#include "netinet/ip_lookup.h" +#include "netinet/ip_dstlist.h" +#ifdef IPFILTER_SCAN +#include "netinet/ip_scan.h" +#endif +#include "netinet/ip_pool.h" +#include <sys/kernel.h> +extern int ip_optcopy __P((struct ip *, struct ip *)); + +#ifdef IPFILTER_M_IPFILTER +MALLOC_DEFINE(M_IPFILTER, "IP Filter", "IP Filter packet filter data structures"); +#endif + + +extern struct protosw inetsw[]; +extern int ipforwarding; +#ifdef USE_INET6 +extern int ip6_getpmtu(struct route_in6 *, struct route_in6 *, + struct ifnet *, struct in6_addr *, u_long *); +#endif + +static int (*ipf_savep) __P((ip_t *, int, void *, int, struct mbuf **)); +static int ipf_send_ip __P((fr_info_t *, mb_t *)); +#ifdef USE_INET6 +static int ipf_fastroute6 __P((struct mbuf *, struct mbuf **, + fr_info_t *, frdest_t *)); +#endif + +#include <sys/timeout.h> +struct timeout ipf_slowtimer_ch; + +#include <sys/conf.h> +/* + * We provide the ipf_checkp name just to minimize changes later. + */ +int (*ipf_checkp) __P((ip_t *ip, int hlen, void *ifp, int out, mb_t **mp)); + + +#if defined(IPFILTER_LKM) +int +iplidentify(s) + char *s; +{ + if (strcmp(s, "ipl") == 0) + return 1; + return 0; +} +#endif /* IPFILTER_LKM */ + + +int +ipfattach() +{ + int s; + + SPL_NET(s); + if ((ipf_running > 0) || (ipf_checkp == ipf_check)) { + printf("IP Filter: already initialized\n"); + SPL_X(s); + return EBUSY; + } + + if (ipf_initialise() < 0) { + SPL_X(s); + return EIO; + } + + bzero((char *)ipf_cache, sizeof(ipf_cache)); + ipf_savep = ipf_checkp; + ipf_checkp = ipf_check; + + if (ipf_control_forwarding & 1) + ipforwarding = 1; + + SPL_X(s); + timeout_set(&ipf_slowtimer_ch, ipf_slowtimer, &ipfmain); + timeout_add(&ipf_slowtimer_ch, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT); + return 0; +} + + +/* + * Disable the filter by removing the hooks from the IP input/output + * stream. + */ +int +ipfdetach() +{ + int s; + + SPL_NET(s); + + timeout_del(&ipf_slowtimer_ch); + + ipf_deinitialise(); + + ipf_checkp = ipf_savep; + (void) frflush(IPL_LOGIPF, FR_INQUE|FR_OUTQUE|FR_INACTIVE); + (void) frflush(IPL_LOGIPF, FR_INQUE|FR_OUTQUE); + + if (ipf_control_forwarding & 2) + ipforwarding = 0; + + SPL_X(s); + return 0; +} + + +/* + * Filter ioctl interface. + */ +int +ipfioctl(dev, cmd, data, mode , p) + struct proc *p; + dev_t dev; + u_long cmd; + caddr_t data; + int mode; +{ + int error = 0, unit = 0; + SPL_INT(s); + + if ((securelevel >= 2) && (mode & FWRITE)) + return EPERM; + + unit = GET_MINOR(dev); + if ((IPL_LOGMAX < unit) || (unit < 0)) + return ENXIO; + + if (ipf_running <= 0) { + if (unit != IPL_LOGIPF && cmd != SIOCIPFINTERROR) + return EIO; + if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET && + cmd != SIOCIPFSET && cmd != SIOCFRENB && + cmd != SIOCGETFS && cmd != SIOCGETFF && + cmd != SIOCIPFINTERROR) + return EIO; + } + + SPL_NET(s); + + error = ipf_ioctlswitch(unit, data, cmd, mode, p->p_cred->p_ruid, p); + if (error != -1) { + SPL_X(s); + return error; + } + + SPL_X(s); + return error; +} + + +/* + * ipf_send_reset - this could conceivably be a call to tcp_respond(), but that + * requires a large amount of setting up and isn't any more efficient. + */ +int ipf_send_reset(fin) + fr_info_t *fin; +{ + struct tcphdr *tcp, *tcp2; + int tlen = 0, hlen; + struct mbuf *m; +#ifdef USE_INET6 + ip6_t *ip6; +#endif + ip_t *ip; + + tcp = fin->fin_dp; + if (tcp->th_flags & TH_RST) + return -1; /* feedback loop */ + + if (ipf_checkl4sum(fin) == -1) + return -1; + + tlen = fin->fin_dlen - (TCP_OFF(tcp) << 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 + hlen = sizeof(ip_t); +#endif +#ifdef MGETHDR + MGETHDR(m, M_DONTWAIT, MT_HEADER); +#else + MGET(m, M_DONTWAIT, MT_HEADER); +#endif + if (m == NULL) + return -1; + if (sizeof(*tcp2) + hlen > MHLEN) { + MCLGET(m, M_DONTWAIT); + if ((m->m_flags & M_EXT) == 0) { + FREE_MB_T(m); + return -1; + } + } + + m->m_len = sizeof(*tcp2) + hlen; + m->m_data += max_linkhdr; + m->m_pkthdr.len = m->m_len; + m->m_pkthdr.rcvif = (struct ifnet *)0; + ip = mtod(m, struct ip *); + bzero((char *)ip, hlen); +#ifdef USE_INET6 + ip6 = (ip6_t *)ip; +#endif + tcp2 = (struct tcphdr *)((char *)ip + hlen); + tcp2->th_sport = tcp->th_dport; + tcp2->th_dport = tcp->th_sport; + + if (tcp->th_flags & TH_ACK) { + tcp2->th_seq = tcp->th_ack; + tcp2->th_flags = TH_RST; + tcp2->th_ack = 0; + } else { + tcp2->th_seq = 0; + 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; + } + TCP_X2_A(tcp2, 0); + TCP_OFF_A(tcp2, sizeof(*tcp2) >> 2); + tcp2->th_win = tcp->th_win; + tcp2->th_sum = 0; + tcp2->th_urp = 0; + +#ifdef USE_INET6 + if (fin->fin_v == 6) { + ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; + ip6->ip6_plen = htons(sizeof(struct tcphdr)); + ip6->ip6_nxt = IPPROTO_TCP; + ip6->ip6_hlim = 0; + ip6->ip6_src = fin->fin_dst6; + ip6->ip6_dst = fin->fin_src6; + tcp2->th_sum = in6_cksum(m, IPPROTO_TCP, + sizeof(*ip6), sizeof(*tcp2)); + return ipf_send_ip(fin, m); + } +#endif + ip->ip_p = IPPROTO_TCP; + ip->ip_len = htons(sizeof(struct tcphdr)); + ip->ip_src.s_addr = fin->fin_daddr; + ip->ip_dst.s_addr = fin->fin_saddr; + tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2)); + ip->ip_len = hlen + sizeof(*tcp2); + return ipf_send_ip(fin, m); +} + + +/* + * On entry, ip_len is in host byte order. + */ +static int +ipf_send_ip(fin, m) + fr_info_t *fin; + mb_t *m; +{ + fr_info_t fnew; + ip_t *ip, *oip; + int hlen; + + ip = mtod(m, ip_t *); + bzero((char *)&fnew, sizeof(fnew)); + fnew.fin_main_soft = fin->fin_main_soft; + + IP_V_A(ip, fin->fin_v); + switch (fin->fin_v) + { + case 4 : + oip = fin->fin_ip; + hlen = sizeof(*oip); + fnew.fin_v = 4; + fnew.fin_p = ip->ip_p; + fnew.fin_plen = ip->ip_len + hlen; + IP_HL_A(ip, sizeof(*oip) >> 2); + ip->ip_tos = oip->ip_tos; + ip->ip_len = ntohs(ip->ip_len); + ip->ip_id = ipf_nextipid(fin); + ip->ip_off = htons(ip_mtudisc ? IP_DF : 0); + ip->ip_ttl = ip_defttl; + ip->ip_sum = 0; + break; +#ifdef USE_INET6 + case 6 : + { + ip6_t *ip6 = (ip6_t *)ip; + + ip6->ip6_vfc = 0x60; + ip6->ip6_hlim = IPDEFTTL; + + fnew.fin_v = 6; + fnew.fin_p = ip6->ip6_nxt; + fnew.fin_plen = ntohs(ip6->ip6_plen) + hlen; + hlen = sizeof(*ip6); + break; + } +#endif + default : + return EINVAL; + } +#ifdef IPSEC + m->m_pkthdr.rcvif = NULL; +#endif + + fnew.fin_ifp = fin->fin_ifp; + fnew.fin_flx = FI_NOCKSUM; + fnew.fin_m = m; + fnew.fin_ip = ip; + fnew.fin_mp = &m; + fnew.fin_hlen = hlen; + fnew.fin_dp = (char *)ip + hlen; + (void) ipf_makefrip(hlen, ip, &fnew); + + return ipf_fastroute(m, &m, &fnew, NULL); +} + + +int +ipf_send_icmp_err(type, fin, dst) + int type; + fr_info_t *fin; + int dst; +{ + int err, hlen, xtra, iclen, ohlen, avail, code; + struct in_addr dst4; + struct icmp *icmp; + struct mbuf *m; + i6addr_t dst6; + void *ifp; +#ifdef USE_INET6 + ip6_t *ip6; +#endif + ip_t *ip, *ip2; + + if ((type < 0) || (type > ICMP_MAXTYPE)) + return -1; + + code = fin->fin_icode; +#ifdef USE_INET6 + if ((code < 0) || (code > sizeof(icmptoicmp6unreach)/sizeof(int))) + return -1; +#endif + + if (ipf_checkl4sum(fin) == -1) + return -1; +#ifdef MGETHDR + MGETHDR(m, M_DONTWAIT, MT_HEADER); +#else + MGET(m, M_DONTWAIT, MT_HEADER); +#endif + if (m == NULL) + return -1; + avail = MHLEN; + + xtra = 0; + hlen = 0; + ohlen = 0; + ifp = fin->fin_ifp; + if (fin->fin_v == 4) { + if ((fin->fin_p == IPPROTO_ICMP) && !(fin->fin_flx & FI_SHORT)) + switch (ntohs(fin->fin_data[0]) >> 8) + { + case ICMP_ECHO : + case ICMP_TSTAMP : + case ICMP_IREQ : + case ICMP_MASKREQ : + break; + default : + FREE_MB_T(m); + return 0; + } + + if (dst == 0) { + if (ipf_ifpaddr(&ipfmain, 4, FRI_NORMAL, ifp, + &dst6, NULL) == -1) { + FREE_MB_T(m); + return -1; + } + dst4 = dst6.in4; + } else + dst4.s_addr = fin->fin_daddr; + + hlen = sizeof(ip_t); + ohlen = fin->fin_hlen; + iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen; + if (fin->fin_hlen < fin->fin_plen) + xtra = MIN(fin->fin_dlen, 8); + else + xtra = 0; + } + +#ifdef USE_INET6 + else if (fin->fin_v == 6) { + hlen = sizeof(ip6_t); + ohlen = sizeof(ip6_t); + iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen; + type = icmptoicmp6types[type]; + if (type == ICMP6_DST_UNREACH) + code = icmptoicmp6unreach[code]; + + if (iclen + max_linkhdr + fin->fin_plen > avail) { + MCLGET(m, M_DONTWAIT); + if ((m->m_flags & M_EXT) == 0) { + FREE_MB_T(m); + return -1; + } + avail = MCLBYTES; + } + xtra = MIN(fin->fin_plen, avail - iclen - max_linkhdr); + xtra = MIN(xtra, IPV6_MMTU - iclen); + if (dst == 0) { + if (ipf_ifpaddr(&ipfmain, 6, FRI_NORMAL, ifp, + &dst6, NULL) == -1) { + FREE_MB_T(m); + return -1; + } + } else + dst6 = fin->fin_dst6; + } +#endif + else { + FREE_MB_T(m); + return -1; + } + + avail -= (max_linkhdr + iclen); + if (avail < 0) { + FREE_MB_T(m); + return -1; + } + if (xtra > avail) + xtra = avail; + iclen += xtra; + m->m_data += max_linkhdr; + m->m_pkthdr.rcvif = (struct ifnet *)0; + m->m_pkthdr.len = iclen; + m->m_len = iclen; + ip = mtod(m, ip_t *); + icmp = (struct icmp *)((char *)ip + hlen); + ip2 = (ip_t *)&icmp->icmp_ip; + bzero((char *)ip, iclen); + + 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) { + if (fin->fin_mtu != 0) { + icmp->icmp_nextmtu = htons(fin->fin_mtu); + + } else if (ifp != NULL) { + icmp->icmp_nextmtu = htons(GETIFMTU_4(ifp)); + + } else { /* make up a number... */ + icmp->icmp_nextmtu = htons(fin->fin_plen - 20); + } + } +#endif + + bcopy((char *)fin->fin_ip, (char *)ip2, ohlen); + +#ifdef USE_INET6 + ip6 = (ip6_t *)ip; + if (fin->fin_v == 6) { + ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; + ip6->ip6_plen = htons(iclen - hlen); + ip6->ip6_nxt = IPPROTO_ICMPV6; + ip6->ip6_hlim = 0; + ip6->ip6_src = dst6; + ip6->ip6_dst = fin->fin_src6; + if (xtra > 0) + bcopy((char *)fin->fin_ip + ohlen, + (char *)&icmp->icmp_ip + ohlen, xtra); + icmp->icmp_cksum = in6_cksum(m, IPPROTO_ICMPV6, + sizeof(*ip6), iclen - hlen); + } else +#endif + { + ip->ip_p = IPPROTO_ICMP; + ip->ip_src.s_addr = dst4.s_addr; + ip->ip_dst.s_addr = fin->fin_saddr; + + if (xtra > 0) + bcopy((char *)fin->fin_ip + ohlen, + (char *)&icmp->icmp_ip + ohlen, xtra); + icmp->icmp_cksum = ipf_cksum((u_short *)icmp, + sizeof(*icmp) + 8); + ip->ip_len = iclen; + ip->ip_p = IPPROTO_ICMP; + } + err = ipf_send_ip(fin, m); + return err; +} + + +#if !defined(IPFILTER_LKM) +void iplinit __P((void)); + +void +iplinit() +{ + if (ipfattach() != 0) + printf("IP Filter failed to attach\n"); + else + ipf_running = 1; + ip_init(); +} +#endif /* ! IPFILTER_LKM */ + + +/* + * m0 - pointer to mbuf where the IP packet starts + * mpp - pointer to the mbuf pointer that is the start of the mbuf chain + */ +int +ipf_fastroute(m0, mpp, fin, fdp) + mb_t *m0, **mpp; + fr_info_t *fin; + frdest_t *fdp; +{ + register struct ip *ip, *mhip; + register struct mbuf *m = *mpp; + register struct route *ro; + int len, off, error = 0, hlen, code; + struct ifnet *ifp, *sifp; + struct sockaddr_in *dst; + u_short ip_off, ip_len; + struct route iproute; + frdest_t node; + frentry_t *fr; + +#ifdef USE_INET6 + if (fin->fin_v == 6) { + /* + * currently "to <if>" and "to <if>:ip#" are not supported + * for IPv6 + */ + error = ipf_fastroute6(m, mpp, fin, fdp); + if ((error != 0) && (*mpp != NULL)) { + FREE_MB_T(*mpp); + } + return error; + } +#endif + + hlen = fin->fin_hlen; + ip = mtod(m0, struct ip *); + + /* + * Route packet. + */ + ro = &iproute; + bzero((caddr_t)ro, sizeof (*ro)); + dst = (struct sockaddr_in *)&ro->ro_dst; + dst->sin_family = AF_INET; + dst->sin_addr = ip->ip_dst; + + fr = fin->fin_fr; + if ((fr != NULL) && !(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) && + (fdp->fd_type == FRD_DSTLIST)) { + if (ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node) == 0) + fdp = &node; + } + if (fdp != NULL) + ifp = fdp->fd_ptr; + else + ifp = fin->fin_ifp; + + if ((ifp == NULL) && (!fr || !(fr->fr_flags & FR_FASTROUTE))) { + error = -2; + goto bad; + } + + if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0)) + dst->sin_addr = fdp->fd_ip; + + dst->sin_len = sizeof(*dst); + rtalloc(ro); + + if ((ifp == NULL) && (ro->ro_rt != NULL)) + ifp = ro->ro_rt->rt_ifp; + + if ((ro->ro_rt == NULL) || (ifp == NULL)) { + if (in_localaddr(ip->ip_dst)) + error = EHOSTUNREACH; + else + error = ENETUNREACH; + goto bad; + } + if (ro->ro_rt->rt_flags & RTF_GATEWAY) + dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway; + if (ro->ro_rt) + ro->ro_rt->rt_use++; + + /* + * For input packets which are being "fastrouted", they won't + * go back through output filtering and miss their chance to get + * NAT'd and counted. Duplicated packets aren't considered to be + * part of the normal packet stream, so do not NAT them or pass + * them through stateful checking, etc. + */ + if ((fdp != &fr->fr_dif) && (fin->fin_out == 0)) { + sifp = fin->fin_ifp; + fin->fin_ifp = ifp; + fin->fin_out = 1; + (void) ipf_acctpkt(fin, NULL); + fin->fin_fr = NULL; + if (!fr || !(fr->fr_flags & FR_RETMASK)) { + u_32_t pass; + + (void) ipf_state_check(fin, &pass); + } + + switch (ipf_nat_checkout(fin, NULL)) + { + case 0 : + break; + case 1 : + ip->ip_sum = 0; + break; + case -1 : + error = -1; + goto bad; + break; + } + + fin->fin_ifp = sifp; + fin->fin_out = 0; + } else + ip->ip_sum = 0; + /* + * If small enough for interface, can just send directly. + */ + ip_len = ntohs(ip->ip_len); + if (ip_len <= ifp->if_mtu) { + if (!ip->ip_sum) + ip->ip_sum = in_cksum(m, hlen); + error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, + ro->ro_rt); + goto done; + } + /* + * Too large for interface; fragment if possible. + * Must be able to put at least 8 bytes per fragment. + */ + ip_off = ntohs(ip->ip_off); + if (ip_off & IP_DF) { + error = EMSGSIZE; + goto bad; + } + len = (ifp->if_mtu - hlen) &~ 7; + if (len < 8) { + error = EMSGSIZE; + goto bad; + } + + { + int mhlen, firstlen = len; + struct mbuf **mnext = &m->m_act; + + /* + * Loop through length of segment after first fragment, + * make new header and copy data of each part and link onto chain. + */ + m0 = m; + mhlen = sizeof (struct ip); + for (off = hlen + len; off < ip_len; off += len) { +#ifdef MGETHDR + MGETHDR(m, M_DONTWAIT, MT_HEADER); +#else + MGET(m, M_DONTWAIT, MT_HEADER); +#endif + if (m == 0) { + m = m0; + error = ENOBUFS; + goto bad; + } + m->m_data += max_linkhdr; + mhip = mtod(m, struct ip *); + bcopy((char *)ip, (char *)mhip, sizeof(*ip)); + if (hlen > sizeof (struct ip)) { + mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); + IP_HL_A(mhip, mhlen >> 2); + } + m->m_len = mhlen; + mhip->ip_off = ((off - hlen) >> 3) + ip_off; + if (off + len >= ip_len) + len = ip_len - off; + else + mhip->ip_off |= IP_MF; + mhip->ip_len = htons((u_short)(len + mhlen)); + m->m_next = m_copy(m0, off, len); + if (m->m_next == 0) { + error = ENOBUFS; /* ??? */ + goto sendorfree; + } + m->m_pkthdr.len = mhlen + len; + m->m_pkthdr.rcvif = NULL; + mhip->ip_off = htons((u_short)mhip->ip_off); + mhip->ip_sum = 0; + mhip->ip_sum = in_cksum(m, mhlen); + *mnext = m; + mnext = &m->m_act; + } + /* + * Update first fragment by trimming what's been copied out + * and updating header, then send each fragment (in order). + */ + m_adj(m0, hlen + firstlen - ip_len); + ip->ip_len = htons((u_short)(hlen + firstlen)); + ip->ip_off = htons((u_short)IP_MF); + ip->ip_sum = 0; + ip->ip_sum = in_cksum(m0, hlen); +sendorfree: + for (m = m0; m; m = m0) { + m0 = m->m_act; + m->m_act = 0; + if (error == 0) + error = (*ifp->if_output)(ifp, m, + (struct sockaddr *)dst, ro->ro_rt); + else + FREE_MB_T(m); + } + } +done: + if (!error) + ipf_frouteok[0]++; + else + ipf_frouteok[1]++; + + if (ro->ro_rt) { + RTFREE(ro->ro_rt); + } + return 0; +bad: + if (error == EMSGSIZE) { + sifp = fin->fin_ifp; + code = fin->fin_icode; + fin->fin_icode = ICMP_UNREACH_NEEDFRAG; + fin->fin_ifp = ifp; + (void) ipf_send_icmp_err(ICMP_UNREACH, fin, 1); + fin->fin_ifp = sifp; + fin->fin_icode = code; + } + FREE_MB_T(m); + goto done; +} + + +#if defined(USE_INET6) +/* + * This is the IPv6 specific fastroute code. It doesn't clean up the mbuf's + * or ensure that it is an IPv6 packet that is being forwarded, those are + * expected to be done by the called (ipf_fastroute). + */ +static int +ipf_fastroute6(m0, mpp, fin, fdp) + struct mbuf *m0, **mpp; + fr_info_t *fin; + frdest_t *fdp; +{ + struct route_in6 ip6route; + struct sockaddr_in6 *dst6; + struct route_in6 *ro; + struct ifnet *ifp; + frentry_t *fr; +#if defined(OpenBSD) && (OpenBSD >= 200211) + struct route_in6 *ro_pmtu = NULL; + struct in6_addr finaldst; + ip6_t *ip6; +#endif + u_long mtu; + int error; + + ro = &ip6route; + fr = fin->fin_fr; + bzero((caddr_t)ro, sizeof(*ro)); + dst6 = (struct sockaddr_in6 *)&ro->ro_dst; + dst6->sin6_family = AF_INET6; + dst6->sin6_len = sizeof(struct sockaddr_in6); + dst6->sin6_addr = fin->fin_fi.fi_src.in6; + + if (fdp != NULL) + ifp = fdp->fd_ifp; + else + ifp = fin->fin_ifp; + + if ((fr != NULL) && (fin->fin_rev != 0)) { + if ((ifp != NULL) && (fdp == &fr->fr_tif)) + return 0; + } else if (fdp != NULL) { + if (IP6_NOTZERO(&fdp->fd_ip6)) + dst6->sin6_addr = fdp->fd_ip6.in6; + } + if (ifp == NULL) + return -2; + + rtalloc((struct route *)ro); + + if ((ifp == NULL) && (ro->ro_rt != NULL)) + ifp = ro->ro_rt->rt_ifp; + + if ((ro->ro_rt == NULL) || (ifp == NULL) || + (ifp != ro->ro_rt->rt_ifp)) { + error = EHOSTUNREACH; + } else { + if (ro->ro_rt->rt_flags & RTF_GATEWAY) + dst6 = (struct sockaddr_in6 *)ro->ro_rt->rt_gateway; + ro->ro_rt->rt_use++; + +#if defined(OpenBSD) && (OpenBSD >= 200211) + ip6 = mtod(m0, ip6_t *); + ro_pmtu = ro; + finaldst = ip6->ip6_dst; + error = ip6_getpmtu(ro_pmtu, ro, ifp, &finaldst, &mtu); + if (error == 0) { +#else + mtu = nd_ifinfo[ifp->if_index].linkmtu; +#endif + if (m0->m_pkthdr.len <= mtu) { + error = nd6_output(ifp, fin->fin_ifp, *mpp, + dst6, ro->ro_rt); + } else { + error = EMSGSIZE; + } +#if defined(OpenBSD) && (OpenBSD >= 200211) + } +#endif + } + + if (ro->ro_rt != NULL) { + RTFREE(ro->ro_rt); + } + return error; +} +#endif + + +int +ipf_verifysrc(fin) + fr_info_t *fin; +{ + struct sockaddr_in *dst; + struct route iproute; + + bzero((char *)&iproute, sizeof(iproute)); + dst = (struct sockaddr_in *)&iproute.ro_dst; + dst->sin_len = sizeof(*dst); + dst->sin_family = AF_INET; + dst->sin_addr = fin->fin_src; + rtalloc(&iproute); + if (iproute.ro_rt == NULL) + return 0; + return (fin->fin_ifp == iproute.ro_rt->rt_ifp); +} + + +/* + * return the first IP Address associated with an interface + */ +int +ipf_ifpaddr(softc, v, atype, ifptr, inp, inpmask) + ipf_main_softc_t *softc; + int v, atype; + void *ifptr; + i6addr_t *inp, *inpmask; +{ +#ifdef USE_INET6 + struct in6_addr *inp6 = NULL; +#endif + struct sockaddr *sock, *mask; + struct sockaddr_in *sin; + struct ifaddr *ifa; + struct ifnet *ifp; + + if ((ifptr == NULL) || (ifptr == (void *)-1)) + return -1; + + ifp = ifptr; + + if (v == 4) + inp->in4.s_addr = 0; +#ifdef USE_INET6 + else if (v == 6) + bzero((char *)inp, sizeof(*inp)); +#endif + ifa = ifp->if_addrlist.tqh_first; + sock = ifa->ifa_addr; + while (sock != NULL && ifa != NULL) { + sin = (struct sockaddr_in *)sock; + if ((v == 4) && (sin->sin_family == AF_INET)) + break; +#ifdef USE_INET6 + if ((v == 6) && (sin->sin_family == AF_INET6)) { + inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr; + if (!IN6_IS_ADDR_LINKLOCAL(inp6) && + !IN6_IS_ADDR_LOOPBACK(inp6)) + break; + } +#endif + ifa = ifa->ifa_list.tqe_next; + if (ifa != NULL) + sock = ifa->ifa_addr; + } + if (ifa == NULL || sock == NULL) + return -1; + + mask = ifa->ifa_netmask; + if (atype == FRI_BROADCAST) + sock = ifa->ifa_broadaddr; + else if (atype == FRI_PEERADDR) + sock = ifa->ifa_dstaddr; + +#ifdef USE_INET6 + if (v == 6) + return ipf_ifpfillv6addr(atype, (struct sockaddr_in6 *)sock, + (struct sockaddr_in6 *)mask, + inp, inpmask); +#endif + return ipf_ifpfillv4addr(atype, (struct sockaddr_in *)sock, + (struct sockaddr_in *)mask, + &inp->in4, &inpmask->in4); +} + + +u_32_t +ipf_newisn(fin) + fr_info_t *fin; +{ + u_32_t newiss; +#if OpenBSD > 200012 + newiss = tcp_rndiss_next(); +#else + static iss_seq_off = 0; + u_char hash[16]; + MD5_CTX ctx; + + /* + * Compute the base value of the ISS. It is a hash + * of (saddr, sport, daddr, dport, secret). + */ + MD5Init(&ctx); + + MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, + sizeof(fin->fin_fi.fi_src)); + MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, + sizeof(fin->fin_fi.fi_dst)); + MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); + + MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); + + MD5Final(hash, &ctx); + + memcpy(&newiss, hash, sizeof(newiss)); + + /* + * Now increment our "timer", and add it in to + * the computed value. + * + * XXX Use `addin'? + * XXX TCP_ISSINCR too large to use? + */ + iss_seq_off += 0x00010000; + newiss += iss_seq_off; +#endif + return newiss; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nextipid */ +/* Returns: int - 0 == success, -1 == error (packet should be droppped) */ +/* Parameters: fin(I) - pointer to packet information */ +/* */ +/* Returns the next IPv4 ID to use for this packet. */ +/* ------------------------------------------------------------------------ */ +u_short +ipf_nextipid(fin) + fr_info_t *fin; +{ + u_short id; + + id = htons(ip_randomid()); + + return id; +} + + +INLINE int +ipf_checkv4sum(fin) + fr_info_t *fin; +{ +#ifdef M_CSUM_TCP_UDP_BAD + int manual, pflag, cflags, active; + mb_t *m; + + if ((fin->fin_flx & FI_NOCKSUM) != 0) + return 0; + + if ((fin->fin_flx & FI_SHORT) != 0) + return 1; + + if (fin->fin_cksum != FI_CK_NEEDED) + return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; + + manual = 0; + m = fin->fin_m; + if (m == NULL) { + manual = 1; + goto skipauto; + } + + switch (fin->fin_p) + { + case IPPROTO_UDP : + active = M_TCP_CSUM_IN_OK | M_TCP_CSUM_IN_BAD; + pflag = M_TCP_CSUM_IN_OK; + break; + case IPPROTO_TCP : + active = M_UDP_CSUM_IN_OK | M_UDP_CSUM_IN_BAD; + pflag = M_UDP_CSUM_IN_OK; + break; + default : + pflag = 0; + manual = 1; + break; + } + + cflags = m->m_pkthdr.csum & active; + + if (pflag != 0) { + if (cflags == active)) { + fin->fin_flx |= FI_BAD + fin->fin_cksum = FI_CK_BAD; + } else if (cflags == pflag) { + fin->fin_cksum = FI_CK_SUMOK; + } else { + manual = 1; + } + } +skipauto: + if (manual != 0) { + if (ipf_checkl4sum(fin) == -1) { + fin->fin_flx |= FI_BAD; + return -1; + } else { + m->m_pkthdr.csum |= pflag; + } + } +#else + if (ipf_checkl4sum(fin) == -1) { + fin->fin_flx |= FI_BAD; + return -1; + } +#endif + return 0; +} + + +#ifdef USE_INET6 +INLINE int +ipf_checkv6sum(fin) + fr_info_t *fin; +{ + if ((fin->fin_flx & FI_NOCKSUM) != 0) + return 0; + + if ((fin->fin_flx & FI_SHORT) != 0) + return 1; + + if (fin->fin_cksum != FI_CK_NEEDED) + return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; + + if (ipf_checkv4sum(fin) == -1) + return -1; + return 0; +} +#endif + + +size_t +mbufchainlen(m0) + struct mbuf *m0; +{ + size_t len; + + if ((m0->m_flags & M_PKTHDR) != 0) { + len = m0->m_pkthdr.len; + } else { + struct mbuf *m; + + for (m = m0, len = 0; m != NULL; m = m->m_next) + len += m->m_len; + } + return len; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pullup */ +/* Returns: NULL == pullup failed, else pointer to protocol header */ +/* Parameters: xmin(I)- pointer to buffer where data packet starts */ +/* fin(I) - pointer to packet information */ +/* len(I) - number of bytes to pullup */ +/* */ +/* Attempt to move at least len bytes (from the start of the buffer) into a */ +/* single buffer for ease of access. Operating system native functions are */ +/* used to manage buffers - if necessary. If the entire packet ends up in */ +/* a single buffer, set the FI_COALESCE flag even though ipf_coalesce() has */ +/* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */ +/* and ONLY if the pullup succeeds. */ +/* */ +/* We assume that 'min' is a pointer to a buffer that is part of the chain */ +/* of buffers that starts at *fin->fin_mp. */ +/* ------------------------------------------------------------------------ */ +void * +ipf_pullup(xmin, fin, len) + mb_t *xmin; + fr_info_t *fin; + int len; +{ + int out = fin->fin_out, dpoff, ipoff; + mb_t *m = xmin; + char *ip; + + if (m == NULL) + return NULL; + + ip = (char *)fin->fin_ip; + if ((fin->fin_flx & FI_COALESCE) != 0) + return ip; + + ipoff = fin->fin_ipoff; + if (fin->fin_dp != NULL) + dpoff = (char *)fin->fin_dp - (char *)ip; + else + dpoff = 0; + + if (M_LEN(m) < len) { + mb_t *n = *fin->fin_mp; + /* + * Assume that M_PKTHDR is set and just work with what is left + * rather than check.. + * Should not make any real difference, anyway. + */ + if (m != n) { + /* + * Record the mbuf that points to the mbuf that we're + * about to go to work on so that we can update the + * m_next appropriately later. + */ + for (; n->m_next != m; n = n->m_next) + ; + } else { + n = NULL; + } + +#ifdef MHLEN + if (len > MHLEN) +#else + if (len > MLEN) +#endif + { +#ifdef HAVE_M_PULLDOWN + if (m_pulldown(m, 0, len, NULL) == NULL) + m = NULL; +#else + FREE_MB_T(*fin->fin_mp); + m = NULL; +#endif + } else + { + m = m_pullup(m, len); + } + if (n != NULL) + n->m_next = m; + if (m == NULL) { + /* + * When n is non-NULL, it indicates that m pointed to + * a sub-chain (tail) of the mbuf and that the head + * of this chain has not yet been free'd. + */ + if (n != NULL) { + FREE_MB_T(*fin->fin_mp); + } + + *fin->fin_mp = NULL; + fin->fin_m = NULL; + return NULL; + } + + if (n == NULL) + *fin->fin_mp = m; + + while (M_LEN(m) == 0) { + m = m->m_next; + } + fin->fin_m = m; + ip = MTOD(m, char *) + ipoff; + + fin->fin_ip = (ip_t *)ip; + if (fin->fin_dp != NULL) + fin->fin_dp = (char *)fin->fin_ip + dpoff; + if (fin->fin_fraghdr != NULL) + fin->fin_fraghdr = (char *)ip + + ((char *)fin->fin_fraghdr - + (char *)fin->fin_ip); + } + + if (len == fin->fin_plen) + fin->fin_flx |= FI_COALESCE; + return ip; +} + + +int +ipf_inject(fin, m) + fr_info_t *fin; + mb_t *m; +{ + int error; + + if (fin->fin_out == 0) { + struct ifqueue *ifq; + + ifq = &ipintrq; + + if (IF_QFULL(ifq)) { + IF_DROP(ifq); + FREE_MB_T(m); + error = ENOBUFS; + } else { + IF_ENQUEUE(ifq, m); + error = 0; + } + } else { + error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL); + } + + return error; +} + + +int +ipf_random() +{ + int number; + + number = arc4random(); + return number; +} diff --git a/ip_fil_osf.c b/ip_fil_osf.c new file mode 100644 index 0000000000000..62b9763d14d01 --- /dev/null +++ b/ip_fil_osf.c @@ -0,0 +1,1378 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ +#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$"; +#endif + +#if defined(KERNEL) || defined(_KERNEL) +# undef KERNEL +# undef _KERNEL +# define KERNEL 1 +# define _KERNEL 1 +#endif +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/types.h> +#include <sys/file.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/systm.h> +#include <sys/dir.h> +#include <sys/mbuf.h> +#include <sys/protosw.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <net/radix.h> +#include <netinet/in.h> +#include <netinet/in_var.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/ip_var.h> +#include <netinet/tcp.h> +#include <netinet/tcp_timer.h> +#include <netinet/udp.h> +#include <netinet/tcpip.h> +#include <netinet/ip_icmp.h> +#include "netinet/ip_compat.h" +#ifdef USE_INET6 +# include <netinet/icmp6.h> +#endif +#include "netinet/ip_fil.h" +#include "netinet/ip_nat.h" +#include "netinet/ip_frag.h" +#include "netinet/ip_state.h" +#include "netinet/ip_proxy.h" +#include "netinet/ip_auth.h" +#include "netinet/ip_sync.h" +#ifdef IPFILTER_SCAN +#include "netinet/ip_scan.h" +#endif +/* + * It is important that these #define's only affect this .h file in here + * because we depend on the routing stuff getting the current names. + */ +#define radix_mask ipf_radix_mask +#define radix_node ipf_radix_node +#define radix_node_head ipf_radix_node_head +#undef radix_mask +#undef radix_node +#undef radix_node_head +#include "md5.h" +#include <sys/kernel.h> +extern int ip_optcopy __P((struct ip *, struct ip *)); +extern int udp_ttl; +extern int ipdefttl; +extern int ipforwarding; + +extern ipf_main_softc_t ipfmain; + +/* #undef IPFDEBUG */ + +static u_short ipid = 0; +static int ipf_send_ip __P((fr_info_t *, mb_t *)); + +ipfmutex_t ipf_rw, ipl_mutex, ipf_auth_mx, ipf_timeoutlock; +ipfmutex_t ipf_nat_new, ipf_natio, ipf_stinsert; +ipfrwlock_t ipf_mutex, ipf_global, ipf_frag, ipf_tru64, ipf_frcache; +ipfrwlock_t ipf_state, ipf_nat, ipf_natfrag, ipf_authlk, ipf_ipidfrag; +ipfrwlock_t ipf_tokens; +int ipf_locks_done = 0; + +#if defined(IPFILTER_LKM) +int +iplidentify(s) + char *s; +{ + if (strcmp(s, "ipl") == 0) + return 1; + return 0; +} +#endif /* IPFILTER_LKM */ + + +int +ipfattach(softc) + ipf_main_softc_t *softc; +{ + int s, i; + + SPL_NET(s); + if (softc->ipf_running > 0) { + printf("IP Filter: already initialized\n"); + SPL_X(s); + return EBUSY; + } + + if (ipf_init_all(softc) < 0) { + SPL_X(s); +#ifdef IPFDEBUG + printf("ipf_initialise() == %d\n", i); +#endif + return EIO; + } + + if (softc->ipf_control_forwarding & 1) + ipforwarding = 1; + + ipid = 0; + + SPL_X(s); + + return 0; +} + + +/* + * Disable the filter by removing the hooks from the IP input/output + * stream. + */ +int +ipfdetach(softc) + ipf_main_softc_t *softc; +{ + int s; + + if (softc->ipf_refcnt) + return EBUSY; + + SPL_NET(s); + + if (softc->ipf_control_forwarding & 2) + ipforwarding = 0; + + ipf_fini_all(softc); + + SPL_X(s); + + return 0; +} + + +/* + * Filter ioctl interface. + */ +int +ipfioctl(dev, cmd, data, mode) + dev_t dev; + int cmd; + caddr_t data; + int mode; +{ + int error = 0, unit = 0; + struct proc *p; + SPL_INT(s); + + unit = minor(dev); + if ((IPL_LOGMAX < unit) || (unit < 0)) { + ipfmain.ipf_interror = 130002; + return ENXIO; + } + + if (ipfmain.ipf_running <= 0) { + if (unit != IPL_LOGIPF && cmd != SIOCIPFINTERROR) { + ipfmain.ipf_interror = 130003; + return EIO; + } + if (cmd != (ioctlcmd_t)SIOCIPFGETNEXT && + cmd != (ioctlcmd_t)SIOCIPFGET && + cmd != (ioctlcmd_t)SIOCIPFSET && + cmd != (ioctlcmd_t)SIOCFRENB && + cmd != (ioctlcmd_t)SIOCGETFS && + cmd != (ioctlcmd_t)SIOCGETFF && + cmd != (ioctlcmd_t)SIOCIPFINTERROR) { + ipfmain.ipf_interror = 130004; + return EIO; + } + } + + SPL_NET(s); + + p = task_to_proc(current_task()); + error = ipf_ioctlswitch(&ipfmain, unit, data, cmd, mode, p->p_ruid, p); + if (error != -1) { + SPL_X(s); + return error; + } + + SPL_X(s); + return error; +} + + +/* + * ipf_send_reset - this could conceivably be a call to tcp_respond(), but that + * requires a large amount of setting up and isn't any more efficient. + */ +int +ipf_send_reset(fin) + fr_info_t *fin; +{ + struct tcphdr *tcp, *tcp2; + int tlen = 0, hlen; + struct mbuf *m; +#ifdef USE_INET6 + ip6_t *ip6; +#endif + ip_t *ip; + + tcp = fin->fin_dp; + if (tcp->th_flags & TH_RST) + return -1; /* feedback loop */ + + if (ipf_checkl4sum(fin) == -1) + return -1; + + tlen = fin->fin_dlen - (TCP_OFF(tcp) << 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 + hlen = sizeof(ip_t); +#endif +#ifdef MGETHDR + MGETHDR(m, M_DONTWAIT, MT_HEADER); +#else + MGET(m, M_DONTWAIT, MT_HEADER); +#endif + if (m == NULL) + return -1; + if (sizeof(*tcp2) + hlen > MHLEN) { + MCLGET(m, M_DONTWAIT); + if ((m->m_flags & M_EXT) == 0) { + FREE_MB_T(m); + return -1; + } + } + + m->m_len = sizeof(*tcp2) + hlen; + m->m_data += max_linkhdr; + m->m_pkthdr.len = m->m_len; + m->m_pkthdr.rcvif = (struct ifnet *)0; + + ip = mtod(m, struct ip *); + bzero((char *)ip, hlen); +#ifdef USE_INET6 + ip6 = (ip6_t *)ip; +#endif + tcp2 = (struct tcphdr *)((char *)ip + hlen); + tcp2->th_sport = tcp->th_dport; + tcp2->th_dport = tcp->th_sport; + + if (tcp->th_flags & TH_ACK) { + tcp2->th_seq = tcp->th_ack; + tcp2->th_flags = TH_RST; + tcp2->th_ack = 0; + } else { + tcp2->th_seq = 0; + 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; + } + TCP_X2_A(tcp2, 0); + TCP_OFF_A(tcp2, sizeof(*tcp2) >> 2); + tcp2->th_win = tcp->th_win; + tcp2->th_sum = 0; + tcp2->th_urp = 0; + +#ifdef USE_INET6 + if (fin->fin_v == 6) { + ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; + ip6->ip6_plen = htons(sizeof(struct tcphdr)); + ip6->ip6_nxt = IPPROTO_TCP; + ip6->ip6_hlim = 0; + ip6->ip6_src = fin->fin_dst6.in6; + ip6->ip6_dst = fin->fin_src6.in6; +/* + tcp2->th_sum = in6_cksum(m, IPPROTO_TCP, + sizeof(*ip6), sizeof(*tcp2)); +*/ + return ipf_send_ip(fin, m); + } +#endif + ip->ip_p = IPPROTO_TCP; + ip->ip_len = htons(sizeof(struct tcphdr)); + ip->ip_src.s_addr = fin->fin_daddr; + ip->ip_dst.s_addr = fin->fin_saddr; + tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2)); + ip->ip_len = hlen + sizeof(*tcp2); + return ipf_send_ip(fin, m); +} + + +static int +ipf_send_ip(fin, m) + fr_info_t *fin; + mb_t *m; +{ + fr_info_t fnew; + ip_t *ip, *oip; + int ttl, hlen; + + ip = mtod(m, ip_t *); + bzero((char *)&fnew, sizeof(fnew)); + fnew.fin_main_soft = fin->fin_main_soft; + + switch (fin->fin_p) + { + case IPPROTO_TCP : + ttl = tcp_ttl; + break; + case IPPROTO_UDP : + ttl = udp_ttl; + break; + default : + ttl = ipdefttl; + break; + } + + IP_V_A(ip, fin->fin_v); + + switch (fin->fin_v) + { + case 4 : + oip = fin->fin_ip; + hlen = sizeof(*oip); + fnew.fin_v = 4; + fnew.fin_p = ip->ip_p; + fnew.fin_plen = ip->ip_len + hlen; + IP_HL_A(ip, sizeof(*oip) >> 2); + ip->ip_tos = oip->ip_tos; + ip->ip_id = fin->fin_ip->ip_id; + ip->ip_len = htons(ip->ip_len); + ip->ip_off = 0; + ip->ip_ttl = ttl; + ip->ip_sum = 0; + break; +#ifdef USE_INET6 + case 6 : + { + ip6_t *ip6 = (ip6_t *)ip; + +# if TRU64 <= 1885 + ip6->ip6_vcf = 0x60; +# else + ip6->ip6_vfc = 0x60; +# endif + ip6->ip6_hlim = ttl; + + hlen = sizeof(*ip6); + fnew.fin_p = ip6->ip6_nxt; + fnew.fin_v = 6; + fnew.fin_plen = ntohs(ip6->ip6_plen) + hlen; + } +#endif + default : + return EINVAL; + } +#ifdef IPSEC + m->m_pkthdr.rcvif = NULL; +#endif + + fnew.fin_ifp = fin->fin_ifp; + fnew.fin_flx = FI_NOCKSUM; + fnew.fin_m = m; + fnew.fin_ip = ip; + fnew.fin_mp = &m; + fnew.fin_hlen = hlen; + fnew.fin_dp = (char *)ip + hlen; + (void) ipf_makefrip(hlen, ip, &fnew); + + return ipf_fastroute(m, &m, &fnew, NULL); +} + + +int +ipf_send_icmp_err(type, fin, dst) + int type; + fr_info_t *fin; + int dst; +{ + int err, hlen = 0, xtra = 0, iclen, ohlen = 0, avail, code; + struct in_addr dst4; + struct icmp *icmp; + struct mbuf *m; + i6addr_t dst6; + void *ifp; +#ifdef USE_INET6 + ip6_t *ip6; +#endif + ip_t *ip, *ip2; + + if ((type < 0) || (type > ICMP_MAXTYPE)) + return -1; + + code = fin->fin_icode; +#ifdef USE_INET6 + if ((code < 0) || (code > sizeof(icmptoicmp6unreach)/sizeof(int))) + return -1; +#endif + + if (ipf_checkl4sum(fin) == -1) + return -1; +#ifdef MGETHDR + MGETHDR(m, M_DONTWAIT, MT_HEADER); +#else + MGET(m, M_DONTWAIT, MT_HEADER); +#endif + if (m == NULL) + return -1; + avail = MHLEN; + + ifp = fin->fin_ifp; + if (fin->fin_v == 4) { + if ((fin->fin_p == IPPROTO_ICMP) && !(fin->fin_flx & FI_SHORT)) + switch (ntohs(fin->fin_data[0]) >> 8) + { + case ICMP_ECHO : + case ICMP_TSTAMP : + case ICMP_IREQ : + case ICMP_MASKREQ : + break; + default : + FREE_MB_T(m); + return 0; + } + + if (dst == 0) { + if (ipf_ifpaddr(&ipfmain, 4, FRI_NORMAL, ifp, + &dst6, NULL) == -1) { + FREE_MB_T(m); + return -1; + } + dst4 = dst6.in4; + } else + dst4.s_addr = fin->fin_daddr; + + hlen = sizeof(ip_t); + iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen; + if (fin->fin_hlen < fin->fin_plen) + xtra = MIN(fin->fin_dlen, 8); + else + xtra = 0; + } + +#ifdef USE_INET6 + else if (fin->fin_v == 6) { + hlen = sizeof(ip6_t); + ohlen = sizeof(ip6_t); + iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen; + type = icmptoicmp6types[type]; + if (type == ICMP6_DST_UNREACH) + code = icmptoicmp6unreach[code]; + + if (hlen + sizeof(*icmp) + max_linkhdr + + fin->fin_plen > avail) { + MCLGET(m, M_DONTWAIT); + if ((m->m_flags & M_EXT) == 0) { + FREE_MB_T(m); + return -1; + } + avail = MCLBYTES; + } + xtra = MIN(fin->fin_plen, avail - iclen - max_linkhdr); + xtra = MIN(xtra, IPV6_MMTU - iclen); + if (dst == 0) { + if (ipf_ifpaddr(&ipfmain, 6, FRI_NORMAL, ifp, + &dst6, NULL) == -1) { + FREE_MB_T(m); + return -1; + } + } else + dst6 = fin->fin_dst6; + } +#endif + else { + FREE_MB_T(m); + return -1; + } + + avail -= (max_linkhdr + iclen); + m->m_data += max_linkhdr; + m->m_pkthdr.rcvif = (struct ifnet *)0; + if (xtra > avail) + xtra = avail; + iclen += xtra; + m->m_pkthdr.len = iclen; + + if (avail < 0) { + FREE_MB_T(m); + return -1; + } + m->m_len = iclen; + ip = mtod(m, ip_t *); + icmp = (struct icmp *)((char *)ip + hlen); + ip2 = (ip_t *)&icmp->icmp_ip; + + 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) { + if (fin->fin_mtu != 0) { + icmp->icmp_nextmtu = htons(fin->fin_mtu); + + } else if (ifp != NULL) { + icmp->icmp_nextmtu = htons(GETIFMTU_4(ifp)); + + } else { /* make up a number... */ + icmp->icmp_nextmtu = htons(fin->fin_plen - 20); + } + } +#endif + + bcopy((char *)fin->fin_ip, (char *)ip2, ohlen); + +#ifdef USE_INET6 + ip6 = (ip6_t *)ip; + if (fin->fin_v == 6) { + ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; + ip6->ip6_plen = htons(iclen - hlen); + ip6->ip6_nxt = IPPROTO_ICMPV6; + ip6->ip6_hlim = 0; + ip6->ip6_src = dst6.in6; + ip6->ip6_dst = fin->fin_src6.in6; + if (xtra > 0) + bcopy((char *)fin->fin_ip + ohlen, + (char *)&icmp->icmp_ip + ohlen, xtra); +/* + icmp->icmp_cksum = in6_cksum(m, IPPROTO_ICMPV6, + sizeof(*ip6), iclen - hlen); +*/ + } else +#endif + { + ip->ip_p = IPPROTO_ICMP; + ip->ip_src.s_addr = dst4.s_addr; + ip->ip_dst.s_addr = fin->fin_saddr; + + if (xtra > 0) + bcopy((char *)fin->fin_ip + ohlen, + (char *)&icmp->icmp_ip + ohlen, xtra); + icmp->icmp_cksum = ipf_cksum((u_short *)icmp, + sizeof(*icmp) + 8); + ip->ip_len = iclen; + ip->ip_p = IPPROTO_ICMP; + } + err = ipf_send_ip(fin, m); + return err; +} + + +void iplinit __P((void)); + +void iplinit() +{ + if (ipfattach(&ipfmain) != 0) + printf("IP Filter failed to attach\n"); + ip_init(); +} + + +/* + * m0 - pointer to mbuf where the IP packet starts + * mpp - pointer to the mbuf pointer that is the start of the mbuf chain + */ +int +ipf_fastroute(m0, mpp, fin, fdp) + struct mbuf *m0, **mpp; + fr_info_t *fin; + frdest_t *fdp; +{ + register struct ip *ip, *mhip; + register struct mbuf *m = *mpp; + register struct route *ro; + int len, off, error = 0, hlen, code; + struct ifnet *ifp, *sifp; + struct sockaddr_in *dst; + ipf_main_softc_t *softc; + u_short ip_off, ip_len; + struct route iproute; + frdest_t node; + frentry_t *fr; + + softc = fin->fin_main_soft; + +#ifdef M_WRITABLE + /* + * HOT FIX/KLUDGE: + * + * If the mbuf we're about to send is not writable (because of + * a cluster reference, for example) we'll need to make a copy + * of it since this routine modifies the contents. + * + * If you have non-crappy network hardware that can transmit data + * from the mbuf, rather than making a copy, this is gonna be a + * problem. + */ + if (M_WRITABLE(m) == 0) { + if ((m0 = m_dup(m, M_DONTWAIT)) != 0) { + FREE_MB_T(m); + m = m0; + *mpp = m; + } else { + error = ENOBUFS; + FREE_MB_T(m); + goto done; + } + } +#endif + + hlen = fin->fin_hlen; + ip = mtod(m0, struct ip *); + +#if 0 /* ifdef USE_INET6 */ + if (fin->fin_v == 6) { + dst6->sin6_family = AF_INET6; + + fr = fin->fin_fr; + if (fdp != NULL) + ifp = fdp->fd_ifp; + else { + ifp = fin->fin_ifp; + dst->sin6_addr = fin->fin_daddr6; + } + + ip6tx.tx_mbuf = *mpp; + ip6tx.tx_ip6 = (ip6_t *)ip; + ip6tx.tx_ro = ro; + ip6tx.tx_if6 = NULL; + ip6tx.tx_nexthop = dst6; + ip6tx.tx_imo6 = NULL; + ip6tx.tx_pmtudisc = 0; + ip6tx.tx_dontroute = 0; + ip6tx.tx_rawoutput = 0; + ip6tx.tx_mtu = ifp->if_mtu; + ip6tx.tx_opt = NULL; + + /* + * currently "to <if>" and "to <if>:ip#" are not supported + * for IPv6 + */ + return ip6_output(&ip6tx); + } +# endif + /* + * Route packet. + */ + ro = &iproute; + bzero((caddr_t)ro, sizeof (*ro)); + dst = (struct sockaddr_in *)&ro->ro_dst; + dst->sin_family = AF_INET; + dst->sin_addr = ip->ip_dst; + + fr = fin->fin_fr; + if ((fr != NULL) && !(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) && + (fdp->fd_type == FRD_DSTLIST)) { + if (ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node) == 0) + fdp = &node; + } + + if (fdp != NULL) + ifp = fdp->fd_ptr; + else + ifp = fin->fin_ifp; + + if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0)) + dst->sin_addr = fdp->fd_ip; + + dst->sin_len = sizeof(*dst); + rtalloc(ro); + if (!ifp) { + if (!fr || !(fr->fr_flags & FR_FASTROUTE)) { + error = -2; + goto bad; + } + if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) { + i6addr_t i6; + + i6.in4 = ip->ip_dst; + + if (in_localaddr(&i6.in6, ro->ro_rt)) + error = EHOSTUNREACH; + else + error = ENETUNREACH; + goto bad; + } + if (ro->ro_rt->rt_flags & RTF_GATEWAY) + dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway; + } + if (ro->ro_rt) + ro->ro_rt->rt_use++; + + /* + * For input packets which are being "fastrouted", they won't + * go back through output filtering and miss their chance to get + * NAT'd and counted. Duplicated packets aren't considered to be + * part of the normal packet stream, so do not NAT them or pass + * them through stateful checking, etc. + */ + if ((fdp != &fr->fr_dif) && (fin->fin_out == 0)) { + sifp = fin->fin_ifp; + fin->fin_ifp = ifp; + fin->fin_out = 1; + (void) ipf_acctpkt(fin, NULL); + fin->fin_fr = NULL; + if (!fr || !(fr->fr_flags & FR_RETMASK)) { + u_32_t pass; + + (void) ipf_state_check(fin, &pass); + } + + switch (ipf_nat_checkout(fin, NULL)) + { + case 0 : + break; + case 1 : + ip->ip_sum = 0; + break; + case -1 : + error = -1; + goto bad; + break; + } + + fin->fin_ifp = sifp; + fin->fin_out = 0; + } else + ip->ip_sum = 0; + /* + * If small enough for interface, can just send directly. + */ + ip_len = ntohs(ip->ip_len); + if (ip_len <= ifp->if_mtu) { + if (!ip->ip_sum) + ip->ip_sum = in_cksum(m, hlen); +#if TRU64 >= 1885 + error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, + ro->ro_rt, NULL); +#else + error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, + ro->ro_rt); +#endif + goto done; + } + /* + * Too large for interface; fragment if possible. + * Must be able to put at least 8 bytes per fragment. + */ + ip_off = ntohs(ip->ip_off); + if (ip_off & IP_DF) { + error = EMSGSIZE; + goto bad; + } + len = (ifp->if_mtu - hlen) &~ 7; + if (len < 8) { + error = EMSGSIZE; + goto bad; + } + + { + int mhlen, firstlen = len; + struct mbuf **mnext = &m->m_act; + + /* + * Loop through length of segment after first fragment, + * make new header and copy data of each part and link onto chain. + */ + m0 = m; + mhlen = sizeof (struct ip); + for (off = hlen + len; off < ip_len; off += len) { +#ifdef MGETHDR + MGETHDR(m, M_DONTWAIT, MT_HEADER); +#else + MGET(m, M_DONTWAIT, MT_HEADER); +#endif + if (m == 0) { + m = m0; + error = ENOBUFS; + goto bad; + } + m->m_data += max_linkhdr; + mhip = mtod(m, struct ip *); + bcopy((char *)ip, (char *)mhip, sizeof(*ip)); + if (hlen > sizeof (struct ip)) { + mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); + IP_HL_A(mhip, mhlen >> 2); + } + m->m_len = mhlen; + mhip->ip_off = ((off - hlen) >> 3) + ip_off; + if (off + len >= ip_len) + len = ip_len - off; + else + mhip->ip_off |= IP_MF; + mhip->ip_len = htons((u_short)(len + mhlen)); + m->m_next = m_copy(m0, off, len); + if (m->m_next == 0) { + error = ENOBUFS; /* ??? */ + goto sendorfree; + } + m->m_pkthdr.len = mhlen + len; + m->m_pkthdr.rcvif = NULL; + mhip->ip_off = htons((u_short)mhip->ip_off); + mhip->ip_sum = 0; + mhip->ip_sum = in_cksum(m, mhlen); + *mnext = m; + mnext = &m->m_act; + } + /* + * Update first fragment by trimming what's been copied out + * and updating header, then send each fragment (in order). + */ + m_adj(m0, hlen + firstlen - ip_len); + ip->ip_len = htons((u_short)(hlen + firstlen)); + ip->ip_off = htons((u_short)IP_MF); + ip->ip_sum = 0; + ip->ip_sum = in_cksum(m0, hlen); +sendorfree: + for (m = m0; m; m = m0) { + m0 = m->m_act; + m->m_act = 0; + if (error == 0) +#if TRU64 >= 1885 + error = (*ifp->if_output)(ifp, m, + (struct sockaddr *)dst, ro->ro_rt, NULL); +#else + error = (*ifp->if_output)(ifp, m, + (struct sockaddr *)dst, ro->ro_rt); +#endif + else + FREE_MB_T(m); + } + } +done: + if (!error) + softc->ipf_frouteok[0]++; + else + softc->ipf_frouteok[1]++; + + if (ro->ro_rt) { + RTFREE(ro->ro_rt); + } + return 0; +bad: + if (error == EMSGSIZE) { + sifp = fin->fin_ifp; + code = fin->fin_icode; + fin->fin_icode = ICMP_UNREACH_NEEDFRAG; + fin->fin_ifp = ifp; + (void) ipf_send_icmp_err(ICMP_UNREACH, fin, 1); + fin->fin_ifp = sifp; + fin->fin_icode = code; + } + FREE_MB_T(m); + goto done; +} + + +int +ipf_verifysrc(fin) + fr_info_t *fin; +{ + struct sockaddr_in *dst; + struct route iproute; + + bzero((char *)&iproute, sizeof(iproute)); + dst = (struct sockaddr_in *)&iproute.ro_dst; + dst->sin_len = sizeof(*dst); + dst->sin_family = AF_INET; + dst->sin_addr = fin->fin_src; + rtalloc(&iproute); + if (iproute.ro_rt == NULL) + return 0; + return (fin->fin_ifp == iproute.ro_rt->rt_ifp); +} + + +/* + * return the first IP Address associated with an interface + */ +int +ipf_ifpaddr(softc, v, atype, ifptr, inp, inpmask) + ipf_main_softc_t *softc; + int v, atype; + void *ifptr; + i6addr_t *inp, *inpmask; +{ +#ifdef USE_INET6 + struct in6_addr *inp6 = NULL; +#endif + struct sockaddr *sock, *mask; + struct sockaddr_in *sin; + struct ifaddr *ifa; + struct in_addr in; + struct ifnet *ifp; + + if ((ifptr == NULL) || (ifptr == (void *)-1)) + return -1; + + ifp = ifptr; + + if (v == 4) + inp->in4.s_addr = 0; +#ifdef USE_INET6 + else if (v == 6) + bzero((char *)inp, sizeof(*inp)); +#endif + + ifa = ifp->if_addrlist; + sock = ifa->ifa_addr; + while (sock != NULL && ifa != NULL) { + sin = (struct sockaddr_in *)sock; + if ((v == 4) && (sin->sin_family == AF_INET)) + break; +#ifdef USE_INET6 + if ((v == 6) && (sin->sin_family == AF_INET6)) { + inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr; + if (!IN6_IS_ADDR_LINKLOCAL(inp6) && + !IN6_IS_ADDR_LOOPBACK(inp6)) + break; + } +#endif + ifa = ifa->ifa_next; + if (ifa) + sock = ifa->ifa_addr; + } + if (ifa == NULL || sock == NULL) + return -1; + + mask = ifa->ifa_netmask; + if (atype == FRI_BROADCAST) + sock = ifa->ifa_broadaddr; + else if (atype == FRI_PEERADDR) + sock = ifa->ifa_dstaddr; + +#ifdef USE_INET6 + if (v == 6) + return ipf_ifpfillv6addr(atype, (struct sockaddr_in6 *)sock, + (struct sockaddr_in6 *)mask, + inp, inpmask); +#endif + return ipf_ifpfillv4addr(atype, (struct sockaddr_in *)sock, + (struct sockaddr_in *)mask, + &inp->in4, &inpmask->in4); +} + + +u_32_t +ipf_newisn(fin) + fr_info_t *fin; +{ + static int iss_seq_off = 0; + ipf_main_softc_t *softc = fin->fin_main_soft; + u_char hash[16]; + u_32_t newiss; + MD5_CTX ctx; + + /* + * Compute the base value of the ISS. It is a hash + * of (saddr, sport, daddr, dport, secret). + */ + MD5Init(&ctx); + + MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, + sizeof(fin->fin_fi.fi_src)); + MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, + sizeof(fin->fin_fi.fi_dst)); + MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); + + MD5Update(&ctx, softc->ipf_iss_secret, sizeof(softc->ipf_iss_secret)); + + MD5Final(hash, &ctx); + + bcopy(hash, &newiss, sizeof(newiss)); + + /* + * Now increment our "timer", and add it in to + * the computed value. + * + * XXX Use `addin'? + * XXX TCP_ISSINCR too large to use? + */ + iss_seq_off += 0x00010000; + newiss += iss_seq_off; + return newiss; +} + + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_slowtimer */ +/* Returns: Nil */ +/* Parameters: Nil */ +/* */ +/* Slowly expire held state for fragments. Timeouts are set * in */ +/* expectation of this being called twice per second. */ +/* ------------------------------------------------------------------------ */ +void +ipf_timer_func __P((void *ptr)) +{ + ipf_main_softc_t *softc = ptr; + + READ_ENTER(&softc->ipf_global); + + if (softc->ipf_running == 1) + ipf_slowtimer(softc); + + RWLOCK_EXIT(&softc->ipf_global); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nextipid */ +/* Returns: int - 0 == success, -1 == error (packet should be droppped) */ +/* Parameters: fin(I) - pointer to packet information */ +/* */ +/* Returns the next IPv4 ID to use for this packet. */ +/* ------------------------------------------------------------------------ */ +INLINE u_short +ipf_nextipid(fin) + fr_info_t *fin; +{ + u_short id; + + MUTEX_ENTER(&ipf_rw); + id = ipid++; + MUTEX_EXIT(&ipf_rw); + + return id; +} + + +INLINE int +ipf_checkv4sum(fin) + fr_info_t *fin; +{ + int manual, pflag, cflags, active; + mb_t *m; + + if ((fin->fin_flx & FI_NOCKSUM) != 0) + return 0; + + if ((fin->fin_flx & FI_SHORT) != 0) + return 1; + + if (fin->fin_cksum != FI_CK_NEEDED) + return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; + + m = fin->fin_m; + if (m == NULL) { + manual = 1; + goto skipauto; + } + + switch (fin->fin_p) + { + case IPPROTO_UDP : + case IPPROTO_TCP : + active = M_PROTOCOL_SUM | M_CHECKSUM | M_NOCHECKSUM | + M_IPPREPROCESS; + pflag = M_PROTOCOL_SUM; + manual = 0; + break; + default : + active = 0; + pflag = 0; + manual = 1; + break; + } + + cflags = m->m_flags & active; + + if (pflag != 0) { + if (cflags == pflag) { + fin->fin_cksum = FI_CK_SUMOK; + } else { + manual = 1; + } + } +skipauto: + if (manual != 0) { + if (ipf_checkl4sum(fin) == -1) { + fin->fin_flx |= FI_BAD; + return -1; + } + } + return 0; +} + + +#ifdef USE_INET6 +INLINE int +ipf_checkv6sum(fin) + fr_info_t *fin; +{ + if ((fin->fin_flx & FI_NOCKSUM) != 0) + return 0; + + if ((fin->fin_flx & FI_SHORT) != 0) + return 1; + + if (fin->fin_cksum != FI_CK_NEEDED) + return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; + + if (ipf_checkl4sum(fin) == -1) { + fin->fin_flx |= FI_BAD; + return -1; + } + return 0; +} +#endif /* USE_INET6 */ + + +size_t +mbufchainlen(m0) + struct mbuf *m0; +{ + size_t len; + + if ((m0->m_flags & M_PKTHDR) != 0) { + len = m0->m_pkthdr.len; + } else { + struct mbuf *m; + + for (m = m0, len = 0; m != NULL; m = m->m_next) + len += m->m_len; + } + return len; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pullup */ +/* Returns: NULL == pullup failed, else pointer to protocol header */ +/* Parameters: xmin(I)- pointer to buffer where data packet starts */ +/* fin(I) - pointer to packet information */ +/* len(I) - number of bytes to pullup */ +/* */ +/* Attempt to move at least len bytes (from the start of the buffer) into a */ +/* single buffer for ease of access. Operating system native functions are */ +/* used to manage buffers - if necessary. If the entire packet ends up in */ +/* a single buffer, set the FI_COALESCE flag even though ipf_coalesce() has */ +/* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */ +/* and ONLY if the pullup succeeds. */ +/* */ +/* We assume that 'xmin' is a pointer to a buffer that is part of the chain */ +/* of buffers that starts at *fin->fin_mp. */ +/* ------------------------------------------------------------------------ */ +void * +ipf_pullup(xmin, fin, len) + mb_t *xmin; + fr_info_t *fin; + int len; +{ + int out = fin->fin_out, dpoff, ipoff; + mb_t *m = xmin; + char *ip; + + if (m == NULL) + return NULL; + + ip = (char *)fin->fin_ip; + if ((fin->fin_flx & FI_COALESCE) != 0) + return ip; + + ipoff = fin->fin_ipoff; + if (fin->fin_dp != NULL) + dpoff = (char *)fin->fin_dp - (char *)ip; + else + dpoff = 0; + + if (M_LEN(m) < len) { + mb_t *n = *fin->fin_mp; + /* + * Assume that M_PKTHDR is set and just work with what is left + * rather than check.. + * Should not make any real difference, anyway. + */ + if (m != n) { + /* + * Record the mbuf that points to the mbuf that we're + * about to go to work on so that we can update the + * m_next appropriately later. + */ + for (; n->m_next != m; n = n->m_next) + ; + } else { + n = NULL; + } + +#ifdef MHLEN + if (len > MHLEN) +#else + if (len > MLEN) +#endif + { +#ifdef HAVE_M_PULLDOWN + if (m_pulldown(m, 0, len, NULL) == NULL) + m = NULL; +#else + FREE_MB_T(*fin->fin_mp); + m = NULL; +#endif + } else + { + m = m_pullup(m, len); + } + if (n = NULL) + n->m_next = n; + if (m == NULL) { + /* + * When n is non-NULL, it indicates that m pointed to + * a sub-chain (tail) of the mbuf and that the head + * of this chain has not yet been free'd. + */ + if (n != NULL) { + FREE_MB_T(*fin->fin_mp); + } + + *fin->fin_mp = NULL; + fin->fin_m = NULL; + return NULL; + } + + if (n == NULL) + *fin->fin_mp = m; + + while (M_LEN(m) == 0) { + m = m->m_next; + } + fin->fin_m = m; + ip = MTOD(m, char *) + ipoff; + + fin->fin_ip = (ip_t *)ip; + if (fin->fin_dp != NULL) + fin->fin_dp = (char *)fin->fin_ip + dpoff; + if (fin->fin_fraghdr != NULL) + fin->fin_fraghdr = (char *)ip + + ((char *)fin->fin_fraghdr - + (char *)fin->fin_ip); + } + + if (len == fin->fin_plen) + fin->fin_flx |= FI_COALESCE; + return ip; +} + + +int +ipf_inject(fin, m) + fr_info_t *fin; + mb_t *m; +{ + int error; + + if (fin->fin_out == 0) { + struct ifqueue *ifq; + + ifq = &ipintrq; + + if (IF_QFULL(ifq)) { + IF_DROP(ifq); + FREE_MB_T(m); + error = ENOBUFS; + } else { + IF_ENQUEUE(ifq, m); + error = 0; + } + } else { + error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL); + } + + return error; +} + + +/* + * Copy a packet header mbuf chain into a completely new chain, including + * copying any mbuf clusters. Use this instead of m_copypacket() when + * you need a writable copy of an mbuf chain. + */ +struct mbuf * +m_dup(struct mbuf *m, int how) +{ + struct mbuf **p, *top = NULL; + int remain, moff, nsize; + + if (m == NULL) + return (NULL); + + /* While there's more data, get a new mbuf, tack it on, and fill it */ + remain = m->m_pkthdr.len; + moff = 0; + p = ⊤ + while (remain > 0 || top == NULL) { /* allow m->m_pkthdr.len == 0 */ + struct mbuf *n; + + /* Get the next new mbuf */ + if (remain >= MINCLSIZE) { + n = m_getcl(how, m->m_type, 0); + nsize = MCLBYTES; + } else { + n = m_get(how, m->m_type); + nsize = MLEN; + } + if (n == NULL) + goto nospace; + + if (top == NULL) { /* First one, must be PKTHDR */ + if (!m_dup_pkthdr(n, m, how)) { + m_free(n); + goto nospace; + } + if ((n->m_flags & M_EXT) == 0) + nsize = MHLEN; + } + n->m_len = 0; + + /* Link it into the new chain */ + *p = n; + p = &n->m_next; + + /* Copy data from original mbuf(s) into new mbuf */ + while (n->m_len < nsize && m != NULL) { + int chunk = min(nsize - n->m_len, m->m_len - moff); + + bcopy(m->m_data + moff, n->m_data + n->m_len, chunk); + moff += chunk; + n->m_len += chunk; + remain -= chunk; + if (moff == m->m_len) { + m = m->m_next; + moff = 0; + } + } + + /* Check correct total mbuf length */ + KASSERT((remain > 0 && m != NULL) || (remain == 0 && m == NULL), + ("%s: bogus m_pkthdr.len", __func__)); + } + return (top); + +nospace: + m_freem(top); + return (NULL); +} + + +/* + * Duplicate "from"'s mbuf pkthdr in "to". + * "from" must have M_PKTHDR set, and "to" must be empty. + * In particular, this does a deep copy of the packet tags. + */ +int +m_dup_pkthdr(struct mbuf *to, struct mbuf *from, int how) +{ + to->m_flags = (from->m_flags & M_COPYFLAGS) | (to->m_flags & M_EXT); + if ((to->m_flags & M_EXT) == 0) + to->m_data = to->m_pktdat; + to->m_pkthdr = from->m_pkthdr; + return (0); +} diff --git a/ip_fil_solaris.c b/ip_fil_solaris.c new file mode 100644 index 0000000000000..70c4027e6d397 --- /dev/null +++ b/ip_fil_solaris.c @@ -0,0 +1,1550 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ +#if !defined(lint) +static const char sccsid[] = "%W% %G% (C) 1993-2000 Darren Reed"; +static const char rcsid[] = "@(#)$Id$"; +#endif + +#include <sys/types.h> +#include <sys/errno.h> +#include <sys/param.h> +#include <sys/cpuvar.h> +#include <sys/open.h> +#include <sys/ioctl.h> +#include <sys/filio.h> +#include <sys/systm.h> +#if SOLARIS2 >= 10 +# include <sys/cred_impl.h> +#else +# include <sys/cred.h> +#endif +#include <sys/ddi.h> +#include <sys/sunddi.h> +#include <sys/ksynch.h> +#include <sys/kmem.h> +#include <sys/mkdev.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/dditypes.h> +#include <sys/cmn_err.h> +#include <net/if.h> +#include <net/af.h> +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/ip_var.h> +#include <netinet/tcp.h> +#include <netinet/udp.h> +#include <netinet/tcpip.h> +#include <netinet/ip_icmp.h> +#include "netinet/ip_compat.h" +#ifdef USE_INET6 +# include <netinet/icmp6.h> +#endif +#include "netinet/ip_fil.h" +#include "netinet/ip_nat.h" +#include "netinet/ip_frag.h" +#include "netinet/ip_state.h" +#include "netinet/ip_auth.h" +#include "netinet/ip_proxy.h" +#include "netinet/ip_lookup.h" +#include "netinet/ip_dstlist.h" +#include <inet/ip_ire.h> + +#ifdef HAS_SYS_MD5_H +# include <sys/md5.h> +#else +# include "md5.h" +#endif + +static int ipf_send_ip __P((fr_info_t *fin, mblk_t *m)); +static void ipf_fixl4sum __P((fr_info_t *)); +static void *ipf_routeto __P((fr_info_t *, int, void *)); +static int ipf_sendpkt __P((ipf_main_softc_t *, int, void *, mblk_t *, + struct ip *, void *)); +static void ipf_call_slow_timer __P((ipf_main_softc_t *)); +#if (SOLARIS2 < 7) +static void ipf_timer_func __P((void)); +#else +static void ipf_timer_func __P((void *)); +#endif + +static u_short ipid = 0; +#if !defined(FW_HOOKS) +# if SOLARIS2 >= 7 +u_int *ip_ttl_ptr = NULL; +u_int *ip_mtudisc = NULL; +# if SOLARIS2 >= 8 +int *ip_forwarding = NULL; +u_int *ip6_forwarding = NULL; +# else +u_int *ip_forwarding = NULL; +# endif +# else +u_long *ip_ttl_ptr = NULL; +u_long *ip_mtudisc = NULL; +u_long *ip_forwarding = NULL; +# endif +extern ipf_main_softc_t ipfmain; +#else +extern void ipf_attach_hooks __P((ipf_main_softc_t *)); +extern void ipf_detach_hooks __P((ipf_main_softc_t *)); +#endif + + +/* ------------------------------------------------------------------------ */ +/* Function: ipfdetach */ +/* Returns: int - 0 == success, else error. */ +/* Parameters: Nil */ +/* */ +/* This function is responsible for undoing anything that might have been */ +/* done in a call to ipfattach(). It must be able to clean up from a call */ +/* to ipfattach() that did not succeed. Why might that happen? Someone */ +/* configures a table to be so large that we cannot allocate enough memory */ +/* for it. */ +/* ------------------------------------------------------------------------ */ +int +ipfdetach(softc) + ipf_main_softc_t *softc; +{ + +#if !defined(FW_HOOKS) + if (softc->ipf_control_forwarding & 2) { + if (ip_forwarding != NULL) + *ip_forwarding = 0; +# if SOLARIS2 >= 8 + if (ip6_forwarding != NULL) + *ip6_forwarding = 0; +# endif + } + + ipf_pfil_hooks_remove(); +#else + ipf_detach_hooks(softc); +#endif + + if (softc->ipf_slow_ch != 0) { + (void) untimeout(softc->ipf_slow_ch); + softc->ipf_slow_ch = 0; + } + +#ifdef IPFDEBUG + cmn_err(CE_CONT, "ipfdetach()\n"); +#endif + + if (ipf_fini_all(softc) < 0) + return EIO; + + return 0; +} + + +int +ipfattach(softc) + ipf_main_softc_t *softc; +{ + int i; + +#ifdef IPFDEBUG + cmn_err(CE_CONT, "ipfattach()\n"); +#endif + +#if !defined(FW_HOOKS) +# if SOLARIS2 >= 8 + ip_forwarding = &ip_g_forward; +# endif + /* + * XXX - There is no terminator for this array, so it is not possible + * to tell if what we are looking for is missing and go off the end + * of the array. + */ + +# if SOLARIS2 <= 8 + for (i = 0; ; i++) { + if (!strcmp(ip_param_arr[i].ip_param_name, "ip_def_ttl")) { + ip_ttl_ptr = &ip_param_arr[i].ip_param_value; + } else if (!strcmp(ip_param_arr[i].ip_param_name, + "ip_path_mtu_discovery")) { + ip_mtudisc = &ip_param_arr[i].ip_param_value; + } +# if SOLARIS2 < 8 + else if (!strcmp(ip_param_arr[i].ip_param_name, + "ip_forwarding")) { + ip_forwarding = &ip_param_arr[i].ip_param_value; + } +# else + else if (!strcmp(ip_param_arr[i].ip_param_name, + "ip6_forwarding")) { + ip6_forwarding = &ip_param_arr[i].ip_param_value; + } +# endif + + if (ip_mtudisc != NULL && ip_ttl_ptr != NULL && +# if SOLARIS2 >= 8 + ip6_forwarding != NULL && +# endif + ip_forwarding != NULL) + break; + } +# endif + + if (softc->ipf_control_forwarding & 1) { + if (ip_forwarding != NULL) + *ip_forwarding = 1; +# if SOLARIS2 >= 8 + if (ip6_forwarding != NULL) + *ip6_forwarding = 1; +# endif + } +#endif + + if (ipf_init_all(softc) < 0) + return EIO; + softc->ipf_slow_ch = timeout(ipf_timer_func, softc, + drv_usectohz(500000)); + +#if !defined(FW_HOOKS) + ipf_set_pfil_hooks(); +#else + ipf_attach_hooks(softc); +#endif + ipid = 0; + + return 0; +} + + +/* + * Filter ioctl interface. + */ +/*ARGSUSED*/ +int +ipfioctl(dev, cmd, data, mode, cp, rp) + dev_t dev; + int cmd; +#if SOLARIS2 >= 7 + intptr_t data; +#else + int *data; +#endif + int mode; + cred_t *cp; + int *rp; +{ + ipf_main_softc_t *softc; + int error = 0; + minor_t unit; + +#ifdef IPFDEBUG + cmn_err(CE_CONT, "ipfioctl(%x,%x,%x,%d,%x,%d)\n", + dev, cmd, data, mode, cp, rp); +#endif + unit = getminor(dev); + if (IPL_LOGMAX < unit) { + IPFERROR(130002); + return ENXIO; + } + + softc = GET_SOFTC(crgetzoneid(cp)); + + if (softc->ipf_running <= 0) { + if (unit != IPL_LOGIPF && cmd != SIOCIPFINTERROR) { + IPFERROR(130003); + return EIO; + } + if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET && + cmd != SIOCIPFSET && cmd != SIOCFRENB && + cmd != SIOCGETFS && cmd != SIOCGETFF && + cmd != SIOCIPFINTERROR) { + IPFERROR(130004); + return EIO; + } + } + + error = ipf_ioctlswitch(softc, unit, (caddr_t)data, cmd, mode, + cp->cr_uid, curproc); + if (error != -1) { + return error; + } + + return error; +} + + +void * +get_unit(soft, name, family) + void *soft; + char *name; + int family; +{ + void *ifp; +#if !defined(FW_HOOKS) + qif_t *qf; + int sap; + + if (family == 4) + sap = 0x0800; + else if (family == 6) + sap = 0x86dd; + else + return NULL; + rw_enter(&pfil_rw, RW_READER); + qf = qif_iflookup(name, sap); + rw_exit(&pfil_rw); + return qf; +#else + ipf_main_softc_t *softc = soft; + net_handle_t proto; + + if (family == 0) { + ifp = (void *)net_phylookup(softc->ipf_nd_v4, name); + if (ifp == NULL) + ifp = (void *)net_phylookup(softc->ipf_nd_v6, name); + return ifp; + } + if (family == 4) + proto = softc->ipf_nd_v4; + else if (family == 6) + proto = softc->ipf_nd_v6; + else + return NULL; + return (void *)net_phylookup(proto, name); +#endif +} + + +/* + * ipf_send_reset - this could conceivably be a call to tcp_respond(), but + * that requires a large amount of setting up and isn't any more efficient. + */ +int +ipf_send_reset(fr_info_t *fin) +{ + tcphdr_t *tcp, *tcp2; + int tlen, hlen; + mblk_t *m; +#ifdef USE_INET6 + ip6_t *ip6; +#endif + ip_t *ip; + + tcp = fin->fin_dp; + if (tcp->th_flags & TH_RST) + return -1; + + if (ipf_checkl4sum(fin) == -1) + return -1; + + tlen = (tcp->th_flags & (TH_SYN|TH_FIN)) ? 1 : 0; +#ifdef USE_INET6 + if (fin->fin_v == 6) + hlen = sizeof(ip6_t); + else +#endif + hlen = sizeof(ip_t); + hlen += sizeof(*tcp2); + if ((m = (mblk_t *)allocb(hlen + 64, BPRI_HI)) == NULL) + return -1; + + m->b_rptr += 64; + MTYPE(m) = M_DATA; + m->b_wptr = m->b_rptr + hlen; + ip = (ip_t *)m->b_rptr; + bzero((char *)ip, hlen); + tcp2 = (struct tcphdr *)(m->b_rptr + hlen - sizeof(*tcp2)); + tcp2->th_dport = tcp->th_sport; + tcp2->th_sport = tcp->th_dport; + 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(struct tcphdr) >> 2; + + ip->ip_v = fin->fin_v; +#ifdef USE_INET6 + if (fin->fin_v == 6) { + ip6 = (ip6_t *)m->b_rptr; + ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; + ip6->ip6_src = fin->fin_dst6.in6; + ip6->ip6_dst = fin->fin_src6.in6; + ip6->ip6_plen = htons(sizeof(*tcp)); + ip6->ip6_nxt = IPPROTO_TCP; + } else +#endif + { + ip->ip_src.s_addr = fin->fin_daddr; + ip->ip_dst.s_addr = fin->fin_saddr; + ip->ip_id = ipf_nextipid(fin); + ip->ip_hl = sizeof(*ip) >> 2; + ip->ip_p = IPPROTO_TCP; + ip->ip_len = htons(sizeof(*ip) + sizeof(*tcp)); + ip->ip_tos = fin->fin_ip->ip_tos; + } + return ipf_send_ip(fin, m); +} + + +/*ARGSUSED*/ +static int +ipf_send_ip(fr_info_t *fin, mblk_t *m) +{ +#if !defined(FW_HOOKS) + qif_t *qif; +#endif + qpktinfo_t qpi, *qpip; + fr_info_t fnew; + ip_t *ip; + int i, hlen; + + ip = (ip_t *)m->b_rptr; + bzero((char *)&fnew, sizeof(fnew)); + fnew.fin_main_soft = fin->fin_main_soft; + +#ifdef USE_INET6 + if (fin->fin_v == 6) { + ip6_t *ip6; + + ip6 = (ip6_t *)ip; + ip6->ip6_vfc = 0x60; + ip6->ip6_hlim = 127; + fnew.fin_p = ip6->ip6_nxt; + fnew.fin_v = 6; + hlen = sizeof(*ip6); + fnew.fin_plen = ntohs(ip6->ip6_plen) + hlen; + } else +#endif + { + fnew.fin_v = 4; +#if !defined(FW_HOOKS) + if (ip_ttl_ptr != NULL) + ip->ip_ttl = (u_char)(*ip_ttl_ptr); + else +#endif + ip->ip_ttl = 63; +#if !defined(FW_HOOKS) + if (ip_mtudisc != NULL) + ip->ip_off = htons(*ip_mtudisc ? IP_DF : 0); + else +#endif + ip->ip_off = htons(IP_DF); + fnew.fin_p = ip->ip_p; + fnew.fin_plen = ntohs(ip->ip_len); + ip->ip_sum = ipf_cksum((u_short *)ip, sizeof(*ip)); + hlen = sizeof(*ip); + } + + qpip = fin->fin_qpi; + qpi.qpi_q = qpip->qpi_q; + qpi.qpi_off = 0; +#if defined(FW_HOOKS) + qpi.qpi_real = qpip->qpi_real; + qpi.qpi_ill = qpip->qpi_real; +#else + qif = qpip->qpi_real; + qpi.qpi_real = qif; + qpi.qpi_ill = qif->qf_ill; + qpi.qpi_flags = qif->qf_flags; +#endif + qpi.qpi_m = m; + qpi.qpi_data = ip; + fnew.fin_qpi = &qpi; + fnew.fin_ifp = fin->fin_ifp; + fnew.fin_flx = FI_NOCKSUM; + fnew.fin_m = m; + fnew.fin_qfm = m; + fnew.fin_ip = ip; + fnew.fin_mp = &m; + fnew.fin_hlen = hlen; + fnew.fin_dp = (char *)ip + hlen; + if (fnew.fin_p == IPPROTO_TCP) { + tcphdr_t *tcp2 = fnew.fin_dp; + tcp2->th_sum = fr_cksum(&fnew, ip, IPPROTO_TCP, tcp2); + } + if (ipf_makefrip(hlen, ip, &fnew) == -1) + return -1; + + if (fin->fin_fr != NULL && fin->fin_fr->fr_type == FR_T_IPF) { + frdest_t *fdp = &fin->fin_fr->fr_rif; + + if ((fdp->fd_ptr != NULL) && + (fdp->fd_ptr != (struct ifnet *)-1)) + return ipf_fastroute(m, &m, &fnew, fdp); + } + + i = ipf_fastroute(m, &m, &fnew, NULL); + return i; +} + + +int +ipf_send_icmp_err(int type, fr_info_t *fin, int dst) +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + struct in_addr dst4; + struct icmp *icmp; + qpktinfo_t *qpi; + int hlen, code; + i6addr_t dst6; + u_short sz; +#ifdef USE_INET6 + mblk_t *mb; +#endif + mblk_t *m; +#ifdef USE_INET6 + ip6_t *ip6; +#endif + ip_t *ip; + + if ((type < 0) || (type > ICMP_MAXTYPE)) + return -1; + + code = fin->fin_icode; +#ifdef USE_INET6 + if ((code < 0) || (code > sizeof(icmptoicmp6unreach)/sizeof(int))) + return -1; +#endif + + if (ipf_checkl4sum(fin) == -1) + return -1; + + qpi = fin->fin_qpi; + +#ifdef USE_INET6 + mb = fin->fin_qfm; + + if (fin->fin_v == 6) { + sz = sizeof(ip6_t); + sz += MIN(mb->b_wptr - mb->b_rptr, 512); + hlen = sizeof(ip6_t); + type = icmptoicmp6types[type]; + if (type == ICMP6_DST_UNREACH) + code = icmptoicmp6unreach[code]; + } else +#endif + { + if ((fin->fin_p == IPPROTO_ICMP) && !(fin->fin_flx & FI_SHORT)) + switch (ntohs(fin->fin_data[0]) >> 8) + { + case ICMP_ECHO : + case ICMP_TSTAMP : + case ICMP_IREQ : + case ICMP_MASKREQ : + break; + default : + return 0; + } + + sz = sizeof(ip_t) * 2; + sz += 8; /* 64 bits of data */ + hlen = sizeof(ip_t); + } + + sz += offsetof(struct icmp, icmp_ip); + if ((m = (mblk_t *)allocb((size_t)sz + 64, BPRI_HI)) == NULL) + return -1; + MTYPE(m) = M_DATA; + m->b_rptr += 64; + m->b_wptr = m->b_rptr + sz; + bzero((char *)m->b_rptr, (size_t)sz); + ip = (ip_t *)m->b_rptr; + ip->ip_v = fin->fin_v; + icmp = (struct icmp *)(m->b_rptr + hlen); + icmp->icmp_type = type & 0xff; + icmp->icmp_code = code & 0xff; +#ifdef icmp_nextmtu + if (type == ICMP_UNREACH && fin->fin_icode == ICMP_UNREACH_NEEDFRAG) { + if (fin->fin_mtu != 0) { + icmp->icmp_nextmtu = htons(fin->fin_mtu); + + } else if (GETIFMTU_4(qpi->qpi_real) != 0) { + icmp->icmp_nextmtu = GETIFMTU_4(qpi->qpi_real); + + } else { /* Make up a number */ + icmp->icmp_nextmtu = htons(fin->fin_plen - 20); + } + } +#endif + +#ifdef USE_INET6 + if (fin->fin_v == 6) { + int csz; + + if (dst == 0) { + if (ipf_ifpaddr(softc, 6, FRI_NORMAL, qpi->qpi_real, + &dst6, NULL) == -1) { + FREE_MB_T(m); + return -1; + } + } else + dst6 = fin->fin_dst6; + + csz = sz; + sz -= sizeof(ip6_t); + ip6 = (ip6_t *)m->b_rptr; + ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; + ip6->ip6_plen = htons((u_short)sz); + ip6->ip6_nxt = IPPROTO_ICMPV6; + ip6->ip6_src = dst6.in6; + ip6->ip6_dst = fin->fin_src6.in6; + sz -= offsetof(struct icmp, icmp_ip); + bcopy((char *)mb->b_rptr, (char *)&icmp->icmp_ip, sz); + icmp->icmp_cksum = csz - sizeof(ip6_t); + } else +#endif + { + ip->ip_hl = sizeof(*ip) >> 2; + ip->ip_p = IPPROTO_ICMP; + ip->ip_id = fin->fin_ip->ip_id; + ip->ip_tos = fin->fin_ip->ip_tos; + ip->ip_len = (u_short)sz; + if (dst == 0) { + if (ipf_ifpaddr(softc, 4, FRI_NORMAL, qpi->qpi_real, + &dst6, NULL) == -1) { + FREE_MB_T(m); + return -1; + } + dst4 = dst6.in4; + } else + dst4 = fin->fin_dst; + ip->ip_src = dst4; + ip->ip_dst = fin->fin_src; + bcopy((char *)fin->fin_ip, (char *)&icmp->icmp_ip, + sizeof(*fin->fin_ip)); + bcopy((char *)fin->fin_ip + fin->fin_hlen, + (char *)&icmp->icmp_ip + sizeof(*fin->fin_ip), 8); + icmp->icmp_cksum = ipf_cksum((u_short *)icmp, + sz - sizeof(ip_t)); + } + + /* + * Need to exit out of these so we don't recursively call rw_enter + * from fr_qout. + */ + return ipf_send_ip(fin, m); +} + + +#if !defined(FW_HOOKS) +/* + * return the first IP Address associated with an interface + */ +/*ARGSUSED*/ +int +ipf_ifpaddr(softc, v, atype, qifptr, inp, inpmask) + ipf_main_softc_t *softc; + int v; + int atype; + void *qifptr; + i6addr_t *inp, *inpmask; +{ +# ifdef USE_INET6 + struct sockaddr_in6 sin6, mask6; +# endif + struct sockaddr_in sin, mask; + qif_t *qif; + + if ((qifptr == NULL) || (qifptr == (void *)-1)) + return -1; + + qif = qifptr; + if (qif->qf_ill == NULL) + return -1; + +# ifdef USE_INET6 + if (v == 6) { + in6_addr_t *inp6; + ipif_t *ipif; + ill_t *ill; + + ill = qif->qf_ill; + + /* + * First is always link local. + */ + for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) { + inp6 = &ipif->ipif_v6lcl_addr; + if (!IN6_IS_ADDR_LINKLOCAL(inp6) && + !IN6_IS_ADDR_LOOPBACK(inp6)) + break; + } + if (ipif == NULL) + return -1; + + mask6.sin6_addr = ipif->ipif_v6net_mask; + if (atype == FRI_BROADCAST) + sin6.sin6_addr = ipif->ipif_v6brd_addr; + else if (atype == FRI_PEERADDR) + sin6.sin6_addr = ipif->ipif_v6pp_dst_addr; + else + sin6.sin6_addr = *inp6; + return ipf_ifpfillv6addr(atype, &sin6, &mask6, inp, inpmask); + } +# endif + + if (((ill_t *)qif->qf_ill)->ill_ipif == NULL) + return -1; + + switch (atype) + { + case FRI_BROADCAST : + sin.sin_addr.s_addr = QF_V4_BROADCAST(qif); + break; + case FRI_PEERADDR : + sin.sin_addr.s_addr = QF_V4_PEERADDR(qif); + break; + default : + sin.sin_addr.s_addr = QF_V4_ADDR(qif); + break; + } + mask.sin_addr.s_addr = QF_V4_NETMASK(qif); + + return ipf_ifpfillv4addr(atype, &sin, &mask, &inp->in4, &inpmask->in4); +} +#else +/*ARGSUSED*/ +int +ipf_ifpaddr(softc, v, atype, qifptr, inp, inpmask) + ipf_main_softc_t *softc; + int v; + int atype; + void *qifptr; + i6addr_t *inp, *inpmask; +{ + struct sockaddr_in6 sin6[2]; + struct sockaddr_in sin[2]; + net_ifaddr_t types[2]; + void *array; + int error; + + if ((qifptr == NULL) || (qifptr == (void *)-1)) + return -1; + + switch (atype) + { + case FRI_BROADCAST : + types[0] = NA_BROADCAST; + break; + case FRI_PEERADDR : + types[0] = NA_PEER; + break; + default : + types[0] = NA_ADDRESS; + break; + } + types[1] = NA_NETMASK; + + if (v == 4) { + int logical = 0; + + array = sin; + do { + error = net_getlifaddr(softc->ipf_nd_v4, + (phy_if_t)qifptr, logical, + 2, types, sin); + logical++; + } while (types[0] == NA_ADDRESS && error == 0 && + sin[0].sin_addr.s_addr == 0); + if (sin[0].sin_addr.s_addr == 0 && error != 0) + return error; + } else { + array = sin6; + net_getlifaddr(softc->ipf_nd_v6, (phy_if_t)qifptr, 0, + 2, types, sin6); + } + + if (v == 6) + return ipf_ifpfillv6addr(atype, &sin6[0], &sin6[1], + inp, inpmask); + + return ipf_ifpfillv4addr(atype, &sin[0], &sin[1], + &inp->in4, &inpmask->in4); +} +#endif + + +u_32_t +ipf_newisn(fr_info_t *fin) +{ + static int iss_seq_off = 0; + ipf_main_softc_t *softc = fin->fin_main_soft; + u_char hash[16]; + u_32_t newiss; + MD5_CTX ctx; + + /* + * Compute the base value of the ISS. It is a hash + * of (saddr, sport, daddr, dport, secret). + */ + MD5Init(&ctx); + + MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, + sizeof(fin->fin_fi.fi_src)); + MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, + sizeof(fin->fin_fi.fi_dst)); + MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); + + MD5Update(&ctx, softc->ipf_iss_secret, sizeof(softc->ipf_iss_secret)); + + MD5Final(hash, &ctx); + + bcopy(hash, &newiss, sizeof(newiss)); + + /* + * Now increment our "timer", and add it in to + * the computed value. + * + * XXX Use `addin'? + * XXX TCP_ISSINCR too large to use? + */ + iss_seq_off += 0x00010000; + newiss += iss_seq_off; + return newiss; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nextipid */ +/* Returns: int - 0 == success, -1 == error (packet should be droppped) */ +/* Parameters: fin(I) - pointer to packet information */ +/* */ +/* Returns the next IPv4 ID to use for this packet. */ +/* ------------------------------------------------------------------------ */ +u_short +ipf_nextipid(fr_info_t *fin) +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + ipstate_t *is; + nat_t *nat; + u_short id; + + MUTEX_ENTER(&softc->ipf_rw); + if (fin->fin_pktnum != 0) { + /* + * The -1 is for aligned test results. + */ + id = (fin->fin_pktnum - 1) & 0xffff; + id = ipid++; + } else { + id = ipid++; + } + MUTEX_EXIT(&softc->ipf_rw); + + return id; +} + + +INLINE int +ipf_checkv4sum(fr_info_t *fin) +{ +#if defined(NET_HCK_L4_FULL) + ipf_main_softc_t *softc = fin->fin_main_soft; +#endif + int ckbits; + + if ((fin->fin_flx & FI_NOCKSUM) != 0) + return 0; + + if ((fin->fin_flx & FI_SHORT) != 0) + return 1; + + if (fin->fin_cksum != FI_CK_NEEDED) + return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; + +#if defined(NET_HCK_L4_FULL) + ckbits = net_ispartialchecksum(softc->ipf_nd_v4, fin->fin_m); + if (ckbits & NET_HCK_L4_FULL) { + fin->fin_cksum = FI_CK_L4FULL; + return 0; + } else if (ckbits & NET_HCK_L4_PART) { + fin->fin_cksum = FI_CK_L4PART; + return 0; + } +#endif +#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) && defined(ICK_VALID) + if (dohwcksum && ((*fin->fin_mp)->b_ick_flag == ICK_VALID)) { + fin->fin_cksum = FI_CK_SUMOK; + return 0; + } +#endif + + if (ipf_checkl4sum(fin) == -1) { + DT1(bad_l4_sum, fr_info_t *, fin); + fin->fin_flx |= FI_BAD; + return -1; + } + return 0; +} + + +#ifdef USE_INET6 +INLINE int +ipf_checkv6sum(fr_info_t *fin) +{ +#if defined(NET_HCK_L4_FULL) + ipf_main_softc_t *softc = fin->fin_main_soft; +#endif + int ckbits; + + if ((fin->fin_flx & FI_NOCKSUM) != 0) + return 0; + + if ((fin->fin_flx & FI_SHORT) != 0) + return 1; + + if (fin->fin_cksum != FI_CK_NEEDED) + return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; + +#if defined(NET_HCK_L4_FULL) + ckbits = net_ispartialchecksum(softc->ipf_nd_v6, fin->fin_m); + if (ckbits & NET_HCK_L4_FULL) { + fin->fin_cksum = FI_CK_L4FULL; + return 0; + } else if (ckbits & NET_HCK_L4_PART) { + fin->fin_cksum = FI_CK_L4PART; + return 0; + } +#endif + + if (ipf_checkl4sum(fin) == -1) { + DT1(bad_l4_sum, fr_info_t *, fin); + fin->fin_flx |= FI_BAD; + return -1; + } + return 0; +} +#endif /* USE_INET6 */ + + +#if !defined(FW_HOOKS) +/* + * Function: ipf_verifysrc + * Returns: int (really boolean) + * Parameters: fin - packet information + * + * Check whether the packet has a valid source address for the interface on + * which the packet arrived, implementing the "ipf_chksrc" feature. + * Returns true iff the packet's source address is valid. + * Pre-Solaris 10, we call into the routing code to make the determination. + * On Solaris 10 and later, we have a valid address set from pfild to check + * against. + */ +int +ipf_verifysrc(fin) + fr_info_t *fin; +{ + ire_t *dir; + int result; + +#if SOLARIS2 >= 6 + dir = ire_route_lookup(fin->fin_saddr, 0xffffffff, 0, 0, NULL, + NULL, NULL, +# ifdef IP_ULP_OUT_LABELED + NULL, +# endif + MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT| + MATCH_IRE_RECURSIVE); +#else + dir = ire_lookup(fin->fin_saddr); +#endif + + if (!dir) + return 0; + result = (ire_to_ill(dir) == fin->fin_ifp); +#if SOLARIS2 >= 8 + ire_refrele(dir); +#endif + return result; +} +#else +int +ipf_verifysrc(fin) + fr_info_t *fin; +{ + int result; + + result = (ipf_routeto(fin, fin->fin_v, &fin->fin_src) == fin->fin_ifp); + return result; +} +#endif + + +#if (SOLARIS2 < 7) +static void +ipf_timer_func() +{ + ipf_call_slow_timer(&ipfmain); +} +#else +void +/*ARGSUSED*/ +ipf_timer_func(ptr) + void *ptr; +{ + ipf_call_slow_timer(ptr); +} +#endif + +static void +ipf_call_slow_timer(softc) + ipf_main_softc_t *softc; +{ + READ_ENTER(&softc->ipf_global); + + if (softc->ipf_running > 0) + ipf_slowtimer(softc); + + if (softc->ipf_running == -1 || softc->ipf_running == 1) + softc->ipf_slow_ch = timeout(ipf_timer_func, softc, + drv_usectohz(500000)); + else + softc->ipf_slow_ch = NULL; + RWLOCK_EXIT(&softc->ipf_global); +} + + +/* + * Function: ipf_fastroute + * Returns: 0: success; + * -1: failed + * Parameters: + * mb: the message block where ip head starts + * mpp: the pointer to the pointer of the orignal + * packet message + * fin: packet information + * fdp: destination interface information + * if it is NULL, no interface information provided. + * + * This function is for fastroute/to/dup-to rules. It calls + * pfil_make_lay2_packet to search route, make lay-2 header + * ,and identify output queue for the IP packet. + * The destination address depends on the following conditions: + * 1: for fastroute rule, fdp is passed in as NULL, so the + * destination address is the IP Packet's destination address + * 2: for to/dup-to rule, if an ip address is specified after + * the interface name, this address is the as destination + * address. Otherwise IP Packet's destination address is used + */ +int +ipf_fastroute(mb, mpp, fin, fdp) + mblk_t *mb, **mpp; + fr_info_t *fin; + frdest_t *fdp; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + struct in_addr dst; + qpktinfo_t *qpi; + frdest_t node; + frentry_t *fr; + frdest_t fd; + void *dstp; + void *sifp; + void *ifp; + ip_t *ip; +#ifndef sparc + u_short __iplen, __ipoff; +#endif +#ifdef USE_INET6 + ip6_t *ip6 = (ip6_t *)fin->fin_ip; + struct in6_addr dst6; +#endif + + fr = fin->fin_fr; + ip = fin->fin_ip; + qpi = fin->fin_qpi; + + if ((fr != NULL) && !(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) && + (fdp->fd_type == FRD_DSTLIST)) { + if (ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node) == 0) + fdp = &node; + } + + /* + * If this is a duplicate mblk then we want ip to point at that + * data, not the original, if and only if it is already pointing at + * the current mblk data. + */ + if (ip == (ip_t *)qpi->qpi_m->b_rptr && qpi->qpi_m != mb) + ip = (ip_t *)mb->b_rptr; + + /* + * If there is another M_PROTO, we don't want it + */ + if (*mpp != mb) { + mblk_t *mp; + + mp = unlinkb(*mpp); + freeb(*mpp); + *mpp = mp; + } + + /* + * If the fdp is NULL then there is no set route for this packet. + */ + if (fdp == NULL) { + ifp = fin->fin_ifp; + + switch (fin->fin_v) + { + case 4 : + fd.fd_ip = ip->ip_dst; + ifp = ipf_routeto(fin, 4, &ip->ip_dst); + break; +#ifdef USE_INET6 + case 6 : + fd.fd_ip6.in6 = ip6->ip6_dst; + ifp = ipf_routeto(fin, 6, &ip6->ip6_dst); + break; +#endif + } + fdp = &fd; + } else { + ifp = fdp->fd_ptr; + + if (ifp == NULL || ifp == (void *)-1) + goto bad_fastroute; + } + + /* + * In case we're here due to "to <if>" being used with + * "keep state", check that we're going in the correct + * direction. + */ + if ((fr != NULL) && (fin->fin_rev != 0)) { + if ((ifp != NULL) && (fdp == &fr->fr_tif)) + return -1; + dst.s_addr = fin->fin_fi.fi_daddr; + } else { + if (fin->fin_v == 4) { + if (fdp->fd_ip.s_addr != 0) + dst = fdp->fd_ip; + else + dst.s_addr = fin->fin_fi.fi_daddr; + dstp = &dst; + } +#ifdef USE_INET6 + else if (fin->fin_v == 6) { + if (IP6_NOTZERO(&fdp->fd_ip)) + dst6 = fdp->fd_ip6.in6; + else + dst6 = fin->fin_dst6.in6; + } +#endif + } + + /* + * For input packets which are being "fastrouted", they won't + * go back through output filtering and miss their chance to get + * NAT'd and counted. Duplicated packets aren't considered to be + * part of the normal packet stream, so do not NAT them or pass + * them through stateful checking, etc. + */ + if ((fdp != &fr->fr_dif) && (fin->fin_out == 0)) { + sifp = fin->fin_ifp; + fin->fin_ifp = ifp; + fin->fin_out = 1; + (void) ipf_acctpkt(fin, NULL); + fin->fin_fr = NULL; + if (!fr || !(fr->fr_flags & FR_RETMASK)) { + u_32_t pass; + + (void) ipf_state_check(fin, &pass); + } + + switch (ipf_nat_checkout(fin, NULL)) + { + case 0 : + break; + case 1 : + ip->ip_sum = 0; + break; + case -1 : + goto bad_fastroute; + break; + } + + fin->fin_out = 0; + fin->fin_ifp = sifp; + } else if (fin->fin_out == 1) { +#if SOLARIS2 >= 6 + /* + * We're taking a packet from an interface and putting it on + * another interface. There's no guarantee that the other + * interface will have the same capabilities, so disable + * any flags that are set and do things manually for both + * IP and TCP/UDP + */ + if (mb->b_datap->db_struioflag) { + mb->b_datap->db_struioflag = 0; + + if (fin->fin_v == 4) { + ip->ip_sum = 0; + ip->ip_sum = ipf_cksum((u_short *)ip, + sizeof(*ip)); + } + ipf_fixl4sum(fin); + } +#endif + } + +#ifndef sparc + if (fin->fin_v == 4) { + __iplen = (u_short)ip->ip_len, + __ipoff = (u_short)ip->ip_off; + + ip->ip_len = htons(__iplen); + ip->ip_off = htons(__ipoff); + } +#endif + if (ipf_sendpkt(softc, 4, ifp, mb, ip, dstp) == 0) { + ATOMIC_INCL(softc->ipf_frouteok[0]); + } else { + ATOMIC_INCL(softc->ipf_frouteok[1]); + } + return 0; + +bad_fastroute: + ATOMIC_INCL(softc->ipf_frouteok[1]); + freemsg(mb); + return -1; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pullup */ +/* Returns: NULL == pullup failed, else pointer to protocol header */ +/* Parameters: xmin(I)- pointer to buffer where data packet starts */ +/* fin(I) - pointer to packet information */ +/* len(I) - number of bytes to pullup */ +/* */ +/* Attempt to move at least len bytes (from the start of the buffer) into a */ +/* single buffer for ease of access. Operating system native functions are */ +/* used to manage buffers - if necessary. If the entire packet ends up in */ +/* a single buffer, set the FI_COALESCE flag even though ipf_coalesce() has */ +/* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */ +/* and ONLY if the pullup succeeds. */ +/* */ +/* We assume that 'xmin' is a pointer to a buffer that is part of the chain */ +/* of buffers that starts at *fin->fin_mp. */ +/* ------------------------------------------------------------------------ */ +void * +ipf_pullup(mb_t *xmin, fr_info_t *fin, int len) +{ + qpktinfo_t *qpi = fin->fin_qpi; + int out = fin->fin_out, dpoff; + char *ip; + mb_t *m; + + if (xmin == NULL) + return NULL; + + ip = (char *)fin->fin_ip; + if ((fin->fin_flx & FI_COALESCE) != 0) + return ip; + + len += fin->fin_ipoff; + + if (M_LEN(xmin) < len) { + mblk_t *mnew = msgpullup(xmin, len); + + if (mnew == NULL) { + FREE_MB_T(*fin->fin_mp); + *fin->fin_mp = NULL; + fin->fin_m = NULL; + fin->fin_ip = NULL; + fin->fin_dp = NULL; + qpi->qpi_data = NULL; + return NULL; + } + + if (fin->fin_dp != NULL) + dpoff = (char *)fin->fin_dp - (char *)ip; + else + dpoff = 0; + + if (*fin->fin_mp == xmin) { + dblk_t *dt, *dm; + + /* + * These fields are not preserved by msgpullup and as + * they are used by hardware checksum code, preserving + * them is necessary or else the packet is dropped. + * This information is only stored in the first dblk + * in an mblk chain and because the change here is to + * how much data is in the dblk and not where the data + * is relative to the start of the dblk, copying the + * values is safe. + */ + dt = mnew->b_datap; + dm = xmin->b_datap; + dt->db_cksumstart = dm->db_cksumstart; + dt->db_cksumend = dm->db_cksumend; + dt->db_cksumstuff = dm->db_cksumstuff; + dt->db_struioun = dm->db_struioun; + freemsg(*fin->fin_mp); + *fin->fin_mp = mnew; + } else { + for (m = *fin->fin_mp; m != NULL; m = m->b_cont) + if (m->b_cont == xmin) + break; + freemsg(m->b_cont); + m->b_cont = mnew; + } + + fin->fin_qfm = mnew; + fin->fin_m = mnew; + ip = MTOD(mnew, char *) + fin->fin_ipoff; + if (fin->fin_dp != NULL) + fin->fin_dp = (char *)ip + dpoff; + if (fin->fin_fraghdr != NULL) + fin->fin_fraghdr = (char *)ip + + ((char *)fin->fin_fraghdr - + (char *)fin->fin_ip); + fin->fin_ip = (ip_t *)ip; + qpi->qpi_data = ip; + qpi->qpi_m = mnew; + } + + if (len == fin->fin_plen) + fin->fin_flx |= FI_COALESCE; + return ip; +} + + +int +ipf_inject(fr_info_t *fin, mb_t *m) +{ +#if !defined(FW_HOOKS) + qifpkt_t *qp; + + qp = kmem_alloc(sizeof(*qp), KM_NOSLEEP); + if (qp == NULL) { + freemsg(*fin->fin_mp); + return ENOMEM; + } + + qp->qp_mb = *fin->fin_mp; + if (fin->fin_v == 4) + qp->qp_sap = 0x800; + else if (fin->fin_v == 6) + qp->qp_sap = 0x86dd; + qp->qp_inout = fin->fin_out; + strncpy(qp->qp_ifname, fin->fin_ifname, LIFNAMSIZ); + qif_addinject(qp); +#else + ipf_main_softc_t *softc = fin->fin_main_soft; + struct sockaddr_in6 *sin6; + struct sockaddr_in *sin; + net_inject_t inject; + inject.ni_physical = (phy_if_t)fin->fin_ifp; + inject.ni_packet = *fin->fin_mp; + if (fin->fin_v == 4) { + sin = (struct sockaddr_in *)&inject.ni_addr; + sin->sin_family = AF_INET; + sin->sin_addr = fin->fin_dst; + if (fin->fin_out == 0) + return net_inject(softc->ipf_nd_v4, NI_QUEUE_IN, + &inject); + return net_inject(softc->ipf_nd_v4, NI_QUEUE_OUT, &inject); + } + + sin6 = (struct sockaddr_in6 *)&inject.ni_addr; + sin6->sin6_family = AF_INET6; + memcpy(&sin6->sin6_addr, &fin->fin_dst6, sizeof(fin->fin_dst6)); + if (fin->fin_out == 0) + return net_inject(softc->ipf_nd_v6, NI_QUEUE_IN, &inject); + return net_inject(softc->ipf_nd_v6, NI_QUEUE_OUT, &inject); +#endif +} + + +static int +ipf_sendpkt(softc, v, ifp, mb, ip, dstp) + ipf_main_softc_t *softc; + int v; + void *ifp; + mblk_t *mb; + struct ip *ip; + void *dstp; +{ +#if !defined(FW_HOOKS) + return pfil_sendbuf(ifp, mb, ip, dstp); +#else + struct sockaddr_in6 *sin6; + struct sockaddr_in *sin; + net_inject_t inject; + + inject.ni_physical = (phy_if_t)ifp; + inject.ni_packet = mb; + + if (v == 4) { + sin = (struct sockaddr_in *)&inject.ni_addr; + sin->sin_family = AF_INET; + memcpy(&sin->sin_addr, dstp, sizeof(sin->sin_addr)); + return net_inject(softc->ipf_nd_v4, NI_DIRECT_OUT, &inject); + } + + sin6 = (struct sockaddr_in6 *)&inject.ni_addr; + sin6->sin6_family = AF_INET6; + memcpy(&sin6->sin6_addr, dstp, sizeof(sin6->sin6_addr)); + return net_inject(softc->ipf_nd_v6, NI_DIRECT_OUT, &inject); +#endif +} + + +static void +ipf_fixl4sum(fr_info_t *fin) +{ + u_short *csump; + udphdr_t *udp; + + csump = NULL; + + switch (fin->fin_p) + { + case IPPROTO_TCP : + csump = &((tcphdr_t *)fin->fin_dp)->th_sum; + break; + + case IPPROTO_UDP : + udp = fin->fin_dp; + if (udp->uh_sum != 0) + csump = &udp->uh_sum; + break; + + default : + break; + } + + if (csump != NULL) { + *csump = 0; + *csump = fr_cksum(fin, fin->fin_ip, fin->fin_p, fin->fin_dp); + } +} + + +mblk_t * +allocmbt(size_t len) +{ + mblk_t *m; + + /* + * +64 is to reverse some token amount of space so that we + * might have a good chance of copying over data from the + * front of the existing IP packet to this one. + */ + m = allocb(len + 128, BPRI_HI); + if (m != NULL) { + m->b_rptr += 128; + m->b_wptr = m->b_rptr + len; + } + return m; +} + + +void +ipf_prependmbt(fr_info_t *fin, mblk_t *m) +{ + mblk_t *o = NULL, *top; + mblk_t *n = *fin->fin_mp; + qpktinfo_t *qpi; + int x; + + qpi = fin->fin_qpi; + qpi->qpi_m = m; + qpi->qpi_data = m->b_rptr; + + if (MTYPE(n) == M_DATA) { + /* + * The aim here is to copy x bytes of data from immediately + * preceding the IP packet in the original mblk to the new + * mblk that now precedes it. In doing this, b_rptr in the + * original packet is moved so that we don't transmit data + * that has been moved. + */ + x = min(fin->fin_ipoff, m->b_rptr - m->b_datap->db_base); + + if (x > 0) { + m->b_rptr -= x; + bcopy(n->b_rptr, m->b_rptr, x); + n->b_rptr += x; + } + } else { + /* + * If there are special mblk's at the start of the current + * message, free them so we can put our own there. It doesn't + * matter what they were as we're completely changing the + * nature of this packet. + */ + for (; n != fin->fin_m; n = o) { + o = n->b_cont; + n->b_cont = NULL; + freemsg(n); + } + } + + m->b_cont = n; + *fin->fin_mp = m; + fin->fin_m = m; +} + + +static void * +ipf_routeto(fin, v, dstip) + fr_info_t *fin; + int v; + void *dstip; +{ +#if defined(FW_HOOKS) + ipf_main_softc_t *softc = fin->fin_main_soft; + struct sockaddr_in6 sin6; + struct sockaddr_in sin; + struct sockaddr *sock; + net_handle_t proto; + int result; + + switch (fin->fin_v) + { + case 4 : + bzero((char *)&sin, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr = fin->fin_src; + sock = (struct sockaddr *)&sin; + proto = softc->ipf_nd_v4; + break; + + case 6 : + bzero((char *)&sin6, sizeof(sin6)); + sin6.sin6_family = AF_INET; + sin6.sin6_addr = fin->fin_srcip6; + proto = softc->ipf_nd_v6; + break; + default : + return NULL; + } + return (void *)net_routeto(proto, sock, NULL); +#else + return qif_illrouteto(v, dstip); +#endif +} + + +u_int +ipf_pcksum(fin, hlen, sum) + fr_info_t *fin; + int hlen; + u_int sum; +{ + u_int sum2; + + sum2 = ip_cksum(fin->fin_m, fin->fin_ipoff + hlen, sum); + sum2 = (~sum2 & 0xffff); + return sum2; +} diff --git a/ip_fil_sunos4.c b/ip_fil_sunos4.c new file mode 100644 index 0000000000000..901e200110218 --- /dev/null +++ b/ip_fil_sunos4.c @@ -0,0 +1,969 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ +#if defined(KERNEL) || defined(_KERNEL) +# undef KERNEL +# undef _KERNEL +# define KERNEL 1 +# define _KERNEL 1 +#endif +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/types.h> +#include <sys/file.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/systm.h> +#include <sys/dir.h> +#include <sys/mbuf.h> +#include <sys/protosw.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <net/af.h> +#include <net/route.h> +#include <netinet/in.h> +#include <netinet/in_var.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/ip_var.h> +#include <netinet/tcp.h> +#include <netinet/tcp_timer.h> +#include <netinet/udp.h> +#include <netinet/tcpip.h> +#include <netinet/ip_icmp.h> +#include "netinet/ip_compat.h" +#include "netinet/ip_fil.h" +#include "netinet/ip_nat.h" +#include "netinet/ip_frag.h" +#include "netinet/ip_state.h" +#include "netinet/ip_proxy.h" +#include "netinet/ip_auth.h" +#include "netinet/ip_sync.h" +#ifdef IPFILTER_SCAN +#include "netinet/ip_scan.h" +#endif +#include "netinet/ip_pool.h" +#include "md5.h" +#include <sys/kernel.h> +extern int ip_optcopy __P((struct ip *, struct ip *)); + +#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$"; +#endif + +extern struct protosw inetsw[]; +extern int ip_forwarding; + +static u_short ipid = 0; +static int (*ipf_savep) __P((ip_t *, int, void *, int, struct mbuf **)); +static int ipf_send_ip __P((fr_info_t *, mb_t *)); + + +#if defined(IPFILTER_LKM) +int +iplidentify(s) + char *s; +{ + if (strcmp(s, "ipl") == 0) + return 1; + return 0; +} +#endif /* IPFILTER_LKM */ + + +int +ipfattach() +{ + int s; + + SPL_NET(s); + if ((ipf_running > 0) || (ipf_checkp == ipf_check)) { + printf("IP Filter: already initialized\n"); + SPL_X(s); + return EBUSY; + } + + if (ipf_initialise() < 0) { + SPL_X(s); + return EIO; + } + + bzero((char *)ipfcache, sizeof(ipfcache)); + ipf_savep = ipf_checkp; + ipf_checkp = ipf_check; + + if (ipf_control_forwarding & 1) + ip_forwarding = 1; + + ipid = 0; + + SPL_X(s); + timeout(ipf_slowtimer, &ipfmain, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT); + return 0; +} + + +static void +ipf_timer_func(ptr) + void *ptr; +{ + ipf_main_softc_t *softc = ptr; + int s; + + SPL_NET(s); + + if (softc->ipf_running > 0) + ipf_slowtimer(softc); + + if (softc->ipf_running == -1 || softc->ipf_running == 1) + timeout(ipf_timer_func, &ipfmain, + (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT); + + SPL_X(s); +} + + +/* + * Disable the filter by removing the hooks from the IP input/output + * stream. + */ +int +ipfdetach() +{ + int s; + + SPL_NET(s); + + untimeout(ipf_slowtimer, &ipfmain); + + if (ipf_control_forwarding & 2) + ip_forwarding = 0; + + ipf_deinitialise(); + + if (ipf_savep != NULL) + ipf_checkp = ipf_savep; + ipf_savep = NULL; + + (void) ipf_flush(IPL_LOGIPF, FR_INQUE|FR_OUTQUE|FR_INACTIVE); + (void) ipf_flush(IPL_LOGIPF, FR_INQUE|FR_OUTQUE); + + SPL_X(s); + + return 0; +} + + +/* + * Filter ioctl interface. + */ +int +ipfioctl(dev, cmd, data, mode) + dev_t dev; + int cmd; + caddr_t data; + int mode; +{ + int error = 0, unit = 0; + SPL_INT(s); + + unit = GET_MINOR(dev); + if ((IPL_LOGMAX < unit) || (unit < 0)) { + ipfmain.ipf_interror = 130002; + return ENXIO; + } + + if (ipf_running <= 0) { + if (unit != IPL_LOGIPF && cmd != SIOCIPFINTERROR) { + ipfmain.ipf_interror = 130003; + return EIO; + } + if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET && + cmd != SIOCIPFSET && cmd != SIOCFRENB && + cmd != SIOCGETFS && cmd != SIOCGETFF && + cmd != SIOCIPFINTERROR) { + ipfmain.ipf_interror = 130004; + return EIO; + } + } + + SPL_NET(s); + + error = ipf_ioctlswitch(unit, data, cmd, mode, curproc->p_uid, curproc); + if (error != -1) { + SPL_X(s); + return error; + } + + SPL_X(s); + return error; +} + + +/* + * ipf_send_reset - this could conceivably be a call to tcp_respond(), but that + * requires a large amount of setting up and isn't any more efficient. + */ +int +ipf_send_reset(fin) + fr_info_t *fin; +{ + struct tcphdr *tcp, *tcp2; + int tlen = 0, hlen; + struct mbuf *m; + ip_t *ip; + + tcp = fin->fin_dp; + if (tcp->th_flags & TH_RST) + return -1; /* feedback loop */ + + if (ipf_checkl4sum(fin) == -1) + return -1; + + tlen = fin->fin_dlen - (TCP_OFF(tcp) << 2) + + ((tcp->th_flags & TH_SYN) ? 1 : 0) + + ((tcp->th_flags & TH_FIN) ? 1 : 0); + + MGET(m, M_DONTWAIT, MT_HEADER); + if (m == NULL) + return -1; + + hlen = sizeof(ip_t); + m->m_len = sizeof(*tcp2) + hlen; + ip = mtod(m, struct ip *); + bzero((char *)ip, hlen); + + tcp2 = (struct tcphdr *)((char *)ip + hlen); + tcp2->th_sport = tcp->th_dport; + tcp2->th_dport = tcp->th_sport; + + if (tcp->th_flags & TH_ACK) { + tcp2->th_seq = tcp->th_ack; + tcp2->th_flags = TH_RST; + tcp2->th_ack = 0; + } else { + tcp2->th_seq = 0; + 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_x2 = 0; + tcp2->th_win = tcp->th_win; + tcp2->th_sum = 0; + tcp2->th_urp = 0; + + ip->ip_p = IPPROTO_TCP; + ip->ip_len = htons(sizeof(struct tcphdr)); + ip->ip_src.s_addr = fin->fin_daddr; + ip->ip_dst.s_addr = fin->fin_saddr; + tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2)); + ip->ip_len = hlen + sizeof(*tcp2); + return ipf_send_ip(fin, m); +} + + +static int +ipf_send_ip(fin, m) + fr_info_t *fin; + mb_t *m; +{ + fr_info_t fnew; + ip_t *ip, *oip; + int hlen; + + ip = mtod(m, ip_t *); + bzero((char *)&fnew, sizeof(fnew)); + fnew.fin_main_soft = fin->fin_main_soft; + + IP_V_A(ip, fin->fin_v); + switch (fin->fin_v) + { + case 4 : + hlen = sizeof(*oip); + oip = fin->fin_ip; + fnew.fin_v = 4; + fnew.fin_p = ip->ip_p; + fnew.fin_plen = ntohs(ip->ip_len) + hlen; + IP_HL_A(ip, sizeof(*oip) >> 2); + ip->ip_tos = oip->ip_tos; + ip->ip_id = fin->fin_ip->ip_id; + ip->ip_off = 0; + ip->ip_ttl = tcp_ttl; + ip->ip_sum = 0; + break; + default : + return EINVAL; + } + + fnew.fin_ifp = fin->fin_ifp; + fnew.fin_flx = FI_NOCKSUM; + fnew.fin_m = m; + fnew.fin_ip = ip; + fnew.fin_mp = &m; + fnew.fin_hlen = hlen; + fnew.fin_dp = (char *)ip + hlen; + (void) ipf_makefrip(hlen, ip, &fnew); + + return ipf_fastroute(m, &m, &fnew, NULL); +} + + +int +ipf_send_icmp_err(type, fin, dst) + int type; + fr_info_t *fin; + int dst; +{ + int err, hlen = 0, xtra = 0, iclen, ohlen = 0, avail, code; + struct in_addr dst4; + struct icmp *icmp; + struct mbuf *m; + i6addr_t dst6; + void *ifp; + ip_t *ip, *ip2; + + if ((type < 0) || (type > ICMP_MAXTYPE)) + return -1; + + if (ipf_checkl4sum(fin) == -1) + return -1; + MGET(m, M_DONTWAIT, MT_HEADER); + if (m == NULL) + return -1; + avail = MLEN; + + code = fin->fin_icode; + + ifp = fin->fin_ifp; + if (fin->fin_v == 4) { + if ((fin->fin_p == IPPROTO_ICMP) && !(fin->fin_flx & FI_SHORT)) + switch (ntohs(fin->fin_data[0]) >> 8) + { + case ICMP_ECHO : + case ICMP_TSTAMP : + case ICMP_IREQ : + case ICMP_MASKREQ : + break; + default : + FREE_MB_T(m); + return 0; + } + + if (dst == 0) { + if (ipf_ifpaddr(&ipfmain, 4, FRI_NORMAL, ifp, + &dst6, NULL) == -1) { + FREE_MB_T(m); + return -1; + } + dst4 = dst6.in4; + } else + dst4.s_addr = fin->fin_daddr; + + hlen = sizeof(ip_t); + ohlen = fin->fin_hlen; + if (fin->fin_hlen < fin->fin_plen) + xtra = MIN(fin->fin_dlen, 8); + else + xtra = 0; + } else { + FREE_MB_T(m); + return -1; + } + + iclen = hlen + sizeof(*icmp) + xtra; + avail -= (m->m_off + iclen); + if (xtra > avail) + xtra = avail; + iclen += xtra; + if (avail < 0) { + FREE_MB_T(m); + return -1; + } + m->m_len = iclen; + ip = mtod(m, ip_t *); + icmp = (struct icmp *)((char *)ip + hlen); + ip2 = (ip_t *)&icmp->icmp_ip; + bzero((char *)ip, iclen); + + 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) { + if (fin->fin_mtu != 0) { + icmp->icmp_nextmtu = htons(fin->fin_mtu); + + } else if (ifp != NULL) { + icmp->icmp_nextmtu = htons(GETIFMTU_4(ifp)); + + } else { /* make up a number... */ + icmp->icmp_nextmtu = htons(fin->fin_plen - 20); + } + } +#endif + + bcopy((char *)fin->fin_ip, (char *)ip2, ohlen); + + ip2->ip_len = htons(ip2->ip_len); + ip2->ip_off = htons(ip2->ip_off); + + ip->ip_p = IPPROTO_ICMP; + ip->ip_src.s_addr = dst4.s_addr; + ip->ip_dst.s_addr = fin->fin_saddr; + + if (xtra > 0) + bcopy((char *)fin->fin_ip + fin->fin_hlen, + (char *)&icmp->icmp_ip + fin->fin_hlen, xtra); + icmp->icmp_cksum = ipf_cksum((u_short *)icmp, sizeof(*icmp) + 8); + ip->ip_len = iclen; + ip->ip_p = IPPROTO_ICMP; + err = ipf_send_ip(fin, m); + return err; +} + + +#if !defined(IPFILTER_LKM) +int iplinit __P((void)); + +int +iplinit() +{ + if (ipfattach() != 0) + printf("IP Filter failed to attach\n"); + ip_init(); +} +#endif + + +size_t +mbufchainlen(m0) + register struct mbuf *m0; +{ + register size_t len = 0; + + for (; m0; m0 = m0->m_next) + len += m0->m_len; + return len; +} + + +/* + * m0 - pointer to mbuf where the IP packet starts + * mpp - pointer to the mbuf pointer that is the start of the mbuf chain + */ +int +ipf_fastroute(m0, mpp, fin, fdp) + struct mbuf *m0, **mpp; + fr_info_t *fin; + frdest_t *fdp; +{ + register struct ip *ip, *mhip; + register struct mbuf *m = *mpp; + register struct route *ro; + int len, off, error = 0, hlen, code; + struct ifnet *ifp, *sifp; + struct sockaddr_in *dst; + struct route iproute; + u_short ip_off; + frdest_t node; + frentry_t *fr; + + hlen = fin->fin_hlen; + ip = mtod(m0, struct ip *); + + /* + * Route packet. + */ + ro = &iproute; + bzero((caddr_t)ro, sizeof (*ro)); + dst = (struct sockaddr_in *)&ro->ro_dst; + dst->sin_family = AF_INET; + dst->sin_addr = ip->ip_dst; + + fr = fin->fin_fr; + if ((fr != NULL) && !(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) && + (fdp->fd_type == FRD_DSTLIST)) { + if (ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node) == 0) + fdp = &node; + } + if (fdp != NULL) + ifp = fdp->fd_ptr; + else + ifp = fin->fin_ifp; + + if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0)) + dst->sin_addr = fdp->fd_ip; + + rtalloc(ro); + if (ifp == NULL) { + if (!fr || !(fr->fr_flags & FR_FASTROUTE)) { + error = -2; + goto bad; + } + if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) { + if (in_localaddr(ip->ip_dst)) + error = EHOSTUNREACH; + else + error = ENETUNREACH; + goto bad; + } + if (ro->ro_rt->rt_flags & RTF_GATEWAY) + dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway; + } + if (ro->ro_rt != NULL) + ro->ro_rt->rt_use++; + + /* + * For input packets which are being "fastrouted", they won't + * go back through output filtering and miss their chance to get + * NAT'd and counted. Duplicated packets aren't considered to be + * part of the normal packet stream, so do not NAT them or pass + * them through stateful checking, etc. + */ + if ((fdp != &fr->fr_dif) && (fin->fin_out == 0)) { + sifp = fin->fin_ifp; + fin->fin_ifp = ifp; + fin->fin_out = 1; + (void) ipf_acctpkt(fin, NULL); + fin->fin_fr = NULL; + if (!fr || !(fr->fr_flags & FR_RETMASK)) { + u_32_t pass; + + (void) ipf_state_check(fin, &pass); + } + + switch (ipf_nat_checkout(fin, NULL)) + { + case 0 : + break; + case 1 : + break; + case -1 : + error = -1; + goto bad; + break; + } + + fin->fin_ifp = sifp; + fin->fin_out = 0; + } else + ip->ip_sum = 0; + /* + * If small enough for interface, can just send directly. + */ + if (ip->ip_len <= ifp->if_mtu) { + ip->ip_len = htons(ip->ip_len); + ip->ip_off = htons(ip->ip_off); + if (!ip->ip_sum) + ip->ip_sum = in_cksum(m, hlen); + error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst); + goto done; + } + /* + * Too large for interface; fragment if possible. + * Must be able to put at least 8 bytes per fragment. + */ + ip_off = ip->ip_off; + if (ip_off & IP_DF) { + error = EMSGSIZE; + goto bad; + } + len = (ifp->if_mtu - hlen) &~ 7; + if (len < 8) { + error = EMSGSIZE; + goto bad; + } + + { + int mhlen, firstlen = len; + struct mbuf **mnext = &m->m_act; + + /* + * Loop through length of segment after first fragment, + * make new header and copy data of each part and link onto chain. + */ + m0 = m; + mhlen = sizeof (struct ip); + for (off = hlen + len; off < ip->ip_len; off += len) { + MGET(m, M_DONTWAIT, MT_HEADER); + if (m == 0) { + m = m0; + error = ENOBUFS; + goto bad; + } + m->m_off = MMAXOFF - hlen; + mhip = mtod(m, struct ip *); + bcopy((char *)ip, (char *)mhip, sizeof(*ip)); + if (hlen > sizeof (struct ip)) { + mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); + IP_HL_A(mhip, mhlen >> 2); + } + m->m_len = mhlen; + mhip->ip_off = ((off - hlen) >> 3) + ip_off; + if (off + len >= ip->ip_len) + len = ip->ip_len - off; + else + mhip->ip_off |= IP_MF; + mhip->ip_len = htons((u_short)(len + mhlen)); + m->m_next = m_copy(m0, off, len); + if (m->m_next == 0) { + error = ENOBUFS; /* ??? */ + goto sendorfree; + } + mhip->ip_off = htons((u_short)mhip->ip_off); + mhip->ip_sum = 0; + mhip->ip_sum = in_cksum(m, mhlen); + *mnext = m; + mnext = &m->m_act; + } + /* + * Update first fragment by trimming what's been copied out + * and updating header, then send each fragment (in order). + */ + m_adj(m0, hlen + firstlen - ip->ip_len); + ip->ip_len = htons((u_short)(hlen + firstlen)); + ip->ip_off = htons((u_short)IP_MF); + ip->ip_sum = 0; + ip->ip_sum = in_cksum(m0, hlen); +sendorfree: + for (m = m0; m; m = m0) { + m0 = m->m_act; + m->m_act = 0; + if (error == 0) + error = (*ifp->if_output)(ifp, m, + (struct sockaddr *)dst); + else + FREE_MB_T(m); + } + } +done: + if (!error) + ipf_frouteok[0]++; + else + ipf_frouteok[1]++; + + if (ro->ro_rt != NULL) { + RTFREE(ro->ro_rt); + } + return 0; +bad: + if (error == EMSGSIZE) { + sifp = fin->fin_ifp; + code = fin->fin_icode; + fin->fin_icode = ICMP_UNREACH_NEEDFRAG; + fin->fin_ifp = ifp; + (void) ipf_send_icmp_err(ICMP_UNREACH, fin, 1); + fin->fin_ifp = sifp; + fin->fin_icode = code; + } + FREE_MB_T(m); + goto done; +} + + +int +ipf_verifysrc(fin) + fr_info_t *fin; +{ + struct sockaddr_in *dst; + struct route iproute; + void *rtifp; + + bzero((char *)&iproute, sizeof(iproute)); + dst = (struct sockaddr_in *)&iproute.ro_dst; + dst->sin_family = AF_INET; + dst->sin_addr.s_addr = fin->fin_saddr; + rtalloc(&iproute); + if (iproute.ro_rt == NULL) + return 0; + rtifp = iproute.ro_rt->rt_ifp; + RTFREE(iproute.ro_rt); + return (fin->fin_ifp == rtifp); +} + + +/* + * return the first IP Address associated with an interface + */ +int +ipf_ifpaddr(softc, v, atype, ifptr, inp, inpmask) + ipf_main_softc_t *softc; + int v, atype; + void *ifptr; + i6addr_t *inp, *inpmask; +{ + struct sockaddr_in *sin, *mask; + struct in_ifaddr *ia; + struct ifnet *ifp; + + if ((ifptr == NULL) || (ifptr == (void *)-1)) + return -1; + + ifp = ifptr; + if (ifp == NULL) + return -1; + + for (ia = in_ifaddr; ia != NULL; ia = ia->ia_next) + if (ia->ia_ifp == ifp) { + sin = (struct sockaddr_in *)&ia->ia_addr; + break; + } + + if (ia == NULL) + return -1; + + if (atype == FRI_BROADCAST) + sin = (struct sockaddr_in *)&ia->ia_broadaddr; + else if (atype == FRI_PEERADDR) + sin = (struct sockaddr_in *)&ia->ia_dstaddr; + mask = (struct sockaddr_in *)&ia->ia_subnetmask; + + return ipf_ifpfillv4addr(atype, sin, mask, &inp->in4, &inpmask->in4); +} + + +u_32_t +ipf_newisn(fin) + fr_info_t *fin; +{ + static iss_seq_off = 0; + u_char hash[16]; + u_32_t newiss; + MD5_CTX ctx; + + /* + * Compute the base value of the ISS. It is a hash + * of (saddr, sport, daddr, dport, secret). + */ + MD5Init(&ctx); + + MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, + sizeof(fin->fin_fi.fi_src)); + MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, + sizeof(fin->fin_fi.fi_dst)); + MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); + + MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); + + MD5Final(hash, &ctx); + + memcpy(&newiss, hash, sizeof(newiss)); + + /* + * Now increment our "timer", and add it in to + * the computed value. + * + * XXX Use `addin'? + * XXX TCP_ISSINCR too large to use? + */ + iss_seq_off += 0x00010000; + newiss += iss_seq_off; + return newiss; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nextipid */ +/* Returns: int - 0 == success, -1 == error (packet should be droppped) */ +/* Parameters: fin(I) - pointer to packet information */ +/* */ +/* Returns the next IPv4 ID to use for this packet. */ +/* ------------------------------------------------------------------------ */ +INLINE u_short +ipf_nextipid(fin) + fr_info_t *fin; +{ + u_short id; + + id = ipid++; + + return id; +} + + +INLINE int +ipf_checkv4sum(fin) + fr_info_t *fin; +{ + if ((fin->fin_flx & FI_NOCKSUM) != 0) + return 0; + + if ((fin->fin_flx & FI_SHORT) != 0) + return 1; + + if (fin->fin_cksum != FI_CK_NEEDED) + return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; + + if (ipf_checkl4sum(fin) == -1) { + fin->fin_flx |= FI_BAD; + return -1; + } + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pullup */ +/* Returns: NULL == pullup failed, else pointer to protocol header */ +/* Parameters: xmin(I)- pointer to buffer where data packet starts */ +/* fin(I) - pointer to packet information */ +/* len(I) - number of bytes to pullup */ +/* */ +/* Attempt to move at least len bytes (from the start of the buffer) into a */ +/* single buffer for ease of access. Operating system native functions are */ +/* used to manage buffers - if necessary. If the entire packet ends up in */ +/* a single buffer, set the FI_COALESCE flag even though ipf_coalesce() has */ +/* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */ +/* and ONLY if the pullup succeeds. */ +/* */ +/* We assume that 'xmin' is a pointer to a buffer that is part of the chain */ +/* of buffers that starts at *fin->fin_mp. */ +/* ------------------------------------------------------------------------ */ +void * +ipf_pullup(xmin, fin, len) + mb_t *xmin; + fr_info_t *fin; + int len; +{ + int out = fin->fin_out, dpoff, ipoff; + mb_t *m = xmin; + char *ip; + + if (m == NULL) + return NULL; + + ip = (char *)fin->fin_ip; + if ((fin->fin_flx & FI_COALESCE) != 0) + return ip; + + ipoff = fin->fin_ipoff; + if (fin->fin_dp != NULL) + dpoff = (char *)fin->fin_dp - (char *)ip; + else + dpoff = 0; + + if (M_LEN(m) < len) { + mb_t *n = *fin->fin_mp; + + if (m != n) { + for (; n->m_next != m; n = n->m_next) + ; + } else { + n = NULL; + } + + if (len > MLEN) { + FREE_MB_T(*fin->fin_mp); + m = NULL; + n = NULL; + } else { + m = m_pullup(m, len); + } + + if (n != NULL) + n->m_next = m; + + if (m == NULL) { + if (n != NULL) { + FREE_MB_T(*fin->fin_mp); + } + *fin->fin_mp = NULL; + fin->fin_m = NULL; + return NULL; + } + + if (n == NULL) + *fin->fin_mp = m; + + while (M_LEN(m) == 0) { + m = m->m_next; + } + + fin->fin_m = m; + ip = MTOD(m, char *) + ipoff; + + fin->fin_ip = (ip_t *)ip; + if (fin->fin_dp != NULL) + fin->fin_dp = (char *)fin->fin_ip + dpoff; + } + + if (len == fin->fin_plen) + fin->fin_flx |= FI_COALESCE; + return ip; +} + + +int +ipf_inject(fin, m) + fr_info_t *fin; + mb_t *m; +{ + int error; + + if (fin->fin_out == 0) { + struct ifqueue *ifq; + + ifq = &ipintrq; + + if (IF_QFULL(ifq)) { + IF_DROP(ifq); + FREE_MB_T(m); + error = ENOBUFS; + } else { + IF_ENQUEUE(ifq, m); + error = 0; + } + } else { + error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL); + } + + return error; +} + + +/* + * In the face of no kernel random function, this is implemented...it is + * not meant to be random, just a fill in. + */ +int +ipf_random() +{ + static int last = 0; + static int calls = 0; + struct timeval tv; + int number; + + GETKTIME(&tv); + last *= tv.tv_usec + calls++; + last += (int)&range * ipf_ticks; + number = last + tv.tv_sec; + return number; +} + + +u_short +ipf_pcksum(fin, hlen, sum) +{ + u_short sum2; + + slen = fin->fin_plen - hlen; + m->m_off += hlen; + m->m_len -= hlen; + sum2 = in_cksum(fin->fin_m, slen); + m->m_len += hlen; + m->m_off -= hlen; + /* + * Both sum and sum2 are partial sums, so combine them together. + */ + sum += ~sum2 & 0xffff; + while (sum > 0xffff) + sum = (sum & 0xffff) + (sum >> 16); + sum2 = ~sum & 0xffff; + return sum2; +} diff --git a/ip_frag.c b/ip_frag.c index 087ca19e72c3d..0649b22617aec 100644 --- a/ip_frag.c +++ b/ip_frag.c @@ -1,7 +1,5 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1993-2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -30,7 +28,8 @@ struct file; # include <sys/uio.h> # undef _KERNEL #endif -#if defined(_KERNEL) && (__FreeBSD_version >= 220000) +#if defined(_KERNEL) && \ + defined(__FreeBSD_version) && (__FreeBSD_version >= 220000) # include <sys/filio.h> # include <sys/fcntl.h> #else @@ -47,7 +46,7 @@ struct file; # endif #endif #if !defined(__SVR4) && !defined(__svr4__) -# if defined(_KERNEL) && !defined(__sgi) +# if defined(_KERNEL) && !defined(__sgi) && !defined(AIX) # include <sys/kernel.h> # endif #else @@ -62,7 +61,6 @@ struct file; #ifdef sun # include <net/af.h> #endif -#include <net/route.h> #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> @@ -79,207 +77,417 @@ struct file; #include "netinet/ip_frag.h" #include "netinet/ip_state.h" #include "netinet/ip_auth.h" +#include "netinet/ip_lookup.h" #include "netinet/ip_proxy.h" -#if (__FreeBSD_version >= 300000) -# include <sys/malloc.h> -# if defined(_KERNEL) -# ifndef IPFILTER_LKM -# include <sys/libkern.h> -# include <sys/systm.h> -# endif -extern struct callout_handle fr_slowtimer_ch; -# endif -#endif -#if defined(__NetBSD__) && (__NetBSD_Version__ >= 104230000) -# include <sys/callout.h> -extern struct callout fr_slowtimer_ch; -#endif -#if defined(__OpenBSD__) -# include <sys/timeout.h> -extern struct timeout fr_slowtimer_ch; -#endif +#include "netinet/ip_sync.h" /* END OF INCLUDES */ #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.77 2004/01/27 00:24:54 darrenr Exp"; +static const char rcsid[] = "@(#)$Id$"; #endif -static ipfr_t *ipfr_list = NULL; -static ipfr_t **ipfr_tail = &ipfr_list; -static ipfr_t **ipfr_heads; +typedef struct ipf_frag_softc_s { + ipfrwlock_t ipfr_ipidfrag; + ipfrwlock_t ipfr_frag; + ipfrwlock_t ipfr_natfrag; + int ipfr_size; + int ipfr_ttl; + int ipfr_lock; + int ipfr_inited; + ipfr_t *ipfr_list; + ipfr_t **ipfr_tail; + ipfr_t *ipfr_natlist; + ipfr_t **ipfr_nattail; + ipfr_t *ipfr_ipidlist; + ipfr_t **ipfr_ipidtail; + ipfr_t **ipfr_heads; + ipfr_t **ipfr_nattab; + ipfr_t **ipfr_ipidtab; + ipfrstat_t ipfr_stats; +} ipf_frag_softc_t; + + +#ifdef USE_MUTEXES +static ipfr_t *ipfr_frag_new __P((ipf_main_softc_t *, ipf_frag_softc_t *, + fr_info_t *, u_32_t, ipfr_t **, + ipfrwlock_t *)); +static ipfr_t *ipf_frag_lookup __P((ipf_main_softc_t *, ipf_frag_softc_t *, fr_info_t *, ipfr_t **, ipfrwlock_t *)); +static void ipf_frag_deref __P((void *, ipfr_t **, ipfrwlock_t *)); +static int ipf_frag_next __P((ipf_main_softc_t *, ipftoken_t *, ipfgeniter_t *, + ipfr_t **, ipfrwlock_t *)); +#else +static ipfr_t *ipfr_frag_new __P((ipf_main_softc_t *, ipf_frag_softc_t *, + fr_info_t *, u_32_t, ipfr_t **)); +static ipfr_t *ipf_frag_lookup __P((ipf_main_softc_t *, ipf_frag_softc_t *, fr_info_t *, ipfr_t **)); +static void ipf_frag_deref __P((void *, ipfr_t **)); +static int ipf_frag_next __P((ipf_main_softc_t *, ipftoken_t *, ipfgeniter_t *, + ipfr_t **)); +#endif +static void ipf_frag_delete __P((ipf_main_softc_t *, ipfr_t *, ipfr_t ***)); +static void ipf_frag_free __P((ipf_frag_softc_t *, ipfr_t *)); + +static frentry_t ipfr_block; + +ipftuneable_t ipf_tuneables[] = { + { { (void *)offsetof(ipf_frag_softc_t, ipfr_size) }, + "frag_size", 1, 0x7fffffff, + stsizeof(ipf_frag_softc_t, ipfr_size), + IPFT_WRDISABLED, NULL, NULL }, + { { (void *)offsetof(ipf_frag_softc_t, ipfr_ttl) }, + "frag_ttl", 1, 0x7fffffff, + stsizeof(ipf_frag_softc_t, ipfr_ttl), + 0, NULL, NULL }, + { { NULL }, + NULL, 0, 0, + 0, + 0, NULL, NULL } +}; + +#define FBUMP(x) softf->ipfr_stats.x++ +#define FBUMPD(x) do { softf->ipfr_stats.x++; DT(x); } while (0) + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_frag_main_load */ +/* Returns: int - 0 == success, -1 == error */ +/* Parameters: Nil */ +/* */ +/* Initialise the filter rule associted with blocked packets - everyone can */ +/* use it. */ +/* ------------------------------------------------------------------------ */ +int +ipf_frag_main_load() +{ + bzero((char *)&ipfr_block, sizeof(ipfr_block)); + ipfr_block.fr_flags = FR_BLOCK|FR_QUICK; + ipfr_block.fr_ref = 1; + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_frag_main_unload */ +/* Returns: int - 0 == success, -1 == error */ +/* Parameters: Nil */ +/* */ +/* A null-op function that exists as a placeholder so that the flow in */ +/* other functions is obvious. */ +/* ------------------------------------------------------------------------ */ +int +ipf_frag_main_unload() +{ + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_frag_soft_create */ +/* Returns: void * - NULL = failure, else pointer to local context */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* */ +/* Allocate a new soft context structure to track fragment related info. */ +/* ------------------------------------------------------------------------ */ +/*ARGSUSED*/ +void * +ipf_frag_soft_create(softc) + ipf_main_softc_t *softc; +{ + ipf_frag_softc_t *softf; + + KMALLOC(softf, ipf_frag_softc_t *); + if (softf == NULL) + return NULL; + + bzero((char *)softf, sizeof(*softf)); -static ipfr_t *ipfr_natlist = NULL; -static ipfr_t **ipfr_nattail = &ipfr_natlist; -static ipfr_t **ipfr_nattab; + RWLOCK_INIT(&softf->ipfr_ipidfrag, "frag ipid lock"); + RWLOCK_INIT(&softf->ipfr_frag, "ipf fragment rwlock"); + RWLOCK_INIT(&softf->ipfr_natfrag, "ipf NAT fragment rwlock"); -static ipfr_t *ipfr_ipidlist = NULL; -static ipfr_t **ipfr_ipidtail = &ipfr_ipidlist; -static ipfr_t **ipfr_ipidtab; + softf->ipfr_size = IPFT_SIZE; + softf->ipfr_ttl = IPF_TTLVAL(60); + softf->ipfr_lock = 1; + softf->ipfr_tail = &softf->ipfr_list; + softf->ipfr_nattail = &softf->ipfr_natlist; + softf->ipfr_ipidtail = &softf->ipfr_ipidlist; -static ipfrstat_t ipfr_stats; -static int ipfr_inuse = 0; -int ipfr_size = IPFT_SIZE; + return softf; +} -int fr_ipfrttl = 120; /* 60 seconds */ -int fr_frag_lock = 0; -int fr_frag_init = 0; -u_long fr_ticks = 0; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_frag_soft_destroy */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* */ +/* Initialise the hash tables for the fragment cache lookups. */ +/* ------------------------------------------------------------------------ */ +void +ipf_frag_soft_destroy(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_frag_softc_t *softf = arg; + + RW_DESTROY(&softf->ipfr_ipidfrag); + RW_DESTROY(&softf->ipfr_frag); + RW_DESTROY(&softf->ipfr_natfrag); -static ipfr_t *ipfr_newfrag __P((fr_info_t *, u_32_t, ipfr_t **)); -static ipfr_t *fr_fraglookup __P((fr_info_t *, ipfr_t **)); -static void fr_fragdelete __P((ipfr_t *, ipfr_t ***)); + KFREE(softf); +} /* ------------------------------------------------------------------------ */ -/* Function: fr_fraginit */ -/* Returns: int - 0 == success, -1 == error */ -/* Parameters: Nil */ +/* Function: ipf_frag_soft_init */ +/* Returns: int - 0 == success, -1 == error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ /* */ /* Initialise the hash tables for the fragment cache lookups. */ /* ------------------------------------------------------------------------ */ -int fr_fraginit() +/*ARGSUSED*/ +int +ipf_frag_soft_init(softc, arg) + ipf_main_softc_t *softc; + void *arg; { - KMALLOCS(ipfr_heads, ipfr_t **, ipfr_size * sizeof(ipfr_t *)); - if (ipfr_heads == NULL) - return -1; - bzero((char *)ipfr_heads, ipfr_size * sizeof(ipfr_t *)); + ipf_frag_softc_t *softf = arg; - KMALLOCS(ipfr_nattab, ipfr_t **, ipfr_size * sizeof(ipfr_t *)); - if (ipfr_nattab == NULL) + KMALLOCS(softf->ipfr_heads, ipfr_t **, + softf->ipfr_size * sizeof(ipfr_t *)); + if (softf->ipfr_heads == NULL) return -1; - bzero((char *)ipfr_nattab, ipfr_size * sizeof(ipfr_t *)); - KMALLOCS(ipfr_ipidtab, ipfr_t **, ipfr_size * sizeof(ipfr_t *)); - if (ipfr_ipidtab == NULL) - return -1; - bzero((char *)ipfr_ipidtab, ipfr_size * sizeof(ipfr_t *)); + bzero((char *)softf->ipfr_heads, softf->ipfr_size * sizeof(ipfr_t *)); + + KMALLOCS(softf->ipfr_nattab, ipfr_t **, + softf->ipfr_size * sizeof(ipfr_t *)); + if (softf->ipfr_nattab == NULL) + return -2; + + bzero((char *)softf->ipfr_nattab, softf->ipfr_size * sizeof(ipfr_t *)); + + KMALLOCS(softf->ipfr_ipidtab, ipfr_t **, + softf->ipfr_size * sizeof(ipfr_t *)); + if (softf->ipfr_ipidtab == NULL) + return -3; - RWLOCK_INIT(&ipf_frag, "ipf fragment rwlock"); - fr_frag_init = 1; + bzero((char *)softf->ipfr_ipidtab, + softf->ipfr_size * sizeof(ipfr_t *)); + + softf->ipfr_lock = 0; + softf->ipfr_inited = 1; return 0; } /* ------------------------------------------------------------------------ */ -/* Function: fr_fragunload */ -/* Returns: Nil */ -/* Parameters: Nil */ +/* Function: ipf_frag_soft_fini */ +/* Returns: int - 0 == success, -1 == error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ /* */ /* Free all memory allocated whilst running and from initialisation. */ /* ------------------------------------------------------------------------ */ -void fr_fragunload() +int +ipf_frag_soft_fini(softc, arg) + ipf_main_softc_t *softc; + void *arg; { - if (fr_frag_init == 1) { - fr_fragclear(); + ipf_frag_softc_t *softf = arg; + + softf->ipfr_lock = 1; - RW_DESTROY(&ipf_frag); - fr_frag_init = 0; + if (softf->ipfr_inited == 1) { + ipf_frag_clear(softc); + + softf->ipfr_inited = 0; } - if (ipfr_heads != NULL) - KFREES(ipfr_heads, ipfr_size * sizeof(ipfr_t *)); - ipfr_heads = NULL; + if (softf->ipfr_heads != NULL) + KFREES(softf->ipfr_heads, + softf->ipfr_size * sizeof(ipfr_t *)); + softf->ipfr_heads = NULL; + + if (softf->ipfr_nattab != NULL) + KFREES(softf->ipfr_nattab, + softf->ipfr_size * sizeof(ipfr_t *)); + softf->ipfr_nattab = NULL; + + if (softf->ipfr_ipidtab != NULL) + KFREES(softf->ipfr_ipidtab, + softf->ipfr_size * sizeof(ipfr_t *)); + softf->ipfr_ipidtab = NULL; + + return 0; +} - if (ipfr_nattab != NULL) - KFREES(ipfr_nattab, ipfr_size * sizeof(ipfr_t *)); - ipfr_nattab = NULL; - if (ipfr_ipidtab != NULL) - KFREES(ipfr_ipidtab, ipfr_size * sizeof(ipfr_t *)); - ipfr_ipidtab = NULL; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_frag_set_lock */ +/* Returns: Nil */ +/* Parameters: arg(I) - pointer to local context to use */ +/* tmp(I) - new value for lock */ +/* */ +/* Stub function that allows for external manipulation of ipfr_lock */ +/* ------------------------------------------------------------------------ */ +void +ipf_frag_setlock(arg, tmp) + void *arg; + int tmp; +{ + ipf_frag_softc_t *softf = arg; + + softf->ipfr_lock = tmp; } /* ------------------------------------------------------------------------ */ -/* Function: fr_fragstats */ +/* Function: ipf_frag_stats */ /* Returns: ipfrstat_t* - pointer to struct with current frag stats */ -/* Parameters: Nil */ +/* Parameters: arg(I) - pointer to local context to use */ /* */ /* Updates ipfr_stats with current information and returns a pointer to it */ /* ------------------------------------------------------------------------ */ -ipfrstat_t *fr_fragstats() +ipfrstat_t * +ipf_frag_stats(arg) + void *arg; { - ipfr_stats.ifs_table = ipfr_heads; - ipfr_stats.ifs_nattab = ipfr_nattab; - ipfr_stats.ifs_inuse = ipfr_inuse; - return &ipfr_stats; + ipf_frag_softc_t *softf = arg; + + softf->ipfr_stats.ifs_table = softf->ipfr_heads; + softf->ipfr_stats.ifs_nattab = softf->ipfr_nattab; + return &softf->ipfr_stats; } /* ------------------------------------------------------------------------ */ -/* Function: ipfr_newfrag */ +/* Function: ipfr_frag_new */ /* Returns: ipfr_t * - pointer to fragment cache state info or NULL */ /* Parameters: fin(I) - pointer to packet information */ /* table(I) - pointer to frag table to add to */ +/* lock(I) - pointer to lock to get a write hold of */ /* */ /* Add a new entry to the fragment cache, registering it as having come */ /* through this box, with the result of the filter operation. */ +/* */ +/* If this function succeeds, it returns with a write lock held on "lock". */ +/* If it fails, no lock is held on return. */ /* ------------------------------------------------------------------------ */ -static ipfr_t *ipfr_newfrag(fin, pass, table) -fr_info_t *fin; -u_32_t pass; -ipfr_t *table[]; +static ipfr_t * +ipfr_frag_new(softc, softf, fin, pass, table +#ifdef USE_MUTEXES +, lock +#endif +) + ipf_main_softc_t *softc; + ipf_frag_softc_t *softf; + fr_info_t *fin; + u_32_t pass; + ipfr_t *table[]; +#ifdef USE_MUTEXES + ipfrwlock_t *lock; +#endif { - ipfr_t *fra, frag; + ipfr_t *fra, frag, *fran; u_int idx, off; - ip_t *ip; + frentry_t *fr; - if (ipfr_inuse >= IPFT_SIZE) + if (softf->ipfr_stats.ifs_inuse >= softf->ipfr_size) { + FBUMPD(ifs_maximum); return NULL; + } - if ((fin->fin_flx & (FI_FRAG|FI_BAD)) != FI_FRAG) + if ((fin->fin_flx & (FI_FRAG|FI_BAD)) != FI_FRAG) { + FBUMPD(ifs_newbad); return NULL; + } - ip = fin->fin_ip; - - if (pass & FR_FRSTRICT) - if ((ip->ip_off & IP_OFFMASK) != 0) + if (pass & FR_FRSTRICT) { + if (fin->fin_off != 0) { + FBUMPD(ifs_newrestrictnot0); return NULL; + } + } - frag.ipfr_p = ip->ip_p; - idx = ip->ip_p; - frag.ipfr_id = ip->ip_id; - idx += ip->ip_id; - frag.ipfr_tos = ip->ip_tos; - frag.ipfr_src.s_addr = ip->ip_src.s_addr; - idx += ip->ip_src.s_addr; - frag.ipfr_dst.s_addr = ip->ip_dst.s_addr; - idx += ip->ip_dst.s_addr; + frag.ipfr_v = fin->fin_v; + idx = fin->fin_v; + frag.ipfr_p = fin->fin_p; + idx += fin->fin_p; + frag.ipfr_id = fin->fin_id; + idx += fin->fin_id; + frag.ipfr_source = fin->fin_fi.fi_src; + idx += frag.ipfr_src.s_addr; + frag.ipfr_dest = fin->fin_fi.fi_dst; + idx += frag.ipfr_dst.s_addr; frag.ipfr_ifp = fin->fin_ifp; idx *= 127; - idx %= IPFT_SIZE; + idx %= softf->ipfr_size; frag.ipfr_optmsk = fin->fin_fi.fi_optmsk & IPF_OPTCOPY; frag.ipfr_secmsk = fin->fin_fi.fi_secmsk; frag.ipfr_auth = fin->fin_fi.fi_auth; + off = fin->fin_off >> 3; + if (off == 0) { + char *ptr; + int end; + +#ifdef USE_INET6 + if (fin->fin_v == 6) { + + ptr = (char *)fin->fin_fraghdr + + sizeof(struct ip6_frag); + } else +#endif + { + ptr = fin->fin_dp; + } + end = fin->fin_plen - (ptr - (char *)fin->fin_ip); + frag.ipfr_firstend = end >> 3; + } else { + frag.ipfr_firstend = 0; + } + + /* + * allocate some memory, if possible, if not, just record that we + * failed to do so. + */ + KMALLOC(fran, ipfr_t *); + if (fran == NULL) { + FBUMPD(ifs_nomem); + return NULL; + } + + WRITE_ENTER(lock); + /* * first, make sure it isn't already there... */ for (fra = table[idx]; (fra != NULL); fra = fra->ipfr_hnext) if (!bcmp((char *)&frag.ipfr_ifp, (char *)&fra->ipfr_ifp, IPFR_CMPSZ)) { - ipfr_stats.ifs_exists++; + RWLOCK_EXIT(lock); + FBUMPD(ifs_exists); + KFREE(fra); return NULL; } - /* - * allocate some memory, if possible, if not, just record that we - * failed to do so. - */ - KMALLOC(fra, ipfr_t *); - if (fra == NULL) { - ipfr_stats.ifs_nomem++; - return NULL; + fra = fran; + fran = NULL; + fr = fin->fin_fr; + fra->ipfr_rule = fr; + if (fr != NULL) { + MUTEX_ENTER(&fr->fr_lock); + fr->fr_ref++; + MUTEX_EXIT(&fr->fr_lock); } - if ((fra->ipfr_rule = fin->fin_fr) != NULL) - fin->fin_fr->fr_ref++; - /* * Insert the fragment into the fragment table, copy the struct used * in the search using bcopy rather than reassign each field. @@ -291,55 +499,63 @@ ipfr_t *table[]; fra->ipfr_data = NULL; table[idx] = fra; bcopy((char *)&frag.ipfr_ifp, (char *)&fra->ipfr_ifp, IPFR_CMPSZ); - fra->ipfr_ttl = fr_ticks + fr_ipfrttl; + fra->ipfr_v = fin->fin_v; + fra->ipfr_ttl = softc->ipf_ticks + softf->ipfr_ttl; + fra->ipfr_firstend = frag.ipfr_firstend; /* * Compute the offset of the expected start of the next packet. */ - off = ip->ip_off & IP_OFFMASK; if (off == 0) fra->ipfr_seen0 = 1; fra->ipfr_off = off + (fin->fin_dlen >> 3); fra->ipfr_pass = pass; - ipfr_stats.ifs_new++; - ipfr_inuse++; + fra->ipfr_ref = 1; + fra->ipfr_pkts = 1; + fra->ipfr_bytes = fin->fin_plen; + FBUMP(ifs_inuse); + FBUMP(ifs_new); return fra; } /* ------------------------------------------------------------------------ */ -/* Function: fr_newfrag */ +/* Function: ipf_frag_new */ /* Returns: int - 0 == success, -1 == error */ /* Parameters: fin(I) - pointer to packet information */ /* */ /* Add a new entry to the fragment cache table based on the current packet */ /* ------------------------------------------------------------------------ */ -int fr_newfrag(fin, pass) -u_32_t pass; -fr_info_t *fin; +int +ipf_frag_new(softc, fin, pass) + ipf_main_softc_t *softc; + u_32_t pass; + fr_info_t *fin; { + ipf_frag_softc_t *softf = softc->ipf_frag_soft; ipfr_t *fra; - if ((fin->fin_v != 4) || (fr_frag_lock != 0)) + if (softf->ipfr_lock != 0) return -1; - WRITE_ENTER(&ipf_frag); - fra = ipfr_newfrag(fin, pass, ipfr_heads); +#ifdef USE_MUTEXES + fra = ipfr_frag_new(softc, softf, fin, pass, softf->ipfr_heads, &softc->ipf_frag); +#else + fra = ipfr_frag_new(softc, softf, fin, pass, softf->ipfr_heads); +#endif if (fra != NULL) { - *ipfr_tail = fra; - fra->ipfr_prev = ipfr_tail; - ipfr_tail = &fra->ipfr_next; - if (ipfr_list == NULL) - ipfr_list = fra; + *softf->ipfr_tail = fra; + fra->ipfr_prev = softf->ipfr_tail; + softf->ipfr_tail = &fra->ipfr_next; fra->ipfr_next = NULL; + RWLOCK_EXIT(&softc->ipf_frag); } - RWLOCK_EXIT(&ipf_frag); return fra ? 0 : -1; } /* ------------------------------------------------------------------------ */ -/* Function: fr_nat_newfrag */ +/* Function: ipf_frag_natnew */ /* Returns: int - 0 == success, -1 == error */ /* Parameters: fin(I) - pointer to packet information */ /* nat(I) - pointer to NAT structure */ @@ -347,33 +563,41 @@ fr_info_t *fin; /* Create a new NAT fragment cache entry based on the current packet and */ /* the NAT structure for this "session". */ /* ------------------------------------------------------------------------ */ -int fr_nat_newfrag(fin, pass, nat) -fr_info_t *fin; -u_32_t pass; -nat_t *nat; +int +ipf_frag_natnew(softc, fin, pass, nat) + ipf_main_softc_t *softc; + fr_info_t *fin; + u_32_t pass; + nat_t *nat; { + ipf_frag_softc_t *softf = softc->ipf_frag_soft; ipfr_t *fra; - if ((fin->fin_v != 4) || (fr_frag_lock != 0)) + if (softf->ipfr_lock != 0) return 0; - WRITE_ENTER(&ipf_natfrag); - fra = ipfr_newfrag(fin, pass, ipfr_nattab); +#ifdef USE_MUTEXES + fra = ipfr_frag_new(softc, softf, fin, pass, softf->ipfr_nattab, + &softf->ipfr_natfrag); +#else + fra = ipfr_frag_new(softc, softf, fin, pass, softf->ipfr_nattab); +#endif if (fra != NULL) { fra->ipfr_data = nat; nat->nat_data = fra; - *ipfr_nattail = fra; - fra->ipfr_prev = ipfr_nattail; - ipfr_nattail = &fra->ipfr_next; + *softf->ipfr_nattail = fra; + fra->ipfr_prev = softf->ipfr_nattail; + softf->ipfr_nattail = &fra->ipfr_next; fra->ipfr_next = NULL; + RWLOCK_EXIT(&softf->ipfr_natfrag); + return 0; } - RWLOCK_EXIT(&ipf_natfrag); - return fra ? 0 : -1; + return -1; } /* ------------------------------------------------------------------------ */ -/* Function: fr_ipid_newfrag */ +/* Function: ipf_frag_ipidnew */ /* Returns: int - 0 == success, -1 == error */ /* Parameters: fin(I) - pointer to packet information */ /* ipid(I) - new IP ID for this fragmented packet */ @@ -381,31 +605,37 @@ nat_t *nat; /* Create a new fragment cache entry for this packet and store, as a data */ /* pointer, the new IP ID value. */ /* ------------------------------------------------------------------------ */ -int fr_ipid_newfrag(fin, ipid) -fr_info_t *fin; -u_32_t ipid; +int +ipf_frag_ipidnew(fin, ipid) + fr_info_t *fin; + u_32_t ipid; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_frag_softc_t *softf = softc->ipf_frag_soft; ipfr_t *fra; - if ((fin->fin_v != 4) || (fr_frag_lock)) + if (softf->ipfr_lock) return 0; - WRITE_ENTER(&ipf_ipidfrag); - fra = ipfr_newfrag(fin, 0, ipfr_ipidtab); +#ifdef USE_MUTEXES + fra = ipfr_frag_new(softc, softf, fin, 0, softf->ipfr_ipidtab, &softf->ipfr_ipidfrag); +#else + fra = ipfr_frag_new(softc, softf, fin, 0, softf->ipfr_ipidtab); +#endif if (fra != NULL) { - fra->ipfr_data = (void *)ipid; - *ipfr_ipidtail = fra; - fra->ipfr_prev = ipfr_ipidtail; - ipfr_ipidtail = &fra->ipfr_next; + fra->ipfr_data = (void *)(intptr_t)ipid; + *softf->ipfr_ipidtail = fra; + fra->ipfr_prev = softf->ipfr_ipidtail; + softf->ipfr_ipidtail = &fra->ipfr_next; fra->ipfr_next = NULL; + RWLOCK_EXIT(&softf->ipfr_ipidfrag); } - RWLOCK_EXIT(&ipf_ipidfrag); return fra ? 0 : -1; } /* ------------------------------------------------------------------------ */ -/* Function: fr_fraglookup */ +/* Function: ipf_frag_lookup */ /* Returns: ipfr_t * - pointer to ipfr_t structure if there's a */ /* matching entry in the frag table, else NULL */ /* Parameters: fin(I) - pointer to packet information */ @@ -413,17 +643,44 @@ u_32_t ipid; /* */ /* Check the fragment cache to see if there is already a record of this */ /* packet with its filter result known. */ +/* */ +/* If this function succeeds, it returns with a write lock held on "lock". */ +/* If it fails, no lock is held on return. */ /* ------------------------------------------------------------------------ */ -static ipfr_t *fr_fraglookup(fin, table) -fr_info_t *fin; -ipfr_t *table[]; +static ipfr_t * +ipf_frag_lookup(softc, softf, fin, table +#ifdef USE_MUTEXES +, lock +#endif +) + ipf_main_softc_t *softc; + ipf_frag_softc_t *softf; + fr_info_t *fin; + ipfr_t *table[]; +#ifdef USE_MUTEXES + ipfrwlock_t *lock; +#endif { ipfr_t *f, frag; u_int idx; - ip_t *ip; - if ((fin->fin_flx & (FI_FRAG|FI_BAD)) != FI_FRAG) + /* + * We don't want to let short packets match because they could be + * compromising the security of other rules that want to match on + * layer 4 fields (and can't because they have been fragmented off.) + * Why do this check here? The counter acts as an indicator of this + * kind of attack, whereas if it was elsewhere, it wouldn't know if + * other matching packets had been seen. + */ + if (fin->fin_flx & FI_SHORT) { + FBUMPD(ifs_short); + return NULL; + } + + if ((fin->fin_flx & FI_BAD) != 0) { + FBUMPD(ifs_bad); return NULL; + } /* * For fragments, we record protocol, packet id, TOS and both IP#'s @@ -431,59 +688,58 @@ ipfr_t *table[]; * * build up a hash value to index the table with. */ - ip = fin->fin_ip; - frag.ipfr_p = ip->ip_p; - idx = ip->ip_p; - frag.ipfr_id = ip->ip_id; - idx += ip->ip_id; - frag.ipfr_tos = ip->ip_tos; - frag.ipfr_src.s_addr = ip->ip_src.s_addr; - idx += ip->ip_src.s_addr; - frag.ipfr_dst.s_addr = ip->ip_dst.s_addr; - idx += ip->ip_dst.s_addr; + frag.ipfr_v = fin->fin_v; + idx = fin->fin_v; + frag.ipfr_p = fin->fin_p; + idx += fin->fin_p; + frag.ipfr_id = fin->fin_id; + idx += fin->fin_id; + frag.ipfr_source = fin->fin_fi.fi_src; + idx += frag.ipfr_src.s_addr; + frag.ipfr_dest = fin->fin_fi.fi_dst; + idx += frag.ipfr_dst.s_addr; frag.ipfr_ifp = fin->fin_ifp; idx *= 127; - idx %= IPFT_SIZE; + idx %= softf->ipfr_size; frag.ipfr_optmsk = fin->fin_fi.fi_optmsk & IPF_OPTCOPY; frag.ipfr_secmsk = fin->fin_fi.fi_secmsk; frag.ipfr_auth = fin->fin_fi.fi_auth; + READ_ENTER(lock); + /* * check the table, careful to only compare the right amount of data */ - for (f = table[idx]; f; f = f->ipfr_hnext) + for (f = table[idx]; f; f = f->ipfr_hnext) { if (!bcmp((char *)&frag.ipfr_ifp, (char *)&f->ipfr_ifp, IPFR_CMPSZ)) { u_short off; /* - * We don't want to let short packets match because - * they could be compromising the security of other - * rules that want to match on layer 4 fields (and - * can't because they have been fragmented off.) - * Why do this check here? The counter acts as an - * indicator of this kind of attack, whereas if it was - * elsewhere, it wouldn't know if other matching - * packets had been seen. - */ - if (fin->fin_flx & FI_SHORT) { - ATOMIC_INCL(ipfr_stats.ifs_short); - continue; - } - - /* * XXX - We really need to be guarding against the * retransmission of (src,dst,id,offset-range) here * because a fragmented packet is never resent with * the same IP ID# (or shouldn't). */ - off = ip->ip_off & IP_OFFMASK; + off = fin->fin_off >> 3; if (f->ipfr_seen0) { if (off == 0) { - ATOMIC_INCL(ipfr_stats.ifs_retrans0); + FBUMPD(ifs_retrans0); continue; } + + /* + * Case 3. See comment for frpr_fragment6. + */ + if ((f->ipfr_firstend != 0) && + (off < f->ipfr_firstend)) { + FBUMP(ifs_overlap); + DT2(ifs_overlap, u_short, off, + ipfr_t *, f); + fin->fin_flx |= FI_BAD; + break; + } } else if (off == 0) f->ipfr_seen0 = 1; @@ -512,82 +768,124 @@ ipfr_t *table[]; * last (in order), shrink expiration time. */ if (off == f->ipfr_off) { - if (!(ip->ip_off & IP_MF)) - f->ipfr_ttl = fr_ticks + 1; f->ipfr_off = (fin->fin_dlen >> 3) + off; - } else if (f->ipfr_pass & FR_FRSTRICT) - continue; - ATOMIC_INCL(ipfr_stats.ifs_hits); + + /* + * Well, we could shrink the expiration time + * but only if every fragment has been seen + * in order upto this, the last. ipfr_badorder + * is used here to count those out of order + * and if it equals 0 when we get to the last + * fragment then we can assume all of the + * fragments have been seen and in order. + */ +#if 0 + /* + * Doing this properly requires moving it to + * the head of the list which is infesible. + */ + if ((more == 0) && (f->ipfr_badorder == 0)) + f->ipfr_ttl = softc->ipf_ticks + 1; +#endif + } else { + f->ipfr_badorder++; + FBUMPD(ifs_unordered); + if (f->ipfr_pass & FR_FRSTRICT) { + FBUMPD(ifs_strict); + continue; + } + } + f->ipfr_pkts++; + f->ipfr_bytes += fin->fin_plen; + FBUMP(ifs_hits); return f; } + } + + RWLOCK_EXIT(lock); + FBUMP(ifs_miss); return NULL; } /* ------------------------------------------------------------------------ */ -/* Function: fr_nat_knownfrag */ +/* Function: ipf_frag_natknown */ /* Returns: nat_t* - pointer to 'parent' NAT structure if frag table */ /* match found, else NULL */ /* Parameters: fin(I) - pointer to packet information */ /* */ /* Functional interface for NAT lookups of the NAT fragment cache */ /* ------------------------------------------------------------------------ */ -nat_t *fr_nat_knownfrag(fin) -fr_info_t *fin; +nat_t * +ipf_frag_natknown(fin) + fr_info_t *fin; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_frag_softc_t *softf = softc->ipf_frag_soft; nat_t *nat; ipfr_t *ipf; - if ((fin->fin_v != 4) || (fr_frag_lock) || !ipfr_natlist) + if ((softf->ipfr_lock) || !softf->ipfr_natlist) return NULL; - READ_ENTER(&ipf_natfrag); - ipf = fr_fraglookup(fin, ipfr_nattab); +#ifdef USE_MUTEXES + ipf = ipf_frag_lookup(softc, softf, fin, softf->ipfr_nattab, + &softf->ipfr_natfrag); +#else + ipf = ipf_frag_lookup(softc, softf, fin, softf->ipfr_nattab); +#endif if (ipf != NULL) { nat = ipf->ipfr_data; /* * This is the last fragment for this packet. */ - if ((ipf->ipfr_ttl == fr_ticks + 1) && (nat != NULL)) { + if ((ipf->ipfr_ttl == softc->ipf_ticks + 1) && (nat != NULL)) { nat->nat_data = NULL; ipf->ipfr_data = NULL; } + RWLOCK_EXIT(&softf->ipfr_natfrag); } else nat = NULL; - RWLOCK_EXIT(&ipf_natfrag); return nat; } /* ------------------------------------------------------------------------ */ -/* Function: fr_ipid_knownfrag */ +/* Function: ipf_frag_ipidknown */ /* Returns: u_32_t - IPv4 ID for this packet if match found, else */ /* return 0xfffffff to indicate no match. */ /* Parameters: fin(I) - pointer to packet information */ /* */ /* Functional interface for IP ID lookups of the IP ID fragment cache */ /* ------------------------------------------------------------------------ */ -u_32_t fr_ipid_knownfrag(fin) -fr_info_t *fin; +u_32_t +ipf_frag_ipidknown(fin) + fr_info_t *fin; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_frag_softc_t *softf = softc->ipf_frag_soft; ipfr_t *ipf; u_32_t id; - if ((fin->fin_v != 4) || (fr_frag_lock) || !ipfr_ipidlist) + if (softf->ipfr_lock || !softf->ipfr_ipidlist) return 0xffffffff; - READ_ENTER(&ipf_ipidfrag); - ipf = fr_fraglookup(fin, ipfr_ipidtab); - if (ipf != NULL) - id = (u_32_t)ipf->ipfr_data; - else +#ifdef USE_MUTEXES + ipf = ipf_frag_lookup(softc, softf, fin, softf->ipfr_ipidtab, + &softf->ipfr_ipidfrag); +#else + ipf = ipf_frag_lookup(softc, softf, fin, softf->ipfr_ipidtab); +#endif + if (ipf != NULL) { + id = (u_32_t)(intptr_t)ipf->ipfr_data; + RWLOCK_EXIT(&softf->ipfr_ipidfrag); + } else id = 0xffffffff; - RWLOCK_EXIT(&ipf_ipidfrag); return id; } /* ------------------------------------------------------------------------ */ -/* Function: fr_knownfrag */ +/* Function: ipf_frag_known */ /* Returns: frentry_t* - pointer to filter rule if a match is found in */ /* the frag cache table, else NULL. */ /* Parameters: fin(I) - pointer to packet information */ @@ -597,78 +895,82 @@ fr_info_t *fin; /* match is found, return the rule pointer and flags from the rule, except */ /* that if FR_LOGFIRST is set, reset FR_LOG. */ /* ------------------------------------------------------------------------ */ -frentry_t *fr_knownfrag(fin, passp) -fr_info_t *fin; -u_32_t *passp; +frentry_t * +ipf_frag_known(fin, passp) + fr_info_t *fin; + u_32_t *passp; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_frag_softc_t *softf = softc->ipf_frag_soft; frentry_t *fr = NULL; ipfr_t *fra; u_32_t pass; - if ((fin->fin_v != 4) || (fr_frag_lock) || (ipfr_list == NULL)) + if ((softf->ipfr_lock) || (softf->ipfr_list == NULL)) return NULL; - READ_ENTER(&ipf_frag); - fra = fr_fraglookup(fin, ipfr_heads); +#ifdef USE_MUTEXES + fra = ipf_frag_lookup(softc, softf, fin, softf->ipfr_heads, + &softc->ipf_frag); +#else + fra = ipf_frag_lookup(softc, softf, fin, softf->ipfr_heads); +#endif if (fra != NULL) { - fr = fra->ipfr_rule; + if (fin->fin_flx & FI_BAD) { + fr = &ipfr_block; + fin->fin_reason = FRB_BADFRAG; + } else { + fr = fra->ipfr_rule; + } fin->fin_fr = fr; if (fr != NULL) { pass = fr->fr_flags; + if ((pass & FR_KEEPSTATE) != 0) { + fin->fin_flx |= FI_STATE; + /* + * Reset the keep state flag here so that we + * don't try and add a new state entry because + * of a match here. That leads to blocking of + * the packet later because the add fails. + */ + pass &= ~FR_KEEPSTATE; + } if ((pass & FR_LOGFIRST) != 0) pass &= ~(FR_LOGFIRST|FR_LOG); *passp = pass; } + RWLOCK_EXIT(&softc->ipf_frag); } - RWLOCK_EXIT(&ipf_frag); return fr; } /* ------------------------------------------------------------------------ */ -/* Function: fr_forget */ -/* Returns: Nil */ -/* Parameters: ptr(I) - pointer to data structure */ -/* */ -/* Search through all of the fragment cache entries and wherever a pointer */ -/* is found to match ptr, reset it to NULL. */ -/* ------------------------------------------------------------------------ */ -void fr_forget(ptr) -void *ptr; -{ - ipfr_t *fr; - - WRITE_ENTER(&ipf_frag); - for (fr = ipfr_list; fr; fr = fr->ipfr_next) - if (fr->ipfr_data == ptr) - fr->ipfr_data = NULL; - RWLOCK_EXIT(&ipf_frag); -} - - -/* ------------------------------------------------------------------------ */ -/* Function: fr_forgetnat */ +/* Function: ipf_frag_natforget */ /* Returns: Nil */ /* Parameters: ptr(I) - pointer to data structure */ /* */ /* Search through all of the fragment cache entries for NAT and wherever a */ /* pointer is found to match ptr, reset it to NULL. */ /* ------------------------------------------------------------------------ */ -void fr_forgetnat(ptr) -void *ptr; +void +ipf_frag_natforget(softc, ptr) + ipf_main_softc_t *softc; + void *ptr; { + ipf_frag_softc_t *softf = softc->ipf_frag_soft; ipfr_t *fr; - WRITE_ENTER(&ipf_natfrag); - for (fr = ipfr_natlist; fr; fr = fr->ipfr_next) + WRITE_ENTER(&softf->ipfr_natfrag); + for (fr = softf->ipfr_natlist; fr; fr = fr->ipfr_next) if (fr->ipfr_data == ptr) fr->ipfr_data = NULL; - RWLOCK_EXIT(&ipf_natfrag); + RWLOCK_EXIT(&softf->ipfr_natfrag); } /* ------------------------------------------------------------------------ */ -/* Function: fr_fragdelete */ +/* Function: ipf_frag_delete */ /* Returns: Nil */ /* Parameters: fra(I) - pointer to fragment structure to delete */ /* tail(IO) - pointer to the pointer to the tail of the frag */ @@ -678,14 +980,12 @@ void *ptr; /* the filter rule it is associated with it if it is no longer used as a */ /* result of decreasing the reference count. */ /* ------------------------------------------------------------------------ */ -static void fr_fragdelete(fra, tail) -ipfr_t *fra, ***tail; +static void +ipf_frag_delete(softc, fra, tail) + ipf_main_softc_t *softc; + ipfr_t *fra, ***tail; { - frentry_t *fr; - - fr = fra->ipfr_rule; - if (fr != NULL) - (void)fr_derefrule(&fr); + ipf_frag_softc_t *softf = softc->ipf_frag_soft; if (fra->ipfr_next) fra->ipfr_next->ipfr_prev = fra->ipfr_prev; @@ -696,87 +996,114 @@ ipfr_t *fra, ***tail; if (fra->ipfr_hnext) fra->ipfr_hnext->ipfr_hprev = fra->ipfr_hprev; *fra->ipfr_hprev = fra->ipfr_hnext; + + if (fra->ipfr_rule != NULL) { + (void) ipf_derefrule(softc, &fra->ipfr_rule); + } + + if (fra->ipfr_ref <= 0) + ipf_frag_free(softf, fra); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_frag_free */ +/* Returns: Nil */ +/* */ +/* ------------------------------------------------------------------------ */ +static void +ipf_frag_free(softf, fra) + ipf_frag_softc_t *softf; + ipfr_t *fra; +{ KFREE(fra); + FBUMP(ifs_expire); + softf->ipfr_stats.ifs_inuse--; } /* ------------------------------------------------------------------------ */ -/* Function: fr_fragclear */ +/* Function: ipf_frag_clear */ /* Returns: Nil */ /* Parameters: Nil */ /* */ /* Free memory in use by fragment state information kept. Do the normal */ /* fragment state stuff first and then the NAT-fragment table. */ /* ------------------------------------------------------------------------ */ -void fr_fragclear() +void +ipf_frag_clear(softc) + ipf_main_softc_t *softc; { + ipf_frag_softc_t *softf = softc->ipf_frag_soft; ipfr_t *fra; nat_t *nat; - WRITE_ENTER(&ipf_frag); - while ((fra = ipfr_list) != NULL) - fr_fragdelete(fra, &ipfr_tail); - ipfr_tail = &ipfr_list; - RWLOCK_EXIT(&ipf_frag); + WRITE_ENTER(&softc->ipf_frag); + while ((fra = softf->ipfr_list) != NULL) { + fra->ipfr_ref--; + ipf_frag_delete(softc, fra, &softf->ipfr_tail); + } + softf->ipfr_tail = &softf->ipfr_list; + RWLOCK_EXIT(&softc->ipf_frag); - WRITE_ENTER(&ipf_nat); - WRITE_ENTER(&ipf_natfrag); - while ((fra = ipfr_natlist) != NULL) { + WRITE_ENTER(&softc->ipf_nat); + WRITE_ENTER(&softf->ipfr_natfrag); + while ((fra = softf->ipfr_natlist) != NULL) { nat = fra->ipfr_data; if (nat != NULL) { if (nat->nat_data == fra) nat->nat_data = NULL; } - fr_fragdelete(fra, &ipfr_nattail); + fra->ipfr_ref--; + ipf_frag_delete(softc, fra, &softf->ipfr_nattail); } - ipfr_nattail = &ipfr_natlist; - RWLOCK_EXIT(&ipf_natfrag); - RWLOCK_EXIT(&ipf_nat); + softf->ipfr_nattail = &softf->ipfr_natlist; + RWLOCK_EXIT(&softf->ipfr_natfrag); + RWLOCK_EXIT(&softc->ipf_nat); } /* ------------------------------------------------------------------------ */ -/* Function: fr_fragexpire */ +/* Function: ipf_frag_expire */ /* Returns: Nil */ /* Parameters: Nil */ /* */ /* Expire entries in the fragment cache table that have been there too long */ /* ------------------------------------------------------------------------ */ -void fr_fragexpire() +void +ipf_frag_expire(softc) + ipf_main_softc_t *softc; { + ipf_frag_softc_t *softf = softc->ipf_frag_soft; ipfr_t **fp, *fra; nat_t *nat; -#if defined(USE_SPL) && defined(_KERNEL) - int s; -#endif + SPL_INT(s); - if (fr_frag_lock) + if (softf->ipfr_lock) return; SPL_NET(s); - WRITE_ENTER(&ipf_frag); + WRITE_ENTER(&softc->ipf_frag); /* * Go through the entire table, looking for entries to expire, - * which is indicated by the ttl being less than or equal to fr_ticks. + * which is indicated by the ttl being less than or equal to ipf_ticks. */ - for (fp = &ipfr_list; ((fra = *fp) != NULL); ) { - if (fra->ipfr_ttl > fr_ticks) + for (fp = &softf->ipfr_list; ((fra = *fp) != NULL); ) { + if (fra->ipfr_ttl > softc->ipf_ticks) break; - fr_fragdelete(fra, &ipfr_tail); - ipfr_stats.ifs_expire++; - ipfr_inuse--; + fra->ipfr_ref--; + ipf_frag_delete(softc, fra, &softf->ipfr_tail); } - RWLOCK_EXIT(&ipf_frag); + RWLOCK_EXIT(&softc->ipf_frag); - WRITE_ENTER(&ipf_ipidfrag); - for (fp = &ipfr_ipidlist; ((fra = *fp) != NULL); ) { - if (fra->ipfr_ttl > fr_ticks) + WRITE_ENTER(&softf->ipfr_ipidfrag); + for (fp = &softf->ipfr_ipidlist; ((fra = *fp) != NULL); ) { + if (fra->ipfr_ttl > softc->ipf_ticks) break; - fr_fragdelete(fra, &ipfr_ipidtail); - ipfr_stats.ifs_expire++; - ipfr_inuse--; + fra->ipfr_ref--; + ipf_frag_delete(softc, fra, &softf->ipfr_ipidtail); } - RWLOCK_EXIT(&ipf_ipidfrag); + RWLOCK_EXIT(&softf->ipfr_ipidfrag); /* * Same again for the NAT table, except that if the structure also @@ -784,75 +1111,225 @@ void fr_fragexpire() * at the one to be free'd, NULL the reference from the NAT struct. * NOTE: We need to grab both mutex's early, and in this order so as * to prevent a deadlock if both try to expire at the same time. + * The extra if() statement here is because it locks out all NAT + * operations - no need to do that if there are no entries in this + * list, right? */ - WRITE_ENTER(&ipf_nat); - WRITE_ENTER(&ipf_natfrag); - for (fp = &ipfr_natlist; ((fra = *fp) != NULL); ) { - if (fra->ipfr_ttl > fr_ticks) - break; - nat = fra->ipfr_data; - if (nat != NULL) { - if (nat->nat_data == fra) - nat->nat_data = NULL; + if (softf->ipfr_natlist != NULL) { + WRITE_ENTER(&softc->ipf_nat); + WRITE_ENTER(&softf->ipfr_natfrag); + for (fp = &softf->ipfr_natlist; ((fra = *fp) != NULL); ) { + if (fra->ipfr_ttl > softc->ipf_ticks) + break; + nat = fra->ipfr_data; + if (nat != NULL) { + if (nat->nat_data == fra) + nat->nat_data = NULL; + } + fra->ipfr_ref--; + ipf_frag_delete(softc, fra, &softf->ipfr_nattail); } - fr_fragdelete(fra, &ipfr_nattail); - ipfr_stats.ifs_expire++; - ipfr_inuse--; + RWLOCK_EXIT(&softf->ipfr_natfrag); + RWLOCK_EXIT(&softc->ipf_nat); } - RWLOCK_EXIT(&ipf_natfrag); - RWLOCK_EXIT(&ipf_nat); SPL_X(s); } /* ------------------------------------------------------------------------ */ -/* Function: fr_slowtimer */ +/* Function: ipf_frag_pkt_next */ +/* ------------------------------------------------------------------------ */ +int +ipf_frag_pkt_next(softc, token, itp) + ipf_main_softc_t *softc; + ipftoken_t *token; + ipfgeniter_t *itp; +{ + ipf_frag_softc_t *softf = softc->ipf_frag_soft; + +#ifdef USE_MUTEXES + return ipf_frag_next(softc, token, itp, &softf->ipfr_list, + &softf->ipfr_frag); +#else + return ipf_frag_next(softc, token, itp, &softf->ipfr_list); +#endif +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_frag_nat_next */ +/* ------------------------------------------------------------------------ */ +int +ipf_frag_nat_next(softc, token, itp) + ipf_main_softc_t *softc; + ipftoken_t *token; + ipfgeniter_t *itp; +{ + ipf_frag_softc_t *softf = softc->ipf_frag_soft;; + +#ifdef USE_MUTEXES + return ipf_frag_next(softc, token, itp, &softf->ipfr_natlist, + &softf->ipfr_natfrag); +#else + return ipf_frag_next(softc, token, itp, &softf->ipfr_natlist); +#endif +} + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_frag_next */ +/* Returns: int - 0 == success, else error */ +/* Parameters: token(I) - pointer to token information for this caller */ +/* itp(I) - pointer to generic iterator from caller */ +/* top(I) - top of the fragment list */ +/* lock(I) - fragment cache lock */ +/* */ +/* This function is used to interate through the list of entries in the */ +/* fragment cache. It increases the reference count on the one currently */ +/* being returned so that the caller can come back and resume from it later.*/ +/* */ +/* This function is used for both the NAT fragment cache as well as the ipf */ +/* fragment cache - hence the reason for passing in top and lock. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_frag_next(softc, token, itp, top +#ifdef USE_MUTEXES +, lock +#endif +) + ipf_main_softc_t *softc; + ipftoken_t *token; + ipfgeniter_t *itp; + ipfr_t **top; +#ifdef USE_MUTEXES + ipfrwlock_t *lock; +#endif +{ + ipfr_t *frag, *next, zero; + int error = 0; + + if (itp->igi_data == NULL) { + IPFERROR(20001); + return EFAULT; + } + + if (itp->igi_nitems != 1) { + IPFERROR(20003); + return EFAULT; + } + + frag = token->ipt_data; + + READ_ENTER(lock); + + if (frag == NULL) + next = *top; + else + next = frag->ipfr_next; + + if (next != NULL) { + ATOMIC_INC(next->ipfr_ref); + token->ipt_data = next; + } else { + bzero(&zero, sizeof(zero)); + next = &zero; + token->ipt_data = NULL; + } + if (next->ipfr_next == NULL) + ipf_token_mark_complete(token); + + RWLOCK_EXIT(lock); + + error = COPYOUT(next, itp->igi_data, sizeof(*next)); + if (error != 0) + IPFERROR(20002); + + if (frag != NULL) { +#ifdef USE_MUTEXES + ipf_frag_deref(softc, &frag, lock); +#else + ipf_frag_deref(softc, &frag); +#endif + } + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_frag_pkt_deref */ /* Returns: Nil */ -/* Parameters: Nil */ /* */ -/* Slowly expire held state for fragments. Timeouts are set * in */ -/* expectation of this being called twice per second. */ -/* ------------------------------------------------------------------------ */ -#if !defined(_KERNEL) || (!SOLARIS && !defined(__hpux) && !defined(__sgi) && \ - !defined(__osf__)) -# if defined(_KERNEL) && ((BSD >= 199103) || defined(__sgi)) -void fr_slowtimer __P((void *ptr)) -# else -int fr_slowtimer() -# endif +/* ------------------------------------------------------------------------ */ +void +ipf_frag_pkt_deref(softc, data) + ipf_main_softc_t *softc; + void *data; { - READ_ENTER(&ipf_global); - - fr_fragexpire(); - fr_timeoutstate(); - fr_natexpire(); - fr_authexpire(); - fr_ticks++; - if (fr_running <= 0) - goto done; -# ifdef _KERNEL -# if defined(__NetBSD__) && (__NetBSD_Version__ >= 104240000) - callout_reset(&fr_slowtimer_ch, hz / 2, fr_slowtimer, NULL); -# else -# if defined(__OpenBSD__) - timeout_add(&fr_slowtimer_ch, hz/2); -# else -# if (__FreeBSD_version >= 300000) - fr_slowtimer_ch = timeout(fr_slowtimer, NULL, hz/2); -# else -# ifdef linux - ; -# else - timeout(fr_slowtimer, NULL, hz/2); -# endif -# endif /* FreeBSD */ -# endif /* OpenBSD */ -# endif /* NetBSD */ -# endif -done: - RWLOCK_EXIT(&ipf_global); -# if (BSD < 199103) || !defined(_KERNEL) - return 0; -# endif + ipfr_t **frp = data; + +#ifdef USE_MUTEXES + ipf_frag_softc_t *softf = softc->ipf_frag_soft; + + ipf_frag_deref(softc->ipf_frag_soft, frp, &softf->ipfr_frag); +#else + ipf_frag_deref(softc->ipf_frag_soft, frp); +#endif +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_frag_nat_deref */ +/* Returns: Nil */ +/* */ +/* ------------------------------------------------------------------------ */ +void +ipf_frag_nat_deref(softc, data) + ipf_main_softc_t *softc; + void *data; +{ + ipfr_t **frp = data; + +#ifdef USE_MUTEXES + ipf_frag_softc_t *softf = softc->ipf_frag_soft; + + ipf_frag_deref(softc->ipf_frag_soft, frp, &softf->ipfr_natfrag); +#else + ipf_frag_deref(softc->ipf_frag_soft, frp); +#endif +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_frag_deref */ +/* Returns: Nil */ +/* Parameters: frp(IO) - pointer to fragment structure to deference */ +/* lock(I) - lock associated with the fragment */ +/* */ +/* This function dereferences a fragment structure (ipfr_t). The pointer */ +/* passed in will always be reset back to NULL, even if the structure is */ +/* not freed, to enforce the notion that the caller is no longer entitled */ +/* to use the pointer it is dropping the reference to. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_frag_deref(arg, frp +#ifdef USE_MUTEXES +, lock +#endif +) + void *arg; + ipfr_t **frp; +#ifdef USE_MUTEXES + ipfrwlock_t *lock; +#endif +{ + ipf_frag_softc_t *softf = arg; + ipfr_t *fra; + + fra = *frp; + *frp = NULL; + + WRITE_ENTER(lock); + fra->ipfr_ref--; + if (fra->ipfr_ref <= 0) + ipf_frag_free(softf, fra); + RWLOCK_EXIT(lock); } -#endif /* !SOLARIS && !defined(__hpux) && !defined(__sgi) */ diff --git a/ip_frag.h b/ip_frag.h index 786a088210860..0d7199e5850e3 100644 --- a/ip_frag.h +++ b/ip_frag.h @@ -1,12 +1,10 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_frag.h 1.5 3/24/96 - * Id: ip_frag.h,v 2.23.2.1 2004/03/29 16:21:56 darrenr Exp + * $Id$ */ #ifndef __IP_FRAG_H__ @@ -18,22 +16,35 @@ typedef struct ipfr { struct ipfr *ipfr_hnext, **ipfr_hprev; struct ipfr *ipfr_next, **ipfr_prev; void *ipfr_data; + frentry_t *ipfr_rule; + u_long ipfr_ttl; + u_int ipfr_pkts; + u_int ipfr_bytes; + u_int ipfr_badorder; + int ipfr_ref; + u_short ipfr_off; + u_short ipfr_firstend; + u_char ipfr_p; + u_char ipfr_seen0; + /* + * All of the fields, from ipfr_ifp to ipfr_pass, are compared + * using bcmp to see if an identical entry is present. It is + * therefore important for this set to remain together. + */ void *ipfr_ifp; - struct in_addr ipfr_src; - struct in_addr ipfr_dst; + i6addr_t ipfr_source; + i6addr_t ipfr_dest; u_32_t ipfr_optmsk; u_short ipfr_secmsk; u_short ipfr_auth; - u_short ipfr_id; - u_char ipfr_p; - u_char ipfr_tos; + u_32_t ipfr_id; u_32_t ipfr_pass; - u_short ipfr_off; - u_char ipfr_ttl; - u_char ipfr_seen0; - frentry_t *ipfr_rule; + int ipfr_v; } ipfr_t; +#define ipfr_src ipfr_source.in4 +#define ipfr_dst ipfr_dest.in4 + typedef struct ipfrstat { u_long ifs_exists; /* add & already exists */ @@ -44,6 +55,14 @@ typedef struct ipfrstat { u_long ifs_inuse; u_long ifs_retrans0; u_long ifs_short; + u_long ifs_bad; + u_long ifs_overlap; + u_long ifs_unordered; + u_long ifs_strict; + u_long ifs_miss; + u_long ifs_maximum; + u_long ifs_newbad; + u_long ifs_newrestrictnot0; struct ipfr **ifs_table; struct ipfr **ifs_nattab; } ipfrstat_t; @@ -51,36 +70,32 @@ typedef struct ipfrstat { #define IPFR_CMPSZ (offsetof(ipfr_t, ipfr_pass) - \ offsetof(ipfr_t, ipfr_ifp)) -extern int ipfr_size; -extern int fr_ipfrttl; -extern int fr_frag_lock; -extern int fr_fraginit __P((void)); -extern void fr_fragunload __P((void)); -extern ipfrstat_t *fr_fragstats __P((void)); - -extern int fr_newfrag __P((fr_info_t *, u_32_t)); -extern frentry_t *fr_knownfrag __P((fr_info_t *, u_32_t *)); - -extern int fr_nat_newfrag __P((fr_info_t *, u_32_t, struct nat *)); -extern nat_t *fr_nat_knownfrag __P((fr_info_t *)); - -extern int fr_ipid_newfrag __P((fr_info_t *, u_32_t)); -extern u_32_t fr_ipid_knownfrag __P((fr_info_t *)); - -extern void fr_forget __P((void *)); -extern void fr_forgetnat __P((void *)); -extern void fr_fragclear __P((void)); -extern void fr_fragexpire __P((void)); - -#if defined(_KERNEL) && ((BSD >= 199306) || SOLARIS || defined(__sgi) \ - || defined(__osf__) || (defined(__sgi) && (IRIX >= 60500))) -# if defined(SOLARIS2) && (SOLARIS2 < 7) -extern void fr_slowtimer __P((void)); -# else -extern void fr_slowtimer __P((void *)); -# endif -#else -extern int fr_slowtimer __P((void)); -#endif +extern void *ipf_frag_soft_create __P((ipf_main_softc_t *)); +extern int ipf_frag_soft_init __P((ipf_main_softc_t *, void *)); +extern int ipf_frag_soft_fini __P((ipf_main_softc_t *, void *)); +extern void ipf_frag_soft_destroy __P((ipf_main_softc_t *, void *)); +extern int ipf_frag_main_load __P((void)); +extern int ipf_frag_main_unload __P((void)); +extern int ipf_frag_load __P((void)); +extern void ipf_frag_clear __P((ipf_main_softc_t *)); +extern void ipf_frag_expire __P((ipf_main_softc_t *)); +extern void ipf_frag_forget __P((void *)); +extern int ipf_frag_init __P((void)); +extern u_32_t ipf_frag_ipidknown __P((fr_info_t *)); +extern int ipf_frag_ipidnew __P((fr_info_t *, u_32_t)); +extern frentry_t *ipf_frag_known __P((fr_info_t *, u_32_t *)); +extern void ipf_frag_natforget __P((ipf_main_softc_t *, void *)); +extern int ipf_frag_natnew __P((ipf_main_softc_t *, fr_info_t *, u_32_t, struct nat *)); +extern nat_t *ipf_frag_natknown __P((fr_info_t *)); +extern int ipf_frag_new __P((ipf_main_softc_t *, fr_info_t *, u_32_t)); +extern ipfrstat_t *ipf_frag_stats __P((void *)); +extern void ipf_frag_setlock __P((void *, int)); +extern void ipf_frag_pkt_deref __P((ipf_main_softc_t *, void *)); +extern int ipf_frag_pkt_next __P((ipf_main_softc_t *, ipftoken_t *, + ipfgeniter_t *)); +extern void ipf_frag_nat_deref __P((ipf_main_softc_t *, void *)); +extern int ipf_frag_nat_next __P((ipf_main_softc_t *, ipftoken_t *, + ipfgeniter_t *)); +extern void ipf_slowtimer __P((ipf_main_softc_t *)); #endif /* __IP_FRAG_H__ */ diff --git a/ip_ftp_pxy.c b/ip_ftp_pxy.c index 5bdc18a7c1ed2..15370a27820e7 100644 --- a/ip_ftp_pxy.c +++ b/ip_ftp_pxy.c @@ -1,19 +1,18 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1997-2003 by Darren Reed + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * Simple FTP transparent proxy for in-kernel use. For use with the NAT * code. * - * Id: ip_ftp_pxy.c,v 2.88.2.15 2005/03/19 19:38:10 darrenr Exp + * $Id$ */ #define IPF_FTP_PROXY #define IPF_MINPORTLEN 18 +#define IPF_MINEPRTLEN 20 #define IPF_MAXPORTLEN 30 #define IPF_MIN227LEN 39 #define IPF_MAX227LEN 51 @@ -37,93 +36,197 @@ #define FTPXY_PASS_2 14 #define FTPXY_PAOK_2 15 +#define FTPXY_JUNK_OK 0 +#define FTPXY_JUNK_BAD 1 /* Ignore all commands for this connection */ +#define FTPXY_JUNK_EOL 2 /* consume the rest of this line only */ +#define FTPXY_JUNK_CONT 3 /* Saerching for next numeric */ + /* * Values for FTP commands. Numerics cover 0-999 */ #define FTPXY_C_PASV 1000 +#define FTPXY_C_PORT 1001 +#define FTPXY_C_EPSV 1002 +#define FTPXY_C_EPRT 1003 + + +typedef struct ipf_ftp_softc_s { + int ipf_p_ftp_pasvonly; + /* Do not require logins before transfers */ + int ipf_p_ftp_insecure; + int ipf_p_ftp_pasvrdr; + /* PASV must be last command prior to 227 */ + int ipf_p_ftp_forcepasv; + int ipf_p_ftp_debug; + int ipf_p_ftp_single_xfer; + void *ipf_p_ftp_tune; +} ipf_ftp_softc_t; + + +void ipf_p_ftp_main_load __P((void)); +void ipf_p_ftp_main_unload __P((void)); +void *ipf_p_ftp_soft_create __P((ipf_main_softc_t *)); +void ipf_p_ftp_soft_destroy __P((ipf_main_softc_t *, void *)); + +int ipf_p_ftp_client __P((ipf_ftp_softc_t *, fr_info_t *, ip_t *, nat_t *, + ftpinfo_t *, int)); +int ipf_p_ftp_complete __P((char *, size_t)); +int ipf_p_ftp_in __P((void *, fr_info_t *, ap_session_t *, nat_t *)); +int ipf_p_ftp_new __P((void *, fr_info_t *, ap_session_t *, nat_t *)); +void ipf_p_ftp_del __P((ipf_main_softc_t *, ap_session_t *)); +int ipf_p_ftp_out __P((void *, fr_info_t *, ap_session_t *, nat_t *)); +int ipf_p_ftp_pasv __P((ipf_ftp_softc_t *, fr_info_t *, ip_t *, nat_t *, + ftpinfo_t *, int)); +int ipf_p_ftp_epsv __P((ipf_ftp_softc_t *, fr_info_t *, ip_t *, nat_t *, + ftpinfo_t *, int)); +int ipf_p_ftp_port __P((ipf_ftp_softc_t *, fr_info_t *, ip_t *, nat_t *, + ftpinfo_t *, int)); +int ipf_p_ftp_process __P((ipf_ftp_softc_t *, fr_info_t *, nat_t *, + ftpinfo_t *, int)); +int ipf_p_ftp_server __P((ipf_ftp_softc_t *, fr_info_t *, ip_t *, nat_t *, + ftpinfo_t *, int)); +int ipf_p_ftp_valid __P((ipf_ftp_softc_t *, ftpinfo_t *, int, char *, size_t)); +int ipf_p_ftp_server_valid __P((ipf_ftp_softc_t *, ftpside_t *, char *, + size_t)); +int ipf_p_ftp_client_valid __P((ipf_ftp_softc_t *, ftpside_t *, char *, + size_t)); +u_short ipf_p_ftp_atoi __P((char **)); +int ipf_p_ftp_pasvreply __P((ipf_ftp_softc_t *, fr_info_t *, ip_t *, nat_t *, + ftpinfo_t *, u_int, char *, char *)); +int ipf_p_ftp_eprt __P((ipf_ftp_softc_t *, fr_info_t *, ip_t *, nat_t *, + ftpinfo_t *, int)); +int ipf_p_ftp_eprt4 __P((ipf_ftp_softc_t *, fr_info_t *, ip_t *, nat_t *, + ftpinfo_t *, int)); +int ipf_p_ftp_eprt6 __P((ipf_ftp_softc_t *, fr_info_t *, ip_t *, nat_t *, + ftpinfo_t *, int)); +int ipf_p_ftp_addport __P((ipf_ftp_softc_t *, fr_info_t *, ip_t *, nat_t *, + ftpinfo_t *, int, int, int)); +void ipf_p_ftp_setpending __P((ipf_main_softc_t *, ftpinfo_t *)); -int ippr_ftp_client __P((fr_info_t *, ip_t *, nat_t *, ftpinfo_t *, int)); -int ippr_ftp_complete __P((char *, size_t)); -int ippr_ftp_in __P((fr_info_t *, ap_session_t *, nat_t *)); -int ippr_ftp_init __P((void)); -void ippr_ftp_fini __P((void)); -int ippr_ftp_new __P((fr_info_t *, ap_session_t *, nat_t *)); -int ippr_ftp_out __P((fr_info_t *, ap_session_t *, nat_t *)); -int ippr_ftp_pasv __P((fr_info_t *, ip_t *, nat_t *, ftpinfo_t *, int)); -int ippr_ftp_epsv __P((fr_info_t *, ip_t *, nat_t *, ftpside_t *, int)); -int ippr_ftp_port __P((fr_info_t *, ip_t *, nat_t *, ftpside_t *, int)); -int ippr_ftp_process __P((fr_info_t *, nat_t *, ftpinfo_t *, int)); -int ippr_ftp_server __P((fr_info_t *, ip_t *, nat_t *, ftpinfo_t *, int)); -int ippr_ftp_valid __P((ftpinfo_t *, int, char *, size_t)); -int ippr_ftp_server_valid __P((ftpside_t *, char *, size_t)); -int ippr_ftp_client_valid __P((ftpside_t *, char *, size_t)); -u_short ippr_ftp_atoi __P((char **)); -int ippr_ftp_pasvreply __P((fr_info_t *, ip_t *, nat_t *, ftpside_t *, - u_int, char *, char *, u_int)); - - -int ftp_proxy_init = 0; -int ippr_ftp_pasvonly = 0; -int ippr_ftp_insecure = 0; /* Do not require logins before transfers */ -int ippr_ftp_pasvrdr = 0; -int ippr_ftp_forcepasv = 0; /* PASV must be last command prior to 227 */ -#if defined(_KERNEL) -int ippr_ftp_debug = 0; -#else -int ippr_ftp_debug = 2; -#endif /* - * 1 - security - * 2 - errors - * 3 - error debugging - * 4 - parsing errors - * 5 - parsing info - * 6 - parsing debug + * Debug levels */ - +#define DEBUG_SECURITY 0x01 +#define DEBUG_ERROR 0x02 +#define DEBUG_INFO 0x04 +#define DEBUG_PARSE_ERR 0x08 +#define DEBUG_PARSE_INFO 0x10 +#define DEBUG_PARSE 0x20 + +static int ipf_p_ftp_proxy_init = 0; static frentry_t ftppxyfr; -static ipftuneable_t ftptune = { - { &ippr_ftp_debug }, - "ippr_ftp_debug", - 0, - 10, - sizeof(ippr_ftp_debug), - 0, - NULL +static ipftuneable_t ipf_ftp_tuneables[] = { + { { (void *)offsetof(ipf_ftp_softc_t, ipf_p_ftp_debug) }, + "ftp_debug", 0, 0x7f, + stsizeof(ipf_ftp_softc_t, ipf_p_ftp_debug), + 0, NULL, NULL }, + { { (void *)offsetof(ipf_ftp_softc_t, ipf_p_ftp_pasvonly) }, + "ftp_pasvonly", 0, 1, + stsizeof(ipf_ftp_softc_t, ipf_p_ftp_pasvonly), + 0, NULL, NULL }, + { { (void *)offsetof(ipf_ftp_softc_t, ipf_p_ftp_insecure) }, + "ftp_insecure", 0, 1, + stsizeof(ipf_ftp_softc_t, ipf_p_ftp_insecure), + 0, NULL, NULL }, + { { (void *)offsetof(ipf_ftp_softc_t, ipf_p_ftp_pasvrdr) }, + "ftp_pasvrdr", 0, 1, + stsizeof(ipf_ftp_softc_t, ipf_p_ftp_pasvrdr), + 0, NULL, NULL }, + { { (void *)offsetof(ipf_ftp_softc_t, ipf_p_ftp_forcepasv) }, + "ftp_forcepasv", 0, 1, + stsizeof(ipf_ftp_softc_t, ipf_p_ftp_forcepasv), + 0, NULL, NULL }, + { { (void *)offsetof(ipf_ftp_softc_t, ipf_p_ftp_single_xfer) }, + "ftp_single_xfer", 0, 1, + stsizeof(ipf_ftp_softc_t, ipf_p_ftp_single_xfer), + 0, NULL, NULL }, + { { NULL }, NULL, 0, 0, 0, 0, NULL, NULL } }; -/* - * Initialize local structures. - */ -int ippr_ftp_init() +void +ipf_p_ftp_main_load() { bzero((char *)&ftppxyfr, sizeof(ftppxyfr)); ftppxyfr.fr_ref = 1; ftppxyfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE; - MUTEX_INIT(&ftppxyfr.fr_lock, "FTP Proxy Mutex"); - ftp_proxy_init = 1; - (void) fr_addipftune(&ftptune); - return 0; + MUTEX_INIT(&ftppxyfr.fr_lock, "FTP Proxy Mutex"); + ipf_p_ftp_proxy_init = 1; } -void ippr_ftp_fini() +void +ipf_p_ftp_main_unload() { - (void) fr_delipftune(&ftptune); - if (ftp_proxy_init == 1) { + if (ipf_p_ftp_proxy_init == 1) { MUTEX_DESTROY(&ftppxyfr.fr_lock); - ftp_proxy_init = 0; + ipf_p_ftp_proxy_init = 0; + } +} + + +/* + * Initialize local structures. + */ +void * +ipf_p_ftp_soft_create(softc) + ipf_main_softc_t *softc; +{ + ipf_ftp_softc_t *softf; + + KMALLOC(softf, ipf_ftp_softc_t *); + if (softf == NULL) + return NULL; + + bzero((char *)softf, sizeof(*softf)); +#if defined(_KERNEL) + softf->ipf_p_ftp_debug = 0; +#else + softf->ipf_p_ftp_debug = DEBUG_PARSE_ERR; +#endif + softf->ipf_p_ftp_forcepasv = 1; + + softf->ipf_p_ftp_tune = ipf_tune_array_copy(softf, + sizeof(ipf_ftp_tuneables), + ipf_ftp_tuneables); + if (softf->ipf_p_ftp_tune == NULL) { + ipf_p_ftp_soft_destroy(softc, softf); + return NULL; + } + if (ipf_tune_array_link(softc, softf->ipf_p_ftp_tune) == -1) { + ipf_p_ftp_soft_destroy(softc, softf); + return NULL; + } + + return softf; +} + + +void +ipf_p_ftp_soft_destroy(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_ftp_softc_t *softf = arg; + + if (softf->ipf_p_ftp_tune != NULL) { + ipf_tune_array_unlink(softc, softf->ipf_p_ftp_tune); + KFREES(softf->ipf_p_ftp_tune, sizeof(ipf_ftp_tuneables)); + softf->ipf_p_ftp_tune = NULL; } + + KFREE(softf); } -int ippr_ftp_new(fin, aps, nat) -fr_info_t *fin; -ap_session_t *aps; -nat_t *nat; +int +ipf_p_ftp_new(arg, fin, aps, nat) + void *arg; + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; { ftpinfo_t *ftp; ftpside_t *f; @@ -132,11 +235,12 @@ nat_t *nat; if (ftp == NULL) return -1; - fin = fin; /* LINT */ nat = nat; /* LINT */ aps->aps_data = ftp; aps->aps_psiz = sizeof(ftpinfo_t); + aps->aps_sport = htons(fin->fin_sport); + aps->aps_dport = htons(fin->fin_dport); bzero((char *)ftp, sizeof(*ftp)); f = &ftp->ftp_side[0]; @@ -151,25 +255,53 @@ nat_t *nat; } -int ippr_ftp_port(fin, ip, nat, f, dlen) -fr_info_t *fin; -ip_t *ip; -nat_t *nat; -ftpside_t *f; -int dlen; +void +ipf_p_ftp_setpending(ipf_main_softc_t *softc, ftpinfo_t *ftp) +{ + if (ftp->ftp_pendnat != NULL) + ipf_nat_setpending(softc, ftp->ftp_pendnat); + + if (ftp->ftp_pendstate != NULL) { + READ_ENTER(&softc->ipf_state); + ipf_state_setpending(softc, ftp->ftp_pendstate); + RWLOCK_EXIT(&softc->ipf_state); + } +} + + +void +ipf_p_ftp_del(softc, aps) + ipf_main_softc_t *softc; + ap_session_t *aps; +{ + ftpinfo_t *ftp; + + ftp = aps->aps_data; + if (ftp != NULL) + ipf_p_ftp_setpending(softc, ftp); +} + + +int +ipf_p_ftp_port(softf, fin, ip, nat, ftp, dlen) + ipf_ftp_softc_t *softf; + fr_info_t *fin; + ip_t *ip; + nat_t *nat; + ftpinfo_t *ftp; + int dlen; { - tcphdr_t *tcp, tcph, *tcp2 = &tcph; char newbuf[IPF_FTPBUFSZ], *s; - struct in_addr swip, swip2; u_int a1, a2, a3, a4; - int inc, off, flags; u_short a5, a6, sp; size_t nlen, olen; - fr_info_t fi; - nat_t *nat2; + tcphdr_t *tcp; + int inc, off; + ftpside_t *f; mb_t *m; m = fin->fin_m; + f = &ftp->ftp_side[0]; tcp = (tcphdr_t *)fin->fin_dp; off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff; @@ -177,8 +309,10 @@ int dlen; * Check for client sending out PORT message. */ if (dlen < IPF_MINPORTLEN) { - if (ippr_ftp_debug > 1) - printf("ippr_ftp_port:dlen(%d) < IPF_MINPORTLEN\n", + DT3(ftp_PORT_error_dlen, nat_t *, nat, ftpside_t *, f, + u_int, dlen); + if (softf->ipf_p_ftp_debug & DEBUG_PARSE) + printf("ipf_p_ftp_port:dlen(%d) < IPF_MINPORTLEN\n", dlen); return 0; } @@ -189,16 +323,18 @@ int dlen; /* * Pick out the address components, two at a time. */ - a1 = ippr_ftp_atoi(&s); + a1 = ipf_p_ftp_atoi(&s); if (s == NULL) { - if (ippr_ftp_debug > 1) - printf("ippr_ftp_port:ippr_ftp_atoi(%d) failed\n", 1); + DT2(ftp_PORT_error_atoi_1, nat_t *, nat, ftpside_t *, f); + if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) + printf("ipf_p_ftp_port:ipf_p_ftp_atoi(%d) failed\n", 1); return 0; } - a2 = ippr_ftp_atoi(&s); + a2 = ipf_p_ftp_atoi(&s); if (s == NULL) { - if (ippr_ftp_debug > 1) - printf("ippr_ftp_port:ippr_ftp_atoi(%d) failed\n", 2); + DT2(ftp_PORT_error_atoi_2, nat_t *, nat, ftpside_t *, f); + if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) + printf("ipf_p_ftp_port:ipf_p_ftp_atoi(%d) failed\n", 2); return 0; } @@ -209,18 +345,21 @@ int dlen; a1 <<= 16; a1 |= a2; if (((nat->nat_dir == NAT_OUTBOUND) && - (a1 != ntohl(nat->nat_inip.s_addr))) || + (a1 != ntohl(nat->nat_osrcaddr))) || ((nat->nat_dir == NAT_INBOUND) && - (a1 != ntohl(nat->nat_oip.s_addr)))) { - if (ippr_ftp_debug > 0) - printf("ippr_ftp_port:%s != nat->nat_inip\n", "a1"); + (a1 != ntohl(nat->nat_nsrcaddr)))) { + DT3(ftp_PORT_error_address, nat_t *, nat, ftpside_t *, f, + u_int, a1); + if (softf->ipf_p_ftp_debug & DEBUG_ERROR) + printf("ipf_p_ftp_port:%s != nat->nat_inip\n", "a1"); return APR_ERR(1); } - a5 = ippr_ftp_atoi(&s); + a5 = ipf_p_ftp_atoi(&s); if (s == NULL) { - if (ippr_ftp_debug > 1) - printf("ippr_ftp_port:ippr_ftp_atoi(%d) failed\n", 3); + DT2(ftp_PORT_error_atoi_3, nat_t *, nat, ftpside_t *, f); + if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) + printf("ipf_p_ftp_port:ipf_p_ftp_atoi(%d) failed\n", 3); return 0; } if (*s == ')') @@ -231,34 +370,31 @@ int dlen; */ if (*s == '\n') s--; - if ((*s == '\r') && (*(s + 1) == '\n')) { - s += 2; - a6 = a5 & 0xff; - } else { - if (ippr_ftp_debug > 1) - printf("ippr_ftp_port:missing %s\n", "cr-lf"); + if ((*s != '\r') || (*(s + 1) != '\n')) { + DT2(ftp_PORT_error_no_crlf, nat_t *, nat, ftpside_t *, f); + if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) + printf("ipf_p_ftp_port:missing %s\n", "cr-lf"); return 0; } + s += 2; + a6 = a5 & 0xff; + /* + * Calculate the source port. Verification of > 1024 is in + * ipf_p_ftp_addport. + */ a5 >>= 8; a5 &= 0xff; sp = a5 << 8 | a6; - /* - * Don't allow the PORT command to specify a port < 1024 due to - * security crap. - */ - if (sp < 1024) { - if (ippr_ftp_debug > 0) - printf("ippr_ftp_port:sp(%d) < 1024\n", sp); - return 0; - } + /* * Calculate new address parts for PORT command */ if (nat->nat_dir == NAT_INBOUND) - a1 = ntohl(nat->nat_oip.s_addr); + a1 = ntohl(nat->nat_ndstaddr); else a1 = ntohl(ip->ip_src.s_addr); + a1 = ntohl(ip->ip_src.s_addr); a2 = (a1 >> 16) & 0xff; a3 = (a1 >> 8) & 0xff; a4 = a1 & 0xff; @@ -275,130 +411,212 @@ int dlen; nlen = strlen(newbuf); inc = nlen - olen; - if ((inc + ip->ip_len) > 65535) { - if (ippr_ftp_debug > 0) - printf("ippr_ftp_port:inc(%d) + ip->ip_len > 65535\n", + if ((inc + fin->fin_plen) > 65535) { + DT3(ftp_PORT_error_inc, nat_t *, nat, ftpside_t *, f, + int, inc); + if (softf->ipf_p_ftp_debug & DEBUG_ERROR) + printf("ipf_p_ftp_port:inc(%d) + ip->ip_len > 65535\n", inc); return 0; } #if !defined(_KERNEL) - bcopy(newbuf, MTOD(m, char *) + off, nlen); + M_ADJ(m, inc); #else -# if defined(MENTAT) - if (inc < 0) - (void)adjmsg(m, inc); -# else /* defined(MENTAT) */ /* * m_adj takes care of pkthdr.len, if required and treats inc<0 to * mean remove -len bytes from the end of the packet. * The mbuf chain will be extended if necessary by m_copyback(). */ if (inc < 0) - m_adj(m, inc); -# endif /* defined(MENTAT) */ + M_ADJ(m, inc); #endif /* !defined(_KERNEL) */ COPYBACK(m, off, nlen, newbuf); + fin->fin_flx |= FI_DOCKSUM; if (inc != 0) { - ip->ip_len += inc; - fin->fin_dlen += inc; fin->fin_plen += inc; + ip->ip_len = htons(fin->fin_plen); + fin->fin_dlen += inc; + } + + f->ftps_cmd = FTPXY_C_PORT; + return ipf_p_ftp_addport(softf, fin, ip, nat, ftp, dlen, sp, inc); +} + + +int +ipf_p_ftp_addport(softf, fin, ip, nat, ftp, dlen, nport, inc) + ipf_ftp_softc_t *softf; + fr_info_t *fin; + ip_t *ip; + nat_t *nat; + ftpinfo_t *ftp; + int dlen, nport, inc; +{ + tcphdr_t tcph, *tcp2 = &tcph; + ipf_main_softc_t *softc; + ipf_nat_softc_t *softn; + int direction; + fr_info_t fi; + ipnat_t *ipn; + nat_t *nat2; + u_short sp; + int flags; + + softc = fin->fin_main_soft; + softn = softc->ipf_nat_soft; + + if ((ftp->ftp_pendnat != NULL) || (ftp->ftp_pendstate != NULL)) { + if (softf->ipf_p_ftp_single_xfer != 0) { + DT2(ftp_PORT_error_add_active, nat_t *, nat, + ftpinfo_t *, ftp); + if (softf->ipf_p_ftp_debug & DEBUG_ERROR) + printf("ipf_p_ftp_addport:xfer active %p/%p\n", + ftp->ftp_pendnat, ftp->ftp_pendstate); + return 0; + } + ipf_p_ftp_setpending(softc, ftp); } /* + * Add skeleton NAT entry for connection which will come back the + * other way. + */ + sp = nport; + /* + * Don't allow the PORT command to specify a port < 1024 due to + * security risks. + */ + if (sp < 1024) { + DT3(ftp_PORT_error_port, nat_t *, nat, ftpinfo_t *, ftp, + u_int, sp); + if (softf->ipf_p_ftp_debug & DEBUG_SECURITY) + printf("ipf_p_ftp_addport:sp(%d) < 1024\n", sp); + return 0; + } + /* * The server may not make the connection back from port 20, but * it is the most likely so use it here to check for a conflicting * mapping. */ bcopy((char *)fin, (char *)&fi, sizeof(fi)); - fi.fin_state = NULL; - fi.fin_nat = NULL; fi.fin_flx |= FI_IGNORE; fi.fin_data[0] = sp; fi.fin_data[1] = fin->fin_data[1] - 1; + fi.fin_src6 = nat->nat_ndst6; + fi.fin_dst6 = nat->nat_nsrc6; + + if (nat->nat_v[0] == 6) { +#ifndef USE_INET6 + return APR_INC(inc); +#endif + } + /* * Add skeleton NAT entry for connection which will come back the * other way. */ - if (nat->nat_dir == NAT_OUTBOUND) - nat2 = nat_outlookup(&fi, NAT_SEARCH|IPN_TCP, nat->nat_p, - nat->nat_inip, nat->nat_oip); - else - nat2 = nat_inlookup(&fi, NAT_SEARCH|IPN_TCP, nat->nat_p, - nat->nat_inip, nat->nat_oip); - if (nat2 == NULL) { - int slen; - - slen = ip->ip_len; - ip->ip_len = fin->fin_hlen + sizeof(*tcp2); - bzero((char *)tcp2, sizeof(*tcp2)); - tcp2->th_win = htons(8192); - tcp2->th_sport = htons(sp); - TCP_OFF_A(tcp2, 5); - tcp2->th_flags = TH_SYN; - tcp2->th_dport = 0; /* XXX - don't specify remote port */ - fi.fin_data[1] = 0; - fi.fin_dlen = sizeof(*tcp2); - fi.fin_plen = fi.fin_hlen + sizeof(*tcp2); - fi.fin_dp = (char *)tcp2; - fi.fin_fr = &ftppxyfr; - fi.fin_out = nat->nat_dir; - fi.fin_flx &= FI_LOWTTL|FI_FRAG|FI_TCPUDP|FI_OPTIONS|FI_IGNORE; - swip = ip->ip_src; - swip2 = ip->ip_dst; + if (nat->nat_v[0] == 6) { +#ifdef USE_INET6 if (nat->nat_dir == NAT_OUTBOUND) { - fi.fin_fi.fi_saddr = nat->nat_inip.s_addr; - ip->ip_src = nat->nat_inip; - } else if (nat->nat_dir == NAT_INBOUND) { - fi.fin_fi.fi_saddr = nat->nat_oip.s_addr; - ip->ip_src = nat->nat_oip; - } - - flags = NAT_SLAVE|IPN_TCP|SI_W_DPORT; - if (nat->nat_dir == NAT_INBOUND) - flags |= NAT_NOTRULEPORT; - nat2 = nat_new(&fi, nat->nat_ptr, NULL, flags, nat->nat_dir); - - if (nat2 != NULL) { - (void) nat_proto(&fi, nat2, IPN_TCP); - nat_update(&fi, nat2, nat->nat_ptr); - fi.fin_ifp = NULL; - if (nat->nat_dir == NAT_INBOUND) { - fi.fin_fi.fi_daddr = nat->nat_inip.s_addr; - ip->ip_dst = nat->nat_inip; - } - (void) fr_addstate(&fi, &nat2->nat_state, SI_W_DPORT); - if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); + nat2 = ipf_nat6_outlookup(&fi, IPN_TCP|NAT_SEARCH, + nat->nat_pr[1], + &nat->nat_osrc6.in6, + &nat->nat_odst6.in6); + } else { + nat2 = ipf_nat6_inlookup(&fi, IPN_TCP|NAT_SEARCH, + nat->nat_pr[0], + &nat->nat_odst6.in6, + &nat->nat_osrc6.in6); } - ip->ip_len = slen; - ip->ip_src = swip; - ip->ip_dst = swip2; +#endif } else { - ipstate_t *is; - - nat_update(&fi, nat2, nat->nat_ptr); - READ_ENTER(&ipf_state); - is = nat2->nat_state; - if (is != NULL) { - MUTEX_ENTER(&is->is_lock); - (void)fr_tcp_age(&is->is_sti, &fi, ips_tqtqb, - is->is_flags); - MUTEX_EXIT(&is->is_lock); + if (nat->nat_dir == NAT_OUTBOUND) { + nat2 = ipf_nat_outlookup(&fi, IPN_TCP|NAT_SEARCH, + nat->nat_pr[1], + nat->nat_osrcip, + nat->nat_odstip); + } else { + nat2 = ipf_nat_inlookup(&fi, IPN_TCP|NAT_SEARCH, + nat->nat_pr[0], + nat->nat_odstip, + nat->nat_osrcip); } - RWLOCK_EXIT(&ipf_state); } + if (nat2 != NULL) + return APR_INC(inc); + + ipn = ipf_proxy_rule_rev(nat); + if (ipn == NULL) + return APR_ERR(1); + ipn->in_use = 0; + + fi.fin_fr = &ftppxyfr; + fi.fin_dp = (char *)tcp2; + fi.fin_dlen = sizeof(*tcp2); + fi.fin_plen = fi.fin_hlen + sizeof(*tcp2); + fi.fin_flx &= FI_LOWTTL|FI_FRAG|FI_TCPUDP|FI_OPTIONS|FI_IGNORE; + fi.fin_data[1] = sp; + fi.fin_data[0] = 0; + + bzero((char *)tcp2, sizeof(*tcp2)); + tcp2->th_sport = 0; + tcp2->th_dport = htons(sp); + + tcp2->th_win = htons(8192); + TCP_OFF_A(tcp2, 5); + tcp2->th_flags = TH_SYN; + + if (nat->nat_dir == NAT_INBOUND) { + fi.fin_out = 1; + direction = NAT_OUTBOUND; + } else { + fi.fin_out = 0; + direction = NAT_INBOUND; + } + flags = SI_W_SPORT|NAT_SLAVE|IPN_TCP; + + MUTEX_ENTER(&softn->ipf_nat_new); + if (nat->nat_v[0] == 6) { +#ifdef USE_INET6 + nat2 = ipf_nat6_add(&fi, ipn, &ftp->ftp_pendnat, flags, + direction); +#endif + } else { + nat2 = ipf_nat_add(&fi, ipn, &ftp->ftp_pendnat, flags, + direction); + } + MUTEX_EXIT(&softn->ipf_nat_new); + + if (nat2 == NULL) { + KFREES(ipn, ipn->in_size); + return APR_ERR(1); + } + + (void) ipf_nat_proto(&fi, nat2, IPN_TCP); + MUTEX_ENTER(&nat2->nat_lock); + ipf_nat_update(&fi, nat2); + MUTEX_EXIT(&nat2->nat_lock); + fi.fin_ifp = NULL; + if (nat2->nat_dir == NAT_INBOUND) + fi.fin_dst6 = nat->nat_osrc6; + if (ipf_state_add(softc, &fi, (ipstate_t **)&ftp->ftp_pendstate, + SI_W_SPORT) != 0) + ipf_nat_setpending(softc, nat2); + return APR_INC(inc); } -int ippr_ftp_client(fin, ip, nat, ftp, dlen) -fr_info_t *fin; -nat_t *nat; -ftpinfo_t *ftp; -ip_t *ip; -int dlen; +int +ipf_p_ftp_client(softf, fin, ip, nat, ftp, dlen) + ipf_ftp_softc_t *softf; + fr_info_t *fin; + nat_t *nat; + ftpinfo_t *ftp; + ip_t *ip; + int dlen; { char *rptr, *wptr, cmd[6], c; ftpside_t *f; @@ -420,6 +638,7 @@ int dlen; cmd[i] = '\0'; ftp->ftp_incok = 0; + DT2(ftp_client_command, char [], cmd, int, ftp->ftp_passok); if (!strncmp(cmd, "USER ", 5) || !strncmp(cmd, "XAUT ", 5)) { if (ftp->ftp_passok == FTPXY_ADOK_1 || ftp->ftp_passok == FTPXY_AUOK_1) { @@ -449,14 +668,24 @@ int dlen; !strncmp(cmd, "ACCT ", 5)) { ftp->ftp_passok = FTPXY_ACCT_1; ftp->ftp_incok = 1; - } else if ((ftp->ftp_passok == FTPXY_GO) && !ippr_ftp_pasvonly && + } else if ((ftp->ftp_passok == FTPXY_GO) && + !softf->ipf_p_ftp_pasvonly && !strncmp(cmd, "PORT ", 5)) { - inc = ippr_ftp_port(fin, ip, nat, f, dlen); - } else if (ippr_ftp_insecure && !ippr_ftp_pasvonly && + inc = ipf_p_ftp_port(softf, fin, ip, nat, ftp, dlen); + } else if ((ftp->ftp_passok == FTPXY_GO) && + !softf->ipf_p_ftp_pasvonly && + !strncmp(cmd, "EPRT ", 5)) { + inc = ipf_p_ftp_eprt(softf, fin, ip, nat, ftp, dlen); + } else if (softf->ipf_p_ftp_insecure && + !softf->ipf_p_ftp_pasvonly && !strncmp(cmd, "PORT ", 5)) { - inc = ippr_ftp_port(fin, ip, nat, f, dlen); + inc = ipf_p_ftp_port(softf, fin, ip, nat, ftp, dlen); } + if (softf->ipf_p_ftp_debug & DEBUG_PARSE) + printf("ipf_p_ftp_client: cmd[%s] passok %d incok %d inc %d\n", + cmd, ftp->ftp_passok, ftp->ftp_incok, inc); + DT2(ftp_client_passok, char *, cmd, int, ftp->ftp_passok); while ((*rptr++ != '\n') && (rptr < wptr)) ; f->ftps_rptr = rptr; @@ -464,24 +693,28 @@ int dlen; } -int ippr_ftp_pasv(fin, ip, nat, ftp, dlen) -fr_info_t *fin; -ip_t *ip; -nat_t *nat; -ftpinfo_t *ftp; -int dlen; +int +ipf_p_ftp_pasv(softf, fin, ip, nat, ftp, dlen) + ipf_ftp_softc_t *softf; + fr_info_t *fin; + ip_t *ip; + nat_t *nat; + ftpinfo_t *ftp; + int dlen; { u_int a1, a2, a3, a4, data_ip; char newbuf[IPF_FTPBUFSZ]; - char *s, *brackets[2]; + const char *brackets[2]; u_short a5, a6; ftpside_t *f; + char *s; - if (ippr_ftp_forcepasv != 0 && - ftp->ftp_side[0].ftps_cmds != FTPXY_C_PASV) { - if (ippr_ftp_debug > 0) - printf("ippr_ftp_pasv:ftps_cmds(%d) != FTPXY_C_PASV\n", - ftp->ftp_side[0].ftps_cmds); + if ((softf->ipf_p_ftp_forcepasv != 0) && + (ftp->ftp_side[0].ftps_cmd != FTPXY_C_PASV)) { + DT2(ftp_PASV_error_state, nat_t *, nat, ftpinfo_t *, ftp); + if (softf->ipf_p_ftp_debug & DEBUG_ERROR) + printf("ipf_p_ftp_pasv:ftps_cmd(%d) != FTPXY_C_PASV\n", + ftp->ftp_side[0].ftps_cmd); return 0; } @@ -492,14 +725,17 @@ int dlen; * Check for PASV reply message. */ if (dlen < IPF_MIN227LEN) { - if (ippr_ftp_debug > 1) - printf("ippr_ftp_pasv:dlen(%d) < IPF_MIN227LEN\n", + DT3(ftp_PASV_error_short, nat_t *, nat, ftpinfo_t *, ftp, + int, dlen); + if (softf->ipf_p_ftp_debug & DEBUG_ERROR) + printf("ipf_p_ftp_pasv:dlen(%d) < IPF_MIN227LEN\n", dlen); return 0; } else if (strncmp(f->ftps_rptr, "227 Entering Passive Mod", PASV_REPLEN)) { - if (ippr_ftp_debug > 0) - printf("ippr_ftp_pasv:%d reply wrong\n", 227); + DT2(ftp_PASV_error_string, nat_t *, nat, ftpinfo_t *, ftp); + if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) + printf("ipf_p_ftp_pasv:%d reply wrong\n", 227); return 0; } @@ -520,16 +756,18 @@ int dlen; /* * Pick out the address components, two at a time. */ - a1 = ippr_ftp_atoi(&s); + a1 = ipf_p_ftp_atoi(&s); if (s == NULL) { - if (ippr_ftp_debug > 1) - printf("ippr_ftp_pasv:ippr_ftp_atoi(%d) failed\n", 1); + DT2(ftp_PASV_error_atoi_1, nat_t *, nat, ftpside_t *, f); + if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) + printf("ipf_p_ftp_pasv:ipf_p_ftp_atoi(%d) failed\n", 1); return 0; } - a2 = ippr_ftp_atoi(&s); + a2 = ipf_p_ftp_atoi(&s); if (s == NULL) { - if (ippr_ftp_debug > 1) - printf("ippr_ftp_pasv:ippr_ftp_atoi(%d) failed\n", 2); + DT2(ftp_PASV_error_atoi_2, nat_t *, nat, ftpside_t *, f); + if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) + printf("ipf_p_ftp_pasv:ipf_p_ftp_atoi(%d) failed\n", 2); return 0; } @@ -541,18 +779,21 @@ int dlen; a1 |= a2; if (((nat->nat_dir == NAT_INBOUND) && - (a1 != ntohl(nat->nat_inip.s_addr))) || + (a1 != ntohl(nat->nat_ndstaddr))) || ((nat->nat_dir == NAT_OUTBOUND) && - (a1 != ntohl(nat->nat_oip.s_addr)))) { - if (ippr_ftp_debug > 0) - printf("ippr_ftp_pasv:%s != nat->nat_oip\n", "a1"); + (a1 != ntohl(nat->nat_odstaddr)))) { + DT3(ftp_PASV_error_address, nat_t *, nat, ftpside_t *, f, + u_int, a1); + if (softf->ipf_p_ftp_debug & DEBUG_ERROR) + printf("ipf_p_ftp_pasv:%s != nat->nat_oip\n", "a1"); return 0; } - a5 = ippr_ftp_atoi(&s); + a5 = ipf_p_ftp_atoi(&s); if (s == NULL) { - if (ippr_ftp_debug > 1) - printf("ippr_ftp_pasv:ippr_ftp_atoi(%d) failed\n", 3); + DT2(ftp_PASV_error_atoi_3, nat_t *, nat, ftpside_t *, f); + if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) + printf("ipf_p_ftp_pasv:ipf_p_ftp_atoi(%d) failed\n", 3); return 0; } @@ -565,13 +806,13 @@ int dlen; /* * check for CR-LF at the end. */ - if ((*s == '\r') && (*(s + 1) == '\n')) { - s += 2; - } else { - if (ippr_ftp_debug > 1) - printf("ippr_ftp_pasv:missing %s", "cr-lf\n"); + if ((*s != '\r') || (*(s + 1) != '\n')) { + DT(pasv_missing_crlf); + if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) + printf("ipf_p_ftp_pasv:missing %s", "cr-lf\n"); return 0; } + s += 2; a6 = a5 & 0xff; a5 >>= 8; @@ -579,7 +820,7 @@ int dlen; * Calculate new address parts for 227 reply */ if (nat->nat_dir == NAT_INBOUND) { - data_ip = nat->nat_outip.s_addr; + data_ip = nat->nat_odstaddr; a1 = ntohl(data_ip); } else data_ip = htonl(a1); @@ -598,169 +839,166 @@ int dlen; "227 Entering Passive Mode", brackets[0], a1, a2, a3, a4, a5, a6, brackets[1]); #endif - return ippr_ftp_pasvreply(fin, ip, nat, f, (a5 << 8 | a6), - newbuf, s, data_ip); + return ipf_p_ftp_pasvreply(softf, fin, ip, nat, ftp, (a5 << 8 | a6), + newbuf, s); } -int ippr_ftp_pasvreply(fin, ip, nat, f, port, newmsg, s, data_ip) -fr_info_t *fin; -ip_t *ip; -nat_t *nat; -ftpside_t *f; -u_int port; -char *newmsg; -char *s; -u_int data_ip; +int +ipf_p_ftp_pasvreply(softf, fin, ip, nat, ftp, port, newmsg, s) + ipf_ftp_softc_t *softf; + fr_info_t *fin; + ip_t *ip; + nat_t *nat; + ftpinfo_t *ftp; + u_int port; + char *newmsg; + char *s; { - int inc, off, nflags, sflags; + int inc, off, nflags; tcphdr_t *tcp, tcph, *tcp2; - struct in_addr swip, swip2; - struct in_addr data_addr; + ipf_main_softc_t *softc; + ipf_nat_softc_t *softn; size_t nlen, olen; +#ifdef USE_INET6 + ip6_t *ip6; +#endif + ipnat_t *ipn; fr_info_t fi; + ftpside_t *f; nat_t *nat2; mb_t *m; + softc = fin->fin_main_soft; + softn = softc->ipf_nat_soft; + + if ((ftp->ftp_pendnat != NULL) || (ftp->ftp_pendstate != NULL)) + ipf_p_ftp_setpending(softc, ftp); + m = fin->fin_m; tcp = (tcphdr_t *)fin->fin_dp; off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff; - data_addr.s_addr = data_ip; tcp2 = &tcph; inc = 0; - + f = &ftp->ftp_side[1]; olen = s - f->ftps_rptr; nlen = strlen(newmsg); inc = nlen - olen; - if ((inc + ip->ip_len) > 65535) { - if (ippr_ftp_debug > 0) - printf("ippr_ftp_pasv:inc(%d) + ip->ip_len > 65535\n", + if ((inc + fin->fin_plen) > 65535) { + DT3(ftp_PASV_error_inc, nat_t *, nat, ftpside_t *, f, + int, inc); + if (softf->ipf_p_ftp_debug & DEBUG_ERROR) + printf("ipf_p_ftp_pasv:inc(%d) + ip->ip_len > 65535\n", inc); return 0; } -#if !defined(_KERNEL) - bcopy(newmsg, MTOD(m, char *) + off, nlen); -#else -# if defined(MENTAT) - if (inc < 0) - (void)adjmsg(m, inc); -# else /* defined(MENTAT) */ - /* - * m_adj takes care of pkthdr.len, if required and treats inc<0 to - * mean remove -len bytes from the end of the packet. - * The mbuf chain will be extended if necessary by m_copyback(). - */ - if (inc < 0) - m_adj(m, inc); -# endif /* defined(MENTAT) */ -#endif /* !defined(_KERNEL) */ - COPYBACK(m, off, nlen, newmsg); - - if (inc != 0) { - ip->ip_len += inc; - fin->fin_dlen += inc; - fin->fin_plen += inc; - } + ipn = ipf_proxy_rule_fwd(nat); + if (ipn == NULL) + return APR_ERR(1); + ipn->in_use = 0; /* * Add skeleton NAT entry for connection which will come back the * other way. */ + bzero((char *)tcp2, sizeof(*tcp2)); bcopy((char *)fin, (char *)&fi, sizeof(fi)); - fi.fin_state = NULL; - fi.fin_nat = NULL; fi.fin_flx |= FI_IGNORE; fi.fin_data[0] = 0; fi.fin_data[1] = port; nflags = IPN_TCP|SI_W_SPORT; - if (ippr_ftp_pasvrdr && f->ftps_ifp) - nflags |= SI_W_DPORT; - if (nat->nat_dir == NAT_OUTBOUND) - nat2 = nat_outlookup(&fi, nflags|NAT_SEARCH, - nat->nat_p, nat->nat_inip, nat->nat_oip); - else - nat2 = nat_inlookup(&fi, nflags|NAT_SEARCH, - nat->nat_p, nat->nat_inip, nat->nat_oip); + + fi.fin_fr = &ftppxyfr; + fi.fin_dp = (char *)tcp2; + fi.fin_out = 1 - fin->fin_out; + fi.fin_dlen = sizeof(*tcp2); + fi.fin_src6 = nat->nat_osrc6; + fi.fin_dst6 = nat->nat_odst6; + fi.fin_plen = fi.fin_hlen + sizeof(*tcp); + fi.fin_flx &= FI_LOWTTL|FI_FRAG|FI_TCPUDP|FI_OPTIONS|FI_IGNORE; + + TCP_OFF_A(tcp2, 5); + tcp2->th_flags = TH_SYN; + tcp2->th_win = htons(8192); + tcp2->th_dport = htons(port); + + MUTEX_ENTER(&softn->ipf_nat_new); + if (nat->nat_v[0] == 6) { +#ifdef USE_INET6 + nat2 = ipf_nat6_add(&fi, ipn, &ftp->ftp_pendnat, + nflags, nat->nat_dir); +#endif + } else { + nat2 = ipf_nat_add(&fi, ipn, &ftp->ftp_pendnat, + nflags, nat->nat_dir); + } + MUTEX_EXIT(&softn->ipf_nat_new); + if (nat2 == NULL) { - int slen; - - slen = ip->ip_len; - ip->ip_len = fin->fin_hlen + sizeof(*tcp2); - bzero((char *)tcp2, sizeof(*tcp2)); - tcp2->th_win = htons(8192); - tcp2->th_sport = 0; /* XXX - fake it for nat_new */ - TCP_OFF_A(tcp2, 5); - tcp2->th_flags = TH_SYN; - fi.fin_data[1] = port; - fi.fin_dlen = sizeof(*tcp2); - tcp2->th_dport = htons(port); - fi.fin_data[0] = 0; - fi.fin_dp = (char *)tcp2; - fi.fin_plen = fi.fin_hlen + sizeof(*tcp); - fi.fin_fr = &ftppxyfr; - fi.fin_out = nat->nat_dir; - fi.fin_flx &= FI_LOWTTL|FI_FRAG|FI_TCPUDP|FI_OPTIONS|FI_IGNORE; - swip = ip->ip_src; - swip2 = ip->ip_dst; - if (nat->nat_dir == NAT_OUTBOUND) { - fi.fin_fi.fi_daddr = data_addr.s_addr; - fi.fin_fi.fi_saddr = nat->nat_inip.s_addr; - ip->ip_dst = data_addr; - ip->ip_src = nat->nat_inip; - } else if (nat->nat_dir == NAT_INBOUND) { - fi.fin_fi.fi_saddr = nat->nat_oip.s_addr; - fi.fin_fi.fi_daddr = nat->nat_outip.s_addr; - ip->ip_src = nat->nat_oip; - ip->ip_dst = nat->nat_outip; - } + KFREES(ipn, ipn->in_size); + return APR_ERR(1); + } - sflags = nflags; - nflags |= NAT_SLAVE; - if (nat->nat_dir == NAT_INBOUND) - nflags |= NAT_NOTRULEPORT; - nat2 = nat_new(&fi, nat->nat_ptr, NULL, nflags, nat->nat_dir); - if (nat2 != NULL) { - (void) nat_proto(&fi, nat2, IPN_TCP); - nat_update(&fi, nat2, nat->nat_ptr); - fi.fin_ifp = NULL; - if (nat->nat_dir == NAT_INBOUND) { - fi.fin_fi.fi_daddr = nat->nat_inip.s_addr; - ip->ip_dst = nat->nat_inip; - } - (void) fr_addstate(&fi, &nat2->nat_state, sflags); - if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); + (void) ipf_nat_proto(&fi, nat2, IPN_TCP); + MUTEX_ENTER(&nat2->nat_lock); + ipf_nat_update(&fi, nat2); + MUTEX_EXIT(&nat2->nat_lock); + fi.fin_ifp = NULL; + if (nat->nat_dir == NAT_INBOUND) { + if (nat->nat_v[0] == 6) { +#ifdef USE_INET6 + fi.fin_dst6 = nat->nat_ndst6; +#endif + } else { + fi.fin_daddr = nat->nat_ndstaddr; } + } + if (ipf_state_add(softc, &fi, (ipstate_t **)&ftp->ftp_pendstate, + SI_W_SPORT) != 0) + ipf_nat_setpending(softc, nat2); - ip->ip_len = slen; - ip->ip_src = swip; - ip->ip_dst = swip2; - } else { - ipstate_t *is; - - nat_update(&fi, nat2, nat->nat_ptr); - READ_ENTER(&ipf_state); - is = nat2->nat_state; - if (is != NULL) { - MUTEX_ENTER(&is->is_lock); - (void)fr_tcp_age(&is->is_sti, &fi, ips_tqtqb, - is->is_flags); - MUTEX_EXIT(&is->is_lock); +#if !defined(_KERNEL) + M_ADJ(m, inc); +#else + /* + * m_adj takes care of pkthdr.len, if required and treats inc<0 to + * mean remove -len bytes from the end of the packet. + * The mbuf chain will be extended if necessary by m_copyback(). + */ + if (inc < 0) + M_ADJ(m, inc); +#endif /* !defined(_KERNEL) */ + COPYBACK(m, off, nlen, newmsg); + fin->fin_flx |= FI_DOCKSUM; + + if (inc != 0) { + fin->fin_plen += inc; + fin->fin_dlen += inc; + if (nat->nat_v[0] == 6) { +#ifdef USE_INET6 + ip6 = (ip6_t *)fin->fin_ip; + u_short len = ntohs(ip6->ip6_plen) + inc; + ip6->ip6_plen = htons(len); +#endif + } else { + ip->ip_len = htons(fin->fin_plen); } - RWLOCK_EXIT(&ipf_state); } - return inc; + + return APR_INC(inc); } -int ippr_ftp_server(fin, ip, nat, ftp, dlen) -fr_info_t *fin; -ip_t *ip; -nat_t *nat; -ftpinfo_t *ftp; -int dlen; +int +ipf_p_ftp_server(softf, fin, ip, nat, ftp, dlen) + ipf_ftp_softc_t *softf; + fr_info_t *fin; + ip_t *ip; + nat_t *nat; + ftpinfo_t *ftp; + int dlen; { char *rptr, *wptr; ftpside_t *f; @@ -771,19 +1009,29 @@ int dlen; rptr = f->ftps_rptr; wptr = f->ftps_wptr; + DT2(ftp_server_response, char *, rptr, int, ftp->ftp_passok); if (*rptr == ' ') goto server_cmd_ok; if (!ISDIGIT(*rptr) || !ISDIGIT(*(rptr + 1)) || !ISDIGIT(*(rptr + 2))) return 0; + if (softf->ipf_p_ftp_debug & DEBUG_PARSE) + printf("ipf_p_ftp_server_1: cmd[%4.4s] passok %d\n", + rptr, ftp->ftp_passok); if (ftp->ftp_passok == FTPXY_GO) { if (!strncmp(rptr, "227 ", 4)) - inc = ippr_ftp_pasv(fin, ip, nat, ftp, dlen); + inc = ipf_p_ftp_pasv(softf, fin, ip, nat, ftp, dlen); else if (!strncmp(rptr, "229 ", 4)) - inc = ippr_ftp_epsv(fin, ip, nat, f, dlen); - } else if (ippr_ftp_insecure && !strncmp(rptr, "227 ", 4)) { - inc = ippr_ftp_pasv(fin, ip, nat, ftp, dlen); - } else if (ippr_ftp_insecure && !strncmp(rptr, "229 ", 4)) { - inc = ippr_ftp_epsv(fin, ip, nat, f, dlen); + inc = ipf_p_ftp_epsv(softf, fin, ip, nat, ftp, dlen); + else if (strncmp(rptr, "200", 3)) { + /* + * 200 is returned for a successful command. + */ + ; + } + } else if (softf->ipf_p_ftp_insecure && !strncmp(rptr, "227 ", 4)) { + inc = ipf_p_ftp_pasv(softf, fin, ip, nat, ftp, dlen); + } else if (softf->ipf_p_ftp_insecure && !strncmp(rptr, "229 ", 4)) { + inc = ipf_p_ftp_epsv(softf, fin, ip, nat, ftp, dlen); } else if (*rptr == '5' || *rptr == '4') ftp->ftp_passok = FTPXY_INIT; else if (ftp->ftp_incok) { @@ -808,8 +1056,13 @@ int dlen; } } } -server_cmd_ok: ftp->ftp_incok = 0; +server_cmd_ok: + if (softf->ipf_p_ftp_debug & DEBUG_PARSE) + printf("ipf_p_ftp_server_2: cmd[%4.4s] passok %d\n", + rptr, ftp->ftp_passok); + DT3(ftp_server_passok, char *,rptr, int, ftp->ftp_incok, + int, ftp->ftp_passok); while ((*rptr++ != '\n') && (rptr < wptr)) ; @@ -819,13 +1072,20 @@ server_cmd_ok: /* + * 0 FTPXY_JUNK_OK + * 1 FTPXY_JUNK_BAD + * 2 FTPXY_JUNK_EOL + * 3 FTPXY_JUNK_CONT + * * Look to see if the buffer starts with something which we recognise as * being the correct syntax for the FTP protocol. */ -int ippr_ftp_client_valid(ftps, buf, len) -ftpside_t *ftps; -char *buf; -size_t len; +int +ipf_p_ftp_client_valid(softf, ftps, buf, len) + ipf_ftp_softc_t *softf; + ftpside_t *ftps; + char *buf; + size_t len; { register char *s, c, pc; register size_t i = len; @@ -833,12 +1093,13 @@ size_t len; s = buf; - if (ftps->ftps_junk == 1) - return 1; + if (ftps->ftps_junk == FTPXY_JUNK_BAD) + return FTPXY_JUNK_BAD; if (i < 5) { - if (ippr_ftp_debug > 3) - printf("ippr_ftp_client_valid:i(%d) < 5\n", (int)i); + DT1(client_valid, int, i); + if (softf->ipf_p_ftp_debug & DEBUG_ERROR) + printf("ipf_p_ftp_client_valid:i(%d) < 5\n", (int)i); return 2; } @@ -871,12 +1132,13 @@ size_t len; goto bad_client_command; } else { bad_client_command: - if (ippr_ftp_debug > 3) + DT4(client_junk, int, len, int, i, int, c, char *, buf); + if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) printf("%s:bad:junk %d len %d/%d c 0x%x buf [%*.*s]\n", - "ippr_ftp_client_valid", + "ipf_p_ftp_client_valid", ftps->ftps_junk, (int)len, (int)i, c, (int)len, (int)len, buf); - return 1; + return FTPXY_JUNK_BAD; } for (; i; i--) { @@ -884,25 +1146,30 @@ bad_client_command: c = *s++; if ((pc == '\r') && (c == '\n')) { cmd[4] = '\0'; - if (!strcmp(cmd, "PASV")) - ftps->ftps_cmds = FTPXY_C_PASV; - else - ftps->ftps_cmds = 0; + if (!strcmp(cmd, "PASV")) { + ftps->ftps_cmd = FTPXY_C_PASV; + } else if (!strcmp(cmd, "EPSV")) { + ftps->ftps_cmd = FTPXY_C_EPSV; + } else { + ftps->ftps_cmd = 0; + } return 0; } } #if !defined(_KERNEL) - printf("ippr_ftp_client_valid:junk after cmd[%*.*s]\n", + printf("ipf_p_ftp_client_valid:junk after cmd[%*.*s]\n", (int)len, (int)len, buf); #endif - return 2; + return FTPXY_JUNK_EOL; } -int ippr_ftp_server_valid(ftps, buf, len) -ftpside_t *ftps; -char *buf; -size_t len; +int +ipf_p_ftp_server_valid(softf, ftps, buf, len) + ipf_ftp_softc_t *softf; + ftpside_t *ftps; + char *buf; + size_t len; { register char *s, c, pc; register size_t i = len; @@ -911,19 +1178,22 @@ size_t len; s = buf; cmd = 0; - if (ftps->ftps_junk == 1) - return 1; + if (ftps->ftps_junk == FTPXY_JUNK_BAD) + return FTPXY_JUNK_BAD; if (i < 5) { - if (ippr_ftp_debug > 3) - printf("ippr_ftp_servert_valid:i(%d) < 5\n", (int)i); + DT1(server_valid, int, i); + if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) + printf("ipf_p_ftp_servert_valid:i(%d) < 5\n", (int)i); return 2; } c = *s++; i--; - if (c == ' ') + if (c == ' ') { + cmd = -1; goto search_eol; + } if (ISDIGIT(c)) { cmd = (c - '0') * 100; @@ -939,40 +1209,54 @@ size_t len; i--; if ((c != '-') && (c != ' ')) goto bad_server_command; + if (c == '-') + return FTPXY_JUNK_CONT; } else goto bad_server_command; } else goto bad_server_command; } else { bad_server_command: - if (ippr_ftp_debug > 3) + DT4(server_junk, int len, buf, int, i, int, c, char *, buf); + if (softf->ipf_p_ftp_debug & DEBUG_PARSE_INFO) printf("%s:bad:junk %d len %d/%d c 0x%x buf [%*.*s]\n", - "ippr_ftp_server_valid", + "ipf_p_ftp_server_valid", ftps->ftps_junk, (int)len, (int)i, c, (int)len, (int)len, buf); - return 1; + if (ftps->ftps_junk == FTPXY_JUNK_CONT) + return FTPXY_JUNK_CONT; + return FTPXY_JUNK_BAD; } search_eol: for (; i; i--) { pc = c; c = *s++; if ((pc == '\r') && (c == '\n')) { - ftps->ftps_cmds = cmd; - return 0; + if (cmd == -1) { + if (ftps->ftps_junk == FTPXY_JUNK_CONT) + return FTPXY_JUNK_CONT; + } else { + ftps->ftps_cmd = cmd; + } + return FTPXY_JUNK_OK; } } - if (ippr_ftp_debug > 3) - printf("ippr_ftp_server_valid:junk after cmd[%*.*s]\n", + + DT2(junk_eol, int, len, char *, buf); + if (softf->ipf_p_ftp_debug & DEBUG_PARSE_INFO) + printf("ipf_p_ftp_server_valid:junk after cmd[%*.*s]\n", (int)len, (int)len, buf); - return 2; + return FTPXY_JUNK_EOL; } -int ippr_ftp_valid(ftp, side, buf, len) -ftpinfo_t *ftp; -int side; -char *buf; -size_t len; +int +ipf_p_ftp_valid(softf, ftp, side, buf, len) + ipf_ftp_softc_t *softf; + ftpinfo_t *ftp; + int side; + char *buf; + size_t len; { ftpside_t *ftps; int ret; @@ -980,9 +1264,9 @@ size_t len; ftps = &ftp->ftp_side[side]; if (side == 0) - ret = ippr_ftp_client_valid(ftps, buf, len); + ret = ipf_p_ftp_client_valid(softf, ftps, buf, len); else - ret = ippr_ftp_server_valid(ftps, buf, len); + ret = ipf_p_ftp_server_valid(softf, ftps, buf, len); return ret; } @@ -995,13 +1279,15 @@ size_t len; * rv == 0 for inbound processing, * rv == 1 for outbound processing. */ -int ippr_ftp_process(fin, nat, ftp, rv) -fr_info_t *fin; -nat_t *nat; -ftpinfo_t *ftp; -int rv; +int +ipf_p_ftp_process(softf, fin, nat, ftp, rv) + ipf_ftp_softc_t *softf; + fr_info_t *fin; + nat_t *nat; + ftpinfo_t *ftp; + int rv; { - int mlen, len, off, inc, i, sel, sel2, ok, ackoff, seqoff; + int mlen, len, off, inc, i, sel, sel2, ok, ackoff, seqoff, retry; char *rptr, *wptr, *s; u_32_t thseq, thack; ap_session_t *aps; @@ -1019,27 +1305,31 @@ int rv; t = &ftp->ftp_side[1 - rv]; thseq = ntohl(tcp->th_seq); thack = ntohl(tcp->th_ack); - #ifdef __sgi mlen = fin->fin_plen - off; #else mlen = MSGDSIZE(m) - off; #endif - if (ippr_ftp_debug > 4) - printf("ippr_ftp_process: mlen %d\n", mlen); - if (mlen <= 0) { - if ((tcp->th_flags & TH_OPENING) == TH_OPENING) { - f->ftps_seq[0] = thseq + 1; - t->ftps_seq[0] = thack; - } + DT3(process_debug, tcphdr_t *, tcp, int, off, int, mlen); + if (softf->ipf_p_ftp_debug & DEBUG_INFO) + printf("ipf_p_ftp_process: %d:%d,%d, mlen %d flags %x\n", + fin->fin_out, fin->fin_sport, fin->fin_dport, + mlen, tcp->th_flags); + + if ((mlen == 0) && ((tcp->th_flags & TH_OPENING) == TH_OPENING)) { + f->ftps_seq[0] = thseq + 1; + t->ftps_seq[0] = thack; + return 0; + } else if (mlen < 0) { return 0; } + aps = nat->nat_aps; sel = aps->aps_sel[1 - rv]; sel2 = aps->aps_sel[rv]; - if (rv == 0) { + if (rv == 1) { seqoff = aps->aps_seqoff[sel]; if (aps->aps_seqmin[sel] > seqoff + thseq) seqoff = aps->aps_seqoff[!sel]; @@ -1048,14 +1338,14 @@ int rv; ackoff = aps->aps_ackoff[!sel2]; } else { seqoff = aps->aps_ackoff[sel]; - if (ippr_ftp_debug > 2) + if (softf->ipf_p_ftp_debug & DEBUG_INFO) printf("seqoff %d thseq %x ackmin %x\n", seqoff, thseq, aps->aps_ackmin[sel]); if (aps->aps_ackmin[sel] > seqoff + thseq) seqoff = aps->aps_ackoff[!sel]; ackoff = aps->aps_seqoff[sel2]; - if (ippr_ftp_debug > 2) + if (softf->ipf_p_ftp_debug & DEBUG_INFO) printf("ackoff %d thack %x seqmin %x\n", ackoff, thack, aps->aps_seqmin[sel2]); if (ackoff > 0) { @@ -1066,7 +1356,7 @@ int rv; ackoff = aps->aps_seqoff[!sel2]; } } - if (ippr_ftp_debug > 2) { + if (softf->ipf_p_ftp_debug & DEBUG_INFO) { printf("%s: %x seq %x/%d ack %x/%d len %d/%d off %d\n", rv ? "IN" : "OUT", tcp->th_flags, thseq, seqoff, thack, ackoff, mlen, fin->fin_plen, off); @@ -1083,7 +1373,7 @@ int rv; * that it is out of order (and there is no real danger in doing so * apart from causing packets to go through here ordered). */ - if (ippr_ftp_debug > 2) { + if (softf->ipf_p_ftp_debug & DEBUG_INFO) { printf("rv %d t:seq[0] %x seq[1] %x %d/%d\n", rv, t->ftps_seq[0], t->ftps_seq[1], seqoff, ackoff); } @@ -1101,37 +1391,44 @@ int rv; ok = 1; } } else { - if (t->ftps_seq[0] + ackoff == thack) + if (t->ftps_seq[0] + ackoff == thack) { + t->ftps_seq[0] = thack; ok = 1; - else if (t->ftps_seq[0] == thack + ackoff) + } else if (t->ftps_seq[0] == thack + ackoff) { + t->ftps_seq[0] = thack + ackoff; ok = 1; - else if (t->ftps_seq[1] + ackoff == thack) { - t->ftps_seq[0] = thack - ackoff; + } else if (t->ftps_seq[1] + ackoff == thack) { + t->ftps_seq[0] = thack; ok = 1; } else if (t->ftps_seq[1] == thack + ackoff) { - t->ftps_seq[0] = thack - ackoff; + t->ftps_seq[0] = thack + ackoff; ok = 1; } } } - if (ippr_ftp_debug > 2) { + if (softf->ipf_p_ftp_debug & DEBUG_INFO) { if (!ok) printf("%s ok\n", "not"); } if (!mlen) { - if (t->ftps_seq[0] + ackoff != thack) { - if (ippr_ftp_debug > 1) { - printf("%s:seq[0](%x) + (%x) != (%x)\n", - "ippr_ftp_process", t->ftps_seq[0], + if (t->ftps_seq[0] + ackoff != thack && + t->ftps_seq[1] + ackoff != thack) { + DT3(thack, ftpside_t *t, t, int, ackoff, u_32_t, thack); + if (softf->ipf_p_ftp_debug & DEBUG_ERROR) { + printf("%s:seq[0](%u) + (%d) != (%u)\n", + "ipf_p_ftp_process", t->ftps_seq[0], + ackoff, thack); + printf("%s:seq[0](%u) + (%d) != (%u)\n", + "ipf_p_ftp_process", t->ftps_seq[1], ackoff, thack); } return APR_ERR(1); } - if (ippr_ftp_debug > 2) { - printf("ippr_ftp_process:f:seq[0] %x seq[1] %x\n", + if (softf->ipf_p_ftp_debug & DEBUG_PARSE) { + printf("ipf_p_ftp_process:f:seq[0] %x seq[1] %x\n", f->ftps_seq[0], f->ftps_seq[1]); } @@ -1140,7 +1437,8 @@ int rv; f->ftps_seq[0] = f->ftps_seq[1] - seqoff; f->ftps_seq[1] = thseq + 1 - seqoff; } else { - if (ippr_ftp_debug > 1) { + DT2(thseq, ftpside_t *t, t, u_32_t, thseq); + if (softf->ipf_p_ftp_debug & DEBUG_ERROR) { printf("FIN: thseq %x seqoff %d ftps_seq %x\n", thseq, seqoff, f->ftps_seq[0]); } @@ -1163,8 +1461,9 @@ int rv; } if (ok == 0) { + DT3(ok_0, ftpside_t *, f, u_32_t, thseq, int, mlen); inc = thseq - f->ftps_seq[0]; - if (ippr_ftp_debug > 1) { + if (softf->ipf_p_ftp_debug & DEBUG_ERROR) { printf("inc %d sel %d rv %d\n", inc, sel, rv); printf("th_seq %x ftps_seq %x/%x\n", thseq, f->ftps_seq[0], f->ftps_seq[1]); @@ -1186,68 +1485,69 @@ int rv; while (mlen > 0) { len = MIN(mlen, sizeof(f->ftps_buf) - (wptr - rptr)); + if (len == 0) + break; COPYDATA(m, off, len, wptr); mlen -= len; off += len; wptr += len; - if (ippr_ftp_debug > 3) +whilemore: + if (softf->ipf_p_ftp_debug & DEBUG_PARSE) printf("%s:len %d/%d off %d wptr %lx junk %d [%*.*s]\n", - "ippr_ftp_process", + "ipf_p_ftp_process", len, mlen, off, (u_long)wptr, f->ftps_junk, len, len, rptr); f->ftps_wptr = wptr; - if (f->ftps_junk != 0) { + if (f->ftps_junk != FTPXY_JUNK_OK) { i = f->ftps_junk; - f->ftps_junk = ippr_ftp_valid(ftp, rv, rptr, + f->ftps_junk = ipf_p_ftp_valid(softf, ftp, rv, rptr, wptr - rptr); + DT2(junk_transit, int, i, int, f->ftps_junk); - if (ippr_ftp_debug > 5) + if (softf->ipf_p_ftp_debug & DEBUG_PARSE) printf("%s:junk %d -> %d\n", - "ippr_ftp_process", i, f->ftps_junk); + "ipf_p_ftp_process", i, f->ftps_junk); - if (f->ftps_junk != 0) { + if (f->ftps_junk == FTPXY_JUNK_BAD) { + DT(buffer_full); if (wptr - rptr == sizeof(f->ftps_buf)) { - if (ippr_ftp_debug > 4) + if (softf->ipf_p_ftp_debug & + DEBUG_PARSE_INFO) printf("%s:full buffer\n", - "ippr_ftp_process"); + "ipf_p_ftp_process"); f->ftps_rptr = f->ftps_buf; f->ftps_wptr = f->ftps_buf; rptr = f->ftps_rptr; wptr = f->ftps_wptr; - /* - * Because we throw away data here that - * we would otherwise parse, set the - * junk flag to indicate just ignore - * any data upto the next CRLF. - */ - f->ftps_junk = 1; continue; } } } - while ((f->ftps_junk == 0) && (wptr > rptr)) { + while ((f->ftps_junk == FTPXY_JUNK_OK) && (wptr > rptr)) { len = wptr - rptr; - f->ftps_junk = ippr_ftp_valid(ftp, rv, rptr, len); + f->ftps_junk = ipf_p_ftp_valid(softf, ftp, rv, + rptr, len); - if (ippr_ftp_debug > 3) { + if (softf->ipf_p_ftp_debug & DEBUG_PARSE) { printf("%s=%d len %d rv %d ptr %lx/%lx ", - "ippr_ftp_valid", + "ipf_p_ftp_valid", f->ftps_junk, len, rv, (u_long)rptr, (u_long)wptr); printf("buf [%*.*s]\n", len, len, rptr); } - if (f->ftps_junk == 0) { + if (f->ftps_junk == FTPXY_JUNK_OK) { + f->ftps_cmds++; f->ftps_rptr = rptr; if (rv) - inc += ippr_ftp_server(fin, ip, nat, - ftp, len); + inc += ipf_p_ftp_server(softf, fin, ip, + nat, ftp, len); else - inc += ippr_ftp_client(fin, ip, nat, - ftp, len); + inc += ipf_p_ftp_client(softf, fin, ip, + nat, ftp, len); rptr = f->ftps_rptr; wptr = f->ftps_wptr; } @@ -1257,21 +1557,25 @@ int rv; * Off to a bad start so lets just forget about using the * ftp proxy for this connection. */ - if ((f->ftps_cmds == 0) && (f->ftps_junk == 1)) { + if ((f->ftps_cmds == 0) && (f->ftps_junk == FTPXY_JUNK_BAD)) { /* f->ftps_seq[1] += inc; */ - if (ippr_ftp_debug > 1) + DT(ftp_junk_cmd); + if (softf->ipf_p_ftp_debug & DEBUG_ERROR) printf("%s:cmds == 0 junk == 1\n", - "ippr_ftp_process"); + "ipf_p_ftp_process"); return APR_ERR(2); } - if ((f->ftps_junk != 0) && (rptr < wptr)) { + retry = 0; + if ((f->ftps_junk != FTPXY_JUNK_OK) && (rptr < wptr)) { for (s = rptr; s < wptr; s++) { if ((*s == '\r') && (s + 1 < wptr) && (*(s + 1) == '\n')) { rptr = s + 2; - f->ftps_junk = 0; + retry = 1; + if (f->ftps_junk != FTPXY_JUNK_CONT) + f->ftps_junk = FTPXY_JUNK_OK; break; } } @@ -1287,19 +1591,21 @@ int rv; * current state. */ if (rptr > f->ftps_buf) { - bcopy(rptr, f->ftps_buf, len); + bcopy(rptr, f->ftps_buf, wptr - rptr); wptr -= rptr - f->ftps_buf; rptr = f->ftps_buf; } } f->ftps_rptr = rptr; f->ftps_wptr = wptr; + if (retry) + goto whilemore; } /* f->ftps_seq[1] += inc; */ if (tcp->th_flags & TH_FIN) f->ftps_seq[1]++; - if (ippr_ftp_debug > 3) { + if (softf->ipf_p_ftp_debug & DEBUG_PARSE_INFO) { #ifdef __sgi mlen = fin->fin_plen; #else @@ -1316,11 +1622,14 @@ int rv; } -int ippr_ftp_out(fin, aps, nat) -fr_info_t *fin; -ap_session_t *aps; -nat_t *nat; +int +ipf_p_ftp_out(arg, fin, aps, nat) + void *arg; + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; { + ipf_ftp_softc_t *softf = arg; ftpinfo_t *ftp; int rev; @@ -1332,15 +1641,18 @@ nat_t *nat; if (ftp->ftp_side[1 - rev].ftps_ifp == NULL) ftp->ftp_side[1 - rev].ftps_ifp = fin->fin_ifp; - return ippr_ftp_process(fin, nat, ftp, rev); + return ipf_p_ftp_process(softf, fin, nat, ftp, rev); } -int ippr_ftp_in(fin, aps, nat) -fr_info_t *fin; -ap_session_t *aps; -nat_t *nat; +int +ipf_p_ftp_in(arg, fin, aps, nat) + void *arg; + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; { + ipf_ftp_softc_t *softf = arg; ftpinfo_t *ftp; int rev; @@ -1352,18 +1664,19 @@ nat_t *nat; if (ftp->ftp_side[rev].ftps_ifp == NULL) ftp->ftp_side[rev].ftps_ifp = fin->fin_ifp; - return ippr_ftp_process(fin, nat, ftp, 1 - rev); + return ipf_p_ftp_process(softf, fin, nat, ftp, 1 - rev); } /* - * ippr_ftp_atoi - implement a version of atoi which processes numbers in + * ipf_p_ftp_atoi - implement a version of atoi which processes numbers in * pairs separated by commas (which are expected to be in the range 0 - 255), * returning a 16 bit number combining either side of the , as the MSB and * LSB. */ -u_short ippr_ftp_atoi(ptr) -char **ptr; +u_short +ipf_p_ftp_atoi(ptr) + char **ptr; { register char *s = *ptr, c; register u_char i = 0, j = 0; @@ -1387,26 +1700,235 @@ char **ptr; } -int ippr_ftp_epsv(fin, ip, nat, f, dlen) -fr_info_t *fin; -ip_t *ip; -nat_t *nat; -ftpside_t *f; -int dlen; +int +ipf_p_ftp_eprt(softf, fin, ip, nat, ftp, dlen) + ipf_ftp_softc_t *softf; + fr_info_t *fin; + ip_t *ip; + nat_t *nat; + ftpinfo_t *ftp; + int dlen; +{ + ftpside_t *f; + + /* + * Check for client sending out EPRT message. + */ + if (dlen < IPF_MINEPRTLEN) { + DT1(epert_dlen, int, dlen); + if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) + printf("ipf_p_ftp_eprt:dlen(%d) < IPF_MINEPRTLEN\n", + dlen); + return 0; + } + + /* + * Parse the EPRT command. Format is: + * "EPRT |1|1.2.3.4|2000|" for IPv4 and + * "EPRT |2|ef00::1:2|2000|" for IPv6 + */ + f = &ftp->ftp_side[0]; + if (f->ftps_rptr[5] != '|') + return 0; + if (f->ftps_rptr[5] == f->ftps_rptr[7]) { + if (f->ftps_rptr[6] == '1' && nat->nat_v[0] == 4) + return ipf_p_ftp_eprt4(softf, fin, ip, nat, ftp, dlen); + if (f->ftps_rptr[6] == '2' && nat->nat_v[0] == 6) + return ipf_p_ftp_eprt6(softf, fin, ip, nat, ftp, dlen); + } + return 0; +} + + +int +ipf_p_ftp_eprt4(softf, fin, ip, nat, ftp, dlen) + ipf_ftp_softc_t *softf; + fr_info_t *fin; + ip_t *ip; + nat_t *nat; + ftpinfo_t *ftp; + int dlen; +{ + int a1, a2, a3, a4, port, olen, nlen, inc, off; + char newbuf[IPF_FTPBUFSZ]; + char *s, c, delim; + u_32_t addr, i; + tcphdr_t *tcp; + ftpside_t *f; + mb_t *m; + + m = fin->fin_m; + tcp = (tcphdr_t *)fin->fin_dp; + off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff; + f = &ftp->ftp_side[0]; + delim = f->ftps_rptr[5]; + s = f->ftps_rptr + 8; + + /* + * get the IP address. + */ + i = 0; + while (((c = *s++) != '\0') && ISDIGIT(c)) { + i *= 10; + i += c - '0'; + } + if (i > 255) + return 0; + if (c != '.') + return 0; + addr = (i << 24); + + i = 0; + while (((c = *s++) != '\0') && ISDIGIT(c)) { + i *= 10; + i += c - '0'; + } + if (i > 255) + return 0; + if (c != '.') + return 0; + addr |= (addr << 16); + + i = 0; + while (((c = *s++) != '\0') && ISDIGIT(c)) { + i *= 10; + i += c - '0'; + } + if (i > 255) + return 0; + if (c != '.') + return 0; + addr |= (addr << 8); + + i = 0; + while (((c = *s++) != '\0') && ISDIGIT(c)) { + i *= 10; + i += c - '0'; + } + if (i > 255) + return 0; + if (c != delim) + return 0; + addr |= addr; + + /* + * Get the port number + */ + i = 0; + while (((c = *s++) != '\0') && ISDIGIT(c)) { + i *= 10; + i += c - '0'; + } + if (i > 65535) + return 0; + if (c != delim) + return 0; + port = i; + + /* + * Check for CR-LF at the end of the command string. + */ + if ((*s != '\r') || (*(s + 1) != '\n')) { + DT(eprt4_no_crlf); + if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) + printf("ipf_p_ftp_eprt4:missing %s\n", "cr-lf"); + return 0; + } + s += 2; + + /* + * Calculate new address parts for PORT command + */ + if (nat->nat_dir == NAT_INBOUND) + a1 = ntohl(nat->nat_odstaddr); + else + a1 = ntohl(ip->ip_src.s_addr); + a2 = (a1 >> 16) & 0xff; + a3 = (a1 >> 8) & 0xff; + a4 = a1 & 0xff; + a1 >>= 24; + olen = s - f->ftps_rptr; + /* DO NOT change this to snprintf! */ + /* + * While we could force the use of | as a delimiter here, it makes + * sense to preserve whatever character is being used by the systems + * involved in the communication. + */ +#if defined(SNPRINTF) && defined(_KERNEL) + SNPRINTF(newbuf, sizeof(newbuf), "%s %c1%c%u.%u.%u.%u%c%u%c\r\n", + "EPRT", delim, delim, a1, a2, a3, a4, delim, port, delim); +#else + (void) sprintf(newbuf, "%s %c1%c%u.%u.%u.%u%c%u%c\r\n", + "EPRT", delim, delim, a1, a2, a3, a4, delim, port, + delim); +#endif + + nlen = strlen(newbuf); + inc = nlen - olen; + if ((inc + fin->fin_plen) > 65535) { + DT2(eprt4_len, int, inc, int, fin->fin_plen); + if (softf->ipf_p_ftp_debug & DEBUG_ERROR) + printf("ipf_p_ftp_eprt4:inc(%d) + ip->ip_len > 65535\n", + inc); + return 0; + } + + off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff; +#if !defined(_KERNEL) + M_ADJ(m, inc); +#else + if (inc < 0) + M_ADJ(m, inc); +#endif + /* the mbuf chain will be extended if necessary by m_copyback() */ + COPYBACK(m, off, nlen, newbuf); + fin->fin_flx |= FI_DOCKSUM; + + if (inc != 0) { + fin->fin_plen += inc; + ip->ip_len = htons(fin->fin_plen); + fin->fin_dlen += inc; + } + + f->ftps_cmd = FTPXY_C_EPRT; + return ipf_p_ftp_addport(softf, fin, ip, nat, ftp, dlen, port, inc); +} + + +int +ipf_p_ftp_epsv(softf, fin, ip, nat, ftp, dlen) + ipf_ftp_softc_t *softf; + fr_info_t *fin; + ip_t *ip; + nat_t *nat; + ftpinfo_t *ftp; + int dlen; { char newbuf[IPF_FTPBUFSZ]; - char *s; u_short ap = 0; + ftpside_t *f; + char *s; + + if ((softf->ipf_p_ftp_forcepasv != 0) && + (ftp->ftp_side[0].ftps_cmd != FTPXY_C_EPSV)) { + DT1(epsv_cmd, int, ftp->ftp_side[0].ftps_cmd); + if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) + printf("ipf_p_ftp_epsv:ftps_cmd(%d) != FTPXY_C_EPSV\n", + ftp->ftp_side[0].ftps_cmd); + return 0; + } + f = &ftp->ftp_side[1]; #define EPSV_REPLEN 33 /* * Check for EPSV reply message. */ - if (dlen < IPF_MIN229LEN) + if (dlen < IPF_MIN229LEN) { return (0); - else if (strncmp(f->ftps_rptr, - "229 Entering Extended Passive Mode", EPSV_REPLEN)) + } else if (strncmp(f->ftps_rptr, + "229 Entering Extended Passive Mode", EPSV_REPLEN)) { return (0); +} /* * Skip the EPSV command + space @@ -1424,8 +1946,9 @@ int dlen; ap += *s++ - '0'; } - if (!s) + if (!s) { return 0; +} if (*s == '|') s++; @@ -1436,10 +1959,10 @@ int dlen; /* * check for CR-LF at the end. */ - if ((*s == '\r') && (*(s + 1) == '\n')) { - s += 2; - } else + if ((*s != '\r') || (*(s + 1) != '\n')) { return 0; + } + s += 2; #if defined(SNPRINTF) && defined(_KERNEL) SNPRINTF(newbuf, sizeof(newbuf), "%s (|||%u|)\r\n", @@ -1449,6 +1972,217 @@ int dlen; "229 Entering Extended Passive Mode", ap); #endif - return ippr_ftp_pasvreply(fin, ip, nat, f, (u_int)ap, newbuf, s, - ip->ip_src.s_addr); + return ipf_p_ftp_pasvreply(softf, fin, ip, nat, ftp, (u_int)ap, + newbuf, s); +} + + +int +ipf_p_ftp_eprt6(softf, fin, ip, nat, ftp, dlen) + ipf_ftp_softc_t *softf; + fr_info_t *fin; + ip_t *ip; + nat_t *nat; + ftpinfo_t *ftp; + int dlen; +{ + int port, olen, nlen, inc, off, left, i; + char newbuf[IPF_FTPBUFSZ]; + char *s, c; + i6addr_t addr, *a6; + tcphdr_t *tcp; + ip6_t *ip6; + char delim; + u_short whole; + u_short part; + ftpside_t *f; + u_short *t; + int fwd; + mb_t *m; + u_32_t a; + + m = fin->fin_m; + ip6 = (ip6_t *)ip; + f = &ftp->ftp_side[0]; + s = f->ftps_rptr + 8; + f = &ftp->ftp_side[0]; + delim = f->ftps_rptr[5]; + tcp = (tcphdr_t *)fin->fin_dp; + off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff; + + addr.i6[0] = 0; + addr.i6[1] = 0; + addr.i6[2] = 0; + addr.i6[3] = 0; + /* + * Parse an IPv6 address. + * Go forward until either :: or | is found. If :: is found, + * reverse direction. Direction change is performed to ease + * parsing an unknown number of 0s in the middle. + */ + whole = 0; + t = (u_short *)&addr; + fwd = 1; + for (part = 0; (c = *s) != '\0'; ) { + if (c == delim) { + *t = htons((u_short)whole); + break; + } + if (c == ':') { + *t = part; + if (fwd) { + *t = htons((u_short)whole); + t++; + } else { + *t = htons((u_short)(whole >> 16)); + t--; + } + whole = 0; + if (fwd == 1 && s[1] == ':') { + while (*s && *s != '|') + s++; + if ((c = *s) != delim) + break; + t = (u_short *)&addr.i6[3]; + t++; + fwd = 0; + } else if (fwd == 0 && s[-1] == ':') { + break; + } + } else { + if (c >= '0' && c <= '9') { + c -= '0'; + } else if (c >= 'a' && c <= 'f') { + c -= 'a' + 10; + } else if (c >= 'A' && c <= 'F') { + c -= 'A' + 10; + } + if (fwd) { + whole <<= 8; + whole |= c; + } else { + whole >>= 8; + whole |= ((u_32_t)c) << 24; + } + } + if (fwd) + s++; + else + s--; + } + if (c != ':' && c != delim) + return 0; + + while (*s != '|') + s++; + s++; + + /* + * Get the port number + */ + i = 0; + while (((c = *s++) != '\0') && ISDIGIT(c)) { + i *= 10; + i += c - '0'; + } + if (i > 65535) + return 0; + if (c != delim) + return 0; + port = (u_short)(i & 0xffff); + + /* + * Check for CR-LF at the end of the command string. + */ + if ((*s != '\r') || (*(s + 1) != '\n')) { + DT(eprt6_no_crlf); + if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) + printf("ipf_p_ftp_eprt6:missing %s\n", "cr-lf"); + return 0; + } + s += 2; + + /* + * Calculate new address parts for PORT command + */ + a6 = (i6addr_t *)&ip6->ip6_src; + olen = s - f->ftps_rptr; + /* DO NOT change this to snprintf! */ + /* + * While we could force the use of | as a delimiter here, it makes + * sense to preserve whatever character is being used by the systems + * involved in the communication. + */ + s = newbuf; + left = sizeof(newbuf); +#if defined(SNPRINTF) && defined(_KERNEL) + SNPRINTF(newbuf, left, "EPRT %c2%c", delim, delim); + left -= strlen(s) + 1; + s += strlen(s); + a = ntohl(a6->i6[0]); + SNPRINTF(s, left, "%x:%x:", a >> 16, a & 0xffff); + left -= strlen(s); + s += strlen(s); + a = ntohl(a6->i6[1]); + SNPRINTF(s, left, "%x:%x:", a >> 16, a & 0xffff); + left -= strlen(s); + s += strlen(s); + a = ntohl(a6->i6[2]); + SNPRINTF(s, left, "%x:%x:", a >> 16, a & 0xffff); + left -= strlen(s); + s += strlen(s); + a = ntohl(a6->i6[3]); + SNPRINTF(s, left, "%x:%x", a >> 16, a & 0xffff); + left -= strlen(s); + s += strlen(s); + sprintf(s, "|%d|\r\n", port); +#else + (void) sprintf(s, "EPRT %c2%c", delim, delim); + s += strlen(s); + a = ntohl(a6->i6[0]); + sprintf(s, "%x:%x:", a >> 16, a & 0xffff); + s += strlen(s); + a = ntohl(a6->i6[1]); + sprintf(s, "%x:%x:", a >> 16, a & 0xffff); + left -= strlen(s); + s += strlen(s); + a = ntohl(a6->i6[2]); + sprintf(s, "%x:%x:", a >> 16, a & 0xffff); + left -= strlen(s); + s += strlen(s); + a = ntohl(a6->i6[3]); + sprintf(s, "%x:%x", a >> 16, a & 0xffff); + left -= strlen(s); + s += strlen(s); + sprintf(s, "|%d|\r\n", port); +#endif + nlen = strlen(newbuf); + inc = nlen - olen; + if ((inc + fin->fin_plen) > 65535) { + DT2(eprt6_len, int, inc, int, fin->fin_plen); + if (softf->ipf_p_ftp_debug & DEBUG_ERROR) + printf("ipf_p_ftp_eprt6:inc(%d) + ip->ip_len > 65535\n", + inc); + return 0; + } + + off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff; +#if !defined(_KERNEL) + M_ADJ(m, inc); +#else + if (inc < 0) + M_ADJ(m, inc); +#endif + /* the mbuf chain will be extended if necessary by m_copyback() */ + COPYBACK(m, off, nlen, newbuf); + fin->fin_flx |= FI_DOCKSUM; + + if (inc != 0) { + fin->fin_plen += inc; + ip6->ip6_plen = htons(fin->fin_plen - fin->fin_hlen); + fin->fin_dlen += inc; + } + + f->ftps_cmd = FTPXY_C_EPRT; + return ipf_p_ftp_addport(softf, fin, ip, nat, ftp, dlen, port, inc); } diff --git a/ip_h323_pxy.c b/ip_h323_pxy.c deleted file mode 100644 index b6e7c7bf34e82..0000000000000 --- a/ip_h323_pxy.c +++ /dev/null @@ -1,296 +0,0 @@ -/* $NetBSD$ */ - -/* - * Copyright 2001, QNX Software Systems Ltd. All Rights Reserved - * - * This source code has been published by QNX Software Systems Ltd. (QSSL). - * However, any use, reproduction, modification, distribution or transfer of - * this software, or any software which includes or is based upon any of this - * code, is only permitted under the terms of the QNX Open Community License - * version 1.0 (see licensing.qnx.com for details) or as otherwise expressly - * authorized by a written license agreement from QSSL. For more information, - * please email licensing@qnx.com. - * - * For more details, see QNX_OCL.txt provided with this distribution. - */ - -/* - * Simple H.323 proxy - * - * by xtang@canada.com - * ported to ipfilter 3.4.20 by Michael Grant mg-ipf@grant.org - */ - -#if __FreeBSD_version >= 220000 && defined(_KERNEL) -# include <sys/fcntl.h> -# include <sys/filio.h> -#else -# ifndef linux -# include <sys/ioctl.h> -# endif -#endif - -#define IPF_H323_PROXY - -int ippr_h323_init __P((void)); -void ippr_h323_fini __P((void)); -int ippr_h323_new __P((fr_info_t *, ap_session_t *, nat_t *)); -void ippr_h323_del __P((ap_session_t *)); -int ippr_h323_out __P((fr_info_t *, ap_session_t *, nat_t *)); -int ippr_h323_in __P((fr_info_t *, ap_session_t *, nat_t *)); - -int ippr_h245_new __P((fr_info_t *, ap_session_t *, nat_t *)); -int ippr_h245_out __P((fr_info_t *, ap_session_t *, nat_t *)); -int ippr_h245_in __P((fr_info_t *, ap_session_t *, nat_t *)); - -static frentry_t h323_fr; - -int h323_proxy_init = 0; - -static int find_port __P((int, caddr_t, int datlen, int *, u_short *)); - - -static int find_port(ipaddr, data, datlen, off, port) -int ipaddr; -caddr_t data; -int datlen, *off; -unsigned short *port; -{ - u_32_t addr, netaddr; - u_char *dp; - int offset; - - if (datlen < 6) - return -1; - - *port = 0; - offset = *off; - dp = (u_char *)data; - netaddr = ntohl(ipaddr); - - for (offset = 0; offset <= datlen - 6; offset++, dp++) { - addr = (dp[0] << 24) | (dp[1] << 16) | (dp[2] << 8) | dp[3]; - if (netaddr == addr) - { - *port = (*(dp + 4) << 8) | *(dp + 5); - break; - } - } - *off = offset; - return (offset > datlen - 6) ? -1 : 0; -} - -/* - * Initialize local structures. - */ -int ippr_h323_init() -{ - bzero((char *)&h323_fr, sizeof(h323_fr)); - h323_fr.fr_ref = 1; - h323_fr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE; - MUTEX_INIT(&h323_fr.fr_lock, "H323 proxy rule lock"); - h323_proxy_init = 1; - - return 0; -} - - -void ippr_h323_fini() -{ - if (h323_proxy_init == 1) { - MUTEX_DESTROY(&h323_fr.fr_lock); - h323_proxy_init = 0; - } -} - - -int ippr_h323_new(fin, aps, nat) -fr_info_t *fin; -ap_session_t *aps; -nat_t *nat; -{ - fin = fin; /* LINT */ - nat = nat; /* LINT */ - - aps->aps_data = NULL; - aps->aps_psiz = 0; - - return 0; -} - - -void ippr_h323_del(aps) -ap_session_t *aps; -{ - int i; - ipnat_t *ipn; - - if (aps->aps_data) { - for (i = 0, ipn = aps->aps_data; - i < (aps->aps_psiz / sizeof(ipnat_t)); - i++, ipn = (ipnat_t *)((char *)ipn + sizeof(*ipn))) - { - /* - * Check the comment in ippr_h323_in() function, - * just above fr_nat_ioctl() call. - * We are lucky here because this function is not - * called with ipf_nat locked. - */ - if (fr_nat_ioctl((caddr_t)ipn, SIOCRMNAT, NAT_SYSSPACE| - NAT_LOCKHELD|FWRITE) == -1) { - /*EMPTY*/; - /* log the error */ - } - } - KFREES(aps->aps_data, aps->aps_psiz); - /* avoid double free */ - aps->aps_data = NULL; - aps->aps_psiz = 0; - } - return; -} - - -int ippr_h323_in(fin, aps, nat) -fr_info_t *fin; -ap_session_t *aps; -nat_t *nat; -{ - int ipaddr, off, datlen; - unsigned short port; - caddr_t data; - tcphdr_t *tcp; - ip_t *ip; - - ip = fin->fin_ip; - tcp = (tcphdr_t *)fin->fin_dp; - ipaddr = ip->ip_src.s_addr; - - data = (caddr_t)tcp + (TCP_OFF(tcp) << 2); - datlen = fin->fin_dlen - (TCP_OFF(tcp) << 2); - if (find_port(ipaddr, data, datlen, &off, &port) == 0) { - ipnat_t *ipn; - char *newarray; - - /* setup a nat rule to set a h245 proxy on tcp-port "port" - * it's like: - * map <if> <inter_ip>/<mask> -> <gate_ip>/<mask> proxy port <port> <port>/tcp - */ - KMALLOCS(newarray, char *, aps->aps_psiz + sizeof(*ipn)); - if (newarray == NULL) { - return -1; - } - ipn = (ipnat_t *)&newarray[aps->aps_psiz]; - bcopy((caddr_t)nat->nat_ptr, (caddr_t)ipn, sizeof(ipnat_t)); - (void) strncpy(ipn->in_plabel, "h245", APR_LABELLEN); - - ipn->in_inip = nat->nat_inip.s_addr; - ipn->in_inmsk = 0xffffffff; - ipn->in_dport = htons(port); - /* - * we got a problem here. we need to call fr_nat_ioctl() to add - * the h245 proxy rule, but since we already hold (READ locked) - * the nat table rwlock (ipf_nat), if we go into fr_nat_ioctl(), - * it will try to WRITE lock it. This will causing dead lock - * on RTP. - * - * The quick & dirty solution here is release the read lock, - * call fr_nat_ioctl() and re-lock it. - * A (maybe better) solution is do a UPGRADE(), and instead - * of calling fr_nat_ioctl(), we add the nat rule ourself. - */ - RWLOCK_EXIT(&ipf_nat); - if (fr_nat_ioctl((caddr_t)ipn, SIOCADNAT, - NAT_SYSSPACE|FWRITE) == -1) { - READ_ENTER(&ipf_nat); - return -1; - } - READ_ENTER(&ipf_nat); - if (aps->aps_data != NULL && aps->aps_psiz > 0) { - bcopy(aps->aps_data, newarray, aps->aps_psiz); - KFREES(aps->aps_data, aps->aps_psiz); - } - aps->aps_data = newarray; - aps->aps_psiz += sizeof(*ipn); - } - return 0; -} - - -int ippr_h245_new(fin, aps, nat) -fr_info_t *fin; -ap_session_t *aps; -nat_t *nat; -{ - fin = fin; /* LINT */ - nat = nat; /* LINT */ - - aps->aps_data = NULL; - aps->aps_psiz = 0; - return 0; -} - - -int ippr_h245_out(fin, aps, nat) -fr_info_t *fin; -ap_session_t *aps; -nat_t *nat; -{ - int ipaddr, off, datlen; - tcphdr_t *tcp; - caddr_t data; - u_short port; - ip_t *ip; - - aps = aps; /* LINT */ - - ip = fin->fin_ip; - tcp = (tcphdr_t *)fin->fin_dp; - ipaddr = nat->nat_inip.s_addr; - data = (caddr_t)tcp + (TCP_OFF(tcp) << 2); - datlen = ip->ip_len - fin->fin_hlen - (TCP_OFF(tcp) << 2); - if (find_port(ipaddr, data, datlen, &off, &port) == 0) { - fr_info_t fi; - nat_t *nat2; - -/* port = htons(port); */ - nat2 = nat_outlookup(fin->fin_ifp, IPN_UDP, IPPROTO_UDP, - ip->ip_src, ip->ip_dst); - if (nat2 == NULL) { - struct ip newip; - struct udphdr udp; - - bcopy((caddr_t)ip, (caddr_t)&newip, sizeof(newip)); - newip.ip_len = fin->fin_hlen + sizeof(udp); - newip.ip_p = IPPROTO_UDP; - newip.ip_src = nat->nat_inip; - - bzero((char *)&udp, sizeof(udp)); - udp.uh_sport = port; - - bcopy((caddr_t)fin, (caddr_t)&fi, sizeof(fi)); - fi.fin_fi.fi_p = IPPROTO_UDP; - fi.fin_data[0] = port; - fi.fin_data[1] = 0; - fi.fin_dp = (char *)&udp; - - nat2 = nat_new(&fi, nat->nat_ptr, NULL, - NAT_SLAVE|IPN_UDP|SI_W_DPORT, - NAT_OUTBOUND); - if (nat2 != NULL) { - (void) nat_proto(&fi, nat2, IPN_UDP); - nat_update(&fi, nat2, nat2->nat_ptr); - - nat2->nat_ptr->in_hits++; -#ifdef IPFILTER_LOG - nat_log(nat2, (u_int)(nat->nat_ptr->in_redir)); -#endif - bcopy((caddr_t)&ip->ip_src.s_addr, - data + off, 4); - bcopy((caddr_t)&nat2->nat_outport, - data + off + 4, 2); - } - } - } - return 0; -} diff --git a/ip_htable.c b/ip_htable.c index 50aa92627b29d..ca89c23d746f1 100644 --- a/ip_htable.c +++ b/ip_htable.c @@ -1,7 +1,5 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1993-2001, 2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -41,7 +39,7 @@ struct file; #if defined(_KERNEL) # include <sys/systm.h> #else -# include <stdio.h> +# include "ipf.h" #endif #include <netinet/in.h> #include <net/if.h> @@ -53,78 +51,279 @@ struct file; /* END OF INCLUDES */ #if !defined(lint) -static const char rcsid[] = "@(#)Id: ip_htable.c,v 2.34.2.2 2004/10/17 15:49:15 darrenr Exp"; +static const char rcsid[] = "@(#)$Id$"; #endif -#ifdef IPFILTER_LOOKUP -static iphtent_t *fr_iphmfind __P((iphtable_t *, struct in_addr *)); -static u_long ipht_nomem[IPL_LOGSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0 }; -static u_long ipf_nhtables[IPL_LOGSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0 }; -static u_long ipf_nhtnodes[IPL_LOGSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +# ifdef USE_INET6 +static iphtent_t *ipf_iphmfind6 __P((iphtable_t *, i6addr_t *)); +# endif +static iphtent_t *ipf_iphmfind __P((iphtable_t *, struct in_addr *)); +static int ipf_iphmfindip __P((ipf_main_softc_t *, void *, int, void *, u_int)); +static int ipf_htable_clear __P((ipf_main_softc_t *, void *, iphtable_t *)); +static int ipf_htable_create __P((ipf_main_softc_t *, void *, iplookupop_t *)); +static int ipf_htable_deref __P((ipf_main_softc_t *, void *, void *)); +static int ipf_htable_destroy __P((ipf_main_softc_t *, void *, int, char *)); +static void *ipf_htable_exists __P((void *, int, char *)); +static size_t ipf_htable_flush __P((ipf_main_softc_t *, void *, + iplookupflush_t *)); +static void ipf_htable_free __P((void *, iphtable_t *)); +static int ipf_htable_iter_deref __P((ipf_main_softc_t *, void *, int, + int, void *)); +static int ipf_htable_iter_next __P((ipf_main_softc_t *, void *, ipftoken_t *, + ipflookupiter_t *)); +static int ipf_htable_node_add __P((ipf_main_softc_t *, void *, + iplookupop_t *, int)); +static int ipf_htable_node_del __P((ipf_main_softc_t *, void *, + iplookupop_t *, int)); +static int ipf_htable_remove __P((ipf_main_softc_t *, void *, iphtable_t *)); +static void *ipf_htable_soft_create __P((ipf_main_softc_t *)); +static void ipf_htable_soft_destroy __P((ipf_main_softc_t *, void *)); +static int ipf_htable_soft_init __P((ipf_main_softc_t *, void *)); +static void ipf_htable_soft_fini __P((ipf_main_softc_t *, void *)); +static int ipf_htable_stats_get __P((ipf_main_softc_t *, void *, + iplookupop_t *)); +static int ipf_htable_table_add __P((ipf_main_softc_t *, void *, + iplookupop_t *)); +static int ipf_htable_table_del __P((ipf_main_softc_t *, void *, + iplookupop_t *)); +static int ipf_htent_deref __P((void *, iphtent_t *)); +static iphtent_t *ipf_htent_find __P((iphtable_t *, iphtent_t *)); +static int ipf_htent_insert __P((ipf_main_softc_t *, void *, iphtable_t *, + iphtent_t *)); +static int ipf_htent_remove __P((ipf_main_softc_t *, void *, iphtable_t *, + iphtent_t *)); +static void *ipf_htable_select_add_ref __P((void *, int, char *)); +static void ipf_htable_expire __P((ipf_main_softc_t *, void *)); + + +typedef struct ipf_htable_softc_s { + u_long ipht_nomem[LOOKUP_POOL_SZ]; + u_long ipf_nhtables[LOOKUP_POOL_SZ]; + u_long ipf_nhtnodes[LOOKUP_POOL_SZ]; + iphtable_t *ipf_htables[LOOKUP_POOL_SZ]; + iphtent_t *ipf_node_explist; +} ipf_htable_softc_t; + +ipf_lookup_t ipf_htable_backend = { + IPLT_HASH, + ipf_htable_soft_create, + ipf_htable_soft_destroy, + ipf_htable_soft_init, + ipf_htable_soft_fini, + ipf_iphmfindip, + ipf_htable_flush, + ipf_htable_iter_deref, + ipf_htable_iter_next, + ipf_htable_node_add, + ipf_htable_node_del, + ipf_htable_stats_get, + ipf_htable_table_add, + ipf_htable_table_del, + ipf_htable_deref, + ipf_htable_exists, + ipf_htable_select_add_ref, + NULL, + ipf_htable_expire, + NULL +}; + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htable_soft_create */ +/* Returns: void * - NULL = failure, else pointer to local context */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* */ +/* Initialise the routing table data structures where required. */ +/* ------------------------------------------------------------------------ */ +static void * +ipf_htable_soft_create(softc) + ipf_main_softc_t *softc; +{ + ipf_htable_softc_t *softh; + + KMALLOC(softh, ipf_htable_softc_t *); + if (softh == NULL) { + IPFERROR(30026); + return NULL; + } + + bzero((char *)softh, sizeof(*softh)); + + return softh; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htable_soft_destroy */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* */ +/* Clean up the pool by free'ing the radix tree associated with it and free */ +/* up the pool context too. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_htable_soft_destroy(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_htable_softc_t *softh = arg; + + KFREE(softh); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htable_soft_init */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* */ +/* Initialise the hash table ready for use. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_htable_soft_init(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_htable_softc_t *softh = arg; + + bzero((char *)softh, sizeof(*softh)); -iphtable_t *ipf_htables[IPL_LOGSIZE] = { NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL }; + return 0; +} -void fr_htable_unload() +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htable_soft_fini */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* Locks: WRITE(ipf_global) */ +/* */ +/* Clean up all the pool data structures allocated and call the cleanup */ +/* function for the radix tree that supports the pools. ipf_pool_destroy is */ +/* used to delete the pools one by one to ensure they're properly freed up. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_htable_soft_fini(softc, arg) + ipf_main_softc_t *softc; + void *arg; { iplookupflush_t fop; + fop.iplf_type = IPLT_HASH; fop.iplf_unit = IPL_LOGALL; - (void)fr_flushhtable(&fop); + fop.iplf_arg = 0; + fop.iplf_count = 0; + *fop.iplf_name = '\0'; + ipf_htable_flush(softc, arg, &fop); } -int fr_gethtablestat(op) -iplookupop_t *op; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htable_stats_get */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* op(I) - pointer to lookup operation data */ +/* */ +/* Copy the relevant statistics out of internal structures and into the */ +/* structure used to export statistics. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_htable_stats_get(softc, arg, op) + ipf_main_softc_t *softc; + void *arg; + iplookupop_t *op; { + ipf_htable_softc_t *softh = arg; iphtstat_t stats; + int err; - if (op->iplo_size != sizeof(stats)) + if (op->iplo_size != sizeof(stats)) { + IPFERROR(30001); return EINVAL; + } - stats.iphs_tables = ipf_htables[op->iplo_unit]; - stats.iphs_numtables = ipf_nhtables[op->iplo_unit]; - stats.iphs_numnodes = ipf_nhtnodes[op->iplo_unit]; - stats.iphs_nomem = ipht_nomem[op->iplo_unit]; + stats.iphs_tables = softh->ipf_htables[op->iplo_unit + 1]; + stats.iphs_numtables = softh->ipf_nhtables[op->iplo_unit + 1]; + stats.iphs_numnodes = softh->ipf_nhtnodes[op->iplo_unit + 1]; + stats.iphs_nomem = softh->ipht_nomem[op->iplo_unit + 1]; - return COPYOUT(&stats, op->iplo_struct, sizeof(stats)); + err = COPYOUT(&stats, op->iplo_struct, sizeof(stats)); + if (err != 0) { + IPFERROR(30013); + return EFAULT; + } + return 0; } -/* - * Create a new hash table using the template passed. - */ -int fr_newhtable(op) -iplookupop_t *op; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htable_create */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* op(I) - pointer to lookup operation data */ +/* */ +/* Create a new hash table using the template passed. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_htable_create(softc, arg, op) + ipf_main_softc_t *softc; + void *arg; + iplookupop_t *op; { - iphtable_t *iph, *oiph; + ipf_htable_softc_t *softh = arg; + iphtable_t htab, *iph, *oiph; char name[FR_GROUPLEN]; int err, i, unit; - KMALLOC(iph, iphtable_t *); - if (iph == NULL) - return ENOMEM; - - err = COPYIN(op->iplo_struct, iph, sizeof(*iph)); + if (op->iplo_size != sizeof(htab)) { + IPFERROR(30024); + return EINVAL; + } + err = COPYIN(op->iplo_struct, &htab, sizeof(htab)); if (err != 0) { - KFREE(iph); + IPFERROR(30003); return EFAULT; } unit = op->iplo_unit; - if (iph->iph_unit != unit) { - KFREE(iph); + if (htab.iph_unit != unit) { + IPFERROR(30005); + return EINVAL; + } + if (htab.iph_size < 1) { + IPFERROR(30025); return EINVAL; } + if ((op->iplo_arg & IPHASH_ANON) == 0) { - if (fr_findhtable(op->iplo_unit, op->iplo_name) != NULL) { - KFREE(iph); - return EEXIST; + iph = ipf_htable_exists(softh, unit, op->iplo_name); + if (iph != NULL) { + if ((iph->iph_flags & IPHASH_DELETE) == 0) { + IPFERROR(30004); + return EEXIST; + } + iph->iph_flags &= ~IPHASH_DELETE; + iph->iph_ref++; + return 0; } - } else { + } + + KMALLOC(iph, iphtable_t *); + if (iph == NULL) { + softh->ipht_nomem[op->iplo_unit + 1]++; + IPFERROR(30002); + return ENOMEM; + } + *iph = htab; + + if ((op->iplo_arg & IPHASH_ANON) != 0) { i = IPHASH_ANON; do { i++; @@ -133,130 +332,508 @@ iplookupop_t *op; #else (void)sprintf(name, "%u", i); #endif - for (oiph = ipf_htables[unit]; oiph != NULL; + for (oiph = softh->ipf_htables[unit + 1]; oiph != NULL; oiph = oiph->iph_next) if (strncmp(oiph->iph_name, name, sizeof(oiph->iph_name)) == 0) break; } while (oiph != NULL); + (void)strncpy(iph->iph_name, name, sizeof(iph->iph_name)); - err = COPYOUT(iph, op->iplo_struct, sizeof(*iph)); - if (err != 0) { - KFREE(iph); - return EFAULT; - } + (void)strncpy(op->iplo_name, name, sizeof(op->iplo_name)); iph->iph_type |= IPHASH_ANON; + } else { + (void)strncpy(iph->iph_name, op->iplo_name, + sizeof(iph->iph_name)); + iph->iph_name[sizeof(iph->iph_name) - 1] = '\0'; } KMALLOCS(iph->iph_table, iphtent_t **, iph->iph_size * sizeof(*iph->iph_table)); if (iph->iph_table == NULL) { KFREE(iph); - ipht_nomem[unit]++; + softh->ipht_nomem[unit + 1]++; + IPFERROR(30006); return ENOMEM; } bzero((char *)iph->iph_table, iph->iph_size * sizeof(*iph->iph_table)); - iph->iph_masks = 0; + iph->iph_maskset[0] = 0; + iph->iph_maskset[1] = 0; + iph->iph_maskset[2] = 0; + iph->iph_maskset[3] = 0; + + iph->iph_ref = 1; + iph->iph_list = NULL; + iph->iph_tail = &iph->iph_list; + iph->iph_next = softh->ipf_htables[unit + 1]; + iph->iph_pnext = &softh->ipf_htables[unit + 1]; + if (softh->ipf_htables[unit + 1] != NULL) + softh->ipf_htables[unit + 1]->iph_pnext = &iph->iph_next; + softh->ipf_htables[unit + 1] = iph; + + softh->ipf_nhtables[unit + 1]++; - iph->iph_next = ipf_htables[unit]; - iph->iph_pnext = &ipf_htables[unit]; - if (ipf_htables[unit] != NULL) - ipf_htables[unit]->iph_pnext = &iph->iph_next; - ipf_htables[unit] = iph; + return 0; +} - ipf_nhtables[unit]++; - return 0; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htable_table_del */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* op(I) - pointer to lookup operation data */ +/* */ +/* ------------------------------------------------------------------------ */ +static int +ipf_htable_table_del(softc, arg, op) + ipf_main_softc_t *softc; + void *arg; + iplookupop_t *op; +{ + return ipf_htable_destroy(softc, arg, op->iplo_unit, op->iplo_name); } -/* - */ -int fr_removehtable(op) -iplookupop_t *op; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htable_destroy */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* op(I) - pointer to lookup operation data */ +/* */ +/* Find the hash table that belongs to the relevant part of ipfilter with a */ +/* matching name and attempt to destroy it. If it is in use, empty it out */ +/* and mark it for deletion so that when all the references disappear, it */ +/* can be removed. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_htable_destroy(softc, arg, unit, name) + ipf_main_softc_t *softc; + void *arg; + int unit; + char *name; { iphtable_t *iph; - - iph = fr_findhtable(op->iplo_unit, op->iplo_name); - if (iph == NULL) + iph = ipf_htable_find(arg, unit, name); + if (iph == NULL) { + IPFERROR(30007); return ESRCH; + } - if (iph->iph_unit != op->iplo_unit) { + if (iph->iph_unit != unit) { + IPFERROR(30008); return EINVAL; } if (iph->iph_ref != 0) { - return EBUSY; + ipf_htable_clear(softc, arg, iph); + iph->iph_flags |= IPHASH_DELETE; + return 0; } - fr_delhtable(iph); + ipf_htable_remove(softc, arg, iph); return 0; } -void fr_delhtable(iph) -iphtable_t *iph; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htable_clear */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* iph(I) - pointer to hash table to destroy */ +/* */ +/* Clean out the hash table by walking the list of entries and removing */ +/* each one, one by one. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_htable_clear(softc, arg, iph) + ipf_main_softc_t *softc; + void *arg; + iphtable_t *iph; { iphtent_t *ipe; - int i; - for (i = 0; i < iph->iph_size; i++) - while ((ipe = iph->iph_table[i]) != NULL) - if (fr_delhtent(iph, ipe) != 0) - return; + while ((ipe = iph->iph_list) != NULL) + if (ipf_htent_remove(softc, arg, iph, ipe) != 0) + return 1; + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htable_free */ +/* Returns: Nil */ +/* Parameters: arg(I) - pointer to local context to use */ +/* iph(I) - pointer to hash table to destroy */ +/* */ +/* ------------------------------------------------------------------------ */ +static void +ipf_htable_free(arg, iph) + void *arg; + iphtable_t *iph; +{ + ipf_htable_softc_t *softh = arg; - *iph->iph_pnext = iph->iph_next; if (iph->iph_next != NULL) iph->iph_next->iph_pnext = iph->iph_pnext; + if (iph->iph_pnext != NULL) + *iph->iph_pnext = iph->iph_next; + iph->iph_pnext = NULL; + iph->iph_next = NULL; - ipf_nhtables[iph->iph_unit]--; + softh->ipf_nhtables[iph->iph_unit + 1]--; - if (iph->iph_ref == 0) { - KFREES(iph->iph_table, iph->iph_size * sizeof(*iph->iph_table)); - KFREE(iph); + KFREES(iph->iph_table, iph->iph_size * sizeof(*iph->iph_table)); + KFREE(iph); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htable_remove */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* iph(I) - pointer to hash table to destroy */ +/* */ +/* It is necessary to unlink here as well as free (called by deref) so that */ +/* the while loop in ipf_htable_flush() functions properly. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_htable_remove(softc, arg, iph) + ipf_main_softc_t *softc; + void *arg; + iphtable_t *iph; +{ + + if (ipf_htable_clear(softc, arg, iph) != 0) + return 1; + + if (iph->iph_pnext != NULL) + *iph->iph_pnext = iph->iph_next; + if (iph->iph_next != NULL) + iph->iph_next->iph_pnext = iph->iph_pnext; + iph->iph_pnext = NULL; + iph->iph_next = NULL; + + return ipf_htable_deref(softc, arg, iph); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htable_node_del */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* op(I) - pointer to lookup operation data */ +/* uid(I) - real uid of process doing operation */ +/* */ +/* ------------------------------------------------------------------------ */ +static int +ipf_htable_node_del(softc, arg, op, uid) + ipf_main_softc_t *softc; + void *arg; + iplookupop_t *op; + int uid; +{ + iphtable_t *iph; + iphtent_t hte, *ent; + int err; + + if (op->iplo_size != sizeof(hte)) { + IPFERROR(30014); + return EINVAL; + } + + err = COPYIN(op->iplo_struct, &hte, sizeof(hte)); + if (err != 0) { + IPFERROR(30015); + return EFAULT; + } + + iph = ipf_htable_find(arg, op->iplo_unit, op->iplo_name); + if (iph == NULL) { + IPFERROR(30016); + return ESRCH; + } + + ent = ipf_htent_find(iph, &hte); + if (ent == NULL) { + IPFERROR(30022); + return ESRCH; + } + + if ((uid != 0) && (ent->ipe_uid != uid)) { + IPFERROR(30023); + return EACCES; + } + + err = ipf_htent_remove(softc, arg, iph, ent); + + return err; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htable_node_del */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* op(I) - pointer to lookup operation data */ +/* */ +/* ------------------------------------------------------------------------ */ +static int +ipf_htable_table_add(softc, arg, op) + ipf_main_softc_t *softc; + void *arg; + iplookupop_t *op; +{ + int err; + + if (ipf_htable_find(arg, op->iplo_unit, op->iplo_name) != NULL) { + IPFERROR(30017); + err = EEXIST; + } else { + err = ipf_htable_create(softc, arg, op); } + + return err; } -void fr_derefhtable(iph) -iphtable_t *iph; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htent_remove */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* iph(I) - pointer to hash table */ +/* ipe(I) - pointer to hash table entry to remove */ +/* */ +/* Delete an entry from a hash table. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_htent_remove(softc, arg, iph, ipe) + ipf_main_softc_t *softc; + void *arg; + iphtable_t *iph; + iphtent_t *ipe; { + + if (iph->iph_tail == &ipe->ipe_next) + iph->iph_tail = ipe->ipe_pnext; + + if (ipe->ipe_hnext != NULL) + ipe->ipe_hnext->ipe_phnext = ipe->ipe_phnext; + if (ipe->ipe_phnext != NULL) + *ipe->ipe_phnext = ipe->ipe_hnext; + ipe->ipe_phnext = NULL; + ipe->ipe_hnext = NULL; + + if (ipe->ipe_dnext != NULL) + ipe->ipe_dnext->ipe_pdnext = ipe->ipe_pdnext; + if (ipe->ipe_pdnext != NULL) + *ipe->ipe_pdnext = ipe->ipe_dnext; + ipe->ipe_pdnext = NULL; + ipe->ipe_dnext = NULL; + + if (ipe->ipe_next != NULL) + ipe->ipe_next->ipe_pnext = ipe->ipe_pnext; + if (ipe->ipe_pnext != NULL) + *ipe->ipe_pnext = ipe->ipe_next; + ipe->ipe_pnext = NULL; + ipe->ipe_next = NULL; + + switch (iph->iph_type & ~IPHASH_ANON) + { + case IPHASH_GROUPMAP : + if (ipe->ipe_group != NULL) + ipf_group_del(softc, ipe->ipe_ptr, NULL); + break; + + default : + ipe->ipe_ptr = NULL; + ipe->ipe_value = 0; + break; + } + + return ipf_htent_deref(arg, ipe); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htable_deref */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* object(I) - pointer to hash table */ +/* */ +/* ------------------------------------------------------------------------ */ +static int +ipf_htable_deref(softc, arg, object) + ipf_main_softc_t *softc; + void *arg, *object; +{ + ipf_htable_softc_t *softh = arg; + iphtable_t *iph = object; + int refs; + iph->iph_ref--; - if (iph->iph_ref == 0) - fr_delhtable(iph); + refs = iph->iph_ref; + + if (iph->iph_ref == 0) { + ipf_htable_free(softh, iph); + } + + return refs; } -iphtable_t *fr_findhtable(unit, name) -int unit; -char *name; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htent_deref */ +/* Parameters: arg(I) - pointer to local context to use */ +/* ipe(I) - */ +/* */ +/* ------------------------------------------------------------------------ */ +static int +ipf_htent_deref(arg, ipe) + void *arg; + iphtent_t *ipe; { + ipf_htable_softc_t *softh = arg; + + ipe->ipe_ref--; + if (ipe->ipe_ref == 0) { + softh->ipf_nhtnodes[ipe->ipe_unit + 1]--; + KFREE(ipe); + + return 0; + } + + return ipe->ipe_ref; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htable_exists */ +/* Parameters: arg(I) - pointer to local context to use */ +/* */ +/* ------------------------------------------------------------------------ */ +static void * +ipf_htable_exists(arg, unit, name) + void *arg; + int unit; + char *name; +{ + ipf_htable_softc_t *softh = arg; iphtable_t *iph; - for (iph = ipf_htables[unit]; iph != NULL; iph = iph->iph_next) - if (strncmp(iph->iph_name, name, sizeof(iph->iph_name)) == 0) - break; + if (unit == IPL_LOGALL) { + int i; + + for (i = 0; i <= LOOKUP_POOL_MAX; i++) { + for (iph = softh->ipf_htables[i]; iph != NULL; + iph = iph->iph_next) { + if (strncmp(iph->iph_name, name, + sizeof(iph->iph_name)) == 0) + break; + } + if (iph != NULL) + break; + } + } else { + for (iph = softh->ipf_htables[unit + 1]; iph != NULL; + iph = iph->iph_next) { + if (strncmp(iph->iph_name, name, + sizeof(iph->iph_name)) == 0) + break; + } + } + return iph; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htable_select_add_ref */ +/* Returns: void * - NULL = failure, else pointer to the hash table */ +/* Parameters: arg(I) - pointer to local context to use */ +/* unit(I) - ipfilter device to which we are working on */ +/* name(I) - name of the hash table */ +/* */ +/* ------------------------------------------------------------------------ */ +static void * +ipf_htable_select_add_ref(arg, unit, name) + void *arg; + int unit; + char *name; +{ + iphtable_t *iph; + + iph = ipf_htable_exists(arg, unit, name); + if (iph != NULL) { + ATOMIC_INC32(iph->iph_ref); + } return iph; } -size_t fr_flushhtable(op) -iplookupflush_t *op; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htable_find */ +/* Returns: void * - NULL = failure, else pointer to the hash table */ +/* Parameters: arg(I) - pointer to local context to use */ +/* unit(I) - ipfilter device to which we are working on */ +/* name(I) - name of the hash table */ +/* */ +/* This function is exposed becaues it is used in the group-map feature. */ +/* ------------------------------------------------------------------------ */ +iphtable_t * +ipf_htable_find(arg, unit, name) + void *arg; + int unit; + char *name; { iphtable_t *iph; + + iph = ipf_htable_exists(arg, unit, name); + if ((iph != NULL) && (iph->iph_flags & IPHASH_DELETE) == 0) + return iph; + + return NULL; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htable_flush */ +/* Returns: size_t - number of entries flushed */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* op(I) - pointer to lookup operation data */ +/* */ +/* ------------------------------------------------------------------------ */ +static size_t +ipf_htable_flush(softc, arg, op) + ipf_main_softc_t *softc; + void *arg; + iplookupflush_t *op; +{ + ipf_htable_softc_t *softh = arg; + iphtable_t *iph; size_t freed; int i; freed = 0; - for (i = 0; i <= IPL_LOGMAX; i++) { + for (i = -1; i <= IPL_LOGMAX; i++) { if (op->iplf_unit == i || op->iplf_unit == IPL_LOGALL) { - while ((iph = ipf_htables[i]) != NULL) { - fr_delhtable(iph); - freed++; + while ((iph = softh->ipf_htables[i + 1]) != NULL) { + if (ipf_htable_remove(softc, arg, iph) == 0) { + freed++; + } else { + iph->iph_flags |= IPHASH_DELETE; + } } } } @@ -265,13 +842,73 @@ iplookupflush_t *op; } -/* - * Add an entry to a hash table. - */ -int fr_addhtent(iph, ipeo) -iphtable_t *iph; -iphtent_t *ipeo; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htable_node_add */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* op(I) - pointer to lookup operation data */ +/* uid(I) - real uid of process doing operation */ +/* */ +/* ------------------------------------------------------------------------ */ +static int +ipf_htable_node_add(softc, arg, op, uid) + ipf_main_softc_t *softc; + void *arg; + iplookupop_t *op; + int uid; +{ + iphtable_t *iph; + iphtent_t hte; + int err; + + if (op->iplo_size != sizeof(hte)) { + IPFERROR(30018); + return EINVAL; + } + + err = COPYIN(op->iplo_struct, &hte, sizeof(hte)); + if (err != 0) { + IPFERROR(30019); + return EFAULT; + } + hte.ipe_uid = uid; + + iph = ipf_htable_find(arg, op->iplo_unit, op->iplo_name); + if (iph == NULL) { + IPFERROR(30020); + return ESRCH; + } + + if (ipf_htent_find(iph, &hte) != NULL) { + IPFERROR(30021); + return EEXIST; + } + + err = ipf_htent_insert(softc, arg, iph, &hte); + + return err; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htent_insert */ +/* Returns: int - 0 = success, -1 = error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* op(I) - pointer to lookup operation data */ +/* ipeo(I) - */ +/* */ +/* Add an entry to a hash table. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_htent_insert(softc, arg, iph, ipeo) + ipf_main_softc_t *softc; + void *arg; + iphtable_t *iph; + iphtent_t *ipeo; { + ipf_htable_softc_t *softh = arg; iphtent_t *ipe; u_int hv; int bits; @@ -281,29 +918,100 @@ iphtent_t *ipeo; return -1; bcopy((char *)ipeo, (char *)ipe, sizeof(*ipe)); - ipe->ipe_addr.in4_addr &= ipe->ipe_mask.in4_addr; - ipe->ipe_addr.in4_addr = ntohl(ipe->ipe_addr.in4_addr); - bits = count4bits(ipe->ipe_mask.in4_addr); - ipe->ipe_mask.in4_addr = ntohl(ipe->ipe_mask.in4_addr); + ipe->ipe_addr.i6[0] &= ipe->ipe_mask.i6[0]; + if (ipe->ipe_family == AF_INET) { + bits = count4bits(ipe->ipe_mask.in4_addr); + ipe->ipe_addr.i6[1] = 0; + ipe->ipe_addr.i6[2] = 0; + ipe->ipe_addr.i6[3] = 0; + ipe->ipe_mask.i6[1] = 0; + ipe->ipe_mask.i6[2] = 0; + ipe->ipe_mask.i6[3] = 0; + hv = IPE_V4_HASH_FN(ipe->ipe_addr.in4_addr, + ipe->ipe_mask.in4_addr, iph->iph_size); + } else +#ifdef USE_INET6 + if (ipe->ipe_family == AF_INET6) { + ipe->ipe_addr.i6[1] &= ipe->ipe_mask.i6[1]; + ipe->ipe_addr.i6[2] &= ipe->ipe_mask.i6[2]; + ipe->ipe_addr.i6[3] &= ipe->ipe_mask.i6[3]; + + bits = count6bits(ipe->ipe_mask.i6); + hv = IPE_V6_HASH_FN(ipe->ipe_addr.i6, + ipe->ipe_mask.i6, iph->iph_size); + } else +#endif + { + KFREE(ipe); + return -1; + } - hv = IPE_HASH_FN(ipe->ipe_addr.in4_addr, ipe->ipe_mask.in4_addr, - iph->iph_size); - ipe->ipe_ref = 0; - ipe->ipe_next = iph->iph_table[hv]; - ipe->ipe_pnext = iph->iph_table + hv; + ipe->ipe_owner = iph; + ipe->ipe_ref = 1; + ipe->ipe_hnext = iph->iph_table[hv]; + ipe->ipe_phnext = iph->iph_table + hv; if (iph->iph_table[hv] != NULL) - iph->iph_table[hv]->ipe_pnext = &ipe->ipe_next; + iph->iph_table[hv]->ipe_phnext = &ipe->ipe_hnext; iph->iph_table[hv] = ipe; - if ((bits >= 0) && (bits != 32)) - iph->iph_masks |= 1 << bits; + + ipe->ipe_pnext = iph->iph_tail; + *iph->iph_tail = ipe; + iph->iph_tail = &ipe->ipe_next; + ipe->ipe_next = NULL; + + if (ipe->ipe_die != 0) { + /* + * If the new node has a given expiration time, insert it + * into the list of expiring nodes with the ones to be + * removed first added to the front of the list. The + * insertion is O(n) but it is kept sorted for quick scans + * at expiration interval checks. + */ + iphtent_t *n; + + ipe->ipe_die = softc->ipf_ticks + IPF_TTLVAL(ipe->ipe_die); + for (n = softh->ipf_node_explist; n != NULL; n = n->ipe_dnext) { + if (ipe->ipe_die < n->ipe_die) + break; + if (n->ipe_dnext == NULL) { + /* + * We've got to the last node and everything + * wanted to be expired before this new node, + * so we have to tack it on the end... + */ + n->ipe_dnext = ipe; + ipe->ipe_pdnext = &n->ipe_dnext; + n = NULL; + break; + } + } + + if (softh->ipf_node_explist == NULL) { + softh->ipf_node_explist = ipe; + ipe->ipe_pdnext = &softh->ipf_node_explist; + } else if (n != NULL) { + ipe->ipe_dnext = n; + ipe->ipe_pdnext = n->ipe_pdnext; + n->ipe_pdnext = &ipe->ipe_dnext; + } + } + + if (ipe->ipe_family == AF_INET) { + ipf_inet_mask_add(bits, &iph->iph_v4_masks); + } +#ifdef USE_INET6 + else if (ipe->ipe_family == AF_INET6) { + ipf_inet6_mask_add(bits, &ipe->ipe_mask, &iph->iph_v6_masks); + } +#endif switch (iph->iph_type & ~IPHASH_ANON) { case IPHASH_GROUPMAP : - ipe->ipe_ptr = fr_addgroup(ipe->ipe_group, NULL, + ipe->ipe_ptr = ipf_group_add(softc, ipe->ipe_group, NULL, iph->iph_flags, IPL_LOGIPF, - fr_active); + softc->ipf_active); break; default : @@ -312,144 +1020,446 @@ iphtent_t *ipeo; break; } - ipf_nhtnodes[iph->iph_unit]++; + ipe->ipe_unit = iph->iph_unit; + softh->ipf_nhtnodes[ipe->ipe_unit + 1]++; return 0; } -/* - * Delete an entry from a hash table. - */ -int fr_delhtent(iph, ipe) -iphtable_t *iph; -iphtent_t *ipe; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htent_find */ +/* Returns: int - 0 = success, else error */ +/* Parameters: iph(I) - pointer to table to search */ +/* ipeo(I) - pointer to entry to find */ +/* */ +/* While it isn't absolutely necessary to for the address and mask to be */ +/* passed in through an iphtent_t structure, one is always present when it */ +/* is time to call this function, so it is just more convenient. */ +/* ------------------------------------------------------------------------ */ +static iphtent_t * +ipf_htent_find(iph, ipeo) + iphtable_t *iph; + iphtent_t *ipeo; { + iphtent_t ipe, *ent; + u_int hv; + int bits; - if (ipe->ipe_ref != 0) - return EBUSY; - - - *ipe->ipe_pnext = ipe->ipe_next; - if (ipe->ipe_next != NULL) - ipe->ipe_next->ipe_pnext = ipe->ipe_pnext; - - switch (iph->iph_type & ~IPHASH_ANON) - { - case IPHASH_GROUPMAP : - if (ipe->ipe_group != NULL) - fr_delgroup(ipe->ipe_group, IPL_LOGIPF, fr_active); - break; + bcopy((char *)ipeo, (char *)&ipe, sizeof(ipe)); + ipe.ipe_addr.i6[0] &= ipe.ipe_mask.i6[0]; + ipe.ipe_addr.i6[1] &= ipe.ipe_mask.i6[1]; + ipe.ipe_addr.i6[2] &= ipe.ipe_mask.i6[2]; + ipe.ipe_addr.i6[3] &= ipe.ipe_mask.i6[3]; + if (ipe.ipe_family == AF_INET) { + bits = count4bits(ipe.ipe_mask.in4_addr); + ipe.ipe_addr.i6[1] = 0; + ipe.ipe_addr.i6[2] = 0; + ipe.ipe_addr.i6[3] = 0; + ipe.ipe_mask.i6[1] = 0; + ipe.ipe_mask.i6[2] = 0; + ipe.ipe_mask.i6[3] = 0; + hv = IPE_V4_HASH_FN(ipe.ipe_addr.in4_addr, + ipe.ipe_mask.in4_addr, iph->iph_size); + } else +#ifdef USE_INET6 + if (ipe.ipe_family == AF_INET6) { + bits = count6bits(ipe.ipe_mask.i6); + hv = IPE_V6_HASH_FN(ipe.ipe_addr.i6, + ipe.ipe_mask.i6, iph->iph_size); + } else +#endif + return NULL; - default : - ipe->ipe_ptr = NULL; - ipe->ipe_value = 0; + for (ent = iph->iph_table[hv]; ent != NULL; ent = ent->ipe_hnext) { + if (ent->ipe_family != ipe.ipe_family) + continue; + if (IP6_NEQ(&ipe.ipe_addr, &ent->ipe_addr)) + continue; + if (IP6_NEQ(&ipe.ipe_mask, &ent->ipe_mask)) + continue; break; } - KFREE(ipe); - - ipf_nhtnodes[iph->iph_unit]--; - - return 0; + return ent; } -void *fr_iphmfindgroup(tptr, aptr) -void *tptr, *aptr; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_iphmfindgroup */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* tptr(I) - */ +/* aptr(I) - */ +/* */ +/* Search a hash table for a matching entry and return the pointer stored */ +/* in it for use as the next group of rules to search. */ +/* */ +/* This function is exposed becaues it is used in the group-map feature. */ +/* ------------------------------------------------------------------------ */ +void * +ipf_iphmfindgroup(softc, tptr, aptr) + ipf_main_softc_t *softc; + void *tptr, *aptr; { struct in_addr *addr; iphtable_t *iph; iphtent_t *ipe; void *rval; - READ_ENTER(&ip_poolrw); + READ_ENTER(&softc->ipf_poolrw); iph = tptr; addr = aptr; - ipe = fr_iphmfind(iph, addr); + ipe = ipf_iphmfind(iph, addr); if (ipe != NULL) rval = ipe->ipe_ptr; else rval = NULL; - RWLOCK_EXIT(&ip_poolrw); + RWLOCK_EXIT(&softc->ipf_poolrw); return rval; } /* ------------------------------------------------------------------------ */ -/* Function: fr_iphmfindip */ +/* Function: ipf_iphmfindip */ /* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */ -/* Parameters: tptr(I) - pointer to the pool to search */ -/* version(I) - IP protocol version (4 or 6) */ -/* aptr(I) - pointer to address information */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* tptr(I) - pointer to the pool to search */ +/* ipversion(I) - IP protocol version (4 or 6) */ +/* aptr(I) - pointer to address information */ +/* bytes(I) - packet length */ /* */ /* Search the hash table for a given address and return a search result. */ /* ------------------------------------------------------------------------ */ -int fr_iphmfindip(tptr, version, aptr) -void *tptr, *aptr; -int version; +static int +ipf_iphmfindip(softc, tptr, ipversion, aptr, bytes) + ipf_main_softc_t *softc; + void *tptr, *aptr; + int ipversion; + u_int bytes; { struct in_addr *addr; iphtable_t *iph; iphtent_t *ipe; int rval; - if (version != 4) - return -1; - if (tptr == NULL || aptr == NULL) return -1; iph = tptr; addr = aptr; - READ_ENTER(&ip_poolrw); - ipe = fr_iphmfind(iph, addr); - if (ipe != NULL) + READ_ENTER(&softc->ipf_poolrw); + if (ipversion == 4) { + ipe = ipf_iphmfind(iph, addr); +#ifdef USE_INET6 + } else if (ipversion == 6) { + ipe = ipf_iphmfind6(iph, (i6addr_t *)addr); +#endif + } else { + ipe = NULL; + } + + if (ipe != NULL) { rval = 0; - else + ipe->ipe_hits++; + ipe->ipe_bytes += bytes; + } else { rval = 1; - RWLOCK_EXIT(&ip_poolrw); + } + RWLOCK_EXIT(&softc->ipf_poolrw); return rval; } -/* Locks: ip_poolrw */ -static iphtent_t *fr_iphmfind(iph, addr) -iphtable_t *iph; -struct in_addr *addr; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_iphmfindip */ +/* Parameters: iph(I) - pointer to hash table */ +/* addr(I) - pointer to IPv4 address */ +/* Locks: ipf_poolrw */ +/* */ +/* ------------------------------------------------------------------------ */ +static iphtent_t * +ipf_iphmfind(iph, addr) + iphtable_t *iph; + struct in_addr *addr; { - u_32_t hmsk, msk, ips; + u_32_t msk, ips; iphtent_t *ipe; u_int hv; + int i; - hmsk = iph->iph_masks; - msk = 0xffffffff; + i = 0; maskloop: - ips = ntohl(addr->s_addr) & msk; - hv = IPE_HASH_FN(ips, msk, iph->iph_size); - for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_next) { - if (ipe->ipe_mask.in4_addr != msk || - ipe->ipe_addr.in4_addr != ips) { + msk = iph->iph_v4_masks.imt4_active[i]; + ips = addr->s_addr & msk; + hv = IPE_V4_HASH_FN(ips, msk, iph->iph_size); + for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_hnext) { + if ((ipe->ipe_family != AF_INET) || + (ipe->ipe_mask.in4_addr != msk) || + (ipe->ipe_addr.in4_addr != ips)) { continue; } break; } - if ((ipe == NULL) && (hmsk != 0)) { - while (hmsk != 0) { - msk <<= 1; - if (hmsk & 0x80000000) - break; - hmsk <<= 1; - } - if (hmsk != 0) { - hmsk <<= 1; + if (ipe == NULL) { + i++; + if (i < iph->iph_v4_masks.imt4_max) goto maskloop; + } + return ipe; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htable_iter_next */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* token(I) - */ +/* ilp(I) - */ +/* */ +/* ------------------------------------------------------------------------ */ +static int +ipf_htable_iter_next(softc, arg, token, ilp) + ipf_main_softc_t *softc; + void *arg; + ipftoken_t *token; + ipflookupiter_t *ilp; +{ + ipf_htable_softc_t *softh = arg; + iphtent_t *node, zn, *nextnode; + iphtable_t *iph, zp, *nextiph; + void *hnext; + int err; + + err = 0; + iph = NULL; + node = NULL; + nextiph = NULL; + nextnode = NULL; + + READ_ENTER(&softc->ipf_poolrw); + + switch (ilp->ili_otype) + { + case IPFLOOKUPITER_LIST : + iph = token->ipt_data; + if (iph == NULL) { + nextiph = softh->ipf_htables[(int)ilp->ili_unit + 1]; + } else { + nextiph = iph->iph_next; + } + + if (nextiph != NULL) { + ATOMIC_INC(nextiph->iph_ref); + token->ipt_data = nextiph; + } else { + bzero((char *)&zp, sizeof(zp)); + nextiph = &zp; + token->ipt_data = NULL; + } + hnext = nextiph->iph_next; + break; + + case IPFLOOKUPITER_NODE : + node = token->ipt_data; + if (node == NULL) { + iph = ipf_htable_find(arg, ilp->ili_unit, + ilp->ili_name); + if (iph == NULL) { + IPFERROR(30009); + err = ESRCH; + } else { + nextnode = iph->iph_list; + } + } else { + nextnode = node->ipe_next; + } + + if (nextnode != NULL) { + ATOMIC_INC(nextnode->ipe_ref); + token->ipt_data = nextnode; + } else { + bzero((char *)&zn, sizeof(zn)); + nextnode = &zn; + token->ipt_data = NULL; + } + hnext = nextnode->ipe_next; + break; + + default : + IPFERROR(30010); + err = EINVAL; + hnext = NULL; + break; + } + + RWLOCK_EXIT(&softc->ipf_poolrw); + if (err != 0) + return err; + + switch (ilp->ili_otype) + { + case IPFLOOKUPITER_LIST : + err = COPYOUT(nextiph, ilp->ili_data, sizeof(*nextiph)); + if (err != 0) { + IPFERROR(30011); + err = EFAULT; + } + if (iph != NULL) { + WRITE_ENTER(&softc->ipf_poolrw); + ipf_htable_deref(softc, softh, iph); + RWLOCK_EXIT(&softc->ipf_poolrw); + } + break; + + case IPFLOOKUPITER_NODE : + err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode)); + if (err != 0) { + IPFERROR(30012); + err = EFAULT; + } + if (node != NULL) { + WRITE_ENTER(&softc->ipf_poolrw); + ipf_htent_deref(softc, node); + RWLOCK_EXIT(&softc->ipf_poolrw); } + break; + } + + if (hnext == NULL) + ipf_token_mark_complete(token); + + return err; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_htable_iter_deref */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* otype(I) - which data structure type is being walked */ +/* unit(I) - ipfilter device to which we are working on */ +/* data(I) - pointer to old data structure */ +/* */ +/* ------------------------------------------------------------------------ */ +static int +ipf_htable_iter_deref(softc, arg, otype, unit, data) + ipf_main_softc_t *softc; + void *arg; + int otype; + int unit; + void *data; +{ + + if (data == NULL) + return EFAULT; + + if (unit < -1 || unit > IPL_LOGMAX) + return EINVAL; + + switch (otype) + { + case IPFLOOKUPITER_LIST : + ipf_htable_deref(softc, arg, (iphtable_t *)data); + break; + + case IPFLOOKUPITER_NODE : + ipf_htent_deref(arg, (iphtent_t *)data); + break; + default : + break; + } + + return 0; +} + + +#ifdef USE_INET6 +/* ------------------------------------------------------------------------ */ +/* Function: ipf_iphmfind6 */ +/* Parameters: iph(I) - pointer to hash table */ +/* addr(I) - pointer to IPv6 address */ +/* Locks: ipf_poolrw */ +/* */ +/* ------------------------------------------------------------------------ */ +static iphtent_t * +ipf_iphmfind6(iph, addr) + iphtable_t *iph; + i6addr_t *addr; +{ + i6addr_t *msk, ips; + iphtent_t *ipe; + u_int hv; + int i; + + i = 0; +maskloop: + msk = iph->iph_v6_masks.imt6_active + i; + ips.i6[0] = addr->i6[0] & msk->i6[0]; + ips.i6[1] = addr->i6[1] & msk->i6[1]; + ips.i6[2] = addr->i6[2] & msk->i6[2]; + ips.i6[3] = addr->i6[3] & msk->i6[3]; + hv = IPE_V6_HASH_FN(ips.i6, msk->i6, iph->iph_size); + for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_next) { + if ((ipe->ipe_family != AF_INET6) || + IP6_NEQ(&ipe->ipe_mask, msk) || + IP6_NEQ(&ipe->ipe_addr, &ips)) { + continue; + } + break; + } + + if (ipe == NULL) { + i++; + if (i < iph->iph_v6_masks.imt6_max) + goto maskloop; } return ipe; } +#endif + + +static void +ipf_htable_expire(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_htable_softc_t *softh = arg; + iphtent_t *n; + + while ((n = softh->ipf_node_explist) != NULL) { + if (n->ipe_die > softc->ipf_ticks) + break; + + ipf_htent_remove(softc, softh, n->ipe_owner, n); + } +} + -#endif /* IPFILTER_LOOKUP */ +#ifndef _KERNEL + +/* ------------------------------------------------------------------------ */ +/* */ +/* ------------------------------------------------------------------------ */ +void +ipf_htable_dump(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_htable_softc_t *softh = arg; + iphtable_t *iph; + int i; + + printf("List of configured hash tables\n"); + for (i = 0; i < IPL_LOGSIZE; i++) + for (iph = softh->ipf_htables[i]; iph != NULL; + iph = iph->iph_next) + printhash(iph, bcopywrap, NULL, opts, NULL); + +} +#endif diff --git a/ip_htable.h b/ip_htable.h index e13845977d097..8038bbcc1044c 100644 --- a/ip_htable.h +++ b/ip_htable.h @@ -1,5 +1,3 @@ -/* $NetBSD$ */ - #ifndef __IP_HTABLE_H__ #define __IP_HTABLE_H__ @@ -7,40 +5,60 @@ typedef struct iphtent_s { struct iphtent_s *ipe_next, **ipe_pnext; + struct iphtent_s *ipe_hnext, **ipe_phnext; + struct iphtent_s *ipe_dnext, **ipe_pdnext; + struct iphtable_s *ipe_owner; void *ipe_ptr; i6addr_t ipe_addr; i6addr_t ipe_mask; + U_QUAD_T ipe_hits; + U_QUAD_T ipe_bytes; + u_long ipe_die; + int ipe_uid; int ipe_ref; + int ipe_unit; + char ipe_family; + char ipe_xxx[3]; union { char ipeu_char[16]; u_long ipeu_long; u_int ipeu_int; - }ipe_un; + } ipe_un; } iphtent_t; #define ipe_value ipe_un.ipeu_int #define ipe_group ipe_un.ipeu_char -#define IPE_HASH_FN(a, m, s) (((a) * (m)) % (s)) - +#define IPE_V4_HASH_FN(a, m, s) ((((m) ^ (a)) - 1 - ((a) >> 8)) % (s)) +#define IPE_V6_HASH_FN(a, m, s) (((((m)[0] ^ (a)[0]) - ((a)[0] >> 8)) + \ + (((m)[1] & (a)[1]) - ((a)[1] >> 8)) + \ + (((m)[2] & (a)[2]) - ((a)[2] >> 8)) + \ + (((m)[3] & (a)[3]) - ((a)[3] >> 8))) % (s)) typedef struct iphtable_s { ipfrwlock_t iph_rwlock; struct iphtable_s *iph_next, **iph_pnext; struct iphtent_s **iph_table; + struct iphtent_s *iph_list; + struct iphtent_s **iph_tail; +#ifdef USE_INET6 + ipf_v6_masktab_t iph_v6_masks; +#endif + ipf_v4_masktab_t iph_v4_masks; size_t iph_size; /* size of hash table */ u_long iph_seed; /* hashing seed */ u_32_t iph_flags; u_int iph_unit; /* IPL_LOG* */ u_int iph_ref; u_int iph_type; /* lookup or group map - IPHASH_* */ - u_int iph_masks; /* IPv4 netmasks in use */ + u_int iph_maskset[4]; /* netmasks in use */ char iph_name[FR_GROUPLEN]; /* hash table number */ } iphtable_t; /* iph_type */ #define IPHASH_LOOKUP 0 #define IPHASH_GROUPMAP 1 +#define IPHASH_DELETE 2 #define IPHASH_ANON 0x80000000 @@ -53,19 +71,11 @@ typedef struct iphtstat_s { } iphtstat_t; -extern iphtable_t *ipf_htables[IPL_LOGSIZE]; - -extern void fr_htable_unload __P((void)); -extern int fr_newhtable __P((iplookupop_t *)); -extern iphtable_t *fr_findhtable __P((int, char *)); -extern int fr_removehtable __P((iplookupop_t *)); -extern size_t fr_flushhtable __P((iplookupflush_t *)); -extern int fr_addhtent __P((iphtable_t *, iphtent_t *)); -extern int fr_delhtent __P((iphtable_t *, iphtent_t *)); -extern void fr_derefhtable __P((iphtable_t *)); -extern void fr_delhtable __P((iphtable_t *)); -extern void *fr_iphmfindgroup __P((void *, void *)); -extern int fr_iphmfindip __P((void *, int, void *)); -extern int fr_gethtablestat __P((iplookupop_t *)); +extern void *ipf_iphmfindgroup __P((ipf_main_softc_t *, void *, void *)); +extern iphtable_t *ipf_htable_find __P((void *, int, char *)); +extern ipf_lookup_t ipf_htable_backend; +#ifndef _KERNEL +extern void ipf_htable_dump __P((ipf_main_softc_t *, void *)); +#endif #endif /* __IP_HTABLE_H__ */ diff --git a/ip_ipsec_pxy.c b/ip_ipsec_pxy.c index 2159ecb08078a..980476ad8bf98 100644 --- a/ip_ipsec_pxy.c +++ b/ip_ipsec_pxy.c @@ -1,154 +1,228 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 2001-2003 by Darren Reed + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * Simple ISAKMP transparent proxy for in-kernel use. For use with the NAT * code. * - * Id: ip_ipsec_pxy.c,v 2.20.2.6 2005/03/28 10:47:53 darrenr Exp + * $Id$ * */ #define IPF_IPSEC_PROXY -int ippr_ipsec_init __P((void)); -void ippr_ipsec_fini __P((void)); -int ippr_ipsec_new __P((fr_info_t *, ap_session_t *, nat_t *)); -void ippr_ipsec_del __P((ap_session_t *)); -int ippr_ipsec_inout __P((fr_info_t *, ap_session_t *, nat_t *)); -int ippr_ipsec_match __P((fr_info_t *, ap_session_t *, nat_t *)); - -static frentry_t ipsecfr; -static ipftq_t *ipsecnattqe; -static ipftq_t *ipsecstatetqe; -static char ipsec_buffer[1500]; +/* + * IPSec proxy + */ +typedef struct ipf_ipsec_softc_s { + frentry_t ipsec_fr; + int ipsec_proxy_init; + int ipsec_proxy_ttl; + ipftq_t *ipsec_nat_tqe; + ipftq_t *ipsec_state_tqe; + char ipsec_buffer[1500]; +} ipf_ipsec_softc_t; + + +void *ipf_p_ipsec_soft_create __P((ipf_main_softc_t *)); +void ipf_p_ipsec_soft_destroy __P((ipf_main_softc_t *, void *)); +int ipf_p_ipsec_soft_init __P((ipf_main_softc_t *, void *)); +void ipf_p_ipsec_soft_fini __P((ipf_main_softc_t *, void *)); +int ipf_p_ipsec_init __P((void)); +void ipf_p_ipsec_fini __P((void)); +int ipf_p_ipsec_new __P((void *, fr_info_t *, ap_session_t *, nat_t *)); +void ipf_p_ipsec_del __P((ipf_main_softc_t *, ap_session_t *)); +int ipf_p_ipsec_inout __P((void *, fr_info_t *, ap_session_t *, nat_t *)); +int ipf_p_ipsec_match __P((fr_info_t *, ap_session_t *, nat_t *)); -int ipsec_proxy_init = 0; -int ipsec_proxy_ttl = 60; /* * IPSec application proxy initialization. */ -int ippr_ipsec_init() +void * +ipf_p_ipsec_soft_create(softc) + ipf_main_softc_t *softc; { - bzero((char *)&ipsecfr, sizeof(ipsecfr)); - ipsecfr.fr_ref = 1; - ipsecfr.fr_flags = FR_OUTQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE; - MUTEX_INIT(&ipsecfr.fr_lock, "IPsec proxy rule lock"); - ipsec_proxy_init = 1; - - ipsecnattqe = fr_addtimeoutqueue(&nat_utqe, ipsec_proxy_ttl); - if (ipsecnattqe == NULL) + ipf_ipsec_softc_t *softi; + + KMALLOC(softi, ipf_ipsec_softc_t *); + if (softi == NULL) + return NULL; + + bzero((char *)softi, sizeof(*softi)); + softi->ipsec_fr.fr_ref = 1; + softi->ipsec_fr.fr_flags = FR_OUTQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE; + MUTEX_INIT(&softi->ipsec_fr.fr_lock, "IPsec proxy rule lock"); + softi->ipsec_proxy_init = 1; + softi->ipsec_proxy_ttl = 60; + + return softi; +} + + +int +ipf_p_ipsec_soft_init(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_ipsec_softc_t *softi = arg; + + softi->ipsec_nat_tqe = ipf_state_add_tq(softc, softi->ipsec_proxy_ttl); + if (softi->ipsec_nat_tqe == NULL) return -1; - ipsecstatetqe = fr_addtimeoutqueue(&ips_utqe, ipsec_proxy_ttl); - if (ipsecstatetqe == NULL) { - if (fr_deletetimeoutqueue(ipsecnattqe) == 0) - fr_freetimeoutqueue(ipsecnattqe); - ipsecnattqe = NULL; + softi->ipsec_state_tqe = ipf_nat_add_tq(softc, softi->ipsec_proxy_ttl); + if (softi->ipsec_state_tqe == NULL) { + if (ipf_deletetimeoutqueue(softi->ipsec_nat_tqe) == 0) + ipf_freetimeoutqueue(softc, softi->ipsec_nat_tqe); + softi->ipsec_nat_tqe = NULL; return -1; } - ipsecnattqe->ifq_flags |= IFQF_PROXY; - ipsecstatetqe->ifq_flags |= IFQF_PROXY; - - ipsecfr.fr_age[0] = ipsec_proxy_ttl; - ipsecfr.fr_age[1] = ipsec_proxy_ttl; + softi->ipsec_nat_tqe->ifq_flags |= IFQF_PROXY; + softi->ipsec_state_tqe->ifq_flags |= IFQF_PROXY; + softi->ipsec_fr.fr_age[0] = softi->ipsec_proxy_ttl; + softi->ipsec_fr.fr_age[1] = softi->ipsec_proxy_ttl; return 0; } -void ippr_ipsec_fini() +void +ipf_p_ipsec_soft_fini(softc, arg) + ipf_main_softc_t *softc; + void *arg; { - if (ipsecnattqe != NULL) { - if (fr_deletetimeoutqueue(ipsecnattqe) == 0) - fr_freetimeoutqueue(ipsecnattqe); + ipf_ipsec_softc_t *softi = arg; + + if (arg == NULL) + return; + + if (softi->ipsec_nat_tqe != NULL) { + if (ipf_deletetimeoutqueue(softi->ipsec_nat_tqe) == 0) + ipf_freetimeoutqueue(softc, softi->ipsec_nat_tqe); } - ipsecnattqe = NULL; - if (ipsecstatetqe != NULL) { - if (fr_deletetimeoutqueue(ipsecstatetqe) == 0) - fr_freetimeoutqueue(ipsecstatetqe); + softi->ipsec_nat_tqe = NULL; + if (softi->ipsec_state_tqe != NULL) { + if (ipf_deletetimeoutqueue(softi->ipsec_state_tqe) == 0) + ipf_freetimeoutqueue(softc, softi->ipsec_state_tqe); } - ipsecstatetqe = NULL; + softi->ipsec_state_tqe = NULL; +} + - if (ipsec_proxy_init == 1) { - MUTEX_DESTROY(&ipsecfr.fr_lock); - ipsec_proxy_init = 0; +void +ipf_p_ipsec_soft_destroy(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_ipsec_softc_t *softi = arg; + + if (softi->ipsec_proxy_init == 1) { + MUTEX_DESTROY(&softi->ipsec_fr.fr_lock); + softi->ipsec_proxy_init = 0; } + + KFREE(softi); } /* * Setup for a new IPSEC proxy. */ -int ippr_ipsec_new(fin, aps, nat) -fr_info_t *fin; -ap_session_t *aps; -nat_t *nat; +int +ipf_p_ipsec_new(arg, fin, aps, nat) + void *arg; + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; { + ipf_ipsec_softc_t *softi = arg; + ipf_main_softc_t *softc = fin->fin_main_soft; +#ifdef USE_MUTEXES + ipf_nat_softc_t *softn = softc->ipf_nat_soft; +#endif + int p, off, dlen, ttl; ipsec_pxy_t *ipsec; + ipnat_t *ipn, *np; fr_info_t fi; - ipnat_t *ipn; char *ptr; - int p, off, dlen, ttl; - mb_t *m; + int size; ip_t *ip; + mb_t *m; + + if (fin->fin_v != 4) + return -1; - bzero(ipsec_buffer, sizeof(ipsec_buffer)); - off = fin->fin_hlen + sizeof(udphdr_t); + off = fin->fin_plen - fin->fin_dlen + fin->fin_ipoff; + bzero(softi->ipsec_buffer, sizeof(softi->ipsec_buffer)); ip = fin->fin_ip; m = fin->fin_m; dlen = M_LEN(m) - off; if (dlen < 16) return -1; - COPYDATA(m, off, MIN(sizeof(ipsec_buffer), dlen), ipsec_buffer); + COPYDATA(m, off, MIN(sizeof(softi->ipsec_buffer), dlen), + softi->ipsec_buffer); - if (nat_outlookup(fin, 0, IPPROTO_ESP, nat->nat_inip, + if (ipf_nat_outlookup(fin, 0, IPPROTO_ESP, nat->nat_nsrcip, ip->ip_dst) != NULL) return -1; - aps->aps_psiz = sizeof(*ipsec); - KMALLOCS(aps->aps_data, ipsec_pxy_t *, sizeof(*ipsec)); - if (aps->aps_data == NULL) + np = nat->nat_ptr; + size = np->in_size; + KMALLOC(ipsec, ipsec_pxy_t *); + if (ipsec == NULL) return -1; - ipsec = aps->aps_data; + KMALLOCS(ipn, ipnat_t *, size); + if (ipn == NULL) { + KFREE(ipsec); + return -1; + } + + aps->aps_data = ipsec; + aps->aps_psiz = sizeof(*ipsec); bzero((char *)ipsec, sizeof(*ipsec)); + bzero((char *)ipn, size); + ipsec->ipsc_rule = ipn; /* * Create NAT rule against which the tunnel/transport mapping is * created. This is required because the current NAT rule does not * describe ESP but UDP instead. */ - ipn = &ipsec->ipsc_rule; - ttl = IPF_TTLVAL(ipsecnattqe->ifq_ttl); - ipn->in_tqehead[0] = fr_addtimeoutqueue(&nat_utqe, ttl); - ipn->in_tqehead[1] = fr_addtimeoutqueue(&nat_utqe, ttl); + ipn->in_size = size; + ttl = IPF_TTLVAL(softi->ipsec_nat_tqe->ifq_ttl); + ipn->in_tqehead[0] = ipf_nat_add_tq(softc, ttl); + ipn->in_tqehead[1] = ipf_nat_add_tq(softc, ttl); ipn->in_ifps[0] = fin->fin_ifp; ipn->in_apr = NULL; ipn->in_use = 1; ipn->in_hits = 1; - ipn->in_nip = ntohl(nat->nat_outip.s_addr); + ipn->in_snip = ntohl(nat->nat_nsrcaddr); ipn->in_ippip = 1; - ipn->in_inip = nat->nat_inip.s_addr; - ipn->in_inmsk = 0xffffffff; - ipn->in_outip = fin->fin_saddr; - ipn->in_outmsk = nat->nat_outip.s_addr; - ipn->in_srcip = fin->fin_saddr; - ipn->in_srcmsk = 0xffffffff; + ipn->in_osrcip = nat->nat_osrcip; + ipn->in_osrcmsk = 0xffffffff; + ipn->in_nsrcip = nat->nat_nsrcip; + ipn->in_nsrcmsk = 0xffffffff; + ipn->in_odstip = nat->nat_odstip; + ipn->in_odstmsk = 0xffffffff; + ipn->in_ndstip = nat->nat_ndstip; + ipn->in_ndstmsk = 0xffffffff; ipn->in_redir = NAT_MAP; - bcopy(nat->nat_ptr->in_ifnames[0], ipn->in_ifnames[0], - sizeof(ipn->in_ifnames[0])); - ipn->in_p = IPPROTO_ESP; + ipn->in_pr[0] = IPPROTO_ESP; + ipn->in_pr[1] = IPPROTO_ESP; + ipn->in_flags = (np->in_flags | IPN_PROXYRULE); + MUTEX_INIT(&ipn->in_lock, "IPSec proxy NAT rule"); + + ipn->in_namelen = np->in_namelen; + bcopy(np->in_names, ipn->in_ifnames, ipn->in_namelen); + ipn->in_ifnames[0] = np->in_ifnames[0]; + ipn->in_ifnames[1] = np->in_ifnames[1]; bcopy((char *)fin, (char *)&fi, sizeof(fi)); - fi.fin_state = NULL; - fi.fin_nat = NULL; fi.fin_fi.fi_p = IPPROTO_ESP; - fi.fin_fr = &ipsecfr; + fi.fin_fr = &softi->ipsec_fr; fi.fin_data[0] = 0; fi.fin_data[1] = 0; p = ip->ip_p; @@ -156,7 +230,7 @@ nat_t *nat; fi.fin_flx &= ~(FI_TCPUDP|FI_STATE|FI_FRAG); fi.fin_flx |= FI_IGNORE; - ptr = ipsec_buffer; + ptr = softi->ipsec_buffer; bcopy(ptr, (char *)ipsec->ipsc_icookie, sizeof(ipsec_cookie_t)); ptr += sizeof(ipsec_cookie_t); bcopy(ptr, (char *)ipsec->ipsc_rcookie, sizeof(ipsec_cookie_t)); @@ -168,18 +242,19 @@ nat_t *nat; if ((ipsec->ipsc_rcookie[0]|ipsec->ipsc_rcookie[1]) != 0) ipsec->ipsc_rckset = 1; - ipsec->ipsc_nat = nat_new(&fi, ipn, &ipsec->ipsc_nat, - NAT_SLAVE|SI_WILDP, NAT_OUTBOUND); + MUTEX_ENTER(&softn->ipf_nat_new); + ipsec->ipsc_nat = ipf_nat_add(&fi, ipn, &ipsec->ipsc_nat, + NAT_SLAVE|SI_WILDP, NAT_OUTBOUND); + MUTEX_EXIT(&softn->ipf_nat_new); if (ipsec->ipsc_nat != NULL) { - (void) nat_proto(&fi, ipsec->ipsc_nat, 0); - nat_update(&fi, ipsec->ipsc_nat, ipn); + (void) ipf_nat_proto(&fi, ipsec->ipsc_nat, 0); + MUTEX_ENTER(&ipsec->ipsc_nat->nat_lock); + ipf_nat_update(&fi, ipsec->ipsc_nat); + MUTEX_EXIT(&ipsec->ipsc_nat->nat_lock); fi.fin_data[0] = 0; fi.fin_data[1] = 0; - ipsec->ipsc_state = fr_addstate(&fi, &ipsec->ipsc_state, - SI_WILDP); - if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); + (void) ipf_state_add(softc, &fi, &ipsec->ipsc_state, SI_WILDP); } ip->ip_p = p & 0xff; return 0; @@ -190,11 +265,15 @@ nat_t *nat; * For outgoing IKE packets. refresh timeouts for NAT & state entries, if * we can. If they have disappeared, recreate them. */ -int ippr_ipsec_inout(fin, aps, nat) -fr_info_t *fin; -ap_session_t *aps; -nat_t *nat; +int +ipf_p_ipsec_inout(arg, fin, aps, nat) + void *arg; + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; { + ipf_ipsec_softc_t *softi = arg; + ipf_main_softc_t *softc = fin->fin_main_soft; ipsec_pxy_t *ipsec; fr_info_t fi; ip_t *ip; @@ -214,10 +293,8 @@ nat_t *nat; if ((ipsec->ipsc_nat == NULL) || (ipsec->ipsc_state == NULL)) { bcopy((char *)fin, (char *)&fi, sizeof(fi)); - fi.fin_state = NULL; - fi.fin_nat = NULL; fi.fin_fi.fi_p = IPPROTO_ESP; - fi.fin_fr = &ipsecfr; + fi.fin_fr = &softi->ipsec_fr; fi.fin_data[0] = 0; fi.fin_data[1] = 0; ip->ip_p = IPPROTO_ESP; @@ -229,36 +306,42 @@ nat_t *nat; * Update NAT timeout/create NAT if missing. */ if (ipsec->ipsc_nat != NULL) - fr_queueback(&ipsec->ipsc_nat->nat_tqe); + ipf_queueback(softc->ipf_ticks, + &ipsec->ipsc_nat->nat_tqe); else { - ipsec->ipsc_nat = nat_new(&fi, &ipsec->ipsc_rule, - &ipsec->ipsc_nat, - NAT_SLAVE|SI_WILDP, - nat->nat_dir); +#ifdef USE_MUTEXES + ipf_nat_softc_t *softn = softc->ipf_nat_soft; +#endif + + MUTEX_ENTER(&softn->ipf_nat_new); + ipsec->ipsc_nat = ipf_nat_add(&fi, ipsec->ipsc_rule, + &ipsec->ipsc_nat, + NAT_SLAVE|SI_WILDP, + nat->nat_dir); + MUTEX_EXIT(&softn->ipf_nat_new); if (ipsec->ipsc_nat != NULL) { - (void) nat_proto(&fi, ipsec->ipsc_nat, 0); - nat_update(&fi, ipsec->ipsc_nat, - &ipsec->ipsc_rule); + (void) ipf_nat_proto(&fi, ipsec->ipsc_nat, 0); + MUTEX_ENTER(&ipsec->ipsc_nat->nat_lock); + ipf_nat_update(&fi, ipsec->ipsc_nat); + MUTEX_EXIT(&ipsec->ipsc_nat->nat_lock); } } /* * Update state timeout/create state if missing. */ - READ_ENTER(&ipf_state); + READ_ENTER(&softc->ipf_state); if (ipsec->ipsc_state != NULL) { - fr_queueback(&ipsec->ipsc_state->is_sti); + ipf_queueback(softc->ipf_ticks, + &ipsec->ipsc_state->is_sti); ipsec->ipsc_state->is_die = nat->nat_age; - RWLOCK_EXIT(&ipf_state); + RWLOCK_EXIT(&softc->ipf_state); } else { - RWLOCK_EXIT(&ipf_state); + RWLOCK_EXIT(&softc->ipf_state); fi.fin_data[0] = 0; fi.fin_data[1] = 0; - ipsec->ipsc_state = fr_addstate(&fi, - &ipsec->ipsc_state, - SI_WILDP); - if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); + (void) ipf_state_add(softc, &fi, &ipsec->ipsc_state, + SI_WILDP); } ip->ip_p = p; } @@ -272,10 +355,11 @@ nat_t *nat; * in the same order (not reversed depending on packet flow direction as with * UDP/TCP port numbers). */ -int ippr_ipsec_match(fin, aps, nat) -fr_info_t *fin; -ap_session_t *aps; -nat_t *nat; +int +ipf_p_ipsec_match(fin, aps, nat) + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; { ipsec_pxy_t *ipsec; u_32_t cookies[4]; @@ -287,8 +371,8 @@ nat_t *nat; if ((fin->fin_dlen < sizeof(cookies)) || (fin->fin_flx & FI_FRAG)) return -1; + off = fin->fin_plen - fin->fin_dlen + fin->fin_ipoff; ipsec = aps->aps_data; - off = fin->fin_hlen + sizeof(udphdr_t); m = fin->fin_m; COPYDATA(m, off, sizeof(cookies), (char *)cookies); @@ -316,8 +400,10 @@ nat_t *nat; /* * clean up after ourselves. */ -void ippr_ipsec_del(aps) -ap_session_t *aps; +void +ipf_p_ipsec_del(softc, aps) + ipf_main_softc_t *softc; + ap_session_t *aps; { ipsec_pxy_t *ipsec; @@ -329,15 +415,17 @@ ap_session_t *aps; * *_del() is on a callback from aps_free(), from nat_delete() */ - READ_ENTER(&ipf_state); + READ_ENTER(&softc->ipf_state); if (ipsec->ipsc_state != NULL) { - ipsec->ipsc_state->is_die = fr_ticks + 1; + ipsec->ipsc_state->is_die = softc->ipf_ticks + 1; ipsec->ipsc_state->is_me = NULL; - fr_queuefront(&ipsec->ipsc_state->is_sti); + ipf_queuefront(&ipsec->ipsc_state->is_sti); } - RWLOCK_EXIT(&ipf_state); + RWLOCK_EXIT(&softc->ipf_state); ipsec->ipsc_state = NULL; ipsec->ipsc_nat = NULL; + ipsec->ipsc_rule->in_flags |= IPN_DELETE; + ipf_nat_rule_deref(softc, &ipsec->ipsc_rule); } } diff --git a/ip_irc_pxy.c b/ip_irc_pxy.c index 45a120f519b69..b9954b4c067ab 100644 --- a/ip_irc_pxy.c +++ b/ip_irc_pxy.c @@ -1,11 +1,9 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 2000-2003 Darren Reed + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * Id: ip_irc_pxy.c,v 2.39.2.4 2005/02/04 10:22:55 darrenr Exp + * $Id$ */ #define IPF_IRC_PROXY @@ -13,12 +11,12 @@ #define IPF_IRCBUFSZ 96 /* This *MUST* be >= 64! */ -int ippr_irc_init __P((void)); -void ippr_irc_fini __P((void)); -int ippr_irc_new __P((fr_info_t *, ap_session_t *, nat_t *)); -int ippr_irc_out __P((fr_info_t *, ap_session_t *, nat_t *)); -int ippr_irc_send __P((fr_info_t *, nat_t *)); -int ippr_irc_complete __P((ircinfo_t *, char *, size_t)); +void ipf_p_irc_main_load __P((void)); +void ipf_p_irc_main_unload __P((void)); +int ipf_p_irc_new __P((void *, fr_info_t *, ap_session_t *, nat_t *)); +int ipf_p_irc_out __P((void *, fr_info_t *, ap_session_t *, nat_t *)); +int ipf_p_irc_send __P((fr_info_t *, nat_t *)); +int ipf_p_irc_complete __P((ircinfo_t *, char *, size_t)); u_short ipf_irc_atoi __P((char **)); static frentry_t ircnatfr; @@ -29,19 +27,19 @@ int irc_proxy_init = 0; /* * Initialize local structures. */ -int ippr_irc_init() +void +ipf_p_irc_main_load() { bzero((char *)&ircnatfr, sizeof(ircnatfr)); ircnatfr.fr_ref = 1; ircnatfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE; MUTEX_INIT(&ircnatfr.fr_lock, "IRC proxy rule lock"); irc_proxy_init = 1; - - return 0; } -void ippr_irc_fini() +void +ipf_p_irc_main_unload() { if (irc_proxy_init == 1) { MUTEX_DESTROY(&ircnatfr.fr_lock); @@ -50,7 +48,7 @@ void ippr_irc_fini() } -char *ippr_irc_dcctypes[] = { +const char *ipf_p_irc_dcctypes[] = { "CHAT ", /* CHAT chat ipnumber portnumber */ "SEND ", /* SEND filename ipnumber portnumber */ "MOVE ", @@ -66,10 +64,11 @@ char *ippr_irc_dcctypes[] = { */ -int ippr_irc_complete(ircp, buf, len) -ircinfo_t *ircp; -char *buf; -size_t len; +int +ipf_p_irc_complete(ircp, buf, len) + ircinfo_t *ircp; + char *buf; + size_t len; { register char *s, c; register size_t i; @@ -147,12 +146,12 @@ size_t len; /* * Check for a recognised DCC command */ - for (j = 0, k = 0; ippr_irc_dcctypes[j]; j++) { - k = MIN(strlen(ippr_irc_dcctypes[j]), i); - if (!strncmp(ippr_irc_dcctypes[j], s, k)) + for (j = 0, k = 0; ipf_p_irc_dcctypes[j]; j++) { + k = MIN(strlen(ipf_p_irc_dcctypes[j]), i); + if (!strncmp(ipf_p_irc_dcctypes[j], s, k)) break; } - if (!ippr_irc_dcctypes[j]) + if (!ipf_p_irc_dcctypes[j]) return 0; ircp->irc_type = s; @@ -224,18 +223,22 @@ size_t len; } -int ippr_irc_new(fin, aps, nat) -fr_info_t *fin; -ap_session_t *aps; -nat_t *nat; +int +ipf_p_irc_new(arg, fin, aps, nat) + void *arg; + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; { ircinfo_t *irc; + if (fin->fin_v != 4) + return -1; + KMALLOC(irc, ircinfo_t *); if (irc == NULL) return -1; - fin = fin; /* LINT */ nat = nat; /* LINT */ aps->aps_data = irc; @@ -246,13 +249,15 @@ nat_t *nat; } -int ippr_irc_send(fin, nat) -fr_info_t *fin; -nat_t *nat; +int +ipf_p_irc_send(fin, nat) + fr_info_t *fin; + nat_t *nat; { char ctcpbuf[IPF_IRCBUFSZ], newbuf[IPF_IRCBUFSZ]; tcphdr_t *tcp, tcph, *tcp2 = &tcph; int off, inc = 0, i, dlen; + ipf_main_softc_t *softc; size_t nlen = 0, olen; struct in_addr swip; u_short a5, sp; @@ -265,6 +270,7 @@ nat_t *nat; #ifdef MENTAT mb_t *m1; #endif + softc = fin->fin_main_soft; m = fin->fin_m; ip = fin->fin_ip; @@ -287,14 +293,14 @@ nat_t *nat; *newbuf = '\0'; irc = nat->nat_aps->aps_data; - if (ippr_irc_complete(irc, ctcpbuf, dlen) == 0) + if (ipf_p_irc_complete(irc, ctcpbuf, dlen) == 0) return 0; /* - * check that IP address in the PORT/PASV reply is the same as the - * sender of the command - prevents using PORT for port scanning. + * check that IP address in the DCC reply is the same as the + * sender of the command - prevents use for port scanning. */ - if (irc->irc_ipnum != ntohl(nat->nat_inip.s_addr)) + if (irc->irc_ipnum != ntohl(nat->nat_osrcaddr)) return 0; a5 = irc->irc_port; @@ -317,7 +323,7 @@ nat_t *nat; nlen = strlen(newbuf); inc = nlen - olen; - if ((inc + ip->ip_len) > 65535) + if ((inc + fin->fin_plen) > 65535) return 0; #ifdef MENTAT @@ -328,14 +334,14 @@ nat_t *nat; /* alloc enough to keep same trailer space for lower driver */ nm = allocb(nlen, BPRI_MED); - PANIC((!nm),("ippr_irc_out: allocb failed")); + PANIC((!nm),("ipf_p_irc_out: allocb failed")); nm->b_band = m1->b_band; nm->b_wptr += nlen; m1->b_wptr -= olen; PANIC((m1->b_wptr < m1->b_rptr), - ("ippr_irc_out: cannot handle fragmented data block")); + ("ipf_p_irc_out: cannot handle fragmented data block")); linkb(m1, nm); } else { @@ -352,13 +358,14 @@ nat_t *nat; /* the mbuf chain will be extended if necessary by m_copyback() */ #endif COPYBACK(m, off, nlen, newbuf); + fin->fin_flx |= FI_DOCKSUM; if (inc != 0) { #if defined(MENTAT) || defined(__sgi) register u_32_t sum1, sum2; - sum1 = ip->ip_len; - sum2 = ip->ip_len + inc; + sum1 = fin->fin_plen; + sum2 = fin->fin_plen + inc; /* Because ~1 == -2, We really need ~1 == -1 */ if (sum1 > sum2) @@ -366,9 +373,11 @@ nat_t *nat; sum2 -= sum1; sum2 = (sum2 & 0xffff) + (sum2 >> 16); - fix_outcksum(fin, &ip->ip_sum, sum2); + ipf_fix_outcksum(0, &ip->ip_sum, sum2, 0); #endif - ip->ip_len += inc; + fin->fin_plen += inc; + ip->ip_len = htons(fin->fin_plen); + fin->fin_dlen += inc; } /* @@ -391,16 +400,18 @@ nat_t *nat; bcopy((caddr_t)fin, (caddr_t)&fi, sizeof(fi)); fi.fin_data[0] = sp; fi.fin_data[1] = fin->fin_data[1]; - nat2 = nat_outlookup(fin, IPN_TCP, nat->nat_p, nat->nat_inip, + nat2 = ipf_nat_outlookup(fin, IPN_TCP, nat->nat_pr[1], nat->nat_nsrcip, ip->ip_dst); if (nat2 == NULL) { +#ifdef USE_MUTEXES + ipf_nat_softc_t *softn = softc->ipf_nat_soft; +#endif + bcopy((caddr_t)fin, (caddr_t)&fi, sizeof(fi)); bzero((char *)tcp2, sizeof(*tcp2)); tcp2->th_win = htons(8192); tcp2->th_sport = sp; tcp2->th_dport = 0; /* XXX - don't specify remote port */ - fi.fin_state = NULL; - fi.fin_nat = NULL; fi.fin_data[0] = ntohs(sp); fi.fin_data[1] = 0; fi.fin_dp = (char *)tcp2; @@ -408,16 +419,18 @@ nat_t *nat; fi.fin_dlen = sizeof(*tcp2); fi.fin_plen = fi.fin_hlen + sizeof(*tcp2); swip = ip->ip_src; - ip->ip_src = nat->nat_inip; - nat2 = nat_new(&fi, nat->nat_ptr, NULL, + ip->ip_src = nat->nat_nsrcip; + MUTEX_ENTER(&softn->ipf_nat_new); + nat2 = ipf_nat_add(&fi, nat->nat_ptr, NULL, NAT_SLAVE|IPN_TCP|SI_W_DPORT, NAT_OUTBOUND); + MUTEX_EXIT(&softn->ipf_nat_new); if (nat2 != NULL) { - (void) nat_proto(&fi, nat2, 0); - nat_update(&fi, nat2, nat2->nat_ptr); + (void) ipf_nat_proto(&fi, nat2, 0); + MUTEX_ENTER(&nat2->nat_lock); + ipf_nat_update(&fi, nat2); + MUTEX_EXIT(&nat2->nat_lock); - (void) fr_addstate(&fi, NULL, SI_W_DPORT); - if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); + (void) ipf_state_add(softc, &fi, NULL, SI_W_DPORT); } ip->ip_src = swip; } @@ -425,11 +438,13 @@ nat_t *nat; } -int ippr_irc_out(fin, aps, nat) -fr_info_t *fin; -ap_session_t *aps; -nat_t *nat; +int +ipf_p_irc_out(arg, fin, aps, nat) + void *arg; + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; { aps = aps; /* LINT */ - return ippr_irc_send(fin, nat); + return ipf_p_irc_send(fin, nat); } diff --git a/ip_lfil.c b/ip_lfil.c deleted file mode 100644 index 196d64e0fedf2..0000000000000 --- a/ip_lfil.c +++ /dev/null @@ -1,975 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - */ -#if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_lfil.c,v 2.6.2.5 2002/10/03 13:47:19 darrenr Exp $"; -#endif - -#if defined(KERNEL) && !defined(_KERNEL) -# define _KERNEL -#endif -#include <sys/errno.h> -#include <sys/types.h> -#include <sys/param.h> -#include <sys/file.h> -#include <sys/ioctl.h> -#include <sys/time.h> -#include <sys/dir.h> -#include <sys/socket.h> -#ifndef _KERNEL -# include <stdio.h> -# include <string.h> -# include <stdlib.h> -# include <ctype.h> -#else -# include <linux/module.h> -#endif - -#include <net/if.h> -#include <net/route.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/tcp.h> -#include <netinet/udp.h> -#include <netinet/ip_icmp.h> -#ifndef _KERNEL -# include <syslog.h> -#endif -#include "netinet/ip_compat.h" -#include <netinet/tcpip.h> -#include "netinet/ip_fil.h" -#include "netinet/ip_nat.h" -#include "netinet/ip_proxy.h" -#include "netinet/ip_frag.h" -#include "netinet/ip_state.h" -#include "netinet/ip_auth.h" -#ifdef _KERNEL -#include <net/ip_forward.h> -#endif -#ifndef MIN -#define MIN(a,b) (((a)<(b))?(a):(b)) -#endif - - -#ifndef _KERNEL -# include "ipt.h" -static struct ifnet **ifneta = NULL; -static int nifs = 0; -#endif - -int fr_running = 0; -int ipl_unreach = ICMP_UNREACH_FILTER; -u_long ipl_frouteok[2] = {0, 0}; - -static int frzerostats __P((caddr_t)); -static void frsync __P((void)); -#if defined(__NetBSD__) || defined(__OpenBSD__) -static int frrequest __P((int, u_long, caddr_t, int)); -#else -static int frrequest __P((int, u_long, caddr_t, int)); -#endif -#ifdef _KERNEL -static int (*fr_savep) __P((ip_t *, int, void *, int, mb_t **)); -#else -int ipllog __P((void)); -void init_ifp __P((void)); -static int no_output __P((mb_t *, struct ifnet *)); -static int write_output __P((mb_t *, struct ifnet *)); -#endif - -#ifdef _KERNEL - -int fr_precheck(struct iphdr *ip, struct device *dev, int out, struct device **ifp) -{ - int hlen = ip->ihl << 2; - - return fr_check((ip_t *)ip, hlen, dev, out, (mb_t **)ifp); -} - - -int iplattach() -{ - char *defpass; - int s; - - if (fr_running || (fr_checkp == fr_precheck)) { - printk("IP Filter: already initialized\n"); - return EBUSY; - } - - fr_running = 1; - bzero((char *)frcache, sizeof(frcache)); - bzero((char *)nat_table, sizeof(nat_table)); - fr_savep = fr_checkp; - fr_checkp = fr_precheck; - -# ifdef IPFILTER_LOG - ipflog_init(); -# endif - if (fr_pass & FR_PASS) - defpass = "pass"; - else if (fr_pass & FR_BLOCK) - defpass = "block"; - else - defpass = "no-match -> block"; - - printk("IP Filter: initialized. Default = %s all, Logging = %s\n", - defpass, -# ifdef IPFILTER_LOG - "enabled"); -# else - "disabled"); -# endif - return 0; -} - - -/* - * Disable the filter by removing the hooks from the IP input/output - * stream. - */ -int ipldetach() -{ - int s, i = FR_INQUE|FR_OUTQUE; - - if (!fr_running) - { - printk("IP Filter: not initialized\n"); - return 0; - } - - fr_checkp = fr_savep; - i = frflush(IPL_LOGIPF, i); - fr_running = 0; - - ipfr_unload(); - ip_natunload(); - fr_stateunload(); - fr_authunload(); - - printk("IP Filter: unloaded\n"); - - return 0; -} -#endif /* _KERNEL */ - - -static int frzerostats(data) -caddr_t data; -{ - struct friostat fio; - int error; - - bcopy((char *)frstats, (char *)fio.f_st, - sizeof(struct filterstats) * 2); - fio.f_fin[0] = ipfilter[0][0]; - fio.f_fin[1] = ipfilter[0][1]; - fio.f_fout[0] = ipfilter[1][0]; - fio.f_fout[1] = ipfilter[1][1]; - fio.f_acctin[0] = ipacct[0][0]; - fio.f_acctin[1] = ipacct[0][1]; - fio.f_acctout[0] = ipacct[1][0]; - fio.f_acctout[1] = ipacct[1][1]; - fio.f_active = fr_active; - fio.f_froute[0] = ipl_frouteok[0]; - fio.f_froute[1] = ipl_frouteok[1]; - error = IWCOPYPTR((caddr_t)&fio, data, sizeof(fio)); - if (!error) - bzero((char *)frstats, sizeof(*frstats) * 2); - return error; -} - - -/* - * Filter ioctl interface. - */ -#if defined(_KERNEL) -int iplioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg) -{ - int s; - caddr_t data = (caddr_t)arg; - - int mode = file->f_mode; -#else -int iplioctl(dev_t dev, int cmd, caddr_t data, int mode) -{ -#endif - int error = 0, unit = 0, tmp; - -#ifdef _KERNEL - unit = GET_MINOR(inode->i_rdev); - if ((IPL_LOGMAX < unit) || (unit < 0)) - return ENXIO; -#endif - - if (unit == IPL_LOGNAT) { - error = nat_ioctl(data, cmd, mode); - return error; - } - if (unit == IPL_LOGSTATE) { - error = fr_state_ioctl(data, cmd, mode); - return error; - } - - switch (cmd) { - case FIONREAD : -#ifdef IPFILTER_LOG - error = IWCOPY((caddr_t)&iplused[IPL_LOGIPF], data, - sizeof(iplused[IPL_LOGIPF])); -#endif - break; -#if !defined(IPFILTER_LKM) && defined(_KERNEL) - case SIOCFRENB : - { - u_int enable; - - if (!(mode & FWRITE)) - error = EPERM; - else { - error = IRCOPY(data, (caddr_t)&enable, sizeof(enable)); - if (error) - break; - if (enable) - error = iplattach(); - else - error = ipldetach(); - } - break; - } -#endif - case SIOCSETFF : - if (!(mode & FWRITE)) - error = EPERM; - else - error = IRCOPY(data, (caddr_t)&fr_flags, - sizeof(fr_flags)); - break; - case SIOCGETFF : - error = IWCOPY((caddr_t)&fr_flags, data, sizeof(fr_flags)); - break; - case SIOCINAFR : - case SIOCRMAFR : - case SIOCADAFR : - case SIOCZRLST : - if (!(mode & FWRITE)) - error = EPERM; - else - error = frrequest(unit, cmd, data, fr_active); - break; - case SIOCINIFR : - case SIOCRMIFR : - case SIOCADIFR : - if (!(mode & FWRITE)) - error = EPERM; - else - error = frrequest(unit, cmd, data, 1 - fr_active); - break; - case SIOCSWAPA : - if (!(mode & FWRITE)) - error = EPERM; - else { - bzero((char *)frcache, sizeof(frcache[0]) * 2); - *(u_int *)data = fr_active; - fr_active = 1 - fr_active; - } - break; - case SIOCGETFS : - { - struct friostat fio; - - bcopy((char *)frstats, (char *)fio.f_st, - sizeof(struct filterstats) * 2); - fio.f_fin[0] = ipfilter[0][0]; - fio.f_fin[1] = ipfilter[0][1]; - fio.f_fout[0] = ipfilter[1][0]; - fio.f_fout[1] = ipfilter[1][1]; - fio.f_acctin[0] = ipacct[0][0]; - fio.f_acctin[1] = ipacct[0][1]; - fio.f_acctout[0] = ipacct[1][0]; - fio.f_acctout[1] = ipacct[1][1]; - fio.f_auth = ipauth; - fio.f_active = fr_active; - fio.f_froute[0] = ipl_frouteok[0]; - fio.f_froute[1] = ipl_frouteok[1]; - error = IWCOPYPTR((caddr_t)&fio, data, sizeof(fio)); - break; - } - case SIOCFRZST : - if (!(mode & FWRITE)) - error = EPERM; - else - error = frzerostats(data); - break; - case SIOCIPFFL : - if (!(mode & FWRITE)) - error = EPERM; - else { - error = IRCOPY(data, (caddr_t)&tmp, sizeof(tmp)); - if (!error) { - tmp = frflush(unit, tmp); - error = IWCOPY((caddr_t)&tmp, data, - sizeof(tmp)); - } - } - break; -#ifdef IPFILTER_LOG - case SIOCIPFFB : - if (!(mode & FWRITE)) - error = EPERM; - else - *(int *)data = ipflog_clear(unit); - break; -#endif /* IPFILTER_LOG */ - case SIOCGFRST : - error = IWCOPYPTR((caddr_t)ipfr_fragstats(), data, - sizeof(ipfrstat_t)); - break; - case SIOCFRSYN : - if (!(mode & FWRITE)) - error = EPERM; - else { -#if defined(_KERNEL) && defined(__sgi) - ipfsync(); -#endif - frsync(); - } - break; - default : - error = EINVAL; - break; - } - return error; -} - - -static void frsync() -{ -#ifdef _KERNEL - struct device *dev; - - for (dev = dev_base; dev; dev = dev->next) - ip_natsync(dev); -#endif -} - - -static int frrequest(unit, req, data, set) -int unit; -u_long req; -int set; -caddr_t data; -{ - register frentry_t *fp, *f, **fprev; - register frentry_t **ftail; - frentry_t frd; - frdest_t *fdp; - frgroup_t *fg = NULL; - int error = 0, in; - u_int group; - - fp = &frd; - error = IRCOPYPTR(data, (caddr_t)fp, sizeof(*fp)); - if (error) - return error; - - /* - * Check that the group number does exist and that if a head group - * has been specified, doesn't exist. - */ - if (fp->fr_grhead && - fr_findgroup((u_int)fp->fr_grhead, fp->fr_flags, unit, set, NULL)) - return EEXIST; - if (fp->fr_group && - !fr_findgroup((u_int)fp->fr_group, fp->fr_flags, unit, set, NULL)) - return ESRCH; - - in = (fp->fr_flags & FR_INQUE) ? 0 : 1; - - if (unit == IPL_LOGAUTH) - ftail = fprev = &ipauth; - else if (fp->fr_flags & FR_ACCOUNT) - ftail = fprev = &ipacct[in][set]; - else if (fp->fr_flags & (FR_OUTQUE|FR_INQUE)) - ftail = fprev = &ipfilter[in][set]; - else - return ESRCH; - - if ((group = fp->fr_group)) { - if (!(fg = fr_findgroup(group, fp->fr_flags, unit, set, NULL))) - return ESRCH; - ftail = fprev = fg->fg_start; - } - - bzero((char *)frcache, sizeof(frcache[0]) * 2); - - if (*fp->fr_ifname) { - fp->fr_ifa = GETUNIT(fp->fr_ifname, fp->fr_ip.fi_v); - if (!fp->fr_ifa) - fp->fr_ifa = (void *)-1; - } - - fdp = &fp->fr_dif; - fp->fr_flags &= ~FR_DUP; - if (*fdp->fd_ifname) { - fdp->fd_ifp = GETUNIT(fdp->fd_ifname, fp->fr_ip.fi_v); - if (!fdp->fd_ifp) - fdp->fd_ifp = (struct ifnet *)-1; - else - fp->fr_flags |= FR_DUP; - } - - fdp = &fp->fr_tif; - if (*fdp->fd_ifname) { - fdp->fd_ifp = GETUNIT(fdp->fd_ifname, fp->fr_ip.fi_v); - if (!fdp->fd_ifp) - fdp->fd_ifp = (struct ifnet *)-1; - } - - /* - * Look for a matching filter rule, but don't include the next or - * interface pointer in the comparison (fr_next, fr_ifa). - */ - for (; (f = *ftail); ftail = &f->fr_next) - if (bcmp((char *)&f->fr_ip, (char *)&fp->fr_ip, - FR_CMPSIZ) == 0) - break; - - /* - * If zero'ing statistics, copy current to caller and zero. - */ - if (req == SIOCZRLST) { - if (!f) - return ESRCH; - error = IWCOPYPTR((caddr_t)f, data, sizeof(*f)); - if (error) - return error; - f->fr_hits = 0; - f->fr_bytes = 0; - return 0; - } - - if (!f) { - if (req == SIOCINAFR || req == SIOCINIFR) { - ftail = fprev; - if (fp->fr_hits) { - while (--fp->fr_hits && (f = *ftail)) { - ftail = &f->fr_next; - } - } - } - f = NULL; - } - - if (req == SIOCRMAFR || req == SIOCRMIFR) { - if (!f) - error = ESRCH; - else { - if (f->fr_ref > 1) - return EBUSY; - if (fg && fg->fg_head) - fg->fg_head->fr_ref--; - if (unit == IPL_LOGAUTH) - return fr_auth_ioctl(data, mode, req, f, ftail); - if (f->fr_grhead) - fr_delgroup((u_int)f->fr_grhead, fp->fr_flags, - unit, set); - fixskip(fprev, f, -1); - *ftail = f->fr_next; - KFREE(f); - } - } else { - if (f) - error = EEXIST; - else { - if (unit == IPL_LOGAUTH) - return fr_auth_ioctl(data, mode, req, f, ftail); - KMALLOC(f, frentry_t *); - if (f != NULL) { - if (fg && fg->fg_head) - fg->fg_head->fr_ref++; - bcopy((char *)fp, (char *)f, sizeof(*f)); - f->fr_ref = 1; - f->fr_hits = 0; - f->fr_next = *ftail; - *ftail = f; - if (req == SIOCINIFR || req == SIOCINAFR) - fixskip(fprev, f, 1); - f->fr_grp = NULL; - if ((group = f->fr_grhead)) - fg = fr_addgroup(group, f, unit, set); - } else - error = ENOMEM; - } - } - return (error); -} - - -#ifdef _KERNEL -/* - * routines below for saving IP headers to buffer - */ -int iplopen(struct inode *inode, struct file *file) -{ - u_int min = GET_MINOR(inode->i_rdev); - - if (IPL_LOGMAX < min) - min = ENXIO; - else { - MOD_INC_USE_COUNT; - min = 0; - } - return min; -} - - -void iplclose(struct inode *inode, struct file *file) -{ - u_int min = GET_MINOR(inode->i_rdev); - - if (IPL_LOGMAX >= min) { - MOD_DEC_USE_COUNT; - } -} - -/* - * iplread/ipllog - * both of these must operate with at least splnet() lest they be - * called during packet processing and cause an inconsistancy to appear in - * the filter lists. - */ -int iplread(struct inode *inode, struct file *file, char *buf, int nbytes) -{ - struct uio uiob, *uio = &uiob; - - uio->uio_buf = buf; - uio->uio_resid = nbytes; -# ifdef IPFILTER_LOG - return ipflog_read(GET_MINOR(inode->i_rdev), uio); -# else - return ENXIO; -# endif -} - - -/* - * send_reset - this could conceivably be a call to tcp_respond(), but that - * requires a large amount of setting up and isn't any more efficient. - */ -int send_reset(ti, ifp) -struct tcpiphdr *ti; -struct ifnet *ifp; -{ - tcphdr_t *tcp; - int tlen = 0; - ip_t *ip; - mb_t *m; - - if (ti->ti_flags & TH_RST) - return -1; /* feedback loop */ - - m = alloc_skb(sizeof(tcpiphdr_t), GFP_ATOMIC); - if (m == NULL) - return -1; - - if (ti->ti_flags & TH_SYN) - tlen = 1; - - m->dev = ifp; - m->csum = 0; - ip = mtod(m, ip_t *); - m->h.iph = ip; - m->ip_hdr = NULL; - m->m_len = sizeof(tcpiphdr_t); - tcp = (tcphdr_t *)((char *)ip + sizeof(ip_t)); - bzero((char *)ip, sizeof(tcpiphdr_t)); - - ip->ip_v = IPVERSION; - ip->ip_hl = sizeof(ip_t) >> 2; - ip->ip_tos = ((ip_t *)ti)->ip_tos; - ip->ip_p = ((ip_t *)ti)->ip_p; - ip->ip_id = ((ip_t *)ti)->ip_id; - ip->ip_len = htons(sizeof(tcpiphdr_t)); - ip->ip_ttl = 127; - ip->ip_src.s_addr = ti->ti_dst.s_addr; - ip->ip_dst.s_addr = ti->ti_src.s_addr; - tcp->th_dport = ti->ti_sport; - tcp->th_sport = ti->ti_dport; - tcp->th_ack = htonl(ntohl(ti->ti_seq) + tlen); - tcp->th_off = sizeof(tcphdr_t) >> 2; - tcp->th_flags = TH_RST|TH_ACK; - - ip->ip_sum = 0; - ip->ip_sum = ipf_cksum((u_short *)ip, sizeof(ip_t)); - tcp->th_sum = fr_tcpsum(m, ip, tcp); - return ip_forward(m, NULL, IPFWD_NOTTLDEC, ip->ip_dst.s_addr); -} - - -size_t mbufchainlen(m0) -register mb_t *m0; -{ - register size_t len = 0; - - for (; m0; m0 = m0->m_next) - len += m0->m_len; - return len; -} - - -void ipfr_fastroute(m0, fin, fdp) -mb_t *m0; -fr_info_t *fin; -frdest_t *fdp; -{ -#if notyet - register ip_t *ip, *mhip; - register mb_t *m = m0; - register struct route *ro; - struct ifnet *ifp = fdp->fd_ifp; - int len, off, error = 0; - int hlen = fin->fin_hlen; - struct route iproute; - struct sockaddr_in *dst; - - ip = mtod(m0, ip_t *); - /* - * Route packet. - */ - ro = &iproute; - bzero((caddr_t)ro, sizeof (*ro)); - dst = (struct sockaddr_in *)&ro->ro_dst; - dst->sin_family = AF_INET; - dst->sin_addr = fdp->fd_ip.s_addr ? fdp->fd_ip : ip->ip_dst; - /* - * XXX -allocate route here - */ - if (!ifp) { - if (!(fin->fin_fr->fr_flags & FR_FASTROUTE)) { - error = -2; - goto bad; - } - if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) { - if (in_localaddr(ip->ip_dst)) - error = EHOSTUNREACH; - else - error = ENETUNREACH; - goto bad; - } - if (ro->ro_rt->rt_flags & RTF_GATEWAY) - dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway; - } - ro->ro_rt->rt_use++; - - /* - * For input packets which are being "fastrouted", they won't - * go back through output filtering and miss their chance to get - * NAT'd. - */ - (void) ip_natout(ip, hlen, fin); - if (fin->fin_out) - ip->ip_sum = 0; - /* - * If small enough for interface, can just send directly. - */ - if (ip->ip_len <= ifp->if_mtu) { -# ifndef sparc - ip->ip_id = htons(ip->ip_id); - ip->ip_len = htons(ip->ip_len); - ip->ip_off = htons(ip->ip_off); -# endif - if (!ip->ip_sum) - ip->ip_sum = in_cksum(m, hlen); - error = (*ifp->hard_start_xmit)(m, ifp, m); - goto done; - } - /* - * Too large for interface; fragment if possible. - * Must be able to put at least 8 bytes per fragment. - */ - if (ip->ip_off & IP_DF) { - error = EMSGSIZE; - goto bad; - } - len = (ifp->if_mtu - hlen) &~ 7; - if (len < 8) { - error = EMSGSIZE; - goto bad; - } - - { - int mhlen, firstlen = len; - mb_t **mnext = &m->m_act; - - /* - * Loop through length of segment after first fragment, - * make new header and copy data of each part and link onto chain. - */ - m0 = m; - mhlen = sizeof (struct ip); - for (off = hlen + len; off < ip->ip_len; off += len) { - MGET(m, M_DONTWAIT, MT_HEADER); - if (m == 0) { - error = ENOBUFS; - goto bad; - } - m->m_data += max_linkhdr; - mhip = mtod(m, struct ip *); - bcopy((char *)ip, (char *)mhip, sizeof(*ip)); - if (hlen > sizeof (struct ip)) { - mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); - mhip->ip_hl = mhlen >> 2; - } - m->m_len = mhlen; - mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF); - if (ip->ip_off & IP_MF) - mhip->ip_off |= IP_MF; - if (off + len >= ip->ip_len) - len = ip->ip_len - off; - else - mhip->ip_off |= IP_MF; - mhip->ip_len = htons((u_short)(len + mhlen)); - m->m_next = m_copy(m0, off, len); - if (m->m_next == 0) { - error = ENOBUFS; /* ??? */ - goto sendorfree; - } -# ifndef sparc - mhip->ip_off = htons((u_short)mhip->ip_off); -# endif - mhip->ip_sum = 0; - mhip->ip_sum = in_cksum(m, mhlen); - *mnext = m; - mnext = &m->m_act; - } - /* - * Update first fragment by trimming what's been copied out - * and updating header, then send each fragment (in order). - */ - m_adj(m0, hlen + firstlen - ip->ip_len); - ip->ip_len = htons((u_short)(hlen + firstlen)); - ip->ip_off = htons((u_short)(ip->ip_off | IP_MF)); - ip->ip_sum = 0; - ip->ip_sum = in_cksum(m0, hlen); -sendorfree: - for (m = m0; m; m = m0) { - m0 = m->m_act; - m->m_act = 0; - if (error == 0) - error = (*ifp->if_output)(ifp, m, - (struct sockaddr *)dst); - else - m_freem(m); - } - } -done: - if (!error) - ipl_frouteok[0]++; - else - ipl_frouteok[1]++; - - if (ro->ro_rt) { - RTFREE(ro->ro_rt); - } - return; -bad: - m_freem(m); - goto done; -# endif -} - - -/* - * Fake BSD uiomove() call. - */ -int uiomove(caddr_t src, size_t ssize, int rw, struct uio *uio) -{ - int error; - size_t mv = MIN(ssize, uio->uio_resid); - - if (rw == UIO_READ) { - error = IWCOPY(src, (caddr_t)uio->uio_buf, mv); - } else if (rw == UIO_WRITE) { - error = IRCOPY((caddr_t)uio->uio_buf, src, mv); - } else - error = EINVAL; - if (!error) { - uio->uio_resid -= mv; - uio->uio_buf += mv; - } - return error; -} - -# ifdef IPFILTER_LKM -# ifndef IPL_MAJOR -# define IPL_MAJOR 95 -# endif - -# ifndef IPL_NAME -# define IPL_NAME "/dev/ipl" -# endif - -static struct file_operations ipl_fops = { - NULL, /* lseek */ - iplread, /* read */ - NULL, /* write */ - NULL, /* readdir */ - NULL, /* select */ - iplioctl, /* ioctl */ - NULL, /* mmap */ - iplopen, /* open */ - iplclose, /* release */ - NULL, /* fsync */ - NULL, /* fasync */ - NULL, /* check_media_change */ - NULL, /* revalidate */ -}; - - -int init_module(void) -{ - int error = 0, major; - - if (register_chrdev(IPL_MAJOR, "ipf", &ipl_fops)) { - printk("ipf: unable to get major number: %d\n", IPL_MAJOR); - return -EIO; - } - - error = iplattach(); - if (!error) - register_symtab(0); - return -error; -} - -void cleanup_module(void) -{ - unregister_chrdev(IPL_MAJOR, "ipf"); - (void) ipldetach(); -} -# endif /* IPFILTER_LKM */ -#else /* #ifdef _KERNEL */ - - -static int no_output __P((mb_t *m, struct ifnet *ifp)) -{ - return 0; -} - - -static int write_output __P((mb_t *m, struct ifnet *ifp)) -{ - FILE *fp; - char fname[32]; - ip_t *ip; - - ip = mtod(m, ip_t *); - sprintf(fname, "/tmp/%s", ifp->name); - if ((fp = fopen(fname, "a"))) { - fwrite((char *)ip, ntohs(ip->ip_len), 1, fp); - fclose(fp); - } - return 0; -} - - -struct ifnet *get_unit(name, v) -char *name; -int v; -{ - struct ifnet *ifp, **ifa; - char ifname[32], *s; - - for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) { - (void) sprintf(ifname, "%s", ifp->name); - if (!strcmp(name, ifname)) - return ifp; - } - - if (!ifneta) { - ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2); - ifneta[1] = NULL; - ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp)); - nifs = 1; - } else { - nifs++; - ifneta = (struct ifnet **)realloc(ifneta, - (nifs + 1) * sizeof(*ifa)); - ifneta[nifs] = NULL; - ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp)); - } - ifp = ifneta[nifs - 1]; - - for (s = name; *s && !isdigit(*s); s++) - ; - if (*s && isdigit(*s)) { - ifp->name = (char *)malloc(s - name + 1); - strncpy(ifp->name, name, s - name); - ifp->name[s - name] = '\0'; - } else { - ifp->name = strdup(name); - } - ifp->hard_start_xmit = no_output; - return ifp; -} - - - -void init_ifp() -{ - FILE *fp; - struct ifnet *ifp, **ifa; - char fname[32]; - - for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) { - ifp->hard_start_xmit = write_output; - sprintf(fname, "/tmp/%s", ifp->name); - if ((fp = fopen(fname, "w"))) - fclose(fp); - } -} - - -void ipfr_fastroute(ip, fin, fdp) -ip_t *ip; -fr_info_t *fin; -frdest_t *fdp; -{ - struct ifnet *ifp = fdp->fd_ifp; - - if (!ifp) - return; /* no routing table out here */ - - ip->ip_len = htons((u_short)ip->ip_len); - ip->ip_off = htons((u_short)(ip->ip_off | IP_MF)); - ip->ip_sum = 0; - (*ifp->hard_start_xmit)((mb_t *)ip, ifp); -} - - -int ipllog __P((void)) -{ - verbose("l"); - return 0; -} - - -int send_reset(ip, ifp) -ip_t *ip; -struct ifnet *ifp; -{ - verbose("- TCP RST sent\n"); - return 0; -} - - -int icmp_error(ip, ifp) -ip_t *ip; -struct ifnet *ifp; -{ - verbose("- TCP RST sent\n"); - return 0; -} -#endif /* _KERNEL */ diff --git a/ip_log.c b/ip_log.c index 1243081979493..49119bae45c49 100644 --- a/ip_log.c +++ b/ip_log.c @@ -1,11 +1,9 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1997-2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * Id: ip_log.c,v 2.75.2.6 2004/10/16 07:59:27 darrenr Exp + * $Id$ */ #include <sys/param.h> #if defined(KERNEL) || defined(_KERNEL) @@ -14,18 +12,8 @@ # define KERNEL 1 # define _KERNEL 1 #endif -#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ - defined(_KERNEL) -# include "opt_ipfilter_log.h" -#endif -#if defined(__FreeBSD__) && !defined(IPFILTER_LKM) -# if defined(_KERNEL) -# if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) -# include "opt_ipfilter.h" -# endif -# else -# include <osreldate.h> -# endif +#if defined(__FreeBSD__) && !defined(_KERNEL) +# include <osreldate.h> #endif #ifndef SOLARIS # define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) @@ -47,7 +35,8 @@ struct file; # undef _KERNEL # undef KERNEL #endif -#if __FreeBSD_version >= 220000 && defined(_KERNEL) +#if (defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)) && \ + defined(_KERNEL) # include <sys/fcntl.h> # include <sys/filio.h> #else @@ -56,17 +45,23 @@ struct file; #include <sys/time.h> #if defined(_KERNEL) # include <sys/systm.h> -# if defined(NetBSD) && (__NetBSD_Version__ >= 104000000) +# if (defined(NetBSD) && (__NetBSD_Version__ >= 104000000)) # include <sys/proc.h> # endif #endif /* _KERNEL */ #if !SOLARIS && !defined(__hpux) && !defined(linux) -# if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000) +# if (defined(NetBSD) && (NetBSD > 199609)) || \ + (defined(OpenBSD) && (OpenBSD > 199603)) || \ + (defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)) # include <sys/dirent.h> # else # include <sys/dir.h> # endif # include <sys/mbuf.h> +# include <sys/select.h> +# if __FreeBSD_version >= 500000 +# include <sys/selinfo.h> +# endif #else # if !defined(__hpux) && defined(_KERNEL) # include <sys/filio.h> @@ -92,7 +87,6 @@ struct file; #if __FreeBSD_version >= 300000 # include <net/if_var.h> #endif -#include <net/route.h> #include <netinet/in.h> #ifdef __sgi # include <sys/ddi.h> @@ -136,100 +130,240 @@ struct file; # include <machine/sys/user.h> # include <sys/kthread_iface.h> # define READ_COLLISION 0x001 - -iplog_select_t iplog_ss[IPL_LOGMAX+1]; - extern int selwait; # endif /* IPL_SELECT */ +typedef struct ipf_log_softc_s { + ipfmutex_t ipl_mutex[IPL_LOGSIZE]; +# if SOLARIS && defined(_KERNEL) + kcondvar_t ipl_wait[IPL_LOGSIZE]; +# endif # if defined(linux) && defined(_KERNEL) -wait_queue_head_t iplh_linux[IPL_LOGSIZE]; + wait_queue_head_t iplh_linux[IPL_LOGSIZE]; # endif -# if SOLARIS -extern kcondvar_t iplwait; +# if defined(__hpux) && defined(_KERNEL) + iplog_select_t ipl_ss[IPL_LOGSIZE]; # endif + iplog_t **iplh[IPL_LOGSIZE]; + iplog_t *iplt[IPL_LOGSIZE]; + iplog_t *ipll[IPL_LOGSIZE]; + u_long ipl_logfail[IPL_LOGSIZE]; + u_long ipl_logok[IPL_LOGSIZE]; + fr_info_t ipl_crc[IPL_LOGSIZE]; + u_32_t ipl_counter[IPL_LOGSIZE]; + int ipl_suppress; + int ipl_logall; + int ipl_log_init; + int ipl_logsize; + int ipl_used[IPL_LOGSIZE]; + int ipl_magic[IPL_LOGSIZE]; + ipftuneable_t *ipf_log_tune; + int ipl_readers[IPL_LOGSIZE]; +} ipf_log_softc_t; + +static int magic[IPL_LOGSIZE] = { IPL_MAGIC, IPL_MAGIC_NAT, IPL_MAGIC_STATE, + IPL_MAGIC, IPL_MAGIC, IPL_MAGIC, + IPL_MAGIC, IPL_MAGIC }; + +static ipftuneable_t ipf_log_tuneables[] = { + /* log */ + { { (void *)offsetof(ipf_log_softc_t, ipl_suppress) }, + "log_suppress", 0, 1, + stsizeof(ipf_log_softc_t, ipl_suppress), + 0, NULL, NULL }, + { { (void *)offsetof(ipf_log_softc_t, ipl_logall) }, + "log_all", 0, 1, + stsizeof(ipf_log_softc_t, ipl_logall), + 0, NULL, NULL }, + { { (void *)offsetof(ipf_log_softc_t, ipl_logsize) }, + "log_size", 0, 0x80000, + stsizeof(ipf_log_softc_t, ipl_logsize), + 0, NULL, NULL }, + { { NULL }, NULL, 0, 0, + 0, + 0, NULL, NULL } +}; + + +int +ipf_log_main_load() +{ + return 0; +} + + +int +ipf_log_main_unload() +{ + return 0; +} + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_log_soft_create */ +/* Returns: void * - NULL = failure, else pointer to log context data */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* */ +/* Initialise log buffers & pointers. Also iniialised the CRC to a local */ +/* secret for use in calculating the "last log checksum". */ +/* ------------------------------------------------------------------------ */ +void * +ipf_log_soft_create(softc) + ipf_main_softc_t *softc; +{ + ipf_log_softc_t *softl; -iplog_t **iplh[IPL_LOGSIZE], *iplt[IPL_LOGSIZE], *ipll[IPL_LOGSIZE]; -int iplused[IPL_LOGSIZE]; -static fr_info_t iplcrc[IPL_LOGSIZE]; -int ipl_suppress = 1; -int ipl_buffer_sz; -int ipl_logmax = IPL_LOGMAX; -int ipl_logall = 0; -int ipl_log_init = 0; -int ipl_logsize = IPFILTER_LOGSIZE; -int ipl_magic[IPL_LOGSIZE] = { IPL_MAGIC, IPL_MAGIC_NAT, IPL_MAGIC_STATE, - IPL_MAGIC, IPL_MAGIC, IPL_MAGIC, - IPL_MAGIC, IPL_MAGIC }; + KMALLOC(softl, ipf_log_softc_t *); + if (softl == NULL) + return NULL; + bzero((char *)softl, sizeof(*softl)); + bcopy((char *)magic, (char *)softl->ipl_magic, sizeof(magic)); + + softl->ipf_log_tune = ipf_tune_array_copy(softl, + sizeof(ipf_log_tuneables), + ipf_log_tuneables); + if (softl->ipf_log_tune == NULL) { + ipf_log_soft_destroy(softc, softl); + return NULL; + } + if (ipf_tune_array_link(softc, softl->ipf_log_tune) == -1) { + ipf_log_soft_destroy(softc, softl); + return NULL; + } + + softl->ipl_suppress = 1; + softl->ipl_logall = 0; + softl->ipl_log_init = 0; + softl->ipl_logsize = IPFILTER_LOGSIZE; + + return softl; +} /* ------------------------------------------------------------------------ */ -/* Function: fr_loginit */ +/* Function: ipf_log_soft_init */ /* Returns: int - 0 == success (always returned) */ -/* Parameters: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ /* */ /* Initialise log buffers & pointers. Also iniialised the CRC to a local */ /* secret for use in calculating the "last log checksum". */ /* ------------------------------------------------------------------------ */ -int fr_loginit() +int +ipf_log_soft_init(softc, arg) + ipf_main_softc_t *softc; + void *arg; { - int i; + ipf_log_softc_t *softl = arg; + int i; for (i = IPL_LOGMAX; i >= 0; i--) { - iplt[i] = NULL; - ipll[i] = NULL; - iplh[i] = &iplt[i]; - iplused[i] = 0; - bzero((char *)&iplcrc[i], sizeof(iplcrc[i])); + softl->iplt[i] = NULL; + softl->ipll[i] = NULL; + softl->iplh[i] = &softl->iplt[i]; + bzero((char *)&softl->ipl_crc[i], sizeof(softl->ipl_crc[i])); # ifdef IPL_SELECT - iplog_ss[i].read_waiter = 0; - iplog_ss[i].state = 0; + softl->iplog_ss[i].read_waiter = 0; + softl->iplog_ss[i].state = 0; # endif # if defined(linux) && defined(_KERNEL) - init_waitqueue_head(iplh_linux + i); + init_waitqueue_head(softl->iplh_linux + i); # endif - } - # if SOLARIS && defined(_KERNEL) - cv_init(&iplwait, "ipl condvar", CV_DRIVER, NULL); + cv_init(&softl->ipl_wait[i], NULL, CV_DRIVER, NULL); # endif - MUTEX_INIT(&ipl_mutex, "ipf log mutex"); + MUTEX_INIT(&softl->ipl_mutex[i], "ipf log mutex"); + } - ipl_log_init = 1; + + softl->ipl_log_init = 1; return 0; } /* ------------------------------------------------------------------------ */ -/* Function: fr_logunload */ -/* Returns: Nil */ -/* Parameters: Nil */ +/* Function: ipf_log_soft_fini */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to log context structure */ /* */ /* Clean up any log data that has accumulated without being read. */ /* ------------------------------------------------------------------------ */ -void fr_logunload() +int +ipf_log_soft_fini(softc, arg) + ipf_main_softc_t *softc; + void *arg; { + ipf_log_softc_t *softl = arg; int i; - if (ipl_log_init == 0) - return; + if (softl->ipl_log_init == 0) + return 0; + + softl->ipl_log_init = 0; + + for (i = IPL_LOGMAX; i >= 0; i--) { + (void) ipf_log_clear(softc, i); + + /* + * This is a busy-wait loop so as to avoid yet another lock + * to wait on. + */ + MUTEX_ENTER(&softl->ipl_mutex[i]); + while (softl->ipl_readers[i] > 0) { +# if SOLARIS && defined(_KERNEL) + cv_broadcast(&softl->ipl_wait[i]); + MUTEX_EXIT(&softl->ipl_mutex[i]); + delay(100); + pollwakeup(&softc->ipf_poll_head[i], POLLRDNORM); +# else + MUTEX_EXIT(&softl->ipl_mutex[i]); + WAKEUP(softl->iplh, i); + POLLWAKEUP(i); +# endif + MUTEX_ENTER(&softl->ipl_mutex[i]); + } + MUTEX_EXIT(&softl->ipl_mutex[i]); + } + + return 0; +} - for (i = IPL_LOGMAX; i >= 0; i--) - (void) ipflog_clear(i); +/* ------------------------------------------------------------------------ */ +/* Function: ipf_log_soft_destroy */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to log context structure */ +/* */ +/* When this function is called, it is expected that there are no longer */ +/* any threads active in the reading code path or the logging code path. */ +/* ------------------------------------------------------------------------ */ +void +ipf_log_soft_destroy(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_log_softc_t *softl = arg; + int i; + + for (i = IPL_LOGMAX; i >= 0; i--) { # if SOLARIS && defined(_KERNEL) - cv_destroy(&iplwait); + cv_destroy(&softl->ipl_wait[i]); # endif - MUTEX_DESTROY(&ipl_mutex); + MUTEX_DESTROY(&softl->ipl_mutex[i]); + } + + if (softl->ipf_log_tune != NULL) { + ipf_tune_array_unlink(softc, softl->ipf_log_tune); + KFREES(softl->ipf_log_tune, sizeof(ipf_log_tuneables)); + softl->ipf_log_tune = NULL; + } - ipl_log_init = 0; + KFREE(softl); } /* ------------------------------------------------------------------------ */ -/* Function: ipflog */ -/* Returns: int - 0 == success, -1 == failure */ +/* Function: ipf_log_pkt */ +/* Returns: int - 0 == success, -1 == failure */ /* Parameters: fin(I) - pointer to packet information */ /* flags(I) - flags from filter rules */ /* */ @@ -239,10 +373,13 @@ void fr_logunload() /* how much data to copy into the log, including part of the data body if */ /* requested. */ /* ------------------------------------------------------------------------ */ -int ipflog(fin, flags) -fr_info_t *fin; -u_int flags; +int +ipf_log_pkt(fin, flags) + fr_info_t *fin; + u_int flags; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_log_softc_t *softl = softc->ipf_log_soft; register size_t hlen; int types[2], mlen; size_t sizes[2]; @@ -250,16 +387,20 @@ u_int flags; ipflog_t ipfl; u_char p; mb_t *m; -# if (SOLARIS || defined(__hpux)) && defined(_KERNEL) +# if (SOLARIS || defined(__hpux)) && defined(_KERNEL) && !defined(FW_HOOKS) qif_t *ifp; # else struct ifnet *ifp; # endif /* SOLARIS || __hpux */ - ipfl.fl_nattag.ipt_num[0] = 0; m = fin->fin_m; + if (m == NULL) + return -1; + + ipfl.fl_nattag.ipt_num[0] = 0; ifp = fin->fin_ifp; - hlen = fin->fin_hlen; + hlen = (char *)fin->fin_dp - (char *)fin->fin_ip; + /* * calculate header size. */ @@ -273,7 +414,7 @@ u_int flags; struct icmp *icmp; icmp = (struct icmp *)fin->fin_dp; - + /* * For ICMP, if the packet is an error packet, also * include the information about the packet which @@ -321,13 +462,14 @@ u_int flags; * currently associated. */ # if (SOLARIS || defined(__hpux)) && defined(_KERNEL) +# if !defined(FW_HOOKS) ipfl.fl_unit = (u_int)ifp->qf_ppa; - COPYIFNAME(ifp, ipfl.fl_ifname); +# endif + COPYIFNAME(fin->fin_v, ifp, ipfl.fl_ifname); # else -# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ - (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) - COPYIFNAME(ifp, ipfl.fl_ifname); +# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ + OPENBSD_GE_REV(199603) || defined(linux) || FREEBSD_GE_REV(501113) + COPYIFNAME(fin->fin_v, ifp, ipfl.fl_ifname); # else ipfl.fl_unit = (u_int)ifp->if_unit; # if defined(_KERNEL) @@ -342,7 +484,7 @@ u_int flags; # endif # endif /* __hpux || SOLARIS */ mlen = fin->fin_plen - hlen; - if (!ipl_logall) { + if (!softl->ipl_logall) { mlen = (flags & FR_LOGBODY) ? MIN(mlen, 128) : 0; } else if ((flags & FR_LOGBODY) == 0) { mlen = 0; @@ -364,8 +506,10 @@ u_int flags; bcopy(fin->fin_nattag, (void *)&ipfl.fl_nattag, sizeof(ipfl.fl_nattag)); ipfl.fl_flags = flags; + ipfl.fl_breason = (fin->fin_reason & 0xff); ipfl.fl_dir = fin->fin_out; ipfl.fl_lflags = fin->fin_flx; + ipfl.fl_family = fin->fin_family; ptrs[0] = (void *)&ipfl; sizes[0] = sizeof(ipfl); types[0] = 0; @@ -387,14 +531,15 @@ u_int flags; sizes[1] = hlen + mlen; types[1] = 1; # endif /* MENTAT */ - return ipllog(IPL_LOGIPF, fin, ptrs, sizes, types, 2); + return ipf_log_items(softc, IPL_LOGIPF, fin, ptrs, sizes, types, 2); } /* ------------------------------------------------------------------------ */ -/* Function: ipllog */ -/* Returns: int - 0 == success, -1 == failure */ -/* Parameters: dev(I) - device that owns this log record */ +/* Function: ipf_log_items */ +/* Returns: int - 0 == success, -1 == failure */ +/* Parameters: softc(I) - pointer to main soft context */ +/* unit(I) - device we are reading from */ /* fin(I) - pointer to packet information */ /* items(I) - array of pointers to log data */ /* itemsz(I) - array of size of valid memory pointed to */ @@ -405,41 +550,21 @@ u_int flags; /* miscellaneous packet information, as well as packet data, for reading */ /* from the log device. */ /* ------------------------------------------------------------------------ */ -int ipllog(dev, fin, items, itemsz, types, cnt) -int dev; -fr_info_t *fin; -void **items; -size_t *itemsz; -int *types, cnt; +int +ipf_log_items(softc, unit, fin, items, itemsz, types, cnt) + ipf_main_softc_t *softc; + int unit; + fr_info_t *fin; + void **items; + size_t *itemsz; + int *types, cnt; { + ipf_log_softc_t *softl = softc->ipf_log_soft; caddr_t buf, ptr; iplog_t *ipl; size_t len; int i; -# if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL) - int s; -# endif - - /* - * Check to see if this log record has a CRC which matches the last - * record logged. If it does, just up the count on the previous one - * rather than create a new one. - */ - if (ipl_suppress) { - MUTEX_ENTER(&ipl_mutex); - if ((fin != NULL) && (fin->fin_off == 0)) { - if ((ipll[dev] != NULL) && - bcmp((char *)fin, (char *)&iplcrc[dev], - FI_LCSIZE) == 0) { - ipll[dev]->ipl_count++; - MUTEX_EXIT(&ipl_mutex); - return 0; - } - bcopy((char *)fin, (char *)&iplcrc[dev], FI_LCSIZE); - } else - bzero((char *)&iplcrc[dev], FI_CSIZE); - MUTEX_EXIT(&ipl_mutex); - } + SPL_INT(s); /* * Get the total amount of data to be logged. @@ -447,32 +572,29 @@ int *types, cnt; for (i = 0, len = sizeof(iplog_t); i < cnt; i++) len += itemsz[i]; + SPL_NET(s); + MUTEX_ENTER(&softl->ipl_mutex[unit]); + softl->ipl_counter[unit]++; /* * check that we have space to record this information and can * allocate that much. */ - KMALLOCS(buf, caddr_t, len); - if (buf == NULL) - return -1; - SPL_NET(s); - MUTEX_ENTER(&ipl_mutex); - if ((iplused[dev] + len) > ipl_logsize) { - MUTEX_EXIT(&ipl_mutex); - SPL_X(s); - KFREES(buf, len); + if ((softl->ipl_used[unit] + len) > softl->ipl_logsize) { + softl->ipl_logfail[unit]++; + MUTEX_EXIT(&softl->ipl_mutex[unit]); return -1; } - iplused[dev] += len; - MUTEX_EXIT(&ipl_mutex); - SPL_X(s); - /* - * advance the log pointer to the next empty record and deduct the - * amount of space we're going to use. - */ + KMALLOCS(buf, caddr_t, len); + if (buf == NULL) { + softl->ipl_logfail[unit]++; + MUTEX_EXIT(&softl->ipl_mutex[unit]); + return -1; + } ipl = (iplog_t *)buf; - ipl->ipl_magic = ipl_magic[dev]; + ipl->ipl_magic = softl->ipl_magic[unit]; ipl->ipl_count = 1; + ipl->ipl_seqnum = softl->ipl_counter[unit]; ipl->ipl_next = NULL; ipl->ipl_dsize = len; #ifdef _KERNEL @@ -494,36 +616,67 @@ int *types, cnt; } ptr += itemsz[i]; } - SPL_NET(s); - MUTEX_ENTER(&ipl_mutex); - ipll[dev] = ipl; - *iplh[dev] = ipl; - iplh[dev] = &ipl->ipl_next; + /* + * Check to see if this log record has a CRC which matches the last + * record logged. If it does, just up the count on the previous one + * rather than create a new one. + */ + if (softl->ipl_suppress) { + if ((fin != NULL) && (fin->fin_off == 0)) { + if ((softl->ipll[unit] != NULL) && + (fin->fin_crc == softl->ipl_crc[unit].fin_crc) && + bcmp((char *)fin, (char *)&softl->ipl_crc[unit], + FI_LCSIZE) == 0) { + softl->ipll[unit]->ipl_count++; + MUTEX_EXIT(&softl->ipl_mutex[unit]); + SPL_X(s); + KFREES(buf, len); + return 0; + } + bcopy((char *)fin, (char *)&softl->ipl_crc[unit], + FI_LCSIZE); + softl->ipl_crc[unit].fin_crc = fin->fin_crc; + } else + bzero((char *)&softl->ipl_crc[unit], FI_CSIZE); + } + + /* + * advance the log pointer to the next empty record and deduct the + * amount of space we're going to use. + */ + softl->ipl_logok[unit]++; + softl->ipll[unit] = ipl; + *softl->iplh[unit] = ipl; + softl->iplh[unit] = &ipl->ipl_next; + softl->ipl_used[unit] += len; /* * Now that the log record has been completed and added to the queue, * wake up any listeners who may want to read it. */ # if SOLARIS && defined(_KERNEL) - cv_signal(&iplwait); - MUTEX_EXIT(&ipl_mutex); + cv_signal(&softl->ipl_wait[unit]); + MUTEX_EXIT(&softl->ipl_mutex[unit]); + pollwakeup(&softc->ipf_poll_head[unit], POLLRDNORM); # else - MUTEX_EXIT(&ipl_mutex); - WAKEUP(iplh,dev); + MUTEX_EXIT(&softl->ipl_mutex[unit]); + WAKEUP(softl->iplh, unit); + POLLWAKEUP(unit); # endif SPL_X(s); # ifdef IPL_SELECT - iplog_input_ready(dev); + iplog_input_ready(unit); # endif return 0; } /* ------------------------------------------------------------------------ */ -/* Function: ipflog_read */ -/* Returns: int - 0 == success, else error value. */ -/* Parameters: unit(I) - device we are reading from */ -/* uio(O) - pointer to information about where to store data */ +/* Function: ipf_log_read */ +/* Returns: int - 0 == success, else error value. */ +/* Parameters: softc(I) - pointer to main soft context */ +/* unit(I) - device we are reading from */ +/* uio(O) - pointer to information about where to store data */ /* */ /* Called to handle a read on an IPFilter device. Returns only complete */ /* log messages - will not partially copy a log record out to userland. */ @@ -531,40 +684,58 @@ int *types, cnt; /* NOTE: This function will block and wait for a signal to return data if */ /* there is none present. Asynchronous I/O is not implemented. */ /* ------------------------------------------------------------------------ */ -int ipflog_read(unit, uio) -minor_t unit; -struct uio *uio; +int +ipf_log_read(softc, unit, uio) + ipf_main_softc_t *softc; + minor_t unit; + struct uio *uio; { + ipf_log_softc_t *softl = softc->ipf_log_soft; size_t dlen, copied; int error = 0; iplog_t *ipl; -# if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL) - int s; -# endif + SPL_INT(s); + + if (softl->ipl_log_init == 0) { + IPFERROR(40007); + return 0; + } /* * Sanity checks. Make sure the minor # is valid and we're copying * a valid chunk of data. */ - if (IPL_LOGMAX < unit) + if (IPL_LOGMAX < unit) { + IPFERROR(40001); return ENXIO; + } if (uio->uio_resid == 0) return 0; - if ((uio->uio_resid < sizeof(iplog_t)) || - (uio->uio_resid > ipl_logsize)) + + if (uio->uio_resid < sizeof(iplog_t)) { + IPFERROR(40002); + return EINVAL; + } + if (uio->uio_resid > softl->ipl_logsize) { + IPFERROR(40005); return EINVAL; + } /* * Lock the log so we can snapshot the variables. Wait for a signal * if the log is empty. */ SPL_NET(s); - MUTEX_ENTER(&ipl_mutex); + MUTEX_ENTER(&softl->ipl_mutex[unit]); + softl->ipl_readers[unit]++; - while (iplt[unit] == NULL) { + while (softl->ipl_log_init == 1 && softl->iplt[unit] == NULL) { # if SOLARIS && defined(_KERNEL) - if (!cv_wait_sig(&iplwait, &ipl_mutex.ipf_lk)) { - MUTEX_EXIT(&ipl_mutex); + if (!cv_wait_sig(&softl->ipl_wait[unit], + &softl->ipl_mutex[unit].ipf_lk)) { + softl->ipl_readers[unit]--; + MUTEX_EXIT(&softl->ipl_mutex[unit]); + IPFERROR(40003); return EINTR; } # else @@ -574,101 +745,206 @@ struct uio *uio; # ifdef IPL_SELECT if (uio->uio_fpflags & (FNBLOCK|FNDELAY)) { /* this is no blocking system call */ - MUTEX_EXIT(&ipl_mutex); + softl->ipl_readers[unit]--; + MUTEX_EXIT(&softl->ipl_mutex[unit]); return 0; } # endif - MUTEX_EXIT(&ipl_mutex); - l = get_sleep_lock(&iplh[unit]); - error = sleep(&iplh[unit], PZERO+1); + MUTEX_EXIT(&softl->ipl_mutex[unit]); + l = get_sleep_lock(&softl->iplh[unit]); + error = sleep(&softl->iplh[unit], PZERO+1); spinunlock(l); # else # if defined(__osf__) && defined(_KERNEL) - error = mpsleep(&iplh[unit], PSUSP|PCATCH, "iplread", 0, - &ipl_mutex, MS_LOCK_SIMPLE); + error = mpsleep(&softl->iplh[unit], PSUSP|PCATCH, "ipfread", 0, + &softl->ipl_mutex, MS_LOCK_SIMPLE); # else - MUTEX_EXIT(&ipl_mutex); + MUTEX_EXIT(&softl->ipl_mutex[unit]); SPL_X(s); - error = SLEEP(unit + iplh, "ipl sleep"); + error = SLEEP(unit + softl->iplh, "ipl sleep"); # endif /* __osf__ */ # endif /* __hpux */ - if (error) - return error; SPL_NET(s); - MUTEX_ENTER(&ipl_mutex); + MUTEX_ENTER(&softl->ipl_mutex[unit]); + if (error) { + softl->ipl_readers[unit]--; + MUTEX_EXIT(&softl->ipl_mutex[unit]); + IPFERROR(40004); + return error; + } # endif /* SOLARIS */ } + if (softl->ipl_log_init != 1) { + softl->ipl_readers[unit]--; + MUTEX_EXIT(&softl->ipl_mutex[unit]); + IPFERROR(40008); + return EIO; + } -# if (BSD >= 199101) || defined(__FreeBSD__) || defined(__osf__) +# if (defined(BSD) && (BSD >= 199101)) || defined(__FreeBSD__) || \ + defined(__osf__) uio->uio_rw = UIO_READ; # endif - for (copied = 0; (ipl = iplt[unit]) != NULL; copied += dlen) { + for (copied = 0; (ipl = softl->iplt[unit]) != NULL; copied += dlen) { dlen = ipl->ipl_dsize; if (dlen > uio->uio_resid) break; /* * Don't hold the mutex over the uiomove call. */ - iplt[unit] = ipl->ipl_next; - iplused[unit] -= dlen; - MUTEX_EXIT(&ipl_mutex); + softl->iplt[unit] = ipl->ipl_next; + softl->ipl_used[unit] -= dlen; + MUTEX_EXIT(&softl->ipl_mutex[unit]); SPL_X(s); - error = UIOMOVE((caddr_t)ipl, dlen, UIO_READ, uio); + error = UIOMOVE(ipl, dlen, UIO_READ, uio); if (error) { SPL_NET(s); - MUTEX_ENTER(&ipl_mutex); - ipl->ipl_next = iplt[unit]; - iplt[unit] = ipl; - iplused[unit] += dlen; + MUTEX_ENTER(&softl->ipl_mutex[unit]); + IPFERROR(40006); + ipl->ipl_next = softl->iplt[unit]; + softl->iplt[unit] = ipl; + softl->ipl_used[unit] += dlen; break; } - MUTEX_ENTER(&ipl_mutex); + MUTEX_ENTER(&softl->ipl_mutex[unit]); KFREES((caddr_t)ipl, dlen); SPL_NET(s); } - if (!iplt[unit]) { - iplused[unit] = 0; - iplh[unit] = &iplt[unit]; - ipll[unit] = NULL; + if (!softl->iplt[unit]) { + softl->ipl_used[unit] = 0; + softl->iplh[unit] = &softl->iplt[unit]; + softl->ipll[unit] = NULL; } - MUTEX_EXIT(&ipl_mutex); + softl->ipl_readers[unit]--; + MUTEX_EXIT(&softl->ipl_mutex[unit]); SPL_X(s); return error; } /* ------------------------------------------------------------------------ */ -/* Function: ipflog_clear */ -/* Returns: int - number of log bytes cleared. */ -/* Parameters: unit(I) - device we are reading from */ +/* Function: ipf_log_clear */ +/* Returns: int - number of log bytes cleared. */ +/* Parameters: softc(I) - pointer to main soft context */ +/* unit(I) - device we are reading from */ /* */ /* Deletes all queued up log records for a given output device. */ /* ------------------------------------------------------------------------ */ -int ipflog_clear(unit) -minor_t unit; +int +ipf_log_clear(softc, unit) + ipf_main_softc_t *softc; + minor_t unit; { + ipf_log_softc_t *softl = softc->ipf_log_soft; iplog_t *ipl; int used; -# if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL) - int s; -# endif + SPL_INT(s); SPL_NET(s); - MUTEX_ENTER(&ipl_mutex); - while ((ipl = iplt[unit]) != NULL) { - iplt[unit] = ipl->ipl_next; + MUTEX_ENTER(&softl->ipl_mutex[unit]); + while ((ipl = softl->iplt[unit]) != NULL) { + softl->iplt[unit] = ipl->ipl_next; KFREES((caddr_t)ipl, ipl->ipl_dsize); } - iplh[unit] = &iplt[unit]; - ipll[unit] = NULL; - used = iplused[unit]; - iplused[unit] = 0; - bzero((char *)&iplcrc[unit], FI_CSIZE); - MUTEX_EXIT(&ipl_mutex); + softl->iplh[unit] = &softl->iplt[unit]; + softl->ipll[unit] = NULL; + used = softl->ipl_used[unit]; + softl->ipl_used[unit] = 0; + bzero((char *)&softl->ipl_crc[unit], FI_CSIZE); + MUTEX_EXIT(&softl->ipl_mutex[unit]); SPL_X(s); return used; } + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_log_canread */ +/* Returns: int - 0 == no data to read, 1 = data present */ +/* Parameters: softc(I) - pointer to main soft context */ +/* unit(I) - device we are reading from */ +/* */ +/* Returns an indication of whether or not there is data present in the */ +/* current buffer for the selected ipf device. */ +/* ------------------------------------------------------------------------ */ +int +ipf_log_canread(softc, unit) + ipf_main_softc_t *softc; + int unit; +{ + ipf_log_softc_t *softl = softc->ipf_log_soft; + + return softl->iplt[unit] != NULL; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_log_canread */ +/* Returns: int - 0 == no data to read, 1 = data present */ +/* Parameters: softc(I) - pointer to main soft context */ +/* unit(I) - device we are reading from */ +/* */ +/* Returns how many bytes are currently held in log buffers for the */ +/* selected ipf device. */ +/* ------------------------------------------------------------------------ */ +int +ipf_log_bytesused(softc, unit) + ipf_main_softc_t *softc; + int unit; +{ + ipf_log_softc_t *softl = softc->ipf_log_soft; + + if (softl == NULL) + return 0; + + return softl->ipl_used[unit]; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_log_failures */ +/* Returns: U_QUAD_T - number of log failures */ +/* Parameters: softc(I) - pointer to main soft context */ +/* unit(I) - device we are reading from */ +/* */ +/* Returns how many times we've tried to log a packet but failed to do so */ +/* for the selected ipf device. */ +/* ------------------------------------------------------------------------ */ +u_long +ipf_log_failures(softc, unit) + ipf_main_softc_t *softc; + int unit; +{ + ipf_log_softc_t *softl = softc->ipf_log_soft; + + if (softl == NULL) + return 0; + + return softl->ipl_logfail[unit]; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_log_logok */ +/* Returns: U_QUAD_T - number of packets logged */ +/* Parameters: softc(I) - pointer to main soft context */ +/* unit(I) - device we are reading from */ +/* */ +/* Returns how many times we've successfully logged a packet for the */ +/* selected ipf device. */ +/* ------------------------------------------------------------------------ */ +u_long +ipf_log_logok(softc, unit) + ipf_main_softc_t *softc; + int unit; +{ + ipf_log_softc_t *softl = softc->ipf_log_soft; + + if (softl == NULL) + return 0; + + return softl->ipl_logok[unit]; +} #endif /* IPFILTER_LOG */ diff --git a/ip_lookup.c b/ip_lookup.c index b8323739e6dd4..61b6166125059 100644 --- a/ip_lookup.c +++ b/ip_lookup.c @@ -1,7 +1,5 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 2002-2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -26,7 +24,9 @@ # include <sys/ioctl.h> #endif #if !defined(_KERNEL) +# include <stdio.h> # include <string.h> +# include <stdlib.h> # define _KERNEL # ifdef __OpenBSD__ struct file; @@ -35,111 +35,226 @@ struct file; # undef _KERNEL #endif #include <sys/socket.h> -#if (defined(__osf__) || defined(__hpux) || defined(__sgi)) && defined(_KERNEL) -# ifdef __osf__ -# include <net/radix.h> -# endif -# include "radix_ipf_local.h" -# define _RADIX_H_ -#endif #include <net/if.h> #if defined(__FreeBSD__) -# include <sys/cdefs.h> -# include <sys/proc.h> +# include <sys/cdefs.h> +# include <sys/proc.h> #endif #if defined(_KERNEL) # include <sys/systm.h> # if !defined(__SVR4) && !defined(__svr4__) # include <sys/mbuf.h> # endif +#else +# include "ipf.h" #endif #include <netinet/in.h> #include "netinet/ip_compat.h" #include "netinet/ip_fil.h" +#include "netinet/ip_lookup.h" #include "netinet/ip_pool.h" #include "netinet/ip_htable.h" -#include "netinet/ip_lookup.h" +#include "netinet/ip_dstlist.h" /* END OF INCLUDES */ #if !defined(lint) -static const char rcsid[] = "@(#)Id: ip_lookup.c,v 2.35.2.5 2004/07/06 11:16:25 darrenr Exp"; +static const char rcsid[] = "@(#)$Id$"; #endif -#ifdef IPFILTER_LOOKUP -int ip_lookup_inited = 0; +/* + * In this file, ip_pool.c, ip_htable.c and ip_dstlist.c, you will find the + * range for unit is [-1,IPL_LOGMAX]. The -1 is considered to be a valid number + * and represents a "wildcard" or "all" units (IPL_LOGALL). The reason for not + * starting the numbering at 0 is because the numbers [0,IPL_LOGMAX] correspond + * to the minor device number for their respective device. Thus where there is + * array indexing on the unit, +1 is used to map [-1.IPL_LOGMAX] to + * [0.POOL_LOOKUP_MAX]. + */ +static int ipf_lookup_addnode __P((ipf_main_softc_t *, caddr_t, int)); +static int ipf_lookup_delnode __P((ipf_main_softc_t *, caddr_t, int)); +static int ipf_lookup_addtable __P((ipf_main_softc_t *, caddr_t)); +static int ipf_lookup_deltable __P((ipf_main_softc_t *, caddr_t)); +static int ipf_lookup_stats __P((ipf_main_softc_t *, caddr_t)); +static int ipf_lookup_flush __P((ipf_main_softc_t *, caddr_t)); +static int ipf_lookup_iterate __P((ipf_main_softc_t *, void *, int, void *)); +static int ipf_lookup_deltok __P((ipf_main_softc_t *, void *, int, void *)); -static int iplookup_addnode __P((caddr_t)); -static int iplookup_delnode __P((caddr_t data)); -static int iplookup_addtable __P((caddr_t)); -static int iplookup_deltable __P((caddr_t)); -static int iplookup_stats __P((caddr_t)); -static int iplookup_flush __P((caddr_t)); +#define MAX_BACKENDS 3 +static ipf_lookup_t *backends[MAX_BACKENDS] = { + &ipf_pool_backend, + &ipf_htable_backend, + &ipf_dstlist_backend +}; + + +typedef struct ipf_lookup_softc_s { + void *ipf_back[MAX_BACKENDS]; +} ipf_lookup_softc_t; /* ------------------------------------------------------------------------ */ -/* Function: iplookup_init */ -/* Returns: int - 0 = success, else error */ -/* Parameters: Nil */ +/* Function: ipf_lookup_init */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ /* */ /* Initialise all of the subcomponents of the lookup infrstructure. */ /* ------------------------------------------------------------------------ */ -int ip_lookup_init() +void * +ipf_lookup_soft_create(softc) + ipf_main_softc_t *softc; { + ipf_lookup_softc_t *softl; + ipf_lookup_t **l; + int i; + + KMALLOC(softl, ipf_lookup_softc_t *); + if (softl == NULL) + return NULL; + + bzero((char *)softl, sizeof(*softl)); + + for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) { + softl->ipf_back[i] = (*(*l)->ipfl_create)(softc); + if (softl->ipf_back[i] == NULL) { + ipf_lookup_soft_destroy(softc, softl); + return NULL; + } + } + + return softl; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_lookup_soft_init */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* */ +/* Initialise all of the subcomponents of the lookup infrstructure. */ +/* ------------------------------------------------------------------------ */ +int +ipf_lookup_soft_init(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_lookup_softc_t *softl = (ipf_lookup_softc_t *)arg; + int err = 0; + int i; + + for (i = 0; i < MAX_BACKENDS; i++) { + err = (*backends[i]->ipfl_init)(softc, softl->ipf_back[i]); + if (err != 0) + break; + } + + return err; +} - if (ip_pool_init() == -1) - return -1; - RWLOCK_INIT(&ip_poolrw, "ip pool rwlock"); +/* ------------------------------------------------------------------------ */ +/* Function: ipf_lookup_soft_fini */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* */ +/* Call the fini function in each backend to cleanup all allocated data. */ +/* ------------------------------------------------------------------------ */ +int +ipf_lookup_soft_fini(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_lookup_softc_t *softl = (ipf_lookup_softc_t *)arg; + int i; - ip_lookup_inited = 1; + for (i = 0; i < MAX_BACKENDS; i++) { + if (softl->ipf_back[i] != NULL) + (*backends[i]->ipfl_fini)(softc, + softl->ipf_back[i]); + } return 0; } /* ------------------------------------------------------------------------ */ -/* Function: iplookup_unload */ +/* Function: ipf_lookup_expire */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* */ +/* Step through each of the backends and call their expire functions, */ +/* allowing them to delete any lifetime limited data. */ +/* ------------------------------------------------------------------------ */ +void +ipf_lookup_expire(softc) + ipf_main_softc_t *softc; +{ + ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; + int i; + + WRITE_ENTER(&softc->ipf_poolrw); + for (i = 0; i < MAX_BACKENDS; i++) + (*backends[i]->ipfl_expire)(softc, softl->ipf_back[i]); + RWLOCK_EXIT(&softc->ipf_poolrw); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_lookup_softc_destroy */ /* Returns: int - 0 = success, else error */ -/* Parameters: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ /* */ /* Free up all pool related memory that has been allocated whilst IPFilter */ /* has been running. Also, do any other deinitialisation required such */ -/* ip_lookup_init() can be called again, safely. */ +/* ipf_lookup_init() can be called again, safely. */ /* ------------------------------------------------------------------------ */ -void ip_lookup_unload() +void +ipf_lookup_soft_destroy(softc, arg) + ipf_main_softc_t *softc; + void *arg; { - ip_pool_fini(); - fr_htable_unload(); + ipf_lookup_softc_t *softl = (ipf_lookup_softc_t *)arg; + int i; - if (ip_lookup_inited == 1) { - RW_DESTROY(&ip_poolrw); - ip_lookup_inited = 0; + for (i = 0; i < MAX_BACKENDS; i++) { + if (softl->ipf_back[i] != NULL) + (*backends[i]->ipfl_destroy)(softc, + softl->ipf_back[i]); } + + KFREE(softl); } /* ------------------------------------------------------------------------ */ -/* Function: iplookup_ioctl */ +/* Function: ipf_lookup_ioctl */ /* Returns: int - 0 = success, else error */ -/* Parameters: data(IO) - pointer to ioctl data to be copied to/from user */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* data(IO) - pointer to ioctl data to be copied to/from user */ /* space. */ /* cmd(I) - ioctl command number */ /* mode(I) - file mode bits used with open */ +/* uid(I) - uid of process doing ioctl */ +/* ctx(I) - pointer that represents context for uid */ /* */ /* Handle ioctl commands sent to the ioctl device. For the most part, this */ /* involves just calling another function to handle the specifics of each */ /* command. */ /* ------------------------------------------------------------------------ */ -int ip_lookup_ioctl(data, cmd, mode) -caddr_t data; -ioctlcmd_t cmd; -int mode; +int +ipf_lookup_ioctl(softc, data, cmd, mode, uid, ctx) + ipf_main_softc_t *softc; + caddr_t data; + ioctlcmd_t cmd; + int mode, uid; + void *ctx; { int err; -# if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL) - int s; -# endif + SPL_INT(s); mode = mode; /* LINT */ @@ -149,44 +264,53 @@ int mode; { case SIOCLOOKUPADDNODE : case SIOCLOOKUPADDNODEW : - WRITE_ENTER(&ip_poolrw); - err = iplookup_addnode(data); - RWLOCK_EXIT(&ip_poolrw); + WRITE_ENTER(&softc->ipf_poolrw); + err = ipf_lookup_addnode(softc, data, uid); + RWLOCK_EXIT(&softc->ipf_poolrw); break; case SIOCLOOKUPDELNODE : case SIOCLOOKUPDELNODEW : - WRITE_ENTER(&ip_poolrw); - err = iplookup_delnode(data); - RWLOCK_EXIT(&ip_poolrw); + WRITE_ENTER(&softc->ipf_poolrw); + err = ipf_lookup_delnode(softc, data, uid); + RWLOCK_EXIT(&softc->ipf_poolrw); break; case SIOCLOOKUPADDTABLE : - WRITE_ENTER(&ip_poolrw); - err = iplookup_addtable(data); - RWLOCK_EXIT(&ip_poolrw); + WRITE_ENTER(&softc->ipf_poolrw); + err = ipf_lookup_addtable(softc, data); + RWLOCK_EXIT(&softc->ipf_poolrw); break; case SIOCLOOKUPDELTABLE : - WRITE_ENTER(&ip_poolrw); - err = iplookup_deltable(data); - RWLOCK_EXIT(&ip_poolrw); + WRITE_ENTER(&softc->ipf_poolrw); + err = ipf_lookup_deltable(softc, data); + RWLOCK_EXIT(&softc->ipf_poolrw); break; case SIOCLOOKUPSTAT : case SIOCLOOKUPSTATW : - WRITE_ENTER(&ip_poolrw); - err = iplookup_stats(data); - RWLOCK_EXIT(&ip_poolrw); + WRITE_ENTER(&softc->ipf_poolrw); + err = ipf_lookup_stats(softc, data); + RWLOCK_EXIT(&softc->ipf_poolrw); break; case SIOCLOOKUPFLUSH : - WRITE_ENTER(&ip_poolrw); - err = iplookup_flush(data); - RWLOCK_EXIT(&ip_poolrw); + WRITE_ENTER(&softc->ipf_poolrw); + err = ipf_lookup_flush(softc, data); + RWLOCK_EXIT(&softc->ipf_poolrw); + break; + + case SIOCLOOKUPITER : + err = ipf_lookup_iterate(softc, data, uid, ctx); + break; + + case SIOCIPFDELTOK : + err = ipf_lookup_deltok(softc, data, uid, ctx); break; default : + IPFERROR(50001); err = EINVAL; break; } @@ -196,335 +320,684 @@ int mode; /* ------------------------------------------------------------------------ */ -/* Function: iplookup_addnode */ +/* Function: ipf_lookup_addnode */ /* Returns: int - 0 = success, else error */ -/* Parameters: data(I) - pointer to data from ioctl call */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* data(I) - pointer to data from ioctl call */ /* */ /* Add a new data node to a lookup structure. First, check to see if the */ /* parent structure refered to by name exists and if it does, then go on to */ /* add a node to it. */ /* ------------------------------------------------------------------------ */ -static int iplookup_addnode(data) -caddr_t data; +static int +ipf_lookup_addnode(softc, data, uid) + ipf_main_softc_t *softc; + caddr_t data; + int uid; { - ip_pool_node_t node, *m; + ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; iplookupop_t op; - iphtable_t *iph; - iphtent_t hte; - ip_pool_t *p; + ipf_lookup_t **l; int err; + int i; - err = 0; - BCOPYIN(data, &op, sizeof(op)); - op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; - - switch (op.iplo_type) - { - case IPLT_POOL : - if (op.iplo_size != sizeof(node)) - return EINVAL; - - err = COPYIN(op.iplo_struct, &node, sizeof(node)); - if (err != 0) - return EFAULT; - - p = ip_pool_find(op.iplo_unit, op.iplo_name); - if (p == NULL) - return ESRCH; - - /* - * add an entry to a pool - return an error if it already - * exists remove an entry from a pool - if it exists - * - in both cases, the pool *must* exist! - */ - m = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask); - if (m) - return EEXIST; - err = ip_pool_insert(p, &node.ipn_addr.adf_addr, - &node.ipn_mask.adf_addr, node.ipn_info); - break; + err = BCOPYIN(data, &op, sizeof(op)); + if (err != 0) { + IPFERROR(50002); + return EFAULT; + } - case IPLT_HASH : - if (op.iplo_size != sizeof(hte)) - return EINVAL; + if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) && + (op.iplo_unit != IPLT_ALL)) { + IPFERROR(50003); + return EINVAL; + } - err = COPYIN(op.iplo_struct, &hte, sizeof(hte)); - if (err != 0) - return EFAULT; + op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; - iph = fr_findhtable(op.iplo_unit, op.iplo_name); - if (iph == NULL) - return ESRCH; - err = fr_addhtent(iph, &hte); - break; + for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) { + if (op.iplo_type == (*l)->ipfl_type) { + err = (*(*l)->ipfl_node_add)(softc, + softl->ipf_back[i], + &op, uid); + break; + } + } - default : + if (i == MAX_BACKENDS) { + IPFERROR(50012); err = EINVAL; - break; } + return err; } /* ------------------------------------------------------------------------ */ -/* Function: iplookup_delnode */ +/* Function: ipf_lookup_delnode */ /* Returns: int - 0 = success, else error */ -/* Parameters: data(I) - pointer to data from ioctl call */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* data(I) - pointer to data from ioctl call */ /* */ /* Delete a node from a lookup table by first looking for the table it is */ /* in and then deleting the entry that gets found. */ /* ------------------------------------------------------------------------ */ -static int iplookup_delnode(data) -caddr_t data; +static int +ipf_lookup_delnode(softc, data, uid) + ipf_main_softc_t *softc; + caddr_t data; + int uid; { - ip_pool_node_t node, *m; + ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; iplookupop_t op; - iphtable_t *iph; - iphtent_t hte; - ip_pool_t *p; + ipf_lookup_t **l; int err; + int i; - err = 0; - BCOPYIN(data, &op, sizeof(op)); - - op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; - - switch (op.iplo_type) - { - case IPLT_POOL : - if (op.iplo_size != sizeof(node)) - return EINVAL; - - err = COPYIN(op.iplo_struct, &node, sizeof(node)); - if (err != 0) - return EFAULT; - - p = ip_pool_find(op.iplo_unit, op.iplo_name); - if (!p) - return ESRCH; - - m = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask); - if (m == NULL) - return ENOENT; - err = ip_pool_remove(p, m); - break; + err = BCOPYIN(data, &op, sizeof(op)); + if (err != 0) { + IPFERROR(50042); + return EFAULT; + } - case IPLT_HASH : - if (op.iplo_size != sizeof(hte)) - return EINVAL; + if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) && + (op.iplo_unit != IPLT_ALL)) { + IPFERROR(50013); + return EINVAL; + } - err = COPYIN(op.iplo_struct, &hte, sizeof(hte)); - if (err != 0) - return EFAULT; + op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; - iph = fr_findhtable(op.iplo_unit, op.iplo_name); - if (iph == NULL) - return ESRCH; - err = fr_delhtent(iph, &hte); - break; + for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) { + if (op.iplo_type == (*l)->ipfl_type) { + err = (*(*l)->ipfl_node_del)(softc, softl->ipf_back[i], + &op, uid); + break; + } + } - default : + if (i == MAX_BACKENDS) { + IPFERROR(50021); err = EINVAL; - break; } return err; } /* ------------------------------------------------------------------------ */ -/* Function: iplookup_addtable */ +/* Function: ipf_lookup_addtable */ /* Returns: int - 0 = success, else error */ -/* Parameters: data(I) - pointer to data from ioctl call */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* data(I) - pointer to data from ioctl call */ /* */ /* Create a new lookup table, if one doesn't already exist using the name */ /* for this one. */ /* ------------------------------------------------------------------------ */ -static int iplookup_addtable(data) -caddr_t data; +static int +ipf_lookup_addtable(softc, data) + ipf_main_softc_t *softc; + caddr_t data; { + ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; iplookupop_t op; - int err; + ipf_lookup_t **l; + int err, i; - err = 0; - BCOPYIN(data, &op, sizeof(op)); + err = BCOPYIN(data, &op, sizeof(op)); + if (err != 0) { + IPFERROR(50022); + return EFAULT; + } - op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; + if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) && + (op.iplo_unit != IPLT_ALL)) { + IPFERROR(50023); + return EINVAL; + } - switch (op.iplo_type) - { - case IPLT_POOL : - if (ip_pool_find(op.iplo_unit, op.iplo_name) != NULL) - err = EEXIST; - else - err = ip_pool_create(&op); - break; + op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; - case IPLT_HASH : - if (fr_findhtable(op.iplo_unit, op.iplo_name) != NULL) - err = EEXIST; - else - err = fr_newhtable(&op); - break; + for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) { + if (op.iplo_type == (*l)->ipfl_type) { + err = (*(*l)->ipfl_table_add)(softc, + softl->ipf_back[i], + &op); + break; + } + } - default : + if (i == MAX_BACKENDS) { + IPFERROR(50026); err = EINVAL; - break; } + + /* + * For anonymous pools, copy back the operation struct because in the + * case of success it will contain the new table's name. + */ + if ((err == 0) && ((op.iplo_arg & LOOKUP_ANON) != 0)) { + err = BCOPYOUT(&op, data, sizeof(op)); + if (err != 0) { + IPFERROR(50027); + err = EFAULT; + } + } + return err; } /* ------------------------------------------------------------------------ */ -/* Function: iplookup_deltable */ +/* Function: ipf_lookup_deltable */ /* Returns: int - 0 = success, else error */ -/* Parameters: data(I) - pointer to data from ioctl call */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* data(I) - pointer to data from ioctl call */ /* */ /* Decodes ioctl request to remove a particular hash table or pool and */ /* calls the relevant function to do the cleanup. */ /* ------------------------------------------------------------------------ */ -static int iplookup_deltable(data) -caddr_t data; +static int +ipf_lookup_deltable(softc, data) + ipf_main_softc_t *softc; + caddr_t data; { + ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; iplookupop_t op; - int err; + ipf_lookup_t **l; + int err, i; - BCOPYIN(data, &op, sizeof(op)); - op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; + err = BCOPYIN(data, &op, sizeof(op)); + if (err != 0) { + IPFERROR(50028); + return EFAULT; + } - if (op.iplo_arg & IPLT_ANON) - op.iplo_arg &= IPLT_ANON; + if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) && + (op.iplo_unit != IPLT_ALL)) { + IPFERROR(50029); + return EINVAL; + } - /* - * create a new pool - fail if one already exists with - * the same # - */ - switch (op.iplo_type) - { - case IPLT_POOL : - err = ip_pool_destroy(&op); - break; + op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; - case IPLT_HASH : - err = fr_removehtable(&op); - break; + for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) { + if (op.iplo_type == (*l)->ipfl_type) { + err = (*(*l)->ipfl_table_del)(softc, + softl->ipf_back[i], + &op); + break; + } + } - default : + if (i == MAX_BACKENDS) { + IPFERROR(50030); err = EINVAL; - break; } return err; } /* ------------------------------------------------------------------------ */ -/* Function: iplookup_stats */ +/* Function: ipf_lookup_stats */ /* Returns: int - 0 = success, else error */ -/* Parameters: data(I) - pointer to data from ioctl call */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* data(I) - pointer to data from ioctl call */ /* */ /* Copy statistical information from inside the kernel back to user space. */ /* ------------------------------------------------------------------------ */ -static int iplookup_stats(data) -caddr_t data; +static int +ipf_lookup_stats(softc, data) + ipf_main_softc_t *softc; + caddr_t data; { + ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; iplookupop_t op; + ipf_lookup_t **l; int err; + int i; - err = 0; - BCOPYIN(data, &op, sizeof(op)); + err = BCOPYIN(data, &op, sizeof(op)); + if (err != 0) { + IPFERROR(50031); + return EFAULT; + } - switch (op.iplo_type) - { - case IPLT_POOL : - err = ip_pool_statistics(&op); - break; + if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) && + (op.iplo_unit != IPLT_ALL)) { + IPFERROR(50032); + return EINVAL; + } - case IPLT_HASH : - err = fr_gethtablestat(&op); - break; + for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) { + if (op.iplo_type == (*l)->ipfl_type) { + err = (*(*l)->ipfl_stats_get)(softc, + softl->ipf_back[i], + &op); + break; + } + } - default : + if (i == MAX_BACKENDS) { + IPFERROR(50033); err = EINVAL; - break; } + return err; } /* ------------------------------------------------------------------------ */ -/* Function: iplookup_flush */ +/* Function: ipf_lookup_flush */ /* Returns: int - 0 = success, else error */ -/* Parameters: data(I) - pointer to data from ioctl call */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* data(I) - pointer to data from ioctl call */ /* */ /* A flush is called when we want to flush all the nodes from a particular */ /* entry in the hash table/pool or want to remove all groups from those. */ /* ------------------------------------------------------------------------ */ -static int iplookup_flush(data) -caddr_t data; +static int +ipf_lookup_flush(softc, data) + ipf_main_softc_t *softc; + caddr_t data; { - int err, unit, num, type; + ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; + int err, unit, num, type, i; iplookupflush_t flush; + ipf_lookup_t **l; - err = 0; - BCOPYIN(data, &flush, sizeof(flush)); - - flush.iplf_name[sizeof(flush.iplf_name) - 1] = '\0'; + err = BCOPYIN(data, &flush, sizeof(flush)); + if (err != 0) { + IPFERROR(50034); + return EFAULT; + } unit = flush.iplf_unit; - if ((unit < 0 || unit > IPL_LOGMAX) && (unit != IPLT_ALL)) + if ((unit < 0 || unit > IPL_LOGMAX) && (unit != IPLT_ALL)) { + IPFERROR(50035); return EINVAL; + } + + flush.iplf_name[sizeof(flush.iplf_name) - 1] = '\0'; type = flush.iplf_type; + IPFERROR(50036); err = EINVAL; num = 0; - if (type == IPLT_POOL || type == IPLT_ALL) { - err = 0; - num = ip_pool_flush(&flush); - } - - if (type == IPLT_HASH || type == IPLT_ALL) { - err = 0; - num += fr_flushhtable(&flush); + for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) { + if (type == (*l)->ipfl_type || type == IPLT_ALL) { + err = 0; + num += (*(*l)->ipfl_flush)(softc, + softl->ipf_back[i], + &flush); + } } if (err == 0) { flush.iplf_count = num; - err = COPYOUT(&flush, data, sizeof(flush)); + err = BCOPYOUT(&flush, data, sizeof(flush)); + if (err != 0) { + IPFERROR(50037); + err = EFAULT; + } } return err; } -void ip_lookup_deref(type, ptr) -int type; -void *ptr; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_lookup_delref */ +/* Returns: void */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* type(I) - table type to operate on */ +/* ptr(I) - pointer to object to remove reference for */ +/* */ +/* This function organises calling the correct deref function for a given */ +/* type of object being passed into it. */ +/* ------------------------------------------------------------------------ */ +void +ipf_lookup_deref(softc, type, ptr) + ipf_main_softc_t *softc; + int type; + void *ptr; { + ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; + int i; + if (ptr == NULL) return; - WRITE_ENTER(&ip_poolrw); - switch (type) - { - case IPLT_POOL : - ip_pool_deref(ptr); - break; + for (i = 0; i < MAX_BACKENDS; i++) { + if (type == backends[i]->ipfl_type) { + WRITE_ENTER(&softc->ipf_poolrw); + (*backends[i]->ipfl_table_deref)(softc, + softl->ipf_back[i], + ptr); + RWLOCK_EXIT(&softc->ipf_poolrw); + break; + } + } +} - case IPLT_HASH : - fr_derefhtable(ptr); - break; + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_lookup_iterate */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* data(I) - pointer to data from ioctl call */ +/* uid(I) - uid of caller */ +/* ctx(I) - pointer to give the uid context */ +/* */ +/* Decodes ioctl request to step through either hash tables or pools. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_lookup_iterate(softc, data, uid, ctx) + ipf_main_softc_t *softc; + void *data; + int uid; + void *ctx; +{ + ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; + ipflookupiter_t iter; + ipftoken_t *token; + int err, i; + SPL_INT(s); + + err = ipf_inobj(softc, data, NULL, &iter, IPFOBJ_LOOKUPITER); + if (err != 0) + return err; + + if (iter.ili_unit < IPL_LOGALL && iter.ili_unit > IPL_LOGMAX) { + IPFERROR(50038); + return EINVAL; + } + + if (iter.ili_ival != IPFGENITER_LOOKUP) { + IPFERROR(50039); + return EINVAL; + } + + SPL_SCHED(s); + token = ipf_token_find(softc, iter.ili_key, uid, ctx); + if (token == NULL) { + SPL_X(s); + IPFERROR(50040); + return ESRCH; + } + + for (i = 0; i < MAX_BACKENDS; i++) { + if (iter.ili_type == backends[i]->ipfl_type) { + err = (*backends[i]->ipfl_iter_next)(softc, + softl->ipf_back[i], + token, &iter); + break; + } + } + SPL_X(s); + + if (i == MAX_BACKENDS) { + IPFERROR(50041); + err = EINVAL; } - RWLOCK_EXIT(&ip_poolrw); + + WRITE_ENTER(&softc->ipf_tokens); + ipf_token_deref(softc, token); + RWLOCK_EXIT(&softc->ipf_tokens); + + return err; } -#else /* IPFILTER_LOOKUP */ +/* ------------------------------------------------------------------------ */ +/* Function: ipf_lookup_iterderef */ +/* Returns: void */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* type(I) - backend type to iterate through */ +/* data(I) - pointer to data from ioctl call */ +/* */ +/* Decodes ioctl request to remove a particular hash table or pool and */ +/* calls the relevant function to do the cleanup. */ +/* Because each of the backend types has a different data structure, */ +/* iteration is limited to one type at a time (i.e. it is not permitted to */ +/* go on from pool types to hash types as part of the "get next".) */ +/* ------------------------------------------------------------------------ */ +void +ipf_lookup_iterderef(softc, type, data) + ipf_main_softc_t *softc; + u_32_t type; + void *data; +{ + ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; + struct iplookupiterkey *lkey; + iplookupiterkey_t key; + int i; + + key.ilik_key = type; + lkey = &key.ilik_unstr; + + if (lkey->ilik_ival != IPFGENITER_LOOKUP) + return; + WRITE_ENTER(&softc->ipf_poolrw); + + for (i = 0; i < MAX_BACKENDS; i++) { + if (lkey->ilik_type == backends[i]->ipfl_type) { + (*backends[i]->ipfl_iter_deref)(softc, + softl->ipf_back[i], + lkey->ilik_otype, + lkey->ilik_unit, + data); + break; + } + } + RWLOCK_EXIT(&softc->ipf_poolrw); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_lookup_deltok */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* data(I) - pointer to data from ioctl call */ +/* uid(I) - uid of caller */ +/* ctx(I) - pointer to give the uid context */ +/* */ +/* Deletes the token identified by the combination of (type,uid,ctx) */ +/* "key" is a combination of the table type, iterator type and the unit for */ +/* which the token was being used. */ +/* ------------------------------------------------------------------------ */ +int +ipf_lookup_deltok(softc, data, uid, ctx) + ipf_main_softc_t *softc; + void *data; + int uid; + void *ctx; +{ + int error, key; + SPL_INT(s); + + SPL_SCHED(s); + error = BCOPYIN(data, &key, sizeof(key)); + if (error == 0) + error = ipf_token_del(softc, key, uid, ctx); + SPL_X(s); + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_lookup_res_num */ +/* Returns: void * - NULL = failure, else success. */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* unit(I) - device for which this is for */ +/* type(I) - type of lookup these parameters are for. */ +/* number(I) - table number to use when searching */ +/* funcptr(IO) - pointer to pointer for storing IP address */ +/* searching function. */ +/* */ +/* Search for the "table" number passed in amongst those configured for */ +/* that particular type. If the type is recognised then the function to */ +/* call to do the IP address search will be change, regardless of whether */ +/* or not the "table" number exists. */ +/* ------------------------------------------------------------------------ */ +void * +ipf_lookup_res_num(softc, unit, type, number, funcptr) + ipf_main_softc_t *softc; + int unit; + u_int type; + u_int number; + lookupfunc_t *funcptr; +{ + char name[FR_GROUPLEN]; + +#if defined(SNPRINTF) && defined(_KERNEL) + SNPRINTF(name, sizeof(name), "%u", number); +#else + (void) sprintf(name, "%u", number); +#endif + + return ipf_lookup_res_name(softc, unit, type, name, funcptr); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_lookup_res_name */ +/* Returns: void * - NULL = failure, else success. */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* unit(I) - device for which this is for */ +/* type(I) - type of lookup these parameters are for. */ +/* name(I) - table name to use when searching */ +/* funcptr(IO) - pointer to pointer for storing IP address */ +/* searching function. */ +/* */ +/* Search for the "table" number passed in amongst those configured for */ +/* that particular type. If the type is recognised then the function to */ +/* call to do the IP address search will be changed, regardless of whether */ +/* or not the "table" number exists. */ +/* ------------------------------------------------------------------------ */ +void * +ipf_lookup_res_name(softc, unit, type, name, funcptr) + ipf_main_softc_t *softc; + int unit; + u_int type; + char *name; + lookupfunc_t *funcptr; +{ + ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; + ipf_lookup_t **l; + void *ptr = NULL; + int i; + + READ_ENTER(&softc->ipf_poolrw); + + for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) { + if (type == (*l)->ipfl_type) { + ptr = (*(*l)->ipfl_select_add_ref)(softl->ipf_back[i], + unit, name); + if (ptr != NULL && funcptr != NULL) { + *funcptr = (*l)->ipfl_addr_find; + } + break; + } + } + + if (i == MAX_BACKENDS) { + ptr = NULL; + if (funcptr != NULL) + *funcptr = NULL; + } + + RWLOCK_EXIT(&softc->ipf_poolrw); + + return ptr; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_lookup_find_htable */ +/* Returns: void * - NULL = failure, else success. */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* unit(I) - device for which this is for */ +/* name(I) - table name to use when searching */ +/* */ +/* To support the group-map feature, where a hash table maps address */ +/* networks to rule group numbers, we need to expose a function that uses */ +/* only the hash table backend. */ +/* ------------------------------------------------------------------------ */ +void * +ipf_lookup_find_htable(softc, unit, name) + ipf_main_softc_t *softc; + int unit; + char *name; +{ + ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; + ipf_lookup_t **l; + void *tab = NULL; + int i; + + READ_ENTER(&softc->ipf_poolrw); + + for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) + if (IPLT_HASH == (*l)->ipfl_type) { + tab = ipf_htable_find(softl->ipf_back[i], unit, name); + break; + } + + RWLOCK_EXIT(&softc->ipf_poolrw); + + return tab; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_lookup_sync */ +/* Returns: void */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* */ +/* This function is the interface that the machine dependent sync functions */ +/* call when a network interface name change occurs. It then calls the sync */ +/* functions of the lookup implementations - if they have one. */ +/* ------------------------------------------------------------------------ */ /*ARGSUSED*/ -int ip_lookup_ioctl(data, cmd, mode) -caddr_t data; -ioctlcmd_t cmd; -int mode; +void +ipf_lookup_sync(softc, ifp) + ipf_main_softc_t *softc; + void *ifp; +{ + ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; + ipf_lookup_t **l; + int i; + + READ_ENTER(&softc->ipf_poolrw); + + for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) + if ((*l)->ipfl_sync != NULL) + (*(*l)->ipfl_sync)(softc, softl->ipf_back[i]); + + RWLOCK_EXIT(&softc->ipf_poolrw); +} + + +#ifndef _KERNEL +void +ipf_lookup_dump(softc, arg) + ipf_main_softc_t *softc; + void *arg; { - return EIO; + ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; + ipf_lookup_t **l; + int i; + + for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) + if (IPLT_POOL == (*l)->ipfl_type) { + ipf_pool_dump(softc, softl->ipf_back[i]); + break; + } + + for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) + if (IPLT_HASH == (*l)->ipfl_type) { + ipf_htable_dump(softc, softl->ipf_back[i]); + break; + } } -#endif /* IPFILTER_LOOKUP */ +#endif diff --git a/ip_lookup.h b/ip_lookup.h index e9f8cb8afe4d0..181e1bc5d176e 100644 --- a/ip_lookup.h +++ b/ip_lookup.h @@ -1,10 +1,14 @@ -/* $NetBSD$ */ - - +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ #ifndef __IP_LOOKUP_H__ #define __IP_LOOKUP_H__ -#if defined(__STDC__) || defined(__GNUC__) +#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51) # define SIOCLOOKUPADDTABLE _IOWR('r', 60, struct iplookupop) # define SIOCLOOKUPDELTABLE _IOWR('r', 61, struct iplookupop) # define SIOCLOOKUPSTAT _IOWR('r', 64, struct iplookupop) @@ -26,6 +30,9 @@ # define SIOCLOOKUPDELNODEW _IOW(r, 68, struct iplookupop) #endif +#define LOOKUP_POOL_MAX (IPL_LOGSIZE) +#define LOOKUP_POOL_SZ (IPL_LOGSIZE + 1) + typedef struct iplookupop { int iplo_type; /* IPLT_* */ int iplo_unit; /* IPL_LOG* */ @@ -35,11 +42,14 @@ typedef struct iplookupop { void *iplo_struct; } iplookupop_t; +#define LOOKUP_ANON 0x80000000 + + typedef struct iplookupflush { int iplf_type; /* IPLT_* */ int iplf_unit; /* IPL_LOG* */ u_int iplf_arg; - size_t iplf_count; + u_int iplf_count; char iplf_name[FR_GROUPLEN]; } iplookupflush_t; @@ -54,12 +64,89 @@ typedef struct iplookuplink { #define IPLT_NONE 0 #define IPLT_POOL 1 #define IPLT_HASH 2 +#define IPLT_DSTLIST 3 + #define IPLT_ANON 0x80000000 -extern int ip_lookup_init __P((void)); -extern int ip_lookup_ioctl __P((caddr_t, ioctlcmd_t, int)); -extern void ip_lookup_unload __P((void)); -extern void ip_lookup_deref __P((int, void *)); +typedef union { + struct iplookupiterkey { + u_char ilik_ival; + u_char ilik_type; /* IPLT_* */ + u_char ilik_otype; + signed char ilik_unit; /* IPL_LOG* */ + } ilik_unstr; + u_32_t ilik_key; +} iplookupiterkey_t; + +typedef struct ipflookupiter { + int ili_nitems; + iplookupiterkey_t ili_lkey; + char ili_name[FR_GROUPLEN]; + void *ili_data; +} ipflookupiter_t; + +#define ili_key ili_lkey.ilik_key +#define ili_ival ili_lkey.ilik_unstr.ilik_ival +#define ili_unit ili_lkey.ilik_unstr.ilik_unit +#define ili_type ili_lkey.ilik_unstr.ilik_type +#define ili_otype ili_lkey.ilik_unstr.ilik_otype + +#define IPFLOOKUPITER_LIST 0 +#define IPFLOOKUPITER_NODE 1 + + +typedef struct ipf_lookup { + int ipfl_type; + void *(*ipfl_create) __P((ipf_main_softc_t *)); + void (*ipfl_destroy) __P((ipf_main_softc_t *, void *)); + int (*ipfl_init) __P((ipf_main_softc_t *, void *)); + void (*ipfl_fini) __P((ipf_main_softc_t *, void *)); + int (*ipfl_addr_find) __P((ipf_main_softc_t *, void *, + int, void *, u_int)); + size_t (*ipfl_flush) __P((ipf_main_softc_t *, void *, + iplookupflush_t *)); + int (*ipfl_iter_deref) __P((ipf_main_softc_t *, void *, + int, int, void *)); + int (*ipfl_iter_next) __P((ipf_main_softc_t *, void *, + ipftoken_t *, ipflookupiter_t *)); + int (*ipfl_node_add) __P((ipf_main_softc_t *, void *, + iplookupop_t *, int)); + int (*ipfl_node_del) __P((ipf_main_softc_t *, void *, + iplookupop_t *, int)); + int (*ipfl_stats_get) __P((ipf_main_softc_t *, void *, + iplookupop_t *)); + int (*ipfl_table_add) __P((ipf_main_softc_t *, void *, + iplookupop_t *)); + int (*ipfl_table_del) __P((ipf_main_softc_t *, void *, + iplookupop_t *)); + int (*ipfl_table_deref) __P((ipf_main_softc_t *, void *, void *)); + void *(*ipfl_table_find) __P((void *, int, char *)); + void *(*ipfl_select_add_ref) __P((void *, int, char *)); + int (*ipfl_select_node) __P((fr_info_t *, void *, u_32_t *, + frdest_t *)); + void (*ipfl_expire) __P((ipf_main_softc_t *, void *)); + void (*ipfl_sync) __P((ipf_main_softc_t *, void *)); +} ipf_lookup_t; + +extern int ipf_lookup_init __P((void)); +extern int ipf_lookup_ioctl __P((ipf_main_softc_t *, caddr_t, ioctlcmd_t, int, int, void *)); +extern void ipf_lookup_main_unload __P((void)); +extern void ipf_lookup_deref __P((ipf_main_softc_t *, int, void *)); +extern void ipf_lookup_iterderef __P((ipf_main_softc_t *, u_32_t, void *)); +extern void *ipf_lookup_res_name __P((ipf_main_softc_t *, int, u_int, char *, + lookupfunc_t *)); +extern void *ipf_lookup_res_num __P((ipf_main_softc_t *, int, u_int, u_int, + lookupfunc_t *)); +extern void ipf_lookup_soft_destroy __P((ipf_main_softc_t *, void *)); +extern void *ipf_lookup_soft_create __P((ipf_main_softc_t *)); +extern int ipf_lookup_soft_init __P((ipf_main_softc_t *, void *)); +extern int ipf_lookup_soft_fini __P((ipf_main_softc_t *, void *)); +extern void *ipf_lookup_find_htable __P((ipf_main_softc_t *, int, char *)); +extern void ipf_lookup_expire __P((ipf_main_softc_t *)); +extern void ipf_lookup_sync __P((ipf_main_softc_t *, void *)); +#ifndef _KERNEL +extern void ipf_lookup_dump __P((ipf_main_softc_t *, void *)); +#endif #endif /* __IP_LOOKUP_H__ */ diff --git a/ip_msnrpc_pxy.c b/ip_msnrpc_pxy.c deleted file mode 100644 index 187a9645a5271..0000000000000 --- a/ip_msnrpc_pxy.c +++ /dev/null @@ -1,328 +0,0 @@ -/* $NetBSD$ */ - -/* - * Copyright (C) 2000-2003 by Darren Reed - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * Simple DCE transparent proxy for MSN RPC. - * - * ******* NOTE: THIS PROXY DOES NOT DO ADDRESS TRANSLATION ******** - * - * Id: ip_msnrpc_pxy.c,v 2.17.2.1 2005/02/04 10:22:55 darrenr Exp - */ - -#define IPF_MSNRPC_PROXY - -#define IPF_MINMSNRPCLEN 24 -#define IPF_MSNRPCSKIP (2 + 19 + 2 + 2 + 2 + 19 + 2 + 2) - - -typedef struct msnrpchdr { - u_char mrh_major; /* major # == 5 */ - u_char mrh_minor; /* minor # == 0 */ - u_char mrh_type; - u_char mrh_flags; - u_32_t mrh_endian; - u_short mrh_dlen; /* data size */ - u_short mrh_alen; /* authentication length */ - u_32_t mrh_cid; /* call identifier */ - u_32_t mrh_hint; /* allocation hint */ - u_short mrh_ctxt; /* presentation context hint */ - u_char mrh_ccnt; /* cancel count */ - u_char mrh_ans; -} msnrpchdr_t; - -int ippr_msnrpc_init __P((void)); -void ippr_msnrpc_fini __P((void)); -int ippr_msnrpc_new __P((fr_info_t *, ap_session_t *, nat_t *)); -int ippr_msnrpc_out __P((fr_info_t *, ap_session_t *, nat_t *)); -int ippr_msnrpc_in __P((fr_info_t *, ap_session_t *, nat_t *)); -int ippr_msnrpc_check __P((ip_t *, msnrpchdr_t *)); - -static frentry_t msnfr; - -int msn_proxy_init = 0; - -/* - * Initialize local structures. - */ -int ippr_msnrpc_init() -{ - bzero((char *)&msnfr, sizeof(msnfr)); - msnfr.fr_ref = 1; - msnfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE; - MUTEX_INIT(&msnfr.fr_lock, "MSN RPC proxy rule lock"); - msn_proxy_init = 1; - - return 0; -} - - -void ippr_msnrpc_fini() -{ - if (msn_proxy_init == 1) { - MUTEX_DESTROY(&msnfr.fr_lock); - msn_proxy_init = 0; - } -} - - -int ippr_msnrpc_new(fin, aps, nat) -fr_info_t *fin; -ap_session_t *aps; -nat_t *nat; -{ - msnrpcinfo_t *mri; - - KMALLOC(mri, msnrpcinfo_t *); - if (mri == NULL) - return -1; - aps->aps_data = mri; - aps->aps_psiz = sizeof(msnrpcinfo_t); - - bzero((char *)mri, sizeof(*mri)); - mri->mri_cmd[0] = 0xff; - mri->mri_cmd[1] = 0xff; - return 0; -} - - -int ippr_msnrpc_check(ip, mrh) -ip_t *ip; -msnrpchdr_t *mrh; -{ - if (mrh->mrh_major != 5) - return -1; - if (mrh->mrh_minor != 0) - return -1; - if (mrh->mrh_alen != 0) - return -1; - if (mrh->mrh_endian == 0x10) { - /* Both gateway and packet match endian */ - if (mrh->mrh_dlen > ip->ip_len) - return -1; - if (mrh->mrh_type == 0 || mrh->mrh_type == 2) - if (mrh->mrh_hint > ip->ip_len) - return -1; - } else if (mrh->mrh_endian == 0x10000000) { - /* XXX - Endian mismatch - should be swapping! */ - return -1; - } else { - return -1; - } - return 0; -} - - -int ippr_msnrpc_out(fin, ip, aps, nat) -fr_info_t *fin; -ip_t *ip; -ap_session_t *aps; -nat_t *nat; -{ - msnrpcinfo_t *mri; - msnrpchdr_t *mrh; - tcphdr_t *tcp; - int dlen; - - mri = aps->aps_data; - if (mri == NULL) - return 0; - - tcp = (tcphdr_t *)fin->fin_dp; - dlen = fin->fin_dlen - (TCP_OFF(tcp) << 2); - if (dlen < IPF_MINMSNRPCLEN) - return 0; - - mrh = (msnrpchdr_t *)((char *)tcp + (TCP_OFF(tcp) << 2)); - if (ippr_msnrpc_check(ip, mrh)) - return 0; - - mri->mri_valid++; - - switch (mrh->mrh_type) - { - case 0x0b : /* BIND */ - case 0x00 : /* REQUEST */ - break; - case 0x0c : /* BIND ACK */ - case 0x02 : /* RESPONSE */ - default: - return 0; - } - mri->mri_cmd[1] = mrh->mrh_type; - return 0; -} - - -int ippr_msnrpc_in(fin, ip, aps, nat) -fr_info_t *fin; -ip_t *ip; -ap_session_t *aps; -nat_t *nat; -{ - tcphdr_t *tcp, tcph, *tcp2 = &tcph; - int dlen, sz, sz2, i; - msnrpcinfo_t *mri; - msnrpchdr_t *mrh; - fr_info_t fi; - u_short len; - char *s; - - mri = aps->aps_data; - if (mri == NULL) - return 0; - tcp = (tcphdr_t *)fin->fin_dp; - dlen = fin->fin_dlen - (TCP_OFF(tcp) << 2); - if (dlen < IPF_MINMSNRPCLEN) - return 0; - - mrh = (msnrpchdr_t *)((char *)tcp + (TCP_OFF(tcp) << 2)); - if (ippr_msnrpc_check(ip, mrh)) - return 0; - - mri->mri_valid++; - - switch (mrh->mrh_type) - { - case 0x0c : /* BIND ACK */ - if (mri->mri_cmd[1] != 0x0b) - return 0; - break; - case 0x02 : /* RESPONSE */ - if (mri->mri_cmd[1] != 0x00) - return 0; - break; - case 0x0b : /* BIND */ - case 0x00 : /* REQUEST */ - default: - return 0; - } - mri->mri_cmd[0] = mrh->mrh_type; - dlen -= sizeof(*mrh); - - /* - * Only processes RESPONSE's - */ - if (mrh->mrh_type != 0x02) - return 0; - - /* - * Skip over some bytes...what are these really ? - */ - if (dlen <= 44) - return 0; - s = (char *)(mrh + 1) + 20; - dlen -= 20; - bcopy(s, (char *)&len, sizeof(len)); - if (len == 1) { - s += 20; - dlen -= 20; - } else if (len == 2) { - s += 24; - dlen -= 24; - } else - return 0; - - if (dlen <= 10) - return 0; - dlen -= 10; - bcopy(s, (char *)&sz, sizeof(sz)); - s += sizeof(sz); - bcopy(s, (char *)&sz2, sizeof(sz2)); - s += sizeof(sz2); - if (sz2 != sz) - return 0; - if (sz > dlen) - return 0; - if (*s++ != 5) - return 0; - if (*s++ != 0) - return 0; - sz -= IPF_MSNRPCSKIP; - s += IPF_MSNRPCSKIP; - dlen -= IPF_MSNRPCSKIP; - - do { - if (sz < 7 || dlen < 7) - break; - bcopy(s, (char *)&len, sizeof(len)); - if (dlen < len) - break; - if (sz < len) - break; - - if (len != 1) - break; - sz -= 3; - i = *(s + 2); - s += 3; - dlen -= 3; - - bcopy(s, (char *)&len, sizeof(len)); - if (dlen < len) - break; - if (sz < len) - break; - s += sizeof(len); - - switch (i) - { - case 7 : - if (len == 2) { - bcopy(s, (char *)&mri->mri_rport, 2); - mri->mri_flags |= 1; - } - break; - case 9 : - if (len == 4) { - bcopy(s, (char *)&mri->mri_raddr, 4); - mri->mri_flags |= 2; - } - break; - default : - break; - } - sz -= len; - s += len; - dlen -= len; - } while (sz > 0); - - if (mri->mri_flags == 3) { - int slen; - - bcopy((char *)fin, (char *)&fi, sizeof(fi)); - bzero((char *)tcp2, sizeof(*tcp2)); - - slen = ip->ip_len; - ip->ip_len = fin->fin_hlen + sizeof(*tcp2); - bcopy((char *)fin, (char *)&fi, sizeof(fi)); - bzero((char *)tcp2, sizeof(*tcp2)); - tcp2->th_win = htons(8192); - TCP_OFF_A(tcp2, 5); - fi.fin_data[0] = htons(mri->mri_rport); - tcp2->th_sport = mri->mri_rport; - fi.fin_data[1] = 0; - tcp2->th_dport = 0; - fi.fin_state = NULL; - fi.fin_nat = NULL; - fi.fin_dlen = sizeof(*tcp2); - fi.fin_plen = fi.fin_hlen + sizeof(*tcp2); - fi.fin_dp = (char *)tcp2; - fi.fin_fi.fi_daddr = ip->ip_dst.s_addr; - fi.fin_fi.fi_saddr = mri->mri_raddr.s_addr; - if (!fi.fin_fr) - fi.fin_fr = &msnfr; - if (fr_stlookup(&fi, NULL, NULL)) { - RWLOCK_EXIT(&ipf_state); - } else { - (void) fr_addstate(&fi, NULL, SI_W_DPORT|SI_CLONE); - if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); - } - ip->ip_len = slen; - } - mri->mri_flags = 0; - return 0; -} diff --git a/ip_nat.c b/ip_nat.c index 55295028463ae..8b214a3b5cb6a 100644 --- a/ip_nat.c +++ b/ip_nat.c @@ -1,43 +1,44 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1995-2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #if defined(KERNEL) || defined(_KERNEL) # undef KERNEL -# undef _KERNEL +# undef KERNEL +# define KERNEL 1 # define KERNEL 1 -# define _KERNEL 1 #endif #include <sys/errno.h> #include <sys/types.h> #include <sys/param.h> #include <sys/time.h> #include <sys/file.h> -#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ - defined(_KERNEL) -# include "opt_ipfilter_log.h" +#if defined(_KERNEL) && \ + (defined(__NetBSD_Version) && (__NetBSD_Version >= 399002000)) +# include <sys/kauth.h> #endif #if !defined(_KERNEL) # include <stdio.h> # include <string.h> # include <stdlib.h> -# define _KERNEL -# ifdef __OpenBSD__ +# define KERNEL +# ifdef _OpenBSD__ struct file; # endif # include <sys/uio.h> -# undef _KERNEL +# undef KERNEL #endif -#if defined(_KERNEL) && (__FreeBSD_version >= 220000) +#if defined(_KERNEL) && \ + defined(__FreeBSD_version) && (__FreeBSD_version >= 220000) # include <sys/filio.h> # include <sys/fcntl.h> #else # include <sys/ioctl.h> #endif -#include <sys/fcntl.h> +#if !defined(AIX) +# include <sys/fcntl.h> +#endif #if !defined(linux) # include <sys/protosw.h> #endif @@ -51,26 +52,22 @@ struct file; #if defined(__SVR4) || defined(__svr4__) # include <sys/filio.h> # include <sys/byteorder.h> -# ifdef _KERNEL +# ifdef KERNEL # include <sys/dditypes.h> # endif # include <sys/stream.h> # include <sys/kmem.h> #endif -#if __FreeBSD_version >= 300000 +#if _FreeBSD_version >= 300000 # include <sys/queue.h> #endif #include <net/if.h> -#if __FreeBSD_version >= 300000 +#if _FreeBSD_version >= 300000 # include <net/if_var.h> -# if defined(_KERNEL) && !defined(IPFILTER_LKM) -# include "opt_ipfilter.h" -# endif #endif #ifdef sun # include <net/af.h> #endif -#include <net/route.h> #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> @@ -89,17 +86,23 @@ extern struct ifnet vpnif; #include <netinet/ip_icmp.h> #include "netinet/ip_compat.h" #include <netinet/tcpip.h> +#include "netinet/ipl.h" #include "netinet/ip_fil.h" #include "netinet/ip_nat.h" #include "netinet/ip_frag.h" #include "netinet/ip_state.h" #include "netinet/ip_proxy.h" -#ifdef IPFILTER_SYNC +#include "netinet/ip_lookup.h" +#include "netinet/ip_dstlist.h" #include "netinet/ip_sync.h" -#endif -#if (__FreeBSD_version >= 300000) +#if FREEBSD_GE_REV(300000) # include <sys/malloc.h> #endif +#ifdef HAS_SYS_MD5_H +# include <sys/md5.h> +#else +# include "md5.h" +#endif /* END OF INCLUDES */ #undef SOCKADDR_IN @@ -107,190 +110,400 @@ extern struct ifnet vpnif; #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.195.2.38 2005/03/28 11:09:54 darrenr Exp"; +static const char rcsid[] = "@(#)$Id$"; #endif +#define NATFSUM(n,v,f) ((v) == 4 ? (n)->f.in4.s_addr : (n)->f.i6[0] + \ + (n)->f.i6[1] + (n)->f.i6[2] + (n)->f.i6[3]) +#define NBUMP(x) softn->(x)++ +#define NBUMPD(x, y) do { \ + softn->x.y++; \ + DT(y); \ + } while (0) +#define NBUMPSIDE(y,x) softn->ipf_nat_stats.ns_side[y].x++ +#define NBUMPSIDED(y,x) do { softn->ipf_nat_stats.ns_side[y].x++; \ + DT(x); } while (0) +#define NBUMPSIDEX(y,x,z) \ + do { softn->ipf_nat_stats.ns_side[y].x++; \ + DT(z); } while (0) +#define NBUMPSIDEDF(y,x)do { softn->ipf_nat_stats.ns_side[y].x++; \ + DT1(x, fr_info_t *, fin); } while (0) + +frentry_t ipfnatblock; + +static ipftuneable_t ipf_nat_tuneables[] = { + /* nat */ + { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_lock) }, + "nat_lock", 0, 1, + stsizeof(ipf_nat_softc_t, ipf_nat_lock), + IPFT_RDONLY, NULL, NULL }, + { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_table_sz) }, + "nat_table_size", 1, 0x7fffffff, + stsizeof(ipf_nat_softc_t, ipf_nat_table_sz), + 0, NULL, ipf_nat_rehash }, + { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_table_max) }, + "nat_table_max", 1, 0x7fffffff, + stsizeof(ipf_nat_softc_t, ipf_nat_table_max), + 0, NULL, NULL }, + { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_maprules_sz) }, + "nat_rules_size", 1, 0x7fffffff, + stsizeof(ipf_nat_softc_t, ipf_nat_maprules_sz), + 0, NULL, ipf_nat_rehash_rules }, + { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_rdrrules_sz) }, + "rdr_rules_size", 1, 0x7fffffff, + stsizeof(ipf_nat_softc_t, ipf_nat_rdrrules_sz), + 0, NULL, ipf_nat_rehash_rules }, + { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_hostmap_sz) }, + "hostmap_size", 1, 0x7fffffff, + stsizeof(ipf_nat_softc_t, ipf_nat_hostmap_sz), + 0, NULL, ipf_nat_hostmap_rehash }, + { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_maxbucket) }, + "nat_maxbucket",1, 0x7fffffff, + stsizeof(ipf_nat_softc_t, ipf_nat_maxbucket), + 0, NULL, NULL }, + { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_logging) }, + "nat_logging", 0, 1, + stsizeof(ipf_nat_softc_t, ipf_nat_logging), + 0, NULL, NULL }, + { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_doflush) }, + "nat_doflush", 0, 1, + stsizeof(ipf_nat_softc_t, ipf_nat_doflush), + 0, NULL, NULL }, + { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_table_wm_low) }, + "nat_table_wm_low", 1, 99, + stsizeof(ipf_nat_softc_t, ipf_nat_table_wm_low), + 0, NULL, NULL }, + { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_table_wm_high) }, + "nat_table_wm_high", 2, 100, + stsizeof(ipf_nat_softc_t, ipf_nat_table_wm_high), + 0, NULL, NULL }, + { { 0 }, + NULL, 0, 0, + 0, + 0, NULL, NULL } +}; + /* ======================================================================== */ /* How the NAT is organised and works. */ /* */ /* Inside (interface y) NAT Outside (interface x) */ /* -------------------- -+- ------------------------------------- */ -/* Packet going | out, processsed by fr_checknatout() for x */ +/* Packet going | out, processsed by ipf_nat_checkout() for x */ /* ------------> | ------------> */ /* src=10.1.1.1 | src=192.1.1.1 */ /* | */ -/* | in, processed by fr_checknatin() for x */ +/* | in, processed by ipf_nat_checkin() for x */ /* <------------ | <------------ */ /* dst=10.1.1.1 | dst=192.1.1.1 */ /* -------------------- -+- ------------------------------------- */ -/* fr_checknatout() - changes ip_src and if required, sport */ +/* ipf_nat_checkout() - changes ip_src and if required, sport */ /* - creates a new mapping, if required. */ -/* fr_checknatin() - changes ip_dst and if required, dport */ +/* ipf_nat_checkin() - changes ip_dst and if required, dport */ /* */ /* In the NAT table, internal source is recorded as "in" and externally */ /* seen as "out". */ /* ======================================================================== */ -nat_t **nat_table[2] = { NULL, NULL }, - *nat_instances = NULL; -ipnat_t *nat_list = NULL; -u_int ipf_nattable_max = NAT_TABLE_MAX; -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; -u_int fr_nat_maxbucket = 0, - fr_nat_maxbucket_reset = 1; -u_32_t nat_masks = 0; -u_32_t rdr_masks = 0; -ipnat_t **nat_rules = NULL; -ipnat_t **rdr_rules = NULL; -hostmap_t **maptable = NULL; -ipftq_t nat_tqb[IPF_TCP_NSTATES]; -ipftq_t nat_udptq; -ipftq_t nat_icmptq; -ipftq_t nat_iptq; -ipftq_t *nat_utqe = NULL; +#if SOLARIS && !defined(INSTANCES) +extern int pfil_delayed_copy; +#endif + +static int ipf_nat_flush_entry __P((ipf_main_softc_t *, void *)); +static int ipf_nat_getent __P((ipf_main_softc_t *, caddr_t, int)); +static int ipf_nat_getsz __P((ipf_main_softc_t *, caddr_t, int)); +static int ipf_nat_putent __P((ipf_main_softc_t *, caddr_t, int)); +static void ipf_nat_addmap __P((ipf_nat_softc_t *, ipnat_t *)); +static void ipf_nat_addrdr __P((ipf_nat_softc_t *, ipnat_t *)); +static int ipf_nat_builddivertmp __P((ipf_nat_softc_t *, ipnat_t *)); +static int ipf_nat_clearlist __P((ipf_main_softc_t *, ipf_nat_softc_t *)); +static int ipf_nat_cmp_rules __P((ipnat_t *, ipnat_t *)); +static int ipf_nat_decap __P((fr_info_t *, nat_t *)); +static void ipf_nat_delrule __P((ipf_main_softc_t *, ipf_nat_softc_t *, + ipnat_t *, int)); +static int ipf_nat_extraflush __P((ipf_main_softc_t *, ipf_nat_softc_t *, int)); +static int ipf_nat_finalise __P((fr_info_t *, nat_t *)); +static int ipf_nat_flushtable __P((ipf_main_softc_t *, ipf_nat_softc_t *)); +static int ipf_nat_getnext __P((ipf_main_softc_t *, ipftoken_t *, + ipfgeniter_t *, ipfobj_t *)); +static int ipf_nat_gettable __P((ipf_main_softc_t *, ipf_nat_softc_t *, + char *)); +static hostmap_t *ipf_nat_hostmap __P((ipf_nat_softc_t *, ipnat_t *, + struct in_addr, struct in_addr, + struct in_addr, u_32_t)); +static int ipf_nat_icmpquerytype __P((int)); +static int ipf_nat_iterator __P((ipf_main_softc_t *, ipftoken_t *, + ipfgeniter_t *, ipfobj_t *)); +static int ipf_nat_match __P((fr_info_t *, ipnat_t *)); +static int ipf_nat_matcharray __P((nat_t *, int *, u_long)); +static int ipf_nat_matchflush __P((ipf_main_softc_t *, ipf_nat_softc_t *, + caddr_t)); +static void ipf_nat_mssclamp __P((tcphdr_t *, u_32_t, fr_info_t *, + u_short *)); +static int ipf_nat_newmap __P((fr_info_t *, nat_t *, natinfo_t *)); +static int ipf_nat_newdivert __P((fr_info_t *, nat_t *, natinfo_t *)); +static int ipf_nat_newrdr __P((fr_info_t *, nat_t *, natinfo_t *)); +static int ipf_nat_newrewrite __P((fr_info_t *, nat_t *, natinfo_t *)); +static int ipf_nat_nextaddr __P((fr_info_t *, nat_addr_t *, u_32_t *, + u_32_t *)); +static int ipf_nat_nextaddrinit __P((ipf_main_softc_t *, char *, + nat_addr_t *, int, void *)); +static int ipf_nat_resolverule __P((ipf_main_softc_t *, ipnat_t *)); +static int ipf_nat_ruleaddrinit __P((ipf_main_softc_t *, + ipf_nat_softc_t *, ipnat_t *)); +static void ipf_nat_rule_fini __P((ipf_main_softc_t *, ipnat_t *)); +static int ipf_nat_rule_init __P((ipf_main_softc_t *, ipf_nat_softc_t *, + ipnat_t *)); +static int ipf_nat_siocaddnat __P((ipf_main_softc_t *, ipf_nat_softc_t *, + ipnat_t *, int)); +static void ipf_nat_siocdelnat __P((ipf_main_softc_t *, ipf_nat_softc_t *, + ipnat_t *, int)); +static void ipf_nat_tabmove __P((ipf_nat_softc_t *, nat_t *)); + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_main_load */ +/* Returns: int - 0 == success, -1 == failure */ +/* Parameters: Nil */ +/* */ +/* The only global NAT structure that needs to be initialised is the filter */ +/* rule that is used with blocking packets. */ +/* ------------------------------------------------------------------------ */ +int +ipf_nat_main_load() +{ + bzero((char *)&ipfnatblock, sizeof(ipfnatblock)); + ipfnatblock.fr_flags = FR_BLOCK|FR_QUICK; + ipfnatblock.fr_ref = 1; + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_main_unload */ +/* Returns: int - 0 == success, -1 == failure */ +/* Parameters: Nil */ +/* */ +/* A null-op function that exists as a placeholder so that the flow in */ +/* other functions is obvious. */ +/* ------------------------------------------------------------------------ */ +int +ipf_nat_main_unload() +{ + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_soft_create */ +/* Returns: void * - NULL = failure, else pointer to NAT context */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* */ +/* Allocate the initial soft context structure for NAT and populate it with */ +/* some default values. Creating the tables is left until we call _init so */ +/* that sizes can be changed before we get under way. */ +/* ------------------------------------------------------------------------ */ +void * +ipf_nat_soft_create(softc) + ipf_main_softc_t *softc; +{ + ipf_nat_softc_t *softn; + + KMALLOC(softn, ipf_nat_softc_t *); + if (softn == NULL) + return NULL; + + bzero((char *)softn, sizeof(*softn)); + + softn->ipf_nat_tune = ipf_tune_array_copy(softn, + sizeof(ipf_nat_tuneables), + ipf_nat_tuneables); + if (softn->ipf_nat_tune == NULL) { + ipf_nat_soft_destroy(softc, softn); + return NULL; + } + if (ipf_tune_array_link(softc, softn->ipf_nat_tune) == -1) { + ipf_nat_soft_destroy(softc, softn); + return NULL; + } + + softn->ipf_nat_list_tail = &softn->ipf_nat_list; + + softn->ipf_nat_table_max = NAT_TABLE_MAX; + softn->ipf_nat_table_sz = NAT_TABLE_SZ; + softn->ipf_nat_maprules_sz = NAT_SIZE; + softn->ipf_nat_rdrrules_sz = RDR_SIZE; + softn->ipf_nat_hostmap_sz = HOSTMAP_SIZE; + softn->ipf_nat_doflush = 0; #ifdef IPFILTER_LOG -int nat_logging = 1; + softn->ipf_nat_logging = 1; #else -int nat_logging = 0; + softn->ipf_nat_logging = 0; #endif -u_long fr_defnatage = DEF_NAT_AGE, - fr_defnatipage = 120, /* 60 seconds */ - fr_defnaticmpage = 6; /* 3 seconds */ -natstat_t nat_stats; -int fr_nat_lock = 0; -int fr_nat_init = 0; -#if SOLARIS -extern int pfil_delayed_copy; -#endif + softn->ipf_nat_defage = DEF_NAT_AGE; + softn->ipf_nat_defipage = IPF_TTLVAL(60); + softn->ipf_nat_deficmpage = IPF_TTLVAL(3); + softn->ipf_nat_table_wm_high = 99; + softn->ipf_nat_table_wm_low = 90; + + return softn; +} + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_soft_destroy */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* */ +/* ------------------------------------------------------------------------ */ +void +ipf_nat_soft_destroy(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_nat_softc_t *softn = arg; -static int nat_flushtable __P((void)); -static int nat_clearlist __P((void)); -static void nat_addnat __P((struct ipnat *)); -static void nat_addrdr __P((struct ipnat *)); -static void nat_delete __P((struct nat *, int)); -static void nat_delrdr __P((struct ipnat *)); -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, int)); -static void nat_tabmove __P((nat_t *)); -static int nat_match __P((fr_info_t *, ipnat_t *)); -static INLINE int nat_newmap __P((fr_info_t *, nat_t *, natinfo_t *)); -static INLINE int nat_newrdr __P((fr_info_t *, nat_t *, natinfo_t *)); -static hostmap_t *nat_hostmap __P((ipnat_t *, struct in_addr, - struct in_addr, struct in_addr, u_32_t)); -static void nat_hostmapdel __P((struct hostmap *)); -static INLINE int nat_icmpquerytype4 __P((int)); -static int nat_siocaddnat __P((ipnat_t *, ipnat_t **, int)); -static void nat_siocdelnat __P((ipnat_t *, ipnat_t **, int)); -static INLINE int nat_finalise __P((fr_info_t *, nat_t *, natinfo_t *, - tcphdr_t *, nat_t **, int)); -static void nat_resolverule __P((ipnat_t *)); -static nat_t *fr_natclone __P((fr_info_t *, nat_t *)); -static void nat_mssclamp __P((tcphdr_t *, u_32_t, fr_info_t *, u_short *)); -static INLINE int nat_wildok __P((nat_t *, int, int, int, int)); - - -/* ------------------------------------------------------------------------ */ -/* Function: fr_natinit */ + if (softn->ipf_nat_tune != NULL) { + ipf_tune_array_unlink(softc, softn->ipf_nat_tune); + KFREES(softn->ipf_nat_tune, sizeof(ipf_nat_tuneables)); + softn->ipf_nat_tune = NULL; + } + + KFREE(softn); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_init */ /* Returns: int - 0 == success, -1 == failure */ -/* Parameters: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ /* */ /* Initialise all of the NAT locks, tables and other structures. */ /* ------------------------------------------------------------------------ */ -int fr_natinit() +int +ipf_nat_soft_init(softc, arg) + ipf_main_softc_t *softc; + void *arg; { + ipf_nat_softc_t *softn = arg; + ipftq_t *tq; int i; - KMALLOCS(nat_table[0], nat_t **, sizeof(nat_t *) * ipf_nattable_sz); - if (nat_table[0] != NULL) - bzero((char *)nat_table[0], ipf_nattable_sz * sizeof(nat_t *)); - else + KMALLOCS(softn->ipf_nat_table[0], nat_t **, \ + sizeof(nat_t *) * softn->ipf_nat_table_sz); + + if (softn->ipf_nat_table[0] != NULL) { + bzero((char *)softn->ipf_nat_table[0], + softn->ipf_nat_table_sz * sizeof(nat_t *)); + } else { return -1; + } - KMALLOCS(nat_table[1], nat_t **, sizeof(nat_t *) * ipf_nattable_sz); - if (nat_table[1] != NULL) - bzero((char *)nat_table[1], ipf_nattable_sz * sizeof(nat_t *)); - else + KMALLOCS(softn->ipf_nat_table[1], nat_t **, \ + sizeof(nat_t *) * softn->ipf_nat_table_sz); + + if (softn->ipf_nat_table[1] != NULL) { + bzero((char *)softn->ipf_nat_table[1], + softn->ipf_nat_table_sz * sizeof(nat_t *)); + } else { return -2; + } - KMALLOCS(nat_rules, ipnat_t **, sizeof(ipnat_t *) * ipf_natrules_sz); - if (nat_rules != NULL) - bzero((char *)nat_rules, ipf_natrules_sz * sizeof(ipnat_t *)); - else + KMALLOCS(softn->ipf_nat_map_rules, ipnat_t **, \ + sizeof(ipnat_t *) * softn->ipf_nat_maprules_sz); + + if (softn->ipf_nat_map_rules != NULL) { + bzero((char *)softn->ipf_nat_map_rules, + softn->ipf_nat_maprules_sz * sizeof(ipnat_t *)); + } else { return -3; + } - KMALLOCS(rdr_rules, ipnat_t **, sizeof(ipnat_t *) * ipf_rdrrules_sz); - if (rdr_rules != NULL) - bzero((char *)rdr_rules, ipf_rdrrules_sz * sizeof(ipnat_t *)); - else + KMALLOCS(softn->ipf_nat_rdr_rules, ipnat_t **, \ + sizeof(ipnat_t *) * softn->ipf_nat_rdrrules_sz); + + if (softn->ipf_nat_rdr_rules != NULL) { + bzero((char *)softn->ipf_nat_rdr_rules, + softn->ipf_nat_rdrrules_sz * sizeof(ipnat_t *)); + } else { return -4; + } - KMALLOCS(maptable, hostmap_t **, sizeof(hostmap_t *) * ipf_hostmap_sz); - if (maptable != NULL) - bzero((char *)maptable, sizeof(hostmap_t *) * ipf_hostmap_sz); - else + KMALLOCS(softn->ipf_hm_maptable, hostmap_t **, \ + sizeof(hostmap_t *) * softn->ipf_nat_hostmap_sz); + + if (softn->ipf_hm_maptable != NULL) { + bzero((char *)softn->ipf_hm_maptable, + sizeof(hostmap_t *) * softn->ipf_nat_hostmap_sz); + } else { return -5; + } + softn->ipf_hm_maplist = NULL; + + KMALLOCS(softn->ipf_nat_stats.ns_side[0].ns_bucketlen, u_int *, + softn->ipf_nat_table_sz * sizeof(u_int)); - KMALLOCS(nat_stats.ns_bucketlen[0], u_long *, - ipf_nattable_sz * sizeof(u_long)); - if (nat_stats.ns_bucketlen[0] == NULL) + if (softn->ipf_nat_stats.ns_side[0].ns_bucketlen == NULL) { return -6; - bzero((char *)nat_stats.ns_bucketlen[0], - ipf_nattable_sz * sizeof(u_long)); + } + bzero((char *)softn->ipf_nat_stats.ns_side[0].ns_bucketlen, + softn->ipf_nat_table_sz * sizeof(u_int)); + + KMALLOCS(softn->ipf_nat_stats.ns_side[1].ns_bucketlen, u_int *, + softn->ipf_nat_table_sz * sizeof(u_int)); - KMALLOCS(nat_stats.ns_bucketlen[1], u_long *, - ipf_nattable_sz * sizeof(u_long)); - if (nat_stats.ns_bucketlen[1] == NULL) + if (softn->ipf_nat_stats.ns_side[1].ns_bucketlen == NULL) { return -7; + } - bzero((char *)nat_stats.ns_bucketlen[1], - ipf_nattable_sz * sizeof(u_long)); + bzero((char *)softn->ipf_nat_stats.ns_side[1].ns_bucketlen, + softn->ipf_nat_table_sz * sizeof(u_int)); - if (fr_nat_maxbucket == 0) { - for (i = ipf_nattable_sz; i > 0; i >>= 1) - fr_nat_maxbucket++; - fr_nat_maxbucket *= 2; + if (softn->ipf_nat_maxbucket == 0) { + for (i = softn->ipf_nat_table_sz; i > 0; i >>= 1) + softn->ipf_nat_maxbucket++; + softn->ipf_nat_maxbucket *= 2; } - fr_sttab_init(nat_tqb); + ipf_sttab_init(softc, softn->ipf_nat_tcptq); /* * Increase this because we may have "keep state" following this too * and packet storms can occur if this is removed too quickly. */ - nat_tqb[IPF_TCPS_CLOSED].ifq_ttl = fr_tcplastack; - nat_tqb[IPF_TCP_NSTATES - 1].ifq_next = &nat_udptq; - nat_udptq.ifq_ttl = fr_defnatage; - nat_udptq.ifq_ref = 1; - nat_udptq.ifq_head = NULL; - nat_udptq.ifq_tail = &nat_udptq.ifq_head; - MUTEX_INIT(&nat_udptq.ifq_lock, "nat ipftq udp tab"); - nat_udptq.ifq_next = &nat_icmptq; - nat_icmptq.ifq_ttl = fr_defnaticmpage; - nat_icmptq.ifq_ref = 1; - nat_icmptq.ifq_head = NULL; - nat_icmptq.ifq_tail = &nat_icmptq.ifq_head; - MUTEX_INIT(&nat_icmptq.ifq_lock, "nat icmp ipftq tab"); - nat_icmptq.ifq_next = &nat_iptq; - nat_iptq.ifq_ttl = fr_defnatipage; - nat_iptq.ifq_ref = 1; - nat_iptq.ifq_head = NULL; - nat_iptq.ifq_tail = &nat_iptq.ifq_head; - MUTEX_INIT(&nat_iptq.ifq_lock, "nat ip ipftq tab"); - nat_iptq.ifq_next = NULL; - - for (i = 0; i < IPF_TCP_NSTATES; i++) { - if (nat_tqb[i].ifq_ttl < fr_defnaticmpage) - nat_tqb[i].ifq_ttl = fr_defnaticmpage; + softn->ipf_nat_tcptq[IPF_TCPS_CLOSED].ifq_ttl = softc->ipf_tcplastack; + softn->ipf_nat_tcptq[IPF_TCP_NSTATES - 1].ifq_next = + &softn->ipf_nat_udptq; + + IPFTQ_INIT(&softn->ipf_nat_udptq, softn->ipf_nat_defage, + "nat ipftq udp tab"); + softn->ipf_nat_udptq.ifq_next = &softn->ipf_nat_udpacktq; + + IPFTQ_INIT(&softn->ipf_nat_udpacktq, softn->ipf_nat_defage, + "nat ipftq udpack tab"); + softn->ipf_nat_udpacktq.ifq_next = &softn->ipf_nat_icmptq; + + IPFTQ_INIT(&softn->ipf_nat_icmptq, softn->ipf_nat_deficmpage, + "nat icmp ipftq tab"); + softn->ipf_nat_icmptq.ifq_next = &softn->ipf_nat_icmpacktq; + + IPFTQ_INIT(&softn->ipf_nat_icmpacktq, softn->ipf_nat_defage, + "nat icmpack ipftq tab"); + softn->ipf_nat_icmpacktq.ifq_next = &softn->ipf_nat_iptq; + + IPFTQ_INIT(&softn->ipf_nat_iptq, softn->ipf_nat_defipage, + "nat ip ipftq tab"); + softn->ipf_nat_iptq.ifq_next = &softn->ipf_nat_pending; + + IPFTQ_INIT(&softn->ipf_nat_pending, 1, "nat pending ipftq tab"); + softn->ipf_nat_pending.ifq_next = NULL; + + for (i = 0, tq = softn->ipf_nat_tcptq; i < IPF_TCP_NSTATES; i++, tq++) { + if (tq->ifq_ttl < softn->ipf_nat_deficmpage) + tq->ifq_ttl = softn->ipf_nat_deficmpage; #ifdef LARGE_NAT - else if (nat_tqb[i].ifq_ttl > fr_defnatage) - nat_tqb[i].ifq_ttl = fr_defnatage; + else if (tq->ifq_ttl > softn->ipf_nat_defage) + tq->ifq_ttl = softn->ipf_nat_defage; #endif } @@ -299,21 +512,124 @@ int fr_natinit() * this too and packet storms can occur if this is removed * too quickly. */ - nat_tqb[IPF_TCPS_CLOSED].ifq_ttl = nat_tqb[IPF_TCPS_LAST_ACK].ifq_ttl; + softn->ipf_nat_tcptq[IPF_TCPS_CLOSED].ifq_ttl = softc->ipf_tcplastack; - RWLOCK_INIT(&ipf_nat, "ipf IP NAT rwlock"); - RWLOCK_INIT(&ipf_natfrag, "ipf IP NAT-Frag rwlock"); - MUTEX_INIT(&ipf_nat_new, "ipf nat new mutex"); - MUTEX_INIT(&ipf_natio, "ipf nat io mutex"); + MUTEX_INIT(&softn->ipf_nat_new, "ipf nat new mutex"); + MUTEX_INIT(&softn->ipf_nat_io, "ipf nat io mutex"); - fr_nat_init = 1; + softn->ipf_nat_inited = 1; return 0; } /* ------------------------------------------------------------------------ */ -/* Function: nat_addrdr */ +/* Function: ipf_nat_soft_fini */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* */ +/* Free all memory used by NAT structures allocated at runtime. */ +/* ------------------------------------------------------------------------ */ +int +ipf_nat_soft_fini(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_nat_softc_t *softn = arg; + ipftq_t *ifq, *ifqnext; + + (void) ipf_nat_clearlist(softc, softn); + (void) ipf_nat_flushtable(softc, softn); + + /* + * Proxy timeout queues are not cleaned here because although they + * exist on the NAT list, ipf_proxy_unload is called after unload + * and the proxies actually are responsible for them being created. + * Should the proxy timeouts have their own list? There's no real + * justification as this is the only complication. + */ + for (ifq = softn->ipf_nat_utqe; ifq != NULL; ifq = ifqnext) { + ifqnext = ifq->ifq_next; + if (ipf_deletetimeoutqueue(ifq) == 0) + ipf_freetimeoutqueue(softc, ifq); + } + + if (softn->ipf_nat_table[0] != NULL) { + KFREES(softn->ipf_nat_table[0], + sizeof(nat_t *) * softn->ipf_nat_table_sz); + softn->ipf_nat_table[0] = NULL; + } + if (softn->ipf_nat_table[1] != NULL) { + KFREES(softn->ipf_nat_table[1], + sizeof(nat_t *) * softn->ipf_nat_table_sz); + softn->ipf_nat_table[1] = NULL; + } + if (softn->ipf_nat_map_rules != NULL) { + KFREES(softn->ipf_nat_map_rules, + sizeof(ipnat_t *) * softn->ipf_nat_maprules_sz); + softn->ipf_nat_map_rules = NULL; + } + if (softn->ipf_nat_rdr_rules != NULL) { + KFREES(softn->ipf_nat_rdr_rules, + sizeof(ipnat_t *) * softn->ipf_nat_rdrrules_sz); + softn->ipf_nat_rdr_rules = NULL; + } + if (softn->ipf_hm_maptable != NULL) { + KFREES(softn->ipf_hm_maptable, + sizeof(hostmap_t *) * softn->ipf_nat_hostmap_sz); + softn->ipf_hm_maptable = NULL; + } + if (softn->ipf_nat_stats.ns_side[0].ns_bucketlen != NULL) { + KFREES(softn->ipf_nat_stats.ns_side[0].ns_bucketlen, + sizeof(u_int) * softn->ipf_nat_table_sz); + softn->ipf_nat_stats.ns_side[0].ns_bucketlen = NULL; + } + if (softn->ipf_nat_stats.ns_side[1].ns_bucketlen != NULL) { + KFREES(softn->ipf_nat_stats.ns_side[1].ns_bucketlen, + sizeof(u_int) * softn->ipf_nat_table_sz); + softn->ipf_nat_stats.ns_side[1].ns_bucketlen = NULL; + } + + if (softn->ipf_nat_inited == 1) { + softn->ipf_nat_inited = 0; + ipf_sttab_destroy(softn->ipf_nat_tcptq); + + MUTEX_DESTROY(&softn->ipf_nat_new); + MUTEX_DESTROY(&softn->ipf_nat_io); + + MUTEX_DESTROY(&softn->ipf_nat_udptq.ifq_lock); + MUTEX_DESTROY(&softn->ipf_nat_udpacktq.ifq_lock); + MUTEX_DESTROY(&softn->ipf_nat_icmptq.ifq_lock); + MUTEX_DESTROY(&softn->ipf_nat_icmpacktq.ifq_lock); + MUTEX_DESTROY(&softn->ipf_nat_iptq.ifq_lock); + MUTEX_DESTROY(&softn->ipf_nat_pending.ifq_lock); + } + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_setlock */ +/* Returns: Nil */ +/* Parameters: arg(I) - pointer to soft state information */ +/* tmp(I) - new lock value */ +/* */ +/* Set the "lock status" of NAT to the value in tmp. */ +/* ------------------------------------------------------------------------ */ +void +ipf_nat_setlock(arg, tmp) + void *arg; + int tmp; +{ + ipf_nat_softc_t *softn = arg; + + softn->ipf_nat_lock = tmp; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_addrdr */ /* Returns: Nil */ /* Parameters: n(I) - pointer to NAT rule to add */ /* */ @@ -321,31 +637,41 @@ int fr_natinit() /* loaded NAT rules. Updates the bitmask indicating which netmasks are in */ /* use by redirect rules. */ /* ------------------------------------------------------------------------ */ -static void nat_addrdr(n) -ipnat_t *n; +static void +ipf_nat_addrdr(softn, n) + ipf_nat_softc_t *softn; + ipnat_t *n; { ipnat_t **np; u_32_t j; u_int hv; + u_int rhv; int k; - k = count4bits(n->in_outmsk); - if ((k >= 0) && (k != 32)) - rdr_masks |= 1 << k; - j = (n->in_outip & n->in_outmsk); - hv = NAT_HASH_FN(j, 0, ipf_rdrrules_sz); - np = rdr_rules + hv; + if (n->in_odstatype == FRI_NORMAL) { + k = count4bits(n->in_odstmsk); + ipf_inet_mask_add(k, &softn->ipf_nat_rdr_mask); + j = (n->in_odstaddr & n->in_odstmsk); + rhv = NAT_HASH_FN(j, 0, 0xffffffff); + } else { + ipf_inet_mask_add(0, &softn->ipf_nat_rdr_mask); + j = 0; + rhv = 0; + } + hv = rhv % softn->ipf_nat_rdrrules_sz; + np = softn->ipf_nat_rdr_rules + hv; while (*np != NULL) np = &(*np)->in_rnext; n->in_rnext = NULL; n->in_prnext = np; - n->in_hv = hv; + n->in_hv[0] = hv; + n->in_use++; *np = n; } /* ------------------------------------------------------------------------ */ -/* Function: nat_addnat */ +/* Function: ipf_nat_addmap */ /* Returns: Nil */ /* Parameters: n(I) - pointer to NAT rule to add */ /* */ @@ -353,63 +679,91 @@ ipnat_t *n; /* NAT rules. Updates the bitmask indicating which netmasks are in use by */ /* redirect rules. */ /* ------------------------------------------------------------------------ */ -static void nat_addnat(n) -ipnat_t *n; +static void +ipf_nat_addmap(softn, n) + ipf_nat_softc_t *softn; + ipnat_t *n; { ipnat_t **np; u_32_t j; u_int hv; + u_int rhv; int k; - k = count4bits(n->in_inmsk); - if ((k >= 0) && (k != 32)) - nat_masks |= 1 << k; - j = (n->in_inip & n->in_inmsk); - hv = NAT_HASH_FN(j, 0, ipf_natrules_sz); - np = nat_rules + hv; + if (n->in_osrcatype == FRI_NORMAL) { + k = count4bits(n->in_osrcmsk); + ipf_inet_mask_add(k, &softn->ipf_nat_map_mask); + j = (n->in_osrcaddr & n->in_osrcmsk); + rhv = NAT_HASH_FN(j, 0, 0xffffffff); + } else { + ipf_inet_mask_add(0, &softn->ipf_nat_map_mask); + j = 0; + rhv = 0; + } + hv = rhv % softn->ipf_nat_maprules_sz; + np = softn->ipf_nat_map_rules + hv; while (*np != NULL) np = &(*np)->in_mnext; n->in_mnext = NULL; n->in_pmnext = np; - n->in_hv = hv; + n->in_hv[1] = rhv; + n->in_use++; *np = n; } /* ------------------------------------------------------------------------ */ -/* Function: nat_delrdr */ +/* Function: ipf_nat_delrdr */ /* Returns: Nil */ /* Parameters: n(I) - pointer to NAT rule to delete */ /* */ /* Removes a redirect rule from the hash table of redirect rules. */ /* ------------------------------------------------------------------------ */ -static void nat_delrdr(n) -ipnat_t *n; +void +ipf_nat_delrdr(softn, n) + ipf_nat_softc_t *softn; + ipnat_t *n; { + if (n->in_odstatype == FRI_NORMAL) { + int k = count4bits(n->in_odstmsk); + ipf_inet_mask_del(k, &softn->ipf_nat_rdr_mask); + } else { + ipf_inet_mask_del(0, &softn->ipf_nat_rdr_mask); + } if (n->in_rnext) n->in_rnext->in_prnext = n->in_prnext; *n->in_prnext = n->in_rnext; + n->in_use--; } /* ------------------------------------------------------------------------ */ -/* Function: nat_delnat */ +/* Function: ipf_nat_delmap */ /* Returns: Nil */ /* Parameters: n(I) - pointer to NAT rule to delete */ /* */ /* Removes a NAT map rule from the hash table of NAT map rules. */ /* ------------------------------------------------------------------------ */ -static void nat_delnat(n) -ipnat_t *n; +void +ipf_nat_delmap(softn, n) + ipf_nat_softc_t *softn; + ipnat_t *n; { + if (n->in_osrcatype == FRI_NORMAL) { + int k = count4bits(n->in_osrcmsk); + ipf_inet_mask_del(k, &softn->ipf_nat_map_mask); + } else { + ipf_inet_mask_del(0, &softn->ipf_nat_map_mask); + } if (n->in_mnext != NULL) n->in_mnext->in_pmnext = n->in_pmnext; *n->in_pmnext = n->in_mnext; + n->in_use--; } /* ------------------------------------------------------------------------ */ -/* Function: nat_hostmap */ +/* Function: ipf_nat_hostmap */ /* Returns: struct hostmap* - NULL if no hostmap could be created, */ /* else a pointer to the hostmapping to use */ /* Parameters: np(I) - pointer to NAT rule */ @@ -422,64 +776,93 @@ ipnat_t *n; /* that is not doing port based translation. If is not yet allocated, then */ /* create a new entry if a non-NULL NAT rule pointer has been supplied. */ /* ------------------------------------------------------------------------ */ -static struct hostmap *nat_hostmap(np, src, dst, map, port) -ipnat_t *np; -struct in_addr src; -struct in_addr dst; -struct in_addr map; -u_32_t port; +static struct hostmap * +ipf_nat_hostmap(softn, np, src, dst, map, port) + ipf_nat_softc_t *softn; + ipnat_t *np; + struct in_addr src; + struct in_addr dst; + struct in_addr map; + u_32_t port; { hostmap_t *hm; - u_int hv; + u_int hv, rhv; hv = (src.s_addr ^ dst.s_addr); hv += src.s_addr; hv += dst.s_addr; - hv %= HOSTMAP_SIZE; - for (hm = maptable[hv]; hm; hm = hm->hm_next) - if ((hm->hm_srcip.s_addr == src.s_addr) && - (hm->hm_dstip.s_addr == dst.s_addr) && + rhv = hv; + hv %= softn->ipf_nat_hostmap_sz; + for (hm = softn->ipf_hm_maptable[hv]; hm; hm = hm->hm_hnext) + if ((hm->hm_osrcip.s_addr == src.s_addr) && + (hm->hm_odstip.s_addr == dst.s_addr) && ((np == NULL) || (np == hm->hm_ipnat)) && ((port == 0) || (port == hm->hm_port))) { + softn->ipf_nat_stats.ns_hm_addref++; hm->hm_ref++; return hm; } - if (np == NULL) + if (np == NULL) { + softn->ipf_nat_stats.ns_hm_nullnp++; return NULL; + } KMALLOC(hm, hostmap_t *); if (hm) { - hm->hm_next = maptable[hv]; - hm->hm_pnext = maptable + hv; - if (maptable[hv] != NULL) - maptable[hv]->hm_pnext = &hm->hm_next; - maptable[hv] = hm; + hm->hm_next = softn->ipf_hm_maplist; + hm->hm_pnext = &softn->ipf_hm_maplist; + if (softn->ipf_hm_maplist != NULL) + softn->ipf_hm_maplist->hm_pnext = &hm->hm_next; + softn->ipf_hm_maplist = hm; + hm->hm_hnext = softn->ipf_hm_maptable[hv]; + hm->hm_phnext = softn->ipf_hm_maptable + hv; + if (softn->ipf_hm_maptable[hv] != NULL) + softn->ipf_hm_maptable[hv]->hm_phnext = &hm->hm_hnext; + softn->ipf_hm_maptable[hv] = hm; hm->hm_ipnat = np; - hm->hm_srcip = src; - hm->hm_dstip = dst; - hm->hm_mapip = map; + np->in_use++; + hm->hm_osrcip = src; + hm->hm_odstip = dst; + hm->hm_nsrcip = map; + hm->hm_ndstip.s_addr = 0; hm->hm_ref = 1; hm->hm_port = port; + hm->hm_hv = rhv; + hm->hm_v = 4; + softn->ipf_nat_stats.ns_hm_new++; + } else { + softn->ipf_nat_stats.ns_hm_newfail++; } return hm; } /* ------------------------------------------------------------------------ */ -/* Function: nat_hostmapdel */ +/* Function: ipf_nat_hostmapdel */ /* Returns: Nil */ -/* Parameters: hm(I) - pointer to hostmap structure */ +/* Parameters: hmp(I) - pointer to hostmap structure pointer */ /* Write Locks: ipf_nat */ /* */ /* Decrement the references to this hostmap structure by one. If this */ /* reaches zero then remove it and free it. */ /* ------------------------------------------------------------------------ */ -static void nat_hostmapdel(hm) -struct hostmap *hm; +void +ipf_nat_hostmapdel(softc, hmp) + ipf_main_softc_t *softc; + struct hostmap **hmp; { + struct hostmap *hm; + + hm = *hmp; + *hmp = NULL; + hm->hm_ref--; if (hm->hm_ref == 0) { + ipf_nat_rule_deref(softc, &hm->hm_ipnat); + if (hm->hm_hnext) + hm->hm_hnext->hm_phnext = hm->hm_phnext; + *hm->hm_phnext = hm->hm_hnext; if (hm->hm_next) hm->hm_next->hm_pnext = hm->hm_pnext; *hm->hm_pnext = hm->hm_next; @@ -489,7 +872,7 @@ struct hostmap *hm; /* ------------------------------------------------------------------------ */ -/* Function: fix_outcksum */ +/* Function: ipf_fix_outcksum */ /* Returns: Nil */ /* Parameters: fin(I) - pointer to packet information */ /* sp(I) - location of 16bit checksum to update */ @@ -497,10 +880,11 @@ struct hostmap *hm; /* */ /* Adjusts the 16bit checksum by "n" for packets going out. */ /* ------------------------------------------------------------------------ */ -void fix_outcksum(fin, sp, n) -fr_info_t *fin; -u_short *sp; -u_32_t n; +void +ipf_fix_outcksum(cksum, sp, n, partial) + int cksum; + u_short *sp; + u_32_t n, partial; { u_short sumshort; u_32_t sum1; @@ -508,11 +892,14 @@ u_32_t n; if (n == 0) return; - if (n & NAT_HW_CKSUM) { - n &= 0xffff; - n += fin->fin_dlen; - n = (n & 0xffff) + (n >> 16); - *sp = n & 0xffff; + if (cksum == 4) { + *sp = 0; + return; + } + if (cksum == 2) { + sum1 = partial; + sum1 = (sum1 & 0xffff) + (sum1 >> 16); + *sp = htons(sum1); return; } sum1 = (~ntohs(*sp)) & 0xffff; @@ -526,7 +913,7 @@ u_32_t n; /* ------------------------------------------------------------------------ */ -/* Function: fix_incksum */ +/* Function: ipf_fix_incksum */ /* Returns: Nil */ /* Parameters: fin(I) - pointer to packet information */ /* sp(I) - location of 16bit checksum to update */ @@ -534,10 +921,11 @@ u_32_t n; /* */ /* Adjusts the 16bit checksum by "n" for packets going in. */ /* ------------------------------------------------------------------------ */ -void fix_incksum(fin, sp, n) -fr_info_t *fin; -u_short *sp; -u_32_t n; +void +ipf_fix_incksum(cksum, sp, n, partial) + int cksum; + u_short *sp; + u_32_t n, partial; { u_short sumshort; u_32_t sum1; @@ -545,13 +933,17 @@ u_32_t n; if (n == 0) return; - if (n & NAT_HW_CKSUM) { - n &= 0xffff; - n += fin->fin_dlen; - n = (n & 0xffff) + (n >> 16); - *sp = n & 0xffff; + if (cksum == 4) { + *sp = 0; + return; + } + if (cksum == 2) { + sum1 = partial; + sum1 = (sum1 & 0xffff) + (sum1 >> 16); + *sp = htons(sum1); return; } + sum1 = (~ntohs(*sp)) & 0xffff; sum1 += ~(n) & 0xffff; sum1 = (sum1 >> 16) + (sum1 & 0xffff); @@ -563,7 +955,7 @@ u_32_t n; /* ------------------------------------------------------------------------ */ -/* Function: fix_datacksum */ +/* Function: ipf_fix_datacksum */ /* Returns: Nil */ /* Parameters: sp(I) - location of 16bit checksum to update */ /* n((I) - amount to adjust checksum by */ @@ -580,9 +972,10 @@ u_32_t n; /* 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; +void +ipf_fix_datacksum(sp, n) + u_short *sp; + u_32_t n; { u_short sumshort; u_32_t sum1; @@ -601,26 +994,48 @@ u_32_t n; /* ------------------------------------------------------------------------ */ -/* Function: fr_nat_ioctl */ +/* Function: ipf_nat_ioctl */ /* Returns: int - 0 == success, != 0 == failure */ -/* Parameters: data(I) - pointer to ioctl data */ -/* cmd(I) - ioctl command integer */ -/* mode(I) - file mode bits used with open */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* data(I) - pointer to ioctl data */ +/* cmd(I) - ioctl command integer */ +/* mode(I) - file mode bits used with open */ +/* uid(I) - uid of calling process */ +/* ctx(I) - pointer used as key for finding context */ /* */ /* Processes an ioctl call made to operate on the IP Filter NAT device. */ /* ------------------------------------------------------------------------ */ -int fr_nat_ioctl(data, cmd, mode) -ioctlcmd_t cmd; -caddr_t data; -int mode; +int +ipf_nat_ioctl(softc, data, cmd, mode, uid, ctx) + ipf_main_softc_t *softc; + ioctlcmd_t cmd; + caddr_t data; + int mode, uid; + void *ctx; { - ipnat_t *nat, *nt, *n = NULL, **np = NULL; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; int error = 0, ret, arg, getlock; + ipnat_t *nat, *nt, *n; ipnat_t natd; - -#if (BSD >= 199306) && defined(_KERNEL) - if ((securelevel >= 2) && (mode & FWRITE)) + SPL_INT(s); + +#if BSD_GE_YEAR(199306) && defined(_KERNEL) +# if NETBSD_GE_REV(399002000) + if ((mode & FWRITE) && + kauth_authorize_network(curlwp->l_cred, KAUTH_NETWORK_FIREWALL, + KAUTH_REQ_NETWORK_FIREWALL_FW, + NULL, NULL, NULL)) +# else +# if defined(__FreeBSD_version) && (__FreeBSD_version >= 500034) + if (securelevel_ge(curthread->td_ucred, 3) && (mode & FWRITE)) +# else + if ((securelevel >= 3) && (mode & FWRITE)) +# endif +# endif + { + IPFERROR(60001); return EPERM; + } #endif #if defined(__osf__) && defined(_KERNEL) @@ -629,46 +1044,68 @@ int mode; getlock = (mode & NAT_LOCKHELD) ? 0 : 1; #endif - nat = NULL; /* XXX gcc -Wuninitialized */ - if (cmd == (ioctlcmd_t)SIOCADNAT) { - KMALLOC(nt, ipnat_t *); - } else { - nt = NULL; - } + n = NULL; + nt = NULL; + nat = NULL; - if ((cmd == (ioctlcmd_t)SIOCADNAT) || (cmd == (ioctlcmd_t)SIOCRMNAT)) { + if ((cmd == (ioctlcmd_t)SIOCADNAT) || (cmd == (ioctlcmd_t)SIOCRMNAT) || + (cmd == (ioctlcmd_t)SIOCPURGENAT)) { if (mode & NAT_SYSSPACE) { bcopy(data, (char *)&natd, sizeof(natd)); + nat = &natd; error = 0; } else { - error = fr_inobj(data, &natd, IPFOBJ_IPNAT); + bzero(&natd, sizeof(natd)); + error = ipf_inobj(softc, data, NULL, &natd, + IPFOBJ_IPNAT); + if (error != 0) + goto done; + + if (natd.in_size < sizeof(ipnat_t)) { + error = EINVAL; + goto done; + } + KMALLOCS(nt, ipnat_t *, natd.in_size); + if (nt == NULL) { + IPFERROR(60070); + error = ENOMEM; + goto done; + } + bzero(nt, natd.in_size); + error = ipf_inobjsz(softc, data, nt, IPFOBJ_IPNAT, + natd.in_size); + if (error) + goto done; + nat = nt; } - } else if (cmd == (ioctlcmd_t)SIOCIPFFL) { /* SIOCFLNAT & SIOCCNATL */ - BCOPYIN(data, &arg, sizeof(arg)); - } - - if (error != 0) - goto done; - - /* - * For add/delete, look to see if the NAT entry is already present - */ - if ((cmd == (ioctlcmd_t)SIOCADNAT) || (cmd == (ioctlcmd_t)SIOCRMNAT)) { - nat = &natd; - if (nat->in_v == 0) /* For backward compat. */ - nat->in_v = 4; + /* + * For add/delete, look to see if the NAT entry is + * already present + */ nat->in_flags &= IPN_USERFLAGS; if ((nat->in_redir & NAT_MAPBLK) == 0) { - if ((nat->in_flags & IPN_SPLIT) == 0) - nat->in_inip &= nat->in_inmsk; - if ((nat->in_flags & IPN_IPRANGE) == 0) - nat->in_outip &= nat->in_outmsk; - } - MUTEX_ENTER(&ipf_natio); - for (np = &nat_list; ((n = *np) != NULL); np = &n->in_next) - if (!bcmp((char *)&nat->in_flags, (char *)&n->in_flags, - IPN_CMPSIZ)) + if (nat->in_osrcatype == FRI_NORMAL || + nat->in_osrcatype == FRI_NONE) + nat->in_osrcaddr &= nat->in_osrcmsk; + if (nat->in_odstatype == FRI_NORMAL || + nat->in_odstatype == FRI_NONE) + nat->in_odstaddr &= nat->in_odstmsk; + if ((nat->in_flags & (IPN_SPLIT|IPN_SIPRANGE)) == 0) { + if (nat->in_nsrcatype == FRI_NORMAL) + nat->in_nsrcaddr &= nat->in_nsrcmsk; + if (nat->in_ndstatype == FRI_NORMAL) + nat->in_ndstaddr &= nat->in_ndstmsk; + } + } + + error = ipf_nat_rule_init(softc, softn, nat); + if (error != 0) + goto done; + + MUTEX_ENTER(&softn->ipf_nat_io); + for (n = softn->ipf_nat_list; n != NULL; n = n->in_next) + if (ipf_nat_cmp_rules(nat, n) == 0) break; } @@ -679,302 +1116,428 @@ int mode; { int tmp; - if (!(mode & FWRITE)) + if (!(mode & FWRITE)) { + IPFERROR(60002); error = EPERM; - else { - tmp = ipflog_clear(IPL_LOGNAT); - BCOPYOUT((char *)&tmp, (char *)data, sizeof(tmp)); + } else { + tmp = ipf_log_clear(softc, IPL_LOGNAT); + error = BCOPYOUT(&tmp, data, sizeof(tmp)); + if (error != 0) { + IPFERROR(60057); + error = EFAULT; + } } break; } + case SIOCSETLG : - if (!(mode & FWRITE)) + if (!(mode & FWRITE)) { + IPFERROR(60003); error = EPERM; - else { - BCOPYIN((char *)data, (char *)&nat_logging, - sizeof(nat_logging)); + } else { + error = BCOPYIN(data, &softn->ipf_nat_logging, + sizeof(softn->ipf_nat_logging)); + if (error != 0) + error = EFAULT; } break; + case SIOCGETLG : - BCOPYOUT((char *)&nat_logging, (char *)data, - sizeof(nat_logging)); + error = BCOPYOUT(&softn->ipf_nat_logging, data, + sizeof(softn->ipf_nat_logging)); + if (error != 0) { + IPFERROR(60004); + error = EFAULT; + } break; + case FIONREAD : - arg = iplused[IPL_LOGNAT]; - BCOPYOUT(&arg, data, sizeof(arg)); + arg = ipf_log_bytesused(softc, IPL_LOGNAT); + error = BCOPYOUT(&arg, data, sizeof(arg)); + if (error != 0) { + IPFERROR(60005); + error = EFAULT; + } break; #endif case SIOCADNAT : if (!(mode & FWRITE)) { + IPFERROR(60006); error = EPERM; } else if (n != NULL) { + natd.in_flineno = n->in_flineno; + (void) ipf_outobj(softc, data, &natd, IPFOBJ_IPNAT); + IPFERROR(60007); error = EEXIST; } else if (nt == NULL) { + IPFERROR(60008); error = ENOMEM; } if (error != 0) { - MUTEX_EXIT(&ipf_natio); + MUTEX_EXIT(&softn->ipf_nat_io); break; } - bcopy((char *)nat, (char *)nt, sizeof(*n)); - error = nat_siocaddnat(nt, np, getlock); - MUTEX_EXIT(&ipf_natio); - if (error == 0) + if (nat != nt) + bcopy((char *)nat, (char *)nt, sizeof(*n)); + error = ipf_nat_siocaddnat(softc, softn, nt, getlock); + MUTEX_EXIT(&softn->ipf_nat_io); + if (error == 0) { + nat = NULL; nt = NULL; + } break; + case SIOCRMNAT : + case SIOCPURGENAT : if (!(mode & FWRITE)) { + IPFERROR(60009); error = EPERM; n = NULL; } else if (n == NULL) { + IPFERROR(60010); error = ESRCH; } if (error != 0) { - MUTEX_EXIT(&ipf_natio); + MUTEX_EXIT(&softn->ipf_nat_io); break; } - nat_siocdelnat(n, np, getlock); + if (cmd == (ioctlcmd_t)SIOCPURGENAT) { + error = ipf_outobjsz(softc, data, n, IPFOBJ_IPNAT, + n->in_size); + if (error) { + MUTEX_EXIT(&softn->ipf_nat_io); + goto done; + } + n->in_flags |= IPN_PURGE; + } + ipf_nat_siocdelnat(softc, softn, n, getlock); - MUTEX_EXIT(&ipf_natio); + MUTEX_EXIT(&softn->ipf_nat_io); n = NULL; break; + case SIOCGNATS : - nat_stats.ns_table[0] = nat_table[0]; - nat_stats.ns_table[1] = nat_table[1]; - nat_stats.ns_list = nat_list; - nat_stats.ns_maptable = maptable; - nat_stats.ns_nattab_sz = ipf_nattable_sz; - nat_stats.ns_nattab_max = ipf_nattable_max; - nat_stats.ns_rultab_sz = ipf_natrules_sz; - nat_stats.ns_rdrtab_sz = ipf_rdrrules_sz; - nat_stats.ns_hostmap_sz = ipf_hostmap_sz; - nat_stats.ns_instances = nat_instances; - nat_stats.ns_apslist = ap_sess_list; - error = fr_outobj(data, &nat_stats, IPFOBJ_NATSTAT); + { + natstat_t *nsp = &softn->ipf_nat_stats; + + nsp->ns_side[0].ns_table = softn->ipf_nat_table[0]; + nsp->ns_side[1].ns_table = softn->ipf_nat_table[1]; + nsp->ns_list = softn->ipf_nat_list; + nsp->ns_maptable = softn->ipf_hm_maptable; + nsp->ns_maplist = softn->ipf_hm_maplist; + nsp->ns_nattab_sz = softn->ipf_nat_table_sz; + nsp->ns_nattab_max = softn->ipf_nat_table_max; + nsp->ns_rultab_sz = softn->ipf_nat_maprules_sz; + nsp->ns_rdrtab_sz = softn->ipf_nat_rdrrules_sz; + nsp->ns_hostmap_sz = softn->ipf_nat_hostmap_sz; + nsp->ns_instances = softn->ipf_nat_instances; + nsp->ns_ticks = softc->ipf_ticks; +#ifdef IPFILTER_LOGGING + nsp->ns_log_ok = ipf_log_logok(softc, IPF_LOGNAT); + nsp->ns_log_fail = ipf_log_failures(softc, IPF_LOGNAT); +#else + nsp->ns_log_ok = 0; + nsp->ns_log_fail = 0; +#endif + error = ipf_outobj(softc, data, nsp, IPFOBJ_NATSTAT); break; + } + case SIOCGNATL : { natlookup_t nl; - if (getlock) { - READ_ENTER(&ipf_nat); - } - error = fr_inobj(data, &nl, IPFOBJ_NATLOOKUP); + error = ipf_inobj(softc, data, NULL, &nl, IPFOBJ_NATLOOKUP); if (error == 0) { - if (nat_lookupredir(&nl) != NULL) { - error = fr_outobj(data, &nl, IPFOBJ_NATLOOKUP); + void *ptr; + + if (getlock) { + READ_ENTER(&softc->ipf_nat); + } + + switch (nl.nl_v) + { + case 4 : + ptr = ipf_nat_lookupredir(&nl); + break; +#ifdef USE_INET6 + case 6 : + ptr = ipf_nat6_lookupredir(&nl); + break; +#endif + default: + ptr = NULL; + break; + } + + if (getlock) { + RWLOCK_EXIT(&softc->ipf_nat); + } + if (ptr != NULL) { + error = ipf_outobj(softc, data, &nl, + IPFOBJ_NATLOOKUP); } else { + IPFERROR(60011); error = ESRCH; } } - if (getlock) { - RWLOCK_EXIT(&ipf_nat); - } break; } + case SIOCIPFFL : /* old SIOCFLNAT & SIOCCNATL */ if (!(mode & FWRITE)) { + IPFERROR(60012); error = EPERM; break; } if (getlock) { - WRITE_ENTER(&ipf_nat); + WRITE_ENTER(&softc->ipf_nat); } - error = 0; - if (arg == 0) - ret = nat_flushtable(); - else if (arg == 1) - ret = nat_clearlist(); - else - error = EINVAL; + + error = BCOPYIN(data, &arg, sizeof(arg)); + if (error != 0) { + IPFERROR(60013); + error = EFAULT; + } else { + if (arg == 0) + ret = ipf_nat_flushtable(softc, softn); + else if (arg == 1) + ret = ipf_nat_clearlist(softc, softn); + else + ret = ipf_nat_extraflush(softc, softn, arg); + ipf_proxy_flush(softc->ipf_proxy_soft, arg); + } + if (getlock) { - RWLOCK_EXIT(&ipf_nat); + RWLOCK_EXIT(&softc->ipf_nat); } if (error == 0) { - BCOPYOUT(&ret, data, sizeof(ret)); + error = BCOPYOUT(&ret, data, sizeof(ret)); } break; + + case SIOCMATCHFLUSH : + if (!(mode & FWRITE)) { + IPFERROR(60014); + error = EPERM; + break; + } + if (getlock) { + WRITE_ENTER(&softc->ipf_nat); + } + + error = ipf_nat_matchflush(softc, softn, data); + + if (getlock) { + RWLOCK_EXIT(&softc->ipf_nat); + } + break; + case SIOCPROXY : - error = appr_ioctl(data, cmd, mode); + error = ipf_proxy_ioctl(softc, data, cmd, mode, ctx); break; + case SIOCSTLCK : - fr_lock(data, &fr_nat_lock); + if (!(mode & FWRITE)) { + IPFERROR(60015); + error = EPERM; + } else { + error = ipf_lock(data, &softn->ipf_nat_lock); + } break; + case SIOCSTPUT : - if (fr_nat_lock) { - error = fr_natputent(data, getlock); + if ((mode & FWRITE) != 0) { + error = ipf_nat_putent(softc, data, getlock); } else { + IPFERROR(60016); error = EACCES; } break; + case SIOCSTGSZ : - if (fr_nat_lock) { - if (getlock) { - READ_ENTER(&ipf_nat); - } - error = fr_natgetsz(data); - if (getlock) { - RWLOCK_EXIT(&ipf_nat); - } - } else + if (softn->ipf_nat_lock) { + error = ipf_nat_getsz(softc, data, getlock); + } else { + IPFERROR(60017); error = EACCES; + } break; + case SIOCSTGET : - if (fr_nat_lock) { - if (getlock) { - READ_ENTER(&ipf_nat); - } - error = fr_natgetent(data); - if (getlock) { - RWLOCK_EXIT(&ipf_nat); - } - } else + if (softn->ipf_nat_lock) { + error = ipf_nat_getent(softc, data, getlock); + } else { + IPFERROR(60018); error = EACCES; + } + break; + + case SIOCGENITER : + { + ipfgeniter_t iter; + ipftoken_t *token; + ipfobj_t obj; + + error = ipf_inobj(softc, data, &obj, &iter, IPFOBJ_GENITER); + if (error != 0) + break; + + SPL_SCHED(s); + token = ipf_token_find(softc, iter.igi_type, uid, ctx); + if (token != NULL) { + error = ipf_nat_iterator(softc, token, &iter, &obj); + WRITE_ENTER(&softc->ipf_tokens); + ipf_token_deref(softc, token); + RWLOCK_EXIT(&softc->ipf_tokens); + } + SPL_X(s); + break; + } + + case SIOCIPFDELTOK : + error = BCOPYIN(data, &arg, sizeof(arg)); + if (error == 0) { + SPL_SCHED(s); + error = ipf_token_del(softc, arg, uid, ctx); + SPL_X(s); + } else { + IPFERROR(60019); + error = EFAULT; + } + break; + + case SIOCGTQTAB : + error = ipf_outobj(softc, data, softn->ipf_nat_tcptq, + IPFOBJ_STATETQTAB); + break; + + case SIOCGTABL : + error = ipf_nat_gettable(softc, softn, data); break; + default : + IPFERROR(60020); error = EINVAL; break; } done: - if (nt) - KFREE(nt); + if (nat != NULL) + ipf_nat_rule_fini(softc, nat); + if (nt != NULL) + KFREES(nt, nt->in_size); return error; } /* ------------------------------------------------------------------------ */ -/* Function: nat_siocaddnat */ +/* Function: ipf_nat_siocaddnat */ /* Returns: int - 0 == success, != 0 == failure */ -/* Parameters: n(I) - pointer to new NAT rule */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* softn(I) - pointer to NAT context structure */ +/* n(I) - pointer to new NAT rule */ /* np(I) - pointer to where to insert new NAT rule */ -/* getlock(I) - flag indicating if lock on ipf_nat is held */ -/* Mutex Locks: ipf_natio */ +/* getlock(I) - flag indicating if lock on is held */ +/* Mutex Locks: ipf_nat_io */ /* */ /* Handle SIOCADNAT. Resolve and calculate details inside the NAT rule */ /* from information passed to the kernel, then add it to the appropriate */ /* NAT rule table(s). */ /* ------------------------------------------------------------------------ */ -static int nat_siocaddnat(n, np, getlock) -ipnat_t *n, **np; -int getlock; +static int +ipf_nat_siocaddnat(softc, softn, n, getlock) + ipf_main_softc_t *softc; + ipf_nat_softc_t *softn; + ipnat_t *n; + int getlock; { - int error = 0, i, j; + int error = 0; - nat_resolverule(n); - if (n->in_plabel[0] != '\0') { - if (n->in_apr == NULL) - return ENOENT; + if (ipf_nat_resolverule(softc, n) != 0) { + IPFERROR(60022); + return ENOENT; } - if ((n->in_age[0] == 0) && (n->in_age[1] != 0)) + if ((n->in_age[0] == 0) && (n->in_age[1] != 0)) { + IPFERROR(60023); return EINVAL; + } - n->in_use = 0; - if (n->in_redir & NAT_MAPBLK) - n->in_space = USABLE_PORTS * ~ntohl(n->in_outmsk); - else if (n->in_flags & IPN_AUTOPORTMAP) - n->in_space = USABLE_PORTS * ~ntohl(n->in_inmsk); - else if (n->in_flags & IPN_IPRANGE) - n->in_space = ntohl(n->in_outmsk) - ntohl(n->in_outip); - else if (n->in_flags & IPN_SPLIT) - n->in_space = 2; - else if (n->in_outmsk != 0) - n->in_space = ~ntohl(n->in_outmsk); - else - n->in_space = 1; - - /* - * Calculate the number of valid IP addresses in the output - * mapping range. In all cases, the range is inclusive of - * the start and ending IP addresses. - * If to a CIDR address, lose 2: broadcast + network address - * (so subtract 1) - * If to a range, add one. - * If to a single IP address, set to 1. - */ - if (n->in_space) { - if ((n->in_flags & IPN_IPRANGE) != 0) - n->in_space += 1; - else - n->in_space -= 1; - } else - n->in_space = 1; - - if ((n->in_outmsk != 0xffffffff) && (n->in_outmsk != 0) && - ((n->in_flags & (IPN_IPRANGE|IPN_SPLIT)) == 0)) - n->in_nip = ntohl(n->in_outip) + 1; - else if ((n->in_flags & IPN_SPLIT) && - (n->in_redir & NAT_REDIRECT)) - n->in_nip = ntohl(n->in_inip); - else - n->in_nip = ntohl(n->in_outip); - if (n->in_redir & NAT_MAP) { - n->in_pnext = ntohs(n->in_pmin); - /* - * Multiply by the number of ports made available. - */ - if (ntohs(n->in_pmax) >= ntohs(n->in_pmin)) { - n->in_space *= (ntohs(n->in_pmax) - - ntohs(n->in_pmin) + 1); - /* - * Because two different sources can map to - * different destinations but use the same - * local IP#/port #. - * If the result is smaller than in_space, then - * we may have wrapped around 32bits. - */ - i = n->in_inmsk; - if ((i != 0) && (i != 0xffffffff)) { - j = n->in_space * (~ntohl(i) + 1); - if (j >= n->in_space) - n->in_space = j; - else - n->in_space = 0xffffffff; - } - } + if (n->in_redir == (NAT_DIVERTUDP|NAT_MAP)) { /* - * If no protocol is specified, multiple by 256 to allow for - * at least one IP:IP mapping per protocol. + * Prerecord whether or not the destination of the divert + * is local or not to the interface the packet is going + * to be sent out. */ - if ((n->in_flags & IPN_TCPUDPICMP) == 0) { - j = n->in_space * 256; - if (j >= n->in_space) - n->in_space = j; - else - n->in_space = 0xffffffff; - } + n->in_dlocal = ipf_deliverlocal(softc, n->in_v[1], + n->in_ifps[1], &n->in_ndstip6); } - /* Otherwise, these fields are preset */ - if (getlock) { - WRITE_ENTER(&ipf_nat); + WRITE_ENTER(&softc->ipf_nat); } n->in_next = NULL; - *np = n; - - if (n->in_age[0] != 0) - n->in_tqehead[0] = fr_addtimeoutqueue(&nat_utqe, n->in_age[0]); - - if (n->in_age[1] != 0) - n->in_tqehead[1] = fr_addtimeoutqueue(&nat_utqe, n->in_age[1]); + n->in_pnext = softn->ipf_nat_list_tail; + *n->in_pnext = n; + softn->ipf_nat_list_tail = &n->in_next; + n->in_use++; if (n->in_redir & NAT_REDIRECT) { n->in_flags &= ~IPN_NOTDST; - nat_addrdr(n); + switch (n->in_v[0]) + { + case 4 : + ipf_nat_addrdr(softn, n); + break; +#ifdef USE_INET6 + case 6 : + ipf_nat6_addrdr(softn, n); + break; +#endif + default : + break; + } + ATOMIC_INC32(softn->ipf_nat_stats.ns_rules_rdr); } + if (n->in_redir & (NAT_MAP|NAT_MAPBLK)) { n->in_flags &= ~IPN_NOTSRC; - nat_addnat(n); + switch (n->in_v[0]) + { + case 4 : + ipf_nat_addmap(softn, n); + break; +#ifdef USE_INET6 + case 6 : + ipf_nat6_addmap(softn, n); + break; +#endif + default : + break; + } + ATOMIC_INC32(softn->ipf_nat_stats.ns_rules_map); } + + if (n->in_age[0] != 0) + n->in_tqehead[0] = ipf_addtimeoutqueue(softc, + &softn->ipf_nat_utqe, + n->in_age[0]); + + if (n->in_age[1] != 0) + n->in_tqehead[1] = ipf_addtimeoutqueue(softc, + &softn->ipf_nat_utqe, + n->in_age[1]); + + MUTEX_INIT(&n->in_lock, "ipnat rule lock"); + n = NULL; - nat_stats.ns_rules++; -#if SOLARIS + ATOMIC_INC32(softn->ipf_nat_stats.ns_rules); +#if SOLARIS && !defined(INSTANCES) pfil_delayed_copy = 0; #endif if (getlock) { - RWLOCK_EXIT(&ipf_nat); /* WRITE */ + RWLOCK_EXIT(&softc->ipf_nat); /* WRITE */ } return error; @@ -982,124 +1545,208 @@ int getlock; /* ------------------------------------------------------------------------ */ -/* Function: nat_resolvrule */ +/* Function: ipf_nat_ruleaddrinit */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* softn(I) - pointer to NAT context structure */ +/* n(I) - pointer to NAT rule */ +/* */ +/* Initialise all of the NAT address structures in a NAT rule. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat_ruleaddrinit(softc, softn, n) + ipf_main_softc_t *softc; + ipf_nat_softc_t *softn; + ipnat_t *n; +{ + int idx, error; + + if ((n->in_ndst.na_atype == FRI_LOOKUP) && + (n->in_ndst.na_type != IPLT_DSTLIST)) { + IPFERROR(60071); + return EINVAL; + } + if ((n->in_nsrc.na_atype == FRI_LOOKUP) && + (n->in_nsrc.na_type != IPLT_DSTLIST)) { + IPFERROR(60069); + return EINVAL; + } + + if (n->in_redir == NAT_BIMAP) { + n->in_ndstaddr = n->in_osrcaddr; + n->in_ndstmsk = n->in_osrcmsk; + n->in_odstaddr = n->in_nsrcaddr; + n->in_odstmsk = n->in_nsrcmsk; + + } + + if (n->in_redir & NAT_REDIRECT) + idx = 1; + else + idx = 0; + /* + * Initialise all of the address fields. + */ + error = ipf_nat_nextaddrinit(softc, n->in_names, &n->in_osrc, 1, + n->in_ifps[idx]); + if (error != 0) + return error; + + error = ipf_nat_nextaddrinit(softc, n->in_names, &n->in_odst, 1, + n->in_ifps[idx]); + if (error != 0) + return error; + + error = ipf_nat_nextaddrinit(softc, n->in_names, &n->in_nsrc, 1, + n->in_ifps[idx]); + if (error != 0) + return error; + + error = ipf_nat_nextaddrinit(softc, n->in_names, &n->in_ndst, 1, + n->in_ifps[idx]); + if (error != 0) + return error; + + if (n->in_redir & NAT_DIVERTUDP) + ipf_nat_builddivertmp(softn, n); + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_resolvrule */ /* Returns: Nil */ -/* Parameters: n(I) - pointer to NAT rule */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* n(I) - pointer to NAT rule */ /* */ /* Handle SIOCADNAT. Resolve and calculate details inside the NAT rule */ /* from information passed to the kernel, then add it to the appropriate */ /* NAT rule table(s). */ /* ------------------------------------------------------------------------ */ -static void nat_resolverule(n) -ipnat_t *n; +static int +ipf_nat_resolverule(softc, n) + ipf_main_softc_t *softc; + ipnat_t *n; { - n->in_ifnames[0][LIFNAMSIZ - 1] = '\0'; - n->in_ifps[0] = fr_resolvenic(n->in_ifnames[0], 4); + char *base; - n->in_ifnames[1][LIFNAMSIZ - 1] = '\0'; - if (n->in_ifnames[1][0] == '\0') { - (void) strncpy(n->in_ifnames[1], n->in_ifnames[0], LIFNAMSIZ); + base = n->in_names; + + n->in_ifps[0] = ipf_resolvenic(softc, base + n->in_ifnames[0], + n->in_v[0]); + + if (n->in_ifnames[1] == -1) { + n->in_ifnames[1] = n->in_ifnames[0]; n->in_ifps[1] = n->in_ifps[0]; } else { - n->in_ifps[1] = fr_resolvenic(n->in_ifnames[0], 4); + n->in_ifps[1] = ipf_resolvenic(softc, base + n->in_ifnames[1], + n->in_v[1]); } - if (n->in_plabel[0] != '\0') { - n->in_apr = appr_lookup(n->in_p, n->in_plabel); + if (n->in_plabel != -1) { + if (n->in_redir & NAT_REDIRECT) + n->in_apr = ipf_proxy_lookup(softc->ipf_proxy_soft, + n->in_pr[0], + base + n->in_plabel); + else + n->in_apr = ipf_proxy_lookup(softc->ipf_proxy_soft, + n->in_pr[1], + base + n->in_plabel); + if (n->in_apr == NULL) + return -1; } + return 0; } /* ------------------------------------------------------------------------ */ -/* Function: nat_siocdelnat */ +/* Function: ipf_nat_siocdelnat */ /* Returns: int - 0 == success, != 0 == failure */ -/* Parameters: n(I) - pointer to new NAT rule */ -/* np(I) - pointer to where to insert new NAT rule */ -/* getlock(I) - flag indicating if lock on ipf_nat is held */ -/* Mutex Locks: ipf_natio */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* softn(I) - pointer to NAT context structure */ +/* n(I) - pointer to new NAT rule */ +/* getlock(I) - flag indicating if lock on is held */ +/* Mutex Locks: ipf_nat_io */ /* */ /* Handle SIOCADNAT. Resolve and calculate details inside the NAT rule */ /* from information passed to the kernel, then add it to the appropriate */ /* NAT rule table(s). */ /* ------------------------------------------------------------------------ */ -static void nat_siocdelnat(n, np, getlock) -ipnat_t *n, **np; -int getlock; +static void +ipf_nat_siocdelnat(softc, softn, n, getlock) + ipf_main_softc_t *softc; + ipf_nat_softc_t *softn; + ipnat_t *n; + int getlock; { - if (getlock) { - WRITE_ENTER(&ipf_nat); - } - if (n->in_redir & NAT_REDIRECT) - nat_delrdr(n); - if (n->in_redir & (NAT_MAPBLK|NAT_MAP)) - nat_delnat(n); - if (nat_list == NULL) { - nat_masks = 0; - rdr_masks = 0; - } - - if (n->in_tqehead[0] != NULL) { - if (fr_deletetimeoutqueue(n->in_tqehead[0]) == 0) { - fr_freetimeoutqueue(n->in_tqehead[1]); - } - } +#ifdef IPF_NAT6 + int i; +#endif - if (n->in_tqehead[1] != NULL) { - if (fr_deletetimeoutqueue(n->in_tqehead[1]) == 0) { - fr_freetimeoutqueue(n->in_tqehead[1]); - } + if (getlock) { + WRITE_ENTER(&softc->ipf_nat); } - *np = n->in_next; + ipf_nat_delrule(softc, softn, n, 1); - if (n->in_use == 0) { - if (n->in_apr) - appr_free(n->in_apr); - KFREE(n); - nat_stats.ns_rules--; -#if SOLARIS - if (nat_stats.ns_rules == 0) - pfil_delayed_copy = 1; -#endif - } else { - n->in_flags |= IPN_DELETE; - n->in_next = NULL; - } if (getlock) { - RWLOCK_EXIT(&ipf_nat); /* READ/WRITE */ + RWLOCK_EXIT(&softc->ipf_nat); /* READ/WRITE */ } } /* ------------------------------------------------------------------------ */ -/* Function: fr_natgetsz */ +/* Function: ipf_nat_getsz */ /* Returns: int - 0 == success, != 0 is the error value. */ -/* Parameters: data(I) - pointer to natget structure with kernel pointer */ -/* get the size of. */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* data(I) - pointer to natget structure with kernel */ +/* pointer get the size of. */ +/* getlock(I) - flag indicating whether or not the caller */ +/* holds a lock on ipf_nat */ /* */ /* Handle SIOCSTGSZ. */ /* Return the size of the nat list entry to be copied back to user space. */ /* The size of the entry is stored in the ng_sz field and the enture natget */ /* structure is copied back to the user. */ /* ------------------------------------------------------------------------ */ -static int fr_natgetsz(data) -caddr_t data; +static int +ipf_nat_getsz(softc, data, getlock) + ipf_main_softc_t *softc; + caddr_t data; + int getlock; { + ipf_nat_softc_t *softn = softc->ipf_nat_soft; ap_session_t *aps; nat_t *nat, *n; natget_t ng; + int error; + + error = BCOPYIN(data, &ng, sizeof(ng)); + if (error != 0) { + IPFERROR(60024); + return EFAULT; + } - BCOPYIN(data, &ng, sizeof(ng)); + if (getlock) { + READ_ENTER(&softc->ipf_nat); + } nat = ng.ng_ptr; if (!nat) { - nat = nat_instances; + nat = softn->ipf_nat_instances; ng.ng_sz = 0; /* * Empty list so the size returned is 0. Simple. */ if (nat == NULL) { - BCOPYOUT(&ng, data, sizeof(ng)); + if (getlock) { + RWLOCK_EXIT(&softc->ipf_nat); + } + error = BCOPYOUT(&ng, data, sizeof(ng)); + if (error != 0) { + IPFERROR(60025); + return EFAULT; + } return 0; } } else { @@ -1108,11 +1755,16 @@ caddr_t data; * current list of entries. Security precaution to prevent * copying of random kernel data. */ - for (n = nat_instances; n; n = n->nat_next) + for (n = softn->ipf_nat_instances; n; n = n->nat_next) if (n == nat) break; - if (!n) + if (n == NULL) { + if (getlock) { + RWLOCK_EXIT(&softc->ipf_nat); + } + IPFERROR(60026); return ESRCH; + } } /* @@ -1125,48 +1777,72 @@ caddr_t data; if (aps->aps_data != 0) ng.ng_sz += aps->aps_psiz; } + if (getlock) { + RWLOCK_EXIT(&softc->ipf_nat); + } - BCOPYOUT(&ng, data, sizeof(ng)); + error = BCOPYOUT(&ng, data, sizeof(ng)); + if (error != 0) { + IPFERROR(60027); + return EFAULT; + } return 0; } /* ------------------------------------------------------------------------ */ -/* Function: fr_natgetent */ +/* Function: ipf_nat_getent */ /* Returns: int - 0 == success, != 0 is the error value. */ -/* Parameters: data(I) - pointer to natget structure with kernel pointer */ -/* to NAT structure to copy out. */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* data(I) - pointer to natget structure with kernel pointer*/ +/* to NAT structure to copy out. */ +/* getlock(I) - flag indicating whether or not the caller */ +/* holds a lock on ipf_nat */ /* */ /* Handle SIOCSTGET. */ /* Copies out NAT entry to user space. Any additional data held for a */ /* proxy is also copied, as to is the NAT rule which was responsible for it */ /* ------------------------------------------------------------------------ */ -static int fr_natgetent(data) -caddr_t data; +static int +ipf_nat_getent(softc, data, getlock) + ipf_main_softc_t *softc; + caddr_t data; + int getlock; { + ipf_nat_softc_t *softn = softc->ipf_nat_soft; int error, outsize; ap_session_t *aps; nat_save_t *ipn, ipns; nat_t *n, *nat; - error = fr_inobj(data, &ipns, IPFOBJ_NATSAVE); + error = ipf_inobj(softc, data, NULL, &ipns, IPFOBJ_NATSAVE); if (error != 0) return error; - if ((ipns.ipn_dsize < sizeof(ipns)) || (ipns.ipn_dsize > 81920)) + if ((ipns.ipn_dsize < sizeof(ipns)) || (ipns.ipn_dsize > 81920)) { + IPFERROR(60028); return EINVAL; + } KMALLOCS(ipn, nat_save_t *, ipns.ipn_dsize); - if (ipn == NULL) + if (ipn == NULL) { + IPFERROR(60029); return ENOMEM; + } + + if (getlock) { + READ_ENTER(&softc->ipf_nat); + } ipn->ipn_dsize = ipns.ipn_dsize; nat = ipns.ipn_next; if (nat == NULL) { - nat = nat_instances; + nat = softn->ipf_nat_instances; if (nat == NULL) { - if (nat_instances == NULL) + if (softn->ipf_nat_instances == NULL) { + IPFERROR(60030); error = ENOENT; + } goto finished; } } else { @@ -1175,10 +1851,11 @@ caddr_t data; * current list of entries. Security precaution to prevent * copying of random kernel data. */ - for (n = nat_instances; n; n = n->nat_next) + for (n = softn->ipf_nat_instances; n; n = n->nat_next) if (n == nat) break; if (n == NULL) { + IPFERROR(60031); error = ESRCH; goto finished; } @@ -1195,7 +1872,7 @@ caddr_t data; */ if (nat->nat_ptr != NULL) bcopy((char *)nat->nat_ptr, (char *)&ipn->ipn_ipnat, - sizeof(ipn->ipn_ipnat)); + ipn->ipn_ipnat.in_size); /* * If we also know the NAT entry has an associated filter rule, @@ -1216,6 +1893,7 @@ caddr_t data; char *s; if (outsize < sizeof(*aps)) { + IPFERROR(60032); error = ENOBUFS; goto finished; } @@ -1226,14 +1904,24 @@ caddr_t data; outsize -= sizeof(*aps); if ((aps->aps_data != NULL) && (outsize >= aps->aps_psiz)) bcopy(aps->aps_data, s, aps->aps_psiz); - else + else { + IPFERROR(60033); error = ENOBUFS; + } } if (error == 0) { - error = fr_outobjsz(data, ipn, IPFOBJ_NATSAVE, ipns.ipn_dsize); + if (getlock) { + READ_ENTER(&softc->ipf_nat); + getlock = 0; + } + error = ipf_outobjsz(softc, data, ipn, IPFOBJ_NATSAVE, + ipns.ipn_dsize); } finished: + if (getlock) { + READ_ENTER(&softc->ipf_nat); + } if (ipn != NULL) { KFREES(ipn, ipns.ipn_dsize); } @@ -1242,21 +1930,25 @@ finished: /* ------------------------------------------------------------------------ */ -/* Function: fr_natputent */ +/* Function: ipf_nat_putent */ /* Returns: int - 0 == success, != 0 is the error value. */ -/* Parameters: data(I) - pointer to natget structure with NAT */ -/* structure information to load into the kernel */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* data(I) - pointer to natget structure with NAT */ +/* structure information to load into the kernel */ /* getlock(I) - flag indicating whether or not a write lock */ -/* on ipf_nat is already held. */ +/* on is already held. */ /* */ /* Handle SIOCSTPUT. */ /* Loads a NAT table entry from user space, including a NAT rule, proxy and */ /* firewall rule data structures, if pointers to them indicate so. */ /* ------------------------------------------------------------------------ */ -static int fr_natputent(data, getlock) -caddr_t data; -int getlock; +static int +ipf_nat_putent(softc, data, getlock) + ipf_main_softc_t *softc; + caddr_t data; + int getlock; { + ipf_nat_softc_t *softn = softc->ipf_nat_soft; nat_save_t ipn, *ipnn; ap_session_t *aps; nat_t *n, *nat; @@ -1265,36 +1957,41 @@ int getlock; ipnat_t *in; int error; - error = fr_inobj(data, &ipn, IPFOBJ_NATSAVE); + error = ipf_inobj(softc, data, NULL, &ipn, IPFOBJ_NATSAVE); if (error != 0) return error; /* * Initialise early because of code at junkput label. */ + n = NULL; in = NULL; aps = NULL; nat = NULL; ipnn = NULL; + fr = NULL; /* * New entry, copy in the rest of the NAT entry if it's size is more * than just the nat_t structure. */ - fr = NULL; if (ipn.ipn_dsize > sizeof(ipn)) { if (ipn.ipn_dsize > 81920) { + IPFERROR(60034); error = ENOMEM; goto junkput; } KMALLOCS(ipnn, nat_save_t *, ipn.ipn_dsize); - if (ipnn == NULL) + if (ipnn == NULL) { + IPFERROR(60035); return ENOMEM; + } - error = fr_inobjsz(data, ipnn, IPFOBJ_NATSAVE, ipn.ipn_dsize); + bzero(ipnn, ipn.ipn_dsize); + error = ipf_inobjsz(softc, data, ipnn, IPFOBJ_NATSAVE, + ipn.ipn_dsize); if (error != 0) { - error = EFAULT; goto junkput; } } else @@ -1302,13 +1999,29 @@ int getlock; KMALLOC(nat, nat_t *); if (nat == NULL) { + IPFERROR(60037); error = ENOMEM; goto junkput; } bcopy((char *)&ipnn->ipn_nat, (char *)nat, sizeof(*nat)); + + switch (nat->nat_v[0]) + { + case 4: +#ifdef USE_IENT6 + case 6 : +#endif + break; + default : + IPFERROR(60061); + error = EPROTONOSUPPORT; + goto junkput; + /*NOTREACHED*/ + } + /* - * Initialize all these so that nat_delete() doesn't cause a crash. + * Initialize all these so that ipf_nat_delete() doesn't cause a crash. */ bzero((char *)nat, offsetof(struct nat, nat_tqe)); nat->nat_tqe.tqe_pnext = NULL; @@ -1321,46 +2034,103 @@ int getlock; */ in = ipnn->ipn_nat.nat_ptr; if (in != NULL) { - KMALLOC(in, ipnat_t *); + KMALLOCS(in, ipnat_t *, ipnn->ipn_ipnat.in_size); nat->nat_ptr = in; if (in == NULL) { + IPFERROR(60038); error = ENOMEM; goto junkput; } - bzero((char *)in, offsetof(struct ipnat, in_next6)); - bcopy((char *)&ipnn->ipn_ipnat, (char *)in, sizeof(*in)); + bcopy((char *)&ipnn->ipn_ipnat, (char *)in, + ipnn->ipn_ipnat.in_size); in->in_use = 1; in->in_flags |= IPN_DELETE; - ATOMIC_INC(nat_stats.ns_rules); + ATOMIC_INC32(softn->ipf_nat_stats.ns_rules); - nat_resolverule(in); + if (ipf_nat_resolverule(softc, in) != 0) { + IPFERROR(60039); + error = ESRCH; + goto junkput; + } } /* * Check that the NAT entry doesn't already exist in the kernel. + * + * For NAT_OUTBOUND, we're lookup for a duplicate MAP entry. To do + * this, we check to see if the inbound combination of addresses and + * ports is already known. Similar logic is applied for NAT_INBOUND. + * */ bzero((char *)&fin, sizeof(fin)); - fin.fin_p = nat->nat_p; - if (nat->nat_dir == NAT_OUTBOUND) { - fin.fin_data[0] = ntohs(nat->nat_oport); - fin.fin_data[1] = ntohs(nat->nat_outport); - fin.fin_ifp = nat->nat_ifps[1]; - if (nat_inlookup(&fin, 0, fin.fin_p, nat->nat_oip, - nat->nat_inip) != NULL) { + fin.fin_v = nat->nat_v[0]; + fin.fin_p = nat->nat_pr[0]; + fin.fin_rev = nat->nat_rev; + fin.fin_ifp = nat->nat_ifps[0]; + fin.fin_data[0] = ntohs(nat->nat_ndport); + fin.fin_data[1] = ntohs(nat->nat_nsport); + + switch (nat->nat_dir) + { + case NAT_OUTBOUND : + case NAT_DIVERTOUT : + if (getlock) { + READ_ENTER(&softc->ipf_nat); + } + + fin.fin_v = nat->nat_v[1]; + if (nat->nat_v[1] == 4) { + n = ipf_nat_inlookup(&fin, nat->nat_flags, fin.fin_p, + nat->nat_ndstip, nat->nat_nsrcip); +#ifdef USE_INET6 + } else if (nat->nat_v[1] == 6) { + n = ipf_nat6_inlookup(&fin, nat->nat_flags, fin.fin_p, + &nat->nat_ndst6.in6, + &nat->nat_nsrc6.in6); +#endif + } + + if (getlock) { + RWLOCK_EXIT(&softc->ipf_nat); + } + if (n != NULL) { + IPFERROR(60040); error = EEXIST; goto junkput; } - } else if (nat->nat_dir == NAT_INBOUND) { - fin.fin_data[0] = ntohs(nat->nat_outport); - fin.fin_data[1] = ntohs(nat->nat_oport); - fin.fin_ifp = nat->nat_ifps[0]; - if (nat_outlookup(&fin, 0, fin.fin_p, nat->nat_outip, - nat->nat_oip) != NULL) { + break; + + case NAT_INBOUND : + case NAT_DIVERTIN : + if (getlock) { + READ_ENTER(&softc->ipf_nat); + } + + if (fin.fin_v == 4) { + n = ipf_nat_outlookup(&fin, nat->nat_flags, fin.fin_p, + nat->nat_ndstip, + nat->nat_nsrcip); +#ifdef USE_INET6 + } else if (fin.fin_v == 6) { + n = ipf_nat6_outlookup(&fin, nat->nat_flags, fin.fin_p, + &nat->nat_ndst6.in6, + &nat->nat_nsrc6.in6); +#endif + } + + if (getlock) { + RWLOCK_EXIT(&softc->ipf_nat); + } + if (n != NULL) { + IPFERROR(60041); error = EEXIST; goto junkput; } - } else { + break; + + default : + IPFERROR(60042); error = EINVAL; goto junkput; } @@ -1374,6 +2144,7 @@ int getlock; KMALLOC(aps, ap_session_t *); nat->nat_aps = aps; if (aps == NULL) { + IPFERROR(60043); error = ENOMEM; goto junkput; } @@ -1384,11 +2155,13 @@ int getlock; aps->aps_apr = NULL; if (aps->aps_psiz != 0) { if (aps->aps_psiz > 81920) { + IPFERROR(60044); error = ENOMEM; goto junkput; } KMALLOCS(aps->aps_data, void *, aps->aps_psiz); if (aps->aps_data == NULL) { + IPFERROR(60045); error = ENOMEM; goto junkput; } @@ -1410,18 +2183,27 @@ int getlock; KMALLOC(fr, frentry_t *); nat->nat_fr = fr; if (fr == NULL) { + IPFERROR(60046); error = ENOMEM; goto junkput; } ipnn->ipn_nat.nat_fr = fr; fr->fr_ref = 1; - (void) fr_outobj(data, ipnn, IPFOBJ_NATSAVE); + (void) ipf_outobj(softc, data, ipnn, IPFOBJ_NATSAVE); bcopy((char *)&ipnn->ipn_fr, (char *)fr, sizeof(*fr)); + + fr->fr_ref = 1; + fr->fr_dsize = 0; + fr->fr_data = NULL; + fr->fr_type = FR_T_NONE; + MUTEX_NUKE(&fr->fr_lock); MUTEX_INIT(&fr->fr_lock, "nat-filter rule lock"); } else { - READ_ENTER(&ipf_nat); - for (n = nat_instances; n; n = n->nat_next) + if (getlock) { + READ_ENTER(&softc->ipf_nat); + } + for (n = softn->ipf_nat_instances; n; n = n->nat_next) if (n->nat_fr == fr) break; @@ -1430,9 +2212,12 @@ int getlock; fr->fr_ref++; MUTEX_EXIT(&fr->fr_lock); } - RWLOCK_EXIT(&ipf_nat); + if (getlock) { + RWLOCK_EXIT(&softc->ipf_nat); + } - if (!n) { + if (n == NULL) { + IPFERROR(60047); error = ESRCH; goto junkput; } @@ -1445,25 +2230,30 @@ int getlock; } if (getlock) { - WRITE_ENTER(&ipf_nat); - } - error = nat_insert(nat, nat->nat_rev); - if ((error == 0) && (aps != NULL)) { - aps->aps_next = ap_sess_list; - ap_sess_list = aps; + WRITE_ENTER(&softc->ipf_nat); } + + if (fin.fin_v == 4) + error = ipf_nat_finalise(&fin, nat); +#ifdef USE_INET6 + else + error = ipf_nat6_finalise(&fin, nat); +#endif + if (getlock) { - RWLOCK_EXIT(&ipf_nat); + RWLOCK_EXIT(&softc->ipf_nat); } if (error == 0) return 0; + IPFERROR(60048); error = ENOMEM; junkput: - if (fr != NULL) - fr_derefrule(&fr); + if (fr != NULL) { + (void) ipf_derefrule(softc, &fr); + } if ((ipnn != NULL) && (ipnn != &ipn)) { KFREES(ipnn, ipn.ipn_dsize); @@ -1477,8 +2267,8 @@ junkput: } if (in != NULL) { if (in->in_apr) - appr_free(in->in_apr); - KFREE(in); + ipf_proxy_deref(in->in_apr); + KFREES(in, in->in_size); } KFREE(nat); } @@ -1487,33 +2277,50 @@ junkput: /* ------------------------------------------------------------------------ */ -/* Function: nat_delete */ +/* Function: ipf_nat_delete */ /* Returns: Nil */ -/* Parameters: natd(I) - pointer to NAT structure to delete */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* nat(I) - pointer to NAT structure to delete */ /* logtype(I) - type of LOG record to create before deleting */ /* Write Lock: ipf_nat */ /* */ /* Delete a nat entry from the various lists and table. If NAT logging is */ /* enabled then generate a NAT log record for this event. */ /* ------------------------------------------------------------------------ */ -static void nat_delete(nat, logtype) -struct nat *nat; -int logtype; +void +ipf_nat_delete(softc, nat, logtype) + ipf_main_softc_t *softc; + struct nat *nat; + int logtype; { + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + int madeorphan = 0, bkt, removed = 0; + nat_stat_side_t *nss; struct ipnat *ipn; - if (logtype != 0 && nat_logging != 0) - nat_log(nat, logtype); - - MUTEX_ENTER(&ipf_nat_new); + if (logtype != 0 && softn->ipf_nat_logging != 0) + ipf_nat_log(softc, softn, nat, logtype); /* * Take it as a general indication that all the pointers are set if * nat_pnext is set. */ if (nat->nat_pnext != NULL) { - nat_stats.ns_bucketlen[0][nat->nat_hv[0]]--; - nat_stats.ns_bucketlen[1][nat->nat_hv[1]]--; + removed = 1; + + bkt = nat->nat_hv[0] % softn->ipf_nat_table_sz; + nss = &softn->ipf_nat_stats.ns_side[0]; + nss->ns_bucketlen[bkt]--; + if (nss->ns_bucketlen[bkt] == 0) { + nss->ns_inuse--; + } + + bkt = nat->nat_hv[1] % softn->ipf_nat_table_sz; + nss = &softn->ipf_nat_stats.ns_side[1]; + nss->ns_bucketlen[bkt]--; + if (nss->ns_bucketlen[bkt] == 0) { + nss->ns_inuse--; + } *nat->nat_pnext = nat->nat_next; if (nat->nat_next != NULL) { @@ -1536,33 +2343,76 @@ int logtype; } nat->nat_phnext[1] = NULL; - if ((nat->nat_flags & SI_WILDP) != 0) - nat_stats.ns_wilds--; + if ((nat->nat_flags & SI_WILDP) != 0) { + ATOMIC_DEC32(softn->ipf_nat_stats.ns_wilds); + } + madeorphan = 1; } if (nat->nat_me != NULL) { *nat->nat_me = NULL; nat->nat_me = NULL; + nat->nat_ref--; + ASSERT(nat->nat_ref >= 0); } - fr_deletequeueentry(&nat->nat_tqe); + if (nat->nat_tqe.tqe_ifq != NULL) { + /* + * No call to ipf_freetimeoutqueue() is made here, they are + * garbage collected in ipf_nat_expire(). + */ + (void) ipf_deletequeueentry(&nat->nat_tqe); + } - nat->nat_ref--; - if (nat->nat_ref > 0) { - MUTEX_EXIT(&ipf_nat_new); + if (nat->nat_sync) { + ipf_sync_del_nat(softc->ipf_sync_soft, nat->nat_sync); + nat->nat_sync = NULL; + } + + if (logtype == NL_EXPIRE) + softn->ipf_nat_stats.ns_expire++; + + MUTEX_ENTER(&nat->nat_lock); + /* + * NL_DESTROY should only be passed in when we've got nat_ref >= 2. + * This happens when a nat'd packet is blocked and we want to throw + * away the NAT session. + */ + if (logtype == NL_DESTROY) { + if (nat->nat_ref > 2) { + nat->nat_ref -= 2; + MUTEX_EXIT(&nat->nat_lock); + if (removed) + softn->ipf_nat_stats.ns_orphans++; + return; + } + } else if (nat->nat_ref > 1) { + nat->nat_ref--; + MUTEX_EXIT(&nat->nat_lock); + if (madeorphan == 1) + softn->ipf_nat_stats.ns_orphans++; return; } + ASSERT(nat->nat_ref >= 0); + MUTEX_EXIT(&nat->nat_lock); -#ifdef IPFILTER_SYNC - if (nat->nat_sync) - ipfsync_del(nat->nat_sync); -#endif + nat->nat_ref = 0; - if (nat->nat_fr != NULL) - (void)fr_derefrule(&nat->nat_fr); + if (madeorphan == 0) + softn->ipf_nat_stats.ns_orphans--; - if (nat->nat_hm != NULL) - nat_hostmapdel(nat->nat_hm); + /* + * At this point, nat_ref can be either 0 or -1 + */ + softn->ipf_nat_stats.ns_proto[nat->nat_pr[0]]--; + + if (nat->nat_fr != NULL) { + (void) ipf_derefrule(softc, &nat->nat_fr); + } + + if (nat->nat_hm != NULL) { + ipf_nat_hostmapdel(softc, &nat->nat_hm); + } /* * If there is an active reference from the nat entry to its parent @@ -1570,50 +2420,51 @@ int logtype; * longer being used. */ ipn = nat->nat_ptr; + nat->nat_ptr = NULL; + if (ipn != NULL) { ipn->in_space++; - ipn->in_use--; - if (ipn->in_use == 0 && (ipn->in_flags & IPN_DELETE)) { - if (ipn->in_apr) - appr_free(ipn->in_apr); - KFREE(ipn); - nat_stats.ns_rules--; -#if SOLARIS - if (nat_stats.ns_rules == 0) - pfil_delayed_copy = 1; -#endif - } + ipf_nat_rule_deref(softc, &ipn); + } + + if (nat->nat_aps != NULL) { + ipf_proxy_free(softc, nat->nat_aps); + nat->nat_aps = NULL; } MUTEX_DESTROY(&nat->nat_lock); - aps_free(nat->nat_aps); - nat_stats.ns_inuse--; - MUTEX_EXIT(&ipf_nat_new); + softn->ipf_nat_stats.ns_active--; /* * If there's a fragment table entry too for this nat entry, then * dereference that as well. This is after nat_lock is released * because of Tru64. */ - fr_forgetnat((void *)nat); + ipf_frag_natforget(softc, (void *)nat); KFREE(nat); } /* ------------------------------------------------------------------------ */ -/* Function: nat_flushtable */ +/* Function: ipf_nat_flushtable */ /* Returns: int - number of NAT rules deleted */ -/* Parameters: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* softn(I) - pointer to NAT context structure */ +/* Write Lock: ipf_nat */ /* */ /* Deletes all currently active NAT sessions. In deleting each NAT entry a */ -/* log record should be emitted in nat_delete() if NAT logging is enabled. */ +/* log record should be emitted in ipf_nat_delete() if NAT logging is */ +/* enabled. */ /* ------------------------------------------------------------------------ */ /* * nat_flushtable - clear the NAT table of all mapping entries. */ -static int nat_flushtable() +static int +ipf_nat_flushtable(softc, softn) + ipf_main_softc_t *softc; + ipf_nat_softc_t *softn; { nat_t *nat; int j = 0; @@ -1622,66 +2473,137 @@ static int nat_flushtable() * ALL NAT mappings deleted, so lets just make the deletions * quicker. */ - if (nat_table[0] != NULL) - bzero((char *)nat_table[0], - sizeof(nat_table[0]) * ipf_nattable_sz); - if (nat_table[1] != NULL) - bzero((char *)nat_table[1], - sizeof(nat_table[1]) * ipf_nattable_sz); - - while ((nat = nat_instances) != NULL) { - nat_delete(nat, NL_FLUSH); + if (softn->ipf_nat_table[0] != NULL) + bzero((char *)softn->ipf_nat_table[0], + sizeof(softn->ipf_nat_table[0]) * + softn->ipf_nat_table_sz); + if (softn->ipf_nat_table[1] != NULL) + bzero((char *)softn->ipf_nat_table[1], + sizeof(softn->ipf_nat_table[1]) * + softn->ipf_nat_table_sz); + + while ((nat = softn->ipf_nat_instances) != NULL) { + ipf_nat_delete(softc, nat, NL_FLUSH); j++; } - nat_stats.ns_inuse = 0; return j; } /* ------------------------------------------------------------------------ */ -/* Function: nat_clearlist */ +/* Function: ipf_nat_clearlist */ /* Returns: int - number of NAT/RDR rules deleted */ -/* Parameters: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* softn(I) - pointer to NAT context structure */ /* */ /* Delete all rules in the current list of rules. There is nothing elegant */ /* about this cleanup: simply free all entries on the list of rules and */ /* clear out the tables used for hashed NAT rule lookups. */ /* ------------------------------------------------------------------------ */ -static int nat_clearlist() +static int +ipf_nat_clearlist(softc, softn) + ipf_main_softc_t *softc; + ipf_nat_softc_t *softn; { - ipnat_t *n, **np = &nat_list; + ipnat_t *n; int i = 0; - if (nat_rules != NULL) - bzero((char *)nat_rules, sizeof(*nat_rules) * ipf_natrules_sz); - if (rdr_rules != NULL) - bzero((char *)rdr_rules, sizeof(*rdr_rules) * ipf_rdrrules_sz); - - while ((n = *np) != NULL) { - *np = n->in_next; - if (n->in_use == 0) { - if (n->in_apr != NULL) - appr_free(n->in_apr); - KFREE(n); - nat_stats.ns_rules--; - } else { - n->in_flags |= IPN_DELETE; - n->in_next = NULL; - } + if (softn->ipf_nat_map_rules != NULL) { + bzero((char *)softn->ipf_nat_map_rules, + sizeof(*softn->ipf_nat_map_rules) * + softn->ipf_nat_maprules_sz); + } + if (softn->ipf_nat_rdr_rules != NULL) { + bzero((char *)softn->ipf_nat_rdr_rules, + sizeof(*softn->ipf_nat_rdr_rules) * + softn->ipf_nat_rdrrules_sz); + } + + while ((n = softn->ipf_nat_list) != NULL) { + ipf_nat_delrule(softc, softn, n, 0); i++; } -#if SOLARIS +#if SOLARIS && !defined(INSTANCES) pfil_delayed_copy = 1; #endif - nat_masks = 0; - rdr_masks = 0; return i; } /* ------------------------------------------------------------------------ */ -/* Function: nat_newmap */ +/* Function: ipf_nat_delrule */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* softn(I) - pointer to NAT context structure */ +/* np(I) - pointer to NAT rule to delete */ +/* purge(I) - 1 == allow purge, 0 == prevent purge */ +/* Locks: WRITE(ipf_nat) */ +/* */ +/* Preventing "purge" from occuring is allowed because when all of the NAT */ +/* rules are being removed, allowing the "purge" to walk through the list */ +/* of NAT sessions, possibly multiple times, would be a large performance */ +/* hit, on the order of O(N^2). */ +/* ------------------------------------------------------------------------ */ +static void +ipf_nat_delrule(softc, softn, np, purge) + ipf_main_softc_t *softc; + ipf_nat_softc_t *softn; + ipnat_t *np; + int purge; +{ + + if (np->in_pnext != NULL) { + *np->in_pnext = np->in_next; + if (np->in_next != NULL) + np->in_next->in_pnext = np->in_pnext; + if (softn->ipf_nat_list_tail == &np->in_next) + softn->ipf_nat_list_tail = np->in_pnext; + } + + if ((purge == 1) && ((np->in_flags & IPN_PURGE) != 0)) { + nat_t *next; + nat_t *nat; + + for (next = softn->ipf_nat_instances; (nat = next) != NULL;) { + next = nat->nat_next; + if (nat->nat_ptr == np) + ipf_nat_delete(softc, nat, NL_PURGE); + } + } + + if ((np->in_flags & IPN_DELETE) == 0) { + if (np->in_redir & NAT_REDIRECT) { + switch (np->in_v[0]) + { + case 4 : + ipf_nat_delrdr(softn, np); + break; + case 6 : + ipf_nat6_delrdr(softn, np); + break; + } + } + if (np->in_redir & (NAT_MAPBLK|NAT_MAP)) { + switch (np->in_v[0]) + { + case 4 : + ipf_nat_delmap(softn, np); + break; + case 6 : + ipf_nat6_delmap(softn, np); + break; + } + } + } + + np->in_flags |= IPN_DELETE; + ipf_nat_rule_deref(softc, &np); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_newmap */ /* Returns: int - -1 == error, 0 == success */ /* Parameters: fin(I) - pointer to packet information */ /* nat(I) - pointer to NAT entry */ @@ -1693,11 +2615,14 @@ static int nat_clearlist() /* ni.nai_ip is passed in uninitialised and must be set, in host byte order,*/ /* to the new IP address for the translation. */ /* ------------------------------------------------------------------------ */ -static INLINE int nat_newmap(fin, nat, ni) -fr_info_t *fin; -nat_t *nat; -natinfo_t *ni; +static int +ipf_nat_newmap(fin, nat, ni) + fr_info_t *fin; + nat_t *nat; + natinfo_t *ni; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; u_short st_port, dport, sport, port, sp, dp; struct in_addr in, inb; hostmap_t *hm; @@ -1714,11 +2639,17 @@ natinfo_t *ni; l = 0; hm = NULL; np = ni->nai_np; - st_ip = np->in_nip; - st_port = np->in_pnext; - flags = ni->nai_flags; - sport = ni->nai_sport; - dport = ni->nai_dport; + st_ip = np->in_snip; + st_port = np->in_spnext; + flags = nat->nat_flags; + + if (flags & IPN_ICMPQUERY) { + sport = fin->fin_data[1]; + dport = 0; + } else { + sport = htons(fin->fin_data[0]); + dport = htons(fin->fin_data[1]); + } /* * Do a loop until we either run out of entries to try or we find @@ -1727,51 +2658,54 @@ natinfo_t *ni; */ do { port = 0; - in.s_addr = htonl(np->in_nip); + in.s_addr = htonl(np->in_snip); if (l == 0) { /* * Check to see if there is an existing NAT * setup for this IP address pair. */ - hm = nat_hostmap(np, fin->fin_src, fin->fin_dst, - in, 0); + hm = ipf_nat_hostmap(softn, np, fin->fin_src, + fin->fin_dst, in, 0); if (hm != NULL) - in.s_addr = hm->hm_mapip.s_addr; + in.s_addr = hm->hm_nsrcip.s_addr; } else if ((l == 1) && (hm != NULL)) { - nat_hostmapdel(hm); - hm = NULL; + ipf_nat_hostmapdel(softc, &hm); } in.s_addr = ntohl(in.s_addr); nat->nat_hm = hm; - if ((np->in_outmsk == 0xffffffff) && (np->in_pnext == 0)) { - if (l > 0) + if ((np->in_nsrcmsk == 0xffffffff) && (np->in_spnext == 0)) { + if (l > 0) { + NBUMPSIDEX(1, ns_exhausted, ns_exhausted_1); return -1; + } } if (np->in_redir == NAT_BIMAP && - np->in_inmsk == np->in_outmsk) { + np->in_osrcmsk == np->in_nsrcmsk) { /* * map the address block in a 1:1 fashion */ - in.s_addr = np->in_outip; - in.s_addr |= fin->fin_saddr & ~np->in_inmsk; + in.s_addr = np->in_nsrcaddr; + in.s_addr |= fin->fin_saddr & ~np->in_osrcmsk; in.s_addr = ntohl(in.s_addr); } else if (np->in_redir & NAT_MAPBLK) { if ((l >= np->in_ppip) || ((l > 0) && - !(flags & IPN_TCPUDP))) + !(flags & IPN_TCPUDP))) { + NBUMPSIDEX(1, ns_exhausted, ns_exhausted_2); return -1; + } /* * map-block - Calculate destination address. */ in.s_addr = ntohl(fin->fin_saddr); - in.s_addr &= ntohl(~np->in_inmsk); + in.s_addr &= ntohl(~np->in_osrcmsk); inb.s_addr = in.s_addr; in.s_addr /= np->in_ippip; - in.s_addr &= ntohl(~np->in_outmsk); - in.s_addr += ntohl(np->in_outip); + in.s_addr &= ntohl(~np->in_nsrcmsk); + in.s_addr += ntohl(np->in_nsrcaddr); /* * Calculate destination port. */ @@ -1785,28 +2719,34 @@ natinfo_t *ni; port = htons(port); } - } else if ((np->in_outip == 0) && - (np->in_outmsk == 0xffffffff)) { + } else if ((np->in_nsrcaddr == 0) && + (np->in_nsrcmsk == 0xffffffff)) { + i6addr_t in6; + /* * 0/32 - use the interface's IP address. */ if ((l > 0) || - fr_ifpaddr(4, FRI_NORMAL, fin->fin_ifp, - &in, NULL) == -1) + ipf_ifpaddr(softc, 4, FRI_NORMAL, fin->fin_ifp, + &in6, NULL) == -1) { + NBUMPSIDEX(1, ns_new_ifpaddr, ns_new_ifpaddr_1); return -1; - in.s_addr = ntohl(in.s_addr); + } + in.s_addr = ntohl(in6.in4.s_addr); - } else if ((np->in_outip == 0) && (np->in_outmsk == 0)) { + } else if ((np->in_nsrcaddr == 0) && (np->in_nsrcmsk == 0)) { /* * 0/0 - use the original source address/port. */ - if (l > 0) + if (l > 0) { + NBUMPSIDEX(1, ns_exhausted, ns_exhausted_3); return -1; + } in.s_addr = ntohl(fin->fin_saddr); - } else if ((np->in_outmsk != 0xffffffff) && - (np->in_pnext == 0) && ((l > 0) || (hm == NULL))) - np->in_nip++; + } else if ((np->in_nsrcmsk != 0xffffffff) && + (np->in_spnext == 0) && ((l > 0) || (hm == NULL))) + np->in_snip++; natl = NULL; @@ -1817,11 +2757,9 @@ natinfo_t *ni; * "ports auto" (without map-block) */ if ((l > 0) && (l % np->in_ppip == 0)) { - if (l > np->in_space) { - return -1; - } else if ((l > np->in_ppip) && - np->in_outmsk != 0xffffffff) - np->in_nip++; + if ((l > np->in_ppip) && + np->in_nsrcmsk != 0xffffffff) + np->in_snip++; } if (np->in_ppip != 0) { port = ntohs(sport); @@ -1835,27 +2773,35 @@ natinfo_t *ni; } } else if (((np->in_redir & NAT_MAPBLK) == 0) && - (flags & IPN_TCPUDPICMP) && (np->in_pnext != 0)) { + (flags & IPN_TCPUDPICMP) && (np->in_spnext != 0)) { /* * Standard port translation. Select next port. */ - port = htons(np->in_pnext++); + if (np->in_flags & IPN_SEQUENTIAL) { + port = np->in_spnext; + } else { + port = ipf_random() % (np->in_spmax - + np->in_spmin + 1); + port += np->in_spmin; + } + port = htons(port); + np->in_spnext++; - if (np->in_pnext > ntohs(np->in_pmax)) { - np->in_pnext = ntohs(np->in_pmin); - if (np->in_outmsk != 0xffffffff) - np->in_nip++; + if (np->in_spnext > np->in_spmax) { + np->in_spnext = np->in_spmin; + if (np->in_nsrcmsk != 0xffffffff) + np->in_snip++; } } - if (np->in_flags & IPN_IPRANGE) { - if (np->in_nip > ntohl(np->in_outmsk)) - np->in_nip = ntohl(np->in_outip); + if (np->in_flags & IPN_SIPRANGE) { + if (np->in_snip > ntohl(np->in_nsrcmsk)) + np->in_snip = ntohl(np->in_nsrcaddr); } else { - if ((np->in_outmsk != 0xffffffff) && - ((np->in_nip + 1) & ntohl(np->in_outmsk)) > - ntohl(np->in_outip)) - np->in_nip = ntohl(np->in_outip) + 1; + if ((np->in_nsrcmsk != 0xffffffff) && + ((np->in_snip + 1) & ntohl(np->in_nsrcmsk)) > + ntohl(np->in_nsrcaddr)) + np->in_snip = ntohl(np->in_nsrcaddr) + 1; } if ((port == 0) && (flags & (IPN_TCPUDPICMP|IPN_ICMPQUERY))) @@ -1875,9 +2821,9 @@ natinfo_t *ni; sp = fin->fin_data[0]; dp = fin->fin_data[1]; fin->fin_data[0] = fin->fin_data[1]; - fin->fin_data[1] = htons(port); - natl = nat_inlookup(fin, flags & ~(SI_WILDP|NAT_SEARCH), - (u_int)fin->fin_p, fin->fin_dst, inb); + fin->fin_data[1] = ntohs(port); + natl = ipf_nat_inlookup(fin, flags & ~(SI_WILDP|NAT_SEARCH), + (u_int)fin->fin_p, fin->fin_dst, inb); fin->fin_data[0] = sp; fin->fin_data[1] = dp; @@ -1886,64 +2832,41 @@ natinfo_t *ni; * start ? */ if ((natl != NULL) && - (np->in_pnext != 0) && (st_port == np->in_pnext) && - (np->in_nip != 0) && (st_ip == np->in_nip)) + (np->in_spnext != 0) && (st_port == np->in_spnext) && + (np->in_snip != 0) && (st_ip == np->in_snip)) { + NBUMPSIDED(1, ns_wrap); return -1; + } l++; } while (natl != NULL); - if (np->in_space > 0) - np->in_space--; - /* Setup the NAT table */ - nat->nat_inip = fin->fin_src; - nat->nat_outip.s_addr = htonl(in.s_addr); - nat->nat_oip = fin->fin_dst; + nat->nat_osrcip = fin->fin_src; + nat->nat_nsrcaddr = htonl(in.s_addr); + nat->nat_odstip = fin->fin_dst; + nat->nat_ndstip = fin->fin_dst; if (nat->nat_hm == NULL) - nat->nat_hm = nat_hostmap(np, fin->fin_src, fin->fin_dst, - nat->nat_outip, 0); - - /* - * The ICMP checksum does not have a pseudo header containing - * the IP addresses - */ - ni->nai_sum1 = LONG_SUM(ntohl(fin->fin_saddr)); - ni->nai_sum2 = LONG_SUM(in.s_addr); - if ((flags & IPN_TCPUDP)) { - ni->nai_sum1 += ntohs(sport); - ni->nai_sum2 += ntohs(port); - } + nat->nat_hm = ipf_nat_hostmap(softn, np, fin->fin_src, + fin->fin_dst, nat->nat_nsrcip, + 0); if (flags & IPN_TCPUDP) { - nat->nat_inport = sport; - nat->nat_outport = port; /* sport */ - nat->nat_oport = dport; + nat->nat_osport = sport; + nat->nat_nsport = port; /* sport */ + nat->nat_odport = dport; + nat->nat_ndport = dport; ((tcphdr_t *)fin->fin_dp)->th_sport = port; } else if (flags & IPN_ICMPQUERY) { + nat->nat_oicmpid = fin->fin_data[1]; ((icmphdr_t *)fin->fin_dp)->icmp_id = port; - nat->nat_inport = port; - nat->nat_outport = port; - } else if (fin->fin_p == IPPROTO_GRE) { -#if 0 - nat->nat_gre.gs_flags = ((grehdr_t *)fin->fin_dp)->gr_flags; - if (GRE_REV(nat->nat_gre.gs_flags) == 1) { - nat->nat_oport = 0;/*fin->fin_data[1];*/ - nat->nat_inport = 0;/*fin->fin_data[0];*/ - nat->nat_outport = 0;/*fin->fin_data[0];*/ - nat->nat_call[0] = fin->fin_data[0]; - nat->nat_call[1] = fin->fin_data[0]; - } -#endif + nat->nat_nicmpid = port; } - ni->nai_ip.s_addr = in.s_addr; - ni->nai_port = port; - ni->nai_nport = dport; return 0; } /* ------------------------------------------------------------------------ */ -/* Function: nat_newrdr */ +/* Function: ipf_nat_newrdr */ /* Returns: int - -1 == error, 0 == success (no move), 1 == success and */ /* allow rule to be moved if IPN_ROUNDR is set. */ /* Parameters: fin(I) - pointer to packet information */ @@ -1954,25 +2877,39 @@ natinfo_t *ni; /* ni.nai_ip is passed in uninitialised and must be set, in host byte order,*/ /* to the new IP address for the translation. */ /* ------------------------------------------------------------------------ */ -static INLINE int nat_newrdr(fin, nat, ni) -fr_info_t *fin; -nat_t *nat; -natinfo_t *ni; +static int +ipf_nat_newrdr(fin, nat, ni) + fr_info_t *fin; + nat_t *nat; + natinfo_t *ni; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; u_short nport, dport, sport; - struct in_addr in; + struct in_addr in, inb; + u_short sp, dp; hostmap_t *hm; u_32_t flags; ipnat_t *np; + nat_t *natl; int move; move = 1; hm = NULL; in.s_addr = 0; np = ni->nai_np; - flags = ni->nai_flags; - sport = ni->nai_sport; - dport = ni->nai_dport; + flags = nat->nat_flags; + + if (flags & IPN_ICMPQUERY) { + dport = fin->fin_data[1]; + sport = 0; + } else { + sport = htons(fin->fin_data[0]); + dport = htons(fin->fin_data[1]); + } + + /* TRACE sport, dport */ + /* * If the matching rule has IPN_STICKY set, then we want to have the @@ -1981,15 +2918,16 @@ natinfo_t *ni; * packet might match a different one to the previous connection but * we want the same destination to be used. */ - if ((np->in_flags & (IPN_ROUNDR|IPN_STICKY)) == - (IPN_ROUNDR|IPN_STICKY)) { - hm = nat_hostmap(NULL, fin->fin_src, fin->fin_dst, in, - (u_32_t)dport); + if (((np->in_flags & (IPN_ROUNDR|IPN_SPLIT)) != 0) && + ((np->in_flags & IPN_STICKY) != 0)) { + hm = ipf_nat_hostmap(softn, NULL, fin->fin_src, fin->fin_dst, + in, (u_32_t)dport); if (hm != NULL) { - in.s_addr = ntohl(hm->hm_mapip.s_addr); + in.s_addr = ntohl(hm->hm_ndstip.s_addr); np = hm->hm_ipnat; ni->nai_np = np; move = 0; + ipf_nat_hostmapdel(softc, &hm); } } @@ -2000,53 +2938,60 @@ natinfo_t *ni; * internal port. */ if (np->in_flags & IPN_SPLIT) { - in.s_addr = np->in_nip; + in.s_addr = np->in_dnip; if ((np->in_flags & (IPN_ROUNDR|IPN_STICKY)) == IPN_STICKY) { - hm = nat_hostmap(np, fin->fin_src, fin->fin_dst, - in, (u_32_t)dport); + hm = ipf_nat_hostmap(softn, NULL, fin->fin_src, + fin->fin_dst, in, (u_32_t)dport); if (hm != NULL) { - in.s_addr = hm->hm_mapip.s_addr; + in.s_addr = hm->hm_ndstip.s_addr; move = 0; } } if (hm == NULL || hm->hm_ref == 1) { - if (np->in_inip == htonl(in.s_addr)) { - np->in_nip = ntohl(np->in_inmsk); + if (np->in_ndstaddr == htonl(in.s_addr)) { + np->in_dnip = ntohl(np->in_ndstmsk); move = 0; } else { - np->in_nip = ntohl(np->in_inip); + np->in_dnip = ntohl(np->in_ndstaddr); } } + if (hm != NULL) + ipf_nat_hostmapdel(softc, &hm); + + } else if ((np->in_ndstaddr == 0) && (np->in_ndstmsk == 0xffffffff)) { + i6addr_t in6; - } else if ((np->in_inip == 0) && (np->in_inmsk == 0xffffffff)) { /* * 0/32 - use the interface's IP address. */ - if (fr_ifpaddr(4, FRI_NORMAL, fin->fin_ifp, &in, NULL) == -1) + if (ipf_ifpaddr(softc, 4, FRI_NORMAL, fin->fin_ifp, + &in6, NULL) == -1) { + NBUMPSIDEX(0, ns_new_ifpaddr, ns_new_ifpaddr_2); return -1; - in.s_addr = ntohl(in.s_addr); + } + in.s_addr = ntohl(in6.in4.s_addr); - } else if ((np->in_inip == 0) && (np->in_inmsk== 0)) { + } else if ((np->in_ndstaddr == 0) && (np->in_ndstmsk== 0)) { /* * 0/0 - use the original destination address/port. */ in.s_addr = ntohl(fin->fin_daddr); } else if (np->in_redir == NAT_BIMAP && - np->in_inmsk == np->in_outmsk) { + np->in_ndstmsk == np->in_odstmsk) { /* * map the address block in a 1:1 fashion */ - in.s_addr = np->in_inip; - in.s_addr |= fin->fin_daddr & ~np->in_inmsk; + in.s_addr = np->in_ndstaddr; + in.s_addr |= fin->fin_daddr & ~np->in_ndstmsk; in.s_addr = ntohl(in.s_addr); } else { - in.s_addr = ntohl(np->in_inip); + in.s_addr = ntohl(np->in_ndstaddr); } - if ((np->in_pnext == 0) || ((flags & NAT_NOTRULEPORT) != 0)) + if ((np->in_dpnext == 0) || ((flags & NAT_NOTRULEPORT) != 0)) nport = dport; else { /* @@ -2054,12 +2999,15 @@ natinfo_t *ni; * pmin == pmax, the gain is not significant. */ if (((np->in_flags & IPN_FIXEDDPORT) == 0) && - (np->in_pmin != np->in_pmax)) { - nport = ntohs(dport) - ntohs(np->in_pmin) + - ntohs(np->in_pnext); + (np->in_odport != np->in_dtop)) { + nport = ntohs(dport) - np->in_odport + np->in_dpmax; nport = htons(nport); - } else - nport = np->in_pnext; + } else { + nport = htons(np->in_dpnext); + np->in_dpnext++; + if (np->in_dpnext > np->in_dpmax) + np->in_dpnext = np->in_dpmin; + } } /* @@ -2068,49 +3016,58 @@ natinfo_t *ni; * setup any translation for this either. */ if (in.s_addr == 0) { - if (nport == dport) + if (nport == dport) { + NBUMPSIDED(0, ns_xlate_null); return -1; + } in.s_addr = ntohl(fin->fin_daddr); } - nat->nat_inip.s_addr = htonl(in.s_addr); - nat->nat_outip = fin->fin_dst; - nat->nat_oip = fin->fin_src; - - ni->nai_sum1 = LONG_SUM(ntohl(fin->fin_daddr)) + ntohs(dport); - ni->nai_sum2 = LONG_SUM(in.s_addr) + ntohs(nport); + /* + * Check to see if this redirect mapping already exists and if + * it does, return "failure" (allowing it to be created will just + * cause one or both of these "connections" to stop working.) + */ + inb.s_addr = htonl(in.s_addr); + sp = fin->fin_data[0]; + dp = fin->fin_data[1]; + fin->fin_data[1] = fin->fin_data[0]; + fin->fin_data[0] = ntohs(nport); + natl = ipf_nat_outlookup(fin, flags & ~(SI_WILDP|NAT_SEARCH), + (u_int)fin->fin_p, inb, fin->fin_src); + fin->fin_data[0] = sp; + fin->fin_data[1] = dp; + if (natl != NULL) { + DT2(ns_new_xlate_exists, fr_info_t *, fin, nat_t *, natl); + NBUMPSIDE(0, ns_xlate_exists); + return -1; + } - ni->nai_ip.s_addr = in.s_addr; - ni->nai_nport = nport; - ni->nai_port = sport; + nat->nat_ndstaddr = htonl(in.s_addr); + nat->nat_odstip = fin->fin_dst; + nat->nat_nsrcip = fin->fin_src; + nat->nat_osrcip = fin->fin_src; + if ((nat->nat_hm == NULL) && ((np->in_flags & IPN_STICKY) != 0)) + nat->nat_hm = ipf_nat_hostmap(softn, np, fin->fin_src, + fin->fin_dst, in, (u_32_t)dport); if (flags & IPN_TCPUDP) { - nat->nat_inport = nport; - nat->nat_outport = dport; - nat->nat_oport = sport; + nat->nat_odport = dport; + nat->nat_ndport = nport; + nat->nat_osport = sport; + nat->nat_nsport = sport; ((tcphdr_t *)fin->fin_dp)->th_dport = nport; } else if (flags & IPN_ICMPQUERY) { + nat->nat_oicmpid = fin->fin_data[1]; ((icmphdr_t *)fin->fin_dp)->icmp_id = nport; - nat->nat_inport = nport; - nat->nat_outport = nport; - } else if (fin->fin_p == IPPROTO_GRE) { -#if 0 - nat->nat_gre.gs_flags = ((grehdr_t *)fin->fin_dp)->gr_flags; - if (GRE_REV(nat->nat_gre.gs_flags) == 1) { - nat->nat_call[0] = fin->fin_data[0]; - nat->nat_call[1] = fin->fin_data[1]; - nat->nat_oport = 0; /*fin->fin_data[0];*/ - nat->nat_inport = 0; /*fin->fin_data[1];*/ - nat->nat_outport = 0; /*fin->fin_data[1];*/ - } -#endif + nat->nat_nicmpid = nport; } return move; } /* ------------------------------------------------------------------------ */ -/* Function: nat_new */ +/* Function: ipf_nat_add */ /* Returns: nat_t* - NULL == failure to create new NAT structure, */ /* else pointer to new NAT structure */ /* Parameters: fin(I) - pointer to packet information */ @@ -2127,29 +3084,36 @@ natinfo_t *ni; /* structure for a "MAP" rule (outgoing NAT translation); (2) deal with */ /* creating a new NAT structure for a "RDR" rule (incoming NAT translation) */ /* and (3) building that structure and putting it into the NAT table(s). */ +/* */ +/* NOTE: natsave should NOT be used top point back to an ipstate_t struct */ +/* as it can result in memory being corrupted. */ /* ------------------------------------------------------------------------ */ -nat_t *nat_new(fin, np, natsave, flags, direction) -fr_info_t *fin; -ipnat_t *np; -nat_t **natsave; -u_int flags; -int direction; +nat_t * +ipf_nat_add(fin, np, natsave, flags, direction) + fr_info_t *fin; + ipnat_t *np; + nat_t **natsave; + u_int flags; + int direction; { - u_short port = 0, sport = 0, dport = 0, nport = 0; - tcphdr_t *tcp = NULL; + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; hostmap_t *hm = NULL; - struct in_addr in; nat_t *nat, *natl; + natstat_t *nsp; u_int nflags; natinfo_t ni; - u_32_t sumd; int move; -#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) && defined(ICK_M_CTL_MAGIC) - qpktinfo_t *qpi = fin->fin_qpi; -#endif - if (nat_stats.ns_inuse >= ipf_nattable_max) { - nat_stats.ns_memfail++; + nsp = &softn->ipf_nat_stats; + + if ((nsp->ns_active * 100 / softn->ipf_nat_table_max) > + softn->ipf_nat_table_wm_high) { + softn->ipf_nat_doflush = 1; + } + + if (nsp->ns_active >= softn->ipf_nat_table_max) { + NBUMPSIDED(fin->fin_out, ns_table_max); return NULL; } @@ -2158,32 +3122,29 @@ int direction; nflags &= NAT_FROMRULE; ni.nai_np = np; - ni.nai_nflags = nflags; - ni.nai_flags = flags; + ni.nai_dport = 0; + ni.nai_sport = 0; /* Give me a new nat */ KMALLOC(nat, nat_t *); if (nat == NULL) { - nat_stats.ns_memfail++; + NBUMPSIDED(fin->fin_out, ns_memfail); /* * Try to automatically tune the max # of entries in the * table allowed to be less than what will cause kmem_alloc() * to fail and try to eliminate panics due to out of memory * conditions arising. */ - if (ipf_nattable_max > ipf_nattable_sz) { - ipf_nattable_max = nat_stats.ns_inuse - 100; - printf("ipf_nattable_max reduced to %d\n", - ipf_nattable_max); + if ((softn->ipf_nat_table_max > softn->ipf_nat_table_sz) && + (nsp->ns_active > 100)) { + softn->ipf_nat_table_max = nsp->ns_active - 100; + printf("table_max reduced to %d\n", + softn->ipf_nat_table_max); } return NULL; } - if (flags & IPN_TCPUDP) { - tcp = fin->fin_dp; - ni.nai_sport = htons(fin->fin_sport); - ni.nai_dport = htons(fin->fin_dport); - } else if (flags & IPN_ICMPQUERY) { + if (flags & IPN_ICMPQUERY) { /* * In the ICMP query NAT code, we translate the ICMP id fields * to make them unique. This is indepedent of the ICMP type @@ -2197,182 +3158,219 @@ int direction; * the concept of source port. We overlay sport, so we can * maximally reuse the existing code. */ - ni.nai_sport = ((icmphdr_t *)fin->fin_dp)->icmp_id; - ni.nai_dport = ni.nai_sport; + ni.nai_sport = fin->fin_data[1]; + ni.nai_dport = 0; } bzero((char *)nat, sizeof(*nat)); nat->nat_flags = flags; - - if ((flags & NAT_SLAVE) == 0) { - MUTEX_ENTER(&ipf_nat_new); - } + nat->nat_redir = np->in_redir; + nat->nat_dir = direction; + nat->nat_pr[0] = fin->fin_p; + nat->nat_pr[1] = fin->fin_p; /* - * Search the current table for a match. + * Search the current table for a match and create a new mapping + * if there is none found. */ - if (direction == NAT_OUTBOUND) { + if (np->in_redir & NAT_DIVERTUDP) { + move = ipf_nat_newdivert(fin, nat, &ni); + + } else if (np->in_redir & NAT_REWRITE) { + move = ipf_nat_newrewrite(fin, nat, &ni); + + } else if (direction == NAT_OUTBOUND) { /* * We can now arrange to call this for the same connection * because ipf_nat_new doesn't protect the code path into * this function. */ - natl = nat_outlookup(fin, nflags, (u_int)fin->fin_p, + natl = ipf_nat_outlookup(fin, nflags, (u_int)fin->fin_p, fin->fin_src, fin->fin_dst); if (natl != NULL) { + KFREE(nat); nat = natl; goto done; } - move = nat_newmap(fin, nat, &ni); - if (move == -1) - goto badnat; - - np = ni.nai_np; - in = ni.nai_ip; + move = ipf_nat_newmap(fin, nat, &ni); } else { /* - * NAT_INBOUND is used only for redirects rules + * NAT_INBOUND is used for redirects rules */ - natl = nat_inlookup(fin, nflags, (u_int)fin->fin_p, - fin->fin_src, fin->fin_dst); + natl = ipf_nat_inlookup(fin, nflags, (u_int)fin->fin_p, + fin->fin_src, fin->fin_dst); if (natl != NULL) { + KFREE(nat); nat = natl; goto done; } - move = nat_newrdr(fin, nat, &ni); - if (move == -1) - goto badnat; - - np = ni.nai_np; - in = ni.nai_ip; + move = ipf_nat_newrdr(fin, nat, &ni); } - port = ni.nai_port; - nport = ni.nai_nport; + if (move == -1) + goto badnat; - if ((move == 1) && (np->in_flags & IPN_ROUNDR)) { - if (np->in_redir == NAT_REDIRECT) { - nat_delrdr(np); - nat_addrdr(np); - } else if (np->in_redir == NAT_MAP) { - nat_delnat(np); - nat_addnat(np); + np = ni.nai_np; + + nat->nat_mssclamp = np->in_mssclamp; + nat->nat_me = natsave; + nat->nat_fr = fin->fin_fr; + nat->nat_rev = fin->fin_rev; + nat->nat_ptr = np; + nat->nat_dlocal = np->in_dlocal; + + if ((np->in_apr != NULL) && ((nat->nat_flags & NAT_SLAVE) == 0)) { + if (ipf_proxy_new(fin, nat) == -1) { + NBUMPSIDED(fin->fin_out, ns_appr_fail); + goto badnat; } } - if (flags & IPN_TCPUDP) { - sport = ni.nai_sport; - dport = ni.nai_dport; - } else if (flags & IPN_ICMPQUERY) { - sport = ni.nai_sport; - dport = 0; + nat->nat_ifps[0] = np->in_ifps[0]; + if (np->in_ifps[0] != NULL) { + COPYIFNAME(np->in_v[0], np->in_ifps[0], nat->nat_ifnames[0]); } - CALC_SUMD(ni.nai_sum1, ni.nai_sum2, sumd); - nat->nat_sumd[0] = (sumd & 0xffff) + (sumd >> 16); -#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) && defined(ICK_M_CTL_MAGIC) - if ((flags & IPN_TCP) && dohwcksum && - (((ill_t *)qpi->qpi_ill)->ill_ick.ick_magic == ICK_M_CTL_MAGIC)) { - if (direction == NAT_OUTBOUND) - ni.nai_sum1 = LONG_SUM(in.s_addr); - else - ni.nai_sum1 = LONG_SUM(ntohl(fin->fin_saddr)); - ni.nai_sum1 += LONG_SUM(ntohl(fin->fin_daddr)); - ni.nai_sum1 += 30; - ni.nai_sum1 = (ni.nai_sum1 & 0xffff) + (ni.nai_sum1 >> 16); - nat->nat_sumd[1] = NAT_HW_CKSUM|(ni.nai_sum1 & 0xffff); - } else -#endif - nat->nat_sumd[1] = nat->nat_sumd[0]; + nat->nat_ifps[1] = np->in_ifps[1]; + if (np->in_ifps[1] != NULL) { + COPYIFNAME(np->in_v[1], np->in_ifps[1], nat->nat_ifnames[1]); + } - if ((flags & IPN_TCPUDPICMP) && ((sport != port) || (dport != nport))) { - if (direction == NAT_OUTBOUND) - ni.nai_sum1 = LONG_SUM(ntohl(fin->fin_saddr)); - else - ni.nai_sum1 = LONG_SUM(ntohl(fin->fin_daddr)); + if (ipf_nat_finalise(fin, nat) == -1) { + goto badnat; + } - ni.nai_sum2 = LONG_SUM(in.s_addr); + np->in_use++; - CALC_SUMD(ni.nai_sum1, ni.nai_sum2, sumd); - nat->nat_ipsumd = (sumd & 0xffff) + (sumd >> 16); - } else { - nat->nat_ipsumd = nat->nat_sumd[0]; - if (!(flags & IPN_TCPUDPICMP)) { - nat->nat_sumd[0] = 0; - nat->nat_sumd[1] = 0; + if ((move == 1) && (np->in_flags & IPN_ROUNDR)) { + if ((np->in_redir & (NAT_REDIRECT|NAT_MAP)) == NAT_REDIRECT) { + ipf_nat_delrdr(softn, np); + ipf_nat_addrdr(softn, np); + } else if ((np->in_redir & (NAT_REDIRECT|NAT_MAP)) == NAT_MAP) { + ipf_nat_delmap(softn, np); + ipf_nat_addmap(softn, np); } } - if (nat_finalise(fin, nat, &ni, tcp, natsave, direction) == -1) { - goto badnat; - } if (flags & SI_WILDP) - nat_stats.ns_wilds++; + nsp->ns_wilds++; + nsp->ns_proto[nat->nat_pr[0]]++; + goto done; badnat: - nat_stats.ns_badnat++; + DT2(ns_badnatnew, fr_info_t *, fin, nat_t *, nat); + NBUMPSIDE(fin->fin_out, ns_badnatnew); if ((hm = nat->nat_hm) != NULL) - nat_hostmapdel(hm); + ipf_nat_hostmapdel(softc, &hm); KFREE(nat); nat = NULL; done: - if ((flags & NAT_SLAVE) == 0) { - MUTEX_EXIT(&ipf_nat_new); - } + if (nat != NULL && np != NULL) + np->in_hits++; + if (natsave != NULL) + *natsave = nat; return nat; } /* ------------------------------------------------------------------------ */ -/* Function: nat_finalise */ +/* Function: ipf_nat_finalise */ /* Returns: int - 0 == sucess, -1 == failure */ /* Parameters: fin(I) - pointer to packet information */ /* nat(I) - pointer to NAT entry */ -/* ni(I) - pointer to structure with misc. information needed */ -/* to create new NAT entry. */ /* Write Lock: ipf_nat */ /* */ /* This is the tail end of constructing a new NAT entry and is the same */ /* for both IPv4 and IPv6. */ /* ------------------------------------------------------------------------ */ /*ARGSUSED*/ -static INLINE int nat_finalise(fin, nat, ni, tcp, natsave, direction) -fr_info_t *fin; -nat_t *nat; -natinfo_t *ni; -tcphdr_t *tcp; -nat_t **natsave; -int direction; +static int +ipf_nat_finalise(fin, nat) + fr_info_t *fin; + nat_t *nat; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + u_32_t sum1, sum2, sumd; frentry_t *fr; - ipnat_t *np; + u_32_t flags; +#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) && defined(ICK_M_CTL_MAGIC) + qpktinfo_t *qpi = fin->fin_qpi; +#endif - np = ni->nai_np; + flags = nat->nat_flags; - COPYIFNAME(fin->fin_ifp, nat->nat_ifnames[0]); -#ifdef IPFILTER_SYNC - if ((nat->nat_flags & SI_CLONE) == 0) - nat->nat_sync = ipfsync_new(SMC_NAT, fin, nat); -#endif + switch (nat->nat_pr[0]) + { + case IPPROTO_ICMP : + sum1 = LONG_SUM(ntohs(nat->nat_oicmpid)); + sum2 = LONG_SUM(ntohs(nat->nat_nicmpid)); + CALC_SUMD(sum1, sum2, sumd); + nat->nat_sumd[0] = (sumd & 0xffff) + (sumd >> 16); - nat->nat_me = natsave; - nat->nat_dir = direction; - nat->nat_ifps[0] = fin->fin_ifp; - nat->nat_ptr = np; - nat->nat_p = fin->fin_p; - nat->nat_mssclamp = np->in_mssclamp; - fr = fin->fin_fr; - nat->nat_fr = fr; + break; - if ((np->in_apr != NULL) && ((ni->nai_flags & NAT_SLAVE) == 0)) - if (appr_new(fin, nat) == -1) - return -1; + default : + sum1 = LONG_SUM(ntohl(nat->nat_osrcaddr) + \ + ntohs(nat->nat_osport)); + sum2 = LONG_SUM(ntohl(nat->nat_nsrcaddr) + \ + ntohs(nat->nat_nsport)); + CALC_SUMD(sum1, sum2, sumd); + nat->nat_sumd[0] = (sumd & 0xffff) + (sumd >> 16); - if (nat_insert(nat, fin->fin_rev) == 0) { - if (nat_logging) - nat_log(nat, (u_int)np->in_redir); - np->in_use++; + sum1 = LONG_SUM(ntohl(nat->nat_odstaddr) + \ + ntohs(nat->nat_odport)); + sum2 = LONG_SUM(ntohl(nat->nat_ndstaddr) + \ + ntohs(nat->nat_ndport)); + CALC_SUMD(sum1, sum2, sumd); + nat->nat_sumd[0] += (sumd & 0xffff) + (sumd >> 16); + break; + } + + /* + * Compute the partial checksum, just in case. + * This is only ever placed into outbound packets so care needs + * to be taken over which pair of addresses are used. + */ + if (nat->nat_dir == NAT_OUTBOUND) { + sum1 = LONG_SUM(ntohl(nat->nat_nsrcaddr)); + sum1 += LONG_SUM(ntohl(nat->nat_ndstaddr)); + } else { + sum1 = LONG_SUM(ntohl(nat->nat_osrcaddr)); + sum1 += LONG_SUM(ntohl(nat->nat_odstaddr)); + } + sum1 += nat->nat_pr[1]; + nat->nat_sumd[1] = (sum1 & 0xffff) + (sum1 >> 16); + + sum1 = LONG_SUM(ntohl(nat->nat_osrcaddr)); + sum2 = LONG_SUM(ntohl(nat->nat_nsrcaddr)); + CALC_SUMD(sum1, sum2, sumd); + nat->nat_ipsumd = (sumd & 0xffff) + (sumd >> 16); + + sum1 = LONG_SUM(ntohl(nat->nat_odstaddr)); + sum2 = LONG_SUM(ntohl(nat->nat_ndstaddr)); + CALC_SUMD(sum1, sum2, sumd); + nat->nat_ipsumd += (sumd & 0xffff) + (sumd >> 16); + + nat->nat_v[0] = 4; + nat->nat_v[1] = 4; + + if ((nat->nat_ifps[0] != NULL) && (nat->nat_ifps[0] != (void *)-1)) { + nat->nat_mtu[0] = GETIFMTU_4(nat->nat_ifps[0]); + } + + if ((nat->nat_ifps[1] != NULL) && (nat->nat_ifps[1] != (void *)-1)) { + nat->nat_mtu[1] = GETIFMTU_4(nat->nat_ifps[1]); + } + + if ((nat->nat_flags & SI_CLONE) == 0) + nat->nat_sync = ipf_sync_new(softc, SMC_NAT, fin, nat); + + if (ipf_nat_insert(softc, softn, nat) == 0) { + if (softn->ipf_nat_logging) + ipf_nat_log(softc, softn, nat, NL_NEW); + fr = nat->nat_fr; if (fr != NULL) { MUTEX_ENTER(&fr->fr_lock); fr->fr_ref++; @@ -2381,112 +3379,224 @@ int direction; return 0; } + NBUMPSIDED(fin->fin_out, ns_unfinalised); /* * nat_insert failed, so cleanup time... */ + if (nat->nat_sync != NULL) + ipf_sync_del_nat(softc->ipf_sync_soft, nat->nat_sync); return -1; } /* ------------------------------------------------------------------------ */ -/* Function: nat_insert */ -/* Returns: int - 0 == sucess, -1 == failure */ -/* Parameters: nat(I) - pointer to NAT structure */ -/* rev(I) - flag indicating forward/reverse direction of packet */ -/* Write Lock: ipf_nat */ +/* Function: ipf_nat_insert */ +/* Returns: int - 0 == sucess, -1 == failure */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* softn(I) - pointer to NAT context structure */ +/* nat(I) - pointer to NAT structure */ +/* Write Lock: ipf_nat */ /* */ /* Insert a NAT entry into the hash tables for searching and add it to the */ /* list of active NAT entries. Adjust global counters when complete. */ /* ------------------------------------------------------------------------ */ -int nat_insert(nat, rev) -nat_t *nat; -int rev; +int +ipf_nat_insert(softc, softn, nat) + ipf_main_softc_t *softc; + ipf_nat_softc_t *softn; + nat_t *nat; { - u_int hv1, hv2; - nat_t **natp; + u_int hv0, hv1; + u_int sp, dp; + ipnat_t *in; /* * Try and return an error as early as possible, so calculate the hash * entry numbers first and then proceed. */ if ((nat->nat_flags & (SI_W_SPORT|SI_W_DPORT)) == 0) { - hv1 = NAT_HASH_FN(nat->nat_inip.s_addr, nat->nat_inport, - 0xffffffff); - hv1 = NAT_HASH_FN(nat->nat_oip.s_addr, hv1 + nat->nat_oport, - ipf_nattable_sz); - hv2 = NAT_HASH_FN(nat->nat_outip.s_addr, nat->nat_outport, - 0xffffffff); - hv2 = NAT_HASH_FN(nat->nat_oip.s_addr, hv2 + nat->nat_oport, - ipf_nattable_sz); + if ((nat->nat_flags & IPN_TCPUDP) != 0) { + sp = nat->nat_osport; + dp = nat->nat_odport; + } else if ((nat->nat_flags & IPN_ICMPQUERY) != 0) { + sp = 0; + dp = nat->nat_oicmpid; + } else { + sp = 0; + dp = 0; + } + hv0 = NAT_HASH_FN(nat->nat_osrcaddr, sp, 0xffffffff); + hv0 = NAT_HASH_FN(nat->nat_odstaddr, hv0 + dp, 0xffffffff); + /* + * TRACE nat_osrcaddr, nat_osport, nat_odstaddr, + * nat_odport, hv0 + */ + + if ((nat->nat_flags & IPN_TCPUDP) != 0) { + sp = nat->nat_nsport; + dp = nat->nat_ndport; + } else if ((nat->nat_flags & IPN_ICMPQUERY) != 0) { + sp = 0; + dp = nat->nat_nicmpid; + } else { + sp = 0; + dp = 0; + } + hv1 = NAT_HASH_FN(nat->nat_nsrcaddr, sp, 0xffffffff); + hv1 = NAT_HASH_FN(nat->nat_ndstaddr, hv1 + dp, 0xffffffff); + /* + * TRACE nat_nsrcaddr, nat_nsport, nat_ndstaddr, + * nat_ndport, hv1 + */ } else { - hv1 = NAT_HASH_FN(nat->nat_inip.s_addr, 0, 0xffffffff); - hv1 = NAT_HASH_FN(nat->nat_oip.s_addr, hv1, ipf_nattable_sz); - hv2 = NAT_HASH_FN(nat->nat_outip.s_addr, 0, 0xffffffff); - hv2 = NAT_HASH_FN(nat->nat_oip.s_addr, hv2, ipf_nattable_sz); - } + hv0 = NAT_HASH_FN(nat->nat_osrcaddr, 0, 0xffffffff); + hv0 = NAT_HASH_FN(nat->nat_odstaddr, hv0, 0xffffffff); + /* TRACE nat_osrcaddr, nat_odstaddr, hv0 */ - if (nat_stats.ns_bucketlen[0][hv1] >= fr_nat_maxbucket || - nat_stats.ns_bucketlen[1][hv2] >= fr_nat_maxbucket) { - return -1; + hv1 = NAT_HASH_FN(nat->nat_nsrcaddr, 0, 0xffffffff); + hv1 = NAT_HASH_FN(nat->nat_ndstaddr, hv1, 0xffffffff); + /* TRACE nat_nsrcaddr, nat_ndstaddr, hv1 */ } - nat->nat_hv[0] = hv1; - nat->nat_hv[1] = hv2; + nat->nat_hv[0] = hv0; + nat->nat_hv[1] = hv1; MUTEX_INIT(&nat->nat_lock, "nat entry lock"); - nat->nat_rev = rev; - nat->nat_ref = 1; - nat->nat_bytes[0] = 0; - nat->nat_pkts[0] = 0; - nat->nat_bytes[1] = 0; - nat->nat_pkts[1] = 0; + in = nat->nat_ptr; + nat->nat_ref = nat->nat_me ? 2 : 1; nat->nat_ifnames[0][LIFNAMSIZ - 1] = '\0'; - nat->nat_ifps[0] = fr_resolvenic(nat->nat_ifnames[0], 4); + nat->nat_ifps[0] = ipf_resolvenic(softc, nat->nat_ifnames[0], 4); - if (nat->nat_ifnames[1][0] !='\0') { + if (nat->nat_ifnames[1][0] != '\0') { nat->nat_ifnames[1][LIFNAMSIZ - 1] = '\0'; - nat->nat_ifps[1] = fr_resolvenic(nat->nat_ifnames[1], 4); - } else { - (void) strncpy(nat->nat_ifnames[1], nat->nat_ifnames[0], - LIFNAMSIZ); - nat->nat_ifnames[1][LIFNAMSIZ - 1] = '\0'; - nat->nat_ifps[1] = nat->nat_ifps[0]; + nat->nat_ifps[1] = ipf_resolvenic(softc, + nat->nat_ifnames[1], 4); + } else if (in->in_ifnames[1] != -1) { + char *name; + + name = in->in_names + in->in_ifnames[1]; + if (name[1] != '\0' && name[0] != '-' && name[0] != '*') { + (void) strncpy(nat->nat_ifnames[1], + nat->nat_ifnames[0], LIFNAMSIZ); + nat->nat_ifnames[1][LIFNAMSIZ - 1] = '\0'; + nat->nat_ifps[1] = nat->nat_ifps[0]; + } + } + if ((nat->nat_ifps[0] != NULL) && (nat->nat_ifps[0] != (void *)-1)) { + nat->nat_mtu[0] = GETIFMTU_4(nat->nat_ifps[0]); + } + if ((nat->nat_ifps[1] != NULL) && (nat->nat_ifps[1] != (void *)-1)) { + nat->nat_mtu[1] = GETIFMTU_4(nat->nat_ifps[1]); } - nat->nat_next = nat_instances; - nat->nat_pnext = &nat_instances; - if (nat_instances) - nat_instances->nat_pnext = &nat->nat_next; - nat_instances = nat; + return ipf_nat_hashtab_add(softc, softn, nat); +} - natp = &nat_table[0][hv1]; - if (*natp) - (*natp)->nat_phnext[0] = &nat->nat_hnext[0]; + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_hashtab_add */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* softn(I) - pointer to NAT context structure */ +/* nat(I) - pointer to NAT structure */ +/* */ +/* Handle the insertion of a NAT entry into the table/list. */ +/* ------------------------------------------------------------------------ */ +int +ipf_nat_hashtab_add(softc, softn, nat) + ipf_main_softc_t *softc; + ipf_nat_softc_t *softn; + nat_t *nat; +{ + nat_t **natp; + u_int hv0; + u_int hv1; + + hv0 = nat->nat_hv[0] % softn->ipf_nat_table_sz; + hv1 = nat->nat_hv[1] % softn->ipf_nat_table_sz; + + if (nat->nat_dir == NAT_INBOUND || nat->nat_dir == NAT_DIVERTIN) { + u_int swap; + + swap = hv0; + hv0 = hv1; + hv1 = swap; + } + + if (softn->ipf_nat_stats.ns_side[0].ns_bucketlen[hv0] >= + softn->ipf_nat_maxbucket) { + DT1(ns_bucket_max_0, int, + softn->ipf_nat_stats.ns_side[0].ns_bucketlen[hv0]); + NBUMPSIDE(0, ns_bucket_max); + return -1; + } + + if (softn->ipf_nat_stats.ns_side[1].ns_bucketlen[hv1] >= + softn->ipf_nat_maxbucket) { + DT1(ns_bucket_max_1, int, + softn->ipf_nat_stats.ns_side[1].ns_bucketlen[hv1]); + NBUMPSIDE(1, ns_bucket_max); + return -1; + } + + /* + * The ordering of operations in the list and hash table insertion + * is very important. The last operation for each task should be + * to update the top of the list, after all the "nexts" have been + * done so that walking the list while it is being done does not + * find strange pointers. + * + * Global list of NAT instances + */ + nat->nat_next = softn->ipf_nat_instances; + nat->nat_pnext = &softn->ipf_nat_instances; + if (softn->ipf_nat_instances) + softn->ipf_nat_instances->nat_pnext = &nat->nat_next; + softn->ipf_nat_instances = nat; + + /* + * Inbound hash table. + */ + natp = &softn->ipf_nat_table[0][hv0]; nat->nat_phnext[0] = natp; nat->nat_hnext[0] = *natp; + if (*natp) { + (*natp)->nat_phnext[0] = &nat->nat_hnext[0]; + } else { + NBUMPSIDE(0, ns_inuse); + } *natp = nat; - nat_stats.ns_bucketlen[0][hv1]++; + NBUMPSIDE(0, ns_bucketlen[hv0]); - natp = &nat_table[1][hv2]; - if (*natp) - (*natp)->nat_phnext[1] = &nat->nat_hnext[1]; + /* + * Outbound hash table. + */ + natp = &softn->ipf_nat_table[1][hv1]; nat->nat_phnext[1] = natp; nat->nat_hnext[1] = *natp; + if (*natp) + (*natp)->nat_phnext[1] = &nat->nat_hnext[1]; + else { + NBUMPSIDE(1, ns_inuse); + } *natp = nat; - nat_stats.ns_bucketlen[1][hv2]++; + NBUMPSIDE(1, ns_bucketlen[hv1]); - fr_setnatqueue(nat, rev); + ipf_nat_setqueue(softc, softn, nat); - nat_stats.ns_added++; - nat_stats.ns_inuse++; + if (nat->nat_dir & NAT_OUTBOUND) { + NBUMPSIDE(1, ns_added); + } else { + NBUMPSIDE(0, ns_added); + } + softn->ipf_nat_stats.ns_active++; return 0; } /* ------------------------------------------------------------------------ */ -/* Function: nat_icmperrorlookup */ +/* Function: ipf_nat_icmperrorlookup */ /* Returns: nat_t* - point to matching NAT structure */ /* Parameters: fin(I) - pointer to packet information */ /* dir(I) - direction of packet (in/out) */ @@ -2495,12 +3605,16 @@ int rev; /* ICMP query nat entry. It is assumed that the packet is already of the */ /* the required length. */ /* ------------------------------------------------------------------------ */ -nat_t *nat_icmperrorlookup(fin, dir) -fr_info_t *fin; -int dir; +nat_t * +ipf_nat_icmperrorlookup(fin, dir) + fr_info_t *fin; + int dir; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; int flags = 0, type, minlen; icmphdr_t *icmp, *orgicmp; + nat_stat_side_t *nside; tcphdr_t *tcp = NULL; u_short data[2]; nat_t *nat; @@ -2509,14 +3623,16 @@ int dir; icmp = fin->fin_dp; type = icmp->icmp_type; + nside = &softn->ipf_nat_stats.ns_side[fin->fin_out]; /* * Does it at least have the return (basic) IP header ? * Only a basic IP header (no options) should be with an ICMP error * header. Also, if it's not an error type, then return. */ - if ((fin->fin_hlen != sizeof(ip_t)) || - !fr_icmp4errortype(type)) + if ((fin->fin_hlen != sizeof(ip_t)) || !(fin->fin_flx & FI_ICMPERR)) { + ATOMIC_INCL(nside->ns_icmp_basic); return NULL; + } /* * Check packet size @@ -2524,35 +3640,45 @@ int dir; oip = (ip_t *)((char *)fin->fin_dp + 8); minlen = IP_HL(oip) << 2; if ((minlen < sizeof(ip_t)) || - (fin->fin_plen < ICMPERR_IPICMPHLEN + minlen)) + (fin->fin_plen < ICMPERR_IPICMPHLEN + minlen)) { + ATOMIC_INCL(nside->ns_icmp_size); return NULL; + } + /* * Is the buffer big enough for all of it ? It's the size of the IP * header claimed in the encapsulated part which is of concern. It * may be too big to be in this buffer but not so big that it's * outside the ICMP packet, leading to TCP deref's causing problems. * This is possible because we don't know how big oip_hl is when we - * do the pullup early in fr_check() and thus can't gaurantee it is + * do the pullup early in ipf_check() and thus can't gaurantee it is * all here now. */ -#ifdef _KERNEL +#ifdef ipf_nat_KERNEL { mb_t *m; m = fin->fin_m; # if defined(MENTAT) - if ((char *)oip + fin->fin_dlen - ICMPERR_ICMPHLEN > (char *)m->b_wptr) + if ((char *)oip + fin->fin_dlen - ICMPERR_ICMPHLEN > + (char *)m->b_wptr) { + ATOMIC_INCL(nside->ns_icmp_mbuf); return NULL; + } # else if ((char *)oip + fin->fin_dlen - ICMPERR_ICMPHLEN > - (char *)fin->fin_ip + M_LEN(m)) + (char *)fin->fin_ip + M_LEN(m)) { + ATOMIC_INCL(nside->ns_icmp_mbuf); return NULL; + } # endif } #endif - if (fin->fin_daddr != oip->ip_src.s_addr) + if (fin->fin_daddr != oip->ip_src.s_addr) { + ATOMIC_INCL(nside->ns_icmp_address); return NULL; + } p = oip->ip_p; if (p == IPPROTO_TCP) @@ -2563,7 +3689,7 @@ int dir; orgicmp = (icmphdr_t *)((char *)oip + (IP_HL(oip) << 2)); /* see if this is related to an ICMP query */ - if (nat_icmpquerytype4(orgicmp->icmp_type)) { + if (ipf_nat_icmpquerytype(orgicmp->icmp_type)) { data[0] = fin->fin_data[0]; data[1] = fin->fin_data[1]; fin->fin_data[0] = 0; @@ -2576,21 +3702,26 @@ int dir; * message flows in the opposite direction. */ if (dir == NAT_INBOUND) - nat = nat_inlookup(fin, flags, p, oip->ip_dst, - oip->ip_src); + nat = ipf_nat_inlookup(fin, flags, p, + oip->ip_dst, + oip->ip_src); else - nat = nat_outlookup(fin, flags, p, oip->ip_dst, - oip->ip_src); + nat = ipf_nat_outlookup(fin, flags, p, + oip->ip_dst, + oip->ip_src); fin->fin_data[0] = data[0]; fin->fin_data[1] = data[1]; return nat; } } - + if (flags & IPN_TCPUDP) { minlen += 8; /* + 64bits of data to get ports */ - if (fin->fin_plen < ICMPERR_IPICMPHLEN + minlen) + /* TRACE (fin,minlen) */ + if (fin->fin_plen < ICMPERR_IPICMPHLEN + minlen) { + ATOMIC_INCL(nside->ns_icmp_short); return NULL; + } data[0] = fin->fin_data[0]; data[1] = fin->fin_data[1]; @@ -2599,10 +3730,10 @@ int dir; fin->fin_data[1] = ntohs(tcp->th_sport); if (dir == NAT_INBOUND) { - nat = nat_inlookup(fin, flags, p, oip->ip_dst, - oip->ip_src); + nat = ipf_nat_inlookup(fin, flags, p, oip->ip_dst, + oip->ip_src); } else { - nat = nat_outlookup(fin, flags, p, oip->ip_dst, + nat = ipf_nat_outlookup(fin, flags, p, oip->ip_dst, oip->ip_src); } fin->fin_data[0] = data[0]; @@ -2610,14 +3741,16 @@ int dir; return nat; } if (dir == NAT_INBOUND) - return nat_inlookup(fin, 0, p, oip->ip_dst, oip->ip_src); + nat = ipf_nat_inlookup(fin, 0, p, oip->ip_dst, oip->ip_src); else - return nat_outlookup(fin, 0, p, oip->ip_dst, oip->ip_src); + nat = ipf_nat_outlookup(fin, 0, p, oip->ip_dst, oip->ip_src); + + return nat; } /* ------------------------------------------------------------------------ */ -/* Function: nat_icmperror */ +/* Function: ipf_nat_icmperror */ /* Returns: nat_t* - point to matching NAT structure */ /* Parameters: fin(I) - pointer to packet information */ /* nflags(I) - NAT flags for this packet */ @@ -2629,28 +3762,36 @@ int dir; /* This should *ONLY* be used for incoming ICMP error packets to make sure */ /* a NAT'd ICMP packet gets correctly recognised. */ /* ------------------------------------------------------------------------ */ -nat_t *nat_icmperror(fin, nflags, dir) -fr_info_t *fin; -u_int *nflags; -int dir; +nat_t * +ipf_nat_icmperror(fin, nflags, dir) + fr_info_t *fin; + u_int *nflags; + int dir; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; u_32_t sum1, sum2, sumd, sumd2; - struct in_addr in; + struct in_addr a1, a2, a3, a4; + int flags, dlen, odst; icmphdr_t *icmp; - int flags, dlen; u_short *csump; tcphdr_t *tcp; nat_t *nat; ip_t *oip; void *dp; - if ((fin->fin_flx & (FI_SHORT|FI_FRAGBODY))) + if ((fin->fin_flx & (FI_SHORT|FI_FRAGBODY))) { + NBUMPSIDED(fin->fin_out, ns_icmp_short); return NULL; + } + /* - * nat_icmperrorlookup() will return NULL for `defective' packets. + * ipf_nat_icmperrorlookup() will return NULL for `defective' packets. */ - if ((fin->fin_v != 4) || !(nat = nat_icmperrorlookup(fin, dir))) + if ((fin->fin_v != 4) || !(nat = ipf_nat_icmperrorlookup(fin, dir))) { + NBUMPSIDED(fin->fin_out, ns_icmp_notfound); return NULL; + } tcp = NULL; csump = NULL; @@ -2678,7 +3819,7 @@ int dir; /* * 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 as it will be modified again in fr_checknatout + * IP address change as it will be modified again in ipf_nat_checkout * 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 @@ -2688,33 +3829,7 @@ int dir; /* * 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. - */ - - if (oip->ip_dst.s_addr == nat->nat_oip.s_addr) { - sum1 = LONG_SUM(ntohl(oip->ip_src.s_addr)); - in = nat->nat_inip; - oip->ip_src = in; - } else { - sum1 = LONG_SUM(ntohl(oip->ip_dst.s_addr)); - in = nat->nat_outip; - oip->ip_dst = in; - } - - sum2 = LONG_SUM(ntohl(in.s_addr)); - - CALC_SUMD(sum1, sum2, sumd); - - /* - * Fix IP checksum of the offending IP packet to adjust for - * the change in the IP address. + * to adjust the IP header checksum of that offending IP packet. * * Normally, you would expect that the ICMP checksum of the * ICMP error message needs to be adjusted as well for the @@ -2726,228 +3841,175 @@ int dir; * 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) + * Inbound ICMP + * ------------ + * MAP rule, SRC=a,DST=b -> SRC=c,DST=b + * - response to outgoing packet (a,b)=>(c,b) (OIP_SRC=c,OIP_DST=b) + * - OIP_SRC(c)=nat_newsrcip, OIP_DST(b)=nat_newdstip + *=> OIP_SRC(c)=nat_oldsrcip, OIP_DST(b)=nat_olddstip + * + * RDR rule, SRC=a,DST=b -> SRC=a,DST=c + * - response to outgoing packet (c,a)=>(b,a) (OIP_SRC=b,OIP_DST=a) + * - OIP_SRC(b)=nat_olddstip, OIP_DST(a)=nat_oldsrcip + *=> OIP_SRC(b)=nat_newdstip, OIP_DST(a)=nat_newsrcip + * + * REWRITE out rule, SRC=a,DST=b -> SRC=c,DST=d + * - response to outgoing packet (a,b)=>(c,d) (OIP_SRC=c,OIP_DST=d) + * - OIP_SRC(c)=nat_newsrcip, OIP_DST(d)=nat_newdstip + *=> OIP_SRC(c)=nat_oldsrcip, OIP_DST(d)=nat_olddstip + * + * REWRITE in rule, SRC=a,DST=b -> SRC=c,DST=d + * - response to outgoing packet (d,c)=>(b,a) (OIP_SRC=b,OIP_DST=a) + * - OIP_SRC(b)=nat_olddstip, OIP_DST(a)=nat_oldsrcip + *=> OIP_SRC(b)=nat_newdstip, OIP_DST(a)=nat_newsrcip + * + * Outbound ICMP + * ------------- + * MAP rule, SRC=a,DST=b -> SRC=c,DST=b + * - response to incoming packet (b,c)=>(b,a) (OIP_SRC=b,OIP_DST=a) + * - OIP_SRC(b)=nat_olddstip, OIP_DST(a)=nat_oldsrcip + *=> OIP_SRC(b)=nat_newdstip, OIP_DST(a)=nat_newsrcip + * + * RDR rule, SRC=a,DST=b -> SRC=a,DST=c + * - response to incoming packet (a,b)=>(a,c) (OIP_SRC=a,OIP_DST=c) + * - OIP_SRC(a)=nat_newsrcip, OIP_DST(c)=nat_newdstip + *=> OIP_SRC(a)=nat_oldsrcip, OIP_DST(c)=nat_olddstip + * + * REWRITE out rule, SRC=a,DST=b -> SRC=c,DST=d + * - response to incoming packet (d,c)=>(b,a) (OIP_SRC=c,OIP_DST=d) + * - OIP_SRC(c)=nat_olddstip, OIP_DST(d)=nat_oldsrcip + *=> OIP_SRC(b)=nat_newdstip, OIP_DST(a)=nat_newsrcip + * + * REWRITE in rule, SRC=a,DST=b -> SRC=c,DST=d + * - response to incoming packet (a,b)=>(c,d) (OIP_SRC=b,OIP_DST=a) + * - OIP_SRC(b)=nat_newsrcip, OIP_DST(a)=nat_newdstip + *=> OIP_SRC(a)=nat_oldsrcip, OIP_DST(c)=nat_olddstip */ - fix_datacksum(&oip->ip_sum, sumd); - /* Fix icmp cksum : IP Addr + Cksum */ - sumd2 = (sumd >> 16); - /* - * Fix UDP pseudo header checksum to compensate for the - * IP address change. - */ - if ((oip->ip_p == IPPROTO_UDP) && (dlen >= 8) && (*csump != 0)) { - /* - * The UDP checksum is optional, only adjust it - * if it has been set. - */ - sum1 = ntohs(*csump); - fix_datacksum(csump, sumd); - sum2 = ntohs(*csump); - - /* - * Fix ICMP checksum to compensate the UDP - * checksum adjustment. - */ - sumd2 = sumd << 1; - CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd; + if (((fin->fin_out == 0) && ((nat->nat_redir & NAT_MAP) != 0)) || + ((fin->fin_out == 1) && ((nat->nat_redir & NAT_REDIRECT) != 0))) { + a1.s_addr = ntohl(nat->nat_osrcaddr); + a4.s_addr = ntohl(oip->ip_src.s_addr); + a3.s_addr = ntohl(nat->nat_odstaddr); + a2.s_addr = ntohl(oip->ip_dst.s_addr); + oip->ip_src.s_addr = htonl(a1.s_addr); + oip->ip_dst.s_addr = htonl(a3.s_addr); + odst = 1; + } else { + a1.s_addr = ntohl(nat->nat_ndstaddr); + a2.s_addr = ntohl(oip->ip_dst.s_addr); + a3.s_addr = ntohl(nat->nat_nsrcaddr); + a4.s_addr = ntohl(oip->ip_src.s_addr); + oip->ip_dst.s_addr = htonl(a3.s_addr); + oip->ip_src.s_addr = htonl(a1.s_addr); + odst = 0; } + sum1 = 0; + sum2 = 0; + sumd = 0; + CALC_SUMD(a2.s_addr, a3.s_addr, sum1); + CALC_SUMD(a4.s_addr, a1.s_addr, sum2); + sumd = sum2 + sum1; + if (sumd != 0) + ipf_fix_datacksum(&oip->ip_sum, sumd); + + sumd2 = sumd; + sum1 = 0; + sum2 = 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!). - * 18 = offsetof(tcphdr_t, th_sum) + 2 + * Fix UDP pseudo header checksum to compensate for the + * IP address change. */ - else if (oip->ip_p == IPPROTO_TCP && dlen >= 18) { - sum1 = ntohs(*csump); - fix_datacksum(csump, sumd); - sum2 = ntohs(*csump); - - /* - * Fix ICMP checksum to compensate the TCP - * checksum adjustment. - */ - sumd2 = sumd << 1; - CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd; - } else { - if (nat->nat_dir == NAT_OUTBOUND) - sumd2 = ~sumd2; - else - sumd2 = ~sumd2 + 1; - } - if (((flags & IPN_TCPUDP) != 0) && (dlen >= 4)) { - int mode = 0; + u_32_t sum3, sum4, sumt; /* * 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 :-) + * a change may be reflected in the ICMP checksum as well. * * 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. Some OSses like Solaris return enough bytes to - * include the TCP checksum. So we have to check if the - * ip->ip_len actually holds the TCP checksum of the oip! + * as well... except that the change in the port numbers should + * be offset by the checksum change. However, the TCP/UDP + * checksum will also need to change if there has been an + * IP address change. */ + if (odst == 1) { + sum1 = ntohs(nat->nat_osport); + sum4 = ntohs(tcp->th_sport); + sum3 = ntohs(nat->nat_odport); + sum2 = ntohs(tcp->th_dport); - if (nat->nat_oport == tcp->th_dport) { - if (tcp->th_sport != nat->nat_inport) { - mode = 1; - sum1 = ntohs(nat->nat_inport); - sum2 = ntohs(tcp->th_sport); - } - } else if (tcp->th_sport == nat->nat_oport) { - mode = 2; - sum1 = ntohs(nat->nat_outport); + tcp->th_sport = htons(sum1); + tcp->th_dport = htons(sum3); + } else { + sum1 = ntohs(nat->nat_ndport); sum2 = ntohs(tcp->th_dport); - } + sum3 = ntohs(nat->nat_nsport); + sum4 = ntohs(tcp->th_sport); - if (mode == 1) { - /* - * Fix ICMP checksum to compensate port adjustment. - */ + tcp->th_dport = htons(sum3); tcp->th_sport = htons(sum1); + } + CALC_SUMD(sum4, sum1, sumt); + sumd += sumt; + CALC_SUMD(sum2, sum3, sumt); + sumd += sumt; + if (sumd != 0 || sumd2 != 0) { /* - * Fix udp checksum to compensate port adjustment. - * NOTE : the offending IP packet flows the other - * direction compared to the ICMP message. + * At this point, sumd is the delta to apply to the + * TCP/UDP header, given the changes in both the IP + * address and the ports and sumd2 is the delta to + * apply to the ICMP header, given the IP address + * change delta that may need to be applied to the + * TCP/UDP checksum instead. * - * The UDP checksum is optional, only adjust it if - * it has been set. - */ - if ((oip->ip_p == IPPROTO_UDP) && - (dlen >= 8) && (*csump != 0)) { - sumd = sum1 - sum2; - sumd2 += sumd; - - sum1 = ntohs(*csump); - fix_datacksum(csump, sumd); - sum2 = ntohs(*csump); - - /* - * Fix ICMP checksum to compenstate - * UDP checksum adjustment. - */ - CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd; - } - - /* - * Fix TCP checksum (if present) to compensate port - * adjustment. NOTE : the offending IP packet flows - * the other direction compared to the ICMP message. + * If we will both the IP and TCP/UDP checksums + * then the ICMP checksum changes by the address + * delta applied to the TCP/UDP checksum. If we + * do not change the TCP/UDP checksum them we + * apply the delta in ports to the ICMP checksum. */ - if (oip->ip_p == IPPROTO_TCP) { - if (dlen >= 18) { - sumd = sum1 - sum2; - sumd2 += sumd; - - sum1 = ntohs(*csump); - fix_datacksum(csump, sumd); - sum2 = ntohs(*csump); - - /* - * Fix ICMP checksum to compensate - * TCP checksum adjustment. - */ - CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd; + if (oip->ip_p == IPPROTO_UDP) { + if ((dlen >= 8) && (*csump != 0)) { + ipf_fix_datacksum(csump, sumd); } else { - sumd = sum2 - sum1 + 1; - sumd2 += sumd; + CALC_SUMD(sum1, sum4, sumd2); + CALC_SUMD(sum3, sum2, sumt); + sumd2 += sumt; } - } - } else if (mode == 2) { - /* - * Fix ICMP checksum to compensate port adjustment. - */ - tcp->th_dport = htons(sum1); - - /* - * 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) && - (dlen >= 8) && (*csump != 0)) { - sumd = sum1 - sum2; - sumd2 += sumd; - - sum1 = ntohs(*csump); - fix_datacksum(csump, sumd); - sum2 = ntohs(*csump); - - /* - * Fix ICMP checksum to compensate - * UDP checksum adjustment. - */ - CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd; - } - - /* - * Fix TCP checksum (if present) to compensate port - * adjustment. NOTE : the offending IP packet flows - * the other direction compared to the ICMP message. - */ - if (oip->ip_p == IPPROTO_TCP) { + } else if (oip->ip_p == IPPROTO_TCP) { if (dlen >= 18) { - sumd = sum1 - sum2; - sumd2 += sumd; - - sum1 = ntohs(*csump); - fix_datacksum(csump, sumd); - sum2 = ntohs(*csump); - - /* - * Fix ICMP checksum to compensate - * TCP checksum adjustment. - */ - CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd; + ipf_fix_datacksum(csump, sumd); } else { - if (nat->nat_dir == NAT_INBOUND) - sumd = sum2 - sum1; - else - sumd = sum2 - sum1 + 1; - sumd2 += sumd; + CALC_SUMD(sum1, sum4, sumd2); + CALC_SUMD(sum3, sum2, sumt); + sumd2 += sumt; } } - } - if (sumd2 != 0) { - sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16); - sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16); - fix_incksum(fin, &icmp->icmp_cksum, sumd2); + if (sumd2 != 0) { + sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16); + sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16); + sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16); + ipf_fix_incksum(0, &icmp->icmp_cksum, sumd2, 0); + } } } else if (((flags & IPN_ICMPQUERY) != 0) && (dlen >= 8)) { icmphdr_t *orgicmp; /* * XXX - what if this is bogus hl and we go off the end ? - * In this case, nat_icmperrorlookup() will have returned NULL. + * In this case, ipf_nat_icmperrorlookup() will have + * returned NULL. */ orgicmp = (icmphdr_t *)dp; - if (nat->nat_dir == NAT_OUTBOUND) { - if (orgicmp->icmp_id != nat->nat_inport) { + if (odst == 1) { + if (orgicmp->icmp_id != nat->nat_osport) { /* * Fix ICMP checksum (of the offening ICMP @@ -2962,10 +4024,10 @@ int dir; * overall icmp->icmp_cksum */ sum1 = ntohs(orgicmp->icmp_id); - sum2 = ntohs(nat->nat_inport); + sum2 = ntohs(nat->nat_oicmpid); CALC_SUMD(sum1, sum2, sumd); - orgicmp->icmp_id = nat->nat_inport; - fix_datacksum(&orgicmp->icmp_cksum, sumd); + orgicmp->icmp_id = nat->nat_oicmpid; + ipf_fix_datacksum(&orgicmp->icmp_cksum, sumd); } } /* nat_dir == NAT_INBOUND is impossible for icmp queries */ } @@ -2974,12 +4036,19 @@ int dir; /* + * MAP-IN MAP-OUT RDR-IN RDR-OUT + * osrc X == src == src X + * odst X == dst == dst X + * nsrc == dst X X == dst + * ndst == src X X == src + * MAP = NAT_OUTBOUND, RDR = NAT_INBOUND + */ +/* * NB: these lookups don't lock access to the list, it assumed that it has * already been done! */ - /* ------------------------------------------------------------------------ */ -/* Function: nat_inlookup */ +/* Function: ipf_nat_inlookup */ /* Returns: nat_t* - NULL == no match, */ /* else pointer to matching NAT entry */ /* Parameters: fin(I) - pointer to packet information */ @@ -2994,17 +4063,20 @@ int dir; /* */ /* NOTE: THE PACKET BEING CHECKED (IF FOUND) HAS A MAPPING ALREADY. */ /* */ -/* NOTE: IT IS ASSUMED THAT ipf_nat IS ONLY HELD WITH A READ LOCK WHEN */ +/* NOTE: IT IS ASSUMED THAT IS ONLY HELD WITH A READ LOCK WHEN */ /* THIS FUNCTION IS CALLED WITH NAT_SEARCH SET IN nflags. */ /* */ /* flags -> relevant are IPN_UDP/IPN_TCP/IPN_ICMPQUERY that indicate if */ /* the packet is of said protocol */ /* ------------------------------------------------------------------------ */ -nat_t *nat_inlookup(fin, flags, p, src, mapdst) -fr_info_t *fin; -u_int flags, p; -struct in_addr src , mapdst; +nat_t * +ipf_nat_inlookup(fin, flags, p, src, mapdst) + fr_info_t *fin; + u_int flags, p; + struct in_addr src , mapdst; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; u_short sport, dport; grehdr_t *gre; ipnat_t *ipn; @@ -3013,14 +4085,9 @@ struct in_addr src , mapdst; int nflags; u_32_t dst; void *ifp; - u_int hv; + u_int hv, rhv; - if (fin != NULL) - ifp = fin->fin_ifp; - else - ifp = NULL; - sport = 0; - dport = 0; + ifp = fin->fin_ifp; gre = NULL; dst = mapdst.s_addr; sflags = flags & NAT_TCPUDPICMP; @@ -3033,12 +4100,17 @@ struct in_addr src , mapdst; dport = htons(fin->fin_data[1]); break; case IPPROTO_ICMP : - if (flags & IPN_ICMPERR) + if (flags & IPN_ICMPERR) { sport = fin->fin_data[1]; - else + dport = 0; + } else { dport = fin->fin_data[1]; + sport = 0; + } break; default : + sport = 0; + dport = 0; break; } @@ -3046,61 +4118,81 @@ struct in_addr src , mapdst; if ((flags & SI_WILDP) != 0) goto find_in_wild_ports; - hv = NAT_HASH_FN(dst, dport, 0xffffffff); - hv = NAT_HASH_FN(src.s_addr, hv + sport, ipf_nattable_sz); - nat = nat_table[1][hv]; + rhv = NAT_HASH_FN(dst, dport, 0xffffffff); + rhv = NAT_HASH_FN(src.s_addr, rhv + sport, 0xffffffff); + hv = rhv % softn->ipf_nat_table_sz; + nat = softn->ipf_nat_table[1][hv]; + /* TRACE dst, dport, src, sport, hv, nat */ + for (; nat; nat = nat->nat_hnext[1]) { - nflags = nat->nat_flags; + if (nat->nat_ifps[0] != NULL) { + if ((ifp != NULL) && (ifp != nat->nat_ifps[0])) + continue; + } - if (ifp != NULL) { - if (nat->nat_dir == NAT_REDIRECT) { - if (ifp != nat->nat_ifps[0]) + if (nat->nat_pr[0] != p) + continue; + + switch (nat->nat_dir) + { + case NAT_INBOUND : + case NAT_DIVERTIN : + if (nat->nat_v[0] != 4) + continue; + if (nat->nat_osrcaddr != src.s_addr || + nat->nat_odstaddr != dst) + continue; + if ((nat->nat_flags & IPN_TCPUDP) != 0) { + if (nat->nat_osport != sport) continue; - } else { - if (ifp != nat->nat_ifps[1]) + if (nat->nat_odport != dport) continue; - } - } - if (nat->nat_oip.s_addr == src.s_addr && - nat->nat_outip.s_addr == dst && - (((p == 0) && - (sflags == (nat->nat_flags & IPN_TCPUDPICMP))) - || (p == nat->nat_p))) { - switch (p) - { -#if 0 - case IPPROTO_GRE : - if (nat->nat_call[1] != fin->fin_data[0]) + } else if (p == IPPROTO_ICMP) { + if (nat->nat_osport != dport) { continue; - break; -#endif - case IPPROTO_ICMP : - if ((flags & IPN_ICMPERR) != 0) { - if (nat->nat_outport != sport) - continue; - } else { - if (nat->nat_outport != dport) - continue; } - break; - case IPPROTO_TCP : - case IPPROTO_UDP : - if (nat->nat_oport != sport) + } + break; + case NAT_DIVERTOUT : + if (nat->nat_dlocal) + continue; + case NAT_OUTBOUND : + if (nat->nat_v[1] != 4) + continue; + if (nat->nat_dlocal) + continue; + if (nat->nat_dlocal) + continue; + if (nat->nat_ndstaddr != src.s_addr || + nat->nat_nsrcaddr != dst) + continue; + if ((nat->nat_flags & IPN_TCPUDP) != 0) { + if (nat->nat_ndport != sport) continue; - if (nat->nat_outport != dport) + if (nat->nat_nsport != dport) continue; - break; - default : - break; + + } else if (p == IPPROTO_ICMP) { + if (nat->nat_osport != dport) { + continue; + } } + break; + } + + if ((nat->nat_flags & IPN_TCPUDP) != 0) { ipn = nat->nat_ptr; if ((ipn != NULL) && (nat->nat_aps != NULL)) - if (appr_match(fin, nat) != 0) + if (ipf_proxy_match(fin, nat) != 0) continue; - return nat; } + if ((nat->nat_ifps[0] == NULL) && (ifp != NULL)) { + nat->nat_ifps[0] = ifp; + nat->nat_mtu[0] = GETIFMTU_4(ifp); + } + return nat; } /* @@ -3111,130 +4203,191 @@ struct in_addr src , mapdst; * for "dummy" (FI_IGNORE) lookups. */ find_in_wild_ports: - if (!(flags & NAT_TCPUDP) || !(flags & NAT_SEARCH)) + if (!(flags & NAT_TCPUDP) || !(flags & NAT_SEARCH)) { + NBUMPSIDEX(0, ns_lookup_miss, ns_lookup_miss_0); return NULL; - if (nat_stats.ns_wilds == 0) + } + if (softn->ipf_nat_stats.ns_wilds == 0 || (fin->fin_flx & FI_NOWILD)) { + NBUMPSIDEX(0, ns_lookup_nowild, ns_lookup_nowild_0); return NULL; + } - RWLOCK_EXIT(&ipf_nat); + RWLOCK_EXIT(&softc->ipf_nat); hv = NAT_HASH_FN(dst, 0, 0xffffffff); - hv = NAT_HASH_FN(src.s_addr, hv, ipf_nattable_sz); + hv = NAT_HASH_FN(src.s_addr, hv, softn->ipf_nat_table_sz); + WRITE_ENTER(&softc->ipf_nat); - WRITE_ENTER(&ipf_nat); - - nat = nat_table[1][hv]; + nat = softn->ipf_nat_table[1][hv]; + /* TRACE dst, src, hv, nat */ for (; nat; nat = nat->nat_hnext[1]) { - if (ifp != NULL) { - if (nat->nat_dir == NAT_REDIRECT) { - if (ifp != nat->nat_ifps[0]) - continue; - } else { - if (ifp != nat->nat_ifps[1]) - continue; - } + if (nat->nat_ifps[0] != NULL) { + if ((ifp != NULL) && (ifp != nat->nat_ifps[0])) + continue; } - if (nat->nat_p != fin->fin_p) - continue; - if (nat->nat_oip.s_addr != src.s_addr || - nat->nat_outip.s_addr != dst) + if (nat->nat_pr[0] != fin->fin_p) continue; + switch (nat->nat_dir & (NAT_INBOUND|NAT_OUTBOUND)) + { + case NAT_INBOUND : + if (nat->nat_v[0] != 4) + continue; + if (nat->nat_osrcaddr != src.s_addr || + nat->nat_odstaddr != dst) + continue; + break; + case NAT_OUTBOUND : + if (nat->nat_v[1] != 4) + continue; + if (nat->nat_ndstaddr != src.s_addr || + nat->nat_nsrcaddr != dst) + continue; + break; + } + nflags = nat->nat_flags; if (!(nflags & (NAT_TCPUDP|SI_WILDP))) continue; - if (nat_wildok(nat, (int)sport, (int)dport, nflags, - NAT_INBOUND) == 1) { + if (ipf_nat_wildok(nat, (int)sport, (int)dport, nflags, + NAT_INBOUND) == 1) { if ((fin->fin_flx & FI_IGNORE) != 0) break; if ((nflags & SI_CLONE) != 0) { - nat = fr_natclone(fin, nat); + nat = ipf_nat_clone(fin, nat); if (nat == NULL) break; } else { - MUTEX_ENTER(&ipf_nat_new); - nat_stats.ns_wilds--; - MUTEX_EXIT(&ipf_nat_new); + MUTEX_ENTER(&softn->ipf_nat_new); + softn->ipf_nat_stats.ns_wilds--; + MUTEX_EXIT(&softn->ipf_nat_new); + } + + if (nat->nat_dir == NAT_INBOUND) { + if (nat->nat_osport == 0) { + nat->nat_osport = sport; + nat->nat_nsport = sport; + } + if (nat->nat_odport == 0) { + nat->nat_odport = dport; + nat->nat_ndport = dport; + } + } else if (nat->nat_dir == NAT_OUTBOUND) { + if (nat->nat_osport == 0) { + nat->nat_osport = dport; + nat->nat_nsport = dport; + } + if (nat->nat_odport == 0) { + nat->nat_odport = sport; + nat->nat_ndport = sport; + } + } + if ((nat->nat_ifps[0] == NULL) && (ifp != NULL)) { + nat->nat_ifps[0] = ifp; + nat->nat_mtu[0] = GETIFMTU_4(ifp); } - nat->nat_oport = sport; - nat->nat_outport = dport; nat->nat_flags &= ~(SI_W_DPORT|SI_W_SPORT); - nat_tabmove(nat); + ipf_nat_tabmove(softn, nat); break; } } - MUTEX_DOWNGRADE(&ipf_nat); + MUTEX_DOWNGRADE(&softc->ipf_nat); + if (nat == NULL) { + NBUMPSIDE(0, ns_lookup_miss); + } return nat; } /* ------------------------------------------------------------------------ */ -/* Function: nat_tabmove */ +/* Function: ipf_nat_tabmove */ /* Returns: Nil */ -/* Parameters: nat(I) - pointer to NAT structure */ +/* Parameters: softn(I) - pointer to NAT context structure */ +/* nat(I) - pointer to NAT structure */ /* Write Lock: ipf_nat */ /* */ /* This function is only called for TCP/UDP NAT table entries where the */ /* original was placed in the table without hashing on the ports and we now */ /* want to include hashing on port numbers. */ /* ------------------------------------------------------------------------ */ -static void nat_tabmove(nat) -nat_t *nat; +static void +ipf_nat_tabmove(softn, nat) + ipf_nat_softc_t *softn; + nat_t *nat; { + u_int hv0, hv1, rhv0, rhv1; + natstat_t *nsp; nat_t **natp; - u_int hv; if (nat->nat_flags & SI_CLONE) return; + nsp = &softn->ipf_nat_stats; /* * 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]; - nat_stats.ns_bucketlen[0][nat->nat_hv[0]]--; + nsp->ns_side[0].ns_bucketlen[nat->nat_hv[0] % + softn->ipf_nat_table_sz]--; if (nat->nat_hnext[1]) nat->nat_hnext[1]->nat_phnext[1] = nat->nat_phnext[1]; *nat->nat_phnext[1] = nat->nat_hnext[1]; - nat_stats.ns_bucketlen[1][nat->nat_hv[1]]--; + nsp->ns_side[1].ns_bucketlen[nat->nat_hv[1] % + softn->ipf_nat_table_sz]--; /* * Add into the NAT table in the new position */ - hv = NAT_HASH_FN(nat->nat_inip.s_addr, nat->nat_inport, 0xffffffff); - hv = NAT_HASH_FN(nat->nat_oip.s_addr, hv + nat->nat_oport, - ipf_nattable_sz); - nat->nat_hv[0] = hv; - natp = &nat_table[0][hv]; + rhv0 = NAT_HASH_FN(nat->nat_osrcaddr, nat->nat_osport, 0xffffffff); + rhv0 = NAT_HASH_FN(nat->nat_odstaddr, rhv0 + nat->nat_odport, + 0xffffffff); + rhv1 = NAT_HASH_FN(nat->nat_nsrcaddr, nat->nat_nsport, 0xffffffff); + rhv1 = NAT_HASH_FN(nat->nat_ndstaddr, rhv1 + nat->nat_ndport, + 0xffffffff); + + hv0 = rhv0 % softn->ipf_nat_table_sz; + hv1 = rhv1 % softn->ipf_nat_table_sz; + + if (nat->nat_dir == NAT_INBOUND || nat->nat_dir == NAT_DIVERTIN) { + u_int swap; + + swap = hv0; + hv0 = hv1; + hv1 = swap; + } + + /* TRACE nat_osrcaddr, nat_osport, nat_odstaddr, nat_odport, hv0 */ + /* TRACE nat_nsrcaddr, nat_nsport, nat_ndstaddr, nat_ndport, hv1 */ + + nat->nat_hv[0] = rhv0; + natp = &softn->ipf_nat_table[0][hv0]; if (*natp) (*natp)->nat_phnext[0] = &nat->nat_hnext[0]; nat->nat_phnext[0] = natp; nat->nat_hnext[0] = *natp; *natp = nat; - nat_stats.ns_bucketlen[0][hv]++; + nsp->ns_side[0].ns_bucketlen[hv0]++; - hv = NAT_HASH_FN(nat->nat_outip.s_addr, nat->nat_outport, 0xffffffff); - hv = NAT_HASH_FN(nat->nat_oip.s_addr, hv + nat->nat_oport, - ipf_nattable_sz); - nat->nat_hv[1] = hv; - natp = &nat_table[1][hv]; + nat->nat_hv[1] = rhv1; + natp = &softn->ipf_nat_table[1][hv1]; if (*natp) (*natp)->nat_phnext[1] = &nat->nat_hnext[1]; nat->nat_phnext[1] = natp; nat->nat_hnext[1] = *natp; *natp = nat; - nat_stats.ns_bucketlen[1][hv]++; + nsp->ns_side[1].ns_bucketlen[hv1]++; } /* ------------------------------------------------------------------------ */ -/* Function: nat_outlookup */ +/* Function: ipf_nat_outlookup */ /* Returns: nat_t* - NULL == no match, */ /* else pointer to matching NAT entry */ /* Parameters: fin(I) - pointer to packet information */ @@ -3242,7 +4395,7 @@ nat_t *nat; /* p(I) - protocol for this packet */ /* src(I) - source IP address */ /* dst(I) - destination IP address */ -/* rw(I) - 1 == write lock on ipf_nat held, 0 == read lock. */ +/* rw(I) - 1 == write lock on held, 0 == read lock. */ /* */ /* Lookup a nat entry based on the source 'real' ip address/port and */ /* destination address/port. We use this lookup when sending a packet out, */ @@ -3250,28 +4403,28 @@ nat_t *nat; /* */ /* NOTE: THE PACKET BEING CHECKED (IF FOUND) HAS A MAPPING ALREADY. */ /* */ -/* NOTE: IT IS ASSUMED THAT ipf_nat IS ONLY HELD WITH A READ LOCK WHEN */ +/* NOTE: IT IS ASSUMED THAT IS ONLY HELD WITH A READ LOCK WHEN */ /* THIS FUNCTION IS CALLED WITH NAT_SEARCH SET IN nflags. */ /* */ /* flags -> relevant are IPN_UDP/IPN_TCP/IPN_ICMPQUERY that indicate if */ /* the packet is of said protocol */ /* ------------------------------------------------------------------------ */ -nat_t *nat_outlookup(fin, flags, p, src, dst) -fr_info_t *fin; -u_int flags, p; -struct in_addr src , dst; +nat_t * +ipf_nat_outlookup(fin, flags, p, src, dst) + fr_info_t *fin; + u_int flags, p; + struct in_addr src , dst; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; u_short sport, dport; u_int sflags; ipnat_t *ipn; - u_32_t srcip; nat_t *nat; - int nflags; void *ifp; u_int hv; ifp = fin->fin_ifp; - srcip = src.s_addr; sflags = flags & IPN_TCPUDPICMP; sport = 0; dport = 0; @@ -3296,51 +4449,75 @@ struct in_addr src , dst; if ((flags & SI_WILDP) != 0) goto find_out_wild_ports; - hv = NAT_HASH_FN(srcip, sport, 0xffffffff); - hv = NAT_HASH_FN(dst.s_addr, hv + dport, ipf_nattable_sz); - nat = nat_table[0][hv]; + hv = NAT_HASH_FN(src.s_addr, sport, 0xffffffff); + hv = NAT_HASH_FN(dst.s_addr, hv + dport, softn->ipf_nat_table_sz); + nat = softn->ipf_nat_table[0][hv]; + + /* TRACE src, sport, dst, dport, hv, nat */ + for (; nat; nat = nat->nat_hnext[0]) { - nflags = nat->nat_flags; + if (nat->nat_ifps[1] != NULL) { + if ((ifp != NULL) && (ifp != nat->nat_ifps[1])) + continue; + } + + if (nat->nat_pr[1] != p) + continue; + + switch (nat->nat_dir) + { + case NAT_INBOUND : + case NAT_DIVERTIN : + if (nat->nat_v[1] != 4) + continue; + if (nat->nat_ndstaddr != src.s_addr || + nat->nat_nsrcaddr != dst.s_addr) + continue; - if (ifp != NULL) { - if (nat->nat_dir == NAT_REDIRECT) { - if (ifp != nat->nat_ifps[1]) + if ((nat->nat_flags & IPN_TCPUDP) != 0) { + if (nat->nat_ndport != sport) continue; - } else { - if (ifp != nat->nat_ifps[0]) + if (nat->nat_nsport != dport) + continue; + + } else if (p == IPPROTO_ICMP) { + if (nat->nat_osport != dport) { continue; + } } - } + break; + case NAT_OUTBOUND : + case NAT_DIVERTOUT : + if (nat->nat_v[0] != 4) + continue; + if (nat->nat_osrcaddr != src.s_addr || + nat->nat_odstaddr != dst.s_addr) + continue; - if (nat->nat_inip.s_addr == srcip && - nat->nat_oip.s_addr == dst.s_addr && - (((p == 0) && (sflags == (nflags & NAT_TCPUDPICMP))) - || (p == nat->nat_p))) { - switch (p) - { -#if 0 - case IPPROTO_GRE : - if (nat->nat_call[1] != fin->fin_data[0]) + if ((nat->nat_flags & IPN_TCPUDP) != 0) { + if (nat->nat_odport != dport) continue; - break; -#endif - case IPPROTO_TCP : - case IPPROTO_UDP : - if (nat->nat_oport != dport) + if (nat->nat_osport != sport) continue; - if (nat->nat_inport != sport) + + } else if (p == IPPROTO_ICMP) { + if (nat->nat_osport != dport) { continue; - break; - default : - break; + } } + break; + } - ipn = nat->nat_ptr; - if ((ipn != NULL) && (nat->nat_aps != NULL)) - if (appr_match(fin, nat) != 0) - continue; - return nat; + ipn = nat->nat_ptr; + if ((ipn != NULL) && (nat->nat_aps != NULL)) + if (ipf_proxy_match(fin, nat) != 0) + continue; + + if ((nat->nat_ifps[1] == NULL) && (ifp != NULL)) { + nat->nat_ifps[1] = ifp; + nat->nat_mtu[1] = GETIFMTU_4(ifp); } + return nat; } /* @@ -3351,80 +4528,127 @@ struct in_addr src , dst; * for "dummy" (FI_IGNORE) lookups. */ find_out_wild_ports: - if (!(flags & NAT_TCPUDP) || !(flags & NAT_SEARCH)) + if (!(flags & NAT_TCPUDP) || !(flags & NAT_SEARCH)) { + NBUMPSIDEX(1, ns_lookup_miss, ns_lookup_miss_1); return NULL; - if (nat_stats.ns_wilds == 0) + } + if (softn->ipf_nat_stats.ns_wilds == 0 || (fin->fin_flx & FI_NOWILD)) { + NBUMPSIDEX(1, ns_lookup_nowild, ns_lookup_nowild_1); return NULL; + } - RWLOCK_EXIT(&ipf_nat); + RWLOCK_EXIT(&softc->ipf_nat); - hv = NAT_HASH_FN(srcip, 0, 0xffffffff); - hv = NAT_HASH_FN(dst.s_addr, hv, ipf_nattable_sz); + hv = NAT_HASH_FN(src.s_addr, 0, 0xffffffff); + hv = NAT_HASH_FN(dst.s_addr, hv, softn->ipf_nat_table_sz); - WRITE_ENTER(&ipf_nat); + WRITE_ENTER(&softc->ipf_nat); - nat = nat_table[0][hv]; + nat = softn->ipf_nat_table[0][hv]; for (; nat; nat = nat->nat_hnext[0]) { - if (ifp != NULL) { - if (nat->nat_dir == NAT_REDIRECT) { - if (ifp != nat->nat_ifps[1]) - continue; - } else { - if (ifp != nat->nat_ifps[0]) - continue; - } + if (nat->nat_ifps[1] != NULL) { + if ((ifp != NULL) && (ifp != nat->nat_ifps[1])) + continue; } - if (nat->nat_p != fin->fin_p) - continue; - if ((nat->nat_inip.s_addr != srcip) || - (nat->nat_oip.s_addr != dst.s_addr)) + if (nat->nat_pr[1] != fin->fin_p) continue; - nflags = nat->nat_flags; - if (!(nflags & (NAT_TCPUDP|SI_WILDP))) + switch (nat->nat_dir & (NAT_INBOUND|NAT_OUTBOUND)) + { + case NAT_INBOUND : + if (nat->nat_v[1] != 4) + continue; + if (nat->nat_ndstaddr != src.s_addr || + nat->nat_nsrcaddr != dst.s_addr) + continue; + break; + case NAT_OUTBOUND : + if (nat->nat_v[0] != 4) + continue; + if (nat->nat_osrcaddr != src.s_addr || + nat->nat_odstaddr != dst.s_addr) + continue; + break; + } + + if (!(nat->nat_flags & (NAT_TCPUDP|SI_WILDP))) continue; - if (nat_wildok(nat, (int)sport, (int)dport, nflags, - NAT_OUTBOUND) == 1) { + if (ipf_nat_wildok(nat, (int)sport, (int)dport, nat->nat_flags, + NAT_OUTBOUND) == 1) { if ((fin->fin_flx & FI_IGNORE) != 0) break; - if ((nflags & SI_CLONE) != 0) { - nat = fr_natclone(fin, nat); + if ((nat->nat_flags & SI_CLONE) != 0) { + nat = ipf_nat_clone(fin, nat); if (nat == NULL) break; } else { - MUTEX_ENTER(&ipf_nat_new); - nat_stats.ns_wilds--; - MUTEX_EXIT(&ipf_nat_new); + MUTEX_ENTER(&softn->ipf_nat_new); + softn->ipf_nat_stats.ns_wilds--; + MUTEX_EXIT(&softn->ipf_nat_new); + } + + if (nat->nat_dir == NAT_OUTBOUND) { + if (nat->nat_osport == 0) { + nat->nat_osport = sport; + nat->nat_nsport = sport; + } + if (nat->nat_odport == 0) { + nat->nat_odport = dport; + nat->nat_ndport = dport; + } + } else if (nat->nat_dir == NAT_INBOUND) { + if (nat->nat_osport == 0) { + nat->nat_osport = dport; + nat->nat_nsport = dport; + } + if (nat->nat_odport == 0) { + nat->nat_odport = sport; + nat->nat_ndport = sport; + } + } + if ((nat->nat_ifps[1] == NULL) && (ifp != NULL)) { + nat->nat_ifps[1] = ifp; + nat->nat_mtu[1] = GETIFMTU_4(ifp); } - nat->nat_inport = sport; - nat->nat_oport = dport; - if (nat->nat_outport == 0) - nat->nat_outport = sport; nat->nat_flags &= ~(SI_W_DPORT|SI_W_SPORT); - nat_tabmove(nat); + ipf_nat_tabmove(softn, nat); break; } } - MUTEX_DOWNGRADE(&ipf_nat); + MUTEX_DOWNGRADE(&softc->ipf_nat); + if (nat == NULL) { + NBUMPSIDE(1, ns_lookup_miss); + } return nat; } /* ------------------------------------------------------------------------ */ -/* Function: nat_lookupredir */ +/* Function: ipf_nat_lookupredir */ /* Returns: nat_t* - NULL == no match, */ /* else pointer to matching NAT entry */ /* Parameters: np(I) - pointer to description of packet to find NAT table */ /* entry for. */ /* */ /* Lookup the NAT tables to search for a matching redirect */ +/* The contents of natlookup_t should imitate those found in a packet that */ +/* would be translated - ie a packet coming in for RDR or going out for MAP.*/ +/* We can do the lookup in one of two ways, imitating an inbound or */ +/* outbound packet. By default we assume outbound, unless IPN_IN is set. */ +/* For IN, the fields are set as follows: */ +/* nl_real* = source information */ +/* nl_out* = destination information (translated) */ +/* For an out packet, the fields are set like this: */ +/* nl_in* = source information (untranslated) */ +/* nl_out* = destination information (translated) */ /* ------------------------------------------------------------------------ */ -nat_t *nat_lookupredir(np) -natlookup_t *np; +nat_t * +ipf_nat_lookupredir(np) + natlookup_t *np; { fr_info_t fi; nat_t *nat; @@ -3450,34 +4674,34 @@ natlookup_t *np; * - default: we have the `in' and `out' address, look for `real'. */ if (np->nl_flags & IPN_IN) { - if ((nat = nat_inlookup(&fi, np->nl_flags, fi.fin_p, - np->nl_realip, np->nl_outip))) { - np->nl_inip = nat->nat_inip; - np->nl_inport = nat->nat_inport; + if ((nat = ipf_nat_inlookup(&fi, np->nl_flags, fi.fin_p, + np->nl_realip, np->nl_outip))) { + np->nl_inip = nat->nat_odstip; + np->nl_inport = nat->nat_odport; } } else { /* * If nl_inip is non null, this is a lookup based on the real * ip address. Else, we use the fake. */ - if ((nat = nat_outlookup(&fi, np->nl_flags, fi.fin_p, + if ((nat = ipf_nat_outlookup(&fi, np->nl_flags, fi.fin_p, np->nl_inip, np->nl_outip))) { if ((np->nl_flags & IPN_FINDFORWARD) != 0) { fr_info_t fin; bzero((char *)&fin, sizeof(fin)); - fin.fin_p = nat->nat_p; - fin.fin_data[0] = ntohs(nat->nat_outport); - fin.fin_data[1] = ntohs(nat->nat_oport); - if (nat_inlookup(&fin, np->nl_flags, fin.fin_p, - nat->nat_outip, - nat->nat_oip) != NULL) { + fin.fin_p = nat->nat_pr[0]; + fin.fin_data[0] = ntohs(nat->nat_ndport); + fin.fin_data[1] = ntohs(nat->nat_nsport); + if (ipf_nat_inlookup(&fin, np->nl_flags, + fin.fin_p, nat->nat_ndstip, + nat->nat_nsrcip) != NULL) { np->nl_flags &= ~IPN_FINDFORWARD; } } - np->nl_realip = nat->nat_outip; - np->nl_realport = nat->nat_outport; + np->nl_realip = nat->nat_ndstip; + np->nl_realport = nat->nat_ndport; } } @@ -3486,46 +4710,54 @@ natlookup_t *np; /* ------------------------------------------------------------------------ */ -/* Function: nat_match */ +/* Function: ipf_nat_match */ /* Returns: int - 0 == no match, 1 == match */ /* Parameters: fin(I) - pointer to packet information */ /* np(I) - pointer to NAT rule */ /* */ /* Pull the matching of a packet against a NAT rule out of that complex */ -/* loop inside fr_checknatin() and lay it out properly in its own function. */ +/* loop inside ipf_nat_checkin() and lay it out properly in its own function. */ /* ------------------------------------------------------------------------ */ -static int nat_match(fin, np) -fr_info_t *fin; -ipnat_t *np; +static int +ipf_nat_match(fin, np) + fr_info_t *fin; + ipnat_t *np; { + ipf_main_softc_t *softc = fin->fin_main_soft; frtuc_t *ft; + int match; - if (fin->fin_v != 4) - return 0; - - if (np->in_p && fin->fin_p != np->in_p) + match = 0; + switch (np->in_osrcatype) + { + case FRI_NORMAL : + match = ((fin->fin_saddr & np->in_osrcmsk) != np->in_osrcaddr); + break; + case FRI_LOOKUP : + match = (*np->in_osrcfunc)(softc, np->in_osrcptr, + 4, &fin->fin_saddr, fin->fin_plen); + break; + } + match ^= ((np->in_flags & IPN_NOTSRC) != 0); + if (match) return 0; - if (fin->fin_out) { - if (!(np->in_redir & (NAT_MAP|NAT_MAPBLK))) - return 0; - if (((fin->fin_fi.fi_saddr & np->in_inmsk) != np->in_inip) - ^ ((np->in_flags & IPN_NOTSRC) != 0)) - return 0; - if (((fin->fin_fi.fi_daddr & np->in_srcmsk) != np->in_srcip) - ^ ((np->in_flags & IPN_NOTDST) != 0)) - return 0; - } else { - if (!(np->in_redir & NAT_REDIRECT)) - return 0; - if (((fin->fin_fi.fi_saddr & np->in_srcmsk) != np->in_srcip) - ^ ((np->in_flags & IPN_NOTSRC) != 0)) - return 0; - if (((fin->fin_fi.fi_daddr & np->in_outmsk) != np->in_outip) - ^ ((np->in_flags & IPN_NOTDST) != 0)) - return 0; + match = 0; + switch (np->in_odstatype) + { + case FRI_NORMAL : + match = ((fin->fin_daddr & np->in_odstmsk) != np->in_odstaddr); + break; + case FRI_LOOKUP : + match = (*np->in_odstfunc)(softc, np->in_odstptr, + 4, &fin->fin_daddr, fin->fin_plen); + break; } + match ^= ((np->in_flags & IPN_NOTDST) != 0); + if (match) + return 0; + ft = &np->in_tuc; if (!(fin->fin_flx & FI_TCPUDP) || (fin->fin_flx & (FI_SHORT|FI_FRAGBODY))) { @@ -3534,28 +4766,33 @@ ipnat_t *np; return 1; } - return fr_tcpudpchk(fin, ft); + return ipf_tcpudpchk(&fin->fin_fi, ft); } /* ------------------------------------------------------------------------ */ -/* Function: nat_update */ +/* Function: ipf_nat_update */ /* Returns: Nil */ -/* Parameters: nat(I) - pointer to NAT structure */ -/* np(I) - pointer to NAT rule */ +/* Parameters: fin(I) - pointer to packet information */ +/* nat(I) - pointer to NAT structure */ /* */ /* Updates the lifetime of a NAT table entry for non-TCP packets. Must be */ -/* called with fin_rev updated - i.e. after calling nat_proto(). */ +/* called with fin_rev updated - i.e. after calling ipf_nat_proto(). */ +/* */ +/* This *MUST* be called after ipf_nat_proto() as it expects fin_rev to */ +/* already be set. */ /* ------------------------------------------------------------------------ */ -void nat_update(fin, nat, np) -fr_info_t *fin; -nat_t *nat; -ipnat_t *np; +void +ipf_nat_update(fin, nat) + fr_info_t *fin; + nat_t *nat; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; ipftq_t *ifq, *ifq2; ipftqent_t *tqe; + ipnat_t *np = nat->nat_ptr; - MUTEX_ENTER(&nat->nat_lock); tqe = &nat->nat_tqe; ifq = tqe->tqe_ifq; @@ -3564,31 +4801,36 @@ ipnat_t *np; * TCP, however, if it is TCP and there is no rule timeout set, * then do not update the timeout here. */ - if (np != NULL) + if (np != NULL) { + np->in_bytes[fin->fin_rev] += fin->fin_plen; ifq2 = np->in_tqehead[fin->fin_rev]; - else + } else { ifq2 = NULL; + } - if (nat->nat_p == IPPROTO_TCP && ifq2 == NULL) { - (void) fr_tcp_age(&nat->nat_tqe, fin, nat_tqb, 0); + if (nat->nat_pr[0] == IPPROTO_TCP && ifq2 == NULL) { + (void) ipf_tcp_age(&nat->nat_tqe, fin, softn->ipf_nat_tcptq, + 0, 2); } else { if (ifq2 == NULL) { - if (nat->nat_p == IPPROTO_UDP) - ifq2 = &nat_udptq; - else if (nat->nat_p == IPPROTO_ICMP) - ifq2 = &nat_icmptq; + if (nat->nat_pr[0] == IPPROTO_UDP) + ifq2 = fin->fin_rev ? &softn->ipf_nat_udpacktq : + &softn->ipf_nat_udptq; + else if (nat->nat_pr[0] == IPPROTO_ICMP || + nat->nat_pr[0] == IPPROTO_ICMPV6) + ifq2 = fin->fin_rev ? &softn->ipf_nat_icmpacktq: + &softn->ipf_nat_icmptq; else - ifq2 = &nat_iptq; + ifq2 = &softn->ipf_nat_iptq; } - fr_movequeue(tqe, ifq, ifq2); + ipf_movequeue(softc->ipf_ticks, tqe, ifq, ifq2); } - MUTEX_EXIT(&nat->nat_lock); } /* ------------------------------------------------------------------------ */ -/* Function: fr_checknatout */ +/* Function: ipf_nat_checkout */ /* Returns: int - -1 == packet failed NAT checks so block it, */ /* 0 == no packet translation occurred, */ /* 1 == packet was successfully translated. */ @@ -3602,30 +4844,49 @@ ipnat_t *np; /* NAT entry if a we matched a NAT rule. Lastly, actually change the */ /* packet header(s) as required. */ /* ------------------------------------------------------------------------ */ -int fr_checknatout(fin, passp) -fr_info_t *fin; -u_32_t *passp; +int +ipf_nat_checkout(fin, passp) + fr_info_t *fin; + u_32_t *passp; { + ipnat_t *np = NULL, *npnext; struct ifnet *ifp, *sifp; + ipf_main_softc_t *softc; + ipf_nat_softc_t *softn; icmphdr_t *icmp = NULL; tcphdr_t *tcp = NULL; int rval, natfailed; - ipnat_t *np = NULL; u_int nflags = 0; u_32_t ipa, iph; int natadd = 1; frentry_t *fr; nat_t *nat; - if (nat_stats.ns_rules == 0 || fr_nat_lock != 0) + if (fin->fin_v == 6) { +#ifdef USE_INET6 + return ipf_nat6_checkout(fin, passp); +#else + return 0; +#endif + } + + softc = fin->fin_main_soft; + softn = softc->ipf_nat_soft; + + if (softn->ipf_nat_lock != 0) + return 0; + if (softn->ipf_nat_stats.ns_rules == 0 && + softn->ipf_nat_instances == NULL) return 0; natfailed = 0; fr = fin->fin_fr; sifp = fin->fin_ifp; - if ((fr != NULL) && !(fr->fr_flags & FR_DUP) && - fr->fr_tif.fd_ifp && fr->fr_tif.fd_ifp != (void *)-1) - fin->fin_ifp = fr->fr_tif.fd_ifp; + if (fr != NULL) { + ifp = fr->fr_tifs[fin->fin_rev].fd_ptr; + if ((ifp != NULL) && (ifp != (void *)-1)) + fin->fin_ifp = ifp; + } ifp = fin->fin_ifp; if (!(fin->fin_flx & FI_SHORT) && (fin->fin_off == 0)) { @@ -3644,116 +4905,152 @@ u_32_t *passp; * This is an incoming packet, so the destination is * the icmp_id and the source port equals 0 */ - if (nat_icmpquerytype4(icmp->icmp_type)) + if ((fin->fin_flx & FI_ICMPQUERY) != 0) nflags = IPN_ICMPQUERY; break; default : break; } - + if ((nflags & IPN_TCPUDP)) tcp = fin->fin_dp; } ipa = fin->fin_saddr; - READ_ENTER(&ipf_nat); + READ_ENTER(&softc->ipf_nat); if ((fin->fin_p == IPPROTO_ICMP) && !(nflags & IPN_ICMPQUERY) && - (nat = nat_icmperror(fin, &nflags, NAT_OUTBOUND))) + (nat = ipf_nat_icmperror(fin, &nflags, NAT_OUTBOUND))) /*EMPTY*/; - else if ((fin->fin_flx & FI_FRAG) && (nat = fr_nat_knownfrag(fin))) + else if ((fin->fin_flx & FI_FRAG) && (nat = ipf_frag_natknown(fin))) natadd = 0; - else if ((nat = nat_outlookup(fin, nflags|NAT_SEARCH, (u_int)fin->fin_p, - fin->fin_src, fin->fin_dst))) { + else if ((nat = ipf_nat_outlookup(fin, nflags|NAT_SEARCH, + (u_int)fin->fin_p, fin->fin_src, + fin->fin_dst))) { nflags = nat->nat_flags; - } else { - u_32_t hv, msk, nmsk; + } else if (fin->fin_off == 0) { + u_32_t hv, msk, nmsk = 0; /* * If there is no current entry in the nat table for this IP#, * create one for it (if there is a matching rule). */ - RWLOCK_EXIT(&ipf_nat); - msk = 0xffffffff; - nmsk = nat_masks; - WRITE_ENTER(&ipf_nat); maskloop: - iph = ipa & htonl(msk); - hv = NAT_HASH_FN(iph, 0, ipf_natrules_sz); - for (np = nat_rules[hv]; np; np = np->in_mnext) - { - if ((np->in_ifps[0] && (np->in_ifps[0] != ifp))) + msk = softn->ipf_nat_map_active_masks[nmsk]; + iph = ipa & msk; + hv = NAT_HASH_FN(iph, 0, softn->ipf_nat_maprules_sz); +retry_roundrobin: + for (np = softn->ipf_nat_map_rules[hv]; np; np = npnext) { + npnext = np->in_mnext; + if ((np->in_ifps[1] && (np->in_ifps[1] != ifp))) continue; - if (np->in_v != fin->fin_v) + if (np->in_v[0] != 4) continue; - if (np->in_p && (np->in_p != fin->fin_p)) + if (np->in_pr[1] && (np->in_pr[1] != fin->fin_p)) continue; - if ((np->in_flags & IPN_RF) && !(np->in_flags & nflags)) + if ((np->in_flags & IPN_RF) && + !(np->in_flags & nflags)) continue; if (np->in_flags & IPN_FILTER) { - if (!nat_match(fin, np)) + switch (ipf_nat_match(fin, np)) + { + case 0 : continue; - } else if ((ipa & np->in_inmsk) != np->in_inip) + case -1 : + rval = -1; + goto outmatchfail; + case 1 : + default : + break; + } + } else if ((ipa & np->in_osrcmsk) != np->in_osrcaddr) continue; if ((fr != NULL) && - !fr_matchtag(&np->in_tag, &fr->fr_nattag)) + !ipf_matchtag(&np->in_tag, &fr->fr_nattag)) continue; - if (*np->in_plabel != '\0') { + if (np->in_plabel != -1) { if (((np->in_flags & IPN_FILTER) == 0) && - (np->in_dport != tcp->th_dport)) + (np->in_odport != fin->fin_data[1])) continue; - if (appr_ok(fin, tcp, np) == 0) + if (ipf_proxy_ok(fin, tcp, np) == 0) continue; } - if ((nat = nat_new(fin, np, NULL, nflags, - NAT_OUTBOUND))) { + if (np->in_flags & IPN_NO) { np->in_hits++; break; - } else - natfailed = -1; - } - if ((np == NULL) && (nmsk != 0)) { - while (nmsk) { - msk <<= 1; - if (nmsk & 0x80000000) - break; - nmsk <<= 1; } - if (nmsk != 0) { - nmsk <<= 1; - goto maskloop; + MUTEX_ENTER(&softn->ipf_nat_new); + /* + * If we've matched a round-robin rule but it has + * moved in the list since we got it, start over as + * this is now no longer correct. + */ + if (npnext != np->in_mnext) { + if ((np->in_flags & IPN_ROUNDR) != 0) { + MUTEX_EXIT(&softn->ipf_nat_new); + goto retry_roundrobin; + } + npnext = np->in_mnext; } + + nat = ipf_nat_add(fin, np, NULL, nflags, NAT_OUTBOUND); + MUTEX_EXIT(&softn->ipf_nat_new); + if (nat != NULL) { + natfailed = 0; + break; + } + natfailed = -1; + } + if ((np == NULL) && (nmsk < softn->ipf_nat_map_max)) { + nmsk++; + goto maskloop; } - MUTEX_DOWNGRADE(&ipf_nat); } if (nat != NULL) { - rval = fr_natout(fin, nat, natadd, nflags); + rval = ipf_nat_out(fin, nat, natadd, nflags); if (rval == 1) { MUTEX_ENTER(&nat->nat_lock); - nat->nat_ref++; + ipf_nat_update(fin, nat); + nat->nat_bytes[1] += fin->fin_plen; + nat->nat_pkts[1]++; + fin->fin_pktnum = nat->nat_pkts[1]; MUTEX_EXIT(&nat->nat_lock); - fin->fin_nat = nat; } } else rval = natfailed; - RWLOCK_EXIT(&ipf_nat); +outmatchfail: + RWLOCK_EXIT(&softc->ipf_nat); - if (rval == -1) { - if (passp != NULL) + switch (rval) + { + case -1 : + if (passp != NULL) { + DT1(frb_natv4out, fr_info_t *, fin); + NBUMPSIDED(1, ns_drop); *passp = FR_BLOCK; + fin->fin_reason = FRB_NATV4; + } fin->fin_flx |= FI_BADNAT; + NBUMPSIDED(1, ns_badnat); + break; + case 0 : + NBUMPSIDE(1, ns_ignored); + break; + case 1 : + NBUMPSIDE(1, ns_translated); + break; } fin->fin_ifp = sifp; return rval; } /* ------------------------------------------------------------------------ */ -/* Function: fr_natout */ +/* Function: ipf_nat_out */ /* Returns: int - -1 == packet failed NAT checks so block it, */ /* 1 == packet was successfully translated. */ /* Parameters: fin(I) - pointer to packet information */ @@ -3763,30 +5060,27 @@ maskloop: /* */ /* Translate a packet coming "out" on an interface. */ /* ------------------------------------------------------------------------ */ -int fr_natout(fin, nat, natadd, nflags) -fr_info_t *fin; -nat_t *nat; -int natadd; -u_32_t nflags; +int +ipf_nat_out(fin, nat, natadd, nflags) + fr_info_t *fin; + nat_t *nat; + int natadd; + u_32_t nflags; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; icmphdr_t *icmp; - u_short *csump; tcphdr_t *tcp; ipnat_t *np; + int skip; int i; tcp = NULL; icmp = NULL; - csump = NULL; np = nat->nat_ptr; if ((natadd != 0) && (fin->fin_flx & FI_FRAG) && (np != NULL)) - (void) fr_nat_newfrag(fin, 0, nat); - - MUTEX_ENTER(&nat->nat_lock); - nat->nat_bytes[1] += fin->fin_plen; - nat->nat_pkts[1]++; - MUTEX_EXIT(&nat->nat_lock); + (void) ipf_frag_natnew(softc, fin, 0, nat); /* * Fix up checksums, not by recalculating them, but @@ -3796,83 +5090,240 @@ u_32_t nflags; * IPFilter is called before the checksum needs calculating so there * is no call to modify whatever is in the header now. */ - if (fin->fin_v == 4) { - if (nflags == IPN_ICMPERR) { - u_32_t s1, s2, sumd; + if (nflags == IPN_ICMPERR) { + u_32_t s1, s2, sumd, msumd; - s1 = LONG_SUM(ntohl(fin->fin_saddr)); - s2 = LONG_SUM(ntohl(nat->nat_outip.s_addr)); - CALC_SUMD(s1, s2, sumd); - fix_outcksum(fin, &fin->fin_ip->ip_sum, sumd); + s1 = LONG_SUM(ntohl(fin->fin_saddr)); + if (nat->nat_dir == NAT_OUTBOUND) { + s2 = LONG_SUM(ntohl(nat->nat_nsrcaddr)); + } else { + s2 = LONG_SUM(ntohl(nat->nat_odstaddr)); } -#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) || defined(linux) - else { - if (nat->nat_dir == NAT_OUTBOUND) - fix_outcksum(fin, &fin->fin_ip->ip_sum, - nat->nat_ipsumd); - else - fix_incksum(fin, &fin->fin_ip->ip_sum, - nat->nat_ipsumd); + CALC_SUMD(s1, s2, sumd); + msumd = sumd; + + s1 = LONG_SUM(ntohl(fin->fin_daddr)); + if (nat->nat_dir == NAT_OUTBOUND) { + s2 = LONG_SUM(ntohl(nat->nat_ndstaddr)); + } else { + s2 = LONG_SUM(ntohl(nat->nat_osrcaddr)); } + CALC_SUMD(s1, s2, sumd); + msumd += sumd; + + ipf_fix_outcksum(0, &fin->fin_ip->ip_sum, msumd, 0); + } +#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) || \ + defined(linux) || defined(BRIDGE_IPF) + else { + /* + * Strictly speaking, this isn't necessary on BSD + * kernels because they do checksum calculation after + * this code has run BUT if ipfilter is being used + * to do NAT as a bridge, that code doesn't exist. + */ + switch (nat->nat_dir) + { + case NAT_OUTBOUND : + ipf_fix_outcksum(fin->fin_cksum & FI_CK_L4PART, + &fin->fin_ip->ip_sum, + nat->nat_ipsumd, 0); + break; + + case NAT_INBOUND : + ipf_fix_incksum(fin->fin_cksum & FI_CK_L4PART, + &fin->fin_ip->ip_sum, + nat->nat_ipsumd, 0); + break; + + default : + break; + } + } +#endif + + /* + * Address assignment is after the checksum modification because + * we are using the address in the packet for determining the + * correct checksum offset (the ICMP error could be coming from + * anyone...) + */ + switch (nat->nat_dir) + { + case NAT_OUTBOUND : + fin->fin_ip->ip_src = nat->nat_nsrcip; + fin->fin_saddr = nat->nat_nsrcaddr; + fin->fin_ip->ip_dst = nat->nat_ndstip; + fin->fin_daddr = nat->nat_ndstaddr; + break; + + case NAT_INBOUND : + fin->fin_ip->ip_src = nat->nat_odstip; + fin->fin_saddr = nat->nat_ndstaddr; + fin->fin_ip->ip_dst = nat->nat_osrcip; + fin->fin_daddr = nat->nat_nsrcaddr; + break; + + case NAT_DIVERTIN : + { + mb_t *m; + + skip = ipf_nat_decap(fin, nat); + if (skip <= 0) { + NBUMPSIDED(1, ns_decap_fail); + return -1; + } + + m = fin->fin_m; + +#if defined(MENTAT) && defined(_KERNEL) + m->b_rptr += skip; +#else + m->m_data += skip; + m->m_len -= skip; + +# ifdef M_PKTHDR + if (m->m_flags & M_PKTHDR) + m->m_pkthdr.len -= skip; +# endif +#endif + + MUTEX_ENTER(&nat->nat_lock); + ipf_nat_update(fin, nat); + MUTEX_EXIT(&nat->nat_lock); + fin->fin_flx |= FI_NATED; + if (np != NULL && np->in_tag.ipt_num[0] != 0) + fin->fin_nattag = &np->in_tag; + return 1; + /* NOTREACHED */ + } + + case NAT_DIVERTOUT : + { + u_32_t s1, s2, sumd; + udphdr_t *uh; + ip_t *ip; + mb_t *m; + + m = M_DUP(np->in_divmp); + if (m == NULL) { + NBUMPSIDED(1, ns_divert_dup); + return -1; + } + + ip = MTOD(m, ip_t *); + ip->ip_id = htons(ipf_nextipid(fin)); + s2 = ntohs(ip->ip_id); + + s1 = ip->ip_len; + ip->ip_len = ntohs(ip->ip_len); + ip->ip_len += fin->fin_plen; + ip->ip_len = htons(ip->ip_len); + s2 += ntohs(ip->ip_len); + CALC_SUMD(s1, s2, sumd); + + uh = (udphdr_t *)(ip + 1); + uh->uh_ulen += fin->fin_plen; + uh->uh_ulen = htons(uh->uh_ulen); +#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) || \ + defined(linux) || defined(BRIDGE_IPF) + ipf_fix_outcksum(0, &ip->ip_sum, sumd, 0); #endif + + PREP_MB_T(fin, m); + + fin->fin_src = ip->ip_src; + fin->fin_dst = ip->ip_dst; + fin->fin_ip = ip; + fin->fin_plen += sizeof(ip_t) + 8; /* UDP + IPv4 hdr */ + fin->fin_dlen += sizeof(ip_t) + 8; /* UDP + IPv4 hdr */ + + nflags &= ~IPN_TCPUDPICMP; + + break; + } + + default : + break; } if (!(fin->fin_flx & FI_SHORT) && (fin->fin_off == 0)) { - if ((nat->nat_outport != 0) && (nflags & IPN_TCPUDP)) { + u_short *csump; + + if ((nat->nat_nsport != 0) && (nflags & IPN_TCPUDP)) { tcp = fin->fin_dp; - tcp->th_sport = nat->nat_outport; - fin->fin_data[0] = ntohs(nat->nat_outport); + switch (nat->nat_dir) + { + case NAT_OUTBOUND : + tcp->th_sport = nat->nat_nsport; + fin->fin_data[0] = ntohs(nat->nat_nsport); + tcp->th_dport = nat->nat_ndport; + fin->fin_data[1] = ntohs(nat->nat_ndport); + break; + + case NAT_INBOUND : + tcp->th_sport = nat->nat_odport; + fin->fin_data[0] = ntohs(nat->nat_odport); + tcp->th_dport = nat->nat_osport; + fin->fin_data[1] = ntohs(nat->nat_osport); + break; + } } - if ((nat->nat_outport != 0) && (nflags & IPN_ICMPQUERY)) { + if ((nat->nat_nsport != 0) && (nflags & IPN_ICMPQUERY)) { icmp = fin->fin_dp; - icmp->icmp_id = nat->nat_outport; + icmp->icmp_id = nat->nat_nicmpid; } - csump = nat_proto(fin, nat, nflags); - } - - fin->fin_ip->ip_src = nat->nat_outip; + csump = ipf_nat_proto(fin, nat, nflags); - nat_update(fin, nat, np); - - /* - * The above comments do not hold for layer 4 (or higher) checksums... - */ - if (csump != NULL) { - if (nat->nat_dir == NAT_OUTBOUND) - fix_outcksum(fin, csump, nat->nat_sumd[1]); - else - fix_incksum(fin, csump, nat->nat_sumd[1]); + /* + * The above comments do not hold for layer 4 (or higher) + * checksums... + */ + if (csump != NULL) { + if (nat->nat_dir == NAT_OUTBOUND) + ipf_fix_outcksum(fin->fin_cksum, csump, + nat->nat_sumd[0], + nat->nat_sumd[1] + + fin->fin_dlen); + else + ipf_fix_incksum(fin->fin_cksum, csump, + nat->nat_sumd[0], + nat->nat_sumd[1] + + fin->fin_dlen); + } } -#ifdef IPFILTER_SYNC - ipfsync_update(SMC_NAT, fin, nat->nat_sync); -#endif + + ipf_sync_update(softc, SMC_NAT, fin, nat->nat_sync); /* ------------------------------------------------------------- */ - /* A few quick notes: */ - /* Following are test conditions prior to calling the */ - /* appr_check routine. */ - /* */ - /* A NULL tcp indicates a non TCP/UDP packet. When dealing */ - /* with a redirect rule, we attempt to match the packet's */ - /* source port against in_dport, otherwise we'd compare the */ - /* packet's destination. */ + /* A few quick notes: */ + /* Following are test conditions prior to calling the */ + /* ipf_proxy_check routine. */ + /* */ + /* A NULL tcp indicates a non TCP/UDP packet. When dealing */ + /* with a redirect rule, we attempt to match the packet's */ + /* source port against in_dport, otherwise we'd compare the */ + /* packet's destination. */ /* ------------------------------------------------------------- */ if ((np != NULL) && (np->in_apr != NULL)) { - i = appr_check(fin, nat); - if (i == 0) + i = ipf_proxy_check(fin, nat); + if (i == 0) { i = 1; - } else + } else if (i == -1) { + NBUMPSIDED(1, ns_ipf_proxy_fail); + } + } else { i = 1; - ATOMIC_INCL(nat_stats.ns_mapped[1]); + } fin->fin_flx |= FI_NATED; return i; } /* ------------------------------------------------------------------------ */ -/* Function: fr_checknatin */ +/* Function: ipf_nat_checkin */ /* Returns: int - -1 == packet failed NAT checks so block it, */ /* 0 == no packet translation occurred, */ /* 1 == packet was successfully translated. */ @@ -3886,22 +5337,31 @@ u_32_t nflags; /* NAT entry if a we matched a NAT rule. Lastly, actually change the */ /* packet header(s) as required. */ /* ------------------------------------------------------------------------ */ -int fr_checknatin(fin, passp) -fr_info_t *fin; -u_32_t *passp; +int +ipf_nat_checkin(fin, passp) + fr_info_t *fin; + u_32_t *passp; { + ipf_main_softc_t *softc; + ipf_nat_softc_t *softn; u_int nflags, natadd; + ipnat_t *np, *npnext; int rval, natfailed; struct ifnet *ifp; struct in_addr in; icmphdr_t *icmp; tcphdr_t *tcp; u_short dport; - ipnat_t *np; nat_t *nat; u_32_t iph; - if (nat_stats.ns_rules == 0 || fr_nat_lock != 0) + softc = fin->fin_main_soft; + softn = softc->ipf_nat_soft; + + if (softn->ipf_nat_lock != 0) + return 0; + if (softn->ipf_nat_stats.ns_rules == 0 && + softn->ipf_nat_instances == NULL) return 0; tcp = NULL; @@ -3928,182 +5388,213 @@ u_32_t *passp; * This is an incoming packet, so the destination is * the icmp_id and the source port equals 0 */ - if (nat_icmpquerytype4(icmp->icmp_type)) { + if ((fin->fin_flx & FI_ICMPQUERY) != 0) { nflags = IPN_ICMPQUERY; - dport = icmp->icmp_id; + dport = icmp->icmp_id; } break; default : break; } - + if ((nflags & IPN_TCPUDP)) { tcp = fin->fin_dp; - dport = tcp->th_dport; + dport = fin->fin_data[1]; } } in = fin->fin_dst; - READ_ENTER(&ipf_nat); + READ_ENTER(&softc->ipf_nat); if ((fin->fin_p == IPPROTO_ICMP) && !(nflags & IPN_ICMPQUERY) && - (nat = nat_icmperror(fin, &nflags, NAT_INBOUND))) + (nat = ipf_nat_icmperror(fin, &nflags, NAT_INBOUND))) /*EMPTY*/; - else if ((fin->fin_flx & FI_FRAG) && (nat = fr_nat_knownfrag(fin))) + else if ((fin->fin_flx & FI_FRAG) && (nat = ipf_frag_natknown(fin))) natadd = 0; - else if ((nat = nat_inlookup(fin, nflags|NAT_SEARCH, (u_int)fin->fin_p, - fin->fin_src, in))) { + else if ((nat = ipf_nat_inlookup(fin, nflags|NAT_SEARCH, + (u_int)fin->fin_p, + fin->fin_src, in))) { nflags = nat->nat_flags; - } else { - u_32_t hv, msk, rmsk; + } else if (fin->fin_off == 0) { + u_32_t hv, msk, rmsk = 0; - RWLOCK_EXIT(&ipf_nat); - rmsk = rdr_masks; - msk = 0xffffffff; - WRITE_ENTER(&ipf_nat); /* * If there is no current entry in the nat table for this IP#, * create one for it (if there is a matching rule). */ maskloop: - iph = in.s_addr & htonl(msk); - hv = NAT_HASH_FN(iph, 0, ipf_rdrrules_sz); - for (np = rdr_rules[hv]; np; np = np->in_rnext) { + msk = softn->ipf_nat_rdr_active_masks[rmsk]; + iph = in.s_addr & msk; + hv = NAT_HASH_FN(iph, 0, softn->ipf_nat_rdrrules_sz); +retry_roundrobin: + /* TRACE (iph,msk,rmsk,hv,softn->ipf_nat_rdrrules_sz) */ + for (np = softn->ipf_nat_rdr_rules[hv]; np; np = npnext) { + npnext = np->in_rnext; if (np->in_ifps[0] && (np->in_ifps[0] != ifp)) continue; - if (np->in_v != fin->fin_v) + if (np->in_v[0] != 4) continue; - if (np->in_p && (np->in_p != fin->fin_p)) + if (np->in_pr[0] && (np->in_pr[0] != fin->fin_p)) continue; if ((np->in_flags & IPN_RF) && !(np->in_flags & nflags)) continue; if (np->in_flags & IPN_FILTER) { - if (!nat_match(fin, np)) + switch (ipf_nat_match(fin, np)) + { + case 0 : continue; + case -1 : + rval = -1; + goto inmatchfail; + case 1 : + default : + break; + } } else { - if ((in.s_addr & np->in_outmsk) != np->in_outip) + if ((in.s_addr & np->in_odstmsk) != + np->in_odstaddr) continue; - if (np->in_pmin && - ((ntohs(np->in_pmax) < ntohs(dport)) || - (ntohs(dport) < ntohs(np->in_pmin)))) + if (np->in_odport && + ((np->in_dtop < dport) || + (dport < np->in_odport))) continue; } - if (*np->in_plabel != '\0') { - if (!appr_ok(fin, tcp, np)) { + if (np->in_plabel != -1) { + if (!ipf_proxy_ok(fin, tcp, np)) { continue; } } - nat = nat_new(fin, np, NULL, nflags, NAT_INBOUND); - if (nat != NULL) { + if (np->in_flags & IPN_NO) { np->in_hits++; break; - } else - natfailed = -1; - } + } - if ((np == NULL) && (rmsk != 0)) { - while (rmsk) { - msk <<= 1; - if (rmsk & 0x80000000) - break; - rmsk <<= 1; + MUTEX_ENTER(&softn->ipf_nat_new); + /* + * If we've matched a round-robin rule but it has + * moved in the list since we got it, start over as + * this is now no longer correct. + */ + if (npnext != np->in_rnext) { + if ((np->in_flags & IPN_ROUNDR) != 0) { + MUTEX_EXIT(&softn->ipf_nat_new); + goto retry_roundrobin; + } + npnext = np->in_rnext; } - if (rmsk != 0) { - rmsk <<= 1; - goto maskloop; + + nat = ipf_nat_add(fin, np, NULL, nflags, NAT_INBOUND); + MUTEX_EXIT(&softn->ipf_nat_new); + if (nat != NULL) { + natfailed = 0; + break; } + natfailed = -1; + } + if ((np == NULL) && (rmsk < softn->ipf_nat_rdr_max)) { + rmsk++; + goto maskloop; } - MUTEX_DOWNGRADE(&ipf_nat); } + if (nat != NULL) { - rval = fr_natin(fin, nat, natadd, nflags); + rval = ipf_nat_in(fin, nat, natadd, nflags); if (rval == 1) { MUTEX_ENTER(&nat->nat_lock); - nat->nat_ref++; + ipf_nat_update(fin, nat); + nat->nat_bytes[0] += fin->fin_plen; + nat->nat_pkts[0]++; + fin->fin_pktnum = nat->nat_pkts[0]; MUTEX_EXIT(&nat->nat_lock); - fin->fin_nat = nat; - fin->fin_state = nat->nat_state; } } else rval = natfailed; - RWLOCK_EXIT(&ipf_nat); +inmatchfail: + RWLOCK_EXIT(&softc->ipf_nat); - if (rval == -1) { - if (passp != NULL) + switch (rval) + { + case -1 : + if (passp != NULL) { + DT1(frb_natv4in, fr_info_t *, fin); + NBUMPSIDED(0, ns_drop); *passp = FR_BLOCK; + fin->fin_reason = FRB_NATV4; + } fin->fin_flx |= FI_BADNAT; + NBUMPSIDED(0, ns_badnat); + break; + case 0 : + NBUMPSIDE(0, ns_ignored); + break; + case 1 : + NBUMPSIDE(0, ns_translated); + break; } return rval; } /* ------------------------------------------------------------------------ */ -/* Function: fr_natin */ +/* Function: ipf_nat_in */ /* Returns: int - -1 == packet failed NAT checks so block it, */ /* 1 == packet was successfully translated. */ /* Parameters: fin(I) - pointer to packet information */ /* nat(I) - pointer to NAT structure */ /* natadd(I) - flag indicating if it is safe to add frag cache */ /* nflags(I) - NAT flags set for this packet */ -/* Locks Held: ipf_nat (READ) */ +/* Locks Held: ipf_nat(READ) */ /* */ /* Translate a packet coming "in" on an interface. */ /* ------------------------------------------------------------------------ */ -int fr_natin(fin, nat, natadd, nflags) -fr_info_t *fin; -nat_t *nat; -int natadd; -u_32_t nflags; +int +ipf_nat_in(fin, nat, natadd, nflags) + fr_info_t *fin; + nat_t *nat; + int natadd; + u_32_t nflags; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + u_32_t sumd, ipsumd, sum1, sum2; icmphdr_t *icmp; - u_short *csump; tcphdr_t *tcp; ipnat_t *np; + int skip; int i; tcp = NULL; - csump = NULL; np = nat->nat_ptr; fin->fin_fr = nat->nat_fr; if (np != NULL) { if ((natadd != 0) && (fin->fin_flx & FI_FRAG)) - (void) fr_nat_newfrag(fin, 0, nat); + (void) ipf_frag_natnew(softc, fin, 0, nat); /* ------------------------------------------------------------- */ - /* A few quick notes: */ - /* Following are test conditions prior to calling the */ - /* appr_check routine. */ - /* */ - /* A NULL tcp indicates a non TCP/UDP packet. When dealing */ - /* with a map rule, we attempt to match the packet's */ - /* source port against in_dport, otherwise we'd compare the */ - /* packet's destination. */ + /* A few quick notes: */ + /* Following are test conditions prior to calling the */ + /* ipf_proxy_check routine. */ + /* */ + /* A NULL tcp indicates a non TCP/UDP packet. When dealing */ + /* with a map rule, we attempt to match the packet's */ + /* source port against in_dport, otherwise we'd compare the */ + /* packet's destination. */ /* ------------------------------------------------------------- */ if (np->in_apr != NULL) { - i = appr_check(fin, nat); + i = ipf_proxy_check(fin, nat); if (i == -1) { + NBUMPSIDED(0, ns_ipf_proxy_fail); return -1; } } } -#ifdef IPFILTER_SYNC - ipfsync_update(SMC_NAT, fin, nat->nat_sync); -#endif - - MUTEX_ENTER(&nat->nat_lock); - nat->nat_bytes[0] += fin->fin_plen; - nat->nat_pkts[0]++; - MUTEX_EXIT(&nat->nat_lock); - - fin->fin_ip->ip_dst = nat->nat_inip; - fin->fin_fi.fi_daddr = nat->nat_inip.s_addr; - if (nflags & IPN_TCPUDP) - tcp = fin->fin_dp; + ipf_sync_update(softc, SMC_NAT, fin, nat->nat_sync); + ipsumd = nat->nat_ipsumd; /* * Fix up checksums, not by recalculating them, but * simply computing adjustments. @@ -4114,42 +5605,166 @@ u_32_t nflags; * fast forwarding (so that it doesn't need to be recomputed) but with * header checksum offloading, perhaps it is a moot point. */ + + switch (nat->nat_dir) + { + case NAT_INBOUND : + if ((fin->fin_flx & FI_ICMPERR) == 0) { + fin->fin_ip->ip_src = nat->nat_nsrcip; + fin->fin_saddr = nat->nat_nsrcaddr; + } else { + sum1 = nat->nat_osrcaddr; + sum2 = nat->nat_nsrcaddr; + CALC_SUMD(sum1, sum2, sumd); + ipsumd -= sumd; + } + fin->fin_ip->ip_dst = nat->nat_ndstip; + fin->fin_daddr = nat->nat_ndstaddr; #if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) || \ defined(__osf__) || defined(linux) - if (nat->nat_dir == NAT_OUTBOUND) - fix_incksum(fin, &fin->fin_ip->ip_sum, nat->nat_ipsumd); - else - fix_outcksum(fin, &fin->fin_ip->ip_sum, nat->nat_ipsumd); + ipf_fix_outcksum(0, &fin->fin_ip->ip_sum, ipsumd, 0); #endif + break; - if (!(fin->fin_flx & FI_SHORT) && (fin->fin_off == 0)) { - if ((nat->nat_inport != 0) && (nflags & IPN_TCPUDP)) { - tcp->th_dport = nat->nat_inport; - fin->fin_data[1] = ntohs(nat->nat_inport); + case NAT_OUTBOUND : + if ((fin->fin_flx & FI_ICMPERR) == 0) { + fin->fin_ip->ip_src = nat->nat_odstip; + fin->fin_saddr = nat->nat_odstaddr; + } else { + sum1 = nat->nat_odstaddr; + sum2 = nat->nat_ndstaddr; + CALC_SUMD(sum1, sum2, sumd); + ipsumd -= sumd; } + fin->fin_ip->ip_dst = nat->nat_osrcip; + fin->fin_daddr = nat->nat_osrcaddr; +#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) || \ + defined(__osf__) || defined(linux) + ipf_fix_incksum(0, &fin->fin_ip->ip_sum, ipsumd, 0); +#endif + break; + case NAT_DIVERTIN : + { + udphdr_t *uh; + ip_t *ip; + mb_t *m; - if ((nat->nat_inport != 0) && (nflags & IPN_ICMPQUERY)) { - icmp = fin->fin_dp; + m = M_DUP(np->in_divmp); + if (m == NULL) { + NBUMPSIDED(0, ns_divert_dup); + return -1; + } + + ip = MTOD(m, ip_t *); + ip->ip_id = htons(ipf_nextipid(fin)); + sum1 = ntohs(ip->ip_len); + ip->ip_len = ntohs(ip->ip_len); + ip->ip_len += fin->fin_plen; + ip->ip_len = htons(ip->ip_len); + + uh = (udphdr_t *)(ip + 1); + uh->uh_ulen += fin->fin_plen; + uh->uh_ulen = htons(uh->uh_ulen); + + sum2 = ntohs(ip->ip_id) + ntohs(ip->ip_len); + sum2 += ntohs(ip->ip_off) & IP_DF; + CALC_SUMD(sum1, sum2, sumd); + +#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) || \ + defined(__osf__) || defined(linux) + ipf_fix_outcksum(0, &ip->ip_sum, sumd, 0); +#endif + PREP_MB_T(fin, m); + + fin->fin_ip = ip; + fin->fin_plen += sizeof(ip_t) + 8; /* UDP + new IPv4 hdr */ + fin->fin_dlen += sizeof(ip_t) + 8; /* UDP + old IPv4 hdr */ + + nflags &= ~IPN_TCPUDPICMP; + + break; + } + + case NAT_DIVERTOUT : + { + mb_t *m; - icmp->icmp_id = nat->nat_inport; + skip = ipf_nat_decap(fin, nat); + if (skip <= 0) { + NBUMPSIDED(0, ns_decap_fail); + return -1; } - csump = nat_proto(fin, nat, nflags); + m = fin->fin_m; + +#if defined(MENTAT) && defined(_KERNEL) + m->b_rptr += skip; +#else + m->m_data += skip; + m->m_len -= skip; + +# ifdef M_PKTHDR + if (m->m_flags & M_PKTHDR) + m->m_pkthdr.len -= skip; +# endif +#endif + + ipf_nat_update(fin, nat); + nflags &= ~IPN_TCPUDPICMP; + fin->fin_flx |= FI_NATED; + if (np != NULL && np->in_tag.ipt_num[0] != 0) + fin->fin_nattag = &np->in_tag; + return 1; + /* NOTREACHED */ + } } + if (nflags & IPN_TCPUDP) + tcp = fin->fin_dp; - nat_update(fin, nat, np); + if (!(fin->fin_flx & FI_SHORT) && (fin->fin_off == 0)) { + u_short *csump; - /* - * The above comments do not hold for layer 4 (or higher) checksums... - */ - if (csump != NULL) { - if (nat->nat_dir == NAT_OUTBOUND) - fix_incksum(fin, csump, nat->nat_sumd[0]); - else - fix_outcksum(fin, csump, nat->nat_sumd[0]); + if ((nat->nat_odport != 0) && (nflags & IPN_TCPUDP)) { + switch (nat->nat_dir) + { + case NAT_INBOUND : + tcp->th_sport = nat->nat_nsport; + fin->fin_data[0] = ntohs(nat->nat_nsport); + tcp->th_dport = nat->nat_ndport; + fin->fin_data[1] = ntohs(nat->nat_ndport); + break; + + case NAT_OUTBOUND : + tcp->th_sport = nat->nat_odport; + fin->fin_data[0] = ntohs(nat->nat_odport); + tcp->th_dport = nat->nat_osport; + fin->fin_data[1] = ntohs(nat->nat_osport); + break; + } + } + + + if ((nat->nat_odport != 0) && (nflags & IPN_ICMPQUERY)) { + icmp = fin->fin_dp; + + icmp->icmp_id = nat->nat_nicmpid; + } + + csump = ipf_nat_proto(fin, nat, nflags); + + /* + * The above comments do not hold for layer 4 (or higher) + * checksums... + */ + if (csump != NULL) { + if (nat->nat_dir == NAT_OUTBOUND) + ipf_fix_incksum(0, csump, nat->nat_sumd[0], 0); + else + ipf_fix_outcksum(0, csump, nat->nat_sumd[0], 0); + } } - ATOMIC_INCL(nat_stats.ns_mapped[0]); + fin->fin_flx |= FI_NATED; if (np != NULL && np->in_tag.ipt_num[0] != 0) fin->fin_nattag = &np->in_tag; @@ -4158,7 +5773,7 @@ u_32_t nflags; /* ------------------------------------------------------------------------ */ -/* Function: nat_proto */ +/* Function: ipf_nat_proto */ /* Returns: u_short* - pointer to transport header checksum to update, */ /* NULL if the transport protocol is not recognised */ /* as needing a checksum update. */ @@ -4171,10 +5786,11 @@ u_32_t nflags; /* that is not strictly 'address' translation, such as clamping the MSS in */ /* TCP down to a specific value, then do it from here. */ /* ------------------------------------------------------------------------ */ -u_short *nat_proto(fin, nat, nflags) -fr_info_t *fin; -nat_t *nat; -u_int nflags; +u_short * +ipf_nat_proto(fin, nat, nflags) + fr_info_t *fin; + nat_t *nat; + u_int nflags; { icmphdr_t *icmp; u_short *csump; @@ -4183,9 +5799,9 @@ u_int nflags; csump = NULL; if (fin->fin_out == 0) { - fin->fin_rev = (nat->nat_dir == NAT_OUTBOUND); + fin->fin_rev = (nat->nat_dir & NAT_OUTBOUND); } else { - fin->fin_rev = (nat->nat_dir == NAT_INBOUND); + fin->fin_rev = ((nat->nat_dir & NAT_OUTBOUND) == 0); } switch (fin->fin_p) @@ -4193,22 +5809,25 @@ u_int nflags; case IPPROTO_TCP : tcp = fin->fin_dp; - csump = &tcp->th_sum; + if ((nflags & IPN_TCP) != 0) + csump = &tcp->th_sum; /* * Do a MSS CLAMPING on a SYN packet, * only deal IPv4 for now. */ if ((nat->nat_mssclamp != 0) && (tcp->th_flags & TH_SYN) != 0) - nat_mssclamp(tcp, nat->nat_mssclamp, fin, csump); + ipf_nat_mssclamp(tcp, nat->nat_mssclamp, fin, csump); break; case IPPROTO_UDP : udp = fin->fin_dp; - if (udp->uh_sum) - csump = &udp->uh_sum; + if ((nflags & IPN_UDP) != 0) { + if (udp->uh_sum != 0) + csump = &udp->uh_sum; + } break; case IPPROTO_ICMP : @@ -4219,164 +5838,108 @@ u_int nflags; csump = &icmp->icmp_cksum; } break; - } - return csump; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: fr_natunload */ -/* Returns: Nil */ -/* Parameters: Nil */ -/* */ -/* Free all memory used by NAT structures allocated at runtime. */ -/* ------------------------------------------------------------------------ */ -void fr_natunload() -{ - ipftq_t *ifq, *ifqnext; - - (void) nat_clearlist(); - (void) nat_flushtable(); - - /* - * Proxy timeout queues are not cleaned here because although they - * exist on the NAT list, appr_unload is called after fr_natunload - * and the proxies actually are responsible for them being created. - * Should the proxy timeouts have their own list? There's no real - * justification as this is the only complication. - */ - for (ifq = nat_utqe; ifq != NULL; ifq = ifqnext) { - ifqnext = ifq->ifq_next; - if (((ifq->ifq_flags & IFQF_PROXY) == 0) && - (fr_deletetimeoutqueue(ifq) == 0)) - fr_freetimeoutqueue(ifq); - } - - if (nat_table[0] != NULL) { - KFREES(nat_table[0], sizeof(nat_t *) * ipf_nattable_sz); - nat_table[0] = NULL; - } - if (nat_table[1] != NULL) { - KFREES(nat_table[1], sizeof(nat_t *) * ipf_nattable_sz); - nat_table[1] = NULL; - } - if (nat_rules != NULL) { - KFREES(nat_rules, sizeof(ipnat_t *) * ipf_natrules_sz); - nat_rules = NULL; - } - if (rdr_rules != NULL) { - KFREES(rdr_rules, sizeof(ipnat_t *) * ipf_rdrrules_sz); - rdr_rules = NULL; - } - if (maptable != NULL) { - KFREES(maptable, sizeof(hostmap_t *) * ipf_hostmap_sz); - maptable = NULL; - } - if (nat_stats.ns_bucketlen[0] != NULL) { - KFREES(nat_stats.ns_bucketlen[0], - sizeof(u_long *) * ipf_nattable_sz); - nat_stats.ns_bucketlen[0] = NULL; - } - if (nat_stats.ns_bucketlen[1] != NULL) { - KFREES(nat_stats.ns_bucketlen[1], - sizeof(u_long *) * ipf_nattable_sz); - nat_stats.ns_bucketlen[1] = NULL; - } - if (fr_nat_maxbucket_reset == 1) - fr_nat_maxbucket = 0; - - if (fr_nat_init == 1) { - fr_nat_init = 0; - fr_sttab_destroy(nat_tqb); - - RW_DESTROY(&ipf_natfrag); - RW_DESTROY(&ipf_nat); +#ifdef USE_INET6 + case IPPROTO_ICMPV6 : + { + struct icmp6_hdr *icmp6 = (struct icmp6_hdr *)fin->fin_dp; - MUTEX_DESTROY(&ipf_nat_new); - MUTEX_DESTROY(&ipf_natio); + icmp6 = fin->fin_dp; - MUTEX_DESTROY(&nat_udptq.ifq_lock); - MUTEX_DESTROY(&nat_icmptq.ifq_lock); - MUTEX_DESTROY(&nat_iptq.ifq_lock); + if ((nflags & IPN_ICMPQUERY) != 0) { + if (icmp6->icmp6_cksum != 0) + csump = &icmp6->icmp6_cksum; + } + break; + } +#endif } + return csump; } /* ------------------------------------------------------------------------ */ -/* Function: fr_natexpire */ +/* Function: ipf_nat_expire */ /* Returns: Nil */ -/* Parameters: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ /* */ /* Check all of the timeout queues for entries at the top which need to be */ /* expired. */ /* ------------------------------------------------------------------------ */ -void fr_natexpire() +void +ipf_nat_expire(softc) + ipf_main_softc_t *softc; { + ipf_nat_softc_t *softn = softc->ipf_nat_soft; ipftq_t *ifq, *ifqnext; ipftqent_t *tqe, *tqn; -#if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL) - int s; -#endif int i; + SPL_INT(s); SPL_NET(s); - WRITE_ENTER(&ipf_nat); - for (ifq = nat_tqb, i = 0; ifq != NULL; ifq = ifq->ifq_next) { + WRITE_ENTER(&softc->ipf_nat); + for (ifq = softn->ipf_nat_tcptq, i = 0; ifq != NULL; + ifq = ifq->ifq_next) { for (tqn = ifq->ifq_head; ((tqe = tqn) != NULL); i++) { - if (tqe->tqe_die > fr_ticks) + if (tqe->tqe_die > softc->ipf_ticks) break; tqn = tqe->tqe_next; - nat_delete(tqe->tqe_parent, NL_EXPIRE); + ipf_nat_delete(softc, tqe->tqe_parent, NL_EXPIRE); } } - for (ifq = nat_utqe; ifq != NULL; ifq = ifqnext) { - ifqnext = ifq->ifq_next; - + for (ifq = softn->ipf_nat_utqe; ifq != NULL; ifq = ifq->ifq_next) { for (tqn = ifq->ifq_head; ((tqe = tqn) != NULL); i++) { - if (tqe->tqe_die > fr_ticks) + if (tqe->tqe_die > softc->ipf_ticks) break; tqn = tqe->tqe_next; - nat_delete(tqe->tqe_parent, NL_EXPIRE); + ipf_nat_delete(softc, tqe->tqe_parent, NL_EXPIRE); } } - for (ifq = nat_utqe; ifq != NULL; ifq = ifqnext) { + for (ifq = softn->ipf_nat_utqe; ifq != NULL; ifq = ifqnext) { ifqnext = ifq->ifq_next; if (((ifq->ifq_flags & IFQF_DELETE) != 0) && (ifq->ifq_ref == 0)) { - fr_freetimeoutqueue(ifq); + ipf_freetimeoutqueue(softc, ifq); } } - RWLOCK_EXIT(&ipf_nat); + if (softn->ipf_nat_doflush != 0) { + ipf_nat_extraflush(softc, softn, 2); + softn->ipf_nat_doflush = 0; + } + + RWLOCK_EXIT(&softc->ipf_nat); SPL_X(s); } /* ------------------------------------------------------------------------ */ -/* Function: fr_natsync */ +/* Function: ipf_nat_sync */ /* Returns: Nil */ -/* Parameters: ifp(I) - pointer to network interface */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* ifp(I) - pointer to network interface */ /* */ /* Walk through all of the currently active NAT sessions, looking for those */ /* which need to have their translated address updated. */ /* ------------------------------------------------------------------------ */ -void fr_natsync(ifp) -void *ifp; +void +ipf_nat_sync(softc, ifp) + ipf_main_softc_t *softc; + void *ifp; { + ipf_nat_softc_t *softn = softc->ipf_nat_soft; u_32_t sum1, sum2, sumd; - struct in_addr in; + i6addr_t in; ipnat_t *n; nat_t *nat; void *ifp2; -#if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL) - int s; -#endif + int idx; + SPL_INT(s); - if (fr_running <= 0) + if (softc->ipf_running <= 0) return; /* @@ -4386,28 +5949,63 @@ void *ifp; * where the rule specifies the address is taken from the interface. */ SPL_NET(s); - WRITE_ENTER(&ipf_nat); + WRITE_ENTER(&softc->ipf_nat); - if (fr_running <= 0) { - RWLOCK_EXIT(&ipf_nat); + if (softc->ipf_running <= 0) { + RWLOCK_EXIT(&softc->ipf_nat); return; } - for (nat = nat_instances; nat; nat = nat->nat_next) { + for (nat = softn->ipf_nat_instances; nat; nat = nat->nat_next) { if ((nat->nat_flags & IPN_TCP) != 0) continue; + n = nat->nat_ptr; - if ((n == NULL) || - (n->in_outip != 0) || (n->in_outmsk != 0xffffffff)) - continue; + if (n != NULL) { + if (n->in_v[1] == 4) { + if (n->in_redir & NAT_MAP) { + if ((n->in_nsrcaddr != 0) || + (n->in_nsrcmsk != 0xffffffff)) + continue; + } else if (n->in_redir & NAT_REDIRECT) { + if ((n->in_ndstaddr != 0) || + (n->in_ndstmsk != 0xffffffff)) + continue; + } + } +#ifdef USE_INET6 + if (n->in_v[1] == 4) { + if (n->in_redir & NAT_MAP) { + if (!IP6_ISZERO(&n->in_nsrcaddr) || + !IP6_ISONES(&n->in_nsrcmsk)) + continue; + } else if (n->in_redir & NAT_REDIRECT) { + if (!IP6_ISZERO(&n->in_ndstaddr) || + !IP6_ISONES(&n->in_ndstmsk)) + continue; + } + } +#endif + } + if (((ifp == NULL) || (ifp == nat->nat_ifps[0]) || (ifp == nat->nat_ifps[1]))) { - nat->nat_ifps[0] = GETIFP(nat->nat_ifnames[0], 4); + nat->nat_ifps[0] = GETIFP(nat->nat_ifnames[0], + nat->nat_v[0]); + if ((nat->nat_ifps[0] != NULL) && + (nat->nat_ifps[0] != (void *)-1)) { + nat->nat_mtu[0] = GETIFMTU_4(nat->nat_ifps[0]); + } if (nat->nat_ifnames[1][0] != '\0') { nat->nat_ifps[1] = GETIFP(nat->nat_ifnames[1], - 4); - } else + nat->nat_v[1]); + } else { nat->nat_ifps[1] = nat->nat_ifps[0]; + } + if ((nat->nat_ifps[1] != NULL) && + (nat->nat_ifps[1] != (void *)-1)) { + nat->nat_mtu[1] = GETIFMTU_4(nat->nat_ifps[1]); + } ifp2 = nat->nat_ifps[0]; if (ifp2 == NULL) continue; @@ -4416,10 +6014,13 @@ void *ifp; * Change the map-to address to be the same as the * new one. */ - sum1 = nat->nat_outip.s_addr; - if (fr_ifpaddr(4, FRI_NORMAL, ifp2, &in, NULL) != -1) - nat->nat_outip = in; - sum2 = nat->nat_outip.s_addr; + sum1 = NATFSUM(nat, nat->nat_v[1], nat_nsrc6); + if (ipf_ifpaddr(softc, nat->nat_v[0], FRI_NORMAL, ifp2, + &in, NULL) != -1) { + if (nat->nat_v[0] == 4) + nat->nat_nsrcip = in.in4; + } + sum2 = NATFSUM(nat, nat->nat_v[1], nat_nsrc6); if (sum1 == sum2) continue; @@ -4437,27 +6038,53 @@ void *ifp; } } - for (n = nat_list; (n != NULL); n = n->in_next) { + for (n = softn->ipf_nat_list; (n != NULL); n = n->in_next) { + char *base = n->in_names; + if ((ifp == NULL) || (n->in_ifps[0] == ifp)) - n->in_ifps[0] = fr_resolvenic(n->in_ifnames[0], 4); + n->in_ifps[0] = ipf_resolvenic(softc, + base + n->in_ifnames[0], + n->in_v[0]); if ((ifp == NULL) || (n->in_ifps[1] == ifp)) - n->in_ifps[1] = fr_resolvenic(n->in_ifnames[1], 4); + n->in_ifps[1] = ipf_resolvenic(softc, + base + n->in_ifnames[1], + n->in_v[1]); + + if (n->in_redir & NAT_REDIRECT) + idx = 1; + else + idx = 0; + + if (((ifp == NULL) || (n->in_ifps[idx] == ifp)) && + (n->in_ifps[idx] != NULL && + n->in_ifps[idx] != (void *)-1)) { + + ipf_nat_nextaddrinit(softc, n->in_names, &n->in_osrc, + 0, n->in_ifps[idx]); + ipf_nat_nextaddrinit(softc, n->in_names, &n->in_odst, + 0, n->in_ifps[idx]); + ipf_nat_nextaddrinit(softc, n->in_names, &n->in_nsrc, + 0, n->in_ifps[idx]); + ipf_nat_nextaddrinit(softc, n->in_names, &n->in_ndst, + 0, n->in_ifps[idx]); + } } - RWLOCK_EXIT(&ipf_nat); + RWLOCK_EXIT(&softc->ipf_nat); SPL_X(s); } /* ------------------------------------------------------------------------ */ -/* Function: nat_icmpquerytype4 */ +/* Function: ipf_nat_icmpquerytype */ /* Returns: int - 1 == success, 0 == failure */ /* Parameters: icmptype(I) - ICMP type number */ /* */ /* Tests to see if the ICMP type number passed is a query/response type or */ /* not. */ /* ------------------------------------------------------------------------ */ -static INLINE int nat_icmpquerytype4(icmptype) -int icmptype; +static int +ipf_nat_icmpquerytype(icmptype) + int icmptype; { /* @@ -4469,10 +6096,8 @@ int icmptype; * altough it seems silly to call a reply a query, this is exactly * as it is defined in the IPv4 specification */ - switch (icmptype) { - case ICMP_ECHOREPLY: case ICMP_ECHO: /* route aedvertisement/solliciation is currently unsupported: */ @@ -4493,14 +6118,19 @@ int icmptype; /* ------------------------------------------------------------------------ */ /* Function: nat_log */ /* Returns: Nil */ -/* Parameters: nat(I) - pointer to NAT structure */ -/* type(I) - type of log entry to create */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* softn(I) - pointer to NAT context structure */ +/* nat(I) - pointer to NAT structure */ +/* action(I) - action related to NAT structure being performed */ /* */ /* Creates a NAT log entry. */ /* ------------------------------------------------------------------------ */ -void nat_log(nat, type) -struct nat *nat; -u_int type; +void +ipf_nat_log(softc, softn, nat, action) + ipf_main_softc_t *softc; + ipf_nat_softc_t *softn; + struct nat *nat; + u_int action; { #ifdef IPFILTER_LOG # ifndef LARGE_NAT @@ -4512,22 +6142,40 @@ u_int type; size_t sizes[1]; int types[1]; - natl.nl_inip = nat->nat_inip; - natl.nl_outip = nat->nat_outip; - natl.nl_origip = nat->nat_oip; + bcopy((char *)&nat->nat_osrc6, (char *)&natl.nl_osrcip, + sizeof(natl.nl_osrcip)); + bcopy((char *)&nat->nat_nsrc6, (char *)&natl.nl_nsrcip, + sizeof(natl.nl_nsrcip)); + bcopy((char *)&nat->nat_odst6, (char *)&natl.nl_odstip, + sizeof(natl.nl_odstip)); + bcopy((char *)&nat->nat_ndst6, (char *)&natl.nl_ndstip, + sizeof(natl.nl_ndstip)); + natl.nl_bytes[0] = nat->nat_bytes[0]; natl.nl_bytes[1] = nat->nat_bytes[1]; natl.nl_pkts[0] = nat->nat_pkts[0]; natl.nl_pkts[1] = nat->nat_pkts[1]; - natl.nl_origport = nat->nat_oport; - natl.nl_inport = nat->nat_inport; - natl.nl_outport = nat->nat_outport; - natl.nl_p = nat->nat_p; - natl.nl_type = type; + natl.nl_odstport = nat->nat_odport; + natl.nl_osrcport = nat->nat_osport; + natl.nl_nsrcport = nat->nat_nsport; + natl.nl_ndstport = nat->nat_ndport; + natl.nl_p[0] = nat->nat_pr[0]; + natl.nl_p[1] = nat->nat_pr[1]; + natl.nl_v[0] = nat->nat_v[0]; + natl.nl_v[1] = nat->nat_v[1]; + natl.nl_type = nat->nat_redir; + natl.nl_action = action; natl.nl_rule = -1; + + bcopy(nat->nat_ifnames[0], natl.nl_ifnames[0], + sizeof(nat->nat_ifnames[0])); + bcopy(nat->nat_ifnames[1], natl.nl_ifnames[1], + sizeof(nat->nat_ifnames[1])); + # ifndef LARGE_NAT if (nat->nat_ptr != NULL) { - for (rulen = 0, np = nat_list; np; np = np->in_next, rulen++) + for (rulen = 0, np = softn->ipf_nat_list; np != NULL; + np = np->in_next, rulen++) if (np == nat->nat_ptr) { natl.nl_rule = rulen; break; @@ -4538,54 +6186,147 @@ u_int type; sizes[0] = sizeof(natl); types[0] = 0; - (void) ipllog(IPL_LOGNAT, NULL, items, sizes, types, 1); + (void) ipf_log_items(softc, IPL_LOGNAT, NULL, items, sizes, types, 1); #endif } #if defined(__OpenBSD__) /* ------------------------------------------------------------------------ */ -/* Function: nat_ifdetach */ +/* Function: ipf_nat_ifdetach */ /* Returns: Nil */ /* Parameters: ifp(I) - pointer to network interface */ /* */ /* Compatibility interface for OpenBSD to trigger the correct updating of */ /* interface references within IPFilter. */ /* ------------------------------------------------------------------------ */ -void nat_ifdetach(ifp) -void *ifp; +void +ipf_nat_ifdetach(ifp) + void *ifp; { - frsync(ifp); + ipf_main_softc_t *softc; + + softc = ipf_get_softc(0); + + ipf_sync(ifp); return; } #endif /* ------------------------------------------------------------------------ */ -/* Function: fr_natderef */ +/* Function: ipf_nat_rule_deref */ /* Returns: Nil */ -/* Parameters: isp(I) - pointer to pointer to NAT table entry */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* inp(I) - pointer to pointer to NAT rule */ +/* Write Locks: ipf_nat */ +/* */ +/* Dropping the refernce count for a rule means that whatever held the */ +/* pointer to this rule (*inp) is no longer interested in it and when the */ +/* reference count drops to zero, any resources allocated for the rule can */ +/* be released and the rule itself free'd. */ +/* ------------------------------------------------------------------------ */ +void +ipf_nat_rule_deref(softc, inp) + ipf_main_softc_t *softc; + ipnat_t **inp; +{ + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + ipnat_t *n; + + n = *inp; + *inp = NULL; + n->in_use--; + if (n->in_use > 0) + return; + + if (n->in_apr != NULL) + ipf_proxy_deref(n->in_apr); + + ipf_nat_rule_fini(softc, n); + + if (n->in_redir & NAT_REDIRECT) { + if ((n->in_flags & IPN_PROXYRULE) == 0) { + ATOMIC_DEC32(softn->ipf_nat_stats.ns_rules_rdr); + } + } + if (n->in_redir & (NAT_MAP|NAT_MAPBLK)) { + if ((n->in_flags & IPN_PROXYRULE) == 0) { + ATOMIC_DEC32(softn->ipf_nat_stats.ns_rules_map); + } + } + + if (n->in_tqehead[0] != NULL) { + if (ipf_deletetimeoutqueue(n->in_tqehead[0]) == 0) { + ipf_freetimeoutqueue(softc, n->in_tqehead[1]); + } + } + + if (n->in_tqehead[1] != NULL) { + if (ipf_deletetimeoutqueue(n->in_tqehead[1]) == 0) { + ipf_freetimeoutqueue(softc, n->in_tqehead[1]); + } + } + + if ((n->in_flags & IPN_PROXYRULE) == 0) { + ATOMIC_DEC32(softn->ipf_nat_stats.ns_rules); + } + + MUTEX_DESTROY(&n->in_lock); + + KFREES(n, n->in_size); + +#if SOLARIS && !defined(INSTANCES) + if (softn->ipf_nat_stats.ns_rules == 0) + pfil_delayed_copy = 1; +#endif +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_deref */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* natp(I) - pointer to pointer to NAT table entry */ /* */ /* Decrement the reference counter for this NAT table entry and free it if */ /* there are no more things using it. */ +/* */ +/* IF nat_ref == 1 when this function is called, then we have an orphan nat */ +/* structure *because* it only gets called on paths _after_ nat_ref has been*/ +/* incremented. If nat_ref == 1 then we shouldn't decrement it here */ +/* because nat_delete() will do that and send nat_ref to -1. */ +/* */ +/* Holding the lock on nat_lock is required to serialise nat_delete() being */ +/* called from a NAT flush ioctl with a deref happening because of a packet.*/ /* ------------------------------------------------------------------------ */ -void fr_natderef(natp) -nat_t **natp; +void +ipf_nat_deref(softc, natp) + ipf_main_softc_t *softc; + nat_t **natp; { nat_t *nat; nat = *natp; *natp = NULL; - WRITE_ENTER(&ipf_nat); - nat->nat_ref--; - if (nat->nat_ref == 0) - nat_delete(nat, NL_EXPIRE); - RWLOCK_EXIT(&ipf_nat); + + MUTEX_ENTER(&nat->nat_lock); + if (nat->nat_ref > 1) { + nat->nat_ref--; + ASSERT(nat->nat_ref >= 0); + MUTEX_EXIT(&nat->nat_lock); + return; + } + MUTEX_EXIT(&nat->nat_lock); + + WRITE_ENTER(&softc->ipf_nat); + ipf_nat_delete(softc, nat, NL_EXPIRE); + RWLOCK_EXIT(&softc->ipf_nat); } /* ------------------------------------------------------------------------ */ -/* Function: fr_natclone */ +/* Function: ipf_nat_clone */ /* Returns: ipstate_t* - NULL == cloning failed, */ /* else pointer to new state structure */ /* Parameters: fin(I) - pointer to packet information */ @@ -4594,33 +6335,52 @@ nat_t **natp; /* */ /* Create a "duplcate" state table entry from the master. */ /* ------------------------------------------------------------------------ */ -static nat_t *fr_natclone(fin, nat) -fr_info_t *fin; -nat_t *nat; +nat_t * +ipf_nat_clone(fin, nat) + fr_info_t *fin; + nat_t *nat; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; frentry_t *fr; nat_t *clone; ipnat_t *np; KMALLOC(clone, nat_t *); - if (clone == NULL) + if (clone == NULL) { + NBUMPSIDED(fin->fin_out, ns_clone_nomem); return NULL; + } bcopy((char *)nat, (char *)clone, sizeof(*clone)); MUTEX_NUKE(&clone->nat_lock); + clone->nat_rev = fin->fin_rev; + clone->nat_aps = NULL; + /* + * Initialize all these so that ipf_nat_delete() doesn't cause a crash. + */ + clone->nat_tqe.tqe_pnext = NULL; + clone->nat_tqe.tqe_next = NULL; + clone->nat_tqe.tqe_ifq = NULL; + clone->nat_tqe.tqe_parent = clone; + clone->nat_flags &= ~SI_CLONE; clone->nat_flags |= SI_CLONED; + if (clone->nat_hm) + clone->nat_hm->hm_ref++; - if (nat_insert(clone, fin->fin_rev) == -1) { + if (ipf_nat_insert(softc, softn, clone) == -1) { KFREE(clone); + NBUMPSIDED(fin->fin_out, ns_insert_fail); return NULL; } + np = clone->nat_ptr; if (np != NULL) { - if (nat_logging) - nat_log(clone, (u_int)np->in_redir); + if (softn->ipf_nat_logging) + ipf_nat_log(softc, softn, clone, NL_CLONE); np->in_use++; } fr = clone->nat_fr; @@ -4636,21 +6396,19 @@ nat_t *nat; * TCP has special needs in terms of state, initialise the timeout * state of the new NAT from here. */ - if (clone->nat_p == IPPROTO_TCP) { - (void) fr_tcp_age(&clone->nat_tqe, fin, nat_tqb, \ - clone->nat_flags); + if (clone->nat_pr[0] == IPPROTO_TCP) { + (void) ipf_tcp_age(&clone->nat_tqe, fin, softn->ipf_nat_tcptq, + clone->nat_flags, 2); } -#ifdef IPFILTER_SYNC - clone->nat_sync = ipfsync_new(SMC_NAT, fin, clone); -#endif - if (nat_logging) - nat_log(clone, NL_CLONE); + clone->nat_sync = ipf_sync_new(softc, SMC_NAT, fin, clone); + if (softn->ipf_nat_logging) + ipf_nat_log(softc, softn, clone, NL_CLONE); return clone; } /* ------------------------------------------------------------------------ */ -/* Function: nat_wildok */ +/* Function: ipf_nat_wildok */ /* Returns: int - 1 == packet's ports match wildcards */ /* 0 == packet's ports don't match wildcards */ /* Parameters: nat(I) - NAT entry */ @@ -4662,12 +6420,10 @@ nat_t *nat; /* Use NAT entry and packet direction to determine which combination of */ /* wildcard flags should be used. */ /* ------------------------------------------------------------------------ */ -static INLINE int nat_wildok(nat, sport, dport, flags, dir) -nat_t *nat; -int sport; -int dport; -int flags; -int dir; +int +ipf_nat_wildok(nat, sport, dport, flags, dir) + nat_t *nat; + int sport, dport, flags, dir; { /* * When called by dir is set to @@ -4678,34 +6434,33 @@ int dir; * "intended" direction of that NAT entry in nat->nat_dir to decide * which combination of wildcard flags to allow. */ - - switch ((dir << 1) | nat->nat_dir) + switch ((dir << 1) | (nat->nat_dir & (NAT_INBOUND|NAT_OUTBOUND))) { case 3: /* outbound packet / outbound entry */ - if (((nat->nat_inport == sport) || + if (((nat->nat_osport == sport) || (flags & SI_W_SPORT)) && - ((nat->nat_oport == dport) || + ((nat->nat_odport == dport) || (flags & SI_W_DPORT))) return 1; break; case 2: /* outbound packet / inbound entry */ - if (((nat->nat_outport == sport) || - (flags & SI_W_DPORT)) && - ((nat->nat_oport == dport) || - (flags & SI_W_SPORT))) + if (((nat->nat_osport == dport) || + (flags & SI_W_SPORT)) && + ((nat->nat_odport == sport) || + (flags & SI_W_DPORT))) return 1; break; case 1: /* inbound packet / outbound entry */ - if (((nat->nat_oport == sport) || - (flags & SI_W_DPORT)) && - ((nat->nat_outport == dport) || - (flags & SI_W_SPORT))) + if (((nat->nat_osport == dport) || + (flags & SI_W_SPORT)) && + ((nat->nat_odport == sport) || + (flags & SI_W_DPORT))) return 1; break; case 0: /* inbound packet / inbound entry */ - if (((nat->nat_oport == sport) || + if (((nat->nat_osport == sport) || (flags & SI_W_SPORT)) && - ((nat->nat_outport == dport) || + ((nat->nat_odport == dport) || (flags & SI_W_DPORT))) return 1; break; @@ -4729,11 +6484,12 @@ int dir; /* then the TCP header checksum will be updated to reflect the change in */ /* the MSS. */ /* ------------------------------------------------------------------------ */ -static void nat_mssclamp(tcp, maxmss, fin, csump) -tcphdr_t *tcp; -u_32_t maxmss; -fr_info_t *fin; -u_short *csump; +static void +ipf_nat_mssclamp(tcp, maxmss, fin, csump) + tcphdr_t *tcp; + u_32_t maxmss; + fr_info_t *fin; + u_short *csump; { u_char *cp, *ep, opt; int hlen, advance; @@ -4768,7 +6524,7 @@ u_short *csump; cp[2] = maxmss / 256; cp[3] = maxmss & 0xff; CALC_SUMD(mss, maxmss, sumd); - fix_outcksum(fin, csump, sumd); + ipf_fix_outcksum(0, csump, sumd, 0); } break; default: @@ -4783,20 +6539,24 @@ u_short *csump; /* ------------------------------------------------------------------------ */ -/* Function: fr_setnatqueue */ +/* Function: ipf_nat_setqueue */ /* Returns: Nil */ -/* Parameters: nat(I)- pointer to NAT structure */ -/* rev(I) - forward(0) or reverse(1) direction */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* softn(I) - pointer to NAT context structure */ +/* nat(I)- pointer to NAT structure */ /* Locks: ipf_nat (read or write) */ /* */ /* Put the NAT entry on its default queue entry, using rev as a helped in */ /* determining which queue it should be placed on. */ /* ------------------------------------------------------------------------ */ -void fr_setnatqueue(nat, rev) -nat_t *nat; -int rev; +void +ipf_nat_setqueue(softc, softn, nat) + ipf_main_softc_t *softc; + ipf_nat_softc_t *softn; + nat_t *nat; { ipftq_t *oifq, *nifq; + int rev = nat->nat_rev; if (nat->nat_ptr != NULL) nifq = nat->nat_ptr->in_tqehead[rev]; @@ -4804,19 +6564,20 @@ int rev; nifq = NULL; if (nifq == NULL) { - switch (nat->nat_p) + switch (nat->nat_pr[0]) { case IPPROTO_UDP : - nifq = &nat_udptq; + nifq = &softn->ipf_nat_udptq; break; case IPPROTO_ICMP : - nifq = &nat_icmptq; + nifq = &softn->ipf_nat_icmptq; break; case IPPROTO_TCP : - nifq = nat_tqb + nat->nat_tqe.tqe_state[rev]; + nifq = softn->ipf_nat_tcptq + + nat->nat_tqe.tqe_state[rev]; break; default : - nifq = &nat_iptq; + nifq = &softn->ipf_nat_iptq; break; } } @@ -4827,8 +6588,1996 @@ int rev; * another, else put it on the end of the newly determined queue. */ if (oifq != NULL) - fr_movequeue(&nat->nat_tqe, oifq, nifq); + ipf_movequeue(softc->ipf_ticks, &nat->nat_tqe, oifq, nifq); else - fr_queueappend(&nat->nat_tqe, nifq, nat); + ipf_queueappend(softc->ipf_ticks, &nat->nat_tqe, nifq, nat); return; } + + +/* ------------------------------------------------------------------------ */ +/* Function: nat_getnext */ +/* Returns: int - 0 == ok, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* t(I) - pointer to ipftoken structure */ +/* itp(I) - pointer to ipfgeniter_t structure */ +/* */ +/* Fetch the next nat/ipnat structure pointer from the linked list and */ +/* copy it out to the storage space pointed to by itp_data. The next item */ +/* in the list to look at is put back in the ipftoken struture. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat_getnext(softc, t, itp, objp) + ipf_main_softc_t *softc; + ipftoken_t *t; + ipfgeniter_t *itp; + ipfobj_t *objp; +{ + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + hostmap_t *hm, *nexthm = NULL, zerohm; + ipnat_t *ipn, *nextipnat = NULL, zeroipn; + nat_t *nat, *nextnat = NULL, zeronat; + int error = 0; + void *nnext; + + if (itp->igi_nitems != 1) { + IPFERROR(60075); + return ENOSPC; + } + + READ_ENTER(&softc->ipf_nat); + + switch (itp->igi_type) + { + case IPFGENITER_HOSTMAP : + hm = t->ipt_data; + if (hm == NULL) { + nexthm = softn->ipf_hm_maplist; + } else { + nexthm = hm->hm_next; + } + if (nexthm != NULL) { + ATOMIC_INC32(nexthm->hm_ref); + t->ipt_data = nexthm; + } else { + bzero(&zerohm, sizeof(zerohm)); + nexthm = &zerohm; + t->ipt_data = NULL; + } + nnext = nexthm->hm_next; + break; + + case IPFGENITER_IPNAT : + ipn = t->ipt_data; + if (ipn == NULL) { + nextipnat = softn->ipf_nat_list; + } else { + nextipnat = ipn->in_next; + } + if (nextipnat != NULL) { + ATOMIC_INC32(nextipnat->in_use); + t->ipt_data = nextipnat; + } else { + bzero(&zeroipn, sizeof(zeroipn)); + nextipnat = &zeroipn; + t->ipt_data = NULL; + } + nnext = nextipnat->in_next; + break; + + case IPFGENITER_NAT : + nat = t->ipt_data; + if (nat == NULL) { + nextnat = softn->ipf_nat_instances; + } else { + nextnat = nat->nat_next; + } + if (nextnat != NULL) { + MUTEX_ENTER(&nextnat->nat_lock); + nextnat->nat_ref++; + MUTEX_EXIT(&nextnat->nat_lock); + t->ipt_data = nextnat; + } else { + bzero(&zeronat, sizeof(zeronat)); + nextnat = &zeronat; + t->ipt_data = NULL; + } + nnext = nextnat->nat_next; + break; + + default : + RWLOCK_EXIT(&softc->ipf_nat); + IPFERROR(60055); + return EINVAL; + } + + RWLOCK_EXIT(&softc->ipf_nat); + + objp->ipfo_ptr = itp->igi_data; + + switch (itp->igi_type) + { + case IPFGENITER_HOSTMAP : + error = COPYOUT(nexthm, objp->ipfo_ptr, sizeof(*nexthm)); + if (error != 0) { + IPFERROR(60049); + error = EFAULT; + } + if (hm != NULL) { + WRITE_ENTER(&softc->ipf_nat); + ipf_nat_hostmapdel(softc, &hm); + RWLOCK_EXIT(&softc->ipf_nat); + } + break; + + case IPFGENITER_IPNAT : + objp->ipfo_size = nextipnat->in_size; + objp->ipfo_type = IPFOBJ_IPNAT; + error = ipf_outobjk(softc, objp, nextipnat); + if (ipn != NULL) { + WRITE_ENTER(&softc->ipf_nat); + ipf_nat_rule_deref(softc, &ipn); + RWLOCK_EXIT(&softc->ipf_nat); + } + break; + + case IPFGENITER_NAT : + objp->ipfo_size = sizeof(nat_t); + objp->ipfo_type = IPFOBJ_NAT; + error = ipf_outobjk(softc, objp, nextnat); + if (nat != NULL) + ipf_nat_deref(softc, &nat); + + break; + } + + if (nnext == NULL) + ipf_token_mark_complete(t); + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: nat_extraflush */ +/* Returns: int - 0 == success, -1 == failure */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* softn(I) - pointer to NAT context structure */ +/* which(I) - how to flush the active NAT table */ +/* Write Locks: ipf_nat */ +/* */ +/* Flush nat tables. Three actions currently defined: */ +/* which == 0 : flush all nat table entries */ +/* which == 1 : flush TCP connections which have started to close but are */ +/* stuck for some reason. */ +/* which == 2 : flush TCP connections which have been idle for a long time, */ +/* starting at > 4 days idle and working back in successive half-*/ +/* days to at most 12 hours old. If this fails to free enough */ +/* slots then work backwards in half hour slots to 30 minutes. */ +/* If that too fails, then work backwards in 30 second intervals */ +/* for the last 30 minutes to at worst 30 seconds idle. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat_extraflush(softc, softn, which) + ipf_main_softc_t *softc; + ipf_nat_softc_t *softn; + int which; +{ + nat_t *nat, **natp; + ipftqent_t *tqn; + ipftq_t *ifq; + int removed; + SPL_INT(s); + + removed = 0; + + SPL_NET(s); + switch (which) + { + case 0 : + softn->ipf_nat_stats.ns_flush_all++; + /* + * Style 0 flush removes everything... + */ + for (natp = &softn->ipf_nat_instances; + ((nat = *natp) != NULL); ) { + ipf_nat_delete(softc, nat, NL_FLUSH); + removed++; + } + break; + + case 1 : + softn->ipf_nat_stats.ns_flush_closing++; + /* + * Since we're only interested in things that are closing, + * we can start with the appropriate timeout queue. + */ + for (ifq = softn->ipf_nat_tcptq + IPF_TCPS_CLOSE_WAIT; + ifq != NULL; ifq = ifq->ifq_next) { + + for (tqn = ifq->ifq_head; tqn != NULL; ) { + nat = tqn->tqe_parent; + tqn = tqn->tqe_next; + if (nat->nat_pr[0] != IPPROTO_TCP || + nat->nat_pr[1] != IPPROTO_TCP) + break; + ipf_nat_delete(softc, nat, NL_EXPIRE); + removed++; + } + } + + /* + * Also need to look through the user defined queues. + */ + for (ifq = softn->ipf_nat_utqe; ifq != NULL; + ifq = ifq->ifq_next) { + for (tqn = ifq->ifq_head; tqn != NULL; ) { + nat = tqn->tqe_parent; + tqn = tqn->tqe_next; + if (nat->nat_pr[0] != IPPROTO_TCP || + nat->nat_pr[1] != IPPROTO_TCP) + continue; + + if ((nat->nat_tcpstate[0] > + IPF_TCPS_ESTABLISHED) && + (nat->nat_tcpstate[1] > + IPF_TCPS_ESTABLISHED)) { + ipf_nat_delete(softc, nat, NL_EXPIRE); + removed++; + } + } + } + break; + + /* + * Args 5-11 correspond to flushing those particular states + * for TCP connections. + */ + case IPF_TCPS_CLOSE_WAIT : + case IPF_TCPS_FIN_WAIT_1 : + case IPF_TCPS_CLOSING : + case IPF_TCPS_LAST_ACK : + case IPF_TCPS_FIN_WAIT_2 : + case IPF_TCPS_TIME_WAIT : + case IPF_TCPS_CLOSED : + softn->ipf_nat_stats.ns_flush_state++; + tqn = softn->ipf_nat_tcptq[which].ifq_head; + while (tqn != NULL) { + nat = tqn->tqe_parent; + tqn = tqn->tqe_next; + ipf_nat_delete(softc, nat, NL_FLUSH); + removed++; + } + break; + + default : + if (which < 30) + break; + + softn->ipf_nat_stats.ns_flush_timeout++; + /* + * Take a large arbitrary number to mean the number of seconds + * for which which consider to be the maximum value we'll allow + * the expiration to be. + */ + which = IPF_TTLVAL(which); + for (natp = &softn->ipf_nat_instances; + ((nat = *natp) != NULL); ) { + if (softc->ipf_ticks - nat->nat_touched > which) { + ipf_nat_delete(softc, nat, NL_FLUSH); + removed++; + } else + natp = &nat->nat_next; + } + break; + } + + if (which != 2) { + SPL_X(s); + return removed; + } + + softn->ipf_nat_stats.ns_flush_queue++; + + /* + * Asked to remove inactive entries because the table is full, try + * again, 3 times, if first attempt failed with a different criteria + * each time. The order tried in must be in decreasing age. + * Another alternative is to implement random drop and drop N entries + * at random until N have been freed up. + */ + if (softc->ipf_ticks - softn->ipf_nat_last_force_flush > + IPF_TTLVAL(5)) { + softn->ipf_nat_last_force_flush = softc->ipf_ticks; + + removed = ipf_queueflush(softc, ipf_nat_flush_entry, + softn->ipf_nat_tcptq, + softn->ipf_nat_utqe, + &softn->ipf_nat_stats.ns_active, + softn->ipf_nat_table_sz, + softn->ipf_nat_table_wm_low); + } + + SPL_X(s); + return removed; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_flush_entry */ +/* Returns: 0 - always succeeds */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* entry(I) - pointer to NAT entry */ +/* Write Locks: ipf_nat */ +/* */ +/* This function is a stepping stone between ipf_queueflush() and */ +/* nat_dlete(). It is used so we can provide a uniform interface via the */ +/* ipf_queueflush() function. Since the nat_delete() function returns void */ +/* we translate that to mean it always succeeds in deleting something. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat_flush_entry(softc, entry) + ipf_main_softc_t *softc; + void *entry; +{ + ipf_nat_delete(softc, entry, NL_FLUSH); + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_iterator */ +/* Returns: int - 0 == ok, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* token(I) - pointer to ipftoken structure */ +/* itp(I) - pointer to ipfgeniter_t structure */ +/* obj(I) - pointer to data description structure */ +/* */ +/* This function acts as a handler for the SIOCGENITER ioctls that use a */ +/* generic structure to iterate through a list. There are three different */ +/* linked lists of NAT related information to go through: NAT rules, active */ +/* NAT mappings and the NAT fragment cache. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat_iterator(softc, token, itp, obj) + ipf_main_softc_t *softc; + ipftoken_t *token; + ipfgeniter_t *itp; + ipfobj_t *obj; +{ + int error; + + if (itp->igi_data == NULL) { + IPFERROR(60052); + return EFAULT; + } + + switch (itp->igi_type) + { + case IPFGENITER_HOSTMAP : + case IPFGENITER_IPNAT : + case IPFGENITER_NAT : + error = ipf_nat_getnext(softc, token, itp, obj); + break; + + case IPFGENITER_NATFRAG : + error = ipf_frag_nat_next(softc, token, itp); + break; + default : + IPFERROR(60053); + error = EINVAL; + break; + } + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_setpending */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* nat(I) - pointer to NAT structure */ +/* Locks: ipf_nat (read or write) */ +/* */ +/* Put the NAT entry on to the pending queue - this queue has a very short */ +/* lifetime where items are put that can't be deleted straight away because */ +/* of locking issues but we want to delete them ASAP, anyway. In calling */ +/* this function, it is assumed that the owner (if there is one, as shown */ +/* by nat_me) is no longer interested in it. */ +/* ------------------------------------------------------------------------ */ +void +ipf_nat_setpending(softc, nat) + ipf_main_softc_t *softc; + nat_t *nat; +{ + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + ipftq_t *oifq; + + oifq = nat->nat_tqe.tqe_ifq; + if (oifq != NULL) + ipf_movequeue(softc->ipf_ticks, &nat->nat_tqe, oifq, + &softn->ipf_nat_pending); + else + ipf_queueappend(softc->ipf_ticks, &nat->nat_tqe, + &softn->ipf_nat_pending, nat); + + if (nat->nat_me != NULL) { + *nat->nat_me = NULL; + nat->nat_me = NULL; + nat->nat_ref--; + ASSERT(nat->nat_ref >= 0); + } +} + + +/* ------------------------------------------------------------------------ */ +/* Function: nat_newrewrite */ +/* Returns: int - -1 == error, 0 == success (no move), 1 == success and */ +/* allow rule to be moved if IPN_ROUNDR is set. */ +/* Parameters: fin(I) - pointer to packet information */ +/* nat(I) - pointer to NAT entry */ +/* ni(I) - pointer to structure with misc. information needed */ +/* to create new NAT entry. */ +/* Write Lock: ipf_nat */ +/* */ +/* This function is responsible for setting up an active NAT session where */ +/* we are changing both the source and destination parameters at the same */ +/* time. The loop in here works differently to elsewhere - each iteration */ +/* is responsible for changing a single parameter that can be incremented. */ +/* So one pass may increase the source IP#, next source port, next dest. IP#*/ +/* and the last destination port for a total of 4 iterations to try each. */ +/* This is done to try and exhaustively use the translation space available.*/ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat_newrewrite(fin, nat, nai) + fr_info_t *fin; + nat_t *nat; + natinfo_t *nai; +{ + int src_search = 1; + int dst_search = 1; + fr_info_t frnat; + u_32_t flags; + u_short swap; + ipnat_t *np; + nat_t *natl; + int l = 0; + int changed; + + natl = NULL; + changed = -1; + np = nai->nai_np; + flags = nat->nat_flags; + bcopy((char *)fin, (char *)&frnat, sizeof(*fin)); + + nat->nat_hm = NULL; + + do { + changed = -1; + /* TRACE (l, src_search, dst_search, np) */ + + if ((src_search == 0) && (np->in_spnext == 0) && + (dst_search == 0) && (np->in_dpnext == 0)) { + if (l > 0) + return -1; + } + + /* + * Find a new source address + */ + if (ipf_nat_nextaddr(fin, &np->in_nsrc, &frnat.fin_saddr, + &frnat.fin_saddr) == -1) { + return -1; + } + + if ((np->in_nsrcaddr == 0) && (np->in_nsrcmsk == 0xffffffff)) { + src_search = 0; + if (np->in_stepnext == 0) + np->in_stepnext = 1; + + } else if ((np->in_nsrcaddr == 0) && (np->in_nsrcmsk == 0)) { + src_search = 0; + if (np->in_stepnext == 0) + np->in_stepnext = 1; + + } else if (np->in_nsrcmsk == 0xffffffff) { + src_search = 0; + if (np->in_stepnext == 0) + np->in_stepnext = 1; + + } else if (np->in_nsrcmsk != 0xffffffff) { + if (np->in_stepnext == 0 && changed == -1) { + np->in_snip++; + np->in_stepnext++; + changed = 0; + } + } + + if ((flags & IPN_TCPUDPICMP) != 0) { + if (np->in_spnext != 0) + frnat.fin_data[0] = np->in_spnext; + + /* + * Standard port translation. Select next port. + */ + if ((flags & IPN_FIXEDSPORT) != 0) { + np->in_stepnext = 2; + } else if ((np->in_stepnext == 1) && + (changed == -1) && (natl != NULL)) { + np->in_spnext++; + np->in_stepnext++; + changed = 1; + if (np->in_spnext > np->in_spmax) + np->in_spnext = np->in_spmin; + } + } else { + np->in_stepnext = 2; + } + np->in_stepnext &= 0x3; + + /* + * Find a new destination address + */ + /* TRACE (fin, np, l, frnat) */ + + if (ipf_nat_nextaddr(fin, &np->in_ndst, &frnat.fin_daddr, + &frnat.fin_daddr) == -1) + return -1; + if ((np->in_ndstaddr == 0) && (np->in_ndstmsk == 0xffffffff)) { + dst_search = 0; + if (np->in_stepnext == 2) + np->in_stepnext = 3; + + } else if ((np->in_ndstaddr == 0) && (np->in_ndstmsk == 0)) { + dst_search = 0; + if (np->in_stepnext == 2) + np->in_stepnext = 3; + + } else if (np->in_ndstmsk == 0xffffffff) { + dst_search = 0; + if (np->in_stepnext == 2) + np->in_stepnext = 3; + + } else if (np->in_ndstmsk != 0xffffffff) { + if ((np->in_stepnext == 2) && (changed == -1) && + (natl != NULL)) { + changed = 2; + np->in_stepnext++; + np->in_dnip++; + } + } + + if ((flags & IPN_TCPUDPICMP) != 0) { + if (np->in_dpnext != 0) + frnat.fin_data[1] = np->in_dpnext; + + /* + * Standard port translation. Select next port. + */ + if ((flags & IPN_FIXEDDPORT) != 0) { + np->in_stepnext = 0; + } else if (np->in_stepnext == 3 && changed == -1) { + np->in_dpnext++; + np->in_stepnext++; + changed = 3; + if (np->in_dpnext > np->in_dpmax) + np->in_dpnext = np->in_dpmin; + } + } else { + if (np->in_stepnext == 3) + np->in_stepnext = 0; + } + + /* TRACE (frnat) */ + + /* + * Here we do a lookup of the connection as seen from + * the outside. If an IP# pair already exists, try + * again. So if you have A->B becomes C->B, you can + * also have D->E become C->E but not D->B causing + * another C->B. Also take protocol and ports into + * account when determining whether a pre-existing + * NAT setup will cause an external conflict where + * this is appropriate. + * + * fin_data[] is swapped around because we are doing a + * lookup of the packet is if it were moving in the opposite + * direction of the one we are working with now. + */ + if (flags & IPN_TCPUDP) { + swap = frnat.fin_data[0]; + frnat.fin_data[0] = frnat.fin_data[1]; + frnat.fin_data[1] = swap; + } + if (fin->fin_out == 1) { + natl = ipf_nat_inlookup(&frnat, + flags & ~(SI_WILDP|NAT_SEARCH), + (u_int)frnat.fin_p, + frnat.fin_dst, frnat.fin_src); + + } else { + natl = ipf_nat_outlookup(&frnat, + flags & ~(SI_WILDP|NAT_SEARCH), + (u_int)frnat.fin_p, + frnat.fin_dst, frnat.fin_src); + } + if (flags & IPN_TCPUDP) { + swap = frnat.fin_data[0]; + frnat.fin_data[0] = frnat.fin_data[1]; + frnat.fin_data[1] = swap; + } + + /* TRACE natl, in_stepnext, l */ + + if ((natl != NULL) && (l > 8)) /* XXX 8 is arbitrary */ + return -1; + + np->in_stepnext &= 0x3; + + l++; + changed = -1; + } while (natl != NULL); + + nat->nat_osrcip = fin->fin_src; + nat->nat_odstip = fin->fin_dst; + nat->nat_nsrcip = frnat.fin_src; + nat->nat_ndstip = frnat.fin_dst; + + if ((flags & IPN_TCPUDP) != 0) { + nat->nat_osport = htons(fin->fin_data[0]); + nat->nat_odport = htons(fin->fin_data[1]); + nat->nat_nsport = htons(frnat.fin_data[0]); + nat->nat_ndport = htons(frnat.fin_data[1]); + } else if ((flags & IPN_ICMPQUERY) != 0) { + nat->nat_oicmpid = fin->fin_data[1]; + nat->nat_nicmpid = frnat.fin_data[1]; + } + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: nat_newdivert */ +/* Returns: int - -1 == error, 0 == success */ +/* Parameters: fin(I) - pointer to packet information */ +/* nat(I) - pointer to NAT entry */ +/* ni(I) - pointer to structure with misc. information needed */ +/* to create new NAT entry. */ +/* Write Lock: ipf_nat */ +/* */ +/* Create a new NAT divert session as defined by the NAT rule. This is */ +/* somewhat different to other NAT session creation routines because we */ +/* do not iterate through either port numbers or IP addresses, searching */ +/* for a unique mapping, however, a complimentary duplicate check is made. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat_newdivert(fin, nat, nai) + fr_info_t *fin; + nat_t *nat; + natinfo_t *nai; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + fr_info_t frnat; + ipnat_t *np; + nat_t *natl; + int p; + + np = nai->nai_np; + bcopy((char *)fin, (char *)&frnat, sizeof(*fin)); + + nat->nat_pr[0] = 0; + nat->nat_osrcaddr = fin->fin_saddr; + nat->nat_odstaddr = fin->fin_daddr; + frnat.fin_saddr = htonl(np->in_snip); + frnat.fin_daddr = htonl(np->in_dnip); + if ((nat->nat_flags & IPN_TCPUDP) != 0) { + nat->nat_osport = htons(fin->fin_data[0]); + nat->nat_odport = htons(fin->fin_data[1]); + } else if ((nat->nat_flags & IPN_ICMPQUERY) != 0) { + nat->nat_oicmpid = fin->fin_data[1]; + } + + if (np->in_redir & NAT_DIVERTUDP) { + frnat.fin_data[0] = np->in_spnext; + frnat.fin_data[1] = np->in_dpnext; + frnat.fin_flx |= FI_TCPUDP; + p = IPPROTO_UDP; + } else { + frnat.fin_flx &= ~FI_TCPUDP; + p = IPPROTO_IPIP; + } + + if (fin->fin_out == 1) { + natl = ipf_nat_inlookup(&frnat, 0, p, + frnat.fin_dst, frnat.fin_src); + + } else { + natl = ipf_nat_outlookup(&frnat, 0, p, + frnat.fin_dst, frnat.fin_src); + } + + if (natl != NULL) { + NBUMPSIDED(fin->fin_out, ns_divert_exist); + return -1; + } + + nat->nat_nsrcaddr = frnat.fin_saddr; + nat->nat_ndstaddr = frnat.fin_daddr; + if ((nat->nat_flags & IPN_TCPUDP) != 0) { + nat->nat_nsport = htons(frnat.fin_data[0]); + nat->nat_ndport = htons(frnat.fin_data[1]); + } else if ((nat->nat_flags & IPN_ICMPQUERY) != 0) { + nat->nat_nicmpid = frnat.fin_data[1]; + } + + nat->nat_pr[fin->fin_out] = fin->fin_p; + nat->nat_pr[1 - fin->fin_out] = p; + + if (np->in_redir & NAT_REDIRECT) + nat->nat_dir = NAT_DIVERTIN; + else + nat->nat_dir = NAT_DIVERTOUT; + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: nat_builddivertmp */ +/* Returns: int - -1 == error, 0 == success */ +/* Parameters: softn(I) - pointer to NAT context structure */ +/* np(I) - pointer to a NAT rule */ +/* */ +/* For divert rules, a skeleton packet representing what will be prepended */ +/* to the real packet is created. Even though we don't have the full */ +/* packet here, a checksum is calculated that we update later when we */ +/* fill in the final details. At present a 0 checksum for UDP is being set */ +/* here because it is expected that divert will be used for localhost. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat_builddivertmp(softn, np) + ipf_nat_softc_t *softn; + ipnat_t *np; +{ + udphdr_t *uh; + size_t len; + ip_t *ip; + + if ((np->in_redir & NAT_DIVERTUDP) != 0) + len = sizeof(ip_t) + sizeof(udphdr_t); + else + len = sizeof(ip_t); + + ALLOC_MB_T(np->in_divmp, len); + if (np->in_divmp == NULL) { + NBUMPD(ipf_nat_stats, ns_divert_build); + return -1; + } + + /* + * First, the header to get the packet diverted to the new destination + */ + ip = MTOD(np->in_divmp, ip_t *); + IP_V_A(ip, 4); + IP_HL_A(ip, 5); + ip->ip_tos = 0; + if ((np->in_redir & NAT_DIVERTUDP) != 0) + ip->ip_p = IPPROTO_UDP; + else + ip->ip_p = IPPROTO_IPIP; + ip->ip_ttl = 255; + ip->ip_off = 0; + ip->ip_sum = 0; + ip->ip_len = htons(len); + ip->ip_id = 0; + ip->ip_src.s_addr = htonl(np->in_snip); + ip->ip_dst.s_addr = htonl(np->in_dnip); + ip->ip_sum = ipf_cksum((u_short *)ip, sizeof(*ip)); + + if (np->in_redir & NAT_DIVERTUDP) { + uh = (udphdr_t *)(ip + 1); + uh->uh_sum = 0; + uh->uh_ulen = 8; + uh->uh_sport = htons(np->in_spnext); + uh->uh_dport = htons(np->in_dpnext); + } + + return 0; +} + + +#define MINDECAP (sizeof(ip_t) + sizeof(udphdr_t) + sizeof(ip_t)) + +/* ------------------------------------------------------------------------ */ +/* Function: nat_decap */ +/* Returns: int - -1 == error, 0 == success */ +/* Parameters: fin(I) - pointer to packet information */ +/* nat(I) - pointer to current NAT session */ +/* */ +/* This function is responsible for undoing a packet's encapsulation in the */ +/* reverse of an encap/divert rule. After removing the outer encapsulation */ +/* it is necessary to call ipf_makefrip() again so that the contents of 'fin'*/ +/* match the "new" packet as it may still be used by IPFilter elsewhere. */ +/* We use "dir" here as the basis for some of the expectations about the */ +/* outer header. If we return an error, the goal is to leave the original */ +/* packet information undisturbed - this falls short at the end where we'd */ +/* need to back a backup copy of "fin" - expensive. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat_decap(fin, nat) + fr_info_t *fin; + nat_t *nat; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + char *hdr; + int hlen; + int skip; + mb_t *m; + + if ((fin->fin_flx & FI_ICMPERR) != 0) { + /* + * ICMP packets don't get decapsulated, instead what we need + * to do is change the ICMP reply from including (in the data + * portion for errors) the encapsulated packet that we sent + * out to something that resembles the original packet prior + * to encapsulation. This isn't done here - all we're doing + * here is changing the outer address to ensure that it gets + * targetted back to the correct system. + */ + + if (nat->nat_dir & NAT_OUTBOUND) { + u_32_t sum1, sum2, sumd; + + sum1 = ntohl(fin->fin_daddr); + sum2 = ntohl(nat->nat_osrcaddr); + CALC_SUMD(sum1, sum2, sumd); + fin->fin_ip->ip_dst = nat->nat_osrcip; + fin->fin_daddr = nat->nat_osrcaddr; +#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) || \ + defined(__osf__) || defined(linux) + ipf_fix_outcksum(0, &fin->fin_ip->ip_sum, sumd, 0); +#endif + } + return 0; + } + + m = fin->fin_m; + skip = fin->fin_hlen; + + switch (nat->nat_dir) + { + case NAT_DIVERTIN : + case NAT_DIVERTOUT : + if (fin->fin_plen < MINDECAP) + return -1; + skip += sizeof(udphdr_t); + break; + + case NAT_ENCAPIN : + case NAT_ENCAPOUT : + if (fin->fin_plen < (skip + sizeof(ip_t))) + return -1; + break; + default : + return -1; + /* NOTREACHED */ + } + + /* + * The aim here is to keep the original packet details in "fin" for + * as long as possible so that returning with an error is for the + * original packet and there is little undoing work to do. + */ + if (M_LEN(m) < skip + sizeof(ip_t)) { + if (ipf_pr_pullup(fin, skip + sizeof(ip_t)) == -1) + return -1; + } + + hdr = MTOD(fin->fin_m, char *); + fin->fin_ip = (ip_t *)(hdr + skip); + hlen = IP_HL(fin->fin_ip) << 2; + + if (ipf_pr_pullup(fin, skip + hlen) == -1) { + NBUMPSIDED(fin->fin_out, ns_decap_pullup); + return -1; + } + + fin->fin_hlen = hlen; + fin->fin_dlen -= skip; + fin->fin_plen -= skip; + fin->fin_ipoff += skip; + + if (ipf_makefrip(hlen, (ip_t *)hdr, fin) == -1) { + NBUMPSIDED(fin->fin_out, ns_decap_bad); + return -1; + } + + return skip; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: nat_nextaddr */ +/* Returns: int - -1 == bad input (no new address), */ +/* 0 == success and dst has new address */ +/* Parameters: fin(I) - pointer to packet information */ +/* na(I) - how to generate new address */ +/* old(I) - original address being replaced */ +/* dst(O) - where to put the new address */ +/* Write Lock: ipf_nat */ +/* */ +/* This function uses the contents of the "na" structure, in combination */ +/* with "old" to produce a new address to store in "dst". Not all of the */ +/* possible uses of "na" will result in a new address. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat_nextaddr(fin, na, old, dst) + fr_info_t *fin; + nat_addr_t *na; + u_32_t *old, *dst; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + u_32_t amin, amax, new; + i6addr_t newip; + int error; + + new = 0; + amin = na->na_addr[0].in4.s_addr; + + switch (na->na_atype) + { + case FRI_RANGE : + amax = na->na_addr[1].in4.s_addr; + break; + + case FRI_NETMASKED : + case FRI_DYNAMIC : + case FRI_NORMAL : + /* + * Compute the maximum address by adding the inverse of the + * netmask to the minimum address. + */ + amax = ~na->na_addr[1].in4.s_addr; + amax |= amin; + break; + + case FRI_LOOKUP : + break; + + case FRI_BROADCAST : + case FRI_PEERADDR : + case FRI_NETWORK : + default : + return -1; + } + + error = -1; + + if (na->na_atype == FRI_LOOKUP) { + if (na->na_type == IPLT_DSTLIST) { + error = ipf_dstlist_select_node(fin, na->na_ptr, dst, + NULL); + } else { + NBUMPSIDE(fin->fin_out, ns_badnextaddr); + } + + } else if (na->na_atype == IPLT_NONE) { + /* + * 0/0 as the new address means leave it alone. + */ + if (na->na_addr[0].in4.s_addr == 0 && + na->na_addr[1].in4.s_addr == 0) { + new = *old; + + /* + * 0/32 means get the interface's address + */ + } else if (na->na_addr[0].in4.s_addr == 0 && + na->na_addr[1].in4.s_addr == 0xffffffff) { + if (ipf_ifpaddr(softc, 4, na->na_atype, + fin->fin_ifp, &newip, NULL) == -1) { + NBUMPSIDED(fin->fin_out, ns_ifpaddrfail); + return -1; + } + new = newip.in4.s_addr; + } else { + new = htonl(na->na_nextip); + } + *dst = new; + error = 0; + + } else { + NBUMPSIDE(fin->fin_out, ns_badnextaddr); + } + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: nat_nextaddrinit */ +/* Returns: int - 0 == success, else error number */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* na(I) - NAT address information for generating new addr*/ +/* initial(I) - flag indicating if it is the first call for */ +/* this "na" structure. */ +/* ifp(I) - network interface to derive address */ +/* information from. */ +/* */ +/* This function is expected to be called in two scenarious: when a new NAT */ +/* rule is loaded into the kernel and when the list of NAT rules is sync'd */ +/* up with the valid network interfaces (possibly due to them changing.) */ +/* To distinguish between these, the "initial" parameter is used. If it is */ +/* 1 then this indicates the rule has just been reloaded and 0 for when we */ +/* are updating information. This difference is important because in */ +/* instances where we are not updating address information associated with */ +/* a network interface, we don't want to disturb what the "next" address to */ +/* come out of ipf_nat_nextaddr() will be. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat_nextaddrinit(softc, base, na, initial, ifp) + ipf_main_softc_t *softc; + char *base; + nat_addr_t *na; + int initial; + void *ifp; +{ + + switch (na->na_atype) + { + case FRI_LOOKUP : + if (na->na_subtype == 0) { + na->na_ptr = ipf_lookup_res_num(softc, IPL_LOGNAT, + na->na_type, + na->na_num, + &na->na_func); + } else if (na->na_subtype == 1) { + na->na_ptr = ipf_lookup_res_name(softc, IPL_LOGNAT, + na->na_type, + base + na->na_num, + &na->na_func); + } + if (na->na_func == NULL) { + IPFERROR(60060); + return ESRCH; + } + if (na->na_ptr == NULL) { + IPFERROR(60056); + return ESRCH; + } + break; + + case FRI_DYNAMIC : + case FRI_BROADCAST : + case FRI_NETWORK : + case FRI_NETMASKED : + case FRI_PEERADDR : + if (ifp != NULL) + (void )ipf_ifpaddr(softc, 4, na->na_atype, ifp, + &na->na_addr[0], &na->na_addr[1]); + break; + + case FRI_SPLIT : + case FRI_RANGE : + if (initial) + na->na_nextip = ntohl(na->na_addr[0].in4.s_addr); + break; + + case FRI_NONE : + na->na_addr[0].in4.s_addr &= na->na_addr[1].in4.s_addr; + return 0; + + case FRI_NORMAL : + na->na_addr[0].in4.s_addr &= na->na_addr[1].in4.s_addr; + break; + + default : + IPFERROR(60054); + return EINVAL; + } + + if (initial && (na->na_atype == FRI_NORMAL)) { + if (na->na_addr[0].in4.s_addr == 0) { + if ((na->na_addr[1].in4.s_addr == 0xffffffff) || + (na->na_addr[1].in4.s_addr == 0)) { + return 0; + } + } + + if (na->na_addr[1].in4.s_addr == 0xffffffff) { + na->na_nextip = ntohl(na->na_addr[0].in4.s_addr); + } else { + na->na_nextip = ntohl(na->na_addr[0].in4.s_addr) + 1; + } + } + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_matchflush */ +/* Returns: int - -1 == error, 0 == success */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* softn(I) - pointer to NAT context structure */ +/* nat(I) - pointer to current NAT session */ +/* */ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat_matchflush(softc, softn, data) + ipf_main_softc_t *softc; + ipf_nat_softc_t *softn; + caddr_t data; +{ + int *array, flushed, error; + nat_t *nat, *natnext; + ipfobj_t obj; + + error = ipf_matcharray_load(softc, data, &obj, &array); + if (error != 0) + return error; + + flushed = 0; + + for (nat = softn->ipf_nat_instances; nat != NULL; nat = natnext) { + natnext = nat->nat_next; + if (ipf_nat_matcharray(nat, array, softc->ipf_ticks) == 0) { + ipf_nat_delete(softc, nat, NL_FLUSH); + flushed++; + } + } + + obj.ipfo_retval = flushed; + error = BCOPYOUT(&obj, data, sizeof(obj)); + + KFREES(array, array[0] * sizeof(*array)); + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_matcharray */ +/* Returns: int - -1 == error, 0 == success */ +/* Parameters: fin(I) - pointer to packet information */ +/* nat(I) - pointer to current NAT session */ +/* */ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat_matcharray(nat, array, ticks) + nat_t *nat; + int *array; + u_long ticks; +{ + int i, n, *x, e, p; + + e = 0; + n = array[0]; + x = array + 1; + + for (; n > 0; x += 3 + x[2]) { + if (x[0] == IPF_EXP_END) + break; + e = 0; + + n -= x[2] + 3; + if (n < 0) + break; + + p = x[0] >> 16; + if (p != 0 && p != nat->nat_pr[1]) + break; + + switch (x[0]) + { + case IPF_EXP_IP_PR : + for (i = 0; !e && i < x[2]; i++) { + e |= (nat->nat_pr[1] == x[i + 3]); + } + break; + + case IPF_EXP_IP_SRCADDR : + if (nat->nat_v[0] == 4) { + for (i = 0; !e && i < x[2]; i++) { + e |= ((nat->nat_osrcaddr & x[i + 4]) == + x[i + 3]); + } + } + if (nat->nat_v[1] == 4) { + for (i = 0; !e && i < x[2]; i++) { + e |= ((nat->nat_nsrcaddr & x[i + 4]) == + x[i + 3]); + } + } + break; + + case IPF_EXP_IP_DSTADDR : + if (nat->nat_v[0] == 4) { + for (i = 0; !e && i < x[2]; i++) { + e |= ((nat->nat_odstaddr & x[i + 4]) == + x[i + 3]); + } + } + if (nat->nat_v[1] == 4) { + for (i = 0; !e && i < x[2]; i++) { + e |= ((nat->nat_ndstaddr & x[i + 4]) == + x[i + 3]); + } + } + break; + + case IPF_EXP_IP_ADDR : + for (i = 0; !e && i < x[2]; i++) { + if (nat->nat_v[0] == 4) { + e |= ((nat->nat_osrcaddr & x[i + 4]) == + x[i + 3]); + } + if (nat->nat_v[1] == 4) { + e |= ((nat->nat_nsrcaddr & x[i + 4]) == + x[i + 3]); + } + if (nat->nat_v[0] == 4) { + e |= ((nat->nat_odstaddr & x[i + 4]) == + x[i + 3]); + } + if (nat->nat_v[1] == 4) { + e |= ((nat->nat_ndstaddr & x[i + 4]) == + x[i + 3]); + } + } + break; + +#ifdef USE_INET6 + case IPF_EXP_IP6_SRCADDR : + if (nat->nat_v[0] == 6) { + for (i = 0; !e && i < x[3]; i++) { + e |= IP6_MASKEQ(&nat->nat_osrc6, + x + i + 7, x + i + 3); + } + } + if (nat->nat_v[1] == 6) { + for (i = 0; !e && i < x[3]; i++) { + e |= IP6_MASKEQ(&nat->nat_nsrc6, + x + i + 7, x + i + 3); + } + } + break; + + case IPF_EXP_IP6_DSTADDR : + if (nat->nat_v[0] == 6) { + for (i = 0; !e && i < x[3]; i++) { + e |= IP6_MASKEQ(&nat->nat_odst6, + x + i + 7, + x + i + 3); + } + } + if (nat->nat_v[1] == 6) { + for (i = 0; !e && i < x[3]; i++) { + e |= IP6_MASKEQ(&nat->nat_ndst6, + x + i + 7, + x + i + 3); + } + } + break; + + case IPF_EXP_IP6_ADDR : + for (i = 0; !e && i < x[3]; i++) { + if (nat->nat_v[0] == 6) { + e |= IP6_MASKEQ(&nat->nat_osrc6, + x + i + 7, + x + i + 3); + } + if (nat->nat_v[0] == 6) { + e |= IP6_MASKEQ(&nat->nat_odst6, + x + i + 7, + x + i + 3); + } + if (nat->nat_v[1] == 6) { + e |= IP6_MASKEQ(&nat->nat_nsrc6, + x + i + 7, + x + i + 3); + } + if (nat->nat_v[1] == 6) { + e |= IP6_MASKEQ(&nat->nat_ndst6, + x + i + 7, + x + i + 3); + } + } + break; +#endif + + case IPF_EXP_UDP_PORT : + case IPF_EXP_TCP_PORT : + for (i = 0; !e && i < x[2]; i++) { + e |= (nat->nat_nsport == x[i + 3]) || + (nat->nat_ndport == x[i + 3]); + } + break; + + case IPF_EXP_UDP_SPORT : + case IPF_EXP_TCP_SPORT : + for (i = 0; !e && i < x[2]; i++) { + e |= (nat->nat_nsport == x[i + 3]); + } + break; + + case IPF_EXP_UDP_DPORT : + case IPF_EXP_TCP_DPORT : + for (i = 0; !e && i < x[2]; i++) { + e |= (nat->nat_ndport == x[i + 3]); + } + break; + + case IPF_EXP_TCP_STATE : + for (i = 0; !e && i < x[2]; i++) { + e |= (nat->nat_tcpstate[0] == x[i + 3]) || + (nat->nat_tcpstate[1] == x[i + 3]); + } + break; + + case IPF_EXP_IDLE_GT : + e |= (ticks - nat->nat_touched > x[3]); + break; + } + e ^= x[1]; + + if (!e) + break; + } + + return e; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_gettable */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* softn(I) - pointer to NAT context structure */ +/* data(I) - pointer to ioctl data */ +/* */ +/* This function handles ioctl requests for tables of nat information. */ +/* At present the only table it deals with is the hash bucket statistics. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat_gettable(softc, softn, data) + ipf_main_softc_t *softc; + ipf_nat_softc_t *softn; + char *data; +{ + ipftable_t table; + int error; + + error = ipf_inobj(softc, data, NULL, &table, IPFOBJ_GTABLE); + if (error != 0) + return error; + + switch (table.ita_type) + { + case IPFTABLE_BUCKETS_NATIN : + error = COPYOUT(softn->ipf_nat_stats.ns_side[0].ns_bucketlen, + table.ita_table, + softn->ipf_nat_table_sz * sizeof(u_int)); + break; + + case IPFTABLE_BUCKETS_NATOUT : + error = COPYOUT(softn->ipf_nat_stats.ns_side[1].ns_bucketlen, + table.ita_table, + softn->ipf_nat_table_sz * sizeof(u_int)); + break; + + default : + IPFERROR(60058); + return EINVAL; + } + + if (error != 0) { + IPFERROR(60059); + error = EFAULT; + } + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_settimeout */ +/* Returns: int - 0 = success, else failure */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* t(I) - pointer to tunable */ +/* p(I) - pointer to new tuning data */ +/* */ +/* Apply the timeout change to the NAT timeout queues. */ +/* ------------------------------------------------------------------------ */ +int +ipf_nat_settimeout(softc, t, p) + struct ipf_main_softc_s *softc; + ipftuneable_t *t; + ipftuneval_t *p; +{ + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + + if (!strncmp(t->ipft_name, "tcp_", 4)) + return ipf_settimeout_tcp(t, p, softn->ipf_nat_tcptq); + + if (!strcmp(t->ipft_name, "udp_timeout")) { + ipf_apply_timeout(&softn->ipf_nat_udptq, p->ipftu_int); + } else if (!strcmp(t->ipft_name, "udp_ack_timeout")) { + ipf_apply_timeout(&softn->ipf_nat_udpacktq, p->ipftu_int); + } else if (!strcmp(t->ipft_name, "icmp_timeout")) { + ipf_apply_timeout(&softn->ipf_nat_icmptq, p->ipftu_int); + } else if (!strcmp(t->ipft_name, "icmp_ack_timeout")) { + ipf_apply_timeout(&softn->ipf_nat_icmpacktq, p->ipftu_int); + } else if (!strcmp(t->ipft_name, "ip_timeout")) { + ipf_apply_timeout(&softn->ipf_nat_iptq, p->ipftu_int); + } else { + IPFERROR(60062); + return ESRCH; + } + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_rehash */ +/* Returns: int - 0 = success, else failure */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* t(I) - pointer to tunable */ +/* p(I) - pointer to new tuning data */ +/* */ +/* To change the size of the basic NAT table, we need to first allocate the */ +/* new tables (lest it fails and we've got nowhere to store all of the NAT */ +/* sessions currently active) and then walk through the entire list and */ +/* insert them into the table. There are two tables here: an inbound one */ +/* and an outbound one. Each NAT entry goes into each table once. */ +/* ------------------------------------------------------------------------ */ +int +ipf_nat_rehash(softc, t, p) + ipf_main_softc_t *softc; + ipftuneable_t *t; + ipftuneval_t *p; +{ + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + nat_t **newtab[2], *nat, **natp; + u_int *bucketlens[2]; + u_int maxbucket; + u_int newsize; + int error; + u_int hv; + int i; + + newsize = p->ipftu_int; + /* + * In case there is nothing to do... + */ + if (newsize == softn->ipf_nat_table_sz) + return 0; + + newtab[0] = NULL; + newtab[1] = NULL; + bucketlens[0] = NULL; + bucketlens[1] = NULL; + /* + * 4 tables depend on the NAT table size: the inbound looking table, + * the outbound lookup table and the hash chain length for each. + */ + KMALLOCS(newtab[0], nat_t **, newsize * sizeof(nat_t *)); + if (newtab == NULL) { + error = 60063; + goto badrehash; + } + + KMALLOCS(newtab[1], nat_t **, newsize * sizeof(nat_t *)); + if (newtab == NULL) { + error = 60064; + goto badrehash; + } + + KMALLOCS(bucketlens[0], u_int *, newsize * sizeof(u_int)); + if (bucketlens[0] == NULL) { + error = 60065; + goto badrehash; + } + + KMALLOCS(bucketlens[1], u_int *, newsize * sizeof(u_int)); + if (bucketlens[1] == NULL) { + error = 60066; + goto badrehash; + } + + /* + * Recalculate the maximum length based on the new size. + */ + for (maxbucket = 0, i = newsize; i > 0; i >>= 1) + maxbucket++; + maxbucket *= 2; + + bzero((char *)newtab[0], newsize * sizeof(nat_t *)); + bzero((char *)newtab[1], newsize * sizeof(nat_t *)); + bzero((char *)bucketlens[0], newsize * sizeof(u_int)); + bzero((char *)bucketlens[1], newsize * sizeof(u_int)); + + WRITE_ENTER(&softc->ipf_nat); + + if (softn->ipf_nat_table[0] != NULL) { + KFREES(softn->ipf_nat_table[0], + softn->ipf_nat_table_sz * + sizeof(*softn->ipf_nat_table[0])); + } + softn->ipf_nat_table[0] = newtab[0]; + + if (softn->ipf_nat_table[1] != NULL) { + KFREES(softn->ipf_nat_table[1], + softn->ipf_nat_table_sz * + sizeof(*softn->ipf_nat_table[1])); + } + softn->ipf_nat_table[1] = newtab[1]; + + if (softn->ipf_nat_stats.ns_side[0].ns_bucketlen != NULL) { + KFREES(softn->ipf_nat_stats.ns_side[0].ns_bucketlen, + softn->ipf_nat_table_sz * sizeof(u_int)); + } + softn->ipf_nat_stats.ns_side[0].ns_bucketlen = bucketlens[0]; + + if (softn->ipf_nat_stats.ns_side[1].ns_bucketlen != NULL) { + KFREES(softn->ipf_nat_stats.ns_side[1].ns_bucketlen, + softn->ipf_nat_table_sz * sizeof(u_int)); + } + softn->ipf_nat_stats.ns_side[1].ns_bucketlen = bucketlens[1]; + + if (softn->ipf_nat_stats.ns_side6[0].ns_bucketlen != NULL) { + KFREES(softn->ipf_nat_stats.ns_side6[0].ns_bucketlen, + softn->ipf_nat_table_sz * sizeof(u_int)); + } + softn->ipf_nat_stats.ns_side6[0].ns_bucketlen = bucketlens[0]; + + if (softn->ipf_nat_stats.ns_side6[1].ns_bucketlen != NULL) { + KFREES(softn->ipf_nat_stats.ns_side6[1].ns_bucketlen, + softn->ipf_nat_table_sz * sizeof(u_int)); + } + softn->ipf_nat_stats.ns_side6[1].ns_bucketlen = bucketlens[1]; + + softn->ipf_nat_maxbucket = maxbucket; + softn->ipf_nat_table_sz = newsize; + /* + * Walk through the entire list of NAT table entries and put them + * in the new NAT table, somewhere. Because we have a new table, + * we need to restart the counter of how many chains are in use. + */ + softn->ipf_nat_stats.ns_side[0].ns_inuse = 0; + softn->ipf_nat_stats.ns_side[1].ns_inuse = 0; + softn->ipf_nat_stats.ns_side6[0].ns_inuse = 0; + softn->ipf_nat_stats.ns_side6[1].ns_inuse = 0; + + for (nat = softn->ipf_nat_instances; nat != NULL; nat = nat->nat_next) { + nat->nat_hnext[0] = NULL; + nat->nat_phnext[0] = NULL; + hv = nat->nat_hv[0] % softn->ipf_nat_table_sz; + + natp = &softn->ipf_nat_table[0][hv]; + if (*natp) { + (*natp)->nat_phnext[0] = &nat->nat_hnext[0]; + } else { + NBUMPSIDE(0, ns_inuse); + } + nat->nat_phnext[0] = natp; + nat->nat_hnext[0] = *natp; + *natp = nat; + NBUMPSIDE(0, ns_bucketlen[hv]); + + nat->nat_hnext[1] = NULL; + nat->nat_phnext[1] = NULL; + hv = nat->nat_hv[1] % softn->ipf_nat_table_sz; + + natp = &softn->ipf_nat_table[1][hv]; + if (*natp) { + (*natp)->nat_phnext[1] = &nat->nat_hnext[1]; + } else { + NBUMPSIDE(1, ns_inuse); + } + nat->nat_phnext[1] = natp; + nat->nat_hnext[1] = *natp; + *natp = nat; + NBUMPSIDE(1, ns_bucketlen[hv]); + } + RWLOCK_EXIT(&softc->ipf_nat); + + return 0; + +badrehash: + if (bucketlens[1] != NULL) { + KFREES(bucketlens[0], newsize * sizeof(u_int)); + } + if (bucketlens[0] != NULL) { + KFREES(bucketlens[0], newsize * sizeof(u_int)); + } + if (newtab[0] != NULL) { + KFREES(newtab[0], newsize * sizeof(nat_t *)); + } + if (newtab[1] != NULL) { + KFREES(newtab[1], newsize * sizeof(nat_t *)); + } + IPFERROR(error); + return ENOMEM; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_rehash_rules */ +/* Returns: int - 0 = success, else failure */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* t(I) - pointer to tunable */ +/* p(I) - pointer to new tuning data */ +/* */ +/* All of the NAT rules hang off of a hash table that is searched with a */ +/* hash on address after the netmask is applied. There is a different table*/ +/* for both inbound rules (rdr) and outbound (map.) The resizing will only */ +/* affect one of these two tables. */ +/* ------------------------------------------------------------------------ */ +int +ipf_nat_rehash_rules(softc, t, p) + ipf_main_softc_t *softc; + ipftuneable_t *t; + ipftuneval_t *p; +{ + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + ipnat_t **newtab, *np, ***old, **npp; + u_int newsize; + u_int mask; + u_int hv; + + newsize = p->ipftu_int; + /* + * In case there is nothing to do... + */ + if (newsize == *t->ipft_pint) + return 0; + + /* + * All inbound rules have the NAT_REDIRECT bit set in in_redir and + * all outbound rules have either NAT_MAP or MAT_MAPBLK set. + * This if statement allows for some more generic code to be below, + * rather than two huge gobs of code that almost do the same thing. + */ + if (t->ipft_pint == &softn->ipf_nat_rdrrules_sz) { + old = &softn->ipf_nat_rdr_rules; + mask = NAT_REDIRECT; + } else { + old = &softn->ipf_nat_map_rules; + mask = NAT_MAP|NAT_MAPBLK; + } + + KMALLOCS(newtab, ipnat_t **, newsize * sizeof(ipnat_t *)); + if (newtab == NULL) { + IPFERROR(60067); + return ENOMEM; + } + + bzero((char *)newtab, newsize * sizeof(ipnat_t *)); + + WRITE_ENTER(&softc->ipf_nat); + + if (*old != NULL) { + KFREES(*old, *t->ipft_pint * sizeof(ipnat_t **)); + } + *old = newtab; + *t->ipft_pint = newsize; + + for (np = softn->ipf_nat_list; np != NULL; np = np->in_next) { + if ((np->in_redir & mask) == 0) + continue; + + if (np->in_redir & NAT_REDIRECT) { + np->in_rnext = NULL; + hv = np->in_hv[0] % newsize; + for (npp = newtab + hv; *npp != NULL; ) + npp = &(*npp)->in_rnext; + np->in_prnext = npp; + *npp = np; + } + if (np->in_redir & NAT_MAP) { + np->in_mnext = NULL; + hv = np->in_hv[1] % newsize; + for (npp = newtab + hv; *npp != NULL; ) + npp = &(*npp)->in_mnext; + np->in_pmnext = npp; + *npp = np; + } + + } + RWLOCK_EXIT(&softc->ipf_nat); + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_hostmap_rehash */ +/* Returns: int - 0 = success, else failure */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* t(I) - pointer to tunable */ +/* p(I) - pointer to new tuning data */ +/* */ +/* Allocate and populate a new hash table that will contain a reference to */ +/* all of the active IP# translations currently in place. */ +/* ------------------------------------------------------------------------ */ +int +ipf_nat_hostmap_rehash(softc, t, p) + ipf_main_softc_t *softc; + ipftuneable_t *t; + ipftuneval_t *p; +{ + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + hostmap_t *hm, **newtab; + u_int newsize; + u_int hv; + + newsize = p->ipftu_int; + /* + * In case there is nothing to do... + */ + if (newsize == *t->ipft_pint) + return 0; + + KMALLOCS(newtab, hostmap_t **, newsize * sizeof(hostmap_t *)); + if (newtab == NULL) { + IPFERROR(60068); + return ENOMEM; + } + + bzero((char *)newtab, newsize * sizeof(hostmap_t *)); + + WRITE_ENTER(&softc->ipf_nat); + if (softn->ipf_hm_maptable != NULL) { + KFREES(softn->ipf_hm_maptable, + softn->ipf_nat_hostmap_sz * sizeof(hostmap_t *)); + } + softn->ipf_hm_maptable = newtab; + softn->ipf_nat_hostmap_sz = newsize; + + for (hm = softn->ipf_hm_maplist; hm != NULL; hm = hm->hm_next) { + hv = hm->hm_hv % softn->ipf_nat_hostmap_sz; + hm->hm_hnext = softn->ipf_hm_maptable[hv]; + hm->hm_phnext = softn->ipf_hm_maptable + hv; + if (softn->ipf_hm_maptable[hv] != NULL) + softn->ipf_hm_maptable[hv]->hm_phnext = &hm->hm_hnext; + softn->ipf_hm_maptable[hv] = hm; + } + RWLOCK_EXIT(&softc->ipf_nat); + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_add_tq */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* */ +/* ------------------------------------------------------------------------ */ +ipftq_t * +ipf_nat_add_tq(softc, ttl) + ipf_main_softc_t *softc; + int ttl; +{ + ipf_nat_softc_t *softs = softc->ipf_nat_soft; + + return ipf_addtimeoutqueue(softc, &softs->ipf_nat_utqe, ttl); +} + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_uncreate */ +/* Returns: Nil */ +/* Parameters: fin(I) - pointer to packet information */ +/* */ +/* This function is used to remove a NAT entry from the NAT table when we */ +/* decide that the create was actually in error. It is thus assumed that */ +/* fin_flx will have both FI_NATED and FI_NATNEW set. Because we're dealing */ +/* with the translated packet (not the original), we have to reverse the */ +/* lookup. Although doing the lookup is expensive (relatively speaking), it */ +/* is not anticipated that this will be a frequent occurance for normal */ +/* traffic patterns. */ +/* ------------------------------------------------------------------------ */ +void +ipf_nat_uncreate(fin) + fr_info_t *fin; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + int nflags; + nat_t *nat; + + switch (fin->fin_p) + { + case IPPROTO_TCP : + nflags = IPN_TCP; + break; + case IPPROTO_UDP : + nflags = IPN_UDP; + break; + default : + nflags = 0; + break; + } + + WRITE_ENTER(&softc->ipf_nat); + + if (fin->fin_out == 0) { + nat = ipf_nat_outlookup(fin, nflags, (u_int)fin->fin_p, + fin->fin_dst, fin->fin_src); + } else { + nat = ipf_nat_inlookup(fin, nflags, (u_int)fin->fin_p, + fin->fin_src, fin->fin_dst); + } + + if (nat != NULL) { + NBUMPSIDE(fin->fin_out, ns_uncreate[0]); + ipf_nat_delete(softc, nat, NL_DESTROY); + } else { + NBUMPSIDE(fin->fin_out, ns_uncreate[1]); + } + + RWLOCK_EXIT(&softc->ipf_nat); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_cmp_rules */ +/* Returns: int - 0 == success, else rules do not match. */ +/* Parameters: n1(I) - first rule to compare */ +/* n2(I) - first rule to compare */ +/* */ +/* Compare two rules using pointers to each rule. A straight bcmp will not */ +/* work as some fields (such as in_dst, in_pkts) actually do change once */ +/* the rule has been loaded into the kernel. Whilst this function returns */ +/* various non-zero returns, they're strictly to aid in debugging. Use of */ +/* this function should simply care if the result is zero or not. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat_cmp_rules(n1, n2) + ipnat_t *n1, *n2; +{ + if (n1->in_size != n2->in_size) + return 1; + + if (bcmp((char *)&n1->in_v, (char *)&n2->in_v, + offsetof(ipnat_t, in_ndst) - offsetof(ipnat_t, in_v)) != 0) + return 2; + + if (bcmp((char *)&n1->in_tuc, (char *)&n2->in_tuc, + n1->in_size - offsetof(ipnat_t, in_tuc)) != 0) + return 3; + if (n1->in_ndst.na_atype != n2->in_ndst.na_atype) + return 5; + if (n1->in_ndst.na_function != n2->in_ndst.na_function) + return 6; + if (bcmp((char *)&n1->in_ndst.na_addr, (char *)&n2->in_ndst.na_addr, + sizeof(n1->in_ndst.na_addr))) + return 7; + if (n1->in_nsrc.na_atype != n2->in_nsrc.na_atype) + return 8; + if (n1->in_nsrc.na_function != n2->in_nsrc.na_function) + return 9; + if (bcmp((char *)&n1->in_nsrc.na_addr, (char *)&n2->in_nsrc.na_addr, + sizeof(n1->in_nsrc.na_addr))) + return 10; + if (n1->in_odst.na_atype != n2->in_odst.na_atype) + return 11; + if (n1->in_odst.na_function != n2->in_odst.na_function) + return 12; + if (bcmp((char *)&n1->in_odst.na_addr, (char *)&n2->in_odst.na_addr, + sizeof(n1->in_odst.na_addr))) + return 13; + if (n1->in_osrc.na_atype != n2->in_osrc.na_atype) + return 14; + if (n1->in_osrc.na_function != n2->in_osrc.na_function) + return 15; + if (bcmp((char *)&n1->in_osrc.na_addr, (char *)&n2->in_osrc.na_addr, + sizeof(n1->in_osrc.na_addr))) + return 16; + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_rule_init */ +/* Returns: int - 0 == success, else rules do not match. */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* softn(I) - pointer to NAT context structure */ +/* n(I) - first rule to compare */ +/* */ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat_rule_init(softc, softn, n) + ipf_main_softc_t *softc; + ipf_nat_softc_t *softn; + ipnat_t *n; +{ + int error = 0; + + if ((n->in_flags & IPN_SIPRANGE) != 0) + n->in_nsrcatype = FRI_RANGE; + + if ((n->in_flags & IPN_DIPRANGE) != 0) + n->in_ndstatype = FRI_RANGE; + + if ((n->in_flags & IPN_SPLIT) != 0) + n->in_ndstatype = FRI_SPLIT; + + if ((n->in_redir & (NAT_MAP|NAT_REWRITE|NAT_DIVERTUDP)) != 0) + n->in_spnext = n->in_spmin; + + if ((n->in_redir & (NAT_REWRITE|NAT_DIVERTUDP)) != 0) { + n->in_dpnext = n->in_dpmin; + } else if (n->in_redir == NAT_REDIRECT) { + n->in_dpnext = n->in_dpmin; + } + + n->in_stepnext = 0; + + switch (n->in_v[0]) + { + case 4 : + error = ipf_nat_ruleaddrinit(softc, softn, n); + if (error != 0) + return error; + break; +#ifdef USE_INET6 + case 6 : + error = ipf_nat6_ruleaddrinit(softc, softn, n); + if (error != 0) + return error; + break; +#endif + default : + break; + } + + if (n->in_redir == (NAT_DIVERTUDP|NAT_MAP)) { + /* + * Prerecord whether or not the destination of the divert + * is local or not to the interface the packet is going + * to be sent out. + */ + n->in_dlocal = ipf_deliverlocal(softc, n->in_v[1], + n->in_ifps[1], &n->in_ndstip6); + } + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat_rule_fini */ +/* Returns: int - 0 == success, else rules do not match. */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* n(I) - rule to work on */ +/* */ +/* This function is used to release any objects that were referenced during */ +/* the rule initialisation. This is useful both when free'ing the rule and */ +/* when handling ioctls that need to initialise these fields but not */ +/* actually use them after the ioctl processing has finished. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_nat_rule_fini(softc, n) + ipf_main_softc_t *softc; + ipnat_t *n; +{ + if (n->in_odst.na_atype == FRI_LOOKUP && n->in_odst.na_ptr != NULL) + ipf_lookup_deref(softc, n->in_odst.na_type, n->in_odst.na_ptr); + + if (n->in_osrc.na_atype == FRI_LOOKUP && n->in_osrc.na_ptr != NULL) + ipf_lookup_deref(softc, n->in_osrc.na_type, n->in_osrc.na_ptr); + + if (n->in_ndst.na_atype == FRI_LOOKUP && n->in_ndst.na_ptr != NULL) + ipf_lookup_deref(softc, n->in_ndst.na_type, n->in_ndst.na_ptr); + + if (n->in_nsrc.na_atype == FRI_LOOKUP && n->in_nsrc.na_ptr != NULL) + ipf_lookup_deref(softc, n->in_nsrc.na_type, n->in_nsrc.na_ptr); + + if (n->in_divmp != NULL) + FREE_MB_T(n->in_divmp); +} diff --git a/ip_nat.h b/ip_nat.h index 09cc11989a11b..27969111f2820 100644 --- a/ip_nat.h +++ b/ip_nat.h @@ -1,12 +1,10 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1995-2001, 2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_nat.h 1.5 2/4/96 - * Id: ip_nat.h,v 2.90.2.9 2005/03/28 11:09:55 darrenr Exp + * $Id$ */ #ifndef __IP_NAT_H__ @@ -16,18 +14,18 @@ #define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) #endif -#if defined(__STDC__) || defined(__GNUC__) +#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51) #define SIOCADNAT _IOW('r', 60, struct ipfobj) #define SIOCRMNAT _IOW('r', 61, struct ipfobj) #define SIOCGNATS _IOWR('r', 62, struct ipfobj) #define SIOCGNATL _IOWR('r', 63, struct ipfobj) -#define SIOCPROXY _IOWR('r', 64, struct ap_control) +#define SIOCPURGENAT _IOWR('r', 100, struct ipfobj) #else #define SIOCADNAT _IOW(r, 60, struct ipfobj) #define SIOCRMNAT _IOW(r, 61, struct ipfobj) #define SIOCGNATS _IOWR(r, 62, struct ipfobj) #define SIOCGNATL _IOWR(r, 63, struct ipfobj) -#define SIOCPROXY _IOWR(r, 64, struct ap_control) +#define SIOCPURGENAT _IOWR(r, 100, struct ipfobj) #endif #undef LARGE_NAT /* define this if you're setting up a system to NAT @@ -79,13 +77,18 @@ #ifndef APR_LABELLEN #define APR_LABELLEN 16 #endif -#define NAT_HW_CKSUM 0x80000000 +#define NAT_HW_CKSUM 0x80000000 +#define NAT_HW_CKSUM_PART 0x40000000 #define DEF_NAT_AGE 1200 /* 10 minutes (600 seconds) */ struct ipstate; struct ap_session; +/* + * This structure is used in the active NAT table and represents an + * active NAT session. + */ typedef struct nat { ipfmutex_t nat_lock; struct nat *nat_next; @@ -102,13 +105,15 @@ typedef struct nat { void *nat_ifps[2]; void *nat_sync; ipftqent_t nat_tqe; + int nat_mtu[2]; u_32_t nat_flags; u_32_t nat_sumd[2]; /* ip checksum delta for data segment*/ u_32_t nat_ipsumd; /* ip checksum delta for ip header */ u_32_t nat_mssclamp; /* if != zero clamp MSS to this */ - i6addr_t nat_inip6; - i6addr_t nat_outip6; - i6addr_t nat_oip6; /* other ip */ + i6addr_t nat_odst6; + i6addr_t nat_osrc6; + i6addr_t nat_ndst6; + i6addr_t nat_nsrc6; U_QUAD_T nat_pkts[2]; U_QUAD_T nat_bytes[2]; union { @@ -116,33 +121,50 @@ typedef struct nat { tcpinfo_t nat_unt; icmpinfo_t nat_uni; greinfo_t nat_ugre; - } nat_un; - u_short nat_oport; /* other port */ - u_short nat_use; - u_char nat_p; /* protocol for NAT */ + } nat_unold, nat_unnew; + int nat_use; + int nat_pr[2]; /* protocol for NAT */ int nat_dir; int nat_ref; /* reference count */ - int nat_hv[2]; + u_int nat_hv[2]; char nat_ifnames[2][LIFNAMSIZ]; int nat_rev; /* 0 = forward, 1 = reverse */ + int nat_dlocal; + int nat_v[2]; /* 0 = old, 1 = new */ + u_int nat_redir; /* copy of in_redir */ } nat_t; -#define nat_inip nat_inip6.in4 -#define nat_outip nat_outip6.in4 -#define nat_oip nat_oip6.in4 +#define nat_osrcip nat_osrc6.in4 +#define nat_odstip nat_odst6.in4 +#define nat_nsrcip nat_nsrc6.in4 +#define nat_ndstip nat_ndst6.in4 +#define nat_osrcaddr nat_osrc6.in4.s_addr +#define nat_odstaddr nat_odst6.in4.s_addr +#define nat_nsrcaddr nat_nsrc6.in4.s_addr +#define nat_ndstaddr nat_ndst6.in4.s_addr #define nat_age nat_tqe.tqe_die -#define nat_inport nat_un.nat_unt.ts_sport -#define nat_outport nat_un.nat_unt.ts_dport -#define nat_type nat_un.nat_uni.ici_type -#define nat_seq nat_un.nat_uni.ici_seq -#define nat_id nat_un.nat_uni.ici_id +#define nat_osport nat_unold.nat_unt.ts_sport +#define nat_odport nat_unold.nat_unt.ts_dport +#define nat_nsport nat_unnew.nat_unt.ts_sport +#define nat_ndport nat_unnew.nat_unt.ts_dport +#define nat_oicmpid nat_unold.nat_uni.ici_id +#define nat_nicmpid nat_unnew.nat_uni.ici_id +#define nat_type nat_unold.nat_uni.ici_type +#define nat_oseq nat_unold.nat_uni.ici_seq +#define nat_nseq nat_unnew.nat_uni.ici_seq #define nat_tcpstate nat_tqe.tqe_state +#define nat_die nat_tqe.tqe_die +#define nat_touched nat_tqe.tqe_touched /* * Values for nat_dir */ #define NAT_INBOUND 0 #define NAT_OUTBOUND 1 +#define NAT_ENCAPIN 2 +#define NAT_ENCAPOUT 3 +#define NAT_DIVERTIN 4 +#define NAT_DIVERTOUT 5 /* * Definitions for nat_flags @@ -153,7 +175,7 @@ typedef struct nat { #define NAT_ICMPQUERY 0x0008 /* IPN_ICMPQUERY */ #define NAT_SEARCH 0x0010 #define NAT_SLAVE 0x0020 /* Slave connection for a proxy */ -#define NAT_NOTRULEPORT 0x0040 +#define NAT_NOTRULEPORT 0x0040 /* Don't use the port # in the NAT rule */ #define NAT_TCPUDP (NAT_TCP|NAT_UDP) #define NAT_TCPUDPICMP (NAT_TCP|NAT_UDP|NAT_ICMPERR) @@ -171,8 +193,29 @@ typedef struct nat { #define NAT_DEBUG 0x800000 +typedef struct nat_addr_s { + i6addr_t na_addr[2]; + i6addr_t na_nextaddr; + int na_atype; + int na_function; +} nat_addr_t; + +#define na_nextip na_nextaddr.in4.s_addr +#define na_nextip6 na_nextaddr.in6 +#define na_num na_addr[0].iplookupnum +#define na_type na_addr[0].iplookuptype +#define na_subtype na_addr[0].iplookupsubtype +#define na_ptr na_addr[1].iplookupptr +#define na_func na_addr[1].iplookupfunc + + +/* + * This structure represents an actual NAT rule, loaded by ipnat. + */ typedef struct ipnat { + ipfmutex_t in_lock; struct ipnat *in_next; /* NAT rule list next */ + struct ipnat **in_pnext; /* prior rdr next ptr */ struct ipnat *in_rnext; /* rdr rule hash next */ struct ipnat **in_prnext; /* prior rdr next ptr */ struct ipnat *in_mnext; /* map rule hash next */ @@ -181,49 +224,114 @@ typedef struct ipnat { void *in_ifps[2]; void *in_apr; char *in_comment; - i6addr_t in_next6; + mb_t *in_divmp; + void *in_pconf; + U_QUAD_T in_pkts[2]; + U_QUAD_T in_bytes[2]; u_long in_space; u_long in_hits; - u_int in_use; - u_int in_hv; + int in_size; + int in_use; + u_int in_hv[2]; int in_flineno; /* conf. file line number */ - u_short in_pnext; - u_char in_v; - u_char in_xxx; + int in_stepnext; + int in_dlocal; + u_short in_dpnext; + u_short in_spnext; /* From here to the end is covered by IPN_CMPSIZ */ + u_char in_v[2]; /* 0 = old, 1 = new */ u_32_t in_flags; u_32_t in_mssclamp; /* if != 0 clamp MSS to this */ u_int in_age[2]; int in_redir; /* see below for values */ - int in_p; /* protocol. */ - i6addr_t in_in[2]; - i6addr_t in_out[2]; - i6addr_t in_src[2]; + int in_pr[2]; /* protocol. */ + nat_addr_t in_ndst; + nat_addr_t in_nsrc; + nat_addr_t in_osrc; + nat_addr_t in_odst; frtuc_t in_tuc; - u_short in_port[2]; u_short in_ppip; /* ports per IP. */ u_short in_ippip; /* IP #'s per IP# */ - char in_ifnames[2][LIFNAMSIZ]; - char in_plabel[APR_LABELLEN]; /* proxy label. */ + u_short in_ndports[2]; + u_short in_nsports[2]; + int in_ifnames[2]; + int in_plabel; /* proxy label. */ + int in_pconfig; /* proxy label. */ ipftag_t in_tag; + int in_namelen; + char in_names[1]; } ipnat_t; -#define in_pmin in_port[0] /* Also holds static redir port */ -#define in_pmax in_port[1] -#define in_nextip in_next6.in4 -#define in_nip in_next6.in4.s_addr -#define in_inip in_in[0].in4.s_addr -#define in_inmsk in_in[1].in4.s_addr -#define in_outip in_out[0].in4.s_addr -#define in_outmsk in_out[1].in4.s_addr -#define in_srcip in_src[0].in4.s_addr -#define in_srcmsk in_src[1].in4.s_addr +/* + * MAP-IN MAP-OUT RDR-IN RDR-OUT + * osrc X == src == src X + * odst X == dst == dst X + * nsrc == dst X X == dst + * ndst == src X X == src + */ +#define in_dpmin in_ndports[0] /* Also holds static redir port */ +#define in_dpmax in_ndports[1] +#define in_spmin in_nsports[0] /* Also holds static redir port */ +#define in_spmax in_nsports[1] +#define in_ndport in_ndports[0] +#define in_nsport in_nsports[0] +#define in_dipnext in_ndst.na_nextaddr.in4 +#define in_dipnext6 in_ndst.na_nextaddr +#define in_dnip in_ndst.na_nextaddr.in4.s_addr +#define in_dnip6 in_ndst.na_nextaddr +#define in_sipnext in_nsrc.na_nextaddr.in4 +#define in_snip in_nsrc.na_nextaddr.in4.s_addr +#define in_snip6 in_nsrc.na_nextaddr +#define in_odstip in_odst.na_addr[0].in4 +#define in_odstip6 in_odst.na_addr[0] +#define in_odstaddr in_odst.na_addr[0].in4.s_addr +#define in_odstmsk in_odst.na_addr[1].in4.s_addr +#define in_odstmsk6 in_odst.na_addr[1] +#define in_odstatype in_odst.na_atype +#define in_osrcip in_osrc.na_addr[0].in4 +#define in_osrcip6 in_osrc.na_addr[0] +#define in_osrcaddr in_osrc.na_addr[0].in4.s_addr +#define in_osrcmsk in_osrc.na_addr[1].in4.s_addr +#define in_osrcmsk6 in_osrc.na_addr[1] +#define in_osrcatype in_osrc.na_atype +#define in_ndstip in_ndst.na_addr[0].in4 +#define in_ndstip6 in_ndst.na_addr[0] +#define in_ndstaddr in_ndst.na_addr[0].in4.s_addr +#define in_ndstmsk in_ndst.na_addr[1].in4.s_addr +#define in_ndstmsk6 in_ndst.na_addr[1] +#define in_ndstatype in_ndst.na_atype +#define in_ndstafunc in_ndst.na_function +#define in_nsrcip in_nsrc.na_addr[0].in4 +#define in_nsrcip6 in_nsrc.na_addr[0] +#define in_nsrcaddr in_nsrc.na_addr[0].in4.s_addr +#define in_nsrcmsk in_nsrc.na_addr[1].in4.s_addr +#define in_nsrcmsk6 in_nsrc.na_addr[1] +#define in_nsrcatype in_nsrc.na_atype +#define in_nsrcafunc in_nsrc.na_function #define in_scmp in_tuc.ftu_scmp #define in_dcmp in_tuc.ftu_dcmp #define in_stop in_tuc.ftu_stop #define in_dtop in_tuc.ftu_dtop -#define in_sport in_tuc.ftu_sport -#define in_dport in_tuc.ftu_dport +#define in_osport in_tuc.ftu_sport +#define in_odport in_tuc.ftu_dport +#define in_ndstnum in_ndst.na_addr[0].iplookupnum +#define in_ndsttype in_ndst.na_addr[0].iplookuptype +#define in_ndstptr in_ndst.na_addr[1].iplookupptr +#define in_ndstfunc in_ndst.na_addr[1].iplookupfunc +#define in_nsrcnum in_nsrc.na_addr[0].iplookupnum +#define in_nsrctype in_nsrc.na_addr[0].iplookuptype +#define in_nsrcptr in_nsrc.na_addr[1].iplookupptr +#define in_nsrcfunc in_nsrc.na_addr[1].iplookupfunc +#define in_odstnum in_odst.na_addr[0].iplookupnum +#define in_odsttype in_odst.na_addr[0].iplookuptype +#define in_odstptr in_odst.na_addr[1].iplookupptr +#define in_odstfunc in_odst.na_addr[1].iplookupfunc +#define in_osrcnum in_osrc.na_addr[0].iplookupnum +#define in_osrctype in_osrc.na_addr[0].iplookuptype +#define in_osrcptr in_osrc.na_addr[1].iplookupptr +#define in_osrcfunc in_osrc.na_addr[1].iplookupfunc +#define in_icmpidmin in_nsports[0] +#define in_icmpidmax in_nsports[1] /* * Bit definitions for in_flags @@ -238,23 +346,30 @@ typedef struct ipnat { #define IPN_TCPUDPICMPQ (IPN_TCP|IPN_UDP|IPN_ICMPQUERY) #define IPN_RF (IPN_TCPUDP|IPN_DELETE|IPN_ICMPERR) #define IPN_AUTOPORTMAP 0x00010 -#define IPN_IPRANGE 0x00020 -#define IPN_FILTER 0x00040 -#define IPN_SPLIT 0x00080 -#define IPN_ROUNDR 0x00100 -#define IPN_NOTSRC 0x04000 -#define IPN_NOTDST 0x08000 -#define IPN_DYNSRCIP 0x10000 /* dynamic src IP# */ -#define IPN_DYNDSTIP 0x20000 /* dynamic dst IP# */ -#define IPN_DELETE 0x40000 -#define IPN_STICKY 0x80000 -#define IPN_FRAG 0x100000 -#define IPN_FIXEDDPORT 0x200000 -#define IPN_FINDFORWARD 0x400000 -#define IPN_IN 0x800000 -#define IPN_USERFLAGS (IPN_TCPUDP|IPN_AUTOPORTMAP|IPN_IPRANGE|IPN_SPLIT|\ - IPN_ROUNDR|IPN_FILTER|IPN_NOTSRC|IPN_NOTDST|\ - IPN_FRAG|IPN_STICKY|IPN_FIXEDDPORT|IPN_ICMPQUERY) +#define IPN_FILTER 0x00020 +#define IPN_SPLIT 0x00040 +#define IPN_ROUNDR 0x00080 +#define IPN_SIPRANGE 0x00100 +#define IPN_DIPRANGE 0x00200 +#define IPN_NOTSRC 0x00400 +#define IPN_NOTDST 0x00800 +#define IPN_NO 0x01000 +#define IPN_DYNSRCIP 0x02000 /* dynamic src IP# */ +#define IPN_DYNDSTIP 0x04000 /* dynamic dst IP# */ +#define IPN_DELETE 0x08000 +#define IPN_STICKY 0x10000 +#define IPN_FRAG 0x20000 +#define IPN_FIXEDSPORT 0x40000 +#define IPN_FIXEDDPORT 0x80000 +#define IPN_FINDFORWARD 0x100000 +#define IPN_IN 0x200000 +#define IPN_SEQUENTIAL 0x400000 +#define IPN_PURGE 0x800000 +#define IPN_PROXYRULE 0x1000000 +#define IPN_USERFLAGS (IPN_TCPUDP|IPN_AUTOPORTMAP|IPN_SIPRANGE|IPN_SPLIT|\ + IPN_ROUNDR|IPN_FILTER|IPN_NOTSRC|IPN_NOTDST|IPN_NO|\ + IPN_FRAG|IPN_STICKY|IPN_FIXEDDPORT|IPN_ICMPQUERY|\ + IPN_DIPRANGE|IPN_SEQUENTIAL|IPN_PURGE) /* * Values for in_redir @@ -263,22 +378,33 @@ typedef struct ipnat { #define NAT_REDIRECT 0x02 #define NAT_BIMAP (NAT_MAP|NAT_REDIRECT) #define NAT_MAPBLK 0x04 +#define NAT_REWRITE 0x08 +#define NAT_ENCAP 0x10 +#define NAT_DIVERTUDP 0x20 #define MAPBLK_MINPORT 1024 /* don't use reserved ports for src port */ #define USABLE_PORTS (65536 - MAPBLK_MINPORT) -#define IPN_CMPSIZ (sizeof(ipnat_t) - offsetof(ipnat_t, in_flags)) +#define IPN_CMPSIZ (sizeof(ipnat_t) - offsetof(ipnat_t, in_v)) typedef struct natlookup { - struct in_addr nl_inip; - struct in_addr nl_outip; - struct in_addr nl_realip; - int nl_flags; - u_short nl_inport; - u_short nl_outport; - u_short nl_realport; + i6addr_t nl_inipaddr; + i6addr_t nl_outipaddr; + i6addr_t nl_realipaddr; + int nl_v; + int nl_flags; + u_short nl_inport; + u_short nl_outport; + u_short nl_realport; } natlookup_t; +#define nl_inip nl_inipaddr.in4 +#define nl_outip nl_outipaddr.in4 +#define nl_realip nl_realipaddr.in4 +#define nl_inip6 nl_inipaddr.in6 +#define nl_outip6 nl_outipaddr.in6 +#define nl_realip6 nl_realipaddr.in6 + typedef struct nat_save { void *ipn_next; @@ -297,24 +423,6 @@ typedef struct natget { } natget_t; -typedef struct nattrpnt { - struct in_addr tr_dstip; /* real destination IP# */ - struct in_addr tr_srcip; /* real source IP# */ - struct in_addr tr_locip; /* local source IP# */ - u_int tr_flags; - int tr_expire; - u_short tr_dstport; /* real destination port# */ - u_short tr_srcport; /* real source port# */ - u_short tr_locport; /* local source port# */ - struct nattrpnt *tr_hnext; - struct nattrpnt **tr_phnext; - struct nattrpnt *tr_next; - struct nattrpnt **tr_pnext; /* previous next */ -} nattrpnt_t; - -#define TN_CMPSIZ offsetof(nattrpnt_t, tr_hnext) - - /* * This structure gets used to help NAT sessions keep the same NAT rule (and * thus translation for IP address) when: @@ -322,16 +430,30 @@ typedef struct nattrpnt { * (b) different IP add */ typedef struct hostmap { + struct hostmap *hm_hnext; + struct hostmap **hm_phnext; struct hostmap *hm_next; struct hostmap **hm_pnext; struct ipnat *hm_ipnat; - struct in_addr hm_srcip; - struct in_addr hm_dstip; - struct in_addr hm_mapip; + i6addr_t hm_osrcip6; + i6addr_t hm_odstip6; + i6addr_t hm_nsrcip6; + i6addr_t hm_ndstip6; u_32_t hm_port; int hm_ref; + int hm_hv; + int hm_v; } hostmap_t; +#define hm_osrcip hm_osrcip6.in4 +#define hm_odstip hm_odstip6.in4 +#define hm_nsrcip hm_nsrcip6.in4 +#define hm_ndstip hm_ndstip6.in4 +#define hm_osrc6 hm_osrcip6.in6 +#define hm_odst6 hm_odstip6.in6 +#define hm_nsrc6 hm_nsrcip6.in6 +#define hm_ndst6 hm_ndstip6.in6 + /* * Structure used to pass information in to nat_newmap and nat_newrdr. @@ -340,9 +462,7 @@ typedef struct natinfo { ipnat_t *nai_np; u_32_t nai_sum1; u_32_t nai_sum2; - u_32_t nai_nflags; - u_32_t nai_flags; - struct in_addr nai_ip; + struct in_addr nai_ip; /* In host byte order */ u_short nai_port; u_short nai_nport; u_short nai_sport; @@ -350,59 +470,134 @@ typedef struct natinfo { } natinfo_t; -typedef struct natstat { - u_long ns_mapped[2]; - u_long ns_rules; +typedef struct nat_stat_side { + u_int *ns_bucketlen; + nat_t **ns_table; u_long ns_added; - u_long ns_expire; + u_long ns_appr_fail; + u_long ns_badnat; + u_long ns_badnatnew; + u_long ns_badnextaddr; + u_long ns_bucket_max; + u_long ns_clone_nomem; + u_long ns_decap_bad; + u_long ns_decap_fail; + u_long ns_decap_pullup; + u_long ns_divert_dup; + u_long ns_divert_exist; + u_long ns_drop; + u_long ns_encap_dup; + u_long ns_encap_pullup; + u_long ns_exhausted; + u_long ns_icmp_address; + u_long ns_icmp_basic; + u_long ns_icmp_mbuf; + u_long ns_icmp_notfound; + u_long ns_icmp_rebuild; + u_long ns_icmp_short; + u_long ns_icmp_size; + u_long ns_ifpaddrfail; + u_long ns_ignored; + u_long ns_insert_fail; u_long ns_inuse; - u_long ns_logged; - u_long ns_logfail; + u_long ns_log; + u_long ns_lookup_miss; + u_long ns_lookup_nowild; + u_long ns_new_ifpaddr; u_long ns_memfail; - u_long ns_badnat; - u_long ns_addtrpnt; - nat_t **ns_table[2]; - hostmap_t **ns_maptable; - ipnat_t *ns_list; - void *ns_apslist; - u_int ns_wilds; - u_int ns_nattab_sz; - u_int ns_nattab_max; - u_int ns_rultab_sz; - u_int ns_rdrtab_sz; - u_int ns_trpntab_sz; - u_int ns_hostmap_sz; - nat_t *ns_instances; - nattrpnt_t *ns_trpntlist; - u_long *ns_bucketlen[2]; + u_long ns_table_max; + u_long ns_translated; + u_long ns_unfinalised; + u_long ns_wrap; + u_long ns_xlate_null; + u_long ns_xlate_exists; + u_long ns_ipf_proxy_fail; + u_long ns_uncreate[2]; +} nat_stat_side_t; + + +typedef struct natstat { + nat_t *ns_instances; + ipnat_t *ns_list; + hostmap_t *ns_maplist; + hostmap_t **ns_maptable; + u_int ns_active; + u_long ns_addtrpnt; + u_long ns_divert_build; + u_long ns_expire; + u_long ns_flush_all; + u_long ns_flush_closing; + u_long ns_flush_queue; + u_long ns_flush_state; + u_long ns_flush_timeout; + u_long ns_hm_new; + u_long ns_hm_newfail; + u_long ns_hm_addref; + u_long ns_hm_nullnp; + u_long ns_log_ok; + u_long ns_log_fail; + u_int ns_hostmap_sz; + u_int ns_nattab_sz; + u_int ns_nattab_max; + u_int ns_orphans; + u_int ns_rules; + u_int ns_rules_map; + u_int ns_rules_rdr; + u_int ns_rultab_sz; + u_int ns_rdrtab_sz; + u_32_t ns_ticks; + u_int ns_trpntab_sz; + u_int ns_wilds; + u_long ns_proto[256]; + nat_stat_side_t ns_side[2]; +#ifdef USE_INET6 + nat_stat_side_t ns_side6[2]; +#endif } natstat_t; typedef struct natlog { - struct in_addr nl_origip; - struct in_addr nl_outip; - struct in_addr nl_inip; - u_short nl_origport; - u_short nl_outport; - u_short nl_inport; - u_short nl_type; - int nl_rule; + i6addr_t nl_osrcip; + i6addr_t nl_odstip; + i6addr_t nl_nsrcip; + i6addr_t nl_ndstip; + u_short nl_osrcport; + u_short nl_odstport; + u_short nl_nsrcport; + u_short nl_ndstport; + int nl_action; + int nl_type; + int nl_rule; U_QUAD_T nl_pkts[2]; U_QUAD_T nl_bytes[2]; - u_char nl_p; + u_char nl_p[2]; + u_char nl_v[2]; + u_char nl_ifnames[2][LIFNAMSIZ]; } natlog_t; -#define NL_NEWMAP NAT_MAP -#define NL_NEWRDR NAT_REDIRECT -#define NL_NEWBIMAP NAT_BIMAP -#define NL_NEWBLOCK NAT_MAPBLK -#define NL_CLONE 0xfffd +#define NL_NEW 0 +#define NL_CLONE 1 +#define NL_PURGE 0xfffc +#define NL_DESTROY 0xfffd #define NL_FLUSH 0xfffe #define NL_EXPIRE 0xffff -#define NAT_HASH_FN(k,l,m) (((k) + ((k) >> 12) + l) % (m)) - -#define LONG_SUM(in) (((in) & 0xffff) + ((in) >> 16)) +#define NAT_HASH_FN(_k,_l,_m) (((_k) + ((_k) >> 12) + _l) % (_m)) +#define NAT_HASH_FN6(_k,_l,_m) ((((u_32_t *)(_k))[3] \ + + (((u_32_t *)(_k))[3] >> 12) \ + + (((u_32_t *)(_k))[2]) \ + + (((u_32_t *)(_k))[2] >> 12) \ + + (((u_32_t *)(_k))[1]) \ + + (((u_32_t *)(_k))[1] >> 12) \ + + (((u_32_t *)(_k))[0]) \ + + (((u_32_t *)(_k))[0] >> 12) \ + + _l) % (_m)) + +#define LONG_SUM(_i) (((_i) & 0xffff) + ((_i) >> 16)) +#define LONG_SUM6(_i) (LONG_SUM(ntohl(((u_32_t *)(_i))[0])) + \ + LONG_SUM(ntohl(((u_32_t *)(_i))[1])) + \ + LONG_SUM(ntohl(((u_32_t *)(_i))[2])) + \ + LONG_SUM(ntohl(((u_32_t *)(_i))[3]))) #define CALC_SUMD(s1, s2, sd) { \ (s1) = ((s1) & 0xffff) + ((s1) >> 16); \ @@ -418,60 +613,161 @@ typedef struct natlog { #define NAT_SYSSPACE 0x80000000 #define NAT_LOCKHELD 0x40000000 - -extern u_int ipf_nattable_sz; -extern u_int ipf_nattable_max; -extern u_int ipf_natrules_sz; -extern u_int ipf_rdrrules_sz; -extern u_int ipf_hostmap_sz; -extern u_int fr_nat_maxbucket; -extern u_int fr_nat_maxbucket_reset; -extern int fr_nat_lock; -extern void fr_natsync __P((void *)); -extern u_long fr_defnatage; -extern u_long fr_defnaticmpage; -extern u_long fr_defnatipage; - /* nat_table[0] -> hashed list sorted by inside (ip, port) */ - /* nat_table[1] -> hashed list sorted by outside (ip, port) */ -extern nat_t **nat_table[2]; -extern nat_t *nat_instances; -extern ipnat_t *nat_list; -extern ipnat_t **nat_rules; -extern ipnat_t **rdr_rules; -extern ipftq_t *nat_utqe; -extern natstat_t nat_stats; - +/* + * This is present in ip_nat.h because it needs to be shared between + * ip_nat.c and ip_nat6.c + */ +typedef struct ipf_nat_softc_s { + ipfmutex_t ipf_nat_new; + ipfmutex_t ipf_nat_io; + int ipf_nat_doflush; + int ipf_nat_logging; + int ipf_nat_lock; + int ipf_nat_inited; + int ipf_nat_table_wm_high; + int ipf_nat_table_wm_low; + u_int ipf_nat_table_max; + u_int ipf_nat_table_sz; + u_int ipf_nat_maprules_sz; + u_int ipf_nat_rdrrules_sz; + u_int ipf_nat_hostmap_sz; + u_int ipf_nat_maxbucket; + u_int ipf_nat_last_force_flush; + u_int ipf_nat_defage; + u_int ipf_nat_defipage; + u_int ipf_nat_deficmpage; + ipf_v4_masktab_t ipf_nat_map_mask; + ipf_v6_masktab_t ipf_nat6_map_mask; + ipf_v4_masktab_t ipf_nat_rdr_mask; + ipf_v6_masktab_t ipf_nat6_rdr_mask; + nat_t **ipf_nat_table[2]; + nat_t *ipf_nat_instances; + ipnat_t *ipf_nat_list; + ipnat_t **ipf_nat_list_tail; + ipnat_t **ipf_nat_map_rules; + ipnat_t **ipf_nat_rdr_rules; + ipftq_t *ipf_nat_utqe; + hostmap_t **ipf_hm_maptable ; + hostmap_t *ipf_hm_maplist ; + ipftuneable_t *ipf_nat_tune; + ipftq_t ipf_nat_udptq; + ipftq_t ipf_nat_udpacktq; + ipftq_t ipf_nat_icmptq; + ipftq_t ipf_nat_icmpacktq; + ipftq_t ipf_nat_iptq; + ipftq_t ipf_nat_pending; + ipftq_t ipf_nat_tcptq[IPF_TCP_NSTATES]; + natstat_t ipf_nat_stats; +} ipf_nat_softc_t ; + +#define ipf_nat_map_max ipf_nat_map_mask.imt4_max +#define ipf_nat_rdr_max ipf_nat_rdr_mask.imt4_max +#define ipf_nat6_map_max ipf_nat6_map_mask.imt6_max +#define ipf_nat6_rdr_max ipf_nat6_rdr_mask.imt6_max +#define ipf_nat_map_active_masks ipf_nat_map_mask.imt4_active +#define ipf_nat_rdr_active_masks ipf_nat_rdr_mask.imt4_active +#define ipf_nat6_map_active_masks ipf_nat6_map_mask.imt6_active +#define ipf_nat6_rdr_active_masks ipf_nat6_rdr_mask.imt6_active + +extern frentry_t ipfnatblock; + +extern void ipf_fix_datacksum __P((u_short *, u_32_t)); +extern void ipf_fix_incksum __P((int, u_short *, u_32_t, u_32_t)); +extern void ipf_fix_outcksum __P((int, u_short *, u_32_t, u_32_t)); + +extern int ipf_nat_checkin __P((fr_info_t *, u_32_t *)); +extern int ipf_nat_checkout __P((fr_info_t *, u_32_t *)); +extern void ipf_nat_delete __P((ipf_main_softc_t *, struct nat *, int)); +extern void ipf_nat_deref __P((ipf_main_softc_t *, nat_t **)); +extern void ipf_nat_expire __P((ipf_main_softc_t *)); +extern int ipf_nat_hashtab_add __P((ipf_main_softc_t *, + ipf_nat_softc_t *, nat_t *)); +extern void ipf_nat_hostmapdel __P((ipf_main_softc_t *, hostmap_t **)); +extern int ipf_nat_hostmap_rehash __P((ipf_main_softc_t *, + ipftuneable_t *, ipftuneval_t *)); +extern nat_t *ipf_nat_icmperrorlookup __P((fr_info_t *, int)); +extern nat_t *ipf_nat_icmperror __P((fr_info_t *, u_int *, int)); #if defined(__OpenBSD__) -extern void nat_ifdetach __P((void *)); +extern void ipf_nat_ifdetach __P((void *)); #endif -extern int fr_nat_ioctl __P((caddr_t, ioctlcmd_t, int)); -extern int fr_natinit __P((void)); -extern nat_t *nat_new __P((fr_info_t *, ipnat_t *, nat_t **, u_int, int)); -extern nat_t *nat_outlookup __P((fr_info_t *, u_int, u_int, struct in_addr, - struct in_addr)); -extern void fix_datacksum __P((u_short *, u_32_t)); -extern nat_t *nat_inlookup __P((fr_info_t *, u_int, u_int, struct in_addr, - struct in_addr)); -extern nat_t *nat_tnlookup __P((fr_info_t *, int)); -extern nat_t *nat_maplookup __P((void *, u_int, struct in_addr, +extern int ipf_nat_init __P((void)); +extern nat_t *ipf_nat_inlookup __P((fr_info_t *, u_int, u_int, + struct in_addr, struct in_addr)); +extern int ipf_nat_in __P((fr_info_t *, nat_t *, int, u_32_t)); +extern int ipf_nat_insert __P((ipf_main_softc_t *, ipf_nat_softc_t *, + nat_t *)); +extern int ipf_nat_ioctl __P((ipf_main_softc_t *, caddr_t, ioctlcmd_t, + int, int, void *)); +extern void ipf_nat_log __P((ipf_main_softc_t *, ipf_nat_softc_t *, + struct nat *, u_int)); +extern nat_t *ipf_nat_lookupredir __P((natlookup_t *)); +extern nat_t *ipf_nat_maplookup __P((void *, u_int, struct in_addr, struct in_addr)); -extern nat_t *nat_lookupredir __P((natlookup_t *)); -extern nat_t *nat_icmperrorlookup __P((fr_info_t *, int)); -extern nat_t *nat_icmperror __P((fr_info_t *, u_int *, int)); -extern int nat_insert __P((nat_t *, int)); - -extern int fr_checknatout __P((fr_info_t *, u_32_t *)); -extern int fr_natout __P((fr_info_t *, nat_t *, int, u_32_t)); -extern int fr_checknatin __P((fr_info_t *, u_32_t *)); -extern int fr_natin __P((fr_info_t *, nat_t *, int, u_32_t)); -extern void fr_natunload __P((void)); -extern void fr_natexpire __P((void)); -extern void nat_log __P((struct nat *, u_int)); -extern void fix_incksum __P((fr_info_t *, u_short *, u_32_t)); -extern void fix_outcksum __P((fr_info_t *, u_short *, u_32_t)); -extern void fr_natderef __P((nat_t **)); -extern u_short *nat_proto __P((fr_info_t *, nat_t *, u_int)); -extern void nat_update __P((fr_info_t *, nat_t *, ipnat_t *)); -extern void fr_setnatqueue __P((nat_t *, int)); +extern nat_t *ipf_nat_add __P((fr_info_t *, ipnat_t *, nat_t **, + u_int, int)); +extern int ipf_nat_out __P((fr_info_t *, nat_t *, int, u_32_t)); +extern nat_t *ipf_nat_outlookup __P((fr_info_t *, u_int, u_int, + struct in_addr, struct in_addr)); +extern u_short *ipf_nat_proto __P((fr_info_t *, nat_t *, u_int)); +extern void ipf_nat_rule_deref __P((ipf_main_softc_t *, ipnat_t **)); +extern void ipf_nat_setqueue __P((ipf_main_softc_t *, ipf_nat_softc_t *, + nat_t *)); +extern void ipf_nat_setpending __P((ipf_main_softc_t *, nat_t *)); +extern nat_t *ipf_nat_tnlookup __P((fr_info_t *, int)); +extern void ipf_nat_update __P((fr_info_t *, nat_t *)); +extern int ipf_nat_in __P((fr_info_t *, nat_t *, int, u_32_t)); +extern int ipf_nat_out __P((fr_info_t *, nat_t *, int, u_32_t)); +extern int ipf_nat_rehash __P((ipf_main_softc_t *, ipftuneable_t *, + ipftuneval_t *)); +extern int ipf_nat_rehash_rules __P((ipf_main_softc_t *, ipftuneable_t *, + ipftuneval_t *)); +extern int ipf_nat_settimeout __P((struct ipf_main_softc_s *, + ipftuneable_t *, ipftuneval_t *)); +extern void ipf_nat_sync __P((ipf_main_softc_t *, void *)); + +extern nat_t *ipf_nat_clone __P((fr_info_t *, nat_t *)); +extern void ipf_nat_delmap __P((ipf_nat_softc_t *, ipnat_t *)); +extern void ipf_nat_delrdr __P((ipf_nat_softc_t *, ipnat_t *)); +extern int ipf_nat_wildok __P((nat_t *, int, int, int, int)); +extern void ipf_nat_setlock __P((void *, int)); +extern void ipf_nat_load __P((void)); +extern void *ipf_nat_soft_create __P((ipf_main_softc_t *)); +extern int ipf_nat_soft_init __P((ipf_main_softc_t *, void *)); +extern void ipf_nat_soft_destroy __P((ipf_main_softc_t *, void *)); +extern int ipf_nat_soft_fini __P((ipf_main_softc_t *, void *)); +extern int ipf_nat_main_load __P((void)); +extern int ipf_nat_main_unload __P((void)); +extern ipftq_t *ipf_nat_add_tq __P((ipf_main_softc_t *, int)); +extern void ipf_nat_uncreate __P((fr_info_t *)); + +#ifdef USE_INET6 +extern nat_t *ipf_nat6_add __P((fr_info_t *, ipnat_t *, nat_t **, + u_int, int)); +extern void ipf_nat6_addrdr __P((ipf_nat_softc_t *, ipnat_t *)); +extern void ipf_nat6_addmap __P((ipf_nat_softc_t *, ipnat_t *)); +extern void ipf_nat6_addencap __P((ipf_nat_softc_t *, ipnat_t *)); +extern int ipf_nat6_checkout __P((fr_info_t *, u_32_t *)); +extern int ipf_nat6_checkin __P((fr_info_t *, u_32_t *)); +extern void ipf_nat6_delmap __P((ipf_nat_softc_t *, ipnat_t *)); +extern void ipf_nat6_delrdr __P((ipf_nat_softc_t *, ipnat_t *)); +extern int ipf_nat6_finalise __P((fr_info_t *, nat_t *)); +extern nat_t *ipf_nat6_icmperror __P((fr_info_t *, u_int *, int)); +extern nat_t *ipf_nat6_icmperrorlookup __P((fr_info_t *, int)); +extern nat_t *ipf_nat6_inlookup __P((fr_info_t *, u_int, u_int, + struct in6_addr *, struct in6_addr *)); +extern u_32_t ipf_nat6_ip6subtract __P((i6addr_t *, i6addr_t *)); +extern frentry_t *ipf_nat6_ipfin __P((fr_info_t *, u_32_t *)); +extern frentry_t *ipf_nat6_ipfout __P((fr_info_t *, u_32_t *)); +extern nat_t *ipf_nat6_lookupredir __P((natlookup_t *)); +extern int ipf_nat6_newmap __P((fr_info_t *, nat_t *, natinfo_t *)); +extern int ipf_nat6_newrdr __P((fr_info_t *, nat_t *, natinfo_t *)); +extern nat_t *ipf_nat6_outlookup __P((fr_info_t *, u_int, u_int, + struct in6_addr *, struct in6_addr *)); +extern int ipf_nat6_newrewrite __P((fr_info_t *, nat_t *, natinfo_t *)); +extern int ipf_nat6_newdivert __P((fr_info_t *, nat_t *, natinfo_t *)); +extern int ipf_nat6_ruleaddrinit __P((ipf_main_softc_t *, ipf_nat_softc_t *, ipnat_t *)); + +#endif + #endif /* __IP_NAT_H__ */ diff --git a/ip_nat6.c b/ip_nat6.c new file mode 100644 index 0000000000000..9fb5db1f94bc2 --- /dev/null +++ b/ip_nat6.c @@ -0,0 +1,4098 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ +#if defined(KERNEL) || defined(_KERNEL) +# undef KERNEL +# undef ipf_nat6_KERNEL +# define KERNEL 1 +# define ipf_nat6_KERNEL 1 +#endif +#include <sys/errno.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/time.h> +#include <sys/file.h> +#if defined(_KERNEL) && defined(__NetBSD_Version__) && \ + (__NetBSD_Version__ >= 399002000) +# include <sys/kauth.h> +#endif +#if !defined(_KERNEL) +# include <stdio.h> +# include <string.h> +# include <stdlib.h> +# define ipf_nat6_KERNEL +# ifdef ipf_nat6__OpenBSD__ +struct file; +# endif +# include <sys/uio.h> +# undef ipf_nat6_KERNEL +#endif +#if defined(_KERNEL) && (__FreeBSD_version >= 220000) +# include <sys/filio.h> +# include <sys/fcntl.h> +#else +# include <sys/ioctl.h> +#endif +#if !defined(AIX) +# include <sys/fcntl.h> +#endif +#if !defined(linux) +# include <sys/protosw.h> +#endif +#include <sys/socket.h> +#if defined(_KERNEL) +# include <sys/systm.h> +# if !defined(__SVR4) && !defined(__svr4__) +# include <sys/mbuf.h> +# endif +#endif +#if defined(__SVR4) || defined(__svr4__) +# include <sys/filio.h> +# include <sys/byteorder.h> +# ifdef ipf_nat6_KERNEL +# include <sys/dditypes.h> +# endif +# include <sys/stream.h> +# include <sys/kmem.h> +#endif +#if ipf_nat6__FreeBSD_version >= 300000 +# include <sys/queue.h> +#endif +#include <net/if.h> +#if ipf_nat6__FreeBSD_version >= 300000 +# include <net/if_var.h> +#endif +#ifdef sun +# include <net/af.h> +#endif +#include <net/route.h> +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> + +#ifdef RFC1825 +# include <vpn/md5.h> +# include <vpn/ipsec.h> +extern struct ifnet vpnif; +#endif + +#if !defined(linux) +# include <netinet/ip_var.h> +#endif +#include <netinet/tcp.h> +#include <netinet/udp.h> +#include <netinet/ip_icmp.h> +#include "netinet/ip_compat.h" +#include <netinet/tcpip.h> +#include "netinet/ip_fil.h" +#include "netinet/ip_nat.h" +#include "netinet/ip_frag.h" +#include "netinet/ip_state.h" +#include "netinet/ip_proxy.h" +#include "netinet/ip_lookup.h" +#include "netinet/ip_dstlist.h" +#include "netinet/ip_sync.h" +#if (__FreeBSD_version >= 300000) +# include <sys/malloc.h> +#endif +#ifdef HAS_SYS_MD5_H +# include <sys/md5.h> +#else +# include "md5.h" +#endif +/* END OF INCLUDES */ + +#undef SOCKADDR_IN +#define SOCKADDR_IN struct sockaddr_in + +#if !defined(lint) +static const char rcsid[] = "@(#)$Id: ip_nat6.c,v 1.22.2.20 2012/07/22 08:04:23 darren_r Exp $"; +#endif + +#ifdef USE_INET6 +static struct hostmap *ipf_nat6_hostmap __P((ipf_nat_softc_t *, ipnat_t *, + i6addr_t *, i6addr_t *, + i6addr_t *, u_32_t)); +static int ipf_nat6_match __P((fr_info_t *, ipnat_t *)); +static void ipf_nat6_tabmove __P((ipf_nat_softc_t *, nat_t *)); +static int ipf_nat6_decap __P((fr_info_t *, nat_t *)); +static int ipf_nat6_nextaddr __P((fr_info_t *, nat_addr_t *, i6addr_t *, + i6addr_t *)); +static int ipf_nat6_icmpquerytype __P((int)); +static int ipf_nat6_out __P((fr_info_t *, nat_t *, int, u_32_t)); +static int ipf_nat6_in __P((fr_info_t *, nat_t *, int, u_32_t)); +static int ipf_nat6_builddivertmp __P((ipf_nat_softc_t *, ipnat_t *)); +static int ipf_nat6_nextaddrinit __P((ipf_main_softc_t *, char *, + nat_addr_t *, int, void *)); +static int ipf_nat6_insert __P((ipf_main_softc_t *, ipf_nat_softc_t *, + nat_t *)); + + +#define NINCLSIDE6(y,x) ATOMIC_INCL(softn->ipf_nat_stats.ns_side6[y].x) +#define NBUMPSIDE(y,x) softn->ipf_nat_stats.ns_side[y].x++ +#define NBUMPSIDE6(y,x) softn->ipf_nat_stats.ns_side6[y].x++ +#define NBUMPSIDE6D(y,x) \ + do { \ + softn->ipf_nat_stats.ns_side6[y].x++; \ + DT(x); \ + } while (0) +#define NBUMPSIDE6DX(y,x,z) \ + do { \ + softn->ipf_nat_stats.ns_side6[y].x++; \ + DT(z); \ + } while (0) + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_ruleaddrinit */ +/* Returns: int - 0 == success, else failure */ +/* Parameters: in(I) - NAT rule that requires address fields to be init'd */ +/* */ +/* For each of the source/destination address fields in a NAT rule, call */ +/* ipf_nat6_nextaddrinit() to prepare the structure for active duty. Other */ +/* IPv6 specific actions can also be taken care of here. */ +/* ------------------------------------------------------------------------ */ +int +ipf_nat6_ruleaddrinit(softc, softn, n) + ipf_main_softc_t *softc; + ipf_nat_softc_t *softn; + ipnat_t *n; +{ + int idx, error; + + if (n->in_redir == NAT_BIMAP) { + n->in_ndstip6 = n->in_osrcip6; + n->in_ndstmsk6 = n->in_osrcmsk6; + n->in_odstip6 = n->in_nsrcip6; + n->in_odstmsk6 = n->in_nsrcmsk6; + + } + + if (n->in_redir & NAT_REDIRECT) + idx = 1; + else + idx = 0; + /* + * Initialise all of the address fields. + */ + error = ipf_nat6_nextaddrinit(softc, n->in_names, &n->in_osrc, 1, + n->in_ifps[idx]); + if (error != 0) + return error; + + error = ipf_nat6_nextaddrinit(softc, n->in_names, &n->in_odst, 1, + n->in_ifps[idx]); + if (error != 0) + return error; + + error = ipf_nat6_nextaddrinit(softc, n->in_names, &n->in_nsrc, 1, + n->in_ifps[idx]); + if (error != 0) + return error; + + error = ipf_nat6_nextaddrinit(softc, n->in_names, &n->in_ndst, 1, + n->in_ifps[idx]); + if (error != 0) + return error; + + if (n->in_redir & NAT_DIVERTUDP) + ipf_nat6_builddivertmp(softn, n); + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_addrdr */ +/* Returns: Nil */ +/* Parameters: n(I) - pointer to NAT rule to add */ +/* */ +/* Adds a redirect rule to the hash table of redirect rules and the list of */ +/* loaded NAT rules. Updates the bitmask indicating which netmasks are in */ +/* use by redirect rules. */ +/* ------------------------------------------------------------------------ */ +void +ipf_nat6_addrdr(softn, n) + ipf_nat_softc_t *softn; + ipnat_t *n; +{ + i6addr_t *mask; + ipnat_t **np; + i6addr_t j; + u_int hv; + int k; + + if ((n->in_redir & NAT_BIMAP) == NAT_BIMAP) { + k = count6bits(n->in_nsrcmsk6.i6); + mask = &n->in_nsrcmsk6; + IP6_AND(&n->in_odstip6, &n->in_odstmsk6, &j); + hv = NAT_HASH_FN6(&j, 0, softn->ipf_nat_rdrrules_sz); + + } else if (n->in_odstatype == FRI_NORMAL) { + k = count6bits(n->in_odstmsk6.i6); + mask = &n->in_odstmsk6; + IP6_AND(&n->in_odstip6, &n->in_odstmsk6, &j); + hv = NAT_HASH_FN6(&j, 0, softn->ipf_nat_rdrrules_sz); + } else { + k = 0; + hv = 0; + mask = NULL; + } + ipf_inet6_mask_add(k, mask, &softn->ipf_nat6_rdr_mask); + + np = softn->ipf_nat_rdr_rules + hv; + while (*np != NULL) + np = &(*np)->in_rnext; + n->in_rnext = NULL; + n->in_prnext = np; + n->in_hv[0] = hv; + n->in_use++; + *np = n; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_addmap */ +/* Returns: Nil */ +/* Parameters: n(I) - pointer to NAT rule to add */ +/* */ +/* Adds a NAT map rule to the hash table of rules and the list of loaded */ +/* NAT rules. Updates the bitmask indicating which netmasks are in use by */ +/* redirect rules. */ +/* ------------------------------------------------------------------------ */ +void +ipf_nat6_addmap(softn, n) + ipf_nat_softc_t *softn; + ipnat_t *n; +{ + i6addr_t *mask; + ipnat_t **np; + i6addr_t j; + u_int hv; + int k; + + if (n->in_osrcatype == FRI_NORMAL) { + k = count6bits(n->in_osrcmsk6.i6); + mask = &n->in_osrcmsk6; + IP6_AND(&n->in_osrcip6, &n->in_osrcmsk6, &j); + hv = NAT_HASH_FN6(&j, 0, softn->ipf_nat_maprules_sz); + } else { + k = 0; + hv = 0; + mask = NULL; + } + ipf_inet6_mask_add(k, mask, &softn->ipf_nat6_map_mask); + + np = softn->ipf_nat_map_rules + hv; + while (*np != NULL) + np = &(*np)->in_mnext; + n->in_mnext = NULL; + n->in_pmnext = np; + n->in_hv[1] = hv; + n->in_use++; + *np = n; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_del_rdr */ +/* Returns: Nil */ +/* Parameters: n(I) - pointer to NAT rule to delete */ +/* */ +/* Removes a NAT rdr rule from the hash table of NAT rdr rules. */ +/* ------------------------------------------------------------------------ */ +void +ipf_nat6_delrdr(softn, n) + ipf_nat_softc_t *softn; + ipnat_t *n; +{ + i6addr_t *mask; + int k; + + if ((n->in_redir & NAT_BIMAP) == NAT_BIMAP) { + k = count6bits(n->in_nsrcmsk6.i6); + mask = &n->in_nsrcmsk6; + } else if (n->in_odstatype == FRI_NORMAL) { + k = count6bits(n->in_odstmsk6.i6); + mask = &n->in_odstmsk6; + } else { + k = 0; + mask = NULL; + } + ipf_inet6_mask_del(k, mask, &softn->ipf_nat6_rdr_mask); + + if (n->in_rnext != NULL) + n->in_rnext->in_prnext = n->in_prnext; + *n->in_prnext = n->in_rnext; + n->in_use--; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_delmap */ +/* Returns: Nil */ +/* Parameters: n(I) - pointer to NAT rule to delete */ +/* */ +/* Removes a NAT map rule from the hash table of NAT map rules. */ +/* ------------------------------------------------------------------------ */ +void +ipf_nat6_delmap(softn, n) + ipf_nat_softc_t *softn; + ipnat_t *n; +{ + i6addr_t *mask; + int k; + + if (n->in_osrcatype == FRI_NORMAL) { + k = count6bits(n->in_osrcmsk6.i6); + mask = &n->in_osrcmsk6; + } else { + k = 0; + mask = NULL; + } + ipf_inet6_mask_del(k, mask, &softn->ipf_nat6_map_mask); + + if (n->in_mnext != NULL) + n->in_mnext->in_pmnext = n->in_pmnext; + *n->in_pmnext = n->in_mnext; + n->in_use--; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_hostmap */ +/* Returns: struct hostmap* - NULL if no hostmap could be created, */ +/* else a pointer to the hostmapping to use */ +/* Parameters: np(I) - pointer to NAT rule */ +/* real(I) - real IP address */ +/* map(I) - mapped IP address */ +/* port(I) - destination port number */ +/* Write Locks: ipf_nat */ +/* */ +/* Check if an ip address has already been allocated for a given mapping */ +/* that is not doing port based translation. If is not yet allocated, then */ +/* create a new entry if a non-NULL NAT rule pointer has been supplied. */ +/* ------------------------------------------------------------------------ */ +static struct hostmap * +ipf_nat6_hostmap(softn, np, src, dst, map, port) + ipf_nat_softc_t *softn; + ipnat_t *np; + i6addr_t *src, *dst, *map; + u_32_t port; +{ + hostmap_t *hm; + u_int hv; + + hv = (src->i6[3] ^ dst->i6[3]); + hv += (src->i6[2] ^ dst->i6[2]); + hv += (src->i6[1] ^ dst->i6[1]); + hv += (src->i6[0] ^ dst->i6[0]); + hv += src->i6[3]; + hv += src->i6[2]; + hv += src->i6[1]; + hv += src->i6[0]; + hv += dst->i6[3]; + hv += dst->i6[2]; + hv += dst->i6[1]; + hv += dst->i6[0]; + hv %= HOSTMAP_SIZE; + for (hm = softn->ipf_hm_maptable[hv]; hm; hm = hm->hm_next) + if (IP6_EQ(&hm->hm_osrc6, src) && + IP6_EQ(&hm->hm_odst6, dst) && + ((np == NULL) || (np == hm->hm_ipnat)) && + ((port == 0) || (port == hm->hm_port))) { + softn->ipf_nat_stats.ns_hm_addref++; + hm->hm_ref++; + return hm; + } + + if (np == NULL) { + softn->ipf_nat_stats.ns_hm_nullnp++; + return NULL; + } + + KMALLOC(hm, hostmap_t *); + if (hm) { + hm->hm_next = softn->ipf_hm_maplist; + hm->hm_pnext = &softn->ipf_hm_maplist; + if (softn->ipf_hm_maplist != NULL) + softn->ipf_hm_maplist->hm_pnext = &hm->hm_next; + softn->ipf_hm_maplist = hm; + hm->hm_hnext = softn->ipf_hm_maptable[hv]; + hm->hm_phnext = softn->ipf_hm_maptable + hv; + if (softn->ipf_hm_maptable[hv] != NULL) + softn->ipf_hm_maptable[hv]->hm_phnext = &hm->hm_hnext; + softn->ipf_hm_maptable[hv] = hm; + hm->hm_ipnat = np; + np->in_use++; + hm->hm_osrcip6 = *src; + hm->hm_odstip6 = *dst; + hm->hm_nsrcip6 = *map; + hm->hm_ndstip6.i6[0] = 0; + hm->hm_ndstip6.i6[1] = 0; + hm->hm_ndstip6.i6[2] = 0; + hm->hm_ndstip6.i6[3] = 0; + hm->hm_ref = 1; + hm->hm_port = port; + hm->hm_hv = hv; + hm->hm_v = 6; + softn->ipf_nat_stats.ns_hm_new++; + } else { + softn->ipf_nat_stats.ns_hm_newfail++; + } + return hm; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_newmap */ +/* Returns: int - -1 == error, 0 == success */ +/* Parameters: fin(I) - pointer to packet information */ +/* nat(I) - pointer to NAT entry */ +/* ni(I) - pointer to structure with misc. information needed */ +/* to create new NAT entry. */ +/* */ +/* Given an empty NAT structure, populate it with new information about a */ +/* new NAT session, as defined by the matching NAT rule. */ +/* ni.nai_ip is passed in uninitialised and must be set, in host byte order,*/ +/* to the new IP address for the translation. */ +/* ------------------------------------------------------------------------ */ +int +ipf_nat6_newmap(fin, nat, ni) + fr_info_t *fin; + nat_t *nat; + natinfo_t *ni; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + u_short st_port, dport, sport, port, sp, dp; + i6addr_t in, st_ip; + hostmap_t *hm; + u_32_t flags; + ipnat_t *np; + nat_t *natl; + int l; + + /* + * If it's an outbound packet which doesn't match any existing + * record, then create a new port + */ + l = 0; + hm = NULL; + np = ni->nai_np; + st_ip = np->in_snip6; + st_port = np->in_spnext; + flags = nat->nat_flags; + + if (flags & IPN_ICMPQUERY) { + sport = fin->fin_data[1]; + dport = 0; + } else { + sport = htons(fin->fin_data[0]); + dport = htons(fin->fin_data[1]); + } + + /* + * Do a loop until we either run out of entries to try or we find + * a NAT mapping that isn't currently being used. This is done + * because the change to the source is not (usually) being fixed. + */ + do { + port = 0; + in = np->in_nsrc.na_nextaddr; + if (l == 0) { + /* + * Check to see if there is an existing NAT + * setup for this IP address pair. + */ + hm = ipf_nat6_hostmap(softn, np, &fin->fin_src6, + &fin->fin_dst6, &in, 0); + if (hm != NULL) + in = hm->hm_nsrcip6; + } else if ((l == 1) && (hm != NULL)) { + ipf_nat_hostmapdel(softc, &hm); + } + + nat->nat_hm = hm; + + if (IP6_ISONES(&np->in_nsrcmsk6) && (np->in_spnext == 0)) { + if (l > 0) { + NBUMPSIDE6DX(1, ns_exhausted, ns_exhausted_1); + return -1; + } + } + + if ((np->in_redir == NAT_BIMAP) && + IP6_EQ(&np->in_osrcmsk6, &np->in_nsrcmsk6)) { + i6addr_t temp; + /* + * map the address block in a 1:1 fashion + */ + temp.i6[0] = fin->fin_src6.i6[0] & + ~np->in_osrcmsk6.i6[0]; + temp.i6[1] = fin->fin_src6.i6[1] & + ~np->in_osrcmsk6.i6[1]; + temp.i6[2] = fin->fin_src6.i6[2] & + ~np->in_osrcmsk6.i6[0]; + temp.i6[3] = fin->fin_src6.i6[3] & + ~np->in_osrcmsk6.i6[3]; + in = np->in_nsrcip6; + IP6_MERGE(&in, &temp, &np->in_osrc); + +#ifdef NEED_128BIT_MATH + } else if (np->in_redir & NAT_MAPBLK) { + if ((l >= np->in_ppip) || ((l > 0) && + !(flags & IPN_TCPUDP))) { + NBUMPSIDE6DX(1, ns_exhausted, ns_exhausted_2); + return -1; + } + /* + * map-block - Calculate destination address. + */ + IP6_MASK(&in, &fin->fin_src6, &np->in_osrcmsk6); + in = ntohl(in); + inb = in; + in.s_addr /= np->in_ippip; + in.s_addr &= ntohl(~np->in_nsrcmsk6); + in.s_addr += ntohl(np->in_nsrcaddr6); + /* + * Calculate destination port. + */ + if ((flags & IPN_TCPUDP) && + (np->in_ppip != 0)) { + port = ntohs(sport) + l; + port %= np->in_ppip; + port += np->in_ppip * + (inb.s_addr % np->in_ippip); + port += MAPBLK_MINPORT; + port = htons(port); + } +#endif + + } else if (IP6_ISZERO(&np->in_nsrcaddr) && + IP6_ISONES(&np->in_nsrcmsk)) { + /* + * 0/32 - use the interface's IP address. + */ + if ((l > 0) || + ipf_ifpaddr(softc, 6, FRI_NORMAL, fin->fin_ifp, + &in, NULL) == -1) { + NBUMPSIDE6DX(1, ns_new_ifpaddr, + ns_new_ifpaddr_1); + return -1; + } + + } else if (IP6_ISZERO(&np->in_nsrcip6) && + IP6_ISZERO(&np->in_nsrcmsk6)) { + /* + * 0/0 - use the original source address/port. + */ + if (l > 0) { + NBUMPSIDE6DX(1, ns_exhausted, ns_exhausted_3); + return -1; + } + in = fin->fin_src6; + + } else if (!IP6_ISONES(&np->in_nsrcmsk6) && + (np->in_spnext == 0) && ((l > 0) || (hm == NULL))) { + IP6_INC(&np->in_snip6); + } + + natl = NULL; + + if ((flags & IPN_TCPUDP) && + ((np->in_redir & NAT_MAPBLK) == 0) && + (np->in_flags & IPN_AUTOPORTMAP)) { +#ifdef NEED_128BIT_MATH + /* + * "ports auto" (without map-block) + */ + if ((l > 0) && (l % np->in_ppip == 0)) { + if ((l > np->in_ppip) && + !IP6_ISONES(&np->in_nsrcmsk)) { + IP6_INC(&np->in_snip6) + } + } + if (np->in_ppip != 0) { + port = ntohs(sport); + port += (l % np->in_ppip); + port %= np->in_ppip; + port += np->in_ppip * + (ntohl(fin->fin_src6) % + np->in_ippip); + port += MAPBLK_MINPORT; + port = htons(port); + } +#endif + + } else if (((np->in_redir & NAT_MAPBLK) == 0) && + (flags & IPN_TCPUDPICMP) && (np->in_spnext != 0)) { + /* + * Standard port translation. Select next port. + */ + if (np->in_flags & IPN_SEQUENTIAL) { + port = np->in_spnext; + } else { + port = ipf_random() % (np->in_spmax - + np->in_spmin + 1); + port += np->in_spmin; + } + port = htons(port); + np->in_spnext++; + + if (np->in_spnext > np->in_spmax) { + np->in_spnext = np->in_spmin; + if (!IP6_ISONES(&np->in_nsrcmsk6)) { + IP6_INC(&np->in_snip6); + } + } + } + + if (np->in_flags & IPN_SIPRANGE) { + if (IP6_GT(&np->in_snip, &np->in_nsrcmsk)) + np->in_snip6 = np->in_nsrcip6; + } else { + i6addr_t a1, a2; + + a1 = np->in_snip6; + IP6_INC(&a1); + IP6_AND(&a1, &np->in_nsrcmsk6, &a2); + + if (!IP6_ISONES(&np->in_nsrcmsk6) && + IP6_GT(&a2, &np->in_nsrcip6)) { + IP6_ADD(&np->in_nsrcip6, 1, &np->in_snip6); + } + } + + if ((port == 0) && (flags & (IPN_TCPUDPICMP|IPN_ICMPQUERY))) + port = sport; + + /* + * Here we do a lookup of the connection as seen from + * the outside. If an IP# pair already exists, try + * again. So if you have A->B becomes C->B, you can + * also have D->E become C->E but not D->B causing + * another C->B. Also take protocol and ports into + * account when determining whether a pre-existing + * NAT setup will cause an external conflict where + * this is appropriate. + */ + sp = fin->fin_data[0]; + dp = fin->fin_data[1]; + fin->fin_data[0] = fin->fin_data[1]; + fin->fin_data[1] = ntohs(port); + natl = ipf_nat6_inlookup(fin, flags & ~(SI_WILDP|NAT_SEARCH), + (u_int)fin->fin_p, &fin->fin_dst6.in6, + &in.in6); + fin->fin_data[0] = sp; + fin->fin_data[1] = dp; + + /* + * Has the search wrapped around and come back to the + * start ? + */ + if ((natl != NULL) && + (np->in_spnext != 0) && (st_port == np->in_spnext) && + (!IP6_ISZERO(&np->in_snip6) && + IP6_EQ(&st_ip, &np->in_snip6))) { + NBUMPSIDE6D(1, ns_wrap); + return -1; + } + l++; + } while (natl != NULL); + + /* Setup the NAT table */ + nat->nat_osrc6 = fin->fin_src6; + nat->nat_nsrc6 = in; + nat->nat_odst6 = fin->fin_dst6; + nat->nat_ndst6 = fin->fin_dst6; + if (nat->nat_hm == NULL) + nat->nat_hm = ipf_nat6_hostmap(softn, np, &fin->fin_src6, + &fin->fin_dst6, + &nat->nat_nsrc6, 0); + + if (flags & IPN_TCPUDP) { + nat->nat_osport = sport; + nat->nat_nsport = port; /* sport */ + nat->nat_odport = dport; + nat->nat_ndport = dport; + ((tcphdr_t *)fin->fin_dp)->th_sport = port; + } else if (flags & IPN_ICMPQUERY) { + nat->nat_oicmpid = fin->fin_data[1]; + ((struct icmp6_hdr *)fin->fin_dp)->icmp6_id = port; + nat->nat_nicmpid = port; + } + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_newrdr */ +/* Returns: int - -1 == error, 0 == success (no move), 1 == success and */ +/* allow rule to be moved if IPN_ROUNDR is set. */ +/* Parameters: fin(I) - pointer to packet information */ +/* nat(I) - pointer to NAT entry */ +/* ni(I) - pointer to structure with misc. information needed */ +/* to create new NAT entry. */ +/* */ +/* ni.nai_ip is passed in uninitialised and must be set, in host byte order,*/ +/* to the new IP address for the translation. */ +/* ------------------------------------------------------------------------ */ +int +ipf_nat6_newrdr(fin, nat, ni) + fr_info_t *fin; + nat_t *nat; + natinfo_t *ni; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + u_short nport, dport, sport; + u_short sp, dp; + hostmap_t *hm; + u_32_t flags; + i6addr_t in; + ipnat_t *np; + nat_t *natl; + int move; + + move = 1; + hm = NULL; + in.i6[0] = 0; + in.i6[1] = 0; + in.i6[2] = 0; + in.i6[3] = 0; + np = ni->nai_np; + flags = nat->nat_flags; + + if (flags & IPN_ICMPQUERY) { + dport = fin->fin_data[1]; + sport = 0; + } else { + sport = htons(fin->fin_data[0]); + dport = htons(fin->fin_data[1]); + } + + /* TRACE sport, dport */ + + + /* + * If the matching rule has IPN_STICKY set, then we want to have the + * same rule kick in as before. Why would this happen? If you have + * a collection of rdr rules with "round-robin sticky", the current + * packet might match a different one to the previous connection but + * we want the same destination to be used. + */ + if (((np->in_flags & (IPN_ROUNDR|IPN_SPLIT)) != 0) && + ((np->in_flags & IPN_STICKY) != 0)) { + hm = ipf_nat6_hostmap(softn, NULL, &fin->fin_src6, + &fin->fin_dst6, &in, (u_32_t)dport); + if (hm != NULL) { + in = hm->hm_ndstip6; + np = hm->hm_ipnat; + ni->nai_np = np; + move = 0; + } + } + + /* + * Otherwise, it's an inbound packet. Most likely, we don't + * want to rewrite source ports and source addresses. Instead, + * we want to rewrite to a fixed internal address and fixed + * internal port. + */ + if (np->in_flags & IPN_SPLIT) { + in = np->in_dnip6; + + if ((np->in_flags & (IPN_ROUNDR|IPN_STICKY)) == IPN_STICKY) { + hm = ipf_nat6_hostmap(softn, NULL, &fin->fin_src6, + &fin->fin_dst6, &in, + (u_32_t)dport); + if (hm != NULL) { + in = hm->hm_ndstip6; + move = 0; + } + } + + if (hm == NULL || hm->hm_ref == 1) { + if (IP6_EQ(&np->in_ndstip6, &in)) { + np->in_dnip6 = np->in_ndstmsk6; + move = 0; + } else { + np->in_dnip6 = np->in_ndstip6; + } + } + + } else if (IP6_ISZERO(&np->in_ndstaddr) && + IP6_ISONES(&np->in_ndstmsk)) { + /* + * 0/32 - use the interface's IP address. + */ + if (ipf_ifpaddr(softc, 6, FRI_NORMAL, fin->fin_ifp, + &in, NULL) == -1) { + NBUMPSIDE6DX(0, ns_new_ifpaddr, ns_new_ifpaddr_2); + return -1; + } + + } else if (IP6_ISZERO(&np->in_ndstip6) && + IP6_ISZERO(&np->in_ndstmsk6)) { + /* + * 0/0 - use the original destination address/port. + */ + in = fin->fin_dst6; + + } else if (np->in_redir == NAT_BIMAP && + IP6_EQ(&np->in_ndstmsk6, &np->in_odstmsk6)) { + i6addr_t temp; + /* + * map the address block in a 1:1 fashion + */ + temp.i6[0] = fin->fin_dst6.i6[0] & ~np->in_osrcmsk6.i6[0]; + temp.i6[1] = fin->fin_dst6.i6[1] & ~np->in_osrcmsk6.i6[1]; + temp.i6[2] = fin->fin_dst6.i6[2] & ~np->in_osrcmsk6.i6[0]; + temp.i6[3] = fin->fin_dst6.i6[3] & ~np->in_osrcmsk6.i6[3]; + in = np->in_ndstip6; + IP6_MERGE(&in, &temp, &np->in_ndstmsk6); + } else { + in = np->in_ndstip6; + } + + if ((np->in_dpnext == 0) || ((flags & NAT_NOTRULEPORT) != 0)) + nport = dport; + else { + /* + * Whilst not optimized for the case where + * pmin == pmax, the gain is not significant. + */ + if (((np->in_flags & IPN_FIXEDDPORT) == 0) && + (np->in_odport != np->in_dtop)) { + nport = ntohs(dport) - np->in_odport + np->in_dpmax; + nport = htons(nport); + } else { + nport = htons(np->in_dpnext); + np->in_dpnext++; + if (np->in_dpnext > np->in_dpmax) + np->in_dpnext = np->in_dpmin; + } + } + + /* + * When the redirect-to address is set to 0.0.0.0, just + * assume a blank `forwarding' of the packet. We don't + * setup any translation for this either. + */ + if (IP6_ISZERO(&in)) { + if (nport == dport) { + NBUMPSIDE6D(0, ns_xlate_null); + return -1; + } + in = fin->fin_dst6; + } + + /* + * Check to see if this redirect mapping already exists and if + * it does, return "failure" (allowing it to be created will just + * cause one or both of these "connections" to stop working.) + */ + sp = fin->fin_data[0]; + dp = fin->fin_data[1]; + fin->fin_data[1] = fin->fin_data[0]; + fin->fin_data[0] = ntohs(nport); + natl = ipf_nat6_outlookup(fin, flags & ~(SI_WILDP|NAT_SEARCH), + (u_int)fin->fin_p, &in.in6, + &fin->fin_src6.in6); + fin->fin_data[0] = sp; + fin->fin_data[1] = dp; + if (natl != NULL) { + NBUMPSIDE6D(0, ns_xlate_exists); + return -1; + } + + nat->nat_ndst6 = in; + nat->nat_odst6 = fin->fin_dst6; + nat->nat_nsrc6 = fin->fin_src6; + nat->nat_osrc6 = fin->fin_src6; + if ((nat->nat_hm == NULL) && ((np->in_flags & IPN_STICKY) != 0)) + nat->nat_hm = ipf_nat6_hostmap(softn, np, &fin->fin_src6, + &fin->fin_dst6, &in, + (u_32_t)dport); + + if (flags & IPN_TCPUDP) { + nat->nat_odport = dport; + nat->nat_ndport = nport; + nat->nat_osport = sport; + nat->nat_nsport = sport; + ((tcphdr_t *)fin->fin_dp)->th_dport = nport; + } else if (flags & IPN_ICMPQUERY) { + nat->nat_oicmpid = fin->fin_data[1]; + ((struct icmp6_hdr *)fin->fin_dp)->icmp6_id = nport; + nat->nat_nicmpid = nport; + } + + return move; +} + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_add */ +/* Returns: nat6_t* - NULL == failure to create new NAT structure, */ +/* else pointer to new NAT structure */ +/* Parameters: fin(I) - pointer to packet information */ +/* np(I) - pointer to NAT rule */ +/* natsave(I) - pointer to where to store NAT struct pointer */ +/* flags(I) - flags describing the current packet */ +/* direction(I) - direction of packet (in/out) */ +/* Write Lock: ipf_nat */ +/* */ +/* Attempts to create a new NAT entry. Does not actually change the packet */ +/* in any way. */ +/* */ +/* This fucntion is in three main parts: (1) deal with creating a new NAT */ +/* structure for a "MAP" rule (outgoing NAT translation); (2) deal with */ +/* creating a new NAT structure for a "RDR" rule (incoming NAT translation) */ +/* and (3) building that structure and putting it into the NAT table(s). */ +/* */ +/* NOTE: natsave should NOT be used top point back to an ipstate_t struct */ +/* as it can result in memory being corrupted. */ +/* ------------------------------------------------------------------------ */ +nat_t * +ipf_nat6_add(fin, np, natsave, flags, direction) + fr_info_t *fin; + ipnat_t *np; + nat_t **natsave; + u_int flags; + int direction; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + hostmap_t *hm = NULL; + nat_t *nat, *natl; + natstat_t *nsp; + u_int nflags; + natinfo_t ni; + int move; +#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) && defined(ICK_M_CTL_MAGIC) + qpktinfo_t *qpi = fin->fin_qpi; +#endif + + nsp = &softn->ipf_nat_stats; + + if ((nsp->ns_active * 100 / softn->ipf_nat_table_max) > + softn->ipf_nat_table_wm_high) { + softn->ipf_nat_doflush = 1; + } + + if (nsp->ns_active >= softn->ipf_nat_table_max) { + NBUMPSIDE6(fin->fin_out, ns_table_max); + return NULL; + } + + move = 1; + nflags = np->in_flags & flags; + nflags &= NAT_FROMRULE; + + ni.nai_np = np; + ni.nai_dport = 0; + ni.nai_sport = 0; + + /* Give me a new nat */ + KMALLOC(nat, nat_t *); + if (nat == NULL) { + NBUMPSIDE6(fin->fin_out, ns_memfail); + /* + * Try to automatically tune the max # of entries in the + * table allowed to be less than what will cause kmem_alloc() + * to fail and try to eliminate panics due to out of memory + * conditions arising. + */ + if ((softn->ipf_nat_table_max > softn->ipf_nat_table_sz) && + (nsp->ns_active > 100)) { + softn->ipf_nat_table_max = nsp->ns_active - 100; + printf("table_max reduced to %d\n", + softn->ipf_nat_table_max); + } + return NULL; + } + + if (flags & IPN_ICMPQUERY) { + /* + * In the ICMP query NAT code, we translate the ICMP id fields + * to make them unique. This is indepedent of the ICMP type + * (e.g. in the unlikely event that a host sends an echo and + * an tstamp request with the same id, both packets will have + * their ip address/id field changed in the same way). + */ + /* The icmp6_id field is used by the sender to identify the + * process making the icmp request. (the receiver justs + * copies it back in its response). So, it closely matches + * the concept of source port. We overlay sport, so we can + * maximally reuse the existing code. + */ + ni.nai_sport = fin->fin_data[1]; + ni.nai_dport = 0; + } + + bzero((char *)nat, sizeof(*nat)); + nat->nat_flags = flags; + nat->nat_redir = np->in_redir; + nat->nat_dir = direction; + nat->nat_pr[0] = fin->fin_p; + nat->nat_pr[1] = fin->fin_p; + + /* + * Search the current table for a match and create a new mapping + * if there is none found. + */ + if (np->in_redir & NAT_DIVERTUDP) { + move = ipf_nat6_newdivert(fin, nat, &ni); + + } else if (np->in_redir & NAT_REWRITE) { + move = ipf_nat6_newrewrite(fin, nat, &ni); + + } else if (direction == NAT_OUTBOUND) { + /* + * We can now arrange to call this for the same connection + * because ipf_nat6_new doesn't protect the code path into + * this function. + */ + natl = ipf_nat6_outlookup(fin, nflags, (u_int)fin->fin_p, + &fin->fin_src6.in6, + &fin->fin_dst6.in6); + if (natl != NULL) { + KFREE(nat); + nat = natl; + goto done; + } + + move = ipf_nat6_newmap(fin, nat, &ni); + } else { + /* + * NAT_INBOUND is used for redirects rules + */ + natl = ipf_nat6_inlookup(fin, nflags, (u_int)fin->fin_p, + &fin->fin_src6.in6, + &fin->fin_dst6.in6); + if (natl != NULL) { + KFREE(nat); + nat = natl; + goto done; + } + + move = ipf_nat6_newrdr(fin, nat, &ni); + } + if (move == -1) + goto badnat; + + np = ni.nai_np; + + nat->nat_mssclamp = np->in_mssclamp; + nat->nat_me = natsave; + nat->nat_fr = fin->fin_fr; + nat->nat_rev = fin->fin_rev; + nat->nat_ptr = np; + nat->nat_dlocal = np->in_dlocal; + + if ((np->in_apr != NULL) && ((nat->nat_flags & NAT_SLAVE) == 0)) { + if (ipf_proxy_new(fin, nat) == -1) { + NBUMPSIDE6D(fin->fin_out, ns_appr_fail); + goto badnat; + } + } + + nat->nat_ifps[0] = np->in_ifps[0]; + if (np->in_ifps[0] != NULL) { + COPYIFNAME(np->in_v[0], np->in_ifps[0], nat->nat_ifnames[0]); + } + + nat->nat_ifps[1] = np->in_ifps[1]; + if (np->in_ifps[1] != NULL) { + COPYIFNAME(np->in_v[1], np->in_ifps[1], nat->nat_ifnames[1]); + } + + if (ipf_nat6_finalise(fin, nat) == -1) { + goto badnat; + } + + np->in_use++; + + if ((move == 1) && (np->in_flags & IPN_ROUNDR)) { + if ((np->in_redir & (NAT_REDIRECT|NAT_MAP)) == NAT_REDIRECT) { + ipf_nat6_delrdr(softn, np); + ipf_nat6_addrdr(softn, np); + } else if ((np->in_redir & (NAT_REDIRECT|NAT_MAP)) == NAT_MAP) { + ipf_nat6_delmap(softn, np); + ipf_nat6_addmap(softn, np); + } + } + + if (flags & SI_WILDP) + nsp->ns_wilds++; + softn->ipf_nat_stats.ns_proto[nat->nat_pr[0]]++; + + goto done; +badnat: + NBUMPSIDE6(fin->fin_out, ns_badnatnew); + if ((hm = nat->nat_hm) != NULL) + ipf_nat_hostmapdel(softc, &hm); + KFREE(nat); + nat = NULL; +done: + if (nat != NULL && np != NULL) + np->in_hits++; + if (natsave != NULL) + *natsave = nat; + return nat; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_finalise */ +/* Returns: int - 0 == sucess, -1 == failure */ +/* Parameters: fin(I) - pointer to packet information */ +/* nat(I) - pointer to NAT entry */ +/* Write Lock: ipf_nat */ +/* */ +/* This is the tail end of constructing a new NAT entry and is the same */ +/* for both IPv4 and IPv6. */ +/* ------------------------------------------------------------------------ */ +/*ARGSUSED*/ +int +ipf_nat6_finalise(fin, nat) + fr_info_t *fin; + nat_t *nat; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + u_32_t sum1, sum2, sumd; + frentry_t *fr; + u_32_t flags; + + flags = nat->nat_flags; + + switch (fin->fin_p) + { + case IPPROTO_ICMPV6 : + sum1 = LONG_SUM6(&nat->nat_osrc6); + sum1 += ntohs(nat->nat_oicmpid); + sum2 = LONG_SUM6(&nat->nat_nsrc6); + sum2 += ntohs(nat->nat_nicmpid); + CALC_SUMD(sum1, sum2, sumd); + nat->nat_sumd[0] = (sumd & 0xffff) + (sumd >> 16); + + sum1 = LONG_SUM6(&nat->nat_odst6); + sum2 = LONG_SUM6(&nat->nat_ndst6); + CALC_SUMD(sum1, sum2, sumd); + nat->nat_sumd[0] += (sumd & 0xffff) + (sumd >> 16); + break; + + case IPPROTO_TCP : + case IPPROTO_UDP : + sum1 = LONG_SUM6(&nat->nat_osrc6); + sum1 += ntohs(nat->nat_osport); + sum2 = LONG_SUM6(&nat->nat_nsrc6); + sum2 += ntohs(nat->nat_nsport); + CALC_SUMD(sum1, sum2, sumd); + nat->nat_sumd[0] = (sumd & 0xffff) + (sumd >> 16); + + sum1 = LONG_SUM6(&nat->nat_odst6); + sum1 += ntohs(nat->nat_odport); + sum2 = LONG_SUM6(&nat->nat_ndst6); + sum2 += ntohs(nat->nat_ndport); + CALC_SUMD(sum1, sum2, sumd); + nat->nat_sumd[0] += (sumd & 0xffff) + (sumd >> 16); + break; + + default : + sum1 = LONG_SUM6(&nat->nat_osrc6); + sum2 = LONG_SUM6(&nat->nat_nsrc6); + CALC_SUMD(sum1, sum2, sumd); + nat->nat_sumd[0] = (sumd & 0xffff) + (sumd >> 16); + + sum1 = LONG_SUM6(&nat->nat_odst6); + sum2 = LONG_SUM6(&nat->nat_ndst6); + CALC_SUMD(sum1, sum2, sumd); + nat->nat_sumd[0] += (sumd & 0xffff) + (sumd >> 16); + break; + } + + /* + * Compute the partial checksum, just in case. + * This is only ever placed into outbound packets so care needs + * to be taken over which pair of addresses are used. + */ + if (nat->nat_dir == NAT_OUTBOUND) { + sum1 = LONG_SUM6(&nat->nat_nsrc6); + sum1 += LONG_SUM6(&nat->nat_ndst6); + } else { + sum1 = LONG_SUM6(&nat->nat_osrc6); + sum1 += LONG_SUM6(&nat->nat_odst6); + } + sum1 += nat->nat_pr[1]; + nat->nat_sumd[1] = (sum1 & 0xffff) + (sum1 >> 16); + + if ((nat->nat_flags & SI_CLONE) == 0) + nat->nat_sync = ipf_sync_new(softc, SMC_NAT, fin, nat); + + if ((nat->nat_ifps[0] != NULL) && (nat->nat_ifps[0] != (void *)-1)) { + nat->nat_mtu[0] = GETIFMTU_6(nat->nat_ifps[0]); + } + + if ((nat->nat_ifps[1] != NULL) && (nat->nat_ifps[1] != (void *)-1)) { + nat->nat_mtu[1] = GETIFMTU_6(nat->nat_ifps[1]); + } + + nat->nat_v[0] = 6; + nat->nat_v[1] = 6; + + if (ipf_nat6_insert(softc, softn, nat) == 0) { + if (softn->ipf_nat_logging) + ipf_nat_log(softc, softn, nat, NL_NEW); + fr = nat->nat_fr; + if (fr != NULL) { + MUTEX_ENTER(&fr->fr_lock); + fr->fr_ref++; + MUTEX_EXIT(&fr->fr_lock); + } + return 0; + } + + NBUMPSIDE6D(fin->fin_out, ns_unfinalised); + /* + * nat6_insert failed, so cleanup time... + */ + if (nat->nat_sync != NULL) + ipf_sync_del_nat(softc->ipf_sync_soft, nat->nat_sync); + return -1; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_insert */ +/* Returns: int - 0 == sucess, -1 == failure */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* softn(I) - pointer to NAT context structure */ +/* nat(I) - pointer to NAT structure */ +/* Write Lock: ipf_nat */ +/* */ +/* Insert a NAT entry into the hash tables for searching and add it to the */ +/* list of active NAT entries. Adjust global counters when complete. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat6_insert(softc, softn, nat) + ipf_main_softc_t *softc; + ipf_nat_softc_t *softn; + nat_t *nat; +{ + u_int hv1, hv2; + u_32_t sp, dp; + ipnat_t *in; + + /* + * Try and return an error as early as possible, so calculate the hash + * entry numbers first and then proceed. + */ + if ((nat->nat_flags & (SI_W_SPORT|SI_W_DPORT)) == 0) { + if ((nat->nat_flags & IPN_TCPUDP) != 0) { + sp = nat->nat_osport; + dp = nat->nat_odport; + } else if ((nat->nat_flags & IPN_ICMPQUERY) != 0) { + sp = 0; + dp = nat->nat_oicmpid; + } else { + sp = 0; + dp = 0; + } + hv1 = NAT_HASH_FN6(&nat->nat_osrc6, sp, 0xffffffff); + hv1 = NAT_HASH_FN6(&nat->nat_odst6, hv1 + dp, + softn->ipf_nat_table_sz); + + /* + * TRACE nat6_osrc6, nat6_osport, nat6_odst6, + * nat6_odport, hv1 + */ + + if ((nat->nat_flags & IPN_TCPUDP) != 0) { + sp = nat->nat_nsport; + dp = nat->nat_ndport; + } else if ((nat->nat_flags & IPN_ICMPQUERY) != 0) { + sp = 0; + dp = nat->nat_nicmpid; + } else { + sp = 0; + dp = 0; + } + hv2 = NAT_HASH_FN6(&nat->nat_nsrc6, sp, 0xffffffff); + hv2 = NAT_HASH_FN6(&nat->nat_ndst6, hv2 + dp, + softn->ipf_nat_table_sz); + /* + * TRACE nat6_nsrcaddr, nat6_nsport, nat6_ndstaddr, + * nat6_ndport, hv1 + */ + } else { + hv1 = NAT_HASH_FN6(&nat->nat_osrc6, 0, 0xffffffff); + hv1 = NAT_HASH_FN6(&nat->nat_odst6, hv1, + softn->ipf_nat_table_sz); + /* TRACE nat6_osrcip6, nat6_odstip6, hv1 */ + + hv2 = NAT_HASH_FN6(&nat->nat_nsrc6, 0, 0xffffffff); + hv2 = NAT_HASH_FN6(&nat->nat_ndst6, hv2, + softn->ipf_nat_table_sz); + /* TRACE nat6_nsrcip6, nat6_ndstip6, hv2 */ + } + + nat->nat_hv[0] = hv1; + nat->nat_hv[1] = hv2; + + MUTEX_INIT(&nat->nat_lock, "nat entry lock"); + + in = nat->nat_ptr; + nat->nat_ref = nat->nat_me ? 2 : 1; + + nat->nat_ifnames[0][LIFNAMSIZ - 1] = '\0'; + nat->nat_ifps[0] = ipf_resolvenic(softc, nat->nat_ifnames[0], + nat->nat_v[0]); + + if (nat->nat_ifnames[1][0] != '\0') { + nat->nat_ifnames[1][LIFNAMSIZ - 1] = '\0'; + nat->nat_ifps[1] = ipf_resolvenic(softc, nat->nat_ifnames[1], + nat->nat_v[1]); + } else if (in->in_ifnames[1] != -1) { + char *name; + + name = in->in_names + in->in_ifnames[1]; + if (name[1] != '\0' && name[0] != '-' && name[0] != '*') { + (void) strncpy(nat->nat_ifnames[1], + nat->nat_ifnames[0], LIFNAMSIZ); + nat->nat_ifnames[1][LIFNAMSIZ - 1] = '\0'; + nat->nat_ifps[1] = nat->nat_ifps[0]; + } + } + if ((nat->nat_ifps[0] != NULL) && (nat->nat_ifps[0] != (void *)-1)) { + nat->nat_mtu[0] = GETIFMTU_6(nat->nat_ifps[0]); + } + if ((nat->nat_ifps[1] != NULL) && (nat->nat_ifps[1] != (void *)-1)) { + nat->nat_mtu[1] = GETIFMTU_6(nat->nat_ifps[1]); + } + + return ipf_nat_hashtab_add(softc, softn, nat); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_icmperrorlookup */ +/* Returns: nat6_t* - point to matching NAT structure */ +/* Parameters: fin(I) - pointer to packet information */ +/* dir(I) - direction of packet (in/out) */ +/* */ +/* Check if the ICMP error message is related to an existing TCP, UDP or */ +/* ICMP query nat entry. It is assumed that the packet is already of the */ +/* the required length. */ +/* ------------------------------------------------------------------------ */ +nat_t * +ipf_nat6_icmperrorlookup(fin, dir) + fr_info_t *fin; + int dir; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + struct icmp6_hdr *icmp6, *orgicmp; + int flags = 0, type, minlen; + nat_stat_side_t *nside; + tcphdr_t *tcp = NULL; + u_short data[2]; + ip6_t *oip6; + nat_t *nat; + u_int p; + + minlen = 40; + icmp6 = fin->fin_dp; + type = icmp6->icmp6_type; + nside = &softn->ipf_nat_stats.ns_side6[fin->fin_out]; + /* + * Does it at least have the return (basic) IP header ? + * Only a basic IP header (no options) should be with an ICMP error + * header. Also, if it's not an error type, then return. + */ + if (!(fin->fin_flx & FI_ICMPERR)) { + ATOMIC_INCL(nside->ns_icmp_basic); + return NULL; + } + + /* + * Check packet size + */ + if (fin->fin_plen < ICMP6ERR_IPICMPHLEN) { + ATOMIC_INCL(nside->ns_icmp_size); + return NULL; + } + oip6 = (ip6_t *)((char *)fin->fin_dp + 8); + + /* + * Is the buffer big enough for all of it ? It's the size of the IP + * header claimed in the encapsulated part which is of concern. It + * may be too big to be in this buffer but not so big that it's + * outside the ICMP packet, leading to TCP deref's causing problems. + * This is possible because we don't know how big oip_hl is when we + * do the pullup early in ipf_check() and thus can't gaurantee it is + * all here now. + */ +#ifdef ipf_nat6_KERNEL + { + mb_t *m; + + m = fin->fin_m; +# if defined(MENTAT) + if ((char *)oip6 + fin->fin_dlen - ICMPERR_ICMPHLEN > + (char *)m->b_wptr) { + ATOMIC_INCL(nside->ns_icmp_mbuf); + return NULL; + } +# else + if ((char *)oip6 + fin->fin_dlen - ICMPERR_ICMPHLEN > + (char *)fin->fin_ip + M_LEN(m)) { + ATOMIC_INCL(nside->ns_icmp_mbuf); + return NULL; + } +# endif + } +#endif + + if (IP6_NEQ(&fin->fin_dst6, &oip6->ip6_src)) { + ATOMIC_INCL(nside->ns_icmp_address); + return NULL; + } + + p = oip6->ip6_nxt; + if (p == IPPROTO_TCP) + flags = IPN_TCP; + else if (p == IPPROTO_UDP) + flags = IPN_UDP; + else if (p == IPPROTO_ICMPV6) { + orgicmp = (struct icmp6_hdr *)(oip6 + 1); + + /* see if this is related to an ICMP query */ + if (ipf_nat6_icmpquerytype(orgicmp->icmp6_type)) { + data[0] = fin->fin_data[0]; + data[1] = fin->fin_data[1]; + fin->fin_data[0] = 0; + fin->fin_data[1] = orgicmp->icmp6_id; + + flags = IPN_ICMPERR|IPN_ICMPQUERY; + /* + * NOTE : dir refers to the direction of the original + * ip packet. By definition the icmp error + * message flows in the opposite direction. + */ + if (dir == NAT_INBOUND) + nat = ipf_nat6_inlookup(fin, flags, p, + &oip6->ip6_dst, + &oip6->ip6_src); + else + nat = ipf_nat6_outlookup(fin, flags, p, + &oip6->ip6_dst, + &oip6->ip6_src); + fin->fin_data[0] = data[0]; + fin->fin_data[1] = data[1]; + return nat; + } + } + + if (flags & IPN_TCPUDP) { + minlen += 8; /* + 64bits of data to get ports */ + /* TRACE (fin,minlen) */ + if (fin->fin_plen < ICMPERR_IPICMPHLEN + minlen) { + ATOMIC_INCL(nside->ns_icmp_short); + return NULL; + } + + data[0] = fin->fin_data[0]; + data[1] = fin->fin_data[1]; + tcp = (tcphdr_t *)(oip6 + 1); + fin->fin_data[0] = ntohs(tcp->th_dport); + fin->fin_data[1] = ntohs(tcp->th_sport); + + if (dir == NAT_INBOUND) { + nat = ipf_nat6_inlookup(fin, flags, p, &oip6->ip6_dst, + &oip6->ip6_src); + } else { + nat = ipf_nat6_outlookup(fin, flags, p, &oip6->ip6_dst, + &oip6->ip6_src); + } + fin->fin_data[0] = data[0]; + fin->fin_data[1] = data[1]; + return nat; + } + if (dir == NAT_INBOUND) + nat = ipf_nat6_inlookup(fin, 0, p, &oip6->ip6_dst, + &oip6->ip6_src); + else + nat = ipf_nat6_outlookup(fin, 0, p, &oip6->ip6_dst, + &oip6->ip6_src); + + return nat; +} + + +/* result = ip1 - ip2 */ +u_32_t +ipf_nat6_ip6subtract(ip1, ip2) + i6addr_t *ip1, *ip2; +{ + i6addr_t l1, l2, d; + u_short *s1, *s2, *ds; + u_32_t r; + int i, neg; + + neg = 0; + l1 = *ip1; + l2 = *ip2; + s1 = (u_short *)&l1; + s2 = (u_short *)&l2; + ds = (u_short *)&d; + + for (i = 7; i > 0; i--) { + if (s1[i] > s2[i]) { + ds[i] = s2[i] + 0x10000 - s1[i]; + s2[i - 1] += 0x10000; + } else { + ds[i] = s2[i] - s1[i]; + } + } + if (s2[0] > s1[0]) { + ds[0] = s2[0] + 0x10000 - s1[0]; + neg = 1; + } else { + ds[0] = s2[0] - s1[0]; + } + + for (i = 0, r = 0; i < 8; i++) { + r += ds[i]; + } + + return r; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_icmperror */ +/* Returns: nat6_t* - point to matching NAT structure */ +/* Parameters: fin(I) - pointer to packet information */ +/* nflags(I) - NAT flags for this packet */ +/* dir(I) - direction of packet (in/out) */ +/* */ +/* Fix up an ICMP packet which is an error message for an existing NAT */ +/* session. This will correct both packet header data and checksums. */ +/* */ +/* This should *ONLY* be used for incoming ICMP error packets to make sure */ +/* a NAT'd ICMP packet gets correctly recognised. */ +/* ------------------------------------------------------------------------ */ +nat_t * +ipf_nat6_icmperror(fin, nflags, dir) + fr_info_t *fin; + u_int *nflags; + int dir; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + u_32_t sum1, sum2, sumd, sumd2; + i6addr_t a1, a2, a3, a4; + struct icmp6_hdr *icmp6; + int flags, dlen, odst; + u_short *csump; + tcphdr_t *tcp; + ip6_t *oip6; + nat_t *nat; + void *dp; + + if ((fin->fin_flx & (FI_SHORT|FI_FRAGBODY))) { + NBUMPSIDE6D(fin->fin_out, ns_icmp_short); + return NULL; + } + + /* + * ipf_nat6_icmperrorlookup() will return NULL for `defective' packets. + */ + if ((fin->fin_v != 6) || !(nat = ipf_nat6_icmperrorlookup(fin, dir))) { + NBUMPSIDE6D(fin->fin_out, ns_icmp_notfound); + return NULL; + } + + tcp = NULL; + csump = NULL; + flags = 0; + sumd2 = 0; + *nflags = IPN_ICMPERR; + icmp6 = fin->fin_dp; + oip6 = (ip6_t *)((u_char *)icmp6 + sizeof(*icmp6)); + dp = (u_char *)oip6 + sizeof(*oip6); + if (oip6->ip6_nxt == IPPROTO_TCP) { + tcp = (tcphdr_t *)dp; + csump = (u_short *)&tcp->th_sum; + flags = IPN_TCP; + } else if (oip6->ip6_nxt == IPPROTO_UDP) { + udphdr_t *udp; + + udp = (udphdr_t *)dp; + tcp = (tcphdr_t *)dp; + csump = (u_short *)&udp->uh_sum; + flags = IPN_UDP; + } else if (oip6->ip6_nxt == IPPROTO_ICMPV6) + flags = IPN_ICMPQUERY; + dlen = fin->fin_plen - ((char *)dp - (char *)fin->fin_ip); + + /* + * 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 as it will be modified again in ipf_nat6_checkout + * 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. + * + * 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 oip6->ip6_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. + * + * Inbound ICMP + * ------------ + * MAP rule, SRC=a,DST=b -> SRC=c,DST=b + * - response to outgoing packet (a,b)=>(c,b) (OIP_SRC=c,OIP_DST=b) + * - OIP_SRC(c)=nat6_newsrcip, OIP_DST(b)=nat6_newdstip + *=> OIP_SRC(c)=nat6_oldsrcip, OIP_DST(b)=nat6_olddstip + * + * RDR rule, SRC=a,DST=b -> SRC=a,DST=c + * - response to outgoing packet (c,a)=>(b,a) (OIP_SRC=b,OIP_DST=a) + * - OIP_SRC(b)=nat6_olddstip, OIP_DST(a)=nat6_oldsrcip + *=> OIP_SRC(b)=nat6_newdstip, OIP_DST(a)=nat6_newsrcip + * + * REWRITE out rule, SRC=a,DST=b -> SRC=c,DST=d + * - response to outgoing packet (a,b)=>(c,d) (OIP_SRC=c,OIP_DST=d) + * - OIP_SRC(c)=nat6_newsrcip, OIP_DST(d)=nat6_newdstip + *=> OIP_SRC(c)=nat6_oldsrcip, OIP_DST(d)=nat6_olddstip + * + * REWRITE in rule, SRC=a,DST=b -> SRC=c,DST=d + * - response to outgoing packet (d,c)=>(b,a) (OIP_SRC=b,OIP_DST=a) + * - OIP_SRC(b)=nat6_olddstip, OIP_DST(a)=nat6_oldsrcip + *=> OIP_SRC(b)=nat6_newdstip, OIP_DST(a)=nat6_newsrcip + * + * Outbound ICMP + * ------------- + * MAP rule, SRC=a,DST=b -> SRC=c,DST=b + * - response to incoming packet (b,c)=>(b,a) (OIP_SRC=b,OIP_DST=a) + * - OIP_SRC(b)=nat6_olddstip, OIP_DST(a)=nat6_oldsrcip + *=> OIP_SRC(b)=nat6_newdstip, OIP_DST(a)=nat6_newsrcip + * + * RDR rule, SRC=a,DST=b -> SRC=a,DST=c + * - response to incoming packet (a,b)=>(a,c) (OIP_SRC=a,OIP_DST=c) + * - OIP_SRC(a)=nat6_newsrcip, OIP_DST(c)=nat6_newdstip + *=> OIP_SRC(a)=nat6_oldsrcip, OIP_DST(c)=nat6_olddstip + * + * REWRITE out rule, SRC=a,DST=b -> SRC=c,DST=d + * - response to incoming packet (d,c)=>(b,a) (OIP_SRC=c,OIP_DST=d) + * - OIP_SRC(c)=nat6_olddstip, OIP_DST(d)=nat6_oldsrcip + *=> OIP_SRC(b)=nat6_newdstip, OIP_DST(a)=nat6_newsrcip + * + * REWRITE in rule, SRC=a,DST=b -> SRC=c,DST=d + * - response to incoming packet (a,b)=>(c,d) (OIP_SRC=b,OIP_DST=a) + * - OIP_SRC(b)=nat6_newsrcip, OIP_DST(a)=nat6_newdstip + *=> OIP_SRC(a)=nat6_oldsrcip, OIP_DST(c)=nat6_olddstip + */ + + if (((fin->fin_out == 0) && ((nat->nat_redir & NAT_MAP) != 0)) || + ((fin->fin_out == 1) && ((nat->nat_redir & NAT_REDIRECT) != 0))) { + a1 = nat->nat_osrc6; + a4.in6 = oip6->ip6_src; + a3 = nat->nat_odst6; + a2.in6 = oip6->ip6_dst; + oip6->ip6_src = a1.in6; + oip6->ip6_dst = a3.in6; + odst = 1; + } else { + a1 = nat->nat_ndst6; + a2.in6 = oip6->ip6_dst; + a3 = nat->nat_nsrc6; + a4.in6 = oip6->ip6_src; + oip6->ip6_dst = a3.in6; + oip6->ip6_src = a1.in6; + odst = 0; + } + + sumd = 0; + if (IP6_NEQ(&a3, &a2) || IP6_NEQ(&a1, &a4)) { + if (IP6_GT(&a3, &a2)) { + sumd = ipf_nat6_ip6subtract(&a2, &a3); + sumd--; + } else { + sumd = ipf_nat6_ip6subtract(&a2, &a3); + } + if (IP6_GT(&a1, &a4)) { + sumd += ipf_nat6_ip6subtract(&a4, &a1); + sumd--; + } else { + sumd += ipf_nat6_ip6subtract(&a4, &a1); + } + sumd = ~sumd; + } + + sumd2 = sumd; + sum1 = 0; + sum2 = 0; + + /* + * Fix UDP pseudo header checksum to compensate for the + * IP address change. + */ + if (((flags & IPN_TCPUDP) != 0) && (dlen >= 4)) { + u_32_t sum3, sum4; + /* + * Step 2 : + * For offending TCP/UDP IP packets, translate the ports as + * well, based on the NAT specification. Of course such + * a change may be reflected in the ICMP checksum as well. + * + * Since the port fields are part of the TCP/UDP checksum + * of the offending IP packet, you need to adjust that checksum + * as well... except that the change in the port numbers should + * be offset by the checksum change. However, the TCP/UDP + * checksum will also need to change if there has been an + * IP address change. + */ + if (odst == 1) { + sum1 = ntohs(nat->nat_osport); + sum4 = ntohs(tcp->th_sport); + sum3 = ntohs(nat->nat_odport); + sum2 = ntohs(tcp->th_dport); + + tcp->th_sport = htons(sum1); + tcp->th_dport = htons(sum3); + } else { + sum1 = ntohs(nat->nat_ndport); + sum2 = ntohs(tcp->th_dport); + sum3 = ntohs(nat->nat_nsport); + sum4 = ntohs(tcp->th_sport); + + tcp->th_dport = htons(sum3); + tcp->th_sport = htons(sum1); + } + sumd += sum1 - sum4; + sumd += sum3 - sum2; + + if (sumd != 0 || sumd2 != 0) { + /* + * At this point, sumd is the delta to apply to the + * TCP/UDP header, given the changes in both the IP + * address and the ports and sumd2 is the delta to + * apply to the ICMP header, given the IP address + * change delta that may need to be applied to the + * TCP/UDP checksum instead. + * + * If we will both the IP and TCP/UDP checksums + * then the ICMP checksum changes by the address + * delta applied to the TCP/UDP checksum. If we + * do not change the TCP/UDP checksum them we + * apply the delta in ports to the ICMP checksum. + */ + if (oip6->ip6_nxt == IPPROTO_UDP) { + if ((dlen >= 8) && (*csump != 0)) { + ipf_fix_datacksum(csump, sumd); + } else { + sumd2 = sum4 - sum1; + if (sum1 > sum4) + sumd2--; + sumd2 += sum2 - sum3; + if (sum3 > sum2) + sumd2--; + } + } else if (oip6->ip6_nxt == IPPROTO_TCP) { + if (dlen >= 18) { + ipf_fix_datacksum(csump, sumd); + } else { + sumd2 = sum4 - sum1; + if (sum1 > sum4) + sumd2--; + sumd2 += sum2 - sum3; + if (sum3 > sum2) + sumd2--; + } + } + if (sumd2 != 0) { + sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16); + sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16); + sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16); + ipf_fix_incksum(0, &icmp6->icmp6_cksum, + sumd2, 0); + } + } + } else if (((flags & IPN_ICMPQUERY) != 0) && (dlen >= 8)) { + struct icmp6_hdr *orgicmp; + + /* + * XXX - what if this is bogus hl and we go off the end ? + * In this case, ipf_nat6_icmperrorlookup() will have + * returned NULL. + */ + orgicmp = (struct icmp6_hdr *)dp; + + if (odst == 1) { + if (orgicmp->icmp6_id != nat->nat_osport) { + + /* + * Fix ICMP checksum (of the offening ICMP + * query packet) to compensate the change + * in the ICMP id of the offending ICMP + * packet. + * + * Since you modify orgicmp->icmp6_id with + * a delta (say x) and you compensate that + * in origicmp->icmp6_cksum with a delta + * minus x, you don't have to adjust the + * overall icmp->icmp6_cksum + */ + sum1 = ntohs(orgicmp->icmp6_id); + sum2 = ntohs(nat->nat_osport); + CALC_SUMD(sum1, sum2, sumd); + orgicmp->icmp6_id = nat->nat_oicmpid; + ipf_fix_datacksum(&orgicmp->icmp6_cksum, sumd); + } + } /* nat6_dir == NAT_INBOUND is impossible for icmp queries */ + } + return nat; +} + + +/* + * MAP-IN MAP-OUT RDR-IN RDR-OUT + * osrc X == src == src X + * odst X == dst == dst X + * nsrc == dst X X == dst + * ndst == src X X == src + * MAP = NAT_OUTBOUND, RDR = NAT_INBOUND + */ +/* + * NB: these lookups don't lock access to the list, it assumed that it has + * already been done! + */ +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_inlookup */ +/* Returns: nat6_t* - NULL == no match, */ +/* else pointer to matching NAT entry */ +/* Parameters: fin(I) - pointer to packet information */ +/* flags(I) - NAT flags for this packet */ +/* p(I) - protocol for this packet */ +/* src(I) - source IP address */ +/* mapdst(I) - destination IP address */ +/* */ +/* Lookup a nat entry based on the mapped destination ip address/port and */ +/* real source address/port. We use this lookup when receiving a packet, */ +/* we're looking for a table entry, based on the destination address. */ +/* */ +/* NOTE: THE PACKET BEING CHECKED (IF FOUND) HAS A MAPPING ALREADY. */ +/* */ +/* NOTE: IT IS ASSUMED THAT IS ONLY HELD WITH A READ LOCK WHEN */ +/* THIS FUNCTION IS CALLED WITH NAT_SEARCH SET IN nflags. */ +/* */ +/* flags -> relevant are IPN_UDP/IPN_TCP/IPN_ICMPQUERY that indicate if */ +/* the packet is of said protocol */ +/* ------------------------------------------------------------------------ */ +nat_t * +ipf_nat6_inlookup(fin, flags, p, src, mapdst) + fr_info_t *fin; + u_int flags, p; + struct in6_addr *src , *mapdst; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + u_short sport, dport; + grehdr_t *gre; + ipnat_t *ipn; + u_int sflags; + nat_t *nat; + int nflags; + i6addr_t dst; + void *ifp; + u_int hv; + + ifp = fin->fin_ifp; + sport = 0; + dport = 0; + gre = NULL; + dst.in6 = *mapdst; + sflags = flags & NAT_TCPUDPICMP; + + switch (p) + { + case IPPROTO_TCP : + case IPPROTO_UDP : + sport = htons(fin->fin_data[0]); + dport = htons(fin->fin_data[1]); + break; + case IPPROTO_ICMPV6 : + if (flags & IPN_ICMPERR) + sport = fin->fin_data[1]; + else + dport = fin->fin_data[1]; + break; + default : + break; + } + + + if ((flags & SI_WILDP) != 0) + goto find_in_wild_ports; + + hv = NAT_HASH_FN6(&dst, dport, 0xffffffff); + hv = NAT_HASH_FN6(src, hv + sport, softn->ipf_nat_table_sz); + nat = softn->ipf_nat_table[1][hv]; + /* TRACE dst, dport, src, sport, hv, nat */ + + for (; nat; nat = nat->nat_hnext[1]) { + if (nat->nat_ifps[0] != NULL) { + if ((ifp != NULL) && (ifp != nat->nat_ifps[0])) + continue; + } + + if (nat->nat_pr[0] != p) + continue; + + switch (nat->nat_dir) + { + case NAT_INBOUND : + if (nat->nat_v[0] != 6) + continue; + if (IP6_NEQ(&nat->nat_osrc6, src) || + IP6_NEQ(&nat->nat_odst6, &dst)) + continue; + if ((nat->nat_flags & IPN_TCPUDP) != 0) { + if (nat->nat_osport != sport) + continue; + if (nat->nat_odport != dport) + continue; + + } else if (p == IPPROTO_ICMPV6) { + if (nat->nat_osport != dport) { + continue; + } + } + break; + case NAT_OUTBOUND : + if (nat->nat_v[1] != 6) + continue; + if (IP6_NEQ(&nat->nat_ndst6, src) || + IP6_NEQ(&nat->nat_nsrc6, &dst)) + continue; + if ((nat->nat_flags & IPN_TCPUDP) != 0) { + if (nat->nat_ndport != sport) + continue; + if (nat->nat_nsport != dport) + continue; + + } else if (p == IPPROTO_ICMPV6) { + if (nat->nat_osport != dport) { + continue; + } + } + break; + } + + + if ((nat->nat_flags & IPN_TCPUDP) != 0) { + ipn = nat->nat_ptr; +#ifdef IPF_V6_PROXIES + if ((ipn != NULL) && (nat->nat_aps != NULL)) + if (appr_match(fin, nat) != 0) + continue; +#endif + } + if ((nat->nat_ifps[0] == NULL) && (ifp != NULL)) { + nat->nat_ifps[0] = ifp; + nat->nat_mtu[0] = GETIFMTU_6(ifp); + } + return nat; + } + + /* + * So if we didn't find it but there are wildcard members in the hash + * table, go back and look for them. We do this search and update here + * because it is modifying the NAT table and we want to do this only + * for the first packet that matches. The exception, of course, is + * for "dummy" (FI_IGNORE) lookups. + */ +find_in_wild_ports: + if (!(flags & NAT_TCPUDP) || !(flags & NAT_SEARCH)) { + NBUMPSIDE6DX(0, ns_lookup_miss, ns_lookup_miss_1); + return NULL; + } + if (softn->ipf_nat_stats.ns_wilds == 0 || (fin->fin_flx & FI_NOWILD)) { + NBUMPSIDE6D(0, ns_lookup_nowild); + return NULL; + } + + RWLOCK_EXIT(&softc->ipf_nat); + + hv = NAT_HASH_FN6(&dst, 0, 0xffffffff); + hv = NAT_HASH_FN6(src, hv, softn->ipf_nat_table_sz); + WRITE_ENTER(&softc->ipf_nat); + + nat = softn->ipf_nat_table[1][hv]; + /* TRACE dst, src, hv, nat */ + for (; nat; nat = nat->nat_hnext[1]) { + if (nat->nat_ifps[0] != NULL) { + if ((ifp != NULL) && (ifp != nat->nat_ifps[0])) + continue; + } + + if (nat->nat_pr[0] != fin->fin_p) + continue; + + switch (nat->nat_dir) + { + case NAT_INBOUND : + if (nat->nat_v[0] != 6) + continue; + if (IP6_NEQ(&nat->nat_osrc6, src) || + IP6_NEQ(&nat->nat_odst6, &dst)) + continue; + break; + case NAT_OUTBOUND : + if (nat->nat_v[1] != 6) + continue; + if (IP6_NEQ(&nat->nat_ndst6, src) || + IP6_NEQ(&nat->nat_nsrc6, &dst)) + continue; + break; + } + + nflags = nat->nat_flags; + if (!(nflags & (NAT_TCPUDP|SI_WILDP))) + continue; + + if (ipf_nat_wildok(nat, (int)sport, (int)dport, nflags, + NAT_INBOUND) == 1) { + if ((fin->fin_flx & FI_IGNORE) != 0) + break; + if ((nflags & SI_CLONE) != 0) { + nat = ipf_nat_clone(fin, nat); + if (nat == NULL) + break; + } else { + MUTEX_ENTER(&softn->ipf_nat_new); + softn->ipf_nat_stats.ns_wilds--; + MUTEX_EXIT(&softn->ipf_nat_new); + } + + if (nat->nat_dir == NAT_INBOUND) { + if (nat->nat_osport == 0) { + nat->nat_osport = sport; + nat->nat_nsport = sport; + } + if (nat->nat_odport == 0) { + nat->nat_odport = dport; + nat->nat_ndport = dport; + } + } else { + if (nat->nat_osport == 0) { + nat->nat_osport = dport; + nat->nat_nsport = dport; + } + if (nat->nat_odport == 0) { + nat->nat_odport = sport; + nat->nat_ndport = sport; + } + } + if ((nat->nat_ifps[0] == NULL) && (ifp != NULL)) { + nat->nat_ifps[0] = ifp; + nat->nat_mtu[0] = GETIFMTU_6(ifp); + } + nat->nat_flags &= ~(SI_W_DPORT|SI_W_SPORT); + ipf_nat6_tabmove(softn, nat); + break; + } + } + + MUTEX_DOWNGRADE(&softc->ipf_nat); + + if (nat == NULL) { + NBUMPSIDE6DX(0, ns_lookup_miss, ns_lookup_miss_2); + } + return nat; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_tabmove */ +/* Returns: Nil */ +/* Parameters: nat(I) - pointer to NAT structure */ +/* Write Lock: ipf_nat */ +/* */ +/* This function is only called for TCP/UDP NAT table entries where the */ +/* original was placed in the table without hashing on the ports and we now */ +/* want to include hashing on port numbers. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_nat6_tabmove(softn, nat) + ipf_nat_softc_t *softn; + nat_t *nat; +{ + nat_t **natp; + u_int hv0, hv1; + + if (nat->nat_flags & SI_CLONE) + return; + + /* + * 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]; + softn->ipf_nat_stats.ns_side[0].ns_bucketlen[nat->nat_hv[0]]--; + + if (nat->nat_hnext[1]) + nat->nat_hnext[1]->nat_phnext[1] = nat->nat_phnext[1]; + *nat->nat_phnext[1] = nat->nat_hnext[1]; + softn->ipf_nat_stats.ns_side[1].ns_bucketlen[nat->nat_hv[1]]--; + + /* + * Add into the NAT table in the new position + */ + hv0 = NAT_HASH_FN6(&nat->nat_osrc6, nat->nat_osport, 0xffffffff); + hv0 = NAT_HASH_FN6(&nat->nat_odst6, hv0 + nat->nat_odport, + softn->ipf_nat_table_sz); + hv1 = NAT_HASH_FN6(&nat->nat_nsrc6, nat->nat_nsport, 0xffffffff); + hv1 = NAT_HASH_FN6(&nat->nat_ndst6, hv1 + nat->nat_ndport, + softn->ipf_nat_table_sz); + + if (nat->nat_dir == NAT_INBOUND || nat->nat_dir == NAT_DIVERTIN) { + u_int swap; + + swap = hv0; + hv0 = hv1; + hv1 = swap; + } + + /* TRACE nat_osrc6, nat_osport, nat_odst6, nat_odport, hv0 */ + /* TRACE nat_nsrc6, nat_nsport, nat_ndst6, nat_ndport, hv1 */ + + nat->nat_hv[0] = hv0; + natp = &softn->ipf_nat_table[0][hv0]; + if (*natp) + (*natp)->nat_phnext[0] = &nat->nat_hnext[0]; + nat->nat_phnext[0] = natp; + nat->nat_hnext[0] = *natp; + *natp = nat; + softn->ipf_nat_stats.ns_side[0].ns_bucketlen[hv0]++; + + nat->nat_hv[1] = hv1; + natp = &softn->ipf_nat_table[1][hv1]; + if (*natp) + (*natp)->nat_phnext[1] = &nat->nat_hnext[1]; + nat->nat_phnext[1] = natp; + nat->nat_hnext[1] = *natp; + *natp = nat; + softn->ipf_nat_stats.ns_side[1].ns_bucketlen[hv1]++; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_outlookup */ +/* Returns: nat6_t* - NULL == no match, */ +/* else pointer to matching NAT entry */ +/* Parameters: fin(I) - pointer to packet information */ +/* flags(I) - NAT flags for this packet */ +/* p(I) - protocol for this packet */ +/* src(I) - source IP address */ +/* dst(I) - destination IP address */ +/* rw(I) - 1 == write lock on held, 0 == read lock. */ +/* */ +/* Lookup a nat entry based on the source 'real' ip address/port and */ +/* destination address/port. We use this lookup when sending a packet out, */ +/* we're looking for a table entry, based on the source address. */ +/* */ +/* NOTE: THE PACKET BEING CHECKED (IF FOUND) HAS A MAPPING ALREADY. */ +/* */ +/* NOTE: IT IS ASSUMED THAT IS ONLY HELD WITH A READ LOCK WHEN */ +/* THIS FUNCTION IS CALLED WITH NAT_SEARCH SET IN nflags. */ +/* */ +/* flags -> relevant are IPN_UDP/IPN_TCP/IPN_ICMPQUERY that indicate if */ +/* the packet is of said protocol */ +/* ------------------------------------------------------------------------ */ +nat_t * +ipf_nat6_outlookup(fin, flags, p, src, dst) + fr_info_t *fin; + u_int flags, p; + struct in6_addr *src , *dst; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + u_short sport, dport; + u_int sflags; + ipnat_t *ipn; + nat_t *nat; + void *ifp; + u_int hv; + + ifp = fin->fin_ifp; + sflags = flags & IPN_TCPUDPICMP; + sport = 0; + dport = 0; + + switch (p) + { + case IPPROTO_TCP : + case IPPROTO_UDP : + sport = htons(fin->fin_data[0]); + dport = htons(fin->fin_data[1]); + break; + case IPPROTO_ICMPV6 : + if (flags & IPN_ICMPERR) + sport = fin->fin_data[1]; + else + dport = fin->fin_data[1]; + break; + default : + break; + } + + if ((flags & SI_WILDP) != 0) + goto find_out_wild_ports; + + hv = NAT_HASH_FN6(src, sport, 0xffffffff); + hv = NAT_HASH_FN6(dst, hv + dport, softn->ipf_nat_table_sz); + nat = softn->ipf_nat_table[0][hv]; + + /* TRACE src, sport, dst, dport, hv, nat */ + + for (; nat; nat = nat->nat_hnext[0]) { + if (nat->nat_ifps[1] != NULL) { + if ((ifp != NULL) && (ifp != nat->nat_ifps[1])) + continue; + } + + if (nat->nat_pr[1] != p) + continue; + + switch (nat->nat_dir) + { + case NAT_INBOUND : + if (nat->nat_v[1] != 6) + continue; + if (IP6_NEQ(&nat->nat_ndst6, src) || + IP6_NEQ(&nat->nat_nsrc6, dst)) + continue; + + if ((nat->nat_flags & IPN_TCPUDP) != 0) { + if (nat->nat_ndport != sport) + continue; + if (nat->nat_nsport != dport) + continue; + + } else if (p == IPPROTO_ICMPV6) { + if (nat->nat_osport != dport) { + continue; + } + } + break; + case NAT_OUTBOUND : + if (nat->nat_v[0] != 6) + continue; + if (IP6_NEQ(&nat->nat_osrc6, src) || + IP6_NEQ(&nat->nat_odst6, dst)) + continue; + + if ((nat->nat_flags & IPN_TCPUDP) != 0) { + if (nat->nat_odport != dport) + continue; + if (nat->nat_osport != sport) + continue; + + } else if (p == IPPROTO_ICMPV6) { + if (nat->nat_osport != dport) { + continue; + } + } + break; + } + + ipn = nat->nat_ptr; +#ifdef IPF_V6_PROXIES + if ((ipn != NULL) && (nat->nat_aps != NULL)) + if (appr_match(fin, nat) != 0) + continue; +#endif + + if ((nat->nat_ifps[1] == NULL) && (ifp != NULL)) { + nat->nat_ifps[1] = ifp; + nat->nat_mtu[1] = GETIFMTU_6(ifp); + } + return nat; + } + + /* + * So if we didn't find it but there are wildcard members in the hash + * table, go back and look for them. We do this search and update here + * because it is modifying the NAT table and we want to do this only + * for the first packet that matches. The exception, of course, is + * for "dummy" (FI_IGNORE) lookups. + */ +find_out_wild_ports: + if (!(flags & NAT_TCPUDP) || !(flags & NAT_SEARCH)) { + NBUMPSIDE6DX(1, ns_lookup_miss, ns_lookup_miss_3); + return NULL; + } + if (softn->ipf_nat_stats.ns_wilds == 0 || (fin->fin_flx & FI_NOWILD)) { + NBUMPSIDE6D(1, ns_lookup_nowild); + return NULL; + } + + RWLOCK_EXIT(&softc->ipf_nat); + + hv = NAT_HASH_FN6(src, 0, 0xffffffff); + hv = NAT_HASH_FN6(dst, hv, softn->ipf_nat_table_sz); + + WRITE_ENTER(&softc->ipf_nat); + + nat = softn->ipf_nat_table[0][hv]; + for (; nat; nat = nat->nat_hnext[0]) { + if (nat->nat_ifps[1] != NULL) { + if ((ifp != NULL) && (ifp != nat->nat_ifps[1])) + continue; + } + + if (nat->nat_pr[1] != fin->fin_p) + continue; + + switch (nat->nat_dir) + { + case NAT_INBOUND : + if (nat->nat_v[1] != 6) + continue; + if (IP6_NEQ(&nat->nat_ndst6, src) || + IP6_NEQ(&nat->nat_nsrc6, dst)) + continue; + break; + case NAT_OUTBOUND : + if (nat->nat_v[0] != 6) + continue; + if (IP6_NEQ(&nat->nat_osrc6, src) || + IP6_NEQ(&nat->nat_odst6, dst)) + continue; + break; + } + + if (!(nat->nat_flags & (NAT_TCPUDP|SI_WILDP))) + continue; + + if (ipf_nat_wildok(nat, (int)sport, (int)dport, nat->nat_flags, + NAT_OUTBOUND) == 1) { + if ((fin->fin_flx & FI_IGNORE) != 0) + break; + if ((nat->nat_flags & SI_CLONE) != 0) { + nat = ipf_nat_clone(fin, nat); + if (nat == NULL) + break; + } else { + MUTEX_ENTER(&softn->ipf_nat_new); + softn->ipf_nat_stats.ns_wilds--; + MUTEX_EXIT(&softn->ipf_nat_new); + } + + if (nat->nat_dir == NAT_OUTBOUND) { + if (nat->nat_osport == 0) { + nat->nat_osport = sport; + nat->nat_nsport = sport; + } + if (nat->nat_odport == 0) { + nat->nat_odport = dport; + nat->nat_ndport = dport; + } + } else { + if (nat->nat_osport == 0) { + nat->nat_osport = dport; + nat->nat_nsport = dport; + } + if (nat->nat_odport == 0) { + nat->nat_odport = sport; + nat->nat_ndport = sport; + } + } + if ((nat->nat_ifps[1] == NULL) && (ifp != NULL)) { + nat->nat_ifps[1] = ifp; + nat->nat_mtu[1] = GETIFMTU_6(ifp); + } + nat->nat_flags &= ~(SI_W_DPORT|SI_W_SPORT); + ipf_nat6_tabmove(softn, nat); + break; + } + } + + MUTEX_DOWNGRADE(&softc->ipf_nat); + + if (nat == NULL) { + NBUMPSIDE6DX(1, ns_lookup_miss, ns_lookup_miss_4); + } + return nat; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_lookupredir */ +/* Returns: nat6_t* - NULL == no match, */ +/* else pointer to matching NAT entry */ +/* Parameters: np(I) - pointer to description of packet to find NAT table */ +/* entry for. */ +/* */ +/* Lookup the NAT tables to search for a matching redirect */ +/* The contents of natlookup_t should imitate those found in a packet that */ +/* would be translated - ie a packet coming in for RDR or going out for MAP.*/ +/* We can do the lookup in one of two ways, imitating an inbound or */ +/* outbound packet. By default we assume outbound, unless IPN_IN is set. */ +/* For IN, the fields are set as follows: */ +/* nl_real* = source information */ +/* nl_out* = destination information (translated) */ +/* For an out packet, the fields are set like this: */ +/* nl_in* = source information (untranslated) */ +/* nl_out* = destination information (translated) */ +/* ------------------------------------------------------------------------ */ +nat_t * +ipf_nat6_lookupredir(np) + natlookup_t *np; +{ + fr_info_t fi; + nat_t *nat; + + bzero((char *)&fi, sizeof(fi)); + if (np->nl_flags & IPN_IN) { + fi.fin_data[0] = ntohs(np->nl_realport); + fi.fin_data[1] = ntohs(np->nl_outport); + } else { + fi.fin_data[0] = ntohs(np->nl_inport); + fi.fin_data[1] = ntohs(np->nl_outport); + } + if (np->nl_flags & IPN_TCP) + fi.fin_p = IPPROTO_TCP; + else if (np->nl_flags & IPN_UDP) + fi.fin_p = IPPROTO_UDP; + else if (np->nl_flags & (IPN_ICMPERR|IPN_ICMPQUERY)) + fi.fin_p = IPPROTO_ICMPV6; + + /* + * We can do two sorts of lookups: + * - IPN_IN: we have the `real' and `out' address, look for `in'. + * - default: we have the `in' and `out' address, look for `real'. + */ + if (np->nl_flags & IPN_IN) { + if ((nat = ipf_nat6_inlookup(&fi, np->nl_flags, fi.fin_p, + &np->nl_realip6, + &np->nl_outip6))) { + np->nl_inip6 = nat->nat_odst6.in6; + np->nl_inport = nat->nat_odport; + } + } else { + /* + * If nl_inip is non null, this is a lookup based on the real + * ip address. Else, we use the fake. + */ + if ((nat = ipf_nat6_outlookup(&fi, np->nl_flags, fi.fin_p, + &np->nl_inip6, &np->nl_outip6))) { + + if ((np->nl_flags & IPN_FINDFORWARD) != 0) { + fr_info_t fin; + bzero((char *)&fin, sizeof(fin)); + fin.fin_p = nat->nat_pr[0]; + fin.fin_data[0] = ntohs(nat->nat_ndport); + fin.fin_data[1] = ntohs(nat->nat_nsport); + if (ipf_nat6_inlookup(&fin, np->nl_flags, + fin.fin_p, + &nat->nat_ndst6.in6, + &nat->nat_nsrc6.in6) != + NULL) { + np->nl_flags &= ~IPN_FINDFORWARD; + } + } + + np->nl_realip6 = nat->nat_ndst6.in6; + np->nl_realport = nat->nat_ndport; + } + } + + return nat; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_match */ +/* Returns: int - 0 == no match, 1 == match */ +/* Parameters: fin(I) - pointer to packet information */ +/* np(I) - pointer to NAT rule */ +/* */ +/* Pull the matching of a packet against a NAT rule out of that complex */ +/* loop inside ipf_nat6_checkin() and lay it out properly in its own */ +/* function. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat6_match(fin, np) + fr_info_t *fin; + ipnat_t *np; +{ + frtuc_t *ft; + int match; + + match = 0; + switch (np->in_osrcatype) + { + case FRI_NORMAL : + match = IP6_MASKNEQ(&fin->fin_src6, &np->in_osrcmsk6, + &np->in_osrcip6); + break; + case FRI_LOOKUP : + match = (*np->in_osrcfunc)(fin->fin_main_soft, np->in_osrcptr, + 6, &fin->fin_src6, fin->fin_plen); + break; + } + match ^= ((np->in_flags & IPN_NOTSRC) != 0); + if (match) + return 0; + + match = 0; + switch (np->in_odstatype) + { + case FRI_NORMAL : + match = IP6_MASKNEQ(&fin->fin_dst6, &np->in_odstmsk6, + &np->in_odstip6); + break; + case FRI_LOOKUP : + match = (*np->in_odstfunc)(fin->fin_main_soft, np->in_odstptr, + 6, &fin->fin_dst6, fin->fin_plen); + break; + } + + match ^= ((np->in_flags & IPN_NOTDST) != 0); + if (match) + return 0; + + ft = &np->in_tuc; + if (!(fin->fin_flx & FI_TCPUDP) || + (fin->fin_flx & (FI_SHORT|FI_FRAGBODY))) { + if (ft->ftu_scmp || ft->ftu_dcmp) + return 0; + return 1; + } + + return ipf_tcpudpchk(&fin->fin_fi, ft); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_checkout */ +/* Returns: int - -1 == packet failed NAT checks so block it, */ +/* 0 == no packet translation occurred, */ +/* 1 == packet was successfully translated. */ +/* Parameters: fin(I) - pointer to packet information */ +/* passp(I) - pointer to filtering result flags */ +/* */ +/* Check to see if an outcoming packet should be changed. ICMP packets are */ +/* first checked to see if they match an existing entry (if an error), */ +/* otherwise a search of the current NAT table is made. If neither results */ +/* in a match then a search for a matching NAT rule is made. Create a new */ +/* NAT entry if a we matched a NAT rule. Lastly, actually change the */ +/* packet header(s) as required. */ +/* ------------------------------------------------------------------------ */ +int +ipf_nat6_checkout(fin, passp) + fr_info_t *fin; + u_32_t *passp; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + struct icmp6_hdr *icmp6 = NULL; + struct ifnet *ifp, *sifp; + tcphdr_t *tcp = NULL; + int rval, natfailed; + ipnat_t *np = NULL; + u_int nflags = 0; + i6addr_t ipa, iph; + int natadd = 1; + frentry_t *fr; + nat_t *nat; + + if (softn->ipf_nat_stats.ns_rules == 0 || softn->ipf_nat_lock != 0) + return 0; + + icmp6 = NULL; + natfailed = 0; + fr = fin->fin_fr; + sifp = fin->fin_ifp; + if (fr != NULL) { + ifp = fr->fr_tifs[fin->fin_rev].fd_ptr; + if ((ifp != NULL) && (ifp != (void *)-1)) + fin->fin_ifp = ifp; + } + ifp = fin->fin_ifp; + + if (!(fin->fin_flx & FI_SHORT) && (fin->fin_off == 0)) { + switch (fin->fin_p) + { + case IPPROTO_TCP : + nflags = IPN_TCP; + break; + case IPPROTO_UDP : + nflags = IPN_UDP; + break; + case IPPROTO_ICMPV6 : + icmp6 = fin->fin_dp; + + /* + * Apart from ECHO request and reply, all other + * informational messages should not be translated + * so as to keep IPv6 working. + */ + if (icmp6->icmp6_type > ICMP6_ECHO_REPLY) + return 0; + + /* + * This is an incoming packet, so the destination is + * the icmp6_id and the source port equals 0 + */ + if ((fin->fin_flx & FI_ICMPQUERY) != 0) + nflags = IPN_ICMPQUERY; + break; + default : + break; + } + + if ((nflags & IPN_TCPUDP)) + tcp = fin->fin_dp; + } + + ipa = fin->fin_src6; + + READ_ENTER(&softc->ipf_nat); + + if ((fin->fin_p == IPPROTO_ICMPV6) && !(nflags & IPN_ICMPQUERY) && + (nat = ipf_nat6_icmperror(fin, &nflags, NAT_OUTBOUND))) + /*EMPTY*/; + else if ((fin->fin_flx & FI_FRAG) && (nat = ipf_frag_natknown(fin))) + natadd = 0; + else if ((nat = ipf_nat6_outlookup(fin, nflags|NAT_SEARCH, + (u_int)fin->fin_p, + &fin->fin_src6.in6, + &fin->fin_dst6.in6))) { + nflags = nat->nat_flags; + } else if (fin->fin_off == 0) { + u_32_t hv, nmsk = 0; + i6addr_t *msk; + + /* + * If there is no current entry in the nat table for this IP#, + * create one for it (if there is a matching rule). + */ +maskloop: + msk = &softn->ipf_nat6_map_active_masks[nmsk]; + IP6_AND(&ipa, msk, &iph); + hv = NAT_HASH_FN6(&iph, 0, softn->ipf_nat_maprules_sz); + for (np = softn->ipf_nat_map_rules[hv]; np; np = np->in_mnext) { + if ((np->in_ifps[1] && (np->in_ifps[1] != ifp))) + continue; + if (np->in_v[0] != 6) + continue; + if (np->in_pr[1] && (np->in_pr[1] != fin->fin_p)) + continue; + if ((np->in_flags & IPN_RF) && + !(np->in_flags & nflags)) + continue; + if (np->in_flags & IPN_FILTER) { + switch (ipf_nat6_match(fin, np)) + { + case 0 : + continue; + case -1 : + rval = -1; + goto outmatchfail; + case 1 : + default : + break; + } + } else if (!IP6_MASKEQ(&ipa, &np->in_osrcmsk, + &np->in_osrcip6)) + continue; + + if ((fr != NULL) && + !ipf_matchtag(&np->in_tag, &fr->fr_nattag)) + continue; + +#ifdef IPF_V6_PROXIES + if (np->in_plabel != -1) { + if (((np->in_flags & IPN_FILTER) == 0) && + (np->in_odport != fin->fin_data[1])) + continue; + if (appr_ok(fin, tcp, np) == 0) + continue; + } +#endif + + if (np->in_flags & IPN_NO) { + np->in_hits++; + break; + } + + MUTEX_ENTER(&softn->ipf_nat_new); + nat = ipf_nat6_add(fin, np, NULL, nflags, NAT_OUTBOUND); + MUTEX_EXIT(&softn->ipf_nat_new); + if (nat != NULL) { + np->in_hits++; + break; + } + natfailed = -1; + } + if ((np == NULL) && (nmsk < softn->ipf_nat6_map_max)) { + nmsk++; + goto maskloop; + } + } + + if (nat != NULL) { + rval = ipf_nat6_out(fin, nat, natadd, nflags); + if (rval == 1) { + MUTEX_ENTER(&nat->nat_lock); + ipf_nat_update(fin, nat); + nat->nat_bytes[1] += fin->fin_plen; + nat->nat_pkts[1]++; + MUTEX_EXIT(&nat->nat_lock); + } + } else + rval = natfailed; +outmatchfail: + RWLOCK_EXIT(&softc->ipf_nat); + + switch (rval) + { + case -1 : + if (passp != NULL) { + NBUMPSIDE6D(1, ns_drop); + *passp = FR_BLOCK; + fin->fin_reason = FRB_NATV6; + } + fin->fin_flx |= FI_BADNAT; + NBUMPSIDE6D(1, ns_badnat); + break; + case 0 : + NBUMPSIDE6D(1, ns_ignored); + break; + case 1 : + NBUMPSIDE6D(1, ns_translated); + break; + } + fin->fin_ifp = sifp; + return rval; +} + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_out */ +/* Returns: int - -1 == packet failed NAT checks so block it, */ +/* 1 == packet was successfully translated. */ +/* Parameters: fin(I) - pointer to packet information */ +/* nat(I) - pointer to NAT structure */ +/* natadd(I) - flag indicating if it is safe to add frag cache */ +/* nflags(I) - NAT flags set for this packet */ +/* */ +/* Translate a packet coming "out" on an interface. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat6_out(fin, nat, natadd, nflags) + fr_info_t *fin; + nat_t *nat; + int natadd; + u_32_t nflags; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + struct icmp6_hdr *icmp6; + tcphdr_t *tcp; + ipnat_t *np; + int skip; + int i; + + tcp = NULL; + icmp6 = NULL; + np = nat->nat_ptr; + + if ((natadd != 0) && (fin->fin_flx & FI_FRAG) && (np != NULL)) + (void) ipf_frag_natnew(softc, fin, 0, nat); + + /* + * Address assignment is after the checksum modification because + * we are using the address in the packet for determining the + * correct checksum offset (the ICMP error could be coming from + * anyone...) + */ + switch (nat->nat_dir) + { + case NAT_OUTBOUND : + fin->fin_ip6->ip6_src = nat->nat_nsrc6.in6; + fin->fin_src6 = nat->nat_nsrc6; + fin->fin_ip6->ip6_dst = nat->nat_ndst6.in6; + fin->fin_dst6 = nat->nat_ndst6; + break; + + case NAT_INBOUND : + fin->fin_ip6->ip6_src = nat->nat_odst6.in6; + fin->fin_src6 = nat->nat_ndst6; + fin->fin_ip6->ip6_dst = nat->nat_osrc6.in6; + fin->fin_dst6 = nat->nat_nsrc6; + break; + + case NAT_DIVERTIN : + { + mb_t *m; + + skip = ipf_nat6_decap(fin, nat); + if (skip <= 0) { + NBUMPSIDE6D(1, ns_decap_fail); + return -1; + } + + m = fin->fin_m; + +#if defined(MENTAT) && defined(_KERNEL) + m->b_rptr += skip; +#else + m->m_data += skip; + m->m_len -= skip; + +# ifdef M_PKTHDR + if (m->m_flags & M_PKTHDR) + m->m_pkthdr.len -= skip; +# endif +#endif + + MUTEX_ENTER(&nat->nat_lock); + ipf_nat_update(fin, nat); + MUTEX_EXIT(&nat->nat_lock); + fin->fin_flx |= FI_NATED; + if (np != NULL && np->in_tag.ipt_num[0] != 0) + fin->fin_nattag = &np->in_tag; + return 1; + /* NOTREACHED */ + } + + case NAT_DIVERTOUT : + { + udphdr_t *uh; + ip6_t *ip6; + mb_t *m; + + m = M_DUP(np->in_divmp); + if (m == NULL) { + NBUMPSIDE6D(1, ns_divert_dup); + return -1; + } + + ip6 = MTOD(m, ip6_t *); + + ip6->ip6_plen = htons(fin->fin_plen + 8); + + uh = (udphdr_t *)(ip6 + 1); + uh->uh_ulen = htons(fin->fin_plen); + + PREP_MB_T(fin, m); + + fin->fin_ip6 = ip6; + fin->fin_plen += sizeof(ip6_t) + 8; /* UDP + new IPv4 hdr */ + fin->fin_dlen += sizeof(ip6_t) + 8; /* UDP + old IPv4 hdr */ + + nflags &= ~IPN_TCPUDPICMP; + + break; + } + + default : + break; + } + + if (!(fin->fin_flx & FI_SHORT) && (fin->fin_off == 0)) { + u_short *csump; + + if ((nat->nat_nsport != 0) && (nflags & IPN_TCPUDP)) { + tcp = fin->fin_dp; + + switch (nat->nat_dir) + { + case NAT_OUTBOUND : + tcp->th_sport = nat->nat_nsport; + fin->fin_data[0] = ntohs(nat->nat_nsport); + tcp->th_dport = nat->nat_ndport; + fin->fin_data[1] = ntohs(nat->nat_ndport); + break; + + case NAT_INBOUND : + tcp->th_sport = nat->nat_odport; + fin->fin_data[0] = ntohs(nat->nat_odport); + tcp->th_dport = nat->nat_osport; + fin->fin_data[1] = ntohs(nat->nat_osport); + break; + } + } + + if ((nat->nat_nsport != 0) && (nflags & IPN_ICMPQUERY)) { + icmp6 = fin->fin_dp; + icmp6->icmp6_id = nat->nat_nicmpid; + } + + csump = ipf_nat_proto(fin, nat, nflags); + + /* + * The above comments do not hold for layer 4 (or higher) + * checksums... + */ + if (csump != NULL) { + if (nat->nat_dir == NAT_OUTBOUND) + ipf_fix_outcksum(fin->fin_cksum, csump, + nat->nat_sumd[0], + nat->nat_sumd[1] + + fin->fin_dlen); + else + ipf_fix_incksum(fin->fin_cksum, csump, + nat->nat_sumd[0], + nat->nat_sumd[1] + + fin->fin_dlen); + } + } + + ipf_sync_update(softc, SMC_NAT, fin, nat->nat_sync); + /* ------------------------------------------------------------- */ + /* A few quick notes: */ + /* Following are test conditions prior to calling the */ + /* ipf_proxy_check routine. */ + /* */ + /* A NULL tcp indicates a non TCP/UDP packet. When dealing */ + /* with a redirect rule, we attempt to match the packet's */ + /* source port against in_dport, otherwise we'd compare the */ + /* packet's destination. */ + /* ------------------------------------------------------------- */ + if ((np != NULL) && (np->in_apr != NULL)) { + i = ipf_proxy_check(fin, nat); + if (i == 0) { + i = 1; + } else if (i == -1) { + NBUMPSIDE6D(1, ns_ipf_proxy_fail); + } + } else { + i = 1; + } + fin->fin_flx |= FI_NATED; + return i; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_checkin */ +/* Returns: int - -1 == packet failed NAT checks so block it, */ +/* 0 == no packet translation occurred, */ +/* 1 == packet was successfully translated. */ +/* Parameters: fin(I) - pointer to packet information */ +/* passp(I) - pointer to filtering result flags */ +/* */ +/* Check to see if an incoming packet should be changed. ICMP packets are */ +/* first checked to see if they match an existing entry (if an error), */ +/* otherwise a search of the current NAT table is made. If neither results */ +/* in a match then a search for a matching NAT rule is made. Create a new */ +/* NAT entry if a we matched a NAT rule. Lastly, actually change the */ +/* packet header(s) as required. */ +/* ------------------------------------------------------------------------ */ +int +ipf_nat6_checkin(fin, passp) + fr_info_t *fin; + u_32_t *passp; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + struct icmp6_hdr *icmp6; + u_int nflags, natadd; + int rval, natfailed; + struct ifnet *ifp; + i6addr_t ipa, iph; + tcphdr_t *tcp; + u_short dport; + ipnat_t *np; + nat_t *nat; + + if (softn->ipf_nat_stats.ns_rules == 0 || softn->ipf_nat_lock != 0) + return 0; + + tcp = NULL; + icmp6 = NULL; + dport = 0; + natadd = 1; + nflags = 0; + natfailed = 0; + ifp = fin->fin_ifp; + + if (!(fin->fin_flx & FI_SHORT) && (fin->fin_off == 0)) { + switch (fin->fin_p) + { + case IPPROTO_TCP : + nflags = IPN_TCP; + break; + case IPPROTO_UDP : + nflags = IPN_UDP; + break; + case IPPROTO_ICMPV6 : + icmp6 = fin->fin_dp; + + /* + * Apart from ECHO request and reply, all other + * informational messages should not be translated + * so as to keep IPv6 working. + */ + if (icmp6->icmp6_type > ICMP6_ECHO_REPLY) + return 0; + + /* + * This is an incoming packet, so the destination is + * the icmp6_id and the source port equals 0 + */ + if ((fin->fin_flx & FI_ICMPQUERY) != 0) { + nflags = IPN_ICMPQUERY; + dport = icmp6->icmp6_id; + } break; + default : + break; + } + + if ((nflags & IPN_TCPUDP)) { + tcp = fin->fin_dp; + dport = fin->fin_data[1]; + } + } + + ipa = fin->fin_dst6; + + READ_ENTER(&softc->ipf_nat); + + if ((fin->fin_p == IPPROTO_ICMPV6) && !(nflags & IPN_ICMPQUERY) && + (nat = ipf_nat6_icmperror(fin, &nflags, NAT_INBOUND))) + /*EMPTY*/; + else if ((fin->fin_flx & FI_FRAG) && (nat = ipf_frag_natknown(fin))) + natadd = 0; + else if ((nat = ipf_nat6_inlookup(fin, nflags|NAT_SEARCH, + (u_int)fin->fin_p, + &fin->fin_src6.in6, &ipa.in6))) { + nflags = nat->nat_flags; + } else if (fin->fin_off == 0) { + u_32_t hv, rmsk = 0; + i6addr_t *msk; + + /* + * If there is no current entry in the nat table for this IP#, + * create one for it (if there is a matching rule). + */ +maskloop: + msk = &softn->ipf_nat6_rdr_active_masks[rmsk]; + IP6_AND(&ipa, msk, &iph); + hv = NAT_HASH_FN6(&iph, 0, softn->ipf_nat_rdrrules_sz); + for (np = softn->ipf_nat_rdr_rules[hv]; np; np = np->in_rnext) { + if (np->in_ifps[0] && (np->in_ifps[0] != ifp)) + continue; + if (np->in_v[0] != 6) + continue; + if (np->in_pr[0] && (np->in_pr[0] != fin->fin_p)) + continue; + if ((np->in_flags & IPN_RF) && !(np->in_flags & nflags)) + continue; + if (np->in_flags & IPN_FILTER) { + switch (ipf_nat6_match(fin, np)) + { + case 0 : + continue; + case -1 : + rval = -1; + goto inmatchfail; + case 1 : + default : + break; + } + } else { + if (!IP6_MASKEQ(&ipa, &np->in_odstmsk6, + &np->in_odstip6)) { + continue; + } + if (np->in_odport && + ((np->in_dtop < dport) || + (dport < np->in_odport))) + continue; + } + +#ifdef IPF_V6_PROXIES + if (np->in_plabel != -1) { + if (!appr_ok(fin, tcp, np)) { + continue; + } + } +#endif + + if (np->in_flags & IPN_NO) { + np->in_hits++; + break; + } + + MUTEX_ENTER(&softn->ipf_nat_new); + nat = ipf_nat6_add(fin, np, NULL, nflags, NAT_INBOUND); + MUTEX_EXIT(&softn->ipf_nat_new); + if (nat != NULL) { + np->in_hits++; + break; + } + natfailed = -1; + } + + if ((np == NULL) && (rmsk < softn->ipf_nat6_rdr_max)) { + rmsk++; + goto maskloop; + } + } + if (nat != NULL) { + rval = ipf_nat6_in(fin, nat, natadd, nflags); + if (rval == 1) { + MUTEX_ENTER(&nat->nat_lock); + ipf_nat_update(fin, nat); + nat->nat_bytes[0] += fin->fin_plen; + nat->nat_pkts[0]++; + MUTEX_EXIT(&nat->nat_lock); + } + } else + rval = natfailed; +inmatchfail: + RWLOCK_EXIT(&softc->ipf_nat); + + switch (rval) + { + case -1 : + if (passp != NULL) { + NBUMPSIDE6D(0, ns_drop); + *passp = FR_BLOCK; + fin->fin_reason = FRB_NATV6; + } + fin->fin_flx |= FI_BADNAT; + NBUMPSIDE6D(0, ns_badnat); + break; + case 0 : + NBUMPSIDE6D(0, ns_ignored); + break; + case 1 : + NBUMPSIDE6D(0, ns_translated); + break; + } + return rval; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_in */ +/* Returns: int - -1 == packet failed NAT checks so block it, */ +/* 1 == packet was successfully translated. */ +/* Parameters: fin(I) - pointer to packet information */ +/* nat(I) - pointer to NAT structure */ +/* natadd(I) - flag indicating if it is safe to add frag cache */ +/* nflags(I) - NAT flags set for this packet */ +/* Locks Held: (READ) */ +/* */ +/* Translate a packet coming "in" on an interface. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat6_in(fin, nat, natadd, nflags) + fr_info_t *fin; + nat_t *nat; + int natadd; + u_32_t nflags; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + struct icmp6_hdr *icmp6; + u_short *csump; + tcphdr_t *tcp; + ipnat_t *np; + int skip; + int i; + + tcp = NULL; + csump = NULL; + np = nat->nat_ptr; + fin->fin_fr = nat->nat_fr; + + if (np != NULL) { + if ((natadd != 0) && (fin->fin_flx & FI_FRAG)) + (void) ipf_frag_natnew(softc, fin, 0, nat); + + /* ------------------------------------------------------------- */ + /* A few quick notes: */ + /* Following are test conditions prior to calling the */ + /* ipf_proxy_check routine. */ + /* */ + /* A NULL tcp indicates a non TCP/UDP packet. When dealing */ + /* with a map rule, we attempt to match the packet's */ + /* source port against in_dport, otherwise we'd compare the */ + /* packet's destination. */ + /* ------------------------------------------------------------- */ + if (np->in_apr != NULL) { + i = ipf_proxy_check(fin, nat); + if (i == -1) { + NBUMPSIDE6D(0, ns_ipf_proxy_fail); + return -1; + } + } + } + + ipf_sync_update(softc, SMC_NAT, fin, nat->nat_sync); + + /* + * Fix up checksums, not by recalculating them, but + * simply computing adjustments. + * Why only do this for some platforms on inbound packets ? + * Because for those that it is done, IP processing is yet to happen + * and so the IPv4 header checksum has not yet been evaluated. + * Perhaps it should always be done for the benefit of things like + * fast forwarding (so that it doesn't need to be recomputed) but with + * header checksum offloading, perhaps it is a moot point. + */ + + switch (nat->nat_dir) + { + case NAT_INBOUND : + if ((fin->fin_flx & FI_ICMPERR) == 0) { + fin->fin_ip6->ip6_src = nat->nat_nsrc6.in6; + fin->fin_src6 = nat->nat_nsrc6; + } + fin->fin_ip6->ip6_dst = nat->nat_ndst6.in6; + fin->fin_dst6 = nat->nat_ndst6; + break; + + case NAT_OUTBOUND : + if ((fin->fin_flx & FI_ICMPERR) == 0) { + fin->fin_ip6->ip6_src = nat->nat_odst6.in6; + fin->fin_src6 = nat->nat_odst6; + } + fin->fin_ip6->ip6_dst = nat->nat_osrc6.in6; + fin->fin_dst6 = nat->nat_osrc6; + break; + + case NAT_DIVERTIN : + { + udphdr_t *uh; + ip6_t *ip6; + mb_t *m; + + m = M_DUP(np->in_divmp); + if (m == NULL) { + NBUMPSIDE6D(0, ns_divert_dup); + return -1; + } + + ip6 = MTOD(m, ip6_t *); + ip6->ip6_plen = htons(fin->fin_plen + sizeof(udphdr_t)); + + uh = (udphdr_t *)(ip6 + 1); + uh->uh_ulen = ntohs(fin->fin_plen); + + PREP_MB_T(fin, m); + + fin->fin_ip6 = ip6; + fin->fin_plen += sizeof(ip6_t) + 8; /* UDP + new IPv6 hdr */ + fin->fin_dlen += sizeof(ip6_t) + 8; /* UDP + old IPv6 hdr */ + + nflags &= ~IPN_TCPUDPICMP; + + break; + } + + case NAT_DIVERTOUT : + { + mb_t *m; + + skip = ipf_nat6_decap(fin, nat); + if (skip <= 0) { + NBUMPSIDE6D(0, ns_decap_fail); + return -1; + } + + m = fin->fin_m; + +#if defined(MENTAT) && defined(_KERNEL) + m->b_rptr += skip; +#else + m->m_data += skip; + m->m_len -= skip; + +# ifdef M_PKTHDR + if (m->m_flags & M_PKTHDR) + m->m_pkthdr.len -= skip; +# endif +#endif + + ipf_nat_update(fin, nat); + fin->fin_flx |= FI_NATED; + if (np != NULL && np->in_tag.ipt_num[0] != 0) + fin->fin_nattag = &np->in_tag; + return 1; + /* NOTREACHED */ + } + } + if (nflags & IPN_TCPUDP) + tcp = fin->fin_dp; + + if (!(fin->fin_flx & FI_SHORT) && (fin->fin_off == 0)) { + if ((nat->nat_odport != 0) && (nflags & IPN_TCPUDP)) { + switch (nat->nat_dir) + { + case NAT_INBOUND : + tcp->th_sport = nat->nat_nsport; + fin->fin_data[0] = ntohs(nat->nat_nsport); + tcp->th_dport = nat->nat_ndport; + fin->fin_data[1] = ntohs(nat->nat_ndport); + break; + + case NAT_OUTBOUND : + tcp->th_sport = nat->nat_odport; + fin->fin_data[0] = ntohs(nat->nat_odport); + tcp->th_dport = nat->nat_osport; + fin->fin_data[1] = ntohs(nat->nat_osport); + break; + } + } + + + if ((nat->nat_odport != 0) && (nflags & IPN_ICMPQUERY)) { + icmp6 = fin->fin_dp; + + icmp6->icmp6_id = nat->nat_nicmpid; + } + + csump = ipf_nat_proto(fin, nat, nflags); + } + + /* + * The above comments do not hold for layer 4 (or higher) checksums... + */ + if (csump != NULL) { + if (nat->nat_dir == NAT_OUTBOUND) + ipf_fix_incksum(0, csump, nat->nat_sumd[0], 0); + else + ipf_fix_outcksum(0, csump, nat->nat_sumd[0], 0); + } + fin->fin_flx |= FI_NATED; + if (np != NULL && np->in_tag.ipt_num[0] != 0) + fin->fin_nattag = &np->in_tag; + return 1; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_newrewrite */ +/* Returns: int - -1 == error, 0 == success (no move), 1 == success and */ +/* allow rule to be moved if IPN_ROUNDR is set. */ +/* Parameters: fin(I) - pointer to packet information */ +/* nat(I) - pointer to NAT entry */ +/* ni(I) - pointer to structure with misc. information needed */ +/* to create new NAT entry. */ +/* Write Lock: ipf_nat */ +/* */ +/* This function is responsible for setting up an active NAT session where */ +/* we are changing both the source and destination parameters at the same */ +/* time. The loop in here works differently to elsewhere - each iteration */ +/* is responsible for changing a single parameter that can be incremented. */ +/* So one pass may increase the source IP#, next source port, next dest. IP#*/ +/* and the last destination port for a total of 4 iterations to try each. */ +/* This is done to try and exhaustively use the translation space available.*/ +/* ------------------------------------------------------------------------ */ +int +ipf_nat6_newrewrite(fin, nat, nai) + fr_info_t *fin; + nat_t *nat; + natinfo_t *nai; +{ + int src_search = 1; + int dst_search = 1; + fr_info_t frnat; + u_32_t flags; + u_short swap; + ipnat_t *np; + nat_t *natl; + int l = 0; + int changed; + + natl = NULL; + changed = -1; + np = nai->nai_np; + flags = nat->nat_flags; + bcopy((char *)fin, (char *)&frnat, sizeof(*fin)); + + nat->nat_hm = NULL; + + do { + changed = -1; + /* TRACE (l, src_search, dst_search, np) */ + + if ((src_search == 0) && (np->in_spnext == 0) && + (dst_search == 0) && (np->in_dpnext == 0)) { + if (l > 0) + return -1; + } + + /* + * Find a new source address + */ + if (ipf_nat6_nextaddr(fin, &np->in_nsrc, &frnat.fin_src6, + &frnat.fin_src6) == -1) { + return -1; + } + + if (IP6_ISZERO(&np->in_nsrcip6) && + IP6_ISONES(&np->in_nsrcmsk6)) { + src_search = 0; + if (np->in_stepnext == 0) + np->in_stepnext = 1; + + } else if (IP6_ISZERO(&np->in_nsrcip6) && + IP6_ISZERO(&np->in_nsrcmsk6)) { + src_search = 0; + if (np->in_stepnext == 0) + np->in_stepnext = 1; + + } else if (IP6_ISONES(&np->in_nsrcmsk)) { + src_search = 0; + if (np->in_stepnext == 0) + np->in_stepnext = 1; + + } else if (!IP6_ISONES(&np->in_nsrcmsk6)) { + if (np->in_stepnext == 0 && changed == -1) { + IP6_INC(&np->in_snip); + np->in_stepnext++; + changed = 0; + } + } + + if ((flags & IPN_TCPUDPICMP) != 0) { + if (np->in_spnext != 0) + frnat.fin_data[0] = np->in_spnext; + + /* + * Standard port translation. Select next port. + */ + if ((flags & IPN_FIXEDSPORT) != 0) { + np->in_stepnext = 2; + } else if ((np->in_stepnext == 1) && + (changed == -1) && (natl != NULL)) { + np->in_spnext++; + np->in_stepnext++; + changed = 1; + if (np->in_spnext > np->in_spmax) + np->in_spnext = np->in_spmin; + } + } else { + np->in_stepnext = 2; + } + np->in_stepnext &= 0x3; + + /* + * Find a new destination address + */ + /* TRACE (fin, np, l, frnat) */ + + if (ipf_nat6_nextaddr(fin, &np->in_ndst, &frnat.fin_dst6, + &frnat.fin_dst6) == -1) + return -1; + + if (IP6_ISZERO(&np->in_ndstip6) && + IP6_ISONES(&np->in_ndstmsk6)) { + dst_search = 0; + if (np->in_stepnext == 2) + np->in_stepnext = 3; + + } else if (IP6_ISZERO(&np->in_ndstip6) && + IP6_ISZERO(&np->in_ndstmsk6)) { + dst_search = 0; + if (np->in_stepnext == 2) + np->in_stepnext = 3; + + } else if (IP6_ISONES(&np->in_ndstmsk6)) { + dst_search = 0; + if (np->in_stepnext == 2) + np->in_stepnext = 3; + + } else if (!IP6_ISONES(&np->in_ndstmsk6)) { + if ((np->in_stepnext == 2) && (changed == -1) && + (natl != NULL)) { + changed = 2; + np->in_stepnext++; + IP6_INC(&np->in_dnip6); + } + } + + if ((flags & IPN_TCPUDPICMP) != 0) { + if (np->in_dpnext != 0) + frnat.fin_data[1] = np->in_dpnext; + + /* + * Standard port translation. Select next port. + */ + if ((flags & IPN_FIXEDDPORT) != 0) { + np->in_stepnext = 0; + } else if (np->in_stepnext == 3 && changed == -1) { + np->in_dpnext++; + np->in_stepnext++; + changed = 3; + if (np->in_dpnext > np->in_dpmax) + np->in_dpnext = np->in_dpmin; + } + } else { + if (np->in_stepnext == 3) + np->in_stepnext = 0; + } + + /* TRACE (frnat) */ + + /* + * Here we do a lookup of the connection as seen from + * the outside. If an IP# pair already exists, try + * again. So if you have A->B becomes C->B, you can + * also have D->E become C->E but not D->B causing + * another C->B. Also take protocol and ports into + * account when determining whether a pre-existing + * NAT setup will cause an external conflict where + * this is appropriate. + * + * fin_data[] is swapped around because we are doing a + * lookup of the packet is if it were moving in the opposite + * direction of the one we are working with now. + */ + if (flags & IPN_TCPUDP) { + swap = frnat.fin_data[0]; + frnat.fin_data[0] = frnat.fin_data[1]; + frnat.fin_data[1] = swap; + } + if (fin->fin_out == 1) { + natl = ipf_nat6_inlookup(&frnat, + flags & ~(SI_WILDP|NAT_SEARCH), + (u_int)frnat.fin_p, + &frnat.fin_dst6.in6, + &frnat.fin_src6.in6); + + } else { + natl = ipf_nat6_outlookup(&frnat, + flags & ~(SI_WILDP|NAT_SEARCH), + (u_int)frnat.fin_p, + &frnat.fin_dst6.in6, + &frnat.fin_src6.in6); + } + if (flags & IPN_TCPUDP) { + swap = frnat.fin_data[0]; + frnat.fin_data[0] = frnat.fin_data[1]; + frnat.fin_data[1] = swap; + } + + /* TRACE natl, in_stepnext, l */ + + if ((natl != NULL) && (l > 8)) /* XXX 8 is arbitrary */ + return -1; + + np->in_stepnext &= 0x3; + + l++; + changed = -1; + } while (natl != NULL); + nat->nat_osrc6 = fin->fin_src6; + nat->nat_odst6 = fin->fin_dst6; + nat->nat_nsrc6 = frnat.fin_src6; + nat->nat_ndst6 = frnat.fin_dst6; + + if ((flags & IPN_TCPUDP) != 0) { + nat->nat_osport = htons(fin->fin_data[0]); + nat->nat_odport = htons(fin->fin_data[1]); + nat->nat_nsport = htons(frnat.fin_data[0]); + nat->nat_ndport = htons(frnat.fin_data[1]); + } else if ((flags & IPN_ICMPQUERY) != 0) { + nat->nat_oicmpid = fin->fin_data[1]; + nat->nat_nicmpid = frnat.fin_data[1]; + } + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_newdivert */ +/* Returns: int - -1 == error, 0 == success */ +/* Parameters: fin(I) - pointer to packet information */ +/* nat(I) - pointer to NAT entry */ +/* ni(I) - pointer to structure with misc. information needed */ +/* to create new NAT entry. */ +/* Write Lock: ipf_nat */ +/* */ +/* Create a new NAT divert session as defined by the NAT rule. This is */ +/* somewhat different to other NAT session creation routines because we */ +/* do not iterate through either port numbers or IP addresses, searching */ +/* for a unique mapping, however, a complimentary duplicate check is made. */ +/* ------------------------------------------------------------------------ */ +int +ipf_nat6_newdivert(fin, nat, nai) + fr_info_t *fin; + nat_t *nat; + natinfo_t *nai; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + fr_info_t frnat; + ipnat_t *np; + nat_t *natl; + int p; + + np = nai->nai_np; + bcopy((char *)fin, (char *)&frnat, sizeof(*fin)); + + nat->nat_pr[0] = 0; + nat->nat_osrc6 = fin->fin_src6; + nat->nat_odst6 = fin->fin_dst6; + nat->nat_osport = htons(fin->fin_data[0]); + nat->nat_odport = htons(fin->fin_data[1]); + frnat.fin_src6 = np->in_snip6; + frnat.fin_dst6 = np->in_dnip6; + + if (np->in_redir & NAT_DIVERTUDP) { + frnat.fin_data[0] = np->in_spnext; + frnat.fin_data[1] = np->in_dpnext; + frnat.fin_flx |= FI_TCPUDP; + p = IPPROTO_UDP; + } else { + frnat.fin_flx &= ~FI_TCPUDP; + p = IPPROTO_IPIP; + } + + if (fin->fin_out == 1) { + natl = ipf_nat6_inlookup(&frnat, 0, p, &frnat.fin_dst6.in6, + &frnat.fin_src6.in6); + + } else { + natl = ipf_nat6_outlookup(&frnat, 0, p, &frnat.fin_dst6.in6, + &frnat.fin_src6.in6); + } + + if (natl != NULL) { + NBUMPSIDE6D(fin->fin_out, ns_divert_exist); + return -1; + } + + nat->nat_nsrc6 = frnat.fin_src6; + nat->nat_ndst6 = frnat.fin_dst6; + if (np->in_redir & NAT_DIVERTUDP) { + nat->nat_nsport = htons(frnat.fin_data[0]); + nat->nat_ndport = htons(frnat.fin_data[1]); + } + nat->nat_pr[fin->fin_out] = fin->fin_p; + nat->nat_pr[1 - fin->fin_out] = p; + + if (np->in_redir & NAT_REDIRECT) + nat->nat_dir = NAT_DIVERTIN; + else + nat->nat_dir = NAT_DIVERTOUT; + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: nat6_builddivertmp */ +/* Returns: int - -1 == error, 0 == success */ +/* Parameters: np(I) - pointer to a NAT rule */ +/* */ +/* For divert rules, a skeleton packet representing what will be prepended */ +/* to the real packet is created. Even though we don't have the full */ +/* packet here, a checksum is calculated that we update later when we */ +/* fill in the final details. At present a 0 checksum for UDP is being set */ +/* here because it is expected that divert will be used for localhost. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat6_builddivertmp(softn, np) + ipf_nat_softc_t *softn; + ipnat_t *np; +{ + udphdr_t *uh; + size_t len; + ip6_t *ip6; + + if ((np->in_redir & NAT_DIVERTUDP) != 0) + len = sizeof(ip6_t) + sizeof(udphdr_t); + else + len = sizeof(ip6_t); + + ALLOC_MB_T(np->in_divmp, len); + if (np->in_divmp == NULL) { + ATOMIC_INCL(softn->ipf_nat_stats.ns_divert_build); + return -1; + } + + /* + * First, the header to get the packet diverted to the new destination + */ + ip6 = MTOD(np->in_divmp, ip6_t *); + ip6->ip6_vfc = 0x60; + if ((np->in_redir & NAT_DIVERTUDP) != 0) + ip6->ip6_nxt = IPPROTO_UDP; + else + ip6->ip6_nxt = IPPROTO_IPIP; + ip6->ip6_hlim = 255; + ip6->ip6_plen = 0; + ip6->ip6_src = np->in_snip6.in6; + ip6->ip6_dst = np->in_dnip6.in6; + + if (np->in_redir & NAT_DIVERTUDP) { + uh = (udphdr_t *)((u_char *)ip6 + sizeof(*ip6)); + uh->uh_sum = 0; + uh->uh_ulen = 8; + uh->uh_sport = htons(np->in_spnext); + uh->uh_dport = htons(np->in_dpnext); + } + + return 0; +} + + +#define MINDECAP (sizeof(ip6_t) + sizeof(udphdr_t) + sizeof(ip6_t)) + +/* ------------------------------------------------------------------------ */ +/* Function: nat6_decap */ +/* Returns: int - -1 == error, 0 == success */ +/* Parameters: fin(I) - pointer to packet information */ +/* nat(I) - pointer to current NAT session */ +/* */ +/* This function is responsible for undoing a packet's encapsulation in the */ +/* reverse of an encap/divert rule. After removing the outer encapsulation */ +/* it is necessary to call ipf_makefrip() again so that the contents of 'fin'*/ +/* match the "new" packet as it may still be used by IPFilter elsewhere. */ +/* We use "dir" here as the basis for some of the expectations about the */ +/* outer header. If we return an error, the goal is to leave the original */ +/* packet information undisturbed - this falls short at the end where we'd */ +/* need to back a backup copy of "fin" - expensive. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat6_decap(fin, nat) + fr_info_t *fin; + nat_t *nat; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + char *hdr; + int skip; + mb_t *m; + + if ((fin->fin_flx & FI_ICMPERR) != 0) { + return 0; + } + + m = fin->fin_m; + skip = fin->fin_hlen; + + switch (nat->nat_dir) + { + case NAT_DIVERTIN : + case NAT_DIVERTOUT : + if (fin->fin_plen < MINDECAP) + return -1; + skip += sizeof(udphdr_t); + break; + + case NAT_ENCAPIN : + case NAT_ENCAPOUT : + if (fin->fin_plen < (skip + sizeof(ip6_t))) + return -1; + break; + default : + return -1; + /* NOTREACHED */ + } + + /* + * The aim here is to keep the original packet details in "fin" for + * as long as possible so that returning with an error is for the + * original packet and there is little undoing work to do. + */ + if (M_LEN(m) < skip + sizeof(ip6_t)) { + if (ipf_pr_pullup(fin, skip + sizeof(ip6_t)) == -1) + return -1; + } + + hdr = MTOD(fin->fin_m, char *); + fin->fin_ip6 = (ip6_t *)(hdr + skip); + + if (ipf_pr_pullup(fin, skip + sizeof(ip6_t)) == -1) { + NBUMPSIDE6D(fin->fin_out, ns_decap_pullup); + return -1; + } + + fin->fin_hlen = sizeof(ip6_t); + fin->fin_dlen -= skip; + fin->fin_plen -= skip; + fin->fin_ipoff += skip; + + if (ipf_makefrip(sizeof(ip6_t), (ip_t *)hdr, fin) == -1) { + NBUMPSIDE6D(fin->fin_out, ns_decap_bad); + return -1; + } + + return skip; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: nat6_nextaddr */ +/* Returns: int - -1 == bad input (no new address), */ +/* 0 == success and dst has new address */ +/* Parameters: fin(I) - pointer to packet information */ +/* na(I) - how to generate new address */ +/* old(I) - original address being replaced */ +/* dst(O) - where to put the new address */ +/* Write Lock: ipf_nat */ +/* */ +/* This function uses the contents of the "na" structure, in combination */ +/* with "old" to produce a new address to store in "dst". Not all of the */ +/* possible uses of "na" will result in a new address. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat6_nextaddr(fin, na, old, dst) + fr_info_t *fin; + nat_addr_t *na; + i6addr_t *old, *dst; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_nat_softc_t *softn = softc->ipf_nat_soft; + i6addr_t newip, new; + u_32_t amin, amax; + int error; + + new.i6[0] = 0; + new.i6[1] = 0; + new.i6[2] = 0; + new.i6[3] = 0; + amin = na->na_addr[0].in4.s_addr; + + switch (na->na_atype) + { + case FRI_RANGE : + amax = na->na_addr[1].in4.s_addr; + break; + + case FRI_NETMASKED : + case FRI_DYNAMIC : + case FRI_NORMAL : + /* + * Compute the maximum address by adding the inverse of the + * netmask to the minimum address. + */ + amax = ~na->na_addr[1].in4.s_addr; + amax |= amin; + break; + + case FRI_LOOKUP : + break; + + case FRI_BROADCAST : + case FRI_PEERADDR : + case FRI_NETWORK : + default : + return -1; + } + + error = -1; + switch (na->na_function) + { + case IPLT_DSTLIST : + error = ipf_dstlist_select_node(fin, na->na_ptr, dst->i6, + NULL); + break; + + case IPLT_NONE : + /* + * 0/0 as the new address means leave it alone. + */ + if (na->na_addr[0].in4.s_addr == 0 && + na->na_addr[1].in4.s_addr == 0) { + new = *old; + + /* + * 0/32 means get the interface's address + */ + } else if (IP6_ISZERO(&na->na_addr[0].in6) && + IP6_ISONES(&na->na_addr[1].in6)) { + if (ipf_ifpaddr(softc, 6, na->na_atype, + fin->fin_ifp, &newip, NULL) == -1) { + NBUMPSIDE6(fin->fin_out, ns_ifpaddrfail); + return -1; + } + new = newip; + } else { + new.in6 = na->na_nextip6; + } + *dst = new; + error = 0; + break; + + default : + NBUMPSIDE6(fin->fin_out, ns_badnextaddr); + break; + } + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_nextaddrinit */ +/* Returns: int - 0 == success, else error number */ +/* Parameters: na(I) - NAT address information for generating new addr*/ +/* base(I) - start of where to find strings */ +/* initial(I) - flag indicating if it is the first call for */ +/* this "na" structure. */ +/* ifp(I) - network interface to derive address */ +/* information from. */ +/* */ +/* This function is expected to be called in two scenarious: when a new NAT */ +/* rule is loaded into the kernel and when the list of NAT rules is sync'd */ +/* up with the valid network interfaces (possibly due to them changing.) */ +/* To distinguish between these, the "initial" parameter is used. If it is */ +/* 1 then this indicates the rule has just been reloaded and 0 for when we */ +/* are updating information. This difference is important because in */ +/* instances where we are not updating address information associated with */ +/* a network interface, we don't want to disturb what the "next" address to */ +/* come out of ipf_nat6_nextaddr() will be. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat6_nextaddrinit(softc, base, na, initial, ifp) + ipf_main_softc_t *softc; + char *base; + nat_addr_t *na; + int initial; + void *ifp; +{ + switch (na->na_atype) + { + case FRI_LOOKUP : + if (na->na_subtype == 0) { + na->na_ptr = ipf_lookup_res_num(softc, IPL_LOGNAT, + na->na_type, + na->na_num, + &na->na_func); + } else if (na->na_subtype == 1) { + na->na_ptr = ipf_lookup_res_name(softc, IPL_LOGNAT, + na->na_type, + base + na->na_num, + &na->na_func); + } + if (na->na_func == NULL) { + IPFERROR(60072); + return ESRCH; + } + if (na->na_ptr == NULL) { + IPFERROR(60073); + return ESRCH; + } + break; + case FRI_DYNAMIC : + case FRI_BROADCAST : + case FRI_NETWORK : + case FRI_NETMASKED : + case FRI_PEERADDR : + if (ifp != NULL) + (void )ipf_ifpaddr(softc, 6, na->na_atype, ifp, + &na->na_addr[0], + &na->na_addr[1]); + break; + + case FRI_SPLIT : + case FRI_RANGE : + if (initial) + na->na_nextip6 = na->na_addr[0].in6; + break; + + case FRI_NONE : + IP6_ANDASSIGN(&na->na_addr[0].in6, &na->na_addr[1].in6); + return 0; + + case FRI_NORMAL : + IP6_ANDASSIGN(&na->na_addr[0].in6, &na->na_addr[1].in6); + break; + + default : + IPFERROR(60074); + return EINVAL; + } + + if (initial && (na->na_atype == FRI_NORMAL)) { + if (IP6_ISZERO(&na->na_addr[0].in6)) { + if (IP6_ISONES(&na->na_addr[1].in6) || + IP6_ISZERO(&na->na_addr[1].in6)) { + return 0; + } + } + + na->na_nextip6 = na->na_addr[0].in6; + if (!IP6_ISONES(&na->na_addr[1].in6)) { + IP6_INC(&na->na_nextip6); + } + } + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_nat6_icmpquerytype */ +/* Returns: int - 1 == success, 0 == failure */ +/* Parameters: icmptype(I) - ICMP type number */ +/* */ +/* Tests to see if the ICMP type number passed is a query/response type or */ +/* not. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_nat6_icmpquerytype(icmptype) + int icmptype; +{ + + /* + * For the ICMP query NAT code, it is essential that both the query + * and the reply match on the NAT rule. Because the NAT structure + * does not keep track of the icmptype, and a single NAT structure + * is used for all icmp types with the same src, dest and id, we + * simply define the replies as queries as well. The funny thing is, + * altough it seems silly to call a reply a query, this is exactly + * as it is defined in the IPv4 specification + */ + + switch (icmptype) + { + + case ICMP6_ECHO_REPLY: + case ICMP6_ECHO_REQUEST: + /* route aedvertisement/solliciation is currently unsupported: */ + /* it would require rewriting the ICMP data section */ + case ICMP6_MEMBERSHIP_QUERY: + case ICMP6_MEMBERSHIP_REPORT: + case ICMP6_MEMBERSHIP_REDUCTION: + case ICMP6_WRUREQUEST: + case ICMP6_WRUREPLY: + case MLD6_MTRACE_RESP: + case MLD6_MTRACE: + return 1; + default: + return 0; + } +} +#endif /* USE_INET6 */ diff --git a/ip_netbios_pxy.c b/ip_netbios_pxy.c index 0ff6d25638919..4e8bdc66a2f29 100644 --- a/ip_netbios_pxy.c +++ b/ip_netbios_pxy.c @@ -1,9 +1,7 @@ -/* $NetBSD$ */ - /* * Simple netbios-dgm transparent proxy for in-kernel use. * For use with the NAT code. - * Id: ip_netbios_pxy.c,v 2.8 2003/12/01 02:52:16 darrenr Exp + * $Id$ */ /*- @@ -31,14 +29,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Id: ip_netbios_pxy.c,v 2.8 2003/12/01 02:52:16 darrenr Exp + * $Id$ */ #define IPF_NETBIOS_PROXY -int ippr_netbios_init __P((void)); -void ippr_netbios_fini __P((void)); -int ippr_netbios_out __P((fr_info_t *, ap_session_t *, nat_t *)); +void ipf_p_netbios_main_load __P((void)); +void ipf_p_netbios_main_unload __P((void)); +int ipf_p_netbios_out __P((void *, fr_info_t *, ap_session_t *, nat_t *)); static frentry_t netbiosfr; @@ -47,19 +45,19 @@ int netbios_proxy_init = 0; /* * Initialize local structures. */ -int ippr_netbios_init() +void +ipf_p_netbios_main_load() { bzero((char *)&netbiosfr, sizeof(netbiosfr)); netbiosfr.fr_ref = 1; netbiosfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE; MUTEX_INIT(&netbiosfr.fr_lock, "NETBIOS proxy rule lock"); netbios_proxy_init = 1; - - return 0; } -void ippr_netbios_fini() +void +ipf_p_netbios_main_unload() { if (netbios_proxy_init == 1) { MUTEX_DESTROY(&netbiosfr.fr_lock); @@ -68,10 +66,12 @@ void ippr_netbios_fini() } -int ippr_netbios_out(fin, aps, nat) -fr_info_t *fin; -ap_session_t *aps; -nat_t *nat; +int +ipf_p_netbios_out(arg, fin, aps, nat) + void *arg; + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; { char dgmbuf[6]; int off, dlen; @@ -82,19 +82,17 @@ nat_t *nat; aps = aps; /* LINT */ nat = nat; /* LINT */ - ip = fin->fin_ip; - m = *(mb_t **)fin->fin_mp; - off = fin->fin_hlen + sizeof(udphdr_t); - dlen = M_LEN(m); - dlen -= off; - + m = fin->fin_m; + dlen = fin->fin_dlen - sizeof(*udp); /* * no net bios datagram could possibly be shorter than this */ if (dlen < 11) return 0; + ip = fin->fin_ip; udp = (udphdr_t *)fin->fin_dp; + off = (char *)udp - (char *)ip + sizeof(*udp) + fin->fin_ipoff; /* * move past the diff --git a/ip_pool.c b/ip_pool.c index b6e111bdd9464..2a43cdb00bfa5 100644 --- a/ip_pool.c +++ b/ip_pool.c @@ -1,7 +1,5 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1993-2001, 2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -35,15 +33,10 @@ struct file; # endif #endif #include <sys/time.h> -#if !defined(linux) -# include <sys/protosw.h> -#endif -#include <sys/socket.h> -#if defined(_KERNEL) && (!defined(__SVR4) && !defined(__svr4__)) +#if defined(_KERNEL) && !defined(SOLARIS2) # include <sys/mbuf.h> #endif #if defined(__SVR4) || defined(__svr4__) -# include <sys/filio.h> # include <sys/byteorder.h> # ifdef _KERNEL # include <sys/dditypes.h> @@ -55,64 +48,91 @@ struct file; # include <sys/malloc.h> #endif -#if (defined(__osf__) || defined(__hpux) || defined(__sgi)) && defined(_KERNEL) -# ifdef __osf__ -# include <net/radix.h> -# endif -# include "radix_ipf_local.h" -# define _RADIX_H_ -#endif +#include <sys/socket.h> #include <net/if.h> #include <netinet/in.h> +#if !defined(_KERNEL) +# include "ipf.h" +#endif #include "netinet/ip_compat.h" #include "netinet/ip_fil.h" #include "netinet/ip_pool.h" - -#if defined(IPFILTER_LOOKUP) && defined(_KERNEL) && \ - ((BSD >= 198911) && !defined(__osf__) && \ - !defined(__hpux) && !defined(__sgi)) -static int rn_freenode __P((struct radix_node *, void *)); -#endif +#include "netinet/radix_ipf.h" /* END OF INCLUDES */ #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_pool.c,v 2.55.2.12 2005/02/01 04:04:46 darrenr Exp"; +static const char rcsid[] = "@(#)$Id$"; #endif -#ifdef IPFILTER_LOOKUP - -# ifndef RADIX_NODE_HEAD_LOCK -# define RADIX_NODE_HEAD_LOCK(x) ; -# endif -# ifndef RADIX_NODE_HEAD_UNLOCK -# define RADIX_NODE_HEAD_UNLOCK(x) ; -# endif - -ip_pool_stat_t ipoolstat; -ipfrwlock_t ip_poolrw; - -/* - * Binary tree routines from Sedgewick and enhanced to do ranges of addresses. - * NOTE: Insertion *MUST* be from greatest range to least for it to work! - * These should be replaced, eventually, by something else - most notably a - * interval searching method. The important feature is to be able to find - * the best match. - * - * So why not use a radix tree for this? As the first line implies, it - * has been written to work with a _range_ of addresses. A range is not - * necessarily a match with any given netmask so what we end up dealing - * with is an interval tree. Implementations of these are hard to find - * and the one herein is far from bug free. - * - * Sigh, in the end I became convinced that the bugs the code contained did - * not make it worthwhile not using radix trees. For now the radix tree from - * 4.4 BSD is used, but this is not viewed as a long term solution. - */ -ip_pool_t *ip_pool_list[IPL_LOGSIZE] = { NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL }; +typedef struct ipf_pool_softc_s { + void *ipf_radix; + ip_pool_t *ipf_pool_list[LOOKUP_POOL_SZ]; + ipf_pool_stat_t ipf_pool_stats; + ip_pool_node_t *ipf_node_explist; +} ipf_pool_softc_t; + + +static void ipf_pool_clearnodes __P((ipf_main_softc_t *, ipf_pool_softc_t *, + ip_pool_t *)); +static int ipf_pool_create __P((ipf_main_softc_t *, ipf_pool_softc_t *, iplookupop_t *)); +static int ipf_pool_deref __P((ipf_main_softc_t *, void *, void *)); +static int ipf_pool_destroy __P((ipf_main_softc_t *, ipf_pool_softc_t *, int, char *)); +static void *ipf_pool_exists __P((ipf_pool_softc_t *, int, char *)); +static void *ipf_pool_find __P((void *, int, char *)); +static ip_pool_node_t *ipf_pool_findeq __P((ipf_pool_softc_t *, ip_pool_t *, + addrfamily_t *, addrfamily_t *)); +static void ipf_pool_free __P((ipf_main_softc_t *, ipf_pool_softc_t *, + ip_pool_t *)); +static int ipf_pool_insert_node __P((ipf_main_softc_t *, ipf_pool_softc_t *, + ip_pool_t *, struct ip_pool_node *)); +static int ipf_pool_iter_deref __P((ipf_main_softc_t *, void *, int, int, void *)); +static int ipf_pool_iter_next __P((ipf_main_softc_t *, void *, ipftoken_t *, + ipflookupiter_t *)); +static size_t ipf_pool_flush __P((ipf_main_softc_t *, void *, iplookupflush_t *)); +static int ipf_pool_node_add __P((ipf_main_softc_t *, void *, iplookupop_t *, + int)); +static int ipf_pool_node_del __P((ipf_main_softc_t *, void *, iplookupop_t *, + int)); +static void ipf_pool_node_deref __P((ipf_pool_softc_t *, ip_pool_node_t *)); +static int ipf_pool_remove_node __P((ipf_main_softc_t *, ipf_pool_softc_t *, + ip_pool_t *, ip_pool_node_t *)); +static int ipf_pool_search __P((ipf_main_softc_t *, void *, int, + void *, u_int)); +static void *ipf_pool_soft_create __P((ipf_main_softc_t *)); +static void ipf_pool_soft_destroy __P((ipf_main_softc_t *, void *)); +static void ipf_pool_soft_fini __P((ipf_main_softc_t *, void *)); +static int ipf_pool_soft_init __P((ipf_main_softc_t *, void *)); +static int ipf_pool_stats_get __P((ipf_main_softc_t *, void *, iplookupop_t *)); +static int ipf_pool_table_add __P((ipf_main_softc_t *, void *, iplookupop_t *)); +static int ipf_pool_table_del __P((ipf_main_softc_t *, void *, iplookupop_t *)); +static void *ipf_pool_select_add_ref __P((void *, int, char *)); +static void ipf_pool_expire __P((ipf_main_softc_t *, void *)); + +ipf_lookup_t ipf_pool_backend = { + IPLT_POOL, + ipf_pool_soft_create, + ipf_pool_soft_destroy, + ipf_pool_soft_init, + ipf_pool_soft_fini, + ipf_pool_search, + ipf_pool_flush, + ipf_pool_iter_deref, + ipf_pool_iter_next, + ipf_pool_node_add, + ipf_pool_node_del, + ipf_pool_stats_get, + ipf_pool_table_add, + ipf_pool_table_del, + ipf_pool_deref, + ipf_pool_find, + ipf_pool_select_add_ref, + NULL, + ipf_pool_expire, + NULL +}; #ifdef TEST_POOL @@ -123,96 +143,98 @@ main(argc, argv) int argc; char *argv[]; { + ip_pool_node_t node; addrfamily_t a, b; iplookupop_t op; ip_pool_t *ipo; i6addr_t ip; - RWLOCK_INIT(&ip_poolrw, "poolrw"); - ip_pool_init(); + RWLOCK_INIT(softc->ipf_poolrw, "poolrw"); + ipf_pool_init(); - bzero((char *)&a, sizeof(a)); - bzero((char *)&b, sizeof(b)); bzero((char *)&ip, sizeof(ip)); bzero((char *)&op, sizeof(op)); + bzero((char *)&node, sizeof(node)); strcpy(op.iplo_name, "0"); - if (ip_pool_create(&op) == 0) - ipo = ip_pool_find(0, "0"); - - a.adf_addr.in4.s_addr = 0x0a010203; - b.adf_addr.in4.s_addr = 0xffffffff; - ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1); - ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1); - - a.adf_addr.in4.s_addr = 0x0a000000; - b.adf_addr.in4.s_addr = 0xff000000; - ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0); - ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0); - - a.adf_addr.in4.s_addr = 0x0a010100; - b.adf_addr.in4.s_addr = 0xffffff00; - ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1); - ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1); - - a.adf_addr.in4.s_addr = 0x0a010200; - b.adf_addr.in4.s_addr = 0xffffff00; - ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0); - ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0); - - a.adf_addr.in4.s_addr = 0x0a010000; - b.adf_addr.in4.s_addr = 0xffff0000; - ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1); - ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1); - - a.adf_addr.in4.s_addr = 0x0a01020f; - b.adf_addr.in4.s_addr = 0xffffffff; - ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1); - ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1); + if (ipf_pool_create(&op) == 0) + ipo = ipf_pool_exists(0, "0"); + + node.ipn_addr.adf_family = AF_INET; + + node.ipn_addr.adf_addr.in4.s_addr = 0x0a010203; + node.ipn_mask.adf_addr.in4.s_addr = 0xffffffff; + node.ipn_info = 1; + ipf_pool_insert_node(ipo, &node); + + node.ipn_addr.adf_addr.in4.s_addr = 0x0a000000; + node.ipn_mask.adf_addr.in4.s_addr = 0xff000000; + node.ipn_info = 0; + ipf_pool_insert_node(ipo, &node); + + node.ipn_addr.adf_addr.in4.s_addr = 0x0a010100; + node.ipn_mask.adf_addr.in4.s_addr = 0xffffff00; + node.ipn_info = 1; + ipf_pool_insert_node(ipo, &node); + + node.ipn_addr.adf_addr.in4.s_addr = 0x0a010200; + node.ipn_mask.adf_addr.in4.s_addr = 0xffffff00; + node.ipn_info = 0; + ipf_pool_insert_node(ipo, &node); + + node.ipn_addr.adf_addr.in4.s_addr = 0x0a010000; + node.ipn_mask.adf_addr.in4.s_addr = 0xffff0000; + node.ipn_info = 1; + ipf_pool_insert_node(ipo, &node); + + node.ipn_addr.adf_addr.in4.s_addr = 0x0a01020f; + node.ipn_mask.adf_addr.in4.s_addr = 0xffffffff; + node.ipn_info = 1; + ipf_pool_insert_node(ipo, &node); #ifdef DEBUG_POOL -treeprint(ipo); + treeprint(ipo); #endif ip.in4.s_addr = 0x0a00aabb; printf("search(%#x) = %d (0)\n", ip.in4.s_addr, - ip_pool_search(ipo, 4, &ip)); + ipf_pool_search(ipo, 4, &ip, 1)); ip.in4.s_addr = 0x0a000001; printf("search(%#x) = %d (0)\n", ip.in4.s_addr, - ip_pool_search(ipo, 4, &ip)); + ipf_pool_search(ipo, 4, &ip, 1)); ip.in4.s_addr = 0x0a000101; printf("search(%#x) = %d (0)\n", ip.in4.s_addr, - ip_pool_search(ipo, 4, &ip)); + ipf_pool_search(ipo, 4, &ip, 1)); ip.in4.s_addr = 0x0a010001; printf("search(%#x) = %d (1)\n", ip.in4.s_addr, - ip_pool_search(ipo, 4, &ip)); + ipf_pool_search(ipo, 4, &ip, 1)); ip.in4.s_addr = 0x0a010101; printf("search(%#x) = %d (1)\n", ip.in4.s_addr, - ip_pool_search(ipo, 4, &ip)); + ipf_pool_search(ipo, 4, &ip, 1)); ip.in4.s_addr = 0x0a010201; printf("search(%#x) = %d (0)\n", ip.in4.s_addr, - ip_pool_search(ipo, 4, &ip)); + ipf_pool_search(ipo, 4, &ip, 1)); ip.in4.s_addr = 0x0a010203; printf("search(%#x) = %d (1)\n", ip.in4.s_addr, - ip_pool_search(ipo, 4, &ip)); + ipf_pool_search(ipo, 4, &ip, 1)); ip.in4.s_addr = 0x0a01020f; printf("search(%#x) = %d (1)\n", ip.in4.s_addr, - ip_pool_search(ipo, 4, &ip)); + ipf_pool_search(ipo, 4, &ip, 1)); ip.in4.s_addr = 0x0b00aabb; printf("search(%#x) = %d (-1)\n", ip.in4.s_addr, - ip_pool_search(ipo, 4, &ip)); + ipf_pool_search(ipo, 4, &ip, 1)); #ifdef DEBUG_POOL -treeprint(ipo); + treeprint(ipo); #endif - ip_pool_fini(); + ipf_pool_fini(); return 0; } @@ -220,7 +242,7 @@ treeprint(ipo); void treeprint(ipo) -ip_pool_t *ipo; + ip_pool_t *ipo; { ip_pool_node_t *c; @@ -234,156 +256,522 @@ ip_pool_t *ipo; /* ------------------------------------------------------------------------ */ -/* Function: ip_pool_init */ +/* Function: ipf_pool_soft_create */ +/* Returns: void * - NULL = failure, else pointer to local context */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* */ +/* Initialise the routing table data structures where required. */ +/* ------------------------------------------------------------------------ */ +static void * +ipf_pool_soft_create(softc) + ipf_main_softc_t *softc; +{ + ipf_pool_softc_t *softp; + + KMALLOC(softp, ipf_pool_softc_t *); + if (softp == NULL) { + IPFERROR(70032); + return NULL; + } + + bzero((char *)softp, sizeof(*softp)); + + softp->ipf_radix = ipf_rx_create(); + if (softp->ipf_radix == NULL) { + IPFERROR(70033); + KFREE(softp); + return NULL; + } + + return softp; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pool_soft_init */ /* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ /* */ /* Initialise the routing table data structures where required. */ /* ------------------------------------------------------------------------ */ -int ip_pool_init() +static int +ipf_pool_soft_init(softc, arg) + ipf_main_softc_t *softc; + void *arg; { + ipf_pool_softc_t *softp = arg; - bzero((char *)&ipoolstat, sizeof(ipoolstat)); + ipf_rx_init(softp->ipf_radix); -#if (!defined(_KERNEL) || (BSD < 199306)) - rn_init(); -#endif return 0; } /* ------------------------------------------------------------------------ */ -/* Function: ip_pool_fini */ -/* Returns: int - 0 = success, else error */ +/* Function: ipf_pool_soft_fini */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ /* Locks: WRITE(ipf_global) */ /* */ /* Clean up all the pool data structures allocated and call the cleanup */ -/* function for the radix tree that supports the pools. ip_pool_destroy() is*/ +/* function for the radix tree that supports the pools. ipf_pool_destroy is */ /* used to delete the pools one by one to ensure they're properly freed up. */ /* ------------------------------------------------------------------------ */ -void ip_pool_fini() +static void +ipf_pool_soft_fini(softc, arg) + ipf_main_softc_t *softc; + void *arg; { + ipf_pool_softc_t *softp = arg; ip_pool_t *p, *q; - iplookupop_t op; int i; - ASSERT(rw_read_locked(&ipf_global.ipf_lk) == 0); + softc = arg; - for (i = 0; i <= IPL_LOGMAX; i++) { - for (q = ip_pool_list[i]; (p = q) != NULL; ) { - op.iplo_unit = i; - (void)strncpy(op.iplo_name, p->ipo_name, - sizeof(op.iplo_name)); + for (i = -1; i <= IPL_LOGMAX; i++) { + for (q = softp->ipf_pool_list[i + 1]; (p = q) != NULL; ) { q = p->ipo_next; - (void) ip_pool_destroy(&op); + (void) ipf_pool_destroy(softc, arg, i, p->ipo_name); + } + } +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pool_soft_destroy */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* */ +/* Clean up the pool by free'ing the radix tree associated with it and free */ +/* up the pool context too. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_pool_soft_destroy(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_pool_softc_t *softp = arg; + + ipf_rx_destroy(softp->ipf_radix); + + KFREE(softp); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pool_node_add */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* op(I) - pointer to lookup operatin data */ +/* */ +/* When adding a new node, a check is made to ensure that the address/mask */ +/* pair supplied has been appropriately prepared by applying the mask to */ +/* the address prior to calling for the pair to be added. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_pool_node_add(softc, arg, op, uid) + ipf_main_softc_t *softc; + void *arg; + iplookupop_t *op; + int uid; +{ + ip_pool_node_t node, *m; + ip_pool_t *p; + int err; + + if (op->iplo_size != sizeof(node)) { + IPFERROR(70014); + return EINVAL; + } + + err = COPYIN(op->iplo_struct, &node, sizeof(node)); + if (err != 0) { + IPFERROR(70015); + return EFAULT; + } + + p = ipf_pool_find(arg, op->iplo_unit, op->iplo_name); + if (p == NULL) { + IPFERROR(70017); + return ESRCH; + } + + if (node.ipn_addr.adf_family == AF_INET) { + if (node.ipn_addr.adf_len != offsetof(addrfamily_t, adf_addr) + + sizeof(struct in_addr)) { + IPFERROR(70028); + return EINVAL; + } + } +#ifdef USE_INET6 + else if (node.ipn_addr.adf_family == AF_INET6) { + if (node.ipn_addr.adf_len != offsetof(addrfamily_t, adf_addr) + + sizeof(struct in6_addr)) { + IPFERROR(70034); + return EINVAL; + } + } +#endif + if (node.ipn_mask.adf_len != node.ipn_addr.adf_len) { + IPFERROR(70029); + return EINVAL; + } + + /* + * Check that the address/mask pair works. + */ + if (node.ipn_addr.adf_family == AF_INET) { + if ((node.ipn_addr.adf_addr.in4.s_addr & + node.ipn_mask.adf_addr.in4.s_addr) != + node.ipn_addr.adf_addr.in4.s_addr) { + IPFERROR(70035); + return EINVAL; + } + } +#ifdef USE_INET6 + else if (node.ipn_addr.adf_family == AF_INET6) { + if (IP6_MASKNEQ(&node.ipn_addr.adf_addr.in6, + &node.ipn_mask.adf_addr.in6, + &node.ipn_addr.adf_addr.in6)) { + IPFERROR(70036); + return EINVAL; } } +#endif + + /* + * add an entry to a pool - return an error if it already + * exists remove an entry from a pool - if it exists + * - in both cases, the pool *must* exist! + */ + m = ipf_pool_findeq(arg, p, &node.ipn_addr, &node.ipn_mask); + if (m != NULL) { + IPFERROR(70018); + return EEXIST; + } + err = ipf_pool_insert_node(softc, arg, p, &node); + + return err; +} + -#if (!defined(_KERNEL) || (BSD < 199306)) - rn_fini(); +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pool_node_del */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* op(I) - pointer to lookup operatin data */ +/* */ +/* ------------------------------------------------------------------------ */ +static int +ipf_pool_node_del(softc, arg, op, uid) + ipf_main_softc_t *softc; + void *arg; + iplookupop_t *op; + int uid; +{ + ip_pool_node_t node, *m; + ip_pool_t *p; + int err; + + + if (op->iplo_size != sizeof(node)) { + IPFERROR(70019); + return EINVAL; + } + node.ipn_uid = uid; + + err = COPYIN(op->iplo_struct, &node, sizeof(node)); + if (err != 0) { + IPFERROR(70020); + return EFAULT; + } + + if (node.ipn_addr.adf_family == AF_INET) { + if (node.ipn_addr.adf_len != offsetof(addrfamily_t, adf_addr) + + sizeof(struct in_addr)) { + IPFERROR(70030); + return EINVAL; + } + } +#ifdef USE_INET6 + else if (node.ipn_addr.adf_family == AF_INET6) { + if (node.ipn_addr.adf_len != offsetof(addrfamily_t, adf_addr) + + sizeof(struct in6_addr)) { + IPFERROR(70037); + return EINVAL; + } + } #endif + if (node.ipn_mask.adf_len != node.ipn_addr.adf_len) { + IPFERROR(70031); + return EINVAL; + } + + p = ipf_pool_find(arg, op->iplo_unit, op->iplo_name); + if (p == NULL) { + IPFERROR(70021); + return ESRCH; + } + + m = ipf_pool_findeq(arg, p, &node.ipn_addr, &node.ipn_mask); + if (m == NULL) { + IPFERROR(70022); + return ENOENT; + } + + if ((uid != 0) && (uid != m->ipn_uid)) { + IPFERROR(70024); + return EACCES; + } + + err = ipf_pool_remove_node(softc, arg, p, m); + + return err; } /* ------------------------------------------------------------------------ */ -/* Function: ip_pool_statistics */ -/* Returns: int - 0 = success, else error */ -/* Parameters: op(I) - pointer to lookup operation arguments */ +/* Function: ipf_pool_table_add */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* op(I) - pointer to lookup operatin data */ +/* */ +/* ------------------------------------------------------------------------ */ +static int +ipf_pool_table_add(softc, arg, op) + ipf_main_softc_t *softc; + void *arg; + iplookupop_t *op; +{ + int err; + + if (((op->iplo_arg & LOOKUP_ANON) == 0) && + (ipf_pool_find(arg, op->iplo_unit, op->iplo_name) != NULL)) { + IPFERROR(70023); + err = EEXIST; + } else { + err = ipf_pool_create(softc, arg, op); + } + + return err; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pool_table_del */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* op(I) - pointer to lookup operatin data */ +/* */ +/* ------------------------------------------------------------------------ */ +static int +ipf_pool_table_del(softc, arg, op) + ipf_main_softc_t *softc; + void *arg; + iplookupop_t *op; +{ + return ipf_pool_destroy(softc, arg, op->iplo_unit, op->iplo_name); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pool_statistics */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* op(I) - pointer to lookup operatin data */ /* */ /* Copy the current statistics out into user space, collecting pool list */ /* pointers as appropriate for later use. */ /* ------------------------------------------------------------------------ */ -int ip_pool_statistics(op) -iplookupop_t *op; +static int +ipf_pool_stats_get(softc, arg, op) + ipf_main_softc_t *softc; + void *arg; + iplookupop_t *op; { - ip_pool_stat_t stats; + ipf_pool_softc_t *softp = arg; + ipf_pool_stat_t stats; int unit, i, err = 0; - if (op->iplo_size != sizeof(ipoolstat)) + if (op->iplo_size != sizeof(ipf_pool_stat_t)) { + IPFERROR(70001); return EINVAL; + } - bcopy((char *)&ipoolstat, (char *)&stats, sizeof(stats)); + bcopy((char *)&softp->ipf_pool_stats, (char *)&stats, sizeof(stats)); unit = op->iplo_unit; if (unit == IPL_LOGALL) { - for (i = 0; i < IPL_LOGSIZE; i++) - stats.ipls_list[i] = ip_pool_list[i]; - } else if (unit >= 0 && unit < IPL_LOGSIZE) { + for (i = 0; i <= LOOKUP_POOL_MAX; i++) + stats.ipls_list[i] = softp->ipf_pool_list[i]; + } else if (unit >= 0 && unit <= IPL_LOGMAX) { + unit++; /* -1 => 0 */ if (op->iplo_name[0] != '\0') - stats.ipls_list[unit] = ip_pool_find(unit, - op->iplo_name); + stats.ipls_list[unit] = ipf_pool_exists(softp, unit - 1, + op->iplo_name); else - stats.ipls_list[unit] = ip_pool_list[unit]; - } else + stats.ipls_list[unit] = softp->ipf_pool_list[unit]; + } else { + IPFERROR(70025); err = EINVAL; - if (err == 0) + } + if (err == 0) { err = COPYOUT(&stats, op->iplo_struct, sizeof(stats)); - return err; + if (err != 0) { + IPFERROR(70026); + return EFAULT; + } + } + return 0; } - /* ------------------------------------------------------------------------ */ -/* Function: ip_pool_find */ -/* Returns: int - 0 = success, else error */ -/* Parameters: ipo(I) - pointer to the pool getting the new node. */ +/* Function: ipf_pool_exists */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softp(I) - pointer to soft context pool information */ +/* unit(I) - ipfilter device to which we are working on */ +/* name(I) - name of the pool */ /* */ /* Find a matching pool inside the collection of pools for a particular */ /* device, indicated by the unit number. */ /* ------------------------------------------------------------------------ */ -void *ip_pool_find(unit, name) -int unit; -char *name; +static void * +ipf_pool_exists(softp, unit, name) + ipf_pool_softc_t *softp; + int unit; + char *name; { ip_pool_t *p; + int i; - for (p = ip_pool_list[unit]; p != NULL; p = p->ipo_next) - if (strncmp(p->ipo_name, name, sizeof(p->ipo_name)) == 0) - break; + if (unit == IPL_LOGALL) { + for (i = 0; i <= LOOKUP_POOL_MAX; i++) { + for (p = softp->ipf_pool_list[i]; p != NULL; + p = p->ipo_next) { + if (strncmp(p->ipo_name, name, + sizeof(p->ipo_name)) == 0) + break; + } + if (p != NULL) + break; + } + } else { + for (p = softp->ipf_pool_list[unit + 1]; p != NULL; + p = p->ipo_next) + if (strncmp(p->ipo_name, name, + sizeof(p->ipo_name)) == 0) + break; + } return p; } /* ------------------------------------------------------------------------ */ -/* Function: ip_pool_findeq */ +/* Function: ipf_pool_find */ +/* Returns: int - 0 = success, else error */ +/* Parameters: arg(I) - pointer to local context to use */ +/* unit(I) - ipfilter device to which we are working on */ +/* name(I) - name of the pool */ +/* */ +/* Find a matching pool inside the collection of pools for a particular */ +/* device, indicated by the unit number. If it is marked for deletion then */ +/* pretend it does not exist. */ +/* ------------------------------------------------------------------------ */ +static void * +ipf_pool_find(arg, unit, name) + void *arg; + int unit; + char *name; +{ + ipf_pool_softc_t *softp = arg; + ip_pool_t *p; + + p = ipf_pool_exists(softp, unit, name); + if ((p != NULL) && (p->ipo_flags & IPOOL_DELETE)) + return NULL; + + return p; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pool_select_add_ref */ +/* Returns: int - 0 = success, else error */ +/* Parameters: arg(I) - pointer to local context to use */ +/* unit(I) - ipfilter device to which we are working on */ +/* name(I) - name of the pool */ +/* */ +/* ------------------------------------------------------------------------ */ +static void * +ipf_pool_select_add_ref(arg, unit, name) + void *arg; + int unit; + char *name; +{ + ip_pool_t *p; + + p = ipf_pool_find(arg, -1, name); + if (p == NULL) + p = ipf_pool_find(arg, unit, name); + if (p != NULL) { + ATOMIC_INC32(p->ipo_ref); + } + return p; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pool_findeq */ /* Returns: int - 0 = success, else error */ -/* Parameters: ipo(I) - pointer to the pool getting the new node. */ -/* addr(I) - pointer to address information to delete */ -/* mask(I) - */ +/* Parameters: softp(I) - pointer to soft context pool information */ +/* ipo(I) - pointer to the pool getting the new node. */ +/* addr(I) - pointer to address information to match on */ +/* mask(I) - pointer to the address mask to match */ /* */ /* Searches for an exact match of an entry in the pool. */ /* ------------------------------------------------------------------------ */ -ip_pool_node_t *ip_pool_findeq(ipo, addr, mask) -ip_pool_t *ipo; -addrfamily_t *addr, *mask; +extern void printhostmask __P((int, u_32_t *, u_32_t *)); +static ip_pool_node_t * +ipf_pool_findeq(softp, ipo, addr, mask) + ipf_pool_softc_t *softp; + ip_pool_t *ipo; + addrfamily_t *addr, *mask; { - struct radix_node *n; -#ifdef USE_SPL - int s; + ipf_rdx_node_t *n; - SPL_NET(s); -#endif - RADIX_NODE_HEAD_LOCK(ipo->ipo_head); - n = ipo->ipo_head->rnh_lookup(addr, mask, ipo->ipo_head); - RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head); - SPL_X(s); + n = ipo->ipo_head->lookup(ipo->ipo_head, addr, mask); return (ip_pool_node_t *)n; } /* ------------------------------------------------------------------------ */ -/* Function: ip_pool_search */ +/* Function: ipf_pool_search */ /* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */ -/* Parameters: tptr(I) - pointer to the pool to search */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* tptr(I) - pointer to the pool to search */ /* version(I) - IP protocol version (4 or 6) */ /* dptr(I) - pointer to address information */ +/* bytes(I) - length of packet */ /* */ /* Search the pool for a given address and return a search result. */ /* ------------------------------------------------------------------------ */ -int ip_pool_search(tptr, version, dptr) -void *tptr; -int version; -void *dptr; +static int +ipf_pool_search(softc, tptr, ipversion, dptr, bytes) + ipf_main_softc_t *softc; + void *tptr; + int ipversion; + void *dptr; + u_int bytes; { - struct radix_node *rn; + ipf_rdx_node_t *rn; ip_pool_node_t *m; i6addr_t *addr; addrfamily_t v; @@ -398,136 +786,207 @@ void *dptr; m = NULL; addr = (i6addr_t *)dptr; bzero(&v, sizeof(v)); - v.adf_len = offsetof(addrfamily_t, adf_addr); - if (version == 4) { - v.adf_len += sizeof(addr->in4); + if (ipversion == 4) { + v.adf_family = AF_INET; + v.adf_len = offsetof(addrfamily_t, adf_addr) + + sizeof(struct in_addr); v.adf_addr.in4 = addr->in4; #ifdef USE_INET6 - } else if (version == 6) { - v.adf_len += sizeof(addr->in6); + } else if (ipversion == 6) { + v.adf_family = AF_INET6; + v.adf_len = offsetof(addrfamily_t, adf_addr) + + sizeof(struct in6_addr); v.adf_addr.in6 = addr->in6; #endif } else return -1; - READ_ENTER(&ip_poolrw); + READ_ENTER(&softc->ipf_poolrw); - RADIX_NODE_HEAD_LOCK(ipo->ipo_head); - rn = ipo->ipo_head->rnh_matchaddr(&v, ipo->ipo_head); - RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head); + rn = ipo->ipo_head->matchaddr(ipo->ipo_head, &v); - if ((rn != NULL) && ((rn->rn_flags & RNF_ROOT) == 0)) { + if ((rn != NULL) && (rn->root == 0)) { m = (ip_pool_node_t *)rn; ipo->ipo_hits++; + m->ipn_bytes += bytes; m->ipn_hits++; rv = m->ipn_info; } - RWLOCK_EXIT(&ip_poolrw); + RWLOCK_EXIT(&softc->ipf_poolrw); return rv; } /* ------------------------------------------------------------------------ */ -/* Function: ip_pool_insert */ -/* Returns: int - 0 = success, else error */ -/* Parameters: ipo(I) - pointer to the pool getting the new node. */ -/* addr(I) - address being added as a node */ -/* mask(I) - netmask to with the node being added */ -/* info(I) - extra information to store in this node. */ -/* Locks: WRITE(ip_poolrw) */ +/* Function: ipf_pool_insert_node */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* softp(I) - pointer to soft context pool information */ +/* ipo(I) - pointer to the pool getting the new node. */ +/* node(I) - structure with address/mask to add */ +/* Locks: WRITE(ipf_poolrw) */ /* */ /* Add another node to the pool given by ipo. The three parameters passed */ /* in (addr, mask, info) shold all be stored in the node. */ /* ------------------------------------------------------------------------ */ -int ip_pool_insert(ipo, addr, mask, info) -ip_pool_t *ipo; -i6addr_t *addr, *mask; -int info; +static int +ipf_pool_insert_node(softc, softp, ipo, node) + ipf_main_softc_t *softc; + ipf_pool_softc_t *softp; + ip_pool_t *ipo; + struct ip_pool_node *node; { - struct radix_node *rn; + ipf_rdx_node_t *rn; ip_pool_node_t *x; - ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0); + if ((node->ipn_addr.adf_len > sizeof(*rn)) || + (node->ipn_addr.adf_len < 4)) { + IPFERROR(70003); + return EINVAL; + } + + if ((node->ipn_mask.adf_len > sizeof(*rn)) || + (node->ipn_mask.adf_len < 4)) { + IPFERROR(70004); + return EINVAL; + } KMALLOC(x, ip_pool_node_t *); if (x == NULL) { + IPFERROR(70002); return ENOMEM; } - bzero(x, sizeof(*x)); - - x->ipn_info = info; - (void)strncpy(x->ipn_name, ipo->ipo_name, sizeof(x->ipn_name)); + *x = *node; + bzero((char *)x->ipn_nodes, sizeof(x->ipn_nodes)); + x->ipn_owner = ipo; + x->ipn_hits = 0; + x->ipn_next = NULL; + x->ipn_pnext = NULL; + x->ipn_dnext = NULL; + x->ipn_pdnext = NULL; + + if (x->ipn_die != 0) { + /* + * If the new node has a given expiration time, insert it + * into the list of expiring nodes with the ones to be + * removed first added to the front of the list. The + * insertion is O(n) but it is kept sorted for quick scans + * at expiration interval checks. + */ + ip_pool_node_t *n; + + x->ipn_die = softc->ipf_ticks + IPF_TTLVAL(x->ipn_die); + for (n = softp->ipf_node_explist; n != NULL; n = n->ipn_dnext) { + if (x->ipn_die < n->ipn_die) + break; + if (n->ipn_dnext == NULL) { + /* + * We've got to the last node and everything + * wanted to be expired before this new node, + * so we have to tack it on the end... + */ + n->ipn_dnext = x; + x->ipn_pdnext = &n->ipn_dnext; + n = NULL; + break; + } + } - bcopy(addr, &x->ipn_addr.adf_addr, sizeof(*addr)); - x->ipn_addr.adf_len = sizeof(x->ipn_addr); - bcopy(mask, &x->ipn_mask.adf_addr, sizeof(*mask)); - x->ipn_mask.adf_len = sizeof(x->ipn_mask); + if (softp->ipf_node_explist == NULL) { + softp->ipf_node_explist = x; + x->ipn_pdnext = &softp->ipf_node_explist; + } else if (n != NULL) { + x->ipn_dnext = n; + x->ipn_pdnext = n->ipn_pdnext; + n->ipn_pdnext = &x->ipn_dnext; + } + } - RADIX_NODE_HEAD_LOCK(ipo->ipo_head); - rn = ipo->ipo_head->rnh_addaddr(&x->ipn_addr, &x->ipn_mask, - ipo->ipo_head, x->ipn_nodes); - RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head); + rn = ipo->ipo_head->addaddr(ipo->ipo_head, &x->ipn_addr, &x->ipn_mask, + x->ipn_nodes); #ifdef DEBUG_POOL printf("Added %p at %p\n", x, rn); #endif if (rn == NULL) { KFREE(x); + IPFERROR(70005); return ENOMEM; } - x->ipn_next = ipo->ipo_list; - x->ipn_pnext = &ipo->ipo_list; - if (ipo->ipo_list != NULL) - ipo->ipo_list->ipn_pnext = &x->ipn_next; - ipo->ipo_list = x; + x->ipn_ref = 1; + x->ipn_pnext = ipo->ipo_tail; + *ipo->ipo_tail = x; + ipo->ipo_tail = &x->ipn_next; - ipoolstat.ipls_nodes++; + softp->ipf_pool_stats.ipls_nodes++; return 0; } /* ------------------------------------------------------------------------ */ -/* Function: ip_pool_create */ -/* Returns: int - 0 = success, else error */ -/* Parameters: op(I) - pointer to iplookup struct with call details */ -/* Locks: WRITE(ip_poolrw) */ +/* Function: ipf_pool_create */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* softp(I) - pointer to soft context pool information */ +/* op(I) - pointer to iplookup struct with call details */ +/* Locks: WRITE(ipf_poolrw) */ /* */ /* Creates a new group according to the paramters passed in via the */ /* iplookupop structure. Does not check to see if the group already exists */ /* when being inserted - assume this has already been done. If the pool is */ /* marked as being anonymous, give it a new, unique, identifier. Call any */ /* other functions required to initialise the structure. */ +/* */ +/* If the structure is flagged for deletion then reset the flag and return, */ +/* as this likely means we've tried to free a pool that is in use (flush) */ +/* and now want to repopulate it with "new" data. */ /* ------------------------------------------------------------------------ */ -int ip_pool_create(op) -iplookupop_t *op; +static int +ipf_pool_create(softc, softp, op) + ipf_main_softc_t *softc; + ipf_pool_softc_t *softp; + iplookupop_t *op; { char name[FR_GROUPLEN]; int poolnum, unit; ip_pool_t *h; - ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0); + unit = op->iplo_unit; + + if ((op->iplo_arg & LOOKUP_ANON) == 0) { + h = ipf_pool_exists(softp, unit, op->iplo_name); + if (h != NULL) { + if ((h->ipo_flags & IPOOL_DELETE) == 0) { + IPFERROR(70006); + return EEXIST; + } + h->ipo_flags &= ~IPOOL_DELETE; + return 0; + } + } KMALLOC(h, ip_pool_t *); - if (h == NULL) + if (h == NULL) { + IPFERROR(70007); return ENOMEM; + } bzero(h, sizeof(*h)); - if (rn_inithead((void **)&h->ipo_head, - offsetof(addrfamily_t, adf_addr) << 3) == 0) { + if (ipf_rx_inithead(softp->ipf_radix, &h->ipo_head) != 0) { KFREE(h); + IPFERROR(70008); return ENOMEM; } - unit = op->iplo_unit; - - if ((op->iplo_arg & IPOOL_ANON) != 0) { + if ((op->iplo_arg & LOOKUP_ANON) != 0) { ip_pool_t *p; - poolnum = IPOOL_ANON; + h->ipo_flags |= IPOOL_ANON; + poolnum = LOOKUP_ANON; #if defined(SNPRINTF) && defined(_KERNEL) SNPRINTF(name, sizeof(name), "%x", poolnum); @@ -535,7 +994,7 @@ iplookupop_t *op; (void)sprintf(name, "%x", poolnum); #endif - for (p = ip_pool_list[unit]; p != NULL; ) { + for (p = softp->ipf_pool_list[unit + 1]; p != NULL; ) { if (strncmp(name, p->ipo_name, sizeof(p->ipo_name)) == 0) { poolnum++; @@ -544,138 +1003,155 @@ iplookupop_t *op; #else (void)sprintf(name, "%x", poolnum); #endif - p = ip_pool_list[unit]; + p = softp->ipf_pool_list[unit + 1]; } else p = p->ipo_next; } (void)strncpy(h->ipo_name, name, sizeof(h->ipo_name)); + (void)strncpy(op->iplo_name, name, sizeof(op->iplo_name)); } else { - (void) strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name)); + (void)strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name)); } + h->ipo_radix = softp->ipf_radix; h->ipo_ref = 1; h->ipo_list = NULL; + h->ipo_tail = &h->ipo_list; h->ipo_unit = unit; - h->ipo_next = ip_pool_list[unit]; - if (ip_pool_list[unit] != NULL) - ip_pool_list[unit]->ipo_pnext = &h->ipo_next; - h->ipo_pnext = &ip_pool_list[unit]; - ip_pool_list[unit] = h; + h->ipo_next = softp->ipf_pool_list[unit + 1]; + if (softp->ipf_pool_list[unit + 1] != NULL) + softp->ipf_pool_list[unit + 1]->ipo_pnext = &h->ipo_next; + h->ipo_pnext = &softp->ipf_pool_list[unit + 1]; + softp->ipf_pool_list[unit + 1] = h; - ipoolstat.ipls_pools++; + softp->ipf_pool_stats.ipls_pools++; return 0; } /* ------------------------------------------------------------------------ */ -/* Function: ip_pool_remove */ -/* Returns: int - 0 = success, else error */ -/* Parameters: ipo(I) - pointer to the pool to remove the node from. */ -/* ipe(I) - address being deleted as a node */ -/* Locks: WRITE(ip_poolrw) */ +/* Function: ipf_pool_remove_node */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* ipo(I) - pointer to the pool to remove the node from. */ +/* ipe(I) - address being deleted as a node */ +/* Locks: WRITE(ipf_poolrw) */ /* */ -/* Add another node to the pool given by ipo. The three parameters passed */ -/* in (addr, mask, info) shold all be stored in the node. */ +/* Remove a node from the pool given by ipo. */ /* ------------------------------------------------------------------------ */ -int ip_pool_remove(ipo, ipe) -ip_pool_t *ipo; -ip_pool_node_t *ipe; +static int +ipf_pool_remove_node(softc, softp, ipo, ipe) + ipf_main_softc_t *softc; + ipf_pool_softc_t *softp; + ip_pool_t *ipo; + ip_pool_node_t *ipe; { - ip_pool_node_t **ipp, *n; - - ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0); + void *ptr; - for (ipp = &ipo->ipo_list; (n = *ipp) != NULL; ipp = &n->ipn_next) { - if (ipe == n) { - *n->ipn_pnext = n->ipn_next; - if (n->ipn_next) - n->ipn_next->ipn_pnext = n->ipn_pnext; - break; - } - } + if (ipo->ipo_tail == &ipe->ipn_next) + ipo->ipo_tail = ipe->ipn_pnext; - if (n == NULL) - return ENOENT; + if (ipe->ipn_pnext != NULL) + *ipe->ipn_pnext = ipe->ipn_next; + if (ipe->ipn_next != NULL) + ipe->ipn_next->ipn_pnext = ipe->ipn_pnext; - RADIX_NODE_HEAD_LOCK(ipo->ipo_head); - ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask, - ipo->ipo_head); - RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head); - KFREE(n); + if (ipe->ipn_pdnext != NULL) + *ipe->ipn_pdnext = ipe->ipn_dnext; + if (ipe->ipn_dnext != NULL) + ipe->ipn_dnext->ipn_pdnext = ipe->ipn_pdnext; - ipoolstat.ipls_nodes--; + ptr = ipo->ipo_head->deladdr(ipo->ipo_head, &ipe->ipn_addr, + &ipe->ipn_mask); - return 0; + if (ptr != NULL) { + ipf_pool_node_deref(softp, ipe); + return 0; + } + IPFERROR(70027); + return ESRCH; } /* ------------------------------------------------------------------------ */ -/* Function: ip_pool_destroy */ +/* Function: ipf_pool_destroy */ /* Returns: int - 0 = success, else error */ -/* Parameters: op(I) - information about the pool to remove */ -/* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* softp(I) - pointer to soft context pool information */ +/* unit(I) - ipfilter device to which we are working on */ +/* name(I) - name of the pool */ +/* Locks: WRITE(ipf_poolrw) or WRITE(ipf_global) */ /* */ /* Search for a pool using paramters passed in and if it's not otherwise */ -/* busy, free it. */ +/* busy, free it. If it is busy, clear all of its nodes, mark it for being */ +/* deleted and return an error saying it is busy. */ /* */ -/* NOTE: Because this function is called out of ipldetach() where ip_poolrw */ +/* NOTE: Because this function is called out of ipfdetach() where ipf_poolrw*/ /* may not be initialised, we can't use an ASSERT to enforce the locking */ -/* assertion that one of the two (ip_poolrw,ipf_global) is held. */ +/* assertion that one of the two (ipf_poolrw,ipf_global) is held. */ /* ------------------------------------------------------------------------ */ -int ip_pool_destroy(op) -iplookupop_t *op; +static int +ipf_pool_destroy(softc, softp, unit, name) + ipf_main_softc_t *softc; + ipf_pool_softc_t *softp; + int unit; + char *name; { ip_pool_t *ipo; - ipo = ip_pool_find(op->iplo_unit, op->iplo_name); - if (ipo == NULL) + ipo = ipf_pool_exists(softp, unit, name); + if (ipo == NULL) { + IPFERROR(70009); return ESRCH; + } - if (ipo->ipo_ref != 1) - return EBUSY; + if (ipo->ipo_ref != 1) { + ipf_pool_clearnodes(softc, softp, ipo); + ipo->ipo_flags |= IPOOL_DELETE; + return 0; + } - ip_pool_free(ipo); + ipf_pool_free(softc, softp, ipo); return 0; } /* ------------------------------------------------------------------------ */ -/* Function: ip_pool_flush */ +/* Function: ipf_pool_flush */ /* Returns: int - number of pools deleted */ -/* Parameters: fp(I) - which pool(s) to flush */ -/* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* fp(I) - which pool(s) to flush */ +/* Locks: WRITE(ipf_poolrw) or WRITE(ipf_global) */ /* */ /* Free all pools associated with the device that matches the unit number */ /* passed in with operation. */ /* */ -/* NOTE: Because this function is called out of ipldetach() where ip_poolrw */ +/* NOTE: Because this function is called out of ipfdetach() where ipf_poolrw*/ /* may not be initialised, we can't use an ASSERT to enforce the locking */ -/* assertion that one of the two (ip_poolrw,ipf_global) is held. */ +/* assertion that one of the two (ipf_poolrw,ipf_global) is held. */ /* ------------------------------------------------------------------------ */ -int ip_pool_flush(fp) -iplookupflush_t *fp; +static size_t +ipf_pool_flush(softc, arg, fp) + ipf_main_softc_t *softc; + void *arg; + iplookupflush_t *fp; { + ipf_pool_softc_t *softp = arg; int i, num = 0, unit, err; ip_pool_t *p, *q; - iplookupop_t op; unit = fp->iplf_unit; - - for (i = 0; i <= IPL_LOGMAX; i++) { + for (i = -1; i <= IPL_LOGMAX; i++) { if (unit != IPLT_ALL && i != unit) continue; - for (q = ip_pool_list[i]; (p = q) != NULL; ) { - op.iplo_unit = i; - (void)strncpy(op.iplo_name, p->ipo_name, - sizeof(op.iplo_name)); + for (q = softp->ipf_pool_list[i + 1]; (p = q) != NULL; ) { q = p->ipo_next; - err = ip_pool_destroy(&op); + err = ipf_pool_destroy(softc, softp, i, p->ipo_name); if (err == 0) num++; - else - break; } } return num; @@ -683,104 +1159,331 @@ iplookupflush_t *fp; /* ------------------------------------------------------------------------ */ -/* Function: ip_pool_free */ +/* Function: ipf_pool_free */ /* Returns: void */ -/* Parameters: ipo(I) - pointer to pool structure */ -/* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* softp(I) - pointer to soft context pool information */ +/* ipo(I) - pointer to pool structure */ +/* Locks: WRITE(ipf_poolrw) or WRITE(ipf_global) */ /* */ /* Deletes the pool strucutre passed in from the list of pools and deletes */ /* all of the address information stored in it, including any tree data */ /* structures also allocated. */ /* */ -/* NOTE: Because this function is called out of ipldetach() where ip_poolrw */ +/* NOTE: Because this function is called out of ipfdetach() where ipf_poolrw*/ /* may not be initialised, we can't use an ASSERT to enforce the locking */ -/* assertion that one of the two (ip_poolrw,ipf_global) is held. */ +/* assertion that one of the two (ipf_poolrw,ipf_global) is held. */ /* ------------------------------------------------------------------------ */ -void ip_pool_free(ipo) -ip_pool_t *ipo; +static void +ipf_pool_free(softc, softp, ipo) + ipf_main_softc_t *softc; + ipf_pool_softc_t *softp; + ip_pool_t *ipo; { - ip_pool_node_t *n; - - RADIX_NODE_HEAD_LOCK(ipo->ipo_head); - while ((n = ipo->ipo_list) != NULL) { - ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask, - ipo->ipo_head); - - *n->ipn_pnext = n->ipn_next; - if (n->ipn_next) - n->ipn_next->ipn_pnext = n->ipn_pnext; - KFREE(n); + ipf_pool_clearnodes(softc, softp, ipo); - ipoolstat.ipls_nodes--; - } - RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head); - - ipo->ipo_list = NULL; if (ipo->ipo_next != NULL) ipo->ipo_next->ipo_pnext = ipo->ipo_pnext; *ipo->ipo_pnext = ipo->ipo_next; - rn_freehead(ipo->ipo_head); + ipf_rx_freehead(ipo->ipo_head); KFREE(ipo); - ipoolstat.ipls_pools--; + softp->ipf_pool_stats.ipls_pools--; } /* ------------------------------------------------------------------------ */ -/* Function: ip_pool_deref */ +/* Function: ipf_pool_clearnodes */ /* Returns: void */ -/* Parameters: ipo(I) - pointer to pool structure */ -/* Locks: WRITE(ip_poolrw) */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* softp(I) - pointer to soft context pool information */ +/* ipo(I) - pointer to pool structure */ +/* Locks: WRITE(ipf_poolrw) or WRITE(ipf_global) */ +/* */ +/* Deletes all nodes stored in a pool structure. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_pool_clearnodes(softc, softp, ipo) + ipf_main_softc_t *softc; + ipf_pool_softc_t *softp; + ip_pool_t *ipo; +{ + ip_pool_node_t *n, **next; + + for (next = &ipo->ipo_list; (n = *next) != NULL; ) + ipf_pool_remove_node(softc, softp, ipo, n); + + ipo->ipo_list = NULL; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pool_deref */ +/* Returns: void */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* pool(I) - pointer to pool structure */ +/* Locks: WRITE(ipf_poolrw) */ /* */ /* Drop the number of known references to this pool structure by one and if */ /* we arrive at zero known references, free it. */ /* ------------------------------------------------------------------------ */ -void ip_pool_deref(ipo) -ip_pool_t *ipo; +static int +ipf_pool_deref(softc, arg, pool) + ipf_main_softc_t *softc; + void *arg, *pool; { - - ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0); + ip_pool_t *ipo = pool; ipo->ipo_ref--; + if (ipo->ipo_ref == 0) - ip_pool_free(ipo); + ipf_pool_free(softc, arg, ipo); + + else if ((ipo->ipo_ref == 1) && (ipo->ipo_flags & IPOOL_DELETE)) + ipf_pool_destroy(softc, arg, ipo->ipo_unit, ipo->ipo_name); + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pool_node_deref */ +/* Returns: void */ +/* Parameters: softp(I) - pointer to soft context pool information */ +/* ipn(I) - pointer to pool structure */ +/* Locks: WRITE(ipf_poolrw) */ +/* */ +/* Drop a reference to the pool node passed in and if we're the last, free */ +/* it all up and adjust the stats accordingly. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_pool_node_deref(softp, ipn) + ipf_pool_softc_t *softp; + ip_pool_node_t *ipn; +{ + + ipn->ipn_ref--; + + if (ipn->ipn_ref == 0) { + KFREE(ipn); + softp->ipf_pool_stats.ipls_nodes--; + } } -# if defined(_KERNEL) && ((BSD >= 198911) && !defined(__osf__) && \ - !defined(__hpux) && !defined(__sgi)) +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pool_iter_next */ +/* Returns: void */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* token(I) - pointer to pool structure */ +/* ilp(IO) - pointer to pool iterating structure */ +/* */ +/* ------------------------------------------------------------------------ */ static int -rn_freenode(struct radix_node *n, void *p) +ipf_pool_iter_next(softc, arg, token, ilp) + ipf_main_softc_t *softc; + void *arg; + ipftoken_t *token; + ipflookupiter_t *ilp; { - struct radix_node_head *rnh = p; - struct radix_node *d; + ipf_pool_softc_t *softp = arg; + ip_pool_node_t *node, zn, *nextnode; + ip_pool_t *ipo, zp, *nextipo; + void *pnext; + int err; + + err = 0; + node = NULL; + nextnode = NULL; + ipo = NULL; + nextipo = NULL; + + READ_ENTER(&softc->ipf_poolrw); + + switch (ilp->ili_otype) + { + case IPFLOOKUPITER_LIST : + ipo = token->ipt_data; + if (ipo == NULL) { + nextipo = softp->ipf_pool_list[(int)ilp->ili_unit + 1]; + } else { + nextipo = ipo->ipo_next; + } + + if (nextipo != NULL) { + ATOMIC_INC32(nextipo->ipo_ref); + token->ipt_data = nextipo; + } else { + bzero((char *)&zp, sizeof(zp)); + nextipo = &zp; + token->ipt_data = NULL; + } + pnext = nextipo->ipo_next; + break; + + case IPFLOOKUPITER_NODE : + node = token->ipt_data; + if (node == NULL) { + ipo = ipf_pool_exists(arg, ilp->ili_unit, + ilp->ili_name); + if (ipo == NULL) { + IPFERROR(70010); + err = ESRCH; + } else { + nextnode = ipo->ipo_list; + ipo = NULL; + } + } else { + nextnode = node->ipn_next; + } - d = rnh->rnh_deladdr(n->rn_key, NULL, rnh); - if (d != NULL) { - FreeS(d, max_keylen + 2 * sizeof (*d)); + if (nextnode != NULL) { + ATOMIC_INC32(nextnode->ipn_ref); + token->ipt_data = nextnode; + } else { + bzero((char *)&zn, sizeof(zn)); + nextnode = &zn; + token->ipt_data = NULL; + } + pnext = nextnode->ipn_next; + break; + + default : + IPFERROR(70011); + pnext = NULL; + err = EINVAL; + break; } - return 0; + + RWLOCK_EXIT(&softc->ipf_poolrw); + if (err != 0) + return err; + + switch (ilp->ili_otype) + { + case IPFLOOKUPITER_LIST : + err = COPYOUT(nextipo, ilp->ili_data, sizeof(*nextipo)); + if (err != 0) { + IPFERROR(70012); + err = EFAULT; + } + if (ipo != NULL) { + WRITE_ENTER(&softc->ipf_poolrw); + ipf_pool_deref(softc, softp, ipo); + RWLOCK_EXIT(&softc->ipf_poolrw); + } + break; + + case IPFLOOKUPITER_NODE : + err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode)); + if (err != 0) { + IPFERROR(70013); + err = EFAULT; + } + if (node != NULL) { + WRITE_ENTER(&softc->ipf_poolrw); + ipf_pool_node_deref(softp, node); + RWLOCK_EXIT(&softc->ipf_poolrw); + } + break; + } + if (pnext == NULL) + ipf_token_mark_complete(token); + + return err; } -void -rn_freehead(rnh) - struct radix_node_head *rnh; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pool_iterderef */ +/* Returns: void */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* unit(I) - ipfilter device to which we are working on */ +/* Locks: WRITE(ipf_poolrw) */ +/* */ +/* ------------------------------------------------------------------------ */ +static int +ipf_pool_iter_deref(softc, arg, otype, unit, data) + ipf_main_softc_t *softc; + void *arg; + int otype; + int unit; + void *data; { + ipf_pool_softc_t *softp = arg; + + if (data == NULL) + return EINVAL; - RADIX_NODE_HEAD_LOCK(rnh); - (*rnh->rnh_walktree)(rnh, rn_freenode, rnh); + if (unit < 0 || unit > IPL_LOGMAX) + return EINVAL; - rnh->rnh_addaddr = NULL; - rnh->rnh_deladdr = NULL; - rnh->rnh_matchaddr = NULL; - rnh->rnh_lookup = NULL; - rnh->rnh_walktree = NULL; - RADIX_NODE_HEAD_UNLOCK(rnh); + switch (otype) + { + case IPFLOOKUPITER_LIST : + ipf_pool_deref(softc, softp, (ip_pool_t *)data); + break; + + case IPFLOOKUPITER_NODE : + ipf_pool_node_deref(softp, (ip_pool_node_t *)data); + break; + default : + break; + } - Free(rnh); + return 0; } -# endif -#endif /* IPFILTER_LOOKUP */ + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_pool_expire */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* */ +/* At present this function exists just to support temporary addition of */ +/* nodes to the address pool. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_pool_expire(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_pool_softc_t *softp = arg; + ip_pool_node_t *n; + + while ((n = softp->ipf_node_explist) != NULL) { + /* + * Because the list is kept sorted on insertion, the fist + * one that dies in the future means no more work to do. + */ + if (n->ipn_die > softc->ipf_ticks) + break; + ipf_pool_remove_node(softc, softp, n->ipn_owner, n); + } +} + + + + +#ifndef _KERNEL +void +ipf_pool_dump(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_pool_softc_t *softp = arg; + ip_pool_t *ipl; + int i; + + printf("List of configured pools\n"); + for (i = 0; i <= LOOKUP_POOL_MAX; i++) + for (ipl = softp->ipf_pool_list[i]; ipl != NULL; + ipl = ipl->ipo_next) + printpool(ipl, bcopywrap, NULL, opts, NULL); +} +#endif diff --git a/ip_pool.h b/ip_pool.h index 3e3c073552295..8524e607949c8 100644 --- a/ip_pool.h +++ b/ip_pool.h @@ -1,87 +1,67 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1993-2001, 2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * Id: ip_pool.h,v 2.26.2.2 2004/03/23 12:44:34 darrenr Exp + * $Id$ */ #ifndef __IP_POOL_H__ #define __IP_POOL_H__ -#if defined(_KERNEL) && !defined(__osf__) && !defined(__hpux) && \ - !defined(linux) && !defined(sun) -# include <net/radix.h> -extern void rn_freehead __P((struct radix_node_head *)); -# define FreeS(p, z) KFREES(p, z) -extern int max_keylen; -#else -# if defined(__osf__) || defined(__hpux) -# include "radix_ipf_local.h" -# define radix_mask ipf_radix_mask -# define radix_node ipf_radix_node -# define radix_node_head ipf_radix_node_head -# else -# include "radix_ipf.h" -# endif -#endif #include "netinet/ip_lookup.h" +#include "radix_ipf.h" #define IP_POOL_NOMATCH 0 #define IP_POOL_POSITIVE 1 typedef struct ip_pool_node { - struct radix_node ipn_nodes[2]; + ipf_rdx_node_t ipn_nodes[2]; addrfamily_t ipn_addr; addrfamily_t ipn_mask; + int ipn_uid; int ipn_info; + int ipn_ref; char ipn_name[FR_GROUPLEN]; - u_long ipn_hits; + U_QUAD_T ipn_hits; + U_QUAD_T ipn_bytes; + u_long ipn_die; struct ip_pool_node *ipn_next, **ipn_pnext; + struct ip_pool_node *ipn_dnext, **ipn_pdnext; + struct ip_pool_s *ipn_owner; } ip_pool_node_t; typedef struct ip_pool_s { struct ip_pool_s *ipo_next; struct ip_pool_s **ipo_pnext; - struct radix_node_head *ipo_head; - ip_pool_node_t *ipo_list; - u_long ipo_hits; - int ipo_unit; - int ipo_flags; - int ipo_ref; - char ipo_name[FR_GROUPLEN]; + ipf_rdx_head_t *ipo_head; + ip_pool_node_t *ipo_list; + ip_pool_node_t **ipo_tail; + ip_pool_node_t *ipo_nextaddr; + void *ipo_radix; + u_long ipo_hits; + int ipo_unit; + int ipo_flags; + int ipo_ref; + char ipo_name[FR_GROUPLEN]; } ip_pool_t; -#define IPOOL_ANON 0x80000000 +#define IPOOL_DELETE 0x01 +#define IPOOL_ANON 0x02 -typedef struct ip_pool_stat { - u_long ipls_pools; - u_long ipls_tables; - u_long ipls_nodes; - ip_pool_t *ipls_list[IPL_LOGSIZE]; -} ip_pool_stat_t; +typedef struct ipf_pool_stat { + u_long ipls_pools; + u_long ipls_tables; + u_long ipls_nodes; + ip_pool_t *ipls_list[LOOKUP_POOL_SZ]; +} ipf_pool_stat_t; +extern ipf_lookup_t ipf_pool_backend; -extern ip_pool_stat_t ipoolstat; -extern ip_pool_t *ip_pool_list[IPL_LOGSIZE]; - -extern int ip_pool_search __P((void *, int, void *)); -extern int ip_pool_init __P((void)); -extern void ip_pool_fini __P((void)); -extern int ip_pool_create __P((iplookupop_t *)); -extern int ip_pool_insert __P((ip_pool_t *, i6addr_t *, i6addr_t *, int)); -extern int ip_pool_remove __P((ip_pool_t *, ip_pool_node_t *)); -extern int ip_pool_destroy __P((iplookupop_t *)); -extern void ip_pool_free __P((ip_pool_t *)); -extern void ip_pool_deref __P((ip_pool_t *)); -extern void *ip_pool_find __P((int, char *)); -extern ip_pool_node_t *ip_pool_findeq __P((ip_pool_t *, - addrfamily_t *, addrfamily_t *)); -extern int ip_pool_flush __P((iplookupflush_t *)); -extern int ip_pool_statistics __P((iplookupop_t *)); +#ifndef _KERNEL +extern void ipf_pool_dump __P((ipf_main_softc_t *, void *)); +#endif #endif /* __IP_POOL_H__ */ diff --git a/ip_pptp_pxy.c b/ip_pptp_pxy.c index 2511a17600d6c..959b107cd6af5 100644 --- a/ip_pptp_pxy.c +++ b/ip_pptp_pxy.c @@ -1,20 +1,42 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 2002-2003 by Darren Reed + * Copyright (C) 2012 by Darren Reed. * * Simple PPTP transparent proxy for in-kernel use. For use with the NAT * code. * - * Id: ip_pptp_pxy.c,v 2.10.2.9 2005/03/16 18:17:34 darrenr Exp + * $Id$ * */ #define IPF_PPTP_PROXY + + +/* + * PPTP proxy + */ +typedef struct pptp_side { + u_32_t pptps_nexthdr; + u_32_t pptps_next; + int pptps_state; + int pptps_gothdr; + int pptps_len; + int pptps_bytes; + char *pptps_wptr; + char pptps_buffer[512]; +} pptp_side_t; + +typedef struct pptp_pxy { + nat_t *pptp_nat; + struct ipstate *pptp_state; + u_short pptp_call[2]; + pptp_side_t pptp_side[2]; + ipnat_t *pptp_rule; +} pptp_pxy_t; + typedef struct pptp_hdr { - u_short pptph_len; - u_short pptph_type; - u_32_t pptph_cookie; + u_short pptph_len; + u_short pptph_type; + u_32_t pptph_cookie; } pptp_hdr_t; #define PPTP_MSGTYPE_CTL 1 @@ -35,41 +57,41 @@ typedef struct pptp_hdr { #define PPTP_MTCTL_LINKINFO 15 -int ippr_pptp_init __P((void)); -void ippr_pptp_fini __P((void)); -int ippr_pptp_new __P((fr_info_t *, ap_session_t *, nat_t *)); -void ippr_pptp_del __P((ap_session_t *)); -int ippr_pptp_inout __P((fr_info_t *, ap_session_t *, nat_t *)); -void ippr_pptp_donatstate __P((fr_info_t *, nat_t *, pptp_pxy_t *)); -int ippr_pptp_message __P((fr_info_t *, nat_t *, pptp_pxy_t *, pptp_side_t *)); -int ippr_pptp_nextmessage __P((fr_info_t *, nat_t *, pptp_pxy_t *, int)); -int ippr_pptp_mctl __P((fr_info_t *, nat_t *, pptp_pxy_t *, pptp_side_t *)); +void ipf_p_pptp_main_load __P((void)); +void ipf_p_pptp_main_unload __P((void)); +int ipf_p_pptp_new __P((void *, fr_info_t *, ap_session_t *, nat_t *)); +void ipf_p_pptp_del __P((ipf_main_softc_t *, ap_session_t *)); +int ipf_p_pptp_inout __P((void *, fr_info_t *, ap_session_t *, nat_t *)); +void ipf_p_pptp_donatstate __P((fr_info_t *, nat_t *, pptp_pxy_t *)); +int ipf_p_pptp_message __P((fr_info_t *, nat_t *, pptp_pxy_t *, pptp_side_t *)); +int ipf_p_pptp_nextmessage __P((fr_info_t *, nat_t *, pptp_pxy_t *, int)); +int ipf_p_pptp_mctl __P((fr_info_t *, nat_t *, pptp_pxy_t *, pptp_side_t *)); static frentry_t pptpfr; -int pptp_proxy_init = 0; -int ippr_pptp_debug = 0; -int ippr_pptp_gretimeout = IPF_TTLVAL(120); /* 2 minutes */ +static int pptp_proxy_init = 0; +static int ipf_p_pptp_debug = 0; +static int ipf_p_pptp_gretimeout = IPF_TTLVAL(120); /* 2 minutes */ /* * PPTP application proxy initialization. */ -int ippr_pptp_init() +void +ipf_p_pptp_main_load() { bzero((char *)&pptpfr, sizeof(pptpfr)); pptpfr.fr_ref = 1; - pptpfr.fr_age[0] = ippr_pptp_gretimeout; - pptpfr.fr_age[1] = ippr_pptp_gretimeout; + pptpfr.fr_age[0] = ipf_p_pptp_gretimeout; + pptpfr.fr_age[1] = ipf_p_pptp_gretimeout; pptpfr.fr_flags = FR_OUTQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE; MUTEX_INIT(&pptpfr.fr_lock, "PPTP proxy rule lock"); pptp_proxy_init = 1; - - return 0; } -void ippr_pptp_fini() +void +ipf_p_pptp_main_unload() { if (pptp_proxy_init == 1) { MUTEX_DESTROY(&pptpfr.fr_lock); @@ -80,65 +102,87 @@ void ippr_pptp_fini() /* * Setup for a new PPTP proxy. + * + * NOTE: The printf's are broken up with %s in them to prevent them being + * optimised into puts statements on FreeBSD (this doesn't exist in the kernel) */ -int ippr_pptp_new(fin, aps, nat) -fr_info_t *fin; -ap_session_t *aps; -nat_t *nat; +int +ipf_p_pptp_new(arg, fin, aps, nat) + void *arg; + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; { pptp_pxy_t *pptp; ipnat_t *ipn; + ipnat_t *np; + int size; ip_t *ip; - int off; + + if (fin->fin_v != 4) + return -1; ip = fin->fin_ip; - off = fin->fin_hlen + sizeof(udphdr_t); + np = nat->nat_ptr; + size = np->in_size; - if (nat_outlookup(fin, 0, IPPROTO_GRE, nat->nat_inip, + if (ipf_nat_outlookup(fin, 0, IPPROTO_GRE, nat->nat_osrcip, ip->ip_dst) != NULL) { - if (ippr_pptp_debug > 0) - printf("ippr_pptp_new: GRE session already exists\n"); + if (ipf_p_pptp_debug > 0) + printf("ipf_p_pptp_new: GRE session already exists\n"); return -1; } - aps->aps_psiz = sizeof(*pptp); - KMALLOCS(aps->aps_data, pptp_pxy_t *, sizeof(*pptp)); - if (aps->aps_data == NULL) { - if (ippr_pptp_debug > 0) - printf("ippr_pptp_new: malloc for aps_data failed\n"); + KMALLOC(pptp, pptp_pxy_t *); + if (pptp == NULL) { + if (ipf_p_pptp_debug > 0) + printf("ipf_p_pptp_new: malloc for aps_data failed\n"); + return -1; + } + KMALLOCS(ipn, ipnat_t *, size); + if (ipn == NULL) { + KFREE(pptp); return -1; } + aps->aps_data = pptp; + aps->aps_psiz = sizeof(*pptp); + bzero((char *)pptp, sizeof(*pptp)); + bzero((char *)ipn, size); + pptp->pptp_rule = ipn; + /* * Create NAT rule against which the tunnel/transport mapping is * created. This is required because the current NAT rule does not * describe GRE but TCP instead. */ - pptp = aps->aps_data; - bzero((char *)pptp, sizeof(*pptp)); - ipn = &pptp->pptp_rule; + ipn->in_size = size; ipn->in_ifps[0] = fin->fin_ifp; ipn->in_apr = NULL; ipn->in_use = 1; ipn->in_hits = 1; ipn->in_ippip = 1; - if (nat->nat_dir == NAT_OUTBOUND) { - ipn->in_nip = ntohl(nat->nat_outip.s_addr); - ipn->in_outip = fin->fin_saddr; - ipn->in_redir = NAT_MAP; - } else if (nat->nat_dir == NAT_INBOUND) { - ipn->in_nip = 0; - ipn->in_outip = nat->nat_outip.s_addr; - ipn->in_redir = NAT_REDIRECT; - } - ipn->in_inip = nat->nat_inip.s_addr; - ipn->in_inmsk = 0xffffffff; - ipn->in_outmsk = 0xffffffff; - ipn->in_srcip = fin->fin_saddr; - ipn->in_srcmsk = 0xffffffff; - bcopy(nat->nat_ptr->in_ifnames[0], ipn->in_ifnames[0], - sizeof(ipn->in_ifnames[0])); - ipn->in_p = IPPROTO_GRE; + ipn->in_snip = ntohl(nat->nat_nsrcaddr); + ipn->in_nsrcaddr = fin->fin_saddr; + ipn->in_dnip = ntohl(nat->nat_ndstaddr); + ipn->in_ndstaddr = nat->nat_ndstaddr; + ipn->in_redir = np->in_redir; + ipn->in_osrcaddr = nat->nat_osrcaddr; + ipn->in_odstaddr = nat->nat_odstaddr; + ipn->in_osrcmsk = 0xffffffff; + ipn->in_nsrcmsk = 0xffffffff; + ipn->in_odstmsk = 0xffffffff; + ipn->in_ndstmsk = 0xffffffff; + ipn->in_flags = (np->in_flags | IPN_PROXYRULE); + MUTEX_INIT(&ipn->in_lock, "pptp proxy NAT rule"); + + ipn->in_namelen = np->in_namelen; + bcopy(np->in_names, ipn->in_ifnames, ipn->in_namelen); + ipn->in_ifnames[0] = np->in_ifnames[0]; + ipn->in_ifnames[1] = np->in_ifnames[1]; + + ipn->in_pr[0] = IPPROTO_GRE; + ipn->in_pr[1] = IPPROTO_GRE; pptp->pptp_side[0].pptps_wptr = pptp->pptp_side[0].pptps_buffer; pptp->pptp_side[1].pptps_wptr = pptp->pptp_side[1].pptps_buffer; @@ -146,11 +190,13 @@ nat_t *nat; } -void ippr_pptp_donatstate(fin, nat, pptp) -fr_info_t *fin; -nat_t *nat; -pptp_pxy_t *pptp; +void +ipf_p_pptp_donatstate(fin, nat, pptp) + fr_info_t *fin; + nat_t *nat; + pptp_pxy_t *pptp; { + ipf_main_softc_t *softc = fin->fin_main_soft; fr_info_t fi; grehdr_t gre; nat_t *nat2; @@ -164,8 +210,6 @@ pptp_pxy_t *pptp; if ((nat2 == NULL) || (pptp->pptp_state == NULL)) { bcopy((char *)fin, (char *)&fi, sizeof(fi)); bzero((char *)&gre, sizeof(gre)); - fi.fin_state = NULL; - fi.fin_nat = NULL; fi.fin_fi.fi_p = IPPROTO_GRE; fi.fin_fr = &pptpfr; if ((nat->nat_dir == NAT_OUTBOUND && fin->fin_out) || @@ -182,45 +226,47 @@ pptp_pxy_t *pptp; fi.fin_flx |= FI_IGNORE; fi.fin_dp = &gre; gre.gr_flags = htons(1 << 13); - if (fin->fin_out && nat->nat_dir == NAT_INBOUND) { - fi.fin_fi.fi_saddr = fin->fin_fi.fi_daddr; - fi.fin_fi.fi_daddr = nat->nat_outip.s_addr; - } else if (!fin->fin_out && nat->nat_dir == NAT_OUTBOUND) { - fi.fin_fi.fi_saddr = nat->nat_inip.s_addr; - fi.fin_fi.fi_daddr = fin->fin_fi.fi_saddr; - } + + fi.fin_fi.fi_saddr = nat->nat_osrcaddr; + fi.fin_fi.fi_daddr = nat->nat_odstaddr; } /* * Update NAT timeout/create NAT if missing. */ if (nat2 != NULL) - fr_queueback(&nat2->nat_tqe); + ipf_queueback(softc->ipf_ticks, &nat2->nat_tqe); else { - nat2 = nat_new(&fi, &pptp->pptp_rule, &pptp->pptp_nat, - NAT_SLAVE, nat->nat_dir); - pptp->pptp_nat = nat2; +#ifdef USE_MUTEXES + ipf_nat_softc_t *softn = softc->ipf_nat_soft; +#endif + + MUTEX_ENTER(&softn->ipf_nat_new); + nat2 = ipf_nat_add(&fi, pptp->pptp_rule, &pptp->pptp_nat, + NAT_SLAVE, nat->nat_dir); + MUTEX_EXIT(&softn->ipf_nat_new); if (nat2 != NULL) { - (void) nat_proto(&fi, nat2, 0); - nat_update(&fi, nat2, nat2->nat_ptr); + (void) ipf_nat_proto(&fi, nat2, 0); + MUTEX_ENTER(&nat2->nat_lock); + ipf_nat_update(&fi, nat2); + MUTEX_EXIT(&nat2->nat_lock); } } - READ_ENTER(&ipf_state); + READ_ENTER(&softc->ipf_state); if (pptp->pptp_state != NULL) { - fr_queueback(&pptp->pptp_state->is_sti); - RWLOCK_EXIT(&ipf_state); + ipf_queueback(softc->ipf_ticks, &pptp->pptp_state->is_sti); + RWLOCK_EXIT(&softc->ipf_state); } else { - RWLOCK_EXIT(&ipf_state); - if (nat->nat_dir == NAT_INBOUND) - fi.fin_fi.fi_daddr = nat2->nat_inip.s_addr; - else - fi.fin_fi.fi_saddr = nat2->nat_inip.s_addr; + RWLOCK_EXIT(&softc->ipf_state); + if (nat2 != NULL) { + if (nat->nat_dir == NAT_INBOUND) + fi.fin_fi.fi_daddr = nat2->nat_ndstaddr; + else + fi.fin_fi.fi_saddr = nat2->nat_osrcaddr; + } fi.fin_ifp = NULL; - pptp->pptp_state = fr_addstate(&fi, &pptp->pptp_state, - 0); - if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); + (void) ipf_state_add(softc, &fi, &pptp->pptp_state, 0); } ip->ip_p = p; return; @@ -232,13 +278,14 @@ pptp_pxy_t *pptp; * build it up completely (fits in our buffer) then pass it off to the message * parsing function. */ -int ippr_pptp_nextmessage(fin, nat, pptp, rev) -fr_info_t *fin; -nat_t *nat; -pptp_pxy_t *pptp; -int rev; +int +ipf_p_pptp_nextmessage(fin, nat, pptp, rev) + fr_info_t *fin; + nat_t *nat; + pptp_pxy_t *pptp; + int rev; { - static char *funcname = "ippr_pptp_nextmessage"; + static const char *funcname = "ipf_p_pptp_nextmessage"; pptp_side_t *pptps; u_32_t start, end; pptp_hdr_t *hdr; @@ -268,7 +315,7 @@ int rev; return 0; if (pptps->pptps_next != start) { - if (ippr_pptp_debug > 5) + if (ipf_p_pptp_debug > 5) printf("%s: next (%x) != start (%x)\n", funcname, pptps->pptps_next, start); return -1; @@ -293,7 +340,7 @@ int rev; if (pptps->pptps_bytes == 8) { pptps->pptps_next += 8; if (ntohl(hdr->pptph_cookie) != 0x1a2b3c4d) { - if (ippr_pptp_debug > 1) + if (ipf_p_pptp_debug > 1) printf("%s: bad cookie (%x)\n", funcname, hdr->pptph_cookie); @@ -317,7 +364,7 @@ int rev; * bad data packet, anyway. */ if (len > sizeof(pptps->pptps_buffer)) { - if (ippr_pptp_debug > 3) + if (ipf_p_pptp_debug > 3) printf("%s: message too big (%d)\n", funcname, len); pptps->pptps_next = pptps->pptps_nexthdr; @@ -338,7 +385,7 @@ int rev; if (pptps->pptps_len > pptps->pptps_bytes) break; - ippr_pptp_message(fin, nat, pptp, pptps); + ipf_p_pptp_message(fin, nat, pptp, pptps); pptps->pptps_wptr = pptps->pptps_buffer; pptps->pptps_gothdr = 0; pptps->pptps_bytes = 0; @@ -356,18 +403,19 @@ int rev; /* * handle a complete PPTP message */ -int ippr_pptp_message(fin, nat, pptp, pptps) -fr_info_t *fin; -nat_t *nat; -pptp_pxy_t *pptp; -pptp_side_t *pptps; +int +ipf_p_pptp_message(fin, nat, pptp, pptps) + fr_info_t *fin; + nat_t *nat; + pptp_pxy_t *pptp; + pptp_side_t *pptps; { pptp_hdr_t *hdr = (pptp_hdr_t *)pptps->pptps_buffer; switch (ntohs(hdr->pptph_type)) { case PPTP_MSGTYPE_CTL : - ippr_pptp_mctl(fin, nat, pptp, pptps); + ipf_p_pptp_mctl(fin, nat, pptp, pptps); break; default : @@ -380,11 +428,12 @@ pptp_side_t *pptps; /* * handle a complete PPTP control message */ -int ippr_pptp_mctl(fin, nat, pptp, pptps) -fr_info_t *fin; -nat_t *nat; -pptp_pxy_t *pptp; -pptp_side_t *pptps; +int +ipf_p_pptp_mctl(fin, nat, pptp, pptps) + fr_info_t *fin; + nat_t *nat; + pptp_pxy_t *pptp; + pptp_side_t *pptps; { u_short *buffer = (u_short *)(pptps->pptps_buffer); pptp_side_t *pptpo; @@ -429,7 +478,7 @@ pptp_side_t *pptps; pptps->pptps_state = PPTP_MTCTL_OUTREP; pptp->pptp_call[0] = buffer[7]; pptp->pptp_call[1] = buffer[6]; - ippr_pptp_donatstate(fin, nat, pptp); + ipf_p_pptp_donatstate(fin, nat, pptp); } break; case PPTP_MTCTL_INREQ : @@ -440,7 +489,7 @@ pptp_side_t *pptps; pptps->pptps_state = PPTP_MTCTL_INREP; pptp->pptp_call[0] = buffer[7]; pptp->pptp_call[1] = buffer[6]; - ippr_pptp_donatstate(fin, nat, pptp); + ipf_p_pptp_donatstate(fin, nat, pptp); } break; case PPTP_MTCTL_INCONNECT : @@ -468,10 +517,12 @@ pptp_side_t *pptps; * For outgoing PPTP packets. refresh timeouts for NAT & state entries, if * we can. If they have disappeared, recreate them. */ -int ippr_pptp_inout(fin, aps, nat) -fr_info_t *fin; -ap_session_t *aps; -nat_t *nat; +int +ipf_p_pptp_inout(arg, fin, aps, nat) + void *arg; + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; { pptp_pxy_t *pptp; tcphdr_t *tcp; @@ -492,7 +543,7 @@ nat_t *nat; pptp->pptp_side[rev].pptps_next = ntohl(tcp->th_seq) + 1; pptp->pptp_side[rev].pptps_nexthdr = ntohl(tcp->th_seq) + 1; } - return ippr_pptp_nextmessage(fin, nat, (pptp_pxy_t *)aps->aps_data, + return ipf_p_pptp_nextmessage(fin, nat, (pptp_pxy_t *)aps->aps_data, rev); } @@ -500,8 +551,10 @@ nat_t *nat; /* * clean up after ourselves. */ -void ippr_pptp_del(aps) -ap_session_t *aps; +void +ipf_p_pptp_del(softc, aps) + ipf_main_softc_t *softc; + ap_session_t *aps; { pptp_pxy_t *pptp; @@ -513,15 +566,15 @@ ap_session_t *aps; * *_del() is on a callback from aps_free(), from nat_delete() */ - READ_ENTER(&ipf_state); + READ_ENTER(&softc->ipf_state); if (pptp->pptp_state != NULL) { - pptp->pptp_state->is_die = fr_ticks + 1; - pptp->pptp_state->is_me = NULL; - fr_queuefront(&pptp->pptp_state->is_sti); + ipf_state_setpending(softc, pptp->pptp_state); } - RWLOCK_EXIT(&ipf_state); + RWLOCK_EXIT(&softc->ipf_state); - pptp->pptp_state = NULL; - pptp->pptp_nat = NULL; + if (pptp->pptp_nat != NULL) + ipf_nat_setpending(softc, pptp->pptp_nat); + pptp->pptp_rule->in_flags |= IPN_DELETE; + ipf_nat_rule_deref(softc, &pptp->pptp_rule); } } diff --git a/ip_proxy.c b/ip_proxy.c index 18bc4e1fce5ab..3e4decac320a7 100644 --- a/ip_proxy.c +++ b/ip_proxy.c @@ -1,7 +1,5 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1997-2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -16,7 +14,9 @@ #include <sys/param.h> #include <sys/time.h> #include <sys/file.h> -#include <sys/fcntl.h> +#if !defined(AIX) +# include <sys/fcntl.h> +#endif #if !defined(_KERNEL) && !defined(__KERNEL__) # include <stdio.h> # include <string.h> @@ -35,7 +35,8 @@ struct file; #include <sys/socket.h> #if defined(_KERNEL) # if !defined(__NetBSD__) && !defined(sun) && !defined(__osf__) && \ - !defined(__OpenBSD__) && !defined(__hpux) && !defined(__sgi) + !defined(__OpenBSD__) && !defined(__hpux) && !defined(__sgi) && \ + !defined(AIX) # include <sys/ctype.h> # endif # include <sys/systm.h> @@ -46,9 +47,6 @@ struct file; #if defined(_KERNEL) && (__FreeBSD_version >= 220000) # include <sys/filio.h> # include <sys/fcntl.h> -# if (__FreeBSD_version >= 300000) && !defined(IPFILTER_LKM) -# include "opt_ipfilter.h" -# endif #else # include <sys/ioctl.h> #endif @@ -67,7 +65,6 @@ struct file; #ifdef sun # include <net/af.h> #endif -#include <net/route.h> #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> @@ -87,199 +84,603 @@ struct file; # include <sys/malloc.h> #endif +/* END OF INCLUDES */ + #include "netinet/ip_ftp_pxy.c" +#include "netinet/ip_tftp_pxy.c" #include "netinet/ip_rcmd_pxy.c" -# include "netinet/ip_pptp_pxy.c" +#include "netinet/ip_pptp_pxy.c" #if defined(_KERNEL) # include "netinet/ip_irc_pxy.c" # include "netinet/ip_raudio_pxy.c" -# include "netinet/ip_h323_pxy.c" -# ifdef IPFILTER_PRO -# include "netinet/ip_msnrpc_pxy.c" -# endif # include "netinet/ip_netbios_pxy.c" #endif #include "netinet/ip_ipsec_pxy.c" #include "netinet/ip_rpcb_pxy.c" -/* END OF INCLUDES */ - #if !defined(lint) -static const char rcsid[] = "@(#)Id: ip_proxy.c,v 2.62.2.12 2005/03/03 14:28:24 darrenr Exp"; +static const char rcsid[] = "@(#)$Id$"; #endif -static int appr_fixseqack __P((fr_info_t *, ip_t *, ap_session_t *, int )); - #define AP_SESS_SIZE 53 -#if defined(_KERNEL) -int ipf_proxy_debug = 0; -#else -int ipf_proxy_debug = 2; -#endif -ap_session_t *ap_sess_tab[AP_SESS_SIZE]; -ap_session_t *ap_sess_list = NULL; -aproxy_t *ap_proxylist = NULL; -aproxy_t ap_proxies[] = { +static int ipf_proxy_fixseqack __P((fr_info_t *, ip_t *, ap_session_t *, int )); +static aproxy_t *ipf_proxy_create_clone __P((ipf_main_softc_t *, aproxy_t *)); + +typedef struct ipf_proxy_softc_s { + int ips_proxy_debug; + int ips_proxy_session_size; + ap_session_t **ips_sess_tab; + ap_session_t *ips_sess_list; + aproxy_t *ips_proxies; + int ips_init_run; + ipftuneable_t *ipf_proxy_tune; +} ipf_proxy_softc_t; + +static ipftuneable_t ipf_proxy_tuneables[] = { + { { (void *)offsetof(ipf_proxy_softc_t, ips_proxy_debug) }, + "proxy_debug", 0, 0x1f, + stsizeof(ipf_proxy_softc_t, ips_proxy_debug), + 0, NULL, NULL }, + { { NULL }, NULL, 0, 0, + 0, + 0, NULL, NULL} +}; + +static aproxy_t *ap_proxylist = NULL; +static aproxy_t ips_proxies[] = { #ifdef IPF_FTP_PROXY - { NULL, "ftp", (char)IPPROTO_TCP, 0, 0, ippr_ftp_init, ippr_ftp_fini, - ippr_ftp_new, NULL, ippr_ftp_in, ippr_ftp_out, NULL }, + { NULL, NULL, "ftp", (char)IPPROTO_TCP, 0, 0, 0, + ipf_p_ftp_main_load, ipf_p_ftp_main_unload, + ipf_p_ftp_soft_create, ipf_p_ftp_soft_destroy, + NULL, NULL, + ipf_p_ftp_new, ipf_p_ftp_del, ipf_p_ftp_in, ipf_p_ftp_out, NULL, + NULL, NULL, NULL, NULL }, +#endif +#ifdef IPF_TFTP_PROXY + { NULL, NULL, "tftp", (char)IPPROTO_UDP, 0, 0, 0, + ipf_p_tftp_main_load, ipf_p_tftp_main_unload, + ipf_p_tftp_soft_create, ipf_p_tftp_soft_destroy, + NULL, NULL, + ipf_p_tftp_new, ipf_p_tftp_del, + ipf_p_tftp_in, ipf_p_tftp_out, NULL, + NULL, NULL, NULL, NULL }, #endif #ifdef IPF_IRC_PROXY - { NULL, "irc", (char)IPPROTO_TCP, 0, 0, ippr_irc_init, ippr_irc_fini, - ippr_irc_new, NULL, NULL, ippr_irc_out, NULL, NULL }, + { NULL, NULL, "irc", (char)IPPROTO_TCP, 0, 0, 0, + ipf_p_irc_main_load, ipf_p_irc_main_unload, + NULL, NULL, + NULL, NULL, + ipf_p_irc_new, NULL, NULL, ipf_p_irc_out, NULL, + NULL, NULL, NULL, NULL }, #endif #ifdef IPF_RCMD_PROXY - { NULL, "rcmd", (char)IPPROTO_TCP, 0, 0, ippr_rcmd_init, ippr_rcmd_fini, - ippr_rcmd_new, NULL, ippr_rcmd_in, ippr_rcmd_out, NULL, NULL }, + { NULL, NULL, "rcmd", (char)IPPROTO_TCP, 0, 0, 0, + ipf_p_rcmd_main_load, ipf_p_rcmd_main_unload, + NULL, NULL, + NULL, NULL, + ipf_p_rcmd_new, ipf_p_rcmd_del, + ipf_p_rcmd_in, ipf_p_rcmd_out, NULL, + NULL, NULL, NULL, NULL }, #endif #ifdef IPF_RAUDIO_PROXY - { NULL, "raudio", (char)IPPROTO_TCP, 0, 0, ippr_raudio_init, ippr_raudio_fini, - ippr_raudio_new, NULL, ippr_raudio_in, ippr_raudio_out, NULL, NULL }, + { NULL, NULL, "raudio", (char)IPPROTO_TCP, 0, 0, 0, + ipf_p_raudio_main_load, ipf_p_raudio_main_unload, + NULL, NULL, + NULL, NULL, + ipf_p_raudio_new, NULL, ipf_p_raudio_in, ipf_p_raudio_out, NULL, + NULL, NULL, NULL, NULL }, #endif #ifdef IPF_MSNRPC_PROXY - { NULL, "msnrpc", (char)IPPROTO_TCP, 0, 0, ippr_msnrpc_init, ippr_msnrpc_fini, - ippr_msnrpc_new, NULL, ippr_msnrpc_in, ippr_msnrpc_out, NULL, NULL }, + { NULL, NULL, "msnrpc", (char)IPPROTO_TCP, 0, 0, 0, + ipf_p_msnrpc_init, ipf_p_msnrpc_fini, + NULL, NULL, + NULL, NULL, + ipf_p_msnrpc_new, NULL, ipf_p_msnrpc_in, ipf_p_msnrpc_out, NULL, + NULL, NULL, NULL, NULL }, #endif #ifdef IPF_NETBIOS_PROXY - { NULL, "netbios", (char)IPPROTO_UDP, 0, 0, ippr_netbios_init, ippr_netbios_fini, - NULL, NULL, NULL, ippr_netbios_out, NULL, NULL }, + { NULL, NULL, "netbios", (char)IPPROTO_UDP, 0, 0, 0, + ipf_p_netbios_main_load, ipf_p_netbios_main_unload, + NULL, NULL, + NULL, NULL, + NULL, NULL, NULL, ipf_p_netbios_out, NULL, + NULL, NULL, NULL, NULL }, #endif #ifdef IPF_IPSEC_PROXY - { NULL, "ipsec", (char)IPPROTO_UDP, 0, 0, - ippr_ipsec_init, ippr_ipsec_fini, ippr_ipsec_new, ippr_ipsec_del, - ippr_ipsec_inout, ippr_ipsec_inout, ippr_ipsec_match, NULL }, + { NULL, NULL, "ipsec", (char)IPPROTO_UDP, 0, 0, 0, + NULL, NULL, + ipf_p_ipsec_soft_create, ipf_p_ipsec_soft_destroy, + ipf_p_ipsec_soft_init, ipf_p_ipsec_soft_fini, + ipf_p_ipsec_new, ipf_p_ipsec_del, + ipf_p_ipsec_inout, ipf_p_ipsec_inout, ipf_p_ipsec_match, + NULL, NULL, NULL, NULL }, #endif -#ifdef IPF_PPTP_PROXY - { NULL, "pptp", (char)IPPROTO_TCP, 0, 0, - ippr_pptp_init, ippr_pptp_fini, ippr_pptp_new, ippr_pptp_del, - ippr_pptp_inout, ippr_pptp_inout, NULL, NULL }, +#ifdef IPF_DNS_PROXY + { NULL, NULL, "dns", (char)IPPROTO_UDP, 0, 0, 0, + NULL, NULL, + ipf_p_dns_soft_create, ipf_p_dns_soft_destroy, + NULL, NULL, + ipf_p_dns_new, ipf_p_ipsec_del, + ipf_p_dns_inout, ipf_p_dns_inout, ipf_p_dns_match, + ipf_p_dns_ctl, NULL, NULL, NULL }, #endif -#ifdef IPF_H323_PROXY - { NULL, "h323", (char)IPPROTO_TCP, 0, 0, ippr_h323_init, ippr_h323_fini, - ippr_h323_new, ippr_h323_del, ippr_h323_in, NULL, NULL }, - { NULL, "h245", (char)IPPROTO_TCP, 0, 0, NULL, NULL, - ippr_h245_new, NULL, NULL, ippr_h245_out, NULL }, +#ifdef IPF_PPTP_PROXY + { NULL, NULL, "pptp", (char)IPPROTO_TCP, 0, 0, 0, + ipf_p_pptp_main_load, ipf_p_pptp_main_unload, + NULL, NULL, + NULL, NULL, + ipf_p_pptp_new, ipf_p_pptp_del, + ipf_p_pptp_inout, ipf_p_pptp_inout, NULL, + NULL, NULL, NULL, NULL }, #endif #ifdef IPF_RPCB_PROXY -# if 0 - { NULL, "rpcbt", (char)IPPROTO_TCP, 0, 0, - ippr_rpcb_init, ippr_rpcb_fini, ippr_rpcb_new, ippr_rpcb_del, - ippr_rpcb_in, ippr_rpcb_out, NULL, NULL }, +# ifndef _KERNEL + { NULL, NULL, "rpcbt", (char)IPPROTO_TCP, 0, 0, 0, + NULL, NULL, + NULL, NULL, + NULL, NULL, + ipf_p_rpcb_new, ipf_p_rpcb_del, + ipf_p_rpcb_in, ipf_p_rpcb_out, NULL, + NULL, NULL, NULL, NULL }, # endif - { NULL, "rpcbu", (char)IPPROTO_UDP, 0, 0, - ippr_rpcb_init, ippr_rpcb_fini, ippr_rpcb_new, ippr_rpcb_del, - ippr_rpcb_in, ippr_rpcb_out, NULL, NULL }, + { NULL, NULL, "rpcbu", (char)IPPROTO_UDP, 0, 0, 0, + ipf_p_rpcb_main_load, ipf_p_rpcb_main_unload, + NULL, NULL, + NULL, NULL, + ipf_p_rpcb_new, ipf_p_rpcb_del, + ipf_p_rpcb_in, ipf_p_rpcb_out, NULL, + NULL, NULL, NULL, NULL }, #endif - { NULL, "", '\0', 0, 0, NULL, NULL, NULL, NULL } + { NULL, NULL, "", '\0', 0, 0, 0, + NULL, NULL, + NULL, NULL, + NULL, NULL, + NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL } }; -/* - * Dynamically add a new kernel proxy. Ensure that it is unique in the - * collection compiled in and dynamically added. - */ -int appr_add(ap) -aproxy_t *ap; + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_proxy_main_load */ +/* Returns: int - 0 == success, else failure. */ +/* Parameters: Nil */ +/* */ +/* Initialise hook for kernel application proxies. */ +/* Call the initialise routine for all the compiled in kernel proxies. */ +/* ------------------------------------------------------------------------ */ +int +ipf_proxy_main_load() +{ + aproxy_t *ap; + + for (ap = ips_proxies; ap->apr_p; ap++) { + if (ap->apr_load != NULL) + (*ap->apr_load)(); + } + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_proxy_main_unload */ +/* Returns: int - 0 == success, else failure. */ +/* Parameters: Nil */ +/* */ +/* Unload hook for kernel application proxies. */ +/* Call the finialise routine for all the compiled in kernel proxies. */ +/* ------------------------------------------------------------------------ */ +int +ipf_proxy_main_unload() +{ + aproxy_t *ap; + + for (ap = ips_proxies; ap->apr_p; ap++) + if (ap->apr_unload != NULL) + (*ap->apr_unload)(); + for (ap = ap_proxylist; ap; ap = ap->apr_next) + if (ap->apr_unload != NULL) + (*ap->apr_unload)(); + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_proxy_soft_create */ +/* Returns: void * - */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* */ +/* Build the structure to hold all of the run time data to support proxies. */ +/* ------------------------------------------------------------------------ */ +void * +ipf_proxy_soft_create(softc) + ipf_main_softc_t *softc; { + ipf_proxy_softc_t *softp; + aproxy_t *last; + aproxy_t *apn; + aproxy_t *ap; + + KMALLOC(softp, ipf_proxy_softc_t *); + if (softp == NULL) + return softp; + + bzero((char *)softp, sizeof(*softp)); + +#if defined(_KERNEL) + softp->ips_proxy_debug = 0; +#else + softp->ips_proxy_debug = 2; +#endif + softp->ips_proxy_session_size = AP_SESS_SIZE; + + softp->ipf_proxy_tune = ipf_tune_array_copy(softp, + sizeof(ipf_proxy_tuneables), + ipf_proxy_tuneables); + if (softp->ipf_proxy_tune == NULL) { + ipf_proxy_soft_destroy(softc, softp); + return NULL; + } + if (ipf_tune_array_link(softc, softp->ipf_proxy_tune) == -1) { + ipf_proxy_soft_destroy(softc, softp); + return NULL; + } + + last = NULL; + for (ap = ips_proxies; ap->apr_p; ap++) { + apn = ipf_proxy_create_clone(softc, ap); + if (apn == NULL) + goto failed; + if (last != NULL) + last->apr_next = apn; + else + softp->ips_proxies = apn; + last = apn; + } + for (ap = ips_proxies; ap != NULL; ap = ap->apr_next) { + apn = ipf_proxy_create_clone(softc, ap); + if (apn == NULL) + goto failed; + if (last != NULL) + last->apr_next = apn; + else + softp->ips_proxies = apn; + last = apn; + } + + return softp; +failed: + ipf_proxy_soft_destroy(softc, softp); + return NULL; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_proxy_soft_create */ +/* Returns: void * - */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* orig(I) - pointer to proxy definition to copy */ +/* */ +/* This function clones a proxy definition given by orig and returns a */ +/* a pointer to that copy. */ +/* ------------------------------------------------------------------------ */ +static aproxy_t * +ipf_proxy_create_clone(softc, orig) + ipf_main_softc_t *softc; + aproxy_t *orig; +{ + aproxy_t *apn; + + KMALLOC(apn, aproxy_t *); + if (apn == NULL) + return NULL; + + bcopy((char *)orig, (char *)apn, sizeof(*apn)); + apn->apr_next = NULL; + apn->apr_soft = NULL; + + if (apn->apr_create != NULL) { + apn->apr_soft = (*apn->apr_create)(softc); + if (apn->apr_soft == NULL) { + KFREE(apn); + return NULL; + } + } + + apn->apr_parent = orig; + orig->apr_clones++; + + return apn; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_proxy_soft_create */ +/* Returns: int - 0 == success, else failure. */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to proxy contect data */ +/* */ +/* Initialise the proxy context and walk through each of the proxies and */ +/* call its initialisation function. This allows for proxies to do any */ +/* local setup prior to actual use. */ +/* ------------------------------------------------------------------------ */ +int +ipf_proxy_soft_init(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_proxy_softc_t *softp; + aproxy_t *ap; + u_int size; + int err; + + softp = arg; + size = softp->ips_proxy_session_size * sizeof(ap_session_t *); + + KMALLOCS(softp->ips_sess_tab, ap_session_t **, size); + + if (softp->ips_sess_tab == NULL) + return -1; + + bzero(softp->ips_sess_tab, size); + + for (ap = softp->ips_proxies; ap != NULL; ap = ap->apr_next) { + if (ap->apr_init != NULL) { + err = (*ap->apr_init)(softc, ap->apr_soft); + if (err != 0) + return -2; + } + } + softp->ips_init_run = 1; + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_proxy_soft_create */ +/* Returns: int - 0 == success, else failure. */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to proxy contect data */ +/* */ +/* This function should always succeed. It is responsible for ensuring that */ +/* the proxy context can be safely called when ipf_proxy_soft_destroy is */ +/* called and suring all of the proxies have similarly been instructed. */ +/* ------------------------------------------------------------------------ */ +int +ipf_proxy_soft_fini(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_proxy_softc_t *softp = arg; + aproxy_t *ap; + + for (ap = softp->ips_proxies; ap != NULL; ap = ap->apr_next) { + if (ap->apr_fini != NULL) { + (*ap->apr_fini)(softc, ap->apr_soft); + } + } + + if (softp->ips_sess_tab != NULL) { + KFREES(softp->ips_sess_tab, + softp->ips_proxy_session_size * sizeof(ap_session_t *)); + softp->ips_sess_tab = NULL; + } + softp->ips_init_run = 0; + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_proxy_soft_destroy */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to proxy contect data */ +/* */ +/* Free up all of the local data structures allocated during creation. */ +/* ------------------------------------------------------------------------ */ +void +ipf_proxy_soft_destroy(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_proxy_softc_t *softp = arg; + aproxy_t *ap; + + while ((ap = softp->ips_proxies) != NULL) { + softp->ips_proxies = ap->apr_next; + if (ap->apr_destroy != NULL) + (*ap->apr_destroy)(softc, ap->apr_soft); + ap->apr_parent->apr_clones--; + KFREE(ap); + } + + if (softp->ipf_proxy_tune != NULL) { + ipf_tune_array_unlink(softc, softp->ipf_proxy_tune); + KFREES(softp->ipf_proxy_tune, sizeof(ipf_proxy_tuneables)); + softp->ipf_proxy_tune = NULL; + } + + KFREE(softp); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_proxy_flush */ +/* Returns: Nil */ +/* Parameters: arg(I) - pointer to proxy contect data */ +/* how(I) - indicates the type of flush operation */ +/* */ +/* Walk through all of the proxies and pass on the flush command as either */ +/* a flush or a clear. */ +/* ------------------------------------------------------------------------ */ +void +ipf_proxy_flush(arg, how) + void *arg; + int how; +{ + ipf_proxy_softc_t *softp = arg; + aproxy_t *ap; + + switch (how) + { + case 0 : + for (ap = softp->ips_proxies; ap; ap = ap->apr_next) + if (ap->apr_flush != NULL) + (*ap->apr_flush)(ap, how); + break; + case 1 : + for (ap = softp->ips_proxies; ap; ap = ap->apr_next) + if (ap->apr_clear != NULL) + (*ap->apr_clear)(ap); + break; + default : + break; + } +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_proxy_add */ +/* Returns: int - 0 == success, else failure. */ +/* Parameters: ap(I) - pointer to proxy structure */ +/* */ +/* Dynamically add a new kernel proxy. Ensure that it is unique in the */ +/* collection compiled in and dynamically added. */ +/* ------------------------------------------------------------------------ */ +int +ipf_proxy_add(arg, ap) + void *arg; + aproxy_t *ap; +{ + ipf_proxy_softc_t *softp = arg; + aproxy_t *a; - for (a = ap_proxies; a->apr_p; a++) + for (a = ips_proxies; a->apr_p; a++) if ((a->apr_p == ap->apr_p) && !strncmp(a->apr_label, ap->apr_label, sizeof(ap->apr_label))) { - if (ipf_proxy_debug > 1) - printf("appr_add: %s/%d already present (B)\n", + if (softp->ips_proxy_debug & 0x01) + printf("ipf_proxy_add: %s/%d present (B)\n", a->apr_label, a->apr_p); return -1; } - for (a = ap_proxylist; a->apr_p; a = a->apr_next) + for (a = ap_proxylist; (a != NULL); a = a->apr_next) if ((a->apr_p == ap->apr_p) && !strncmp(a->apr_label, ap->apr_label, sizeof(ap->apr_label))) { - if (ipf_proxy_debug > 1) - printf("appr_add: %s/%d already present (D)\n", + if (softp->ips_proxy_debug & 0x01) + printf("ipf_proxy_add: %s/%d present (D)\n", a->apr_label, a->apr_p); return -1; } ap->apr_next = ap_proxylist; ap_proxylist = ap; - if (ap->apr_init != NULL) - return (*ap->apr_init)(); + if (ap->apr_load != NULL) + (*ap->apr_load)(); return 0; } -/* - * Check to see if the proxy this control request has come through for - * exists, and if it does and it has a control function then invoke that - * control function. - */ -int appr_ctl(ctl) -ap_ctl_t *ctl; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_proxy_ctl */ +/* Returns: int - 0 == success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to proxy context */ +/* ctl(I) - pointer to proxy control structure */ +/* */ +/* Check to see if the proxy this control request has come through for */ +/* exists, and if it does and it has a control function then invoke that */ +/* control function. */ +/* ------------------------------------------------------------------------ */ +int +ipf_proxy_ctl(softc, arg, ctl) + ipf_main_softc_t *softc; + void *arg; + ap_ctl_t *ctl; { + ipf_proxy_softc_t *softp = arg; aproxy_t *a; int error; - a = appr_lookup(ctl->apc_p, ctl->apc_label); + a = ipf_proxy_lookup(arg, ctl->apc_p, ctl->apc_label); if (a == NULL) { - if (ipf_proxy_debug > 1) - printf("appr_ctl: can't find %s/%d\n", + if (softp->ips_proxy_debug & 0x01) + printf("ipf_proxy_ctl: can't find %s/%d\n", ctl->apc_label, ctl->apc_p); + IPFERROR(80001); error = ESRCH; } else if (a->apr_ctl == NULL) { - if (ipf_proxy_debug > 1) - printf("appr_ctl: no ctl function for %s/%d\n", + if (softp->ips_proxy_debug & 0x01) + printf("ipf_proxy_ctl: no ctl function for %s/%d\n", ctl->apc_label, ctl->apc_p); + IPFERROR(80002); error = ENXIO; } else { - error = (*a->apr_ctl)(a, ctl); - if ((error != 0) && (ipf_proxy_debug > 1)) - printf("appr_ctl: %s/%d ctl error %d\n", + error = (*a->apr_ctl)(softc, a->apr_soft, ctl); + if ((error != 0) && (softp->ips_proxy_debug & 0x02)) + printf("ipf_proxy_ctl: %s/%d ctl error %d\n", a->apr_label, a->apr_p, error); } return error; } -/* - * Delete a proxy that has been added dynamically from those available. - * If it is in use, return 1 (do not destroy NOW), not in use 0 or -1 - * if it cannot be matched. - */ -int appr_del(ap) -aproxy_t *ap; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_proxy_del */ +/* Returns: int - 0 == success, else failure. */ +/* Parameters: ap(I) - pointer to proxy structure */ +/* */ +/* Delete a proxy that has been added dynamically from those available. */ +/* If it is in use, return 1 (do not destroy NOW), not in use 0 or -1 */ +/* if it cannot be matched. */ +/* ------------------------------------------------------------------------ */ +int +ipf_proxy_del(ap) + aproxy_t *ap; { aproxy_t *a, **app; - for (app = &ap_proxylist; ((a = *app) != NULL); app = &a->apr_next) + for (app = &ap_proxylist; ((a = *app) != NULL); app = &a->apr_next) { if (a == ap) { a->apr_flags |= APR_DELETE; - *app = a->apr_next; - if (ap->apr_ref != 0) { - if (ipf_proxy_debug > 2) - printf("appr_del: orphaning %s/%d\n", - ap->apr_label, ap->apr_p); - return 1; + if (ap->apr_ref == 0 && ap->apr_clones == 0) { + *app = a->apr_next; + return 0; } - return 0; + return 1; } - if (ipf_proxy_debug > 1) - printf("appr_del: proxy %lx not found\n", (u_long)ap); + } + return -1; } -/* - * Return 1 if the packet is a good match against a proxy, else 0. - */ -int appr_ok(fin, tcp, nat) -fr_info_t *fin; -tcphdr_t *tcp; -ipnat_t *nat; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_proxy_ok */ +/* Returns: int - 1 == good match else not. */ +/* Parameters: fin(I) - pointer to packet information */ +/* tcp(I) - pointer to TCP/UDP header */ +/* nat(I) - pointer to current NAT session */ +/* */ +/* This function extends the NAT matching to ensure that a packet that has */ +/* arrived matches the proxy information attached to the NAT rule. Notably, */ +/* if the proxy is scheduled to be deleted then packets will not match the */ +/* rule even if the rule is still active. */ +/* ------------------------------------------------------------------------ */ +int +ipf_proxy_ok(fin, tcp, np) + fr_info_t *fin; + tcphdr_t *tcp; + ipnat_t *np; { - aproxy_t *apr = nat->in_apr; - u_short dport = nat->in_dport; + aproxy_t *apr = np->in_apr; + u_short dport = np->in_odport; if ((apr == NULL) || (apr->apr_flags & APR_DELETE) || (fin->fin_p != apr->apr_p)) @@ -290,10 +691,23 @@ ipnat_t *nat; } -int appr_ioctl(data, cmd, mode) -caddr_t data; -ioctlcmd_t cmd; -int mode; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_proxy_ioctl */ +/* Returns: int - 0 == success, else error */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* data(I) - pointer to ioctl data */ +/* cmd(I) - ioctl command */ +/* mode(I) - mode bits for device */ +/* ctx(I) - pointer to context information */ +/* */ +/* ------------------------------------------------------------------------ */ +int +ipf_proxy_ioctl(softc, data, cmd, mode, ctx) + ipf_main_softc_t *softc; + caddr_t data; + ioctlcmd_t cmd; + int mode; + void *ctx; { ap_ctl_t ctl; caddr_t ptr; @@ -304,15 +718,19 @@ int mode; switch (cmd) { case SIOCPROXY : - BCOPYIN(data, &ctl, sizeof(ctl)); + error = ipf_inobj(softc, data, NULL, &ctl, IPFOBJ_PROXYCTL); + if (error != 0) { + return error; + } ptr = NULL; if (ctl.apc_dsize > 0) { KMALLOCS(ptr, caddr_t, ctl.apc_dsize); - if (ptr == NULL) + if (ptr == NULL) { + IPFERROR(80003); error = ENOMEM; - else { - error = copyinptr(ctl.apc_data, ptr, + } else { + error = copyinptr(softc, ctl.apc_data, ptr, ctl.apc_dsize); if (error == 0) ctl.apc_data = ptr; @@ -323,50 +741,61 @@ int mode; } if (error == 0) - error = appr_ctl(&ctl); + error = ipf_proxy_ctl(softc, softc->ipf_proxy_soft, + &ctl); - if ((ctl.apc_dsize > 0) && (ptr != NULL) && - (ctl.apc_data == ptr)) { + if ((error != 0) && (ptr != NULL)) { KFREES(ptr, ctl.apc_dsize); } break; default : + IPFERROR(80004); error = EINVAL; } return error; } -/* - * If a proxy has a match function, call that to do extended packet - * matching. - */ -int appr_match(fin, nat) -fr_info_t *fin; -nat_t *nat; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_proxy_match */ +/* Returns: int - 0 == success, else error */ +/* Parameters: fin(I) - pointer to packet information */ +/* nat(I) - pointer to current NAT session */ +/* */ +/* If a proxy has a match function, call that to do extended packet */ +/* matching. Whilst other parts of the NAT code are rather lenient when it */ +/* comes to the quality of the packet that it will transform, the proxy */ +/* matching is not because they need to work with data, not just headers. */ +/* ------------------------------------------------------------------------ */ +int +ipf_proxy_match(fin, nat) + fr_info_t *fin; + nat_t *nat; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_proxy_softc_t *softp = softc->ipf_proxy_soft; aproxy_t *apr; ipnat_t *ipn; int result; ipn = nat->nat_ptr; - if (ipf_proxy_debug > 8) - printf("appr_match(%lx,%lx) aps %lx ptr %lx\n", + if (softp->ips_proxy_debug & 0x04) + printf("ipf_proxy_match(%lx,%lx) aps %lx ptr %lx\n", (u_long)fin, (u_long)nat, (u_long)nat->nat_aps, (u_long)ipn); if ((fin->fin_flx & (FI_SHORT|FI_BAD)) != 0) { - if (ipf_proxy_debug > 0) - printf("appr_match: flx 0x%x (BAD|SHORT)\n", + if (softp->ips_proxy_debug & 0x08) + printf("ipf_proxy_match: flx 0x%x (BAD|SHORT)\n", fin->fin_flx); return -1; } apr = ipn->in_apr; if ((apr == NULL) || (apr->apr_flags & APR_DELETE)) { - if (ipf_proxy_debug > 0) - printf("appr_match:apr %lx apr_flags 0x%x\n", + if (softp->ips_proxy_debug & 0x08) + printf("ipf_proxy_match:apr %lx apr_flags 0x%x\n", (u_long)apr, apr ? apr->apr_flags : 0); return -1; } @@ -374,8 +803,8 @@ nat_t *nat; if (apr->apr_match != NULL) { result = (*apr->apr_match)(fin, nat->nat_aps, nat); if (result != 0) { - if (ipf_proxy_debug > 4) - printf("appr_match: result %d\n", result); + if (softp->ips_proxy_debug & 0x08) + printf("ipf_proxy_match: result %d\n", result); return -1; } } @@ -383,24 +812,32 @@ nat_t *nat; } -/* - * Allocate a new application proxy structure and fill it in with the - * relevant details. call the init function once complete, prior to - * returning. - */ -int appr_new(fin, nat) -fr_info_t *fin; -nat_t *nat; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_proxy_new */ +/* Returns: int - 0 == success, else error */ +/* Parameters: fin(I) - pointer to packet information */ +/* nat(I) - pointer to current NAT session */ +/* */ +/* Allocate a new application proxy structure and fill it in with the */ +/* relevant details. call the init function once complete, prior to */ +/* returning. */ +/* ------------------------------------------------------------------------ */ +int +ipf_proxy_new(fin, nat) + fr_info_t *fin; + nat_t *nat; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_proxy_softc_t *softp = softc->ipf_proxy_soft; register ap_session_t *aps; aproxy_t *apr; - if (ipf_proxy_debug > 8) - printf("appr_new(%lx,%lx) \n", (u_long)fin, (u_long)nat); + if (softp->ips_proxy_debug & 0x04) + printf("ipf_proxy_new(%lx,%lx) \n", (u_long)fin, (u_long)nat); if ((nat->nat_ptr == NULL) || (nat->nat_aps != NULL)) { - if (ipf_proxy_debug > 0) - printf("appr_new: nat_ptr %lx nat_aps %lx\n", + if (softp->ips_proxy_debug & 0x08) + printf("ipf_proxy_new: nat_ptr %lx nat_aps %lx\n", (u_long)nat->nat_ptr, (u_long)nat->nat_aps); return -1; } @@ -409,65 +846,71 @@ nat_t *nat; if ((apr->apr_flags & APR_DELETE) || (fin->fin_p != apr->apr_p)) { - if (ipf_proxy_debug > 2) - printf("appr_new: apr_flags 0x%x p %d/%d\n", + if (softp->ips_proxy_debug & 0x08) + printf("ipf_proxy_new: apr_flags 0x%x p %d/%d\n", apr->apr_flags, fin->fin_p, apr->apr_p); return -1; } KMALLOC(aps, ap_session_t *); if (!aps) { - if (ipf_proxy_debug > 0) - printf("appr_new: malloc failed (%lu)\n", + if (softp->ips_proxy_debug & 0x08) + printf("ipf_proxy_new: malloc failed (%lu)\n", (u_long)sizeof(ap_session_t)); return -1; } bzero((char *)aps, sizeof(*aps)); - aps->aps_p = fin->fin_p; aps->aps_data = NULL; aps->aps_apr = apr; aps->aps_psiz = 0; if (apr->apr_new != NULL) - if ((*apr->apr_new)(fin, aps, nat) == -1) { + if ((*apr->apr_new)(apr->apr_soft, fin, aps, nat) == -1) { if ((aps->aps_data != NULL) && (aps->aps_psiz != 0)) { KFREES(aps->aps_data, aps->aps_psiz); } KFREE(aps); - if (ipf_proxy_debug > 2) - printf("appr_new: new(%lx) failed\n", + if (softp->ips_proxy_debug & 0x08) + printf("ipf_proxy_new: new(%lx) failed\n", (u_long)apr->apr_new); return -1; } aps->aps_nat = nat; - aps->aps_next = ap_sess_list; - ap_sess_list = aps; + aps->aps_next = softp->ips_sess_list; + softp->ips_sess_list = aps; nat->nat_aps = aps; return 0; } -/* - * Check to see if a packet should be passed through an active proxy routine - * if one has been setup for it. We don't need to check the checksum here if - * IPFILTER_CKSUM is defined because if it is, a failed check causes FI_BAD - * to be set. - */ -int appr_check(fin, nat) -fr_info_t *fin; -nat_t *nat; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_proxy_check */ +/* Returns: int - -1 == error, 0 == success */ +/* Parameters: fin(I) - pointer to packet information */ +/* nat(I) - pointer to current NAT session */ +/* */ +/* Check to see if a packet should be passed through an active proxy */ +/* routine if one has been setup for it. We don't need to check the */ +/* checksum here if IPFILTER_CKSUM is defined because if it is, a failed */ +/* check causes FI_BAD to be set. */ +/* ------------------------------------------------------------------------ */ +int +ipf_proxy_check(fin, nat) + fr_info_t *fin; + nat_t *nat; { -#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) -# if defined(ICK_VALID) + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_proxy_softc_t *softp = softc->ipf_proxy_soft; +#if SOLARIS && defined(_KERNEL) && defined(ICK_VALID) mb_t *m; -# endif - int dosum = 1; #endif tcphdr_t *tcp = NULL; udphdr_t *udp = NULL; ap_session_t *aps; aproxy_t *apr; + short adjlen; + int dosum; ip_t *ip; short rv; int err; @@ -476,55 +919,54 @@ nat_t *nat; #endif if (fin->fin_flx & FI_BAD) { - if (ipf_proxy_debug > 0) - printf("appr_check: flx 0x%x (BAD)\n", fin->fin_flx); + if (softp->ips_proxy_debug & 0x08) + printf("ipf_proxy_check: flx 0x%x (BAD)\n", + fin->fin_flx); return -1; } #ifndef IPFILTER_CKSUM - if ((fin->fin_out == 0) && (fr_checkl4sum(fin) == -1)) { - if (ipf_proxy_debug > 0) - printf("appr_check: l4 checksum failure %d\n", + if ((fin->fin_out == 0) && (ipf_checkl4sum(fin) == -1)) { + if (softp->ips_proxy_debug & 0x08) + printf("ipf_proxy_check: l4 checksum failure %d\n", fin->fin_p); if (fin->fin_p == IPPROTO_TCP) - frstats[fin->fin_out].fr_tcpbad++; + softc->ipf_stats[fin->fin_out].fr_tcpbad++; return -1; } #endif aps = nat->nat_aps; - if ((aps != NULL) && (aps->aps_p == fin->fin_p)) { + if (aps != NULL) { /* * If there is data in this packet to be proxied then try and * get it all into the one buffer, else drop it. */ #if defined(MENTAT) || defined(HAVE_M_PULLDOWN) if ((fin->fin_dlen > 0) && !(fin->fin_flx & FI_COALESCE)) - if (fr_coalesce(fin) == -1) { - if (ipf_proxy_debug > 0) - printf("appr_check: fr_coalesce failed %x\n", fin->fin_flx); + if (ipf_coalesce(fin) == -1) { + if (softp->ips_proxy_debug & 0x08) + printf("ipf_proxy_check: %s %x\n", + "coalesce failed", fin->fin_flx); return -1; } #endif ip = fin->fin_ip; + if (fin->fin_cksum > FI_CK_SUMOK) + dosum = 0; + else + dosum = 1; switch (fin->fin_p) { case IPPROTO_TCP : tcp = (tcphdr_t *)fin->fin_dp; - -#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) && defined(ICK_VALID) +#if SOLARIS && defined(_KERNEL) && defined(ICK_VALID) m = fin->fin_qfm; if (dohwcksum && (m->b_ick_flag == ICK_VALID)) dosum = 0; #endif - /* - * Don't bother the proxy with these...or in fact, - * should we free up proxy stuff when seen? - */ - if ((fin->fin_tcpf & TH_RST) != 0) - break; - /*FALLTHROUGH*/ + break; case IPPROTO_UDP : udp = (udphdr_t *)fin->fin_dp; break; @@ -536,22 +978,24 @@ nat_t *nat; err = 0; if (fin->fin_out != 0) { if (apr->apr_outpkt != NULL) - err = (*apr->apr_outpkt)(fin, aps, nat); + err = (*apr->apr_outpkt)(apr->apr_soft, fin, + aps, nat); } else { if (apr->apr_inpkt != NULL) - err = (*apr->apr_inpkt)(fin, aps, nat); + err = (*apr->apr_inpkt)(apr->apr_soft, fin, + aps, nat); } rv = APR_EXIT(err); - if (((ipf_proxy_debug > 0) && (rv != 0)) || - (ipf_proxy_debug > 8)) - printf("appr_check: out %d err %x rv %d\n", + if (((softp->ips_proxy_debug & 0x08) && (rv != 0)) || + (softp->ips_proxy_debug & 0x04)) + printf("ipf_proxy_check: out %d err %x rv %d\n", fin->fin_out, err, rv); if (rv == 1) return -1; if (rv == 2) { - appr_free(apr); + ipf_proxy_deref(apr); nat->nat_aps = NULL; return -1; } @@ -561,16 +1005,17 @@ nat_t *nat; * so we need to recalculate the header checksums for the * packet. */ + adjlen = APR_INC(err); #if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) - if (err != 0) { - short adjlen = err & 0xffff; - - s1 = LONG_SUM(ip->ip_len - adjlen); - s2 = LONG_SUM(ip->ip_len); - CALC_SUMD(s1, s2, sd); - fix_outcksum(fin, &ip->ip_sum, sd); - } + s1 = LONG_SUM(fin->fin_plen - adjlen); + s2 = LONG_SUM(fin->fin_plen); + CALC_SUMD(s1, s2, sd); + if ((err != 0) && (fin->fin_cksum < FI_CK_L4PART) && + fin->fin_v == 4) + ipf_fix_outcksum(0, &ip->ip_sum, sd, 0); #endif + if (fin->fin_flx & FI_DOCKSUM) + dosum = 1; /* * For TCP packets, we may need to adjust the sequence and @@ -582,24 +1027,24 @@ nat_t *nat; * changed or not. */ if (tcp != NULL) { - err = appr_fixseqack(fin, ip, aps, APR_INC(err)); -#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) - if (dosum) - tcp->th_sum = fr_cksum(fin->fin_qfm, ip, + err = ipf_proxy_fixseqack(fin, ip, aps, adjlen); + if (fin->fin_cksum == FI_CK_L4PART) { + u_short sum = ntohs(tcp->th_sum); + sum += adjlen; + tcp->th_sum = htons(sum); + } else if (fin->fin_cksum < FI_CK_L4PART) { + tcp->th_sum = fr_cksum(fin, ip, IPPROTO_TCP, tcp); -#else - tcp->th_sum = fr_cksum(fin->fin_m, ip, - IPPROTO_TCP, tcp); -#endif + } } else if ((udp != NULL) && (udp->uh_sum != 0)) { -#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) - if (dosum) - udp->uh_sum = fr_cksum(fin->fin_qfm, ip, + if (fin->fin_cksum == FI_CK_L4PART) { + u_short sum = ntohs(udp->uh_sum); + sum += adjlen; + udp->uh_sum = htons(sum); + } else if (dosum) { + udp->uh_sum = fr_cksum(fin, ip, IPPROTO_UDP, udp); -#else - udp->uh_sum = fr_cksum(fin->fin_m, ip, - IPPROTO_UDP, udp); -#endif + } } aps->aps_bytes += fin->fin_plen; aps->aps_pkts++; @@ -609,54 +1054,78 @@ nat_t *nat; } -/* - * Search for an proxy by the protocol it is being used with and its name. - */ -aproxy_t *appr_lookup(pr, name) -u_int pr; -char *name; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_proxy_lookup */ +/* Returns: int - -1 == error, 0 == success */ +/* Parameters: arg(I) - pointer to proxy context information */ +/* pr(I) - protocol number for proxy */ +/* name(I) - proxy name */ +/* */ +/* Search for an proxy by the protocol it is being used with and its name. */ +/* ------------------------------------------------------------------------ */ +aproxy_t * +ipf_proxy_lookup(arg, pr, name) + void *arg; + u_int pr; + char *name; { + ipf_proxy_softc_t *softp = arg; aproxy_t *ap; - if (ipf_proxy_debug > 8) - printf("appr_lookup(%d,%s)\n", pr, name); + if (softp->ips_proxy_debug & 0x04) + printf("ipf_proxy_lookup(%d,%s)\n", pr, name); - for (ap = ap_proxies; ap->apr_p; ap++) + for (ap = softp->ips_proxies; ap != NULL; ap = ap->apr_next) if ((ap->apr_p == pr) && !strncmp(name, ap->apr_label, sizeof(ap->apr_label))) { ap->apr_ref++; return ap; } - for (ap = ap_proxylist; ap; ap = ap->apr_next) - if ((ap->apr_p == pr) && - !strncmp(name, ap->apr_label, sizeof(ap->apr_label))) { - ap->apr_ref++; - return ap; - } - if (ipf_proxy_debug > 2) - printf("appr_lookup: failed for %d/%s\n", pr, name); + if (softp->ips_proxy_debug & 0x08) + printf("ipf_proxy_lookup: failed for %d/%s\n", pr, name); return NULL; } -void appr_free(ap) -aproxy_t *ap; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_proxy_deref */ +/* Returns: Nil */ +/* Parameters: ap(I) - pointer to proxy structure */ +/* */ +/* Drop the reference counter associated with the proxy. */ +/* ------------------------------------------------------------------------ */ +void +ipf_proxy_deref(ap) + aproxy_t *ap; { ap->apr_ref--; } -void aps_free(aps) -ap_session_t *aps; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_proxy_free */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* aps(I) - pointer to current proxy session */ +/* Locks Held: ipf_nat_new, ipf_nat(W) */ +/* */ +/* Free up proxy session information allocated to be used with a NAT */ +/* session. */ +/* ------------------------------------------------------------------------ */ +void +ipf_proxy_free(softc, aps) + ipf_main_softc_t *softc; + ap_session_t *aps; { + ipf_proxy_softc_t *softp = softc->ipf_proxy_soft; ap_session_t *a, **ap; aproxy_t *apr; if (!aps) return; - for (ap = &ap_sess_list; ((a = *ap) != NULL); ap = &a->aps_next) + for (ap = &softp->ips_sess_list; ((a = *ap) != NULL); ap = &a->aps_next) if (a == aps) { *ap = a->aps_next; break; @@ -664,7 +1133,7 @@ ap_session_t *aps; apr = aps->aps_apr; if ((apr != NULL) && (apr->apr_del != NULL)) - (*apr->apr_del)(aps); + (*apr->apr_del)(softc, aps); if ((aps->aps_data != NULL) && (aps->aps_psiz != 0)) KFREES(aps->aps_data, aps->aps_psiz); @@ -672,15 +1141,28 @@ ap_session_t *aps; } -/* - * returns 2 if ack or seq number in TCP header is changed, returns 0 otherwise - */ -static int appr_fixseqack(fin, ip, aps, inc) -fr_info_t *fin; -ip_t *ip; -ap_session_t *aps; -int inc; +/* ------------------------------------------------------------------------ */ +/* Function: ipf_proxy_fixseqack */ +/* Returns: int - 2 if TCP ack/seq is changed, else 0 */ +/* Parameters: fin(I) - pointer to packet information */ +/* ip(I) - pointer to IP header */ +/* nat(I) - pointer to current NAT session */ +/* inc(I) - delta to apply to TCP sequence numbering */ +/* */ +/* Adjust the TCP sequence/acknowledge numbers in the TCP header based on */ +/* whether or not the new header is past the point at which an adjustment */ +/* occurred. This might happen because of (say) an FTP string being changed */ +/* and the new string being a different length to the old. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_proxy_fixseqack(fin, ip, aps, inc) + fr_info_t *fin; + ip_t *ip; + ap_session_t *aps; + int inc; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_proxy_softc_t *softp = softc->ipf_proxy_soft; int sel, ch = 0, out, nlen; u_32_t seq1, seq2; tcphdr_t *tcp; @@ -691,8 +1173,8 @@ int inc; /* * ip_len has already been adjusted by 'inc'. */ - nlen = ip->ip_len; - nlen -= (IP_HL(ip) << 2) + (TCP_OFF(tcp) << 2); + nlen = fin->fin_dlen; + nlen -= (TCP_OFF(tcp) << 2); inc2 = inc; inc = (int)inc2; @@ -704,7 +1186,7 @@ int inc; /* switch to other set ? */ if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) && (seq1 > aps->aps_seqmin[!sel])) { - if (ipf_proxy_debug > 7) + if (softp->ips_proxy_debug & 0x10) printf("proxy out switch set seq %d -> %d %x > %x\n", sel, !sel, seq1, aps->aps_seqmin[!sel]); @@ -724,7 +1206,7 @@ int inc; if (inc && (seq1 > aps->aps_seqmin[!sel])) { aps->aps_seqmin[sel] = seq1 + nlen - 1; aps->aps_seqoff[sel] = aps->aps_seqoff[sel] + inc; - if (ipf_proxy_debug > 7) + if (softp->ips_proxy_debug & 0x10) printf("proxy seq set %d at %x to %d + %d\n", sel, aps->aps_seqmin[sel], aps->aps_seqoff[sel], inc); @@ -738,7 +1220,7 @@ int inc; /* switch to other set ? */ if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) && (seq1 > aps->aps_ackmin[!sel])) { - if (ipf_proxy_debug > 7) + if (softp->ips_proxy_debug & 0x10) printf("proxy out switch set ack %d -> %d %x > %x\n", sel, !sel, seq1, aps->aps_ackmin[!sel]); @@ -757,7 +1239,7 @@ int inc; /* switch to other set ? */ if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) && (seq1 > aps->aps_ackmin[!sel])) { - if (ipf_proxy_debug > 7) + if (softp->ips_proxy_debug & 0x10) printf("proxy in switch set ack %d -> %d %x > %x\n", sel, !sel, seq1, aps->aps_ackmin[!sel]); sel = aps->aps_sel[out] = !sel; @@ -777,7 +1259,7 @@ int inc; aps->aps_ackmin[!sel] = seq1 + nlen - 1; aps->aps_ackoff[!sel] = aps->aps_ackoff[sel] + inc; - if (ipf_proxy_debug > 7) + if (softp->ips_proxy_debug & 0x10) printf("proxy ack set %d at %x to %d + %d\n", !sel, aps->aps_seqmin[!sel], aps->aps_seqoff[sel], inc); @@ -791,14 +1273,14 @@ int inc; /* switch to other set ? */ if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) && (seq1 > aps->aps_seqmin[!sel])) { - if (ipf_proxy_debug > 7) + if (softp->ips_proxy_debug & 0x10) printf("proxy in switch set seq %d -> %d %x > %x\n", sel, !sel, seq1, aps->aps_seqmin[!sel]); sel = aps->aps_sel[1 - out] = !sel; } if (aps->aps_seqoff[sel] != 0) { - if (ipf_proxy_debug > 7) + if (softp->ips_proxy_debug & 0x10) printf("sel %d seqoff %d seq1 %x seqmin %x\n", sel, aps->aps_seqoff[sel], seq1, aps->aps_seqmin[sel]); @@ -810,45 +1292,175 @@ int inc; } } - if (ipf_proxy_debug > 8) - printf("appr_fixseqack: seq %x ack %x\n", - ntohl(tcp->th_seq), ntohl(tcp->th_ack)); + if (softp->ips_proxy_debug & 0x10) + printf("ipf_proxy_fixseqack: seq %u ack %u\n", + (u_32_t)ntohl(tcp->th_seq), (u_32_t)ntohl(tcp->th_ack)); return ch ? 2 : 0; } -/* - * Initialise hook for kernel application proxies. - * Call the initialise routine for all the compiled in kernel proxies. - */ -int appr_init() +/* ------------------------------------------------------------------------ */ +/* Function: ipf_proxy_rule_rev */ +/* Returns: ipnat_t * - NULL = failure, else pointer to new rule */ +/* Parameters: nat(I) - pointer to NAT session to create rule from */ +/* */ +/* This function creates a NAT rule that is based upon the reverse packet */ +/* flow associated with this NAT session. Thus if this NAT session was */ +/* created with a map rule then this function will create a rdr rule. */ +/* Only address fields and network interfaces are assigned in this function */ +/* and the address fields are formed such that an exact is required. If the */ +/* original rule had a netmask, that is not replicated here not is it */ +/* desired. The ultimate goal here is to create a NAT rule to support a NAT */ +/* session being created that does not have a user configured rule. The */ +/* classic example is supporting the FTP proxy, where a data channel needs */ +/* to be setup, based on the addresses used for the control connection. In */ +/* that case, this function is used to handle creating NAT rules to support */ +/* data connections with the PORT and EPRT commands. */ +/* ------------------------------------------------------------------------ */ +ipnat_t * +ipf_proxy_rule_rev(nat) + nat_t *nat; { - aproxy_t *ap; - int err = 0; - - for (ap = ap_proxies; ap->apr_p; ap++) { - if (ap->apr_init != NULL) { - err = (*ap->apr_init)(); - if (err != 0) - break; + ipnat_t *old; + ipnat_t *ipn; + int size; + + old = nat->nat_ptr; + size = old->in_size; + + KMALLOCS(ipn, ipnat_t *, size); + if (ipn == NULL) + return NULL; + + bzero((char *)ipn, size); + + ipn->in_use = 1; + ipn->in_hits = 1; + ipn->in_ippip = 1; + ipn->in_apr = NULL; + ipn->in_size = size; + ipn->in_pr[0] = old->in_pr[1]; + ipn->in_pr[1] = old->in_pr[0]; + ipn->in_v[0] = old->in_v[1]; + ipn->in_v[1] = old->in_v[0]; + ipn->in_ifps[0] = old->in_ifps[1]; + ipn->in_ifps[1] = old->in_ifps[0]; + ipn->in_flags = (old->in_flags | IPN_PROXYRULE); + + ipn->in_nsrcip6 = nat->nat_odst6; + ipn->in_osrcip6 = nat->nat_ndst6; + + if ((old->in_redir & NAT_REDIRECT) != 0) { + ipn->in_redir = NAT_MAP; + if (ipn->in_v[0] == 4) { + ipn->in_snip = ntohl(nat->nat_odstaddr); + ipn->in_dnip = ntohl(nat->nat_nsrcaddr); + } else { +#ifdef USE_INET6 + ipn->in_snip6 = nat->nat_odst6; + ipn->in_dnip6 = nat->nat_nsrc6; +#endif } + ipn->in_ndstip6 = nat->nat_nsrc6; + ipn->in_odstip6 = nat->nat_osrc6; + } else { + ipn->in_redir = NAT_REDIRECT; + if (ipn->in_v[0] == 4) { + ipn->in_snip = ntohl(nat->nat_odstaddr); + ipn->in_dnip = ntohl(nat->nat_osrcaddr); + } else { +#ifdef USE_INET6 + ipn->in_snip6 = nat->nat_odst6; + ipn->in_dnip6 = nat->nat_osrc6; +#endif + } + ipn->in_ndstip6 = nat->nat_osrc6; + ipn->in_odstip6 = nat->nat_nsrc6; } - return err; + + IP6_SETONES(&ipn->in_osrcmsk6); + IP6_SETONES(&ipn->in_nsrcmsk6); + IP6_SETONES(&ipn->in_odstmsk6); + IP6_SETONES(&ipn->in_ndstmsk6); + + ipn->in_namelen = old->in_namelen; + ipn->in_ifnames[0] = old->in_ifnames[1]; + ipn->in_ifnames[1] = old->in_ifnames[0]; + bcopy(old->in_names, ipn->in_names, ipn->in_namelen); + MUTEX_INIT(&ipn->in_lock, "ipnat rev rule lock"); + + return ipn; } -/* - * Unload hook for kernel application proxies. - * Call the finialise routine for all the compiled in kernel proxies. - */ -void appr_unload() +/* ------------------------------------------------------------------------ */ +/* Function: ipf_proxy_rule_fwd */ +/* Returns: ipnat_t * - NULL = failure, else pointer to new rule */ +/* Parameters: nat(I) - pointer to NAT session to create rule from */ +/* */ +/* The purpose and rationale of this function is much the same as the above */ +/* function, ipf_proxy_rule_rev, except that a rule is created that matches */ +/* the same direction as that of the existing NAT session. Thus if this NAT */ +/* session was created with a map rule then this function will also create */ +/* a data structure to represent a map rule. Whereas ipf_proxy_rule_rev is */ +/* used to support PORT/EPRT, this function supports PASV/EPSV. */ +/* ------------------------------------------------------------------------ */ +ipnat_t * +ipf_proxy_rule_fwd(nat) + nat_t *nat; { - aproxy_t *ap; + ipnat_t *old; + ipnat_t *ipn; + int size; + + old = nat->nat_ptr; + size = old->in_size; + + KMALLOCS(ipn, ipnat_t *, size); + if (ipn == NULL) + return NULL; + + bzero((char *)ipn, size); + + ipn->in_use = 1; + ipn->in_hits = 1; + ipn->in_ippip = 1; + ipn->in_apr = NULL; + ipn->in_size = size; + ipn->in_pr[0] = old->in_pr[0]; + ipn->in_pr[1] = old->in_pr[1]; + ipn->in_v[0] = old->in_v[0]; + ipn->in_v[1] = old->in_v[1]; + ipn->in_ifps[0] = nat->nat_ifps[0]; + ipn->in_ifps[1] = nat->nat_ifps[1]; + ipn->in_flags = (old->in_flags | IPN_PROXYRULE); + + ipn->in_nsrcip6 = nat->nat_nsrc6; + ipn->in_osrcip6 = nat->nat_osrc6; + ipn->in_ndstip6 = nat->nat_ndst6; + ipn->in_odstip6 = nat->nat_odst6; + ipn->in_redir = old->in_redir; + + if (ipn->in_v[0] == 4) { + ipn->in_snip = ntohl(nat->nat_nsrcaddr); + ipn->in_dnip = ntohl(nat->nat_ndstaddr); + } else { +#ifdef USE_INET6 + ipn->in_snip6 = nat->nat_nsrc6; + ipn->in_dnip6 = nat->nat_ndst6; +#endif + } - for (ap = ap_proxies; ap->apr_p; ap++) - if (ap->apr_fini != NULL) - (*ap->apr_fini)(); - for (ap = ap_proxylist; ap; ap = ap->apr_next) - if (ap->apr_fini != NULL) - (*ap->apr_fini)(); + IP6_SETONES(&ipn->in_osrcmsk6); + IP6_SETONES(&ipn->in_nsrcmsk6); + IP6_SETONES(&ipn->in_odstmsk6); + IP6_SETONES(&ipn->in_ndstmsk6); + + ipn->in_namelen = old->in_namelen; + ipn->in_ifnames[0] = old->in_ifnames[0]; + ipn->in_ifnames[1] = old->in_ifnames[1]; + bcopy(old->in_names, ipn->in_names, ipn->in_namelen); + MUTEX_INIT(&ipn->in_lock, "ipnat fwd rule lock"); + + return ipn; } diff --git a/ip_proxy.h b/ip_proxy.h index 8e53c988cc95d..f533fe7ebf605 100644 --- a/ip_proxy.h +++ b/ip_proxy.h @@ -1,11 +1,9 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1997-2001 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * Id: ip_proxy.h,v 2.31.2.2 2005/03/12 19:33:48 darrenr Exp + * $Id$ */ #ifndef __IP_PROXY_H__ @@ -15,6 +13,12 @@ #define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) #endif +#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51) +#define SIOCPROXY _IOWR('r', 64, struct ap_control) +#else +#define SIOCPROXY _IOWR(r, 64, struct ap_control) +#endif + #ifndef APR_LABELLEN #define APR_LABELLEN 16 #endif @@ -22,15 +26,16 @@ struct nat; struct ipnat; +struct ipstate; typedef struct ap_tcp { u_short apt_sport; /* source port */ u_short apt_dport; /* destination port */ short apt_sel[2]; /* {seq,ack}{off,min} set selector */ short apt_seqoff[2]; /* sequence # difference */ - tcp_seq apt_seqmin[2]; /* don't change seq-off until after this */ + u_32_t apt_seqmin[2]; /* don't change seq-off until after this */ short apt_ackoff[2]; /* sequence # difference */ - tcp_seq apt_ackmin[2]; /* don't change seq-off until after this */ + u_32_t apt_ackmin[2]; /* don't change seq-off until after this */ u_char apt_state[2]; /* connection state */ } ap_tcp_t; @@ -45,14 +50,11 @@ typedef struct ap_session { struct ap_tcp apu_tcp; struct ap_udp apu_udp; } aps_un; - u_int aps_flags; U_QUAD_T aps_bytes; /* bytes sent */ U_QUAD_T aps_pkts; /* packets sent */ void *aps_nat; /* pointer back to nat struct */ void *aps_data; /* private data */ - int aps_p; /* protocol */ int aps_psiz; /* size of private data */ - struct ap_session *aps_hnext; struct ap_session *aps_next; } ap_session_t; @@ -68,6 +70,7 @@ typedef struct ap_session { typedef struct ap_control { char apc_label[APR_LABELLEN]; + char apc_config[APR_LABELLEN]; u_char apc_p; /* * The following fields are upto the proxy's apr_ctl routine to deal @@ -85,21 +88,36 @@ typedef struct ap_control { size_t apc_dsize; } ap_ctl_t; +#define APC_CMD_ADD 0 +#define APC_CMD_DEL 1 + typedef struct aproxy { struct aproxy *apr_next; + struct aproxy *apr_parent; char apr_label[APR_LABELLEN]; /* Proxy label # */ - u_char apr_p; /* protocol */ - int apr_ref; /* +1 per rule referencing it */ + u_char apr_p; /* protocol */ int apr_flags; - int (* apr_init) __P((void)); - void (* apr_fini) __P((void)); - int (* apr_new) __P((fr_info_t *, ap_session_t *, struct nat *)); - void (* apr_del) __P((ap_session_t *)); - int (* apr_inpkt) __P((fr_info_t *, ap_session_t *, struct nat *)); - int (* apr_outpkt) __P((fr_info_t *, ap_session_t *, struct nat *)); + int apr_ref; + int apr_clones; + void (* apr_load) __P((void)); + void (* apr_unload) __P((void)); + void *(* apr_create) __P((ipf_main_softc_t *)); + void (* apr_destroy) __P((ipf_main_softc_t *, void *)); + int (* apr_init) __P((ipf_main_softc_t *, void *)); + void (* apr_fini) __P((ipf_main_softc_t *, void *)); + int (* apr_new) __P((void *, fr_info_t *, ap_session_t *, + struct nat *)); + void (* apr_del) __P((ipf_main_softc_t *, ap_session_t *)); + int (* apr_inpkt) __P((void *, fr_info_t *, ap_session_t *, + struct nat *)); + int (* apr_outpkt) __P((void *, fr_info_t *, ap_session_t *, + struct nat *)); int (* apr_match) __P((fr_info_t *, ap_session_t *, struct nat *)); - int (* apr_ctl) __P((struct aproxy *, struct ap_control *)); + int (* apr_ctl) __P((ipf_main_softc_t *, void *, ap_ctl_t *)); + int (* apr_clear) __P((struct aproxy *)); + int (* apr_flush) __P((struct aproxy *, int)); + void *apr_soft; } aproxy_t; #define APR_DELETE 1 @@ -108,42 +126,37 @@ typedef struct aproxy { #define APR_EXIT(x) (((x) >> 16) & 0xffff) #define APR_INC(x) ((x) & 0xffff) + +#ifdef _KERNEL /* * Generic #define's to cover missing things in the kernel */ -#ifndef isdigit -#define isdigit(x) ((x) >= '0' && (x) <= '9') -#endif -#ifndef isupper -#define isupper(x) (((unsigned)(x) >= 'A') && ((unsigned)(x) <= 'Z')) -#endif -#ifndef islower -#define islower(x) (((unsigned)(x) >= 'a') && ((unsigned)(x) <= 'z')) -#endif -#ifndef isalpha -#define isalpha(x) (isupper(x) || islower(x)) -#endif -#ifndef toupper -#define toupper(x) (isupper(x) ? (x) : (x) - 'a' + 'A') -#endif -#ifndef isspace -#define isspace(x) (((x) == ' ') || ((x) == '\r') || ((x) == '\n') || \ +# ifndef isdigit +# define isdigit(x) ((x) >= '0' && (x) <= '9') +# endif +# ifndef isupper +# define isupper(x) (((unsigned)(x) >= 'A') && ((unsigned)(x) <= 'Z')) +# endif +# ifndef islower +# define islower(x) (((unsigned)(x) >= 'a') && ((unsigned)(x) <= 'z')) +# endif +# ifndef isalpha +# define isalpha(x) (isupper(x) || islower(x)) +# endif +# ifndef toupper +# define toupper(x) (isupper(x) ? (x) : (x) - 'a' + 'A') +# endif +# ifndef isspace +# define isspace(x) (((x) == ' ') || ((x) == '\r') || ((x) == '\n') || \ ((x) == '\t') || ((x) == '\b')) -#endif +# endif +#endif /* _KERNEL */ /* - * This is the scratch buffer size used to hold strings from the TCP stream - * that we may want to parse. It's an arbitrary size, really, but it must - * be at least as large as IPF_FTPBUFSZ. - */ -#define FTP_BUFSZ 120 - -/* - * This buffer, however, doesn't need to be nearly so big. It just needs to - * be able to squeeze in the largest command it needs to rewrite, Which ones - * does it rewrite? EPRT, PORT, 227 replies. + * For the ftp proxy. */ -#define IPF_FTPBUFSZ 80 /* This *MUST* be >= 53! */ +#define FTP_BUFSZ 160 +#define IPF_FTPBUFSZ 160 typedef struct ftpside { char *ftps_rptr; @@ -151,19 +164,37 @@ typedef struct ftpside { void *ftps_ifp; u_32_t ftps_seq[2]; u_32_t ftps_len; - int ftps_junk; /* 2 = no cr/lf yet, 1 = cannot parse */ + int ftps_junk; int ftps_cmds; + int ftps_cmd; char ftps_buf[FTP_BUFSZ]; } ftpside_t; typedef struct ftpinfo { int ftp_passok; int ftp_incok; + void *ftp_pendstate; + nat_t *ftp_pendnat; ftpside_t ftp_side[2]; } ftpinfo_t; /* + * IPsec proxy + */ +typedef u_32_t ipsec_cookie_t[2]; + +typedef struct ipsec_pxy { + ipsec_cookie_t ipsc_icookie; + ipsec_cookie_t ipsc_rcookie; + int ipsc_rckset; + nat_t *ipsc_nat; + struct ipstate *ipsc_state; + ipnat_t *ipsc_rule; +} ipsec_pxy_t; + + +/* * For the irc proxy. */ typedef struct ircinfo { @@ -179,6 +210,16 @@ typedef struct ircinfo { /* + * For the DNS "proxy" + */ +typedef struct dnsinfo { + ipfmutex_t dnsi_lock; + u_short dnsi_id; + char dnsi_buffer[512]; +} dnsinfo_t; + + +/* * Real audio proxy structure and #defines */ typedef struct raudio_s { @@ -197,7 +238,7 @@ typedef struct raudio_s { u_32_t rap_sbf; /* flag to indicate which of the 19 bytes have * been filled */ - tcp_seq rap_sseq; + u_32_t rap_sseq; } raudio_t; #define RA_ID_END 0 @@ -223,43 +264,6 @@ typedef struct msnrpcinfo { /* - * IPSec proxy - */ -typedef u_32_t ipsec_cookie_t[2]; - -typedef struct ipsec_pxy { - ipsec_cookie_t ipsc_icookie; - ipsec_cookie_t ipsc_rcookie; - int ipsc_rckset; - ipnat_t ipsc_rule; - nat_t *ipsc_nat; - ipstate_t *ipsc_state; -} ipsec_pxy_t; - -/* - * PPTP proxy - */ -typedef struct pptp_side { - u_32_t pptps_nexthdr; - u_32_t pptps_next; - int pptps_state; - int pptps_gothdr; - int pptps_len; - int pptps_bytes; - char *pptps_wptr; - char pptps_buffer[512]; -} pptp_side_t; - -typedef struct pptp_pxy { - ipnat_t pptp_rule; - nat_t *pptp_nat; - ipstate_t *pptp_state; - u_short pptp_call[2]; - pptp_side_t pptp_side[2]; -} pptp_pxy_t; - - -/* * Sun RPCBIND proxy */ #define RPCB_MAXMSG 888 @@ -431,23 +435,26 @@ typedef struct rpcb_session { */ #define XDRALIGN(x) ((((x) % 4) != 0) ? ((((x) + 3) / 4) * 4) : (x)) -extern ap_session_t *ap_sess_tab[AP_SESS_SIZE]; -extern ap_session_t *ap_sess_list; -extern aproxy_t ap_proxies[]; -extern int ippr_ftp_pasvonly; - -extern int appr_add __P((aproxy_t *)); -extern int appr_ctl __P((ap_ctl_t *)); -extern int appr_del __P((aproxy_t *)); -extern int appr_init __P((void)); -extern void appr_unload __P((void)); -extern int appr_ok __P((fr_info_t *, tcphdr_t *, struct ipnat *)); -extern int appr_match __P((fr_info_t *, struct nat *)); -extern void appr_free __P((aproxy_t *)); -extern void aps_free __P((ap_session_t *)); -extern int appr_check __P((fr_info_t *, struct nat *)); -extern aproxy_t *appr_lookup __P((u_int, char *)); -extern int appr_new __P((fr_info_t *, struct nat *)); -extern int appr_ioctl __P((caddr_t, ioctlcmd_t, int)); +extern int ipf_proxy_add __P((void *, aproxy_t *)); +extern int ipf_proxy_check __P((fr_info_t *, struct nat *)); +extern int ipf_proxy_ctl __P((ipf_main_softc_t *, void *, ap_ctl_t *)); +extern int ipf_proxy_del __P((aproxy_t *)); +extern void ipf_proxy_deref __P((aproxy_t *)); +extern void ipf_proxy_flush __P((void *, int)); +extern int ipf_proxy_init __P((void)); +extern int ipf_proxy_ioctl __P((ipf_main_softc_t *, caddr_t, ioctlcmd_t, int, void *)); +extern aproxy_t *ipf_proxy_lookup __P((void *, u_int, char *)); +extern int ipf_proxy_match __P((fr_info_t *, struct nat *)); +extern int ipf_proxy_new __P((fr_info_t *, struct nat *)); +extern int ipf_proxy_ok __P((fr_info_t *, tcphdr_t *, struct ipnat *)); +extern void ipf_proxy_free __P((ipf_main_softc_t *, ap_session_t *)); +extern int ipf_proxy_main_load __P((void)); +extern int ipf_proxy_main_unload __P((void)); +extern ipnat_t *ipf_proxy_rule_fwd __P((nat_t *)); +extern ipnat_t *ipf_proxy_rule_rev __P((nat_t *)); +extern void *ipf_proxy_soft_create __P((ipf_main_softc_t *)); +extern void ipf_proxy_soft_destroy __P((ipf_main_softc_t *, void *)); +extern int ipf_proxy_soft_init __P((ipf_main_softc_t *, void *)); +extern int ipf_proxy_soft_fini __P((ipf_main_softc_t *, void *)); #endif /* __IP_PROXY_H__ */ diff --git a/ip_raudio_pxy.c b/ip_raudio_pxy.c index 260fcd4658561..2a54d45e7305c 100644 --- a/ip_raudio_pxy.c +++ b/ip_raudio_pxy.c @@ -1,21 +1,19 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1998-2003 by Darren Reed + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * Id: ip_raudio_pxy.c,v 1.40.2.3 2005/02/04 10:22:55 darrenr Exp + * $Id$ */ #define IPF_RAUDIO_PROXY -int ippr_raudio_init __P((void)); -void ippr_raudio_fini __P((void)); -int ippr_raudio_new __P((fr_info_t *, ap_session_t *, nat_t *)); -int ippr_raudio_in __P((fr_info_t *, ap_session_t *, nat_t *)); -int ippr_raudio_out __P((fr_info_t *, ap_session_t *, nat_t *)); +void ipf_p_raudio_main_load __P((void)); +void ipf_p_raudio_main_unload __P((void)); +int ipf_p_raudio_new __P((void *, fr_info_t *, ap_session_t *, nat_t *)); +int ipf_p_raudio_in __P((void *, fr_info_t *, ap_session_t *, nat_t *)); +int ipf_p_raudio_out __P((void *, fr_info_t *, ap_session_t *, nat_t *)); static frentry_t raudiofr; @@ -25,19 +23,19 @@ int raudio_proxy_init = 0; /* * Real Audio application proxy initialization. */ -int ippr_raudio_init() +void +ipf_p_raudio_main_load() { bzero((char *)&raudiofr, sizeof(raudiofr)); raudiofr.fr_ref = 1; raudiofr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE; MUTEX_INIT(&raudiofr.fr_lock, "Real Audio proxy rule lock"); raudio_proxy_init = 1; - - return 0; } -void ippr_raudio_fini() +void +ipf_p_raudio_main_unload() { if (raudio_proxy_init == 1) { MUTEX_DESTROY(&raudiofr.fr_lock); @@ -49,20 +47,24 @@ void ippr_raudio_fini() /* * Setup for a new proxy to handle Real Audio. */ -int ippr_raudio_new(fin, aps, nat) -fr_info_t *fin; -ap_session_t *aps; -nat_t *nat; +int +ipf_p_raudio_new(arg, fin, aps, nat) + void *arg; + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; { raudio_t *rap; + nat = nat; /* LINT */ + + if (fin->fin_v != 4) + return -1; + KMALLOCS(aps->aps_data, void *, sizeof(raudio_t)); if (aps->aps_data == NULL) return -1; - fin = fin; /* LINT */ - nat = nat; /* LINT */ - bzero(aps->aps_data, sizeof(raudio_t)); rap = aps->aps_data; aps->aps_psiz = sizeof(raudio_t); @@ -72,10 +74,12 @@ nat_t *nat; -int ippr_raudio_out(fin, aps, nat) -fr_info_t *fin; -ap_session_t *aps; -nat_t *nat; +int +ipf_p_raudio_out(arg, fin, aps, nat) + void *arg; + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; { raudio_t *rap = aps->aps_data; unsigned char membuf[512 + 1], *s; @@ -178,14 +182,18 @@ nat_t *nat; } -int ippr_raudio_in(fin, aps, nat) -fr_info_t *fin; -ap_session_t *aps; -nat_t *nat; +int +ipf_p_raudio_in(arg, fin, aps, nat) + void *arg; + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; { unsigned char membuf[IPF_MAXPORTLEN + 1], *s; tcphdr_t *tcp, tcph, *tcp2 = &tcph; raudio_t *rap = aps->aps_data; + ipf_main_softc_t *softc; + ipf_nat_softc_t *softn; struct in_addr swa, swb; int off, dlen, slen; int a1, a2, a3, a4; @@ -197,6 +205,8 @@ nat_t *nat; ip_t *ip; mb_t *m; + softc = fin->fin_main_soft; + softn = softc->ipf_nat_soft; /* * Wait until we've seen the end of the start messages and even then * only proceed further if we're using UDP. If they want to use TCP @@ -271,14 +281,12 @@ nat_t *nat; swb = ip->ip_dst; ip->ip_p = IPPROTO_UDP; - ip->ip_src = nat->nat_inip; - ip->ip_dst = nat->nat_oip; + ip->ip_src = nat->nat_ndstip; + ip->ip_dst = nat->nat_odstip; bcopy((char *)fin, (char *)&fi, sizeof(fi)); bzero((char *)tcp2, sizeof(*tcp2)); TCP_OFF_A(tcp2, 5); - fi.fin_state = NULL; - fi.fin_nat = NULL; fi.fin_flx |= FI_IGNORE; fi.fin_dp = (char *)tcp2; fi.fin_fr = &raudiofr; @@ -286,7 +294,7 @@ nat_t *nat; fi.fin_plen = fi.fin_hlen + sizeof(*tcp2); tcp2->th_win = htons(8192); slen = ip->ip_len; - ip->ip_len = fin->fin_hlen + sizeof(*tcp); + ip->ip_len = htons(fin->fin_hlen + sizeof(*tcp)); if (((rap->rap_mode & RAP_M_UDP_ROBUST) == RAP_M_UDP_ROBUST) && (rap->rap_srport != 0)) { @@ -297,16 +305,19 @@ nat_t *nat; fi.fin_data[0] = dp; fi.fin_data[1] = sp; fi.fin_out = 0; - nat2 = nat_new(&fi, nat->nat_ptr, NULL, + MUTEX_ENTER(&softn->ipf_nat_new); + nat2 = ipf_nat_add(&fi, nat->nat_ptr, NULL, NAT_SLAVE|IPN_UDP | (sp ? 0 : SI_W_SPORT), NAT_OUTBOUND); + MUTEX_EXIT(&softn->ipf_nat_new); if (nat2 != NULL) { - (void) nat_proto(&fi, nat2, IPN_UDP); - nat_update(&fi, nat2, nat2->nat_ptr); + (void) ipf_nat_proto(&fi, nat2, IPN_UDP); + MUTEX_ENTER(&nat2->nat_lock); + ipf_nat_update(&fi, nat2); + MUTEX_EXIT(&nat2->nat_lock); - (void) fr_addstate(&fi, NULL, (sp ? 0 : SI_W_SPORT)); - if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); + (void) ipf_state_add(softc, &fi, NULL, + (sp ? 0 : SI_W_SPORT)); } } @@ -317,16 +328,18 @@ nat_t *nat; fi.fin_data[0] = sp; fi.fin_data[1] = 0; fi.fin_out = 1; - nat2 = nat_new(&fi, nat->nat_ptr, NULL, + MUTEX_ENTER(&softn->ipf_nat_new); + nat2 = ipf_nat_add(&fi, nat->nat_ptr, NULL, NAT_SLAVE|IPN_UDP|SI_W_DPORT, NAT_OUTBOUND); + MUTEX_EXIT(&softn->ipf_nat_new); if (nat2 != NULL) { - (void) nat_proto(&fi, nat2, IPN_UDP); - nat_update(&fi, nat2, nat2->nat_ptr); + (void) ipf_nat_proto(&fi, nat2, IPN_UDP); + MUTEX_ENTER(&nat2->nat_lock); + ipf_nat_update(&fi, nat2); + MUTEX_EXIT(&nat2->nat_lock); - (void) fr_addstate(&fi, NULL, SI_W_DPORT); - if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); + (void) ipf_state_add(softc, &fi, NULL, SI_W_DPORT); } } diff --git a/ip_rcmd_pxy.c b/ip_rcmd_pxy.c index b7904c8b13569..ec67268d7a95c 100644 --- a/ip_rcmd_pxy.c +++ b/ip_rcmd_pxy.c @@ -1,11 +1,9 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1998-2003 by Darren Reed + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * Id: ip_rcmd_pxy.c,v 1.41.2.4 2005/02/04 10:22:55 darrenr Exp + * $Id$ * * Simple RCMD transparent proxy for in-kernel use. For use with the NAT * code. @@ -13,36 +11,45 @@ #define IPF_RCMD_PROXY - -int ippr_rcmd_init __P((void)); -void ippr_rcmd_fini __P((void)); -int ippr_rcmd_new __P((fr_info_t *, ap_session_t *, nat_t *)); -int ippr_rcmd_out __P((fr_info_t *, ap_session_t *, nat_t *)); -int ippr_rcmd_in __P((fr_info_t *, ap_session_t *, nat_t *)); +typedef struct rcmdinfo { + u_32_t rcmd_port; /* Port number seen */ + u_32_t rcmd_portseq; /* Sequence number where port is first seen */ + ipnat_t *rcmd_rule; /* Template rule for back connection */ +} rcmdinfo_t; + +void ipf_p_rcmd_main_load __P((void)); +void ipf_p_rcmd_main_unload __P((void)); + +int ipf_p_rcmd_init __P((void)); +void ipf_p_rcmd_fini __P((void)); +void ipf_p_rcmd_del __P((ipf_main_softc_t *, ap_session_t *)); +int ipf_p_rcmd_new __P((void *, fr_info_t *, ap_session_t *, nat_t *)); +int ipf_p_rcmd_out __P((void *, fr_info_t *, ap_session_t *, nat_t *)); +int ipf_p_rcmd_in __P((void *, fr_info_t *, ap_session_t *, nat_t *)); u_short ipf_rcmd_atoi __P((char *)); -int ippr_rcmd_portmsg __P((fr_info_t *, ap_session_t *, nat_t *)); +int ipf_p_rcmd_portmsg __P((fr_info_t *, ap_session_t *, nat_t *)); static frentry_t rcmdfr; -int rcmd_proxy_init = 0; +static int rcmd_proxy_init = 0; /* * RCMD application proxy initialization. */ -int ippr_rcmd_init() +void +ipf_p_rcmd_main_load() { bzero((char *)&rcmdfr, sizeof(rcmdfr)); rcmdfr.fr_ref = 1; rcmdfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE; MUTEX_INIT(&rcmdfr.fr_lock, "RCMD proxy rule lock"); rcmd_proxy_init = 1; - - return 0; } -void ippr_rcmd_fini() +void +ipf_p_rcmd_main_unload() { if (rcmd_proxy_init == 1) { MUTEX_DESTROY(&rcmdfr.fr_lock); @@ -54,36 +61,70 @@ void ippr_rcmd_fini() /* * Setup for a new RCMD proxy. */ -int ippr_rcmd_new(fin, aps, nat) -fr_info_t *fin; -ap_session_t *aps; -nat_t *nat; +int +ipf_p_rcmd_new(arg, fin, aps, nat) + void *arg; + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; { tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp; + rcmdinfo_t *rc; + ipnat_t *ipn; + ipnat_t *np; + int size; fin = fin; /* LINT */ - nat = nat; /* LINT */ - aps->aps_psiz = sizeof(u_32_t); - KMALLOCS(aps->aps_data, u_32_t *, sizeof(u_32_t)); - if (aps->aps_data == NULL) { + np = nat->nat_ptr; + size = np->in_size; + KMALLOC(rc, rcmdinfo_t *); + if (rc == NULL) { #ifdef IP_RCMD_PROXY_DEBUG - printf("ippr_rcmd_new:KMALLOCS(%d) failed\n", sizeof(u_32_t)); + printf("ipf_p_rcmd_new:KMALLOCS(%d) failed\n", sizeof(*rc)); #endif return -1; } - *(u_32_t *)aps->aps_data = 0; aps->aps_sport = tcp->th_sport; aps->aps_dport = tcp->th_dport; + + ipn = ipf_proxy_rule_rev(nat); + if (ipn == NULL) { + KFREE(rc); + return -1; + } + + aps->aps_data = rc; + aps->aps_psiz = sizeof(*rc); + bzero((char *)rc, sizeof(*rc)); + + rc->rcmd_rule = ipn; + return 0; } +void +ipf_p_rcmd_del(softc, aps) + ipf_main_softc_t *softc; + ap_session_t *aps; +{ + rcmdinfo_t *rci; + + rci = aps->aps_data; + if (rci != NULL) { + rci->rcmd_rule->in_flags |= IPN_DELETE; + ipf_nat_rule_deref(softc, &rci->rcmd_rule); + } +} + + /* * ipf_rcmd_atoi - implement a simple version of atoi */ -u_short ipf_rcmd_atoi(ptr) -char *ptr; +u_short +ipf_rcmd_atoi(ptr) + char *ptr; { register char *s = ptr, c; register u_short i = 0; @@ -96,44 +137,46 @@ char *ptr; } -int ippr_rcmd_portmsg(fin, aps, nat) -fr_info_t *fin; -ap_session_t *aps; -nat_t *nat; +int +ipf_p_rcmd_portmsg(fin, aps, nat) + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; { tcphdr_t *tcp, tcph, *tcp2 = &tcph; - struct in_addr swip, swip2; - int off, dlen, nflags; + int off, dlen, nflags, direction; + ipf_main_softc_t *softc; + ipf_nat_softc_t *softn; char portbuf[8], *s; + rcmdinfo_t *rc; fr_info_t fi; u_short sp; nat_t *nat2; + ip6_t *ip6; + int tcpsz; + int slen; ip_t *ip; mb_t *m; tcp = (tcphdr_t *)fin->fin_dp; - if (tcp->th_flags & TH_SYN) { - *(u_32_t *)aps->aps_data = htonl(ntohl(tcp->th_seq) + 1); - return 0; - } - - if ((*(u_32_t *)aps->aps_data != 0) && - (tcp->th_seq != *(u_32_t *)aps->aps_data)) - return 0; - m = fin->fin_m; ip = fin->fin_ip; - off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff; + tcpsz = TCP_OFF(tcp) << 2; + ip6 = (ip6_t *)fin->fin_ip; + softc = fin->fin_main_soft; + softn = softc->ipf_nat_soft; + off = (char *)tcp - (char *)ip + tcpsz + fin->fin_ipoff; -#ifdef __sgi - dlen = fin->fin_plen - off; -#else - dlen = MSGDSIZE(m) - off; -#endif + dlen = fin->fin_dlen - tcpsz; if (dlen <= 0) return 0; + rc = (rcmdinfo_t *)aps->aps_data; + if ((rc->rcmd_portseq != 0) && + (tcp->th_seq != rc->rcmd_portseq)) + return 0; + bzero(portbuf, sizeof(portbuf)); COPYDATA(m, off, MIN(sizeof(portbuf), dlen), portbuf); @@ -142,95 +185,161 @@ nat_t *nat; sp = ipf_rcmd_atoi(s); if (sp == 0) { #ifdef IP_RCMD_PROXY_DEBUG - printf("ippr_rcmd_portmsg:sp == 0 dlen %d [%s]\n", + printf("ipf_p_rcmd_portmsg:sp == 0 dlen %d [%s]\n", dlen, portbuf); #endif return 0; } + if (rc->rcmd_port != 0 && sp != rc->rcmd_port) { +#ifdef IP_RCMD_PROXY_DEBUG + printf("ipf_p_rcmd_portmsg:sp(%d) != rcmd_port(%d)\n", + sp, rc->rcmd_port); +#endif + return 0; + } + + rc->rcmd_port = sp; + rc->rcmd_portseq = tcp->th_seq; + /* - * Add skeleton NAT entry for connection which will come back the - * other way. + * Initialise the packet info structure so we can search the NAT + * table to see if there already is soemthing present that matches + * up with what we want to add. */ bcopy((char *)fin, (char *)&fi, sizeof(fi)); fi.fin_flx |= FI_IGNORE; - fi.fin_data[0] = sp; - fi.fin_data[1] = 0; - if (nat->nat_dir == NAT_OUTBOUND) - nat2 = nat_outlookup(&fi, NAT_SEARCH|IPN_TCP, nat->nat_p, - nat->nat_inip, nat->nat_oip); - else - nat2 = nat_inlookup(&fi, NAT_SEARCH|IPN_TCP, nat->nat_p, - nat->nat_inip, nat->nat_oip); - if (nat2 == NULL) { - int slen; - - slen = ip->ip_len; - ip->ip_len = fin->fin_hlen + sizeof(*tcp); - bzero((char *)tcp2, sizeof(*tcp2)); - tcp2->th_win = htons(8192); - tcp2->th_sport = htons(sp); - tcp2->th_dport = 0; /* XXX - don't specify remote port */ - TCP_OFF_A(tcp2, 5); - tcp2->th_flags = TH_SYN; - fi.fin_dp = (char *)tcp2; - fi.fin_fr = &rcmdfr; - fi.fin_dlen = sizeof(*tcp2); - fi.fin_plen = fi.fin_hlen + sizeof(*tcp2); - fi.fin_flx &= FI_LOWTTL|FI_FRAG|FI_TCPUDP|FI_OPTIONS|FI_IGNORE; - nflags = NAT_SLAVE|IPN_TCP|SI_W_DPORT; - - swip = ip->ip_src; - swip2 = ip->ip_dst; + fi.fin_data[0] = 0; + fi.fin_data[1] = sp; + fi.fin_src6 = nat->nat_ndst6; + fi.fin_dst6 = nat->nat_nsrc6; + if (nat->nat_v[0] == 6) { +#ifdef USE_INET6 if (nat->nat_dir == NAT_OUTBOUND) { - fi.fin_fi.fi_saddr = nat->nat_inip.s_addr; - ip->ip_src = nat->nat_inip; + nat2 = ipf_nat6_outlookup(&fi, NAT_SEARCH|IPN_TCP, + nat->nat_pr[1], + &nat->nat_osrc6.in6, + &nat->nat_odst6.in6); } else { - fi.fin_fi.fi_saddr = nat->nat_oip.s_addr; - ip->ip_src = nat->nat_oip; - nflags |= NAT_NOTRULEPORT; + nat2 = ipf_nat6_inlookup(&fi, NAT_SEARCH|IPN_TCP, + nat->nat_pr[0], + &nat->nat_osrc6.in6, + &nat->nat_odst6.in6); } - - nat2 = nat_new(&fi, nat->nat_ptr, NULL, nflags, nat->nat_dir); - - if (nat2 != NULL) { - (void) nat_proto(&fi, nat2, IPN_TCP); - nat_update(&fi, nat2, nat2->nat_ptr); - fi.fin_ifp = NULL; - if (nat->nat_dir == NAT_INBOUND) { - fi.fin_fi.fi_daddr = nat->nat_inip.s_addr; - ip->ip_dst = nat->nat_inip; - } - (void) fr_addstate(&fi, &nat2->nat_state, SI_W_DPORT); - if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); +#else + nat2 = (void *)-1; +#endif + } else { + if (nat->nat_dir == NAT_OUTBOUND) { + nat2 = ipf_nat_outlookup(&fi, NAT_SEARCH|IPN_TCP, + nat->nat_pr[1], + nat->nat_osrcip, + nat->nat_odstip); + } else { + nat2 = ipf_nat_inlookup(&fi, NAT_SEARCH|IPN_TCP, + nat->nat_pr[0], + nat->nat_osrcip, + nat->nat_odstip); } + } + if (nat2 != NULL) + return APR_ERR(1); + + /* + * Add skeleton NAT entry for connection which will come + * back the other way. + */ + + if (nat->nat_v[0] == 6) { +#ifdef USE_INET6 + slen = ip6->ip6_plen; + ip6->ip6_plen = htons(sizeof(*tcp)); +#endif + } else { + slen = ip->ip_len; + ip->ip_len = htons(fin->fin_hlen + sizeof(*tcp)); + } + + /* + * Fill out the fake TCP header with a few fields that ipfilter + * considers to be important. + */ + bzero((char *)tcp2, sizeof(*tcp2)); + tcp2->th_win = htons(8192); + TCP_OFF_A(tcp2, 5); + tcp2->th_flags = TH_SYN; + + fi.fin_dp = (char *)tcp2; + fi.fin_fr = &rcmdfr; + fi.fin_dlen = sizeof(*tcp2); + fi.fin_plen = fi.fin_hlen + sizeof(*tcp2); + fi.fin_flx &= FI_LOWTTL|FI_FRAG|FI_TCPUDP|FI_OPTIONS|FI_IGNORE; + + if (nat->nat_dir == NAT_OUTBOUND) { + fi.fin_out = 0; + direction = NAT_INBOUND; + } else { + fi.fin_out = 1; + direction = NAT_OUTBOUND; + } + nflags = SI_W_SPORT|NAT_SLAVE|IPN_TCP; + + MUTEX_ENTER(&softn->ipf_nat_new); + if (fin->fin_v == 4) + nat2 = ipf_nat_add(&fi, rc->rcmd_rule, NULL, nflags, + direction); +#ifdef USE_INET6 + else + nat2 = ipf_nat6_add(&fi, rc->rcmd_rule, NULL, nflags, + direction); +#endif + MUTEX_EXIT(&softn->ipf_nat_new); + + if (nat2 != NULL) { + (void) ipf_nat_proto(&fi, nat2, IPN_TCP); + MUTEX_ENTER(&nat2->nat_lock); + ipf_nat_update(&fi, nat2); + MUTEX_EXIT(&nat2->nat_lock); + fi.fin_ifp = NULL; + if (nat2->nat_dir == NAT_INBOUND) + fi.fin_dst6 = nat->nat_osrc6; + (void) ipf_state_add(softc, &fi, NULL, SI_W_SPORT); + } + if (nat->nat_v[0] == 6) { +#ifdef USE_INET6 + ip6->ip6_plen = slen; +#endif + } else { ip->ip_len = slen; - ip->ip_src = swip; - ip->ip_dst = swip2; } + if (nat2 == NULL) + return APR_ERR(1); return 0; } -int ippr_rcmd_out(fin, aps, nat) -fr_info_t *fin; -ap_session_t *aps; -nat_t *nat; +int +ipf_p_rcmd_out(arg, fin, aps, nat) + void *arg; + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; { if (nat->nat_dir == NAT_OUTBOUND) - return ippr_rcmd_portmsg(fin, aps, nat); + return ipf_p_rcmd_portmsg(fin, aps, nat); return 0; } -int ippr_rcmd_in(fin, aps, nat) -fr_info_t *fin; -ap_session_t *aps; -nat_t *nat; +int +ipf_p_rcmd_in(arg, fin, aps, nat) + void *arg; + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; { if (nat->nat_dir == NAT_INBOUND) - return ippr_rcmd_portmsg(fin, aps, nat); + return ipf_p_rcmd_portmsg(fin, aps, nat); return 0; } diff --git a/ip_rpcb_pxy.c b/ip_rpcb_pxy.c index 5d0a1ee43daca..9493d2bfae384 100644 --- a/ip_rpcb_pxy.c +++ b/ip_rpcb_pxy.c @@ -1,7 +1,5 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 2002-2003 by Ryan Beasley <ryanb@goddamnbastard.org> + * Copyright (C) 2002-2012 by Ryan Beasley <ryanb@goddamnbastard.org> * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -39,44 +37,43 @@ * o The enclosed hack of STREAMS support is pretty sick and most likely * broken. * - * Id: ip_rpcb_pxy.c,v 2.25.2.3 2005/02/04 10:22:56 darrenr Exp + * $Id$ */ - #define IPF_RPCB_PROXY /* * Function prototypes */ -int ippr_rpcb_init __P((void)); -void ippr_rpcb_fini __P((void)); -int ippr_rpcb_new __P((fr_info_t *, ap_session_t *, nat_t *)); -void ippr_rpcb_del __P((ap_session_t *)); -int ippr_rpcb_in __P((fr_info_t *, ap_session_t *, nat_t *)); -int ippr_rpcb_out __P((fr_info_t *, ap_session_t *, nat_t *)); - -static void ippr_rpcb_flush __P((rpcb_session_t *)); -static int ippr_rpcb_decodereq __P((fr_info_t *, nat_t *, +void ipf_p_rpcb_main_load __P((void)); +void ipf_p_rpcb_main_unload __P((void)); +int ipf_p_rpcb_new __P((void *, fr_info_t *, ap_session_t *, nat_t *)); +void ipf_p_rpcb_del __P((ipf_main_softc_t *, ap_session_t *)); +int ipf_p_rpcb_in __P((void *, fr_info_t *, ap_session_t *, nat_t *)); +int ipf_p_rpcb_out __P((void *, fr_info_t *, ap_session_t *, nat_t *)); + +static void ipf_p_rpcb_flush __P((rpcb_session_t *)); +static int ipf_p_rpcb_decodereq __P((fr_info_t *, nat_t *, rpcb_session_t *, rpc_msg_t *)); -static int ippr_rpcb_skipauth __P((rpc_msg_t *, xdr_auth_t *, u_32_t **)); -static int ippr_rpcb_insert __P((rpcb_session_t *, rpcb_xact_t *)); -static int ippr_rpcb_xdrrpcb __P((rpc_msg_t *, u_32_t *, rpcb_args_t *)); -static int ippr_rpcb_getuaddr __P((rpc_msg_t *, xdr_uaddr_t *, +static int ipf_p_rpcb_skipauth __P((rpc_msg_t *, xdr_auth_t *, u_32_t **)); +static int ipf_p_rpcb_insert __P((rpcb_session_t *, rpcb_xact_t *)); +static int ipf_p_rpcb_xdrrpcb __P((rpc_msg_t *, u_32_t *, rpcb_args_t *)); +static int ipf_p_rpcb_getuaddr __P((rpc_msg_t *, xdr_uaddr_t *, u_32_t **)); -static u_int ippr_rpcb_atoi __P((char *)); -static int ippr_rpcb_modreq __P((fr_info_t *, nat_t *, rpc_msg_t *, +static u_int ipf_p_rpcb_atoi __P((char *)); +static int ipf_p_rpcb_modreq __P((fr_info_t *, nat_t *, rpc_msg_t *, mb_t *, u_int)); -static int ippr_rpcb_decoderep __P((fr_info_t *, nat_t *, +static int ipf_p_rpcb_decoderep __P((fr_info_t *, nat_t *, rpcb_session_t *, rpc_msg_t *, rpcb_xact_t **)); -static rpcb_xact_t * ippr_rpcb_lookup __P((rpcb_session_t *, u_32_t)); -static void ippr_rpcb_deref __P((rpcb_session_t *, rpcb_xact_t *)); -static int ippr_rpcb_getproto __P((rpc_msg_t *, xdr_proto_t *, +static rpcb_xact_t * ipf_p_rpcb_lookup __P((rpcb_session_t *, u_32_t)); +static void ipf_p_rpcb_deref __P((rpcb_session_t *, rpcb_xact_t *)); +static int ipf_p_rpcb_getproto __P((rpc_msg_t *, xdr_proto_t *, u_32_t **)); -static int ippr_rpcb_getnat __P((fr_info_t *, nat_t *, u_int, u_int)); -static int ippr_rpcb_modv3 __P((fr_info_t *, nat_t *, rpc_msg_t *, +static int ipf_p_rpcb_getnat __P((fr_info_t *, nat_t *, u_int, u_int)); +static int ipf_p_rpcb_modv3 __P((fr_info_t *, nat_t *, rpc_msg_t *, mb_t *, u_int)); -static int ippr_rpcb_modv4 __P((fr_info_t *, nat_t *, rpc_msg_t *, +static int ipf_p_rpcb_modv4 __P((fr_info_t *, nat_t *, rpc_msg_t *, mb_t *, u_int)); -static void ippr_rpcb_fixlen __P((fr_info_t *, int)); +static void ipf_p_rpcb_fixlen __P((fr_info_t *, int)); /* * Global variables @@ -86,7 +83,7 @@ static frentry_t rpcbfr; /* Skeleton rule for reference by entities static int rpcbcnt; /* Upper bound of allocated RPCB sessions. */ /* XXX rpcbcnt still requires locking. */ -int rpcb_proxy_init = 0; +static int rpcb_proxy_init = 0; /* @@ -100,15 +97,15 @@ int rpcb_proxy_init = 0; * Public subroutines */ -/* -------------------------------------------------------------------- */ -/* Function: ippr_rpcb_init */ -/* Returns: int - 0 == success */ -/* Parameters: (void) */ -/* */ -/* Initialize the filter rule entry and session limiter. */ -/* -------------------------------------------------------------------- */ -int -ippr_rpcb_init() +/* -------------------------------------------------------------------- */ +/* Function: ipf_p_rpcb_main_load */ +/* Returns: void */ +/* Parameters: (void) */ +/* */ +/* Initialize the filter rule entry and session limiter. */ +/* -------------------------------------------------------------------- */ +void +ipf_p_rpcb_main_load() { rpcbcnt = 0; @@ -117,19 +114,17 @@ ippr_rpcb_init() rpcbfr.fr_flags = FR_PASS|FR_QUICK|FR_KEEPSTATE; MUTEX_INIT(&rpcbfr.fr_lock, "ipf Sun RPCB proxy rule lock"); rpcb_proxy_init = 1; - - return(0); } -/* -------------------------------------------------------------------- */ -/* Function: ippr_rpcb_fini */ -/* Returns: void */ -/* Parameters: (void) */ -/* */ -/* Destroy rpcbfr's mutex to avoid a lock leak. */ -/* -------------------------------------------------------------------- */ +/* -------------------------------------------------------------------- */ +/* Function: ipf_p_rpcb_main_unload */ +/* Returns: void */ +/* Parameters: (void) */ +/* */ +/* Destroy rpcbfr's mutex to avoid a lock leak. */ +/* -------------------------------------------------------------------- */ void -ippr_rpcb_fini() +ipf_p_rpcb_main_unload() { if (rpcb_proxy_init == 1) { MUTEX_DESTROY(&rpcbfr.fr_lock); @@ -138,7 +133,7 @@ ippr_rpcb_fini() } /* -------------------------------------------------------------------- */ -/* Function: ippr_rpcb_new */ +/* Function: ipf_p_rpcb_new */ /* Returns: int - -1 == failure, 0 == success */ /* Parameters: fin(I) - pointer to packet information */ /* aps(I) - pointer to proxy session structure */ @@ -147,16 +142,19 @@ ippr_rpcb_fini() /* Allocate resources for per-session proxy structures. */ /* -------------------------------------------------------------------- */ int -ippr_rpcb_new(fin, aps, nat) +ipf_p_rpcb_new(arg, fin, aps, nat) + void *arg; fr_info_t *fin; ap_session_t *aps; nat_t *nat; { rpcb_session_t *rs; - fin = fin; /* LINT */ nat = nat; /* LINT */ + if (fin->fin_v != 4) + return -1; + KMALLOC(rs, rpcb_session_t *); if (rs == NULL) return(-1); @@ -170,27 +168,28 @@ ippr_rpcb_new(fin, aps, nat) } /* -------------------------------------------------------------------- */ -/* Function: ippr_rpcb_del */ +/* Function: ipf_p_rpcb_del */ /* Returns: void */ /* Parameters: aps(I) - pointer to proxy session structure */ /* */ /* Free up a session's list of RPCB requests. */ /* -------------------------------------------------------------------- */ void -ippr_rpcb_del(aps) +ipf_p_rpcb_del(softc, aps) + ipf_main_softc_t *softc; ap_session_t *aps; { rpcb_session_t *rs; rs = (rpcb_session_t *)aps->aps_data; MUTEX_ENTER(&rs->rs_rxlock); - ippr_rpcb_flush(rs); + ipf_p_rpcb_flush(rs); MUTEX_EXIT(&rs->rs_rxlock); MUTEX_DESTROY(&rs->rs_rxlock); } /* -------------------------------------------------------------------- */ -/* Function: ippr_rpcb_in */ +/* Function: ipf_p_rpcb_in */ /* Returns: int - APR_ERR(1) == drop the packet, */ /* APR_ERR(2) == kill the proxy session, */ /* else change in packet length (in bytes) */ @@ -203,7 +202,8 @@ ippr_rpcb_del(aps) /* for decoding. Also pass packet off for a rewrite if necessary. */ /* -------------------------------------------------------------------- */ int -ippr_rpcb_in(fin, aps, nat) +ipf_p_rpcb_in(arg, fin, aps, nat) + void *arg; fr_info_t *fin; ap_session_t *aps; nat_t *nat; @@ -237,7 +237,7 @@ ippr_rpcb_in(fin, aps, nat) rm->rm_buflen = dlen; /* Send off to decode request. */ - rv = ippr_rpcb_decodereq(fin, nat, rs, rm); + rv = ipf_p_rpcb_decodereq(fin, nat, rs, rm); switch(rv) { @@ -248,18 +248,18 @@ ippr_rpcb_in(fin, aps, nat) case 0: break; case 1: - rv = ippr_rpcb_modreq(fin, nat, rm, m, off); + rv = ipf_p_rpcb_modreq(fin, nat, rm, m, off); break; default: /*CONSTANTCONDITION*/ - IPF_PANIC(1, ("illegal rv %d (ippr_rpcb_req)", rv)); + IPF_PANIC(1, ("illegal rv %d (ipf_p_rpcb_req)", rv)); } return(rv); } /* -------------------------------------------------------------------- */ -/* Function: ippr_rpcb_out */ +/* Function: ipf_p_rpcb_out */ /* Returns: int - APR_ERR(1) == drop the packet, */ /* APR_ERR(2) == kill the proxy session, */ /* else change in packet length (in bytes) */ @@ -274,7 +274,8 @@ ippr_rpcb_in(fin, aps, nat) /* allow direct communication between RPC client and server. */ /* -------------------------------------------------------------------- */ int -ippr_rpcb_out(fin, aps, nat) +ipf_p_rpcb_out(arg, fin, aps, nat) + void *arg; fr_info_t *fin; ap_session_t *aps; nat_t *nat; @@ -292,6 +293,7 @@ ippr_rpcb_out(fin, aps, nat) /* Perform basic variable initialization. */ rs = (rpcb_session_t *)aps->aps_data; + rx = NULL; m = fin->fin_m; off = (char *)fin->fin_dp - (char *)fin->fin_ip; @@ -309,15 +311,17 @@ ippr_rpcb_out(fin, aps, nat) COPYDATA(m, off, dlen, (caddr_t)&rm->rm_msgbuf); rm->rm_buflen = dlen; + rx = NULL; /* XXX gcc */ + /* Send off to decode reply. */ - rv = ippr_rpcb_decoderep(fin, nat, rs, rm, &rx); + rv = ipf_p_rpcb_decoderep(fin, nat, rs, rm, &rx); switch(rv) { case -1: /* Bad packet */ if (rx != NULL) { MUTEX_ENTER(&rs->rs_rxlock); - ippr_rpcb_deref(rs, rx); + ipf_p_rpcb_deref(rs, rx); MUTEX_EXIT(&rs->rs_rxlock); } return(APR_ERR(1)); @@ -333,16 +337,16 @@ ippr_rpcb_out(fin, aps, nat) * same. (i.e., this box is either a router or rpcbind * only listens on loopback.) */ - if (nat->nat_inip.s_addr != nat->nat_outip.s_addr) { + if (nat->nat_odstaddr != nat->nat_ndstaddr) { if (rx->rx_type == RPCB_RES_STRING) - diff = ippr_rpcb_modv3(fin, nat, rm, m, off); + diff = ipf_p_rpcb_modv3(fin, nat, rm, m, off); else if (rx->rx_type == RPCB_RES_LIST) - diff = ippr_rpcb_modv4(fin, nat, rm, m, off); + diff = ipf_p_rpcb_modv4(fin, nat, rm, m, off); } break; default: /*CONSTANTCONDITION*/ - IPF_PANIC(1, ("illegal rv %d (ippr_rpcb_decoderep)", rv)); + IPF_PANIC(1, ("illegal rv %d (ipf_p_rpcb_decoderep)", rv)); } if (rx != NULL) { @@ -353,8 +357,8 @@ ippr_rpcb_out(fin, aps, nat) * finished with rx, and the other signals that we've * processed its reply. */ - ippr_rpcb_deref(rs, rx); - ippr_rpcb_deref(rs, rx); + ipf_p_rpcb_deref(rs, rx); + ipf_p_rpcb_deref(rs, rx); MUTEX_EXIT(&rs->rs_rxlock); } @@ -366,14 +370,14 @@ ippr_rpcb_out(fin, aps, nat) */ /* -------------------------------------------------------------------- */ -/* Function: ippr_rpcb_flush */ +/* Function: ipf_p_rpcb_flush */ /* Returns: void */ /* Parameters: rs(I) - pointer to RPCB session structure */ /* */ /* Simply flushes the list of outstanding transactions, if any. */ /* -------------------------------------------------------------------- */ static void -ippr_rpcb_flush(rs) +ipf_p_rpcb_flush(rs) rpcb_session_t *rs; { rpcb_xact_t *r1, *r2; @@ -390,7 +394,7 @@ ippr_rpcb_flush(rs) } /* -------------------------------------------------------------------- */ -/* Function: ippr_rpcb_decodereq */ +/* Function: ipf_p_rpcb_decodereq */ /* Returns: int - -1 == bad request or critical failure, */ /* 0 == request successfully decoded, */ /* 1 == request successfully decoded; requires */ @@ -407,7 +411,7 @@ ippr_rpcb_flush(rs) /* is enough room in rs_buf for the basic RPC message "preamble". */ /* -------------------------------------------------------------------- */ static int -ippr_rpcb_decodereq(fin, nat, rs, rm) +ipf_p_rpcb_decodereq(fin, nat, rs, rm) fr_info_t *fin; nat_t *nat; rpcb_session_t *rs; @@ -439,9 +443,9 @@ ippr_rpcb_decodereq(fin, nat, rs, rm) rc->rc_proc = p++; /* Bypass RPC authentication stuff. */ - if (ippr_rpcb_skipauth(rm, &rc->rc_authcred, &p) != 0) + if (ipf_p_rpcb_skipauth(rm, &rc->rc_authcred, &p) != 0) return(-1); - if (ippr_rpcb_skipauth(rm, &rc->rc_authverf, &p) != 0) + if (ipf_p_rpcb_skipauth(rm, &rc->rc_authverf, &p) != 0) return(-1); /* Compare RPCB version and procedure numbers. */ @@ -487,17 +491,17 @@ ippr_rpcb_decodereq(fin, nat, rs, rm) ra = &rc->rc_rpcbargs; /* Decode the 'struct rpcb' request. */ - if (ippr_rpcb_xdrrpcb(rm, p, ra) != 0) + if (ipf_p_rpcb_xdrrpcb(rm, p, ra) != 0) return(-1); /* Are the target address & port valid? */ - if ((ra->ra_maddr.xu_ip != nat->nat_outip.s_addr) || - (ra->ra_maddr.xu_port != nat->nat_outport)) + if ((ra->ra_maddr.xu_ip != nat->nat_ndstaddr) || + (ra->ra_maddr.xu_port != nat->nat_ndport)) return(-1); /* Do we need to rewrite this packet? */ - if ((nat->nat_outip.s_addr != nat->nat_inip.s_addr) || - (nat->nat_outport != nat->nat_inport)) + if ((nat->nat_ndstaddr != nat->nat_odstaddr) || + (nat->nat_ndport != nat->nat_odport)) mod = 1; break; default: @@ -505,7 +509,7 @@ ippr_rpcb_decodereq(fin, nat, rs, rm) } MUTEX_ENTER(&rs->rs_rxlock); - if (ippr_rpcb_insert(rs, &rx) != 0) { + if (ipf_p_rpcb_insert(rs, &rx) != 0) { MUTEX_EXIT(&rs->rs_rxlock); return(-1); } @@ -515,7 +519,7 @@ ippr_rpcb_decodereq(fin, nat, rs, rm) } /* -------------------------------------------------------------------- */ -/* Function: ippr_rpcb_skipauth */ +/* Function: ipf_p_rpcb_skipauth */ /* Returns: int -- -1 == illegal auth parameters (lengths) */ /* 0 == valid parameters, pointer advanced */ /* Parameters: rm(I) - pointer to RPC message structure */ @@ -526,7 +530,7 @@ ippr_rpcb_decodereq(fin, nat, rs, rm) /* it. */ /* -------------------------------------------------------------------- */ static int -ippr_rpcb_skipauth(rm, auth, buf) +ipf_p_rpcb_skipauth(rm, auth, buf) rpc_msg_t *rm; xdr_auth_t *auth; u_32_t **buf; @@ -558,20 +562,20 @@ ippr_rpcb_skipauth(rm, auth, buf) } /* -------------------------------------------------------------------- */ -/* Function: ippr_rpcb_insert */ +/* Function: ipf_p_rpcb_insert */ /* Returns: int -- -1 == list insertion failed, */ /* 0 == item successfully added */ /* Parameters: rs(I) - pointer to RPCB session structure */ /* rx(I) - pointer to RPCB transaction structure */ /* -------------------------------------------------------------------- */ static int -ippr_rpcb_insert(rs, rx) +ipf_p_rpcb_insert(rs, rx) rpcb_session_t *rs; rpcb_xact_t *rx; { rpcb_xact_t *rxp; - rxp = ippr_rpcb_lookup(rs, rx->rx_xid); + rxp = ipf_p_rpcb_lookup(rs, rx->rx_xid); if (rxp != NULL) { ++rxp->rx_ref; return(0); @@ -601,7 +605,7 @@ ippr_rpcb_insert(rs, rx) } /* -------------------------------------------------------------------- */ -/* Function: ippr_rpcb_xdrrpcb */ +/* Function: ipf_p_rpcb_xdrrpcb */ /* Returns: int -- -1 == failure to properly decode the request */ /* 0 == rpcb successfully decoded */ /* Parameters: rs(I) - pointer to RPCB session structure */ @@ -612,7 +616,7 @@ ippr_rpcb_insert(rs, rx) /* within only the context of TCP/UDP over IP networks. */ /* -------------------------------------------------------------------- */ static int -ippr_rpcb_xdrrpcb(rm, p, ra) +ipf_p_rpcb_xdrrpcb(rm, p, ra) rpc_msg_t *rm; u_32_t *p; rpcb_args_t *ra; @@ -624,11 +628,11 @@ ippr_rpcb_xdrrpcb(rm, p, ra) p += 2; /* Decode r_netid. Must be "tcp" or "udp". */ - if (ippr_rpcb_getproto(rm, &ra->ra_netid, &p) != 0) + if (ipf_p_rpcb_getproto(rm, &ra->ra_netid, &p) != 0) return(-1); /* Decode r_maddr. */ - if (ippr_rpcb_getuaddr(rm, &ra->ra_maddr, &p) != 0) + if (ipf_p_rpcb_getuaddr(rm, &ra->ra_maddr, &p) != 0) return(-1); /* Advance to r_owner and make sure it's empty. */ @@ -639,7 +643,7 @@ ippr_rpcb_xdrrpcb(rm, p, ra) } /* -------------------------------------------------------------------- */ -/* Function: ippr_rpcb_getuaddr */ +/* Function: ipf_p_rpcb_getuaddr */ /* Returns: int -- -1 == illegal string, */ /* 0 == string parsed; contents recorded */ /* Parameters: rm(I) - pointer to RPC message structure */ @@ -649,7 +653,7 @@ ippr_rpcb_xdrrpcb(rm, p, ra) /* Decode the IP address / port at p and record them in xu. */ /* -------------------------------------------------------------------- */ static int -ippr_rpcb_getuaddr(rm, xu, p) +ipf_p_rpcb_getuaddr(rm, xu, p) rpc_msg_t *rm; xdr_uaddr_t *xu; u_32_t **p; @@ -698,7 +702,7 @@ ippr_rpcb_getuaddr(rm, xu, p) /* Check for ASCII byte. */ *c = '\0'; - t = ippr_rpcb_atoi(b); + t = ipf_p_rpcb_atoi(b); if (t > 255) return(-1); @@ -720,7 +724,7 @@ ippr_rpcb_getuaddr(rm, xu, p) return(-1); /* Handle the last byte (port low byte) */ - t = ippr_rpcb_atoi(b); + t = ipf_p_rpcb_atoi(b); if (t > 255) return(-1); pp[d - 4] = t & 0xff; @@ -729,14 +733,14 @@ ippr_rpcb_getuaddr(rm, xu, p) } /* -------------------------------------------------------------------- */ -/* Function: ippr_rpcb_atoi (XXX should be generic for all proxies) */ +/* Function: ipf_p_rpcb_atoi (XXX should be generic for all proxies) */ /* Returns: int -- integer representation of supplied string */ /* Parameters: ptr(I) - input string */ /* */ /* Simple version of atoi(3) ripped from ip_rcmd_pxy.c. */ /* -------------------------------------------------------------------- */ static u_int -ippr_rpcb_atoi(ptr) +ipf_p_rpcb_atoi(ptr) char *ptr; { register char *s = ptr, c; @@ -750,7 +754,7 @@ ippr_rpcb_atoi(ptr) } /* -------------------------------------------------------------------- */ -/* Function: ippr_rpcb_modreq */ +/* Function: ipf_p_rpcb_modreq */ /* Returns: int -- change in datagram length */ /* APR_ERR(2) - critical failure */ /* Parameters: fin(I) - pointer to packet information */ @@ -763,7 +767,7 @@ ippr_rpcb_atoi(ptr) /* with the latter. (This is exclusive to protocol versions 3 & 4). */ /* -------------------------------------------------------------------- */ static int -ippr_rpcb_modreq(fin, nat, rm, m, off) +ipf_p_rpcb_modreq(fin, nat, rm, m, off) fr_info_t *fin; nat_t *nat; rpc_msg_t *rm; @@ -778,8 +782,8 @@ ippr_rpcb_modreq(fin, nat, rm, m, off) int diff; ra = &rm->rm_call.rc_rpcbargs; - i = (char *)&nat->nat_inip.s_addr; - p = (char *)&nat->nat_inport; + i = (char *)&nat->nat_odstaddr; + p = (char *)&nat->nat_odport; /* Form new string. */ bzero(uaddr, sizeof(uaddr)); /* Just in case we need padding. */ @@ -820,9 +824,9 @@ ippr_rpcb_modreq(fin, nat, rm, m, off) if (diff != 0) { udp = fin->fin_dp; udp->uh_ulen = htons(ntohs(udp->uh_ulen) + diff); - fin->fin_ip->ip_len += diff; - fin->fin_dlen += diff; fin->fin_plen += diff; + fin->fin_ip->ip_len = htons(fin->fin_plen); + fin->fin_dlen += diff; /* XXX Storage lengths. */ } @@ -830,7 +834,7 @@ ippr_rpcb_modreq(fin, nat, rm, m, off) } /* -------------------------------------------------------------------- */ -/* Function: ippr_rpcb_decoderep */ +/* Function: ipf_p_rpcb_decoderep */ /* Returns: int - -1 == bad request or critical failure, */ /* 0 == valid, negative reply */ /* 1 == vaddlid, positive reply; needs no changes */ @@ -850,7 +854,7 @@ ippr_rpcb_modreq(fin, nat, rm, m, off) /* is enough room in rs_buf for the basic RPC message "preamble". */ /* -------------------------------------------------------------------- */ static int -ippr_rpcb_decoderep(fin, nat, rs, rm, rxp) +ipf_p_rpcb_decoderep(fin, nat, rs, rm, rxp) fr_info_t *fin; nat_t *nat; rpcb_session_t *rs; @@ -874,7 +878,7 @@ ippr_rpcb_decoderep(fin, nat, rs, rm, rxp) /* Lookup XID */ MUTEX_ENTER(&rs->rs_rxlock); - if ((rx = ippr_rpcb_lookup(rs, xdr)) == NULL) { + if ((rx = ipf_p_rpcb_lookup(rs, xdr)) == NULL) { MUTEX_EXIT(&rs->rs_rxlock); return(-1); } @@ -899,7 +903,7 @@ ippr_rpcb_decoderep(fin, nat, rs, rm, rxp) } /* Bypass RPC authentication stuff. */ - if (ippr_rpcb_skipauth(rm, &rr->rr_authverf, &p) != 0) + if (ipf_p_rpcb_skipauth(rm, &rr->rr_authverf, &p) != 0) return(-1); /* Test accept status */ @@ -915,20 +919,20 @@ ippr_rpcb_decoderep(fin, nat, rs, rm, rxp) /* There must be only one 4 byte argument. */ if (!RPCB_BUF_EQ(rm, p, 4)) return(-1); - + rr->rr_v2 = p; xdr = B(rr->rr_v2); - + /* Reply w/ a 0 port indicates service isn't registered */ if (xdr == 0) return(0); - + /* Is the value sane? */ if (xdr > 65535) return(-1); /* Create NAT & state table entries. */ - if (ippr_rpcb_getnat(fin, nat, rx->rx_proto, (u_int)xdr) != 0) + if (ipf_p_rpcb_getnat(fin, nat, rx->rx_proto, (u_int)xdr) != 0) return(-1); break; case RPCB_RES_STRING: @@ -946,15 +950,15 @@ ippr_rpcb_decoderep(fin, nat, rs, rm, rxp) return(0); /* Decode the target IP address / port. */ - if (ippr_rpcb_getuaddr(rm, &rr->rr_v3, &p) != 0) + if (ipf_p_rpcb_getuaddr(rm, &rr->rr_v3, &p) != 0) return(-1); /* Validate the IP address and port contained. */ - if (nat->nat_inip.s_addr != rr->rr_v3.xu_ip) + if (nat->nat_odstaddr != rr->rr_v3.xu_ip) return(-1); /* Create NAT & state table entries. */ - if (ippr_rpcb_getnat(fin, nat, rx->rx_proto, + if (ipf_p_rpcb_getnat(fin, nat, rx->rx_proto, (u_int)rr->rr_v3.xu_port) != 0) return(-1); break; @@ -979,9 +983,9 @@ ippr_rpcb_decoderep(fin, nat, rs, rm, rxp) for(;;) { re = &rl->rl_entries[rl->rl_cnt]; - if (ippr_rpcb_getuaddr(rm, &re->re_maddr, &p) != 0) + if (ipf_p_rpcb_getuaddr(rm, &re->re_maddr, &p) != 0) return(-1); - if (ippr_rpcb_getproto(rm, &re->re_netid, &p) != 0) + if (ipf_p_rpcb_getproto(rm, &re->re_netid, &p) != 0) return(-1); /* re_semantics & re_pfamily length */ if (!RPCB_BUF_GEQ(rm, p, 12)) @@ -991,7 +995,7 @@ ippr_rpcb_decoderep(fin, nat, rs, rm, rxp) if ((xdr != 4) || strncmp((char *)p, "inet", 4)) return(-1); p++; - if (ippr_rpcb_getproto(rm, &re->re_proto, &p) != 0) + if (ipf_p_rpcb_getproto(rm, &re->re_proto, &p) != 0) return(-1); if (!RPCB_BUF_GEQ(rm, p, 4)) return(-1); @@ -1010,7 +1014,7 @@ ippr_rpcb_decoderep(fin, nat, rs, rm, rxp) for(rl->rl_cnt = 0; rl->rl_cnt < cnt; rl->rl_cnt++) { re = &rl->rl_entries[rl->rl_cnt]; - rv = ippr_rpcb_getnat(fin, nat, + rv = ipf_p_rpcb_getnat(fin, nat, re->re_proto.xp_proto, (u_int)re->re_maddr.xu_port); if (rv != 0) @@ -1026,14 +1030,14 @@ ippr_rpcb_decoderep(fin, nat, rs, rm, rxp) } /* -------------------------------------------------------------------- */ -/* Function: ippr_rpcb_lookup */ +/* Function: ipf_p_rpcb_lookup */ /* Returns: rpcb_xact_t * - NULL == no matching record, */ /* else pointer to relevant entry */ /* Parameters: rs(I) - pointer to RPCB session */ /* xid(I) - XID to look for */ /* -------------------------------------------------------------------- */ static rpcb_xact_t * -ippr_rpcb_lookup(rs, xid) +ipf_p_rpcb_lookup(rs, xid) rpcb_session_t *rs; u_32_t xid; { @@ -1050,7 +1054,7 @@ ippr_rpcb_lookup(rs, xid) } /* -------------------------------------------------------------------- */ -/* Function: ippr_rpcb_deref */ +/* Function: ipf_p_rpcb_deref */ /* Returns: (void) */ /* Parameters: rs(I) - pointer to RPCB session */ /* rx(I) - pointer to RPC transaction struct to remove */ @@ -1061,7 +1065,7 @@ ippr_rpcb_lookup(rs, xid) /* Free the RPCB transaction record rx from the chain of entries. */ /* -------------------------------------------------------------------- */ static void -ippr_rpcb_deref(rs, rx) +ipf_p_rpcb_deref(rs, rx) rpcb_session_t *rs; rpcb_xact_t *rx; { @@ -1084,7 +1088,7 @@ ippr_rpcb_deref(rs, rx) } /* -------------------------------------------------------------------- */ -/* Function: ippr_rpcb_getproto */ +/* Function: ipf_p_rpcb_getproto */ /* Returns: int - -1 == illegal protocol/netid, */ /* 0 == legal protocol/netid */ /* Parameters: rm(I) - pointer to RPC message structure */ @@ -1094,7 +1098,7 @@ ippr_rpcb_deref(rs, rx) /* Decode netid/proto stored at p and record its numeric value. */ /* -------------------------------------------------------------------- */ static int -ippr_rpcb_getproto(rm, xp, p) +ipf_p_rpcb_getproto(rm, xp, p) rpc_msg_t *rm; xdr_proto_t *xp; u_32_t **p; @@ -1121,7 +1125,7 @@ ippr_rpcb_getproto(rm, xp, p) else { return(-1); } - + /* Advance past the string. */ (*p)++; @@ -1129,7 +1133,7 @@ ippr_rpcb_getproto(rm, xp, p) } /* -------------------------------------------------------------------- */ -/* Function: ippr_rpcb_getnat */ +/* Function: ipf_p_rpcb_getnat */ /* Returns: int -- -1 == failed to create table entries, */ /* 0 == success */ /* Parameters: fin(I) - pointer to packet information */ @@ -1141,12 +1145,13 @@ ippr_rpcb_getproto(rm, xp, p) /* attempt between RPC client and server. */ /* -------------------------------------------------------------------- */ static int -ippr_rpcb_getnat(fin, nat, proto, port) +ipf_p_rpcb_getnat(fin, nat, proto, port) fr_info_t *fin; nat_t *nat; u_int proto; u_int port; { + ipf_main_softc_t *softc = fin->fin_main_soft; ipnat_t *ipn, ipnat; tcphdr_t tcp; ipstate_t *is; @@ -1159,12 +1164,12 @@ ippr_rpcb_getnat(fin, nat, proto, port) /* Generate dummy fr_info */ bcopy((char *)fin, (char *)&fi, sizeof(fi)); fi.fin_out = 0; - fi.fin_src = fin->fin_dst; - fi.fin_dst = nat->nat_outip; fi.fin_p = proto; fi.fin_sport = 0; fi.fin_dport = port & 0xffff; fi.fin_flx |= FI_IGNORE; + fi.fin_saddr = nat->nat_osrcaddr; + fi.fin_daddr = nat->nat_odstaddr; bzero((char *)&tcp, sizeof(tcp)); tcp.th_dport = htons(port); @@ -1192,17 +1197,18 @@ ippr_rpcb_getnat(fin, nat, proto, port) * If successful, fr_stlookup returns with ipf_state locked. We have * no use for this lock, so simply unlock it if necessary. */ - is = fr_stlookup(&fi, &tcp, NULL); - if (is != NULL) - RWLOCK_EXIT(&ipf_state); + is = ipf_state_lookup(&fi, &tcp, NULL); + if (is != NULL) { + RWLOCK_EXIT(&softc->ipf_state); + } - RWLOCK_EXIT(&ipf_nat); + RWLOCK_EXIT(&softc->ipf_nat); - WRITE_ENTER(&ipf_nat); - natl = nat_inlookup(&fi, nflags, proto, fi.fin_src, fi.fin_dst); + WRITE_ENTER(&softc->ipf_nat); + natl = ipf_nat_inlookup(&fi, nflags, proto, fi.fin_src, fi.fin_dst); if ((natl != NULL) && (is != NULL)) { - MUTEX_DOWNGRADE(&ipf_nat); + MUTEX_DOWNGRADE(&softc->ipf_nat); return(0); } @@ -1216,6 +1222,10 @@ ippr_rpcb_getnat(fin, nat, proto, port) nflags &= ~NAT_SEARCH; if (natl == NULL) { +#ifdef USE_MUTEXES + ipf_nat_softc_t *softn = softc->ipf_nat_soft; +#endif + /* XXX Since we're just copying the original ipn contents * back, would we be better off just sending a pointer to * the 'temp' copy off to nat_new instead? @@ -1224,46 +1234,51 @@ ippr_rpcb_getnat(fin, nat, proto, port) bcopy((char *)ipn, (char *)&ipnat, sizeof(ipnat)); ipn->in_flags = nflags & IPN_TCPUDP; ipn->in_apr = NULL; - ipn->in_p = proto; - ipn->in_pmin = htons(fi.fin_dport); - ipn->in_pmax = htons(fi.fin_dport); - ipn->in_pnext = htons(fi.fin_dport); + ipn->in_pr[0] = proto; + ipn->in_pr[1] = proto; + ipn->in_dpmin = fi.fin_dport; + ipn->in_dpmax = fi.fin_dport; + ipn->in_dpnext = fi.fin_dport; ipn->in_space = 1; ipn->in_ippip = 1; if (ipn->in_flags & IPN_FILTER) { ipn->in_scmp = 0; ipn->in_dcmp = 0; } - *ipn->in_plabel = '\0'; + ipn->in_plabel = -1; /* Create NAT entry. return NULL if this fails. */ - natl = nat_new(&fi, ipn, NULL, nflags|SI_CLONE|NAT_SLAVE, + MUTEX_ENTER(&softn->ipf_nat_new); + natl = ipf_nat_add(&fi, ipn, NULL, nflags|SI_CLONE|NAT_SLAVE, NAT_INBOUND); + MUTEX_EXIT(&softn->ipf_nat_new); bcopy((char *)&ipnat, (char *)ipn, sizeof(ipnat)); if (natl == NULL) { - MUTEX_DOWNGRADE(&ipf_nat); + MUTEX_DOWNGRADE(&softc->ipf_nat); return(-1); } + natl->nat_ptr = ipn; + fi.fin_saddr = natl->nat_nsrcaddr; + fi.fin_daddr = natl->nat_ndstaddr; ipn->in_use++; - (void) nat_proto(&fi, natl, nflags); - nat_update(&fi, natl, natl->nat_ptr); + (void) ipf_nat_proto(&fi, natl, nflags); + MUTEX_ENTER(&natl->nat_lock); + ipf_nat_update(&fi, natl); + MUTEX_EXIT(&natl->nat_lock); } - MUTEX_DOWNGRADE(&ipf_nat); + MUTEX_DOWNGRADE(&softc->ipf_nat); if (is == NULL) { /* Create state entry. Return NULL if this fails. */ - fi.fin_dst = nat->nat_inip; - fi.fin_nat = (void *)natl; fi.fin_flx |= FI_NATED; fi.fin_flx &= ~FI_STATE; nflags &= NAT_TCPUDP; nflags |= SI_W_SPORT|SI_CLONE; - is = fr_addstate(&fi, NULL, nflags); - if (is == NULL) { + if (ipf_state_add(softc, &fi, NULL, nflags) != 0) { /* * XXX nat_delete is private to ip_nat.c. Should * check w/ Darren about this one. @@ -1272,15 +1287,13 @@ ippr_rpcb_getnat(fin, nat, proto, port) */ return(-1); } - if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); } return(0); } /* -------------------------------------------------------------------- */ -/* Function: ippr_rpcb_modv3 */ +/* Function: ipf_p_rpcb_modv3 */ /* Returns: int -- change in packet length */ /* Parameters: fin(I) - pointer to packet information */ /* nat(I) - pointer to NAT session */ @@ -1292,7 +1305,7 @@ ippr_rpcb_getnat(fin, nat, proto, port) /* lengths as necessary. */ /* -------------------------------------------------------------------- */ static int -ippr_rpcb_modv3(fin, nat, rm, m, off) +ipf_p_rpcb_modv3(fin, nat, rm, m, off) fr_info_t *fin; nat_t *nat; rpc_msg_t *rm; @@ -1306,7 +1319,7 @@ ippr_rpcb_modv3(fin, nat, rm, m, off) int diff; rr = &rm->rm_resp; - i = (char *)&nat->nat_outip.s_addr; + i = (char *)&nat->nat_ndstaddr; p = (char *)&rr->rr_v3.xu_port; /* Form new string. */ @@ -1332,7 +1345,7 @@ ippr_rpcb_modv3(fin, nat, rm, m, off) /* Write new string. */ COPYBACK(m, off, xlen, uaddr); - + /* Determine difference in data lengths. */ diff = xlen - XDRALIGN(B(rr->rr_v3.xu_xslen)); @@ -1341,13 +1354,13 @@ ippr_rpcb_modv3(fin, nat, rm, m, off) * adjustments. */ if (diff != 0) - ippr_rpcb_fixlen(fin, diff); + ipf_p_rpcb_fixlen(fin, diff); return(diff); } /* -------------------------------------------------------------------- */ -/* Function: ippr_rpcb_modv4 */ +/* Function: ipf_p_rpcb_modv4 */ /* Returns: int -- change in packet length */ /* Parameters: fin(I) - pointer to packet information */ /* nat(I) - pointer to NAT session */ @@ -1358,7 +1371,7 @@ ippr_rpcb_modv3(fin, nat, rm, m, off) /* Write new rpcb_entry list, adjusting lengths as necessary. */ /* -------------------------------------------------------------------- */ static int -ippr_rpcb_modv4(fin, nat, rm, m, off) +ipf_p_rpcb_modv4(fin, nat, rm, m, off) fr_info_t *fin; nat_t *nat; rpc_msg_t *rm; @@ -1377,7 +1390,7 @@ ippr_rpcb_modv4(fin, nat, rm, m, off) rr = &rm->rm_resp; rl = &rr->rr_v4; - i = (char *)&nat->nat_outip.s_addr; + i = (char *)&nat->nat_ndstaddr; /* Determine mbuf offset to write to. */ re = &rl->rl_entries[0]; @@ -1428,14 +1441,14 @@ ippr_rpcb_modv4(fin, nat, rm, m, off) * adjustments. */ if (diff != 0) - ippr_rpcb_fixlen(fin, diff); + ipf_p_rpcb_fixlen(fin, diff); return(diff); } /* -------------------------------------------------------------------- */ -/* Function: ippr_rpcb_fixlen */ +/* Function: ipf_p_rpcb_fixlen */ /* Returns: (void) */ /* Parameters: fin(I) - pointer to packet information */ /* len(I) - change in packet length */ @@ -1444,7 +1457,7 @@ ippr_rpcb_modv4(fin, nat, rm, m, off) /* header fields. */ /* -------------------------------------------------------------------- */ static void -ippr_rpcb_fixlen(fin, len) +ipf_p_rpcb_fixlen(fin, len) fr_info_t *fin; int len; { @@ -1452,9 +1465,9 @@ ippr_rpcb_fixlen(fin, len) udp = fin->fin_dp; udp->uh_ulen = htons(ntohs(udp->uh_ulen) + len); - fin->fin_ip->ip_len += len; - fin->fin_dlen += len; fin->fin_plen += len; + fin->fin_ip->ip_len = htons(fin->fin_plen); + fin->fin_dlen += len; } #undef B diff --git a/ip_scan.c b/ip_scan.c index 37f6d58ef1676..049a42f246a4f 100644 --- a/ip_scan.c +++ b/ip_scan.c @@ -1,7 +1,5 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1995-2001 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -34,7 +32,7 @@ struct file; # endif #endif #include <sys/socket.h> -#if !defined(__hpux) && !defined(__osf__) && !defined(linux) +#if !defined(__hpux) && !defined(__osf__) && !defined(linux) && !defined(AIX) # include <sys/ioccom.h> #endif #ifdef __FreeBSD__ @@ -60,17 +58,17 @@ struct file; #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_scan.c,v 2.40.2.2 2005/01/18 10:13:16 darrenr Exp"; +static const char rcsid[] = "@(#)$Id$"; #endif #ifdef IPFILTER_SCAN /* endif at bottom of file */ -ipscan_t *ipsc_list = NULL, - *ipsc_tail = NULL; -ipscanstat_t ipsc_stat; +ipscan_t *ipf_scan_list = NULL, + *ipf_scan_tail = NULL; +ipscanstat_t ipf_scan_stat; # ifdef USE_MUTEXES -ipfrwlock_t ipsc_rwlock; +ipfrwlock_t ipf_scan_rwlock; # endif # ifndef isalpha @@ -79,59 +77,72 @@ ipfrwlock_t ipsc_rwlock; # endif -int ipsc_add __P((caddr_t)); -int ipsc_delete __P((caddr_t)); -struct ipscan *ipsc_lookup __P((char *)); -int ipsc_matchstr __P((sinfo_t *, char *, int)); -int ipsc_matchisc __P((ipscan_t *, ipstate_t *, int, int, int *)); -int ipsc_match __P((ipstate_t *)); +int ipf_scan_add __P((caddr_t)); +int ipf_scan_remove __P((caddr_t)); +struct ipscan *ipf_scan_lookup __P((char *)); +int ipf_scan_matchstr __P((sinfo_t *, char *, int)); +int ipf_scan_matchisc __P((ipscan_t *, ipstate_t *, int, int, int *)); +int ipf_scan_match __P((ipstate_t *)); +static int ipf_scan_inited = 0; -int ipsc_init() +int +ipf_scan_init() { - RWLOCK_INIT(&ipsc_rwlock, "ip scan rwlock"); + RWLOCK_INIT(&ipf_scan_rwlock, "ip scan rwlock"); + ipf_scan_inited = 1; return 0; } -void fr_scanunload() +void +ipf_scan_unload(void *arg) { - RW_DESTROY(&ipsc_rwlock); + if (ipf_scan_inited == 1) { + RW_DESTROY(&ipf_scan_rwlock); + ipf_scan_inited = 0; + } } -int ipsc_add(data) -caddr_t data; +int +ipf_scan_add(data) + caddr_t data; { ipscan_t *i, *isc; int err; KMALLOC(isc, ipscan_t *); - if (!isc) + if (!isc) { + ipf_interror = 90001; return ENOMEM; + } err = copyinptr(data, isc, sizeof(*isc)); - if (err) + if (err) { + KFREE(isc); return err; + } - WRITE_ENTER(&ipsc_rwlock); + WRITE_ENTER(&ipf_scan_rwlock); - i = ipsc_lookup(isc->ipsc_tag); - if (i) { - RWLOCK_EXIT(&ipsc_rwlock); + i = ipf_scan_lookup(isc->ipsc_tag); + if (i != NULL) { + RWLOCK_EXIT(&ipf_scan_rwlock); KFREE(isc); + ipf_interror = 90002; return EEXIST; } - if (ipsc_tail) { - ipsc_tail->ipsc_next = isc; - isc->ipsc_pnext = &ipsc_tail->ipsc_next; - ipsc_tail = isc; + if (ipf_scan_tail) { + ipf_scan_tail->ipsc_next = isc; + isc->ipsc_pnext = &ipf_scan_tail->ipsc_next; + ipf_scan_tail = isc; } else { - ipsc_list = isc; - ipsc_tail = isc; - isc->ipsc_pnext = &ipsc_list; + ipf_scan_list = isc; + ipf_scan_tail = isc; + isc->ipsc_pnext = &ipf_scan_list; } isc->ipsc_next = NULL; @@ -140,14 +151,15 @@ caddr_t data; isc->ipsc_sref = 0; isc->ipsc_active = 0; - ipsc_stat.iscs_entries++; - RWLOCK_EXIT(&ipsc_rwlock); + ipf_scan_stat.iscs_entries++; + RWLOCK_EXIT(&ipf_scan_rwlock); return 0; } -int ipsc_delete(data) -caddr_t data; +int +ipf_scan_remove(data) + caddr_t data; { ipscan_t isc, *i; int err; @@ -156,14 +168,15 @@ caddr_t data; if (err) return err; - WRITE_ENTER(&ipsc_rwlock); + WRITE_ENTER(&ipf_scan_rwlock); - i = ipsc_lookup(isc.ipsc_tag); + i = ipf_scan_lookup(isc.ipsc_tag); if (i == NULL) err = ENOENT; else { if (i->ipsc_fref) { - RWLOCK_EXIT(&ipsc_rwlock); + RWLOCK_EXIT(&ipf_scan_rwlock); + ipf_interror = 90003; return EBUSY; } @@ -171,85 +184,88 @@ caddr_t data; if (i->ipsc_next) i->ipsc_next->ipsc_pnext = i->ipsc_pnext; else { - if (i->ipsc_pnext == &ipsc_list) - ipsc_tail = NULL; + if (i->ipsc_pnext == &ipf_scan_list) + ipf_scan_tail = NULL; else - ipsc_tail = *(*i->ipsc_pnext)->ipsc_pnext; + ipf_scan_tail = *(*i->ipsc_pnext)->ipsc_pnext; } - ipsc_stat.iscs_entries--; + ipf_scan_stat.iscs_entries--; KFREE(i); } - RWLOCK_EXIT(&ipsc_rwlock); + RWLOCK_EXIT(&ipf_scan_rwlock); return err; } -struct ipscan *ipsc_lookup(tag) -char *tag; +struct ipscan * +ipf_scan_lookup(tag) + char *tag; { ipscan_t *i; - for (i = ipsc_list; i; i = i->ipsc_next) + for (i = ipf_scan_list; i; i = i->ipsc_next) if (!strcmp(i->ipsc_tag, tag)) return i; return NULL; } -int ipsc_attachfr(fr) -struct frentry *fr; +int +ipf_scan_attachfr(fr) + struct frentry *fr; { ipscan_t *i; - if (fr->fr_isctag[0]) { - READ_ENTER(&ipsc_rwlock); - i = ipsc_lookup(fr->fr_isctag); + if (fr->fr_isctag != -1) { + READ_ENTER(&ipf_scan_rwlock); + i = ipf_scan_lookup(fr->fr_isctag + fr->fr_names); if (i != NULL) { ATOMIC_INC32(i->ipsc_fref); } - RWLOCK_EXIT(&ipsc_rwlock); - if (i == NULL) + RWLOCK_EXIT(&ipf_scan_rwlock); + if (i == NULL) { + ipf_interror = 90004; return ENOENT; + } fr->fr_isc = i; } return 0; } -int ipsc_attachis(is) -struct ipstate *is; +int +ipf_scan_attachis(is) + struct ipstate *is; { frentry_t *fr; ipscan_t *i; - READ_ENTER(&ipsc_rwlock); + READ_ENTER(&ipf_scan_rwlock); fr = is->is_rule; - if (fr) { + if (fr != NULL) { i = fr->fr_isc; - if (!i || (i != (ipscan_t *)-1)) { + if ((i != NULL) && (i != (ipscan_t *)-1)) { is->is_isc = i; - if (i) { - ATOMIC_INC32(i->ipsc_sref); - if (i->ipsc_clen) - is->is_flags |= IS_SC_CLIENT; - else - is->is_flags |= IS_SC_MATCHC; - if (i->ipsc_slen) - is->is_flags |= IS_SC_SERVER; - else - is->is_flags |= IS_SC_MATCHS; - } else - is->is_flags |= (IS_SC_CLIENT|IS_SC_SERVER); + ATOMIC_INC32(i->ipsc_sref); + if (i->ipsc_clen) + is->is_flags |= IS_SC_CLIENT; + else + is->is_flags |= IS_SC_MATCHC; + if (i->ipsc_slen) + is->is_flags |= IS_SC_SERVER; + else + is->is_flags |= IS_SC_MATCHS; } } - RWLOCK_EXIT(&ipsc_rwlock); + RWLOCK_EXIT(&ipf_scan_rwlock); return 0; } -int ipsc_detachfr(fr) -struct frentry *fr; +int +ipf_scan_detachfr(fr) + struct frentry *fr; { ipscan_t *i; @@ -261,18 +277,19 @@ struct frentry *fr; } -int ipsc_detachis(is) -struct ipstate *is; +int +ipf_scan_detachis(is) + struct ipstate *is; { ipscan_t *i; - READ_ENTER(&ipsc_rwlock); + READ_ENTER(&ipf_scan_rwlock); if ((i = is->is_isc) && (i != (ipscan_t *)-1)) { ATOMIC_DEC32(i->ipsc_sref); is->is_isc = NULL; is->is_flags &= ~(IS_SC_CLIENT|IS_SC_SERVER); } - RWLOCK_EXIT(&ipsc_rwlock); + RWLOCK_EXIT(&ipf_scan_rwlock); return 0; } @@ -280,10 +297,11 @@ struct ipstate *is; /* * 'string' compare for scanning */ -int ipsc_matchstr(sp, str, n) -sinfo_t *sp; -char *str; -int n; +int +ipf_scan_matchstr(sp, str, n) + sinfo_t *sp; + char *str; + int n; { char *s, *t, *up; int i = n; @@ -314,10 +332,11 @@ int n; * Returns 3 if both server and client match, 2 if just server, * 1 if just client */ -int ipsc_matchisc(isc, is, cl, sl, maxm) -ipscan_t *isc; -ipstate_t *is; -int cl, sl, maxm[2]; +int +ipf_scan_matchisc(isc, is, cl, sl, maxm) + ipscan_t *isc; + ipstate_t *is; + int cl, sl, maxm[2]; { int i, j, k, n, ret = 0, flags; @@ -346,7 +365,8 @@ int cl, sl, maxm[2]; i = 0; n = MIN(cl, isc->ipsc_clen); if ((n > 0) && (!maxm || (n >= maxm[1]))) { - if (!ipsc_matchstr(&isc->ipsc_cl, is->is_sbuf[0], n)) { + if (!ipf_scan_matchstr(&isc->ipsc_cl, + is->is_sbuf[0], n)) { i++; ret |= 1; if (n > j) @@ -362,7 +382,8 @@ int cl, sl, maxm[2]; i = 0; n = MIN(cl, isc->ipsc_slen); if ((n > 0) && (!maxm || (n >= maxm[1]))) { - if (!ipsc_matchstr(&isc->ipsc_sl, is->is_sbuf[1], n)) { + if (!ipf_scan_matchstr(&isc->ipsc_sl, + is->is_sbuf[1], n)) { i++; ret |= 2; if (n > k) @@ -379,8 +400,9 @@ int cl, sl, maxm[2]; } -int ipsc_match(is) -ipstate_t *is; +int +ipf_scan_match(is) + ipstate_t *is; { int i, j, k, n, cl, sl, maxm[2]; ipscan_t *isc, *lm; @@ -397,7 +419,7 @@ ipstate_t *is; /* * Known object to scan for. */ - i = ipsc_matchisc(isc, is, cl, sl, NULL); + i = ipf_scan_matchisc(isc, is, cl, sl, NULL); if (i & 1) { is->is_flags |= IS_SC_MATCHC; is->is_flags &= ~IS_SC_CLIENT; @@ -413,8 +435,8 @@ ipstate_t *is; lm = NULL; maxm[0] = 0; maxm[1] = 0; - for (k = 0, isc = ipsc_list; isc; isc = isc->ipsc_next) { - i = ipsc_matchisc(isc, is, cl, sl, maxm); + for (k = 0, isc = ipf_scan_list; isc; isc = isc->ipsc_next) { + i = ipf_scan_matchisc(isc, is, cl, sl, maxm); if (i) { /* * We only want to remember the best match @@ -433,6 +455,8 @@ ipstate_t *is; } if (k == 1) isc = lm; + if (isc == NULL) + return 0; /* * No matches or partial matches, so reset the respective @@ -471,7 +495,7 @@ ipstate_t *is; j = ISC_A_NONE; if ((is->is_flags & IS_SC_MATCHALL) == IS_SC_MATCHALL) { j = isc->ipsc_action; - ipsc_stat.iscs_acted++; + ipf_scan_stat.iscs_acted++; } else if ((is->is_isc != NULL) && ((is->is_flags & IS_SC_MATCHALL) != IS_SC_MATCHALL) && !(is->is_flags & (IS_SC_CLIENT|IS_SC_SERVER))) { @@ -479,7 +503,7 @@ ipstate_t *is; * Matching failed... */ j = isc->ipsc_else; - ipsc_stat.iscs_else++; + ipf_scan_stat.iscs_else++; } switch (j) @@ -504,9 +528,10 @@ ipstate_t *is; /* * check if a packet matches what we're scanning for */ -int ipsc_packet(fin, is) -fr_info_t *fin; -ipstate_t *is; +int +ipf_scan_packet(fin, is) + fr_info_t *fin; + ipstate_t *is; { int i, j, rv, dlen, off, thoff; u_32_t seq, s0; @@ -539,8 +564,8 @@ ipstate_t *is; j = 0xffff >> (16 - dlen); i = (0xffff & j) << off; #ifdef _KERNEL - COPYDATA(*(mb_t **)fin->fin_mp, fin->fin_hlen + thoff, dlen, - (caddr_t)is->is_sbuf[rv] + off); + COPYDATA(*(mb_t **)fin->fin_mp, fin->fin_plen - fin->fin_dlen + thoff, + dlen, (caddr_t)is->is_sbuf[rv] + off); #endif is->is_smsk[rv] |= i; for (j = 0, i = is->is_smsk[rv]; i & 1; i >>= 1) @@ -548,7 +573,7 @@ ipstate_t *is; if (j == 0) return 1; - (void) ipsc_match(is); + (void) ipf_scan_match(is); #if 0 /* * There is the potential here for plain text passwords to get @@ -563,10 +588,12 @@ ipstate_t *is; } -int fr_scan_ioctl(data, cmd, mode) -caddr_t data; -ioctlcmd_t cmd; -int mode; +int +ipf_scan_ioctl(data, cmd, mode, uid, ctx) + caddr_t data; + ioctlcmd_t cmd; + int mode, uid; + void *ctx; { ipscanstat_t ipscs; int err = 0; @@ -574,15 +601,19 @@ int mode; switch (cmd) { case SIOCADSCA : - err = ipsc_add(data); + err = ipf_scan_add(data); break; case SIOCRMSCA : - err = ipsc_delete(data); + err = ipf_scan_remove(data); break; case SIOCGSCST : - bcopy((char *)&ipsc_stat, (char *)&ipscs, sizeof(ipscs)); - ipscs.iscs_list = ipsc_list; - BCOPYOUT(&ipscs, data, sizeof(ipscs)); + bcopy((char *)&ipf_scan_stat, (char *)&ipscs, sizeof(ipscs)); + ipscs.iscs_list = ipf_scan_list; + err = BCOPYOUT(&ipscs, data, sizeof(ipscs)); + if (err != 0) { + ipf_interror = 90005; + err = EFAULT; + } break; default : err = EINVAL; diff --git a/ip_scan.h b/ip_scan.h index de98f9cd6b792..99032095ba05d 100644 --- a/ip_scan.h +++ b/ip_scan.h @@ -1,12 +1,10 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_fil.h 1.35 6/5/96 - * Id: ip_scan.h,v 2.9 2003/07/25 22:05:01 darrenr Exp + * $Id$ */ #ifndef __IP_SCAN_H__ @@ -27,7 +25,7 @@ struct ip; struct ipstate; -#if defined(__STDC__) || defined(__GNUC__) +#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51) # define SIOCADSCA _IOWR('r', 60, struct ipscan *) # define SIOCRMSCA _IOWR('r', 61, struct ipscan *) # define SIOCGSCST _IOWR('r', 62, struct ipscan *) @@ -96,13 +94,13 @@ typedef struct ipscanstat { } ipscanstat_t; -extern int fr_scan_ioctl __P((caddr_t, ioctlcmd_t, int)); -extern int ipsc_init __P((void)); -extern int ipsc_attachis __P((struct ipstate *)); -extern int ipsc_attachfr __P((struct frentry *)); -extern int ipsc_detachis __P((struct ipstate *)); -extern int ipsc_detachfr __P((struct frentry *)); -extern int ipsc_packet __P((struct fr_info *, struct ipstate *)); -extern void fr_scanunload __P((void)); +extern int ipf_scan_ioctl __P((ipf_main_softc_t *, caddr_t, ioctlcmd_t, int, int, void *)); +extern int ipf_scan_init __P((void)); +extern int ipf_scan_attachis __P((struct ipstate *)); +extern int ipf_scan_attachfr __P((struct frentry *)); +extern int ipf_scan_detachis __P((struct ipstate *)); +extern int ipf_scan_detachfr __P((struct frentry *)); +extern int ipf_scan_packet __P((struct fr_info *, struct ipstate *)); +extern void ipf_scan_unload __P((ipf_main_softc_t *)); #endif /* __IP_SCAN_H__ */ diff --git a/ip_sfil.c b/ip_sfil.c deleted file mode 100644 index 9e995d9b85c8d..0000000000000 --- a/ip_sfil.c +++ /dev/null @@ -1,991 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * I hate legaleese, don't you ? - */ -#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.27 2003/06/12 16:03:14 darrenr Exp $"; -#endif - -#include <sys/types.h> -#include <sys/errno.h> -#include <sys/param.h> -#include <sys/cpuvar.h> -#include <sys/open.h> -#include <sys/ioctl.h> -#include <sys/filio.h> -#include <sys/systm.h> -#include <sys/cred.h> -#include <sys/ddi.h> -#include <sys/sunddi.h> -#include <sys/ksynch.h> -#include <sys/kmem.h> -#include <sys/mkdev.h> -#include <sys/protosw.h> -#include <sys/socket.h> -#include <sys/dditypes.h> -#include <sys/cmn_err.h> -#include <net/if.h> -#include <net/af.h> -#include <net/route.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/ip_var.h> -#include <netinet/tcp.h> -#include <netinet/udp.h> -#include <netinet/tcpip.h> -#include <netinet/ip_icmp.h> -#include "ip_compat.h" -#ifdef USE_INET6 -# include <netinet/icmp6.h> -#endif -#include "ip_fil.h" -#include "ip_state.h" -#include "ip_nat.h" -#include "ip_frag.h" -#include "ip_auth.h" -#include "ip_proxy.h" -#include <inet/ip_ire.h> -#ifndef MIN -#define MIN(a,b) (((a)<(b))?(a):(b)) -#endif - - -extern fr_flags, fr_active; - -int fr_running = 0; -int ipl_unreach = ICMP_UNREACH_HOST; -u_long ipl_frouteok[2] = {0, 0}; -static int frzerostats __P((caddr_t)); -#if SOLARIS2 >= 7 -static u_int *ip_ttl_ptr; -static u_int *ip_mtudisc; -#else -static u_long *ip_ttl_ptr; -static u_long *ip_mtudisc; -#endif - -static int frrequest __P((minor_t, int, caddr_t, int)); -static int send_ip __P((fr_info_t *fin, mblk_t *m)); -kmutex_t ipl_mutex, ipf_authmx, ipf_rw; -KRWLOCK_T ipf_mutex, ipfs_mutex, ipf_solaris; -KRWLOCK_T ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth; -kcondvar_t iplwait, ipfauthwait; - - -int ipldetach() -{ - int i; - -#ifdef IPFDEBUG - cmn_err(CE_CONT, "ipldetach()\n"); -#endif -#ifdef IPFILTER_LOG - for (i = IPL_LOGMAX; i >= 0; i--) - ipflog_clear(i); -#endif - i = frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE|FR_INACTIVE); - i += frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE); - ipfr_unload(); - fr_stateunload(); - ip_natunload(); - cv_destroy(&iplwait); - cv_destroy(&ipfauthwait); - mutex_destroy(&ipf_authmx); - mutex_destroy(&ipl_mutex); - mutex_destroy(&ipf_rw); - RW_DESTROY(&ipf_mutex); - RW_DESTROY(&ipf_frag); - RW_DESTROY(&ipf_state); - RW_DESTROY(&ipf_natfrag); - RW_DESTROY(&ipf_nat); - RW_DESTROY(&ipf_auth); - RW_DESTROY(&ipfs_mutex); - /* NOTE: This lock is acquired in ipf_detach */ - RWLOCK_EXIT(&ipf_solaris); - RW_DESTROY(&ipf_solaris); - return 0; -} - - -int iplattach __P((void)) -{ - int i; - -#ifdef IPFDEBUG - cmn_err(CE_CONT, "iplattach()\n"); -#endif - bzero((char *)frcache, sizeof(frcache)); - mutex_init(&ipf_rw, "ipf rw mutex", MUTEX_DRIVER, NULL); - mutex_init(&ipl_mutex, "ipf log mutex", MUTEX_DRIVER, NULL); - mutex_init(&ipf_authmx, "ipf auth log mutex", MUTEX_DRIVER, NULL); - RWLOCK_INIT(&ipf_solaris, "ipf filter load/unload mutex", NULL); - RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock", NULL); - RWLOCK_INIT(&ipfs_mutex, "ipf solaris mutex", NULL); - RWLOCK_INIT(&ipf_frag, "ipf fragment rwlock", NULL); - RWLOCK_INIT(&ipf_state, "ipf IP state rwlock", NULL); - RWLOCK_INIT(&ipf_nat, "ipf IP NAT rwlock", NULL); - RWLOCK_INIT(&ipf_natfrag, "ipf IP NAT-Frag rwlock", NULL); - RWLOCK_INIT(&ipf_auth, "ipf IP User-Auth rwlock", NULL); - cv_init(&iplwait, "ipl condvar", CV_DRIVER, NULL); - cv_init(&ipfauthwait, "ipf auth condvar", CV_DRIVER, NULL); -#ifdef IPFILTER_LOG - ipflog_init(); -#endif - if (nat_init() == -1) - return -1; - if (fr_stateinit() == -1) - return -1; - if (appr_init() == -1) - return -1; - - ip_ttl_ptr = NULL; - ip_mtudisc = NULL; - /* - * XXX - There is no terminator for this array, so it is not possible - * to tell if what we are looking for is missing and go off the end - * of the array. - */ - for (i = 0; ; i++) { - if (strcmp(ip_param_arr[i].ip_param_name, "ip_def_ttl") == 0) { - ip_ttl_ptr = &ip_param_arr[i].ip_param_value; - } else if (strcmp(ip_param_arr[i].ip_param_name, - "ip_path_mtu_discovery") == 0) { - ip_mtudisc = &ip_param_arr[i].ip_param_value; - } - - if (ip_mtudisc != NULL && ip_ttl_ptr != NULL) - break; - } - return 0; -} - - -static int frzerostats(data) -caddr_t data; -{ - friostat_t fio; - int error; - - fr_getstat(&fio); - error = IWCOPYPTR((caddr_t)&fio, data, sizeof(fio)); - if (error) - return error; - - bzero((char *)frstats, sizeof(*frstats) * 2); - - return 0; -} - - -/* - * Filter ioctl interface. - */ -int iplioctl(dev, cmd, data, mode, cp, rp) -dev_t dev; -int cmd; -#if SOLARIS2 >= 7 -intptr_t data; -#else -int *data; -#endif -int mode; -cred_t *cp; -int *rp; -{ - int error = 0, tmp; - minor_t unit; - -#ifdef IPFDEBUG - cmn_err(CE_CONT, "iplioctl(%x,%x,%x,%d,%x,%d)\n", - dev, cmd, data, mode, cp, rp); -#endif - unit = getminor(dev); - if (IPL_LOGMAX < unit) - return ENXIO; - - if (fr_running == 0 && (cmd != SIOCFRENB || unit != IPL_LOGIPF)) - return ENODEV; - - if (fr_running <= 0) - return 0; - - READ_ENTER(&ipf_solaris); - if (unit == IPL_LOGNAT) { - error = nat_ioctl((caddr_t)data, cmd, mode); - RWLOCK_EXIT(&ipf_solaris); - return error; - } - if (unit == IPL_LOGSTATE) { - error = fr_state_ioctl((caddr_t)data, cmd, mode); - RWLOCK_EXIT(&ipf_solaris); - return error; - } - if (unit == IPL_LOGAUTH) { - if ((cmd == SIOCADAFR) || (cmd == SIOCRMAFR)) { - if (!(mode & FWRITE)) { - error = EPERM; - } else { - error = frrequest(unit, cmd, (caddr_t)data, - fr_active); - } - } else { - error = fr_auth_ioctl((caddr_t)data, mode, cmd); - } - RWLOCK_EXIT(&ipf_solaris); - return error; - } - - switch (cmd) { - case SIOCFRENB : - { - u_int enable; - - if (!(mode & FWRITE)) - error = EPERM; - else - error = IRCOPY((caddr_t)data, (caddr_t)&enable, - sizeof(enable)); - break; - } - case SIOCSETFF : - if (!(mode & FWRITE)) - error = EPERM; - else { - WRITE_ENTER(&ipf_mutex); - error = IRCOPY((caddr_t)data, (caddr_t)&fr_flags, - sizeof(fr_flags)); - RWLOCK_EXIT(&ipf_mutex); - } - break; - case SIOCGETFF : - error = IWCOPY((caddr_t)&fr_flags, (caddr_t)data, - sizeof(fr_flags)); - if (error) - error = EFAULT; - break; - case SIOCINAFR : - case SIOCRMAFR : - case SIOCADAFR : - case SIOCZRLST : - if (!(mode & FWRITE)) - error = EPERM; - else - error = frrequest(unit, cmd, (caddr_t)data, fr_active); - break; - case SIOCINIFR : - case SIOCRMIFR : - case SIOCADIFR : - if (!(mode & FWRITE)) - error = EPERM; - else - error = frrequest(unit, cmd, (caddr_t)data, - 1 - fr_active); - break; - case SIOCSWAPA : - if (!(mode & FWRITE)) - error = EPERM; - else { - WRITE_ENTER(&ipf_mutex); - bzero((char *)frcache, sizeof(frcache[0]) * 2); - error = IWCOPY((caddr_t)&fr_active, (caddr_t)data, - sizeof(fr_active)); - if (error) - error = EFAULT; - fr_active = 1 - fr_active; - RWLOCK_EXIT(&ipf_mutex); - } - break; - case SIOCGETFS : - { - friostat_t fio; - - READ_ENTER(&ipf_mutex); - fr_getstat(&fio); - RWLOCK_EXIT(&ipf_mutex); - error = IWCOPYPTR((caddr_t)&fio, (caddr_t)data, sizeof(fio)); - if (error) - error = EFAULT; - break; - } - case SIOCFRZST : - if (!(mode & FWRITE)) - error = EPERM; - else - error = frzerostats((caddr_t)data); - break; - case SIOCIPFFL : - if (!(mode & FWRITE)) - error = EPERM; - else { - error = IRCOPY((caddr_t)data, (caddr_t)&tmp, - sizeof(tmp)); - if (!error) { - tmp = frflush(unit, 4, tmp); - error = IWCOPY((caddr_t)&tmp, (caddr_t)data, - sizeof(tmp)); - if (error) - error = EFAULT; - } - } - break; -#ifdef USE_INET6 - case SIOCIPFL6 : - if (!(mode & FWRITE)) - error = EPERM; - else { - error = IRCOPY((caddr_t)data, (caddr_t)&tmp, - sizeof(tmp)); - if (!error) { - tmp = frflush(unit, 6, tmp); - error = IWCOPY((caddr_t)&tmp, (caddr_t)data, - sizeof(tmp)); - if (error) - error = EFAULT; - } - } - break; -#endif - case SIOCSTLCK : - error = IRCOPY((caddr_t)data, (caddr_t)&tmp, sizeof(tmp)); - if (!error) { - fr_state_lock = tmp; - fr_nat_lock = tmp; - fr_frag_lock = tmp; - fr_auth_lock = tmp; - } else - error = EFAULT; - break; -#ifdef IPFILTER_LOG - case SIOCIPFFB : - if (!(mode & FWRITE)) - error = EPERM; - else { - tmp = ipflog_clear(unit); - error = IWCOPY((caddr_t)&tmp, (caddr_t)data, - sizeof(tmp)); - if (error) - error = EFAULT; - } - break; -#endif /* IPFILTER_LOG */ - case SIOCFRSYN : - if (!(mode & FWRITE)) - error = EPERM; - else - error = ipfsync(); - break; - case SIOCGFRST : - error = IWCOPYPTR((caddr_t)ipfr_fragstats(), (caddr_t)data, - sizeof(ipfrstat_t)); - break; - case FIONREAD : - { -#ifdef IPFILTER_LOG - int copy = (int)iplused[IPL_LOGIPF]; - - error = IWCOPY((caddr_t)©, (caddr_t)data, sizeof(copy)); - if (error) - error = EFAULT; -#endif - break; - } - default : - error = EINVAL; - break; - } - RWLOCK_EXIT(&ipf_solaris); - return error; -} - - -ill_t *get_unit(name, v) -char *name; -int v; -{ - size_t len = strlen(name) + 1; /* includes \0 */ - ill_t *il; -#if SOLARIS2 >= 10 - ill_walk_context_t ctx; -#endif - int sap; - - if (v == 4) - sap = 0x0800; - else if (v == 6) - sap = 0x86dd; - else - return NULL; -#if SOLARIS2 >= 10 - for (il = ILL_START_WALK_ALL(&ctx); il; il = ill_next(&ctx, il)) -#else - for (il = ill_g_head; il; il = il->ill_next) -#endif - if ((len == il->ill_name_length) && (il->ill_sap == sap) && - !strncmp(il->ill_name, name, len)) - return il; - return NULL; -} - - -static int frrequest(unit, req, data, set) -minor_t unit; -int req, set; -caddr_t data; -{ - register frentry_t *fp, *f, **fprev; - register frentry_t **ftail; - frgroup_t *fg = NULL; - int error = 0, in, i; - u_int *p, *pp; - frdest_t *fdp; - frentry_t fr; - u_32_t group; - ipif_t *ipif; - ill_t *ill; - ire_t *ire; - - fp = &fr; - error = IRCOPYPTR(data, (caddr_t)fp, sizeof(*fp)); - if (error) - return EFAULT; - fp->fr_ref = 0; -#if SOLARIS2 >= 8 - if (fp->fr_v == 4) - fp->fr_sap = IP_DL_SAP; - else if (fp->fr_v == 6) - fp->fr_sap = IP6_DL_SAP; - else - return EINVAL; -#else - fp->fr_sap = 0; -#endif - - WRITE_ENTER(&ipf_mutex); - /* - * Check that the group number does exist and that if a head group - * has been specified, doesn't exist. - */ - if ((req != SIOCZRLST) && ((req == SIOCINAFR) || (req == SIOCINIFR) || - (req == SIOCADAFR) || (req == SIOCADIFR)) && fp->fr_grhead && - fr_findgroup(fp->fr_grhead, fp->fr_flags, unit, set, NULL)) { - error = EEXIST; - goto out; - } - if ((req != SIOCZRLST) && fp->fr_group && - !fr_findgroup(fp->fr_group, fp->fr_flags, unit, set, NULL)) { - error = ESRCH; - goto out; - } - - in = (fp->fr_flags & FR_INQUE) ? 0 : 1; - - if (unit == IPL_LOGAUTH) - ftail = fprev = &ipauth; - else if ((fp->fr_flags & FR_ACCOUNT) && (fp->fr_v == 4)) - ftail = fprev = &ipacct[in][set]; - else if ((fp->fr_flags & (FR_OUTQUE|FR_INQUE)) && (fp->fr_v == 4)) - ftail = fprev = &ipfilter[in][set]; -#ifdef USE_INET6 - else if ((fp->fr_flags & FR_ACCOUNT) && (fp->fr_v == 6)) - ftail = fprev = &ipacct6[in][set]; - else if ((fp->fr_flags & (FR_OUTQUE|FR_INQUE)) && (fp->fr_v == 6)) - ftail = fprev = &ipfilter6[in][set]; -#endif - else { - error = ESRCH; - goto out; - } - - group = fp->fr_group; - if (group != 0) { - fg = fr_findgroup(group, fp->fr_flags, unit, set, NULL); - if (fg == NULL) { - error = ESRCH; - goto out; - } - ftail = fprev = fg->fg_start; - } - - bzero((char *)frcache, sizeof(frcache[0]) * 2); - - for (i = 0; i < 4; i++) { - if ((fp->fr_ifnames[i][1] == '\0') && - ((fp->fr_ifnames[i][0] == '-') || - (fp->fr_ifnames[i][0] == '*'))) { - fp->fr_ifas[i] = NULL; - } else if (*fp->fr_ifnames[i]) { - fp->fr_ifas[i] = GETUNIT(fp->fr_ifnames[i], fp->fr_v); - if (!fp->fr_ifas[i]) - fp->fr_ifas[i] = (void *)-1; - } - } - - fdp = &fp->fr_dif; - fdp->fd_mp = NULL; - fp->fr_flags &= ~FR_DUP; - if (*fdp->fd_ifname) { - ill = get_unit(fdp->fd_ifname, (int)fp->fr_v); - if (!ill) - ire = (ire_t *)-1; - else if ((ipif = ill->ill_ipif) && (fp->fr_v == 4)) { -#if SOLARIS2 > 5 - ire = ire_ctable_lookup(ipif->ipif_local_addr, 0, - IRE_LOCAL, NULL, NULL, - MATCH_IRE_TYPE); -#else - ire = ire_lookup_myaddr(ipif->ipif_local_addr); -#endif - if (!ire) - ire = (ire_t *)-1; - else - fp->fr_flags |= FR_DUP; - } -#ifdef USE_INET6 - else if ((ipif = ill->ill_ipif) && (fp->fr_v == 6)) { - ire = ire_ctable_lookup_v6(&ipif->ipif_v6lcl_addr, 0, - IRE_LOCAL, NULL, NULL, - MATCH_IRE_TYPE); - if (!ire) - ire = (ire_t *)-1; - else - fp->fr_flags |= FR_DUP; - } -#endif - fdp->fd_ifp = (struct ifnet *)ire; - } - - fdp = &fp->fr_tif; - fdp->fd_mp = NULL; - if (*fdp->fd_ifname) { - ill = get_unit(fdp->fd_ifname, (int)fp->fr_v); - if (!ill) - ire = (ire_t *)-1; - else if ((ipif = ill->ill_ipif) && (fp->fr_v == 4)) { -#if SOLARIS2 > 5 - ire = ire_ctable_lookup(ipif->ipif_local_addr, 0, - IRE_LOCAL, NULL, NULL, - MATCH_IRE_TYPE); -#else - ire = ire_lookup_myaddr(ipif->ipif_local_addr); -#endif - if (!ire) - ire = (ire_t *)-1; - } -#ifdef USE_INET6 - else if ((ipif = ill->ill_ipif) && (fp->fr_v == 6)) { - ire = ire_ctable_lookup_v6(&ipif->ipif_v6lcl_addr, 0, - IRE_LOCAL, NULL, NULL, - MATCH_IRE_TYPE); - if (!ire) - ire = (ire_t *)-1; - } -#endif - fdp->fd_ifp = (struct ifnet *)ire; - } - - /* - * Look for a matching filter rule, but don't include the next or - * interface pointer in the comparison (fr_next, fr_ifa). - */ - for (fp->fr_cksum = 0, p = (u_int *)&fp->fr_ip, pp = &fp->fr_cksum; - p < pp; p++) - fp->fr_cksum += *p; - - for (; (f = *ftail); ftail = &f->fr_next) - if ((fp->fr_cksum == f->fr_cksum) && - !bcmp((char *)&f->fr_ip, (char *)&fp->fr_ip, FR_CMPSIZ)) - break; - - /* - * If zero'ing statistics, copy current to caller and zero. - */ - if (req == SIOCZRLST) { - if (!f) { - error = ESRCH; - goto out; - } - MUTEX_DOWNGRADE(&ipf_mutex); - error = IWCOPYPTR((caddr_t)f, data, sizeof(*f)); - if (error) - goto out; - f->fr_hits = 0; - f->fr_bytes = 0; - goto out; - } - - if (!f) { - if (req != SIOCINAFR && req != SIOCINIFR) - while ((f = *ftail)) - ftail = &f->fr_next; - else { - ftail = fprev; - if (fp->fr_hits) { - while (--fp->fr_hits && (f = *ftail)) - ftail = &f->fr_next; - } - f = NULL; - } - } - - if (req == SIOCRMAFR || req == SIOCRMIFR) { - if (!f) - error = ESRCH; - else { - /* - * Only return EBUSY if there is a group list, else - * it's probably just state information referencing - * the rule. - */ - if ((f->fr_ref > 1) && f->fr_grp) { - error = EBUSY; - goto out; - } - if (fg && fg->fg_head) - fg->fg_head->fr_ref--; - if (unit == IPL_LOGAUTH) { - return fr_preauthcmd(req, f, ftail); - } - if (f->fr_grhead) - fr_delgroup(f->fr_grhead, fp->fr_flags, - unit, set); - fixskip(fprev, f, -1); - *ftail = f->fr_next; - f->fr_next = NULL; - f->fr_ref--; - if (f->fr_ref == 0) - KFREE(f); - } - } else { - if (f) { - error = EEXIST; - } else { - if (unit == IPL_LOGAUTH) { - return fr_preauthcmd(req, fp, ftail); - } - KMALLOC(f, frentry_t *); - if (f != NULL) { - if (fg && fg->fg_head) - fg->fg_head->fr_ref++; - bcopy((char *)fp, (char *)f, sizeof(*f)); - f->fr_ref = 1; - f->fr_hits = 0; - f->fr_next = *ftail; - *ftail = f; - if (req == SIOCINIFR || req == SIOCINAFR) - fixskip(fprev, f, 1); - f->fr_grp = NULL; - group = f->fr_grhead; - if (group != 0) - fg = fr_addgroup(group, f, unit, set); - } else - error = ENOMEM; - } - } -out: - RWLOCK_EXIT(&ipf_mutex); - return (error); -} - - -/* - * routines below for saving IP headers to buffer - */ -int iplopen(devp, flags, otype, cred) -dev_t *devp; -int flags, otype; -cred_t *cred; -{ - minor_t min = getminor(*devp); - -#ifdef IPFDEBUG - cmn_err(CE_CONT, "iplopen(%x,%x,%x,%x)\n", devp, flags, otype, cred); -#endif - if ((fr_running <= 0) || !(otype & OTYP_CHR)) - return ENXIO; - min = (IPL_LOGMAX < min) ? ENXIO : 0; - return min; -} - - -int iplclose(dev, flags, otype, cred) -dev_t dev; -int flags, otype; -cred_t *cred; -{ - minor_t min = getminor(dev); - -#ifdef IPFDEBUG - cmn_err(CE_CONT, "iplclose(%x,%x,%x,%x)\n", dev, flags, otype, cred); -#endif - min = (IPL_LOGMAX < min) ? ENXIO : 0; - return min; -} - -#ifdef IPFILTER_LOG -/* - * iplread/ipllog - * both of these must operate with at least splnet() lest they be - * called during packet processing and cause an inconsistancy to appear in - * the filter lists. - */ -int iplread(dev, uio, cp) -dev_t dev; -register struct uio *uio; -cred_t *cp; -{ -#ifdef IPFDEBUG - cmn_err(CE_CONT, "iplread(%x,%x,%x)\n", dev, uio, cp); -#endif - return ipflog_read(getminor(dev), uio); -} -#endif /* IPFILTER_LOG */ - - -/* - * send_reset - this could conceivably be a call to tcp_respond(), but that - * requires a large amount of setting up and isn't any more efficient. - */ -int send_reset(oip, fin) -ip_t *oip; -fr_info_t *fin; -{ - tcphdr_t *tcp, *tcp2; - int tlen, hlen; - mblk_t *m; -#ifdef USE_INET6 - ip6_t *ip6, *oip6 = (ip6_t *)oip; -#endif - ip_t *ip; - - tcp = (struct tcphdr *)fin->fin_dp; - if (tcp->th_flags & TH_RST) - return -1; - tlen = (tcp->th_flags & (TH_SYN|TH_FIN)) ? 1 : 0; -#ifdef USE_INET6 - if (fin->fin_v == 6) - hlen = sizeof(ip6_t); - else -#endif - hlen = sizeof(ip_t); - hlen += sizeof(*tcp2); - if ((m = (mblk_t *)allocb(hlen + 16, BPRI_HI)) == NULL) - return -1; - - m->b_rptr += 16; - MTYPE(m) = M_DATA; - m->b_wptr = m->b_rptr + hlen; - bzero((char *)m->b_rptr, hlen); - tcp2 = (struct tcphdr *)(m->b_rptr + hlen - sizeof(*tcp2)); - tcp2->th_dport = tcp->th_sport; - tcp2->th_sport = tcp->th_dport; - 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(struct tcphdr) >> 2; - - /* - * This is to get around a bug in the Solaris 2.4/2.5 TCP checksum - * computation that is done by their put routine. - */ - tcp2->th_sum = htons(0x14); -#ifdef USE_INET6 - if (fin->fin_v == 6) { - ip6 = (ip6_t *)m->b_rptr; - ip6->ip6_src = oip6->ip6_dst; - ip6->ip6_dst = oip6->ip6_src; - ip6->ip6_plen = htons(sizeof(*tcp)); - ip6->ip6_nxt = IPPROTO_TCP; - } else -#endif - { - ip = (ip_t *)m->b_rptr; - ip->ip_src.s_addr = oip->ip_dst.s_addr; - ip->ip_dst.s_addr = oip->ip_src.s_addr; - ip->ip_hl = sizeof(*ip) >> 2; - ip->ip_p = IPPROTO_TCP; - ip->ip_len = htons(sizeof(*ip) + sizeof(*tcp)); - ip->ip_tos = oip->ip_tos; - } - return send_ip(fin, m); -} - - -int static send_ip(fin, m) -fr_info_t *fin; -mblk_t *m; -{ - RWLOCK_EXIT(&ipfs_mutex); - RWLOCK_EXIT(&ipf_solaris); -#ifdef USE_INET6 - if (fin->fin_v == 6) { - extern void ip_wput_v6 __P((queue_t *, mblk_t *)); - ip6_t *ip6; - - ip6 = (ip6_t *)m->b_rptr; - ip6->ip6_flow = 0; - ip6->ip6_vfc = 0x60; - ip6->ip6_hlim = 127; - ip_wput_v6(((qif_t *)fin->fin_qif)->qf_ill->ill_wq, m); - } else -#endif - { - ip_t *ip; - - ip = (ip_t *)m->b_rptr; - ip->ip_v = IPVERSION; - ip->ip_ttl = (u_char)(*ip_ttl_ptr); - ip->ip_off = htons(*ip_mtudisc ? IP_DF : 0); - ip_wput(((qif_t *)fin->fin_qif)->qf_ill->ill_wq, m); - } - READ_ENTER(&ipf_solaris); - READ_ENTER(&ipfs_mutex); - return 0; -} - - -int send_icmp_err(oip, type, fin, dst) -ip_t *oip; -int type; -fr_info_t *fin; -int dst; -{ - struct in_addr dst4; - struct icmp *icmp; - mblk_t *m, *mb; - int hlen, code; - qif_t *qif; - u_short sz; - ill_t *il; -#ifdef USE_INET6 - ip6_t *ip6, *oip6; -#endif - ip_t *ip; - - if ((type < 0) || (type > ICMP_MAXTYPE)) - return -1; - - code = fin->fin_icode; -#ifdef USE_INET6 - if ((code < 0) || (code > sizeof(icmptoicmp6unreach)/sizeof(int))) - return -1; -#endif - - qif = fin->fin_qif; - m = fin->fin_qfm; - -#ifdef USE_INET6 - if (oip->ip_v == 6) { - oip6 = (ip6_t *)oip; - sz = sizeof(ip6_t); - sz += MIN(m->b_wptr - m->b_rptr, 512); - hlen = sizeof(ip6_t); - type = icmptoicmp6types[type]; - if (type == ICMP6_DST_UNREACH) - code = icmptoicmp6unreach[code]; - } else -#endif - { - if ((oip->ip_p == IPPROTO_ICMP) && - !(fin->fin_fi.fi_fl & FI_SHORT)) - switch (ntohs(fin->fin_data[0]) >> 8) - { - case ICMP_ECHO : - case ICMP_TSTAMP : - case ICMP_IREQ : - case ICMP_MASKREQ : - break; - default : - return 0; - } - - sz = sizeof(ip_t) * 2; - sz += 8; /* 64 bits of data */ - hlen = sz; - } - - sz += offsetof(struct icmp, icmp_ip); - if ((mb = (mblk_t *)allocb((size_t)sz + 16, BPRI_HI)) == NULL) - return -1; - MTYPE(mb) = M_DATA; - mb->b_rptr += 16; - mb->b_wptr = mb->b_rptr + sz; - bzero((char *)mb->b_rptr, (size_t)sz); - icmp = (struct icmp *)(mb->b_rptr + sizeof(*ip)); - 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) { - struct in6_addr dst6; - int csz; - - if (dst == 0) { - if (fr_ifpaddr(6, ((qif_t *)fin->fin_qif)->qf_ill, - (struct in_addr *)&dst6) == -1) - return -1; - } else - dst6 = oip6->ip6_dst; - - csz = sz; - sz -= sizeof(ip6_t); - ip6 = (ip6_t *)mb->b_rptr; - ip6->ip6_flow = 0; - ip6->ip6_vfc = 0x60; - ip6->ip6_hlim = 127; - ip6->ip6_plen = htons(sz); - ip6->ip6_nxt = IPPROTO_ICMPV6; - ip6->ip6_src = dst6; - ip6->ip6_dst = oip6->ip6_src; - sz -= offsetof(struct icmp, icmp_ip); - bcopy((char *)m->b_rptr, (char *)&icmp->icmp_ip, sz); - icmp->icmp_cksum = csz - sizeof(ip6_t); - } else -#endif - { - ip = (ip_t *)mb->b_rptr; - ip->ip_v = IPVERSION; - ip->ip_hl = (sizeof(*ip) >> 2); - ip->ip_p = IPPROTO_ICMP; - ip->ip_id = oip->ip_id; - ip->ip_sum = 0; - ip->ip_ttl = (u_char)(*ip_ttl_ptr); - ip->ip_tos = oip->ip_tos; - ip->ip_len = (u_short)htons(sz); - if (dst == 0) { - if (fr_ifpaddr(4, ((qif_t *)fin->fin_qif)->qf_ill, - &dst4) == -1) - return -1; - } else - dst4 = oip->ip_dst; - ip->ip_src = dst4; - ip->ip_dst = oip->ip_src; - bcopy((char *)oip, (char *)&icmp->icmp_ip, sizeof(*oip)); - bcopy((char *)oip + (oip->ip_hl << 2), - (char *)&icmp->icmp_ip + sizeof(*oip), 8); - icmp->icmp_cksum = ipf_cksum((u_short *)icmp, - sizeof(*icmp) + 8); - } - - /* - * Need to exit out of these so we don't recursively call rw_enter - * from fr_qout. - */ - return send_ip(fin, mb); -} diff --git a/ip_state.c b/ip_state.c index 4ced16d3460df..19580a2f3c194 100644 --- a/ip_state.c +++ b/ip_state.c @@ -1,9 +1,11 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1995-2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. + * + * Copyright 2008 Sun Microsystems. + * + * $Id$ */ #if defined(KERNEL) || defined(_KERNEL) # undef KERNEL @@ -15,10 +17,6 @@ #include <sys/types.h> #include <sys/param.h> #include <sys/file.h> -#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ - defined(_KERNEL) -# include "opt_ipfilter_log.h" -#endif #if defined(_KERNEL) && defined(__FreeBSD_version) && \ (__FreeBSD_version >= 400000) && !defined(KLD_MODULE) #include "opt_inet6.h" @@ -37,9 +35,6 @@ struct file; #if defined(_KERNEL) && (__FreeBSD_version >= 220000) # include <sys/filio.h> # include <sys/fcntl.h> -# if (__FreeBSD_version >= 300000) && !defined(IPFILTER_LKM) -# include "opt_ipfilter.h" -# endif #else # include <sys/ioctl.h> #endif @@ -68,36 +63,31 @@ struct file; #ifdef sun # include <net/af.h> #endif -#include <net/route.h> #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> #include <netinet/tcp.h> -#if !defined(linux) -# include <netinet/ip_var.h> -#endif #if !defined(__hpux) && !defined(linux) # include <netinet/tcp_fsm.h> #endif #include <netinet/udp.h> #include <netinet/ip_icmp.h> +#if !defined(_KERNEL) +# include "ipf.h" +#endif #include "netinet/ip_compat.h" -#include <netinet/tcpip.h> #include "netinet/ip_fil.h" #include "netinet/ip_nat.h" #include "netinet/ip_frag.h" #include "netinet/ip_state.h" #include "netinet/ip_proxy.h" -#ifdef IPFILTER_SYNC +#include "netinet/ip_lookup.h" +#include "netinet/ip_dstlist.h" #include "netinet/ip_sync.h" -#endif -#ifdef IPFILTER_SCAN -#include "netinet/ip_scan.h" -#endif #ifdef USE_INET6 #include <netinet/icmp6.h> #endif -#if (__FreeBSD_version >= 300000) +#if FREEBSD_GE_REV(300000) # include <sys/malloc.h> # if defined(_KERNEL) && !defined(IPFILTER_LKM) # include <sys/libkern.h> @@ -109,319 +99,503 @@ struct file; #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.186.2.29 2005/03/28 10:47:54 darrenr Exp"; +static const char rcsid[] = "@(#)$Id$"; #endif -static ipstate_t **ips_table = NULL; -static u_long *ips_seed = NULL; -static int ips_num = 0; -static u_long ips_last_force_flush = 0; -ips_stat_t ips_stats; + +static ipftuneable_t ipf_state_tuneables[] = { + { { (void *)offsetof(ipf_state_softc_t, ipf_state_max) }, + "state_max", 1, 0x7fffffff, + stsizeof(ipf_state_softc_t, ipf_state_max), + 0, NULL, NULL }, + { { (void *)offsetof(ipf_state_softc_t, ipf_state_size) }, + "state_size", 1, 0x7fffffff, + stsizeof(ipf_state_softc_t, ipf_state_size), + 0, NULL, ipf_state_rehash }, + { { (void *)offsetof(ipf_state_softc_t, ipf_state_lock) }, + "state_lock", 0, 1, + stsizeof(ipf_state_softc_t, ipf_state_lock), + IPFT_RDONLY, NULL, NULL }, + { { (void *)offsetof(ipf_state_softc_t, ipf_state_maxbucket) }, + "state_maxbucket", 1, 0x7fffffff, + stsizeof(ipf_state_softc_t, ipf_state_maxbucket), + 0, NULL, NULL }, + { { (void *)offsetof(ipf_state_softc_t, ipf_state_logging) }, + "state_logging",0, 1, + stsizeof(ipf_state_softc_t, ipf_state_logging), + 0, NULL, NULL }, + { { (void *)offsetof(ipf_state_softc_t, ipf_state_wm_high) }, + "state_wm_high",2, 100, + stsizeof(ipf_state_softc_t, ipf_state_wm_high), + 0, NULL, NULL }, + { { (void *)offsetof(ipf_state_softc_t, ipf_state_wm_low) }, + "state_wm_low", 1, 99, + stsizeof(ipf_state_softc_t, ipf_state_wm_low), + 0, NULL, NULL }, + { { (void *)offsetof(ipf_state_softc_t, ipf_state_wm_freq) }, + "state_wm_freq",2, 999999, + stsizeof(ipf_state_softc_t, ipf_state_wm_freq), + 0, NULL, NULL }, + { { NULL }, + NULL, 0, 0, + 0, + 0, NULL, NULL } +}; + +#define SINCL(x) ATOMIC_INCL(softs->x) +#define SBUMP(x) (softs->x)++ +#define SBUMPD(x, y) do { (softs->x.y)++; DT(y); } while (0) +#define SBUMPDX(x, y, z)do { (softs->x.y)++; DT(z); } while (0) #ifdef USE_INET6 -static ipstate_t *fr_checkicmp6matchingstate __P((fr_info_t *)); +static ipstate_t *ipf_checkicmp6matchingstate __P((fr_info_t *)); #endif -static ipstate_t *fr_matchsrcdst __P((fr_info_t *, ipstate_t *, i6addr_t *, +static int ipf_allowstateicmp __P((fr_info_t *, ipstate_t *, i6addr_t *)); +static ipstate_t *ipf_matchsrcdst __P((fr_info_t *, ipstate_t *, i6addr_t *, i6addr_t *, tcphdr_t *, u_32_t)); -static ipstate_t *fr_checkicmpmatchingstate __P((fr_info_t *)); -static int fr_state_flush __P((int, int)); -static ips_stat_t *fr_statetstats __P((void)); -static void fr_delstate __P((ipstate_t *, int)); -static int fr_state_remove __P((caddr_t)); -static void fr_ipsmove __P((ipstate_t *, u_int)); -static int fr_tcpstate __P((fr_info_t *, tcphdr_t *, ipstate_t *)); -static int fr_tcpoptions __P((fr_info_t *, tcphdr_t *, tcpdata_t *)); -static ipstate_t *fr_stclone __P((fr_info_t *, tcphdr_t *, ipstate_t *)); -static void fr_fixinisn __P((fr_info_t *, ipstate_t *)); -static void fr_fixoutisn __P((fr_info_t *, ipstate_t *)); -static void fr_checknewisn __P((fr_info_t *, ipstate_t *)); - -int fr_stputent __P((caddr_t)); -int fr_stgetent __P((caddr_t)); +static ipstate_t *ipf_checkicmpmatchingstate __P((fr_info_t *)); +static int ipf_state_flush_entry __P((ipf_main_softc_t *, void *)); +static ips_stat_t *ipf_state_stats __P((ipf_main_softc_t *)); +static int ipf_state_del __P((ipf_main_softc_t *, ipstate_t *, int)); +static int ipf_state_remove __P((ipf_main_softc_t *, caddr_t)); +static int ipf_state_match __P((ipstate_t *is1, ipstate_t *is2)); +static int ipf_state_matchaddresses __P((ipstate_t *is1, ipstate_t *is2)); +static int ipf_state_matchipv4addrs __P((ipstate_t *is1, ipstate_t *is2)); +static int ipf_state_matchipv6addrs __P((ipstate_t *is1, ipstate_t *is2)); +static int ipf_state_matchisps __P((ipstate_t *is1, ipstate_t *is2)); +static int ipf_state_matchports __P((udpinfo_t *is1, udpinfo_t *is2)); +static int ipf_state_matcharray __P((ipstate_t *, int *, u_long)); +static void ipf_ipsmove __P((ipf_state_softc_t *, ipstate_t *, u_int)); +static int ipf_state_tcp __P((ipf_main_softc_t *, ipf_state_softc_t *, + fr_info_t *, tcphdr_t *, ipstate_t *)); +static int ipf_tcpoptions __P((ipf_state_softc_t *, fr_info_t *, + tcphdr_t *, tcpdata_t *)); +static ipstate_t *ipf_state_clone __P((fr_info_t *, tcphdr_t *, ipstate_t *)); +static void ipf_fixinisn __P((fr_info_t *, ipstate_t *)); +static void ipf_fixoutisn __P((fr_info_t *, ipstate_t *)); +static void ipf_checknewisn __P((fr_info_t *, ipstate_t *)); +static int ipf_state_iter __P((ipf_main_softc_t *, ipftoken_t *, + ipfgeniter_t *, ipfobj_t *)); +static int ipf_state_gettable __P((ipf_main_softc_t *, ipf_state_softc_t *, + char *)); +static int ipf_state_tcpinwindow __P((struct fr_info *, struct tcpdata *, + struct tcpdata *, tcphdr_t *, int)); + +static int ipf_state_getent __P((ipf_main_softc_t *, ipf_state_softc_t *, + caddr_t)); +static int ipf_state_putent __P((ipf_main_softc_t *, ipf_state_softc_t *, + caddr_t)); #define ONE_DAY IPF_TTLVAL(1 * 86400) /* 1 day */ #define FIVE_DAYS (5 * ONE_DAY) -#define DOUBLE_HASH(x) (((x) + ips_seed[(x) % fr_statesize]) % fr_statesize) - -u_long fr_tcpidletimeout = FIVE_DAYS, - fr_tcpclosewait = IPF_TTLVAL(2 * TCP_MSL), - fr_tcplastack = IPF_TTLVAL(2 * TCP_MSL), - fr_tcptimeout = IPF_TTLVAL(2 * TCP_MSL), - fr_tcpclosed = IPF_TTLVAL(60), - fr_tcphalfclosed = IPF_TTLVAL(2 * 3600), /* 2 hours */ - fr_udptimeout = IPF_TTLVAL(120), - fr_udpacktimeout = IPF_TTLVAL(12), - fr_icmptimeout = IPF_TTLVAL(60), - fr_icmpacktimeout = IPF_TTLVAL(6), - fr_iptimeout = IPF_TTLVAL(60); -int fr_statemax = IPSTATE_MAX, - fr_statesize = IPSTATE_SIZE; -int fr_state_doflush = 0, - fr_state_lock = 0, - fr_state_maxbucket = 0, - fr_state_maxbucket_reset = 1, - fr_state_init = 0; -ipftq_t ips_tqtqb[IPF_TCP_NSTATES], - ips_udptq, - ips_udpacktq, - ips_iptq, - ips_icmptq, - ips_icmpacktq, - *ips_utqe = NULL; +#define DOUBLE_HASH(x) (((x) + softs->ipf_state_seed[(x) % \ + softs->ipf_state_size]) % softs->ipf_state_size) + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_state_main_load */ +/* Returns: int - 0 == success, -1 == failure */ +/* Parameters: Nil */ +/* */ +/* A null-op function that exists as a placeholder so that the flow in */ +/* other functions is obvious. */ +/* ------------------------------------------------------------------------ */ +int +ipf_state_main_load() +{ + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_state_main_unload */ +/* Returns: int - 0 == success, -1 == failure */ +/* Parameters: Nil */ +/* */ +/* A null-op function that exists as a placeholder so that the flow in */ +/* other functions is obvious. */ +/* ------------------------------------------------------------------------ */ +int +ipf_state_main_unload() +{ + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_state_soft_create */ +/* Returns: void * - NULL = failure, else pointer to soft context */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* */ +/* Create a new state soft context structure and populate it with the list */ +/* of tunables and other default settings. */ +/* ------------------------------------------------------------------------ */ +void * +ipf_state_soft_create(softc) + ipf_main_softc_t *softc; +{ + ipf_state_softc_t *softs; + + KMALLOC(softs, ipf_state_softc_t *); + if (softs == NULL) + return NULL; + + bzero((char *)softs, sizeof(*softs)); + + softs->ipf_state_tune = ipf_tune_array_copy(softs, + sizeof(ipf_state_tuneables), + ipf_state_tuneables); + if (softs->ipf_state_tune == NULL) { + ipf_state_soft_destroy(softc, softs); + return NULL; + } + if (ipf_tune_array_link(softc, softs->ipf_state_tune) == -1) { + ipf_state_soft_destroy(softc, softs); + return NULL; + } + #ifdef IPFILTER_LOG -int ipstate_logging = 1; + softs->ipf_state_logging = 1; #else -int ipstate_logging = 0; + softs->ipf_state_logging = 0; #endif -ipstate_t *ips_list = NULL; + softs->ipf_state_size = IPSTATE_SIZE, + softs->ipf_state_maxbucket = 0; + softs->ipf_state_wm_freq = IPF_TTLVAL(10); + softs->ipf_state_max = IPSTATE_MAX; + softs->ipf_state_wm_last = 0; + softs->ipf_state_wm_high = 99; + softs->ipf_state_wm_low = 90; + softs->ipf_state_inited = 0; + softs->ipf_state_lock = 0; + softs->ipf_state_doflush = 0; + + return softs; +} /* ------------------------------------------------------------------------ */ -/* Function: fr_stateinit */ -/* Returns: int - 0 == success, -1 == failure */ -/* Parameters: Nil */ +/* Function: ipf_state_soft_destroy */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ /* */ -/* Initialise all the global variables used within the state code. */ -/* This action also includes initiailising locks. */ +/* Undo only what we did in soft create: unlink and free the tunables and */ +/* free the soft context structure itself. */ /* ------------------------------------------------------------------------ */ -int fr_stateinit() +void +ipf_state_soft_destroy(softc, arg) + ipf_main_softc_t *softc; + void *arg; { + ipf_state_softc_t *softs = arg; + + if (softs->ipf_state_tune != NULL) { + ipf_tune_array_unlink(softc, softs->ipf_state_tune); + KFREES(softs->ipf_state_tune, sizeof(ipf_state_tuneables)); + softs->ipf_state_tune = NULL; + } + + KFREE(softs); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_state_soft_init */ +/* Returns: int - 0 == success, -1 == failure */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ +/* */ +/* Initialise the state soft context structure so it is ready for use. */ +/* This involves: */ +/* - allocating a hash table and zero'ing it out */ +/* - building a secondary table of seeds for double hashing to make it more */ +/* difficult to attempt to attack the hash table itself (for DoS) */ +/* - initialise all of the timeout queues, including a table for TCP, some */ +/* pairs of query/response for UDP and other IP protocols (typically the */ +/* reply queue has a shorter timeout than the query) */ +/* ------------------------------------------------------------------------ */ +int +ipf_state_soft_init(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_state_softc_t *softs = arg; int i; - KMALLOCS(ips_table, ipstate_t **, fr_statesize * sizeof(ipstate_t *)); - if (ips_table == NULL) + KMALLOCS(softs->ipf_state_table, + ipstate_t **, softs->ipf_state_size * sizeof(ipstate_t *)); + if (softs->ipf_state_table == NULL) return -1; - bzero((char *)ips_table, fr_statesize * sizeof(ipstate_t *)); - KMALLOCS(ips_seed, u_long *, fr_statesize * sizeof(*ips_seed)); - if (ips_seed == NULL) + bzero((char *)softs->ipf_state_table, + softs->ipf_state_size * sizeof(ipstate_t *)); + + KMALLOCS(softs->ipf_state_seed, u_long *, + softs->ipf_state_size * sizeof(*softs->ipf_state_seed)); + if (softs->ipf_state_seed == NULL) return -2; - for (i = 0; i < fr_statesize; i++) { + + for (i = 0; i < softs->ipf_state_size; i++) { /* - * XXX - ips_seed[X] should be a random number of sorts. + * XXX - ipf_state_seed[X] should be a random number of sorts. */ -#if (__FreeBSD_version >= 400000) - ips_seed[i] = arc4random(); +#if FREEBSD_GE_REV(400000) + softs->ipf_state_seed[i] = arc4random(); #else - ips_seed[i] = ((u_long)ips_seed + i) * fr_statesize; - ips_seed[i] ^= 0xa5a55a5a; - ips_seed[i] *= (u_long)ips_seed; - ips_seed[i] ^= 0x5a5aa5a5; - ips_seed[i] *= fr_statemax; + softs->ipf_state_seed[i] = ((u_long)softs->ipf_state_seed + i) * + softs->ipf_state_size; + softs->ipf_state_seed[i] ^= 0xa5a55a5a; + softs->ipf_state_seed[i] *= (u_long)softs->ipf_state_seed; + softs->ipf_state_seed[i] ^= 0x5a5aa5a5; + softs->ipf_state_seed[i] *= softs->ipf_state_max; #endif } - /* fill icmp reply type table */ - for (i = 0; i <= ICMP_MAXTYPE; i++) - icmpreplytype4[i] = -1; - icmpreplytype4[ICMP_ECHO] = ICMP_ECHOREPLY; - icmpreplytype4[ICMP_TSTAMP] = ICMP_TSTAMPREPLY; - icmpreplytype4[ICMP_IREQ] = ICMP_IREQREPLY; - icmpreplytype4[ICMP_MASKREQ] = ICMP_MASKREPLY; -#ifdef USE_INET6 - /* fill icmp reply type table */ - for (i = 0; i <= ICMP6_MAXTYPE; i++) - icmpreplytype6[i] = -1; - icmpreplytype6[ICMP6_ECHO_REQUEST] = ICMP6_ECHO_REPLY; - icmpreplytype6[ICMP6_MEMBERSHIP_QUERY] = ICMP6_MEMBERSHIP_REPORT; - icmpreplytype6[ICMP6_NI_QUERY] = ICMP6_NI_REPLY; - icmpreplytype6[ND_ROUTER_SOLICIT] = ND_ROUTER_ADVERT; - icmpreplytype6[ND_NEIGHBOR_SOLICIT] = ND_NEIGHBOR_ADVERT; -#endif + KMALLOCS(softs->ipf_state_stats.iss_bucketlen, u_int *, + softs->ipf_state_size * sizeof(u_int)); + if (softs->ipf_state_stats.iss_bucketlen == NULL) + return -3; + + bzero((char *)softs->ipf_state_stats.iss_bucketlen, + softs->ipf_state_size * sizeof(u_int)); + + if (softs->ipf_state_maxbucket == 0) { + for (i = softs->ipf_state_size; i > 0; i >>= 1) + softs->ipf_state_maxbucket++; + softs->ipf_state_maxbucket *= 2; + } + + ipf_sttab_init(softc, softs->ipf_state_tcptq); + softs->ipf_state_stats.iss_tcptab = softs->ipf_state_tcptq; + softs->ipf_state_tcptq[IPF_TCP_NSTATES - 1].ifq_next = + &softs->ipf_state_udptq; + + IPFTQ_INIT(&softs->ipf_state_udptq, softc->ipf_udptimeout, + "ipftq udp tab"); + softs->ipf_state_udptq.ifq_next = &softs->ipf_state_udpacktq; + + IPFTQ_INIT(&softs->ipf_state_udpacktq, softc->ipf_udpacktimeout, + "ipftq udpack tab"); + softs->ipf_state_udpacktq.ifq_next = &softs->ipf_state_icmptq; + + IPFTQ_INIT(&softs->ipf_state_icmptq, softc->ipf_icmptimeout, + "ipftq icmp tab"); + softs->ipf_state_icmptq.ifq_next = &softs->ipf_state_icmpacktq; + + IPFTQ_INIT(&softs->ipf_state_icmpacktq, softc->ipf_icmpacktimeout, + "ipftq icmpack tab"); + softs->ipf_state_icmpacktq.ifq_next = &softs->ipf_state_iptq; + + IPFTQ_INIT(&softs->ipf_state_iptq, softc->ipf_iptimeout, + "ipftq iptimeout tab"); + softs->ipf_state_iptq.ifq_next = &softs->ipf_state_pending; + + IPFTQ_INIT(&softs->ipf_state_pending, IPF_HZ_DIVIDE, "ipftq pending"); + softs->ipf_state_pending.ifq_next = &softs->ipf_state_deletetq; + + IPFTQ_INIT(&softs->ipf_state_deletetq, 1, "ipftq delete"); + softs->ipf_state_deletetq.ifq_next = NULL; + + MUTEX_INIT(&softs->ipf_stinsert, "ipf state insert mutex"); + + + softs->ipf_state_wm_last = softc->ipf_ticks; + softs->ipf_state_inited = 1; - KMALLOCS(ips_stats.iss_bucketlen, u_long *, - fr_statesize * sizeof(u_long)); - if (ips_stats.iss_bucketlen == NULL) - return -1; - bzero((char *)ips_stats.iss_bucketlen, fr_statesize * sizeof(u_long)); - - if (fr_state_maxbucket == 0) { - for (i = fr_statesize; i > 0; i >>= 1) - fr_state_maxbucket++; - fr_state_maxbucket *= 2; - } - - fr_sttab_init(ips_tqtqb); - ips_tqtqb[IPF_TCP_NSTATES - 1].ifq_next = &ips_udptq; - ips_udptq.ifq_ttl = (u_long)fr_udptimeout; - ips_udptq.ifq_ref = 1; - ips_udptq.ifq_head = NULL; - ips_udptq.ifq_tail = &ips_udptq.ifq_head; - MUTEX_INIT(&ips_udptq.ifq_lock, "ipftq udp tab"); - ips_udptq.ifq_next = &ips_udpacktq; - ips_udpacktq.ifq_ttl = (u_long)fr_udpacktimeout; - ips_udpacktq.ifq_ref = 1; - ips_udpacktq.ifq_head = NULL; - ips_udpacktq.ifq_tail = &ips_udpacktq.ifq_head; - MUTEX_INIT(&ips_udpacktq.ifq_lock, "ipftq udpack tab"); - ips_udpacktq.ifq_next = &ips_icmptq; - ips_icmptq.ifq_ttl = (u_long)fr_icmptimeout; - ips_icmptq.ifq_ref = 1; - ips_icmptq.ifq_head = NULL; - ips_icmptq.ifq_tail = &ips_icmptq.ifq_head; - MUTEX_INIT(&ips_icmptq.ifq_lock, "ipftq icmp tab"); - ips_icmptq.ifq_next = &ips_icmpacktq; - ips_icmpacktq.ifq_ttl = (u_long)fr_icmpacktimeout; - ips_icmpacktq.ifq_ref = 1; - ips_icmpacktq.ifq_head = NULL; - ips_icmpacktq.ifq_tail = &ips_icmpacktq.ifq_head; - MUTEX_INIT(&ips_icmpacktq.ifq_lock, "ipftq icmpack tab"); - ips_icmpacktq.ifq_next = &ips_iptq; - ips_iptq.ifq_ttl = (u_long)fr_iptimeout; - ips_iptq.ifq_ref = 1; - ips_iptq.ifq_head = NULL; - ips_iptq.ifq_tail = &ips_iptq.ifq_head; - MUTEX_INIT(&ips_iptq.ifq_lock, "ipftq ip tab"); - ips_iptq.ifq_next = NULL; - - RWLOCK_INIT(&ipf_state, "ipf IP state rwlock"); - MUTEX_INIT(&ipf_stinsert, "ipf state insert mutex"); - fr_state_init = 1; - - ips_last_force_flush = fr_ticks; return 0; } /* ------------------------------------------------------------------------ */ -/* Function: fr_stateunload */ -/* Returns: Nil */ -/* Parameters: Nil */ +/* Function: ipf_state_soft_fini */ +/* Returns: int - 0 = success, -1 = failure */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* arg(I) - pointer to local context to use */ /* */ /* Release and destroy any resources acquired or initialised so that */ /* IPFilter can be unloaded or re-initialised. */ /* ------------------------------------------------------------------------ */ -void fr_stateunload() +int +ipf_state_soft_fini(softc, arg) + ipf_main_softc_t *softc; + void *arg; { + ipf_state_softc_t *softs = arg; ipftq_t *ifq, *ifqnext; ipstate_t *is; - while ((is = ips_list) != NULL) - fr_delstate(is, 0); + while ((is = softs->ipf_state_list) != NULL) + ipf_state_del(softc, is, ISL_UNLOAD); /* * Proxy timeout queues are not cleaned here because although they - * exist on the state list, appr_unload is called after fr_stateunload - * and the proxies actually are responsible for them being created. - * Should the proxy timeouts have their own list? There's no real - * justification as this is the only complicationA + * exist on the state list, appr_unload is called after + * ipf_state_unload and the proxies actually are responsible for them + * being created. Should the proxy timeouts have their own list? + * There's no real justification as this is the only complication. */ - for (ifq = ips_utqe; ifq != NULL; ifq = ifqnext) { + for (ifq = softs->ipf_state_usertq; ifq != NULL; ifq = ifqnext) { ifqnext = ifq->ifq_next; - if (((ifq->ifq_flags & IFQF_PROXY) == 0) && - (fr_deletetimeoutqueue(ifq) == 0)) - fr_freetimeoutqueue(ifq); - } - ips_stats.iss_inuse = 0; - ips_num = 0; + if (ipf_deletetimeoutqueue(ifq) == 0) + ipf_freetimeoutqueue(softc, ifq); + } - if (fr_state_init == 1) { - fr_sttab_destroy(ips_tqtqb); - MUTEX_DESTROY(&ips_udptq.ifq_lock); - MUTEX_DESTROY(&ips_icmptq.ifq_lock); - MUTEX_DESTROY(&ips_udpacktq.ifq_lock); - MUTEX_DESTROY(&ips_icmpacktq.ifq_lock); - MUTEX_DESTROY(&ips_iptq.ifq_lock); + softs->ipf_state_stats.iss_inuse = 0; + softs->ipf_state_stats.iss_active = 0; + + if (softs->ipf_state_inited == 1) { + softs->ipf_state_inited = 0; + ipf_sttab_destroy(softs->ipf_state_tcptq); + MUTEX_DESTROY(&softs->ipf_state_udptq.ifq_lock); + MUTEX_DESTROY(&softs->ipf_state_icmptq.ifq_lock); + MUTEX_DESTROY(&softs->ipf_state_udpacktq.ifq_lock); + MUTEX_DESTROY(&softs->ipf_state_icmpacktq.ifq_lock); + MUTEX_DESTROY(&softs->ipf_state_iptq.ifq_lock); + MUTEX_DESTROY(&softs->ipf_state_deletetq.ifq_lock); + MUTEX_DESTROY(&softs->ipf_state_pending.ifq_lock); + MUTEX_DESTROY(&softs->ipf_stinsert); } - if (ips_table != NULL) { - KFREES(ips_table, fr_statesize * sizeof(*ips_table)); - ips_table = NULL; + if (softs->ipf_state_table != NULL) { + KFREES(softs->ipf_state_table, + softs->ipf_state_size * sizeof(*softs->ipf_state_table)); + softs->ipf_state_table = NULL; } - if (ips_seed != NULL) { - KFREES(ips_seed, fr_statesize * sizeof(*ips_seed)); - ips_seed = NULL; + if (softs->ipf_state_seed != NULL) { + KFREES(softs->ipf_state_seed, + softs->ipf_state_size * sizeof(*softs->ipf_state_seed)); + softs->ipf_state_seed = NULL; } - if (ips_stats.iss_bucketlen != NULL) { - KFREES(ips_stats.iss_bucketlen, fr_statesize * sizeof(u_long)); - ips_stats.iss_bucketlen = NULL; + if (softs->ipf_state_stats.iss_bucketlen != NULL) { + KFREES(softs->ipf_state_stats.iss_bucketlen, + softs->ipf_state_size * sizeof(u_int)); + softs->ipf_state_stats.iss_bucketlen = NULL; } - if (fr_state_maxbucket_reset == 1) - fr_state_maxbucket = 0; + return 0; +} - if (fr_state_init == 1) { - fr_state_init = 0; - RW_DESTROY(&ipf_state); - MUTEX_DESTROY(&ipf_stinsert); - } + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_state_set_lock */ +/* Returns: Nil */ +/* Parameters: arg(I) - pointer to local context to use */ +/* tmp(I) - new value for lock */ +/* */ +/* Stub function that allows for external manipulation of ipf_state_lock */ +/* ------------------------------------------------------------------------ */ +void +ipf_state_setlock(arg, tmp) + void *arg; + int tmp; +{ + ipf_state_softc_t *softs = arg; + + softs->ipf_state_lock = tmp; } /* ------------------------------------------------------------------------ */ -/* Function: fr_statetstats */ +/* Function: ipf_state_stats */ /* Returns: ips_state_t* - pointer to state stats structure */ -/* Parameters: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ /* */ /* Put all the current numbers and pointers into a single struct and return */ /* a pointer to it. */ /* ------------------------------------------------------------------------ */ -static ips_stat_t *fr_statetstats() +static ips_stat_t * +ipf_state_stats(softc) + ipf_main_softc_t *softc; { - ips_stats.iss_active = ips_num; - ips_stats.iss_statesize = fr_statesize; - ips_stats.iss_statemax = fr_statemax; - ips_stats.iss_table = ips_table; - ips_stats.iss_list = ips_list; - ips_stats.iss_ticks = fr_ticks; - return &ips_stats; + ipf_state_softc_t *softs = softc->ipf_state_soft; + ips_stat_t *issp = &softs->ipf_state_stats; + + issp->iss_state_size = softs->ipf_state_size; + issp->iss_state_max = softs->ipf_state_max; + issp->iss_table = softs->ipf_state_table; + issp->iss_list = softs->ipf_state_list; + issp->iss_ticks = softc->ipf_ticks; + +#ifdef IPFILTER_LOGGING + issp->iss_log_ok = ipf_log_logok(softc, IPF_LOGSTATE); + issp->iss_log_fail = ipf_log_failures(softc, IPF_LOGSTATE); +#else + issp->iss_log_ok = 0; + issp->iss_log_fail = 0; +#endif + return issp; } /* ------------------------------------------------------------------------ */ -/* Function: fr_state_remove */ +/* Function: ipf_state_remove */ /* Returns: int - 0 == success, != 0 == failure */ -/* Parameters: data(I) - pointer to state structure to delete from table */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* data(I) - pointer to state structure to delete from table */ /* */ /* Search for a state structure that matches the one passed, according to */ /* the IP addresses and other protocol specific information. */ /* ------------------------------------------------------------------------ */ -static int fr_state_remove(data) -caddr_t data; +static int +ipf_state_remove(softc, data) + ipf_main_softc_t *softc; + caddr_t data; { + ipf_state_softc_t *softs = softc->ipf_state_soft; ipstate_t *sp, st; int error; sp = &st; - error = fr_inobj(data, &st, IPFOBJ_IPSTATE); + error = ipf_inobj(softc, data, NULL, &st, IPFOBJ_IPSTATE); if (error) return EFAULT; - WRITE_ENTER(&ipf_state); - for (sp = ips_list; sp; sp = sp->is_next) + WRITE_ENTER(&softc->ipf_state); + for (sp = softs->ipf_state_list; sp; sp = sp->is_next) if ((sp->is_p == st.is_p) && (sp->is_v == st.is_v) && !bcmp((caddr_t)&sp->is_src, (caddr_t)&st.is_src, sizeof(st.is_src)) && - !bcmp((caddr_t)&sp->is_dst, (caddr_t)&st.is_src, + !bcmp((caddr_t)&sp->is_dst, (caddr_t)&st.is_dst, sizeof(st.is_dst)) && !bcmp((caddr_t)&sp->is_ps, (caddr_t)&st.is_ps, sizeof(st.is_ps))) { - fr_delstate(sp, ISL_REMOVE); - RWLOCK_EXIT(&ipf_state); + ipf_state_del(softc, sp, ISL_REMOVE); + RWLOCK_EXIT(&softc->ipf_state); return 0; } - RWLOCK_EXIT(&ipf_state); + RWLOCK_EXIT(&softc->ipf_state); + + IPFERROR(100001); return ESRCH; } /* ------------------------------------------------------------------------ */ -/* Function: fr_state_ioctl */ +/* Function: ipf_state_ioctl */ /* Returns: int - 0 == success, != 0 == failure */ -/* Parameters: data(I) - pointer to ioctl data */ -/* cmd(I) - ioctl command integer */ -/* mode(I) - file mode bits used with open */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* data(I) - pointer to ioctl data */ +/* cmd(I) - ioctl command integer */ +/* mode(I) - file mode bits used with open */ +/* uid(I) - uid of process making the ioctl call */ +/* ctx(I) - pointer specific to context of the call */ /* */ /* Processes an ioctl call made to operate on the IP Filter state device. */ /* ------------------------------------------------------------------------ */ -int fr_state_ioctl(data, cmd, mode) -caddr_t data; -ioctlcmd_t cmd; -int mode; +int +ipf_state_ioctl(softc, data, cmd, mode, uid, ctx) + ipf_main_softc_t *softc; + caddr_t data; + ioctlcmd_t cmd; + int mode, uid; + void *ctx; { + ipf_state_softc_t *softs = softc->ipf_state_soft; int arg, ret, error = 0; + SPL_INT(s); switch (cmd) { @@ -429,107 +603,225 @@ int mode; * Delete an entry from the state table. */ case SIOCDELST : - error = fr_state_remove(data); + error = ipf_state_remove(softc, data); break; + /* * Flush the state table */ case SIOCIPFFL : - BCOPYIN(data, (char *)&arg, sizeof(arg)); - if (arg == 0 || arg == 1) { - WRITE_ENTER(&ipf_state); - ret = fr_state_flush(arg, 4); - RWLOCK_EXIT(&ipf_state); - BCOPYOUT((char *)&ret, data, sizeof(ret)); - } else - error = EINVAL; + error = BCOPYIN(data, &arg, sizeof(arg)); + if (error != 0) { + IPFERROR(100002); + error = EFAULT; + + } else { + WRITE_ENTER(&softc->ipf_state); + ret = ipf_state_flush(softc, arg, 4); + RWLOCK_EXIT(&softc->ipf_state); + + error = BCOPYOUT(&ret, data, sizeof(ret)); + if (error != 0) { + IPFERROR(100003); + error = EFAULT; + } + } break; + #ifdef USE_INET6 case SIOCIPFL6 : - BCOPYIN(data, (char *)&arg, sizeof(arg)); - if (arg == 0 || arg == 1) { - WRITE_ENTER(&ipf_state); - ret = fr_state_flush(arg, 6); - RWLOCK_EXIT(&ipf_state); - BCOPYOUT((char *)&ret, data, sizeof(ret)); - } else - error = EINVAL; + error = BCOPYIN(data, &arg, sizeof(arg)); + if (error != 0) { + IPFERROR(100004); + error = EFAULT; + + } else { + WRITE_ENTER(&softc->ipf_state); + ret = ipf_state_flush(softc, arg, 6); + RWLOCK_EXIT(&softc->ipf_state); + + error = BCOPYOUT(&ret, data, sizeof(ret)); + if (error != 0) { + IPFERROR(100005); + error = EFAULT; + } + } break; #endif + + case SIOCMATCHFLUSH : + WRITE_ENTER(&softc->ipf_state); + error = ipf_state_matchflush(softc, data); + RWLOCK_EXIT(&softc->ipf_state); + break; + #ifdef IPFILTER_LOG /* * Flush the state log. */ case SIOCIPFFB : - if (!(mode & FWRITE)) + if (!(mode & FWRITE)) { + IPFERROR(100008); error = EPERM; - else { + } else { int tmp; - tmp = ipflog_clear(IPL_LOGSTATE); - BCOPYOUT((char *)&tmp, data, sizeof(tmp)); + tmp = ipf_log_clear(softc, IPL_LOGSTATE); + error = BCOPYOUT(&tmp, data, sizeof(tmp)); + if (error != 0) { + IPFERROR(100009); + error = EFAULT; + } } break; + /* * Turn logging of state information on/off. */ case SIOCSETLG : - if (!(mode & FWRITE)) + if (!(mode & FWRITE)) { + IPFERROR(100010); error = EPERM; - else { - BCOPYIN((char *)data, (char *)&ipstate_logging, - sizeof(ipstate_logging)); + } else { + error = BCOPYIN(data, &softs->ipf_state_logging, + sizeof(softs->ipf_state_logging)); + if (error != 0) { + IPFERROR(100011); + error = EFAULT; + } } break; + /* * Return the current state of logging. */ case SIOCGETLG : - BCOPYOUT((char *)&ipstate_logging, (char *)data, - sizeof(ipstate_logging)); + error = BCOPYOUT(&softs->ipf_state_logging, data, + sizeof(softs->ipf_state_logging)); + if (error != 0) { + IPFERROR(100012); + error = EFAULT; + } break; + /* * Return the number of bytes currently waiting to be read. */ case FIONREAD : - arg = iplused[IPL_LOGSTATE]; /* returned in an int */ - BCOPYOUT((char *)&arg, data, sizeof(arg)); + arg = ipf_log_bytesused(softc, IPL_LOGSTATE); + error = BCOPYOUT(&arg, data, sizeof(arg)); + if (error != 0) { + IPFERROR(100013); + error = EFAULT; + } break; #endif + /* * Get the current state statistics. */ case SIOCGETFS : - error = fr_outobj(data, fr_statetstats(), IPFOBJ_STATESTAT); + error = ipf_outobj(softc, data, ipf_state_stats(softc), + IPFOBJ_STATESTAT); break; + /* * Lock/Unlock the state table. (Locking prevents any changes, which * means no packets match). */ case SIOCSTLCK : - fr_lock(data, &fr_state_lock); + if (!(mode & FWRITE)) { + IPFERROR(100014); + error = EPERM; + } else { + error = ipf_lock(data, &softs->ipf_state_lock); + } break; + /* * Add an entry to the current state table. */ case SIOCSTPUT : - if (!fr_state_lock) { + if (!softs->ipf_state_lock || !(mode &FWRITE)) { + IPFERROR(100015); error = EACCES; break; } - error = fr_stputent(data); + error = ipf_state_putent(softc, softs, data); break; + /* * Get a state table entry. */ case SIOCSTGET : - if (!fr_state_lock) { + if (!softs->ipf_state_lock) { + IPFERROR(100016); error = EACCES; break; } - error = fr_stgetent(data); + error = ipf_state_getent(softc, softs, data); + break; + + /* + * Return a copy of the hash table bucket lengths + */ + case SIOCSTAT1 : + error = BCOPYOUT(softs->ipf_state_stats.iss_bucketlen, data, + softs->ipf_state_size * sizeof(u_int)); + if (error != 0) { + IPFERROR(100017); + error = EFAULT; + } + break; + + case SIOCGENITER : + { + ipftoken_t *token; + ipfgeniter_t iter; + ipfobj_t obj; + + error = ipf_inobj(softc, data, &obj, &iter, IPFOBJ_GENITER); + if (error != 0) + break; + + SPL_SCHED(s); + token = ipf_token_find(softc, IPFGENITER_STATE, uid, ctx); + if (token != NULL) { + error = ipf_state_iter(softc, token, &iter, &obj); + WRITE_ENTER(&softc->ipf_tokens); + ipf_token_deref(softc, token); + RWLOCK_EXIT(&softc->ipf_tokens); + } else { + IPFERROR(100018); + error = ESRCH; + } + SPL_X(s); + break; + } + + case SIOCGTABL : + error = ipf_state_gettable(softc, softs, data); + break; + + case SIOCIPFDELTOK : + error = BCOPYIN(data, &arg, sizeof(arg)); + if (error != 0) { + IPFERROR(100019); + error = EFAULT; + } else { + SPL_SCHED(s); + error = ipf_token_del(softc, arg, uid, ctx); + SPL_X(s); + } break; + + case SIOCGTQTAB : + error = ipf_outobj(softc, data, softs->ipf_state_tcptq, + IPFOBJ_STATETQTAB); + break; + default : + IPFERROR(100020); error = EINVAL; break; } @@ -538,9 +830,11 @@ int mode; /* ------------------------------------------------------------------------ */ -/* Function: fr_stgetent */ +/* Function: ipf_state_getent */ /* Returns: int - 0 == success, != 0 == failure */ -/* Parameters: data(I) - pointer to state structure to retrieve from table */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* softs(I) - pointer to state context structure */ +/* data(I) - pointer to state structure to retrieve from table*/ /* */ /* Copy out state information from the kernel to a user space process. If */ /* there is a filter rule associated with the state entry, copy that out */ @@ -548,23 +842,30 @@ int mode; /* the struct passed in and if not null and not found in the list of current*/ /* state entries, the retrieval fails. */ /* ------------------------------------------------------------------------ */ -int fr_stgetent(data) -caddr_t data; +static int +ipf_state_getent(softc, softs, data) + ipf_main_softc_t *softc; + ipf_state_softc_t *softs; + caddr_t data; { ipstate_t *is, *isn; ipstate_save_t ips; int error; - error = fr_inobj(data, &ips, IPFOBJ_STATESAVE); + error = ipf_inobj(softc, data, NULL, &ips, IPFOBJ_STATESAVE); if (error) return EFAULT; + READ_ENTER(&softc->ipf_state); isn = ips.ips_next; if (isn == NULL) { - isn = ips_list; + isn = softs->ipf_state_list; if (isn == NULL) { - if (ips.ips_next == NULL) + if (ips.ips_next == NULL) { + RWLOCK_EXIT(&softc->ipf_state); + IPFERROR(100021); return ENOENT; + } return 0; } } else { @@ -573,11 +874,14 @@ caddr_t data; * current list of entries. Security precaution to prevent * copying of random kernel data. */ - for (is = ips_list; is; is = is->is_next) + for (is = softs->ipf_state_list; is; is = is->is_next) if (is == isn) break; - if (!is) + if (!is) { + RWLOCK_EXIT(&softc->ipf_state); + IPFERROR(100022); return ESRCH; + } } ips.ips_next = isn->is_next; bcopy((char *)isn, (char *)&ips.ips_is, sizeof(ips.ips_is)); @@ -585,25 +889,29 @@ caddr_t data; if (isn->is_rule != NULL) bcopy((char *)isn->is_rule, (char *)&ips.ips_fr, sizeof(ips.ips_fr)); - error = fr_outobj(data, &ips, IPFOBJ_STATESAVE); - if (error) - return EFAULT; - return 0; + RWLOCK_EXIT(&softc->ipf_state); + error = ipf_outobj(softc, data, &ips, IPFOBJ_STATESAVE); + return error; } /* ------------------------------------------------------------------------ */ -/* Function: fr_stputent */ +/* Function: ipf_state_putent */ /* Returns: int - 0 == success, != 0 == failure */ -/* Parameters: data(I) - pointer to state information struct */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* softs(I) - pointer to state context structure */ +/* data(I) - pointer to state information struct */ /* */ /* This function implements the SIOCSTPUT ioctl: insert a state entry into */ /* the state table. If the state info. includes a pointer to a filter rule */ /* then also add in an orphaned rule (will not show up in any "ipfstat -io" */ /* output. */ /* ------------------------------------------------------------------------ */ -int fr_stputent(data) -caddr_t data; +int +ipf_state_putent(softc, softs, data) + ipf_main_softc_t *softc; + ipf_state_softc_t *softs; + caddr_t data; { ipstate_t *is, *isn; ipstate_save_t ips; @@ -611,13 +919,15 @@ caddr_t data; frentry_t *fr; char *name; - error = fr_inobj(data, &ips, IPFOBJ_STATESAVE); - if (error) - return EFAULT; + error = ipf_inobj(softc, data, NULL, &ips, IPFOBJ_STATESAVE); + if (error != 0) + return error; KMALLOC(isn, ipstate_t *); - if (isn == NULL) + if (isn == NULL) { + IPFERROR(100023); return ENOMEM; + } bcopy((char *)&ips.ips_is, (char *)isn, sizeof(*isn)); bzero((char *)isn, offsetof(struct ipstate, is_pkts)); @@ -633,16 +943,21 @@ caddr_t data; fr = ips.ips_rule; if (fr == NULL) { - READ_ENTER(&ipf_state); - fr_stinsert(isn, 0); - RWLOCK_EXIT(&ipf_state); - return 0; + int inserr; + + READ_ENTER(&softc->ipf_state); + inserr = ipf_state_insert(softc, isn, 0); + MUTEX_EXIT(&isn->is_lock); + RWLOCK_EXIT(&softc->ipf_state); + + return inserr; } if (isn->is_flags & SI_NEWFR) { KMALLOC(fr, frentry_t *); if (fr == NULL) { KFREE(isn); + IPFERROR(100024); return ENOMEM; } bcopy((char *)&ips.ips_fr, (char *)fr, sizeof(*fr)); @@ -656,39 +971,56 @@ caddr_t data; * Look up all the interface names in the rule. */ for (i = 0; i < 4; i++) { - name = fr->fr_ifnames[i]; - fr->fr_ifas[i] = fr_resolvenic(name, fr->fr_v); + if (fr->fr_ifnames[i] == -1) { + fr->fr_ifas[i] = NULL; + continue; + } + name = fr->fr_names + fr->fr_ifnames[i]; + fr->fr_ifas[i] = ipf_resolvenic(softc, name, + fr->fr_family); + } + + for (i = 0; i < 4; i++) { name = isn->is_ifname[i]; - isn->is_ifp[i] = fr_resolvenic(name, isn->is_v); + isn->is_ifp[i] = ipf_resolvenic(softc, name, + isn->is_v); } fr->fr_ref = 0; fr->fr_dsize = 0; fr->fr_data = NULL; + fr->fr_type = FR_T_NONE; - fr_resolvedest(&fr->fr_tif, fr->fr_v); - fr_resolvedest(&fr->fr_dif, fr->fr_v); + (void) ipf_resolvedest(softc, fr->fr_names, &fr->fr_tifs[0], + fr->fr_family); + (void) ipf_resolvedest(softc, fr->fr_names, &fr->fr_tifs[1], + fr->fr_family); + (void) ipf_resolvedest(softc, fr->fr_names, &fr->fr_dif, + fr->fr_family); /* * send a copy back to userland of what we ended up * to allow for verification. */ - error = fr_outobj(data, &ips, IPFOBJ_STATESAVE); - if (error) { + error = ipf_outobj(softc, data, &ips, IPFOBJ_STATESAVE); + if (error != 0) { KFREE(isn); MUTEX_DESTROY(&fr->fr_lock); KFREE(fr); + IPFERROR(100025); return EFAULT; } - READ_ENTER(&ipf_state); - fr_stinsert(isn, 0); - RWLOCK_EXIT(&ipf_state); + READ_ENTER(&softc->ipf_state); + error = ipf_state_insert(softc, isn, 0); + MUTEX_EXIT(&isn->is_lock); + RWLOCK_EXIT(&softc->ipf_state); } else { - READ_ENTER(&ipf_state); - for (is = ips_list; is; is = is->is_next) + READ_ENTER(&softc->ipf_state); + for (is = softs->ipf_state_list; is; is = is->is_next) if (is->is_rule == fr) { - fr_stinsert(isn, 0); + error = ipf_state_insert(softc, isn, 0); + MUTEX_EXIT(&isn->is_lock); break; } @@ -696,59 +1028,62 @@ caddr_t data; KFREE(isn); isn = NULL; } - RWLOCK_EXIT(&ipf_state); + RWLOCK_EXIT(&softc->ipf_state); - return (isn == NULL) ? ESRCH : 0; + if (isn == NULL) { + IPFERROR(100033); + error = ESRCH; + } } - return 0; + return error; } /* ------------------------------------------------------------------------ */ -/* Function: fr_stinsert */ -/* Returns: Nil */ -/* Parameters: is(I) - pointer to state structure */ -/* rev(I) - flag indicating forward/reverse direction of packet */ +/* Function: ipf_state_insert */ +/* Returns: int - 0 == success, -1 == failure */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* Parameters: is(I) - pointer to state structure */ +/* rev(I) - flag indicating direction of packet */ /* */ /* Inserts a state structure into the hash table (for lookups) and the list */ /* of state entries (for enumeration). Resolves all of the interface names */ /* to pointers and adjusts running stats for the hash table as appropriate. */ /* */ +/* This function can fail if the filter rule has had a population policy of */ +/* IP addresses used with stateful filteirng assigned to it. */ +/* */ /* Locking: it is assumed that some kind of lock on ipf_state is held. */ +/* Exits with is_lock initialised and held - *EVEN IF ERROR*. */ /* ------------------------------------------------------------------------ */ -void fr_stinsert(is, rev) -ipstate_t *is; -int rev; +int +ipf_state_insert(softc, is, rev) + ipf_main_softc_t *softc; + ipstate_t *is; + int rev; { + ipf_state_softc_t *softs = softc->ipf_state_soft; frentry_t *fr; u_int hv; int i; - MUTEX_INIT(&is->is_lock, "ipf state entry"); - - fr = is->is_rule; - if (fr != NULL) { - MUTEX_ENTER(&fr->fr_lock); - fr->fr_ref++; - fr->fr_statecnt++; - MUTEX_EXIT(&fr->fr_lock); - } - /* * Look up all the interface names in the state entry. */ for (i = 0; i < 4; i++) { if (is->is_ifp[i] != NULL) continue; - is->is_ifp[i] = fr_resolvenic(is->is_ifname[i], is->is_v); + is->is_ifp[i] = ipf_resolvenic(softc, is->is_ifname[i], + is->is_v); } /* - * If we could trust is_hv, then the modulous would not be needed, but - * when running with IPFILTER_SYNC, this stops bad values. + * If we could trust is_hv, then the modulous would not be needed, + * but when running with IPFILTER_SYNC, this stops bad values. */ - hv = is->is_hv % fr_statesize; + hv = is->is_hv % softs->ipf_state_size; + /* TRACE is, hv */ is->is_hv = hv; /* @@ -756,38 +1091,265 @@ int rev; * possible that once the insert is complete another packet might * come along, match the entry and want to update it. */ + MUTEX_INIT(&is->is_lock, "ipf state entry"); MUTEX_ENTER(&is->is_lock); - MUTEX_ENTER(&ipf_stinsert); + MUTEX_ENTER(&softs->ipf_stinsert); + + fr = is->is_rule; + if (fr != NULL) { + if ((fr->fr_srctrack.ht_max_nodes != 0) && + (ipf_ht_node_add(softc, &fr->fr_srctrack, + is->is_family, &is->is_src) == -1)) { + SBUMPD(ipf_state_stats, iss_max_track); + MUTEX_EXIT(&softs->ipf_stinsert); + return -1; + } + + MUTEX_ENTER(&fr->fr_lock); + fr->fr_ref++; + MUTEX_EXIT(&fr->fr_lock); + fr->fr_statecnt++; + } + + if (is->is_flags & (SI_WILDP|SI_WILDA)) { + DT(iss_wild_plus_one); + SINCL(ipf_state_stats.iss_wild); + } + + SBUMP(ipf_state_stats.iss_proto[is->is_p]); + SBUMP(ipf_state_stats.iss_active_proto[is->is_p]); /* * add into list table. */ - if (ips_list != NULL) - ips_list->is_pnext = &is->is_next; - is->is_pnext = &ips_list; - is->is_next = ips_list; - ips_list = is; + if (softs->ipf_state_list != NULL) + softs->ipf_state_list->is_pnext = &is->is_next; + is->is_pnext = &softs->ipf_state_list; + is->is_next = softs->ipf_state_list; + softs->ipf_state_list = is; + + if (softs->ipf_state_table[hv] != NULL) + softs->ipf_state_table[hv]->is_phnext = &is->is_hnext; + else + softs->ipf_state_stats.iss_inuse++; + is->is_phnext = softs->ipf_state_table + hv; + is->is_hnext = softs->ipf_state_table[hv]; + softs->ipf_state_table[hv] = is; + softs->ipf_state_stats.iss_bucketlen[hv]++; + softs->ipf_state_stats.iss_active++; + MUTEX_EXIT(&softs->ipf_stinsert); + + ipf_state_setqueue(softc, is, rev); - if (ips_table[hv] != NULL) - ips_table[hv]->is_phnext = &is->is_hnext; + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_state_matchipv4addrs */ +/* Returns: int - 2 addresses match (strong match), 1 reverse match, */ +/* 0 no match */ +/* Parameters: is1, is2 pointers to states we are checking */ +/* */ +/* Function matches IPv4 addresses it returns strong match for ICMP proto */ +/* even there is only reverse match */ +/* ------------------------------------------------------------------------ */ +static int +ipf_state_matchipv4addrs(is1, is2) + ipstate_t *is1, *is2; +{ + int rv; + + if (is1->is_saddr == is2->is_saddr && is1->is_daddr == is2->is_daddr) + rv = 2; + else if (is1->is_saddr == is2->is_daddr && + is1->is_daddr == is2->is_saddr) { + /* force strong match for ICMP protocol */ + rv = (is1->is_p == IPPROTO_ICMP) ? 2 : 1; + } else - ips_stats.iss_inuse++; - is->is_phnext = ips_table + hv; - is->is_hnext = ips_table[hv]; - ips_table[hv] = is; - ips_stats.iss_bucketlen[hv]++; - ips_num++; - MUTEX_EXIT(&ipf_stinsert); - - fr_setstatequeue(is, rev); - MUTEX_EXIT(&is->is_lock); + rv = 0; + + return (rv); } /* ------------------------------------------------------------------------ */ -/* Function: fr_addstate */ -/* Returns: ipstate_t* - NULL == failure, else pointer to new state */ -/* Parameters: fin(I) - pointer to packet information */ +/* Function: ipf_state_matchipv6addrs */ +/* Returns: int - 2 addresses match (strong match), 1 reverse match, */ +/* 0 no match */ +/* Parameters: is1, is2 pointers to states we are checking */ +/* */ +/* Function matches IPv6 addresses it returns strong match for ICMP proto */ +/* even there is only reverse match */ +/* ------------------------------------------------------------------------ */ +static int +ipf_state_matchipv6addrs(is1, is2) + ipstate_t *is1, *is2; +{ + int rv; + + if (IP6_EQ(&is1->is_src, &is2->is_src) && + IP6_EQ(&is1->is_dst, &is2->is_dst)) + rv = 2; + else if (IP6_EQ(&is1->is_src, &is2->is_dst) && + IP6_EQ(&is1->is_dst, &is2->is_src)) { + /* force strong match for ICMPv6 protocol */ + rv = (is1->is_p == IPPROTO_ICMPV6) ? 2 : 1; + } + else + rv = 0; + + return (rv); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_state_matchaddresses */ +/* Returns: int - 2 addresses match, 1 reverse match, zero no match */ +/* Parameters: is1, is2 pointers to states we are checking */ +/* */ +/* function retruns true if two pairs of addresses belong to single */ +/* connection. suppose there are two endpoints: */ +/* endpoint1 1.1.1.1 */ +/* endpoint2 1.1.1.2 */ +/* */ +/* the state is established by packet flying from .1 to .2 so we see: */ +/* is1->src = 1.1.1.1 */ +/* is1->dst = 1.1.1.2 */ +/* now endpoint 1.1.1.2 sends answer */ +/* retreives is1 record created by first packat and compares it with is2 */ +/* temporal record, is2 is initialized as follows: */ +/* is2->src = 1.1.1.2 */ +/* is2->dst = 1.1.1.1 */ +/* in this case 1 will be returned */ +/* */ +/* the ipf_matchaddresses() assumes those two records to be same. of course */ +/* the ipf_matchaddresses() also assume records are same in case you pass */ +/* identical arguments (i.e. ipf_matchaddress(is1, is1) would return 2 */ +/* ------------------------------------------------------------------------ */ +static int +ipf_state_matchaddresses(is1, is2) + ipstate_t *is1, *is2; +{ + int rv; + + if (is1->is_v == 4) { + rv = ipf_state_matchipv4addrs(is1, is2); + } + else { + rv = ipf_state_matchipv6addrs(is1, is2); + } + + return (rv); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_matchports */ +/* Returns: int - 2 match, 1 rverse match, 0 no match */ +/* Parameters: ppairs1, ppairs - src, dst ports we want to match */ +/* */ +/* performs the same match for isps members as for addresses */ +/* ------------------------------------------------------------------------ */ +static int +ipf_state_matchports(ppairs1, ppairs2) + udpinfo_t *ppairs1, *ppairs2; +{ + int rv; + + if (ppairs1->us_sport == ppairs2->us_sport && + ppairs1->us_dport == ppairs2->us_dport) + rv = 2; + else if (ppairs1->us_sport == ppairs2->us_dport && + ppairs1->us_dport == ppairs2->us_sport) + rv = 1; + else + rv = 0; + + return (rv); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_matchisps */ +/* Returns: int - nonzero if isps members match, 0 nomatch */ +/* Parameters: is1, is2 - states we want to match */ +/* */ +/* performs the same match for isps members as for addresses */ +/* ------------------------------------------------------------------------ */ +static int +ipf_state_matchisps(is1, is2) + ipstate_t *is1, *is2; +{ + int rv; + + if (is1->is_p == is2->is_p) { + switch (is1->is_p) + { + case IPPROTO_TCP : + case IPPROTO_UDP : + case IPPROTO_GRE : + /* greinfo_t can be also interprted as port pair */ + rv = ipf_state_matchports(&is1->is_ps.is_us, + &is2->is_ps.is_us); + break; + + case IPPROTO_ICMP : + case IPPROTO_ICMPV6 : + /* force strong match for ICMP datagram. */ + if (bcmp(&is1->is_ps, &is2->is_ps, + sizeof(icmpinfo_t)) == 0) { + rv = 2; + } else { + rv = 0; + } + break; + + default: + rv = 0; + } + } else { + rv = 0; + } + + return (rv); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_state_match */ +/* Returns: int - nonzero match, zero no match */ +/* Parameters: is1, is2 - states we want to match */ +/* */ +/* ------------------------------------------------------------------------ */ +static int +ipf_state_match(is1, is2) + ipstate_t *is1, *is2; +{ + int rv; + int amatch; + int pomatch; + + if (bcmp(&is1->is_pass, &is2->is_pass, + offsetof(struct ipstate, is_authmsk) - + offsetof(struct ipstate, is_pass)) == 0) { + + pomatch = ipf_state_matchisps(is1, is2); + amatch = ipf_state_matchaddresses(is1, is2); + rv = (amatch != 0) && (amatch == pomatch); + } else { + rv = 0; + } + + return (rv); +} + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_state_add */ +/* Returns: ipstate_t - 0 = success */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* fin(I) - pointer to packet information */ /* stsave(O) - pointer to place to save pointer to created */ /* state structure. */ /* flags(I) - flags to use when creating the structure */ @@ -796,56 +1358,111 @@ int rev; /* Inserts it into the state table and appends to the bottom of the active */ /* list. If the capacity of the table has reached the maximum allowed then */ /* the call will fail and a flush is scheduled for the next timeout call. */ +/* */ +/* NOTE: The use of stsave to point to nat_state will result in memory */ +/* corruption. It should only be used to point to objects that will */ +/* either outlive this (not expired) or will deref the ip_state_t */ +/* when they are deleted. */ /* ------------------------------------------------------------------------ */ -ipstate_t *fr_addstate(fin, stsave, flags) -fr_info_t *fin; -ipstate_t **stsave; -u_int flags; +int +ipf_state_add(softc, fin, stsave, flags) + ipf_main_softc_t *softc; + fr_info_t *fin; + ipstate_t **stsave; + u_int flags; { + ipf_state_softc_t *softs = softc->ipf_state_soft; ipstate_t *is, ips; struct icmp *ic; u_int pass, hv; frentry_t *fr; tcphdr_t *tcp; - grehdr_t *gre; - void *ifp; + frdest_t *fdp; int out; - if (fr_state_lock || - (fin->fin_flx & (FI_SHORT|FI_STATE|FI_FRAGBODY|FI_BAD))) - return NULL; + /* + * If a packet that was created locally is trying to go out but we + * do not match here here because of this lock, it is likely that + * the policy will block it and return network unreachable back up + * the stack. To mitigate this error, EAGAIN is returned instead, + * telling the IP stack to try sending this packet again later. + */ + if (softs->ipf_state_lock) { + SBUMPD(ipf_state_stats, iss_add_locked); + fin->fin_error = EAGAIN; + return -1; + } - if ((fin->fin_flx & FI_OOW) && !(fin->fin_tcpf & TH_SYN)) - return NULL; + if (fin->fin_flx & (FI_SHORT|FI_STATE|FI_FRAGBODY|FI_BAD)) { + SBUMPD(ipf_state_stats, iss_add_bad); + return -1; + } - fr = fin->fin_fr; - if ((fr->fr_statemax == 0) && (ips_num == fr_statemax)) { - ATOMIC_INCL(ips_stats.iss_max); - fr_state_doflush = 1; - return NULL; + if ((fin->fin_flx & FI_OOW) && !(fin->fin_tcpf & TH_SYN)) { + SBUMPD(ipf_state_stats, iss_add_oow); + return -1; + } + + if ((softs->ipf_state_stats.iss_active * 100 / softs->ipf_state_max) > + softs->ipf_state_wm_high) { + softs->ipf_state_doflush = 1; } /* * If a "keep state" rule has reached the maximum number of references * to it, then schedule an automatic flush in case we can clear out - * some "dead old wood". + * some "dead old wood". Note that because the lock isn't held on + * fr it is possible that we could overflow. The cost of overflowing + * is being ignored here as the number by which it can overflow is + * a product of the number of simultaneous threads that could be + * executing in here, so a limit of 100 won't result in 200, but could + * result in 101 or 102. */ - if ((fr != NULL) && (fr->fr_statemax != 0) && - (fr->fr_statecnt >= fr->fr_statemax)) { - MUTEX_EXIT(&fr->fr_lock); - ATOMIC_INCL(ips_stats.iss_maxref); - fr_state_doflush = 1; - return NULL; + fr = fin->fin_fr; + if (fr != NULL) { + if ((softs->ipf_state_stats.iss_active >= + softs->ipf_state_max) && (fr->fr_statemax == 0)) { + SBUMPD(ipf_state_stats, iss_max); + return 1; + } + if ((fr->fr_statemax != 0) && + (fr->fr_statecnt >= fr->fr_statemax)) { + SBUMPD(ipf_state_stats, iss_max_ref); + return 2; + } } - pass = (fr == NULL) ? 0 : fr->fr_flags; + is = &ips; + if (fr == NULL) { + pass = softc->ipf_flags; + is->is_tag = FR_NOLOGTAG; + } else { + pass = fr->fr_flags; + } ic = NULL; tcp = NULL; out = fin->fin_out; - is = &ips; bzero((char *)is, sizeof(*is)); - is->is_die = 1 + fr_ticks; + is->is_die = 1 + softc->ipf_ticks; + /* + * We want to check everything that is a property of this packet, + * but we don't (automatically) care about it's fragment status as + * this may change. + */ + is->is_pass = pass; + is->is_v = fin->fin_v; + is->is_sec = fin->fin_secmsk; + is->is_secmsk = 0xffff; + is->is_auth = fin->fin_auth; + is->is_authmsk = 0xffff; + is->is_family = fin->fin_family; + is->is_opt[0] = fin->fin_optmsk; + is->is_optmsk[0] = 0xffffffff; + if (is->is_v == 6) { + is->is_opt[0] &= ~0x8; + is->is_optmsk[0] &= ~0x8; + } /* * Copy and calculate... @@ -884,6 +1501,11 @@ u_int flags; hv += is->is_src.i6[3]; } #endif + if ((fin->fin_v == 4) && + (fin->fin_flx & (FI_MULTICAST|FI_BROADCAST|FI_MBCAST))) { + flags |= SI_W_DADDR; + hv -= is->is_daddr; + } switch (is->is_p) { @@ -894,9 +1516,8 @@ u_int flags; switch (ic->icmp_type) { case ICMP6_ECHO_REQUEST : - is->is_icmp.ici_type = ic->icmp_type; hv += (is->is_icmp.ici_id = ic->icmp_id); - break; + /*FALLTHROUGH*/ case ICMP6_MEMBERSHIP_QUERY : case ND_ROUTER_SOLICIT : case ND_NEIGHBOR_SOLICIT : @@ -904,9 +1525,9 @@ u_int flags; is->is_icmp.ici_type = ic->icmp_type; break; default : - return NULL; + SBUMPD(ipf_state_stats, iss_icmp6_notquery); + return -2; } - ATOMIC_INCL(ips_stats.iss_icmp); break; #endif case IPPROTO_ICMP : @@ -922,11 +1543,12 @@ u_int flags; hv += (is->is_icmp.ici_id = ic->icmp_id); break; default : - return NULL; + SBUMPD(ipf_state_stats, iss_icmp_notquery); + return -3; } - ATOMIC_INCL(ips_stats.iss_icmp); break; +#if 0 case IPPROTO_GRE : gre = fin->fin_dp; @@ -937,12 +1559,18 @@ u_int flags; is->is_call[1] = fin->fin_data[1]; } break; +#endif case IPPROTO_TCP : tcp = fin->fin_dp; - if (tcp->th_flags & TH_RST) - return NULL; + if (tcp->th_flags & TH_RST) { + SBUMPD(ipf_state_stats, iss_tcp_rstadd); + return -4; + } + + /* TRACE is, flags, hv */ + /* * The endian of the ports doesn't matter, but the ack and * sequence numbers do as we do mathematics on them later. @@ -954,6 +1582,8 @@ u_int flags; hv += is->is_dport; } + /* TRACE is, flags, hv */ + /* * If this is a real packet then initialise fields in the * state information structure from the TCP header information. @@ -978,15 +1608,14 @@ u_int flags; if ((tcp->th_flags & ~(TH_FIN|TH_ACK|TH_ECNALL)) == TH_SYN && (TCP_OFF(tcp) > (sizeof(tcphdr_t) >> 2))) { - if (fr_tcpoptions(fin, tcp, - &is->is_tcp.ts_data[0])) - is->is_swinflags = TCP_WSCALE_SEEN| - TCP_WSCALE_FIRST; + if (ipf_tcpoptions(softs, fin, tcp, + &is->is_tcp.ts_data[0]) == -1) + fin->fin_flx |= FI_BAD; } if ((fin->fin_out != 0) && (pass & FR_NEWISN) != 0) { - fr_checknewisn(fin, is); - fr_fixoutisn(fin, is); + ipf_checknewisn(fin, is); + ipf_fixoutisn(fin, is); } if ((tcp->th_flags & TH_OPENING) == TH_SYN) @@ -1000,11 +1629,10 @@ u_int flags; } /* - * If we're creating state for a starting connection, start the - * timer on it as we'll never see an error if it fails to - * connect. + * If we're creating state for a starting connection, start + * the timer on it as we'll never see an error if it fails + * to connect. */ - ATOMIC_INCL(ips_stats.iss_tcp); break; case IPPROTO_UDP : @@ -1016,7 +1644,6 @@ u_int flags; hv += tcp->th_dport; hv += tcp->th_sport; } - ATOMIC_INCL(ips_stats.iss_udp); break; default : @@ -1024,125 +1651,173 @@ u_int flags; } hv = DOUBLE_HASH(hv); is->is_hv = hv; - is->is_rule = fr; - is->is_flags = flags & IS_INHERITED; /* * Look for identical state. */ - for (is = ips_table[is->is_hv % fr_statesize]; is != NULL; - is = is->is_hnext) { - if (bcmp(&ips.is_src, &is->is_src, - offsetof(struct ipstate, is_ps) - - offsetof(struct ipstate, is_src)) == 0) + for (is = softs->ipf_state_table[hv % softs->ipf_state_size]; + is != NULL; is = is->is_hnext) { + if (ipf_state_match(&ips, is) == 1) break; } - if (is != NULL) - return NULL; + if (is != NULL) { + SBUMPD(ipf_state_stats, iss_add_dup); + return 3; + } - if (ips_stats.iss_bucketlen[hv] >= fr_state_maxbucket) { - ATOMIC_INCL(ips_stats.iss_bucketfull); - return NULL; + if (softs->ipf_state_stats.iss_bucketlen[hv] >= + softs->ipf_state_maxbucket) { + SBUMPD(ipf_state_stats, iss_bucket_full); + return 4; } KMALLOC(is, ipstate_t *); if (is == NULL) { - ATOMIC_INCL(ips_stats.iss_nomem); - return NULL; + SBUMPD(ipf_state_stats, iss_nomem); + return 5; } bcopy((char *)&ips, (char *)is, sizeof(*is)); + is->is_flags = flags & IS_INHERITED; + is->is_rulen = fin->fin_rule; + is->is_rule = fr; + /* - * Do not do the modulous here, it is done in fr_stinsert(). + * Do not do the modulous here, it is done in ipf_state_insert(). */ if (fr != NULL) { - (void) strncpy(is->is_group, fr->fr_group, FR_GROUPLEN); + ipftq_t *tq; + + (void) strncpy(is->is_group, FR_NAME(fr, fr_group), + FR_GROUPLEN); if (fr->fr_age[0] != 0) { - is->is_tqehead[0] = fr_addtimeoutqueue(&ips_utqe, - fr->fr_age[0]); + tq = ipf_addtimeoutqueue(softc, + &softs->ipf_state_usertq, + fr->fr_age[0]); + is->is_tqehead[0] = tq; is->is_sti.tqe_flags |= TQE_RULEBASED; } if (fr->fr_age[1] != 0) { - is->is_tqehead[1] = fr_addtimeoutqueue(&ips_utqe, - fr->fr_age[1]); + tq = ipf_addtimeoutqueue(softc, + &softs->ipf_state_usertq, + fr->fr_age[1]); + is->is_tqehead[1] = tq; is->is_sti.tqe_flags |= TQE_RULEBASED; } is->is_tag = fr->fr_logtag; - - is->is_ifp[(out << 1) + 1] = fr->fr_ifas[1]; - is->is_ifp[(1 - out) << 1] = fr->fr_ifas[2]; - is->is_ifp[((1 - out) << 1) + 1] = fr->fr_ifas[3]; - - if (((ifp = fr->fr_ifas[1]) != NULL) && - (ifp != (void *)-1)) { - COPYIFNAME(ifp, is->is_ifname[(out << 1) + 1]); - } - if (((ifp = fr->fr_ifas[2]) != NULL) && - (ifp != (void *)-1)) { - COPYIFNAME(ifp, is->is_ifname[(1 - out) << 1]); - } - if (((ifp = fr->fr_ifas[3]) != NULL) && - (ifp != (void *)-1)) { - COPYIFNAME(ifp, is->is_ifname[((1 - out) << 1) + 1]); - } - } else { - pass = fr_flags; - is->is_tag = FR_NOLOGTAG; - } - - is->is_ifp[out << 1] = fin->fin_ifp; - if (fin->fin_ifp != NULL) { - COPYIFNAME(fin->fin_ifp, is->is_ifname[out << 1]); } /* - * It may seem strange to set is_ref to 2, but fr_check() will call - * fr_statederef() after calling fr_addstate() and the idea is to - * have it exist at the end of fr_check() with is_ref == 1. + * It may seem strange to set is_ref to 2, but if stsave is not NULL + * then a copy of the pointer is being stored somewhere else and in + * the end, it will expect to be able to do osmething with it. */ - is->is_ref = 2; - is->is_pass = pass; + is->is_me = stsave; + if (stsave != NULL) { + *stsave = is; + is->is_ref = 2; + } else { + is->is_ref = 1; + } is->is_pkts[0] = 0, is->is_bytes[0] = 0; is->is_pkts[1] = 0, is->is_bytes[1] = 0; is->is_pkts[2] = 0, is->is_bytes[2] = 0; is->is_pkts[3] = 0, is->is_bytes[3] = 0; if ((fin->fin_flx & FI_IGNORE) == 0) { is->is_pkts[out] = 1; + fin->fin_pktnum = 1; is->is_bytes[out] = fin->fin_plen; is->is_flx[out][0] = fin->fin_flx & FI_CMP; is->is_flx[out][0] &= ~FI_OOW; } + if (pass & FR_STLOOSE) + is->is_flags |= IS_LOOSE; + if (pass & FR_STSTRICT) is->is_flags |= IS_STRICT; if (pass & FR_STATESYNC) is->is_flags |= IS_STATESYNC; - /* - * We want to check everything that is a property of this packet, - * but we don't (automatically) care about it's fragment status as - * this may change. - */ - is->is_v = fin->fin_v; - is->is_opt = fin->fin_optmsk; - is->is_optmsk = 0xffffffff; - is->is_sec = fin->fin_secmsk; - is->is_secmsk = 0xffff; - is->is_auth = fin->fin_auth; - is->is_authmsk = 0xffff; - if (flags & (SI_WILDP|SI_WILDA)) { - ATOMIC_INCL(ips_stats.iss_wild); + if (pass & FR_LOGFIRST) + is->is_pass &= ~(FR_LOGFIRST|FR_LOG); + + READ_ENTER(&softc->ipf_state); + + if (ipf_state_insert(softc, is, fin->fin_rev) == -1) { + RWLOCK_EXIT(&softc->ipf_state); + /* + * This is a bit more manual than it should be but + * ipf_state_del cannot be called. + */ + MUTEX_EXIT(&is->is_lock); + MUTEX_DESTROY(&is->is_lock); + if (is->is_tqehead[0] != NULL) { + if (ipf_deletetimeoutqueue(is->is_tqehead[0]) == 0) + ipf_freetimeoutqueue(softc, is->is_tqehead[0]); + is->is_tqehead[0] = NULL; + } + if (is->is_tqehead[1] != NULL) { + if (ipf_deletetimeoutqueue(is->is_tqehead[1]) == 0) + ipf_freetimeoutqueue(softc, is->is_tqehead[1]); + is->is_tqehead[1] = NULL; + } + KFREE(is); + return -1; } - is->is_rulen = fin->fin_rule; + /* + * Filling in the interface name is after the insert so that an + * event (such as add/delete) of an interface that is referenced + * by this rule will see this state entry. + */ + if (fr != NULL) { + /* + * The name '-' is special for network interfaces and causes + * a NULL name to be present, always, allowing packets to + * match it, regardless of their interface. + */ + if ((fin->fin_ifp == NULL) || + (fr->fr_ifnames[out << 1] != -1 && + fr->fr_names[fr->fr_ifnames[out << 1] + 0] == '-' && + fr->fr_names[fr->fr_ifnames[out << 1] + 1] == '\0')) { + is->is_ifp[out << 1] = fr->fr_ifas[0]; + strncpy(is->is_ifname[out << 1], + fr->fr_names + fr->fr_ifnames[0], + sizeof(fr->fr_ifnames[0])); + } else { + is->is_ifp[out << 1] = fin->fin_ifp; + COPYIFNAME(fin->fin_v, fin->fin_ifp, + is->is_ifname[out << 1]); + } - if (pass & FR_LOGFIRST) - is->is_pass &= ~(FR_LOGFIRST|FR_LOG); + is->is_ifp[(out << 1) + 1] = fr->fr_ifas[1]; + if (fr->fr_ifnames[1] != -1) { + strncpy(is->is_ifname[(out << 1) + 1], + fr->fr_names + fr->fr_ifnames[1], + sizeof(fr->fr_ifnames[1])); + } - READ_ENTER(&ipf_state); - is->is_me = stsave; + is->is_ifp[(1 - out) << 1] = fr->fr_ifas[2]; + if (fr->fr_ifnames[2] != -1) { + strncpy(is->is_ifname[((1 - out) << 1)], + fr->fr_names + fr->fr_ifnames[2], + sizeof(fr->fr_ifnames[2])); + } - fr_stinsert(is, fin->fin_rev); + is->is_ifp[((1 - out) << 1) + 1] = fr->fr_ifas[3]; + if (fr->fr_ifnames[3] != -1) { + strncpy(is->is_ifname[((1 - out) << 1) + 1], + fr->fr_names + fr->fr_ifnames[3], + sizeof(fr->fr_ifnames[3])); + } + } else { + if (fin->fin_ifp != NULL) { + is->is_ifp[out << 1] = fin->fin_ifp; + COPYIFNAME(fin->fin_v, fin->fin_ifp, + is->is_ifname[out << 1]); + } + } if (fin->fin_p == IPPROTO_TCP) { /* @@ -1150,58 +1825,84 @@ u_int flags; * timer on it as we'll never see an error if it fails to * connect. */ - MUTEX_ENTER(&is->is_lock); - (void) fr_tcp_age(&is->is_sti, fin, ips_tqtqb, is->is_flags); - MUTEX_EXIT(&is->is_lock); -#ifdef IPFILTER_SCAN - if ((is->is_flags & SI_CLONE) == 0) - (void) ipsc_attachis(is); -#endif + (void) ipf_tcp_age(&is->is_sti, fin, softs->ipf_state_tcptq, + is->is_flags, 2); } -#ifdef IPFILTER_SYNC + MUTEX_EXIT(&is->is_lock); if ((is->is_flags & IS_STATESYNC) && ((is->is_flags & SI_CLONE) == 0)) - is->is_sync = ipfsync_new(SMC_STATE, fin, is); -#endif - if (ipstate_logging) - ipstate_log(is, ISL_NEW); + is->is_sync = ipf_sync_new(softc, SMC_STATE, fin, is); + if (softs->ipf_state_logging) + ipf_state_log(softc, is, ISL_NEW); + + RWLOCK_EXIT(&softc->ipf_state); - RWLOCK_EXIT(&ipf_state); - fin->fin_state = is; - fin->fin_rev = IP6_NEQ(&is->is_dst, &fin->fin_daddr); fin->fin_flx |= FI_STATE; if (fin->fin_flx & FI_FRAG) - (void) fr_newfrag(fin, pass ^ FR_KEEPSTATE); + (void) ipf_frag_new(softc, fin, pass); - return is; + fdp = &fr->fr_tifs[0]; + if (fdp->fd_type == FRD_DSTLIST) { + ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, + &is->is_tifs[0]); + } else { + bcopy(fdp, &is->is_tifs[0], sizeof(*fdp)); + } + + fdp = &fr->fr_tifs[1]; + if (fdp->fd_type == FRD_DSTLIST) { + ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, + &is->is_tifs[1]); + } else { + bcopy(fdp, &is->is_tifs[1], sizeof(*fdp)); + } + fin->fin_tif = &is->is_tifs[fin->fin_rev]; + + fdp = &fr->fr_dif; + if (fdp->fd_type == FRD_DSTLIST) { + ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, + &is->is_dif); + } else { + bcopy(fdp, &is->is_dif, sizeof(*fdp)); + } + fin->fin_dif = &is->is_dif; + + return 0; } /* ------------------------------------------------------------------------ */ -/* Function: fr_tcpoptions */ -/* Returns: int - 1 == packet matches state entry, 0 == it does not */ -/* Parameters: fin(I) - pointer to packet information */ +/* Function: ipf_tcpoptions */ +/* Returns: int - 1 == packet matches state entry, 0 == it does not, */ +/* -1 == packet has bad TCP options data */ +/* Parameters: softs(I) - pointer to state context structure */ +/* fin(I) - pointer to packet information */ /* tcp(I) - pointer to TCP packet header */ /* td(I) - pointer to TCP data held as part of the state */ /* */ /* Look after the TCP header for any options and deal with those that are */ /* present. Record details about those that we recogise. */ /* ------------------------------------------------------------------------ */ -static int fr_tcpoptions(fin, tcp, td) -fr_info_t *fin; -tcphdr_t *tcp; -tcpdata_t *td; +static int +ipf_tcpoptions(softs, fin, tcp, td) + ipf_state_softc_t *softs; + fr_info_t *fin; + tcphdr_t *tcp; + tcpdata_t *td; { int off, mlen, ol, i, len, retval; char buf[64], *s, opt; mb_t *m = NULL; - off = fin->fin_hlen + sizeof(*tcp); - len = (TCP_OFF(tcp) << 2) - sizeof(*tcp); - if (fin->fin_plen < off + len) + len = (TCP_OFF(tcp) << 2); + if (fin->fin_dlen < len) { + SBUMPD(ipf_state_stats, iss_tcp_toosmall); return 0; + } + len -= sizeof(*tcp); + + off = fin->fin_plen - fin->fin_dlen + sizeof(*tcp) + fin->fin_ipoff; m = fin->fin_m; - off += fin->fin_ipoff; mlen = MSGDSIZE(m) - off; if (len > mlen) { len = mlen; @@ -1239,7 +1940,10 @@ tcpdata_t *td; else if (i < 0) i = 0; td->td_winscale = i; - } + td->td_winflags |= TCP_WSCALE_SEEN| + TCP_WSCALE_FIRST; + } else + retval = -1; break; case TCPOPT_MAXSEG : /* @@ -1251,21 +1955,33 @@ tcpdata_t *td; i <<= 8; i += (int)*(s + 3); td->td_maxseg = i; - } + } else + retval = -1; + break; + case TCPOPT_SACK_PERMITTED : + if (ol == TCPOLEN_SACK_PERMITTED) + td->td_winflags |= TCP_SACK_PERMIT; + else + retval = -1; break; } } len -= ol; s += ol; } + if (retval == -1) { + SBUMPD(ipf_state_stats, iss_tcp_badopt); + } return retval; } /* ------------------------------------------------------------------------ */ -/* Function: fr_tcpstate */ +/* Function: ipf_state_tcp */ /* Returns: int - 1 == packet matches state entry, 0 == it does not */ -/* Parameters: fin(I) - pointer to packet information */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* softs(I) - pointer to state context structure */ +/* fin(I) - pointer to packet information */ /* tcp(I) - pointer to TCP packet header */ /* is(I) - pointer to master state structure */ /* */ @@ -1273,42 +1989,65 @@ tcpdata_t *td; /* Change timeout depending on whether new packet is a SYN-ACK returning */ /* for a SYN or a RST or FIN which indicate time to close up shop. */ /* ------------------------------------------------------------------------ */ -static int fr_tcpstate(fin, tcp, is) -fr_info_t *fin; -tcphdr_t *tcp; -ipstate_t *is; +static int +ipf_state_tcp(softc, softs, fin, tcp, is) + ipf_main_softc_t *softc; + ipf_state_softc_t *softs; + fr_info_t *fin; + tcphdr_t *tcp; + ipstate_t *is; { - int source, ret = 0, flags; tcpdata_t *fdata, *tdata; + int source, ret, flags; source = !fin->fin_rev; - if (((is->is_flags & IS_TCPFSM) != 0) && (source == 1) && + if (((is->is_flags & IS_TCPFSM) != 0) && (source == 1) && (ntohs(is->is_sport) != fin->fin_data[0])) source = 0; fdata = &is->is_tcp.ts_data[!source]; tdata = &is->is_tcp.ts_data[source]; MUTEX_ENTER(&is->is_lock); - if (fr_tcpinwindow(fin, fdata, tdata, tcp, is->is_flags)) { -#ifdef IPFILTER_SCAN - if (is->is_flags & (IS_SC_CLIENT|IS_SC_SERVER)) { - ipsc_packet(fin, is); - if (FR_ISBLOCK(is->is_pass)) { - MUTEX_EXIT(&is->is_lock); - return 1; - } + + /* + * If a SYN packet is received for a connection that is on the way out + * but hasn't yet departed then advance this session along the way. + */ + if ((tcp->th_flags & TH_OPENING) == TH_SYN) { + if ((is->is_state[0] > IPF_TCPS_ESTABLISHED) && + (is->is_state[1] > IPF_TCPS_ESTABLISHED)) { + is->is_state[!source] = IPF_TCPS_CLOSED; + ipf_movequeue(softc->ipf_ticks, &is->is_sti, + is->is_sti.tqe_ifq, + &softs->ipf_state_deletetq); + MUTEX_EXIT(&is->is_lock); + DT1(iss_tcp_closing, ipstate_t *, is); + SBUMP(ipf_state_stats.iss_tcp_closing); + return 0; } -#endif + } + if (is->is_flags & IS_LOOSE) + ret = 1; + else + ret = ipf_state_tcpinwindow(fin, fdata, tdata, tcp, + is->is_flags); + if (ret > 0) { /* * Nearing end of connection, start timeout. */ - ret = fr_tcp_age(&is->is_sti, fin, ips_tqtqb, is->is_flags); + ret = ipf_tcp_age(&is->is_sti, fin, softs->ipf_state_tcptq, + is->is_flags, ret); if (ret == 0) { MUTEX_EXIT(&is->is_lock); + DT2(iss_tcp_fsm, fr_info_t *, fin, ipstate_t *, is); + SBUMP(ipf_state_stats.iss_tcp_fsm); return 0; } + if (softs->ipf_state_logging > 4) + ipf_state_log(softc, is, ISL_STATECHANGE); + /* * set s0's as appropriate. Use syn-ack packet as it * contains both pieces of required information. @@ -1321,40 +2060,38 @@ ipstate_t *is; if (flags == (TH_SYN|TH_ACK)) { is->is_s0[source] = ntohl(tcp->th_ack); is->is_s0[!source] = ntohl(tcp->th_seq) + 1; - if ((TCP_OFF(tcp) > (sizeof(tcphdr_t) >> 2)) && - tdata->td_winscale) { - if (fr_tcpoptions(fin, tcp, fdata)) { - fdata->td_winflags = TCP_WSCALE_SEEN| - TCP_WSCALE_FIRST; - } else { - if (!fdata->td_winscale) - tdata->td_winscale = 0; - } + if ((TCP_OFF(tcp) > (sizeof(tcphdr_t) >> 2))) { + if (ipf_tcpoptions(softs, fin, tcp, + fdata) == -1) + fin->fin_flx |= FI_BAD; } if ((fin->fin_out != 0) && (is->is_pass & FR_NEWISN)) - fr_checknewisn(fin, is); + ipf_checknewisn(fin, is); } else if (flags == TH_SYN) { is->is_s0[source] = ntohl(tcp->th_seq) + 1; - if ((TCP_OFF(tcp) > (sizeof(tcphdr_t) >> 2))) - if (fr_tcpoptions(fin, tcp, tdata)) { - tdata->td_winflags = TCP_WSCALE_SEEN| - TCP_WSCALE_FIRST; - } + if ((TCP_OFF(tcp) > (sizeof(tcphdr_t) >> 2))) { + if (ipf_tcpoptions(softs, fin, tcp, + fdata) == -1) + fin->fin_flx |= FI_BAD; + } if ((fin->fin_out != 0) && (is->is_pass & FR_NEWISN)) - fr_checknewisn(fin, is); + ipf_checknewisn(fin, is); } ret = 1; - } else - fin->fin_flx |= FI_OOW; + } else { + DT2(iss_tcp_oow, fr_info_t *, fin, ipstate_t *, is); + SBUMP(ipf_state_stats.iss_tcp_oow); + ret = 0; + } MUTEX_EXIT(&is->is_lock); return ret; } /* ------------------------------------------------------------------------ */ -/* Function: fr_checknewisn */ +/* Function: ipf_checknewisn */ /* Returns: Nil */ /* Parameters: fin(I) - pointer to packet information */ /* is(I) - pointer to master state structure */ @@ -1365,9 +2102,10 @@ ipstate_t *is; /* NOTE: This does not actually change the sequence numbers, only gets new */ /* one ready. */ /* ------------------------------------------------------------------------ */ -static void fr_checknewisn(fin, is) -fr_info_t *fin; -ipstate_t *is; +static void +ipf_checknewisn(fin, is) + fr_info_t *fin; + ipstate_t *is; { u_32_t sumd, old, new; tcphdr_t *tcp; @@ -1379,7 +2117,7 @@ ipstate_t *is; if (((i == 0) && !(is->is_flags & IS_ISNSYN)) || ((i == 1) && !(is->is_flags & IS_ISNACK))) { old = ntohl(tcp->th_seq); - new = fr_newisn(fin); + new = ipf_newisn(fin); is->is_isninc[i] = new - old; CALC_SUMD(old, new, sumd); is->is_sumd[i] = (sumd & 0xffff) + (sumd >> 16); @@ -1390,7 +2128,7 @@ ipstate_t *is; /* ------------------------------------------------------------------------ */ -/* Function: fr_tcpinwindow */ +/* Function: ipf_state_tcpinwindow */ /* Returns: int - 1 == packet inside TCP "window", 0 == not inside. */ /* Parameters: fin(I) - pointer to packet information */ /* fdata(I) - pointer to tcp state informatio (forward) */ @@ -1401,15 +2139,19 @@ ipstate_t *is; /* within the TCP data window. In a show of generosity, allow packets that */ /* are within the window space behind the current sequence # as well. */ /* ------------------------------------------------------------------------ */ -int fr_tcpinwindow(fin, fdata, tdata, tcp, flags) -fr_info_t *fin; -tcpdata_t *fdata, *tdata; -tcphdr_t *tcp; -int flags; +static int +ipf_state_tcpinwindow(fin, fdata, tdata, tcp, flags) + fr_info_t *fin; + tcpdata_t *fdata, *tdata; + tcphdr_t *tcp; + int flags; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_state_softc_t *softs = softc->ipf_state_soft; tcp_seq seq, ack, end; int ackskew, tcpflags; u_32_t win, maxwin; + int dsize, inseq; /* * Find difference between last checked packet and this packet. @@ -1421,9 +2163,16 @@ int flags; win = ntohs(tcp->th_win); else win = ntohs(tcp->th_win) << fdata->td_winscale; + + /* + * A window of 0 produces undesirable behaviour from this function. + */ if (win == 0) win = 1; + dsize = fin->fin_dlen - (TCP_OFF(tcp) << 2) + + ((tcpflags & TH_SYN) ? 1 : 0) + ((tcpflags & TH_FIN) ? 1 : 0); + /* * if window scaling is present, the scaling is only allowed * for windows not in the first SYN packet. In that packet the @@ -1436,19 +2185,11 @@ int flags; * the receiver also does window scaling) */ if (!(tcpflags & TH_SYN) && (fdata->td_winflags & TCP_WSCALE_FIRST)) { - if (tdata->td_winflags & TCP_WSCALE_SEEN) { - fdata->td_winflags &= ~TCP_WSCALE_FIRST; - fdata->td_maxwin = win; - } else { - fdata->td_winscale = 0; - fdata->td_winflags = 0; - tdata->td_winscale = 0; - tdata->td_winflags = 0; - } + fdata->td_winflags &= ~TCP_WSCALE_FIRST; + fdata->td_maxwin = win; } - end = seq + fin->fin_dlen - (TCP_OFF(tcp) << 2) + - ((tcpflags & TH_SYN) ? 1 : 0) + ((tcpflags & TH_FIN) ? 1 : 0); + end = seq + dsize; if ((fdata->td_end == 0) && (!(flags & IS_TCPFSM) || @@ -1456,7 +2197,7 @@ int flags; /* * Must be a (outgoing) SYN-ACK in reply to a SYN. */ - fdata->td_end = end; + fdata->td_end = end - 1; fdata->td_maxwin = 1; fdata->td_maxend = end + win; } @@ -1469,9 +2210,6 @@ int flags; ack = tdata->td_end; } - if (seq == end) - seq = end = fdata->td_end; - maxwin = tdata->td_maxwin; ackskew = tdata->td_end - ack; @@ -1480,22 +2218,71 @@ int flags; */ if ((flags & IS_STRICT) != 0) { if (seq != fdata->td_end) { + DT2(iss_tcp_struct, tcpdata_t *, fdata, int, seq); + SBUMP(ipf_state_stats.iss_tcp_strict); + fin->fin_flx |= FI_OOW; return 0; } } #define SEQ_GE(a,b) ((int)((a) - (b)) >= 0) #define SEQ_GT(a,b) ((int)((a) - (b)) > 0) - if ( -#if defined(_KERNEL) - (SEQ_GE(fdata->td_maxend, end)) && + inseq = 0; + if ((SEQ_GE(fdata->td_maxend, end)) && (SEQ_GE(seq, fdata->td_end - maxwin)) && -#endif /* XXX what about big packets */ #define MAXACKWINDOW 66000 - (-ackskew <= (MAXACKWINDOW << fdata->td_winscale)) && + (-ackskew <= (MAXACKWINDOW)) && ( ackskew <= (MAXACKWINDOW << fdata->td_winscale))) { + inseq = 1; + /* + * Microsoft Windows will send the next packet to the right of the + * window if SACK is in use. + */ + } else if ((seq == fdata->td_maxend) && (ackskew == 0) && + (fdata->td_winflags & TCP_SACK_PERMIT) && + (tdata->td_winflags & TCP_SACK_PERMIT)) { + DT2(iss_sinsack, tcpdata_t *, fdata, int, seq); + SBUMP(ipf_state_stats.iss_winsack); + inseq = 1; + /* + * Sometimes a TCP RST will be generated with only the ACK field + * set to non-zero. + */ + } else if ((seq == 0) && (tcpflags == (TH_RST|TH_ACK)) && + (ackskew >= -1) && (ackskew <= 1)) { + inseq = 1; + } else if (!(flags & IS_TCPFSM)) { + int i; + i = (fin->fin_rev << 1) + fin->fin_out; + +#if 0 + if (is_pkts[i]0 == 0) { + /* + * Picking up a connection in the middle, the "next" + * packet seen from a direction that is new should be + * accepted, even if it appears out of sequence. + */ + inseq = 1; + } else +#endif + if (!(fdata->td_winflags & + (TCP_WSCALE_SEEN|TCP_WSCALE_FIRST))) { + /* + * No TCPFSM and no window scaling, so make some + * extra guesses. + */ + if ((seq == fdata->td_maxend) && (ackskew == 0)) + inseq = 1; + else if (SEQ_GE(seq + maxwin, fdata->td_end - maxwin)) + inseq = 1; + } + } + + /* TRACE(inseq, fdata, tdata, seq, end, ack, ackskew, win, maxwin) */ + + if (inseq) { /* if ackskew < 0 then this should be due to fragmented * packets. There is no way to know the length of the * total packet in advance. @@ -1522,12 +2309,14 @@ int flags; tdata->td_maxend = ack + win; return 1; } + SBUMP(ipf_state_stats.iss_oow); + fin->fin_flx |= FI_OOW; return 0; } /* ------------------------------------------------------------------------ */ -/* Function: fr_stclone */ +/* Function: ipf_state_clone */ /* Returns: ipstate_t* - NULL == cloning failed, */ /* else pointer to new state structure */ /* Parameters: fin(I) - pointer to packet information */ @@ -1536,27 +2325,40 @@ int flags; /* */ /* Create a "duplcate" state table entry from the master. */ /* ------------------------------------------------------------------------ */ -static ipstate_t *fr_stclone(fin, tcp, is) -fr_info_t *fin; -tcphdr_t *tcp; -ipstate_t *is; +static ipstate_t * +ipf_state_clone(fin, tcp, is) + fr_info_t *fin; + tcphdr_t *tcp; + ipstate_t *is; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_state_softc_t *softs = softc->ipf_state_soft; ipstate_t *clone; u_32_t send; - if (ips_num == fr_statemax) { - ATOMIC_INCL(ips_stats.iss_max); - fr_state_doflush = 1; + if (softs->ipf_state_stats.iss_active == softs->ipf_state_max) { + SBUMPD(ipf_state_stats, iss_max); + softs->ipf_state_doflush = 1; return NULL; } KMALLOC(clone, ipstate_t *); - if (clone == NULL) + if (clone == NULL) { + SBUMPD(ipf_state_stats, iss_clone_nomem); return NULL; + } bcopy((char *)is, (char *)clone, sizeof(*clone)); MUTEX_NUKE(&clone->is_lock); + /* + * It has not yet been placed on any timeout queue, so make sure + * all of that data is zero'd out. + */ + clone->is_sti.tqe_pnext = NULL; + clone->is_sti.tqe_next = NULL; + clone->is_sti.tqe_ifq = NULL; + clone->is_sti.tqe_parent = clone; - clone->is_die = ONE_DAY + fr_ticks; + clone->is_die = ONE_DAY + softc->ipf_ticks; clone->is_state[0] = 0; clone->is_state[1] = 0; send = ntohl(tcp->th_seq) + fin->fin_dlen - (TCP_OFF(tcp) << 2) + @@ -1583,50 +2385,61 @@ ipstate_t *is; clone->is_flags &= ~SI_CLONE; clone->is_flags |= SI_CLONED; - fr_stinsert(clone, fin->fin_rev); - MUTEX_ENTER(&clone->is_lock); + if (ipf_state_insert(softc, clone, fin->fin_rev) == -1) { + KFREE(clone); + return NULL; + } + clone->is_ref = 1; if (clone->is_p == IPPROTO_TCP) { - (void) fr_tcp_age(&clone->is_sti, fin, ips_tqtqb, - clone->is_flags); + (void) ipf_tcp_age(&clone->is_sti, fin, softs->ipf_state_tcptq, + clone->is_flags, 2); } MUTEX_EXIT(&clone->is_lock); -#ifdef IPFILTER_SCAN - (void) ipsc_attachis(is); -#endif -#ifdef IPFILTER_SYNC if (is->is_flags & IS_STATESYNC) - clone->is_sync = ipfsync_new(SMC_STATE, fin, clone); -#endif + clone->is_sync = ipf_sync_new(softc, SMC_STATE, fin, clone); + DT2(iss_clone, ipstate_t *, is, ipstate_t *, clone); + SBUMP(ipf_state_stats.iss_cloned); return clone; } /* ------------------------------------------------------------------------ */ -/* Function: fr_matchsrcdst */ +/* Function: ipf_matchsrcdst */ /* Returns: Nil */ -/* Parameters: fin(I) - pointer to packet information */ -/* is(I) - pointer to state structure */ -/* src(I) - pointer to source address */ -/* dst(I) - pointer to destination address */ -/* tcp(I) - pointer to TCP/UDP header */ +/* Parameters: fin(I) - pointer to packet information */ +/* is(I) - pointer to state structure */ +/* src(I) - pointer to source address */ +/* dst(I) - pointer to destination address */ +/* tcp(I) - pointer to TCP/UDP header */ +/* cmask(I) - mask of FI_* bits to check */ /* */ /* Match a state table entry against an IP packet. The logic below is that */ /* ret gets set to one if the match succeeds, else remains 0. If it is */ /* still 0 after the test. no match. */ /* ------------------------------------------------------------------------ */ -static ipstate_t *fr_matchsrcdst(fin, is, src, dst, tcp, cmask) -fr_info_t *fin; -ipstate_t *is; -i6addr_t *src, *dst; -tcphdr_t *tcp; -u_32_t cmask; +static ipstate_t * +ipf_matchsrcdst(fin, is, src, dst, tcp, cmask) + fr_info_t *fin; + ipstate_t *is; + i6addr_t *src, *dst; + tcphdr_t *tcp; + u_32_t cmask; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_state_softc_t *softs = softc->ipf_state_soft; int ret = 0, rev, out, flags, flx = 0, idx; u_short sp, dp; u_32_t cflx; void *ifp; + /* + * If a connection is about to be deleted, no packets + * are allowed to match it. + */ + if (is->is_sti.tqe_ifq == &softs->ipf_state_deletetq) + return NULL; + rev = IP6_NEQ(&is->is_dst, dst); ifp = fin->fin_ifp; out = fin->fin_out; @@ -1653,13 +2466,17 @@ u_32_t cmask; * If the interface for this 'direction' is set, make sure it matches. * An interface name that is not set matches any, as does a name of *. */ - if ((is->is_ifp[idx] == NULL && - (*is->is_ifname[idx] == '\0' || *is->is_ifname[idx] == '*')) || - is->is_ifp[idx] == ifp) + if ((is->is_ifp[idx] == ifp) || (is->is_ifp[idx] == NULL && + (*is->is_ifname[idx] == '\0' || *is->is_ifname[idx] == '-' || + *is->is_ifname[idx] == '*'))) ret = 1; - if (ret == 0) + if (ret == 0) { + DT2(iss_lookup_badifp, fr_info_t *, fin, ipstate_t *, is); + SBUMP(ipf_state_stats.iss_lookup_badifp); + /* TRACE is, out, rev, idx */ return NULL; + } ret = 0; /* @@ -1669,7 +2486,8 @@ u_32_t cmask; if ((IP6_EQ(&is->is_dst, dst) || (flags & SI_W_DADDR)) && (IP6_EQ(&is->is_src, src) || (flags & SI_W_SADDR))) { if (tcp) { - if ((sp == is->is_sport || flags & SI_W_SPORT)&& + if ((sp == is->is_sport || flags & SI_W_SPORT) + && (dp == is->is_dport || flags & SI_W_DPORT)) ret = 1; } else { @@ -1680,7 +2498,8 @@ u_32_t cmask; if ((IP6_EQ(&is->is_dst, src) || (flags & SI_W_DADDR)) && (IP6_EQ(&is->is_src, dst) || (flags & SI_W_SADDR))) { if (tcp) { - if ((dp == is->is_sport || flags & SI_W_SPORT)&& + if ((dp == is->is_sport || flags & SI_W_SPORT) + && (sp == is->is_dport || flags & SI_W_DPORT)) ret = 1; } else { @@ -1689,8 +2508,12 @@ u_32_t cmask; } } - if (ret == 0) + if (ret == 0) { + SBUMP(ipf_state_stats.iss_lookup_badport); + DT2(iss_lookup_badport, fr_info_t *, fin, ipstate_t *, is); + /* TRACE rev, is, sp, dp, src, dst */ return NULL; + } /* * Whether or not this should be here, is questionable, but the aim @@ -1711,55 +2534,27 @@ u_32_t cmask; if ((flags & SI_W_SADDR) != 0) { if (rev == 0) { -#ifdef USE_INET6 - if (is->is_v == 6 && - IN6_IS_ADDR_MULTICAST(&fi->fi_src.in6)) - /*EMPTY*/; - else -#endif - { - is->is_src = fi->fi_src; - is->is_flags &= ~SI_W_SADDR; - } + is->is_src = fi->fi_src; + is->is_flags &= ~SI_W_SADDR; } else { -#ifdef USE_INET6 - if (is->is_v == 6 && - IN6_IS_ADDR_MULTICAST(&fi->fi_dst.in6)) - /*EMPTY*/; - else -#endif - { + if (!(fin->fin_flx & (FI_MULTICAST|FI_MBCAST))){ is->is_src = fi->fi_dst; is->is_flags &= ~SI_W_SADDR; } } } else if ((flags & SI_W_DADDR) != 0) { if (rev == 0) { -#ifdef USE_INET6 - if (is->is_v == 6 && - IN6_IS_ADDR_MULTICAST(&fi->fi_dst.in6)) - /*EMPTY*/; - else -#endif - { + if (!(fin->fin_flx & (FI_MULTICAST|FI_MBCAST))){ is->is_dst = fi->fi_dst; is->is_flags &= ~SI_W_DADDR; } } else { -#ifdef USE_INET6 - if (is->is_v == 6 && - IN6_IS_ADDR_MULTICAST(&fi->fi_src.in6)) - /*EMPTY*/; - else -#endif - { - is->is_dst = fi->fi_src; - is->is_flags &= ~SI_W_DADDR; - } + is->is_dst = fi->fi_src; + is->is_flags &= ~SI_W_DADDR; } } if ((is->is_flags & (SI_WILDA|SI_WILDP)) == 0) { - ATOMIC_DECL(ips_stats.iss_wild); + ATOMIC_DECL(softs->ipf_state_stats.iss_wild); } } @@ -1770,28 +2565,33 @@ u_32_t cmask; * Match up any flags set from IP options. */ if ((cflx && (flx != (cflx & cmask))) || - ((fin->fin_optmsk & is->is_optmsk) != is->is_opt) || + ((fin->fin_optmsk & is->is_optmsk[rev]) != is->is_opt[rev]) || ((fin->fin_secmsk & is->is_secmsk) != is->is_sec) || - ((fin->fin_auth & is->is_authmsk) != is->is_auth)) + ((fin->fin_auth & is->is_authmsk) != is->is_auth)) { + SBUMPD(ipf_state_stats, iss_miss_mask); return NULL; + } - /* - * Only one of the source or destination port can be flagged as a - * wildcard. When filling it in, fill in a copy of the matched entry - * if it has the cloning flag set. - */ if ((fin->fin_flx & FI_IGNORE) != 0) { fin->fin_rev = rev; return is; } + /* + * Only one of the source or destination port can be flagged as a + * wildcard. When filling it in, fill in a copy of the matched entry + * if it has the cloning flag set. + */ if ((flags & (SI_W_SPORT|SI_W_DPORT))) { if ((flags & SI_CLONE) != 0) { - is = fr_stclone(fin, tcp, is); - if (is == NULL) + ipstate_t *clone; + + clone = ipf_state_clone(fin, tcp, is); + if (clone == NULL) return NULL; + is = clone; } else { - ATOMIC_DECL(ips_stats.iss_wild); + ATOMIC_DECL(softs->ipf_state_stats.iss_wild); } if ((flags & SI_W_SPORT) != 0) { @@ -1814,14 +2614,23 @@ u_32_t cmask; is->is_maxdend = is->is_dend + 1; } is->is_flags &= ~(SI_W_SPORT|SI_W_DPORT); - if ((flags & SI_CLONED) && ipstate_logging) - ipstate_log(is, ISL_CLONE); + if ((flags & SI_CLONED) && softs->ipf_state_logging) + ipf_state_log(softc, is, ISL_CLONE); } ret = -1; - if (is->is_flx[out][rev] == 0) + if (is->is_flx[out][rev] == 0) { is->is_flx[out][rev] = flx; + if (rev == 1 && is->is_optmsk[1] == 0) { + is->is_opt[1] = fin->fin_optmsk; + is->is_optmsk[1] = 0xffffffff; + if (is->is_v == 6) { + is->is_opt[1] &= ~0x8; + is->is_optmsk[1] &= ~0x8; + } + } + } /* * Check if the interface name for this "direction" is set and if not, @@ -1830,7 +2639,7 @@ u_32_t cmask; if (is->is_ifp[idx] == NULL && (*is->is_ifname[idx] == '\0' || *is->is_ifname[idx] == '*')) { is->is_ifp[idx] = ifp; - COPYIFNAME(ifp, is->is_ifname[idx]); + COPYIFNAME(fin->fin_v, ifp, is->is_ifname[idx]); } fin->fin_rev = rev; return is; @@ -1838,7 +2647,7 @@ u_32_t cmask; /* ------------------------------------------------------------------------ */ -/* Function: fr_checkicmpmatchingstate */ +/* Function: ipf_checkicmpmatchingstate */ /* Returns: Nil */ /* Parameters: fin(I) - pointer to packet information */ /* */ @@ -1848,13 +2657,13 @@ u_32_t cmask; /* If we return NULL then no lock on ipf_state is held. */ /* If we return non-null then a read-lock on ipf_state is held. */ /* ------------------------------------------------------------------------ */ -static ipstate_t *fr_checkicmpmatchingstate(fin) -fr_info_t *fin; +static ipstate_t * +ipf_checkicmpmatchingstate(fin) + fr_info_t *fin; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_state_softc_t *softs = softc->ipf_state_soft; ipstate_t *is, **isp; - u_short sport, dport; - u_char pr; - int backward, i, oi; i6addr_t dst, src; struct icmp *ic; u_short savelen; @@ -1862,41 +2671,44 @@ fr_info_t *fin; fr_info_t ofin; tcphdr_t *tcp; int type, len; + u_char pr; ip_t *oip; u_int hv; /* * Does it at least have the return (basic) IP header ? + * Is it an actual recognised ICMP error type? * Only a basic IP header (no options) should be with * an ICMP error header. */ if ((fin->fin_v != 4) || (fin->fin_hlen != sizeof(ip_t)) || - (fin->fin_plen < ICMPERR_MINPKTLEN)) + (fin->fin_plen < ICMPERR_MINPKTLEN) || + !(fin->fin_flx & FI_ICMPERR)) { + SBUMPD(ipf_state_stats, iss_icmp_bad); return NULL; + } ic = fin->fin_dp; type = ic->icmp_type; - /* - * If it's not an error type, then return - */ - if ((type != ICMP_UNREACH) && (type != ICMP_SOURCEQUENCH) && - (type != ICMP_REDIRECT) && (type != ICMP_TIMXCEED) && - (type != ICMP_PARAMPROB)) - return NULL; oip = (ip_t *)((char *)ic + ICMPERR_ICMPHLEN); /* * Check if the at least the old IP header (with options) and * 8 bytes of payload is present. */ - if (fin->fin_plen < ICMPERR_MAXPKTLEN + ((IP_HL(oip) - 5) << 2)) + if (fin->fin_plen < ICMPERR_MAXPKTLEN + ((IP_HL(oip) - 5) << 2)) { + SBUMPDX(ipf_state_stats, iss_icmp_short, iss_icmp_short_1); return NULL; + } /* * Sanity Checks. */ len = fin->fin_dlen - ICMPERR_ICMPHLEN; - if ((len <= 0) || ((IP_HL(oip) << 2) > len)) + if ((len <= 0) || ((IP_HL(oip) << 2) > len)) { + DT2(iss_icmp_len, fr_info_t *, fin, struct ip*, oip); + SBUMPDX(ipf_state_stats, iss_icmp_short, iss_icmp_short_1); return NULL; + } /* * Is the buffer big enough for all of it ? It's the size of the IP @@ -1904,7 +2716,7 @@ fr_info_t *fin; * may be too big to be in this buffer but not so big that it's * outside the ICMP packet, leading to TCP deref's causing problems. * This is possible because we don't know how big oip_hl is when we - * do the pullup early in fr_check() and thus can't guarantee it is + * do the pullup early in ipf_check() and thus can't guarantee it is * all here now. */ #ifdef _KERNEL @@ -1913,15 +2725,20 @@ fr_info_t *fin; m = fin->fin_m; # if defined(MENTAT) - if ((char *)oip + len > (char *)m->b_wptr) + if ((char *)oip + len > (char *)m->b_wptr) { + SBUMPDX(ipf_state_stats, iss_icmp_short, iss_icmp_short_2); return NULL; + } # else - if ((char *)oip + len > (char *)fin->fin_ip + m->m_len) + if ((char *)oip + len > (char *)fin->fin_ip + m->m_len) { + SBUMPDX(ipf_state_stats, iss_icmp_short, iss_icmp_short_3); return NULL; + } # endif } #endif - bcopy((char *)fin, (char *)&ofin, sizeof(fin)); + + bcopy((char *)fin, (char *)&ofin, sizeof(*fin)); /* * in the IPv4 case we must zero the i6addr union otherwise @@ -1936,44 +2753,46 @@ fr_info_t *fin; * matchsrcdst note that not all fields are encessary * but this is the cleanest way. Note further we fill * in fin_mp such that if someone uses it we'll get - * a kernel panic. fr_matchsrcdst does not use this. + * a kernel panic. ipf_matchsrcdst does not use this. * * watch out here, as ip is in host order and oip in network * order. Any change we make must be undone afterwards, like - * oip->ip_off - it is still in network byte order so fix it. + * oip->ip_len. */ savelen = oip->ip_len; - oip->ip_len = len; - oip->ip_off = htons(oip->ip_off); + oip->ip_len = htons(len); ofin.fin_flx = FI_NOCKSUM; ofin.fin_v = 4; ofin.fin_ip = oip; ofin.fin_m = NULL; /* if dereferenced, panic XXX */ ofin.fin_mp = NULL; /* if dereferenced, panic XXX */ - ofin.fin_plen = fin->fin_dlen - ICMPERR_ICMPHLEN; - (void) fr_makefrip(IP_HL(oip) << 2, oip, &ofin); + (void) ipf_makefrip(IP_HL(oip) << 2, oip, &ofin); ofin.fin_ifp = fin->fin_ifp; ofin.fin_out = !fin->fin_out; + + hv = (pr = oip->ip_p); + src.in4 = oip->ip_src; + hv += src.in4.s_addr; + dst.in4 = oip->ip_dst; + hv += dst.in4.s_addr; + /* - * Reset the short and bad flag here because in fr_matchsrcdst() + * Reset the short and bad flag here because in ipf_matchsrcdst() * the flags for the current packet (fin_flx) are compared against * those for the existing session. */ ofin.fin_flx &= ~(FI_BAD|FI_SHORT); /* - * Put old values of ip_len and ip_off back as we don't know - * if we have to forward the packet (or process it again. + * Put old values of ip_len back as we don't know + * if we have to forward the packet or process it again. */ oip->ip_len = savelen; - oip->ip_off = htons(oip->ip_off); switch (oip->ip_p) { case IPPROTO_ICMP : - icmp = (icmphdr_t *)((char *)oip + (IP_HL(oip) << 2)); - /* * an ICMP error can only be generated as a result of an * ICMP query, not as the response on an ICMP error @@ -1981,81 +2800,52 @@ fr_info_t *fin; * XXX theoretically ICMP_ECHOREP and the other reply's are * ICMP query's as well, but adding them here seems strange XXX */ - if ((icmp->icmp_type != ICMP_ECHO) && - (icmp->icmp_type != ICMP_TSTAMP) && - (icmp->icmp_type != ICMP_IREQ) && - (icmp->icmp_type != ICMP_MASKREQ)) + if ((ofin.fin_flx & FI_ICMPERR) != 0) { + DT1(iss_icmp_icmperr, fr_info_t *, &ofin); + SBUMP(ipf_state_stats.iss_icmp_icmperr); return NULL; + } /* * perform a lookup of the ICMP packet in the state table */ - hv = (pr = oip->ip_p); - src.in4 = oip->ip_src; - hv += src.in4.s_addr; - dst.in4 = oip->ip_dst; - hv += dst.in4.s_addr; + icmp = (icmphdr_t *)((char *)oip + (IP_HL(oip) << 2)); hv += icmp->icmp_id; hv = DOUBLE_HASH(hv); - READ_ENTER(&ipf_state); - for (isp = &ips_table[hv]; ((is = *isp) != NULL); ) { + READ_ENTER(&softc->ipf_state); + for (isp = &softs->ipf_state_table[hv]; + ((is = *isp) != NULL); ) { isp = &is->is_hnext; if ((is->is_p != pr) || (is->is_v != 4)) continue; if (is->is_pass & FR_NOICMPERR) continue; - is = fr_matchsrcdst(&ofin, is, &src, &dst, + + is = ipf_matchsrcdst(&ofin, is, &src, &dst, NULL, FI_ICMPCMP); - if (is != NULL) { - if ((is->is_pass & FR_NOICMPERR) != 0) { - RWLOCK_EXIT(&ipf_state); - return NULL; - } - /* - * i : the index of this packet (the icmp - * unreachable) - * oi : the index of the original packet found - * in the icmp header (i.e. the packet - * causing this icmp) - * backward : original packet was backward - * compared to the state - */ - backward = IP6_NEQ(&is->is_src, &src); - fin->fin_rev = !backward; - i = (!backward << 1) + fin->fin_out; - oi = (backward << 1) + ofin.fin_out; - if (is->is_icmppkts[i] > is->is_pkts[oi]) - continue; - ips_stats.iss_hits++; - is->is_icmppkts[i]++; + if ((is != NULL) && !ipf_allowstateicmp(fin, is, &src)) return is; - } } - RWLOCK_EXIT(&ipf_state); + RWLOCK_EXIT(&softc->ipf_state); + SBUMPDX(ipf_state_stats, iss_icmp_miss, iss_icmp_miss_1); return NULL; case IPPROTO_TCP : case IPPROTO_UDP : break; default : + SBUMPDX(ipf_state_stats, iss_icmp_miss, iss_icmp_miss_2); return NULL; } tcp = (tcphdr_t *)((char *)oip + (IP_HL(oip) << 2)); - dport = tcp->th_dport; - sport = tcp->th_sport; - hv = (pr = oip->ip_p); - src.in4 = oip->ip_src; - hv += src.in4.s_addr; - dst.in4 = oip->ip_dst; - hv += dst.in4.s_addr; - hv += dport; - hv += sport; + hv += tcp->th_dport;; + hv += tcp->th_sport;; hv = DOUBLE_HASH(hv); - READ_ENTER(&ipf_state); - for (isp = &ips_table[hv]; ((is = *isp) != NULL); ) { + READ_ENTER(&softc->ipf_state); + for (isp = &softs->ipf_state_table[hv]; ((is = *isp) != NULL); ) { isp = &is->is_hnext; /* * Only allow this icmp though if the @@ -2067,40 +2857,93 @@ fr_info_t *fin; * short flag is set. */ if ((is->is_p == pr) && (is->is_v == 4) && - (is = fr_matchsrcdst(&ofin, is, &src, &dst, - tcp, FI_ICMPCMP))) { - /* - * i : the index of this packet (the icmp unreachable) - * oi : the index of the original packet found in the - * icmp header (i.e. the packet causing this icmp) - * backward : original packet was backward compared to - * the state - */ - backward = IP6_NEQ(&is->is_src, &src); - fin->fin_rev = !backward; - i = (!backward << 1) + fin->fin_out; - oi = (backward << 1) + ofin.fin_out; - - if (((is->is_pass & FR_NOICMPERR) != 0) || - (is->is_icmppkts[i] > is->is_pkts[oi])) - break; - ips_stats.iss_hits++; - is->is_icmppkts[i]++; - /* - * we deliberately do not touch the timeouts - * for the accompanying state table entry. - * It remains to be seen if that is correct. XXX - */ - return is; + (is = ipf_matchsrcdst(&ofin, is, &src, &dst, + tcp, FI_ICMPCMP))) { + if (ipf_allowstateicmp(fin, is, &src) == 0) + return is; } } - RWLOCK_EXIT(&ipf_state); + RWLOCK_EXIT(&softc->ipf_state); + SBUMPDX(ipf_state_stats, iss_icmp_miss, iss_icmp_miss_3); return NULL; } /* ------------------------------------------------------------------------ */ -/* Function: fr_ipsmove */ +/* Function: ipf_allowstateicmp */ +/* Returns: int - 1 = packet denied, 0 = packet allowed */ +/* Parameters: fin(I) - pointer to packet information */ +/* is(I) - pointer to state table entry */ +/* src(I) - source address to check permission for */ +/* */ +/* For an ICMP packet that has so far matched a state table entry, check if */ +/* there are any further refinements that might mean we want to block this */ +/* packet. This code isn't specific to either IPv4 or IPv6. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_allowstateicmp(fin, is, src) + fr_info_t *fin; + ipstate_t *is; + i6addr_t *src; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_state_softc_t *softs = softc->ipf_state_soft; + frentry_t *savefr; + frentry_t *fr; + u_32_t ipass; + int backward; + int oi; + int i; + + fr = is->is_rule; + if (fr != NULL && fr->fr_icmpgrp != NULL) { + savefr = fin->fin_fr; + fin->fin_fr = fr->fr_icmpgrp->fg_start; + + ipass = ipf_scanlist(fin, softc->ipf_pass); + fin->fin_fr = savefr; + if (FR_ISBLOCK(ipass)) { + SBUMPD(ipf_state_stats, iss_icmp_headblock); + return 1; + } + } + + /* + * i : the index of this packet (the icmp unreachable) + * oi : the index of the original packet found in the + * icmp header (i.e. the packet causing this icmp) + * backward : original packet was backward compared to + * the state + */ + backward = IP6_NEQ(&is->is_src, src); + fin->fin_rev = !backward; + i = (!backward << 1) + fin->fin_out; + oi = (backward << 1) + !fin->fin_out; + + if (is->is_pass & FR_NOICMPERR) { + SBUMPD(ipf_state_stats, iss_icmp_banned); + return 1; + } + if (is->is_icmppkts[i] > is->is_pkts[oi]) { + SBUMPD(ipf_state_stats, iss_icmp_toomany); + return 1; + } + + DT2(iss_icmp_hits, fr_info_t *, fin, ipstate_t *, is); + SBUMP(ipf_state_stats.iss_icmp_hits); + is->is_icmppkts[i]++; + + /* + * we deliberately do not touch the timeouts + * for the accompanying state table entry. + * It remains to be seen if that is correct. XXX + */ + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_ipsmove */ /* Returns: Nil */ /* Parameters: is(I) - pointer to state table entry */ /* hv(I) - new hash value for state table entry */ @@ -2108,16 +2951,19 @@ fr_info_t *fin; /* */ /* Move a state entry from one position in the hash table to another. */ /* ------------------------------------------------------------------------ */ -static void fr_ipsmove(is, hv) -ipstate_t *is; -u_int hv; +static void +ipf_ipsmove(softs, is, hv) + ipf_state_softc_t *softs; + ipstate_t *is; + u_int hv; { ipstate_t **isp; u_int hvm; - ASSERT(rw_read_locked(&ipf_state.ipf_lk) == 0); - hvm = is->is_hv; + + /* TRACE is, is_hv, hvm */ + /* * Remove the hash from the old location... */ @@ -2125,21 +2971,24 @@ u_int hv; if (is->is_hnext) is->is_hnext->is_phnext = isp; *isp = is->is_hnext; - if (ips_table[hvm] == NULL) - ips_stats.iss_inuse--; - ips_stats.iss_bucketlen[hvm]--; + if (softs->ipf_state_table[hvm] == NULL) + softs->ipf_state_stats.iss_inuse--; + softs->ipf_state_stats.iss_bucketlen[hvm]--; /* * ...and put the hash in the new one. */ hvm = DOUBLE_HASH(hv); is->is_hv = hvm; - isp = &ips_table[hvm]; + + /* TRACE is, hv, is_hv, hvm */ + + isp = &softs->ipf_state_table[hvm]; if (*isp) (*isp)->is_phnext = &is->is_hnext; else - ips_stats.iss_inuse++; - ips_stats.iss_bucketlen[hvm]++; + softs->ipf_state_stats.iss_inuse++; + softs->ipf_state_stats.iss_bucketlen[hvm]++; is->is_phnext = isp; is->is_hnext = *isp; *isp = is; @@ -2147,23 +2996,28 @@ u_int hv; /* ------------------------------------------------------------------------ */ -/* Function: fr_stlookup */ +/* Function: ipf_state_lookup */ /* Returns: ipstate_t* - NULL == no matching state found, */ /* else pointer to state information is returned */ -/* Parameters: fin(I) - pointer to packet information */ -/* tcp(I) - pointer to TCP/UDP header. */ +/* Parameters: fin(I) - pointer to packet information */ +/* tcp(I) - pointer to TCP/UDP header. */ +/* ifqp(O) - pointer for storing tailq timeout */ /* */ /* Search the state table for a matching entry to the packet described by */ -/* the contents of *fin. */ +/* the contents of *fin. For certain protocols, when a match is found the */ +/* timeout queue is also selected and stored in ifpq if it is non-NULL. */ /* */ /* If we return NULL then no lock on ipf_state is held. */ /* If we return non-null then a read-lock on ipf_state is held. */ /* ------------------------------------------------------------------------ */ -ipstate_t *fr_stlookup(fin, tcp, ifqp) -fr_info_t *fin; -tcphdr_t *tcp; -ipftq_t **ifqp; +ipstate_t * +ipf_state_lookup(fin, tcp, ifqp) + fr_info_t *fin; + tcphdr_t *tcp; + ipftq_t **ifqp; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_state_softc_t *softs = softc->ipf_state_soft; u_int hv, hvm, pr, v, tryagain; ipstate_t *is, **isp; u_short dport, sport; @@ -2199,6 +3053,16 @@ ipftq_t **ifqp; } } #endif + if ((v == 4) && + (fin->fin_flx & (FI_MULTICAST|FI_BROADCAST|FI_MBCAST))) { + if (fin->fin_out == 0) { + hv -= src.in4.s_addr; + } else { + hv -= dst.in4.s_addr; + } + } + + /* TRACE fin_saddr, fin_daddr, hv */ /* * Search the hash table for matching packet header info. @@ -2214,21 +3078,22 @@ ipftq_t **ifqp; hv += ic->icmp_id; } } - READ_ENTER(&ipf_state); + READ_ENTER(&softc->ipf_state); icmp6again: hvm = DOUBLE_HASH(hv); - for (isp = &ips_table[hvm]; ((is = *isp) != NULL); ) { + for (isp = &softs->ipf_state_table[hvm]; + ((is = *isp) != NULL); ) { isp = &is->is_hnext; if ((is->is_p != pr) || (is->is_v != v)) continue; - is = fr_matchsrcdst(fin, is, &src, &dst, NULL, FI_CMP); + is = ipf_matchsrcdst(fin, is, &src, &dst, NULL, FI_CMP); if (is != NULL && - fr_matchicmpqueryreply(v, &is->is_icmp, + ipf_matchicmpqueryreply(v, &is->is_icmp, ic, fin->fin_rev)) { if (fin->fin_rev) - ifq = &ips_icmpacktq; + ifq = &softs->ipf_state_icmpacktq; else - ifq = &ips_icmptq; + ifq = &softs->ipf_state_icmptq; break; } } @@ -2239,12 +3104,12 @@ icmp6again: hv += fin->fin_fi.fi_src.i6[1]; hv += fin->fin_fi.fi_src.i6[2]; hv += fin->fin_fi.fi_src.i6[3]; - fr_ipsmove(is, hv); - MUTEX_DOWNGRADE(&ipf_state); + ipf_ipsmove(softs, is, hv); + MUTEX_DOWNGRADE(&softc->ipf_state); } break; } - RWLOCK_EXIT(&ipf_state); + RWLOCK_EXIT(&softc->ipf_state); /* * No matching icmp state entry. Perhaps this is a @@ -2256,18 +3121,19 @@ icmp6again: * advantage of this requires some significant code changes * to handle the specific types where that is the case. */ - if ((ips_stats.iss_wild != 0) && (v == 6) && (tryagain == 0) && - !IN6_IS_ADDR_MULTICAST(&fin->fin_fi.fi_src.in6)) { + if ((softs->ipf_state_stats.iss_wild != 0) && + ((fin->fin_flx & FI_NOWILD) == 0) && + (v == 6) && (tryagain == 0)) { hv -= fin->fin_fi.fi_src.i6[0]; hv -= fin->fin_fi.fi_src.i6[1]; hv -= fin->fin_fi.fi_src.i6[2]; hv -= fin->fin_fi.fi_src.i6[3]; tryagain = 1; - WRITE_ENTER(&ipf_state); + WRITE_ENTER(&softc->ipf_state); goto icmp6again; } - is = fr_checkicmp6matchingstate(fin); + is = ipf_checkicmp6matchingstate(fin); if (is != NULL) return is; break; @@ -2278,24 +3144,26 @@ icmp6again: hv += ic->icmp_id; } hv = DOUBLE_HASH(hv); - READ_ENTER(&ipf_state); - for (isp = &ips_table[hv]; ((is = *isp) != NULL); ) { + READ_ENTER(&softc->ipf_state); + for (isp = &softs->ipf_state_table[hv]; + ((is = *isp) != NULL); ) { isp = &is->is_hnext; if ((is->is_p != pr) || (is->is_v != v)) continue; - is = fr_matchsrcdst(fin, is, &src, &dst, NULL, FI_CMP); - if (is != NULL && - fr_matchicmpqueryreply(v, &is->is_icmp, + is = ipf_matchsrcdst(fin, is, &src, &dst, NULL, FI_CMP); + if ((is != NULL) && + (ic->icmp_id == is->is_icmp.ici_id) && + ipf_matchicmpqueryreply(v, &is->is_icmp, ic, fin->fin_rev)) { if (fin->fin_rev) - ifq = &ips_icmpacktq; + ifq = &softs->ipf_state_icmpacktq; else - ifq = &ips_icmptq; + ifq = &softs->ipf_state_icmptq; break; } } if (is == NULL) { - RWLOCK_EXIT(&ipf_state); + RWLOCK_EXIT(&softc->ipf_state); } break; @@ -2308,18 +3176,23 @@ icmp6again: hv += dport; oow = 0; tryagain = 0; - READ_ENTER(&ipf_state); + READ_ENTER(&softc->ipf_state); retry_tcpudp: hvm = DOUBLE_HASH(hv); - for (isp = &ips_table[hvm]; ((is = *isp) != NULL); ) { + + /* TRACE hv, hvm */ + + for (isp = &softs->ipf_state_table[hvm]; + ((is = *isp) != NULL); ) { isp = &is->is_hnext; if ((is->is_p != pr) || (is->is_v != v)) continue; fin->fin_flx &= ~FI_OOW; - is = fr_matchsrcdst(fin, is, &src, &dst, tcp, FI_CMP); + is = ipf_matchsrcdst(fin, is, &src, &dst, tcp, FI_CMP); if (is != NULL) { if (pr == IPPROTO_TCP) { - if (!fr_tcpstate(fin, tcp, is)) { + if (!ipf_state_tcp(softc, softs, fin, + tcp, is)) { oow |= fin->fin_flx & FI_OOW; continue; } @@ -2332,19 +3205,39 @@ retry_tcpudp: !(is->is_flags & (SI_CLONE|SI_WILDP|SI_WILDA))) { hv += dport; hv += sport; - fr_ipsmove(is, hv); - MUTEX_DOWNGRADE(&ipf_state); + ipf_ipsmove(softs, is, hv); + MUTEX_DOWNGRADE(&softc->ipf_state); } break; } - RWLOCK_EXIT(&ipf_state); - - if (!tryagain && ips_stats.iss_wild) { - hv -= dport; - hv -= sport; - tryagain = 1; - WRITE_ENTER(&ipf_state); - goto retry_tcpudp; + RWLOCK_EXIT(&softc->ipf_state); + + if ((softs->ipf_state_stats.iss_wild != 0) && + ((fin->fin_flx & FI_NOWILD) == 0)) { + if (tryagain == 0) { + hv -= dport; + hv -= sport; + } else if (tryagain == 1) { + hv = fin->fin_fi.fi_p; + /* + * If we try to pretend this is a reply to a + * multicast/broadcast packet then we need to + * exclude part of the address from the hash + * calculation. + */ + if (fin->fin_out == 0) { + hv += src.in4.s_addr; + } else { + hv += dst.in4.s_addr; + } + hv += dport; + hv += sport; + } + tryagain++; + if (tryagain <= 2) { + WRITE_ENTER(&softc->ipf_state); + goto retry_tcpudp; + } } fin->fin_flx |= oow; break; @@ -2360,111 +3253,69 @@ retry_tcpudp: default : ifqp = NULL; hvm = DOUBLE_HASH(hv); - READ_ENTER(&ipf_state); - for (isp = &ips_table[hvm]; ((is = *isp) != NULL); ) { + READ_ENTER(&softc->ipf_state); + for (isp = &softs->ipf_state_table[hvm]; + ((is = *isp) != NULL); ) { isp = &is->is_hnext; if ((is->is_p != pr) || (is->is_v != v)) continue; - is = fr_matchsrcdst(fin, is, &src, &dst, NULL, FI_CMP); + is = ipf_matchsrcdst(fin, is, &src, &dst, NULL, FI_CMP); if (is != NULL) { - ifq = &ips_iptq; + ifq = &softs->ipf_state_iptq; break; } } if (is == NULL) { - RWLOCK_EXIT(&ipf_state); + RWLOCK_EXIT(&softc->ipf_state); } break; } - if ((is != NULL) && ((is->is_sti.tqe_flags & TQE_RULEBASED) != 0) && - (is->is_tqehead[fin->fin_rev] != NULL)) - ifq = is->is_tqehead[fin->fin_rev]; - if (ifq != NULL && ifqp != NULL) - *ifqp = ifq; + if (is != NULL) { + if (((is->is_sti.tqe_flags & TQE_RULEBASED) != 0) && + (is->is_tqehead[fin->fin_rev] != NULL)) + ifq = is->is_tqehead[fin->fin_rev]; + if (ifq != NULL && ifqp != NULL) + *ifqp = ifq; + } else { + SBUMP(ipf_state_stats.iss_lookup_miss); + } return is; } /* ------------------------------------------------------------------------ */ -/* Function: fr_updatestate */ -/* Returns: Nil */ -/* Parameters: fin(I) - pointer to packet information */ -/* is(I) - pointer to state table entry */ -/* Read Locks: ipf_state */ -/* */ -/* Updates packet and byte counters for a newly received packet. Seeds the */ -/* fragment cache with a new entry as required. */ -/* ------------------------------------------------------------------------ */ -void fr_updatestate(fin, is, ifq) -fr_info_t *fin; -ipstate_t *is; -ipftq_t *ifq; -{ - ipftqent_t *tqe; - int i, pass; - - i = (fin->fin_rev << 1) + fin->fin_out; - - /* - * For TCP packets, ifq == NULL. For all others, check if this new - * queue is different to the last one it was on and move it if so. - */ - tqe = &is->is_sti; - MUTEX_ENTER(&is->is_lock); - if ((tqe->tqe_flags & TQE_RULEBASED) != 0) - ifq = is->is_tqehead[fin->fin_rev]; - - if (ifq != NULL) - fr_movequeue(tqe, tqe->tqe_ifq, ifq); - - is->is_pkts[i]++; - is->is_bytes[i] += fin->fin_plen; - MUTEX_EXIT(&is->is_lock); - -#ifdef IPFILTER_SYNC - if (is->is_flags & IS_STATESYNC) - ipfsync_update(SMC_STATE, fin, is->is_sync); -#endif - - ATOMIC_INCL(ips_stats.iss_hits); - - fin->fin_fr = is->is_rule; - - /* - * If this packet is a fragment and the rule says to track fragments, - * then create a new fragment cache entry. - */ - pass = is->is_pass; - if ((fin->fin_flx & FI_FRAG) && FR_ISPASS(pass)) - (void) fr_newfrag(fin, pass ^ FR_KEEPSTATE); -} - - -/* ------------------------------------------------------------------------ */ -/* Function: fr_checkstate */ +/* Function: ipf_state_check */ /* Returns: frentry_t* - NULL == search failed, */ /* else pointer to rule for matching state */ -/* Parameters: ifp(I) - pointer to interface */ +/* Parameters: fin(I) - pointer to packet information */ /* passp(I) - pointer to filtering result flags */ /* */ /* Check if a packet is associated with an entry in the state table. */ /* ------------------------------------------------------------------------ */ -frentry_t *fr_checkstate(fin, passp) -fr_info_t *fin; -u_32_t *passp; +frentry_t * +ipf_state_check(fin, passp) + fr_info_t *fin; + u_32_t *passp; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_state_softc_t *softs = softc->ipf_state_soft; + ipftqent_t *tqe; ipstate_t *is; frentry_t *fr; tcphdr_t *tcp; ipftq_t *ifq; u_int pass; + int inout; - if (fr_state_lock || (ips_list == NULL) || - (fin->fin_flx & (FI_SHORT|FI_STATE|FI_FRAGBODY|FI_BAD))) + if (softs->ipf_state_lock || (softs->ipf_state_list == NULL)) return NULL; - is = NULL; + if (fin->fin_flx & (FI_SHORT|FI_FRAGBODY|FI_BAD)) { + SBUMPD(ipf_state_stats, iss_check_bad); + return NULL; + } + if ((fin->fin_flx & FI_TCPUDP) || (fin->fin_fi.fi_p == IPPROTO_ICMP) #ifdef USE_INET6 @@ -2475,13 +3326,12 @@ u_32_t *passp; else tcp = NULL; + ifq = NULL; /* * Search the hash table for matching packet header info. */ - ifq = NULL; - is = fin->fin_state; - if (is == NULL) - is = fr_stlookup(fin, tcp, &ifq); + is = ipf_state_lookup(fin, tcp, &ifq); + switch (fin->fin_p) { #ifdef USE_INET6 @@ -2489,9 +3339,7 @@ u_32_t *passp; if (is != NULL) break; if (fin->fin_v == 6) { - is = fr_checkicmp6matchingstate(fin); - if (is != NULL) - goto matched; + is = ipf_checkicmp6matchingstate(fin); } break; #endif @@ -2502,58 +3350,92 @@ u_32_t *passp; * No matching icmp state entry. Perhaps this is a * response to another state entry. */ - is = fr_checkicmpmatchingstate(fin); - if (is != NULL) - goto matched; + is = ipf_checkicmpmatchingstate(fin); break; + case IPPROTO_TCP : if (is == NULL) break; if (is->is_pass & FR_NEWISN) { if (fin->fin_out == 0) - fr_fixinisn(fin, is); + ipf_fixinisn(fin, is); else if (fin->fin_out == 1) - fr_fixoutisn(fin, is); + ipf_fixoutisn(fin, is); } break; default : if (fin->fin_rev) - ifq = &ips_udpacktq; + ifq = &softs->ipf_state_udpacktq; else - ifq = &ips_udptq; + ifq = &softs->ipf_state_udptq; break; } if (is == NULL) { - ATOMIC_INCL(ips_stats.iss_miss); + SBUMP(ipf_state_stats.iss_check_miss); return NULL; } -matched: fr = is->is_rule; if (fr != NULL) { if ((fin->fin_out == 0) && (fr->fr_nattag.ipt_num[0] != 0)) { - if (fin->fin_nattag == NULL) + if (fin->fin_nattag == NULL) { + RWLOCK_EXIT(&softc->ipf_state); + SBUMPD(ipf_state_stats, iss_check_notag); return NULL; - if (fr_matchtag(&fr->fr_nattag, fin->fin_nattag) != 0) + } + if (ipf_matchtag(&fr->fr_nattag, fin->fin_nattag)!=0) { + RWLOCK_EXIT(&softc->ipf_state); + SBUMPD(ipf_state_stats, iss_check_nattag); return NULL; + } } - (void) strncpy(fin->fin_group, fr->fr_group, FR_GROUPLEN); + (void) strncpy(fin->fin_group, FR_NAME(fr, fr_group), + FR_GROUPLEN); fin->fin_icode = fr->fr_icode; } fin->fin_rule = is->is_rulen; - pass = is->is_pass; - fr_updatestate(fin, is, ifq); - if (fin->fin_out == 1) - fin->fin_nat = is->is_nat[fin->fin_rev]; + fin->fin_fr = fr; + + /* + * If this packet is a fragment and the rule says to track fragments, + * then create a new fragment cache entry. + */ + if ((fin->fin_flx & FI_FRAG) && FR_ISPASS(is->is_pass)) + (void) ipf_frag_new(softc, fin, is->is_pass); + + /* + * For TCP packets, ifq == NULL. For all others, check if this new + * queue is different to the last one it was on and move it if so. + */ + tqe = &is->is_sti; + if ((tqe->tqe_flags & TQE_RULEBASED) != 0) + ifq = is->is_tqehead[fin->fin_rev]; - fin->fin_state = is; - is->is_touched = fr_ticks; MUTEX_ENTER(&is->is_lock); - is->is_ref++; + + if (ifq != NULL) + ipf_movequeue(softc->ipf_ticks, tqe, tqe->tqe_ifq, ifq); + + inout = (fin->fin_rev << 1) + fin->fin_out; + is->is_pkts[inout]++; + is->is_bytes[inout] += fin->fin_plen; + fin->fin_pktnum = is->is_pkts[inout] + is->is_icmppkts[inout]; + MUTEX_EXIT(&is->is_lock); - RWLOCK_EXIT(&ipf_state); + + pass = is->is_pass; + + if (is->is_flags & IS_STATESYNC) + ipf_sync_update(softc, SMC_STATE, fin, is->is_sync); + + RWLOCK_EXIT(&softc->ipf_state); + + SBUMP(ipf_state_stats.iss_hits); + + fin->fin_dif = &is->is_dif; + fin->fin_tif = &is->is_tifs[fin->fin_rev]; fin->fin_flx |= FI_STATE; if ((pass & FR_LOGFIRST) != 0) pass &= ~(FR_LOGFIRST|FR_LOG); @@ -2563,17 +3445,18 @@ matched: /* ------------------------------------------------------------------------ */ -/* Function: fr_fixoutisn */ +/* Function: ipf_fixoutisn */ /* Returns: Nil */ -/* Parameters: fin(I) - pointer to packet information */ +/* Parameters: fin(I) - pointer to packet information */ /* is(I) - pointer to master state structure */ /* */ /* Called only for outbound packets, adjusts the sequence number and the */ /* TCP checksum to match that change. */ /* ------------------------------------------------------------------------ */ -static void fr_fixoutisn(fin, is) -fr_info_t *fin; -ipstate_t *is; +static void +ipf_fixoutisn(fin, is) + fr_info_t *fin; + ipstate_t *is; { tcphdr_t *tcp; int rev; @@ -2582,26 +3465,26 @@ ipstate_t *is; tcp = fin->fin_dp; rev = fin->fin_rev; if ((is->is_flags & IS_ISNSYN) != 0) { - if (rev == 0) { + if ((rev == 0) && (fin->fin_cksum < FI_CK_L4PART)) { seq = ntohl(tcp->th_seq); seq += is->is_isninc[0]; tcp->th_seq = htonl(seq); - fix_outcksum(fin, &tcp->th_sum, is->is_sumd[0]); + ipf_fix_outcksum(0, &tcp->th_sum, is->is_sumd[0], 0); } } if ((is->is_flags & IS_ISNACK) != 0) { - if (rev == 1) { + if ((rev == 1) && (fin->fin_cksum < FI_CK_L4PART)) { seq = ntohl(tcp->th_seq); seq += is->is_isninc[1]; tcp->th_seq = htonl(seq); - fix_outcksum(fin, &tcp->th_sum, is->is_sumd[1]); + ipf_fix_outcksum(0, &tcp->th_sum, is->is_sumd[1], 0); } } } /* ------------------------------------------------------------------------ */ -/* Function: fr_fixinisn */ +/* Function: ipf_fixinisn */ /* Returns: Nil */ /* Parameters: fin(I) - pointer to packet information */ /* is(I) - pointer to master state structure */ @@ -2609,9 +3492,10 @@ ipstate_t *is; /* Called only for inbound packets, adjusts the acknowledge number and the */ /* TCP checksum to match that change. */ /* ------------------------------------------------------------------------ */ -static void fr_fixinisn(fin, is) -fr_info_t *fin; -ipstate_t *is; +static void +ipf_fixinisn(fin, is) + fr_info_t *fin; + ipstate_t *is; { tcphdr_t *tcp; int rev; @@ -2620,28 +3504,29 @@ ipstate_t *is; tcp = fin->fin_dp; rev = fin->fin_rev; if ((is->is_flags & IS_ISNSYN) != 0) { - if (rev == 1) { + if ((rev == 1) && (fin->fin_cksum < FI_CK_L4PART)) { ack = ntohl(tcp->th_ack); ack -= is->is_isninc[0]; tcp->th_ack = htonl(ack); - fix_incksum(fin, &tcp->th_sum, is->is_sumd[0]); + ipf_fix_incksum(0, &tcp->th_sum, is->is_sumd[0], 0); } } if ((is->is_flags & IS_ISNACK) != 0) { - if (rev == 0) { + if ((rev == 0) && (fin->fin_cksum < FI_CK_L4PART)) { ack = ntohl(tcp->th_ack); ack -= is->is_isninc[1]; tcp->th_ack = htonl(ack); - fix_incksum(fin, &tcp->th_sum, is->is_sumd[1]); + ipf_fix_incksum(0, &tcp->th_sum, is->is_sumd[1], 0); } } } /* ------------------------------------------------------------------------ */ -/* Function: fr_statesync */ +/* Function: ipf_state_sync */ /* Returns: Nil */ -/* Parameters: ifp(I) - pointer to interface */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* ifp(I) - pointer to interface */ /* */ /* Walk through all state entries and if an interface pointer match is */ /* found then look it up again, based on its name in case the pointer has */ @@ -2650,40 +3535,45 @@ ipstate_t *is; /* If ifp is passed in as being non-null then we are only doing updates for */ /* existing, matching, uses of it. */ /* ------------------------------------------------------------------------ */ -void fr_statesync(ifp) -void *ifp; +void +ipf_state_sync(softc, ifp) + ipf_main_softc_t *softc; + void *ifp; { + ipf_state_softc_t *softs = softc->ipf_state_soft; ipstate_t *is; int i; - if (fr_running <= 0) + if (softc->ipf_running <= 0) return; - WRITE_ENTER(&ipf_state); + WRITE_ENTER(&softc->ipf_state); - if (fr_running <= 0) { - RWLOCK_EXIT(&ipf_state); + if (softc->ipf_running <= 0) { + RWLOCK_EXIT(&softc->ipf_state); return; } - for (is = ips_list; is; is = is->is_next) { + for (is = softs->ipf_state_list; is; is = is->is_next) { /* * Look up all the interface names in the state entry. */ for (i = 0; i < 4; i++) { if (ifp == NULL || ifp == is->is_ifp[i]) - is->is_ifp[i] = fr_resolvenic(is->is_ifname[i], + is->is_ifp[i] = ipf_resolvenic(softc, + is->is_ifname[i], is->is_v); } } - RWLOCK_EXIT(&ipf_state); + RWLOCK_EXIT(&softc->ipf_state); } /* ------------------------------------------------------------------------ */ -/* Function: fr_delstate */ -/* Returns: Nil */ -/* Parameters: is(I) - pointer to state structure to delete */ +/* Function: ipf_state_del */ +/* Returns: int - 0 = deleted, else refernce count on active struct */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* is(I) - pointer to state structure to delete */ /* why(I) - if not 0, log reason why it was deleted */ /* Write Locks: ipf_state */ /* */ @@ -2691,47 +3581,41 @@ void *ifp; /* and timeout queue lists. Make adjustments to hash table statistics and */ /* global counters as required. */ /* ------------------------------------------------------------------------ */ -static void fr_delstate(is, why) -ipstate_t *is; -int why; +static int +ipf_state_del(softc, is, why) + ipf_main_softc_t *softc; + ipstate_t *is; + int why; { - - ASSERT(rw_read_locked(&ipf_state.ipf_lk) == 0); + ipf_state_softc_t *softs = softc->ipf_state_soft; + int orphan = 1; + frentry_t *fr; /* * Since we want to delete this, remove it from the state table, * where it can be found & used, first. */ - if (is->is_pnext != NULL) { - *is->is_pnext = is->is_next; - - if (is->is_next != NULL) - is->is_next->is_pnext = is->is_pnext; - - is->is_pnext = NULL; - is->is_next = NULL; - } - if (is->is_phnext != NULL) { *is->is_phnext = is->is_hnext; if (is->is_hnext != NULL) is->is_hnext->is_phnext = is->is_phnext; - if (ips_table[is->is_hv] == NULL) - ips_stats.iss_inuse--; - ips_stats.iss_bucketlen[is->is_hv]--; + if (softs->ipf_state_table[is->is_hv] == NULL) + softs->ipf_state_stats.iss_inuse--; + softs->ipf_state_stats.iss_bucketlen[is->is_hv]--; is->is_phnext = NULL; is->is_hnext = NULL; + orphan = 0; } /* - * Because ips_stats.iss_wild is a count of entries in the state + * Because ipf_state_stats.iss_wild is a count of entries in the state * table that have wildcard flags set, only decerement it once * and do it here. */ if (is->is_flags & (SI_WILDP|SI_WILDA)) { if (!(is->is_flags & SI_CLONED)) { - ATOMIC_DECL(ips_stats.iss_wild); + ATOMIC_DECL(softs->ipf_state_stats.iss_wild); } is->is_flags &= ~(SI_WILDP|SI_WILDA); } @@ -2739,117 +3623,165 @@ int why; /* * Next, remove it from the timeout queue it is in. */ - fr_deletequeueentry(&is->is_sti); + if (is->is_sti.tqe_ifq != NULL) + ipf_deletequeueentry(&is->is_sti); + /* + * If it is still in use by something else, do not go any further, + * but note that at this point it is now an orphan. How can this + * be? ipf_state_flush() calls ipf_delete() directly because it wants + * to empty the table out and if something has a hold on a state + * entry (such as ipfstat), it'll do the deref path that'll bring + * us back here to do the real delete & free. + */ + MUTEX_ENTER(&is->is_lock); if (is->is_me != NULL) { *is->is_me = NULL; is->is_me = NULL; + is->is_ref--; } + if (is->is_ref > 1) { + int refs; - /* - * If it is still in use by something else, do not go any further, - * but note that at this point it is now an orphan. - */ - is->is_ref--; - if (is->is_ref > 0) - return; + is->is_ref--; + refs = is->is_ref; + MUTEX_EXIT(&is->is_lock); + if (!orphan) + softs->ipf_state_stats.iss_orphan++; + return refs; + } + MUTEX_EXIT(&is->is_lock); + + fr = is->is_rule; + is->is_rule = NULL; + if (fr != NULL) { + if (fr->fr_srctrack.ht_max_nodes != 0) { + (void) ipf_ht_node_del(&fr->fr_srctrack, + is->is_family, &is->is_src); + } + } + + is->is_ref = 0; if (is->is_tqehead[0] != NULL) { - if (fr_deletetimeoutqueue(is->is_tqehead[0]) == 0) - fr_freetimeoutqueue(is->is_tqehead[0]); + if (ipf_deletetimeoutqueue(is->is_tqehead[0]) == 0) + ipf_freetimeoutqueue(softc, is->is_tqehead[0]); } if (is->is_tqehead[1] != NULL) { - if (fr_deletetimeoutqueue(is->is_tqehead[1]) == 0) - fr_freetimeoutqueue(is->is_tqehead[1]); + if (ipf_deletetimeoutqueue(is->is_tqehead[1]) == 0) + ipf_freetimeoutqueue(softc, is->is_tqehead[1]); } -#ifdef IPFILTER_SYNC if (is->is_sync) - ipfsync_del(is->is_sync); -#endif -#ifdef IPFILTER_SCAN - (void) ipsc_detachis(is); -#endif + ipf_sync_del_state(softc->ipf_sync_soft, is->is_sync); - if (ipstate_logging != 0 && why != 0) - ipstate_log(is, why); + /* + * Now remove it from the linked list of known states + */ + if (is->is_pnext != NULL) { + *is->is_pnext = is->is_next; - if (is->is_rule != NULL) { - is->is_rule->fr_statecnt--; - (void)fr_derefrule(&is->is_rule); + if (is->is_next != NULL) + is->is_next->is_pnext = is->is_pnext; + + is->is_pnext = NULL; + is->is_next = NULL; } + if (softs->ipf_state_logging != 0 && why != 0) + ipf_state_log(softc, is, why); + + if (is->is_p == IPPROTO_TCP) + softs->ipf_state_stats.iss_fin++; + else + softs->ipf_state_stats.iss_expire++; + if (orphan) + softs->ipf_state_stats.iss_orphan--; + + if (fr != NULL) { + fr->fr_statecnt--; + (void) ipf_derefrule(softc, &fr); + } + + softs->ipf_state_stats.iss_active_proto[is->is_p]--; + MUTEX_DESTROY(&is->is_lock); KFREE(is); - ips_num--; + softs->ipf_state_stats.iss_active--; + + return 0; } /* ------------------------------------------------------------------------ */ -/* Function: fr_timeoutstate */ +/* Function: ipf_state_expire */ /* Returns: Nil */ -/* Parameters: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ /* */ /* Slowly expire held state for thingslike UDP and ICMP. The algorithm */ /* used here is to keep the queue sorted with the oldest things at the top */ /* and the youngest at the bottom. So if the top one doesn't need to be */ /* expired then neither will any under it. */ /* ------------------------------------------------------------------------ */ -void fr_timeoutstate() +void +ipf_state_expire(softc) + ipf_main_softc_t *softc; { + ipf_state_softc_t *softs = softc->ipf_state_soft; ipftq_t *ifq, *ifqnext; ipftqent_t *tqe, *tqn; ipstate_t *is; -#if defined(USE_SPL) && defined(_KERNEL) - int s; -#endif + SPL_INT(s); SPL_NET(s); - WRITE_ENTER(&ipf_state); - for (ifq = ips_tqtqb; ifq != NULL; ifq = ifq->ifq_next) + WRITE_ENTER(&softc->ipf_state); + for (ifq = softs->ipf_state_tcptq; ifq != NULL; ifq = ifq->ifq_next) for (tqn = ifq->ifq_head; ((tqe = tqn) != NULL); ) { - if (tqe->tqe_die > fr_ticks) + if (tqe->tqe_die > softc->ipf_ticks) break; tqn = tqe->tqe_next; is = tqe->tqe_parent; - fr_delstate(is, ISL_EXPIRE); + ipf_state_del(softc, is, ISL_EXPIRE); } - for (ifq = ips_utqe; ifq != NULL; ifq = ifqnext) { + for (ifq = softs->ipf_state_usertq; ifq != NULL; ifq = ifqnext) { ifqnext = ifq->ifq_next; for (tqn = ifq->ifq_head; ((tqe = tqn) != NULL); ) { - if (tqe->tqe_die > fr_ticks) + if (tqe->tqe_die > softc->ipf_ticks) break; tqn = tqe->tqe_next; is = tqe->tqe_parent; - fr_delstate(is, ISL_EXPIRE); + ipf_state_del(softc, is, ISL_EXPIRE); } } - for (ifq = ips_utqe; ifq != NULL; ifq = ifqnext) { + for (ifq = softs->ipf_state_usertq; ifq != NULL; ifq = ifqnext) { ifqnext = ifq->ifq_next; if (((ifq->ifq_flags & IFQF_DELETE) != 0) && (ifq->ifq_ref == 0)) { - fr_freetimeoutqueue(ifq); + ipf_freetimeoutqueue(softc, ifq); } } - if (fr_state_doflush) { - (void) fr_state_flush(2, 0); - fr_state_doflush = 0; + if (softs->ipf_state_doflush) { + (void) ipf_state_flush(softc, 2, 0); + softs->ipf_state_doflush = 0; + softs->ipf_state_wm_last = softc->ipf_ticks; } - RWLOCK_EXIT(&ipf_state); + RWLOCK_EXIT(&softc->ipf_state); SPL_X(s); } /* ------------------------------------------------------------------------ */ -/* Function: fr_state_flush */ +/* Function: ipf_state_flush */ /* Returns: int - 0 == success, -1 == failure */ -/* Parameters: Nil */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* which(I) - which flush action to perform */ +/* proto(I) - which protocol to flush (0 == ALL) */ /* Write Locks: ipf_state */ /* */ /* Flush state tables. Three actions currently defined: */ @@ -2863,54 +3795,130 @@ void fr_timeoutstate() /* If that too fails, then work backwards in 30 second intervals */ /* for the last 30 minutes to at worst 30 seconds idle. */ /* ------------------------------------------------------------------------ */ -static int fr_state_flush(which, proto) -int which, proto; +int +ipf_state_flush(softc, which, proto) + ipf_main_softc_t *softc; + int which, proto; { - ipftq_t *ifq, *ifqnext; + ipf_state_softc_t *softs = softc->ipf_state_soft; ipftqent_t *tqe, *tqn; ipstate_t *is, **isp; - int delete, removed; - long try, maxtick; - u_long interval; -#if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL) - int s; -#endif + ipftq_t *ifq; + int removed; + SPL_INT(s); removed = 0; SPL_NET(s); - for (isp = &ips_list; ((is = *isp) != NULL); ) { - delete = 0; - if ((proto != 0) && (is->is_v != proto)) { - isp = &is->is_next; - continue; + switch (which) + { + case 0 : + SBUMP(ipf_state_stats.iss_flush_all); + /* + * Style 0 flush removes everything... + */ + for (isp = &softs->ipf_state_list; ((is = *isp) != NULL); ) { + if ((proto != 0) && (is->is_v != proto)) { + isp = &is->is_next; + continue; + } + if (ipf_state_del(softc, is, ISL_FLUSH) == 0) + removed++; + else + isp = &is->is_next; } + break; - switch (which) - { - case 0 : - delete = 1; - break; - case 1 : - case 2 : - if (is->is_p != IPPROTO_TCP) - break; - if ((is->is_state[0] != IPF_TCPS_ESTABLISHED) || - (is->is_state[1] != IPF_TCPS_ESTABLISHED)) - delete = 1; - break; + case 1 : + SBUMP(ipf_state_stats.iss_flush_closing); + /* + * Since we're only interested in things that are closing, + * we can start with the appropriate timeout queue. + */ + for (ifq = softs->ipf_state_tcptq + IPF_TCPS_CLOSE_WAIT; + ifq != NULL; ifq = ifq->ifq_next) { + + for (tqn = ifq->ifq_head; ((tqe = tqn) != NULL); ) { + tqn = tqe->tqe_next; + is = tqe->tqe_parent; + if (is->is_p != IPPROTO_TCP) + break; + if (ipf_state_del(softc, is, ISL_FLUSH) == 0) + removed++; + } } - if (delete) { - if (is->is_p == IPPROTO_TCP) - ips_stats.iss_fin++; - else - ips_stats.iss_expire++; - fr_delstate(is, ISL_FLUSH); - removed++; - } else + /* + * Also need to look through the user defined queues. + */ + for (ifq = softs->ipf_state_usertq; ifq != NULL; + ifq = ifq->ifq_next) { + for (tqn = ifq->ifq_head; ((tqe = tqn) != NULL); ) { + tqn = tqe->tqe_next; + is = tqe->tqe_parent; + if (is->is_p != IPPROTO_TCP) + continue; + + if ((is->is_state[0] > IPF_TCPS_ESTABLISHED) && + (is->is_state[1] > IPF_TCPS_ESTABLISHED)) { + if (ipf_state_del(softc, is, + ISL_FLUSH) == 0) + removed++; + } + } + } + break; + + case 2 : + break; + + /* + * Args 5-11 correspond to flushing those particular states + * for TCP connections. + */ + case IPF_TCPS_CLOSE_WAIT : + case IPF_TCPS_FIN_WAIT_1 : + case IPF_TCPS_CLOSING : + case IPF_TCPS_LAST_ACK : + case IPF_TCPS_FIN_WAIT_2 : + case IPF_TCPS_TIME_WAIT : + case IPF_TCPS_CLOSED : + SBUMP(ipf_state_stats.iss_flush_queue); + tqn = softs->ipf_state_tcptq[which].ifq_head; + while (tqn != NULL) { + tqe = tqn; + tqn = tqe->tqe_next; + is = tqe->tqe_parent; + if (ipf_state_del(softc, is, ISL_FLUSH) == 0) + removed++; + } + break; + + default : + if (which < 30) + break; + + SBUMP(ipf_state_stats.iss_flush_state); + /* + * Take a large arbitrary number to mean the number of seconds + * for which which consider to be the maximum value we'll allow + * the expiration to be. + */ + which = IPF_TTLVAL(which); + for (isp = &softs->ipf_state_list; ((is = *isp) != NULL); ) { + if ((proto == 0) || (is->is_v == proto)) { + if (softc->ipf_ticks - is->is_touched > which) { + if (ipf_state_del(softc, is, + ISL_FLUSH) == 0) { + removed++; + continue; + } + } + } isp = &is->is_next; + } + break; } if (which != 2) { @@ -2918,6 +3926,7 @@ int which, proto; return removed; } + SBUMP(ipf_state_stats.iss_flush_timeout); /* * Asked to remove inactive entries because the table is full, try * again, 3 times, if first attempt failed with a different criteria @@ -2925,85 +3934,50 @@ int which, proto; * Another alternative is to implement random drop and drop N entries * at random until N have been freed up. */ - if (fr_ticks - ips_last_force_flush < IPF_TTLVAL(5)) - goto force_flush_skipped; - ips_last_force_flush = fr_ticks; - - if (fr_ticks > IPF_TTLVAL(43200)) - interval = IPF_TTLVAL(43200); - else if (fr_ticks > IPF_TTLVAL(1800)) - interval = IPF_TTLVAL(1800); - else if (fr_ticks > IPF_TTLVAL(30)) - interval = IPF_TTLVAL(30); - else - interval = IPF_TTLVAL(10); - try = fr_ticks - (fr_ticks - interval); - if (try < 0) - goto force_flush_skipped; - - while (removed == 0) { - maxtick = fr_ticks - interval; - if (maxtick < 0) - break; - - while (try < maxtick) { - for (ifq = ips_tqtqb; ifq != NULL; - ifq = ifq->ifq_next) { - for (tqn = ifq->ifq_head; - ((tqe = tqn) != NULL); ) { - if (tqe->tqe_die > try) - break; - tqn = tqe->tqe_next; - is = tqe->tqe_parent; - fr_delstate(is, ISL_EXPIRE); - removed++; - } - } - - for (ifq = ips_utqe; ifq != NULL; ifq = ifqnext) { - ifqnext = ifq->ifq_next; - - for (tqn = ifq->ifq_head; - ((tqe = tqn) != NULL); ) { - if (tqe->tqe_die > try) - break; - tqn = tqe->tqe_next; - is = tqe->tqe_parent; - fr_delstate(is, ISL_EXPIRE); - removed++; - } - } - if (try + interval > maxtick) - break; - try += interval; - } - - if (removed == 0) { - if (interval == IPF_TTLVAL(43200)) { - interval = IPF_TTLVAL(1800); - } else if (interval == IPF_TTLVAL(1800)) { - interval = IPF_TTLVAL(30); - } else if (interval == IPF_TTLVAL(30)) { - interval = IPF_TTLVAL(10); - } else { - break; - } - } + if (softc->ipf_ticks - softs->ipf_state_wm_last > + softs->ipf_state_wm_freq) { + removed = ipf_queueflush(softc, ipf_state_flush_entry, + softs->ipf_state_tcptq, + softs->ipf_state_usertq, + &softs->ipf_state_stats.iss_active, + softs->ipf_state_size, + softs->ipf_state_wm_low); + softs->ipf_state_wm_last = softc->ipf_ticks; } -force_flush_skipped: + SPL_X(s); return removed; } +/* ------------------------------------------------------------------------ */ +/* Function: ipf_state_flush_entry */ +/* Returns: int - 0 = entry deleted, else not deleted */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* entry(I) - pointer to state structure to delete */ +/* Write Locks: ipf_state */ +/* */ +/* This function is a stepping stone between ipf_queueflush() and */ +/* ipf_state_del(). It is used so we can provide a uniform interface via */ +/* the ipf_queueflush() function. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_state_flush_entry(softc, entry) + ipf_main_softc_t *softc; + void *entry; +{ + return ipf_state_del(softc, entry, ISL_FLUSH); +} + /* ------------------------------------------------------------------------ */ -/* Function: fr_tcp_age */ +/* Function: ipf_tcp_age */ /* Returns: int - 1 == state transition made, 0 == no change (rejected) */ -/* Parameters: tq(I) - pointer to timeout queue information */ +/* Parameters: tqe(I) - pointer to timeout queue information */ /* fin(I) - pointer to packet information */ /* tqtab(I) - TCP timeout queue table this is in */ /* flags(I) - flags from state/NAT entry */ +/* ok(I) - can we advance state */ /* */ /* Rewritten by Arjan de Vet <Arjan.deVet@adv.iae.nl>, 2000-07-29: */ /* */ @@ -3015,7 +3989,7 @@ force_flush_skipped: /* */ /* - store the state of the source in state[0] such that ipfstat */ /* displays the state as source/dest instead of dest/source; the calls */ -/* to fr_tcp_age have been changed accordingly. */ +/* to ipf_tcp_age have been changed accordingly. */ /* */ /* Internal Parameters: */ /* */ @@ -3025,14 +3999,35 @@ force_flush_skipped: /* dir == 0 : a packet from source to dest */ /* dir == 1 : a packet from dest to source */ /* */ +/* A typical procession for a connection is as follows: */ +/* */ +/* +--------------+-------------------+ */ +/* | Side '0' | Side '1' | */ +/* +--------------+-------------------+ */ +/* | 0 -> 1 (SYN) | | */ +/* | | 0 -> 2 (SYN-ACK) | */ +/* | 1 -> 3 (ACK) | | */ +/* | | 2 -> 4 (ACK-PUSH) | */ +/* | 3 -> 4 (ACK) | | */ +/* | ... | ... | */ +/* | | 4 -> 6 (FIN-ACK) | */ +/* | 4 -> 5 (ACK) | | */ +/* | | 6 -> 6 (ACK-PUSH) | */ +/* | 5 -> 5 (ACK) | | */ +/* | 5 -> 8 (FIN) | | */ +/* | | 6 -> 10 (ACK) | */ +/* +--------------+-------------------+ */ +/* */ /* Locking: it is assumed that the parent of the tqe structure is locked. */ /* ------------------------------------------------------------------------ */ -int fr_tcp_age(tqe, fin, tqtab, flags) -ipftqent_t *tqe; -fr_info_t *fin; -ipftq_t *tqtab; -int flags; +int +ipf_tcp_age(tqe, fin, tqtab, flags, ok) + ipftqent_t *tqe; + fr_info_t *fin; + ipftq_t *tqtab; + int flags, ok; { + ipf_main_softc_t *softc = fin->fin_main_soft; int dlen, ostate, nstate, rval, dir; u_char tcpflags; tcphdr_t *tcp; @@ -3042,30 +4037,33 @@ int flags; rval = 0; dir = fin->fin_rev; tcpflags = tcp->th_flags; - dlen = fin->fin_plen - fin->fin_hlen - (TCP_OFF(tcp) << 2); + dlen = fin->fin_dlen - (TCP_OFF(tcp) << 2); + ostate = tqe->tqe_state[1 - dir]; + nstate = tqe->tqe_state[dir]; if (tcpflags & TH_RST) { if (!(tcpflags & TH_PUSH) && !dlen) nstate = IPF_TCPS_CLOSED; else nstate = IPF_TCPS_CLOSE_WAIT; + + if (ostate <= IPF_TCPS_ESTABLISHED) { + tqe->tqe_state[1 - dir] = IPF_TCPS_CLOSE_WAIT; + } rval = 1; } else { - ostate = tqe->tqe_state[1 - dir]; - nstate = tqe->tqe_state[dir]; - switch (nstate) { - case IPF_TCPS_CLOSED: /* 0 */ + case IPF_TCPS_LISTEN: /* 0 */ if ((tcpflags & TH_OPENING) == TH_OPENING) { /* * 'dir' received an S and sends SA in - * response, CLOSED -> SYN_RECEIVED + * response, LISTEN -> SYN_RECEIVED */ nstate = IPF_TCPS_SYN_RECEIVED; rval = 1; } else if ((tcpflags & TH_OPENING) == TH_SYN) { - /* 'dir' sent S, CLOSED -> SYN_SENT */ + /* 'dir' sent S, LISTEN -> SYN_SENT */ nstate = IPF_TCPS_SYN_SENT; rval = 1; } @@ -3084,7 +4082,7 @@ int flags; */ switch (ostate) { - case IPF_TCPS_CLOSED : + case IPF_TCPS_LISTEN : case IPF_TCPS_SYN_RECEIVED : nstate = IPF_TCPS_HALF_ESTAB; rval = 1; @@ -3105,15 +4103,11 @@ int flags; */ break; - case IPF_TCPS_LISTEN: /* 1 */ - /* NOT USED */ - break; - - case IPF_TCPS_SYN_SENT: /* 2 */ + case IPF_TCPS_SYN_SENT: /* 1 */ if ((tcpflags & ~(TH_ECN|TH_CWR)) == TH_SYN) { /* * A retransmitted SYN packet. We do not reset - * the timeout here to fr_tcptimeout because a + * the timeout here to ipf_tcptimeout because a * connection connect timeout does not renew * after every packet that is sent. We need to * set rval so as to indicate the packet has @@ -3150,7 +4144,7 @@ int flags; } break; - case IPF_TCPS_SYN_RECEIVED: /* 3 */ + case IPF_TCPS_SYN_RECEIVED: /* 2 */ if ((tcpflags & (TH_SYN|TH_FIN|TH_ACK)) == TH_ACK) { /* * we see an A from 'dir' which was in @@ -3179,17 +4173,38 @@ int flags; } break; - case IPF_TCPS_HALF_ESTAB: /* 4 */ - if (ostate >= IPF_TCPS_HALF_ESTAB) { - if ((tcpflags & TH_ACKMASK) == TH_ACK) { + case IPF_TCPS_HALF_ESTAB: /* 3 */ + if (tcpflags & TH_FIN) { + nstate = IPF_TCPS_FIN_WAIT_1; + rval = 1; + } else if ((tcpflags & TH_ACKMASK) == TH_ACK) { + /* + * If we've picked up a connection in mid + * flight, we could be looking at a follow on + * packet from the same direction as the one + * that created this state. Recognise it but + * do not advance the entire connection's + * state. + */ + switch (ostate) + { + case IPF_TCPS_LISTEN : + case IPF_TCPS_SYN_SENT : + case IPF_TCPS_SYN_RECEIVED : + rval = 1; + break; + case IPF_TCPS_HALF_ESTAB : + case IPF_TCPS_ESTABLISHED : nstate = IPF_TCPS_ESTABLISHED; rval = 1; + break; + default : + break; } } - break; - case IPF_TCPS_ESTABLISHED: /* 5 */ + case IPF_TCPS_ESTABLISHED: /* 4 */ rval = 1; if (tcpflags & TH_FIN) { /* @@ -3197,7 +4212,11 @@ int flags; * this gives us a half-closed connection; * ESTABLISHED -> FIN_WAIT_1 */ - nstate = IPF_TCPS_FIN_WAIT_1; + if (ostate == IPF_TCPS_FIN_WAIT_1) { + nstate = IPF_TCPS_CLOSING; + } else { + nstate = IPF_TCPS_FIN_WAIT_1; + } } else if (tcpflags & TH_ACK) { /* * an ACK, should we exclude other flags here? @@ -3222,7 +4241,7 @@ int flags; } break; - case IPF_TCPS_CLOSE_WAIT: /* 6 */ + case IPF_TCPS_CLOSE_WAIT: /* 5 */ rval = 1; if (tcpflags & TH_FIN) { /* @@ -3240,7 +4259,7 @@ int flags; } break; - case IPF_TCPS_FIN_WAIT_1: /* 7 */ + case IPF_TCPS_FIN_WAIT_1: /* 6 */ rval = 1; if ((tcpflags & TH_ACK) && ostate > IPF_TCPS_CLOSE_WAIT) { @@ -3256,7 +4275,7 @@ int flags; * the FIN packet here? does the window code * guarantee that? */ - nstate = IPF_TCPS_TIME_WAIT; + nstate = IPF_TCPS_LAST_ACK; } else { /* * we closed our side of the connection @@ -3268,58 +4287,45 @@ int flags; } break; - case IPF_TCPS_CLOSING: /* 8 */ - /* NOT USED */ + case IPF_TCPS_CLOSING: /* 7 */ + if ((tcpflags & (TH_FIN|TH_ACK)) == TH_ACK) { + nstate = IPF_TCPS_TIME_WAIT; + } + rval = 1; break; - case IPF_TCPS_LAST_ACK: /* 9 */ + case IPF_TCPS_LAST_ACK: /* 8 */ if (tcpflags & TH_ACK) { - if ((tcpflags & TH_PUSH) || dlen) - /* - * there is still data to be delivered, - * reset timeout - */ - rval = 1; - else - rval = 2; + rval = 1; } /* - * we cannot detect when we go out of LAST_ACK state to - * CLOSED because that is based on the reception of ACK - * packets; ipfilter can only detect that a packet - * has been sent by a host + * we cannot detect when we go out of LAST_ACK state + * to CLOSED because that is based on the reception + * of ACK packets; ipfilter can only detect that a + * packet has been sent by a host */ break; - case IPF_TCPS_FIN_WAIT_2: /* 10 */ - rval = 1; - if ((tcpflags & TH_OPENING) == TH_OPENING) - nstate = IPF_TCPS_SYN_RECEIVED; - else if (tcpflags & TH_SYN) - nstate = IPF_TCPS_SYN_SENT; + case IPF_TCPS_FIN_WAIT_2: /* 9 */ + /* NOT USED */ break; - case IPF_TCPS_TIME_WAIT: /* 11 */ + case IPF_TCPS_TIME_WAIT: /* 10 */ /* we're in 2MSL timeout now */ - rval = 1; + if (ostate == IPF_TCPS_LAST_ACK) { + nstate = IPF_TCPS_CLOSED; + rval = 1; + } else { + rval = 2; + } + break; + + case IPF_TCPS_CLOSED: /* 11 */ + rval = 2; break; default : -#if defined(_KERNEL) -# if SOLARIS - cmn_err(CE_NOTE, - "tcp %lx flags %x si %lx nstate %d ostate %d\n", - (u_long)tcp, tcpflags, (u_long)tqe, - nstate, ostate); -# else - printf("tcp %lx flags %x si %lx nstate %d ostate %d\n", - (u_long)tcp, tcpflags, (u_long)tqe, - nstate, ostate); -# endif -# ifdef DIAGNOSTIC - panic("invalid TCP state"); -# endif -#else +#if !defined(_KERNEL) abort(); #endif break; @@ -3333,9 +4339,11 @@ int flags; if (rval == 2) rval = 1; else if (rval == 1) { - tqe->tqe_state[dir] = nstate; + if (ok) + tqe->tqe_state[dir] = nstate; if ((tqe->tqe_flags & TQE_RULEBASED) == 0) - fr_movequeue(tqe, tqe->tqe_ifq, tqtab + nstate); + ipf_movequeue(softc->ipf_ticks, tqe, tqe->tqe_ifq, + tqtab + nstate); } return rval; @@ -3343,18 +4351,21 @@ int flags; /* ------------------------------------------------------------------------ */ -/* Function: ipstate_log */ +/* Function: ipf_state_log */ /* Returns: Nil */ -/* Parameters: is(I) - pointer to state structure */ -/* type(I) - type of log entry to create */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* is(I) - pointer to state structure */ +/* type(I) - type of log entry to create */ /* */ /* Creates a state table log entry using the state structure and type info. */ /* passed in. Log packet/byte counts, source/destination address and other */ /* protocol specific information. */ /* ------------------------------------------------------------------------ */ -void ipstate_log(is, type) -struct ipstate *is; -u_int type; +void +ipf_state_log(softc, is, type) + ipf_main_softc_t *softc; + struct ipstate *is; + u_int type; { #ifdef IPFILTER_LOG struct ipslog ipsl; @@ -3404,18 +4415,14 @@ u_int type; sizes[0] = sizeof(ipsl); types[0] = 0; - if (ipllog(IPL_LOGSTATE, NULL, items, sizes, types, 1)) { - ATOMIC_INCL(ips_stats.iss_logged); - } else { - ATOMIC_INCL(ips_stats.iss_logfail); - } + (void) ipf_log_items(softc, IPL_LOGSTATE, NULL, items, sizes, types, 1); #endif } #ifdef USE_INET6 /* ------------------------------------------------------------------------ */ -/* Function: fr_checkicmp6matchingstate */ +/* Function: ipf_checkicmp6matchingstate */ /* Returns: ipstate_t* - NULL == no match found, */ /* else pointer to matching state entry */ /* Parameters: fin(I) - pointer to packet information */ @@ -3424,11 +4431,13 @@ u_int type; /* If we've got an ICMPv6 error message, using the information stored in */ /* the ICMPv6 packet, look for a matching state table entry. */ /* ------------------------------------------------------------------------ */ -static ipstate_t *fr_checkicmp6matchingstate(fin) -fr_info_t *fin; +static ipstate_t * +ipf_checkicmp6matchingstate(fin) + fr_info_t *fin; { + ipf_main_softc_t *softc = fin->fin_main_soft; + ipf_state_softc_t *softs = softc->ipf_state_soft; struct icmp6_hdr *ic6, *oic; - int type, backward, i; ipstate_t *is, **isp; u_short sport, dport; i6addr_t dst, src; @@ -3437,31 +4446,32 @@ fr_info_t *fin; fr_info_t ofin; tcphdr_t *tcp; ip6_t *oip6; - u_char pr; + u_char pr; u_int hv; + int type; /* * Does it at least have the return (basic) IP header ? + * Is it an actual recognised ICMP error type? * Only a basic IP header (no options) should be with * an ICMP error header. */ - if ((fin->fin_v != 6) || (fin->fin_plen < ICMP6ERR_MINPKTLEN)) + if ((fin->fin_v != 6) || (fin->fin_plen < ICMP6ERR_MINPKTLEN) || + !(fin->fin_flx & FI_ICMPERR)) { + SBUMPD(ipf_state_stats, iss_icmp_bad); return NULL; + } ic6 = fin->fin_dp; type = ic6->icmp6_type; - /* - * If it's not an error type, then return - */ - if ((type != ICMP6_DST_UNREACH) && (type != ICMP6_PACKET_TOO_BIG) && - (type != ICMP6_TIME_EXCEEDED) && (type != ICMP6_PARAM_PROB)) - return NULL; oip6 = (ip6_t *)((char *)ic6 + ICMPERR_ICMPHLEN); - if (fin->fin_plen < sizeof(*oip6)) + if (fin->fin_plen < sizeof(*oip6)) { + SBUMPD(ipf_state_stats, iss_icmp_short); return NULL; + } - bcopy((char *)fin, (char *)&ofin, sizeof(fin)); + bcopy((char *)fin, (char *)&ofin, sizeof(*fin)); ofin.fin_v = 6; ofin.fin_ifp = fin->fin_ifp; ofin.fin_out = !fin->fin_out; @@ -3473,22 +4483,31 @@ fr_info_t *fin; * matchsrcdst. Note that not all fields are necessary * but this is the cleanest way. Note further we fill * in fin_mp such that if someone uses it we'll get - * a kernel panic. fr_matchsrcdst does not use this. + * a kernel panic. ipf_matchsrcdst does not use this. * * watch out here, as ip is in host order and oip6 in network * order. Any change we make must be undone afterwards. */ savelen = oip6->ip6_plen; - oip6->ip6_plen = fin->fin_dlen - ICMPERR_ICMPHLEN; + oip6->ip6_plen = htons(fin->fin_dlen - ICMPERR_ICMPHLEN); ofin.fin_flx = FI_NOCKSUM; ofin.fin_ip = (ip_t *)oip6; - ofin.fin_plen = oip6->ip6_plen; - (void) fr_makefrip(sizeof(*oip6), (ip_t *)oip6, &ofin); + (void) ipf_makefrip(sizeof(*oip6), (ip_t *)oip6, &ofin); ofin.fin_flx &= ~(FI_BAD|FI_SHORT); oip6->ip6_plen = savelen; + pr = ofin.fin_p; + + /* + * an ICMP error can never generate an ICMP error in response. + */ + if (ofin.fin_flx & FI_ICMPERR) { + DT1(iss_icmp6_icmperr, fr_info_t *, &ofin); + SBUMP(ipf_state_stats.iss_icmp6_icmperr); + return NULL; + } if (oip6->ip6_nxt == IPPROTO_ICMPV6) { - oic = (struct icmp6_hdr *)(oip6 + 1); + oic = ofin.fin_dp; /* * an ICMP error can only be generated as a result of an * ICMP query, not as the response on an ICMP error @@ -3496,8 +4515,11 @@ fr_info_t *fin; * XXX theoretically ICMP_ECHOREP and the other reply's are * ICMP query's as well, but adding them here seems strange XXX */ - if (!(oic->icmp6_type & ICMP6_INFOMSG_MASK)) - return NULL; + if (!(oic->icmp6_type & ICMP6_INFOMSG_MASK)) { + DT1(iss_icmp6_notinfo, fr_info_t *, &ofin); + SBUMP(ipf_state_stats.iss_icmp6_notinfo); + return NULL; + } /* * perform a lookup of the ICMP packet in the state table @@ -3511,15 +4533,16 @@ fr_info_t *fin; hv += oic->icmp6_seq; hv = DOUBLE_HASH(hv); - READ_ENTER(&ipf_state); - for (isp = &ips_table[hv]; ((is = *isp) != NULL); ) { + READ_ENTER(&softc->ipf_state); + for (isp = &softs->ipf_state_table[hv]; + ((is = *isp) != NULL); ) { ic = &is->is_icmp; isp = &is->is_hnext; if ((is->is_p == pr) && !(is->is_pass & FR_NOICMPERR) && (oic->icmp6_id == ic->ici_id) && (oic->icmp6_seq == ic->ici_seq) && - (is = fr_matchsrcdst(&ofin, is, &src, + (is = ipf_matchsrcdst(&ofin, is, &src, &dst, NULL, FI_ICMPCMP))) { /* * in the state table ICMP query's are stored @@ -3529,16 +4552,13 @@ fr_info_t *fin; if (((ic->ici_type == ICMP6_ECHO_REPLY) && (oic->icmp6_type == ICMP6_ECHO_REQUEST)) || (ic->ici_type - 1 == oic->icmp6_type )) { - ips_stats.iss_hits++; - backward = IP6_NEQ(&is->is_dst, &src); - fin->fin_rev = !backward; - i = (backward << 1) + fin->fin_out; - is->is_icmppkts[i]++; - return is; + if (!ipf_allowstateicmp(fin, is, &src)) + return is; } } } - RWLOCK_EXIT(&ipf_state); + RWLOCK_EXIT(&softc->ipf_state); + SBUMPD(ipf_state_stats, iss_icmp6_miss); return NULL; } @@ -3554,18 +4574,33 @@ fr_info_t *fin; hv += dst.i6[2]; hv += dst.i6[3]; - if ((oip6->ip6_nxt == IPPROTO_TCP) || (oip6->ip6_nxt == IPPROTO_UDP)) { + tcp = NULL; + + switch (oip6->ip6_nxt) + { + case IPPROTO_TCP : + case IPPROTO_UDP : tcp = (tcphdr_t *)(oip6 + 1); dport = tcp->th_dport; sport = tcp->th_sport; hv += dport; hv += sport; - } else - tcp = NULL; + break; + + case IPPROTO_ICMPV6 : + oic = (struct icmp6_hdr *)(oip6 + 1); + hv += oic->icmp6_id; + hv += oic->icmp6_seq; + break; + + default : + break; + } + hv = DOUBLE_HASH(hv); - READ_ENTER(&ipf_state); - for (isp = &ips_table[hv]; ((is = *isp) != NULL); ) { + READ_ENTER(&softc->ipf_state); + for (isp = &softs->ipf_state_table[hv]; ((is = *isp) != NULL); ) { isp = &is->is_hnext; /* * Only allow this icmp though if the @@ -3577,73 +4612,63 @@ fr_info_t *fin; if ((is->is_p != pr) || (is->is_v != 6) || (is->is_pass & FR_NOICMPERR)) continue; - is = fr_matchsrcdst(&ofin, is, &src, &dst, tcp, FI_ICMPCMP); - if (is != NULL) { - ips_stats.iss_hits++; - backward = IP6_NEQ(&is->is_dst, &src); - fin->fin_rev = !backward; - i = (backward << 1) + fin->fin_out; - is->is_icmppkts[i]++; - /* - * we deliberately do not touch the timeouts - * for the accompanying state table entry. - * It remains to be seen if that is correct. XXX - */ + is = ipf_matchsrcdst(&ofin, is, &src, &dst, tcp, FI_ICMPCMP); + if ((is != NULL) && (ipf_allowstateicmp(fin, is, &src) == 0)) return is; - } } - RWLOCK_EXIT(&ipf_state); + RWLOCK_EXIT(&softc->ipf_state); + SBUMPD(ipf_state_stats, iss_icmp_miss); return NULL; } #endif /* ------------------------------------------------------------------------ */ -/* Function: fr_sttab_init */ +/* Function: ipf_sttab_init */ /* Returns: Nil */ -/* Parameters: tqp(I) - pointer to an array of timeout queues for TCP */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* tqp(I) - pointer to an array of timeout queues for TCP */ /* */ /* Initialise the array of timeout queues for TCP. */ /* ------------------------------------------------------------------------ */ -void fr_sttab_init(tqp) -ipftq_t *tqp; +void +ipf_sttab_init(softc, tqp) + ipf_main_softc_t *softc; + ipftq_t *tqp; { int i; for (i = IPF_TCP_NSTATES - 1; i >= 0; i--) { - tqp[i].ifq_ttl = 0; - tqp[i].ifq_ref = 1; - tqp[i].ifq_head = NULL; - tqp[i].ifq_tail = &tqp[i].ifq_head; + IPFTQ_INIT(&tqp[i], 0, "ipftq tcp tab"); tqp[i].ifq_next = tqp + i + 1; - MUTEX_INIT(&tqp[i].ifq_lock, "ipftq tcp tab"); } tqp[IPF_TCP_NSTATES - 1].ifq_next = NULL; - tqp[IPF_TCPS_CLOSED].ifq_ttl = fr_tcpclosed; - tqp[IPF_TCPS_LISTEN].ifq_ttl = fr_tcptimeout; - tqp[IPF_TCPS_SYN_SENT].ifq_ttl = fr_tcptimeout; - tqp[IPF_TCPS_SYN_RECEIVED].ifq_ttl = fr_tcptimeout; - tqp[IPF_TCPS_ESTABLISHED].ifq_ttl = fr_tcpidletimeout; - tqp[IPF_TCPS_CLOSE_WAIT].ifq_ttl = fr_tcphalfclosed; - tqp[IPF_TCPS_FIN_WAIT_1].ifq_ttl = fr_tcphalfclosed; - tqp[IPF_TCPS_CLOSING].ifq_ttl = fr_tcptimeout; - tqp[IPF_TCPS_LAST_ACK].ifq_ttl = fr_tcplastack; - tqp[IPF_TCPS_FIN_WAIT_2].ifq_ttl = fr_tcpclosewait; - tqp[IPF_TCPS_TIME_WAIT].ifq_ttl = fr_tcptimeout; - tqp[IPF_TCPS_HALF_ESTAB].ifq_ttl = fr_tcptimeout; + tqp[IPF_TCPS_CLOSED].ifq_ttl = softc->ipf_tcpclosed; + tqp[IPF_TCPS_LISTEN].ifq_ttl = softc->ipf_tcptimeout; + tqp[IPF_TCPS_SYN_SENT].ifq_ttl = softc->ipf_tcpsynsent; + tqp[IPF_TCPS_SYN_RECEIVED].ifq_ttl = softc->ipf_tcpsynrecv; + tqp[IPF_TCPS_ESTABLISHED].ifq_ttl = softc->ipf_tcpidletimeout; + tqp[IPF_TCPS_CLOSE_WAIT].ifq_ttl = softc->ipf_tcphalfclosed; + tqp[IPF_TCPS_FIN_WAIT_1].ifq_ttl = softc->ipf_tcphalfclosed; + tqp[IPF_TCPS_CLOSING].ifq_ttl = softc->ipf_tcptimeout; + tqp[IPF_TCPS_LAST_ACK].ifq_ttl = softc->ipf_tcplastack; + tqp[IPF_TCPS_FIN_WAIT_2].ifq_ttl = softc->ipf_tcpclosewait; + tqp[IPF_TCPS_TIME_WAIT].ifq_ttl = softc->ipf_tcptimewait; + tqp[IPF_TCPS_HALF_ESTAB].ifq_ttl = softc->ipf_tcptimeout; } /* ------------------------------------------------------------------------ */ -/* Function: fr_sttab_destroy */ +/* Function: ipf_sttab_destroy */ /* Returns: Nil */ /* Parameters: tqp(I) - pointer to an array of timeout queues for TCP */ /* */ /* Do whatever is necessary to "destroy" each of the entries in the array */ /* of timeout queues for TCP. */ /* ------------------------------------------------------------------------ */ -void fr_sttab_destroy(tqp) -ipftq_t *tqp; +void +ipf_sttab_destroy(tqp) + ipftq_t *tqp; { int i; @@ -3653,13 +4678,22 @@ ipftq_t *tqp; /* ------------------------------------------------------------------------ */ -/* Function: fr_statederef */ +/* Function: ipf_state_deref */ /* Returns: Nil */ -/* Parameters: isp(I) - pointer to pointer to state table entry */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* isp(I) - pointer to pointer to state table entry */ /* */ /* Decrement the reference counter for this state table entry and free it */ /* if there are no more things using it. */ /* */ +/* This function is only called when cleaning up after increasing is_ref by */ +/* one earlier in the 'code path' so if is_ref is 1 when entering, we do */ +/* have an orphan, otherwise not. However there is a possible race between */ +/* the entry being deleted via flushing with an ioctl call (that calls the */ +/* delete function directly) and the tail end of packet processing so we */ +/* need to grab is_lock before doing the check to synchronise the two code */ +/* paths. */ +/* */ /* When operating in userland (ipftest), we have no timers to clear a state */ /* entry. Therefore, we make a few simple tests before deleting an entry */ /* outright. We compare states on each side looking for a combination of */ @@ -3675,81 +4709,56 @@ ipftq_t *tqp; /* dir == 0 : a packet from source to dest */ /* dir == 1 : a packet from dest to source */ /* ------------------------------------------------------------------------ */ -void fr_statederef(fin, isp) -fr_info_t *fin; -ipstate_t **isp; +void +ipf_state_deref(softc, isp) + ipf_main_softc_t *softc; + ipstate_t **isp; { ipstate_t *is = *isp; -#if 0 - int nstate, ostate, dir, eol; - eol = 0; /* End-of-the-line flag. */ - dir = fin->fin_rev; - ostate = is->is_state[1 - dir]; - nstate = is->is_state[dir]; - /* - * Determine whether this packet is local or routed. State entries - * with us as the destination will have an interface list of - * int1,-,-,int1. Entries with us as the origin run as -,int1,int1,-. - */ - if ((fin->fin_p == IPPROTO_TCP) && (fin->fin_out == 0)) { - if ((strcmp(is->is_ifname[0], is->is_ifname[3]) == 0) && - (strcmp(is->is_ifname[1], is->is_ifname[2]) == 0)) { - if ((dir == 0) && - (strcmp(is->is_ifname[1], "-") == 0) && - (strcmp(is->is_ifname[0], "-") != 0)) { - eol = 1; - } else if ((dir == 1) && - (strcmp(is->is_ifname[0], "-") == 0) && - (strcmp(is->is_ifname[1], "-") != 0)) { - eol = 1; - } - } - } -#endif - - fin = fin; /* LINT */ is = *isp; *isp = NULL; - WRITE_ENTER(&ipf_state); - is->is_ref--; - if (is->is_ref == 0) { - is->is_ref++; /* To counter ref-- in fr_delstate() */ - fr_delstate(is, ISL_EXPIRE); + + MUTEX_ENTER(&is->is_lock); + if (is->is_ref > 1) { + is->is_ref--; + MUTEX_EXIT(&is->is_lock); #ifndef _KERNEL -#if 0 - } else if (((fin->fin_out == 1) || (eol == 1)) && - ((ostate == IPF_TCPS_LAST_ACK) && - (nstate == IPF_TCPS_TIME_WAIT))) { - ; -#else - } else if ((is->is_sti.tqe_state[0] > IPF_TCPS_ESTABLISHED) || - (is->is_sti.tqe_state[1] > IPF_TCPS_ESTABLISHED)) { -#endif - fr_delstate(is, ISL_ORPHAN); + if ((is->is_sti.tqe_state[0] > IPF_TCPS_ESTABLISHED) || + (is->is_sti.tqe_state[1] > IPF_TCPS_ESTABLISHED)) { + ipf_state_del(softc, is, ISL_EXPIRE); + } #endif + return; } - RWLOCK_EXIT(&ipf_state); + MUTEX_EXIT(&is->is_lock); + + WRITE_ENTER(&softc->ipf_state); + ipf_state_del(softc, is, ISL_ORPHAN); + RWLOCK_EXIT(&softc->ipf_state); } /* ------------------------------------------------------------------------ */ -/* Function: fr_setstatequeue */ +/* Function: ipf_state_setqueue */ /* Returns: Nil */ -/* Parameters: is(I) - pointer to state structure */ -/* rev(I) - forward(0) or reverse(1) direction */ +/* Parameters: softc(I) - pointer to soft context main structure */ +/* is(I) - pointer to state structure */ +/* rev(I) - forward(0) or reverse(1) direction */ /* Locks: ipf_state (read or write) */ /* */ /* Put the state entry on its default queue entry, using rev as a helped in */ /* determining which queue it should be placed on. */ /* ------------------------------------------------------------------------ */ -void fr_setstatequeue(is, rev) -ipstate_t *is; -int rev; +void +ipf_state_setqueue(softc, is, rev) + ipf_main_softc_t *softc; + ipstate_t *is; + int rev; { + ipf_state_softc_t *softs = softc->ipf_state_soft; ipftq_t *oifq, *nifq; - if ((is->is_sti.tqe_flags & TQE_RULEBASED) != 0) nifq = is->is_tqehead[rev]; else @@ -3761,30 +4770,30 @@ int rev; #ifdef USE_INET6 case IPPROTO_ICMPV6 : if (rev == 1) - nifq = &ips_icmpacktq; + nifq = &softs->ipf_state_icmpacktq; else - nifq = &ips_icmptq; + nifq = &softs->ipf_state_icmptq; break; #endif case IPPROTO_ICMP : if (rev == 1) - nifq = &ips_icmpacktq; + nifq = &softs->ipf_state_icmpacktq; else - nifq = &ips_icmptq; + nifq = &softs->ipf_state_icmptq; break; case IPPROTO_TCP : - nifq = ips_tqtqb + is->is_state[rev]; + nifq = softs->ipf_state_tcptq + is->is_state[rev]; break; case IPPROTO_UDP : if (rev == 1) - nifq = &ips_udpacktq; + nifq = &softs->ipf_state_udpacktq; else - nifq = &ips_udptq; + nifq = &softs->ipf_state_udptq; break; default : - nifq = &ips_iptq; + nifq = &softs->ipf_state_iptq; break; } } @@ -3795,8 +4804,560 @@ int rev; * another, else put it on the end of the newly determined queue. */ if (oifq != NULL) - fr_movequeue(&is->is_sti, oifq, nifq); + ipf_movequeue(softc->ipf_ticks, &is->is_sti, oifq, nifq); else - fr_queueappend(&is->is_sti, nifq, is); + ipf_queueappend(softc->ipf_ticks, &is->is_sti, nifq, is); return; } + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_state_iter */ +/* Returns: int - 0 == success, else error */ +/* Parameters: softc(I) - pointer to main soft context */ +/* token(I) - pointer to ipftoken structure */ +/* itp(I) - pointer to ipfgeniter structure */ +/* obj(I) - pointer to data description structure */ +/* */ +/* This function handles the SIOCGENITER ioctl for the state tables and */ +/* walks through the list of entries in the state table list (softs->ipf_state_list.) */ +/* ------------------------------------------------------------------------ */ +static int +ipf_state_iter(softc, token, itp, obj) + ipf_main_softc_t *softc; + ipftoken_t *token; + ipfgeniter_t *itp; + ipfobj_t *obj; +{ + ipf_state_softc_t *softs = softc->ipf_state_soft; + ipstate_t *is, *next, zero; + int error; + + if (itp->igi_data == NULL) { + IPFERROR(100026); + return EFAULT; + } + + if (itp->igi_nitems < 1) { + IPFERROR(100027); + return ENOSPC; + } + + if (itp->igi_type != IPFGENITER_STATE) { + IPFERROR(100028); + return EINVAL; + } + + is = token->ipt_data; + if (is == (void *)-1) { + IPFERROR(100029); + return ESRCH; + } + + error = 0; + obj->ipfo_type = IPFOBJ_IPSTATE; + obj->ipfo_size = sizeof(ipstate_t); + + READ_ENTER(&softc->ipf_state); + + is = token->ipt_data; + if (is == NULL) { + next = softs->ipf_state_list; + } else { + next = is->is_next; + } + + /* + * If we find a state entry to use, bump its reference count so that + * it can be used for is_next when we come back. + */ + if (next != NULL) { + MUTEX_ENTER(&next->is_lock); + next->is_ref++; + MUTEX_EXIT(&next->is_lock); + token->ipt_data = next; + } else { + bzero(&zero, sizeof(zero)); + next = &zero; + token->ipt_data = NULL; + } + if (next->is_next == NULL) + ipf_token_mark_complete(token); + + RWLOCK_EXIT(&softc->ipf_state); + + obj->ipfo_ptr = itp->igi_data; + error = ipf_outobjk(softc, obj, next); + if (is != NULL) + ipf_state_deref(softc, &is); + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_state_gettable */ +/* Returns: int - 0 = success, else error */ +/* Parameters: softc(I) - pointer to main soft context */ +/* softs(I) - pointer to state context structure */ +/* data(I) - pointer to ioctl data */ +/* */ +/* This function handles ioctl requests for tables of state information. */ +/* At present the only table it deals with is the hash bucket statistics. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_state_gettable(softc, softs, data) + ipf_main_softc_t *softc; + ipf_state_softc_t *softs; + char *data; +{ + ipftable_t table; + int error; + + error = ipf_inobj(softc, data, NULL, &table, IPFOBJ_GTABLE); + if (error != 0) + return error; + + if (table.ita_type != IPFTABLE_BUCKETS) { + IPFERROR(100031); + return EINVAL; + } + + error = COPYOUT(softs->ipf_state_stats.iss_bucketlen, table.ita_table, + softs->ipf_state_size * sizeof(u_int)); + if (error != 0) { + IPFERROR(100032); + error = EFAULT; + } + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_state_setpending */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to main soft context */ +/* is(I) - pointer to state structure */ +/* Locks: ipf_state (read or write) */ +/* */ +/* Put the state entry on to the pending queue - this queue has a very */ +/* short lifetime where items are put that can't be deleted straight away */ +/* because of locking issues but we want to delete them ASAP, anyway. */ +/* ------------------------------------------------------------------------ */ +void +ipf_state_setpending(softc, is) + ipf_main_softc_t *softc; + ipstate_t *is; +{ + ipf_state_softc_t *softs = softc->ipf_state_soft; + ipftq_t *oifq; + + oifq = is->is_sti.tqe_ifq; + if (oifq != NULL) + ipf_movequeue(softc->ipf_ticks, &is->is_sti, oifq, + &softs->ipf_state_pending); + else + ipf_queueappend(softc->ipf_ticks, &is->is_sti, + &softs->ipf_state_pending, is); + + MUTEX_ENTER(&is->is_lock); + if (is->is_me != NULL) { + *is->is_me = NULL; + is->is_me = NULL; + is->is_ref--; + } + MUTEX_EXIT(&is->is_lock); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_state_matchflush */ +/* Returns: Nil */ +/* Parameters: softc(I) - pointer to main soft context */ +/* data(I) - pointer to state structure */ +/* Locks: ipf_state (read or write) */ +/* */ +/* Flush all entries from the list of state entries that match the */ +/* properties in the array loaded. */ +/* ------------------------------------------------------------------------ */ +int +ipf_state_matchflush(softc, data) + ipf_main_softc_t *softc; + caddr_t data; +{ + ipf_state_softc_t *softs = softc->ipf_state_soft; + int *array, flushed, error; + ipstate_t *state, *statenext; + ipfobj_t obj; + + error = ipf_matcharray_load(softc, data, &obj, &array); + if (error != 0) + return error; + + flushed = 0; + + for (state = softs->ipf_state_list; state != NULL; state = statenext) { + statenext = state->is_next; + if (ipf_state_matcharray(state, array, softc->ipf_ticks) == 0) { + ipf_state_del(softc, state, ISL_FLUSH); + flushed++; + } + } + + obj.ipfo_retval = flushed; + error = BCOPYOUT(&obj, data, sizeof(obj)); + + KFREES(array, array[0] * sizeof(*array)); + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_state_matcharray */ +/* Returns: int - 0 = no match, 1 = match */ +/* Parameters: state(I) - pointer to state structure */ +/* array(I) - pointer to ipf matching expression */ +/* ticks(I) - current value of ipfilter tick timer */ +/* Locks: ipf_state (read or write) */ +/* */ +/* Compare a state entry with the match array passed in and return a value */ +/* to indicate whether or not the matching was successful. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_state_matcharray(state, array, ticks) + ipstate_t *state; + int *array; + u_long ticks; +{ + int i, n, *x, rv, p; + ipfexp_t *e; + + rv = 0; + n = array[0]; + x = array + 1; + + for (; n > 0; x += 3 + x[3], rv = 0) { + e = (ipfexp_t *)x; + n -= e->ipfe_size; + if (x[0] == IPF_EXP_END) + break; + + /* + * If we need to match the protocol and that doesn't match, + * don't even both with the instruction array. + */ + p = e->ipfe_cmd >> 16; + if ((p != 0) && (p != state->is_p)) + break; + + switch (e->ipfe_cmd) + { + case IPF_EXP_IP_PR : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (state->is_p == e->ipfe_arg0[i]); + } + break; + + case IPF_EXP_IP_SRCADDR : + if (state->is_v != 4) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= ((state->is_saddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]); + } + break; + + case IPF_EXP_IP_DSTADDR : + if (state->is_v != 4) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= ((state->is_daddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]); + } + break; + + case IPF_EXP_IP_ADDR : + if (state->is_v != 4) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= ((state->is_saddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]) || + ((state->is_daddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]); + } + break; + +#ifdef USE_INET6 + case IPF_EXP_IP6_SRCADDR : + if (state->is_v != 6) + break; + for (i = 0; !rv && i < x[3]; i++) { + rv |= IP6_MASKEQ(&state->is_src.in6, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]); + } + break; + + case IPF_EXP_IP6_DSTADDR : + if (state->is_v != 6) + break; + for (i = 0; !rv && i < x[3]; i++) { + rv |= IP6_MASKEQ(&state->is_dst.in6, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]); + } + break; + + case IPF_EXP_IP6_ADDR : + if (state->is_v != 6) + break; + for (i = 0; !rv && i < x[3]; i++) { + rv |= IP6_MASKEQ(&state->is_src.in6, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]) || + IP6_MASKEQ(&state->is_dst.in6, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]); + } + break; +#endif + + case IPF_EXP_UDP_PORT : + case IPF_EXP_TCP_PORT : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (state->is_sport == e->ipfe_arg0[i]) || + (state->is_dport == e->ipfe_arg0[i]); + } + break; + + case IPF_EXP_UDP_SPORT : + case IPF_EXP_TCP_SPORT : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (state->is_sport == e->ipfe_arg0[i]); + } + break; + + case IPF_EXP_UDP_DPORT : + case IPF_EXP_TCP_DPORT : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (state->is_dport == e->ipfe_arg0[i]); + } + break; + + case IPF_EXP_TCP_STATE : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (state->is_state[0] == e->ipfe_arg0[i]) || + (state->is_state[1] == e->ipfe_arg0[i]); + } + break; + + case IPF_EXP_IDLE_GT : + rv |= (ticks - state->is_touched > e->ipfe_arg0[0]); + break; + } + + /* + * Factor in doing a negative match. + */ + rv ^= e->ipfe_not; + + if (rv == 0) + break; + } + + return rv; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_state_settimeout */ +/* Returns: int 0 = success, else failure */ +/* Parameters: softc(I) - pointer to main soft context */ +/* t(I) - pointer to tuneable being changed */ +/* p(I) - pointer to the new value */ +/* */ +/* Sets a timeout value for one of the many timeout queues. We find the */ +/* correct queue using a somewhat manual process of comparing the timeout */ +/* names for each specific value available and calling ipf_apply_timeout on */ +/* that queue so that all of the items on it are updated accordingly. */ +/* ------------------------------------------------------------------------ */ +int +ipf_state_settimeout(softc, t, p) + struct ipf_main_softc_s *softc; + ipftuneable_t *t; + ipftuneval_t *p; +{ + ipf_state_softc_t *softs = softc->ipf_state_soft; + + /* + * In case there is nothing to do... + */ + if (*t->ipft_pint == p->ipftu_int) + return 0; + + if (!strncmp(t->ipft_name, "tcp_", 4)) + return ipf_settimeout_tcp(t, p, softs->ipf_state_tcptq); + + if (!strcmp(t->ipft_name, "udp_timeout")) { + ipf_apply_timeout(&softs->ipf_state_udptq, p->ipftu_int); + } else if (!strcmp(t->ipft_name, "udp_ack_timeout")) { + ipf_apply_timeout(&softs->ipf_state_udpacktq, p->ipftu_int); + } else if (!strcmp(t->ipft_name, "icmp_timeout")) { + ipf_apply_timeout(&softs->ipf_state_icmptq, p->ipftu_int); + } else if (!strcmp(t->ipft_name, "icmp_ack_timeout")) { + ipf_apply_timeout(&softs->ipf_state_icmpacktq, p->ipftu_int); + } else if (!strcmp(t->ipft_name, "ip_timeout")) { + ipf_apply_timeout(&softs->ipf_state_iptq, p->ipftu_int); + } else { + IPFERROR(100034); + return ESRCH; + } + + /* + * Update the tuneable being set. + */ + *t->ipft_pint = p->ipftu_int; + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_state_rehash */ +/* Returns: int 0 = success, else failure */ +/* Parameters: softc(I) - pointer to main soft context */ +/* t(I) - pointer to tuneable being changed */ +/* p(I) - pointer to the new value */ +/* */ +/* To change the size of the state hash table at runtime, a new table has */ +/* to be allocated and then all of the existing entries put in it, bumping */ +/* up the bucketlength for it as we go along. */ +/* ------------------------------------------------------------------------ */ +int +ipf_state_rehash(softc, t, p) + ipf_main_softc_t *softc; + ipftuneable_t *t; + ipftuneval_t *p; +{ + ipf_state_softc_t *softs = softc->ipf_state_soft; + ipstate_t **newtab, *is; + u_int *bucketlens; + u_int maxbucket; + u_int newsize; + u_int hv; + int i; + + newsize = p->ipftu_int; + /* + * In case there is nothing to do... + */ + if (newsize == softs->ipf_state_size) + return 0; + + KMALLOCS(newtab, ipstate_t **, newsize * sizeof(ipstate_t *)); + if (newtab == NULL) { + IPFERROR(100035); + return ENOMEM; + } + + KMALLOCS(bucketlens, u_int *, newsize * sizeof(u_int)); + if (bucketlens == NULL) { + KFREES(newtab, newsize * sizeof(*softs->ipf_state_table)); + IPFERROR(100036); + return ENOMEM; + } + + for (maxbucket = 0, i = newsize; i > 0; i >>= 1) + maxbucket++; + maxbucket *= 2; + + bzero((char *)newtab, newsize * sizeof(ipstate_t *)); + bzero((char *)bucketlens, newsize * sizeof(u_int)); + + WRITE_ENTER(&softc->ipf_state); + + if (softs->ipf_state_table != NULL) { + KFREES(softs->ipf_state_table, + softs->ipf_state_size * sizeof(*softs->ipf_state_table)); + } + softs->ipf_state_table = newtab; + + if (softs->ipf_state_stats.iss_bucketlen != NULL) { + KFREES(softs->ipf_state_stats.iss_bucketlen, + softs->ipf_state_size * sizeof(u_int)); + } + softs->ipf_state_stats.iss_bucketlen = bucketlens; + softs->ipf_state_maxbucket = maxbucket; + softs->ipf_state_size = newsize; + + /* + * Walk through the entire list of state table entries and put them + * in the new state table, somewhere. Because we have a new table, + * we need to restart the counter of how many chains are in use. + */ + softs->ipf_state_stats.iss_inuse = 0; + for (is = softs->ipf_state_list; is != NULL; is = is->is_next) { + is->is_hnext = NULL; + is->is_phnext = NULL; + hv = is->is_hv % softs->ipf_state_size; + + if (softs->ipf_state_table[hv] != NULL) + softs->ipf_state_table[hv]->is_phnext = &is->is_hnext; + else + softs->ipf_state_stats.iss_inuse++; + is->is_phnext = softs->ipf_state_table + hv; + is->is_hnext = softs->ipf_state_table[hv]; + softs->ipf_state_table[hv] = is; + softs->ipf_state_stats.iss_bucketlen[hv]++; + } + RWLOCK_EXIT(&softc->ipf_state); + + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_state_add_tq */ +/* Returns: ipftq_t * - NULL = failure, else pointer to new timeout */ +/* queue */ +/* Parameters: softc(I) - pointer to main soft context */ +/* ttl(I) - pointer to the ttl for the new queue */ +/* */ +/* Request a pointer to a timeout queue that has a ttl as given by the */ +/* value being passed in. The timeout queue is added tot the list of those */ +/* used internally for stateful filtering. */ +/* ------------------------------------------------------------------------ */ +ipftq_t * +ipf_state_add_tq(softc, ttl) + ipf_main_softc_t *softc; + int ttl; +{ + ipf_state_softc_t *softs = softc->ipf_state_soft; + + return ipf_addtimeoutqueue(softc, &softs->ipf_state_usertq, ttl); +} + + +#ifndef _KERNEL +/* + * Display the built up state table rules and mapping entries. + */ +void +ipf_state_dump(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_state_softc_t *softs = arg; + ipstate_t *ips; + + printf("List of active state sessions:\n"); + for (ips = softs->ipf_state_list; ips != NULL; ) + ips = printstate(ips, opts & (OPT_DEBUG|OPT_VERBOSE), + softc->ipf_ticks); +} +#endif diff --git a/ip_state.h b/ip_state.h index 2f5f7f11dcc34..7265ec02d91ab 100644 --- a/ip_state.h +++ b/ip_state.h @@ -1,17 +1,15 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1995-2001 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_state.h 1.3 1/12/96 (C) 1995 Darren Reed - * Id: ip_state.h,v 2.68.2.3 2005/03/03 14:24:11 darrenr Exp + * $Id$ */ #ifndef __IP_STATE_H__ #define __IP_STATE_H__ -#if defined(__STDC__) || defined(__GNUC__) +#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51) # define SIOCDELST _IOW('r', 61, struct ipfobj) #else # define SIOCDELST _IOW(r, 61, struct ipfobj) @@ -41,7 +39,6 @@ typedef struct ipstate { struct ipstate **is_me; void *is_ifp[4]; void *is_sync; - struct nat *is_nat[2]; frentry_t *is_rule; struct ipftq *is_tqehead[2]; struct ipscan *is_isc; @@ -58,10 +55,11 @@ typedef struct ipstate { u_int is_pass; u_char is_p; /* Protocol */ u_char is_v; + int is_family; u_32_t is_hv; u_32_t is_tag; - u_32_t is_opt; /* packet options set */ - u_32_t is_optmsk; /* " " mask */ + u_32_t is_opt[2]; /* packet options set */ + u_32_t is_optmsk[2]; /* " " mask */ u_short is_sec; /* security options set */ u_short is_secmsk; /* " " mask */ u_short is_auth; /* authentication options set */ @@ -77,6 +75,8 @@ typedef struct ipstate { u_32_t is_rulen; /* rule number when created */ u_32_t is_s0[2]; u_short is_smsk[2]; + frdest_t is_dif; + frdest_t is_tifs[2]; char is_group[FR_GROUPLEN]; char is_sbuf[2][16]; char is_ifname[4][LIFNAMSIZ]; @@ -89,7 +89,6 @@ typedef struct ipstate { #define is_daddr is_dst.in4.s_addr #define is_icmp is_ps.is_ics #define is_type is_icmp.ici_type -#define is_code is_icmp.ici_code #define is_tcp is_ps.is_ts #define is_udp is_ps.is_us #define is_send is_tcp.ts_data[0].td_end @@ -121,6 +120,7 @@ typedef struct ipstate { #define IS_ISNSYN 0x40000 #define IS_ISNACK 0x80000 #define IS_STATESYNC 0x100000 +#define IS_LOOSE 0x200000 /* * IS_SC flags are for scan-operations that need to be recognised in state. */ @@ -132,7 +132,7 @@ typedef struct ipstate { #define IS_SC_ALL (IS_SC_MATCHC|IS_SC_MATCHC|IS_SC_CLIENT|IS_SC_SERVER) /* - * Flags that can be passed into fr_addstate + * Flags that can be passed into ipf_addstate */ #define IS_INHERITED 0x0fffff00 @@ -183,79 +183,153 @@ typedef struct ipslog { #define ISL_NEW 0 #define ISL_CLONE 1 +#define ISL_STATECHANGE 2 #define ISL_EXPIRE 0xffff #define ISL_FLUSH 0xfffe #define ISL_REMOVE 0xfffd #define ISL_INTERMEDIATE 0xfffc #define ISL_KILLED 0xfffb #define ISL_ORPHAN 0xfffa +#define ISL_UNLOAD 0xfff9 typedef struct ips_stat { + u_int iss_active; + u_int iss_active_proto[256]; + u_long iss_add_bad; + u_long iss_add_dup; + u_long iss_add_locked; + u_long iss_add_oow; + u_long iss_bucket_full; + u_long iss_check_bad; + u_long iss_check_miss; + u_long iss_check_nattag; + u_long iss_check_notag; + u_long iss_clone_nomem; + u_long iss_cloned; + u_long iss_expire; + u_long iss_fin; + u_long iss_flush_all; + u_long iss_flush_closing; + u_long iss_flush_queue; + u_long iss_flush_state; + u_long iss_flush_timeout; u_long iss_hits; - u_long iss_miss; + u_long iss_icmp6_icmperr; + u_long iss_icmp6_miss; + u_long iss_icmp6_notinfo; + u_long iss_icmp6_notquery; + u_long iss_icmp_bad; + u_long iss_icmp_banned; + u_long iss_icmp_headblock; + u_long iss_icmp_hits; + u_long iss_icmp_icmperr; + u_long iss_icmp_miss; + u_long iss_icmp_notquery; + u_long iss_icmp_short; + u_long iss_icmp_toomany; + u_int iss_inuse; + ipstate_t *iss_list; + u_long iss_log_fail; + u_long iss_log_ok; + u_long iss_lookup_badifp; + u_long iss_lookup_badport; + u_long iss_lookup_miss; u_long iss_max; - u_long iss_maxref; - u_long iss_tcp; - u_long iss_udp; - u_long iss_icmp; + u_long iss_max_ref; + u_long iss_max_track; + u_long iss_miss_mask; u_long iss_nomem; - u_long iss_expire; - u_long iss_fin; - u_long iss_active; - u_long iss_logged; - u_long iss_logfail; - u_long iss_inuse; - u_long iss_wild; - u_long iss_killed; - u_long iss_ticks; - u_long iss_bucketfull; - int iss_statesize; - int iss_statemax; + u_long iss_oow; + u_long iss_orphan; + u_long iss_proto[256]; + u_long iss_scan_block; + u_long iss_state_max; + u_long iss_state_size; + u_long iss_states[IPF_TCP_NSTATES]; ipstate_t **iss_table; - ipstate_t *iss_list; - u_long *iss_bucketlen; + u_long iss_tcp_closing; + u_long iss_tcp_oow; + u_long iss_tcp_rstadd; + u_long iss_tcp_toosmall; + u_long iss_tcp_badopt; + u_long iss_tcp_fsm; + u_long iss_tcp_strict; + ipftq_t *iss_tcptab; + u_int iss_ticks; + u_long iss_wild; + u_long iss_winsack; + u_int *iss_bucketlen; } ips_stat_t; -extern u_long fr_tcpidletimeout; -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_udpacktimeout; -extern u_long fr_icmptimeout; -extern u_long fr_icmpacktimeout; -extern u_long fr_iptimeout; -extern int fr_statemax; -extern int fr_statesize; -extern int fr_state_lock; -extern int fr_state_maxbucket; -extern int fr_state_maxbucket_reset; -extern ipstate_t *ips_list; -extern ipftq_t *ips_utqe; -extern ipftq_t ips_tqtqb[IPF_TCP_NSTATES]; +typedef struct ipf_state_softc_s { + ipfmutex_t ipf_stinsert; + int ipf_state_logging; + int ipf_state_lock; + int ipf_state_doflush; + u_int ipf_state_inited; + u_int ipf_state_max; + u_int ipf_state_maxbucket; + u_int ipf_state_size; + u_int ipf_state_wm_freq; + u_int ipf_state_wm_high; + u_int ipf_state_wm_low; + u_int ipf_state_wm_last; + u_long *ipf_state_seed; + ipstate_t *ipf_state_list; + ipstate_t **ipf_state_table; + ipftuneable_t *ipf_state_tune; + ipftq_t *ipf_state_usertq; + ipftq_t ipf_state_pending; + ipftq_t ipf_state_deletetq; + ipftq_t ipf_state_udptq; + ipftq_t ipf_state_udpacktq; + ipftq_t ipf_state_iptq; + ipftq_t ipf_state_icmptq; + ipftq_t ipf_state_icmpacktq; + ipftq_t ipf_state_tcptq[IPF_TCP_NSTATES]; + ips_stat_t ipf_state_stats; +} ipf_state_softc_t; + -extern int fr_stateinit __P((void)); -extern ipstate_t *fr_addstate __P((fr_info_t *, ipstate_t **, u_int)); -extern frentry_t *fr_checkstate __P((struct fr_info *, u_32_t *)); -extern ipstate_t *fr_stlookup __P((fr_info_t *, tcphdr_t *, ipftq_t **)); -extern void fr_statesync __P((void *)); -extern void fr_timeoutstate __P((void)); -extern int fr_tcp_age __P((struct ipftqent *, struct fr_info *, - struct ipftq *, int)); -extern int fr_tcpinwindow __P((struct fr_info *, struct tcpdata *, +#ifndef _KERNEL +extern void ipf_state_dump __P((ipf_main_softc_t *, void *)); +#endif +extern int ipf_tcp_age __P((struct ipftqent *, struct fr_info *, + struct ipftq *, int, int)); +extern int ipf_tcpinwindow __P((struct fr_info *, struct tcpdata *, struct tcpdata *, tcphdr_t *, int)); -extern void fr_stateunload __P((void)); -extern void ipstate_log __P((struct ipstate *, u_int)); -extern int fr_state_ioctl __P((caddr_t, ioctlcmd_t, int)); -extern void fr_stinsert __P((struct ipstate *, int)); -extern void fr_sttab_init __P((struct ipftq *)); -extern void fr_sttab_destroy __P((struct ipftq *)); -extern void fr_updatestate __P((fr_info_t *, ipstate_t *, ipftq_t *)); -extern void fr_statederef __P((fr_info_t *, ipstate_t **)); -extern void fr_setstatequeue __P((ipstate_t *, int)); + +extern int ipf_state_add __P((ipf_main_softc_t *, fr_info_t *, + ipstate_t **, u_int)); +extern frentry_t *ipf_state_check __P((struct fr_info *, u_32_t *)); +extern void ipf_state_deref __P((ipf_main_softc_t *, ipstate_t **)); +extern void ipf_state_expire __P((ipf_main_softc_t *)); +extern int ipf_state_flush __P((ipf_main_softc_t *, int, int)); +extern ipstate_t *ipf_state_lookup __P((fr_info_t *, tcphdr_t *, ipftq_t **)); +extern int ipf_state_init __P((void)); +extern int ipf_state_insert __P((ipf_main_softc_t *, struct ipstate *, int)); +extern int ipf_state_ioctl __P((ipf_main_softc_t *, caddr_t, ioctlcmd_t, int, int, void *)); +extern void ipf_state_log __P((ipf_main_softc_t *, struct ipstate *, u_int)); +extern int ipf_state_matchflush __P((ipf_main_softc_t *, caddr_t)); +extern int ipf_state_rehash __P((ipf_main_softc_t *, ipftuneable_t *, ipftuneval_t *)); +extern void ipf_state_setqueue __P((ipf_main_softc_t *, ipstate_t *, int)); +extern void ipf_state_setpending __P((ipf_main_softc_t *, ipstate_t *)); +extern int ipf_state_settimeout __P((struct ipf_main_softc_s *, ipftuneable_t *, ipftuneval_t *)); +extern void ipf_state_sync __P((ipf_main_softc_t *, void *)); +extern void ipf_state_update __P((fr_info_t *, ipstate_t *)); + +extern void ipf_sttab_init __P((ipf_main_softc_t *, struct ipftq *)); +extern void ipf_sttab_destroy __P((struct ipftq *)); +extern void ipf_state_setlock __P((void *, int)); +extern int ipf_state_main_load __P((void)); +extern int ipf_state_main_unload __P((void)); +extern void *ipf_state_soft_create __P((ipf_main_softc_t *)); +extern void ipf_state_soft_destroy __P((ipf_main_softc_t *, void *)); +extern int ipf_state_soft_init __P((ipf_main_softc_t *, void *)); +extern int ipf_state_soft_fini __P((ipf_main_softc_t *, void *)); +extern int ipf_state_main_load __P((void)); +extern ipftq_t *ipf_state_add_tq __P((ipf_main_softc_t *, int)); #endif /* __IP_STATE_H__ */ diff --git a/ip_sync.c b/ip_sync.c index 396bae791196e..a441c59619174 100644 --- a/ip_sync.c +++ b/ip_sync.c @@ -1,7 +1,5 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1995-1998 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -32,6 +30,10 @@ struct file; # if !defined(__SVR4) && !defined(__svr4__) # include <sys/mbuf.h> # endif +# include <sys/select.h> +# if __FreeBSD_version >= 500000 +# include <sys/selinfo.h> +# endif #endif #if defined(__NetBSD__) && (__NetBSD_Version__ >= 104000000) # include <sys/proc.h> @@ -39,9 +41,6 @@ struct file; #if defined(_KERNEL) && (__FreeBSD_version >= 220000) # include <sys/filio.h> # include <sys/fcntl.h> -# if (__FreeBSD_version >= 300000) && !defined(IPFILTER_LKM) -# include "opt_ipfilter.h" -# endif #else # include <sys/ioctl.h> #endif @@ -64,7 +63,6 @@ struct file; #ifdef sun # include <net/af.h> #endif -#include <net/route.h> #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> @@ -98,66 +96,219 @@ struct file; /* END OF INCLUDES */ #if !defined(lint) -static const char rcsid[] = "@(#)Id: ip_sync.c,v 2.40.2.3 2005/02/18 13:06:29 darrenr Exp"; +static const char rcsid[] = "@(#)$Id$"; #endif #define SYNC_STATETABSZ 256 #define SYNC_NATTABSZ 256 -#ifdef IPFILTER_SYNC -ipfmutex_t ipf_syncadd, ipsl_mutex; -ipfrwlock_t ipf_syncstate, ipf_syncnat; +typedef struct ipf_sync_softc_s { + ipfmutex_t ipf_syncadd; + ipfmutex_t ipsl_mutex; + ipfrwlock_t ipf_syncstate; + ipfrwlock_t ipf_syncnat; #if SOLARIS && defined(_KERNEL) -kcondvar_t ipslwait; + kcondvar_t ipslwait; #endif -synclist_t *syncstatetab[SYNC_STATETABSZ]; -synclist_t *syncnattab[SYNC_NATTABSZ]; -synclogent_t synclog[SYNCLOG_SZ]; -syncupdent_t syncupd[SYNCLOG_SZ]; -u_int ipf_syncnum = 1; -u_int ipf_syncwrap = 0; -u_int sl_idx = 0, /* next available sync log entry */ - su_idx = 0, /* next available sync update entry */ - sl_tail = 0, /* next sync log entry to read */ - su_tail = 0; /* next sync update entry to read */ -int ipf_sync_debug = 0; - +#if defined(linux) && defined(_KERNEL) + wait_queue_head_t sl_tail_linux; +#endif + synclist_t **syncstatetab; + synclist_t **syncnattab; + synclogent_t *synclog; + syncupdent_t *syncupd; + u_int ipf_sync_num; + u_int ipf_sync_wrap; + u_int sl_idx; /* next available sync log entry */ + u_int su_idx; /* next available sync update entry */ + u_int sl_tail; /* next sync log entry to read */ + u_int su_tail; /* next sync update entry to read */ + int ipf_sync_log_sz; + int ipf_sync_nat_tab_sz; + int ipf_sync_state_tab_sz; + int ipf_sync_debug; + int ipf_sync_events; + u_32_t ipf_sync_lastwakeup; + int ipf_sync_wake_interval; + int ipf_sync_event_high_wm; + int ipf_sync_queue_high_wm; + int ipf_sync_inited; +} ipf_sync_softc_t; + +static int ipf_sync_flush_table __P((ipf_sync_softc_t *, int, synclist_t **)); +static void ipf_sync_wakeup __P((ipf_main_softc_t *)); +static void ipf_sync_del __P((ipf_sync_softc_t *, synclist_t *)); +static void ipf_sync_poll_wakeup __P((ipf_main_softc_t *)); +static int ipf_sync_nat __P((ipf_main_softc_t *, synchdr_t *, void *)); +static int ipf_sync_state __P((ipf_main_softc_t *, synchdr_t *, void *)); # if !defined(sparc) && !defined(__hppa) -void ipfsync_tcporder __P((int, struct tcpdata *)); -void ipfsync_natorder __P((int, struct nat *)); -void ipfsync_storder __P((int, struct ipstate *)); +void ipf_sync_tcporder __P((int, struct tcpdata *)); +void ipf_sync_natorder __P((int, struct nat *)); +void ipf_sync_storder __P((int, struct ipstate *)); # endif +void * +ipf_sync_soft_create(softc) + ipf_main_softc_t *softc; +{ + ipf_sync_softc_t *softs; + + KMALLOC(softs, ipf_sync_softc_t *); + if (softs == NULL) { + IPFERROR(110024); + return NULL; + } + + bzero((char *)softs, sizeof(*softs)); + + softs->ipf_sync_log_sz = SYNCLOG_SZ; + softs->ipf_sync_nat_tab_sz = SYNC_STATETABSZ; + softs->ipf_sync_state_tab_sz = SYNC_STATETABSZ; + softs->ipf_sync_event_high_wm = SYNCLOG_SZ * 100 / 90; /* 90% */ + softs->ipf_sync_queue_high_wm = SYNCLOG_SZ * 100 / 90; /* 90% */ + + return softs; +} + + /* ------------------------------------------------------------------------ */ -/* Function: ipfsync_init */ +/* Function: ipf_sync_init */ /* Returns: int - 0 == success, -1 == failure */ /* Parameters: Nil */ /* */ /* Initialise all of the locks required for the sync code and initialise */ /* any data structures, as required. */ /* ------------------------------------------------------------------------ */ -int ipfsync_init() +int +ipf_sync_soft_init(softc, arg) + ipf_main_softc_t *softc; + void *arg; { - RWLOCK_INIT(&ipf_syncstate, "add things to state sync table"); - RWLOCK_INIT(&ipf_syncnat, "add things to nat sync table"); - MUTEX_INIT(&ipf_syncadd, "add things to sync table"); - MUTEX_INIT(&ipsl_mutex, "add things to sync table"); + ipf_sync_softc_t *softs = arg; + + KMALLOCS(softs->synclog, synclogent_t *, + softs->ipf_sync_log_sz * sizeof(*softs->synclog)); + if (softs->synclog == NULL) + return -1; + bzero((char *)softs->synclog, + softs->ipf_sync_log_sz * sizeof(*softs->synclog)); + + KMALLOCS(softs->syncupd, syncupdent_t *, + softs->ipf_sync_log_sz * sizeof(*softs->syncupd)); + if (softs->syncupd == NULL) + return -2; + bzero((char *)softs->syncupd, + softs->ipf_sync_log_sz * sizeof(*softs->syncupd)); + + KMALLOCS(softs->syncstatetab, synclist_t **, + softs->ipf_sync_state_tab_sz * sizeof(*softs->syncstatetab)); + if (softs->syncstatetab == NULL) + return -3; + bzero((char *)softs->syncstatetab, + softs->ipf_sync_state_tab_sz * sizeof(*softs->syncstatetab)); + + KMALLOCS(softs->syncnattab, synclist_t **, + softs->ipf_sync_nat_tab_sz * sizeof(*softs->syncnattab)); + if (softs->syncnattab == NULL) + return -3; + bzero((char *)softs->syncnattab, + softs->ipf_sync_nat_tab_sz * sizeof(*softs->syncnattab)); + + softs->ipf_sync_num = 1; + softs->ipf_sync_wrap = 0; + softs->sl_idx = 0; + softs->su_idx = 0; + softs->sl_tail = 0; + softs->su_tail = 0; + softs->ipf_sync_events = 0; + softs->ipf_sync_lastwakeup = 0; + + # if SOLARIS && defined(_KERNEL) - cv_init(&ipslwait, "ipsl condvar", CV_DRIVER, NULL); + cv_init(&softs->ipslwait, "ipsl condvar", CV_DRIVER, NULL); # endif + RWLOCK_INIT(&softs->ipf_syncstate, "add things to state sync table"); + RWLOCK_INIT(&softs->ipf_syncnat, "add things to nat sync table"); + MUTEX_INIT(&softs->ipf_syncadd, "add things to sync table"); + MUTEX_INIT(&softs->ipsl_mutex, "read ring lock"); - bzero((char *)syncnattab, sizeof(syncnattab)); - bzero((char *)syncstatetab, sizeof(syncstatetab)); + softs->ipf_sync_inited = 1; return 0; } +/* ------------------------------------------------------------------------ */ +/* Function: ipf_sync_unload */ +/* Returns: int - 0 == success, -1 == failure */ +/* Parameters: Nil */ +/* */ +/* Destroy the locks created when initialising and free any memory in use */ +/* with the synchronisation tables. */ +/* ------------------------------------------------------------------------ */ +int +ipf_sync_soft_fini(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_sync_softc_t *softs = arg; + + if (softs->syncnattab != NULL) { + ipf_sync_flush_table(softs, softs->ipf_sync_nat_tab_sz, + softs->syncnattab); + KFREES(softs->syncnattab, + softs->ipf_sync_nat_tab_sz * sizeof(*softs->syncnattab)); + softs->syncnattab = NULL; + } + + if (softs->syncstatetab != NULL) { + ipf_sync_flush_table(softs, softs->ipf_sync_state_tab_sz, + softs->syncstatetab); + KFREES(softs->syncstatetab, + softs->ipf_sync_state_tab_sz * + sizeof(*softs->syncstatetab)); + softs->syncstatetab = NULL; + } + + if (softs->syncupd != NULL) { + KFREES(softs->syncupd, + softs->ipf_sync_log_sz * sizeof(*softs->syncupd)); + softs->syncupd = NULL; + } + + if (softs->synclog != NULL) { + KFREES(softs->synclog, + softs->ipf_sync_log_sz * sizeof(*softs->synclog)); + softs->synclog = NULL; + } + + if (softs->ipf_sync_inited == 1) { + MUTEX_DESTROY(&softs->ipsl_mutex); + MUTEX_DESTROY(&softs->ipf_syncadd); + RW_DESTROY(&softs->ipf_syncnat); + RW_DESTROY(&softs->ipf_syncstate); + softs->ipf_sync_inited = 0; + } + + return 0; +} + +void +ipf_sync_soft_destroy(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_sync_softc_t *softs = arg; + + KFREE(softs); +} + + # if !defined(sparc) && !defined(__hppa) /* ------------------------------------------------------------------------ */ -/* Function: ipfsync_tcporder */ +/* Function: ipf_sync_tcporder */ /* Returns: Nil */ /* Parameters: way(I) - direction of byte order conversion. */ /* td(IO) - pointer to data to be converted. */ @@ -165,9 +316,10 @@ int ipfsync_init() /* Do byte swapping on values in the TCP state information structure that */ /* need to be used at both ends by the host in their native byte order. */ /* ------------------------------------------------------------------------ */ -void ipfsync_tcporder(way, td) -int way; -tcpdata_t *td; +void +ipf_sync_tcporder(way, td) + int way; + tcpdata_t *td; { if (way) { td->td_maxwin = htons(td->td_maxwin); @@ -182,7 +334,7 @@ tcpdata_t *td; /* ------------------------------------------------------------------------ */ -/* Function: ipfsync_natorder */ +/* Function: ipf_sync_natorder */ /* Returns: Nil */ /* Parameters: way(I) - direction of byte order conversion. */ /* nat(IO) - pointer to data to be converted. */ @@ -190,9 +342,10 @@ tcpdata_t *td; /* Do byte swapping on values in the NAT data structure that need to be */ /* used at both ends by the host in their native byte order. */ /* ------------------------------------------------------------------------ */ -void ipfsync_natorder(way, n) -int way; -nat_t *n; +void +ipf_sync_natorder(way, n) + int way; + nat_t *n; { if (way) { n->nat_age = htonl(n->nat_age); @@ -211,7 +364,7 @@ nat_t *n; /* ------------------------------------------------------------------------ */ -/* Function: ipfsync_storder */ +/* Function: ipf_sync_storder */ /* Returns: Nil */ /* Parameters: way(I) - direction of byte order conversion. */ /* ips(IO) - pointer to data to be converted. */ @@ -219,20 +372,23 @@ nat_t *n; /* Do byte swapping on values in the IP state data structure that need to */ /* be used at both ends by the host in their native byte order. */ /* ------------------------------------------------------------------------ */ -void ipfsync_storder(way, ips) -int way; -ipstate_t *ips; +void +ipf_sync_storder(way, ips) + int way; + ipstate_t *ips; { - ipfsync_tcporder(way, &ips->is_tcp.ts_data[0]); - ipfsync_tcporder(way, &ips->is_tcp.ts_data[1]); + ipf_sync_tcporder(way, &ips->is_tcp.ts_data[0]); + ipf_sync_tcporder(way, &ips->is_tcp.ts_data[1]); if (way) { ips->is_hv = htonl(ips->is_hv); ips->is_die = htonl(ips->is_die); ips->is_pass = htonl(ips->is_pass); ips->is_flags = htonl(ips->is_flags); - ips->is_opt = htonl(ips->is_opt); - ips->is_optmsk = htonl(ips->is_optmsk); + ips->is_opt[0] = htonl(ips->is_opt[0]); + ips->is_opt[1] = htonl(ips->is_opt[1]); + ips->is_optmsk[0] = htonl(ips->is_optmsk[0]); + ips->is_optmsk[1] = htonl(ips->is_optmsk[1]); ips->is_sec = htons(ips->is_sec); ips->is_secmsk = htons(ips->is_secmsk); ips->is_auth = htons(ips->is_auth); @@ -246,8 +402,10 @@ ipstate_t *ips; ips->is_die = ntohl(ips->is_die); ips->is_pass = ntohl(ips->is_pass); ips->is_flags = ntohl(ips->is_flags); - ips->is_opt = ntohl(ips->is_opt); - ips->is_optmsk = ntohl(ips->is_optmsk); + ips->is_opt[0] = ntohl(ips->is_opt[0]); + ips->is_opt[1] = ntohl(ips->is_opt[1]); + ips->is_optmsk[0] = ntohl(ips->is_optmsk[0]); + ips->is_optmsk[1] = ntohl(ips->is_optmsk[1]); ips->is_sec = ntohs(ips->is_sec); ips->is_secmsk = ntohs(ips->is_secmsk); ips->is_auth = ntohs(ips->is_auth); @@ -259,36 +417,37 @@ ipstate_t *ips; } } # else /* !defined(sparc) && !defined(__hppa) */ -# define ipfsync_tcporder(x,y) -# define ipfsync_natorder(x,y) -# define ipfsync_storder(x,y) +# define ipf_sync_tcporder(x,y) +# define ipf_sync_natorder(x,y) +# define ipf_sync_storder(x,y) # endif /* !defined(sparc) && !defined(__hppa) */ -/* enable this for debugging */ -# ifdef _KERNEL /* ------------------------------------------------------------------------ */ -/* Function: ipfsync_write */ +/* Function: ipf_sync_write */ /* Returns: int - 0 == success, else error value. */ /* Parameters: uio(I) - pointer to information about data to write */ /* */ /* Moves data from user space into the kernel and uses it for updating data */ /* structures in the state/NAT tables. */ /* ------------------------------------------------------------------------ */ -int ipfsync_write(uio) -struct uio *uio; +int +ipf_sync_write(softc, uio) + ipf_main_softc_t *softc; + struct uio *uio; { + ipf_sync_softc_t *softs = softc->ipf_sync_soft; synchdr_t sh; - /* + /* * THIS MUST BE SUFFICIENT LARGE TO STORE - * ANY POSSIBLE DATA TYPE + * ANY POSSIBLE DATA TYPE */ - char data[2048]; + char data[2048]; int err = 0; -# if (BSD >= 199306) || defined(__FreeBSD__) || defined(__osf__) +# if BSD_GE_YEAR(199306) || defined(__FreeBSD__) || defined(__osf__) uio->uio_rw = UIO_WRITE; # endif @@ -297,10 +456,10 @@ struct uio *uio; if (uio->uio_resid >= sizeof(sh)) { - err = UIOMOVE((caddr_t)&sh, sizeof(sh), UIO_WRITE, uio); + err = UIOMOVE(&sh, sizeof(sh), UIO_WRITE, uio); if (err) { - if (ipf_sync_debug > 2) + if (softs->ipf_sync_debug > 2) printf("uiomove(header) failed: %d\n", err); return err; @@ -311,94 +470,101 @@ struct uio *uio; sh.sm_len = ntohl(sh.sm_len); sh.sm_num = ntohl(sh.sm_num); - if (ipf_sync_debug > 8) + if (softs->ipf_sync_debug > 8) printf("[%d] Read v:%d p:%d cmd:%d table:%d rev:%d len:%d magic:%x\n", sh.sm_num, sh.sm_v, sh.sm_p, sh.sm_cmd, sh.sm_table, sh.sm_rev, sh.sm_len, sh.sm_magic); if (sh.sm_magic != SYNHDRMAGIC) { - if (ipf_sync_debug > 2) - printf("uiomove(header) invalud %s\n", + if (softs->ipf_sync_debug > 2) + printf("uiomove(header) invalid %s\n", "magic"); + IPFERROR(110001); return EINVAL; } if (sh.sm_v != 4 && sh.sm_v != 6) { - if (ipf_sync_debug > 2) + if (softs->ipf_sync_debug > 2) printf("uiomove(header) invalid %s\n", "protocol"); + IPFERROR(110002); return EINVAL; } if (sh.sm_cmd > SMC_MAXCMD) { - if (ipf_sync_debug > 2) + if (softs->ipf_sync_debug > 2) printf("uiomove(header) invalid %s\n", "command"); + IPFERROR(110003); return EINVAL; } if (sh.sm_table > SMC_MAXTBL) { - if (ipf_sync_debug > 2) + if (softs->ipf_sync_debug > 2) printf("uiomove(header) invalid %s\n", "table"); + IPFERROR(110004); return EINVAL; } } else { /* unsufficient data, wait until next call */ - if (ipf_sync_debug > 2) + if (softs->ipf_sync_debug > 2) printf("uiomove(header) insufficient data"); + IPFERROR(110005); return EAGAIN; } /* - * We have a header, so try to read the amount of data + * We have a header, so try to read the amount of data * needed for the request */ /* not supported */ if (sh.sm_len == 0) { - if (ipf_sync_debug > 2) + if (softs->ipf_sync_debug > 2) printf("uiomove(data zero length %s\n", "not supported"); + IPFERROR(110006); return EINVAL; } if (uio->uio_resid >= sh.sm_len) { - err = UIOMOVE((caddr_t)data, sh.sm_len, UIO_WRITE, uio); + err = UIOMOVE(data, sh.sm_len, UIO_WRITE, uio); if (err) { - if (ipf_sync_debug > 2) + if (softs->ipf_sync_debug > 2) printf("uiomove(data) failed: %d\n", err); return err; } - if (ipf_sync_debug > 7) + if (softs->ipf_sync_debug > 7) printf("uiomove(data) %d bytes read\n", sh.sm_len); if (sh.sm_table == SMC_STATE) - err = ipfsync_state(&sh, data); + err = ipf_sync_state(softc, &sh, data); else if (sh.sm_table == SMC_NAT) - err = ipfsync_nat(&sh, data); - if (ipf_sync_debug > 7) + err = ipf_sync_nat(softc, &sh, data); + if (softs->ipf_sync_debug > 7) printf("[%d] Finished with error %d\n", sh.sm_num, err); } else { /* insufficient data, wait until next call */ - if (ipf_sync_debug > 2) + if (softs->ipf_sync_debug > 2) printf("uiomove(data) %s %d bytes, got %d\n", "insufficient data, need", - sh.sm_len, uio->uio_resid); + sh.sm_len, (int)uio->uio_resid); + IPFERROR(110007); return EAGAIN; } - } + } /* no more data */ return 0; @@ -406,7 +572,7 @@ struct uio *uio; /* ------------------------------------------------------------------------ */ -/* Function: ipfsync_read */ +/* Function: ipf_sync_read */ /* Returns: int - 0 == success, else error value. */ /* Parameters: uio(O) - pointer to information about where to store data */ /* */ @@ -414,84 +580,105 @@ struct uio *uio; /* for pending state/NAT updates. If no data is available, the caller is */ /* put to sleep, pending a wakeup from the "lower half" of this code. */ /* ------------------------------------------------------------------------ */ -int ipfsync_read(uio) -struct uio *uio; +int +ipf_sync_read(softc, uio) + ipf_main_softc_t *softc; + struct uio *uio; { + ipf_sync_softc_t *softs = softc->ipf_sync_soft; syncupdent_t *su; synclogent_t *sl; int err = 0; - if ((uio->uio_resid & 3) || (uio->uio_resid < 8)) + if ((uio->uio_resid & 3) || (uio->uio_resid < 8)) { + IPFERROR(110008); return EINVAL; + } -# if (BSD >= 199306) || defined(__FreeBSD__) || defined(__osf__) +# if BSD_GE_YEAR(199306) || defined(__FreeBSD__) || defined(__osf__) uio->uio_rw = UIO_READ; # endif - MUTEX_ENTER(&ipsl_mutex); - while ((sl_tail == sl_idx) && (su_tail == su_idx)) { -# if SOLARIS && defined(_KERNEL) - if (!cv_wait_sig(&ipslwait, &ipsl_mutex)) { - MUTEX_EXIT(&ipsl_mutex); + MUTEX_ENTER(&softs->ipsl_mutex); + while ((softs->sl_tail == softs->sl_idx) && + (softs->su_tail == softs->su_idx)) { +# if defined(_KERNEL) +# if SOLARIS + if (!cv_wait_sig(&softs->ipslwait, &softs->ipsl_mutex.ipf_lk)) { + MUTEX_EXIT(&softs->ipsl_mutex); + IPFERROR(110009); return EINTR; } -# else -# ifdef __hpux +# else +# ifdef __hpux { lock_t *l; - l = get_sleep_lock(&sl_tail); - err = sleep(&sl_tail, PZERO+1); + l = get_sleep_lock(&softs->sl_tail); + err = sleep(&softs->sl_tail, PZERO+1); + if (err) { + MUTEX_EXIT(&softs->ipsl_mutex); + IPFERROR(110010); + return EINTR; + } spinunlock(l); } -# else /* __hpux */ -# ifdef __osf__ - err = mpsleep(&sl_tail, PSUSP|PCATCH, "ipl sleep", 0, - &ipsl_mutex, MS_LOCK_SIMPLE); -# else - MUTEX_EXIT(&ipsl_mutex); - err = SLEEP(&sl_tail, "ipl sleep"); -# endif /* __osf__ */ -# endif /* __hpux */ +# else /* __hpux */ +# ifdef __osf__ + err = mpsleep(&softs->sl_tail, PSUSP|PCATCH, "ipl sleep", 0, + &softs->ipsl_mutex, MS_LOCK_SIMPLE); if (err) { - MUTEX_EXIT(&ipsl_mutex); - return err; + IPFERROR(110011); + return EINTR; + } +# else + MUTEX_EXIT(&softs->ipsl_mutex); + err = SLEEP(&softs->sl_tail, "ipl sleep"); + if (err) { + IPFERROR(110012); + return EINTR; } -# endif /* SOLARIS */ + MUTEX_ENTER(&softs->ipsl_mutex); +# endif /* __osf__ */ +# endif /* __hpux */ +# endif /* SOLARIS */ +# endif /* _KERNEL */ } - MUTEX_EXIT(&ipsl_mutex); - READ_ENTER(&ipf_syncstate); - while ((sl_tail < sl_idx) && (uio->uio_resid > sizeof(*sl))) { - sl = synclog + sl_tail++; - err = UIOMOVE((caddr_t)sl, sizeof(*sl), UIO_READ, uio); + while ((softs->sl_tail < softs->sl_idx) && + (uio->uio_resid > sizeof(*sl))) { + sl = softs->synclog + softs->sl_tail++; + MUTEX_EXIT(&softs->ipsl_mutex); + err = UIOMOVE(sl, sizeof(*sl), UIO_READ, uio); if (err != 0) - break; + goto goterror; + MUTEX_ENTER(&softs->ipsl_mutex); } - while ((su_tail < su_idx) && (uio->uio_resid > sizeof(*su))) { - su = syncupd + su_tail; - su_tail++; - err = UIOMOVE((caddr_t)su, sizeof(*su), UIO_READ, uio); + while ((softs->su_tail < softs->su_idx) && + (uio->uio_resid > sizeof(*su))) { + su = softs->syncupd + softs->su_tail; + softs->su_tail++; + MUTEX_EXIT(&softs->ipsl_mutex); + err = UIOMOVE(su, sizeof(*su), UIO_READ, uio); if (err != 0) - break; + goto goterror; + MUTEX_ENTER(&softs->ipsl_mutex); if (su->sup_hdr.sm_sl != NULL) su->sup_hdr.sm_sl->sl_idx = -1; } - - MUTEX_ENTER(&ipf_syncadd); - if (su_tail == su_idx) - su_tail = su_idx = 0; - if (sl_tail == sl_idx) - sl_tail = sl_idx = 0; - MUTEX_EXIT(&ipf_syncadd); - RWLOCK_EXIT(&ipf_syncstate); + if (softs->sl_tail == softs->sl_idx) + softs->sl_tail = softs->sl_idx = 0; + if (softs->su_tail == softs->su_idx) + softs->su_tail = softs->su_idx = 0; + MUTEX_EXIT(&softs->ipsl_mutex); +goterror: return err; } /* ------------------------------------------------------------------------ */ -/* Function: ipfsync_state */ +/* Function: ipf_sync_state */ /* Returns: int - 0 == success, else error value. */ /* Parameters: sp(I) - pointer to sync packet data header */ /* uio(I) - pointer to user data for further information */ @@ -502,10 +689,13 @@ struct uio *uio; /* create a new state entry or update one. Deletion is left to the state */ /* structures being timed out correctly. */ /* ------------------------------------------------------------------------ */ -int ipfsync_state(sp, data) -synchdr_t *sp; -void *data; +static int +ipf_sync_state(softc, sp, data) + ipf_main_softc_t *softc; + synchdr_t *sp; + void *data; { + ipf_sync_softc_t *softs = softc->ipf_sync_soft; synctcp_update_t su; ipstate_t *is, sn; synclist_t *sl; @@ -513,7 +703,7 @@ void *data; u_int hv; int err = 0; - hv = sp->sm_num & (SYNC_STATETABSZ - 1); + hv = sp->sm_num & (softs->ipf_sync_state_tab_sz - 1); switch (sp->sm_cmd) { @@ -522,12 +712,14 @@ void *data; bcopy(data, &sn, sizeof(sn)); KMALLOC(is, ipstate_t *); if (is == NULL) { + IPFERROR(110013); err = ENOMEM; break; } KMALLOC(sl, synclist_t *); if (sl == NULL) { + IPFERROR(110014); err = ENOMEM; KFREE(is); break; @@ -536,23 +728,23 @@ void *data; bzero((char *)is, offsetof(ipstate_t, is_die)); bcopy((char *)&sn.is_die, (char *)&is->is_die, sizeof(*is) - offsetof(ipstate_t, is_die)); - ipfsync_storder(0, is); + ipf_sync_storder(0, is); /* * We need to find the same rule on the slave as was used on * the master to create this state entry. */ - READ_ENTER(&ipf_mutex); - fr = fr_getrulen(IPL_LOGIPF, sn.is_group, sn.is_rulen); + READ_ENTER(&softc->ipf_mutex); + fr = ipf_getrulen(softc, IPL_LOGIPF, sn.is_group, sn.is_rulen); if (fr != NULL) { MUTEX_ENTER(&fr->fr_lock); fr->fr_ref++; fr->fr_statecnt++; MUTEX_EXIT(&fr->fr_lock); } - RWLOCK_EXIT(&ipf_mutex); + RWLOCK_EXIT(&softc->ipf_mutex); - if (ipf_sync_debug > 4) + if (softs->ipf_sync_debug > 4) printf("[%d] Filter rules = %p\n", sp->sm_num, fr); is->is_rule = fr; @@ -562,16 +754,16 @@ void *data; sl->sl_ips = is; bcopy(sp, &sl->sl_hdr, sizeof(struct synchdr)); - WRITE_ENTER(&ipf_syncstate); - WRITE_ENTER(&ipf_state); + WRITE_ENTER(&softs->ipf_syncstate); + WRITE_ENTER(&softc->ipf_state); - sl->sl_pnext = syncstatetab + hv; - sl->sl_next = syncstatetab[hv]; - if (syncstatetab[hv] != NULL) - syncstatetab[hv]->sl_pnext = &sl->sl_next; - syncstatetab[hv] = sl; - MUTEX_DOWNGRADE(&ipf_syncstate); - fr_stinsert(is, sp->sm_rev); + sl->sl_pnext = softs->syncstatetab + hv; + sl->sl_next = softs->syncstatetab[hv]; + if (softs->syncstatetab[hv] != NULL) + softs->syncstatetab[hv]->sl_pnext = &sl->sl_next; + softs->syncstatetab[hv] = sl; + MUTEX_DOWNGRADE(&softs->ipf_syncstate); + ipf_state_insert(softc, is, sp->sm_rev); /* * Do not initialise the interface pointers for the state * entry as the full complement of interface names may not @@ -585,29 +777,31 @@ void *data; case SMC_UPDATE : bcopy(data, &su, sizeof(su)); - if (ipf_sync_debug > 4) + if (softs->ipf_sync_debug > 4) printf("[%d] Update age %lu state %d/%d \n", sp->sm_num, su.stu_age, su.stu_state[0], su.stu_state[1]); - READ_ENTER(&ipf_syncstate); - for (sl = syncstatetab[hv]; (sl != NULL); sl = sl->sl_next) + READ_ENTER(&softs->ipf_syncstate); + for (sl = softs->syncstatetab[hv]; (sl != NULL); + sl = sl->sl_next) if (sl->sl_hdr.sm_num == sp->sm_num) break; if (sl == NULL) { - if (ipf_sync_debug > 1) + if (softs->ipf_sync_debug > 1) printf("[%d] State not found - can't update\n", sp->sm_num); - RWLOCK_EXIT(&ipf_syncstate); + RWLOCK_EXIT(&softs->ipf_syncstate); + IPFERROR(110015); err = ENOENT; break; } - READ_ENTER(&ipf_state); + READ_ENTER(&softc->ipf_state); - if (ipf_sync_debug > 6) - printf("[%d] Data from state v:%d p:%d cmd:%d table:%d rev:%d\n", - sp->sm_num, sl->sl_hdr.sm_v, sl->sl_hdr.sm_p, + if (softs->ipf_sync_debug > 6) + printf("[%d] Data from state v:%d p:%d cmd:%d table:%d rev:%d\n", + sp->sm_num, sl->sl_hdr.sm_v, sl->sl_hdr.sm_p, sl->sl_hdr.sm_cmd, sl->sl_hdr.sm_table, sl->sl_hdr.sm_rev); @@ -631,56 +825,97 @@ void *data; break; } - if (ipf_sync_debug > 6) + if (softs->ipf_sync_debug > 6) printf("[%d] Setting timers for state\n", sp->sm_num); - fr_setstatequeue(is, sp->sm_rev); + ipf_state_setqueue(softc, is, sp->sm_rev); MUTEX_EXIT(&is->is_lock); break; default : + IPFERROR(110016); err = EINVAL; break; } if (err == 0) { - RWLOCK_EXIT(&ipf_state); - RWLOCK_EXIT(&ipf_syncstate); + RWLOCK_EXIT(&softc->ipf_state); + RWLOCK_EXIT(&softs->ipf_syncstate); } - if (ipf_sync_debug > 6) + if (softs->ipf_sync_debug > 6) printf("[%d] Update completed with error %d\n", sp->sm_num, err); return err; } -# endif /* _KERNEL */ /* ------------------------------------------------------------------------ */ -/* Function: ipfsync_del */ +/* Function: ipf_sync_del */ /* Returns: Nil */ /* Parameters: sl(I) - pointer to synclist object to delete */ /* */ -/* Deletes an object from the synclist table and free's its memory. */ +/* Deletes an object from the synclist. */ /* ------------------------------------------------------------------------ */ -void ipfsync_del(sl) -synclist_t *sl; +static void +ipf_sync_del(softs, sl) + ipf_sync_softc_t *softs; + synclist_t *sl; { - WRITE_ENTER(&ipf_syncstate); *sl->sl_pnext = sl->sl_next; if (sl->sl_next != NULL) sl->sl_next->sl_pnext = sl->sl_pnext; if (sl->sl_idx != -1) - syncupd[sl->sl_idx].sup_hdr.sm_sl = NULL; - RWLOCK_EXIT(&ipf_syncstate); + softs->syncupd[sl->sl_idx].sup_hdr.sm_sl = NULL; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_sync_del_state */ +/* Returns: Nil */ +/* Parameters: sl(I) - pointer to synclist object to delete */ +/* */ +/* Deletes an object from the synclist state table and free's its memory. */ +/* ------------------------------------------------------------------------ */ +void +ipf_sync_del_state(arg, sl) + void *arg; + synclist_t *sl; +{ + ipf_sync_softc_t *softs = arg; + + WRITE_ENTER(&softs->ipf_syncstate); + ipf_sync_del(softs, sl); + RWLOCK_EXIT(&softs->ipf_syncstate); KFREE(sl); } /* ------------------------------------------------------------------------ */ -/* Function: ipfsync_nat */ +/* Function: ipf_sync_del_nat */ +/* Returns: Nil */ +/* Parameters: sl(I) - pointer to synclist object to delete */ +/* */ +/* Deletes an object from the synclist nat table and free's its memory. */ +/* ------------------------------------------------------------------------ */ +void +ipf_sync_del_nat(arg, sl) + void *arg; + synclist_t *sl; +{ + ipf_sync_softc_t *softs = arg; + + WRITE_ENTER(&softs->ipf_syncnat); + ipf_sync_del(softs, sl); + RWLOCK_EXIT(&softs->ipf_syncnat); + KFREE(sl); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_sync_nat */ /* Returns: int - 0 == success, else error value. */ /* Parameters: sp(I) - pointer to sync packet data header */ /* uio(I) - pointer to user data for further information */ @@ -691,94 +926,100 @@ synclist_t *sl; /* create a new NAT entry or update one. Deletion is left to the NAT */ /* structures being timed out correctly. */ /* ------------------------------------------------------------------------ */ -int ipfsync_nat(sp, data) -synchdr_t *sp; -void *data; +static int +ipf_sync_nat(softc, sp, data) + ipf_main_softc_t *softc; + synchdr_t *sp; + void *data; { - synclogent_t sle; + ipf_sync_softc_t *softs = softc->ipf_sync_soft; syncupdent_t su; nat_t *n, *nat; synclist_t *sl; u_int hv = 0; int err; - READ_ENTER(&ipf_syncstate); + READ_ENTER(&softs->ipf_syncnat); switch (sp->sm_cmd) { case SMC_CREATE : - bcopy(data, &sle, sizeof(sle)); - KMALLOC(n, nat_t *); if (n == NULL) { + IPFERROR(110017); err = ENOMEM; break; } KMALLOC(sl, synclist_t *); if (sl == NULL) { + IPFERROR(110018); err = ENOMEM; KFREE(n); break; } - WRITE_ENTER(&ipf_nat); - - nat = &sle.sle_un.sleu_ipn; + nat = (nat_t *)data; bzero((char *)n, offsetof(nat_t, nat_age)); bcopy((char *)&nat->nat_age, (char *)&n->nat_age, sizeof(*n) - offsetof(nat_t, nat_age)); - ipfsync_natorder(0, n); + ipf_sync_natorder(0, n); n->nat_sync = sl; + n->nat_rev = sl->sl_rev; sl->sl_idx = -1; sl->sl_ipn = n; sl->sl_num = ntohl(sp->sm_num); - sl->sl_pnext = syncstatetab + hv; - sl->sl_next = syncstatetab[hv]; - if (syncstatetab[hv] != NULL) - syncstatetab[hv]->sl_pnext = &sl->sl_next; - syncstatetab[hv] = sl; - nat_insert(n, sl->sl_rev); - RWLOCK_EXIT(&ipf_nat); + + WRITE_ENTER(&softc->ipf_nat); + sl->sl_pnext = softs->syncnattab + hv; + sl->sl_next = softs->syncnattab[hv]; + if (softs->syncnattab[hv] != NULL) + softs->syncnattab[hv]->sl_pnext = &sl->sl_next; + softs->syncnattab[hv] = sl; + (void) ipf_nat_insert(softc, softc->ipf_nat_soft, n); + RWLOCK_EXIT(&softc->ipf_nat); break; case SMC_UPDATE : bcopy(data, &su, sizeof(su)); - READ_ENTER(&ipf_syncstate); - for (sl = syncstatetab[hv]; (sl != NULL); sl = sl->sl_next) + for (sl = softs->syncnattab[hv]; (sl != NULL); + sl = sl->sl_next) if (sl->sl_hdr.sm_num == sp->sm_num) break; if (sl == NULL) { + IPFERROR(110019); err = ENOENT; break; } - READ_ENTER(&ipf_nat); + READ_ENTER(&softc->ipf_nat); nat = sl->sl_ipn; + nat->nat_rev = sl->sl_rev; MUTEX_ENTER(&nat->nat_lock); - fr_setnatqueue(nat, sl->sl_rev); + ipf_nat_setqueue(softc, softc->ipf_nat_soft, nat); MUTEX_EXIT(&nat->nat_lock); - RWLOCK_EXIT(&ipf_nat); + RWLOCK_EXIT(&softc->ipf_nat); break; default : + IPFERROR(110020); err = EINVAL; break; } - RWLOCK_EXIT(&ipf_syncstate); + RWLOCK_EXIT(&softs->ipf_syncnat); return 0; } /* ------------------------------------------------------------------------ */ -/* Function: ipfsync_new */ +/* Function: ipf_sync_new */ /* Returns: synclist_t* - NULL == failure, else pointer to new synclist */ /* data structure. */ /* Parameters: tab(I) - type of synclist_t to create */ @@ -788,43 +1029,36 @@ void *data; /* Creates a new sync table entry and notifies any sleepers that it's there */ /* waiting to be processed. */ /* ------------------------------------------------------------------------ */ -synclist_t *ipfsync_new(tab, fin, ptr) -int tab; -fr_info_t *fin; -void *ptr; +synclist_t * +ipf_sync_new(softc, tab, fin, ptr) + ipf_main_softc_t *softc; + int tab; + fr_info_t *fin; + void *ptr; { + ipf_sync_softc_t *softs = softc->ipf_sync_soft; synclist_t *sl, *ss; synclogent_t *sle; u_int hv, sz; - if (sl_idx == SYNCLOG_SZ) + if (softs->sl_idx == softs->ipf_sync_log_sz) return NULL; KMALLOC(sl, synclist_t *); if (sl == NULL) return NULL; - MUTEX_ENTER(&ipf_syncadd); + MUTEX_ENTER(&softs->ipf_syncadd); /* * Get a unique number for this synclist_t. The number is only meant * to be unique for the lifetime of the structure and may be reused * later. */ - ipf_syncnum++; - if (ipf_syncnum == 0) { - ipf_syncnum = 1; - ipf_syncwrap = 1; + softs->ipf_sync_num++; + if (softs->ipf_sync_num == 0) { + softs->ipf_sync_num = 1; + softs->ipf_sync_wrap++; } - hv = ipf_syncnum & (SYNC_STATETABSZ - 1); - while (ipf_syncwrap != 0) { - for (ss = syncstatetab[hv]; ss; ss = ss->sl_next) - if (ss->sl_hdr.sm_num == ipf_syncnum) - break; - if (ss == NULL) - break; - ipf_syncnum++; - hv = ipf_syncnum & (SYNC_STATETABSZ - 1); - } /* * Use the synch number of the object as the hash key. Should end up * with relatively even distribution over time. @@ -833,11 +1067,48 @@ void *ptr; * nth connection they make, where n is a value in the interval * [0, SYNC_STATETABSZ-1]. */ - sl->sl_pnext = syncstatetab + hv; - sl->sl_next = syncstatetab[hv]; - syncstatetab[hv] = sl; - sl->sl_num = ipf_syncnum; - MUTEX_EXIT(&ipf_syncadd); + switch (tab) + { + case SMC_STATE : + hv = softs->ipf_sync_num & (softs->ipf_sync_state_tab_sz - 1); + while (softs->ipf_sync_wrap != 0) { + for (ss = softs->syncstatetab[hv]; ss; ss = ss->sl_next) + if (ss->sl_hdr.sm_num == softs->ipf_sync_num) + break; + if (ss == NULL) + break; + softs->ipf_sync_num++; + hv = softs->ipf_sync_num & + (softs->ipf_sync_state_tab_sz - 1); + } + sl->sl_pnext = softs->syncstatetab + hv; + sl->sl_next = softs->syncstatetab[hv]; + softs->syncstatetab[hv] = sl; + break; + + case SMC_NAT : + hv = softs->ipf_sync_num & (softs->ipf_sync_nat_tab_sz - 1); + while (softs->ipf_sync_wrap != 0) { + for (ss = softs->syncnattab[hv]; ss; ss = ss->sl_next) + if (ss->sl_hdr.sm_num == softs->ipf_sync_num) + break; + if (ss == NULL) + break; + softs->ipf_sync_num++; + hv = softs->ipf_sync_num & + (softs->ipf_sync_nat_tab_sz - 1); + } + sl->sl_pnext = softs->syncnattab + hv; + sl->sl_next = softs->syncnattab[hv]; + softs->syncnattab[hv] = sl; + break; + + default : + break; + } + + sl->sl_num = softs->ipf_sync_num; + MUTEX_EXIT(&softs->ipf_syncadd); sl->sl_magic = htonl(SYNHDRMAGIC); sl->sl_v = fin->fin_v; @@ -862,8 +1133,8 @@ void *ptr; * Create the log entry to be read by a user daemon. When it has been * finished and put on the queue, send a signal to wakeup any waiters. */ - MUTEX_ENTER(&ipf_syncadd); - sle = synclog + sl_idx++; + MUTEX_ENTER(&softs->ipf_syncadd); + sle = softs->synclog + softs->sl_idx++; bcopy((char *)&sl->sl_hdr, (char *)&sle->sle_hdr, sizeof(sle->sle_hdr)); sle->sle_hdr.sm_num = htonl(sle->sle_hdr.sm_num); @@ -871,31 +1142,20 @@ void *ptr; if (ptr != NULL) { bcopy((char *)ptr, (char *)&sle->sle_un, sz); if (tab == SMC_STATE) { - ipfsync_storder(1, &sle->sle_un.sleu_ips); + ipf_sync_storder(1, &sle->sle_un.sleu_ips); } else if (tab == SMC_NAT) { - ipfsync_natorder(1, &sle->sle_un.sleu_ipn); + ipf_sync_natorder(1, &sle->sle_un.sleu_ipn); } } - MUTEX_EXIT(&ipf_syncadd); + MUTEX_EXIT(&softs->ipf_syncadd); - MUTEX_ENTER(&ipsl_mutex); -# if SOLARIS -# ifdef _KERNEL - cv_signal(&ipslwait); -# endif - MUTEX_EXIT(&ipsl_mutex); -# else - MUTEX_EXIT(&ipsl_mutex); -# ifdef _KERNEL - wakeup(&sl_tail); -# endif -# endif + ipf_sync_wakeup(softc); return sl; } /* ------------------------------------------------------------------------ */ -/* Function: ipfsync_update */ +/* Function: ipf_sync_update */ /* Returns: Nil */ /* Parameters: tab(I) - type of synclist_t to create */ /* fin(I) - pointer to packet information */ @@ -904,24 +1164,36 @@ void *ptr; /* For outbound packets, only, create an sync update record for the user */ /* process to read. */ /* ------------------------------------------------------------------------ */ -void ipfsync_update(tab, fin, sl) -int tab; -fr_info_t *fin; -synclist_t *sl; +void +ipf_sync_update(softc, tab, fin, sl) + ipf_main_softc_t *softc; + int tab; + fr_info_t *fin; + synclist_t *sl; { + ipf_sync_softc_t *softs = softc->ipf_sync_soft; synctcp_update_t *st; syncupdent_t *slu; ipstate_t *ips; nat_t *nat; + ipfrwlock_t *lock; if (fin->fin_out == 0 || sl == NULL) return; - WRITE_ENTER(&ipf_syncstate); - MUTEX_ENTER(&ipf_syncadd); + if (tab == SMC_STATE) { + lock = &softs->ipf_syncstate; + } else { + lock = &softs->ipf_syncnat; + } + + READ_ENTER(lock); if (sl->sl_idx == -1) { - slu = syncupd + su_idx; - sl->sl_idx = su_idx++; + MUTEX_ENTER(&softs->ipf_syncadd); + slu = softs->syncupd + softs->su_idx; + sl->sl_idx = softs->su_idx++; + MUTEX_EXIT(&softs->ipf_syncadd); + bcopy((char *)&sl->sl_hdr, (char *)&slu->sup_hdr, sizeof(slu->sup_hdr)); slu->sup_hdr.sm_magic = htonl(SYNHDRMAGIC); @@ -938,9 +1210,7 @@ synclist_t *sl; } # endif } else - slu = syncupd + sl->sl_idx; - MUTEX_EXIT(&ipf_syncadd); - MUTEX_DOWNGRADE(&ipf_syncstate); + slu = softs->syncupd + sl->sl_idx; /* * Only TCP has complex timeouts, others just use default timeouts. @@ -964,25 +1234,61 @@ synclist_t *sl; st->stu_age = htonl(nat->nat_age); } } - RWLOCK_EXIT(&ipf_syncstate); + RWLOCK_EXIT(lock); - MUTEX_ENTER(&ipsl_mutex); -# if SOLARIS -# ifdef _KERNEL - cv_signal(&ipslwait); -# endif - MUTEX_EXIT(&ipsl_mutex); -# else - MUTEX_EXIT(&ipsl_mutex); -# ifdef _KERNEL - wakeup(&sl_tail); -# endif -# endif + ipf_sync_wakeup(softc); } /* ------------------------------------------------------------------------ */ -/* Function: fr_sync_ioctl */ +/* Function: ipf_sync_flush_table */ +/* Returns: int - number of entries freed by flushing table */ +/* Parameters: tabsize(I) - size of the array pointed to by table */ +/* table(I) - pointer to sync table to empty */ +/* */ +/* Walk through a table of sync entries and free each one. It is assumed */ +/* that some lock is held so that nobody else tries to access the table */ +/* during this cleanup. */ +/* ------------------------------------------------------------------------ */ +static int +ipf_sync_flush_table(softs, tabsize, table) + ipf_sync_softc_t *softs; + int tabsize; + synclist_t **table; +{ + synclist_t *sl; + int i, items; + + items = 0; + + for (i = 0; i < tabsize; i++) { + while ((sl = table[i]) != NULL) { + switch (sl->sl_table) { + case SMC_STATE : + if (sl->sl_ips != NULL) + sl->sl_ips->is_sync = NULL; + break; + case SMC_NAT : + if (sl->sl_ipn != NULL) + sl->sl_ipn->nat_sync = NULL; + break; + } + if (sl->sl_next != NULL) + sl->sl_next->sl_pnext = sl->sl_pnext; + table[i] = sl->sl_next; + if (sl->sl_idx != -1) + softs->syncupd[sl->sl_idx].sup_hdr.sm_sl = NULL; + KFREE(sl); + items++; + } + } + + return items; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_sync_ioctl */ /* Returns: int - 0 == success, != 0 == failure */ /* Parameters: data(I) - pointer to ioctl data */ /* cmd(I) - ioctl command integer */ @@ -991,11 +1297,199 @@ synclist_t *sl; /* This function currently does not handle any ioctls and so just returns */ /* EINVAL on all occasions. */ /* ------------------------------------------------------------------------ */ -int fr_sync_ioctl(data, cmd, mode) -caddr_t data; -ioctlcmd_t cmd; -int mode; +int +ipf_sync_ioctl(softc, data, cmd, mode, uid, ctx) + ipf_main_softc_t *softc; + caddr_t data; + ioctlcmd_t cmd; + int mode, uid; + void *ctx; { - return EINVAL; + ipf_sync_softc_t *softs = softc->ipf_sync_soft; + int error, i; + SPL_INT(s); + + switch (cmd) + { + case SIOCIPFFL: + error = BCOPYIN(data, &i, sizeof(i)); + if (error != 0) { + IPFERROR(110023); + error = EFAULT; + break; + } + + switch (i) + { + case SMC_RLOG : + SPL_NET(s); + MUTEX_ENTER(&softs->ipsl_mutex); + i = (softs->sl_tail - softs->sl_idx) + + (softs->su_tail - softs->su_idx); + softs->sl_idx = 0; + softs->su_idx = 0; + softs->sl_tail = 0; + softs->su_tail = 0; + MUTEX_EXIT(&softs->ipsl_mutex); + SPL_X(s); + break; + + case SMC_NAT : + SPL_NET(s); + WRITE_ENTER(&softs->ipf_syncnat); + i = ipf_sync_flush_table(softs, SYNC_NATTABSZ, + softs->syncnattab); + RWLOCK_EXIT(&softs->ipf_syncnat); + SPL_X(s); + break; + + case SMC_STATE : + SPL_NET(s); + WRITE_ENTER(&softs->ipf_syncstate); + i = ipf_sync_flush_table(softs, SYNC_STATETABSZ, + softs->syncstatetab); + RWLOCK_EXIT(&softs->ipf_syncstate); + SPL_X(s); + break; + } + + error = BCOPYOUT(&i, data, sizeof(i)); + if (error != 0) { + IPFERROR(110022); + error = EFAULT; + } + break; + + default : + IPFERROR(110021); + error = EINVAL; + break; + } + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_sync_canread */ +/* Returns: int - 0 == success, != 0 == failure */ +/* Parameters: Nil */ +/* */ +/* This function provides input to the poll handler about whether or not */ +/* there is data waiting to be read from the /dev/ipsync device. */ +/* ------------------------------------------------------------------------ */ +int +ipf_sync_canread(arg) + void *arg; +{ + ipf_sync_softc_t *softs = arg; + return !((softs->sl_tail == softs->sl_idx) && + (softs->su_tail == softs->su_idx)); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_sync_canwrite */ +/* Returns: int - 1 == can always write */ +/* Parameters: Nil */ +/* */ +/* This function lets the poll handler know that it is always ready willing */ +/* to accept write events. */ +/* XXX Maybe this should return false if the sync table is full? */ +/* ------------------------------------------------------------------------ */ +int +ipf_sync_canwrite(arg) + void *arg; +{ + return 1; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_sync_wakeup */ +/* Parameters: Nil */ +/* Returns: Nil */ +/* */ +/* This function implements the heuristics that decide how often to */ +/* generate a poll wakeup for programs that are waiting for information */ +/* about when they can do a read on /dev/ipsync. */ +/* */ +/* There are three different considerations here: */ +/* - do not keep a program waiting too long: ipf_sync_wake_interval is the */ +/* maximum number of ipf ticks to let pass by; */ +/* - do not let the queue of ouststanding things to generate notifies for */ +/* get too full (ipf_sync_queue_high_wm is the high water mark); */ +/* - do not let too many events get collapsed in before deciding that the */ +/* other host(s) need an update (ipf_sync_event_high_wm is the high water */ +/* mark for this counter.) */ +/* ------------------------------------------------------------------------ */ +static void +ipf_sync_wakeup(softc) + ipf_main_softc_t *softc; +{ + ipf_sync_softc_t *softs = softc->ipf_sync_soft; + + softs->ipf_sync_events++; + if ((softc->ipf_ticks > + softs->ipf_sync_lastwakeup + softs->ipf_sync_wake_interval) || + (softs->ipf_sync_events > softs->ipf_sync_event_high_wm) || + ((softs->sl_tail - softs->sl_idx) > + softs->ipf_sync_queue_high_wm) || + ((softs->su_tail - softs->su_idx) > + softs->ipf_sync_queue_high_wm)) { + + ipf_sync_poll_wakeup(softc); + } +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_sync_poll_wakeup */ +/* Parameters: Nil */ +/* Returns: Nil */ +/* */ +/* Deliver a poll wakeup and reset counters for two of the three heuristics */ +/* ------------------------------------------------------------------------ */ +static void +ipf_sync_poll_wakeup(softc) + ipf_main_softc_t *softc; +{ + ipf_sync_softc_t *softs = softc->ipf_sync_soft; + + softs->ipf_sync_events = 0; + softs->ipf_sync_lastwakeup = softc->ipf_ticks; + +# ifdef _KERNEL +# if SOLARIS + MUTEX_ENTER(&softs->ipsl_mutex); + cv_signal(&softs->ipslwait); + MUTEX_EXIT(&softs->ipsl_mutex); + pollwakeup(&softc->ipf_poll_head[IPL_LOGSYNC], POLLIN|POLLRDNORM); +# else + WAKEUP(&softs->sl_tail, 0); + POLLWAKEUP(IPL_LOGSYNC); +# endif +# endif +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_sync_expire */ +/* Parameters: Nil */ +/* Returns: Nil */ +/* */ +/* This is the function called even ipf_tick. It implements one of the */ +/* three heuristics above *IF* there are events waiting. */ +/* ------------------------------------------------------------------------ */ +void +ipf_sync_expire(softc) + ipf_main_softc_t *softc; +{ + ipf_sync_softc_t *softs = softc->ipf_sync_soft; + + if ((softs->ipf_sync_events > 0) && + (softc->ipf_ticks > + softs->ipf_sync_lastwakeup + softs->ipf_sync_wake_interval)) { + ipf_sync_poll_wakeup(softc); + } } -#endif /* IPFILTER_SYNC */ diff --git a/ip_sync.h b/ip_sync.h index e319a95dfcdb8..d9d6d41046e80 100644 --- a/ip_sync.h +++ b/ip_sync.h @@ -1,12 +1,10 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_fil.h 1.35 6/5/96 - * Id: ip_sync.h,v 2.11.2.2 2004/11/04 19:29:07 darrenr Exp + * $Id$ */ #ifndef __IP_SYNC_H__ @@ -38,6 +36,7 @@ typedef struct synchdr { /* * Tables */ +#define SMC_RLOG -2 /* Only used with SIOCIPFFL */ #define SMC_NAT 0 #define SMC_STATE 1 #define SMC_MAXTBL 1 @@ -101,17 +100,22 @@ typedef struct syncupdent { /* 28 or 32 bytes */ struct synctcp_update sup_tcp; } syncupdent_t; -extern synclogent_t synclog[SYNCLOG_SZ]; - - -extern int fr_sync_ioctl __P((caddr_t, ioctlcmd_t, int)); -extern synclist_t *ipfsync_new __P((int, fr_info_t *, void *)); -extern void ipfsync_del __P((synclist_t *)); -extern void ipfsync_update __P((int, fr_info_t *, synclist_t *)); -extern int ipfsync_init __P((void)); -extern int ipfsync_nat __P((synchdr_t *sp, void *data)); -extern int ipfsync_state __P((synchdr_t *sp, void *data)); -extern int ipfsync_read __P((struct uio *uio)); -extern int ipfsync_write __P((struct uio *uio)); - -#endif /* IP_SYNC */ +extern void *ipf_sync_create __P((ipf_main_softc_t *)); +extern int ipf_sync_soft_init __P((ipf_main_softc_t *, void *)); +extern int ipf_sync_soft_fini __P((ipf_main_softc_t *, void *)); +extern int ipf_sync_canread __P((void *)); +extern int ipf_sync_canwrite __P((void *)); +extern void ipf_sync_del_nat __P((void *, synclist_t *)); +extern void ipf_sync_del_state __P((void *, synclist_t *)); +extern int ipf_sync_init __P((void)); +extern int ipf_sync_ioctl __P((ipf_main_softc_t *, caddr_t, ioctlcmd_t, int, int, void *)); +extern synclist_t *ipf_sync_new __P((ipf_main_softc_t *, int, fr_info_t *, void *)); +extern int ipf_sync_read __P((ipf_main_softc_t *, struct uio *uio)); +extern int ipf_sync_write __P((ipf_main_softc_t *, struct uio *uio)); +extern int ipf_sync_main_unload __P((void)); +extern void ipf_sync_update __P((ipf_main_softc_t *, int, fr_info_t *, synclist_t *)); +extern void ipf_sync_expire __P((ipf_main_softc_t *)); +extern void ipf_sync_soft_destroy __P((ipf_main_softc_t *, void *)); +extern void *ipf_sync_soft_create __P((ipf_main_softc_t *)); + +#endif /* __IP_SYNC_H__ */ diff --git a/ip_tftp_pxy.c b/ip_tftp_pxy.c new file mode 100644 index 0000000000000..67fb9f82d5b14 --- /dev/null +++ b/ip_tftp_pxy.c @@ -0,0 +1,506 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: ip_tftp_pxy.c,v 1.1.2.9 2012/07/22 08:04:23 darren_r Exp $ + */ + +#define IPF_TFTP_PROXY + +typedef struct ipf_tftp_softc_s { + int ipf_p_tftp_readonly; + ipftuneable_t *ipf_p_tftp_tune; +} ipf_tftp_softc_t; + +int ipf_p_tftp_backchannel __P((fr_info_t *, ap_session_t *, nat_t *)); +int ipf_p_tftp_client __P((ipf_tftp_softc_t *, fr_info_t *, ap_session_t *, + nat_t *)); +int ipf_p_tftp_in __P((void *, fr_info_t *, ap_session_t *, nat_t *)); +void ipf_p_tftp_main_load __P((void)); +void ipf_p_tftp_main_unload __P((void)); +int ipf_p_tftp_new __P((void *, fr_info_t *, ap_session_t *, nat_t *)); +void ipf_p_tftp_del __P((ipf_main_softc_t *, ap_session_t *)); +int ipf_p_tftp_out __P((void *, fr_info_t *, ap_session_t *, nat_t *)); +int ipf_p_tftp_server __P((ipf_tftp_softc_t *, fr_info_t *, ap_session_t *, + nat_t *)); +void *ipf_p_tftp_soft_create __P((ipf_main_softc_t *)); +void ipf_p_tftp_soft_destroy __P((ipf_main_softc_t *, void *)); + +static frentry_t tftpfr; +static int tftp_proxy_init = 0; + +typedef enum tftp_cmd_e { + TFTP_CMD_READ = 1, + TFTP_CMD_WRITE = 2, + TFTP_CMD_DATA = 3, + TFTP_CMD_ACK = 4, + TFTP_CMD_ERROR = 5 +} tftp_cmd_t; + +typedef struct tftpinfo { + tftp_cmd_t ti_lastcmd; + int ti_nextblk; + int ti_lastblk; + int ti_lasterror; + char ti_filename[80]; + ipnat_t *ti_rule; +} tftpinfo_t; + +static ipftuneable_t ipf_tftp_tuneables[] = { + { { (void *)offsetof(ipf_tftp_softc_t, ipf_p_tftp_readonly) }, + "tftp_read_only", 0, 1, + stsizeof(ipf_tftp_softc_t, ipf_p_tftp_readonly), + 0, NULL, NULL }, + { { NULL }, NULL, 0, 0, 0, 0, NULL, NULL } +}; + + +/* + * TFTP application proxy initialization. + */ +void +ipf_p_tftp_main_load() +{ + + bzero((char *)&tftpfr, sizeof(tftpfr)); + tftpfr.fr_ref = 1; + tftpfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE; + MUTEX_INIT(&tftpfr.fr_lock, "TFTP proxy rule lock"); + tftp_proxy_init = 1; +} + + +void +ipf_p_tftp_main_unload() +{ + + if (tftp_proxy_init == 1) { + MUTEX_DESTROY(&tftpfr.fr_lock); + tftp_proxy_init = 0; + } +} + + +void * +ipf_p_tftp_soft_create(softc) + ipf_main_softc_t *softc; +{ + ipf_tftp_softc_t *softt; + + KMALLOC(softt, ipf_tftp_softc_t *); + if (softt == NULL) + return NULL; + + bzero((char *)softt, sizeof(*softt)); + + softt->ipf_p_tftp_tune = ipf_tune_array_copy(softt, + sizeof(ipf_tftp_tuneables), + ipf_tftp_tuneables); + if (softt->ipf_p_tftp_tune == NULL) { + ipf_p_tftp_soft_destroy(softc, softt); + return NULL; + } + if (ipf_tune_array_link(softc, softt->ipf_p_tftp_tune) == -1) { + ipf_p_tftp_soft_destroy(softc, softt); + return NULL; + } + + softt->ipf_p_tftp_readonly = 1; + + return softt; +} + + +void +ipf_p_tftp_soft_destroy(softc, arg) + ipf_main_softc_t *softc; + void *arg; +{ + ipf_tftp_softc_t *softt = arg; + + if (softt->ipf_p_tftp_tune != NULL) { + ipf_tune_array_unlink(softc, softt->ipf_p_tftp_tune); + KFREES(softt->ipf_p_tftp_tune, sizeof(ipf_tftp_tuneables)); + softt->ipf_p_tftp_tune = NULL; + } + + KFREE(softt); +} + + +int +ipf_p_tftp_out(arg, fin, aps, nat) + void *arg; + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; +{ + ipf_tftp_softc_t *softt = arg; + + fin->fin_flx |= FI_NOWILD; + if (nat->nat_dir == NAT_OUTBOUND) + return ipf_p_tftp_client(softt, fin, aps, nat); + return ipf_p_tftp_server(softt, fin, aps, nat); +} + + +int +ipf_p_tftp_in(arg, fin, aps, nat) + void *arg; + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; +{ + ipf_tftp_softc_t *softt = arg; + + fin->fin_flx |= FI_NOWILD; + if (nat->nat_dir == NAT_INBOUND) + return ipf_p_tftp_client(softt, fin, aps, nat); + return ipf_p_tftp_server(softt, fin, aps, nat); +} + + +int +ipf_p_tftp_new(arg, fin, aps, nat) + void *arg; + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; +{ + udphdr_t *udp; + tftpinfo_t *ti; + ipnat_t *ipn; + ipnat_t *np; + int size; + + fin = fin; /* LINT */ + + np = nat->nat_ptr; + size = np->in_size; + + KMALLOC(ti, tftpinfo_t *); + if (ti == NULL) + return -1; + KMALLOCS(ipn, ipnat_t *, size); + if (ipn == NULL) { + KFREE(ti); + return -1; + } + + aps->aps_data = ti; + aps->aps_psiz = sizeof(*ti); + bzero((char *)ti, sizeof(*ti)); + bzero((char *)ipn, size); + ti->ti_rule = ipn; + + udp = (udphdr_t *)fin->fin_dp; + aps->aps_sport = udp->uh_sport; + aps->aps_dport = udp->uh_dport; + + ipn->in_size = size; + ipn->in_apr = NULL; + ipn->in_use = 1; + ipn->in_hits = 1; + ipn->in_ippip = 1; + ipn->in_pr[0] = IPPROTO_UDP; + ipn->in_pr[1] = IPPROTO_UDP; + ipn->in_ifps[0] = nat->nat_ifps[0]; + ipn->in_ifps[1] = nat->nat_ifps[1]; + ipn->in_v[0] = nat->nat_ptr->in_v[1]; + ipn->in_v[1] = nat->nat_ptr->in_v[0]; + ipn->in_flags = IPN_UDP|IPN_FIXEDDPORT|IPN_PROXYRULE; + + ipn->in_nsrcip6 = nat->nat_odst6; + ipn->in_osrcip6 = nat->nat_ndst6; + + if ((np->in_redir & NAT_REDIRECT) != 0) { + ipn->in_redir = NAT_MAP; + if (ipn->in_v[0] == 4) { + ipn->in_snip = ntohl(nat->nat_odstaddr); + ipn->in_dnip = ntohl(nat->nat_nsrcaddr); + } else { +#ifdef USE_INET6 + ipn->in_snip6 = nat->nat_odst6; + ipn->in_dnip6 = nat->nat_nsrc6; +#endif + } + ipn->in_ndstip6 = nat->nat_nsrc6; + ipn->in_odstip6 = nat->nat_osrc6; + } else { + ipn->in_redir = NAT_REDIRECT; + if (ipn->in_v[0] == 4) { + ipn->in_snip = ntohl(nat->nat_odstaddr); + ipn->in_dnip = ntohl(nat->nat_osrcaddr); + } else { +#ifdef USE_INET6 + ipn->in_snip6 = nat->nat_odst6; + ipn->in_dnip6 = nat->nat_osrc6; +#endif + } + ipn->in_ndstip6 = nat->nat_osrc6; + ipn->in_odstip6 = nat->nat_nsrc6; + } + ipn->in_odport = htons(fin->fin_sport); + ipn->in_ndport = htons(fin->fin_sport); + + IP6_SETONES(&ipn->in_osrcmsk6); + IP6_SETONES(&ipn->in_nsrcmsk6); + IP6_SETONES(&ipn->in_odstmsk6); + IP6_SETONES(&ipn->in_ndstmsk6); + MUTEX_INIT(&ipn->in_lock, "tftp proxy NAT rule"); + + ipn->in_namelen = np->in_namelen; + bcopy(np->in_names, ipn->in_ifnames, ipn->in_namelen); + ipn->in_ifnames[0] = np->in_ifnames[0]; + ipn->in_ifnames[1] = np->in_ifnames[1]; + + ti->ti_lastcmd = 0; + + return 0; +} + + +void +ipf_p_tftp_del(softc, aps) + ipf_main_softc_t *softc; + ap_session_t *aps; +{ + tftpinfo_t *tftp; + + tftp = aps->aps_data; + if (tftp != NULL) { + tftp->ti_rule->in_flags |= IPN_DELETE; + ipf_nat_rule_deref(softc, &tftp->ti_rule); + } +} + + +/* + * Setup for a new TFTP proxy. + */ +int +ipf_p_tftp_backchannel(fin, aps, nat) + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; +{ + ipf_main_softc_t *softc = fin->fin_main_soft; +#ifdef USE_MUTEXES + ipf_nat_softc_t *softn = softc->ipf_nat_soft; +#endif +#ifdef USE_INET6 + i6addr_t swip6, sw2ip6; + ip6_t *ip6; +#endif + struct in_addr swip, sw2ip; + tftpinfo_t *ti; + udphdr_t udp; + fr_info_t fi; + u_short slen; + nat_t *nat2; + int nflags; + ip_t *ip; + int dir; + + ti = aps->aps_data; + /* + * Add skeleton NAT entry for connection which will come back the + * other way. + */ + bcopy((char *)fin, (char *)&fi, sizeof(fi)); + fi.fin_flx |= FI_IGNORE; + fi.fin_data[1] = 0; + + bzero((char *)&udp, sizeof(udp)); + udp.uh_sport = 0; /* XXX - don't specify remote port */ + udp.uh_dport = ti->ti_rule->in_ndport; + udp.uh_ulen = htons(sizeof(udp)); + udp.uh_sum = 0; + + fi.fin_fr = &tftpfr; + fi.fin_dp = (char *)&udp; + fi.fin_sport = 0; + fi.fin_dport = ntohs(ti->ti_rule->in_ndport); + fi.fin_dlen = sizeof(udp); + fi.fin_plen = fi.fin_hlen + sizeof(udp); + fi.fin_flx &= FI_LOWTTL|FI_FRAG|FI_TCPUDP|FI_OPTIONS|FI_IGNORE; + nflags = NAT_SLAVE|IPN_UDP|SI_W_SPORT; +#ifdef USE_INET6 + ip6 = (ip6_t *)fin->fin_ip; +#endif + ip = fin->fin_ip; + sw2ip.s_addr = 0; + swip.s_addr = 0; + + fi.fin_src6 = nat->nat_ndst6; + fi.fin_dst6 = nat->nat_nsrc6; + if (nat->nat_v[0] == 4) { + slen = ip->ip_len; + ip->ip_len = htons(fin->fin_hlen + sizeof(udp)); + swip = ip->ip_src; + sw2ip = ip->ip_dst; + ip->ip_src = nat->nat_ndstip; + ip->ip_dst = nat->nat_nsrcip; + } else { +#ifdef USE_INET6 + slen = ip6->ip6_plen; + ip6->ip6_plen = htons(sizeof(udp)); + swip6.in6 = ip6->ip6_src; + sw2ip6.in6 = ip6->ip6_dst; + ip6->ip6_src = nat->nat_ndst6.in6; + ip6->ip6_dst = nat->nat_nsrc6.in6; +#endif + } + + if (nat->nat_dir == NAT_INBOUND) { + dir = NAT_OUTBOUND; + fi.fin_out = 1; + } else { + dir = NAT_INBOUND; + fi.fin_out = 0; + } + nflags |= NAT_NOTRULEPORT; + + MUTEX_ENTER(&softn->ipf_nat_new); + if (nat->nat_v[0] == 4) + nat2 = ipf_nat_add(&fi, ti->ti_rule, NULL, nflags, dir); + else + nat2 = ipf_nat6_add(&fi, ti->ti_rule, NULL, nflags, dir); + MUTEX_EXIT(&softn->ipf_nat_new); + if (nat2 != NULL) { + (void) ipf_nat_proto(&fi, nat2, IPN_UDP); + ipf_nat_update(&fi, nat2); + fi.fin_ifp = NULL; + if (ti->ti_rule->in_redir == NAT_MAP) { + fi.fin_src6 = nat->nat_ndst6; + fi.fin_dst6 = nat->nat_nsrc6; + if (nat->nat_v[0] == 4) { + ip->ip_src = nat->nat_ndstip; + ip->ip_dst = nat->nat_nsrcip; + } else { +#ifdef USE_INET6 + ip6->ip6_src = nat->nat_ndst6.in6; + ip6->ip6_dst = nat->nat_nsrc6.in6; +#endif + } + } else { + fi.fin_src6 = nat->nat_odst6; + fi.fin_dst6 = nat->nat_osrc6; + if (fin->fin_v == 4) { + ip->ip_src = nat->nat_odstip; + ip->ip_dst = nat->nat_osrcip; + } else { +#ifdef USE_INET6 + ip6->ip6_src = nat->nat_odst6.in6; + ip6->ip6_dst = nat->nat_osrc6.in6; +#endif + } + } + if (ipf_state_add(softc, &fi, NULL, SI_W_SPORT) != 0) { + ipf_nat_setpending(softc, nat2); + } + } + if (nat->nat_v[0] == 4) { + ip->ip_len = slen; + ip->ip_src = swip; + ip->ip_dst = sw2ip; + } else { +#ifdef USE_INET6 + ip6->ip6_plen = slen; + ip6->ip6_src = swip6.in6; + ip6->ip6_dst = sw2ip6.in6; +#endif + } + return 0; +} + + +int +ipf_p_tftp_client(softt, fin, aps, nat) + ipf_tftp_softc_t *softt; + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; +{ + u_char *msg, *s, *t; + tftpinfo_t *ti; + u_short opcode; + udphdr_t *udp; + int len; + + if (fin->fin_dlen < 4) + return 0; + + ti = aps->aps_data; + msg = fin->fin_dp; + msg += sizeof(udphdr_t); + opcode = (msg[0] << 8) | msg[1]; + DT3(tftp_cmd, fr_info_t *, fin, int, opcode, nat_t *, nat); + + switch (opcode) + { + case TFTP_CMD_WRITE : + if (softt->ipf_p_tftp_readonly != 0) + break; + /* FALLTHROUGH */ + case TFTP_CMD_READ : + len = fin->fin_dlen - sizeof(*udp) - 2; + if (len > sizeof(ti->ti_filename) - 1) + len = sizeof(ti->ti_filename) - 1; + s = msg + 2; + for (t = (u_char *)ti->ti_filename; (len > 0); len--, s++) { + *t++ = *s; + if (*s == '\0') + break; + } + ipf_p_tftp_backchannel(fin, aps, nat); + break; + default : + return -1; + } + + ti = aps->aps_data; + ti->ti_lastcmd = opcode; + return 0; +} + + +int +ipf_p_tftp_server(softt, fin, aps, nat) + ipf_tftp_softc_t *softt; + fr_info_t *fin; + ap_session_t *aps; + nat_t *nat; +{ + tftpinfo_t *ti; + u_short opcode; + u_short arg; + u_char *msg; + + if (fin->fin_dlen < 4) + return 0; + + ti = aps->aps_data; + msg = fin->fin_dp; + msg += sizeof(udphdr_t); + arg = (msg[2] << 8) | msg[3]; + opcode = (msg[0] << 8) | msg[1]; + + switch (opcode) + { + case TFTP_CMD_ACK : + ti->ti_lastblk = arg; + break; + + case TFTP_CMD_ERROR : + ti->ti_lasterror = arg; + break; + + default : + return -1; + } + + ti->ti_lastcmd = opcode; + return 0; +} diff --git a/ipf.c b/ipf.c deleted file mode 100644 index cf8528046897c..0000000000000 --- a/ipf.c +++ /dev/null @@ -1,764 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - */ -#ifdef __FreeBSD__ -# ifndef __FreeBSD_cc_version -# include <osreldate.h> -# else -# if __FreeBSD_cc_version < 430000 -# include <osreldate.h> -# endif -# endif -#endif -#if defined(__sgi) && (IRIX > 602) -# include <sys/ptimers.h> -#endif -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <fcntl.h> -#include <errno.h> -#if !defined(__SVR4) && !defined(__GNUC__) -#include <strings.h> -#endif -#include <sys/types.h> -#include <sys/param.h> -#include <sys/file.h> -#include <stdlib.h> -#include <stddef.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <sys/time.h> -#include <net/if.h> -#if __FreeBSD_version >= 300000 -# include <net/if_var.h> -#endif -#include <netinet/ip.h> -#include <netdb.h> -#include <arpa/nameser.h> -#include <resolv.h> -#include "ip_compat.h" -#include "ip_fil.h" -#include "ip_nat.h" -#include "ip_state.h" -#include "ipf.h" -#include "ipl.h" - -#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.23 2003/06/27 14:39:13 darrenr Exp $"; -#endif - -#if SOLARIS -static void blockunknown __P((void)); -#endif -#if !defined(__SVR4) && defined(__GNUC__) -extern char *index __P((const char *, int)); -#endif - -extern char *optarg; -extern int optind; - -void frsync __P((void)); -void zerostats __P((void)); -int main __P((int, char *[])); - -int opts = 0; -int use_inet6 = 0; - -static int fd = -1; - -static void procfile __P((char *, char *)), flushfilter __P((char *)); -static int set_state __P((u_int)); -static void 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 *, int *)); -static char *ipfname = IPL_NAME; -static void usage __P((char *)); -static int showversion __P((void)); -static int get_flags __P((int *)); - - -#if SOLARIS -# define OPTS "6AdDEf:F:Il:noPrsUvVyzZ" -#else -# define OPTS "6AdDEf:F:Il:noPrsvVyzZ" -#endif - -static void usage(name) -char *name; -{ - fprintf(stderr, "usage: %s [-%s] %s %s %s\n", name, OPTS, - "[-l block|pass|nomatch]", "[-F i|o|a|s|S]", "[-f filename]"); - exit(1); -} - - -int main(argc,argv) -int argc; -char *argv[]; -{ - int c; - - if (argc < 2) - usage(argv[0]); - - while ((c = getopt(argc, argv, OPTS)) != -1) { - switch (c) - { - case '6' : - use_inet6 = 1; - break; - case 'A' : - opts &= ~OPT_INACTIVE; - break; - case 'E' : - if (set_state((u_int)1)) - exit(1); - break; - case 'D' : - if (set_state((u_int)0)) - exit(1); - break; - case 'd' : - opts |= OPT_DEBUG; - break; - case 'f' : - procfile(argv[0], optarg); - break; - case 'F' : - flushfilter(optarg); - break; - case 'I' : - opts |= OPT_INACTIVE; - break; - case 'l' : - packetlogon(optarg); - break; - case 'n' : - opts |= OPT_DONOTHING; - break; - case 'o' : - break; - case 'P' : - ipfname = IPL_AUTH; - break; - case 'r' : - opts |= OPT_REMOVE; - break; - case 's' : - swapactive(); - break; -#if SOLARIS - case 'U' : - blockunknown(); - break; -#endif - case 'v' : - opts += OPT_VERBOSE; - break; - case 'V' : - if (showversion()) - exit(1); - break; - case 'y' : - frsync(); - break; - case 'z' : - opts |= OPT_ZERORULEST; - break; - case 'Z' : - zerostats(); - break; - case '?' : - default : - usage(argv[0]); - break; - } - } - - if (optind < 2) - usage(argv[0]); - - if (fd != -1) - (void) close(fd); - - exit(0); - /* NOTREACHED */ -} - - -static int opendevice(ipfdev) -char *ipfdev; -{ - if (opts & OPT_DONOTHING) - return 0; - - if (!ipfdev) - ipfdev = ipfname; - - /* - * shouldn't we really be testing for fd < 0 here and below? - */ - - if (fd != -1) - return 0; - - if ((fd = open(ipfdev, O_RDWR)) == -1) { - if ((fd = open(ipfdev, O_RDONLY)) == -1) { - perror("open device"); - if (errno == ENODEV) - fprintf(stderr, "IPFilter enabled?\n"); - return -1; - } - } - - return 0; -} - - -static void closedevice() -{ - if (fd != -1) - close(fd); - fd = -1; -} - - -/* - * Return codes: - * 0 Success - * !0 Failure (and an error message has already been printed) - */ -static int get_flags(i) -int *i; -{ - - if (opts & OPT_DONOTHING) - return 0; - - if (opendevice(ipfname) < 0) - return -1; - - if (ioctl(fd, SIOCGETFF, i) == -1) { - perror("SIOCGETFF"); - return -1; - } - return 0; -} - - -static int set_state(enable) -u_int enable; -{ - if (opts & OPT_DONOTHING) - return 0; - - if (opendevice(ipfname)) - return -1; - - if (ioctl(fd, SIOCFRENB, &enable) == -1) { - if (errno == EBUSY) - /* Not really an error */ - fprintf(stderr, - "IP Filter: already initialized\n"); - else { - perror("SIOCFRENB"); - return -1; - } - } - return 0; -} - -static void procfile(name, file) -char *name, *file; -{ - FILE *fp; - char line[513], *s; - struct frentry *fr; - u_int add, del; - int linenum = 0; - int parsestatus; - - if (opendevice(ipfname) == -1) - exit(1); - - if (opts & OPT_INACTIVE) { - add = SIOCADIFR; - del = SIOCRMIFR; - } else { - add = SIOCADAFR; - del = SIOCRMAFR; - } - if (opts & OPT_DEBUG) - printf("add %x del %x\n", add, del); - - initparse(); - - if (!strcmp(file, "-")) - fp = stdin; - else if (!(fp = fopen(file, "r"))) { - fprintf(stderr, "%s: fopen(%s) failed: %s\n", name, file, - STRERROR(errno)); - exit(1); - } - - while (getline(line, sizeof(line), fp, &linenum)) { - /* - * treat CR as EOL. LF is converted to NUL by getline(). - */ - if ((s = index(line, '\r'))) - *s = '\0'; - /* - * # is comment marker, everything after is a ignored - */ - if ((s = index(line, '#'))) - *s = '\0'; - - if (!*line) - continue; - - if (opts & OPT_VERBOSE) - (void)fprintf(stderr, "[%s]\n", line); - - parsestatus = 1; - fr = parse(line, linenum, &parsestatus); - (void)fflush(stdout); - - if (parsestatus != 0) { - fprintf(stderr, "%s: %s: %s error (%d), quitting\n", - name, file, - ((parsestatus < 0)? "parse": "internal"), - parsestatus); - exit(1); - } - - if (fr) { - if (opts & OPT_ZERORULEST) - add = SIOCZRLST; - else if (opts & OPT_INACTIVE) - add = (u_int)fr->fr_hits ? SIOCINIFR : - SIOCADIFR; - else - add = (u_int)fr->fr_hits ? SIOCINAFR : - SIOCADAFR; - if (fr->fr_hits) - fr->fr_hits--; - if (fr && (opts & OPT_VERBOSE)) - printfr(fr); - if (fr && (opts & OPT_OUTQUE)) - fr->fr_flags |= FR_OUTQUE; - - if (opts & OPT_DEBUG) - binprint(fr); - - if ((opts & OPT_ZERORULEST) && - !(opts & OPT_DONOTHING)) { - if (ioctl(fd, add, &fr) == -1) { - fprintf(stderr, "%d:", linenum); - perror("ioctl(SIOCZRLST)"); - exit(1); - } else { -#ifdef USE_QUAD_T - printf("hits %qd bytes %qd ", - (long long)fr->fr_hits, - (long long)fr->fr_bytes); -#else - printf("hits %ld bytes %ld ", - fr->fr_hits, fr->fr_bytes); -#endif - printfr(fr); - } - } else if ((opts & OPT_REMOVE) && - !(opts & OPT_DONOTHING)) { - if (ioctl(fd, del, &fr) == -1) { - fprintf(stderr, "%d:", linenum); - perror("ioctl(delete rule)"); - exit(1); - } - } else if (!(opts & OPT_DONOTHING)) { - if (ioctl(fd, add, &fr) == -1) { - fprintf(stderr, "%d:", linenum); - perror("ioctl(add/insert rule)"); - exit(1); - } - } - } - } - if (ferror(fp) || !feof(fp)) { - fprintf(stderr, "%s: %s: file error or line too long\n", - name, file); - exit(1); - } - (void)fclose(fp); -} - -/* - * Similar to fgets(3) but can handle '\\' and NL is converted to NUL. - * Returns NULL if error occurred, EOF encounterd or input line is too long. - */ -static char *getline(str, size, file, linenum) -register char *str; -size_t size; -FILE *file; -int *linenum; -{ - char *p; - int s, len; - - do { - for (p = str, s = size;; p += (len - 1), s -= (len - 1)) { - /* - * if an error occurred, EOF was encounterd, or there - * was no room to put NUL, return NULL. - */ - if (fgets(p, s, file) == NULL) - return (NULL); - len = strlen(p); - if (p[len - 1] != '\n') { - p[len] = '\0'; - break; - } - (*linenum)++; - p[len - 1] = '\0'; - if (len < 2 || p[len - 2] != '\\') - break; - else - /* - * Convert '\\' to a space so words don't - * run together - */ - p[len - 2] = ' '; - } - } while (*str == '\0'); - return (str); -} - - -static void packetlogon(opt) -char *opt; -{ - int flag; - - if (get_flags(&flag)) - exit(1); - - if (flag != 0) { - if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) - printf("log flag is currently %#x\n", flag); - } - - flag &= ~(FF_LOGPASS|FF_LOGNOMATCH|FF_LOGBLOCK); - - if (index(opt, 'p')) { - flag |= FF_LOGPASS; - if (opts & OPT_VERBOSE) - printf("set log flag: pass\n"); - } - if (index(opt, 'm') && (*opt == 'n' || *opt == 'N')) { - flag |= FF_LOGNOMATCH; - if (opts & OPT_VERBOSE) - printf("set log flag: nomatch\n"); - } - if (index(opt, 'b') || index(opt, 'd')) { - flag |= FF_LOGBLOCK; - if (opts & OPT_VERBOSE) - printf("set log flag: block\n"); - } - - if (opendevice(ipfname) == -1) { - exit(1); - } - - if (!(opts & OPT_DONOTHING)) { - if (ioctl(fd, SIOCSETFF, &flag) != 0) { - perror("ioctl(SIOCSETFF)"); - exit(1); - } - } - - if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { - /* - * Even though the ioctls above succeeded, it - * is possible that a calling script/program - * relies on the following verbose mode string. - * Thus, we still take an error exit if get_flags - * fails here. - */ - if (get_flags(&flag)) - exit(1); - printf("log flag is now %#x\n", flag); - } -} - - -static void flushfilter(arg) -char *arg; -{ - int fl = 0, rem; - - if (!arg || !*arg) { - fprintf(stderr, "-F: no filter specified\n"); - exit(1); - } - - if (!strcmp(arg, "s") || !strcmp(arg, "S")) { - if (*arg == 'S') - fl = 0; - else - fl = 1; - rem = fl; - - closedevice(); - - if (opendevice(IPL_STATE) == -1) { - exit(1); - } - - if (!(opts & OPT_DONOTHING)) { - if (use_inet6) { - if (ioctl(fd, SIOCIPFL6, &fl) == -1) { - perror("ioctl(SIOCIPFL6)"); - exit(1); - } - } else { - if (ioctl(fd, SIOCIPFFL, &fl) == -1) { - perror("ioctl(SIOCIPFFL)"); - exit(1); - } - } - } - if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { - printf("remove flags %s (%d)\n", arg, rem); - printf("removed %d filter rules\n", fl); - } - closedevice(); - return; - } - if (strchr(arg, 'i') || strchr(arg, 'I')) - fl = FR_INQUE; - if (strchr(arg, 'o') || strchr(arg, 'O')) - fl = FR_OUTQUE; - if (strchr(arg, 'a') || strchr(arg, 'A')) - fl = FR_OUTQUE|FR_INQUE; - fl |= (opts & FR_INACTIVE); - rem = fl; - - if (opendevice(ipfname) == -1) { - exit(1); - } - - if (!(opts & OPT_DONOTHING)) { - if (use_inet6) { - if (ioctl(fd, SIOCIPFL6, &fl) == -1) { - perror("ioctl(SIOCIPFL6)"); - exit(1); - } - } else { - if (ioctl(fd, SIOCIPFFL, &fl) == -1) { - perror("ioctl(SIOCIPFFL)"); - exit(1); - } - } - } - if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { - printf("remove flags %s%s (%d)\n", (rem & FR_INQUE) ? "I" : "", - (rem & FR_OUTQUE) ? "O" : "", rem); - printf("removed %d filter rules\n", fl); - } - return; -} - - -static void swapactive() -{ - int in = 2; - - if (opendevice(ipfname) == -1) { - exit(1); - } - - - if (!(opts & OPT_DONOTHING)) { - if (ioctl(fd, SIOCSWAPA, &in) == -1) { - perror("ioctl(SIOCSWAPA)"); - exit(1); - } - } - printf("Set %d now inactive\n", in); -} - - -void frsync() -{ - int frsyn = 0; - - if (opendevice(ipfname) == -1) - exit(1); - - if (!(opts & OPT_DONOTHING)) { - if (ioctl(fd, SIOCFRSYN, &frsyn) == -1) { - perror("SIOCFRSYN"); - exit(1); - } - } - printf("filter sync'd\n"); -} - - -void zerostats() -{ - friostat_t fio; - friostat_t *fiop = &fio; - - if (opendevice(ipfname) == -1) - exit(1); - - if (!(opts & OPT_DONOTHING)) { - if (ioctl(fd, SIOCFRZST, &fiop) == -1) { - perror("ioctl(SIOCFRZST)"); - exit(-1); - } - showstats(fiop); - } - -} - - -/* - * Read the kernel stats for packets blocked and passed - */ -static void showstats(fp) -friostat_t *fp; -{ -#if SOLARIS - printf("dropped packets:\tin %lu\tout %lu\n", - fp->f_st[0].fr_drop, fp->f_st[1].fr_drop); - printf("non-ip packets:\t\tin %lu\tout %lu\n", - fp->f_st[0].fr_notip, fp->f_st[1].fr_notip); - printf(" bad packets:\t\tin %lu\tout %lu\n", - fp->f_st[0].fr_bad, fp->f_st[1].fr_bad); -#endif - printf(" input packets:\t\tblocked %lu passed %lu nomatch %lu", - fp->f_st[0].fr_block, fp->f_st[0].fr_pass, - fp->f_st[0].fr_nom); - printf(" counted %lu\n", fp->f_st[0].fr_acct); - printf("output packets:\t\tblocked %lu passed %lu nomatch %lu", - fp->f_st[1].fr_block, fp->f_st[1].fr_pass, - fp->f_st[1].fr_nom); - printf(" counted %lu\n", fp->f_st[0].fr_acct); - printf(" input packets logged:\tblocked %lu passed %lu\n", - fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl); - printf("output packets logged:\tblocked %lu passed %lu\n", - fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl); - printf(" packets logged:\tinput %lu-%lu output %lu-%lu\n", - fp->f_st[0].fr_pkl, fp->f_st[0].fr_skip, - fp->f_st[1].fr_pkl, fp->f_st[1].fr_skip); -} - - -#if SOLARIS -static void blockunknown() -{ - int flag; - - if (opendevice(ipfname) == -1) - exit(1); - - if (get_flags(&flag)) - exit(1); - - if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) - printf("log flag is currently %#x\n", flag); - - flag ^= FF_BLOCKNONIP; - - if (opendevice(ipfname) == -1) - exit(1); - - if (!(opts & OPT_DONOTHING)) { - if (ioctl(fd, SIOCSETFF, &flag)) - perror("ioctl(SIOCSETFF)"); - } - - if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { - if (ioctl(fd, SIOCGETFF, &flag)) - perror("ioctl(SIOCGETFF)"); - - printf("log flag is now %#x\n", flag); - } -} -#endif - - -/* - * nonzero return value means caller should exit with error - */ -static int showversion() -{ - struct friostat fio; - struct friostat *fiop=&fio; - int flags, vfd; - char *s; - - printf("ipf: %s (%d)\n", IPL_VERSION, (int)sizeof(frentry_t)); - - if ((vfd = open(ipfname, O_RDONLY)) == -1) { - perror("open device"); - return 1; - } - - if (ioctl(vfd, SIOCGETFS, &fiop)) { - perror("ioctl(SIOCGETFS)"); - close(vfd); - return 1; - } - close(vfd); - - printf("Kernel: %-*.*s\n", (int)sizeof(fio.f_version), - (int)sizeof(fio.f_version), fio.f_version); - printf("Running: %s\n", fio.f_running ? "yes" : "no"); - - if (get_flags(&flags)) { - return 1; - } - printf("Log Flags: %#x = ", flags); - s = ""; - if (flags & FF_LOGPASS) { - printf("pass"); - s = ", "; - } - if (flags & FF_LOGBLOCK) { - printf("%sblock", s); - s = ", "; - } - if (flags & FF_LOGNOMATCH) { - printf("%snomatch", s); - s = ", "; - } - if (flags & FF_BLOCKNONIP) { - printf("%snonip", s); - s = ", "; - } - if (!*s) - printf("none set"); - putchar('\n'); - - printf("Default: "); - if (fio.f_defpass & FR_PASS) - s = "pass"; - else if (fio.f_defpass & FR_BLOCK) - s = "block"; - else - s = "nomatch -> block"; - printf("%s all, Logging: %savailable\n", s, fio.f_logging ? "" : "un"); - printf("Active list: %d\n", fio.f_active); - - return 0; -} @@ -1,10 +1,10 @@ /* - * Copyright (C) 1993-2001, 2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ipf.h 1.12 6/5/96 - * $Id: ipf.h,v 2.71.2.15 2007/05/11 10:44:14 darrenr Exp $ + * $Id$ */ #ifndef __IPF_H__ @@ -78,6 +78,7 @@ struct file; #include "netinet/ip_scan.h" #include "netinet/ip_htable.h" #include "netinet/ip_sync.h" +#include "netinet/ip_dstlist.h" #include "opts.h" @@ -118,6 +119,9 @@ typedef unsigned int u_32_t; #define MAX_ICMPCODE 16 #define MAX_ICMPTYPE 19 +#define PRINTF (void)printf +#define FPRINTF (void)fprintf + struct ipopt_names { int on_value; @@ -130,6 +134,7 @@ struct ipopt_names { typedef struct alist_s { struct alist_s *al_next; int al_not; + int al_family; i6addr_t al_i6addr; i6addr_t al_i6mask; } alist_t; @@ -140,6 +145,14 @@ typedef struct alist_s { #define al_2 al_mask +typedef struct plist_s { + struct plist_s *pl_next; + int pl_compare; + u_short pl_port1; + u_short pl_port2; +} plist_t; + + typedef struct { u_short fb_c; u_char fb_t; @@ -148,6 +161,35 @@ typedef struct { } fakebpf_t; +typedef struct { + char *it_name; + int it_v4; + int it_v6; +} icmptype_t; + + +typedef struct wordtab { + char *w_word; + int w_value; +} wordtab_t; + + +typedef struct namelist { + struct namelist *na_next; + char *na_name; + int na_value; +} namelist_t; + + +typedef struct proxyrule { + struct proxyrule *pr_next; + char *pr_proxy; + char *pr_conf; + namelist_t *pr_names; + int pr_proto; +} proxyrule_t; + + #if defined(__NetBSD__) || defined(__OpenBSD__) || \ (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) || \ SOLARIS || defined(__sgi) || defined(__osf__) || defined(linux) @@ -156,7 +198,7 @@ typedef int (* ioctlfunc_t) __P((int, ioctlcmd_t, ...)); #else typedef int (* ioctlfunc_t) __P((dev_t, ioctlcmd_t, void *)); #endif -typedef void (* addfunc_t) __P((int, ioctlfunc_t, void *)); +typedef int (* addfunc_t) __P((int, ioctlfunc_t, void *)); typedef int (* copyfunc_t) __P((void *, void *, size_t)); @@ -176,90 +218,143 @@ extern char *icmpcodes[MAX_ICMPCODE + 1]; extern char *icmptypes[MAX_ICMPTYPE + 1]; extern int use_inet6; extern int lineNum; +extern int debuglevel; extern struct ipopt_names v6ionames[]; +extern icmptype_t icmptypelist[]; +extern wordtab_t statefields[]; +extern wordtab_t natfields[]; +extern wordtab_t poolfields[]; extern int addicmp __P((char ***, struct frentry *, int)); extern int addipopt __P((char *, struct ipopt_names *, int, char *)); -extern void alist_free __P((alist_t *)); +extern int addkeep __P((char ***, struct frentry *, int)); extern alist_t *alist_new __P((int, char *)); +extern void alist_free __P((alist_t *)); +extern void assigndefined __P((char *)); extern void binprint __P((void *, size_t)); -extern void initparse __P((void)); extern u_32_t buildopts __P((char *, char *, int)); extern int checkrev __P((char *)); +extern int connecttcp __P((char *, int)); extern int count6bits __P((u_32_t *)); extern int count4bits __P((u_32_t)); extern char *fac_toname __P((int)); extern int fac_findname __P((char *)); +extern const char *familyname __P((const int)); extern void fill6bits __P((int, u_int *)); -extern int gethost __P((char *, u_32_t *)); -extern int getport __P((struct frentry *, char *, u_short *)); +extern wordtab_t *findword __P((wordtab_t *, char *)); +extern int ftov __P((int)); +extern char *ipf_geterror __P((int, ioctlfunc_t *)); +extern int genmask __P((int, char *, i6addr_t *)); +extern int gethost __P((int, char *, i6addr_t *)); +extern int geticmptype __P((int, char *)); +extern int getport __P((struct frentry *, char *, u_short *, char *)); extern int getportproto __P((char *, int)); extern int getproto __P((char *)); -extern char *getnattype __P((struct nat *, int)); +extern char *getnattype __P((struct nat *)); extern char *getsumd __P((u_32_t)); extern u_32_t getoptbyname __P((char *)); extern u_32_t getoptbyvalue __P((int)); extern u_32_t getv6optbyname __P((char *)); extern u_32_t getv6optbyvalue __P((int)); +extern char *icmptypename __P((int, int)); extern void initparse __P((void)); -extern void ipf_dotuning __P((int, char *, ioctlfunc_t)); -extern void ipf_addrule __P((int, ioctlfunc_t, void *)); +extern void ipf_dotuning __P((int, char *, ioctlfunc_t)); +extern int ipf_addrule __P((int, ioctlfunc_t, void *)); +extern void ipf_mutex_clean __P((void)); extern int ipf_parsefile __P((int, addfunc_t, ioctlfunc_t *, char *)); extern int ipf_parsesome __P((int, addfunc_t, ioctlfunc_t *, FILE *)); +extern void ipf_perror __P((int, char *)); +extern int ipf_perror_fd __P(( int, ioctlfunc_t, char *)); +extern void ipf_rwlock_clean __P((void)); +extern char *ipf_strerror __P((int)); +extern void ipferror __P((int, char *)); extern int ipmon_parsefile __P((char *)); extern int ipmon_parsesome __P((FILE *)); -extern void ipnat_addrule __P((int, ioctlfunc_t, void *)); +extern int ipnat_addrule __P((int, ioctlfunc_t, void *)); extern int ipnat_parsefile __P((int, addfunc_t, ioctlfunc_t, char *)); extern int ipnat_parsesome __P((int, addfunc_t, ioctlfunc_t, FILE *)); extern int ippool_parsefile __P((int, char *, ioctlfunc_t)); extern int ippool_parsesome __P((int, FILE *, ioctlfunc_t)); extern int kmemcpywrap __P((void *, void *, size_t)); extern char *kvatoname __P((ipfunc_t, ioctlfunc_t)); +extern int load_dstlist __P((struct ippool_dst *, ioctlfunc_t, + ipf_dstnode_t *)); +extern int load_dstlistnode __P((int, char *, struct ipf_dstnode *, + ioctlfunc_t)); extern alist_t *load_file __P((char *)); extern int load_hash __P((struct iphtable_s *, struct iphtent_s *, ioctlfunc_t)); -extern int load_hashnode __P((int, char *, struct iphtent_s *, ioctlfunc_t)); +extern int load_hashnode __P((int, char *, struct iphtent_s *, int, + ioctlfunc_t)); extern alist_t *load_http __P((char *)); extern int load_pool __P((struct ip_pool_s *list, ioctlfunc_t)); -extern int load_poolnode __P((int, char *, ip_pool_node_t *, ioctlfunc_t)); +extern int load_poolnode __P((int, char *, ip_pool_node_t *, int, ioctlfunc_t)); extern alist_t *load_url __P((char *)); extern alist_t *make_range __P((int, struct in_addr, struct in_addr)); +extern void mb_hexdump __P((mb_t *, FILE *)); extern ipfunc_t nametokva __P((char *, ioctlfunc_t)); extern void nat_setgroupmap __P((struct ipnat *)); extern int ntomask __P((int, int, u_32_t *)); extern u_32_t optname __P((char ***, u_short *, int)); -extern struct frentry *parse __P((char *, int)); +extern wordtab_t *parsefields __P((wordtab_t *, char *)); +extern int *parseipfexpr __P((char *, char **)); +extern int parsewhoisline __P((char *, addrfamily_t *, addrfamily_t *)); +extern void pool_close __P((void)); +extern int pool_fd __P((void)); +extern int pool_ioctl __P((ioctlfunc_t, ioctlcmd_t, void *)); +extern int pool_open __P((void)); extern char *portname __P((int, int)); extern int pri_findname __P((char *)); extern char *pri_toname __P((int)); -extern void print_toif __P((char *, struct frdest *)); -extern void printaps __P((ap_session_t *, int)); +extern void print_toif __P((int, char *, char *, struct frdest *)); +extern void printaps __P((ap_session_t *, int, int)); +extern void printaddr __P((int, int, char *, int, u_32_t *, u_32_t *)); extern void printbuf __P((char *, int, int)); +extern void printfieldhdr __P((wordtab_t *, wordtab_t *)); extern void printfr __P((struct frentry *, ioctlfunc_t)); -extern void printtunable __P((ipftune_t *)); extern struct iphtable_s *printhash __P((struct iphtable_s *, copyfunc_t, - char *, int)); -extern struct iphtable_s *printhash_live __P((iphtable_t *, int, char *, int)); + char *, int, wordtab_t *)); +extern struct iphtable_s *printhash_live __P((iphtable_t *, int, char *, + int, wordtab_t *)); +extern ippool_dst_t *printdstl_live __P((ippool_dst_t *, int, char *, + int, wordtab_t *)); extern void printhashdata __P((iphtable_t *, int)); extern struct iphtent_s *printhashnode __P((struct iphtable_s *, struct iphtent_s *, - copyfunc_t, int)); + copyfunc_t, int, wordtab_t *)); +extern void printhost __P((int, u_32_t *)); extern void printhostmask __P((int, u_32_t *, u_32_t *)); -extern void printip __P((u_32_t *)); +extern void printip __P((int, u_32_t *)); extern void printlog __P((struct frentry *)); -extern void printlookup __P((i6addr_t *addr, i6addr_t *mask)); -extern void printmask __P((u_32_t *)); -extern void printpacket __P((struct ip *)); -extern void printpacket6 __P((struct ip *)); +extern void printlookup __P((char *, i6addr_t *addr, i6addr_t *mask)); +extern void printmask __P((int, u_32_t *)); +extern void printnataddr __P((int, char *, nat_addr_t *, int)); +extern void printnatfield __P((nat_t *, int)); +extern void printnatside __P((char *, nat_stat_side_t *)); +extern void printpacket __P((int, mb_t *)); +extern void printpacket6 __P((int, mb_t *)); +extern struct ippool_dst *printdstlist __P((struct ippool_dst *, copyfunc_t, + char *, int, ipf_dstnode_t *, + wordtab_t *)); +extern void printdstlistdata __P((ippool_dst_t *, int)); +extern ipf_dstnode_t *printdstlistnode __P((ipf_dstnode_t *, copyfunc_t, + int, wordtab_t *)); +extern void printdstlistpolicy __P((ippool_policy_t)); extern struct ip_pool_s *printpool __P((struct ip_pool_s *, copyfunc_t, - char *, int)); + char *, int, wordtab_t *)); extern struct ip_pool_s *printpool_live __P((struct ip_pool_s *, int, - char *, int)); + char *, int, wordtab_t *)); extern void printpooldata __P((ip_pool_t *, int)); -extern struct ip_pool_node *printpoolnode __P((struct ip_pool_node *, int)); +extern void printpoolfield __P((void *, int, int)); +extern struct ip_pool_node *printpoolnode __P((struct ip_pool_node *, + int, wordtab_t *)); extern void printproto __P((struct protoent *, int, struct ipnat *)); extern void printportcmp __P((int, struct frpcmp *)); +extern void printstatefield __P((ipstate_t *, int)); +extern void printtqtable __P((ipftq_t *)); +extern void printtunable __P((ipftune_t *)); +extern void printunit __P((int)); extern void optprint __P((u_short *, u_long, u_long)); #ifdef USE_INET6 extern void optprintv6 __P((u_short *, u_long, u_long)); @@ -268,7 +363,6 @@ extern int remove_hash __P((struct iphtable_s *, ioctlfunc_t)); extern int remove_hashnode __P((int, char *, struct iphtent_s *, ioctlfunc_t)); extern int remove_pool __P((ip_pool_t *, ioctlfunc_t)); extern int remove_poolnode __P((int, char *, ip_pool_node_t *, ioctlfunc_t)); -extern u_char tcp_flags __P((char *, u_char *, int)); extern u_char tcpflags __P((char *)); extern void printc __P((struct frentry *)); extern void printC __P((int)); @@ -281,14 +375,26 @@ extern char *hostname __P((int, void *)); extern struct ipstate *printstate __P((struct ipstate *, int, u_long)); extern void printsbuf __P((char *)); extern void printnat __P((struct ipnat *, int)); -extern void printactivenat __P((struct nat *, int, int, u_long)); +extern void printactiveaddress __P((int, char *, i6addr_t *, char *)); +extern void printactivenat __P((struct nat *, int, u_long)); extern void printhostmap __P((struct hostmap *, u_int)); -extern void printtqtable __P((ipftq_t *)); +extern void printtcpflags __P((u_32_t, u_32_t)); +extern void printipfexpr __P((int *)); +extern void printstatefield __P((ipstate_t *, int)); +extern void printstatefieldhdr __P((int)); +extern int sendtrap_v1_0 __P((int, char *, char *, int, time_t)); +extern int sendtrap_v2_0 __P((int, char *, char *, int)); +extern int vtof __P((int)); extern void set_variable __P((char *, char *)); extern char *get_variable __P((char *, char **, int)); extern void resetlexer __P((void)); +extern void debug __P((int, char *, ...)); +extern void verbose __P((int, char *, ...)); +extern void ipfkdebug __P((char *, ...)); +extern void ipfkverbose __P((char *, ...)); + #if SOLARIS extern int gethostname __P((char *, int )); extern void sync __P((void)); diff --git a/ipf_rb.h b/ipf_rb.h new file mode 100644 index 0000000000000..3d7a59d99d366 --- /dev/null +++ b/ipf_rb.h @@ -0,0 +1,364 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + */ +typedef enum rbcolour_e { + C_BLACK = 0, + C_RED = 1 +} rbcolour_t; + +#define RBI_LINK(_n, _t) \ + struct _n##_rb_link { \ + struct _t *left; \ + struct _t *right; \ + struct _t *parent; \ + rbcolour_t colour; \ + } + +#define RBI_HEAD(_n, _t) \ +struct _n##_rb_head { \ + struct _t top; \ + int count; \ + int (* compare)(struct _t *, struct _t *); \ +} + +#define RBI_CODE(_n, _t, _f, _cmp) \ + \ +typedef void (*_n##_rb_walker_t)(_t *, void *); \ + \ +_t * _n##_rb_delete(struct _n##_rb_head *, _t *); \ +void _n##_rb_init(struct _n##_rb_head *); \ +void _n##_rb_insert(struct _n##_rb_head *, _t *); \ +_t * _n##_rb_search(struct _n##_rb_head *, void *); \ +void _n##_rb_walktree(struct _n##_rb_head *, _n##_rb_walker_t, void *);\ + \ +static void \ +rotate_left(struct _n##_rb_head *head, _t *node) \ +{ \ + _t *parent, *tmp1, *tmp2; \ + \ + parent = node->_f.parent; \ + tmp1 = node->_f.right; \ + tmp2 = tmp1->_f.left; \ + node->_f.right = tmp2; \ + if (tmp2 != & _n##_rb_zero) \ + tmp2->_f.parent = node; \ + if (parent == & _n##_rb_zero) \ + head->top._f.right = tmp1; \ + else if (parent->_f.right == node) \ + parent->_f.right = tmp1; \ + else \ + parent->_f.left = tmp1; \ + tmp1->_f.left = node; \ + tmp1->_f.parent = parent; \ + node->_f.parent = tmp1; \ +} \ + \ +static void \ +rotate_right(struct _n##_rb_head *head, _t *node) \ +{ \ + _t *parent, *tmp1, *tmp2; \ + \ + parent = node->_f.parent; \ + tmp1 = node->_f.left; \ + tmp2 = tmp1->_f.right; \ + node->_f.left = tmp2; \ + if (tmp2 != &_n##_rb_zero) \ + tmp2->_f.parent = node; \ + if (parent == &_n##_rb_zero) \ + head->top._f.right = tmp1; \ + else if (parent->_f.right == node) \ + parent->_f.right = tmp1; \ + else \ + parent->_f.left = tmp1; \ + tmp1->_f.right = node; \ + tmp1->_f.parent = parent; \ + node->_f.parent = tmp1; \ +} \ + \ +void \ +_n##_rb_insert(struct _n##_rb_head *head, _t *node) \ +{ \ + _t *n, *parent, **p, *tmp1, *gparent; \ + \ + parent = &head->top; \ + node->_f.left = &_n##_rb_zero; \ + node->_f.right = &_n##_rb_zero; \ + p = &head->top._f.right; \ + while ((n = *p) != &_n##_rb_zero) { \ + if (_cmp(node, n) < 0) \ + p = &n->_f.left; \ + else \ + p = &n->_f.right; \ + parent = n; \ + } \ + *p = node; \ + node->_f.colour = C_RED; \ + node->_f.parent = parent; \ + \ + while ((node != &_n##_rb_zero) && (parent->_f.colour == C_RED)){\ + gparent = parent->_f.parent; \ + if (parent == gparent->_f.left) { \ + tmp1 = gparent->_f.right; \ + if (tmp1->_f.colour == C_RED) { \ + parent->_f.colour = C_BLACK; \ + tmp1->_f.colour = C_BLACK; \ + gparent->_f.colour = C_RED; \ + node = gparent; \ + } else { \ + if (node == parent->_f.right) { \ + node = parent; \ + rotate_left(head, node); \ + parent = node->_f.parent; \ + } \ + parent->_f.colour = C_BLACK; \ + gparent->_f.colour = C_RED; \ + rotate_right(head, gparent); \ + } \ + } else { \ + tmp1 = gparent->_f.left; \ + if (tmp1->_f.colour == C_RED) { \ + parent->_f.colour = C_BLACK; \ + tmp1->_f.colour = C_BLACK; \ + gparent->_f.colour = C_RED; \ + node = gparent; \ + } else { \ + if (node == parent->_f.left) { \ + node = parent; \ + rotate_right(head, node); \ + parent = node->_f.parent; \ + } \ + parent->_f.colour = C_BLACK; \ + gparent->_f.colour = C_RED; \ + rotate_left(head, parent->_f.parent); \ + } \ + } \ + parent = node->_f.parent; \ + } \ + head->top._f.right->_f.colour = C_BLACK; \ + head->count++; \ +} \ + \ +static void \ +deleteblack(struct _n##_rb_head *head, _t *parent, _t *node) \ +{ \ + _t *tmp; \ + \ + while ((node == &_n##_rb_zero || node->_f.colour == C_BLACK) && \ + node != &head->top) { \ + if (parent->_f.left == node) { \ + tmp = parent->_f.right; \ + if (tmp->_f.colour == C_RED) { \ + tmp->_f.colour = C_BLACK; \ + parent->_f.colour = C_RED; \ + rotate_left(head, parent); \ + tmp = parent->_f.right; \ + } \ + if ((tmp->_f.left == &_n##_rb_zero || \ + tmp->_f.left->_f.colour == C_BLACK) && \ + (tmp->_f.right == &_n##_rb_zero || \ + tmp->_f.right->_f.colour == C_BLACK)) { \ + tmp->_f.colour = C_RED; \ + node = parent; \ + parent = node->_f.parent; \ + } else { \ + if (tmp->_f.right == &_n##_rb_zero || \ + tmp->_f.right->_f.colour == C_BLACK) {\ + _t *tmp2 = tmp->_f.left; \ + \ + if (tmp2 != &_n##_rb_zero) \ + tmp2->_f.colour = C_BLACK;\ + tmp->_f.colour = C_RED; \ + rotate_right(head, tmp); \ + tmp = parent->_f.right; \ + } \ + tmp->_f.colour = parent->_f.colour; \ + parent->_f.colour = C_BLACK; \ + if (tmp->_f.right != &_n##_rb_zero) \ + tmp->_f.right->_f.colour = C_BLACK;\ + rotate_left(head, parent); \ + node = head->top._f.right; \ + } \ + } else { \ + tmp = parent->_f.left; \ + if (tmp->_f.colour == C_RED) { \ + tmp->_f.colour = C_BLACK; \ + parent->_f.colour = C_RED; \ + rotate_right(head, parent); \ + tmp = parent->_f.left; \ + } \ + if ((tmp->_f.left == &_n##_rb_zero || \ + tmp->_f.left->_f.colour == C_BLACK) && \ + (tmp->_f.right == &_n##_rb_zero || \ + tmp->_f.right->_f.colour == C_BLACK)) { \ + tmp->_f.colour = C_RED; \ + node = parent; \ + parent = node->_f.parent; \ + } else { \ + if (tmp->_f.left == &_n##_rb_zero || \ + tmp->_f.left->_f.colour == C_BLACK) {\ + _t *tmp2 = tmp->_f.right; \ + \ + if (tmp2 != &_n##_rb_zero) \ + tmp2->_f.colour = C_BLACK;\ + tmp->_f.colour = C_RED; \ + rotate_left(head, tmp); \ + tmp = parent->_f.left; \ + } \ + tmp->_f.colour = parent->_f.colour; \ + parent->_f.colour = C_BLACK; \ + if (tmp->_f.left != &_n##_rb_zero) \ + tmp->_f.left->_f.colour = C_BLACK;\ + rotate_right(head, parent); \ + node = head->top._f.right; \ + break; \ + } \ + } \ + } \ + if (node != &_n##_rb_zero) \ + node->_f.colour = C_BLACK; \ +} \ + \ +_t * \ +_n##_rb_delete(struct _n##_rb_head *head, _t *node) \ +{ \ + _t *child, *parent, *old = node, *left; \ + rbcolour_t color; \ + \ + if (node->_f.left == &_n##_rb_zero) { \ + child = node->_f.right; \ + } else if (node->_f.right == &_n##_rb_zero) { \ + child = node->_f.left; \ + } else { \ + node = node->_f.right; \ + while ((left = node->_f.left) != &_n##_rb_zero) \ + node = left; \ + child = node->_f.right; \ + parent = node->_f.parent; \ + color = node->_f.colour; \ + if (child != &_n##_rb_zero) \ + child->_f.parent = parent; \ + if (parent != &_n##_rb_zero) { \ + if (parent->_f.left == node) \ + parent->_f.left = child; \ + else \ + parent->_f.right = child; \ + } else { \ + head->top._f.right = child; \ + } \ + if (node->_f.parent == old) \ + parent = node; \ + *node = *old; \ + if (old->_f.parent != &_n##_rb_zero) { \ + if (old->_f.parent->_f.left == old) \ + old->_f.parent->_f.left = node; \ + else \ + old->_f.parent->_f.right = node; \ + } else { \ + head->top._f.right = child; \ + } \ + old->_f.left->_f.parent = node; \ + if (old->_f.right != &_n##_rb_zero) \ + old->_f.right->_f.parent = node; \ + if (parent != &_n##_rb_zero) { \ + left = parent; \ + } \ + goto colour; \ + } \ + parent = node->_f.parent; \ + color= node->_f.colour; \ + if (child != &_n##_rb_zero) \ + child->_f.parent = parent; \ + if (parent != &_n##_rb_zero) { \ + if (parent->_f.left == node) \ + parent->_f.left = child; \ + else \ + parent->_f.right = child; \ + } else { \ + head->top._f.right = child; \ + } \ +colour: \ + if (color == C_BLACK) \ + deleteblack(head, parent, node); \ + head->count--; \ + return old; \ +} \ + \ +void \ +_n##_rb_init(struct _n##_rb_head *head) \ +{ \ + memset(head, 0, sizeof(*head)); \ + memset(&_n##_rb_zero, 0, sizeof(_n##_rb_zero)); \ + head->top._f.left = &_n##_rb_zero; \ + head->top._f.right = &_n##_rb_zero; \ + head->top._f.parent = &head->top; \ + _n##_rb_zero._f.left = &_n##_rb_zero; \ + _n##_rb_zero._f.right = &_n##_rb_zero; \ + _n##_rb_zero._f.parent = &_n##_rb_zero; \ +} \ + \ +void \ +_n##_rb_walktree(struct _n##_rb_head *head, _n##_rb_walker_t func, void *arg)\ +{ \ + _t *prev; \ + _t *next; \ + _t *node = head->top._f.right; \ + _t *base; \ + \ + while (node != &_n##_rb_zero) \ + node = node->_f.left; \ + \ + for (;;) { \ + base = node; \ + prev = node; \ + while ((node->_f.parent->_f.right == node) && \ + (node != &_n##_rb_zero)) { \ + prev = node; \ + node = node->_f.parent; \ + } \ + \ + node = prev; \ + for (node = node->_f.parent->_f.right; node != &_n##_rb_zero;\ + node = node->_f.left) \ + prev = node; \ + next = prev; \ + \ + if (node != &_n##_rb_zero) \ + func(node, arg); \ + \ + node = next; \ + if (node == &_n##_rb_zero) \ + break; \ + } \ +} \ + \ +_t * \ +_n##_rb_search(struct _n##_rb_head *head, void *key) \ +{ \ + int match; \ + _t *node; \ + node = head->top._f.right; \ + while (node != &_n##_rb_zero) { \ + match = _cmp(key, node); \ + if (match == 0) \ + break; \ + if (match< 0) \ + node = node->_f.left; \ + else \ + node = node->_f.right; \ + } \ + if (node == &_n##_rb_zero || match != 0) \ + return (NULL); \ + return (node); \ +} + +#define RBI_DELETE(_n, _h, _v) _n##_rb_delete(_h, _v) +#define RBI_FIELD(_n) struct _n##_rb_link +#define RBI_INIT(_n, _h) _n##_rb_init(_h) +#define RBI_INSERT(_n, _h, _v) _n##_rb_insert(_h, _v) +#define RBI_ISEMPTY(_h) ((_h)->count == 0) +#define RBI_SEARCH(_n, _h, _k) _n##_rb_search(_h, _k) +#define RBI_WALK(_n, _h, _w, _a) _n##_rb_walktree(_h, _w, _a) +#define RBI_ZERO(_n) _n##_rb_zero diff --git a/ipfs.c b/ipfs.c deleted file mode 100644 index ffbd71bd64889..0000000000000 --- a/ipfs.c +++ /dev/null @@ -1,859 +0,0 @@ -/* - * Copyright (C) 1999-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - */ -#ifdef __FreeBSD__ -# ifndef __FreeBSD_cc_version -# include <osreldate.h> -# else -# if __FreeBSD_cc_version < 430000 -# include <osreldate.h> -# endif -# endif -#endif -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <fcntl.h> -#include <errno.h> -#if !defined(__SVR4) && !defined(__GNUC__) -#include <strings.h> -#endif -#include <sys/types.h> -#include <sys/param.h> -#include <sys/file.h> -#include <stdlib.h> -#include <stddef.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <sys/time.h> -#include <net/if.h> -#if __FreeBSD_version >= 300000 -# include <net/if_var.h> -#endif -#include <netinet/ip.h> -#include <netdb.h> -#include <arpa/nameser.h> -#include <resolv.h> -#include "ip_compat.h" -#include "ip_fil.h" -#include "ip_nat.h" -#include "ip_state.h" -#include "ipf.h" - -#if !defined(lint) -static const char rcsid[] = "@(#)$Id: ipfs.c,v 2.6.2.15 2003/05/31 02:12:21 darrenr Exp $"; -#endif - -#ifndef IPF_SAVEDIR -# define IPF_SAVEDIR "/var/db/ipf" -#endif -#ifndef IPF_NATFILE -# define IPF_NATFILE "ipnat.ipf" -#endif -#ifndef IPF_STATEFILE -# define IPF_STATEFILE "ipstate.ipf" -#endif - -#if !defined(__SVR4) && defined(__GNUC__) -extern char *index __P((const char *, int)); -#endif - -extern char *optarg; -extern int optind; - -int main __P((int, char *[])); -void usage __P((void)); -int changestateif __P((char *, char *)); -int changenatif __P((char *, char *)); -int readstate __P((int, char *)); -int readnat __P((int, char *)); -int writestate __P((int, char *)); -int opendevice __P((char *)); -void closedevice __P((int)); -int setlock __P((int, int)); -int writeall __P((char *)); -int readall __P((char *)); -int writenat __P((int, char *)); -char *concat __P((char *, char *)); - -int opts = 0; -char *progname; - - -void usage() -{ - fprintf(stderr, "\ -usage: %s [-nv] -l\n\ -usage: %s [-nv] -u\n\ -usage: %s [-nv] [-d <dir>] -R\n\ -usage: %s [-nv] [-d <dir>] -W\n\ -usage: %s [-nv] -N [-f <file> | -d <dir>] -r\n\ -usage: %s [-nv] -S [-f <file> | -d <dir>] -r\n\ -usage: %s [-nv] -N [-f <file> | -d <dir>] -w\n\ -usage: %s [-nv] -S [-f <file> | -d <dir>] -w\n\ -usage: %s [-nv] -N [-f <filename> | -d <dir> ] -i <if1>,<if2>\n\ -usage: %s [-nv] -S [-f <filename> | -d <dir> ] -i <if1>,<if2>\n\ -", progname, progname, progname, progname, progname, progname, - progname, progname, progname, progname); - exit(1); -} - - -/* - * Change interface names in state information saved out to disk. - */ -int changestateif(ifs, fname) -char *ifs, *fname; -{ - int fd, olen, nlen, rw; - ipstate_save_t ips; - off_t pos; - char *s; - - s = strchr(ifs, ','); - if (!s) - usage(); - *s++ = '\0'; - nlen = strlen(s); - olen = strlen(ifs); - if (nlen >= sizeof(ips.ips_is.is_ifname) || - olen >= sizeof(ips.ips_is.is_ifname)) - usage(); - - fd = open(fname, O_RDWR); - if (fd == -1) { - perror("open"); - exit(1); - } - - for (pos = 0; read(fd, &ips, sizeof(ips)) == sizeof(ips); ) { - rw = 0; - if (!strncmp(ips.ips_is.is_ifname[0], ifs, olen + 1)) { - strcpy(ips.ips_is.is_ifname[0], s); - rw = 1; - } - if (!strncmp(ips.ips_is.is_ifname[1], ifs, olen + 1)) { - strcpy(ips.ips_is.is_ifname[1], s); - rw = 1; - } - if (rw == 1) { - if (lseek(fd, pos, SEEK_SET) != pos) { - perror("lseek"); - exit(1); - } - if (write(fd, &ips, sizeof(ips)) != sizeof(ips)) { - perror("write"); - exit(1); - } - } - pos = lseek(fd, 0, SEEK_CUR); - } - close(fd); - - return 0; -} - - -/* - * Change interface names in NAT information saved out to disk. - */ -int changenatif(ifs, fname) -char *ifs, *fname; -{ - int fd, olen, nlen, rw; - nat_save_t ipn; - nat_t *nat; - off_t pos; - char *s; - - s = strchr(ifs, ','); - if (!s) - usage(); - *s++ = '\0'; - nlen = strlen(s); - olen = strlen(ifs); - nat = &ipn.ipn_nat; - if (nlen >= sizeof(nat->nat_ifname) || olen >= sizeof(nat->nat_ifname)) - usage(); - - fd = open(fname, O_RDWR); - if (fd == -1) { - perror("open"); - exit(1); - } - - for (pos = 0; read(fd, &ipn, sizeof(ipn)) == sizeof(ipn); ) { - rw = 0; - if (!strncmp(nat->nat_ifname, ifs, olen + 1)) { - strcpy(nat->nat_ifname, s); - rw = 1; - } - if (rw == 1) { - if (lseek(fd, pos, SEEK_SET) != pos) { - perror("lseek"); - exit(1); - } - if (write(fd, &ipn, sizeof(ipn)) != sizeof(ipn)) { - perror("write"); - exit(1); - } - } - pos = lseek(fd, 0, SEEK_CUR); - } - close(fd); - - return 0; -} - - -int main(argc,argv) -int argc; -char *argv[]; -{ - int c, lock = -1, devfd = -1, err = 0, rw = -1, ns = -1, set = 0; - char *dirname = NULL, *filename = NULL, *ifs = NULL; - - progname = argv[0]; - - while ((c = getopt(argc, argv, "d:f:i:lNnSRruvWw")) != -1) - switch (c) - { - case 'd' : - if ((set == 0) && !dirname && !filename) - dirname = optarg; - else - usage(); - break; - case 'f' : - if ((set == 1) && !dirname && !filename && !(rw & 2)) - filename = optarg; - else - usage(); - break; - case 'i' : - ifs = optarg; - set = 1; - break; - case 'l' : - if (filename || dirname || set) - usage(); - lock = 1; - set = 1; - break; - case 'n' : - opts |= OPT_DONOTHING; - break; - case 'N' : - if ((ns >= 0) || dirname || (rw != -1) || set) - usage(); - ns = 0; - set = 1; - break; - case 'r' : - if (dirname || (rw != -1) || (ns == -1)) - usage(); - rw = 0; - set = 1; - break; - case 'R' : - if (filename || (ns != -1)) - usage(); - rw = 2; - set = 1; - break; - case 'S' : - if ((ns >= 0) || dirname || (rw != -1) || set) - usage(); - ns = 1; - set = 1; - break; - case 'u' : - if (filename || dirname || set) - usage(); - lock = 0; - set = 1; - break; - case 'v' : - opts |= OPT_VERBOSE; - break; - case 'w' : - if (dirname || (rw != -1) || (ns == -1)) - usage(); - rw = 1; - set = 1; - break; - case 'W' : - if (filename || (ns != -1)) - usage(); - rw = 3; - set = 1; - break; - case '?' : - default : - usage(); - } - - if (optind < 2) - usage(); - - if (filename == NULL) { - if (ns == 0) { - if (dirname == NULL) - dirname = IPF_SAVEDIR; - if (dirname[strlen(dirname) - 1] != '/') - dirname = concat(dirname, "/"); - filename = concat(dirname, IPF_NATFILE); - } else if (ns == 1) { - if (dirname == NULL) - dirname = IPF_SAVEDIR; - if (dirname[strlen(dirname) - 1] != '/') - dirname = concat(dirname, "/"); - filename = concat(dirname, IPF_STATEFILE); - } - } - - if (ifs) { - if (!filename || ns < 0) - usage(); - if (ns == 0) - return changenatif(ifs, filename); - else - return changestateif(ifs, filename); - } - - if ((ns >= 0) || (lock >= 0)) { - if (lock >= 0) - devfd = opendevice(NULL); - else if (ns >= 0) { - if (ns == 1) - devfd = opendevice(IPL_STATE); - else if (ns == 0) - devfd = opendevice(IPL_NAT); - } - if (devfd == -1) - exit(1); - } - - if (lock >= 0) - err = setlock(devfd, lock); - else if (rw >= 0) { - if (rw & 1) { /* WRITE */ - if (rw & 2) - err = writeall(dirname); - else { - if (ns == 0) - err = writenat(devfd, filename); - else if (ns == 1) - err = writestate(devfd, filename); - } - } else { - if (rw & 2) - err = readall(dirname); - else { - if (ns == 0) - err = readnat(devfd, filename); - else if (ns == 1) - err = readstate(devfd, filename); - } - } - } - return err; -} - - -char *concat(base, append) -char *base, *append; -{ - char *str; - - str = malloc(strlen(base) + strlen(append) + 1); - if (str != NULL) { - strcpy(str, base); - strcat(str, append); - } - return str; -} - - -int opendevice(ipfdev) -char *ipfdev; -{ - int fd = -1; - - if (opts & OPT_DONOTHING) - return -2; - - if (!ipfdev) - ipfdev = IPL_NAME; - - if ((fd = open(ipfdev, O_RDWR)) == -1) - if ((fd = open(ipfdev, O_RDONLY)) == -1) - perror("open device"); - return fd; -} - - -void closedevice(fd) -int fd; -{ - close(fd); -} - - -int setlock(fd, lock) -int fd, lock; -{ - if (opts & OPT_VERBOSE) - printf("Turn lock %s\n", lock ? "on" : "off"); - if (!(opts & OPT_DONOTHING)) { - if (ioctl(fd, SIOCSTLCK, &lock) == -1) { - perror("SIOCSTLCK"); - return 1; - } - if (opts & OPT_VERBOSE) - printf("Lock now %s\n", lock ? "on" : "off"); - } - return 0; -} - - -int writestate(fd, file) -int fd; -char *file; -{ - ipstate_save_t ips, *ipsp; - int wfd = -1; - - if (!file) - file = IPF_STATEFILE; - - wfd = open(file, O_WRONLY|O_TRUNC|O_CREAT, 0600); - if (wfd == -1) { - fprintf(stderr, "%s ", file); - perror("state:open"); - return 1; - } - - ipsp = &ips; - bzero((char *)ipsp, sizeof(ips)); - - do { - if (opts & OPT_VERBOSE) - printf("Getting state from addr %p\n", ips.ips_next); - if (ioctl(fd, SIOCSTGET, &ipsp)) { - if (errno == ENOENT) - break; - perror("state:SIOCSTGET"); - close(wfd); - return 1; - } - if (opts & OPT_VERBOSE) - printf("Got state next %p\n", ips.ips_next); - if (write(wfd, ipsp, sizeof(ips)) != sizeof(ips)) { - perror("state:write"); - close(wfd); - return 1; - } - } while (ips.ips_next != NULL); - close(wfd); - - return 0; -} - - -int readstate(fd, file) -int fd; -char *file; -{ - ipstate_save_t ips, *is, *ipshead = NULL, *is1, *ipstail = NULL; - int sfd = -1, i; - - if (!file) - file = IPF_STATEFILE; - - sfd = open(file, O_RDONLY, 0600); - if (sfd == -1) { - fprintf(stderr, "%s ", file); - perror("open"); - return 1; - } - - bzero((char *)&ips, sizeof(ips)); - - /* - * 1. Read all state information in. - */ - do { - i = read(sfd, &ips, sizeof(ips)); - if (i == -1) { - perror("read"); - close(sfd); - return 1; - } - if (i == 0) - break; - if (i != sizeof(ips)) { - fprintf(stderr, "incomplete read: %d != %d\n", i, - (int)sizeof(ips)); - close(sfd); - return 1; - } - is = (ipstate_save_t *)malloc(sizeof(*is)); - if(!is) { - fprintf(stderr, "malloc failed\n"); - return 1; - } - - bcopy((char *)&ips, (char *)is, sizeof(ips)); - - /* - * Check to see if this is the first state entry that will - * reference a particular rule and if so, flag it as such - * else just adjust the rule pointer to become a pointer to - * the other. We do this so we have a means later for tracking - * who is referencing us when we get back the real pointer - * in is_rule after doing the ioctl. - */ - for (is1 = ipshead; is1 != NULL; is1 = is1->ips_next) - if (is1->ips_rule == is->ips_rule) - break; - if (is1 == NULL) - is->ips_is.is_flags |= FI_NEWFR; - else - is->ips_rule = (void *)&is1->ips_rule; - - /* - * Use a tail-queue type list (add things to the end).. - */ - is->ips_next = NULL; - if (!ipshead) - ipshead = is; - if (ipstail) - ipstail->ips_next = is; - ipstail = is; - } while (1); - - close(sfd); - - for (is = ipshead; is; is = is->ips_next) { - if (opts & OPT_VERBOSE) - printf("Loading new state table entry\n"); - if (is->ips_is.is_flags & FI_NEWFR) { - if (opts & OPT_VERBOSE) - printf("Loading new filter rule\n"); - } - if (!(opts & OPT_DONOTHING)) - if (ioctl(fd, SIOCSTPUT, &is)) { - perror("SIOCSTPUT"); - return 1; - } - - if (is->ips_is.is_flags & FI_NEWFR) { - if (opts & OPT_VERBOSE) - printf("Real rule addr %p\n", is->ips_rule); - for (is1 = is->ips_next; is1; is1 = is1->ips_next) - if (is1->ips_rule == (frentry_t *)&is->ips_rule) - is1->ips_rule = is->ips_rule; - } - } - - return 0; -} - - -int readnat(fd, file) -int fd; -char *file; -{ - nat_save_t ipn, *in, *ipnhead = NULL, *in1, *ipntail = NULL; - int nfd = -1, i; - nat_t *nat; - char *s; - int n; - - if (!file) - file = IPF_NATFILE; - - nfd = open(file, O_RDONLY); - if (nfd == -1) { - fprintf(stderr, "%s ", file); - perror("nat:open"); - return 1; - } - - bzero((char *)&ipn, sizeof(ipn)); - - /* - * 1. Read all state information in. - */ - do { - i = read(nfd, &ipn, sizeof(ipn)); - if (i == -1) { - perror("read"); - close(nfd); - return 1; - } - if (i == 0) - break; - if (i != sizeof(ipn)) { - fprintf(stderr, "incomplete read: %d != %d\n", i, - (int)sizeof(ipn)); - close(nfd); - return 1; - } - - if (ipn.ipn_dsize > 0) { - n = ipn.ipn_dsize; - - if (n > sizeof(ipn.ipn_data)) - n -= sizeof(ipn.ipn_data); - else - n = 0; - in = malloc(sizeof(*in) + n); - if (!in) - break; - - if (n > 0) { - s = in->ipn_data + sizeof(in->ipn_data); - i = read(nfd, s, n); - if (i == 0) - break; - if (i != n) { - fprintf(stderr, - "incomplete read: %d != %d\n", - i, n); - close(nfd); - return 1; - } - } - } else - in = (nat_save_t *)malloc(sizeof(*in)); - bcopy((char *)&ipn, (char *)in, sizeof(ipn)); - - /* - * Check to see if this is the first NAT entry that will - * reference a particular rule and if so, flag it as such - * else just adjust the rule pointer to become a pointer to - * the other. We do this so we have a means later for tracking - * who is referencing us when we get back the real pointer - * in is_rule after doing the ioctl. - */ - nat = &in->ipn_nat; - if (nat->nat_fr != NULL) { - for (in1 = ipnhead; in1 != NULL; in1 = in1->ipn_next) - if (in1->ipn_rule == nat->nat_fr) - break; - if (in1 == NULL) - nat->nat_flags |= FI_NEWFR; - else - nat->nat_fr = &in1->ipn_fr; - } - - /* - * Use a tail-queue type list (add things to the end).. - */ - in->ipn_next = NULL; - if (!ipnhead) - ipnhead = in; - if (ipntail) - ipntail->ipn_next = in; - ipntail = in; - } while (1); - - close(nfd); - nfd = -1; - - for (in = ipnhead; in; in = in->ipn_next) { - if (opts & OPT_VERBOSE) - printf("Loading new NAT table entry\n"); - nat = &in->ipn_nat; - if (nat->nat_flags & FI_NEWFR) { - if (opts & OPT_VERBOSE) - printf("Loading new filter rule\n"); - } - if (!(opts & OPT_DONOTHING)) - if (ioctl(fd, SIOCSTPUT, &in)) { - perror("SIOCSTPUT"); - return 1; - } - - if (nat->nat_flags & FI_NEWFR) { - if (opts & OPT_VERBOSE) - printf("Real rule addr %p\n", nat->nat_fr); - for (in1 = in->ipn_next; in1; in1 = in1->ipn_next) - if (in1->ipn_rule == &in->ipn_fr) - in1->ipn_rule = nat->nat_fr; - } - } - - return 0; -} - - -int writenat(fd, file) -int fd; -char *file; -{ - nat_save_t *ipnp = NULL, *next = NULL; - int nfd = -1; - natget_t ng; - - if (!file) - file = IPF_NATFILE; - - nfd = open(file, O_WRONLY|O_TRUNC|O_CREAT, 0600); - if (nfd == -1) { - fprintf(stderr, "%s ", file); - perror("nat:open"); - return 1; - } - - - do { - if (opts & OPT_VERBOSE) - printf("Getting nat from addr %p\n", ipnp); - ng.ng_ptr = next; - ng.ng_sz = 0; - if (ioctl(fd, SIOCSTGSZ, &ng)) { - perror("nat:SIOCSTGSZ"); - close(nfd); - return 1; - } - - if (opts & OPT_VERBOSE) - printf("NAT size %d from %p\n", ng.ng_sz, ng.ng_ptr); - - if (ng.ng_sz == 0) - break; - - if (!ipnp) - ipnp = malloc(ng.ng_sz); - else - ipnp = realloc((char *)ipnp, ng.ng_sz); - if (!ipnp) { - fprintf(stderr, - "malloc for %d bytes failed\n", ng.ng_sz); - break; - } - - bzero((char *)ipnp, ng.ng_sz); - ipnp->ipn_next = next; - if (ioctl(fd, SIOCSTGET, &ipnp)) { - if (errno == ENOENT) - break; - perror("nat:SIOCSTGET"); - close(nfd); - return 1; - } - - if (opts & OPT_VERBOSE) - printf("Got nat next %p\n", ipnp->ipn_next); - if (write(nfd, ipnp, ng.ng_sz) != ng.ng_sz) { - perror("nat:write"); - close(nfd); - return 1; - } - next = ipnp->ipn_next; - } while (ipnp && next); - close(nfd); - - return 0; -} - - -int writeall(dirname) -char *dirname; -{ - int fd, devfd; - - if (!dirname) - dirname = IPF_SAVEDIR; - - if (chdir(dirname)) { - fprintf(stderr, "IPF_SAVEDIR=%s: ", dirname); - perror("chdir(IPF_SAVEDIR)"); - return 1; - } - - fd = opendevice(NULL); - if (fd == -1) - return 1; - if (setlock(fd, 1)) { - close(fd); - return 1; - } - - devfd = opendevice(IPL_STATE); - if (devfd == -1) - goto bad; - if (writestate(devfd, NULL)) - goto bad; - close(devfd); - - devfd = opendevice(IPL_NAT); - if (devfd == -1) - goto bad; - if (writenat(devfd, NULL)) - goto bad; - close(devfd); - - if (setlock(fd, 0)) { - close(fd); - return 1; - } - - return 0; - -bad: - setlock(fd, 0); - close(fd); - return 1; -} - - -int readall(dirname) -char *dirname; -{ - int fd, devfd; - - if (!dirname) - dirname = IPF_SAVEDIR; - - if (chdir(dirname)) { - perror("chdir(IPF_SAVEDIR)"); - return 1; - } - - fd = opendevice(NULL); - if (fd == -1) - return 1; - if (setlock(fd, 1)) { - close(fd); - return 1; - } - - devfd = opendevice(IPL_STATE); - if (devfd == -1) - return 1; - if (readstate(devfd, NULL)) - return 1; - close(devfd); - - devfd = opendevice(IPL_NAT); - if (devfd == -1) - return 1; - if (readnat(devfd, NULL)) - return 1; - close(devfd); - - if (setlock(fd, 0)) { - close(fd); - return 1; - } - - return 0; -} diff --git a/ipft_ef.c b/ipft_ef.c deleted file mode 100644 index c8ae3f2a59340..0000000000000 --- a/ipft_ef.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - */ - -/* - icmp type - lnth proto source destination src port dst port - -etherfind -n - - 60 tcp 128.250.20.20 128.250.133.13 2419 telnet - -etherfind -n -t - - 0.32 91 04 131.170.1.10 128.250.133.13 - 0.33 566 udp 128.250.37.155 128.250.133.3 901 901 -*/ -#if defined(__sgi) && (IRIX > 602) -# include <sys/ptimers.h> -#endif -#include <stdio.h> -#include <string.h> -#if !defined(__SVR4) && !defined(__GNUC__) -#include <strings.h> -#endif -#include <sys/types.h> -#include <stdlib.h> -#include <unistd.h> -#include <stddef.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <sys/param.h> -#include <sys/time.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netinet/in_systm.h> -#ifndef linux -#include <netinet/ip_var.h> -#endif -#include <netinet/ip.h> -#include <netinet/tcp.h> -#include <netinet/udp.h> -#include <netinet/ip_icmp.h> -#include <net/if.h> -#include <netdb.h> -#include "ip_compat.h" -#include <netinet/tcpip.h> -#include "ipf.h" -#include "ipt.h" - -#if !defined(lint) -static const char sccsid[] = "@(#)ipft_ef.c 1.6 2/4/96 (C)1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipft_ef.c,v 2.2.2.5 2003/05/19 12:02:35 darrenr Exp $"; -#endif - -static int etherf_open __P((char *)); -static int etherf_close __P((void)); -static int etherf_readip __P((char *, int, char **, int *)); - -struct ipread etherf = { etherf_open, etherf_close, etherf_readip }; - -static FILE *efp = NULL; -static int efd = -1; - - -static int etherf_open(fname) -char *fname; -{ - if (efd != -1) - return efd; - - if (!strcmp(fname, "-")) { - efd = 0; - efp = stdin; - } else { - efd = open(fname, O_RDONLY); - efp = fdopen(efd, "r"); - } - return efd; -} - - -static int etherf_close() -{ - return close(efd); -} - - -static int etherf_readip(buf, cnt, ifn, dir) -char *buf, **ifn; -int cnt, *dir; -{ - struct tcpiphdr pkt; - ip_t *ip = (ip_t *)&pkt; - struct protoent *p = NULL; - char src[16], dst[16], sprt[16], dprt[16]; - char lbuf[128], len[8], prot[8], time[8], *s; - int slen, extra = 0, i; - - if (!fgets(lbuf, sizeof(lbuf) - 1, efp)) - return 0; - - if ((s = strchr(lbuf, '\n'))) - *s = '\0'; - lbuf[sizeof(lbuf)-1] = '\0'; - - bzero(&pkt, sizeof(pkt)); - - if (sscanf(lbuf, "%7s %7s %15s %15s %15s %15s", len, prot, src, dst, - sprt, dprt) != 6) - if (sscanf(lbuf, "%7s %7s %7s %15s %15s %15s %15s", time, - len, prot, src, dst, sprt, dprt) != 7) - return -1; - - ip->ip_p = atoi(prot); - if (ip->ip_p == 0) { - if (!(p = getprotobyname(prot))) - return -1; - ip->ip_p = p->p_proto; - } - - switch (ip->ip_p) { - case IPPROTO_TCP : - case IPPROTO_UDP : - s = strtok(NULL, " :"); - ip->ip_len += atoi(s); - if (p->p_proto == IPPROTO_TCP) - extra = sizeof(struct tcphdr); - else if (p->p_proto == IPPROTO_UDP) - extra = sizeof(struct udphdr); - break; -#ifdef IGMP - case IPPROTO_IGMP : - extra = sizeof(struct igmp); - break; -#endif - case IPPROTO_ICMP : - extra = sizeof(struct icmp); - break; - default : - break; - } - - (void) inet_aton(src, &ip->ip_src); - (void) inet_aton(dst, &ip->ip_dst); - ip->ip_len = atoi(len); - ip->ip_hl = sizeof(ip_t); - - slen = ip->ip_hl + extra; - i = MIN(cnt, slen); - bcopy((char *)&pkt, buf, i); - return i; -} diff --git a/ipft_hx.c b/ipft_hx.c deleted file mode 100644 index b26bd93e02aad..0000000000000 --- a/ipft_hx.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 1995-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - */ -#if defined(__sgi) && (IRIX > 602) -# include <sys/ptimers.h> -#endif -#include <stdio.h> -#include <ctype.h> -#include <assert.h> -#include <string.h> -#include <sys/types.h> -#if !defined(__SVR4) && !defined(__svr4__) -#include <strings.h> -#else -#include <sys/byteorder.h> -#endif -#include <sys/param.h> -#include <sys/time.h> -#include <stdlib.h> -#include <unistd.h> -#include <stddef.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#ifndef linux -#include <netinet/ip_var.h> -#endif -#include <netinet/ip.h> -#include <netinet/udp.h> -#include <netinet/tcp.h> -#include <netinet/ip_icmp.h> -#include <net/if.h> -#include <netdb.h> -#include <arpa/nameser.h> -#include <resolv.h> -#include "ip_compat.h" -#include <netinet/tcpip.h> -#include "ipf.h" -#include "ipt.h" - -#if !defined(lint) -static const char sccsid[] = "@(#)ipft_hx.c 1.1 3/9/96 (C) 1996 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipft_hx.c,v 2.2.2.6 2002/12/06 11:40:25 darrenr Exp $"; -#endif - -extern int opts; - -static int hex_open __P((char *)); -static int hex_close __P((void)); -static int hex_readip __P((char *, int, char **, int *)); -static char *readhex __P((char *, char *)); - -struct ipread iphex = { hex_open, hex_close, hex_readip }; -static FILE *tfp = NULL; -static int tfd = -1; - -static int hex_open(fname) -char *fname; -{ - if (tfp && tfd != -1) { - rewind(tfp); - return tfd; - } - - if (!strcmp(fname, "-")) { - tfd = 0; - tfp = stdin; - } else { - tfd = open(fname, O_RDONLY); - if (tfd != -1) - tfp = fdopen(tfd, "r"); - } - return tfd; -} - - -static int hex_close() -{ - int cfd = tfd; - - tfd = -1; - return close(cfd); -} - - -static int hex_readip(buf, cnt, ifn, dir) -char *buf, **ifn; -int cnt, *dir; -{ - register char *s, *t, *u; - char line[513]; - ip_t *ip; - - /* - * interpret start of line as possibly "[ifname]" or - * "[in/out,ifname]". - */ - if (ifn) - *ifn = NULL; - if (dir) - *dir = 0; - ip = (ip_t *)buf; - while (fgets(line, sizeof(line)-1, tfp)) { - if ((s = index(line, '\n'))) { - if (s == line) - return (char *)ip - buf; - *s = '\0'; - } - if ((s = index(line, '#'))) - *s = '\0'; - if (!*line) - continue; - if (!(opts & OPT_BRIEF)) { - printf("input: %s\n", line); - fflush(stdout); - } - - if ((*line == '[') && (s = index(line, ']'))) { - t = line + 1; - if (s - t > 0) { - *s++ = '\0'; - if ((u = index(t, ',')) && (u < s)) { - u++; - if (ifn) - *ifn = strdup(u); - if (dir) { - if (*t == 'i') - *dir = 0; - else if (*t == 'o') - *dir = 1; - } - } else if (ifn) - *ifn = t; - } - } else - s = line; - ip = (ip_t *)readhex(s, (char *)ip); - } - return -1; -} - - -static char *readhex(src, dst) -register char *src, *dst; -{ - int state = 0; - char c; - - while ((c = *src++)) { - if (isspace(c)) { - if (state) { - dst++; - state = 0; - } - continue; - } else if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || - (c >= 'A' && c <= 'F')) { - c = isdigit(c) ? (c - '0') : (toupper(c) - 55); - if (state == 0) { - *dst = (c << 4); - state++; - } else { - *dst++ |= c; - state = 0; - } - } else - break; - } - return dst; -} diff --git a/ipft_pc.c b/ipft_pc.c deleted file mode 100644 index b6060de2297db..0000000000000 --- a/ipft_pc.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - */ -#if defined(__sgi) && (IRIX > 602) -# include <sys/ptimers.h> -#endif -#include <stdio.h> -#include <string.h> -#if !defined(__SVR4) && !defined(__GNUC__) -#include <strings.h> -#endif -#include <sys/types.h> -#include <sys/time.h> -#include <stdlib.h> -#include <unistd.h> -#include <stddef.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <sys/param.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#ifndef linux -#include <netinet/ip_var.h> -#endif -#include <netinet/ip.h> -#include <netinet/tcp.h> -#include <net/if.h> -#include "ip_compat.h" -#include <netinet/tcpip.h> -#include "ipf.h" -#include "pcap.h" -#include "bpf.h" -#include "ipt.h" - -#if !defined(lint) -static const char rcsid[] = "@(#)$Id: ipft_pc.c,v 2.2.2.5 2002/12/06 11:40:25 darrenr Exp $"; -#endif - -struct llc { - int lc_type; - int lc_sz; /* LLC header length */ - int lc_to; /* LLC Type offset */ - int lc_tl; /* LLC Type length */ -}; - -/* - * While many of these maybe the same, some do have different header formats - * which make this useful. - */ - -static struct llc llcs[] = { - { DLT_NULL, 0, 0, 0 }, - { DLT_EN10MB, 14, 12, 2 }, - { DLT_EN3MB, 0, 0, 0 }, - { DLT_AX25, 0, 0, 0 }, - { DLT_PRONET, 0, 0, 0 }, - { DLT_CHAOS, 0, 0, 0 }, - { DLT_IEEE802, 0, 0, 0 }, - { DLT_ARCNET, 0, 0, 0 }, - { DLT_SLIP, 0, 0, 0 }, - { DLT_PPP, 0, 0, 0 }, - { DLT_FDDI, 0, 0, 0 }, -#ifdef DLT_ATMRFC1483 - { DLT_ATMRFC1483, 0, 0, 0 }, -#endif - { DLT_RAW, 0, 0, 0 }, -#ifdef DLT_ENC - { DLT_ENC, 0, 0, 0 }, -#endif -#ifdef DLT_SLIP_BSDOS - { DLT_SLIP_BSDOS, 0, 0, 0 }, -#endif -#ifdef DLT_PPP_BSDOS - { DLT_PPP_BSDOS, 0, 0, 0 }, -#endif -#ifdef DLT_HIPPI - { DLT_HIPPI, 0, 0, 0 }, -#endif -#ifdef DLT_HDLC - { DLT_HDLC, 0, 0, 0 }, -#endif -#ifdef DLT_PPP_SERIAL - { DLT_PPP_SERIAL, 4, 4, 0 }, -#endif -#ifdef DLT_PPP_ETHER - { DLT_PPP_ETHER, 8, 8, 0 }, -#endif -#ifdef DLT_ECONET - { DLT_ECONET, 0, 0, 0 }, -#endif - { -1, -1, -1, -1 } -}; - -static int pcap_open __P((char *)); -static int pcap_close __P((void)); -static int pcap_readip __P((char *, int, char **, int *)); -static void swap_hdr __P((pcaphdr_t *)); -static int pcap_read_rec __P((struct pcap_pkthdr *)); - -static int pfd = -1, s_type = -1, swapped = 0; -static struct llc *llcp = NULL; - -struct ipread pcap = { pcap_open, pcap_close, pcap_readip }; - -#define SWAPLONG(y) \ - ((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff)) -#define SWAPSHORT(y) \ - ( (((y)&0xff)<<8) | (((y)&0xff00)>>8) ) - -static void swap_hdr(p) -pcaphdr_t *p; -{ - p->pc_v_maj = SWAPSHORT(p->pc_v_maj); - p->pc_v_min = SWAPSHORT(p->pc_v_min); - p->pc_zone = SWAPLONG(p->pc_zone); - p->pc_sigfigs = SWAPLONG(p->pc_sigfigs); - p->pc_slen = SWAPLONG(p->pc_slen); - p->pc_type = SWAPLONG(p->pc_type); -} - -static int pcap_open(fname) -char *fname; -{ - pcaphdr_t ph; - int fd, i; - - if (pfd != -1) - return pfd; - - if (!strcmp(fname, "-")) - fd = 0; - else if ((fd = open(fname, O_RDONLY)) == -1) - return -1; - - if (read(fd, (char *)&ph, sizeof(ph)) != sizeof(ph)) - return -2; - - if (ph.pc_id != TCPDUMP_MAGIC) { - if (SWAPLONG(ph.pc_id) != TCPDUMP_MAGIC) { - (void) close(fd); - return -2; - } - swapped = 1; - swap_hdr(&ph); - } - - if (ph.pc_v_maj != PCAP_VERSION_MAJ) { - (void) close(fd); - return -2; - } - - for (i = 0; llcs[i].lc_type != -1; i++) - if (llcs[i].lc_type == ph.pc_type) { - llcp = llcs + i; - break; - } - - if (llcp == NULL) { - (void) close(fd); - return -2; - } - - pfd = fd; - s_type = ph.pc_type; - printf("opened pcap file %s:\n", fname); - printf("\tid: %08x version: %d.%d type: %d snap %d\n", - ph.pc_id, ph.pc_v_maj, ph.pc_v_min, ph.pc_type, ph.pc_slen); - - return fd; -} - - -static int pcap_close() -{ - return close(pfd); -} - - -/* - * read in the header (and validate) which should be the first record - * in a pcap file. - */ -static int pcap_read_rec(rec) -struct pcap_pkthdr *rec; -{ - int n, p; - - if (read(pfd, (char *)rec, sizeof(*rec)) != sizeof(*rec)) - return -2; - - if (swapped) { - rec->ph_clen = SWAPLONG(rec->ph_clen); - rec->ph_len = SWAPLONG(rec->ph_len); - rec->ph_ts.tv_sec = SWAPLONG(rec->ph_ts.tv_sec); - rec->ph_ts.tv_usec = SWAPLONG(rec->ph_ts.tv_usec); - } - p = rec->ph_clen; - n = MIN(p, rec->ph_len); - if (!n || n < 0) - return -3; - - return p; -} - - -#ifdef notyet -/* - * read an entire pcap packet record. only the data part is copied into - * the available buffer, with the number of bytes copied returned. - */ -static int pcap_read(buf, cnt) -char *buf; -int cnt; -{ - struct pcap_pkthdr rec; - static char *bufp = NULL; - int i, n; - - if ((i = pcap_read_rec(&rec)) <= 0) - return i; - - if (!bufp) - bufp = malloc(i); - else - bufp = realloc(bufp, i); - - if (read(pfd, bufp, i) != i) - return -2; - - n = MIN(i, cnt); - bcopy(bufp, buf, n); - return n; -} -#endif - - -/* - * return only an IP packet read into buf - */ -static int pcap_readip(buf, cnt, ifn, dir) -char *buf, **ifn; -int cnt, *dir; -{ - static char *bufp = NULL; - struct pcap_pkthdr rec; - struct llc *l; - char *s, ty[4]; - int i, n; - - l = llcp; - - /* do { */ - if ((i = pcap_read_rec(&rec)) <= 0) - return i; - - if (!bufp) - bufp = malloc(i); - else - bufp = realloc(bufp, i); - s = bufp; - - if (read(pfd, s, i) != i) - return -2; - - i -= l->lc_sz; - s += l->lc_to; - bcopy(s, ty, l->lc_tl); - s += l->lc_tl; - /* } while (ty[0] != 0x8 && ty[1] != 0); */ - n = MIN(i, cnt); - bcopy(s, buf, n); - return n; -} diff --git a/ipft_sn.c b/ipft_sn.c deleted file mode 100644 index 859bf5ed9df72..0000000000000 --- a/ipft_sn.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - */ - -/* - * Written to comply with the recent RFC 1761 from Sun. - */ -#if defined(__sgi) && (IRIX > 602) -# include <sys/ptimers.h> -#endif -#include <stdio.h> -#include <string.h> -#if !defined(__SVR4) && !defined(__GNUC__) -#include <strings.h> -#endif -#include <sys/types.h> -#include <stdlib.h> -#include <unistd.h> -#include <stddef.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <sys/param.h> -#include <sys/time.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#ifndef linux -#include <netinet/ip_var.h> -#endif -#include <netinet/ip.h> -#include <netinet/tcp.h> -#include <net/if.h> -#include "ip_compat.h" -#include <netinet/tcpip.h> -#include "ipf.h" -#include "snoop.h" -#include "ipt.h" - -#if !defined(lint) -static const char rcsid[] = "@(#)$Id: ipft_sn.c,v 2.2.2.4 2002/12/06 11:40:26 darrenr Exp $"; -#endif - -struct llc { - int lc_sz; /* LLC header length */ - int lc_to; /* LLC Type offset */ - int lc_tl; /* LLC Type length */ -}; - -/* - * While many of these maybe the same, some do have different header formats - * which make this useful. - */ -static struct llc llcs[SDL_MAX+1] = { - { 0, 0, 0 }, /* SDL_8023 */ - { 0, 0, 0 }, /* SDL_8024 */ - { 0, 0, 0 }, /* SDL_8025 */ - { 0, 0, 0 }, /* SDL_8026 */ - { 14, 12, 2 }, /* SDL_ETHER */ - { 0, 0, 0 }, /* SDL_HDLC */ - { 0, 0, 0 }, /* SDL_CHSYNC */ - { 0, 0, 0 }, /* SDL_IBMCC */ - { 0, 0, 0 }, /* SDL_FDDI */ - { 0, 0, 0 }, /* SDL_OTHER */ -}; - -static int snoop_open __P((char *)); -static int snoop_close __P((void)); -static int snoop_readip __P((char *, int, char **, int *)); - -static int sfd = -1, s_type = -1; -static int snoop_read_rec __P((struct snooppkt *)); - -struct ipread snoop = { snoop_open, snoop_close, snoop_readip }; - - -static int snoop_open(fname) -char *fname; -{ - struct snoophdr sh; - int fd; - int s_v; - - if (sfd != -1) - return sfd; - - if (!strcmp(fname, "-")) - fd = 0; - else if ((fd = open(fname, O_RDONLY)) == -1) - return -1; - - if (read(fd, (char *)&sh, sizeof(sh)) != sizeof(sh)) - return -2; - - s_v = (int)ntohl(sh.s_v); - s_type = (int)ntohl(sh.s_type); - - if (s_v != SNOOP_VERSION || - s_type < 0 || s_type > SDL_MAX) { - (void) close(fd); - return -2; - } - - sfd = fd; - printf("opened snoop file %s:\n", fname); - printf("\tid: %8.8s version: %d type: %d\n", sh.s_id, s_v, s_type); - - return fd; -} - - -static int snoop_close() -{ - return close(sfd); -} - - -/* - * read in the header (and validate) which should be the first record - * in a snoop file. - */ -static int snoop_read_rec(rec) -struct snooppkt *rec; -{ - int n, plen, ilen; - - if (read(sfd, (char *)rec, sizeof(*rec)) != sizeof(*rec)) - return -2; - - ilen = (int)ntohl(rec->sp_ilen); - plen = (int)ntohl(rec->sp_plen); - if (ilen > plen || plen < sizeof(*rec)) - return -2; - - plen -= sizeof(*rec); - n = MIN(plen, ilen); - if (!n || n < 0) - return -3; - - return plen; -} - - -#ifdef notyet -/* - * read an entire snoop packet record. only the data part is copied into - * the available buffer, with the number of bytes copied returned. - */ -static int snoop_read(buf, cnt) -char *buf; -int cnt; -{ - struct snooppkt rec; - static char *bufp = NULL; - int i, n; - - if ((i = snoop_read_rec(&rec)) <= 0) - return i; - - if (!bufp) - bufp = malloc(i); - else - bufp = realloc(bufp, i); - - if (read(sfd, bufp, i) != i) - return -2; - - n = MIN(i, cnt); - bcopy(bufp, buf, n); - return n; -} -#endif - - -/* - * return only an IP packet read into buf - */ -static int snoop_readip(buf, cnt, ifn, dir) -char *buf, **ifn; -int cnt, *dir; -{ - static char *bufp = NULL; - struct snooppkt rec; - struct llc *l; - char ty[4], *s; - int i, n; - - do { - if ((i = snoop_read_rec(&rec)) <= 0) - return i; - - if (!bufp) - bufp = malloc(i); - else - bufp = realloc(bufp, i); - s = bufp; - - if (read(sfd, s, i) != i) - return -2; - - l = &llcs[s_type]; - i -= l->lc_to; - s += l->lc_to; - /* - * XXX - bogus assumption here on the part of the time field - * that it won't be greater than 4 bytes and the 1st two will - * have the values 8 and 0 for IP. Should be a table of - * these too somewhere. Really only works for SDL_ETHER. - */ - bcopy(s, ty, l->lc_tl); - } while (ty[0] != 0x8 && ty[1] != 0); - - i -= l->lc_tl; - s += l->lc_tl; - n = MIN(i, cnt); - bcopy(s, buf, n); - - return n; -} diff --git a/ipft_td.c b/ipft_td.c deleted file mode 100644 index 99beab5b6a446..0000000000000 --- a/ipft_td.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - */ - -/* -tcpdump -n - -00:05:47.816843 128.231.76.76.3291 > 224.2.252.231.36573: udp 36 (encap) - -tcpdump -nq - -00:33:48.410771 192.73.213.11.1463 > 224.2.248.153.59360: udp 31 (encap) - -tcpdump -nqt - -128.250.133.13.23 > 128.250.20.20.2419: tcp 27 - -tcpdump -nqtt - -123456789.1234567 128.250.133.13.23 > 128.250.20.20.2419: tcp 27 - -tcpdump -nqte - -8:0:20:f:65:f7 0:0:c:1:8a:c5 81: 128.250.133.13.23 > 128.250.20.20.2419: tcp 27 - -*/ -#if defined(__sgi) && (IRIX > 602) -# include <sys/ptimers.h> -#endif -#include <stdio.h> -#include <string.h> -#if !defined(__SVR4) && !defined(__GNUC__) -#include <strings.h> -#endif -#include <sys/types.h> -#include <sys/param.h> -#include <sys/time.h> -#include <stdlib.h> -#include <unistd.h> -#include <stddef.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netinet/in_systm.h> -#ifndef linux -#include <netinet/ip_var.h> -#endif -#include <netinet/ip.h> -#include <netinet/tcp.h> -#include <netinet/udp.h> -#include <netinet/ip_icmp.h> -#include <net/if.h> -#include <netdb.h> -#include "ip_compat.h" -#include <netinet/tcpip.h> -#include "ipf.h" -#include "ipt.h" - -#if !defined(lint) -static const char sccsid[] = "@(#)ipft_td.c 1.8 2/4/96 (C)1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipft_td.c,v 2.2.2.6 2003/05/31 02:13:04 darrenr Exp $"; -#endif - -static int tcpd_open __P((char *)); -static int tcpd_close __P((void)); -static int tcpd_readip __P((char *, int, char **, int *)); -static int count_dots __P((char *)); - -struct ipread tcpd = { tcpd_open, tcpd_close, tcpd_readip }; - -static FILE *tfp = NULL; -static int tfd = -1; - - -static int tcpd_open(fname) -char *fname; -{ - if (tfd != -1) - return tfd; - - if (!strcmp(fname, "-")) { - tfd = 0; - tfp = stdin; - } else { - tfd = open(fname, O_RDONLY); - tfp = fdopen(tfd, "r"); - } - return tfd; -} - - -static int tcpd_close() -{ - (void) fclose(tfp); - return close(tfd); -} - - -static int count_dots(str) -char *str; -{ - int i = 0; - - while (*str) - if (*str++ == '.') - i++; - return i; -} - - -static int tcpd_readip(buf, cnt, ifn, dir) -char *buf, **ifn; -int cnt, *dir; -{ - struct tcpiphdr pkt; - ip_t *ip = (ip_t *)&pkt; - struct protoent *p; - char src[32], dst[32], misc[256], time[32], link1[32], link2[32]; - char lbuf[160], *s; - int n, slen, extra = 0; - - if (!fgets(lbuf, sizeof(lbuf) - 1, tfp)) - return 0; - - if ((s = strchr(lbuf, '\n'))) - *s = '\0'; - lbuf[sizeof(lbuf)-1] = '\0'; - - bzero(&pkt, sizeof(pkt)); - - if ((n = sscanf(lbuf, "%31s > %31s: %255s", src, dst, misc)) != 3) - if ((n = sscanf(lbuf, "%31s %31s > %31s: %255s", - time, src, dst, misc)) != 4) - if ((n = sscanf(lbuf, "%31s %31s: %31s > %31s: %255s", - link1, link2, src, dst, misc)) != 5) { - n = sscanf(lbuf, - "%31s %31s %31s: %31s > %31s: %255s", - time, link1, link2, src, dst, misc); - if (n != 6) - return -1; - } - - if (count_dots(dst) == 4) { - s = strrchr(src, '.'); - *s++ = '\0'; - (void) inet_aton(src, &ip->ip_src); - pkt.ti_sport = htons(atoi(s)); - *--s = '.'; - s = strrchr(dst, '.'); - - *s++ = '\0'; - (void) inet_aton(src, &ip->ip_dst); - pkt.ti_dport = htons(atoi(s)); - *--s = '.'; - - } else { - (void) inet_aton(src, &ip->ip_src); - (void) inet_aton(src, &ip->ip_dst); - } - ip->ip_len = ip->ip_hl = sizeof(ip_t); - - s = strtok(misc, " :"); - if ((p = getprotobyname(s))) { - ip->ip_p = p->p_proto; - - switch (p->p_proto) { - case IPPROTO_TCP : - case IPPROTO_UDP : - s = strtok(NULL, " :"); - ip->ip_len += atoi(s); - if (p->p_proto == IPPROTO_TCP) - extra = sizeof(struct tcphdr); - else if (p->p_proto == IPPROTO_UDP) - extra = sizeof(struct udphdr); - break; -#ifdef IGMP - case IPPROTO_IGMP : - extra = sizeof(struct igmp); - break; -#endif - case IPPROTO_ICMP : - extra = sizeof(struct icmp); - break; - default : - break; - } - } - slen = ip->ip_hl + extra + ip->ip_len; - return slen; -} diff --git a/ipft_tx.c b/ipft_tx.c deleted file mode 100644 index 7ea87e334c86c..0000000000000 --- a/ipft_tx.c +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Copyright (C) 1995-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - */ -#if defined(__sgi) && (IRIX > 602) -# include <sys/ptimers.h> -#endif -#include <stdio.h> -#include <ctype.h> -#include <assert.h> -#include <string.h> -#include <sys/types.h> -#if !defined(__SVR4) && !defined(__svr4__) -#include <strings.h> -#else -#include <sys/byteorder.h> -#endif -#include <sys/param.h> -#include <sys/time.h> -#include <stdlib.h> -#include <unistd.h> -#include <stddef.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#ifndef linux -#include <netinet/ip_var.h> -#endif -#include <netinet/ip.h> -#include <netinet/udp.h> -#include <netinet/tcp.h> -#include <netinet/ip_icmp.h> -#include <arpa/inet.h> -#include <net/if.h> -#include <netdb.h> -#include <arpa/nameser.h> -#include <resolv.h> -#include "ip_compat.h" -#include <netinet/tcpip.h> -#include "ipf.h" -#include "ipt.h" - -#if !defined(lint) -static const char sccsid[] = "@(#)ipft_tx.c 1.7 6/5/96 (C) 1993 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipft_tx.c,v 2.3.2.8 2002/12/06 11:40:26 darrenr Exp $"; -#endif - -extern int opts; - -static char *tx_proto = ""; - -static int text_open __P((char *)), text_close __P((void)); -static int text_readip __P((char *, int, char **, int *)); -static int parseline __P((char *, ip_t *, char **, int *)); - -static char _tcp_flagset[] = "FSRPAUEC"; -static u_char _tcp_flags[] = { TH_FIN, TH_SYN, TH_RST, TH_PUSH, - TH_ACK, TH_URG, TH_ECN, TH_CWR }; - -struct ipread iptext = { text_open, text_close, text_readip }; -static FILE *tfp = NULL; -static int tfd = -1; - -static u_32_t tx_hostnum __P((char *, int *)); -static u_short tx_portnum __P((char *)); - - -/* - * returns an ip address as a long var as a result of either a DNS lookup or - * straight inet_addr() call - */ -static u_32_t tx_hostnum(host, resolved) -char *host; -int *resolved; -{ - struct hostent *hp; - struct netent *np; - - *resolved = 0; - if (!strcasecmp("any",host)) - return 0L; - if (isdigit(*host)) - return inet_addr(host); - - if (!(hp = gethostbyname(host))) { - if (!(np = getnetbyname(host))) { - *resolved = -1; - fprintf(stderr, "can't resolve hostname: %s\n", host); - return 0; - } - return htonl(np->n_net); - } - return *(u_32_t *)hp->h_addr; -} - - -/* - * find the port number given by the name, either from getservbyname() or - * straight atoi() - */ -static u_short tx_portnum(name) -char *name; -{ - struct servent *sp, *sp2; - u_short p1 = 0; - - if (isdigit(*name)) - return (u_short)atoi(name); - if (!tx_proto) - tx_proto = "tcp/udp"; - if (strcasecmp(tx_proto, "tcp/udp")) { - sp = getservbyname(name, tx_proto); - if (sp) - return ntohs(sp->s_port); - (void) fprintf(stderr, "unknown service \"%s\".\n", name); - return 0; - } - sp = getservbyname(name, "tcp"); - if (sp) - p1 = sp->s_port; - sp2 = getservbyname(name, "udp"); - if (!sp || !sp2) { - (void) fprintf(stderr, "unknown tcp/udp service \"%s\".\n", - name); - return 0; - } - if (p1 != sp2->s_port) { - (void) fprintf(stderr, "%s %d/tcp is a different port to ", - name, p1); - (void) fprintf(stderr, "%s %d/udp\n", name, sp->s_port); - return 0; - } - return ntohs(p1); -} - - -char *tx_icmptypes[] = { - "echorep", (char *)NULL, (char *)NULL, "unreach", "squench", - "redir", (char *)NULL, (char *)NULL, "echo", "routerad", - "routersol", "timex", "paramprob", "timest", "timestrep", - "inforeq", "inforep", "maskreq", "maskrep", "END" -}; - -static int text_open(fname) -char *fname; -{ - if (tfp && tfd != -1) { - rewind(tfp); - return tfd; - } - - if (!strcmp(fname, "-")) { - tfd = 0; - tfp = stdin; - } else { - tfd = open(fname, O_RDONLY); - if (tfd != -1) - tfp = fdopen(tfd, "r"); - } - return tfd; -} - - -static int text_close() -{ - int cfd = tfd; - - tfd = -1; - return close(cfd); -} - - -static int text_readip(buf, cnt, ifn, dir) -char *buf, **ifn; -int cnt, *dir; -{ - register char *s; - char line[513]; - - *ifn = NULL; - while (fgets(line, sizeof(line)-1, tfp)) { - if ((s = index(line, '\n'))) - *s = '\0'; - if ((s = index(line, '\r'))) - *s = '\0'; - if ((s = index(line, '#'))) - *s = '\0'; - if (!*line) - continue; - if (!(opts & OPT_BRIEF)) - printf("input: %s\n", line); - *ifn = NULL; - *dir = 0; - if (!parseline(line, (ip_t *)buf, ifn, dir)) -#if 0 - return sizeof(ip_t) + sizeof(tcphdr_t); -#else - return sizeof(ip_t); -#endif - } - return -1; -} - -static int parseline(line, ip, ifn, out) -char *line; -ip_t *ip; -char **ifn; -int *out; -{ - tcphdr_t th, *tcp = &th; - struct icmp icmp, *ic = &icmp; - char *cps[20], **cpp, c, ipopts[68]; - int i, r; - - if (*ifn) - free(*ifn); - bzero((char *)ip, MAX(sizeof(*tcp), sizeof(*ic)) + sizeof(*ip)); - bzero((char *)tcp, sizeof(*tcp)); - bzero((char *)ic, sizeof(*ic)); - bzero(ipopts, sizeof(ipopts)); - ip->ip_hl = sizeof(*ip) >> 2; - ip->ip_v = IPVERSION; - for (i = 0, cps[0] = strtok(line, " \b\t\r\n"); cps[i] && (i < 19); ) - cps[++i] = strtok(NULL, " \b\t\r\n"); - - cpp = cps; - if (!*cpp) - return 1; - - c = **cpp; - if (!isalpha(c) || (tolower(c) != 'o' && tolower(c) != 'i')) { - fprintf(stderr, "bad direction \"%s\"\n", *cpp); - return 1; - } - *out = (tolower(c) == 'o') ? 1 : 0; - cpp++; - if (!*cpp) - return 1; - - if (!strcasecmp(*cpp, "on")) { - cpp++; - if (!*cpp) - return 1; - *ifn = strdup(*cpp++); - if (!*cpp) - return 1; - } - - c = **cpp; - ip->ip_len = sizeof(ip_t); - if (!strcasecmp(*cpp, "tcp") || !strcasecmp(*cpp, "udp") || - !strcasecmp(*cpp, "icmp")) { - if (c == 't') { - ip->ip_p = IPPROTO_TCP; - ip->ip_len += sizeof(struct tcphdr); - tx_proto = "tcp"; - } else if (c == 'u') { - ip->ip_p = IPPROTO_UDP; - ip->ip_len += sizeof(struct udphdr); - tx_proto = "udp"; - } else { - ip->ip_p = IPPROTO_ICMP; - ip->ip_len += ICMPERR_IPICMPHLEN; - tx_proto = "icmp"; - } - cpp++; - } else if (isdigit(**cpp) && !index(*cpp, '.')) { - ip->ip_p = atoi(*cpp); - cpp++; - } else - ip->ip_p = IPPROTO_IP; - - if (!*cpp) - return 1; - if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) { - char *last; - - last = index(*cpp, ','); - if (!last) { - fprintf(stderr, "tcp/udp with no source port\n"); - return 1; - } - *last++ = '\0'; - tcp->th_sport = htons(tx_portnum(last)); - } - ip->ip_src.s_addr = tx_hostnum(*cpp, &r); - cpp++; - if (!*cpp) - return 1; - - if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) { - char *last; - - last = index(*cpp, ','); - if (!last) { - fprintf(stderr, "tcp/udp with no destination port\n"); - return 1; - } - *last++ = '\0'; - tcp->th_dport = htons(tx_portnum(last)); - } - ip->ip_dst.s_addr = tx_hostnum(*cpp, &r); - cpp++; - if (*cpp && ip->ip_p == IPPROTO_TCP) { - extern char _tcp_flagset[]; - extern u_char _tcp_flags[]; - char *s, *t; - - for (s = *cpp; *s; s++) - if ((t = index(_tcp_flagset, *s))) - tcp->th_flags |= _tcp_flags[t - _tcp_flagset]; - if (tcp->th_flags) - cpp++; - assert(tcp->th_flags != 0); - tcp->th_win = htons(4096); - tcp->th_off = sizeof(*tcp) >> 2; - } else if (*cpp && ip->ip_p == IPPROTO_ICMP) { - extern char *tx_icmptypes[]; - char **s, *t; - int i; - - for (s = tx_icmptypes, i = 0; !*s || strcmp(*s, "END"); - s++, i++) - if (*s && !strncasecmp(*cpp, *s, strlen(*s))) { - ic->icmp_type = i; - if ((t = index(*cpp, ','))) - ic->icmp_code = atoi(t+1); - cpp++; - break; - } - } - - if (*cpp && !strcasecmp(*cpp, "opt")) { - u_long olen; - - cpp++; - olen = buildopts(*cpp, ipopts, (ip->ip_hl - 5) << 2); - if (olen) { - bcopy(ipopts, (char *)(ip + 1), olen); - ip->ip_hl += olen >> 2; - } - } - if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) - bcopy((char *)tcp, ((char *)ip) + (ip->ip_hl << 2), - sizeof(*tcp)); - else if (ip->ip_p == IPPROTO_ICMP) - bcopy((char *)ic, ((char *)ip) + (ip->ip_hl << 2), - sizeof(*ic)); - ip->ip_len = htons(ip->ip_len); - return 0; -} @@ -1,19 +1,17 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1993-2001, 2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ipl.h 1.21 6/5/96 - * Id: ipl.h,v 2.52.2.9 2005/03/30 14:14:05 darrenr Exp + * $Id$ */ #ifndef __IPL_H__ #define __IPL_H__ -#define IPL_VERSION "IP Filter: v4.1.8" +#define IPL_VERSION "IP Filter: v5.1.2" -#define IPFILTER_VERSION 4010800 +#define IPFILTER_VERSION 5010200 -#endif +#endif /* __IPL_H__ */ diff --git a/ipl_ldev.c b/ipl_ldev.c deleted file mode 100644 index a2893257e72e1..0000000000000 --- a/ipl_ldev.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * (C)opyright 1993,1994,1995 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - */ - -/* - * routines below for saving IP headers to buffer - */ -int iplopen(struct inode * inode, struct file * filp) -{ - u_int min = MINOR(inode->i_rdev); - - if (flags & FWRITE) - return ENXIO; - if (min) - return ENXIO; - iplbusy++; - return 0; -} - - -int iplclose(struct inode * inode, struct file * filp) -{ - u_int min = MINOR(inode->i_rdev); - - if (min) - return ENXIO; - iplbusy--; - return 0; -} - - -/* - * iplread/ipllog - * all three of these must operate with at least splnet() lest they be - * called during packet processing and cause an inconsistancy to appear in - * the filter lists. - */ -int iplread(struct inode *inode, struct file *file, char *buf, int count) -{ - register int ret, s; - register size_t sz, sx; - int error; - - if (!uio->uio_resid) - return 0; - while (!iplused) { - error = SLEEP(iplbuf, "ipl sleep"); - if (error) - return error; - } - - SPLNET(s); - - ret = sx = sz = MIN(count, iplused); - if (iplh < iplt) - sz = MIN(sz, LOGSIZE - (iplt - iplbuf)); - sx -= sz; - - memcpy_tofs(buf, iplt, sz); - buf += sz; - iplt += sz; - iplused -= sz; - if ((iplh < iplt) && (iplt == iplbuf + LOGSIZE)) - iplt = iplbuf; - - if (sx) { - memcpy_tofs(buf, iplt, sx); - ret += sx; - iplt += sx; - iplused -= sx; - if ((iplh < iplt) && (iplt == iplbuf + LOGSIZE)) - iplt = iplbuf; - } - if (!iplused) /* minimise wrapping around the end */ - iplh = iplt = iplbuf; - - SPLX(s); - return ret; -} diff --git a/iplang/.cvsignore b/iplang/.cvsignore deleted file mode 100644 index 68b5b4e4e9853..0000000000000 --- a/iplang/.cvsignore +++ /dev/null @@ -1,9 +0,0 @@ -y.tab.h -y.output -lex.yy.c -y.tab.c -y.tab.o -lex.yy.o -iplang_y.output -iplang_y.tab.c -iplang_y.tab.h diff --git a/iplang/Makefile b/iplang/Makefile index 1d66bb655c5a9..5b53e9a43609a 100644 --- a/iplang/Makefile +++ b/iplang/Makefile @@ -3,21 +3,20 @@ # #CC=gcc -Wuninitialized -Wstrict-prototypes -Werror -O CFLAGS=-I.. -CCARGS=$(DEBUG) -I. -I.. $(CFLAGS) -I$(DESTDIR) -I$(DESTDIR)/.. -I../ipsend all: $(DESTDIR)/iplang_y.o $(DESTDIR)/iplang_l.o $(DESTDIR)/iplang_y.o: $(DESTDIR)/iplang_y.c - $(CC) $(CCARGS) $(LINUX) -c $(DESTDIR)/iplang_y.c -o $@ + $(CC) $(DEBUG) -I. -I.. -I$(DESTDIR) -I../ipsend $(CFLAGS) $(LINUX) -c $(DESTDIR)/iplang_y.c -o $@ $(DESTDIR)/iplang_l.o: $(DESTDIR)/iplang_l.c - $(CC) $(CCARGS) $(LINUX) -c $(DESTDIR)/iplang_l.c -o $@ + $(CC) $(DEBUG) -I. -I.. -I$(DESTDIR) -I../ipsend $(CFLAGS) $(LINUX) -c $(DESTDIR)/iplang_l.c -o $@ iplang_y.o: iplang_y.c - $(CC) $(CCARGS) $< -o $@ + $(CC) $(DEBUG) -I. -I.. -I../ipsend $(CFLAGS) $(LINUX) -c $< -o $@ iplang_l.o: iplang_l.c - $(CC) $(CCARGS) $< -o $@ + $(CC) $(DEBUG) -I. -I.. -I../ipsend $(CFLAGS) $(LINUX) -c $< -o $@ $(DESTDIR)/iplang_l.c: iplang_l.l $(DESTDIR)/iplang_y.h lex iplang_l.l diff --git a/iplang/iplang.h b/iplang/iplang.h index f36a3843c0aa6..4490df992088f 100644 --- a/iplang/iplang.h +++ b/iplang/iplang.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1997-1998 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ diff --git a/iplang/iplang.tst b/iplang/iplang.tst index a0a2ad3315ae1..841c3aed13163 100644 --- a/iplang/iplang.tst +++ b/iplang/iplang.tst @@ -4,7 +4,7 @@ interface { ifname le0; mtu 1500; } ; ipv4 { src 1.1.1.1; dst 2.2.2.2; tcp { - seq 12345; ack 0; sport 9999; dport 23; flags S; + seq 12345; ack 0; sport 9999; dport 23; flags S; data { value "abcdef"; } ; } ; } ; diff --git a/iplang/iplang_l.l b/iplang/iplang_l.l index fae30a25ed2da..f213090d6243a 100644 --- a/iplang/iplang_l.l +++ b/iplang/iplang_l.l @@ -1,10 +1,10 @@ %{ /* - * Copyright (C) 1997-1998 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: iplang_l.l,v 2.8 2003/07/28 01:15:31 darrenr Exp $ + * $Id$ */ #include <stdio.h> #include <string.h> diff --git a/iplang/iplang_y.y b/iplang/iplang_y.y index 735ac37a23ffc..c384706194a7a 100644 --- a/iplang/iplang_y.y +++ b/iplang/iplang_y.y @@ -1,10 +1,10 @@ %{ /* - * Copyright (C) 1997-1998 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: iplang_y.y,v 2.9.2.5 2007/02/17 12:41:48 darrenr Exp $ + * $Id$ */ #include <stdio.h> @@ -23,17 +23,13 @@ #include <unistd.h> #include <stddef.h> #include <sys/socket.h> +#include <net/if.h> #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> #ifndef linux # include <netinet/ip_var.h> -#endif -#ifdef __osf__ -# include "radix_ipf_local.h" -#endif -#include <net/if.h> -#ifndef linux +# include <net/route.h> # include <netinet/if_ether.h> #endif #include <netdb.h> @@ -602,7 +598,7 @@ struct statetoopt tosecopts[] = { #ifdef bsdi struct ether_addr * ether_aton(s) - char *s; + char *s; { static struct ether_addr n; u_int i[6]; @@ -1327,7 +1323,7 @@ void packet_done() sprintf((char *)t, " "); t += 8; for (k = 16; k; k--, s++) - *t++ = (ISPRINT(*s) ? *s : '.'); + *t++ = (isprint(*s) ? *s : '.'); s--; } @@ -1345,7 +1341,7 @@ void packet_done() t += 7; s -= j & 0xf; for (k = j & 0xf; k; k--, s++) - *t++ = (ISPRINT(*s) ? *s : '.'); + *t++ = (isprint(*s) ? *s : '.'); *t++ = '\n'; *t = '\0'; } @@ -1837,7 +1833,7 @@ u_long init; { u_long sum = init; int nwords = len >> 1; - + for(; nwords > 0; nwords--) sum += *buf++; sum = (sum>>16) + (sum & 0xffff); @@ -1852,7 +1848,7 @@ u_int len; { u_long sum = 0; int nwords = len >> 1; - + for(; nwords > 0; nwords--) sum += *buf++; return sum; diff --git a/ipmon.c b/ipmon.c deleted file mode 100644 index 2e4b2b5462751..0000000000000 --- a/ipmon.c +++ /dev/null @@ -1,1493 +0,0 @@ -/* - * Copyright (C) 1993-2002 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - */ -#ifndef SOLARIS -#define SOLARIS (defined(__SVR4) || defined(__svr4__)) && defined(sun) -#endif - -#if defined(__sgi) && (IRIX > 602) -# include <sys/ptimers.h> -#endif -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/param.h> -#include <sys/file.h> -#include <sys/time.h> -#include <sys/socket.h> -#include <sys/ioctl.h> - -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <fcntl.h> -#include <errno.h> -#if !defined(__SVR4) && !defined(__svr4__) -# if (__FreeBSD_version >= 300000) -# include <sys/dirent.h> -# else -# include <sys/dir.h> -# endif -#else -# include <sys/filio.h> -# include <sys/byteorder.h> -#endif -#if !defined(__SVR4) && !defined(__GNUC__) -# include <strings.h> -#endif -#include <signal.h> -#include <stdlib.h> -#include <stddef.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <net/if.h> -#include <netinet/ip.h> -#include <netinet/tcp_fsm.h> -#include <netdb.h> -#include <arpa/inet.h> -#include <arpa/nameser.h> -#include <resolv.h> - -#ifndef linux -# include <sys/protosw.h> -# include <netinet/ip_var.h> -#endif - -#include <netinet/tcp.h> -#include <netinet/ip_icmp.h> - -#include <ctype.h> -#include <syslog.h> - -#include "netinet/ip_compat.h" -#include <netinet/tcpip.h> -#include "netinet/ip_fil.h" -#include "netinet/ip_nat.h" -#include "netinet/ip_state.h" - -#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.40 2004/05/12 23:21:55 darrenr Exp $"; -#endif - - -#if defined(sun) && !defined(SOLARIS2) -#define STRERROR(x) sys_errlist[x] -extern char *sys_errlist[]; -#else -#define STRERROR(x) strerror(x) -#endif - - -struct flags { - int value; - char flag; -}; - - -typedef struct icmp_subtype { - int ist_val; - char *ist_name; -} icmp_subtype_t; - -typedef struct icmp_type { - int it_val; - struct icmp_subtype *it_subtable; - size_t it_stsize; - char *it_name; -} icmp_type_t; - - -#define IST_SZ(x) (sizeof(x)/sizeof(icmp_subtype_t)) - - -struct flags tcpfl[] = { - { TH_ACK, 'A' }, - { TH_RST, 'R' }, - { TH_SYN, 'S' }, - { TH_FIN, 'F' }, - { TH_URG, 'U' }, - { TH_PUSH,'P' }, - { TH_ECN, 'E' }, - { TH_CWR, 'C' }, - { 0, '\0' } -}; - -#if SOLARIS -static char *pidfile = "/etc/opt/ipf/ipmon.pid"; -#else -# if BSD >= 199306 -static char *pidfile = "/var/run/ipmon.pid"; -# else -static char *pidfile = "/etc/ipmon.pid"; -# endif -#endif - -static char line[2048]; -static int opts = 0; -static FILE *newlog = NULL; -static char *logfile = NULL; -static int donehup = 0; -static void usage __P((char *)); -static void handlehup __P((int)); -static void flushlogs __P((char *, FILE *)); -static void print_log __P((int, FILE *, char *, int)); -static void print_ipflog __P((FILE *, char *, int)); -static void print_natlog __P((FILE *, char *, int)); -static void print_statelog __P((FILE *, char *, int)); -static void dumphex __P((FILE *, u_char *, int)); -static int read_log __P((int, int *, char *, int)); -static void write_pid __P((char *)); -static char *icmpname __P((u_int, u_int)); -static char *icmpname6 __P((u_int, u_int)); -static icmp_type_t *find_icmptype __P((int, icmp_type_t *, size_t)); -static icmp_subtype_t *find_icmpsubtype __P((int, icmp_subtype_t *, size_t)); - -char *hostname __P((int, int, u_32_t *)); -char *portname __P((int, char *, u_int)); -int main __P((int, char *[])); - -static void logopts __P((int, char *)); -static void init_tabs __P((void)); -static char *getproto __P((u_int)); - -static char **protocols = NULL; -static char **udp_ports = NULL; -static char **tcp_ports = NULL; - -#define OPT_SYSLOG 0x001 -#define OPT_RESOLVE 0x002 -#define OPT_HEXBODY 0x004 -#define OPT_VERBOSE 0x008 -#define OPT_HEXHDR 0x010 -#define OPT_TAIL 0x020 -#define OPT_NAT 0x080 -#define OPT_STATE 0x100 -#define OPT_FILTER 0x200 -#define OPT_PORTNUM 0x400 -#define OPT_LOGALL (OPT_NAT|OPT_STATE|OPT_FILTER) -#define OPT_LOGBODY 0x800 - -#define HOSTNAME_V4(a,b) hostname((a), 4, (u_32_t *)&(b)) - -#ifndef LOGFAC -#define LOGFAC LOG_LOCAL0 -#endif - - -static icmp_subtype_t icmpunreachnames[] = { - { ICMP_UNREACH_NET, "net" }, - { ICMP_UNREACH_HOST, "host" }, - { ICMP_UNREACH_PROTOCOL, "protocol" }, - { ICMP_UNREACH_PORT, "port" }, - { ICMP_UNREACH_NEEDFRAG, "needfrag" }, - { ICMP_UNREACH_SRCFAIL, "srcfail" }, - { ICMP_UNREACH_NET_UNKNOWN, "net_unknown" }, - { ICMP_UNREACH_HOST_UNKNOWN, "host_unknown" }, - { ICMP_UNREACH_NET, "isolated" }, - { ICMP_UNREACH_NET_PROHIB, "net_prohib" }, - { ICMP_UNREACH_NET_PROHIB, "host_prohib" }, - { ICMP_UNREACH_TOSNET, "tosnet" }, - { ICMP_UNREACH_TOSHOST, "toshost" }, - { ICMP_UNREACH_ADMIN_PROHIBIT, "admin_prohibit" }, - { -2, NULL } -}; - -static icmp_subtype_t redirectnames[] = { - { ICMP_REDIRECT_NET, "net" }, - { ICMP_REDIRECT_HOST, "host" }, - { ICMP_REDIRECT_TOSNET, "tosnet" }, - { ICMP_REDIRECT_TOSHOST, "toshost" }, - { -2, NULL } -}; - -static icmp_subtype_t timxceednames[] = { - { ICMP_TIMXCEED_INTRANS, "transit" }, - { ICMP_TIMXCEED_REASS, "reassem" }, - { -2, NULL } -}; - -static icmp_subtype_t paramnames[] = { - { ICMP_PARAMPROB_ERRATPTR, "errata_pointer" }, - { ICMP_PARAMPROB_OPTABSENT, "optmissing" }, - { ICMP_PARAMPROB_LENGTH, "length" }, - { -2, NULL } -}; - -static icmp_type_t icmptypes[] = { - { ICMP_ECHOREPLY, NULL, 0, "echoreply" }, - { -1, NULL, 0, NULL }, - { -1, NULL, 0, NULL }, - { ICMP_UNREACH, icmpunreachnames, - IST_SZ(icmpunreachnames),"unreach" }, - { ICMP_SOURCEQUENCH, NULL, 0, "sourcequench" }, - { ICMP_REDIRECT, redirectnames, - IST_SZ(redirectnames), "redirect" }, - { -1, NULL, 0, NULL }, - { -1, NULL, 0, NULL }, - { ICMP_ECHO, NULL, 0, "echo" }, - { ICMP_ROUTERADVERT, NULL, 0, "routeradvert" }, - { ICMP_ROUTERSOLICIT, NULL, 0, "routersolicit" }, - { ICMP_TIMXCEED, timxceednames, - IST_SZ(timxceednames), "timxceed" }, - { ICMP_PARAMPROB, paramnames, - IST_SZ(paramnames), "paramprob" }, - { ICMP_TSTAMP, NULL, 0, "timestamp" }, - { ICMP_TSTAMPREPLY, NULL, 0, "timestampreply" }, - { ICMP_IREQ, NULL, 0, "inforeq" }, - { ICMP_IREQREPLY, NULL, 0, "inforeply" }, - { ICMP_MASKREQ, NULL, 0, "maskreq" }, - { ICMP_MASKREPLY, NULL, 0, "maskreply" }, - { -2, NULL, 0, NULL } -}; - -static icmp_subtype_t icmpredirect6[] = { - { ICMP6_DST_UNREACH_NOROUTE, "noroute" }, - { ICMP6_DST_UNREACH_ADMIN, "admin" }, - { ICMP6_DST_UNREACH_NOTNEIGHBOR, "neighbour" }, - { ICMP6_DST_UNREACH_ADDR, "address" }, - { ICMP6_DST_UNREACH_NOPORT, "noport" }, - { -2, NULL } -}; - -static icmp_subtype_t icmptimexceed6[] = { - { ICMP6_TIME_EXCEED_TRANSIT, "intransit" }, - { ICMP6_TIME_EXCEED_REASSEMBLY, "reassem" }, - { -2, NULL } -}; - -static icmp_subtype_t icmpparamprob6[] = { - { ICMP6_PARAMPROB_HEADER, "header" }, - { ICMP6_PARAMPROB_NEXTHEADER, "nextheader" }, - { ICMP6_PARAMPROB_OPTION, "option" }, - { -2, NULL } -}; - -static icmp_subtype_t icmpquerysubject6[] = { - { ICMP6_NI_SUBJ_IPV6, "ipv6" }, - { ICMP6_NI_SUBJ_FQDN, "fqdn" }, - { ICMP6_NI_SUBJ_IPV4, "ipv4" }, - { -2, NULL }, -}; - -static icmp_subtype_t icmpnodeinfo6[] = { - { ICMP6_NI_SUCCESS, "success" }, - { ICMP6_NI_REFUSED, "refused" }, - { ICMP6_NI_UNKNOWN, "unknown" }, - { -2, NULL } -}; - -static icmp_subtype_t icmprenumber6[] = { - { ICMP6_ROUTER_RENUMBERING_COMMAND, "command" }, - { ICMP6_ROUTER_RENUMBERING_RESULT, "result" }, - { ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET, "seqnum_reset" }, - { -2, NULL } -}; - -static icmp_type_t icmptypes6[] = { - { 0, NULL, 0, NULL }, - { ICMP6_DST_UNREACH, icmpredirect6, - IST_SZ(icmpredirect6), "unreach" }, - { ICMP6_PACKET_TOO_BIG, NULL, 0, "toobig" }, - { ICMP6_TIME_EXCEEDED, icmptimexceed6, - IST_SZ(icmptimexceed6), "timxceed" }, - { ICMP6_PARAM_PROB, icmpparamprob6, - IST_SZ(icmpparamprob6), "paramprob" }, - { ICMP6_ECHO_REQUEST, NULL, 0, "echo" }, - { ICMP6_ECHO_REPLY, NULL, 0, "echoreply" }, - { ICMP6_MEMBERSHIP_QUERY, icmpquerysubject6, - IST_SZ(icmpquerysubject6), "groupmemberquery" }, - { ICMP6_MEMBERSHIP_REPORT,NULL, 0, "groupmemberreport" }, - { ICMP6_MEMBERSHIP_REDUCTION,NULL, 0, "groupmemberterm" }, - { ND_ROUTER_SOLICIT, NULL, 0, "routersolicit" }, - { ND_ROUTER_ADVERT, NULL, 0, "routeradvert" }, - { ND_NEIGHBOR_SOLICIT, NULL, 0, "neighborsolicit" }, - { ND_NEIGHBOR_ADVERT, NULL, 0, "neighboradvert" }, - { ND_REDIRECT, NULL, 0, "redirect" }, - { ICMP6_ROUTER_RENUMBERING, icmprenumber6, - IST_SZ(icmprenumber6), "routerrenumber" }, - { ICMP6_WRUREQUEST, NULL, 0, "whoareyourequest" }, - { ICMP6_WRUREPLY, NULL, 0, "whoareyoureply" }, - { ICMP6_FQDN_QUERY, NULL, 0, "fqdnquery" }, - { ICMP6_FQDN_REPLY, NULL, 0, "fqdnreply" }, - { ICMP6_NI_QUERY, icmpnodeinfo6, - IST_SZ(icmpnodeinfo6), "nodeinforequest" }, - { ICMP6_NI_REPLY, NULL, 0, "nodeinforeply" }, - { MLD6_MTRACE_RESP, NULL, 0, "mtraceresponse" }, - { MLD6_MTRACE, NULL, 0, "mtracerequest" }, - { -2, NULL, 0, NULL } -}; - -static icmp_subtype_t *find_icmpsubtype(type, table, tablesz) -int type; -icmp_subtype_t *table; -size_t tablesz; -{ - icmp_subtype_t *ist; - int i; - - if (tablesz < 2) - return NULL; - - if ((type < 0) || (type > table[tablesz - 2].ist_val)) - return NULL; - - i = type; - if (table[type].ist_val == type) - return table + type; - - for (i = 0, ist = table; ist->ist_val != -2; i++, ist++) - if (ist->ist_val == type) - return ist; - return NULL; -} - - -static icmp_type_t *find_icmptype(type, table, tablesz) -int type; -icmp_type_t *table; -size_t tablesz; -{ - icmp_type_t *it; - int i; - - if (tablesz < 2) - return NULL; - - if ((type < 0) || (type > table[tablesz - 2].it_val)) - return NULL; - - i = type; - if (table[type].it_val == type) - return table + type; - - for (i = 0, it = table; it->it_val != -2; i++, it++) - if (it->it_val == type) - return it; - return NULL; -} - - -static void handlehup(sig) -int sig; -{ - FILE *fp; - - signal(SIGHUP, handlehup); - if (logfile && (fp = fopen(logfile, "a"))) - newlog = fp; - init_tabs(); - donehup = 1; -} - - -static void init_tabs() -{ - struct protoent *p; - struct servent *s; - char *name, **tab; - int port; - - if (protocols != NULL) { - free(protocols); - protocols = NULL; - } - protocols = (char **)malloc(256 * sizeof(*protocols)); - if (protocols != NULL) { - bzero((char *)protocols, 256 * sizeof(*protocols)); - - setprotoent(1); - while ((p = getprotoent()) != NULL) - if (p->p_proto >= 0 && p->p_proto <= 255 && - p->p_name != NULL && protocols[p->p_proto] == NULL) - protocols[p->p_proto] = strdup(p->p_name); - endprotoent(); - } - - if (udp_ports != NULL) { - free(udp_ports); - udp_ports = NULL; - } - udp_ports = (char **)malloc(65536 * sizeof(*udp_ports)); - if (udp_ports != NULL) - bzero((char *)udp_ports, 65536 * sizeof(*udp_ports)); - - if (tcp_ports != NULL) { - free(tcp_ports); - tcp_ports = NULL; - } - tcp_ports = (char **)malloc(65536 * sizeof(*tcp_ports)); - if (tcp_ports != NULL) - bzero((char *)tcp_ports, 65536 * sizeof(*tcp_ports)); - - setservent(1); - while ((s = getservent()) != NULL) { - if (s->s_proto == NULL) - continue; - else if (!strcmp(s->s_proto, "tcp")) { - port = ntohs(s->s_port); - name = s->s_name; - tab = tcp_ports; - } else if (!strcmp(s->s_proto, "udp")) { - port = ntohs(s->s_port); - name = s->s_name; - tab = udp_ports; - } else - continue; - if ((port < 0 || port > 65535) || (name == NULL)) - continue; - tab[port] = strdup(name); - } - endservent(); -} - - -static char *getproto(p) -u_int p; -{ - static char pnum[4]; - char *s; - - p &= 0xff; - s = protocols ? protocols[p] : NULL; - if (s == NULL) { - sprintf(pnum, "%u", p); - s = pnum; - } - return s; -} - - -static int read_log(fd, lenp, buf, bufsize) -int fd, bufsize, *lenp; -char *buf; -{ - int nr; - - nr = read(fd, buf, bufsize); - if (!nr) - return 2; - if ((nr < 0) && (errno != EINTR)) - return -1; - *lenp = nr; - return 0; -} - - -char *hostname(res, v, ip) -int res, v; -u_32_t *ip; -{ -# define MAX_INETA 16 - static char hname[MAXHOSTNAMELEN + MAX_INETA + 3]; -#ifdef USE_INET6 - static char hostbuf[MAXHOSTNAMELEN+1]; -#endif - struct hostent *hp; - struct in_addr ipa; - - if (v == 4) { - ipa.s_addr = *ip; - if (!res) - return inet_ntoa(ipa); - hp = gethostbyaddr((char *)ip, sizeof(*ip), AF_INET); - if (!hp) - return inet_ntoa(ipa); - sprintf(hname, "%.*s[%s]", MAXHOSTNAMELEN, hp->h_name, - inet_ntoa(ipa)); - return hname; - } -#ifdef USE_INET6 - (void) inet_ntop(AF_INET6, ip, hostbuf, sizeof(hostbuf) - 1); - hostbuf[MAXHOSTNAMELEN] = '\0'; - return hostbuf; -#else - return "IPv6"; -#endif -} - - -char *portname(res, proto, port) -int res; -char *proto; -u_int port; -{ - static char pname[8]; - char *s; - - port = ntohs(port); - port &= 0xffff; - (void) sprintf(pname, "%u", port); - if (!res || (opts & OPT_PORTNUM)) - return pname; - s = NULL; - if (!strcmp(proto, "tcp")) - s = tcp_ports[port]; - else if (!strcmp(proto, "udp")) - s = udp_ports[port]; - if (s == NULL) - s = pname; - return s; -} - - -static char *icmpname(type, code) -u_int type; -u_int code; -{ - static char name[80]; - icmp_subtype_t *ist; - icmp_type_t *it; - char *s; - - s = NULL; - it = find_icmptype(type, icmptypes, sizeof(icmptypes) / sizeof(*it)); - if (it != NULL) - s = it->it_name; - - if (s == NULL) - sprintf(name, "icmptype(%d)/", type); - else - sprintf(name, "%s/", s); - - ist = NULL; - if (it != NULL && it->it_subtable != NULL) - ist = find_icmpsubtype(code, it->it_subtable, it->it_stsize); - - if (ist != NULL && ist->ist_name != NULL) - strcat(name, ist->ist_name); - else - sprintf(name + strlen(name), "%d", code); - - return name; -} - -static char *icmpname6(type, code) -u_int type; -u_int code; -{ - static char name[80]; - icmp_subtype_t *ist; - icmp_type_t *it; - char *s; - - s = NULL; - it = find_icmptype(type, icmptypes6, sizeof(icmptypes6) / sizeof(*it)); - if (it != NULL) - s = it->it_name; - - if (s == NULL) - sprintf(name, "icmpv6type(%d)/", type); - else - sprintf(name, "%s/", s); - - ist = NULL; - if (it != NULL && it->it_subtable != NULL) - ist = find_icmpsubtype(code, it->it_subtable, it->it_stsize); - - if (ist != NULL && ist->ist_name != NULL) - strcat(name, ist->ist_name); - else - sprintf(name + strlen(name), "%d", code); - - return name; -} - - -static void dumphex(log, buf, len) -FILE *log; -u_char *buf; -int len; -{ - char line[80]; - int i, j, k; - u_char *s = buf, *t = (u_char *)line; - - if (len == 0 || buf == 0) - return; - *line = '\0'; - - for (i = len, j = 0; i; i--, j++, s++) { - if (j && !(j & 0xf)) { - *t++ = '\n'; - *t = '\0'; - if (!(opts & OPT_SYSLOG)) - fputs(line, log); - else - syslog(LOG_INFO, "%s", line); - t = (u_char *)line; - *t = '\0'; - } - sprintf((char *)t, "%02x", *s & 0xff); - t += 2; - if (!((j + 1) & 0xf)) { - s -= 15; - sprintf((char *)t, " "); - t += 8; - for (k = 16; k; k--, s++) - *t++ = (isprint(*s) ? *s : '.'); - s--; - } - - if ((j + 1) & 0xf) - *t++ = ' ';; - } - - if (j & 0xf) { - for (k = 16 - (j & 0xf); k; k--) { - *t++ = ' '; - *t++ = ' '; - *t++ = ' '; - } - sprintf((char *)t, " "); - t += 7; - s -= j & 0xf; - for (k = j & 0xf; k; k--, s++) - *t++ = (isprint(*s) ? *s : '.'); - *t++ = '\n'; - *t = '\0'; - } - if (!(opts & OPT_SYSLOG)) { - fputs(line, log); - fflush(log); - } else - syslog(LOG_INFO, "%s", line); -} - -static void print_natlog(log, buf, blen) -FILE *log; -char *buf; -int blen; -{ - struct natlog *nl; - iplog_t *ipl = (iplog_t *)buf; - char *t = line; - struct tm *tm; - int res, i, len; - char *proto; - - nl = (struct natlog *)((char *)ipl + IPLOG_SIZE); - res = (opts & OPT_RESOLVE) ? 1 : 0; - tm = localtime((time_t *)&ipl->ipl_sec); - len = sizeof(line); - if (!(opts & OPT_SYSLOG)) { - (void) strftime(t, len, "%d/%m/%Y ", tm); - i = strlen(t); - len -= i; - t += i; - } - (void) strftime(t, len, "%T", tm); - t += strlen(t); - (void) sprintf(t, ".%-.6ld @%hd ", ipl->ipl_usec, nl->nl_rule + 1); - t += strlen(t); - - if (nl->nl_type == NL_NEWMAP) - strcpy(t, "NAT:MAP "); - else if (nl->nl_type == NL_NEWRDR) - strcpy(t, "NAT:RDR "); - else if (nl->nl_type == NL_EXPIRE) - strcpy(t, "NAT:EXPIRE "); - else if (nl->nl_type == NL_FLUSH) - strcpy(t, "NAT:FLUSH "); - else if (nl->nl_type == NL_NEWBIMAP) - strcpy(t, "NAT:BIMAP "); - else if (nl->nl_type == NL_NEWBLOCK) - strcpy(t, "NAT:MAPBLOCK "); - else - sprintf(t, "Type: %d ", nl->nl_type); - t += strlen(t); - - proto = getproto(nl->nl_p); - - (void) sprintf(t, "%s,%s <- -> ", HOSTNAME_V4(res, nl->nl_inip), - portname(res, proto, (u_int)nl->nl_inport)); - t += strlen(t); - (void) sprintf(t, "%s,%s ", HOSTNAME_V4(res, nl->nl_outip), - portname(res, proto, (u_int)nl->nl_outport)); - t += strlen(t); - (void) sprintf(t, "[%s,%s]", HOSTNAME_V4(res, nl->nl_origip), - portname(res, proto, (u_int)nl->nl_origport)); - t += strlen(t); - if (nl->nl_type == NL_EXPIRE) { -#ifdef USE_QUAD_T - (void) sprintf(t, " Pkts %qd Bytes %qd", - (long long)nl->nl_pkts, - (long long)nl->nl_bytes); -#else - (void) sprintf(t, " Pkts %ld Bytes %ld", - nl->nl_pkts, nl->nl_bytes); -#endif - t += strlen(t); - } - - *t++ = '\n'; - *t++ = '\0'; - if (opts & OPT_SYSLOG) - syslog(LOG_INFO, "%s", line); - else - (void) fprintf(log, "%s", line); -} - - -static void print_statelog(log, buf, blen) -FILE *log; -char *buf; -int blen; -{ - struct ipslog *sl; - iplog_t *ipl = (iplog_t *)buf; - char *t = line, *proto; - struct tm *tm; - int res, i, len; - - sl = (struct ipslog *)((char *)ipl + IPLOG_SIZE); - res = (opts & OPT_RESOLVE) ? 1 : 0; - tm = localtime((time_t *)&ipl->ipl_sec); - len = sizeof(line); - if (!(opts & OPT_SYSLOG)) { - (void) strftime(t, len, "%d/%m/%Y ", tm); - i = strlen(t); - len -= i; - t += i; - } - (void) strftime(t, len, "%T", tm); - t += strlen(t); - (void) sprintf(t, ".%-.6ld ", ipl->ipl_usec); - t += strlen(t); - - if (sl->isl_type == ISL_NEW) - strcpy(t, "STATE:NEW "); - else if (sl->isl_type == ISL_EXPIRE) { - if ((sl->isl_p == IPPROTO_TCP) && - (sl->isl_state[0] > TCPS_ESTABLISHED || - sl->isl_state[1] > TCPS_ESTABLISHED)) - strcpy(t, "STATE:CLOSE "); - else - strcpy(t, "STATE:EXPIRE "); - } else if (sl->isl_type == ISL_FLUSH) - strcpy(t, "STATE:FLUSH "); - else if (sl->isl_type == ISL_REMOVE) - strcpy(t, "STATE:REMOVE "); - else - sprintf(t, "Type: %d ", sl->isl_type); - t += strlen(t); - - proto = getproto(sl->isl_p); - - if (sl->isl_p == IPPROTO_TCP || sl->isl_p == IPPROTO_UDP) { - (void) sprintf(t, "%s,%s -> ", - hostname(res, sl->isl_v, (u_32_t *)&sl->isl_src), - portname(res, proto, (u_int)sl->isl_sport)); - t += strlen(t); - (void) sprintf(t, "%s,%s PR %s", - hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), - portname(res, proto, (u_int)sl->isl_dport), proto); - } else if (sl->isl_p == IPPROTO_ICMP) { - (void) sprintf(t, "%s -> ", hostname(res, sl->isl_v, - (u_32_t *)&sl->isl_src)); - t += strlen(t); - (void) sprintf(t, "%s PR icmp %d", - hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), - sl->isl_itype); - } else if (sl->isl_p == IPPROTO_ICMPV6) { - (void) sprintf(t, "%s -> ", hostname(res, sl->isl_v, - (u_32_t *)&sl->isl_src)); - t += strlen(t); - (void) sprintf(t, "%s PR icmpv6 %d", - hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), - sl->isl_itype); - } - t += strlen(t); - if (sl->isl_type != ISL_NEW) { -#ifdef USE_QUAD_T - (void) sprintf(t, " Pkts %qd Bytes %qd", - (long long)sl->isl_pkts, - (long long)sl->isl_bytes); -#else - (void) sprintf(t, " Pkts %ld Bytes %ld", - sl->isl_pkts, sl->isl_bytes); -#endif - t += strlen(t); - } - - *t++ = '\n'; - *t++ = '\0'; - if (opts & OPT_SYSLOG) - syslog(LOG_INFO, "%s", line); - else - (void) fprintf(log, "%s", line); -} - - -static void print_log(logtype, log, buf, blen) -FILE *log; -char *buf; -int logtype, blen; -{ - iplog_t *ipl; - char *bp = NULL, *bpo = NULL; - int psize; - - while (blen > 0) { - ipl = (iplog_t *)buf; - if ((u_long)ipl & (sizeof(long)-1)) { - if (bp) - bpo = bp; - bp = (char *)malloc(blen); - bcopy((char *)ipl, bp, blen); - if (bpo) { - free(bpo); - bpo = NULL; - } - buf = bp; - continue; - } - if (ipl->ipl_magic != IPL_MAGIC) { - /* invalid data or out of sync */ - break; - } - psize = ipl->ipl_dsize; - switch (logtype) - { - case IPL_LOGIPF : - print_ipflog(log, buf, psize); - break; - case IPL_LOGNAT : - print_natlog(log, buf, psize); - break; - case IPL_LOGSTATE : - print_statelog(log, buf, psize); - break; - } - - blen -= psize; - buf += psize; - } - if (bp) - free(bp); - return; -} - - -static void print_ipflog(log, buf, blen) -FILE *log; -char *buf; -int blen; -{ - tcphdr_t *tp; - struct icmp *ic; - struct icmp *icmp; - struct tm *tm; - char *t, *proto; - int i, v, lvl, res, len, off, plen, ipoff; - ip_t *ipc, *ip; - u_short hl, p; - ipflog_t *ipf; - iplog_t *ipl; - u_32_t *s, *d; -#ifdef USE_INET6 - ip6_t *ip6; -#endif - - ipl = (iplog_t *)buf; - ipf = (ipflog_t *)((char *)buf + IPLOG_SIZE); - ip = (ip_t *)((char *)ipf + sizeof(*ipf)); - v = ip->ip_v; - res = (opts & OPT_RESOLVE) ? 1 : 0; - t = line; - *t = '\0'; - tm = localtime((time_t *)&ipl->ipl_sec); -#ifdef linux - if (v == 4) - ip->ip_len = ntohs(ip->ip_len); -#endif - - len = sizeof(line); - if (!(opts & OPT_SYSLOG)) { - (void) strftime(t, len, "%d/%m/%Y ", tm); - i = strlen(t); - len -= i; - t += i; - } - (void) strftime(t, len, "%T", tm); - t += strlen(t); - (void) sprintf(t, ".%-.6ld ", ipl->ipl_usec); - t += strlen(t); - if (ipl->ipl_count > 1) { - (void) sprintf(t, "%dx ", ipl->ipl_count); - t += strlen(t); - } -#if (SOLARIS || \ - (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ - (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603))) || defined(linux) - { - char ifname[sizeof(ipf->fl_ifname) + 1]; - - strncpy(ifname, (char *)ipf->fl_ifname, sizeof(ipf->fl_ifname)); - ifname[sizeof(ipf->fl_ifname)] = '\0'; - (void) sprintf(t, "%s", ifname); - t += strlen(t); -# if SOLARIS - if (isalpha(*(t - 1))) { - sprintf(t, "%d", ipf->fl_unit); - t += strlen(t); - } -# endif - } -#else - for (len = 0; len < 3; len++) - if (ipf->fl_ifname[len] == '\0') - break; - if (ipf->fl_ifname[len]) - len++; - (void) sprintf(t, "%*.*s%u", len, len, ipf->fl_ifname, ipf->fl_unit); - t += strlen(t); -#endif - if (ipf->fl_group == 0xffffffff) - strcat(t, " @-1:"); - else - (void) sprintf(t, " @%u:", ipf->fl_group); - t += strlen(t); - if (ipf->fl_rule == 0xffffffff) - strcat(t, "-1 "); - else - (void) sprintf(t, "%u ", ipf->fl_rule + 1); - t += strlen(t); - - if (ipf->fl_flags & FF_SHORT) { - *t++ = 'S'; - lvl = LOG_ERR; - } else if (ipf->fl_flags & FR_PASS) { - if (ipf->fl_flags & FR_LOG) - *t++ = 'p'; - else - *t++ = 'P'; - lvl = LOG_NOTICE; - } else if (ipf->fl_flags & FR_BLOCK) { - if (ipf->fl_flags & FR_LOG) - *t++ = 'b'; - else - *t++ = 'B'; - lvl = LOG_WARNING; - } else if (ipf->fl_flags & FF_LOGNOMATCH) { - *t++ = 'n'; - lvl = LOG_NOTICE; - } else { - *t++ = 'L'; - lvl = LOG_INFO; - } - if (ipf->fl_loglevel != 0xffff) - lvl = ipf->fl_loglevel; - *t++ = ' '; - *t = '\0'; - - if (v == 6) { -#ifdef USE_INET6 - off = 0; - ipoff = 0; - hl = sizeof(ip6_t); - ip6 = (ip6_t *)ip; - p = (u_short)ip6->ip6_nxt; - s = (u_32_t *)&ip6->ip6_src; - d = (u_32_t *)&ip6->ip6_dst; - plen = hl + ntohs(ip6->ip6_plen); -#else - sprintf(t, "ipv6"); - goto printipflog; -#endif - } else if (v == 4) { - hl = (ip->ip_hl << 2); - ipoff = ip->ip_off; - off = ipoff & IP_OFFMASK; - p = (u_short)ip->ip_p; - s = (u_32_t *)&ip->ip_src; - d = (u_32_t *)&ip->ip_dst; - plen = ip->ip_len; - } else { - goto printipflog; - } - proto = getproto(p); - - if ((p == IPPROTO_TCP || p == IPPROTO_UDP) && !off) { - tp = (tcphdr_t *)((char *)ip + hl); - if (!(ipf->fl_flags & FF_SHORT)) { - (void) sprintf(t, "%s,%s -> ", hostname(res, v, s), - portname(res, proto, (u_int)tp->th_sport)); - t += strlen(t); - (void) sprintf(t, "%s,%s PR %s len %hu %hu", - hostname(res, v, d), - portname(res, proto, (u_int)tp->th_dport), - proto, hl, plen); - t += strlen(t); - - if (p == IPPROTO_TCP) { - *t++ = ' '; - *t++ = '-'; - for (i = 0; tcpfl[i].value; i++) - if (tp->th_flags & tcpfl[i].value) - *t++ = tcpfl[i].flag; - if (opts & OPT_VERBOSE) { - (void) sprintf(t, " %lu %lu %hu", - (u_long)(ntohl(tp->th_seq)), - (u_long)(ntohl(tp->th_ack)), - ntohs(tp->th_win)); - t += strlen(t); - } - } - *t = '\0'; - } else { - (void) sprintf(t, "%s -> ", hostname(res, v, s)); - t += strlen(t); - (void) sprintf(t, "%s PR %s len %hu %hu", - hostname(res, v, d), proto, hl, plen); - } - } else if ((p == IPPROTO_ICMPV6) && !off && (v == 6)) { - ic = (struct icmp *)((char *)ip + hl); - (void) sprintf(t, "%s -> ", hostname(res, v, s)); - t += strlen(t); - (void) sprintf(t, "%s PR icmpv6 len %hu %hu icmpv6 %s", - hostname(res, v, d), hl, plen, - icmpname6(ic->icmp_type, ic->icmp_code)); - } else if ((p == IPPROTO_ICMP) && !off && (v == 4)) { - ic = (struct icmp *)((char *)ip + hl); - (void) sprintf(t, "%s -> ", hostname(res, v, s)); - t += strlen(t); - (void) sprintf(t, "%s PR icmp len %hu %hu icmp %s", - hostname(res, v, d), hl, plen, - icmpname(ic->icmp_type, ic->icmp_code)); - if (ic->icmp_type == ICMP_UNREACH || - ic->icmp_type == ICMP_SOURCEQUENCH || - ic->icmp_type == ICMP_PARAMPROB || - ic->icmp_type == ICMP_REDIRECT || - ic->icmp_type == ICMP_TIMXCEED) { - ipc = &ic->icmp_ip; - i = ntohs(ipc->ip_len); - ipoff = ntohs(ipc->ip_off); - proto = getproto(ipc->ip_p); - - if (!(ipoff & IP_OFFMASK) && - ((ipc->ip_p == IPPROTO_TCP) || - (ipc->ip_p == IPPROTO_UDP))) { - tp = (tcphdr_t *)((char *)ipc + hl); - t += strlen(t); - (void) sprintf(t, " for %s,%s -", - HOSTNAME_V4(res, ipc->ip_src), - portname(res, proto, - (u_int)tp->th_sport)); - t += strlen(t); - (void) sprintf(t, " %s,%s PR %s len %hu %hu", - HOSTNAME_V4(res, ipc->ip_dst), - portname(res, proto, - (u_int)tp->th_dport), - proto, ipc->ip_hl << 2, i); - } else if (!(ipoff & IP_OFFMASK) && - (ipc->ip_p == IPPROTO_ICMP)) { - icmp = (icmphdr_t *)((char *)ipc + hl); - - t += strlen(t); - (void) sprintf(t, " for %s -", - HOSTNAME_V4(res, ipc->ip_src)); - t += strlen(t); - (void) sprintf(t, - " %s PR icmp len %hu %hu icmp %d/%d", - HOSTNAME_V4(res, ipc->ip_dst), - ipc->ip_hl << 2, i, - icmp->icmp_type, icmp->icmp_code); - - } else { - t += strlen(t); - (void) sprintf(t, " for %s -", - HOSTNAME_V4(res, ipc->ip_src)); - t += strlen(t); - (void) sprintf(t, " %s PR %s len %hu (%hu)", - HOSTNAME_V4(res, ipc->ip_dst), proto, - ipc->ip_hl << 2, i); - t += strlen(t); - if (ipoff & IP_OFFMASK) { - (void) sprintf(t, " (frag %d:%hu@%hu%s%s)", - ntohs(ipc->ip_id), - i - (ipc->ip_hl<<2), - (ipoff & IP_OFFMASK) << 3, - ipoff & IP_MF ? "+" : "", - ipoff & IP_DF ? "-" : ""); - } - } - } - } else { - (void) sprintf(t, "%s -> ", hostname(res, v, s)); - t += strlen(t); - (void) sprintf(t, "%s PR %s len %hu (%hu)", - hostname(res, v, d), proto, hl, plen); - t += strlen(t); - if (off & IP_OFFMASK) - (void) sprintf(t, " (frag %d:%hu@%hu%s%s)", - ntohs(ip->ip_id), - plen - hl, (off & IP_OFFMASK) << 3, - ipoff & IP_MF ? "+" : "", - ipoff & IP_DF ? "-" : ""); - } - t += strlen(t); - - if (ipf->fl_flags & FR_KEEPSTATE) { - (void) strcpy(t, " K-S"); - t += strlen(t); - } - - if (ipf->fl_flags & FR_KEEPFRAG) { - (void) strcpy(t, " K-F"); - t += strlen(t); - } - - if (ipf->fl_dir == 0) - strcpy(t, " IN"); - else if (ipf->fl_dir == 1) - strcpy(t, " OUT"); - t += strlen(t); -printipflog: - *t++ = '\n'; - *t++ = '\0'; - if (opts & OPT_SYSLOG) - syslog(lvl, "%s", line); - else - (void) fprintf(log, "%s", line); - if (opts & OPT_HEXHDR) - dumphex(log, (u_char *)buf, sizeof(iplog_t) + sizeof(*ipf)); - if (opts & OPT_HEXBODY) - dumphex(log, (u_char *)ip, ipf->fl_plen + ipf->fl_hlen); - else if ((opts & OPT_LOGBODY) && (ipf->fl_flags & FR_LOGBODY)) - dumphex(log, (u_char *)ip + ipf->fl_hlen, ipf->fl_plen); -} - - -static void usage(prog) -char *prog; -{ - fprintf(stderr, "%s: [-NFhstvxX] [-f <logfile>]\n", prog); - exit(1); -} - - -static void write_pid(file) -char *file; -{ - FILE *fp = NULL; - int fd; - - if ((fd = open(file, O_CREAT|O_TRUNC|O_WRONLY, 0644)) >= 0) - fp = fdopen(fd, "w"); - if (!fp) { - close(fd); - fprintf(stderr, "unable to open/create pid file: %s\n", file); - return; - } - fprintf(fp, "%d", getpid()); - fclose(fp); - close(fd); -} - - -static void flushlogs(file, log) -char *file; -FILE *log; -{ - int fd, flushed = 0; - - if ((fd = open(file, O_RDWR)) == -1) { - (void) fprintf(stderr, "%s: open: %s\n", - file, STRERROR(errno)); - exit(1); - } - - if (ioctl(fd, SIOCIPFFB, &flushed) == 0) { - printf("%d bytes flushed from log buffer\n", - flushed); - fflush(stdout); - } else - perror("SIOCIPFFB"); - (void) close(fd); - - if (flushed) { - if (opts & OPT_SYSLOG) - syslog(LOG_INFO, "%d bytes flushed from log\n", - flushed); - else if (log != stdout) - fprintf(log, "%d bytes flushed from log\n", flushed); - } -} - - -static void logopts(turnon, options) -int turnon; -char *options; -{ - int flags = 0; - char *s; - - for (s = options; *s; s++) - { - switch (*s) - { - case 'N' : - flags |= OPT_NAT; - break; - case 'S' : - flags |= OPT_STATE; - break; - case 'I' : - flags |= OPT_FILTER; - break; - default : - fprintf(stderr, "Unknown log option %c\n", *s); - exit(1); - } - } - - if (turnon) - opts |= flags; - else - opts &= ~(flags); -} - - -int main(argc, argv) -int argc; -char *argv[]; -{ - int fdt[3], devices = 0, make_daemon = 0; - char buf[IPLLOGSIZE], *iplfile[3], *s; - int fd[3], doread, n, i; - extern char *optarg; - extern int optind; - int regular[3], c; - FILE *log = stdout; - struct stat sb; - size_t nr, tr; - - fd[0] = fd[1] = fd[2] = -1; - fdt[0] = fdt[1] = fdt[2] = -1; - iplfile[0] = IPL_NAME; - iplfile[1] = IPNAT_NAME; - iplfile[2] = IPSTATE_NAME; - - while ((c = getopt(argc, argv, "?abDf:FhnN:o:O:pP:sS:tvxX")) != -1) - switch (c) - { - case 'a' : - opts |= OPT_LOGALL; - fdt[0] = IPL_LOGIPF; - fdt[1] = IPL_LOGNAT; - fdt[2] = IPL_LOGSTATE; - break; - case 'b' : - opts |= OPT_LOGBODY; - break; - case 'D' : - make_daemon = 1; - break; - case 'f' : case 'I' : - opts |= OPT_FILTER; - fdt[0] = IPL_LOGIPF; - iplfile[0] = optarg; - break; - case 'F' : - flushlogs(iplfile[0], log); - flushlogs(iplfile[1], log); - flushlogs(iplfile[2], log); - break; - case 'n' : - opts |= OPT_RESOLVE; - break; - case 'N' : - opts |= OPT_NAT; - fdt[1] = IPL_LOGNAT; - iplfile[1] = optarg; - break; - case 'o' : case 'O' : - logopts(c == 'o', optarg); - fdt[0] = fdt[1] = fdt[2] = -1; - if (opts & OPT_FILTER) - fdt[0] = IPL_LOGIPF; - if (opts & OPT_NAT) - fdt[1] = IPL_LOGNAT; - if (opts & OPT_STATE) - fdt[2] = IPL_LOGSTATE; - break; - case 'p' : - opts |= OPT_PORTNUM; - break; - case 'P' : - pidfile = optarg; - break; - case 's' : - s = strrchr(argv[0], '/'); - if (s == NULL) - s = argv[0]; - else - s++; - openlog(s, LOG_NDELAY|LOG_PID, LOGFAC); - opts |= OPT_SYSLOG; - log = NULL; - break; - case 'S' : - opts |= OPT_STATE; - fdt[2] = IPL_LOGSTATE; - iplfile[2] = optarg; - break; - case 't' : - opts |= OPT_TAIL; - break; - case 'v' : - opts |= OPT_VERBOSE; - break; - case 'x' : - opts |= OPT_HEXBODY; - break; - case 'X' : - opts |= OPT_HEXHDR; - break; - default : - case 'h' : - case '?' : - usage(argv[0]); - } - - init_tabs(); - - /* - * Default action is to only open the filter log file. - */ - if ((fdt[0] == -1) && (fdt[1] == -1) && (fdt[2] == -1)) - fdt[0] = IPL_LOGIPF; - - for (i = 0; i < 3; i++) { - if (fdt[i] == -1) - continue; - if (!strcmp(iplfile[i], "-")) - fd[i] = 0; - else { - if ((fd[i] = open(iplfile[i], O_RDONLY)) == -1) { - (void) fprintf(stderr, - "%s: open: %s\n", iplfile[i], - STRERROR(errno)); - exit(1); - /* NOTREACHED */ - } - if (fstat(fd[i], &sb) == -1) { - (void) fprintf(stderr, "%d: fstat: %s\n", - fd[i], STRERROR(errno)); - exit(1); - /* NOTREACHED */ - } - if (!(regular[i] = !S_ISCHR(sb.st_mode))) - devices++; - } - } - - if (!(opts & OPT_SYSLOG)) { - logfile = argv[optind]; - log = logfile ? fopen(logfile, "a") : stdout; - if (log == NULL) { - (void) fprintf(stderr, "%s: fopen: %s\n", - argv[optind], STRERROR(errno)); - exit(1); - /* NOTREACHED */ - } - setvbuf(log, NULL, _IONBF, 0); - } else - log = NULL; - - if (make_daemon && ((log != stdout) || (opts & OPT_SYSLOG))) { -#if BSD - daemon(0, !(opts & OPT_SYSLOG)); -#else - int pid; - if ((pid = fork()) > 0) - exit(0); - if (pid < 0) { - (void) fprintf(stderr, "%s: fork() failed: %s\n", - argv[0], STRERROR(errno)); - exit(1); - /* NOTREACHED */ - } - setsid(); - if ((opts & OPT_SYSLOG)) - close(2); -#endif /* !BSD */ - close(0); - close(1); - } - write_pid(pidfile); - - signal(SIGHUP, handlehup); - - for (doread = 1; doread; ) { - nr = 0; - - for (i = 0; i < 3; i++) { - tr = 0; - if (fdt[i] == -1) - continue; - if (!regular[i]) { - if (ioctl(fd[i], FIONREAD, &tr) == -1) { - if (opts & OPT_SYSLOG) - syslog(LOG_CRIT, - "ioctl(FIONREAD): %m"); - else - perror("ioctl(FIONREAD)"); - exit(1); - /* NOTREACHED */ - } - } else { - tr = (lseek(fd[i], 0, SEEK_CUR) < sb.st_size); - if (!tr && !(opts & OPT_TAIL)) - doread = 0; - } - if (!tr) - continue; - nr += tr; - - tr = read_log(fd[i], &n, buf, sizeof(buf)); - if (donehup) { - donehup = 0; - if (newlog) { - fclose(log); - log = newlog; - newlog = NULL; - } - } - - switch (tr) - { - case -1 : - if (opts & OPT_SYSLOG) - syslog(LOG_CRIT, "read: %m\n"); - else - perror("read"); - doread = 0; - break; - case 1 : - if (opts & OPT_SYSLOG) - syslog(LOG_CRIT, "aborting logging\n"); - else - fprintf(log, "aborting logging\n"); - doread = 0; - break; - case 2 : - break; - case 0 : - if (n > 0) { - print_log(fdt[i], log, buf, n); - if (!(opts & OPT_SYSLOG)) - fflush(log); - } - break; - } - } - if (!nr && ((opts & OPT_TAIL) || devices)) - sleep(1); - } - exit(0); - /* NOTREACHED */ -} @@ -1,20 +1,61 @@ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_fil.h 1.35 6/5/96 - * $Id: ipmon.h,v 2.8.2.1 2006/03/21 16:13:31 darrenr Exp $ + * $Id$ */ +typedef struct ipmon_msg_s { + int imm_msglen; + char *imm_msg; + int imm_dsize; + void *imm_data; + time_t imm_when; + int imm_loglevel; +} ipmon_msg_t; -typedef struct ipmon_action { +typedef void (*ims_destroy_func_t)(void *); +typedef void *(*ims_dup_func_t)(void *); +typedef int (*ims_match_func_t)(void *, void *); +typedef void *(*ims_parse_func_t)(char **); +typedef void (*ims_print_func_t)(void *); +typedef int (*ims_store_func_t)(void *, ipmon_msg_t *); + +typedef struct ipmon_saver_s { + char *ims_name; + ims_destroy_func_t ims_destroy; + ims_dup_func_t ims_dup; + ims_match_func_t ims_match; + ims_parse_func_t ims_parse; + ims_print_func_t ims_print; + ims_store_func_t ims_store; +} ipmon_saver_t; + +typedef struct ipmon_saver_int_s { + struct ipmon_saver_int_s *imsi_next; + ipmon_saver_t *imsi_stor; + void *imsi_handle; +} ipmon_saver_int_t; + +typedef struct ipmon_doing_s { + struct ipmon_doing_s *ipmd_next; + void *ipmd_token; + ipmon_saver_t *ipmd_saver; + /* + * ipmd_store is "cached" in this structure to avoid a double + * deref when doing saves.... + */ + int (*ipmd_store)(void *, ipmon_msg_t *); +} ipmon_doing_t; + + +typedef struct ipmon_action { struct ipmon_action *ac_next; int ac_mflag; /* collection of things to compare */ int ac_dflag; /* flags to compliment the doing fields */ - int ac_syslog; /* = 1 to syslog rules. */ - char *ac_savefile; /* filename to save log records to */ - FILE *ac_savefp; + int ac_logpri; int ac_direction; char ac_group[FR_GROUPLEN]; char ac_nattag[16]; @@ -26,19 +67,21 @@ typedef struct ipmon_action { int ac_second; int ac_result; u_32_t ac_sip; - u_32_t ac_smsk; + u_32_t ac_smsk; u_32_t ac_dip; - u_32_t ac_dmsk; + u_32_t ac_dmsk; u_short ac_sport; u_short ac_dport; - char *ac_exec; /* execute argument */ - char *ac_run; /* actual command that gets run */ char *ac_iface; /* * used with ac_packet/ac_second */ struct timeval ac_last; int ac_pktcnt; + /* + * What to do with matches + */ + ipmon_doing_t *ac_doing; } ipmon_action_t; #define ac_lastsec ac_last.tv_sec @@ -68,19 +111,18 @@ typedef struct ipmon_action { #define IPMR_NOMATCH 3 #define IPMR_LOG 4 -#define IPMDO_SAVERAW 0x0001 - -#define OPT_SYSLOG 0x001 -#define OPT_RESOLVE 0x002 -#define OPT_HEXBODY 0x004 -#define OPT_VERBOSE 0x008 -#define OPT_HEXHDR 0x010 -#define OPT_TAIL 0x020 -#define OPT_NAT 0x080 -#define OPT_STATE 0x100 -#define OPT_FILTER 0x200 -#define OPT_PORTNUM 0x400 -#define OPT_LOGALL (OPT_NAT|OPT_STATE|OPT_FILTER) +#define IPMON_SYSLOG 0x001 +#define IPMON_RESOLVE 0x002 +#define IPMON_HEXBODY 0x004 +#define IPMON_HEXHDR 0x010 +#define IPMON_TAIL 0x020 +#define IPMON_VERBOSE 0x040 +#define IPMON_NAT 0x080 +#define IPMON_STATE 0x100 +#define IPMON_FILTER 0x200 +#define IPMON_PORTNUM 0x400 +#define IPMON_LOGALL (IPMON_NAT|IPMON_STATE|IPMON_FILTER) +#define IPMON_LOGBODY 0x800 #define HOSTNAME_V4(a,b) hostname((a), 4, (u_32_t *)&(b)) @@ -88,8 +130,11 @@ typedef struct ipmon_action { #define LOGFAC LOG_LOCAL0 #endif +extern void dump_config __P((void)); extern int load_config __P((char *)); +extern void unload_config __P((void)); extern void dumphex __P((FILE *, int, char *, int)); extern int check_action __P((char *, char *, int, int)); extern char *getword __P((int)); -extern int fac_findname __P((char *)); +extern void *add_doing __P((ipmon_saver_t *)); + diff --git a/ipnat.c b/ipnat.c deleted file mode 100644 index 69e7959260e71..0000000000000 --- a/ipnat.c +++ /dev/null @@ -1,433 +0,0 @@ -/* - * Copyright (C) 1993-2002 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com) - */ -#if defined(__sgi) && (IRIX > 602) -# include <sys/ptimers.h> -#endif -#include <stdio.h> -#include <string.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/types.h> -#if !defined(__SVR4) && !defined(__svr4__) -#include <strings.h> -#else -#include <sys/byteorder.h> -#endif -#include <sys/time.h> -#include <sys/param.h> -#include <stdlib.h> -#include <unistd.h> -#include <stddef.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#if defined(sun) && (defined(__svr4__) || defined(__SVR4)) -# include <sys/ioccom.h> -# include <sys/sysmacros.h> -#endif -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/tcp.h> -#include <net/if.h> -#if __FreeBSD_version >= 300000 -# include <net/if_var.h> -#endif -#include <netdb.h> -#include <arpa/nameser.h> -#include <arpa/inet.h> -#include <resolv.h> -#include <ctype.h> -#include <nlist.h> -#include "netinet/ip_compat.h" -#include "netinet/ip_fil.h" -#include "netinet/ip_nat.h" -#include "netinet/ip_state.h" -#include "netinet/ip_proxy.h" -#include "ipf.h" -#include "kmem.h" - -#if defined(sun) && !SOLARIS2 -# define STRERROR(x) sys_errlist[x] -extern char *sys_errlist[]; -#else -# define STRERROR(x) strerror(x) -#endif - -#if !defined(lint) -static const char sccsid[] ="@(#)ipnat.c 1.9 6/5/96 (C) 1993 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipnat.c,v 2.16.2.25 2003/06/05 14:00:28 darrenr Exp $"; -#endif - - -#if SOLARIS -#define bzero(a,b) memset(a,0,b) -#endif -int use_inet6 = 0; -char thishost[MAXHOSTNAMELEN]; - -extern char *optarg; -extern int optind; -#if 0 -extern ipnat_t *natparse __P((char *, int)); -#endif -extern void natparsefile __P((int, char *, int)); -extern void printnat __P((ipnat_t *, int)); -extern void printactivenat __P((nat_t *, int)); -extern void printhostmap __P((hostmap_t *, u_int)); -extern char *getsumd __P((u_32_t)); - -static int dostats __P((natstat_t *, int)); -static int flushtable __P((int, int)); -void usage __P((char *)); -int countbits __P((u_32_t)); -char *getnattype __P((ipnat_t *)); -int main __P((int, char*[])); -void printaps __P((ap_session_t *, int)); -static int showhostmap __P((natstat_t *nsp)); -static int natstat_dead __P((natstat_t *, char *)); - - -void usage(name) -char *name; -{ - fprintf(stderr, "Usage: %s [-CFhlnrsv] [-f filename]\n", name); - exit(1); -} - - -int main(argc, argv) -int argc; -char *argv[]; -{ - natstat_t ns, *nsp = &ns; - char *file, *core, *kernel; - int fd, opts, c, mode; - - fd = -1; - opts = 0; - file = NULL; - core = NULL; - kernel = NULL; - mode = O_RDWR; - - while ((c = getopt(argc, argv, "CdFf:hlM:N:nrsv")) != -1) - switch (c) - { - case 'C' : - opts |= OPT_CLEAR; - break; - case 'd' : - opts |= OPT_DEBUG; - break; - case 'f' : - file = optarg; - break; - case 'F' : - opts |= OPT_FLUSH; - break; - case 'h' : - opts |=OPT_HITS; - break; - case 'l' : - opts |= OPT_LIST; - mode = O_RDONLY; - break; - case 'M' : - core = optarg; - break; - case 'N' : - kernel = optarg; - break; - case 'n' : - opts |= OPT_NODO; - mode = O_RDONLY; - break; - case 'r' : - opts |= OPT_REMOVE; - break; - case 's' : - opts |= OPT_STAT; - mode = O_RDONLY; - break; - case 'v' : - opts |= OPT_VERBOSE; - break; - case '?' : - default : - usage(argv[0]); - } - - if (optind < 2) - usage(argv[0]); - - if ((kernel != NULL) || (core != NULL)) { - (void) setgid(getgid()); - (void) setuid(getuid()); - } - - bzero((char *)&ns, sizeof(ns)); - - gethostname(thishost, sizeof(thishost)); - thishost[sizeof(thishost) - 1] = '\0'; - - if (!(opts & OPT_NODO) && (kernel == NULL) && (core == NULL)) { - if (openkmem(kernel, core) == -1) - exit(1); - - if (((fd = open(IPL_NAT, mode)) == -1) && - ((fd = open(IPL_NAT, O_RDONLY)) == -1)) { - (void) fprintf(stderr, "%s: open: %s\n", IPL_NAT, - STRERROR(errno)); - if (errno == ENODEV) - fprintf(stderr, "IPFilter enabled?\n"); - exit(1); - } - if (ioctl(fd, SIOCGNATS, &nsp) == -1) { - perror("ioctl(SIOCGNATS)"); - exit(1); - } - (void) setgid(getgid()); - (void) setuid(getuid()); - } else if ((kernel != NULL) || (core != NULL)) { - if (openkmem(kernel, core) == -1) - exit(1); - - if (natstat_dead(nsp, kernel)) - exit(1); - if (opts & (OPT_LIST|OPT_STAT)) { - if (dostats(nsp, opts)) - exit(1); - } - exit(0); - } - - if (opts & (OPT_FLUSH|OPT_CLEAR)) - if (flushtable(fd, opts)) - exit(1); - if (file) { - /* NB natparsefile exits with nonzero in case of error */ - natparsefile(fd, file, opts); - } - if (opts & (OPT_LIST|OPT_STAT)) - if (dostats(nsp, opts)) - exit(1); - - /* TBD why not exit(0)? */ - return 0; -} - - -/* - * Read NAT statistic information in using a symbol table and memory file - * rather than doing ioctl's. - */ -static int natstat_dead(nsp, kernel) -natstat_t *nsp; -char *kernel; -{ - struct nlist nat_nlist[10] = { - { "nat_table" }, /* 0 */ - { "nat_list" }, - { "maptable" }, - { "ipf_nattable_sz" }, - { "ipf_natrules_sz" }, - { "ipf_rdrrules_sz" }, /* 5 */ - { "ipf_hostmap_sz" }, - { "nat_instances" }, - { "ap_sess_list" }, - { NULL } - }; - void *tables[2]; - - if (nlist(kernel, nat_nlist) == -1) { - fprintf(stderr, "nlist error\n"); - return -1; - } - - /* - * Normally the ioctl copies all of these values into the structure - * for us, before returning it to userland, so here we must copy each - * one in individually. - */ - kmemcpy((char *)&tables, nat_nlist[0].n_value, sizeof(tables)); - nsp->ns_table[0] = tables[0]; - nsp->ns_table[1] = tables[1]; - - kmemcpy((char *)&nsp->ns_list, nat_nlist[1].n_value, - sizeof(nsp->ns_list)); - kmemcpy((char *)&nsp->ns_maptable, nat_nlist[2].n_value, - sizeof(nsp->ns_maptable)); - kmemcpy((char *)&nsp->ns_nattab_sz, nat_nlist[3].n_value, - sizeof(nsp->ns_nattab_sz)); - kmemcpy((char *)&nsp->ns_rultab_sz, nat_nlist[4].n_value, - sizeof(nsp->ns_rultab_sz)); - kmemcpy((char *)&nsp->ns_rdrtab_sz, nat_nlist[5].n_value, - sizeof(nsp->ns_rdrtab_sz)); - kmemcpy((char *)&nsp->ns_hostmap_sz, nat_nlist[6].n_value, - sizeof(nsp->ns_hostmap_sz)); - kmemcpy((char *)&nsp->ns_instances, nat_nlist[7].n_value, - sizeof(nsp->ns_instances)); - kmemcpy((char *)&nsp->ns_apslist, nat_nlist[8].n_value, - sizeof(nsp->ns_apslist)); - - return 0; -} - - -/* - * Display NAT statistics. - */ -static int dostats(nsp, opts) -natstat_t *nsp; -int opts; -{ - nat_t **nt[2], *np, nat; - ipnat_t ipn; - int rc = 0; - - /* - * Show statistics ? - */ - if (opts & OPT_STAT) { - printf("mapped\tin\t%lu\tout\t%lu\n", - nsp->ns_mapped[0], nsp->ns_mapped[1]); - printf("added\t%lu\texpired\t%lu\n", - nsp->ns_added, nsp->ns_expire); - printf("no memory\t%lu\tbad nat\t%lu\n", - nsp->ns_memfail, nsp->ns_badnat); - printf("inuse\t%lu\nrules\t%lu\n", - nsp->ns_inuse, nsp->ns_rules); - printf("wilds\t%u\n", nsp->ns_wilds); - if (opts & OPT_VERBOSE) - printf("table %p list %p\n", - nsp->ns_table, nsp->ns_list); - } - - /* - * Show list of NAT rules and NAT sessions ? - */ - if (opts & OPT_LIST) { - printf("List of active MAP/Redirect filters:\n"); - while (nsp->ns_list) { - if (kmemcpy((char *)&ipn, (long)nsp->ns_list, - sizeof(ipn))) { - perror("kmemcpy"); - rc = -1; - break; - } - if (opts & OPT_HITS) - printf("%d ", ipn.in_hits); - printnat(&ipn, opts & (OPT_DEBUG|OPT_VERBOSE)); - nsp->ns_list = ipn.in_next; - } - - nt[0] = (nat_t **)malloc(sizeof(*nt) * NAT_SIZE); - if (kmemcpy((char *)nt[0], (long)nsp->ns_table[0], - sizeof(**nt) * NAT_SIZE)) { - perror("kmemcpy"); - rc = -1; - } - if (rc) { - free(nt[0]); - return rc; - } - - printf("\nList of active sessions:\n"); - - for (np = nsp->ns_instances; np; np = nat.nat_next) { - if (kmemcpy((char *)&nat, (long)np, sizeof(nat))) { - /* TBD Is this an error? If so, return -1 */ - break; - } - printactivenat(&nat, opts); - } - - if (opts & OPT_VERBOSE) { - if (showhostmap(nsp)) { - free(nt[0]); - return -1; - } - } - - free(nt[0]); - } - return 0; -} - - -/* - * Display the active host mapping table. - */ -static int showhostmap(nsp) -natstat_t *nsp; -{ - hostmap_t hm, *hmp, **maptable; - u_int hv; - - printf("\nList of active host mappings:\n"); - - maptable = (hostmap_t **)malloc(sizeof(hostmap_t *) * - nsp->ns_hostmap_sz); - if (kmemcpy((char *)maptable, (u_long)nsp->ns_maptable, - sizeof(hostmap_t *) * nsp->ns_hostmap_sz)) { - perror("kmemcpy (maptable)"); - free(maptable); - return -1; - } - - for (hv = 0; hv < nsp->ns_hostmap_sz; hv++) { - hmp = maptable[hv]; - - while (hmp) { - if (kmemcpy((char *)&hm, (u_long)hmp, sizeof(hm))) { - perror("kmemcpy (hostmap)"); - free(maptable); - return -1; - } - - printhostmap(&hm, hv); - hmp = hm.hm_next; - } - } - free(maptable); - return 0; -} - - -/* - * Issue an ioctl to flush either the NAT rules table or the active mapping - * table or both. - */ -static int flushtable(fd, opts) -int fd, opts; -{ - int n = 0; - int rc = 0; - - if (opts & OPT_FLUSH) { - n = 0; - if (!(opts & OPT_NODO) && ioctl(fd, SIOCIPFFL, &n) == -1) { - perror("ioctl(SIOCFLNAT)"); - rc = -1; - } else { - printf("%d entries flushed from NAT table\n", n); - } - } - - if (opts & OPT_CLEAR) { - n = 1; - if (!(opts & OPT_NODO) && ioctl(fd, SIOCIPFFL, &n) == -1) { - perror("ioctl(SIOCCNATL)"); - rc = -1; - } else { - printf("%d entries flushed from NAT list\n", n); - } - } - - return rc; -} diff --git a/ipsd/Makefile b/ipsd/Makefile index 0f3ce08ba229c..d5dde8e7eec54 100644 --- a/ipsd/Makefile +++ b/ipsd/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 1993-1998 by Darren Reed. +# Copyright (C) 2012 by Darren Reed. # # See the IPFILTER.LICENCE file for details on licencing. # diff --git a/ipsd/ip_compat.h b/ipsd/ip_compat.h deleted file mode 100644 index a911fd83c3f3c..0000000000000 --- a/ipsd/ip_compat.h +++ /dev/null @@ -1,201 +0,0 @@ -/* - * (C)opyright 1995 by Darren Reed. - * - * This code may be freely distributed as long as it retains this notice - * and is not changed in any way. The author accepts no responsibility - * for the use of this software. I hate legaleese, don't you ? - * - * @(#)ip_compat.h 1.1 9/14/95 - */ - -/* - * These #ifdef's are here mainly for linux, but who knows, they may - * not be in other places or maybe one day linux will grow up and some - * of these will turn up there too. - */ -#ifndef ICMP_UNREACH -# define ICMP_UNREACH ICMP_DEST_UNREACH -#endif -#ifndef ICMP_SOURCEQUENCH -# define ICMP_SOURCEQUENCH ICMP_SOURCE_QUENCH -#endif -#ifndef ICMP_TIMXCEED -# define ICMP_TIMXCEED ICMP_TIME_EXCEEDED -#endif -#ifndef ICMP_PARAMPROB -# define ICMP_PARAMPROB ICMP_PARAMETERPROB -#endif -#ifndef IPVERSION -# define IPVERSION 4 -#endif -#ifndef IPOPT_MINOFF -# define IPOPT_MINOFF 4 -#endif -#ifndef IPOPT_COPIED -# define IPOPT_COPIED(x) ((x)&0x80) -#endif -#ifndef IPOPT_EOL -# define IPOPT_EOL 0 -#endif -#ifndef IPOPT_NOP -# define IPOPT_NOP 1 -#endif -#ifndef IP_MF -# define IP_MF ((u_short)0x2000) -#endif -#ifndef ETHERTYPE_IP -# define ETHERTYPE_IP ((u_short)0x0800) -#endif -#ifndef TH_FIN -# define TH_FIN 0x01 -#endif -#ifndef TH_SYN -# define TH_SYN 0x02 -#endif -#ifndef TH_RST -# define TH_RST 0x04 -#endif -#ifndef TH_PUSH -# define TH_PUSH 0x08 -#endif -#ifndef TH_ACK -# define TH_ACK 0x10 -#endif -#ifndef TH_URG -# define TH_URG 0x20 -#endif -#ifndef IPOPT_EOL -# define IPOPT_EOL 0 -#endif -#ifndef IPOPT_NOP -# define IPOPT_NOP 1 -#endif -#ifndef IPOPT_RR -# define IPOPT_RR 7 -#endif -#ifndef IPOPT_TS -# define IPOPT_TS 68 -#endif -#ifndef IPOPT_SECURITY -# define IPOPT_SECURITY 130 -#endif -#ifndef IPOPT_LSRR -# define IPOPT_LSRR 131 -#endif -#ifndef IPOPT_SATID -# define IPOPT_SATID 136 -#endif -#ifndef IPOPT_SSRR -# define IPOPT_SSRR 137 -#endif -#ifndef IPOPT_SECUR_UNCLASS -# define IPOPT_SECUR_UNCLASS ((u_short)0x0000) -#endif -#ifndef IPOPT_SECUR_CONFID -# define IPOPT_SECUR_CONFID ((u_short)0xf135) -#endif -#ifndef IPOPT_SECUR_EFTO -# define IPOPT_SECUR_EFTO ((u_short)0x789a) -#endif -#ifndef IPOPT_SECUR_MMMM -# define IPOPT_SECUR_MMMM ((u_short)0xbc4d) -#endif -#ifndef IPOPT_SECUR_RESTR -# define IPOPT_SECUR_RESTR ((u_short)0xaf13) -#endif -#ifndef IPOPT_SECUR_SECRET -# define IPOPT_SECUR_SECRET ((u_short)0xd788) -#endif -#ifndef IPOPT_SECUR_TOPSECRET -# define IPOPT_SECUR_TOPSECRET ((u_short)0x6bc5) -#endif - -#ifdef linux -# define icmp icmphdr -# define icmp_type type -# define icmp_code code - -/* - * From /usr/include/netinet/ip_var.h - * !%@#!$@# linux... - */ -struct ipovly { - caddr_t ih_next, ih_prev; /* for protocol sequence q's */ - u_char ih_x1; /* (unused) */ - u_char ih_pr; /* protocol */ - short ih_len; /* protocol length */ - struct in_addr ih_src; /* source internet address */ - struct in_addr ih_dst; /* destination internet address */ -}; - -typedef struct { - __u16 th_sport; - __u16 th_dport; - __u32 th_seq; - __u32 th_ack; -# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\ - defined(vax) - __u8 th_res:4; - __u8 th_off:4; -#else - __u8 th_off:4; - __u8 th_res:4; -#endif - __u8 th_flags; - __u16 th_win; - __u16 th_sum; - __u16 th_urp; -} tcphdr_t; - -typedef struct { - __u16 uh_sport; - __u16 uh_dport; - __s16 uh_ulen; - __u16 uh_sum; -} udphdr_t; - -typedef struct { -# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\ - defined(vax) - __u8 ip_hl:4; - __u8 ip_v:4; -# else - __u8 ip_hl:4; - __u8 ip_v:4; -# endif - __u8 ip_tos; - __u16 ip_len; - __u16 ip_id; - __u16 ip_off; - __u8 ip_ttl; - __u8 ip_p; - __u16 ip_sum; - struct in_addr ip_src; - struct in_addr ip_dst; -} ip_t; - -typedef struct { - __u8 ether_dhost[6]; - __u8 ether_shost[6]; - __u16 ether_type; -} ether_header_t; - -# define bcopy(a,b,c) memmove(b,a,c) -# define bcmp(a,b,c) memcmp(a,b,c) - -# define ifnet device - -#else - -typedef struct udphdr udphdr_t; -typedef struct tcphdr tcphdr_t; -typedef struct ip ip_t; -typedef struct ether_header ether_header_t; - -#endif - -#ifdef solaris -# define bcopy(a,b,c) memmove(b,a,c) -# define bcmp(a,b,c) memcmp(a,b,c) -# define bzero(a,b) memset(a,0,b) -#endif diff --git a/ipsd/ipsd.c b/ipsd/ipsd.c index 51d0a148902f5..ae52351aa289e 100644 --- a/ipsd/ipsd.c +++ b/ipsd/ipsd.c @@ -32,7 +32,7 @@ #ifndef lint static const char sccsid[] = "@(#)ipsd.c 1.3 12/3/95 (C)1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipsd.c,v 2.2 2001/06/09 17:09:25 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif extern char *optarg; @@ -64,7 +64,7 @@ int writes = 0; int ipcmp(sh1, sh2) -sdhit_t *sh1, *sh2; + sdhit_t *sh1, *sh2; { return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr; } @@ -75,9 +75,9 @@ sdhit_t *sh1, *sh2; * port. */ int findhit(ihp, src, dport) -ipsd_t *ihp; -struct in_addr src; -u_short dport; + ipsd_t *ihp; + struct in_addr src; + u_short dport; { int i, j, k; sdhit_t *sh; @@ -108,8 +108,8 @@ u_short dport; * interested in. */ int detect(ip, tcp) -ip_t *ip; -tcphdr_t *tcp; + ip_t *ip; + tcphdr_t *tcp; { ipsd_t *ihp; sdhit_t *sh; @@ -177,7 +177,7 @@ waiter() * Write statistics out to a file */ writestats(nwrites) -int nwrites; + int nwrites; { ipsd_t **ipsd, *ips; char fname[32]; @@ -217,7 +217,7 @@ void writenow() void usage(prog) -char *prog; + char *prog; { fprintf(stderr, "Usage: %s [-d device]\n", prog); exit(1); @@ -225,7 +225,7 @@ char *prog; void detecthits(fd, writecount) -int fd, writecount; + int fd, writecount; { struct in_addr ip; int hits = 0; @@ -241,8 +241,8 @@ int fd, writecount; main(argc, argv) -int argc; -char *argv[]; + int argc; + char *argv[]; { char *name = argv[0], *dev = NULL; int fd, writeafter = 10000, angelic = 0, c; diff --git a/ipsd/ipsdr.c b/ipsd/ipsdr.c index af007e45f8aa7..e71a710113cef 100644 --- a/ipsd/ipsdr.c +++ b/ipsd/ipsdr.c @@ -33,7 +33,7 @@ #ifndef lint static const char sccsid[] = "@(#)ipsdr.c 1.3 12/3/95 (C)1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipsdr.c,v 2.2 2001/06/09 17:09:25 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif extern char *optarg; @@ -55,21 +55,21 @@ int pkts; int ipcmp(sh1, sh2) -sdhit_t *sh1, *sh2; + sdhit_t *sh1, *sh2; { return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr; } int ssipcmp(sh1, sh2) -ipss_t *sh1, *sh2; + ipss_t *sh1, *sh2; { return sh1->ss_ip.s_addr - sh2->ss_ip.s_addr; } int countpbits(num) -u_long num; + u_long num; { int i, j; @@ -85,9 +85,9 @@ u_long num; * port. */ int findhit(ihp, src, dport) -ipsd_t *ihp; -struct in_addr src; -u_short dport; + ipsd_t *ihp; + struct in_addr src; + u_short dport; { int i, j, k; sdhit_t *sh; @@ -118,9 +118,9 @@ u_short dport; * interested in. */ int detect(srcip, dport, date) -struct in_addr srcip; -u_short dport; -time_t date; + struct in_addr srcip; + u_short dport; + time_t date; { ipsd_t *ihp; sdhit_t *sh; @@ -179,7 +179,7 @@ setuphits() * Write statistics out to a file */ addfile(file) -char *file; + char *file; { ipsd_t ipsd, *ips = &ipsd; sdhit_t hit, *hp; @@ -207,7 +207,7 @@ char *file; readfiles(dir) -char *dir; + char *dir; { struct direct **d; int i, j; @@ -224,8 +224,8 @@ char *dir; void printreport(ss, num) -ipss_t *ss; -int num; + ipss_t *ss; + int num; { struct in_addr ip; ipss_t *sp; @@ -299,8 +299,8 @@ collectips() main(argc, argv) -int argc; -char *argv[]; + int argc; + char *argv[]; { char c, *name = argv[0], *dir = NULL; int fd; diff --git a/ipsd/linux.h b/ipsd/linux.h index d9606cbba15dc..c66e48e2e6dde 100644 --- a/ipsd/linux.h +++ b/ipsd/linux.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1997-1998 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * diff --git a/ipsd/sbpf.c b/ipsd/sbpf.c index 457891b78104a..616e3c2097a16 100644 --- a/ipsd/sbpf.c +++ b/ipsd/sbpf.c @@ -66,7 +66,7 @@ static u_int bufsize = 32768, timeout = 1; int ack_recv(ep) -char *ep; + char *ep; { struct tcpiphdr tip; tcphdr_t *tcp; @@ -87,8 +87,8 @@ char *ep; int readloop(fd, port, dst) -int fd, port; -struct in_addr dst; + int fd, port; + struct in_addr dst; { register u_char *bp, *cp, *bufend; register struct bpf_hdr *bh; @@ -117,8 +117,8 @@ struct in_addr dst; } int initdevice(device, tout) -char *device; -int tout; + char *device; + int tout; { struct bpf_program prog; struct bpf_version bv; diff --git a/ipsd/sdlpi.c b/ipsd/sdlpi.c index baede7c46a06d..75e7683491ce3 100644 --- a/ipsd/sdlpi.c +++ b/ipsd/sdlpi.c @@ -58,7 +58,7 @@ void nullbell() int ack_recv(ep) -char *ep; + char *ep; { struct tcpiphdr tip; tcphdr_t *tcp; @@ -78,8 +78,8 @@ char *ep; int readloop(fd, port, dst) -int fd, port; -struct in_addr dst; + int fd, port; + struct in_addr dst; { static u_char buf[BUFSPACE]; register u_char *bp, *cp, *bufend; @@ -143,8 +143,8 @@ struct in_addr dst; } int initdevice(device, tout) -char *device; -int tout; + char *device; + int tout; { struct strioctl si; struct timeval to; diff --git a/ipsd/slinux.c b/ipsd/slinux.c index 6372a607b2c17..930dd1578d98c 100644 --- a/ipsd/slinux.c +++ b/ipsd/slinux.c @@ -41,7 +41,7 @@ static char *eth_dev = NULL; int ack_recv(bp) -char *bp; + char *bp; { struct tcpip tip; tcphdr_t *tcp; @@ -59,8 +59,8 @@ char *bp; void readloop(fd, port, dst) -int fd, port; -struct in_addr dst; + int fd, port; + struct in_addr dst; { static u_char buf[BUFSPACE]; struct sockaddr dest; @@ -100,8 +100,8 @@ struct in_addr dst; } int initdevice(dev, tout) -char *dev; -int tout; + char *dev; + int tout; { int fd; diff --git a/ipsd/snit.c b/ipsd/snit.c index e78c59190e001..0ce05e014e34a 100644 --- a/ipsd/snit.c +++ b/ipsd/snit.c @@ -53,7 +53,7 @@ static int timeout; int ack_recv(ep) -char *ep; + char *ep; { struct tcpiphdr tip; struct tcphdr *tcp; @@ -72,8 +72,8 @@ char *ep; int readloop(fd, dst) -int fd; -struct in_addr dst; + int fd; + struct in_addr dst; { static u_char buf[BUFSPACE]; register u_char *bp, *cp, *bufend; @@ -112,8 +112,8 @@ struct in_addr dst; } int initdevice(device, tout) -char *device; -int tout; + char *device; + int tout; { struct strioctl si; struct timeval to; diff --git a/ipsend/.cvsignore b/ipsend/.cvsignore deleted file mode 100644 index b7aea24eb8816..0000000000000 --- a/ipsend/.cvsignore +++ /dev/null @@ -1,3 +0,0 @@ -ipsend -ipresend -iptest diff --git a/ipsend/44arp.c b/ipsend/44arp.c index 4b08a8b5ce189..f284c3fa5ad10 100644 --- a/ipsend/44arp.c +++ b/ipsend/44arp.c @@ -11,9 +11,6 @@ #endif #include <net/if_dl.h> #include <net/if_types.h> -#if defined(__FreeBSD__) -# include "radix_ipf.h" -#endif #ifndef __osf__ # include <net/route.h> #endif @@ -42,7 +39,7 @@ * (4 bytes) */ int resolve(host, address) -char *host, *address; + char *host, *address; { struct hostent *hp; u_long add; @@ -64,7 +61,7 @@ char *host, *address; int arp(addr, eaddr) -char *addr, *eaddr; + char *addr, *eaddr; { int mib[6]; size_t needed; diff --git a/ipsend/Makefile b/ipsend/Makefile index ed3a51e453708..34485efce0d67 100644 --- a/ipsend/Makefile +++ b/ipsend/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 1993-1998 by Darren Reed. +# Copyright (C) 2012 by Darren Reed. # # See the IPFILTER.LICENCE file for details on licencing. # diff --git a/ipsend/README b/ipsend/README deleted file mode 100644 index 198556d834fba..0000000000000 --- a/ipsend/README +++ /dev/null @@ -1,8 +0,0 @@ - -This distribution contains *ONLY* the code required to build the 'ipsend' -directory of programs (including man pages) found in the IP Filter package: -http://coombs.anu.edu.au/~avalon/ip-filter.html - -Patches, bugs, etc, please send to: - -darrenr@pobox.com diff --git a/ipsend/arp.c b/ipsend/arp.c index d5497ef2599e3..7cadf6178b583 100644 --- a/ipsend/arp.c +++ b/ipsend/arp.c @@ -5,7 +5,7 @@ */ #if !defined(lint) static const char sccsid[] = "@(#)arp.c 1.4 1/11/96 (C)1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: arp.c,v 2.8.2.2 2007/02/17 12:41:50 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #include <sys/types.h> #include <sys/socket.h> @@ -15,9 +15,6 @@ static const char rcsid[] = "@(#)$Id: arp.c,v 2.8.2.2 2007/02/17 12:41:50 darren #include <sys/ioctl.h> #include <netinet/in_systm.h> #include <netinet/in.h> -#ifdef __osf__ -# include "radix_ipf_local.h" -#endif #include <net/if.h> #include <netinet/if_ether.h> #ifndef ultrix @@ -40,7 +37,7 @@ static const char rcsid[] = "@(#)$Id: arp.c,v 2.8.2.2 2007/02/17 12:41:50 darren * (4 bytes) */ int resolve(host, address) -char *host, *address; + char *host, *address; { struct hostent *hp; u_long add; @@ -66,8 +63,8 @@ char *host, *address; * some BSD program, I cant remember which. */ int arp(ip, ether) -char *ip; -char *ether; + char *ip; + char *ether; { static int sfd = -1; static char ethersave[6], ipsave[4]; diff --git a/ipsend/dlcommon.c b/ipsend/dlcommon.c index 89941388a618f..04067d0c6e5cc 100644 --- a/ipsend/dlcommon.c +++ b/ipsend/dlcommon.c @@ -30,18 +30,18 @@ typedef unsigned long ulong; #define CASERET(s) case s: return ("s") -char *dlprim(); -char *dlstate(); -char *dlerrno(); -char *dlpromisclevel(); -char *dlservicemode(); -char *dlstyle(); -char *dlmactype(); + char *dlprim(); + char *dlstate(); + char *dlerrno(); + char *dlpromisclevel(); + char *dlservicemode(); + char *dlstyle(); + char *dlmactype(); void dlinforeq(fd) -int fd; + int fd; { dl_info_req_t info_req; struct strbuf ctl; @@ -61,8 +61,8 @@ int fd; void dlinfoack(fd, bufp) -int fd; -char *bufp; + int fd; + char *bufp; { union DL_primitives *dlp; struct strbuf ctl; @@ -90,8 +90,8 @@ char *bufp; void dlattachreq(fd, ppa) -int fd; -u_long ppa; + int fd; + u_long ppa; { dl_attach_req_t attach_req; struct strbuf ctl; @@ -112,9 +112,9 @@ u_long ppa; void dlenabmultireq(fd, addr, length) -int fd; -char *addr; -int length; + int fd; + char *addr; + int length; { long buf[MAXDLBUF]; union DL_primitives *dlp; @@ -141,9 +141,9 @@ int length; void dldisabmultireq(fd, addr, length) -int fd; -char *addr; -int length; + int fd; + char *addr; + int length; { long buf[MAXDLBUF]; union DL_primitives *dlp; @@ -170,8 +170,8 @@ int length; void dlpromisconreq(fd, level) -int fd; -u_long level; + int fd; + u_long level; { dl_promiscon_req_t promiscon_req; struct strbuf ctl; @@ -193,8 +193,8 @@ u_long level; void dlpromiscoff(fd, level) -int fd; -u_long level; + int fd; + u_long level; { dl_promiscoff_req_t promiscoff_req; struct strbuf ctl; @@ -215,8 +215,8 @@ u_long level; void dlphysaddrreq(fd, addrtype) -int fd; -u_long addrtype; + int fd; + u_long addrtype; { dl_phys_addr_req_t phys_addr_req; struct strbuf ctl; @@ -237,9 +237,9 @@ u_long addrtype; void dlsetphysaddrreq(fd, addr, length) -int fd; -char *addr; -int length; + int fd; + char *addr; + int length; { long buf[MAXDLBUF]; union DL_primitives *dlp; @@ -266,7 +266,7 @@ int length; void dldetachreq(fd) -int fd; + int fd; { dl_detach_req_t detach_req; struct strbuf ctl; @@ -286,12 +286,12 @@ int fd; void dlbindreq(fd, sap, max_conind, service_mode, conn_mgmt, xidtest) -int fd; -u_long sap; -u_long max_conind; -u_long service_mode; -u_long conn_mgmt; -u_long xidtest; + int fd; + u_long sap; + u_long max_conind; + u_long service_mode; + u_long conn_mgmt; + u_long xidtest; { dl_bind_req_t bind_req; struct strbuf ctl; @@ -316,12 +316,12 @@ u_long xidtest; void dlunitdatareq(fd, addrp, addrlen, minpri, maxpri, datap, datalen) -int fd; -u_char *addrp; -int addrlen; -u_long minpri, maxpri; -u_char *datap; -int datalen; + int fd; + u_char *addrp; + int addrlen; + u_long minpri, maxpri; + u_char *datap; + int datalen; { long buf[MAXDLBUF]; union DL_primitives *dlp; @@ -351,7 +351,7 @@ int datalen; void dlunbindreq(fd) -int fd; + int fd; { dl_unbind_req_t unbind_req; struct strbuf ctl; @@ -371,8 +371,8 @@ int fd; void dlokack(fd, bufp) -int fd; -char *bufp; + int fd; + char *bufp; { union DL_primitives *dlp; struct strbuf ctl; @@ -400,8 +400,8 @@ char *bufp; void dlerrorack(fd, bufp) -int fd; -char *bufp; + int fd; + char *bufp; { union DL_primitives *dlp; struct strbuf ctl; @@ -429,8 +429,8 @@ char *bufp; void dlbindack(fd, bufp) -int fd; -char *bufp; + int fd; + char *bufp; { union DL_primitives *dlp; struct strbuf ctl; @@ -455,8 +455,8 @@ char *bufp; void dlphysaddrack(fd, bufp) -int fd; -char *bufp; + int fd; + char *bufp; { union DL_primitives *dlp; struct strbuf ctl; @@ -486,10 +486,10 @@ sigalrm() } strgetmsg(fd, ctlp, datap, flagsp, caller) -int fd; -struct strbuf *ctlp, *datap; -int *flagsp; -char *caller; + int fd; + struct strbuf *ctlp, *datap; + int *flagsp; + char *caller; { int rc; static char errmsg[80]; @@ -538,8 +538,8 @@ char *caller; } expecting(prim, dlp) -int prim; -union DL_primitives *dlp; + int prim; + union DL_primitives *dlp; { if (dlp->dl_primitive != (u_long)prim) { printdlprim(dlp); @@ -553,7 +553,7 @@ union DL_primitives *dlp; * Print any DLPI msg in human readable format. */ printdlprim(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { switch (dlp->dl_primitive) { case DL_INFO_REQ: @@ -657,13 +657,13 @@ union DL_primitives *dlp; /* ARGSUSED */ printdlinforeq(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { (void) printf("DL_INFO_REQ\n"); } printdlinfoack(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { u_char addr[MAXDLADDR]; u_char brdcst[MAXDLADDR]; @@ -700,21 +700,21 @@ union DL_primitives *dlp; } printdlattachreq(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { (void) printf("DL_ATTACH_REQ: ppa %d\n", dlp->attach_req.dl_ppa); } printdlokack(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { (void) printf("DL_OK_ACK: correct_primitive %s\n", dlprim(dlp->ok_ack.dl_correct_primitive)); } printdlerrorack(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { (void) printf("DL_ERROR_ACK: error_primitive %s errno %s unix_errno %d: %s\n", dlprim(dlp->error_ack.dl_error_primitive), @@ -724,7 +724,7 @@ union DL_primitives *dlp; } printdlenabmultireq(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { u_char addr[MAXDLADDR]; @@ -738,7 +738,7 @@ union DL_primitives *dlp; } printdldisabmultireq(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { u_char addr[MAXDLADDR]; @@ -752,28 +752,28 @@ union DL_primitives *dlp; } printdlpromisconreq(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { (void) printf("DL_PROMISCON_REQ: level %s\n", dlpromisclevel(dlp->promiscon_req.dl_level)); } printdlpromiscoffreq(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { (void) printf("DL_PROMISCOFF_REQ: level %s\n", dlpromisclevel(dlp->promiscoff_req.dl_level)); } printdlphysaddrreq(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { (void) printf("DL_PHYS_ADDR_REQ: addr_type 0x%x\n", dlp->physaddr_req.dl_addr_type); } printdlphysaddrack(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { u_char addr[MAXDLADDR]; @@ -787,7 +787,7 @@ union DL_primitives *dlp; } printdlsetphysaddrreq(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { u_char addr[MAXDLADDR]; @@ -802,13 +802,13 @@ union DL_primitives *dlp; /* ARGSUSED */ printdldetachreq(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { (void) printf("DL_DETACH_REQ\n"); } printdlbindreq(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { (void) printf("DL_BIND_REQ: sap %d max_conind %d\n", dlp->bind_req.dl_sap, @@ -820,7 +820,7 @@ union DL_primitives *dlp; } printdlbindack(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { u_char addr[MAXDLADDR]; @@ -839,13 +839,13 @@ union DL_primitives *dlp; /* ARGSUSED */ printdlunbindreq(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { (void) printf("DL_UNBIND_REQ\n"); } printdlsubsbindreq(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { u_char sap[MAXDLADDR]; @@ -859,7 +859,7 @@ union DL_primitives *dlp; } printdlsubsbindack(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { u_char sap[MAXDLADDR]; @@ -873,7 +873,7 @@ union DL_primitives *dlp; } printdlsubsunbindreq(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { u_char sap[MAXDLADDR]; @@ -887,7 +887,7 @@ union DL_primitives *dlp; } printdlunitdatareq(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { u_char addr[MAXDLADDR]; @@ -904,7 +904,7 @@ union DL_primitives *dlp; } printdlunitdataind(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { u_char dest[MAXDLADDR]; u_char src[MAXDLADDR]; @@ -927,7 +927,7 @@ union DL_primitives *dlp; } printdluderrorind(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { u_char addr[MAXDLADDR]; @@ -944,7 +944,7 @@ union DL_primitives *dlp; } printdltestreq(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { u_char addr[MAXDLADDR]; @@ -959,7 +959,7 @@ union DL_primitives *dlp; } printdltestind(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { u_char dest[MAXDLADDR]; u_char src[MAXDLADDR]; @@ -981,7 +981,7 @@ union DL_primitives *dlp; } printdltestres(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { u_char dest[MAXDLADDR]; @@ -996,7 +996,7 @@ union DL_primitives *dlp; } printdltestcon(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { u_char dest[MAXDLADDR]; u_char src[MAXDLADDR]; @@ -1018,7 +1018,7 @@ union DL_primitives *dlp; } printdlxidreq(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { u_char dest[MAXDLADDR]; @@ -1033,7 +1033,7 @@ union DL_primitives *dlp; } printdlxidind(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { u_char dest[MAXDLADDR]; u_char src[MAXDLADDR]; @@ -1055,7 +1055,7 @@ union DL_primitives *dlp; } printdlxidres(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { u_char dest[MAXDLADDR]; @@ -1070,7 +1070,7 @@ union DL_primitives *dlp; } printdlxidcon(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { u_char dest[MAXDLADDR]; u_char src[MAXDLADDR]; @@ -1092,7 +1092,7 @@ union DL_primitives *dlp; } printdludqosreq(dlp) -union DL_primitives *dlp; + union DL_primitives *dlp; { (void) printf("DL_UDQOS_REQ: qos_length %d qos_offset %d\n", dlp->udqos_req.dl_qos_length, @@ -1103,9 +1103,9 @@ union DL_primitives *dlp; * Return string. */ addrtostring(addr, length, s) -u_char *addr; -u_long length; -u_char *s; + u_char *addr; + u_long length; + u_char *s; { int i; @@ -1121,8 +1121,8 @@ u_char *s; * Return length */ stringtoaddr(sp, addr) -char *sp; -char *addr; + char *sp; + char *addr; { int n = 0; char *p; @@ -1138,14 +1138,14 @@ char *addr; n++; p = NULL; } - + return (n); } static char hexnibble(c) -char c; + char c; { static char hextab[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', @@ -1157,7 +1157,7 @@ char c; char* dlprim(prim) -u_long prim; + u_long prim; { static char primbuf[80]; @@ -1198,7 +1198,7 @@ u_long prim; char* dlstate(state) -u_long state; + u_long state; { static char statebuf[80]; @@ -1232,7 +1232,7 @@ u_long state; char* dlerrno(errno) -u_long errno; + u_long errno; { static char errnobuf[80]; @@ -1274,7 +1274,7 @@ u_long errno; char* dlpromisclevel(level) -u_long level; + u_long level; { static char levelbuf[80]; @@ -1290,7 +1290,7 @@ u_long level; char* dlservicemode(servicemode) -u_long servicemode; + u_long servicemode; { static char servicemodebuf[80]; @@ -1307,7 +1307,7 @@ u_long servicemode; char* dlstyle(style) -long style; + long style; { static char stylebuf[80]; @@ -1322,7 +1322,7 @@ long style; char* dlmactype(media) -u_long media; + u_long media; { static char mediabuf[80]; @@ -1343,8 +1343,8 @@ u_long media; /*VARARGS1*/ err(fmt, a1, a2, a3, a4) -char *fmt; -char *a1, *a2, *a3, *a4; + char *fmt; + char *a1, *a2, *a3, *a4; { (void) fprintf(stderr, fmt, a1, a2, a3, a4); (void) fprintf(stderr, "\n"); @@ -1352,18 +1352,18 @@ char *a1, *a2, *a3, *a4; } syserr(s) -char *s; + char *s; { (void) perror(s); exit(1); } strioctl(fd, cmd, timout, len, dp) -int fd; -int cmd; -int timout; -int len; -char *dp; + int fd; + int cmd; + int timout; + int len; + char *dp; { struct strioctl sioc; int rc; diff --git a/ipsend/hpux.c b/ipsend/hpux.c deleted file mode 100644 index 42078e3b7f545..0000000000000 --- a/ipsend/hpux.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * (C)opyright 1997-1998 Darren Reed. (from tcplog) - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - */ -#include <stdio.h> -#include <strings.h> -#include <unistd.h> -#include <stdlib.h> -#include <sys/types.h> -#include <sys/param.h> -#include <sys/socket.h> -#include <sys/file.h> -#include <sys/ioctl.h> - - -int initdevice(device, sport, tout) -char *device; -int sport, tout; -{ - int fd; - - if ((fd = socket(AF_DLI, SOCK_RAW, 0)) == -1) - perror("socket"); - return fd; -} - - -/* - * output an IP packet onto a fd opened for /dev/bpf - */ -int sendip(fd, pkt, len) -int fd, len; -char *pkt; -{ - if (send(fd, pkt, len, 0) == -1) - { - perror("send"); - return -1; - } - - return len; -} - - -char *strdup(str) -char *str; -{ - char *s; - - if ((s = (char *)malloc(strlen(str) + 1))) - return strcpy(s, str); - return NULL; -} -/* - * (C)opyright 1997 Darren Reed. (from tcplog) - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - */ -#include <stdio.h> -#include <strings.h> -#include <unistd.h> -#include <stdlib.h> -#include <sys/types.h> -#include <sys/param.h> -#include <sys/socket.h> -#include <sys/file.h> -#include <sys/ioctl.h> - - -int initdevice(device, sport, tout) -char *device; -int sport, tout; -{ - int fd; - - if ((fd = socket(AF_DLI, SOCK_RAW, 0)) == -1) - perror("socket"); - return fd; -} - - -/* - * output an IP packet onto a fd opened for /dev/bpf - */ -int sendip(fd, pkt, len) -int fd, len; -char *pkt; -{ - if (send(fd, pkt, len, 0) == -1) - { - perror("send"); - return -1; - } - - return len; -} - - -char *strdup(str) -char *str; -{ - char *s; - - if ((s = (char *)malloc(strlen(str) + 1))) - return strcpy(s, str); - return NULL; -} diff --git a/ipsend/in_var.h b/ipsend/in_var.h deleted file mode 100644 index 2ebd731a4892d..0000000000000 --- a/ipsend/in_var.h +++ /dev/null @@ -1,177 +0,0 @@ -/* @(#)in_var.h 1.3 88/08/19 SMI; from UCB 7.1 6/5/86 */ - -/* - * Copyright (c) 1985, 1986 Regents of the University of California. - * All rights reserved. The Berkeley software License Agreement - * specifies the terms and conditions for redistribution. - */ - -/* - * Interface address, Internet version. One of these structures - * is allocated for each interface with an Internet address. - * The ifaddr structure contains the protocol-independent part - * of the structure and is assumed to be first. - */ - -#ifndef _netinet_in_var_h -#define _netinet_in_var_h - -struct in_ifaddr { - struct ifaddr ia_ifa; /* protocol-independent info */ -#define ia_addr ia_ifa.ifa_addr -#define ia_broadaddr ia_ifa.ifa_broadaddr -#define ia_dstaddr ia_ifa.ifa_dstaddr -#define ia_ifp ia_ifa.ifa_ifp - u_long ia_net; /* network number of interface */ - u_long ia_netmask; /* mask of net part */ - u_long ia_subnet; /* subnet number, including net */ - u_long ia_subnetmask; /* mask of net + subnet */ - struct in_addr ia_netbroadcast; /* broadcast addr for (logical) net */ - int ia_flags; - struct in_ifaddr *ia_next; /* next in list of internet addresses */ - struct in_multi *ia_multiaddrs;/* list of multicast addresses */ -}; -/* - * Given a pointer to an in_ifaddr (ifaddr), - * return a pointer to the addr as a sockadd_in. - */ -#define IA_SIN(ia) ((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_addr)) -/* - * ia_flags - */ -#define IFA_ROUTE 0x01 /* routing entry installed */ - -#ifdef KERNEL -struct in_ifaddr *in_ifaddr; -struct in_ifaddr *in_iaonnetof(); -struct ifqueue ipintrq; /* ip packet input queue */ -#endif - -#ifdef KERNEL -/* - * Macro for finding the interface (ifnet structure) corresponding to one - * of our IP addresses. - */ -#define INADDR_TO_IFP(addr, ifp) \ - /* struct in_addr addr; */ \ - /* struct ifnet *ifp; */ \ -{ \ - register struct in_ifaddr *ia; \ - \ - for (ia = in_ifaddr; \ - ia != NULL && IA_SIN(ia)->sin_addr.s_addr != (addr).s_addr; \ - ia = ia->ia_next); \ - (ifp) = (ia == NULL) ? NULL : ia->ia_ifp; \ -} - -/* - * Macro for finding the internet address structure (in_ifaddr) corresponding - * to a given interface (ifnet structure). - */ -#define IFP_TO_IA(ifp, ia) \ - /* struct ifnet *ifp; */ \ - /* struct in_ifaddr *ia; */ \ -{ \ - for ((ia) = in_ifaddr; \ - (ia) != NULL && (ia)->ia_ifp != (ifp); \ - (ia) = (ia)->ia_next); \ -} -#endif /* KERNEL */ - -/* - * Per-interface router version information is kept in this list. - * This information should be part of the ifnet structure but we don't wish - * to change that - as it might break a number of things - */ - -struct router_info { - struct ifnet *ifp; - int type; /* type of router which is querier on this interface */ - int time; /* # of slow timeouts since last old query */ - struct router_info *next; -}; - -/* - * Internet multicast address structure. There is one of these for each IP - * multicast group to which this host belongs on a given network interface. - * They are kept in a linked list, rooted in the interface's in_ifaddr - * structure. - */ - -struct in_multi { - struct in_addr inm_addr; /* IP multicast address */ - struct ifnet *inm_ifp; /* back pointer to ifnet */ - struct in_ifaddr *inm_ia; /* back pointer to in_ifaddr */ - u_int inm_refcount;/* no. membership claims by sockets */ - u_int inm_timer; /* IGMP membership report timer */ - struct in_multi *inm_next; /* ptr to next multicast address */ - u_int inm_state; /* state of the membership */ - struct router_info *inm_rti; /* router info*/ -}; - -#ifdef KERNEL -/* - * Structure used by macros below to remember position when stepping through - * all of the in_multi records. - */ -struct in_multistep { - struct in_ifaddr *i_ia; - struct in_multi *i_inm; -}; - -/* - * Macro for looking up the in_multi record for a given IP multicast address - * on a given interface. If no matching record is found, "inm" returns NULL. - */ -#define IN_LOOKUP_MULTI(addr, ifp, inm) \ - /* struct in_addr addr; */ \ - /* struct ifnet *ifp; */ \ - /* struct in_multi *inm; */ \ -{ \ - register struct in_ifaddr *ia; \ - \ - IFP_TO_IA((ifp), ia); \ - if (ia == NULL) \ - (inm) = NULL; \ - else \ - for ((inm) = ia->ia_multiaddrs; \ - (inm) != NULL && (inm)->inm_addr.s_addr != (addr).s_addr; \ - (inm) = inm->inm_next); \ -} - -/* - * Macro to step through all of the in_multi records, one at a time. - * The current position is remembered in "step", which the caller must - * provide. IN_FIRST_MULTI(), below, must be called to initialize "step" - * and get the first record. Both macros return a NULL "inm" when there - * are no remaining records. - */ -#define IN_NEXT_MULTI(step, inm) \ - /* struct in_multistep step; */ \ - /* struct in_multi *inm; */ \ -{ \ - if (((inm) = (step).i_inm) != NULL) { \ - (step).i_inm = (inm)->inm_next; \ - } \ - else while ((step).i_ia != NULL) { \ - (inm) = (step).i_ia->ia_multiaddrs; \ - (step).i_ia = (step).i_ia->ia_next; \ - if ((inm) != NULL) { \ - (step).i_inm = (inm)->inm_next; \ - break; \ - } \ - } \ -} - -#define IN_FIRST_MULTI(step, inm) \ - /* struct in_multistep step; */ \ - /* struct in_multi *inm; */ \ -{ \ - (step).i_ia = in_ifaddr; \ - (step).i_inm = NULL; \ - IN_NEXT_MULTI((step), (inm)); \ -} - -struct in_multi *in_addmulti(); -#endif /* KERNEL */ -#endif /*!_netinet_in_var_h*/ diff --git a/ipsend/ip.c b/ipsend/ip.c index e29f722536503..46387e5eee127 100644 --- a/ipsend/ip.c +++ b/ipsend/ip.c @@ -5,20 +5,18 @@ */ #if !defined(lint) static const char sccsid[] = "%W% %G% (C)1995"; -static const char rcsid[] = "@(#)$Id: ip.c,v 2.8.2.2 2007/02/17 12:41:51 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #include <sys/param.h> #include <sys/types.h> #include <netinet/in_systm.h> #include <sys/socket.h> -#ifdef __osf__ -# include "radix_ipf_local.h" -#endif #include <net/if.h> #include <netinet/in.h> #include <netinet/ip.h> #include <sys/param.h> #ifndef linux +# include <net/route.h> # include <netinet/if_ether.h> # include <netinet/ip_var.h> # if __FreeBSD_version >= 300000 @@ -37,8 +35,8 @@ static char *ipbuf = NULL, *ethbuf = NULL; u_short chksum(buf,len) -u_short *buf; -int len; + u_short *buf; + int len; { u_long sum = 0; int nwords = len >> 1; @@ -52,9 +50,9 @@ int len; int send_ether(nfd, buf, len, gwip) -int nfd, len; -char *buf; -struct in_addr gwip; + int nfd, len; + char *buf; + struct in_addr gwip; { static struct in_addr last_gw; static char last_arp[6] = { 0, 0, 0, 0, 0, 0}; @@ -87,10 +85,10 @@ struct in_addr gwip; /* */ int send_ip(nfd, mtu, ip, gwip, frag) -int nfd, mtu; -ip_t *ip; -struct in_addr gwip; -int frag; + int nfd, mtu; + ip_t *ip; + struct in_addr gwip; + int frag; { static struct in_addr last_gw, local_ip; static char local_arp[6] = { 0, 0, 0, 0, 0, 0}; @@ -248,9 +246,9 @@ int frag; * send a tcp packet. */ int send_tcp(nfd, mtu, ip, gwip) -int nfd, mtu; -ip_t *ip; -struct in_addr gwip; + int nfd, mtu; + ip_t *ip; + struct in_addr gwip; { static tcp_seq iss = 2; tcphdr_t *t, *t2; @@ -301,9 +299,9 @@ struct in_addr gwip; * send a udp packet. */ int send_udp(nfd, mtu, ip, gwip) -int nfd, mtu; -ip_t *ip; -struct in_addr gwip; + int nfd, mtu; + ip_t *ip; + struct in_addr gwip; { struct tcpiphdr *ti; int thlen; @@ -333,9 +331,9 @@ struct in_addr gwip; * send an icmp packet. */ int send_icmp(nfd, mtu, ip, gwip) -int nfd, mtu; -ip_t *ip; -struct in_addr gwip; + int nfd, mtu; + ip_t *ip; + struct in_addr gwip; { struct icmp *ic; @@ -349,9 +347,9 @@ struct in_addr gwip; int send_packet(nfd, mtu, ip, gwip) -int nfd, mtu; -ip_t *ip; -struct in_addr gwip; + int nfd, mtu; + ip_t *ip; + struct in_addr gwip; { switch (ip->ip_p) { diff --git a/ipsend/ip_compat.h b/ipsend/ip_compat.h deleted file mode 100644 index c38fa59ed3c71..0000000000000 --- a/ipsend/ip_compat.h +++ /dev/null @@ -1,242 +0,0 @@ -/* - * (C)opyright 1995 by Darren Reed. - * - * This code may be freely distributed as long as it retains this notice - * and is not changed in any way. The author accepts no responsibility - * for the use of this software. I hate legaleese, don't you ? - * - * @(#)ip_compat.h 1.2 12/7/95 - */ - -/* - * These #ifdef's are here mainly for linux, but who knows, they may - * not be in other places or maybe one day linux will grow up and some - * of these will turn up there too. - */ -#ifndef ICMP_UNREACH -# define ICMP_UNREACH ICMP_DEST_UNREACH -#endif -#ifndef ICMP_SOURCEQUENCH -# define ICMP_SOURCEQUENCH ICMP_SOURCE_QUENCH -#endif -#ifndef ICMP_TIMXCEED -# define ICMP_TIMXCEED ICMP_TIME_EXCEEDED -#endif -#ifndef ICMP_PARAMPROB -# define ICMP_PARAMPROB ICMP_PARAMETERPROB -#endif -#ifndef IPVERSION -# define IPVERSION 4 -#endif -#ifndef IPOPT_MINOFF -# define IPOPT_MINOFF 4 -#endif -#ifndef IPOPT_COPIED -# define IPOPT_COPIED(x) ((x)&0x80) -#endif -#ifndef IPOPT_EOL -# define IPOPT_EOL 0 -#endif -#ifndef IPOPT_NOP -# define IPOPT_NOP 1 -#endif -#ifndef IP_MF -# define IP_MF ((u_short)0x2000) -#endif -#ifndef ETHERTYPE_IP -# define ETHERTYPE_IP ((u_short)0x0800) -#endif -#ifndef TH_FIN -# define TH_FIN 0x01 -#endif -#ifndef TH_SYN -# define TH_SYN 0x02 -#endif -#ifndef TH_RST -# define TH_RST 0x04 -#endif -#ifndef TH_PUSH -# define TH_PUSH 0x08 -#endif -#ifndef TH_ACK -# define TH_ACK 0x10 -#endif -#ifndef TH_URG -# define TH_URG 0x20 -#endif -#ifndef IPOPT_EOL -# define IPOPT_EOL 0 -#endif -#ifndef IPOPT_NOP -# define IPOPT_NOP 1 -#endif -#ifndef IPOPT_RR -# define IPOPT_RR 7 -#endif -#ifndef IPOPT_TS -# define IPOPT_TS 68 -#endif -#ifndef IPOPT_SECURITY -# define IPOPT_SECURITY 130 -#endif -#ifndef IPOPT_LSRR -# define IPOPT_LSRR 131 -#endif -#ifndef IPOPT_SATID -# define IPOPT_SATID 136 -#endif -#ifndef IPOPT_SSRR -# define IPOPT_SSRR 137 -#endif -#ifndef IPOPT_SECUR_UNCLASS -# define IPOPT_SECUR_UNCLASS ((u_short)0x0000) -#endif -#ifndef IPOPT_SECUR_CONFID -# define IPOPT_SECUR_CONFID ((u_short)0xf135) -#endif -#ifndef IPOPT_SECUR_EFTO -# define IPOPT_SECUR_EFTO ((u_short)0x789a) -#endif -#ifndef IPOPT_SECUR_MMMM -# define IPOPT_SECUR_MMMM ((u_short)0xbc4d) -#endif -#ifndef IPOPT_SECUR_RESTR -# define IPOPT_SECUR_RESTR ((u_short)0xaf13) -#endif -#ifndef IPOPT_SECUR_SECRET -# define IPOPT_SECUR_SECRET ((u_short)0xd788) -#endif -#ifndef IPOPT_SECUR_TOPSECRET -# define IPOPT_SECUR_TOPSECRET ((u_short)0x6bc5) -#endif - -#ifdef linux -# if LINUX < 0200 -# define icmp icmphdr -# define icmp_type type -# define icmp_code code -# endif - -/* - * From /usr/include/netinet/ip_var.h - * !%@#!$@# linux... - */ -struct ipovly { - caddr_t ih_next, ih_prev; /* for protocol sequence q's */ - u_char ih_x1; /* (unused) */ - u_char ih_pr; /* protocol */ - short ih_len; /* protocol length */ - struct in_addr ih_src; /* source internet address */ - struct in_addr ih_dst; /* destination internet address */ -}; - -typedef struct { - __u16 th_sport; - __u16 th_dport; - __u32 th_seq; - __u32 th_ack; -# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\ - defined(vax) - __u8 th_res:4; - __u8 th_off:4; -#else - __u8 th_off:4; - __u8 th_res:4; -#endif - __u8 th_flags; - __u16 th_win; - __u16 th_sum; - __u16 th_urp; -} tcphdr_t; - -typedef struct { - __u16 uh_sport; - __u16 uh_dport; - __s16 uh_ulen; - __u16 uh_sum; -} udphdr_t; - -typedef struct { -# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\ - defined(vax) - __u8 ip_hl:4; - __u8 ip_v:4; -# else - __u8 ip_hl:4; - __u8 ip_v:4; -# endif - __u8 ip_tos; - __u16 ip_len; - __u16 ip_id; - __u16 ip_off; - __u8 ip_ttl; - __u8 ip_p; - __u16 ip_sum; - struct in_addr ip_src; - struct in_addr ip_dst; -} ip_t; - -typedef struct { - __u8 ether_dhost[6]; - __u8 ether_shost[6]; - __u16 ether_type; -} ether_header_t; - -typedef struct icmp { - u_char icmp_type; /* type of message, see below */ - u_char icmp_code; /* type sub code */ - u_short icmp_cksum; /* ones complement cksum of struct */ - union { - u_char ih_pptr; /* ICMP_PARAMPROB */ - struct in_addr ih_gwaddr; /* ICMP_REDIRECT */ - struct ih_idseq { - n_short icd_id; - n_short icd_seq; - } ih_idseq; - int ih_void; - } icmp_hun; -#define icmp_pptr icmp_hun.ih_pptr -#define icmp_gwaddr icmp_hun.ih_gwaddr -#define icmp_id icmp_hun.ih_idseq.icd_id -#define icmp_seq icmp_hun.ih_idseq.icd_seq -#define icmp_void icmp_hun.ih_void - union { - struct id_ts { - n_time its_otime; - n_time its_rtime; - n_time its_ttime; - } id_ts; - struct id_ip { - ip_t idi_ip; - /* options and then 64 bits of data */ - } id_ip; - u_long id_mask; - char id_data[1]; - } icmp_dun; -#define icmp_otime icmp_dun.id_ts.its_otime -#define icmp_rtime icmp_dun.id_ts.its_rtime -#define icmp_ttime icmp_dun.id_ts.its_ttime -#define icmp_ip icmp_dun.id_ip.idi_ip -#define icmp_mask icmp_dun.id_mask -#define icmp_data icmp_dun.id_data -} icmphdr_t; - -# define bcopy(a,b,c) memmove(b,a,c) -# define bcmp(a,b,c) memcmp(a,b,c) - -# define ifnet device - -#else - -typedef struct udphdr udphdr_t; -typedef struct tcphdr tcphdr_t; -typedef struct ip ip_t; -typedef struct ether_header ether_header_t; - -#endif - -#if defined(__SVR4) || defined(__svr4__) -# define bcopy(a,b,c) memmove(b,a,c) -# define bcmp(a,b,c) memcmp(a,b,c) -# define bzero(a,b) memset(a,0,b) -#endif diff --git a/ipsend/ip_var.h b/ipsend/ip_var.h deleted file mode 100644 index 92eb38a0befc5..0000000000000 --- a/ipsend/ip_var.h +++ /dev/null @@ -1,123 +0,0 @@ -/* @(#)ip_var.h 1.11 88/08/19 SMI; from UCB 7.1 6/5/86 */ - -/* - * Copyright (c) 1982, 1986 Regents of the University of California. - * All rights reserved. The Berkeley software License Agreement - * specifies the terms and conditions for redistribution. - */ - -/* - * Overlay for ip header used by other protocols (tcp, udp). - */ - -#ifndef _netinet_ip_var_h -#define _netinet_ip_var_h - -struct ipovly { - caddr_t ih_next, ih_prev; /* for protocol sequence q's */ - u_char ih_x1; /* (unused) */ - u_char ih_pr; /* protocol */ - short ih_len; /* protocol length */ - struct in_addr ih_src; /* source internet address */ - struct in_addr ih_dst; /* destination internet address */ -}; - -/* - * Ip reassembly queue structure. Each fragment - * being reassembled is attached to one of these structures. - * They are timed out after ipq_ttl drops to 0, and may also - * be reclaimed if memory becomes tight. - */ -struct ipq { - struct ipq *next,*prev; /* to other reass headers */ - u_char ipq_ttl; /* time for reass q to live */ - u_char ipq_p; /* protocol of this fragment */ - u_short ipq_id; /* sequence id for reassembly */ - struct ipasfrag *ipq_next,*ipq_prev; - /* to ip headers of fragments */ - struct in_addr ipq_src,ipq_dst; -}; - -/* - * Ip header, when holding a fragment. - * - * Note: ipf_next must be at same offset as ipq_next above - */ -struct ipasfrag { -#if defined(vax) || defined(i386) - u_char ip_hl:4, - ip_v:4; -#endif -#if defined(mc68000) || defined(sparc) - u_char ip_v:4, - ip_hl:4; -#endif - u_char ipf_mff; /* copied from (ip_off&IP_MF) */ - short ip_len; - u_short ip_id; - short ip_off; - u_char ip_ttl; - u_char ip_p; - u_short ip_sum; - struct ipasfrag *ipf_next; /* next fragment */ - struct ipasfrag *ipf_prev; /* previous fragment */ -}; - -/* - * Structure stored in mbuf in inpcb.ip_options - * and passed to ip_output when ip options are in use. - * The actual length of the options (including ipopt_dst) - * is in m_len. - */ -#define MAX_IPOPTLEN 40 - -struct ipoption { - struct in_addr ipopt_dst; /* first-hop dst if source routed */ - char ipopt_list[MAX_IPOPTLEN]; /* options proper */ -}; - -/* - * Structure stored in an mbuf attached to inpcb.ip_moptions and - * passed to ip_output when IP multicast options are in use. - */ -struct ip_moptions { - struct ifnet *imo_multicast_ifp; /* ifp for outgoing multicasts */ - u_char imo_multicast_ttl; /* TTL for outgoing multicasts */ - u_char imo_multicast_loop; /* 1 => hear sends if a member */ - u_short imo_num_memberships;/* no. memberships this socket */ - struct in_multi *imo_membership[IP_MAX_MEMBERSHIPS]; -#ifdef RSVP_ISI - long imo_multicast_vif; /* vif for outgoing multicasts */ -#endif /* RSVP_ISI */ -}; - -struct ipstat { - long ips_total; /* total packets received */ - long ips_badsum; /* checksum bad */ - long ips_tooshort; /* packet too short */ - long ips_toosmall; /* not enough data */ - long ips_badhlen; /* ip header length < data size */ - long ips_badlen; /* ip length < ip header length */ - long ips_fragments; /* fragments received */ - long ips_fragdropped; /* frags dropped (dups, out of space) */ - long ips_fragtimeout; /* fragments timed out */ - long ips_forward; /* packets forwarded */ - long ips_cantforward; /* packets rcvd for unreachable dest */ - long ips_redirectsent; /* packets forwarded on same net */ -}; - -#ifdef KERNEL -/* flags passed to ip_output as last parameter */ -#define IP_FORWARDING 0x1 /* most of ip header exists */ -#define IP_MULTICASTOPTS 0x2 /* multicast opts present */ -#define IP_ROUTETOIF SO_DONTROUTE /* bypass routing tables */ -#define IP_ALLOWBROADCAST SO_BROADCAST /* can send broadcast packets */ - -struct ipstat ipstat; -struct ipq ipq; /* ip reass. queue */ -u_short ip_id; /* ip packet ctr, for ids */ - -struct mbuf *ip_srcroute(); -#endif - -#endif /*!_netinet_ip_var_h*/ diff --git a/ipsend/ipresend.c b/ipsend/ipresend.c index 7e52fe959f519..22cfbccfa2b26 100644 --- a/ipsend/ipresend.c +++ b/ipsend/ipresend.c @@ -6,7 +6,7 @@ */ #if !defined(lint) static const char sccsid[] = "%W% %G% (C)1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipresend.c,v 2.4 2004/01/08 13:34:31 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #include <sys/param.h> #include <sys/types.h> @@ -30,7 +30,7 @@ static const char rcsid[] = "@(#)$Id: ipresend.c,v 2.4 2004/01/08 13:34:31 darre extern char *optarg; extern int optind; #ifndef NO_IPF -extern struct ipread snoop, pcap, etherf, iphex, tcpd, iptext; +extern struct ipread pcap, iphex, iptext; #endif int opts = 0; @@ -66,7 +66,7 @@ int main __P((int, char **)); static void usage(prog) -char *prog; + char *prog; { fprintf(stderr, "Usage: %s [options] <-r filename|-R filename>\n\ \t\t-r filename\tsnoop data file to resend\n\ @@ -81,8 +81,8 @@ char *prog; int main(argc, argv) -int argc; -char **argv; + int argc; + char **argv; { struct in_addr gwip; struct ipread *ipr = NULL; @@ -113,21 +113,12 @@ char **argv; opts |= OPT_RAW; break; #ifndef NO_IPF - case 'E' : - ipr = ðerf; - break; case 'H' : ipr = &iphex; break; case 'P' : ipr = &pcap; break; - case 'S' : - ipr = &snoop; - break; - case 'T' : - ipr = &tcpd; - break; case 'X' : ipr = &iptext; break; diff --git a/ipsend/ipsend.5 b/ipsend/ipsend.5 index 4c1e66af3f81d..3dfedf6cbb059 100644 --- a/ipsend/ipsend.5 +++ b/ipsend/ipsend.5 @@ -122,7 +122,7 @@ be adjusted to accommodate data or further protocol headers. sets the fragment offset field of the IP packet. Default is 0. .TP .B ttl <number> -sets the time to live (TTL) field of the IP header. Default is 60. +sets the time to live (TTL) field of the IP header. Default is 60. .TP .B proto <protocol> sets the protocol field of the IP header. The protocol can either be a diff --git a/ipsend/ipsend.c b/ipsend/ipsend.c index dcd897ccdda7f..563ceba4bf736 100644 --- a/ipsend/ipsend.c +++ b/ipsend/ipsend.c @@ -5,7 +5,7 @@ */ #if !defined(lint) static const char sccsid[] = "@(#)ipsend.c 1.5 12/10/95 (C)1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipsend.c,v 2.8.2.3 2006/03/17 13:45:34 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #include <sys/param.h> #include <sys/types.h> @@ -66,7 +66,7 @@ int main __P((int, char **)); static void usage(prog) -char *prog; + char *prog; { fprintf(stderr, "Usage: %s [options] dest [flags]\n\ \toptions:\n\ @@ -95,8 +95,8 @@ char *prog; static void do_icmp(ip, args) -ip_t *ip; -char *args; + ip_t *ip; + char *args; { struct icmp *ic; char *s; @@ -146,10 +146,10 @@ char *args; int send_packets(dev, mtu, ip, gwip) -char *dev; -int mtu; -ip_t *ip; -struct in_addr gwip; + char *dev; + int mtu; + ip_t *ip; + struct in_addr gwip; { int wfd; @@ -192,8 +192,8 @@ udpcksum(ip_t *ip, struct udphdr *udp, int len) } int main(argc, argv) -int argc; -char **argv; + int argc; + char **argv; { FILE *langfile = NULL; struct in_addr gwip; diff --git a/ipsend/ipsend.h b/ipsend/ipsend.h index f5e51a7364c22..9feff713054cb 100644 --- a/ipsend/ipsend.h +++ b/ipsend/ipsend.h @@ -27,7 +27,7 @@ #ifdef linux #include <linux/sockios.h> #endif -#include "tcpip.h" +#include "netinet/tcpip.h" #include "ipt.h" extern int resolve __P((char *, char *)); diff --git a/ipsend/ipsend.sed b/ipsend/ipsend.sed deleted file mode 100644 index 774c0e24e3df6..0000000000000 --- a/ipsend/ipsend.sed +++ /dev/null @@ -1,3 +0,0 @@ -0Æ. Ä,..+CVS0Í -.cvsignore0Î44arp.c0Ï Crashable0ÐMakefile0Ñarp.c0Ò -dlcommon.c0Ódltest.h0Ôin_var.h0Õip.c0Öip_compat.h0×ip_var.h0Ø diff --git a/ipsend/ipsopt.c b/ipsend/ipsopt.c index 9326bc63c4a2d..c827c56c33576 100644 --- a/ipsend/ipsopt.c +++ b/ipsend/ipsopt.c @@ -1,12 +1,12 @@ /* - * Copyright (C) 1995-1998 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * */ #if !defined(lint) static const char sccsid[] = "@(#)ipsopt.c 1.2 1/11/96 (C)1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipsopt.c,v 2.4.4.1 2004/03/23 12:58:05 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #include <sys/param.h> #include <sys/types.h> @@ -60,7 +60,7 @@ struct ipopt_names secnames[] = { u_short ipseclevel(slevel) -char *slevel; + char *slevel; { struct ipopt_names *so; @@ -77,10 +77,10 @@ char *slevel; int addipopt(op, io, len, class) -char *op; -struct ipopt_names *io; -int len; -char *class; + char *op; + struct ipopt_names *io; + int len; + char *class; { struct in_addr ipadr; int olen = len, srr = 0; @@ -148,8 +148,8 @@ char *class; u_32_t buildopts(cp, op, len) -char *cp, *op; -int len; + char *cp, *op; + int len; { struct ipopt_names *io; u_32_t msk = 0; diff --git a/ipsend/iptest.c b/ipsend/iptest.c index 000d1cc254e83..b0bf693405c43 100644 --- a/ipsend/iptest.c +++ b/ipsend/iptest.c @@ -6,7 +6,7 @@ */ #if !defined(lint) static const char sccsid[] = "%W% %G% (C)1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: iptest.c,v 2.6 2004/01/08 13:34:31 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #include <sys/param.h> #include <sys/types.h> @@ -61,7 +61,7 @@ int main __P((int, char **)); static void usage(prog) -char *prog; + char *prog; { fprintf(stderr, "Usage: %s [options] dest\n\ \toptions:\n\ @@ -83,8 +83,8 @@ char *prog; int main(argc, argv) -int argc; -char **argv; + int argc; + char **argv; { struct tcpiphdr *ti; struct in_addr gwip; diff --git a/ipsend/iptests.c b/ipsend/iptests.c index 56cc34b9f87dd..1ac04f577a91e 100644 --- a/ipsend/iptests.c +++ b/ipsend/iptests.c @@ -1,12 +1,12 @@ /* - * Copyright (C) 1993-1998 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * */ #if !defined(lint) static const char sccsid[] = "%W% %G% (C)1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: iptests.c,v 2.8.2.9 2007/09/13 07:19:34 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #include <sys/param.h> #include <sys/types.h> @@ -20,7 +20,7 @@ typedef int boolean_t; #endif #include <sys/time.h> #if !defined(__osf__) -# ifdef __NetBSD__ +# ifdef __NetBSD__ # include <machine/lock.h> # endif # define _KERNEL @@ -49,8 +49,9 @@ typedef int boolean_t; #endif #if defined(solaris) # include <sys/stream.h> +#else +# include <sys/socketvar.h> #endif -#include <sys/socketvar.h> #ifdef sun #include <sys/systm.h> #include <sys/session.h> @@ -65,9 +66,6 @@ typedef int boolean_t; #ifdef __hpux # define _NET_ROUTE_INCLUDED #endif -#ifdef __osf__ -# include "radix_ipf_local.h" -#endif #include <net/if.h> #if defined(linux) && (LINUX >= 0200) # include <asm/atomic.h> @@ -76,7 +74,9 @@ typedef int boolean_t; # if defined(__FreeBSD__) # include "radix_ipf.h" # endif -# include <net/route.h> +# if !defined(solaris) +# include <net/route.h> +# endif #else # define __KERNEL__ /* because there's a macro not wrapped by this */ # include <net/route.h> /* in this file :-/ */ @@ -84,12 +84,6 @@ typedef int boolean_t; #include <netinet/in.h> #include <arpa/inet.h> #include <netinet/ip.h> -#if !defined(linux) -# include <netinet/ip_var.h> -# if !defined(__hpux) -# include <netinet/in_pcb.h> -# endif -#endif #if defined(__SVR4) || defined(__svr4__) || defined(__sgi) # include <sys/sysmacros.h> #endif @@ -100,6 +94,12 @@ typedef int boolean_t; #ifdef __hpux # undef _NET_ROUTE_INCLUDED #endif +#if !defined(linux) +# include <netinet/ip_var.h> +# if !defined(__hpux) && !defined(solaris) +# include <netinet/in_pcb.h> +# endif +#endif #include "ipsend.h" #if !defined(linux) && !defined(__hpux) # include <netinet/tcp_timer.h> @@ -120,11 +120,11 @@ typedef int boolean_t; void ip_test1(dev, mtu, ip, gwip, ptest) -char *dev; -int mtu; -ip_t *ip; -struct in_addr gwip; -int ptest; + char *dev; + int mtu; + ip_t *ip; + struct in_addr gwip; + int ptest; { #ifdef USE_NANOSLEEP struct timespec ts; @@ -471,11 +471,11 @@ int ptest; void ip_test2(dev, mtu, ip, gwip, ptest) -char *dev; -int mtu; -ip_t *ip; -struct in_addr gwip; -int ptest; + char *dev; + int mtu; + ip_t *ip; + struct in_addr gwip; + int ptest; { #ifdef USE_NANOSLEEP struct timespec ts; @@ -567,11 +567,11 @@ int ptest; * test 3 (ICMP) */ void ip_test3(dev, mtu, ip, gwip, ptest) -char *dev; -int mtu; -ip_t *ip; -struct in_addr gwip; -int ptest; + char *dev; + int mtu; + ip_t *ip; + struct in_addr gwip; + int ptest; { static int ict1[10] = { 8, 9, 10, 13, 14, 15, 16, 17, 18, 0 }; static int ict2[8] = { 3, 9, 10, 13, 14, 17, 18, 0 }; @@ -768,11 +768,11 @@ int ptest; /* Perform test 4 (UDP) */ void ip_test4(dev, mtu, ip, gwip, ptest) -char *dev; -int mtu; -ip_t *ip; -struct in_addr gwip; -int ptest; + char *dev; + int mtu; + ip_t *ip; + struct in_addr gwip; + int ptest; { #ifdef USE_NANOSLEEP struct timespec ts; @@ -933,11 +933,11 @@ int ptest; /* Perform test 5 (TCP) */ void ip_test5(dev, mtu, ip, gwip, ptest) -char *dev; -int mtu; -ip_t *ip; -struct in_addr gwip; -int ptest; + char *dev; + int mtu; + ip_t *ip; + struct in_addr gwip; + int ptest; { #ifdef USE_NANOSLEEP struct timespec ts; @@ -1283,11 +1283,11 @@ skip_five_and_six: /* Perform test 6 (exhaust mbuf test) */ void ip_test6(dev, mtu, ip, gwip, ptest) -char *dev; -int mtu; -ip_t *ip; -struct in_addr gwip; -int ptest; + char *dev; + int mtu; + ip_t *ip; + struct in_addr gwip; + int ptest; { #ifdef USE_NANOSLEEP struct timespec ts; @@ -1365,11 +1365,11 @@ int ptest; static u_long tbuf[64]; void ip_test7(dev, mtu, ip, gwip, ptest) -char *dev; -int mtu; -ip_t *ip; -struct in_addr gwip; -int ptest; + char *dev; + int mtu; + ip_t *ip; + struct in_addr gwip; + int ptest; { ip_t *pip; #ifdef USE_NANOSLEEP diff --git a/ipsend/larp.c b/ipsend/larp.c index 3d0c89c66a568..762993ebac3ce 100644 --- a/ipsend/larp.c +++ b/ipsend/larp.c @@ -6,7 +6,7 @@ */ #if !defined(lint) static const char sccsid[] = "@(#)larp.c 1.1 8/19/95 (C)1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: larp.c,v 2.4 2003/12/01 02:01:16 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #include <sys/param.h> #include <sys/types.h> @@ -28,7 +28,7 @@ static const char rcsid[] = "@(#)$Id: larp.c,v 2.4 2003/12/01 02:01:16 darrenr E * (4 bytes) */ int resolve(host, address) -char *host, *address; + char *host, *address; { struct hostent *hp; u_long add; @@ -54,8 +54,8 @@ char *host, *address; * some BSD program, I cant remember which. */ int arp(ip, ether) -char *ip; -char *ether; + char *ip; + char *ether; { static int s = -1; struct arpreq ar; diff --git a/ipsend/linux.h b/ipsend/linux.h index ae2e05f582643..9c03f644b36fb 100644 --- a/ipsend/linux.h +++ b/ipsend/linux.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1995-1998 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * This code may be freely distributed as long as it retains this notice * and is not changed in any way. The author accepts no responsibility diff --git a/ipsend/lsock.c b/ipsend/lsock.c index 7163ea7db5fd8..53df06c1e98fa 100644 --- a/ipsend/lsock.c +++ b/ipsend/lsock.c @@ -6,7 +6,7 @@ */ #if !defined(lint) static const char sccsid[] = "@(#)lsock.c 1.2 1/11/96 (C)1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: lsock.c,v 2.3.4.1 2006/03/17 13:45:34 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #include <stdio.h> #include <unistd.h> @@ -64,9 +64,9 @@ struct task_struct *proc; #endif int kmemcpy(buf, pos, n) -char *buf; -void *pos; -int n; + char *buf; + void *pos; + int n; { static int kfd = -1; @@ -148,8 +148,8 @@ struct task_struct *getproc() struct sock *find_tcp(fd, ti) -int fd; -struct tcpiphdr *ti; + int fd; + struct tcpiphdr *ti; { struct sock *s; struct inode *i; @@ -187,10 +187,10 @@ struct tcpiphdr *ti; } int do_socket(dev, mtu, ti, gwip) -char *dev; -int mtu; -struct tcpiphdr *ti; -struct in_addr gwip; + char *dev; + int mtu; + struct tcpiphdr *ti; + struct in_addr gwip; { struct sockaddr_in rsin, lsin; struct sock *s, sk; diff --git a/ipsend/resend.c b/ipsend/resend.c index e7b1ef42cfa5a..4bdc04f9095c0 100644 --- a/ipsend/resend.c +++ b/ipsend/resend.c @@ -6,15 +6,12 @@ */ #if !defined(lint) static const char sccsid[] = "@(#)resend.c 1.3 1/11/96 (C)1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: resend.c,v 2.8.2.3 2007/02/17 12:41:51 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #include <sys/param.h> #include <sys/types.h> #include <sys/time.h> #include <sys/socket.h> -#ifdef __osf__ -# include "radix_ipf_local.h" -#endif #include <net/if.h> #include <netinet/in.h> #include <arpa/inet.h> @@ -36,12 +33,11 @@ static const char rcsid[] = "@(#)$Id: resend.c,v 2.8.2.3 2007/02/17 12:41:51 dar extern int opts; -static u_char pbuf[65536]; /* 1 big packet */ -void printpacket __P((ip_t *)); +void dumppacket __P((ip_t *)); -void printpacket(ip) -ip_t *ip; +void dumppacket(ip) + ip_t *ip; { tcphdr_t *t; int i, j; @@ -71,16 +67,17 @@ ip_t *ip; int ip_resend(dev, mtu, r, gwip, datain) -char *dev; -int mtu; -struct in_addr gwip; -struct ipread *r; -char *datain; + char *dev; + int mtu; + struct in_addr gwip; + struct ipread *r; + char *datain; { ether_header_t *eh; char dhost[6]; ip_t *ip; int fd, wfd = initdevice(dev, 5), len, i; + mb_t mb; if (wfd == -1) return -1; @@ -93,7 +90,7 @@ char *datain; if (fd < 0) exit(-1); - ip = (struct ip *)pbuf; + ip = (struct ip *)mb.mb_buf; eh = (ether_header_t *)malloc(sizeof(*eh)); if(!eh) { @@ -109,7 +106,7 @@ char *datain; return -2; } - while ((i = (*r->r_readip)((char *)pbuf, sizeof(pbuf), NULL, NULL)) > 0) + while ((i = (*r->r_readip)(&mb, NULL, NULL)) > 0) { if (!(opts & OPT_RAW)) { len = ntohs(ip->ip_len); @@ -129,9 +126,9 @@ char *datain; IP_HL(ip) << 2); bcopy(ip, (char *)(eh + 1), len); len += sizeof(*eh); - printpacket(ip); + dumppacket(ip); } else { - eh = (ether_header_t *)pbuf; + eh = (ether_header_t *)mb.mb_buf; len = i; } diff --git a/ipsend/sbpf.c b/ipsend/sbpf.c index 374b7ed6ad9b6..21e06c1e746ef 100644 --- a/ipsend/sbpf.c +++ b/ipsend/sbpf.c @@ -26,9 +26,7 @@ #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> -#include <netinet/ip_var.h> #include <netinet/udp.h> -#include <netinet/udp_var.h> #include <netinet/tcp.h> #include <stdio.h> @@ -47,7 +45,7 @@ #if !defined(lint) static const char sccsid[] = "@(#)sbpf.c 1.3 8/25/95 (C)1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: sbpf.c,v 2.5.4.1 2006/03/21 16:32:58 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif /* @@ -58,8 +56,8 @@ static int bufsize = 0, timeout = 1; int initdevice(device, tout) -char *device; -int tout; + char *device; + int tout; { struct bpf_version bv; struct timeval to; @@ -142,9 +140,9 @@ int tout; * output an IP packet onto a fd opened for /dev/bpf */ int sendip(fd, pkt, len) -int fd, len; -char *pkt; -{ + int fd, len; + char *pkt; +{ if (write(fd, pkt, len) == -1) { perror("send"); diff --git a/ipsend/sdlpi.c b/ipsend/sdlpi.c index 1ce894659c3ac..4867008396773 100644 --- a/ipsend/sdlpi.c +++ b/ipsend/sdlpi.c @@ -25,7 +25,6 @@ #endif #ifdef __osf__ # include <sys/dlpihdr.h> -# include "radix_ipf_local.h" #else # include <sys/dlpi.h> #endif @@ -47,7 +46,7 @@ #if !defined(lint) static const char sccsid[] = "@(#)sdlpi.c 1.3 10/30/95 (C)1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: sdlpi.c,v 2.8.2.2 2007/02/17 12:41:51 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #define CHUNKSIZE 8192 @@ -59,8 +58,8 @@ static const char rcsid[] = "@(#)$Id: sdlpi.c,v 2.8.2.2 2007/02/17 12:41:51 darr * interface are included in the header size. */ int initdevice(device, tout) -char *device; -int tout; + char *device; + int tout; { char devname[16], *s, buf[256]; int i, fd; @@ -134,9 +133,9 @@ int tout; * output an IP packet onto a fd opened for /dev/nit */ int sendip(fd, pkt, len) -int fd, len; -char *pkt; -{ + int fd, len; + char *pkt; +{ struct strbuf dbuf, *dp = &dbuf, *cp = NULL; int pri = 0; #ifdef DL_HP_RAWDLS diff --git a/ipsend/sirix.c b/ipsend/sirix.c index 0f634f766a466..fa6189ed51e5c 100644 --- a/ipsend/sirix.c +++ b/ipsend/sirix.c @@ -58,7 +58,7 @@ int initdevice(char *device, int tout) * output an IP packet */ int sendip(int fd, char *pkt, int len) -{ +{ struct sockaddr_raw sr; int srlen = sizeof(sr); struct ifreq ifr; diff --git a/ipsend/slinux.c b/ipsend/slinux.c index 7c362b6e46d7a..dbcbed607160b 100644 --- a/ipsend/slinux.c +++ b/ipsend/slinux.c @@ -28,7 +28,7 @@ #if !defined(lint) static const char sccsid[] = "@(#)slinux.c 1.2 8/25/95"; -static const char rcsid[] = "@(#)$Id: slinux.c,v 2.3 2001/06/09 17:09:26 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #define CHUNKSIZE 8192 @@ -44,8 +44,8 @@ static char *eth_dev = NULL; int initdevice(dev, spare) -char *dev; -int spare; + char *dev; + int spare; { int fd; @@ -64,8 +64,8 @@ int spare; * output an IP packet onto a fd opened for /dev/nit */ int sendip(fd, pkt, len) -int fd, len; -char *pkt; + int fd, len; + char *pkt; { struct sockaddr s; struct ifreq ifr; diff --git a/ipsend/snit.c b/ipsend/snit.c index bcd07d04003e2..c0ad9e97b5b4d 100644 --- a/ipsend/snit.c +++ b/ipsend/snit.c @@ -39,7 +39,7 @@ #if !defined(lint) static const char sccsid[] = "@(#)snit.c 1.5 1/11/96 (C)1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: snit.c,v 2.3 2001/06/09 17:09:26 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #define CHUNKSIZE 8192 @@ -56,8 +56,8 @@ static int timeout; int initdevice(device, tout) -char *device; -int tout; + char *device; + int tout; { struct strioctl si; struct timeval to; @@ -113,9 +113,9 @@ int tout; * output an IP packet onto a fd opened for /dev/nit */ int sendip(fd, pkt, len) -int fd, len; -char *pkt; -{ + int fd, len; + char *pkt; +{ struct sockaddr sk, *sa = &sk; struct strbuf cbuf, *cp = &cbuf, dbuf, *dp = &dbuf; diff --git a/ipsend/sock.c b/ipsend/sock.c index f4317fcccb165..0c63cd2a6f44f 100644 --- a/ipsend/sock.c +++ b/ipsend/sock.c @@ -6,7 +6,7 @@ */ #if !defined(lint) static const char sccsid[] = "@(#)sock.c 1.2 1/11/96 (C)1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: sock.c,v 2.8.4.7 2007/09/13 07:19:34 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #include <sys/param.h> #include <sys/types.h> @@ -29,7 +29,7 @@ typedef int boolean_t; # include <sys/dir.h> #endif #if !defined(__osf__) -# ifdef __NetBSD__ +# ifdef __NetBSD__ # include <machine/lock.h> # endif # define _KERNEL @@ -65,9 +65,6 @@ typedef int boolean_t; #include <netinet/ip.h> #include <netinet/tcp.h> #include <net/if.h> -#if defined(__FreeBSD__) -# include "radix_ipf.h" -#endif #ifndef __osf__ # include <net/route.h> #endif @@ -113,9 +110,9 @@ static struct kinfo_proc *getproc __P((void)); int kmemcpy(buf, pos, n) -char *buf; -void *pos; -int n; + char *buf; + void *pos; + int n; { static int kfd = -1; off_t offset = (u_long)pos; @@ -193,8 +190,8 @@ static struct proc *getproc() struct tcpcb *find_tcp(fd, ti) -int fd; -struct tcpiphdr *ti; + int fd; + struct tcpiphdr *ti; { struct tcpcb *t; struct inpcb *i; @@ -284,8 +281,8 @@ static struct kinfo_proc *getproc() struct tcpcb *find_tcp(tfd, ti) -int tfd; -struct tcpiphdr *ti; + int tfd; + struct tcpiphdr *ti; { struct tcpcb *t; struct inpcb *i; @@ -380,10 +377,10 @@ finderror: #endif /* BSD < 199301 */ int do_socket(dev, mtu, ti, gwip) -char *dev; -int mtu; -struct tcpiphdr *ti; -struct in_addr gwip; + char *dev; + int mtu; + struct tcpiphdr *ti; + struct in_addr gwip; { struct sockaddr_in rsin, lsin; struct tcpcb *t, tcb; diff --git a/ipsend/tcpip.h b/ipsend/tcpip.h deleted file mode 100644 index 44a2de995c283..0000000000000 --- a/ipsend/tcpip.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)tcpip.h 8.1 (Berkeley) 6/10/93 - * $Id: tcpip.h,v 2.2.2.3 2004/05/26 15:45:48 darrenr Exp $ - */ - -#ifndef _NETINET_TCPIP_H_ -#define _NETINET_TCPIP_H_ - -# if defined(linux) && !defined(LINUX_IPOVLY) -# define LINUX_IPOVLY -struct ipovly { - caddr_t ih_next, ih_prev; /* for protocol sequence q's */ - u_char ih_x1; /* (unused) */ - u_char ih_pr; /* protocol */ - short ih_len; /* protocol length */ - struct in_addr ih_src; /* source internet address */ - struct in_addr ih_dst; /* destination internet address */ -}; -# endif - -/* - * Tcp+ip header, after ip options removed. - */ -struct tcpiphdr { - struct ipovly ti_i; /* overlaid ip structure */ - struct tcphdr ti_t; /* tcp header */ -}; - -#ifdef notyet -/* - * Tcp+ip header, after ip options removed but including TCP options. - */ -struct full_tcpiphdr { - struct ipovly ti_i; /* overlaid ip structure */ - struct tcphdr ti_t; /* tcp header */ - char ti_o[TCP_MAXOLEN]; /* space for tcp options */ -}; -#endif /* notyet */ -#define ti_next ti_i.ih_next -#define ti_prev ti_i.ih_prev -#define ti_x1 ti_i.ih_x1 -#define ti_pr ti_i.ih_pr -#define ti_len ti_i.ih_len -#define ti_src ti_i.ih_src -#define ti_dst ti_i.ih_dst -#define ti_sport ti_t.th_sport -#define ti_dport ti_t.th_dport -#define ti_seq ti_t.th_seq -#define ti_ack ti_t.th_ack -#define ti_x2 ti_t.th_x2 -#define ti_off ti_t.th_off -#define ti_flags ti_t.th_flags -#define ti_win ti_t.th_win -#define ti_sum ti_t.th_sum -#define ti_urp ti_t.th_urp - -#endif diff --git a/ipsend/ultrix.c b/ipsend/ultrix.c deleted file mode 100644 index f41a8a9a7481a..0000000000000 --- a/ipsend/ultrix.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * (C)opyright 1998 Darren Reed. (from tcplog) - * - * See the IPFILTER.LICENCE file for details on licencing. - */ -#include <stdio.h> -#include <strings.h> -#include <unistd.h> -#include <stdlib.h> -#include <ctype.h> -#include <sys/types.h> -#include <sys/param.h> -#include <sys/socket.h> -#include <sys/file.h> -#include <sys/ioctl.h> -#include <net/if.h> -#include <netinet/in.h> -#include <netinet/if_ether.h> -#include <netdnet/dli_var.h> - - -static struct dli_devid dli_devid; - - -int initdevice(device, sport, tout) -char *device; -int sport, tout; -{ - u_char *s; - int fd; - - fd = socket(AF_DLI, SOCK_DGRAM, 0); - if (fd == -1) - perror("socket(AF_DLI,SOCK_DGRAM)"); - else { - strncpy(dli_devid.dli_devname, device, DLI_DEVSIZE); - dli_devid.dli_devname[DLI_DEVSIZE] ='\0'; - for (s = dli_devid.dli_devname; *s && isalpha((char)*s); s++) - ; - if (*s && isdigit((char)*s)) { - dli_devid.dli_devnumber = atoi(s); - } - } - return fd; -} - - -/* - * output an IP packet onto a fd opened for /dev/bpf - */ -int sendip(fd, pkt, len) -int fd, len; -char *pkt; -{ - struct sockaddr_dl dl; - struct sockaddr_edl *edl = &dl.choose_addr.dli_eaddr; - - dl.dli_family = AF_DLI; - dl.dli_substructype = DLI_ETHERNET; - bcopy((char *)&dli_devid, (char *)&dl.dli_device, sizeof(dli_devid)); - bcopy(pkt, edl->dli_target, DLI_EADDRSIZE); - bcopy(pkt, edl->dli_dest, DLI_EADDRSIZE); - bcopy(pkt + DLI_EADDRSIZE * 2, (char *)&edl->dli_protype, 2); - edl->dli_ioctlflg = 0; - - if (sendto(fd, pkt, len, 0, (struct sockaddr *)&dl, sizeof(dl)) == -1) - { - perror("send"); - return -1; - } - - return len; -} - - -char *strdup(str) -char *str; -{ - char *s; - - if ((s = (char *)malloc(strlen(str) + 1))) - return strcpy(s, str); - return NULL; -} diff --git a/ipt.c b/ipt.c deleted file mode 100644 index 5a20f240aa9d9..0000000000000 --- a/ipt.c +++ /dev/null @@ -1,551 +0,0 @@ -/* - * Copyright (C) 1993-2002 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - */ -#ifdef __FreeBSD__ -# ifndef __FreeBSD_cc_version -# include <osreldate.h> -# else -# if __FreeBSD_cc_version < 430000 -# include <osreldate.h> -# endif -# endif -#endif -#if defined(__sgi) && (IRIX > 602) -# define _KMEMUSER -# include <sys/ptimers.h> -#endif -#include <stdio.h> -#include <assert.h> -#include <string.h> -#include <sys/types.h> -#if !defined(__SVR4) && !defined(__svr4__) && !defined(__sgi) -#include <strings.h> -#else -#if !defined(__sgi) -#include <sys/byteorder.h> -#endif -#include <sys/file.h> -#endif -#include <sys/param.h> -#include <sys/time.h> -#include <stdlib.h> -#include <unistd.h> -#include <stddef.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#ifndef linux -#include <netinet/ip_var.h> -#endif -#include <netinet/ip.h> -#include <netinet/udp.h> -#include <netinet/tcp.h> -#include <netinet/ip_icmp.h> -#include <net/if.h> -#if __FreeBSD_version >= 300000 -# include <net/if_var.h> -#endif -#include <netdb.h> -#include <arpa/nameser.h> -#include <arpa/inet.h> -#include <resolv.h> -#include <ctype.h> -#include "ip_compat.h" -#include <netinet/tcpip.h> -#include "ip_fil.h" -#include "ip_nat.h" -#include "ip_state.h" -#include "ip_frag.h" -#include "ipf.h" -#include "ipt.h" - -#if !defined(lint) -static const char sccsid[] = "@(#)ipt.c 1.19 6/3/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipt.c,v 2.6.2.26 2003/11/09 17:22:21 darrenr Exp $"; -#endif - -extern char *optarg; -extern struct frentry *ipfilter[2][2]; -extern struct ipread snoop, etherf, tcpd, pcap, iptext, iphex; -extern struct ifnet *get_unit __P((char *, int)); -extern void init_ifp __P((void)); -extern ipnat_t *natparse __P((char *, int, int *)); -extern int fr_running; - -int opts = 0; -int rremove = 0; -int use_inet6 = 0; -int main __P((int, char *[])); -int loadrules __P((char *)); -int kmemcpy __P((char *, long, int)); -void dumpnat __P((void)); -void dumpstate __P((void)); -char *getifname __P((void *)); -void drain_log __P((char *)); - -int main(argc,argv) -int argc; -char *argv[]; -{ - char *datain, *iface, *ifname, *packet, *logout; - int fd, i, dir, c, loaded, dump, hlen; - struct in_addr src; - struct ifnet *ifp; - struct ipread *r; - u_long buf[2048]; - ip_t *ip; - - dir = 0; - dump = 0; - loaded = 0; - r = &iptext; - iface = NULL; - logout = NULL; - src.s_addr = 0; - ifname = "anon0"; - datain = NULL; - - nat_init(); - fr_stateinit(); - initparse(); - ipflog_init(); - fr_running = 1; - - while ((c = getopt(argc, argv, "6bdDEHi:I:l:NoPr:Rs:STvxX")) != -1) - switch (c) - { - case '6' : -#ifdef USE_INET6 - use_inet6 = 1; - break; -#else - fprintf(stderr, "IPv6 not supported\n"); - exit(1); -#endif - case 'b' : - opts |= OPT_BRIEF; - break; - case 'd' : - opts |= OPT_DEBUG; - break; - case 'D' : - dump = 1; - break; - case 'i' : - datain = optarg; - break; - case 'I' : - ifname = optarg; - break; - case 'l' : - logout = optarg; - break; - case 'o' : - opts |= OPT_SAVEOUT; - break; - case 'r' : - if (loadrules(optarg) == -1) - return -1; - loaded = 1; - break; - case 's' : - src.s_addr = inet_addr(optarg); - break; - case 'v' : - opts |= OPT_VERBOSE; - break; - case 'E' : - r = ðerf; - break; - case 'H' : - r = &iphex; - break; - case 'N' : - opts |= OPT_NAT; - break; - case 'P' : - r = &pcap; - break; - case 'R' : - rremove = 1; - break; - case 'S' : - r = &snoop; - break; - case 'T' : - r = &tcpd; - break; - case 'x' : - opts |= OPT_HEX; - break; - case 'X' : - r = &iptext; - break; - } - - if (loaded == 0) { - (void)fprintf(stderr,"no rules loaded\n"); - exit(-1); - } - - if (opts & OPT_SAVEOUT) - init_ifp(); - - if (datain) - fd = (*r->r_open)(datain); - else - fd = (*r->r_open)("-"); - - if (fd < 0) - exit(-1); - - ip = (ip_t *)buf; - while ((i = (*r->r_readip)((char *)buf, sizeof(buf), - &iface, &dir)) > 0) { - if (iface == NULL || *iface == '\0') - iface = ifname; - ifp = get_unit(iface, ip->ip_v); - hlen = 0; - if (!use_inet6) { - ip->ip_off = ntohs(ip->ip_off); - ip->ip_len = ntohs(ip->ip_len); - hlen = ip->ip_hl << 2; - if (src.s_addr != 0) { - if (src.s_addr == ip->ip_src.s_addr) - dir = 1; - else if (src.s_addr == ip->ip_dst.s_addr) - dir = 0; - } - } -#ifdef USE_INET6 - else - hlen = sizeof(ip6_t); -#endif - if (opts & OPT_VERBOSE) { - printf("%s on [%s]: ", dir ? "out" : "in", - (iface && *iface) ? iface : "??"); - } - packet = (char *)buf; - /* ipfr_slowtimer(); */ - i = fr_check(ip, hlen, ifp, dir, (mb_t **)&packet); - if ((opts & OPT_NAT) == 0) - switch (i) - { - case -5 : - (void)printf("block return-icmp-as-dest"); - break; - case -4 : - (void)printf("block return-icmp"); - break; - case -3 : - (void)printf("block return-rst"); - break; - case -2 : - (void)printf("auth"); - break; - case -1 : - (void)printf("block"); - break; - case 0 : - (void)printf("pass"); - break; - case 1 : - (void)printf("nomatch"); - break; - } - if (!use_inet6) { - ip->ip_off = htons(ip->ip_off); - ip->ip_len = htons(ip->ip_len); - } - - if (!(opts & OPT_BRIEF)) { - putchar(' '); - printpacket((ip_t *)buf); - printf("--------------"); - } else if ((opts & (OPT_BRIEF|OPT_NAT)) == (OPT_NAT|OPT_BRIEF)) - printpacket((ip_t *)buf); -#ifndef linux - if (dir && (ifp != NULL) && ip->ip_v && (packet != NULL)) -# if defined(__sgi) && (IRIX < 605) - (*ifp->if_output)(ifp, (void *)packet, NULL); -# else - (*ifp->if_output)(ifp, (void *)packet, NULL, 0); -# endif -#endif - if ((opts & (OPT_BRIEF|OPT_NAT)) != (OPT_NAT|OPT_BRIEF)) - putchar('\n'); - dir = 0; - if (iface != ifname) { - free(iface); - iface = ifname; - } - } - (*r->r_close)(); - - if (logout != NULL) { - drain_log(logout); - } - - if (dump == 1) { - dumpnat(); - dumpstate(); - } - - return 0; -} - - -/* - * Load in either NAT or ipf rules from a file, which is treated as stdin - * if the name is "-". NOTE, stdin can only be used once as the file is - * closed after use. - */ -int loadrules(file) -char *file; -{ - char line[513], *s; - int linenum, i; - void *fr; - FILE *fp; - int parsestatus; - - if (!strcmp(file, "-")) - fp = stdin; - else if (!(fp = fopen(file, "r"))) { - (void)fprintf(stderr, "couldn't open %s\n", file); - return (-1); - } - - if (!(opts & OPT_BRIEF)) - (void)printf("opening rule file \"%s\"\n", file); - - linenum = 0; - - while (fgets(line, sizeof(line) - 1, fp)) { - linenum++; - - /* - * treat both CR and LF as EOL - */ - if ((s = index(line, '\n'))) - *s = '\0'; - if ((s = index(line, '\r'))) - *s = '\0'; - - /* - * # is comment marker, everything after is a ignored - */ - if ((s = index(line, '#'))) - *s = '\0'; - - if (!*line) - continue; - - /* fake an `ioctl' call :) */ - - if ((opts & OPT_NAT) != 0) { - parsestatus = 1; - fr = natparse(line, linenum, &parsestatus); - if (parsestatus != 0) { - if (*line) { - fprintf(stderr, - "%d: syntax error in \"%s\"\n", - linenum, line); - } - fprintf(stderr, "%s: %s error (%d), quitting\n", - file, - ((parsestatus < 0)? "parse": "internal"), - parsestatus); - exit(1); - } - if (!fr) - continue; - - if (rremove == 0) { - i = IPL_EXTERN(ioctl)(IPL_LOGNAT, SIOCADNAT, - (caddr_t)&fr, - FWRITE|FREAD); - if (opts & OPT_DEBUG) - fprintf(stderr, - "iplioctl(ADNAT,%p,1) = %d\n", - fr, i); - } else { - i = IPL_EXTERN(ioctl)(IPL_LOGNAT, SIOCRMNAT, - (caddr_t)&fr, - FWRITE|FREAD); - if (opts & OPT_DEBUG) - fprintf(stderr, - "iplioctl(RMNAT,%p,1) = %d\n", - fr, i); - } - } else { - fr = parse(line, linenum, &parsestatus); - - if (parsestatus != 0) { - fprintf(stderr, "%s: %s error (%d), quitting\n", - file, - ((parsestatus < 0)? "parse": "internal"), - parsestatus); - exit(1); - } - - if (!fr) { - continue; - } - - if (rremove == 0) { - i = IPL_EXTERN(ioctl)(0, SIOCADAFR, - (caddr_t)&fr, - FWRITE|FREAD); - if (opts & OPT_DEBUG) - fprintf(stderr, - "iplioctl(ADAFR,%p,1) = %d\n", - fr, i); - } else { - i = IPL_EXTERN(ioctl)(0, SIOCRMAFR, - (caddr_t)&fr, - FWRITE|FREAD); - if (opts & OPT_DEBUG) - fprintf(stderr, - "iplioctl(RMAFR,%p,1) = %d\n", - fr, i); - } - } - } - (void)fclose(fp); - - return 0; -} - - -int kmemcpy(addr, offset, size) -char *addr; -long offset; -int size; -{ - bcopy((char *)offset, addr, size); - return 0; -} - - -/* - * Display the built up NAT table rules and mapping entries. - */ -void dumpnat() -{ - ipnat_t *ipn; - nat_t *nat; - - printf("List of active MAP/Redirect filters:\n"); - for (ipn = nat_list; ipn != NULL; ipn = ipn->in_next) - printnat(ipn, opts & (OPT_DEBUG|OPT_VERBOSE)); - printf("\nList of active sessions:\n"); - for (nat = nat_instances; nat; nat = nat->nat_next) - printactivenat(nat, opts); -} - - -/* - * Display the built up state table rules and mapping entries. - */ -void dumpstate() -{ - ipstate_t *ips; - - printf("List of active state sessions:\n"); - for (ips = ips_list; ips != NULL; ) - ips = printstate(ips, opts & (OPT_DEBUG|OPT_VERBOSE)); -} - - -/* - * Given a pointer to an interface in the kernel, return a pointer to a - * string which is the interface name. - */ -char *getifname(ptr) -void *ptr; -{ -#if defined(NetBSD) && (NetBSD >= 199905) && (NetBSD < 1991011) || \ - defined(__OpenBSD__) || \ - (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) -#else - char buf[32], *s; - int len; -#endif - struct ifnet netif; - - if (ptr == (void *)-1) - return "!"; - if (ptr == NULL) - return "-"; - - if (kmemcpy((char *)&netif, (u_long)ptr, sizeof(netif)) == -1) - return "X"; -#if defined(NetBSD) && (NetBSD >= 199905) && (NetBSD < 1991011) || \ - defined(__OpenBSD__) || \ - (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) - return strdup(netif.if_xname); -#else - if (kmemcpy(buf, (u_long)netif.if_name, sizeof(buf)) == -1) - return "X"; - if (netif.if_unit < 10) - len = 2; - else if (netif.if_unit < 1000) - len = 3; - else if (netif.if_unit < 10000) - len = 4; - else - len = 5; - buf[sizeof(buf) - len] = '\0'; - for (s = buf; *s && !isdigit(*s); s++) - ; - if (isdigit(*s)) - *s = '\0'; - sprintf(buf + strlen(buf), "%d", netif.if_unit % 10000); - return strdup(buf); -#endif -} - - -void drain_log(filename) -char *filename; -{ - char buffer[IPLLOGSIZE]; - struct iovec iov; - struct uio uio; - size_t resid; - int fd; - - fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0644); - if (fd == -1) { - perror("drain_log:open"); - return; - } - - while (1) { - bzero((char *)&iov, sizeof(iov)); - iov.iov_base = buffer; - iov.iov_len = sizeof(buffer); - - bzero((char *)&uio, sizeof(uio)); - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_resid = iov.iov_len; - resid = uio.uio_resid; - - if (ipflog_read(0, &uio) == 0) { - /* - * If nothing was read then break out. - */ - if (uio.uio_resid == resid) - break; - write(fd, buffer, resid - uio.uio_resid); - } else - break; - } - - close(fd); -} @@ -1,9 +1,9 @@ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ipt.h,v 2.6.4.2 2006/03/26 23:42:04 darrenr Exp $ + * $Id$ */ #ifndef __IPT_H__ @@ -24,15 +24,12 @@ struct ipread { int (*r_open) __P((char *)); int (*r_close) __P((void)); - int (*r_readip) __P((char *, int, char **, int *)); + int (*r_readip) __P((mb_t *, char **, int *)); int r_flags; }; #define R_DO_CKSUM 0x01 -extern void debug __P((char *, ...)); -extern void verbose __P((char *, ...)); - #ifdef P_DEF # undef __P # undef P_DEF diff --git a/kmem.c b/kmem.c deleted file mode 100644 index 5723ba3806c6e..0000000000000 --- a/kmem.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (C) 1993-2002 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - */ -/* - * kmemcpy() - copies n bytes from kernel memory into user buffer. - * returns 0 on success, -1 on error. - */ - -#if defined(__sgi) && (IRIX > 602) -# include <sys/ptimers.h> -#endif -#include <stdio.h> -#include <sys/param.h> -#include <sys/types.h> -#include <unistd.h> -#include <string.h> -#include <fcntl.h> -#include <stdlib.h> -#include <sys/file.h> -#ifndef __sgi -#include <kvm.h> -#endif -#include <fcntl.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <net/if.h> -#if __FreeBSD_version >= 300000 -# include <net/if_var.h> -#endif - -#include "kmem.h" -#include "netinet/ip_compat.h" -#include "netinet/ip_fil.h" -#include "ipf.h" - - -#ifndef __STDC__ -# define const -#endif - -#if !defined(lint) -static const char sccsid[] = "@(#)kmem.c 1.4 1/12/96 (C) 1992 Darren Reed"; -static const char rcsid[] = "@(#)$Id: kmem.c,v 2.2.2.18 2003/11/09 17:22:22 darrenr Exp $"; -#endif - -#ifdef __sgi -typedef int kvm_t; - -static int kvm_fd = -1; -static char *kvm_errstr = NULL; - -kvm_t *kvm_open(kernel, core, swap, mode, errstr) -char *kernel, *core, *swap; -int mode; -char *errstr; -{ - kvm_errstr = errstr; - - if (core == NULL) - core = "/dev/kmem"; - kvm_fd = open(core, mode); - return (kvm_fd >= 0) ? (kvm_t *)&kvm_fd : NULL; -} - -int kvm_read(kvm, pos, buffer, size) -kvm_t *kvm; -u_long pos; -char *buffer; -size_t size; -{ - size_t left; - char *bufp; - int r; - - if (lseek(*kvm, pos, 0) == -1) { - if (kvm_errstr != NULL) { - fprintf(stderr, "%s:", kvm_errstr); - perror("lseek"); - } - return -1; - } - - for (bufp = buffer, left = size; left > 0; bufp += r, left -= r) { - r = read(*kvm, bufp, 1); - if (r <= 0) - return -1; - } - return size; -} -#endif - -static kvm_t *kvm_f = NULL; - -int openkmem(kern, core) -char *kern, *core; -{ - union { - int ui; - kvm_t *uk; - } k; - - kvm_f = kvm_open(kern, core, NULL, O_RDONLY, NULL); - if (kvm_f == NULL) - { - perror("openkmem:open"); - return -1; - } - k.uk = kvm_f; - return k.ui; -} - -int kmemcpy(buf, pos, n) -register char *buf; -long pos; -register int n; -{ - register int r; - - if (!n) - return 0; - - if (kvm_f == NULL) - if (openkmem(NULL, NULL) == -1) - return -1; - - while ((r = kvm_read(kvm_f, pos, buf, (size_t)n)) < n) - if (r <= 0) - { - fprintf(stderr, "pos=0x%x ", (u_int)pos); - perror("kmemcpy:read"); - return -1; - } - else - { - buf += r; - pos += r; - n -= r; - } - return 0; -} - -int kstrncpy(buf, pos, n) -register char *buf; -long pos; -register int n; -{ - register int r; - - if (!n) - return 0; - - if (kvm_f == NULL) - if (openkmem(NULL, NULL) == -1) - return -1; - - while (n > 0) - { - r = kvm_read(kvm_f, pos, buf, (size_t)1); - if (r <= 0) - { - fprintf(stderr, "pos=0x%x ", (u_int)pos); - perror("kstrncpy:read"); - return -1; - } - else - { - if (*buf == '\0') - break; - buf++; - pos++; - n--; - } - } - return 0; -} - - -/* - * Given a pointer to an interface in the kernel, return a pointer to a - * string which is the interface name. - */ -char *getifname(ptr) -void *ptr; -{ -#if SOLARIS - char *ifname; - ill_t ill; - - if (ptr == (void *)-1) - return "!"; - if (ptr == NULL) - return "-"; - - if (kmemcpy((char *)&ill, (u_long)ptr, sizeof(ill)) == -1) - return "X"; - ifname = malloc(ill.ill_name_length + 1); - if (kmemcpy(ifname, (u_long)ill.ill_name, - ill.ill_name_length) == -1) - return "X"; - return ifname; -#else -# if defined(NetBSD) && (NetBSD >= 199905) && (NetBSD < 1991011) || \ - defined(__OpenBSD__) || \ - (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) -#else - char buf[32]; - int len; -# endif - struct ifnet netif; - - if (ptr == (void *)-1) - return "!"; - if (ptr == NULL) - return "-"; - - if (kmemcpy((char *)&netif, (u_long)ptr, sizeof(netif)) == -1) - return "X"; -# if defined(NetBSD) && (NetBSD >= 199905) && (NetBSD < 1991011) || \ - defined(__OpenBSD__) || \ - (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) - return strdup(netif.if_xname); -# else - if (kstrncpy(buf, (u_long)netif.if_name, sizeof(buf)) == -1) - return "X"; - if (netif.if_unit < 10) - len = 2; - else if (netif.if_unit < 1000) - len = 3; - else if (netif.if_unit < 10000) - len = 4; - else - len = 5; - buf[sizeof(buf) - len] = '\0'; - sprintf(buf + strlen(buf), "%d", netif.if_unit % 10000); - return strdup(buf); -# endif -#endif -} @@ -1,8 +1,8 @@ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. - * $Id: kmem.h,v 2.5 2002/08/21 22:57:36 darrenr Exp $ + * $Id$ */ #ifndef __KMEM_H__ diff --git a/l4check/Makefile b/l4check/Makefile index e2bb9f8b3cff1..e7366b63ad6ae 100644 --- a/l4check/Makefile +++ b/l4check/Makefile @@ -4,7 +4,7 @@ all: l4check l4check: l4check.c - $(CC) -g -I.. -Wall $(CFLAGS) $(LIBS) l4check.c -o $@ + $(CC) -g -I.. $(CFLAGS) $(LIBS) l4check.c -o $@ clean: /bin/rm -f l4check diff --git a/l4check/l4check.c b/l4check/l4check.c index a096fffe44777..bf9d032f838bf 100644 --- a/l4check/l4check.c +++ b/l4check/l4check.c @@ -1,5 +1,5 @@ /* - * (C)Copyright March, 2000 - Darren Reed. + * (C)Copyright (C) 2012 by Darren Reed. */ #include <sys/types.h> #include <sys/stat.h> @@ -25,7 +25,6 @@ #include "ip_compat.h" #include "ip_fil.h" #include "ip_nat.h" -#include "ipl.h" #include "ipf.h" @@ -66,7 +65,7 @@ int opts = 0; char *copystr(dst, src) -char *dst, *src; + char *dst, *src; { register char *s, *t, c; register int esc = 0; @@ -95,44 +94,29 @@ char *dst, *src; } void addnat(l4) -l4cfg_t *l4; + l4cfg_t *l4; { - ipnat_t *ipn = &l4->l4_nat; - printf("Add NAT rule for %s/%#x,%u -> ", inet_ntoa(ipn->in_out[0].in4), + printf("Add NAT rule for %s/%#x,%u -> ", inet_ntoa(ipn->in_out[0]), ipn->in_outmsk, ntohs(ipn->in_pmin)); - printf("%s,%u\n", inet_ntoa(ipn->in_in[0].in4), ntohs(ipn->in_pnext)); + printf("%s,%u\n", inet_ntoa(ipn->in_in[0]), ntohs(ipn->in_pnext)); if (!(opts & OPT_DONOTHING)) { - ipfobj_t obj; - - bzero(&obj, sizeof(obj)); - obj.ipfo_rev = IPFILTER_VERSION; - obj.ipfo_size = sizeof(*ipn); - obj.ipfo_ptr = ipn; - - if (ioctl(natfd, SIOCADNAT, &obj) == -1) + if (ioctl(natfd, SIOCADNAT, &ipn) == -1) perror("ioctl(SIOCADNAT)"); } } void delnat(l4) -l4cfg_t *l4; + l4cfg_t *l4; { ipnat_t *ipn = &l4->l4_nat; printf("Remove NAT rule for %s/%#x,%u -> ", - inet_ntoa(ipn->in_out[0].in4), ipn->in_outmsk, ipn->in_pmin); - printf("%s,%u\n", inet_ntoa(ipn->in_in[0].in4), ipn->in_pnext); + inet_ntoa(ipn->in_out[0]), ipn->in_outmsk, ipn->in_pmin); + printf("%s,%u\n", inet_ntoa(ipn->in_in[0]), ipn->in_pnext); if (!(opts & OPT_DONOTHING)) { - ipfobj_t obj; - - bzero(&obj, sizeof(obj)); - obj.ipfo_rev = IPFILTER_VERSION; - obj.ipfo_size = sizeof(*ipn); - obj.ipfo_ptr = ipn; - if (ioctl(natfd, SIOCRMNAT, &ipn) == -1) perror("ioctl(SIOCRMNAT)"); } @@ -140,7 +124,7 @@ l4cfg_t *l4; void connectl4(l4) -l4cfg_t *l4; + l4cfg_t *l4; { l4->l4_rw = 1; l4->l4_rlen = 0; @@ -154,8 +138,8 @@ l4cfg_t *l4; void closel4(l4, dead) -l4cfg_t *l4; -int dead; + l4cfg_t *l4; + int dead; { close(l4->l4_fd); l4->l4_fd = -1; @@ -168,7 +152,7 @@ int dead; void connectfd(l4) -l4cfg_t *l4; + l4cfg_t *l4; { if (connect(l4->l4_fd, (struct sockaddr *)&l4->l4_sin, sizeof(l4->l4_sin)) == -1) { @@ -190,8 +174,9 @@ l4cfg_t *l4; void writefd(l4) -l4cfg_t *l4; + l4cfg_t *l4; { + char buf[80], *ptr; int n, i, fd; fd = l4->l4_fd; @@ -221,7 +206,7 @@ l4cfg_t *l4; void readfd(l4) -l4cfg_t *l4; + l4cfg_t *l4; { char buf[80], *ptr; int n, i, fd; @@ -415,14 +400,15 @@ int runconfig() int gethostport(str, lnum, ipp, portp) -char *str; -int lnum; -u_32_t *ipp; -u_short *portp; + char *str; + int lnum; + u_32_t *ipp; + u_short *portp; { struct servent *sp; struct hostent *hp; char *host, *port; + struct in_addr ip; host = str; port = strchr(host, ','); @@ -465,8 +451,8 @@ u_short *portp; char *mapfile(file, sizep) -char *file; -size_t *sizep; + char *file; + size_t *sizep; { struct stat sb; caddr_t addr; @@ -497,7 +483,7 @@ size_t *sizep; int readconfig(filename) -char *filename; + char *filename; { char c, buf[512], *s, *t, *errtxt = NULL, *line; int num, err = 0; @@ -567,8 +553,7 @@ char *filename; break; } - strncpy(ipn->in_ifnames[0], s, LIFNAMSIZ); - strncpy(ipn->in_ifnames[1], s, LIFNAMSIZ); + strncpy(ipn->in_ifname, s, sizeof(ipn->in_ifname)); if (!gethostport(t, num, &ipn->in_outip, &ipn->in_pmin)) { errtxt = line; @@ -580,11 +565,11 @@ char *filename; if (opts & OPT_VERBOSE) fprintf(stderr, "Interface %s %s/%#x port %u\n", - ipn->in_ifnames[0], - inet_ntoa(ipn->in_out[0].in4), + ipn->in_ifname, + inet_ntoa(ipn->in_out[0]), ipn->in_outmsk, ipn->in_pmin); } else if (!strcasecmp(t, "remote")) { - if (!*ipn->in_ifnames[0]) { + if (!*ipn->in_ifname) { fprintf(stderr, "%d: ifname not set prior to remote\n", num); @@ -619,7 +604,7 @@ char *filename; break; } bcopy((char *)&template, (char *)l4, sizeof(*l4)); - l4->l4_sin.sin_addr = ipn->in_in[0].in4; + l4->l4_sin.sin_addr = ipn->in_in[0]; l4->l4_sin.sin_port = ipn->in_pnext; l4->l4_next = l4list; l4list = l4; @@ -766,7 +751,7 @@ char *filename; void usage(prog) -char *prog; + char *prog; { fprintf(stderr, "Usage: %s -f <configfile>\n", prog); exit(1); @@ -774,8 +759,8 @@ char *prog; int main(argc, argv) -int argc; -char *argv[]; + int argc; + char *argv[]; { char *config = NULL; int c; @@ -806,7 +791,7 @@ char *argv[]; } if (!(opts & OPT_DONOTHING)) { - natfd = open(IPNAT_NAME, O_RDWR); + natfd = open(IPL_NAT, O_RDWR); if (natfd == -1) { perror("open(IPL_NAT)"); exit(1); @@ -817,6 +802,4 @@ char *argv[]; fprintf(stderr, "Starting...\n"); while (runconfig() == 0) ; - - exit(1); } diff --git a/lib/Makefile b/lib/Makefile index a838063c674c9..fdda78ed41a66 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,27 +1,37 @@ # -# Copyright (C) 1993-2001 by Darren Reed. -# -# See the IPFILTER.LICENCE file for details on licencing. -# -# $Id: Makefile,v 1.41.2.14 2007/09/21 08:30:43 darrenr Exp $ -# +# Copyright (C) 2012 by Darren Reed. +# +# See the IPFILTER.LICENCE file for details on licencing. +# +# $Id$ +# INCDEP=$(TOP)/ip_compat.h $(TOP)/ip_fil.h $(TOP)/ipf.h LIBOBJS=$(DEST)/addicmp.o \ $(DEST)/addipopt.o \ $(DEST)/alist_free.o \ $(DEST)/alist_new.o \ + $(DEST)/allocmbt.o \ + $(DEST)/assigndefined.o \ $(DEST)/bcopywrap.o \ $(DEST)/binprint.o \ $(DEST)/buildopts.o \ $(DEST)/checkrev.o \ + $(DEST)/connecttcp.o \ $(DEST)/count6bits.o \ $(DEST)/count4bits.o \ $(DEST)/debug.o \ + $(DEST)/dupmbt.o \ + $(DEST)/familyname.o \ $(DEST)/facpri.o \ - $(DEST)/flags.o \ $(DEST)/fill6bits.o \ + $(DEST)/findword.o \ + $(DEST)/flags.o \ + $(DEST)/freembt.o \ + $(DEST)/ftov.o \ + $(DEST)/genmask.o \ $(DEST)/gethost.o \ + $(DEST)/geticmptype.o \ $(DEST)/getifname.o \ $(DEST)/getnattype.o \ $(DEST)/getport.o \ @@ -30,27 +40,30 @@ LIBOBJS=$(DEST)/addicmp.o \ $(DEST)/getsumd.o \ $(DEST)/hostname.o \ $(DEST)/icmpcode.o \ - $(DEST)/inet_addr.o \ + $(DEST)/icmptypename.o \ + $(DEST)/icmptypes.o \ $(DEST)/initparse.o \ + $(DEST)/interror.o \ $(DEST)/ionames.o \ - $(DEST)/ipoptsec.o \ $(DEST)/ipf_dotuning.o \ - $(DEST)/ipft_ef.o \ + $(DEST)/ipf_perror.o \ $(DEST)/ipft_hx.o \ $(DEST)/ipft_pc.o \ - $(DEST)/ipft_sn.o \ - $(DEST)/ipft_td.o \ $(DEST)/ipft_tx.o \ + $(DEST)/ipoptsec.o \ $(DEST)/kmem.o \ $(DEST)/kmemcpywrap.o \ $(DEST)/kvatoname.o \ $(DEST)/load_file.o \ + $(DEST)/load_dstlist.o \ + $(DEST)/load_dstlistnode.o \ $(DEST)/load_hash.o \ $(DEST)/load_hashnode.o \ $(DEST)/load_http.o \ $(DEST)/load_pool.o \ $(DEST)/load_poolnode.o \ $(DEST)/load_url.o \ + $(DEST)/msgdsize.o \ $(DEST)/mutex_emul.o \ $(DEST)/nametokva.o \ $(DEST)/nat_setgroupmap.o \ @@ -59,46 +72,74 @@ LIBOBJS=$(DEST)/addicmp.o \ $(DEST)/optprint.o \ $(DEST)/optprintv6.o \ $(DEST)/optvalue.o \ + $(DEST)/parsefields.o \ + $(DEST)/parseipfexpr.o \ + $(DEST)/parsewhoisline.o \ + $(DEST)/poolio.o \ $(DEST)/portname.o \ $(DEST)/print_toif.o \ + $(DEST)/printactiveaddr.o \ $(DEST)/printactivenat.o \ + $(DEST)/printaddr.o \ $(DEST)/printaps.o \ $(DEST)/printbuf.o \ + $(DEST)/printdstlist.o \ + $(DEST)/printdstlistdata.o \ + $(DEST)/printdstlistnode.o \ + $(DEST)/printdstlistpolicy.o \ + $(DEST)/printdstl_live.o \ + $(DEST)/printfieldhdr.o \ + $(DEST)/printfr.o \ + $(DEST)/printfraginfo.o \ $(DEST)/printhash.o \ $(DEST)/printhashdata.o \ $(DEST)/printhashnode.o \ $(DEST)/printhash_live.o \ + $(DEST)/printhost.o \ + $(DEST)/printhostmap.o \ + $(DEST)/printhostmask.o \ + $(DEST)/printifname.o \ $(DEST)/printip.o \ + $(DEST)/printipfexpr.o \ + $(DEST)/printlog.o \ + $(DEST)/printlookup.o \ + $(DEST)/printmask.o \ + $(DEST)/printnat.o \ + $(DEST)/printnataddr.o \ + $(DEST)/printnatfield.o \ + $(DEST)/printnatside.o \ $(DEST)/printpool.o \ $(DEST)/printpooldata.o \ + $(DEST)/printpoolfield.o \ $(DEST)/printpoolnode.o \ $(DEST)/printpool_live.o \ $(DEST)/printproto.o \ - $(DEST)/printfr.o \ - $(DEST)/printfraginfo.o \ - $(DEST)/printhostmap.o \ - $(DEST)/printifname.o \ - $(DEST)/printhostmask.o \ - $(DEST)/printlog.o \ - $(DEST)/printmask.o \ - $(DEST)/printnat.o \ $(DEST)/printportcmp.o \ $(DEST)/printpacket.o \ $(DEST)/printpacket6.o \ $(DEST)/printsbuf.o \ $(DEST)/printstate.o \ + $(DEST)/printstatefields.o \ + $(DEST)/printtcpflags.o \ $(DEST)/printtqtable.o \ $(DEST)/printtunable.o \ + $(DEST)/printunit.o \ $(DEST)/remove_hash.o \ $(DEST)/remove_hashnode.o \ $(DEST)/remove_pool.o \ $(DEST)/remove_poolnode.o \ $(DEST)/resetlexer.o \ $(DEST)/rwlock_emul.o \ + $(DEST)/save_execute.o \ + $(DEST)/save_file.o \ + $(DEST)/save_nothing.o \ + $(DEST)/save_syslog.o \ + $(DEST)/save_v1trap.o \ + $(DEST)/save_v2trap.o \ $(DEST)/tcpflags.o \ - $(DEST)/tcp_flags.o \ $(DEST)/var.o \ $(DEST)/verbose.o \ + $(DEST)/vtof.o \ $(DEST)/v6ionames.o \ $(DEST)/v6optvalue.o @@ -115,12 +156,18 @@ $(DEST)/alist_free.o: $(LIBSRC)/alist_free.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/alist_free.c -o $@ $(DEST)/alist_new.o: $(LIBSRC)/alist_new.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/alist_new.c -o $@ +$(DEST)/allocmbt.o: $(LIBSRC)/allocmbt.c $(INCDEP) + $(CC) $(CCARGS) -c $(LIBSRC)/allocmbt.c -o $@ +$(DEST)/assigndefined.o: $(LIBSRC)/assigndefined.c $(INCDEP) + $(CC) $(CCARGS) -c $(LIBSRC)/assigndefined.c -o $@ $(DEST)/bcopywrap.o: $(LIBSRC)/bcopywrap.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/bcopywrap.c -o $@ $(DEST)/binprint.o: $(LIBSRC)/binprint.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/binprint.c -o $@ $(DEST)/buildopts.o: $(LIBSRC)/buildopts.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/buildopts.c -o $@ +$(DEST)/connecttcp.o: $(LIBSRC)/connecttcp.c $(INCDEP) + $(CC) $(CCARGS) -c $(LIBSRC)/connecttcp.c -o $@ $(DEST)/count6bits.o: $(LIBSRC)/count6bits.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/count6bits.c -o $@ $(DEST)/checkrev.o: $(LIBSRC)/checkrev.c $(INCDEP) $(TOP)/ipl.h @@ -129,17 +176,31 @@ $(DEST)/count4bits.o: $(LIBSRC)/count4bits.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/count4bits.c -o $@ $(DEST)/debug.o: $(LIBSRC)/debug.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/debug.c -o $@ +$(DEST)/dupmbt.o: $(LIBSRC)/dupmbt.c $(INCDEP) + $(CC) $(CCARGS) -c $(LIBSRC)/dupmbt.c -o $@ $(DEST)/facpri.o: $(LIBSRC)/facpri.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/facpri.c -o $@ +$(DEST)/familyname.o: $(LIBSRC)/familyname.c $(INCDEP) + $(CC) $(CCARGS) -c $(LIBSRC)/familyname.c -o $@ $(DEST)/fill6bits.o: $(LIBSRC)/fill6bits.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/fill6bits.c -o $@ +$(DEST)/findword.o: $(LIBSRC)/findword.c $(INCDEP) + $(CC) $(CCARGS) -c $(LIBSRC)/findword.c -o $@ $(DEST)/flags.o: $(LIBSRC)/flags.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/flags.c -o $@ +$(DEST)/freembt.o: $(LIBSRC)/freembt.c $(INCDEP) + $(CC) $(CCARGS) -c $(LIBSRC)/freembt.c -o $@ +$(DEST)/ftov.o: $(LIBSRC)/ftov.c $(INCDEP) + $(CC) $(CCARGS) -c $(LIBSRC)/ftov.c -o $@ +$(DEST)/genmask.o: $(LIBSRC)/genmask.c $(INCDEP) + $(CC) $(CCARGS) -c $(LIBSRC)/genmask.c -o $@ $(DEST)/gethost.o: $(LIBSRC)/gethost.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/gethost.c -o $@ +$(DEST)/geticmptype.o: $(LIBSRC)/geticmptype.c $(INCDEP) + $(CC) $(CCARGS) -c $(LIBSRC)/geticmptype.c -o $@ $(DEST)/getifname.o: $(LIBSRC)/getifname.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/getifname.c -o $@ -$(DEST)/getnattype.o: $(LIBSRC)/getnattype.c $(INCDEP) +$(DEST)/getnattype.o: $(LIBSRC)/getnattype.c $(INCDEP) $(TOP)/ip_nat.h $(CC) $(CCARGS) -c $(LIBSRC)/getnattype.c -o $@ $(DEST)/getport.o: $(LIBSRC)/getport.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/getport.c -o $@ @@ -153,26 +214,26 @@ $(DEST)/hostname.o: $(LIBSRC)/hostname.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/hostname.c -o $@ $(DEST)/icmpcode.o: $(LIBSRC)/icmpcode.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/icmpcode.c -o $@ +$(DEST)/icmptypename.o: $(LIBSRC)/icmptypename.c $(INCDEP) + $(CC) $(CCARGS) -c $(LIBSRC)/icmptypename.c -o $@ +$(DEST)/icmptypes.o: $(LIBSRC)/icmptypes.c $(INCDEP) + $(CC) $(CCARGS) -c $(LIBSRC)/icmptypes.c -o $@ +$(DEST)/interror.o: $(LIBSRC)/interror.c $(INCDEP) + $(CC) $(CCARGS) -c $(LIBSRC)/interror.c -o $@ $(DEST)/ipoptsec.o: $(LIBSRC)/ipoptsec.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/ipoptsec.c -o $@ -$(DEST)/inet_addr.o: $(LIBSRC)/inet_addr.c $(INCDEP) - $(CC) $(CCARGS) -c $(LIBSRC)/inet_addr.c -o $@ $(DEST)/initparse.o: $(LIBSRC)/initparse.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/initparse.c -o $@ $(DEST)/ionames.o: $(LIBSRC)/ionames.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/ionames.c -o $@ $(DEST)/ipf_dotuning.o: $(LIBSRC)/ipf_dotuning.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/ipf_dotuning.c -o $@ -$(DEST)/ipft_ef.o: $(LIBSRC)/ipft_ef.c $(INCDEP) - $(CC) $(CCARGS) -c $(LIBSRC)/ipft_ef.c -o $@ +$(DEST)/ipf_perror.o: $(LIBSRC)/ipf_perror.c $(INCDEP) + $(CC) $(CCARGS) -c $(LIBSRC)/ipf_perror.c -o $@ $(DEST)/ipft_hx.o: $(LIBSRC)/ipft_hx.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/ipft_hx.c -o $@ $(DEST)/ipft_pc.o: $(LIBSRC)/ipft_pc.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/ipft_pc.c -o $@ -$(DEST)/ipft_sn.o: $(LIBSRC)/ipft_sn.c $(TOP)/snoop.h - $(CC) $(CCARGS) -c $(LIBSRC)/ipft_sn.c -o $@ -$(DEST)/ipft_td.o: $(LIBSRC)/ipft_td.c $(INCDEP) - $(CC) $(CCARGS) -c $(LIBSRC)/ipft_td.c -o $@ $(DEST)/ipft_tx.o: $(LIBSRC)/ipft_tx.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/ipft_tx.c -o $@ $(DEST)/kmem.o: $(LIBSRC)/kmem.c $(INCDEP) @@ -183,6 +244,11 @@ $(DEST)/kvatoname.o: $(LIBSRC)/kvatoname.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/kvatoname.c -o $@ $(DEST)/load_file.o: $(LIBSRC)/load_file.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/load_file.c -o $@ +$(DEST)/load_dstlist.o: $(LIBSRC)/load_dstlist.c $(INCDEP) $(TOP)/ip_dstlist.h + $(CC) $(CCARGS) -c $(LIBSRC)/load_dstlist.c -o $@ +$(DEST)/load_dstlistnode.o: $(LIBSRC)/load_dstlistnode.c $(INCDEP) \ + $(TOP)/ip_dstlist.h + $(CC) $(CCARGS) -c $(LIBSRC)/load_dstlistnode.c -o $@ $(DEST)/load_hash.o: $(LIBSRC)/load_hash.c $(INCDEP) $(TOP)/ip_htable.h $(CC) $(CCARGS) -c $(LIBSRC)/load_hash.c -o $@ $(DEST)/load_hashnode.o: $(LIBSRC)/load_hashnode.c $(INCDEP) $(TOP)/ip_htable.h @@ -195,8 +261,8 @@ $(DEST)/load_poolnode.o: $(LIBSRC)/load_poolnode.c $(INCDEP) $(TOP)/ip_pool.h $(CC) $(CCARGS) -c $(LIBSRC)/load_poolnode.c -o $@ $(DEST)/load_url.o: $(LIBSRC)/load_url.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/load_url.c -o $@ -$(DEST)/make_range.o: $(LIBSRC)/make_range.c $(INCDEP) - $(CC) $(CCARGS) -c $(LIBSRC)/make_range.c -o $@ +$(DEST)/msgdsize.o: $(LIBSRC)/msgdsize.c $(INCDEP) + $(CC) $(CCARGS) -c $(LIBSRC)/msgdsize.c -o $@ $(DEST)/mutex_emul.o: $(LIBSRC)/mutex_emul.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/mutex_emul.c -o $@ $(DEST)/nametokva.o: $(LIBSRC)/nametokva.c $(INCDEP) @@ -214,35 +280,78 @@ $(DEST)/optprintv6.o: $(LIBSRC)/optprintv6.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/optprintv6.c -o $@ $(DEST)/optvalue.o: $(LIBSRC)/optvalue.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/optvalue.c -o $@ +$(DEST)/parsefields.o: $(LIBSRC)/parsefields.c $(INCDEP) + $(CC) $(CCARGS) -c $(LIBSRC)/parsefields.c -o $@ +$(DEST)/parseipfexpr.o: $(LIBSRC)/parseipfexpr.c $(INCDEP) + $(CC) $(CCARGS) -c $(LIBSRC)/parseipfexpr.c -o $@ +$(DEST)/parsewhoisline.o: $(LIBSRC)/parsewhoisline.c $(INCDEP) + $(CC) $(CCARGS) -c $(LIBSRC)/parsewhoisline.c -o $@ +$(DEST)/poolio.o: $(LIBSRC)/poolio.c $(INCDEP) + $(CC) $(CCARGS) -c $(LIBSRC)/poolio.c -o $@ $(DEST)/portname.o: $(LIBSRC)/portname.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/portname.c -o $@ $(DEST)/print_toif.o: $(LIBSRC)/print_toif.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/print_toif.c -o $@ -$(DEST)/printactivenat.o: $(LIBSRC)/printactivenat.c $(INCDEP) +$(DEST)/printactiveaddr.o: $(LIBSRC)/printactiveaddr.c $(INCDEP) $(TOP)/ip_nat.h + $(CC) $(CCARGS) -c $(LIBSRC)/printactiveaddr.c -o $@ +$(DEST)/printactivenat.o: $(LIBSRC)/printactivenat.c $(INCDEP) $(TOP)/ip_nat.h $(CC) $(CCARGS) -c $(LIBSRC)/printactivenat.c -o $@ +$(DEST)/printaddr.o: $(LIBSRC)/printaddr.c $(INCDEP) + $(CC) $(CCARGS) -c $(LIBSRC)/printaddr.c -o $@ $(DEST)/printaps.o: $(LIBSRC)/printaps.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/printaps.c -o $@ $(DEST)/printbuf.o: $(LIBSRC)/printbuf.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/printbuf.c -o $@ +$(DEST)/printdstlist.o: $(LIBSRC)/printdstlist.c $(INCDEP) $(TOP)/ip_dstlist.h + $(CC) $(CCARGS) -c $(LIBSRC)/printdstlist.c -o $@ +$(DEST)/printdstlistdata.o: $(LIBSRC)/printdstlistdata.c $(INCDEP) \ + $(TOP)/ip_dstlist.h + $(CC) $(CCARGS) -c $(LIBSRC)/printdstlistdata.c -o $@ +$(DEST)/printdstlistnode.o: $(LIBSRC)/printdstlistnode.c $(INCDEP) \ + $(TOP)/ip_dstlist.h + $(CC) $(CCARGS) -c $(LIBSRC)/printdstlistnode.c -o $@ +$(DEST)/printdstlistpolicy.o: $(LIBSRC)/printdstlistpolicy.c $(INCDEP) \ + $(TOP)/ip_dstlist.h + $(CC) $(CCARGS) -c $(LIBSRC)/printdstlistpolicy.c -o $@ +$(DEST)/printfieldhdr.o: $(LIBSRC)/printfieldhdr.c $(TOP)/ip_fil.h + $(CC) $(CCARGS) -c $(LIBSRC)/printfieldhdr.c -o $@ $(DEST)/printfr.o: $(LIBSRC)/printfr.c $(TOP)/ip_fil.h $(CC) $(CCARGS) -c $(LIBSRC)/printfr.c -o $@ -$(DEST)/printfraginfo.o: $(LIBSRC)/printfraginfo.c $(TOP)/ip_fil.h +$(DEST)/printfraginfo.o: $(LIBSRC)/printfraginfo.c $(TOP)/ip_fil.h \ + $(TOP)/ip_frag.h $(CC) $(CCARGS) -c $(LIBSRC)/printfraginfo.c -o $@ $(DEST)/printhash.o: $(LIBSRC)/printhash.c $(TOP)/ip_fil.h $(TOP)/ip_htable.h $(CC) $(CCARGS) -c $(LIBSRC)/printhash.c -o $@ -$(DEST)/printhashdata.o: $(LIBSRC)/printhash.c $(TOP)/ip_fil.h $(TOP)/ip_htable.h +$(DEST)/printhashdata.o: $(LIBSRC)/printhashdata.c $(TOP)/ip_fil.h \ + $(TOP)/ip_htable.h $(CC) $(CCARGS) -c $(LIBSRC)/printhashdata.c -o $@ $(DEST)/printhashnode.o: $(LIBSRC)/printhashnode.c $(TOP)/ip_fil.h \ $(TOP)/ip_htable.h $(TOP)/ip_lookup.h $(CC) $(CCARGS) -c $(LIBSRC)/printhashnode.c -o $@ -$(DEST)/printhash_live.o: $(LIBSRC)/printhash_live.c $(TOP)/ip_fil.h $(TOP)/ip_htable.h +$(DEST)/printhash_live.o: $(LIBSRC)/printhash_live.c $(TOP)/ip_fil.h \ + $(TOP)/ip_htable.h $(CC) $(CCARGS) -c $(LIBSRC)/printhash_live.c -o $@ +$(DEST)/printdstl_live.o: $(LIBSRC)/printdstl_live.c $(TOP)/ip_fil.h \ + $(TOP)/ip_dstlist.h + $(CC) $(CCARGS) -c $(LIBSRC)/printdstl_live.c -o $@ $(DEST)/printip.o: $(LIBSRC)/printip.c $(TOP)/ip_fil.h $(CC) $(CCARGS) -c $(LIBSRC)/printip.c -o $@ +$(DEST)/printipfexpr.o: $(LIBSRC)/printipfexpr.c $(TOP)/ip_fil.h + $(CC) $(CCARGS) -c $(LIBSRC)/printipfexpr.c -o $@ +$(DEST)/printlookup.o: $(LIBSRC)/printlookup.c $(INCDEP) + $(CC) $(CCARGS) -c $(LIBSRC)/printlookup.c -o $@ +$(DEST)/printnataddr.o: $(LIBSRC)/printnataddr.c $(INCDEP) $(TOP)/ip_nat.h + $(CC) $(CCARGS) -c $(LIBSRC)/printnataddr.c -o $@ +$(DEST)/printnatside.o: $(LIBSRC)/printnatside.c $(INCDEP) $(TOP)/ip_nat.h + $(CC) $(CCARGS) -c $(LIBSRC)/printnatside.c -o $@ $(DEST)/printpool.o: $(LIBSRC)/printpool.c $(TOP)/ip_fil.h $(TOP)/ip_pool.h $(CC) $(CCARGS) -c $(LIBSRC)/printpool.c -o $@ -$(DEST)/printpooldata.o: $(LIBSRC)/printpooldata.c $(TOP)/ip_fil.h $(TOP)/ip_pool.h +$(DEST)/printpooldata.o: $(LIBSRC)/printpooldata.c $(TOP)/ip_fil.h \ + $(TOP)/ip_pool.h $(TOP)/ip_lookup.h $(CC) $(CCARGS) -c $(LIBSRC)/printpooldata.c -o $@ +$(DEST)/printpoolfield.o: $(LIBSRC)/printpoolfield.c $(TOP)/ip_fil.h \ + $(TOP)/ip_pool.h $(TOP)/ip_lookup.h + $(CC) $(CCARGS) -c $(LIBSRC)/printpoolfield.c -o $@ $(DEST)/printpoolnode.o: $(LIBSRC)/printpoolnode.c $(TOP)/ip_fil.h \ $(TOP)/ip_pool.h $(TOP)/ip_lookup.h $(CC) $(CCARGS) -c $(LIBSRC)/printpoolnode.c -o $@ @@ -251,14 +360,18 @@ $(DEST)/printpool_live.o: $(LIBSRC)/printpool_live.c $(TOP)/ip_fil.h \ $(CC) $(CCARGS) -c $(LIBSRC)/printpool_live.c -o $@ $(DEST)/printproto.o: $(LIBSRC)/printproto.c $(TOP)/ip_fil.h $(CC) $(CCARGS) -c $(LIBSRC)/printproto.c -o $@ +$(DEST)/printhost.o: $(LIBSRC)/printhost.c $(TOP)/ip_fil.h + $(CC) $(CCARGS) -c $(LIBSRC)/printhost.c -o $@ $(DEST)/printhostmap.o: $(LIBSRC)/printhostmap.c $(TOP)/ip_fil.h $(CC) $(CCARGS) -c $(LIBSRC)/printhostmap.c -o $@ $(DEST)/printifname.o: $(LIBSRC)/printifname.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/printifname.c -o $@ $(DEST)/printmask.o: $(LIBSRC)/printmask.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/printmask.c -o $@ -$(DEST)/printnat.o: $(LIBSRC)/printnat.c $(INCDEP) +$(DEST)/printnat.o: $(LIBSRC)/printnat.c $(INCDEP) $(TOP)/ip_nat.h $(CC) $(CCARGS) -c $(LIBSRC)/printnat.c -o $@ +$(DEST)/printnatfield.o: $(LIBSRC)/printnatfield.c $(INCDEP) $(TOP)/ip_nat.h + $(CC) $(CCARGS) -c $(LIBSRC)/printnatfield.c -o $@ $(DEST)/printhostmask.o: $(LIBSRC)/printhostmask.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/printhostmask.c -o $@ $(DEST)/printlog.o: $(LIBSRC)/printlog.c $(INCDEP) @@ -273,10 +386,16 @@ $(DEST)/printsbuf.o: $(LIBSRC)/printsbuf.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/printsbuf.c -o $@ $(DEST)/printstate.o: $(LIBSRC)/printstate.c $(INCDEP) $(TOP)/ip_state.h $(CC) $(CCARGS) -c $(LIBSRC)/printstate.c -o $@ +$(DEST)/printstatefields.o: $(LIBSRC)/printstatefields.c $(INCDEP) $(TOP)/ip_state.h + $(CC) $(CCARGS) -c $(LIBSRC)/printstatefields.c -o $@ +$(DEST)/printtcpflags.o: $(LIBSRC)/printtcpflags.c $(INCDEP) + $(CC) $(CCARGS) -c $(LIBSRC)/printtcpflags.c -o $@ $(DEST)/printtqtable.o: $(LIBSRC)/printtqtable.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/printtqtable.c -o $@ $(DEST)/printtunable.o: $(LIBSRC)/printtunable.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/printtunable.c -o $@ +$(DEST)/printunit.o: $(LIBSRC)/printunit.c $(INCDEP) + $(CC) $(CCARGS) -c $(LIBSRC)/printunit.c -o $@ $(DEST)/remove_hash.o: $(LIBSRC)/remove_hash.c $(INCDEP) \ $(TOP)/ip_htable.h $(CC) $(CCARGS) -c $(LIBSRC)/remove_hash.c -o $@ @@ -301,6 +420,20 @@ $(DEST)/var.o: $(LIBSRC)/var.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/var.c -o $@ $(DEST)/verbose.o: $(LIBSRC)/verbose.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/verbose.c -o $@ +$(DEST)/save_execute.o: $(LIBSRC)/save_execute.c $(TOP)/ipl.h + $(CC) $(CCARGS) -c $(LIBSRC)/save_execute.c -o $@ +$(DEST)/save_file.o: $(LIBSRC)/save_file.c $(TOP)/ipl.h + $(CC) $(CCARGS) -c $(LIBSRC)/save_file.c -o $@ +$(DEST)/save_nothing.o: $(LIBSRC)/save_nothing.c $(TOP)/ipl.h + $(CC) $(CCARGS) -c $(LIBSRC)/save_nothing.c -o $@ +$(DEST)/save_syslog.o: $(LIBSRC)/save_syslog.c $(TOP)/ipl.h + $(CC) $(CCARGS) -c $(LIBSRC)/save_syslog.c -o $@ +$(DEST)/vtof.o: $(LIBSRC)/vtof.c $(INCDEP) + $(CC) $(CCARGS) -c $(LIBSRC)/vtof.c -o $@ +$(DEST)/save_v1trap.o: $(LIBSRC)/save_v1trap.c $(TOP)/ipl.h + $(CC) $(CCARGS) -c $(LIBSRC)/save_v1trap.c -o $@ +$(DEST)/save_v2trap.o: $(LIBSRC)/save_v2trap.c $(TOP)/ipl.h + $(CC) $(CCARGS) -c $(LIBSRC)/save_v2trap.c -o $@ $(DEST)/v6ionames.o: $(LIBSRC)/v6ionames.c $(INCDEP) $(CC) $(CCARGS) -c $(LIBSRC)/v6ionames.c -o $@ $(DEST)/v6optvalue.o: $(LIBSRC)/v6optvalue.c $(INCDEP) diff --git a/lib/addicmp.c b/lib/addicmp.c index 256739786b17e..739ce09502927 100644 --- a/lib/addicmp.c +++ b/lib/addicmp.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2000-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: addicmp.c,v 1.10.2.5 2006/06/16 17:20:55 darrenr Exp $ + * $Id$ */ #include <ctype.h> diff --git a/lib/addipopt.c b/lib/addipopt.c index 17fac0dc2c8ea..cb06da996c70b 100644 --- a/lib/addipopt.c +++ b/lib/addipopt.c @@ -1,19 +1,19 @@ /* - * Copyright (C) 2000-2002 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: addipopt.c,v 1.7.4.1 2006/06/16 17:20:56 darrenr Exp $ + * $Id$ */ #include "ipf.h" int addipopt(op, io, len, class) -char *op; -struct ipopt_names *io; -int len; -char *class; + char *op; + struct ipopt_names *io; + int len; + char *class; { int olen = len; struct in_addr ipadr; @@ -39,6 +39,10 @@ char *class; lvl = seclevel(class); *(op - 1) = lvl; break; + case IPOPT_RR : + case IPOPT_TS : + s[IPOPT_OLEN] = IPOPT_MINOFF - 1 + 4; + break; case IPOPT_LSRR : case IPOPT_SSRR : ipadr.s_addr = inet_addr(class); @@ -51,12 +55,6 @@ char *class; break; } } - - op += io->on_siz - 3; - if (len & 3) { - *op++ = IPOPT_NOP; - len++; - } } if (opts & OPT_DEBUG) fprintf(stderr, "bo: %s %d %#x: %d\n", diff --git a/lib/addkeep.c b/lib/addkeep.c deleted file mode 100644 index bbc7759fbc931..0000000000000 --- a/lib/addkeep.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: addkeep.c,v 1.12 2003/12/01 01:59:42 darrenr Exp $ - */ - -#include "ipf.h" - - -/* - * Parses "keep state" and "keep frags" stuff on the end of a line. - */ -int addkeep(cp, fp, linenum) -char ***cp; -struct frentry *fp; -int linenum; -{ - char *s; - - (*cp)++; - if (!**cp) { - fprintf(stderr, "%d: Missing state/frag after keep\n", - linenum); - return -1; - } - - if (!strcasecmp(**cp, "state")) { - fp->fr_flags |= FR_KEEPSTATE; - (*cp)++; - if (**cp && !strcasecmp(**cp, "limit")) { - (*cp)++; - fp->fr_statemax = atoi(**cp); - (*cp)++; - } - if (**cp && !strcasecmp(**cp, "scan")) { - (*cp)++; - if (!strcmp(**cp, "*")) { - fp->fr_isc = NULL; - fp->fr_isctag[0] = '\0'; - } else { - strncpy(fp->fr_isctag, **cp, - sizeof(fp->fr_isctag)); - fp->fr_isctag[sizeof(fp->fr_isctag)-1] = '\0'; - fp->fr_isc = NULL; - } - (*cp)++; - } else - fp->fr_isc = (struct ipscan *)-1; - } else if (!strncasecmp(**cp, "frag", 4)) { - fp->fr_flags |= FR_KEEPFRAG; - (*cp)++; - } else if (!strcasecmp(**cp, "state-age")) { - if (fp->fr_ip.fi_p == IPPROTO_TCP) { - fprintf(stderr, "%d: cannot use state-age with tcp\n", - linenum); - return -1; - } - if ((fp->fr_flags & FR_KEEPSTATE) == 0) { - fprintf(stderr, "%d: state-age with no 'keep state'\n", - linenum); - return -1; - } - (*cp)++; - if (!**cp) { - fprintf(stderr, "%d: state-age with no arg\n", - linenum); - return -1; - } - fp->fr_age[0] = atoi(**cp); - s = strchr(**cp, '/'); - if (s != NULL) { - s++; - fp->fr_age[1] = atoi(s); - } else - fp->fr_age[1] = fp->fr_age[0]; - } else { - fprintf(stderr, "%d: Unrecognised state keyword \"%s\"\n", - linenum, **cp); - return -1; - } - return 0; -} diff --git a/lib/alist_free.c b/lib/alist_free.c index 3c1a518804307..44dea1330f814 100644 --- a/lib/alist_free.c +++ b/lib/alist_free.c @@ -1,15 +1,15 @@ /* - * Copyright (C) 2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: alist_free.c,v 1.1.2.1 2006/08/25 21:13:04 darrenr Exp $ + * $Id: alist_free.c,v 1.3.2.2 2012/07/22 08:04:24 darren_r Exp $ */ #include "ipf.h" void alist_free(hosts) -alist_t *hosts; + alist_t *hosts; { alist_t *a, *next; diff --git a/lib/alist_new.c b/lib/alist_new.c index 50a4275e7d540..73bc03073990f 100644 --- a/lib/alist_new.c +++ b/lib/alist_new.c @@ -1,20 +1,30 @@ /* - * Copyright (C) 2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: alist_new.c,v 1.1.2.3 2007/06/06 08:05:33 darrenr Exp $ + * $Id: alist_new.c,v 1.5.2.2 2012/07/22 08:04:24 darren_r Exp $ */ #include "ipf.h" +#include <ctype.h> -alist_t * -alist_new(int v, char *host) +alist_t * +alist_new(int family, char *host) { int a, b, c, d, bits; - char *slash; - alist_t *al; - u_int mask; + char *slash; + alist_t *al; + u_int mask; + + if (family == AF_UNSPEC) { + if (strchr(host, ':') != NULL) + family = AF_INET6; + else + family = AF_INET; + } + if (family != AF_INET && family != AF_INET6) + return NULL; al = calloc(1, sizeof(*al)); if (al == NULL) { @@ -22,45 +32,62 @@ alist_new(int v, char *host) return NULL; } - bits = -1; + while (ISSPACE(*host)) + host++; + + if (*host == '!') { + al->al_not = 1; + host++; + while (ISSPACE(*host)) + host++; + } + + bits = -1; slash = strchr(host, '/'); if (slash != NULL) { *slash = '\0'; bits = atoi(slash + 1); } - a = b = c = d = -1; - sscanf(host, "%d.%d.%d.%d", &a, &b, &c, &d); + if (family == AF_INET) { + if (bits > 32) + goto bad; - if (bits > 0 && bits < 33) { - mask = 0xffffffff << (32 - bits); - } else if (b == -1) { - mask = 0xff000000; - b = c = d = 0; - } else if (c == -1) { - mask = 0xffff0000; - c = d = 0; - } else if (d == -1) { - mask = 0xffffff00; - d = 0; - } else { - mask = 0xffffffff; - } + a = b = c = d = -1; + sscanf(host, "%d.%d.%d.%d", &a, &b, &c, &d); - if (*host == '!') { - al->al_not = 1; - host++; + if (bits > 0 && bits < 33) { + mask = 0xffffffff << (32 - bits); + } else if (b == -1) { + mask = 0xff000000; + b = c = d = 0; + } else if (c == -1) { + mask = 0xffff0000; + c = d = 0; + } else if (d == -1) { + mask = 0xffffff00; + d = 0; + } else { + mask = 0xffffffff; + } + al->al_mask = htonl(mask); + } else { + if (bits > 128) + goto bad; + fill6bits(bits, al->al_i6mask.i6); } - if (gethost(host, &al->al_addr) == -1) { + if (gethost(family, host, &al->al_i6addr) == -1) { if (slash != NULL) *slash = '/'; fprintf(stderr, "Cannot parse hostname\n"); - free(al); - return NULL; + goto bad; } - al->al_mask = htonl(mask); + al->al_family = family; if (slash != NULL) *slash = '/'; return al; +bad: + free(al); + return NULL; } diff --git a/lib/allocmbt.c b/lib/allocmbt.c new file mode 100644 index 0000000000000..df776842736c8 --- /dev/null +++ b/lib/allocmbt.c @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: allocmbt.c,v 1.1.4.1 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" + +mb_t *allocmbt(size_t len) +{ + mb_t *m; + + m = (mb_t *)malloc(sizeof(mb_t)); + if (m == NULL) + return NULL; + m->mb_len = len; + m->mb_next = NULL; + m->mb_data = (char *)m->mb_buf; + return m; +} diff --git a/lib/assigndefined.c b/lib/assigndefined.c new file mode 100644 index 0000000000000..34f8d9af3accb --- /dev/null +++ b/lib/assigndefined.c @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: assigndefined.c,v 1.4.2.2 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" + +void assigndefined(env) + char *env; +{ + char *s, *t; + + if (env == NULL) + return; + + for (s = strtok(env, ";"); s != NULL; s = strtok(NULL, ";")) { + t = strchr(s, '='); + if (t == NULL) + continue; + *t++ = '\0'; + set_variable(s, t); + *--t = '='; + } +} diff --git a/lib/bcopywrap.c b/lib/bcopywrap.c index 83fd04b346347..d6ebac1da46ca 100644 --- a/lib/bcopywrap.c +++ b/lib/bcopywrap.c @@ -1,16 +1,16 @@ /* - * Copyright (C) 2002 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: bcopywrap.c,v 1.1.4.1 2006/06/16 17:20:56 darrenr Exp $ - */ + * + * $Id$ + */ #include "ipf.h" int bcopywrap(from, to, size) -void *from, *to; -size_t size; + void *from, *to; + size_t size; { bcopy((caddr_t)from, (caddr_t)to, size); return 0; diff --git a/lib/binprint.c b/lib/binprint.c index 4eb38280763cf..20cb058ece565 100644 --- a/lib/binprint.c +++ b/lib/binprint.c @@ -1,17 +1,17 @@ /* - * Copyright (C) 2000-2002 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: binprint.c,v 1.8.4.1 2006/06/16 17:20:56 darrenr Exp $ + * $Id$ */ #include "ipf.h" void binprint(ptr, size) -void *ptr; -size_t size; + void *ptr; + size_t size; { u_char *s; int i, j; diff --git a/lib/buildopts.c b/lib/buildopts.c index d493f5e8de76a..bd4b599b1e87b 100644 --- a/lib/buildopts.c +++ b/lib/buildopts.c @@ -1,17 +1,17 @@ /* - * Copyright (C) 2000-2002 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: buildopts.c,v 1.6.4.1 2006/06/16 17:20:56 darrenr Exp $ + * $Id$ */ #include "ipf.h" u_32_t buildopts(cp, op, len) -char *cp, *op; -int len; + char *cp, *op; + int len; { struct ipopt_names *io; u_32_t msk = 0; @@ -21,6 +21,8 @@ int len; for (s = strtok(cp, ","); s; s = strtok(NULL, ",")) { if ((t = strchr(s, '='))) *t++ = '\0'; + else + t = ""; for (io = ionames; io->on_name; io++) { if (strcasecmp(s, io->on_name) || (msk & io->on_bit)) continue; @@ -36,6 +38,10 @@ int len; return 0; } } + while ((len & 3) != 3) { + *op++ = IPOPT_NOP; + len++; + } *op++ = IPOPT_EOL; len++; return len; diff --git a/lib/checkrev.c b/lib/checkrev.c index 3c40226a98cff..0b686f8af2acf 100644 --- a/lib/checkrev.c +++ b/lib/checkrev.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2000-2004 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: checkrev.c,v 1.12.2.2 2006/06/16 17:20:56 darrenr Exp $ + * $Id$ */ #include <sys/ioctl.h> @@ -13,25 +13,25 @@ #include "netinet/ipl.h" int checkrev(ipfname) -char *ipfname; + char *ipfname; { static int vfd = -1; - struct friostat fio, *fiop = &fio; - ipfobj_t ipfo; + struct friostat fio; + ipfobj_t obj; - bzero((caddr_t)&ipfo, sizeof(ipfo)); - ipfo.ipfo_rev = IPFILTER_VERSION; - ipfo.ipfo_size = sizeof(*fiop); - ipfo.ipfo_ptr = (void *)fiop; - ipfo.ipfo_type = IPFOBJ_IPFSTAT; + bzero((caddr_t)&obj, sizeof(obj)); + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_size = sizeof(fio); + obj.ipfo_ptr = (void *)&fio; + obj.ipfo_type = IPFOBJ_IPFSTAT; if ((vfd == -1) && ((vfd = open(ipfname, O_RDONLY)) == -1)) { perror("open device"); return -1; } - if (ioctl(vfd, SIOCGETFS, &ipfo)) { - perror("ioctl(SIOCGETFS)"); + if (ioctl(vfd, SIOCGETFS, &obj)) { + ipferror(vfd, "ioctl(SIOCGETFS)"); close(vfd); vfd = -1; return -1; diff --git a/lib/connecttcp.c b/lib/connecttcp.c new file mode 100644 index 0000000000000..2bab2afe0daa0 --- /dev/null +++ b/lib/connecttcp.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: connecttcp.c,v 1.3.2.2 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" +#include <ctype.h> + +/* + * Format expected is one addres per line, at the start of each line. + */ +int +connecttcp(char *server, int port) +{ + struct sockaddr_in sin; + struct hostent *host; + int fd; + + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(port & 65535); + + if (ISDIGIT(*server)) { + if (inet_aton(server, &sin.sin_addr) == -1) { + return -1; + } + } else { + host = gethostbyname(server); + if (host == NULL) + return -1; + memcpy(&sin.sin_addr, host->h_addr_list[0], + sizeof(sin.sin_addr)); + } + + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd == -1) + return -1; + + if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) { + close(fd); + return -1; + } + + return fd; +} diff --git a/lib/count4bits.c b/lib/count4bits.c index 51e60252b3bf1..c91f707510ba0 100644 --- a/lib/count4bits.c +++ b/lib/count4bits.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2002 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: count4bits.c,v 1.1.4.1 2006/06/16 17:20:57 darrenr Exp $ + * $Id$ */ #include "ipf.h" @@ -15,7 +15,7 @@ * of bits. */ int count4bits(ip) -u_int ip; + u_int ip; { int cnt = 0, i, j; u_int ipn; diff --git a/lib/count6bits.c b/lib/count6bits.c index be090b7be30de..e354ad022a5a0 100644 --- a/lib/count6bits.c +++ b/lib/count6bits.c @@ -1,16 +1,16 @@ /* - * Copyright (C) 2000-2001 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: count6bits.c,v 1.4.4.1 2006/06/16 17:20:57 darrenr Exp $ + * $Id$ */ #include "ipf.h" int count6bits(msk) -u_32_t *msk; + u_32_t *msk; { int i = 0, k; u_32_t j; diff --git a/lib/debug.c b/lib/debug.c index 144bc0231a06c..c442983b4f23a 100644 --- a/lib/debug.c +++ b/lib/debug.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2000-2001 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: debug.c,v 1.6.4.1 2006/06/16 17:20:57 darrenr Exp $ + * $Id$ */ #if defined(__STDC__) @@ -13,16 +13,37 @@ #endif #include <stdio.h> -#include "ipt.h" +#include "ipf.h" #include "opts.h" +int debuglevel = 0; + + +#ifdef __STDC__ +void debug(int level, char *fmt, ...) +#else +void debug(level, fmt, va_alist) + int level; + char *fmt; + va_dcl +#endif +{ + va_list pvar; + + va_start(pvar, fmt); + + if ((debuglevel > 0) && (level <= debuglevel)) + vfprintf(stderr, fmt, pvar); + va_end(pvar); +} + #ifdef __STDC__ -void debug(char *fmt, ...) +void ipfkdebug(char *fmt, ...) #else -void debug(fmt, va_alist) -char *fmt; -va_dcl +void ipfkdebug(fmt, va_alist) + char *fmt; + va_dcl #endif { va_list pvar; @@ -30,6 +51,6 @@ va_dcl va_start(pvar, fmt); if (opts & OPT_DEBUG) - vprintf(fmt, pvar); + debug(0x1fffffff, fmt, pvar); va_end(pvar); } diff --git a/lib/dupmbt.c b/lib/dupmbt.c new file mode 100644 index 0000000000000..0929eeb54229c --- /dev/null +++ b/lib/dupmbt.c @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: dupmbt.c,v 1.3.2.2 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" + +mb_t *dupmbt(orig) + mb_t *orig; +{ + mb_t *m; + + m = (mb_t *)malloc(sizeof(mb_t)); + if (m == NULL) + return NULL; + m->mb_len = orig->mb_len; + m->mb_next = NULL; + m->mb_data = (char *)m->mb_buf + (orig->mb_data - (char *)orig->mb_buf); + bcopy(orig->mb_data, m->mb_data, m->mb_len); + return m; +} diff --git a/lib/extras.c b/lib/extras.c deleted file mode 100644 index 9087ca69c1ab2..0000000000000 --- a/lib/extras.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: extras.c,v 1.12 2002/07/13 12:06:49 darrenr Exp $ - */ - -#include "ipf.h" - - -/* - * deal with extra bits on end of the line - */ -int extras(cp, fr, linenum) -char ***cp; -struct frentry *fr; -int linenum; -{ - u_short secmsk; - u_long opts; - int notopt; - - opts = 0; - secmsk = 0; - notopt = 0; - (*cp)++; - if (!**cp) - return -1; - - while (**cp) { - if (!strcasecmp(**cp, "not") || !strcasecmp(**cp, "no")) { - notopt = 1; - (*cp)++; - continue; - } else if (!strncasecmp(**cp, "ipopt", 5)) { - if (!notopt) - fr->fr_flx |= FI_OPTIONS; - fr->fr_mflx |= FI_OPTIONS; - goto nextopt; - } else if (!strcasecmp(**cp, "lowttl")) { - if (!notopt) - fr->fr_flx |= FI_LOWTTL; - fr->fr_mflx |= FI_LOWTTL; - goto nextopt; - } else if (!strcasecmp(**cp, "bad-src")) { - if (!notopt) - fr->fr_flx |= FI_BADSRC; - fr->fr_mflx |= FI_BADSRC; - goto nextopt; - } else if (!strncasecmp(**cp, "mbcast", 6)) { - if (!notopt) - fr->fr_flx |= FI_MBCAST; - fr->fr_mflx |= FI_MBCAST; - goto nextopt; - } else if (!strncasecmp(**cp, "nat", 3)) { - if (!notopt) - fr->fr_flx |= FI_NATED; - fr->fr_mflx |= FI_NATED; - goto nextopt; - } else if (!strncasecmp(**cp, "frag", 4)) { - if (!notopt) - fr->fr_flx |= FI_FRAG; - fr->fr_mflx |= FI_FRAG; - goto nextopt; - } else if (!strncasecmp(**cp, "opt", 3)) { - if (!*(*cp + 1)) { - fprintf(stderr, "%d: opt missing arguements\n", - linenum); - return -1; - } - (*cp)++; - if (!(opts = optname(cp, &secmsk, linenum))) - return -1; - - if (notopt) { - if (!secmsk) { - fr->fr_optmask |= opts; - } else { - fr->fr_optmask |= (opts & ~0x0100); - fr->fr_secmask |= secmsk; - } - fr->fr_secbits &= ~secmsk; - fr->fr_optbits &= ~opts; - } else { - fr->fr_optmask |= opts; - fr->fr_secmask |= secmsk; - fr->fr_optbits |= opts; - fr->fr_secbits |= secmsk; - } - } else if (!strncasecmp(**cp, "short", 5)) { - if (fr->fr_tcpf) { - fprintf(stderr, - "%d: short cannot be used with TCP flags\n", - linenum); - return -1; - } - - if (!notopt) - fr->fr_flx |= FI_SHORT; - fr->fr_mflx |= FI_SHORT; - goto nextopt; - } else - return -1; -nextopt: - notopt = 0; - opts = 0; - secmsk = 0; - (*cp)++; - } - return 0; -} diff --git a/lib/facpri.c b/lib/facpri.c index 6785e22448f68..fc79ceaf52998 100644 --- a/lib/facpri.c +++ b/lib/facpri.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2000-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: facpri.c,v 1.6.2.5 2006/06/16 17:20:58 darrenr Exp $ + * $Id$ */ #include <stdio.h> @@ -20,7 +20,7 @@ #include "facpri.h" #if !defined(lint) -static const char rcsid[] = "@(#)$Id: facpri.c,v 1.6.2.5 2006/06/16 17:20:58 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif @@ -94,7 +94,7 @@ fac_toname(facpri) /* * map a facility name to its number */ -int +int fac_findname(name) char *name; { @@ -117,6 +117,22 @@ table_t pris[] = { /* + * map a facility name to its number + */ +int +pri_findname(name) + char *name; +{ + int i; + + for (i = 0; pris[i].name; i++) + if (!strcmp(pris[i].name, name)) + return pris[i].value; + return -1; +} + + +/* * map a priority number to its name */ char * diff --git a/lib/facpri.h b/lib/facpri.h index b6d5f5afc3637..5a02e4b3c892b 100644 --- a/lib/facpri.h +++ b/lib/facpri.h @@ -1,9 +1,9 @@ /* - * Copyright (C) 2000-2001 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: facpri.h,v 1.3.4.1 2006/06/16 17:20:58 darrenr Exp $ + * $Id$ */ #ifndef __FACPRI_H__ diff --git a/lib/familyname.c b/lib/familyname.c new file mode 100644 index 0000000000000..35bb975cc6b17 --- /dev/null +++ b/lib/familyname.c @@ -0,0 +1,12 @@ +#include "ipf.h" + +const char *familyname(int family) +{ + if (family == AF_INET) + return "inet"; +#ifdef AF_INET6 + if (family == AF_INET6) + return "inet6"; +#endif + return "unknown"; +} diff --git a/lib/fill6bits.c b/lib/fill6bits.c index a5f459a28af0c..f9554e25ba5e4 100644 --- a/lib/fill6bits.c +++ b/lib/fill6bits.c @@ -1,17 +1,17 @@ /* - * Copyright (C) 2000-2002 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: fill6bits.c,v 1.5.4.1 2006/06/16 17:20:58 darrenr Exp $ + * $Id$ */ #include "ipf.h" void fill6bits(bits, msk) -int bits; -u_int *msk; + int bits; + u_int *msk; { if (bits == 0) { msk[0] = 0; diff --git a/lib/findword.c b/lib/findword.c new file mode 100644 index 0000000000000..e06f213c05406 --- /dev/null +++ b/lib/findword.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: findword.c,v 1.3.4.1 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" + + +wordtab_t *findword(words, name) + wordtab_t *words; + char *name; +{ + wordtab_t *w; + + for (w = words; w->w_word != NULL; w++) + if (!strcmp(name, w->w_word)) + break; + if (w->w_word == NULL) + return NULL; + + return w; +} diff --git a/lib/flags.c b/lib/flags.c index 4baf3bdc277f5..e0cf835ac12f6 100644 --- a/lib/flags.c +++ b/lib/flags.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2001-2002 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: flags.c,v 1.4.4.1 2006/06/16 17:20:58 darrenr Exp $ + * $Id$ */ #include "ipf.h" diff --git a/lib/freembt.c b/lib/freembt.c new file mode 100644 index 0000000000000..0fc748decd650 --- /dev/null +++ b/lib/freembt.c @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: freembt.c,v 1.3.2.2 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" + +void freembt(m) + mb_t *m; +{ + + free(m); +} diff --git a/lib/ftov.c b/lib/ftov.c new file mode 100644 index 0000000000000..cb9715de450f9 --- /dev/null +++ b/lib/ftov.c @@ -0,0 +1,16 @@ +#include "ipf.h" + +int +ftov(version) + int version; +{ +#ifdef USE_INET6 + if (version == AF_INET6) + return 6; +#endif + if (version == AF_INET) + return 4; + if (version == AF_UNSPEC) + return 0; + return -1; +} diff --git a/lib/genmask.c b/lib/genmask.c index 238e5b62afebd..75193e3ea3982 100644 --- a/lib/genmask.c +++ b/lib/genmask.c @@ -1,54 +1,68 @@ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: genmask.c,v 1.7 2003/11/11 13:40:15 darrenr Exp $ + * $Id$ */ #include "ipf.h" -int genmask(msk, mskp) -char *msk; -u_32_t *mskp; +int genmask(family, msk, mskp) + int family; + char *msk; + i6addr_t *mskp; { char *endptr = 0L; + u_32_t addr; int bits; if (strchr(msk, '.') || strchr(msk, 'x') || strchr(msk, ':')) { /* possibly of the form xxx.xxx.xxx.xxx * or 0xYYYYYYYY */ -#ifdef USE_INET6 - if (use_inet6) { - if (inet_pton(AF_INET6, msk, mskp) != 1) + switch (family) + { +#ifdef USE_INET6 + case AF_INET6 : + if (inet_pton(AF_INET6, msk, &mskp->in4) != 1) return -1; - } else + break; #endif - if (inet_aton(msk, (struct in_addr *)mskp) == 0) + case AF_INET : + if (inet_aton(msk, &mskp->in4) == 0) + return -1; + break; + default : return -1; + /*NOTREACHED*/ + } } else { /* * set x most significant bits */ bits = (int)strtol(msk, &endptr, 0); -#ifdef USE_INET6 - if ((*endptr != '\0') || - ((bits > 32) && !use_inet6) || (bits < 0) || - ((bits > 128) && use_inet6)) -#else - if (*endptr != '\0' || bits > 32 || bits < 0) -#endif + + switch (family) + { + case AF_INET6 : + if ((*endptr != '\0') || (bits < 0) || (bits > 128)) + return -1; + fill6bits(bits, mskp->i6); + break; + case AF_INET : + if (*endptr != '\0' || bits > 32 || bits < 0) + return -1; + if (bits == 0) + addr = 0; + else + addr = htonl(0xffffffff << (32 - bits)); + mskp->in4.s_addr = addr; + break; + default : return -1; -#ifdef USE_INET6 - if (use_inet6) - fill6bits(bits, mskp); - else -#endif - if (bits == 0) - *mskp = 0; - else - *mskp = htonl(0xffffffff << (32 - bits)); + /*NOTREACHED*/ + } } return 0; } diff --git a/lib/gethost.c b/lib/gethost.c index d97766f1f102b..35dcdae26764d 100644 --- a/lib/gethost.c +++ b/lib/gethost.c @@ -1,42 +1,73 @@ /* - * Copyright (C) 2002-2004 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: gethost.c,v 1.3.2.2 2006/06/16 17:20:59 darrenr Exp $ - */ + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ #include "ipf.h" -int gethost(name, hostp) -char *name; -u_32_t *hostp; +int gethost(family, name, hostp) + int family; + char *name; + i6addr_t *hostp; { struct hostent *h; struct netent *n; u_32_t addr; if (!strcmp(name, "test.host.dots")) { - *hostp = htonl(0xfedcba98); + if (family == AF_INET) { + hostp->in4.s_addr = htonl(0xfedcba98); + } +#ifdef USE_INET6 + if (family == AF_INET6) { + hostp->i6[0] = 0xfe80aa55; + hostp->i6[1] = 0x12345678; + hostp->i6[2] = 0x5a5aa5a5; + hostp->i6[3] = 0xfedcba98; + } +#endif return 0; } if (!strcmp(name, "<thishost>")) name = thishost; - h = gethostbyname(name); - if (h != NULL) { - if ((h->h_addr != NULL) && (h->h_length == sizeof(addr))) { - bcopy(h->h_addr, (char *)&addr, sizeof(addr)); - *hostp = addr; + if (family == AF_INET) { + h = gethostbyname(name); + if (h != NULL) { + if ((h->h_addr != NULL) && + (h->h_length == sizeof(addr))) { + bcopy(h->h_addr, (char *)&addr, sizeof(addr)); + hostp->in4.s_addr = addr; + return 0; + } + } + + n = getnetbyname(name); + if (n != NULL) { + hostp->in4.s_addr = htonl(n->n_net & 0xffffffff); return 0; } } +#ifdef USE_INET6 + if (family == AF_INET6) { + struct addrinfo hints, *res; + struct sockaddr_in6 *sin6; - n = getnetbyname(name); - if (n != NULL) { - *hostp = (u_32_t)htonl(n->n_net & 0xffffffff); - return 0; + bzero((char *)&hints, sizeof(hints)); + hints.ai_family = PF_INET6; + + getaddrinfo(name, NULL, &hints, &res); + if (res != NULL) { + sin6 = (struct sockaddr_in6 *)res->ai_addr; + hostp->in6 = sin6->sin6_addr; + freeaddrinfo(res); + return 0; + } } +#endif return -1; } diff --git a/lib/geticmptype.c b/lib/geticmptype.c new file mode 100644 index 0000000000000..5c962e949526e --- /dev/null +++ b/lib/geticmptype.c @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ +#include "ipf.h" + +int geticmptype(family, name) + int family; + char *name; +{ + icmptype_t *i; + + for (i = icmptypelist; i->it_name != NULL; i++) { + if (!strcmp(name, i->it_name)) { + if (family == AF_INET) + return i->it_v4; +#ifdef USE_INET6 + if (family == AF_INET6) + return i->it_v6; +#endif + return -1; + } + } + + return -1; +} diff --git a/lib/getifname.c b/lib/getifname.c index 6163239edb294..176528273f51e 100644 --- a/lib/getifname.c +++ b/lib/getifname.c @@ -1,10 +1,10 @@ /* - * Copyright (C) 2002-2004 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: getifname.c,v 1.5.2.3 2006/07/14 06:12:24 darrenr Exp $ - */ + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ #include "ipf.h" @@ -16,7 +16,7 @@ */ #if 0 char *getifname(ptr) -struct ifnet *ptr; + struct ifnet *ptr; { #if SOLARIS || defined(__hpux) # if SOLARIS @@ -48,7 +48,7 @@ struct ifnet *ptr; defined(__OpenBSD__) || \ (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) #else - char buf[32]; + char buf[LIFNAMSIZ]; int len; # endif struct ifnet netif; @@ -83,8 +83,9 @@ struct ifnet *ptr; } #else char *getifname(ptr) -struct ifnet *ptr; + struct ifnet *ptr; { + ptr = ptr; return "X"; } #endif diff --git a/lib/getline.c b/lib/getline.c deleted file mode 100644 index 7d06d4367b28c..0000000000000 --- a/lib/getline.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: getline.c,v 1.3 2001/06/09 17:09:24 darrenr Exp $ - */ - -#include <stdio.h> -#if !defined(__SVR4) && !defined(__GNUC__) -#include <strings.h> -#endif -#include <string.h> -#include "ipf.h" - - -/* - * 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. - */ -char *getline(str, size, file, linenum) -register char *str; -size_t size; -FILE *file; -int *linenum; -{ - char *p; - int s, len; - - do { - for (p = str, s = size;; p += (len - 1), s -= (len - 1)) { - /* - * if an error occured, EOF was encounterd, or there - * was no room to put NUL, return NULL. - */ - if (fgets(p, s, file) == NULL) - return (NULL); - len = strlen(p); - if (p[len - 1] != '\n') { - p[len] = '\0'; - break; - } - (*linenum)++; - p[len - 1] = '\0'; - if (len < 2 || p[len - 2] != '\\') - break; - else - /* - * Convert '\\' to a space so words don't - * run together - */ - p[len - 2] = ' '; - } - } while (*str == '\0'); - return (str); -} diff --git a/lib/getnattype.c b/lib/getnattype.c index 04463c22234a4..607eb6a7a435d 100644 --- a/lib/getnattype.c +++ b/lib/getnattype.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2004 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * @@ -9,34 +9,24 @@ #include "kmem.h" #if !defined(lint) -static const char rcsid[] = "@(#)$Id: getnattype.c,v 1.3.2.2 2006/07/14 06:12:24 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif /* * Get a nat filter type given its kernel address. */ -char *getnattype(nat, alive) -nat_t *nat; -int alive; +char * +getnattype(nat) + nat_t *nat; { static char unknownbuf[20]; - ipnat_t *ipn, ipnat; char *which; - int type; if (!nat) return "???"; - if (alive) { - type = nat->nat_redir; - } else { - ipn = nat->nat_ptr; - if (kmemcpy((char *)&ipnat, (long)ipn, sizeof(ipnat))) - return "!!!"; - type = ipnat.in_redir; - } - switch (type) + switch (nat->nat_redir) { case NAT_MAP : which = "MAP"; @@ -47,11 +37,30 @@ int alive; case NAT_REDIRECT : which = "RDR"; break; + case NAT_MAP|NAT_REWRITE : + which = "RWR-MAP"; + break; + case NAT_REDIRECT|NAT_REWRITE : + which = "RWR-RDR"; + break; case NAT_BIMAP : which = "BIMAP"; break; + case NAT_REDIRECT|NAT_DIVERTUDP : + which = "DIV-RDR"; + break; + case NAT_MAP|NAT_DIVERTUDP : + which = "DIV-MAP"; + break; + case NAT_REDIRECT|NAT_ENCAP : + which = "ENC-RDR"; + break; + case NAT_MAP|NAT_ENCAP : + which = "ENC-MAP"; + break; default : - sprintf(unknownbuf, "unknown(%04x)", type & 0xffffffff); + sprintf(unknownbuf, "unknown(%04x)", + nat->nat_redir & 0xffffffff); which = unknownbuf; break; } diff --git a/lib/getport.c b/lib/getport.c index 1c5177c560063..d30f1ad5086ea 100644 --- a/lib/getport.c +++ b/lib/getport.c @@ -1,28 +1,37 @@ /* - * Copyright (C) 2002-2005 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: getport.c,v 1.1.4.6 2006/06/16 17:21:00 darrenr Exp $ - */ + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ #include "ipf.h" +#include <ctype.h> -int getport(fr, name, port) -frentry_t *fr; -char *name; -u_short *port; +int getport(fr, name, port, proto) + frentry_t *fr; + char *name, *proto; + u_short *port; { struct protoent *p; struct servent *s; u_short p1; if (fr == NULL || fr->fr_type != FR_T_IPF) { - s = getservbyname(name, NULL); + s = getservbyname(name, proto); if (s != NULL) { *port = s->s_port; return 0; } + + if (ISDIGIT(*name)) { + int portval = atoi(name); + if (portval < 0 || portval > 65535) + return -1; + *port = htons((u_short)portval); + return 0; + } return -1; } diff --git a/lib/getportproto.c b/lib/getportproto.c index 5a247aec6f68f..b431198c953e8 100644 --- a/lib/getportproto.c +++ b/lib/getportproto.c @@ -1,17 +1,17 @@ /* - * Copyright (C) 2002-2005 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: getportproto.c,v 1.2.4.4 2006/06/16 17:21:00 darrenr Exp $ - */ + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ #include <ctype.h> #include "ipf.h" int getportproto(name, proto) -char *name; -int proto; + char *name; + int proto; { struct servent *s; struct protoent *p; diff --git a/lib/getproto.c b/lib/getproto.c index 9714da26a8241..5a8dae30b18ea 100644 --- a/lib/getproto.c +++ b/lib/getproto.c @@ -1,15 +1,16 @@ /* - * Copyright (C) 2002-2005 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: getproto.c,v 1.2.2.3 2006/06/16 17:21:00 darrenr Exp $ - */ + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ #include "ipf.h" +#include <ctype.h> int getproto(name) -char *name; + char *name; { struct protoent *p; char *s; @@ -23,10 +24,13 @@ char *name; #ifdef _AIX51 /* * For some bogus reason, "ip" is 252 in /etc/protocols on AIX 5 + * The IANA has doubled up on the definition of 0 - it is now also + * used for IPv6 hop-opts, so we can no longer rely on /etc/protocols + * providing the correct name->number mapping */ +#endif if (!strcasecmp(name, "ip")) return 0; -#endif p = getprotobyname(name); if (p != NULL) diff --git a/lib/getsumd.c b/lib/getsumd.c index 00974bcf6f8f0..ffc046cd12ada 100644 --- a/lib/getsumd.c +++ b/lib/getsumd.c @@ -1,15 +1,15 @@ /* - * Copyright (C) 2002 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: getsumd.c,v 1.2.4.1 2006/06/16 17:21:01 darrenr Exp $ - */ + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ #include "ipf.h" char *getsumd(sum) -u_32_t sum; + u_32_t sum; { static char sumdbuf[17]; diff --git a/lib/hexdump.c b/lib/hexdump.c deleted file mode 100644 index 86e731ee4a23d..0000000000000 --- a/lib/hexdump.c +++ /dev/null @@ -1,28 +0,0 @@ -#include <ctype.h> - -#include "ipf.h" - -void hexdump(out, addr, len, ascii) -FILE *out; -void *addr; -int len, ascii; -{ - FILE *fpout; - u_char *s, *t; - int i; - - fpout = out ? out : stdout; - for (i = 0, s = addr; i < len; i++, s++) { - fprintf(fpout, "%02x", *s); - if (i % 16 == 15) { - if (ascii != 0) { - fputc('\t', fpout); - for (t = s - 15; t<= s; t++) - fputc(ISPRINT(*t) ? *t : '.', fpout); - } - fputc('\n', fpout); - } else if (i % 4 == 3) { - fputc(' ', fpout); - } - } -} diff --git a/lib/hostmask.c b/lib/hostmask.c deleted file mode 100644 index 4ee41e16b94f4..0000000000000 --- a/lib/hostmask.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: hostmask.c,v 1.10 2002/01/28 06:50:46 darrenr Exp $ - */ - -#include "ipf.h" - - -/* - * returns -1 if neither "hostmask/num" or "hostmask mask addr" are - * found in the line segments, there is an error processing this information, - * or there is an error processing ports information. - */ -int hostmask(seg, proto, ifname, sa, msk, linenum) -char ***seg, *proto, *ifname; -u_32_t *sa, *msk; -int linenum; -{ - struct in_addr maskaddr; - char *s; - - if ((s = strchr(**seg, '='))) { - *s++ = '\0'; - if (!strcmp(**seg, "pool")) { - *sa = atoi(s); - return 1; - } - } - - /* - * is it possibly hostname/num ? - */ - if ((s = strchr(**seg, '/')) || - ((s = strchr(**seg, ':')) && !strchr(s + 1, ':'))) { - *s++ ='\0'; - if (genmask(s, msk) == -1) { - fprintf(stderr, "%d: bad mask (%s)\n", linenum, s); - return -1; - } - if (hostnum(sa, **seg, linenum, ifname) == -1) { - fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg); - return -1; - } - *sa &= *msk; - (*seg)++; - return 0; - } - - /* - * look for extra segments if "mask" found in right spot - */ - if (*(*seg+1) && *(*seg+2) && !strcasecmp(*(*seg+1), "mask")) { - if (hostnum(sa, **seg, linenum, ifname) == -1) { - fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg); - return -1; - } - (*seg)++; - (*seg)++; - if (inet_aton(**seg, &maskaddr) == 0) { - fprintf(stderr, "%d: bad mask (%s)\n", linenum, **seg); - return -1; - } - *msk = maskaddr.s_addr; - (*seg)++; - *sa &= *msk; - return 0; - } - - if (**seg) { - u_32_t k; - - if (hostnum(sa, **seg, linenum, ifname) == -1) { - fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg); - return -1; - } - (*seg)++; - k = *sa ? 0xffffffff : 0; -#ifdef USE_INET6 - if (use_inet6) { - msk[1] = k; - msk[2] = k; - msk[3] = k; - } -#endif - *msk = k; - return 0; - } - fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg); - return -1; -} diff --git a/lib/hostname.c b/lib/hostname.c index b8295d40321ba..4f9bf2a216628 100644 --- a/lib/hostname.c +++ b/lib/hostname.c @@ -1,16 +1,16 @@ /* - * Copyright (C) 2002-2003 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: hostname.c,v 1.6.2.2 2007/01/16 02:25:22 darrenr Exp $ - */ + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ #include "ipf.h" -char *hostname(v, ip) -int v; -void *ip; +char *hostname(family, ip) + int family; + void *ip; { static char hostbuf[MAXHOSTNAMELEN+1]; struct hostent *hp; @@ -19,14 +19,14 @@ void *ip; memset(&ipa, 0, sizeof(ipa)); /* XXX gcc */ - if (v == 4) { + if (family == AF_INET) { ipa.s_addr = *(u_32_t *)ip; if (ipa.s_addr == htonl(0xfedcba98)) return "test.host.dots"; } if ((opts & OPT_NORESOLVE) == 0) { - if (v == 4) { + if (family == AF_INET) { hp = gethostbyaddr(ip, 4, AF_INET); if (hp != NULL && hp->h_name != NULL && *hp->h_name != '\0') { @@ -45,7 +45,7 @@ void *ip; } } - if (v == 4) { + if (family == AF_INET) { return inet_ntoa(ipa); } #ifdef USE_INET6 diff --git a/lib/hostnum.c b/lib/hostnum.c deleted file mode 100644 index 2ec0529a29815..0000000000000 --- a/lib/hostnum.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: hostnum.c,v 1.10.2.1 2004/12/09 19:41:20 darrenr Exp $ - */ - -#include <ctype.h> - -#include "ipf.h" - - -/* - * returns an ip address as a long var as a result of either a DNS lookup or - * straight inet_addr() call - */ -int hostnum(ipa, host, linenum, ifname) -u_32_t *ipa; -char *host; -int linenum; -char *ifname; -{ - struct in_addr ip; - - if (!strcasecmp("any", host) || - (ifname && *ifname && !strcasecmp(ifname, host))) - return 0; - -#ifdef USE_INET6 - if (use_inet6) { - if (inet_pton(AF_INET6, host, ipa) == 1) - return 0; - else - return -1; - } -#endif - if (ISDIGIT(*host) && inet_aton(host, &ip)) { - *ipa = ip.s_addr; - return 0; - } - - if (!strcasecmp("<thishost>", host)) - host = thishost; - - return gethost(host, ipa); -} diff --git a/lib/icmpcode.c b/lib/icmpcode.c index 69841e0cc4b7d..99a63975a162e 100644 --- a/lib/icmpcode.c +++ b/lib/icmpcode.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2000-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: icmpcode.c,v 1.7.2.5 2006/06/16 17:21:02 darrenr Exp $ + * $Id$ */ #include <ctype.h> diff --git a/lib/icmptypename.c b/lib/icmptypename.c new file mode 100644 index 0000000000000..d7eb3bd3ab731 --- /dev/null +++ b/lib/icmptypename.c @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ +#include "ipf.h" + +char *icmptypename(family, type) + int family, type; +{ + icmptype_t *i; + + if ((type < 0) || (type > 255)) + return NULL; + + for (i = icmptypelist; i->it_name != NULL; i++) { + if ((family == AF_INET) && (i->it_v4 == type)) + return i->it_name; +#ifdef USE_INET6 + if ((family == AF_INET6) && (i->it_v6 == type)) + return i->it_name; +#endif + } + + return NULL; +} diff --git a/lib/icmptypes.c b/lib/icmptypes.c new file mode 100644 index 0000000000000..c1123ff5e04db --- /dev/null +++ b/lib/icmptypes.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ +#include "ipf.h" + +#ifndef USE_INET6 +# undef ICMP6_ECHO_REQUEST +# define ICMP6_ECHO_REQUEST 0 +# undef ICMP6_ECHO_REPLY +# define ICMP6_ECHO_REPLY 0 +# undef ICMP6_NI_QUERY +# define ICMP6_NI_QUERY 0 +# undef ICMP6_NI_REPLY +# define ICMP6_NI_REPLY 0 +# undef ICMP6_PARAM_PROB +# define ICMP6_PARAM_PROB 0 +# undef ND_ROUTER_ADVERT +# define ND_ROUTER_ADVERT 0 +# undef ND_ROUTER_SOLICIT +# define ND_ROUTER_SOLICIT 0 +# undef ICMP6_TIME_EXCEEDED +# define ICMP6_TIME_EXCEEDED 0 +# undef ICMP6_DST_UNREACH +# define ICMP6_DST_UNREACH 0 +# undef ICMP6_PACKET_TOO_BIG +# define ICMP6_PACKET_TOO_BIG 0 +# undef MLD_LISTENER_QUERY +# define MLD_LISTENER_QUERY 0 +# undef MLD_LISTENER_REPORT +# define MLD_LISTENER_REPORT 0 +# undef MLD_LISTENER_DONE +# define MLD_LISTENER_DONE 0 +# undef ICMP6_MEMBERSHIP_QUERY +# define ICMP6_MEMBERSHIP_QUERY 0 +# undef ICMP6_MEMBERSHIP_REPORT +# define ICMP6_MEMBERSHIP_REPORT 0 +# undef ICMP6_MEMBERSHIP_REDUCTION +# define ICMP6_MEMBERSHIP_REDUCTION 0 +# undef ND_NEIGHBOR_ADVERT +# define ND_NEIGHBOR_ADVERT 0 +# undef ND_NEIGHBOR_SOLICIT +# define ND_NEIGHBOR_SOLICIT 0 +# undef ICMP6_ROUTER_RENUMBERING +# define ICMP6_ROUTER_RENUMBERING 0 +# undef ICMP6_WRUREQUEST +# define ICMP6_WRUREQUEST 0 +# undef ICMP6_WRUREPLY +# define ICMP6_WRUREPLY 0 +# undef ICMP6_FQDN_QUERY +# define ICMP6_FQDN_QUERY 0 +# undef ICMP6_FQDN_REPLY +# define ICMP6_FQDN_REPLY 0 +#else +# if !defined(MLD_LISTENER_QUERY) +# define MLD_LISTENER_QUERY 130 +# endif +# if !defined(MLD_LISTENER_REPORT) +# define MLD_LISTENER_REPORT 131 +# endif +# if !defined(MLD_LISTENER_DONE) +# define MLD_LISTENER_DONE 132 +# endif +# if defined(MLD_LISTENER_REDUCTION) && !defined(MLD_LISTENER_DONE) +# define MLD_LISTENER_DONE MLD_LISTENER_REDUCTION +# endif +#endif + +icmptype_t icmptypelist[] = { + { "echo", ICMP_ECHO, ICMP6_ECHO_REQUEST }, + { "echorep", ICMP_ECHOREPLY, ICMP6_ECHO_REPLY }, + { "fqdnquery", -1, ICMP6_FQDN_QUERY }, + { "fqdnreply", -1, ICMP6_FQDN_REPLY }, + { "infoqry", -1, ICMP6_NI_QUERY }, + { "inforeq", ICMP_IREQ, ICMP6_NI_QUERY }, + { "inforep", ICMP_IREQREPLY, ICMP6_NI_REPLY }, + { "listendone", -1, MLD_LISTENER_DONE }, + { "listenqry", -1, MLD_LISTENER_QUERY }, + { "listenrep", -1, MLD_LISTENER_REPORT }, + { "maskrep", ICMP_MASKREPLY, -1 }, + { "maskreq", ICMP_MASKREQ, -1 }, + { "memberqry", -1, ICMP6_MEMBERSHIP_QUERY }, + { "memberred", -1, ICMP6_MEMBERSHIP_REDUCTION }, + { "memberreply",-1, ICMP6_MEMBERSHIP_REPORT }, + { "neighadvert", -1, ND_NEIGHBOR_ADVERT }, + { "neighborsol", -1, ND_NEIGHBOR_SOLICIT }, + { "neighborsolicit", -1, ND_NEIGHBOR_SOLICIT }, + { "paramprob", ICMP_PARAMPROB, ICMP6_PARAM_PROB }, + { "redir", ICMP_REDIRECT, ND_REDIRECT }, + { "renumber", -1, ICMP6_ROUTER_RENUMBERING }, + { "routerad", ICMP_ROUTERADVERT, ND_ROUTER_ADVERT }, + { "routeradvert",ICMP_ROUTERADVERT, ND_ROUTER_ADVERT }, + { "routersol", ICMP_ROUTERSOLICIT, ND_ROUTER_SOLICIT }, + { "routersolcit",ICMP_ROUTERSOLICIT, ND_ROUTER_SOLICIT }, + { "squench", ICMP_SOURCEQUENCH, -1 }, + { "timest", ICMP_TSTAMP, -1 }, + { "timestrep", ICMP_TSTAMPREPLY, -1 }, + { "timex", ICMP_TIMXCEED, ICMP6_TIME_EXCEEDED }, + { "toobig", -1, ICMP6_PACKET_TOO_BIG }, + { "unreach", ICMP_UNREACH, ICMP6_DST_UNREACH }, + { "whorep", -1, ICMP6_WRUREPLY }, + { "whoreq", -1, ICMP6_WRUREQUEST }, + { NULL, -1, -1 } +}; diff --git a/lib/inet_addr.c b/lib/inet_addr.c deleted file mode 100644 index 820b7b58a416c..0000000000000 --- a/lib/inet_addr.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * ++Copyright++ 1983, 1990, 1993 - * - - * Copyright (c) 1983, 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies, and that - * the name of Digital Equipment Corporation not be used in advertising or - * publicity pertaining to distribution of the document or software without - * specific, written prior permission. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT - * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - * - - * --Copyright-- - */ - -#if !defined(lint) -static const char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93"; -static const char rcsid[] = "@(#)$Id: inet_addr.c,v 1.8.2.3 2004/12/09 19:41:20 darrenr Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/param.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <ctype.h> - -#ifndef __P -# ifdef __STDC__ -# define __P(x) x -# else -# define __P(x) () -# endif -#endif -#ifndef linux -int inet_aton __P((const char *, struct in_addr *)); - -/* - * Because the ctype(3) posix definition, if used "safely" in code everywhere, - * would mean all normal code that walks through strings needed casts. Yuck. - */ -#define ISALNUM(x) isalnum((u_char)(x)) -#define ISALPHA(x) isalpha((u_char)(x)) -#define ISASCII(x) isascii((u_char)(x)) -#define ISDIGIT(x) isdigit((u_char)(x)) -#define ISPRINT(x) isprint((u_char)(x)) -#define ISSPACE(x) isspace((u_char)(x)) -#define ISUPPER(x) isupper((u_char)(x)) -#define ISXDIGIT(x) isxdigit((u_char)(x)) -#define ISLOWER(x) islower((u_char)(x)) - -/* - * Check whether "cp" is a valid ascii representation - * of an Internet address and convert to a binary address. - * Returns 1 if the address is valid, 0 if not. - * This replaces inet_addr, the return value from which - * cannot distinguish between failure and a local broadcast address. - */ -int -inet_aton(cp, addr) - register const char *cp; - struct in_addr *addr; -{ - register u_long val; - register int base, n; - register char c; - u_int parts[4]; - register u_int *pp = parts; - - c = *cp; - for (;;) { - /* - * Collect number up to ``.''. - * Values are specified as for C: - * 0x=hex, 0=octal, isdigit=decimal. - */ - if (!ISDIGIT(c)) - return (0); - val = 0; base = 10; - if (c == '0') { - c = *++cp; - if (c == 'x' || c == 'X') - base = 16, c = *++cp; - else - base = 8; - } - for (;;) { - if (ISASCII(c) && ISDIGIT(c)) { - val = (val * base) + (c - '0'); - c = *++cp; - } else if (base == 16 && ISASCII(c) && ISXDIGIT(c)) { - val = (val << 4) | - (c + 10 - (ISLOWER(c) ? 'a' : 'A')); - c = *++cp; - } else - break; - } - if (c == '.') { - /* - * Internet format: - * a.b.c.d - * a.b.c (with c treated as 16 bits) - * a.b (with b treated as 24 bits) - */ - if (pp >= parts + 3) - return (0); - *pp++ = val; - c = *++cp; - } else - break; - } - /* - * Check for trailing characters. - */ - if (c != '\0' && (!ISASCII(c) || !ISSPACE(c))) - return (0); - /* - * Concoct the address according to - * the number of parts specified. - */ - n = pp - parts + 1; - switch (n) { - - case 0: - return (0); /* initial nondigit */ - - case 1: /* a -- 32 bits */ - break; - - case 2: /* a.b -- 8.24 bits */ - if (val > 0xffffff) - return (0); - val |= parts[0] << 24; - break; - - case 3: /* a.b.c -- 8.8.16 bits */ - if (val > 0xffff) - return (0); - val |= (parts[0] << 24) | (parts[1] << 16); - break; - - case 4: /* a.b.c.d -- 8.8.8.8 bits */ - if (val > 0xff) - return (0); - val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); - break; - } - if (addr) - addr->s_addr = htonl(val); - return (1); -} -#endif - -/* these are compatibility routines, not needed on recent BSD releases */ - -/* - * Ascii internet address interpretation routine. - * The value returned is in network order. - */ -#if 0 -inet_addr(cp) - const char *cp; -{ - struct in_addr val; - - if (inet_aton(cp, &val)) - return (val.s_addr); - return (0xffffffff); -} -#endif diff --git a/lib/initparse.c b/lib/initparse.c index b9f162f55c274..bfdf057af6ed8 100644 --- a/lib/initparse.c +++ b/lib/initparse.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2000-2002 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: initparse.c,v 1.6.4.1 2006/06/16 17:21:02 darrenr Exp $ + * $Id$ */ #include "ipf.h" diff --git a/lib/interror.c b/lib/interror.c new file mode 100644 index 0000000000000..c13f5f8618a8d --- /dev/null +++ b/lib/interror.c @@ -0,0 +1,582 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: interror.c,v 1.9.2.12 2012/07/22 08:03:39 darren_r Exp $ + */ + +#include "ipf.h" +#include <fcntl.h> +#include <sys/ioctl.h> + +typedef struct { + int iee_number; + char *iee_text; +} ipf_error_entry_t; + +static ipf_error_entry_t *find_error __P((int)); + +#define IPF_NUM_ERRORS 475 + +/* + * NO REUSE OF NUMBERS! + * + * IF YOU WANT TO ADD AN ERROR TO THIS TABLE, _ADD_ A NEW NUMBER. + * DO _NOT_ USE AN EMPTY NUMBER OR FILL IN A GAP. + */ +static ipf_error_entry_t ipf_errors[IPF_NUM_ERRORS] = { + { 1, "auth table locked/full" }, + { 2, "" }, + { 3, "copyinptr received bad address" }, + { 4, "copyoutptr received bad address" }, + { 5, "" }, + { 6, "cannot load a rule with FR_T_BUILTIN flag set" }, + { 7, "internal rule without FR_T_BUILDINT flag set" }, + { 8, "no data provided with filter rule" }, + { 9, "invalid ioctl for rule" }, + { 10, "rule protocol is not 4 or 6" }, + { 11, "cannot find rule function" }, + { 12, "cannot find rule group" }, + { 13, "group in/out does not match rule in/out" }, + { 14, "rule without in/out does not belong to a group" }, + { 15, "cannot determine where to append rule" }, + { 16, "malloc for rule data failed" }, + { 17, "copyin for rule data failed" }, + { 18, "" }, + { 19, "zero data size for BPF rule" }, + { 20, "BPF validation failed" }, + { 21, "incorrect data size for IPF rule" }, + { 22, "'keep state' rule included 'with oow'" }, + { 23, "bad interface index with dynamic source address" }, + { 24, "bad interface index with dynamic dest. address" }, + { 25, "match array verif failed for filter rule" }, + { 26, "bad filter rule type" }, + { 27, "rule not found for zero'stats" }, + { 28, "copyout failed for zero'ing stats" }, + { 29, "rule not found for removing" }, + { 30, "cannot remove internal rule" }, + { 31, "rule in use" }, + { 32, "rule already exists" }, + { 33, "no memory for another rule" }, + { 34, "could not find function" }, + { 35, "copyout failed for resolving function name -> addr" }, + { 36, "copyout failed for resolving function addr -> name" }, + { 37, "function name/addr resolving search failed" }, + { 38, "group map cannot find it's hash table" }, + { 39, "group map hash-table in/out do not match rule" }, + { 40, "bcopyout failed for SIOCIPFINTERROR" }, + { 41, "" }, + { 42, "ipfilter not enabled for NAT ioctl" }, + { 43, "ipfilter not enabled for state ioctl" }, + { 44, "ipfilter not enabled for auth ioctl" }, + { 45, "ipfilter not enbaled for sync ioctl" }, + { 46, "ipfilter not enabled for scan ioctl" }, + { 47, "ipfilter not enabled for lookup ioctl" }, + { 48, "unrecognised device minor number for ioctl" }, + { 49, "unrecognised object type for copying in ipfobj" }, + { 50, "mismatching object type for copying in ipfobj" }, + { 51, "object size too small for copying in ipfobj" }, + { 52, "object size mismatch for copying in ipfobj" }, + { 53, "compat object size too small for copying in ipfobj" }, + { 54, "compat object size mismatch for copying in ipfobj" }, + { 55, "error doing copyin of data for in ipfobj" }, + { 56, "unrecognised object type for size copy in ipfobj" }, + { 57, "object size too small for size copy in ipfobj" }, + { 58, "mismatching object type for size copy in ipfobj" }, + { 59, "object size mismatch for size copy in ipfobj" }, + { 60, "compat object size mismatch for size copy in ipfobj" }, + { 61, "error doing size copyin of data for in ipfobj" }, + { 62, "bad object type for size copy out ipfobj" }, + { 63, "mismatching object type for size copy out ipfobj" }, + { 64, "object size mismatch for size copy out ipfobj" }, + { 65, "compat object size wrong for size copy out ipfobj" }, + { 66, "error doing size copyout of data for out ipfobj" }, + { 67, "unrecognised object type for copying out ipfobj" }, + { 68, "mismatching object type for copying out ipfobj" }, + { 69, "object size too small for copying out ipfobj" }, + { 70, "object size mismatch for copying out ipfobj" }, + { 71, "compat object size too small for copying out ipfobj" }, + { 72, "compat object size mismatch for copying out ipfobj" }, + { 73, "error doing copyout of data for out ipfobj" }, + { 74, "attempt to add existing tunable name" }, + { 75, "cannot find tunable name to delete" }, + { 76, "internal data too big for next tunable" }, + { 77, "could not find tunable" }, + { 78, "tunable can only be changed when ipfilter disabled" }, + { 79, "new tunable value outside accepted range" }, + { 80, "ipftune called for unrecognised ioctl" }, + { 81, "" }, + { 82, "could not find token to delete" }, + { 83, "" }, + { 84, "attempt to get next rule when no more exist" }, + { 85, "value for iri_inout outside accepted range" }, + { 86, "value for iri_active outside accepted range" }, + { 87, "value for iri_nrules is 0" }, + { 88, "NULL pointer specified for where to copy rule to" }, + { 89, "copyout of rule failed" }, + { 90, "" }, + { 91, "could not get token for rule iteration" }, + { 92, "unrecognised generic iterator" }, + { 93, "could not find token for generic iterator" }, + { 94, "need write permissions to disable/enable ipfilter" }, + { 95, "error copying in enable/disable value" }, + { 96, "need write permissions to set ipf tunable" }, + { 97, "need write permissions to set ipf flags" }, + { 98, "error doing copyin of ipf flags" }, + { 99, "error doing copyout of ipf flags" }, + { 100, "need write permissions to add another rule" }, + { 101, "need write permissions to insert another rule" }, + { 102, "need write permissions to swap active rule set" }, + { 103, "error copying out current active rule set" }, + { 104, "need write permissions to zero ipf stats" }, + { 105, "need write permissions to flush ipf v4 rules" }, + { 106, "error copying out v4 flush results" }, + { 107, "error copying in v4 flush command" }, + { 108, "need write permissions to flush ipf v6 rules" }, + { 109, "error copying out v6 flush results" }, + { 110, "error copying in v6 flush command" }, + { 111, "error copying in new lock state for ipfilter" }, + { 112, "need write permissions to flush ipf logs" }, + { 113, "error copying out results of log flush" }, + { 114, "need write permissions to resync ipf" }, + { 115, "unrecognised ipf ioctl" }, + { 116, "error copying in match array" }, + { 117, "match array type is not IPFOBJ_IPFEXPR" }, + { 118, "bad size for match array" }, + { 119, "cannot allocate memory for match aray" }, + { 120, "error copying in match array" }, + { 121, "error verifying contents of match array" }, + { 122, "need write permissions to set ipf lock status" }, + { 123, "error copying in data for function resolution" }, + { 124, "error copying in ipfobj structure" }, + { 125, "error copying in ipfobj structure" }, + { 126, "error copying in ipfobj structure" }, + { 127, "error copying in ipfobj structure" }, + { 128, "no memory for filter rule comment" }, + { 129, "error copying in filter rule comment" }, + { 130, "error copying out filter rule comment" }, + { 131, "no memory for new rule alloc buffer" }, + { 132, "cannot find source lookup pool" }, + { 133, "unknown source address type" }, + { 134, "cannot find destination lookup pool" }, + { 135, "unknown destination address type" }, + { 136, "icmp head group name index incorrect" }, + { 137, "group head name index incorrect" }, + { 138, "group name index incorrect" }, + { 139, "to interface name index incorrect" }, + { 140, "dup-to interface name index incorrect" }, + { 141, "reply-to interface name index incorrect" }, + { 142, "could not initialise call now function" }, + { 143, "could not initialise call function" }, + { 144, "could not find destination list" }, + { 145, "auth rules cannot have dup/to/fastroute" }, + { 146, "incorrect size for object to copy out" }, + { 147, "object type out of bounds for kernel copyout" }, + { 148, "object size too small for kernel copyout" }, + { 149, "object size validation failed for kernel copyout" }, + { 150, "error copying data out for kernel copyout" }, + { 151, "version mismatch for kernel copyout" }, +/* -------------------------------------------------------------------------- */ + { 10001, "could not find token for auth iterator" }, + { 10002, "write permissions require to add/remove auth rule" }, + { 10003, "need write permissions to set auth lock" }, + { 10004, "error copying out results of auth flush" }, + { 10005, "unknown auth ioctl" }, + { 10006, "can only append or remove preauth rules" }, + { 10007, "NULL pointers passed in for preauth remove" }, + { 10008, "preauth rule not found to remove" }, + { 10009, "could not malloc memory for preauth entry" }, + { 10010, "unrecognised preauth rule ioctl command" }, + { 10011, "iterator data supplied with NULL pointer" }, + { 10012, "unknown auth iterator type" }, + { 10013, "iterator error copying out auth data" }, + { 10014, "sleep waiting for auth packet interrupted" }, + { 10015, "bad index supplied in auth reply" }, + { 10016, "error injecting outbound packet back into kernel" }, + { 10017, "error injecting inbound packet back into kernel" }, + { 10018, "could not attempt to inject packet back into kernel" }, + { 10019, "packet id does not match" }, +/* -------------------------------------------------------------------------- */ + { 20001, "invalid frag token data pointer supplied" }, + { 20002, "error copying out frag token data" }, + { 20003, "can only copy one fragment state entry at a time" }, +/* -------------------------------------------------------------------------- */ + { 30001, "incorrect object size to get hash table stats" }, + { 30002, "could not malloc memory for new hash table" }, + { 30003, "error coping in hash table structure" }, + { 30004, "hash table already exists" }, + { 30005, "mismach between new hash table and operation unit" }, + { 30006, "could not malloc memory for hash table base" }, + { 30007, "could not find hash table" }, + { 30008, "mismatch between hash table and operation unit" }, + { 30009, "could not find hash table for iterators next node" }, + { 30010, "unknown iterator tpe" }, + { 30011, "iterator error copying out hash table" }, + { 30012, "iterator error copying out hash table entry" }, + { 30013, "error copying out hash table statistics" }, + { 30014, "table node delete structure wrong size" }, + { 30015, "error copying in node to delete" }, + { 30016, "table to delete node from does not exist" }, + { 30017, "could not find table to remove node from" }, + { 30018, "table node add structure wrong size" }, + { 30019, "error copying in node to add" }, + { 30020, "could not find table to add node to" }, + { 30021, "node already exists in the table" }, + { 30022, "could not find node to delete in table" }, + { 30023, "uid mismatch on node to delete" }, + { 30024, "object size incorrect for hash table" }, + { 30025, "hash table size must be at least 1"}, + { 30026, "cannot allocate memory for hash table context" }, +/* -------------------------------------------------------------------------- */ + { 40001, "invalid minor device numebr for log read" }, + { 40002, "read size too small" }, + { 40003, "interrupted waiting for log data to read" }, + { 40004, "interrupted waiting for log data to read" }, + { 40005, "read size too large" }, + { 40006, "uiomove for read operation failed" }, +/* -------------------------------------------------------------------------- */ + { 50001, "unknown lookup ioctl" }, + { 50002, "error copying in object data for add node" }, + { 50003, "invalid unit for lookup add node" }, + { 50004, "incorrect size for adding a pool node" }, + { 50005, "error copying in pool node structure" }, + { 50006, "mismatch in pool node address/mask families" }, + { 50007, "could not find pool name" }, + { 50008, "node already exists in pool" }, + { 50009, "incorrect size for adding a hash node" }, + { 50010, "error copying in hash node structure" }, + { 50011, "could not find hash table name" }, + { 50012, "unrecognised object type for lookup add node" }, + { 50013, "invalid unit for lookup delete node" }, + { 50014, "incorrect size for deleting a pool node" }, + { 50015, "error copying in pool node structure" }, + { 50016, "could not find pool name" }, + { 50017, "could not find pool node" }, + { 50018, "incorrect size for removing a hash node" }, + { 50019, "error copying in hash node structure" }, + { 50020, "could not find hash table name" }, + { 50021, "unrecognised object type for lookup delete node" }, + { 50022, "error copying in add table data" }, + { 50023, "invalid unit for lookup add table" }, + { 50024, "pool name already exists" }, + { 50025, "hash table name already exists" }, + { 50026, "unrecognised object type for lookup add table" }, + { 50027, "error copying table data back out" }, + { 50028, "error copying in remove table data" }, + { 50029, "invalid unit for lookup remove table" }, + { 50030, "unrecognised object type for lookup remove table" }, + { 50031, "error copying in lookup stats structure" }, + { 50032, "invalid unit for lookup stats" }, + { 50033, "unrecognised object type for lookup stats" }, + { 50034, "error copying in flush lookup data" }, + { 50035, "invalid unit for lookup flush" }, + { 50036, "incorrect table type for lookup flush" }, + { 50037, "error copying out lookup flush results" }, + { 50038, "invalid unit for lookup iterator" }, + { 50039, "invalid unit for lookup iterator" }, + { 50040, "could not find token for lookup iterator" }, + { 50041, "unrecognised object type for lookup interator" }, + { 50042, "error copying in lookup delete node operation" }, +/* -------------------------------------------------------------------------- */ + { 60001, "insufficient privilege for NAT write operation" }, + { 60002, "need write permissions to flush NAT logs" }, + { 60003, "need write permissions to turn NAT logging on/off" }, + { 60004, "error copying out current NAT log setting" }, + { 60005, "error copying out bytes waiting to be read in NAT \ +log" }, + { 60006, "need write permissions to add NAT rule" }, + { 60007, "NAT rule already exists" }, + { 60008, "could not allocate memory for NAT rule" }, + { 60009, "need write permissions to remove NAT rule" }, + { 60010, "NAT rule could not be found" }, + { 60011, "could not find NAT entry for redirect lookup" }, + { 60012, "need write permissions to flush NAT table" }, + { 60013, "error copying in NAT flush command" }, + { 60014, "need write permissions to do matching NAT flush" }, + { 60015, "need write permissions to set NAT lock" }, + { 60016, "need write permissions to add entry to NAT table" }, + { 60017, "NAT not locked for size retrieval" }, + { 60018, "NAT not locked for fetching NAT table entry" }, + { 60019, "error copying in NAT token data for deletion" }, + { 60020, "unknown NAT ioctl" }, + { 60021, "" }, + { 60022, "resolving proxy name in NAT rule failed" }, + { 60023, "only reply age specified in NAT rule" }, + { 60024, "error doing copyin to determine NAT entry size" }, + { 60025, "error copying out NAT size of 0" }, + { 60026, "NAT entry not found" }, + { 60027, "error doing copyout of NAT entry size" }, + { 60028, "invalid data size for getting NAT entry" }, + { 60029, "could not malloc temporary space for NAT entry" }, + { 60030, "no NAT table entries present" }, + { 60031, "NAT entry to get next from not found" }, + { 60032, "not enough space for proxy structure" }, + { 60033, "not enough space for private proxy data" }, + { 60034, "NAT entry size is too large" }, + { 60035, "could not malloc memory for NAT entry sratch space" }, + { 60036, "" }, + { 60037, "could not malloc memory for NAT entry" }, + { 60038, "could not malloc memory for NAT entry rule" }, + { 60039, "could not resolve NAT entry rule's proxy" }, + { 60040, "cannot add outbound duplicate NAT entry" }, + { 60041, "cannot add inbound duplicate NAT entry" }, + { 60042, "cannot add NAT entry that is neither IN nor OUT" }, + { 60043, "could not malloc memory for NAT proxy data" }, + { 60044, "proxy data size too big" }, + { 60045, "could not malloc proxy private data for NAT entry" }, + { 60046, "could not malloc memory for new NAT filter rule" }, + { 60047, "could not find existing filter rule for NAT entry" }, + { 60048, "insertion into NAT table failed" }, + { 60049, "iterator error copying out hostmap data" }, + { 60050, "iterator error copying out NAT rule data" }, + { 60051, "iterator error copying out NAT entry data" }, + { 60052, "iterator data supplied with NULL pointer" }, + { 60053, "unknown NAT iterator type" }, + { 60054, "unknwon next address type" }, + { 60055, "iterator suppled with unknown type for get-next" }, + { 60056, "unknown lookup group for next address" }, + { 60057, "error copying out NAT log flush results" }, + { 60058, "bucket table type is incorrect" }, + { 60059, "error copying out NAT bucket table" }, + { 60060, "function not found for lookup" }, + { 60061, "address family not supported with SIOCSTPUT" }, + { 60062, "unknown timeout name" }, + { 60063, "cannot allocate new inbound NAT entry table" }, + { 60064, "cannot allocate new outbound NAT entry table" }, + { 60065, "cannot allocate new inbound NAT bucketlen table" }, + { 60066, "cannot allocate new outbound NAT bucketlen table" }, + { 60067, "cannot allocate new NAT rules table" }, + { 60068, "cannot allocate new NAT hostmap table" }, + { 60069, "new source lookup type is not dstlist" }, + { 60070, "cannot allocate NAT rule scratch space" }, + { 60071, "new destination lookup type is not dstlist" }, + { 60072, "function not found for lookup (ipv6)" }, + { 60073, "unknown lookup group for next address (ipv6)" }, + { 60074, "unknown next address type (ipv6)" }, + { 60075, "one object at a time must be copied" }, +/* -------------------------------------------------------------------------- */ + { 70001, "incorrect object size to get pool stats" }, + { 70002, "could not malloc memory for new pool node" }, + { 70003, "invalid addresss length for new pool node" }, + { 70004, "invalid mask length for new pool node" }, + { 70005, "error adding node to pool" }, + { 70006, "pool already exists" }, + { 70007, "could not malloc memory for new pool" }, + { 70008, "could not allocate radix tree for new pool" }, + { 70009, "could not find pool" }, + { 70010, "unknown pool name for iteration" }, + { 70011, "unknown pool iterator" }, + { 70012, "error copying out pool head" }, + { 70013, "error copying out pool node" }, + { 70014, "add node size incorrect" }, + { 70015, "error copying in pool node" }, + { 70016, "" }, + { 70017, "cannot find pool for node" }, + { 70018, "node entry already present in pool" }, + { 70019, "delete node size incorrect" }, + { 70020, "error copying in node to delete" }, + { 70021, "cannot find pool to delete node from" }, + { 70022, "cannot find node to delete in pool" }, + { 70023, "pool name already exists" }, + { 70024, "uid mismatch for node removal" }, + { 70025, "stats device unit is invalid" }, + { 70026, "error copying out statistics" }, + { 70027, "could not remove node from radix tree" }, + { 70028, "incorrect address length in pool node add" }, + { 70029, "incorrect mask length in pool node add" }, + { 70030, "incorrect address length in pool node remove" }, + { 70031, "incorrect mask length in pool node remove" }, + { 70032, "cannot allocate memory for pool context" }, + { 70033, "cannot allocate memory for radix tree context" }, + { 70034, "adding IPv6 node with incorrect address length" }, + { 70035, "IPv4 address not masked" }, + { 70036, "IPv6 address not masked" }, + { 70037, "removing IPv6 node with incorrect address length" }, +/* -------------------------------------------------------------------------- */ + { 80001, "could not find proxy" }, + { 80002, "proxy does not support control operations" }, + { 80003, "could not allocate data to hold proxy operation" }, + { 80004, "unknown proxy ioctl" }, + { 80005, "could not copyin proxy control structure" }, + { 80006, "DNS proxy could not find rule to delete" }, + { 80007, "DNS proxy found existing matching rule" }, + { 80008, "DNS proxy could not allocate memory for new rule" }, + { 80009, "DNS proxy unknown command request" }, +/* -------------------------------------------------------------------------- */ + { 90001, "could not malloc space for new scan structure" }, + { 90002, "scan tag already exists" }, + { 90003, "scan structure in use" }, + { 90004, "could not find matching scan tag for filter rule" }, + { 90005, "could not copyout scan statistics" }, +/* -------------------------------------------------------------------------- */ + { 100001, "cannot find matching state entry to remove" }, + { 100002, "error copying in v4 state flush command" }, + { 100003, "error copying out v4 state flush results" }, + { 100004, "error copying in v6 state flush command" }, + { 100005, "error copying out v6 state flush results" }, + { 100006, "" }, + { 100007, "" }, + { 100008, "need write permissions to flush state log" }, + { 100009, "erorr copyout results of flushing state log" }, + { 100010, "need write permissions to turn state logging on/off" }, + { 100011, "error copying in new state logging state" }, + { 100012, "error copying out current state logging state" }, + { 100013, "error copying out bytes waiting to be read in state \ +log" }, + { 100014, "need write permissions to set state lock" }, + { 100015, "need write permissions to add entry to state table" }, + { 100016, "state not locked for size retrieval" }, + { 100017, "error copying out hash table bucket lengths" }, + { 100018, "could not find token for state iterator" }, + { 100019, "error copying in state token data for deletion" }, + { 100020, "unknown state ioctl" }, + { 100021, "no state table entries present" }, + { 100022, "state entry to get next from not found" }, + { 100023, "could not malloc memory for state entry" }, + { 100024, "could not malloc memory for state entry rule" }, + { 100025, "could not copy back state entry to user space" }, + { 100026, "iterator data supplied with NULL pointer" }, + { 100027, "iterator supplied with 0 item count" }, + { 100028, "iterator type is incorrect" }, + { 100029, "invalid state token data pointer supplied" }, + { 100030, "error copying out next state entry" }, + { 100031, "unrecognised table request" }, + { 100032, "error copying out bucket length data" }, + { 100033, "could not find existing filter rule for state entry" }, + { 100034, "could not find timeout name" }, + { 100035, "could not allocate new state table" }, + { 100036, "could not allocate new state bucket length table" }, +/* -------------------------------------------------------------------------- */ + { 110001, "sync write header magic number is incorrect" }, + { 110002, "sync write header protocol is incorrect" }, + { 110003, "sync write header command is incorrect" }, + { 110004, "sync write header table number is incorrect" }, + { 110005, "data structure too small for sync write operation" }, + { 110006, "zero length data with sync write header" }, + { 110007, "insufficient data for sync write" }, + { 110008, "bad sync read size" }, + { 110009, "interrupted sync read (solaris)" }, + { 110010, "interrupted sync read (hpux)" }, + { 110011, "interrupted sync read (osf)" }, + { 110012, "interrupted sync read" }, + { 110013, "could not malloc memory for sync'd state" }, + { 110014, "could not malloc memory for sync-state list item" }, + { 110015, "sync update could not find state" }, + { 110016, "unrecognised sync state command" }, + { 110017, "could not malloc memory for new sync'd NAT entry" }, + { 110018, "could not malloc memory for sync-NAT list item" }, + { 110019, "sync update could not find NAT entry" }, + { 110020, "unrecognised sync NAT command" }, + { 110021, "ioctls are not handled with sync" }, +/* -------------------------------------------------------------------------- */ + { 120001, "null data pointer for iterator" }, + { 120002, "unit outside of acceptable range" }, + { 120003, "unknown iterator subtype" }, + { 120004, "cannot find dest. list for iteration" }, + { 120005, "error copying out destination iteration list" }, + { 120006, "error copying out destination iteration node" }, + { 120007, "wrong size for frdest_t structure" }, + { 120008, "cannot allocate memory for new destination node" }, + { 120009, "error copying in destination node to add" }, + { 120010, "could not find destination list to add node to" }, + { 120011, "error copying in destination node to remove" }, + { 120012, "could not find dest. list to remove node from" }, + { 120013, "destination list already exists" }, + { 120014, "could not allocate new destination table" }, + { 120015, "could not find destination list to remove" }, + { 120016, "destination list cannot be removed - it is busy" }, + { 120017, "error copying in names for destination" }, + { 120018, "destination name is too long/short" }, + { 120019, "unrecognised address family in destination" }, + { 120020, "" }, + { 120021, "error copying in new destination table" }, + { 120022, "cannot allocate memory for node table" }, + { 120023, "stats object size is incorrect for dest. lists" }, + { 120024, "stats device unit is invalid for dest. lists" }, + { 120025, "error copying out dest. list statistics" }, + { 120026, "cannot allocate memory for destination node" }, + { 120027, "error copying in destination node" }, + { 120028, "cannot allocate memory for destination context " }, +/* -------------------------------------------------------------------------- */ + { 130001, "ioctl denied by system security level" }, + { 130002, "ioctl operation on invalid minor device" }, + { 130003, "ioctl on device denied, ipfitler is disabled" }, + { 130004, "ioctl command not allowed when disabled" }, + { 130005, "ioctl denied due to insufficient authorisation" }, + { 130006, "cannot read while ipfilter is disabled" }, + { 130007, "read on minor device not supported" }, + { 130008, "cannot write while ipfilter is disabled" }, + { 130009, "write on minor device not supported" }, + { 130010, "poll on minor device is not supported" }, + { 130011, "error removing IPv4 filter hooks" }, + { 130012, "error removing IPv6 filter hooks" }, + { 130013, "attaching IPv4 hook failed" }, + { 130014, "attaching IPv6 hook failed" }, + { 130015, "ipf_init_all failed" }, + { 130016, "finding pfil head failed" }, + { 130017, "ipfilter is already initialised and running" }, +}; + + +static ipf_error_entry_t * +find_error(errnum) + int errnum; +{ + ipf_error_entry_t *ie; + + int l = -1, r = IPF_NUM_ERRORS + 1, step; + step = (r - l) / 2;; + + while (step != 0) { + ie = ipf_errors + l + step; + if (ie->iee_number == errnum) + return ie; + step = l + step; + if (ie->iee_number > errnum) + r = step; + else + l = step; + step = (r - l) / 2;; + } + + return NULL; +} + +char * +ipf_geterror(fd, func) + int fd; + ioctlfunc_t *func; +{ + static char text[80]; + ipf_error_entry_t *ie; + int errnum; + + if ((*func)(fd, SIOCIPFINTERROR, &errnum) == 0) { + + ie = find_error(errnum); + if (ie != NULL) + return ie->iee_text; + sprintf(text, "unknown error %d", errnum); + } else { + sprintf(text, "retrieving error number failed (%d)", errno); + } + return text; +} + + +char * +ipf_strerror(errnum) + int errnum; +{ + static char text[80]; + ipf_error_entry_t *ie; + + + ie = find_error(errnum); + if (ie != NULL) + return ie->iee_text; + + sprintf(text, "unknown error %d", errnum); + return text; +} diff --git a/lib/ionames.c b/lib/ionames.c index cc9374d676442..4460875210b5c 100644 --- a/lib/ionames.c +++ b/lib/ionames.c @@ -1,38 +1,39 @@ /* - * Copyright (C) 2000-2005 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ionames.c,v 1.7.4.1 2006/06/16 17:21:02 darrenr Exp $ + * $Id$ */ #include "ipf.h" struct ipopt_names ionames[] ={ { IPOPT_NOP, 0x000001, 1, "nop" }, /* RFC791 */ - { IPOPT_RR, 0x000002, 7, "rr" }, /* 1 route */ - { IPOPT_ZSU, 0x000004, 3, "zsu" }, /* size ?? */ - { IPOPT_MTUP, 0x000008, 3, "mtup" }, /* RFC1191 */ - { IPOPT_MTUR, 0x000010, 3, "mtur" }, /* RFC1191 */ - { IPOPT_ENCODE, 0x000020, 3, "encode" }, /* size ?? */ + { IPOPT_RR, 0x000002, 8, "rr" }, /* 1 route */ + { IPOPT_ZSU, 0x000004, 4, "zsu" }, /* size ?? */ + { IPOPT_MTUP, 0x000008, 4, "mtup" }, /* RFC1191 */ + { IPOPT_MTUR, 0x000010, 4, "mtur" }, /* RFC1191 */ + { IPOPT_ENCODE, 0x000020, 4, "encode" }, /* size ?? */ { IPOPT_TS, 0x000040, 8, "ts" }, /* 1 TS */ - { IPOPT_TR, 0x000080, 3, "tr" }, /* RFC1393 */ - { IPOPT_SECURITY,0x000100, 11, "sec" }, /* RFC1108 */ - { IPOPT_SECURITY,0x000100, 11, "sec-class" }, /* RFC1108 */ - { IPOPT_LSRR, 0x000200, 7, "lsrr" }, /* 1 route */ - { IPOPT_E_SEC, 0x000400, 3, "e-sec" }, /* RFC1108 */ - { IPOPT_CIPSO, 0x000800, 3, "cipso" }, /* size ?? */ + { IPOPT_TR, 0x000080, 4, "tr" }, /* RFC1393 */ + { IPOPT_SECURITY,0x000100, 12, "sec" }, /* RFC1108 */ + { IPOPT_SECURITY,0x000100, 12, "sec-class" }, /* RFC1108 */ + { IPOPT_LSRR, 0x000200, 8, "lsrr" }, /* 1 route */ + { IPOPT_E_SEC, 0x000400, 8, "e-sec" }, /* RFC1108 */ + { IPOPT_CIPSO, 0x000800, 8, "cipso" }, /* size ?? */ { IPOPT_SATID, 0x001000, 4, "satid" }, /* RFC791 */ - { IPOPT_SSRR, 0x002000, 7, "ssrr" }, /* 1 route */ - { IPOPT_ADDEXT, 0x004000, 3, "addext" }, /* IPv7 ?? */ - { IPOPT_VISA, 0x008000, 3, "visa" }, /* size ?? */ - { IPOPT_IMITD, 0x010000, 3, "imitd" }, /* size ?? */ - { IPOPT_EIP, 0x020000, 3, "eip" }, /* RFC1385 */ - { IPOPT_FINN, 0x040000, 3, "finn" }, /* size ?? */ - { IPOPT_DPS, 0x080000, 3, "dps" }, /* size ?? */ - { IPOPT_SDB, 0x100000, 3, "sdb" }, /* size ?? */ - { IPOPT_NSAPA, 0x200000, 3, "nsapa" }, /* size ?? */ - { IPOPT_RTRALRT,0x400000, 3, "rtralrt" }, /* RFC2113 */ - { IPOPT_UMP, 0x800000, 3, "ump" }, /* size ?? */ + { IPOPT_SSRR, 0x002000, 8, "ssrr" }, /* 1 route */ + { IPOPT_ADDEXT, 0x004000, 4, "addext" }, /* IPv7 ?? */ + { IPOPT_VISA, 0x008000, 4, "visa" }, /* size ?? */ + { IPOPT_IMITD, 0x010000, 4, "imitd" }, /* size ?? */ + { IPOPT_EIP, 0x020000, 4, "eip" }, /* RFC1385 */ + { IPOPT_FINN, 0x040000, 4, "finn" }, /* size ?? */ + { IPOPT_DPS, 0x080000, 4, "dps" }, /* size ?? */ + { IPOPT_SDB, 0x100000, 4, "sdb" }, /* size ?? */ + { IPOPT_NSAPA, 0x200000, 4, "nsapa" }, /* size ?? */ + { IPOPT_RTRALRT,0x400000, 4, "rtralrt" }, /* RFC2113 */ + { IPOPT_UMP, 0x800000, 4, "ump" }, /* size ?? */ + { IPOPT_AH, 0x1000000, 0, "ah" }, /* IPPROTO_AH */ { 0, 0, 0, (char *)NULL } /* must be last */ }; diff --git a/lib/ipf_dotuning.c b/lib/ipf_dotuning.c index 8f90fdbe95a95..fb009a3a6d564 100644 --- a/lib/ipf_dotuning.c +++ b/lib/ipf_dotuning.c @@ -1,19 +1,19 @@ /* - * Copyright (C) 2003-2005 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: ipf_dotuning.c,v 1.2.4.3 2006/06/16 17:21:02 darrenr Exp $ - */ + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ #include "ipf.h" #include "netinet/ipl.h" #include <sys/ioctl.h> void ipf_dotuning(fd, tuneargs, iocfn) -int fd; -char *tuneargs; -ioctlfunc_t iocfn; + int fd; + char *tuneargs; + ioctlfunc_t iocfn; { ipfobj_t obj; ipftune_t tu; @@ -29,7 +29,8 @@ ioctlfunc_t iocfn; if (!strcmp(s, "list")) { while (1) { if ((*iocfn)(fd, SIOCIPFGETNEXT, &obj) == -1) { - perror("ioctl(SIOCIPFGETNEXT)"); + ipf_perror_fd(fd, iocfn, + "ioctl(SIOCIPFGETNEXT)"); break; } if (tu.ipft_cookie == NULL) @@ -44,7 +45,8 @@ ioctlfunc_t iocfn; strncpy(tu.ipft_name, s, sizeof(tu.ipft_name)); if (sscanf(t, "%lu", &tu.ipft_vlong) == 1) { if ((*iocfn)(fd, SIOCIPFSET, &obj) == -1) { - perror("ioctl(SIOCIPFSET)"); + ipf_perror_fd(fd, iocfn, + "ioctl(SIOCIPFSET)"); return; } } else { @@ -55,7 +57,7 @@ ioctlfunc_t iocfn; tu.ipft_cookie = NULL; strncpy(tu.ipft_name, s, sizeof(tu.ipft_name)); if ((*iocfn)(fd, SIOCIPFGET, &obj) == -1) { - perror("ioctl(SIOCIPFGET)"); + ipf_perror_fd(fd, iocfn, "ioctl(SIOCIPFGET)"); return; } if (tu.ipft_cookie == NULL) { diff --git a/lib/ipf_perror.c b/lib/ipf_perror.c new file mode 100644 index 0000000000000..85a1b1d66e2ec --- /dev/null +++ b/lib/ipf_perror.c @@ -0,0 +1,47 @@ +#include <fcntl.h> +#include <sys/ioctl.h> +#include "ipf.h" + +void +ipf_perror(err, string) + int err; + char *string; +{ + if (err == 0) + fprintf(stderr, "%s\n", string); + else + fprintf(stderr, "%s %s\n", string, ipf_strerror(err)); +} + +int +ipf_perror_fd(fd, iocfunc, string) + int fd; + ioctlfunc_t iocfunc; + char *string; +{ + int save; + int realerr; + + save = errno; + if ((*iocfunc)(fd, SIOCIPFINTERROR, &realerr) == -1) + realerr = 0; + + errno = save; + fprintf(stderr, "%d:", realerr); + ipf_perror(realerr, string); + return realerr ? realerr : save; + +} + +void +ipferror(fd, msg) + int fd; + char *msg; +{ + if (fd >= 0) { + ipf_perror_fd(fd, ioctl, msg); + } else { + fprintf(stderr, "0:"); + perror(msg); + } +} diff --git a/lib/ipft_ef.c b/lib/ipft_ef.c deleted file mode 100644 index 52eb508de6b14..0000000000000 --- a/lib/ipft_ef.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2000-2006 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: ipft_ef.c,v 1.14.2.2 2006/06/16 17:21:02 darrenr Exp $ - */ - -/* - icmp type - lnth proto source destination src port dst port - -etherfind -n - - 60 tcp 128.250.20.20 128.250.133.13 2419 telnet - -etherfind -n -t - - 0.32 91 04 131.170.1.10 128.250.133.13 - 0.33 566 udp 128.250.37.155 128.250.133.3 901 901 -*/ - -#include "ipf.h" -#include "ipt.h" - -#ifndef linux -#include <netinet/ip_var.h> -#endif -#include <netinet/tcpip.h> - - -#if !defined(lint) -static const char sccsid[] = "@(#)ipft_ef.c 1.6 2/4/96 (C)1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipft_ef.c,v 1.14.2.2 2006/06/16 17:21:02 darrenr Exp $"; -#endif - -static int etherf_open __P((char *)); -static int etherf_close __P((void)); -static int etherf_readip __P((char *, int, char **, int *)); - -struct ipread etherf = { etherf_open, etherf_close, etherf_readip, 0 }; - -static FILE *efp = NULL; -static int efd = -1; - - -static int etherf_open(fname) -char *fname; -{ - if (efd != -1) - return efd; - - if (!strcmp(fname, "-")) { - efd = 0; - efp = stdin; - } else { - efd = open(fname, O_RDONLY); - efp = fdopen(efd, "r"); - } - return efd; -} - - -static int etherf_close() -{ - return close(efd); -} - - -static int etherf_readip(buf, cnt, ifn, dir) -char *buf, **ifn; -int cnt, *dir; -{ - struct tcpiphdr pkt; - ip_t *ip = (ip_t *)&pkt; - char src[16], dst[16], sprt[16], dprt[16]; - char lbuf[128], len[8], prot[8], time[8], *s; - int slen, extra = 0, i; - - if (!fgets(lbuf, sizeof(lbuf) - 1, efp)) - return 0; - - if ((s = strchr(lbuf, '\n'))) - *s = '\0'; - lbuf[sizeof(lbuf)-1] = '\0'; - - bzero(&pkt, sizeof(pkt)); - - if (sscanf(lbuf, "%7s %7s %15s %15s %15s %15s", len, prot, src, dst, - sprt, dprt) != 6) - if (sscanf(lbuf, "%7s %7s %7s %15s %15s %15s %15s", time, - len, prot, src, dst, sprt, dprt) != 7) - return -1; - - ip->ip_p = getproto(prot); - - switch (ip->ip_p) { - case IPPROTO_TCP : - if (isdigit(*sprt)) - pkt.ti_sport = htons(atoi(sprt) & 65535); - if (isdigit(*dprt)) - pkt.ti_dport = htons(atoi(dprt) & 65535); - extra = sizeof(struct tcphdr); - break; - case IPPROTO_UDP : - if (isdigit(*sprt)) - pkt.ti_sport = htons(atoi(sprt) & 65535); - if (isdigit(*dprt)) - pkt.ti_dport = htons(atoi(dprt) & 65535); - extra = sizeof(struct udphdr); - break; -#ifdef IGMP - case IPPROTO_IGMP : - extra = sizeof(struct igmp); - break; -#endif - case IPPROTO_ICMP : - extra = sizeof(struct icmp); - break; - default : - break; - } - - (void) inet_aton(src, &ip->ip_src); - (void) inet_aton(dst, &ip->ip_dst); - ip->ip_len = atoi(len); - IP_HL_A(ip, sizeof(ip_t)); - - slen = IP_HL(ip) + extra; - i = MIN(cnt, slen); - bcopy((char *)&pkt, buf, i); - return i; -} diff --git a/lib/ipft_hx.c b/lib/ipft_hx.c index 4851fff3eae4a..18fee1e64a0aa 100644 --- a/lib/ipft_hx.c +++ b/lib/ipft_hx.c @@ -1,11 +1,11 @@ /* - * Copyright (C) 2000-2005 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #if !defined(lint) static const char sccsid[] = "@(#)ipft_hx.c 1.1 3/9/96 (C) 1996 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipft_hx.c,v 1.11.4.4 2006/06/16 17:21:03 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #include <ctype.h> @@ -18,7 +18,7 @@ extern int opts; static int hex_open __P((char *)); static int hex_close __P((void)); -static int hex_readip __P((char *, int, char **, int *)); +static int hex_readip __P((mb_t *, char **, int *)); static char *readhex __P((char *, char *)); struct ipread iphex = { hex_open, hex_close, hex_readip, 0 }; @@ -26,7 +26,7 @@ static FILE *tfp = NULL; static int tfd = -1; static int hex_open(fname) -char *fname; + char *fname; { if (tfp && tfd != -1) { rewind(tfp); @@ -54,14 +54,19 @@ static int hex_close() } -static int hex_readip(buf, cnt, ifn, dir) -char *buf, **ifn; -int cnt, *dir; +static int hex_readip(mb, ifn, dir) + mb_t *mb; + char **ifn; + int *dir; { register char *s, *t, *u; char line[513]; ip_t *ip; + char *buf; + int cnt; + buf = (char *)mb->mb_buf; + cnt = sizeof(mb->mb_buf); /* * interpret start of line as possibly "[ifname]" or * "[in/out,ifname]". @@ -73,8 +78,10 @@ int cnt, *dir; ip = (ip_t *)buf; while (fgets(line, sizeof(line)-1, tfp)) { if ((s = strchr(line, '\n'))) { - if (s == line) - return (char *)ip - buf; + if (s == line) { + mb->mb_len = (char *)ip - buf; + return mb->mb_len; + } *s = '\0'; } if ((s = strchr(line, '#'))) @@ -102,17 +109,35 @@ int cnt, *dir; } else if (ifn) *ifn = t; } + + while (*s++ == '+') { + if (!strncasecmp(s, "mcast", 5)) { + mb->mb_flags |= M_MCAST; + s += 5; + } + if (!strncasecmp(s, "bcast", 5)) { + mb->mb_flags |= M_BCAST; + s += 5; + } + if (!strncasecmp(s, "mbcast", 6)) { + mb->mb_flags |= M_MBCAST; + s += 6; + } + } + while (ISSPACE(*s)) + s++; } else s = line; t = (char *)ip; ip = (ip_t *)readhex(s, (char *)ip); if ((opts & OPT_DEBUG) != 0) { if (opts & OPT_ASCII) { + int c = *t; if (t < (char *)ip) putchar('\t'); while (t < (char *)ip) { - if (ISPRINT(*t) && ISASCII(*t)) - putchar(*t); + if (isprint(c) && isascii(c)) + putchar(c); else putchar('.'); t++; diff --git a/lib/ipft_pc.c b/lib/ipft_pc.c index fbfe6b063db5a..c141cf5c8842b 100644 --- a/lib/ipft_pc.c +++ b/lib/ipft_pc.c @@ -1,17 +1,15 @@ /* - * Copyright (C) 2000-2005 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ipft_pc.c,v 1.10.2.2 2006/06/16 17:21:03 darrenr Exp $ + * $Id$ */ #include "ipf.h" -#include "pcap-ipf.h" -#include "bpf-ipf.h" #include "ipt.h" #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ipft_pc.c,v 1.10.2.2 2006/06/16 17:21:03 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif struct llc { @@ -27,79 +25,61 @@ struct llc { */ static struct llc llcs[] = { - { DLT_NULL, 0, 0, 0 }, - { DLT_EN10MB, 14, 12, 2 }, - { DLT_EN3MB, 0, 0, 0 }, - { DLT_AX25, 0, 0, 0 }, - { DLT_PRONET, 0, 0, 0 }, - { DLT_CHAOS, 0, 0, 0 }, - { DLT_IEEE802, 0, 0, 0 }, - { DLT_ARCNET, 0, 0, 0 }, - { DLT_SLIP, 0, 0, 0 }, - { DLT_PPP, 0, 0, 0 }, - { DLT_FDDI, 0, 0, 0 }, -#ifdef DLT_ATMRFC1483 - { DLT_ATMRFC1483, 0, 0, 0 }, -#endif - { DLT_RAW, 0, 0, 0 }, -#ifdef DLT_ENC - { DLT_ENC, 0, 0, 0 }, -#endif -#ifdef DLT_SLIP_BSDOS - { DLT_SLIP_BSDOS, 0, 0, 0 }, -#endif -#ifdef DLT_PPP_BSDOS - { DLT_PPP_BSDOS, 0, 0, 0 }, -#endif -#ifdef DLT_HIPPI - { DLT_HIPPI, 0, 0, 0 }, -#endif -#ifdef DLT_HDLC - { DLT_HDLC, 0, 0, 0 }, -#endif -#ifdef DLT_PPP_SERIAL - { DLT_PPP_SERIAL, 4, 4, 0 }, -#endif -#ifdef DLT_PPP_ETHER - { DLT_PPP_ETHER, 8, 8, 0 }, -#endif -#ifdef DLT_ECONET - { DLT_ECONET, 0, 0, 0 }, -#endif + { 0, 0, 0, 0 }, /* DLT_NULL */ + { 1, 14, 12, 2 }, /* DLT_Ethernet */ + { 10, 0, 0, 0 }, /* DLT_FDDI */ + { 12, 0, 0, 0 }, /* DLT_RAW */ { -1, -1, -1, -1 } }; -static int pcap_open __P((char *)); -static int pcap_close __P((void)); -static int pcap_readip __P((char *, int, char **, int *)); -static void swap_hdr __P((pcaphdr_t *)); -static int pcap_read_rec __P((struct pcap_pkthdr *)); +typedef struct { + u_int id; + u_short major; + u_short minor; + u_int timezone; + u_int sigfigs; + u_int snaplen; + u_int type; +} fileheader_t; + +typedef struct { + u_32_t seconds; + u_32_t microseconds; + u_32_t caplen; + u_32_t wirelen; +} packetheader_t; + +static int ipcap_open __P((char *)); +static int ipcap_close __P((void)); +static int ipcap_readip __P((mb_t *, char **, int *)); +static int ipcap_read_rec __P((packetheader_t *)); +static void iswap_hdr __P((fileheader_t *)); static int pfd = -1, swapped = 0; static struct llc *llcp = NULL; -struct ipread pcap = { pcap_open, pcap_close, pcap_readip, 0 }; +struct ipread pcap = { ipcap_open, ipcap_close, ipcap_readip, 0 }; #define SWAPLONG(y) \ ((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff)) #define SWAPSHORT(y) \ ( (((y)&0xff)<<8) | (((y)&0xff00)>>8) ) -static void swap_hdr(p) -pcaphdr_t *p; +static void iswap_hdr(p) + fileheader_t *p; { - p->pc_v_maj = SWAPSHORT(p->pc_v_maj); - p->pc_v_min = SWAPSHORT(p->pc_v_min); - p->pc_zone = SWAPLONG(p->pc_zone); - p->pc_sigfigs = SWAPLONG(p->pc_sigfigs); - p->pc_slen = SWAPLONG(p->pc_slen); - p->pc_type = SWAPLONG(p->pc_type); + p->major = SWAPSHORT(p->major); + p->minor = SWAPSHORT(p->minor); + p->timezone = SWAPLONG(p->timezone); + p->sigfigs = SWAPLONG(p->sigfigs); + p->snaplen = SWAPLONG(p->snaplen); + p->type = SWAPLONG(p->type); } -static int pcap_open(fname) -char *fname; +static int ipcap_open(fname) + char *fname; { - pcaphdr_t ph; + fileheader_t ph; int fd, i; if (pfd != -1) @@ -113,22 +93,17 @@ char *fname; if (read(fd, (char *)&ph, sizeof(ph)) != sizeof(ph)) return -2; - if (ph.pc_id != TCPDUMP_MAGIC) { - if (SWAPLONG(ph.pc_id) != TCPDUMP_MAGIC) { + if (ph.id != 0xa1b2c3d4) { + if (SWAPLONG(ph.id) != 0xa1b2c3d4) { (void) close(fd); return -2; } swapped = 1; - swap_hdr(&ph); - } - - if (ph.pc_v_maj != PCAP_VERSION_MAJ) { - (void) close(fd); - return -2; + iswap_hdr(&ph); } for (i = 0; llcs[i].lc_type != -1; i++) - if (llcs[i].lc_type == ph.pc_type) { + if (llcs[i].lc_type == ph.type) { llcp = llcs + i; break; } @@ -141,13 +116,13 @@ char *fname; pfd = fd; printf("opened pcap file %s:\n", fname); printf("\tid: %08x version: %d.%d type: %d snap %d\n", - ph.pc_id, ph.pc_v_maj, ph.pc_v_min, ph.pc_type, ph.pc_slen); + ph.id, ph.major, ph.minor, ph.type, ph.snaplen); return fd; } -static int pcap_close() +static int ipcap_close() { return close(pfd); } @@ -157,8 +132,8 @@ static int pcap_close() * read in the header (and validate) which should be the first record * in a pcap file. */ -static int pcap_read_rec(rec) -struct pcap_pkthdr *rec; +static int ipcap_read_rec(rec) + packetheader_t *rec; { int n, p, i; char *s; @@ -175,13 +150,13 @@ struct pcap_pkthdr *rec; } if (swapped) { - rec->ph_clen = SWAPLONG(rec->ph_clen); - rec->ph_len = SWAPLONG(rec->ph_len); - rec->ph_ts.tv_sec = SWAPLONG(rec->ph_ts.tv_sec); - rec->ph_ts.tv_usec = SWAPLONG(rec->ph_ts.tv_usec); + rec->caplen = SWAPLONG(rec->caplen); + rec->wirelen = SWAPLONG(rec->wirelen); + rec->seconds = SWAPLONG(rec->seconds); + rec->microseconds = SWAPLONG(rec->microseconds); } - p = rec->ph_clen; - n = MIN(p, rec->ph_len); + p = rec->caplen; + n = MIN(p, rec->wirelen); if (!n || n < 0) return -3; @@ -196,15 +171,15 @@ struct pcap_pkthdr *rec; * read an entire pcap packet record. only the data part is copied into * the available buffer, with the number of bytes copied returned. */ -static int pcap_read(buf, cnt) -char *buf; -int cnt; +static int ipcap_read(buf, cnt) + char *buf; + int cnt; { - struct pcap_pkthdr rec; + packetheader_t rec; static char *bufp = NULL; int i, n; - if ((i = pcap_read_rec(&rec)) <= 0) + if ((i = ipcap_read_rec(&rec)) <= 0) return i; if (!bufp) @@ -225,20 +200,27 @@ int cnt; /* * return only an IP packet read into buf */ -static int pcap_readip(buf, cnt, ifn, dir) -char *buf, **ifn; -int cnt, *dir; +static int ipcap_readip(mb, ifn, dir) + mb_t *mb; + char **ifn; + int *dir; { static char *bufp = NULL; - struct pcap_pkthdr rec; + packetheader_t rec; struct llc *l; char *s, ty[4]; int i, j, n; + char *buf; + int cnt; + ifn = ifn; /* gcc -Wextra */ + dir = dir; /* gcc -Wextra */ + buf = (char *)mb->mb_buf; + cnt = sizeof(mb->mb_buf); l = llcp; /* do { */ - if ((i = pcap_read_rec(&rec)) <= 0) + if ((i = ipcap_read_rec(&rec)) <= 0) return i; if (!bufp) @@ -263,5 +245,6 @@ int cnt, *dir; /* } while (ty[0] != 0x8 && ty[1] != 0); */ n = MIN(i, cnt); bcopy(s, buf, n); + mb->mb_len = n; return n; } diff --git a/lib/ipft_sn.c b/lib/ipft_sn.c deleted file mode 100644 index a4c73185cee3c..0000000000000 --- a/lib/ipft_sn.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (C) 2000-2003 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: ipft_sn.c,v 1.7.4.1 2006/06/16 17:21:03 darrenr Exp $ - */ - -/* - * Written to comply with the recent RFC 1761 from Sun. - */ -#include "ipf.h" -#include "snoop.h" -#include "ipt.h" - -#if !defined(lint) -static const char rcsid[] = "@(#)$Id: ipft_sn.c,v 1.7.4.1 2006/06/16 17:21:03 darrenr Exp $"; -#endif - -struct llc { - int lc_sz; /* LLC header length */ - int lc_to; /* LLC Type offset */ - int lc_tl; /* LLC Type length */ -}; - -/* - * While many of these maybe the same, some do have different header formats - * which make this useful. - */ -static struct llc llcs[SDL_MAX+1] = { - { 0, 0, 0 }, /* SDL_8023 */ - { 0, 0, 0 }, /* SDL_8024 */ - { 0, 0, 0 }, /* SDL_8025 */ - { 0, 0, 0 }, /* SDL_8026 */ - { 14, 12, 2 }, /* SDL_ETHER */ - { 0, 0, 0 }, /* SDL_HDLC */ - { 0, 0, 0 }, /* SDL_CHSYNC */ - { 0, 0, 0 }, /* SDL_IBMCC */ - { 0, 0, 0 }, /* SDL_FDDI */ - { 0, 0, 0 }, /* SDL_OTHER */ -}; - -static int snoop_open __P((char *)); -static int snoop_close __P((void)); -static int snoop_readip __P((char *, int, char **, int *)); - -static int sfd = -1, s_type = -1; -static int snoop_read_rec __P((struct snooppkt *)); - -struct ipread snoop = { snoop_open, snoop_close, snoop_readip, 0 }; - - -static int snoop_open(fname) -char *fname; -{ - struct snoophdr sh; - int fd; - int s_v; - - if (sfd != -1) - return sfd; - - if (!strcmp(fname, "-")) - fd = 0; - else if ((fd = open(fname, O_RDONLY)) == -1) - return -1; - - if (read(fd, (char *)&sh, sizeof(sh)) != sizeof(sh)) - return -2; - - s_v = (int)ntohl(sh.s_v); - s_type = (int)ntohl(sh.s_type); - - if (s_v != SNOOP_VERSION || - s_type < 0 || s_type > SDL_MAX) { - (void) close(fd); - return -2; - } - - sfd = fd; - printf("opened snoop file %s:\n", fname); - printf("\tid: %8.8s version: %d type: %d\n", sh.s_id, s_v, s_type); - - return fd; -} - - -static int snoop_close() -{ - return close(sfd); -} - - -/* - * read in the header (and validate) which should be the first record - * in a snoop file. - */ -static int snoop_read_rec(rec) -struct snooppkt *rec; -{ - int n, plen, ilen; - - if (read(sfd, (char *)rec, sizeof(*rec)) != sizeof(*rec)) - return -2; - - ilen = (int)ntohl(rec->sp_ilen); - plen = (int)ntohl(rec->sp_plen); - if (ilen > plen || plen < sizeof(*rec)) - return -2; - - plen -= sizeof(*rec); - n = MIN(plen, ilen); - if (!n || n < 0) - return -3; - - return plen; -} - - -#ifdef notyet -/* - * read an entire snoop packet record. only the data part is copied into - * the available buffer, with the number of bytes copied returned. - */ -static int snoop_read(buf, cnt) -char *buf; -int cnt; -{ - struct snooppkt rec; - static char *bufp = NULL; - int i, n; - - if ((i = snoop_read_rec(&rec)) <= 0) - return i; - - if (!bufp) - bufp = malloc(i); - else - bufp = realloc(bufp, i); - - if (read(sfd, bufp, i) != i) - return -2; - - n = MIN(i, cnt); - bcopy(bufp, buf, n); - return n; -} -#endif - - -/* - * return only an IP packet read into buf - */ -static int snoop_readip(buf, cnt, ifn, dir) -char *buf, **ifn; -int cnt, *dir; -{ - static char *bufp = NULL; - struct snooppkt rec; - struct llc *l; - char ty[4], *s; - int i, n; - - do { - if ((i = snoop_read_rec(&rec)) <= 0) - return i; - - if (!bufp) - bufp = malloc(i); - else - bufp = realloc(bufp, i); - s = bufp; - - if (read(sfd, s, i) != i) - return -2; - - l = &llcs[s_type]; - i -= l->lc_to; - s += l->lc_to; - /* - * XXX - bogus assumption here on the part of the time field - * that it won't be greater than 4 bytes and the 1st two will - * have the values 8 and 0 for IP. Should be a table of - * these too somewhere. Really only works for SDL_ETHER. - */ - bcopy(s, ty, l->lc_tl); - } while (ty[0] != 0x8 && ty[1] != 0); - - i -= l->lc_tl; - s += l->lc_tl; - n = MIN(i, cnt); - bcopy(s, buf, n); - - return n; -} diff --git a/lib/ipft_td.c b/lib/ipft_td.c deleted file mode 100644 index 21bb76430e149..0000000000000 --- a/lib/ipft_td.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2000-2006 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: ipft_td.c,v 1.15.2.2 2006/06/16 17:21:03 darrenr Exp $ - */ - -/* -tcpdump -n - -00:05:47.816843 128.231.76.76.3291 > 224.2.252.231.36573: udp 36 (encap) - -tcpdump -nq - -00:33:48.410771 192.73.213.11.1463 > 224.2.248.153.59360: udp 31 (encap) - -tcpdump -nqt - -128.250.133.13.23 > 128.250.20.20.2419: tcp 27 - -tcpdump -nqtt - -123456789.1234567 128.250.133.13.23 > 128.250.20.20.2419: tcp 27 - -tcpdump -nqte - -8:0:20:f:65:f7 0:0:c:1:8a:c5 81: 128.250.133.13.23 > 128.250.20.20.2419: tcp 27 - -*/ - -#include "ipf.h" -#include "ipt.h" - -#ifndef linux -#include <netinet/ip_var.h> -#endif -#include <netinet/tcpip.h> - - -#if !defined(lint) -static const char sccsid[] = "@(#)ipft_td.c 1.8 2/4/96 (C)1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipft_td.c,v 1.15.2.2 2006/06/16 17:21:03 darrenr Exp $"; -#endif - -static int tcpd_open __P((char *)); -static int tcpd_close __P((void)); -static int tcpd_readip __P((char *, int, char **, int *)); -static int count_dots __P((char *)); - -struct ipread tcpd = { tcpd_open, tcpd_close, tcpd_readip, 0 }; - -static FILE *tfp = NULL; -static int tfd = -1; - - -static int tcpd_open(fname) -char *fname; -{ - if (tfd != -1) - return tfd; - - if (!strcmp(fname, "-")) { - tfd = 0; - tfp = stdin; - } else { - tfd = open(fname, O_RDONLY); - tfp = fdopen(tfd, "r"); - } - return tfd; -} - - -static int tcpd_close() -{ - (void) fclose(tfp); - return close(tfd); -} - - -static int count_dots(str) -char *str; -{ - int i = 0; - - while (*str) - if (*str++ == '.') - i++; - return i; -} - - -static int tcpd_readip(buf, cnt, ifn, dir) -char *buf, **ifn; -int cnt, *dir; -{ - struct tcpiphdr pkt; - ip_t *ip = (ip_t *)&pkt; - char src[32], dst[32], misc[256], time[32], link1[32], link2[32]; - char lbuf[160], *s; - int n, slen, extra = 0; - - if (!fgets(lbuf, sizeof(lbuf) - 1, tfp)) - return 0; - - if ((s = strchr(lbuf, '\n'))) - *s = '\0'; - lbuf[sizeof(lbuf)-1] = '\0'; - - bzero(&pkt, sizeof(pkt)); - - if ((n = sscanf(lbuf, "%31s > %31s: %255s", src, dst, misc)) != 3) - if ((n = sscanf(lbuf, "%31s %31s > %31s: %255s", - time, src, dst, misc)) != 4) - if ((n = sscanf(lbuf, "%31s %31s: %31s > %31s: %255s", - link1, link2, src, dst, misc)) != 5) { - n = sscanf(lbuf, - "%31s %31s %31s: %31s > %31s: %255s", - time, link1, link2, src, dst, misc); - if (n != 6) - return -1; - } - - if (count_dots(dst) == 4) { - s = strrchr(src, '.'); - *s++ = '\0'; - (void) inet_aton(src, &ip->ip_src); - pkt.ti_sport = htons(atoi(s)); - *--s = '.'; - s = strrchr(dst, '.'); - - *s++ = '\0'; - (void) inet_aton(src, &ip->ip_dst); - pkt.ti_dport = htons(atoi(s)); - *--s = '.'; - - } else { - (void) inet_aton(src, &ip->ip_src); - (void) inet_aton(src, &ip->ip_dst); - } - ip->ip_len = sizeof(ip_t); - IP_HL_A(ip, sizeof(ip_t)); - - s = strtok(misc, " :"); - if (s == NULL) - return 0; - ip->ip_p = getproto(s); - - switch (ip->ip_p) - { - case IPPROTO_TCP : - case IPPROTO_UDP : - s = strtok(NULL, " :"); - if (s == NULL) - return 0; - ip->ip_len += atoi(s); - if (ip->ip_p == IPPROTO_TCP) - extra = sizeof(struct tcphdr); - else if (ip->ip_p == IPPROTO_UDP) - extra = sizeof(struct udphdr); - break; -#ifdef IGMP - case IPPROTO_IGMP : - extra = sizeof(struct igmp); - break; -#endif - case IPPROTO_ICMP : - extra = sizeof(struct icmp); - break; - default : - break; - } - - slen = IP_HL(ip) + extra + ip->ip_len; - return slen; -} diff --git a/lib/ipft_tx.c b/lib/ipft_tx.c index 5dc65b42be2fc..726b85a25f57c 100644 --- a/lib/ipft_tx.c +++ b/lib/ipft_tx.c @@ -1,13 +1,13 @@ /* - * Copyright (C) 2000-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ipft_tx.c,v 1.15.2.10 2007/09/03 21:54:44 darrenr Exp $ + * $Id$ */ #if !defined(lint) static const char sccsid[] = "@(#)ipft_tx.c 1.7 6/5/96 (C) 1993 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipft_tx.c,v 1.15.2.10 2007/09/03 21:54:44 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #include <ctype.h> @@ -15,18 +15,12 @@ static const char rcsid[] = "@(#)$Id: ipft_tx.c,v 1.15.2.10 2007/09/03 21:54:44 #include "ipf.h" #include "ipt.h" -#ifndef linux -#include <netinet/ip_var.h> -#endif -#include <netinet/tcpip.h> - - extern int opts; static char *tx_proto = ""; static int text_open __P((char *)), text_close __P((void)); -static int text_readip __P((char *, int, char **, int *)); +static int text_readip __P((mb_t *, char **, int *)); static int parseline __P((char *, ip_t *, char **, int *)); static char myflagset[] = "FSRPAUEC"; @@ -40,16 +34,19 @@ static int tfd = -1; static u_32_t tx_hostnum __P((char *, int *)); static u_short tx_portnum __P((char *)); +#ifdef USE_INET6 +int parseipv6 __P((char **, ip6_t *, char **, int *)); +#endif /* * returns an ip address as a long var as a result of either a DNS lookup or * straight inet_addr() call */ static u_32_t tx_hostnum(host, resolved) -char *host; -int *resolved; + char *host; + int *resolved; { - u_32_t ipa; + i6addr_t ipa; *resolved = 0; if (!strcasecmp("any", host)) @@ -57,12 +54,12 @@ int *resolved; if (ISDIGIT(*host)) return inet_addr(host); - if (gethost(host, &ipa) == -1) { + if (gethost(AF_INET, host, &ipa) == -1) { *resolved = -1; fprintf(stderr, "can't resolve hostname: %s\n", host); return 0; } - return ipa; + return ipa.in4.s_addr; } @@ -71,7 +68,7 @@ int *resolved; * straight atoi() */ static u_short tx_portnum(name) -char *name; + char *name; { struct servent *sp; @@ -85,15 +82,8 @@ char *name; } -char *tx_icmptypes[] = { - "echorep", (char *)NULL, (char *)NULL, "unreach", "squench", - "redir", (char *)NULL, (char *)NULL, "echo", "routerad", - "routersol", "timex", "paramprob", "timest", "timestrep", - "inforeq", "inforep", "maskreq", "maskrep", "END" -}; - static int text_open(fname) -char *fname; + char *fname; { if (tfp && tfd != -1) { rewind(tfp); @@ -121,13 +111,19 @@ static int text_close() } -static int text_readip(buf, cnt, ifn, dir) -char *buf, **ifn; -int cnt, *dir; +static int text_readip(mb, ifn, dir) + mb_t *mb; + char **ifn; + int *dir; { register char *s; char line[513]; ip_t *ip; + char *buf; + int cnt; + + buf = (char *)mb->mb_buf; + cnt = sizeof(mb->mb_buf); *ifn = NULL; while (fgets(line, sizeof(line)-1, tfp)) { @@ -145,7 +141,17 @@ int cnt, *dir; *dir = 0; if (!parseline(line, (ip_t *)buf, ifn, dir)) { ip = (ip_t *)buf; - return ntohs(ip->ip_len); + if (IP_V(ip) == 6) { +#ifdef USE_INET6 + mb->mb_len = ntohs(((ip6_t *)ip)->ip6_plen) + + sizeof(ip6_t); +#else + mb->mb_len = 0; +#endif + } else { + mb->mb_len = ntohs(ip->ip_len); + } + return mb->mb_len; } } if (feof(tfp)) @@ -154,10 +160,10 @@ int cnt, *dir; } static int parseline(line, ip, ifn, out) -char *line; -ip_t *ip; -char **ifn; -int *out; + char *line; + ip_t *ip; + char **ifn; + int *out; { tcphdr_t th, *tcp = &th; struct icmp icmp, *ic = &icmp; @@ -172,6 +178,7 @@ int *out; bzero(ipopts, sizeof(ipopts)); IP_HL_A(ip, sizeof(*ip) >> 2); IP_V_A(ip, IPVERSION); + ip->ip_ttl = 63; for (i = 0, cps[0] = strtok(line, " \b\t\r\n"); cps[i] && i < 19; ) cps[++i] = strtok(NULL, " \b\t\r\n"); @@ -184,6 +191,13 @@ int *out; fprintf(stderr, "bad direction \"%s\"\n", *cpp); return 1; } + +#ifdef USE_INET6 + if (!strcasecmp(*cpp, "out6") || !strcasecmp(*cpp, "in6")) { + return parseipv6(cpp, (ip6_t *)ip, ifn, out); + } +#endif + *out = (TOLOWER(c) == 'o') ? 1 : 0; cpp++; if (!*cpp) @@ -282,24 +296,20 @@ int *out; cpp++; } } else if (*cpp && ip->ip_p == IPPROTO_ICMP) { - extern char *tx_icmptypes[]; - char **s, *t; - int i; + char *t; t = strchr(*cpp, ','); if (t != NULL) *t = '\0'; - for (s = tx_icmptypes, i = 0; !*s || strcmp(*s, "END"); - s++, i++) { - if (*s && !strcasecmp(*cpp, *s)) { - ic->icmp_type = i; - if (t != NULL) - ic->icmp_code = atoi(t + 1); - cpp++; - break; - } - } + ic->icmp_type = geticmptype(AF_INET, *cpp); + if (t != NULL) + ic->icmp_code = atoi(t + 1); + cpp++; + + if (ic->icmp_type == ICMP_ECHO || + ic->icmp_type == ICMP_ECHOREPLY) + ic->icmp_id = htons(getpid()); if (t != NULL) *t = ','; } @@ -312,6 +322,7 @@ int *out; if (olen) { bcopy(ipopts, (char *)(ip + 1), olen); IP_HL_A(ip, IP_HL(ip) + (olen >> 2)); + ip->ip_len += olen; } } if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) @@ -323,3 +334,175 @@ int *out; ip->ip_len = htons(ip->ip_len); return 0; } + + +#ifdef USE_INET6 +int parseipv6(cpp, ip6, ifn, out) + char **cpp; + ip6_t *ip6; + char **ifn; + int *out; +{ + tcphdr_t th, *tcp = &th; + struct icmp6_hdr icmp, *ic6 = &icmp; + + bzero((char *)ip6, MAX(sizeof(*tcp), sizeof(*ic6)) + sizeof(*ip6)); + bzero((char *)tcp, sizeof(*tcp)); + bzero((char *)ic6, sizeof(*ic6)); + ip6->ip6_vfc = 0x60; + + *out = (**cpp == 'o') ? 1 : 0; + cpp++; + if (!*cpp) + return 1; + + if (!strcasecmp(*cpp, "on")) { + cpp++; + if (!*cpp) + return 1; + *ifn = strdup(*cpp++); + if (!*cpp) + return 1; + } + + if (!strcasecmp(*cpp, "tcp")) { + ip6->ip6_nxt = IPPROTO_TCP; + tx_proto = "tcp"; + cpp++; + } else if (!strcasecmp(*cpp, "udp")) { + ip6->ip6_nxt = IPPROTO_UDP; + tx_proto = "udp"; + cpp++; + } else if (!strcasecmp(*cpp, "icmpv6")) { + ip6->ip6_nxt = IPPROTO_ICMPV6; + tx_proto = "icmpv6"; + cpp++; + } else if (ISDIGIT(**cpp) && !index(*cpp, ':')) { + ip6->ip6_nxt = atoi(*cpp); + cpp++; + } else + ip6->ip6_nxt = IPPROTO_IPV6; + + if (!*cpp) + return 1; + + switch (ip6->ip6_nxt) + { + case IPPROTO_TCP : + ip6->ip6_plen = sizeof(struct tcphdr); + break; + case IPPROTO_UDP : + ip6->ip6_plen = sizeof(struct udphdr); + break; + case IPPROTO_ICMPV6 : + ip6->ip6_plen = ICMP6ERR_IPICMPHLEN; + break; + default : + break; + } + + if (ip6->ip6_nxt == IPPROTO_TCP || ip6->ip6_nxt == IPPROTO_UDP) { + char *last; + + last = strchr(*cpp, ','); + if (!last) { + fprintf(stderr, "tcp/udp with no source port\n"); + return 1; + } + *last++ = '\0'; + tcp->th_sport = htons(tx_portnum(last)); + if (ip6->ip6_nxt == IPPROTO_TCP) { + tcp->th_win = htons(4096); + TCP_OFF_A(tcp, sizeof(*tcp) >> 2); + } + } + + if (inet_pton(AF_INET6, *cpp, &ip6->ip6_src) != 1) { + fprintf(stderr, "cannot parse source address '%s'\n", *cpp); + return 1; + } + + cpp++; + if (!*cpp) + return 1; + + if (ip6->ip6_nxt == IPPROTO_TCP || ip6->ip6_nxt == IPPROTO_UDP) { + char *last; + + last = strchr(*cpp, ','); + if (!last) { + fprintf(stderr, "tcp/udp with no destination port\n"); + return 1; + } + *last++ = '\0'; + tcp->th_dport = htons(tx_portnum(last)); + } + + if (inet_pton(AF_INET6, *cpp, &ip6->ip6_dst) != 1) { + fprintf(stderr, "cannot parse destination address '%s'\n", + *cpp); + return 1; + } + + cpp++; + if (ip6->ip6_nxt == IPPROTO_TCP) { + if (*cpp != NULL) { + char *s, *t; + + tcp->th_flags = 0; + for (s = *cpp; *s; s++) + if ((t = strchr(myflagset, *s))) + tcp->th_flags |= myflags[t-myflagset]; + if (tcp->th_flags) + cpp++; + } + + if (tcp->th_flags & TH_URG) + tcp->th_urp = htons(1); + + if (*cpp && !strncasecmp(*cpp, "seq=", 4)) { + tcp->th_seq = htonl(atoi(*cpp + 4)); + cpp++; + } + + if (*cpp && !strncasecmp(*cpp, "ack=", 4)) { + tcp->th_ack = htonl(atoi(*cpp + 4)); + cpp++; + } + } else if (*cpp && ip6->ip6_nxt == IPPROTO_ICMPV6) { + char *t; + + t = strchr(*cpp, ','); + if (t != NULL) + *t = '\0'; + + ic6->icmp6_type = geticmptype(AF_INET6, *cpp); + if (t != NULL) + ic6->icmp6_code = atoi(t + 1); + + if (ic6->icmp6_type == ICMP6_ECHO_REQUEST || + ic6->icmp6_type == ICMP6_ECHO_REPLY) + ic6->icmp6_id = htons(getpid()); + + if (t != NULL) + *t = ','; + } + + if (ip6->ip6_nxt == IPPROTO_TCP || ip6->ip6_nxt == IPPROTO_UDP) { + bcopy((char *)tcp, (char *)ip6 + sizeof(*ip6), + sizeof(*tcp)); + } else if (ip6->ip6_nxt == IPPROTO_ICMPV6) { + bcopy((char *)ic6, (char *)ip6 + sizeof(*ip6), + sizeof(*ic6)); + } + + /* + * Because a length of 0 == jumbo gram... + */ + if (ip6->ip6_plen == 0) { + ip6->ip6_plen++; + } + ip6->ip6_plen = htons(ip6->ip6_plen); + return 0; +} +#endif diff --git a/lib/ipoptsec.c b/lib/ipoptsec.c index a59db23616fdc..96400bffc1a4e 100644 --- a/lib/ipoptsec.c +++ b/lib/ipoptsec.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2001-2002 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ipoptsec.c,v 1.2.4.1 2006/06/16 17:21:04 darrenr Exp $ + * $Id$ */ #include "ipf.h" @@ -23,16 +23,19 @@ struct ipopt_names secclass[] = { u_char seclevel(slevel) -char *slevel; + char *slevel; { struct ipopt_names *so; + if (slevel == NULL || *slevel == '\0') + return 0; + for (so = secclass; so->on_name; so++) if (!strcasecmp(slevel, so->on_name)) break; if (!so->on_name) { - fprintf(stderr, "no such security level: %s\n", slevel); + fprintf(stderr, "no such security level: '%s'\n", slevel); return 0; } return (u_char)so->on_value; @@ -40,7 +43,7 @@ char *slevel; u_char secbit(class) -int class; + int class; { struct ipopt_names *so; @@ -49,7 +52,7 @@ int class; break; if (!so->on_name) { - fprintf(stderr, "no such security class: %d\n", class); + fprintf(stderr, "no such security class: %d.\n", class); return 0; } return (u_char)so->on_bit; diff --git a/lib/kmem.c b/lib/kmem.c index 07830fbe10734..1b5b7ca659aac 100644 --- a/lib/kmem.c +++ b/lib/kmem.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2005 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -42,7 +42,7 @@ #if !defined(lint) static const char sccsid[] = "@(#)kmem.c 1.4 1/12/96 (C) 1992 Darren Reed"; -static const char rcsid[] = "@(#)$Id: kmem.c,v 1.16.2.3 2006/06/16 17:21:04 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif @@ -68,9 +68,9 @@ kvm_t kvm_open __P((char *, char *, char *, int, char *)); int kvm_read __P((kvm_t, u_long, char *, size_t)); kvm_t kvm_open(kernel, core, swap, mode, errstr) -char *kernel, *core, *swap; -int mode; -char *errstr; + char *kernel, *core, *swap; + int mode; + char *errstr; { kvm_t k; int fd; @@ -91,10 +91,10 @@ char *errstr; } int kvm_read(kvm, pos, buffer, size) -kvm_t kvm; -u_long pos; -char *buffer; -size_t size; + kvm_t kvm; + u_long pos; + char *buffer; + size_t size; { int r = 0, left; char *bufp; @@ -125,7 +125,7 @@ size_t size; #endif /* !defined(__sgi) && !defined(__hpux) && !defined(__osf__) */ int openkmem(kern, core) -char *kern, *core; + char *kern, *core; { kvm_f = kvm_open(kern, core, NULL, O_RDONLY, NULL); if (kvm_f == NULL) @@ -137,9 +137,9 @@ char *kern, *core; } int kmemcpy(buf, pos, n) -register char *buf; -long pos; -register int n; + register char *buf; + long pos; + register int n; { register int r; @@ -167,9 +167,9 @@ register int n; } int kstrncpy(buf, pos, n) -register char *buf; -long pos; -register int n; + register char *buf; + long pos; + register int n; { register int r; diff --git a/lib/kmem.h b/lib/kmem.h index 70f0a7a108869..ccd5396ee1675 100644 --- a/lib/kmem.h +++ b/lib/kmem.h @@ -1,8 +1,8 @@ /* - * Copyright (C) 2002 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. - * $Id: kmem.h,v 1.2.4.1 2006/06/16 17:21:04 darrenr Exp $ + * $Id$ */ #ifndef __KMEM_H__ diff --git a/lib/kmemcpywrap.c b/lib/kmemcpywrap.c index 7a4a161f339b2..f8f2812c61a4f 100644 --- a/lib/kmemcpywrap.c +++ b/lib/kmemcpywrap.c @@ -1,17 +1,17 @@ /* - * Copyright (C) 2002 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: kmemcpywrap.c,v 1.1.4.1 2006/06/16 17:21:05 darrenr Exp $ - */ + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ #include "ipf.h" #include "kmem.h" int kmemcpywrap(from, to, size) -void *from, *to; -size_t size; + void *from, *to; + size_t size; { int ret; diff --git a/lib/kvatoname.c b/lib/kvatoname.c index b0fe69dafb3c5..7b5d0c4f1bc82 100644 --- a/lib/kvatoname.c +++ b/lib/kvatoname.c @@ -1,10 +1,10 @@ /* - * Copyright (C) 2002 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: kvatoname.c,v 1.1.4.1 2006/06/16 17:21:05 darrenr Exp $ - */ + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ #include "ipf.h" @@ -12,8 +12,8 @@ #include <sys/ioctl.h> char *kvatoname(func, iocfunc) -ipfunc_t func; -ioctlfunc_t iocfunc; + ipfunc_t func; + ioctlfunc_t iocfunc; { static char funcname[40]; ipfunc_resolve_t res; @@ -23,7 +23,7 @@ ioctlfunc_t iocfunc; res.ipfu_name[0] = '\0'; fd = -1; - if ((opts & OPT_DONOTHING) == 0) { + if ((opts & OPT_DONTOPEN) == 0) { fd = open(IPL_NAME, O_RDONLY); if (fd == -1) return NULL; diff --git a/lib/load_dstlist.c b/lib/load_dstlist.c new file mode 100644 index 0000000000000..760699dafeae3 --- /dev/null +++ b/lib/load_dstlist.c @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: load_dstlist.c,v 1.1.2.5 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include <fcntl.h> +#include <sys/ioctl.h> +#include "ipf.h" +#include "netinet/ip_lookup.h" +#include "netinet/ip_dstlist.h" + + +int +load_dstlist(dst, iocfunc, nodes) + ippool_dst_t *dst; + ioctlfunc_t iocfunc; + ipf_dstnode_t *nodes; +{ + iplookupop_t op; + ipf_dstnode_t *a; + ippool_dst_t dest; + + if (dst->ipld_name[0] == '\0') + return -1; + + if (pool_open() == -1) + return -1; + + op.iplo_unit = dst->ipld_unit; + op.iplo_type = IPLT_DSTLIST; + op.iplo_arg = 0; + strncpy(op.iplo_name, dst->ipld_name, sizeof(op.iplo_name)); + op.iplo_size = sizeof(dest); + op.iplo_struct = &dest; + bzero((char *)&dest, sizeof(dest)); + dest.ipld_unit = dst->ipld_unit; + dest.ipld_policy = dst->ipld_policy; + dest.ipld_flags = dst->ipld_flags; + strncpy(dest.ipld_name, dst->ipld_name, sizeof(dest.ipld_name)); + + if ((opts & OPT_REMOVE) == 0) { + if (pool_ioctl(iocfunc, SIOCLOOKUPADDTABLE, &op)) + if ((opts & OPT_DONOTHING) == 0) { + return ipf_perror_fd(pool_fd(), iocfunc, + "add destination list table"); + } + } + + if ((opts & OPT_VERBOSE) != 0) { + dest.ipld_dests = dst->ipld_dests; + printdstlist(&dest, bcopywrap, dest.ipld_name, opts, nodes, NULL); + dest.ipld_dests = NULL; + } + + for (a = nodes; a != NULL; a = a->ipfd_next) + load_dstlistnode(dst->ipld_unit, dest.ipld_name, a, iocfunc); + + if ((opts & OPT_REMOVE) != 0) { + if (pool_ioctl(iocfunc, SIOCLOOKUPDELTABLE, &op)) + if ((opts & OPT_DONOTHING) == 0) { + return ipf_perror_fd(pool_fd(), iocfunc, + "delete destination list table"); + } + } + return 0; +} diff --git a/lib/load_dstlistnode.c b/lib/load_dstlistnode.c new file mode 100644 index 0000000000000..e1ec0013fae7a --- /dev/null +++ b/lib/load_dstlistnode.c @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: load_dstlistnode.c,v 1.1.2.5 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include <fcntl.h> +#include <sys/ioctl.h> +#include "ipf.h" +#include "netinet/ip_lookup.h" +#include "netinet/ip_pool.h" + + +int +load_dstlistnode(role, name, node, iocfunc) + int role; + char *name; + ipf_dstnode_t *node; + ioctlfunc_t iocfunc; +{ + iplookupop_t op; + frdest_t *dst; + char *what; + int err; + + if (pool_open() == -1) + return -1; + + dst = calloc(1, sizeof(*dst) + node->ipfd_dest.fd_name); + if (dst == NULL) + return -1; + + op.iplo_unit = role; + op.iplo_type = IPLT_DSTLIST; + op.iplo_arg = 0; + op.iplo_struct = dst; + op.iplo_size = sizeof(*dst); + if (node->ipfd_dest.fd_name >= 0) + op.iplo_size += node->ipfd_dest.fd_name; + (void) strncpy(op.iplo_name, name, sizeof(op.iplo_name)); + + dst->fd_addr = node->ipfd_dest.fd_addr; + dst->fd_type = node->ipfd_dest.fd_type; + dst->fd_name = node->ipfd_dest.fd_name; + if (node->ipfd_dest.fd_name >= 0) + bcopy(node->ipfd_names, (char *)dst + sizeof(*dst), + node->ipfd_dest.fd_name); + + if ((opts & OPT_REMOVE) == 0) { + what = "add"; + err = pool_ioctl(iocfunc, SIOCLOOKUPADDNODE, &op); + } else { + what = "delete"; + err = pool_ioctl(iocfunc, SIOCLOOKUPDELNODE, &op); + } + free(dst); + + if (err != 0) { + if ((opts & OPT_DONOTHING) == 0) { + char msg[80]; + + (void) sprintf(msg, "%s lookup node", what); + return ipf_perror_fd(pool_fd(), iocfunc, msg); + } + } + + return 0; +} diff --git a/lib/load_file.c b/lib/load_file.c index 9bb3899aebf5f..a1d1f70b5c330 100644 --- a/lib/load_file.c +++ b/lib/load_file.c @@ -1,12 +1,13 @@ /* - * Copyright (C) 2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: load_file.c,v 1.1.2.1 2006/08/25 21:13:04 darrenr Exp $ + * $Id: load_file.c,v 1.6.2.2 2012/07/22 08:04:24 darren_r Exp $ */ #include "ipf.h" +#include <ctype.h> alist_t * load_file(char *filename) @@ -20,13 +21,13 @@ load_file(char *filename) if (fp == NULL) { fprintf(stderr, "load_file cannot open '%s'\n", filename); return NULL; - } + } a = NULL; rtop = NULL; rbot = NULL; - linenum = 0; - + linenum = 0; + while (fgets(line, sizeof(line) - 1, fp)) { line[sizeof(line) - 1] = '\0'; linenum++; @@ -35,17 +36,23 @@ load_file(char *filename) */ s = strchr(line, '\n'); if (s == NULL) { - fprintf(stderr, "%d:%s: line too long\n", linenum, filename); + fprintf(stderr, "%d:%s: line too long\n", + linenum, filename); fclose(fp); alist_free(rtop); return NULL; } - *s = '\0'; + /* + * Remove trailing spaces + */ + for (; ISSPACE(*s); s--) + *s = '\0'; + s = strchr(line, '\r'); if (s != NULL) *s = '\0'; - for (t = line; isspace(*t); t++) + for (t = line; ISSPACE(*t); t++) ; if (*t == '!') { not = 1; @@ -56,21 +63,22 @@ load_file(char *filename) /* * Remove comment markers */ - for (s = t; *s; s++) { - if (*s == '#') - *s = '\0'; + s = strchr(t, '#'); + if (s != NULL) { + *s = '\0'; + if (s == t) + continue; } - if (!*t) - continue; + /* * Trim off tailing white spaces */ s = strlen(t) + t - 1; - while (isspace(*s)) + while (ISSPACE(*s)) *s-- = '\0'; - if (isdigit(*t)) { - a = alist_new(4, t); + a = alist_new(AF_UNSPEC, t); + if (a != NULL) { a->al_not = not; if (rbot != NULL) rbot->al_next = a; @@ -78,8 +86,8 @@ load_file(char *filename) rtop = a; rbot = a; } else { - fprintf(stderr, "%s: unrecognised content line %d\n", - filename, linenum); + fprintf(stderr, "%s:%d unrecognised content :%s\n", + filename, linenum, t); } } fclose(fp); diff --git a/lib/load_hash.c b/lib/load_hash.c index 84abca03c1662..7a4c232b4605e 100644 --- a/lib/load_hash.c +++ b/lib/load_hash.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2002-2005 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: load_hash.c,v 1.11.2.5 2006/07/14 06:12:25 darrenr Exp $ + * $Id$ */ #include <fcntl.h> @@ -12,13 +12,12 @@ #include "netinet/ip_lookup.h" #include "netinet/ip_htable.h" -static int hashfd = -1; - -int load_hash(iphp, list, iocfunc) -iphtable_t *iphp; -iphtent_t *list; -ioctlfunc_t iocfunc; +int +load_hash(iphp, list, iocfunc) + iphtable_t *iphp; + iphtent_t *list; + ioctlfunc_t iocfunc; { iplookupop_t op; iphtable_t iph; @@ -26,14 +25,13 @@ ioctlfunc_t iocfunc; size_t size; int n; - if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0)) - hashfd = open(IPLOOKUP_NAME, O_RDWR); - if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0)) + if (pool_open() == -1) return -1; for (n = 0, a = list; a != NULL; a = a->ipe_next) n++; + bzero((char *)&iph, sizeof(iph)); op.iplo_arg = 0; op.iplo_type = IPLT_HASH; op.iplo_unit = iphp->iph_unit; @@ -42,10 +40,7 @@ ioctlfunc_t iocfunc; op.iplo_arg = IPHASH_ANON; op.iplo_size = sizeof(iph); op.iplo_struct = &iph; - iph.iph_unit = iphp->iph_unit; - iph.iph_type = iphp->iph_type; - strncpy(iph.iph_name, iphp->iph_name, sizeof(iph.iph_name)); - iph.iph_flags = iphp->iph_flags; + iph = *iphp; if (n <= 0) n = 1; if (iphp->iph_size == 0) @@ -58,16 +53,15 @@ ioctlfunc_t iocfunc; iphp->iph_name, "size to match expected use"); } iph.iph_size = size; - iph.iph_seed = iphp->iph_seed; iph.iph_table = NULL; iph.iph_list = NULL; iph.iph_ref = 0; if ((opts & OPT_REMOVE) == 0) { - if ((*iocfunc)(hashfd, SIOCLOOKUPADDTABLE, &op)) + if (pool_ioctl(iocfunc, SIOCLOOKUPADDTABLE, &op)) if ((opts & OPT_DONOTHING) == 0) { - perror("load_hash:SIOCLOOKUPADDTABLE"); - return -1; + return ipf_perror_fd(pool_fd(), iocfunc, + "add lookup hash table"); } } @@ -75,19 +69,14 @@ ioctlfunc_t iocfunc; strncpy(iphp->iph_name, op.iplo_name, sizeof(op.iplo_name)); if (opts & OPT_VERBOSE) { - for (a = list; a != NULL; a = a->ipe_next) { - a->ipe_addr.in4_addr = ntohl(a->ipe_addr.in4_addr); - a->ipe_mask.in4_addr = ntohl(a->ipe_mask.in4_addr); - } iph.iph_table = calloc(size, sizeof(*iph.iph_table)); if (iph.iph_table == NULL) { perror("calloc(size, sizeof(*iph.iph_table))"); return -1; } iph.iph_list = list; - printhash(&iph, bcopywrap, iph.iph_name, opts); + printhash(&iph, bcopywrap, iph.iph_name, opts, NULL); free(iph.iph_table); - iph.iph_list = NULL; for (a = list; a != NULL; a = a->ipe_next) { a->ipe_addr.in4_addr = htonl(a->ipe_addr.in4_addr); @@ -99,13 +88,13 @@ ioctlfunc_t iocfunc; printf("Hash %s:\n", iph.iph_name); for (a = list; a != NULL; a = a->ipe_next) - load_hashnode(iphp->iph_unit, iph.iph_name, a, iocfunc); + load_hashnode(iphp->iph_unit, iph.iph_name, a, 0, iocfunc); if ((opts & OPT_REMOVE) != 0) { - if ((*iocfunc)(hashfd, SIOCLOOKUPDELTABLE, &op)) + if (pool_ioctl(iocfunc, SIOCLOOKUPDELTABLE, &op)) if ((opts & OPT_DONOTHING) == 0) { - perror("load_hash:SIOCLOOKUPDELTABLE"); - return -1; + return ipf_perror_fd(pool_fd(), iocfunc, + "delete lookup hash table"); } } return 0; diff --git a/lib/load_hashnode.c b/lib/load_hashnode.c index 8ff907abe9bf7..8028333723632 100644 --- a/lib/load_hashnode.c +++ b/lib/load_hashnode.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2003-2005 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: load_hashnode.c,v 1.2.4.2 2006/06/16 17:21:05 darrenr Exp $ + * $Id$ */ #include <fcntl.h> @@ -12,22 +12,21 @@ #include "netinet/ip_lookup.h" #include "netinet/ip_htable.h" -static int hashfd = -1; - -int load_hashnode(unit, name, node, iocfunc) -int unit; -char *name; -iphtent_t *node; -ioctlfunc_t iocfunc; +int +load_hashnode(unit, name, node, ttl, iocfunc) + int unit; + char *name; + iphtent_t *node; + int ttl; + ioctlfunc_t iocfunc; { iplookupop_t op; iphtent_t ipe; + char *what; int err; - if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0)) - hashfd = open(IPLOOKUP_NAME, O_RDWR); - if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0)) + if (pool_open() == -1) return -1; op.iplo_type = IPLT_HASH; @@ -38,6 +37,8 @@ ioctlfunc_t iocfunc; strncpy(op.iplo_name, name, sizeof(op.iplo_name)); bzero((char *)&ipe, sizeof(ipe)); + ipe.ipe_family = node->ipe_family; + ipe.ipe_die = ttl; bcopy((char *)&node->ipe_addr, (char *)&ipe.ipe_addr, sizeof(ipe.ipe_addr)); bcopy((char *)&node->ipe_mask, (char *)&ipe.ipe_mask, @@ -45,15 +46,20 @@ ioctlfunc_t iocfunc; bcopy((char *)&node->ipe_group, (char *)&ipe.ipe_group, sizeof(ipe.ipe_group)); - if ((opts & OPT_REMOVE) == 0) - err = (*iocfunc)(hashfd, SIOCLOOKUPADDNODE, &op); - else - err = (*iocfunc)(hashfd, SIOCLOOKUPDELNODE, &op); + if ((opts & OPT_REMOVE) == 0) { + what = "add"; + err = pool_ioctl(iocfunc, SIOCLOOKUPADDNODE, &op); + } else { + what = "delete"; + err = pool_ioctl(iocfunc, SIOCLOOKUPDELNODE, &op); + } if (err != 0) if (!(opts & OPT_DONOTHING)) { - perror("load_hash:SIOCLOOKUP*NODE"); - return -1; + char msg[80]; + + sprintf(msg, "%s node from lookup hash table", what); + return ipf_perror_fd(pool_fd(), iocfunc, msg); } return 0; } diff --git a/lib/load_http.c b/lib/load_http.c index 164b8b4945f55..db229db19dfc8 100644 --- a/lib/load_http.c +++ b/lib/load_http.c @@ -1,12 +1,26 @@ /* - * Copyright (C) 2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: load_http.c,v 1.1.2.1 2006/08/25 21:13:04 darrenr Exp $ + * $Id: load_http.c,v 1.5.2.5 2012/07/22 08:04:24 darren_r Exp $ */ #include "ipf.h" +#include <ctype.h> + +/* + * Because the URL can be included twice into the buffer, once as the + * full path for the "GET" and once as the "Host:", the buffer it is + * put in needs to be larger than 512*2 to make room for the supporting + * text. Why not just use snprintf and truncate? The warning about the + * URL being too long tells you something is wrong and does not fetch + * any data - just truncating the URL (with snprintf, etc) and sending + * that to the server is allowing an unknown and unintentioned action + * to happen. + */ +#define MAX_URL_LEN 512 +#define LOAD_BUFSIZE (MAX_URL_LEN * 2 + 128) /* * Format expected is one addres per line, at the start of each line. @@ -14,17 +28,16 @@ alist_t * load_http(char *url) { - int fd, len, left, port, endhdr, removed; - char *s, *t, *u, buffer[1024], *myurl; + int fd, len, left, port, endhdr, removed, linenum = 0; + char *s, *t, *u, buffer[LOAD_BUFSIZE], *myurl; alist_t *a, *rtop, *rbot; - struct sockaddr_in sin; - struct hostent *host; /* * More than this would just be absurd. */ - if (strlen(url) > 512) { - fprintf(stderr, "load_http has a URL > 512 bytes?!\n"); + if (strlen(url) > MAX_URL_LEN) { + fprintf(stderr, "load_http has a URL > %d bytes?!\n", + MAX_URL_LEN); return NULL; } @@ -47,6 +60,15 @@ load_http(char *url) } *t++ = '\0'; + /* + * 10 is the length of 'Host: \r\n\r\n' below. + */ + if (strlen(s) + strlen(buffer) + 10 > sizeof(buffer)) { + fprintf(stderr, "load_http has a malformed URL '%s'\n", url); + free(myurl); + return NULL; + } + u = strchr(s, '@'); if (u != NULL) s = u + 1; /* AUTH */ @@ -63,30 +85,11 @@ load_http(char *url) port = 80; } - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_port = htons(port); - if (isdigit(*s)) { - if (inet_aton(s, &sin.sin_addr) == -1) { - goto done; - } - } else { - host = gethostbyname(s); - if (host == NULL) - goto done; - memcpy(&sin.sin_addr, host->h_addr_list[0], - sizeof(sin.sin_addr)); - } - - fd = socket(AF_INET, SOCK_STREAM, 0); + fd = connecttcp(s, port); if (fd == -1) goto done; - if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) { - close(fd); - goto done; - } len = strlen(buffer); if (write(fd, buffer, len) != len) { @@ -141,30 +144,40 @@ load_http(char *url) if (t == NULL) break; - *t++ = '\0'; - for (u = buffer; isdigit(*u) || (*u == '.'); u++) - ; - if (*u == '/') { - char *slash; - - slash = u; - u++; - while (isdigit(*u)) - u++; - if (!isspace(*u) && *u) - u = slash; + linenum++; + *t = '\0'; + + /* + * Remove comment and continue to the next line if + * the comment is at the start of the line. + */ + u = strchr(buffer, '#'); + if (u != NULL) { + *u = '\0'; + if (u == buffer) + continue; } - *u = '\0'; - a = alist_new(4, buffer); + /* + * Trim off tailing white spaces, will include \r + */ + for (u = t - 1; (u >= buffer) && ISSPACE(*u); u--) + *u = '\0'; + + a = alist_new(AF_UNSPEC, buffer); if (a != NULL) { if (rbot != NULL) rbot->al_next = a; else rtop = a; rbot = a; + } else { + fprintf(stderr, + "%s:%d unrecognised content:%s\n", + url, linenum, buffer); } + t++; removed = t - buffer; memmove(buffer, t, sizeof(buffer) - left - removed); s -= removed; diff --git a/lib/load_pool.c b/lib/load_pool.c index f22b06328b6fb..3d5011aec0bf8 100644 --- a/lib/load_pool.c +++ b/lib/load_pool.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2002-2005 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: load_pool.c,v 1.14.2.4 2006/06/16 17:21:06 darrenr Exp $ + * $Id$ */ #include <fcntl.h> @@ -12,20 +12,17 @@ #include "netinet/ip_lookup.h" #include "netinet/ip_pool.h" -static int poolfd = -1; - -int load_pool(plp, iocfunc) -ip_pool_t *plp; -ioctlfunc_t iocfunc; +int +load_pool(plp, iocfunc) + ip_pool_t *plp; + ioctlfunc_t iocfunc; { iplookupop_t op; ip_pool_node_t *a; ip_pool_t pool; - if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0)) - poolfd = open(IPLOOKUP_NAME, O_RDWR); - if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0)) + if (pool_open() == -1) return -1; op.iplo_unit = plp->ipo_unit; @@ -35,16 +32,18 @@ ioctlfunc_t iocfunc; op.iplo_size = sizeof(pool); op.iplo_struct = &pool; bzero((char *)&pool, sizeof(pool)); + pool.ipo_unit = plp->ipo_unit; strncpy(pool.ipo_name, plp->ipo_name, sizeof(pool.ipo_name)); if (plp->ipo_name[0] == '\0') op.iplo_arg |= IPOOL_ANON; if ((opts & OPT_REMOVE) == 0) { - if ((*iocfunc)(poolfd, SIOCLOOKUPADDTABLE, &op)) + if (pool_ioctl(iocfunc, SIOCLOOKUPADDTABLE, &op)) { if ((opts & OPT_DONOTHING) == 0) { - perror("load_pool:SIOCLOOKUPADDTABLE"); - return -1; + return ipf_perror_fd(pool_fd(), iocfunc, + "add lookup table"); } + } } if (op.iplo_arg & IPOOL_ANON) @@ -52,18 +51,19 @@ ioctlfunc_t iocfunc; if ((opts & OPT_VERBOSE) != 0) { pool.ipo_list = plp->ipo_list; - printpool(&pool, bcopywrap, pool.ipo_name, opts); + (void) printpool(&pool, bcopywrap, pool.ipo_name, opts, NULL); pool.ipo_list = NULL; } for (a = plp->ipo_list; a != NULL; a = a->ipn_next) - load_poolnode(plp->ipo_unit, pool.ipo_name, a, iocfunc); + load_poolnode(plp->ipo_unit, pool.ipo_name, + a, 0, iocfunc); if ((opts & OPT_REMOVE) != 0) { - if ((*iocfunc)(poolfd, SIOCLOOKUPDELTABLE, &op)) + if (pool_ioctl(iocfunc, SIOCLOOKUPDELTABLE, &op)) if ((opts & OPT_DONOTHING) == 0) { - perror("load_pool:SIOCLOOKUPDELTABLE"); - return -1; + return ipf_perror_fd(pool_fd(), iocfunc, + "delete lookup table"); } } return 0; diff --git a/lib/load_poolnode.c b/lib/load_poolnode.c index 2afc4d21f3ac1..7ab845f0cb045 100644 --- a/lib/load_poolnode.c +++ b/lib/load_poolnode.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2003-2004 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: load_poolnode.c,v 1.3.2.3 2006/06/16 17:21:06 darrenr Exp $ + * $Id$ */ #include <fcntl.h> @@ -12,22 +12,21 @@ #include "netinet/ip_lookup.h" #include "netinet/ip_pool.h" -static int poolfd = -1; - -int load_poolnode(role, name, node, iocfunc) -int role; -char *name; -ip_pool_node_t *node; -ioctlfunc_t iocfunc; +int +load_poolnode(role, name, node, ttl, iocfunc) + int role; + char *name; + ip_pool_node_t *node; + int ttl; + ioctlfunc_t iocfunc; { ip_pool_node_t pn; iplookupop_t op; + char *what; int err; - if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0)) - poolfd = open(IPLOOKUP_NAME, O_RDWR); - if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0)) + if (pool_open() == -1) return -1; op.iplo_unit = role; @@ -43,17 +42,25 @@ ioctlfunc_t iocfunc; bcopy((char *)&node->ipn_mask, (char *)&pn.ipn_mask, sizeof(pn.ipn_mask)); pn.ipn_info = node->ipn_info; + pn.ipn_die = ttl; strncpy(pn.ipn_name, node->ipn_name, sizeof(pn.ipn_name)); - if ((opts & OPT_REMOVE) == 0) - err = (*iocfunc)(poolfd, SIOCLOOKUPADDNODE, &op); - else - err = (*iocfunc)(poolfd, SIOCLOOKUPDELNODE, &op); + if ((opts & OPT_REMOVE) == 0) { + what = "add"; + err = pool_ioctl(iocfunc, SIOCLOOKUPADDNODE, &op); + } else { + what = "delete"; + err = pool_ioctl(iocfunc, SIOCLOOKUPDELNODE, &op); + } if (err != 0) { if ((opts & OPT_DONOTHING) == 0) { - perror("load_poolnode:SIOCLOOKUP*NODE"); - return -1; + char msg[80]; + + sprintf(msg, "%s pool node(%s/", what, + inet_ntoa(pn.ipn_addr.adf_addr.in4)); + strcat(msg, inet_ntoa(pn.ipn_mask.adf_addr.in4)); + return ipf_perror_fd(pool_fd(), iocfunc, msg); } } diff --git a/lib/load_url.c b/lib/load_url.c index 77091534b0c26..dcda4c07fdf85 100644 --- a/lib/load_url.c +++ b/lib/load_url.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: load_url.c,v 1.1.2.1 2006/08/25 21:13:04 darrenr Exp $ + * $Id: load_url.c,v 1.3.2.2 2012/07/22 08:04:24 darren_r Exp $ */ #include "ipf.h" @@ -13,11 +13,11 @@ load_url(char *url) { alist_t *hosts = NULL; - if (strncmp(url, "file://", 7) == 0) { - /* + if (strncmp(url, "file://", 7) == 0) { + /* * file:///etc/passwd * ^------------s - */ + */ hosts = load_file(url); } else if (*url == '/' || *url == '.') { @@ -27,5 +27,5 @@ load_url(char *url) hosts = load_http(url); } - return hosts; + return hosts; } diff --git a/lib/loglevel.c b/lib/loglevel.c deleted file mode 100644 index 47dd8bac02736..0000000000000 --- a/lib/loglevel.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: loglevel.c,v 1.5 2001/06/09 17:09:24 darrenr Exp $ - */ - -#include "ipf.h" - - -int loglevel(cpp, facpri, linenum) -char **cpp; -u_int *facpri; -int linenum; -{ - int fac, pri; - char *s; - - fac = 0; - pri = 0; - if (!*++cpp) { - fprintf(stderr, "%d: %s\n", linenum, - "missing identifier after level"); - return -1; - } - - s = strchr(*cpp, '.'); - if (s) { - *s++ = '\0'; - fac = fac_findname(*cpp); - if (fac == -1) { - fprintf(stderr, "%d: %s %s\n", linenum, - "Unknown facility", *cpp); - return -1; - } - pri = pri_findname(s); - if (pri == -1) { - fprintf(stderr, "%d: %s %s\n", linenum, - "Unknown priority", s); - return -1; - } - } else { - pri = pri_findname(*cpp); - if (pri == -1) { - fprintf(stderr, "%d: %s %s\n", linenum, - "Unknown priority", *cpp); - return -1; - } - } - *facpri = fac|pri; - return 0; -} diff --git a/lib/make_range.c b/lib/make_range.c deleted file mode 100644 index e4335cddf18bf..0000000000000 --- a/lib/make_range.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2002 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: make_range.c,v 1.2 2002/05/18 07:27:52 darrenr Exp $ - */ -#include "ipf.h" - - -alist_t *make_range(not, a1, a2) -int not; -struct in_addr a1, a2; -{ - alist_t *a; - - a = (alist_t *)calloc(1, sizeof(*a)); - if (a != NULL) { - a->al_1 = a1.s_addr; - a->al_2 = a2.s_addr; - a->al_not = not; - } - return a; -} diff --git a/lib/mb_hexdump.c b/lib/mb_hexdump.c new file mode 100644 index 0000000000000..6da65633191c0 --- /dev/null +++ b/lib/mb_hexdump.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: mb_hexdump.c,v 1.1.2.3 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" + +void +mb_hexdump(m, fp) + mb_t *m; + FILE *fp; +{ + u_char *s; + int len; + int i; + + for (; m != NULL; m = m->mb_next) { + len = m->mb_len; + for (s = (u_char *)m->mb_data, i = 0; i < len; i++) { + fprintf(fp, "%02x", *s++ & 0xff); + if (len - i > 1) { + i++; + fprintf(fp, "%02x", *s++ & 0xff); + } + fputc(' ', fp); + } + } + fputc('\n', fp); +} diff --git a/lib/msgdsize.c b/lib/msgdsize.c new file mode 100644 index 0000000000000..9bdc584bc0084 --- /dev/null +++ b/lib/msgdsize.c @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: msgdsize.c,v 1.2.4.3 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" + +size_t msgdsize(orig) + mb_t *orig; +{ + size_t sz = 0; + mb_t *m; + + for (m = orig; m != NULL; m = m->mb_next) + sz += m->mb_len; + return sz; +} diff --git a/lib/mutex_emul.c b/lib/mutex_emul.c index 1a5815658236f..57ed987388869 100644 --- a/lib/mutex_emul.c +++ b/lib/mutex_emul.c @@ -1,20 +1,28 @@ /* - * Copyright (C) 2003 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: mutex_emul.c,v 1.2.4.1 2006/06/16 17:21:06 darrenr Exp $ - */ + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ #include "ipf.h" #define EMM_MAGIC 0x9d7adba3 -void eMmutex_enter(mtx, file, line) -eMmutex_t *mtx; -char *file; -int line; +static int mutex_debug = 0; +static FILE *mutex_file = NULL; +static int initcount = 0; + +void +eMmutex_enter(mtx, file, line) + eMmutex_t *mtx; + char *file; + int line; { + if (mutex_debug & 2) + fprintf(mutex_file, "%s:%d:eMmutex_enter(%s)\n", file, line, + mtx->eMm_owner); if (mtx->eMm_magic != EMM_MAGIC) { fprintf(stderr, "%s:eMmutex_enter(%p): bad magic: %#x\n", mtx->eMm_owner, mtx, mtx->eMm_magic); @@ -31,9 +39,15 @@ int line; } -void eMmutex_exit(mtx) -eMmutex_t *mtx; +void +eMmutex_exit(mtx, file, line) + eMmutex_t *mtx; + char *file; + int line; { + if (mutex_debug & 2) + fprintf(mutex_file, "%s:%d:eMmutex_exit(%s)\n", file, line, + mtx->eMm_owner); if (mtx->eMm_magic != EMM_MAGIC) { fprintf(stderr, "%s:eMmutex_exit(%p): bad magic: %#x\n", mtx->eMm_owner, mtx, mtx->eMm_magic); @@ -50,10 +64,18 @@ eMmutex_t *mtx; } -void eMmutex_init(mtx, who) -eMmutex_t *mtx; -char *who; +void +eMmutex_init(mtx, who, file, line) + eMmutex_t *mtx; + char *who; + char *file; + int line; { + if (mutex_file == NULL && mutex_debug) + mutex_file = fopen("ipf_mutex_log", "w"); + if (mutex_debug & 1) + fprintf(mutex_file, "%s:%d:eMmutex_init(%p,%s)\n", + file, line, mtx, who); if (mtx->eMm_magic == EMM_MAGIC) { /* safe bet ? */ fprintf(stderr, "%s:eMmutex_init(%p): already initialised?: %#x\n", @@ -66,21 +88,44 @@ char *who; mtx->eMm_owner = strdup(who); else mtx->eMm_owner = NULL; + initcount++; } -void eMmutex_destroy(mtx) -eMmutex_t *mtx; +void +eMmutex_destroy(mtx, file, line) + eMmutex_t *mtx; + char *file; + int line; { + if (mutex_debug & 1) + fprintf(mutex_file, + "%s:%d:eMmutex_destroy(%p,%s)\n", file, line, + mtx, mtx->eMm_owner); if (mtx->eMm_magic != EMM_MAGIC) { fprintf(stderr, "%s:eMmutex_destroy(%p): bad magic: %#x\n", mtx->eMm_owner, mtx, mtx->eMm_magic); abort(); } if (mtx->eMm_held != 0) { - fprintf(stderr, "%s:eMmutex_enter(%p): still locked: %d\n", + fprintf(stderr, + "%s:eMmutex_enter(%p): still locked: %d\n", mtx->eMm_owner, mtx, mtx->eMm_held); abort(); } + if (mtx->eMm_owner != NULL) + free(mtx->eMm_owner); memset(mtx, 0xa5, sizeof(*mtx)); + initcount--; +} + + +void +ipf_mutex_clean() +{ + if (initcount != 0) { + if (mutex_file) + fprintf(mutex_file, "initcount %d\n", initcount); + abort(); + } } diff --git a/lib/nametokva.c b/lib/nametokva.c index 89e347467f425..67539fce4a8e4 100644 --- a/lib/nametokva.c +++ b/lib/nametokva.c @@ -1,10 +1,10 @@ /* - * Copyright (C) 2002 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: nametokva.c,v 1.1.4.1 2006/06/16 17:21:07 darrenr Exp $ - */ + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ #include "ipf.h" @@ -12,8 +12,8 @@ #include <fcntl.h> ipfunc_t nametokva(name, iocfunc) -char *name; -ioctlfunc_t iocfunc; + char *name; + ioctlfunc_t iocfunc; { ipfunc_resolve_t res; int fd; @@ -22,7 +22,7 @@ ioctlfunc_t iocfunc; res.ipfu_addr = NULL; fd = -1; - if ((opts & OPT_DONOTHING) == 0) { + if ((opts & OPT_DONTOPEN) == 0) { fd = open(IPL_NAME, O_RDONLY); if (fd == -1) return NULL; diff --git a/lib/nat_setgroupmap.c b/lib/nat_setgroupmap.c index ccf7864d40cb7..3d73b4e705317 100644 --- a/lib/nat_setgroupmap.c +++ b/lib/nat_setgroupmap.c @@ -1,31 +1,31 @@ /* - * Copyright (C) 2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: nat_setgroupmap.c,v 1.1.4.1 2006/06/16 17:21:07 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #include "ipf.h" void nat_setgroupmap(n) -ipnat_t *n; + ipnat_t *n; { - if (n->in_outmsk == n->in_inmsk) + if (n->in_nsrcmsk == n->in_osrcmsk) n->in_ippip = 1; else if (n->in_flags & IPN_AUTOPORTMAP) { - n->in_ippip = ~ntohl(n->in_inmsk); - if (n->in_outmsk != 0xffffffff) - n->in_ippip /= (~ntohl(n->in_outmsk) + 1); + n->in_ippip = ~ntohl(n->in_osrcmsk); + if (n->in_nsrcmsk != 0xffffffff) + n->in_ippip /= (~ntohl(n->in_nsrcmsk) + 1); n->in_ippip++; if (n->in_ippip == 0) n->in_ippip = 1; n->in_ppip = USABLE_PORTS / n->in_ippip; } else { - n->in_space = USABLE_PORTS * ~ntohl(n->in_outmsk); - n->in_nip = 0; - if (!(n->in_ppip = n->in_pmin)) + n->in_space = USABLE_PORTS * ~ntohl(n->in_nsrcmsk); + n->in_snip = 0; + if (!(n->in_ppip = n->in_spmin)) n->in_ppip = 1; n->in_ippip = USABLE_PORTS / n->in_ppip; } diff --git a/lib/natparse.c b/lib/natparse.c deleted file mode 100644 index 9937380f35a7f..0000000000000 --- a/lib/natparse.c +++ /dev/null @@ -1,728 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - */ -#if !defined(lint) -static const char sccsid[] ="@(#)ipnat.c 1.9 6/5/96 (C) 1993 Darren Reed"; -static const char rcsid[] = "@(#)$Id: natparse.c,v 1.8.2.1 2004/12/09 19:41:21 darrenr Exp $"; -#endif - -#include <sys/ioctl.h> -#include <errno.h> -#include <ctype.h> - -#include "ipf.h" -#include "opts.h" - - -void nat_setgroupmap(n) -ipnat_t *n; -{ - if (n->in_outmsk == n->in_inmsk) - n->in_ippip = 1; - else if (n->in_flags & IPN_AUTOPORTMAP) { - n->in_ippip = ~ntohl(n->in_inmsk); - if (n->in_outmsk != 0xffffffff) - n->in_ippip /= (~ntohl(n->in_outmsk) + 1); - n->in_ippip++; - if (n->in_ippip == 0) - n->in_ippip = 1; - n->in_ppip = USABLE_PORTS / n->in_ippip; - } else { - n->in_space = USABLE_PORTS * ~ntohl(n->in_outmsk); - n->in_nip = 0; - if (!(n->in_ppip = n->in_pmin)) - n->in_ppip = 1; - n->in_ippip = USABLE_PORTS / n->in_ppip; - } -} - - - -ipnat_t *natparse(line, linenum) -char *line; -int linenum; -{ - static ipnat_t ipn; - struct protoent *pr; - char *dnetm = NULL, *dport = NULL, *proto = NULL; - char *s, *t, *cps[31], **cpp; - int i, cnt; - - - if ((s = strchr(line, '\n'))) - *s = '\0'; - if ((s = strchr(line, '#'))) - *s = '\0'; - while (*line && ISSPACE(*line)) - line++; - if (!*line) - return NULL; - - bzero((char *)&ipn, sizeof(ipn)); - cnt = 0; - - for (i = 0, *cps = strtok(line, " \b\t\r\n"); cps[i] && i < 30; cnt++) - cps[++i] = strtok(NULL, " \b\t\r\n"); - - cps[i] = NULL; - - if (cnt < 3) { - fprintf(stderr, "%d: not enough segments in line\n", linenum); - return NULL; - } - - cpp = cps; - - if (!strcasecmp(*cpp, "map")) - ipn.in_redir = NAT_MAP; - else if (!strcasecmp(*cpp, "map-block")) - ipn.in_redir = NAT_MAPBLK; - else if (!strcasecmp(*cpp, "rdr")) - ipn.in_redir = NAT_REDIRECT; - else if (!strcasecmp(*cpp, "bimap")) - ipn.in_redir = NAT_BIMAP; - else { - fprintf(stderr, "%d: unknown mapping: \"%s\"\n", - linenum, *cpp); - return NULL; - } - - cpp++; - - strncpy(ipn.in_ifnames[0], *cpp, sizeof(ipn.in_ifnames[0]) - 1); - ipn.in_ifnames[0][sizeof(ipn.in_ifnames[0]) - 1] = '\0'; - cpp++; - - if (!strcasecmp(*cpp, "from") || (**cpp == '!')) { - if (!strcmp(*cpp, "!")) { - cpp++; - if (strcasecmp(*cpp, "from")) { - fprintf(stderr, "Missing from after !\n"); - return NULL; - } - ipn.in_flags |= IPN_NOTSRC; - } else if (**cpp == '!') { - if (strcasecmp(*cpp + 1, "from")) { - fprintf(stderr, "Missing from after !\n"); - return NULL; - } - ipn.in_flags |= IPN_NOTSRC; - } - if ((ipn.in_flags & IPN_NOTSRC) && - (ipn.in_redir & (NAT_MAP|NAT_MAPBLK))) { - fprintf(stderr, "Cannot use '! from' with map\n"); - return NULL; - } - - ipn.in_flags |= IPN_FILTER; - cpp++; - if (ipn.in_redir == NAT_REDIRECT) { - if (hostmask(&cpp, proto, NULL, - (u_32_t *)&ipn.in_srcip, - (u_32_t *)&ipn.in_srcmsk, linenum) == -1) - return NULL; - - if (ports(&cpp, proto, &ipn.in_sport, - &ipn.in_scmp, &ipn.in_stop, linenum)) - return NULL; - } else { - if (hostmask(&cpp, proto, NULL, - (u_32_t *)&ipn.in_inip, - (u_32_t *)&ipn.in_inmsk, linenum) == -1) - return NULL; - - if (ports(&cpp, proto, &ipn.in_dport, - &ipn.in_dcmp, &ipn.in_dtop, linenum)) - return NULL; - } - - if (!strcmp(*cpp, "!")) { - cpp++; - ipn.in_flags |= IPN_NOTDST; - } else if (**cpp == '!') { - (*cpp)++; - ipn.in_flags |= IPN_NOTDST; - } - - if (strcasecmp(*cpp, "to")) { - fprintf(stderr, "%d: unexpected keyword (%s) - to\n", - linenum, *cpp); - return NULL; - } - if ((ipn.in_flags & IPN_NOTDST) && - (ipn.in_redir & (NAT_REDIRECT))) { - fprintf(stderr, "Cannot use '! to' with rdr\n"); - return NULL; - } - - if (!*++cpp) { - fprintf(stderr, "%d: missing host after to\n", linenum); - return NULL; - } - if (ipn.in_redir == NAT_REDIRECT) { - if (hostmask(&cpp, proto, NULL, - (u_32_t *)&ipn.in_outip, - (u_32_t *)&ipn.in_outmsk, linenum)) - return NULL; - - if (ports(&cpp, proto, &ipn.in_dport, - &ipn.in_dcmp, &ipn.in_dtop, linenum)) - return NULL; - ipn.in_pmin = htons(ipn.in_dport); - } else { - if (hostmask(&cpp, proto, NULL, - (u_32_t *)&ipn.in_srcip, - (u_32_t *)&ipn.in_srcmsk, linenum)) - return NULL; - - if (ports(&cpp, proto, &ipn.in_sport, - &ipn.in_scmp, &ipn.in_stop, linenum)) - return NULL; - } - } else { - s = *cpp; - if (!s) - return NULL; - t = strchr(s, '/'); - if (!t) - return NULL; - *t++ = '\0'; - if (ipn.in_redir == NAT_REDIRECT) { - if (hostnum((u_32_t *)&ipn.in_outip, s, linenum, NULL)) - return NULL; - if (genmask(t, (u_32_t *)&ipn.in_outmsk) == -1) { - return NULL; - } - } else { - if (hostnum((u_32_t *)&ipn.in_inip, s, linenum, NULL)) - return NULL; - if (genmask(t, (u_32_t *)&ipn.in_inmsk) == -1) { - return NULL; - } - } - cpp++; - if (!*cpp) - return NULL; - } - - if ((ipn.in_redir == NAT_REDIRECT) && !(ipn.in_flags & IPN_FILTER)) { - if (strcasecmp(*cpp, "port")) { - fprintf(stderr, "%d: missing fields - 1st port\n", - linenum); - return NULL; - } - - cpp++; - - if (!*cpp) { - fprintf(stderr, - "%d: missing fields (destination port)\n", - linenum); - return NULL; - } - - if (ISDIGIT(**cpp) && (s = strchr(*cpp, '-'))) - *s++ = '\0'; - else - s = NULL; - - if (!portnum(*cpp, proto, &ipn.in_pmin, linenum)) - return NULL; - ipn.in_pmin = htons(ipn.in_pmin); - cpp++; - - if (!strcmp(*cpp, "-")) { - cpp++; - s = *cpp++; - } - - if (s) { - if (!portnum(s, proto, &ipn.in_pmax, linenum)) - return NULL; - ipn.in_pmax = htons(ipn.in_pmax); - } else - ipn.in_pmax = ipn.in_pmin; - } - - if (!*cpp) { - fprintf(stderr, "%d: missing fields (->)\n", linenum); - return NULL; - } - if (strcmp(*cpp, "->")) { - fprintf(stderr, "%d: missing ->\n", linenum); - return NULL; - } - cpp++; - - if (!*cpp) { - fprintf(stderr, "%d: missing fields (%s)\n", - linenum, ipn.in_redir ? "destination" : "target"); - return NULL; - } - - if (ipn.in_redir == NAT_MAP) { - if (!strcasecmp(*cpp, "range")) { - cpp++; - ipn.in_flags |= IPN_IPRANGE; - if (!*cpp) { - fprintf(stderr, "%d: missing fields (%s)\n", - linenum, - ipn.in_redir ? "destination":"target"); - return NULL; - } - } - } - - if (ipn.in_flags & IPN_IPRANGE) { - dnetm = strrchr(*cpp, '-'); - if (dnetm == NULL) { - cpp++; - if (*cpp && !strcmp(*cpp, "-") && *(cpp + 1)) - dnetm = *(cpp + 1); - } else - *dnetm++ = '\0'; - if (dnetm == NULL || *dnetm == '\0') { - fprintf(stderr, - "%d: desination range not specified\n", - linenum); - return NULL; - } - } else if (ipn.in_redir != NAT_REDIRECT) { - dnetm = strrchr(*cpp, '/'); - if (dnetm == NULL) { - cpp++; - if (*cpp && !strcasecmp(*cpp, "netmask")) - dnetm = *++cpp; - } - if (dnetm == NULL) { - fprintf(stderr, - "%d: missing fields (dest netmask)\n", - linenum); - return NULL; - } - if (*dnetm == '/') - *dnetm++ = '\0'; - } - - if (ipn.in_redir == NAT_REDIRECT) { - dnetm = strchr(*cpp, ','); - if (dnetm != NULL) { - ipn.in_flags |= IPN_SPLIT; - *dnetm++ = '\0'; - } - if (hostnum((u_32_t *)&ipn.in_inip, *cpp, linenum, NULL)) - return NULL; - } else { - if (hostnum((u_32_t *)&ipn.in_outip, *cpp, linenum, NULL)) - return NULL; - } - cpp++; - - if (ipn.in_redir & NAT_MAPBLK) { - if (*cpp && strcasecmp(*cpp, "ports")) { - fprintf(stderr, - "%d: expected \"ports\" - got \"%s\"\n", - linenum, *cpp); - return NULL; - } - cpp++; - if (*cpp) { - ipn.in_pmin = atoi(*cpp); - cpp++; - } else - ipn.in_pmin = 0; - } else if ((ipn.in_redir & NAT_BIMAP) == NAT_REDIRECT) { - if (*cpp && strrchr(*cpp, '/') != NULL) { - fprintf(stderr, "%d: No netmask supported in %s\n", - linenum, "destination host for redirect"); - return NULL; - } - /* If it's a in_redir, expect target port */ - - if (!*cpp || strcasecmp(*cpp, "port")) { - fprintf(stderr, "%d: missing fields - 2nd port (%s)\n", - linenum, *cpp); - return NULL; - } - cpp++; - if (!*cpp) { - fprintf(stderr, - "%d: missing fields (destination port)\n", - linenum); - return NULL; - } - if (!portnum(*cpp, proto, &ipn.in_pnext, linenum)) - return NULL; - ipn.in_pnext = htons(ipn.in_pnext); - cpp++; - } - if (dnetm && *dnetm == '/') - *dnetm++ = '\0'; - - if (ipn.in_redir & (NAT_MAP|NAT_MAPBLK)) { - if (ipn.in_flags & IPN_IPRANGE) { - if (hostnum((u_32_t *)&ipn.in_outmsk, dnetm, - linenum, NULL) == -1) - return NULL; - } else if (genmask(dnetm, (u_32_t *)&ipn.in_outmsk)) - return NULL; - } else { - if (ipn.in_flags & IPN_SPLIT) { - if (hostnum((u_32_t *)&ipn.in_inmsk, dnetm, - linenum, NULL) == -1) - return NULL; - } else if (genmask("255.255.255.255", (u_32_t *)&ipn.in_inmsk)) - return NULL; - if (!*cpp) { - ipn.in_flags |= IPN_TCP; /* XXX- TCP only by default */ - proto = "tcp"; - } else { - if (!strcasecmp(*cpp, "tcp")) - ipn.in_flags |= IPN_TCP; - else if (!strcasecmp(*cpp, "udp")) - ipn.in_flags |= IPN_UDP; - else if (!strcasecmp(*cpp, "tcp/udp")) - ipn.in_flags |= IPN_TCPUDP; - else if (!strcasecmp(*cpp, "tcpudp")) - ipn.in_flags |= IPN_TCPUDP; - else if (!strcasecmp(*cpp, "ip")) - ipn.in_flags |= IPN_ANY; - else { - ipn.in_flags |= IPN_ANY; - ipn.in_p = getproto(*cpp); - } - proto = *cpp; - cpp++; - - if (*cpp && !strcasecmp(*cpp, "round-robin")) { - cpp++; - ipn.in_flags |= IPN_ROUNDR; - } - - if (*cpp && !strcasecmp(*cpp, "frag")) { - cpp++; - ipn.in_flags |= IPN_FRAG; - } - - if (*cpp && !strcasecmp(*cpp, "age")) { - cpp++; - if (!*cpp) { - fprintf(stderr, - "%d: age with no parameters\n", - linenum); - return NULL; - } - - ipn.in_age[0] = atoi(*cpp); - s = strchr(*cpp, '/'); - if (s != NULL) - ipn.in_age[1] = atoi(s + 1); - else - ipn.in_age[1] = ipn.in_age[0]; - cpp++; - } - - if (*cpp && !strcasecmp(*cpp, "mssclamp")) { - cpp++; - if (*cpp) { - ipn.in_mssclamp = atoi(*cpp); - cpp++; - } else { - fprintf(stderr, - "%d: mssclamp with no parameters\n", - linenum); - return NULL; - } - } - - if (*cpp) { - fprintf(stderr, - "%d: extra junk at the end of rdr: %s\n", - linenum, *cpp); - return NULL; - } - } - } - - if (!(ipn.in_flags & IPN_SPLIT)) - ipn.in_inip &= ipn.in_inmsk; - if ((ipn.in_flags & IPN_IPRANGE) == 0) - ipn.in_outip &= ipn.in_outmsk; - ipn.in_srcip &= ipn.in_srcmsk; - - if ((ipn.in_redir & NAT_MAPBLK) != 0) - nat_setgroupmap(&ipn); - - if (*cpp && !strcasecmp(*cpp, "frag")) { - cpp++; - ipn.in_flags |= IPN_ROUNDR; - } - - if (!*cpp) - return &ipn; - - if (ipn.in_redir != NAT_BIMAP && !strcasecmp(*cpp, "proxy")) { - if (ipn.in_redir == NAT_BIMAP) { - fprintf(stderr, "%d: cannot use proxy with bimap\n", - linenum); - return NULL; - } - - cpp++; - if (!*cpp) { - fprintf(stderr, - "%d: missing parameter for \"proxy\"\n", - linenum); - return NULL; - } - dport = NULL; - - if (!strcasecmp(*cpp, "port")) { - cpp++; - if (!*cpp) { - fprintf(stderr, - "%d: missing parameter for \"port\"\n", - linenum); - return NULL; - } - - dport = *cpp; - cpp++; - - if (!*cpp) { - fprintf(stderr, - "%d: missing parameter for \"proxy\"\n", - linenum); - return NULL; - } - } else { - fprintf(stderr, - "%d: missing keyword \"port\"\n", linenum); - return NULL; - } - - if ((proto = strchr(*cpp, '/'))) { - *proto++ = '\0'; - ipn.in_p = getproto(proto); - } else - ipn.in_p = 0; - - if (dport && !portnum(dport, proto, &ipn.in_dport, linenum)) - return NULL; - ipn.in_dport = htons(ipn.in_dport); - - (void) strncpy(ipn.in_plabel, *cpp, sizeof(ipn.in_plabel)); - cpp++; - - if (*cpp) { - fprintf(stderr, - "%d: too many parameters for \"proxy\"\n", - linenum); - return NULL; - } - return &ipn; - } - - - if (!strcasecmp(*cpp, "icmpidmap")) { - - cpp++; - if (!*cpp) { - fprintf(stderr, - "%d: icmpidmap misses protocol and range\n", - linenum); - return NULL; - }; - - if (!strcasecmp(*cpp, "icmp")) - ipn.in_flags = IPN_ICMPQUERY; - else { - fprintf(stderr, "%d: icmpidmap only valid for icmp\n", - linenum); - return NULL; - } - cpp++; - - if (!*cpp) { - fprintf(stderr, "%d: no icmp id argument found\n", - linenum); - return NULL; - } - - if (!(t = strchr(*cpp, ':'))) { - fprintf(stderr, - "%d: no icmp id range detected in \"%s\"\n", - linenum, *cpp); - return NULL; - } - *t++ = '\0'; - - if (!icmpidnum(*cpp, &ipn.in_pmin, linenum) || - !icmpidnum(t, &ipn.in_pmax, linenum)) - return NULL; - } else if (!strcasecmp(*cpp, "portmap")) { - if (ipn.in_redir == NAT_BIMAP) { - fprintf(stderr, "%d: cannot use proxy with bimap\n", - linenum); - return NULL; - } - cpp++; - if (!*cpp) { - fprintf(stderr, - "%d: missing expression following portmap\n", - linenum); - return NULL; - } - - if (!strcasecmp(*cpp, "tcp")) - ipn.in_flags |= IPN_TCP; - else if (!strcasecmp(*cpp, "udp")) - ipn.in_flags |= IPN_UDP; - else if (!strcasecmp(*cpp, "tcpudp")) - ipn.in_flags |= IPN_TCPUDP; - else if (!strcasecmp(*cpp, "tcp/udp")) - ipn.in_flags |= IPN_TCPUDP; - else { - fprintf(stderr, - "%d: expected protocol name - got \"%s\"\n", - linenum, *cpp); - return NULL; - } - proto = *cpp; - cpp++; - - if (!*cpp) { - fprintf(stderr, "%d: no port range found\n", linenum); - return NULL; - } - - if (!strcasecmp(*cpp, "auto")) { - ipn.in_flags |= IPN_AUTOPORTMAP; - ipn.in_pmin = htons(1024); - ipn.in_pmax = htons(65535); - nat_setgroupmap(&ipn); - } else { - if (!(t = strchr(*cpp, ':'))) { - fprintf(stderr, - "%d: no port range in \"%s\"\n", - linenum, *cpp); - return NULL; - } - *t++ = '\0'; - if (!portnum(*cpp, proto, &ipn.in_pmin, linenum) || - !portnum(t, proto, &ipn.in_pmax, linenum)) - return NULL; - } - cpp++; - } - - if (*cpp && !strcasecmp(*cpp, "round-robin")) { - cpp++; - ipn.in_flags |= IPN_ROUNDR; - } - - if (*cpp && !strcasecmp(*cpp, "age")) { - cpp++; - if (!*cpp) { - fprintf(stderr, "%d: age with no parameters\n", - linenum); - return NULL; - } - s = strchr(*cpp, '/'); - if (s != NULL) - ipn.in_age[1] = atoi(s + 1); - else - ipn.in_age[1] = ipn.in_age[0]; - cpp++; - } - - if (*cpp && !strcasecmp(*cpp, "mssclamp")) { - cpp++; - if (*cpp) { - ipn.in_mssclamp = atoi(*cpp); - cpp++; - } else { - fprintf(stderr, "%d: mssclamp with no parameters\n", - linenum); - return NULL; - } - } - - if (*cpp) { - fprintf(stderr, "%d: extra junk at the end of the line: %s\n", - linenum, *cpp); - return NULL; - } - - ipn.in_pmin = htons(ipn.in_pmin); - ipn.in_pmax = htons(ipn.in_pmax); - return &ipn; -} - - -void natparsefile(fd, file, opts) -int fd; -char *file; -int opts; -{ - char line[512], *s; - ipnat_t *np; - FILE *fp; - int linenum = 0; - - if (strcmp(file, "-")) { - if (!(fp = fopen(file, "r"))) { - fprintf(stderr, "%s: open: %s\n", file, - STRERROR(errno)); - exit(1); - } - } else - fp = stdin; - - while (getline(line, sizeof(line) - 1, fp, &linenum)) { - line[sizeof(line) - 1] = '\0'; - if ((s = strchr(line, '\n'))) - *s = '\0'; - - if (!(np = natparse(line, linenum))) { - if (*line) - fprintf(stderr, "%d: syntax error in \"%s\"\n", - linenum, line); - } else { - if ((opts & OPT_VERBOSE) && np) - printnat(np, opts); - if (!(opts & OPT_DONOTHING)) { - if (!(opts & OPT_REMOVE)) { - if (ioctl(fd, SIOCADNAT, &np) == -1) - perror("ioctl(SIOCADNAT)"); - } else if (ioctl(fd, SIOCRMNAT, &np) == -1) - perror("ioctl(SIOCRMNAT)"); - } - } - } - if (fp != stdin) - fclose(fp); -} - - -int icmpidnum(str, id, linenum) -char *str; -u_short *id; -int linenum; -{ - int i; - - - i = atoi(str); - - if ((i<0) || (i>65535)) { - fprintf(stderr, "%d: invalid icmp id\"%s\".\n", linenum, str); - return 0; - } - - *id = (u_short)i; - - return 1; -} diff --git a/lib/ntomask.c b/lib/ntomask.c index 4a50ef8045786..1caa57dca1487 100644 --- a/lib/ntomask.c +++ b/lib/ntomask.c @@ -1,26 +1,26 @@ /* - * Copyright (C) 2002-2005 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: ntomask.c,v 1.6.2.1 2006/06/16 17:21:07 darrenr Exp $ - */ + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ #include "ipf.h" -int ntomask(v, nbits, ap) -int v, nbits; -u_32_t *ap; +int ntomask(family, nbits, ap) + int family, nbits; + u_32_t *ap; { u_32_t mask; if (nbits < 0) return -1; - switch (v) + switch (family) { - case 4 : - if (nbits > 32 || use_inet6 != 0) + case AF_INET : + if (nbits > 32 || use_inet6 == 1) return -1; if (nbits == 0) { mask = 0; @@ -31,8 +31,9 @@ u_32_t *ap; *ap = htonl(mask); break; - case 6 : - if ((nbits > 128) || (use_inet6 == 0)) + case 0 : + case AF_INET6 : + if ((nbits > 128) || (use_inet6 == -1)) return -1; fill6bits(nbits, ap); break; diff --git a/lib/optname.c b/lib/optname.c index 33e5f17be3485..1144458480d35 100644 --- a/lib/optname.c +++ b/lib/optname.c @@ -1,18 +1,18 @@ /* - * Copyright (C) 2000-2001 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: optname.c,v 1.3.4.1 2006/06/16 17:21:07 darrenr Exp $ + * $Id$ */ #include "ipf.h" u_32_t optname(cp, sp, linenum) -char ***cp; -u_short *sp; -int linenum; + char ***cp; + u_short *sp; + int linenum; { struct ipopt_names *io, *so; u_long msk = 0; diff --git a/lib/optprint.c b/lib/optprint.c index 8c14fe47e6b6f..32438021f12b8 100644 --- a/lib/optprint.c +++ b/lib/optprint.c @@ -1,16 +1,16 @@ /* - * Copyright (C) 2000-2005 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: optprint.c,v 1.6.4.2 2006/06/16 17:21:08 darrenr Exp $ + * $Id$ */ #include "ipf.h" void optprint(sec, optmsk, optbits) -u_short *sec; -u_long optmsk, optbits; + u_short *sec; + u_long optmsk, optbits; { u_short secmsk = sec[0], secbits = sec[1]; struct ipopt_names *io, *so; diff --git a/lib/optprintv6.c b/lib/optprintv6.c index 5172b5c1a6b48..18ac5afeb69ba 100644 --- a/lib/optprintv6.c +++ b/lib/optprintv6.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: optprintv6.c,v 1.2.4.1 2006/06/16 17:21:08 darrenr Exp $ + * $Id$ */ #include "ipf.h" @@ -11,14 +11,14 @@ #ifdef USE_INET6 void optprintv6(sec, optmsk, optbits) -u_short *sec; -u_long optmsk, optbits; + u_short *sec; + u_long optmsk, optbits; { u_short secmsk = sec[0], secbits = sec[1]; struct ipopt_names *io; char *s; - s = " v6hdrs "; + s = " v6hdr "; for (io = v6ionames; io->on_name; io++) if ((io->on_bit & optmsk) && ((io->on_bit & optmsk) == (io->on_bit & optbits))) { diff --git a/lib/optvalue.c b/lib/optvalue.c index 37bfcf9031f4a..47f619f3d9e65 100644 --- a/lib/optvalue.c +++ b/lib/optvalue.c @@ -1,15 +1,15 @@ /* - * Copyright (C) 2001-2002 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: optvalue.c,v 1.2.4.1 2006/06/16 17:21:08 darrenr Exp $ + * $Id$ */ #include "ipf.h" u_32_t getoptbyname(optname) -char *optname; + char *optname; { struct ipopt_names *io; @@ -21,7 +21,7 @@ char *optname; u_32_t getoptbyvalue(optval) -int optval; + int optval; { struct ipopt_names *io; diff --git a/lib/parse.c b/lib/parse.c deleted file mode 100644 index 1a49d16bbd7e0..0000000000000 --- a/lib/parse.c +++ /dev/null @@ -1,752 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: parse.c,v 1.34.2.1 2004/12/09 19:41:21 darrenr Exp $ - */ -#include <ctype.h> -#include "ipf.h" -#include "opts.h" - -static frentry_t *fp = NULL; - -/* parse() - * - * parse a line read from the input filter rule file - */ -struct frentry *parse(line, linenum) -char *line; -int linenum; -{ - static fripf_t fip; - char *cps[31], **cpp, *endptr, *proto = NULL, *s; - struct protoent *p = NULL; - int i, cnt = 1, j; - u_int k; - - if (fp == NULL) { - fp = malloc(sizeof(*fp)); - if (fp == NULL) - return NULL; - } - - while (*line && ISSPACE(*line)) - line++; - if (!*line) - return NULL; - - bzero((char *)fp, sizeof(*fp)); - bzero((char *)&fip, sizeof(fip)); - fp->fr_v = use_inet6 ? 6 : 4; - fp->fr_ipf = &fip; - fp->fr_dsize = sizeof(fip); - fp->fr_ip.fi_v = fp->fr_v; - fp->fr_mip.fi_v = 0xf; - fp->fr_type = FR_T_NONE; - fp->fr_loglevel = 0xffff; - fp->fr_isc = (void *)-1; - fp->fr_tag = FR_NOTAG; - - /* - * break line up into max of 20 segments - */ - if (opts & OPT_DEBUG) - fprintf(stderr, "parse [%s]\n", line); - for (i = 0, *cps = strtok(line, " \b\t\r\n"); cps[i] && i < 30; cnt++) - cps[++i] = strtok(NULL, " \b\t\r\n"); - cps[i] = NULL; - - if (cnt < 3) { - fprintf(stderr, "%d: not enough segments in line\n", linenum); - return NULL; - } - - cpp = cps; - /* - * The presence of an '@' followed by a number gives the position in - * the current rule list to insert this one. - */ - if (**cpp == '@') - fp->fr_hits = (U_QUAD_T)atoi(*cpp++ + 1) + 1; - - /* - * Check the first keyword in the rule and any options that are - * expected to follow it. - */ - if (!strcasecmp("block", *cpp)) { - fp->fr_flags |= FR_BLOCK; - if (!strncasecmp(*(cpp+1), "return-icmp-as-dest", 19) && - (i = 19)) - fp->fr_flags |= FR_FAKEICMP; - else if (!strncasecmp(*(cpp+1), "return-icmp", 11) && (i = 11)) - fp->fr_flags |= FR_RETICMP; - if (fp->fr_flags & FR_RETICMP) { - cpp++; - if (strlen(*cpp) == i) { - if (*(cpp + 1) && **(cpp +1) == '(') { - cpp++; - i = 0; - } else - i = -1; - } - - /* - * The ICMP code is not required to follow in ()'s - */ - if ((i >= 0) && (*(*cpp + i) == '(')) { - i++; - j = icmpcode(*cpp + i); - if (j == -1) { - fprintf(stderr, - "%d: unrecognised icmp code %s\n", - linenum, *cpp + 20); - return NULL; - } - fp->fr_icode = j; - } - } else if (!strncasecmp(*(cpp+1), "return-rst", 10)) { - fp->fr_flags |= FR_RETRST; - cpp++; - } - } else if (!strcasecmp("count", *cpp)) { - fp->fr_flags |= FR_ACCOUNT; - } else if (!strcasecmp("pass", *cpp)) { - fp->fr_flags |= FR_PASS; - } else if (!strcasecmp("auth", *cpp)) { - fp->fr_flags |= FR_AUTH; - } else if (fp->fr_arg != 0) { - printf("skip %u", fp->fr_arg); - } else if (!strcasecmp("preauth", *cpp)) { - fp->fr_flags |= FR_PREAUTH; - } else if (!strcasecmp("nomatch", *cpp)) { - fp->fr_flags |= FR_NOMATCH; - } else if (!strcasecmp("skip", *cpp)) { - cpp++; - if (ratoui(*cpp, &k, 0, UINT_MAX)) - fp->fr_arg = k; - else { - fprintf(stderr, "%d: integer must follow skip\n", - linenum); - return NULL; - } - } else if (!strcasecmp("log", *cpp)) { - fp->fr_flags |= FR_LOG; - if (!strcasecmp(*(cpp+1), "body")) { - fp->fr_flags |= FR_LOGBODY; - cpp++; - } - if (!strcasecmp(*(cpp+1), "first")) { - fp->fr_flags |= FR_LOGFIRST; - cpp++; - } - if (*cpp && !strcasecmp(*(cpp+1), "or-block")) { - fp->fr_flags |= FR_LOGORBLOCK; - cpp++; - } - if (!strcasecmp(*(cpp+1), "level")) { - cpp++; - if (loglevel(cpp, &fp->fr_loglevel, linenum) == -1) - return NULL; - cpp++; - } - } else { - /* - * Doesn't start with one of the action words - */ - fprintf(stderr, "%d: unknown keyword (%s)\n", linenum, *cpp); - return NULL; - } - if (!*++cpp) { - fprintf(stderr, "%d: missing 'in'/'out' keyword\n", linenum); - return NULL; - } - - /* - * Get the direction for filtering. Impose restrictions on direction - * if blocking with returning ICMP or an RST has been requested. - */ - if (!strcasecmp("in", *cpp)) - fp->fr_flags |= FR_INQUE; - else if (!strcasecmp("out", *cpp)) { - fp->fr_flags |= FR_OUTQUE; - if (fp->fr_flags & FR_RETICMP) { - fprintf(stderr, - "%d: Can only use return-icmp with 'in'\n", - linenum); - return NULL; - } else if (fp->fr_flags & FR_RETRST) { - fprintf(stderr, - "%d: Can only use return-rst with 'in'\n", - linenum); - return NULL; - } - } - if (!*++cpp) { - fprintf(stderr, "%d: missing source specification\n", linenum); - return NULL; - } - - if (!strcasecmp("log", *cpp)) { - if (!*++cpp) { - fprintf(stderr, "%d: missing source specification\n", - linenum); - return NULL; - } - if (FR_ISPASS(fp->fr_flags)) - fp->fr_flags |= FR_LOGP; - else if (FR_ISBLOCK(fp->fr_flags)) - fp->fr_flags |= FR_LOGB; - if (*cpp && !strcasecmp(*cpp, "body")) { - fp->fr_flags |= FR_LOGBODY; - cpp++; - } - if (*cpp && !strcasecmp(*cpp, "first")) { - fp->fr_flags |= FR_LOGFIRST; - cpp++; - } - if (*cpp && !strcasecmp(*cpp, "or-block")) { - if (!FR_ISPASS(fp->fr_flags)) { - fprintf(stderr, - "%d: or-block must be used with pass\n", - linenum); - return NULL; - } - fp->fr_flags |= FR_LOGORBLOCK; - cpp++; - } - if (*cpp && !strcasecmp(*cpp, "level")) { - if (loglevel(cpp, &fp->fr_loglevel, linenum) == -1) - return NULL; - cpp++; - cpp++; - } - } - - if (*cpp && !strcasecmp("quick", *cpp)) { - if (fp->fr_arg != 0) { - fprintf(stderr, "%d: cannot use skip with quick\n", - linenum); - return NULL; - } - cpp++; - fp->fr_flags |= FR_QUICK; - } - - /* - * Parse rule options that are available if a rule is tied to an - * interface. - */ - *fp->fr_ifname = '\0'; - *fp->fr_oifname = '\0'; - if (*cpp && !strcasecmp(*cpp, "on")) { - if (!*++cpp) { - fprintf(stderr, "%d: interface name missing\n", - linenum); - return NULL; - } - (void)strncpy(fp->fr_ifname, *cpp, IFNAMSIZ-1); - fp->fr_ifname[IFNAMSIZ-1] = '\0'; - cpp++; - if (!*cpp) { - if ((fp->fr_flags & FR_RETMASK) == FR_RETRST) { - fprintf(stderr, - "%d: %s can only be used with TCP\n", - linenum, "return-rst"); - return NULL; - } - return fp; - } - - if (!strcasecmp(*cpp, "out-via")) { - if (fp->fr_flags & FR_OUTQUE) { - fprintf(stderr, - "out-via must be used with in\n"); - return NULL; - } - cpp++; - (void)strncpy(fp->fr_oifname, *cpp, IFNAMSIZ-1); - fp->fr_oifname[IFNAMSIZ-1] = '\0'; - cpp++; - } else if (!strcasecmp(*cpp, "in-via")) { - if (fp->fr_flags & FR_INQUE) { - fprintf(stderr, - "in-via must be used with out\n"); - return NULL; - } - cpp++; - (void)strncpy(fp->fr_oifname, *cpp, IFNAMSIZ-1); - fp->fr_oifname[IFNAMSIZ-1] = '\0'; - cpp++; - } - - if (!strcasecmp(*cpp, "dup-to") && *(cpp + 1)) { - cpp++; - if (to_interface(&fp->fr_dif, *cpp, linenum)) - return NULL; - cpp++; - } - if (*cpp && !strcasecmp(*cpp, "to") && *(cpp + 1)) { - cpp++; - if (to_interface(&fp->fr_tif, *cpp, linenum)) - return NULL; - cpp++; - } else if (*cpp && !strcasecmp(*cpp, "fastroute")) { - if (!(fp->fr_flags & FR_INQUE)) { - fprintf(stderr, - "can only use %s with 'in'\n", - "fastroute"); - return NULL; - } - fp->fr_flags |= FR_FASTROUTE; - cpp++; - } - - /* - * Set the "other" interface name. Lets you specify both - * inbound and outbound interfaces for state rules. Do not - * prevent both interfaces from being the same. - */ - strcpy(fp->fr_ifnames[3], "*"); - if ((*cpp != NULL) && (*(cpp + 1) != NULL) && - ((((fp->fr_flags & FR_INQUE) != 0) && - (strcasecmp(*cpp, "out-via") == 0)) || - (((fp->fr_flags & FR_OUTQUE) != 0) && - (strcasecmp(*cpp, "in-via") == 0)))) { - cpp++; - - s = strchr(*cpp, ','); - if (s != NULL) { - *s++ = '\0'; - (void)strncpy(fp->fr_ifnames[3], s, - IFNAMSIZ - 1); - fp->fr_ifnames[3][IFNAMSIZ - 1] = '\0'; - } - - (void)strncpy(fp->fr_ifnames[2], *cpp, IFNAMSIZ - 1); - fp->fr_ifnames[2][IFNAMSIZ - 1] = '\0'; - cpp++; - } else - strcpy(fp->fr_ifnames[2], "*"); - - } - - if (*cpp && !strcasecmp(*cpp, "tos")) { - if (!*++cpp) { - fprintf(stderr, "%d: tos missing value\n", linenum); - return NULL; - } - fp->fr_tos = strtol(*cpp, NULL, 0); - fp->fr_mip.fi_tos = 0xff; - cpp++; - } - - if (*cpp && !strcasecmp(*cpp, "ttl")) { - if (!*++cpp) { - fprintf(stderr, "%d: ttl missing hopcount value\n", - linenum); - return NULL; - } - if (ratoi(*cpp, &i, 0, 255)) - fp->fr_ttl = i; - else { - fprintf(stderr, "%d: invalid ttl (%s)\n", - linenum, *cpp); - return NULL; - } - fp->fr_mip.fi_ttl = 0xff; - cpp++; - } - - /* - * check for "proto <protoname>" only decode udp/tcp/icmp as protoname - */ - if (*cpp && !strcasecmp(*cpp, "proto")) { - if (!*++cpp) { - fprintf(stderr, "%d: protocol name missing\n", linenum); - return NULL; - } - fp->fr_type = FR_T_IPF; - proto = *cpp++; - if (!strcasecmp(proto, "tcp/udp")) { - fp->fr_flx |= FI_TCPUDP; - fp->fr_mflx |= FI_TCPUDP; - } else if (use_inet6 && !strcasecmp(proto, "icmp")) { - fprintf(stderr, -"%d: use proto ipv6-icmp with IPv6 (or use proto 1 if you really mean icmp)\n", - linenum); - return NULL; - } else { - fp->fr_proto = getproto(proto); - fp->fr_mip.fi_p = 0xff; - } - } - if ((fp->fr_proto != IPPROTO_TCP) && - ((fp->fr_flags & FR_RETMASK) == FR_RETRST)) { - fprintf(stderr, "%d: %s can only be used with TCP\n", - linenum, "return-rst"); - return NULL; - } - - /* - * get the from host and bit mask to use against packets - */ - - if (!*cpp) { - fprintf(stderr, "%d: missing source specification\n", linenum); - return NULL; - } - if (!strcasecmp(*cpp, "all")) { - cpp++; - if (!*cpp) { - if (fp->fr_type == FR_T_NONE) { - fp->fr_dsize = 0; - fp->fr_data = NULL; - } - return fp; - } - fp->fr_type = FR_T_IPF; -#ifdef IPFILTER_BPF - } else if (!strcmp(*cpp, "{")) { - struct bpf_program bpf; - struct pcap *p; - char **cp; - u_32_t l; - - if (fp->fr_type != FR_T_NONE) { - fprintf(stderr, - "%d: cannot mix BPF/ipf matching\n", linenum); - return NULL; - } - fp->fr_type = FR_T_BPFOPC; - cpp++; - if (!strncmp(*cpp, "0x", 2)) { - fp->fr_data = malloc(4); - for (cp = cpp, i = 0; *cp; cp++, i++) { - if (!strcmp(*cp, "}")) - break; - fp->fr_data = realloc(fp->fr_data, - (i + 1) * 4); - l = strtoul(*cp, NULL, 0); - ((u_32_t *)fp->fr_data)[i] = l; - } - if (!*cp) { - fprintf(stderr, "Missing closing '}'\n"); - return NULL; - } - fp->fr_dsize = i * sizeof(l); - bpf.bf_insns = fp->fr_data; - bpf.bf_len = fp->fr_dsize / sizeof(struct bpf_insn); - } else { - for (cp = cpp; *cp; cp++) { - if (!strcmp(*cp, "}")) - break; - (*cp)[-1] = ' '; - } - if (!*cp) { - fprintf(stderr, "Missing closing '}'\n"); - return NULL; - } - - bzero((char *)&bpf, sizeof(bpf)); - p = pcap_open_dead(DLT_RAW, 1); - if (!p) { - fprintf(stderr, "pcap_open_dead failed\n"); - return NULL; - } - - if (pcap_compile(p, &bpf, *cpp, 1, 0xffffffff)) { - pcap_perror(p, "ipf"); - pcap_close(p); - fprintf(stderr, "pcap parsing failed\n"); - return NULL; - } - pcap_close(p); - fp->fr_dsize = bpf.bf_len * sizeof(struct bpf_insn); - fp->fr_data = bpf.bf_insns; - if (!bpf_validate(fp->fr_data, bpf.bf_len)) { - fprintf(stderr, "BPF validation failed\n"); - return NULL; - } - if (opts & OPT_DEBUG) - bpf_dump(&bpf, 0); - } - cpp = cp; - (*cpp)++; -#endif - } else { - fp->fr_type = FR_T_IPF; - - if (strcasecmp(*cpp, "from")) { - fprintf(stderr, "%d: unexpected keyword (%s) - from\n", - linenum, *cpp); - return NULL; - } - if (!*++cpp) { - fprintf(stderr, "%d: missing host after from\n", - linenum); - return NULL; - } - if (**cpp == '!') { - fp->fr_flags |= FR_NOTSRCIP; - (*cpp)++; - } else if (!strcmp(*cpp, "!")) { - fp->fr_flags |= FR_NOTSRCIP; - cpp++; - } - - s = *cpp; - i = hostmask(&cpp, proto, fp->fr_ifname, (u_32_t *)&fp->fr_src, - (u_32_t *)&fp->fr_smsk, linenum); - if (i == -1) - return NULL; - if (*fp->fr_ifname && !strcasecmp(s, fp->fr_ifname)) - fp->fr_satype = FRI_DYNAMIC; - if (i == 1) { - if (fp->fr_v == 6) { - fprintf(stderr, - "can only use pools with ipv4\n"); - return NULL; - } - fp->fr_satype = FRI_LOOKUP; - } - - if (ports(&cpp, proto, &fp->fr_sport, &fp->fr_scmp, - &fp->fr_stop, linenum)) - return NULL; - - if (!*cpp) { - fprintf(stderr, "%d: missing to fields\n", linenum); - return NULL; - } - - /* - * do the same for the to field (destination host) - */ - if (strcasecmp(*cpp, "to")) { - fprintf(stderr, "%d: unexpected keyword (%s) - to\n", - linenum, *cpp); - return NULL; - } - if (!*++cpp) { - fprintf(stderr, "%d: missing host after to\n", linenum); - return NULL; - } - - if (**cpp == '!') { - fp->fr_flags |= FR_NOTDSTIP; - (*cpp)++; - } else if (!strcmp(*cpp, "!")) { - fp->fr_flags |= FR_NOTDSTIP; - cpp++; - } - - s = *cpp; - i = hostmask(&cpp, proto, fp->fr_ifname, (u_32_t *)&fp->fr_dst, - (u_32_t *)&fp->fr_dmsk, linenum); - if (i == -1) - return NULL; - if (*fp->fr_ifname && !strcasecmp(s, fp->fr_ifname)) - fp->fr_datype = FRI_DYNAMIC; - if (i == 1) { - if (fp->fr_v == 6) { - fprintf(stderr, - "can only use pools with ipv4\n"); - return NULL; - } - fp->fr_datype = FRI_LOOKUP; - } - - if (ports(&cpp, proto, &fp->fr_dport, &fp->fr_dcmp, - &fp->fr_dtop, linenum)) - return NULL; - } - - if (fp->fr_type == FR_T_IPF) { - /* - * check some sanity, make sure we don't have icmp checks - * with tcp or udp or visa versa. - */ - if (fp->fr_proto && (fp->fr_dcmp || fp->fr_scmp) && - fp->fr_proto != IPPROTO_TCP && - fp->fr_proto != IPPROTO_UDP) { - fprintf(stderr, - "%d: port operation on non tcp/udp\n",linenum); - return NULL; - } - if (fp->fr_icmp && fp->fr_proto != IPPROTO_ICMP) { - fprintf(stderr, - "%d: icmp comparisons on wrong protocol\n", - linenum); - return NULL; - } - - if (!*cpp) - return fp; - - if (*cpp && (fp->fr_type == FR_T_IPF) && - !strcasecmp(*cpp, "flags")) { - if (!*++cpp) { - fprintf(stderr, "%d: no flags present\n", - linenum); - return NULL; - } - fp->fr_tcpf = tcp_flags(*cpp, &fp->fr_tcpfm, linenum); - cpp++; - } - - /* - * extras... - */ - if ((fp->fr_v == 4) && *cpp && (!strcasecmp(*cpp, "with") || - !strcasecmp(*cpp, "and"))) - if (extras(&cpp, fp, linenum)) - return NULL; - - /* - * icmp types for use with the icmp protocol - */ - if (*cpp && !strcasecmp(*cpp, "icmp-type")) { - if (fp->fr_proto != IPPROTO_ICMP && - fp->fr_proto != IPPROTO_ICMPV6) { - fprintf(stderr, - "%d: icmp with wrong protocol (%d)\n", - linenum, fp->fr_proto); - return NULL; - } - if (addicmp(&cpp, fp, linenum)) - return NULL; - fp->fr_icmp = htons(fp->fr_icmp); - fp->fr_icmpm = htons(fp->fr_icmpm); - } - } - - /* - * Keep something... - */ - while (*cpp && !strcasecmp(*cpp, "keep")) - if (addkeep(&cpp, fp, linenum)) - return NULL; - - /* - * This is here to enforce the old interface binding behaviour. - * That is, "on X" is equivalent to "<dir> on X <!dir>-via -,X" - */ - if (fp->fr_flags & FR_KEEPSTATE) { - if (*fp->fr_ifnames[0] && !*fp->fr_ifnames[3]) { - bcopy(fp->fr_ifnames[0], fp->fr_ifnames[3], - sizeof(fp->fr_ifnames[3])); - strncpy(fp->fr_ifnames[2], "*", - sizeof(fp->fr_ifnames[3])); - } - } - - /* - * head of a new group ? - */ - if (*cpp && !strcasecmp(*cpp, "head")) { - if (fp->fr_arg != 0) { - fprintf(stderr, "%d: cannot use skip with head\n", - linenum); - return NULL; - } - if (!*++cpp) { - fprintf(stderr, "%d: head without group #\n", linenum); - return NULL; - } - if (strlen(*cpp) > FR_GROUPLEN) { - fprintf(stderr, "%d: head name too long #\n", linenum); - return NULL; - } - strncpy(fp->fr_grhead, *cpp, FR_GROUPLEN); - cpp++; - } - - /* - * reference to an already existing group ? - */ - if (*cpp && !strcasecmp(*cpp, "group")) { - if (!*++cpp) { - fprintf(stderr, "%d: group without group #\n", - linenum); - return NULL; - } - if (strlen(*cpp) > FR_GROUPLEN) { - fprintf(stderr, "%d: group name too long #\n", linenum); - return NULL; - } - strncpy(fp->fr_group, *cpp, FR_GROUPLEN); - cpp++; - } - - if (*cpp && !strcasecmp(*cpp, "tag")) { - if (!*++cpp) { - fprintf(stderr, "%d: tag id missing value\n", linenum); - return NULL; - } - fp->fr_tag = strtol(*cpp, NULL, 0); - cpp++; - } - - /* - * pps counter - */ - if (*cpp && !strcasecmp(*cpp, "pps")) { - if (!*++cpp) { - fprintf(stderr, "%d: pps without rate\n", linenum); - return NULL; - } - if (ratoui(*cpp, &k, 0, INT_MAX)) - fp->fr_pps = k; - else { - fprintf(stderr, "%d: invalid pps rate (%s)\n", - linenum, *cpp); - return NULL; - } - cpp++; - } - - /* - * leftovers...yuck - */ - if (*cpp && **cpp) { - fprintf(stderr, "%d: unknown words at end: [", linenum); - for (; *cpp; cpp++) - fprintf(stderr, "%s ", *cpp); - fprintf(stderr, "]\n"); - return NULL; - } - - /* - * lazy users... - */ - if (fp->fr_type == FR_T_IPF) { - if ((fp->fr_tcpf || fp->fr_tcpfm) && - (fp->fr_proto != IPPROTO_TCP)) { - fprintf(stderr, - "%d: TCP protocol not specified\n", linenum); - return NULL; - } - if (!(fp->fr_flx & FI_TCPUDP) && - (fp->fr_proto != IPPROTO_TCP) && - (fp->fr_proto != IPPROTO_UDP) && - (fp->fr_dcmp || fp->fr_scmp)) { - if (!fp->fr_proto) { - fp->fr_flx |= FI_TCPUDP; - fp->fr_mflx |= FI_TCPUDP; - } else { - fprintf(stderr, - "%d: port check for non-TCP/UDP\n", - linenum); - return NULL; - } - } - } - if (*fp->fr_oifname && strcmp(fp->fr_oifname, "*") && - !(fp->fr_flags & FR_KEEPSTATE)) { - fprintf(stderr, "%d: *-via <if> must be used %s\n", - linenum, "with keep-state"); - return NULL; - } - return fp; -} diff --git a/lib/parsefields.c b/lib/parsefields.c new file mode 100644 index 0000000000000..241496c96da9a --- /dev/null +++ b/lib/parsefields.c @@ -0,0 +1,48 @@ +#include "ipf.h" + +extern int nohdrfields; + +wordtab_t *parsefields(table, arg) + wordtab_t *table; + char *arg; +{ + wordtab_t *f, *fields; + char *s, *t; + int num; + + fields = NULL; + num = 0; + + for (s = strtok(arg, ","); s != NULL; s = strtok(NULL, ",")) { + t = strchr(s, '='); + if (t != NULL) { + *t++ = '\0'; + if (*t == '\0') + nohdrfields = 1; + } + + f = findword(table, s); + if (f == NULL) { + fprintf(stderr, "Unknown field '%s'\n", s); + exit(1); + } + + num++; + if (fields == NULL) { + fields = malloc(2 * sizeof(*fields)); + } else { + fields = realloc(fields, (num + 1) * sizeof(*fields)); + } + + if (t == NULL) { + fields[num - 1].w_word = f->w_word; + } else { + fields[num - 1].w_word = t; + } + fields[num - 1].w_value = f->w_value; + fields[num].w_word = NULL; + fields[num].w_value = 0; + } + + return fields; +} diff --git a/lib/parseipfexpr.c b/lib/parseipfexpr.c new file mode 100644 index 0000000000000..9a2a2071e9dbc --- /dev/null +++ b/lib/parseipfexpr.c @@ -0,0 +1,283 @@ +#include "ipf.h" +#include <ctype.h> + + +typedef struct ipfopentry { + int ipoe_cmd; + int ipoe_nbasearg; + int ipoe_maxarg; + int ipoe_argsize; + char *ipoe_word; +} ipfopentry_t; + +static ipfopentry_t opwords[17] = { + { IPF_EXP_IP_ADDR, 2, 0, 1, "ip.addr" }, + { IPF_EXP_IP6_ADDR, 2, 0, 4, "ip6.addr" }, + { IPF_EXP_IP_PR, 1, 0, 1, "ip.p" }, + { IPF_EXP_IP_SRCADDR, 2, 0, 1, "ip.src" }, + { IPF_EXP_IP_DSTADDR, 2, 0, 1, "ip.dst" }, + { IPF_EXP_IP6_SRCADDR, 2, 0, 4, "ip6.src" }, + { IPF_EXP_IP6_DSTADDR, 2, 0, 4, "ip6.dst" }, + { IPF_EXP_TCP_PORT, 1, 0, 1, "tcp.port" }, + { IPF_EXP_TCP_DPORT, 1, 0, 1, "tcp.dport" }, + { IPF_EXP_TCP_SPORT, 1, 0, 1, "tcp.sport" }, + { IPF_EXP_TCP_FLAGS, 2, 0, 1, "tcp.flags" }, + { IPF_EXP_UDP_PORT, 1, 0, 1, "udp.port" }, + { IPF_EXP_UDP_DPORT, 1, 0, 1, "udp.dport" }, + { IPF_EXP_UDP_SPORT, 1, 0, 1, "udp.sport" }, + { IPF_EXP_TCP_STATE, 1, 0, 1, "tcp.state" }, + { IPF_EXP_IDLE_GT, 1, 1, 1, "idle-gt" }, + { -1, 0, 0, 0, NULL } +}; + + +int * +parseipfexpr(line, errorptr) + char *line; + char **errorptr; +{ + int not, items, asize, *oplist, osize, i; + char *temp, *arg, *s, *t, *ops, *error; + ipfopentry_t *e; + ipfexp_t *ipfe; + + asize = 0; + error = NULL; + oplist = NULL; + + temp = strdup(line); + if (temp == NULL) { + error = "strdup failed"; + goto parseerror; + } + + /* + * Eliminate any white spaces to make parsing easier. + */ + for (s = temp; *s != '\0'; ) { + if (ISSPACE(*s)) + strcpy(s, s + 1); + else + s++; + } + + /* + * Parse the string. + * It should be sets of "ip.dst=1.2.3.4/32;" things. + * There must be a "=" or "!=" and it must end in ";". + */ + if (temp[strlen(temp) - 1] != ';') { + error = "last character not ';'"; + goto parseerror; + } + + /* + * Work through the list of complete operands present. + */ + for (ops = strtok(temp, ";"); ops != NULL; ops = strtok(NULL, ";")) { + arg = strchr(ops, '='); + if ((arg < ops + 2) || (arg == NULL)) { + error = "bad 'arg' vlaue"; + goto parseerror; + } + + if (*(arg - 1) == '!') { + *(arg - 1) = '\0'; + not = 1; + } else { + not = 0; + } + *arg++ = '\0'; + + + for (e = opwords; e->ipoe_word; e++) { + if (strcmp(ops, e->ipoe_word) == 0) + break; + } + if (e->ipoe_word == NULL) { + error = malloc(32); + if (error != NULL) { + sprintf(error, "keyword (%.10s) not found", + ops); + } + goto parseerror; + } + + /* + * Count the number of commas so we know how big to + * build the array + */ + for (s = arg, items = 1; *s != '\0'; s++) + if (*s == ',') + items++; + + if ((e->ipoe_maxarg != 0) && (items > e->ipoe_maxarg)) { + error = "too many items"; + goto parseerror; + } + + /* + * osize will mark the end of where we have filled up to + * and is thus where we start putting new data. + */ + osize = asize; + asize += 4 + (items * e->ipoe_nbasearg * e->ipoe_argsize); + if (oplist == NULL) + oplist = calloc(1, sizeof(int) * (asize + 2)); + else + oplist = realloc(oplist, sizeof(int) * (asize + 2)); + if (oplist == NULL) { + error = "oplist alloc failed"; + goto parseerror; + } + ipfe = (ipfexp_t *)(oplist + osize); + osize += 4; + ipfe->ipfe_cmd = e->ipoe_cmd; + ipfe->ipfe_not = not; + ipfe->ipfe_narg = items * e->ipoe_nbasearg; + ipfe->ipfe_size = items * e->ipoe_nbasearg * e->ipoe_argsize; + ipfe->ipfe_size += 4; + + for (s = arg; (*s != '\0') && (osize < asize); s = t) { + /* + * Look for the end of this arg or the ',' to say + * there is another following. + */ + for (t = s; (*t != '\0') && (*t != ','); t++) + ; + if (*t == ',') + *t++ = '\0'; + + if (!strcasecmp(ops, "ip.addr") || + !strcasecmp(ops, "ip.src") || + !strcasecmp(ops, "ip.dst")) { + i6addr_t mask, addr; + char *delim; + + delim = strchr(s, '/'); + if (delim != NULL) { + *delim++ = '\0'; + if (genmask(AF_INET, delim, + &mask) == -1) { + error = "genmask failed"; + goto parseerror; + } + } else { + mask.in4.s_addr = 0xffffffff; + } + if (gethost(AF_INET, s, &addr) == -1) { + error = "gethost failed"; + goto parseerror; + } + + oplist[osize++] = addr.in4.s_addr; + oplist[osize++] = mask.in4.s_addr; + +#ifdef USE_INET6 + } else if (!strcasecmp(ops, "ip6.addr") || + !strcasecmp(ops, "ip6.src") || + !strcasecmp(ops, "ip6.dst")) { + i6addr_t mask, addr; + char *delim; + + delim = strchr(s, '/'); + if (delim != NULL) { + *delim++ = '\0'; + if (genmask(AF_INET6, delim, + &mask) == -1) { + error = "genmask failed"; + goto parseerror; + } + } else { + mask.i6[0] = 0xffffffff; + mask.i6[1] = 0xffffffff; + mask.i6[2] = 0xffffffff; + mask.i6[3] = 0xffffffff; + } + if (gethost(AF_INET6, s, &addr) == -1) { + error = "gethost failed"; + goto parseerror; + } + + oplist[osize++] = addr.i6[0]; + oplist[osize++] = addr.i6[1]; + oplist[osize++] = addr.i6[2]; + oplist[osize++] = addr.i6[3]; + oplist[osize++] = mask.i6[0]; + oplist[osize++] = mask.i6[1]; + oplist[osize++] = mask.i6[2]; + oplist[osize++] = mask.i6[3]; +#endif + + } else if (!strcasecmp(ops, "ip.p")) { + int p; + + p = getproto(s); + if (p == -1) + goto parseerror; + oplist[osize++] = p; + + } else if (!strcasecmp(ops, "tcp.flags")) { + u_32_t mask, flags; + char *delim; + + delim = strchr(s, '/'); + if (delim != NULL) { + *delim++ = '\0'; + mask = tcpflags(delim); + } else { + mask = 0xff; + } + flags = tcpflags(s); + + oplist[osize++] = flags; + oplist[osize++] = mask; + + + } else if (!strcasecmp(ops, "tcp.port") || + !strcasecmp(ops, "tcp.sport") || + !strcasecmp(ops, "tcp.dport") || + !strcasecmp(ops, "udp.port") || + !strcasecmp(ops, "udp.sport") || + !strcasecmp(ops, "udp.dport")) { + char proto[4]; + u_short port; + + strncpy(proto, ops, 3); + proto[3] = '\0'; + if (getport(NULL, s, &port, proto) == -1) + goto parseerror; + oplist[osize++] = port; + + } else if (!strcasecmp(ops, "tcp.state")) { + oplist[osize++] = atoi(s); + + } else { + error = "unknown word"; + goto parseerror; + } + } + } + + free(temp); + + if (errorptr != NULL) + *errorptr = NULL; + + for (i = asize; i > 0; i--) + oplist[i] = oplist[i - 1]; + + oplist[0] = asize + 2; + oplist[asize + 1] = IPF_EXP_END; + + return oplist; + +parseerror: + if (errorptr != NULL) + *errorptr = error; + if (oplist != NULL) + free(oplist); + if (temp != NULL) + free(temp); + return NULL; +} diff --git a/lib/parsewhoisline.c b/lib/parsewhoisline.c new file mode 100644 index 0000000000000..526935ca23a50 --- /dev/null +++ b/lib/parsewhoisline.c @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: parsewhoisline.c,v 1.2.2.5 2012/07/22 08:04:24 darren_r Exp $ + */ +#include "ipf.h" + +/* +Microsoft Corp MICROSOFT19 (NET-198-136-97-0-1) 198.137.97.0 - 198.137.97.255 +Microsoft Corp SAVV-S233053-6 (NET-206-79-74-32-1) 206.79.74.32 - 206.79.74.47 + */ +int +parsewhoisline(line, addrp, maskp) + char *line; + addrfamily_t *addrp; + addrfamily_t *maskp; +{ + struct in_addr a1, a2; + char *src = line; + char *s = NULL; + + if (line == NULL) + return -1; + + while (*src != '\0') { + s = strchr(src, '('); + if (s == NULL) + break; + + if (strncmp(s, "(NET", 4)) { + src = s + 1; + } + break; + } + + if (s == NULL) + return -1; + + memset(addrp, 0x00, sizeof(*maskp)); + memset(maskp, 0x00, sizeof(*maskp)); + + if (*(s + 4) == '6') { +#ifdef USE_INET6 + i6addr_t a61, a62; + + s = strchr(s, ')'); + if (s == NULL || *++s != ' ') + return -1; + /* + * Parse the IPv6 + */ + if (inet_pton(AF_INET6, s, &a61.in6) != 1) + return -1; + + s = strchr(s, ' '); + if (s == NULL || strncmp(s, " - ", 3)) + return -1; + + s += 3; + if (inet_pton(AF_INET6, s, &a62) != 1) + return -1; + + addrp->adf_addr = a61; + addrp->adf_family = AF_INET6; + addrp->adf_len = offsetof(addrfamily_t, adf_addr) + + sizeof(struct in6_addr); + + maskp->adf_addr.i6[0] = ~(a62.i6[0] ^ a61.i6[0]); + maskp->adf_addr.i6[1] = ~(a62.i6[1] ^ a61.i6[1]); + maskp->adf_addr.i6[2] = ~(a62.i6[2] ^ a61.i6[2]); + maskp->adf_addr.i6[3] = ~(a62.i6[3] ^ a61.i6[3]); + + /* + * If the mask that's been generated isn't a consecutive mask + * then we can't add it into a pool. + */ + if (count6bits(maskp->adf_addr.i6) == -1) + return -1; + + maskp->adf_family = AF_INET6; + maskp->adf_len = addrp->adf_len; + + if (IP6_MASKNEQ(&addrp->adf_addr.in6, &maskp->adf_addr.in6, + &addrp->adf_addr.in6)) { + return -1; + } + return 0; +#else + return -1; +#endif + } + + s = strchr(s, ')'); + if (s == NULL || *++s != ' ') + return -1; + + s++; + + if (inet_aton(s, &a1) != 1) + return -1; + + s = strchr(s, ' '); + if (s == NULL || strncmp(s, " - ", 3)) + return -1; + + s += 3; + if (inet_aton(s, &a2) != 1) + return -1; + + addrp->adf_addr.in4 = a1; + addrp->adf_family = AF_INET; + addrp->adf_len = offsetof(addrfamily_t, adf_addr) + + sizeof(struct in_addr); + maskp->adf_addr.in4.s_addr = ~(a2.s_addr ^ a1.s_addr); + + /* + * If the mask that's been generated isn't a consecutive mask then + * we can't add it into a pool. + */ + if (count4bits(maskp->adf_addr.in4.s_addr) == -1) + return -1; + + maskp->adf_family = AF_INET; + maskp->adf_len = addrp->adf_len; + bzero((char *)maskp + maskp->adf_len, sizeof(*maskp) - maskp->adf_len); + if ((addrp->adf_addr.in4.s_addr & maskp->adf_addr.in4.s_addr) != + addrp->adf_addr.in4.s_addr) + return -1; + return 0; +} diff --git a/lib/poolio.c b/lib/poolio.c new file mode 100644 index 0000000000000..18cf698222a8b --- /dev/null +++ b/lib/poolio.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: poolio.c,v 1.1.2.3 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include <fcntl.h> +#include <sys/ioctl.h> +#include "ipf.h" +#include "netinet/ip_lookup.h" +#include "netinet/ip_pool.h" + +static int poolfd = -1; + + +int +pool_open() +{ + + if ((opts & OPT_DONTOPEN) != 0) + return 0; + + if (poolfd == -1) + poolfd = open(IPLOOKUP_NAME, O_RDWR); + return poolfd; +} + +int +pool_ioctl(iocfunc, cmd, ptr) + ioctlfunc_t iocfunc; + ioctlcmd_t cmd; + void *ptr; +{ + return (*iocfunc)(poolfd, cmd, ptr); +} + + +void +pool_close() +{ + if (poolfd != -1) { + close(poolfd); + poolfd = -1; + } +} + +int +pool_fd() +{ + return poolfd; +} diff --git a/lib/portname.c b/lib/portname.c index d8bf1d91cc5bc..a9c60711dff66 100644 --- a/lib/portname.c +++ b/lib/portname.c @@ -1,19 +1,20 @@ /* - * Copyright (C) 2000-2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: portname.c,v 1.7.2.1 2006/06/16 17:21:09 darrenr Exp $ + * $Id$ */ #include "ipf.h" -char *portname(pr, port) -int pr, port; +char *portname(pr, port) + int pr, port; { - static char buf[32]; - struct protoent *p = NULL; - struct servent *sv = NULL, *sv1 = NULL; + static char buf[32]; + struct protoent *p = NULL; + struct servent *sv = NULL; + struct servent *sv1 = NULL; if ((opts & OPT_NORESOLVE) == 0) { if (pr == -1) { diff --git a/lib/portnum.c b/lib/portnum.c deleted file mode 100644 index 4079f464c21f6..0000000000000 --- a/lib/portnum.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * - * $Id: portnum.c,v 1.6.4.1 2004/12/09 19:41:22 darrenr Exp $ - */ - -#include <ctype.h> - -#include "ipf.h" - - -/* - * find the port number given by the name, either from getservbyname() or - * straight atoi(). Return 1 on success, 0 on failure - */ -int portnum(name, proto, port, linenum) -char *name, *proto; -u_short *port; -int linenum; -{ - struct servent *sp, *sp2; - u_short p1 = 0; - int i; - - if (ISDIGIT(*name)) { - if (ratoi(name, &i, 0, USHRT_MAX)) { - *port = (u_short)i; - return 1; - } - fprintf(stderr, "%d: unknown port \"%s\"\n", linenum, name); - return 0; - } - if (proto != NULL && strcasecmp(proto, "tcp/udp") != 0) { - sp = getservbyname(name, proto); - if (sp) { - *port = ntohs(sp->s_port); - return 1; - } - fprintf(stderr, "%d: unknown service \"%s\".\n", linenum, name); - return 0; - } - sp = getservbyname(name, "tcp"); - if (sp) - p1 = sp->s_port; - sp2 = getservbyname(name, "udp"); - if (!sp || !sp2) { - fprintf(stderr, "%d: unknown tcp/udp service \"%s\".\n", - linenum, name); - return 0; - } - if (p1 != sp2->s_port) { - fprintf(stderr, "%d: %s %d/tcp is a different port to ", - linenum, name, p1); - fprintf(stderr, "%d: %s %d/udp\n", linenum, name, sp->s_port); - return 0; - } - *port = ntohs(p1); - return 1; -} diff --git a/lib/ports.c b/lib/ports.c deleted file mode 100644 index 9a44e2c06a2d5..0000000000000 --- a/lib/ports.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: ports.c,v 1.9.4.1 2004/12/09 19:41:22 darrenr Exp $ - */ - -#include <ctype.h> - -#include "ipf.h" - - -/* - * check for possible presence of the port fields in the line - */ -int ports(seg, proto, pp, cp, tp, linenum) -char ***seg; -char *proto; -u_short *pp; -int *cp; -u_short *tp; -int linenum; -{ - int comp = -1; - - if (!*seg || !**seg || !***seg) - return 0; - if (!strcasecmp(**seg, "port") && *(*seg + 1) && *(*seg + 2)) { - (*seg)++; - if (ISALNUM(***seg) && *(*seg + 2)) { - if (portnum(**seg, proto, pp, linenum) == 0) - return -1; - (*seg)++; - if (!strcmp(**seg, "<>")) - comp = FR_OUTRANGE; - else if (!strcmp(**seg, "><")) - comp = FR_INRANGE; - else { - fprintf(stderr, - "%d: unknown range operator (%s)\n", - linenum, **seg); - return -1; - } - (*seg)++; - if (**seg == NULL) { - fprintf(stderr, "%d: missing 2nd port value\n", - linenum); - return -1; - } - if (portnum(**seg, proto, tp, linenum) == 0) - return -1; - } else if (!strcmp(**seg, "=") || !strcasecmp(**seg, "eq")) - comp = FR_EQUAL; - else if (!strcmp(**seg, "!=") || !strcasecmp(**seg, "ne")) - comp = FR_NEQUAL; - else if (!strcmp(**seg, "<") || !strcasecmp(**seg, "lt")) - comp = FR_LESST; - else if (!strcmp(**seg, ">") || !strcasecmp(**seg, "gt")) - comp = FR_GREATERT; - else if (!strcmp(**seg, "<=") || !strcasecmp(**seg, "le")) - comp = FR_LESSTE; - else if (!strcmp(**seg, ">=") || !strcasecmp(**seg, "ge")) - comp = FR_GREATERTE; - else { - fprintf(stderr, "%d: unknown comparator (%s)\n", - linenum, **seg); - return -1; - } - if (comp != FR_OUTRANGE && comp != FR_INRANGE) { - (*seg)++; - if (portnum(**seg, proto, pp, linenum) == 0) - return -1; - } - *cp = comp; - (*seg)++; - } - return 0; -} diff --git a/lib/prependmbt.c b/lib/prependmbt.c new file mode 100644 index 0000000000000..4f7220ba236af --- /dev/null +++ b/lib/prependmbt.c @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: prependmbt.c,v 1.3.2.3 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" + +int prependmbt(fin, m) + fr_info_t *fin; + mb_t *m; +{ + m->mb_next = *fin->fin_mp; + *fin->fin_mp = m; + return 0; +} diff --git a/lib/print_toif.c b/lib/print_toif.c index 696fcd3172791..ab1791ad9b72e 100644 --- a/lib/print_toif.c +++ b/lib/print_toif.c @@ -1,30 +1,48 @@ /* - * Copyright (C) 2000-2002 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: print_toif.c,v 1.8.4.1 2006/06/16 17:21:09 darrenr Exp $ + * $Id$ */ #include "ipf.h" -void print_toif(tag, fdp) -char *tag; -frdest_t *fdp; +void +print_toif(family, tag, base, fdp) + int family; + char *tag; + char *base; + frdest_t *fdp; { - printf("%s %s%s", tag, fdp->fd_ifname, - (fdp->fd_ifp || (long)fdp->fd_ifp == -1) ? "" : "(!)"); + switch (fdp->fd_type) + { + case FRD_NORMAL : + PRINTF("%s %s%s", tag, base + fdp->fd_name, + (fdp->fd_ptr || (long)fdp->fd_ptr == -1) ? "" : "(!)"); #ifdef USE_INET6 - if (use_inet6 && IP6_NOTZERO(&fdp->fd_ip6.in6)) { - char ipv6addr[80]; + if (family == AF_INET6) { + if (IP6_NOTZERO(&fdp->fd_ip6)) { + char ipv6addr[80]; - inet_ntop(AF_INET6, &fdp->fd_ip6, ipv6addr, - sizeof(fdp->fd_ip6)); - printf(":%s", ipv6addr); - } else + inet_ntop(AF_INET6, &fdp->fd_ip6, ipv6addr, + sizeof(fdp->fd_ip6)); + PRINTF(":%s", ipv6addr); + } + } else #endif - if (fdp->fd_ip.s_addr) - printf(":%s", inet_ntoa(fdp->fd_ip)); - putchar(' '); + if (fdp->fd_ip.s_addr) + PRINTF(":%s", inet_ntoa(fdp->fd_ip)); + putchar(' '); + break; + + case FRD_DSTLIST : + PRINTF("%s dstlist/%s ", tag, base + fdp->fd_name); + break; + + default : + PRINTF("%s <%d>", tag, fdp->fd_type); + break; + } } diff --git a/lib/printactiveaddr.c b/lib/printactiveaddr.c new file mode 100644 index 0000000000000..531cdc1fc782a --- /dev/null +++ b/lib/printactiveaddr.c @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com) + */ + +#include "ipf.h" + + +#if !defined(lint) +static const char rcsid[] = "@(#)$Id: printactiveaddr.c,v 1.3.2.2 2012/07/22 08:04:24 darren_r Exp $"; +#endif + + +void +printactiveaddress(v, fmt, addr, ifname) + int v; + char *fmt, *ifname; + i6addr_t *addr; +{ + switch (v) + { + case 4 : + PRINTF(fmt, inet_ntoa(addr->in4)); + break; +#ifdef USE_INET6 + case 6 : + printaddr(AF_INET6, FRI_NORMAL, ifname, 0, + (u_32_t *)&addr->in6, NULL); + break; +#endif + default : + break; + } +} diff --git a/lib/printactivenat.c b/lib/printactivenat.c index 99f3e586e7599..5d9c4acbaae28 100644 --- a/lib/printactivenat.c +++ b/lib/printactivenat.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2004 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * @@ -10,73 +10,135 @@ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: printactivenat.c,v 1.3.2.7 2006/12/12 16:13:00 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif -void printactivenat(nat, opts, alive, now) -nat_t *nat; -int opts, alive; -u_long now; +void +printactivenat(nat, opts, ticks) + nat_t *nat; + int opts; + u_long ticks; { - printf("%s", getnattype(nat, alive)); + PRINTF("%s", getnattype(nat)); if (nat->nat_flags & SI_CLONE) - printf(" CLONE"); + PRINTF(" CLONE"); + if (nat->nat_phnext[0] == NULL && nat->nat_phnext[1] == NULL) + PRINTF(" ORPHAN"); - printf(" %-15s", inet_ntoa(nat->nat_inip)); + putchar(' '); + if (nat->nat_redir & NAT_REWRITE) { + printactiveaddress(nat->nat_v[0], "%-15s", &nat->nat_osrc6, + nat->nat_ifnames[0]); - if ((nat->nat_flags & IPN_TCPUDP) != 0) - printf(" %-5hu", ntohs(nat->nat_inport)); + if ((nat->nat_flags & IPN_TCPUDP) != 0) + PRINTF(" %-5hu", ntohs(nat->nat_osport)); - printf(" <- -> %-15s",inet_ntoa(nat->nat_outip)); + putchar(' '); + printactiveaddress(nat->nat_v[0], "%-15s", &nat->nat_odst6, + nat->nat_ifnames[0]); - if ((nat->nat_flags & IPN_TCPUDP) != 0) - printf(" %-5hu", ntohs(nat->nat_outport)); + if ((nat->nat_flags & IPN_TCPUDP) != 0) + PRINTF(" %-5hu", ntohs(nat->nat_odport)); - printf(" [%s", inet_ntoa(nat->nat_oip)); - if ((nat->nat_flags & IPN_TCPUDP) != 0) - printf(" %hu", ntohs(nat->nat_oport)); - printf("]"); + PRINTF("<- -> "); + printactiveaddress(nat->nat_v[1], "%-15s", &nat->nat_nsrc6, + nat->nat_ifnames[0]); + + if ((nat->nat_flags & IPN_TCPUDP) != 0) + PRINTF(" %-5hu", ntohs(nat->nat_nsport)); + + putchar(' '); + printactiveaddress(nat->nat_v[1], "%-15s", &nat->nat_ndst6, + nat->nat_ifnames[0]); + if ((nat->nat_flags & IPN_TCPUDP) != 0) + PRINTF(" %-5hu", ntohs(nat->nat_ndport)); + + } else if (nat->nat_dir == NAT_OUTBOUND) { + printactiveaddress(nat->nat_v[0], "%-15s", &nat->nat_osrc6, + nat->nat_ifnames[0]); + + if ((nat->nat_flags & IPN_TCPUDP) != 0) + PRINTF(" %-5hu", ntohs(nat->nat_osport)); + + PRINTF(" <- -> "); + printactiveaddress(nat->nat_v[1], "%-15s", &nat->nat_nsrc6, + nat->nat_ifnames[0]); + + if ((nat->nat_flags & IPN_TCPUDP) != 0) + PRINTF(" %-5hu", ntohs(nat->nat_nsport)); + + PRINTF(" ["); + printactiveaddress(nat->nat_v[0], "%s", &nat->nat_odst6, + nat->nat_ifnames[0]); + + if ((nat->nat_flags & IPN_TCPUDP) != 0) + PRINTF(" %hu", ntohs(nat->nat_odport)); + PRINTF("]"); + } else { + printactiveaddress(nat->nat_v[1], "%-15s", &nat->nat_ndst6, + nat->nat_ifnames[0]); + + if ((nat->nat_flags & IPN_TCPUDP) != 0) + PRINTF(" %-5hu", ntohs(nat->nat_ndport)); + + PRINTF(" <- -> "); + printactiveaddress(nat->nat_v[0], "%-15s", &nat->nat_odst6, + nat->nat_ifnames[0]); + + if ((nat->nat_flags & IPN_TCPUDP) != 0) + PRINTF(" %-5hu", ntohs(nat->nat_odport)); + + PRINTF(" ["); + printactiveaddress(nat->nat_v[0], "%s", &nat->nat_osrc6, + nat->nat_ifnames[0]); + + if ((nat->nat_flags & IPN_TCPUDP) != 0) + PRINTF(" %hu", ntohs(nat->nat_osport)); + PRINTF("]"); + } if (opts & OPT_VERBOSE) { - printf("\n\tttl %lu use %hu sumd %s/", - nat->nat_age - now, nat->nat_use, + PRINTF("\n\tttl %lu use %hu sumd %s/", + nat->nat_age - ticks, nat->nat_use, getsumd(nat->nat_sumd[0])); - printf("%s pr %u bkt %d/%d flags %x\n", - getsumd(nat->nat_sumd[1]), nat->nat_p, + PRINTF("%s pr %u/%u hash %u/%u flags %x\n", + getsumd(nat->nat_sumd[1]), + nat->nat_pr[0], nat->nat_pr[1], nat->nat_hv[0], nat->nat_hv[1], nat->nat_flags); - printf("\tifp %s", getifname(nat->nat_ifps[0])); - printf(",%s ", getifname(nat->nat_ifps[1])); + PRINTF("\tifp %s", getifname(nat->nat_ifps[0])); + PRINTF(",%s ", getifname(nat->nat_ifps[1])); #ifdef USE_QUAD_T - printf("bytes %qu/%qu pkts %qu/%qu", + PRINTF("bytes %"PRIu64"/%"PRIu64" pkts %"PRIu64"/%"PRIu64"", (unsigned long long)nat->nat_bytes[0], (unsigned long long)nat->nat_bytes[1], (unsigned long long)nat->nat_pkts[0], (unsigned long long)nat->nat_pkts[1]); #else - printf("bytes %lu/%lu pkts %lu/%lu", nat->nat_bytes[0], + PRINTF("bytes %lu/%lu pkts %lu/%lu", nat->nat_bytes[0], nat->nat_bytes[1], nat->nat_pkts[0], nat->nat_pkts[1]); #endif - printf(" ipsumd %x", nat->nat_ipsumd); + PRINTF(" ipsumd %x", nat->nat_ipsumd); } if (opts & OPT_DEBUG) { - printf("\n\tnat_next %p _pnext %p _hm %p\n", + PRINTF("\n\tnat_next %p _pnext %p _hm %p\n", nat->nat_next, nat->nat_pnext, nat->nat_hm); - printf("\t_hnext %p/%p _phnext %p/%p\n", + PRINTF("\t_hnext %p/%p _phnext %p/%p\n", nat->nat_hnext[0], nat->nat_hnext[1], nat->nat_phnext[0], nat->nat_phnext[1]); - printf("\t_data %p _me %p _state %p _aps %p\n", - nat->nat_data, nat->nat_me, nat->nat_state, nat->nat_aps); - printf("\tfr %p ptr %p ifps %p/%p sync %p\n", + PRINTF("\t_data %p _me %p _state %p _aps %p\n", + nat->nat_data, nat->nat_me, nat->nat_state, + nat->nat_aps); + PRINTF("\tfr %p ptr %p ifps %p/%p sync %p\n", nat->nat_fr, nat->nat_ptr, nat->nat_ifps[0], nat->nat_ifps[1], nat->nat_sync); - printf("\ttqe:pnext %p next %p ifq %p parent %p/%p\n", + PRINTF("\ttqe:pnext %p next %p ifq %p parent %p/%p\n", nat->nat_tqe.tqe_pnext, nat->nat_tqe.tqe_next, nat->nat_tqe.tqe_ifq, nat->nat_tqe.tqe_parent, nat); - printf("\ttqe:die %ld touched %ld flags %x state %d/%d\n", + PRINTF("\ttqe:die %d touched %d flags %x state %d/%d\n", nat->nat_tqe.tqe_die, nat->nat_tqe.tqe_touched, nat->nat_tqe.tqe_flags, nat->nat_tqe.tqe_state[0], nat->nat_tqe.tqe_state[1]); diff --git a/lib/printaddr.c b/lib/printaddr.c new file mode 100644 index 0000000000000..03fbacbcce741 --- /dev/null +++ b/lib/printaddr.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + +void +printaddr(family, type, base, ifidx, addr, mask) + int family, type, ifidx; + char *base; + u_32_t *addr, *mask; +{ + char *suffix; + + switch (type) + { + case FRI_BROADCAST : + suffix = "bcast"; + break; + + case FRI_DYNAMIC : + PRINTF("%s", base + ifidx); + printmask(family, mask); + suffix = NULL; + break; + + case FRI_NETWORK : + suffix = "net"; + break; + + case FRI_NETMASKED : + suffix = "netmasked"; + break; + + case FRI_PEERADDR : + suffix = "peer"; + break; + + case FRI_LOOKUP : + suffix = NULL; + printlookup(base, (i6addr_t *)addr, (i6addr_t *)mask); + break; + + case FRI_NONE : + case FRI_NORMAL : + printhostmask(family, addr, mask); + suffix = NULL; + break; + case FRI_RANGE : + printhost(family, addr); + putchar('-'); + printhost(family, mask); + suffix = NULL; + break; + case FRI_SPLIT : + printhost(family, addr); + putchar(','); + printhost(family, mask); + suffix = NULL; + break; + default : + PRINTF("<%d>", type); + printmask(family, mask); + suffix = NULL; + break; + } + + if (suffix != NULL) { + PRINTF("%s/%s", base + ifidx, suffix); + } +} diff --git a/lib/printaps.c b/lib/printaps.c index c0c36d4dbf6bb..9256d5d5decf5 100644 --- a/lib/printaps.c +++ b/lib/printaps.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2004 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * @@ -11,13 +11,14 @@ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: printaps.c,v 1.4.2.1 2006/06/16 17:21:10 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif -void printaps(aps, opts) -ap_session_t *aps; -int opts; +void +printaps(aps, opts, proto) + ap_session_t *aps; + int opts, proto; { ipsec_pxy_t ipsec; ap_session_t ap; @@ -29,33 +30,33 @@ int opts; return; if (kmemcpy((char *)&apr, (long)ap.aps_apr, sizeof(apr))) return; - printf("\tproxy %s/%d use %d flags %x\n", apr.apr_label, + PRINTF("\tproxy %s/%d use %d flags %x\n", apr.apr_label, apr.apr_p, apr.apr_ref, apr.apr_flags); - printf("\t\tproto %d flags %#x bytes ", ap.aps_p, ap.aps_flags); #ifdef USE_QUAD_T - printf("%qu pkts %qu", (unsigned long long)ap.aps_bytes, + PRINTF("\tbytes %"PRIu64" pkts %"PRIu64"", + (unsigned long long)ap.aps_bytes, (unsigned long long)ap.aps_pkts); #else - printf("%lu pkts %lu", ap.aps_bytes, ap.aps_pkts); + PRINTF("\tbytes %lu pkts %lu", ap.aps_bytes, ap.aps_pkts); #endif - printf(" data %s size %d\n", ap.aps_data ? "YES" : "NO", ap.aps_psiz); - if ((ap.aps_p == IPPROTO_TCP) && (opts & OPT_VERBOSE)) { - printf("\t\tstate[%u,%u], sel[%d,%d]\n", + PRINTF(" data %s\n", ap.aps_data ? "YES" : "NO"); + if ((proto == IPPROTO_TCP) && (opts & OPT_VERBOSE)) { + PRINTF("\t\tstate[%u,%u], sel[%d,%d]\n", ap.aps_state[0], ap.aps_state[1], ap.aps_sel[0], ap.aps_sel[1]); #if (defined(NetBSD) && (NetBSD >= 199905) && (NetBSD < 1991011)) || \ (__FreeBSD_version >= 300000) || defined(OpenBSD) - printf("\t\tseq: off %hd/%hd min %x/%x\n", + PRINTF("\t\tseq: off %hd/%hd min %x/%x\n", ap.aps_seqoff[0], ap.aps_seqoff[1], ap.aps_seqmin[0], ap.aps_seqmin[1]); - printf("\t\tack: off %hd/%hd min %x/%x\n", + PRINTF("\t\tack: off %hd/%hd min %x/%x\n", ap.aps_ackoff[0], ap.aps_ackoff[1], ap.aps_ackmin[0], ap.aps_ackmin[1]); #else - printf("\t\tseq: off %hd/%hd min %lx/%lx\n", + PRINTF("\t\tseq: off %hd/%hd min %lx/%lx\n", ap.aps_seqoff[0], ap.aps_seqoff[1], ap.aps_seqmin[0], ap.aps_seqmin[1]); - printf("\t\tack: off %hd/%hd min %lx/%lx\n", + PRINTF("\t\tack: off %hd/%hd min %lx/%lx\n", ap.aps_ackoff[0], ap.aps_ackoff[1], ap.aps_ackmin[0], ap.aps_ackmin[1]); #endif @@ -64,43 +65,43 @@ int opts; if (!strcmp(apr.apr_label, "raudio") && ap.aps_psiz == sizeof(ra)) { if (kmemcpy((char *)&ra, (long)ap.aps_data, sizeof(ra))) return; - printf("\tReal Audio Proxy:\n"); - printf("\t\tSeen PNA: %d\tVersion: %d\tEOS: %d\n", + PRINTF("\tReal Audio Proxy:\n"); + PRINTF("\t\tSeen PNA: %d\tVersion: %d\tEOS: %d\n", ra.rap_seenpna, ra.rap_version, ra.rap_eos); - printf("\t\tMode: %#x\tSBF: %#x\n", ra.rap_mode, ra.rap_sbf); - printf("\t\tPorts:pl %hu, pr %hu, sr %hu\n", + PRINTF("\t\tMode: %#x\tSBF: %#x\n", ra.rap_mode, ra.rap_sbf); + PRINTF("\t\tPorts:pl %hu, pr %hu, sr %hu\n", ra.rap_plport, ra.rap_prport, ra.rap_srport); } else if (!strcmp(apr.apr_label, "ftp") && (ap.aps_psiz == sizeof(ftp))) { if (kmemcpy((char *)&ftp, (long)ap.aps_data, sizeof(ftp))) return; - printf("\tFTP Proxy:\n"); - printf("\t\tpassok: %d\n", ftp.ftp_passok); + PRINTF("\tFTP Proxy:\n"); + PRINTF("\t\tpassok: %d\n", ftp.ftp_passok); ftp.ftp_side[0].ftps_buf[FTP_BUFSZ - 1] = '\0'; ftp.ftp_side[1].ftps_buf[FTP_BUFSZ - 1] = '\0'; - printf("\tClient:\n"); - printf("\t\tseq %x (ack %x) len %d junk %d cmds %d\n", + PRINTF("\tClient:\n"); + PRINTF("\t\tseq %x (ack %x) len %d junk %d cmds %d\n", ftp.ftp_side[0].ftps_seq[0], ftp.ftp_side[0].ftps_seq[1], ftp.ftp_side[0].ftps_len, ftp.ftp_side[0].ftps_junk, ftp.ftp_side[0].ftps_cmds); - printf("\t\tbuf ["); + PRINTF("\t\tbuf ["); printbuf(ftp.ftp_side[0].ftps_buf, FTP_BUFSZ, 1); - printf("]\n\tServer:\n"); - printf("\t\tseq %x (ack %x) len %d junk %d cmds %d\n", + PRINTF("]\n\tServer:\n"); + PRINTF("\t\tseq %x (ack %x) len %d junk %d cmds %d\n", ftp.ftp_side[1].ftps_seq[0], ftp.ftp_side[1].ftps_seq[1], ftp.ftp_side[1].ftps_len, ftp.ftp_side[1].ftps_junk, ftp.ftp_side[1].ftps_cmds); - printf("\t\tbuf ["); + PRINTF("\t\tbuf ["); printbuf(ftp.ftp_side[1].ftps_buf, FTP_BUFSZ, 1); - printf("]\n"); + PRINTF("]\n"); } else if (!strcmp(apr.apr_label, "ipsec") && (ap.aps_psiz == sizeof(ipsec))) { if (kmemcpy((char *)&ipsec, (long)ap.aps_data, sizeof(ipsec))) return; - printf("\tIPSec Proxy:\n"); - printf("\t\tICookie %08x%08x RCookie %08x%08x %s\n", + PRINTF("\tIPSec Proxy:\n"); + PRINTF("\t\tICookie %08x%08x RCookie %08x%08x %s\n", (u_int)ntohl(ipsec.ipsc_icookie[0]), (u_int)ntohl(ipsec.ipsc_icookie[1]), (u_int)ntohl(ipsec.ipsc_rcookie[0]), diff --git a/lib/printbuf.c b/lib/printbuf.c index bc097e025a675..9b1e76cc60b13 100644 --- a/lib/printbuf.c +++ b/lib/printbuf.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2000-2004 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: printbuf.c,v 1.5.4.2 2006/06/16 17:21:10 darrenr Exp $ + * $Id$ */ #include <ctype.h> @@ -11,19 +11,21 @@ #include "ipf.h" -void printbuf(buf, len, zend) -char *buf; -int len, zend; +void +printbuf(buf, len, zend) + char *buf; + int len, zend; { - char *s, c; + char *s; + int c; int i; for (s = buf, i = len; i; i--) { c = *s++; - if (ISPRINT(c)) + if (isprint(c)) putchar(c); else - printf("\\%03o", c); + PRINTF("\\%03o", c); if ((c == '\0') && zend) break; } diff --git a/lib/printdstl_live.c b/lib/printdstl_live.c new file mode 100644 index 0000000000000..c8741ed4005a2 --- /dev/null +++ b/lib/printdstl_live.c @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include <sys/ioctl.h> +#include "ipf.h" +#include "netinet/ipl.h" + + +/* + * Because the ipf_dstnode_t can vary in size because of the interface name, + * the size may be larger than just sizeof(). + */ +ippool_dst_t * +printdstl_live(d, fd, name, opts, fields) + ippool_dst_t *d; + int fd; + char *name; + int opts; + wordtab_t *fields; +{ + ipf_dstnode_t *entry, *zero; + ipflookupiter_t iter; + int printed, last; + ipfobj_t obj; + + if ((name != NULL) && strncmp(name, d->ipld_name, FR_GROUPLEN)) + return d->ipld_next; + + entry = calloc(1, sizeof(*entry) + 64); + if (entry == NULL) + return d->ipld_next; + zero = calloc(1, sizeof(*zero) + 64); + if (zero == NULL) { + free(entry); + return d->ipld_next; + } + + if (fields == NULL) + printdstlistdata(d, opts); + + if ((d->ipld_flags & IPHASH_DELETE) != 0) + PRINTF("# "); + + if ((opts & OPT_DEBUG) == 0) + PRINTF("\t{"); + + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_type = IPFOBJ_LOOKUPITER; + obj.ipfo_ptr = &iter; + obj.ipfo_size = sizeof(iter); + + iter.ili_data = entry; + iter.ili_type = IPLT_DSTLIST; + iter.ili_otype = IPFLOOKUPITER_NODE; + iter.ili_ival = IPFGENITER_LOOKUP; + iter.ili_unit = d->ipld_unit; + strncpy(iter.ili_name, d->ipld_name, FR_GROUPLEN); + + last = 0; + printed = 0; + + while (!last && (ioctl(fd, SIOCLOOKUPITER, &obj) == 0)) { + if (entry->ipfd_next == NULL) + last = 1; + if (bcmp((char *)zero, (char *)entry, sizeof(*zero)) == 0) + break; + (void) printdstlistnode(entry, bcopywrap, opts, fields); + printed++; + } + + (void) ioctl(fd, SIOCIPFDELTOK, &iter.ili_key); + free(entry); + free(zero); + + if (printed == 0) + putchar(';'); + + if ((opts & OPT_DEBUG) == 0) + PRINTF(" };\n"); + return d->ipld_next; +} diff --git a/lib/printdstlist.c b/lib/printdstlist.c new file mode 100644 index 0000000000000..829a1d2e69ced --- /dev/null +++ b/lib/printdstlist.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include "ipf.h" + + +ippool_dst_t * +printdstlist(pp, copyfunc, name, opts, nodes, fields) + ippool_dst_t *pp; + copyfunc_t copyfunc; + char *name; + int opts; + ipf_dstnode_t *nodes; + wordtab_t *fields; +{ + ipf_dstnode_t *node; + ippool_dst_t dst; + + if ((*copyfunc)(pp, &dst, sizeof(dst))) + return NULL; + + if ((name != NULL) && strncmp(name, dst.ipld_name, FR_GROUPLEN)) + return dst.ipld_next; + + if (fields == NULL) + printdstlistdata(&dst, opts); + + if ((dst.ipld_flags & IPDST_DELETE) != 0) + PRINTF("# "); + if ((opts & OPT_DEBUG) == 0) + PRINTF("\t{"); + + if (nodes == NULL) { + putchar(';'); + } else { + for (node = nodes; node != NULL; ) { + ipf_dstnode_t *n; + + n = calloc(1, node->ipfd_size); + if (n == NULL) + break; + if ((*copyfunc)(node, n, node->ipfd_size)) { + free(n); + return NULL; + } + + node = printdstlistnode(n, bcopywrap, opts, fields); + + free(n); + } + } + + if ((opts & OPT_DEBUG) == 0) + PRINTF(" };\n"); + + return dst.ipld_next; +} diff --git a/lib/printdstlistdata.c b/lib/printdstlistdata.c new file mode 100644 index 0000000000000..8b55afdb57c7d --- /dev/null +++ b/lib/printdstlistdata.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include "ipf.h" +#include <ctype.h> + + +void +printdstlistdata(pool, opts) + ippool_dst_t *pool; + int opts; +{ + + if ((opts & OPT_DEBUG) == 0) { + if ((pool->ipld_flags & IPDST_DELETE) != 0) + PRINTF("# "); + PRINTF("pool "); + } else { + if ((pool->ipld_flags & IPDST_DELETE) != 0) + PRINTF("# "); + PRINTF("Name: %s\tRole: ", pool->ipld_name); + } + + printunit(pool->ipld_unit); + + if ((opts & OPT_DEBUG) == 0) { + PRINTF("/dstlist (name %s;", pool->ipld_name); + if (pool->ipld_policy != IPLDP_NONE) { + PRINTF(" policy "); + printdstlistpolicy(pool->ipld_policy); + putchar(';'); + } + PRINTF(")\n"); + } else { + putchar(' '); + + PRINTF("\tReferences: %d\n", pool->ipld_ref); + if ((pool->ipld_flags & IPDST_DELETE) != 0) + PRINTF("# "); + PRINTF("Policy: \n"); + printdstlistpolicy(pool->ipld_policy); + PRINTF("\n\tNodes Starting at %p\n", pool->ipld_dests); + } +} diff --git a/lib/printdstlistnode.c b/lib/printdstlistnode.c new file mode 100644 index 0000000000000..898986d1c0661 --- /dev/null +++ b/lib/printdstlistnode.c @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include "ipf.h" + + +ipf_dstnode_t * +printdstlistnode(inp, copyfunc, opts, fields) + ipf_dstnode_t *inp; + copyfunc_t copyfunc; + int opts; + wordtab_t *fields; +{ + ipf_dstnode_t node, *np; + int i; +#ifdef USE_INET6 + char buf[INET6_ADDRSTRLEN+1]; + const char *str; +#endif + + if ((*copyfunc)(inp, &node, sizeof(node))) + return NULL; + + np = calloc(1, node.ipfd_size); + if (np == NULL) + return node.ipfd_next; + if ((*copyfunc)(inp, np, node.ipfd_size)) + return NULL; + + if (fields != NULL) { + for (i = 0; fields[i].w_value != 0; i++) { + printpoolfield(np, IPLT_DSTLIST, i); + if (fields[i + 1].w_value != 0) + printf("\t"); + } + printf("\n"); + } else if ((opts & OPT_DEBUG) == 0) { + putchar(' '); + if (np->ipfd_dest.fd_name >= 0) + PRINTF("%s:", np->ipfd_names); + if (np->ipfd_dest.fd_addr.adf_family == AF_INET) { + printip(AF_INET, (u_32_t *)&np->ipfd_dest.fd_ip); + } else { +#ifdef USE_INET6 + str = inet_ntop(AF_INET6, &np->ipfd_dest.fd_ip6, + buf, sizeof(buf) - 1); + if (str != NULL) + PRINTF("%s", str); +#endif + } + putchar(';'); + } else { + PRINTF("Interface: [%s]/%d\n", np->ipfd_names, + np->ipfd_dest.fd_name); +#ifdef USE_INET6 + str = inet_ntop(np->ipfd_dest.fd_addr.adf_family, + &np->ipfd_dest.fd_ip6, buf, sizeof(buf) - 1); + if (str != NULL) { + PRINTF("\tAddress: %s\n", str); + } +#else + PRINTF("\tAddress: %s\n", inet_ntoa(np->ipfd_dest.fd_ip)); +#endif + PRINTF( +#ifdef USE_QUAD_T + "\t\tStates %d\tRef %d\tName [%s]\tUid %d\n", +#else + "\t\tStates %d\tRef %d\tName [%s]\tUid %d\n", +#endif + np->ipfd_states, np->ipfd_ref, + np->ipfd_names, np->ipfd_uid); + } + free(np); + return node.ipfd_next; +} diff --git a/lib/printdstlistpolicy.c b/lib/printdstlistpolicy.c new file mode 100644 index 0000000000000..4873b95e207f5 --- /dev/null +++ b/lib/printdstlistpolicy.c @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include "ipf.h" + + +void +printdstlistpolicy(policy) + ippool_policy_t policy; +{ + switch (policy) + { + case IPLDP_NONE : + PRINTF("none"); + break; + case IPLDP_ROUNDROBIN : + PRINTF("round-robin"); + break; + case IPLDP_CONNECTION : + PRINTF("weighting connection"); + break; + case IPLDP_RANDOM : + PRINTF("random"); + break; + default : + break; + } +} diff --git a/lib/printfieldhdr.c b/lib/printfieldhdr.c new file mode 100644 index 0000000000000..3cc22a655a635 --- /dev/null +++ b/lib/printfieldhdr.c @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: printfieldhdr.c,v 1.5.2.3 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" +#include <ctype.h> + + +void +printfieldhdr(words, field) + wordtab_t *words, *field; +{ + wordtab_t *w; + char *s, *t; + int i; + + if (field->w_value == -2) { + for (i = 0, w = words; w->w_word != NULL; ) { + if (w->w_value > 0) { + printfieldhdr(words, w); + w++; + if (w->w_value > 0) + putchar('\t'); + } else { + w++; + } + } + return; + } + + for (w = words; w->w_word != NULL; w++) { + if (w->w_value == field->w_value) { + if (w->w_word == field->w_word) { + s = strdup(w->w_word); + } else { + s = NULL; + } + + if ((w->w_word != field->w_word) || (s == NULL)) { + PRINTF("%s", field->w_word); + } else { + for (t = s; *t != '\0'; t++) { + if (ISALPHA(*t) && ISLOWER(*t)) + *t = TOUPPER(*t); + } + PRINTF("%s", s); + free(s); + } + } + } +} diff --git a/lib/printfr.c b/lib/printfr.c index 07506945a02c1..44a56fa4912fb 100644 --- a/lib/printfr.c +++ b/lib/printfr.c @@ -1,159 +1,86 @@ /* - * Copyright (C) 2000-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: printfr.c,v 1.43.2.18 2007/05/07 06:55:38 darrenr Exp $ + * $Id$ */ #include "ipf.h" -static void printaddr(int, int, char *, u_32_t *, u_32_t *); - -static void printaddr(v, type, ifname, addr, mask) -int v, type; -char *ifname; -u_32_t *addr, *mask; -{ - char *suffix; - - switch (type) - { - case FRI_BROADCAST : - suffix = "bcast"; - break; - - case FRI_DYNAMIC : - printf("%s", ifname); - printmask(mask); - suffix = NULL; - break; - - case FRI_NETWORK : - suffix = "net"; - break; - - case FRI_NETMASKED : - suffix = "netmasked"; - break; - - case FRI_PEERADDR : - suffix = "peer"; - break; - - case FRI_LOOKUP : - suffix = NULL; - printlookup((i6addr_t *)addr, (i6addr_t *)mask); - break; - - case FRI_NORMAL : - printhostmask(v, addr, mask); - suffix = NULL; - break; - default : - printf("<%d>", type); - printmask(mask); - suffix = NULL; - break; - } - - if (suffix != NULL) { - printf("%s/%s", ifname, suffix); - } -} - - -void printlookup(addr, mask) -i6addr_t *addr, *mask; -{ - switch (addr->iplookuptype) - { - case IPLT_POOL : - printf("pool/"); - break; - case IPLT_HASH : - printf("hash/"); - break; - default : - printf("lookup(%x)=", addr->iplookuptype); - break; - } - - printf("%u", addr->iplookupnum); - if (mask->iplookupptr == NULL) - printf("(!)"); -} - /* * print the filter structure in a useful way */ -void printfr(fp, iocfunc) -struct frentry *fp; -ioctlfunc_t iocfunc; +void +printfr(fp, iocfunc) + struct frentry *fp; + ioctlfunc_t iocfunc; { struct protoent *p; u_short sec[2]; u_32_t type; - u_char *t; + int pr, af; char *s; - int pr; + int hash; pr = -2; type = fp->fr_type & ~FR_T_BUILTIN; if ((fp->fr_type & FR_T_BUILTIN) != 0) - printf("# Builtin: "); + PRINTF("# Builtin: "); if (fp->fr_collect != 0) - printf("%u ", fp->fr_collect); + PRINTF("%u ", fp->fr_collect); if (fp->fr_type == FR_T_CALLFUNC) { ; } else if (fp->fr_func != NULL) { - printf("call"); + PRINTF("call"); if ((fp->fr_flags & FR_CALLNOW) != 0) - printf(" now"); + PRINTF(" now"); s = kvatoname(fp->fr_func, iocfunc); - printf(" %s/%u", s ? s : "?", fp->fr_arg); + PRINTF(" %s/%u", s ? s : "?", fp->fr_arg); } else if (FR_ISPASS(fp->fr_flags)) - printf("pass"); + PRINTF("pass"); else if (FR_ISBLOCK(fp->fr_flags)) { - printf("block"); + PRINTF("block"); } else if ((fp->fr_flags & FR_LOGMASK) == FR_LOG) { printlog(fp); } else if (FR_ISACCOUNT(fp->fr_flags)) - printf("count"); + PRINTF("count"); else if (FR_ISAUTH(fp->fr_flags)) - printf("auth"); + PRINTF("auth"); else if (FR_ISPREAUTH(fp->fr_flags)) - printf("preauth"); + PRINTF("preauth"); else if (FR_ISNOMATCH(fp->fr_flags)) - printf("nomatch"); + PRINTF("nomatch"); + else if (FR_ISDECAPS(fp->fr_flags)) + PRINTF("decapsulate"); else if (FR_ISSKIP(fp->fr_flags)) - printf("skip %u", fp->fr_arg); + PRINTF("skip %u", fp->fr_arg); else { - printf("%x", fp->fr_flags); + PRINTF("%x", fp->fr_flags); } if (fp->fr_flags & FR_RETICMP) { if ((fp->fr_flags & FR_RETMASK) == FR_FAKEICMP) - printf(" return-icmp-as-dest"); + PRINTF(" return-icmp-as-dest"); else if ((fp->fr_flags & FR_RETMASK) == FR_RETICMP) - printf(" return-icmp"); + PRINTF(" return-icmp"); if (fp->fr_icode) { if (fp->fr_icode <= MAX_ICMPCODE) - printf("(%s)", + PRINTF("(%s)", icmpcodes[(int)fp->fr_icode]); else - printf("(%d)", fp->fr_icode); + PRINTF("(%d)", fp->fr_icode); } } else if ((fp->fr_flags & FR_RETMASK) == FR_RETRST) - printf(" return-rst"); + PRINTF(" return-rst"); if (fp->fr_flags & FR_OUTQUE) - printf(" out "); - else - printf(" in "); + PRINTF(" out "); + else if (fp->fr_flags & FR_INQUE) + PRINTF(" in "); if (((fp->fr_flags & FR_LOGB) == FR_LOGB) || ((fp->fr_flags & FR_LOGP) == FR_LOGP)) { @@ -162,126 +89,153 @@ ioctlfunc_t iocfunc; } if (fp->fr_flags & FR_QUICK) - printf("quick "); - - if (*fp->fr_ifname) { - printifname("on ", fp->fr_ifname, fp->fr_ifa); - if (*fp->fr_ifnames[1] && strcmp(fp->fr_ifnames[1], "*")) - printifname(",", fp->fr_ifnames[1], fp->fr_ifas[1]); + PRINTF("quick "); + + if (fp->fr_ifnames[0] != -1) { + printifname("on ", fp->fr_names + fp->fr_ifnames[0], + fp->fr_ifa); + if (fp->fr_ifnames[1] != -1 && + strcmp(fp->fr_names + fp->fr_ifnames[1], "*")) + printifname(",", fp->fr_names + fp->fr_ifnames[1], + fp->fr_ifas[1]); putchar(' '); } - if (*fp->fr_dif.fd_ifname || (fp->fr_flags & FR_DUP)) - print_toif("dup-to", &fp->fr_dif); - if (*fp->fr_tif.fd_ifname) - print_toif("to", &fp->fr_tif); - if (*fp->fr_rif.fd_ifname) - print_toif("reply-to", &fp->fr_rif); + if (fp->fr_tif.fd_name != -1) + print_toif(fp->fr_family, "to", fp->fr_names, &fp->fr_tif); + if (fp->fr_dif.fd_name != -1) + print_toif(fp->fr_family, "dup-to", fp->fr_names, + &fp->fr_dif); + if (fp->fr_rif.fd_name != -1) + print_toif(fp->fr_family, "reply-to", fp->fr_names, + &fp->fr_rif); if (fp->fr_flags & FR_FASTROUTE) - printf("fastroute "); + PRINTF("fastroute "); - if ((*fp->fr_ifnames[2] && strcmp(fp->fr_ifnames[2], "*")) || - (*fp->fr_ifnames[3] && strcmp(fp->fr_ifnames[3], "*"))) { + if ((fp->fr_ifnames[2] != -1 && + strcmp(fp->fr_names + fp->fr_ifnames[2], "*")) || + (fp->fr_ifnames[3] != -1 && + strcmp(fp->fr_names + fp->fr_ifnames[3], "*"))) { if (fp->fr_flags & FR_OUTQUE) - printf("in-via "); + PRINTF("in-via "); else - printf("out-via "); + PRINTF("out-via "); - if (*fp->fr_ifnames[2]) { - printifname("", fp->fr_ifnames[2], + if (fp->fr_ifnames[2] != -1) { + printifname("", fp->fr_names + fp->fr_ifnames[2], fp->fr_ifas[2]); - if (*fp->fr_ifnames[3]) { - printifname(",", fp->fr_ifnames[3], + if (fp->fr_ifnames[3] != -1) { + printifname(",", + fp->fr_names + fp->fr_ifnames[3], fp->fr_ifas[3]); } putchar(' '); } } + if (fp->fr_family == AF_INET) { + PRINTF("inet "); + af = AF_INET; +#ifdef USE_INET6 + } else if (fp->fr_family == AF_INET6) { + PRINTF("inet6 "); + af = AF_INET6; +#endif + } else { + af = -1; + } + if (type == FR_T_IPF) { if (fp->fr_mip.fi_tos) - printf("tos %#x ", fp->fr_tos); + PRINTF("tos %#x ", fp->fr_tos); if (fp->fr_mip.fi_ttl) - printf("ttl %d ", fp->fr_ttl); + PRINTF("ttl %d ", fp->fr_ttl); if (fp->fr_flx & FI_TCPUDP) { - printf("proto tcp/udp "); + PRINTF("proto tcp/udp "); pr = -1; } else if (fp->fr_mip.fi_p) { pr = fp->fr_ip.fi_p; p = getprotobynumber(pr); - printf("proto "); + PRINTF("proto "); printproto(p, pr, NULL); putchar(' '); } } - if (type == FR_T_NONE) { - printf("all"); - } else if (type == FR_T_IPF) { - printf("from %s", fp->fr_flags & FR_NOTSRCIP ? "!" : ""); - printaddr(fp->fr_v, fp->fr_satype, fp->fr_ifname, + switch (type) + { + case FR_T_NONE : + PRINTF("all"); + break; + + case FR_T_IPF : + PRINTF("from %s", fp->fr_flags & FR_NOTSRCIP ? "!" : ""); + printaddr(af, fp->fr_satype, fp->fr_names, fp->fr_ifnames[0], &fp->fr_src.s_addr, &fp->fr_smsk.s_addr); if (fp->fr_scmp) printportcmp(pr, &fp->fr_tuc.ftu_src); - printf(" to %s", fp->fr_flags & FR_NOTDSTIP ? "!" : ""); - printaddr(fp->fr_v, fp->fr_datype, fp->fr_ifname, + PRINTF(" to %s", fp->fr_flags & FR_NOTDSTIP ? "!" : ""); + printaddr(af, fp->fr_datype, fp->fr_names, fp->fr_ifnames[0], &fp->fr_dst.s_addr, &fp->fr_dmsk.s_addr); if (fp->fr_dcmp) printportcmp(pr, &fp->fr_tuc.ftu_dst); - if (fp->fr_proto == IPPROTO_ICMP && fp->fr_icmpm) { + if (((fp->fr_proto == IPPROTO_ICMP) || + (fp->fr_proto == IPPROTO_ICMPV6)) && fp->fr_icmpm) { int type = fp->fr_icmp, code; + char *name; type = ntohs(fp->fr_icmp); code = type & 0xff; type /= 256; - if (type < (sizeof(icmptypes) / sizeof(char *) - 1) && - icmptypes[type]) - printf(" icmp-type %s", icmptypes[type]); + name = icmptypename(fp->fr_family, type); + if (name == NULL) + PRINTF(" icmp-type %d", type); else - printf(" icmp-type %d", type); + PRINTF(" icmp-type %s", name); if (ntohs(fp->fr_icmpm) & 0xff) - printf(" code %d", code); + PRINTF(" code %d", code); } if ((fp->fr_proto == IPPROTO_TCP) && (fp->fr_tcpf || fp->fr_tcpfm)) { - printf(" flags "); - if (fp->fr_tcpf & ~TCPF_ALL) - printf("0x%x", fp->fr_tcpf); - else - for (s = flagset, t = flags; *s; s++, t++) - if (fp->fr_tcpf & *t) - (void)putchar(*s); - if (fp->fr_tcpfm) { - (void)putchar('/'); - if (fp->fr_tcpfm & ~TCPF_ALL) - printf("0x%x", fp->fr_tcpfm); - else - for (s = flagset, t = flags; *s; - s++, t++) - if (fp->fr_tcpfm & *t) - (void)putchar(*s); - } + PRINTF(" flags "); + printtcpflags(fp->fr_tcpf, fp->fr_tcpfm); } - } else if (type == FR_T_BPFOPC) { + break; + + case FR_T_BPFOPC : + { fakebpf_t *fb; int i; - printf("bpf-v%d { \"", fp->fr_v); + PRINTF("bpf-v%d { \"", fp->fr_family); i = fp->fr_dsize / sizeof(*fb); for (fb = fp->fr_data, s = ""; i; i--, fb++, s = " ") - printf("%s%#x %#x %#x %#x", s, fb->fb_c, fb->fb_t, + PRINTF("%s%#x %#x %#x %#x", s, fb->fb_c, fb->fb_t, fb->fb_f, fb->fb_k); - printf("\" }"); - } else if (type == FR_T_COMPIPF) { - ; - } else if (type == FR_T_CALLFUNC) { - printf("call function at %p", fp->fr_data); - } else { - printf("[unknown filter type %#x]", fp->fr_type); + PRINTF("\" }"); + break; + } + + case FR_T_COMPIPF : + break; + + case FR_T_CALLFUNC : + PRINTF("call function at %p", fp->fr_data); + break; + + case FR_T_IPFEXPR : + PRINTF("exp { \""); + printipfexpr(fp->fr_data); + PRINTF("\" } "); + break; + + default : + PRINTF("[unknown filter type %#x]", fp->fr_type); + break; } if ((type == FR_T_IPF) && @@ -290,12 +244,12 @@ ioctlfunc_t iocfunc; fp->fr_secbits || fp->fr_secmask)) { char *comma = " "; - printf(" with"); + PRINTF(" with"); if (fp->fr_optbits || fp->fr_optmask || fp->fr_secbits || fp->fr_secmask) { sec[0] = fp->fr_secmask; sec[1] = fp->fr_secbits; - if (fp->fr_v == 4) + if (fp->fr_family == AF_INET) optprint(sec, fp->fr_optmask, fp->fr_optbits); #ifdef USE_INET6 else @@ -305,175 +259,213 @@ ioctlfunc_t iocfunc; } else if (fp->fr_mflx & FI_OPTIONS) { fputs(comma, stdout); if (!(fp->fr_flx & FI_OPTIONS)) - printf("not "); - printf("ipopts"); + PRINTF("not "); + PRINTF("ipopts"); comma = ","; } if (fp->fr_mflx & FI_SHORT) { fputs(comma, stdout); if (!(fp->fr_flx & FI_SHORT)) - printf("not "); - printf("short"); + PRINTF("not "); + PRINTF("short"); comma = ","; } if (fp->fr_mflx & FI_FRAG) { fputs(comma, stdout); if (!(fp->fr_flx & FI_FRAG)) - printf("not "); - printf("frag"); + PRINTF("not "); + PRINTF("frag"); comma = ","; } if (fp->fr_mflx & FI_FRAGBODY) { fputs(comma, stdout); if (!(fp->fr_flx & FI_FRAGBODY)) - printf("not "); - printf("frag-body"); + PRINTF("not "); + PRINTF("frag-body"); comma = ","; } if (fp->fr_mflx & FI_NATED) { fputs(comma, stdout); if (!(fp->fr_flx & FI_NATED)) - printf("not "); - printf("nat"); + PRINTF("not "); + PRINTF("nat"); comma = ","; } if (fp->fr_mflx & FI_LOWTTL) { fputs(comma, stdout); if (!(fp->fr_flx & FI_LOWTTL)) - printf("not "); - printf("lowttl"); + PRINTF("not "); + PRINTF("lowttl"); comma = ","; } if (fp->fr_mflx & FI_BAD) { fputs(comma, stdout); if (!(fp->fr_flx & FI_BAD)) - printf("not "); - printf("bad"); + PRINTF("not "); + PRINTF("bad"); comma = ","; } if (fp->fr_mflx & FI_BADSRC) { fputs(comma, stdout); if (!(fp->fr_flx & FI_BADSRC)) - printf("not "); - printf("bad-src"); + PRINTF("not "); + PRINTF("bad-src"); comma = ","; } if (fp->fr_mflx & FI_BADNAT) { fputs(comma, stdout); if (!(fp->fr_flx & FI_BADNAT)) - printf("not "); - printf("bad-nat"); + PRINTF("not "); + PRINTF("bad-nat"); comma = ","; } if (fp->fr_mflx & FI_OOW) { fputs(comma, stdout); if (!(fp->fr_flx & FI_OOW)) - printf("not "); - printf("oow"); + PRINTF("not "); + PRINTF("oow"); comma = ","; } if (fp->fr_mflx & FI_MBCAST) { fputs(comma, stdout); if (!(fp->fr_flx & FI_MBCAST)) - printf("not "); - printf("mbcast"); + PRINTF("not "); + PRINTF("mbcast"); comma = ","; } if (fp->fr_mflx & FI_BROADCAST) { fputs(comma, stdout); if (!(fp->fr_flx & FI_BROADCAST)) - printf("not "); - printf("bcast"); + PRINTF("not "); + PRINTF("bcast"); comma = ","; } if (fp->fr_mflx & FI_MULTICAST) { fputs(comma, stdout); if (!(fp->fr_flx & FI_MULTICAST)) - printf("not "); - printf("mcast"); + PRINTF("not "); + PRINTF("mcast"); comma = ","; } if (fp->fr_mflx & FI_STATE) { fputs(comma, stdout); if (!(fp->fr_flx & FI_STATE)) - printf("not "); - printf("state"); + PRINTF("not "); + PRINTF("state"); + comma = ","; + } + if (fp->fr_mflx & FI_V6EXTHDR) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_V6EXTHDR)) + PRINTF("not "); + PRINTF("v6hdrs"); comma = ","; } } if (fp->fr_flags & FR_KEEPSTATE) { - printf(" keep state"); - if ((fp->fr_flags & (FR_STSTRICT|FR_NEWISN|FR_NOICMPERR|FR_STATESYNC)) || - (fp->fr_statemax != 0) || (fp->fr_age[0] != 0)) { + host_track_t *src = &fp->fr_srctrack; + PRINTF(" keep state"); + if ((fp->fr_flags & (FR_STSTRICT|FR_NEWISN| + FR_NOICMPERR|FR_STATESYNC)) || + (fp->fr_statemax != 0) || (fp->fr_age[0] != 0) || + (src->ht_max_nodes != 0)) { char *comma = ""; - printf(" ("); + PRINTF(" ("); if (fp->fr_statemax != 0) { - printf("limit %u", fp->fr_statemax); + PRINTF("limit %u", fp->fr_statemax); + comma = ","; + } + if (src->ht_max_nodes != 0) { + PRINTF("%smax-nodes %d", comma, + src->ht_max_nodes); + if (src->ht_max_per_node) + PRINTF(", max-per-src %d/%d", + src->ht_max_per_node, + src->ht_netmask); comma = ","; } if (fp->fr_flags & FR_STSTRICT) { - printf("%sstrict", comma); + PRINTF("%sstrict", comma); + comma = ","; + } + if (fp->fr_flags & FR_STLOOSE) { + PRINTF("%sloose", comma); comma = ","; } if (fp->fr_flags & FR_NEWISN) { - printf("%snewisn", comma); + PRINTF("%snewisn", comma); comma = ","; } if (fp->fr_flags & FR_NOICMPERR) { - printf("%sno-icmp-err", comma); + PRINTF("%sno-icmp-err", comma); comma = ","; } if (fp->fr_flags & FR_STATESYNC) { - printf("%ssync", comma); + PRINTF("%ssync", comma); comma = ","; } if (fp->fr_age[0] || fp->fr_age[1]) - printf("%sage %d/%d", comma, fp->fr_age[0], + PRINTF("%sage %d/%d", comma, fp->fr_age[0], fp->fr_age[1]); - printf(")"); + PRINTF(")"); } } if (fp->fr_flags & FR_KEEPFRAG) { - printf(" keep frags"); + PRINTF(" keep frags"); if (fp->fr_flags & (FR_FRSTRICT)) { - printf(" ("); + PRINTF(" ("); if (fp->fr_flags & FR_FRSTRICT) - printf("strict"); - printf(")"); - + PRINTF("strict"); + PRINTF(")"); + } } if (fp->fr_isc != (struct ipscan *)-1) { - if (fp->fr_isctag[0]) - printf(" scan %s", fp->fr_isctag); + if (fp->fr_isctag != -1) + PRINTF(" scan %s", fp->fr_isctag + fp->fr_names); else - printf(" scan *"); + PRINTF(" scan *"); } - if (*fp->fr_grhead != '\0') - printf(" head %s", fp->fr_grhead); - if (*fp->fr_group != '\0') - printf(" group %s", fp->fr_group); + if (fp->fr_grhead != -1) + PRINTF(" head %s", fp->fr_names + fp->fr_grhead); + if (fp->fr_group != -1) + PRINTF(" group %s", fp->fr_names + fp->fr_group); if (fp->fr_logtag != FR_NOLOGTAG || *fp->fr_nattag.ipt_tag) { char *s = ""; - printf(" set-tag("); + PRINTF(" set-tag("); if (fp->fr_logtag != FR_NOLOGTAG) { - printf("log=%u", fp->fr_logtag); + PRINTF("log=%u", fp->fr_logtag); s = ", "; } if (*fp->fr_nattag.ipt_tag) { - printf("%snat=%-.*s", s, IPFTAG_LEN, + PRINTF("%snat=%-.*s", s, IPFTAG_LEN, fp->fr_nattag.ipt_tag); } - printf(")"); + PRINTF(")"); } if (fp->fr_pps) - printf(" pps %d", fp->fr_pps); + PRINTF(" pps %d", fp->fr_pps); + if (fp->fr_comment != -1) + PRINTF(" comment \"%s\"", fp->fr_names + fp->fr_comment); + + hash = 0; if ((fp->fr_flags & FR_KEEPSTATE) && (opts & OPT_VERBOSE)) { - printf(" # count %d", fp->fr_statecnt); + PRINTF(" # count %d", fp->fr_statecnt); + if (fp->fr_die != 0) + PRINTF(" rule-ttl %u", fp->fr_die); + hash = 1; + } else if (fp->fr_die != 0) { + PRINTF(" # rule-ttl %u", fp->fr_die); + hash = 1; + } + if (opts & OPT_DEBUG) { + if (hash == 0) + putchar('#'); + PRINTF(" ref %d", fp->fr_ref); } (void)putchar('\n'); } diff --git a/lib/printfraginfo.c b/lib/printfraginfo.c index 012df06960cb6..053c2337adb0f 100644 --- a/lib/printfraginfo.c +++ b/lib/printfraginfo.c @@ -1,28 +1,40 @@ /* - * Copyright (C) 2004-2005 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: printfraginfo.c,v 1.1.2.5 2006/12/25 15:10:37 darrenr Exp $ + * $Id$ */ #include "ipf.h" #include "kmem.h" -void printfraginfo(prefix, ifr) -char *prefix; -struct ipfr *ifr; + +void +printfraginfo(prefix, ifr) + char *prefix; + struct ipfr *ifr; { frentry_t fr; + int family; + PRINTF("%s", prefix); + if (ifr->ipfr_v == 6) { + PRINTF("inet6"); + family = AF_INET6; + } else { + PRINTF("inet"); + family = AF_INET; + } fr.fr_flags = 0xffffffff; - printf("%s%s -> ", prefix, hostname(4, &ifr->ipfr_src)); + PRINTF(" %s -> ", hostname(family, &ifr->ipfr_src)); /* if (kmemcpy((char *)&fr, (u_long)ifr->ipfr_rule, sizeof(fr)) == -1) return; -*/ - printf("%s id %d ttl %ld pr %d seen0 %d ref %d tos %#02x\n", - hostname(4, &ifr->ipfr_dst), ifr->ipfr_id, ifr->ipfr_ttl, - ifr->ipfr_p, ifr->ipfr_seen0, ifr->ipfr_ref, ifr->ipfr_tos); + */ + PRINTF("%s id %x ttl %lu pr %d pkts %u bytes %u seen0 %d ref %d\n", + hostname(family, &ifr->ipfr_dst), ifr->ipfr_id, + ifr->ipfr_ttl, ifr->ipfr_p, ifr->ipfr_pkts, ifr->ipfr_bytes, + ifr->ipfr_seen0, ifr->ipfr_ref); } diff --git a/lib/printhash.c b/lib/printhash.c index 8e7948b88d897..77cde960d2080 100644 --- a/lib/printhash.c +++ b/lib/printhash.c @@ -1,20 +1,19 @@ /* - * Copyright (C) 2002-2005 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #include "ipf.h" -#define PRINTF (void)printf -#define FPRINTF (void)fprintf - -iphtable_t *printhash(hp, copyfunc, name, opts) -iphtable_t *hp; -copyfunc_t copyfunc; -char *name; -int opts; +iphtable_t * +printhash(hp, copyfunc, name, opts, fields) + iphtable_t *hp; + copyfunc_t copyfunc; + char *name; + int opts; + wordtab_t *fields; { iphtent_t *ipep, **table; iphtable_t iph; @@ -27,7 +26,8 @@ int opts; if ((name != NULL) && strncmp(name, iph.iph_name, FR_GROUPLEN)) return iph.iph_next; - printhashdata(hp, opts); + if (fields == NULL) + printhashdata(hp, opts); if ((hp->iph_flags & IPHASH_DELETE) != 0) PRINTF("# "); @@ -41,7 +41,7 @@ int opts; return NULL; for (printed = 0, ipep = iph.iph_list; ipep != NULL; ) { - ipep = printhashnode(&iph, ipep, copyfunc, opts); + ipep = printhashnode(&iph, ipep, copyfunc, opts, fields); printed++; } if (printed == 0) diff --git a/lib/printhash_live.c b/lib/printhash_live.c index 1afe63228e487..53159b1330236 100644 --- a/lib/printhash_live.c +++ b/lib/printhash_live.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -8,25 +8,25 @@ #include "ipf.h" #include "netinet/ipl.h" -#define PRINTF (void)printf -#define FPRINTF (void)fprintf - -iphtable_t *printhash_live(hp, fd, name, opts) -iphtable_t *hp; -int fd; -char *name; -int opts; +iphtable_t * +printhash_live(hp, fd, name, opts, fields) + iphtable_t *hp; + int fd; + char *name; + int opts; + wordtab_t *fields; { - iphtent_t entry, *top, *node; + iphtent_t entry, zero; ipflookupiter_t iter; - int printed, last; + int last, printed; ipfobj_t obj; if ((name != NULL) && strncmp(name, hp->iph_name, FR_GROUPLEN)) return hp->iph_next; - printhashdata(hp, opts); + if (fields == NULL) + printhashdata(hp, opts); if ((hp->iph_flags & IPHASH_DELETE) != 0) PRINTF("# "); @@ -47,26 +47,19 @@ int opts; strncpy(iter.ili_name, hp->iph_name, FR_GROUPLEN); last = 0; - top = NULL; printed = 0; + bzero((char *)&zero, sizeof(zero)); while (!last && (ioctl(fd, SIOCLOOKUPITER, &obj) == 0)) { if (entry.ipe_next == NULL) last = 1; - entry.ipe_next = top; - top = malloc(sizeof(*top)); - if (top == NULL) + if (bcmp(&zero, &entry, sizeof(zero)) == 0) break; - bcopy(&entry, top, sizeof(entry)); - } - - while (top != NULL) { - node = top; - (void) printhashnode(hp, node, bcopywrap, opts); - top = node->ipe_next; - free(node); + (void) printhashnode(hp, &entry, bcopywrap, opts, fields); printed++; } + if (last == 0) + ipferror(fd, "walking hash nodes:"); if (printed == 0) putchar(';'); diff --git a/lib/printhashdata.c b/lib/printhashdata.c index d278c365a69f7..ea2d41636e461 100644 --- a/lib/printhashdata.c +++ b/lib/printhashdata.c @@ -1,23 +1,22 @@ /* - * Copyright (C) 2002 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #include "ipf.h" +#include <ctype.h> -#define PRINTF (void)printf -#define FPRINTF (void)fprintf - -void printhashdata(hp, opts) -iphtable_t *hp; -int opts; +void +printhashdata(hp, opts) + iphtable_t *hp; + int opts; { if ((opts & OPT_DEBUG) == 0) { if ((hp->iph_type & IPHASH_ANON) == IPHASH_ANON) - PRINTF("# 'anonymous' table\n"); + PRINTF("# 'anonymous' table refs %d\n", hp->iph_ref); if ((hp->iph_flags & IPHASH_DELETE) == IPHASH_DELETE) PRINTF("# "); switch (hp->iph_type & ~IPHASH_ANON) @@ -38,10 +37,10 @@ int opts; PRINTF("%#x", hp->iph_type); break; } - PRINTF(" role = "); + PRINTF(" role="); } else { PRINTF("Hash Table %s: %s", - isdigit(*hp->iph_name) ? "Number" : "Name", + ISDIGIT(*hp->iph_name) ? "Number" : "Name", hp->iph_name); if ((hp->iph_type & IPHASH_ANON) == IPHASH_ANON) PRINTF("(anon)"); @@ -49,33 +48,16 @@ int opts; PRINTF("Role: "); } - switch (hp->iph_unit) - { - case IPL_LOGNAT : - PRINTF("nat"); - break; - case IPL_LOGIPF : - PRINTF("ipf"); - break; - case IPL_LOGAUTH : - PRINTF("auth"); - break; - case IPL_LOGCOUNT : - PRINTF("count"); - break; - default : - PRINTF("#%d", hp->iph_unit); - break; - } + printunit(hp->iph_unit); if ((opts & OPT_DEBUG) == 0) { if ((hp->iph_type & ~IPHASH_ANON) == IPHASH_LOOKUP) - PRINTF(" type = hash"); - PRINTF(" %s = %s size = %lu", - isdigit(*hp->iph_name) ? "number" : "name", + PRINTF(" type=hash"); + PRINTF(" %s=%s size=%lu", + ISDIGIT(*hp->iph_name) ? "number" : "name", hp->iph_name, (u_long)hp->iph_size); if (hp->iph_seed != 0) - PRINTF(" seed = %lu", hp->iph_seed); + PRINTF(" seed=%lu", hp->iph_seed); putchar('\n'); } else { PRINTF(" Type: "); @@ -95,7 +77,7 @@ int opts; PRINTF("\t\tSize: %lu\tSeed: %lu", (u_long)hp->iph_size, hp->iph_seed); PRINTF("\tRef. Count: %d\tMasks: %#x\n", hp->iph_ref, - hp->iph_masks); + hp->iph_maskset[0]); } if ((opts & OPT_DEBUG) != 0) { @@ -103,8 +85,8 @@ int opts; int i; for (i = 0; i < 32; i++) { - if ((1 << i) & hp->iph_masks) { - ntomask(4, i, &m.s_addr); + if ((1 << i) & hp->iph_maskset[0]) { + ntomask(AF_INET, i, &m.s_addr); PRINTF("\t\tMask: %s\n", inet_ntoa(m)); } } diff --git a/lib/printhashnode.c b/lib/printhashnode.c index 9b51af9bf9ac0..d8708c9fb19e5 100644 --- a/lib/printhashnode.c +++ b/lib/printhashnode.c @@ -1,45 +1,61 @@ /* - * Copyright (C) 2002-2005 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #include "ipf.h" -#define PRINTF (void)printf -#define FPRINTF (void)fprintf -iphtent_t *printhashnode(iph, ipep, copyfunc, opts) -iphtable_t *iph; -iphtent_t *ipep; -copyfunc_t copyfunc; -int opts; +iphtent_t * +printhashnode(iph, ipep, copyfunc, opts, fields) + iphtable_t *iph; + iphtent_t *ipep; + copyfunc_t copyfunc; + int opts; + wordtab_t *fields; { iphtent_t ipe; + u_int hv; + int i; if ((*copyfunc)(ipep, &ipe, sizeof(ipe))) return NULL; - ipe.ipe_addr.in4_addr = htonl(ipe.ipe_addr.in4_addr); - ipe.ipe_mask.in4_addr = htonl(ipe.ipe_mask.in4_addr); + hv = IPE_V4_HASH_FN(ipe.ipe_addr.i6[0], ipe.ipe_mask.i6[0], + iph->iph_size); - if ((opts & OPT_DEBUG) != 0) { - PRINTF("\tAddress: %s", + if (fields != NULL) { + for (i = 0; fields[i].w_value != 0; i++) { + printpoolfield(&ipe, IPLT_HASH, i); + if (fields[i + 1].w_value != 0) + printf("\t"); + } + printf("\n"); + } else if ((opts & OPT_DEBUG) != 0) { + PRINTF("\t%d\tAddress: %s", hv, inet_ntoa(ipe.ipe_addr.in4)); - printmask((u_32_t *)&ipe.ipe_mask.in4_addr); + printmask(ipe.ipe_family, (u_32_t *)&ipe.ipe_mask.in4_addr); PRINTF("\tRef. Count: %d\tGroup: %s\n", ipe.ipe_ref, ipe.ipe_group); +#ifdef USE_QUAD_T + PRINTF("\tHits: %"PRIu64"\tBytes: %"PRIu64"\n", + ipe.ipe_hits, ipe.ipe_bytes); +#else + PRINTF("\tHits: %lu\tBytes: %lu\n", + ipe.ipe_hits, ipe.ipe_bytes); +#endif } else { putchar(' '); - printip((u_32_t *)&ipe.ipe_addr.in4_addr); - printmask((u_32_t *)&ipe.ipe_mask.in4_addr); + printip(ipe.ipe_family, (u_32_t *)&ipe.ipe_addr.in4_addr); + printmask(ipe.ipe_family, (u_32_t *)&ipe.ipe_mask.in4_addr); if (ipe.ipe_value != 0) { switch (iph->iph_type & ~IPHASH_ANON) { case IPHASH_GROUPMAP : if (strncmp(ipe.ipe_group, iph->iph_name, FR_GROUPLEN)) - PRINTF(", group = %s", ipe.ipe_group); + PRINTF(", group=%s", ipe.ipe_group); break; } } diff --git a/lib/printhost.c b/lib/printhost.c new file mode 100644 index 0000000000000..eaf3fda458440 --- /dev/null +++ b/lib/printhost.c @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: printhost.c,v 1.3.2.2 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" + + +void +printhost(family, addr) + int family; + u_32_t *addr; +{ +#ifdef USE_INET6 + char ipbuf[64]; +#else + struct in_addr ipa; +#endif + + if ((family == -1) || !*addr) + PRINTF("any"); + else { + void *ptr = addr; + +#ifdef USE_INET6 + PRINTF("%s", inet_ntop(family, ptr, ipbuf, sizeof(ipbuf))); +#else + ipa.s_addr = *addr; + PRINTF("%s", inet_ntoa(ipa)); +#endif + } +} diff --git a/lib/printhostmap.c b/lib/printhostmap.c index 92996edfc371d..ee08318183eea 100644 --- a/lib/printhostmap.c +++ b/lib/printhostmap.c @@ -1,20 +1,29 @@ /* - * Copyright (C) 2002-2005 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: printhostmap.c,v 1.3.2.3 2006/09/30 21:42:07 darrenr Exp $ - */ + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ #include "ipf.h" -void printhostmap(hmp, hv) -hostmap_t *hmp; -u_int hv; +void +printhostmap(hmp, hv) + hostmap_t *hmp; + u_int hv; { - printf("%s,", inet_ntoa(hmp->hm_srcip)); - printf("%s -> ", inet_ntoa(hmp->hm_dstip)); - printf("%s ", inet_ntoa(hmp->hm_mapip)); - printf("(use = %d hv = %u)\n", hmp->hm_ref, hv); + printactiveaddress(hmp->hm_v, "%s", &hmp->hm_osrcip6, NULL); + putchar(','); + printactiveaddress(hmp->hm_v, "%s", &hmp->hm_odstip6, NULL); + PRINTF(" -> "); + printactiveaddress(hmp->hm_v, "%s", &hmp->hm_nsrcip6, NULL); + putchar(','); + printactiveaddress(hmp->hm_v, "%s", &hmp->hm_ndstip6, NULL); + putchar(' '); + PRINTF("(use = %d", hmp->hm_ref); + if (opts & OPT_VERBOSE) + PRINTF(" hv = %u", hv); + printf(")\n"); } diff --git a/lib/printhostmask.c b/lib/printhostmask.c index 105fb20bb56e8..f49c3914f7757 100644 --- a/lib/printhostmask.c +++ b/lib/printhostmask.c @@ -1,17 +1,18 @@ /* - * Copyright (C) 2000-2005 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: printhostmask.c,v 1.8.4.1 2006/06/16 17:21:12 darrenr Exp $ + * $Id$ */ #include "ipf.h" -void printhostmask(v, addr, mask) -int v; -u_32_t *addr, *mask; +void +printhostmask(family, addr, mask) + int family; + u_32_t *addr, *mask; { #ifdef USE_INET6 char ipbuf[64]; @@ -19,26 +20,18 @@ u_32_t *addr, *mask; struct in_addr ipa; #endif - if (!*addr && !*mask) - printf("any"); + if ((family == -1) || ((!addr || !*addr) && (!mask || !*mask))) + PRINTF("any"); else { -#ifdef USE_INET6 void *ptr = addr; - int af; - if (v == 4) { - ptr = addr; - af = AF_INET; - } else if (v == 6) { - ptr = addr; - af = AF_INET6; - } else - af = 0; - printf("%s", inet_ntop(af, ptr, ipbuf, sizeof(ipbuf))); +#ifdef USE_INET6 + PRINTF("%s", inet_ntop(family, ptr, ipbuf, sizeof(ipbuf))); #else ipa.s_addr = *addr; - printf("%s", inet_ntoa(ipa)); + PRINTF("%s", inet_ntoa(ipa)); #endif - printmask(mask); + if (mask != NULL) + printmask(family, mask); } } diff --git a/lib/printifname.c b/lib/printifname.c index 1bfe27deeb83b..720b6a8ee8095 100644 --- a/lib/printifname.c +++ b/lib/printifname.c @@ -1,18 +1,20 @@ /* - * Copyright (C) 2002 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: printifname.c,v 1.2.4.1 2006/06/16 17:21:12 darrenr Exp $ + * $Id$ */ #include "ipf.h" -void printifname(format, name, ifp) -char *format, *name; -void *ifp; + +void +printifname(format, name, ifp) + char *format, *name; + void *ifp; { - printf("%s%s", format, name); + PRINTF("%s%s", format, name); if ((ifp == NULL) && strcmp(name, "-") && strcmp(name, "*")) - printf("(!)"); + PRINTF("(!)"); } diff --git a/lib/printip.c b/lib/printip.c index fb91208e9f6b7..82c0ff4ecd780 100644 --- a/lib/printip.c +++ b/lib/printip.c @@ -1,22 +1,41 @@ /* - * Copyright (C) 2002-2005 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: printip.c,v 1.3.4.1 2006/06/16 17:21:12 darrenr Exp $ + * $Id$ */ #include "ipf.h" -void printip(addr) -u_32_t *addr; +void +printip(family, addr) + int family; + u_32_t *addr; { struct in_addr ipa; - ipa.s_addr = *addr; - if (ntohl(ipa.s_addr) < 256) - printf("%lu", (u_long)ntohl(ipa.s_addr)); + if (family == AF_INET) { + ipa.s_addr = *addr; + if (ntohl(ipa.s_addr) < 256) + PRINTF("%lu", (u_long)ntohl(ipa.s_addr)); + else + PRINTF("%s", inet_ntoa(ipa)); + } +#ifdef AF_INET6 + else if (family == AF_INET6) { + char buf[INET6_ADDRSTRLEN + 1]; + const char *str; + + buf[0] = '\0'; + str = inet_ntop(AF_INET6, addr, buf, sizeof(buf) - 1); + if (str != NULL) + PRINTF("%s", str); + else + PRINTF("???"); + } +#endif else - printf("%s", inet_ntoa(ipa)); + PRINTF("?(%d)?", family); } diff --git a/lib/printipfexpr.c b/lib/printipfexpr.c new file mode 100644 index 0000000000000..64c2f1c1a7e86 --- /dev/null +++ b/lib/printipfexpr.c @@ -0,0 +1,197 @@ +#include "ipf.h" + +static void printport __P((int *)); +static void printhosts __P((int *)); +static void printsingle __P((int *)); +static void printhostsv6 __P((int *)); + +void +printipfexpr(array) + int *array; +{ + int i, nelems, j, not; + ipfexp_t *ipfe; + + nelems = array[0]; + + for (i = 1; i < nelems; ) { + ipfe = (ipfexp_t *)(array + i); + if (ipfe->ipfe_cmd == IPF_EXP_END) + break; + + not = ipfe->ipfe_not; + + switch (ipfe->ipfe_cmd) + { + case IPF_EXP_IP_ADDR : + PRINTF("ip.addr %s= ", not ? "!" : ""); + printhosts(array + i); + break; + + case IPF_EXP_IP_PR : + PRINTF("ip.p %s= ", not ? "!" : ""); + printsingle(array + i); + break; + + case IPF_EXP_IP_SRCADDR : + PRINTF("ip.src %s= ", not ? "!" : ""); + printhosts(array + i); + break; + + case IPF_EXP_IP_DSTADDR : + PRINTF("ip.dst %s= ", not ? "!" : ""); + printhosts(array + i); + break; + + case IPF_EXP_TCP_PORT : + PRINTF("tcp.port %s= ", not ? "!" : ""); + printport(array + i); + break; + + case IPF_EXP_TCP_DPORT : + PRINTF("tcp.dport %s= ", not ? "!" : ""); + printport(array + i); + break; + + case IPF_EXP_TCP_SPORT : + PRINTF("tcp.sport %s= ", not ? "!" : ""); + printport(array + i); + break; + + case IPF_EXP_TCP_FLAGS : + PRINTF("tcp.flags %s= ", not ? "!" : ""); + + for (j = 0; j < ipfe->ipfe_narg; ) { + printtcpflags(array[i + 4], array[i + 5]); + j += 2; + if (j < array[4]) + putchar(','); + } + break; + + case IPF_EXP_UDP_PORT : + PRINTF("udp.port %s= ", not ? "!" : ""); + printport(array + i); + break; + + case IPF_EXP_UDP_DPORT : + PRINTF("udp.dport %s= ", not ? "!" : ""); + printport(array + i); + break; + + case IPF_EXP_UDP_SPORT : + PRINTF("udp.sport %s= ", not ? "!" : ""); + printport(array + i); + break; + + case IPF_EXP_IDLE_GT : + PRINTF("idle-gt %s= ", not ? "!" : ""); + printsingle(array + i); + break; + + case IPF_EXP_TCP_STATE : + PRINTF("tcp-state %s= ", not ? "!" : ""); + printsingle(array + i); + break; + +#ifdef USE_INET6 + case IPF_EXP_IP6_ADDR : + PRINTF("ip6.addr %s= ", not ? "!" : ""); + printhostsv6(array + i); + break; + + case IPF_EXP_IP6_SRCADDR : + PRINTF("ip6.src %s= ", not ? "!" : ""); + printhostsv6(array + i); + break; + + case IPF_EXP_IP6_DSTADDR : + PRINTF("ip6.dst %s= ", not ? "!" : ""); + printhostsv6(array + i); + break; +#endif + + case IPF_EXP_END : + break; + + default : + PRINTF("#%#x,len=%d;", + ipfe->ipfe_cmd, ipfe->ipfe_narg); + } + + if (array[i] != IPF_EXP_END) + putchar(';'); + + i += ipfe->ipfe_size; + if (array[i] != IPF_EXP_END) + putchar(' '); + } +} + + +static void +printsingle(array) + int *array; +{ + ipfexp_t *ipfe = (ipfexp_t *)array; + int i; + + for (i = 0; i < ipfe->ipfe_narg; ) { + PRINTF("%d", array[i + 4]); + i++; + if (i < ipfe->ipfe_narg) + putchar(','); + } +} + + +static void +printport(array) + int *array; +{ + ipfexp_t *ipfe = (ipfexp_t *)array; + int i; + + for (i = 0; i < ipfe->ipfe_narg; ) { + PRINTF("%d", ntohs(array[i + 4])); + i++; + if (i < ipfe->ipfe_narg) + putchar(','); + } +} + + +static void +printhosts(array) + int *array; +{ + ipfexp_t *ipfe = (ipfexp_t *)array; + int i, j; + + for (i = 0, j = 0; i < ipfe->ipfe_narg; j++) { + printhostmask(AF_INET, (u_32_t *)ipfe->ipfe_arg0 + j * 2, + (u_32_t *)ipfe->ipfe_arg0 + j * 2 + 1); + i += 2; + if (i < ipfe->ipfe_narg) + putchar(','); + } +} + + +#ifdef USE_INET6 +static void +printhostsv6(array) + int *array; +{ + ipfexp_t *ipfe = (ipfexp_t *)array; + int i, j; + + for (i = 4, j= 0; i < ipfe->ipfe_size; j++) { + printhostmask(AF_INET6, (u_32_t *)ipfe->ipfe_arg0 + j * 8, + (u_32_t *)ipfe->ipfe_arg0 + j * 8 + 4); + i += 8; + if (i < ipfe->ipfe_size) + putchar(','); + } +} +#endif diff --git a/lib/printiphdr.c b/lib/printiphdr.c new file mode 100644 index 0000000000000..fdf0f75f90795 --- /dev/null +++ b/lib/printiphdr.c @@ -0,0 +1,20 @@ +/* + * Copyright (C) by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: printiphdr.c,v 1.1 2009/03/01 12:48:32 darren_r Exp $ + */ + +#include "ipf.h" + + +void +printiphdr(ip) + ip_t *ip; +{ + PRINTF("ip(v=%d,hl=%d,len=%d,tos=%#x,off=%#x,sum=%#x,src=%#x,dst=%#x", + ip->ip_v, ip->ip_hl, ntohs(ip->ip_len), ip->ip_tos, + ntohs(ip->ip_off), ntohs(ip->ip_sum), ntohl(ip->ip_src.s_addr), + ntohl(ip->ip_dst.s_addr)); +} diff --git a/lib/printlog.c b/lib/printlog.c index 192c6717e100c..6e61a271b009c 100644 --- a/lib/printlog.c +++ b/lib/printlog.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2000-2005 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: printlog.c,v 1.6.4.3 2006/06/16 17:21:12 darrenr Exp $ + * $Id$ */ #include "ipf.h" @@ -11,26 +11,27 @@ #include <syslog.h> -void printlog(fp) -frentry_t *fp; +void +printlog(fp) + frentry_t *fp; { char *s, *u; - printf("log"); + PRINTF("log"); if (fp->fr_flags & FR_LOGBODY) - printf(" body"); + PRINTF(" body"); if (fp->fr_flags & FR_LOGFIRST) - printf(" first"); + PRINTF(" first"); if (fp->fr_flags & FR_LOGORBLOCK) - printf(" or-block"); + PRINTF(" or-block"); if (fp->fr_loglevel != 0xffff) { - printf(" level "); + PRINTF(" level "); s = fac_toname(fp->fr_loglevel); if (s == NULL || *s == '\0') s = "!!!"; u = pri_toname(fp->fr_loglevel); if (u == NULL || *u == '\0') u = "!!!"; - printf("%s.%s", s, u); + PRINTF("%s.%s", s, u); } } diff --git a/lib/printlookup.c b/lib/printlookup.c new file mode 100644 index 0000000000000..51f8d6e3b2df7 --- /dev/null +++ b/lib/printlookup.c @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + + +void +printlookup(base, addr, mask) + char *base; + i6addr_t *addr, *mask; +{ + char name[32]; + + switch (addr->iplookuptype) + { + case IPLT_POOL : + PRINTF("pool/"); + break; + case IPLT_HASH : + PRINTF("hash/"); + break; + case IPLT_DSTLIST : + PRINTF("dstlist/"); + break; + default : + PRINTF("lookup(%x)=", addr->iplookuptype); + break; + } + + if (addr->iplookupsubtype == 0) + PRINTF("%u", addr->iplookupnum); + else if (addr->iplookupsubtype == 1) { + strncpy(name, base + addr->iplookupname, sizeof(name)); + name[sizeof(name) - 1] = '\0'; + PRINTF("%s", name); + } +} diff --git a/lib/printmask.c b/lib/printmask.c index 27b3e6cbbf6eb..fb805f588a65f 100644 --- a/lib/printmask.c +++ b/lib/printmask.c @@ -1,28 +1,28 @@ /* - * Copyright (C) 2000-2005 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: printmask.c,v 1.5.4.1 2006/06/16 17:21:13 darrenr Exp $ + * $Id$ */ #include "ipf.h" -void printmask(mask) -u_32_t *mask; +void +printmask(family, mask) + int family; + u_32_t *mask; { struct in_addr ipa; int ones; -#ifdef USE_INET6 - if (use_inet6) - printf("/%d", count6bits(mask)); - else -#endif - if ((ones = count4bits(*mask)) == -1) { + if (family == AF_INET6) { + PRINTF("/%d", count6bits(mask)); + } else if ((ones = count4bits(*mask)) == -1) { ipa.s_addr = *mask; - printf("/%s", inet_ntoa(ipa)); - } else - printf("/%d", ones); + PRINTF("/%s", inet_ntoa(ipa)); + } else { + PRINTF("/%d", ones); + } } diff --git a/lib/printnat.c b/lib/printnat.c index 37666a2a8d58c..a017c3fd75344 100644 --- a/lib/printnat.c +++ b/lib/printnat.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2005 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * @@ -11,228 +11,339 @@ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: printnat.c,v 1.22.2.14 2007/09/06 16:40:11 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif + /* * Print out a NAT rule */ -void printnat(np, opts) -ipnat_t *np; -int opts; +void +printnat(np, opts) + ipnat_t *np; + int opts; { - struct protoent *pr; - int bits; + struct protoent *pr; + char *base; + int family; + int proto; + + if (np->in_v[0] == 4) + family = AF_INET; +#ifdef USE_INET6 + else if (np->in_v[0] == 6) + family = AF_INET6; +#endif + else + family = AF_UNSPEC; - pr = getprotobynumber(np->in_p); + if (np->in_flags & IPN_NO) + PRINTF("no "); switch (np->in_redir) { + case NAT_REDIRECT|NAT_ENCAP : + PRINTF("encap in on"); + proto = np->in_pr[0]; + break; + case NAT_MAP|NAT_ENCAP : + PRINTF("encap out on"); + proto = np->in_pr[1]; + break; + case NAT_REDIRECT|NAT_DIVERTUDP : + PRINTF("divert in on"); + proto = np->in_pr[0]; + break; + case NAT_MAP|NAT_DIVERTUDP : + PRINTF("divert out on"); + proto = np->in_pr[1]; + break; + case NAT_REDIRECT|NAT_REWRITE : + PRINTF("rewrite in on"); + proto = np->in_pr[0]; + break; + case NAT_MAP|NAT_REWRITE : + PRINTF("rewrite out on"); + proto = np->in_pr[1]; + break; case NAT_REDIRECT : - printf("rdr"); + PRINTF("rdr"); + proto = np->in_pr[0]; break; case NAT_MAP : - printf("map"); + PRINTF("map"); + proto = np->in_pr[1]; break; case NAT_MAPBLK : - printf("map-block"); + PRINTF("map-block"); + proto = np->in_pr[1]; break; case NAT_BIMAP : - printf("bimap"); + PRINTF("bimap"); + proto = np->in_pr[0]; break; default : - fprintf(stderr, "unknown value for in_redir: %#x\n", + FPRINTF(stderr, "unknown value for in_redir: %#x\n", np->in_redir); + proto = np->in_pr[0]; break; } - if (!strcmp(np->in_ifnames[0], "-")) - printf(" \"%s\"", np->in_ifnames[0]); + pr = getprotobynumber(proto); + + base = np->in_names; + if (!strcmp(base + np->in_ifnames[0], "-")) + PRINTF(" \"%s\"", base + np->in_ifnames[0]); else - printf(" %s", np->in_ifnames[0]); - if ((np->in_ifnames[1][0] != '\0') && - (strncmp(np->in_ifnames[0], np->in_ifnames[1], LIFNAMSIZ) != 0)) { - if (!strcmp(np->in_ifnames[1], "-")) - printf(",\"%s\"", np->in_ifnames[1]); + PRINTF(" %s", base + np->in_ifnames[0]); + if ((np->in_ifnames[1] != -1) && + (strcmp(base + np->in_ifnames[0], base + np->in_ifnames[1]) != 0)) { + if (!strcmp(base + np->in_ifnames[1], "-")) + PRINTF(",\"%s\"", base + np->in_ifnames[1]); else - printf(",%s", np->in_ifnames[1]); + PRINTF(",%s", base + np->in_ifnames[1]); } putchar(' '); + if (family == AF_INET6) + PRINTF("inet6 "); + + if (np->in_redir & (NAT_REWRITE|NAT_ENCAP|NAT_DIVERTUDP)) { + if ((proto != 0) || (np->in_flags & IPN_TCPUDP)) { + PRINTF("proto "); + printproto(pr, proto, np); + putchar(' '); + } + } + if (np->in_flags & IPN_FILTER) { if (np->in_flags & IPN_NOTSRC) - printf("! "); - printf("from "); - if (np->in_redir == NAT_REDIRECT) { - printhostmask(4, (u_32_t *)&np->in_srcip, - (u_32_t *)&np->in_srcmsk); - } else { - printhostmask(4, (u_32_t *)&np->in_inip, - (u_32_t *)&np->in_inmsk); - } + PRINTF("! "); + PRINTF("from "); + printnataddr(np->in_v[0], np->in_names, &np->in_osrc, + np->in_ifnames[0]); if (np->in_scmp) - printportcmp(np->in_p, &np->in_tuc.ftu_src); + printportcmp(proto, &np->in_tuc.ftu_src); if (np->in_flags & IPN_NOTDST) - printf(" !"); - printf(" to "); - if (np->in_redir == NAT_REDIRECT) { - printhostmask(4, (u_32_t *)&np->in_outip, - (u_32_t *)&np->in_outmsk); - } else { - printhostmask(4, (u_32_t *)&np->in_srcip, - (u_32_t *)&np->in_srcmsk); - } + PRINTF(" !"); + PRINTF(" to "); + printnataddr(np->in_v[0], np->in_names, &np->in_odst, + np->in_ifnames[0]); if (np->in_dcmp) - printportcmp(np->in_p, &np->in_tuc.ftu_dst); + printportcmp(proto, &np->in_tuc.ftu_dst); } - if (np->in_redir == NAT_REDIRECT) { - if (!(np->in_flags & IPN_FILTER)) { - printf("%s", inet_ntoa(np->in_out[0].in4)); - bits = count4bits(np->in_outmsk); - if (bits != -1) - printf("/%d", bits); + if (np->in_redir & (NAT_ENCAP|NAT_DIVERTUDP)) { + PRINTF(" -> src "); + printnataddr(np->in_v[1], np->in_names, &np->in_nsrc, + np->in_ifnames[0]); + if ((np->in_redir & NAT_DIVERTUDP) != 0) + PRINTF(",%u", np->in_spmin); + PRINTF(" dst "); + printnataddr(np->in_v[1], np->in_names, &np->in_ndst, + np->in_ifnames[0]); + if ((np->in_redir & NAT_DIVERTUDP) != 0) + PRINTF(",%u udp", np->in_dpmin); + if ((np->in_flags & IPN_PURGE) != 0) + PRINTF(" purge"); + PRINTF(";\n"); + + } else if (np->in_redir & NAT_REWRITE) { + PRINTF(" -> src "); + if (np->in_nsrc.na_type == IPLT_DSTLIST) { + PRINTF("dstlist/"); + if (np->in_nsrc.na_subtype == 0) + PRINTF("%d", np->in_nsrc.na_num); else - printf("/%s", inet_ntoa(np->in_out[1].in4)); + PRINTF("%s", base + np->in_nsrc.na_num); + } else { + printnataddr(np->in_v[1], np->in_names, &np->in_nsrc, + np->in_ifnames[0]); + } + if ((((np->in_flags & IPN_TCPUDP) != 0)) && + (np->in_spmin != 0)) { + if ((np->in_flags & IPN_FIXEDSPORT) != 0) { + PRINTF(",port = %u", np->in_spmin); + } else { + PRINTF(",%u", np->in_spmin); + if (np->in_spmax != np->in_spmin) + PRINTF("-%u", np->in_spmax); + } + } + PRINTF(" dst "); + if (np->in_ndst.na_type == IPLT_DSTLIST) { + PRINTF("dstlist/"); + if (np->in_ndst.na_subtype == 0) + PRINTF("%d", np->in_nsrc.na_num); + else + PRINTF("%s", base + np->in_ndst.na_num); + } else { + printnataddr(np->in_v[1], np->in_names, &np->in_ndst, + np->in_ifnames[0]); + } + if ((((np->in_flags & IPN_TCPUDP) != 0)) && + (np->in_dpmin != 0)) { + if ((np->in_flags & IPN_FIXEDDPORT) != 0) { + PRINTF(",port = %u", np->in_dpmin); + } else { + PRINTF(",%u", np->in_dpmin); + if (np->in_dpmax != np->in_dpmin) + PRINTF("-%u", np->in_dpmax); + } + } + if ((np->in_flags & IPN_PURGE) != 0) + PRINTF(" purge"); + PRINTF(";\n"); + + } else if (np->in_redir == NAT_REDIRECT) { + if (!(np->in_flags & IPN_FILTER)) { + printnataddr(np->in_v[0], np->in_names, &np->in_odst, + np->in_ifnames[0]); if (np->in_flags & IPN_TCPUDP) { - printf(" port %d", ntohs(np->in_pmin)); - if (np->in_pmax != np->in_pmin) - printf("-%d", ntohs(np->in_pmax)); + PRINTF(" port %d", np->in_odport); + if (np->in_odport != np->in_dtop) + PRINTF("-%d", np->in_dtop); } } - printf(" -> %s", inet_ntoa(np->in_in[0].in4)); - if (np->in_flags & IPN_SPLIT) - printf(",%s", inet_ntoa(np->in_in[1].in4)); - else if (np->in_inmsk == 0 && np->in_inip == 0) - printf("/0"); + if (np->in_flags & IPN_NO) { + putchar(' '); + printproto(pr, proto, np); + PRINTF(";\n"); + return; + } + PRINTF(" -> "); + printnataddr(np->in_v[1], np->in_names, &np->in_ndst, + np->in_ifnames[0]); if (np->in_flags & IPN_TCPUDP) { if ((np->in_flags & IPN_FIXEDDPORT) != 0) - printf(" port = %d", ntohs(np->in_pnext)); - else - printf(" port %d", ntohs(np->in_pnext)); + PRINTF(" port = %d", np->in_dpmin); + else { + PRINTF(" port %d", np->in_dpmin); + if (np->in_dpmin != np->in_dpmax) + PRINTF("-%d", np->in_dpmax); + } } putchar(' '); - printproto(pr, np->in_p, np); + printproto(pr, proto, np); if (np->in_flags & IPN_ROUNDR) - printf(" round-robin"); + PRINTF(" round-robin"); if (np->in_flags & IPN_FRAG) - printf(" frag"); + PRINTF(" frag"); if (np->in_age[0] != 0 || np->in_age[1] != 0) { - printf(" age %d/%d", np->in_age[0], np->in_age[1]); + PRINTF(" age %d/%d", np->in_age[0], np->in_age[1]); } if (np->in_flags & IPN_STICKY) - printf(" sticky"); + PRINTF(" sticky"); if (np->in_mssclamp != 0) - printf(" mssclamp %d", np->in_mssclamp); - if (*np->in_plabel != '\0') - printf(" proxy %.*s", (int)sizeof(np->in_plabel), - np->in_plabel); + PRINTF(" mssclamp %d", np->in_mssclamp); + if (np->in_plabel != -1) + PRINTF(" proxy %s", np->in_names + np->in_plabel); if (np->in_tag.ipt_tag[0] != '\0') - printf(" tag %-.*s", IPFTAG_LEN, np->in_tag.ipt_tag); - printf("\n"); + PRINTF(" tag %-.*s", IPFTAG_LEN, np->in_tag.ipt_tag); + if ((np->in_flags & IPN_PURGE) != 0) + PRINTF(" purge"); + PRINTF("\n"); if (opts & OPT_DEBUG) - printf("\tpmax %u\n", np->in_pmax); + PRINTF("\tpmax %u\n", np->in_dpmax); + } else { int protoprinted = 0; if (!(np->in_flags & IPN_FILTER)) { - printf("%s/", inet_ntoa(np->in_in[0].in4)); - bits = count4bits(np->in_inmsk); - if (bits != -1) - printf("%d", bits); - else - printf("%s", inet_ntoa(np->in_in[1].in4)); + printnataddr(np->in_v[0], np->in_names, &np->in_osrc, + np->in_ifnames[0]); } - printf(" -> "); - if (np->in_flags & IPN_IPRANGE) { - printf("range %s-", inet_ntoa(np->in_out[0].in4)); - printf("%s", inet_ntoa(np->in_out[1].in4)); + if (np->in_flags & IPN_NO) { + putchar(' '); + printproto(pr, proto, np); + PRINTF(";\n"); + return; + } + PRINTF(" -> "); + if (np->in_flags & IPN_SIPRANGE) { + PRINTF("range "); + printnataddr(np->in_v[1], np->in_names, &np->in_nsrc, + np->in_ifnames[0]); } else { - printf("%s/", inet_ntoa(np->in_out[0].in4)); - bits = count4bits(np->in_outmsk); - if (bits != -1) - printf("%d", bits); - else - printf("%s", inet_ntoa(np->in_out[1].in4)); + printnataddr(np->in_v[1], np->in_names, &np->in_nsrc, + np->in_ifnames[0]); } - if (*np->in_plabel != '\0') { - printf(" proxy port "); - if (np->in_dcmp != 0) - np->in_dport = htons(np->in_dport); - if (np->in_dport != 0) { + if (np->in_plabel != -1) { + PRINTF(" proxy port "); + if (np->in_odport != 0) { char *s; - s = portname(np->in_p, ntohs(np->in_dport)); + s = portname(proto, np->in_odport); if (s != NULL) fputs(s, stdout); else fputs("???", stdout); } - printf(" %.*s/", (int)sizeof(np->in_plabel), - np->in_plabel); - printproto(pr, np->in_p, NULL); + PRINTF(" %s/", np->in_names + np->in_plabel); + printproto(pr, proto, NULL); protoprinted = 1; } else if (np->in_redir == NAT_MAPBLK) { - if ((np->in_pmin == 0) && + if ((np->in_spmin == 0) && (np->in_flags & IPN_AUTOPORTMAP)) - printf(" ports auto"); + PRINTF(" ports auto"); else - printf(" ports %d", np->in_pmin); + PRINTF(" ports %d", np->in_spmin); if (opts & OPT_DEBUG) - printf("\n\tip modulous %d", np->in_pmax); - } else if (np->in_pmin || np->in_pmax) { + PRINTF("\n\tip modulous %d", np->in_spmax); + + } else if (np->in_spmin || np->in_spmax) { if (np->in_flags & IPN_ICMPQUERY) { - printf(" icmpidmap "); + PRINTF(" icmpidmap "); } else { - printf(" portmap "); + PRINTF(" portmap "); } - printproto(pr, np->in_p, np); + printproto(pr, proto, np); protoprinted = 1; if (np->in_flags & IPN_AUTOPORTMAP) { - printf(" auto"); + PRINTF(" auto"); if (opts & OPT_DEBUG) - printf(" [%d:%d %d %d]", - ntohs(np->in_pmin), - ntohs(np->in_pmax), + PRINTF(" [%d:%d %d %d]", + np->in_spmin, np->in_spmax, np->in_ippip, np->in_ppip); } else { - printf(" %d:%d", ntohs(np->in_pmin), - ntohs(np->in_pmax)); + PRINTF(" %d:%d", np->in_spmin, np->in_spmax); } + if (np->in_flags & IPN_SEQUENTIAL) + PRINTF(" sequential"); } if (np->in_flags & IPN_FRAG) - printf(" frag"); + PRINTF(" frag"); if (np->in_age[0] != 0 || np->in_age[1] != 0) { - printf(" age %d/%d", np->in_age[0], np->in_age[1]); + PRINTF(" age %d/%d", np->in_age[0], np->in_age[1]); } if (np->in_mssclamp != 0) - printf(" mssclamp %d", np->in_mssclamp); + PRINTF(" mssclamp %d", np->in_mssclamp); if (np->in_tag.ipt_tag[0] != '\0') - printf(" tag %s", np->in_tag.ipt_tag); - if (!protoprinted && (np->in_flags & IPN_TCPUDP || np->in_p)) { + PRINTF(" tag %s", np->in_tag.ipt_tag); + if (!protoprinted && (np->in_flags & IPN_TCPUDP || proto)) { putchar(' '); - printproto(pr, np->in_p, np); + printproto(pr, proto, np); } - printf("\n"); + if ((np->in_flags & IPN_PURGE) != 0) + PRINTF(" purge"); + PRINTF("\n"); if (opts & OPT_DEBUG) { - struct in_addr nip; - - nip.s_addr = htonl(np->in_nextip.s_addr); - - printf("\tnextip %s pnext %d\n", - inet_ntoa(nip), np->in_pnext); + PRINTF("\tnextip "); + printip(family, &np->in_snip); + PRINTF(" pnext %d\n", np->in_spnext); } } if (opts & OPT_DEBUG) { - printf("\tspace %lu use %u hits %lu flags %#x proto %d hv %d\n", + PRINTF("\tspace %lu use %u hits %lu flags %#x proto %d/%d", np->in_space, np->in_use, np->in_hits, - np->in_flags, np->in_p, np->in_hv); - printf("\tifp[0] %p ifp[1] %p apr %p\n", + np->in_flags, np->in_pr[0], np->in_pr[1]); + PRINTF(" hv %u/%u\n", np->in_hv[0], np->in_hv[1]); + PRINTF("\tifp[0] %p ifp[1] %p apr %p\n", np->in_ifps[0], np->in_ifps[1], np->in_apr); - printf("\ttqehead %p/%p comment %p\n", + PRINTF("\ttqehead %p/%p comment %p\n", np->in_tqehead[0], np->in_tqehead[1], np->in_comment); } } diff --git a/lib/printnataddr.c b/lib/printnataddr.c new file mode 100644 index 0000000000000..89faa624193c7 --- /dev/null +++ b/lib/printnataddr.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com) + */ + +#include "ipf.h" +#include "kmem.h" + + +#if !defined(lint) +static const char rcsid[] = "@(#)$Id: printnataddr.c,v 1.4.2.2 2012/07/22 08:04:24 darren_r Exp $"; +#endif + + +void +printnataddr(v, base, addr, ifidx) + int v; + char *base; + nat_addr_t *addr; + int ifidx; +{ + switch (v) + { + case 4 : + if (addr->na_atype == FRI_NORMAL && + addr->na_addr[0].in4.s_addr == 0) { + PRINTF("0/%d", count4bits(addr->na_addr[1].in4.s_addr)); + } else { + printaddr(AF_INET, addr->na_atype, base, ifidx, + (u_32_t *)&addr->na_addr[0].in4.s_addr, + (u_32_t *)&addr->na_addr[1].in4.s_addr); + } + break; +#ifdef USE_INET6 + case 6 : + printaddr(AF_INET6, addr->na_atype, base, ifidx, + (u_32_t *)&addr->na_addr[0].in6, + (u_32_t *)&addr->na_addr[1].in6); + break; +#endif + default : + printf("{v=%d}", v); + break; + } +} diff --git a/lib/printnatfield.c b/lib/printnatfield.c new file mode 100644 index 0000000000000..49596f6071706 --- /dev/null +++ b/lib/printnatfield.c @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: printnatfield.c,v 1.6.2.2 2012/01/26 05:44:26 darren_r Exp $ + */ + +#include "ipf.h" + +wordtab_t natfields[] = { + { "all", -2 }, + { "ifp0", 1 }, + { "ifp1", 2 }, + { "mtu0", 3 }, + { "mtu1", 4 }, + { "ifname0", 5 }, + { "ifname1", 6 }, + { "sumd0", 7 }, + { "sumd1", 8 }, + { "pkts0", 9 }, + { "pkts1", 10 }, + { "bytes0", 11 }, + { "bytes1", 12 }, + { "proto0", 13 }, + { "proto1", 14 }, + { "hash0", 15 }, + { "hash1", 16 }, + { "ref", 17 }, + { "rev", 18 }, + { "v0", 19 }, + { "redir", 20 }, + { "use", 21 }, + { "ipsumd", 22 }, + { "dir", 23 }, + { "olddstip", 24 }, + { "oldsrcip", 25 }, + { "newdstip", 26 }, + { "newsrcip", 27 }, + { "olddport", 28 }, + { "oldsport", 29 }, + { "newdport", 30 }, + { "newsport", 31 }, + { "age", 32 }, + { "v1", 33 }, + { NULL, 0 } +}; + + +void +printnatfield(n, fieldnum) + nat_t *n; + int fieldnum; +{ + int i; + + switch (fieldnum) + { + case -2 : + for (i = 1; natfields[i].w_word != NULL; i++) { + if (natfields[i].w_value > 0) { + printnatfield(n, i); + if (natfields[i + 1].w_value > 0) + putchar('\t'); + } + } + break; + + case 1: + PRINTF("%#lx", (u_long)n->nat_ifps[0]); + break; + + case 2: + PRINTF("%#lx", (u_long)n->nat_ifps[1]); + break; + + case 3: + PRINTF("%d", n->nat_mtu[0]); + break; + + case 4: + PRINTF("%d", n->nat_mtu[1]); + break; + + case 5: + PRINTF("%s", n->nat_ifnames[0]); + break; + + case 6: + PRINTF("%s", n->nat_ifnames[1]); + break; + + case 7: + PRINTF("%d", n->nat_sumd[0]); + break; + + case 8: + PRINTF("%d", n->nat_sumd[1]); + break; + + case 9: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", n->nat_pkts[0]); +#else + PRINTF("%lu", n->nat_pkts[0]); +#endif + break; + + case 10: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", n->nat_pkts[1]); +#else + PRINTF("%lu", n->nat_pkts[1]); +#endif + break; + + case 11: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", n->nat_bytes[0]); +#else + PRINTF("%lu", n->nat_bytes[0]); +#endif + break; + + case 12: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", n->nat_bytes[1]); +#else + PRINTF("%lu", n->nat_bytes[1]); +#endif + break; + + case 13: + PRINTF("%d", n->nat_pr[0]); + break; + + case 14: + PRINTF("%d", n->nat_pr[1]); + break; + + case 15: + PRINTF("%u", n->nat_hv[0]); + break; + + case 16: + PRINTF("%u", n->nat_hv[1]); + break; + + case 17: + PRINTF("%d", n->nat_ref); + break; + + case 18: + PRINTF("%d", n->nat_rev); + break; + + case 19: + PRINTF("%d", n->nat_v[0]); + break; + + case 33: + PRINTF("%d", n->nat_v[0]); + break; + + case 20: + PRINTF("%d", n->nat_redir); + break; + + case 21: + PRINTF("%d", n->nat_use); + break; + + case 22: + PRINTF("%u", n->nat_ipsumd); + break; + + case 23: + PRINTF("%d", n->nat_dir); + break; + + case 24: + PRINTF("%s", hostname(n->nat_v[0], &n->nat_odstip)); + break; + + case 25: + PRINTF("%s", hostname(n->nat_v[0], &n->nat_osrcip)); + break; + + case 26: + PRINTF("%s", hostname(n->nat_v[1], &n->nat_ndstip)); + break; + + case 27: + PRINTF("%s", hostname(n->nat_v[1], &n->nat_nsrcip)); + break; + + case 28: + PRINTF("%hu", ntohs(n->nat_odport)); + break; + + case 29: + PRINTF("%hu", ntohs(n->nat_osport)); + break; + + case 30: + PRINTF("%hu", ntohs(n->nat_ndport)); + break; + + case 31: + PRINTF("%hu", ntohs(n->nat_nsport)); + break; + + case 32: + PRINTF("%u", n->nat_age); + break; + + default: + break; + } +} diff --git a/lib/printnatside.c b/lib/printnatside.c new file mode 100644 index 0000000000000..37e1cb8d1e3ad --- /dev/null +++ b/lib/printnatside.c @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: printnatside.c,v 1.2.2.6 2012/07/22 08:04:24 darren_r Exp $ + */ +#include "ipf.h" + +void +printnatside(side, ns) + char *side; + nat_stat_side_t *ns; +{ + PRINTF("%lu\tproxy create fail %s\n", ns->ns_appr_fail, side); + PRINTF("%lu\tproxy fail %s\n", ns->ns_ipf_proxy_fail, side); + PRINTF("%lu\tbad nat %s\n", ns->ns_badnat, side); + PRINTF("%lu\tbad nat new %s\n", ns->ns_badnatnew, side); + PRINTF("%lu\tbad next addr %s\n", ns->ns_badnextaddr, side); + PRINTF("%lu\tbucket max %s\n", ns->ns_bucket_max, side); + PRINTF("%lu\tclone nomem %s\n", ns->ns_clone_nomem, side); + PRINTF("%lu\tdecap bad %s\n", ns->ns_decap_bad, side); + PRINTF("%lu\tdecap fail %s\n", ns->ns_decap_fail, side); + PRINTF("%lu\tdecap pullup %s\n", ns->ns_decap_pullup, side); + PRINTF("%lu\tdivert dup %s\n", ns->ns_divert_dup, side); + PRINTF("%lu\tdivert exist %s\n", ns->ns_divert_exist, side); + PRINTF("%lu\tdrop %s\n", ns->ns_drop, side); + PRINTF("%lu\texhausted %s\n", ns->ns_exhausted, side); + PRINTF("%lu\ticmp address %s\n", ns->ns_icmp_address, side); + PRINTF("%lu\ticmp basic %s\n", ns->ns_icmp_basic, side); + PRINTF("%lu\tinuse %s\n", ns->ns_inuse, side); + PRINTF("%lu\ticmp mbuf wrong size %s\n", ns->ns_icmp_mbuf, side); + PRINTF("%lu\ticmp header unmatched %s\n", ns->ns_icmp_notfound, side); + PRINTF("%lu\ticmp rebuild failures %s\n", ns->ns_icmp_rebuild, side); + PRINTF("%lu\ticmp short %s\n", ns->ns_icmp_short, side); + PRINTF("%lu\ticmp packet size wrong %s\n", ns->ns_icmp_size, side); + PRINTF("%lu\tIFP address fetch failures %s\n", + ns->ns_ifpaddrfail, side); + PRINTF("%lu\tpackets untranslated %s\n", ns->ns_ignored, side); + PRINTF("%lu\tNAT insert failures %s\n", ns->ns_insert_fail, side); + PRINTF("%lu\tNAT lookup misses %s\n", ns->ns_lookup_miss, side); + PRINTF("%lu\tNAT lookup nowild %s\n", ns->ns_lookup_nowild, side); + PRINTF("%lu\tnew ifpaddr failed %s\n", ns->ns_new_ifpaddr, side); + PRINTF("%lu\tmemory requests failed %s\n", ns->ns_memfail, side); + PRINTF("%lu\ttable max reached %s\n", ns->ns_table_max, side); + PRINTF("%lu\tpackets translated %s\n", ns->ns_translated, side); + PRINTF("%lu\tfinalised failed %s\n", ns->ns_unfinalised, side); + PRINTF("%lu\tsearch wraps %s\n", ns->ns_wrap, side); + PRINTF("%lu\tnull translations %s\n", ns->ns_xlate_null, side); + PRINTF("%lu\ttranslation exists %s\n", ns->ns_xlate_exists, side); + PRINTF("%lu\tno memory %s\n", ns->ns_memfail, side); + + if (opts & OPT_VERBOSE) + PRINTF("%p table %s\n", ns->ns_table, side); +} diff --git a/lib/printpacket.c b/lib/printpacket.c index 6ee36792b4193..e77b75cf21bd6 100644 --- a/lib/printpacket.c +++ b/lib/printpacket.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2000-2005 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: printpacket.c,v 1.12.4.5 2007/09/09 22:15:30 darrenr Exp $ + * $Id$ */ #include "ipf.h" @@ -13,32 +13,43 @@ #endif -void printpacket(ip) -struct ip *ip; +void +printpacket(dir, m) + int dir; + mb_t *m; { - struct tcphdr *tcp; - u_short len; - u_short off; + u_short len, off; + tcphdr_t *tcp; + ip_t *ip; + + ip = MTOD(m, ip_t *); if (IP_V(ip) == 6) { - off = 0; - len = ntohs(((u_short *)ip)[2]) + 40; +#ifdef USE_INET6 + len = ntohs(((ip6_t *)ip)->ip6_plen); +#else + len = ntohs(((u_short *)ip)[2]); +#endif + len += 40; } else { - off = ntohs(ip->ip_off); len = ntohs(ip->ip_len); } + ASSERT(len == msgdsize(m)); if ((opts & OPT_HEX) == OPT_HEX) { u_char *s; int i; - for (s = (u_char *)ip, i = 0; i < len; i++) { - printf("%02x", *s++ & 0xff); - if (len - i > 1) { - i++; - printf("%02x", *s++ & 0xff); + for (; m != NULL; m = m->mb_next) { + len = m->mb_len; + for (s = (u_char *)m->mb_data, i = 0; i < len; i++) { + PRINTF("%02x", *s++ & 0xff); + if (len - i > 1) { + i++; + PRINTF("%02x", *s++ & 0xff); + } + putchar(' '); } - putchar(' '); } putchar('\n'); putchar('\n'); @@ -46,24 +57,32 @@ struct ip *ip; } if (IP_V(ip) == 6) { - printpacket6(ip); + printpacket6(dir, m); return; } + if (dir) + PRINTF("> "); + else + PRINTF("< "); + + PRINTF("%s ", IFNAME(m->mb_ifp)); + + off = ntohs(ip->ip_off); tcp = (struct tcphdr *)((char *)ip + (IP_HL(ip) << 2)); - printf("ip #%d %d(%d) %d", ntohs(ip->ip_id), ntohs(ip->ip_len), + PRINTF("ip #%d %d(%d) %d", ntohs(ip->ip_id), ntohs(ip->ip_len), IP_HL(ip) << 2, ip->ip_p); if (off & IP_OFFMASK) - printf(" @%d", (off & IP_OFFMASK) << 3); - printf(" %s", inet_ntoa(ip->ip_src)); + PRINTF(" @%d", off << 3); + PRINTF(" %s", inet_ntoa(ip->ip_src)); if (!(off & IP_OFFMASK)) if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) - printf(",%d", ntohs(tcp->th_sport)); - printf(" > "); - printf("%s", inet_ntoa(ip->ip_dst)); + PRINTF(",%d", ntohs(tcp->th_sport)); + PRINTF(" > "); + PRINTF("%s", inet_ntoa(ip->ip_dst)); if (!(off & IP_OFFMASK)) { if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) - printf(",%d", ntohs(tcp->th_dport)); + PRINTF(",%d", ntohs(tcp->th_dport)); if ((ip->ip_p == IPPROTO_TCP) && (tcp->th_flags != 0)) { putchar(' '); if (tcp->th_flags & TH_FIN) diff --git a/lib/printpacket6.c b/lib/printpacket6.c index 16c807de647ec..c5537114be9a2 100644 --- a/lib/printpacket6.c +++ b/lib/printpacket6.c @@ -1,10 +1,10 @@ /* - * Copyright (C) 2002 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: printpacket6.c,v 1.3.4.1 2006/06/16 17:21:13 darrenr Exp $ - */ + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ #include "ipf.h" @@ -12,15 +12,17 @@ * This is meant to work without the IPv6 header files being present or * the inet_ntop() library. */ -void printpacket6(ip) -struct ip *ip; +void +printpacket6(dir, m) + int dir; + mb_t *m; { u_char *buf, p; u_short plen, *addrs; tcphdr_t *tcp; u_32_t flow; - buf = (u_char *)ip; + buf = (u_char *)m->mb_data; tcp = (tcphdr_t *)(buf + 40); p = buf[6]; flow = ntohl(*(u_32_t *)buf); @@ -28,22 +30,29 @@ struct ip *ip; plen = ntohs(*((u_short *)buf +2)); addrs = (u_short *)buf + 4; - printf("ip6/%d %d %#x %d", buf[0] & 0xf, plen, flow, p); - printf(" %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + if (dir) + PRINTF("> "); + else + PRINTF("< "); + + PRINTF("%s ", IFNAME(m->mb_ifp)); + + PRINTF("ip6/%d %d %#x %d", buf[0] & 0xf, plen, flow, p); + PRINTF(" %x:%x:%x:%x:%x:%x:%x:%x", ntohs(addrs[0]), ntohs(addrs[1]), ntohs(addrs[2]), ntohs(addrs[3]), ntohs(addrs[4]), ntohs(addrs[5]), ntohs(addrs[6]), ntohs(addrs[7])); if (plen >= 4) if (p == IPPROTO_TCP || p == IPPROTO_UDP) - (void)printf(",%d", ntohs(tcp->th_sport)); - printf(" >"); + (void)PRINTF(",%d", ntohs(tcp->th_sport)); + PRINTF(" >"); addrs += 8; - printf(" %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + PRINTF(" %x:%x:%x:%x:%x:%x:%x:%x", ntohs(addrs[0]), ntohs(addrs[1]), ntohs(addrs[2]), ntohs(addrs[3]), ntohs(addrs[4]), ntohs(addrs[5]), ntohs(addrs[6]), ntohs(addrs[7])); if (plen >= 4) if (p == IPPROTO_TCP || p == IPPROTO_UDP) - (void)printf(",%d", ntohs(tcp->th_dport)); + PRINTF(",%d", ntohs(tcp->th_dport)); putchar('\n'); } diff --git a/lib/printpool.c b/lib/printpool.c index cfb1e785a003e..02bb15bc1fe28 100644 --- a/lib/printpool.c +++ b/lib/printpool.c @@ -1,21 +1,21 @@ /* - * Copyright (C) 2002-2005 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #include "ipf.h" -#define PRINTF (void)printf -#define FPRINTF (void)fprintf -ip_pool_t *printpool(pp, copyfunc, name, opts) -ip_pool_t *pp; -copyfunc_t copyfunc; -char *name; -int opts; +ip_pool_t * +printpool(pp, copyfunc, name, opts, fields) + ip_pool_t *pp; + copyfunc_t copyfunc; + char *name; + int opts; + wordtab_t *fields; { - ip_pool_node_t *ipnp, *ipnpn, ipn; + ip_pool_node_t *ipnp, *ipnpn, ipn, **pnext; ip_pool_t ipp; if ((*copyfunc)(pp, &ipp, sizeof(ipp))) @@ -33,19 +33,22 @@ int opts; ipnpn = ipp.ipo_list; ipp.ipo_list = NULL; + pnext = &ipp.ipo_list; while (ipnpn != NULL) { ipnp = (ip_pool_node_t *)malloc(sizeof(*ipnp)); (*copyfunc)(ipnpn, ipnp, sizeof(ipn)); ipnpn = ipnp->ipn_next; - ipnp->ipn_next = ipp.ipo_list; - ipp.ipo_list = ipnp; + *pnext = ipnp; + pnext = &ipnp->ipn_next; + ipnp->ipn_next = NULL; } if (ipp.ipo_list == NULL) { putchar(';'); } else { - for (ipnp = ipp.ipo_list; ipnp != NULL; ) { - ipnp = printpoolnode(ipnp, opts); + for (ipnp = ipp.ipo_list; ipnp != NULL; ipnp = ipnpn) { + ipnpn = printpoolnode(ipnp, opts, fields); + free(ipnp); if ((opts & OPT_DEBUG) == 0) { putchar(';'); diff --git a/lib/printpool_live.c b/lib/printpool_live.c index e228a3965adbd..2aabf32bc14a2 100644 --- a/lib/printpool_live.c +++ b/lib/printpool_live.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -8,17 +8,16 @@ #include "ipf.h" #include "netinet/ipl.h" -#define PRINTF (void)printf -#define FPRINTF (void)fprintf - -ip_pool_t *printpool_live(pool, fd, name, opts) -ip_pool_t *pool; -int fd; -char *name; -int opts; +ip_pool_t * +printpool_live(pool, fd, name, opts, fields) + ip_pool_t *pool; + int fd; + char *name; + int opts; + wordtab_t *fields; { - ip_pool_node_t entry, *top, *node; + ip_pool_node_t entry; ipflookupiter_t iter; int printed, last; ipfobj_t obj; @@ -26,7 +25,8 @@ int opts; if ((name != NULL) && strncmp(name, pool->ipo_name, FR_GROUPLEN)) return pool->ipo_next; - printpooldata(pool, opts); + if (fields == NULL) + printpooldata(pool, opts); if ((pool->ipo_flags & IPOOL_DELETE) != 0) PRINTF("# "); @@ -46,28 +46,17 @@ int opts; strncpy(iter.ili_name, pool->ipo_name, FR_GROUPLEN); last = 0; - top = NULL; printed = 0; - while (!last && (ioctl(fd, SIOCLOOKUPITER, &obj) == 0)) { - if (entry.ipn_next == NULL) - last = 1; - node = malloc(sizeof(*top)); - if (node == NULL) - break; - bcopy(&entry, node, sizeof(entry)); - node->ipn_next = top; - top = node; - } - - while (top != NULL) { - node = top; - (void) printpoolnode(node, opts); - if ((opts & OPT_DEBUG) == 0) - putchar(';'); - top = node->ipn_next; - free(node); - printed++; + if (pool->ipo_list != NULL) { + while (!last && (ioctl(fd, SIOCLOOKUPITER, &obj) == 0)) { + if (entry.ipn_next == NULL) + last = 1; + (void) printpoolnode(&entry, opts, fields); + if ((opts & OPT_DEBUG) == 0) + putchar(';'); + printed++; + } } if (printed == 0) @@ -76,8 +65,7 @@ int opts; if ((opts & OPT_DEBUG) == 0) PRINTF(" };\n"); - if (ioctl(fd, SIOCIPFDELTOK, &iter.ili_key) != 0) - perror("SIOCIPFDELTOK"); + (void) ioctl(fd,SIOCIPFDELTOK, &iter.ili_key); return pool->ipo_next; } diff --git a/lib/printpooldata.c b/lib/printpooldata.c index 8d8e962cbbdec..a1591774b4df2 100644 --- a/lib/printpooldata.c +++ b/lib/printpooldata.c @@ -1,17 +1,17 @@ /* - * Copyright (C) 2002 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #include "ipf.h" +#include <ctype.h> -#define PRINTF (void)printf -#define FPRINTF (void)fprintf -void printpooldata(pool, opts) -ip_pool_t *pool; -int opts; +void +printpooldata(pool, opts) + ip_pool_t *pool; + int opts; { if ((opts & OPT_DEBUG) == 0) { @@ -19,12 +19,12 @@ int opts; PRINTF("# 'anonymous' tree %s\n", pool->ipo_name); if ((pool->ipo_flags & IPOOL_DELETE) != 0) PRINTF("# "); - PRINTF("table role = "); + PRINTF("table role="); } else { if ((pool->ipo_flags & IPOOL_DELETE) != 0) PRINTF("# "); PRINTF("%s: %s", - isdigit(*pool->ipo_name) ? "Number" : "Name", + ISDIGIT(*pool->ipo_name) ? "Number" : "Name", pool->ipo_name); if ((pool->ipo_flags & IPOOL_ANON) == IPOOL_ANON) PRINTF("(anon)"); @@ -32,40 +32,12 @@ int opts; PRINTF("Role: "); } - switch (pool->ipo_unit) - { - case IPL_LOGIPF : - printf("ipf"); - break; - case IPL_LOGNAT : - printf("nat"); - break; - case IPL_LOGSTATE : - printf("state"); - break; - case IPL_LOGAUTH : - printf("auth"); - break; - case IPL_LOGSYNC : - printf("sync"); - break; - case IPL_LOGSCAN : - printf("scan"); - break; - case IPL_LOGLOOKUP : - printf("lookup"); - break; - case IPL_LOGCOUNT : - printf("count"); - break; - default : - printf("unknown(%d)", pool->ipo_unit); - } + printunit(pool->ipo_unit); if ((opts & OPT_DEBUG) == 0) { - PRINTF(" type = tree %s = %s\n", - isdigit(*pool->ipo_name) ? "number" : "name", - pool->ipo_name); + PRINTF(" type=tree %s=%s\n", + (!*pool->ipo_name || ISDIGIT(*pool->ipo_name)) ? \ + "number" : "name", pool->ipo_name); } else { putchar(' '); diff --git a/lib/printpoolfield.c b/lib/printpoolfield.c new file mode 100644 index 0000000000000..9254ab8446159 --- /dev/null +++ b/lib/printpoolfield.c @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: printpoolfield.c,v 1.1.2.4 2012/01/26 05:44:26 darren_r Exp $ + */ + +#include "ipf.h" + +wordtab_t poolfields[] = { + { "all", -2 }, + { "address", 1 }, + { "mask", 2 }, + { "ifname", 3 }, + { "pkts", 4 }, + { "bytes", 5 }, + { "family", 6 }, + { NULL, 0 } +}; + + +void +printpoolfield(p, ptype, fieldnum) + void *p; + int ptype; + int fieldnum; +{ + addrfamily_t *a; + char abuf[80]; + int i; + + switch (fieldnum) + { + case -2 : + for (i = 1; poolfields[i].w_word != NULL; i++) { + if (poolfields[i].w_value > 0) { + printpoolfield(p, ptype, i); + if (poolfields[i + 1].w_value > 0) + putchar('\t'); + } + } + break; + + case 1: + if (ptype == IPLT_POOL) { + ip_pool_node_t *node = (ip_pool_node_t *)p; + + if (node->ipn_info) + PRINTF("!"); + a = &node->ipn_addr; + PRINTF("%s", inet_ntop(a->adf_family, &a->adf_addr, + abuf, sizeof(abuf))); + } else if (ptype == IPLT_HASH) { + iphtent_t *node = (iphtent_t *)p; + + PRINTF("%s", inet_ntop(node->ipe_family, + &node->ipe_addr, + abuf, sizeof(abuf))); + } else if (ptype == IPLT_DSTLIST) { + ipf_dstnode_t *node = (ipf_dstnode_t *)p; + + a = &node->ipfd_dest.fd_addr; + PRINTF("%s", inet_ntop(a->adf_family, &a->adf_addr, + abuf, sizeof(abuf))); + } + break; + + case 2: + if (ptype == IPLT_POOL) { + ip_pool_node_t *node = (ip_pool_node_t *)p; + + a = &node->ipn_mask; + PRINTF("%s", inet_ntop(a->adf_family, &a->adf_addr, + abuf, sizeof(abuf))); + } else if (ptype == IPLT_HASH) { + iphtent_t *node = (iphtent_t *)p; + + PRINTF("%s", inet_ntop(node->ipe_family, + &node->ipe_mask, + abuf, sizeof(abuf))); + } else if (ptype == IPLT_DSTLIST) { + PRINTF("%s", ""); + } + break; + + case 3: + if (ptype == IPLT_POOL) { + PRINTF("%s", ""); + } else if (ptype == IPLT_HASH) { + PRINTF("%s", ""); + } else if (ptype == IPLT_DSTLIST) { + ipf_dstnode_t *node = (ipf_dstnode_t *)p; + + if (node->ipfd_dest.fd_name == -1) { + PRINTF("%s", ""); + } else { + PRINTF("%s", node->ipfd_names + + node->ipfd_dest.fd_name); + } + } + break; + + case 4: + if (ptype == IPLT_POOL) { + ip_pool_node_t *node = (ip_pool_node_t *)p; + +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", node->ipn_hits); +#else + PRINTF("%lu", node->ipn_hits); +#endif + } else if (ptype == IPLT_HASH) { + iphtent_t *node = (iphtent_t *)p; + +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", node->ipe_hits); +#else + PRINTF("%lu", node->ipe_hits); +#endif + } else if (ptype == IPLT_DSTLIST) { + printf("0"); + } + break; + + case 5: + if (ptype == IPLT_POOL) { + ip_pool_node_t *node = (ip_pool_node_t *)p; + +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", node->ipn_bytes); +#else + PRINTF("%lu", node->ipn_bytes); +#endif + } else if (ptype == IPLT_HASH) { + iphtent_t *node = (iphtent_t *)p; + +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", node->ipe_bytes); +#else + PRINTF("%lu", node->ipe_bytes); +#endif + } else if (ptype == IPLT_DSTLIST) { + printf("0"); + } + break; + + case 6: + if (ptype == IPLT_POOL) { + ip_pool_node_t *node = (ip_pool_node_t *)p; + + PRINTF("%s", familyname(node->ipn_addr.adf_family)); + } else if (ptype == IPLT_HASH) { + iphtent_t *node = (iphtent_t *)p; + + PRINTF("%s", familyname(node->ipe_family)); + } else if (ptype == IPLT_DSTLIST) { + ipf_dstnode_t *node = (ipf_dstnode_t *)p; + + a = &node->ipfd_dest.fd_addr; + PRINTF("%s", familyname(a->adf_family)); + } + break; + + default : + break; + } +} diff --git a/lib/printpoolnode.c b/lib/printpoolnode.c index a53ee3306512a..a03068c8adef0 100644 --- a/lib/printpoolnode.c +++ b/lib/printpoolnode.c @@ -1,31 +1,49 @@ /* - * Copyright (C) 2002-2005 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #include "ipf.h" -#define PRINTF (void)printf -#define FPRINTF (void)fprintf -ip_pool_node_t *printpoolnode(np, opts) -ip_pool_node_t *np; -int opts; +ip_pool_node_t * +printpoolnode(np, opts, fields) + ip_pool_node_t *np; + int opts; + wordtab_t *fields; { + int i; - if ((opts & OPT_DEBUG) == 0) { + if (fields != NULL) { + for (i = 0; fields[i].w_value != 0; i++) { + printpoolfield(np, IPLT_POOL, i); + if (fields[i + 1].w_value != 0) + printf("\t"); + } + printf("\n"); + } else if ((opts & OPT_DEBUG) == 0) { putchar(' '); if (np->ipn_info == 1) PRINTF("! "); - printip((u_32_t *)&np->ipn_addr.adf_addr.in4); - printmask((u_32_t *)&np->ipn_mask.adf_addr); + printip(np->ipn_addr.adf_family, + (u_32_t *)&np->ipn_addr.adf_addr.in4); + printmask(np->ipn_addr.adf_family, + (u_32_t *)&np->ipn_mask.adf_addr); } else { PRINTF("\tAddress: %s%s", np->ipn_info ? "! " : "", inet_ntoa(np->ipn_addr.adf_addr.in4)); - printmask((u_32_t *)&np->ipn_mask.adf_addr); - PRINTF("\t\tHits %lu\tName %s\tRef %d\n", - np->ipn_hits, np->ipn_name, np->ipn_ref); + printmask(np->ipn_addr.adf_family, + (u_32_t *)&np->ipn_mask.adf_addr); +#ifdef USE_QUAD_T + PRINTF("\n\t\tHits %"PRIu64"\tBytes %"PRIu64"\tName %s\tRef %d\n", + np->ipn_hits, np->ipn_bytes, + np->ipn_name, np->ipn_ref); +#else + PRINTF("\n\t\tHits %lu\tBytes %lu\tName %s\tRef %d\n", + np->ipn_hits, np->ipn_bytes, + np->ipn_name, np->ipn_ref); +#endif } return np->ipn_next; } diff --git a/lib/printportcmp.c b/lib/printportcmp.c index a8203874c49f7..94280ee5a5bf5 100644 --- a/lib/printportcmp.c +++ b/lib/printportcmp.c @@ -1,27 +1,28 @@ /* - * Copyright (C) 2000-2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: printportcmp.c,v 1.7.4.1 2006/06/16 17:21:14 darrenr Exp $ + * $Id$ */ #include "ipf.h" -void printportcmp(pr, frp) -int pr; -frpcmp_t *frp; +void +printportcmp(pr, frp) + int pr; + frpcmp_t *frp; { static char *pcmp1[] = { "*", "=", "!=", "<", ">", "<=", ">=", "<>", "><", ":" }; if (frp->frp_cmp == FR_INRANGE || frp->frp_cmp == FR_OUTRANGE) - printf(" port %d %s %d", frp->frp_port, + PRINTF(" port %d %s %d", frp->frp_port, pcmp1[frp->frp_cmp], frp->frp_top); else if (frp->frp_cmp == FR_INCRANGE) - printf(" port %d:%d", frp->frp_port, frp->frp_top); + PRINTF(" port %d:%d", frp->frp_port, frp->frp_top); else - printf(" port %s %s", pcmp1[frp->frp_cmp], + PRINTF(" port %s %s", pcmp1[frp->frp_cmp], portname(pr, frp->frp_port)); } diff --git a/lib/printproto.c b/lib/printproto.c index e65ec11608260..d411bfa004211 100644 --- a/lib/printproto.c +++ b/lib/printproto.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -8,44 +8,48 @@ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: printproto.c,v 1.1.2.2 2006/06/16 17:21:14 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif -void printproto(pr, p, np) -struct protoent *pr; -int p; -ipnat_t *np; +void +printproto(pr, p, np) + struct protoent *pr; + int p; + ipnat_t *np; { if (np != NULL) { if ((np->in_flags & IPN_TCPUDP) == IPN_TCPUDP) - printf("tcp/udp"); + PRINTF("tcp/udp"); else if (np->in_flags & IPN_TCP) - printf("tcp"); + PRINTF("tcp"); else if (np->in_flags & IPN_UDP) - printf("udp"); + PRINTF("udp"); else if (np->in_flags & IPN_ICMPQUERY) - printf("icmp"); + PRINTF("icmp"); #ifdef _AIX51 /* * To make up for "ip = 252" and "hopopt = 0" in /etc/protocols + * The IANA has doubled up on the definition of 0 - it is now + * also used for IPv6 hop-opts, so we can no longer rely on + * /etc/protocols providing the correct name->number mapping. */ - else if (np->in_p == 0) - printf("ip"); #endif + else if (np->in_pr[0] == 0) + PRINTF("ip"); else if (pr != NULL) - printf("%s", pr->p_name); + PRINTF("%s", pr->p_name); else - printf("%d", np->in_p); + PRINTF("%d", np->in_pr[0]); } else { #ifdef _AIX51 if (p == 0) - printf("ip"); + PRINTF("ip"); else #endif if (pr != NULL) - printf("%s", pr->p_name); + PRINTF("%s", pr->p_name); else - printf("%d", p); + PRINTF("%d", p); } } diff --git a/lib/printsbuf.c b/lib/printsbuf.c index 81f5e0b06750c..c56578717b5cf 100644 --- a/lib/printsbuf.c +++ b/lib/printsbuf.c @@ -1,10 +1,10 @@ /* - * Copyright (C) 2002-2004 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: printsbuf.c,v 1.2.4.2 2006/06/16 17:21:14 darrenr Exp $ - */ + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ #ifdef IPFILTER_SCAN @@ -13,8 +13,9 @@ #include "ipf.h" #include "netinet/ip_scan.h" -void printsbuf(buf) -char *buf; +void +printsbuf(buf) + char *buf; { u_char *s; int i; @@ -23,8 +24,15 @@ char *buf; if (ISPRINT(*s)) putchar(*s); else - printf("\\%o", *s); + PRINTF("\\%o", *s); } } +#else +void printsbuf(char *buf); +void printsbuf(buf) + char *buf; +{ + buf = buf; /* gcc -Wextra */ +} #endif diff --git a/lib/printstate.c b/lib/printstate.c index fcf42d675b4db..edf86de9f2984 100644 --- a/lib/printstate.c +++ b/lib/printstate.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2005 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -7,75 +7,102 @@ #include "ipf.h" #include "kmem.h" -#define PRINTF (void)printf -#define FPRINTF (void)fprintf -ipstate_t *printstate(sp, opts, now) -ipstate_t *sp; -int opts; -u_long now; +ipstate_t * +printstate(sp, opts, now) + ipstate_t *sp; + int opts; + u_long now; { + struct protoent *pr; synclist_t ipsync; + if ((opts & OPT_NORESOLVE) == 0) + pr = getprotobynumber(sp->is_p); + else + pr = NULL; + + PRINTF("%d:", sp->is_v); + if (pr != NULL) + PRINTF("%s", pr->p_name); + else + PRINTF("%d", sp->is_p); + + PRINTF(" src:%s", hostname(sp->is_family, &sp->is_src.in4)); + if (sp->is_p == IPPROTO_UDP || sp->is_p == IPPROTO_TCP) { + if (sp->is_flags & IS_WSPORT) + PRINTF(",*"); + else + PRINTF(",%d", ntohs(sp->is_sport)); + } + + PRINTF(" dst:%s", hostname(sp->is_family, &sp->is_dst.in4)); + if (sp->is_p == IPPROTO_UDP || sp->is_p == IPPROTO_TCP) { + if (sp->is_flags & IS_WDPORT) + PRINTF(",*"); + else + PRINTF(",%d", ntohs(sp->is_dport)); + } + + if (sp->is_p == IPPROTO_TCP) { + PRINTF(" state:%d/%d", sp->is_state[0], sp->is_state[1]); + } + + PRINTF(" %ld", sp->is_die - now); if (sp->is_phnext == NULL) - PRINTF("ORPHAN "); - PRINTF("%s -> ", hostname(sp->is_v, &sp->is_src.in4)); - PRINTF("%s pass %#x pr %d state %d/%d", - hostname(sp->is_v, &sp->is_dst.in4), sp->is_pass, sp->is_p, - sp->is_state[0], sp->is_state[1]); - if (opts & OPT_DEBUG) - PRINTF(" bkt %d ref %d", sp->is_hv, sp->is_ref); - PRINTF("\n\ttag %u ttl %lu", sp->is_tag, sp->is_die - now); + PRINTF(" ORPHAN"); + if (sp->is_flags & IS_CLONE) + PRINTF(" CLONE"); + putchar('\n'); if (sp->is_p == IPPROTO_TCP) { - PRINTF("\n\t%hu -> %hu %x:%x %hu<<%d:%hu<<%d\n", - ntohs(sp->is_sport), ntohs(sp->is_dport), + PRINTF("\t%x:%x %hu<<%d:%hu<<%d\n", sp->is_send, sp->is_dend, sp->is_maxswin, sp->is_swinscale, sp->is_maxdwin, sp->is_dwinscale); - PRINTF("\tcmsk %04x smsk %04x s0 %08x/%08x\n", - sp->is_smsk[0], sp->is_smsk[1], - sp->is_s0[0], sp->is_s0[1]); - PRINTF("\tFWD:ISN inc %x sumd %x\n", - sp->is_isninc[0], sp->is_sumd[0]); - PRINTF("\tREV:ISN inc %x sumd %x\n", - sp->is_isninc[1], sp->is_sumd[1]); + if ((opts & OPT_VERBOSE) != 0) { + PRINTF("\tcmsk %04x smsk %04x isc %p s0 %08x/%08x\n", + sp->is_smsk[0], sp->is_smsk[1], sp->is_isc, + sp->is_s0[0], sp->is_s0[1]); + PRINTF("\tFWD: ISN inc %x sumd %x\n", + sp->is_isninc[0], sp->is_sumd[0]); + PRINTF("\tREV: ISN inc %x sumd %x\n", + sp->is_isninc[1], sp->is_sumd[1]); #ifdef IPFILTER_SCAN - PRINTF("\tsbuf[0] ["); - printsbuf(sp->is_sbuf[0]); - PRINTF("] sbuf[1] ["); - printsbuf(sp->is_sbuf[1]); - PRINTF("]\n"); + PRINTF("\tsbuf[0] ["); + printsbuf(sp->is_sbuf[0]); + PRINTF("] sbuf[1] ["); + printsbuf(sp->is_sbuf[1]); + PRINTF("]\n"); #endif - } else if (sp->is_p == IPPROTO_UDP) { - PRINTF(" %hu -> %hu\n", ntohs(sp->is_sport), - ntohs(sp->is_dport)); + } } else if (sp->is_p == IPPROTO_GRE) { - PRINTF(" call %hx/%hx\n", ntohs(sp->is_gre.gs_call[0]), + PRINTF("\tcall %hx/%hx\n", ntohs(sp->is_gre.gs_call[0]), ntohs(sp->is_gre.gs_call[1])); } else if (sp->is_p == IPPROTO_ICMP #ifdef USE_INET6 || sp->is_p == IPPROTO_ICMPV6 #endif - ) - PRINTF(" id %hu seq %hu type %d\n", sp->is_icmp.ici_id, + ) { + PRINTF("\tid %hu seq %hu type %d\n", sp->is_icmp.ici_id, sp->is_icmp.ici_seq, sp->is_icmp.ici_type); + } #ifdef USE_QUAD_T - PRINTF("\tforward: pkts in %qd bytes in %qd pkts out %qd bytes out %qd\n\tbackward: pkts in %qd bytes in %qd pkts out %qd bytes out %qd\n", + PRINTF("\tFWD: IN pkts %"PRIu64" bytes %"PRIu64" OUT pkts %"PRIu64" bytes %"PRIu64"\n\tREV: IN pkts %"PRIu64" bytes %"PRIu64" OUT pkts %"PRIu64" bytes %"PRIu64"\n", sp->is_pkts[0], sp->is_bytes[0], sp->is_pkts[1], sp->is_bytes[1], sp->is_pkts[2], sp->is_bytes[2], sp->is_pkts[3], sp->is_bytes[3]); #else - PRINTF("\tforward: pkts in %ld bytes in %ld pkts out %ld bytes out %ld\n\tbackward: pkts in %ld bytes in %ld pkts out %ld bytes out %ld\n", + PRINTF("\tFWD: IN pkts %lu bytes %lu OUT pkts %lu bytes %lu\n\tREV: IN pkts %lu bytes %lu OUT pkts %lu bytes %lu\n", sp->is_pkts[0], sp->is_bytes[0], sp->is_pkts[1], sp->is_bytes[1], sp->is_pkts[2], sp->is_bytes[2], sp->is_pkts[3], sp->is_bytes[3]); #endif - PRINTF("\t"); + PRINTF("\ttag %u pass %#x = ", sp->is_tag, sp->is_pass); /* * Print out bits set in the result code for the state being @@ -133,22 +160,31 @@ u_long now; /* a given; no? */ if (sp->is_pass & FR_KEEPSTATE) { PRINTF(" keep state"); - if (sp->is_pass & FR_STATESYNC) - PRINTF(" ( sync )"); + if (sp->is_pass & (FR_STATESYNC|FR_STSTRICT|FR_STLOOSE)) { + PRINTF(" ("); + if (sp->is_pass & FR_STATESYNC) + PRINTF(" sync"); + if (sp->is_pass & FR_STSTRICT) + PRINTF(" strict"); + if (sp->is_pass & FR_STLOOSE) + PRINTF(" loose"); + PRINTF(" )"); + } } - PRINTF("\tIPv%d", sp->is_v); PRINTF("\n"); - PRINTF("\tpkt_flags & %x(%x) = %x,\t", - sp->is_flags & 0xf, sp->is_flags, - sp->is_flags >> 4); - PRINTF("\tpkt_options & %x = %x, %x = %x \n", sp->is_optmsk[0], - sp->is_opt[0], sp->is_optmsk[1], sp->is_opt[1]); - PRINTF("\tpkt_security & %x = %x, pkt_auth & %x = %x\n", - sp->is_secmsk, sp->is_sec, sp->is_authmsk, - sp->is_auth); - PRINTF("\tis_flx %#x %#x %#x %#x\n", sp->is_flx[0][0], sp->is_flx[0][1], - sp->is_flx[1][0], sp->is_flx[1][1]); + if ((opts & OPT_VERBOSE) != 0) { + PRINTF("\tref %d", sp->is_ref); + PRINTF(" pkt_flags & %x(%x) = %x\n", + sp->is_flags & 0xf, sp->is_flags, sp->is_flags >> 4); + PRINTF("\tpkt_options & %x = %x, %x = %x \n", sp->is_optmsk[0], + sp->is_opt[0], sp->is_optmsk[1], sp->is_opt[1]); + PRINTF("\tpkt_security & %x = %x, pkt_auth & %x = %x\n", + sp->is_secmsk, sp->is_sec, sp->is_authmsk, + sp->is_auth); + PRINTF("\tis_flx %#x %#x %#x %#x\n", sp->is_flx[0][0], + sp->is_flx[0][1], sp->is_flx[1][0], sp->is_flx[1][1]); + } PRINTF("\tinterfaces: in %s[%s", getifname(sp->is_ifp[0]), sp->is_ifname[0]); if (opts & OPT_DEBUG) @@ -167,20 +203,19 @@ u_long now; PRINTF("/%p", sp->is_ifp[3]); PRINTF("]\n"); + PRINTF("\tSync status: "); if (sp->is_sync != NULL) { - - if (kmemcpy((char *)&ipsync, (u_long)sp->is_sync, sizeof(ipsync))) { - - PRINTF("\tSync status: status could not be retrieved\n"); + if (kmemcpy((char *)&ipsync, (u_long)sp->is_sync, + sizeof(ipsync))) { + PRINTF("status could not be retrieved\n"); return NULL; } - PRINTF("\tSync status: idx %d num %d v %d pr %d rev %d\n", + PRINTF("idx %d num %d v %d pr %d rev %d\n", ipsync.sl_idx, ipsync.sl_num, ipsync.sl_v, ipsync.sl_p, ipsync.sl_rev); - } else { - PRINTF("\tSync status: not synchronized\n"); + PRINTF("not synchronized\n"); } return sp->is_next; diff --git a/lib/printstatefields.c b/lib/printstatefields.c new file mode 100644 index 0000000000000..5632d8416c472 --- /dev/null +++ b/lib/printstatefields.c @@ -0,0 +1,358 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: printstatefields.c,v 1.4.2.2 2012/01/26 05:44:26 darren_r Exp $ + */ + +#include "ipf.h" + +wordtab_t statefields[] = { + { "all", -2 }, + { "ifp0", 1 }, + { "ifp1", 2 }, + { "ifp2", 3 }, + { "ifp3", 4 }, + { "ifname0", 5 }, + { "ifname1", 6 }, + { "ifname2", 7 }, + { "ifname3", 8 }, + { "pkts0", 9 }, + { "pkts1", 10 }, + { "pkts2", 11 }, + { "pkts3", 12 }, + { "bytes0", 13 }, + { "bytes1", 14 }, + { "bytes2", 15 }, + { "bytes3", 16 }, + { "state0", 17 }, + { "state1", 18 }, + { "age0", 19 }, + { "age1", 20 }, + { "ref", 21 }, + { "isn0", 22 }, + { "isn1", 23 }, + { "sumd0", 24 }, + { "sumd1", 25 }, + { "src", 26 }, + { "dst", 27 }, + { "sport", 28 }, + { "dport", 29 }, + { "icmptype", 30 }, + { "-", 31 }, + { "pass", 32 }, + { "proto", 33 }, + { "version", 34 }, + { "hash", 35 }, + { "tag", 36 }, + { "flags", 37 }, + { "rulen", 38 }, + { "group", 39 }, + { "flx0", 40 }, + { "flx1", 41 }, + { "flx2", 42 }, + { "flx3", 43 }, + { "opt0", 44 }, + { "opt1", 45 }, + { "optmsk0", 46 }, + { "optmsk1", 47 }, + { "sec", 48 }, + { "secmsk", 49 }, + { "auth", 50 }, + { "authmsk", 51 }, + { "icmppkts0", 52 }, + { "icmppkts1", 53 }, + { "icmppkts2", 54 }, + { "icmppkts3", 55 }, + { NULL, 0 } +}; + + +void +printstatefield(sp, fieldnum) + ipstate_t *sp; + int fieldnum; +{ + int i; + + switch (fieldnum) + { + case -2 : + for (i = 1; statefields[i].w_word != NULL; i++) { + if (statefields[i].w_value > 0) { + printstatefield(sp, i); + if (statefields[i + 1].w_value > 0) + putchar('\t'); + } + } + break; + + case 1: + PRINTF("%#lx", (u_long)sp->is_ifp[0]); + break; + + case 2: + PRINTF("%#lx", (u_long)sp->is_ifp[1]); + break; + + case 3: + PRINTF("%#lx", (u_long)sp->is_ifp[2]); + break; + + case 4: + PRINTF("%#lx", (u_long)sp->is_ifp[3]); + break; + + case 5: + PRINTF("%s", sp->is_ifname[0]); + break; + + case 6: + PRINTF("%s", sp->is_ifname[1]); + break; + + case 7: + PRINTF("%s", sp->is_ifname[2]); + break; + + case 8: + PRINTF("%s", sp->is_ifname[3]); + break; + + case 9: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", sp->is_pkts[0]); +#else + PRINTF("%lu", sp->is_pkts[0]); +#endif + break; + + case 10: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", sp->is_pkts[1]); +#else + PRINTF("%lu", sp->is_pkts[1]); +#endif + break; + + case 11: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", sp->is_pkts[2]); +#else + PRINTF("%lu", sp->is_pkts[2]); +#endif + break; + + case 12: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", sp->is_pkts[3]); +#else + PRINTF("%lu", sp->is_pkts[3]); +#endif + break; + + case 13: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", sp->is_bytes[0]); +#else + PRINTF("%lu", sp->is_bytes[0]); +#endif + break; + + case 14: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", sp->is_bytes[1]); +#else + PRINTF("%lu", sp->is_bytes[1]); +#endif + break; + + case 15: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", sp->is_bytes[2]); +#else + PRINTF("%lu", sp->is_bytes[2]); +#endif + break; + + case 16: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", sp->is_bytes[3]); +#else + PRINTF("%lu", sp->is_bytes[3]); +#endif + break; + + case 17: + PRINTF("%d", sp->is_state[0]); + break; + + case 18: + PRINTF("%d", sp->is_state[1]); + break; + + case 19: + PRINTF("%d", sp->is_frage[0]); + break; + + case 20: + PRINTF("%d", sp->is_frage[1]); + break; + + case 21: + PRINTF("%d", sp->is_ref); + break; + + case 22: + PRINTF("%d", sp->is_isninc[0]); + break; + + case 23: + PRINTF("%d", sp->is_isninc[1]); + break; + + case 24: + PRINTF("%hd", sp->is_sumd[0]); + break; + + case 25: + PRINTF("%hd", sp->is_sumd[1]); + break; + + case 26: + PRINTF("%s", hostname(sp->is_v, &sp->is_src.in4)); + break; + + case 27: + PRINTF("%s", hostname(sp->is_v, &sp->is_dst.in4)); + break; + + case 28: + PRINTF("%hu", ntohs(sp->is_sport)); + break; + + case 29: + PRINTF("%hu", ntohs(sp->is_dport)); + break; + + case 30: + PRINTF("%d", sp->is_type); + break; + + case 32: + PRINTF("%#x", sp->is_pass); + break; + + case 33: + PRINTF("%d", sp->is_p); + break; + + case 34: + PRINTF("%d", sp->is_v); + break; + + case 35: + PRINTF("%d", sp->is_hv); + break; + + case 36: + PRINTF("%d", sp->is_tag); + break; + + case 37: + PRINTF("%#x", sp->is_flags); + break; + + case 38: + PRINTF("%d", sp->is_rulen); + break; + + case 39: + PRINTF("%s", sp->is_group); + break; + + case 40: + PRINTF("%#x", sp->is_flx[0][0]); + break; + + case 41: + PRINTF("%#x", sp->is_flx[0][1]); + break; + + case 42: + PRINTF("%#x", sp->is_flx[1][0]); + break; + + case 43: + PRINTF("%#x", sp->is_flx[1][1]); + break; + + case 44: + PRINTF("%#x", sp->is_opt[0]); + break; + + case 45: + PRINTF("%#x", sp->is_opt[1]); + break; + + case 46: + PRINTF("%#x", sp->is_optmsk[0]); + break; + + case 47: + PRINTF("%#x", sp->is_optmsk[1]); + break; + + case 48: + PRINTF("%#x", sp->is_sec); + break; + + case 49: + PRINTF("%#x", sp->is_secmsk); + break; + + case 50: + PRINTF("%#x", sp->is_auth); + break; + + case 51: + PRINTF("%#x", sp->is_authmsk); + break; + + case 52: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", sp->is_icmppkts[0]); +#else + PRINTF("%lu", sp->is_icmppkts[0]); +#endif + break; + + case 53: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", sp->is_icmppkts[1]); +#else + PRINTF("%lu", sp->is_icmppkts[1]); +#endif + break; + + case 54: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", sp->is_icmppkts[2]); +#else + PRINTF("%lu", sp->is_icmppkts[2]); +#endif + break; + + case 55: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", sp->is_icmppkts[3]); +#else + PRINTF("%lu", sp->is_icmppkts[3]); +#endif + break; + + default: + break; + } +} diff --git a/lib/printtcpflags.c b/lib/printtcpflags.c new file mode 100644 index 0000000000000..9860780307a88 --- /dev/null +++ b/lib/printtcpflags.c @@ -0,0 +1,30 @@ +#include "ipf.h" + + +void +printtcpflags(tcpf, tcpfm) + u_32_t tcpf, tcpfm; +{ + u_char *t; + char *s; + + if (tcpf & ~TCPF_ALL) { + PRINTF("0x%x", tcpf); + } else { + for (s = flagset, t = flags; *s; s++, t++) { + if (tcpf & *t) + (void)putchar(*s); + } + } + + if (tcpfm) { + (void)putchar('/'); + if (tcpfm & ~TCPF_ALL) { + PRINTF("0x%x", tcpfm); + } else { + for (s = flagset, t = flags; *s; s++, t++) + if (tcpfm & *t) + (void)putchar(*s); + } + } +} diff --git a/lib/printtqtable.c b/lib/printtqtable.c index 67adb53b1c348..ffb512dac42eb 100644 --- a/lib/printtqtable.c +++ b/lib/printtqtable.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -9,17 +9,18 @@ #include "ipf.h" -void printtqtable(table) -ipftq_t *table; +void +printtqtable(table) + ipftq_t *table; { int i; - printf("TCP Entries per state\n"); + PRINTF("TCP Entries per state\n"); for (i = 0; i < IPF_TCP_NSTATES; i++) - printf(" %5d", i); - printf("\n"); + PRINTF(" %5d", i); + PRINTF("\n"); for (i = 0; i < IPF_TCP_NSTATES; i++) - printf(" %5d", table[i].ifq_ref - 1); - printf("\n"); + PRINTF(" %5d", table[i].ifq_ref - 1); + PRINTF("\n"); } diff --git a/lib/printtunable.c b/lib/printtunable.c index dcf9f859355a9..9e9f6c36efea1 100644 --- a/lib/printtunable.c +++ b/lib/printtunable.c @@ -1,27 +1,28 @@ /* - * Copyright (C) 2003 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: printtunable.c,v 1.1.4.1 2006/06/16 17:21:15 darrenr Exp $ - */ + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ #include "ipf.h" -void printtunable(tup) -ipftune_t *tup; +void +printtunable(tup) + ipftune_t *tup; { - printf("%s\tmin %#lx\tmax %#lx\tcurrent ", + PRINTF("%s\tmin %lu\tmax %lu\tcurrent ", tup->ipft_name, tup->ipft_min, tup->ipft_max); if (tup->ipft_sz == sizeof(u_long)) - printf("%lu\n", tup->ipft_vlong); + PRINTF("%lu\n", tup->ipft_vlong); else if (tup->ipft_sz == sizeof(u_int)) - printf("%u\n", tup->ipft_vint); + PRINTF("%u\n", tup->ipft_vint); else if (tup->ipft_sz == sizeof(u_short)) - printf("%hu\n", tup->ipft_vshort); + PRINTF("%hu\n", tup->ipft_vshort); else if (tup->ipft_sz == sizeof(u_char)) - printf("%u\n", (u_int)tup->ipft_vchar); + PRINTF("%u\n", (u_int)tup->ipft_vchar); else { - printf("sz = %d\n", tup->ipft_sz); + PRINTF("sz = %d\n", tup->ipft_sz); } } diff --git a/lib/printunit.c b/lib/printunit.c new file mode 100644 index 0000000000000..bac3d45d34c5b --- /dev/null +++ b/lib/printunit.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include "ipf.h" + + +void +printunit(unit) + int unit; +{ + + switch (unit) + { + case IPL_LOGIPF : + PRINTF("ipf"); + break; + case IPL_LOGNAT : + PRINTF("nat"); + break; + case IPL_LOGSTATE : + PRINTF("state"); + break; + case IPL_LOGAUTH : + PRINTF("auth"); + break; + case IPL_LOGSYNC : + PRINTF("sync"); + break; + case IPL_LOGSCAN : + PRINTF("scan"); + break; + case IPL_LOGLOOKUP : + PRINTF("lookup"); + break; + case IPL_LOGCOUNT : + PRINTF("count"); + break; + case IPL_LOGALL : + PRINTF("all"); + break; + default : + PRINTF("unknown(%d)", unit); + } +} diff --git a/lib/ratoi.c b/lib/ratoi.c deleted file mode 100644 index fb8552dfcc156..0000000000000 --- a/lib/ratoi.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: ratoi.c,v 1.4 2001/06/09 17:09:25 darrenr Exp $ - */ - -#include "ipf.h" - - -int ratoi(ps, pi, min, max) -char *ps; -int *pi, min, max; -{ - int i; - char *pe; - - i = (int)strtol(ps, &pe, 0); - if (*pe != '\0' || i < min || i > max) - return 0; - *pi = i; - return 1; -} diff --git a/lib/ratoui.c b/lib/ratoui.c deleted file mode 100644 index 191f87f4d116b..0000000000000 --- a/lib/ratoui.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: ratoui.c,v 1.4 2001/06/09 17:09:25 darrenr Exp $ - */ - -#include "ipf.h" - - -int ratoui(ps, pi, min, max) -char *ps; -u_int *pi, min, max; -{ - u_int i; - char *pe; - - i = (u_int)strtol(ps, &pe, 0); - if (*pe != '\0' || i < min || i > max) - return 0; - *pi = i; - return 1; -} diff --git a/lib/remove_hash.c b/lib/remove_hash.c index 55dab91ed164b..b64d8ff5d5ec8 100644 --- a/lib/remove_hash.c +++ b/lib/remove_hash.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: remove_hash.c,v 1.1.4.1 2006/06/16 17:21:16 darrenr Exp $ + * $Id$ */ #include <fcntl.h> @@ -12,19 +12,16 @@ #include "netinet/ip_lookup.h" #include "netinet/ip_htable.h" -static int hashfd = -1; - -int remove_hash(iphp, iocfunc) -iphtable_t *iphp; -ioctlfunc_t iocfunc; +int +remove_hash(iphp, iocfunc) + iphtable_t *iphp; + ioctlfunc_t iocfunc; { iplookupop_t op; iphtable_t iph; - if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0)) - hashfd = open(IPLOOKUP_NAME, O_RDWR); - if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0)) + if (pool_open() == -1) return -1; op.iplo_type = IPLT_HASH; @@ -41,11 +38,11 @@ ioctlfunc_t iocfunc; strncpy(iph.iph_name, iphp->iph_name, sizeof(iph.iph_name)); iph.iph_flags = iphp->iph_flags; - if ((*iocfunc)(hashfd, SIOCLOOKUPDELTABLE, &op)) + if (pool_ioctl(iocfunc, SIOCLOOKUPDELTABLE, &op)) { if ((opts & OPT_DONOTHING) == 0) { - perror("remove_hash:SIOCLOOKUPDELTABLE"); - return -1; + return ipf_perror_fd(pool_fd(), iocfunc, + "remove lookup hash table"); } - + } return 0; } diff --git a/lib/remove_hashnode.c b/lib/remove_hashnode.c index d51f8ab53019d..c846b4872dd48 100644 --- a/lib/remove_hashnode.c +++ b/lib/remove_hashnode.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: remove_hashnode.c,v 1.1.4.1 2006/06/16 17:21:16 darrenr Exp $ + * $Id$ */ #include <fcntl.h> @@ -12,21 +12,18 @@ #include "netinet/ip_lookup.h" #include "netinet/ip_htable.h" -static int hashfd = -1; - -int remove_hashnode(unit, name, node, iocfunc) -int unit; -char *name; -iphtent_t *node; -ioctlfunc_t iocfunc; +int +remove_hashnode(unit, name, node, iocfunc) + int unit; + char *name; + iphtent_t *node; + ioctlfunc_t iocfunc; { iplookupop_t op; iphtent_t ipe; - if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0)) - hashfd = open(IPLOOKUP_NAME, O_RDWR); - if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0)) + if (pool_open() == -1) return -1; op.iplo_type = IPLT_HASH; @@ -47,10 +44,11 @@ ioctlfunc_t iocfunc; printf("%s\n", inet_ntoa(ipe.ipe_mask.in4)); } - if ((*iocfunc)(hashfd, SIOCLOOKUPDELNODE, &op)) + if (pool_ioctl(iocfunc, SIOCLOOKUPDELNODE, &op)) { if (!(opts & OPT_DONOTHING)) { - perror("remove_hash:SIOCLOOKUPDELNODE"); - return -1; + return ipf_perror_fd(pool_fd(), iocfunc, + "remove lookup hash node"); } + } return 0; } diff --git a/lib/remove_pool.c b/lib/remove_pool.c index 19ab4c6c11be8..ca3673a9e9129 100644 --- a/lib/remove_pool.c +++ b/lib/remove_pool.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: remove_pool.c,v 1.1.4.1 2006/06/16 17:21:16 darrenr Exp $ + * $Id$ */ #include <fcntl.h> @@ -12,19 +12,16 @@ #include "netinet/ip_lookup.h" #include "netinet/ip_htable.h" -static int poolfd = -1; - -int remove_pool(poolp, iocfunc) -ip_pool_t *poolp; -ioctlfunc_t iocfunc; +int +remove_pool(poolp, iocfunc) + ip_pool_t *poolp; + ioctlfunc_t iocfunc; { iplookupop_t op; ip_pool_t pool; - if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0)) - poolfd = open(IPLOOKUP_NAME, O_RDWR); - if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0)) + if (pool_open() == -1) return -1; op.iplo_type = IPLT_POOL; @@ -38,11 +35,11 @@ ioctlfunc_t iocfunc; strncpy(pool.ipo_name, poolp->ipo_name, sizeof(pool.ipo_name)); pool.ipo_flags = poolp->ipo_flags; - if ((*iocfunc)(poolfd, SIOCLOOKUPDELTABLE, &op)) + if (pool_ioctl(iocfunc, SIOCLOOKUPDELTABLE, &op)) { if ((opts & OPT_DONOTHING) == 0) { - perror("remove_pool:SIOCLOOKUPDELTABLE"); - return -1; + return ipf_perror_fd(pool_fd(), iocfunc, + "delete lookup pool"); } - + } return 0; } diff --git a/lib/remove_poolnode.c b/lib/remove_poolnode.c index ad04b23c03aae..2986defa3d4dd 100644 --- a/lib/remove_poolnode.c +++ b/lib/remove_poolnode.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: remove_poolnode.c,v 1.3.2.1 2006/06/16 17:21:16 darrenr Exp $ + * $Id$ */ #include <fcntl.h> @@ -12,21 +12,18 @@ #include "netinet/ip_lookup.h" #include "netinet/ip_pool.h" -static int poolfd = -1; - -int remove_poolnode(unit, name, node, iocfunc) -int unit; -char *name; -ip_pool_node_t *node; -ioctlfunc_t iocfunc; +int +remove_poolnode(unit, name, node, iocfunc) + int unit; + char *name; + ip_pool_node_t *node; + ioctlfunc_t iocfunc; { ip_pool_node_t pn; iplookupop_t op; - if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0)) - poolfd = open(IPLOOKUP_NAME, O_RDWR); - if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0)) + if (pool_open() == -1) return -1; op.iplo_unit = unit; @@ -44,10 +41,10 @@ ioctlfunc_t iocfunc; pn.ipn_info = node->ipn_info; strncpy(pn.ipn_name, node->ipn_name, sizeof(pn.ipn_name)); - if ((*iocfunc)(poolfd, SIOCLOOKUPDELNODE, &op)) { + if (pool_ioctl(iocfunc, SIOCLOOKUPDELNODE, &op)) { if ((opts & OPT_DONOTHING) == 0) { - perror("remove_pool:SIOCLOOKUPDELNODE"); - return -1; + return ipf_perror_fd(pool_fd(), iocfunc, + "remove lookup pool node"); } } diff --git a/lib/resetlexer.c b/lib/resetlexer.c index ab9b82e468a82..7b176327cef1b 100644 --- a/lib/resetlexer.c +++ b/lib/resetlexer.c @@ -1,10 +1,10 @@ /* - * Copyright (C) 2002 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: resetlexer.c,v 1.1.4.1 2006/06/16 17:21:16 darrenr Exp $ - */ + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ #include "ipf.h" diff --git a/lib/rwlock_emul.c b/lib/rwlock_emul.c index 1f0c3a8156621..8eadae1bd7064 100644 --- a/lib/rwlock_emul.c +++ b/lib/rwlock_emul.c @@ -1,19 +1,19 @@ /* - * Copyright (C) 2003 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: rwlock_emul.c,v 1.1.4.1 2006/06/16 17:21:17 darrenr Exp $ - */ + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ #include "ipf.h" #define EMM_MAGIC 0x97dd8b3a void eMrwlock_read_enter(rw, file, line) -eMrwlock_t *rw; -char *file; -int line; + eMrwlock_t *rw; + char *file; + int line; { if (rw->eMrw_magic != EMM_MAGIC) { fprintf(stderr, "%s:eMrwlock_read_enter(%p): bad magic: %#x\n", @@ -33,9 +33,9 @@ int line; void eMrwlock_write_enter(rw, file, line) -eMrwlock_t *rw; -char *file; -int line; + eMrwlock_t *rw; + char *file; + int line; { if (rw->eMrw_magic != EMM_MAGIC) { fprintf(stderr, "%s:eMrwlock_write_enter(%p): bad magic: %#x\n", @@ -55,9 +55,9 @@ int line; void eMrwlock_downgrade(rw, file, line) -eMrwlock_t *rw; -char *file; -int line; + eMrwlock_t *rw; + char *file; + int line; { if (rw->eMrw_magic != EMM_MAGIC) { fprintf(stderr, "%s:eMrwlock_write_enter(%p): bad magic: %#x\n", @@ -78,7 +78,7 @@ int line; void eMrwlock_exit(rw) -eMrwlock_t *rw; + eMrwlock_t *rw; { if (rw->eMrw_magic != EMM_MAGIC) { fprintf(stderr, "%s:eMrwlock_exit(%p): bad magic: %#x\n", @@ -99,9 +99,11 @@ eMrwlock_t *rw; } +static int initcount = 0; + void eMrwlock_init(rw, who) -eMrwlock_t *rw; -char *who; + eMrwlock_t *rw; + char *who; { if (rw->eMrw_magic == EMM_MAGIC) { /* safe bet ? */ fprintf(stderr, @@ -116,16 +118,26 @@ char *who; rw->eMrw_owner = strdup(who); else rw->eMrw_owner = NULL; + initcount++; } void eMrwlock_destroy(rw) -eMrwlock_t *rw; + eMrwlock_t *rw; { if (rw->eMrw_magic != EMM_MAGIC) { fprintf(stderr, "%s:eMrwlock_destroy(%p): bad magic: %#x\n", rw->eMrw_owner, rw, rw->eMrw_magic); abort(); } + if (rw->eMrw_owner != NULL) + free(rw->eMrw_owner); memset(rw, 0xa5, sizeof(*rw)); + initcount--; +} + +void ipf_rwlock_clean() +{ + if (initcount != 0) + abort(); } diff --git a/lib/save_execute.c b/lib/save_execute.c new file mode 100644 index 0000000000000..65caca46bc766 --- /dev/null +++ b/lib/save_execute.c @@ -0,0 +1,80 @@ +#include "ipf.h" +#include "ipmon.h" + +static void *execute_parse __P((char **)); +static void execute_destroy __P((void *)); +static int execute_send __P((void *, ipmon_msg_t *)); +static void execute_print __P((void *)); + +typedef struct execute_opts_s { + char *path; +} execute_opts_t; + +ipmon_saver_t executesaver = { + "execute", + execute_destroy, + NULL, /* dup */ + NULL, /* match */ + execute_parse, + execute_print, + execute_send +}; + + +static void * +execute_parse(char **strings) +{ + execute_opts_t *ctx; + + ctx = calloc(1, sizeof(*ctx)); + + if (ctx != NULL && strings[0] != NULL && strings[0][0] != '\0') { + ctx->path = strdup(strings[0]); + + } else { + free(ctx); + return NULL; + } + + return ctx; +} + + +static void +execute_print(ctx) + void *ctx; +{ + execute_opts_t *exe = ctx; + + printf("%s", exe->path); +} + + +static void +execute_destroy(ctx) + void *ctx; +{ + execute_opts_t *exe = ctx; + + if (exe != NULL) + free(exe->path); + free(exe); +} + + +static int +execute_send(ctx, msg) + void *ctx; + ipmon_msg_t *msg; +{ + execute_opts_t *exe = ctx; + FILE *fp; + + fp = popen(exe->path, "w"); + if (fp != NULL) { + fwrite(msg->imm_msg, msg->imm_msglen, 1, fp); + pclose(fp); + } + return 0; +} + diff --git a/lib/save_file.c b/lib/save_file.c new file mode 100644 index 0000000000000..b852bd601982e --- /dev/null +++ b/lib/save_file.c @@ -0,0 +1,130 @@ +#include "ipf.h" +#include "ipmon.h" + +static void *file_parse __P((char **)); +static void file_destroy __P((void *)); +static int file_send __P((void *, ipmon_msg_t *)); +static void file_print __P((void *)); +static int file_match __P((void *, void *)); +static void *file_dup __P((void *)); + +typedef struct file_opts_s { + FILE *fp; + int raw; + char *path; + int ref; +} file_opts_t; + +ipmon_saver_t filesaver = { + "file", + file_destroy, + file_dup, + file_match, + file_parse, + file_print, + file_send +}; + + +static void * +file_parse(strings) + char **strings; +{ + file_opts_t *ctx; + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) + return NULL; + + if (strings[0] != NULL && strings[0][0] != '\0') { + ctx->ref = 1; + if (!strncmp(strings[0], "raw://", 6)) { + ctx->raw = 1; + ctx->path = strdup(strings[0] + 6); + ctx->fp = fopen(ctx->path, "ab"); + } else if (!strncmp(strings[0], "file://", 7)) { + ctx->path = strdup(strings[0] + 7); + ctx->fp = fopen(ctx->path, "a"); + } else { + free(ctx); + ctx = NULL; + } + } else { + free(ctx); + ctx = NULL; + } + + return ctx; +} + + +static int +file_match(ctx1, ctx2) + void *ctx1, *ctx2; +{ + file_opts_t *f1 = ctx1, *f2 = ctx2; + + if (f1->raw != f2->raw) + return 1; + if (strcmp(f1->path, f2->path)) + return 1; + return 0; +} + + +static void * +file_dup(ctx) + void *ctx; +{ + file_opts_t *f = ctx; + + f->ref++; + return f; +} + + +static void +file_print(ctx) + void *ctx; +{ + file_opts_t *file = ctx; + + if (file->raw) + printf("raw://"); + else + printf("file://"); + printf("%s", file->path); +} + + +static void +file_destroy(ctx) + void *ctx; +{ + file_opts_t *file = ctx; + + file->ref--; + if (file->ref > 0) + return; + + if (file->path != NULL) + free(file->path); + free(file); +} + + +static int +file_send(ctx, msg) + void *ctx; + ipmon_msg_t *msg; +{ + file_opts_t *file = ctx; + + if (file->raw) { + fwrite(msg->imm_data, msg->imm_dsize, 1, file->fp); + } else { + fprintf(file->fp, "%s", msg->imm_msg); + } + return 0; +} + diff --git a/lib/save_nothing.c b/lib/save_nothing.c new file mode 100644 index 0000000000000..274591b9678fe --- /dev/null +++ b/lib/save_nothing.c @@ -0,0 +1,58 @@ +#include "ipf.h" +#include "ipmon.h" + +static void *nothing_parse __P((char **)); +static void nothing_destroy __P((void *)); +static int nothing_send __P((void *, ipmon_msg_t *)); + +typedef struct nothing_opts_s { + FILE *fp; + int raw; + char *path; +} nothing_opts_t; + +ipmon_saver_t nothingsaver = { + "nothing", + nothing_destroy, + NULL, /* dup */ + NULL, /* match */ + nothing_parse, + NULL, /* print */ + nothing_send +}; + + +static void * +nothing_parse(char **strings) +{ + void *ctx; + + strings = strings; /* gcc -Wextra */ + + ctx = calloc(1, sizeof(void *)); + + return ctx; +} + + +static void +nothing_destroy(ctx) + void *ctx; +{ + free(ctx); +} + + +static int +nothing_send(ctx, msg) + void *ctx; + ipmon_msg_t *msg; +{ + ctx = ctx; /* gcc -Wextra */ + msg = msg; /* gcc -Wextra */ + /* + * Do nothing + */ + return 0; +} + diff --git a/lib/save_syslog.c b/lib/save_syslog.c new file mode 100644 index 0000000000000..c1efdf41d9844 --- /dev/null +++ b/lib/save_syslog.c @@ -0,0 +1,137 @@ +#include "ipf.h" +#include "ipmon.h" +#include <syslog.h> + +static void *syslog_parse __P((char **)); +static void syslog_destroy __P((void *)); +static int syslog_send __P((void *, ipmon_msg_t *)); +static void syslog_print __P((void *)); + +typedef struct syslog_opts_s { + int facpri; + int fac; + int pri; +} syslog_opts_t; + +ipmon_saver_t syslogsaver = { + "syslog", + syslog_destroy, + NULL, /* dup */ + NULL, /* match */ + syslog_parse, + syslog_print, + syslog_send +}; + + +static void * +syslog_parse(char **strings) +{ + syslog_opts_t *ctx; + char *str; + char *s; + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) + return NULL; + + ctx->facpri = -1; + + if (strings[0] != NULL && strings[0][0] != '\0') { + str = strdup(*strings); + if (str != NULL && *str != '\0') { + int fac = -1, pri = -1; + + s = strchr(str, '.'); + if (s != NULL) + *s++ = '\0'; + + if (*str != '\0') { + fac = fac_findname(str); + if (fac == -1) { + free(str); + free(ctx); + return NULL; + } + } + + if (s != NULL && *s != '\0') { + pri = pri_findname(s); + if (pri == -1) { + free(str); + free(ctx); + return NULL; + } + } + free(str); + + ctx->fac = fac; + ctx->pri = pri; + if (pri == -1) + ctx->facpri = fac; + else if (fac == -1) + ctx->facpri = pri; + else + ctx->facpri = fac | pri; + } else { + if (str != NULL) + free(str); + free(ctx); + ctx = NULL; + } + } + + return ctx; +} + + +static void +syslog_print(ctx) + void *ctx; +{ + syslog_opts_t *sys = ctx; + + if (sys->facpri == -1) + return; + + if (sys->fac == -1) { + printf(".%s", pri_toname(sys->pri)); + } else if (sys->pri == -1) { + printf("%s.", fac_toname(sys->fac)); + } else { + printf("%s.%s", fac_toname(sys->facpri & LOG_FACMASK), + pri_toname(sys->facpri & LOG_PRIMASK)); + } +} + + +static void +syslog_destroy(ctx) + void *ctx; +{ + free(ctx); +} + + +static int +syslog_send(ctx, msg) + void *ctx; + ipmon_msg_t *msg; +{ + syslog_opts_t *sys = ctx; + int facpri; + + if (sys->facpri == -1) { + facpri = msg->imm_loglevel; + } else { + if (sys->pri == -1) { + facpri = sys->fac | (msg->imm_loglevel & LOG_PRIMASK); + } else if (sys->fac == -1) { + facpri = sys->pri | (msg->imm_loglevel & LOG_FACMASK); + } else { + facpri = sys->facpri; + } + } + syslog(facpri, "%s", msg->imm_msg); + return 0; +} diff --git a/lib/save_v1trap.c b/lib/save_v1trap.c new file mode 100644 index 0000000000000..b17f62c722ca1 --- /dev/null +++ b/lib/save_v1trap.c @@ -0,0 +1,463 @@ +#include "ipf.h" +#include "netinet/ipl.h" +#include "ipmon.h" +#include <ctype.h> + +#define IPF_ENTERPRISE 9932 +/* + * Enterprise number OID: + * 1.3.6.1.4.1.9932 + */ +static u_char ipf_enterprise[] = { 6, 7, 0x2b, 6, 1, 4, 1, 0xcd, 0x4c }; +static u_char ipf_trap0_1[] = { 6, 10, 0x2b, 6, 1, 4, 1, 0xcd, 0x4c, 1, 1, 1 }; +static u_char ipf_trap0_2[] = { 6, 10, 0x2b, 6, 1, 4, 1, 0xcd, 0x4c, 1, 1, 2 }; + +static int writeint __P((u_char *, int)); +static int writelength __P((u_char *, u_int)); +static int maketrap_v1 __P((char *, u_char *, int, u_char *, int, u_32_t, + time_t)); +static void snmpv1_destroy __P((void *)); +static void *snmpv1_dup __P((void *)); +static int snmpv1_match __P((void *, void *)); +static void *snmpv1_parse __P((char **)); +static void snmpv1_print __P((void *)); +static int snmpv1_send __P((void *, ipmon_msg_t *)); + +typedef struct snmpv1_opts_s { + char *community; + int fd; + int v6; + int ref; +#ifdef USE_INET6 + struct sockaddr_in6 sin6; +#endif + struct sockaddr_in sin; +} snmpv1_opts_t; + +ipmon_saver_t snmpv1saver = { + "snmpv1", + snmpv1_destroy, + snmpv1_dup, /* dup */ + snmpv1_match, /* match */ + snmpv1_parse, + snmpv1_print, + snmpv1_send +}; + + +static int +snmpv1_match(ctx1, ctx2) + void *ctx1, *ctx2; +{ + snmpv1_opts_t *s1 = ctx1, *s2 = ctx2; + + if (s1->v6 != s2->v6) + return 1; + + if (strcmp(s1->community, s2->community)) + return 1; + +#ifdef USE_INET6 + if (s1->v6 == 1) { + if (memcmp(&s1->sin6, &s2->sin6, sizeof(s1->sin6))) + return 1; + } else +#endif + { + if (memcmp(&s1->sin, &s2->sin, sizeof(s1->sin))) + return 1; + } + + return 0; +} + + +static void * +snmpv1_dup(ctx) + void *ctx; +{ + snmpv1_opts_t *s = ctx; + + s->ref++; + return s; +} + + +static void +snmpv1_print(ctx) + void *ctx; +{ + snmpv1_opts_t *snmpv1 = ctx; + + printf("%s ", snmpv1->community); +#ifdef USE_INET6 + if (snmpv1->v6 == 1) { + char buf[80]; + + printf("%s", inet_ntop(AF_INET6, &snmpv1->sin6.sin6_addr, buf, + sizeof(snmpv1->sin6.sin6_addr))); + } else +#endif + { + printf("%s", inet_ntoa(snmpv1->sin.sin_addr)); + } +} + + +static void * +snmpv1_parse(char **strings) +{ + snmpv1_opts_t *ctx; + int result; + char *str; + char *s; + + if (strings[0] == NULL || strings[0][0] == '\0') + return NULL; + + if (strchr(*strings, ' ') == NULL) + return NULL; + + str = strdup(*strings); + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) + return NULL; + + ctx->fd = -1; + + s = strchr(str, ' '); + *s++ = '\0'; + ctx->community = str; + + while (ISSPACE(*s)) + s++; + if (!*s) { + free(str); + free(ctx); + return NULL; + } + +#ifdef USE_INET6 + if (strchr(s, ':') == NULL) { + result = inet_pton(AF_INET, s, &ctx->sin.sin_addr); + if (result == 1) { + ctx->fd = socket(AF_INET, SOCK_DGRAM, 0); + if (ctx->fd >= 0) { + ctx->sin.sin_family = AF_INET; + ctx->sin.sin_port = htons(162); + if (connect(ctx->fd, + (struct sockaddr *)&ctx->sin, + sizeof(ctx->sin)) != 0) { + snmpv1_destroy(ctx); + return NULL; + } + } + } + } else { + result = inet_pton(AF_INET6, s, &ctx->sin6.sin6_addr); + if (result == 1) { + ctx->v6 = 1; + ctx->fd = socket(AF_INET6, SOCK_DGRAM, 0); + if (ctx->fd >= 0) { + ctx->sin6.sin6_family = AF_INET6; + ctx->sin6.sin6_port = htons(162); + if (connect(ctx->fd, + (struct sockaddr *)&ctx->sin6, + sizeof(ctx->sin6)) != 0) { + snmpv1_destroy(ctx); + return NULL; + } + } + } + } +#else + result = inet_aton(s, &ctx->sin.sin_addr); + if (result == 1) { + ctx->fd = socket(AF_INET, SOCK_DGRAM, 0); + if (ctx->fd >= 0) { + ctx->sin.sin_family = AF_INET; + ctx->sin.sin_port = htons(162); + if (connect(ctx->fd, &ctx->sin, + sizeof(ctx->sin)) != 0) { + snmpv1_destroy(ctx); + return NULL; + } + } + } +#endif + + if (result != 1) { + free(str); + free(ctx); + return NULL; + } + + ctx->ref = 1; + + return ctx; +} + + +static void +snmpv1_destroy(ctx) + void *ctx; +{ + snmpv1_opts_t *v1 = ctx; + + v1->ref--; + if (v1->ref > 0) + return; + + if (v1->community) + free(v1->community); + if (v1->fd >= 0) + close(v1->fd); + free(v1); +} + + +static int +snmpv1_send(ctx, msg) + void *ctx; + ipmon_msg_t *msg; +{ + snmpv1_opts_t *v1 = ctx; + + return sendtrap_v1_0(v1->fd, v1->community, + msg->imm_msg, msg->imm_msglen, msg->imm_when); +} + +static char def_community[] = "public"; /* ublic */ + +static int +writelength(buffer, value) + u_char *buffer; + u_int value; +{ + u_int n = htonl(value); + int len; + + if (value < 128) { + *buffer = value; + return 1; + } + if (value > 0xffffff) + len = 4; + else if (value > 0xffff) + len = 3; + else if (value > 0xff) + len = 2; + else + len = 1; + + *buffer = 0x80 | len; + + bcopy((u_char *)&n + 4 - len, buffer + 1, len); + + return len + 1; +} + + +static int +writeint(buffer, value) + u_char *buffer; + int value; +{ + u_char *s = buffer; + u_int n = value; + + if (value == 0) { + *buffer = 0; + return 1; + } + + if (n > 4194304) { + *s++ = 0x80 | (n / 4194304); + n -= 4194304 * (n / 4194304); + } + if (n > 32768) { + *s++ = 0x80 | (n / 32768); + n -= 32768 * (n / 327678); + } + if (n > 128) { + *s++ = 0x80 | (n / 128); + n -= (n / 128) * 128; + } + *s++ = (u_char)n; + + return s - buffer; +} + + + +/* + * First style of traps is: + * 1.3.6.1.4.1.9932.1.1 + */ +static int +maketrap_v1(community, buffer, bufsize, msg, msglen, ipaddr, when) + char *community; + u_char *buffer; + int bufsize; + u_char *msg; + int msglen; + u_32_t ipaddr; + time_t when; +{ + u_char *s = buffer, *t, *pdulen, *varlen; + int basesize = 73; + u_short len; + int trapmsglen; + int pdulensz; + int varlensz; + int baselensz; + int n; + + if (community == NULL || *community == '\0') + community = def_community; + basesize += strlen(community) + msglen; + + if (basesize + 8 > bufsize) + return 0; + + memset(buffer, 0xff, bufsize); + *s++ = 0x30; /* Sequence */ + if (basesize - 1 >= 128) { + baselensz = 2; + basesize++; + } else { + baselensz = 1; + } + s += baselensz; + *s++ = 0x02; /* Integer32 */ + *s++ = 0x01; /* length 1 */ + *s++ = 0x00; /* version 1 */ + *s++ = 0x04; /* octet string */ + *s++ = strlen(community); /* length of "public" */ + bcopy(community, s, s[-1]); + s += s[-1]; + *s++ = 0xA4; /* PDU(4) */ + pdulen = s++; + if (basesize - (s - buffer) >= 128) { + pdulensz = 2; + basesize++; + s++; + } else { + pdulensz = 1; + } + + /* enterprise */ + bcopy(ipf_enterprise, s, sizeof(ipf_enterprise)); + s += sizeof(ipf_enterprise); + + /* Agent address */ + *s++ = 0x40; + *s++ = 0x4; + bcopy(&ipaddr, s, 4); + s += 4; + + /* Generic Trap code */ + *s++ = 0x2; + n = writeint(s + 1, 6); + if (n == 0) + return 0; + *s = n; + s += n + 1; + + /* Specific Trap code */ + *s++ = 0x2; + n = writeint(s + 1, 0); + if (n == 0) + return 0; + *s = n; + s += n + 1; + + /* Time stamp */ + *s++ = 0x43; /* TimeTicks */ + *s++ = 0x04; /* TimeTicks */ + s[0] = when >> 24; + s[1] = when >> 16; + s[2] = when >> 8; + s[3] = when & 0xff; + s += 4; + + /* + * The trap0 message is "ipfilter_version" followed by the message + */ + *s++ = 0x30; + varlen = s; + if (basesize - (s - buffer) >= 128) { + varlensz = 2; + basesize++; + } else { + varlensz = 1; + } + s += varlensz; + + *s++ = 0x30; + t = s + 1; + bcopy(ipf_trap0_1, t, sizeof(ipf_trap0_1)); + t += sizeof(ipf_trap0_1); + + *t++ = 0x2; /* Integer */ + n = writeint(t + 1, IPFILTER_VERSION); + *t = n; + t += n + 1; + + len = t - s - 1; + writelength(s, len); + + s = t; + *s++ = 0x30; + if (basesize - (s - buffer) >= 128) { + trapmsglen = 2; + basesize++; + } else { + trapmsglen = 1; + } + t = s + trapmsglen; + bcopy(ipf_trap0_2, t, sizeof(ipf_trap0_2)); + t += sizeof(ipf_trap0_2); + + *t++ = 0x4; /* Octet string */ + n = writelength(t, msglen); + t += n; + bcopy(msg, t, msglen); + t += msglen; + + len = t - s - trapmsglen; + writelength(s, len); + + len = t - varlen - varlensz; + writelength(varlen, len); /* pdu length */ + + len = t - pdulen - pdulensz; + writelength(pdulen, len); /* pdu length */ + + len = t - buffer - baselensz - 1; + writelength(buffer + 1, len); /* length of trap */ + + return t - buffer; +} + + +int +sendtrap_v1_0(fd, community, msg, msglen, when) + int fd; + char *community, *msg; + int msglen; + time_t when; +{ + + u_char buffer[1500]; + int n; + + n = maketrap_v1(community, buffer, sizeof(buffer), + (u_char *)msg, msglen, 0, when); + if (n > 0) { + return send(fd, buffer, n, 0); + } + + return 0; +} diff --git a/lib/save_v2trap.c b/lib/save_v2trap.c new file mode 100644 index 0000000000000..24349bb40581c --- /dev/null +++ b/lib/save_v2trap.c @@ -0,0 +1,459 @@ +#include "ipf.h" +#include "netinet/ipl.h" +#include "ipmon.h" +#include <ctype.h> + +static u_char sysuptime[] = { 6, 8, 0x2b, 6, 1, 2, 1, 1, 3, 0 }; +/* + * Enterprise number OID: + * 1.3.6.1.4.1.9932 + */ +static u_char ipf_trap0_1[] = { 6, 10, 0x2b, 6, 1, 4, 1, 0xcd, 0x4c, 1, 1, 1 }; +static u_char ipf_trap0_2[] = { 6, 10, 0x2b, 6, 1, 4, 1, 0xcd, 0x4c, 1, 1, 2 }; + +static int writeint __P((u_char *, int)); +static int writelength __P((u_char *, u_int)); +static int maketrap_v2 __P((char *, u_char *, int, u_char *, int)); +static void snmpv2_destroy __P((void *)); +static void *snmpv2_dup __P((void *)); +static int snmpv2_match __P((void *, void *)); +static void *snmpv2_parse __P((char **)); +static void snmpv2_print __P((void *)); +static int snmpv2_send __P((void *, ipmon_msg_t *)); + + +int sendtrap_v2_0 __P((int, char *, char *, int)); + +static char def_community[] = "public"; /* ublic */ + +typedef struct snmpv2_opts_s { + char *community; + char *server; + int fd; + int v6; + int ref; +#ifdef USE_INET6 + struct sockaddr_in6 sin6; +#endif + struct sockaddr_in sin; +} snmpv2_opts_t; + +ipmon_saver_t snmpv2saver = { + "snmpv2", + snmpv2_destroy, + snmpv2_dup, /* dup */ + snmpv2_match, /* match */ + snmpv2_parse, + snmpv2_print, + snmpv2_send +}; + + +static int +snmpv2_match(ctx1, ctx2) + void *ctx1, *ctx2; +{ + snmpv2_opts_t *s1 = ctx1, *s2 = ctx2; + + if (s1->v6 != s2->v6) + return 1; + + if (strcmp(s1->community, s2->community)) + return 1; + +#ifdef USE_INET6 + if (s1->v6 == 1) { + if (memcmp(&s1->sin6, &s2->sin6, sizeof(s1->sin6))) + return 1; + } else +#endif + { + if (memcmp(&s1->sin, &s2->sin, sizeof(s1->sin))) + return 1; + } + + return 0; +} + + +static void * +snmpv2_dup(ctx) + void *ctx; +{ + snmpv2_opts_t *s = ctx; + + s->ref++; + return s; +} + + +static void +snmpv2_print(ctx) + void *ctx; +{ + snmpv2_opts_t *snmpv2 = ctx; + + printf("%s ", snmpv2->community); +#ifdef USE_INET6 + if (snmpv2->v6 == 1) { + char buf[80]; + + printf("%s", inet_ntop(AF_INET6, &snmpv2->sin6.sin6_addr, buf, + sizeof(snmpv2->sin6.sin6_addr))); + } else +#endif + { + printf("%s", inet_ntoa(snmpv2->sin.sin_addr)); + } +} + + +static void * +snmpv2_parse(char **strings) +{ + snmpv2_opts_t *ctx; + int result; + char *str; + char *s; + + if (strings[0] == NULL || strings[0][0] == '\0') + return NULL; + if (strchr(*strings, ' ') == NULL) + return NULL; + + str = strdup(*strings); + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) + return NULL; + + ctx->fd = -1; + + s = strchr(str, ' '); + *s++ = '\0'; + ctx->community = str; + + while (ISSPACE(*s)) + s++; + if (!*s) { + free(str); + free(ctx); + return NULL; + } + +#ifdef USE_INET6 + if (strchr(s, ':') == NULL) { + result = inet_pton(AF_INET, s, &ctx->sin.sin_addr); + if (result == 1) { + ctx->fd = socket(AF_INET, SOCK_DGRAM, 0); + if (ctx->fd >= 0) { + ctx->sin.sin_family = AF_INET; + ctx->sin.sin_port = htons(162); + if (connect(ctx->fd, + (struct sockaddr *)&ctx->sin, + sizeof(ctx->sin)) != 0) { + snmpv2_destroy(ctx); + return NULL; + } + } + } + } else { + result = inet_pton(AF_INET6, s, &ctx->sin6.sin6_addr); + if (result == 1) { + ctx->v6 = 1; + ctx->fd = socket(AF_INET6, SOCK_DGRAM, 0); + if (ctx->fd >= 0) { + ctx->sin6.sin6_family = AF_INET6; + ctx->sin6.sin6_port = htons(162); + if (connect(ctx->fd, + (struct sockaddr *)&ctx->sin6, + sizeof(ctx->sin6)) != 0) { + snmpv2_destroy(ctx); + return NULL; + } + } + } + } +#else + result = inet_aton(s, &ctx->sin.sin_addr); + if (result == 1) { + ctx->fd = socket(AF_INET, SOCK_DGRAM, 0); + if (ctx->fd >= 0) { + ctx->sin.sin_family = AF_INET; + ctx->sin.sin_port = htons(162); + if (connect(ctx->fd, &ctx->sin, + sizeof(ctx->sin)) != 0) { + snmpv2_destroy(ctx); + return NULL; + } + } + } +#endif + + if (result != 1) { + free(str); + free(ctx); + return NULL; + } + + ctx->ref = 1; + + return ctx; +} + + +static void +snmpv2_destroy(ctx) + void *ctx; +{ + snmpv2_opts_t *v2 = ctx; + + v2->ref--; + if (v2->ref > 0) + return; + + if (v2->community) + free(v2->community); + if (v2->fd >= 0) + close(v2->fd); + free(v2); +} + + +static int +snmpv2_send(ctx, msg) + void *ctx; + ipmon_msg_t *msg; +{ + snmpv2_opts_t *v2 = ctx; + + return sendtrap_v2_0(v2->fd, v2->community, + msg->imm_msg, msg->imm_msglen); +} +static int +writelength(buffer, value) + u_char *buffer; + u_int value; +{ + u_int n = htonl(value); + int len; + + if (value < 128) { + *buffer = value; + return 1; + } + if (value > 0xffffff) + len = 4; + else if (value > 0xffff) + len = 3; + else if (value > 0xff) + len = 2; + else + len = 1; + + *buffer = 0x80 | len; + + bcopy((u_char *)&n + 4 - len, buffer + 1, len); + + return len + 1; +} + + +static int +writeint(buffer, value) + u_char *buffer; + int value; +{ + u_char *s = buffer; + u_int n = value; + + if (value == 0) { + *buffer = 0; + return 1; + } + + if (n > 4194304) { + *s++ = 0x80 | (n / 4194304); + n -= 4194304 * (n / 4194304); + } + if (n > 32768) { + *s++ = 0x80 | (n / 32768); + n -= 32768 * (n / 327678); + } + if (n > 128) { + *s++ = 0x80 | (n / 128); + n -= (n / 128) * 128; + } + *s++ = (u_char)n; + + return s - buffer; +} + + + +/* + * First style of traps is: + * 1.3.6.1.4.1.9932.1.1 + */ +static int +maketrap_v2(community, buffer, bufsize, msg, msglen) + char *community; + u_char *buffer; + int bufsize; + u_char *msg; + int msglen; +{ + u_char *s = buffer, *t, *pdulen; + u_char *varlen; + int basesize = 77; + u_short len; + int trapmsglen; + int pdulensz; + int varlensz; + int baselensz; + int n; + + if (community == NULL || *community == '\0') + community = def_community; + basesize += strlen(community) + msglen; + + if (basesize + 8 > bufsize) + return 0; + + memset(buffer, 0xff, bufsize); + *s++ = 0x30; /* Sequence */ + + if (basesize - 1 >= 128) { + baselensz = 2; + basesize++; + } else { + baselensz = 1; + } + s += baselensz; + *s++ = 0x02; /* Integer32 */ + *s++ = 0x01; /* length 1 */ + *s++ = 0x01; /* version 2 */ + *s++ = 0x04; /* octet string */ + *s++ = strlen(community); /* length of "public" */ + bcopy(community, s, s[-1]); + s += s[-1]; + *s++ = 0xA7; /* PDU(7) */ + pdulen = s++; + if (basesize - (s - buffer) >= 128) { + pdulensz = 2; + basesize++; + s++; + } else { + pdulensz = 1; + } + /* request id */ + *s++ = 0x2; /* integer */ + *s++ = 0x4; /* len 4 */ + *s++ = 0x0; /* noError */ + *s++ = 0x0; /* noError */ + *s++ = 0x0; /* noError */ + *s++ = 0x0; /* noError */ + + /* error status */ + *s++ = 0x2; /* integer */ + *s++ = 0x1; /* len 1 */ + *s++ = 0x0; /* noError */ + + /* error-index */ + *s++ = 0x2; /* integer */ + *s++ = 0x1; /* len 1 */ + *s++ = 0x0; /* noError */ + + *s++ = 0x30; /* sequence */ + varlen = s++; + if (basesize - (s - buffer) >= 128) { + varlensz = 2; + basesize++; + s++; + } else { + varlensz = 1; + } + + *s++ = 0x30; /* sequence */ + *s++ = sizeof(sysuptime) + 6; + + bcopy(sysuptime, s, sizeof(sysuptime)); + s += sizeof(sysuptime); + + *s++ = 0x43; /* Timestamp */ + *s++ = 0x04; /* TimeTicks */ + *s++ = 0x0; + *s++ = 0x0; + *s++ = 0x0; + *s++ = 0x0; + + *s++ = 0x30; + t = s + 1; + bcopy(ipf_trap0_1, t, sizeof(ipf_trap0_1)); + t += sizeof(ipf_trap0_1); + + *t++ = 0x2; /* Integer */ + n = writeint(t + 1, IPFILTER_VERSION); + *t = n; + t += n + 1; + + len = t - s - 1; + writelength(s, len); + + s = t; + *s++ = 0x30; + if (msglen < 128) { + if (msglen + 1 + 1 + sizeof(ipf_trap0_2) >= 128) + trapmsglen = 2; + else + trapmsglen = 1; + } else { + if (msglen + 2 + 1 + sizeof(ipf_trap0_2) >= 128) + trapmsglen = 2; + else + trapmsglen = 1; + } + t = s + trapmsglen; + bcopy(ipf_trap0_2, t, sizeof(ipf_trap0_2)); + t += sizeof(ipf_trap0_2); + + *t++ = 0x4; /* Octet string */ + n = writelength(t, msglen); + t += n; + bcopy(msg, t, msglen); + t += msglen; + + len = t - s - trapmsglen; + writelength(s, len); + + len = t - varlen - varlensz; + writelength(varlen, len); /* pdu length */ + + len = t - pdulen - pdulensz; + writelength(pdulen, len); /* pdu length */ + + len = t - buffer - baselensz - 1; + writelength(buffer + 1, len); /* length of trap */ + + return t - buffer; +} + + +int +sendtrap_v2_0(fd, community, msg, msglen) + int fd; + char *community, *msg; + int msglen; +{ + + u_char buffer[1500]; + int n; + + n = maketrap_v2(community, buffer, sizeof(buffer), + (u_char *)msg, msglen); + if (n > 0) { + return send(fd, buffer, n, 0); + } + + return 0; +} diff --git a/lib/tcp_flags.c b/lib/tcp_flags.c deleted file mode 100644 index 67b7dad9431ed..0000000000000 --- a/lib/tcp_flags.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2000-2004 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: tcp_flags.c,v 1.8.2.1 2006/06/16 17:21:17 darrenr Exp $ - */ - -#include "ipf.h" - -extern char flagset[]; -extern u_char flags[]; - - -u_char tcp_flags(flgs, mask, linenum) -char *flgs; -u_char *mask; -int linenum; -{ - u_char tcpf = 0, tcpfm = 0; - char *s; - - s = strchr(flgs, '/'); - if (s) - *s++ = '\0'; - - if (*flgs == '0') { - tcpf = strtol(flgs, NULL, 0); - } else { - tcpf = tcpflags(flgs); - } - - if (s != NULL) { - if (*s == '0') - tcpfm = strtol(s, NULL, 0); - else - tcpfm = tcpflags(s); - } - - if (!tcpfm) { - if (tcpf == TH_SYN) - tcpfm = 0xff & ~(TH_ECN|TH_CWR); - else - tcpfm = 0xff & ~(TH_ECN); - } - *mask = tcpfm; - return tcpf; -} diff --git a/lib/tcpflags.c b/lib/tcpflags.c index bf2c284417cd4..76a6451fc7f4e 100644 --- a/lib/tcpflags.c +++ b/lib/tcpflags.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2001-2002 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: tcpflags.c,v 1.3.4.1 2006/06/16 17:21:17 darrenr Exp $ + * $Id$ */ #include "ipf.h" @@ -24,7 +24,7 @@ extern u_char flags[]; u_char tcpflags(flgs) -char *flgs; + char *flgs; { u_char tcpf = 0; char *s, *t; diff --git a/lib/tcpoptnames.c b/lib/tcpoptnames.c index 7c037366e0f21..3e35e71cb88fd 100644 --- a/lib/tcpoptnames.c +++ b/lib/tcpoptnames.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2000-2002 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: tcpoptnames.c,v 1.5.4.1 2006/06/16 17:21:17 darrenr Exp $ + * $Id$ */ #include "ipf.h" diff --git a/lib/to_interface.c b/lib/to_interface.c deleted file mode 100644 index 8f2c16f043778..0000000000000 --- a/lib/to_interface.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: to_interface.c,v 1.8 2002/01/28 06:50:48 darrenr Exp $ - */ - -#include "ipf.h" - - -int to_interface(fdp, to, linenum) -frdest_t *fdp; -char *to; -int linenum; -{ - char *s; - - s = strchr(to, ':'); - fdp->fd_ifp = NULL; - if (s) { - *s++ = '\0'; - if (hostnum((u_32_t *)&fdp->fd_ip, s, linenum, NULL) == -1) - return -1; - } - (void) strncpy(fdp->fd_ifname, to, sizeof(fdp->fd_ifname) - 1); - fdp->fd_ifname[sizeof(fdp->fd_ifname) - 1] = '\0'; - return 0; -} diff --git a/lib/v6ionames.c b/lib/v6ionames.c index 97c20b0a512af..629a8a4334b75 100644 --- a/lib/v6ionames.c +++ b/lib/v6ionames.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2003-2005 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: v6ionames.c,v 1.1.4.3 2006/06/16 17:21:18 darrenr Exp $ + * $Id$ */ #include "ipf.h" @@ -14,10 +14,10 @@ struct ipopt_names v6ionames[] ={ { IPPROTO_HOPOPTS, 0x000001, 0, "hopopts" }, { IPPROTO_IPV6, 0x000002, 0, "ipv6" }, { IPPROTO_ROUTING, 0x000004, 0, "routing" }, - { IPPROTO_FRAGMENT, 0x000008, 0, "frag" }, + { IPPROTO_FRAGMENT, 0x000008, 0, "frag" }, { IPPROTO_ESP, 0x000010, 0, "esp" }, { IPPROTO_AH, 0x000020, 0, "ah" }, - { IPPROTO_NONE, 0x000040, 0, "none" }, + { IPPROTO_NONE, 0x000040, 0, "none" }, { IPPROTO_DSTOPTS, 0x000080, 0, "dstopts" }, { IPPROTO_MOBILITY, 0x000100, 0, "mobility" }, { 0, 0, 0, (char *)NULL } diff --git a/lib/v6optvalue.c b/lib/v6optvalue.c index 6123fc2470466..0c9dd92341de1 100644 --- a/lib/v6optvalue.c +++ b/lib/v6optvalue.c @@ -1,16 +1,16 @@ /* - * Copyright (C) 2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: v6optvalue.c,v 1.1.4.1 2006/06/16 17:21:18 darrenr Exp $ + * $Id$ */ #include "ipf.h" u_32_t getv6optbyname(optname) -char *optname; + char *optname; { #ifdef USE_INET6 struct ipopt_names *io; @@ -24,7 +24,7 @@ char *optname; u_32_t getv6optbyvalue(optval) -int optval; + int optval; { #ifdef USE_INET6 struct ipopt_names *io; diff --git a/lib/var.c b/lib/var.c index 3d90a236818a6..df4b137d303fd 100644 --- a/lib/var.c +++ b/lib/var.c @@ -1,10 +1,10 @@ /* - * Copyright (C) 2002-2004 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: var.c,v 1.4.2.3 2006/06/16 17:21:18 darrenr Exp $ - */ + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ #include <ctype.h> @@ -23,7 +23,7 @@ static char *expand_string __P((char *, int)); static variable_t *find_var(name) -char *name; + char *name; { variable_t *v; @@ -35,8 +35,8 @@ char *name; char *get_variable(string, after, line) -char *string, **after; -int line; + char *string, **after; + int line; { char c, *s, *t, *value; variable_t *v; @@ -82,8 +82,8 @@ int line; static char *expand_string(oldstring, line) -char *oldstring; -int line; + char *oldstring; + int line; { char c, *s, *p1, *p2, *p3, *newstring, *value; int len; @@ -142,8 +142,8 @@ int line; void set_variable(name, value) -char *name; -char *value; + char *name; + char *value; { variable_t *v; int len; diff --git a/lib/verbose.c b/lib/verbose.c index 4a856b0c0f534..d5e650c799fef 100644 --- a/lib/verbose.c +++ b/lib/verbose.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2000-2001 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: verbose.c,v 1.6.4.1 2006/06/16 17:21:18 darrenr Exp $ + * $Id$ */ #if defined(__STDC__) @@ -13,16 +13,16 @@ #endif #include <stdio.h> -#include "ipt.h" +#include "ipf.h" #include "opts.h" #if defined(__STDC__) -void verbose(char *fmt, ...) +void verbose(int level, char *fmt, ...) #else -void verbose(fmt, va_alist) -char *fmt; -va_dcl +void verbose(level, fmt, va_alist) + char *fmt; + va_dcl #endif { va_list pvar; @@ -33,3 +33,21 @@ va_dcl vprintf(fmt, pvar); va_end(pvar); } + + +#if defined(__STDC__) +void ipfkverbose(char *fmt, ...) +#else +void ipfkverbose(fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + va_list pvar; + + va_start(pvar, fmt); + + if (opts & OPT_VERBOSE) + verbose(0x1fffffff, fmt, pvar); + va_end(pvar); +} diff --git a/lib/vtof.c b/lib/vtof.c new file mode 100644 index 0000000000000..fd1a98432aa85 --- /dev/null +++ b/lib/vtof.c @@ -0,0 +1,16 @@ +#include "ipf.h" + +int +vtof(version) + int version; +{ +#ifdef USE_INET6 + if (version == 6) + return AF_INET6; +#endif + if (version == 4) + return AF_INET; + if (version == 0) + return AF_UNSPEC; + return -1; +} diff --git a/linux.c b/linux.c new file mode 100644 index 0000000000000..63a9f42a2c067 --- /dev/null +++ b/linux.c @@ -0,0 +1,351 @@ + +#include "ipf-linux.h" +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) +# include <linux/devfs_fs_kernel.h> +#endif + +#ifdef MODULE +MODULE_SUPPORTED_DEVICE("ipf"); +MODULE_AUTHOR("Darren Reed"); +MODULE_DESCRIPTION("IP-Filter Firewall"); +MODULE_LICENSE("(C)Copyright (C) 2012 by Darren Reed. +#endif + +static int ipf_open(struct inode *, struct file *); +static ssize_t ipf_write(struct file *, const char *, size_t, loff_t *); +static ssize_t ipf_read(struct file *, char *, size_t, loff_t *); +static u_int ipf_poll(struct file *fp, struct poll_table_struct *wait); +extern int ipf_ioctl(struct inode *, struct file *, u_int, u_long); + + +#ifdef CONFIG_DEVFS_FS +static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, + IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME, + IPLOOKUP_NAME, NULL }; +#endif + +static struct file_operations ipf_fops = { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + .owner = THIS_MODULE, +#endif + open: ipf_open, + read: ipf_read, + write: ipf_write, + ioctl: ipf_ioctl, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + poll: ipf_poll, +#endif +}; + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +static devfs_handle_t dh[IPL_LOGSIZE]; +#endif +static int ipfmajor = 0; + +ipf_main_softc_t ipfmain; + +int +uiomove(address, nbytes, rwflag, uiop) + caddr_t address; + size_t nbytes; + int rwflag; + uio_t *uiop; +{ + int err = 0; + + if (rwflag == UIO_READ) { + err = copy_to_user(uiop->uio_buf, address, nbytes); + if (err == 0) { + uiop->uio_resid -= nbytes; + uiop->uio_buf += nbytes; + } + } else if (rwflag == UIO_WRITE) { + err = copy_from_user(uiop->uio_buf, address, nbytes); + if (err == 0) { + uiop->uio_resid -= nbytes; + uiop->uio_buf += nbytes; + } + } + if (err) + return -EFAULT; + return 0; +} + + +static int +ipf_open(struct inode *in, struct file *fp) +{ + int unit, err; + + unit = MINOR(in->i_rdev); + + if (unit < 0 || unit > IPL_LOGMAX) { + err = -ENXIO; + } else { + switch (unit) + { + case IPL_LOGIPF : + case IPL_LOGNAT : + case IPL_LOGSTATE : + case IPL_LOGAUTH : + case IPL_LOGLOOKUP : + case IPL_LOGSYNC : +#ifdef IPFILTER_SCAN + case IPL_LOGSCAN : +#endif + err = 0; + break; + default : + err = -ENXIO; + break; + } + } + return err; +} + + +static ssize_t +ipf_write(struct file *fp, const char *buf, size_t count, loff_t *posp) +{ + struct inode *i; + int unit, err; + uio_t uio; + + i = fp->f_dentry->d_inode; + unit = MINOR(i->i_rdev); + + if (unit != IPL_LOGSYNC) + return -ENXIO; + + uio.uio_rw = UIO_WRITE; + uio.uio_iov = NULL; + uio.uio_file = fp; + uio.uio_buf = (char *)buf; + uio.uio_iovcnt = 0; + uio.uio_offset = *posp; + uio.uio_resid = count; + + err = ipf_sync_write(&ipfmain, &uio); + if (err > 0) + err = -err; + return err; +} + + +static ssize_t +ipf_read(struct file *fp, char *buf, size_t count, loff_t *posp) +{ + struct inode *i; + int unit, err; + uio_t uio; + + i = fp->f_dentry->d_inode; + unit = MINOR(i->i_rdev); + + uio.uio_rw = UIO_READ; + uio.uio_iov = NULL; + uio.uio_file = fp; + uio.uio_buf = (char *)buf; + uio.uio_iovcnt = 0; + uio.uio_offset = *posp; + uio.uio_resid = count; + + switch (unit) + { + case IPL_LOGSYNC : + err = ipf_sync_read(&ipfmain, &uio); + break; + default : + err = ipf_log_read(&ipfmain, unit, &uio); + if (err == 0) + return count - uio.uio_resid; + break; + } + + if (err > 0) + err = -err; + return err; +} + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +static u_int +ipf_poll(struct file *fp, poll_table *wait) +{ + struct inode *i; + u_int revents; + int unit; + + revents = 0; + i = fp->f_dentry->d_inode; + unit = MINOR(i->i_rdev); + if (unit < 0 || unit > IPL_LOGMAX) + return 0; + + poll_wait(fp, &ipfmain.iplh_linux[unit], wait); + + switch (unit) + { + case IPL_LOGIPF : + case IPL_LOGNAT : + case IPL_LOGSTATE : +# ifdef IPFILTER_LOG + if (ipf_log_canread(&ipfmain, unit)) + revents = (POLLIN | POLLRDNORM); +# endif + break; + case IPL_LOGAUTH : + if (ipf_auth_waiting(&ipfmain)) + revents = (POLLIN | POLLRDNORM); + break; + case IPL_LOGSYNC : + if (ipf_sync_canread(&ipfmain)) + revents = (POLLIN | POLLRDNORM); + break; + case IPL_LOGSCAN : + case IPL_LOGLOOKUP : + default : + break; + } + + return revents; +} +#endif + + +static int +ipfilter_init(void) +{ + char *defpass; + int i; + + ipfmajor = register_chrdev(0, "ipf", &ipf_fops); + if (ipfmajor < 0) { + printf("unable to get major for ipf devs (%d)\n", ipfmajor); + return -EINVAL; + } + +#ifdef CONFIG_DEVFS_FS + for (i = 0; ipf_devfiles[i] != NULL; i++) { + char *s; + + s = strrchr(ipf_devfiles[i], '/'); + if (s != NULL) { +# if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + dh[i] = devfs_register(NULL, s + 1, DEVFS_FL_DEFAULT, + ipfmajor, i, 0600|S_IFCHR, + &ipf_fops, NULL); +# else + devfs_mk_cdev(MKDEV(ipfmajor, i),0600|S_IFCHR,s+1); +# endif + } + } +#endif + + i = ipf_load_all(); + if (i != 0) + return i; + + ipf_create_all(&ipfmain); + + i = ipfattach(&ipfmain); + + if (i != 0) { + ipf_destroy_all(&ipfmain); + ipf_unload_all(); + return i; + } + + if (FR_ISPASS(ipfmain.ipf_pass)) + defpass = "pass"; + else if (FR_ISBLOCK(ipfmain.ipf_pass)) + defpass = "block"; + else + defpass = "no-match -> block"; + + printk(KERN_INFO "%s initialized. Default = %s all, Logging = %s%s\n", + ipfilter_version, defpass, +# ifdef IPFILTER_LOG + "enabled", +# else + "disabled", +# endif +# ifdef IPFILTER_COMPILED + " (COMPILED)" +# else + "" +# endif + ); + + ipfmain.ipf_running = 1; + + return 0; +} + + +static int +ipfilter_fini(void) +{ + int result; +#ifdef CONFIG_DEVFS_FS + int i; +#endif + + if (ipfmain.ipf_refcnt) + return -EBUSY; + + if (ipfmain.ipf_running >= 0) { + result = ipfdetach(&ipfmain); + if (result != 0) { + if (result > 0) + result = -result; + return result; + } else { + ipf_destroy_all(&ipfmain); + ipf_unload_all(); + } + } + + ipfmain.ipf_running = -2; + + +#ifdef CONFIG_DEVFS_FS + for (i = 0; ipf_devfiles[i] != NULL; i++) { + char *s; + + s = strrchr(ipf_devfiles[i], '/'); + if (s != NULL) +# if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + devfs_unregister_chrdev(ipfmajor, s + 1); +# else + devfs_remove(s+1); +# endif + } +#endif + + if (ipfmajor >= 0) + unregister_chrdev(ipfmajor, "ipf"); + printk(KERN_INFO "%s unloaded\n", ipfilter_version); + + return 0; +} + + +static int __init +ipf_init(void) +{ + int result; + + result = ipfilter_init(); + return result; +} + + +static void __exit ipf_fini(void) +{ + (void) ipfilter_fini(); +} + +module_init(ipf_init) +module_exit(ipf_fini) @@ -1,13 +1,10 @@ /* - * Copyright (C) 1993-1998 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. The author accepts no - * responsibility and is not changed in any way. + * See the IPFILTER.LICENCE file for details on licencing. * * I hate legaleese, don't you ? - * $Id: linux.h,v 2.1 1999/08/04 17:30:10 darrenr Exp $ + * $Id$ */ #include <linux/config.h> diff --git a/man/Makefile b/man/Makefile index 3f12ccbe87b42..a1690fc942fe0 100644 --- a/man/Makefile +++ b/man/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 1993-1998 by Darren Reed. +# Copyright (C) 2012 by Darren Reed. # # See the IPFILTER.LICENCE file for details on licencing. # diff --git a/man/ipf.1 b/man/ipf.1 deleted file mode 100644 index 5ea06fa74c359..0000000000000 --- a/man/ipf.1 +++ /dev/null @@ -1,109 +0,0 @@ -.TH IPF 1 -.SH NAME -ipf \- alters packet filtering lists for IP packet input and ouput -.SH SYNOPSIS -.B ipf -[ -.B \-AdDEInorsUvyzZ -] [ -.B \-l -<block|pass|nomatch> -] [ -.B \-F -<i|o|a> -] -.B \-f -<\fIfilename\fP> -[ -.B \-f -<\fIfilename\fP> -[...]] -.SH DESCRIPTION -.PP -\fBipf\fP opens the filenames listed (treating "\-" as stdin) and parses the -file for a set of rules which are to be added or removed from the packet -filter rule set. -.PP -Each rule processed by \fBipf\fP -is added to the kernel's internal lists if there are no parsing problems. -Rules are added to the end of the internal lists, matching the order in -which they appear when given to \fBipf\fP. -.SH OPTIONS -.TP -.B \-A -Set the list to make changes to the active list (default). -.TP -.B \-d -Turn debug mode on. Causes a hexdump of filter rules to be generated as -it processes each one. -.TP -.B \-D -Disable the filter (if enabled). Not effective for loadable kernel versions. -.TP -.B \-E -Enable the filter (if disabled). Not effective for loadable kernel versions. -.TP -.BR \-F \0<param> -This option specifies which filter list to flush. The parameter should -either be "i" (input), "o" (output) or "a" (remove all filter rules). -Either a single letter or an entire word starting with the appropriate -letter maybe used. This option maybe before, or after, any other with -the order on the command line being that used to execute options. -.TP -.BR \-f \0<filename> -This option specifies which files -\fBipf\fP should use to get input from for modifying the packet filter rule -lists. -.TP -.B \-I -Set the list to make changes to the inactive list. -.TP -.B \-l \0<param> -Use of the \fB-l\fP flag toggles default logging of packets. Valid -arguments to this option are \fBpass\fP, \fBblock\fP and \fBnomatch\fP. -When an option is set, any packet which exits filtering and matches the -set category is logged. This is most useful for causing all packets -which don't match any of the loaded rules to be logged. -.TP -.B \-n -This flag (no-change) prevents \fBipf\fP from actually making any ioctl -calls or doing anything which would alter the currently running kernel. -.TP -.B \-o -Force rules by default to be added/deleted to/from the output list, rather -than the (default) input list. -.TP -.B \-r -Remove matching filter rules rather than add them to the internal lists -.TP -.B \-s -Swap the active filter list in use to be the "other" one. -.TP -.B \-U -(SOLARIS 2 ONLY) Block packets travelling along the data stream which aren't -recognised as IP packets. They will be printed out on the console. -.TP -.B \-v -Turn verbose mode on. Displays information relating to rule processing. -.TP -.B \-y -(SOLARIS 2 ONLY) Manually resync the in-kernel interface list maintained -by IP Filter with the current interface status list. -.TP -.B \-z -For each rule in the input file, reset the statistics for it to zero and -display the statistics prior to them being zero'd. -.TP -.B \-Z -Zero global statistics held in the kernel for filtering only (this doesn't -affect fragment or state statistics). -.DT -.SH SEE ALSO -ipfstat(1), ipftest(1), ipf(5), mkfilters(1) -.SH DIAGNOSTICS -.PP -Needs to be run as root for the packet filtering lists to actually -be affected inside the kernel. -.SH BUGS -.PP -If you find any, please send email to me at darrenr@cyber.com.au diff --git a/man/ipf.4 b/man/ipf.4 index e2e5b5b10fbd5..5b48a1ebd0ebc 100644 --- a/man/ipf.4 +++ b/man/ipf.4 @@ -45,7 +45,6 @@ active and inactive, respectively. All of these ioctl's are implemented as being routing ioctls and thus the same rules for the various routing ioctls and the file descriptor are employed, mainly being that the fd must be that of the device associated with the module (i.e., /dev/ipl). -.LP .PP The three groups of ioctls above perform adding rules to the end of the list (SIOCAD*), deletion of rules from any place in the list (SIOCRM*) @@ -82,10 +81,10 @@ typedef struct frentry { u_short fr_icmp; u_char fr_scmp; /* data for port comparisons */ - u_char fr_dcmp; + u_char fr_dcmp; u_short fr_dport; u_short fr_sport; - u_short fr_stop; /* top port for <> and >< */ + u_short fr_stop; /* top port for <> and >< */ u_short fr_dtop; /* top port for <> and >< */ u_32_t fr_flags; /* per-rule flags && options (see below) */ u_short fr_skip; /* # of rules to skip */ @@ -95,7 +94,7 @@ typedef struct frentry { char fr_ifname[IFNAMSIZ]; #if BSD > 199306 char fr_oifname[IFNAMSIZ]; -#endif +#endif struct frdest fr_tif; /* "to" interface */ struct frdest fr_dif; /* duplicate packet interfaces */ } frentry_t; @@ -105,7 +104,6 @@ When adding a new rule, all unused fields (in the filter rule) should be initialised to be zero. To insert a rule, at a particular position in the 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_flags: .nf @@ -136,7 +134,7 @@ Flags which are recognised in fr_flags: FR_NOTDSTIP 0x100000 /* not the dst IP# */ FR_AUTH 0x200000 /* use authentication */ FR_PREAUTH 0x400000 /* require preauthentication */ - + .fi .PP Values for fr_scomp and fr_dcomp (source and destination port value diff --git a/man/ipf.5 b/man/ipf.5 index 3fd9e94abd995..1fdc4e77fde53 100644 --- a/man/ipf.5 +++ b/man/ipf.5 @@ -1,556 +1,1697 @@ .TH IPF 5 .SH NAME -ipf, ipf.conf, ipf6.conf \- IP packet filter rule syntax +ipf, ipf.conf \- IPFilter firewall rules file format .SH DESCRIPTION .PP -A rule file for \fBipf\fP may have any name or even be stdin. As -\fBipfstat\fP produces parsable rules as output when displaying the internal -kernel filter lists, it is quite plausible to use its output to feed back -into \fBipf\fP. Thus, to remove all filters on input packets, the following -could be done: +The ipf.conf file is used to specify rules for the firewall, packet +authentication and packet accounting components of IPFilter. To load rules +specified in the ipf.conf file, the ipf(8) program is used. +.PP +For use as a firewall, there are two important rule types: those that block +and drop packets (block rules) and those that allow packets through (pass +rules.) Accompanying the decision to apply is a collection of statements +that specify under what conditions the result is to be applied and how. +.PP +The simplest rules that can be used in ipf.conf are expressed like this: +.PP .nf - -\fC# ipfstat \-i | ipf \-rf \-\fP +block in all +pass out all .fi -.SH GRAMMAR .PP -The format used by \fBipf\fP for construction of filtering rules can be -described using the following grammar in BNF: -\fC +Each rule must contain at least the following three components +.RS +.IP * +a decision keyword (pass, block, etc.) +.IP * +the direction of the packet (in or out) +.IP * +address patterns or "all" to match any address information +.RE +.SS Long lines +.PP +For rules lines that are particularly long, it is possible to split +them over multiple lines implicity like this: +.PP .nf -filter-rule = [ insert ] action in-out [ options ] [ tos ] [ ttl ] - [ proto ] ip [ group ]. - -insert = "@" decnumber . -action = block | "pass" | log | "count" | skip | auth | call . -in-out = "in" | "out" . -options = [ log ] [ tag ] [ "quick" ] [ "on" interface-name [ dup ] - [ froute ] [ replyto ] ] . -tos = "tos" decnumber | "tos" hexnumber . -ttl = "ttl" decnumber . -proto = "proto" protocol . -ip = srcdst [ flags ] [ with withopt ] [ icmp ] [ keep ] . -group = [ "head" decnumber ] [ "group" decnumber ] . - -block = "block" [ return-icmp[return-code] | "return-rst" ] . -log = "log" [ "body" ] [ "first" ] [ "or-block" ] [ "level" loglevel ] . -tag = "tag" tagid . -skip = "skip" decnumber . -auth = "auth" | "preauth" . -call = "call" [ "now" ] function-name . -dup = "dup-to" interface-name [ ":" ipaddr ] . -froute = "fastroute" | "to" interface-name [ ":" ipaddr ] . -replyto = "reply-to" interface-name [ ":" ipaddr ] . -protocol = "tcp/udp" | "udp" | "tcp" | "icmp" | decnumber . -srcdst = "all" | fromto . -fromto = "from" [ "!" ] object "to" [ "!" ] object . - -return-icmp = "return-icmp" | "return-icmp-as-dest" . -return-code = "(" icmp-code ")" . -object = addr [ port-comp | port-range ] . -addr = "any" | nummask | host-name [ "mask" ipaddr | "mask" hexnumber ] . -addr = "any" | "<thishost>" | nummask | - host-name [ "mask" ipaddr | "mask" hexnumber ] . -port-comp = "port" compare port-num . -port-range = "port" port-num range port-num . -flags = "flags" flag { flag } [ "/" flag { flag } ] . -with = "with" | "and" . -icmp = "icmp-type" icmp-type [ "code" decnumber ] . -return-code = "(" icmp-code ")" . -keep = "keep" "state" [ "(" state-options ")" ] | "keep" "frags" . -loglevel = facility"."priority | priority . - -nummask = host-name [ "/" decnumber ] . -host-name = ipaddr | hostname | "any" . -ipaddr = host-num "." host-num "." host-num "." host-num . -host-num = digit [ digit [ digit ] ] . -port-num = service-name | decnumber . -state-options = state-opts [ "," state-options ] . - -state-opts = "age" decnumber [ "/" decnumber ] | "strict" | - "no-icmp-err" | "limit" decnumber | "newisn" | "sync" . -withopt = [ "not" | "no" ] opttype [ withopt ] . -opttype = "ipopts" | "short" | "frag" | "opt" optname . -optname = ipopts [ "," optname ] . -ipopts = optlist | "sec-class" [ secname ] . -secname = seclvl [ "," secname ] . -seclvl = "unclass" | "confid" | "reserv-1" | "reserv-2" | "reserv-3" | - "reserv-4" | "secret" | "topsecret" . -icmp-type = "unreach" | "echo" | "echorep" | "squench" | "redir" | - "timex" | "paramprob" | "timest" | "timestrep" | "inforeq" | - "inforep" | "maskreq" | "maskrep" | decnumber . -icmp-code = decumber | "net-unr" | "host-unr" | "proto-unr" | "port-unr" | - "needfrag" | "srcfail" | "net-unk" | "host-unk" | "isolate" | - "net-prohib" | "host-prohib" | "net-tos" | "host-tos" | - "filter-prohib" | "host-preced" | "cutoff-preced" . -optlist = "nop" | "rr" | "zsu" | "mtup" | "mtur" | "encode" | "ts" | - "tr" | "sec" | "lsrr" | "e-sec" | "cipso" | "satid" | "ssrr" | - "addext" | "visa" | "imitd" | "eip" | "finn" . -facility = "kern" | "user" | "mail" | "daemon" | "auth" | "syslog" | - "lpr" | "news" | "uucp" | "cron" | "ftp" | "authpriv" | - "audit" | "logalert" | "local0" | "local1" | "local2" | - "local3" | "local4" | "local5" | "local6" | "local7" . -priority = "emerg" | "alert" | "crit" | "err" | "warn" | "notice" | - "info" | "debug" . - -hexnumber = "0" "x" hexstring . -hexstring = hexdigit [ hexstring ] . -decnumber = digit [ decnumber ] . - -compare = "=" | "!=" | "<" | ">" | "<=" | ">=" | "eq" | "ne" | "lt" | - "gt" | "le" | "ge" . -range = "<>" | "><" . -hexdigit = digit | "a" | "b" | "c" | "d" | "e" | "f" . -digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" . -flag = "F" | "S" | "R" | "P" | "A" | "U" . -.fi -.PP -This syntax is somewhat simplified for readability, some combinations -that match this grammar are disallowed by the software because they do -not make sense (such as tcp \fBflags\fP for non-TCP packets). -.SH FILTER RULES -.PP -The "briefest" valid rules are (currently) no-ops and are of the form: -.nf - block in all - pass in all - log out all - count in all -.fi -.PP -Filter rules are checked in order, with the last matching rule -determining the fate of the packet (but see the \fBquick\fP option, -below). -.PP -Filters are installed by default at the end of the kernel's filter -lists, prepending the rule with \fB@n\fP will cause it to be inserted -as the n'th entry in the current list. This is especially useful when -modifying and testing active filter rulesets. See ipf(8) for more -information. -.SH ACTIONS -.PP -The action indicates what to do with the packet if it matches the rest -of the filter rule. Each rule MUST have an action. The following -actions are recognised: -.TP -.B block -indicates that the packet should be flagged to be dropped. In response -to blocking a packet, the filter may be instructed to send a reply -packet, either an ICMP packet (\fBreturn-icmp\fP), an ICMP packet -masquerading as being from the original packet's destination -(\fBreturn-icmp-as-dest\fP), or a TCP "reset" (\fBreturn-rst\fP). An -ICMP packet may be generated in response to any IP packet, and its -type may optionally be specified, but a TCP reset may only be used -with a rule which is being applied to TCP packets. When using -\fBreturn-icmp\fP or \fBreturn-icmp-as-dest\fP, it is possible to specify -the actual unreachable `type'. That is, whether it is a network -unreachable, port unreachable or even administratively -prohibited. This is done by enclosing the ICMP code associated with -it in parenthesis directly following \fBreturn-icmp\fP or -\fBreturn-icmp-as-dest\fP as follows: -.nf - block return-icmp(11) ... -.fi -.PP -Would return a Type-Of-Service (TOS) ICMP unreachable error. -.TP -.B pass -will flag the packet to be let through the filter. -.TP -.B log -causes the packet to be logged (as described in the LOGGING section -below) and has no effect on whether the packet will be allowed through -the filter. -.TP -.B count -causes the packet to be included in the accounting statistics kept by -the filter, and has no effect on whether the packet will be allowed through -the filter. These statistics are viewable with ipfstat(8). -.TP -.B call -this action is used to invoke the named function in the kernel, which -must conform to a specific calling interface. Customised actions and -semantics can thus be implemented to supplement those available. This -feature is for use by knowledgeable hackers, and is not currently -documented. -.TP -.B "skip <n>" -causes the filter to skip over the next \fIn\fP filter rules. If a rule is -inserted or deleted inside the region being skipped over, then the value of -\fIn\fP is adjusted appropriately. -.TP -.B auth -this allows authentication to be performed by a user-space program running -and waiting for packet information to validate. The packet is held for a -period of time in an internal buffer whilst it waits for the program to return -to the kernel the \fIreal\fP flags for whether it should be allowed through -or not. Such a program might look at the source address and request some sort -of authentication from the user (such as a password) before allowing the -packet through or telling the kernel to drop it if from an unrecognised source. -.TP -.B preauth -tells the filter that for packets of this class, it should look in the -pre-authenticated list for further clarification. If no further matching -rule is found, the packet will be dropped (the FR_PREAUTH is not the same -as FR_PASS). If a further matching rule is found, the result from that is -used in its instead. This might be used in a situation where a person -\fIlogs in\fP to the firewall and it sets up some temporary rules defining -the access for that person. -.PP -The next word must be either \fBin\fP or \fBout\fP. Each packet -moving through the kernel is either inbound (just been received on an -interface, and moving towards the kernel's protocol processing) or -outbound (transmitted or forwarded by the stack, and on its way to an -interface). There is a requirement that each filter rule explicitly -state which side of the I/O it is to be used on. -.SH OPTIONS -.PP -The list of options is brief, and all are indeed optional. Where -options are used, they must be present in the order shown here. These -are the currently supported options: -.TP -.B log -indicates that, should this be the last matching rule, the packet -header will be written to the \fBipl\fP log (as described in the -LOGGING section below). -.TP -.B tag tagid -indicates that, if this rule causes the packet to be logged or entered -in the state table, the tagid will be logged as part of the log entry. -This can be used to quickly match "similar" rules in scripts that post -process the log files for e.g. generation of security reports or accounting -purposes. The tagid is a 32 bit unsigned integer. -.TP -.B quick -allows "short-cut" rules in order to speed up the filter or override -later rules. If a packet matches a filter rule which is marked as -\fBquick\fP, this rule will be the last rule checked, allowing a -"short-circuit" path to avoid processing later rules for this -packet. The current status of the packet (after any effects of the -current rule) will determine whether it is passed or blocked. +pass in on bgeo proto tcp from 1.1.1.1 port > 1000 + to 2.2.2.2 port < 5000 flags S keep state +.fi +.PP +or explicitly using the backslash ('\\') character: +.PP +.nf +pass in on bgeo proto tcp from 1.1.1.1 port > 1000 \\ + to 2.2.2.2 port < 5000 flags S keep state +.fi +.SS Comments +.PP +Comments in the ipf.conf file are indicated by the use of the '#' character. +This can either be at the start of the line, like this: +.PP +.nf +# Allow all ICMP packets in +pass in proto icmp from any to any +.fi +.PP +Or at the end of a like, like this: +.PP +.nf +pass in proto icmp from any to any # Allow all ICMP packets in +.fi +.SH Firewall rules +.PP +This section goes into detail on how to construct firewall rules that +are placed in the ipf.conf file. +.PP +It is beyond the scope of this document to describe what makes a good +firewall rule set or which packets should be blocked or allowed in. +Some suggestions will be provided but further reading is expected to +fully understand what is safe and unsafe to allow in/out. +.SS Filter rule keywords +.PP +The first word found in any filter rule describes what the eventual outcome +of a packet that matches it will be. Descriptions of the many and various +sections that can be used to match on the contents of packet headers will +follow on below. +.PP +The complete list of keywords, along with what they do is as follows: +.RS +.HP +pass +rules that match a packet indicate to ipfilter that it should be +allowed to continue on in the direction it is flowing. +.HP +block +rules are used when it is desirable to prevent a packet from going +any further. Packets that are blocked on the "in" side are never seen by +TCP/IP and those that are blocked going "out" are never seen on the wire. +.HP +log +when IPFilter successfully matches a packet against a log rule a log +record is generated and made available for ipmon(8) to read. These rules +have no impact on whether or not a packet is allowed through or not. +So if a packet first matched a block rule and then matched a log rule, +the status of the packet after the log rule is that it will still be +blocked. +.HP +count +rules provide the administrator with the ability to count packets and +bytes that match the criteria laid out in the configuration file. +The count rules are applied after NAT and filter rules on the inbound +path. For outbound packets, count rules are applied before NAT and +before the packet is dropped. Thus the count rule cannot be used as +a true indicator of link layer +.HP +auth +rules cause the matching packet to be queued up for processing by a +user space program. The user space program is responsible for making +an ioctl system call to collect the information about the queued +packet and another ioctl system call to return the verdict (block, +pass, etc) on what to do with the packet. In the event that the queue +becomes full, the packets will end up being dropped. +.HP +call +provides access to functions built into IPFilter that allow for more +complex actions to be taken as part of the decision making that goes +with the rule. +.HP +decapsulate +rules instruct ipfilter to remove any +other headers (IP, UDP, AH) and then process what is inside as a new packet. +For non-UDP packets, there are builtin checks that are applied in addition +to whatever is specified in the rule, to only allow decapsulation of +recognised protocols. After decapsulating the inner packet, any filtering +result that is applied to the inner packet is also applied to the other +packet. +.PP +The default way in which filter rules are applied is for the last +matching rule to be used as the decision maker. So even if the first +rule to match a packet is a pass, if there is a later matching rule +that is a block and no further rules match the packet, then it will +be blocked. +.SS Matching Network Interfaces +.PP +On systems with more than one network interface, it is necessary +to be able to specify different filter rules for each of them. +In the first instance, this is because different networks will send us +packets via each network interface but it is also because of the hosts, +the role and the resulting security policy that we need to be able to +distinguish which network interface a packet is on. +.PP +To accomodate systems where the presence of a network interface is +dynamic, it is not necessary for the network interface named in a +filter rule to be present in the system when the rule is loaded. +This can lead to silent errors being introduced and unexpected +behaviour with the simplest of keyboard mistakes - for example, +typing in hem0 instead of hme0 or hme2 instead of hme3. +.PP +On Solaris systems prior to Solaris 10 Update 4, it is not possible +to filter packets on the loopback interface (lo0) so filter rules +that specify it will have no impact on the corresponding flow of +packets. See below for Solaris specific tips on how to enable this. +.PP +Some examples of including the network interface in filter rules are: +.PP +.nf +block in on bge0 all +pass out on bge0 all +.fi +.SS Address matching (basic) +.PP +The first and most basic part of matching for filtering rules is to +specify IP addresses and TCP/UDP port numbers. The source address +information is matched by the "from" information in a filter rule +and the destination address information is matched with the "to" +information in a filter rule. +.PP +The typical format used for IP addresses is CIDR notation, where an +IP address (or network) is followed by a '/' and a number representing +the size of the netmask in bits. This notation is used for specifying +address matching in both IPv4 and IPv6. If the '/' and bitmask size +are excluded from the matching string, it is assumed that the address +specified is a host address and that the netmask applied should be +all 1's. +.PP +Some examples of this are: +.PP +.nf +pass in from 10.1.0.0/24 to any +block out from any to 10.1.1.1 +.fi +.PP +It is not possible to specify a range of addresses that does not +have a boundary that can be defined by a standard subnet mask. +.IP +.B Names instead of addresses +.RS +.PP +Hostnames, resolved either via DNS or /etc/hosts, or network names, +resolved via /etc/networks, may be used in place of actual addresses +in the filter rules. WARNING: if a hostname expands to more than one +address, only the *first* is used in building the filter rule. +.PP +Caution should be exercised when relying on DNS for filter rules in +case the sending and receiving of DNS packets is blocked when ipf(8) +is processing that part of the configuration file, leading to long +delays, if not errors, in loading the filter rules. +.RE +.SS Protocol Matching +.PP +To match packets based on TCP/UDP port information, it is first necessary +to indicate which protocol the packet must be. This is done using the +"proto" keyword, followed by either the protocol number or a name which +is mapped to the protocol number, usually through the /etc/protocols file. +.PP +.nf +pass in proto tcp from 10.1.0.0/24 to any +block out proto udp from any to 10.1.1.1 +pass in proto icmp from any to 192.168.0.0/16 +.fi +.SS Sending back error packets +.PP +When a packet is just discarded using a block rule, there is no feedback given +to the host that sent the packet. This is both good and bad. If this is the +desired behaviour and it is not desirable to send any feedback about packets +that are to be denied. The catch is that often a host trying to connect to a +TCP port or with a UDP based application will send more than one packet +because it assumes that just one packet may be discarded so a retry is +required. The end result being logs can become cluttered with duplicate +entries due to the retries. +.PP +To address this problem, a block rule can be qualified in two ways. +The first of these is specific to TCP and instructs IPFilter to send back +a reset (RST) packet. This packet indicates to the remote system that the +packet it sent has been rejected and that it shouldn't make any further +attempts to send packets to that port. Telling IPFilter to return a TCP +RST packet in response to something that has been received is achieved +with the return-rst keyword like this: +.PP +.nf +block return-rst in proto tcp from 10.0.0.0/8 to any +.fi +.PP +When sending back a TCP RST packet, IPFilter must construct a new packet +that has the source address of the intended target, not the source address +of the system it is running on (if they are different.) +.PP +For all of the other protocols handled by the IP protocol suite, to send +back an error indicating that the received packet was dropped requires +sending back an ICMP error packet. Whilst these can also be used for TCP, +the sending host may not treat the received ICMP error as a hard error +in the same way as it does the TCP RST packet. To return an ICMP error +it is necessary to place return-icmp after the block keyword like this: +.PP +.nf +block return-icmp in proto udp from any to 192.168.0.1/24 +.fi +.PP +When electing to return an ICMP error packet, it is also possible to +select what type of ICMP error is returned. Whilst the full compliment +of ICMP unreachable codes can be used by specifying a number instead of +the string below, only the following should be used in conjunction with +return-icmp. Which return code to use is a choice to be made when +weighing up the pro's and con's. Using some of the codes may make it +more obvious that a firewall is being used rather than just the host +not responding. +.RS +.HP +filter-prohib +(prohibited by filter) +sending packets to the destination given in the received packet is +prohibited due to the application of a packet filter +.HP +net-prohib +(prohibited network) +sending packets to the destination given in the received packet is +administratively prohibited. +.HP +host-unk +(host unknown) +the destination host address is not known by the system receiving +the packet and therefore cannot be reached. +.HP +host-unr +(host unreachable) +it is not possible to reach the host as given by the destination address +in the packet header. +.HP +net-unk +(network unknown) +the destination network address is not known by the system receiving +the packet and therefore cannot be reached. +.HP +net-unr +(network unreachable) +it is not possible to forward the packet on to its final destination +as given by the destination address +.HP +port-unr +(port unreachable) +there is no application using the given destination port and therefore +it is not possible to reach that port. +.HP +proto-unr +(protocol unreachable) +the IP protocol specified in the packet is not available to receive +packets. +.DE +.PP +An example that shows how to send back a port unreachable packet for +UDP packets to 192.168.1.0/24 is as follows: +.PP +.nf +block return-icmp(port-unr) in proto udp from any to 192.168.1.0/24 +.fi +.PP +In the above examples, when sending the ICMP packet, IPFilter will construct +a new ICMP packet with a source address of the network interface used to +send the packet back to the original source. This can give away that there +is an intermediate system blocking packets. To have IPFilter send back +ICMP packets where the source address is the original destination, regardless +of whether or not it is on the local host, return-icmp-as-dest is used like +this: +.PP +.nf +block return-icmp-as-dest(port-unr) in proto udp \\ + from any to 192.168.1.0/24 +.fi +.SS TCP/UDP Port Matching +.PP +Having specified which protocol is being matched, it is then possible to +indicate which port numbers a packet must have in order to match the rule. +Due to port numbers being used differently to addresses, it is therefore +possible to match on them in different ways. IPFilter allows you to use +the following logical operations: +.IP "< x" +is true if the port number is greater than or equal to x and less than or +equal to y +is true if the port number in the packet is less than x +.IP "<= x" +is true if the port number in the packet is less than or equal to x +.IP "> x" +is true if the port number in the packet is greater than x +.IP ">= x" +is true if the port number in the packet is greater or equal to x +.IP "= x" +is true if the port number in the packet is equal to x +.IP "!= x" +is true if the port number in the packet is not equal to x +.PP +Additionally, there are a number of ways to specify a range of ports: +.IP "x <> y" +is true if the port number is less than a and greater than y +.IP "x >< y" +is true if the port number is greater than x and less than y +.IP "x:y" +is true if the port number is greater than or equal to x and less than or +equal to y +.PP +Some examples of this are: +.PP +.nf +block in proto tcp from any port >= 1024 to any port < 1024 +pass in proto tcp from 10.1.0.0/24 to any port = 22 +block out proto udp from any to 10.1.1.1 port = 135 +pass in proto udp from 1.1.1.1 port = 123 to 10.1.1.1 port = 123 +pass in proto tcp from 127.0.0.0/8 to any port = 6000:6009 +.fi +.PP +If there is no desire to mention any specific source or destintion +information in a filter rule then the word "all" can be used to +indicate that all addresses are considered to match the rule. +.SS IPv4 or IPv6 +.PP +If a filter rule is constructed without any addresses then IPFilter +will attempt to match both IPv4 and IPv6 packets with it. In the +next list of rules, each one can be applied to either network protocol +because there is no address specified from which IPFilter can derive +with network protocol to expect. +.PP +.nf +pass in proto udp from any to any port = 53 +block in proto tcp from any port < 1024 to any +.fi +.PP +To explicitly match a particular network address family with a specific +rule, the family must be added to the rule. For IPv4 it is necessary to +add family inet and for IPv6, family inet6. Thus the next rule will +block all packets (both IPv4 and IPv6: +.PP +.nf +block in all +.fi +.PP +but in the following example, we block all IPv4 packets and only allow +in IPv6 packets: +.PP +.nf +block in family inet all +pass in family inet6 all +.fi +.PP +To continue on from the example where we allowed either IPv4 or IPv6 +packets to port 53 in, to change that such that only IPv6 packets to +port 53 need to allowed blocked then it is possible to add in a +protocol family qualifier: +.PP +.nf +pass in family inet6 proto udp from any to any port = 53 +.fi +.SS First match vs last match +.PP +To change the default behaviour from being the last matched rule decides +the outcome to being the first matched rule, the word "quick" is inserted +to the rule. +.SH Extended Packet Matching +.SS Beyond using plain addresses +.PP +On firewalls that are working with large numbers of hosts and networks +or simply trying to filter discretely against various hosts, it can +be an easier administration task to define a pool of addresses and have +a filter rule reference that address pool rather than have a rule for +each address. +.PP +In addition to being able to use address pools, it is possible to use +the interface name(s) in the from/to address fields of a rule. If the +name being used in the address section can be matched to any of the +interface names mentioned in the rule's "on" or "via" fields then it +can be used with one of the following keywords for extended effect: +.HP +broadcast +use the primary broadcast address of the network interface for matching +packets with this filter rule; .IP -If this option is missing, the rule is taken to be a "fall-through" -rule, meaning that the result of the match (block/pass) is saved and -that processing will continue to see if there are any more matches. -.TP -.B on -allows an interface name to be incorporated into the matching -procedure. Interface names are as printed by "netstat \-i". If this -option is used, the rule will only match if the packet is going -through that interface in the specified direction (in/out). If this -option is absent, the rule is taken to be applied to a packet -regardless of the interface it is present on (i.e. on all interfaces). -Filter rulesets are common to all interfaces, rather than having a -filter list for each interface. +.nf +pass in on fxp0 proto udp from any to fxp0/broadcast port = 123 +.fi +.HP +peer +use the peer address on point to point network interfaces for matching +packets with this filter rule. This option typically only has meaningful +use with link protocols such as SLIP and PPP. +For example, this rule allows ICMP packets from the remote peer of ppp0 +to be received if they're destined for the address assigned to the link +at the firewall end. .IP -This option is especially useful for simple IP-spoofing protection: -packets should only be allowed to pass inbound on the interface from -which the specified source address would be expected, others may be -logged and/or dropped. -.TP -.B dup-to -causes the packet to be copied, and the duplicate packet to be sent -outbound on the specified interface, optionally with the destination -IP address changed to that specified. This is useful for off-host -logging, using a network sniffer. -.TP -.B to -causes the packet to be moved to the outbound queue on the -specified interface. This can be used to circumvent kernel routing -decisions, and even to bypass the rest of the kernel processing of the -packet (if applied to an inbound rule). It is thus possible to -construct a firewall that behaves transparently, like a filtering hub -or switch, rather than a router. The \fBfastroute\fP keyword is a -synonym for this option. -.SH MATCHING PARAMETERS -.PP -The keywords described in this section are used to describe attributes -of the packet to be used when determining whether rules match or don't -match. The following general-purpose attributes are provided for -matching, and must be used in this order: -.TP -.B tos -packets with different Type-Of-Service values can be filtered. -Individual service levels or combinations can be filtered upon. The -value for the TOS mask can either be represented as a hex number or a -decimal integer value. -.TP -.B ttl -packets may also be selected by their Time-To-Live value. The value given in -the filter rule must exactly match that in the packet for a match to occur. -This value can only be given as a decimal integer value. -.TP -.B proto -allows a specific protocol to be matched against. All protocol names -found in \fB/etc/protocols\fP are recognised and may be used. -However, the protocol may also be given as a DECIMAL number, allowing -for rules to match your own protocols, or new ones which would -out-date any attempted listing. +.nf +pass in on ppp0 proto icmp from ppp0/peer to ppp0/32 +.fi +.HP +netmasked +use the primary network address, with its netmask, of the network interface +for matching packets with this filter rule. If a network interface had an +IP address of 192.168.1.1 and its netmask was 255.255.255.0 (/24), then +using the word "netmasked" after the interface name would match any +addresses that would match 192.168.1.0/24. If we assume that bge0 has +this IP address and netmask then the following two rules both serve +to produce the same effect: .IP -The special protocol keyword \fBtcp/udp\fP may be used to match either -a TCP or a UDP packet, and has been added as a convenience to save -duplication of otherwise-identical rules. -.\" XXX grammar should reflect this (/etc/protocols) -.PP -The \fBfrom\fP and \fBto\fP keywords are used to match against IP -addresses (and optionally port numbers). Rules must specify BOTH -source and destination parameters. -.PP -IP addresses may be specified in one of two ways: as a numerical -address\fB/\fPmask, or as a hostname \fBmask\fP netmask. The hostname -may either be a valid hostname, from either the hosts file or DNS -(depending on your configuration and library) or of the dotted numeric -form. There is no special designation for networks but network names -are recognised. Note that having your filter rules depend on DNS -results can introduce an avenue of attack, and is discouraged. -.PP -There is a special case for the hostname \fBany\fP which is taken to -be 0.0.0.0/0 (see below for mask syntax) and matches all IP addresses. -Only the presence of "any" has an implied mask, in all other -situations, a hostname MUST be accompanied by a mask. It is possible -to give "any" a hostmask, but in the context of this language, it is -non-sensical. -.PP -The numerical format "x\fB/\fPy" indicates that a mask of y -consecutive 1 bits set is generated, starting with the MSB, so a y value -of 16 would give 0xffff0000. The symbolic "x \fBmask\fP y" indicates -that the mask y is in dotted IP notation or a hexadecimal number of -the form 0x12345678. Note that all the bits of the IP address -indicated by the bitmask must match the address on the packet exactly; -there isn't currently a way to invert the sense of the match, or to -match ranges of IP addresses which do not express themselves easily as -bitmasks (anthropomorphization; it's not just for breakfast anymore). -.PP -If a \fBport\fP match is included, for either or both of source and -destination, then it is only applied to -.\" XXX - "may only be" ? how does this apply to other protocols? will it not match, or will it be ignored? -TCP and UDP packets. If there is no \fBproto\fP match parameter, -packets from both protocols are compared. This is equivalent to "proto -tcp/udp". When composing \fBport\fP comparisons, either the service -name or an integer port number may be used. Port comparisons may be -done in a number of forms, with a number of comparison operators, or -port ranges may be specified. When the port appears as part of the -\fBfrom\fP object, it matches the source port number, when it appears -as part of the \fBto\fP object, it matches the destination port number. -See the examples for more information. -.PP -The \fBall\fP keyword is essentially a synonym for "from any to any" -with no other match parameters. -.PP -Following the source and destination matching parameters, the -following additional parameters may be used: -.TP -.B with -is used to match irregular attributes that some packets may have -associated with them. To match the presence of IP options in general, -use \fBwith ipopts\fP. To match packets that are too short to contain -a complete header, use \fBwith short\fP. To match fragmented packets, -use \fBwith frag\fP. For more specific filtering on IP options, -individual options can be listed. +.nf +pass in on bge0 proto icmp from any to 192.168.1.0/24 +pass in on bge0 proto icmp from any to bge0/netmasked +.fi +.HP +network +using the primary network address, and its netmask, of the network interface, +construct an address for exact matching. If a network interface has an +address of 192.168.1.1 and its netmask is 255.255.255.0, using this +option would only match packets to 192.168.1.0. .IP -Before any parameter used after the \fBwith\fP keyword, the word -\fBnot\fP or \fBno\fP may be inserted to cause the filter rule to only -match if the option(s) is not present. +.nf +pass in on bge0 proto icmp from any to bge0/network +.fi +.PP +Another way to use the name of a network interface to get the address +is to wrap the name in ()'s. In the above method, IPFilter +looks at the interface names in use and to decide whether or not +the name given is a hostname or network interface name. With the +use of ()'s, it is possible to tell IPFilter that the name should +be treated as a network interface name even though it doesn't +appear in the list of network interface that the rule ias associated +with. .IP -Multiple consecutive \fBwith\fP clauses are allowed. Alternatively, -the keyword \fBand\fP may be used in place of \fBwith\fP, this is -provided purely to make the rules more readable ("with ... and ..."). -When multiple clauses are listed, all those must match to cause a -match of the rule. -.\" XXX describe the options more specifically in a separate section -.TP -.B flags -is only effective for TCP filtering. Each of the letters possible -represents one of the possible flags that can be set in the TCP -header. The association is as follows: -.LP -.nf - F - FIN - S - SYN - R - RST - P - PUSH - A - ACK - U - URG +.nf +pass in proto icmp from any to (bge0)/32 +.fi +.SS Using address pools +.PP +Rather than list out multiple rules that either allow or deny specific +addresses, it is possible to create a single object, call an address +pool, that contains all of those addresses and reference that in the +filter rule. For documentation on how to write the configuration file +for those pools and load them, see ippool.conf(5) and ippool(8). +There are two types of address pools that can be defined in ippool.conf(5): +trees and hash tables. To refer to a tree defined in ippool.conf(5), +use this syntax: +.PP +.nf +pass in from pool/trusted to any .fi +.PP +Either a name or number can be used after the '/', just so long as it +matches up with something that has already been defined in ipool.conf(5) +and loaded in with ippool(8). Loading a filter rule that references a +pool that does not exist will result in an error. +.PP +If hash tables have been used in ippool.conf(5) to store the addresses +in instead of a tree, then replace the word pool with hash: .IP -The various flag symbols may be used in combination, so that "SA" -would represent a SYN-ACK combination present in a packet. There is -nothing preventing the specification of combinations, such as "SFR", -that would not normally be generated by law-abiding TCP -implementations. However, to guard against weird aberrations, it is -necessary to state which flags you are filtering against. To allow -this, it is possible to set a mask indicating which TCP flags you wish -to compare (i.e., those you deem significant). This is done by -appending "/<flags>" to the set of TCP flags you wish to match -against, e.g.: -.LP -.nf - ... flags S - # becomes "flags S/AUPRFS" and will match - # packets with ONLY the SYN flag set. - - ... flags SA - # becomes "flags SA/AUPRFS" and will match any - # packet with only the SYN and ACK flags set. +.nf +pass in from any to hash/webservers +.fi +.PP +There are different operational characteristics with each, so there +may be some situations where a pool works better than hash and vice +versa. +.SS Matching TCP flags +.PP +The TCP header contains a field of flags that is used to decide if the +packet is a connection request, connection termination, data, etc. +By matching on the flags in conjunction with port numbers, it is +possible to restrict the way in which IPFilter allows connections to +be created. A quick overview of the TCP +flags is below. Each is listed with the letter used in IPFilter +rules, followed by its three or four letter pneumonic. +.HP +S +SYN - this bit is set when a host is setting up a connection. +The initiator typically sends a packet with the SYN bit and the +responder sends back SYN plus ACK. +.HP +A +ACK - this bit is set when the sender wishes to acknowledge the receipt +of a packet from another host +.HP +P +PUSH - this bit is set when a sending host has send some data that +is yet to be acknowledged and a reply is sought +.HP +F +FIN - this bit is set when one end of a connection starts to close +the connection down +.HP +U +URG - this bit is set to indicate that the packet contains urgent data +.HP +R +RST - this bit is set only in packets that are a reply to another +that has been received but is not targetted at any open port +.HP +C +CWN +.HP +E +ECN +.PP +When matching TCP flags, it is normal to just list the flag that you +wish to be set. By default the set of flags it is compared against +is "FSRPAU". Rules that say "flags S" will be displayed by ipfstat(8) +as having "flags S/FSRPAU". This is normal. +The last two flags, "C" and "E", are optional - they +may or may not be used by an end host and have no bearing on either +the acceptance of data nor control of the connection. Masking them +out with "flags S/FSRPAUCE" may cause problems for remote hosts +making a successful connection. +.PP +.nf +pass in quick proto tcp from any to any port = 22 flags S/SAFR +pass out quick proto tcp from any port = 22 to any flags SA +.fi +.PP +By itself, filtering based on the TCP flags becomes more work but when +combined with stateful filtering (see below), the situation changes. +.SS Matching on ICMP header information +.PP +The TCP and UDP are not the only protocols for which filtering beyond +just the IP header is possible, extended matching on ICMP packets is +also available. The list of valid ICMP types is different for IPv4 +vs IPv6. +.PP +As a practical example, to allow the ping command to work +against a specific target requires allowing two different types of +ICMP packets, like this: +.PP +.nf +pass in proto icmp from any to webserver icmp-type echo +pass out proto icmp from webserver to any icmp-type echorep +.fi +.PP +The ICMP header has two fields that are of interest for filtering: +the ICMP type and code. Filter rules can accept either a name or +number for both the type and code. The list of names supported for +ICMP types is listed below, however only ICMP unreachable errors +have named codes (see above.) +.PP +The list of ICMP types that are available for matching an IPv4 packet +are as follows: +.PP +echo (echo request), +echorep (echo reply), +inforeq (information request), +inforep (information reply), +maskreq (mask request), +maskrep (mask reply), +paramprob (parameter problem), +redir (redirect), +routerad (router advertisement), +routersol (router solicit), +squence (source quence), +timest (timestamp), +timestreq (timestamp reply), +timex (time exceeded), +unreach (unreachable). +.PP +The list of ICMP types that are available for matching an IPv6 packet +are as follows: +.PP +echo (echo request), +echorep (echo reply), +fqdnquery (FQDN query), +fqdnreply (FQDN reply), +inforeq (information request), +inforep (information reply), +listendone (MLD listener done), +listendqry (MLD listener query), +listendrep (MLD listener reply), +neighadvert (neighbour advert), +neighborsol (neighbour solicit), +paramprob (parameter problem), +redir (redirect), +renumber (router renumbering), +routerad (router advertisement), +routersol (router solicit), +timex (time exceeded), +toobig (packet too big), +unreach (unreachable, +whoreq (WRU request), +whorep (WRU reply). +.SH Stateful Packet Filtering +.PP +Stateful packet filtering is where IPFilter remembers some information from +one or more packets that it has seen and is able to apply it to future +packets that it receives from the network. +.PP +What this means for each transport layer protocol is different. +For TCP it means that if IPFilter +sees the very first packet of an attempt to make a connection, it has enough +information to allow all other subsequent packets without there needing to +be any explicit rules to match them. IPFilter uses the TCP port numbers, +TCP flags, window size and sequence numbers to determine which packets +should be matched. For UDP, only the UDP port numbers are available. +For ICMP, the ICMP types can be combined with the ICMP id field to +determine which reply packets match a request/query that has already +been seen. For all other protocols, only matching on IP address and +protocol number is available for determining if a packet received is a mate +to one that has already been let through. +.PP +The difference this makes is a reduction in the number of rules from +2 or 4 to 1. For example, these 4 rules: +.PP +.nf +pass in on bge0 proto tcp from any to any port = 22 +pass out on bge1 proto tcp from any to any port = 22 +pass in on bge1 proto tcp from any port = 22 to any +pass out on bge0 proto tcp from any port = 22 to any +.fi +.PP +can be replaced with this single rule: +.PP +.nf +pass in on bge0 proto tcp from any to any port = 22 flags S keep state +.fi +.PP +Similar rules for UDP and ICMP might be: +.PP +.nf +pass in on bge0 proto udp from any to any port = 53 keep state +pass in on bge0 proto icmp all icmp-type echo keep state +.fi +.PP +When using stateful filtering with TCP it is best to add "flags S" to the +rule to ensure that state is only created when a packet is seen that is +an indication of a new connection. Although IPFilter can gather some +information from packets in the middle of a TCP connection to do stateful +filtering, there are some options that are only sent at the start of the +connection which alter the valid window of what TCP accepts. The end result +of trying to pickup TCP state in mid connection is that some later packets +that are part of the connection may not match the known state information +and be dropped or blocked, causing problems. If a TCP packet matches IP +addresses and port numbers but does not fit into the recognised window, +it will not be automatically allowed and will be flagged inside of +IPFitler as "out of window" (oow). See below, "Extra packet attributes", +for how to match on this attribute. +.PP +Once a TCP connection has reached the established state, the default +timeout allows for it to be idle for 5 days before it is removed from +the state table. The timeouts for the other TCP connection states +vary from 240 seconds to 30 seconds. +Both UDP and ICMP state entries have asymetric timeouts where the timeout +set upon seeing packets in the forward direction is much larger than +for the reverse direction. For UDP the default timeouts are 120 and +12 seconds, for ICMP 60 and 6 seconds. This is a reflection of the +use of these protocols being more for query-response than for ongoing +connections. For all other protocols the +timeout is 60 seconds in both directions. +.SS Stateful filtering options +.PP +The following options can be used with stateful filtering: +.HP +limit +limit the number of state table entries that this rule can create to +the number given after limit. A rule that has a limit specified is +always permitted that many state table entries, even if creating an +additional entry would cause the table to have more entries than the +otherwise global limit. +.IP +.nf +pass ... keep state(limit 100) +.fi +.HP +age +sets the timeout for the state entry when it sees packets going through +it. Additionally it is possible to set the tieout for the reply packets +that come back through the firewall to a different value than for the +forward path. allowing a short timeout to be set after the reply has +been seen and the state no longer required. +.RS +.PP +.nf +pass in quick proto icmp all icmp-type echo \\ + keep state (age 3) +pass in quick proto udp from any \\ + to any port = 53 keep state (age 30/1) +.fi +.RE +.HP +strict +only has an impact when used with TCP. It forces all packets that are +allowed through the firewall to be sequential: no out of order delivery +of packets is allowed. This can cause significant slowdown for some +connections and may stall others. Use with caution. +.IP +.nf +pass in proto tcp ... keep state(strict) +.fi +.HP +noicmperr +prevents ICMP error packets from being able to match state table entries +created with this flag using the contents of the original packet included. +.IP +.nf +pass ... keep state(noicmperr) +.fi +.HP +sync +indicates to IPFilter that it needs to provide information to the user +land daemons responsible for syncing other machines state tables up +with this one. +.IP +.nf +pass ... keep state(sync) +.fi +.HP +nolog +do not generate any log records for the creation or deletion of state +table entries. +.IP +.nf +pass ... keep state(nolog) +.fi +.HP +icmp-head +rather than just precent ICMP error packets from being able to match +state table entries, allow an ACL to be processed that can filter in or +out ICMP error packets based as you would with normal firewall rules. +The icmp-head option requires a filter rule group number or name to +be present, just as you would use with head. +.RS +.PP +.nf +pass in quick proto tcp ... keep state(icmp-head 101) +block in proto icmp from 10.0.0.0/8 to any group 101 +.fi +.RE +.HP +max-srcs +allows the number of distinct hosts that can create a state entry to +be defined. +.IP +.nf +pass ... keep state(max-srcs 100) +pass ... keep state(limit 1000, max-srcs 100) +.fi +.HP +max-per-src +whilst max-srcs limits the number of individual hosts that may cause +the creation of a state table entry, each one of those hosts is still +table to fill up the state table with new entries until the global +maximum is reached. This option allows the number of state table entries +per address to be limited. +.IP +.nf +pass ... keep state(max-srcs 100, max-per-src 1) +pass ... keep state(limit 100, max-srcs 100, max-per-src 1) +.fi +.IP +Whilst these two rules might seem identical, in that they both +ultimately limit the number of hosts and state table entries created +from the rule to 100, there is a subtle difference: the second will +always allow up to 100 state table entries to be created whereas the +first may not if the state table fills up from other rules. +.IP +Further, it is possible to specify a netmask size after the per-host +limit that enables the per-host limit to become a per-subnet or +per-network limit. +.IP +.nf +pass ... keep state(max-srcs 100, max-per-src 1/24) +.fi +.IP +If there is no IP protocol implied by addresses or other features of +the rule, IPFilter will assume that no netmask is an all ones netmask +for both IPv4 and IPv6. +.SS Tieing down a connection +.PP +For any connection that transits a firewall, each packet will be seen +twice: once going in and once going out. Thus a connection has 4 flows +of packets: +.HP +forward +inbound packets +.HP +forward +outbound packets +.HP +reverse +inbound packets +.HP +reverse +outbound packets +.PP +IPFilter allows you to define the network interface to be used at all +four points in the flow of packets. For rules that match inbound packets, +out-via is used to specify which interfaces the packets go out, For rules +that match outbound packets, in-via is used to match the inbound packets. +In each case, the syntax generalises to this: +.PP +.nf +pass ... in on forward-in,reverse-in \\ + out-via forward-out,reverse-out ... - ... flags S/SA - # will match any packet with just the SYN flag set - # out of the SYN-ACK pair; the common "establish" - # keyword action. "S/SA" will NOT match a packet - # with BOTH SYN and ACK set, but WILL match "SFP". -.fi -.TP -.B icmp-type -is only effective when used with \fBproto icmp\fP and must NOT be used -in conjunction with \fBflags\fP. There are a number of types, which can be -referred to by an abbreviation recognised by this language, or the numbers -with which they are associated can be used. The most important from -a security point of view is the ICMP redirect. -.SH KEEP HISTORY -.PP -The second last parameter which can be set for a filter rule is whether or not -to record historical information for that packet, and what sort to keep. The -following information can be kept: -.TP -.B state -keeps information about the flow of a communication session. State can -be kept for TCP, UDP, and ICMP packets. -.TP -.B frags -keeps information on fragmented packets, to be applied to later -fragments. -.PP -allowing packets which match these to flow straight through, rather -than going through the access control list. -.SH GROUPS -The last pair of parameters control filter rule "grouping". By default, all -filter rules are placed in group 0 if no other group is specified. To add a -rule to a non-default group, the group must first be started by creating a -group \fIhead\fP. If a packet matches a rule which is the \fIhead\fP of a -group, the filter processing then switches to the group, using that rule as -the default for the group. If \fBquick\fP is used with a \fBhead\fP rule, rule -processing isn't stopped until it has returned from processing the group. -.PP -A rule may be both the head for a new group and a member of a non-default -group (\fBhead\fP and \fBgroup\fP may be used together in a rule). -.TP -.B "head <n>" -indicates that a new group (number n) should be created. -.TP -.B "group <n>" -indicates that the rule should be put in group (number n) rather than group 0. -.SH LOGGING -.PP -When a packet is logged, with either the \fBlog\fP action or option, -the headers of the packet are written to the \fBipl\fP packet logging -pseudo-device. Immediately following the \fBlog\fP keyword, the -following qualifiers may be used (in order): -.TP -.B body -indicates that the first 128 bytes of the packet contents will be -logged after the headers. -.TP -.B first -If log is being used in conjunction with a "keep" option, it is recommended -that this option is also applied so that only the triggering packet is logged -and not every packet which thereafter matches state information. -.TP -.B or-block -indicates that, if for some reason the filter is unable to log the -packet (such as the log reader being too slow) then the rule should be -interpreted as if the action was \fBblock\fP for this packet. -.TP -.B "level <loglevel>" -indicates what logging facility and priority, or just priority with -the default facility being used, will be used to log information about -this packet using ipmon's -s option. -.PP -See ipl(4) for the format of records written -to this device. The ipmon(8) program can be used to read and format -this log. -.SH EXAMPLES -.PP -The \fBquick\fP option is good for rules such as: -\fC -.nf -block in quick from any to any with ipopts -.fi -.PP -which will match any packet with a non-standard header length (IP -options present) and abort further processing of later rules, -recording a match and also that the packet should be blocked. -.PP -The "fall-through" rule parsing allows for effects such as this: -.LP -.nf - block in from any to any port < 6000 - pass in from any to any port >= 6000 - block in from any to any port > 6003 -.fi -.PP -which sets up the range 6000-6003 as being permitted and all others being -denied. Note that the effect of the first rule is overridden by subsequent -rules. Another (easier) way to do the same is: -.LP -.nf - block in from any to any port 6000 <> 6003 - pass in from any to any port 5999 >< 6004 -.fi -.PP -Note that both the "block" and "pass" are needed here to effect a -result as a failed match on the "block" action does not imply a pass, -only that the rule hasn't taken effect. To then allow ports < 1024, a -rule such as: -.LP -.nf - pass in quick from any to any port < 1024 -.fi -.PP -would be needed before the first block. To create a new group for -processing all inbound packets on le0/le1/lo0, with the default being to block -all inbound packets, we would do something like: -.LP -.nf - block in all - block in quick on le0 all head 100 - block in quick on le1 all head 200 - block in quick on lo0 all head 300 +pass ... out on forward-out,reverse-out \\ + in-via forward-in,reverse-in ... +.fi +.PP +An example that pins down all 4 network interfaces used by an ssh +connection might look something like this: +.PP +.nf +pass in on bge0,bge1 out-via bge1,bge0 proto tcp \\ + from any to any port = 22 flags S keep state +.fi +.SS Working with packet fragments +.PP +Fragmented packets result in 1 packet containing all of the layer 3 and 4 +header information whilst the data is split across a number of other packets. +.PP +To enforce access control on fragmented packets, one of two approaches +can be taken. The first is to allow through all of the data fragments +(those that made up the body of the original packet) and rely on matching +the header information in the "first" fragment, when it is seen. The +reception of body fragments without the first will result in the receiving +host being unable to completely reassemble the packet and discarding all +of the fragments. The following three rules deny all fragmented packets +from being received except those that are UDP and even then only allows +those destined for port 2049 to be completed. +.PP +.nf +block in all with frags +pass in proto udp from any to any with frag-body +pass in proto udp from any to any port = 2049 with frags +.fi +.PP +Another mechanism that is available is to track "fragment state". +This relies on the first fragment of a packet that arrives to be +the fragment that contains all of the layer 3 and layer 4 header +information. With the receipt of that fragment before any other, +it is possible to determine which other fragments are to be allowed +through without needing to explicitly allow all fragment body packets. +An example of how this is done is as follows: +.PP +.nf +pass in proto udp from any prot = 2049 to any with frags keep fags +.fi +.SH Building a tree of rules +.PP +Writing your filter rules as one long list of rules can be both inefficient +in terms of processing the rules and difficult to understand. To make the +construction of filter rules easier, it is possible to place them in groups. +A rule can be both a member of a group and the head of a new group. +.PP +Using filter groups requires at least two rules: one to be in the group +one one to send matchign packets to the group. If a packet matches a +filtre rule that is a group head but does not match any of the rules +in that group, then the packet is considered to have matched the head +rule. +.PP +Rules that are a member of a group contain the word group followed by +either a name or number that defines which group they're in. Rules that +form the branch point or starting point for the group must use the +word head, followed by either a group name or number. If rules are +loaded in that define a group but there is no matching head then they +will effectively be orphaned rules. It is possible to have more than +one head rule point to the same group, allowing groups to be used +like subroutines to implement specific common policies. +.PP +A common use of filter groups is to define head rules that exist in the +filter "main line" for each direction with the interfaces in use. For +example: +.PP +.nf +block in quick on bge0 all head 100 +block out quick on bge0 all head 101 +block in quick on fxp0 all head internal-in +block out quick on fxp0 all head internal-out +pass in quick proto icmp all icmp-type echo group 100 +.fi +.PP +In the above set of rules, there are four groups defined but only one +of them has a member rule. The only packets that would be allowed +through the above ruleset would be ICMP echo packets that are +received on bge0. +.PP +Rules can be both a member of a group and the head of a new group, +allowing groups to specialise. +.PP +.nf +block in quick on bge0 all head 100 +block in quick proto tcp all head 1006 group 100 +.fi +.PP +Another use of filter rule groups is to provide a place for rules to +be dynamically added without needing to worry about their specific +ordering amongst the entire ruleset. For example, if I was using this +simple ruleset: +.PP +.nf +block in quick all with bad +block in proto tcp from any to any port = smtp head spammers +pass in quick proto tcp from any to any port = smtp flags S keep state +.fi +.PP +and I was getting lots of connections to my email server from 10.1.1.1 +to deliver spam, I could load the following rule to complement the above: +.IP +.nf +block in quick from 10.1.1.1 to any group spammers .fi +.SS Decapsulation .PP +Rule groups also form a different but vital role for decapsulation rules. +With the following simple rule, if IPFilter receives an IP packet that has +an AH header as its layer 4 payload, IPFilter would adjust its view of the +packet internally and then jump to group 1001 using the data beyond the +AH header as the new transport header. +.PP +.nf +decapsulate in proto ah all head 1001 +.fi +.PP +For protocols that +are recognised as being used with tunnelling or otherwise encapsulating +IP protocols, IPFilter is able to decide what it has on the inside +without any assistance. Some tunnelling protocols use UDP as the +transport mechanism. In this case, it is necessary to instruct IPFilter +as to what protocol is inside UDP. +.PP +.nf +decapsulate l5-as(ip) in proto udp from any \\ + to any port = 1520 head 1001 +.fi +.PP +Currently IPFilter only supports finding IPv4 and IPv6 headers +directly after the UDP header. +.PP +If a packet matches a decapsulate rule but fails to match any of the rules +that are within the specified group, processing of the packet continues +to the next rule after the decapsulate and IPFilter's internal view of the +packet is returned to what it was prior to the decapsulate rule. +.PP +It is possible to construct a decapsulate rule without the group +head at the end that ipf(8) will accept but such rules will not +result in anything happening. +.SS Policy Based Routing +.PP +With firewalls being in the position they often are, at the boundary +of different networks connecting together and multiple connections that +have different properties, it is often desirable to have packets flow +in a direction different to what the routing table instructs the kernel. +These decisions can often be extended to changing the route based on +both source and destination address or even port numbers. +.PP +To support this kind of configuration, IPFilter allows the next hop +destination to be specified with a filter rule. The next hop is given +with the interface name to use for output. The syntax for this is +interface:ip.address. It is expected that the address given as the next +hop is directly connected to the network to which the interface is. +.PP +.nf +pass in on bge0 to bge1:1.1.1.1 proto tcp \\ + from 1.1.2.3 to any port = 80 flags S keep state +.fi +.PP +When this feature is combined with stateful filtering, it becomes +possible to influence the network interface used to transmit packets +in both directions because we now have a sense for what its reverse +flow of packets is. +.PP +.nf +pass in on bge0 to bge1:1.1.1.1 reply-to hme1:2.1.1.2 \\ + proto tcp from 1.1.2.3 to any port = 80 flags S keep state +.fi +.PP +If the actions of the routing table are perfectly acceptable, but +you would like to mask the presence of the firewall by not changing +the TTL in IP packets as they transit it, IPFilter can be instructed +to do a "fastroute" action like this: +.PP +.nf +pass in on bge0 fastroute proto icmp all +.fi +.PP +This should be used with caution as it can lead to endless packet +loops. Additionally, policy based routing does not change the IP +header's TTL value. +.PP +A variation on this type of rule supports a duplicate of the original +packet being created and sent out a different network. This can be +useful for monitoring traffic and other purposes. +.PP +.nf +pass in on bge0 to bge1:1.1.1.1 reply-to hme1:2.1.1.2 \\ + dup-to fxp0:10.0.0.1 proto tcp from 1.1.2.3 \\ + to any port = 80 flags S keep state +.fi +.SS Matching IPv4 options +.PP +The design for IPv4 allows for the header to be upto 64 bytes long, +however most traffic only uses the basic header which is 20 bytes long. +The other 44 bytes can be uesd to store IP options. These options are +generally not necessary for proper interaction and function on the +Internet today. For most people it is sufficient to block and drop +all packets that have any options set. This can be achieved with this +rule: +.PP +.nf +block in quick all with ipopts +.fi +.PP +This rule is usually placed towards the top of the configuration +so that all incoming packets are blocked. +.PP +If you wanted to allow in a specific IP option type, the syntax +changes slightly: +.PP +.nf +pass in quick proto igmp all with opt rtralrt +.fi +.PP +The following is a list of IP options that most people encounter and +what their use/threat is. +.HP +lsrr +(loose source route) the sender of the packet includes a list of addresses +that they wish the packet to be routed through to on the way to the +destination. Because replies to such packets are expected to use the +list of addresses in reverse, hackers are able to very effectively use +this header option in address spoofing attacks. +.HP +rr +(record route) the sender allocates some buffer space for recording the +IP address of each router that the packet goes through. This is most often +used with ping, where the ping response contains a copy of all addresses +from the original packet, telling the sender what route the packet took +to get there. Due to performance and security issues with IP header +options, this is almost no longer used. +.HP +rtralrt +(router alert) this option is often used in IGMP messages as a flag to +routers that the packet needs to be handled differently. It is unlikely +to ever be received from an unknown sender. It may be found on LANs or +otherwise controlled networks where the RSVP protocol and multicast +traffic is in heavy use. +.HP +ssrr +(strict source route) the sender of the packet includes a list of addresses +that they wish the packet to be routed through to on the way to the +destination. Where the lsrr option allows the sender to specify only +some of the nodes the packet must go through, with the ssrr option, +every next hop router must be specified. +.PP +The complete list of IPv4 options that can be matched on is: +addext (Address Extention), +cipso (Classical IP Security Option), +dps (Dynamic Packet State), +e-sec (Extended Security), +eip (Extended Internet Protocol), +encode (ENCODE), +finn (Experimental Flow Control), +imitd (IMI Traffic Descriptor), +lsrr (Loose Source Route), +mtup (MTU Probe - obsolete), +mtur (MTU response - obsolete), +nop (No Operation), +nsapa (NSAP Address), +rr (Record Route), +rtralrt (Router Alert), +satid (Stream Identifier), +sdb (Selective Directed Broadcast), +sec (Security), +ssrr (Strict Source Route), +tr (Tracerote), +ts (Timestamp), +ump (Upstream Multicast Packet), +visa (Experimental Access Control) +and zsu (Experimental Measurement). +.SS Security with CIPSO and IPSO +.PP +IPFilter supports filtering on IPv4 packets using security attributes embedded +in the IP options part of the packet. These options are usually only used on +networks and systems that are using lablled security. Unless you know that +you are using labelled security and your networking is also labelled, it +is highly unlikely that this section will be relevant to you. +.PP +With the traditional IP Security Options (IPSO), packets can be tagged with +a security level. The following keywords are recognised and match with the +relevant RFC with respect to the bit patterns matched: +confid (confidential), +rserve-1 (1st reserved value), +rserve-2 (2nd reserved value), +rserve-3 (3rd reserved value), +rserve-4 (4th reserved value), +secret (secret), +topsecret (top secret), +unclass (unclassified). +.PP +.nf +block in quick all with opt sec-class unclass +pass in all with opt sec-class secret +.fi +.SS Matching IPv6 extension headers +.PP +Just as it is possible to filter on the various IPv4 header options, +so too it is possible to filter on the IPv6 extension headers that are +placed between the IPv6 header and the transport protocol header. +.PP +dstopts (destination options), +esp (encrypted, secure, payload), +frag (fragment), +hopopts (hop-by-hop options), +ipv6 (IPv6 header), +mobility (IP mobility), +none, +routing. +.SS Logging +.PP +There are two ways in which packets can be logged with IPFilter. The +first is with a rule that specifically says log these types of packets +and the second is a qualifier to one of the other keywords. Thus it is +possible to both log and allow or deny a packet with a single rule. +.PP +.nf +pass in log quick proto tcp from any to any port = 22 +.fi +.PP +When using stateful filtering, the log action becomes part of the result +that is remembered about a packet. Thus if the above rule was qualified +with keep state, every packet in the connection would be logged. To only +log the first packet from every packet flow tracked with keep state, it +is necessary to indicate to IPFilter that you only wish to log the first +packet. +.PP +.nf +pass in log first quick proto tcp from any to any port = 22 \\ + flags S keep state +.fi +.PP +If it is a requirement that the logging provide an accurate representation +of which connections are allowed, the log action can be qualified with the +option or-block. This allows the administrator to instruct IPFilter to +block the packet if the attempt to record the packet in IPFilter's kernel +log records (which have an upper bound on size) failed. Unless the system +shuts down or reboots, once a log record is written into the kernel buffer, +it is there until ipmon(8) reads it. +.PP +.nf +block in log proto tcp from any to any port = smtp +pass in log or-block first quick proto tcp from any \\ + to any port = 22 flags S keep state +.fi +.PP +By default, IPFilter will only log the header portion of a packet received +on the network. A portion of the body of a packet, upto 128 bytes, can also +be logged with the body keyword. ipmon(8) will display the contents of the +portion of the body logged in hex. +.PP +.nf +block in log body proto icmp all +.fi +.PP +When logging packets from ipmon(8) to syslog, by default ipmon(8) will +control what syslog facility and priority a packet will be logged with. +This can be tuned on a per rule basis like this: +.PP +.nf +block in quick log level err all with bad +pass in log level local1.info proto tcp \\ + from any to any port = 22 flags S keep state +.fi +.PP +ipfstat(8) reports how many packets have been successfully logged and how +many failed attempts to log a packet there were. +.SS Filter rule comments +.PP +If there is a desire to associate a text string, be it an administrative +comment or otherwise, with an IPFilter rule, this can be achieved by giving +the filter rule a comment. The comment is loaded with the rule into the +kernel and can be seen when the rules are listed with ipfstat. +.PP +.nf +pass in quick proto tcp from any \\ + to port = 80 comment "all web server traffic is ok" +pass out quick proto tcp from any port = 80 \\ + to any comment "all web server traffic is ok" +.fi +.SS Tags +.PP +To enable filtering and NAT to correctly match up packets with rules, +tags can be added at with NAT (for inbound packets) and filtering (for +outbound packets.) This allows a filter to be correctly mated with its +NAT rule in the event that the NAT rule changed the packet in a way +that would mean it is not obvious what it was. +.PP +For inbound packets, IPFilter can match the tag used in the filter +rules with that set by NAT. For outbound rules, it is the reverse, +the filter sets the tag and the NAT rule matches up with it. +.PP +.nf +pass in ... match-tag(nat=proxy) +pass out ... set-tag(nat=proxy) +.fi +.PP +Another use of tags is to supply a number that is only used with logging. +When packets match these rules, the log tag is carried over into the +log file records generated by ipmon(8). With the correct use of tools +such as grep, extracting log records of interest is simplified. +.PP +.nf +block in quick log ... set-tag(log=33) +.fi +.SH Filter Rule Expiration +.PP +IPFilter allows rules to be added into the kernel that it will remove after +a specific period of time by specifying rule-ttl at the end of a rule. +When listing rules in the kernel using ipfstat(8), rules that are going +to expire will NOT display "rule-ttl" with the timeout, rather what will +be seen is a comment with how many ipfilter ticks left the rule has to +live. +.PP +The time to live is specified in seconds. +.PP +.nf +pass in on fxp0 proto tcp from any \\ + to port = 22 flags S keep state rule-ttl 30 +.fi +.SH Internal packet attributes +.PP +In addition to being able to filter on very specific network and transport +header fields, it is possible to filter on other attributes that IPFilter +attaches to a packet. These attributes are placed in a rule after the +keyword "with", as can be seen with frags and frag-body above. The +following is a list of the other attributes available: +.HP +oow +the packet's IP addresses and TCP ports match an existing entry in the +state table but the sequence numbers indicate that it is outside of the +accepted window. +.IP +.nf +block return-rst in quick proto tcp from any to any with not oow +.fi +.HP +bcast +this is set by IPFilter when it receives notification that the link +layer packet was a broadcast packet. No checking of the IP addresses +is performned to determine if it is a broadcast destination or not. +.IP +.nf +block in quick proto udp all with bcast +.fi +.HP +mcast +this is set by IPFilter when it receives notification that the link +layer packet was a multicast packet. No checking of the IP addresses +is performned to determine if it is a multicast destination or not. +.IP +.nf +pass in quick proto udp from any to any port = dns with mcast +.fi +.HP +mbcast +can be used to match a packet that is either a multicast or broadcast +packet at the link layer, as indicated by the operating system. +.IP +.nf +pass in quick proto udp from any to any port = ntp with mbcast +.fi +.HP +nat +the packet positively matched a NAT table entry. +.HP +bad +sanity checking of the packet failed. This could indicate that the +layer 3/4 headers are not properly formed. +.HP +bad-src +when reverse path verification is enabled, this flag will be set when +the interface the packet is received on does not match that which would +be used to send a packet out of to the source address in the received +packet. +.HP +bad-nat +an attempt to perform NAT on the packet failed. +.HP +not +each one of the attributes matched using the "with" keyword can also be +looked for to not be present. For example, to only allow in good packets, +I can do this: +.PP +.nf +block in all +pass in all with not bad +.fi +.SH Tuning IPFilter +.PP +The ipf.conf file can also be used to tune the behaviour of IPFilter, +allowing, for example, timeouts for the NAT/state table(s) to be set +along with their sizes. The presence and names of tunables may change +from one release of IPFilter to the next. The tunables that can be +changed via ipf.conf is the same as those that can be seen and modified +using the -T command line option to ipf(8). +.PP +NOTE: When parsing ipf.conf, ipf(8) will apply the settings before +loading any rules. Thus if your settings are at the top, these may +be applied whilst the rules not applied if there is an error further +down in the configuration file. +.PP +To set one of the values below, the syntax is simple: "set", followed +by the name of the tuneable to set and then the value to set it to. +.PP +.nf +set state_max 9999; +set state_size 10101; +.fi +.PP +A list of the currently available variables inside IPFilter that may +be tuned from ipf.conf are as follows: +.HP +active +set through -s command line switch of ipf(8). See ipf(8) for detals. +.HP +chksrc +when set, enables reverse path verification on source addresses and +for filters to match packets with bad-src attribute. +.HP +control_forwarding +when set turns off kernel forwarding when IPFilter is disabled or unloaded. +.HP +default_pass +the default policy - whether packets are blocked or passed, etc - is +represented by the value of this variable. It is a bit field and the +bits that can be set are found in <netinet/ip_fil.h>. It is not +recommended to tune this value directly. +.HP +ftp_debug +set the debugging level of the in-kernel FTP proxy. +Debug messages will be printed to the system console. +.HP +ftp_forcepasv +when set the FTP proxy must see a PASV/EPSV command before creating +the state/NAT entries for the 227 response. +.HP +ftp_insecure +when set the FTP proxy will not wait for a user to login before allowing +data connections to be created. +.HP +ftp_pasvonly +when set the proxy will not create state/NAT entries for when it +sees either the PORT or EPRT command. +.HP +ftp_pasvrdr +when enabled causes the FTP proxy to create very insecure NAT/state +entries that will allow any connection between the client and server +hosts when a 227 reply is seen. Use with extreme caution. +.HP +ftp_single_xfer +when set the FTP proxy will only allow one data connection at a time. +.HP +hostmap_size +sets the size of the hostmap table used by NAT to store address mappings +for use with sticky rules. +.HP +icmp_ack_timeout +default timeout used for ICMP NAT/state when a reply packet is seen for +an ICMP state that already exists +.HP +icmp_minfragmtu +sets the minimum MTU that is considered acceptable in an ICMP error +before deciding it is a bad packet. +.HP +icmp_timeout +default timeout used for ICMP NAT/state when the packet matches the rule +.HP +ip_timeout +default timeout used for NAT/state entries that are not TCP/UDP/ICMP. +.HP +ipf_flags +.HP +ips_proxy_debug +this sets the debugging level for the proxy support code. +When enabled, debugging messages will be printed to the system console. +.HP +log_all +when set it changes the behaviour of "log body" to log the entire packet +rather than just the first 128 bytes. +.HP +log_size +sets the size of the in-kernel log buffer in bytes. +.HP +log_suppress +when set, IPFilter will check to see if the packet it is logging is +similar to the one it previously logged and if so, increases +the occurance count for that packet. The previously logged packet +must not have yet been read by ipmon(8). +.HP +min_ttl +is used to set the TTL value that packets below will be marked with +the low-ttl attribute. +.HP +nat_doflush +if set it will cause the NAT code to do a more aggressive flush of the +NAT table at the next opportunity. Once the flush has been done, the +value is reset to 0. +.HP +nat_lock +this should only be changed using ipfs(8) +.HP +nat_logging +when set, NAT will create log records that can be read from /dev/ipnat. +.HP +nat_maxbucket +maximum number of entries allowed to exist in each NAT hash bucket. +This prevents an attacker trying to load up the hash table with +entries in a single bucket, reducing performance. +.HP +nat_rules_size +size of the hash table to store map rules. +.HP +nat_table_max +maximum number of entries allowed into the NAT table +.HP +nat_table_size +size of the hash table used for NAT +.HP +nat_table_wm_high +when the fill percentage of the NAT table exceeds this mark, more +aggressive flushing is enabled. +.HP +nat_table_wm_low +this sets the percentage at which the NAT table's agressive flushing +will turn itself off at. +.HP +rdr_rules_size +size of the hash table to store rdr rules. +.HP +state_lock +this should only be changed using ipfs(8) +.HP +state_logging +when set, the stateful filtering will create log records +that can be read from /dev/ipstate. +.HP +state_max +maximum number of entries allowed into the state table +.HP +state_maxbucket +maximum number of entries allowed to exist in each state hash bucket. +This prevents an attacker trying to load up the hash table with +entries in a single bucket, reducing performance. +.HP +state_size +size of the hash table used for stateful filtering +.HP +state_wm_freq +this controls how often the agressive flushing should be run once the +state table exceeds state_wm_high in percentage full. +.HP +state_wm_high +when the fill percentage of the state table exceeds this mark, more +aggressive flushing is enabled. +.HP +state_wm_low +this sets the percentage at which the state table's agressive flushing +will turn itself off at. +.HP +tcp_close_wait +timeout used when a TCP state entry reaches the FIN_WAIT_2 state. +.HP +tcp_closed +timeout used when a TCP state entry is ready to be removed after either +a RST packet is seen. +.HP +tcp_half_closed +timeout used when a TCP state entry reaches the CLOSE_WAIT state. +.HP +tcp_idle_timeout +timeout used when a TCP state entry reaches the ESTABLISHED state. +.HP +tcp_last_ack +timeout used when a TCP NAT/state entry reaches the LAST_ACK state. +.HP +tcp_syn_received +timeout applied to a TCP NAT/state entry after SYN-ACK packet has been seen. +.HP +tcp_syn_sent +timeout applied to a TCP NAT/state entry after SYN packet has been seen. +.HP +tcp_time_wait +timeout used when a TCP NAT/state entry reaches the TIME_WAIT state. +.HP +tcp_timeout +timeout used when a TCP NAT/state entry reaches either the half established +state (one ack is seen after a SYN-ACK) or one side is in FIN_WAIT_1. +.HP +udp_ack_timeout +default timeout used for UDP NAT/state when a reply packet is seen for +a UDP state that already exists +.HP +udp_timeout +default timeout used for UDP NAT/state when the packet matches the rule +.HP +update_ipid +when set, turns on changing the IP id field in NAT'd packets to a random +number. +.SS Table of visible variables +.PP +A list of all of the tunables, their minimum, maximum and current +values is as follows. +.PP +.nf +Name Min Max Current +active 0 0 0 +chksrc 0 1 0 +control_forwarding 0 1 0 +default_pass 0 MAXUINT 134217730 +ftp_debug 0 10 0 +ftp_forcepasv 0 1 1 +ftp_insecure 0 1 0 +ftp_pasvonly 0 1 0 +ftp_pasvrdr 0 1 0 +ftp_single_xfer 0 1 0 +hostmap_size 1 MAXINT 2047 +icmp_ack_timeout 1 MAXINT 12 +icmp_minfragmtu 0 1 68 +icmp_timeout 1 MAXINT 120 +ip_timeout 1 MAXINT 120 +ipf_flags 0 MAXUINT 0 +ips_proxy_debug 0 10 0 +log_all 0 1 0 +log_size 0 524288 32768 +log_suppress 0 1 1 +min_ttl 0 1 4 +nat_doflush 0 1 0 +nat_lock 0 1 0 +nat_logging 0 1 1 +nat_maxbucket 1 MAXINT 22 +nat_rules_size 1 MAXINT 127 +nat_table_max 1 MAXINT 30000 +nat_table_size 1 MAXINT 2047 +nat_table_wm_high 2 100 99 +nat_table_wm_low 1 99 90 +rdr_rules_size 1 MAXINT 127 +state_lock 0 1 0 +state_logging 0 1 1 +state_max 1 MAXINT 4013 +state_maxbucket 1 MAXINT 26 +state_size 1 MAXINT 5737 +state_wm_freq 2 999999 20 +state_wm_high 2 100 99 +state_wm_low 1 99 90 +tcp_close_wait 1 MAXINT 480 +tcp_closed 1 MAXINT 60 +tcp_half_closed 1 MAXINT 14400 +tcp_idle_timeout 1 MAXINT 864000 +tcp_last_ack 1 MAXINT 60 +tcp_syn_received 1 MAXINT 480 +tcp_syn_sent 1 MAXINT 480 +tcp_time_wait 1 MAXINT 480 +tcp_timeout 1 MAXINT 480 +udp_ack_timeout 1 MAXINT 24 +udp_timeout 1 MAXINT 240 +update_ipid 0 1 0 +.fi +.SH Calling out to internal functions +.PP +IPFilter provides a pair of functions that can be called from a rule +that allow for a single rule to jump out to a group rather than walk +through a list of rules to find the group. If you've got multiple +networks, each with its own group of rules, this feature may help +provide better filtering performance. +.PP +The lookup to find which rule group to jump to is done on either the +source address or the destination address but not both. +.PP +In this example below, we are blocking all packets by default but then +doing a lookup on the source address from group 1010. The two rules in +the ipf.conf section are lone members of their group. For an incoming +packet that is from 1.1.1.1, it will go through three rules: (1) the +block rule, (2) the call rule and (3) the pass rule for group 1020. +For a packet that is from 3.3.2.2, it will also go through three rules: +(1) the block rule, (2) the call rule and (3) the pass rule for group +1030. Should a packet from 3.1.1.1 arrive, it will be blocked as it +does not match any of the entries in group 1010, leaving it to only +match the first rule. +.PP +.nf +from ipf.conf +------------- +block in all +call now srcgrpmap/1010 in all +pass in proto tcp from any to any port = 80 group 1020 +pass in proto icmp all icmp-type echo group 1030 -and to then allow ICMP packets in on le0, only, we would do: -.LP +from ippool.conf +---------------- +group-map in role=ipf number=1010 + { 1.1.1.1 group = 1020, 3.3.0.0/16 group = 1030; }; +.fi +.SS IPFilter matching expressions +.PP +An experimental feature that has been added to filter rules is to use +the same expression matching that is available with various commands +to flush and list state/NAT table entries. The use of such an expression +precludes the filter rule from using the normal IP header matching. +.PP .nf - pass in proto icmp all group 100 +pass in exp { "tcp.sport 23 or tcp.sport 50" } keep state .fi +.SS Filter rules with BPF +.PP +On platforms that have the BPF built into the kernel, IPFilter can be +built to allow BPF expressions in filter rules. This allows for packet +matching to be on arbitrary data in the packt. The use of a BPF expression +replaces all of the other protocol header matching done by IPFilter. .PP -Note that because only inbound packets on le0 are used processed by group 100, -there is no need to respecify the interface name. Likewise, we could further -breakup processing of TCP, etc, as follows: -.LP .nf - block in proto tcp all head 110 group 100 - pass in from any to any port = 23 group 110 +pass in bpf-v4 { "tcp and (src port 23 or src port 50)" } \\ + keep state .fi .PP -and so on. The last line, if written without the groups would be: -.LP +These rules tend to be +write-only because the act of compiling the filter expression into the +BPF instructions loaded into the kernel can make it difficut to +accurately reconstruct the original text filter. The end result is that +while ipf.conf() can be easy to read, understanding the output from +ipfstat might not be. +.SH VARIABLES +.PP +This configuration file, like all others used with IPFilter, supports the +use of variable substitution throughout the text. +.PP +.nf +nif="ppp0"; +pass in on $nif from any to any +.fi +.PP +would become +.PP .nf - pass in on le0 proto tcp from any to any port = telnet +pass in on ppp0 from any to any .fi .PP -Note, that if we wanted to say "port = telnet", "proto tcp" would -need to be specified as the parser interprets each rule on its own and -qualifies all service/port names with the protocol specified. +Variables can be used recursively, such as 'foo="$bar baz";', so long as +$bar exists when the parser reaches the assignment for foo. +.PP +See +.B ipf(8) +for instructions on how to define variables to be used from a shell +environment. +.DT .SH FILES -/dev/ipauth -.br -/dev/ipl -.br -/dev/ipstate -.br -/etc/hosts +/dev/ipf +/etc/ipf.conf .br -/etc/services +/usr/share/examples/ipf Directory with examples. .SH SEE ALSO -ipftest(1), iptest(1), mkfilters(1), ipf(4), ipnat(5), ipf(8), ipfstat(8) +ipf(8), ipfstat(8), ippool.conf(5), ippool(8) diff --git a/man/ipfilter.4 b/man/ipfilter.4 index b2d2f2a772458..9519db2c51e87 100644 --- a/man/ipfilter.4 +++ b/man/ipfilter.4 @@ -26,7 +26,7 @@ send back an ICMP error/TCP reset for blocked packets .IP keep packet state information for TCP, UDP and ICMP packet flows .IP -keep fragment state information for any IP packet, applying the same rule +keep fragment state information for any IP packet, applying the same rule to all fragments. .IP act as a Network Address Translator (NAT) @@ -51,7 +51,7 @@ On any arbitrary combination of TCP flags .IP "short" (fragmented) IP packets with incomplete headers can be filtered .IP -any of the 19 IP options or 8 registered IP security classes TOS (Type of +any of the 19 IP options or 8 registered IP security classes TOS (Type of Service) field in packets .PP To keep track of the performance of the IP packet filter, a logging device @@ -71,12 +71,12 @@ it matches a rule setup to look for suspicious packets .PP IP Filter keeps its own set of statistics on: .IP -packets blocked +packets blocked .IP packets (and bytes!) used for accounting .IP packets passed -.lP +.IP packets logged .IP attempts to log which failed (buffer full) @@ -85,7 +85,7 @@ and much more, for packets going both in and out. .SH Tools The current implementation provides a small set of tools, which can easily -be used and integrated with regular unix shells and tools. A brief description +be used and integrated with regular unix shells and tools. A brief description of the tools provided: .PP ipf(8) @@ -98,7 +98,7 @@ ipfs(8) is a utility to temporarily lock the IP Filter kernel tables (state tables and NAT mappings) and write them to disk. After that the system can be rebooted, and ipfs can be used to read these tables from disk and restore -them into the kernel. This way the system can be rebooted without the +them into the kernel. This way the system can be rebooted without the connections being terminated. .PP ipfstat(8) @@ -115,7 +115,7 @@ ipmon(8) reads buffered data from the logging device (default is /dev/ipl) for output to either: .IP -screen (standard output) +screen (standard output) .IP file .IP @@ -145,13 +145,13 @@ documented in ipf(4). Documentation on ioctl's and the format of data saved to the logging character device is provided in ipl(4) -so that you may develop your own applications to work with or in place of any +so that you may develop your own applications to work with or in place of any of the above. Similar, the interface to the NAT code is documented in ipnat(4). .SH PACKET PROCESSING FLOW -The following diagram illustrates the flow of TCP/IP packets through the +The following diagram illustrates the flow of TCP/IP packets through the various stages introduced by IP Filter. .PP .nf diff --git a/man/ipfilter.4.mandoc b/man/ipfilter.4.mandoc index 72534a759761f..22e1f36450b6c 100644 --- a/man/ipfilter.4.mandoc +++ b/man/ipfilter.4.mandoc @@ -30,7 +30,7 @@ send back an ICMP error/TCP reset for blocked packets .It keep packet state information for TCP, UDP and ICMP packet flows .It -keep fragment state information for any IP packet, applying the same rule +keep fragment state information for any IP packet, applying the same rule to all fragments. .It act as a Network Address Translator (NAT) @@ -57,7 +57,7 @@ On any arbitrary combination of TCP flags .It "short" (fragmented) IP packets with incomplete headers can be filtered .It -any of the 19 IP options or 8 registered IP security classes TOS (Type of +any of the 19 IP options or 8 registered IP security classes TOS (Type of Service) field in packets .El .Pp @@ -83,7 +83,7 @@ it matches a rule setup to look for suspicious packets IP Filter keeps its own set of statistics on: .Bl -bullet -offset indent -compact .It -packets blocked +packets blocked .It packets (and bytes!) used for accounting .It @@ -97,7 +97,7 @@ and much more, for packets going both in and out. .Sh Tools The current implementation provides a small set of tools, which can easily -be used and integrated with regular unix shells and tools. A brief description +be used and integrated with regular unix shells and tools. A brief description of the tools provided: .Pp .Xr ipf 8 @@ -111,7 +111,7 @@ described in is a utility to temporarily lock the IP Filter kernel tables (state tables and NAT mappings) and write them to disk. After that the system can be rebooted, and ipfs can be used to read these tables from disk and restore -them into the kernel. This way the system can be rebooted without the +them into the kernel. This way the system can be rebooted without the connections being terminated. .Pp .Xr ipfstat 8 @@ -129,7 +129,7 @@ reads buffered data from the logging device (default is /dev/ipl) for output to either: .Bl -bullet -offset indent -compact .It -screen (standard output) +screen (standard output) .It file .It @@ -152,7 +152,7 @@ aimed at. WARNING: this may crash machine(s) targeted! reads in a set of rules, from either stdin or a file and adds them to the kernels current list of active NAT rules. NAT rules can also be deleted using ipnat. The format of the configuration file to be used -with ipnat is described in +with ipnat is described in .Xr ipnat 5 . .Pp For use in your own programs (e.g. for writing of transparent application @@ -162,15 +162,15 @@ documented in Documentation on ioctl's and the format of data saved to the logging character device is provided in -.Xr ipl 4 -so that you may develop your own applications to work with or in place of any +.Xr ipl 4 +so that you may develop your own applications to work with or in place of any of the above. -Similar, the interface to the NAT code is documented in +Similar, the interface to the NAT code is documented in .Xr ipnat 4 . .Sh PACKET PROCESSING FLOW -The following diagram illustrates the flow of TCP/IP packets through the +The following diagram illustrates the flow of TCP/IP packets through the various stages introduced by IP Filter. .Pp .nf diff --git a/man/ipfstat.8 b/man/ipfstat.8 index 95cf6f37ff1f0..94a22bce5ea0c 100644 --- a/man/ipfstat.8 +++ b/man/ipfstat.8 @@ -1,4 +1,4 @@ -.TH ipfstat 8 +.TH IPFSTAT 8 .SH NAME ipfstat \- reports on packet filter statistics and filter list .SH SYNOPSIS @@ -42,7 +42,7 @@ Display the accounting filter list and show bytes counted against each rule. .TP .B \-A Display packet authentication statistics. -.TP +.TP .B \-C This option is only valid in combination with \fB\-t\fP. Display "closed" states as well in the top. Normally, a TCP connection is @@ -144,8 +144,8 @@ The number is incremented every half\-second. .SH STATE TOP Using the \fB\-t\fP option \fBipfstat\fP will enter the state top mode. In this mode the state table is displayed similar to the way \fBtop\fP displays -the process table. The \fB\-C\fP, \fB\-D\fP, \fB\-P\fP, \fB\-S\fP and \fB\-T\fP -command line options can be used to restrict the state entries that will be +the process table. The \fB\-C\fP, \fB\-D\fP, \fB\-P\fP, \fB\-S\fP and \fB\-T\fP +command line options can be used to restrict the state entries that will be shown and to specify the frequency of display updates. .PP In state top mode, the following keys can be used to influence the displayed @@ -157,7 +157,7 @@ information: .TP \fBl\fP redraw the screen. .TP -\fBq\fP quit the program. +\fBq\fP quit the program. .TP \fBs\fP switch between different sorting criterion. .TP diff --git a/man/ipftest.1 b/man/ipftest.1 index 5153687ed1a5c..54b5407315cf3 100644 --- a/man/ipftest.1 +++ b/man/ipftest.1 @@ -1,4 +1,4 @@ -.TH ipftest 1 +.TH IPFTEST 1 .SH NAME ipftest \- test packet filter rules with arbitrary input. .SH SYNOPSIS @@ -142,7 +142,6 @@ are: # a TCP packet going out of le0 with the SYN flag set. out on le0 tcp 10.4.12.1,2245 10.1.1.1,23 S .fi -.LP .RE .DT .TP diff --git a/man/ipmon.5 b/man/ipmon.5 index 2e3eebd06ba2d..18aef343e2638 100644 --- a/man/ipmon.5 +++ b/man/ipmon.5 @@ -2,56 +2,213 @@ .SH NAME ipmon, ipmon.conf \- ipmon configuration file format .SH DESCRIPTION -The format for files accepted by ipmon is described by the following grammar: -.LP +The +.B ipmon.conf +file is optionally loaded by +.B ipmon +when it starts. Its primary purpose is to direct +.B ipmon +to do extra actions when it sees a specific log entry from the kernel. +.PP +A line in the +.B ipmon.conf +file is either a comment or a +.B match +line. Each line must have a matching segment and an action segment. +These are to the left and right of the word "do", respectively. +A comment line is any line that starts with a #. +.PP +.B NOTE: +This file differs from all other IPFilter configuration files because it +attempts to match every line with every log record received. It does +.B not +stop at the +.B first +match or only use the +.B last +match. +.PP +For the action segment, a +.B match +line can delivery output to one of three destinations: +\fBfile\fR, \fBemail\fR or \fBcommand\fR. For example: .nf -"match" "{" matchlist "}" "do" "{" doing "}" ";" - -matchlist ::= matching [ "," matching ] . -matching ::= direction | dstip | dstport | every | group | interface | - logtag | nattag | protocol | result | rule | srcip | srcport . - -dolist ::= doing [ "," doing ] . -doing ::= execute | save | syslog . - -direction ::= "in" | "out" . -dstip ::= "dstip" "=" ipv4 "/" number . -dstport ::= "dstport" "=" number . -every ::= "every" every-options . -execute ::= "execute" "=" string . -group ::= "group" "=" string | "group" "=" number . -interface ::= "interface" "=" string . -logtag ::= "logtag" "=" string | "logtag" "=" number . -nattag ::= "nattag" "=" string . -protocol ::= "protocol" "=" string | "protocol" "=" number . -result ::= "result" "=" result-option . -rule ::= "rule" "=" number . -srcip ::= "srcip" "=" ipv4 "/" number . -srcport ::= "srcport" "=" number . -type ::= "type" "=" ipftype . -ipv4 ::= number "." number "." number "." number . - -every-options ::= "second" | number "seconds" | "packet" | number "packets" . -result-option ::= "pass" | "block" | "short" | "nomatch" | "log" . -ipftype ::= "ipf" | "nat" | "state" . +match { type = ipf; } do { save("file:///var/log/ipf-log"); }; +match { type = nat; } do { syslog; }; +match { type = state; } do { execute("/bin/mail root"); }; .fi .PP -In addition, lines that start with a # are considered to be comments. -.TP -.SH OVERVIEW +and is roughly described like this: +.PP +match { \fImatch-it ,match-it, ...\fP } do { \fIaction, action, ...\fP}; .PP -The ipmon configuration file is used for defining rules to be executed when -logging records are read from -.B /dev/ipl. +where there can be a list of matching expressions and a list of actions +to perform if all of the matching expressions are matched up with by +the current log entry. .PP +The lines above would save all ipf log entries to /var/log/ipf-log, send +all of the entries for NAT (ipnat related) to syslog and generate an email +to root for each log entry from the state tables. +.SH SYNTAX - MATCHING +.PP +In the above example, the matching segment was confined to matching on +the type of log entry generated. The full list of fields that can be +used here is: +.TP +direction <in|out> +This option is used to match on log records generated for packets going +in or out. +.TP +dstip <address/mask> +This option is used to match against the destination address associated +with the packet being logged. A "/mask" must be given and given in CIDR +notation (/0-/32) so to specify host 192.2.2.1, 192.2.2.1/32 must be given. +.TP +dstport <portnumber> +This option is used to match against the destination port in log entries. +A number must be given, symbolic names (such as those from /etc/services) +are not recognised by the parser. +.TP +every <second|# seconds|packet|# packets> +This option is used to regulate how often an \fBipmon.conf\fR entry is +actioned in response to an otherwise matching log record from the kernel. +.TP +group <name|number> +.TP +interface <interface-name> +This option is used to match against the network interface name associated +with the action causing the logging to happen. In general this will be the +network interface where the packet is seen by IPFilter. +.TP +logtag <number> +This option is used to match against tags set by ipf rules in \fBipf.conf\fR. +These tags are set with "set-tag(log=100)" appended to filter rules. +.TP +nattag <string> +This option is used to match against tags set by NAT rules in \fBipnat.conf\fR. +.TP +protocol <name|number> +This option is used to match against the IP protocol field in the packet +being logged. +.TP +result <pass|block|nomatch|log> +This option is used to match against the result of packet matching in the +kernel. If a packet is logged, using a \fBlog\fR rule in \fBipf.conf\fR +then it will match "log" here. The "nomatch" option is for use with +matching log records generated for all packets as the default. +.TP +rule <number> +This option is used to match against the \fInumber\fR of the rule +causing the record to be generated. The \fInumber\fR of a rule can be +observed using "ipfstat -ion". +.TP +srcip <address/mask> +This option is used to match against the source address associated +with the packet being logged. A "/mask" must be given and given in CIDR +notation (/0-/32) so to specify host 192.2.2.1, 192.2.2.1/32 must be given. +.TP +srcport <portnumber> +This option is used to match against the source port in log entries. +A number must be given, symbolic names (such as those from /etc/services) +are not recognised by the parser. +.TP +type <ipf|nat|state> +The format for files accepted by ipmon is described by the following grammar: +.B NOTE: At present, only IPv4 matching is available for source/destination address matching. +.SH SYNTAX - ACTIONS +The list of actions supported is as follows: +.TP +save("file://<filename>") +save("raw://<filename>") +Write out the log record to the filename given. This file will be closed +and reopened on receipt of a SIGHUP. If the \fIraw\fP target is used, +binary log data, as read from the kernel, is written out rather than a +text log record. The filename should be an absolute target, including +the root directory. Thus, saving to /var/log/ipmon.log would be, as an +example, save("file:///var/log/ipmon.log"). +.TP +syslog("<facility>.<priority>") +syslog("<facility>.") +syslog(".<priority>") +To log a text record via syslog, the \fBsyslog\fP action word is used. +The facility used by default is determined at first by the default +compiled into \fBipmon\fP (usually LOG_LOCAL0), which can be changed +via the command line (-L <facility>) or in an \fBipf.conf\fP rule +using the \fIlevel\fP option with logging. If the facility is +specified here, it takes precedence over all other settings. +The same applies to the syslog priority. By default, ipmon will +determine a priority for the packet, depending on whether or not it +has been blocked, passed, etc. It is possible to force the complete +facility/priority value for each log entry or to choose to replace +only one of them. +.TP +execute("<command string>") +The +.B execute +action runs the specified command each time the log entry matches +and feeds the log entry, as text, to the command being executed. +The command string given is executed using /bin/sh. +.TP +nothing +Literally, do nothing. Use this if you want to be verbose in your config +file about doing nothing for a particular log record. +.SH PLUGIN ACTIONS +It is possible to configure +.B ipmon +to use externally supplied modules to save log entries with. +These are added to +.B ipmon +using the +.I load_action +configuration line. The syntax of this line is: +.nf + +load_action <name> <path>; +.fi +.TP +name +is a short name for the action. It does not need to correspond to the +name of the library file, but inside the library file, the functions +.B <name>destroy +, +.B <name>parse +and +.B <name>store +must be present. +.TP +path +specifies the path in the filesystem to the shared object +that contains the implementation of the new action. After the new +action has been declared using +.I load_action +it can then be used in any +.I do +statement. +.SH EXAMPLES +.PP +Some further examples are: +.nf + +# +# log everything to syslog local4, regardless +# +match { ; } do { syslog("local4."); }; +# +# keep a local copy of things packets to/from port 80 +# +match { srcport = 80; } do { save("file:///var/log/web"); }; +match { dstport = 80; } do { save("file:///var/log/web"); }; +# +load_action local "/usr/lib/libmyaction.so"; +match { dstip 127.0.0.1; } do { local("local options"); }; +# +.fi .SH MATCHING .PP -Each rule for ipmon consists of two primary segments: the first describes how -the log record is to be matched, the second defines what action to take if -there is a positive match. All entries of the rules present in the file are +All entries of the rules present in the file are compared for matches - there is no first or last rule match. .SH FILES /dev/ipl diff --git a/man/ipmon.8 b/man/ipmon.8 index 905a9c875404f..d96a06aad4dbe 100644 --- a/man/ipmon.8 +++ b/man/ipmon.8 @@ -1,4 +1,4 @@ -.TH ipmon 8 +.TH IPMON 8 .SH NAME ipmon \- monitors /dev/ipl for logged packets .SH SYNOPSIS diff --git a/man/ipnat.1 b/man/ipnat.1 deleted file mode 100644 index f24141546171f..0000000000000 --- a/man/ipnat.1 +++ /dev/null @@ -1,48 +0,0 @@ -.TH IPNAT 1 -.SH NAME -ipnat \- user interface to the NAT -.SH SYNOPSIS -.B ipnat -[ -.B \-lnrsvCF -] -.B \-f <\fIfilename\fP> -.SH DESCRIPTION -.PP -\fBipnat\fP opens the filename given (treating "\-" as stdin) and parses the -file for a set of rules which are to be added or removed from the IP NAT. -.PP -Each rule processed by \fBipnat\fP -is added to the kernels internal lists if there are no parsing problems. -Rules are added to the end of the internal lists, matching the order in -which they appear when given to \fBipnat\fP. -.SH OPTIONS -.TP -.B \-C -delete all entries in the current NAT rule listing (NAT rules) -.TP -.B \-F -delete all active entries in the current NAT translation table (currently -active NAT mappings) -.TP -.B \-l -Show the list of current NAT table entry mappings. -.TP -.B \-n -This flag (no-change) prevents \fBipf\fP from actually making any ioctl -calls or doing anything which would alter the currently running kernel. -.TP -.B \-s -Retrieve and display NAT statistics -.TP -.B \-r -Remove matching NAT rules rather than add them to the internal lists -.TP -.B \-v -Turn verbose mode on. Displays information relating to rule processing -and active rules/table entries. -.DT -.SH FILES -/dev/ipnat -.SH SEE ALSO -ipnat(5), ipf(8), ipfstat(8) diff --git a/man/ipnat.4 b/man/ipnat.4 index 54f55d3de8106..2a866d4a8f19a 100644 --- a/man/ipnat.4 +++ b/man/ipnat.4 @@ -29,7 +29,6 @@ These ioctl's are implemented as being routing ioctls and thus the same rules for the various routing ioctls and the file descriptor are employed, mainly being that the fd must be that of the device associated with the module (i.e., /dev/ipl). -.LP .PP The structure used with the NAT interface is described below: .LP @@ -64,7 +63,6 @@ Recognised values for in_redir: #define NAT_MAP 0 #define NAT_REDIRECT 1 .fi -.PP .LP \fBNAT statistics\fP Statistics on the number of packets mapped, going in and out are kept, diff --git a/man/ipnat.5 b/man/ipnat.5 index 2d76a46650641..07a6549f50bba 100644 --- a/man/ipnat.5 +++ b/man/ipnat.5 @@ -1,158 +1,670 @@ .TH IPNAT 5 .SH NAME -ipnat, ipnat.conf \- IP NAT file format +ipnat, ipnat.conf \- IPFilter NAT file format .SH DESCRIPTION -The format for files accepted by ipnat is described by the following grammar: -.LP -.nf -ipmap :: = mapblock | redir | map . - -map ::= mapit ifname lhs "->" dstipmask [ mapicmp | mapport | mapproxy ] - mapoptions . -mapblock ::= "map-block" ifname lhs "->" ipmask [ ports ] mapoptions . -redir ::= "rdr" ifname rlhs "->" ip [ "," ip ] rdrport rdroptions . - -lhs ::= ipmask | fromto . -rlhs ::= ipmask dport | fromto . -dport ::= "port" portnum [ "-" portnum ] . -ports ::= "ports" numports | "auto" . -rdrport ::= "port" portnum . -mapit ::= "map" | "bimap" . -fromto ::= "from" object "to" object . -ipmask ::= ip "/" bits | ip "/" mask | ip "netmask" mask . -dstipmask ::= ipmask | "range" ip "-" ip . -mapicmp ::= "icmpidmap" "icmp" number ":" number . -mapport ::= "portmap" tcpudp portspec . -mapoptions ::= [ tcpudp ] [ "frag" ] [ age ] [ clamp ] . -rdroptions ::= rdrproto [ rr ] [ "frag" ] [ age ] [ clamp ] [ rdrproxy ] . - -object :: = addr [ port-comp | port-range ] . -addr :: = "any" | nummask | host-name [ "mask" ipaddr | "mask" hexnumber ] . -port-comp :: = "port" compare port-num . -port-range :: = "port" port-num range port-num . -rdrproto ::= tcpudp | protocol . - -rr ::= "round-robin" . -age ::= "age" decnumber [ "/" decnumber ] . -clamp ::= "mssclamp" decnumber . -tcpudp ::= "tcp/udp" | protocol . -mapproxy ::= "proxy" "port" port proxy-name '/' protocol -rdrproxy ::= "proxy" proxy-name . - -protocol ::= protocol-name | decnumber . -nummask ::= host-name [ "/" decnumber ] . -portspec ::= "auto" | portnumber ":" portnumber . -port ::= portnumber | port-name . -portnumber ::= number { numbers } . -ifname ::= 'A' - 'Z' { 'A' - 'Z' } numbers . - -numbers ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' . -.fi +.PP +The +.B ipnat.conf +file is used to specify rules for the Network Address Translation (NAT) +component of IPFilter. To load rules specified in the +.B ipnat.conf +file, the +.B ipnat(8) +program is used. .PP For standard NAT functionality, a rule should start with \fBmap\fP and then proceeds to specify the interface for which outgoing packets will have their -source address rewritten. -.PP -Packets which will be rewritten can only be selected by matching the original -source address. A netmask must be specified with the IP address. -.PP -The address selected for replacing the original is chosen from an IP#/netmask -pair. A netmask of all 1's indicating a hostname is valid. A netmask of -31 1's (255.255.255.254) is considered invalid as there is no space for -allocating host IP#'s after consideration for broadcast and network -addresses. -.PP -When remapping TCP and UDP packets, it is also possible to change the source -port number. Either TCP or UDP or both can be selected by each rule, with a -range of port numbers to remap into given as \fBport-number:port-number\fP. -.SH COMMANDS -There are four commands recognised by IP Filter's NAT code: -.TP +source address rewritten. Following this it is expected that the old source +address, and optionally port number, will be specified. +.PP +In general, all NAT rules conform to the following layout: +the first word indicates what type of NAT rule is present, this is followed +by some stanzas to match a packet, followed by a "->" and this is then +followed by several more stanzas describing the new data to be put in the +packet. +.PP +In this text and in others, +use of the term "left hand side" (LHS) when talking about a NAT rule refers +to text that appears before the "->" and the "right hand side" (RHS) for text +that appears after it. In essence, the LHS is the packet matching and the +RHS is the new data to be used. +.SH VARIABLES +.PP +This configuration file, like all others used with IPFilter, supports the +use of variable substitution throughout the text. +.nf + +nif="ppp0"; +map $nif 0/0 -> 0/32 +.fi +.PP +would become +.nf + +map ppp0 0/0 -> 0/32 +.fi +.PP +Variables can be used recursively, such as 'foo="$bar baz";', so long as +$bar exists when the parser reaches the assignment for foo. +.PP +See +.B ipnat(8) +for instructions on how to define variables to be used from a shell +environment. +.SH OUTBOUND SOURCE TRANSLATION (map'ing) +Changing the source address of a packet is traditionally performed using .B map -that is used for mapping one address or network to another in an unregulated -round robin fashion; -.TP -.B rdr -that is used for redirecting packets to one IP address and port pair to -another; -.TP -.B bimap -for setting up bidirectional NAT between an external IP address and an internal -IP address and +rules. Both the source address and optionally port number can be changed +according to various controls. +.PP +To start out with, a common rule used is of the form: +.nf + +map le0 0/0 -> 0/32 +.fi +.PP +Here we're saying change the source address of all packets going out of +le0 (the address/mask pair of 0/0 matching all packets) to that of the +interface le0 (0/32 is a synonym for the interface's own address at +the current point in time.) If we wanted to pass the packet through +with no change in address, we would write it as: +.nf + +map le0 0/0 -> 0/0 +.fi +.PP +If we only want to change a portion of our internal network and to a +different address that is routed back through this host, we might do: +.nf + +map le0 10.1.1.0/24 -> 192.168.55.3/32 +.fi +.PP +In some instances, we may have an entire subnet to map internal addresses +out onto, in which case we can express the translation as this: +.nf + +map le0 10.0.0.0/8 -> 192.168.55.0/24 +.fi +.PP +IPFilter will cycle through each of the 256 addresses in the 192.168.55.0/24 +address space to ensure that they all get used. +.PP +Of course this poses a problem for TCP and UDP, with many connections made, +each with its own port number pair. If we're unlucky, translations can be +dropped because the new address/port pair mapping already exists. To +mitigate this problem, we add in port translation or port mapping: +.nf + +map le0 10.0.0.0/8 -> 192.168.55.0/24 portmap tcp/udp auto +.fi +.PP +In this instance, the word "auto" tells IPFilter to calculate a private +range of port numbers for each address on the LHS to use without fear +of them being trampled by others. This can lead to problems if there are +connections being generated mire quickly than IPFilter can expire them. +In this instance, and if we want to get away from a private range of +port numbers, we can say: +.nf + +map le0 10.0.0.0/8 -> 192.168.55.0/24 portmap tcp/udp 5000:65000 +.fi +.PP +And now each connection through le0 will add to the enumeration of +the port number space 5000-65000 as well as the IP address subnet +of 192.168.55.0/24. +.PP +If the new addresses to be used are in a consecutive range, rather +than a complete subnet, we can express this as: +.nf + +map le0 10.0.0.0/8 -> range 192.168.55.10-192.168.55.249 + portmap tcp/udp 5000:65000 +.fi +.PP +This tells IPFilter that it has a range of 240 IP address to use, from +192.168.55.10 to 192.168.55.249, inclusive. +.PP +If there were several ranges of addresses for use, we can use each one +in a round-robin fashion as followed: +.nf + +map le0 10.0.0.0/8 -> range 192.168.55.10-192.168.55.29 + portmap tcp/udp 5000:65000 round-robin +map le0 10.0.0.0/8 -> range 192.168.55.40-192.168.55.49 + portmap tcp/udp 5000:65000 round-robin +.fi +.PP +To specify translation rules that impact a specific IP protocol, +the protocol name or number is appended to the rule like this: +.nf + +map le0 10.0.0.0/8 -> 192.168.55.0/24 tcp/udp +map le0 10.0.0.0/8 -> 192.168.55.1/32 icmp +map le0 10.0.0.0/8 -> 192.168.55.2/32 gre +.fi +.PP +For TCP connections exiting a connection such as PPPoE where the MTU is +slightly smaller than normal ethernet, it can be useful to reduce the +Maximum Segment Size (MSS) offered by the internal machines to match, +reducing the liklihood that the either end will attempt to send packets +that are too big and result in fragmentation. This is acheived using the +.B mssclamp +option with TCP +.B map +rules like this: +.nf + +map pppoe0 0/0 -> 0/32 mssclamp 1400 tcp +.fi +.PP +For ICMP packets, we can map the ICMP id space in query packets: +.nf + +map le0 10.0.0.0/8 -> 192.168.55.1/32 icmpidmap icmp 1000:20000 +.fi +.PP +If we wish to be more specific about our initial matching criteria on the +LHS, we can expand to using a syntax more similar to that in +.B ipf.conf(5) +: +.nf + +map le0 from 10.0.0.0/8 to 26.0.0.0/8 -> + 192.168.55.1 +map le0 from 10.0.0.0/8 port > 1024 to 26.0.0.0/8 -> + 192.168.55.2 portmap 5000:9999 tcp/udp +map le0 from 10.0.0.0/8 ! to 26.0.0.0/8 -> + 192.168.55.3 portmap 5000:9999 tcp/udp +.fi .TP +.B NOTE: +negation matching with source addresses is +.B NOT +possible with +.B map +/ .B map-block -which sets up static IP address based translation, based on a algorithm to -squeeze the addresses to be translated into the destination range. -.SH MATCHING -.PP -For basic NAT and redirection of packets, the address subject to change is used -along with its protocol to check if a packet should be altered. The packet -\fImatching\fP part of the rule is to the left of the "->" in each rule. -.PP -Matching of packets has now been extended to allow more complex compares. -In place of the address which is to be translated, an IP address and port -number comparison can be made using the same expressions available with -\fBipf\fP. A simple NAT rule could be written as: +rules. +.PP +The NAT code has builtin default timeouts for TCP, UDP, ICMP and another +for all other protocols. In general, the timeout for an entry to be +deleted shrinks once a reply packet has been seen (excluding TCP.) +If you wish to specify your own timeouts, this can be achieved either +by setting one timeout for both directions: +.nf + +map le0 0/0 -> 0/32 gre age 30 +.fi +.PP +or setting a different timeout for the reply: +.nf + +map le0 from any to any port = 53 -> 0/32 age 60/10 udp +.fi +.PP +A pressing problem that many people encounter when using NAT is that the +address protocol can be embedded inside an application's communication. +To address this problem, IPFilter provides a number of built-in proxies +for the more common trouble makers, such as FTP. These proxies can be +used as follows: +.nf + +map le0 0/0 -> 0/32 proxy port 21 ftp/tcp +.fi +.PP +In this rule, the word "proxy" tells us that we want to connect up this +translation with an internal proxy. The "port 21" is an extra restriction +that requires the destination port number to be 21 if this rule is to be +activated. The word "ftp" is the proxy identifier that the kernel will +try and resolve internally, "tcp" the protocol that packets must match. +.PP +See below for a list of proxies and their relative staus. +.PP +To associate NAT rules with filtering rules, it is possible to set and +match tags during either inbound or outbound processing. At present the +tags for forwarded packets are not preserved by forwarding, so once the +packet leaves IPFilter, the tag is forgotten. For +.B map +rules, we can match tags set by filter rules like this: +.nf + +map le0 0/0 -> 0/32 proxy portmap 5000:5999 tag lan1 tcp +.fi +.PP +This would be used with "pass out" rules that includes a stanza such +as "set-tag (nat = lan1)". +.PP +If the interface in which packets are received is different from the +interface on which packets are sent out, then the translation rule needs +to be written to take this into account: +.nf + +map hme0,le0 0/0 -> 0/32 +.fi +.PP +Although this might seem counterintuitive, the interfaces when listed +in rules for +.B ipnat.conf +are always in the +.I inbound +, +.I outbound +order. In this case, hme0 would be the return interface and le0 would be +the outgoing interface. If you wish to allow return packets on any +interface, the correct syntax to use would be: +.nf + +map *,le0 0/0 -> 0/32 +.fi .LP +A special variant of +.B map +rules exists, called +.B map-block. +This command is intended for use when there is a large network to be mapped +onto a smaller network, where the difference in netmasks is upto 14 bits +difference in size. This is achieved by dividing the address space and +port space up to ensure that each source address has its own private range +of ports to use. For example, this rule: +.nf + +map-block ppp0 172.192.0.0/16 -> 209.1.2.0/24 ports auto +.fi +.PP +would result in 172.192.0.0/24 being mapped to 209.1.2.0/32 +with each address, from 172.192.0.0 to 172.192.0.255 having 252 ports of its +own. As opposed to the above use of \fBmap\fP, if for some reason the user +of (say) 172.192.0.2 wanted 260 simultaneous connections going out, they would +be limited to 252 with \fBmap-block\fP but would just \fImove on\fP to the next +IP address with the \fBmap\fP command. +.SS Extended matching +.PP +If it is desirable to match on both the source and destination of a packet +before applying an address translation to it, this can be achieved by using +the same from-to syntax as is used in \fBipf.conf\fP(5). What follows +applies equally to the +.B map +rules discussed above and +.B rdr +rules discussed below. A simple example is as follows: +.nf + +map bge0 from 10.1.0.0/16 to 192.168.1.0/24 -> 172.12.1.4 +.fi +.PP +This would only match packets that are coming from hosts that have a source +address matching 10.1.0.0/16 and a destination matching 192.168.1.0/24. +This can be expanded upon with ports for TCP like this: +.nf + +rdr bge0 from 10.1.0.0/16 to any port = 25 -> 127.0.0.1 port 2501 tcp +.fi +.PP +Where only TCP packets from 10.1.0.0/16 to port 25 will be redirected to +port 2501. +.PP +As with \fBipf.conf\fR(5), if we have a large set of networks or addresses +that we would like to match up with then we can define a pool using +\fBippool\fR(8) in \fBippool.conf\fR(5) and then refer to it in an +\fBipnat\fR rule like this: +.nf + +map bge0 from pool/100 to any port = 25 -> 127.0.0.1 port 2501 tcp +.fi +.TP +.B NOTE: +In this situation, the rule is considered to have a netmask of "0" and +thus is looked at last, after any rules with /16's or /24's in them, +.I even if +the defined pool only has /24's or /32's. Pools may also be used +.I wherever +the from-to syntax in \fBipnat.conf\fR(5) is allowed. +.SH INBOUND DESTINATION TRANSLATION (redirection) +.PP +Redirection of packets is used to change the destination fields in a packet +and is supported for packets that are moving \fIin\fP on a network interface. +While the same general syntax for +.B map +rules is supported, there are differences and limitations. +.PP +Firstly, by default all redirection rules target a single IP address, not +a network or range of network addresses, so a rule written like this: +.nf + +rdr le0 0/0 -> 192.168.1.0 +.fi +.PP +Will not spread packets across all 256 IP addresses in that class C network. +If you were to try a rule like this: +.nf + +rdr le0 0/0 -> 192.168.1.0/24 +.fi +.PP +then you will receive a parsing error. +.PP +The from-to source-destination matching used with +.B map +rules can be used with rdr rules, along with negation, however the +restriction moves - only a source address match can be negated: +.nf + +rdr le0 from 1.1.0.0/16 to any -> 192.168.1.3 +rdr le0 ! from 1.1.0.0/16 to any -> 192.168.1.4 +.fi +.PP +If there is a consective set of addresses you wish to spread the packets +over, then this can be done in one of two ways, the word "range" optional +to preserve: +.nf + +rdr le0 0/0 -> 192.168.1.1 - 192.168.1.5 +rdr le0 0/0 -> range 192.168.1.1 - 192.168.1.5 +.fi +.PP +If there are only two addresses to split the packets across, the +recommended method is to use a comma (",") like this: +.nf + +rdr le0 0/0 -> 192.168.1.1,192.168.1.2 +.fi +.PP +If there is a large group of destination addresses that are somewhat +disjoint in nature, we can cycle through them using a +.B round-robin +technique like this: .nf -map de0 10.1.0.0/16 -> 201.2.3.4/32 + +rdr le0 0/0 -> 192.168.1.1,192.168.1.2 round-robin +rdr le0 0/0 -> 192.168.1.5,192.168.1.7 round-robin +rdr le0 0/0 -> 192.168.1.9 round-robin +.fi +.PP +If there are a large number of redirect rules and hosts being targetted +then it may be desirable to have all those from a single source address +be targetted at the same destination address. To achieve this, the +word +.B sticky +is appended to the rule like this: +.nf + +rdr le0 0/0 -> 192.168.1.1,192.168.1.2 sticky +rdr le0 0/0 -> 192.168.1.5,192.168.1.7 round-robin sticky +rdr le0 0/0 -> 192.168.1.9 round-robin sticky +.fi +.PP +The +.B sticky +feature can only be combined with +.B round-robin +and the use of comma. +.PP +For TCP and UDP packets, it is possible to both match on the destiantion +port number and to modify it. For example, to change the destination port +from 80 to 3128, we would use a rule like this: +.nf + +rdr de0 0/0 port 80 -> 127.0.0.1 port 3128 tcp +.fi +.PP +If a range of ports is given on the LHS and a single port is given on the +RHS, the entire range of ports is moved. For example, if we had this: +.nf + +rdr le0 0/0 port 80-88 -> 127.0.0.1 port 3128 tcp +.fi +.PP +then port 80 would become 3128, port 81 would become 3129, etc. If we +want to redirect a number of different pots to just a single port, an +equals sign ("=") is placed before the port number on the RHS like this: +.nf + +rdr le0 0/0 port 80-88 -> 127.0.0.1 port = 3128 tcp +.fi +.PP +In this case, port 80 goes to 3128, port 81 to 3128, etc. +.PP +As with +.B map +rules, it is possible to manually set a timeout using the +.B age +option, like this: +.nf + +rdr le0 0/0 port 53 -> 127.0.0.1 port 10053 udp age 5/5 +.fi +.PP +The use of proxies is not restricted to +.B map +rules and outbound sessions. Proxies can also be used with redirect +rules, although the syntax is slightly different: +.nf + +rdr ge0 0/0 port 21 -> 127.0.0.1 port 21 tcp proxy ftp +.fi +.PP +For +.B rdr +rules, the interfaces supplied are in the same order as +.B map +rules - input first, then output. In situations where the outgoing interface +is not certain, it is also possible to use a wildcard ("*") to effect a match +on any interface. +.nf + +rdr le0,* 0/0 -> 192.168.1.0 +.fi +.PP +A single rule, with as many options set as possible would look something like +this: +.nf + +rdr le0,ppp0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp + round-robin frag age 40/40 sticky mssclamp 1000 tag tagged .fi +.SH REWRITING SOURCE AND DESTINATION +.PP +Whilst the above two commands provide a lot of flexibility in changing +addressing fields in packets, often it can be of benefit to translate +\fIboth\fP source \fBand\fR destination at the same time or to change +the source address on input or the destination address on output. +Doing all of these things can be accomplished using +.B rewrite +NAT rules. +.PP +A +.B rewrite +rule requires the same level of packet matching as before, protocol and +source/destination information but in addition allows either +.B in +or +.B out +to be specified like this: +.nf + +rewrite in on ppp0 proto tcp from any to any port = 80 -> + src 0/0 dst 127.0.0.1,3128; +rewrite out on ppp0 from any to any -> + src 0/32 dst 10.1.1.0/24; +.fi +.PP +On the RHS we can specify both new source and destination information to place +into the packet being sent out. As with other rules used in +\fBipnat.conf\fR, there are shortcuts syntaxes available to use the original +address information (\fB0/0\fR) and the address associated with the network +interface (\fB0/32\fR.) For TCP and UDP, both address and port information +can be changed. At present it is only possible to specify either a range of +port numbers to be used (\fBX-Y\fR) or a single port number (\fB= X\fR) as +follows: +.nf + +rewrite in on le0 proto tcp from any to any port = 80 -> + src 0/0,2000-20000 dst 127.0.0.1,port = 3128; +.fi +.PP +There are four fields that are stepped through in enumerating the number +space available for creating a new destination: +.LP +source address +.LP +source port .LP -or as +destination address .LP +destination port +.PP +If one of these happens to be a static then it will be skipped and the next +one incremented. As an example: .nf -map de0 from 10.1.0.0/16 to any -> 201.2.3.4/32 + +rewrite out on le0 proto tcp from any to any port = 80 -> + src 1.0.0.0/8,5000-5999 dst 2.0.0.0/24,6000-6999; .fi +.PP +The translated packets would be: +.LP +1st src=1.0.0.1,5000 dst=2.0.0.1,6000 +.LP +2nd src=1.0.0.2,5000 dst=2.0.0.1,6000 +.LP +3rd src=1.0.0.2,5001 dst=2.0.0.1,6000 .LP -Only IP address and port numbers can be compared against. This is available -with all NAT rules. -.SH TRANSLATION -.PP -To the right of the "->" is the address and port specification which will be -written into the packet providing it has already successfully matched the -prior constraints. The case of redirections (\fBrdr\fP) is the simplest: -the new destination address is that specified in the rule. For \fBmap\fP -rules, the destination address will be one for which the tuple combining -the new source and destination is known to be unique. If the packet is -either a TCP or UDP packet, the destination and source ports come into the -equation too. If the tuple already exists, IP Filter will increment the -port number first, within the available range specified with \fBportmap\fP -and if there exists no unique tuple, the source address will be incremented -within the specified netmask. If a unique tuple cannot be determined, then -the packet will not be translated. The \fBmap-block\fP is more limited in -how it searches for a new, free and unique tuple, in that it will used an -algorithm to determine what the new source address should be, along with the -range of available ports - the IP address is never changed and nor does the -port number ever exceed its allotted range. -.SH ICMPIDMAP -.PP -ICMP messages can be divided into two groups: "errors" and "queries". ICMP -errors are generated as a response of another IP packet. IP Filter will take -care that ICMP errors that are the response of a NAT-ed IP packet are -handled properly. -.PP -For 4 types of ICMP queries (echo request, timestamp request, information -request and address mask request) IP Filter supports an additional mapping -called "ICMP id mapping". All these 4 types of ICMP queries use a unique -identifier called the ICMP id. This id is set by the process sending the -ICMP query and it is usually equal to the process id. The receiver of the -ICMP query will use the same id in its response, thus enabling the -sender to recognize that the incoming ICMP reply is intended for him and is -an answer to a query that he made. The "ICMP id mapping" feature modifies -these ICMP id in a way identical to \fBportmap\fP for TCP or UDP. -.PP -The reason that you might want this, is that using this feature you don't -need an IP address per host behind the NAT box, that wants to do ICMP queries. -The two numbers behind the \fBicmpidmap\fP keyword are the first and the -last icmp id number that can be used. There is one important caveat: if you -map to an IP address that belongs to the NAT box itself (notably if you have -only a single public IP address), then you must ensure that the NAT box does -not use the \fBicmpidmap\fP range that you specified in the \fBmap\fP rule. -Since the ICMP id is usually the process id, it is wise to restrict the -largest permittable process id (PID) on your operating system to e.g. 63999 and -use the range 64000:65535 for ICMP id mapping. Changing the maximal PID is -system dependent. For most BSD derived systems can be done by changing -PID_MAX in /usr/include/sys/proc.h and then rebuild the system. +4th src=1.0.0.2,5001 dst=2.0.0.2,6000 +.LP +5th src=1.0.0.2,5001 dst=2.0.0.2,6001 +.LP +6th src=1.0.0.3,5001 dst=2.0.0.2,6001 +.PP +and so on. +.PP +As with +.B map +rules, it is possible to specify a range of addresses by including the word +\fIrange\fR before the addresses: +.nf + +rewrite from any to any port = 80 -> + src 1.1.2.3 - 1.1.2.6 dst 2.2.3.4 - 2.2.3.6; +.fi +.SH DIVERTING PACKETS +.PP +If you'd like to send packets to a UDP socket rather than just another +computer to be decapsulated, this can be achieved using a +.B divert +rule. +.PP +Divert rules can be be used with both inbound and outbound packet +matching however the rule +.B must +specify host addresses for the outer packet, not ranges of addresses +or netmasks, just single addresses. +Additionally the syntax must supply required information for UDP. +An example of what a divert rule looks ike is as follows: +.nf + +divert in on le0 proto udp from any to any port = 53 -> + src 192.1.1.1,54 dst 192.168.1.22.1,5300; +.fi +.PP +On the LHS is a normal set of matching capabilities but on the RHS it is +a requirement to specify both the source and destination addresses and +ports. +.PP +As this feature is intended to be used with targetting packets at sockets +and not IPFilter running on other systems, there is no rule provided to +\fIundivert\fR packets. +.TP +.B NOTE: +Diverted packets \fImay\fP be fragmented if the addition of the +encapsulating IP header plus UDP header causes the packet to exceed +the size allowed by the outbound network interface. At present it is +not possible to cause Path MTU discovery to happen as this feature +is intended to be transparent to both endpoints. +.B Path MTU Discovery +If Path MTU discovery is being used and the "do not fragment" flag +is set in packets to be encapsulated, an ICMP error message will +be sent back to the sender if the new packet would need to be +fragmented. +.SH COMMON OPTIONS +This section deals with options that are available with all rules. +.TP +.B purge +When the purge keyword is added to the end of a NAT rule, it will +cause all of the active NAT sessions to be removed when the rule +is removed as an individual operation. If all of the NAT rules +are flushed out, it is expected that the operator will similarly +flush the NAT table and thus NAT sessions are not removed when the +NAT rules are flushed out. +.SH RULE ORDERING +.PP +.B NOTE: +Rules in +.B ipnat.conf +are read in sequentially as listed and loaded into the kernel in this +fashion +.B BUT +packet matching is done on \fBnetmask\fR, going from 32 down to 0. +If a rule uses +.B pool +or +.B hash +to reference a set of addresses or networks, the netmask value for +these fields is considered to be "0". +So if your +.B ipnat.conf +has the following rules: +.nf + +rdr le0 192.0.0.0/8 port 80 -> 127.0.0.1 3132 tcp +rdr le0 192.2.0.0/16 port 80 -> 127.0.0.1 3131 tcp +rdr le0 from any to pool/100 port 80 -> 127.0.0.1 port 3130 tcp +rdr le0 192.2.2.0/24 port 80 -> 127.0.0.1 3129 tcp +rdr le0 192.2.2.1 port 80 -> 127.0.0.1 3128 tcp +.fi +.PP +then the rule with 192.2.2.1 will match \fBfirst\fR, regardless of where +it appears in the ordering of the above rules. In fact, the order in +which they would be used to match a packet is: +.nf + +rdr le0 192.2.2.1 port 80 -> 127.0.0.1 3128 tcp +rdr le0 192.2.2.0/24 port 80 -> 127.0.0.1 3129 tcp +rdr le0 192.2.0.0/16 port 80 -> 127.0.0.1 3131 tcp +rdr le0 192.0.0.0/8 port 80 -> 127.0.0.1 3132 tcp +rdr le0 from any to pool/100 port 80 -> 127.0.0.1 port 3130 tcp +.fi +.PP +where the first line is actually a /32. +.PP +If your +.B ipnat.conf +file has entries with matching target fields (source address for +.B map +rules and destination address for +.B rdr +rules), then the ordering in the +.B ipnat.conf +file does matter. So if you had the following: +.nf + +rdr le0 from 1.1.0.0/16 to 192.2.2.1 port 80 -> 127.0.0.1 3129 tcp +rdr le0 from 1.1.1.0/24 to 192.2.2.1 port 80 -> 127.0.0.1 3128 tcp +.fi +.PP +Then no packets will match the 2nd rule, they'll all match the first. +.SH IPv6 +.PP +In all of the examples above, where an IPv4 address is present, an IPv6 +address can also be used. All rules must use either IPv4 addresses with +both halves of the NAT rule or IPv6 addresses for both halves. Mixing +IPv6 addresses with IPv4 addresses, in a single rule, will result in an +error. +.PP +For shorthand notations such as "0/32", the equivalent for IPv6 is +"0/128". IPFilter will treat any netmask greater than 32 as an +implicit direction that the address should be IPv6, not IPv4. +To be unambiguous with 0/0, for IPv6 use ::0/0. .SH KERNEL PROXIES .PP IP Filter comes with a few, simple, proxies built into the code that is loaded @@ -175,117 +687,38 @@ Mature - well tested, protocol is properly understood by the proxy; .PP The currently compiled in proxy list is as follows: -.HP +.TP FTP - Mature -.HP +(map ... proxy port ftp ftp/tcp) +.TP IRC - Experimental -.HP +(proxy port 6667 irc/tcp) +.TP rpcbind - Experimental -.HP +.TP +PPTP - Experimental +.TP H.323 - Experimental -.HP +(map ... proxy port 1720 h323/tcp) +.TP Real Audio (PNA) - Aging -.HP +.TP +DNS - Developmental +(map ... proxy port 53 dns/udp { block .cnn.com; }) +.TP IPsec - Developmental -.HP +(map ... proxy port 500 ipsec/tcp) +.TP netbios - Experimental -.HP +.TP R-command - Mature - -.SH TRANSPARENT PROXIES -.PP -True transparent proxying should be performed using the redirect (\fBrdr\fP) -rules directing ports to localhost (127.0.0.1) with the proxy program doing -a lookup through \fB/dev/ipnat\fP to determine the real source and address -of the connection. -.SH LOAD-BALANCING -.PP -Two options for use with \fBrdr\fP are available to support primitive, -\fIround-robin\fP based load balancing. The first option allows for a -\fBrdr\fP to specify a second destination, as follows: -.LP -.nf -rdr le0 203.1.2.3/32 port 80 -> 203.1.2.3,203.1.2.4 port 80 tcp -.fi -.LP -This would send alternate connections to either 203.1.2.3 or 203.1.2.4. -In scenarios where the load is being spread amongst a larger set of -servers, you can use: -.LP -.nf -rdr le0 203.1.2.3/32 port 80 -> 203.1.2.3,203.1.2.4 port 80 tcp round-robin -rdr le0 203.1.2.3/32 port 80 -> 203.1.2.5 port 80 tcp round-robin -.fi -.LP -In this case, a connection will be redirected to 203.1.2.3, then 203.1.2.4 -and then 203.1.2.5 before going back to 203.1.2.3. In accomplishing this, -the rule is removed from the top of the list and added to the end, -automatically, as required. This will not effect the display of rules -using "ipnat -l", only the internal application order. -.SH EXAMPLES -.PP -This section deals with the \fBmap\fP command and its variations. -.PP -To change IP#'s used internally from network 10 into an ISP provided 8 bit -subnet at 209.1.2.0 through the ppp0 interface, the following would be used: -.LP -.nf -map ppp0 10.0.0.0/8 -> 209.1.2.0/24 -.fi -.PP -The obvious problem here is we're trying to squeeze over 16,000,000 IP -addresses into a 254 address space. To increase the scope, remapping for TCP -and/or UDP, port remapping can be used; -.LP -.nf -map ppp0 10.0.0.0/8 -> 209.1.2.0/24 portmap tcp/udp 1025:65000 -.fi -.PP -which falls only 527,566 `addresses' short of the space available in network -10. If we were to combine these rules, they would need to be specified as -follows: -.LP -.nf -map ppp0 10.0.0.0/8 -> 209.1.2.0/24 portmap tcp/udp 1025:65000 -map ppp0 10.0.0.0/8 -> 209.1.2.0/24 -.fi -.PP -so that all TCP/UDP packets were port mapped and only other protocols, such as -ICMP, only have their IP# changed. In some instances, it is more appropriate -to use the keyword \fBauto\fP in place of an actual range of port numbers if -you want to guarantee simultaneous access to all within the given range. -However, in the above case, it would default to 1 port per IP address, since -we need to squeeze 24 bits of address space into 8. A good example of how -this is used might be: -.LP -.nf -map ppp0 172.192.0.0/16 -> 209.1.2.0/24 portmap tcp/udp auto -.fi -.PP -which would result in each IP address being given a small range of ports to -use (252). In all cases, the new port number that is used is deterministic. -That is, port X will always map to port Y. -WARNING: It is not advisable to use the \fBauto\fP feature if you are map'ing -to a /32 (i.e. 0/32) because the NAT code will try to map multiple hosts to -the same port number, outgoing and ultimately this will only succeed for one -of them. -The problem here is that the \fBmap\fP directive tells the NAT -code to use the next address/port pair available for an outgoing connection, -resulting in no easily discernible relation between external addresses/ports -and internal ones. This is overcome by using \fBmap-block\fP as follows: -.LP -.nf -map-block ppp0 172.192.0.0/16 -> 209.1.2.0/24 ports auto -.fi -.PP -For example, this would result in 172.192.0.0/24 being mapped to 209.1.2.0/32 -with each address, from 172.192.0.0 to 172.192.0.255 having 252 ports of its -own. As opposed to the above use of \fBmap\fP, if for some reason the user -of (say) 172.192.0.2 wanted 260 simultaneous connections going out, they would -be limited to 252 with \fBmap-block\fP but would just \fImove on\fP to the next -IP address with the \fBmap\fP command. +(map ... proxy port shell rcmd/tcp) +.SH KERNEL PROXIES +.SH FILES /dev/ipnat .br +/etc/protocols +.br /etc/services .br /etc/hosts diff --git a/man/ipnat.8 b/man/ipnat.8 index 683e8f15d9e91..7d8d452a87fcc 100644 --- a/man/ipnat.8 +++ b/man/ipnat.8 @@ -51,6 +51,11 @@ Show the list of current NAT table entry mappings. This flag (no-change) prevents \fBipf\fP from actually making any ioctl calls or doing anything which would alter the currently running kernel. .TP +.B \-p +This flag is used with the \fB-r\fP flag to cause any active NAT +sessions that were created by the rules being removed and that are +currently active to also be removed. +.TP .B \-r Remove matching NAT rules rather than add them to the internal lists. .TP diff --git a/man/ippool.5 b/man/ippool.5 index aeff3c8b3ae5b..e90c33e119d30 100644 --- a/man/ippool.5 +++ b/man/ippool.5 @@ -2,146 +2,311 @@ .SH NAME ippool, ippool.conf \- IP Pool file format .SH DESCRIPTION -The format for files accepted by ippool is described by the following grammar: -.LP +The file ippool.conf is used with ippool(8) to configure address pools for +use with ipnat(8) and ipf(8). +.PP +There are four different types of address pools that can be configured +through ippool.conf. The various types are presented below with a brief +description of how they are used: +.HP +dstlist +.IP +destination list - is a collection of IP addresses with an optional +network interface name that can be used with either redirect (rdr) rules +in ipnat.conf(5) or as the destination in ipf.conf(5) for policy based +routing. +.HP +group-map +.IP +group maps - support the srcgrpmap and dstgrpmap call functions in +ipf.conf(5) by providing a list of addresses or networks rule group +numbers to start processing them with. +.HP +hash +.IP +hash tables - provide the means for performing a very efficient +lookup address or network when there is expected to be only one +exact match. These are best used with more static sets of addresses +so they can be sized optimally. +.HP +pool +.IP +address pools - are an alternative to hash tables that can perform just +as well in most circumstances. In addition, the address pools allow for +heirarchical matching, so it is possible to define a subnet as matching +but then exclude specific addresses from it. +.SS +Evolving Configuration +.PP +Over time the configuration syntax used by ippool.conf(5) has evolved. +Originally the syntax used was more verbose about what a particular +value was being used for, for example: +.PP .nf -line ::= table | groupmap . -table ::= "table" role tabletype . -groupmap ::= "group-map" inout role number ipfgroup -tabletype ::= ipftree | ipfhash . - -role ::= "role" "=" "ipf" . -inout ::= "in" | "out" . - -ipftree ::= "type" "=" "tree" number "{" addrlist "}" . -ipfhash ::= "type" "=" "hash" number hashopts "{" hashlist "}" . - -ipfgroup ::= setgroup hashopts "{" grouplist "}" | - hashopts "{" setgrouplist "}" . -setgroup ::= "group" "=" groupname . - -hashopts ::= size [ seed ] | seed . - -size ::= "size" number . -seed ::= "seed" number . - -addrlist ::= [ "!" ] addrmask ";" [ addrlist ] . -grouplist ::= groupentry ";" [ grouplist ] | addrmask ";" [ grouplist ] . - -setgrouplist ::= groupentry ";" [ setgrouplist ] . - -groupentry ::= addrmask "," setgroup . - -hashlist ::= hashentry ";" [ hashlist ] . -hashentry ::= addrmask . - -addrmask ::= ipaddr | ipaddr "/" mask . - -mask ::= number | ipaddr . - -groupname ::= number | name . - -number ::= digit { digit } . - -ipaddr = host-num "." host-num "." host-num "." host-num . -host-num = digit [ digit [ digit ] ] . - -digit ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" . -name ::= letter { letter | digit } . +table role = ipf type = tree number = 100 + { 1.1.1.1/32; !2.2.0.0/16; 2.2.2.0/24; ef00::5/128; }; .fi .PP -The IP pool configuration file is used for defining a single object that -contains a reference to multiple IP address/netmask pairs. A pool may consist -of a mixture of netmask sizes, from 0 to 32. -.PP -At this point in time, only IPv4 addressing is supported. -.TP -.SH OVERVIEW -.PP -The IP pool configuration file provides for defining two different mechanisms -for improving speed in matching IP addresses with rules. -The first, -.B table -, defines a lookup -.I table -to provide a single reference in a -filter rule to multiple targets and the second, -.B group-map -, provides a mechanism to target multiple groups from a single filter line. -.PP -The -.B group-map -command can only be used with filter rules that use the -.B call -command to invoke either -.B fr_srcgrpmap -or -.B fr_dstgrpmap -, to use the source or destination address, -respectively, for determining which filter group to jump to next for -continuation of filter packet processing. -.SH POOL TYPES -.PP -Two storage formats are provided: hash tables and tree structure. The hash -table is intended for use with objects all containing the same netmask or a -few different sized netmasks of non-overlapping address space and the tree -is designed for being able to support exceptions to a covering mask, in -addition to normal searching as you would do with a table. It is not possible -to use the tree data storage type with -.B group-map -configuration entries. -.SH POOL ROLES -.PP -When a pool is defined in the configuration file, it must have an associated -role. At present the only supported role is -.B ipf. -Future development will see futher expansion of their use by other sections -of IPFilter code. -.SH EXAMPLES -The following examples show how the pool configuration file is used with -the ipf configuration file to enhance the ability for the ipf configuration -file to be succinct in meaning. -.TP -1 -The first example shows how a filter rule makes reference to a specific -pool for matching of the source address. +This is rather long winded. The evolution of the configuration syntax +has also replaced the use of numbers with names, although numbers can +still be used as can be seen here: +.PP .nf -pass in from pool/100 to any +pool ipf/tree (name "100";) + { 1.1.1.1/32; !2.2.0.0/16; 2.2.2.0/24; ef00::5/128; }; .fi .PP -The pool configuration, which matches IP addresses 1.1.1.1 and any -in 2.2.0.0/16, except for those in 2.2.2.0/24. +Both of the above examples produce the same configuration in the kernel +for use with ipf.conf(5). +.PP +Newer options for use in ippool.conf(5) will only be offered in the new +configuration syntax and all output using "ippool -l" will also be in the +new configuration syntax. +.SS +IPFilter devices and pools +.PP +To cater to different administration styles, ipool.conf(5) allows you to +tie a pool to a specific role in IPFilter. The recognised role names are: +.HP +ipf +.IP +pools defined for role "ipf" are available for use with all rules that are +found in ipf.conf(5) except for auth rules. +.HP +nat +.IP +pools defined for role "nat" are available for use with all rules that are +found in ipnat.conf(5). +.HP +auth +.IP +pools defined for role "auth" are available only for use with "auth" rules +that are found in ipf.conf(5) +.HP +all +.IP +pools that are defined for the "all" role are available to all types of +rules, be they NAT rules in ipnat.conf(5) or firewall rules in ipf.conf(5). +.SH Address Pools +.PP +An address pool can be used in ipf.conf(5) and ipnat.conf(5) for matching +the source or destination address of packets. They can be referred to either +by name or number and can hold an arbitrary number of address patterns to +match. +.PP +An address pool is considered to be a "tree type". In the older configuration +style, it was necessary to have "type=tree" in ippool.conf(5). In the new +style configuration, it follows the IPFilter device with which the pool +is being configured. +Now it is the default if left out. +.PP +For convenience, both IPv4 and IPv6 addresses can be stored in the same +address pool. It should go without saying that either type of packet can +only ever match an entry in a pool that is of the same address family. +.PP +The address pool searches the list of addresses configured for the best +match. The "best match" is considered to be the match that has the highest +number of bits set in the mask. Thus if both 2.2.0.0/16 and 2.2.2.0/24 are +present in an address pool, the addres 2.2.2.1 will match 2.2.2.0/24 and +2.2.1.1 will match 2.2.0.0/16. The reason for this is to allow exceptions +to be added through the use of negative matching. In the following example, +the pool contains "2.2.0.0/16" and "!2.2.2.0/24", meaning that all packets +that match 2.2.0.0/16, except those that match 2.2.2.0/24, will be considered +as a match for this pool. .PP -.nf table role = ipf type = tree number = 100 - { 1.1.1.1/32; 2.2.0.0/16; !2.2.2.0/24 }; + { 1.1.1.1/32; 2.2.0.0/16; !2.2.2.0/24; ef00::5/128; }; +.PP +For the sake of clarity and to aid in managing large numbers of addresses +inside address pools, it is possible to specify a location to load the +addresses from. To do this simply use a "file://" URL where you would +specify an actual IP address. +.PP +.nf +pool ipf/tree (name rfc1918;) { file:///etc/ipf/rfc1918; }; .fi -.TP -2 -The following ipf.conf extract uses the -fr_srcgrpmap/fr_dstgrpmap lookups to use the -.B group-map -facility to lookup the next group to use for filter processing, providing -the -.B call -filter rule is matched. +.PP +The contents of the file might look something like this: +.PP .nf -call now fr_srcgrpmap/1010 in all -call now fr_dstgrpmap/2010 out all -pass in all group 1020 -block in all group 1030 -pass out all group 2020 -block out all group 2040 +# RFC 1918 networks +10.0.0.0/8 +!127.0.0.0/8 +172.16.0.0/12 +192.168.0.0/24 .fi .PP -A ippool configuration to work with the above ipf.conf file might -look like this: +In this example, the inclusion of the line "!127.0.0.0/8" is, strictly +speaking not correct and serves only as an example to show that negative +matching is also supported in this file. +.PP +Another format that ippool(8) recognises for input from a file is that +from whois servers. In the following example, output from a query to a +WHOIS server for information about which networks are associated with +the name "microsoft" has been saved in a file named "ms-networks". +There is no need to modify the output from the whois server, so using +either the whois command or dumping data directly from it over a TCP +connection works perfectly file as input. +.PP +.nf +pool ipf/tree (name microsoft;) { whois file "/etc/ipf/ms-networks"; }; +.fi +.PP +And to then block all packets to/from networks defined in that file, +a rule like this might be used: +.PP +.nf +block in from pool/microsoft to any +.fi +.PP +Note that there are limitations on the output returned by whois servers +so be aware that their output may not be 100% perfect for your goal. +.SH Destination Lists +.PP +Destination lists are provided for use primarily with NAT redirect rules +(rdr). Their purpose is to allow more sophisticated methods of selecting +which host to send traffic to next than the simple round-robin technique +that is present with with "round-robin" rules in ipnat.conf(5). +.PP +When building a list of hosts to use as a redirection list, it is +necessary to list each host to be used explicitly. Expressing a +collection of hosts as a range or a subnet is not supported. With each +address it is also possible to specify a network interface name. The +network interface name is ignored by NAT when using destination lists. +The network itnerface name is currently only used with policy based +routing (use of "to"/"dup-to" in ipf.conf(5)). +.PP +Unlike the other directives that can be expressed in this file, destination +lists must be written using the new configuration syntax. Each destination +list must have a name associated with it and a next hop selection policy. +Some policies have further options. The currently available selection +policies are: +.HP +round-robin +.IP +steps through the list of hosts configured with the destination list +one by one +.HP +random +.IP +the next hop is chosen by random selection from the list available +.HP +src-hash +.IP +a hash is made of the source address components of the packet +(address and port number) and this is used to select which +next hop address is used +.HP +dst-hash +.IP +a hash is made of the destination address components of the packet +(address and port number) and this is used to select which +next hop address is used +.HP +hash +.IP +a hash is made of all the address components in the packet +(addresses and port numbers) and this is used to select which +next hop address is used +.HP +weighted +.IP +selecting a weighted policy for destination selection needs further +clarification as to what type of weighted selection will be used. +The sub-options to a weighted policy are: +.RS +.HP +connection +.IP +the host that has received the least number of connections is selected +to be the next hop. When all hosts have the same connection count, +the last one used will be the next address selected. +.RE +.PP +The first example here shows 4 destinations that are used with a +round-robin selection policy. +.PP +.nf +pool nat/dstlist (name servers; policy round-robin;) + { 1.1.1.2; 1.1.1.4; 1.1.1.5; 1.1.1.9; }; +.fi +.PP +In the following example, the destination is chosen by whichever has +had the least number of connections. By placing the interface name +with each address and saying "all/dstlist", the destination list can +be used with both ipnat.conf(5) and ipf.conf(5). +.PP +.nf +pool all/dstlist (name servers; policy weighted connection;) + { bge0:1.1.1.2; bge0:1.1.1.4; bge1:1.1.1.5; bge1:1.1.1.9; }; +.fi +.SH Group maps +.PP +Group maps are provided to allow more efficient processing of packets +where there are a larger number of subnets and groups of rules for those +subnets. Group maps are used with "call" rules in ipf.conf(5) that +use the "srcgrpmap" and "dstgrpmap" functions. +.PP +A group map declaration must mention which group is the default group +for all matching addresses to be applied to. Then inside the list of +addresses and networks for the group, each one may optionally have +a group number associated with it. A simple example like this, where +the first two entries would map to group 2020 but 5.0.0.0/8 sends +rule processing to group 2040. .PP .nf -group-map in role = ipf number = 1010 - { 1.1.1.1/32, group = 1020; 3.3.0.0/16, group = 1030; }; group-map out role = ipf number = 2010 group = 2020 - { 2.2.2.2/32; 4.4.0.0/16; 5.0.0.0/8, group = 2040; }; + { 2.2.2.2/32; 4.4.0.0/16; 5.0.0.0/8, group = 2040; }; +.fi +.PP +An example that outlines the real purpose of group maps is below, +where each one of the 12 subnets is mapped to a different group +number. This might be because each subnet has its own policy and +rather than write a list of twelve rules in ipf.conf(5) that match +the subnet and branch off with a head statement, a single rule can +be used with this group map to achieve the same result. +.PP +.nf +group-map ( name "2010"; in; ) + { 192.168.1.0/24, group = 10010; 192.168.2.0/24, group = 10020; + 192.168.3.0/24, group = 10030; 192.168.4.0/24, group = 10040; + 192.168.5.0/24, group = 10050; 192.168.6.0/24, group = 10060; + 192.168.7.0/24, group = 10070; 192.168.8.0/24, group = 10080; + 192.168.9.0/24, group = 10090; 192.168.10.0/24, group = 10100; + 192.168.11.0/24, group = 10110; 192.168.12.0/24, group = 10120; + }; +.fi +.PP +The limitation with group maps is that only the source address or the +destination address can be used to map the packet to the starting group, +not both, in your ipf.conf(5) file. +.SH Hash Tables +.PP +The hash table is operationally similar to the address pool. It is +used as a store for a collection of address to match on, saving the +need to write a lengthy list of rules. As with address pools, searching +will attempt to find the best match - an address specification with the +largest contiguous netmask. +.PP +Hash tables are best used where the list of addresses, subnets and +networks is relatively static, which is something of a contrast to +the address pool that can work with either static or changing +address list sizes. +.PP +Further work is still needed to have IPFilter correctly size and tune +the hash table to optimise searching. The goal is to allow for small to +medium sized tables to achieve close to O(1) for either a positive or +negative match, in contrast to the address pool, which is O(logn). +.PP +The following two examples build the same table in the kernel, using +the old configuration format (first) and the new one (second). +.PP +.nf +table role=all type=hash name=servers size=5 + { 1.1.1.2/32; 1.1.1.3/32; 11.23.44.66/32; }; + +pool all/hash (name servers; size 5;) + { 1.1.1.2; 1.1.1.3; 11.23.44.66; }; .fi .SH FILES /dev/iplookup diff --git a/man/ippool.8 b/man/ippool.8 index e27cb92c2c912..4e08841680bbb 100644 --- a/man/ippool.8 +++ b/man/ippool.8 @@ -4,7 +4,7 @@ ippool \- user interface to the IPFilter pools .SH SYNOPSIS .br .B ippool --a [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/<netmask>] +-a [-dnv] [-m <name>] [-o <role>] [-t <type>] [-T ttl] -i <ipaddr>[/<netmask>] .br .B ippool -A [-dnv] [-m <name>] [-o <role>] [-S <seed>] [-t <type>] @@ -19,7 +19,7 @@ ippool \- user interface to the IPFilter pools -l [-dv] [-m <name>] [-t <type>] .br .B ippool --r [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/<netmask>] +-r [-dnv] [-m <name>] [-o <role>] [-t <type>] -i <ipaddr>[/<netmask>] .br .B ippool -R [-dnv] [-m <name>] [-o <role>] [-t <type>] @@ -111,6 +111,13 @@ Sets the type of pool being defined. Myst be one of .B hash, .B group-map. .TP +.B -T <ttl> +Sets the expiration of the node being added. The timeout is expressed +as a number of seconds. +.B tree, +.B hash, +.B group-map. +.TP .B -u When parsing a configuration file, rather than load new pool data into the kernel, unload it. diff --git a/man/man.sed b/man/man.sed deleted file mode 100644 index 0be8dab0dc7b5..0000000000000 --- a/man/man.sed +++ /dev/null @@ -1 +0,0 @@ -DF. Ä..–CVSD~MakefileDipf.1D€ipf.4Dipf.5D‚ @@ -33,10 +33,15 @@ *********************************************************************** */ -#if defined(_KERNEL) && !defined(__sgi) -# include <sys/systm.h> +#if defined(linux) && defined(_KERNEL) +extern void *memcpy(void *, const void *, unsigned long); +# define bcopy(a,b,c) memcpy(b,a,c) #else -# include <string.h> +# if defined(_KERNEL) && !defined(__sgi) +# include <sys/systm.h> +# else +# include <string.h> +# endif #endif #include "md5.h" diff --git a/misc.c b/misc.c deleted file mode 100644 index e39b98fd76f3d..0000000000000 --- a/misc.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (C) 1993-2002 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - */ -#if defined(__sgi) && (IRIX > 602) -# include <sys/ptimers.h> -#endif -#if (SOLARIS2 >= 7) -# define _SYS_VARARGS_H -# define _VARARGS_H -#endif -#if defined(__STDC__) -# include <stdarg.h> -#else -# include <varargs.h> -#endif -#include <stdio.h> -#include <assert.h> -#include <string.h> -#include <sys/types.h> -#if !defined(__SVR4) && !defined(__svr4__) -#include <strings.h> -#else -#include <sys/byteorder.h> -#endif -#include <sys/param.h> -#include <sys/time.h> -#include <stdlib.h> -#include <unistd.h> -#include <stddef.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netinet/in_systm.h> -#ifndef linux -#include <netinet/ip_var.h> -#endif -#include <netinet/ip.h> -#include <netinet/udp.h> -#include <netinet/tcp.h> -#include <netinet/ip_icmp.h> -#include <net/if.h> -#include <netdb.h> -#include <arpa/nameser.h> -#include <resolv.h> -#include "ip_compat.h" -#include <netinet/tcpip.h> -#include "ip_fil.h" -#include "ipf.h" -#include "ipt.h" - -#if !defined(lint) -static const char sccsid[] = "@(#)misc.c 1.3 2/4/96 (C) 1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: misc.c,v 2.2.2.9 2002/12/06 11:40:27 darrenr Exp $"; -#endif - -extern int opts; - - -void printpacket(ip) -ip_t *ip; -{ - tcphdr_t *tcp; - u_short len; - - if (ip->ip_v == 4) - len = ntohs(ip->ip_len); - else if (ip->ip_v == 6) - len = ntohs(((u_short *)ip)[2]) + 40; - else - len = 0; - - if ((opts & OPT_HEX) == OPT_HEX) { - u_char *s; - int i; - - for (s = (u_char *)ip, i = 0; i < len; i++) { - printf("%02x", *s++ & 0xff); - if (len - i > 1) { - i++; - printf("%02x", *s++ & 0xff); - } - if (i + 1 != len) - putchar(' '); - } - putchar('\n'); - return; - } - - if (ip->ip_v == 6) { - printpacket6(ip); - return; - } - - tcp = (struct tcphdr *)((char *)ip + (ip->ip_hl << 2)); - printf("ip %d(%d) %d", ntohs(ip->ip_len), ip->ip_hl << 2, ip->ip_p); - if (ip->ip_off & IP_OFFMASK) - printf(" @%d", ip->ip_off << 3); - (void)printf(" %s", inet_ntoa(ip->ip_src)); - if (!(ip->ip_off & IP_OFFMASK)) - if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) - (void)printf(",%d", ntohs(tcp->th_sport)); - (void)printf(" > "); - (void)printf("%s", inet_ntoa(ip->ip_dst)); - if (!(ip->ip_off & IP_OFFMASK)) { - if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) - (void)printf(",%d", ntohs(tcp->th_dport)); - if ((ip->ip_p == IPPROTO_TCP) && (tcp->th_flags)) { - putchar(' '); - if (tcp->th_flags & TH_FIN) - putchar('F'); - if (tcp->th_flags & TH_SYN) - putchar('S'); - if (tcp->th_flags & TH_RST) - putchar('R'); - if (tcp->th_flags & TH_PUSH) - putchar('P'); - if (tcp->th_flags & TH_ACK) - putchar('A'); - if (tcp->th_flags & TH_URG) - putchar('U'); - if (tcp->th_flags & TH_ECN) - putchar('E'); - if (tcp->th_flags & TH_CWR) - putchar('C'); - } - } - putchar('\n'); -} - - -/* - * This is meant to work without the IPv6 header files being present or - * the inet_ntop() library. - */ -void printpacket6(ip) -ip_t *ip; -{ - u_char *buf, p, hops; - u_short plen, *addrs; - tcphdr_t *tcp; - u_32_t flow; - - buf = (u_char *)ip; - tcp = (tcphdr_t *)(buf + 40); - p = buf[6]; - hops = buf[7]; - flow = ntohl(*(u_32_t *)buf); - flow &= 0xfffff; - plen = ntohs(*((u_short *)buf +2)); - addrs = (u_short *)buf + 4; - - printf("ip6/%d %d %#x %d", buf[0] & 0xf, plen, flow, p); - printf(" %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", - ntohs(addrs[0]), ntohs(addrs[1]), ntohs(addrs[2]), - ntohs(addrs[3]), ntohs(addrs[4]), ntohs(addrs[5]), - ntohs(addrs[6]), ntohs(addrs[7])); - if (plen >= 4) - if (p == IPPROTO_TCP || p == IPPROTO_UDP) - (void)printf(",%d", ntohs(tcp->th_sport)); - printf(" >"); - addrs += 8; - printf(" %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", - ntohs(addrs[0]), ntohs(addrs[1]), ntohs(addrs[2]), - ntohs(addrs[3]), ntohs(addrs[4]), ntohs(addrs[5]), - ntohs(addrs[6]), ntohs(addrs[7])); - if (plen >= 4) - if (p == IPPROTO_TCP || p == IPPROTO_UDP) - (void)printf(",%d", ntohs(tcp->th_dport)); - putchar('\n'); -} - - -#if defined(__STDC__) -void verbose(char *fmt, ...) -#else -void verbose(fmt, va_alist) -char *fmt; -va_dcl -#endif -{ - va_list pvar; - - va_start(pvar, fmt); - if (opts & OPT_VERBOSE) - vprintf(fmt, pvar); - va_end(pvar); -} - - -#ifdef __STDC__ -void debug(char *fmt, ...) -#else -void debug(fmt, va_alist) -char *fmt; -va_dcl -#endif -{ - va_list pvar; - - va_start(pvar, fmt); - if (opts & OPT_DEBUG) - vprintf(fmt, pvar); - va_end(pvar); -} diff --git a/mkfilters b/mkfilters index f0e6ff4659405..fe15c55563ab2 100644 --- a/mkfilters +++ b/mkfilters @@ -60,7 +60,7 @@ foreach $i (keys %ifaces) { sub irix_mkfilters { open(NETSTAT, "/usr/etc/netstat -i|") || return 0; - + while (defined($line = <NETSTAT>)) { if ($line =~ m/^Name/) @@ -113,4 +113,4 @@ sub scan_ifconfig } } } - + diff --git a/ml_ipl.c b/ml_ipl.c index 4db9a9b067222..17c785ceb9d40 100644 --- a/ml_ipl.c +++ b/ml_ipl.c @@ -1,10 +1,7 @@ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. - * responsibility and is not changed in any way. - * - * I hate legaleese, don't you ? */ /* * 29/12/94 Added code from Marc Huber <huber@fzi.de> to allow it to allocate @@ -29,47 +26,47 @@ #endif #ifndef IPL_NAME -#define IPL_NAME "/dev/ipl" +#define IPL_NAME "/dev/ipf" #endif -extern int iplattach(), iplopen(), iplclose(), iplioctl(), iplread(); -extern int nulldev(), iplidentify(), errno; +extern int ipfattach(), ipfopen(), ipfclose(), ipfioctl(), ipfread(); +extern int nulldev(), ipfidentify(), errno; -struct cdevsw ipldevsw = +struct cdevsw ipfdevsw = { - iplopen, iplclose, iplread, nulldev, - iplioctl, nulldev, nulldev, nulldev, + ipfopen, ipfclose, ipfread, nulldev, + ipfioctl, nulldev, nulldev, nulldev, 0, nulldev, }; -struct dev_ops ipl_ops = +struct dev_ops ipf_ops = { 1, - iplidentify, - iplattach, - iplopen, - iplclose, - iplread, + ipfidentify, + ipfattach, + ipfopen, + ipfclose, + ipfread, NULL, /* write */ NULL, /* strategy */ NULL, /* dump */ 0, /* psize */ - iplioctl, + ipfioctl, NULL, /* reset */ NULL /* mmap */ }; -int ipl_major = 0; +int ipf_major = 0; #ifdef sun4m -struct vdldrv vd = +struct vdldrv vd = { VDMAGIC_PSEUDO, - "ipl", - &ipl_ops, + "ipf", + &ipf_ops, NULL, - &ipldevsw, + &ipfdevsw, 0, 0, NULL, @@ -82,9 +79,9 @@ struct vdldrv vd = struct vdldrv vd = { VDMAGIC_PSEUDO, /* magic */ - "ipl", /* name */ + "ipf", /* name */ #ifdef sun4c - &ipl_ops, /* dev_ops */ + &ipf_ops, /* dev_ops */ #else NULL, /* struct mb_ctlr *mb_ctlr */ NULL, /* struct mb_driver *mb_driver */ @@ -93,7 +90,7 @@ struct vdldrv vd = 1, /* numdevs */ #endif /* sun4c */ NULL, /* bdevsw */ - &ipldevsw, /* cdevsw */ + &ipfdevsw, /* cdevsw */ 0, /* block major */ 0, /* char major */ }; @@ -104,10 +101,10 @@ extern struct cdevsw cdevsw[]; extern int nchrdev; xxxinit(fc, vdp, vdi, vds) -u_int fc; -struct vddrv *vdp; -caddr_t vdi; -struct vdstat *vds; + u_int fc; + struct vddrv *vdp; + caddr_t vdi; + struct vdstat *vds; { struct vdlinkage *v; int i; @@ -115,17 +112,17 @@ struct vdstat *vds; switch (fc) { case VDLOAD: - while (ipl_major < nchrdev && - cdevsw[ipl_major].d_open != vd_unuseddev) - ipl_major++; - if (ipl_major == nchrdev) + while (ipf_major < nchrdev && + cdevsw[ipf_major].d_open != vd_unuseddev) + ipf_major++; + if (ipf_major == nchrdev) return ENODEV; - vd.Drv_charmajor = ipl_major; + vd.Drv_charmajor = ipf_major; vdp->vdd_vdtab = (struct vdlinkage *)&vd; - return ipl_attach(vdi); + return ipf_attach(vdi); case VDUNLOAD: return unload(vdp, vdi); - + case VDSTAT: return 0; @@ -141,11 +138,11 @@ static unload(vdp, vdi) int i; (void) vn_remove(IPL_NAME, UIO_SYSSPACE, FILE); - return ipldetach(); + return ipfdetach(); } -static int ipl_attach(vdi) +static int ipf_attach(vdi) struct vdioctl_load *vdi; { struct vnode *vp; @@ -156,10 +153,10 @@ struct vdioctl_load *vdi; vattr_null(&vattr); vattr.va_type = MFTOVT(fmode); vattr.va_mode = (fmode & 07777); - vattr.va_rdev = ipl_major<<8; + vattr.va_rdev = ipf_major<<8; error = vn_create(IPL_NAME, UIO_SYSSPACE, &vattr, EXCL, 0, &vp); if (error == 0) VN_RELE(vp); - return iplattach(0); + return ipfattach(0); } diff --git a/mlf_ipl.c b/mlf_ipl.c index b39a14d0d8773..ef156ec8daa6f 100644 --- a/mlf_ipl.c +++ b/mlf_ipl.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -93,43 +93,43 @@ int sysctl_ipf_int SYSCTL_HANDLER_ARGS; # define CTLFLAG_OFF 0x00800000 /* IPFilter must be disabled */ # define CTLFLAG_RWO (CTLFLAG_RW|CTLFLAG_OFF) SYSCTL_NODE(_net_inet, OID_AUTO, ipf, CTLFLAG_RW, 0, "IPF"); -SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &fr_flags, 0, ""); -SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_pass, CTLFLAG_RW, &fr_pass, 0, ""); -SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &fr_active, 0, ""); -SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &fr_chksrc, 0, ""); -SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &fr_minttl, 0, ""); +SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &ipf_flags, 0, ""); +SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_pass, CTLFLAG_RW, &ipf_pass, 0, ""); +SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &ipf_active, 0, ""); +SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &ipf_chksrc, 0, ""); +SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &ipf_minttl, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RWO, - &fr_tcpidletimeout, 0, ""); + &ipf_tcpidletimeout, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RWO, - &fr_tcphalfclosed, 0, ""); + &ipf_tcphalfclosed, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RWO, - &fr_tcpclosewait, 0, ""); + &ipf_tcpclosewait, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RWO, - &fr_tcplastack, 0, ""); + &ipf_tcplastack, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RWO, - &fr_tcptimeout, 0, ""); + &ipf_tcptimeout, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RWO, - &fr_tcpclosed, 0, ""); + &ipf_tcpclosed, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RWO, - &fr_udptimeout, 0, ""); + &ipf_udptimeout, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RWO, - &fr_icmptimeout, 0, ""); + &ipf_icmptimeout, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defnatage, CTLFLAG_RWO, - &fr_defnatage, 0, ""); + &ipf_defnatage, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_ipfrttl, CTLFLAG_RW, - &fr_ipfrttl, 0, ""); -SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_running, CTLFLAG_RD, - &fr_running, 0, ""); + &ipf_ipfrttl, 0, ""); +SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_running, CTLFLAG_RD, + &ipf_running, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statesize, CTLFLAG_RWO, - &fr_statesize, 0, ""); + &ipf_statesize, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statemax, CTLFLAG_RWO, - &fr_statemax, 0, ""); + &ipf_statemax, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authsize, CTLFLAG_RWO, - &fr_authsize, 0, ""); + &ipf_authsize, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authused, CTLFLAG_RD, - &fr_authused, 0, ""); + &ipf_authused, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defaultauthage, CTLFLAG_RW, - &fr_defaultauthage, 0, ""); + &ipf_defaultauthage, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ippr_ftp_pasvonly, CTLFLAG_RW, &ippr_ftp_pasvonly, 0, ""); #endif @@ -139,15 +139,15 @@ static void *ipf_devfs[IPL_LOGSIZE]; #endif #if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000) -int ipl_major = 0; +int ipf_major = 0; -static struct cdevsw ipldevsw = +static struct cdevsw ipfdevsw = { - iplopen, /* open */ - iplclose, /* close */ - iplread, /* read */ + ipfopen, /* open */ + ipfclose, /* close */ + ipfread, /* read */ (void *)nullop, /* write */ - iplioctl, /* ioctl */ + ipfioctl, /* ioctl */ (void *)nullop, /* stop */ (void *)nullop, /* reset */ (void *)NULL, /* tty */ @@ -156,45 +156,45 @@ static struct cdevsw ipldevsw = NULL /* strategy */ }; -MOD_DEV(IPL_VERSION, LM_DT_CHAR, -1, &ipldevsw); +MOD_DEV(IPL_VERSION, LM_DT_CHAR, -1, &ipfdevsw); extern struct cdevsw cdevsw[]; extern int vd_unuseddev __P((void)); extern int nchrdev; #else -static struct cdevsw ipl_cdevsw = { - iplopen, iplclose, iplread, nowrite, /* 79 */ - iplioctl, nostop, noreset, nodevtotty, +static struct cdevsw ipf_cdevsw = { + ipfopen, ipfclose, ipfread, nowrite, /* 79 */ + ipfioctl, nostop, noreset, nodevtotty, #if (__FreeBSD_version >= 300000) - seltrue, nommap, nostrategy, "ipl", + seltrue, nommap, nostrategy, "ipf", #else - noselect, nommap, nostrategy, "ipl", + noselect, nommap, nostrategy, "ipf", #endif NULL, -1 }; #endif -static void ipl_drvinit __P((void *)); +static void ipf_drvinit __P((void *)); #ifdef ACTUALLY_LKM_NOT_KERNEL -static int if_ipl_unload __P((struct lkm_table *, int)); -static int if_ipl_load __P((struct lkm_table *, int)); -static int if_ipl_remove __P((void)); -static int ipl_major = CDEV_MAJOR; +static int if_ipf_unload __P((struct lkm_table *, int)); +static int if_ipf_load __P((struct lkm_table *, int)); +static int if_ipf_remove __P((void)); +static int ipf_major = CDEV_MAJOR; -static int iplaction __P((struct lkm_table *, int)); +static int ipfaction __P((struct lkm_table *, int)); static char *ipf_devfiles[] = { IPL_NAME, IPL_NAT, IPL_STATE, IPL_AUTH, IPL_SCAN, IPL_SYNC, IPL_POOL, NULL }; extern int lkmenodev __P((void)); -static int iplaction(lkmtp, cmd) -struct lkm_table *lkmtp; -int cmd; +static int ipfaction(lkmtp, cmd) + struct lkm_table *lkmtp; + int cmd; { #if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000) - int i = ipl_major; + int i = ipf_major; struct lkm_dev *args = lkmtp->private.lkm_dev; #endif int err = 0; @@ -208,27 +208,27 @@ int cmd; #if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000) for (i = 0; i < nchrdev; i++) if (cdevsw[i].d_open == lkmenodev || - cdevsw[i].d_open == iplopen) + cdevsw[i].d_open == ipfopen) break; if (i == nchrdev) { printf("IP Filter: No free cdevsw slots\n"); return ENODEV; } - ipl_major = i; + ipf_major = i; args->lkm_offset = i; /* slot in cdevsw[] */ #endif - printf("IP Filter: loaded into slot %d\n", ipl_major); - err = if_ipl_load(lkmtp, cmd); + printf("IP Filter: loaded into slot %d\n", ipf_major); + err = if_ipf_load(lkmtp, cmd); if (!err) - ipl_drvinit((void *)NULL); + ipf_drvinit((void *)NULL); return err; break; case LKM_E_UNLOAD : - err = if_ipl_unload(lkmtp, cmd); + err = if_ipf_unload(lkmtp, cmd); if (!err) { printf("IP Filter: unloaded from slot %d\n", - ipl_major); + ipf_major); #ifdef DEVFS if (ipf_devfs[IPL_LOGIPF]) devfs_remove_dev(ipf_devfs[IPL_LOGIPF]); @@ -257,7 +257,7 @@ int cmd; } -static int if_ipl_remove __P((void)) +static int if_ipf_remove __P((void)) { char *name; struct nameidata nd; @@ -290,32 +290,32 @@ static int if_ipl_remove __P((void)) } -static int if_ipl_unload(lkmtp, cmd) -struct lkm_table *lkmtp; -int cmd; +static int if_ipf_unload(lkmtp, cmd) + struct lkm_table *lkmtp; + int cmd; { int error = 0; - error = ipldetach(); + error = ipfdetach(); if (!error) - error = if_ipl_remove(); + error = if_ipf_remove(); return error; } -static int if_ipl_load(lkmtp, cmd) -struct lkm_table *lkmtp; -int cmd; +static int if_ipf_load(lkmtp, cmd) + struct lkm_table *lkmtp; + int cmd; { struct nameidata nd; struct vattr vattr; int error = 0, fmode = S_IFCHR|0600, i; char *name; - error = iplattach(); + error = ipfattach(); if (error) return error; - (void) if_ipl_remove(); + (void) if_ipf_remove(); for (i = 0; (name = ipf_devfiles[i]); i++) { NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, name, curproc); @@ -333,7 +333,7 @@ int cmd; VATTR_NULL(&vattr); vattr.va_type = VCHR; vattr.va_mode = (fmode & 07777); - vattr.va_rdev = (ipl_major << 8) | i; + vattr.va_rdev = (ipf_major << 8) | i; VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE); error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); #if (__FreeBSD_version >= 300000) @@ -352,7 +352,7 @@ int cmd; * strlen isn't present in 2.1.* kernels. */ size_t strlen(string) -char *string; + char *string; { register char *s; @@ -363,19 +363,19 @@ char *string; int xxxinit(lkmtp, cmd, ver) -struct lkm_table *lkmtp; -int cmd, ver; + struct lkm_table *lkmtp; + int cmd, ver; { - DISPATCH(lkmtp, cmd, ver, iplaction, iplaction, iplaction); + DISPATCH(lkmtp, cmd, ver, ipfaction, ipfaction, ipfaction); } #else /* __FREEBSD_version >= 220000 */ # ifdef IPFILTER_LKM # include <sys/exec.h> # if (__FreeBSD_version >= 300000) -MOD_DEV(if_ipl, LM_DT_CHAR, CDEV_MAJOR, &ipl_cdevsw); +MOD_DEV(if_ipf, LM_DT_CHAR, CDEV_MAJOR, &ipf_cdevsw); # else -MOD_DECL(if_ipl); +MOD_DECL(if_ipf); static struct lkm_dev _module = { @@ -384,48 +384,48 @@ static struct lkm_dev _module = { IPL_VERSION, CDEV_MAJOR, LM_DT_CHAR, - { (void *)&ipl_cdevsw } + { (void *)&ipf_cdevsw } }; # endif -int if_ipl __P((struct lkm_table *, int, int)); +int if_ipf __P((struct lkm_table *, int, int)); -int if_ipl(lkmtp, cmd, ver) -struct lkm_table *lkmtp; -int cmd, ver; +int if_ipf(lkmtp, cmd, ver) + struct lkm_table *lkmtp; + int cmd, ver; { # if (__FreeBSD_version >= 300000) - MOD_DISPATCH(if_ipl, lkmtp, cmd, ver, iplaction, iplaction, iplaction); + MOD_DISPATCH(if_ipf, lkmtp, cmd, ver, ipfaction, ipfaction, ipfaction); # else - DISPATCH(lkmtp, cmd, ver, iplaction, iplaction, iplaction); + DISPATCH(lkmtp, cmd, ver, ipfaction, ipfaction, ipfaction); # endif } # endif /* IPFILTER_LKM */ -static ipl_devsw_installed = 0; +static ipf_devsw_installed = 0; -static void ipl_drvinit __P((void *unused)) +static void ipf_drvinit __P((void *unused)) { dev_t dev; # ifdef DEVFS void **tp = ipf_devfs; # endif - if (!ipl_devsw_installed ) { + if (!ipf_devsw_installed ) { dev = makedev(CDEV_MAJOR, 0); - cdevsw_add(&dev, &ipl_cdevsw, NULL); - ipl_devsw_installed = 1; + cdevsw_add(&dev, &ipf_cdevsw, NULL); + ipf_devsw_installed = 1; # ifdef DEVFS - tp[IPL_LOGIPF] = devfs_add_devswf(&ipl_cdevsw, IPL_LOGIPF, + tp[IPL_LOGIPF] = devfs_add_devswf(&ipf_cdevsw, IPL_LOGIPF, DV_CHR, 0, 0, 0600, "ipf"); - tp[IPL_LOGNAT] = devfs_add_devswf(&ipl_cdevsw, IPL_LOGNAT, + tp[IPL_LOGNAT] = devfs_add_devswf(&ipf_cdevsw, IPL_LOGNAT, DV_CHR, 0, 0, 0600, "ipnat"); - tp[IPL_LOGSTATE] = devfs_add_devswf(&ipl_cdevsw, IPL_LOGSTATE, + tp[IPL_LOGSTATE] = devfs_add_devswf(&ipf_cdevsw, IPL_LOGSTATE, DV_CHR, 0, 0, 0600, "ipstate"); - tp[IPL_LOGAUTH] = devfs_add_devswf(&ipl_cdevsw, IPL_LOGAUTH, + tp[IPL_LOGAUTH] = devfs_add_devswf(&ipf_cdevsw, IPL_LOGAUTH, DV_CHR, 0, 0, 0600, "ipauth"); # endif @@ -450,7 +450,7 @@ sysctl_ipf_int SYSCTL_HANDLER_ARGS if (!arg1) error = EPERM; else { - if ((oidp->oid_kind & CTLFLAG_OFF) && (fr_running > 0)) + if ((oidp->oid_kind & CTLFLAG_OFF) && (ipf_running > 0)) error = EBUSY; else error = SYSCTL_IN(req, arg1, sizeof(int)); @@ -462,6 +462,133 @@ sysctl_ipf_int SYSCTL_HANDLER_ARGS # if defined(IPFILTER_LKM) || \ defined(__FreeBSD_version) && (__FreeBSD_version >= 220000) -SYSINIT(ipldev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ipl_drvinit,NULL) +SYSINIT(ipfdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ipf_drvinit,NULL) # endif /* IPFILTER_LKM */ #endif /* _FreeBSD_version */ + + +/* + * routines below for saving IP headers to buffer + */ +int ipfopen(dev, flags +#if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) +, devtype, p) + int devtype; +# if (__FreeBSD_version >= 500024) + struct thread *p; +# else + struct proc *p; +# endif /* __FreeBSD_version >= 500024 */ +#else +) +#endif +#if (__FreeBSD_version >= 502116) + struct cdev *dev; +#else + dev_t dev; +#endif + int flags; +{ + u_int unit = GET_MINOR(dev); + + if (IPL_LOGMAX < unit) + unit = ENXIO; + else + unit = 0; + return unit; +} + + +int ipfclose(dev, flags +#if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) +, devtype, p) + int devtype; +# if (__FreeBSD_version >= 500024) + struct thread *p; +# else + struct proc *p; +# endif /* __FreeBSD_version >= 500024 */ +#else +) +#endif +#if (__FreeBSD_version >= 502116) + struct cdev *dev; +#else + dev_t dev; +#endif + int flags; +{ + u_int unit = GET_MINOR(dev); + + if (IPL_LOGMAX < unit) + unit = ENXIO; + else + unit = 0; + return unit; +} + +/* + * ipfread/ipflog + * both of these must operate with at least splnet() lest they be + * called during packet processing and cause an inconsistancy to appear in + * the filter lists. + */ +#if (BSD >= 199306) +int ipfread(dev, uio, ioflag) + int ioflag; +#else +int ipfread(dev, uio) +#endif +#if (__FreeBSD_version >= 502116) + struct cdev *dev; +#else + dev_t dev; +#endif + register struct uio *uio; +{ + u_int unit = GET_MINOR(dev); + + if (unit < 0) + return ENXIO; + + if (ipf_running < 1) + return EIO; + + if (unit == IPL_LOGSYNC) + return ipfsync_read(uio); + +#ifdef IPFILTER_LOG + return ipflog_read(unit, uio); +#else + return ENXIO; +#endif +} + + +/* + * ipfwrite + * both of these must operate with at least splnet() lest they be + * called during packet processing and cause an inconsistancy to appear in + * the filter lists. + */ +#if (BSD >= 199306) +int ipfwrite(dev, uio, ioflag) + int ioflag; +#else +int ipfwrite(dev, uio) +#endif +#if (__FreeBSD_version >= 502116) + struct cdev *dev; +#else + dev_t dev; +#endif + register struct uio *uio; +{ + + if (ipf_running < 1) + return EIO; + + if (GET_MINOR(dev) == IPL_LOGSYNC) + return ipfsync_write(uio); + return ENXIO; +} diff --git a/mlf_rule.c b/mlf_rule.c index c540ebde5faab..ded884bd4d734 100644 --- a/mlf_rule.c +++ b/mlf_rule.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -77,8 +77,8 @@ static int ipfrule_ioctl __P((struct lkm_table *, int)); #if defined(__FreeBSD_version) && (__FreeBSD_version < 220000) int xxxinit(lkmtp, cmd, ver) -struct lkm_table *lkmtp; -int cmd, ver; + struct lkm_table *lkmtp; + int cmd, ver; { DISPATCH(lkmtp, cmd, ver, ipfrule_ioctl, ipfrule_ioctl, ipfrule_ioctl); } @@ -105,8 +105,8 @@ int ipfrule __P((struct lkm_table *, int, int)); int ipfrule(lkmtp, cmd, ver) -struct lkm_table *lkmtp; -int cmd, ver; + struct lkm_table *lkmtp; + int cmd, ver; { # if (__FreeBSD_version >= 300000) MOD_DISPATCH(ipfrule, lkmtp, cmd, ver, ipfrule_ioctl, ipfrule_ioctl, @@ -119,24 +119,24 @@ int cmd, ver; int ipfrule_load(lkmtp, cmd) -struct lkm_table *lkmtp; -int cmd; + struct lkm_table *lkmtp; + int cmd; { return ipfrule_add(); } int ipfrule_unload(lkmtp, cmd) -struct lkm_table *lkmtp; -int cmd; + struct lkm_table *lkmtp; + int cmd; { return ipfrule_remove(); } static int ipfrule_ioctl(lkmtp, cmd) -struct lkm_table *lkmtp; -int cmd; + struct lkm_table *lkmtp; + int cmd; { int err = 0; @@ -148,12 +148,12 @@ int cmd; err = ipfrule_load(lkmtp, cmd); if (!err) - fr_refcnt++; + ipf_refcnt++; break; case LKM_E_UNLOAD : err = ipfrule_unload(lkmtp, cmd); if (!err) - fr_refcnt--; + ipf_refcnt--; break; case LKM_E_STAT : break; diff --git a/mlfk_ipl.c b/mlfk_ipl.c index 0f50feab0f597..0ef3a0d6cf48e 100644 --- a/mlfk_ipl.c +++ b/mlfk_ipl.c @@ -1,7 +1,5 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 2000 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -14,18 +12,25 @@ #include <sys/conf.h> #include <sys/socket.h> #include <sys/sysctl.h> +#include <sys/select.h> +#if __FreeBSD_version >= 500000 +# include <sys/selinfo.h> +#endif #include <net/if.h> #include <netinet/in_systm.h> #include <netinet/in.h> -#include <netinet/ipl.h> -#include <netinet/ip_compat.h> -#include <netinet/ip_fil.h> -#include <netinet/ip_state.h> -#include <netinet/ip_nat.h> -#include <netinet/ip_auth.h> -#include <netinet/ip_frag.h> +#include "netinet/ipl.h" +#include "netinet/ip_compat.h" +#include "netinet/ip_fil.h" +#include "netinet/ip_state.h" +#include "netinet/ip_nat.h" +#include "netinet/ip_auth.h" +#include "netinet/ip_frag.h" +#include "netinet/ip_sync.h" + +extern ipf_main_softc_t ipfmain; #if __FreeBSD_version >= 502116 static struct cdev *ipf_devs[IPL_LOGSIZE]; @@ -33,10 +38,34 @@ static struct cdev *ipf_devs[IPL_LOGSIZE]; static dev_t ipf_devs[IPL_LOGSIZE]; #endif +#if 0 static int sysctl_ipf_int ( SYSCTL_HANDLER_ARGS ); +#endif static int ipf_modload(void); static int ipf_modunload(void); +#if (__FreeBSD_version >= 500024) +# if (__FreeBSD_version >= 502116) +static int ipfopen __P((struct cdev*, int, int, struct thread *)); +static int ipfclose __P((struct cdev*, int, int, struct thread *)); +# else +static int ipfopen __P((dev_t, int, int, struct thread *)); +static int ipfclose __P((dev_t, int, int, struct thread *)); +# endif /* __FreeBSD_version >= 502116 */ +#else +static int ipfopen __P((dev_t, int, int, struct proc *)); +static int ipfclose __P((dev_t, int, int, struct proc *)); +#endif +#if (__FreeBSD_version >= 502116) +static int ipfread __P((struct cdev*, struct uio *, int)); +static int ipfwrite __P((struct cdev*, struct uio *, int)); +#else +static int ipfread __P((dev_t, struct uio *, int)); +static int ipfwrite __P((dev_t, struct uio *, int)); +#endif /* __FreeBSD_version >= 502116 */ + + + SYSCTL_DECL(_net_inet); #define SYSCTL_IPF(parent, nbr, name, access, ptr, val, descr) \ SYSCTL_OID(parent, nbr, name, CTLTYPE_INT|access, \ @@ -44,79 +73,91 @@ SYSCTL_DECL(_net_inet); #define CTLFLAG_OFF 0x00800000 /* IPFilter must be disabled */ #define CTLFLAG_RWO (CTLFLAG_RW|CTLFLAG_OFF) SYSCTL_NODE(_net_inet, OID_AUTO, ipf, CTLFLAG_RW, 0, "IPF"); -SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &fr_flags, 0, ""); -SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_pass, CTLFLAG_RW, &fr_pass, 0, ""); -SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &fr_active, 0, ""); +#if 0 +SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &ipf_flags, 0, ""); +SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_pass, CTLFLAG_RW, &ipf_pass, 0, ""); +SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &ipf_active, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RWO, - &fr_tcpidletimeout, 0, ""); + &ipf_tcpidletimeout, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RWO, - &fr_tcphalfclosed, 0, ""); + &ipf_tcphalfclosed, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RWO, - &fr_tcpclosewait, 0, ""); + &ipf_tcpclosewait, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RWO, - &fr_tcplastack, 0, ""); + &ipf_tcplastack, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RWO, - &fr_tcptimeout, 0, ""); + &ipf_tcptimeout, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RWO, - &fr_tcpclosed, 0, ""); + &ipf_tcpclosed, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RWO, - &fr_udptimeout, 0, ""); + &ipf_udptimeout, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udpacktimeout, CTLFLAG_RWO, - &fr_udpacktimeout, 0, ""); + &ipf_udpacktimeout, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RWO, - &fr_icmptimeout, 0, ""); + &ipf_icmptimeout, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defnatage, CTLFLAG_RWO, - &fr_defnatage, 0, ""); + &ipf_nat_defage, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_ipfrttl, CTLFLAG_RW, - &fr_ipfrttl, 0, ""); -SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_running, CTLFLAG_RD, - &fr_running, 0, ""); + &ipf_ipfrttl, 0, ""); +SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_running, CTLFLAG_RD, + &ipf_running, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statesize, CTLFLAG_RWO, - &fr_statesize, 0, ""); + &ipf_state_size, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statemax, CTLFLAG_RWO, - &fr_statemax, 0, ""); + &ipf_state_max, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_nattable_sz, CTLFLAG_RWO, - &ipf_nattable_sz, 0, ""); + &ipf_nat_table_sz, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_natrules_sz, CTLFLAG_RWO, - &ipf_natrules_sz, 0, ""); + &ipf_nat_maprules_sz, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_rdrrules_sz, CTLFLAG_RWO, - &ipf_rdrrules_sz, 0, ""); + &ipf_nat_rdrrules_sz, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_hostmap_sz, CTLFLAG_RWO, - &ipf_hostmap_sz, 0, ""); + &ipf_nat_hostmap_sz, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authsize, CTLFLAG_RWO, - &fr_authsize, 0, ""); + &ipf_auth_size, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authused, CTLFLAG_RD, - &fr_authused, 0, ""); + &ipf_auth_used, 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defaultauthage, CTLFLAG_RW, - &fr_defaultauthage, 0, ""); -SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &fr_chksrc, 0, ""); -SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &fr_minttl, 0, ""); + &ipf_auth_defaultage, 0, ""); +SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &ipf_chksrc, 0, ""); +SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &ipf_minttl, 0, ""); +#endif #define CDEV_MAJOR 79 -#if __FreeBSD_version >= 501000 -static struct cdevsw ipl_cdevsw = { +#include <sys/poll.h> +#if __FreeBSD_version >= 500043 +# include <sys/select.h> +static int ipfpoll(struct cdev *dev, int events, struct thread *td); + +static struct cdevsw ipf_cdevsw = { #if __FreeBSD_version >= 502103 .d_version = D_VERSION, .d_flags = 0, /* D_NEEDGIANT - Should be SMP safe */ #endif - .d_open = iplopen, - .d_close = iplclose, - .d_read = iplread, - .d_ioctl = iplioctl, - .d_name = "ipl", + .d_open = ipfopen, + .d_close = ipfclose, + .d_read = ipfread, + .d_write = ipfwrite, + .d_ioctl = ipfioctl, + .d_poll = ipfpoll, + .d_name = "ipf", +#if __FreeBSD_version < 600000 .d_maj = CDEV_MAJOR, +#endif }; #else -static struct cdevsw ipl_cdevsw = { - /* open */ iplopen, - /* close */ iplclose, - /* read */ iplread, - /* write */ iplwrite, - /* ioctl */ iplioctl, - /* poll */ nopoll, +static int ipfpoll(dev_t dev, int events, struct proc *td); + +static struct cdevsw ipf_cdevsw = { + /* open */ ipfopen, + /* close */ ipfclose, + /* read */ ipfread, + /* write */ ipfwrite, + /* ioctl */ ipfioctl, + /* poll */ ipfpoll, /* mmap */ nommap, /* strategy */ nostrategy, - /* name */ "ipl", + /* name */ "ipf", /* maj */ CDEV_MAJOR, /* dump */ nodump, /* psize */ nopsize, @@ -124,7 +165,9 @@ static struct cdevsw ipl_cdevsw = { # if (__FreeBSD_version < 500043) /* bmaj */ -1, # endif +# if (__FreeBSD_version >= 430000) /* kqfilter */ NULL +# endif }; #endif @@ -160,7 +203,13 @@ ipf_modload() char *defpass, *c, *str; int i, j, error; - error = iplattach(); + if (ipf_load_all() != 0) + return EIO; + + if (ipf_create_all(&ipfmain) == NULL) + return EIO; + + error = ipfattach(&ipfmain); if (error) return error; @@ -176,18 +225,23 @@ ipf_modload() } if (!c) c = str; - ipf_devs[i] = make_dev(&ipl_cdevsw, i, 0, 0, 0600, c); + ipf_devs[i] = make_dev(&ipf_cdevsw, i, 0, 0, 0600, c); } - if (FR_ISPASS(fr_pass)) + error = ipf_pfil_hook(); + if (error != 0) + return error; + ipf_event_reg(); + + if (FR_ISPASS(ipfmain.ipf_pass)) defpass = "pass"; - else if (FR_ISBLOCK(fr_pass)) + else if (FR_ISBLOCK(ipfmain.ipf_pass)) defpass = "block"; - else + else defpass = "no-match -> block"; printf("%s initialized. Default = %s all, Logging = %s%s\n", - ipfilter_version, defpass, + ipfilter_version, defpass, #ifdef IPFILTER_LOG "enabled", #else @@ -198,7 +252,7 @@ ipf_modload() #else "" #endif - ); + ); return 0; } @@ -208,17 +262,24 @@ ipf_modunload() { int error, i; - if (fr_refcnt) + if (ipfmain.ipf_refcnt) return EBUSY; - if (fr_running >= 0) { - error = ipldetach(); + error = ipf_pfil_unhook(); + if (error != 0) + return error; + + if (ipfmain.ipf_running >= 0) { + error = ipfdetach(&ipfmain); if (error != 0) return error; + + ipf_destroy_all(&ipfmain); + ipf_unload_all(); } else error = 0; - fr_running = -2; + ipfmain.ipf_running = -2; for (i = 0; ipf_devfiles[i]; i++) { if (ipf_devs[i] != NULL) @@ -244,6 +305,7 @@ MODULE_VERSION(ipfilter, 1); #endif +#if 0 #ifdef SYSCTL_IPF int sysctl_ipf_int ( SYSCTL_HANDLER_ARGS ) @@ -261,7 +323,7 @@ sysctl_ipf_int ( SYSCTL_HANDLER_ARGS ) if (!arg1) error = EPERM; else { - if ((oidp->oid_kind & CTLFLAG_OFF) && (fr_running > 0)) + if ((oidp->oid_kind & CTLFLAG_OFF) && (ipfmain.ipf_running > 0)) error = EBUSY; else error = SYSCTL_IN(req, arg1, sizeof(int)); @@ -269,3 +331,197 @@ sysctl_ipf_int ( SYSCTL_HANDLER_ARGS ) return (error); } #endif +#endif + + +static int +#if __FreeBSD_version >= 500043 +ipfpoll(struct cdev *dev, int events, struct thread *td) +#else +ipfpoll(dev_t dev, int events, struct proc *td) +#endif +{ + u_int unit = GET_MINOR(dev); + int revents; + + if (unit < 0 || unit > IPL_LOGMAX) + return 0; + + revents = 0; + + switch (unit) + { + case IPL_LOGIPF : + case IPL_LOGNAT : + case IPL_LOGSTATE : +#ifdef IPFILTER_LOG + if ((events & (POLLIN | POLLRDNORM)) && ipf_log_canread(&ipfmain, unit)) + revents |= events & (POLLIN | POLLRDNORM); +#endif + break; + case IPL_LOGAUTH : + if ((events & (POLLIN | POLLRDNORM)) && ipf_auth_waiting(&ipfmain)) + revents |= events & (POLLIN | POLLRDNORM); + break; + case IPL_LOGSYNC : + if ((events & (POLLIN | POLLRDNORM)) && ipf_sync_canread(&ipfmain)) + revents |= events & (POLLIN | POLLRDNORM); + if ((events & (POLLOUT | POLLWRNORM)) && ipf_sync_canwrite(&ipfmain)) + revents |= events & (POLLOUT | POLLWRNORM); + break; + case IPL_LOGSCAN : + case IPL_LOGLOOKUP : + default : + break; + } + + if ((revents == 0) && ((events & (POLLIN|POLLRDNORM)) != 0)) + selrecord(td, &ipfmain.ipf_selwait[unit]); + + return revents; +} + + +/* + * routines below for saving IP headers to buffer + */ +static int ipfopen(dev, flags +#if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) +, devtype, p) + int devtype; +# if (__FreeBSD_version >= 500024) + struct thread *p; +# else + struct proc *p; +# endif /* __FreeBSD_version >= 500024 */ +#else +) +#endif +#if (__FreeBSD_version >= 502116) + struct cdev *dev; +#else + dev_t dev; +#endif + int flags; +{ + u_int unit = GET_MINOR(dev); + int error; + + if (IPL_LOGMAX < unit) + error = ENXIO; + else { + switch (unit) + { + case IPL_LOGIPF : + case IPL_LOGNAT : + case IPL_LOGSTATE : + case IPL_LOGAUTH : + case IPL_LOGLOOKUP : + case IPL_LOGSYNC : +#ifdef IPFILTER_SCAN + case IPL_LOGSCAN : +#endif + error = 0; + break; + default : + error = ENXIO; + break; + } + } + return error; +} + + +static int ipfclose(dev, flags +#if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) +, devtype, p) + int devtype; +# if (__FreeBSD_version >= 500024) + struct thread *p; +# else + struct proc *p; +# endif /* __FreeBSD_version >= 500024 */ +#else +) +#endif +#if (__FreeBSD_version >= 502116) + struct cdev *dev; +#else + dev_t dev; +#endif + int flags; +{ + u_int unit = GET_MINOR(dev); + + if (IPL_LOGMAX < unit) + unit = ENXIO; + else + unit = 0; + return unit; +} + +/* + * ipfread/ipflog + * both of these must operate with at least splnet() lest they be + * called during packet processing and cause an inconsistancy to appear in + * the filter lists. + */ +#if (BSD >= 199306) +static int ipfread(dev, uio, ioflag) + int ioflag; +#else +static int ipfread(dev, uio) +#endif +#if (__FreeBSD_version >= 502116) + struct cdev *dev; +#else + dev_t dev; +#endif + struct uio *uio; +{ + u_int unit = GET_MINOR(dev); + + if (unit < 0) + return ENXIO; + + if (ipfmain.ipf_running < 1) + return EIO; + + if (unit == IPL_LOGSYNC) + return ipf_sync_read(&ipfmain, uio); + +#ifdef IPFILTER_LOG + return ipf_log_read(&ipfmain, unit, uio); +#else + return ENXIO; +#endif +} + + +/* + * ipfwrite + * both of these must operate with at least splnet() lest they be + * called during packet processing and cause an inconsistancy to appear in + * the filter lists. + */ +#if (BSD >= 199306) +static int ipfwrite(dev, uio, ioflag) + int ioflag; +#else +static int ipfwrite(dev, uio) +#endif +#if (__FreeBSD_version >= 502116) + struct cdev *dev; +#else + dev_t dev; +#endif + struct uio *uio; +{ + + if (ipfmain.ipf_running < 1) + return EIO; + + if (GET_MINOR(dev) == IPL_LOGSYNC) + return ipf_sync_write(&ipfmain, uio); + return ENXIO; +} diff --git a/mlfk_rule.c b/mlfk_rule.c index c17507613d872..6b473bb70545d 100644 --- a/mlfk_rule.c +++ b/mlfk_rule.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2000 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: mlfk_rule.c,v 2.4.4.2 2004/04/16 23:32:08 darrenr Exp $ + * $Id$ */ @@ -28,6 +28,7 @@ #include "ip_rules.h" +extern ipf_main_softc_t ipfmain; static int ipfrule_modevent(module_t mod, int type, void *unused) @@ -39,12 +40,12 @@ ipfrule_modevent(module_t mod, int type, void *unused) case MOD_LOAD : error = ipfrule_add(); if (!error) - fr_refcnt++; + ipfmain.ipf_refcnt++; break; case MOD_UNLOAD : error = ipfrule_remove(); if (!error) - fr_refcnt--; + ipfmain.ipf_refcnt--; break; default: error = EINVAL; diff --git a/mlh_rule.c b/mlh_rule.c index e71c7be1c0b70..381e32c2004fa 100644 --- a/mlh_rule.c +++ b/mlh_rule.c @@ -1,7 +1,5 @@ -/* $NetBSD$ */ - /* - * Copyright (C) 1993-1998 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * @@ -88,7 +86,7 @@ static int ipf_load(void *arg) i = ipfrule_add(); if (!i) - fr_refcnt--; + ipf_refcnt--; #ifdef IPFDEBUG printf("IP Filter Rules: ipfrule_add() = %d\n", i); #endif @@ -104,7 +102,7 @@ static int ipf_unload(void *arg) i = ipfrule_remove(); if (!i) - fr_refcnt--; + ipf_refcnt--; #ifdef IPFDEBUG printf("IP Filter Rules: ipfrule_remove() = %d\n", i); #endif diff --git a/mli_ipl.c b/mli_ipl.c index 235a5af21f173..4e7181c827708 100644 --- a/mli_ipl.c +++ b/mli_ipl.c @@ -1,8 +1,9 @@ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * (C)opyright 1997 by Marc Boucher. * * See the IPFILTER.LICENCE file for details on licencing. + * */ /* TODO: (MARCXXX) @@ -40,17 +41,25 @@ #include "ip_fil.h" #include "ip_nat.h" -/*#define IPFDEBUG 1*/ +#ifndef MBUF_IS_CLUSTER +# define MBUF_IS_CLUSTER(m) ((m)->m_flags & MCL_CLUSTER) +#endif +#undef IPFDEBUG /* #define IPFDEBUG 9 */ -unsigned IPL_EXTERN(devflag) = D_MP; #ifdef IPFILTER_LKM -char *IPL_EXTERN(mversion) = M_VERSION; +u_int ipldevflag = D_MP; +char *iplmversion = M_VERSION; +#else +u_int ipfilterdevflag = D_MP; +char *ipfiltermversion = M_VERSION; #endif -kmutex_t ipl_mutex, ipf_mutex, ipfi_mutex, ipf_rw; -kmutex_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth; +ipfmutex_t ipl_mutex, ipfi_mutex, ipf_rw, ipf_stinsert, ipf_auth_mx; +ipfmutex_t ipf_nat_new, ipf_natio, ipf_timeoutlock; +ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth; +ipfrwlock_t ipf_global, ipf_mutex, ipf_ipidfrag, ipf_frcache, ipf_tokens; -int (*fr_checkp) __P((struct ip *, int, void *, int, mb_t **)); +int (*ipf_checkp) __P((struct ip *, int, void *, int, mb_t **)); #ifdef IPFILTER_LKM static int *ipff_addr = 0; @@ -58,102 +67,143 @@ static int ipff_value; static __psunsigned_t *ipfk_addr = 0; static __psunsigned_t ipfk_code[4]; #endif +static void nifattach(); +static void nifdetach(); typedef struct nif { struct nif *nf_next; struct ifnet *nf_ifp; -#if IRIX < 605 +#if (IRIX < 60500) int (*nf_output)(struct ifnet *, struct mbuf *, struct sockaddr *); #else int (*nf_output)(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); #endif - char nf_name[IFNAMSIZ]; + char nf_name[LIFNAMSIZ]; int nf_unit; } nif_t; static nif_t *nif_head = 0; static int nif_interfaces = 0; extern int in_interfaces; +#if IRIX >= 60500 +toid_t ipf_timer_id; +#endif extern ipnat_t *nat_list; +#ifdef IPFDEBUG +static void ipf_dumppacket(m) + struct mbuf *m; +{ + u_char *s; + char *t, line[80]; + int len, off, i; + + off = 0; + + while (m != NULL) { + len = M_LEN(m); + s = mtod(m, u_char *); + printf("mbuf 0x%lx len %d flags %x type %d\n", + m, len, m->m_flags, m->m_type); + printf("dat 0x%lx off 0x%lx/%d s 0x%lx next 0x%lx\n", + m->m_dat, m->m_off, m->m_off, s, m->m_next); + while (len > 0) { + t = line; + for (i = 0; (i < 16) && (len > 0); len--, i++) + sprintf(t, " %02x", *s++), t += strlen(t); + *s = '\0'; + printf("mbuf:%x:%s\n", off, line); + off += 16; + } + m = m->m_next; + } +} +#endif + + static int -#if IRIX < 605 +#if IRIX < 60500 ipl_if_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst) #else ipl_if_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt) #endif { +#if (IPFDEBUG >= 0) + static unsigned int cnt = 0; +#endif nif_t *nif; MUTEX_ENTER(&ipfi_mutex); /* sets interrupt priority level to splhi */ for (nif = nif_head; nif; nif = nif->nf_next) if (nif->nf_ifp == ifp) break; - MUTEX_EXIT(&ipfi_mutex); - if (!nif) { + + if (nif == NULL) { printf("IP Filter: ipl_if_output intf %x NOT FOUND\n", ifp); return ENETDOWN; } -#if IPFDEBUG >= 4 - static unsigned int cnt = 0; +#if (IPFDEBUG >= 7) if ((++cnt % 200) == 0) - printf("IP Filter: ipl_if_output(ifp=0x%lx, m=0x%lx, dst=0x%lx), m_type=%d m_flags=0x%lx m_off=0x%lx\n", ifp, m, dst, m->m_type, (unsigned long)(m->m_flags), m->m_off); + printf("IP Filter: ipl_if_output(ifp=0x%lx, m=0x%lx, dst=0x%lx), m_type=%d m_flags=0x%lx m_off=0x%lx\n", ifp, m, dst, m->m_type, (u_long)m->m_flags, m->m_off); #endif - if (fr_checkp) { + + if (ipf_checkp) { struct mbuf *m1 = m; struct ip *ip; int hlen; - switch(m->m_type) { + switch(m->m_type) + { + case MT_HEADER: + if (m->m_len == 0) { + if (m->m_next == NULL) + break; + m = m->m_next; + } + /* FALLTHROUGH */ case MT_DATA: - if (m->m_flags & M_BCAST) { -#if IPFDEBUG >= 2 - printf("IP Filter: ipl_if_output: passing M_BCAST\n"); + if (!MBUF_IS_CLUSTER(m) && + ((m->m_off < MMINOFF) || (m->m_off > MMAXOFF))) { +#if (IPFDEBUG >= 4) + printf("IP Filter: ipl_if_output: bad m_off m_type=%d m_flags=0x%lx m_off=0x%lx\n", m->m_type, (u_long)m->m_flags, m->m_off); #endif break; } - /* FALLTHROUGH */ - case MT_HEADER: -#if IPFDEBUG >= 4 - if (!MBUF_IS_CLUSTER(m) && ((m->m_off < MMINOFF) || (m->m_off > MMAXOFF))) { - printf("IP Filter: ipl_if_output: bad m_off m_type=%d m_flags=0x%lx m_off=0x%lx\n", m->m_type, (unsigned long)(m->m_flags), m->m_off); - goto done; - } -#endif if (m->m_len < sizeof(char)) { - printf("IP Filter: ipl_if_output: mbuf block too small (m_len=%d) for IP vers+hlen, m_type=%d m_flags=0x%lx\n", m->m_len, m->m_type, (unsigned long)(m->m_flags)); - goto done; +#if (IPFDEBUG >= 3) + printf("IP Filter: ipl_if_output: mbuf block too small (m_len=%d) for IP vers+hlen, m_type=%d m_flags=0x%lx\n", m->m_len, m->m_type, (u_long)m->m_flags); +#endif + break; } ip = mtod(m, struct ip *); if (ip->ip_v != IPVERSION) { -#if IPFDEBUG >= 4 - printf("IP Filter: ipl_if_output: bad ip_v m_type=%d m_flags=0x%lx m_off=0x%lx\n", m->m_type, (unsigned long)(m->m_flags), m->m_off); +#if (IPFDEBUG >= 2) + ipf_dumppacket(m); + printf("IP Filter: ipl_if_output: bad ip_v m_type=%d m_flags=0x%lx m_off=0x%lx\n", m->m_type, (u_long)m->m_flags, m->m_off); #endif - goto done; + break; } hlen = ip->ip_hl << 2; - if ((*fr_checkp)(ip, hlen, ifp, 1, &m1)) + if ((*ipf_checkp)(ip, hlen, ifp, 1, &m1) || (m1 == NULL)) return EHOSTUNREACH; - if (!m1) - return 0; - m = m1; break; default: - printf("IP Filter: ipl_if_output: bad m_type=%d m_flags=0x%lxm_off=0x%lx\n", m->m_type, (unsigned long)(m->m_flags), m->m_off); +#if (IPFDEBUG >= 2) + printf("IP Filter: ipl_if_output: bad m_type=%d m_flags=0x%lxm_off=0x%lx\n", m->m_type, (u_long)m->m_flags, m->m_off); +#endif break; } } -done: -#if IRIX < 605 +#if (IRIX < 60500) return (*nif->nf_output)(ifp, m, dst); #else return (*nif->nf_output)(ifp, m, dst, rt); @@ -161,93 +211,120 @@ done: } int -IPL_EXTERN(_kernel)(struct ifnet *rcvif, struct mbuf *m) + + +#if !defined(IPFILTER_LKM) && (IRIX >= 60500) +ipfilter_kernel(struct ifnet *rcvif, struct mbuf *m) +#else +ipl_kernel(struct ifnet *rcvif, struct mbuf *m) +#endif { -#if IPFDEBUG >= 4 +#if (IPFDEBUG >= 7) static unsigned int cnt = 0; + if ((++cnt % 200) == 0) - printf("IP Filter: ipl_ipfilter_kernel(rcvif=0x%lx, m=0x%lx\n", rcvif, m); + printf("IP Filter: ipl_kernel(rcvif=0x%lx, m=0x%lx\n", + rcvif, m); #endif + if (ipf_running <= 0) + return IPF_ACCEPTIT; + /* * Check if we want to allow this packet to be processed. * Consider it to be bad if not. */ - if (fr_checkp) { + if (ipf_checkp) { struct mbuf *m1 = m; struct ip *ip; int hlen; if ((m->m_type != MT_DATA) && (m->m_type != MT_HEADER)) { - printf("IP Filter: ipl_ipfilter_kernel: bad m_type=%d m_flags=0x%lx m_off=0x%lx\n", m->m_type, (unsigned long)(m->m_flags), m->m_off); +#if (IPFDEBUG >= 4) + printf("IP Filter: ipl_kernel: bad m_type=%d m_flags=0x%lx m_off=0x%lx\n", m->m_type, (u_long)m->m_flags, m->m_off); +#endif return IPF_ACCEPTIT; } -#if IPFDEBUG >= 4 - if (!MBUF_IS_CLUSTER(m) && ((m->m_off < MMINOFF) || (m->m_off > MMAXOFF))) { - printf("IP Filter: ipl_ipfilter_kernel: bad m_off m_type=%d m_flags=0x%lx m_off=0x%lx\n", m->m_type, (unsigned long)(m->m_flags), m->m_off); + if (!MBUF_IS_CLUSTER(m) && + ((m->m_off < MMINOFF) || (m->m_off > MMAXOFF))) { +#if (IPFDEBUG >= 4) + printf("IP Filter: ipl_kernel: bad m_off m_type=%d m_flags=0x%lx m_off=0x%lx\n", m->m_type, (u_long)m->m_flags, m->m_off); +#endif return IPF_ACCEPTIT; } -#endif + if (m->m_len < sizeof(char)) { - printf("IP Filter: ipl_ipfilter_kernel: mbuf block too small (m_len=%d) for IP vers+hlen, m_type=%d m_flags=0x%lx\n", m->m_len, m->m_type, (unsigned long)(m->m_flags)); +#if (IPFDEBUG >= 1) + printf("IP Filter: ipl_kernel: mbuf block too small (m_len=%d) for IP vers+hlen, m_type=%d m_flags=0x%lx\n", m->m_len, m->m_type, (u_long)m->m_flags); +#endif return IPF_ACCEPTIT; } + ip = mtod(m, struct ip *); if (ip->ip_v != IPVERSION) { - printf("IP Filter: ipl_ipfilter_kernel: bad ip_v\n"); +#if (IPFDEBUG >= 4) + printf("IP Filter: ipl_kernel: bad ip_v\n"); +#endif m_freem(m); return IPF_DROPIT; } + ip->ip_len = htons(ip->ip_len); + ip->ip_off = htons(ip->ip_off); hlen = ip->ip_hl << 2; - if ((*fr_checkp)(ip, hlen, rcvif, 0, &m1) || !m1) + if ((*ipf_checkp)(ip, hlen, rcvif, 0, &m1) || !m1) return IPF_DROPIT; + ip = mtod(m1, struct ip *); + ip->ip_len = ntohs(ip->ip_len); + ip->ip_off = ntohs(ip->ip_off); + +#if (IPFDEBUG >= 2) if (m != m1) - printf("IP Filter: ipl_ipfilter_kernel: m != m1\n"); + printf("IP Filter: ipl_kernel: m != m1\n"); +#endif } return IPF_ACCEPTIT; } -static int -ipfilterattach(void) +int +ipl_ipfilter_attach(void) { -#ifdef IPFILTER_LKM +#if defined(IPFILTER_LKM) __psunsigned_t *addr_ff, *addr_fk; st_findaddr("ipfilterflag", &addr_ff); -#if IPFDEBUG >= 4 +# if (IPFDEBUG >= 1) printf("IP Filter: st_findaddr ipfilterflag=0x%lx\n", addr_ff); -#endif +# endif if (!addr_ff) return ESRCH; st_findaddr("ipfilter_kernel", &addr_fk); -#if IPFDEBUG >= 4 +# if (IPFDEBUG >= 1) printf("IP Filter: st_findaddr ipfilter_kernel=0x%lx\n", addr_fk); -#endif +# endif if (!addr_fk) return ESRCH; MUTEX_ENTER(&ipfi_mutex); /* sets interrupt priority level to splhi */ ipff_addr = (int *)addr_ff; - + ipff_value = *ipff_addr; *ipff_addr = 0; ipfk_addr = addr_fk; - bcopy(ipfk_addr, ipfk_code, - sizeof(ipfk_code)); + bcopy(ipfk_addr, ipfk_code, sizeof(ipfk_code)); - /* write a "li t4, ipl_ipfilter_kernel" instruction */ + /* write a "li t4, ipl_kernel" instruction */ ipfk_addr[0] = 0x3c0c0000 | - (((__psunsigned_t)IPL_EXTERN(_kernel) >> 16) & 0xffff); + (((__psunsigned_t)ipl_kernel >> 16) & 0xffff); ipfk_addr[1] = 0x358c0000 | - ((__psunsigned_t)IPL_EXTERN(_kernel) & 0xffff); + ((__psunsigned_t)ipl_kernel & 0xffff); /* write a "jr t4" instruction" */ ipfk_addr[2] = 0x01800008; @@ -264,20 +341,23 @@ ipfilterattach(void) ipfilterflag = 1; #endif + nif_interfaces = 0; + nifattach(); return 0; } + /* * attach the packet filter to each non-loopback interface that is running */ static void nifattach() { + nif_t *nif, *qf2; struct ifnet *ifp; struct frentry *f; ipnat_t *np; - nif_t *nif; MUTEX_ENTER(&ipfi_mutex); /* sets interrupt priority level to splhi */ @@ -300,7 +380,7 @@ nifattach() ifp); continue; } -#if IPFDEBUG >= 4 +#if (IPFDEBUG >= 2) printf("IP Filter: nifattach nif %x opt %x\n", ifp, ifp->if_output); #endif @@ -312,7 +392,8 @@ nifattach() } nif->nf_ifp = ifp; - strncpy(nif->nf_name, ifp->if_name, sizeof(nif->nf_name)); + (void) strncpy(nif->nf_name, ifp->if_name, + sizeof(nif->nf_name)); nif->nf_name[sizeof(nif->nf_name) - 1] = '\0'; nif->nf_unit = ifp->if_unit; @@ -322,36 +403,41 @@ nifattach() /* * Activate any rules directly associated with this interface */ - MUTEX_ENTER(&ipf_mutex); - for (f = ipfilter[0][0]; f; f = f->fr_next) { + WRITE_ENTER(&ipf_mutex); + for (f = ipf_rules[0][0]; f; f = f->fr_next) { if ((f->fr_ifa == (struct ifnet *)-1)) { if (f->fr_ifname[0] && - (GETUNIT(f->fr_ifname, 4) == ifp)) + (GETIFP(f->fr_ifname, 4) == ifp)) f->fr_ifa = ifp; } } - for (f = ipfilter[1][0]; f; f = f->fr_next) { + for (f = ipf_rules[1][0]; f; f = f->fr_next) { if ((f->fr_ifa == (struct ifnet *)-1)) { if (f->fr_ifname[0] && - (GETUNIT(f->fr_ifname, 4) == ifp)) + (GETIFP(f->fr_ifname, 4) == ifp)) f->fr_ifa = ifp; } } - MUTEX_EXIT(&ipf_mutex); - MUTEX_ENTER(&ipf_nat); + RWLOCK_EXIT(&ipf_mutex); + WRITE_ENTER(&ipf_nat); for (np = nat_list; np; np = np->in_next) { - if ((np->in_ifp == (void *)-1)) { - if (np->in_ifname[0] && - (GETUNIT(np->in_ifname, 4) == ifp)) - np->in_ifp = (void *)ifp; + if ((np->in_ifps[0] == (void *)-1)) { + if (np->in_ifnames[0][0] && + (GETIFP(np->in_ifnames[0], 4) == ifp)) + np->in_ifps[0] = (void *)ifp; + } + if ((np->in_ifps[1] == (void *)-1)) { + if (np->in_ifnames[1][0] && + (GETIFP(np->in_ifnames[1], 4) == ifp)) + np->in_ifps[1] = (void *)ifp; } } - MUTEX_EXIT(&ipf_nat); + RWLOCK_EXIT(&ipf_nat); nif->nf_output = ifp->if_output; ifp->if_output = ipl_if_output; -#if IPFDEBUG >= 4 +#if (IPFDEBUG >= 2) printf("IP Filter: nifattach: ifp(%lx)->if_output FROM %lx TO %lx\n", ifp, nif->nf_output, ifp->if_output); #endif @@ -369,60 +455,6 @@ nifattach() return; } -/* - * look for bad consistancies between the list of interfaces the filter knows - * about and those which are currently configured. - */ -int -ipfsync(void) -{ - register struct frentry *f; - register ipnat_t *np; - register nif_t *nif, **qp; - register struct ifnet *ifp; - - MUTEX_ENTER(&ipfi_mutex); /* sets interrupt priority level to splhi */ - for (qp = &nif_head; (nif = *qp); ) { - for (ifp = ifnet; ifp; ifp = ifp->if_next) - if ((nif->nf_ifp == ifp) && - (nif->nf_unit == ifp->if_unit) && - !strcmp(nif->nf_name, ifp->if_name)) { - break; - } - if (ifp) { - qp = &nif->nf_next; - continue; - } - printf("IP Filter: detaching [%s]\n", nif->nf_name); - *qp = nif->nf_next; - - /* - * Disable any rules directly associated with this interface - */ - MUTEX_ENTER(&ipf_mutex); - for (f = ipfilter[0][0]; f; f = f->fr_next) - if (f->fr_ifa == (void *)nif->nf_ifp) - f->fr_ifa = (struct ifnet *)-1; - for (f = ipfilter[1][0]; f; f = f->fr_next) - if (f->fr_ifa == (void *)nif->nf_ifp) - f->fr_ifa = (struct ifnet *)-1; - MUTEX_EXIT(&ipf_mutex); - MUTEX_ENTER(&ipf_nat); - for (np = nat_list; np; np = np->in_next) - if (np->in_ifp == (void *)nif->nf_ifp) - np->in_ifp =(struct ifnet *)-1; - MUTEX_EXIT(&ipf_nat); - - KFREE(nif); - nif = *qp; - } - MUTEX_EXIT(&ipfi_mutex); - - nifattach(); - - return 0; -} - /* * unhook the IP filter from all defined interfaces with IP addresses @@ -430,8 +462,8 @@ ipfsync(void) static void nifdetach() { + nif_t *nif, *qf2, **qp; struct ifnet *ifp; - nif_t *nif, **qp; MUTEX_ENTER(&ipfi_mutex); /* sets interrupt priority level to splhi */ /* @@ -460,7 +492,7 @@ nifdetach() printf("IP Filter: detaching [%s,%d]\n", nif->nf_name, ifp->if_unit); -#if IPFDEBUG >= 4 +#if (IPFDEBUG >= 4) printf("IP Filter: nifdetach: ifp(%lx)->if_output FROM %lx TO %lx\n", ifp, ifp->if_output, nif->nf_output); #endif @@ -474,17 +506,20 @@ nifdetach() } -static void -ipfilterdetach(void) +void +ipl_ipfilter_detach(void) { #ifdef IPFILTER_LKM + nifdetach(); MUTEX_ENTER(&ipfi_mutex); /* sets interrupt priority level to splhi */ if (ipff_addr) { *ipff_addr = 0; - if (ipfk_addr) + if (ipfk_addr) { bcopy(ipfk_code, ipfk_addr, sizeof(ipfk_code)); + icache_inval(ipfk_addr - 16, sizeof(ipfk_code)+32); + } *ipff_addr = ipff_value; } @@ -493,45 +528,23 @@ ipfilterdetach(void) #else extern int ipfilterflag; - ipfilterflag = 0; -#endif -} - -/* called by ipldetach() */ -void -ipfilter_sgi_detach(void) -{ nifdetach(); - ipfilterdetach(); + ipfilterflag = 0; +#endif } -/* called by iplattach() */ -int -ipfilter_sgi_attach(void) -{ - int error; - - nif_interfaces = 0; - - error = ipfilterattach(); - - if (!error) - nifattach(); - - return error; -} -/* this function is called from ipfr_slowtimer at 500ms intervals to +/* this function is called from ipf_slowtimer at 500ms intervals to keep our interface list in sync */ void -ipfilter_sgi_intfsync(void) +ipl_ipfilter_intfsync(void) { MUTEX_ENTER(&ipfi_mutex); if (nif_interfaces != in_interfaces) { /* if the number of interfaces has changed, resync */ MUTEX_EXIT(&ipfi_mutex); - ipfsync(); + ipf_sync(&ipfmain, NULL); } else MUTEX_EXIT(&ipfi_mutex); } @@ -542,55 +555,127 @@ ipfilter_sgi_intfsync(void) sleep(), psema() or delay(). */ int -IPL_EXTERN(unload)(void) +iplunload(void) { int error = 0; - error = ipldetach(); + if (ipf_refcnt) + return EBUSY; + WRITE_ENTER(&ipf_global); + error = ipl_detach(); + if (error != 0) { + RWLOCK_EXIT(&ipf_global); + return error; + } + ipf_running = -2; + +#if (IRIX < 60500) LOCK_DEALLOC(ipl_mutex.l); LOCK_DEALLOC(ipf_rw.l); LOCK_DEALLOC(ipf_auth.l); LOCK_DEALLOC(ipf_natfrag.l); + LOCK_DEALLOC(ipf_ipidfrag.l); + LOCK_DEALLOC(ipf_tokens.l); + LOCK_DEALLOC(ipf_stinsert.l); + LOCK_DEALLOC(ipf_nat_new.l); + LOCK_DEALLOC(ipf_natio.l); LOCK_DEALLOC(ipf_nat.l); LOCK_DEALLOC(ipf_state.l); LOCK_DEALLOC(ipf_frag.l); + LOCK_DEALLOC(ipf_auth_mx.l); LOCK_DEALLOC(ipf_mutex.l); + LOCK_DEALLOC(ipf_frcache.l); LOCK_DEALLOC(ipfi_mutex.l); + RWLOCK_EXIT(&ipf_global); + LOCK_DEALLOC(ipf_global.l); +#else + MUTEX_DESTROY(&ipf_rw); + MUTEX_DESTROY(&ipfi_mutex); + MUTEX_DESTROY(&ipf_timeoutlock); + RW_DESTROY(&ipf_mutex); + RW_DESTROY(&ipf_frcache); + RW_DESTROY(&ipf_tokens); + RWLOCK_EXIT(&ipf_global); + delay(hz); + RW_DESTROY(&ipf_global); +#endif + + printf("%s unloaded\n", ipfilter_version); - return error; + delay(hz); + + return 0; } #endif void -IPL_EXTERN(init)(void) +ipfilterinit(void) { #ifdef IPFILTER_LKM int error; #endif +#if (IRIX < 60500) ipfi_mutex.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); - ipf_mutex.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); +ipf_mutex.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); +ipf_frcache.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); +ipf_timeoutlock.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); + ipf_global.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); ipf_frag.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); ipf_state.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); ipf_nat.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); + ipf_stinsert.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); ipf_natfrag.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); + ipf_ipidfrag.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); + ipf_tokens.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); ipf_auth.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); ipf_rw.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); ipl_mutex.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); - if (!ipfi_mutex.l || !ipf_mutex.l || !ipf_frag.l || !ipf_state.l || - !ipf_nat.l || !ipf_natfrag.l || !ipf_auth.l || !ipf_rw.l || - !ipl_mutex.l) + if (!ipfi_mutex.l || !ipf_mutex.l || !ipf_timeoutlock.l || + !ipf_frag.l || !ipf_state.l || !ipf_nat.l || !ipf_natfrag.l || + !ipf_auth.l || !ipf_rw.l || !ipf_ipidfrag.l || !ipl_mutex.l || + !ipf_stinsert.l || !ipf_auth_mx.l || !ipf_frcache.l || + !ipf_tokens.l) panic("IP Filter: LOCK_ALLOC failed"); +#else + MUTEX_INIT(&ipf_rw, "ipf rw mutex"); + MUTEX_INIT(&ipf_timeoutlock, "ipf timeout mutex"); + RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex"); + RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock"); + RWLOCK_INIT(&ipf_frcache, "ipf cache rwlock"); +#endif #ifdef IPFILTER_LKM - error = iplattach(); + error = ipl_attach(); if (error) { - IPL_EXTERN(unload)(); + iplunload(); + } else { + char *defpass; + + if (FR_ISPASS(ipf_pass)) + defpass = "pass"; + else if (FR_ISBLOCK(ipf_pass)) + defpass = "block"; + else + defpass = "no-match -> block"; + + printf("%s initialized. Default = %s all, Logging = %s%s\n", + ipfilter_version, defpass, +# ifdef IPFILTER_LOG + "enabled", +# else + "disabled", +# endif +# ifdef IPFILTER_COMPILED + " (COMPILED)" +# else + "" +# endif + ); } #endif return; } - diff --git a/mln_ipl.c b/mln_ipl.c index b170940e8921a..fa1d422b6a870 100644 --- a/mln_ipl.c +++ b/mln_ipl.c @@ -1,7 +1,8 @@ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. + * */ /* * 29/12/94 Added code from Marc Huber <huber@fzi.de> to allow it to allocate @@ -42,9 +43,15 @@ #include <netinet/tcp.h> #include <netinet/tcpip.h> #include <sys/lkm.h> +#include <sys/poll.h> +#include <sys/select.h> #include "ipl.h" #include "ip_compat.h" #include "ip_fil.h" +#include "ip_auth.h" +#include "ip_state.h" +#include "ip_nat.h" +#include "ip_sync.h" #if !defined(__NetBSD_Version__) || __NetBSD_Version__ < 103050000 #define vn_lock(v,f) VOP_LOCK(v) @@ -54,71 +61,28 @@ #define VOP_LEASE LEASE_CHECK #endif -#ifndef MIN -#define MIN(a,b) (((a)<(b))?(a):(b)) -#endif - extern int lkmenodev __P((void)); -#if (NetBSD >= 199706) || (defined(OpenBSD) && (OpenBSD >= 200211)) -int if_ipl_lkmentry __P((struct lkm_table *, int, int)); -#else -#if defined(OpenBSD) -int if_ipl __P((struct lkm_table *, int, int)); +#if NetBSD >= 199706 +int ipflkm_lkmentry __P((struct lkm_table *, int, int)); #else int xxxinit __P((struct lkm_table *, int, int)); #endif -#endif -static int ipl_unload __P((void)); -static int ipl_load __P((void)); -static int ipl_remove __P((void)); -static int iplaction __P((struct lkm_table *, int)); -static char *ipf_devfiles[] = { IPL_NAME, IPL_NAT, IPL_STATE, IPL_AUTH, - NULL }; - - -#if (defined(NetBSD1_0) && (NetBSD1_0 > 1)) || \ - (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199511)) -# if defined(__NetBSD__) && (__NetBSD_Version__ >= 106080000) -extern const struct cdevsw ipl_cdevsw; -# else -struct cdevsw ipldevsw = -{ - iplopen, /* open */ - iplclose, /* close */ - iplread, /* read */ - 0, /* write */ - iplioctl, /* ioctl */ - 0, /* stop */ - 0, /* tty */ - 0, /* select */ - 0, /* mmap */ - NULL /* strategy */ -}; -# endif -#else -struct cdevsw ipldevsw = -{ - iplopen, /* open */ - iplclose, /* close */ - iplread, /* read */ - (void *)nullop, /* write */ - iplioctl, /* ioctl */ - (void *)nullop, /* stop */ -#ifndef OpenBSD - (void *)nullop, /* reset */ -#endif - (void *)NULL, /* tty */ - (void *)nullop, /* select */ - (void *)nullop, /* mmap */ - NULL /* strategy */ -}; -#endif -int ipl_major = 0; +static int ipf_unload __P((void)); +static int ipf_load __P((void)); +static int ipf_remove __P((void)); +static int ipfaction __P((struct lkm_table *, int)); +static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, + IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME, + IPLOOKUP_NAME, NULL }; + +int ipf_major = 0; +extern ipf_main_softc_t ipfmain; +extern const struct cdevsw ipl_cdevsw; #if defined(__NetBSD__) && (__NetBSD_Version__ >= 106080000) -MOD_DEV(IPL_VERSION, "ipl", NULL, -1, &ipl_cdevsw, -1); +MOD_DEV(IPL_VERSION, "ipf", NULL, -1, &ipl_cdevsw, -1); #else MOD_DEV(IPL_VERSION, LM_DT_CHAR, -1, &ipldevsw); #endif @@ -128,34 +92,29 @@ extern struct cdevsw cdevsw[]; extern int nchrdev; -#if (NetBSD >= 199706) || (defined(OpenBSD) && (OpenBSD >= 200211)) -int if_ipl_lkmentry(lkmtp, cmd, ver) -#else -#if defined(OpenBSD) -int if_ipl(lkmtp, cmd, ver) +int +#if NetBSD >= 199706 +ipflkm_lkmentry(lkmtp, cmd, ver) #else -int xxxinit(lkmtp, cmd, ver) +xxxinit(lkmtp, cmd, ver) #endif -#endif -struct lkm_table *lkmtp; -int cmd, ver; + struct lkm_table *lkmtp; + int cmd, ver; { - DISPATCH(lkmtp, cmd, ver, iplaction, iplaction, iplaction); + DISPATCH(lkmtp, cmd, ver, ipfaction, ipfaction, ipfaction); } -#ifdef OpenBSD -int lkmexists __P((struct lkm_table *)); /* defined in /sys/kern/kern_lkm.c */ -#endif -static int iplaction(lkmtp, cmd) -struct lkm_table *lkmtp; -int cmd; +static int +ipfaction(lkmtp, cmd) + struct lkm_table *lkmtp; + int cmd; { - struct lkm_dev *args = lkmtp->private.lkm_dev; - int err = 0; #if !defined(__NetBSD__) || (__NetBSD_Version__ < 106080000) int i; #endif + struct lkm_dev *args = lkmtp->private.lkm_dev; + int err = 0; switch (cmd) { @@ -163,38 +122,40 @@ int cmd; if (lkmexists(lkmtp)) return EEXIST; -#if !defined(__NetBSD__) || (__NetBSD_Version__ < 106080000) +#if defined(__NetBSD__) && (__NetBSD_Version__ >= 106080000) +# if (__NetBSD_Version__ < 200000000) + err = devsw_attach(args->lkm_devname, + args->lkm_bdev, &args->lkm_bdevmaj, + args->lkm_cdev, &args->lkm_cdevmaj); + if (err != 0) + return (err); +# endif + ipf_major = args->lkm_cdevmaj; +#else for (i = 0; i < nchrdev; i++) if (cdevsw[i].d_open == (dev_type_open((*)))lkmenodev || - cdevsw[i].d_open == iplopen) + cdevsw[i].d_open == ipfopen) break; if (i == nchrdev) { printf("IP Filter: No free cdevsw slots\n"); return ENODEV; } - ipl_major = i; + ipf_major = i; args->lkm_offset = i; /* slot in cdevsw[] */ -#else - err = devsw_attach(args->lkm_devname, - args->lkm_bdev, &args->lkm_bdevmaj, - args->lkm_cdev, &args->lkm_cdevmaj); - if (err != 0) - return (err); - ipl_major = args->lkm_cdevmaj; #endif - printf("IP Filter: loaded into slot %d\n", ipl_major); - return ipl_load(); + printf("IP Filter: loaded into slot %d\n", ipf_major); + return ipf_load(); case LKM_E_UNLOAD : #if defined(__NetBSD__) && (__NetBSD_Version__ >= 106080000) devsw_detach(args->lkm_bdev, args->lkm_cdev); args->lkm_bdevmaj = -1; args->lkm_cdevmaj = -1; #endif - err = ipl_unload(); + err = ipf_unload(); if (!err) printf("IP Filter: unloaded from slot %d\n", - ipl_major); + ipf_major); break; case LKM_E_STAT : break; @@ -206,32 +167,65 @@ int cmd; } -static int ipl_remove() +static int +ipf_remove() { char *name; struct nameidata nd; int error, i; for (i = 0; (name = ipf_devfiles[i]); i++) { +#if (__NetBSD_Version__ > 106009999) +# if (__NetBSD_Version__ > 399001400) +# if (__NetBSD_Version__ > 499001400) + NDINIT(&nd, DELETE, LOCKPARENT|LOCKLEAF, UIO_SYSSPACE, + name); +# else + NDINIT(&nd, DELETE, LOCKPARENT|LOCKLEAF, UIO_SYSSPACE, + name, curlwp); +# endif +# else + NDINIT(&nd, DELETE, LOCKPARENT|LOCKLEAF, UIO_SYSSPACE, + name, curproc); +# endif +#else NDINIT(&nd, DELETE, LOCKPARENT, UIO_SYSSPACE, name, curproc); +#endif if ((error = namei(&nd))) return (error); - VOP_LEASE(nd.ni_vp, curproc, curproc->p_ucred, LEASE_WRITE); -#ifdef OpenBSD - VOP_LOCK(nd.ni_vp, LK_EXCLUSIVE | LK_RETRY, curproc); +#if (__NetBSD_Version__ > 399001400) +# if (__NetBSD_Version__ > 399002000) +# if (__NetBSD_Version__ < 499001400) + VOP_LEASE(nd.ni_dvp, curlwp, curlwp->l_cred, LEASE_WRITE); +# endif +# else + VOP_LEASE(nd.ni_dvp, curlwp, curlwp->l_proc->p_ucred, LEASE_WRITE); +# endif #else -# if !defined(__NetBSD_Version__) || (__NetBSD_Version__ < 106000000) + VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE); +#endif +#if !defined(__NetBSD_Version__) || (__NetBSD_Version__ < 106000000) vn_lock(nd.ni_vp, LK_EXCLUSIVE | LK_RETRY); +#endif +#if (__NetBSD_Version__ >= 399002000) +# if (__NetBSD_Version__ < 499001400) + VOP_LEASE(nd.ni_vp, curlwp, curlwp->l_cred, LEASE_WRITE); +# endif +#else +# if (__NetBSD_Version__ > 399001400) + VOP_LEASE(nd.ni_vp, curlwp, curlwp->l_proc->p_ucred, LEASE_WRITE); +# else + VOP_LEASE(nd.ni_vp, curproc, curproc->p_ucred, LEASE_WRITE); # endif #endif - VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE); (void) VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); } return 0; } -static int ipl_unload() +static int +ipf_unload() { int error = 0; @@ -239,19 +233,27 @@ static int ipl_unload() * Unloading - remove the filter rule check from the IP * input/output stream. */ -#if defined(__NetBSD__) - error = ipl_disable(); -#else - error = ipldetach(); -#endif + if (ipfmain.ipf_refcnt) + error = EBUSY; + else if (ipfmain.ipf_running >= 0) { + error = ipfdetach(&ipfmain); + if (error == 0) { + ipf_destroy_all(&ipfmain); + ipf_unload_all(); + } + } - if (!error) - error = ipl_remove(); + if (error == 0) { + ipfmain.ipf_running = -2; + error = ipf_remove(); + printf("%s unloaded\n", ipfilter_version); + } return error; } -static int ipl_load() +static int +ipf_load() { struct nameidata nd; struct vattr vattr; @@ -263,16 +265,35 @@ static int ipl_load() * XXX using the assigned LKM device slot's major number. In a * XXX perfect world we could use the ones specified by cdevsw[]. */ - (void)ipl_remove(); + (void)ipf_remove(); - error = ipl_enable(); - if (error) + bzero((char *)&ipfmain, sizeof(ipfmain)); + error = ipf_load_all(); + if (error != 0) return error; + if (ipf_create_all(&ipfmain) == NULL) { + ipf_unload_all(); + return EIO; + } - for (i = 0; (name = ipf_devfiles[i]); i++) { + error = ipfattach(&ipfmain); + if (error != 0) { + (void) ipf_unload(); + return error; + } + + for (i = 0; (error == 0) && (name = ipf_devfiles[i]); i++) { +#if (__NetBSD_Version__ > 399001400) +# if (__NetBSD_Version__ > 499001400) + NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, name); +# else + NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, name, curlwp); +# endif +#else NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, name, curproc); +#endif if ((error = namei(&nd))) - return error; + break; if (nd.ni_vp != NULL) { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); if (nd.ni_dvp == nd.ni_vp) @@ -280,16 +301,53 @@ static int ipl_load() else vput(nd.ni_dvp); vrele(nd.ni_vp); - return (EEXIST); + error = EEXIST; + break; } VATTR_NULL(&vattr); vattr.va_type = VCHR; vattr.va_mode = (fmode & 07777); - vattr.va_rdev = (ipl_major << 8) | i; + vattr.va_rdev = (ipf_major << 8) | i; +#if (__NetBSD_Version__ > 399001400) +# if (__NetBSD_Version__ >= 399002000) +# if (__NetBSD_Version__ < 499001400) + VOP_LEASE(nd.ni_dvp, curlwp, curlwp->l_cred, LEASE_WRITE); +# endif +# else + VOP_LEASE(nd.ni_dvp, curlwp, curlwp->l_proc->p_ucred, LEASE_WRITE); +# endif +#else VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE); +#endif error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); - if (error) - return error; + if (error == 0) + vput(nd.ni_vp); + } + + if (error == 0) { + char *defpass; + + if (FR_ISPASS(ipfmain.ipf_pass)) + defpass = "pass"; + else if (FR_ISBLOCK(ipfmain.ipf_pass)) + defpass = "block"; + else + defpass = "no-match -> block"; + + printf("%s initialized. Default = %s all, Logging = %s%s\n", + ipfilter_version, defpass, +#ifdef IPFILTER_LOG + "enabled", +#else + "disabled", +#endif +#ifdef IPFILTER_COMPILED + " (COMPILED)" +#else + "" +#endif + ); + ipfmain.ipf_running = 1; } return error; } diff --git a/mln_rule.c b/mln_rule.c new file mode 100644 index 0000000000000..2df3376816b40 --- /dev/null +++ b/mln_rule.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/proc.h> +#include <sys/ioctl.h> +#include <sys/kernel.h> +#include <sys/mbuf.h> +#include <sys/exec.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/in_systm.h> +#include <netinet/in.h> +#include <netinet/ip.h> +#include <net/route.h> +#include <netinet/ip_var.h> +#include <netinet/tcp.h> +#include <netinet/tcpip.h> +#include <sys/lkm.h> +#include "ip_compat.h" +#include "ip_fil.h" +#include "ip_rules.h" + + +static int ipfruleaction __P((struct lkm_table *, int)); + +#ifdef IPFILTER_LKM +# if NetBSD >= 199706 +int ipfrule_lkmentry __P((struct lkm_table *, int, int)); +# else +int xxxinit __P((struct lkm_table *, int, int)); +# endif + + +MOD_MISC("IPFilter Rules"); + +# if NetBSD >= 199706 +int ipfrule_lkmentry(lkmtp, cmd, ver) +# else +int xxxinit(lkmtp, cmd, ver) +# endif + struct lkm_table *lkmtp; + int cmd, ver; +{ + DISPATCH(lkmtp, cmd, ver, ipfruleaction, ipfruleaction, ipfruleaction); +} + +static int ipfruleaction(lkmtp, cmd) + struct lkm_table *lkmtp; + int cmd; +{ + int err = 0; + + switch (cmd) + { + case LKM_E_LOAD : + if (lkmexists(lkmtp)) + return EEXIST; + + err = ipfrule_add(); + if (!err) + ipf_refcnt++; + break; + case LKM_E_UNLOAD : + err = ipfrule_remove(); + if (!err) + ipf_refcnt--; + break; + case LKM_E_STAT : + break; + default: + err = EIO; + break; + } + return err; +} +#endif /* IPFILTER_LKM */ diff --git a/mlo_ipl.c b/mlo_ipl.c new file mode 100644 index 0000000000000..4cd6c43fc5f6c --- /dev/null +++ b/mlo_ipl.c @@ -0,0 +1,362 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <sys/proc.h> +#include <sys/uio.h> +#include <sys/kernel.h> +#include <sys/vnode.h> +#include <sys/namei.h> +#include <sys/malloc.h> +#include <sys/mount.h> +#include <sys/exec.h> +#include <sys/mbuf.h> +#include <net/if.h> +#include <netinet/in_systm.h> +#include <netinet/in.h> +#include <netinet/ip.h> +#include <net/route.h> +#include <netinet/ip_var.h> +#include <netinet/tcp.h> +#include <netinet/tcpip.h> +#include <sys/lkm.h> +#include "ipl.h" +#include "ip_compat.h" +#include "ip_fil.h" + +#define vn_lock(v,f) VOP_LOCK(v) + +#if !defined(VOP_LEASE) && defined(LEASE_CHECK) +#define VOP_LEASE LEASE_CHECK +#endif + + +extern int lkmenodev __P((void)); + +#if OpenBSD >= 200311 +int if_ipf_lkmentry __P((struct lkm_table *, int, int)); +#else +int if_ipf __P((struct lkm_table *, int, int)); +#endif +static int ipf_unload __P((void)); +static int ipf_load __P((void)); +static int ipf_remove __P((void)); +static int ipfaction __P((struct lkm_table *, int)); +static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, + IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME, + IPLOOKUP_NAME, NULL }; + + +struct cdevsw ipfdevsw = +{ + ipfopen, /* open */ + ipfclose, /* close */ + ipfread, /* read */ + (void *)nullop, /* write */ + ipfioctl, /* ioctl */ + (void *)nullop, /* stop */ + (void *)NULL, /* tty */ + (void *)nullop, /* select */ + (void *)nullop, /* mmap */ + NULL /* strategy */ +}; + +int ipf_major = 0; + +MOD_DEV(IPL_VERSION, LM_DT_CHAR, -1, &ipfdevsw); + +extern int vd_unuseddev __P((void)); +extern struct cdevsw cdevsw[]; +extern int nchrdev; + + +#if OpenBSD >= 200311 +int if_ipf_lkmentry (lkmtp, cmd, ver) +#else +int if_ipf(lkmtp, cmd, ver) +#endif + struct lkm_table *lkmtp; + int cmd, ver; +{ + DISPATCH(lkmtp, cmd, ver, ipfaction, ipfaction, ipfaction); +} + +int lkmexists __P((struct lkm_table *)); /* defined in /sys/kern/kern_lkm.c */ + +static int ipfaction(lkmtp, cmd) + struct lkm_table *lkmtp; + int cmd; +{ + int i; + struct lkm_dev *args = lkmtp->private.lkm_dev; + int err = 0; + + switch (cmd) + { + case LKM_E_LOAD : + if (lkmexists(lkmtp)) + return EEXIST; + + for (i = 0; i < nchrdev; i++) + if (cdevsw[i].d_open == (dev_type_open((*)))lkmenodev || + cdevsw[i].d_open == ipfopen) + break; + if (i == nchrdev) { + printf("IP Filter: No free cdevsw slots\n"); + return ENODEV; + } + + ipf_major = i; + args->lkm_offset = i; /* slot in cdevsw[] */ + printf("IP Filter: loaded into slot %d\n", ipf_major); + return ipf_load(); + case LKM_E_UNLOAD : + err = ipf_unload(); + if (!err) + printf("IP Filter: unloaded from slot %d\n", + ipf_major); + break; + case LKM_E_STAT : + break; + default: + err = EIO; + break; + } + return err; +} + + +static int ipf_remove() +{ + struct nameidata nd; + int error, i; + char *name; + + for (i = 0; (name = ipf_devfiles[i]); i++) { +#if OpenBSD >= 200311 + NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_SYSSPACE, + name, curproc); +#else + NDINIT(&nd, DELETE, LOCKPARENT, UIO_SYSSPACE, name, curproc); +#endif + if ((error = namei(&nd))) + return (error); + VOP_LEASE(nd.ni_vp, curproc, curproc->p_ucred, LEASE_WRITE); +#if OpenBSD < 200311 + VOP_LOCK(nd.ni_vp, LK_EXCLUSIVE | LK_RETRY, curproc); + VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE); +#else + (void)uvm_vnp_uncache(nd.ni_vp); + + VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE); + VOP_LEASE(nd.ni_vp, curproc, curproc->p_ucred, LEASE_WRITE); +#endif + (void) VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); + } + return 0; +} + + +static int ipf_unload() +{ + int error = 0; + + /* + * Unloading - remove the filter rule check from the IP + * input/output stream. + */ + if (ipf_refcnt) + error = EBUSY; + else if (ipf_running >= 0) + error = ipfdetach(); + + if (error == 0) { + ipf_running = -2; + error = ipf_remove(); + printf("%s unloaded\n", ipfilter_version); + } + return error; +} + + +static int ipf_load() +{ + struct nameidata nd; + struct vattr vattr; + int error = 0, fmode = S_IFCHR|0600, i; + char *name; + + /* + * XXX Remove existing device nodes prior to creating new ones + * XXX using the assigned LKM device slot's major number. In a + * XXX perfect world we could use the ones specified by cdevsw[]. + */ + (void)ipf_remove(); + + error = ipfattach(); + + for (i = 0; (error == 0) && (name = ipf_devfiles[i]); i++) { + NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, name, curproc); + if ((error = namei(&nd))) + break; + if (nd.ni_vp != NULL) { + VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); + if (nd.ni_dvp == nd.ni_vp) + vrele(nd.ni_dvp); + else + vput(nd.ni_dvp); + vrele(nd.ni_vp); + error = EEXIST; + break; + } + VATTR_NULL(&vattr); + vattr.va_type = VCHR; + vattr.va_mode = (fmode & 07777); + vattr.va_rdev = (ipf_major << 8) | i; + VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE); + error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); + } + + if (error == 0) { + char *defpass; + + if (FR_ISPASS(ipf_pass)) + defpass = "pass"; + else if (FR_ISBLOCK(ipf_pass)) + defpass = "block"; + else + defpass = "no-match -> block"; + + printf("%s initialized. Default = %s all, Logging = %s%s\n", + ipfilter_version, defpass, +#ifdef IPFILTER_LOG + "enabled", +#else + "disabled", +#endif +#ifdef IPFILTER_COMPILED + " (COMPILED)" +#else + "" +#endif + ); + ipf_running = 1; + } + return error; +} + + +/* + * routines below for saving IP headers to buffer + */ +int +ipfopen(dev, flags, devtype, p) + dev_t dev; + int flags; + int devtype; + struct proc *p; +{ + u_int min = GET_MINOR(dev); + int error; + + if (IPL_LOGMAX < min) { + error = ENXIO; + } else { + switch (unit) + { + case IPL_LOGIPF : + case IPL_LOGNAT : + case IPL_LOGSTATE : + case IPL_LOGAUTH : + case IPL_LOGLOOKUP : + case IPL_LOGSYNC : +#ifdef IPFILTER_SCAN + case IPL_LOGSCAN : +#endif + error = 0; + break; + default : + error = ENXIO; + break; + } + } + return error; +} + + +int +ipfclose(dev, flags, devtype, p) + dev_t dev; + int flags; + int devtype; + struct proc *p; +{ + u_int min = GET_MINOR(dev); + + if (IPL_LOGMAX < min) + min = ENXIO; + else + min = 0; + return min; +} + + +/* + * ipfread/ipflog + * both of these must operate with at least splnet() lest they be + * called during packet processing and cause an inconsistancy to appear in + * the filter lists. + */ +int +ipfread(dev, uio, ioflag) + dev_t dev; + register struct uio *uio; + int ioflag; +{ + + if (ipf_running < 1) + return EIO; + + if (GET_MINOR(dev) == IPL_LOGSYNC) + return ipfsync_read(uio); + +#ifdef IPFILTER_LOG + return ipflog_read(GET_MINOR(dev), uio); +#else + return ENXIO; +#endif +} + + +/* + * ipfwrite + * both of these must operate with at least splnet() lest they be + * called during packet processing and cause an inconsistancy to appear in + * the filter lists. + */ +int +#if (BSD >= 199306) +ipfwrite(dev, uio, ioflag) + int ioflag; +#else +ipfwrite(dev, uio) +#endif + dev_t dev; + register struct uio *uio; +{ + + if (ipf_running < 1) + return EIO; + + if (GET_MINOR(dev) == IPL_LOGSYNC) + return ipfsync_write(uio); + return ENXIO; +} diff --git a/mlo_rule.c b/mlo_rule.c new file mode 100644 index 0000000000000..dba201e0844c2 --- /dev/null +++ b/mlo_rule.c @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/proc.h> +#include <sys/ioctl.h> +#include <sys/kernel.h> +#include <sys/mbuf.h> +#include <sys/exec.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/in_systm.h> +#include <netinet/in.h> +#include <netinet/ip.h> +#include <net/route.h> +#include <netinet/ip_var.h> +#include <netinet/tcp.h> +#include <netinet/tcpip.h> +#include <sys/lkm.h> +#include "ip_compat.h" +#include "ip_fil.h" +#include "ip_rules.h" + + +#ifdef IPFILTER_LKM + +static int ipfruleaction __P((struct lkm_table *, int)); + +int ipfrule __P((struct lkm_table *, int, int)); + + +MOD_MISC("IPFilter Rules"); + +int ipfrule(lkmtp, cmd, ver) + struct lkm_table *lkmtp; + int cmd, ver; +{ + DISPATCH(lkmtp, cmd, ver, ipfruleaction, ipfruleaction, ipfruleaction); +} + +int lkmexists __P((struct lkm_table *)); /* defined in /sys/kern/kern_lkm.c */ + +static int ipfruleaction(lkmtp, cmd) + struct lkm_table *lkmtp; + int cmd; +{ + int err = 0; + + switch (cmd) + { + case LKM_E_LOAD : + if (lkmexists(lkmtp)) + return EEXIST; + + err = ipfrule_add(); + if (!err) + ipf_refcnt++; + break; + case LKM_E_UNLOAD : + err = ipfrule_remove(); + if (!err) + ipf_refcnt--; + break; + case LKM_E_STAT : + break; + default: + err = EIO; + break; + } + return err; +} +#endif /* IPFILTER_LKM */ diff --git a/mls_ipl.c b/mls_ipl.c index 5a70ab9d35a17..d6f54307fb693 100644 --- a/mls_ipl.c +++ b/mls_ipl.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -40,61 +40,65 @@ #if !defined(lint) static const char sccsid[] = "@(#)mls_ipl.c 2.6 10/15/95 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: mls_ipl.c,v 2.2.2.2 2002/04/10 05:05:54 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif -extern int ipldetach __P((void)); +extern int ipfdetach __P((void)); #ifndef IPFILTER_LOG -#define iplread nulldev +#define ipfread nulldev #endif extern int nulldev __P((void)); extern int errno; -extern int iplidentify __P((char *)); extern int nodev __P((void)); static int unload __P((void)); -static int ipl_attach __P((void)); +static int ipf_attach __P((void)); int xxxinit __P((u_int, struct vddrv *, caddr_t, struct vdstat *)); -static char *ipf_devfiles[] = { IPL_NAME, IPL_NAT, IPL_STATE, IPL_AUTH, - NULL }; +static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, + IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME, + IPLOOKUP_NAME, NULL }; +static int ipfopen __P((dev_t, int)); +static int ipfclose __P((dev_t, int)); +static int ipfread __P((dev_t, struct uio *)); +static int ipfwrite __P((dev_t, struct uio *)); -struct cdevsw ipldevsw = +struct cdevsw ipfdevsw = { - iplopen, iplclose, iplread, nulldev, - iplioctl, nulldev, nulldev, nulldev, + ipfopen, ipfclose, ipfread, nulldev, + ipfioctl, nulldev, nulldev, nulldev, 0, nulldev, }; -struct dev_ops ipl_ops = +struct dev_ops ipf_ops = { 1, - iplidentify, - iplattach, - iplopen, - iplclose, - iplread, - NULL, /* write */ + ipfidentify, + ipfattach, + ipfopen, + ipfclose, + ipfread, + ipfwrite, NULL, /* strategy */ NULL, /* dump */ 0, /* psize */ - iplioctl, + ipfioctl, NULL, /* reset */ NULL /* mmap */ }; -int ipl_major = 0; +int ipf_major = 0; #ifdef sun4m -struct vdldrv vd = +struct vdldrv vd = { VDMAGIC_PSEUDO, IPL_VERSION, - &ipl_ops, + &ipf_ops, NULL, - &ipldevsw, + &ipfdevsw, 0, 0, NULL, @@ -109,7 +113,7 @@ struct vdldrv vd = VDMAGIC_PSEUDO, /* magic */ IPL_VERSION, #ifdef sun4c - &ipl_ops, /* dev_ops */ + &ipf_ops, /* dev_ops */ #else NULL, /* struct mb_ctlr *mb_ctlr */ NULL, /* struct mb_driver *mb_driver */ @@ -118,7 +122,7 @@ struct vdldrv vd = 1, /* numdevs */ #endif /* sun4c */ NULL, /* bdevsw */ - &ipldevsw, /* cdevsw */ + &ipfdevsw, /* cdevsw */ 0, /* block major */ 0, /* char major */ }; @@ -129,10 +133,10 @@ extern struct cdevsw cdevsw[]; extern int nchrdev; xxxinit(fc, vdp, data, vds) -u_int fc; -struct vddrv *vdp; -caddr_t data; -struct vdstat *vds; + u_int fc; + struct vddrv *vdp; + caddr_t data; + struct vdstat *vds; { struct vdioctl_load *vdi = (struct vdioctl_load *)data; @@ -144,20 +148,20 @@ struct vdstat *vds; if (vdi && vdi->vdi_userconf) for (vdc = vdi->vdi_userconf; vdc->vdc_type; vdc++) if (vdc->vdc_type == VDCCHARMAJOR) { - ipl_major = vdc->vdc_data; + ipf_major = vdc->vdc_data; break; } - if (!ipl_major) { - while (ipl_major < nchrdev && - cdevsw[ipl_major].d_open != vd_unuseddev) - ipl_major++; - if (ipl_major == nchrdev) + if (!ipf_major) { + while (ipf_major < nchrdev && + cdevsw[ipf_major].d_open != vd_unuseddev) + ipf_major++; + if (ipf_major == nchrdev) return ENODEV; } vdp->vdd_vdtab = (struct vdlinkage *)&vd; - vd.Drv_charmajor = ipl_major; - return ipl_attach(); + vd.Drv_charmajor = ipf_major; + return ipf_attach(); } case VDUNLOAD: return unload(); @@ -169,28 +173,36 @@ struct vdstat *vds; } -static int unload() +static int +unload() { + int err = 0, i; char *name; - int err, i; - err = ipldetach(); + if (ipf_refcnt != 0) + err = EBUSY; + else if (ipf_running >= 0) + err = ipfdetach(); if (err) return err; + + ipf_running = -2; for (i = 0; (name = ipf_devfiles[i]); i++) (void) vn_remove(name, UIO_SYSSPACE, FILE); + printf("%s unloaded\n", ipfilter_version); return 0; } -static int ipl_attach() +static int +ipf_attach() { struct vnode *vp; struct vattr vattr; int error = 0, fmode = S_IFCHR|0600, i; char *name; - error = iplattach(); + error = ipfattach(); if (error) return error; @@ -199,7 +211,7 @@ static int ipl_attach() vattr_null(&vattr); vattr.va_type = MFTOVT(fmode); vattr.va_mode = (fmode & 07777); - vattr.va_rdev = (ipl_major << 8) | i; + vattr.va_rdev = (ipf_major << 8) | i; error = vn_create(name, UIO_SYSSPACE, &vattr, EXCL, 0, &vp); if (error) { @@ -209,5 +221,129 @@ static int ipl_attach() VN_RELE(vp); } } + + if (error == 0) { + char *defpass; + + if (FR_ISPASS(ipf_pass)) + defpass = "pass"; + else if (FR_ISBLOCK(ipf_pass)) + defpass = "block"; + else + defpass = "no-match -> block"; + + printf("%s initialized. Default = %s all, Logging = %s%s\n", + ipfilter_version, defpass, +#ifdef IPFILTER_LOG + "enabled", +#else + "disabled", +#endif +#ifdef IPFILTER_COMPILED + " (COMPILED)" +#else + "" +#endif + ); + ipf_running = 1; + } return error; } + + +/* + * routines below for saving IP headers to buffer + */ +static int +ipfopen(dev, flags) + dev_t dev; + int flags; +{ + u_int unit = GET_MINOR(dev); + int error; + + if (IPL_LOGMAX < unit) { + error = ENXIO; + } else { + switch (unit) + { + case IPL_LOGIPF : + case IPL_LOGNAT : + case IPL_LOGSTATE : + case IPL_LOGAUTH : + case IPL_LOGLOOKUP : + case IPL_LOGSYNC : +#ifdef IPFILTER_SCAN + case IPL_LOGSCAN : +#endif + error = 0; + break; + default : + error = ENXIO; + break; + } + } + return error; +} + + +static int +ipfclose(dev, flags) + dev_t dev; + int flags; +{ + u_int unit = GET_MINOR(dev); + + if (IPL_LOGMAX < unit) + unit = ENXIO; + else + unit = 0; + return unit; +} + + +/* + * ipfread/ipflog + * both of these must operate with at least splnet() lest they be + * called during packet processing and cause an inconsistancy to appear in + * the filter lists. + */ +static int +ipfread(dev, uio) + dev_t dev; + register struct uio *uio; +{ + + if (ipf_running < 1) { + ipfmain.ipf_interror = 130006; + return EIO; + } + +#ifdef IPFILTER_LOG + return ipflog_read(GET_MINOR(dev), uio); +#else + ipfmain.ipf_interror = 130007; + return ENXIO; +#endif +} + + +/* + * ipfwrite + */ +static int +ipfwrite(dev, uio) + dev_t dev; + register struct uio *uio; +{ + + if (ipf_running < 1) { + ipfmain.ipf_interror = 130008; + return EIO; + } + + if (getminor(dev) == IPL_LOGSYNC) + return ipfsync_write(uio); + ipfmain.ipf_interror = 130009; + return ENXIO; +} diff --git a/mls_rule.c b/mls_rule.c new file mode 100644 index 0000000000000..6adec2f0dc16a --- /dev/null +++ b/mls_rule.c @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ +/* + * 29/12/94 Added code from Marc Huber <huber@fzi.de> to allow it to allocate + * its own major char number! Way cool patch! + */ +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/file.h> +#include <sys/socket.h> +#include <sys/conf.h> +#include <sys/syslog.h> +#include <sys/buf.h> +#include <sys/mbuf.h> +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/uio.h> +#include <sys/vnode.h> +#include <sundev/mbvar.h> +#include <sun/autoconf.h> +#include <sun/vddrv.h> +#if defined(sun4c) || defined(sun4m) +# include <sun/openprom.h> +#endif +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/ip_var.h> +#include <netinet/tcp.h> +#include <netinet/tcpip.h> +#include <net/if.h> +#include "ip_compat.h" +#include "ip_fil.h" +#include "ip_rules.h" + + +extern int errno; + + +int xxxinit __P((u_int, struct vddrv *, caddr_t, struct vdstat *)); + +int ipl_major = 0; + +#ifdef sun4m +struct vdldrv vd = +{ + VDMAGIC_USER, + "IP Filter rules", + NULL, + NULL, + NULL, + 0, + 0, + NULL, + NULL, + NULL, + 0, + 1, +}; +#else /* sun4m */ +struct vdldrv vd = +{ + VDMAGIC_USER, /* magic */ + "IP Filter rules", +#ifdef sun4c + NULL, /* dev_ops */ +#else + NULL, /* struct mb_ctlr *mb_ctlr */ + NULL, /* struct mb_driver *mb_driver */ + NULL, /* struct mb_device *mb_device */ + 0, /* num ctlrs */ + 1, /* numdevs */ +#endif /* sun4c */ + NULL, /* bdevsw */ + NULL, /* cdevsw */ + 0, /* block major */ + 0, /* char major */ +}; +#endif /* sun4m */ + + +xxxinit(fc, vdp, data, vds) + u_int fc; + struct vddrv *vdp; + caddr_t data; + struct vdstat *vds; +{ + struct vdioctl_load *vdi = (struct vdioctl_load *)data; + int err; + + switch (fc) + { + case VDLOAD: + err = ipfrule_add(); + if (!err) + ipf_refcnt++; + break; + case VDUNLOAD: + err = ipfrule_remove(); + if (!err) + ipf_refcnt--; + break; + case VDSTAT: + err = 0; + break; + default: + err = EIO; + break; + } +} diff --git a/mlso_rule.c b/mlso_rule.c new file mode 100644 index 0000000000000..eab494b3915b0 --- /dev/null +++ b/mlso_rule.c @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ +#pragma ident "@(#)$Id$" + +#include <sys/systm.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/uio.h> +#include <sys/buf.h> +#include <sys/modctl.h> +#include <sys/open.h> +#include <sys/kmem.h> +#include <sys/conf.h> +#include <sys/cmn_err.h> +#include <sys/stat.h> +#include <sys/cred.h> +#include <sys/dditypes.h> +#include <sys/stream.h> +#include <sys/poll.h> +#include <sys/autoconf.h> +#include <sys/byteorder.h> +#include <sys/socket.h> +#include <sys/dlpi.h> +#include <sys/stropts.h> +#include <sys/sockio.h> +#include <net/if.h> +#if SOLARIS2 >= 6 +# include <net/if_types.h> +#endif +#include <net/af.h> +#include <net/route.h> +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/if_ether.h> +#include <netinet/ip.h> +#include <netinet/ip_var.h> +#include <netinet/tcp.h> +#include <netinet/udp.h> +#include <netinet/tcpip.h> +#include <netinet/ip_icmp.h> +#include <sys/ddi.h> +#include <sys/sunddi.h> +#include "ip_compat.h" +#include "ip_fil.h" +#include "ip_rules.h" + +char _depends_on[] = "drv/ipf"; + + +extern ipf_main_softc_t ipfmain; +extern struct mod_ops mod_miscops; +static struct modlmisc ipfrulemod = { + &mod_miscops, + "IP Filter rules" +}; + +static struct modlinkage modlink1 = { + MODREV_1, + &ipfrulemod, + NULL +}; + + +int _init() +{ + int ipfruleinst; + + ipfruleinst = mod_install(&modlink1); +#ifdef IPFRULEDEBUG + cmn_err(CE_NOTE, "IP Filter Rules: _init() = %d", ipfruleinst); +#endif + + if (ipfruleinst == 0) { + if (ipfmain.ipf_running >= 0) { + ipfruleinst = ipfrule_add(); + if (!ipfruleinst) + ipfmain.ipf_refcnt++; + else { + cmn_err(CE_NOTE, + "IP Filter Rules: ipfrule_add failed"); + ipfruleinst = -1; + } + } else + ipfruleinst = -1; + } + if (ipfruleinst == 0) + cmn_err(CE_CONT, "IP Filter Rules: loaded\n"); + return ipfruleinst; +} + + +int _fini(void) +{ + int ipfruleinst; + + ipfruleinst = mod_remove(&modlink1); +#ifdef IPFRULEDEBUG + cmn_err(CE_NOTE, "IP Filter Rules: _fini() = %d", ipfruleinst); +#endif + if (ipfruleinst == 0) { + ipfruleinst = ipfrule_remove(); + if (!ipfruleinst) + ipfmain.ipf_refcnt--; + else + ipfruleinst = -1; + } + if (ipfruleinst == 0) + cmn_err(CE_CONT, "IP Filter Rules: unloaded\n"); + return ipfruleinst; +} + + +int _info(modinfop) + struct modinfo *modinfop; +{ + int ipfruleinst; + + ipfruleinst = mod_info(&modlink1, modinfop); +#ifdef IPFRULEDEBUG + cmn_err(CE_NOTE, "IP Filter Rules: _info(%x) = %x", + modinfop, ipfruleinst); +#endif + return ipfruleinst; +} diff --git a/natparse.c b/natparse.c deleted file mode 100644 index 72462340b1a5e..0000000000000 --- a/natparse.c +++ /dev/null @@ -1,902 +0,0 @@ -/* - * Copyright (C) 1993-2002 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - */ -#if defined(__sgi) && (IRIX > 602) -# include <sys/ptimers.h> -#endif -#include <stdio.h> -#include <string.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/types.h> -#if !defined(__SVR4) && !defined(__svr4__) -# include <strings.h> -#else -# include <sys/byteorder.h> -#endif -#include <sys/time.h> -#include <sys/param.h> -#include <stdlib.h> -#include <unistd.h> -#include <stddef.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#if defined(sun) && (defined(__svr4__) || defined(__SVR4)) -# include <sys/ioccom.h> -# include <sys/sysmacros.h> -#endif -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/tcp.h> -#include <net/if.h> -#if __FreeBSD_version >= 300000 -# include <net/if_var.h> -#endif -#include <netdb.h> -#include <arpa/nameser.h> -#include <arpa/inet.h> -#include <resolv.h> -#include <ctype.h> -#include "netinet/ip_compat.h" -#include "netinet/ip_fil.h" -#include "netinet/ip_nat.h" -#include "netinet/ip_state.h" -#include "netinet/ip_proxy.h" -#include "ipf.h" - -#if defined(sun) && !SOLARIS2 -# define STRERROR(x) sys_errlist[x] -extern char *sys_errlist[]; -#else -# define STRERROR(x) strerror(x) -#endif - -#if !defined(lint) -static const char sccsid[] ="@(#)ipnat.c 1.9 6/5/96 (C) 1993 Darren Reed"; -static const char rcsid[] = "@(#)$Id: natparse.c,v 1.17.2.29 2003/05/15 17:45:34 darrenr Exp $"; -#endif - - -#if SOLARIS -#define bzero(a,b) memset(a,0,b) -#endif - -extern void printnat __P((ipnat_t *, int)); -extern int countbits __P((u_32_t)); -extern char *proto; - -ipnat_t *natparse __P((char *, int, int *)); -void natparsefile __P((int, char *, int)); -void nat_setgroupmap __P((struct ipnat *)); - - -void nat_setgroupmap(n) -ipnat_t *n; -{ - if (n->in_outmsk == n->in_inmsk) - n->in_ippip = 1; - else if (n->in_flags & IPN_AUTOPORTMAP) { - n->in_ippip = ~ntohl(n->in_inmsk); - if (n->in_outmsk != 0xffffffff) - n->in_ippip /= (~ntohl(n->in_outmsk) + 1); - n->in_ippip++; - if (n->in_ippip == 0) - n->in_ippip = 1; - n->in_ppip = USABLE_PORTS / n->in_ippip; - } else { - n->in_space = USABLE_PORTS * ~ntohl(n->in_outmsk); - n->in_nip = 0; - if (!(n->in_ppip = n->in_pmin)) - n->in_ppip = 1; - n->in_ippip = USABLE_PORTS / n->in_ppip; - } -} - - -/* - * Parse a line of input from the ipnat configuration file - * - * status: - * < 0 error - * = 0 OK - * > 0 programmer error - */ -ipnat_t *natparse(line, linenum, status) -char *line; -int linenum; -int *status; -{ - static ipnat_t ipn; - struct protoent *pr; - char *dnetm = NULL, *dport = NULL; - char *s, *t, *cps[31], **cpp; - int i, cnt; - char *port1a = NULL, *port1b = NULL, *port2a = NULL; - - *status = 100; /* default to error */ - proto = NULL; - - /* - * Search for end of line and comment marker, advance of leading spaces - */ - if ((s = strchr(line, '\n'))) - *s = '\0'; - if ((s = strchr(line, '#'))) - *s = '\0'; - while (*line && isspace(*line)) - line++; - if (!*line) { - *status = 0; - return NULL; - } - - bzero((char *)&ipn, sizeof(ipn)); - cnt = 0; - - /* - * split line upto into segments. - */ - for (i = 0, *cps = strtok(line, " \b\t\r\n"); cps[i] && i < 30; cnt++) - cps[++i] = strtok(NULL, " \b\t\r\n"); - - cps[i] = NULL; - - if (cnt < 3) { - fprintf(stderr, "%d: not enough segments in line\n", linenum); - *status = -1; - return NULL; - } - - cpp = cps; - - /* - * Check first word is a recognised keyword and then is the interface - */ - if (!strcasecmp(*cpp, "map")) - ipn.in_redir = NAT_MAP; - else if (!strcasecmp(*cpp, "map-block")) - ipn.in_redir = NAT_MAPBLK; - else if (!strcasecmp(*cpp, "rdr")) - ipn.in_redir = NAT_REDIRECT; - else if (!strcasecmp(*cpp, "bimap")) - ipn.in_redir = NAT_BIMAP; - else { - fprintf(stderr, "%d: unknown mapping: \"%s\"\n", - linenum, *cpp); - *status = -1; - return NULL; - } - - cpp++; - - strncpy(ipn.in_ifname, *cpp, sizeof(ipn.in_ifname) - 1); - ipn.in_ifname[sizeof(ipn.in_ifname) - 1] = '\0'; - cpp++; - - /* - * If the first word after the interface is "from" or is a ! then - * the expanded syntax is being used so parse it differently. - */ - if (!strcasecmp(*cpp, "from") || (**cpp == '!')) { - if (!strcmp(*cpp, "!")) { - cpp++; - if (strcasecmp(*cpp, "from")) { - fprintf(stderr, "Missing from after !\n"); - *status = -1; - return NULL; - } - ipn.in_flags |= IPN_NOTSRC; - } else if (**cpp == '!') { - if (strcasecmp(*cpp + 1, "from")) { - fprintf(stderr, "Missing from after !\n"); - *status = -1; - return NULL; - } - ipn.in_flags |= IPN_NOTSRC; - } - if ((ipn.in_flags & IPN_NOTSRC) && - (ipn.in_redir & (NAT_MAP|NAT_MAPBLK))) { - fprintf(stderr, "Cannot use '! from' with map\n"); - *status = -1; - return NULL; - } - - ipn.in_flags |= IPN_FILTER; - cpp++; - if (ipn.in_redir == NAT_REDIRECT) { - if (hostmask(&cpp, (u_32_t *)&ipn.in_srcip, - (u_32_t *)&ipn.in_srcmsk, &ipn.in_sport, - &ipn.in_scmp, &ipn.in_stop, linenum)) { - *status = -1; - return NULL; - } - } else { - if (hostmask(&cpp, (u_32_t *)&ipn.in_inip, - (u_32_t *)&ipn.in_inmsk, &ipn.in_sport, - &ipn.in_scmp, &ipn.in_stop, linenum)) { - *status = -1; - return NULL; - } - } - - if (!strcmp(*cpp, "!")) { - cpp++; - ipn.in_flags |= IPN_NOTDST; - } else if (**cpp == '!') { - (*cpp)++; - ipn.in_flags |= IPN_NOTDST; - } - - if (strcasecmp(*cpp, "to")) { - fprintf(stderr, "%d: unexpected keyword (%s) - to\n", - linenum, *cpp); - *status = -1; - return NULL; - } - if ((ipn.in_flags & IPN_NOTDST) && - (ipn.in_redir & (NAT_REDIRECT))) { - fprintf(stderr, "Cannot use '! to' with rdr\n"); - *status = -1; - return NULL; - } - - if (!*++cpp) { - fprintf(stderr, "%d: missing host after to\n", linenum); - *status = -1; - return NULL; - } - if (ipn.in_redir == NAT_REDIRECT) { - if (hostmask(&cpp, (u_32_t *)&ipn.in_outip, - (u_32_t *)&ipn.in_outmsk, &ipn.in_dport, - &ipn.in_dcmp, &ipn.in_dtop, linenum)) { - *status = -1; - return NULL; - } - ipn.in_pmin = htons(ipn.in_dport); - } else { - if (hostmask(&cpp, (u_32_t *)&ipn.in_srcip, - (u_32_t *)&ipn.in_srcmsk, &ipn.in_dport, - &ipn.in_dcmp, &ipn.in_dtop, linenum)) { - *status = -1; - return NULL; - } - } - } else { - s = *cpp; - if (!s) { - fprintf(stderr, "%d: short line\n", linenum); - *status = -1; - return NULL; - } - t = strchr(s, '/'); - if (!t) { - fprintf(stderr, "%d: no netmask on LHS\n", linenum); - *status = -1; - return NULL; - } - *t++ = '\0'; - if (ipn.in_redir == NAT_REDIRECT) { - if (hostnum((u_32_t *)&ipn.in_outip, s, linenum) == -1){ - *status = -1; - return NULL; - } - if (genmask(t, (u_32_t *)&ipn.in_outmsk) == -1) { - *status = -1; - return NULL; - } - } else { - if (hostnum((u_32_t *)&ipn.in_inip, s, linenum) == -1) { - *status = -1; - return NULL; - } - if (genmask(t, (u_32_t *)&ipn.in_inmsk) == -1) { - *status = -1; - return NULL; - } - } - cpp++; - if (!*cpp) { - fprintf(stderr, "%d: short line\n", linenum); - *status = -1; - return NULL; - } - } - - /* - * If it is a standard redirect then we expect it to have a port - * match after the hostmask. - */ - if ((ipn.in_redir == NAT_REDIRECT) && !(ipn.in_flags & IPN_FILTER)) { - if (strcasecmp(*cpp, "port")) { - fprintf(stderr, "%d: missing fields - 1st port\n", - linenum); - *status = -1; - return NULL; - } - - cpp++; - - if (!*cpp) { - fprintf(stderr, - "%d: missing fields (destination port)\n", - linenum); - *status = -1; - return NULL; - } - - if (isdigit(**cpp) && (s = strchr(*cpp, '-'))) - *s++ = '\0'; - else - s = NULL; - - port1a = *cpp++; - - if (!strcmp(*cpp, "-")) { - cpp++; - s = *cpp++; - } - - if (s) - port1b = s; - else - ipn.in_pmax = ipn.in_pmin; - } - - /* - * In the middle of the NAT rule syntax is -> to indicate the - * direction of translation. - */ - if (!*cpp) { - fprintf(stderr, "%d: missing fields (->)\n", linenum); - *status = -1; - return NULL; - } - if (strcmp(*cpp, "->")) { - fprintf(stderr, "%d: missing ->\n", linenum); - *status = -1; - return NULL; - } - cpp++; - - if (!*cpp) { - fprintf(stderr, "%d: missing fields (%s)\n", - linenum, ipn.in_redir ? "destination" : "target"); - *status = -1; - return NULL; - } - - if (ipn.in_redir == NAT_MAP) { - if (!strcasecmp(*cpp, "range")) { - cpp++; - ipn.in_flags |= IPN_IPRANGE; - if (!*cpp) { - fprintf(stderr, "%d: missing fields (%s)\n", - linenum, - ipn.in_redir ? "destination":"target"); - *status = -1; - return NULL; - } - } - } - - if (ipn.in_flags & IPN_IPRANGE) { - dnetm = strrchr(*cpp, '-'); - if (dnetm == NULL) { - cpp++; - if (*cpp && !strcmp(*cpp, "-") && *(cpp + 1)) - dnetm = *(cpp + 1); - } else - *dnetm++ = '\0'; - if (dnetm == NULL || *dnetm == '\0') { - fprintf(stderr, - "%d: desination range not specified\n", - linenum); - *status = -1; - return NULL; - } - } else if (ipn.in_redir != NAT_REDIRECT) { - dnetm = strrchr(*cpp, '/'); - if (dnetm == NULL) { - cpp++; - if (*cpp && !strcasecmp(*cpp, "netmask")) - dnetm = *++cpp; - } - if (dnetm == NULL) { - fprintf(stderr, - "%d: missing fields (dest netmask)\n", - linenum); - *status = -1; - return NULL; - } - if (*dnetm == '/') - *dnetm++ = '\0'; - } - - if (ipn.in_redir == NAT_REDIRECT) { - dnetm = strchr(*cpp, ','); - if (dnetm != NULL) { - ipn.in_flags |= IPN_SPLIT; - *dnetm++ = '\0'; - } - if (hostnum((u_32_t *)&ipn.in_inip, *cpp, linenum) == -1) { - *status = -1; - return NULL; - } -#if SOLARIS - if (ntohl(ipn.in_inip) == INADDR_LOOPBACK) { - fprintf(stderr, - "localhost as destination not supported\n"); - *status = -1; - return NULL; - } -#endif - } else { - if (!strcmp(*cpp, ipn.in_ifname)) - *cpp = "0"; - if (hostnum((u_32_t *)&ipn.in_outip, *cpp, linenum) == -1) { - *status = -1; - return NULL; - } - } - cpp++; - - if (ipn.in_redir & NAT_MAPBLK) { - if (*cpp) { - if (strcasecmp(*cpp, "ports")) { - fprintf(stderr, - "%d: expected \"ports\" - got \"%s\"\n", - linenum, *cpp); - *status = -1; - return NULL; - } - cpp++; - if (*cpp == NULL) { - fprintf(stderr, - "%d: missing argument to \"ports\"\n", - linenum); - *status = -1; - return NULL; - } - if (!strcasecmp(*cpp, "auto")) - ipn.in_flags |= IPN_AUTOPORTMAP; - else - ipn.in_pmin = atoi(*cpp); - cpp++; - } else - ipn.in_pmin = 0; - } else if ((ipn.in_redir & NAT_BIMAP) == NAT_REDIRECT) { - if (*cpp && (strrchr(*cpp, '/') != NULL)) { - fprintf(stderr, "%d: No netmask supported in %s\n", - linenum, "destination host for redirect"); - *status = -1; - return NULL; - } - - if (!*cpp) { - fprintf(stderr, "%d: Missing destination port %s\n", - linenum, "in redirect"); - *status = -1; - return NULL; - } - - /* If it's a in_redir, expect target port */ - - if (strcasecmp(*cpp, "port")) { - fprintf(stderr, "%d: missing fields - 2nd port (%s)\n", - linenum, *cpp); - *status = -1; - return NULL; - } - cpp++; - if (!*cpp) { - fprintf(stderr, - "%d: missing fields (destination port)\n", - linenum); - *status = -1; - return NULL; - } - - port2a = *cpp++; - } - if (dnetm && *dnetm == '/') - *dnetm++ = '\0'; - - if (ipn.in_redir & (NAT_MAP|NAT_MAPBLK)) { - if (ipn.in_flags & IPN_IPRANGE) { - if (hostnum((u_32_t *)&ipn.in_outmsk, dnetm, - linenum) == -1) { - *status = -1; - return NULL; - } - } else if (genmask(dnetm, (u_32_t *)&ipn.in_outmsk)) { - *status = -1; - return NULL; - } - } else { - if (ipn.in_flags & IPN_SPLIT) { - if (hostnum((u_32_t *)&ipn.in_inmsk, dnetm, - linenum) == -1) { - *status = -1; - return NULL; - } - } else if (genmask("255.255.255.255", (u_32_t *)&ipn.in_inmsk)){ - *status = -1; - return NULL; - } - if (!*cpp) { - ipn.in_flags |= IPN_TCP; /* XXX- TCP only by default */ - proto = "tcp"; - } else { - proto = *cpp++; - if (!strcasecmp(proto, "tcp")) - ipn.in_flags |= IPN_TCP; - else if (!strcasecmp(proto, "udp")) - ipn.in_flags |= IPN_UDP; - else if (!strcasecmp(proto, "tcp/udp")) - ipn.in_flags |= IPN_TCPUDP; - else if (!strcasecmp(proto, "tcpudp")) { - ipn.in_flags |= IPN_TCPUDP; - proto = "tcp/udp"; - } else if (!strcasecmp(proto, "ip")) - ipn.in_flags |= IPN_ANY; - else { - ipn.in_flags |= IPN_ANY; - if ((pr = getprotobyname(proto))) - ipn.in_p = pr->p_proto; - else { - if (!isdigit(*proto)) { - fprintf(stderr, - "%d: Unknown protocol %s\n", - linenum, proto); - *status = -1; - return NULL; - } else - ipn.in_p = atoi(proto); - } - } - if ((ipn.in_flags & IPN_TCPUDP) == 0) { - port1a = "0"; - port2a = "0"; - } - - if (*cpp && !strcasecmp(*cpp, "round-robin")) { - cpp++; - ipn.in_flags |= IPN_ROUNDR; - } - - if (*cpp && !strcasecmp(*cpp, "frag")) { - cpp++; - ipn.in_flags |= IPN_FRAG; - } - - if (*cpp && !strcasecmp(*cpp, "age")) { - cpp++; - if (!*cpp) { - fprintf(stderr, - "%d: age with no parameters\n", - linenum); - *status = -1; - return NULL; - } - - ipn.in_age[0] = atoi(*cpp); - s = index(*cpp, '/'); - if (s != NULL) - ipn.in_age[1] = atoi(s + 1); - else - ipn.in_age[1] = ipn.in_age[0]; - cpp++; - } - - if (*cpp && !strcasecmp(*cpp, "mssclamp")) { - cpp++; - if (*cpp) { - ipn.in_mssclamp = atoi(*cpp); - cpp++; - } else { - fprintf(stderr, - "%d: mssclamp with no parameters\n", - linenum); - *status = -1; - return NULL; - } - } - - if (*cpp) { - fprintf(stderr, - "%d: extra junk at the end of the line: %s\n", - linenum, *cpp); - *status = -1; - return NULL; - } - } - } - - if ((ipn.in_redir == NAT_REDIRECT) && !(ipn.in_flags & IPN_FILTER)) { - if (!portnum(port1a, &ipn.in_pmin, linenum)) { - *status = -1; - return NULL; - } - ipn.in_pmin = htons(ipn.in_pmin); - if (port1b != NULL) { - if (!portnum(port1b, &ipn.in_pmax, linenum)) { - *status = -1; - return NULL; - } - ipn.in_pmax = htons(ipn.in_pmax); - } else - ipn.in_pmax = ipn.in_pmin; - } - - if ((ipn.in_redir & NAT_BIMAP) == NAT_REDIRECT) { - if (!portnum(port2a, &ipn.in_pnext, linenum)) { - *status = -1; - return NULL; - } - ipn.in_pnext = htons(ipn.in_pnext); - } - - if (!(ipn.in_flags & IPN_SPLIT)) - ipn.in_inip &= ipn.in_inmsk; - if ((ipn.in_flags & IPN_IPRANGE) == 0) - ipn.in_outip &= ipn.in_outmsk; - ipn.in_srcip &= ipn.in_srcmsk; - - if ((ipn.in_redir & NAT_MAPBLK) != 0) - nat_setgroupmap(&ipn); - - if (*cpp && !*(cpp+1) && !strcasecmp(*cpp, "frag")) { - cpp++; - ipn.in_flags |= IPN_FRAG; - } - - if (!*cpp) { - *status = 0; - return &ipn; - } - - if (ipn.in_redir != NAT_BIMAP && !strcasecmp(*cpp, "proxy")) { - u_short pport; - - if (ipn.in_redir == NAT_BIMAP) { - fprintf(stderr, "%d: cannot use proxy with bimap\n", - linenum); - *status = -1; - return NULL; - } - cpp++; - if (!*cpp) { - fprintf(stderr, - "%d: missing parameter for \"proxy\"\n", - linenum); - *status = -1; - return NULL; - } - dport = NULL; - - if (!strcasecmp(*cpp, "port")) { - cpp++; - if (!*cpp) { - fprintf(stderr, - "%d: missing parameter for \"port\"\n", - linenum); - *status = -1; - return NULL; - } - - dport = *cpp; - cpp++; - - if (!*cpp) { - fprintf(stderr, - "%d: missing parameter for \"proxy\"\n", - linenum); - *status = -1; - return NULL; - } - } else { - fprintf(stderr, - "%d: missing keyword \"port\"\n", linenum); - *status = -1; - return NULL; - } - - if ((proto = index(*cpp, '/'))) { - *proto++ = '\0'; - if ((pr = getprotobyname(proto))) - ipn.in_p = pr->p_proto; - else - ipn.in_p = atoi(proto); - } else - ipn.in_p = 0; - - if (dport && !portnum(dport, &pport, linenum)) - return NULL; - if (ipn.in_dcmp != 0) { - if (pport != ipn.in_dport) { - fprintf(stderr, - "%d: mismatch in port numbers\n", - linenum); - return NULL; - } - } else - ipn.in_dport = htons(pport); - - (void) strncpy(ipn.in_plabel, *cpp, sizeof(ipn.in_plabel)); - cpp++; - - } else if (ipn.in_redir != NAT_BIMAP && !strcasecmp(*cpp, "portmap")) { - if (ipn.in_redir == NAT_BIMAP) { - fprintf(stderr, "%d: cannot use portmap with bimap\n", - linenum); - *status = -1; - return NULL; - } - cpp++; - if (!*cpp) { - fprintf(stderr, - "%d: missing expression following portmap\n", - linenum); - *status = -1; - return NULL; - } - - if (!strcasecmp(*cpp, "tcp")) - ipn.in_flags |= IPN_TCP; - else if (!strcasecmp(*cpp, "udp")) - ipn.in_flags |= IPN_UDP; - else if (!strcasecmp(*cpp, "tcpudp")) - ipn.in_flags |= IPN_TCPUDP; - else if (!strcasecmp(*cpp, "tcp/udp")) - ipn.in_flags |= IPN_TCPUDP; - else { - fprintf(stderr, - "%d: expected protocol name - got \"%s\"\n", - linenum, *cpp); - *status = -1; - return NULL; - } - proto = *cpp; - cpp++; - - if (!*cpp) { - fprintf(stderr, "%d: no port range found\n", linenum); - *status = -1; - return NULL; - } - - if (!strcasecmp(*cpp, "auto")) { - ipn.in_flags |= IPN_AUTOPORTMAP; - ipn.in_pmin = htons(1024); - ipn.in_pmax = htons(65535); - nat_setgroupmap(&ipn); - cpp++; - } else { - if (!(t = strchr(*cpp, ':'))) { - fprintf(stderr, - "%d: no port range in \"%s\"\n", - linenum, *cpp); - *status = -1; - return NULL; - } - *t++ = '\0'; - if (!portnum(*cpp, &ipn.in_pmin, linenum) || - !portnum(t, &ipn.in_pmax, linenum)) { - *status = -1; - return NULL; - } - ipn.in_pmin = htons(ipn.in_pmin); - ipn.in_pmax = htons(ipn.in_pmax); - cpp++; - } - } - - if (*cpp && !strcasecmp(*cpp, "frag")) { - cpp++; - ipn.in_flags |= IPN_FRAG; - } - - if (*cpp && !strcasecmp(*cpp, "age")) { - cpp++; - if (!*cpp) { - fprintf(stderr, "%d: age with no parameters\n", - linenum); - *status = -1; - return NULL; - } - ipn.in_age[0] = atoi(*cpp); - s = index(*cpp, '/'); - if (s != NULL) - ipn.in_age[1] = atoi(s + 1); - else - ipn.in_age[1] = ipn.in_age[0]; - cpp++; - } - - if (*cpp && !strcasecmp(*cpp, "mssclamp")) { - cpp++; - if (*cpp) { - ipn.in_mssclamp = atoi(*cpp); - cpp++; - } else { - fprintf(stderr, "%d: mssclamp with no parameters\n", - linenum); - *status = -1; - return NULL; - } - } - - if (*cpp) { - fprintf(stderr, "%d: extra junk at the end of the line: %s\n", - linenum, *cpp); - *status = -1; - return NULL; - } - - *status = 0; - return &ipn; -} - - -void natparsefile(fd, file, opts) -int fd; -char *file; -int opts; -{ - char line[512], *s; - ipnat_t *np; - FILE *fp; - int linenum = 0; - int parsestatus; - - if (strcmp(file, "-")) { - if (!(fp = fopen(file, "r"))) { - fprintf(stderr, "%s: open: %s\n", file, - STRERROR(errno)); - exit(1); - } - } else - fp = stdin; - - while (fgets(line, sizeof(line) - 1, fp)) { - linenum++; - line[sizeof(line) - 1] = '\0'; - if ((s = strchr(line, '\n'))) - *s = '\0'; - - parsestatus = 1; - np = natparse(line, linenum, &parsestatus); - if (parsestatus != 0) { - if (*line) { - fprintf(stderr, "%d: syntax error in \"%s\"\n", - linenum, line); - } - fprintf(stderr, "%s: %s error (%d), quitting\n", - file, - ((parsestatus < 0)? "parse": "internal"), - parsestatus); - exit(1); - } - if (np) { - if ((opts & OPT_VERBOSE) && np) - printnat(np, opts); - if (!(opts & OPT_NODO)) { - if (!(opts & OPT_REMOVE)) { - if (ioctl(fd, SIOCADNAT, &np) == -1) { - fprintf(stderr, "%d:", - linenum); - perror("ioctl(SIOCADNAT)"); - } - } else if (ioctl(fd, SIOCRMNAT, &np) == -1) { - fprintf(stderr, "%d:", linenum); - perror("ioctl(SIOCRMNAT)"); - } - } - } - } - if (fp != stdin) - fclose(fp); -} diff --git a/net/.cvsignore b/net/.cvsignore deleted file mode 100644 index 19f86f493ab11..0000000000000 --- a/net/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -done diff --git a/opt.c b/opt.c deleted file mode 100644 index 825a5e346dd0f..0000000000000 --- a/opt.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - */ -#if defined(__sgi) && (IRIX > 602) -# include <sys/ptimers.h> -#endif -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <sys/types.h> -#include <sys/time.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#ifndef linux -#include <netinet/ip_var.h> -#endif -#include <netinet/tcp.h> -#include <net/if.h> -#include <arpa/inet.h> -#include "ip_compat.h" -#include <netinet/tcpip.h> -#include "ip_fil.h" -#include "ipf.h" - -#if !defined(lint) -static const char sccsid[] = "@(#)opt.c 1.8 4/10/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: opt.c,v 2.2.2.3 2002/12/06 11:40:27 darrenr Exp $"; -#endif - -extern int opts; - -struct ipopt_names ionames[] ={ - { IPOPT_NOP, 0x000001, 1, "nop" }, - { IPOPT_RR, 0x000002, 7, "rr" }, /* 1 route */ - { IPOPT_ZSU, 0x000004, 3, "zsu" }, - { IPOPT_MTUP, 0x000008, 3, "mtup" }, - { IPOPT_MTUR, 0x000010, 3, "mtur" }, - { IPOPT_ENCODE, 0x000020, 3, "encode" }, - { IPOPT_TS, 0x000040, 8, "ts" }, /* 1 TS */ - { IPOPT_TR, 0x000080, 3, "tr" }, - { IPOPT_SECURITY,0x000100, 11, "sec" }, - { IPOPT_SECURITY,0x000100, 11, "sec-class" }, - { IPOPT_LSRR, 0x000200, 7, "lsrr" }, /* 1 route */ - { IPOPT_E_SEC, 0x000400, 3, "e-sec" }, - { IPOPT_CIPSO, 0x000800, 3, "cipso" }, - { IPOPT_SATID, 0x001000, 4, "satid" }, - { IPOPT_SSRR, 0x002000, 7, "ssrr" }, /* 1 route */ - { IPOPT_ADDEXT, 0x004000, 3, "addext" }, - { IPOPT_VISA, 0x008000, 3, "visa" }, - { IPOPT_IMITD, 0x010000, 3, "imitd" }, - { IPOPT_EIP, 0x020000, 3, "eip" }, - { IPOPT_FINN, 0x040000, 3, "finn" }, - { 0, 0, 0, (char *)NULL } /* must be last */ -}; - -struct ipopt_names secclass[] = { - { IPSO_CLASS_RES4, 0x01, 0, "reserv-4" }, - { IPSO_CLASS_TOPS, 0x02, 0, "topsecret" }, - { IPSO_CLASS_SECR, 0x04, 0, "secret" }, - { IPSO_CLASS_RES3, 0x08, 0, "reserv-3" }, - { IPSO_CLASS_CONF, 0x10, 0, "confid" }, - { IPSO_CLASS_UNCL, 0x20, 0, "unclass" }, - { IPSO_CLASS_RES2, 0x40, 0, "reserv-2" }, - { IPSO_CLASS_RES1, 0x80, 0, "reserv-1" }, - { 0, 0, 0, NULL } /* must be last */ -}; - - -static u_char seclevel __P((char *)); -int addipopt __P((char *, struct ipopt_names *, int, char *)); - -static u_char seclevel(slevel) -char *slevel; -{ - struct ipopt_names *so; - - for (so = secclass; so->on_name; so++) - if (!strcasecmp(slevel, so->on_name)) - break; - - if (!so->on_name) { - fprintf(stderr, "no such security level: %s\n", slevel); - return 0; - } - return (u_char)so->on_value; -} - - -int addipopt(op, io, len, class) -char *op; -struct ipopt_names *io; -int len; -char *class; -{ - int olen = len; - struct in_addr ipadr; - u_short val; - u_char lvl; - char *s; - - if ((len + io->on_siz) > 48) { - fprintf(stderr, "options too long\n"); - return 0; - } - len += io->on_siz; - *op++ = io->on_value; - if (io->on_siz > 1) { - s = op; - *op++ = io->on_siz; - *op++ = IPOPT_MINOFF; - - if (class) { - switch (io->on_value) - { - case IPOPT_SECURITY : - lvl = seclevel(class); - *(op - 1) = lvl; - break; - case IPOPT_LSRR : - case IPOPT_SSRR : - ipadr.s_addr = inet_addr(class); - s[IPOPT_OLEN] = IPOPT_MINOFF - 1 + 4; - bcopy((char *)&ipadr, op, sizeof(ipadr)); - break; - case IPOPT_SATID : - val = atoi(class); - bcopy((char *)&val, op, 2); - break; - } - } - - op += io->on_siz - 3; - if (len & 3) { - *op++ = IPOPT_NOP; - len++; - } - } - if (opts & OPT_DEBUG) - fprintf(stderr, "bo: %s %d %#x: %d\n", - io->on_name, io->on_value, io->on_bit, len); - return len - olen; -} - - -u_32_t buildopts(cp, op, len) -char *cp, *op; -int len; -{ - struct ipopt_names *io; - u_32_t msk = 0; - char *s, *t; - int inc; - - for (s = strtok(cp, ","); s; s = strtok(NULL, ",")) { - if ((t = strchr(s, '='))) - *t++ = '\0'; - for (io = ionames; io->on_name; io++) { - if (strcasecmp(s, io->on_name) || (msk & io->on_bit)) - continue; - if ((inc = addipopt(op, io, len, t))) { - op += inc; - len += inc; - } - msk |= io->on_bit; - break; - } - if (!io->on_name) { - fprintf(stderr, "unknown IP option name %s\n", s); - return 0; - } - } - *op++ = IPOPT_EOL; - len++; - return len; -} diff --git a/opt_inet6.h b/opt_inet6.h deleted file mode 100644 index 43e7657e1ae39..0000000000000 --- a/opt_inet6.h +++ /dev/null @@ -1 +0,0 @@ -#define INET6 @@ -1,9 +1,9 @@ /* - * Copyright (C) 2000 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: opts.h,v 2.12 2003/08/14 14:24:27 darrenr Exp $ + * $Id$ */ #ifndef __OPTS_H__ @@ -40,6 +40,8 @@ #define OPT_HEX 0x2000000 #define OPT_ASCII 0x4000000 #define OPT_NORESOLVE 0x8000000 +#define OPT_DONTOPEN 0x10000000 +#define OPT_PURGE 0x20000000 #define OPT_STAT OPT_FRSTATES #define OPT_LIST OPT_SHOWLIST diff --git a/parse.c b/parse.c deleted file mode 100644 index 0d8a617d4aa33..0000000000000 --- a/parse.c +++ /dev/null @@ -1,1510 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - */ -#if defined(__sgi) && (IRIX > 602) -# include <sys/ptimers.h> -#endif -#include <sys/types.h> -#if !defined(__SVR4) && !defined(__svr4__) -#include <strings.h> -#else -#include <sys/byteorder.h> -#endif -#include <sys/param.h> -#include <sys/time.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/tcp.h> -#include <net/if.h> -#if __FreeBSD_version >= 300000 -# include <net/if_var.h> -#endif -#include <stdio.h> -#include <string.h> -#include <limits.h> -#include <stdlib.h> -#include <unistd.h> -#include <stddef.h> -#include <netdb.h> -#include <arpa/nameser.h> -#include <arpa/inet.h> -#include <resolv.h> -#include <ctype.h> -#include <syslog.h> -#include "ip_compat.h" -#include "ip_fil.h" -#include "ipf.h" -#include "facpri.h" - -#if !defined(lint) -static const char sccsid[] = "@(#)parse.c 1.44 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$IPFilter: parse.c,v 2.8 1999/12/28 10:49:46 darrenr Exp $"; -#endif - -extern struct ipopt_names ionames[], secclass[]; -extern int opts; -extern int use_inet6; - -int addicmp __P((char ***, struct frentry *, int)); -int extras __P((char ***, struct frentry *, int)); - -int icmpcode __P((char *)), addkeep __P((char ***, struct frentry *, int)); -int to_interface __P((frdest_t *, char *, int)); -void print_toif __P((char *, frdest_t *)); -void optprint __P((u_short *, u_long, u_long)); -int loglevel __P((char **, u_int *, int)); -void printlog __P((frentry_t *)); -void printifname __P((char *, char *, void *)); - -extern char *proto; -extern char flagset[]; -extern u_char flags[]; - - -/* parse() - * - * parse a line read from the input filter rule file - * - * status: - * < 0 error - * = 0 OK - * > 0 programmer error - */ -struct frentry *parse(line, linenum, status) -char *line; -int linenum; -int *status; /* good, bad, or indifferent */ -{ - static struct frentry fil; - char *cps[31], **cpp, *endptr, *s; - struct protoent *p = NULL; - int i, cnt = 1, j, ch; - u_int k; - - *status = 100; /* default to error */ - - while (*line && isspace(*line)) - line++; - if (!*line) { - *status = 0; - return NULL; - } - - bzero((char *)&fil, sizeof(fil)); - fil.fr_mip.fi_v = 0xf; - fil.fr_ip.fi_v = use_inet6 ? 6 : 4; - fil.fr_loglevel = 0xffff; - - /* - * break line up into max of 20 segments - */ - if (opts & OPT_DEBUG) - fprintf(stderr, "parse [%s]\n", line); - for (i = 0, *cps = strtok(line, " \b\t\r\n"); cps[i] && i < 30; cnt++) - cps[++i] = strtok(NULL, " \b\t\r\n"); - cps[i] = NULL; - - if (cnt < 3) { - fprintf(stderr, "%d: not enough segments in line\n", linenum); - *status = -1; - return NULL; - } - - cpp = cps; - /* - * The presence of an '@' followed by a number gives the position in - * the current rule list to insert this one. - */ - if (**cpp == '@') - fil.fr_hits = (U_QUAD_T)atoi(*cpp++ + 1) + 1; - - - /* - * Check the first keyword in the rule and any options that are - * expected to follow it. - */ - if (!strcasecmp("block", *cpp)) { - fil.fr_flags |= FR_BLOCK; - if (!strncasecmp(*(cpp+1), "return-icmp-as-dest", 19) && - (i = 19)) - fil.fr_flags |= FR_FAKEICMP; - else if (!strncasecmp(*(cpp+1), "return-icmp", 11) && (i = 11)) - fil.fr_flags |= FR_RETICMP; - if (fil.fr_flags & FR_RETICMP) { - cpp++; - if (strlen(*cpp) == i) { - if (*(cpp + 1) && **(cpp +1) == '(') { - cpp++; - i = 0; - } else - i = -1; - } - - /* - * The ICMP code is not required to follow in ()'s - */ - if ((i >= 0) && (*(*cpp + i) == '(')) { - i++; - j = icmpcode(*cpp + i); - if (j == -1) { - fprintf(stderr, - "%d: unrecognised icmp code %s\n", - linenum, *cpp + 20); - *status = -1; - return NULL; - } - fil.fr_icode = j; - } - } else if (!strcasecmp(*(cpp+1), "return-rst")) { - fil.fr_flags |= FR_RETRST; - cpp++; - } - } else if (!strcasecmp("count", *cpp)) { - fil.fr_flags |= FR_ACCOUNT; - } else if (!strcasecmp("pass", *cpp)) { - fil.fr_flags |= FR_PASS; - } else if (!strcasecmp("nomatch", *cpp)) { - fil.fr_flags |= FR_NOMATCH; - } else if (!strcasecmp("auth", *cpp)) { - fil.fr_flags |= FR_AUTH; - if (!strncasecmp(*(cpp+1), "return-rst", 10)) { - fil.fr_flags |= FR_RETRST; - cpp++; - } - } else if (!strcasecmp("preauth", *cpp)) { - fil.fr_flags |= FR_PREAUTH; - } else if (!strcasecmp("skip", *cpp)) { - cpp++; - if (ratoui(*cpp, &k, 0, UINT_MAX)) - fil.fr_skip = k; - else { - fprintf(stderr, "%d: integer must follow skip\n", - linenum); - *status = -1; - return NULL; - } - } else if (!strcasecmp("log", *cpp)) { - fil.fr_flags |= FR_LOG; - if (!strcasecmp(*(cpp+1), "body")) { - fil.fr_flags |= FR_LOGBODY; - cpp++; - } - if (!strcasecmp(*(cpp+1), "first")) { - fil.fr_flags |= FR_LOGFIRST; - cpp++; - } - if (*cpp && !strcasecmp(*(cpp+1), "or-block")) { - fil.fr_flags |= FR_LOGORBLOCK; - cpp++; - } - if (!strcasecmp(*(cpp+1), "level")) { - cpp++; - if (loglevel(cpp, &fil.fr_loglevel, linenum) == -1) { - /* NB loglevel prints its own error message */ - *status = -1; - return NULL; - } - cpp++; - } - } else { - /* - * Doesn't start with one of the action words - */ - fprintf(stderr, "%d: unknown keyword (%s)\n", linenum, *cpp); - *status = -1; - return NULL; - } - if (!*++cpp) { - fprintf(stderr, "%d: missing 'in'/'out' keyword\n", linenum); - *status = -1; - return NULL; - } - - /* - * Get the direction for filtering. Impose restrictions on direction - * if blocking with returning ICMP or an RST has been requested. - */ - if (!strcasecmp("in", *cpp)) - fil.fr_flags |= FR_INQUE; - else if (!strcasecmp("out", *cpp)) { - fil.fr_flags |= FR_OUTQUE; - if (fil.fr_flags & FR_RETICMP) { - fprintf(stderr, - "%d: Can only use return-icmp with 'in'\n", - linenum); - *status = -1; - return NULL; - } else if (fil.fr_flags & FR_RETRST) { - fprintf(stderr, - "%d: Can only use return-rst with 'in'\n", - linenum); - *status = -1; - return NULL; - } - } - if (!*++cpp) { - fprintf(stderr, "%d: missing source specification\n", linenum); - *status = -1; - return NULL; - } - - if (!strcasecmp("log", *cpp)) { - if (!*++cpp) { - fprintf(stderr, "%d: missing source specification\n", - linenum); - *status = -1; - return NULL; - } - if (fil.fr_flags & FR_PASS) - fil.fr_flags |= FR_LOGP; - else if (fil.fr_flags & FR_BLOCK) - fil.fr_flags |= FR_LOGB; - if (*cpp && !strcasecmp(*cpp, "body")) { - fil.fr_flags |= FR_LOGBODY; - cpp++; - } - if (*cpp && !strcasecmp(*cpp, "first")) { - fil.fr_flags |= FR_LOGFIRST; - cpp++; - } - if (*cpp && !strcasecmp(*cpp, "or-block")) { - if (!(fil.fr_flags & FR_PASS)) { - fprintf(stderr, - "%d: or-block must be used with pass\n", - linenum); - *status = -1; - return NULL; - } - fil.fr_flags |= FR_LOGORBLOCK; - cpp++; - } - if (*cpp && !strcasecmp(*cpp, "level")) { - if (loglevel(cpp, &fil.fr_loglevel, linenum) == -1) { - *status = -1; - return NULL; - } - cpp++; - cpp++; - } - } - - if (*cpp && !strcasecmp("quick", *cpp)) { - if (fil.fr_skip != 0) { - fprintf(stderr, "%d: cannot use skip with quick\n", - linenum); - *status = -1; - return NULL; - } - cpp++; - fil.fr_flags |= FR_QUICK; - } - - /* - * Parse rule options that are available if a rule is tied to an - * interface. - */ - *fil.fr_ifname = '\0'; - *fil.fr_oifname = '\0'; - if (*cpp && !strcasecmp(*cpp, "on")) { - if (!*++cpp) { - fprintf(stderr, "%d: interface name missing\n", - linenum); - *status = -1; - return NULL; - } - - s = index(*cpp, ','); - if (s != NULL) { - *s++ = '\0'; - (void)strncpy(fil.fr_ifnames[1], s, IFNAMSIZ - 1); - fil.fr_ifnames[1][IFNAMSIZ - 1] = '\0'; - } else - strcpy(fil.fr_ifnames[1], "*"); - - (void)strncpy(fil.fr_ifnames[0], *cpp, IFNAMSIZ - 1); - fil.fr_ifnames[0][IFNAMSIZ - 1] = '\0'; - - cpp++; - if (!*cpp) { - if ((fil.fr_flags & FR_RETMASK) == FR_RETRST) { - fprintf(stderr, - "%d: %s can only be used with TCP\n", - linenum, "return-rst"); - *status = -1; - return NULL; - } - *status = 0; - return &fil; - } - - if (*cpp) { - if (!strcasecmp(*cpp, "dup-to") && *(cpp + 1)) { - cpp++; - if (to_interface(&fil.fr_dif, *cpp, linenum)) { - *status = -1; - return NULL; - } - cpp++; - } - if (*cpp && !strcasecmp(*cpp, "to") && *(cpp + 1)) { - cpp++; - if (to_interface(&fil.fr_tif, *cpp, linenum)) { - *status = -1; - return NULL; - } - cpp++; - } else if (*cpp && !strcasecmp(*cpp, "fastroute")) { - if (!(fil.fr_flags & FR_INQUE)) { - fprintf(stderr, - "can only use %s with 'in'\n", - "fastroute"); - *status = -1; - return NULL; - } - fil.fr_flags |= FR_FASTROUTE; - cpp++; - } - } - - /* - * Set the "other" interface name. Lets you specify both - * inbound and outbound interfaces for state rules. Do not - * prevent both interfaces from being the same. - */ - strcpy(fil.fr_ifnames[3], "*"); - if ((*cpp != NULL) && (*(cpp + 1) != NULL) && - ((((fil.fr_flags & FR_INQUE) != 0) && - (strcasecmp(*cpp, "out-via") == 0)) || - (((fil.fr_flags & FR_OUTQUE) != 0) && - (strcasecmp(*cpp, "in-via") == 0)))) { - cpp++; - - s = index(*cpp, ','); - if (s != NULL) { - *s++ = '\0'; - (void)strncpy(fil.fr_ifnames[3], s, - IFNAMSIZ - 1); - fil.fr_ifnames[3][IFNAMSIZ - 1] = '\0'; - } - - (void)strncpy(fil.fr_ifnames[2], *cpp, IFNAMSIZ - 1); - fil.fr_ifnames[2][IFNAMSIZ - 1] = '\0'; - cpp++; - } else - strcpy(fil.fr_ifnames[2], "*"); - } - if (*cpp && !strcasecmp(*cpp, "tos")) { - if (!*++cpp) { - fprintf(stderr, "%d: tos missing value\n", linenum); - *status = -1; - return NULL; - } - fil.fr_tos = strtol(*cpp, NULL, 0); - fil.fr_mip.fi_tos = 0xff; - cpp++; - } - - if (*cpp && !strcasecmp(*cpp, "ttl")) { - if (!*++cpp) { - fprintf(stderr, "%d: ttl missing hopcount value\n", - linenum); - *status = -1; - return NULL; - } - if (ratoi(*cpp, &i, 0, 255)) - fil.fr_ttl = i; - else { - fprintf(stderr, "%d: invalid ttl (%s)\n", - linenum, *cpp); - *status = -1; - return NULL; - } - fil.fr_mip.fi_ttl = 0xff; - cpp++; - } - - /* - * check for "proto <protoname>" only decode udp/tcp/icmp as protoname - */ - proto = NULL; - if (*cpp && !strcasecmp(*cpp, "proto")) { - if (!*++cpp) { - fprintf(stderr, "%d: protocol name missing\n", linenum); - *status = -1; - return NULL; - } - proto = *cpp++; - if (!strcasecmp(proto, "tcp/udp")) { - fil.fr_ip.fi_fl |= FI_TCPUDP; - fil.fr_mip.fi_fl |= FI_TCPUDP; - } else if (use_inet6 && !strcasecmp(proto, "icmp")) { - fprintf(stderr, -"%d: use proto ipv6-icmp with IPv6 (or use proto 1 if you really mean icmp)\n", - linenum); - } else { - if (!(p = getprotobyname(proto)) && !isdigit(*proto)) { - fprintf(stderr, - "%d: unknown protocol (%s)\n", - linenum, proto); - *status = -1; - return NULL; - } - if (p) - fil.fr_proto = p->p_proto; - else if (isdigit(*proto)) { - i = (int)strtol(proto, &endptr, 0); - if (*endptr != '\0' || i < 0 || i > 255) { - fprintf(stderr, - "%d: unknown protocol (%s)\n", - linenum, proto); - *status = -1; - return NULL; - } - fil.fr_proto = i; - } - fil.fr_mip.fi_p = 0xff; - } - } - if ((fil.fr_proto != IPPROTO_TCP) && - ((fil.fr_flags & FR_RETMASK) == FR_RETRST)) { - fprintf(stderr, "%d: %s can only be used with TCP\n", - linenum, "return-rst"); - *status = -1; - return NULL; - } - - /* - * get the from host and bit mask to use against packets - */ - - if (!*cpp) { - fprintf(stderr, "%d: missing source specification\n", linenum); - *status = -1; - return NULL; - } - if (!strcasecmp(*cpp, "all")) { - cpp++; - if (!*cpp) { - *status = 0; - return &fil; - } - } else { - if (strcasecmp(*cpp, "from")) { - fprintf(stderr, "%d: unexpected keyword (%s) - from\n", - linenum, *cpp); - *status = -1; - return NULL; - } - if (!*++cpp) { - fprintf(stderr, "%d: missing host after from\n", - linenum); - *status = -1; - return NULL; - } - if (!strcmp(*cpp, "!")) { - fil.fr_flags |= FR_NOTSRCIP; - if (!*++cpp) { - fprintf(stderr, - "%d: missing host after from\n", - linenum); - *status = -1; - return NULL; - } - } else if (**cpp == '!') { - fil.fr_flags |= FR_NOTSRCIP; - (*cpp)++; - } - ch = 0; - if (hostmask(&cpp, (u_32_t *)&fil.fr_src, - (u_32_t *)&fil.fr_smsk, &fil.fr_sport, &ch, - &fil.fr_stop, linenum)) { - *status = -1; - return NULL; - } - - if ((ch != 0) && (fil.fr_proto != IPPROTO_TCP) && - (fil.fr_proto != IPPROTO_UDP) && - !(fil.fr_ip.fi_fl & FI_TCPUDP)) { - fprintf(stderr, - "%d: cannot use port and neither tcp or udp\n", - linenum); - *status = -1; - return NULL; - } - - fil.fr_scmp = ch; - if (!*cpp) { - fprintf(stderr, "%d: missing to fields\n", linenum); - *status = -1; - return NULL; - } - - /* - * do the same for the to field (destination host) - */ - if (strcasecmp(*cpp, "to")) { - fprintf(stderr, "%d: unexpected keyword (%s) - to\n", - linenum, *cpp); - *status = -1; - return NULL; - } - if (!*++cpp) { - fprintf(stderr, "%d: missing host after to\n", linenum); - *status = -1; - return NULL; - } - ch = 0; - if (!strcmp(*cpp, "!")) { - fil.fr_flags |= FR_NOTDSTIP; - if (!*++cpp) { - fprintf(stderr, - "%d: missing host after from\n", - linenum); - *status = -1; - return NULL; - } - } else if (**cpp == '!') { - fil.fr_flags |= FR_NOTDSTIP; - (*cpp)++; - } - if (hostmask(&cpp, (u_32_t *)&fil.fr_dst, - (u_32_t *)&fil.fr_dmsk, &fil.fr_dport, &ch, - &fil.fr_dtop, linenum)) { - *status = -1; - return NULL; - } - if ((ch != 0) && (fil.fr_proto != IPPROTO_TCP) && - (fil.fr_proto != IPPROTO_UDP) && - !(fil.fr_ip.fi_fl & FI_TCPUDP)) { - fprintf(stderr, - "%d: cannot use port and neither tcp or udp\n", - linenum); - *status = -1; - return NULL; - } - - fil.fr_dcmp = ch; - } - - /* - * check some sanity, make sure we don't have icmp checks with tcp - * or udp or visa versa. - */ - if (fil.fr_proto && (fil.fr_dcmp || fil.fr_scmp) && - fil.fr_proto != IPPROTO_TCP && fil.fr_proto != IPPROTO_UDP) { - fprintf(stderr, "%d: port operation on non tcp/udp\n", linenum); - *status = -1; - return NULL; - } - if (fil.fr_icmp && fil.fr_proto != IPPROTO_ICMP) { - fprintf(stderr, "%d: icmp comparisons on wrong protocol\n", - linenum); - *status = -1; - return NULL; - } - - if (!*cpp) { - *status = 0; - return &fil; - } - - if (*cpp && !strcasecmp(*cpp, "flags")) { - if (!*++cpp) { - fprintf(stderr, "%d: no flags present\n", linenum); - *status = -1; - return NULL; - } - fil.fr_tcpf = tcp_flags(*cpp, &fil.fr_tcpfm, linenum); - cpp++; - } - - /* - * extras... - */ - if ((fil.fr_v == 4) && *cpp && (!strcasecmp(*cpp, "with") || - !strcasecmp(*cpp, "and"))) - if (extras(&cpp, &fil, linenum)) { - *status = -1; - return NULL; - } - - /* - * icmp types for use with the icmp protocol - */ - if (*cpp && !strcasecmp(*cpp, "icmp-type")) { - if (fil.fr_proto != IPPROTO_ICMP && - fil.fr_proto != IPPROTO_ICMPV6) { - fprintf(stderr, - "%d: icmp with wrong protocol (%d)\n", - linenum, fil.fr_proto); - *status = -1; - return NULL; - } - if (addicmp(&cpp, &fil, linenum)) { - *status = -1; - return NULL; - } - fil.fr_icmp = htons(fil.fr_icmp); - fil.fr_icmpm = htons(fil.fr_icmpm); - } - - /* - * Keep something... - */ - while (*cpp && !strcasecmp(*cpp, "keep")) - if (addkeep(&cpp, &fil, linenum)) { - *status = -1; - return NULL; - } - - /* - * This is here to enforce the old interface binding behaviour. - * That is, "on X" is equivalent to "<dir> on X <!dir>-via -,X" - */ - if (fil.fr_flags & FR_KEEPSTATE) { - if (*fil.fr_ifnames[0] && !*fil.fr_ifnames[3]) { - bcopy(fil.fr_ifnames[0], fil.fr_ifnames[3], - sizeof(fil.fr_ifnames[3])); - strncpy(fil.fr_ifnames[2], "*", - sizeof(fil.fr_ifnames[3])); - } - } - - /* - * head of a new group ? - */ - if (*cpp && !strcasecmp(*cpp, "head")) { - if (fil.fr_skip != 0) { - fprintf(stderr, "%d: cannot use skip with head\n", - linenum); - *status = -1; - return NULL; - } - if (!*++cpp) { - fprintf(stderr, "%d: head without group #\n", linenum); - *status = -1; - return NULL; - } - if (ratoui(*cpp, &k, 0, UINT_MAX)) - fil.fr_grhead = (u_32_t)k; - else { - fprintf(stderr, "%d: invalid group (%s)\n", - linenum, *cpp); - *status = -1; - return NULL; - } - cpp++; - } - - /* - * head of a new group ? - */ - if (*cpp && !strcasecmp(*cpp, "group")) { - if (!*++cpp) { - fprintf(stderr, "%d: group without group #\n", - linenum); - *status = -1; - return NULL; - } - if (ratoui(*cpp, &k, 0, UINT_MAX)) - fil.fr_group = k; - else { - fprintf(stderr, "%d: invalid group (%s)\n", - linenum, *cpp); - *status = -1; - return NULL; - } - cpp++; - } - - /* - * leftovers...yuck - */ - if (*cpp && **cpp) { - fprintf(stderr, "%d: unknown words at end: [", linenum); - for (; *cpp; cpp++) - fprintf(stderr, "%s ", *cpp); - fprintf(stderr, "]\n"); - *status = -1; - return NULL; - } - - /* - * lazy users... - */ - if ((fil.fr_tcpf || fil.fr_tcpfm) && fil.fr_proto != IPPROTO_TCP) { - fprintf(stderr, "%d: TCP protocol not specified\n", linenum); - *status = -1; - return NULL; - } - if (!(fil.fr_ip.fi_fl & FI_TCPUDP) && (fil.fr_proto != IPPROTO_TCP) && - (fil.fr_proto != IPPROTO_UDP) && (fil.fr_dcmp || fil.fr_scmp)) { - if (!fil.fr_proto) { - fil.fr_ip.fi_fl |= FI_TCPUDP; - fil.fr_mip.fi_fl |= FI_TCPUDP; - } else { - fprintf(stderr, - "%d: port comparisons for non-TCP/UDP\n", - linenum); - *status = -1; - return NULL; - } - } -/* - if ((fil.fr_flags & FR_KEEPFRAG) && - (!(fil.fr_ip.fi_fl & FI_FRAG) || !(fil.fr_ip.fi_fl & FI_FRAG))) { - fprintf(stderr, - "%d: must use 'with frags' with 'keep frags'\n", - linenum); - *status = -1; - return NULL; - } -*/ - *status = 0; - return &fil; -} - - -int loglevel(cpp, facpri, linenum) -char **cpp; -u_int *facpri; -int linenum; -{ - int fac, pri; - char *s; - - fac = 0; - pri = 0; - if (!*++cpp) { - fprintf(stderr, "%d: %s\n", linenum, - "missing identifier after level"); - return -1; - } - - s = index(*cpp, '.'); - if (s) { - *s++ = '\0'; - fac = fac_findname(*cpp); - if (fac == -1) { - fprintf(stderr, "%d: %s %s\n", linenum, - "Unknown facility", *cpp); - return -1; - } - pri = pri_findname(s); - if (pri == -1) { - fprintf(stderr, "%d: %s %s\n", linenum, - "Unknown priority", s); - return -1; - } - } else { - pri = pri_findname(*cpp); - if (pri == -1) { - fprintf(stderr, "%d: %s %s\n", linenum, - "Unknown priority", *cpp); - return -1; - } - } - *facpri = fac|pri; - return 0; -} - - -int to_interface(fdp, to, linenum) -frdest_t *fdp; -char *to; -int linenum; -{ - char *s; - - s = index(to, ':'); - fdp->fd_ifp = NULL; - if (s) { - *s++ = '\0'; - if (hostnum((u_32_t *)&fdp->fd_ip, s, linenum) == -1) - return -1; - } - (void) strncpy(fdp->fd_ifname, to, sizeof(fdp->fd_ifname) - 1); - fdp->fd_ifname[sizeof(fdp->fd_ifname) - 1] = '\0'; - return 0; -} - - -void print_toif(tag, fdp) -char *tag; -frdest_t *fdp; -{ - printf("%s %s%s", tag, fdp->fd_ifname, - (fdp->fd_ifp || (long)fdp->fd_ifp == -1) ? "" : "(!)"); -#ifdef USE_INET6 - if (use_inet6 && IP6_NOTZERO(&fdp->fd_ip6.in6)) { - char ipv6addr[80]; - - inet_ntop(AF_INET6, &fdp->fd_ip6, ipv6addr, - sizeof(fdp->fd_ip6)); - printf(":%s", ipv6addr); - } else -#endif - if (fdp->fd_ip.s_addr) - printf(":%s", inet_ntoa(fdp->fd_ip)); - putchar(' '); -} - - -/* - * deal with extra bits on end of the line - */ -int extras(cp, fr, linenum) -char ***cp; -struct frentry *fr; -int linenum; -{ - u_short secmsk; - u_long opts; - int notopt; - char oflags; - - opts = 0; - secmsk = 0; - notopt = 0; - (*cp)++; - if (!**cp) - return -1; - - while (**cp && (!strncasecmp(**cp, "ipopt", 5) || - !strcasecmp(**cp, "not") || !strncasecmp(**cp, "opt", 3) || - !strncasecmp(**cp, "frag", 4) || !strcasecmp(**cp, "no") || - !strcasecmp(**cp, "short"))) { - if (***cp == 'n' || ***cp == 'N') { - notopt = 1; - (*cp)++; - continue; - } else if (***cp == 'i' || ***cp == 'I') { - if (!notopt) - fr->fr_ip.fi_fl |= FI_OPTIONS; - fr->fr_mip.fi_fl |= FI_OPTIONS; - goto nextopt; - } else if (***cp == 'f' || ***cp == 'F') { - if (!notopt) - fr->fr_ip.fi_fl |= FI_FRAG; - fr->fr_mip.fi_fl |= FI_FRAG; - goto nextopt; - } else if (***cp == 'o' || ***cp == 'O') { - if (!*(*cp + 1)) { - fprintf(stderr, - "%d: opt missing arguements\n", - linenum); - return -1; - } - (*cp)++; - if (!(opts = optname(cp, &secmsk, linenum))) - return -1; - oflags = FI_OPTIONS; - } else if (***cp == 's' || ***cp == 'S') { - if (fr->fr_tcpf) { - fprintf(stderr, - "%d: short cannot be used with TCP flags\n", - linenum); - return -1; - } - - if (!notopt) - fr->fr_ip.fi_fl |= FI_SHORT; - fr->fr_mip.fi_fl |= FI_SHORT; - goto nextopt; - } else - return -1; - - if (!notopt || !opts) - fr->fr_mip.fi_fl |= oflags; - if (notopt) { - if (!secmsk) { - fr->fr_mip.fi_optmsk |= opts; - } else { - fr->fr_mip.fi_optmsk |= (opts & ~0x0100); - } - } else { - fr->fr_mip.fi_optmsk |= opts; - } - fr->fr_mip.fi_secmsk |= secmsk; - - if (notopt) { - fr->fr_ip.fi_fl &= (~oflags & 0xf); - fr->fr_ip.fi_optmsk &= ~opts; - fr->fr_ip.fi_secmsk &= ~secmsk; - } else { - fr->fr_ip.fi_fl |= oflags; - fr->fr_ip.fi_optmsk |= opts; - fr->fr_ip.fi_secmsk |= secmsk; - } -nextopt: - notopt = 0; - opts = 0; - oflags = 0; - secmsk = 0; - (*cp)++; - } - return 0; -} - - -u_32_t optname(cp, sp, linenum) -char ***cp; -u_short *sp; -int linenum; -{ - struct ipopt_names *io, *so; - u_long msk = 0; - u_short smsk = 0; - char *s; - int sec = 0; - - for (s = strtok(**cp, ","); s; s = strtok(NULL, ",")) { - for (io = ionames; io->on_name; io++) - if (!strcasecmp(s, io->on_name)) { - msk |= io->on_bit; - break; - } - if (!io->on_name) { - fprintf(stderr, "%d: unknown IP option name %s\n", - linenum, s); - return 0; - } - if (!strcasecmp(s, "sec-class")) - sec = 1; - } - - if (sec && !*(*cp + 1)) { - fprintf(stderr, "%d: missing security level after sec-class\n", - linenum); - return 0; - } - - if (sec) { - (*cp)++; - for (s = strtok(**cp, ","); s; s = strtok(NULL, ",")) { - for (so = secclass; so->on_name; so++) - if (!strcasecmp(s, so->on_name)) { - smsk |= so->on_bit; - break; - } - if (!so->on_name) { - fprintf(stderr, - "%d: no such security level: %s\n", - linenum, s); - return 0; - } - } - if (smsk) - *sp = smsk; - } - return msk; -} - - -#ifdef __STDC__ -void optprint(u_short *sec, u_long optmsk, u_long optbits) -#else -void optprint(sec, optmsk, optbits) -u_short *sec; -u_long optmsk, optbits; -#endif -{ - u_short secmsk = sec[0], secbits = sec[1]; - struct ipopt_names *io, *so; - char *s; - - s = " opt "; - for (io = ionames; io->on_name; io++) - if ((io->on_bit & optmsk) && - ((io->on_bit & optmsk) == (io->on_bit & optbits))) { - if ((io->on_value != IPOPT_SECURITY) || - (!secmsk && !secbits)) { - printf("%s%s", s, io->on_name); - if (io->on_value == IPOPT_SECURITY) - io++; - s = ","; - } - } - - - if (secmsk & secbits) { - printf("%ssec-class", s); - s = " "; - for (so = secclass; so->on_name; so++) - if ((secmsk & so->on_bit) && - ((so->on_bit & secmsk) == (so->on_bit & secbits))) { - printf("%s%s", s, so->on_name); - s = ","; - } - } - - if ((optmsk && (optmsk != optbits)) || - (secmsk && (secmsk != secbits))) { - s = " "; - printf(" not opt"); - if (optmsk != optbits) { - for (io = ionames; io->on_name; io++) - if ((io->on_bit & optmsk) && - ((io->on_bit & optmsk) != - (io->on_bit & optbits))) { - if ((io->on_value != IPOPT_SECURITY) || - (!secmsk && !secbits)) { - printf("%s%s", s, io->on_name); - s = ","; - if (io->on_value == - IPOPT_SECURITY) - io++; - } else - io++; - } - } - - if (secmsk != secbits) { - printf("%ssec-class", s); - s = " "; - for (so = secclass; so->on_name; so++) - if ((so->on_bit & secmsk) && - ((so->on_bit & secmsk) != - (so->on_bit & secbits))) { - printf("%s%s", s, so->on_name); - s = ","; - } - } - } -} - -char *icmptypes[] = { - "echorep", (char *)NULL, (char *)NULL, "unreach", "squench", - "redir", (char *)NULL, (char *)NULL, "echo", "routerad", - "routersol", "timex", "paramprob", "timest", "timestrep", - "inforeq", "inforep", "maskreq", "maskrep", "END" -}; - -/* - * set the icmp field to the correct type if "icmp" word is found - */ -int addicmp(cp, fp, linenum) -char ***cp; -struct frentry *fp; -int linenum; -{ - char **t; - int i; - - (*cp)++; - if (!**cp) - return -1; - - if (isdigit(***cp)) { - if (!ratoi(**cp, &i, 0, 255)) { - fprintf(stderr, - "%d: Invalid icmp-type (%s) specified\n", - linenum, **cp); - return -1; - } - } else if (fp->fr_proto == IPPROTO_ICMPV6) { - fprintf(stderr, "%d: Unknown ICMPv6 type (%s) specified, %s", - linenum, **cp, "(use numeric value instead)\n"); - return -1; - } else { - for (t = icmptypes, i = 0; ; t++, i++) { - if (!*t) - continue; - if (!strcasecmp("END", *t)) { - i = -1; - break; - } - if (!strcasecmp(*t, **cp)) - break; - } - if (i == -1) { - fprintf(stderr, - "%d: Invalid icmp-type (%s) specified\n", - linenum, **cp); - return -1; - } - } - fp->fr_icmp = (u_short)(i << 8); - fp->fr_icmpm = (u_short)0xff00; - (*cp)++; - if (!**cp) - return 0; - - if (**cp && strcasecmp("code", **cp)) - return 0; - (*cp)++; - if (isdigit(***cp)) { - if (!ratoi(**cp, &i, 0, 255)) { - fprintf(stderr, - "%d: Invalid icmp code (%s) specified\n", - linenum, **cp); - return -1; - } - } else { - i = icmpcode(**cp); - if (i == -1) { - fprintf(stderr, - "%d: Invalid icmp code (%s) specified\n", - linenum, **cp); - return -1; - } - } - i &= 0xff; - fp->fr_icmp |= (u_short)i; - fp->fr_icmpm = (u_short)0xffff; - (*cp)++; - return 0; -} - - -#define MAX_ICMPCODE 15 - -char *icmpcodes[] = { - "net-unr", "host-unr", "proto-unr", "port-unr", "needfrag", - "srcfail", "net-unk", "host-unk", "isolate", "net-prohib", - "host-prohib", "net-tos", "host-tos", "filter-prohib", "host-preced", - "preced-cutoff", NULL }; -/* - * Return the number for the associated ICMP unreachable code. - */ -int icmpcode(str) -char *str; -{ - char *s; - int i, len; - - if ((s = strrchr(str, ')'))) - *s = '\0'; - if (isdigit(*str)) { - if (!ratoi(str, &i, 0, 255)) - return -1; - else - return i; - } - len = strlen(str); - for (i = 0; icmpcodes[i]; i++) - if (!strncasecmp(str, icmpcodes[i], MIN(len, - strlen(icmpcodes[i])) )) - return i; - return -1; -} - - -/* - * set the icmp field to the correct type if "icmp" word is found - */ -int addkeep(cp, fp, linenum) -char ***cp; -struct frentry *fp; -int linenum; -{ - char *s; - - (*cp)++; - if (!**cp) { - fprintf(stderr, "%d: Missing keyword after keep\n", - linenum); - return -1; - } - - if (strcasecmp(**cp, "state") == 0) - fp->fr_flags |= FR_KEEPSTATE; - else if (strncasecmp(**cp, "frag", 4) == 0) - fp->fr_flags |= FR_KEEPFRAG; - else if (strcasecmp(**cp, "state-age") == 0) { - if (fp->fr_ip.fi_p == IPPROTO_TCP) { - fprintf(stderr, "%d: cannot use state-age with tcp\n", - linenum); - return -1; - } - if ((fp->fr_flags & FR_KEEPSTATE) == 0) { - fprintf(stderr, "%d: state-age with no 'keep state'\n", - linenum); - return -1; - } - (*cp)++; - if (!**cp) { - fprintf(stderr, "%d: state-age with no arg\n", - linenum); - return -1; - } - fp->fr_age[0] = atoi(**cp); - s = index(**cp, '/'); - if (s != NULL) { - s++; - fp->fr_age[1] = atoi(s); - } else - fp->fr_age[1] = fp->fr_age[0]; - } else { - fprintf(stderr, "%d: Unrecognised state keyword \"%s\"\n", - linenum, **cp); - return -1; - } - (*cp)++; - return 0; -} - - -void printifname(format, name, ifp) -char *format, *name; -void *ifp; -{ - printf("%s%s", format, name); - if ((ifp == NULL) && strcmp(name, "-") && strcmp(name, "*")) - printf("(!)"); -} - - -/* - * print the filter structure in a useful way - */ -void printfr(fp) -struct frentry *fp; -{ - struct protoent *p; - u_short sec[2]; - char *s; - u_char *t; - int pr; - - if (fp->fr_flags & FR_PASS) - printf("pass"); - if (fp->fr_flags & FR_NOMATCH) - printf("nomatch"); - else if (fp->fr_flags & FR_BLOCK) { - printf("block"); - if (fp->fr_flags & FR_RETICMP) { - if ((fp->fr_flags & FR_RETMASK) == FR_FAKEICMP) - printf(" return-icmp-as-dest"); - else if ((fp->fr_flags & FR_RETMASK) == FR_RETICMP) - printf(" return-icmp"); - if (fp->fr_icode) { - if (fp->fr_icode <= MAX_ICMPCODE) - printf("(%s)", - icmpcodes[(int)fp->fr_icode]); - else - printf("(%d)", fp->fr_icode); - } - } else if ((fp->fr_flags & FR_RETMASK) == FR_RETRST) - printf(" return-rst"); - } else if ((fp->fr_flags & FR_LOGMASK) == FR_LOG) { - printlog(fp); - } else if (fp->fr_flags & FR_ACCOUNT) - printf("count"); - else if (fp->fr_flags & FR_AUTH) { - printf("auth"); - if ((fp->fr_flags & FR_RETMASK) == FR_RETRST) - printf(" return-rst"); - } else if (fp->fr_flags & FR_PREAUTH) - printf("preauth"); - else if (fp->fr_skip) - printf("skip %hu", fp->fr_skip); - - if (fp->fr_flags & FR_OUTQUE) - printf(" out "); - else - printf(" in "); - - if (((fp->fr_flags & FR_LOGB) == FR_LOGB) || - ((fp->fr_flags & FR_LOGP) == FR_LOGP)) { - printlog(fp); - putchar(' '); - } - - if (fp->fr_flags & FR_QUICK) - printf("quick "); - - if (*fp->fr_ifname) { - printifname("on ", fp->fr_ifname, fp->fr_ifa); - if (*fp->fr_ifnames[1] && strcmp(fp->fr_ifnames[1], "*")) - printifname(",", fp->fr_ifnames[1], fp->fr_ifas[1]); - putchar(' '); - - if (*fp->fr_dif.fd_ifname) - print_toif("dup-to", &fp->fr_dif); - if (*fp->fr_tif.fd_ifname) - print_toif("to", &fp->fr_tif); - if (fp->fr_flags & FR_FASTROUTE) - printf("fastroute "); - - if ((*fp->fr_ifnames[2] && strcmp(fp->fr_ifnames[2], "*")) || - (*fp->fr_ifnames[3] && strcmp(fp->fr_ifnames[3], "*"))) { - if (fp->fr_flags & FR_OUTQUE) - printf("in-via "); - else - printf("out-via "); - - if (*fp->fr_ifnames[2]) { - printifname("", fp->fr_ifnames[2], - fp->fr_ifas[2]); - putchar(','); - } - - if (*fp->fr_ifnames[3]) - printifname("", fp->fr_ifnames[3], - fp->fr_ifas[3]); - putchar(' '); - } - } - - if (fp->fr_mip.fi_tos) - printf("tos %#x ", fp->fr_tos); - if (fp->fr_mip.fi_ttl) - printf("ttl %d ", fp->fr_ttl); - if (fp->fr_ip.fi_fl & FI_TCPUDP) { - printf("proto tcp/udp "); - pr = -1; - } else if ((pr = fp->fr_mip.fi_p)) { - if ((p = getprotobynumber(fp->fr_proto))) - printf("proto %s ", p->p_name); - else - printf("proto %d ", fp->fr_proto); - } - - printf("from %s", fp->fr_flags & FR_NOTSRCIP ? "!" : ""); - printhostmask(fp->fr_v, (u_32_t *)&fp->fr_src.s_addr, - (u_32_t *)&fp->fr_smsk.s_addr); - if (fp->fr_scmp) - printportcmp(pr, &fp->fr_tuc.ftu_src); - - printf(" to %s", fp->fr_flags & FR_NOTDSTIP ? "!" : ""); - printhostmask(fp->fr_v, (u_32_t *)&fp->fr_dst.s_addr, - (u_32_t *)&fp->fr_dmsk.s_addr); - if (fp->fr_dcmp) - printportcmp(pr, &fp->fr_tuc.ftu_dst); - - if ((fp->fr_ip.fi_fl & ~FI_TCPUDP) || - (fp->fr_mip.fi_fl & ~FI_TCPUDP) || - fp->fr_ip.fi_optmsk || fp->fr_mip.fi_optmsk || - fp->fr_ip.fi_secmsk || fp->fr_mip.fi_secmsk) { - printf(" with"); - if (fp->fr_ip.fi_optmsk || fp->fr_mip.fi_optmsk || - fp->fr_ip.fi_secmsk || fp->fr_mip.fi_secmsk) { - sec[0] = fp->fr_mip.fi_secmsk; - sec[1] = fp->fr_ip.fi_secmsk; - optprint(sec, - fp->fr_mip.fi_optmsk, fp->fr_ip.fi_optmsk); - } else if (fp->fr_mip.fi_fl & FI_OPTIONS) { - if (!(fp->fr_ip.fi_fl & FI_OPTIONS)) - printf(" not"); - printf(" ipopt"); - } - if (fp->fr_mip.fi_fl & FI_SHORT) { - if (!(fp->fr_ip.fi_fl & FI_SHORT)) - printf(" not"); - printf(" short"); - } - if (fp->fr_mip.fi_fl & FI_FRAG) { - if (!(fp->fr_ip.fi_fl & FI_FRAG)) - printf(" not"); - printf(" frag"); - } - } - if (fp->fr_proto == IPPROTO_ICMP && fp->fr_icmpm != 0) { - int type = fp->fr_icmp, code; - - type = ntohs(fp->fr_icmp); - code = type & 0xff; - type /= 256; - if (type < (sizeof(icmptypes) / sizeof(char *) - 1) && - icmptypes[type]) - printf(" icmp-type %s", icmptypes[type]); - else - printf(" icmp-type %d", type); - if (ntohs(fp->fr_icmpm) & 0xff) - printf(" code %d", code); - } - if (fp->fr_proto == IPPROTO_ICMPV6 && fp->fr_icmpm != 0) { - int type = fp->fr_icmp, code; - - type = ntohs(fp->fr_icmp); - code = type & 0xff; - type /= 256; - printf(" icmp-type %d", type); - if (ntohs(fp->fr_icmpm) & 0xff) - printf(" code %d", code); - } - if (fp->fr_proto == IPPROTO_TCP && (fp->fr_tcpf || fp->fr_tcpfm)) { - printf(" flags "); - if (fp->fr_tcpf & ~TCPF_ALL) - printf("0x%x", fp->fr_tcpf); - else - for (s = flagset, t = flags; *s; s++, t++) - if (fp->fr_tcpf & *t) - (void)putchar(*s); - if (fp->fr_tcpfm) { - (void)putchar('/'); - if (fp->fr_tcpfm & ~TCPF_ALL) - printf("0x%x", fp->fr_tcpfm); - else - for (s = flagset, t = flags; *s; s++, t++) - if (fp->fr_tcpfm & *t) - (void)putchar(*s); - } - } - - if (fp->fr_flags & FR_KEEPSTATE) - printf(" keep state"); - if (fp->fr_flags & FR_KEEPFRAG) - printf(" keep frags"); - if (fp->fr_age[0] != 0 || fp->fr_age[1]!= 0) - printf(" state-age %u/%u", fp->fr_age[0], fp->fr_age[1]); - if (fp->fr_grhead) - printf(" head %d", fp->fr_grhead); - if (fp->fr_group) - printf(" group %d", fp->fr_group); - (void)putchar('\n'); -} - -void binprint(fp) -struct frentry *fp; -{ - int i = sizeof(*fp), j = 0; - u_char *s; - - for (s = (u_char *)fp; i; i--, s++) { - j++; - printf("%02x ", *s); - if (j == 16) { - printf("\n"); - j = 0; - } - } - putchar('\n'); - (void)fflush(stdout); -} - - -void printlog(fp) -frentry_t *fp; -{ - char *s, *u; - - printf("log"); - if (fp->fr_flags & FR_LOGBODY) - printf(" body"); - if (fp->fr_flags & FR_LOGFIRST) - printf(" first"); - if (fp->fr_flags & FR_LOGORBLOCK) - printf(" or-block"); - if (fp->fr_loglevel != 0xffff) { - printf(" level "); - if (fp->fr_loglevel & LOG_FACMASK) { - s = fac_toname(fp->fr_loglevel); - if (s == NULL) - s = "!!!"; - } else - s = ""; - u = pri_toname(fp->fr_loglevel); - if (u == NULL) - u = "!!!"; - if (*s) - printf("%s.%s", s, u); - else - printf("%s", u); - } -} diff --git a/pcap-ipf.h b/pcap-ipf.h index 2ad5b01b22d5d..90c087ba29895 100644 --- a/pcap-ipf.h +++ b/pcap-ipf.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * diff --git a/pcap.h b/pcap.h deleted file mode 100644 index aa2479811a896..0000000000000 --- a/pcap.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * $Id: pcap.h,v 2.2.2.1 2001/06/26 10:43:20 darrenr Exp $ - */ -/* - * This header file is constructed to match the version described by - * PCAP_VERSION_MAJ. - * - * The structure largely derives from libpcap which wouldn't include - * nicely without bpf. - */ -typedef struct pcap_filehdr { - u_int pc_id; - u_short pc_v_maj; - u_short pc_v_min; - u_int pc_zone; - u_int pc_sigfigs; - u_int pc_slen; - u_int pc_type; -} pcaphdr_t; - -#define TCPDUMP_MAGIC 0xa1b2c3d4 - -#define PCAP_VERSION_MAJ 2 - -typedef struct pcap_pkthdr { - struct timeval ph_ts; - u_int ph_clen; - u_int ph_len; -} pcappkt_t; - diff --git a/perl/Ipfanaly.pl b/perl/Ipfanaly.pl index 0fa7c17ef7fbd..eda232ee9592c 100644 --- a/perl/Ipfanaly.pl +++ b/perl/Ipfanaly.pl @@ -41,7 +41,7 @@ if ($maxout > $maxin) ($dayis,$monthis,$yearis)=split "/",$dateis; $month=$months{$monthis}; $dateis="$dayis " . "$month " . "$yearis "; -# split graphs in to 6 four hour spans for 24 hours +# split graphs in to 6 four hour spans for 24 hours $numgraphs=int($XMAX/240); $junk=0; @@ -62,7 +62,7 @@ while ($cnt1++ < $numgraphs) $filename3="graph$cnt1.conf"; open(OUTDATA,"> $filename2") || die "Couldnt open $filename2 for writing \n"; open(INDATA,"> $filename1") || die "Couldnt open $filename1 for writing \n"; - + $loop=$end; $end=($end + 240); @@ -144,7 +144,7 @@ sub packbytime { local ($xmax)=@_; $XMAX=$xmax; # pass in the dest port number or get graph for all packets -# at 1 minute intervals +# at 1 minute intervals # @shortrecs has form 209.24.1.217 123 192.216.16.2 123 udp len 20 76 # @recs has form 27/07/1998 00:01:05.216596 le0 @0:2 L 192.216.21.16,2733 -> 192.216.16.2,53 PR udp len 20 62 # @@ -175,9 +175,9 @@ while ($cnt++ <= $#recs ) if("$destip" eq "$gatekeep") { # TO GATEKEEP port lookat -# print "to gatekeep at $xpos\n"; +# print "to gatekeep at $xpos\n"; $value5=$inwards[$xpos] [1]; - $value5++ ; + $value5++ ; # $maxin = $value5 if $maxin < $value5 ; if($value5 > $maxin) @@ -190,9 +190,9 @@ while ($cnt++ <= $#recs ) else { # FROM GATEKEEP to port lookat -# print "from gatekeep at $xpos\n"; +# print "from gatekeep at $xpos\n"; $value4=$outwards[$xpos] [1]; - $value4++ ; + $value4++ ; # $maxout = $value4 if $maxout < $value4 ; if($value4 > $maxout) { @@ -212,18 +212,18 @@ while ($cnt++ <= $#recs ) if("$destip" eq "$gatekeep") { # TO GATEKEEP port lookat -# print "to gatekeep at $xpos\n"; +# print "to gatekeep at $xpos\n"; $value5=$inwards[$xpos] [1]; - $value5++ ; + $value5++ ; $maxin = $value5 if $maxin < $value5 ; $inwards[$xpos][1]=$value5; } else { # FROM GATEKEEP to port lookat -# print "from gatekeep at $xpos\n"; +# print "from gatekeep at $xpos\n"; $value4=$outwards[$xpos] [1]; - $value4++ ; + $value4++ ; $maxout = $value4 if $maxout < $value4 ; $outwards[$xpos][1]=$value4; } @@ -276,7 +276,7 @@ $loop=-1; while ($loop++ <= $#recs ) { ($srcip,$srcport,$destip,$destport,$pro)= split " " , @shortrecs[$loop]; - if ("$destip" eq "$gatekeep") + if ("$destip" eq "$gatekeep") { if ($destport < $ITRUSTABOVE ) { @@ -309,10 +309,10 @@ print "# Sites sending > $percsafe % of all packets to gatekeep MAY be attacking print "Trusted hosts are $safehosts\n"; print "\nTOTAL packets were $#recs \n"; print "########################################################################\n"; -while(($ipadd,$numpacketsent)=each %numpacks) +while(($ipadd,$numpacketsent)=each %numpacks) { $perc=$numpacketsent/$#recs*100; -if ($perc > $percsafe) +if ($perc > $percsafe) # dont believe safehosts are attacking! { $where=index($safehosts,$ipadd); @@ -326,7 +326,7 @@ if ($perc > $percsafe) } print "\n\n"; -} # end of subroutine toobusy_site +} # end of subroutine toobusy_site ############### END SUBROUTINE DECLARATIONS ########### @@ -339,7 +339,7 @@ if("$opt_t" eq "0") {usage;print "\n---->ERROR: You must psecify the IP address of the interface that collected the data!\n"; exit; } - + if("$opt_h" eq "1") {usage;exit 0}; if("$opt_H" eq "1") @@ -379,7 +379,7 @@ if("$opt_p" eq "") # -p arg must be all or AN INTEGER in range 1<=N<=64K if ("$opt_p" ne "all") { - $_=$opt_p; + $_=$opt_p; unless (/^[+-]?\d+$/) { usage; @@ -394,7 +394,7 @@ if ("$opt_p" ne "all") $lookat=$opt_p; # -o arg must be all or AN INTEGER in range 1<=N<=64K - $_=$opt_o; + $_=$opt_o; unless (/^[+-]?\d+$/) { usage; @@ -438,7 +438,7 @@ open (REC, $FILENAME) || die "Cant open $FILENAME: \n"; ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$junk)=stat REC; print "Log file $FILENAME is $size bytes in size\n"; #each record is an element of array rec[] now -while(<REC>) +while(<REC>) { @recs[$numrec++]=$_; } @@ -456,7 +456,7 @@ while ($loop++ < $#recs ) $bit=substr(@recs[$loop],39); $bit =~ s/,/ /g; ($sourceip,$junkit)= split " " , $bit ; - + # NOTE the . is the string concat command NOT + .......!!!! $sourceip =~ split " ", $sourceip; @@ -467,7 +467,7 @@ while ($loop++ < $#recs ) $allips = $allips . "$sourceip " ; } } - + print "Put all unique ip addresses into a 1D array\n"; @allips=split " ", $allips; @@ -490,7 +490,7 @@ while ($loop++ < $#recs ) { $a = $srcip . $icmp . $ptr . $destip . $icmp . $icmp . $lenst . $lenicmp ; } - + # dump the "->" and commas from logging $a =~ s/->//g; $a =~ s/PR//g; @@ -503,7 +503,7 @@ while ($loop++ < $#recs ) ($srcip,$junk) = split " ","$a"; $numpackets=$numpacks{"$srcip"}; $numpackets++ ; - $numpacks{"$srcip"}=$numpackets; + $numpacks{"$srcip"}=$numpackets; } @@ -546,7 +546,7 @@ while ($cnt++ < $#allips) while ($loop++ < $#recs ) { -# get src IP num, src port number, +# get src IP num, src port number, # destination IP num, destnation port number,protocol ($srcip,$srcport,$destip,$destport,$pro)= split " " , @shortrecs[$loop]; # loop over all records for the machine $uniqip @@ -564,7 +564,7 @@ while ($cnt++ < $#allips) { $srcportnam=$services{$srcport}; } -# try and get dest portname, if not there, leave it as the +# try and get dest portname, if not there, leave it as the # dest portnumber if ("$destport" eq "icmp") { $destportnam="icmp";} @@ -581,15 +581,15 @@ while ($cnt++ < $#allips) if ($srcportnam eq "") { # increment number of times a (high)/unknown port has gone to destport - $value1=$unknownsrcports{$destportnam}; - $value1++ ; + $value1=$unknownsrcports{$destportnam}; + $value1++ ; $unknownsrcports{$destportnam}=$value1; } else { # want tally(srcport) counter to be increased by 1 $value3=$tally{$srcportnam}; - $value3++ ; + $value3++ ; $tally{$srcportnam}=$value3; } } @@ -603,7 +603,7 @@ if ($set eq "N") $set="Y"; print "\n#### with $uniqip as the the source for packets ####\n"; -while(($key,$value)=each %tally) +while(($key,$value)=each %tally) { if (not "$uniqip" eq "$gatekeep") { @@ -617,7 +617,7 @@ while(($key,$value)=each %tally) -while(($key2,$value2)=each %unknownsrcports) +while(($key2,$value2)=each %unknownsrcports) { if (not "$uniqip" eq "$gatekeep") { @@ -632,7 +632,7 @@ while(($key2,$value2)=each %unknownsrcports) } # print if rests for UNIQIP IF flag is set to N then toggle flag -} # end of all IPs loop +} # end of all IPs loop } # end of if verbose option set block diff --git a/perl/Isbgraph b/perl/Isbgraph index c68b672322f02..8641099b608f8 100644 --- a/perl/Isbgraph +++ b/perl/Isbgraph @@ -67,7 +67,7 @@ close(CNF); # number datapoints/24 hours is 1440 (minutes) # # Split into N graphs where each graph has max of 240 datapoints (4 hours) -# +# $barset=0; $m=0; @@ -117,7 +117,7 @@ $teal=$im->colorAllocate(51,153,153); $xspace= $XINIT+$option{'XCELLGRIDSIZE'}*$i +$i; # $im->line($xspace,$YINIT,$xspace,$YGRAPH,gdStyled); $num = $i+1; - + use integer; { $posis=$num - ($num/60)*60; @@ -157,7 +157,7 @@ $nextdata="N"; $count=0; $i=0; $fname=$_; - + print "fname $fname\n"; # change entry for red in colour table to green for packets LEAVING target host @@ -180,14 +180,14 @@ $nextdata="N"; if($nextdata eq "Y") { - + #$im->line($XINIT,$YGRAPH,$X,$Y,$orange); $im->line($xspaceold,$yspaceold,$xspace,$yspace,$green); } else { $im->line($xspaceold,$yspaceold,$xspace,$yspace,$red); - } + } } else { @@ -214,7 +214,7 @@ $nextdata="N"; $im->line(500,60,530,60,$green); $im->string(gdSmallFont,535,35,"Packets IN",$fg); $im->string(gdSmallFont,535,55,"Packets OUT",$fg); - + if ($option{'Bar'} ne 0) { if ($X eq $option{'XMAX'}) @@ -237,7 +237,7 @@ $nextdata="N"; $nextdata="Y"; # TOP LEFT is 0,0 on GIF (image) -# origin of plot is xinit,yinit +# origin of plot is xinit,yinit # print "little line\n"; $im->line($xspace,$yspace,$xspace,$YGRAPH,$blue); $im->line($xspace,$YGRAPH,$XINIT,$YGRAPH,$blue); diff --git a/perl/Services b/perl/Services index 401fff00dd033..e9ae317367c94 100644 --- a/perl/Services +++ b/perl/Services @@ -89,7 +89,7 @@ 110 pop3 PostOfficeProtocol-Version3 111 sunrpc SUNRemoteProcedureCall 112 mcidas McIDASDataTransmissionProtocol -113 ident +113 ident 114 audionews AudioNewsMulticast 115 sftp SimpleFileTransferProtocol 116 ansanotify ANSAREXNotify @@ -426,7 +426,7 @@ 515 printer spooler 516 videotex videotex 517 talk liketenexlink,butacross -518 ntalk +518 ntalk 519 utime unixtime 520 route 521 ripng ripng @@ -451,7 +451,7 @@ 540 uucp uucpd 541 uucp-rlogin uucp-rlogin 542 commerce commerce -543 klogin +543 klogin 544 kshell krcmd 545 appleqtcsrvr appleqtcsrvr 546 dhcpv6-client DHCPv6Client @@ -463,7 +463,7 @@ 552 deviceshare deviceshare 553 pirp pirp 554 rtsp RealTimeStreamControlProtocol -555 dsf +555 dsf 556 remotefs rfsserver 557 openvms-sysipc openvms-sysipc 558 sdnskmp SDNSKMP @@ -542,7 +542,7 @@ 637 lanserver lanserver 638 mcns-sec mcns-sec 639 msdp MSDP -666 mdqs +666 mdqs 667 disclose campaigncontributiondisclosures-SDRTechnologies 668 mecomm MeComm 669 meregister MeRegister @@ -569,32 +569,32 @@ 748 ris-cm RussellInfoSciCalendarManager 749 kerberos-adm kerberosadministration 750 kerberos-iv kerberosversioniv -751 pump -752 qrh -753 rrh +751 pump +752 qrh +753 rrh 754 tell send -758 nlogin -759 con -760 ns -761 rxe -762 quotad -763 cycleserv -764 omserv -765 webster +758 nlogin +759 con +760 ns +761 rxe +762 quotad +763 cycleserv +764 omserv +765 webster 767 phonebook phone -769 vid -770 cadlock -771 rtip -772 cycleserv2 -773 notify -774 rpasswd -775 acmaint_transd -776 wpages -780 wpgs +769 vid +770 cadlock +771 rtip +772 cycleserv2 +773 notify +774 rpasswd +775 acmaint_transd +776 wpages +780 wpgs 786 concert Concert 787 qsc QSC -800 mdbs_daemon -801 device +800 mdbs_daemon +801 device 829 pkix-3-ca-ra PKIX-3CA/RA 873 rsync rsync 886 iclcnet-locate ICLcoNETionlocateserver @@ -610,10 +610,10 @@ 994 ircs ircprotocoloverTLS/SSL 995 pop3s pop3protocoloverTLS/SSL(wasspop3) 996 vsinet vsinet -997 maitrd -998 busboy -999 garcon -1000 cadlock +997 maitrd +998 busboy +999 garcon +1000 cadlock 1008 ufsd 1010 surf surf 1011 Reserved @@ -654,7 +654,7 @@ 1222 nerv SNIR&Dnetwork 1234 search-agent InfoseekSearchAgent 1239 nmsd NMSD -1248 hermes +1248 hermes 1300 h323hostcallsc H323HostCallSecure 1313 bmc_patroldb BMC_PATROLDB 1314 pdps PhotoscriptDistributedPrintingSystem @@ -695,7 +695,7 @@ 1379 dbreporter IntegritySolutions 1380 telesis-licman TelesisNetworkLicenseManager 1381 apple-licman AppleNetworkLicenseManager -1382 udt_os +1382 udt_os 1383 gwha GWHannawayNetworkLicenseManager 1384 os-licman ObjectiveSolutionsLicenseManager 1385 atex_elmd AtexPublishingLicenseManager @@ -913,7 +913,7 @@ 1597 orbplus-iiop orbplus-iiop 1598 picknfs picknfs 1599 simbaservices simbaservices -1600 issd +1600 issd 1601 aas aas 1602 inspect inspect 1603 picodbc pickodbc @@ -1079,7 +1079,7 @@ 1772 essweb-gw EssWebGateway 1773 kmscontrol KMSControl 1774 global-dtserv global-dtserv -1775 Unknown +1775 Unknown 1776 femis FederalEmergencyManagementInformationSystem 1777 powerguardian powerguardian 1778 prodigy-intrnet prodigy-internet @@ -1180,49 +1180,49 @@ 1997 gdp-port ciscoGatewayDiscoveryProtocol 1998 x25-svc-port ciscoX.25service(XOT) 1999 tcp-id-port ciscoidentificationport -2000 callbook -2001 dc -2002 globe -2004 mailbox -2005 berknet -2006 invokator -2007 dectalk -2008 conf -2009 news -2010 search +2000 callbook +2001 dc +2002 globe +2004 mailbox +2005 berknet +2006 invokator +2007 dectalk +2008 conf +2009 news +2010 search 2011 raid-cc raid -2012 ttyinfo -2013 raid-am -2014 troff -2015 cypress -2016 bootserver -2017 cypress-stat -2018 terminaldb -2019 whosockami -2020 xinupageserver -2021 servexec -2022 down -2023 xinuexpansion3 -2024 xinuexpansion4 -2025 ellpack -2026 scrabble -2027 shadowserver -2028 submitserver -2030 device2 -2032 blackboard -2033 glogger -2034 scoremgr -2035 imsldoc -2038 objectmanager -2040 lam -2041 interbase +2012 ttyinfo +2013 raid-am +2014 troff +2015 cypress +2016 bootserver +2017 cypress-stat +2018 terminaldb +2019 whosockami +2020 xinupageserver +2021 servexec +2022 down +2023 xinuexpansion3 +2024 xinuexpansion4 +2025 ellpack +2026 scrabble +2027 shadowserver +2028 submitserver +2030 device2 +2032 blackboard +2033 glogger +2034 scoremgr +2035 imsldoc +2038 objectmanager +2040 lam +2041 interbase 2042 isis isis 2043 isis-bcast isis-bcast -2044 rimsl -2045 cdfunc -2046 sdfunc -2047 dls -2048 dls-monitor +2044 rimsl +2045 cdfunc +2046 sdfunc +2047 dls +2048 dls-monitor 2049 nfsd-or-shilp 2065 dlsrpn DataLinkSwitchReadPortNumber 2067 dlswpn DataLinkSwitchWritePortNumber @@ -1798,8 +1798,8 @@ 4868 phrelay PhotonRelay 4869 phrelaydbg PhotonRelayDebug 4885 abbs ABBS -5000 commplex-main -5001 commplex-link +5000 commplex-main +5001 commplex-link 5002 rfe radiofreeethernet 5003 fmpro-internal FileMaker,Inc.-Proprietarynamebinding 5004 avt-profile-1 avt-profile-1 @@ -1812,13 +1812,13 @@ 5051 ita-agent ITAAgent 5052 ita-manager ITAManager 5060 sip SIP -5145 rmonitor_secure +5145 rmonitor_secure 5150 atmp AscendTunnelManagementProtocol 5190 aol America-Online 5191 aol-1 AmericaOnline1 5192 aol-2 AmericaOnline2 5193 aol-3 AmericaOnline3 -5236 padl2sim +5236 padl2sim 5272 pk PK 5300 hacl-hb #HAclusterheartbeat 5301 hacl-gs #HAclustergeneralservices @@ -1975,7 +1975,7 @@ 6506 badm_pub BoKSAdminPublicPort 6507 bdir_priv BoKSDirServer,PrivatePort 6508 bdir_pub BoKSDirServer,PublicPort -6558 xdsxdm +6558 xdsxdm 6665 ircu 6666 ircu 6667 ircu @@ -2059,7 +2059,7 @@ 9000 cslistener CSlistener 9006 sctp SCTP 9090 websm WebSM -9535 man +9535 man 9594 msgsys MessageSystem 9595 pds PingDiscoveryService 9876 sd SessionDirector @@ -2093,7 +2093,7 @@ 13821 dsmcc-download DSMCCDownloadProtocol 13822 dsmcc-ccp DSMCCChannelChangeProtocol 14001 itu-sccp-ss7 ITUSCCP(SS7) -17007 isode-dua +17007 isode-dua 17219 chipper Chipper 18000 biimenu BeckmanInstruments,Inc. 19541 jcp JCPClient diff --git a/perl/ipfmeta.pl b/perl/ipfmeta.pl index 1a7bb3f1a0e73..decc35b8bd23a 100644 --- a/perl/ipfmeta.pl +++ b/perl/ipfmeta.pl @@ -83,7 +83,7 @@ sub expand { return @retlines; } - + __END__ =head1 NAME @@ -164,7 +164,7 @@ block in from UNWANTED to any pass in from NOC to WEBSERVERS port = MGMT-PORTS pass out all - + I<Run> ipfmeta ipf.objs <ipf.metarules >ipf.rules diff --git a/perl/logfilter.pl b/perl/logfilter.pl index 6ebe401ab4ee0..fd0da6db181e7 100644 --- a/perl/logfilter.pl +++ b/perl/logfilter.pl @@ -3,7 +3,7 @@ # Author: Chris Grant # Copyright 1999, Codetalker Communications, Inc. # -# This script takes a firewall log and breaks it into several +# This script takes a firewall log and breaks it into several # different files. Each file is named based on the service that # runs on the port that was recognized in log line. After # this script has run, you should end up with several files. @@ -18,11 +18,11 @@ # # You may be wondering why I haven't simply parsed RFC1700 to come up # with a list of port numbers and files. The reason is that I don't -# believe reading firewall logs should be all that automated. You +# believe reading firewall logs should be all that automated. You # should be familiar with what probes are hitting your system. By -# manually adding entries to the data section this ensures that I -# have at least educated myself about what this protocol is, what -# the potential exposure is, and why you might be seeing this traffic. +# manually adding entries to the data section this ensures that I +# have at least educated myself about what this protocol is, what +# the potential exposure is, and why you might be seeing this traffic. %icmp = (); %udp = (); @@ -61,30 +61,30 @@ while($line = <LOGFILE>) { # determine the protocol - send to unknown.log if not found SWITCH: { - ($line =~ m /\sicmp\s/) && do { + ($line =~ m /\sicmp\s/) && do { # - # ICMP Protocol + # ICMP Protocol # # Extract the icmp packet information specifying the type. - # + # # Note: Must check for ICMP first because this may be an ICMP reply # to a TCP or UDP connection (eg Port Unreachable). - + ($icmptype) = $line =~ m/icmp (\d+)\/\d+/; $filename = $TIDBITSFILE; $filename = $icmp{$icmptype} if (defined($icmp{$icmptype})); - last SWITCH; + last SWITCH; }; - ($line =~ m /\stcp\s/) && do { + ($line =~ m /\stcp\s/) && do { - # + # # TCP Protocol # - # extract the source and destination ports and compare them to + # extract the source and destination ports and compare them to # known ports in the tcp hash. For the first match, place this # line in the file specified by the tcp hash. Ignore one of the # port matches if both ports happen to be known services. @@ -96,14 +96,14 @@ while($line = <LOGFILE>) { $filename = $tcp{$sport} if (defined($tcp{$sport})); $filename = $tcp{$dport} if (defined($tcp{$dport})); - last SWITCH; + last SWITCH; }; - ($line =~ m /\sudp\s/) && do { + ($line =~ m /\sudp\s/) && do { # # UDP Protocol - same procedure as with TCP, different hash - # + # ($sport, $dport) = $line =~ m/\d+\.\d+\.\d+\.\d+,(\d+) -> \d+\.\d+\.\d+\.\d+,(\d+)/; @@ -111,7 +111,7 @@ while($line = <LOGFILE>) { $filename = $udp{$sport} if (defined($udp{$sport})); $filename = $udp{$dport} if (defined($udp{$dport})); - last SWITCH; + last SWITCH; }; # @@ -126,7 +126,7 @@ while($line = <LOGFILE>) { # check for filename in the openfiles hash. if it exists then write # to the given handle. otherwise open a handle to the file and add # it to the hash of open files. - + if (defined($openfiles{$filename})) { $handle = $openfiles{$filename}; } else { @@ -178,4 +178,4 @@ tcp 6667 irc.log tcp 7070 realaudio.log tcp 8080 http.log tcp 12345 netbus.log -udp 31337 backorifice.log
\ No newline at end of file +udp 31337 backorifice.log diff --git a/printnat.c b/printnat.c deleted file mode 100644 index 5a12b32165bdb..0000000000000 --- a/printnat.c +++ /dev/null @@ -1,487 +0,0 @@ -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com) - */ -#if defined(__sgi) && (IRIX > 602) -# include <sys/ptimers.h> -#endif -#include <stdio.h> -#include <string.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/types.h> -#if !defined(__SVR4) && !defined(__svr4__) -#include <strings.h> -#else -#include <sys/byteorder.h> -#endif -#include <sys/time.h> -#include <sys/param.h> -#include <stdlib.h> -#include <unistd.h> -#include <stddef.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#if defined(sun) && (defined(__svr4__) || defined(__SVR4)) -# include <sys/ioccom.h> -# include <sys/sysmacros.h> -#endif -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/tcp.h> -#include <net/if.h> -#if __FreeBSD_version >= 300000 -# include <net/if_var.h> -#endif -#include <netdb.h> -#include <arpa/nameser.h> -#include <arpa/inet.h> -#include <resolv.h> -#include <ctype.h> -#include "netinet/ip_compat.h" -#include "netinet/ip_fil.h" -#include "netinet/ip_nat.h" -#include "netinet/ip_state.h" -#include "netinet/ip_proxy.h" -#include "ipf.h" -#include "kmem.h" - -#if defined(sun) && !SOLARIS2 -# define STRERROR(x) sys_errlist[x] -extern char *sys_errlist[]; -#else -# define STRERROR(x) strerror(x) -#endif - -#if !defined(lint) -static const char rcsid[] = "@(#)$Id: printnat.c,v 1.1.2.15 2003/03/22 15:31:49 darrenr Exp $"; -#endif - - -#if SOLARIS -#define bzero(a,b) memset(a,0,b) -#endif -#ifdef USE_INET6 -extern int use_inet6; -#endif - -extern char thishost[MAXHOSTNAMELEN]; - -extern int countbits __P((u_32_t)); - -void printnat __P((ipnat_t *, int)); -char *getnattype __P((ipnat_t *)); -void printactivenat __P((nat_t *, int)); -void printhostmap __P((hostmap_t *, u_int)); -char *getsumd __P((u_32_t)); - -static void printaps __P((ap_session_t *, int)); - -static void printaps(aps, opts) -ap_session_t *aps; -int opts; -{ - ipsec_pxy_t ipsec; - ap_session_t ap; - ftpinfo_t ftp; - aproxy_t apr; - raudio_t ra; - - if (kmemcpy((char *)&ap, (long)aps, sizeof(ap))) - return; - if (kmemcpy((char *)&apr, (long)ap.aps_apr, sizeof(apr))) - return; - printf("\tproxy %s/%d use %d flags %x\n", apr.apr_label, - apr.apr_p, apr.apr_ref, apr.apr_flags); - printf("\t\tproto %d flags %#x bytes ", ap.aps_p, ap.aps_flags); -#ifdef USE_QUAD_T - printf("%qu pkts %qu", (unsigned long long)ap.aps_bytes, - (unsigned long long)ap.aps_pkts); -#else - printf("%lu pkts %lu", ap.aps_bytes, ap.aps_pkts); -#endif - printf(" data %s size %d\n", ap.aps_data ? "YES" : "NO", ap.aps_psiz); - if ((ap.aps_p == IPPROTO_TCP) && (opts & OPT_VERBOSE)) { - printf("\t\tstate[%u,%u], sel[%d,%d]\n", - ap.aps_state[0], ap.aps_state[1], - ap.aps_sel[0], ap.aps_sel[1]); -#if (defined(NetBSD) && (NetBSD >= 199905) && (NetBSD < 1991011)) || \ - (__FreeBSD_version >= 300000) || defined(OpenBSD) - printf("\t\tseq: off %hd/%hd min %x/%x\n", - ap.aps_seqoff[0], ap.aps_seqoff[1], - ap.aps_seqmin[0], ap.aps_seqmin[1]); - printf("\t\tack: off %hd/%hd min %x/%x\n", - ap.aps_ackoff[0], ap.aps_ackoff[1], - ap.aps_ackmin[0], ap.aps_ackmin[1]); -#else - printf("\t\tseq: off %hd/%hd min %lx/%lx\n", - ap.aps_seqoff[0], ap.aps_seqoff[1], - ap.aps_seqmin[0], ap.aps_seqmin[1]); - printf("\t\tack: off %hd/%hd min %lx/%lx\n", - ap.aps_ackoff[0], ap.aps_ackoff[1], - ap.aps_ackmin[0], ap.aps_ackmin[1]); -#endif - } - - if (!strcmp(apr.apr_label, "raudio") && ap.aps_psiz == sizeof(ra)) { - if (kmemcpy((char *)&ra, (long)ap.aps_data, sizeof(ra))) - return; - printf("\tReal Audio Proxy:\n"); - printf("\t\tSeen PNA: %d\tVersion: %d\tEOS: %d\n", - ra.rap_seenpna, ra.rap_version, ra.rap_eos); - printf("\t\tMode: %#x\tSBF: %#x\n", ra.rap_mode, ra.rap_sbf); - printf("\t\tPorts:pl %hu, pr %hu, sr %hu\n", - ra.rap_plport, ra.rap_prport, ra.rap_srport); - } else if (!strcmp(apr.apr_label, "ftp") && - (ap.aps_psiz == sizeof(ftp))) { - if (kmemcpy((char *)&ftp, (long)ap.aps_data, sizeof(ftp))) - return; - printf("\tFTP Proxy:\n"); - printf("\t\tpassok: %d\n", ftp.ftp_passok); - ftp.ftp_side[0].ftps_buf[FTP_BUFSZ - 1] = '\0'; - ftp.ftp_side[1].ftps_buf[FTP_BUFSZ - 1] = '\0'; - printf("\tClient:\n"); - printf("\t\tseq %08x%08x len %d junk %d cmds %d\n", - ftp.ftp_side[0].ftps_seq[1], - ftp.ftp_side[0].ftps_seq[0], - ftp.ftp_side[0].ftps_len, - ftp.ftp_side[0].ftps_junk, ftp.ftp_side[0].ftps_cmds); - printf("\t\tbuf ["); - printbuf(ftp.ftp_side[0].ftps_buf, FTP_BUFSZ, 1); - printf("]\n\tServer:\n"); - printf("\t\tseq %08x%08x len %d junk %d cmds %d\n", - ftp.ftp_side[1].ftps_seq[1], - ftp.ftp_side[1].ftps_seq[0], - ftp.ftp_side[1].ftps_len, - ftp.ftp_side[1].ftps_junk, ftp.ftp_side[1].ftps_cmds); - printf("\t\tbuf ["); - printbuf(ftp.ftp_side[1].ftps_buf, FTP_BUFSZ, 1); - printf("]\n"); - } else if (!strcmp(apr.apr_label, "ipsec") && - (ap.aps_psiz == sizeof(ipsec))) { - if (kmemcpy((char *)&ipsec, (long)ap.aps_data, sizeof(ipsec))) - return; - printf("\tIPSec Proxy:\n"); - printf("\t\tICookie %08x%08x RCookie %08x%08x %s\n", - (u_int)ntohl(ipsec.ipsc_icookie[0]), - (u_int)ntohl(ipsec.ipsc_icookie[1]), - (u_int)ntohl(ipsec.ipsc_rcookie[0]), - (u_int)ntohl(ipsec.ipsc_rcookie[1]), - ipsec.ipsc_rckset ? "(Set)" : "(Not set)"); - } -} - - -/* - * Get a nat filter type given its kernel address. - */ -char *getnattype(ipnat) -ipnat_t *ipnat; -{ - static char unknownbuf[20]; - ipnat_t ipnatbuff; - char *which; - - if (!ipnat || (ipnat && kmemcpy((char *)&ipnatbuff, (long)ipnat, - sizeof(ipnatbuff)))) - return "???"; - - switch (ipnatbuff.in_redir) - { - case NAT_MAP : - which = "MAP"; - break; - case NAT_MAPBLK : - which = "MAP-BLOCK"; - break; - case NAT_REDIRECT : - which = "RDR"; - break; - case NAT_BIMAP : - which = "BIMAP"; - break; - default : - sprintf(unknownbuf, "unknown(%04x)", - ipnatbuff.in_redir & 0xffffffff); - which = unknownbuf; - break; - } - return which; -} - - -void printactivenat(nat, opts) -nat_t *nat; -int opts; -{ - u_int hv1, hv2; - - printf("%s %-15s", getnattype(nat->nat_ptr), inet_ntoa(nat->nat_inip)); - - if ((nat->nat_flags & IPN_TCPUDP) != 0) - printf(" %-5hu", ntohs(nat->nat_inport)); - - printf(" <- -> %-15s",inet_ntoa(nat->nat_outip)); - - if ((nat->nat_flags & IPN_TCPUDP) != 0) - printf(" %-5hu", ntohs(nat->nat_outport)); - - printf(" [%s", inet_ntoa(nat->nat_oip)); - if ((nat->nat_flags & IPN_TCPUDP) != 0) - printf(" %hu", ntohs(nat->nat_oport)); - printf("]"); - - if (opts & OPT_VERBOSE) { - printf("\n\tage %lu use %hu sumd %s/", - nat->nat_age, nat->nat_use, getsumd(nat->nat_sumd[0])); - hv1 = NAT_HASH_FN(nat->nat_inip.s_addr, nat->nat_inport, - 0xffffffff), - hv1 = NAT_HASH_FN(nat->nat_oip.s_addr, hv1 + nat->nat_oport, - NAT_TABLE_SZ), - hv2 = NAT_HASH_FN(nat->nat_outip.s_addr, nat->nat_outport, - 0xffffffff), - hv2 = NAT_HASH_FN(nat->nat_oip.s_addr, hv2 + nat->nat_oport, - NAT_TABLE_SZ), - printf("%s pr %u bkt %d/%d flags %x drop %d/%d\n", - getsumd(nat->nat_sumd[1]), nat->nat_p, - hv1, hv2, nat->nat_flags, - nat->nat_drop[0], nat->nat_drop[1]); - printf("\tifp %s ", getifname(nat->nat_ifp)); -#ifdef USE_QUAD_T - printf("bytes %qu pkts %qu", - (unsigned long long)nat->nat_bytes, - (unsigned long long)nat->nat_pkts); -#else - printf("bytes %lu pkts %lu", nat->nat_bytes, nat->nat_pkts); -#endif -#if SOLARIS - printf(" %lx", nat->nat_ipsumd); -#endif - } - - putchar('\n'); - if (nat->nat_aps) - printaps(nat->nat_aps, opts); -} - - -void printhostmap(hmp, hv) -hostmap_t *hmp; -u_int hv; -{ - printf("%s -> ", inet_ntoa(hmp->hm_realip)); - printf("%s ", inet_ntoa(hmp->hm_mapip)); - printf("(use = %d hv = %u)\n", hmp->hm_ref, hv); -} - - -char *getsumd(sum) -u_32_t sum; -{ - static char sumdbuf[17]; - - if (sum & NAT_HW_CKSUM) - sprintf(sumdbuf, "hw(%#0x)", sum & 0xffff); - else - sprintf(sumdbuf, "%#0x", sum); - return sumdbuf; -} - - -/* - * Print out a NAT rule - */ -void printnat(np, opts) -ipnat_t *np; -int opts; -{ - struct protoent *pr; - struct servent *sv; - int bits; - - pr = getprotobynumber(np->in_p); - - switch (np->in_redir) - { - case NAT_REDIRECT : - printf("rdr"); - break; - case NAT_MAP : - printf("map"); - break; - case NAT_MAPBLK : - printf("map-block"); - break; - case NAT_BIMAP : - printf("bimap"); - break; - default : - fprintf(stderr, "unknown value for in_redir: %#x\n", - np->in_redir); - break; - } - - printf(" %s ", np->in_ifname); - - if (np->in_flags & IPN_FILTER) { - if (np->in_flags & IPN_NOTSRC) - printf("! "); - printf("from "); - if (np->in_redir == NAT_REDIRECT) { - printhostmask(4, (u_32_t *)&np->in_srcip, - (u_32_t *)&np->in_srcmsk); - } else { - printhostmask(4, (u_32_t *)&np->in_inip, - (u_32_t *)&np->in_inmsk); - } - if (np->in_scmp) - printportcmp(np->in_p, &np->in_tuc.ftu_src); - - if (np->in_flags & IPN_NOTDST) - printf(" !"); - printf(" to "); - if (np->in_redir == NAT_REDIRECT) { - printhostmask(4, (u_32_t *)&np->in_outip, - (u_32_t *)&np->in_outmsk); - } else { - printhostmask(4, (u_32_t *)&np->in_srcip, - (u_32_t *)&np->in_srcmsk); - } - if (np->in_dcmp) - printportcmp(np->in_p, &np->in_tuc.ftu_dst); - } - - if (np->in_redir == NAT_REDIRECT) { - if (!(np->in_flags & IPN_FILTER)) { - printf("%s", inet_ntoa(np->in_out[0])); - bits = countbits(np->in_out[1].s_addr); - if (bits != -1) - printf("/%d ", bits); - else - printf("/%s ", inet_ntoa(np->in_out[1])); - printf("port %d", ntohs(np->in_pmin)); - if (np->in_pmax != np->in_pmin) - printf("- %d", ntohs(np->in_pmax)); - } - printf(" -> %s", inet_ntoa(np->in_in[0])); - if (np->in_flags & IPN_SPLIT) - printf(",%s", inet_ntoa(np->in_in[1])); - printf(" port %d", ntohs(np->in_pnext)); - if ((np->in_flags & IPN_TCPUDP) == IPN_TCPUDP) - printf(" tcp/udp"); - else if ((np->in_flags & IPN_TCP) == IPN_TCP) - printf(" tcp"); - else if ((np->in_flags & IPN_UDP) == IPN_UDP) - printf(" udp"); - else if (np->in_p == 0) - printf(" ip"); - else if (np->in_p != 0) { - if (pr != NULL) - printf(" %s", pr->p_name); - else - printf(" %d", np->in_p); - } - if (np->in_flags & IPN_ROUNDR) - printf(" round-robin"); - if (np->in_flags & IPN_FRAG) - printf(" frag"); - if (np->in_age[0]) - printf(" age %d/%d", np->in_age[0], np->in_age[1]); - if (np->in_mssclamp) - printf(" mssclamp %u", np->in_mssclamp); - printf("\n"); - if (opts & OPT_DEBUG) - printf("\tspc %lu flg %#x max %u use %d\n", - np->in_space, np->in_flags, - np->in_pmax, np->in_use); - } else { - if (!(np->in_flags & IPN_FILTER)) { - printf("%s/", inet_ntoa(np->in_in[0])); - bits = countbits(np->in_in[1].s_addr); - if (bits != -1) - printf("%d", bits); - else - printf("%s", inet_ntoa(np->in_in[1])); - } - printf(" -> "); - if (np->in_flags & IPN_IPRANGE) { - printf("range %s-", inet_ntoa(np->in_out[0])); - printf("%s", inet_ntoa(np->in_out[1])); - } else { - printf("%s/", inet_ntoa(np->in_out[0])); - bits = countbits(np->in_out[1].s_addr); - if (bits != -1) - printf("%d", bits); - else - printf("%s", inet_ntoa(np->in_out[1])); - } - if (*np->in_plabel) { - printf(" proxy port"); - if (np->in_dcmp != 0) - np->in_dport = htons(np->in_dport); - if (np->in_dport != 0) { - if (pr != NULL) - sv = getservbyport(np->in_dport, - pr->p_name); - else - sv = getservbyport(np->in_dport, NULL); - if (sv != NULL) - printf(" %s", sv->s_name); - else - printf(" %hu", ntohs(np->in_dport)); - } - printf(" %.*s/", (int)sizeof(np->in_plabel), - np->in_plabel); - if (pr != NULL) - fputs(pr->p_name, stdout); - else - printf("%d", np->in_p); - } else if (np->in_redir == NAT_MAPBLK) { - if ((np->in_pmin == 0) && - (np->in_flags & IPN_AUTOPORTMAP)) - printf(" ports auto"); - else - printf(" ports %d", np->in_pmin); - if (opts & OPT_DEBUG) - printf("\n\tip modulous %d", np->in_pmax); - } else if (np->in_pmin || np->in_pmax) { - printf(" portmap"); - if ((np->in_flags & IPN_TCPUDP) == IPN_TCPUDP) - printf(" tcp/udp"); - else if (np->in_flags & IPN_TCP) - printf(" tcp"); - else if (np->in_flags & IPN_UDP) - printf(" udp"); - if (np->in_flags & IPN_AUTOPORTMAP) { - printf(" auto"); - if (opts & OPT_DEBUG) - printf(" [%d:%d %d %d]", - ntohs(np->in_pmin), - ntohs(np->in_pmax), - np->in_ippip, np->in_ppip); - } else { - printf(" %d:%d", ntohs(np->in_pmin), - ntohs(np->in_pmax)); - } - } - if (np->in_flags & IPN_FRAG) - printf(" frag"); - if (np->in_age[0]) - printf(" age %d/%d", np->in_age[0], np->in_age[1]); - printf("\n"); - if (opts & OPT_DEBUG) { - struct in_addr nip; - - nip.s_addr = htonl(np->in_nextip.s_addr); - - printf("\tspace %lu nextip %s pnext %d", np->in_space, - inet_ntoa(nip), np->in_pnext); - printf(" flags %x use %u\n", - np->in_flags, np->in_use); - } - } -} diff --git a/printstate.c b/printstate.c deleted file mode 100644 index 624493b4686c3..0000000000000 --- a/printstate.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2002 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - */ -#if defined(__sgi) && (IRIX > 602) -# include <sys/ptimers.h> -#endif -#include <sys/types.h> -#include <sys/param.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netinet/in_systm.h> -#include <net/if.h> -#include <stdio.h> -#if __FreeBSD_version >= 300000 -# include <net/if_var.h> -#endif -#include "kmem.h" -#include "netinet/ip_compat.h" -#include "ipf.h" -#include "netinet/ip_fil.h" -#include "netinet/ip_state.h" - -#define PRINTF (void)printf -#define FPRINTF (void)fprintf - -ipstate_t *printstate(sp, opts) -ipstate_t *sp; -int opts; -{ - ipstate_t ips; - - if (kmemcpy((char *)&ips, (u_long)sp, sizeof(ips))) - return NULL; - - PRINTF("%s -> ", hostname(ips.is_v, &ips.is_src.in4)); - PRINTF("%s ttl %ld pass %#x pr %d state %d/%d\n", - hostname(ips.is_v, &ips.is_dst.in4), - ips.is_age, ips.is_pass, ips.is_p, - ips.is_state[0], ips.is_state[1]); -#ifdef USE_QUAD_T - PRINTF("\tpkts %qu bytes %qu", (unsigned long long) ips.is_pkts, - (unsigned long long) ips.is_bytes); -#else - PRINTF("\tpkts %ld bytes %ld", ips.is_pkts, ips.is_bytes); -#endif - if (ips.is_p == IPPROTO_TCP) { -#if defined(NetBSD) && (NetBSD >= 199905) && (NetBSD < 1991011) || \ -(__FreeBSD_version >= 220000) || defined(__OpenBSD__) - PRINTF("\t%hu -> %hu %x:%x (max %x:%x)\n", - ntohs(ips.is_sport), ntohs(ips.is_dport), - ips.is_send, ips.is_dend, - ips.is_maxsend, ips.is_maxdend); - PRINTF("\t%u<<%d:%u<<%d", - ips.is_maxswin>>ips.is_swscale, ips.is_swscale, - ips.is_maxdwin>>ips.is_dwscale, ips.is_dwscale); -#else - PRINTF("\t%hu -> %hu %x:%x (max %x:%x)\n", - ntohs(ips.is_sport), ntohs(ips.is_dport), - ips.is_send, ips.is_dend, - ips.is_maxsend, ips.is_maxdend); - PRINTF("\t%u<<%d:%u<<%d", - ips.is_maxswin>>ips.is_swscale, ips.is_swscale, - ips.is_maxdwin>>ips.is_dwscale, ips.is_dwscale); -#endif - } else if (ips.is_p == IPPROTO_UDP) - PRINTF(" %hu -> %hu", ntohs(ips.is_sport), - ntohs(ips.is_dport)); - else if (ips.is_p == IPPROTO_ICMP -#ifdef USE_INET6 - || ips.is_p == IPPROTO_ICMPV6 -#endif - ) - PRINTF(" id %hu seq %hu type %d", ntohs(ips.is_icmp.ics_id), - ntohs(ips.is_icmp.ics_seq), ips.is_icmp.ics_type); - - PRINTF("\n\t"); - - /* - * Print out bits set in the result code for the state being - * kept as they would for a rule. - */ - if (ips.is_pass & FR_PASS) { - PRINTF("pass"); - } else if (ips.is_pass & FR_BLOCK) { - PRINTF("block"); - switch (ips.is_pass & FR_RETMASK) - { - case FR_RETICMP : - PRINTF(" return-icmp"); - break; - case FR_FAKEICMP : - PRINTF(" return-icmp-as-dest"); - break; - case FR_RETRST : - PRINTF(" return-rst"); - break; - default : - break; - } - } else if ((ips.is_pass & FR_LOGMASK) == FR_LOG) { - PRINTF("log"); - if (ips.is_pass & FR_LOGBODY) - PRINTF(" body"); - if (ips.is_pass & FR_LOGFIRST) - PRINTF(" first"); - } else if (ips.is_pass & FR_ACCOUNT) - PRINTF("count"); - - if (ips.is_pass & FR_OUTQUE) - PRINTF(" out"); - else - PRINTF(" in"); - - if ((ips.is_pass & FR_LOG) != 0) { - PRINTF(" log"); - if (ips.is_pass & FR_LOGBODY) - PRINTF(" body"); - if (ips.is_pass & FR_LOGFIRST) - PRINTF(" first"); - if (ips.is_pass & FR_LOGORBLOCK) - PRINTF(" or-block"); - } - if (ips.is_pass & FR_QUICK) - PRINTF(" quick"); - if (ips.is_pass & FR_KEEPFRAG) - PRINTF(" keep frags"); - /* a given; no? */ - if (ips.is_pass & FR_KEEPSTATE) - PRINTF(" keep state"); - PRINTF("\tIPv%d", ips.is_v); - PRINTF("\n"); - - PRINTF("\tpkt_flags & %x(%x) = %x,\t", - ips.is_flags & 0xf, ips.is_flags, - ips.is_flags >> 4); - PRINTF("\tpkt_options & %x = %x\n", ips.is_optmsk, - ips.is_opt); - PRINTF("\tpkt_security & %x = %x, pkt_auth & %x = %x\n", - ips.is_secmsk, ips.is_sec, ips.is_authmsk, - ips.is_auth); - PRINTF("\tinterfaces: in %s", getifname(ips.is_ifp[0])); - PRINTF(",%s", getifname(ips.is_ifp[1])); - PRINTF(" out %s", getifname(ips.is_ifp[2])); - PRINTF(",%s\n", getifname(ips.is_ifp[3])); - - return ips.is_next; -} diff --git a/radix.c b/radix.c deleted file mode 100644 index f9fc20cc3e18a..0000000000000 --- a/radix.c +++ /dev/null @@ -1,1212 +0,0 @@ -/* - * Copyright (c) 1988, 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)radix.c 8.6 (Berkeley) 10/17/95 - */ - -/* - * Routines to build and maintain radix trees for routing lookups. - */ -#if defined(KERNEL) || defined(_KERNEL) -# undef KERNEL -# undef _KERNEL -# define KERNEL 1 -# define _KERNEL 1 -#endif -#define __SYS_ATOMIC_OPS_H__ -#if !defined(__svr4__) && !defined(__SVR4) && !defined(__osf__) && \ - !defined(__hpux) && !defined(__sgi) -#include <sys/cdefs.h> -#endif -#ifndef __P -# ifdef __STDC__ -# define __P(x) x -# else -# define __P(x) () -# endif -#endif -#ifdef __osf__ -# define CONST -# define _IPV6_SWTAB_H -# define _PROTO_NET_H_ -# define _PROTO_IPV6_H -# include <sys/malloc.h> -#endif - -#include <sys/param.h> -#ifdef _KERNEL -#include <sys/systm.h> -#else -void panic __P((char *str)); -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <string.h> -#endif -#ifdef __hpux -#include <syslog.h> -#else -#include <sys/syslog.h> -#endif -#include <sys/time.h> -#include <netinet/in.h> -#include <sys/socket.h> -#include <net/if.h> -#ifdef SOLARIS2 -# define _RADIX_H_ -#endif -#include "netinet/ip_compat.h" -#include "netinet/ip_fil.h" -#ifdef SOLARIS2 -# undef _RADIX_H_ -#endif -/* END OF INCLUDES */ -#include "radix_ipf.h" -#ifndef min -# define min MIN -#endif -#ifndef max -# define max MAX -#endif - -int max_keylen = 16; -static struct radix_mask *rn_mkfreelist; -static struct radix_node_head *mask_rnhead; -static char *addmask_key; -static u_char normal_chars[] = {0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; -static char *rn_zeros = NULL, *rn_ones = NULL; - -#define rn_masktop (mask_rnhead->rnh_treetop) -#undef Bcmp -#define Bcmp(a, b, l) (l == 0 ? 0 : bcmp((caddr_t)(a), (caddr_t)(b), (u_long)l)) - -static int rn_satisfies_leaf __P((char *, struct radix_node *, int)); -static int rn_lexobetter __P((void *, void *)); -static struct radix_mask *rn_new_radix_mask __P((struct radix_node *, - struct radix_mask *)); -static int rn_freenode __P((struct radix_node *, void *)); -#if defined(AIX) && !defined(_KERNEL) -struct radix_node *rn_match __P((void *, struct radix_node_head *)); -struct radix_node *rn_addmask __P((int, int, void *)); -#define FreeS(x, y) KFREES(x, y) -#define Bcopy(x, y, z) bcopy(x, y, z) -#endif - -/* - * The data structure for the keys is a radix tree with one way - * branching removed. The index rn_b at an internal node n represents a bit - * position to be tested. The tree is arranged so that all descendants - * of a node n have keys whose bits all agree up to position rn_b - 1. - * (We say the index of n is rn_b.) - * - * There is at least one descendant which has a one bit at position rn_b, - * and at least one with a zero there. - * - * A route is determined by a pair of key and mask. We require that the - * bit-wise logical and of the key and mask to be the key. - * We define the index of a route to associated with the mask to be - * the first bit number in the mask where 0 occurs (with bit number 0 - * representing the highest order bit). - * - * We say a mask is normal if every bit is 0, past the index of the mask. - * If a node n has a descendant (k, m) with index(m) == index(n) == rn_b, - * and m is a normal mask, then the route applies to every descendant of n. - * If the index(m) < rn_b, this implies the trailing last few bits of k - * before bit b are all 0, (and hence consequently true of every descendant - * of n), so the route applies to all descendants of the node as well. - * - * Similar logic shows that a non-normal mask m such that - * index(m) <= index(n) could potentially apply to many children of n. - * Thus, for each non-host route, we attach its mask to a list at an internal - * node as high in the tree as we can go. - * - * The present version of the code makes use of normal routes in short- - * circuiting an explicit mask and compare operation when testing whether - * a key satisfies a normal route, and also in remembering the unique leaf - * that governs a subtree. - */ - -struct radix_node * -rn_search(v_arg, head) - void *v_arg; - struct radix_node *head; -{ - struct radix_node *x; - caddr_t v; - - for (x = head, v = v_arg; x->rn_b >= 0;) { - if (x->rn_bmask & v[x->rn_off]) - x = x->rn_r; - else - x = x->rn_l; - } - return (x); -} - -struct radix_node * -rn_search_m(v_arg, head, m_arg) - struct radix_node *head; - void *v_arg, *m_arg; -{ - struct radix_node *x; - caddr_t v = v_arg, m = m_arg; - - for (x = head; x->rn_b >= 0;) { - if ((x->rn_bmask & m[x->rn_off]) && - (x->rn_bmask & v[x->rn_off])) - x = x->rn_r; - else - x = x->rn_l; - } - return x; -} - -int -rn_refines(m_arg, n_arg) - void *m_arg, *n_arg; -{ - caddr_t m = m_arg, n = n_arg; - caddr_t lim, lim2 = lim = n + *(u_char *)n; - int longer = (*(u_char *)n++) - (int)(*(u_char *)m++); - int masks_are_equal = 1; - - if (longer > 0) - lim -= longer; - while (n < lim) { - if (*n & ~(*m)) - return 0; - if (*n++ != *m++) - masks_are_equal = 0; - } - while (n < lim2) - if (*n++) - return 0; - if (masks_are_equal && (longer < 0)) - for (lim2 = m - longer; m < lim2; ) - if (*m++) - return 1; - return (!masks_are_equal); -} - -struct radix_node * -rn_lookup(v_arg, m_arg, head) - void *v_arg, *m_arg; - struct radix_node_head *head; -{ - struct radix_node *x; - caddr_t netmask = 0; - - if (m_arg) { - if ((x = rn_addmask(m_arg, 1, head->rnh_treetop->rn_off)) == 0) - return (0); - netmask = x->rn_key; - } - x = rn_match(v_arg, head); - if (x && netmask) { - while (x && x->rn_mask != netmask) - x = x->rn_dupedkey; - } - return x; -} - -static int -rn_satisfies_leaf(trial, leaf, skip) - char *trial; - struct radix_node *leaf; - int skip; -{ - char *cp = trial, *cp2 = leaf->rn_key, *cp3 = leaf->rn_mask; - char *cplim; - int length = min(*(u_char *)cp, *(u_char *)cp2); - - if (cp3 == 0) - cp3 = rn_ones; - else - length = min(length, *(u_char *)cp3); - cplim = cp + length; - cp3 += skip; - cp2 += skip; - for (cp += skip; cp < cplim; cp++, cp2++, cp3++) - if ((*cp ^ *cp2) & *cp3) - return 0; - return 1; -} - -struct radix_node * -rn_match(v_arg, head) - void *v_arg; - struct radix_node_head *head; -{ - caddr_t v = v_arg; - struct radix_node *t = head->rnh_treetop, *x; - caddr_t cp = v, cp2; - caddr_t cplim; - struct radix_node *saved_t, *top = t; - int off = t->rn_off, vlen = *(u_char *)cp, matched_off; - int test, b, rn_b; - - /* - * Open code rn_search(v, top) to avoid overhead of extra - * subroutine call. - */ - for (; t->rn_b >= 0; ) { - if (t->rn_bmask & cp[t->rn_off]) - t = t->rn_r; - else - t = t->rn_l; - } - /* - * See if we match exactly as a host destination - * or at least learn how many bits match, for normal mask finesse. - * - * It doesn't hurt us to limit how many bytes to check - * to the length of the mask, since if it matches we had a genuine - * match and the leaf we have is the most specific one anyway; - * if it didn't match with a shorter length it would fail - * with a long one. This wins big for class B&C netmasks which - * are probably the most common case... - */ - if (t->rn_mask) - vlen = *(u_char *)t->rn_mask; - cp += off; - cp2 = t->rn_key + off; - cplim = v + vlen; - for (; cp < cplim; cp++, cp2++) - if (*cp != *cp2) - goto on1; - /* - * This extra grot is in case we are explicitly asked - * to look up the default. Ugh! - */ - if ((t->rn_flags & RNF_ROOT) && t->rn_dupedkey) - t = t->rn_dupedkey; - return t; -on1: - test = (*cp ^ *cp2) & 0xff; /* find first bit that differs */ - for (b = 7; (test >>= 1) > 0;) - b--; - matched_off = cp - v; - b += matched_off << 3; - rn_b = -1 - b; - /* - * If there is a host route in a duped-key chain, it will be first. - */ - if ((saved_t = t)->rn_mask == 0) - t = t->rn_dupedkey; - for (; t; t = t->rn_dupedkey) - /* - * Even if we don't match exactly as a host, - * we may match if the leaf we wound up at is - * a route to a net. - */ - if (t->rn_flags & RNF_NORMAL) { - if (rn_b <= t->rn_b) - return t; - } else if (rn_satisfies_leaf(v, t, matched_off)) - return t; - t = saved_t; - /* start searching up the tree */ - do { - struct radix_mask *m; - t = t->rn_p; - m = t->rn_mklist; - if (m) { - /* - * If non-contiguous masks ever become important - * we can restore the masking and open coding of - * the search and satisfaction test and put the - * calculation of "off" back before the "do". - */ - do { - if (m->rm_flags & RNF_NORMAL) { - if (rn_b <= m->rm_b) - return (m->rm_leaf); - } else { - off = min(t->rn_off, matched_off); - x = rn_search_m(v, t, m->rm_mask); - while (x && x->rn_mask != m->rm_mask) - x = x->rn_dupedkey; - if (x && rn_satisfies_leaf(v, x, off)) - return x; - } - m = m->rm_mklist; - } while (m); - } - } while (t != top); - return 0; -} - -#ifdef RN_DEBUG -int rn_nodenum; -struct radix_node *rn_clist; -int rn_saveinfo; -int rn_debug = 1; -#endif - -struct radix_node * -rn_newpair(v, b, nodes) - void *v; - int b; - struct radix_node nodes[2]; -{ - struct radix_node *tt = nodes, *t = tt + 1; - t->rn_b = b; - t->rn_bmask = 0x80 >> (b & 7); - t->rn_l = tt; - t->rn_off = b >> 3; - tt->rn_b = -1; - tt->rn_key = (caddr_t)v; - tt->rn_p = t; - tt->rn_flags = t->rn_flags = RNF_ACTIVE; -#ifdef RN_DEBUG - tt->rn_info = rn_nodenum++; - t->rn_info = rn_nodenum++; - tt->rn_twin = t; - tt->rn_ybro = rn_clist; - rn_clist = tt; -#endif - return t; -} - -struct radix_node * -rn_insert(v_arg, head, dupentry, nodes) - void *v_arg; - struct radix_node_head *head; - int *dupentry; - struct radix_node nodes[2]; -{ - caddr_t v = v_arg; - struct radix_node *top = head->rnh_treetop; - int head_off = top->rn_off, vlen = (int)*((u_char *)v); - struct radix_node *t = rn_search(v_arg, top); - caddr_t cp = v + head_off; - int b; - struct radix_node *tt; - -#ifdef RN_DEBUG - if (rn_debug) - log(LOG_DEBUG, "rn_insert(%p,%p,%p,%p)\n", v_arg, head, dupentry, nodes); -#endif - /* - * Find first bit at which v and t->rn_key differ - */ - { - caddr_t cp2 = t->rn_key + head_off; - int cmp_res; - caddr_t cplim = v + vlen; - - while (cp < cplim) - if (*cp2++ != *cp++) - goto on1; - *dupentry = 1; - return t; -on1: - *dupentry = 0; - cmp_res = (cp[-1] ^ cp2[-1]) & 0xff; - for (b = (cp - v) << 3; cmp_res; b--) - cmp_res >>= 1; - } - { - struct radix_node *p, *x = top; - cp = v; - do { - p = x; - if (cp[x->rn_off] & x->rn_bmask) - x = x->rn_r; - else - x = x->rn_l; - } while (b > (unsigned) x->rn_b); /* x->rn_b < b && x->rn_b >= 0 */ -#ifdef RN_DEBUG - if (rn_debug) - log(LOG_DEBUG, "rn_insert: Going In:\n"); // traverse(p); -#endif - t = rn_newpair(v_arg, b, nodes); - tt = t->rn_l; - if ((cp[p->rn_off] & p->rn_bmask) == 0) - p->rn_l = t; - else - p->rn_r = t; - x->rn_p = t; - t->rn_p = p; /* frees x, p as temp vars below */ - if ((cp[t->rn_off] & t->rn_bmask) == 0) { - t->rn_r = x; - } else { - t->rn_r = tt; - t->rn_l = x; - } -#ifdef RN_DEBUG - if (rn_debug) - log(LOG_DEBUG, "rn_insert: Coming Out:\n"); // traverse(p); -#endif - } - return (tt); -} - -struct radix_node * -rn_addmask(n_arg, search, skip) - int search, skip; - void *n_arg; -{ - caddr_t netmask = (caddr_t)n_arg; - struct radix_node *x; - caddr_t cp, cplim; - int b = 0, mlen, j; - int maskduplicated, m0, isnormal; - struct radix_node *saved_x; - static int last_zeroed = 0; - -#ifdef RN_DEBUG - if (rn_debug) - log(LOG_DEBUG, "rn_addmask(%p,%d,%d)\n", n_arg, search, skip); -#endif - mlen = *(u_char *)netmask; - if ((mlen = *(u_char *)netmask) > max_keylen) - mlen = max_keylen; - if (skip == 0) - skip = 1; - if (mlen <= skip) - return (mask_rnhead->rnh_nodes); - if (skip > 1) - Bcopy(rn_ones + 1, addmask_key + 1, skip - 1); - if ((m0 = mlen) > skip) - Bcopy(netmask + skip, addmask_key + skip, mlen - skip); - /* - * Trim trailing zeroes. - */ - for (cp = addmask_key + mlen; (cp > addmask_key) && cp[-1] == 0;) - cp--; - mlen = cp - addmask_key; - if (mlen <= skip) { - if (m0 >= last_zeroed) - last_zeroed = mlen; - return (mask_rnhead->rnh_nodes); - } - if (m0 < last_zeroed) - Bzero(addmask_key + m0, last_zeroed - m0); - *addmask_key = last_zeroed = mlen; - x = rn_search(addmask_key, rn_masktop); - if (Bcmp(addmask_key, x->rn_key, mlen) != 0) - x = 0; - if (x || search) - return (x); - R_Malloc(x, struct radix_node *, max_keylen + 2 * sizeof (*x)); - if ((saved_x = x) == 0) - return (0); - Bzero(x, max_keylen + 2 * sizeof (*x)); - netmask = cp = (caddr_t)(x + 2); - Bcopy(addmask_key, cp, mlen); - x = rn_insert(cp, mask_rnhead, &maskduplicated, x); - if (maskduplicated) { -#if 0 - log(LOG_ERR, "rn_addmask: mask impossibly already in tree\n"); -#endif - Free(saved_x); - return (x); - } - /* - * Calculate index of mask, and check for normalcy. - */ - cplim = netmask + mlen; - isnormal = 1; - for (cp = netmask + skip; (cp < cplim) && *(u_char *)cp == 0xff;) - cp++; - if (cp != cplim) { - for (j = 0x80; (j & *cp) != 0; j >>= 1) - b++; - if (*cp != normal_chars[b] || cp != (cplim - 1)) - isnormal = 0; - } - b += (cp - netmask) << 3; - x->rn_b = -1 - b; - if (isnormal) - x->rn_flags |= RNF_NORMAL; - return (x); -} - -static int /* XXX: arbitrary ordering for non-contiguous masks */ -rn_lexobetter(m_arg, n_arg) - void *m_arg, *n_arg; -{ - u_char *mp = m_arg, *np = n_arg, *lim; - - if (*mp > *np) - return 1; /* not really, but need to check longer one first */ - if (*mp == *np) - for (lim = mp + *mp; mp < lim;) - if (*mp++ > *np++) - return 1; - return 0; -} - -static struct radix_mask * -rn_new_radix_mask(tt, next) - struct radix_node *tt; - struct radix_mask *next; -{ - struct radix_mask *m; - - MKGet(m); - if (m == 0) { -#if 0 - log(LOG_ERR, "Mask for route not entered\n"); -#endif - return (0); - } - Bzero(m, sizeof *m); - m->rm_b = tt->rn_b; - m->rm_flags = tt->rn_flags; - if (tt->rn_flags & RNF_NORMAL) - m->rm_leaf = tt; - else - m->rm_mask = tt->rn_mask; - m->rm_mklist = next; - tt->rn_mklist = m; - return m; -} - -struct radix_node * -rn_addroute(v_arg, n_arg, head, treenodes) - void *v_arg, *n_arg; - struct radix_node_head *head; - struct radix_node treenodes[2]; -{ - caddr_t v = (caddr_t)v_arg, netmask = (caddr_t)n_arg; - struct radix_node *t, *x = NULL, *tt; - struct radix_node *saved_tt, *top = head->rnh_treetop; - short b = 0, b_leaf = 0; - int keyduplicated; - caddr_t mmask; - struct radix_mask *m, **mp; - -#ifdef RN_DEBUG - if (rn_debug) - log(LOG_DEBUG, "rn_addroute(%p,%p,%p,%p)\n", v_arg, n_arg, head, treenodes); -#endif - /* - * In dealing with non-contiguous masks, there may be - * many different routes which have the same mask. - * We will find it useful to have a unique pointer to - * the mask to speed avoiding duplicate references at - * nodes and possibly save time in calculating indices. - */ - if (netmask) { - if ((x = rn_addmask(netmask, 0, top->rn_off)) == 0) - return (0); - b_leaf = x->rn_b; - b = -1 - x->rn_b; - netmask = x->rn_key; - } - /* - * Deal with duplicated keys: attach node to previous instance - */ - saved_tt = tt = rn_insert(v, head, &keyduplicated, treenodes); - if (keyduplicated) { - for (t = tt; tt; t = tt, tt = tt->rn_dupedkey) { - if (tt->rn_mask == netmask) - return (0); - if (netmask == 0 || - (tt->rn_mask && - ((b_leaf < tt->rn_b) || /* index(netmask) > node */ - rn_refines(netmask, tt->rn_mask) || - rn_lexobetter(netmask, tt->rn_mask)))) - break; - } - /* - * If the mask is not duplicated, we wouldn't - * find it among possible duplicate key entries - * anyway, so the above test doesn't hurt. - * - * We sort the masks for a duplicated key the same way as - * in a masklist -- most specific to least specific. - * This may require the unfortunate nuisance of relocating - * the head of the list. - * - * We also reverse, or doubly link the list through the - * parent pointer. - */ - if (tt == saved_tt) { - struct radix_node *xx = x; - /* link in at head of list */ - (tt = treenodes)->rn_dupedkey = t; - tt->rn_flags = t->rn_flags; - tt->rn_p = x = t->rn_p; - t->rn_p = tt; - if (x->rn_l == t) - x->rn_l = tt; - else - x->rn_r = tt; - saved_tt = tt; - x = xx; - } else { - (tt = treenodes)->rn_dupedkey = t->rn_dupedkey; - t->rn_dupedkey = tt; - tt->rn_p = t; - if (tt->rn_dupedkey) - tt->rn_dupedkey->rn_p = tt; - } -#ifdef RN_DEBUG - t=tt+1; - tt->rn_info = rn_nodenum++; - t->rn_info = rn_nodenum++; - tt->rn_twin = t; - tt->rn_ybro = rn_clist; - rn_clist = tt; -#endif - tt->rn_key = (caddr_t) v; - tt->rn_b = -1; - tt->rn_flags = RNF_ACTIVE; - } - /* - * Put mask in tree. - */ - if (netmask) { - tt->rn_mask = netmask; - tt->rn_b = x->rn_b; - tt->rn_flags |= x->rn_flags & RNF_NORMAL; - } - t = saved_tt->rn_p; - if (keyduplicated) - goto on2; - b_leaf = -1 - t->rn_b; - if (t->rn_r == saved_tt) - x = t->rn_l; - else - x = t->rn_r; - /* Promote general routes from below */ - if (x->rn_b < 0) { - for (mp = &t->rn_mklist; x; x = x->rn_dupedkey) - if (x->rn_mask && (x->rn_b >= b_leaf) && x->rn_mklist == 0) { - *mp = m = rn_new_radix_mask(x, 0); - if (m) - mp = &m->rm_mklist; - } - } else if (x->rn_mklist) { - /* - * Skip over masks whose index is > that of new node - */ - for (mp = &x->rn_mklist; (m = *mp) != NULL; mp = &m->rm_mklist) - if (m->rm_b >= b_leaf) - break; - t->rn_mklist = m; - *mp = 0; - } -on2: - /* Add new route to highest possible ancestor's list */ - if ((netmask == 0) || (b > t->rn_b )) - return tt; /* can't lift at all */ - b_leaf = tt->rn_b; - do { - x = t; - t = t->rn_p; - } while (b <= t->rn_b && x != top); - /* - * Search through routes associated with node to - * insert new route according to index. - * Need same criteria as when sorting dupedkeys to avoid - * double loop on deletion. - */ - for (mp = &x->rn_mklist; (m = *mp) != NULL; mp = &m->rm_mklist) { - if (m->rm_b < b_leaf) - continue; - if (m->rm_b > b_leaf) - break; - if (m->rm_flags & RNF_NORMAL) { - mmask = m->rm_leaf->rn_mask; - if (tt->rn_flags & RNF_NORMAL) { -#if 0 - log(LOG_ERR, "Non-unique normal route," - " mask not entered\n"); -#endif - return tt; - } - } else - mmask = m->rm_mask; - if (mmask == netmask) { - m->rm_refs++; - tt->rn_mklist = m; - return tt; - } - if (rn_refines(netmask, mmask) - || rn_lexobetter(netmask, mmask)) - break; - } - *mp = rn_new_radix_mask(tt, *mp); - return tt; -} - -struct radix_node * -rn_delete(v_arg, netmask_arg, head) - void *v_arg, *netmask_arg; - struct radix_node_head *head; -{ - struct radix_node *t, *p, *x, *tt; - struct radix_mask *m, *saved_m, **mp; - struct radix_node *dupedkey, *saved_tt, *top; - caddr_t v, netmask; - int b, head_off, vlen; - - v = v_arg; - netmask = netmask_arg; - x = head->rnh_treetop; - tt = rn_search(v, x); - head_off = x->rn_off; - vlen = *(u_char *)v; - saved_tt = tt; - top = x; - if (tt == 0 || - Bcmp(v + head_off, tt->rn_key + head_off, vlen - head_off)) - return (0); - /* - * Delete our route from mask lists. - */ - if (netmask) { - if ((x = rn_addmask(netmask, 1, head_off)) == 0) - return (0); - netmask = x->rn_key; - while (tt->rn_mask != netmask) - if ((tt = tt->rn_dupedkey) == 0) - return (0); - } - if (tt->rn_mask == 0 || (saved_m = m = tt->rn_mklist) == 0) - goto on1; - if (tt->rn_flags & RNF_NORMAL) { - if (m->rm_leaf != tt || m->rm_refs > 0) { -#if 0 - log(LOG_ERR, "rn_delete: inconsistent annotation\n"); -#endif - return 0; /* dangling ref could cause disaster */ - } - } else { - if (m->rm_mask != tt->rn_mask) { -#if 0 - log(LOG_ERR, "rn_delete: inconsistent annotation\n"); -#endif - goto on1; - } - if (--m->rm_refs >= 0) - goto on1; - } - b = -1 - tt->rn_b; - t = saved_tt->rn_p; - if (b > t->rn_b) - goto on1; /* Wasn't lifted at all */ - do { - x = t; - t = t->rn_p; - } while (b <= t->rn_b && x != top); - for (mp = &x->rn_mklist; (m = *mp) != NULL; mp = &m->rm_mklist) - if (m == saved_m) { - *mp = m->rm_mklist; - MKFree(m); - break; - } - if (m == 0) { -#if 0 - log(LOG_ERR, "rn_delete: couldn't find our annotation\n"); -#endif - if (tt->rn_flags & RNF_NORMAL) - return (0); /* Dangling ref to us */ - } -on1: - /* - * Eliminate us from tree - */ - if (tt->rn_flags & RNF_ROOT) - return (0); -#ifdef RN_DEBUG - /* Get us out of the creation list */ - for (t = rn_clist; t && t->rn_ybro != tt; t = t->rn_ybro) - ; - if (t) t->rn_ybro = tt->rn_ybro; -#endif - t = tt->rn_p; - dupedkey = saved_tt->rn_dupedkey; - if (dupedkey) { - /* - * Here, tt is the deletion target and - * saved_tt is the head of the dupedkey chain. - */ - if (tt == saved_tt) { - x = dupedkey; - x->rn_p = t; - if (t->rn_l == tt) - t->rn_l = x; - else - t->rn_r = x; - } else { - /* find node in front of tt on the chain */ - for (x = p = saved_tt; p && p->rn_dupedkey != tt;) - p = p->rn_dupedkey; - if (p) { - p->rn_dupedkey = tt->rn_dupedkey; - if (tt->rn_dupedkey) - tt->rn_dupedkey->rn_p = p; - } -#if 0 - else - log(LOG_ERR, "rn_delete: couldn't find us\n"); -#endif - } - t = tt + 1; - if (t->rn_flags & RNF_ACTIVE) { -#ifndef RN_DEBUG - *++x = *t; - p = t->rn_p; -#else - b = t->rn_info; - *++x = *t; - t->rn_info = b; - p = t->rn_p; -#endif - if (p->rn_l == t) - p->rn_l = x; - else - p->rn_r = x; - x->rn_l->rn_p = x; - x->rn_r->rn_p = x; - } - goto out; - } - if (t->rn_l == tt) - x = t->rn_r; - else - x = t->rn_l; - p = t->rn_p; - if (p->rn_r == t) - p->rn_r = x; - else - p->rn_l = x; - x->rn_p = p; - /* - * Demote routes attached to us. - */ - if (t->rn_mklist) { - if (x->rn_b >= 0) { - for (mp = &x->rn_mklist; (m = *mp) != NULL;) - mp = &m->rm_mklist; - *mp = t->rn_mklist; - } else { - /* If there are any key,mask pairs in a sibling - duped-key chain, some subset will appear sorted - in the same order attached to our mklist */ - for (m = t->rn_mklist; m && x; x = x->rn_dupedkey) - if (m == x->rn_mklist) { - struct radix_mask *mm = m->rm_mklist; - x->rn_mklist = 0; - if (--(m->rm_refs) < 0) - MKFree(m); - m = mm; - } -#if 0 - if (m) - log(LOG_ERR, "%s %p at %p\n", - "rn_delete: Orphaned Mask", m, x); -#endif - } - } - /* - * We may be holding an active internal node in the tree. - */ - x = tt + 1; - if (t != x) { -#ifndef RN_DEBUG - *t = *x; -#else - b = t->rn_info; - *t = *x; - t->rn_info = b; -#endif - t->rn_l->rn_p = t; - t->rn_r->rn_p = t; - p = x->rn_p; - if (p->rn_l == x) - p->rn_l = t; - else - p->rn_r = t; - } -out: - tt->rn_flags &= ~RNF_ACTIVE; - tt[1].rn_flags &= ~RNF_ACTIVE; - return (tt); -} - -int -rn_walktree(h, f, w) - struct radix_node_head *h; - int (*f) __P((struct radix_node *, void *)); - void *w; -{ - int error; - struct radix_node *base, *next; - struct radix_node *rn = h->rnh_treetop; - /* - * This gets complicated because we may delete the node - * while applying the function f to it, so we need to calculate - * the successor node in advance. - */ - /* First time through node, go left */ - while (rn->rn_b >= 0) - rn = rn->rn_l; - for (;;) { - base = rn; - /* If at right child go back up, otherwise, go right */ - while (rn->rn_p->rn_r == rn && (rn->rn_flags & RNF_ROOT) == 0) - rn = rn->rn_p; - /* Find the next *leaf* since next node might vanish, too */ - for (rn = rn->rn_p->rn_r; rn->rn_b >= 0;) - rn = rn->rn_l; - next = rn; - /* Process leaves */ - while ((rn = base) != NULL) { - base = rn->rn_dupedkey; - if (!(rn->rn_flags & RNF_ROOT) - && (error = (*f)(rn, w))) - return (error); - } - rn = next; - if (rn->rn_flags & RNF_ROOT) - return (0); - } - /* NOTREACHED */ -} - -int -rn_inithead(head, off) - void **head; - int off; -{ - struct radix_node_head *rnh; - - if (*head) - return (1); - R_Malloc(rnh, struct radix_node_head *, sizeof (*rnh)); - if (rnh == 0) - return (0); - *head = rnh; - return rn_inithead0(rnh, off); -} - -int -rn_inithead0(rnh, off) - struct radix_node_head *rnh; - int off; -{ - struct radix_node *t, *tt, *ttt; - - Bzero(rnh, sizeof (*rnh)); - t = rn_newpair(rn_zeros, off, rnh->rnh_nodes); - ttt = rnh->rnh_nodes + 2; - t->rn_r = ttt; - t->rn_p = t; - tt = t->rn_l; - tt->rn_flags = t->rn_flags = RNF_ROOT | RNF_ACTIVE; - tt->rn_b = -1 - off; - *ttt = *tt; - ttt->rn_key = rn_ones; - rnh->rnh_addaddr = rn_addroute; - rnh->rnh_deladdr = rn_delete; - rnh->rnh_matchaddr = rn_match; - rnh->rnh_lookup = rn_lookup; - rnh->rnh_walktree = rn_walktree; - rnh->rnh_treetop = t; - return (1); -} - -void -rn_init() -{ - char *cp, *cplim; - - if (max_keylen == 0) { -#if 0 - log(LOG_ERR, - "rn_init: radix functions require max_keylen be set\n"); -#endif - return; - } - if (rn_zeros == NULL) { - R_Malloc(rn_zeros, char *, 3 * max_keylen); - } - if (rn_zeros == NULL) - panic("rn_init"); - Bzero(rn_zeros, 3 * max_keylen); - rn_ones = cp = rn_zeros + max_keylen; - addmask_key = cplim = rn_ones + max_keylen; - while (cp < cplim) - *cp++ = -1; - if (rn_inithead((void *)&mask_rnhead, 0) == 0) - panic("rn_init 2"); -} - - -static int -rn_freenode(struct radix_node *n, void *p) -{ - struct radix_node_head *rnh = p; - struct radix_node *d; - - d = rnh->rnh_deladdr(n->rn_key, NULL, rnh); - if (d != NULL) { - FreeS(d, max_keylen + 2 * sizeof (*d)); - } - return 0; -} - - -void -rn_freehead(rnh) - struct radix_node_head *rnh; -{ - - (void)rn_walktree(rnh, rn_freenode, rnh); - - rnh->rnh_addaddr = NULL; - rnh->rnh_deladdr = NULL; - rnh->rnh_matchaddr = NULL; - rnh->rnh_lookup = NULL; - rnh->rnh_walktree = NULL; - - Free(rnh); -} - - -void -rn_fini() -{ - struct radix_mask *m; - - if (rn_zeros != NULL) { - FreeS(rn_zeros, 3 * max_keylen); - rn_zeros = NULL; - } - - if (mask_rnhead != NULL) { - rn_freehead(mask_rnhead); - mask_rnhead = NULL; - } - - while ((m = rn_mkfreelist) != NULL) { - rn_mkfreelist = m->rm_mklist; - KFREE(m); - } -} - - -#ifdef USE_MAIN - -typedef struct myst { - addrfamily_t dst; - addrfamily_t mask; - struct radix_node nodes[2]; -} myst_t; - -int -main(int argc, char *argv[]) -{ - struct radix_node_head *rnh; - struct radix_node *rn; - addrfamily_t af, mf; - myst_t st1, st2, *stp; - - memset(&st1, 0, sizeof(st1)); - memset(&st2, 0, sizeof(st2)); - memset(&af, 0, sizeof(af)); - - rn_init(); - - rnh = NULL; - rn_inithead(&rnh, offsetof(addrfamily_t, adf_addr) << 3); - - st1.dst.adf_len = sizeof(st1); - st1.mask.adf_len = sizeof(st1); - st1.dst.adf_addr.in4.s_addr = inet_addr("127.0.0.0"); - st1.mask.adf_addr.in4.s_addr = inet_addr("255.0.0.0"); - rn = rnh->rnh_addaddr(&st1.dst, &st1.mask, rnh, st1.nodes); - printf("add.1 %p\n", rn); - - st2.dst.adf_len = sizeof(st2); - st2.mask.adf_len = sizeof(st2); - st2.dst.adf_addr.in4.s_addr = inet_addr("127.0.1.0"); - st2.mask.adf_addr.in4.s_addr = inet_addr("255.255.255.0"); - rn = rnh->rnh_addaddr(&st2.dst, &st2.mask, rnh, st2.nodes); - printf("add.2 %p\n", rn); - - af.adf_len = sizeof(af); - af.adf_addr.in4.s_addr = inet_addr("127.0.1.0"); - rn = rnh->rnh_matchaddr(&af, rnh); - if (rn != NULL) { - printf("1.lookup = %p key %p mask %p\n", rn, rn->rn_key, rn->rn_mask); - stp = rn->rn_key; - printf("%s/", inet_ntoa(stp->dst.adf_addr.in4)); - stp = rn->rn_mask; - printf("%s\n", inet_ntoa(stp->dst.adf_addr.in4)); - } - - mf.adf_len = sizeof(mf); - mf.adf_addr.in4.s_addr = inet_addr("255.255.255.0"); - rn = rnh->rnh_lookup(&af, &mf, rnh); - if (rn != NULL) { - printf("2.lookup = %p key %p mask %p\n", rn, rn->rn_key, rn->rn_mask); - stp = rn->rn_key; - printf("%s/", inet_ntoa(stp->dst.adf_addr.in4)); - stp = rn->rn_mask; - printf("%s\n", inet_ntoa(stp->dst.adf_addr.in4)); - } - - af.adf_len = sizeof(af); - af.adf_addr.in4.s_addr = inet_addr("126.0.0.1"); - rn = rnh->rnh_matchaddr(&af, rnh); - if (rn != NULL) { - printf("3.lookup = %p key %p mask %p\n", rn, rn->rn_key, rn->rn_mask); - stp = rn->rn_key; - printf("%s/", inet_ntoa(stp->dst.adf_addr.in4)); - stp = rn->rn_mask; - printf("%s\n", inet_ntoa(stp->dst.adf_addr.in4)); - } - - return 0; -} - - -void -log(int level, char *format, ...) -{ - va_list ap; - - va_start(ap, format); - vfprintf(stderr, format, ap); - va_end(ap); -} -#endif - - -#ifndef _KERNEL -void -panic(char *str) -{ - fputs(str, stderr); - abort(); -} -#endif diff --git a/radix_ipf.c b/radix_ipf.c new file mode 100644 index 0000000000000..f145c38a94d6c --- /dev/null +++ b/radix_ipf.c @@ -0,0 +1,1528 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ +#include <sys/types.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <net/if.h> +#if !defined(_KERNEL) +# include <stddef.h> +# include <stdlib.h> +# include <strings.h> +# include <string.h> +#endif +#include "netinet/ip_compat.h" +#include "netinet/ip_fil.h" +#ifdef RDX_DEBUG +# include <arpa/inet.h> +# include <stdlib.h> +# include <stdio.h> +#endif +#include "netinet/radix_ipf.h" + +#define ADF_OFF offsetof(addrfamily_t, adf_addr) +#define ADF_OFF_BITS (ADF_OFF << 3) + +static ipf_rdx_node_t *ipf_rx_insert __P((ipf_rdx_head_t *, + ipf_rdx_node_t nodes[2], int *)); +static void ipf_rx_attach_mask __P((ipf_rdx_node_t *, ipf_rdx_mask_t *)); +static int count_mask_bits __P((addrfamily_t *, u_32_t **)); +static void buildnodes __P((addrfamily_t *, addrfamily_t *, + ipf_rdx_node_t n[2])); +static ipf_rdx_node_t *ipf_rx_find_addr __P((ipf_rdx_node_t *, u_32_t *)); +static ipf_rdx_node_t *ipf_rx_lookup __P((ipf_rdx_head_t *, addrfamily_t *, + addrfamily_t *)); +static ipf_rdx_node_t *ipf_rx_match __P((ipf_rdx_head_t *, addrfamily_t *)); + +/* + * Foreword. + * --------- + * The code in this file has been written to target using the addrfamily_t + * data structure to house the address information and no other. Thus there + * are certain aspects of thise code (such as offsets to the address itself) + * that are hard coded here whilst they might be more variable elsewhere. + * Similarly, this code enforces no maximum key length as that's implied by + * all keys needing to be stored in addrfamily_t. + */ + +/* ------------------------------------------------------------------------ */ +/* Function: count_mask_bits */ +/* Returns: number of consecutive bits starting at "mask". */ +/* */ +/* Count the number of bits set in the address section of addrfamily_t and */ +/* return both that number and a pointer to the last word with a bit set if */ +/* lastp is not NULL. The bit count is performed using network byte order */ +/* as the guide for which bit is the most significant bit. */ +/* ------------------------------------------------------------------------ */ +static int +count_mask_bits(mask, lastp) + addrfamily_t *mask; + u_32_t **lastp; +{ + u_32_t *mp = (u_32_t *)&mask->adf_addr; + u_32_t m; + int count = 0; + int mlen; + + mlen = mask->adf_len - offsetof(addrfamily_t, adf_addr); + for (; mlen > 0; mlen -= 4, mp++) { + if ((m = ntohl(*mp)) == 0) + break; + if (lastp != NULL) + *lastp = mp; + for (; m & 0x80000000; m <<= 1) + count++; + } + + return count; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: buildnodes */ +/* Returns: Nil */ +/* Parameters: addr(I) - network address for this radix node */ +/* mask(I) - netmask associated with the above address */ +/* nodes(O) - pair of ipf_rdx_node_t's to initialise with data */ +/* associated with addr and mask. */ +/* */ +/* Initialise the fields in a pair of radix tree nodes according to the */ +/* data supplied in the paramters "addr" and "mask". It is expected that */ +/* "mask" will contain a consecutive string of bits set. Masks with gaps in */ +/* the middle are not handled by this implementation. */ +/* ------------------------------------------------------------------------ */ +static void +buildnodes(addr, mask, nodes) + addrfamily_t *addr, *mask; + ipf_rdx_node_t nodes[2]; +{ + u_32_t maskbits; + u_32_t lastbits; + u_32_t lastmask; + u_32_t *last; + int masklen; + + last = NULL; + maskbits = count_mask_bits(mask, &last); + if (last == NULL) { + masklen = 0; + lastmask = 0; + } else { + masklen = last - (u_32_t *)mask; + lastmask = *last; + } + lastbits = maskbits & 0x1f; + + bzero(&nodes[0], sizeof(ipf_rdx_node_t) * 2); + nodes[0].maskbitcount = maskbits; + nodes[0].index = -1 - (ADF_OFF_BITS + maskbits); + nodes[0].addrkey = (u_32_t *)addr; + nodes[0].maskkey = (u_32_t *)mask; + nodes[0].addroff = nodes[0].addrkey + masklen; + nodes[0].maskoff = nodes[0].maskkey + masklen; + nodes[0].parent = &nodes[1]; + nodes[0].offset = masklen; + nodes[0].lastmask = lastmask; + nodes[1].offset = masklen; + nodes[1].left = &nodes[0]; + nodes[1].maskbitcount = maskbits; +#ifdef RDX_DEBUG + (void) strcpy(nodes[0].name, "_BUILD.0"); + (void) strcpy(nodes[1].name, "_BUILD.1"); +#endif +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_rx_find_addr */ +/* Returns: ipf_rdx_node_t * - pointer to a node in the radix tree. */ +/* Parameters: tree(I) - pointer to first right node in tree to search */ +/* addr(I) - pointer to address to match */ +/* */ +/* Walk the radix tree given by "tree", looking for a leaf node that is a */ +/* match for the address given by "addr". */ +/* ------------------------------------------------------------------------ */ +static ipf_rdx_node_t * +ipf_rx_find_addr(tree, addr) + ipf_rdx_node_t *tree; + u_32_t *addr; +{ + ipf_rdx_node_t *cur; + + for (cur = tree; cur->index >= 0;) { + if (cur->bitmask & addr[cur->offset]) { + cur = cur->right; + } else { + cur = cur->left; + } + } + + return (cur); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_rx_match */ +/* Returns: ipf_rdx_node_t * - NULL on error, else pointer to the node */ +/* added to the tree. */ +/* Paramters: head(I) - pointer to tree head to search */ +/* addr(I) - pointer to address to find */ +/* */ +/* Search the radix tree for the best match to the address pointed to by */ +/* "addr" and return a pointer to that node. This search will not match the */ +/* address information stored in either of the root leaves as neither of */ +/* them are considered to be part of the tree of data being stored. */ +/* ------------------------------------------------------------------------ */ +static ipf_rdx_node_t * +ipf_rx_match(head, addr) + ipf_rdx_head_t *head; + addrfamily_t *addr; +{ + ipf_rdx_mask_t *masknode; + ipf_rdx_node_t *prev; + ipf_rdx_node_t *node; + ipf_rdx_node_t *cur; + u_32_t *data; + u_32_t *mask; + u_32_t *key; + u_32_t *end; + int len; + int i; + + len = addr->adf_len; + end = (u_32_t *)((u_char *)addr + len); + node = ipf_rx_find_addr(head->root, (u_32_t *)addr); + + /* + * Search the dupkey list for a potential match. + */ + for (cur = node; (cur != NULL) && (cur->root == 0); cur = cur->dupkey) { + i = cur[0].addroff - cur[0].addrkey; + data = cur[0].addrkey + i; + mask = cur[0].maskkey + i; + key = (u_32_t *)addr + i; + for (; key < end; data++, key++, mask++) + if ((*key & *mask) != *data) + break; + if ((end == key) && (cur->root == 0)) + return (cur); /* Equal keys */ + } + prev = node->parent; + key = (u_32_t *)addr; + + for (node = prev; node->root == 0; node = node->parent) { + /* + * We know that the node hasn't matched so therefore only + * the entries in the mask list are searched, not the top + * node nor the dupkey list. + */ + masknode = node->masks; + for (; masknode != NULL; masknode = masknode->next) { + if (masknode->maskbitcount > node->maskbitcount) + continue; + cur = masknode->node; + for (i = ADF_OFF >> 2; i <= node->offset; i++) { + if ((key[i] & masknode->mask[i]) == + cur->addrkey[i]) + return (cur); + } + } + } + + return NULL; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_rx_lookup */ +/* Returns: ipf_rdx_node_t * - NULL on error, else pointer to the node */ +/* added to the tree. */ +/* Paramters: head(I) - pointer to tree head to search */ +/* addr(I) - address part of the key to match */ +/* mask(I) - netmask part of the key to match */ +/* */ +/* ipf_rx_lookup searches for an exact match on (addr,mask). The intention */ +/* is to see if a given key is in the tree, not to see if a route exists. */ +/* ------------------------------------------------------------------------ */ +ipf_rdx_node_t * +ipf_rx_lookup(head, addr, mask) + ipf_rdx_head_t *head; + addrfamily_t *addr, *mask; +{ + ipf_rdx_node_t *found; + ipf_rdx_node_t *node; + u_32_t *akey; + int count; + + found = ipf_rx_find_addr(head->root, (u_32_t *)addr); + if (found->root == 1) + return NULL; + + /* + * It is possible to find a matching address in the tree but for the + * netmask to not match. If the netmask does not match and there is + * no list of alternatives present at dupkey, return a failure. + */ + count = count_mask_bits(mask, NULL); + if (count != found->maskbitcount && found->dupkey == NULL) + return (NULL); + + akey = (u_32_t *)addr; + if ((found->addrkey[found->offset] & found->maskkey[found->offset]) != + akey[found->offset]) + return NULL; + + if (found->dupkey != NULL) { + node = found; + while (node != NULL && node->maskbitcount != count) + node = node->dupkey; + if (node == NULL) + return (NULL); + found = node; + } + return found; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_rx_attach_mask */ +/* Returns: Nil */ +/* Parameters: node(I) - pointer to a radix tree node */ +/* mask(I) - pointer to mask structure to add */ +/* */ +/* Add the netmask to the given node in an ordering where the most specific */ +/* netmask is at the top of the list. */ +/* ------------------------------------------------------------------------ */ +static void +ipf_rx_attach_mask(node, mask) + ipf_rdx_node_t *node; + ipf_rdx_mask_t *mask; +{ + ipf_rdx_mask_t **pm; + ipf_rdx_mask_t *m; + + for (pm = &node->masks; (m = *pm) != NULL; pm = &m->next) + if (m->maskbitcount < mask->maskbitcount) + break; + mask->next = *pm; + *pm = mask; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_rx_insert */ +/* Returns: ipf_rdx_node_t * - NULL on error, else pointer to the node */ +/* added to the tree. */ +/* Paramters: head(I) - pointer to tree head to add nodes to */ +/* nodes(I) - pointer to radix nodes to be added */ +/* dup(O) - set to 1 if node is a duplicate, else 0. */ +/* */ +/* Add the new radix tree entry that owns nodes[] to the tree given by head.*/ +/* If there is already a matching key in the table, "dup" will be set to 1 */ +/* and the existing node pointer returned if there is a complete key match. */ +/* A complete key match is a matching of all key data that is presented by */ +/* by the netmask. */ +/* ------------------------------------------------------------------------ */ +static ipf_rdx_node_t * +ipf_rx_insert(head, nodes, dup) + ipf_rdx_head_t *head; + ipf_rdx_node_t nodes[2]; + int *dup; +{ + ipf_rdx_mask_t **pmask; + ipf_rdx_node_t *node; + ipf_rdx_node_t *prev; + ipf_rdx_mask_t *mask; + ipf_rdx_node_t *cur; + u_32_t nodemask; + u_32_t *addr; + u_32_t *data; + int nodebits; + u_32_t *key; + u_32_t *end; + u_32_t bits; + int nodekey; + int nodeoff; + int nlen; + int len; + + addr = nodes[0].addrkey; + + node = ipf_rx_find_addr(head->root, addr); + len = ((addrfamily_t *)addr)->adf_len; + key = (u_32_t *)&((addrfamily_t *)addr)->adf_addr; + data= (u_32_t *)&((addrfamily_t *)node->addrkey)->adf_addr; + end = (u_32_t *)((u_char *)addr + len); + for (nlen = 0; key < end; data++, key++, nlen += 32) + if (*key != *data) + break; + if (end == data) { + *dup = 1; + return (node); /* Equal keys */ + } + *dup = 0; + + bits = (ntohl(*data) ^ ntohl(*key)); + for (; bits != 0; nlen++) { + if ((bits & 0x80000000) != 0) + break; + bits <<= 1; + } + nlen += ADF_OFF_BITS; + nodes[1].index = nlen; + nodes[1].bitmask = htonl(0x80000000 >> (nlen & 0x1f)); + nodes[0].offset = nlen / 32; + nodes[1].offset = nlen / 32; + + /* + * Walk through the tree and look for the correct place to attach + * this node. ipf_rx_fin_addr is not used here because the place + * to attach this node may be an internal node (same key, different + * netmask.) Additionally, the depth of the search is forcibly limited + * here to not exceed the netmask, so that a short netmask will be + * added higher up the tree even if there are lower branches. + */ + cur = head->root; + key = nodes[0].addrkey; + do { + prev = cur; + if (key[cur->offset] & cur->bitmask) { + cur = cur->right; + } else { + cur = cur->left; + } + } while (nlen > (unsigned)cur->index); + + if ((key[prev->offset] & prev->bitmask) == 0) { + prev->left = &nodes[1]; + } else { + prev->right = &nodes[1]; + } + cur->parent = &nodes[1]; + nodes[1].parent = prev; + if ((key[nodes[1].offset] & nodes[1].bitmask) == 0) { + nodes[1].right = cur; + } else { + nodes[1].right = &nodes[0]; + nodes[1].left = cur; + } + + nodeoff = nodes[0].offset; + nodekey = nodes[0].addrkey[nodeoff]; + nodemask = nodes[0].lastmask; + nodebits = nodes[0].maskbitcount; + prev = NULL; + /* + * Find the node up the tree with the largest pattern that still + * matches the node being inserted to see if this mask can be + * moved there. + */ + for (cur = nodes[1].parent; cur->root == 0; cur = cur->parent) { + if (cur->maskbitcount <= nodebits) + break; + if (((cur - 1)->addrkey[nodeoff] & nodemask) != nodekey) + break; + prev = cur; + } + + KMALLOC(mask, ipf_rdx_mask_t *); + if (mask == NULL) + return NULL; + bzero(mask, sizeof(*mask)); + mask->next = NULL; + mask->node = &nodes[0]; + mask->maskbitcount = nodebits; + mask->mask = nodes[0].maskkey; + nodes[0].mymask = mask; + + if (prev != NULL) { + ipf_rdx_mask_t *m; + + for (pmask = &prev->masks; (m = *pmask) != NULL; + pmask = &m->next) { + if (m->maskbitcount < nodebits) + break; + } + } else { + /* + * No higher up nodes qualify, so attach mask locally. + */ + pmask = &nodes[0].masks; + } + mask->next = *pmask; + *pmask = mask; + + /* + * Search the mask list on each child to see if there are any masks + * there that can be moved up to this newly inserted node. + */ + cur = nodes[1].right; + if (cur->root == 0) { + for (pmask = &cur->masks; (mask = *pmask) != NULL; ) { + if (mask->maskbitcount < nodebits) { + *pmask = mask->next; + ipf_rx_attach_mask(&nodes[0], mask); + } else { + pmask = &mask->next; + } + } + } + cur = nodes[1].left; + if (cur->root == 0 && cur != &nodes[0]) { + for (pmask = &cur->masks; (mask = *pmask) != NULL; ) { + if (mask->maskbitcount < nodebits) { + *pmask = mask->next; + ipf_rx_attach_mask(&nodes[0], mask); + } else { + pmask = &mask->next; + } + } + } + return (&nodes[0]); +} + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_rx_addroute */ +/* Returns: ipf_rdx_node_t * - NULL on error, else pointer to the node */ +/* added to the tree. */ +/* Paramters: head(I) - pointer to tree head to search */ +/* addr(I) - address portion of "route" to add */ +/* mask(I) - netmask portion of "route" to add */ +/* nodes(I) - radix tree data nodes inside allocate structure */ +/* */ +/* Attempt to add a node to the radix tree. The key for the node is the */ +/* (addr,mask). No memory allocation for the radix nodes themselves is */ +/* performed here, the data structure that this radix node is being used to */ +/* find is expected to house the node data itself however the call to */ +/* ipf_rx_insert() will attempt to allocate memory in order for netmask to */ +/* be promoted further up the tree. */ +/* In this case, the ip_pool_node_t structure from ip_pool.h contains both */ +/* the key material (addr,mask) and the radix tree nodes[]. */ +/* */ +/* The mechanics of inserting the node into the tree is handled by the */ +/* function ipf_rx_insert() above. Here, the code deals with the case */ +/* where the data to be inserted is a duplicate. */ +/* ------------------------------------------------------------------------ */ +ipf_rdx_node_t * +ipf_rx_addroute(head, addr, mask, nodes) + ipf_rdx_head_t *head; + addrfamily_t *addr, *mask; + ipf_rdx_node_t *nodes; +{ + ipf_rdx_node_t *node; + ipf_rdx_node_t *prev; + ipf_rdx_node_t *x; + int dup; + + buildnodes(addr, mask, nodes); + x = ipf_rx_insert(head, nodes, &dup); + if (x == NULL) + return NULL; + + if (dup == 1) { + node = &nodes[0]; + prev = NULL; + /* + * The duplicate list is kept sorted with the longest + * mask at the top, meaning that the most specific entry + * in the listis found first. This list thus allows for + * duplicates such as 128.128.0.0/32 and 128.128.0.0/16. + */ + while ((x != NULL) && (x->maskbitcount > node->maskbitcount)) { + prev = x; + x = x->dupkey; + } + + /* + * Is it a complete duplicate? If so, return NULL and + * fail the insert. Otherwise, insert it into the list + * of netmasks active for this key. + */ + if ((x != NULL) && (x->maskbitcount == node->maskbitcount)) + return (NULL); + + if (prev != NULL) { + nodes[0].dupkey = x; + prev->dupkey = &nodes[0]; + nodes[0].parent = prev; + if (x != NULL) + x->parent = &nodes[0]; + } else { + nodes[0].dupkey = x->dupkey; + prev = x->parent; + nodes[0].parent = prev; + x->parent = &nodes[0]; + if (prev->left == x) + prev->left = &nodes[0]; + else + prev->right = &nodes[0]; + } + } + + return &nodes[0]; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_rx_delete */ +/* Returns: ipf_rdx_node_t * - NULL on error, else node removed from */ +/* the tree. */ +/* Paramters: head(I) - pointer to tree head to search */ +/* addr(I) - pointer to the address part of the key */ +/* mask(I) - pointer to the netmask part of the key */ +/* */ +/* Search for an entry in the radix tree that is an exact match for (addr, */ +/* mask) and remove it if it exists. In the case where (addr,mask) is a not */ +/* a unique key, the tree structure itself is not changed - only the list */ +/* of duplicate keys. */ +/* ------------------------------------------------------------------------ */ +ipf_rdx_node_t * +ipf_rx_delete(head, addr, mask) + ipf_rdx_head_t *head; + addrfamily_t *addr, *mask; +{ + ipf_rdx_mask_t **pmask; + ipf_rdx_node_t *parent; + ipf_rdx_node_t *found; + ipf_rdx_node_t *prev; + ipf_rdx_node_t *node; + ipf_rdx_node_t *cur; + ipf_rdx_mask_t *m; + int count; + + found = ipf_rx_find_addr(head->root, (u_32_t *)addr); + if (found == NULL) + return NULL; + if (found->root == 1) + return NULL; + count = count_mask_bits(mask, NULL); + parent = found->parent; + if (found->dupkey != NULL) { + node = found; + while (node != NULL && node->maskbitcount != count) + node = node->dupkey; + if (node == NULL) + return (NULL); + if (node != found) { + /* + * Remove from the dupkey list. Here, "parent" is + * the previous node on the list (rather than tree) + * and "dupkey" is the next node on the list. + */ + parent = node->parent; + parent->dupkey = node->dupkey; + node->dupkey->parent = parent; + } else { + /* + * + * When removing the top node of the dupkey list, + * the pointers at the top of the list that point + * to other tree nodes need to be preserved and + * any children must have their parent updated. + */ + node = node->dupkey; + node->parent = found->parent; + node->right = found->right; + node->left = found->left; + found->right->parent = node; + found->left->parent = node; + if (parent->left == found) + parent->left = node; + else + parent->right= node; + } + } else { + if (count != found->maskbitcount) + return (NULL); + /* + * Remove the node from the tree and reconnect the subtree + * below. + */ + /* + * If there is a tree to the left, look for something to + * attach in place of "found". + */ + prev = found + 1; + cur = parent->parent; + if (parent != found + 1) { + if ((found + 1)->parent->right == found + 1) + (found + 1)->parent->right = parent; + else + (found + 1)->parent->left = parent; + if (cur->right == parent) { + if (parent->left == found) { + cur->right = parent->right; + } else if (parent->left != parent - 1) { + cur->right = parent->left; + } else { + cur->right = parent - 1; + } + cur->right->parent = cur; + } else { + if (parent->right == found) { + cur->left = parent->left; + } else if (parent->right != parent - 1) { + cur->left = parent->right; + } else { + cur->left = parent - 1; + } + cur->left->parent = cur; + } + parent->left = (found + 1)->left; + if ((found + 1)->right != parent) + parent->right = (found + 1)->right; + parent->left->parent = parent; + parent->right->parent = parent; + parent->parent = (found + 1)->parent; + + parent->bitmask = prev->bitmask; + parent->offset = prev->offset; + parent->index = prev->index; + } else { + /* + * We found an edge node. + */ + cur = parent->parent; + if (cur->left == parent) { + if (parent->left == found) { + cur->left = parent->right; + parent->right->parent = cur; + } else { + cur->left = parent->left; + parent->left->parent = cur; + } + } else { + if (parent->right != found) { + cur->right = parent->right; + parent->right->parent = cur; + } else { + cur->right = parent->left; + prev->left->parent = cur; + } + } + } + } + + /* + * Remove mask associated with this node. + */ + for (cur = parent; cur->root == 0; cur = cur->parent) { + ipf_rdx_mask_t **pm; + + if (cur->maskbitcount <= found->maskbitcount) + break; + if (((cur - 1)->addrkey[found->offset] & found->bitmask) != + found->addrkey[found->offset]) + break; + for (pm = &cur->masks; (m = *pm) != NULL; ) + if (m->node == cur) { + *pm = m->next; + break; + } else { + pm = &m->next; + } + } + KFREE(found->mymask); + + /* + * Masks that have been brought up to this node from below need to + * be sent back down. + */ + for (pmask = &parent->masks; (m = *pmask) != NULL; ) { + *pmask = m->next; + cur = m->node; + if (cur == found) + continue; + if (found->addrkey[cur->offset] & cur->lastmask) { + ipf_rx_attach_mask(parent->right, m); + } else if (parent->left != found) { + ipf_rx_attach_mask(parent->left, m); + } + } + + return (found); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_rx_walktree */ +/* Returns: Nil */ +/* Paramters: head(I) - pointer to tree head to search */ +/* walker(I) - function to call for each node in the tree */ +/* arg(I) - parameter to pass to walker, in addition to the */ +/* node pointer */ +/* */ +/* A standard tree walking function except that it is iterative, rather */ +/* than recursive and tracks the next node in case the "walker" function */ +/* should happen to delete and free the current node. It thus goes without */ +/* saying that the "walker" function is not permitted to cause any change */ +/* in the validity of the data found at either the left or right child. */ +/* ------------------------------------------------------------------------ */ +void +ipf_rx_walktree(head, walker, arg) + ipf_rdx_head_t *head; + radix_walk_func_t walker; + void *arg; +{ + ipf_rdx_node_t *next; + ipf_rdx_node_t *node = head->root; + ipf_rdx_node_t *base; + + while (node->index >= 0) + node = node->left; + + for (;;) { + base = node; + while ((node->parent->right == node) && (node->root == 0)) + node = node->parent; + + for (node = node->parent->right; node->index >= 0; ) + node = node->left; + next = node; + + for (node = base; node != NULL; node = base) { + base = node->dupkey; + if (node->root == 0) + walker(node, arg); + } + node = next; + if (node->root) + return; + } +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_rx_inithead */ +/* Returns: int - 0 = success, else failure */ +/* Paramters: softr(I) - pointer to radix context */ +/* headp(O) - location for where to store allocated tree head */ +/* */ +/* This function allocates and initialises a radix tree head structure. */ +/* As a traditional radix tree, node 0 is used as the "0" sentinel and node */ +/* "2" is used as the all ones sentinel, leaving node "1" as the root from */ +/* which the tree is hung with node "0" on its left and node "2" to the */ +/* right. The context, "softr", is used here to provide a common source of */ +/* the zeroes and ones data rather than have one per head. */ +/* ------------------------------------------------------------------------ */ +int +ipf_rx_inithead(softr, headp) + radix_softc_t *softr; + ipf_rdx_head_t **headp; +{ + ipf_rdx_head_t *ptr; + ipf_rdx_node_t *node; + + KMALLOC(ptr, ipf_rdx_head_t *); + *headp = ptr; + if (ptr == NULL) + return -1; + bzero(ptr, sizeof(*ptr)); + node = ptr->nodes; + ptr->root = node + 1; + node[0].index = ADF_OFF_BITS; + node[0].index = -1 - node[0].index; + node[1].index = ADF_OFF_BITS; + node[2].index = node[0].index; + node[0].parent = node + 1; + node[1].parent = node + 1; + node[2].parent = node + 1; + node[1].bitmask = htonl(0x80000000); + node[0].root = 1; + node[1].root = 1; + node[2].root = 1; + node[0].offset = ADF_OFF_BITS >> 5; + node[1].offset = ADF_OFF_BITS >> 5; + node[2].offset = ADF_OFF_BITS >> 5; + node[1].left = &node[0]; + node[1].right = &node[2]; + node[0].addrkey = (u_32_t *)softr->zeros; + node[2].addrkey = (u_32_t *)softr->ones; +#ifdef RDX_DEBUG + (void) strcpy(node[0].name, "0_ROOT"); + (void) strcpy(node[1].name, "1_ROOT"); + (void) strcpy(node[2].name, "2_ROOT"); +#endif + + ptr->addaddr = ipf_rx_addroute; + ptr->deladdr = ipf_rx_delete; + ptr->lookup = ipf_rx_lookup; + ptr->matchaddr = ipf_rx_match; + ptr->walktree = ipf_rx_walktree; + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_rx_freehead */ +/* Returns: Nil */ +/* Paramters: head(I) - pointer to tree head to free */ +/* */ +/* This function simply free's up the radix tree head. Prior to calling */ +/* this function, it is expected that the tree will have been emptied. */ +/* ------------------------------------------------------------------------ */ +void +ipf_rx_freehead(head) + ipf_rdx_head_t *head; +{ + KFREE(head); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_rx_create */ +/* Parameters: Nil */ +/* */ +/* ------------------------------------------------------------------------ */ +void * +ipf_rx_create() +{ + radix_softc_t *softr; + + KMALLOC(softr, radix_softc_t *); + if (softr == NULL) + return NULL; + bzero((char *)softr, sizeof(*softr)); + + KMALLOCS(softr->zeros, u_char *, 3 * sizeof(addrfamily_t)); + if (softr->zeros == NULL) { + KFREE(softr); + return (NULL); + } + softr->ones = softr->zeros + sizeof(addrfamily_t); + + return softr; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_rx_init */ +/* Returns: int - 0 = success (always) */ +/* */ +/* ------------------------------------------------------------------------ */ +int +ipf_rx_init(ctx) + void *ctx; +{ + radix_softc_t *softr = ctx; + + memset(softr->zeros, 0, 3 * sizeof(addrfamily_t)); + memset(softr->ones, 0xff, sizeof(addrfamily_t)); + + return (0); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_rx_destroy */ +/* Returns: Nil */ +/* */ +/* ------------------------------------------------------------------------ */ +void +ipf_rx_destroy(ctx) + void *ctx; +{ + radix_softc_t *softr = ctx; + + if (softr->zeros != NULL) + KFREES(softr->zeros, 3 * sizeof(addrfamily_t)); + KFREE(softr); +} + +/* ====================================================================== */ + +#ifdef RDX_DEBUG +/* + * To compile this file as a standalone test unit, use -DRDX_DEBUG=1 + */ +#define NAME(x) ((x)->index < 0 ? (x)->name : (x)->name) +#define GNAME(y) ((y) == NULL ? "NULL" : NAME(y)) + +typedef struct myst { + struct ipf_rdx_node nodes[2]; + addrfamily_t dst; + addrfamily_t mask; + struct myst *next; + int printed; +} myst_t; + +typedef struct tabe_s { + char *host; + char *mask; + char *what; +} tabe_t; + +tabe_t builtin[] = { +#if 1 + { "192:168:100::0", "48", "d" }, + { "192:168:100::2", "128", "d" }, +#else + { "127.192.0.0", "255.255.255.0", "d" }, + { "127.128.0.0", "255.255.255.0", "d" }, + { "127.96.0.0", "255.255.255.0", "d" }, + { "127.80.0.0", "255.255.255.0", "d" }, + { "127.72.0.0", "255.255.255.0", "d" }, + { "127.64.0.0", "255.255.255.0", "d" }, + { "127.56.0.0", "255.255.255.0", "d" }, + { "127.48.0.0", "255.255.255.0", "d" }, + { "127.40.0.0", "255.255.255.0", "d" }, + { "127.32.0.0", "255.255.255.0", "d" }, + { "127.24.0.0", "255.255.255.0", "d" }, + { "127.16.0.0", "255.255.255.0", "d" }, + { "127.8.0.0", "255.255.255.0", "d" }, + { "124.0.0.0", "255.0.0.0", "d" }, + { "125.0.0.0", "255.0.0.0", "d" }, + { "126.0.0.0", "255.0.0.0", "d" }, + { "127.0.0.0", "255.0.0.0", "d" }, + { "10.0.0.0", "255.0.0.0", "d" }, + { "128.250.0.0", "255.255.0.0", "d" }, + { "192.168.0.0", "255.255.0.0", "d" }, + { "192.168.1.0", "255.255.255.0", "d" }, +#endif + { NULL, NULL, NULL } +}; + +char *mtable[][1] = { +#if 1 + { "192:168:100::2" }, + { "192:168:101::2" }, +#else + { "9.0.0.0" }, + { "9.0.0.1" }, + { "11.0.0.0" }, + { "11.0.0.1" }, + { "127.0.0.1" }, + { "127.0.1.0" }, + { "255.255.255.0" }, + { "126.0.0.1" }, + { "128.251.0.0" }, + { "128.251.0.1" }, + { "128.251.255.255" }, + { "129.250.0.0" }, + { "129.250.0.1" }, + { "192.168.255.255" }, +#endif + { NULL } +}; + + +int forder[22] = { + 14, 13, 12, 5, 10, 3, 19, 7, 4, 20, 8, + 2, 17, 9, 16, 11, 15, 1, 6, 18, 0, 21 +}; + +static int nodecount = 0; +myst_t *myst_top = NULL; +tabe_t *ttable = NULL; + +void add_addr(ipf_rdx_head_t *, int , int); +void checktree(ipf_rdx_head_t *); +void delete_addr(ipf_rdx_head_t *rnh, int item); +void dumptree(ipf_rdx_head_t *rnh); +void nodeprinter(ipf_rdx_node_t *, void *); +void printroots(ipf_rdx_head_t *); +void random_add(ipf_rdx_head_t *); +void random_delete(ipf_rdx_head_t *); +void test_addr(ipf_rdx_head_t *rnh, int pref, addrfamily_t *, int); + + +static void +ipf_rx_freenode(node, arg) + ipf_rdx_node_t *node; + void *arg; +{ + ipf_rdx_head_t *head = arg; + ipf_rdx_node_t *rv; + myst_t *stp; + + stp = (myst_t *)node; + rv = ipf_rx_delete(head, &stp->dst, &stp->mask); + if (rv != NULL) { + free(rv); + } +} + + +const char * +addrname(ap) + addrfamily_t *ap; +{ + static char name[80]; + const char *txt; + + bzero((char *)name, sizeof(name)); + txt = inet_ntop(ap->adf_family, &ap->adf_addr, name, + sizeof(name)); + return txt; +} + + +void +fill6bits(bits, msk) + int bits; + u_int *msk; +{ + if (bits == 0) { + msk[0] = 0; + msk[1] = 0; + msk[2] = 0; + msk[3] = 0; + return; + } + + msk[0] = 0xffffffff; + msk[1] = 0xffffffff; + msk[2] = 0xffffffff; + msk[3] = 0xffffffff; + + if (bits == 128) + return; + if (bits > 96) { + msk[3] = htonl(msk[3] << (128 - bits)); + } else if (bits > 64) { + msk[3] = 0; + msk[2] = htonl(msk[2] << (96 - bits)); + } else if (bits > 32) { + msk[3] = 0; + msk[2] = 0; + msk[1] = htonl(msk[1] << (64 - bits)); + } else { + msk[3] = 0; + msk[2] = 0; + msk[1] = 0; + msk[0] = htonl(msk[0] << (32 - bits)); + } +} + + +void +setaddr(afp, str) + addrfamily_t *afp; + char *str; +{ + + bzero((char *)afp, sizeof(*afp)); + + if (strchr(str, ':') == NULL) { + afp->adf_family = AF_INET; + afp->adf_len = offsetof(addrfamily_t, adf_addr) + 4; + } else { + afp->adf_family = AF_INET6; + afp->adf_len = offsetof(addrfamily_t, adf_addr) + 16; + } + inet_pton(afp->adf_family, str, &afp->adf_addr); +} + + +void +setmask(afp, str) + addrfamily_t *afp; + char *str; +{ + if (strchr(str, '.') != NULL) { + afp->adf_addr.in4.s_addr = inet_addr(str); + afp->adf_len = offsetof(addrfamily_t, adf_addr) + 4; + } else if (afp->adf_family == AF_INET) { + afp->adf_addr.i6[0] = htonl(0xffffffff << (32 - atoi(str))); + afp->adf_len = offsetof(addrfamily_t, adf_addr) + 4; + } else if (afp->adf_family == AF_INET6) { + fill6bits(atoi(str), afp->adf_addr.i6); + afp->adf_len = offsetof(addrfamily_t, adf_addr) + 16; + } +} + + +void +nodeprinter(node, arg) + ipf_rdx_node_t *node; + void *arg; +{ + myst_t *stp = (myst_t *)node; + + printf("Node %-9.9s L %-9.9s R %-9.9s P %9.9s/%-9.9s %s/%d\n", + node[0].name, + GNAME(node[1].left), GNAME(node[1].right), + GNAME(node[0].parent), GNAME(node[1].parent), + addrname(&stp->dst), node[0].maskbitcount); + if (stp->printed == -1) + printf("!!! %d\n", stp->printed); + else + stp->printed = 1; +} + + +void +printnode(stp) + myst_t *stp; +{ + ipf_rdx_node_t *node = &stp->nodes[0]; + + if (stp->nodes[0].index > 0) + stp = (myst_t *)&stp->nodes[-1]; + + printf("Node %-9.9s ", node[0].name); + printf("L %-9.9s ", GNAME(node[1].left)); + printf("R %-9.9s ", GNAME(node[1].right)); + printf("P %9.9s", GNAME(node[0].parent)); + printf("/%-9.9s ", GNAME(node[1].parent)); + printf("%s P%d\n", addrname(&stp->dst), stp->printed); +} + + +void +buildtab(void) +{ + char line[80], *s; + tabe_t *tab; + int lines; + FILE *fp; + + lines = 0; + fp = fopen("hosts", "r"); + + while (fgets(line, sizeof(line), fp) != NULL) { + s = strchr(line, '\n'); + if (s != NULL) + *s = '\0'; + lines++; + if (lines == 1) + tab = malloc(sizeof(*tab) * 2); + else + tab = realloc(tab, (lines + 1) * sizeof(*tab)); + tab[lines - 1].host = strdup(line); + s = strchr(tab[lines - 1].host, '/'); + *s++ = '\0'; + tab[lines - 1].mask = s; + tab[lines - 1].what = "d"; + } + fclose(fp); + + tab[lines].host = NULL; + tab[lines].mask = NULL; + tab[lines].what = NULL; + ttable = tab; +} + + +void +printroots(rnh) + ipf_rdx_head_t *rnh; +{ + printf("Root.0.%s b %3d p %-9.9s l %-9.9s r %-9.9s\n", + GNAME(&rnh->nodes[0]), + rnh->nodes[0].index, GNAME(rnh->nodes[0].parent), + GNAME(rnh->nodes[0].left), GNAME(rnh->nodes[0].right)); + printf("Root.1.%s b %3d p %-9.9s l %-9.9s r %-9.9s\n", + GNAME(&rnh->nodes[1]), + rnh->nodes[1].index, GNAME(rnh->nodes[1].parent), + GNAME(rnh->nodes[1].left), GNAME(rnh->nodes[1].right)); + printf("Root.2.%s b %3d p %-9.9s l %-9.9s r %-9.9s\n", + GNAME(&rnh->nodes[2]), + rnh->nodes[2].index, GNAME(rnh->nodes[2].parent), + GNAME(rnh->nodes[2].left), GNAME(rnh->nodes[2].right)); +} + + +int +main(int argc, char *argv[]) +{ + addrfamily_t af; + ipf_rdx_head_t *rnh; + radix_softc_t *ctx; + int j; + int i; + + rnh = NULL; + + buildtab(); + ctx = ipf_rx_create(); + ipf_rx_init(ctx); + ipf_rx_inithead(ctx, &rnh); + + printf("=== ADD-0 ===\n"); + for (i = 0; ttable[i].host != NULL; i++) { + add_addr(rnh, i, i); + checktree(rnh); + } + printroots(rnh); + ipf_rx_walktree(rnh, nodeprinter, NULL); + printf("=== DELETE-0 ===\n"); + for (i = 0; ttable[i].host != NULL; i++) { + delete_addr(rnh, i); + printroots(rnh); + ipf_rx_walktree(rnh, nodeprinter, NULL); + } + printf("=== ADD-1 ===\n"); + for (i = 0; ttable[i].host != NULL; i++) { + setaddr(&af, ttable[i].host); + add_addr(rnh, i, i); /*forder[i]); */ + checktree(rnh); + } + dumptree(rnh); + ipf_rx_walktree(rnh, nodeprinter, NULL); + printf("=== TEST-1 ===\n"); + for (i = 0; ttable[i].host != NULL; i++) { + setaddr(&af, ttable[i].host); + test_addr(rnh, i, &af, -1); + } + + printf("=== TEST-2 ===\n"); + for (i = 0; mtable[i][0] != NULL; i++) { + setaddr(&af, mtable[i][0]); + test_addr(rnh, i, &af, -1); + } + printf("=== DELETE-1 ===\n"); + for (i = 0; ttable[i].host != NULL; i++) { + if (ttable[i].what[0] != 'd') + continue; + delete_addr(rnh, i); + for (j = 0; ttable[j].host != NULL; j++) { + setaddr(&af, ttable[j].host); + test_addr(rnh, i, &af, 3); + } + printroots(rnh); + ipf_rx_walktree(rnh, nodeprinter, NULL); + } + + dumptree(rnh); + + printf("=== ADD-2 ===\n"); + random_add(rnh); + checktree(rnh); + dumptree(rnh); + ipf_rx_walktree(rnh, nodeprinter, NULL); + printf("=== DELETE-2 ===\n"); + random_delete(rnh); + checktree(rnh); + dumptree(rnh); + + ipf_rx_walktree(rnh, ipf_rx_freenode, rnh); + + return 0; +} + + +void +dumptree(rnh) + ipf_rdx_head_t *rnh; +{ + myst_t *stp; + + printf("VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV\n"); + printroots(rnh); + for (stp = myst_top; stp; stp = stp->next) + printnode(stp); + printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"); +} + + +void +test_addr(rnh, pref, addr, limit) + ipf_rdx_head_t *rnh; + int pref; + addrfamily_t *addr; +{ + static int extras[14] = { 0, -1, 1, 3, 5, 8, 9, + 15, 16, 19, 255, 256, 65535, 65536 + }; + ipf_rdx_node_t *rn; + addrfamily_t af; + char name[80]; + myst_t *stp; + int i; + + memset(&af, 0, sizeof(af)); +#if 0 + if (limit < 0 || limit > 14) + limit = 14; + + for (i = 0; i < limit; i++) { + if (ttable[i].host == NULL) + break; + setaddr(&af, ttable[i].host); + printf("%d.%d.LOOKUP(%s)", pref, i, addrname(&af)); + rn = ipf_rx_match(rnh, &af); + stp = (myst_t *)rn; + printf(" = %s (%s/%d)\n", GNAME(rn), + rn ? addrname(&stp->dst) : "NULL", + rn ? rn->maskbitcount : 0); + } +#else + printf("%d.%d.LOOKUP(%s)", pref, -1, addrname(addr)); + rn = ipf_rx_match(rnh, addr); + stp = (myst_t *)rn; + printf(" = %s (%s/%d)\n", GNAME(rn), + rn ? addrname(&stp->dst) : "NULL", rn ? rn->maskbitcount : 0); +#endif +} + + +void +delete_addr(rnh, item) + ipf_rdx_head_t *rnh; + int item; +{ + ipf_rdx_node_t *rn; + addrfamily_t mask; + addrfamily_t af; + myst_t **pstp; + myst_t *stp; + + memset(&af, 0, sizeof(af)); + memset(&mask, 0, sizeof(mask)); + setaddr(&af, ttable[item].host); + mask.adf_family = af.adf_family; + setmask(&mask, ttable[item].mask); + + printf("DELETE(%s)\n", addrname(&af)); + rn = ipf_rx_delete(rnh, &af, &mask); + if (rn == NULL) { + printf("FAIL LOOKUP DELETE\n"); + checktree(rnh); + for (stp = myst_top; stp != NULL; stp = stp->next) + if (stp->printed != -1) + stp->printed = -2; + ipf_rx_walktree(rnh, nodeprinter, NULL); + dumptree(rnh); + abort(); + } + printf("%d.delete(%s) = %s\n", item, addrname(&af), GNAME(rn)); + + for (pstp = &myst_top; (stp = *pstp) != NULL; pstp = &stp->next) + if (stp == (myst_t *)rn) + break; + stp->printed = -1; + stp->nodes[0].parent = &stp->nodes[0]; + stp->nodes[1].parent = &stp->nodes[1]; + *pstp = stp->next; + free(stp); + nodecount--; + checktree(rnh); +} + + +void +add_addr(rnh, n, item) + ipf_rdx_head_t *rnh; + int n, item; +{ + ipf_rdx_node_t *rn; + myst_t *stp; + + stp = calloc(1, sizeof(*stp)); + rn = (ipf_rdx_node_t *)stp; + setaddr(&stp->dst, ttable[item].host); + stp->mask.adf_family = stp->dst.adf_family; + setmask(&stp->mask, ttable[item].mask); + stp->next = myst_top; + myst_top = stp; + (void) sprintf(rn[0].name, "_BORN.0"); + (void) sprintf(rn[1].name, "_BORN.1"); + rn = ipf_rx_addroute(rnh, &stp->dst, &stp->mask, stp->nodes); + (void) sprintf(rn[0].name, "%d_NODE.0", item); + (void) sprintf(rn[1].name, "%d_NODE.1", item); + printf("ADD %d/%d %s/%s\n", n, item, rn[0].name, rn[1].name); + nodecount++; + checktree(rnh); +} + + +void +checktree(ipf_rdx_head_t *head) +{ + myst_t *s1; + ipf_rdx_node_t *rn; + + if (nodecount <= 1) + return; + + for (s1 = myst_top; s1 != NULL; s1 = s1->next) { + int fault = 0; + if (s1->printed == -1) + continue; + rn = &s1->nodes[1]; + if (rn->right->parent != rn) + fault |= 1; + if (rn->left->parent != rn) + fault |= 2; + if (rn->parent->left != rn && rn->parent->right != rn) + fault |= 4; + if (fault != 0) { + printf("FAULT %#x %s\n", fault, rn->name); + dumptree(head); + ipf_rx_walktree(head, nodeprinter, NULL); + fflush(stdout); + fflush(stderr); + printf("--\n"); + abort(); + } + } +} + + +int * +randomize(int *pnitems) +{ + int *order; + int nitems; + int choice; + int j; + int i; + + nitems = sizeof(ttable) / sizeof(ttable[0]); + *pnitems = nitems; + order = calloc(nitems, sizeof(*order)); + srandom(getpid() * time(NULL)); + memset(order, 0xff, nitems * sizeof(*order)); + order[21] = 21; + for (i = 0; i < nitems - 1; i++) { + do { + choice = rand() % (nitems - 1); + for (j = 0; j < nitems; j++) + if (order[j] == choice) + break; + } while (j != nitems); + order[i] = choice; + } + + return order; +} + + +void +random_add(rnh) + ipf_rdx_head_t *rnh; +{ + int *order; + int nitems; + int i; + + order = randomize(&nitems); + + for (i = 0; i < nitems - 1; i++) { + add_addr(rnh, i, order[i]); + checktree(rnh); + } +} + + +void +random_delete(rnh) + ipf_rdx_head_t *rnh; +{ + int *order; + int nitems; + int i; + + order = randomize(&nitems); + + for (i = 0; i < nitems - 1; i++) { + delete_addr(rnh, i); + checktree(rnh); + } +} +#endif /* RDX_DEBUG */ diff --git a/radix_ipf.h b/radix_ipf.h index f9b0a3077de9c..73e66b0aa1691 100644 --- a/radix_ipf.h +++ b/radix_ipf.h @@ -1,212 +1,95 @@ /* - * Copyright (c) 1988, 1989, 1993 - * The Regents of the University of California. All rights reserved. + * Copyright (C) 2012 by Darren Reed. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)radix.h 8.2 (Berkeley) 10/31/94 + * See the IPFILTER.LICENCE file for details on licencing. */ +#ifndef __RADIX_IPF_H__ +#define __RADIX_IPF_H__ -#if !defined(_NET_RADIX_H_) && !defined(_RADIX_H_) -#define _NET_RADIX_H_ -#ifndef _RADIX_H_ -#define _RADIX_H_ -#endif /* _RADIX_H_ */ - -#ifndef __P -# ifdef __STDC__ -# define __P(x) x -# else -# define __P(x) () -# endif +#ifndef U_32_T +typedef unsigned int u_32_t; +# define U_32_T 1 #endif -#if defined(__sgi) || defined(__osf__) || defined(sun) -# define radix_mask ipf_radix_mask -# define radix_node ipf_radix_node -# define radix_node_head ipf_radix_node_head -#endif - -/* - * Radix search tree node layout. - */ - -struct radix_node { - struct radix_mask *rn_mklist; /* list of masks contained in subtree */ - struct radix_node *rn_p; /* parent */ - short rn_b; /* bit offset; -1-index(netmask) */ - char rn_bmask; /* node: mask for bit test*/ - u_char rn_flags; /* enumerated next */ -#define RNF_NORMAL 1 /* leaf contains normal route */ -#define RNF_ROOT 2 /* leaf is root leaf for tree */ -#define RNF_ACTIVE 4 /* This node is alive (for rtfree) */ - union { - struct { /* leaf only data: */ - caddr_t rn_Key; /* object of search */ - caddr_t rn_Mask; /* netmask, if present */ - struct radix_node *rn_Dupedkey; - } rn_leaf; - struct { /* node only data: */ - int rn_Off; /* where to start compare */ - struct radix_node *rn_L;/* progeny */ - struct radix_node *rn_R;/* progeny */ - } rn_node; - } rn_u; -#ifdef RN_DEBUG - int rn_info; - struct radix_node *rn_twin; - struct radix_node *rn_ybro; +typedef struct ipf_rdx_mask { + struct ipf_rdx_mask *next; + struct ipf_rdx_node *node; + u_32_t *mask; + int maskbitcount; +} ipf_rdx_mask_t; + +typedef struct ipf_rdx_node { + struct ipf_rdx_node *left; + struct ipf_rdx_node *right; + struct ipf_rdx_node *parent; + struct ipf_rdx_node *dupkey; + struct ipf_rdx_mask *masks; + struct ipf_rdx_mask *mymask; + u_32_t *addrkey; + u_32_t *maskkey; + u_32_t *addroff; + u_32_t *maskoff; + u_32_t lastmask; + u_32_t bitmask; + int offset; + int index; + int maskbitcount; + int root; +#ifdef RDX_DEBUG + char name[40]; #endif -}; - -#define rn_dupedkey rn_u.rn_leaf.rn_Dupedkey -#define rn_key rn_u.rn_leaf.rn_Key -#define rn_mask rn_u.rn_leaf.rn_Mask -#define rn_off rn_u.rn_node.rn_Off -#define rn_l rn_u.rn_node.rn_L -#define rn_r rn_u.rn_node.rn_R - -/* - * Annotations to tree concerning potential routes applying to subtrees. - */ - -struct radix_mask { - short rm_b; /* bit offset; -1-index(netmask) */ - char rm_unused; /* cf. rn_bmask */ - u_char rm_flags; /* cf. rn_flags */ - struct radix_mask *rm_mklist; /* more masks to try */ - union { - caddr_t rmu_mask; /* the mask */ - struct radix_node *rmu_leaf; /* for normal routes */ - } rm_rmu; - int rm_refs; /* # of references to this struct */ -}; - -#define rm_mask rm_rmu.rmu_mask -#define rm_leaf rm_rmu.rmu_leaf /* extra field would make 32 bytes */ - -#define MKGet(m) {\ - if (rn_mkfreelist) {\ - m = rn_mkfreelist; \ - rn_mkfreelist = (m)->rm_mklist; \ - } else \ - R_Malloc(m, struct radix_mask *, sizeof (*(m))); }\ - -#define MKFree(m) { (m)->rm_mklist = rn_mkfreelist; rn_mkfreelist = (m);} - -struct radix_node_head { - struct radix_node *rnh_treetop; - struct radix_node *rnh_leaflist; - u_long rnh_hits; - u_int rnh_number; - u_int rnh_ref; - int rnh_addrsize; /* permit, but not require fixed keys */ - int rnh_pktsize; /* permit, but not require fixed keys */ - struct radix_node *(*rnh_addaddr) /* add based on sockaddr */ - __P((void *v, void *mask, - struct radix_node_head *head, struct radix_node nodes[])); - struct radix_node *(*rnh_addpkt) /* add based on packet hdr */ - __P((void *v, void *mask, - struct radix_node_head *head, struct radix_node nodes[])); - struct radix_node *(*rnh_deladdr) /* remove based on sockaddr */ - __P((void *v, void *mask, struct radix_node_head *head)); - struct radix_node *(*rnh_delpkt) /* remove based on packet hdr */ - __P((void *v, void *mask, struct radix_node_head *head)); - struct radix_node *(*rnh_matchaddr) /* locate based on sockaddr */ - __P((void *v, struct radix_node_head *head)); - struct radix_node *(*rnh_lookup) /* locate based on sockaddr */ - __P((void *v, void *mask, struct radix_node_head *head)); - struct radix_node *(*rnh_matchpkt) /* locate based on packet hdr */ - __P((void *v, struct radix_node_head *head)); - int (*rnh_walktree) /* traverse tree */ - __P((struct radix_node_head *, - int (*)(struct radix_node *, void *), void *)); - struct radix_node rnh_nodes[3]; /* empty tree for common case */ -}; - - -#if defined(AIX) -# undef Bcmp -# undef Bzero -# undef R_Malloc -# undef Free -#endif -#define Bcmp(a, b, n) bcmp(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n)) -#if defined(linux) && defined(_KERNEL) -# define Bcopy(a, b, n) memmove(((caddr_t)(b)), ((caddr_t)(a)), (unsigned)(n)) +} ipf_rdx_node_t; + +struct ipf_rdx_head; + +typedef void (* radix_walk_func_t)(ipf_rdx_node_t *, void *); +typedef ipf_rdx_node_t *(* idx_hamn_func_t)(struct ipf_rdx_head *, + addrfamily_t *, addrfamily_t *, + ipf_rdx_node_t *); +typedef ipf_rdx_node_t *(* idx_ham_func_t)(struct ipf_rdx_head *, + addrfamily_t *, addrfamily_t *); +typedef ipf_rdx_node_t *(* idx_ha_func_t)(struct ipf_rdx_head *, + addrfamily_t *); +typedef void (* idx_walk_func_t)(struct ipf_rdx_head *, + radix_walk_func_t, void *); + +typedef struct ipf_rdx_head { + ipf_rdx_node_t *root; + ipf_rdx_node_t nodes[3]; + ipfmutex_t lock; + idx_hamn_func_t addaddr; /* add addr/mask to tree */ + idx_ham_func_t deladdr; /* delete addr/mask from tree */ + idx_ham_func_t lookup; /* look for specific addr/mask */ + idx_ha_func_t matchaddr; /* search tree for address match */ + idx_walk_func_t walktree; /* walk entire tree */ +} ipf_rdx_head_t; + +typedef struct radix_softc { + u_char *zeros; + u_char *ones; +} radix_softc_t; + +#undef RADIX_NODE_HEAD_LOCK +#undef RADIX_NODE_HEAD_UNLOCK +#ifdef _KERNEL +# define RADIX_NODE_HEAD_LOCK(x) MUTEX_ENTER(&(x)->lock) +# define RADIX_NODE_HEAD_UNLOCK(x) MUTEX_UNLOCK(&(x)->lock) #else -# define Bcopy(a, b, n) bcopy(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n)) +# define RADIX_NODE_HEAD_LOCK(x) +# define RADIX_NODE_HEAD_UNLOCK(x) #endif -#define Bzero(p, n) bzero((caddr_t)(p), (unsigned)(n)); -#define R_Malloc(p, t, n) KMALLOCS(p, t, n) -#define FreeS(p, z) KFREES(p, z) -#define Free(p) KFREE(p) - -#if (defined(__osf__) || defined(AIX) || (IRIX >= 60516) || defined(sun)) && defined(_KERNEL) -# define rn_init ipf_rn_init -# define rn_fini ipf_rn_fini -# define rn_inithead ipf_rn_inithead -# define rn_freehead ipf_rn_freehead -# define rn_inithead0 ipf_rn_inithead0 -# define rn_refines ipf_rn_refines -# define rn_walktree ipf_rn_walktree -# define rn_addmask ipf_rn_addmask -# define rn_addroute ipf_rn_addroute -# define rn_delete ipf_rn_delete -# define rn_insert ipf_rn_insert -# define rn_lookup ipf_rn_lookup -# define rn_match ipf_rn_match -# define rn_newpair ipf_rn_newpair -# define rn_search ipf_rn_search -# define rn_search_m ipf_rn_search_m -# define max_keylen ipf_maxkeylen -# define rn_mkfreelist ipf_rn_mkfreelist -# define rn_zeros ipf_rn_zeros -# define rn_ones ipf_rn_ones -# define rn_satisfies_leaf ipf_rn_satisfies_leaf -# define rn_lexobetter ipf_rn_lexobetter -# define rn_new_radix_mask ipf_rn_new_radix_mask -# define rn_freenode ipf_rn_freenode -#endif - -void rn_init __P((void)); -void rn_fini __P((void)); -int rn_inithead __P((void **, int)); -void rn_freehead __P((struct radix_node_head *)); -int rn_inithead0 __P((struct radix_node_head *, int)); -int rn_refines __P((void *, void *)); -int rn_walktree __P((struct radix_node_head *, - int (*)(struct radix_node *, void *), void *)); -struct radix_node - *rn_addmask __P((void *, int, int)), - *rn_addroute __P((void *, void *, struct radix_node_head *, - struct radix_node [2])), - *rn_delete __P((void *, void *, struct radix_node_head *)), - *rn_insert __P((void *, struct radix_node_head *, int *, - struct radix_node [2])), - *rn_lookup __P((void *, void *, struct radix_node_head *)), - *rn_match __P((void *, struct radix_node_head *)), - *rn_newpair __P((void *, int, struct radix_node[2])), - *rn_search __P((void *, struct radix_node *)), - *rn_search_m __P((void *, struct radix_node *, void *)); -#endif /* _NET_RADIX_H_ */ +extern void *ipf_rx_create __P((void)); +extern int ipf_rx_init __P((void *)); +extern void ipf_rx_destroy __P((void *)); +extern int ipf_rx_inithead __P((radix_softc_t *, ipf_rdx_head_t **)); +extern void ipf_rx_freehead __P((ipf_rdx_head_t *)); +extern ipf_rdx_node_t *ipf_rx_addroute __P((ipf_rdx_head_t *, + addrfamily_t *, addrfamily_t *, + ipf_rdx_node_t *)); +extern ipf_rdx_node_t *ipf_rx_delete __P((ipf_rdx_head_t *, addrfamily_t *, + addrfamily_t *)); +extern void ipf_rx_walktree __P((ipf_rdx_head_t *, radix_walk_func_t, + void *)); + +#endif /* __RADIX_IPF_H__ */ diff --git a/relay.c b/relay.c deleted file mode 100644 index 6a67433c61a91..0000000000000 --- a/relay.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Sample program to be used as a transparent proxy. - * - * Must be executed with permission enough to do an ioctl on /dev/ipl - * or equivalent. This is just a sample and is only alpha quality. - * - Darren Reed (8 April 1996) - */ -#include <unistd.h> -#include <stdio.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/time.h> -#include <sys/errno.h> -#include <sys/syslog.h> -#include <sys/ioctl.h> -#include <netinet/in.h> -#include <net/if.h> -#include <sys/socket.h> -#if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105000000) -# include <poll.h> -# define USE_POLL -#endif -#include "ip_nat.h" - -#define RELAY_BUFSZ 8192 - -char ibuff[RELAY_BUFSZ]; -char obuff[RELAY_BUFSZ]; - -int relay(ifd, ofd, rfd) -int ifd, ofd, rfd; -{ -#ifdef USE_POLL - struct pollfd set[3]; -#else - fd_set rfds, wfds; -#endif - char *irh, *irt, *rrh, *rrt; - char *iwh, *iwt, *rwh, *rwt; - int nfd, n, rw; - - irh = irt = ibuff; - iwh = iwt = obuff; - nfd = ifd; - if (nfd < ofd) - nfd = ofd; - if (nfd < rfd) - nfd = rfd; - -#ifdef USE_POLL - set[0].fd = rfd; - set[1].fd = ifd; - set[2].fd = ofd; -#endif - - while (1) { -#ifdef USE_POLL - set[0].events = (iwh < (obuff + RELAY_BUFSZ) ? POLLIN : 0) | - (irh > irt ? POLLOUT : 0); - set[1].events = (irh < (ibuff + RELAY_BUFSZ) ? POLLIN : 0); - set[2].events = (iwh > iwt ? POLLOUT : 0); - - switch ((n = poll(set, 3, INFTIM))) -#else - FD_ZERO(&rfds); - FD_ZERO(&wfds); - if (irh > irt) - FD_SET(rfd, &wfds); - if (irh < (ibuff + RELAY_BUFSZ)) - FD_SET(ifd, &rfds); - if (iwh > iwt) - FD_SET(ofd, &wfds); - if (iwh < (obuff + RELAY_BUFSZ)) - FD_SET(rfd, &rfds); - - switch ((n = select(nfd + 1, &rfds, &wfds, NULL, NULL))) -#endif - { - case -1 : - case 0 : - return -1; - default : -#ifdef USE_POLL - if (set[1].revents & POLLIN) -#else - if (FD_ISSET(ifd, &rfds)) -#endif - { - rw = read(ifd, irh, ibuff + RELAY_BUFSZ - irh); - if (rw == -1) - return -1; - if (rw == 0) - return 0; - irh += rw; - n--; - } -#ifdef USE_POLL - if (set[2].revents & POLLOUT) -#else - if (n && FD_ISSET(ofd, &wfds)) -#endif - { - rw = write(ofd, iwt, iwh - iwt); - if (rw == -1) - return -1; - iwt += rw; - n--; - } -#ifdef USE_POLL - if (set[0].revents & POLLIN) -#else - if (n && FD_ISSET(rfd, &rfds)) -#endif - { - rw = read(rfd, iwh, obuff + RELAY_BUFSZ - iwh); - if (rw == -1) - return -1; - if (rw == 0) - return 0; - iwh += rw; - n--; - } -#ifdef USE_POLL - if (set[0].revents & POLLOUT) -#else - if (n && FD_ISSET(rfd, &wfds)) -#endif - { - rw = write(rfd, irt, irh - irt); - if (rw == -1) - return -1; - irt += rw; - n--; - } - if (irh == irt) - irh = irt = ibuff; - if (iwh == iwt) - iwh = iwt = obuff; - } - } -} - -main(argc, argv) -int argc; -char *argv[]; -{ - struct sockaddr_in sin; - natlookup_t nl; - natlookup_t *nlp = &nl; - int fd, sl = sizeof(sl), se; - - openlog(argv[0], LOG_PID|LOG_NDELAY, LOG_DAEMON); - if ((fd = open("/dev/ipnat", O_RDONLY)) == -1) { - se = errno; - perror("open"); - errno = se; - syslog(LOG_ERR, "open: %m\n"); - exit(-1); - } - - bzero(&nl, sizeof(nl)); - nl.nl_flags = IPN_TCP; - - bzero(&sin, sizeof(sin)); - sin.sin_family = AF_INET; - sl = sizeof(sin); - if (getsockname(0, (struct sockaddr *)&sin, &sl) == -1) { - se = errno; - perror("getsockname"); - errno = se; - syslog(LOG_ERR, "getsockname: %m\n"); - exit(-1); - } else { - nl.nl_inip.s_addr = sin.sin_addr.s_addr; - nl.nl_inport = sin.sin_port; - } - - bzero(&sin, sizeof(sin)); - sin.sin_family = AF_INET; - sl = sizeof(sin); - if (getpeername(0, (struct sockaddr *)&sin, &sl) == -1) { - se = errno; - perror("getpeername"); - errno = se; - syslog(LOG_ERR, "getpeername: %m\n"); - exit(-1); - } else { - nl.nl_outip.s_addr = sin.sin_addr.s_addr; - nl.nl_outport = sin.sin_port; - } - - if (ioctl(fd, SIOCGNATL, &nlp) == -1) { - se = errno; - perror("ioctl"); - errno = se; - syslog(LOG_ERR, "ioctl: %m\n"); - exit(-1); - } - - sin.sin_port = nl.nl_realport; - sin.sin_addr = nl.nl_realip; - sl = sizeof(sin); - - fd = socket(AF_INET, SOCK_STREAM, 0); - if (connect(fd, (struct sockaddr *)&sin, sl) == -1) { - se = errno; - perror("connect"); - errno = se; - syslog(LOG_ERR, "connect: %m\n"); - exit(-1); - } - - (void) ioctl(fd, F_SETFL, ioctl(fd, F_GETFL, 0)|O_NONBLOCK); - (void) ioctl(0, F_SETFL, ioctl(fd, F_GETFL, 0)|O_NONBLOCK); - (void) ioctl(1, F_SETFL, ioctl(fd, F_GETFL, 0)|O_NONBLOCK); - - syslog(LOG_NOTICE, "connected to %s,%d\n", inet_ntoa(sin.sin_addr), - ntohs(sin.sin_port)); - if (relay(0, 1, fd) == -1) { - se = errno; - perror("relay"); - errno = se; - syslog(LOG_ERR, "relay: %m\n"); - exit(-1); - } - exit(0); -} diff --git a/rules/.cvsignore b/rules/.cvsignore deleted file mode 100644 index 3e757656cf36e..0000000000000 --- a/rules/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -new diff --git a/rules/BASIC_1.FW b/rules/BASIC_1.FW index d2bd60a318895..642dde061efdc 100644 --- a/rules/BASIC_1.FW +++ b/rules/BASIC_1.FW @@ -22,10 +22,10 @@ block in log quick all with short # (especially for ed0) and needs to be further refined. # block in log on ppp0 all head 100 -block in log proto tcp all flags S/SA head 101 group 100 +block in log proto tcp all flags S/SA head 101 group 100 block out log on ppp0 all head 150 block in log on ed0 from w.x.y.z/24 to any head 200 -block in log proto tcp all flags S/SA head 201 group 200 +block in log proto tcp all flags S/SA head 201 group 200 block in log proto udp all head 202 group 200 block out log on ed0 all head 250 #------------------------------------------------------- diff --git a/rules/BASIC_2.FW b/rules/BASIC_2.FW index 46564f0ee412c..1d4fd73176735 100644 --- a/rules/BASIC_2.FW +++ b/rules/BASIC_2.FW @@ -56,7 +56,7 @@ pass out quick on lo0 all # # Allow all outgoing connections (SSH, TELNET, FTP, WWW, gopher, etc) # -pass in log quick proto tcp all flags S/SA keep state group 200 +pass in log quick proto tcp all flags S/SA keep state group 200 # # Support all UDP `connections' initiated from inside. # diff --git a/rules/firewall b/rules/firewall index 681a81da20b6b..f26b7150b98ca 100644 --- a/rules/firewall +++ b/rules/firewall @@ -31,7 +31,7 @@ where closest to your internal network in terms of network hops. * "int-net" is the internal network IP# subnet address range. This might - be something like 10.1.0.0/16, or 128.33.1.0/24 + be something like 10.1.0.0/16, or 128.33.1.0/24 * "ext-service" is the service to which you wish to connect or if it doesn't have a proper name, a number can be used. The translation of "ext-service" diff --git a/rules/ipmon.conf b/rules/ipmon.conf index 47b01463575c1..652afceb3ea14 100644 --- a/rules/ipmon.conf +++ b/rules/ipmon.conf @@ -2,23 +2,24 @@ # # # -match { logtag = 10000 } - do { execute "/usr/bin/mail -s 'logtag 10000' root" }; -match { logtag = 2000, every 10 seconds } - do { execute "echo 'XXXXXXXX tag 2000 packet XXXXXXXX'" }; +match { logtag = 10000; } +do { execute("/usr/bin/mail -s 'logtag 10000' root"); }; # -match { protocol = udp, result = block } - do { execute "/usr/bin/mail -s 'blocked udp' root" -}; +match { logtag = 2000, every 10 seconds; } +do { execute("echo 'XXXXXXXX tag 2000 packet XXXXXXXX'"); }; # -match { - srcip = 10.1.0.0/16, dstip = 192.168.1.0/24 } - do { execute "/usr/bin/mail -s 'from 10.1 to 192.168.1' root" -}; +match { protocol = udp, result = block; } +do { file("file:///var/log/udp-block"); }; +# +match { protocol = tcp, result = block, dstport = 25; } +do { syslog("local0.info"), syslog("local1."), syslog(".warn"); }; +# +match { srcip = 10.1.0.0/16, dstip = 192.168.1.0/24; } +do { execute("/usr/bin/mail -s 'from 10.1 to 192.168.1' root"); }; + # match { rule = 12, logtag = 101, direction = in, result = block, - protocol = udp, srcip = 10.1.0.0/16, dstip = 192.168.1.0/24 } - do { execute "run shell command" -}; + protocol = udp, srcip = 10.1.0.0/16, dstip = 192.168.1.0/24; } +do { nothing; }; # diff --git a/rules/rules.sed b/rules/rules.sed deleted file mode 100644 index 050d9b6ab7103..0000000000000 --- a/rules/rules.sed +++ /dev/null @@ -1,5 +0,0 @@ -WÆ. Ä..'&CVSWÜ example.1WÝ -example.10WÞ -example.11Wß -example.12Wà -example.13Wá example.2Wâ example.3Wã example.4Wä example.5Wå example.6Wæ example.7Wç example.8Wè example.9Wé diff --git a/rules/server b/rules/server index f2fb2041faf0f..de0e9bbd06d86 100644 --- a/rules/server +++ b/rules/server @@ -3,7 +3,7 @@ # 128.1.2.1 (le1), we want to block all IP spoofing attacks. le1 is # connected to the majority of the network, whilst le0 is connected to a # leaf subnet. We're not concerned about filtering individual services -# or +# or # pass in quick on le0 from 128.1.40.0/24 to any block in log quick on le0 from any to any diff --git a/samples/.cvsignore b/samples/.cvsignore deleted file mode 100644 index 4d38251c2f4f9..0000000000000 --- a/samples/.cvsignore +++ /dev/null @@ -1,4 +0,0 @@ -userauth -proxy -relay -trans_relay diff --git a/samples/proxy.c b/samples/proxy.c index f2063ecde8138..1dfe8653dbe06 100644 --- a/samples/proxy.c +++ b/samples/proxy.c @@ -49,8 +49,8 @@ main(argc, argv) -int argc; -char *argv[]; + int argc; + char *argv[]; { struct sockaddr_in sin, sloc, sout; ipfobj_t obj; @@ -130,9 +130,9 @@ char *argv[]; #ifdef DO_NAT_OUT do_nat_out(in, out, fd, nlp, extif) -int fd; -natlookup_t *nlp; -char *extif; + int fd; + natlookup_t *nlp; + char *extif; { nat_save_t ns, *nsp = &ns; struct sockaddr_in usin; @@ -226,7 +226,7 @@ fflush(stdout); relay(in, out, net) -int in, out, net; + int in, out, net; { char netbuf[1024], outbuf[1024]; char *nwptr, *nrptr, *owptr, *orptr; diff --git a/samples/relay.c b/samples/relay.c index 6b96fc42f613c..281e058e76638 100644 --- a/samples/relay.c +++ b/samples/relay.c @@ -27,7 +27,7 @@ char ibuff[RELAY_BUFSZ]; char obuff[RELAY_BUFSZ]; int relay(ifd, ofd, rfd) -int ifd, ofd, rfd; + int ifd, ofd, rfd; { fd_set rfds, wfds; char *irh, *irt, *rrh, *rrt; @@ -101,8 +101,8 @@ int ifd, ofd, rfd; } main(argc, argv) -int argc; -char *argv[]; + int argc; + char *argv[]; { struct sockaddr_in sin; ipfobj_t obj; @@ -1,5 +1,5 @@ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -9,7 +9,7 @@ /* * written to comply with the RFC (1761) from Sun. - * $Id: snoop.h,v 2.3 2001/06/09 17:09:23 darrenr Exp $ + * $Id$ */ struct snoophdr { char s_id[8]; diff --git a/solaris.c b/solaris.c index aa139d3b042aa..c46f3345cb47f 100644 --- a/solaris.c +++ b/solaris.c @@ -1,10 +1,10 @@ /* - * Copyright (C) 1993-2002 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ /* #pragma ident "@(#)solaris.c 1.12 6/5/96 (C) 1995 Darren Reed"*/ -#pragma ident "@(#)$Id: solaris.c,v 2.15.2.30 2002/04/23 14:57:51 darrenr Exp $" +#pragma ident "@(#)$Id$" #include <sys/systm.h> #include <sys/types.h> @@ -45,80 +45,62 @@ #include <netinet/ip_icmp.h> #include <sys/ddi.h> #include <sys/sunddi.h> -#include "ip_compat.h" -#include "ipl.h" -#include "ip_fil.h" -#include "ip_nat.h" -#include "ip_state.h" - - -char _depends_on[] = "drv/ip"; - - -void solipdrvattach __P((void)); -int solipdrvdetach __P((void)); - -void solattach __P((void)); -int soldetach __P((void)); - -extern struct filterstats frstats[]; -extern KRWLOCK_T ipf_mutex, ipfs_mutex, ipf_nat, ipf_solaris; -extern kmutex_t ipf_rw; -extern int fr_running; -extern int fr_flags; +#include "netinet/ip_compat.h" +#include "netinet/ipl.h" +#include "netinet/ip_fil.h" +#include "netinet/ip_nat.h" +#include "netinet/ip_frag.h" +#include "netinet/ip_auth.h" +#include "netinet/ip_state.h" +#include "netinet/ip_sync.h" +#include "netinet/ip_lookup.h" +#ifdef INSTANCES +# include <sys/hook_event.h> +#endif -extern ipnat_t *nat_list; +extern void ipf_rand_push(void *, int); -static qif_t *qif_head = NULL; static int ipf_getinfo __P((dev_info_t *, ddi_info_cmd_t, void *, void **)); -static int ipf_probe __P((dev_info_t *)); +#if SOLARIS2 < 10 static int ipf_identify __P((dev_info_t *)); +#endif static int ipf_attach __P((dev_info_t *, ddi_attach_cmd_t)); static int ipf_detach __P((dev_info_t *, ddi_detach_cmd_t)); -static qif_t *qif_from_queue __P((queue_t *)); -static void fr_donotip __P((int, qif_t *, queue_t *, mblk_t *, - mblk_t *, ip_t *, size_t)); -static char *ipf_devfiles[] = { IPL_NAME, IPL_NAT, IPL_STATE, IPL_AUTH, - NULL }; -static int (*ipf_ip_inp) __P((queue_t *, mblk_t *)) = NULL; - - -#if SOLARIS2 >= 7 -extern void ipfr_slowtimer __P((void *)); -timeout_id_t ipfr_timer_id; -static timeout_id_t synctimeoutid = 0; +static int ipf_detach_instance __P((ipf_main_softc_t *)); +static int ipfpoll __P((dev_t, short, int, short *, struct pollhead **)); +static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, + IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME, + IPLOOKUP_NAME, NULL }; +static int ipfclose __P((dev_t, int, int, cred_t *)); +static int ipfopen __P((dev_t *, int, int, cred_t *)); +static int ipfread __P((dev_t, struct uio *, cred_t *)); +static int ipfwrite __P((dev_t, struct uio *, cred_t *)); +static int ipf_property_update __P((dev_info_t *)); +static int ipf_solaris_init __P((void)); +static int ipf_stack_init __P((void)); +static void ipf_stack_fini __P((void)); +#if !defined(INSTANCES) +static int ipf_qifsync __P((ip_t *, int, void *, int, void *, mblk_t **)); #else -extern void ipfr_slowtimer __P((void)); -int ipfr_timer_id; -static int synctimeoutid = 0; +static void ipf_attach_loopback __P((ipf_main_softc_t *)); +static void ipf_detach_loopback __P((ipf_main_softc_t *)); #endif -int ipf_debug = 0; -int ipf_debug_verbose = 0; - -/* #undef IPFDEBUG 1 */ -/* #undef IPFDEBUG_VERBOSE 1 */ -#ifdef IPFDEBUG -void printire __P((ire_t *)); -#endif -#define isdigit(x) ((x) >= '0' && (x) <= '9') - -static int fr_precheck __P((mblk_t **, queue_t *, qif_t *, int)); static struct cb_ops ipf_cb_ops = { - iplopen, - iplclose, + ipfopen, + ipfclose, nodev, /* strategy */ nodev, /* print */ nodev, /* dump */ - iplread, - nodev, /* write */ - iplioctl, /* ioctl */ + ipfread, + ipfwrite, /* write */ + ipfioctl, /* ioctl */ nodev, /* devmap */ nodev, /* mmap */ nodev, /* segmap */ - nochpoll, /* poll */ + ipfpoll, /* poll */ ddi_prop_op, NULL, D_MTSAFE, @@ -133,8 +115,12 @@ static struct dev_ops ipf_ops = { DEVO_REV, 0, ipf_getinfo, +#if SOLARIS2 >= 10 + nulldev, +#else ipf_identify, - ipf_probe, +#endif + nulldev, ipf_attach, ipf_detach, nodev, /* reset */ @@ -146,17 +132,18 @@ extern struct mod_ops mod_driverops; static struct modldrv iplmod = { &mod_driverops, IPL_VERSION, &ipf_ops }; static struct modlinkage modlink1 = { MODREV_1, &iplmod, NULL }; +static int ipf_pkts = 0; #if SOLARIS2 >= 6 static size_t hdrsizes[57][2] = { { 0, 0 }, { IFT_OTHER, 0 }, - { IFT_1822, 14 }, /* 14 for ire0 ?? */ + { IFT_1822, 0 }, { IFT_HDH1822, 0 }, { IFT_X25DDN, 0 }, { IFT_X25, 0 }, { IFT_ETHER, 14 }, - { IFT_ISO88023, 14 }, + { IFT_ISO88023, 0 }, { IFT_ISO88024, 0 }, { IFT_ISO88025, 0 }, { IFT_ISO88026, 0 }, @@ -207,177 +194,147 @@ static size_t hdrsizes[57][2] = { }; #endif /* SOLARIS2 >= 6 */ -static dev_info_t *ipf_dev_info = NULL; +static dev_info_t *ipf_dev_info = NULL; +#if defined(FW_HOOKS) +ipf_main_softc_t *ipf_instances = NULL; +net_instance_t *ipf_inst = NULL; +#else +ipf_main_softc_t ipfmain; +ipf_main_softc_t *ipf_instances = &ipfmain; +#endif -int _init() +int +_init() { - int ipfinst; + int rval; - ipfinst = mod_install(&modlink1); + rval = mod_install(&modlink1); #ifdef IPFDEBUG - if (ipf_debug) - cmn_err(CE_NOTE, "IP Filter: _init() = %d", ipfinst); + cmn_err(CE_NOTE, "IP Filter: _init() = %d", rval); #endif - return ipfinst; + if (rval != 0) + return rval; + + rval = ipf_solaris_init(); + if (rval != 0) + (void) mod_remove(&modlink1); + return rval; } -int _fini(void) +int +_fini(void) { - int ipfinst; + int rval; - ipfinst = mod_remove(&modlink1); + rval = mod_remove(&modlink1); #ifdef IPFDEBUG - if (ipf_debug) - cmn_err(CE_NOTE, "IP Filter: _fini() = %d", ipfinst); + cmn_err(CE_NOTE, "IP Filter: _fini() = %d", rval); #endif - return ipfinst; + if (rval == 0) { + ipf_unload_all(); + ipf_stack_fini(); + } + return rval; } -int _info(modinfop) -struct modinfo *modinfop; +int +_info(modinfop) + struct modinfo *modinfop; { int ipfinst; ipfinst = mod_info(&modlink1, modinfop); #ifdef IPFDEBUG - if (ipf_debug) - cmn_err(CE_NOTE, "IP Filter: _info(%x) = %x", - modinfop, ipfinst); + cmn_err(CE_NOTE, "IP Filter: _info(%x) = %x", modinfop, ipfinst); #endif - if (fr_running > 0) - ipfsync(); return ipfinst; } -static int ipf_probe(dip) -dev_info_t *dip; -{ - if (fr_running < 0) - return DDI_PROBE_FAILURE; -#ifdef IPFDEBUG - if (ipf_debug) - cmn_err(CE_NOTE, "IP Filter: ipf_probe(%x)", dip); -#endif - return DDI_PROBE_SUCCESS; -} - - -static int ipf_identify(dip) -dev_info_t *dip; +#if SOLARIS2 < 10 +static int +ipf_identify(dip) + dev_info_t *dip; { -#ifdef IPFDEBUG - if (ipf_debug) - cmn_err(CE_NOTE, "IP Filter: ipf_identify(%x)", dip); -#endif +# ifdef IPFDEBUG + cmn_err(CE_NOTE, "IP Filter: ipf_identify(%x)", dip); +# endif if (strcmp(ddi_get_name(dip), "ipf") == 0) return (DDI_IDENTIFIED); return (DDI_NOT_IDENTIFIED); } - - -static void ipf_ire_walk(ire, arg) -ire_t *ire; -void *arg; -{ - qif_t *qif = arg; - - if ((ire->ire_type == IRE_CACHE) && -#if SOLARIS2 >= 6 - (ire->ire_ipif != NULL) && - (ire->ire_ipif->ipif_ill == qif->qf_ill) -#else - (ire_to_ill(ire) == qif->qf_ill) -#endif - ) { -#if SOLARIS2 >= 8 - mblk_t *m = ire->ire_fp_mp; -#else - mblk_t *m = ire->ire_ll_hdr_mp; #endif - if (m != NULL) - qif->qf_hl = m->b_wptr - m->b_rptr; - } -} -static int ipf_attach(dip, cmd) -dev_info_t *dip; -ddi_attach_cmd_t cmd; +static int +ipf_attach(dip, cmd) + dev_info_t *dip; + ddi_attach_cmd_t cmd; { + ipf_main_softc_t *softc; + char *s; + int i; #ifdef IPFDEBUG int instance; - if (ipf_debug) - cmn_err(CE_NOTE, "IP Filter: ipf_attach(%x,%x)", dip, cmd); + cmn_err(CE_NOTE, "IP Filter: ipf_attach(%x,%x)", dip, cmd); #endif - switch (cmd) { + + ipf_rand_push(dip, sizeof(*dip)); + +#if !defined(INSTANCES) + if ((pfilinterface != PFIL_INTERFACE) || (PFIL_INTERFACE < 2000000)) { + cmn_err(CE_NOTE, "pfilinterface(%d) != %d\n", pfilinterface, + PFIL_INTERFACE); + return EINVAL; + } +#endif + softc = GET_SOFTC(0); + if (softc == NULL) + return ENXIO; + + switch (cmd) + { case DDI_ATTACH: - if (fr_running < 0) + if (softc->ipf_running != 0) break; #ifdef IPFDEBUG instance = ddi_get_instance(dip); - if (ipf_debug) cmn_err(CE_NOTE, "IP Filter: attach ipf instance %d", instance); #endif - if (ddi_create_minor_node(dip, "ipf", S_IFCHR, IPL_LOGIPF, - DDI_PSEUDO, 0) == DDI_FAILURE) { - ddi_remove_minor_node(dip, NULL); - goto attach_failed; - } - if (ddi_create_minor_node(dip, "ipnat", S_IFCHR, IPL_LOGNAT, - DDI_PSEUDO, 0) == DDI_FAILURE) { - ddi_remove_minor_node(dip, NULL); - goto attach_failed; - } - if (ddi_create_minor_node(dip, "ipstate", S_IFCHR,IPL_LOGSTATE, - DDI_PSEUDO, 0) == DDI_FAILURE) { - ddi_remove_minor_node(dip, NULL); - goto attach_failed; - } - if (ddi_create_minor_node(dip, "ipauth", S_IFCHR, IPL_LOGAUTH, - DDI_PSEUDO, 0) == DDI_FAILURE) { - ddi_remove_minor_node(dip, NULL); - goto attach_failed; + + softc->ipf_dip = dip; + + (void) ipf_property_update(dip); + + for (i = 0; ((s = ipf_devfiles[i]) != NULL); i++) { + s = strrchr(s, '/'); + if (s == NULL) + continue; + s++; + if (ddi_create_minor_node(dip, s, S_IFCHR, i, + DDI_PSEUDO, 0) == + DDI_FAILURE) { + ddi_remove_minor_node(dip, NULL); + goto attach_failed; + } } + ipf_dev_info = dip; - sync(); /* * Initialize mutex's */ - if (iplattach() == -1) - goto attach_failed; - /* - * Lock people out while we set things up. - */ - WRITE_ENTER(&ipf_solaris); - solattach(); - solipdrvattach(); - RWLOCK_EXIT(&ipf_solaris); - cmn_err(CE_CONT, "%s, attaching complete.\n", - ipfilter_version); - sync(); - if (fr_running == 0) - fr_running = 1; - if (ipfr_timer_id == 0) - ipfr_timer_id = timeout(ipfr_slowtimer, NULL, - drv_usectohz(500000)); - if (fr_running == 1) - return DDI_SUCCESS; -#if SOLARIS2 >= 8 - case DDI_RESUME : - case DDI_PM_RESUME : - if (ipfr_timer_id == 0) - ipfr_timer_id = timeout(ipfr_slowtimer, NULL, - drv_usectohz(500000)); + + cmn_err(CE_CONT, "!%s, loaded.\n", ipfilter_version); + return DDI_SUCCESS; -#endif + /* NOTREACHED */ default: - return DDI_FAILURE; + break; } attach_failed: @@ -391,39 +348,26 @@ attach_failed: } -static int ipf_detach(dip, cmd) -dev_info_t *dip; -ddi_detach_cmd_t cmd; +static int +ipf_detach(dip, cmd) + dev_info_t *dip; + ddi_detach_cmd_t cmd; { + ipf_main_softc_t *tmp; int i; #ifdef IPFDEBUG - if (ipf_debug) - cmn_err(CE_NOTE, "IP Filter: ipf_detach(%x,%x)", dip, cmd); + cmn_err(CE_NOTE, "IP Filter: ipf_detach(%x,%x)", dip, cmd); #endif + switch (cmd) { case DDI_DETACH: - if (fr_running <= 0) + for (tmp = ipf_instances; tmp != NULL; tmp = tmp->ipf_next) + if (ipf_detach_instance(tmp) != DDI_SUCCESS) + break; + + if (tmp != NULL) break; - /* - * Make sure we're the only one's modifying things. With - * this lock others should just fall out of the loop. - */ - mutex_enter(&ipf_rw); - if (ipfr_timer_id != 0) { - untimeout(ipfr_timer_id); - ipfr_timer_id = 0; - } - mutex_exit(&ipf_rw); - WRITE_ENTER(&ipf_solaris); - mutex_enter(&ipf_rw); - if (fr_running <= 0) { - mutex_exit(&ipf_rw); - return DDI_FAILURE; - } - fr_running = -1; - mutex_exit(&ipf_rw); - /* NOTE: ipf_solaris rwlock is released in ipldetach */ /* * Undo what we did in ipf_attach, freeing resources @@ -433,51 +377,33 @@ ddi_detach_cmd_t cmd; */ ddi_prop_remove_all(dip); i = ddi_get_instance(dip); - ddi_remove_minor_node(dip, NULL); - sync(); - i = solipdrvdetach(); if (i > 0) { cmn_err(CE_CONT, "IP Filter: still attached (%d)\n", i); return DDI_FAILURE; } - if (!soldetach()) { - cmn_err(CE_CONT, "%s detached\n", ipfilter_version); - return (DDI_SUCCESS); - } -#if SOLARIS2 >= 8 - case DDI_SUSPEND : - case DDI_PM_SUSPEND : - if (ipfr_timer_id != 0) { - untimeout(ipfr_timer_id); - ipfr_timer_id = 0; - } - if (synctimeoutid) { - untimeout(synctimeoutid); - synctimeoutid = 0; - } - return DDI_SUCCESS; -#endif + + cmn_err(CE_CONT, "!%s detached.\n", ipfilter_version); + return (DDI_SUCCESS); default: - return (DDI_FAILURE); + break; } + cmn_err(CE_NOTE, "IP Filter: failed to detach\n"); return DDI_FAILURE; } -static int ipf_getinfo(dip, infocmd, arg, result) -dev_info_t *dip; -ddi_info_cmd_t infocmd; -void *arg, **result; +/*ARGSUSED*/ +static int +ipf_getinfo(dip, infocmd, arg, result) + dev_info_t *dip; + ddi_info_cmd_t infocmd; + void *arg, **result; { int error; - if (fr_running <= 0) - return DDI_FAILURE; error = DDI_FAILURE; #ifdef IPFDEBUG - if (ipf_debug) - cmn_err(CE_NOTE, "IP Filter: ipf_getinfo(%x,%x,%x)", - dip, infocmd, arg); + cmn_err(CE_NOTE, "IP Filter: ipf_getinfo(%x,%x,%x)", dip, infocmd, arg); #endif switch (infocmd) { case DDI_INFO_DEVT2DEVINFO: @@ -485,7 +411,7 @@ void *arg, **result; error = DDI_SUCCESS; break; case DDI_INFO_DEVT2INSTANCE: - *result = (void *)getminor((dev_t) arg); + *result = (void *)0; error = DDI_SUCCESS; break; default: @@ -494,1638 +420,871 @@ void *arg, **result; return (error); } -/* - * find the filter structure setup for this queue - */ -static qif_t *qif_from_queue(q) -queue_t *q; -{ - qif_t *qif; - for (qif = qif_head; qif; qif = qif->qf_next) - if ((qif->qf_iptr == q->q_ptr) || (qif->qf_optr == q->q_ptr)) - break; - return qif; -} - - -/* - * OK, this is pretty scrappy code, but then it's essentially just here for - * debug purposes and that's it. Packets should not normally come through - * here, and if they do, well, we would like to see as much information as - * possible about them and what they claim to hold. - */ -void fr_donotip(out, qif, q, m, mt, ip, off) -int out; -qif_t *qif; -queue_t *q; -mblk_t *m, *mt; -ip_t *ip; -size_t off; +static int +ipf_solaris_init() { - u_char *s, outb[256], *t; - int i; + int rval = DDI_SUCCESS; - outb[0] = '\0'; - outb[1] = '\0'; - outb[2] = '\0'; - outb[3] = '\0'; - s = ip ? (u_char *)ip : outb; - if (!ip && (m == mt) && m->b_cont && (MTYPE(m) != M_DATA)) - m = m->b_cont; - - cmn_err(CE_CONT, " !IP %s:%d %d %p %p %p %d %p/%d %p/%d %p %d %d %p\n", - qif ? qif->qf_name : "?", out, qif ? qif->qf_hl : -1, q, - q ? q->q_ptr : NULL, q ? q->q_qinfo : NULL, - mt->b_wptr - mt->b_rptr, m, MTYPE(m), mt, MTYPE(mt), m->b_rptr, - m->b_wptr - m->b_rptr, off, ip); - cmn_err(CE_CONT, "%02x%02x%02x%02x\n", *s, *(s+1), *(s+2), *(s+3)); - while (m != mt) { - i = 0; - t = outb; - s = mt->b_rptr; - sprintf((char *)t, "%d:", MTYPE(mt)); - t += strlen((char *)t); - for (; (i < 100) && (s < mt->b_wptr); i++) { - sprintf((char *)t, "%02x%s", *s++, - ((i & 3) == 3) ? " " : ""); - t += ((i & 3) == 3) ? 3 : 2; - } - *t++ = '\n'; - *t = '\0'; - cmn_err(CE_CONT, "%s", outb); - mt = mt->b_cont; + rval = ipf_load_all(); + if (rval != 0) { +#ifdef IPFDEBUG + cmn_err(CE_NOTE, "IP Filter: ipf_load_all() failed\n"); +#endif + return rval; } - i = 0; - t = outb; - s = m->b_rptr; - sprintf((char *)t, "%d:", MTYPE(m)); - t += strlen((char *)t); - for (; (i < 100) && (s < m->b_wptr); i++) { - sprintf((char *)t, "%02x%s", *s++, ((i & 3) == 3) ? " " : ""); - t += ((i & 3) == 3) ? 3 : 2; + +#ifdef IPFDEBUG + cmn_err(CE_NOTE, "IP Filter: ipf_load_all() done\n"); +#endif + rval = ipf_stack_init(); + if (rval != 0) { + ipf_unload_all(); + return rval; } - *t++ = '\n'; - *t = '\0'; - cmn_err(CE_CONT, "%s", outb); +#ifdef IPFDEBUG + cmn_err(CE_NOTE, "IP Filter: ipf_stack_init() done\n"); +#endif + return 0; } +#if !defined(INSTANCES) /* - * find the first data mblk, if present, in the chain we're processing. Also - * make a few sanity checks to try prevent the filter from causing a panic - - * none of the nice IP sanity checks (including checksumming) should have been - * done yet (for incoming packets) - dangerous! + * look for bad consistancies between the list of interfaces the filter knows + * about and those which are currently configured. */ -static int fr_precheck(mp, q, qif, out) -mblk_t **mp; -queue_t *q; -qif_t *qif; -int out; +/*ARGSUSED*/ +static int +ipf_qifsync(ip, hlen, il, out, qif, mp) + ip_t *ip; + int hlen; + void *il; + int out; + void *qif; + mblk_t **mp; { - register mblk_t *m, *mt = *mp; - register ip_t *ip; - size_t hlen, len, off, off2, mlen, iphlen, plen, woff; - int err, synced = 0, sap, p, realigned = 0, multi = 0; - u_char *bp; -#if SOLARIS2 >= 8 - ip6_t *ip6; -#endif -#ifndef sparc - u_short __ipoff; -#endif -tryagain: - ip = NULL; - m = NULL; - /* - * If there is only M_DATA for a packet going out, then any header - * information (which would otherwise appear in an M_PROTO mblk before - * the M_DATA) is prepended before the IP header. We need to set the - * offset to account for this. - see MMM - */ - off = (out) ? qif->qf_hl : 0; + ipf_main_softc_t *softc = &ipfmain; + ipf_sync(softc, qif); /* - * If the message protocol block indicates that there isn't a data - * block following it, just return back. + * Resync. any NAT `connections' using this interface and its IP #. */ - bp = (u_char *)ALIGN32(mt->b_rptr); - if (MTYPE(mt) == M_PROTO || MTYPE(mt) == M_PCPROTO) { - dl_unitdata_ind_t *dl = (dl_unitdata_ind_t *)bp; - if (dl->dl_primitive == DL_UNITDATA_IND) { - multi = dl->dl_group_address; - m = mt->b_cont; - /* - * This is a complete kludge to try and work around - * some bizarre packets which drop through into - * fr_donotip. - */ - if (m && multi && ((*((u_char *)m->b_rptr) == 0x0) && - ((*((u_char *)m->b_rptr + 2) == 0x45)))) { - ip = (ip_t *)(m->b_rptr + 2); - off = 2; - } else - off = 0; - } else if (dl->dl_primitive != DL_UNITDATA_REQ) { - ip = (ip_t *)dl; - if ((ip->ip_v == IPVERSION) && - (ip->ip_hl == (sizeof(*ip) >> 2)) && - (ntohs(ip->ip_len) == mt->b_wptr - mt->b_rptr)) { - off = 0; - m = mt; - } else { - frstats[out].fr_notdata++; - return 0; - } - } - } + ipf_nat_sync(softc, qif); + ipf_state_sync(softc, qif); + ipf_lookup_sync(softc, qif); + return 0; +} - /* - * Find the first data block, count the data blocks in this chain and - * the total amount of data. - */ - if (ip == NULL) - for (m = mt; m && (MTYPE(m) != M_DATA); m = m->b_cont) - off = 0; /* Any non-M_DATA cancels the offset */ - if (!m) { - frstats[out].fr_nodata++; - return 0; /* No data blocks */ - } +/* + * look for bad consistancies between the list of interfaces the filter knows + * about and those which are currently configured. + */ +int +ipfsync() +{ + ipf_sync(&ipfmain, NULL); + return 0; +} +#endif - ip = (ip_t *)(m->b_rptr + off); /* MMM */ - /* - * We might have a 1st data block which is really M_PROTO, i.e. it is - * only big enough for the link layer header - */ - while ((u_char *)ip >= m->b_wptr) { - len = (u_char *)ip - m->b_wptr; - m = m->b_cont; - if (m == NULL) - return 0; /* not enough data for IP */ - ip = (ip_t *)(m->b_rptr + len); +/* + * Fetch configuration file values that have been entered into the ipf.conf + * driver file. + */ +int +ipf_property_update(dip) + dev_info_t *dip; +{ + ipf_main_softc_t *softc; + ipftuneable_t *ipft; + int64_t i64; + char *name; + u_int one; + int *i32p; + int err; + +#ifdef DDI_NO_AUTODETACH + if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, + DDI_NO_AUTODETACH, 1) != DDI_PROP_SUCCESS) { + cmn_err(CE_WARN, "!updating DDI_NO_AUTODETACH failed"); + return DDI_FAILURE; } - off = (u_char *)ip - m->b_rptr; - if (off != 0) - m->b_rptr = (u_char *)ip; - - len = m->b_wptr - m->b_rptr; - if (m->b_wptr < m->b_rptr) { - cmn_err(CE_NOTE, "!IP Filter: Bad packet: wptr %p < rptr %p", - m->b_wptr, m->b_rptr); - frstats[out].fr_bad++; - return -1; +#else + if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, + "ddi-no-autodetach", 1) != DDI_PROP_SUCCESS) { + cmn_err(CE_WARN, "!updating ddi-no-autodetach failed"); + return DDI_FAILURE; } +#endif - mlen = msgdsize(m); - sap = qif->qf_ill->ill_sap; - - if (sap == 0x800) { - u_short tlen; - - hlen = sizeof(*ip); - - /* XXX - might not be aligned (from ppp?) */ - ((char *)&tlen)[0] = ((char *)&ip->ip_len)[0]; - ((char *)&tlen)[1] = ((char *)&ip->ip_len)[1]; - - plen = ntohs(tlen); + softc = GET_SOFTC(0); - sap = 0; - } -#if SOLARIS2 >= 8 - else if (sap == IP6_DL_SAP) { - u_short tlen; - - hlen = sizeof(ip6_t); - ip6 = (ip6_t *)ip; - /* XXX - might not be aligned (from ppp?) */ - ((char *)&tlen)[0] = ((char *)&ip6->ip6_plen)[0]; - ((char *)&tlen)[1] = ((char *)&ip6->ip6_plen)[1]; - plen = ntohs(tlen); - if (!plen) - return -1; /* Jumbo gram */ - plen += sizeof(*ip6); - } -#endif - else { - plen = 0; - hlen = 0; - sap = -1; + ipft = softc->ipf_tuners; + if (ipft == NULL) { + cmn_err(CE_WARN, "!no tuners loaded"); + return DDI_FAILURE; } - /* - * Ok, the IP header isn't on a 32bit aligned address so junk it. - */ - if (((u_long)ip & 0x3) || (plen > mlen) || (len < hlen) || - (sap == -1)) { - mblk_t *m1, *m2; - u_char *s, c; - int v; - - /* - * Junk using pullupmsg - it's next to useless. - */ -fixalign: - if (off) - m->b_rptr -= off; - c = *(u_char *)ip; - c >>= 4; - if (c != 4 -#if SOLARIS2 >= 8 - && c != 6 -#endif - ) { - frstats[out].fr_notip++; - return (fr_flags & FF_BLOCKNONIP) ? -1 : 0; + err = DDI_SUCCESS; + for (; (ipft != NULL) && ((name = (char *)ipft->ipft_name) != NULL); + ipft = ipft->ipft_next) { + one = 1; + i32p = NULL; + err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, + 0, name, &i32p, &one); + if (err == DDI_PROP_NOT_FOUND || i32p == NULL) + continue; + if (*i32p >= ipft->ipft_min && *i32p <= ipft->ipft_max) { + if (ipft->ipft_sz == sizeof(int)) { + *ipft->ipft_pint = *i32p; + } else { + i64 = *(u_int *)i32p; + *(u_long *)ipft->ipft_pint = i64; + } } + } - if (realigned) - return -1; - realigned = 1; - off2 = (size_t)((u_long)ip & 0x3); - if (off2) - off2 = 4 - off2; - len = msgdsize(m); - m2 = allocb(len + off2, BPRI_HI); - if (m2 == NULL) { - frstats[out].fr_pull[1]++; - return -1; - } + return err; +} - MTYPE(m2) = M_DATA; - if (m->b_rptr != (u_char *)ip) - m2->b_rptr += off2; - m2->b_wptr = m2->b_rptr + len; - m1 = m; - s = (u_char *)m->b_rptr; - for (bp = m2->b_rptr; m1 && (bp < m2->b_wptr); bp += len) { - len = MIN(m1->b_wptr - s, m2->b_wptr - bp); - bcopy(s, bp, len); - m1 = m1->b_cont; - if (m1) - s = m1->b_rptr; - } - if (mt != m && mt->b_cont == m && !off) { - /* - * check if the buffer we're changing is chained in- - * between other buffers and unlink/relink as required. - */ - (void) unlinkb(mt); /* should return 'm' */ - m1 = unlinkb(m); - if (m1) - linkb(m2, m1); - freemsg(m); - linkb(mt, m2); - } else { - if (m == mt) { - m1 = unlinkb(mt); - if (m1) - linkb(m2, m1); - } - freemsg(mt); - *mp = m2; - mt = m2; - } +static int +ipfpoll(dev, events, anyyet, reventsp, phpp) + dev_t dev; + short events; + int anyyet; + short *reventsp; + struct pollhead **phpp; +{ + ipf_main_softc_t *softc; + u_int xmin = getminor(dev); + int revents = 0; - frstats[out].fr_pull[0]++; - synced = 1; - off = 0; - goto tryagain; - } + if (xmin < 0 || xmin > IPL_LOGMAX) + return ENXIO; - if (((sap == 0) && (ip->ip_v != IP_VERSION)) -#if SOLARIS2 >= 8 - || ((sap == IP6_DL_SAP) && ((ip6->ip6_vfc >> 4) != 6)) + softc = GET_SOFTC(getzoneid()); + + switch (xmin) + { + case IPL_LOGIPF : + case IPL_LOGNAT : + case IPL_LOGSTATE : +#ifdef IPFILTER_LOG + if ((events & (POLLIN | POLLRDNORM)) && ipf_log_canread(softc, xmin)) + revents |= events & (POLLIN | POLLRDNORM); +#endif + break; + case IPL_LOGAUTH : + if ((events & (POLLIN | POLLRDNORM)) && + ipf_auth_waiting(softc)) + revents |= events & (POLLIN | POLLRDNORM); + break; + case IPL_LOGSYNC : + if ((events & (POLLIN | POLLRDNORM)) && + ipf_sync_canread(softc)) + revents |= events & (POLLIN | POLLRDNORM); + if ((events & (POLLOUT | POLLWRNORM)) && + ipf_sync_canwrite(softc)) + revents |= events & POLLOUT; +#ifdef POLLOUTNORM + revents |= events & POLLOUTNORM; #endif - ) { - m->b_rptr -= off; - return -2; + break; + case IPL_LOGSCAN : + case IPL_LOGLOOKUP : + default : + break; } -#ifndef sparc -# if SOLARIS2 >= 8 - if (sap == IP6_DL_SAP) { - ip6->ip6_plen = plen - sizeof(*ip6); + if (revents) { + *reventsp = revents; } else { -# endif - __ipoff = (u_short)ip->ip_off; - - ip->ip_len = plen; - ip->ip_off = ntohs(__ipoff); -# if SOLARIS2 >= 8 + *reventsp = 0; + if (!anyyet) + *phpp = &softc->ipf_poll_head[xmin]; } -# endif -#endif - if (sap == 0) - iphlen = ip->ip_hl << 2; -#if SOLARIS2 >= 8 - else if (sap == IP6_DL_SAP) - iphlen = sizeof(ip6_t); -#endif + return 0; +} - if (( -#if SOLARIS2 >= 8 - (sap == IP6_DL_SAP) && (mlen < plen)) || - ((sap == 0) && -#endif - ((iphlen < hlen) || (iphlen > plen) || (mlen < plen)))) { - /* - * Bad IP packet or not enough data/data length mismatches - */ -#ifndef sparc -# if SOLARIS2 >= 8 - if (sap == IP6_DL_SAP) { - ip6->ip6_plen = htons(plen - sizeof(*ip6)); - } else { -# endif - __ipoff = (u_short)ip->ip_off; - ip->ip_len = htons(plen); - ip->ip_off = htons(__ipoff); -# if SOLARIS2 >= 8 - } -# endif -#endif - m->b_rptr -= off; - frstats[out].fr_bad++; - return -1; - } - - /* - * Make hlen the total size of the IP header plus TCP/UDP/ICMP header - * (if it is one of these three). - */ - if (sap == 0) - p = ip->ip_p; -#if SOLARIS2 >= 8 - else if (sap == IP6_DL_SAP) - p = ip6->ip6_nxt; +/* + * routines below for saving IP headers to buffer + */ +/*ARGSUSED*/ +static int +ipfopen(devp, flags, otype, cred) + dev_t *devp; + int flags, otype; + cred_t *cred; +{ + minor_t unit = getminor(*devp); + int error; - if ((sap == IP6_DL_SAP) || ((ip->ip_off & IP_OFFMASK) == 0)) -#else - if ((ip->ip_off & IP_OFFMASK) == 0) +#ifdef IPFDEBUG + cmn_err(CE_CONT, "ipfopen(%x,%x,%x,%x)\n", devp, flags, otype, cred); #endif - switch (p) + if (!(otype & OTYP_CHR)) + return ENXIO; + + if (IPL_LOGMAX < unit) { + error = ENXIO; + } else { + switch (unit) { - case IPPROTO_TCP : - hlen += sizeof(tcphdr_t); - break; - case IPPROTO_UDP : - hlen += sizeof(udphdr_t); - break; - case IPPROTO_ICMP : - /* 76 bytes is enough for a complete ICMP error. */ - hlen += 76 + sizeof(icmphdr_t); + case IPL_LOGIPF : + case IPL_LOGNAT : + case IPL_LOGSTATE : + case IPL_LOGAUTH : + case IPL_LOGLOOKUP : + case IPL_LOGSYNC : +#ifdef IPFILTER_SCAN + case IPL_LOGSCAN : +#endif + error = 0; break; default : + error = ENXIO; break; } - - woff = 0; - if (hlen > mlen) { - hlen = mlen; - } else if (m->b_wptr - m->b_rptr > plen) { - woff = m->b_wptr - m->b_rptr - plen; - m->b_wptr -= woff; } + return error; +} - /* - * If we don't have enough data in the mblk or we haven't yet copied - * enough (above), then copy some more. - */ - if ((hlen > len)) { - if (!pullupmsg(m, (int)hlen)) { - cmn_err(CE_NOTE, "pullupmsg failed"); - frstats[out].fr_pull[1]++; - return -1; - } - frstats[out].fr_pull[0]++; - ip = (ip_t *)ALIGN32(m->b_rptr); - } - qif->qf_m = m; - qif->qf_q = q; - qif->qf_off = off; - qif->qf_len = len; - err = fr_check(ip, iphlen, qif->qf_ill, out, qif, mp); - if (err == 2) { - goto fixalign; - } - /* - * Copy back the ip header data if it was changed, we haven't yet - * freed the message and we aren't going to drop the packet. - * BUT only do this if there were no changes to the buffer, else - * we can't be sure that the ip pointer is still correct! - */ - if (*mp != NULL) { - if (*mp == mt) { - m->b_wptr += woff; - m->b_rptr -= off; -#ifndef sparc -# if SOLARIS2 >= 8 - if (sap == IP6_DL_SAP) { - ip6->ip6_plen = htons(plen - sizeof(*ip6)); - } else { -# endif - __ipoff = (u_short)ip->ip_off; - /* - * plen is useless because of NAT. - */ - ip->ip_len = htons(ip->ip_len); - ip->ip_off = htons(__ipoff); -# if SOLARIS2 >= 8 - } -# endif + +/*ARGSUSED*/ +static int +ipfclose(dev, flags, otype, cred) + dev_t dev; + int flags, otype; + cred_t *cred; +{ + minor_t min = getminor(dev); + +#ifdef IPFDEBUG + cmn_err(CE_CONT, "iplclose(%x,%x,%x,%x)\n", dev, flags, otype, cred); #endif - } else - cmn_err(CE_NOTE, - "!IP Filter: *mp %p mt %p %s", *mp, mt, - "mblk changed, cannot revert ip_len, ip_off"); - } - return err; + + min = (IPL_LOGMAX < min) ? ENXIO : 0; + return min; } /* - * Only called for M_IOCACK messages + * ipfread/ipllog + * both of these must operate with at least splnet() lest they be + * called during packet processing and cause an inconsistancy to appear in + * the filter lists. */ -void fr_qif_update(qif, mp) -qif_t *qif; -mblk_t *mp; +/*ARGSUSED*/ +static int +ipfread(dev, uio, cp) + dev_t dev; + register struct uio *uio; + cred_t *cp; { - struct iocblk *iocp; - - if (!qif || !mp) - return; - iocp = (struct iocblk *)mp->b_rptr; - if (mp->b_cont && (iocp->ioc_cmd == DL_IOC_HDR_INFO)) { - mp = mp->b_cont; - if (MTYPE(mp) == M_PROTO && mp->b_cont) { - mp = mp->b_cont; - if (MTYPE(mp) == M_DATA) { - qif->qf_hl = mp->b_wptr - mp->b_rptr; - } - } - } -} + ipf_main_softc_t *softc; - -int fr_qin(q, mb) -queue_t *q; -mblk_t *mb; -{ - int (*pnext) __P((queue_t *, mblk_t *)), type, synced = 0, err = 0; - qif_t qf, *qif; - -#ifdef IPFDEBUG_VERBOSE - if (ipf_debug_verbose) - cmn_err(CE_CONT, - "fr_qin(%lx,%lx) ptr %lx type 0x%x ref %d len %d\n", - q, q->q_ptr, mb, MTYPE(mb), mb->b_datap->db_ref, - msgdsize(mb)); +#ifdef IPFDEBUG + cmn_err(CE_CONT, "ipfread(%x,%x,%x)\n", dev, uio, cp); #endif - /* - * IPFilter is still in the packet path but not enabled. Drop whatever - * it is that has come through. - */ - if (fr_running <= 0) { - mb->b_prev = NULL; - freemsg(mb); - return 0; - } + softc = GET_SOFTC(crgetzoneid(cp)); - type = MTYPE(mb); + if (softc->ipf_running < 1) + return EIO; - /* - * If a mblk has more than one reference, make a copy, filter that and - * free a reference to the original. - */ - if (mb->b_datap->db_ref > 1) { - mblk_t *m1; - - m1 = copymsg(mb); - if (!m1) { - frstats[0].fr_drop++; - mb->b_prev = NULL; - freemsg(mb); - return 0; - } - mb->b_prev = NULL; - freemsg(mb); - mb = m1; - frstats[0].fr_copy++; - } + if (getminor(dev) == IPL_LOGSYNC) + return ipf_sync_read(softc, uio); - READ_ENTER(&ipf_solaris); -again: - if (fr_running <= 0) { - mb->b_prev = NULL; - freemsg(mb); - RWLOCK_EXIT(&ipf_solaris); - return 0; - } - READ_ENTER(&ipfs_mutex); - if (!(qif = qif_from_queue(q))) { - for (qif = qif_head; qif; qif = qif->qf_next) - if (&qif->qf_rqinit == q->q_qinfo && qif->qf_rqinfo && - qif->qf_rqinfo->qi_putp) { - pnext = qif->qf_rqinfo->qi_putp; - frstats[0].fr_notip++; - RWLOCK_EXIT(&ipfs_mutex); - if (!synced) { - ipfsync(); - synced = 1; - goto again; - } - RWLOCK_EXIT(&ipf_solaris); - /* fr_donotip(0, NULL, q, mb, mb, NULL, 0); */ - return (*pnext)(q, mb); - } - RWLOCK_EXIT(&ipfs_mutex); - if (!synced) { - ipfsync(); - synced = 1; - goto again; - } - cmn_err(CE_WARN, - "!IP Filter: dropped: fr_qin(%x,%x): type %x qif %x", - q, mb, type, qif); - cmn_err(CE_CONT, - "!IP Filter: info %x next %x ptr %x fsrv %x bsrv %x\n", - q->q_qinfo, q->q_next, q->q_ptr, q->q_nfsrv, - q->q_nbsrv); - cmn_err(CE_CONT, "!IP Filter: info: putp %x srvp %x info %x\n", - q->q_qinfo->qi_putp, q->q_qinfo->qi_srvp, -#if SOLARIS > 3 - q->q_qinfo->qi_infop +#ifdef IPFILTER_LOG + return ipf_log_read(softc, getminor(dev), uio); #else - 0 + return ENXIO; #endif - ); - frstats[0].fr_drop++; - mb->b_prev = NULL; - freemsg(mb); - RWLOCK_EXIT(&ipf_solaris); - return 0; - } +} - qif->qf_incnt++; - pnext = qif->qf_rqinfo->qi_putp; - if (type == M_IOCACK) - fr_qif_update(qif, mb); - bcopy((char *)qif, (char *)&qf, sizeof(qf)); - if (datamsg(type) || (type == M_BREAK)) - err = fr_precheck(&mb, q, &qf, 0); - RWLOCK_EXIT(&ipfs_mutex); +/* + * ipfread/ipllog + * both of these must operate with at least splnet() lest they be + * called during packet processing and cause an inconsistancy to appear in + * the filter lists. + */ +static int +ipfwrite(dev, uio, cp) + dev_t dev; + register struct uio *uio; + cred_t *cp; +{ + ipf_main_softc_t *softc; - if ((err == 0) && (mb != NULL)) { - if (pnext) { - RWLOCK_EXIT(&ipf_solaris); - return (*pnext)(q, mb); - } +#ifdef IPFDEBUG + cmn_err(CE_CONT, "ipfwrite(%x,%x,%x)\n", dev, uio, cp); +#endif - cmn_err(CE_WARN, - "!IP Filter: inp NULL: qif %x %s q %x info %x", - qif, qf.qf_name, q, q->q_qinfo); - } + softc = GET_SOFTC(crgetzoneid(cp)); - if (err == -2) { - if (synced == 0) { - ipfsync(); - synced = 1; - goto again; - } - frstats[0].fr_notip++; - if (!(fr_flags & FF_BLOCKNONIP) && (pnext != NULL)) { - RWLOCK_EXIT(&ipf_solaris); - return (*pnext)(q, mb); - } - } - + if (softc->ipf_running < 1) + return EIO; - if (mb) { - mb->b_prev = NULL; - freemsg(mb); - } - RWLOCK_EXIT(&ipf_solaris); - return 1; + if (getminor(dev) == IPL_LOGSYNC) + return ipf_sync_write(softc, uio); + return ENXIO; } - -int fr_qout(q, mb) -queue_t *q; -mblk_t *mb; +#if !defined(INSTANCES) + +static int +ipf_bounce(ctx, ip, hlen, ifp, out, qif, mp) + void *ctx; + ip_t *ip; + int hlen; + void *ifp; + int out; + void *qif; + mb_t **mp; { - int (*pnext) __P((queue_t *, mblk_t *)), type, synced = 0, err = 0; - qif_t qf, *qif; - -#ifdef IPFDEBUG_VERBOSE - if (ipf_debug_verbose) - cmn_err(CE_CONT, - "fr_qout(%lx,%lx) ptr %lx type 0x%x ref %d len %d\n", - q, q->q_ptr, mb, MTYPE(mb), mb->b_datap->db_ref, - msgdsize(mb)); -#endif - - if (fr_running <= 0) { - mb->b_prev = NULL; - freemsg(mb); - return 0; - } - - type = MTYPE(mb); + if ((++ipf_pkts & 0xffff) == 0) + ipf_rand_push(*mp, M_LEN(*mp)); -#if SOLARIS2 >= 6 - if ((!dohwcksum || mb->b_ick_flag != ICK_VALID) && - (mb->b_datap->db_ref > 1)) -#else - if (mb->b_datap->db_ref > 1) -#endif - { - mblk_t *m1; - - m1 = copymsg(mb); - if (!m1) { - frstats[1].fr_drop++; - mb->b_prev = NULL; - freemsg(mb); - return 0; - } - mb->b_prev = NULL; - freemsg(mb); - mb = m1; - frstats[1].fr_copy++; - } + return ipf_check(ctx, ip, hlen, ifp, out, qif, mp); +} - READ_ENTER(&ipf_solaris); -again: - if (fr_running <= 0) { - mb->b_prev = NULL; - freemsg(mb); - RWLOCK_EXIT(&ipf_solaris); - return 0; - } - READ_ENTER(&ipfs_mutex); - if (!(qif = qif_from_queue(q))) { - for (qif = qif_head; qif; qif = qif->qf_next) - if (&qif->qf_wqinit == q->q_qinfo && qif->qf_wqinfo && - qif->qf_wqinfo->qi_putp) { - pnext = qif->qf_wqinfo->qi_putp; - RWLOCK_EXIT(&ipfs_mutex); - frstats[1].fr_notip++; - if (!synced) { - ipfsync(); - synced = 1; - goto again; - } - /* fr_donotip(1, NULL, q, mb, mb, NULL, 0); */ - RWLOCK_EXIT(&ipf_solaris); - return (*pnext)(q, mb); - } - RWLOCK_EXIT(&ipfs_mutex); - if (!synced) { - ipfsync(); - synced = 1; - goto again; - } - cmn_err(CE_WARN, - "!IP Filter: dropped: fr_qout(%x,%x): type %x: qif %x", - q, mb, type, qif); - cmn_err(CE_CONT, - "!IP Filter: info %x next %x ptr %x fsrv %x bsrv %x\n", - q->q_qinfo, q->q_next, q->q_ptr, q->q_nfsrv, - q->q_nbsrv); - cmn_err(CE_CONT, "!IP Filter: info: putp %x srvp %x info %x\n", - q->q_qinfo->qi_putp, q->q_qinfo->qi_srvp, -#if SOLARIS > 3 - q->q_qinfo->qi_infop -#else - 0 -#endif - ); - if (q->q_nfsrv) - cmn_err(CE_CONT, - "!IP Filter: nfsrv: info %x next %x ptr %x\n", - q->q_nfsrv->q_qinfo, q->q_nfsrv->q_next, - q->q_nfsrv->q_ptr); - if (q->q_nbsrv) - cmn_err(CE_CONT, - "!IP Filter: nbsrv: info %x next %x ptr %x\n", - q->q_nbsrv->q_qinfo, q->q_nbsrv->q_next, - q->q_nbsrv->q_ptr); - frstats[1].fr_drop++; - mb->b_prev = NULL; - freemsg(mb); - RWLOCK_EXIT(&ipf_solaris); - return 0; - } +void +ipf_pfil_hooks_add() +{ + if (pfil_add_hook(ipf_bounce, PFIL_IN|PFIL_OUT, &pfh_inet4)) + cmn_err(CE_WARN, "IP Filter: %s(pfh_inet4) failed", + "pfil_add_hook"); +# ifdef USE_INET6 + if (pfil_add_hook(ipf_bounce, PFIL_IN|PFIL_OUT, &pfh_inet6)) + cmn_err(CE_WARN, "IP Filter: %s(pfh_inet6) failed", + "pfil_add_hook"); +# endif + if (pfil_add_hook(ipf_qifsync, PFIL_IN|PFIL_OUT, &pfh_sync)) + cmn_err(CE_WARN, "IP Filter: %s(pfh_sync) failed", + "pfil_add_hook"); +} - qif->qf_outcnt++; - pnext = qif->qf_wqinfo->qi_putp; - if (type == M_IOCACK) - fr_qif_update(qif, mb); - bcopy((char *)qif, (char *)&qf, sizeof(qf)); - if (datamsg(type) || (type == M_BREAK)) - err = fr_precheck(&mb, q, &qf, 1); +void +ipf_pfil_hooks_remove() +{ + if (pfil_remove_hook(ipf_bounce, PFIL_IN|PFIL_OUT, &pfh_inet4)) + cmn_err(CE_WARN, "IP Filter: %s(pfh_inet4) failed", + "pfil_remove_hook"); +# ifdef USE_INET6 + if (pfil_remove_hook(ipf_bounce, PFIL_IN|PFIL_OUT, &pfh_inet6)) + cmn_err(CE_WARN, "IP Filter: %s(pfh_inet6) failed", + "pfil_add_hook"); +# endif + if (pfil_remove_hook(ipf_qifsync, PFIL_IN|PFIL_OUT, &pfh_sync)) + cmn_err(CE_WARN, "IP Filter: %s(pfh_sync) failed", + "pfil_remove_hook"); - RWLOCK_EXIT(&ipfs_mutex); +} - if ((err == 0) && (mb != NULL)) { - if (pnext) { - RWLOCK_EXIT(&ipf_solaris); - return (*pnext)(q, mb); - } - cmn_err(CE_WARN, - "!IP Filter: outp NULL: qif %x %s q %x info %x", - qif, qf.qf_name, q, q->q_qinfo); - } +static int +ipf_stack_init() +{ + ipf_create_all(&ipfmain); + return (0); +} - if (err == -2) { - if (synced == 0) { - ipfsync(); - synced = 1; - goto again; - } - frstats[1].fr_notip++; - if (!(fr_flags & FF_BLOCKNONIP) && (pnext != NULL)) { - RWLOCK_EXIT(&ipf_solaris); - return (*pnext)(q, mb); - } - } - if (mb) { - mb->b_prev = NULL; - freemsg(mb); - } - RWLOCK_EXIT(&ipf_solaris); - return 1; +static void +ipf_stack_fini() +{ + ipf_destroy_all(&ipfmain); } +#else -void ipf_synctimeout(arg) -void *arg; +int +ipf_hk_v4_in(tok, data, arg) + hook_event_token_t tok; + hook_data_t data; + void *arg; { - if (fr_running < 0) - return; - READ_ENTER(&ipf_solaris); - ipfsync(); - WRITE_ENTER(&ipfs_mutex); - synctimeoutid = 0; - RWLOCK_EXIT(&ipfs_mutex); - RWLOCK_EXIT(&ipf_solaris); + hook_pkt_event_t *hpe = (hook_pkt_event_t *)data; + ipf_main_softc_t *softc = (ipf_main_softc_t *)arg; + ip_t *ip = hpe->hpe_hdr; + qpktinfo_t qpi; + int rval; + + qpi.qpi_real = (void *)hpe->hpe_ifp; + qpi.qpi_ill = (void *)hpe->hpe_ifp; + qpi.qpi_q = NULL; + qpi.qpi_m = hpe->hpe_mb; + qpi.qpi_data = hpe->hpe_hdr; + qpi.qpi_off = 0; + qpi.qpi_flags = hpe->hpe_flags; + if ((++ipf_pkts & 0xffff) == 0) + ipf_rand_push(qpi.qpi_m, M_LEN(qpi.qpi_m)); + + rval = ipf_check(softc, hpe->hpe_hdr, ip->ip_hl << 2, + (void *)hpe->hpe_ifp, 0, &qpi, hpe->hpe_mp); + if (rval == 0 && *hpe->hpe_mp == NULL) + rval = 1; + + hpe->hpe_hdr = qpi.qpi_data; + hpe->hpe_mb = qpi.qpi_m; + + return rval; } -static int ipf_ip_qin(q, mb) -queue_t *q; -mblk_t *mb; +int +ipf_hk_v4_out(tok, data, arg) + hook_event_token_t tok; + hook_data_t data; + void *arg; { - struct iocblk *ioc; - int ret; - - if (fr_running <= 0) { - mb->b_prev = NULL; - freemsg(mb); - return 0; - } + hook_pkt_event_t *hpe = (hook_pkt_event_t *)data; + ipf_main_softc_t *softc = (ipf_main_softc_t *)arg; + ip_t *ip = hpe->hpe_hdr; + qpktinfo_t qpi; + int rval; + + qpi.qpi_real = (void *)hpe->hpe_ofp; + qpi.qpi_ill = (void *)hpe->hpe_ofp; + qpi.qpi_q = NULL; + qpi.qpi_m = hpe->hpe_mb; + qpi.qpi_data = hpe->hpe_hdr; + qpi.qpi_off = 0; + qpi.qpi_flags = hpe->hpe_flags; + if ((++ipf_pkts & 0xffff) == 0) + ipf_rand_push(qpi.qpi_m, M_LEN(qpi.qpi_m)); + + rval = ipf_check(softc, hpe->hpe_hdr, ip->ip_hl << 2, + (void *)hpe->hpe_ofp, 1, &qpi, hpe->hpe_mp); + if (rval == 0 && *hpe->hpe_mp == NULL) + rval = 1; + + hpe->hpe_hdr = qpi.qpi_data; + hpe->hpe_mb = qpi.qpi_m; + + return rval; +} - if (MTYPE(mb) != M_IOCTL) - return (*ipf_ip_inp)(q, mb); - READ_ENTER(&ipf_solaris); - if (fr_running <= 0) { - RWLOCK_EXIT(&ipf_solaris); - mb->b_prev = NULL; - freemsg(mb); - return 0; - } - ioc = (struct iocblk *)mb->b_rptr; +int +ipf_hk_v4_nic(tok, data, arg) + hook_event_token_t tok; + hook_data_t data; + void *arg; +{ + hook_nic_event_t *nic = (hook_nic_event_t *)data; + ipf_main_softc_t *softc = (ipf_main_softc_t *)arg; - switch (ioc->ioc_cmd) + /* + * Should pass the family through... + */ + switch (nic->hne_event) { - case DL_IOC_HDR_INFO: - fr_qif_update(qif_from_queue(q), mb); + case NE_PLUMB : + case NE_UNPLUMB : + ipf_sync(softc, (void *)nic->hne_nic); + ipf_nat_sync(softc, (void *)nic->hne_nic); + ipf_state_sync(softc, (void *)nic->hne_nic); break; - case I_LINK: - case I_UNLINK: - case SIOCSIFADDR: - case SIOCSIFFLAGS: -#ifdef IPFDEBUG - if (ipf_debug) - cmn_err(CE_NOTE, - "IP Filter: ipf_ip_qin() M_IOCTL type=0x%x", - ioc->ioc_cmd); -#endif - WRITE_ENTER(&ipfs_mutex); - if (synctimeoutid == 0) { - synctimeoutid = timeout(ipf_synctimeout, - NULL, - drv_usectohz(1000000) /*1 sec*/ - ); - } - RWLOCK_EXIT(&ipfs_mutex); + case NE_UP : + case NE_DOWN : break; - default: + case NE_ADDRESS_CHANGE : + if (nic->hne_lif == 0) { + ipf_sync(softc, (void *)nic->hne_nic); + ipf_nat_sync(softc, (void *)nic->hne_nic); + } break; } - RWLOCK_EXIT(&ipf_solaris); - return (*ipf_ip_inp)(q, mb); + + return 0; } -static int ipdrvattcnt = 0; -extern struct streamtab ipinfo; -void solipdrvattach() +int +ipf_hk_v6_in(tok, data, arg) + hook_event_token_t tok; + hook_data_t data; + void *arg; { -#ifdef IPFDEBUG - if (ipf_debug) - cmn_err(CE_NOTE, "IP Filter: solipdrvattach() %d ipinfo=0x%lx", - ipdrvattcnt, &ipinfo); -#endif + hook_pkt_event_t *hpe = (hook_pkt_event_t *)data; + ipf_main_softc_t *softc = (ipf_main_softc_t *)arg; + qpktinfo_t qpi; + int rval; + + qpi.qpi_real = (void *)hpe->hpe_ifp; + qpi.qpi_ill = (void *)hpe->hpe_ifp; + qpi.qpi_q = NULL; + qpi.qpi_m = hpe->hpe_mb; + qpi.qpi_data = hpe->hpe_hdr; + qpi.qpi_off = 0; + qpi.qpi_flags = hpe->hpe_flags; + if ((++ipf_pkts & 0xffff) == 0) + ipf_rand_push(qpi.qpi_m, M_LEN(qpi.qpi_m)); + + rval = ipf_check(softc, hpe->hpe_hdr, sizeof(ip6_t), + (void *)hpe->hpe_ifp, 0, &qpi, hpe->hpe_mp); + if (rval == 0 && *hpe->hpe_mp == NULL) + rval = 1; + + hpe->hpe_hdr = qpi.qpi_data; + hpe->hpe_mb = qpi.qpi_m; + + return rval; +} - if (++ipdrvattcnt == 1) { - if (ipf_ip_inp == NULL) { - ipf_ip_inp = ipinfo.st_wrinit->qi_putp; - ipinfo.st_wrinit->qi_putp = ipf_ip_qin; - } - } + +int +ipf_hk_v6_out(tok, data, arg) + hook_event_token_t tok; + hook_data_t data; + void *arg; +{ + hook_pkt_event_t *hpe = (hook_pkt_event_t *)data; + ipf_main_softc_t *softc = (ipf_main_softc_t *)arg; + qpktinfo_t qpi; + int rval; + + qpi.qpi_real = (void *)hpe->hpe_ofp; + qpi.qpi_ill = (void *)hpe->hpe_ofp; + qpi.qpi_q = NULL; + qpi.qpi_m = hpe->hpe_mb; + qpi.qpi_data = hpe->hpe_hdr; + qpi.qpi_off = 0; + qpi.qpi_flags = hpe->hpe_flags; + if ((++ipf_pkts & 0xffff) == 0) + ipf_rand_push(qpi.qpi_m, M_LEN(qpi.qpi_m)); + + rval = ipf_check(softc, hpe->hpe_hdr, sizeof(ip6_t), + (void *)hpe->hpe_ofp, 1, &qpi, hpe->hpe_mp); + if (rval == 0 && *hpe->hpe_mp == NULL) + rval = 1; + + hpe->hpe_hdr = qpi.qpi_data; + hpe->hpe_mb = qpi.qpi_m; + + return rval; } -int solipdrvdetach() + +int +ipf_hk_v6_nic(tok, data, arg) + hook_event_token_t tok; + hook_data_t data; + void *arg; { -#ifdef IPFDEBUG - if (ipf_debug) - cmn_err(CE_NOTE, "IP Filter: solipdrvdetach() %d ipinfo=0x%lx", - ipdrvattcnt, &ipinfo); -#endif + hook_nic_event_t *nic = (hook_nic_event_t *)data; + ipf_main_softc_t *softc = (ipf_main_softc_t *)arg; - WRITE_ENTER(&ipfs_mutex); - if (--ipdrvattcnt <= 0) { - if (ipf_ip_inp && (ipinfo.st_wrinit->qi_putp == ipf_ip_qin)) { - ipinfo.st_wrinit->qi_putp = ipf_ip_inp; - ipf_ip_inp = NULL; - } - if (synctimeoutid) { - untimeout(synctimeoutid); - synctimeoutid = 0; - } + switch (nic->hne_event) + { + case NE_PLUMB : + case NE_UNPLUMB : + break; + case NE_UP : + case NE_DOWN : + break; + case NE_ADDRESS_CHANGE : + break; } - RWLOCK_EXIT(&ipfs_mutex); - return ipdrvattcnt; + + return 0; } -/* - * attach the packet filter to each interface that is defined as having an - * IP address associated with it and save some of the info. for that struct - * so we're not out of date as soon as the ill disappears - but we must sync - * to be correct! - */ -void solattach() -{ - queue_t *in, *out; - struct frentry *f; - qif_t *qif, *qf2; - ipnat_t *np; - size_t len; - ill_t *il; - - for (il = ill_g_head; il; il = il->ill_next) { - in = il->ill_rq; - if (!in || !il->ill_wq) - continue; - out = il->ill_wq->q_next; +ipf_main_softc_t * +ipf_find_softc(x) + u_long x; +{ + ipf_main_softc_t *softc; - WRITE_ENTER(&ipfs_mutex); - /* - * Look for entry already setup for this device - */ - for (qif = qif_head; qif; qif = qif->qf_next) - if (qif->qf_iptr == in->q_ptr && - qif->qf_optr == out->q_ptr) - break; - if (qif) { - RWLOCK_EXIT(&ipfs_mutex); - continue; - } -#ifdef IPFDEBUGX - if (ipf_debug) - cmn_err(CE_NOTE, - "IP Filter: il %x ipt %x opt %x ipu %x opu %x i %x/%x", - il, in->q_ptr, out->q_ptr, in->q_qinfo->qi_putp, - out->q_qinfo->qi_putp, out->q_qinfo, in->q_qinfo); -#endif - KMALLOC(qif, qif_t *); - if (!qif) { - cmn_err(CE_WARN, - "IP Filter: malloc(%d) for qif_t failed", - sizeof(qif_t)); - RWLOCK_EXIT(&ipfs_mutex); - continue; - } + for (softc = ipf_instances; softc != NULL; softc = softc->ipf_next) + if (softc->ipf_idnum == x) + break; + return softc; +} - if (in->q_qinfo->qi_putp == fr_qin) { - for (qf2 = qif_head; qf2; qf2 = qf2->qf_next) - if (&qf2->qf_rqinit == in->q_qinfo) { - qif->qf_rqinfo = qf2->qf_rqinfo; - break; - } - if (!qf2) { -#ifdef IPFDEBUGX - if (ipf_debug) - cmn_err(CE_WARN, - "IP Filter: rq:%s put %x qi %x", - il->ill_name, in->q_qinfo->qi_putp, - in->q_qinfo); -#endif - RWLOCK_EXIT(&ipfs_mutex); - KFREE(qif); - continue; - } - } else - qif->qf_rqinfo = in->q_qinfo; - - if (out->q_qinfo->qi_putp == fr_qout) { - for (qf2 = qif_head; qf2; qf2 = qf2->qf_next) - if (&qf2->qf_wqinit == out->q_qinfo) { - qif->qf_wqinfo = qf2->qf_wqinfo; - break; - } - if (!qf2) { -#ifdef IPFDEBUGX - if (ipf_debug) - cmn_err(CE_WARN, - "IP Filter: wq:%s put %x qi %x", - il->ill_name, out->q_qinfo->qi_putp, - out->q_qinfo); -#endif - RWLOCK_EXIT(&ipfs_mutex); - KFREE(qif); - continue; - } - } else - qif->qf_wqinfo = out->q_qinfo; - - qif->qf_ill = il; - qif->qf_in = in; - qif->qf_out = out; - qif->qf_iptr = in->q_ptr; - qif->qf_optr = out->q_ptr; -#if SOLARIS2 < 8 - qif->qf_hl = il->ill_hdr_length; -#else - { - ire_t *ire; - mblk_t *m; - qif->qf_hl = 0; - qif->qf_sap = il->ill_sap; -# if 0 - /* - * Can't seem to lookup a route for the IP address on the - * interface itself. - */ - ire = ire_route_lookup(il->ill_ipif->ipif_lcl_addr, 0xffffffff, - 0, 0, NULL, NULL, NULL, - MATCH_IRE_DSTONLY|MATCH_IRE_RECURSIVE); - if ((ire != NULL) && (m = ire->ire_fp_mp)) - qif->qf_hl = m->b_wptr - m->b_rptr; -# endif - if ((qif->qf_hl == 0) && (il->ill_type > 0) && - (il->ill_type < 0x37) && - (hdrsizes[il->ill_type][0] == il->ill_type)) - qif->qf_hl = hdrsizes[il->ill_type][1]; - - /* DREADFUL VLAN HACK - JUST HERE TO CHECK IT WORKS */ - if (il->ill_type == IFT_ETHER && - il->ill_name[0] == 'c' && il->ill_name[1] == 'e' && - isdigit(il->ill_name[2]) && il->ill_name_length >= 6) { - cmn_err(CE_NOTE, "VLAN HACK ENABLED"); - qif->qf_hl += 4; - } - /* DREADFUL VLAN HACK - JUST HERE TO CHECK IT WORKS */ +static void * +ipf_instance_create(netid_t id) +{ + ipf_main_softc_t *softc; - if (qif->qf_hl == 0 && il->ill_type != IFT_OTHER) - cmn_err(CE_WARN, - "Unknown layer 2 header size for %s type %d", - il->ill_name, il->ill_type); - } + softc = ipf_create_all(NULL); + if (softc != NULL) { + softc->ipf_next = ipf_instances; + ipf_instances = softc; - /* - * XXX Awful hack for PPP; fix when PPP/snoop fixed. - */ - if (il->ill_type == IFT_ETHER && !il->ill_bcast_addr_length) - qif->qf_hl = 0; -#endif - strncpy(qif->qf_name, il->ill_name, sizeof(qif->qf_name)); - qif->qf_name[sizeof(qif->qf_name) - 1] = '\0'; + softc->ipf_idnum = id; + } - qif->qf_next = qif_head; - qif_head = qif; + return softc; +} - /* - * Activate any rules directly associated with this interface - */ - WRITE_ENTER(&ipf_mutex); - for (f = ipfilter[0][fr_active]; f; f = f->fr_next) { - if ((f->fr_ifa == (struct ifnet *)-1)) { - len = strlen(f->fr_ifname) + 1; - if ((len != 0) && - (len == (size_t)il->ill_name_length) && - !strncmp(il->ill_name, f->fr_ifname, len)) - f->fr_ifa = il; - } - } - for (f = ipfilter[1][fr_active]; f; f = f->fr_next) { - if ((f->fr_ifa == (struct ifnet *)-1)) { - len = strlen(f->fr_ifname) + 1; - if ((len != 0) && - (len == (size_t)il->ill_name_length) && - !strncmp(il->ill_name, f->fr_ifname, len)) - f->fr_ifa = il; - } - } -#if SOLARIS2 >= 8 - for (f = ipfilter6[0][fr_active]; f; f = f->fr_next) { - if ((f->fr_ifa == (struct ifnet *)-1)) { - len = strlen(f->fr_ifname) + 1; - if ((len != 0) && - (len == (size_t)il->ill_name_length) && - !strncmp(il->ill_name, f->fr_ifname, len)) - f->fr_ifa = il; - } - } - for (f = ipfilter6[1][fr_active]; f; f = f->fr_next) { - if ((f->fr_ifa == (struct ifnet *)-1)) { - len = strlen(f->fr_ifname) + 1; - if ((len != 0) && - (len == (size_t)il->ill_name_length) && - !strncmp(il->ill_name, f->fr_ifname, len)) - f->fr_ifa = il; - } - } -#endif - RWLOCK_EXIT(&ipf_mutex); - WRITE_ENTER(&ipf_nat); - for (np = nat_list; np; np = np->in_next) { - if ((np->in_ifp == (struct ifnet *)-1)) { - len = strlen(np->in_ifname) + 1; - if ((len != 0) && - (len == (size_t)il->ill_name_length) && - !strncmp(il->ill_name, np->in_ifname, len)) - np->in_ifp = il; - } - } - RWLOCK_EXIT(&ipf_nat); - bcopy((caddr_t)qif->qf_rqinfo, (caddr_t)&qif->qf_rqinit, - sizeof(struct qinit)); - qif->qf_rqinit.qi_putp = fr_qin; -#ifdef IPFDEBUG - if (ipf_debug) - cmn_err(CE_NOTE, - "IP Filter: solattach: in queue(%lx)->q_qinfo FROM %lx TO %lx", - in, in->q_qinfo, &qif->qf_rqinit); -#endif - in->q_qinfo = &qif->qf_rqinit; +static void +ipf_instance_shutdown(netid_t id, void *arg) +{ + ipf_main_softc_t *softc = arg; - bcopy((caddr_t)qif->qf_wqinfo, (caddr_t)&qif->qf_wqinit, - sizeof(struct qinit)); - qif->qf_wqinit.qi_putp = fr_qout; -#ifdef IPFDEBUG - if (ipf_debug) - cmn_err(CE_NOTE, - "IP Filter: solattach: out queue(%lx)->q_qinfo FROM %lx TO %lx", - out, out->q_qinfo, &qif->qf_wqinit); -#endif - out->q_qinfo = &qif->qf_wqinit; - - ire_walk(ipf_ire_walk, (char *)qif); - RWLOCK_EXIT(&ipfs_mutex); - cmn_err(CE_CONT, "IP Filter: attach to [%s,%d] - %s\n", - qif->qf_name, il->ill_ppa, -#if SOLARIS2 >= 8 - il->ill_isv6 ? "IPv6" : "IPv4" -#else - "IPv4" -#endif - ); - } - if (!qif_head) - cmn_err(CE_CONT, "IP Filter: not attached to any interfaces\n"); - return; + (void) ipf_detach_instance(softc); } -/* - * look for bad consistancies between the list of interfaces the filter knows - * about and those which are currently configured. - */ -int ipfsync() +static void +ipf_instance_destroy(netid_t id, void *arg) { - register struct frentry *f; - register ipnat_t *np; - register qif_t *qif, **qp; - register ill_t *il; - queue_t *in, *out; - - WRITE_ENTER(&ipfs_mutex); - for (qp = &qif_head; (qif = *qp); ) { - for (il = ill_g_head; il; il = il->ill_next) - if ((qif->qf_ill == il) && - !strcmp(qif->qf_name, il->ill_name)) { -#if SOLARIS2 < 8 - mblk_t *m = il->ill_hdr_mp; - - qif->qf_hl = il->ill_hdr_length; - if (m && qif->qf_hl != (m->b_wptr - m->b_rptr)) - cmn_err(CE_NOTE, - "IP Filter: ILL Header Length Mismatch\n"); -#endif - break; - } - if (il) { - qp = &qif->qf_next; - continue; - } - cmn_err(CE_CONT, "IP Filter: detaching [%s] - %s\n", - qif->qf_name, -#if SOLARIS2 >= 8 - (qif->qf_sap == IP6_DL_SAP) ? "IPv6" : "IPv4" -#else - "IPv4" -#endif - ); - *qp = qif->qf_next; + ipf_main_softc_t *softc = arg; + ipf_main_softc_t **instp; - /* - * Disable any rules directly associated with this interface - */ - WRITE_ENTER(&ipf_nat); - for (np = nat_list; np; np = np->in_next) - if (np->in_ifp == (void *)qif->qf_ill) - np->in_ifp = (struct ifnet *)-1; - RWLOCK_EXIT(&ipf_nat); - WRITE_ENTER(&ipf_mutex); - for (f = ipfilter[0][fr_active]; f; f = f->fr_next) - if (f->fr_ifa == (void *)qif->qf_ill) - f->fr_ifa = (struct ifnet *)-1; - for (f = ipfilter[1][fr_active]; f; f = f->fr_next) - if (f->fr_ifa == (void *)qif->qf_ill) - f->fr_ifa = (struct ifnet *)-1; -#if SOLARIS2 >= 8 - for (f = ipfilter6[0][fr_active]; f; f = f->fr_next) - if (f->fr_ifa == (void *)qif->qf_ill) - f->fr_ifa = (struct ifnet *)-1; - for (f = ipfilter6[1][fr_active]; f; f = f->fr_next) - if (f->fr_ifa == (void *)qif->qf_ill) - f->fr_ifa = (struct ifnet *)-1; -#endif - -#if 0 /* XXX */ - /* - * As well as the ill disappearing when a device is unplumb'd, - * it also appears that the associated queue structures also - * disappear - at least in the case of ppp, which is the most - * volatile here. Thanks to Greg for finding this problem. - */ - /* - * Restore q_qinfo pointers in interface queues - */ - out = qif->qf_out; - in = qif->qf_in; - if (in) { -# ifdef IPFDEBUG - if (ipf_debug) - cmn_err(CE_NOTE, - "IP Filter: ipfsync: in queue(%lx)->q_qinfo FROM %lx TO %lx", - in, in->q_qinfo, qif->qf_rqinfo); -# endif - in->q_qinfo = qif->qf_rqinfo; - } - if (out) { -# ifdef IPFDEBUG - if (ipf_debug) - cmn_err(CE_NOTE, - "IP Filter: ipfsync: out queue(%lx)->q_qinfo FROM %lx TO %lx", - out, out->q_qinfo, qif->qf_wqinfo); -# endif - out->q_qinfo = qif->qf_wqinfo; + for (instp = &ipf_instances; *instp != NULL; ) { + if (*instp == softc) { + *instp = softc->ipf_next; + break; } -#endif /* XXX */ - RWLOCK_EXIT(&ipf_mutex); - KFREE(qif); - qif = *qp; + instp = &(*instp)->ipf_next; } - RWLOCK_EXIT(&ipfs_mutex); - solattach(); - frsync(); - /* - * Resync. any NAT `connections' using this interface and its IP #. - */ - for (il = ill_g_head; il; il = il->ill_next) { - ip_natsync((void *)il); - ip_statesync((void *)il); - } - return 0; + ipf_destroy_all(softc); } -/* - * unhook the IP filter from all defined interfaces with IP addresses - */ -int soldetach() +static int +ipf_stack_init() { - queue_t *in, *out; - qif_t *qif, **qp; - ill_t *il; - - WRITE_ENTER(&ipfs_mutex); - /* - * Make two passes, first get rid of all the unknown devices, next - * unlink known devices. - */ - for (qp = &qif_head; (qif = *qp); ) { - for (il = ill_g_head; il; il = il->ill_next) - if (qif->qf_ill == il) - break; - if (il) { - qp = &qif->qf_next; - continue; - } - cmn_err(CE_CONT, "IP Filter: removing [%s]\n", qif->qf_name); - *qp = qif->qf_next; - KFREE(qif); - } + ipf_inst = net_instance_alloc(NETINFO_VERSION); + ipf_inst->nin_name = "ipf"; + ipf_inst->nin_create = ipf_instance_create; + ipf_inst->nin_destroy = ipf_instance_destroy; + ipf_inst->nin_shutdown = ipf_instance_shutdown; + return net_instance_register(ipf_inst); +} - while ((qif = qif_head)) { - qif_head = qif->qf_next; - for (il = ill_g_head; il; il = il->ill_next) - if (qif->qf_ill == il) - break; - if (il) { - in = qif->qf_in; - out = qif->qf_out; - cmn_err(CE_CONT, "IP Filter: detaching [%s,%d] - %s\n", - qif->qf_name, il->ill_ppa, -#if SOLARIS2 >= 8 - (qif->qf_sap == IP6_DL_SAP) ? "IPv6" : "IPv4" -#else - "IPv4" -#endif - ); -#ifdef IPFDEBUG - if (ipf_debug) - cmn_err(CE_NOTE, - "IP Filter: soldetach: in queue(%lx)->q_qinfo FROM %lx TO %lx", - in, in->q_qinfo, qif->qf_rqinfo); -#endif - in->q_qinfo = qif->qf_rqinfo; - - /* - * and the write queue... - */ -#ifdef IPFDEBUG - if (ipf_debug) - cmn_err(CE_NOTE, - "IP Filter: soldetach: out queue(%lx)->q_qinfo FROM %lx TO %lx", - out, out->q_qinfo, qif->qf_wqinfo); -#endif - out->q_qinfo = qif->qf_wqinfo; - } - KFREE(qif); - } - RWLOCK_EXIT(&ipfs_mutex); - return ipldetach(); +static void +ipf_stack_fini() +{ + net_instance_unregister(ipf_inst); + net_instance_free(ipf_inst); + ipf_inst = NULL; } -#ifdef IPFDEBUG -void printire(ire) -ire_t *ire; +void +ipf_attach_hooks(softc) + ipf_main_softc_t *softc; { - if (!ipf_debug) - return; - printf("ire: ll_hdr_mp %p rfq %p stq %p src_addr %x max_frag %d\n", -# if SOLARIS2 >= 8 - NULL, -# else - ire->ire_ll_hdr_mp, -# endif - ire->ire_rfq, ire->ire_stq, - ire->ire_src_addr, ire->ire_max_frag); - printf("ire: mask %x addr %x gateway_addr %x type %d\n", - ire->ire_mask, ire->ire_addr, ire->ire_gateway_addr, - ire->ire_type); - printf("ire: ll_hdr_length %d ll_hdr_saved_mp %p\n", - ire->ire_ll_hdr_length, -# if SOLARIS2 >= 8 - NULL -# else - ire->ire_ll_hdr_saved_mp -# endif - ); + softc->ipf_nd_v4 = net_protocol_lookup(softc->ipf_idnum, NHF_INET); + softc->ipf_nd_v6 = net_protocol_lookup(softc->ipf_idnum, NHF_INET6); + + HOOK_INIT(softc->ipf_hk_v4_in, ipf_hk_v4_in, "ipf_v4_in", softc); + if (net_hook_register(softc->ipf_nd_v4, NH_PHYSICAL_IN, + softc->ipf_hk_v4_in)) + cmn_err(CE_WARN, "register-hook(v4-in) failed"); + + HOOK_INIT(softc->ipf_hk_v4_out, ipf_hk_v4_out, "ipf_v4_out", softc); + if (net_hook_register(softc->ipf_nd_v4, NH_PHYSICAL_OUT, + softc->ipf_hk_v4_out)) + cmn_err(CE_WARN, "register-hook(v4-out) failed"); + + HOOK_INIT(softc->ipf_hk_v4_nic, ipf_hk_v4_nic, "ipf_v4_event", softc); + if (net_hook_register(softc->ipf_nd_v4, NH_NIC_EVENTS, + softc->ipf_hk_v4_nic)) + cmn_err(CE_WARN, "register-hook(v4-nic) failed"); + + HOOK_INIT(softc->ipf_hk_v6_in, ipf_hk_v6_in, "ipf_v6_in", softc); + if (net_hook_register(softc->ipf_nd_v6, NH_PHYSICAL_IN, + softc->ipf_hk_v6_in)) + cmn_err(CE_WARN, "register-hook(v6-in) failed"); + + HOOK_INIT(softc->ipf_hk_v6_out, ipf_hk_v6_out, "ipf_v6_out", softc); + if (net_hook_register(softc->ipf_nd_v6, NH_PHYSICAL_OUT, + softc->ipf_hk_v6_out)) + cmn_err(CE_WARN, "register-hook(v6-out) failed"); + + HOOK_INIT(softc->ipf_hk_v6_nic, ipf_hk_v6_nic, "ipf_v6_event", softc); + if (net_hook_register(softc->ipf_nd_v6, NH_NIC_EVENTS, + softc->ipf_hk_v6_nic)) + cmn_err(CE_WARN, "register-hook(v6-nic) failed"); + + if (softc->ipf_get_loopback) + ipf_attach_loopback(softc); } -#endif -int ipfr_fastroute(ip, mb, mpp, fin, fdp) -ip_t *ip; -mblk_t *mb, **mpp; -fr_info_t *fin; -frdest_t *fdp; +void +ipf_detach_hooks(softc) + ipf_main_softc_t *softc; { -#ifdef USE_INET6 - ip6_t *ip6 = (ip6_t *)ip; -#endif - ire_t *ir, *dir, *gw; - struct in_addr dst; - queue_t *q = NULL; - mblk_t *mp = NULL; - size_t hlen = 0; - frentry_t *fr; - frdest_t fd; - ill_t *ifp; - u_char *s; - qif_t *qf; - int p; - -#ifndef sparc - u_short __iplen, __ipoff; -#endif - qf = fin->fin_qif; - /* - * If this is a duplicate mblk then we want ip to point at that - * data, not the original, if and only if it is already pointing at - * the current mblk data. - */ - if ((ip == (ip_t *)qf->qf_m->b_rptr) && (qf->qf_m != mb)) - ip = (ip_t *)mb->b_rptr; + if (softc->ipf_get_loopback) + ipf_detach_loopback(softc); - /* - * If there is another M_PROTO, we don't want it - */ - if (*mpp != mb) { - mp = *mpp; - (void) unlinkb(mp); - mp = (*mpp)->b_cont; - (*mpp)->b_cont = NULL; - (*mpp)->b_prev = NULL; - freemsg(*mpp); - *mpp = mp; - } + if (softc->ipf_nd_v4 != NULL) { + if (net_hook_unregister(softc->ipf_nd_v4, NH_PHYSICAL_IN, + softc->ipf_hk_v4_in)) + cmn_err(CE_WARN, "unregister-hook(v4-in) failed"); + hook_free(softc->ipf_hk_v4_in); - if (!fdp) { - ipif_t *ipif; + if (net_hook_unregister(softc->ipf_nd_v4, NH_PHYSICAL_OUT, + softc->ipf_hk_v4_out)) + cmn_err(CE_WARN, "unregister-hook(v4-out) failed"); + hook_free(softc->ipf_hk_v4_out); - ifp = fin->fin_ifp; - ipif = ifp->ill_ipif; - if (!ipif) - goto bad_fastroute; -#if SOLARIS2 > 5 - ir = ire_ctable_lookup(ipif->ipif_local_addr, 0, IRE_LOCAL, - NULL, NULL, MATCH_IRE_TYPE); -#else - ir = ire_lookup_myaddr(ipif->ipif_local_addr); -#endif - if (!ir) - ir = (ire_t *)-1; + if (net_hook_unregister(softc->ipf_nd_v4, NH_NIC_EVENTS, + softc->ipf_hk_v4_nic)) + cmn_err(CE_WARN, "unregister-hook(v4-nic) failed"); + hook_free(softc->ipf_hk_v4_nic); - fd.fd_ifp = (struct ifnet *)ir; - fd.fd_ip = ip->ip_dst; - fdp = &fd; + net_protocol_release(softc->ipf_nd_v4); + softc->ipf_nd_v4 = NULL; } - ir = (ire_t *)fdp->fd_ifp; + if (softc->ipf_nd_v6 != NULL) { + if (net_hook_unregister(softc->ipf_nd_v6, NH_PHYSICAL_IN, + softc->ipf_hk_v6_in)) + cmn_err(CE_WARN, "unregister-hook(v6-in) failed"); + hook_free(softc->ipf_hk_v6_in); - if (fdp->fd_ip.s_addr) - dst = fdp->fd_ip; - else - dst.s_addr = fin->fin_fi.fi_daddr; + if (net_hook_unregister(softc->ipf_nd_v6, NH_PHYSICAL_OUT, + softc->ipf_hk_v6_out)) + cmn_err(CE_WARN, "unregister-hook(v6-out) failed"); + hook_free(softc->ipf_hk_v6_out); -#if SOLARIS2 >= 6 - gw = NULL; - if (fin->fin_v == 4) { - p = ip->ip_p; - dir = ire_route_lookup(dst.s_addr, 0xffffffff, 0, 0, NULL, - &gw, NULL, MATCH_IRE_DSTONLY| - MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE); - } -# ifdef USE_INET6 - else if (fin->fin_v == 6) { - p = ip6->ip6_nxt; - dir = ire_route_lookup_v6(&ip6->ip6_dst, NULL, 0, 0, - NULL, &gw, NULL, MATCH_IRE_DSTONLY| - MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE); - } -# endif -#else - dir = ire_lookup(dst.s_addr); -#endif -#if SOLARIS2 < 8 - if (dir) - if (!dir->ire_ll_hdr_mp || !dir->ire_ll_hdr_length) - dir = NULL; -#else - if (dir) - if (!dir->ire_fp_mp || !dir->ire_dlureq_mp) - dir = NULL; -#endif + if (net_hook_unregister(softc->ipf_nd_v6, NH_NIC_EVENTS, + softc->ipf_hk_v6_nic)) + cmn_err(CE_WARN, "unregister-hook(v6-nic) failed"); + hook_free(softc->ipf_hk_v6_nic); - if (!ir) - ir = dir; + net_protocol_release(softc->ipf_nd_v6); + softc->ipf_nd_v6 = NULL; + } +} - if (ir && dir) { - ifp = ire_to_ill(ir); - if (ifp == NULL) - goto bad_fastroute; - fr = fin->fin_fr; +int +ipf_set_loopback(softc, t, p) + struct ipf_main_softc_s *softc; + ipftuneable_t *t; + ipftuneval_t *p; +{ + if (*t->ipft_pint == p->ipftu_int) + return 0; + *t->ipft_pint = p->ipftu_int; + if (p->ipftu_int == 0) { /* - * In case we're here due to "to <if>" being used with - * "keep state", check that we're going in the correct - * direction. + * Turning it off. */ - if ((fr != NULL) && (fdp->fd_ifp != NULL) && - (fin->fin_rev != 0) && (fdp == &fr->fr_tif)) - return 1; - - fin->fin_ifp = ifp; - if (fin->fin_out == 0) { - fin->fin_fr = ipacct[1][fr_active]; - if ((fin->fin_fr != NULL) && - (fr_scanlist(FR_NOMATCH, ip, fin, mb)&FR_ACCOUNT)){ - ATOMIC_INCL(frstats[1].fr_acct); - } - fin->fin_fr = NULL; - if (!fr || !(fr->fr_flags & FR_RETMASK)) - (void) fr_checkstate(ip, fin); - (void) ip_natout(ip, fin); - } -#ifndef sparc - if (fin->fin_v == 4) { - __iplen = (u_short)ip->ip_len, - __ipoff = (u_short)ip->ip_off; - - ip->ip_len = htons(__iplen); - ip->ip_off = htons(__ipoff); - } -#endif - -#if SOLARIS2 < 8 - mp = dir->ire_ll_hdr_mp; - hlen = dir->ire_ll_hdr_length; -#else - mp = dir->ire_fp_mp; - hlen = mp ? mp->b_wptr - mp->b_rptr : 0; - mp = dir->ire_dlureq_mp; -#endif - if (mp != NULL) { - s = mb->b_rptr; - if ( -#if SOLARIS2 >= 6 - (dohwcksum && - ifp->ill_ick.ick_magic == ICK_M_CTL_MAGIC) || -#endif - (hlen && (s - mb->b_datap->db_base) >= hlen)) { - s -= hlen; - mb->b_rptr = (u_char *)s; - bcopy((char *)mp->b_rptr, (char *)s, hlen); - } else { - mblk_t *mp2; - - mp2 = copyb(mp); - if (!mp2) - goto bad_fastroute; - linkb(mp2, mb); - mb = mp2; - } - } - *mpp = mb; - - if (ir->ire_stq) - q = ir->ire_stq; - else if (ir->ire_rfq) - q = WR(ir->ire_rfq); - if (q) { - mb->b_prev = NULL; - mb->b_queue = q; - RWLOCK_EXIT(&ipfs_mutex); - RWLOCK_EXIT(&ipf_solaris); -#if SOLARIS2 >= 6 - if ((p == IPPROTO_TCP) && dohwcksum && - (ifp->ill_ick.ick_magic == ICK_M_CTL_MAGIC)) { - tcphdr_t *tcp; - u_32_t t; - - tcp = (tcphdr_t *)((char *)ip + fin->fin_hlen); - t = ip->ip_src.s_addr; - t += ip->ip_dst.s_addr; - t += 30; - t = (t & 0xffff) + (t >> 16); - tcp->th_sum = t & 0xffff; - } -#endif - putnext(q, mb); - READ_ENTER(&ipf_solaris); - READ_ENTER(&ipfs_mutex); - ipl_frouteok[0]++; - *mpp = NULL; - return 0; - } + if (softc->ipf_running == 1) + ipf_detach_loopback(softc); + return 0; } -bad_fastroute: - mb->b_prev = NULL; - freemsg(mb); - ipl_frouteok[1]++; - *mpp = NULL; - return -1; + if (softc->ipf_running == 1) + ipf_attach_loopback(softc); + return 0; } -void copyout_mblk(m, off, len, buf) -mblk_t *m; -size_t off, len; -char *buf; +void +ipf_attach_loopback(softc) + ipf_main_softc_t *softc; { - u_char *s, *bp = (u_char *)buf; - size_t mlen, olen, clen; - for (; m && len; m = m->b_cont) { - if (MTYPE(m) != M_DATA) - continue; - s = m->b_rptr; - mlen = m->b_wptr - s; - olen = MIN(off, mlen); - if ((olen == mlen) || (olen < off)) { - off -= olen; - continue; - } else if (olen) { - off -= olen; - s += olen; - mlen -= olen; - } - clen = MIN(mlen, len); - bcopy(s, bp, clen); - len -= clen; - bp += clen; - } + HOOK_INIT(softc->ipf_hk_loop_v4_in, ipf_hk_v4_in, + "ipf_v4_loop_in", softc); + if (net_hook_register(softc->ipf_nd_v4, NH_LOOPBACK_IN, + softc->ipf_hk_loop_v4_in)) + cmn_err(CE_WARN, "register-hook(v4-loop_in) failed"); + + HOOK_INIT(softc->ipf_hk_loop_v4_out, ipf_hk_v4_out, + "ipf_v4_loop_out", softc); + if (net_hook_register(softc->ipf_nd_v4, NH_LOOPBACK_OUT, + softc->ipf_hk_loop_v4_out)) + cmn_err(CE_WARN, "register-hook(v4-loop_out) failed"); + + HOOK_INIT(softc->ipf_hk_loop_v6_in, ipf_hk_v6_in, + "ipf_v6_loop_in", softc); + if (net_hook_register(softc->ipf_nd_v6, NH_LOOPBACK_IN, + softc->ipf_hk_loop_v6_in)) + cmn_err(CE_WARN, "register-hook(v6-loop_in) failed"); + + HOOK_INIT(softc->ipf_hk_loop_v6_out, ipf_hk_v6_out, + "ipf_v6_loop_out", softc); + if (net_hook_register(softc->ipf_nd_v6, NH_LOOPBACK_OUT, + softc->ipf_hk_loop_v6_out)) + cmn_err(CE_WARN, "register-hook(v6-loop_out) failed"); } -void copyin_mblk(m, off, len, buf) -mblk_t *m; -size_t off, len; -char *buf; +void +ipf_detach_loopback(softc) + ipf_main_softc_t *softc; { - u_char *s, *bp = (u_char *)buf; - size_t mlen, olen, clen; - for (; m && len; m = m->b_cont) { - if (MTYPE(m) != M_DATA) - continue; - s = m->b_rptr; - mlen = m->b_wptr - s; - olen = MIN(off, mlen); - if ((olen == mlen) || (olen < off)) { - off -= olen; - continue; - } else if (olen) { - off -= olen; - s += olen; - mlen -= olen; - } - clen = MIN(mlen, len); - bcopy(bp, s, clen); - len -= clen; - bp += clen; - } + if (net_hook_unregister(softc->ipf_nd_v4, NH_LOOPBACK_IN, + softc->ipf_hk_loop_v4_in)) + cmn_err(CE_WARN, "unregister-hook(v4-loop_in) failed"); + hook_free(softc->ipf_hk_v4_in); + + if (net_hook_unregister(softc->ipf_nd_v4, NH_LOOPBACK_OUT, + softc->ipf_hk_loop_v4_out)) + cmn_err(CE_WARN, "unregister-hook(v4-loop_out) failed"); + hook_free(softc->ipf_hk_v4_out); + + if (net_hook_unregister(softc->ipf_nd_v6, NH_LOOPBACK_IN, + softc->ipf_hk_loop_v6_in)) + cmn_err(CE_WARN, "unregister-hook(v6-loop_in) failed"); + hook_free(softc->ipf_hk_v6_in); + + if (net_hook_unregister(softc->ipf_nd_v6, NH_LOOPBACK_OUT, + softc->ipf_hk_loop_v6_out)) + cmn_err(CE_WARN, "unregister-hook(v6-loop_out) failed"); + hook_free(softc->ipf_hk_v6_out); } +#endif - -int fr_verifysrc(ipa, ifp) -struct in_addr ipa; -void *ifp; +static int +ipf_detach_instance(ipf_main_softc_t *softc) { - ire_t *ir, *dir, *gw; + /* + * And no proxy modules loaded. + */ + if (softc->ipf_refcnt != 0) + return DDI_FAILURE; + /* + * If it didn't finish loading or is already + * unloading, fail. + */ + if (softc->ipf_running == -2) + return DDI_FAILURE; -#if SOLARIS2 >= 6 - dir = ire_route_lookup(ipa.s_addr, 0xffffffff, 0, 0, NULL, &gw, NULL, - MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT| - MATCH_IRE_RECURSIVE); -#else - dir = ire_lookup(ipa.s_addr); -#endif + /* + * Make sure we're the only one's modifying things. + * With this lock others should just fall out of + * the loop. + */ + WRITE_ENTER(&softc->ipf_global); + if (softc->ipf_running == -2) { + RWLOCK_EXIT(&softc->ipf_global); + return DDI_FAILURE; + } + if (softc->ipf_running == 1) + (void) ipfdetach(softc); + softc->ipf_running = -2; - if (!dir) - return 0; - return (ire_to_ill(dir) == ifp); + RWLOCK_EXIT(&softc->ipf_global); + + if (softc->ipf_slow_ch != 0) { + (void) untimeout(softc->ipf_slow_ch); + softc->ipf_slow_ch = 0; + } + + return DDI_SUCCESS; } + diff --git a/sys/tree.h b/sys/tree.h new file mode 100644 index 0000000000000..5855885449518 --- /dev/null +++ b/sys/tree.h @@ -0,0 +1,750 @@ +/* $NetBSD: tree.h,v 1.8 2004/03/28 19:38:30 provos Exp $ */ +/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */ +/* $FreeBSD: src/sys/sys/tree.h,v 1.7 2007/12/28 07:03:26 jasone Exp $ */ + +/*- + * Copyright 2002 Niels Provos <provos@citi.umich.edu> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_TREE_H_ +#define _SYS_TREE_H_ + +/* + * This file defines data structures for different types of trees: + * splay trees and red-black trees. + * + * A splay tree is a self-organizing data structure. Every operation + * on the tree causes a splay to happen. The splay moves the requested + * node to the root of the tree and partly rebalances it. + * + * This has the benefit that request locality causes faster lookups as + * the requested nodes move to the top of the tree. On the other hand, + * every lookup causes memory writes. + * + * The Balance Theorem bounds the total access time for m operations + * and n inserts on an initially empty tree as O((m + n)lg n). The + * amortized cost for a sequence of m accesses to a splay tree is O(lg n); + * + * A red-black tree is a binary search tree with the node color as an + * extra attribute. It fulfills a set of conditions: + * - every search path from the root to a leaf consists of the + * same number of black nodes, + * - each red node (except for the root) has a black parent, + * - each leaf node is black. + * + * Every operation on a red-black tree is bounded as O(lg n). + * The maximum height of a red-black tree is 2lg (n+1). + */ + +#define SPLAY_HEAD(name, type) \ +struct name { \ + struct type *sph_root; /* root of the tree */ \ +} + +#define SPLAY_INITIALIZER(root) \ + { NULL } + +#define SPLAY_INIT(root) do { \ + (root)->sph_root = NULL; \ +} while (/*CONSTCOND*/ 0) + +#define SPLAY_ENTRY(type) \ +struct { \ + struct type *spe_left; /* left element */ \ + struct type *spe_right; /* right element */ \ +} + +#define SPLAY_LEFT(elm, field) (elm)->field.spe_left +#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right +#define SPLAY_ROOT(head) (head)->sph_root +#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) + +/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ +#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (/*CONSTCOND*/ 0) + +#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (/*CONSTCOND*/ 0) + +#define SPLAY_LINKLEFT(head, tmp, field) do { \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ +} while (/*CONSTCOND*/ 0) + +#define SPLAY_LINKRIGHT(head, tmp, field) do { \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ +} while (/*CONSTCOND*/ 0) + +#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \ + SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \ + SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \ +} while (/*CONSTCOND*/ 0) + +/* Generates prototypes and inline functions */ + +#define SPLAY_PROTOTYPE(name, type, field, cmp) \ +void name##_SPLAY(struct name *, struct type *); \ +void name##_SPLAY_MINMAX(struct name *, int); \ +struct type *name##_SPLAY_INSERT(struct name *, struct type *); \ +struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \ + \ +/* Finds the node with the same key as elm */ \ +static __inline struct type * \ +name##_SPLAY_FIND(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) \ + return(NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) \ + return (head->sph_root); \ + return (NULL); \ +} \ + \ +static __inline struct type * \ +name##_SPLAY_NEXT(struct name *head, struct type *elm) \ +{ \ + name##_SPLAY(head, elm); \ + if (SPLAY_RIGHT(elm, field) != NULL) { \ + elm = SPLAY_RIGHT(elm, field); \ + while (SPLAY_LEFT(elm, field) != NULL) { \ + elm = SPLAY_LEFT(elm, field); \ + } \ + } else \ + elm = NULL; \ + return (elm); \ +} \ + \ +static __inline struct type * \ +name##_SPLAY_MIN_MAX(struct name *head, int val) \ +{ \ + name##_SPLAY_MINMAX(head, val); \ + return (SPLAY_ROOT(head)); \ +} + +/* Main splay operation. + * Moves node close to the key of elm to top + */ +#define SPLAY_GENERATE(name, type, field, cmp) \ +struct type * \ +name##_SPLAY_INSERT(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) { \ + SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ + } else { \ + int __comp; \ + name##_SPLAY(head, elm); \ + __comp = (cmp)(elm, (head)->sph_root); \ + if(__comp < 0) { \ + SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\ + SPLAY_RIGHT(elm, field) = (head)->sph_root; \ + SPLAY_LEFT((head)->sph_root, field) = NULL; \ + } else if (__comp > 0) { \ + SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT(elm, field) = (head)->sph_root; \ + SPLAY_RIGHT((head)->sph_root, field) = NULL; \ + } else \ + return ((head)->sph_root); \ + } \ + (head)->sph_root = (elm); \ + return (NULL); \ +} \ + \ +struct type * \ +name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *__tmp; \ + if (SPLAY_EMPTY(head)) \ + return (NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) { \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\ + } else { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\ + name##_SPLAY(head, elm); \ + SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ + } \ + return (elm); \ + } \ + return (NULL); \ +} \ + \ +void \ +name##_SPLAY(struct name *head, struct type *elm) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ + int __comp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) > 0){ \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} \ + \ +/* Splay with either the minimum or the maximum element \ + * Used to find minimum or maximum element in tree. \ + */ \ +void name##_SPLAY_MINMAX(struct name *head, int __comp) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while (1) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp > 0) { \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} + +#define SPLAY_NEGINF -1 +#define SPLAY_INF 1 + +#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y) +#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) +#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) +#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) +#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) +#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) + +#define SPLAY_FOREACH(x, name, head) \ + for ((x) = SPLAY_MIN(name, head); \ + (x) != NULL; \ + (x) = SPLAY_NEXT(name, head, x)) + +/* Macros that define a red-black tree */ +#define RB_HEAD(name, type) \ +struct name { \ + struct type *rbh_root; /* root of the tree */ \ +} + +#define RB_INITIALIZER(root) \ + { NULL } + +#define RB_INIT(root) do { \ + (root)->rbh_root = NULL; \ +} while (/*CONSTCOND*/ 0) + +/* + * Undef for Linux + */ +#undef RB_BLACK +#undef RB_RED +#undef RB_ROOT + +#define RB_BLACK 0 +#define RB_RED 1 +#define RB_ENTRY(type) \ +struct { \ + struct type *rbe_left; /* left element */ \ + struct type *rbe_right; /* right element */ \ + struct type *rbe_parent; /* parent element */ \ + int rbe_color; /* node color */ \ +} + +#define RB_LEFT(elm, field) (elm)->field.rbe_left +#define RB_RIGHT(elm, field) (elm)->field.rbe_right +#define RB_PARENT(elm, field) (elm)->field.rbe_parent +#define RB_COLOR(elm, field) (elm)->field.rbe_color +#define RB_ROOT(head) (head)->rbh_root +#define RB_EMPTY(head) (RB_ROOT(head) == NULL) + +#define RB_SET(elm, parent, field) do { \ + RB_PARENT(elm, field) = parent; \ + RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ + RB_COLOR(elm, field) = RB_RED; \ +} while (/*CONSTCOND*/ 0) + +#define RB_SET_BLACKRED(black, red, field) do { \ + RB_COLOR(black, field) = RB_BLACK; \ + RB_COLOR(red, field) = RB_RED; \ +} while (/*CONSTCOND*/ 0) + +#ifndef RB_AUGMENT +#define RB_AUGMENT(x) do {} while (0) +#endif + +#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ + (tmp) = RB_RIGHT(elm, field); \ + if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \ + RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_LEFT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ + if ((RB_PARENT(tmp, field))) \ + RB_AUGMENT(RB_PARENT(tmp, field)); \ +} while (/*CONSTCOND*/ 0) + +#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \ + (tmp) = RB_LEFT(elm, field); \ + if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \ + RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_RIGHT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ + if ((RB_PARENT(tmp, field))) \ + RB_AUGMENT(RB_PARENT(tmp, field)); \ +} while (/*CONSTCOND*/ 0) + +/* Generates prototypes and inline functions */ +#define RB_PROTOTYPE(name, type, field, cmp) \ + RB_PROTOTYPE_INTERNAL(name, type, field, cmp,) +#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \ + RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static) +#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \ +attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \ +attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ +attr struct type *name##_RB_REMOVE(struct name *, struct type *); \ +attr struct type *name##_RB_INSERT(struct name *, struct type *); \ +attr struct type *name##_RB_FIND(struct name *, struct type *); \ +attr struct type *name##_RB_NFIND(struct name *, struct type *); \ +attr struct type *name##_RB_NEXT(struct type *); \ +attr struct type *name##_RB_PREV(struct type *); \ +attr struct type *name##_RB_MINMAX(struct name *, int); \ + \ + +/* Main rb operation. + * Moves node close to the key of elm to top + */ +#define RB_GENERATE(name, type, field, cmp) \ + RB_GENERATE_INTERNAL(name, type, field, cmp,) +#define RB_GENERATE_STATIC(name, type, field, cmp) \ + RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static) +#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \ +attr void \ +name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ +{ \ + struct type *parent, *gparent, *tmp; \ + while ((parent = RB_PARENT(elm, field)) != NULL && \ + RB_COLOR(parent, field) == RB_RED) { \ + gparent = RB_PARENT(parent, field); \ + if (parent == RB_LEFT(gparent, field)) { \ + tmp = RB_RIGHT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_RIGHT(parent, field) == elm) { \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_RIGHT(head, gparent, tmp, field); \ + } else { \ + tmp = RB_LEFT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_LEFT(parent, field) == elm) { \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_LEFT(head, gparent, tmp, field); \ + } \ + } \ + RB_COLOR(head->rbh_root, field) = RB_BLACK; \ +} \ + \ +attr void \ +name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \ +{ \ + struct type *tmp; \ + while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ + elm != RB_ROOT(head)) { \ + if (RB_LEFT(parent, field) == elm) { \ + tmp = RB_RIGHT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\ + struct type *oleft; \ + if ((oleft = RB_LEFT(tmp, field)) \ + != NULL) \ + RB_COLOR(oleft, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_RIGHT(head, tmp, oleft, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_RIGHT(tmp, field)) \ + RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } else { \ + tmp = RB_LEFT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\ + struct type *oright; \ + if ((oright = RB_RIGHT(tmp, field)) \ + != NULL) \ + RB_COLOR(oright, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_LEFT(head, tmp, oright, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_LEFT(tmp, field)) \ + RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } \ + } \ + if (elm) \ + RB_COLOR(elm, field) = RB_BLACK; \ +} \ + \ +attr struct type * \ +name##_RB_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *child, *parent, *old = elm; \ + int color; \ + if (RB_LEFT(elm, field) == NULL) \ + child = RB_RIGHT(elm, field); \ + else if (RB_RIGHT(elm, field) == NULL) \ + child = RB_LEFT(elm, field); \ + else { \ + struct type *left; \ + elm = RB_RIGHT(elm, field); \ + while ((left = RB_LEFT(elm, field)) != NULL) \ + elm = left; \ + child = RB_RIGHT(elm, field); \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ + if (RB_PARENT(elm, field) == old) \ + parent = elm; \ + (elm)->field = (old)->field; \ + if (RB_PARENT(old, field)) { \ + if (RB_LEFT(RB_PARENT(old, field), field) == old)\ + RB_LEFT(RB_PARENT(old, field), field) = elm;\ + else \ + RB_RIGHT(RB_PARENT(old, field), field) = elm;\ + RB_AUGMENT(RB_PARENT(old, field)); \ + } else \ + RB_ROOT(head) = elm; \ + RB_PARENT(RB_LEFT(old, field), field) = elm; \ + if (RB_RIGHT(old, field)) \ + RB_PARENT(RB_RIGHT(old, field), field) = elm; \ + if (parent) { \ + left = parent; \ + do { \ + RB_AUGMENT(left); \ + } while ((left = RB_PARENT(left, field)) != NULL); \ + } \ + goto color; \ + } \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ +color: \ + if (color == RB_BLACK) \ + name##_RB_REMOVE_COLOR(head, parent, child); \ + return (old); \ +} \ + \ +/* Inserts a node into the RB tree */ \ +attr struct type * \ +name##_RB_INSERT(struct name *head, struct type *elm) \ +{ \ + struct type *tmp; \ + struct type *parent = NULL; \ + int comp = 0; \ + tmp = RB_ROOT(head); \ + while (tmp) { \ + parent = tmp; \ + comp = (cmp)(elm, parent); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + RB_SET(elm, parent, field); \ + if (parent != NULL) { \ + if (comp < 0) \ + RB_LEFT(parent, field) = elm; \ + else \ + RB_RIGHT(parent, field) = elm; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = elm; \ + name##_RB_INSERT_COLOR(head, elm); \ + return (NULL); \ +} \ + \ +/* Finds the node with the same key as elm */ \ +attr struct type * \ +name##_RB_FIND(struct name *head, struct type *elm) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + int comp; \ + while (tmp) { \ + comp = cmp(elm, tmp); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + return (NULL); \ +} \ + \ +/* Finds the first node greater than or equal to the search key */ \ +attr struct type * \ +name##_RB_NFIND(struct name *head, struct type *elm) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + struct type *res = NULL; \ + int comp; \ + while (tmp) { \ + comp = cmp(elm, tmp); \ + if (comp < 0) { \ + res = tmp; \ + tmp = RB_LEFT(tmp, field); \ + } \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + return (res); \ +} \ + \ +/* ARGSUSED */ \ +attr struct type * \ +name##_RB_NEXT(struct type *elm) \ +{ \ + if (RB_RIGHT(elm, field)) { \ + elm = RB_RIGHT(elm, field); \ + while (RB_LEFT(elm, field)) \ + elm = RB_LEFT(elm, field); \ + } else { \ + if (RB_PARENT(elm, field) && \ + (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ + elm = RB_PARENT(elm, field); \ + else { \ + while (RB_PARENT(elm, field) && \ + (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\ + elm = RB_PARENT(elm, field); \ + elm = RB_PARENT(elm, field); \ + } \ + } \ + return (elm); \ +} \ + \ +/* ARGSUSED */ \ +attr struct type * \ +name##_RB_PREV(struct type *elm) \ +{ \ + if (RB_LEFT(elm, field)) { \ + elm = RB_LEFT(elm, field); \ + while (RB_RIGHT(elm, field)) \ + elm = RB_RIGHT(elm, field); \ + } else { \ + if (RB_PARENT(elm, field) && \ + (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \ + elm = RB_PARENT(elm, field); \ + else { \ + while (RB_PARENT(elm, field) && \ + (elm == RB_LEFT(RB_PARENT(elm, field), field)))\ + elm = RB_PARENT(elm, field); \ + elm = RB_PARENT(elm, field); \ + } \ + } \ + return (elm); \ +} \ + \ +attr struct type * \ +name##_RB_MINMAX(struct name *head, int val) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + struct type *parent = NULL; \ + while (tmp) { \ + parent = tmp; \ + if (val < 0) \ + tmp = RB_LEFT(tmp, field); \ + else \ + tmp = RB_RIGHT(tmp, field); \ + } \ + return (parent); \ +} + +#define RB_NEGINF -1 +#define RB_INF 1 + +#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) +#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) +#define RB_FIND(name, x, y) name##_RB_FIND(x, y) +#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y) +#define RB_NEXT(name, x, y) name##_RB_NEXT(y) +#define RB_PREV(name, x, y) name##_RB_PREV(y) +#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) +#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) + +#define RB_FOREACH(x, name, head) \ + for ((x) = RB_MIN(name, head); \ + (x) != NULL; \ + (x) = name##_RB_NEXT(x)) + +#define RB_FOREACH_REVERSE(x, name, head) \ + for ((x) = RB_MAX(name, head); \ + (x) != NULL; \ + (x) = name##_RB_PREV(x)) + +#endif /* _SYS_TREE_H_ */ diff --git a/test/.cvsignore b/test/.cvsignore index 5825abcde9c7e..471324e7f8d7e 100644 --- a/test/.cvsignore +++ b/test/.cvsignore @@ -78,10 +78,78 @@ ni9 ni10 ni11 ni12 -n12 in6 -i15 +n12 ni13 ni14 ni15 ni16 +i15 +ipv6.4 +i16 +i17 +ni17 +ni18 +ni19 +ni20 +ni21 +f18 +f19 +i18 +i19 +i20 +i21 +f20 +p4 +in100 +in101 +n100 +n101 +n102 +n103 +n104 +n105 +n106 +n200 +ip2 +n15 +n201 +n202 +f21 +f22 +i22 +ni23 +ipv6.5 +n16 +f24 +ipv6.6 +n17 +n1_6 +n2_6 +n4_6 +n5_6 +n6_6 +n7_6 +n11_6 +n15_6 +n13 +n12_6 +f25 +f26 +f27 +n14 +n8_6 +n18 +n9_6 +i23 +in7 +ip3 +p5 +p6 +in102 +p7 +p9 +p10 +p11 +p12 +p13 diff --git a/test/Makefile b/test/Makefile index b0462f3f388d7..89183117b4e6d 100644 --- a/test/Makefile +++ b/test/Makefile @@ -3,6 +3,9 @@ # # See the IPFILTER.LICENCE file for details on licencing. # +POOLDEP=../ip_lookup.c ../ip_lookup.h ../ip_pool.c ../ip_pool.h \ + ../ip_htable.c ../ip_htable.h ../ip_dstlist.c ../ip_dstlist.h \ + ../tools/ippool_y.y BINDEST=/usr/local/bin SBINDEST=/sbin MANDIR=/usr/share/man @@ -14,86 +17,504 @@ expected.d: results: mkdir -p results -tests: ipf nat logtests ipv6 pools bpf +tests: ipf nat logtests ipv6 pools -ipf: ftests ptests +ipf: patests ftests -nat: ntests nitests intests +nat: intests ntests nitests first: -mkdir -p results # Filtering tests -ftests: f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 f16 f17 f18 f19 f20 f24 +ftests: f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 f16 f17 f18 f19 f20 f21 f22 f24 f25 f26 f27 f28 f29 f30 # Rule parsing tests -ptests: i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 i16 i17 i18 i19 \ - i20 i21 +patests: i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 i16 i17 i18 i19 \ + i20 i21 i22 i23 -ntests: n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12 n13 n14 n16 +ntests: n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12 n13 n14 n15 n16 n17 n18 n100 n101 n102 n103 n104 n105 n106 n200 + +ntests6: n1_6 n2_6 n4_6 n5_6 n6_6 n7_6 n8_6 n9_6 n11_6 n12_6 n15_6 nitests: ni1 ni2 ni3 ni4 ni5 ni6 ni7 ni8 ni9 ni10 ni11 ni12 ni13 ni14 ni15 \ - ni16 ni19 ni20 ni21 ni23 + ni16 ni17 ni18 ni19 ni20 ni21 ni23 -intests: in1 in2 in3 in4 in5 in6 +intests: in1 in2 in3 in4 in5 in6 in7 in8 in100 in101 in102 logtests: l1 -pools: p1 p2 p3 p5 ip1 ip2 +pools: p1 p2 p3 p4 p5 p6 p7 p9 p10 p11 p12 p13 ip1 ip2 ip3 -ipv6: ipv6.1 ipv6.2 ipv6.3 ipv6.5 ipv6.6 +ipv6: ipv6.1 ipv6.2 ipv6.3 ipv6.4 ipv6.5 ipv6.6 ntests6 bpf: bpf1 bpf-f1 -f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f19: +f1: expected/f1 input/f1 regress/f1 + @/bin/sh ./dotest `awk "/^$@ / { print; } " test.format` + +f2: expected/f2 input/f2 regress/f2 + @/bin/sh ./dotest `awk "/^$@ / { print; } " test.format` + +f3: expected/f3 input/f3 regress/f3 + @/bin/sh ./dotest `awk "/^$@ / { print; } " test.format` + +f4: expected/f4 input/f4 regress/f4 + @/bin/sh ./dotest `awk "/^$@ / { print; } " test.format` + +f5: expected/f5 input/f5 regress/f5 + @/bin/sh ./dotest `awk "/^$@ / { print; } " test.format` + +f6: expected/f6 input/f6 regress/f6 + @/bin/sh ./dotest `awk "/^$@ / { print; } " test.format` + +f7: expected/f7 input/f7 regress/f7 + @/bin/sh ./dotest `awk "/^$@ / { print; } " test.format` + +f8: expected/f8 input/f8 regress/f8 + @/bin/sh ./dotest `awk "/^$@ / { print; } " test.format` + +f9: expected/f9 input/f9 regress/f9 @/bin/sh ./dotest `awk "/^$@ / { print; } " test.format` -f15 f16 f17 f18 f20 f24: +f10: expected/f10 input/f10 regress/f10 + @/bin/sh ./dotest `awk "/^$@ / { print; } " test.format` + +f11: expected/f11 input/f11 regress/f11 + @/bin/sh ./dotest `awk "/^$@ / { print; } " test.format` + +f12: expected/f12 input/f12 regress/f12 + @/bin/sh ./dotest `awk "/^$@ / { print; } " test.format` + +f13: expected/f13 input/f13 regress/f13 + @/bin/sh ./dotest `awk "/^$@ / { print; } " test.format` + +f14: expected/f14 input/f14 regress/f14 + @/bin/sh ./dotest `awk "/^$@ / { print; } " test.format` + +f19: expected/f15 input/f15 regress/f15 + @/bin/sh ./dotest `awk "/^$@ / { print; } " test.format` + +f15: expected/f15 input/f15 regress/f15 + @/bin/sh ./mtest `awk "/^$@ / { print; } " test.format` + +f16: expected/f16 input/f16 regress/f16 + @/bin/sh ./mtest `awk "/^$@ / { print; } " test.format` + +f17: expected/f17 input/f17 regress/f17 + @/bin/sh ./mtest `awk "/^$@ / { print; } " test.format` + +f18: expected/f18 input/f18 regress/f18 + @/bin/sh ./mtest `awk "/^$@ / { print; } " test.format` + +f20: expected/f20 input/f20 regress/f20 + @/bin/sh ./mtest `awk "/^$@ / { print; } " test.format` + +f21: expected/f21 input/f21 regress/f21 + @/bin/sh ./mtest `awk "/^$@ / { print; } " test.format` + +f22: expected/f22 input/f22 regress/f22 + @/bin/sh ./mtest `awk "/^$@ / { print; } " test.format` + +f24: expected/f24 input/f24 regress/f24 @/bin/sh ./mtest `awk "/^$@ / { print; } " test.format` -i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 i16 i17 i18 i19 i20 i21 bpf1: +f25: expected/f25 input/f25 regress/f25 + @/bin/sh ./mtest `awk "/^$@ / { print; } " test.format` + +f26: expected/f26 input/f26 regress/f26 + @/bin/sh ./dotest `awk "/^$@ / { print; } " test.format` + +f27: expected/f27 input/f27 regress/f27 + @/bin/sh ./dotest `awk "/^$@ / { print; } " test.format` + +f28: expected/f28 input/f28 regress/f28.ipf regress/f28.pool $(POOLDEP) + @/bin/sh ./ptest `awk "/^$@ / { print; } " test.format` + +f29: expected/f29 input/f29 regress/f29.ipf regress/f29.pool $(POOLDEP) + @/bin/sh ./ptest `awk "/^$@ / { print; } " test.format` + +f30: expected/f30 input/f30 regress/f30 + @/bin/sh ./dotest `awk "/^$@ / { print; } " test.format` + +i1: expected/i1 regress/i1 @/bin/sh ./itest `awk "/^$@ / { print; } " test.format` -n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12 n13 n14 n16: +i2: expected/i2 regress/i2 + @/bin/sh ./itest `awk "/^$@ / { print; } " test.format` + +i3: expected/i3 regress/i3 + @/bin/sh ./itest `awk "/^$@ / { print; } " test.format` + +i4: expected/i4 regress/i4 + @/bin/sh ./itest `awk "/^$@ / { print; } " test.format` + +i5: expected/i5 regress/i5 + @/bin/sh ./itest `awk "/^$@ / { print; } " test.format` + +i6: expected/i6 regress/i6 + @/bin/sh ./itest `awk "/^$@ / { print; } " test.format` + +i7: expected/i7 regress/i7 + @/bin/sh ./itest `awk "/^$@ / { print; } " test.format` + +i8: expected/i8 regress/i8 + @/bin/sh ./itest `awk "/^$@ / { print; } " test.format` + +i9: expected/i9 regress/i9 + @/bin/sh ./itest `awk "/^$@ / { print; } " test.format` + +i10: expected/i10 regress/i10 + @/bin/sh ./itest `awk "/^$@ / { print; } " test.format` + +i11: expected/i11 regress/i11 + @/bin/sh ./itest `awk "/^$@ / { print; } " test.format` + +i12: expected/i12 regress/i12 + @/bin/sh ./itest `awk "/^$@ / { print; } " test.format` + +i13: expected/i13 regress/i13 + @/bin/sh ./itest `awk "/^$@ / { print; } " test.format` + +i14: expected/i14 regress/i14 + @/bin/sh ./itest `awk "/^$@ / { print; } " test.format` + +i15: expected/i15 regress/i15 + @/bin/sh ./itest `awk "/^$@ / { print; } " test.format` + +i16: expected/i16 regress/i16 + @/bin/sh ./itest `awk "/^$@ / { print; } " test.format` + +i17: expected/i17 regress/i17 + @/bin/sh ./itest `awk "/^$@ / { print; } " test.format` + +i18: expected/i18 regress/i18 + @/bin/sh ./itest `awk "/^$@ / { print; } " test.format` + +i19: expected/i19 regress/i19 + @/bin/sh ./itest `awk "/^$@ / { print; } " test.format` + +i20: expected/i20 regress/i20 + @/bin/sh ./itest `awk "/^$@ / { print; } " test.format` + +i21: expected/i21 regress/i21 + @/bin/sh ./itest `awk "/^$@ / { print; } " test.format` + +i22: expected/i22 regress/i22 + @/bin/sh ./itest `awk "/^$@ / { print; } " test.format` + +i23: expected/i23 regress/i23 + @/bin/sh ./itest `awk "/^$@ / { print; } " test.format` + +bpf1: expected/bpf1 regress/bpf1 + @/bin/sh ./itest `awk "/^$@ / { print; } " test.format` + +n1: expected/n1 regress/n1 input/n1 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n2: expected/n2 regress/n2 input/n2 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n3: expected/n3 regress/n3 input/n3 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n4: expected/n4 regress/n4 input/n4 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n5: expected/n5 regress/n5 input/n5 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n6: expected/n6 regress/n6 input/n6 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n7: expected/n7 regress/n7 input/n7 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n8: expected/n8 regress/n8 input/n8 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n9: expected/n9 regress/n9 input/n9 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n10: expected/n10 regress/n10 input/n10 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n11: expected/n11 regress/n11 input/n11 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n12: expected/n12 regress/n12 input/n12 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n13: expected/n13 regress/n13 input/n13 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n14: expected/n14 regress/n14 input/n14 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n15: expected/n15 regress/n15 input/n15 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n16: expected/n16 regress/n16 input/n16 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n17: expected/n17 regress/n17 input/n17 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n18: expected/n18 regress/n18 input/n18 @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` -ni2 ni3 ni4 ni5 ni7 ni8 ni9 ni10 ni11 ni12 ni13 ni14 ni15 ni16 ni19 ni20: +n100: expected/n100 regress/n100 input/n100 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n101: expected/n101 regress/n101 input/n101 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n102: expected/n102 regress/n102 input/n102 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n103: expected/n103 regress/n103 input/n103 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n104: expected/n104 regress/n104 input/n104 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n105: expected/n105 regress/n105 input/n105 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n106: expected/n106 regress/n106 input/n106 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n200: expected/n200 regress/n200 input/n200 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n1_6: expected/n1_6 regress/n1_6 input/n1_6 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n2_6: expected/n2_6 regress/n2_6 input/n2_6 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n4_6: expected/n4_6 regress/n4_6 input/n4_6 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n5_6: expected/n5_6 regress/n5_6 input/n5_6 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n6_6: expected/n6_6 regress/n6_6 input/n6_6 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n7_6: expected/n7_6 regress/n7_6 input/n7_6 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n8_6: expected/n8_6 regress/n8_6 input/n8_6 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n9_6: expected/n9_6 regress/n9_6 input/n9_6 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n11_6: expected/n11_6 regress/n11_6 input/n11_6 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n12_6: expected/n12_6 regress/n12_6 input/n12_6 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +n15_6: expected/n15_6 regress/n15_6 input/n15_6 + @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format` + +ni2: expected/ni2 input/ni2 regress/ni2.nat regress/ni2.ipf + @/bin/sh ./natipftest single `awk "/^$@ / { print; } " test.format` + +ni3: expected/ni3 input/ni3 regress/ni3.nat regress/ni3.ipf + @/bin/sh ./natipftest single `awk "/^$@ / { print; } " test.format` + +ni4: expected/ni4 input/ni4 regress/ni4.nat regress/ni4.ipf + @/bin/sh ./natipftest single `awk "/^$@ / { print; } " test.format` + +ni5: expected/ni5 input/ni5 regress/ni5.nat regress/ni5.ipf + @/bin/sh ./natipftest single `awk "/^$@ / { print; } " test.format` + +ni7: expected/ni7 input/ni7 regress/ni7.nat regress/ni7.ipf + @/bin/sh ./natipftest single `awk "/^$@ / { print; } " test.format` + +ni8: expected/ni8 input/ni8 regress/ni8.nat regress/ni8.ipf + @/bin/sh ./natipftest single `awk "/^$@ / { print; } " test.format` + +ni9: expected/ni9 input/ni9 regress/ni9.nat regress/ni9.ipf + @/bin/sh ./natipftest single `awk "/^$@ / { print; } " test.format` + +ni10: expected/ni10 input/ni10 regress/ni10.nat regress/ni10.ipf + @/bin/sh ./natipftest single `awk "/^$@ / { print; } " test.format` + +ni11: expected/ni11 input/ni11 regress/ni11.nat regress/ni11.ipf + @/bin/sh ./natipftest single `awk "/^$@ / { print; } " test.format` + +ni12: expected/ni12 input/ni12 regress/ni12.nat regress/ni12.ipf + @/bin/sh ./natipftest single `awk "/^$@ / { print; } " test.format` + +ni13: expected/ni13 input/ni13 regress/ni13.nat regress/ni13.ipf + @/bin/sh ./natipftest single `awk "/^$@ / { print; } " test.format` + +ni14: expected/ni14 input/ni14 regress/ni14.nat regress/ni14.ipf + @/bin/sh ./natipftest single `awk "/^$@ / { print; } " test.format` + +ni15: expected/ni15 input/ni15 regress/ni15.nat regress/ni15.ipf + @/bin/sh ./natipftest single `awk "/^$@ / { print; } " test.format` + +ni16: expected/ni16 input/ni16 regress/ni16.nat regress/ni16.ipf + @/bin/sh ./natipftest single `awk "/^$@ / { print; } " test.format` + +ni19: expected/ni19 input/ni19 regress/ni19.nat regress/ni19.ipf + @/bin/sh ./natipftest single `awk "/^$@ / { print; } " test.format` + +ni20: expected/ni20 input/ni20 regress/ni20.nat regress/ni20.ipf @/bin/sh ./natipftest single `awk "/^$@ / { print; } " test.format` -ni1 ni6 ni21 ni23: +ni1: expected/ni1 input/ni1 regress/ni1.nat regress/ni1.ipf @/bin/sh ./natipftest multi `awk "/^$@ / { print; } " test.format` -in1 in2 in3 in4 in5 in6: +ni6: expected/ni6 input/ni6 regress/ni6.nat regress/ni6.ipf + @/bin/sh ./natipftest multi `awk "/^$@ / { print; } " test.format` + +ni17: expected/ni17 input/ni17 regress/ni17.nat regress/ni17.ipf + @/bin/sh ./natipftest multi `awk "/^$@ / { print; } " test.format` + +ni18: expected/ni18 input/ni18 regress/ni18.nat regress/ni18.ipf + @/bin/sh ./natipftest multi `awk "/^$@ / { print; } " test.format` + +ni21: expected/ni21 input/ni21 regress/ni21.nat regress/ni21.ipf + @/bin/sh ./natipftest multi `awk "/^$@ / { print; } " test.format` + +ni23: expected/ni23 input/ni23 regress/ni23.nat regress/ni23.ipf + @/bin/sh ./natipftest multi `awk "/^$@ / { print; } " test.format` + +in1: expected/in1 regress/in1 + @/bin/sh ./intest `awk "/^$@ / { print; } " test.format` + +in2: expected/in2 regress/in2 + @/bin/sh ./intest `awk "/^$@ / { print; } " test.format` + +in3: expected/in3 regress/in3 + @/bin/sh ./intest `awk "/^$@ / { print; } " test.format` + +in4: expected/in4 regress/in4 + @/bin/sh ./intest `awk "/^$@ / { print; } " test.format` + +in5: expected/in5 regress/in5 + @/bin/sh ./intest `awk "/^$@ / { print; } " test.format` + +in6: expected/in6 regress/in6 + @/bin/sh ./intest `awk "/^$@ / { print; } " test.format` + +in7: expected/in7 regress/in7 + @/bin/sh ./intest `awk "/^$@ / { print; } " test.format` + +in8: expected/in8 regress/in8 + @/bin/sh ./intest `awk "/^$@ / { print; } " test.format` + +in100: expected/in100 regress/in100 + @/bin/sh ./intest `awk "/^$@ / { print; } " test.format` + +in101: expected/in101 regress/in101 + @/bin/sh ./intest `awk "/^$@ / { print; } " test.format` + +in102: expected/in102 regress/in102 @/bin/sh ./intest `awk "/^$@ / { print; } " test.format` l1: @/bin/sh ./logtest `awk "/^$@ / { print; } " test.format` -ipv6.1 ipv6.2 ipv6.3 ipv6.5 ipv6.6: +ipv6.1: expected/ipv6.1 input/ipv6.1 regress/ipv6.1 + @/bin/sh ./dotest6 `awk "/^$@ / { print; } " test.format` + +ipv6.2: expected/ipv6.2 input/ipv6.2 regress/ipv6.2 + @/bin/sh ./dotest6 `awk "/^$@ / { print; } " test.format` + +ipv6.3: expected/ipv6.3 input/ipv6.3 regress/ipv6.3 @/bin/sh ./dotest6 `awk "/^$@ / { print; } " test.format` -p1 p2 p3 p5: +ipv6.4: expected/ipv6.4 input/ipv6.4 regress/ipv6.4 + @/bin/sh ./dotest6 `awk "/^$@ / { print; } " test.format` + +ipv6.5: expected/ipv6.5 input/ipv6.5 regress/ipv6.5 + @/bin/sh ./dotest6 `awk "/^$@ / { print; } " test.format` + +ipv6.6: expected/ipv6.6 input/ipv6.6 regress/ipv6.6 + @/bin/sh ./dotest6 `awk "/^$@ / { print; } " test.format` + +p1: expected/p1 input/p1 regress/p1.ipf regress/p1.pool $(POOLDEP) + @/bin/sh ./ptest `awk "/^$@ / { print; } " test.format` + +p2: expected/p2 input/p2 regress/p2.ipf $(POOLDEP) @/bin/sh ./ptest `awk "/^$@ / { print; } " test.format` -ip1 ip2: +p3: expected/p3 input/p3 regress/p3.ipf regress/p3.pool $(POOLDEP) + @/bin/sh ./ptest `awk "/^$@ / { print; } " test.format` + +p4: expected/p4 input/p4 regress/p4.nat regress/p4.pool $(POOLDEP) + @/bin/sh ./ptest `awk "/^$@ / { print; } " test.format` + +p5: expected/p5 input/p5 regress/p5.ipf regress/p5.pool $(POOLDEP) + @/bin/sh ./ptest `awk "/^$@ / { print; } " test.format` + +p6: expected/p6 input/p6 regress/p6.ipf regress/p6.pool $(POOLDEP) + @/bin/sh ./ptest `awk "/^$@ / { print; } " test.format` + +p7: expected/p7 input/p7 regress/p7.nat regress/p7.pool $(POOLDEP) + @/bin/sh ./ptest `awk "/^$@ / { print; } " test.format` + +p9: expected/p9 input/p9 regress/p9.nat regress/p9.pool $(POOLDEP) + @/bin/sh ./ptest `awk "/^$@ / { print; } " test.format` + +p10: expected/p10 input/p10 regress/p10.nat regress/p10.pool $(POOLDEP) + @/bin/sh ./ptest `awk "/^$@ / { print; } " test.format` + +p11: expected/p11 input/p11 regress/p11.nat regress/p11.pool $(POOLDEP) + @/bin/sh ./ptest `awk "/^$@ / { print; } " test.format` + +p12: expected/p12 input/p12 regress/p12.nat regress/p12.pool $(POOLDEP) + @/bin/sh ./ptest `awk "/^$@ / { print; } " test.format` + +p13: expected/p13 input/p13 regress/p13.ipf regress/p13.pool $(POOLDEP) + @/bin/sh ./ptest `awk "/^$@ / { print; } " test.format` + +ip1: expected/ip1 regress/ip1 $(POOLDEP) + @/bin/sh ./iptest `awk "/^$@ / { print; } " test.format` + +ip2: expected/ip2 input/ip2.data regress/ip2 $(POOLDEP) + @/bin/sh ./iptest `awk "/^$@ / { print; } " test.format` + +ip3: expected/ip3 regress/ip3 $(POOLDEP) @/bin/sh ./iptest `awk "/^$@ / { print; } " test.format` -bpf-f1: +bpf-f1: expected/bpf-f1 regress/bpf-f1 /bin/sh ./bpftest `awk "/^$@ / { print; } " test.format` clean: - /bin/rm -f f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 f16 f17 f18 f19 f20 f24 - /bin/rm -f i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 i16 i17 i18 i19 i20 i21 - /bin/rm -f n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12 n13 n14 n16 + /bin/rm -f f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 f16 f17 + /bin/rm -f f18 f19 f20 f21 f22 f24 f25 f26 f27 f28 f29 + /bin/rm -f i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 i16 i17 + /bin/rm -f i18 i19 i20 i21 i22 i23 + /bin/rm -f n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12 n13 n14 n15 n16 n17 n18 n100 n101 n102 n103 n104 n105 n106 n200 + /bin/rm -f n1_6 n2_6 n4_6 n5_6 n6_6 n7_6 n8_6 n9_6 n11_6 n12_6 n15_6 /bin/rm -f ni1 ni2 ni3 ni4 ni5 ni6 ni7 ni8 ni9 - /bin/rm -f ni10 ni11 ni12 ni13 ni14 ni15 ni16 ni19 ni20 ni21 ni23 - /bin/rm -f in1 in2 in3 in4 in5 in6 - /bin/rm -f p1 p2 p3 p5 ip1 ip2 + /bin/rm -f ni10 ni11 ni12 ni13 ni14 ni15 ni16 ni17 ni18 ni19 ni20 ni21 ni23 + /bin/rm -f in1 in2 in3 in4 in5 in6 in7 in100 in101 in102 + /bin/rm -f p1 p2 p3 p4 p5 p6 p7 p9 p10 p11 p12 p13 ip1 ip2 ip3 /bin/rm -f l1 - /bin/rm -f ipv6.1 ipv6.2 ipv6.3 ipv6.5 ipv6.6 + /bin/rm -f ipv6.1 ipv6.2 ipv6.3 ipv6.4 ipv6.5 ipv6.6 /bin/rm -f bpf1 bpf-f1 /bin/rm -f results/* logout (cd expected; make clean) diffs: -cd expected; for i in *; do if [ -f $$i -a ! -f ../$$i -a -f ../results/$$i ] ; then diff -c $$i ../results/$$i >> ../diff.out; fi done + +n6s: + for i in 1 2 4 5 6 7 11 13 14 15; do \ + sh i4to6 < input/n$${i} > input/n$${i}_6; \ + sh e4to6 < regress/n$${i} > regress/n$${i}_6; \ + sh e4to6 < expected/n$${i} > expected/n$${i}_6; \ + done + for i in 8 9 10 12 17; do \ + sh e4to6 < regress/n$${i} > regress/n$${i}_6; \ + perl h4to6 < input/n$${i} > input/n$${i}_6; \ + done diff --git a/test/bpftest b/test/bpftest index b24c0f16ae49d..5449658f820ea 100644 --- a/test/bpftest +++ b/test/bpftest @@ -1,28 +1,19 @@ #!/bin/sh -if [ -f /usr/ucb/touch ] ; then - TOUCH=/usr/ucb/touch -else - if [ -f /usr/bin/touch ] ; then - TOUCH=/usr/bin/touch - else - if [ -f /bin/touch ] ; then - TOUCH=/bin/touch - fi - fi -fi -echo "$1..."; -input=`expr $1 : 'bpf-\(.*\)'` -/bin/cp /dev/null results/$1 +name=$1 + +. ./ipflib.sh + +test_init + +echo "$name..."; +input=`expr $name : 'bpf-\(.*\)'` +/bin/cp /dev/null results/$name ( while read rule; do - echo "$rule" | ../ipftest -Rbr - -i input/$input >> results/$1; + echo "$rule" | ../ipftest -Rbr - -i input/$input >> results/$name if [ $? -ne 0 ] ; then exit 1; fi - echo "--------" >> results/$1 -done ) < regress/$1 -cmp expected/$1 results/$1 -status=$? -if [ $status = 0 ] ; then - $TOUCH $1 -fi + echo "--------" >> results/$name +done ) < regress/$name +check_results $name exit $status diff --git a/test/dotest b/test/dotest index 29891091da596..71c09b7b816e6 100644 --- a/test/dotest +++ b/test/dotest @@ -1,19 +1,13 @@ #!/bin/sh -thistest=$1 +name=$1 format=$2 output=$3 tuning=$4 -if [ -f /usr/ucb/touch ] ; then - TOUCH=/usr/ucb/touch -else - if [ -f /usr/bin/touch ] ; then - TOUCH=/usr/bin/touch - else - if [ -f /bin/touch ] ; then - TOUCH=/bin/touch - fi - fi -fi + +. ./ipflib.sh + +test_init + if [ "$tuning" != "" ] ; then case $tuning in -*) @@ -23,18 +17,17 @@ if [ "$tuning" != "" ] ; then ;; esac fi -echo "${thistest}..."; -/bin/cp /dev/null results/${thistest} +echo "${name}..."; +n=1 +/bin/cp /dev/null results/${name} ( while read rule; do - echo "$rule" | ../ipftest -F $format -Rbr - -i input/${thistest} $tuning>> results/${thistest}; - if [ $? -ne 0 ] ; then - exit 1; - fi - echo "--------" >> results/${thistest} -done ) < regress/${thistest} -cmp expected/${thistest} results/${thistest} -status=$? -if [ $status = 0 ] ; then - $TOUCH ${thistest} -fi + set_core $name $n + echo "$rule" | ../ipftest -F $format -Rbr - -i input/${name} $tuning>> results/${name} & + back=$! + wait $back + test_end_leak $? + n=`expr $n + 1` + echo "--------" >> results/${name} +done ) < regress/${name} +check_results $name exit $status diff --git a/test/e4to6 b/test/e4to6 new file mode 100644 index 0000000000000..87558993b133a --- /dev/null +++ b/test/e4to6 @@ -0,0 +1,61 @@ +sed \ +-e 's/192.168.126.0/c0a8:7e00::/' \ +-e 's/\/32/\/128/g' \ +-e 's/\/24/\/112/g' \ +-e 's/\/16/\/32/g' \ +-e 's/10\.2\.0\.0/10::2:0:0/g' \ +-e 's/1\.\([0-9]\)\.\([0-9]\)\.\([0-9]\)/1:0:0:0:0:\1:\2:\3/g' \ +-e 's/2\.\([0-9]\)\.\([0-9]\)\.\([0-9]\)/2:0:0:0:0:\1:\2:\3/g' \ +-e 's/4\.\([0-9]\)\.\([0-9]\)\.\([0-9]\)/4:\1:\2:0:0:0:0:\3/g' \ +-e 's/3\.\([0-9]\)\.\([0-9]\)\.\([0-9]\)/3:0:\1:0:0:0:\2:\3/g' \ +-e 's/5\.\([0-9]\)\.\([0-9]\)\.\([0-9]\)/5:\1:0:0:0:0:\2:\3/g' \ +-e 's/9\.\([0-9]\)\.\([0-9]\)\.\([0-9]\)/9:\1:\2:0:0:0:0:\3/g' \ +-e 's/10\.1\.\([0-9]\)\.\([0-9]\)/10:1:\1:0:0:0:0:\2/g' \ +-e 's/10\.10\.\([0-9]*\)\.\([0-9]\)/10:10:\1:0:0:0:0:\2/g' \ +-e 's/10\.2\.\([0-9]\)\.\([0-9]\)/10:0:0:0:0:2:\1:\2/g' \ +-e 's/10\.4\.3\.\([0-9]\)/10:4:3:0:0:0:0:\1/g' \ +-e 's/10\.3\.4\.\([0-9]\)/10:0:0:0:0:3:4:\1/g' \ +-e 's/10\.3\.\([0-9]\)\.\([0-9]\)/10:3:\1:0:0:0:0:\2/g' \ +-e 's/0\.0\.0\.0/any/g' \ +-e 's/ 0\/0 / any /g' \ +-e 's/ip #0/ip6\/0/' \ +-e 's/40(20) 6 /20 0 6 /' \ +-e 's/28(20) 17 /8 0 17 /' \ +-e 's/20(20) 0 /1 0 41 /' \ +-e 's/48(20) 1 /88 0 58 /g' \ +-e 's/20(20) 34 /1 0 34 /g' \ +-e 's/20(20) 35 /1 0 35 /g' \ +-e 's/20(20) 255 /1 0 255 /g' \ +-e 's/ */ /g' | sed \ +-e '/use/s/:0:0:0:0:/::/g' \ +-e '/map/s/:0:0:0:0:/::/g' \ +-e '/rdr/s/:0:0:0:0:/::/g' \ +-e '/map/s/:0:0:0:/::/g' \ +-e '/rdr/s/:0:0:0:/::/g' \ +-e '/MAP/s/:0:0:0:0:0:/::/g' \ +-e '/RDR/s/:0:0:0:0:0:/::/g' \ +-e '/MAP/s/:0:0:0:0:/::/g' \ +-e '/RDR/s/:0:0:0:0:/::/g' \ +-e '/MAP/s/:0:0:0:/::/g' \ +-e '/RDR/s/:0:0:0:/::/g' \ +| sed \ +-e '/MAP/s/ \([0-9][0-9][0-9][0-9]\) / \1 /g' \ +-e '/MAP/s/ \([0-9][0-9][0-9]\) / \1 /g' \ +-e '/MAP/s/ \([0-9][0-9]\) / \1 /g' \ +-e '/RDR/s/ \([0-9][0-9][0-9][0-9]\) / \1 /g' \ +-e '/RDR/s/ \([0-9][0-9][0-9]\) / \1 /g' \ +-e '/RDR/s/ \([0-9][0-9]\) / \1 /g' \ +-e 's/::0:0\//::\//g' \ +-e 's/:0:0\//::\//g' \ +-e 's/::0\([^:0-9]\)/::\1/g' \ +-e 's/::0,/::,/g' \ +-e 's/::0:0 \([^>]\)/:: \1/g' \ +-e 's/:0:0 \([^>]\)/:: \1/g' \ +-e 's/::0 \([^>]\)/:: \1/g' \ +| sed \ +-e 's@::\([0-9]*\)::/16@::/16@g' \ +-e 's@::\([0-9]*\)::/32@::/32@g' \ +-e 's@::\([0-9]*\)::@::\1:0:0@g' \ +-e 's@::\([0-9]*\)::@::\1:0:0@g' \ +-e 's@::[:0-9]*\([^0-9:]\)/16@::/16@g' \ +-e 's@::[:0-9]*\([^0-9:]\)/32@::/32@g' diff --git a/test/expected/.cvsignore b/test/expected/.cvsignore new file mode 100644 index 0000000000000..47a4237755ac2 --- /dev/null +++ b/test/expected/.cvsignore @@ -0,0 +1 @@ +i19 diff --git a/test/expected/1 b/test/expected/1 deleted file mode 100644 index 93b733336d39e..0000000000000 --- a/test/expected/1 +++ /dev/null @@ -1,16 +0,0 @@ -block -block -nomatch -nomatch -pass -pass -nomatch -nomatch -nomatch -nomatch -block -block -nomatch -nomatch -pass -pass diff --git a/test/expected/14 b/test/expected/14 deleted file mode 100644 index d06d92b3e02af..0000000000000 --- a/test/expected/14 +++ /dev/null @@ -1,40 +0,0 @@ -nomatch -block -nomatch -nomatch -nomatch -nomatch -pass -nomatch -nomatch -nomatch -nomatch -block -block -nomatch -nomatch -nomatch -pass -pass -nomatch -nomatch -nomatch -block -block -block -nomatch -nomatch -pass -pass -pass -nomatch -block -block -block -block -block -pass -pass -pass -pass -pass diff --git a/test/expected/2 b/test/expected/2 deleted file mode 100644 index 03b71cdb9ea9a..0000000000000 --- a/test/expected/2 +++ /dev/null @@ -1,36 +0,0 @@ -block -block -nomatch -nomatch -nomatch -nomatch -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -nomatch -nomatch -nomatch -nomatch -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -nomatch -nomatch -nomatch -nomatch -pass -pass diff --git a/test/expected/3 b/test/expected/3 deleted file mode 100644 index d06d92b3e02af..0000000000000 --- a/test/expected/3 +++ /dev/null @@ -1,40 +0,0 @@ -nomatch -block -nomatch -nomatch -nomatch -nomatch -pass -nomatch -nomatch -nomatch -nomatch -block -block -nomatch -nomatch -nomatch -pass -pass -nomatch -nomatch -nomatch -block -block -block -nomatch -nomatch -pass -pass -pass -nomatch -block -block -block -block -block -pass -pass -pass -pass -pass diff --git a/test/expected/4 b/test/expected/4 deleted file mode 100644 index d06d92b3e02af..0000000000000 --- a/test/expected/4 +++ /dev/null @@ -1,40 +0,0 @@ -nomatch -block -nomatch -nomatch -nomatch -nomatch -pass -nomatch -nomatch -nomatch -nomatch -block -block -nomatch -nomatch -nomatch -pass -pass -nomatch -nomatch -nomatch -block -block -block -nomatch -nomatch -pass -pass -pass -nomatch -block -block -block -block -block -pass -pass -pass -pass -pass diff --git a/test/expected/5 b/test/expected/5 deleted file mode 100644 index bc805805f136e..0000000000000 --- a/test/expected/5 +++ /dev/null @@ -1,1344 +0,0 @@ -nomatch -nomatch -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -block -block -block -block -block -block -nomatch -nomatch -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -block -block -block -block -block -block -nomatch -nomatch -block -block -block -block -block -block -block -block -block -block -block -block -nomatch -nomatch -block -block -block -block -block -block -block -block -block -block -block -block -nomatch -nomatch -block -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -nomatch -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -nomatch -pass -nomatch -nomatch -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -nomatch -block -block -block -block -block -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -nomatch -block -block -block -block -block -block -block -block -block -block -block -block -block -nomatch -block -block -block -block -block -block -block -block -block -block -block -block -block -nomatch -block -block -block -block -block -block -block -block -block -block -pass -pass -pass -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch diff --git a/test/expected/6 b/test/expected/6 deleted file mode 100644 index bc805805f136e..0000000000000 --- a/test/expected/6 +++ /dev/null @@ -1,1344 +0,0 @@ -nomatch -nomatch -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -block -block -block -block -block -block -nomatch -nomatch -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -block -block -block -block -block -block -nomatch -nomatch -block -block -block -block -block -block -block -block -block -block -block -block -nomatch -nomatch -block -block -block -block -block -block -block -block -block -block -block -block -nomatch -nomatch -block -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -nomatch -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -nomatch -pass -nomatch -nomatch -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -nomatch -block -block -block -block -block -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -nomatch -block -block -block -block -block -block -block -block -block -block -block -block -block -nomatch -block -block -block -block -block -block -block -block -block -block -block -block -block -nomatch -block -block -block -block -block -block -block -block -block -block -pass -pass -pass -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -pass -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -pass -pass -pass -pass -pass -pass -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch diff --git a/test/expected/7 b/test/expected/7 deleted file mode 100644 index c53d6eaa0cb97..0000000000000 --- a/test/expected/7 +++ /dev/null @@ -1,54 +0,0 @@ -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -block -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -pass -pass -pass diff --git a/test/expected/8 b/test/expected/8 deleted file mode 100644 index 398058a5ec526..0000000000000 --- a/test/expected/8 +++ /dev/null @@ -1,36 +0,0 @@ -block -nomatch -nomatch -nomatch -nomatch -nomatch -pass -nomatch -nomatch -nomatch -nomatch -nomatch -block -nomatch -block -nomatch -nomatch -nomatch -pass -nomatch -pass -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -nomatch diff --git a/test/expected/f11 b/test/expected/f11 index c1eb060a71260..d7ab889dacdc3 100644 --- a/test/expected/f11 +++ b/test/expected/f11 @@ -24,6 +24,15 @@ List of configured pools List of configured hash tables List of groups configured (set 0) List of groups configured (set 1) +Rules configured (set 0, in) +1 pass in proto tcp from any to any port = 23 flags S/SA keep state +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) -------- block nomatch @@ -51,6 +60,15 @@ List of configured pools List of configured hash tables List of groups configured (set 0) List of groups configured (set 1) +Rules configured (set 0, in) +1 block in proto tcp from any to any port = 23 flags S/SA keep state +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) -------- nomatch nomatch @@ -78,6 +96,15 @@ List of configured pools List of configured hash tables List of groups configured (set 0) List of groups configured (set 1) +Rules configured (set 0, in) +2 pass in proto udp from any to any port = 53 keep frags +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) -------- nomatch nomatch @@ -105,6 +132,15 @@ List of configured pools List of configured hash tables List of groups configured (set 0) List of groups configured (set 1) +Rules configured (set 0, in) +2 block in proto udp from any to any port = 53 keep frags +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) -------- nomatch nomatch @@ -128,30 +164,31 @@ List of active sessions: Hostmap table: List of active state sessions: -2.2.2.2 -> 4.4.4.4 pass 0x40008402 pr 17 state 0/0 - tag 0 ttl 240 2 -> 53 - forward: pkts in 1 bytes in 28 pkts out 0 bytes out 0 - backward: pkts in 0 bytes in 0 pkts out 0 bytes out 0 - pass in keep state IPv4 - pkt_flags & 0(0) = 0, pkt_options & ffffffff = 0, ffffffff = 0 - pkt_security & ffff = 0, pkt_auth & ffff = 0 - is_flx 0x8001 0 0 0 +4:udp src:2.2.2.2,2 dst:4.4.4.4,53 240 + FWD: IN pkts 1 bytes 28 OUT pkts 0 bytes 0 + REV: IN pkts 0 bytes 0 OUT pkts 0 bytes 0 + tag 0 pass 0x2008402 = pass in keep state interfaces: in X[e1],X[] out X[],X[] Sync status: not synchronized -1.1.1.1 -> 4.4.4.4 pass 0x40008402 pr 17 state 0/0 - tag 0 ttl 24 1 -> 53 - forward: pkts in 1 bytes in 28 pkts out 0 bytes out 0 - backward: pkts in 1 bytes in 28 pkts out 0 bytes out 0 - pass in keep state IPv4 - pkt_flags & 0(0) = 0, pkt_options & ffffffff = 0, ffffffff = 0 - pkt_security & ffff = 0, pkt_auth & ffff = 0 - is_flx 0x8001 0x8001 0 0 +4:udp src:1.1.1.1,1 dst:4.4.4.4,53 24 + FWD: IN pkts 1 bytes 28 OUT pkts 0 bytes 0 + REV: IN pkts 1 bytes 28 OUT pkts 0 bytes 0 + tag 0 pass 0x2008402 = pass in keep state interfaces: in X[e1],X[e0] out X[],X[] Sync status: not synchronized List of configured pools List of configured hash tables List of groups configured (set 0) List of groups configured (set 1) +Rules configured (set 0, in) +2 pass in proto udp from any to any port = 53 keep state +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) -------- nomatch nomatch @@ -175,30 +212,31 @@ List of active sessions: Hostmap table: List of active state sessions: -2.2.2.2 -> 4.4.4.4 pass 0x40008401 pr 17 state 0/0 - tag 0 ttl 240 2 -> 53 - forward: pkts in 1 bytes in 28 pkts out 0 bytes out 0 - backward: pkts in 0 bytes in 0 pkts out 0 bytes out 0 - block in keep state IPv4 - pkt_flags & 0(0) = 0, pkt_options & ffffffff = 0, ffffffff = 0 - pkt_security & ffff = 0, pkt_auth & ffff = 0 - is_flx 0x8001 0 0 0 +4:udp src:2.2.2.2,2 dst:4.4.4.4,53 240 + FWD: IN pkts 1 bytes 28 OUT pkts 0 bytes 0 + REV: IN pkts 0 bytes 0 OUT pkts 0 bytes 0 + tag 0 pass 0x2008401 = block in keep state interfaces: in X[e1],X[] out X[],X[] Sync status: not synchronized -1.1.1.1 -> 4.4.4.4 pass 0x40008401 pr 17 state 0/0 - tag 0 ttl 24 1 -> 53 - forward: pkts in 1 bytes in 28 pkts out 0 bytes out 0 - backward: pkts in 1 bytes in 28 pkts out 0 bytes out 0 - block in keep state IPv4 - pkt_flags & 0(0) = 0, pkt_options & ffffffff = 0, ffffffff = 0 - pkt_security & ffff = 0, pkt_auth & ffff = 0 - is_flx 0x8001 0x8001 0 0 +4:udp src:1.1.1.1,1 dst:4.4.4.4,53 24 + FWD: IN pkts 1 bytes 28 OUT pkts 0 bytes 0 + REV: IN pkts 1 bytes 28 OUT pkts 0 bytes 0 + tag 0 pass 0x2008401 = block in keep state interfaces: in X[e1],X[e0] out X[],X[] Sync status: not synchronized List of configured pools List of configured hash tables List of groups configured (set 0) List of groups configured (set 1) +Rules configured (set 0, in) +2 block in proto udp from any to any port = 53 keep state +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) -------- nomatch nomatch @@ -222,22 +260,24 @@ List of active sessions: Hostmap table: List of active state sessions: -1.1.1.1 -> 2.1.2.2 pass 0x40008402 pr 6 state 3/4 - tag 0 ttl 864000 - 1 -> 25 2:66 4096<<0:16384<<0 - cmsk 0000 smsk 0000 s0 00000000/00000000 - FWD:ISN inc 0 sumd 0 - REV:ISN inc 0 sumd 0 - forward: pkts in 1 bytes in 40 pkts out 0 bytes out 0 - backward: pkts in 1 bytes in 40 pkts out 0 bytes out 0 - pass in keep state IPv4 - pkt_flags & 0(0) = 0, pkt_options & ffffffff = 0, ffffffff = 0 - pkt_security & ffff = 0, pkt_auth & ffff = 0 - is_flx 0x8001 0x8001 0 0 +4:tcp src:1.1.1.1,1 dst:2.1.2.2,25 state:3/4 864000 + 2:66 4096<<0:16384<<0 + FWD: IN pkts 1 bytes 40 OUT pkts 0 bytes 0 + REV: IN pkts 1 bytes 40 OUT pkts 0 bytes 0 + tag 0 pass 0x2008402 = pass in keep state interfaces: in X[e0],X[e1] out X[],X[] Sync status: not synchronized List of configured pools List of configured hash tables List of groups configured (set 0) List of groups configured (set 1) +Rules configured (set 0, in) +1 pass in on e0 proto tcp from any to any port = 25 keep state +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) -------- diff --git a/test/expected/f13 b/test/expected/f13 index 99c05651cea68..ac7947bd2922e 100644 --- a/test/expected/f13 +++ b/test/expected/f13 @@ -154,7 +154,27 @@ nomatch nomatch nomatch pass +block +block +pass +-------- +block +bad-packet +nomatch +pass +bad-packet +nomatch +nomatch +bad-packet +nomatch +bad-packet +nomatch nomatch nomatch +nomatch +nomatch +pass +pass +pass pass -------- diff --git a/test/expected/f18 b/test/expected/f18 index 801abd3694261..1af5de53cd053 100644 --- a/test/expected/f18 +++ b/test/expected/f18 @@ -2,4 +2,26 @@ pass pass pass pass +List of active MAP/Redirect filters: + +List of active sessions: + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +2 pass in inet from 1.1.1.1/32 to any +Rules configured (set 0, out) +2 pass out inet from 2.2.2.2/32 to any +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +1 count in inet from 1.1.1.1/32 to 3.3.3.3/32 +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +1 count out inet from 2.2.2.2/32 to 4.4.4.4/32 +Accounting rules configured (set 1, out) -------- diff --git a/test/expected/f21 b/test/expected/f21 new file mode 100644 index 0000000000000..525dacaae7200 --- /dev/null +++ b/test/expected/f21 @@ -0,0 +1,5 @@ +pass +pass +nomatch +nomatch +-------- diff --git a/test/expected/f22 b/test/expected/f22 new file mode 100644 index 0000000000000..525dacaae7200 --- /dev/null +++ b/test/expected/f22 @@ -0,0 +1,5 @@ +pass +pass +nomatch +nomatch +-------- diff --git a/test/expected/f25 b/test/expected/f25 new file mode 100644 index 0000000000000..a87b084cdadd1 --- /dev/null +++ b/test/expected/f25 @@ -0,0 +1,35 @@ +pass +pass +pass +List of active MAP/Redirect filters: + +List of active sessions: + +Hostmap table: +List of active state sessions: +4:udp src:192.168.1.235,8008 dst:239.255.255.250,1900 240 + FWD: IN pkts 1 bytes 129 OUT pkts 0 bytes 0 + REV: IN pkts 0 bytes 0 OUT pkts 0 bytes 0 + tag 0 pass 0x2008402 = pass in keep state + interfaces: in X[hme0],X[] out X[],X[] + Sync status: not synchronized +4:udp src:192.168.1.235,8008 dst:192.168.1.254,1900 24 + FWD: IN pkts 1 bytes 129 OUT pkts 0 bytes 0 + REV: IN pkts 0 bytes 0 OUT pkts 1 bytes 264 + tag 0 pass 0x2008402 = pass in keep state + interfaces: in X[hme0],X[] out X[],X[hme0] + Sync status: not synchronized +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +2 pass in on hme0 proto udp from any to any with mcast keep state +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +-------- diff --git a/test/expected/10 b/test/expected/f26 index bc0d83ec88f2e..9e4d62b51730e 100644 --- a/test/expected/10 +++ b/test/expected/f26 @@ -1,108 +1,84 @@ -nomatch -block -nomatch -nomatch -nomatch -nomatch pass pass pass -nomatch -nomatch pass -block -block -block -nomatch -nomatch -block pass pass +nomatch +pass pass nomatch +pass +pass nomatch +-------- pass -block -block nomatch nomatch nomatch -block pass pass nomatch nomatch nomatch -pass -block -block -block -block -block -block -pass -pass -pass -pass -pass -pass nomatch -block -block -block nomatch -block nomatch -pass -pass -pass nomatch +-------- pass nomatch -pass nomatch nomatch nomatch nomatch nomatch -block -block -block -block -block nomatch +nomatch +nomatch +nomatch +nomatch +nomatch +-------- pass pass pass pass pass -block -block -nomatch -block -nomatch -block -pass pass nomatch pass -nomatch pass -block -block -block -block -block -block +nomatch pass pass +nomatch +-------- pass +nomatch +nomatch +nomatch pass pass +nomatch +nomatch +nomatch +nomatch +nomatch +nomatch +nomatch +-------- pass -block -block -block nomatch nomatch -block +nomatch +nomatch +nomatch +nomatch +nomatch +nomatch +nomatch +nomatch +nomatch +nomatch +-------- diff --git a/test/expected/9 b/test/expected/f27 index a4572e6e94e0a..c62f588e8b93e 100644 --- a/test/expected/9 +++ b/test/expected/f27 @@ -1,33 +1,24 @@ -block -block -block -block -block -block -nomatch -nomatch -nomatch pass pass -nomatch -nomatch -nomatch -nomatch -nomatch -block -nomatch -nomatch -nomatch -nomatch -nomatch +pass +pass +pass pass nomatch +pass +pass nomatch +pass +pass nomatch nomatch +-------- +pass nomatch nomatch nomatch +pass +pass nomatch nomatch nomatch @@ -36,6 +27,8 @@ nomatch nomatch nomatch nomatch +-------- +pass nomatch nomatch nomatch @@ -47,37 +40,30 @@ nomatch nomatch nomatch nomatch -block -nomatch -nomatch -nomatch -nomatch -nomatch -pass -nomatch -nomatch nomatch nomatch +-------- pass pass pass pass pass pass -block -block -nomatch -nomatch -nomatch nomatch pass pass nomatch +pass +pass nomatch nomatch +-------- +pass nomatch nomatch nomatch +pass +pass nomatch nomatch nomatch @@ -86,6 +72,8 @@ nomatch nomatch nomatch nomatch +-------- +pass nomatch nomatch nomatch @@ -98,11 +86,5 @@ nomatch nomatch nomatch nomatch -nomatch -nomatch -nomatch -nomatch -nomatch -block -block -nomatch +pass +-------- diff --git a/test/expected/f28 b/test/expected/f28 new file mode 100644 index 0000000000000..e5867e690103b --- /dev/null +++ b/test/expected/f28 @@ -0,0 +1,32 @@ +block +block +block +> nic0 ip #0 20(20) 0 4.4.3.1 > 4.2.3.2 +pass +> nic1 ip #0 20(20) 0 4.4.1.1 > 4.2.1.2 +pass +> nic2 ip #0 20(20) 0 4.4.2.1 > 4.2.2.2 +pass +> nic3 ip #0 20(20) 0 4.4.3.1 > 4.2.3.2 +pass +List of active MAP/Redirect filters: + +List of active sessions: + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +7 block in all +4 pass in on nic0 to dstlist/spread inet from 4.4.0.0/16 to any +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/f29 b/test/expected/f29 new file mode 100644 index 0000000000000..a650c1b452897 --- /dev/null +++ b/test/expected/f29 @@ -0,0 +1,64 @@ +block +block +block +> nic0 ip #0 28(20) 17 4.4.3.1,1000 > 4.2.3.2,2000 +pass +> nic0 ip #0 28(20) 17 4.4.3.1,1000 > 4.2.3.2,2000 +pass +> nic1 ip #0 28(20) 17 4.4.1.1,1001 > 4.2.1.2,2001 +pass +> nic1 ip #0 28(20) 17 4.4.1.1,1001 > 4.2.1.2,2001 +pass +> nic2 ip #0 28(20) 17 4.4.2.1,1002 > 4.2.2.2,2002 +pass +> nic2 ip #0 28(20) 17 4.4.2.1,1002 > 4.2.2.2,2002 +pass +> nic3 ip #0 28(20) 17 4.4.3.1,1003 > 4.2.3.2,2003 +pass +> nic3 ip #0 28(20) 17 4.4.3.1,1003 > 4.2.3.2,2003 +pass +List of active MAP/Redirect filters: + +List of active sessions: + +Hostmap table: +List of active state sessions: +4:udp src:4.4.3.1,1003 dst:4.2.3.2,2003 240 + FWD: IN pkts 2 bytes 56 OUT pkts 2 bytes 56 + REV: IN pkts 0 bytes 0 OUT pkts 0 bytes 0 + tag 0 pass 0x2008402 = pass in keep state + interfaces: in X[nic0],X[] out X[nic3],X[] + Sync status: not synchronized +4:udp src:4.4.2.1,1002 dst:4.2.2.2,2002 240 + FWD: IN pkts 2 bytes 56 OUT pkts 2 bytes 56 + REV: IN pkts 0 bytes 0 OUT pkts 0 bytes 0 + tag 0 pass 0x2008402 = pass in keep state + interfaces: in X[nic0],X[] out X[nic2],X[] + Sync status: not synchronized +4:udp src:4.4.1.1,1001 dst:4.2.1.2,2001 240 + FWD: IN pkts 2 bytes 56 OUT pkts 2 bytes 56 + REV: IN pkts 0 bytes 0 OUT pkts 0 bytes 0 + tag 0 pass 0x2008402 = pass in keep state + interfaces: in X[nic0],X[] out X[nic1],X[] + Sync status: not synchronized +4:udp src:4.4.3.1,1000 dst:4.2.3.2,2000 240 + FWD: IN pkts 2 bytes 56 OUT pkts 2 bytes 56 + REV: IN pkts 0 bytes 0 OUT pkts 0 bytes 0 + tag 0 pass 0x2008402 = pass in keep state + interfaces: in X[nic0],X[] out X[nic0],X[] + Sync status: not synchronized +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +7 block in all +4 pass in on nic0 to dstlist/spread inet from 4.4.0.0/16 to any keep state +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/11 b/test/expected/f30 index eb00875e01a91..30b9d405d0aeb 100644 --- a/test/expected/11 +++ b/test/expected/f30 @@ -1,5 +1,6 @@ -pass -pass +nomatch +nomatch +nomatch pass pass nomatch @@ -9,14 +10,13 @@ nomatch nomatch nomatch nomatch -block -block -block -block nomatch nomatch nomatch nomatch +-------- +pass +pass nomatch nomatch nomatch @@ -26,21 +26,20 @@ nomatch nomatch nomatch nomatch -pass -pass nomatch nomatch nomatch nomatch nomatch +-------- nomatch nomatch nomatch nomatch -block -block nomatch +pass nomatch +pass nomatch nomatch nomatch @@ -48,9 +47,9 @@ nomatch nomatch nomatch nomatch -pass -pass -pass +nomatch +-------- +nomatch nomatch nomatch nomatch @@ -59,8 +58,11 @@ nomatch nomatch nomatch nomatch -block -block -block +nomatch +pass +nomatch +nomatch +pass nomatch nomatch +-------- diff --git a/test/expected/i1 b/test/expected/i1 index 74d0f309b6164..19ae393e58e01 100644 --- a/test/expected/i1 +++ b/test/expected/i1 @@ -5,8 +5,8 @@ log body in all count in from any to any pass in from !any to any pps 10 block in from any to !any -pass in on ed0(!) from 127.0.0.1/32 to 127.0.0.1/32 -pass in on ed0(!),vx0(!) from 127.0.0.1/32 to 127.0.0.1/32 +pass in on ed0(!) inet from 127.0.0.1/32 to 127.0.0.1/32 +pass in on ed0(!),vx0(!) inet from 127.0.0.1/32 to 127.0.0.1/32 block in log first on lo0(!) from any to any pass in log body or-block quick from any to any block return-rst in quick on le0(!) proto tcp from any to any @@ -14,4 +14,4 @@ block return-icmp in on qe0(!) from any to any block return-icmp(host-unr) in on qe0(!) from any to any block return-icmp-as-dest in on le0(!) from any to any block return-icmp-as-dest(port-unr) in on qe0(!) from any to any -pass out on longNICname0(!) from 254.220.186.152/32 to 254.220.186.152/32 +pass out on longNICname0(!) inet from 254.220.186.152/32 to 254.220.186.152/32 diff --git a/test/expected/i10 b/test/expected/i10 index 9e0a5d5ab8bab..24137c1e29c9e 100644 --- a/test/expected/i10 +++ b/test/expected/i10 @@ -1,5 +1,5 @@ -pass in from 127.0.0.1/32 to 127.0.0.1/32 with opt sec -pass in from 127.0.0.1/32 to 127.0.0.1/32 with opt lsrr not opt sec -block in from any to any with not opt sec-class topsecret -block in from any to any with not opt sec-class topsecret,secret -pass in from any to any with opt sec-class topsecret,confid not opt sec-class unclass +pass in inet from 127.0.0.1/32 to 127.0.0.1/32 with opt sec +pass in inet from 127.0.0.1/32 to 127.0.0.1/32 with opt lsrr not opt sec +block in inet from any to any with not opt sec-class topsecret +block in inet from any to any with not opt sec-class topsecret,secret +pass in inet from any to any with opt sec-class topsecret,confid not opt sec-class unclass diff --git a/test/expected/i11 b/test/expected/i11 index 154f31e810bb2..d1d2cf6c57426 100644 --- a/test/expected/i11 +++ b/test/expected/i11 @@ -1,11 +1,12 @@ -pass in on ed0(!) proto tcp from 127.0.0.1/32 to 127.0.0.1/32 port = 23 keep state # count 0 +pass in on ed0(!) inet proto tcp from 127.0.0.1/32 to 127.0.0.1/32 port = 23 keep state # count 0 block in log first on lo0(!) proto tcp/udp from any to any port = 7 keep state # count 0 -pass in proto udp from 127.0.0.1/32 to 127.0.0.1/32 port = 20499 keep frags -pass in proto udp from 127.0.0.1/32 to 127.0.0.1/32 port = 2049 keep frags (strict) -pass in proto udp from 127.0.0.1/32 to 127.0.0.1/32 port = 53 keep state keep frags # count 0 +pass in inet proto udp from 127.0.0.1/32 to 127.0.0.1/32 port = 20499 keep frags +pass in inet proto udp from 127.0.0.1/32 to 127.0.0.1/32 port = 2049 keep frags (strict) +pass in inet proto udp from 127.0.0.1/32 to 127.0.0.1/32 port = 53 keep state keep frags # count 0 pass in on ed0(!) out-via vx0(!) proto udp from any to any keep state # count 0 pass out on ppp0(!) in-via le0(!) proto tcp from any to any keep state # count 0 pass in on ed0(!),vx0(!) out-via vx0(!),ed0(!) proto udp from any to any keep state # count 0 -pass in proto tcp from any port > 1024 to 127.0.0.1/32 port = 1024 keep state # count 0 +pass in inet proto tcp from any port > 1024 to 127.0.0.1/32 port = 1024 keep state # count 0 pass in proto tcp from any to any flags S/FSRPAU keep state (limit 101,strict,newisn,no-icmp-err,age 600/600) # count 0 +pass in proto tcp from any to any flags S/FSRPAU keep state (limit 101,loose,newisn,no-icmp-err,age 600/600) # count 0 pass in proto udp from any to any keep state (sync,age 10/20) # count 0 diff --git a/test/expected/i12 b/test/expected/i12 index dadf597fc3dfd..6747d93389022 100644 --- a/test/expected/i12 +++ b/test/expected/i12 @@ -1,39 +1,39 @@ -pass in from 1.1.1.1/32 to 2.2.2.2/32 -pass in from 2.2.2.0/24 to 4.4.4.4/32 -pass in from 3.3.3.3/32 to 4.4.4.4/32 -pass in from 2.2.2.0/24 to 5.5.5.5/32 -pass in from 3.3.3.3/32 to 5.5.5.5/32 -pass in from 2.2.2.0/24 to 6.6.6.6/32 -pass in from 3.3.3.3/32 to 6.6.6.6/32 -pass in from 2.2.2.0/24 to 5.5.5.5/32 port = 22 -pass in from 3.3.3.3/32 to 5.5.5.5/32 port = 22 -pass in from 2.2.2.0/24 to 6.6.6.6/32 port = 22 -pass in from 3.3.3.3/32 to 6.6.6.6/32 port = 22 -pass in from 2.2.2.0/24 to 5.5.5.5/32 port = 25 -pass in from 3.3.3.3/32 to 5.5.5.5/32 port = 25 -pass in from 2.2.2.0/24 to 6.6.6.6/32 port = 25 -pass in from 3.3.3.3/32 to 6.6.6.6/32 port = 25 -pass in proto tcp from 2.2.2.0/24 port = 53 to 5.5.5.5/32 -pass in proto tcp from 3.3.3.3/32 port = 53 to 5.5.5.5/32 -pass in proto tcp from 2.2.2.0/24 port = 9 to 5.5.5.5/32 -pass in proto tcp from 3.3.3.3/32 port = 9 to 5.5.5.5/32 -pass in proto tcp from 2.2.2.0/24 port = 53 to 6.6.6.6/32 -pass in proto tcp from 3.3.3.3/32 port = 53 to 6.6.6.6/32 -pass in proto tcp from 2.2.2.0/24 port = 9 to 6.6.6.6/32 -pass in proto tcp from 3.3.3.3/32 port = 9 to 6.6.6.6/32 -pass in proto udp from 2.2.2.0/24 to 5.5.5.5/32 port = 53 -pass in proto udp from 3.3.3.3/32 to 5.5.5.5/32 port = 53 -pass in proto udp from 2.2.2.0/24 to 6.6.6.6/32 port = 53 -pass in proto udp from 3.3.3.3/32 to 6.6.6.6/32 port = 53 -pass in proto udp from 2.2.2.0/24 to 5.5.5.5/32 port = 9 -pass in proto udp from 3.3.3.3/32 to 5.5.5.5/32 port = 9 -pass in proto udp from 2.2.2.0/24 to 6.6.6.6/32 port = 9 -pass in proto udp from 3.3.3.3/32 to 6.6.6.6/32 port = 9 -pass in from 10.10.10.10/32 to 11.11.11.11/32 -pass in from pool/101(!) to hash/202(!) -pass in from hash/303(!) to pool/404(!) -table role = ipf type = tree name = - { ! 1.1.1.1/32; 2.2.2.2/32; ! 2.2.0.0/16; }; -table role = ipf type = tree name = +pass in inet from 1.1.1.1/32 to 2.2.2.2/32 +pass in inet from 2.2.2.0/24 to 4.4.4.4/32 +pass in inet from 3.3.3.3/32 to 4.4.4.4/32 +pass in inet from 2.2.2.0/24 to 5.5.5.5/32 +pass in inet from 3.3.3.3/32 to 5.5.5.5/32 +pass in inet from 2.2.2.0/24 to 6.6.6.6/32 +pass in inet from 3.3.3.3/32 to 6.6.6.6/32 +pass in inet from 2.2.2.0/24 to 5.5.5.5/32 port = 22 +pass in inet from 3.3.3.3/32 to 5.5.5.5/32 port = 22 +pass in inet from 2.2.2.0/24 to 6.6.6.6/32 port = 22 +pass in inet from 3.3.3.3/32 to 6.6.6.6/32 port = 22 +pass in inet from 2.2.2.0/24 to 5.5.5.5/32 port = 25 +pass in inet from 3.3.3.3/32 to 5.5.5.5/32 port = 25 +pass in inet from 2.2.2.0/24 to 6.6.6.6/32 port = 25 +pass in inet from 3.3.3.3/32 to 6.6.6.6/32 port = 25 +pass in inet proto tcp from 2.2.2.0/24 port = 53 to 5.5.5.5/32 +pass in inet proto tcp from 3.3.3.3/32 port = 53 to 5.5.5.5/32 +pass in inet proto tcp from 2.2.2.0/24 port = 9 to 5.5.5.5/32 +pass in inet proto tcp from 3.3.3.3/32 port = 9 to 5.5.5.5/32 +pass in inet proto tcp from 2.2.2.0/24 port = 53 to 6.6.6.6/32 +pass in inet proto tcp from 3.3.3.3/32 port = 53 to 6.6.6.6/32 +pass in inet proto tcp from 2.2.2.0/24 port = 9 to 6.6.6.6/32 +pass in inet proto tcp from 3.3.3.3/32 port = 9 to 6.6.6.6/32 +pass in inet proto udp from 2.2.2.0/24 to 5.5.5.5/32 port = 53 +pass in inet proto udp from 3.3.3.3/32 to 5.5.5.5/32 port = 53 +pass in inet proto udp from 2.2.2.0/24 to 6.6.6.6/32 port = 53 +pass in inet proto udp from 3.3.3.3/32 to 6.6.6.6/32 port = 53 +pass in inet proto udp from 2.2.2.0/24 to 5.5.5.5/32 port = 9 +pass in inet proto udp from 3.3.3.3/32 to 5.5.5.5/32 port = 9 +pass in inet proto udp from 2.2.2.0/24 to 6.6.6.6/32 port = 9 +pass in inet proto udp from 3.3.3.3/32 to 6.6.6.6/32 port = 9 +pass in inet from 10.10.10.10/32 to 11.11.11.11/32 +pass in from pool/101 to hash/202 +pass in from hash/303 to pool/404 +table role=ipf type=tree number= + { ! 2.2.0.0/16; 2.2.2.2/32; ! 1.1.1.1/32; }; +table role=ipf type=tree number= { 1.1.0.0/16; }; -pass in from pool/0(!) to pool/0(!) +pass in from pool/0 to pool/0 diff --git a/test/expected/i14 b/test/expected/i14 index 08ba19ad55881..bccdcac6deeb5 100644 --- a/test/expected/i14 +++ b/test/expected/i14 @@ -3,8 +3,10 @@ pass in on eri0(!) proto icmp from any to any group 1 pass out on ed0(!) all head 1000000 block out on ed0(!) proto udp from any to any group 1000000 block in on vm0(!) proto tcp/udp from any to any head 101 -pass in proto tcp/udp from 1.1.1.1/32 to 2.2.2.2/32 group 101 -pass in proto tcp from 1.0.0.1/32 to 2.0.0.2/32 group 101 -pass in proto udp from 2.0.0.2/32 to 3.0.0.3/32 group 101 +pass in inet proto tcp/udp from 1.1.1.1/32 to 2.2.2.2/32 group 101 +pass in inet proto tcp from 1.0.0.1/32 to 2.0.0.2/32 group 101 +pass in inet proto udp from 2.0.0.2/32 to 3.0.0.3/32 group 101 block in on vm0(!) proto tcp/udp from any to any head vm0-group -pass in proto tcp/udp from 1.1.1.1/32 to 2.2.2.2/32 group vm0-group +pass in inet proto tcp/udp from 1.1.1.1/32 to 2.2.2.2/32 group vm0-group +block in on vm0(!) proto tcp/udp from any to any head vm0-group +pass in inet proto tcp/udp from 1.1.1.1/32 to 2.2.2.2/32 group vm0-group diff --git a/test/expected/i17 b/test/expected/i17 index bcc4d2d544a5b..9e71cb1003223 100644 --- a/test/expected/i17 +++ b/test/expected/i17 @@ -8,3 +8,22 @@ List of configured pools List of configured hash tables List of groups configured (set 0) List of groups configured (set 1) +Rules configured (set 0, in) +0 pass in inet from 1.1.1.1/32 to any +0 pass in all +0 pass in inet from 3.3.3.3/32 to any +0 pass in inet from any to 127.0.0.1/32 +0 pass in inet from 127.0.0.1/32 to any +0 100 pass in inet from 127.0.0.1/32 to any +0 100 pass in all +0 110 pass in proto udp from any to any +0 110 pass in inet from 2.2.2.2/32 to any +0 110 pass in inet from 127.0.0.1/32 to any +0 200 pass in proto tcp from any to any +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) diff --git a/test/expected/i18 b/test/expected/i18 index 88fca4744c462..2c7e4935d5243 100644 --- a/test/expected/i18 +++ b/test/expected/i18 @@ -1,7 +1,7 @@ pass in tos 0x50 from any to any pass in tos 0x80 from any to any -pass in tos 0x80 from any to any -pass in tos 0x50 from any to any +pass out tos 0x80 from any to any +pass out tos 0x50 from any to any block in ttl 0 from any to any block in ttl 1 from any to any block in ttl 2 from any to any diff --git a/test/expected/i19 b/test/expected/i19 deleted file mode 100644 index 4ca19b5138fa1..0000000000000 --- a/test/expected/i19 +++ /dev/null @@ -1,22 +0,0 @@ -block in log level user.debug quick proto icmp from any to any -block in log level mail.info quick proto icmp from any to any -block in log level daemon.notice quick proto icmp from any to any -block in log level auth.warn quick proto icmp from any to any -block in log level syslog.err quick proto icmp from any to any -block in log level lpr.crit quick proto icmp from any to any -block in log level news.alert quick proto icmp from any to any -block in log level uucp.emerg quick proto icmp from any to any -block in log level cron.debug quick proto icmp from any to any -block in log level ftp.info quick proto icmp from any to any -block in log level authpriv.notice quick proto icmp from any to any -block in log level !!!.warn quick proto icmp from any to any -block in log level local0.err quick proto icmp from any to any -block in log level local1.crit quick proto icmp from any to any -block in log level local2.alert quick proto icmp from any to any -block in log level local3.emerg quick proto icmp from any to any -block in log level local4.debug quick proto icmp from any to any -block in log level local5.info quick proto icmp from any to any -block in log level local6.notice quick proto icmp from any to any -block in log level local7.warn quick proto icmp from any to any -block in log level kern.err quick proto icmp from any to any -block in log level !!!.emerg quick proto icmp from any to any diff --git a/test/expected/i2 b/test/expected/i2 index 5ff18f4f924c4..17b9d07883f72 100644 --- a/test/expected/i2 +++ b/test/expected/i2 @@ -1,8 +1,9 @@ log in proto tcp from any to any pass in proto tcp from any to any -pass in proto udp from 127.0.0.1/32 to 127.0.0.1/32 +pass in inet proto udp from 127.0.0.1/32 to 127.0.0.1/32 block in proto ipv6 from any to any block in proto udp from any to any block in proto 250 from any to any pass in proto tcp/udp from any to any block in proto tcp/udp from any to any +block in proto tcp/udp from any to any diff --git a/test/expected/i20 b/test/expected/i20 index 77eabdb55f0bc..25e35cd9f5c66 100644 --- a/test/expected/i20 +++ b/test/expected/i20 @@ -1,4 +1,4 @@ -pass in on ppp0(!) from ppp0/peer to ppp0/32 -block in on hme0(!) from any to hme0/bcast -pass in on bge0(!) from bge0/net to bge0/32 -block in on eri0(!) from any to eri0/netmasked +pass in on ppp0(!) inet from ppp0/peer to ppp0/32 +block in on hme0(!) inet from any to hme0/bcast +pass in on bge0(!) inet from bge0/net to bge0/32 +block in on eri0(!) inet from any to eri0/netmasked diff --git a/test/expected/i22 b/test/expected/i22 new file mode 100644 index 0000000000000..6e5a07d634b08 --- /dev/null +++ b/test/expected/i22 @@ -0,0 +1,5 @@ +pass in exp { "ip.src != 1.1.1.0/24; tcp.dport = 80;" } +pass in exp { "ip.addr = 1.2.3.4/32,5.6.7.8/32;" } +block out exp { "ip.dst = 127.0.0.0/8;" } +block in exp { "udp.sport = 53; udp.dport = 53;" } +pass out exp { "tcp.sport = 22; tcp.port = 25;" } diff --git a/test/expected/i23 b/test/expected/i23 new file mode 100644 index 0000000000000..e69de29bb2d1d --- /dev/null +++ b/test/expected/i23 diff --git a/test/expected/i3 b/test/expected/i3 index 6150c7e55bd1c..691ad257f3896 100644 --- a/test/expected/i3 +++ b/test/expected/i3 @@ -1,11 +1,11 @@ log in all -pass in from 128.16.0.0/16 to 129.10.10.0/24 -pass in from 128.0.0.0/24 to 128.0.0.0/16 -pass in from 128.0.0.0/24 to 128.0.0.0/16 -pass in from 128.0.0.0/24 to 128.0.0.0/16 -pass in from 128.0.0.0/24 to 128.0.0.0/16 -pass in from 128.0.0.0/24 to 128.0.0.0/16 -pass in from 127.0.0.1/32 to 127.0.0.1/32 -block in log from any to any +pass in inet from 128.16.0.0/16 to 129.10.10.0/24 +pass in inet from 128.0.0.0/24 to 128.0.0.0/16 +pass in inet from 128.0.0.0/24 to 128.0.0.0/16 +pass in inet from 128.0.0.0/24 to 128.0.0.0/16 +pass in inet from 128.0.0.0/24 to 128.0.0.0/16 +pass in inet from 128.0.0.0/24 to 128.0.0.0/16 +pass in inet from 127.0.0.1/32 to 127.0.0.1/32 +block in log inet from any to any block in log level auth.info on hme0(!) all log level local5.warn out all diff --git a/test/expected/i4 b/test/expected/i4 index 49924555a27ea..1198714fb55d0 100644 --- a/test/expected/i4 +++ b/test/expected/i4 @@ -1,7 +1,7 @@ log in proto tcp from any port > 0 to any log in proto tcp from any to any port > 0 pass in proto tcp from any port != 0 to any port 0 >< 65535 -pass in proto udp from 127.0.0.1/32 port > 32000 to 127.0.0.1/32 port < 29000 +pass in inet proto udp from 127.0.0.1/32 port > 32000 to 127.0.0.1/32 port < 29000 block in proto udp from any port != 123 to any port < 7 block in proto tcp from any port = 25 to any port > 25 pass in proto tcp/udp from any port 1 >< 3 to any port 1 <> 3 diff --git a/test/expected/i5 b/test/expected/i5 index edf986558f263..0dbc859b9a4db 100644 --- a/test/expected/i5 +++ b/test/expected/i5 @@ -1,9 +1,9 @@ log in all count in tos 0x80 from any to any -pass in on ed0(!) tos 0x40 from 127.0.0.1/32 to 127.0.0.1/32 +pass in on ed0(!) inet tos 0x40 from 127.0.0.1/32 to 127.0.0.1/32 block in log on lo0(!) ttl 0 from any to any pass in quick ttl 1 from any to any -skip 3 out from 127.0.0.1/32 to any +skip 3 out inet from 127.0.0.1/32 to any auth out on foo0(!) proto tcp from any to any port = 80 preauth out on foo0(!) proto tcp from any to any port = 22 nomatch out on foo0(!) proto tcp from any port < 1024 to any diff --git a/test/expected/i6 b/test/expected/i6 index e4b14c328cbfa..29c33a265f37b 100644 --- a/test/expected/i6 +++ b/test/expected/i6 @@ -1,12 +1,12 @@ pass in on lo0(!) fastroute from any to any -pass in on lo0(!) to qe0(!) from 127.0.0.1/32 to 127.0.0.1/32 -pass in on le0(!) to qe0(!):127.0.0.1 from 127.0.0.1/32 to 127.0.0.1/32 -pass in on lo0(!) dup-to qe0(!) from 127.0.0.1/32 to 127.0.0.1/32 -pass in on le0(!) dup-to qe0(!):127.0.0.1 from 127.0.0.1/32 to 127.0.0.1/32 -pass in on le0(!) dup-to qe0(!):127.0.0.1 to hme0(!):10.1.1.1 from 127.0.0.1/32 to 127.0.0.1/32 +pass in on lo0(!) to qe0(!) inet from 127.0.0.1/32 to 127.0.0.1/32 +pass in on le0(!) to qe0:127.0.0.1 inet from 127.0.0.1/32 to 127.0.0.1/32 +pass in on lo0(!) dup-to qe0(!) inet from 127.0.0.1/32 to 127.0.0.1/32 +pass in on le0(!) dup-to qe0:127.0.0.1 inet from 127.0.0.1/32 to 127.0.0.1/32 +pass in on le0(!) to hme0:10.1.1.1 dup-to qe0:127.0.0.1 inet from 127.0.0.1/32 to 127.0.0.1/32 block in quick on qe0(!) to qe1(!) from any to any block in quick to qe1(!) from any to any pass out quick dup-to hme0(!) from any to any pass out quick on hme0(!) reply-to hme1(!) from any to any -pass in on le0(!) dup-to qe0(!):127.0.0.1 reply-to hme1(!):10.10.10.10 all +pass in on le0(!) dup-to qe0:127.0.0.1 reply-to hme1:10.10.10.10 inet all pass in quick fastroute all diff --git a/test/expected/i7 b/test/expected/i7 index 309cd28691b19..552f7f811ef3b 100644 --- a/test/expected/i7 +++ b/test/expected/i7 @@ -1,4 +1,4 @@ -pass in on ed0(!) proto tcp from 127.0.0.1/32 to 127.0.0.1/32 port = 23 flags S/SA +pass in on ed0(!) inet proto tcp from 127.0.0.1/32 to 127.0.0.1/32 port = 23 flags S/SA block in on lo0(!) proto tcp from any to any flags A/FSRPAU pass in on lo0(!) proto tcp from any to any flags /SPA block in on lo0(!) proto tcp from any to any flags C/A @@ -7,3 +7,8 @@ block in on lo0(!) proto tcp from any to any flags S/SA pass in on lo0(!) proto tcp from any to any flags S/FSRPAU block in on lo0(!) proto tcp from any to any flags /A pass in on lo0(!) proto tcp from any to any flags S/SA +pass in on lo0(!) proto tcp from any to any flags S/SA +block in on lo0(!) proto tcp from any to any flags S/SA +pass in on lo0(!) proto tcp from any to any flags S/FSRPAU +block in on lo0(!) proto tcp from any to any flags /A +pass in on lo0(!) proto tcp from any to any flags S/SA diff --git a/test/expected/i8 b/test/expected/i8 index f033e6b8d891e..a85f1deb270f0 100644 --- a/test/expected/i8 +++ b/test/expected/i8 @@ -1,35 +1,66 @@ -pass in proto icmp from 127.0.0.1/32 to 127.0.0.1/32 icmp-type timest -block in proto icmp from any to any icmp-type unreach code 1 -pass in proto icmp from any to any icmp-type unreach code 15 -pass in proto icmp from any to any icmp-type unreach code 13 -pass in proto icmp from any to any icmp-type unreach code 8 -pass in proto icmp from any to any icmp-type unreach code 4 -pass in proto icmp from any to any icmp-type unreach code 9 -pass in proto icmp from any to any icmp-type unreach code 11 -pass in proto icmp from any to any icmp-type unreach code 14 -pass in proto icmp from any to any icmp-type unreach code 10 -pass in proto icmp from any to any icmp-type unreach code 12 -pass in proto icmp from any to any icmp-type unreach code 7 -pass in proto icmp from any to any icmp-type unreach code 1 -pass in proto icmp from any to any icmp-type unreach code 6 -pass in proto icmp from any to any icmp-type unreach code 0 -pass in proto icmp from any to any icmp-type unreach code 3 -pass in proto icmp from any to any icmp-type unreach code 2 -pass in proto icmp from any to any icmp-type unreach code 5 -pass in proto icmp from any to any icmp-type echo -pass in proto icmp from any to any icmp-type echorep -pass in proto icmp from any to any icmp-type inforeq -pass in proto icmp from any to any icmp-type inforep -pass in proto icmp from any to any icmp-type maskrep -pass in proto icmp from any to any icmp-type maskreq -pass in proto icmp from any to any icmp-type paramprob -pass in proto icmp from any to any icmp-type redir -pass in proto icmp from any to any icmp-type unreach -pass in proto icmp from any to any icmp-type routerad -pass in proto icmp from any to any icmp-type routersol -pass in proto icmp from any to any icmp-type squench -pass in proto icmp from any to any icmp-type timest -pass in proto icmp from any to any icmp-type timestrep -pass in proto icmp from any to any icmp-type timex -pass in proto icmp from any to any icmp-type 254 -pass in proto icmp from any to any icmp-type 253 code 254 +pass in inet proto icmp from 127.0.0.1/32 to 127.0.0.1/32 icmp-type timest +block in inet proto icmp from any to any icmp-type unreach code 1 +pass in inet proto icmp from any to any icmp-type unreach code 15 +pass in inet proto icmp from any to any icmp-type unreach code 13 +pass in inet proto icmp from any to any icmp-type unreach code 8 +pass in inet proto icmp from any to any icmp-type unreach code 4 +pass in inet proto icmp from any to any icmp-type unreach code 9 +pass in inet proto icmp from any to any icmp-type unreach code 11 +pass in inet proto icmp from any to any icmp-type unreach code 14 +pass in inet proto icmp from any to any icmp-type unreach code 10 +pass in inet proto icmp from any to any icmp-type unreach code 12 +pass in inet proto icmp from any to any icmp-type unreach code 7 +pass in inet proto icmp from any to any icmp-type unreach code 1 +pass in inet proto icmp from any to any icmp-type unreach code 6 +pass in inet proto icmp from any to any icmp-type unreach code 0 +pass in inet proto icmp from any to any icmp-type unreach code 3 +pass in inet proto icmp from any to any icmp-type unreach code 2 +pass in inet proto icmp from any to any icmp-type unreach code 5 +pass in inet proto icmp from any to any icmp-type echo +pass in inet proto icmp from any to any icmp-type echorep +pass in inet proto icmp from any to any icmp-type inforeq +pass in inet proto icmp from any to any icmp-type inforep +pass in inet proto icmp from any to any icmp-type maskrep +pass in inet proto icmp from any to any icmp-type maskreq +pass in inet proto icmp from any to any icmp-type paramprob +pass in inet proto icmp from any to any icmp-type redir +pass in inet proto icmp from any to any icmp-type unreach +pass in inet proto icmp from any to any icmp-type routerad +pass in inet proto icmp from any to any icmp-type routersol +pass in inet proto icmp from any to any icmp-type squench +pass in inet proto icmp from any to any icmp-type timest +pass in inet proto icmp from any to any icmp-type timestrep +pass in inet proto icmp from any to any icmp-type timex +pass in inet proto icmp from any to any icmp-type 254 +pass in inet proto icmp from any to any icmp-type 253 code 254 +pass in inet proto icmp from any to any icmp-type unreach code 15 +pass in inet proto icmp from any to any icmp-type unreach code 13 +pass in inet proto icmp from any to any icmp-type unreach code 8 +pass in inet proto icmp from any to any icmp-type unreach code 4 +pass in inet proto icmp from any to any icmp-type unreach code 9 +pass in inet proto icmp from any to any icmp-type unreach code 11 +pass in inet proto icmp from any to any icmp-type unreach code 14 +pass in inet proto icmp from any to any icmp-type unreach code 10 +pass in inet proto icmp from any to any icmp-type unreach code 12 +pass in inet proto icmp from any to any icmp-type unreach code 7 +pass in inet proto icmp from any to any icmp-type unreach code 1 +pass in inet proto icmp from any to any icmp-type unreach code 6 +pass in inet proto icmp from any to any icmp-type unreach code 0 +pass in inet proto icmp from any to any icmp-type unreach code 3 +pass in inet proto icmp from any to any icmp-type unreach code 2 +pass in inet proto icmp from any to any icmp-type unreach code 5 +pass in inet proto icmp from any to any icmp-type echo +pass in inet proto icmp from any to any icmp-type echorep +pass in inet proto icmp from any to any icmp-type inforeq +pass in inet proto icmp from any to any icmp-type inforep +pass in inet proto icmp from any to any icmp-type maskrep +pass in inet proto icmp from any to any icmp-type maskreq +pass in inet proto icmp from any to any icmp-type paramprob +pass in inet proto icmp from any to any icmp-type redir +pass in inet proto icmp from any to any icmp-type unreach +pass in inet proto icmp from any to any icmp-type routerad +pass in inet proto icmp from any to any icmp-type routersol +pass in inet proto icmp from any to any icmp-type squench +pass in inet proto icmp from any to any icmp-type timest +pass in inet proto icmp from any to any icmp-type timestrep +pass in inet proto icmp from any to any icmp-type timex diff --git a/test/expected/i9 b/test/expected/i9 index b128f99d57ac4..deecd17d3a1d9 100644 --- a/test/expected/i9 +++ b/test/expected/i9 @@ -1,9 +1,9 @@ -pass in from 127.0.0.1/32 to 127.0.0.1/32 with short,frag +pass in inet from 127.0.0.1/32 to 127.0.0.1/32 with short,frag block in from any to any with ipopts -pass in from any to any with opt nop,rr,zsu -pass in from any to any with opt nop,rr,zsu not opt lsrr,ssrr -pass in from 127.0.0.1/32 to 127.0.0.1/32 with not frag -pass in from 127.0.0.1/32 to 127.0.0.1/32 with frag,frag-body +pass in inet from any to any with opt nop,rr,zsu +pass in inet from any to any with opt nop,rr,zsu not opt lsrr,ssrr +pass in inet from 127.0.0.1/32 to 127.0.0.1/32 with not frag +pass in inet from 127.0.0.1/32 to 127.0.0.1/32 with frag,frag-body pass in proto tcp from any to any flags S/FSRPAU with not oow keep state # count 0 block in proto tcp from any to any with oow pass in proto tcp from any to any flags S/FSRPAU with not bad,bad-src,bad-nat @@ -14,4 +14,4 @@ pass in quick from any to any with not frag-body block in quick from any to any with not lowttl pass in from any to any with not ipopts,mbcast,not bcast,mcast,not state block in from any to any with not mbcast,bcast,not mcast,state -pass in from any to any with opt mtup,mtur,encode,ts,tr,sec,e-sec,cipso,satid,ssrr,addext,visa,imitd,eip,finn,dps,sdb,nsapa,rtralrt,ump +pass in inet from any to any with opt mtup,mtur,encode,ts,tr,sec,e-sec,cipso,satid,ssrr,addext,visa,imitd,eip,finn,dps,sdb,nsapa,rtralrt,ump diff --git a/test/expected/in1 b/test/expected/in1 index 03436b65a4dd9..2f1cf31df00af 100644 --- a/test/expected/in1 +++ b/test/expected/in1 @@ -1,31 +1,31 @@ -map le0 0.0.0.0/0 -> 0.0.0.0/32 +map le0 0/0 -> 0/32 map le0 0.0.0.1/32 -> 0.0.0.1/32 -map le0 128.0.0.0/1 -> 0.0.0.0/0 +map le0 128.0.0.0/1 -> 0/0 map le0 10.0.0.0/8 -> 1.2.3.0/24 map le0 10.0.0.0/8 -> 1.2.3.0/24 map le0 10.0.0.0/8 -> 1.2.3.0/24 map le0 0.0.0.5/0.0.0.255 -> 1.2.3.0/24 map le0 192.168.0.0/16 -> range 203.1.1.23-203.1.3.45 -map ppp0 192.168.0.0/16 -> 0.0.0.0/32 portmap tcp 10000:19999 -map ppp0 192.168.0.0/16 -> 0.0.0.0/32 portmap udp 20000:29999 -map ppp0 192.168.0.0/16 -> 0.0.0.0/32 portmap tcp/udp 30000:39999 -map ppp0 192.168.0.0/16 -> 0.0.0.0/32 portmap tcp auto -map ppp0 192.168.0.0/16 -> 0.0.0.0/32 portmap udp auto -map ppp0 192.168.0.0/16 -> 0.0.0.0/32 portmap tcp/udp auto -map ppp0 192.168.0.0/16 -> 0.0.0.0/32 proxy port 21 ftp/tcp -map ppp0 192.168.0.0/16 -> 0.0.0.0/32 proxy port 1010 ftp/tcp -map le0 0.0.0.0/0 -> 0.0.0.0/32 frag +map ppp0 192.168.0.0/16 -> 0/32 portmap tcp 10000:19999 +map ppp0 192.168.0.0/16 -> 0/32 portmap udp 20000:29999 +map ppp0 192.168.0.0/16 -> 0/32 portmap tcp/udp 30000:39999 +map ppp0 192.168.0.0/16 -> 0/32 portmap tcp auto +map ppp0 192.168.0.0/16 -> 0/32 portmap udp auto +map ppp0 192.168.0.0/16 -> 0/32 portmap tcp/udp auto +map ppp0 192.168.0.0/16 -> 0/32 proxy port 21 ftp/tcp +map ppp0 192.168.0.0/16 -> 0/32 proxy port 1010 ftp/tcp +map le0 0/0 -> 0/32 frag map le0 192.168.0.0/16 -> range 203.1.1.23-203.1.3.45 frag -map ppp0 192.168.0.0/16 -> 0.0.0.0/32 portmap tcp 10000:19999 frag -map ppp0 192.168.0.0/16 -> 0.0.0.0/32 proxy port 21 ftp/tcp frag -map le0 0.0.0.0/0 -> 0.0.0.0/32 age 10/10 +map ppp0 192.168.0.0/16 -> 0/32 portmap tcp 10000:19999 frag +map ppp0 192.168.0.0/16 -> 0/32 proxy port 21 ftp/tcp frag +map le0 0/0 -> 0/32 age 10/10 map le0 192.168.0.0/16 -> range 203.1.1.23-203.1.3.45 age 10/20 -map ppp0 192.168.0.0/16 -> 0.0.0.0/32 portmap tcp 10000:19999 age 30/30 -map le0 0.0.0.0/0 -> 0.0.0.0/32 frag age 10/10 +map ppp0 192.168.0.0/16 -> 0/32 portmap tcp 10000:19999 age 30/30 +map le0 0/0 -> 0/32 frag age 10/10 map le0 192.168.0.0/16 -> range 203.1.1.23-203.1.3.45 frag age 10/20 -map ppp0 192.168.0.0/16 -> 0.0.0.0/32 portmap tcp 10000:19999 frag age 30/30 -map fxp0 from 192.168.0.0/18 to any port = 21 -> 1.2.3.4/32 proxy port 21 ftp/tcp -map thisisalonginte 0.0.0.0/0 -> 0.0.0.0/32 mssclamp 1452 tag freddyliveshere -map bar0 0.0.0.0/0 -> 0.0.0.0/32 icmpidmap icmp 1000:2000 -map ppp0,adsl0 0.0.0.0/0 -> 0.0.0.0/32 -map ppp0 from 192.168.0.0/16 to any port = 123 -> 0.0.0.0/32 age 30/1 udp +map ppp0 192.168.0.0/16 -> 0/32 portmap tcp 10000:19999 frag age 30/30 +map fxp0 from 192.168.0.0/18 to 0/0 port = 21 -> 1.2.3.4/32 proxy port 21 ftp/tcp +map thisisalonginte 0/0 -> 0/32 mssclamp 1452 tag freddyliveshere +map bar0 0/0 -> 0/32 icmpidmap icmp 1000:2000 +map ppp0,adsl0 0/0 -> 0/32 +map ppp0 from 192.168.0.0/16 to 0/0 port = 123 -> 0/32 age 30/1 udp diff --git a/test/expected/in100 b/test/expected/in100 new file mode 100644 index 0000000000000..dcf3097544105 --- /dev/null +++ b/test/expected/in100 @@ -0,0 +1,3 @@ +rewrite in on bge0 from 1.1.1.1/32 to 2.2.2.2/32 -> src 3.3.3.3/32 dst 4.4.4.4/32; +rewrite out on bge0 from 1.1.1.1/32 to 2.2.2.2/32 -> src 3.3.3.0/24 dst 4.4.4.4/32; +rewrite in on bge0 from 1.1.1.1/32 to 2.2.2.2/32 -> src 3.3.3.0/24 dst 4.4.4.0/24; diff --git a/test/expected/in101 b/test/expected/in101 new file mode 100644 index 0000000000000..04e234c2f164c --- /dev/null +++ b/test/expected/in101 @@ -0,0 +1,4 @@ +rewrite in on bge0 proto icmp from 1.1.1.1/32 to 2.2.2.2/32 -> src 3.3.3.3/32 dst 4.4.4.4/32; +rewrite in on bge0 proto udp from 1.1.1.1/32 to 2.2.2.2/32 -> src 3.3.3.3/32 dst 4.4.4.4/32; +rewrite out on bge0 proto tcp from 1.1.1.1/32 to 2.2.2.2/32 -> src 3.3.3.0/24 dst 4.4.4.4/32; +rewrite in on bge0 proto tcp/udp from 1.1.1.1/32 to 2.2.2.2/32 -> src 3.3.3.0/24,20202 dst 4.4.4.0/24,10101; diff --git a/test/expected/in102 b/test/expected/in102 new file mode 100644 index 0000000000000..0a1b612d2f734 --- /dev/null +++ b/test/expected/in102 @@ -0,0 +1,5 @@ +rewrite in on bge0 proto tcp from 0/0 to 0/0 -> src 0/0 dst dstlist/a; +rewrite in on bge0 proto tcp from 1.1.1.1/32 to 0/0 -> src 0/0 dst dstlist/bee; +rewrite in on bge0 proto tcp from 1.1.1.1/32 to 2.2.2.2/32 -> src 0/0 dst dstlist/cat; +rewrite in on bge0 proto tcp from pool/a to 2.2.2.2/32 -> src 0/0 dst dstlist/bat; +rewrite in on bge0 proto tcp from pool/a to pool/1 -> src 0/0 dst dstlist/ant; diff --git a/test/expected/in2 b/test/expected/in2 index f1239b122137a..dc8f4ac5ba2d4 100644 --- a/test/expected/in2 +++ b/test/expected/in2 @@ -1,71 +1,71 @@ -rdr le0 9.8.7.6/32 port 0 -> 1.1.1.1 port 0 tcp -rdr le0 9.8.7.6/32 -> 1.1.1.1 255 -rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp -rdr le0 9.8.7.6/32 -> 1.1.1.1 ip -rdr le0 9.0.0.0/8 -> 1.1.1.1 ip -rdr le0 9.8.0.0/16 -> 1.1.1.1 ip -rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp -rdr le0 9.8.7.6/32 port 80 -> 0.0.0.0/0 port 80 tcp -rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 udp -rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp/udp -rdr le0 9.8.7.6/32 -> 1.1.1.1 icmp +rdr le0 9.8.7.6/32 port 0 -> 1.1.1.1/32 port 0 tcp +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 255 +rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1/32 port 80 tcp +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 ip +rdr le0 9.0.0.0/8 -> 1.1.1.1/32 ip +rdr le0 9.8.0.0/16 -> 1.1.1.1/32 ip +rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1/32 port 80 tcp +rdr le0 9.8.7.6/32 port 80 -> 0/0 port 80 tcp +rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1/32 port 80 udp +rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1/32 port 80 tcp/udp +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 icmp rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp -rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin +rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1/32 port 80 tcp round-robin rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin -rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag -rdr le0 9.8.7.6/32 -> 1.1.1.1 icmp frag +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 ip frag +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 icmp frag rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp/udp frag -rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin frag +rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1/32 port 80 tcp round-robin frag rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag -rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag age 10/10 -rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag age 10/20 -rdr le0 9.8.7.6/32 -> 1.1.1.1 icmp frag age 10/10 +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 ip frag age 10/10 +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 ip frag age 10/20 +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 icmp frag age 10/10 rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag age 20/20 -rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin frag age 30/30 +rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1/32 port 80 tcp round-robin frag age 30/30 rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag age 40/40 -rdr le0 9.8.7.6/32 -> 1.1.1.1 ip -rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag -rdr le0 9.8.7.6/32 -> 1.1.1.1 icmp frag +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 ip +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 ip frag +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 icmp frag rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag sticky -rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin frag sticky +rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1/32 port 80 tcp round-robin frag sticky rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag sticky -rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag age 10/10 -rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag age 10/20 -rdr le0 9.8.7.6/32 -> 1.1.1.1 icmp frag age 10/10 +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 ip frag age 10/10 +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 ip frag age 10/20 +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 icmp frag age 10/10 rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag age 20/20 sticky -rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin frag age 30/30 sticky +rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1/32 port 80 tcp round-robin frag age 30/30 sticky rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag age 40/40 sticky -rdr le0 9.8.7.6/32 -> 1.1.1.1 ip mssclamp 1000 -rdr le0 9.8.7.6/32 -> 1.1.1.1 ip mssclamp 1000 -rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag mssclamp 1000 -rdr le0 9.8.7.6/32 -> 1.1.1.1 icmp frag mssclamp 1000 +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 ip mssclamp 1000 +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 ip mssclamp 1000 +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 ip frag mssclamp 1000 +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 icmp frag mssclamp 1000 rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag sticky mssclamp 1000 -rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin frag sticky mssclamp 1000 +rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1/32 port 80 tcp round-robin frag sticky mssclamp 1000 rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag sticky mssclamp 1000 -rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag age 10/10 mssclamp 1000 -rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag age 10/20 mssclamp 1000 -rdr le0 9.8.7.6/32 -> 1.1.1.1 icmp frag age 10/10 mssclamp 1000 +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 ip frag age 10/10 mssclamp 1000 +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 ip frag age 10/20 mssclamp 1000 +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 icmp frag age 10/10 mssclamp 1000 rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag age 20/20 sticky mssclamp 1000 -rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin frag age 30/30 sticky mssclamp 1000 +rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1/32 port 80 tcp round-robin frag age 30/30 sticky mssclamp 1000 rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag age 40/40 sticky mssclamp 1000 -rdr le0 9.8.7.6/32 -> 1.1.1.1 ip tag nattagcacheline -rdr le0 9.8.7.6/32 -> 1.1.1.1 ip mssclamp 1000 tag nattagcacheline -rdr le0 9.8.7.6/32 -> 1.1.1.1 ip mssclamp 1000 tag nattagcacheline -rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag mssclamp 1000 tag nattagcacheline -rdr le0 9.8.7.6/32 -> 1.1.1.1 icmp frag mssclamp 1000 tag nattagcacheline +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 ip tag nattagcacheline +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 ip mssclamp 1000 tag nattagcacheline +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 ip mssclamp 1000 tag nattagcacheline +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 ip frag mssclamp 1000 tag nattagcacheline +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 icmp frag mssclamp 1000 tag nattagcacheline rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag sticky mssclamp 1000 tag nattagcacheline -rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin frag sticky mssclamp 1000 tag nattagcacheline +rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1/32 port 80 tcp round-robin frag sticky mssclamp 1000 tag nattagcacheline rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag sticky mssclamp 1000 tag nattagcacheline -rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag age 10/10 mssclamp 1000 tag nattagcacheline -rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag age 10/20 mssclamp 1000 tag nattagcacheline -rdr le0 9.8.7.6/32 -> 1.1.1.1 icmp frag age 10/10 mssclamp 1000 tag nattagcacheline +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 ip frag age 10/10 mssclamp 1000 tag nattagcacheline +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 ip frag age 10/20 mssclamp 1000 tag nattagcacheline +rdr le0 9.8.7.6/32 -> 1.1.1.1/32 icmp frag age 10/10 mssclamp 1000 tag nattagcacheline rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag age 20/20 sticky mssclamp 1000 tag nattagcacheline -rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin frag age 30/30 sticky mssclamp 1000 tag nattagcacheline +rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1/32 port 80 tcp round-robin frag age 30/30 sticky mssclamp 1000 tag nattagcacheline rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag age 40/40 sticky mssclamp 1000 tag nattagcacheline -rdr ge0 9.8.7.6/32 port 21 -> 1.1.1.1 port 21 tcp proxy ftp -rdr ge0 9.8.7.6/32 port 21 -> 1.1.1.1 port 21 tcp proxy ftp -rdr le0 9.8.7.6/32 port 1000-2000 -> 1.1.1.1 port 5555 tcp -rdr le0 9.8.7.6/32 port 1000-2000 -> 1.1.1.1 port = 5555 tcp -rdr le0 0.0.0.0/0 -> 254.220.186.152 ip -rdr le0 0.0.0.0/0 -> 254.220.186.152,254.220.186.152 ip -rdr adsl0,ppp0 0.0.0.0/0 port 25 -> 127.0.0.1 port 25 tcp +rdr ge0 9.8.7.6/32 port 21 -> 1.1.1.1/32 port 21 tcp proxy ftp +rdr ge0 9.8.7.6/32 port 21 -> 1.1.1.1/32 port 21 tcp proxy ftp +rdr le0 9.8.7.6/32 port 1000-2000 -> 1.1.1.1/32 port 5555 tcp +rdr le0 9.8.7.6/32 port 1000-2000 -> 1.1.1.1/32 port = 5555 tcp +rdr le0 0/0 -> 254.220.186.152/32 ip +rdr le0 0/0 -> 254.220.186.152,254.220.186.152 ip +rdr adsl0,ppp0 9.8.7.6/32 port 1000-2000 -> 1.1.1.1/32 port 5555-7777 tcp diff --git a/test/expected/in3 b/test/expected/in3 index b8a85bf9f3800..dac97c7d9cc18 100644 --- a/test/expected/in3 +++ b/test/expected/in3 @@ -1,5 +1,5 @@ -bimap le0 0.0.0.0/0 -> 0.0.0.0/32 +bimap le0 0/0 -> 0/32 bimap le0 0.0.0.1/32 -> 0.0.0.1/32 -bimap le0 128.0.0.0/1 -> 0.0.0.0/0 +bimap le0 128.0.0.0/1 -> 0/0 bimap le0 10.0.0.0/8 -> 1.2.3.0/24 bimap le0 10.0.5.0/24 -> 1.2.3.0/24 diff --git a/test/expected/in5 b/test/expected/in5 index e77de714a90d0..b7c6ef5d4125c 100644 --- a/test/expected/in5 +++ b/test/expected/in5 @@ -1,24 +1,24 @@ -map le0 from 9.8.7.6/32 port > 1024 to any -> 1.1.1.1/32 portmap tcp 10000:20000 +map le0 from 9.8.7.6/32 port > 1024 to 0/0 -> 1.1.1.1/32 portmap tcp 10000:20000 map le0 from 9.8.7.6/32 port > 1024 ! to 1.2.3.4/32 -> 1.1.1.1/32 portmap tcp 10000:20000 -rdr le0 from any to 9.8.7.6/32 port = 0 -> 1.1.1.1 port 0 tcp -rdr le0 from any to 9.8.7.6/32 -> 1.1.1.1 ip -rdr le0 ! from 1.2.3.4/32 to 9.8.7.6/32 port = 8888 -> 1.1.1.1 port 888 tcp -rdr le0 from any to 9.8.7.6/32 -> 1.1.1.1 ip -rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1 port 888 tcp -rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1 port 888 udp -rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1 port 888 tcp/udp -rdr le0 from any to 9.8.7.6/32 -> 1.1.1.1 icmp -rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1,1.1.1.2 port 888 tcp -rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1 port 888 tcp round-robin -rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1,1.1.1.2 port 888 tcp round-robin -rdr le0 from any to 9.8.7.6/32 -> 1.1.1.1 ip frag -rdr le0 from any to 9.8.7.6/32 -> 1.1.1.1 icmp frag -rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1,1.1.1.2 port 888 tcp frag -rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1 port 888 tcp round-robin frag -rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1,1.1.1.2 port 888 tcp round-robin frag -rdr le0 from any to 9.8.7.6/32 -> 1.1.1.1 ip frag age 10/10 -rdr le0 from any to 9.8.7.6/32 -> 1.1.1.1 ip frag age 10/20 -rdr le0 from any to 9.8.7.6/32 -> 1.1.1.1 icmp frag age 10/10 -rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1,1.1.1.2 port 888 tcp frag age 20/20 -rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1 port 888 tcp round-robin frag age 30/30 -rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1,1.1.1.2 port 888 tcp round-robin frag age 40/40 +rdr le0 from 0/0 to 9.8.7.6/32 port = 0 -> 1.1.1.1/32 port 0 tcp +rdr le0 from 0/0 to 9.8.7.6/32 -> 1.1.1.1/32 ip +rdr le0 ! from 1.2.3.4/32 to 9.8.7.6/32 port = 8888 -> 1.1.1.1/32 port 888 tcp +rdr le0 from 0/0 to 9.8.7.6/32 -> 1.1.1.1/32 ip +rdr le0 from 0/0 to 9.8.7.6/32 port = 8888 -> 1.1.1.1/32 port 888 tcp +rdr le0 from 0/0 to 9.8.7.6/32 port = 8888 -> 1.1.1.1/32 port 888 udp +rdr le0 from 0/0 to 9.8.7.6/32 port = 8888 -> 1.1.1.1/32 port 888 tcp/udp +rdr le0 from 0/0 to 9.8.7.6/32 -> 1.1.1.1/32 icmp +rdr le0 from 0/0 to 9.8.7.6/32 port = 8888 -> 1.1.1.1,1.1.1.2 port 888 tcp +rdr le0 from 0/0 to 9.8.7.6/32 port = 8888 -> 1.1.1.1/32 port 888 tcp round-robin +rdr le0 from 0/0 to 9.8.7.6/32 port = 8888 -> 1.1.1.1,1.1.1.2 port 888 tcp round-robin +rdr le0 from 0/0 to 9.8.7.6/32 -> 1.1.1.1/32 ip frag +rdr le0 from 0/0 to 9.8.7.6/32 -> 1.1.1.1/32 icmp frag +rdr le0 from 0/0 to 9.8.7.6/32 port = 8888 -> 1.1.1.1,1.1.1.2 port 888 tcp frag +rdr le0 from 0/0 to 9.8.7.6/32 port = 8888 -> 1.1.1.1/32 port 888 tcp round-robin frag +rdr le0 from 0/0 to 9.8.7.6/32 port = 8888 -> 1.1.1.1,1.1.1.2 port 888 tcp round-robin frag +rdr le0 from 0/0 to 9.8.7.6/32 -> 1.1.1.1/32 ip frag age 10/10 +rdr le0 from 0/0 to 9.8.7.6/32 -> 1.1.1.1/32 ip frag age 10/20 +rdr le0 from 0/0 to 9.8.7.6/32 -> 1.1.1.1/32 icmp frag age 10/10 +rdr le0 from 0/0 to 9.8.7.6/32 port = 8888 -> 1.1.1.1,1.1.1.2 port 888 tcp frag age 20/20 +rdr le0 from 0/0 to 9.8.7.6/32 port = 8888 -> 1.1.1.1/32 port 888 tcp round-robin frag age 30/30 +rdr le0 from 0/0 to 9.8.7.6/32 port = 8888 -> 1.1.1.1,1.1.1.2 port 888 tcp round-robin frag age 40/40 diff --git a/test/expected/in6 b/test/expected/in6 index 05426e7a8dc22..fefc0522c7d8f 100644 --- a/test/expected/in6 +++ b/test/expected/in6 @@ -1,8 +1,8 @@ -map foo0 from any port = 1 to any port != 0 -> 0.0.0.0/32 udp -map foo0 from any port = 1 to any port != 0 -> 0.0.0.0/32 udp -map foo0 from any port < 1 to any port > 0 -> 0.0.0.0/32 tcp -map foo0 from any port < 1 to any port > 0 -> 0.0.0.0/32 tcp -map foo0 from any port <= 1 to any port >= 0 -> 0.0.0.0/32 tcp/udp -map foo0 from any port <= 1 to any port >= 0 -> 0.0.0.0/32 tcp/udp -map foo0 from any port 1 >< 20 to any port 20 <> 40 -> 0.0.0.0/32 tcp/udp -map foo0 from any port 10:20 to any port 30:40 -> 0.0.0.0/32 tcp/udp +map foo0 from 0/0 port = 1 to 0/0 port != 0 -> 0/32 udp +map foo0 from 0/0 port = 1 to 0/0 port != 0 -> 0/32 udp +map foo0 from 0/0 port < 1 to 0/0 port > 0 -> 0/32 tcp +map foo0 from 0/0 port < 1 to 0/0 port > 0 -> 0/32 tcp +map foo0 from 0/0 port <= 1 to 0/0 port >= 0 -> 0/32 tcp/udp +map foo0 from 0/0 port <= 1 to 0/0 port >= 0 -> 0/32 tcp/udp +map foo0 from 0/0 port 1 >< 20 to 0/0 port 20 <> 40 -> 0/32 tcp/udp +map foo0 from 0/0 port 10:20 to 0/0 port 30:40 -> 0/32 tcp/udp diff --git a/test/expected/in7 b/test/expected/in7 new file mode 100644 index 0000000000000..e69de29bb2d1d --- /dev/null +++ b/test/expected/in7 diff --git a/test/expected/ip1 b/test/expected/ip1 index b04fa9d1ad62b..cee7831938677 100644 --- a/test/expected/ip1 +++ b/test/expected/ip1 @@ -1,68 +1,68 @@ -table role = ipf type = tree number = 1 +table role=ipf type=tree number=1 {; }; -table role = ipf type = tree number = 100 - { 2.2.2.0/24; ! 2.2.0.0/16; 1.2.3.4/32; }; -table role = ipf type = tree number = 110 - { 2.2.2.0/24; ! 2.2.0.0/16; 1.2.3.4/32; }; -table role = ipf type = tree number = 120 - { 2.2.2.0/24; ! 2.2.0.0/16; 1.2.3.4/32; }; -table role = ipf type = tree number = 130 - { 2.2.2.0/24; ! 2.2.0.0/16; 1.2.3.4/32; }; -table role = ipf type = hash number = 2 size = 1 +table role=ipf type=tree number=100 + { 1.2.3.4/32; ! 2.2.0.0/16; 2.2.2.0/24; }; +table role=nat type=tree number=110 + { 1.2.3.4/32; ! 2.2.0.0/16; 2.2.2.0/24; }; +table role=auth type=tree number=120 + { 1.2.3.4/32; ! 2.2.0.0/16; 2.2.2.0/24; }; +table role=count type=tree number=130 + { 1.2.3.4/32; ! 2.2.0.0/16; 2.2.2.0/24; }; +table role=ipf type=hash number=2 size=1 {; }; -table role = ipf type = hash number = 200 size = 5 +table role=ipf type=hash number=200 size=5 { 0/0; 1/32; 1.2.3.4/32; }; -table role = nat type = hash number = 210 size = 5 +table role=nat type=hash number=210 size=5 { 0/0; 2/32; 1.2.3.4/32; }; -table role = auth type = hash number = 220 size = 5 +table role=auth type=hash number=220 size=5 { 0/0; 3/32; 1.2.3.4/32; }; -table role = count type = hash number = 230 size = 5 +table role=count type=hash number=230 size=5 { 0/0; 4/32; 1.2.3.4/32; }; -table role = ipf type = hash number = 240 size = 5 seed = 101 +table role=ipf type=hash number=240 size=5 seed=101 { 0/0; 1/32; 1.2.3.4/32; }; -table role = nat type = hash number = 250 size = 5 seed = 101 +table role=nat type=hash number=250 size=5 seed=101 { 0/0; 2/32; 1.2.3.4/32; }; -table role = auth type = hash number = 260 size = 5 seed = 101 +table role=auth type=hash number=260 size=5 seed=101 { 0/0; 3/32; 1.2.3.4/32; }; -table role = count type = hash number = 270 size = 5 seed = 101 +table role=count type=hash number=270 size=5 seed=101 { 0/0; 4/32; 1.2.3.4/32; }; -table role = ipf type = hash number = 2000 size = 1001 +table role=ipf type=hash number=2000 size=1001 { 0/0; 1/32; 1.2.3.4/32; }; -table role = nat type = hash number = 2000 size = 1001 +table role=nat type=hash number=2000 size=1001 { 0/0; 2/32; 1.2.3.4/32; }; -table role = auth type = hash number = 2000 size = 1001 +table role=auth type=hash number=2000 size=1001 { 0/0; 3/32; 1.2.3.4/32; }; -table role = count type = hash number = 2000 size = 1001 +table role=count type=hash number=2000 size=1001 { 0/0; 4/32; 1.2.3.4/32; }; -table role = ipf type = hash number = 100 size = 1001 seed = 101 +table role=ipf type=hash number=100 size=1001 seed=101 { 0/0; 1/32; 1.2.3.4/32; }; -table role = nat type = hash number = 100 size = 1001 seed = 101 +table role=nat type=hash number=100 size=1001 seed=101 { 0/0; 2/32; 1.2.3.4/32; }; -table role = auth type = hash number = 100 size = 1001 seed = 101 +table role=auth type=hash number=100 size=1001 seed=101 { 0/0; 3/32; 1.2.3.4/32; }; -table role = count type = hash number = 100 size = 1001 seed = 101 +table role=count type=hash number=100 size=1001 seed=101 { 0/0; 4/32; 1.2.3.4/32; }; -group-map in role = ipf number = 300 size = 5 - { 0/0, group = 303; 5/32, group = 303; 1.2.3.4/32, group = 303; }; -group-map in role = nat number = 300 size = 5 - { 0/0, group = 303; 6/32, group = 303; 1.2.3.4/32, group = 303; }; -group-map in role = auth number = 300 size = 5 - { 0/0, group = 303; 7/32, group = 303; 1.2.3.4/32, group = 303; }; -group-map in role = count number = 300 size = 5 - { 0/0, group = 303; 8/32, group = 303; 1.2.3.4/32, group = 303; }; -group-map out role = ipf number = 400 size = 5 - { 0/0, group = 303; 5/32, group = 303; 1.2.3.4/32, group = 606; }; -group-map out role = nat number = 400 size = 5 - { 0/0, group = 303; 6/32, group = 303; 1.2.3.4/32, group = 606; }; -group-map out role = auth number = 400 size = 5 - { 0/0, group = 303; 7/32, group = 303; 1.2.3.4/32, group = 606; }; -group-map out role = count number = 400 size = 5 - { 0/0, group = 303; 8/32, group = 303; 1.2.3.4/32, group = 606; }; -group-map in role = ipf number = 500 size = 5 - { 0/0, group = 10; 5/32, group = 800; 1.2.3.4/32, group = 606; }; -group-map in role = nat number = 500 size = 5 - { 0/0, group = 10; 6/32, group = 800; 1.2.3.4/32, group = 606; }; -group-map in role = auth number = 500 size = 5 - { 0/0, group = 10; 7/32, group = 800; 1.2.3.4/32, group = 606; }; -group-map in role = count number = 500 size = 5 - { 0/0, group = 10; 8/32, group = 800; 1.2.3.4/32, group = 606; }; +group-map in role=ipf number=300 size=5 + { 0/0, group=303; 5/32, group=303; 1.2.3.4/32, group=303; }; +group-map in role=nat number=300 size=5 + { 0/0, group=303; 6/32, group=303; 1.2.3.4/32, group=303; }; +group-map in role=auth number=300 size=5 + { 0/0, group=303; 7/32, group=303; 1.2.3.4/32, group=303; }; +group-map in role=count number=300 size=5 + { 0/0, group=303; 8/32, group=303; 1.2.3.4/32, group=303; }; +group-map out role=ipf number=400 size=5 + { 0/0, group=303; 5/32, group=303; 1.2.3.4/32, group=606; }; +group-map out role=nat number=400 size=5 + { 0/0, group=303; 6/32, group=303; 1.2.3.4/32, group=606; }; +group-map out role=auth number=400 size=5 + { 0/0, group=303; 7/32, group=303; 1.2.3.4/32, group=606; }; +group-map out role=count number=400 size=5 + { 0/0, group=303; 8/32, group=303; 1.2.3.4/32, group=606; }; +group-map in role=ipf number=500 size=5 + { 0/0, group=10; 5/32, group=800; 1.2.3.4/32, group=606; }; +group-map in role=nat number=500 size=5 + { 0/0, group=10; 6/32, group=800; 1.2.3.4/32, group=606; }; +group-map in role=auth number=500 size=5 + { 0/0, group=10; 7/32, group=800; 1.2.3.4/32, group=606; }; +group-map in role=count number=500 size=5 + { 0/0, group=10; 8/32, group=800; 1.2.3.4/32, group=606; }; diff --git a/test/expected/ip2 b/test/expected/ip2 index 9b0ed2babae6e..3de3c471fc922 100644 --- a/test/expected/ip2 +++ b/test/expected/ip2 @@ -1,2 +1,2 @@ -table role = ipf type = tree name = letters - { 2.2.2.0/24; ! 2.2.0.0/16; 1.1.1.1/32; }; +table role=ipf type=tree name=letters + { 1.1.1.1/32; ! 2.2.0.0/16; 2.2.2.0/24; }; diff --git a/test/expected/ip3 b/test/expected/ip3 new file mode 100644 index 0000000000000..48dd074a4c043 --- /dev/null +++ b/test/expected/ip3 @@ -0,0 +1,14 @@ +pool ipf/dstlist (name fred; policy round-robin;) + { 3.3.3.3; }; +pool ipf/dstlist (name jack; policy weighting connection;) + { 4.4.4.4; bge0:5.5.5.5; }; +pool ipf/dstlist (name jill; policy random;) + { 1.1.1.1; bge0:2.2.2.2; }; +table role=nat type=hash name=noproxy size=3 + { 1.1.1.1/32; 2.2.2.2/32; }; +table role=nat type=tree name=raw + { 1.1.1.1/32; 2.2.2.2/32; }; +pool all/dstlist (name jill; policy random;) + { 1.1.1.1; bge0:2.2.2.2; }; +table role=all type=hash name=noproxy size=3 + { 1.1.1.1/32; 2.2.2.2/32; }; diff --git a/test/expected/12 b/test/expected/ipv6.4 index f94cf768273a3..e3ae842a7474c 100644 --- a/test/expected/12 +++ b/test/expected/ipv6.4 @@ -1,17 +1,9 @@ pass pass -pass -nomatch -nomatch -nomatch nomatch nomatch -nomatch -pass pass pass -pass -nomatch nomatch nomatch nomatch @@ -19,17 +11,18 @@ nomatch nomatch nomatch nomatch -block -block -nomatch -nomatch nomatch nomatch nomatch -nomatch -block -block -block +-------- +pass +pass +pass +pass +pass +pass +pass +pass nomatch nomatch nomatch @@ -38,17 +31,21 @@ nomatch nomatch nomatch nomatch +-------- nomatch nomatch -pass nomatch -pass nomatch nomatch nomatch nomatch nomatch +pass +pass +block nomatch nomatch nomatch -block +pass +pass +-------- diff --git a/test/expected/ipv6.6 b/test/expected/ipv6.6 index abc0e87c6917f..efd04212578c5 100644 --- a/test/expected/ipv6.6 +++ b/test/expected/ipv6.6 @@ -1,3 +1,10 @@ pass pass +pass +pass +-------- +nomatch +nomatch +block +nomatch -------- diff --git a/test/expected/l1 b/test/expected/l1 index ba0de69b92398..e4a081d8e825c 100644 --- a/test/expected/l1 +++ b/test/expected/l1 @@ -1,11 +1,13 @@ log in all +missed 1 ipf log entries: 0 1 01/01/1970 00:00:00.000000 anon0 @-1:-1 L 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -S IN 01/01/1970 00:00:00.000000 anon0 @-1:-1 L 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -A IN 01/01/1970 00:00:00.000000 anon0 @-1:-1 L 2.2.2.2,25 -> 1.1.1.1,1025 PR tcp len 20 40 -AS IN 01/01/1970 00:00:00.000000 anon0 @-1:-1 L 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -AF IN 01/01/1970 00:00:00.000000 2x anon0 @-1:-1 L 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -A IN 01/01/1970 00:00:00.000000 anon0 @-1:-1 L 1.1.1.1,1 -> 4.4.4.4,53 PR udp len 20 40 IN -01/01/1970 00:00:00.000000 2x anon0 @-1:-1 L 2.2.2.2,1 -> 4.4.4.4,53 PR udp len 20 40 IN +01/01/1970 00:00:00.000000 anon0 @-1:-1 L 2.2.2.2,1 -> 4.4.4.4,53 PR udp len 20 40 IN +01/01/1970 00:00:00.000000 anon0 @-1:-1 L 2.2.2.2,1 -> 4.4.4.4,53 PR udp len 20 56 IN 01/01/1970 00:00:00.000000 anon0 @-1:-1 L 2.2.2.2 -> 4.4.4.4 PR ip len 20 (20) IN 01/01/1970 00:00:00.000000 anon0 @-1:-1 L 3.3.3.3,1023 -> 1.1.1.1,2049 PR udp len 20 28 IN 01/01/1970 00:00:00.000000 anon0 @-1:-1 L 1.1.1.1,2049 -> 3.3.3.3,1023 PR udp len 20 28 IN @@ -15,11 +17,14 @@ pass in on anon0 all head 100 pass in log quick from 3.3.3.3 to any group 100 -------- pass in log body quick from 2.2.2.2 to any +missed 1 ipf log entries: 0 1 01/01/1970 00:00:00.000000 anon0 @0:1 p 2.2.2.2,25 -> 1.1.1.1,1025 PR tcp len 20 40 -AS IN -01/01/1970 00:00:00.000000 2x anon0 @0:1 p 2.2.2.2,1 -> 4.4.4.4,53 PR udp len 20 40 IN +01/01/1970 00:00:00.000000 anon0 @0:1 p 2.2.2.2,1 -> 4.4.4.4,53 PR udp len 20 40 IN +01/01/1970 00:00:00.000000 anon0 @0:1 p 2.2.2.2,1 -> 4.4.4.4,53 PR udp len 20 56 IN 01/01/1970 00:00:00.000000 anon0 @0:1 p 2.2.2.2 -> 4.4.4.4 PR ip len 20 (20) IN -------- pass in log quick proto tcp from 1.1.1.1 to any flags S keep state +missed 1 ipf log entries: 0 1 01/01/1970 00:00:00.000000 anon0 @0:1 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -S K-S IN 01/01/1970 00:00:00.000000 anon0 @0:1 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -A K-S IN 01/01/1970 00:00:00.000000 anon0 @0:1 p 2.2.2.2,25 -> 1.1.1.1,1025 PR tcp len 20 40 -AS K-S IN @@ -27,8 +32,10 @@ pass in log quick proto tcp from 1.1.1.1 to any flags S keep state 01/01/1970 00:00:00.000000 anon0 @0:1 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -AF K-S IN -------- pass in log first quick proto tcp from 1.1.1.1 to any flags S keep state +missed 1 ipf log entries: 0 1 01/01/1970 00:00:00.000000 anon0 @0:1 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -S K-S IN -------- +missed 1 ipf log entries: 0 1 01/01/1970 00:00:00.000000 anon0 @-1:-1 L 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -S IN 01/01/1970 00:00:00.000000 anon0 @0:4 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -S K-S IN 01/01/1970 00:00:00.000000 anon0 @0:4 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -A K-S IN diff --git a/test/expected/l1.b b/test/expected/l1.b index c060086d8df4d..e06e486fcf3a6 100644 --- a/test/expected/l1.b +++ b/test/expected/l1.b @@ -1,29 +1,38 @@ +missed 1 ipf log entries: 0 1 01/01/1970 00:00:00.000000 anon0 @-1:-1 L 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -S IN 01/01/1970 00:00:00.000000 anon0 @-1:-1 L 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -A IN 01/01/1970 00:00:00.000000 anon0 @-1:-1 L 2.2.2.2,25 -> 1.1.1.1,1025 PR tcp len 20 40 -AS IN 01/01/1970 00:00:00.000000 anon0 @-1:-1 L 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -AF IN 01/01/1970 00:00:00.000000 2x anon0 @-1:-1 L 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -A IN 01/01/1970 00:00:00.000000 anon0 @-1:-1 L 1.1.1.1,1 -> 4.4.4.4,53 PR udp len 20 40 IN -01/01/1970 00:00:00.000000 2x anon0 @-1:-1 L 2.2.2.2,1 -> 4.4.4.4,53 PR udp len 20 40 IN +01/01/1970 00:00:00.000000 anon0 @-1:-1 L 2.2.2.2,1 -> 4.4.4.4,53 PR udp len 20 40 IN +01/01/1970 00:00:00.000000 anon0 @-1:-1 L 2.2.2.2,1 -> 4.4.4.4,53 PR udp len 20 56 IN 01/01/1970 00:00:00.000000 anon0 @-1:-1 L 2.2.2.2 -> 4.4.4.4 PR ip len 20 (20) IN 01/01/1970 00:00:00.000000 anon0 @-1:-1 L 3.3.3.3,1023 -> 1.1.1.1,2049 PR udp len 20 28 IN 01/01/1970 00:00:00.000000 anon0 @-1:-1 L 1.1.1.1,2049 -> 3.3.3.3,1023 PR udp len 20 28 IN -------- -------- -------- +missed 1 ipf log entries: 0 1 01/01/1970 00:00:00.000000 anon0 @0:1 p 2.2.2.2,25 -> 1.1.1.1,1025 PR tcp len 20 40 -AS IN -01/01/1970 00:00:00.000000 2x anon0 @0:1 p 2.2.2.2,1 -> 4.4.4.4,53 PR udp len 20 40 IN +01/01/1970 00:00:00.000000 anon0 @0:1 p 2.2.2.2,1 -> 4.4.4.4,53 PR udp len 20 40 IN 01 02 03 04 05 06 07 08 09 0a 0b 0d ............ +01/01/1970 00:00:00.000000 anon0 @0:1 p 2.2.2.2,1 -> 4.4.4.4,53 PR udp len 20 56 IN +01 02 03 04 05 06 07 08 09 0a 0b 0d 0e 0f 40 61 ..............@a +42 63 44 65 46 67 48 69 4a 6b 4c 6d BcDeFgHiJkLm 01/01/1970 00:00:00.000000 anon0 @0:1 p 2.2.2.2 -> 4.4.4.4 PR ip len 20 (20) IN -------- +missed 1 ipf log entries: 0 1 01/01/1970 00:00:00.000000 anon0 @0:1 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -S K-S IN 01/01/1970 00:00:00.000000 anon0 @0:1 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -A K-S IN 01/01/1970 00:00:00.000000 anon0 @0:1 p 2.2.2.2,25 -> 1.1.1.1,1025 PR tcp len 20 40 -AS K-S IN 01/01/1970 00:00:00.000000 e1 @0:1 p 2.2.2.2,25 -> 1.1.1.1,1025 PR tcp len 20 40 -A K-S OUT 01/01/1970 00:00:00.000000 anon0 @0:1 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -AF K-S IN -------- +missed 1 ipf log entries: 0 1 01/01/1970 00:00:00.000000 anon0 @0:1 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -S K-S IN -------- +missed 1 ipf log entries: 0 1 01/01/1970 00:00:00.000000 anon0 @-1:-1 L 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -S IN 01/01/1970 00:00:00.000000 anon0 @0:4 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -S K-S IN 01/01/1970 00:00:00.000000 anon0 @0:4 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -A K-S IN diff --git a/test/expected/n1 b/test/expected/n1 index 537f9bb655038..20eaedc8ea894 100644 --- a/test/expected/n1 +++ b/test/expected/n1 @@ -1,105 +1,197 @@ -ip #0 20(20) 255 10.1.1.0 > 10.1.1.2 -ip #0 20(20) 255 10.2.2.2 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 -ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.1.1.2,1026 > 10.1.1.1,1025 -ip #0 20(20) 255 10.2.2.1 > 10.1.2.1 -ip #0 20(20) 255 10.2.2.2 > 10.1.2.1 -ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 -ip #0 20(20) 255 10.2.2.1 > 10.2.1.1 -ip #0 20(20) 255 10.2.2.2 > 10.2.1.1 -ip #0 20(20) 255 10.2.2.3 > 10.1.1.1 -ip #0 20(20) 255 10.2.3.4 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.1 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 -ip #0 20(20) 255 10.1.1.0 > 10.3.4.5 -ip #0 20(20) 255 10.1.1.1 > 10.3.4.5 -ip #0 20(20) 255 10.1.1.2 > 10.3.4.5 -ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,1025 -ip #0 48(20) 1 10.2.2.2 > 10.4.3.2 -ip #0 48(20) 1 10.4.3.2 > 10.1.1.1 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.1 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.2 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.3 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.4 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.5 -ip #0 20(20) 34 10.1.1.2 > 10.4.3.2 -ip #0 20(20) 34 10.4.3.2 > 10.3.4.4 -ip #0 20(20) 34 10.1.1.2 > 10.4.3.4 -ip #0 20(20) 34 10.4.3.4 > 10.3.4.5 -ip #0 20(20) 34 10.1.1.3 > 10.4.3.4 -ip #0 20(20) 34 10.4.3.4 > 10.3.4.6 -ip #0 20(20) 35 10.1.1.3 > 10.4.3.4 -ip #0 20(20) 35 10.4.3.4 > 10.3.4.7 +> zx0 ip #0 20(20) 255 10.1.1.0 > 10.1.1.2 +> zx0 ip #0 20(20) 255 10.2.2.2 > 10.1.1.2 +> zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 +> zx0 ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.1.1.2,1026 > 10.1.1.1,1025 +> zx0 ip #0 20(20) 255 10.2.2.1 > 10.1.2.1 +> zx0 ip #0 20(20) 255 10.2.2.2 > 10.1.2.1 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.2.2.1 > 10.2.1.1 +< zx0 ip #0 20(20) 255 10.2.2.2 > 10.2.1.1 +< zx0 ip #0 20(20) 255 10.2.2.3 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.2.3.4 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.1.1.0 > 10.3.4.5 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.3.4.5 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.3.4.5 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,1025 +> zx0 ip #0 48(20) 1 10.2.2.2 > 10.4.3.2 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.1.1.1 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.1 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.2 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.3 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.4 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.5 +> zx0 ip #0 20(20) 34 10.1.1.2 > 10.4.3.2 +< zx0 ip #0 20(20) 34 10.4.3.2 > 10.3.4.4 +> zx0 ip #0 20(20) 34 10.1.1.2 > 10.4.3.4 +< zx0 ip #0 20(20) 34 10.4.3.4 > 10.3.4.5 +> zx0 ip #0 20(20) 34 10.1.1.3 > 10.4.3.4 +< zx0 ip #0 20(20) 34 10.4.3.4 > 10.3.4.6 +> zx0 ip #0 20(20) 35 10.1.1.3 > 10.4.3.4 +< zx0 ip #0 20(20) 35 10.4.3.4 > 10.3.4.7 +List of active MAP/Redirect filters: +map zx0 10.1.1.1/32 -> 10.2.2.2/32 + +List of active sessions: +MAP 10.1.1.1 <- -> 10.2.2.2 [10.4.3.2] +MAP 10.1.1.1 <- -> 10.2.2.2 [10.1.1.2] + +Hostmap table: +10.1.1.1,10.4.3.2 -> 10.2.2.2,0.0.0.0 (use = 1) +10.1.1.1,10.1.1.2 -> 10.2.2.2,0.0.0.0 (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- -ip #0 20(20) 255 10.3.4.5 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 -ip #0 20(20) 255 10.3.4.5 > 10.1.1.1 -ip #0 40(20) 6 10.3.4.5,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.3.4.5,1026 > 10.1.1.1,1025 -ip #0 20(20) 255 10.2.2.1 > 10.1.2.1 -ip #0 20(20) 255 10.2.2.2 > 10.1.2.1 -ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 -ip #0 20(20) 255 10.2.2.1 > 10.2.1.1 -ip #0 20(20) 255 10.2.2.2 > 10.2.1.1 -ip #0 20(20) 255 10.2.2.3 > 10.1.1.1 -ip #0 20(20) 255 10.2.3.4 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.1 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.2 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.0 > 10.3.4.5 -ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.0 -ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 -ip #0 48(20) 1 10.3.4.5 > 10.4.3.2 -ip #0 48(20) 1 10.4.3.2 > 10.2.2.2 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.1 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.2 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.3 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.4 -ip #0 48(20) 1 10.4.3.2 > 10.1.1.1 -ip #0 20(20) 34 10.3.4.5 > 10.4.3.2 -ip #0 20(20) 34 10.4.3.2 > 10.3.4.4 -ip #0 20(20) 34 10.3.4.5 > 10.4.3.4 -ip #0 20(20) 34 10.4.3.4 > 10.1.1.2 -ip #0 20(20) 34 10.1.1.3 > 10.4.3.4 -ip #0 20(20) 34 10.4.3.4 > 10.3.4.6 -ip #0 20(20) 35 10.3.4.5 > 10.4.3.4 -ip #0 20(20) 35 10.4.3.4 > 10.3.4.7 +> zx0 ip #0 20(20) 255 10.3.4.5 > 10.1.1.2 +15 +> zx0 ip #0 20(20) 255 10.3.4.5 > 10.1.1.1 +> zx0 ip #0 40(20) 6 10.3.4.5,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.3.4.5,1026 > 10.1.1.1,1025 +> zx0 ip #0 20(20) 255 10.2.2.1 > 10.1.2.1 +> zx0 ip #0 20(20) 255 10.2.2.2 > 10.1.2.1 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.2.2.1 > 10.2.1.1 +< zx0 ip #0 20(20) 255 10.2.2.2 > 10.2.1.1 +< zx0 ip #0 20(20) 255 10.2.2.3 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.2.3.4 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.0 > 10.3.4.5 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.0 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 +> zx0 ip #0 48(20) 1 10.3.4.5 > 10.4.3.2 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.2.2.2 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.1 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.2 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.3 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.4 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.1.1.1 +> zx0 ip #0 20(20) 34 10.3.4.5 > 10.4.3.2 +< zx0 ip #0 20(20) 34 10.4.3.2 > 10.3.4.4 +> zx0 ip #0 20(20) 34 10.3.4.5 > 10.4.3.4 +< zx0 ip #0 20(20) 34 10.4.3.4 > 10.1.1.2 +15 +< zx0 ip #0 20(20) 34 10.4.3.4 > 10.3.4.6 +> zx0 ip #0 20(20) 35 10.3.4.5 > 10.4.3.4 +< zx0 ip #0 20(20) 35 10.4.3.4 > 10.3.4.7 +List of active MAP/Redirect filters: +map zx0 10.1.1.0/24 -> 10.3.4.5/32 + +List of active sessions: +MAP 10.1.1.3 <- -> 10.3.4.5 [10.4.3.4] +MAP 10.1.1.2 <- -> 10.3.4.5 [10.4.3.4] +MAP 10.1.1.2 <- -> 10.3.4.5 [10.4.3.2] +MAP 10.1.1.1 <- -> 10.3.4.5 [10.4.3.2] +MAP 10.1.1.2 1026 <- -> 10.3.4.5 1026 [10.1.1.1 1025] +MAP 10.1.1.2 1025 <- -> 10.3.4.5 1025 [10.1.1.1 1025] +MAP 10.1.1.2 <- -> 10.3.4.5 [10.1.1.1] +MAP 10.1.1.0 <- -> 10.3.4.5 [10.1.1.2] + +Hostmap table: +10.1.1.3,10.4.3.4 -> 10.3.4.5,0.0.0.0 (use = 1) +10.1.1.2,10.4.3.4 -> 10.3.4.5,0.0.0.0 (use = 1) +10.1.1.2,10.4.3.2 -> 10.3.4.5,0.0.0.0 (use = 1) +10.1.1.1,10.4.3.2 -> 10.3.4.5,0.0.0.0 (use = 1) +10.1.1.2,10.1.1.1 -> 10.3.4.5,0.0.0.0 (use = 3) +10.1.1.0,10.1.1.2 -> 10.3.4.5,0.0.0.0 (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- -ip #0 20(20) 255 10.3.4.1 > 10.1.1.2 -ip #0 20(20) 255 10.3.4.2 > 10.1.1.2 -ip #0 20(20) 255 10.3.4.3 > 10.1.1.1 -ip #0 40(20) 6 10.3.4.3,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.3.4.3,1026 > 10.1.1.1,1025 -ip #0 20(20) 255 10.2.2.1 > 10.1.2.1 -ip #0 20(20) 255 10.2.2.2 > 10.1.2.1 -ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 -ip #0 20(20) 255 10.2.2.1 > 10.2.1.1 -ip #0 20(20) 255 10.2.2.2 > 10.2.1.1 -ip #0 20(20) 255 10.2.2.3 > 10.1.1.1 -ip #0 20(20) 255 10.2.3.4 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.1 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.2 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.0 > 10.3.4.5 -ip #0 20(20) 255 10.1.1.1 > 10.3.4.5 -ip #0 20(20) 255 10.1.1.2 > 10.3.4.5 -ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,1025 -ip #0 48(20) 1 10.3.4.3 > 10.4.3.2 -ip #0 48(20) 1 10.4.3.2 > 10.2.2.2 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.1 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.2 -ip #0 48(20) 1 10.4.3.2 > 10.1.1.1 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.4 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.5 -ip #0 20(20) 34 10.3.4.3 > 10.4.3.2 -ip #0 20(20) 34 10.4.3.2 > 10.3.4.4 -ip #0 20(20) 34 10.3.4.3 > 10.4.3.4 -ip #0 20(20) 34 10.4.3.4 > 10.3.4.5 -ip #0 20(20) 34 10.3.4.4 > 10.4.3.4 -ip #0 20(20) 34 10.4.3.4 > 10.3.4.6 -ip #0 20(20) 35 10.3.4.4 > 10.4.3.4 -ip #0 20(20) 35 10.4.3.4 > 10.3.4.7 +> zx0 ip #0 20(20) 255 10.3.4.1 > 10.1.1.2 +> zx0 ip #0 20(20) 255 10.3.4.2 > 10.1.1.2 +> zx0 ip #0 20(20) 255 10.3.4.3 > 10.1.1.1 +> zx0 ip #0 40(20) 6 10.3.4.3,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.3.4.3,1026 > 10.1.1.1,1025 +> zx0 ip #0 20(20) 255 10.2.2.1 > 10.1.2.1 +> zx0 ip #0 20(20) 255 10.2.2.2 > 10.1.2.1 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.2.2.1 > 10.2.1.1 +< zx0 ip #0 20(20) 255 10.2.2.2 > 10.2.1.1 +< zx0 ip #0 20(20) 255 10.2.2.3 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.2.3.4 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.0 > 10.3.4.5 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.3.4.5 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.3.4.5 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,1025 +> zx0 ip #0 48(20) 1 10.3.4.3 > 10.4.3.2 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.2.2.2 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.1 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.2 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.1.1.1 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.4 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.5 +> zx0 ip #0 20(20) 34 10.3.4.3 > 10.4.3.2 +< zx0 ip #0 20(20) 34 10.4.3.2 > 10.3.4.4 +> zx0 ip #0 20(20) 34 10.3.4.3 > 10.4.3.4 +< zx0 ip #0 20(20) 34 10.4.3.4 > 10.3.4.5 +> zx0 ip #0 20(20) 34 10.3.4.4 > 10.4.3.4 +< zx0 ip #0 20(20) 34 10.4.3.4 > 10.3.4.6 +> zx0 ip #0 20(20) 35 10.3.4.4 > 10.4.3.4 +< zx0 ip #0 20(20) 35 10.4.3.4 > 10.3.4.7 +List of active MAP/Redirect filters: +map zx0 10.1.1.0/24 -> 10.3.4.0/24 + +List of active sessions: +MAP 10.1.1.3 <- -> 10.3.4.4 [10.4.3.4] +MAP 10.1.1.3 <- -> 10.3.4.4 [10.4.3.4] +MAP 10.1.1.2 <- -> 10.3.4.3 [10.4.3.4] +MAP 10.1.1.2 <- -> 10.3.4.3 [10.4.3.2] +MAP 10.1.1.1 <- -> 10.3.4.3 [10.4.3.2] +MAP 10.1.1.2 1026 <- -> 10.3.4.3 1026 [10.1.1.1 1025] +MAP 10.1.1.2 1025 <- -> 10.3.4.3 1025 [10.1.1.1 1025] +MAP 10.1.1.2 <- -> 10.3.4.3 [10.1.1.1] +MAP 10.1.1.1 <- -> 10.3.4.2 [10.1.1.2] +MAP 10.1.1.0 <- -> 10.3.4.1 [10.1.1.2] + +Hostmap table: +10.1.1.3,10.4.3.4 -> 10.3.4.4,0.0.0.0 (use = 2) +10.1.1.2,10.4.3.4 -> 10.3.4.3,0.0.0.0 (use = 1) +10.1.1.2,10.4.3.2 -> 10.3.4.3,0.0.0.0 (use = 1) +10.1.1.1,10.4.3.2 -> 10.3.4.3,0.0.0.0 (use = 1) +10.1.1.2,10.1.1.1 -> 10.3.4.3,0.0.0.0 (use = 3) +10.1.1.1,10.1.1.2 -> 10.3.4.2,0.0.0.0 (use = 1) +10.1.1.0,10.1.1.2 -> 10.3.4.1,0.0.0.0 (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- diff --git a/test/expected/n10 b/test/expected/n10 index ae541d1585712..0c03ff088b704 100644 --- a/test/expected/n10 +++ b/test/expected/n10 @@ -1,9 +1,72 @@ 4500 002c 10c9 4000 ff06 5c9d cbcb cbcb 96cb e002 8032 0015 bd6b c9c8 0000 0000 6002 2238 655d 0000 0204 0064 +List of active MAP/Redirect filters: +map ppp0 0/0 -> 203.203.203.203/32 mssclamp 100 + +List of active sessions: +MAP 192.168.1.3 32818 <- -> 203.203.203.203 32818 [150.203.224.2 21] + +Hostmap table: +192.168.1.3,150.203.224.2 -> 203.203.203.203,0.0.0.0 (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- 4500 002c 10c9 4000 ff06 5c9d cbcb cbcb 96cb e002 8032 0015 bd6b c9c8 0000 0000 6002 2238 61d9 0000 0204 03e8 +List of active MAP/Redirect filters: +map ppp0 0/0 -> 203.203.203.203/32 mssclamp 1000 + +List of active sessions: +MAP 192.168.1.3 32818 <- -> 203.203.203.203 32818 [150.203.224.2 21] + +Hostmap table: +192.168.1.3,150.203.224.2 -> 203.203.203.203,0.0.0.0 (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- 4500 002c 10c9 4000 ff06 5c9d cbcb cbcb 96cb e002 8032 0015 bd6b c9c8 0000 0000 6002 2238 600d 0000 0204 05b4 +List of active MAP/Redirect filters: +map ppp0 0/0 -> 203.203.203.203/32 mssclamp 10000 + +List of active sessions: +MAP 192.168.1.3 32818 <- -> 203.203.203.203 32818 [150.203.224.2 21] + +Hostmap table: +192.168.1.3,150.203.224.2 -> 203.203.203.203,0.0.0.0 (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- diff --git a/test/expected/n100 b/test/expected/n100 new file mode 100644 index 0000000000000..80f00a178f30b --- /dev/null +++ b/test/expected/n100 @@ -0,0 +1,33 @@ +> zx0 ip #0 20(20) 255 1.1.1.1 > 2.3.2.3 +> zx0 ip #0 20(20) 255 4.4.4.4 > 6.6.0.1 +> zx0 ip #0 20(20) 255 4.4.4.4 > 6.6.0.2 +> zx0 ip #0 20(20) 255 4.4.4.4 > 6.6.0.3 +> zx0 ip #0 20(20) 255 4.4.4.4 > 6.6.0.4 +> zx0 ip #0 20(20) 255 4.4.4.4 > 6.6.0.1 +> zx0 ip #0 40(20) 6 1.1.1.1,101 > 2.3.2.3,203 +> zx0 ip #0 40(20) 6 4.4.4.4,101 > 6.6.0.5,203 +List of active MAP/Redirect filters: +rewrite out on zx0 from 0/0 to 2.2.0.0/16 -> src 4.4.4.4/32 dst 6.6.0.0/16; + +List of active sessions: +RWR-MAP 1.1.1.1 101 2.2.2.3 203 <- -> 4.4.4.4 101 6.6.0.5 203 +RWR-MAP 1.1.1.1 2.2.2.4 <- -> 4.4.4.4 6.6.0.4 +RWR-MAP 1.2.1.2 2.2.2.3 <- -> 4.4.4.4 6.6.0.3 +RWR-MAP 1.1.1.2 2.2.2.3 <- -> 4.4.4.4 6.6.0.2 +RWR-MAP 1.1.1.1 2.2.2.3 <- -> 4.4.4.4 6.6.0.1 + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/n101 b/test/expected/n101 new file mode 100644 index 0000000000000..ad0ad97bc3a65 --- /dev/null +++ b/test/expected/n101 @@ -0,0 +1,29 @@ +> zx0 ip #0 20(20) 255 1.1.1.1 > 2.3.2.3 +> zx0 ip #0 20(20) 255 1.1.1.1 > 2.2.2.3 +> zx0 ip #0 20(20) 255 1.1.1.2 > 2.2.2.3 +> zx0 ip #0 20(20) 255 1.2.1.2 > 2.2.2.3 +> zx0 ip #0 20(20) 255 1.1.1.1 > 2.2.2.4 +> zx0 ip #0 20(20) 255 1.1.1.1 > 2.2.2.3 +> zx0 ip #0 40(20) 6 1.1.1.1,101 > 2.3.2.3,203 +> zx0 ip #0 40(20) 6 4.4.4.4,101 > 6.6.0.1,203 +List of active MAP/Redirect filters: +rewrite out on zx0 proto tcp from 0/0 to 2.2.0.0/16 -> src 4.4.4.4/32 dst 6.6.0.0/16; + +List of active sessions: +RWR-MAP 1.1.1.1 101 2.2.2.3 203 <- -> 4.4.4.4 101 6.6.0.1 203 + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/n102 b/test/expected/n102 new file mode 100644 index 0000000000000..a2f130ee8a523 --- /dev/null +++ b/test/expected/n102 @@ -0,0 +1,29 @@ +> zx0 ip #0 20(20) 255 1.1.1.1 > 2.3.2.3 +> zx0 ip #0 20(20) 255 1.1.1.1 > 2.2.2.3 +> zx0 ip #0 20(20) 255 1.1.1.2 > 2.2.2.3 +> zx0 ip #0 20(20) 255 1.2.1.2 > 2.2.2.3 +> zx0 ip #0 20(20) 255 1.1.1.1 > 2.2.2.4 +> zx0 ip #0 20(20) 255 1.1.1.1 > 2.2.2.3 +> zx0 ip #0 40(20) 6 1.1.1.1,101 > 2.3.2.3,203 +> zx0 ip #0 40(20) 6 4.4.4.4,1000 > 6.6.0.1,203 +List of active MAP/Redirect filters: +rewrite out on zx0 proto tcp from 0/0 to 2.2.0.0/16 -> src 4.4.4.4/32,1000-2000 dst 6.6.0.0/16; + +List of active sessions: +RWR-MAP 1.1.1.1 101 2.2.2.3 203 <- -> 4.4.4.4 1000 6.6.0.1 203 + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/n103 b/test/expected/n103 new file mode 100644 index 0000000000000..31ed7404a0637 --- /dev/null +++ b/test/expected/n103 @@ -0,0 +1,33 @@ +> zx0 ip #0 40(20) 6 1.1.1.1,101 > 2.3.2.3,203 +> zx0 ip #0 40(20) 6 4.4.4.4,1000 > 6.6.0.1,4000 +> zx0 ip #0 40(20) 6 4.4.4.4,1000 > 6.6.0.1,4000 +> zx0 ip #0 40(20) 6 4.4.4.4,1001 > 6.6.0.1,4000 +> zx0 ip #0 40(20) 6 4.4.4.4,1001 > 6.6.0.2,4000 +> zx0 ip #0 40(20) 6 4.4.4.4,1001 > 6.6.0.2,4001 +< zx0 ip #0 40(20) 6 2.2.2.3,4000 > 4.4.4.4,1000 +> zx0 ip #0 40(20) 6 4.4.4.4,1000 > 6.6.0.2,4001 +List of active MAP/Redirect filters: +rewrite out on zx0 proto tcp from 0/0 to 2.2.0.0/16 -> src 4.4.4.4/32,1000-1001 dst 6.6.0.0/16,4000-4001; + +List of active sessions: +RWR-MAP 7.7.7.7 101 2.2.2.3 203 <- -> 4.4.4.4 1000 6.6.0.2 4001 +RWR-MAP 5.5.5.5 101 2.2.2.3 203 <- -> 4.4.4.4 1001 6.6.0.2 4001 +RWR-MAP 10.10.10.10 101 2.2.2.3 203 <- -> 4.4.4.4 1001 6.6.0.2 4000 +RWR-MAP 1.1.1.2 101 2.2.2.3 203 <- -> 4.4.4.4 1001 6.6.0.1 4000 +RWR-MAP 1.1.1.1 101 2.2.2.3 203 <- -> 4.4.4.4 1000 6.6.0.1 4000 + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/n104 b/test/expected/n104 new file mode 100644 index 0000000000000..3b8a9de2e87bf --- /dev/null +++ b/test/expected/n104 @@ -0,0 +1,50 @@ +4500 0028 0001 0000 ff06 b1c3 0404 0001 0606 0001 03e8 0fa0 0000 0001 1000 0001 5010 2000 623f 0000 + +4500 0028 0002 0000 ff06 b5c8 0202 0202 0101 0101 00cb 0065 0000 0001 1000 0001 5010 2000 789d 0000 + +4500 0028 0003 0000 ff06 b1c0 0404 0002 0606 0001 03e8 0fa0 0000 0001 1000 0001 5010 2000 623e 0000 + +4500 0028 0004 0000 ff06 b5c6 0202 0202 0101 0101 00cb 0066 0000 0001 1000 0001 5010 2000 789c 0000 + +4500 0028 0005 0000 ff06 b1be 0404 0002 0606 0001 03e9 0fa0 0000 0001 1000 0001 5010 2000 623d 0000 + +4500 0028 0006 0000 ff06 b5c4 0202 0202 0101 0101 00cb 0067 0000 0001 1000 0001 5010 2000 789b 0000 + +4500 0028 0007 0000 ff06 b1bb 0404 0002 0606 0002 03e9 0fa0 0000 0001 1000 0001 5010 2000 623c 0000 + +4500 0028 0008 0000 ff06 b5c2 0202 0202 0101 0101 00cb 0068 0000 0001 1000 0001 5010 2000 789a 0000 + +4500 0028 0009 0000 ff06 b1b9 0404 0002 0606 0002 03e9 0fa1 0000 0001 1000 0001 5010 2000 623b 0000 + +4500 0028 000a 0000 ff06 b5c0 0202 0202 0101 0101 00cb 0069 0000 0001 1000 0001 5010 2000 7899 0000 + +4500 0028 000b 0000 ff06 b1b6 0404 0003 0606 0002 03e9 0fa1 0000 0001 1000 0001 5010 2000 623a 0000 + +4500 0028 000c 0000 ff06 b5be 0202 0202 0101 0101 00cb 006a 0000 0001 1000 0001 5010 2000 7898 0000 + +List of active MAP/Redirect filters: +rewrite out on zx0 proto tcp from 0/0 to 2.2.0.0/16 -> src 4.4.0.0/24,1000-1001 dst 6.6.0.0/16,4000-4001; + +List of active sessions: +RWR-MAP 1.1.1.1 106 2.2.2.2 203 <- -> 4.4.0.3 1001 6.6.0.2 4001 +RWR-MAP 1.1.1.1 105 2.2.2.2 203 <- -> 4.4.0.2 1001 6.6.0.2 4001 +RWR-MAP 1.1.1.1 104 2.2.2.2 203 <- -> 4.4.0.2 1001 6.6.0.2 4000 +RWR-MAP 1.1.1.1 103 2.2.2.2 203 <- -> 4.4.0.2 1001 6.6.0.1 4000 +RWR-MAP 1.1.1.1 102 2.2.2.2 203 <- -> 4.4.0.2 1000 6.6.0.1 4000 +RWR-MAP 1.1.1.1 101 2.2.2.2 203 <- -> 4.4.0.1 1000 6.6.0.1 4000 + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/n105 b/test/expected/n105 new file mode 100644 index 0000000000000..d45a4af9840e8 --- /dev/null +++ b/test/expected/n105 @@ -0,0 +1,25 @@ +4500 0028 0001 0000 ff06 adc0 0404 0404 0606 0001 03e8 0c38 0000 0001 1000 0001 5010 2000 61a4 0000 + +4500 0028 0001 0000 ff06 b5c9 0202 0202 0101 0101 0050 0065 0000 0001 1000 0001 5010 2000 7918 0000 + +List of active MAP/Redirect filters: +rewrite in on zx0 proto tcp from 0/0 to 2.2.0.0/16 port = 80 -> src 4.4.4.4/32,1000-1001 dst 6.6.0.0/16,port = 3128; + +List of active sessions: +RWR-RDR 1.1.1.1 101 2.2.2.2 80 <- -> 4.4.4.4 1000 6.6.0.1 3128 + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/n106 b/test/expected/n106 new file mode 100644 index 0000000000000..d466e65533538 --- /dev/null +++ b/test/expected/n106 @@ -0,0 +1,25 @@ +4500 0028 0001 0000 ff06 adc0 0404 0404 0606 0001 03e8 0c38 0000 0001 1000 0001 5010 2000 61a4 0000 + +4500 0028 0001 0000 ff06 b5c9 0202 0202 0101 0101 0050 0065 0000 0001 1000 0001 5010 2000 7918 0000 + +List of active MAP/Redirect filters: +rewrite out on zx0 proto tcp from 0/0 to 2.2.0.0/16 port = 80 -> src 4.4.4.4/32,1000-1001 dst 6.6.0.0/16,port = 3128; + +List of active sessions: +RWR-MAP 1.1.1.1 101 2.2.2.2 80 <- -> 4.4.4.4 1000 6.6.0.1 3128 + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/n11 b/test/expected/n11 index 5257a64a1f088..ea11b93e7caf9 100644 --- a/test/expected/n11 +++ b/test/expected/n11 @@ -1,51 +1,124 @@ -ip #0 20(20) 255 10.1.1.0 > 10.1.1.2 -ip #0 20(20) 255 1.6.7.8 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 -ip #0 20(20) 255 10.2.2.1 > 10.1.2.1 -ip #0 20(20) 255 10.2.2.2 > 10.1.2.1 -ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 -ip #0 20(20) 255 10.2.2.1 > 10.2.1.1 -ip #0 20(20) 255 10.2.2.2 > 10.2.1.1 -ip #0 20(20) 255 10.2.2.3 > 10.1.1.1 -ip #0 20(20) 255 10.2.3.4 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.1 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.2 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.0 > 10.3.4.5 -ip #0 20(20) 255 10.1.1.1 > 10.3.4.5 -ip #0 20(20) 255 10.1.1.2 > 10.3.4.5 +> zx0 ip #0 20(20) 255 10.1.1.0 > 10.1.1.2 +> zx0 ip #0 20(20) 255 1.6.7.8 > 10.1.1.2 +> zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 +> zx0 ip #0 20(20) 255 10.2.2.1 > 10.1.2.1 +> zx0 ip #0 20(20) 255 10.2.2.2 > 10.1.2.1 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.2.2.1 > 10.2.1.1 +< zx0 ip #0 20(20) 255 10.2.2.2 > 10.2.1.1 +< zx0 ip #0 20(20) 255 10.2.2.3 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.2.3.4 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.0 > 10.3.4.5 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.3.4.5 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.3.4.5 +List of active MAP/Redirect filters: +bimap zx0 10.1.1.1/32 -> 1.6.7.8/32 + +List of active sessions: +BIMAP 10.1.1.1 <- -> 1.6.7.8 [10.1.1.2] + +Hostmap table: +10.1.1.1,10.1.1.2 -> 1.6.7.8,0.0.0.0 (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- -ip #0 20(20) 255 10.2.2.2 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 -ip #0 20(20) 255 10.2.2.2 > 10.1.1.1 -ip #0 20(20) 255 10.2.2.1 > 10.1.2.1 -ip #0 20(20) 255 10.2.2.2 > 10.1.2.1 -ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 -ip #0 20(20) 255 10.2.2.1 > 10.2.1.1 -ip #0 20(20) 255 10.2.2.2 > 10.2.1.1 -ip #0 20(20) 255 10.2.2.3 > 10.1.1.1 -ip #0 20(20) 255 10.2.3.4 > 10.1.1.0 -ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.0 -ip #0 20(20) 255 10.1.1.0 > 10.3.4.5 -ip #0 20(20) 255 10.1.1.1 > 10.3.4.5 -ip #0 20(20) 255 10.1.1.2 > 10.3.4.5 +> zx0 ip #0 20(20) 255 10.2.2.2 > 10.1.1.2 +15 +> zx0 ip #0 20(20) 255 10.2.2.2 > 10.1.1.1 +> zx0 ip #0 20(20) 255 10.2.2.1 > 10.1.2.1 +> zx0 ip #0 20(20) 255 10.2.2.2 > 10.1.2.1 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.2.2.1 > 10.2.1.1 +< zx0 ip #0 20(20) 255 10.2.2.2 > 10.2.1.1 +< zx0 ip #0 20(20) 255 10.2.2.3 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.2.3.4 > 10.1.1.0 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.0 +< zx0 ip #0 20(20) 255 10.1.1.0 > 10.3.4.5 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.3.4.5 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.3.4.5 +List of active MAP/Redirect filters: +bimap zx0 10.1.1.0/24 -> 10.2.2.2/32 + +List of active sessions: +BIMAP 10.1.1.0 <- -> 10.2.2.2 [10.2.3.4] +BIMAP 10.1.1.2 <- -> 10.2.2.2 [10.1.1.1] +BIMAP 10.1.1.0 <- -> 10.2.2.2 [10.1.1.2] + +Hostmap table: +10.1.1.2,10.1.1.1 -> 10.2.2.2,0.0.0.0 (use = 1) +10.1.1.0,10.1.1.2 -> 10.2.2.2,0.0.0.0 (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- -ip #0 20(20) 255 10.3.4.0 > 10.1.1.2 -ip #0 20(20) 255 10.3.4.1 > 10.1.1.2 -ip #0 20(20) 255 10.3.4.2 > 10.1.1.1 -ip #0 20(20) 255 10.2.2.1 > 10.1.2.1 -ip #0 20(20) 255 10.2.2.2 > 10.1.2.1 -ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 -ip #0 20(20) 255 10.2.2.1 > 10.2.1.1 -ip #0 20(20) 255 10.2.2.2 > 10.2.1.1 -ip #0 20(20) 255 10.2.2.3 > 10.1.1.1 -ip #0 20(20) 255 10.2.3.4 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.1 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.2 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.0 > 10.1.1.5 -ip #0 20(20) 255 10.1.1.1 > 10.1.1.5 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.5 +> zx0 ip #0 20(20) 255 10.3.4.0 > 10.1.1.2 +> zx0 ip #0 20(20) 255 10.3.4.1 > 10.1.1.2 +> zx0 ip #0 20(20) 255 10.3.4.2 > 10.1.1.1 +> zx0 ip #0 20(20) 255 10.2.2.1 > 10.1.2.1 +> zx0 ip #0 20(20) 255 10.2.2.2 > 10.1.2.1 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.2.2.1 > 10.2.1.1 +< zx0 ip #0 20(20) 255 10.2.2.2 > 10.2.1.1 +< zx0 ip #0 20(20) 255 10.2.2.3 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.2.3.4 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.0 > 10.1.1.5 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.1.1.5 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.5 +List of active MAP/Redirect filters: +bimap zx0 10.1.1.0/24 -> 10.3.4.0/24 + +List of active sessions: +BIMAP 10.1.1.5 <- -> 10.3.4.5 [10.1.1.2] +BIMAP 10.1.1.5 <- -> 10.3.4.5 [10.1.1.1] +BIMAP 10.1.1.5 <- -> 10.3.4.5 [10.1.1.0] +BIMAP 10.1.1.2 <- -> 10.3.4.2 [10.1.1.1] +BIMAP 10.1.1.1 <- -> 10.3.4.1 [10.1.1.2] +BIMAP 10.1.1.0 <- -> 10.3.4.0 [10.1.1.2] + +Hostmap table: +10.1.1.2,10.1.1.1 -> 10.3.4.1,0.0.0.0 (use = 1) +10.1.1.1,10.1.1.2 -> 10.3.4.1,0.0.0.0 (use = 1) +10.1.1.0,10.1.1.2 -> 10.3.4.1,0.0.0.0 (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- diff --git a/test/expected/n11_6 b/test/expected/n11_6 new file mode 100644 index 0000000000000..f1c80de81ba93 --- /dev/null +++ b/test/expected/n11_6 @@ -0,0 +1,124 @@ +> zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:0 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 255 1:0:0:0:0:6:7:8 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:1 > 10:1:2:0:0:0:0:1 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:1:2:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:1 > 10:0:0:0:0:2:1:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:0:0:0:0:2:1:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:3 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:3:4 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:0 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:0:0:0:0:3:4:5 +List of active MAP/Redirect filters: +bimap zx0 inet6 10:1:1::1/128 -> 1::6:7:8/128 + +List of active sessions: +BIMAP 10:1:1::1 <- -> 1::6:7:8 [10:1:1::2] + +Hostmap table: +10:1:1::1,10:1:1::2 -> 1::6:7:8,any (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:1:1:0:0:0:0:2 +16 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:1:1:0:0:0:0:1 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:1 > 10:1:2:0:0:0:0:1 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:1:2:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:1 > 10:0:0:0:0:2:1:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:0:0:0:0:2:1:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:3 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:3:4 > 10:1:1:0:0:0:0:0 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:0 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:0 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:0:0:0:0:3:4:5 +List of active MAP/Redirect filters: +bimap zx0 inet6 10:1:1::/112 -> 10::2:2:2/128 + +List of active sessions: +BIMAP 10:1:1:: <- -> 10::2:2:2 [10::2:3:4] +BIMAP 10:1:1::2 <- -> 10::2:2:2 [10:1:1::1] +BIMAP 10:1:1:: <- -> 10::2:2:2 [10:1:1::2] + +Hostmap table: +10:1:1::2,10:1:1::1 -> 10::2:2:2,any (use = 1) +10:1:1::,10:1:1::2 -> 10::2:2:2,any (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +> zx0 ip6/0 1 0 255 10:0:0:0:0:3:4:0 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 255 10:0:0:0:0:3:4:1 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 255 10:0:0:0:0:3:4:2 > 10:1:1:0:0:0:0:1 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:1 > 10:1:2:0:0:0:0:1 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:1:2:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:1 > 10:0:0:0:0:2:1:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:0:0:0:0:2:1:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:3 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:3:4 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:0 > 10:1:1:0:0:0:0:5 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:5 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:5 +List of active MAP/Redirect filters: +bimap zx0 inet6 10:1:1::/112 -> 10::3:4:0/112 + +List of active sessions: +BIMAP 10:1:1::5 <- -> 10::3:4:5 [10:1:1::2] +BIMAP 10:1:1::5 <- -> 10::3:4:5 [10:1:1::1] +BIMAP 10:1:1::5 <- -> 10::3:4:5 [10:1:1::] +BIMAP 10:1:1::2 <- -> 10::3:4:2 [10:1:1::1] +BIMAP 10:1:1::1 <- -> 10::3:4:1 [10:1:1::2] +BIMAP 10:1:1:: <- -> 10::3:4:0 [10:1:1::2] + +Hostmap table: +10:1:1::2,10:1:1::1 -> 10::3:4:1,any (use = 1) +10:1:1::1,10:1:1::2 -> 10::3:4:1,any (use = 1) +10:1:1::,10:1:1::2 -> 10::3:4:1,any (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/n12 b/test/expected/n12 index 0d5cefbf7e770..56b3a781c9fdf 100644 --- a/test/expected/n12 +++ b/test/expected/n12 @@ -4,4 +4,25 @@ 4510 0034 493b 4000 4006 6b69 c0a8 01bc c0a8 0303 2710 0017 4e33 298f f674 e02d 8010 4000 f673 0000 0101 080a 0c72 549e 2c05 b797 +List of active MAP/Redirect filters: +map le0 192.168.126.0/24 -> 0/32 portmap tcp/udp 10000:20000 sequential + +List of active sessions: +MAP 192.168.126.83 4802 <- -> 192.168.1.188 10000 [192.168.3.3 23] + +Hostmap table: +192.168.126.83,192.168.3.3 -> 0.0.0.0,0.0.0.0 (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- diff --git a/test/expected/n12_6 b/test/expected/n12_6 new file mode 100644 index 0000000000000..9ef040aaafd9d --- /dev/null +++ b/test/expected/n12_6 @@ -0,0 +1,28 @@ +6000 0000 002c 0640 c0a8 0100 0000 0000 0000 0000 0000 00bc c0a8 0300 0000 0000 0000 0000 0000 0003 2710 0017 4e33 298e 0000 0000 b002 4000 6ff8 0000 0204 05b4 0101 0402 0103 0300 0101 080a 0c72 549e 0000 0000 + +6000 0000 0028 06fe c0a8 0300 0000 0000 0000 0000 0000 0003 c0a8 7e00 0000 0000 0000 0000 0000 0053 0017 12c2 f674 e02c 4e33 298f a012 2798 7ace 0000 0101 080a 2c05 b797 0c72 549e 0103 0300 0204 05b4 + +6000 0000 0020 0640 c0a8 0100 0000 0000 0000 0000 0000 00bc c0a8 0300 0000 0000 0000 0000 0000 0003 2710 0017 4e33 298f f674 e02d 8010 4000 f673 0000 0101 080a 0c72 549e 2c05 b797 + +List of active MAP/Redirect filters: +map le0 inet6 c0a8:7e00::/112 -> ::/128 portmap tcp/udp 10000:20000 + +List of active sessions: +MAP c0a8:7e00::53 4802 <- -> c0a8:100::bc 10000 [c0a8:300::3 23] + +Hostmap table: +c0a8:7e00::53,c0a8:300::3 -> any,any (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/n13 b/test/expected/n13 index bfe201886528e..e6d26b2a5480b 100644 --- a/test/expected/n13 +++ b/test/expected/n13 @@ -1,5 +1,32 @@ -ip #0 20(20) 0 203.1.1.23 > 150.1.1.1 -ip #0 20(20) 0 203.1.1.23 > 150.1.1.2 -ip #0 20(20) 0 203.1.1.24 > 150.1.1.2 -ip #0 20(20) 0 203.1.1.25 > 150.1.1.1 +> le0 ip #0 20(20) 0 203.1.1.23 > 150.1.1.1 +> le0 ip #0 20(20) 0 203.1.1.23 > 150.1.1.2 +> le0 ip #0 20(20) 0 203.1.1.24 > 150.1.1.2 +> le0 ip #0 20(20) 0 203.1.1.25 > 150.1.1.1 +List of active MAP/Redirect filters: +map le0 192.168.0.0/16 -> range 203.1.1.23-203.1.3.45 + +List of active sessions: +MAP 192.168.1.3 <- -> 203.1.1.25 [150.1.1.1] +MAP 192.168.1.2 <- -> 203.1.1.24 [150.1.1.2] +MAP 192.168.1.1 <- -> 203.1.1.23 [150.1.1.2] +MAP 192.168.1.1 <- -> 203.1.1.23 [150.1.1.1] + +Hostmap table: +192.168.1.3,150.1.1.1 -> 203.1.1.25,0.0.0.0 (use = 1) +192.168.1.2,150.1.1.2 -> 203.1.1.24,0.0.0.0 (use = 1) +192.168.1.1,150.1.1.2 -> 203.1.1.23,0.0.0.0 (use = 1) +192.168.1.1,150.1.1.1 -> 203.1.1.23,0.0.0.0 (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- diff --git a/test/expected/n13_6 b/test/expected/n13_6 new file mode 100644 index 0000000000000..d3b5fe7fb99d0 --- /dev/null +++ b/test/expected/n13_6 @@ -0,0 +1,32 @@ +> le0 ip6/0 1 0 41 203:0:1:0:0:0:1:23 > 150.1.1.1 +> le0 ip6/0 1 0 41 203:0:1:0:0:0:1:23 > 150.1.1.2 +> le0 ip6/0 1 0 41 203:0:1:0:0:0:1:24 > 150.1.1.2 +> le0 ip6/0 1 0 41 203:0:1:0:0:0:1:25 > 150.1.1.1 +List of active MAP/Redirect filters: +map le0 inet6 192:168:0::0/48 -> range 203:0:1::1:23-203:0:1::3:45 + +List of active sessions: +MAP 192.168.1.3 <- -> 203:0:1::1:25 [150.1.1.1] +MAP 192.168.1.2 <- -> 203:0:1::1:24 [150.1.1.2] +MAP 192.168.1.1 <- -> 203:0:1::1:23 [150.1.1.2] +MAP 192.168.1.1 <- -> 203:0:1::1:23 [150.1.1.1] + +Hostmap table: +192.168.1.3,150.1.1.1 -> 203:0:1:0:0:0:1:25,any (use = 1) +192.168.1.2,150.1.1.2 -> 203:0:1:0:0:0:1:24,any (use = 1) +192.168.1.1,150.1.1.2 -> 203:0:1:0:0:0:1:23,any (use = 1) +192.168.1.1,150.1.1.1 -> 203:0:1:0:0:0:1:23,any (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/n14 b/test/expected/n14 index 46693001a4446..7b1a19ea931a4 100644 --- a/test/expected/n14 +++ b/test/expected/n14 @@ -1,5 +1,30 @@ -ip #0 40(20) 6 10.2.2.5,2000 > 10.1.1.254,80 -ip #0 40(20) 6 10.2.2.6,2000 > 10.1.1.253,80 -ip #0 40(20) 6 10.2.2.7,2000 > 10.1.1.254,80 -ip #0 40(20) 6 10.2.2.5,2001 > 10.1.1.254,80 +< gre0 ip #0 40(20) 6 10.2.2.5,2000 > 10.1.1.254,80 +< gre0 ip #0 40(20) 6 10.2.2.6,2000 > 10.1.1.253,80 +< gre0 ip #0 40(20) 6 10.2.2.7,2000 > 10.1.1.254,80 +15 +List of active MAP/Redirect filters: +rdr gre0 0/0 port 80 -> 10.1.1.254,10.1.1.253 port 80 tcp sticky + +List of active sessions: +RDR 10.1.1.254 80 <- -> 203.1.1.1 80 [10.2.2.7 2000] +RDR 10.1.1.253 80 <- -> 203.1.1.1 80 [10.2.2.6 2000] +RDR 10.1.1.254 80 <- -> 203.1.1.1 80 [10.2.2.5 2000] + +Hostmap table: +10.2.2.7,203.1.1.1 -> 254.1.1.10,0.0.0.0 (use = 1) +10.2.2.6,203.1.1.1 -> 253.1.1.10,0.0.0.0 (use = 1) +10.2.2.5,203.1.1.1 -> 254.1.1.10,0.0.0.0 (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- diff --git a/test/expected/n14_6 b/test/expected/n14_6 new file mode 100644 index 0000000000000..b999ee971d806 --- /dev/null +++ b/test/expected/n14_6 @@ -0,0 +1,30 @@ +< gre0 ip6/0 20 0 6 10:0:0:0:0:2:2:5,2000 > 10:1:1:0:0:0:0:254,80 +< gre0 ip6/0 20 0 6 10:0:0:0:0:2:2:6,2000 > 10:1:1:0:0:0:0:253,80 +< gre0 ip6/0 20 0 6 10:0:0:0:0:2:2:7,2000 > 10:1:1:0:0:0:0:254,80 +< gre0 ip6/0 20 0 6 10:0:0:0:0:2:2:5,2001 > 203:0:1:0:0:0:1:1,80 +List of active MAP/Redirect filters: +rdr gre0 inet6 any port 80 -> 10:1:1::254,10:1:1::253 port 80 tcp sticky + +List of active sessions: +RDR 10:1:1::254 80 <- -> 203:0:1::1:1 80 [10::2:2:7 2000] +RDR 10:1:1::253 80 <- -> 203:0:1::1:1 80 [10::2:2:6 2000] +RDR 10:1:1::254 80 <- -> 203:0:1::1:1 80 [10::2:2:5 2000] + +Hostmap table: +10::2:2:7,203:0:1:0:0:0:1:1 -> 254:1:1::10,any (use = 1) +10::2:2:6,203:0:1:0:0:0:1:1 -> 253:0:1:0:0:0:1:10,any (use = 1) +10::2:2:5,203:0:1:0:0:0:1:1 -> 254:1:1::10,any (use = 3) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/n15 b/test/expected/n15 new file mode 100644 index 0000000000000..3889f82081df1 --- /dev/null +++ b/test/expected/n15 @@ -0,0 +1,47 @@ +< le0 ip #0 40(20) 6 9.9.9.9,10011 > 3.3.3.3,80 +15 +List of active MAP/Redirect filters: +rdr le0 0/0 port 80 -> 3.3.3.3/32 port 80 tcp + +List of active sessions: +RDR 3.3.3.3 80 <- -> 5.5.5.5 80 [9.9.9.9 10011] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +< le0 ip #0 40(20) 6 9.9.9.9,10011 > 3.3.3.3,80 +< le0 ip #0 40(20) 6 9.9.9.9,10011 > 3.3.3.3,81 +List of active MAP/Redirect filters: +rdr le0 0/0 port 80 -> 3.3.3.3/32 port 80-88 tcp + +List of active sessions: +RDR 3.3.3.3 81 <- -> 2.2.2.2 80 [9.9.9.9 10011] +RDR 3.3.3.3 80 <- -> 5.5.5.5 80 [9.9.9.9 10011] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/n15_6 b/test/expected/n15_6 new file mode 100644 index 0000000000000..f01b72b68056f --- /dev/null +++ b/test/expected/n15_6 @@ -0,0 +1,47 @@ +< le0 ip6/0 20 0 6 9:9:9:0:0:0:0:9,10011 > 3:0:3:0:0:0:3:3,80 +16 +List of active MAP/Redirect filters: +rdr le0 inet6 any port 80 -> 3:0:3::3:3/128 port 80 tcp + +List of active sessions: +RDR 3:0:3::3:3 80 <- -> 5:5::5:5 80 [9:9:9::9 10011] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +< le0 ip6/0 20 0 6 9:9:9:0:0:0:0:9,10011 > 3:0:3:0:0:0:3:3,80 +< le0 ip6/0 20 0 6 9:9:9:0:0:0:0:9,10011 > 3:0:3:0:0:0:3:3,81 +List of active MAP/Redirect filters: +rdr le0 inet6 any port 80 -> 3:0:3::3:3/128 port 80-88 tcp + +List of active sessions: +RDR 3:0:3::3:3 81 <- -> 2::2:2:2 80 [9:9:9::9 10011] +RDR 3:0:3::3:3 80 <- -> 5:5::5:5 80 [9:9:9::9 10011] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/n16 b/test/expected/n16 index da617d9d3600b..0eb3954e85727 100644 --- a/test/expected/n16 +++ b/test/expected/n16 @@ -7,7 +7,7 @@ 4500 0084 ee0f 0000 8001 4a21 45f8 4fc1 c05b ac33 0303 bf85 0000 0000 4520 0068 17e4 0000 6a11 3639 c05b ac33 45f8 4fc1 1194 94f8 0054 0000 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 List of active MAP/Redirect filters: -rdr vlan0 from any to 69.248.79.193/32 port = 38136 -> 172.31.83.24 port 2013 udp +rdr vlan0 from 0/0 to 69.248.79.193/32 port = 38136 -> 172.31.83.24/32 port 2013 udp List of active sessions: RDR 172.31.83.24 2013 <- -> 69.248.79.193 38136 [192.91.172.51 4500] @@ -18,4 +18,12 @@ List of configured pools List of configured hash tables List of groups configured (set 0) List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- diff --git a/test/expected/n17 b/test/expected/n17 new file mode 100644 index 0000000000000..f336bb0fb8d76 --- /dev/null +++ b/test/expected/n17 @@ -0,0 +1,24 @@ +4500 00a0 0000 0100 3f06 7555 0101 0101 0201 0101 0401 0019 0000 0000 0000 0000 5010 2000 86b7 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + +4500 00a0 0000 0100 3f06 7553 0201 0101 0101 0103 0401 0019 0000 0000 0000 0000 5010 2000 86b7 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + +List of active MAP/Redirect filters: +bimap zx0 0/0 -> 1.1.1.3/32 + +List of active sessions: + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/n18 b/test/expected/n18 new file mode 100644 index 0000000000000..c51c11c9a52e8 --- /dev/null +++ b/test/expected/n18 @@ -0,0 +1,111 @@ +> z0 ip #0 40(20) 6 1.1.1.1,1 > 3.3.3.3,30 +> z0 ip #0 40(20) 6 1.1.1.1,2 > 3.3.3.3,31 +> z0 ip #0 40(20) 6 1.1.1.1,3 > 3.3.3.3,32 +> z0 ip #0 40(20) 6 1.1.1.1,4 > 3.3.3.3,33 +> z0 ip #0 40(20) 6 1.1.1.1,1 > 3.3.3.3,34 +> z0 ip #0 40(20) 6 1.1.1.1,2 > 3.3.3.3,35 +> z0 ip #0 40(20) 6 1.1.1.1,3 > 3.3.3.3,36 +> z0 ip #0 40(20) 6 1.1.1.1,4 > 3.3.3.3,37 +List of active MAP/Redirect filters: +map z0 0/0 -> 1.1.1.1/32 portmap tcp/udp 1:4 sequential + +List of active sessions: +MAP 2.2.2.2 29 <- -> 1.1.1.1 4 [3.3.3.3 37] +MAP 2.2.2.2 28 <- -> 1.1.1.1 3 [3.3.3.3 36] +MAP 2.2.2.2 27 <- -> 1.1.1.1 2 [3.3.3.3 35] +MAP 2.2.2.2 26 <- -> 1.1.1.1 1 [3.3.3.3 34] +MAP 2.2.2.2 25 <- -> 1.1.1.1 4 [3.3.3.3 33] +MAP 2.2.2.2 24 <- -> 1.1.1.1 3 [3.3.3.3 32] +MAP 2.2.2.2 23 <- -> 1.1.1.1 2 [3.3.3.3 31] +MAP 2.2.2.2 22 <- -> 1.1.1.1 1 [3.3.3.3 30] + +Hostmap table: +2.2.2.2,3.3.3.3 -> 1.1.1.1,0.0.0.0 (use = 8) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +> z0 ip #0 40(20) 6 1.1.1.1,1000 > 3.3.3.3,30 +> z0 ip #0 40(20) 6 1.1.1.1,1001 > 3.3.3.3,31 +> z0 ip #0 40(20) 6 1.1.1.1,1002 > 3.3.3.3,32 +> z0 ip #0 40(20) 6 1.1.1.1,1003 > 3.3.3.3,33 +> z0 ip #0 40(20) 6 1.1.1.1,1004 > 3.3.3.3,34 +> z0 ip #0 40(20) 6 1.1.1.1,1005 > 3.3.3.3,35 +> z0 ip #0 40(20) 6 1.1.1.1,1006 > 3.3.3.3,36 +> z0 ip #0 40(20) 6 1.1.1.1,1007 > 3.3.3.3,37 +List of active MAP/Redirect filters: +map z0 0/0 -> 1.1.1.1/32 portmap tcp/udp 1000:5000 sequential + +List of active sessions: +MAP 2.2.2.2 29 <- -> 1.1.1.1 1007 [3.3.3.3 37] +MAP 2.2.2.2 28 <- -> 1.1.1.1 1006 [3.3.3.3 36] +MAP 2.2.2.2 27 <- -> 1.1.1.1 1005 [3.3.3.3 35] +MAP 2.2.2.2 26 <- -> 1.1.1.1 1004 [3.3.3.3 34] +MAP 2.2.2.2 25 <- -> 1.1.1.1 1003 [3.3.3.3 33] +MAP 2.2.2.2 24 <- -> 1.1.1.1 1002 [3.3.3.3 32] +MAP 2.2.2.2 23 <- -> 1.1.1.1 1001 [3.3.3.3 31] +MAP 2.2.2.2 22 <- -> 1.1.1.1 1000 [3.3.3.3 30] + +Hostmap table: +2.2.2.2,3.3.3.3 -> 1.1.1.1,0.0.0.0 (use = 8) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +> z0 ip #0 40(20) 6 1.1.1.1,1000 > 3.3.3.3,30 +> z0 ip #0 40(20) 6 1.1.1.1,1001 > 3.3.3.3,31 +> z0 ip #0 40(20) 6 1.1.1.1,1002 > 3.3.3.3,32 +> z0 ip #0 40(20) 6 1.1.1.1,1003 > 3.3.3.3,33 +> z0 ip #0 40(20) 6 1.1.1.1,1004 > 3.3.3.3,34 +> z0 ip #0 40(20) 6 1.1.1.1,1005 > 3.3.3.3,35 +> z0 ip #0 40(20) 6 1.1.1.1,1006 > 3.3.3.3,36 +> z0 ip #0 40(20) 6 1.1.1.1,1007 > 3.3.3.3,37 +List of active MAP/Redirect filters: +map z0 0/0 -> 1.1.1.1/32 portmap tcp/udp 1000:50000 sequential + +List of active sessions: +MAP 2.2.2.2 29 <- -> 1.1.1.1 1007 [3.3.3.3 37] +MAP 2.2.2.2 28 <- -> 1.1.1.1 1006 [3.3.3.3 36] +MAP 2.2.2.2 27 <- -> 1.1.1.1 1005 [3.3.3.3 35] +MAP 2.2.2.2 26 <- -> 1.1.1.1 1004 [3.3.3.3 34] +MAP 2.2.2.2 25 <- -> 1.1.1.1 1003 [3.3.3.3 33] +MAP 2.2.2.2 24 <- -> 1.1.1.1 1002 [3.3.3.3 32] +MAP 2.2.2.2 23 <- -> 1.1.1.1 1001 [3.3.3.3 31] +MAP 2.2.2.2 22 <- -> 1.1.1.1 1000 [3.3.3.3 30] + +Hostmap table: +2.2.2.2,3.3.3.3 -> 1.1.1.1,0.0.0.0 (use = 8) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/n1_6 b/test/expected/n1_6 new file mode 100644 index 0000000000000..347bf4aac4bc2 --- /dev/null +++ b/test/expected/n1_6 @@ -0,0 +1,197 @@ +> zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:0 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:2,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:2,1026 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:1 > 10:1:2:0:0:0:0:1 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:1:2:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:1 > 10:0:0:0:0:2:1:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:0:0:0:0:2:1:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:3 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:3:4 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:0 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:0:0:0:0:3:4:5,1025 +> zx0 ip6/0 88 0 58 10:0:0:0:0:2:2:2 > 10:4:3:0:0:0:0:2 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:1 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:2 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:3 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:4 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:5 +> zx0 ip6/0 1 0 34 10:1:1:0:0:0:0:2 > 10:4:3:0:0:0:0:2 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:4 +> zx0 ip6/0 1 0 34 10:1:1:0:0:0:0:2 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:5 +> zx0 ip6/0 1 0 34 10:1:1:0:0:0:0:3 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:6 +> zx0 ip6/0 1 0 35 10:1:1:0:0:0:0:3 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 35 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:7 +List of active MAP/Redirect filters: +map zx0 inet6 10:1:1::1/128 -> 10::2:2:2/128 + +List of active sessions: +MAP 10:1:1::1 <- -> 10::2:2:2 [10:4:3::2] +MAP 10:1:1::1 <- -> 10::2:2:2 [10:1:1::2] + +Hostmap table: +10:1:1::1,10:4:3::2 -> 10::2:2:2,any (use = 1) +10:1:1::1,10:1:1::2 -> 10::2:2:2,any (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +> zx0 ip6/0 1 0 255 10:0:0:0:0:3:4:5 > 10:1:1:0:0:0:0:2 +16 +> zx0 ip6/0 1 0 255 10:0:0:0:0:3:4:5 > 10:1:1:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,1026 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:1 > 10:1:2:0:0:0:0:1 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:1:2:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:1 > 10:0:0:0:0:2:1:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:0:0:0:0:2:1:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:3 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:3:4 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:0 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:0 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:1:1:0:0:0:0:2,1025 +> zx0 ip6/0 88 0 58 10:0:0:0:0:3:4:5 > 10:4:3:0:0:0:0:2 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:1 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:2 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:3 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:4 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +> zx0 ip6/0 1 0 34 10:0:0:0:0:3:4:5 > 10:4:3:0:0:0:0:2 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:4 +> zx0 ip6/0 1 0 34 10:0:0:0:0:3:4:5 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:4 > 10:1:1:0:0:0:0:2 +16 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:6 +> zx0 ip6/0 1 0 35 10:0:0:0:0:3:4:5 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 35 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:7 +List of active MAP/Redirect filters: +map zx0 inet6 10:1:1::/112 -> 10::3:4:5/128 + +List of active sessions: +MAP 10:1:1::3 <- -> 10::3:4:5 [10:4:3::4] +MAP 10:1:1::2 <- -> 10::3:4:5 [10:4:3::4] +MAP 10:1:1::2 <- -> 10::3:4:5 [10:4:3::2] +MAP 10:1:1::1 <- -> 10::3:4:5 [10:4:3::2] +MAP 10:1:1::2 1026 <- -> 10::3:4:5 1026 [10:1:1::1 1025] +MAP 10:1:1::2 1025 <- -> 10::3:4:5 1025 [10:1:1::1 1025] +MAP 10:1:1::2 <- -> 10::3:4:5 [10:1:1::1] +MAP 10:1:1:: <- -> 10::3:4:5 [10:1:1::2] + +Hostmap table: +10:1:1::3,10:4:3::4 -> 10::3:4:5,any (use = 1) +10:1:1::2,10:4:3::4 -> 10::3:4:5,any (use = 1) +10:1:1::2,10:4:3::2 -> 10::3:4:5,any (use = 1) +10:1:1::1,10:4:3::2 -> 10::3:4:5,any (use = 1) +10:1:1::2,10:1:1::1 -> 10::3:4:5,any (use = 3) +10:1:1::,10:1:1::2 -> 10::3:4:5,any (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +> zx0 ip6/0 1 0 255 10:0:0:0:0:3:4:1 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 255 10:0:0:0:0:3:4:2 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 255 10:0:0:0:0:3:4:3 > 10:1:1:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:3,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:3,1026 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:1 > 10:1:2:0:0:0:0:1 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:1:2:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:1 > 10:0:0:0:0:2:1:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:0:0:0:0:2:1:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:3 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:3:4 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:0 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:0:0:0:0:3:4:5,1025 +> zx0 ip6/0 88 0 58 10:0:0:0:0:3:4:3 > 10:4:3:0:0:0:0:2 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:1 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:2 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:4 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:5 +> zx0 ip6/0 1 0 34 10:0:0:0:0:3:4:3 > 10:4:3:0:0:0:0:2 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:4 +> zx0 ip6/0 1 0 34 10:0:0:0:0:3:4:3 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:5 +> zx0 ip6/0 1 0 34 10:0:0:0:0:3:4:4 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:6 +> zx0 ip6/0 1 0 35 10:0:0:0:0:3:4:4 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 35 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:7 +List of active MAP/Redirect filters: +map zx0 inet6 10:1:1::/112 -> 10::3:4:0/112 + +List of active sessions: +MAP 10:1:1::3 <- -> 10::3:4:4 [10:4:3::4] +MAP 10:1:1::3 <- -> 10::3:4:4 [10:4:3::4] +MAP 10:1:1::2 <- -> 10::3:4:3 [10:4:3::4] +MAP 10:1:1::2 <- -> 10::3:4:3 [10:4:3::2] +MAP 10:1:1::1 <- -> 10::3:4:3 [10:4:3::2] +MAP 10:1:1::2 1026 <- -> 10::3:4:3 1026 [10:1:1::1 1025] +MAP 10:1:1::2 1025 <- -> 10::3:4:3 1025 [10:1:1::1 1025] +MAP 10:1:1::2 <- -> 10::3:4:3 [10:1:1::1] +MAP 10:1:1::1 <- -> 10::3:4:2 [10:1:1::2] +MAP 10:1:1:: <- -> 10::3:4:1 [10:1:1::2] + +Hostmap table: +10:1:1::3,10:4:3::4 -> 10::3:4:4,any (use = 2) +10:1:1::2,10:4:3::4 -> 10::3:4:3,any (use = 1) +10:1:1::2,10:4:3::2 -> 10::3:4:3,any (use = 1) +10:1:1::1,10:4:3::2 -> 10::3:4:3,any (use = 1) +10:1:1::2,10:1:1::1 -> 10::3:4:3,any (use = 3) +10:1:1::1,10:1:1::2 -> 10::3:4:2,any (use = 1) +10:1:1::,10:1:1::2 -> 10::3:4:1,any (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/n2 b/test/expected/n2 index 827272e91031e..836608a46ad71 100644 --- a/test/expected/n2 +++ b/test/expected/n2 @@ -1,80 +1,191 @@ -ip #0 40(20) 6 10.2.2.2,10000 > 10.1.1.1,1025 -ip #0 40(20) 6 10.2.2.2,10001 > 10.1.1.2,1025 -ip #0 20(20) 0 10.1.1.0 > 10.1.1.2 -ip #0 20(20) 0 10.1.1.1 > 10.1.2.1 -ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.1.1.2,1026 > 10.1.1.1,1025 -ip #0 28(20) 17 10.1.1.2,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.1.1.3,2000 > 10.1.2.1,80 -ip #0 40(20) 6 10.1.1.3,2001 > 10.1.3.1,80 -ip #0 40(20) 6 10.1.1.3,2002 > 10.1.4.1,80 -ip #0 40(20) 6 10.1.1.3,2003 > 10.1.4.1,80 -ip #0 20(20) 0 10.1.1.1 > 10.1.1.2 -ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 -ip #0 20(20) 0 10.1.1.2 > 10.1.1.1 -ip #0 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000 -ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,40000 -ip #0 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001 -ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 +> zx0 ip #0 40(20) 6 10.2.2.2,10000 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.2.2.2,10001 > 10.1.1.2,1025 +> zx0 ip #0 20(20) 0 10.1.1.0 > 10.1.1.2 +> zx0 ip #0 20(20) 0 10.1.1.1 > 10.1.2.1 +> zx0 ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.1.1.2,1026 > 10.1.1.1,1025 +> zx0 ip #0 28(20) 17 10.1.1.2,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.1.1.3,2000 > 10.1.2.1,80 +> zx0 ip #0 40(20) 6 10.1.1.3,2001 > 10.1.3.1,80 +> zx0 ip #0 40(20) 6 10.1.1.3,2002 > 10.1.4.1,80 +> zx0 ip #0 40(20) 6 10.1.1.3,2003 > 10.1.4.1,80 +< zx0 ip #0 20(20) 0 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 +< zx0 ip #0 20(20) 0 10.1.1.2 > 10.1.1.1 +< zx0 ip #0 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,40000 +< zx0 ip #0 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001 +< zx0 ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 +List of active MAP/Redirect filters: +map zx0 10.1.1.1/32 -> 10.2.2.2/32 portmap tcp 10000:20000 sequential + +List of active sessions: +MAP 10.1.1.1 1025 <- -> 10.2.2.2 10001 [10.1.1.2 1025] +MAP 10.1.1.1 1025 <- -> 10.2.2.2 10000 [10.1.1.1 1025] + +Hostmap table: +10.1.1.1,10.1.1.2 -> 10.2.2.2,0.0.0.0 (use = 1) +10.1.1.1,10.1.1.1 -> 10.2.2.2,0.0.0.0 (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- -ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 -ip #0 20(20) 0 10.1.1.0 > 10.1.1.2 -ip #0 20(20) 0 10.1.1.1 > 10.1.2.1 -ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.1.1.2,1026 > 10.1.1.1,1025 -ip #0 28(20) 17 10.3.4.5,10000 > 10.1.1.1,1025 -ip #0 40(20) 6 10.1.1.3,2000 > 10.1.2.1,80 -ip #0 40(20) 6 10.1.1.3,2001 > 10.1.3.1,80 -ip #0 40(20) 6 10.1.1.3,2002 > 10.1.4.1,80 -ip #0 40(20) 6 10.1.1.3,2003 > 10.1.4.1,80 -ip #0 20(20) 0 10.1.1.1 > 10.1.1.2 -ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 -ip #0 20(20) 0 10.1.1.2 > 10.1.1.1 -ip #0 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000 -ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,40000 -ip #0 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001 -ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 +> zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 +> zx0 ip #0 20(20) 0 10.1.1.0 > 10.1.1.2 +> zx0 ip #0 20(20) 0 10.1.1.1 > 10.1.2.1 +> zx0 ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.1.1.2,1026 > 10.1.1.1,1025 +> zx0 ip #0 28(20) 17 10.3.4.5,10000 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.1.1.3,2000 > 10.1.2.1,80 +> zx0 ip #0 40(20) 6 10.1.1.3,2001 > 10.1.3.1,80 +> zx0 ip #0 40(20) 6 10.1.1.3,2002 > 10.1.4.1,80 +> zx0 ip #0 40(20) 6 10.1.1.3,2003 > 10.1.4.1,80 +< zx0 ip #0 20(20) 0 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 +< zx0 ip #0 20(20) 0 10.1.1.2 > 10.1.1.1 +< zx0 ip #0 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,40000 +< zx0 ip #0 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001 +< zx0 ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 +List of active MAP/Redirect filters: +map zx0 10.1.1.0/24 -> 10.3.4.5/32 portmap udp 10000:20000 sequential + +List of active sessions: +MAP 10.1.1.2 1025 <- -> 10.3.4.5 10000 [10.1.1.1 1025] + +Hostmap table: +10.1.1.2,10.1.1.1 -> 10.3.4.5,0.0.0.0 (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- -ip #0 40(20) 6 10.3.4.1,10000 > 10.1.1.1,1025 -ip #0 40(20) 6 10.3.4.1,10001 > 10.1.1.2,1025 -ip #0 20(20) 0 10.1.1.0 > 10.1.1.2 -ip #0 20(20) 0 10.1.1.1 > 10.1.2.1 -ip #0 40(20) 6 10.3.4.1,10002 > 10.1.1.1,1025 -ip #0 40(20) 6 10.3.4.1,10002 > 10.1.1.1,1025 -ip #0 40(20) 6 10.3.4.1,10003 > 10.1.1.1,1025 -ip #0 28(20) 17 10.3.4.1,10004 > 10.1.1.1,1025 -ip #0 40(20) 6 10.3.4.1,10005 > 10.1.2.1,80 -ip #0 40(20) 6 10.3.4.1,10006 > 10.1.3.1,80 -ip #0 40(20) 6 10.3.4.1,10007 > 10.1.4.1,80 -ip #0 40(20) 6 10.3.4.1,10008 > 10.1.4.1,80 -ip #0 20(20) 0 10.1.1.1 > 10.1.1.2 -ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 -ip #0 20(20) 0 10.1.1.2 > 10.1.1.1 -ip #0 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000 -ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,40000 -ip #0 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001 -ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 +> zx0 ip #0 40(20) 6 10.3.4.1,10000 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.3.4.1,10001 > 10.1.1.2,1025 +> zx0 ip #0 20(20) 0 10.1.1.0 > 10.1.1.2 +> zx0 ip #0 20(20) 0 10.1.1.1 > 10.1.2.1 +> zx0 ip #0 40(20) 6 10.3.4.1,10002 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.3.4.1,10002 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.3.4.1,10003 > 10.1.1.1,1025 +> zx0 ip #0 28(20) 17 10.3.4.1,10004 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.3.4.1,10005 > 10.1.2.1,80 +> zx0 ip #0 40(20) 6 10.3.4.1,10006 > 10.1.3.1,80 +> zx0 ip #0 40(20) 6 10.3.4.1,10007 > 10.1.4.1,80 +> zx0 ip #0 40(20) 6 10.3.4.1,10008 > 10.1.4.1,80 +< zx0 ip #0 20(20) 0 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 +< zx0 ip #0 20(20) 0 10.1.1.2 > 10.1.1.1 +< zx0 ip #0 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,40000 +< zx0 ip #0 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001 +< zx0 ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 +List of active MAP/Redirect filters: +map zx0 10.1.0.0/16 -> 10.3.4.0/24 portmap tcp/udp 10000:20000 sequential + +List of active sessions: +MAP 10.1.1.3 2003 <- -> 10.3.4.1 10008 [10.1.4.1 80] +MAP 10.1.1.3 2002 <- -> 10.3.4.1 10007 [10.1.4.1 80] +MAP 10.1.1.3 2001 <- -> 10.3.4.1 10006 [10.1.3.1 80] +MAP 10.1.1.3 2000 <- -> 10.3.4.1 10005 [10.1.2.1 80] +MAP 10.1.1.2 1025 <- -> 10.3.4.1 10004 [10.1.1.1 1025] +MAP 10.1.1.2 1026 <- -> 10.3.4.1 10003 [10.1.1.1 1025] +MAP 10.1.1.2 1025 <- -> 10.3.4.1 10002 [10.1.1.1 1025] +MAP 10.1.1.1 1025 <- -> 10.3.4.1 10001 [10.1.1.2 1025] +MAP 10.1.1.1 1025 <- -> 10.3.4.1 10000 [10.1.1.1 1025] + +Hostmap table: +10.1.1.3,10.1.4.1 -> 10.3.4.1,0.0.0.0 (use = 2) +10.1.1.3,10.1.3.1 -> 10.3.4.1,0.0.0.0 (use = 1) +10.1.1.3,10.1.2.1 -> 10.3.4.1,0.0.0.0 (use = 1) +10.1.1.2,10.1.1.1 -> 10.3.4.1,0.0.0.0 (use = 3) +10.1.1.1,10.1.1.2 -> 10.3.4.1,0.0.0.0 (use = 1) +10.1.1.1,10.1.1.1 -> 10.3.4.1,0.0.0.0 (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- -ip #0 40(20) 6 10.3.4.5,40000 > 10.1.1.1,1025 -ip #0 40(20) 6 10.3.4.5,40001 > 10.1.1.2,1025 -ip #0 20(20) 0 10.1.1.0 > 10.1.1.2 -ip #0 20(20) 0 10.1.1.1 > 10.1.2.1 -ip #0 40(20) 6 10.3.4.5,40001 > 10.1.1.1,1025 -ip #0 40(20) 6 10.3.4.5,40001 > 10.1.1.1,1025 -ip #0 40(20) 6 10.1.1.2,1026 > 10.1.1.1,1025 -ip #0 28(20) 17 10.3.4.5,40000 > 10.1.1.1,1025 -ip #0 40(20) 6 10.3.4.5,40001 > 10.1.2.1,80 -ip #0 40(20) 6 10.3.4.5,40000 > 10.1.3.1,80 -ip #0 40(20) 6 10.3.4.5,40001 > 10.1.4.1,80 -ip #0 40(20) 6 10.3.4.5,40000 > 10.1.4.1,80 -ip #0 20(20) 0 10.1.1.1 > 10.1.1.2 -ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 -ip #0 20(20) 0 10.1.1.2 > 10.1.1.1 -ip #0 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000 -ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.1,1025 -ip #0 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001 -ip #0 40(20) 6 10.1.2.1,80 > 10.1.1.3,2000 +> zx0 ip #0 40(20) 6 10.3.4.5,40000 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.3.4.5,40001 > 10.1.1.2,1025 +> zx0 ip #0 20(20) 0 10.1.1.0 > 10.1.1.2 +> zx0 ip #0 20(20) 0 10.1.1.1 > 10.1.2.1 +> zx0 ip #0 40(20) 6 10.3.4.5,40001 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.3.4.5,40001 > 10.1.1.1,1025 +15 +> zx0 ip #0 28(20) 17 10.3.4.5,40000 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.3.4.5,40001 > 10.1.2.1,80 +> zx0 ip #0 40(20) 6 10.3.4.5,40000 > 10.1.3.1,80 +> zx0 ip #0 40(20) 6 10.3.4.5,40001 > 10.1.4.1,80 +> zx0 ip #0 40(20) 6 10.3.4.5,40000 > 10.1.4.1,80 +< zx0 ip #0 20(20) 0 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 +< zx0 ip #0 20(20) 0 10.1.1.2 > 10.1.1.1 +< zx0 ip #0 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.1,1025 +< zx0 ip #0 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001 +< zx0 ip #0 40(20) 6 10.1.2.1,80 > 10.1.1.3,2000 +List of active MAP/Redirect filters: +map zx0 10.1.1.0/24 -> 10.3.4.5/32 portmap tcp/udp 40000:40001 sequential + +List of active sessions: +MAP 10.1.1.3 2003 <- -> 10.3.4.5 40000 [10.1.4.1 80] +MAP 10.1.1.3 2002 <- -> 10.3.4.5 40001 [10.1.4.1 80] +MAP 10.1.1.3 2001 <- -> 10.3.4.5 40000 [10.1.3.1 80] +MAP 10.1.1.3 2000 <- -> 10.3.4.5 40001 [10.1.2.1 80] +MAP 10.1.1.2 1025 <- -> 10.3.4.5 40000 [10.1.1.1 1025] +MAP 10.1.1.2 1025 <- -> 10.3.4.5 40001 [10.1.1.1 1025] +MAP 10.1.1.1 1025 <- -> 10.3.4.5 40001 [10.1.1.2 1025] +MAP 10.1.1.1 1025 <- -> 10.3.4.5 40000 [10.1.1.1 1025] + +Hostmap table: +10.1.1.3,10.1.4.1 -> 10.3.4.5,0.0.0.0 (use = 2) +10.1.1.3,10.1.3.1 -> 10.3.4.5,0.0.0.0 (use = 1) +10.1.1.3,10.1.2.1 -> 10.3.4.5,0.0.0.0 (use = 1) +10.1.1.2,10.1.1.1 -> 10.3.4.5,0.0.0.0 (use = 2) +10.1.1.1,10.1.1.2 -> 10.3.4.5,0.0.0.0 (use = 1) +10.1.1.1,10.1.1.1 -> 10.3.4.5,0.0.0.0 (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- diff --git a/test/expected/n200 b/test/expected/n200 new file mode 100644 index 0000000000000..0f3c6a5adece1 --- /dev/null +++ b/test/expected/n200 @@ -0,0 +1,25 @@ +4500 0044 0000 0000 ff11 bda6 7f00 0001 7f00 0001 2775 2775 0030 0000 4500 0028 0000 0000 0006 435a 6363 6363 5858 5858 038d 0050 0000 0000 0000 0000 5000 1000 2491 0000 + +4500 0028 0000 0000 0006 435a 6363 6363 5858 5858 038d 0050 0000 0000 0000 0000 5000 1000 2491 0000 + +List of active MAP/Redirect filters: +divert in on bar0 proto tcp from 0/0 to 0/0 -> src 127.0.0.1/32,10101 dst 127.0.0.1/32,10101 udp; + +List of active sessions: +DIV-RDR 127.0.0.1 10101 <- -> 88.88.88.88 80 [99.99.99.99 909] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/n2_6 b/test/expected/n2_6 new file mode 100644 index 0000000000000..08abc8f5b69c2 --- /dev/null +++ b/test/expected/n2_6 @@ -0,0 +1,191 @@ +> zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,10000 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,10001 > 10:1:1:0:0:0:0:2,1025 +> zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:0 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:1 > 10:1:2:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:2,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:2,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:2,1026 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 8 0 17 10:1:1:0:0:0:0:2,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:3,2000 > 10:1:2:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:3,2001 > 10:1:3:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:3,2002 > 10:1:4:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:3,2003 > 10:1:4:0:0:0:0:1,80 +< zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:1:1:0:0:0:0:2,1025 +< zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1026 > 10:0:0:0:0:3:4:5,40000 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:0:0:0:0:3:4:5,40000 +< zx0 ip6/0 8 0 17 10:1:1:0:0:0:0:2,1025 > 10:0:0:0:0:3:4:5,40001 +< zx0 ip6/0 20 0 6 10:1:2:0:0:0:0:1,80 > 10:0:0:0:0:3:4:5,40001 +List of active MAP/Redirect filters: +map zx0 inet6 10:1:1::1/128 -> 10::2:2:2/128 portmap tcp 10000:20000 sequential + +List of active sessions: +MAP 10:1:1::1 1025 <- -> 10::2:2:2 10001 [10:1:1::2 1025] +MAP 10:1:1::1 1025 <- -> 10::2:2:2 10000 [10:1:1::1 1025] + +Hostmap table: +10:1:1::1,10:1:1::2 -> 10::2:2:2,any (use = 1) +10:1:1::1,10:1:1::1 -> 10::2:2:2,any (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:1:1:0:0:0:0:2,1025 +> zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:0 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:1 > 10:1:2:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:2,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:2,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:2,1026 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 8 0 17 10:0:0:0:0:3:4:5,10000 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:3,2000 > 10:1:2:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:3,2001 > 10:1:3:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:3,2002 > 10:1:4:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:3,2003 > 10:1:4:0:0:0:0:1,80 +< zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:1:1:0:0:0:0:2,1025 +< zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1026 > 10:0:0:0:0:3:4:5,40000 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:0:0:0:0:3:4:5,40000 +< zx0 ip6/0 8 0 17 10:1:1:0:0:0:0:2,1025 > 10:0:0:0:0:3:4:5,40001 +< zx0 ip6/0 20 0 6 10:1:2:0:0:0:0:1,80 > 10:0:0:0:0:3:4:5,40001 +List of active MAP/Redirect filters: +map zx0 inet6 10:1:1::/112 -> 10::3:4:5/128 portmap udp 10000:20000 sequential + +List of active sessions: +MAP 10:1:1::2 1025 <- -> 10::3:4:5 10000 [10:1:1::1 1025] + +Hostmap table: +10:1:1::2,10:1:1::1 -> 10::3:4:5,any (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:1,10000 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:1,10001 > 10:1:1:0:0:0:0:2,1025 +> zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:0 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:1 > 10:1:2:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:1,10002 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:1,10002 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:1,10003 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 8 0 17 10:0:0:0:0:3:4:1,10004 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:1,10005 > 10:1:2:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:1,10006 > 10:1:3:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:1,10007 > 10:1:4:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:1,10008 > 10:1:4:0:0:0:0:1,80 +< zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:1:1:0:0:0:0:2,1025 +< zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1026 > 10:0:0:0:0:3:4:5,40000 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:0:0:0:0:3:4:5,40000 +< zx0 ip6/0 8 0 17 10:1:1:0:0:0:0:2,1025 > 10:0:0:0:0:3:4:5,40001 +< zx0 ip6/0 20 0 6 10:1:2:0:0:0:0:1,80 > 10:0:0:0:0:3:4:5,40001 +List of active MAP/Redirect filters: +map zx0 inet6 10:1::/32 -> 10::3:4:0/112 portmap tcp/udp 10000:20000 sequential + +List of active sessions: +MAP 10:1:1::3 2003 <- -> 10::3:4:1 10008 [10:1:4::1 80] +MAP 10:1:1::3 2002 <- -> 10::3:4:1 10007 [10:1:4::1 80] +MAP 10:1:1::3 2001 <- -> 10::3:4:1 10006 [10:1:3::1 80] +MAP 10:1:1::3 2000 <- -> 10::3:4:1 10005 [10:1:2::1 80] +MAP 10:1:1::2 1025 <- -> 10::3:4:1 10004 [10:1:1::1 1025] +MAP 10:1:1::2 1026 <- -> 10::3:4:1 10003 [10:1:1::1 1025] +MAP 10:1:1::2 1025 <- -> 10::3:4:1 10002 [10:1:1::1 1025] +MAP 10:1:1::1 1025 <- -> 10::3:4:1 10001 [10:1:1::2 1025] +MAP 10:1:1::1 1025 <- -> 10::3:4:1 10000 [10:1:1::1 1025] + +Hostmap table: +10:1:1::3,10:1:4::1 -> 10::3:4:1,any (use = 2) +10:1:1::3,10:1:3::1 -> 10::3:4:1,any (use = 1) +10:1:1::3,10:1:2::1 -> 10::3:4:1,any (use = 1) +10:1:1::2,10:1:1::1 -> 10::3:4:1,any (use = 3) +10:1:1::1,10:1:1::2 -> 10::3:4:1,any (use = 1) +10:1:1::1,10:1:1::1 -> 10::3:4:1,any (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,40000 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,40001 > 10:1:1:0:0:0:0:2,1025 +> zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:0 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:1 > 10:1:2:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,40001 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,40001 > 10:1:1:0:0:0:0:1,1025 +16 +> zx0 ip6/0 8 0 17 10:0:0:0:0:3:4:5,40000 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,40001 > 10:1:2:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,40000 > 10:1:3:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,40001 > 10:1:4:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,40000 > 10:1:4:0:0:0:0:1,80 +< zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:1:1:0:0:0:0:2,1025 +< zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1026 > 10:0:0:0:0:3:4:5,40000 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:1:1:0:0:0:0:1,1025 +< zx0 ip6/0 8 0 17 10:1:1:0:0:0:0:2,1025 > 10:0:0:0:0:3:4:5,40001 +< zx0 ip6/0 20 0 6 10:1:2:0:0:0:0:1,80 > 10:1:1:0:0:0:0:3,2000 +List of active MAP/Redirect filters: +map zx0 inet6 10:1:1::/112 -> 10::3:4:5/128 portmap tcp/udp 40000:40001 sequential + +List of active sessions: +MAP 10:1:1::3 2003 <- -> 10::3:4:5 40000 [10:1:4::1 80] +MAP 10:1:1::3 2002 <- -> 10::3:4:5 40001 [10:1:4::1 80] +MAP 10:1:1::3 2001 <- -> 10::3:4:5 40000 [10:1:3::1 80] +MAP 10:1:1::3 2000 <- -> 10::3:4:5 40001 [10:1:2::1 80] +MAP 10:1:1::2 1025 <- -> 10::3:4:5 40000 [10:1:1::1 1025] +MAP 10:1:1::2 1025 <- -> 10::3:4:5 40001 [10:1:1::1 1025] +MAP 10:1:1::1 1025 <- -> 10::3:4:5 40001 [10:1:1::2 1025] +MAP 10:1:1::1 1025 <- -> 10::3:4:5 40000 [10:1:1::1 1025] + +Hostmap table: +10:1:1::3,10:1:4::1 -> 10::3:4:5,any (use = 2) +10:1:1::3,10:1:3::1 -> 10::3:4:5,any (use = 1) +10:1:1::3,10:1:2::1 -> 10::3:4:5,any (use = 1) +10:1:1::2,10:1:1::1 -> 10::3:4:5,any (use = 2) +10:1:1::1,10:1:1::2 -> 10::3:4:5,any (use = 1) +10:1:1::1,10:1:1::1 -> 10::3:4:5,any (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/n3 b/test/expected/n3 index 0e019aefb2bae..66ada76e930ac 100644 --- a/test/expected/n3 +++ b/test/expected/n3 @@ -1,12 +1,66 @@ -ip #0 40(20) 6 192.168.2.1,1488 > 203.1.1.1,80 -ip #0 40(20) 6 192.168.2.1,1276 > 203.1.1.1,80 -ip #0 40(20) 6 192.168.2.1,1032 > 203.1.1.1,80 -ip #0 28(20) 17 192.168.2.1,1032 > 203.1.1.1,80 -ip #0 40(20) 6 192.168.2.1,65299 > 203.1.1.1,80 +> zz0 ip #0 40(20) 6 192.168.2.1,1488 > 203.1.1.1,80 +> zz0 ip #0 40(20) 6 192.168.2.1,1276 > 203.1.1.1,80 +> zz0 ip #0 40(20) 6 192.168.2.1,1032 > 203.1.1.1,80 +> zz0 ip #0 28(20) 17 192.168.2.1,1032 > 203.1.1.1,80 +> zz0 ip #0 40(20) 6 192.168.2.1,65299 > 203.1.1.1,80 +List of active MAP/Redirect filters: +map zz0 10.1.0.0/16 -> 192.168.2.0/24 portmap tcp/udp auto + +List of active sessions: +MAP 10.1.255.255 65535 <- -> 192.168.2.1 65299 [203.1.1.1 80] +MAP 10.1.0.0 32768 <- -> 192.168.2.1 1032 [203.1.1.1 80] +MAP 10.1.0.0 32768 <- -> 192.168.2.1 1032 [203.1.1.1 80] +MAP 10.1.1.1 252 <- -> 192.168.2.1 1276 [203.1.1.1 80] +MAP 10.1.1.1 5000 <- -> 192.168.2.1 1488 [203.1.1.1 80] + +Hostmap table: +10.1.255.255,203.1.1.1 -> 192.168.2.1,0.0.0.0 (use = 1) +10.1.0.0,203.1.1.1 -> 192.168.2.1,0.0.0.0 (use = 2) +10.1.1.1,203.1.1.1 -> 192.168.2.1,0.0.0.0 (use = 2) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- -ip #0 40(20) 6 192.168.1.1,1488 > 203.1.1.1,80 -ip #0 40(20) 6 192.168.1.1,1276 > 203.1.1.1,80 -ip #0 40(20) 6 192.168.1.0,1032 > 203.1.1.1,80 -ip #0 28(20) 17 192.168.1.0,1032 > 203.1.1.1,80 -ip #0 40(20) 6 192.168.1.255,65299 > 203.1.1.1,80 +> zz0 ip #0 40(20) 6 192.168.1.1,1488 > 203.1.1.1,80 +> zz0 ip #0 40(20) 6 192.168.1.1,1276 > 203.1.1.1,80 +> zz0 ip #0 40(20) 6 192.168.1.0,1032 > 203.1.1.1,80 +> zz0 ip #0 28(20) 17 192.168.1.0,1032 > 203.1.1.1,80 +> zz0 ip #0 40(20) 6 192.168.1.255,65299 > 203.1.1.1,80 +List of active MAP/Redirect filters: +map-block zz0 10.1.0.0/16 -> 192.168.1.0/24 ports 252 + +List of active sessions: +MAP-BLOCK 10.1.255.255 65535 <- -> 192.168.1.255 65299 [203.1.1.1 80] +MAP-BLOCK 10.1.0.0 32768 <- -> 192.168.1.0 1032 [203.1.1.1 80] +MAP-BLOCK 10.1.0.0 32768 <- -> 192.168.1.0 1032 [203.1.1.1 80] +MAP-BLOCK 10.1.1.1 252 <- -> 192.168.1.1 1276 [203.1.1.1 80] +MAP-BLOCK 10.1.1.1 5000 <- -> 192.168.1.1 1488 [203.1.1.1 80] + +Hostmap table: +10.1.255.255,203.1.1.1 -> 192.168.1.1,0.0.0.0 (use = 1) +10.1.0.0,203.1.1.1 -> 192.168.1.1,0.0.0.0 (use = 2) +10.1.1.1,203.1.1.1 -> 192.168.1.1,0.0.0.0 (use = 2) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- diff --git a/test/expected/n4 b/test/expected/n4 index 863217c1db794..746ef7e185830 100644 --- a/test/expected/n4 +++ b/test/expected/n4 @@ -1,66 +1,190 @@ -ip #0 40(20) 6 10.3.3.3,12345 > 10.2.2.1,10023 -ip #0 40(20) 6 10.1.1.1,23 > 10.3.3.3,12345 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.1,53 -ip #0 40(20) 6 10.2.2.1,10053 > 10.3.3.3,12345 -ip #0 40(20) 6 10.3.3.3,12346 > 10.1.0.0,23 -ip #0 40(20) 6 10.2.2.1,10023 > 10.3.3.3,12346 -ip #0 28(20) 17 10.3.3.3,12345 > 10.1.1.0,53 -ip #0 28(20) 17 10.2.2.1,10053 > 10.3.3.3,12345 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.0,53 -ip #0 40(20) 6 10.2.2.1,53 > 10.3.3.3,12345 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.2.2.1,10023 +> zx0 ip #0 40(20) 6 10.1.1.1,23 > 10.3.3.3,12345 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.1,53 +> zx0 ip #0 40(20) 6 10.2.2.1,10053 > 10.3.3.3,12345 +< zx0 ip #0 40(20) 6 10.3.3.3,12346 > 10.1.0.0,23 +> zx0 ip #0 40(20) 6 10.2.2.1,10023 > 10.3.3.3,12346 +< zx0 ip #0 28(20) 17 10.3.3.3,12345 > 10.1.1.0,53 +> zx0 ip #0 28(20) 17 10.2.2.1,10053 > 10.3.3.3,12345 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.0,53 +> zx0 ip #0 40(20) 6 10.2.2.1,53 > 10.3.3.3,12345 +List of active MAP/Redirect filters: +rdr zx0 10.1.1.1/32 port 23 -> 10.2.2.1/32 port 10023 tcp + +List of active sessions: +RDR 10.2.2.1 10023 <- -> 10.1.1.1 23 [10.3.3.3 12345] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- -ip #0 40(20) 6 10.3.3.3,12345 > 10.2.2.1,10023 -ip #0 40(20) 6 10.1.1.1,23 > 10.3.3.3,12345 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.1,53 -ip #0 40(20) 6 10.2.2.1,10053 > 10.3.3.3,12345 -ip #0 40(20) 6 10.3.3.3,12346 > 10.1.0.0,23 -ip #0 40(20) 6 10.2.2.1,10023 > 10.3.3.3,12346 -ip #0 28(20) 17 10.3.3.3,12345 > 10.1.1.0,53 -ip #0 28(20) 17 10.2.2.1,10053 > 10.3.3.3,12345 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.0,53 -ip #0 40(20) 6 10.2.2.1,53 > 10.3.3.3,12345 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.2.2.1,10023 +> zx0 ip #0 40(20) 6 10.1.1.1,23 > 10.3.3.3,12345 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.1,53 +> zx0 ip #0 40(20) 6 10.2.2.1,10053 > 10.3.3.3,12345 +< zx0 ip #0 40(20) 6 10.3.3.3,12346 > 10.1.0.0,23 +> zx0 ip #0 40(20) 6 10.2.2.1,10023 > 10.3.3.3,12346 +< zx0 ip #0 28(20) 17 10.3.3.3,12345 > 10.1.1.0,53 +> zx0 ip #0 28(20) 17 10.2.2.1,10053 > 10.3.3.3,12345 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.0,53 +> zx0 ip #0 40(20) 6 10.2.2.1,53 > 10.3.3.3,12345 +List of active MAP/Redirect filters: +rdr zx0 10.1.1.0/24 port 23 -> 10.2.2.1/32 port 10023 tcp + +List of active sessions: +RDR 10.2.2.1 10023 <- -> 10.1.1.1 23 [10.3.3.3 12345] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- -ip #0 40(20) 6 10.3.3.3,12345 > 10.2.2.1,10023 -ip #0 40(20) 6 10.1.1.1,23 > 10.3.3.3,12345 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.1,53 -ip #0 40(20) 6 10.2.2.1,10053 > 10.3.3.3,12345 -ip #0 40(20) 6 10.3.3.3,12346 > 10.2.2.1,10023 -ip #0 40(20) 6 10.1.0.0,23 > 10.3.3.3,12346 -ip #0 28(20) 17 10.3.3.3,12345 > 10.1.1.0,53 -ip #0 28(20) 17 10.2.2.1,10053 > 10.3.3.3,12345 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.0,53 -ip #0 40(20) 6 10.2.2.1,53 > 10.3.3.3,12345 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.2.2.1,10023 +> zx0 ip #0 40(20) 6 10.1.1.1,23 > 10.3.3.3,12345 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.1,53 +> zx0 ip #0 40(20) 6 10.2.2.1,10053 > 10.3.3.3,12345 +< zx0 ip #0 40(20) 6 10.3.3.3,12346 > 10.2.2.1,10023 +> zx0 ip #0 40(20) 6 10.1.0.0,23 > 10.3.3.3,12346 +< zx0 ip #0 28(20) 17 10.3.3.3,12345 > 10.1.1.0,53 +> zx0 ip #0 28(20) 17 10.2.2.1,10053 > 10.3.3.3,12345 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.0,53 +> zx0 ip #0 40(20) 6 10.2.2.1,53 > 10.3.3.3,12345 +List of active MAP/Redirect filters: +rdr zx0 0/0 port 23 -> 10.2.2.1/32 port 10023 tcp + +List of active sessions: +RDR 10.2.2.1 10023 <- -> 10.1.0.0 23 [10.3.3.3 12346] +RDR 10.2.2.1 10023 <- -> 10.1.1.1 23 [10.3.3.3 12345] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.1,23 -ip #0 40(20) 6 10.2.2.1,10023 > 10.3.3.3,12345 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.1,53 -ip #0 40(20) 6 10.2.2.1,10053 > 10.3.3.3,12345 -ip #0 40(20) 6 10.3.3.3,12346 > 10.1.0.0,23 -ip #0 40(20) 6 10.2.2.1,10023 > 10.3.3.3,12346 -ip #0 28(20) 17 10.3.3.3,12345 > 10.2.2.1,10053 -ip #0 28(20) 17 10.1.1.0,53 > 10.3.3.3,12345 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.0,53 -ip #0 40(20) 6 10.2.2.1,53 > 10.3.3.3,12345 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.1,23 +> zx0 ip #0 40(20) 6 10.2.2.1,10023 > 10.3.3.3,12345 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.1,53 +> zx0 ip #0 40(20) 6 10.2.2.1,10053 > 10.3.3.3,12345 +< zx0 ip #0 40(20) 6 10.3.3.3,12346 > 10.1.0.0,23 +> zx0 ip #0 40(20) 6 10.2.2.1,10023 > 10.3.3.3,12346 +< zx0 ip #0 28(20) 17 10.3.3.3,12345 > 10.2.2.1,10053 +> zx0 ip #0 28(20) 17 10.1.1.0,53 > 10.3.3.3,12345 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.0,53 +> zx0 ip #0 40(20) 6 10.2.2.1,53 > 10.3.3.3,12345 +List of active MAP/Redirect filters: +rdr zx0 10.1.1.0/24 port 53 -> 10.2.2.1/32 port 10053 udp + +List of active sessions: +RDR 10.2.2.1 10053 <- -> 10.1.1.0 53 [10.3.3.3 12345] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- -ip #0 40(20) 6 10.3.3.3,12345 > 10.2.2.1,23 -ip #0 40(20) 6 10.2.2.1,10023 > 10.3.3.3,12345 -ip #0 40(20) 6 10.3.3.3,12345 > 10.2.2.1,53 -ip #0 40(20) 6 10.2.2.1,10053 > 10.3.3.3,12345 -ip #0 40(20) 6 10.3.3.3,12346 > 10.1.0.0,23 -ip #0 40(20) 6 10.2.2.1,10023 > 10.3.3.3,12346 -ip #0 28(20) 17 10.3.3.3,12345 > 10.1.1.0,53 -ip #0 28(20) 17 10.2.2.1,10053 > 10.3.3.3,12345 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.0,53 -ip #0 40(20) 6 10.1.1.1,53 > 10.3.3.3,12345 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.2.2.1,23 +> zx0 ip #0 40(20) 6 10.2.2.1,10023 > 10.3.3.3,12345 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.2.2.1,53 +> zx0 ip #0 40(20) 6 10.2.2.1,10053 > 10.3.3.3,12345 +< zx0 ip #0 40(20) 6 10.3.3.3,12346 > 10.1.0.0,23 +> zx0 ip #0 40(20) 6 10.2.2.1,10023 > 10.3.3.3,12346 +< zx0 ip #0 28(20) 17 10.3.3.3,12345 > 10.1.1.0,53 +> zx0 ip #0 28(20) 17 10.2.2.1,10053 > 10.3.3.3,12345 +15 +> zx0 ip #0 40(20) 6 10.1.1.1,53 > 10.3.3.3,12345 +List of active MAP/Redirect filters: +rdr zx0 10.1.1.0/24 port 0 -> 10.2.2.1/32 port 0 tcp + +List of active sessions: +RDR 10.2.2.1 53 <- -> 10.1.1.1 53 [10.3.3.3 12345] +RDR 10.2.2.1 23 <- -> 10.1.1.1 23 [10.3.3.3 12345] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- -ip #0 40(20) 6 10.3.3.3,12345 > 10.2.2.1,23 -ip #0 40(20) 6 10.2.2.1,10023 > 10.3.3.3,12345 -ip #0 40(20) 6 10.3.3.3,12345 > 10.2.2.1,53 -ip #0 40(20) 6 10.2.2.1,10053 > 10.3.3.3,12345 -ip #0 40(20) 6 10.3.3.3,12346 > 10.1.0.0,23 -ip #0 40(20) 6 10.2.2.1,10023 > 10.3.3.3,12346 -ip #0 28(20) 17 10.3.3.3,12345 > 10.2.2.1,53 -ip #0 28(20) 17 10.2.2.1,10053 > 10.3.3.3,12345 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.0,53 -ip #0 40(20) 6 10.1.1.1,53 > 10.3.3.3,12345 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.2.2.1,23 +> zx0 ip #0 40(20) 6 10.2.2.1,10023 > 10.3.3.3,12345 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.2.2.1,53 +> zx0 ip #0 40(20) 6 10.2.2.1,10053 > 10.3.3.3,12345 +< zx0 ip #0 40(20) 6 10.3.3.3,12346 > 10.1.0.0,23 +> zx0 ip #0 40(20) 6 10.2.2.1,10023 > 10.3.3.3,12346 +< zx0 ip #0 28(20) 17 10.3.3.3,12345 > 10.2.2.1,53 +> zx0 ip #0 28(20) 17 10.2.2.1,10053 > 10.3.3.3,12345 +15 +> zx0 ip #0 40(20) 6 10.1.1.1,53 > 10.3.3.3,12345 +List of active MAP/Redirect filters: +rdr zx0 10.1.1.0/24 -> 10.2.2.1/32 ip + +List of active sessions: +RDR 10.2.2.1 53 <- -> 10.1.1.0 53 [10.3.3.3 12345] +RDR 10.2.2.1 53 <- -> 10.1.1.1 53 [10.3.3.3 12345] +RDR 10.2.2.1 23 <- -> 10.1.1.1 23 [10.3.3.3 12345] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- diff --git a/test/expected/n4_6 b/test/expected/n4_6 new file mode 100644 index 0000000000000..e9a5ce34507c9 --- /dev/null +++ b/test/expected/n4_6 @@ -0,0 +1,190 @@ +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:0:0:0:0:2:2:1,10023 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,23 > 10:3:3:0:0:0:0:3,12345 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:1,53 +> zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:1,10053 > 10:3:3:0:0:0:0:3,12345 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12346 > 10:1:0:0:0:0:0:0,23 +> zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:1,10023 > 10:3:3:0:0:0:0:3,12346 +< zx0 ip6/0 8 0 17 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:0,53 +> zx0 ip6/0 8 0 17 10:0:0:0:0:2:2:1,10053 > 10:3:3:0:0:0:0:3,12345 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:0,53 +> zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:1,53 > 10:3:3:0:0:0:0:3,12345 +List of active MAP/Redirect filters: +rdr zx0 inet6 10:1:1::1/128 port 23 -> 10::2:2:1/128 port 10023 tcp + +List of active sessions: +RDR 10::2:2:1 10023 <- -> 10:1:1::1 23 [10:3:3::3 12345] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:0:0:0:0:2:2:1,10023 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,23 > 10:3:3:0:0:0:0:3,12345 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:1,53 +> zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:1,10053 > 10:3:3:0:0:0:0:3,12345 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12346 > 10:1:0:0:0:0:0:0,23 +> zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:1,10023 > 10:3:3:0:0:0:0:3,12346 +< zx0 ip6/0 8 0 17 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:0,53 +> zx0 ip6/0 8 0 17 10:0:0:0:0:2:2:1,10053 > 10:3:3:0:0:0:0:3,12345 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:0,53 +> zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:1,53 > 10:3:3:0:0:0:0:3,12345 +List of active MAP/Redirect filters: +rdr zx0 inet6 10:1:1::/112 port 23 -> 10::2:2:1/128 port 10023 tcp + +List of active sessions: +RDR 10::2:2:1 10023 <- -> 10:1:1::1 23 [10:3:3::3 12345] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:0:0:0:0:2:2:1,10023 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,23 > 10:3:3:0:0:0:0:3,12345 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:1,53 +> zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:1,10053 > 10:3:3:0:0:0:0:3,12345 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12346 > 10:0:0:0:0:2:2:1,10023 +> zx0 ip6/0 20 0 6 10:1:0:0:0:0:0:0,23 > 10:3:3:0:0:0:0:3,12346 +< zx0 ip6/0 8 0 17 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:0,53 +> zx0 ip6/0 8 0 17 10:0:0:0:0:2:2:1,10053 > 10:3:3:0:0:0:0:3,12345 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:0,53 +> zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:1,53 > 10:3:3:0:0:0:0:3,12345 +List of active MAP/Redirect filters: +rdr zx0 inet6 any port 23 -> 10::2:2:1/128 port 10023 tcp + +List of active sessions: +RDR 10::2:2:1 10023 <- -> 10:1:: 23 [10:3:3::3 12346] +RDR 10::2:2:1 10023 <- -> 10:1:1::1 23 [10:3:3::3 12345] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:1,23 +> zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:1,10023 > 10:3:3:0:0:0:0:3,12345 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:1,53 +> zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:1,10053 > 10:3:3:0:0:0:0:3,12345 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12346 > 10:1:0:0:0:0:0:0,23 +> zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:1,10023 > 10:3:3:0:0:0:0:3,12346 +< zx0 ip6/0 8 0 17 10:3:3:0:0:0:0:3,12345 > 10:0:0:0:0:2:2:1,10053 +> zx0 ip6/0 8 0 17 10:1:1:0:0:0:0:0,53 > 10:3:3:0:0:0:0:3,12345 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:0,53 +> zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:1,53 > 10:3:3:0:0:0:0:3,12345 +List of active MAP/Redirect filters: +rdr zx0 inet6 10:1:1::/112 port 53 -> 10::2:2:1/128 port 10053 udp + +List of active sessions: +RDR 10::2:2:1 10053 <- -> 10:1:1:: 53 [10:3:3::3 12345] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:0:0:0:0:2:2:1,23 +> zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:1,10023 > 10:3:3:0:0:0:0:3,12345 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:0:0:0:0:2:2:1,53 +> zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:1,10053 > 10:3:3:0:0:0:0:3,12345 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12346 > 10:1:0:0:0:0:0:0,23 +> zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:1,10023 > 10:3:3:0:0:0:0:3,12346 +< zx0 ip6/0 8 0 17 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:0,53 +> zx0 ip6/0 8 0 17 10:0:0:0:0:2:2:1,10053 > 10:3:3:0:0:0:0:3,12345 +16 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,53 > 10:3:3:0:0:0:0:3,12345 +List of active MAP/Redirect filters: +rdr zx0 inet6 10:1:1::/112 port 0 -> 10::2:2:1/128 port 0 tcp + +List of active sessions: +RDR 10::2:2:1 53 <- -> 10:1:1::1 53 [10:3:3::3 12345] +RDR 10::2:2:1 23 <- -> 10:1:1::1 23 [10:3:3::3 12345] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:0:0:0:0:2:2:1,23 +> zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:1,10023 > 10:3:3:0:0:0:0:3,12345 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:0:0:0:0:2:2:1,53 +> zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:1,10053 > 10:3:3:0:0:0:0:3,12345 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12346 > 10:1:0:0:0:0:0:0,23 +> zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:1,10023 > 10:3:3:0:0:0:0:3,12346 +< zx0 ip6/0 8 0 17 10:3:3:0:0:0:0:3,12345 > 10:0:0:0:0:2:2:1,53 +> zx0 ip6/0 8 0 17 10:0:0:0:0:2:2:1,10053 > 10:3:3:0:0:0:0:3,12345 +16 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,53 > 10:3:3:0:0:0:0:3,12345 +List of active MAP/Redirect filters: +rdr zx0 inet6 10:1:1::/112 -> 10::2:2:1/128 ip + +List of active sessions: +RDR 10::2:2:1 53 <- -> 10:1:1:: 53 [10:3:3::3 12345] +RDR 10::2:2:1 53 <- -> 10:1:1::1 53 [10:3:3::3 12345] +RDR 10::2:2:1 23 <- -> 10:1:1::1 23 [10:3:3::3 12345] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/n5 b/test/expected/n5 index 0e578b64bcfc8..423bf485008cb 100644 --- a/test/expected/n5 +++ b/test/expected/n5 @@ -1,330 +1,533 @@ -ip #0 20(20) 255 10.1.1.0 > 10.1.1.2 -ip #0 20(20) 255 10.2.2.2 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 -ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.1.1.2,1026 > 10.1.1.1,1025 -ip #0 20(20) 255 10.2.2.1 > 10.1.2.1 -ip #0 20(20) 255 10.2.2.2 > 10.1.2.1 -ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 -ip #0 20(20) 255 10.2.2.1 > 10.2.1.1 -ip #0 20(20) 255 10.2.2.2 > 10.2.1.1 -ip #0 20(20) 255 10.2.2.3 > 10.1.1.1 -ip #0 20(20) 255 10.2.3.4 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.1 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 -ip #0 20(20) 255 10.1.1.0 > 10.3.4.5 -ip #0 20(20) 255 10.1.1.1 > 10.3.4.5 -ip #0 20(20) 255 10.1.1.2 > 10.3.4.5 -ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,1025 -ip #0 48(20) 1 10.2.2.2 > 10.4.3.2 -ip #0 48(20) 1 10.4.3.2 > 10.1.1.1 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.3 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.5 -ip #0 20(20) 34 10.1.1.2 > 10.4.3.2 -ip #0 20(20) 34 10.4.3.2 > 10.3.4.4 -ip #0 20(20) 34 10.1.1.2 > 10.4.3.4 -ip #0 20(20) 34 10.4.3.4 > 10.3.4.5 -ip #0 20(20) 34 10.1.1.3 > 10.4.3.4 -ip #0 20(20) 34 10.4.3.4 > 10.3.4.6 -ip #0 20(20) 35 10.1.1.3 > 10.4.3.4 -ip #0 20(20) 35 10.4.3.4 > 10.3.4.7 -ip #0 40(20) 6 10.2.2.2,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.2.2.2,1025 > 10.1.1.2,1025 -ip #0 20(20) 0 10.1.1.0 > 10.1.1.2 -ip #0 20(20) 0 10.2.2.2 > 10.1.2.1 -ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.1.1.2,1026 > 10.1.1.1,1025 -ip #0 28(20) 17 10.1.1.2,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.1.1.3,2000 > 10.1.2.1,80 -ip #0 40(20) 6 10.1.1.3,2001 > 10.1.3.1,80 -ip #0 40(20) 6 10.1.1.3,2002 > 10.1.4.1,80 -ip #0 40(20) 6 10.1.1.3,2003 > 10.1.4.1,80 -ip #0 20(20) 0 10.1.1.1 > 10.1.1.2 -ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 -ip #0 20(20) 0 10.1.1.2 > 10.1.1.1 -ip #0 40(20) 6 10.2.2.2,1026 > 10.3.4.5,40000 -ip #0 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000 -ip #0 40(20) 6 10.2.2.2,1025 > 10.3.4.5,40000 -ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,40000 -ip #0 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001 -ip #0 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001 -ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 -ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 +> zx0 ip #0 20(20) 255 10.1.1.0 > 10.1.1.2 +> zx0 ip #0 20(20) 255 10.2.2.2 > 10.1.1.2 +> zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 +> zx0 ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.1.1.2,1026 > 10.1.1.1,1025 +> zx0 ip #0 20(20) 255 10.2.2.1 > 10.1.2.1 +> zx0 ip #0 20(20) 255 10.2.2.2 > 10.1.2.1 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.2.2.1 > 10.2.1.1 +< zx0 ip #0 20(20) 255 10.2.2.2 > 10.2.1.1 +< zx0 ip #0 20(20) 255 10.2.2.3 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.2.3.4 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.1.1.0 > 10.3.4.5 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.3.4.5 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.3.4.5 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,1025 +> zx0 ip #0 48(20) 1 10.2.2.2 > 10.4.3.2 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.1.1.1 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.3 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.5 +> zx0 ip #0 20(20) 34 10.1.1.2 > 10.4.3.2 +< zx0 ip #0 20(20) 34 10.4.3.2 > 10.3.4.4 +> zx0 ip #0 20(20) 34 10.1.1.2 > 10.4.3.4 +< zx0 ip #0 20(20) 34 10.4.3.4 > 10.3.4.5 +> zx0 ip #0 20(20) 34 10.1.1.3 > 10.4.3.4 +< zx0 ip #0 20(20) 34 10.4.3.4 > 10.3.4.6 +> zx0 ip #0 20(20) 35 10.1.1.3 > 10.4.3.4 +< zx0 ip #0 20(20) 35 10.4.3.4 > 10.3.4.7 +> zx0 ip #0 40(20) 6 10.2.2.2,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.2.2.2,1025 > 10.1.1.2,1025 +> zx0 ip #0 20(20) 0 10.1.1.0 > 10.1.1.2 +> zx0 ip #0 20(20) 0 10.2.2.2 > 10.1.2.1 +> zx0 ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.1.1.2,1026 > 10.1.1.1,1025 +> zx0 ip #0 28(20) 17 10.1.1.2,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.1.1.3,2000 > 10.1.2.1,80 +> zx0 ip #0 40(20) 6 10.1.1.3,2001 > 10.1.3.1,80 +> zx0 ip #0 40(20) 6 10.1.1.3,2002 > 10.1.4.1,80 +> zx0 ip #0 40(20) 6 10.1.1.3,2003 > 10.1.4.1,80 +< zx0 ip #0 20(20) 0 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 +< zx0 ip #0 20(20) 0 10.1.1.2 > 10.1.1.1 +> zx0 ip #0 40(20) 6 10.2.2.2,1026 > 10.3.4.5,40000 +< zx0 ip #0 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000 +> zx0 ip #0 40(20) 6 10.2.2.2,1025 > 10.3.4.5,40000 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,40000 +> zx0 ip #0 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001 +< zx0 ip #0 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001 +> zx0 ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 +< zx0 ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 +List of active MAP/Redirect filters: +map zx0 10.1.1.1/32 -> 10.2.2.2/32 + +List of active sessions: +MAP 10.1.1.1 1025 <- -> 10.2.2.2 1025 [10.3.4.5 40000] +MAP 10.1.1.1 1026 <- -> 10.2.2.2 1026 [10.3.4.5 40000] +MAP 10.1.1.1 <- -> 10.2.2.2 [10.1.2.1] +MAP 10.1.1.1 1025 <- -> 10.2.2.2 1025 [10.1.1.2 1025] +MAP 10.1.1.1 1025 <- -> 10.2.2.2 1025 [10.1.1.1 1025] +MAP 10.1.1.1 <- -> 10.2.2.2 [10.4.3.2] +MAP 10.1.1.1 <- -> 10.2.2.2 [10.1.1.2] + +Hostmap table: +10.1.1.1,10.3.4.5 -> 10.2.2.2,0.0.0.0 (use = 2) +10.1.1.1,10.1.2.1 -> 10.2.2.2,0.0.0.0 (use = 1) +10.1.1.1,10.1.1.1 -> 10.2.2.2,0.0.0.0 (use = 1) +10.1.1.1,10.4.3.2 -> 10.2.2.2,0.0.0.0 (use = 1) +10.1.1.1,10.1.1.2 -> 10.2.2.2,0.0.0.0 (use = 2) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- -ip #0 20(20) 255 10.3.4.5 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 -ip #0 20(20) 255 10.3.4.5 > 10.1.1.1 -ip #0 40(20) 6 10.3.4.5,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.3.4.5,1026 > 10.1.1.1,1025 -ip #0 20(20) 255 10.2.2.1 > 10.1.2.1 -ip #0 20(20) 255 10.2.2.2 > 10.1.2.1 -ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 -ip #0 20(20) 255 10.2.2.1 > 10.2.1.1 -ip #0 20(20) 255 10.2.2.2 > 10.2.1.1 -ip #0 20(20) 255 10.2.2.3 > 10.1.1.1 -ip #0 20(20) 255 10.2.3.4 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.1 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.2 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.0 > 10.3.4.5 -ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.0 -ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 -ip #0 48(20) 1 10.1.1.1 > 10.4.3.2 -ip #0 48(20) 1 10.4.3.2 > 10.2.2.2 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.3 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.5 -ip #0 20(20) 34 10.1.1.2 > 10.4.3.2 -ip #0 20(20) 34 10.4.3.2 > 10.3.4.4 -ip #0 20(20) 34 10.1.1.2 > 10.4.3.4 -ip #0 20(20) 34 10.4.3.4 > 10.3.4.5 -ip #0 20(20) 34 10.1.1.3 > 10.4.3.4 -ip #0 20(20) 34 10.4.3.4 > 10.3.4.6 -ip #0 20(20) 35 10.1.1.3 > 10.4.3.4 -ip #0 20(20) 35 10.4.3.4 > 10.3.4.7 -ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.3.4.5,1025 > 10.1.1.2,1025 -ip #0 20(20) 0 10.3.4.5 > 10.1.1.2 -ip #0 20(20) 0 10.3.4.5 > 10.1.2.1 -ip #0 40(20) 6 10.3.4.5,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.3.4.5,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.3.4.5,1026 > 10.1.1.1,1025 -ip #0 28(20) 17 10.3.4.5,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.3.4.5,2000 > 10.1.2.1,80 -ip #0 40(20) 6 10.3.4.5,2001 > 10.1.3.1,80 -ip #0 40(20) 6 10.3.4.5,2002 > 10.1.4.1,80 -ip #0 40(20) 6 10.3.4.5,2003 > 10.1.4.1,80 -ip #0 20(20) 0 10.1.1.1 > 10.1.1.2 -ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 -ip #0 20(20) 0 10.1.1.2 > 10.1.1.1 -ip #0 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000 -ip #0 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000 -ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,40000 -ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,40000 -ip #0 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001 -ip #0 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001 -ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 -ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 +> zx0 ip #0 20(20) 255 10.3.4.5 > 10.1.1.2 +15 +> zx0 ip #0 20(20) 255 10.3.4.5 > 10.1.1.1 +> zx0 ip #0 40(20) 6 10.3.4.5,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.3.4.5,1026 > 10.1.1.1,1025 +> zx0 ip #0 20(20) 255 10.2.2.1 > 10.1.2.1 +> zx0 ip #0 20(20) 255 10.2.2.2 > 10.1.2.1 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.2.2.1 > 10.2.1.1 +< zx0 ip #0 20(20) 255 10.2.2.2 > 10.2.1.1 +< zx0 ip #0 20(20) 255 10.2.2.3 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.2.3.4 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.0 > 10.3.4.5 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.0 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 +> zx0 ip #0 48(20) 1 10.1.1.1 > 10.4.3.2 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.2.2.2 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.3 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.5 +> zx0 ip #0 20(20) 34 10.1.1.2 > 10.4.3.2 +< zx0 ip #0 20(20) 34 10.4.3.2 > 10.3.4.4 +> zx0 ip #0 20(20) 34 10.1.1.2 > 10.4.3.4 +< zx0 ip #0 20(20) 34 10.4.3.4 > 10.3.4.5 +> zx0 ip #0 20(20) 34 10.1.1.3 > 10.4.3.4 +< zx0 ip #0 20(20) 34 10.4.3.4 > 10.3.4.6 +> zx0 ip #0 20(20) 35 10.1.1.3 > 10.4.3.4 +< zx0 ip #0 20(20) 35 10.4.3.4 > 10.3.4.7 +15 +> zx0 ip #0 40(20) 6 10.3.4.5,1025 > 10.1.1.2,1025 +> zx0 ip #0 20(20) 0 10.3.4.5 > 10.1.1.2 +> zx0 ip #0 20(20) 0 10.3.4.5 > 10.1.2.1 +> zx0 ip #0 40(20) 6 10.3.4.5,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.3.4.5,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.3.4.5,1026 > 10.1.1.1,1025 +> zx0 ip #0 28(20) 17 10.3.4.5,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.3.4.5,2000 > 10.1.2.1,80 +> zx0 ip #0 40(20) 6 10.3.4.5,2001 > 10.1.3.1,80 +> zx0 ip #0 40(20) 6 10.3.4.5,2002 > 10.1.4.1,80 +> zx0 ip #0 40(20) 6 10.3.4.5,2003 > 10.1.4.1,80 +< zx0 ip #0 20(20) 0 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 +< zx0 ip #0 20(20) 0 10.1.1.2 > 10.1.1.1 +> zx0 ip #0 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000 +< zx0 ip #0 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000 +> zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,40000 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,40000 +> zx0 ip #0 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001 +< zx0 ip #0 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001 +> zx0 ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 +< zx0 ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 +List of active MAP/Redirect filters: +map zx0 from 10.1.1.0/24 to 10.1.0.0/16 -> 10.3.4.5/32 + +List of active sessions: +MAP 10.1.1.3 2003 <- -> 10.3.4.5 2003 [10.1.4.1 80] +MAP 10.1.1.3 2002 <- -> 10.3.4.5 2002 [10.1.4.1 80] +MAP 10.1.1.3 2001 <- -> 10.3.4.5 2001 [10.1.3.1 80] +MAP 10.1.1.3 2000 <- -> 10.3.4.5 2000 [10.1.2.1 80] +MAP 10.1.1.2 1025 <- -> 10.3.4.5 1025 [10.1.1.1 1025] +MAP 10.1.1.1 <- -> 10.3.4.5 [10.1.2.1] +MAP 10.1.1.0 <- -> 10.3.4.5 [10.1.1.2] +MAP 10.1.1.1 1025 <- -> 10.3.4.5 1025 [10.1.1.2 1025] +MAP 10.1.1.2 1026 <- -> 10.3.4.5 1026 [10.1.1.1 1025] +MAP 10.1.1.2 1025 <- -> 10.3.4.5 1025 [10.1.1.1 1025] +MAP 10.1.1.2 <- -> 10.3.4.5 [10.1.1.1] +MAP 10.1.1.0 <- -> 10.3.4.5 [10.1.1.2] + +Hostmap table: +10.1.1.3,10.1.4.1 -> 10.3.4.5,0.0.0.0 (use = 2) +10.1.1.3,10.1.3.1 -> 10.3.4.5,0.0.0.0 (use = 1) +10.1.1.3,10.1.2.1 -> 10.3.4.5,0.0.0.0 (use = 1) +10.1.1.1,10.1.2.1 -> 10.3.4.5,0.0.0.0 (use = 1) +10.1.1.1,10.1.1.2 -> 10.3.4.5,0.0.0.0 (use = 1) +10.1.1.2,10.1.1.1 -> 10.3.4.5,0.0.0.0 (use = 4) +10.1.1.0,10.1.1.2 -> 10.3.4.5,0.0.0.0 (use = 2) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- -ip #0 20(20) 255 10.1.1.0 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 -ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.1.1.2,1026 > 10.1.1.1,1025 -ip #0 20(20) 255 10.2.2.1 > 10.1.2.1 -ip #0 20(20) 255 10.2.2.2 > 10.1.2.1 -ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 -ip #0 20(20) 255 10.2.2.1 > 10.2.1.1 -ip #0 20(20) 255 10.2.2.2 > 10.2.1.1 -ip #0 20(20) 255 10.2.2.3 > 10.1.1.1 -ip #0 20(20) 255 10.2.3.4 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.1 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.2 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.0 > 10.3.4.5 -ip #0 20(20) 255 10.1.1.1 > 10.3.4.5 -ip #0 20(20) 255 10.1.1.2 > 10.3.4.5 -ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,1025 -ip #0 48(20) 1 10.3.4.1 > 10.4.3.2 -ip #0 48(20) 1 10.4.3.2 > 10.2.2.2 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.3 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.5 -ip #0 20(20) 34 10.3.4.1 > 10.4.3.2 -ip #0 20(20) 34 10.4.3.2 > 10.3.4.4 -ip #0 20(20) 34 10.3.4.1 > 10.4.3.4 -ip #0 20(20) 34 10.4.3.4 > 10.3.4.5 -ip #0 20(20) 34 10.3.4.2 > 10.4.3.4 -ip #0 20(20) 34 10.4.3.4 > 10.3.4.6 -ip #0 20(20) 35 10.3.4.2 > 10.4.3.4 -ip #0 20(20) 35 10.4.3.4 > 10.3.4.7 -ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 -ip #0 20(20) 0 10.1.1.0 > 10.1.1.2 -ip #0 20(20) 0 10.1.1.1 > 10.1.2.1 -ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.1.1.2,1026 > 10.1.1.1,1025 -ip #0 28(20) 17 10.1.1.2,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.1.1.3,2000 > 10.1.2.1,80 -ip #0 40(20) 6 10.1.1.3,2001 > 10.1.3.1,80 -ip #0 40(20) 6 10.1.1.3,2002 > 10.1.4.1,80 -ip #0 40(20) 6 10.1.1.3,2003 > 10.1.4.1,80 -ip #0 20(20) 0 10.1.1.1 > 10.1.1.2 -ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 -ip #0 20(20) 0 10.1.1.2 > 10.1.1.1 -ip #0 40(20) 6 10.3.4.3,1026 > 10.3.4.5,40000 -ip #0 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000 -ip #0 40(20) 6 10.3.4.3,1025 > 10.3.4.5,40000 -ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,40000 -ip #0 28(20) 17 10.3.4.3,1025 > 10.3.4.5,40001 -ip #0 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001 -ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 -ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 +> zx0 ip #0 20(20) 255 10.1.1.0 > 10.1.1.2 +> zx0 ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 +> zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 +> zx0 ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.1.1.2,1026 > 10.1.1.1,1025 +> zx0 ip #0 20(20) 255 10.2.2.1 > 10.1.2.1 +> zx0 ip #0 20(20) 255 10.2.2.2 > 10.1.2.1 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.2.2.1 > 10.2.1.1 +< zx0 ip #0 20(20) 255 10.2.2.2 > 10.2.1.1 +< zx0 ip #0 20(20) 255 10.2.2.3 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.2.3.4 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.0 > 10.3.4.5 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.3.4.5 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.3.4.5 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,1025 +> zx0 ip #0 48(20) 1 10.3.4.1 > 10.4.3.2 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.2.2.2 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.3 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.5 +> zx0 ip #0 20(20) 34 10.3.4.1 > 10.4.3.2 +< zx0 ip #0 20(20) 34 10.4.3.2 > 10.3.4.4 +> zx0 ip #0 20(20) 34 10.3.4.1 > 10.4.3.4 +< zx0 ip #0 20(20) 34 10.4.3.4 > 10.3.4.5 +> zx0 ip #0 20(20) 34 10.3.4.2 > 10.4.3.4 +< zx0 ip #0 20(20) 34 10.4.3.4 > 10.3.4.6 +> zx0 ip #0 20(20) 35 10.3.4.2 > 10.4.3.4 +< zx0 ip #0 20(20) 35 10.4.3.4 > 10.3.4.7 +> zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 +> zx0 ip #0 20(20) 0 10.1.1.0 > 10.1.1.2 +> zx0 ip #0 20(20) 0 10.1.1.1 > 10.1.2.1 +> zx0 ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.1.1.2,1026 > 10.1.1.1,1025 +> zx0 ip #0 28(20) 17 10.1.1.2,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.1.1.3,2000 > 10.1.2.1,80 +> zx0 ip #0 40(20) 6 10.1.1.3,2001 > 10.1.3.1,80 +> zx0 ip #0 40(20) 6 10.1.1.3,2002 > 10.1.4.1,80 +> zx0 ip #0 40(20) 6 10.1.1.3,2003 > 10.1.4.1,80 +< zx0 ip #0 20(20) 0 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 +< zx0 ip #0 20(20) 0 10.1.1.2 > 10.1.1.1 +> zx0 ip #0 40(20) 6 10.3.4.3,1026 > 10.3.4.5,40000 +< zx0 ip #0 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000 +> zx0 ip #0 40(20) 6 10.3.4.3,1025 > 10.3.4.5,40000 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,40000 +> zx0 ip #0 28(20) 17 10.3.4.3,1025 > 10.3.4.5,40001 +< zx0 ip #0 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001 +> zx0 ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 +< zx0 ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 +List of active MAP/Redirect filters: +map zx0 from 10.1.1.0/24 ! to 10.1.0.0/16 -> 10.3.4.0/24 + +List of active sessions: +MAP 10.1.1.2 1025 <- -> 10.3.4.3 1025 [10.3.4.5 40001] +MAP 10.1.1.1 1025 <- -> 10.3.4.3 1025 [10.3.4.5 40000] +MAP 10.1.1.1 1026 <- -> 10.3.4.3 1026 [10.3.4.5 40000] +MAP 10.1.1.3 <- -> 10.3.4.2 [10.4.3.4] +MAP 10.1.1.3 <- -> 10.3.4.2 [10.4.3.4] +MAP 10.1.1.2 <- -> 10.3.4.1 [10.4.3.4] +MAP 10.1.1.2 <- -> 10.3.4.1 [10.4.3.2] +MAP 10.1.1.1 <- -> 10.3.4.1 [10.4.3.2] + +Hostmap table: +10.1.1.2,10.3.4.5 -> 10.3.4.3,0.0.0.0 (use = 1) +10.1.1.1,10.3.4.5 -> 10.3.4.3,0.0.0.0 (use = 2) +10.1.1.3,10.4.3.4 -> 10.3.4.2,0.0.0.0 (use = 2) +10.1.1.2,10.4.3.4 -> 10.3.4.1,0.0.0.0 (use = 1) +10.1.1.2,10.4.3.2 -> 10.3.4.1,0.0.0.0 (use = 1) +10.1.1.1,10.4.3.2 -> 10.3.4.1,0.0.0.0 (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- -ip #0 20(20) 255 10.1.1.0 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 -ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.1.1.2,1026 > 10.1.1.1,1025 -ip #0 20(20) 255 10.2.2.1 > 10.1.2.1 -ip #0 20(20) 255 10.2.2.2 > 10.1.2.1 -ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 -ip #0 20(20) 255 10.2.2.1 > 10.2.1.1 -ip #0 20(20) 255 10.2.2.2 > 10.2.1.1 -ip #0 20(20) 255 10.2.2.3 > 10.1.1.1 -ip #0 20(20) 255 10.2.3.4 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.1 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.2 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.0 > 10.3.4.5 -ip #0 20(20) 255 10.1.1.1 > 10.3.4.5 -ip #0 20(20) 255 10.1.1.2 > 10.3.4.5 -ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,1025 -ip #0 48(20) 1 10.1.1.1 > 10.4.3.2 -ip #0 48(20) 1 10.4.3.2 > 10.2.2.2 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.3 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.5 -ip #0 20(20) 34 10.1.1.2 > 10.4.3.2 -ip #0 20(20) 34 10.4.3.2 > 10.3.4.4 -ip #0 20(20) 34 10.1.1.2 > 10.4.3.4 -ip #0 20(20) 34 10.4.3.4 > 10.3.4.5 -ip #0 20(20) 34 10.1.1.3 > 10.4.3.4 -ip #0 20(20) 34 10.4.3.4 > 10.3.4.6 -ip #0 20(20) 35 10.1.1.3 > 10.4.3.4 -ip #0 20(20) 35 10.4.3.4 > 10.3.4.7 -ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 -ip #0 20(20) 0 10.1.1.0 > 10.1.1.2 -ip #0 20(20) 0 10.1.1.1 > 10.1.2.1 -ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.1.1.2,1026 > 10.1.1.1,1025 -ip #0 28(20) 17 10.3.4.5,10000 > 10.1.1.1,1025 -ip #0 40(20) 6 10.1.1.3,2000 > 10.1.2.1,80 -ip #0 40(20) 6 10.1.1.3,2001 > 10.1.3.1,80 -ip #0 40(20) 6 10.1.1.3,2002 > 10.1.4.1,80 -ip #0 40(20) 6 10.1.1.3,2003 > 10.1.4.1,80 -ip #0 20(20) 0 10.1.1.1 > 10.1.1.2 -ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 -ip #0 20(20) 0 10.1.1.2 > 10.1.1.1 -ip #0 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000 -ip #0 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000 -ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,40000 -ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,40000 -ip #0 28(20) 17 10.3.4.5,10001 > 10.3.4.5,40001 -ip #0 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001 -ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 -ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 +> zx0 ip #0 20(20) 255 10.1.1.0 > 10.1.1.2 +> zx0 ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 +> zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 +> zx0 ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.1.1.2,1026 > 10.1.1.1,1025 +> zx0 ip #0 20(20) 255 10.2.2.1 > 10.1.2.1 +> zx0 ip #0 20(20) 255 10.2.2.2 > 10.1.2.1 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.2.2.1 > 10.2.1.1 +< zx0 ip #0 20(20) 255 10.2.2.2 > 10.2.1.1 +< zx0 ip #0 20(20) 255 10.2.2.3 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.2.3.4 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.0 > 10.3.4.5 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.3.4.5 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.3.4.5 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,1025 +> zx0 ip #0 48(20) 1 10.1.1.1 > 10.4.3.2 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.2.2.2 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.3 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.5 +> zx0 ip #0 20(20) 34 10.1.1.2 > 10.4.3.2 +< zx0 ip #0 20(20) 34 10.4.3.2 > 10.3.4.4 +> zx0 ip #0 20(20) 34 10.1.1.2 > 10.4.3.4 +< zx0 ip #0 20(20) 34 10.4.3.4 > 10.3.4.5 +> zx0 ip #0 20(20) 34 10.1.1.3 > 10.4.3.4 +< zx0 ip #0 20(20) 34 10.4.3.4 > 10.3.4.6 +> zx0 ip #0 20(20) 35 10.1.1.3 > 10.4.3.4 +< zx0 ip #0 20(20) 35 10.4.3.4 > 10.3.4.7 +> zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 +> zx0 ip #0 20(20) 0 10.1.1.0 > 10.1.1.2 +> zx0 ip #0 20(20) 0 10.1.1.1 > 10.1.2.1 +> zx0 ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.1.1.2,1025 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.1.1.2,1026 > 10.1.1.1,1025 +> zx0 ip #0 28(20) 17 10.3.4.5,10000 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.1.1.3,2000 > 10.1.2.1,80 +> zx0 ip #0 40(20) 6 10.1.1.3,2001 > 10.1.3.1,80 +> zx0 ip #0 40(20) 6 10.1.1.3,2002 > 10.1.4.1,80 +> zx0 ip #0 40(20) 6 10.1.1.3,2003 > 10.1.4.1,80 +< zx0 ip #0 20(20) 0 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 +< zx0 ip #0 20(20) 0 10.1.1.2 > 10.1.1.1 +> zx0 ip #0 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000 +< zx0 ip #0 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000 +> zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,40000 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,40000 +> zx0 ip #0 28(20) 17 10.3.4.5,10001 > 10.3.4.5,40001 +< zx0 ip #0 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001 +> zx0 ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 +< zx0 ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 +List of active MAP/Redirect filters: +map zx0 10.1.1.0/24 -> 10.3.4.5/32 portmap udp 10000:20000 sequential + +List of active sessions: +MAP 10.1.1.2 1025 <- -> 10.3.4.5 10001 [10.3.4.5 40001] +MAP 10.1.1.2 1025 <- -> 10.3.4.5 10000 [10.1.1.1 1025] + +Hostmap table: +10.1.1.2,10.3.4.5 -> 10.3.4.5,0.0.0.0 (use = 1) +10.1.1.2,10.1.1.1 -> 10.3.4.5,0.0.0.0 (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- -ip #0 20(20) 255 10.1.1.0 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 -ip #0 40(20) 6 10.3.4.1,10000 > 10.1.1.1,1025 -ip #0 40(20) 6 10.3.4.1,10001 > 10.1.1.1,1025 -ip #0 20(20) 255 10.2.2.1 > 10.1.2.1 -ip #0 20(20) 255 10.2.2.2 > 10.1.2.1 -ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 -ip #0 20(20) 255 10.2.2.1 > 10.2.1.1 -ip #0 20(20) 255 10.2.2.2 > 10.2.1.1 -ip #0 20(20) 255 10.2.2.3 > 10.1.1.1 -ip #0 20(20) 255 10.2.3.4 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.1 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.2 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.0 > 10.3.4.5 -ip #0 20(20) 255 10.1.1.1 > 10.3.4.5 -ip #0 20(20) 255 10.1.1.2 > 10.3.4.5 -ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,1025 -ip #0 48(20) 1 10.1.1.1 > 10.4.3.2 -ip #0 48(20) 1 10.4.3.2 > 10.2.2.2 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.3 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.5 -ip #0 20(20) 34 10.1.1.2 > 10.4.3.2 -ip #0 20(20) 34 10.4.3.2 > 10.3.4.4 -ip #0 20(20) 34 10.1.1.2 > 10.4.3.4 -ip #0 20(20) 34 10.4.3.4 > 10.3.4.5 -ip #0 20(20) 34 10.1.1.3 > 10.4.3.4 -ip #0 20(20) 34 10.4.3.4 > 10.3.4.6 -ip #0 20(20) 35 10.1.1.3 > 10.4.3.4 -ip #0 20(20) 35 10.4.3.4 > 10.3.4.7 -ip #0 40(20) 6 10.3.4.1,10002 > 10.1.1.1,1025 -ip #0 40(20) 6 10.3.4.1,10003 > 10.1.1.2,1025 -ip #0 20(20) 0 10.1.1.0 > 10.1.1.2 -ip #0 20(20) 0 10.1.1.1 > 10.1.2.1 -ip #0 40(20) 6 10.3.4.1,10000 > 10.1.1.1,1025 -ip #0 40(20) 6 10.3.4.1,10000 > 10.1.1.1,1025 -ip #0 40(20) 6 10.3.4.1,10001 > 10.1.1.1,1025 -ip #0 28(20) 17 10.3.4.1,10004 > 10.1.1.1,1025 -ip #0 40(20) 6 10.3.4.1,10005 > 10.1.2.1,80 -ip #0 40(20) 6 10.3.4.1,10006 > 10.1.3.1,80 -ip #0 40(20) 6 10.3.4.1,10007 > 10.1.4.1,80 -ip #0 40(20) 6 10.3.4.1,10008 > 10.1.4.1,80 -ip #0 20(20) 0 10.1.1.1 > 10.1.1.2 -ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 -ip #0 20(20) 0 10.1.1.2 > 10.1.1.1 -ip #0 40(20) 6 10.3.4.1,10009 > 10.3.4.5,40000 -ip #0 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000 -ip #0 40(20) 6 10.3.4.1,10010 > 10.3.4.5,40000 -ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,40000 -ip #0 28(20) 17 10.3.4.1,10011 > 10.3.4.5,40001 -ip #0 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001 -ip #0 40(20) 6 10.3.4.1,10012 > 10.3.4.5,40001 -ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 +> zx0 ip #0 20(20) 255 10.1.1.0 > 10.1.1.2 +> zx0 ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 +> zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 +> zx0 ip #0 40(20) 6 10.3.4.1,10000 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.3.4.1,10001 > 10.1.1.1,1025 +> zx0 ip #0 20(20) 255 10.2.2.1 > 10.1.2.1 +> zx0 ip #0 20(20) 255 10.2.2.2 > 10.1.2.1 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.2.2.1 > 10.2.1.1 +< zx0 ip #0 20(20) 255 10.2.2.2 > 10.2.1.1 +< zx0 ip #0 20(20) 255 10.2.2.3 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.2.3.4 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.0 > 10.3.4.5 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.3.4.5 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.3.4.5 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,1025 +> zx0 ip #0 48(20) 1 10.1.1.1 > 10.4.3.2 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.2.2.2 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.3 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.5 +> zx0 ip #0 20(20) 34 10.1.1.2 > 10.4.3.2 +< zx0 ip #0 20(20) 34 10.4.3.2 > 10.3.4.4 +> zx0 ip #0 20(20) 34 10.1.1.2 > 10.4.3.4 +< zx0 ip #0 20(20) 34 10.4.3.4 > 10.3.4.5 +> zx0 ip #0 20(20) 34 10.1.1.3 > 10.4.3.4 +< zx0 ip #0 20(20) 34 10.4.3.4 > 10.3.4.6 +> zx0 ip #0 20(20) 35 10.1.1.3 > 10.4.3.4 +< zx0 ip #0 20(20) 35 10.4.3.4 > 10.3.4.7 +> zx0 ip #0 40(20) 6 10.3.4.1,10002 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.3.4.1,10003 > 10.1.1.2,1025 +> zx0 ip #0 20(20) 0 10.1.1.0 > 10.1.1.2 +> zx0 ip #0 20(20) 0 10.1.1.1 > 10.1.2.1 +> zx0 ip #0 40(20) 6 10.3.4.1,10000 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.3.4.1,10000 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.3.4.1,10001 > 10.1.1.1,1025 +> zx0 ip #0 28(20) 17 10.3.4.1,10004 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.3.4.1,10005 > 10.1.2.1,80 +> zx0 ip #0 40(20) 6 10.3.4.1,10006 > 10.1.3.1,80 +> zx0 ip #0 40(20) 6 10.3.4.1,10007 > 10.1.4.1,80 +> zx0 ip #0 40(20) 6 10.3.4.1,10008 > 10.1.4.1,80 +< zx0 ip #0 20(20) 0 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 +< zx0 ip #0 20(20) 0 10.1.1.2 > 10.1.1.1 +> zx0 ip #0 40(20) 6 10.3.4.1,10009 > 10.3.4.5,40000 +< zx0 ip #0 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000 +> zx0 ip #0 40(20) 6 10.3.4.1,10010 > 10.3.4.5,40000 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,40000 +> zx0 ip #0 28(20) 17 10.3.4.1,10011 > 10.3.4.5,40001 +< zx0 ip #0 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001 +> zx0 ip #0 40(20) 6 10.3.4.1,10012 > 10.3.4.5,40001 +< zx0 ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 +List of active MAP/Redirect filters: +map zx0 10.1.0.0/16 -> 10.3.4.0/24 portmap tcp/udp 10000:20000 sequential + +List of active sessions: +MAP 10.1.2.1 80 <- -> 10.3.4.1 10012 [10.3.4.5 40001] +MAP 10.1.1.2 1025 <- -> 10.3.4.1 10011 [10.3.4.5 40001] +MAP 10.1.1.1 1025 <- -> 10.3.4.1 10010 [10.3.4.5 40000] +MAP 10.1.1.1 1026 <- -> 10.3.4.1 10009 [10.3.4.5 40000] +MAP 10.1.1.3 2003 <- -> 10.3.4.1 10008 [10.1.4.1 80] +MAP 10.1.1.3 2002 <- -> 10.3.4.1 10007 [10.1.4.1 80] +MAP 10.1.1.3 2001 <- -> 10.3.4.1 10006 [10.1.3.1 80] +MAP 10.1.1.3 2000 <- -> 10.3.4.1 10005 [10.1.2.1 80] +MAP 10.1.1.2 1025 <- -> 10.3.4.1 10004 [10.1.1.1 1025] +MAP 10.1.1.1 1025 <- -> 10.3.4.1 10003 [10.1.1.2 1025] +MAP 10.1.1.1 1025 <- -> 10.3.4.1 10002 [10.1.1.1 1025] +MAP 10.1.1.2 1026 <- -> 10.3.4.1 10001 [10.1.1.1 1025] +MAP 10.1.1.2 1025 <- -> 10.3.4.1 10000 [10.1.1.1 1025] + +Hostmap table: +10.1.2.1,10.3.4.5 -> 10.3.4.1,0.0.0.0 (use = 1) +10.1.1.2,10.3.4.5 -> 10.3.4.1,0.0.0.0 (use = 1) +10.1.1.1,10.3.4.5 -> 10.3.4.1,0.0.0.0 (use = 2) +10.1.1.3,10.1.4.1 -> 10.3.4.1,0.0.0.0 (use = 2) +10.1.1.3,10.1.3.1 -> 10.3.4.1,0.0.0.0 (use = 1) +10.1.1.3,10.1.2.1 -> 10.3.4.1,0.0.0.0 (use = 1) +10.1.1.1,10.1.1.2 -> 10.3.4.1,0.0.0.0 (use = 1) +10.1.1.1,10.1.1.1 -> 10.3.4.1,0.0.0.0 (use = 1) +10.1.1.2,10.1.1.1 -> 10.3.4.1,0.0.0.0 (use = 3) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- -ip #0 20(20) 255 10.1.1.0 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 -ip #0 40(20) 6 10.3.4.5,40000 > 10.1.1.1,1025 -ip #0 40(20) 6 10.3.4.5,40001 > 10.1.1.1,1025 -ip #0 20(20) 255 10.2.2.1 > 10.1.2.1 -ip #0 20(20) 255 10.2.2.2 > 10.1.2.1 -ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 -ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 -ip #0 20(20) 255 10.2.2.1 > 10.2.1.1 -ip #0 20(20) 255 10.2.2.2 > 10.2.1.1 -ip #0 20(20) 255 10.2.2.3 > 10.1.1.1 -ip #0 20(20) 255 10.2.3.4 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.1 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.2 > 10.2.2.2 -ip #0 20(20) 255 10.1.1.0 > 10.3.4.5 -ip #0 20(20) 255 10.1.1.1 > 10.3.4.5 -ip #0 20(20) 255 10.1.1.2 > 10.3.4.5 -ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,1025 -ip #0 48(20) 1 10.1.1.1 > 10.4.3.2 -ip #0 48(20) 1 10.4.3.2 > 10.2.2.2 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.3 -ip #0 48(20) 1 10.4.3.2 > 10.3.4.5 -ip #0 20(20) 34 10.1.1.2 > 10.4.3.2 -ip #0 20(20) 34 10.4.3.2 > 10.3.4.4 -ip #0 20(20) 34 10.1.1.2 > 10.4.3.4 -ip #0 20(20) 34 10.4.3.4 > 10.3.4.5 -ip #0 20(20) 34 10.1.1.3 > 10.4.3.4 -ip #0 20(20) 34 10.4.3.4 > 10.3.4.6 -ip #0 20(20) 35 10.1.1.3 > 10.4.3.4 -ip #0 20(20) 35 10.4.3.4 > 10.3.4.7 -ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.1,1025 -ip #0 40(20) 6 10.3.4.5,40000 > 10.1.1.2,1025 -ip #0 20(20) 0 10.1.1.0 > 10.1.1.2 -ip #0 20(20) 0 10.1.1.1 > 10.1.2.1 -ip #0 40(20) 6 10.3.4.5,40000 > 10.1.1.1,1025 -ip #0 40(20) 6 10.3.4.5,40000 > 10.1.1.1,1025 -ip #0 40(20) 6 10.3.4.5,40001 > 10.1.1.1,1025 -ip #0 28(20) 17 10.3.4.5,40001 > 10.1.1.1,1025 -ip #0 40(20) 6 10.3.4.5,40000 > 10.1.2.1,80 -ip #0 40(20) 6 10.3.4.5,40001 > 10.1.3.1,80 -ip #0 40(20) 6 10.3.4.5,40000 > 10.1.4.1,80 -ip #0 40(20) 6 10.3.4.5,40001 > 10.1.4.1,80 -ip #0 20(20) 0 10.1.1.1 > 10.1.1.2 -ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 -ip #0 20(20) 0 10.1.1.2 > 10.1.1.1 -ip #0 40(20) 6 10.3.4.5,40000 > 10.3.4.5,40000 -ip #0 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000 -ip #0 40(20) 6 10.3.4.5,40001 > 10.3.4.5,40000 -ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 -ip #0 28(20) 17 10.3.4.5,40000 > 10.3.4.5,40001 -ip #0 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001 -ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 -ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 +> zx0 ip #0 20(20) 255 10.1.1.0 > 10.1.1.2 +> zx0 ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 +> zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 +> zx0 ip #0 40(20) 6 10.3.4.5,40000 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.3.4.5,40001 > 10.1.1.1,1025 +> zx0 ip #0 20(20) 255 10.2.2.1 > 10.1.2.1 +> zx0 ip #0 20(20) 255 10.2.2.2 > 10.1.2.1 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.2.2.1 > 10.2.1.1 +< zx0 ip #0 20(20) 255 10.2.2.2 > 10.2.1.1 +< zx0 ip #0 20(20) 255 10.2.2.3 > 10.1.1.1 +< zx0 ip #0 20(20) 255 10.2.3.4 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.2.2.2 +< zx0 ip #0 20(20) 255 10.1.1.0 > 10.3.4.5 +< zx0 ip #0 20(20) 255 10.1.1.1 > 10.3.4.5 +< zx0 ip #0 20(20) 255 10.1.1.2 > 10.3.4.5 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.3.4.5,1025 +> zx0 ip #0 48(20) 1 10.1.1.1 > 10.4.3.2 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.2.2.2 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.3 +< zx0 ip #0 48(20) 1 10.4.3.2 > 10.3.4.5 +> zx0 ip #0 20(20) 34 10.1.1.2 > 10.4.3.2 +< zx0 ip #0 20(20) 34 10.4.3.2 > 10.3.4.4 +> zx0 ip #0 20(20) 34 10.1.1.2 > 10.4.3.4 +< zx0 ip #0 20(20) 34 10.4.3.4 > 10.3.4.5 +> zx0 ip #0 20(20) 34 10.1.1.3 > 10.4.3.4 +< zx0 ip #0 20(20) 34 10.4.3.4 > 10.3.4.6 +> zx0 ip #0 20(20) 35 10.1.1.3 > 10.4.3.4 +< zx0 ip #0 20(20) 35 10.4.3.4 > 10.3.4.7 +15 +> zx0 ip #0 40(20) 6 10.3.4.5,40000 > 10.1.1.2,1025 +> zx0 ip #0 20(20) 0 10.1.1.0 > 10.1.1.2 +> zx0 ip #0 20(20) 0 10.1.1.1 > 10.1.2.1 +> zx0 ip #0 40(20) 6 10.3.4.5,40000 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.3.4.5,40000 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.3.4.5,40001 > 10.1.1.1,1025 +> zx0 ip #0 28(20) 17 10.3.4.5,40001 > 10.1.1.1,1025 +> zx0 ip #0 40(20) 6 10.3.4.5,40000 > 10.1.2.1,80 +> zx0 ip #0 40(20) 6 10.3.4.5,40001 > 10.1.3.1,80 +> zx0 ip #0 40(20) 6 10.3.4.5,40000 > 10.1.4.1,80 +> zx0 ip #0 40(20) 6 10.3.4.5,40001 > 10.1.4.1,80 +< zx0 ip #0 20(20) 0 10.1.1.1 > 10.1.1.2 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 +< zx0 ip #0 20(20) 0 10.1.1.2 > 10.1.1.1 +> zx0 ip #0 40(20) 6 10.3.4.5,40000 > 10.3.4.5,40000 +< zx0 ip #0 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000 +> zx0 ip #0 40(20) 6 10.3.4.5,40001 > 10.3.4.5,40000 +< zx0 ip #0 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025 +> zx0 ip #0 28(20) 17 10.3.4.5,40000 > 10.3.4.5,40001 +< zx0 ip #0 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001 +> zx0 ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 +< zx0 ip #0 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001 +List of active MAP/Redirect filters: +map zx0 10.1.1.0/24 -> 10.3.4.5/32 portmap tcp/udp 40000:40001 sequential + +List of active sessions: +MAP 10.1.1.2 1025 <- -> 10.3.4.5 40000 [10.3.4.5 40001] +MAP 10.1.1.1 1025 <- -> 10.3.4.5 40001 [10.3.4.5 40000] +MAP 10.1.1.1 1026 <- -> 10.3.4.5 40000 [10.3.4.5 40000] +MAP 10.1.1.3 2003 <- -> 10.3.4.5 40001 [10.1.4.1 80] +MAP 10.1.1.3 2002 <- -> 10.3.4.5 40000 [10.1.4.1 80] +MAP 10.1.1.3 2001 <- -> 10.3.4.5 40001 [10.1.3.1 80] +MAP 10.1.1.3 2000 <- -> 10.3.4.5 40000 [10.1.2.1 80] +MAP 10.1.1.2 1025 <- -> 10.3.4.5 40001 [10.1.1.1 1025] +MAP 10.1.1.1 1025 <- -> 10.3.4.5 40000 [10.1.1.2 1025] +MAP 10.1.1.2 1026 <- -> 10.3.4.5 40001 [10.1.1.1 1025] +MAP 10.1.1.2 1025 <- -> 10.3.4.5 40000 [10.1.1.1 1025] + +Hostmap table: +10.1.1.2,10.3.4.5 -> 10.3.4.5,0.0.0.0 (use = 1) +10.1.1.1,10.3.4.5 -> 10.3.4.5,0.0.0.0 (use = 2) +10.1.1.3,10.1.4.1 -> 10.3.4.5,0.0.0.0 (use = 2) +10.1.1.3,10.1.3.1 -> 10.3.4.5,0.0.0.0 (use = 1) +10.1.1.3,10.1.2.1 -> 10.3.4.5,0.0.0.0 (use = 1) +10.1.1.1,10.1.1.2 -> 10.3.4.5,0.0.0.0 (use = 1) +10.1.1.2,10.1.1.1 -> 10.3.4.5,0.0.0.0 (use = 3) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- diff --git a/test/expected/n5_6 b/test/expected/n5_6 new file mode 100644 index 0000000000000..1e7bc8eff5adc --- /dev/null +++ b/test/expected/n5_6 @@ -0,0 +1,533 @@ +> zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:0 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:2,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:2,1026 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:1 > 10:1:2:0:0:0:0:1 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:1:2:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:1 > 10:0:0:0:0:2:1:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:0:0:0:0:2:1:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:3 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:3:4 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:0 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:0:0:0:0:3:4:5,1025 +> zx0 ip6/0 88 0 58 10:0:0:0:0:2:2:2 > 10:4:3:0:0:0:0:2 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:3 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:5 +> zx0 ip6/0 1 0 34 10:1:1:0:0:0:0:2 > 10:4:3:0:0:0:0:2 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:4 +> zx0 ip6/0 1 0 34 10:1:1:0:0:0:0:2 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:5 +> zx0 ip6/0 1 0 34 10:1:1:0:0:0:0:3 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:6 +> zx0 ip6/0 1 0 35 10:1:1:0:0:0:0:3 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 35 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:7 +> zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,1025 > 10:1:1:0:0:0:0:2,1025 +> zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:0 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 41 10:0:0:0:0:2:2:2 > 10:1:2:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:2,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:2,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:2,1026 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 8 0 17 10:1:1:0:0:0:0:2,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:3,2000 > 10:1:2:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:3,2001 > 10:1:3:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:3,2002 > 10:1:4:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:3,2003 > 10:1:4:0:0:0:0:1,80 +< zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:1:1:0:0:0:0:2,1025 +< zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,1026 > 10:0:0:0:0:3:4:5,40000 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1026 > 10:0:0:0:0:3:4:5,40000 +> zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,1025 > 10:0:0:0:0:3:4:5,40000 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:0:0:0:0:3:4:5,40000 +> zx0 ip6/0 8 0 17 10:1:1:0:0:0:0:2,1025 > 10:0:0:0:0:3:4:5,40001 +< zx0 ip6/0 8 0 17 10:1:1:0:0:0:0:2,1025 > 10:0:0:0:0:3:4:5,40001 +> zx0 ip6/0 20 0 6 10:1:2:0:0:0:0:1,80 > 10:0:0:0:0:3:4:5,40001 +< zx0 ip6/0 20 0 6 10:1:2:0:0:0:0:1,80 > 10:0:0:0:0:3:4:5,40001 +List of active MAP/Redirect filters: +map zx0 inet6 10:1:1::1/128 -> 10::2:2:2/128 + +List of active sessions: +MAP 10:1:1::1 1025 <- -> 10::2:2:2 1025 [10::3:4:5 40000] +MAP 10:1:1::1 1026 <- -> 10::2:2:2 1026 [10::3:4:5 40000] +MAP 10:1:1::1 <- -> 10::2:2:2 [10:1:2::1] +MAP 10:1:1::1 1025 <- -> 10::2:2:2 1025 [10:1:1::2 1025] +MAP 10:1:1::1 1025 <- -> 10::2:2:2 1025 [10:1:1::1 1025] +MAP 10:1:1::1 <- -> 10::2:2:2 [10:4:3::2] +MAP 10:1:1::1 <- -> 10::2:2:2 [10:1:1::2] + +Hostmap table: +10:1:1::1,10::3:4:5 -> 10::2:2:2,any (use = 2) +10:1:1::1,10:1:2::1 -> 10::2:2:2,any (use = 1) +10:1:1::1,10:1:1::1 -> 10::2:2:2,any (use = 1) +10:1:1::1,10:4:3::2 -> 10::2:2:2,any (use = 1) +10:1:1::1,10:1:1::2 -> 10::2:2:2,any (use = 2) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +> zx0 ip6/0 1 0 255 10:0:0:0:0:3:4:5 > 10:1:1:0:0:0:0:2 +16 +> zx0 ip6/0 1 0 255 10:0:0:0:0:3:4:5 > 10:1:1:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,1026 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:1 > 10:1:2:0:0:0:0:1 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:1:2:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:1 > 10:0:0:0:0:2:1:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:0:0:0:0:2:1:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:3 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:3:4 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:0 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:0 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:1:1:0:0:0:0:2,1025 +> zx0 ip6/0 88 0 58 10:1:1:0:0:0:0:1 > 10:4:3:0:0:0:0:2 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:3 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:5 +> zx0 ip6/0 1 0 34 10:1:1:0:0:0:0:2 > 10:4:3:0:0:0:0:2 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:4 +> zx0 ip6/0 1 0 34 10:1:1:0:0:0:0:2 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:5 +> zx0 ip6/0 1 0 34 10:1:1:0:0:0:0:3 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:6 +> zx0 ip6/0 1 0 35 10:1:1:0:0:0:0:3 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 35 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:7 +16 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,1025 > 10:1:1:0:0:0:0:2,1025 +> zx0 ip6/0 1 0 41 10:0:0:0:0:3:4:5 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 41 10:0:0:0:0:3:4:5 > 10:1:2:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,1026 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 8 0 17 10:0:0:0:0:3:4:5,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,2000 > 10:1:2:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,2001 > 10:1:3:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,2002 > 10:1:4:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,2003 > 10:1:4:0:0:0:0:1,80 +< zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:1:1:0:0:0:0:2,1025 +< zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1026 > 10:0:0:0:0:3:4:5,40000 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1026 > 10:0:0:0:0:3:4:5,40000 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:0:0:0:0:3:4:5,40000 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:0:0:0:0:3:4:5,40000 +> zx0 ip6/0 8 0 17 10:1:1:0:0:0:0:2,1025 > 10:0:0:0:0:3:4:5,40001 +< zx0 ip6/0 8 0 17 10:1:1:0:0:0:0:2,1025 > 10:0:0:0:0:3:4:5,40001 +> zx0 ip6/0 20 0 6 10:1:2:0:0:0:0:1,80 > 10:0:0:0:0:3:4:5,40001 +< zx0 ip6/0 20 0 6 10:1:2:0:0:0:0:1,80 > 10:0:0:0:0:3:4:5,40001 +List of active MAP/Redirect filters: +map zx0 inet6 from 10:1:1::/112 to 10:1::/32 -> 10::3:4:5/128 + +List of active sessions: +MAP 10:1:1::3 2003 <- -> 10::3:4:5 2003 [10:1:4::1 80] +MAP 10:1:1::3 2002 <- -> 10::3:4:5 2002 [10:1:4::1 80] +MAP 10:1:1::3 2001 <- -> 10::3:4:5 2001 [10:1:3::1 80] +MAP 10:1:1::3 2000 <- -> 10::3:4:5 2000 [10:1:2::1 80] +MAP 10:1:1::2 1025 <- -> 10::3:4:5 1025 [10:1:1::1 1025] +MAP 10:1:1::1 <- -> 10::3:4:5 [10:1:2::1] +MAP 10:1:1:: <- -> 10::3:4:5 [10:1:1::2] +MAP 10:1:1::1 1025 <- -> 10::3:4:5 1025 [10:1:1::2 1025] +MAP 10:1:1::2 1026 <- -> 10::3:4:5 1026 [10:1:1::1 1025] +MAP 10:1:1::2 1025 <- -> 10::3:4:5 1025 [10:1:1::1 1025] +MAP 10:1:1::2 <- -> 10::3:4:5 [10:1:1::1] +MAP 10:1:1:: <- -> 10::3:4:5 [10:1:1::2] + +Hostmap table: +10:1:1::3,10:1:4::1 -> 10::3:4:5,any (use = 2) +10:1:1::3,10:1:3::1 -> 10::3:4:5,any (use = 1) +10:1:1::3,10:1:2::1 -> 10::3:4:5,any (use = 1) +10:1:1::1,10:1:2::1 -> 10::3:4:5,any (use = 1) +10:1:1::1,10:1:1::2 -> 10::3:4:5,any (use = 1) +10:1:1::2,10:1:1::1 -> 10::3:4:5,any (use = 4) +10:1:1::,10:1:1::2 -> 10::3:4:5,any (use = 2) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +> zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:0 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:2,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:2,1026 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:1 > 10:1:2:0:0:0:0:1 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:1:2:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:1 > 10:0:0:0:0:2:1:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:0:0:0:0:2:1:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:3 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:3:4 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:0 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:0:0:0:0:3:4:5,1025 +> zx0 ip6/0 88 0 58 10:0:0:0:0:3:4:1 > 10:4:3:0:0:0:0:2 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:3 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:5 +> zx0 ip6/0 1 0 34 10:0:0:0:0:3:4:1 > 10:4:3:0:0:0:0:2 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:4 +> zx0 ip6/0 1 0 34 10:0:0:0:0:3:4:1 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:5 +> zx0 ip6/0 1 0 34 10:0:0:0:0:3:4:2 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:6 +> zx0 ip6/0 1 0 35 10:0:0:0:0:3:4:2 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 35 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:7 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:1:1:0:0:0:0:2,1025 +> zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:0 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:1 > 10:1:2:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:2,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:2,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:2,1026 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 8 0 17 10:1:1:0:0:0:0:2,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:3,2000 > 10:1:2:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:3,2001 > 10:1:3:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:3,2002 > 10:1:4:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:3,2003 > 10:1:4:0:0:0:0:1,80 +< zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:1:1:0:0:0:0:2,1025 +< zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:3,1026 > 10:0:0:0:0:3:4:5,40000 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1026 > 10:0:0:0:0:3:4:5,40000 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:3,1025 > 10:0:0:0:0:3:4:5,40000 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:0:0:0:0:3:4:5,40000 +> zx0 ip6/0 8 0 17 10:0:0:0:0:3:4:3,1025 > 10:0:0:0:0:3:4:5,40001 +< zx0 ip6/0 8 0 17 10:1:1:0:0:0:0:2,1025 > 10:0:0:0:0:3:4:5,40001 +> zx0 ip6/0 20 0 6 10:1:2:0:0:0:0:1,80 > 10:0:0:0:0:3:4:5,40001 +< zx0 ip6/0 20 0 6 10:1:2:0:0:0:0:1,80 > 10:0:0:0:0:3:4:5,40001 +List of active MAP/Redirect filters: +map zx0 inet6 from 10:1:1::/112 ! to 10:1::/32 -> 10::3:4:0/112 + +List of active sessions: +MAP 10:1:1::2 1025 <- -> 10::3:4:3 1025 [10::3:4:5 40001] +MAP 10:1:1::1 1025 <- -> 10::3:4:3 1025 [10::3:4:5 40000] +MAP 10:1:1::1 1026 <- -> 10::3:4:3 1026 [10::3:4:5 40000] +MAP 10:1:1::3 <- -> 10::3:4:2 [10:4:3::4] +MAP 10:1:1::3 <- -> 10::3:4:2 [10:4:3::4] +MAP 10:1:1::2 <- -> 10::3:4:1 [10:4:3::4] +MAP 10:1:1::2 <- -> 10::3:4:1 [10:4:3::2] +MAP 10:1:1::1 <- -> 10::3:4:1 [10:4:3::2] + +Hostmap table: +10:1:1::2,10::3:4:5 -> 10::3:4:3,any (use = 1) +10:1:1::1,10::3:4:5 -> 10::3:4:3,any (use = 2) +10:1:1::3,10:4:3::4 -> 10::3:4:2,any (use = 2) +10:1:1::2,10:4:3::4 -> 10::3:4:1,any (use = 1) +10:1:1::2,10:4:3::2 -> 10::3:4:1,any (use = 1) +10:1:1::1,10:4:3::2 -> 10::3:4:1,any (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +> zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:0 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:2,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:2,1026 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:1 > 10:1:2:0:0:0:0:1 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:1:2:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:1 > 10:0:0:0:0:2:1:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:0:0:0:0:2:1:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:3 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:3:4 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:0 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:0:0:0:0:3:4:5,1025 +> zx0 ip6/0 88 0 58 10:1:1:0:0:0:0:1 > 10:4:3:0:0:0:0:2 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:3 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:5 +> zx0 ip6/0 1 0 34 10:1:1:0:0:0:0:2 > 10:4:3:0:0:0:0:2 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:4 +> zx0 ip6/0 1 0 34 10:1:1:0:0:0:0:2 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:5 +> zx0 ip6/0 1 0 34 10:1:1:0:0:0:0:3 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:6 +> zx0 ip6/0 1 0 35 10:1:1:0:0:0:0:3 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 35 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:7 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:1:1:0:0:0:0:2,1025 +> zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:0 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:1 > 10:1:2:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:2,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:2,1025 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:2,1026 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 8 0 17 10:0:0:0:0:3:4:5,10000 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:3,2000 > 10:1:2:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:3,2001 > 10:1:3:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:3,2002 > 10:1:4:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:3,2003 > 10:1:4:0:0:0:0:1,80 +< zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:1:1:0:0:0:0:2,1025 +< zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1026 > 10:0:0:0:0:3:4:5,40000 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1026 > 10:0:0:0:0:3:4:5,40000 +> zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:0:0:0:0:3:4:5,40000 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:0:0:0:0:3:4:5,40000 +> zx0 ip6/0 8 0 17 10:0:0:0:0:3:4:5,10001 > 10:0:0:0:0:3:4:5,40001 +< zx0 ip6/0 8 0 17 10:1:1:0:0:0:0:2,1025 > 10:0:0:0:0:3:4:5,40001 +> zx0 ip6/0 20 0 6 10:1:2:0:0:0:0:1,80 > 10:0:0:0:0:3:4:5,40001 +< zx0 ip6/0 20 0 6 10:1:2:0:0:0:0:1,80 > 10:0:0:0:0:3:4:5,40001 +List of active MAP/Redirect filters: +map zx0 inet6 10:1:1::/112 -> 10::3:4:5/128 portmap udp 10000:20000 sequential + +List of active sessions: +MAP 10:1:1::2 1025 <- -> 10::3:4:5 10001 [10::3:4:5 40001] +MAP 10:1:1::2 1025 <- -> 10::3:4:5 10000 [10:1:1::1 1025] + +Hostmap table: +10:1:1::2,10::3:4:5 -> 10::3:4:5,any (use = 1) +10:1:1::2,10:1:1::1 -> 10::3:4:5,any (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +> zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:0 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:1,10000 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:1,10001 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:1 > 10:1:2:0:0:0:0:1 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:1:2:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:1 > 10:0:0:0:0:2:1:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:0:0:0:0:2:1:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:3 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:3:4 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:0 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:0:0:0:0:3:4:5,1025 +> zx0 ip6/0 88 0 58 10:1:1:0:0:0:0:1 > 10:4:3:0:0:0:0:2 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:3 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:5 +> zx0 ip6/0 1 0 34 10:1:1:0:0:0:0:2 > 10:4:3:0:0:0:0:2 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:4 +> zx0 ip6/0 1 0 34 10:1:1:0:0:0:0:2 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:5 +> zx0 ip6/0 1 0 34 10:1:1:0:0:0:0:3 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:6 +> zx0 ip6/0 1 0 35 10:1:1:0:0:0:0:3 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 35 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:7 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:1,10002 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:1,10003 > 10:1:1:0:0:0:0:2,1025 +> zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:0 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:1 > 10:1:2:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:1,10000 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:1,10000 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:1,10001 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 8 0 17 10:0:0:0:0:3:4:1,10004 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:1,10005 > 10:1:2:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:1,10006 > 10:1:3:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:1,10007 > 10:1:4:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:1,10008 > 10:1:4:0:0:0:0:1,80 +< zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:1:1:0:0:0:0:2,1025 +< zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:1,10009 > 10:0:0:0:0:3:4:5,40000 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1026 > 10:0:0:0:0:3:4:5,40000 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:1,10010 > 10:0:0:0:0:3:4:5,40000 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:0:0:0:0:3:4:5,40000 +> zx0 ip6/0 8 0 17 10:0:0:0:0:3:4:1,10011 > 10:0:0:0:0:3:4:5,40001 +< zx0 ip6/0 8 0 17 10:1:1:0:0:0:0:2,1025 > 10:0:0:0:0:3:4:5,40001 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:1,10012 > 10:0:0:0:0:3:4:5,40001 +< zx0 ip6/0 20 0 6 10:1:2:0:0:0:0:1,80 > 10:0:0:0:0:3:4:5,40001 +List of active MAP/Redirect filters: +map zx0 inet6 10:1::/32 -> 10::3:4:0/112 portmap tcp/udp 10000:20000 sequential + +List of active sessions: +MAP 10:1:2::1 80 <- -> 10::3:4:1 10012 [10::3:4:5 40001] +MAP 10:1:1::2 1025 <- -> 10::3:4:1 10011 [10::3:4:5 40001] +MAP 10:1:1::1 1025 <- -> 10::3:4:1 10010 [10::3:4:5 40000] +MAP 10:1:1::1 1026 <- -> 10::3:4:1 10009 [10::3:4:5 40000] +MAP 10:1:1::3 2003 <- -> 10::3:4:1 10008 [10:1:4::1 80] +MAP 10:1:1::3 2002 <- -> 10::3:4:1 10007 [10:1:4::1 80] +MAP 10:1:1::3 2001 <- -> 10::3:4:1 10006 [10:1:3::1 80] +MAP 10:1:1::3 2000 <- -> 10::3:4:1 10005 [10:1:2::1 80] +MAP 10:1:1::2 1025 <- -> 10::3:4:1 10004 [10:1:1::1 1025] +MAP 10:1:1::1 1025 <- -> 10::3:4:1 10003 [10:1:1::2 1025] +MAP 10:1:1::1 1025 <- -> 10::3:4:1 10002 [10:1:1::1 1025] +MAP 10:1:1::2 1026 <- -> 10::3:4:1 10001 [10:1:1::1 1025] +MAP 10:1:1::2 1025 <- -> 10::3:4:1 10000 [10:1:1::1 1025] + +Hostmap table: +10:1:2::1,10::3:4:5 -> 10::3:4:1,any (use = 1) +10:1:1::2,10::3:4:5 -> 10::3:4:1,any (use = 1) +10:1:1::1,10::3:4:5 -> 10::3:4:1,any (use = 2) +10:1:1::3,10:1:4::1 -> 10::3:4:1,any (use = 2) +10:1:1::3,10:1:3::1 -> 10::3:4:1,any (use = 1) +10:1:1::3,10:1:2::1 -> 10::3:4:1,any (use = 1) +10:1:1::1,10:1:1::2 -> 10::3:4:1,any (use = 1) +10:1:1::1,10:1:1::1 -> 10::3:4:1,any (use = 1) +10:1:1::2,10:1:1::1 -> 10::3:4:1,any (use = 3) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +> zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:0 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,40000 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,40001 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:1 > 10:1:2:0:0:0:0:1 +> zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:1:2:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:1 > 10:0:0:0:0:2:1:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:2 > 10:0:0:0:0:2:1:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:2:3 > 10:1:1:0:0:0:0:1 +< zx0 ip6/0 1 0 255 10:0:0:0:0:2:3:4 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:0 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:1 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 1 0 255 10:1:1:0:0:0:0:2 > 10:0:0:0:0:3:4:5 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:0:0:0:0:3:4:5,1025 +> zx0 ip6/0 88 0 58 10:1:1:0:0:0:0:1 > 10:4:3:0:0:0:0:2 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:2:2:2 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:3 +< zx0 ip6/0 88 0 58 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:5 +> zx0 ip6/0 1 0 34 10:1:1:0:0:0:0:2 > 10:4:3:0:0:0:0:2 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:2 > 10:0:0:0:0:3:4:4 +> zx0 ip6/0 1 0 34 10:1:1:0:0:0:0:2 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:5 +> zx0 ip6/0 1 0 34 10:1:1:0:0:0:0:3 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 34 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:6 +> zx0 ip6/0 1 0 35 10:1:1:0:0:0:0:3 > 10:4:3:0:0:0:0:4 +< zx0 ip6/0 1 0 35 10:4:3:0:0:0:0:4 > 10:0:0:0:0:3:4:7 +16 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,40000 > 10:1:1:0:0:0:0:2,1025 +> zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:0 > 10:1:1:0:0:0:0:2 +> zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:1 > 10:1:2:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,40000 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,40000 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,40001 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 8 0 17 10:0:0:0:0:3:4:5,40001 > 10:1:1:0:0:0:0:1,1025 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,40000 > 10:1:2:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,40001 > 10:1:3:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,40000 > 10:1:4:0:0:0:0:1,80 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,40001 > 10:1:4:0:0:0:0:1,80 +< zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:1 > 10:1:1:0:0:0:0:2 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:1:1:0:0:0:0:2,1025 +< zx0 ip6/0 1 0 41 10:1:1:0:0:0:0:2 > 10:1:1:0:0:0:0:1 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,40000 > 10:0:0:0:0:3:4:5,40000 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1026 > 10:0:0:0:0:3:4:5,40000 +> zx0 ip6/0 20 0 6 10:0:0:0:0:3:4:5,40001 > 10:0:0:0:0:3:4:5,40000 +< zx0 ip6/0 20 0 6 10:1:1:0:0:0:0:1,1025 > 10:1:1:0:0:0:0:2,1025 +> zx0 ip6/0 8 0 17 10:0:0:0:0:3:4:5,40000 > 10:0:0:0:0:3:4:5,40001 +< zx0 ip6/0 8 0 17 10:1:1:0:0:0:0:2,1025 > 10:0:0:0:0:3:4:5,40001 +> zx0 ip6/0 20 0 6 10:1:2:0:0:0:0:1,80 > 10:0:0:0:0:3:4:5,40001 +< zx0 ip6/0 20 0 6 10:1:2:0:0:0:0:1,80 > 10:0:0:0:0:3:4:5,40001 +List of active MAP/Redirect filters: +map zx0 inet6 10:1:1::/112 -> 10::3:4:5/128 portmap tcp/udp 40000:40001 sequential + +List of active sessions: +MAP 10:1:1::2 1025 <- -> 10::3:4:5 40000 [10::3:4:5 40001] +MAP 10:1:1::1 1025 <- -> 10::3:4:5 40001 [10::3:4:5 40000] +MAP 10:1:1::1 1026 <- -> 10::3:4:5 40000 [10::3:4:5 40000] +MAP 10:1:1::3 2003 <- -> 10::3:4:5 40001 [10:1:4::1 80] +MAP 10:1:1::3 2002 <- -> 10::3:4:5 40000 [10:1:4::1 80] +MAP 10:1:1::3 2001 <- -> 10::3:4:5 40001 [10:1:3::1 80] +MAP 10:1:1::3 2000 <- -> 10::3:4:5 40000 [10:1:2::1 80] +MAP 10:1:1::2 1025 <- -> 10::3:4:5 40001 [10:1:1::1 1025] +MAP 10:1:1::1 1025 <- -> 10::3:4:5 40000 [10:1:1::2 1025] +MAP 10:1:1::2 1026 <- -> 10::3:4:5 40001 [10:1:1::1 1025] +MAP 10:1:1::2 1025 <- -> 10::3:4:5 40000 [10:1:1::1 1025] + +Hostmap table: +10:1:1::2,10::3:4:5 -> 10::3:4:5,any (use = 1) +10:1:1::1,10::3:4:5 -> 10::3:4:5,any (use = 2) +10:1:1::3,10:1:4::1 -> 10::3:4:5,any (use = 2) +10:1:1::3,10:1:3::1 -> 10::3:4:5,any (use = 1) +10:1:1::3,10:1:2::1 -> 10::3:4:5,any (use = 1) +10:1:1::1,10:1:1::2 -> 10::3:4:5,any (use = 1) +10:1:1::2,10:1:1::1 -> 10::3:4:5,any (use = 3) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/n6 b/test/expected/n6 index cbdad9f1388ec..1afd94e54e464 100644 --- a/test/expected/n6 +++ b/test/expected/n6 @@ -1,70 +1,173 @@ -ip #0 40(20) 6 10.2.2.2,12345 > 10.2.2.1,10023 -ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.2,23 -ip #0 40(20) 6 10.3.0.1,12345 > 10.1.2.2,23 -ip #0 40(20) 6 10.3.0.1,12345 > 10.2.2.2,23 -ip #0 40(20) 6 10.3.3.3,12345 > 10.2.2.1,10023 -ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.1,53 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.1,53 -ip #0 40(20) 6 10.2.2.2,12345 > 10.1.0.0,23 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.0.0,23 -ip #0 28(20) 17 10.2.2.2,12345 > 10.1.1.0,53 -ip #0 28(20) 17 10.3.3.3,12345 > 10.1.1.0,53 -ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.0,53 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.0,53 +< zx0 ip #0 40(20) 6 10.2.2.2,12345 > 10.2.2.1,10023 +< zx0 ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.2,23 +< zx0 ip #0 40(20) 6 10.3.0.1,12345 > 10.1.2.2,23 +< zx0 ip #0 40(20) 6 10.3.0.1,12345 > 10.2.2.2,23 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.2.2.1,10023 +< zx0 ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.1,53 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.1,53 +< zx0 ip #0 40(20) 6 10.2.2.2,12345 > 10.1.0.0,23 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.0.0,23 +< zx0 ip #0 28(20) 17 10.2.2.2,12345 > 10.1.1.0,53 +< zx0 ip #0 28(20) 17 10.3.3.3,12345 > 10.1.1.0,53 +< zx0 ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.0,53 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.0,53 +List of active MAP/Redirect filters: +rdr zx0 10.1.1.1/32 port 23 -> 10.2.2.1/32 port 10023 tcp + +List of active sessions: +RDR 10.2.2.1 10023 <- -> 10.1.1.1 23 [10.3.3.3 12345] +RDR 10.2.2.1 10023 <- -> 10.1.1.1 23 [10.2.2.2 12345] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- -ip #0 40(20) 6 10.2.2.2,12345 > 10.2.2.1,10023 -ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.2,23 -ip #0 40(20) 6 10.3.0.1,12345 > 10.1.2.2,23 -ip #0 40(20) 6 10.3.0.1,12345 > 10.2.2.2,23 -ip #0 40(20) 6 10.3.3.3,12345 > 10.2.2.1,10023 -ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.1,53 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.1,53 -ip #0 40(20) 6 10.2.2.2,12345 > 10.1.0.0,23 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.0.0,23 -ip #0 28(20) 17 10.2.2.2,12345 > 10.1.1.0,53 -ip #0 28(20) 17 10.3.3.3,12345 > 10.1.1.0,53 -ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.0,53 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.0,53 +< zx0 ip #0 40(20) 6 10.2.2.2,12345 > 10.2.2.1,10023 +15 +< zx0 ip #0 40(20) 6 10.3.0.1,12345 > 10.1.2.2,23 +< zx0 ip #0 40(20) 6 10.3.0.1,12345 > 10.2.2.2,23 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.2.2.1,10023 +< zx0 ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.1,53 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.1,53 +< zx0 ip #0 40(20) 6 10.2.2.2,12345 > 10.1.0.0,23 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.0.0,23 +< zx0 ip #0 28(20) 17 10.2.2.2,12345 > 10.1.1.0,53 +< zx0 ip #0 28(20) 17 10.3.3.3,12345 > 10.1.1.0,53 +< zx0 ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.0,53 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.0,53 +List of active MAP/Redirect filters: +rdr zx0 from 0/0 to 10.1.1.0/24 port = 23 -> 10.2.2.1/32 port 10023 tcp + +List of active sessions: +RDR 10.2.2.1 10023 <- -> 10.1.1.1 23 [10.3.3.3 12345] +RDR 10.2.2.1 10023 <- -> 10.1.1.1 23 [10.2.2.2 12345] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- -ip #0 40(20) 6 10.2.2.2,12345 > 10.2.2.1,10023 -ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.2,23 -ip #0 40(20) 6 10.3.0.1,12345 > 10.1.2.2,23 -ip #0 40(20) 6 10.3.0.1,12345 > 10.2.2.2,23 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.1,23 -ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.1,53 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.1,53 -ip #0 40(20) 6 10.2.2.2,12345 > 10.1.0.0,23 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.0.0,23 -ip #0 28(20) 17 10.2.2.2,12345 > 10.1.1.0,53 -ip #0 28(20) 17 10.3.3.3,12345 > 10.1.1.0,53 -ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.0,53 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.0,53 +< zx0 ip #0 40(20) 6 10.2.2.2,12345 > 10.2.2.1,10023 +15 +< zx0 ip #0 40(20) 6 10.3.0.1,12345 > 10.1.2.2,23 +< zx0 ip #0 40(20) 6 10.3.0.1,12345 > 10.2.2.2,23 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.1,23 +< zx0 ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.1,53 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.1,53 +< zx0 ip #0 40(20) 6 10.2.2.2,12345 > 10.1.0.0,23 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.0.0,23 +< zx0 ip #0 28(20) 17 10.2.2.2,12345 > 10.1.1.0,53 +< zx0 ip #0 28(20) 17 10.3.3.3,12345 > 10.1.1.0,53 +< zx0 ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.0,53 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.0,53 +List of active MAP/Redirect filters: +rdr zx0 from 10.2.0.0/16 to 10.1.1.0/24 port = 23 -> 10.2.2.1/32 port 10023 tcp + +List of active sessions: +RDR 10.2.2.1 10023 <- -> 10.1.1.1 23 [10.2.2.2 12345] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- -ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.1,23 -ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.2,23 -ip #0 40(20) 6 10.3.0.1,12345 > 10.2.2.1,10023 -ip #0 40(20) 6 10.3.0.1,12345 > 10.2.2.2,23 -ip #0 40(20) 6 10.3.3.3,12345 > 10.2.2.1,10023 -ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.1,53 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.1,53 -ip #0 40(20) 6 10.2.2.2,12345 > 10.1.0.0,23 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.0.0,23 -ip #0 28(20) 17 10.2.2.2,12345 > 10.1.1.0,53 -ip #0 28(20) 17 10.3.3.3,12345 > 10.1.1.0,53 -ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.0,53 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.0,53 +< zx0 ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.1,23 +< zx0 ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.2,23 +< zx0 ip #0 40(20) 6 10.3.0.1,12345 > 10.2.2.1,10023 +< zx0 ip #0 40(20) 6 10.3.0.1,12345 > 10.2.2.2,23 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.2.2.1,10023 +< zx0 ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.1,53 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.1,53 +< zx0 ip #0 40(20) 6 10.2.2.2,12345 > 10.1.0.0,23 +15 +< zx0 ip #0 28(20) 17 10.2.2.2,12345 > 10.1.1.0,53 +< zx0 ip #0 28(20) 17 10.3.3.3,12345 > 10.1.1.0,53 +< zx0 ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.0,53 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.0,53 +List of active MAP/Redirect filters: +rdr zx0 from 10.3.0.0/16 to 10.1.0.0/16 port = 23 -> 10.2.2.1/32 port 10023 tcp + +List of active sessions: +RDR 10.2.2.1 10023 <- -> 10.1.1.1 23 [10.3.3.3 12345] +RDR 10.2.2.1 10023 <- -> 10.1.2.2 23 [10.3.0.1 12345] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- -ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.1,23 -ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.2,23 -ip #0 40(20) 6 10.3.0.1,12345 > 10.1.2.2,23 -ip #0 40(20) 6 10.3.0.1,12345 > 10.2.2.2,23 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.1,23 -ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.1,53 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.1,53 -ip #0 40(20) 6 10.2.2.2,12345 > 10.1.0.0,23 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.0.0,23 -ip #0 28(20) 17 10.2.2.2,12345 > 10.1.1.0,53 -ip #0 28(20) 17 10.3.3.3,12345 > 10.2.2.1,10053 -ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.0,53 -ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.0,53 +< zx0 ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.1,23 +< zx0 ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.2,23 +< zx0 ip #0 40(20) 6 10.3.0.1,12345 > 10.1.2.2,23 +< zx0 ip #0 40(20) 6 10.3.0.1,12345 > 10.2.2.2,23 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.1,23 +< zx0 ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.1,53 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.1,53 +< zx0 ip #0 40(20) 6 10.2.2.2,12345 > 10.1.0.0,23 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.0.0,23 +< zx0 ip #0 28(20) 17 10.2.2.2,12345 > 10.1.1.0,53 +< zx0 ip #0 28(20) 17 10.3.3.3,12345 > 10.2.2.1,10053 +< zx0 ip #0 40(20) 6 10.2.2.2,12345 > 10.1.1.0,53 +< zx0 ip #0 40(20) 6 10.3.3.3,12345 > 10.1.1.0,53 +List of active MAP/Redirect filters: +rdr zx0 ! from 10.2.0.0/16 to 10.1.1.0/24 port = 53 -> 10.2.2.1/32 port 10053 udp + +List of active sessions: +RDR 10.2.2.1 10053 <- -> 10.1.1.0 53 [10.3.3.3 12345] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- diff --git a/test/expected/n6_6 b/test/expected/n6_6 new file mode 100644 index 0000000000000..e10f9bd8f435e --- /dev/null +++ b/test/expected/n6_6 @@ -0,0 +1,173 @@ +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,12345 > 10:0:0:0:0:2:2:1,10023 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,12345 > 10:1:1:0:0:0:0:2,23 +< zx0 ip6/0 20 0 6 10:3:0:0:0:0:0:1,12345 > 10:1:2:0:0:0:0:2,23 +< zx0 ip6/0 20 0 6 10:3:0:0:0:0:0:1,12345 > 10:0:0:0:0:2:2:2,23 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:0:0:0:0:2:2:1,10023 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,12345 > 10:1:1:0:0:0:0:1,53 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:1,53 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,12345 > 10:1:0:0:0:0:0:0,23 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:0:0:0:0:0:0,23 +< zx0 ip6/0 8 0 17 10:0:0:0:0:2:2:2,12345 > 10:1:1:0:0:0:0:0,53 +< zx0 ip6/0 8 0 17 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:0,53 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,12345 > 10:1:1:0:0:0:0:0,53 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:0,53 +List of active MAP/Redirect filters: +rdr zx0 inet6 10:1:1::1/128 port 23 -> 10::2:2:1/128 port 10023 tcp + +List of active sessions: +RDR 10::2:2:1 10023 <- -> 10:1:1::1 23 [10:3:3::3 12345] +RDR 10::2:2:1 10023 <- -> 10:1:1::1 23 [10::2:2:2 12345] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,12345 > 10:0:0:0:0:2:2:1,10023 +16 +< zx0 ip6/0 20 0 6 10:3:0:0:0:0:0:1,12345 > 10:1:2:0:0:0:0:2,23 +< zx0 ip6/0 20 0 6 10:3:0:0:0:0:0:1,12345 > 10:0:0:0:0:2:2:2,23 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:0:0:0:0:2:2:1,10023 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,12345 > 10:1:1:0:0:0:0:1,53 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:1,53 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,12345 > 10:1:0:0:0:0:0:0,23 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:0:0:0:0:0:0,23 +< zx0 ip6/0 8 0 17 10:0:0:0:0:2:2:2,12345 > 10:1:1:0:0:0:0:0,53 +< zx0 ip6/0 8 0 17 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:0,53 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,12345 > 10:1:1:0:0:0:0:0,53 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:0,53 +List of active MAP/Redirect filters: +rdr zx0 inet6 from any to 10:1:1::/112 port = 23 -> 10::2:2:1/128 port 10023 tcp + +List of active sessions: +RDR 10::2:2:1 10023 <- -> 10:1:1::1 23 [10:3:3::3 12345] +RDR 10::2:2:1 10023 <- -> 10:1:1::1 23 [10::2:2:2 12345] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,12345 > 10:0:0:0:0:2:2:1,10023 +16 +< zx0 ip6/0 20 0 6 10:3:0:0:0:0:0:1,12345 > 10:1:2:0:0:0:0:2,23 +< zx0 ip6/0 20 0 6 10:3:0:0:0:0:0:1,12345 > 10:0:0:0:0:2:2:2,23 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:1,23 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,12345 > 10:1:1:0:0:0:0:1,53 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:1,53 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,12345 > 10:1:0:0:0:0:0:0,23 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:0:0:0:0:0:0,23 +< zx0 ip6/0 8 0 17 10:0:0:0:0:2:2:2,12345 > 10:1:1:0:0:0:0:0,53 +< zx0 ip6/0 8 0 17 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:0,53 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,12345 > 10:1:1:0:0:0:0:0,53 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:0,53 +List of active MAP/Redirect filters: +rdr zx0 inet6 from 10::/32 to 10:1:1::/112 port = 23 -> 10::2:2:1/128 port 10023 tcp + +List of active sessions: +RDR 10::2:2:1 10023 <- -> 10:1:1::1 23 [10::2:2:2 12345] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,12345 > 10:1:1:0:0:0:0:1,23 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,12345 > 10:1:1:0:0:0:0:2,23 +< zx0 ip6/0 20 0 6 10:3:0:0:0:0:0:1,12345 > 10:0:0:0:0:2:2:1,10023 +< zx0 ip6/0 20 0 6 10:3:0:0:0:0:0:1,12345 > 10:0:0:0:0:2:2:2,23 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:0:0:0:0:2:2:1,10023 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,12345 > 10:1:1:0:0:0:0:1,53 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:1,53 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,12345 > 10:1:0:0:0:0:0:0,23 +16 +< zx0 ip6/0 8 0 17 10:0:0:0:0:2:2:2,12345 > 10:1:1:0:0:0:0:0,53 +< zx0 ip6/0 8 0 17 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:0,53 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,12345 > 10:1:1:0:0:0:0:0,53 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:0,53 +List of active MAP/Redirect filters: +rdr zx0 inet6 from 10:3::/32 to 10:1::/32 port = 23 -> 10::2:2:1/128 port 10023 tcp + +List of active sessions: +RDR 10::2:2:1 10023 <- -> 10:1:1::1 23 [10:3:3::3 12345] +RDR 10::2:2:1 10023 <- -> 10:1:2::2 23 [10:3::1 12345] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,12345 > 10:1:1:0:0:0:0:1,23 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,12345 > 10:1:1:0:0:0:0:2,23 +< zx0 ip6/0 20 0 6 10:3:0:0:0:0:0:1,12345 > 10:1:2:0:0:0:0:2,23 +< zx0 ip6/0 20 0 6 10:3:0:0:0:0:0:1,12345 > 10:0:0:0:0:2:2:2,23 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:1,23 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,12345 > 10:1:1:0:0:0:0:1,53 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:1,53 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,12345 > 10:1:0:0:0:0:0:0,23 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:0:0:0:0:0:0,23 +< zx0 ip6/0 8 0 17 10:0:0:0:0:2:2:2,12345 > 10:1:1:0:0:0:0:0,53 +< zx0 ip6/0 8 0 17 10:3:3:0:0:0:0:3,12345 > 10:0:0:0:0:2:2:1,10053 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:2:2,12345 > 10:1:1:0:0:0:0:0,53 +< zx0 ip6/0 20 0 6 10:3:3:0:0:0:0:3,12345 > 10:1:1:0:0:0:0:0,53 +List of active MAP/Redirect filters: +rdr zx0 inet6 ! from 10::/32 to 10:1:1::/112 port = 53 -> 10::2:2:1/128 port 10053 udp + +List of active sessions: +RDR 10::2:2:1 10053 <- -> 10:1:1:: 53 [10:3:3::3 12345] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/n7 b/test/expected/n7 index eb23534d0b305..11b811538ba9b 100644 --- a/test/expected/n7 +++ b/test/expected/n7 @@ -1,30 +1,98 @@ -ip #0 40(20) 6 10.2.3.1,1230 > 10.1.1.1,22 -ip #0 40(20) 6 10.2.3.1,1231 > 10.2.2.1,10023 -ip #0 40(20) 6 10.2.3.1,1232 > 10.2.2.1,10050 -ip #0 40(20) 6 10.2.3.1,1233 > 10.2.2.1,10079 -ip #0 40(20) 6 10.2.3.1,1234 > 10.1.1.1,80 -ip #0 40(20) 6 10.2.3.1,1235 > 10.1.1.2,80 -ip #0 40(20) 6 10.2.3.1,1236 > 10.1.1.3,80 -ip #0 40(20) 6 10.2.3.1,1237 > 10.1.1.4,80 -ip #0 40(20) 6 10.2.3.1,1238 > 10.1.1.4,80 +< zx0 ip #0 40(20) 6 10.2.3.1,1230 > 10.1.1.1,22 +< zx0 ip #0 40(20) 6 10.2.3.1,1231 > 10.2.2.1,10023 +< zx0 ip #0 40(20) 6 10.2.3.1,1232 > 10.2.2.1,10050 +< zx0 ip #0 40(20) 6 10.2.3.1,1233 > 10.2.2.1,10079 +< zx0 ip #0 40(20) 6 10.2.3.1,1234 > 10.1.1.1,80 +< zx0 ip #0 40(20) 6 10.2.3.1,1235 > 10.1.1.2,80 +< zx0 ip #0 40(20) 6 10.2.3.1,1236 > 10.1.1.3,80 +< zx0 ip #0 40(20) 6 10.2.3.1,1237 > 10.1.1.4,80 +< zx0 ip #0 40(20) 6 10.2.3.1,1238 > 10.1.1.4,80 +List of active MAP/Redirect filters: +rdr zx0 10.1.1.1/32 port 23-79 -> 10.2.2.1/32 port 10023 tcp + +List of active sessions: +RDR 10.2.2.1 10079 <- -> 10.1.1.1 79 [10.2.3.1 1233] +RDR 10.2.2.1 10050 <- -> 10.1.1.1 50 [10.2.3.1 1232] +RDR 10.2.2.1 10023 <- -> 10.1.1.1 23 [10.2.3.1 1231] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- -ip #0 40(20) 6 10.2.3.1,1230 > 10.1.1.1,22 -ip #0 40(20) 6 10.2.3.1,1231 > 10.2.2.1,10023 -ip #0 40(20) 6 10.2.3.1,1232 > 10.2.2.1,10023 -ip #0 40(20) 6 10.2.3.1,1233 > 10.2.2.1,10023 -ip #0 40(20) 6 10.2.3.1,1234 > 10.1.1.1,80 -ip #0 40(20) 6 10.2.3.1,1235 > 10.1.1.2,80 -ip #0 40(20) 6 10.2.3.1,1236 > 10.1.1.3,80 -ip #0 40(20) 6 10.2.3.1,1237 > 10.1.1.4,80 -ip #0 40(20) 6 10.2.3.1,1238 > 10.1.1.4,80 +< zx0 ip #0 40(20) 6 10.2.3.1,1230 > 10.1.1.1,22 +< zx0 ip #0 40(20) 6 10.2.3.1,1231 > 10.2.2.1,10023 +< zx0 ip #0 40(20) 6 10.2.3.1,1232 > 10.2.2.1,10023 +< zx0 ip #0 40(20) 6 10.2.3.1,1233 > 10.2.2.1,10023 +< zx0 ip #0 40(20) 6 10.2.3.1,1234 > 10.1.1.1,80 +< zx0 ip #0 40(20) 6 10.2.3.1,1235 > 10.1.1.2,80 +< zx0 ip #0 40(20) 6 10.2.3.1,1236 > 10.1.1.3,80 +< zx0 ip #0 40(20) 6 10.2.3.1,1237 > 10.1.1.4,80 +< zx0 ip #0 40(20) 6 10.2.3.1,1238 > 10.1.1.4,80 +List of active MAP/Redirect filters: +rdr zx0 10.1.1.1/32 port 23-79 -> 10.2.2.1/32 port = 10023 tcp + +List of active sessions: +RDR 10.2.2.1 10023 <- -> 10.1.1.1 79 [10.2.3.1 1233] +RDR 10.2.2.1 10023 <- -> 10.1.1.1 50 [10.2.3.1 1232] +RDR 10.2.2.1 10023 <- -> 10.1.1.1 23 [10.2.3.1 1231] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- -ip #0 40(20) 6 10.2.3.1,1230 > 10.1.1.1,22 -ip #0 40(20) 6 10.2.3.1,1231 > 10.1.1.1,23 -ip #0 40(20) 6 10.2.3.1,1232 > 10.1.1.1,50 -ip #0 40(20) 6 10.2.3.1,1233 > 10.1.1.1,79 -ip #0 40(20) 6 10.2.3.1,1234 > 10.2.2.1,3128 -ip #0 40(20) 6 10.2.3.1,1235 > 1.2.2.129,3128 -ip #0 40(20) 6 10.2.3.1,1236 > 10.2.2.1,3128 -ip #0 40(20) 6 10.2.3.1,1237 > 1.2.2.129,3128 -ip #0 40(20) 6 10.2.3.1,1238 > 10.2.2.1,3128 +< zx0 ip #0 40(20) 6 10.2.3.1,1230 > 10.1.1.1,22 +< zx0 ip #0 40(20) 6 10.2.3.1,1231 > 10.1.1.1,23 +< zx0 ip #0 40(20) 6 10.2.3.1,1232 > 10.1.1.1,50 +< zx0 ip #0 40(20) 6 10.2.3.1,1233 > 10.1.1.1,79 +< zx0 ip #0 40(20) 6 10.2.3.1,1234 > 10.2.2.1,3128 +< zx0 ip #0 40(20) 6 10.2.3.1,1235 > 1.2.2.129,3128 +< zx0 ip #0 40(20) 6 10.2.3.1,1236 > 10.2.2.1,3128 +< zx0 ip #0 40(20) 6 10.2.3.1,1237 > 1.2.2.129,3128 +< zx0 ip #0 40(20) 6 10.2.3.1,1238 > 10.2.2.1,3128 +List of active MAP/Redirect filters: +rdr zx0 10.1.1.0/24 port 80 -> 10.2.2.1,1.2.2.129 port 3128 tcp + +List of active sessions: +RDR 10.2.2.1 3128 <- -> 10.1.1.4 80 [10.2.3.1 1238] +RDR 1.2.2.129 3128 <- -> 10.1.1.4 80 [10.2.3.1 1237] +RDR 10.2.2.1 3128 <- -> 10.1.1.3 80 [10.2.3.1 1236] +RDR 1.2.2.129 3128 <- -> 10.1.1.2 80 [10.2.3.1 1235] +RDR 10.2.2.1 3128 <- -> 10.1.1.1 80 [10.2.3.1 1234] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- diff --git a/test/expected/n7_6 b/test/expected/n7_6 new file mode 100644 index 0000000000000..25630334147f4 --- /dev/null +++ b/test/expected/n7_6 @@ -0,0 +1,98 @@ +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1230 > 10:1:1:0:0:0:0:1,22 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1231 > 10:0:0:0:0:2:2:1,10023 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1232 > 10:0:0:0:0:2:2:1,10050 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1233 > 10:0:0:0:0:2:2:1,10079 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1234 > 10:1:1:0:0:0:0:1,80 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1235 > 10:1:1:0:0:0:0:2,80 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1236 > 10:1:1:0:0:0:0:3,80 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1237 > 10:1:1:0:0:0:0:4,80 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1238 > 10:1:1:0:0:0:0:4,80 +List of active MAP/Redirect filters: +rdr zx0 inet6 10:1:1::1/128 port 23-79 -> 10::2:2:1/128 port 10023 tcp + +List of active sessions: +RDR 10::2:2:1 10079 <- -> 10:1:1::1 79 [10::2:3:1 1233] +RDR 10::2:2:1 10050 <- -> 10:1:1::1 50 [10::2:3:1 1232] +RDR 10::2:2:1 10023 <- -> 10:1:1::1 23 [10::2:3:1 1231] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1230 > 10:1:1:0:0:0:0:1,22 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1231 > 10:0:0:0:0:2:2:1,10023 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1232 > 10:0:0:0:0:2:2:1,10023 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1233 > 10:0:0:0:0:2:2:1,10023 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1234 > 10:1:1:0:0:0:0:1,80 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1235 > 10:1:1:0:0:0:0:2,80 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1236 > 10:1:1:0:0:0:0:3,80 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1237 > 10:1:1:0:0:0:0:4,80 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1238 > 10:1:1:0:0:0:0:4,80 +List of active MAP/Redirect filters: +rdr zx0 inet6 10:1:1::1/128 port 23-79 -> 10::2:2:1/128 port = 10023 tcp + +List of active sessions: +RDR 10::2:2:1 10023 <- -> 10:1:1::1 79 [10::2:3:1 1233] +RDR 10::2:2:1 10023 <- -> 10:1:1::1 50 [10::2:3:1 1232] +RDR 10::2:2:1 10023 <- -> 10:1:1::1 23 [10::2:3:1 1231] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1230 > 10:1:1:0:0:0:0:1,22 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1231 > 10:1:1:0:0:0:0:1,23 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1232 > 10:1:1:0:0:0:0:1,50 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1233 > 10:1:1:0:0:0:0:1,79 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1234 > 10:0:0:0:0:2:2:1,3128 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1235 > 1:0:0:0:0:2:2:129,3128 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1236 > 10:0:0:0:0:2:2:1,3128 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1237 > 1:0:0:0:0:2:2:129,3128 +< zx0 ip6/0 20 0 6 10:0:0:0:0:2:3:1,1238 > 10:0:0:0:0:2:2:1,3128 +List of active MAP/Redirect filters: +rdr zx0 inet6 10:1:1::/112 port 80 -> 10::2:2:1,1::2:2:129 port 3128 tcp + +List of active sessions: +RDR 10::2:2:1 3128 <- -> 10:1:1::4 80 [10::2:3:1 1238] +RDR 1::2:2:129 3128 <- -> 10:1:1::4 80 [10::2:3:1 1237] +RDR 10::2:2:1 3128 <- -> 10:1:1::3 80 [10::2:3:1 1236] +RDR 1::2:2:129 3128 <- -> 10:1:1::2 80 [10::2:3:1 1235] +RDR 10::2:2:1 3128 <- -> 10:1:1::1 80 [10::2:3:1 1234] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/n8 b/test/expected/n8 index d3e061da974ac..a5e938f16ef4e 100644 --- a/test/expected/n8 +++ b/test/expected/n8 @@ -6,4 +6,25 @@ 4500 0054 3fd5 4000 ff01 2fc8 0404 0404 0202 0202 0000 f7de 6220 0001 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +List of active MAP/Redirect filters: +map icmp0 2.2.2.0/24 -> 10.10.10.0/24 + +List of active sessions: +MAP 2.2.2.2 <- -> 10.10.10.1 [4.4.4.4] + +Hostmap table: +2.2.2.2,4.4.4.4 -> 10.10.10.1,0.0.0.0 (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- diff --git a/test/expected/n8_6 b/test/expected/n8_6 new file mode 100644 index 0000000000000..4d08efe37e2b4 --- /dev/null +++ b/test/expected/n8_6 @@ -0,0 +1,30 @@ +6000 0000 0040 3aff 0010 0010 0010 0000 0000 0000 0000 0001 0004 0004 0004 0000 0000 0000 0000 0004 8000 7724 6220 0000 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 + +6000 0000 0040 3aff 0004 0004 0004 0000 0000 0000 0000 0004 0002 0000 0000 0000 0000 0002 0002 0002 8100 764d 6220 0000 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 + +6000 0000 0040 3aff 0010 0010 0010 0000 0000 0000 0000 0001 0004 0004 0004 0000 0000 0000 0000 0004 8000 7723 6220 0001 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 + +6000 0000 0040 3aff 0004 0004 0004 0000 0000 0000 0000 0004 0002 0000 0000 0000 0000 0002 0002 0002 8100 764c 6220 0001 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 + +List of active MAP/Redirect filters: +map icmp0 inet6 2::2:2:0/112 -> 10:10:10::/112 + +List of active sessions: +MAP 2::2:2:2 <- -> 10:10:10::1 [4:4:4::4] + +Hostmap table: +2::2:2:2,4:4:4::4 -> 10:10:10::1,any (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/n9 b/test/expected/n9 index 917105f74ed4a..2c762be6af6a2 100644 --- a/test/expected/n9 +++ b/test/expected/n9 @@ -6,4 +6,24 @@ 4500 0054 3fd5 4000 ff01 2fc8 0404 0404 0202 0202 0000 f7de 6220 0001 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +List of active MAP/Redirect filters: +rdr icmp0 4.4.4.0/24 -> 10.10.10.1/32 ip + +List of active sessions: +RDR 10.10.10.1 <- -> 4.4.4.4 [2.2.2.2] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- diff --git a/test/expected/n9_6 b/test/expected/n9_6 new file mode 100644 index 0000000000000..134d74c9fa455 --- /dev/null +++ b/test/expected/n9_6 @@ -0,0 +1,29 @@ +6000 0000 0040 3aff 0002 0000 0000 0000 0000 0002 0002 0002 0010 0010 0010 0000 0000 0000 0000 0001 8000 772c 6220 0000 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 + +6000 0000 0040 3aff 0004 0004 0004 0000 0000 0000 0000 0004 0002 0000 0000 0000 0000 0002 0002 0002 8100 764d 6220 0000 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 + +6000 0000 0040 3aff 0002 0000 0000 0000 0000 0002 0002 0002 0010 0010 0010 0000 0000 0000 0000 0001 8000 772b 6220 0001 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 + +6000 0000 0040 3aff 0004 0004 0004 0000 0000 0000 0000 0004 0002 0000 0000 0000 0000 0002 0002 0002 8100 764c 6220 0001 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 + +List of active MAP/Redirect filters: +rdr icmp0 inet6 4:4:4::/112 -> 10:10:10::1/128 ip + +List of active sessions: +RDR 10:10:10::1 <- -> 4:4:4::4 [2::2:2:2] + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/ni10 b/test/expected/ni10 index 3ee63fb8ddd06..050fb40725eaf 100644 --- a/test/expected/ni10 +++ b/test/expected/ni10 @@ -4,6 +4,5 @@ 4500 0058 0001 0000 ff01 af98 0202 0202 0404 0404 0303 0937 0000 0000 4500 003c 4706 4000 ff06 28aa 0404 0404 0202 0202 5000 0050 0000 0001 0000 0000 a002 16d0 d8e2 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 -4500 0038 809a 0000 ff01 2b1b 0303 0303 0505 0505 0303 acab 0000 0000 4500 003c 4706 4000 ff06 28ab 0404 0404 0202 0201 5000 0050 0000 0001 - +0 ------------------------------- diff --git a/test/expected/ni11 b/test/expected/ni11 index 88d6406e6ee7b..6ed8ecc806345 100644 --- a/test/expected/ni11 +++ b/test/expected/ni11 @@ -1,9 +1,8 @@ 4500 003c 4706 4000 ff06 2aac 0404 0404 0101 0101 5000 9d58 0000 0001 0000 0000 a002 16d0 3ddc 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 -4500 0038 0000 0000 ff01 a7b9 0a02 0202 0404 0404 0303 a7fb 0000 0000 4500 003c 4706 4000 ff06 20aa 0404 0404 0a02 0202 5000 0500 0000 0001 +4500 0038 0000 0000 ff01 a7b9 0a02 0202 0404 0404 0303 a7fc 0000 0000 4500 003c 4706 4000 ff06 20aa 0404 0404 0a02 0202 5000 0500 0000 0001 4500 0058 0001 0000 ff01 a798 0a02 0202 0404 0404 0303 1137 0000 0000 4500 003c 4706 4000 ff06 20aa 0404 0404 0a02 0202 5000 0500 0000 0001 0000 0000 a002 16d0 cc32 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 -4500 0038 809a 0000 ff01 2b1b 0303 0303 0505 0505 0303 0fa3 0000 0000 4500 003c 4706 4000 ff06 2aab 0404 0404 0101 0102 5000 9d58 0000 0001 - +0 ------------------------------- diff --git a/test/expected/ni12 b/test/expected/ni12 index 7d24a493fd32f..590ec23087e88 100644 --- a/test/expected/ni12 +++ b/test/expected/ni12 @@ -1,9 +1,8 @@ 4500 003c 4706 4000 ff06 2aac 0404 0404 0101 0101 5000 9c40 0000 0001 0000 0000 a002 16d0 3ef4 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 -4500 0038 809a 0000 ff01 2d1d 0303 0303 0404 0404 0303 0fa3 0000 0000 4500 003c 4706 4000 ff06 2aac 0404 0404 0101 0101 5000 9d58 0000 0001 +4500 0038 0000 0000 ff01 a7b9 0a02 0202 0404 0404 0303 a7fc 0000 0000 4500 003c 4706 4000 ff06 20aa 0404 0404 0a02 0202 5000 0500 0000 0001 -4500 0058 809a 0000 ff01 2cfd 0303 0303 0404 0404 0303 0735 0000 0000 4500 003c 4706 4000 ff06 2aac 0404 0404 0101 0101 5000 9d58 0000 0001 0000 0000 a002 16d0 3ddc 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 - -4500 0038 809a 0000 ff01 2b1b 0303 0303 0505 0505 0303 0fa3 0000 0000 4500 003c 4706 4000 ff06 2aab 0404 0404 0101 0102 5000 9d58 0000 0001 +4500 0058 0001 0000 ff01 a798 0a02 0202 0404 0404 0303 1137 0000 0000 4500 003c 4706 4000 ff06 20aa 0404 0404 0a02 0202 5000 0500 0000 0001 0000 0000 a002 16d0 cc32 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 +0 ------------------------------- diff --git a/test/expected/ni17 b/test/expected/ni17 new file mode 100644 index 0000000000000..74eb4ddc5f9cd --- /dev/null +++ b/test/expected/ni17 @@ -0,0 +1,7 @@ +< le0 ip #0 40(20) 6 10.2.2.5,2000 > 10.1.1.252,3128 +< le0 ip #0 40(20) 6 10.2.2.6,2000 > 10.1.2.252,3128 +< le0 ip #0 40(20) 6 10.2.2.7,2000 > 10.1.3.252,3128 +< le0 ip #0 40(20) 6 10.2.2.7,2001 > 10.1.3.252,3128 +< le0 ip #0 40(20) 6 10.2.2.8,2000 > 10.1.1.253,3128 +< le0 ip #0 40(20) 6 10.2.2.9,2000 > 10.1.2.253,3128 +------------------------------- diff --git a/test/expected/ni18 b/test/expected/ni18 new file mode 100644 index 0000000000000..defc59cca97b7 --- /dev/null +++ b/test/expected/ni18 @@ -0,0 +1,5 @@ +< hme0 ip #0 40(20) 6 2.2.2.2,3000 > 1.1.1.1,80 +< hme0 ip #0 40(20) 6 2.2.2.2,3000 > 192.168.1.1,80 +> hme1 ip #0 40(20) 6 203.1.1.1,10000 > 4.5.6.7,80 +> hme1 ip #0 40(20) 6 10.1.1.2,5050 > 4.5.6.7,80 +------------------------------- diff --git a/test/expected/ni19 b/test/expected/ni19 index fa40771a0f13f..e55c75dc3837a 100644 --- a/test/expected/ni19 +++ b/test/expected/ni19 @@ -34,16 +34,10 @@ 4500 0034 118c 4000 4006 ec87 0a01 0104 c0a8 7103 03ff 03f0 91d4 c8a7 66e5 b811 8011 05b4 d54e 0000 0101 080a 0039 dd6d 0000 0000 -4500 0028 e404 4000 4006 1a1b c0a8 7103 0a01 0104 03f1 0202 6523 90eb 915a a5cb 5010 8328 bcd3 0000 - -4500 0034 e405 4000 4006 1a0e c0a8 7103 0a01 0104 03f0 03ff 66e5 b811 91d4 c8a8 8010 8328 57d7 0000 0101 080a 0000 0004 0039 dd6c - -4500 0028 e40a 4000 4006 1a15 c0a8 7103 0a01 0104 03f1 0202 6523 90eb 915a a5cb 5011 832c bcce 0000 - -4500 0034 e40b 4000 4006 1a08 c0a8 7103 0a01 0104 03f0 03ff 66e5 b811 91d4 c8a8 8011 832c 57d2 0000 0101 080a 0000 0004 0039 dd6c - -4500 0028 0004 4000 4006 fe1b 0a01 0104 c0a8 7103 0202 03f1 915a a5cb 6523 90ec 5010 05b4 3a47 0000 - -4500 0034 118e 4000 4006 ec85 0a01 0104 c0a8 7103 03ff 03f0 91d4 c8a8 66e5 b812 8010 05b4 d548 0000 0101 080a 0039 dd6e 0000 0004 - +0 +0 +0 +0 +0 +0 ------------------------------- diff --git a/test/expected/ni2 b/test/expected/ni2 index e2a7eb89ffafa..69a52724f0c1e 100644 --- a/test/expected/ni2 +++ b/test/expected/ni2 @@ -14,6 +14,6 @@ 4500 05dc e483 4000 7e06 44bb c0a8 0133 0a01 0201 0077 05f6 fbdf 1a75 a664 248c 5010 2232 9f2d 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3331 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 -4500 0038 0004 4000 4001 76e4 0101 0101 c0a8 0133 0304 9dea 0000 05a0 4500 05dc e483 4000 7e06 4ebb c0a8 0133 0101 0101 0077 9c40 fbdf 1a75 +4500 0038 0004 4000 4001 76e4 0101 0101 c0a8 0133 0304 444f 0000 05a0 4500 05dc e483 4000 7e06 4ebb c0a8 0133 0101 0101 0077 9c40 fbdf 1a75 ------------------------------- diff --git a/test/expected/ni20 b/test/expected/ni20 index 6001a5af9eb89..913ef0b1e461f 100644 --- a/test/expected/ni20 +++ b/test/expected/ni20 @@ -34,16 +34,36 @@ 4500 0034 118c 4000 4006 ec87 0a01 0104 c0a8 7103 03ff 03f0 91d4 c8a7 66e5 b811 8011 05b4 d54e 0000 0101 080a 0039 dd6d 0000 0000 -4500 0028 e404 4000 4006 f372 c0a8 7103 c0a8 7104 03f1 0202 6523 90eb 915a a5cb 5010 8328 962b 0000 - -4500 0034 e405 4000 4006 f365 c0a8 7103 c0a8 7104 03f0 03ff 66e5 b811 91d4 c8a8 8010 8328 312f 0000 0101 080a 0000 0004 0039 dd6c - -4500 0028 e40a 4000 4006 f36c c0a8 7103 c0a8 7104 03f1 0202 6523 90eb 915a a5cb 5011 832c 9626 0000 - -4500 0034 e40b 4000 4006 f35f c0a8 7103 c0a8 7104 03f0 03ff 66e5 b811 91d4 c8a8 8011 832c 312a 0000 0101 080a 0000 0004 0039 dd6c - -4500 0028 0004 4000 4006 d773 c0a8 7104 c0a8 7103 0202 03f1 915a a5cb 6523 90ec 5010 05b4 139f 0000 - -4500 0034 118e 4000 4006 c5dd c0a8 7104 c0a8 7103 03ff 03f0 91d4 c8a8 66e5 b812 8010 05b4 aea0 0000 0101 080a 0039 dd6e 0000 0004 - +0 +0 +0 +0 +0 +0 +List of active MAP/Redirect filters: +rdr bge0 10.1.1.4/32 port 514 -> 192.168.113.4/32 port 514 tcp proxy rcmd + +List of active sessions: +MAP 192.168.113.4 1023 <- -> 10.1.1.4 1023 [192.168.113.3 1008] +RDR 192.168.113.4 514 <- -> 10.1.1.4 514 [192.168.113.3 1009] + proxy active + +Hostmap table: +192.168.113.4,192.168.113.3 -> 10.1.1.4,0.0.0.0 (use = 1) +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +5 block in all +1 pass in quick on bge0 proto tcp from any to any port = 514 flags S/FSRPAU keep state +Rules configured (set 0, out) +2 block out all +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- diff --git a/test/expected/ni21 b/test/expected/ni21 index 349ae2391cc03..53e64a5a1f972 100644 --- a/test/expected/ni21 +++ b/test/expected/ni21 @@ -1,4 +1,6 @@ -ip #0 20(20) 0 4.4.4.4 > 3.3.3.3 -ip #0 20(20) 0 3.3.3.3 > 2.2.2.2 -ip #0 20(20) 0 4.4.4.4 > 3.3.3.3 +> eri0 ip #0 20(20) 0 4.4.4.4 > 3.3.3.3 +0 +< lan0 ip #0 20(20) 0 3.3.3.3 > 2.2.2.2 +> eri0 ip #0 20(20) 0 4.4.4.4 > 3.3.3.3 +0 ------------------------------- diff --git a/test/expected/ni23 b/test/expected/ni23 index 24909b07f0593..586373c070cac 100644 --- a/test/expected/ni23 +++ b/test/expected/ni23 @@ -1,8 +1,9 @@ -ip #0 28(20) 17 4.4.4.4,6700 > 2.2.2.2,4500 -ip #0 28(20) 17 2.2.2.2,4500 > 3.3.3.1,6700 -ip #0 28(20) 17 1.1.2.3,4500 > 3.3.3.1,6700 +> ppp0 ip #0 28(20) 17 4.4.4.4,6700 > 2.2.2.2,4500 +0 +< hme0 ip #0 28(20) 17 2.2.2.2,4500 > 3.3.3.1,6700 +> bge0 ip #0 28(20) 17 1.1.2.3,4500 > 3.3.3.1,6700 List of active MAP/Redirect filters: -rdr le0,bge0 1.1.0.0/16 -> 2.2.2.2 ip +rdr le0,bge0 1.1.0.0/16 -> 2.2.2.2/32 ip map hme0,ppp0 3.3.3.0/24 -> 4.4.4.4/32 List of active sessions: @@ -10,20 +11,27 @@ MAP 3.3.3.1 6700 <- -> 4.4.4.4 6700 [2.2.2.2 4500] RDR 2.2.2.2 4500 <- -> 1.1.2.3 4500 [3.3.3.1 6700] Hostmap table: -3.3.3.1,2.2.2.2 -> 4.4.4.4 (use = 1 hv = 0) +3.3.3.1,2.2.2.2 -> 4.4.4.4,0.0.0.0 (use = 1) List of active state sessions: -3.3.3.1 -> 2.2.2.2 pass 0x40008402 pr 17 state 0/0 - tag 0 ttl 24 6700 -> 4500 - forward: pkts in 1 bytes in 28 pkts out 1 bytes out 28 - backward: pkts in 1 bytes in 28 pkts out 1 bytes out 28 - pass in keep state IPv4 - pkt_flags & 0(0) = 0, pkt_options & ffffffff = 0, ffffffff = 0 - pkt_security & ffff = 0, pkt_auth & ffff = 0 - is_flx 0x8001 0x8001 0x8001 0x1 +4:udp src:3.3.3.1,6700 dst:2.2.2.2,4500 24 + FWD: IN pkts 1 bytes 28 OUT pkts 1 bytes 28 + REV: IN pkts 1 bytes 28 OUT pkts 1 bytes 28 + tag 0 pass 0x2008402 = pass in keep state interfaces: in X[le0],X[hme0] out X[ppp0],X[bge0] Sync status: not synchronized List of configured pools List of configured hash tables List of groups configured (set 0) List of groups configured (set 1) +Rules configured (set 0, in) +1 block in all +1 pass in on le0,hme0 to ppp0:3.3.3.254 out-via ppp0,bge0 inet proto udp from any to any keep state +Rules configured (set 0, out) +0 block out all +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- diff --git a/test/expected/ni4 b/test/expected/ni4 index c9f7504d7ac19..627aa1909da71 100644 --- a/test/expected/ni4 +++ b/test/expected/ni4 @@ -1,6 +1,6 @@ 4500 003c 0000 4000 ff06 67a8 0606 0606 0404 0404 9c40 0050 0000 0001 0000 0000 a002 16d0 849a 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 -4500 0038 809a 0000 ff01 3121 0303 0303 0202 0202 0303 acab 0000 0000 4500 003c 4706 4000 ff06 28aa 0202 0202 0404 0404 5000 0050 0000 0001 +4500 0038 809a 0000 ff01 3121 0303 0303 0202 0202 0303 acac 0000 0000 4500 003c 4706 4000 ff06 28aa 0202 0202 0404 0404 5000 0050 0000 0001 4500 0058 809a 0000 ff01 3101 0303 0303 0202 0202 0303 0937 0000 0000 4500 003c 4706 4000 ff06 28aa 0202 0202 0404 0404 5000 0050 0000 0001 0000 0000 a002 16d0 d8e2 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 diff --git a/test/expected/ni5 b/test/expected/ni5 index e713cf2851018..14d983759f6c4 100644 --- a/test/expected/ni5 +++ b/test/expected/ni5 @@ -4,6 +4,7 @@ 4500 0028 0001 4000 ff06 02ff 0101 0101 96cb e002 8032 0015 bd6b c9c9 3786 76c5 5010 269c 5aa0 0000 +ipf_p_ftp_servert_valid:i(0) < 5 4500 006f ffde 4000 ef06 5330 96cb e002 c0a8 0103 0015 8032 3786 76c5 bd6b c9c9 5018 269c 967e 0000 3232 302d 636f 6f6d 6273 2e61 6e75 2e65 6475 2e61 7520 4e63 4654 5064 2053 6572 7665 7220 2866 7265 6520 6564 7563 6174 696f 6e61 6c20 6c69 6365 6e73 6529 2072 6561 6479 2e0d 0a 4500 0028 0002 4000 ff06 02fe 0101 0101 96cb e002 8032 0015 bd6b c9c9 3786 770c 5010 269c 5a59 0000 @@ -22,6 +23,7 @@ 4500 0036 0006 4000 ff06 02ec 0101 0101 96cb e002 8032 0015 bd6b c9d9 3786 77ef 5018 269c 373f 0000 5041 5353 2061 7661 6c6f 6e40 0d0a +ipf_p_ftp_servert_valid:i(0) < 5 4500 005f ffe2 4000 ef06 533c 96cb e002 c0a8 0103 0015 8032 3786 77ef bd6b c9e7 5018 269c 895e 0000 3233 302d 596f 7520 6172 6520 7573 6572 2023 3420 6f66 2035 3020 7369 6d75 6c74 616e 656f 7573 2075 7365 7273 2061 6c6c 6f77 6564 2e0d 0a 4500 0028 0007 4000 ff06 02f9 0101 0101 96cb e002 8032 0015 bd6b c9e7 3786 7826 5010 269c 5921 0000 @@ -72,32 +74,23 @@ 4500 0028 ffec 4000 ef06 5369 96cb e002 c0a8 0103 0014 8034 d9f8 11d4 0000 0000 5010 2238 e90d 0000 -4500 0063 ffed 4000 ef06 532d 96cb e002 c0a8 0103 0014 8033 d9f8 11d5 bd78 5c13 5018 269c a315 0000 636f 6f6d 6273 7061 7065 7273 0d0a 6465 7074 730d 0a66 6f75 6e64 2d66 696c 6573 0d0a 696e 636f 6d69 6e67 0d0a 6e6c 632d 7465 7374 0d0a 7075 620d 0a - -4500 0028 0014 4000 ff06 02ec 0101 0101 96cb e002 8033 0014 bd78 5c13 d9f8 1210 5010 6348 4de0 0000 - -4500 0028 ffee 4000 ef06 5367 96cb e002 c0a8 0103 0014 8033 d9f8 1210 bd78 5c13 5011 269c cae1 0000 - -4500 0028 10dd 4000 ff06 3279 c0a8 0103 96cb e002 8033 0014 bd78 5c13 d9f8 1211 5010 6348 8e35 0000 - -4500 0028 10dd 4000 ff06 3279 c0a8 0103 96cb e002 8033 0014 bd78 5c13 d9f8 1211 5011 6348 8e34 0000 - -4500 0028 ffef 4000 ef06 5366 96cb e002 c0a8 0103 0014 8033 d9f8 1211 bd78 5c14 5010 269c cae0 0000 - +0 +0 +0 +0 +0 +0 4500 0040 fff0 4000 ef06 534d 96cb e002 c0a8 0103 0015 8032 3786 7903 bd6b ca3f 5018 269c 7c80 0000 3232 3620 4c69 7374 696e 6720 636f 6d70 6c65 7465 642e 0d0a -4500 0028 0015 4000 ff06 02eb 0101 0101 96cb e002 8032 0015 bd6b ca2f 3786 791b 5010 269c 57e4 0000 +4500 0028 0014 4000 ff06 02ec 0101 0101 96cb e002 8032 0015 bd6b ca2f 3786 791b 5010 269c 57e4 0000 -4500 002e 0016 4000 ff06 02e4 0101 0101 96cb e002 8032 0015 bd6b ca2f 3786 791b 5018 269c b022 0000 5155 4954 0d0a +4500 002e 0015 4000 ff06 02e5 0101 0101 96cb e002 8032 0015 bd6b ca2f 3786 791b 5018 269c b022 0000 5155 4954 0d0a 4500 0036 fff2 4000 ef06 5355 96cb e002 c0a8 0103 0015 8032 3786 791b bd6b ca45 5018 269c a936 0000 3232 3120 476f 6f64 6279 652e 0d0a -4500 0028 0017 4000 ff06 02e9 0101 0101 96cb e002 8032 0015 bd6b ca35 3786 7929 5011 269c 57cf 0000 - -4500 0028 fff3 4000 ef06 5362 96cb e002 c0a8 0103 0015 8032 3786 7929 bd6b ca45 5011 269c 9815 0000 - -4500 0028 10e3 4000 ff06 3273 c0a8 0103 96cb e002 8032 0015 bd6b ca3d 3786 792a 5010 269c 981d 0000 - -4500 0028 fff4 4000 ef06 5361 96cb e002 c0a8 0103 0015 8032 3786 792a bd6b ca46 5010 269c 9814 0000 +4500 0028 0016 4000 ff06 02ea 0101 0101 96cb e002 8032 0015 bd6b ca35 3786 7929 5011 269c 57cf 0000 +0 +0 +0 ------------------------------- diff --git a/test/expected/ni6 b/test/expected/ni6 index 0da034a781b35..e70412b7f471a 100644 --- a/test/expected/ni6 +++ b/test/expected/ni6 @@ -1,17 +1,63 @@ -4500 0054 cd8a 4000 ff11 1fbb c0a8 0601 c0a8 0701 8075 006f 0040 d26e 3e1d d249 0000 0000 0000 0002 0001 86a0 0000 0002 0000 0003 0000 0000 0000 0000 0000 0000 0000 0000 0001 86a3 0000 0003 0000 0011 0000 0000 - -4500 0054 0000 4000 ff11 ec44 c0a8 0702 c0a8 0701 8075 006f 0040 d16d 3e1d d249 0000 0000 0000 0002 0001 86a0 0000 0002 0000 0003 0000 0000 0000 0000 0000 0000 0000 0000 0001 86a3 0000 0003 0000 0011 0000 0000 - -4500 0038 cd83 4000 ff11 1fde c0a8 0701 c0a8 0601 006f 8075 0024 d805 3e1d d249 0000 0001 0000 0000 0000 0000 0000 0000 0000 0000 0000 0801 - -4500 0038 0001 4000 ff11 ee5f c0a8 0602 c0a8 0601 006f 8075 0024 d904 3e1d d249 0000 0001 0000 0000 0000 0000 0000 0000 0000 0000 0000 0801 - -4500 0044 d5a6 4000 ff11 17af c0a8 0601 c0a8 0701 80df 0801 0030 03f1 3e10 1fb1 0000 0000 0000 0002 0001 86a3 0000 0002 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 - -4500 0044 0002 4000 ff11 ec52 c0a8 0702 c0a8 0701 80df 0801 0030 02f0 3e10 1fb1 0000 0000 0000 0002 0001 86a3 0000 0002 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 - -4500 0034 0000 4000 fe11 ee65 c0a8 0701 c0a8 0601 0801 80df 0020 8ab8 3e10 1fb1 0000 0001 0000 0000 0000 0000 0000 0000 0000 0000 - -4500 0034 0003 4000 fe11 ef61 c0a8 0602 c0a8 0601 0801 80df 0020 0000 3e10 1fb1 0000 0001 0000 0000 0000 0000 0000 0000 0000 0000 - +< nf0 ip #52618 84(20) 17 192.168.6.1,32885 > 192.168.7.1,111 +> qfe0 ip #0 84(20) 17 192.168.7.2,32885 > 192.168.7.1,111 +< qfe0 ip #52611 56(20) 17 192.168.7.1,111 > 192.168.6.1,32885 +> nf0 ip #1 56(20) 17 192.168.6.2,111 > 192.168.6.1,32885 +< nf0 ip #54694 68(20) 17 192.168.6.1,32991 > 192.168.7.1,2049 +> qfe0 ip #2 68(20) 17 192.168.7.2,32991 > 192.168.7.1,2049 +< qfe0 ip #0 52(20) 17 192.168.7.1,2049 > 192.168.6.1,32991 +> nf0 ip #3 52(20) 17 192.168.6.2,2049 > 192.168.6.1,32991 +List of active MAP/Redirect filters: +rdr nf0 192.168.6.2/32 port 111 -> 192.168.7.1/32 port 111 udp proxy rpcbu +rdr nf0 192.168.6.2/32 port 111 -> 192.168.7.1/32 port 111 tcp proxy rpcbt +map qfe0 192.168.6.0/24 -> 192.168.7.2/32 + +List of active sessions: +MAP 192.168.6.1 32991 <- -> 192.168.7.2 32991 [192.168.7.1 2049] +RDR 192.168.7.1 2049 <- -> 192.168.6.2 2049 [192.168.6.1 32991] +RDR CLONE 192.168.7.1 2049 <- -> 192.168.6.2 2049 [192.168.6.1 0] +MAP 192.168.6.1 32885 <- -> 192.168.7.2 32885 [192.168.7.1 111] +RDR 192.168.7.1 111 <- -> 192.168.6.2 111 [192.168.6.1 32885] + proxy active + +Hostmap table: +192.168.6.1,192.168.7.1 -> 192.168.7.2,0.0.0.0 (use = 2) +List of active state sessions: +4:udp src:192.168.6.1,32991 dst:192.168.7.1,2049 24 + FWD: IN pkts 2 bytes 96 OUT pkts 1 bytes 68 + REV: IN pkts 1 bytes 52 OUT pkts 1 bytes 52 + tag 0 pass 0x502 = pass in quick keep state + interfaces: in X[nf0],X[qfe0] out X[qfe0],X[nf0] + Sync status: not synchronized +4:udp src:192.168.6.1,* dst:192.168.7.1,2049 240 CLONE + FWD: IN pkts 1 bytes 28 OUT pkts 0 bytes 0 + REV: IN pkts 0 bytes 0 OUT pkts 0 bytes 0 + tag 0 pass 0x502 = pass in quick keep state + interfaces: in X[nf0],X[] out X[],X[] + Sync status: not synchronized +4:udp src:192.168.6.1,32885 dst:192.168.7.1,111 24 + FWD: IN pkts 1 bytes 84 OUT pkts 1 bytes 84 + REV: IN pkts 1 bytes 56 OUT pkts 1 bytes 56 + tag 0 pass 0x2008502 = pass in quick keep state + interfaces: in X[nf0],X[qfe0] out X[qfe0],X[nf0] + Sync status: not synchronized +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +0 pass in quick on nf0 proto tcp from any to any port = 111 flags S/FSRPAU keep state +1 pass in quick on nf0 proto udp from any to any port = 111 keep state +0 block return-rst in log quick on nf0 proto tcp from any to any +0 block in log quick on nf0 inet from 192.168.7.0/24 to any +0 block return-rst in log quick on qfe0 proto tcp from any to any +0 block in log quick on qfe0 inet from 192.168.6.0/24 to any +Rules configured (set 0, out) +0 block out log quick on qfe0 inet from 192.168.7.0/24 to any +0 block out log quick on nf0 inet from 192.168.6.0/24 to any +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- diff --git a/test/expected/ni8 b/test/expected/ni8 index 689ccaa87eadc..e0d518270a1f3 100644 --- a/test/expected/ni8 +++ b/test/expected/ni8 @@ -1,6 +1,6 @@ 4500 003c 4706 4000 ff06 2aac 0404 0404 0101 0101 5000 9d58 0000 0001 0000 0000 a002 16d0 3ddc 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 -4500 0038 0000 0000 ff01 a7b9 0a02 0202 0404 0404 0303 a7fb 0000 0000 4500 003c 4706 4000 ff06 20aa 0404 0404 0a02 0202 5000 0500 0000 0001 +4500 0038 0000 0000 ff01 a7b9 0a02 0202 0404 0404 0303 a7fc 0000 0000 4500 003c 4706 4000 ff06 20aa 0404 0404 0a02 0202 5000 0500 0000 0001 4500 0058 0001 0000 ff01 a798 0a02 0202 0404 0404 0303 1137 0000 0000 4500 003c 4706 4000 ff06 20aa 0404 0404 0a02 0202 5000 0500 0000 0001 0000 0000 a002 16d0 cc32 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 diff --git a/test/expected/p1 b/test/expected/p1 index 9f02804439e8e..58dc6813f329f 100644 --- a/test/expected/p1 +++ b/test/expected/p1 @@ -13,9 +13,18 @@ List of active sessions: Hostmap table: List of active state sessions: List of configured pools -table role = ipf type = tree number = 100 - { 1.1.1.1/32; ! 2.2.0.0/16; 2.2.2.0/24; }; +table role=ipf type=tree number=100 + { 1.1.1.1/32; ! 2.2.0.0/16; 2.2.2.0/24; ef00::5/128; }; List of configured hash tables List of groups configured (set 0) List of groups configured (set 1) +Rules configured (set 0, in) +2 pass in from pool/100 to any +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- diff --git a/test/expected/p10 b/test/expected/p10 new file mode 100644 index 0000000000000..9f09502d2499d --- /dev/null +++ b/test/expected/p10 @@ -0,0 +1,40 @@ +< bge0 ip #0 40(20) 6 5.5.5.5,10000 > 1.1.1.2,80 +< bge0 ip #0 40(20) 6 5.5.5.6,10000 > 1.1.1.9,80 +< bge0 ip #0 40(20) 6 5.5.5.7,10000 > 1.1.1.2,80 +< bge0 ip #0 40(20) 6 5.5.5.8,10000 > 1.1.1.9,80 +< bge0 ip #0 40(20) 6 5.5.5.9,10000 > 1.1.1.4,80 +< bge0 ip #0 40(20) 6 5.5.6.5,10000 > 1.1.1.4,80 +< bge0 ip #0 40(20) 6 5.5.6.6,10000 > 1.1.1.9,80 +< bge0 ip #0 40(20) 6 5.5.6.7,10000 > 1.1.1.5,80 +< bge0 ip #0 40(20) 6 5.5.6.8,10000 > 1.1.1.5,80 +< bge0 ip #0 40(20) 6 5.5.6.9,10000 > 1.1.1.9,80 +List of active MAP/Redirect filters: +rewrite in on bge0 proto tcp from 0/0 to 0/0 port = 80 -> src 0/0 dst dstlist/servers; + +List of active sessions: +RWR-RDR 5.5.6.9 10000 9.9.9.9 80 <- -> 5.5.6.9 10000 1.1.1.9 80 +RWR-RDR 5.5.6.8 10000 9.9.9.9 80 <- -> 5.5.6.8 10000 1.1.1.5 80 +RWR-RDR 5.5.6.7 10000 9.9.9.9 80 <- -> 5.5.6.7 10000 1.1.1.5 80 +RWR-RDR 5.5.6.6 10000 9.9.9.9 80 <- -> 5.5.6.6 10000 1.1.1.9 80 +RWR-RDR 5.5.6.5 10000 9.9.9.9 80 <- -> 5.5.6.5 10000 1.1.1.4 80 +RWR-RDR 5.5.5.9 10000 9.9.9.9 80 <- -> 5.5.5.9 10000 1.1.1.4 80 +RWR-RDR 5.5.5.8 10000 9.9.9.9 80 <- -> 5.5.5.8 10000 1.1.1.9 80 +RWR-RDR 5.5.5.7 10000 9.9.9.9 80 <- -> 5.5.5.7 10000 1.1.1.2 80 +RWR-RDR 5.5.5.6 10000 9.9.9.9 80 <- -> 5.5.5.6 10000 1.1.1.9 80 +RWR-RDR 5.5.5.5 10000 9.9.9.9 80 <- -> 5.5.5.5 10000 1.1.1.2 80 + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/p11 b/test/expected/p11 new file mode 100644 index 0000000000000..e907fbb16ab18 --- /dev/null +++ b/test/expected/p11 @@ -0,0 +1,40 @@ +< bge0 ip #0 40(20) 6 5.5.5.5,10000 > 1.1.1.5,80 +< bge0 ip #0 40(20) 6 5.5.5.6,10000 > 1.1.1.5,80 +< bge0 ip #0 40(20) 6 5.5.5.7,10000 > 1.1.1.5,80 +< bge0 ip #0 40(20) 6 5.5.5.8,10000 > 1.1.1.5,80 +< bge0 ip #0 40(20) 6 5.5.5.9,10000 > 1.1.1.5,80 +< bge0 ip #0 40(20) 6 5.5.6.5,10000 > 1.1.1.5,80 +< bge0 ip #0 40(20) 6 5.5.6.6,10000 > 1.1.1.5,80 +< bge0 ip #0 40(20) 6 5.5.6.7,10000 > 1.1.1.5,80 +< bge0 ip #0 40(20) 6 5.5.6.8,10000 > 1.1.1.5,80 +< bge0 ip #0 40(20) 6 5.5.6.9,10000 > 1.1.1.5,80 +List of active MAP/Redirect filters: +rewrite in on bge0 proto tcp from 0/0 to 0/0 port = 80 -> src 0/0 dst dstlist/servers; + +List of active sessions: +RWR-RDR 5.5.6.9 10000 9.9.9.9 80 <- -> 5.5.6.9 10000 1.1.1.5 80 +RWR-RDR 5.5.6.8 10000 9.9.9.9 80 <- -> 5.5.6.8 10000 1.1.1.5 80 +RWR-RDR 5.5.6.7 10000 9.9.9.9 80 <- -> 5.5.6.7 10000 1.1.1.5 80 +RWR-RDR 5.5.6.6 10000 9.9.9.9 80 <- -> 5.5.6.6 10000 1.1.1.5 80 +RWR-RDR 5.5.6.5 10000 9.9.9.9 80 <- -> 5.5.6.5 10000 1.1.1.5 80 +RWR-RDR 5.5.5.9 10000 9.9.9.9 80 <- -> 5.5.5.9 10000 1.1.1.5 80 +RWR-RDR 5.5.5.8 10000 9.9.9.9 80 <- -> 5.5.5.8 10000 1.1.1.5 80 +RWR-RDR 5.5.5.7 10000 9.9.9.9 80 <- -> 5.5.5.7 10000 1.1.1.5 80 +RWR-RDR 5.5.5.6 10000 9.9.9.9 80 <- -> 5.5.5.6 10000 1.1.1.5 80 +RWR-RDR 5.5.5.5 10000 9.9.9.9 80 <- -> 5.5.5.5 10000 1.1.1.5 80 + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/p12 b/test/expected/p12 new file mode 100644 index 0000000000000..d097d5117b651 --- /dev/null +++ b/test/expected/p12 @@ -0,0 +1,40 @@ +< bge0 ip #0 40(20) 6 5.5.5.5,10000 > 1.1.1.2,80 +< bge0 ip #0 40(20) 6 5.5.5.6,10000 > 1.1.1.5,80 +< bge0 ip #0 40(20) 6 5.5.5.7,10000 > 1.1.1.4,80 +< bge0 ip #0 40(20) 6 5.5.5.8,10000 > 1.1.1.4,80 +< bge0 ip #0 40(20) 6 5.5.5.9,10000 > 1.1.1.9,80 +< bge0 ip #0 40(20) 6 5.5.6.5,10000 > 1.1.1.4,80 +< bge0 ip #0 40(20) 6 5.5.6.6,10000 > 1.1.1.4,80 +< bge0 ip #0 40(20) 6 5.5.6.7,10000 > 1.1.1.9,80 +< bge0 ip #0 40(20) 6 5.5.6.8,10000 > 1.1.1.9,80 +< bge0 ip #0 40(20) 6 5.5.6.9,10000 > 1.1.1.5,80 +List of active MAP/Redirect filters: +rewrite in on bge0 proto tcp from 0/0 to 0/0 port = 80 -> src 0/0 dst dstlist/servers; + +List of active sessions: +RWR-RDR 5.5.6.9 10000 9.9.9.9 80 <- -> 5.5.6.9 10000 1.1.1.5 80 +RWR-RDR 5.5.6.8 10000 9.9.9.9 80 <- -> 5.5.6.8 10000 1.1.1.9 80 +RWR-RDR 5.5.6.7 10000 9.9.9.9 80 <- -> 5.5.6.7 10000 1.1.1.9 80 +RWR-RDR 5.5.6.6 10000 9.9.9.9 80 <- -> 5.5.6.6 10000 1.1.1.4 80 +RWR-RDR 5.5.6.5 10000 9.9.9.9 80 <- -> 5.5.6.5 10000 1.1.1.4 80 +RWR-RDR 5.5.5.9 10000 9.9.9.9 80 <- -> 5.5.5.9 10000 1.1.1.9 80 +RWR-RDR 5.5.5.8 10000 9.9.9.9 80 <- -> 5.5.5.8 10000 1.1.1.4 80 +RWR-RDR 5.5.5.7 10000 9.9.9.9 80 <- -> 5.5.5.7 10000 1.1.1.4 80 +RWR-RDR 5.5.5.6 10000 9.9.9.9 80 <- -> 5.5.5.6 10000 1.1.1.5 80 +RWR-RDR 5.5.5.5 10000 9.9.9.9 80 <- -> 5.5.5.5 10000 1.1.1.2 80 + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/p13 b/test/expected/p13 new file mode 100644 index 0000000000000..aa529eada0305 --- /dev/null +++ b/test/expected/p13 @@ -0,0 +1,30 @@ +nomatch +pass +nomatch +nomatch +nomatch +pass +nomatch +nomatch +List of active MAP/Redirect filters: + +List of active sessions: + +Hostmap table: +List of active state sessions: +List of configured pools +table role=all type=tree number=100 + { 1.1.1.1/32; ! 2.2.0.0/16; 2.2.2.0/24; ef00::5/128; }; +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +2 pass in from pool/100 to any +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/p2 b/test/expected/p2 index 67a7c3ea26f3c..53887422b2179 100644 --- a/test/expected/p2 +++ b/test/expected/p2 @@ -14,12 +14,22 @@ Hostmap table: List of active state sessions: List of configured pools List of configured hash tables -# 'anonymous' table -table role = ipf type = hash number = 2147483650 size = 3 +# 'anonymous' table refs 2 +table role=ipf type=hash number=2147483650 size=3 { 127.0.0.1/32; 4.4.0.0/16; }; -# 'anonymous' table -table role = ipf type = hash number = 2147483649 size = 3 +# 'anonymous' table refs 2 +table role=ipf type=hash number=2147483649 size=3 { 127.0.0.1/32; 4.4.0.0/16; }; List of groups configured (set 0) List of groups configured (set 1) +Rules configured (set 0, in) +1 block in from hash/2147483650 to any +Rules configured (set 0, out) +2 pass out from hash/2147483649 to any +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- diff --git a/test/expected/p3 b/test/expected/p3 index 94fde9e701af4..c1e0343253843 100644 --- a/test/expected/p3 +++ b/test/expected/p3 @@ -18,18 +18,28 @@ Hostmap table: List of active state sessions: List of configured pools List of configured hash tables -group-map out role = ipf number = 2010 size = 5 - { 5.0.0.0/8, group = 2040; 4.4.0.0/16, group = 2020; 2.2.2.2/32, group = 2020; }; -group-map in role = ipf number = 1010 size = 3 - { 3.3.0.0/16, group = 1030; 1.1.1.1/32, group = 1020; }; +group-map out role=ipf number=2010 size=5 + { 2.2.2.2/32, group=2020; 4.4.0.0/16, group=2020; 5.0.0.0/8, group=2040; }; +group-map in role=ipf number=1010 size=3 + { 1.1.1.1/32, group=1020; 3.3.0.0/16, group=1030; }; List of groups configured (set 0) -Dev.0. Group 1020 Ref 1 Flags 0x8000 +Dev.0. Group 1020 Ref 2 Flags 0x8000 2 pass in all group 1020 -Dev.0. Group 1030 Ref 1 Flags 0x8000 +Dev.0. Group 1030 Ref 2 Flags 0x8000 2 block in all group 1030 -Dev.0. Group 2020 Ref 2 Flags 0x4000 +Dev.0. Group 2020 Ref 3 Flags 0x4000 4 pass out all group 2020 -Dev.0. Group 2040 Ref 1 Flags 0x4000 +Dev.0. Group 2040 Ref 2 Flags 0x4000 2 block out all group 2040 List of groups configured (set 1) +Rules configured (set 0, in) +6 call now srcgrpmap/1010 in all +Rules configured (set 0, out) +6 call now dstgrpmap/2010 out all +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) ------------------------------- diff --git a/test/expected/p4 b/test/expected/p4 new file mode 100644 index 0000000000000..e7aa73fda3d6c --- /dev/null +++ b/test/expected/p4 @@ -0,0 +1,38 @@ +< anon0 ip #0 20(20) 0 127.0.0.1 > 127.0.0.1 +< anon0 ip #0 20(20) 0 1.1.1.1 > 1.2.1.1 +> anon0 ip #0 20(20) 0 127.0.0.1 > 127.0.0.1 +> anon0 ip #0 20(20) 0 1.2.3.4 > 1.2.1.1 +< anon0 ip #0 20(20) 0 2.3.0.1 > 1.2.1.1 +< anon0 ip #0 20(20) 0 2.2.2.1 > 1.2.1.1 +< anon0 ip #0 20(20) 0 2.2.0.1 > 1.2.1.1 +15 +> anon0 ip #0 20(20) 0 1.2.3.4 > 1.2.1.2 +> anon0 ip #0 20(20) 0 2.2.0.1 > 1.2.1.1 +> anon0 ip #0 20(20) 0 2.2.0.1 > 1.2.1.3 +> anon0 ip #0 20(20) 0 4.4.1.1 > 1.2.1.1 +List of active MAP/Redirect filters: +map * from pool/100 to 0/0 -> 1.2.3.4/32 + +List of active sessions: +MAP 2.2.2.1 <- -> 1.2.3.4 [1.2.1.2] +MAP 1.1.1.1 <- -> 1.2.3.4 [1.2.1.1] + +Hostmap table: +2.2.2.1,1.2.1.2 -> 1.2.3.4,0.0.0.0 (use = 1) +1.1.1.1,1.2.1.1 -> 1.2.3.4,0.0.0.0 (use = 1) +List of active state sessions: +List of configured pools +table role=nat type=tree number=100 + { 1.1.1.1/32; ! 2.2.0.0/16; 2.2.2.0/24; }; +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/p5 b/test/expected/p5 index d8ea95c066a93..b56c3bcb4e9b6 100644 --- a/test/expected/p5 +++ b/test/expected/p5 @@ -13,7 +13,7 @@ List of active sessions: Hostmap table: List of active state sessions: List of configured pools -table role = ipf type = tree name = letters +table role=ipf type=tree name=letters { 1.1.1.1/32; ! 2.2.0.0/16; 2.2.2.0/24; }; List of configured hash tables List of groups configured (set 0) diff --git a/test/expected/p6 b/test/expected/p6 new file mode 100644 index 0000000000000..413f94ba74b94 --- /dev/null +++ b/test/expected/p6 @@ -0,0 +1,24 @@ +block +nomatch +List of active MAP/Redirect filters: + +List of active sessions: + +Hostmap table: +List of active state sessions: +List of configured pools +table role=ipf type=tree name=microsoft + { 131.107.0.0/16; 192.92.90.0/24; 198.105.232.0/22; 204.231.58.0/24; 204.140.77.0/24; 204.140.80.0/22; 199.60.28.0/24; 199.103.90.0/23; 199.103.122.0/24; 204.79.101.0/24; 192.237.67.0/24; 198.137.97.0/24; 204.79.135.0/24; 204.79.179.0/24; 204.79.180.0/23; 204.79.188.0/24; 204.79.7.0/24; 204.79.27.0/24; 198.180.74.0/23; 204.231.236.0/24; 205.163.63.0/24; 205.163.62.0/24; 205.163.144.0/20; 205.248.50.0/23; 205.248.72.0/24; 205.248.212.0/22; 205.248.228.0/24; 205.248.235.0/24; 204.231.76.0/24; 204.231.192.0/24; 207.78.80.0/24; 207.78.81.0/24; 207.78.82.0/24; 207.117.3.0/24; 207.18.117.0/24; 208.139.27.0/24; 209.28.213.0/24; 207.209.68.0/24; 204.95.96.0/20; 207.158.93.192/27; 207.240.123.192/27; 208.26.205.0/24; 192.197.157.0/24; 204.133.231.0/24; 216.72.96.0/22; 207.229.166.152/29; 204.95.149.0/24; 209.192.213.72/29; 206.73.203.0/24; 206.73.118.0/24; 208.45.54.16/29; 208.45.54.8/29; 206.73.31.0/24; 63.161.50.128/25; 63.161.50.0/25; 207.240.8.224/28; 208.45.89.248/29; 206.182.69.0/24; 206.182.240.0/24; 206.182.241.0/24; 206.73.67.0/24; 206.182.251.0/24; 206.182.247.0/24; 206.182.236.0/24; 63.236.198.64/29; 63.236.198.152/29; 165.121.253.232/29; 63.236.170.64/29; 63.236.186.64/29; 63.236.187.104/29; 63.236.187.128/29; 63.236.187.160/29; 199.2.137.0/24; 216.222.104.224/28; 63.151.87.64/29; 64.77.82.96/29; 64.77.93.80/28; 65.52.0.0/14; 207.46.0.0/16; 204.182.144.0/20; 206.107.34.0/24; 205.240.158.0/23; 204.79.252.0/24; 64.200.211.16/28; 12.178.163.0/27; 69.44.126.80/28; 63.173.42.128/25; 12.28.108.0/25; 65.170.29.0/29; 67.132.133.96/29; 8.6.176.0/24; 63.148.123.240/29; 64.41.193.0/24; 64.85.70.32/28; 64.85.81.96/29; 64.85.81.104/29; 216.32.168.224/27; 206.79.74.32/28; 216.32.175.224/27; 216.32.180.0/22; 216.33.229.224/27; 216.33.236.0/22; 216.33.240.0/22; 216.32.240.0/22; 216.34.51.0/24; 209.1.112.0/24; 209.1.113.0/24; 209.1.15.0/24; 216.34.53.176/28; 216.35.8.224/28; 209.185.128.0/22; 65.114.175.128/27; 64.15.229.96/27; 64.15.177.0/24; 64.15.170.192/29; 209.143.238.0/24; 64.15.178.0/24; 66.35.209.120/29; 66.35.211.128/26; 66.35.208.48/28; 216.33.148.0/22; 216.35.66.88/29; 12.230.32.160/29; 12.53.124.0/27; 12.232.18.96/27; 12.190.158.0/24; 12.71.196.32/28; 209.240.192.0/19; 70.37.128.0/23; 70.37.135.0/24; 12.49.87.192/26; 74.93.205.144/29; 74.93.205.152/29; 74.93.206.64/29; 70.89.139.120/29; 206.71.119.0/24; 206.71.117.0/24; 206.71.118.0/24; 209.154.155.112/29; 65.68.62.152/29; 67.39.208.168/29; 65.242.67.0/24; 204.71.191.0/24; 63.194.155.144/29; 66.136.85.192/29; 64.124.184.72/29; 216.200.206.0/24; 63.80.93.0/25; 67.192.225.208/28; 69.74.162.0/24; 65.221.5.0/24; 65.248.85.0/24; 199.243.157.192/27; 199.243.157.112/29; 65.194.210.224/27; 208.194.139.0/24; 208.204.49.128/25; 208.205.26.0/24; 208.217.184.0/22; 208.222.172.0/24; 208.224.200.64/27; 208.229.100.0/23; 208.241.19.0/28; 208.241.19.16/28; 208.241.9.224/28; 208.244.108.0/28; 208.245.16.0/27; 208.249.17.160/28; 63.104.216.0/25; 63.69.245.0/24; 68.90.141.72/29; 63.198.123.160/29; 68.248.48.64/29; 68.248.48.72/29; 99.49.8.248/29; 65.38.172.72/29; 65.38.172.96/28; 75.149.174.16/29; 75.151.100.240/28; 64.81.8.96/27; 67.112.255.144/29; 63.240.201.176/28; 206.16.209.208/28; 63.240.195.208/28; 206.16.204.64/28; 206.16.223.0/24; 63.240.216.0/22; 63.240.220.0/22; 206.16.246.24/29; 63.240.195.192/28; 206.16.224.160/27; 67.192.39.48/28; 72.32.240.160/28; 72.32.201.152/29; 67.39.81.152/29; 69.20.127.32/29; 216.52.28.0/24; 70.42.230.0/23; 63.251.97.0/24; 67.120.132.128/29; 67.120.132.152/29; 67.120.132.192/28; }; +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +1 block in from pool/microsoft to any +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/p7 b/test/expected/p7 new file mode 100644 index 0000000000000..89bfc11301c73 --- /dev/null +++ b/test/expected/p7 @@ -0,0 +1,40 @@ +< bge0 ip #0 40(20) 6 5.5.5.5,10000 > 1.1.1.2,80 +< bge0 ip #0 40(20) 6 5.5.5.6,10000 > 1.1.1.4,80 +< bge0 ip #0 40(20) 6 5.5.5.7,10000 > 1.1.1.5,80 +< bge0 ip #0 40(20) 6 5.5.5.8,10000 > 1.1.1.9,80 +< bge0 ip #0 40(20) 6 5.5.5.9,10000 > 1.1.1.2,80 +< bge0 ip #0 40(20) 6 5.5.6.5,10000 > 1.1.1.4,80 +< bge0 ip #0 40(20) 6 5.5.6.6,10000 > 1.1.1.5,80 +< bge0 ip #0 40(20) 6 5.5.6.7,10000 > 1.1.1.9,80 +< bge0 ip #0 40(20) 6 5.5.6.8,10000 > 1.1.1.2,80 +< bge0 ip #0 40(20) 6 5.5.6.9,10000 > 1.1.1.4,80 +List of active MAP/Redirect filters: +rewrite in on bge0 proto tcp from 0/0 to 0/0 port = 80 -> src 0/0 dst dstlist/servers; + +List of active sessions: +RWR-RDR 5.5.6.9 10000 9.9.9.9 80 <- -> 5.5.6.9 10000 1.1.1.4 80 +RWR-RDR 5.5.6.8 10000 9.9.9.9 80 <- -> 5.5.6.8 10000 1.1.1.2 80 +RWR-RDR 5.5.6.7 10000 9.9.9.9 80 <- -> 5.5.6.7 10000 1.1.1.9 80 +RWR-RDR 5.5.6.6 10000 9.9.9.9 80 <- -> 5.5.6.6 10000 1.1.1.5 80 +RWR-RDR 5.5.6.5 10000 9.9.9.9 80 <- -> 5.5.6.5 10000 1.1.1.4 80 +RWR-RDR 5.5.5.9 10000 9.9.9.9 80 <- -> 5.5.5.9 10000 1.1.1.2 80 +RWR-RDR 5.5.5.8 10000 9.9.9.9 80 <- -> 5.5.5.8 10000 1.1.1.9 80 +RWR-RDR 5.5.5.7 10000 9.9.9.9 80 <- -> 5.5.5.7 10000 1.1.1.5 80 +RWR-RDR 5.5.5.6 10000 9.9.9.9 80 <- -> 5.5.5.6 10000 1.1.1.4 80 +RWR-RDR 5.5.5.5 10000 9.9.9.9 80 <- -> 5.5.5.5 10000 1.1.1.2 80 + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/expected/p9 b/test/expected/p9 new file mode 100644 index 0000000000000..89bfc11301c73 --- /dev/null +++ b/test/expected/p9 @@ -0,0 +1,40 @@ +< bge0 ip #0 40(20) 6 5.5.5.5,10000 > 1.1.1.2,80 +< bge0 ip #0 40(20) 6 5.5.5.6,10000 > 1.1.1.4,80 +< bge0 ip #0 40(20) 6 5.5.5.7,10000 > 1.1.1.5,80 +< bge0 ip #0 40(20) 6 5.5.5.8,10000 > 1.1.1.9,80 +< bge0 ip #0 40(20) 6 5.5.5.9,10000 > 1.1.1.2,80 +< bge0 ip #0 40(20) 6 5.5.6.5,10000 > 1.1.1.4,80 +< bge0 ip #0 40(20) 6 5.5.6.6,10000 > 1.1.1.5,80 +< bge0 ip #0 40(20) 6 5.5.6.7,10000 > 1.1.1.9,80 +< bge0 ip #0 40(20) 6 5.5.6.8,10000 > 1.1.1.2,80 +< bge0 ip #0 40(20) 6 5.5.6.9,10000 > 1.1.1.4,80 +List of active MAP/Redirect filters: +rewrite in on bge0 proto tcp from 0/0 to 0/0 port = 80 -> src 0/0 dst dstlist/servers; + +List of active sessions: +RWR-RDR 5.5.6.9 10000 9.9.9.9 80 <- -> 5.5.6.9 10000 1.1.1.4 80 +RWR-RDR 5.5.6.8 10000 9.9.9.9 80 <- -> 5.5.6.8 10000 1.1.1.2 80 +RWR-RDR 5.5.6.7 10000 9.9.9.9 80 <- -> 5.5.6.7 10000 1.1.1.9 80 +RWR-RDR 5.5.6.6 10000 9.9.9.9 80 <- -> 5.5.6.6 10000 1.1.1.5 80 +RWR-RDR 5.5.6.5 10000 9.9.9.9 80 <- -> 5.5.6.5 10000 1.1.1.4 80 +RWR-RDR 5.5.5.9 10000 9.9.9.9 80 <- -> 5.5.5.9 10000 1.1.1.2 80 +RWR-RDR 5.5.5.8 10000 9.9.9.9 80 <- -> 5.5.5.8 10000 1.1.1.9 80 +RWR-RDR 5.5.5.7 10000 9.9.9.9 80 <- -> 5.5.5.7 10000 1.1.1.5 80 +RWR-RDR 5.5.5.6 10000 9.9.9.9 80 <- -> 5.5.5.6 10000 1.1.1.4 80 +RWR-RDR 5.5.5.5 10000 9.9.9.9 80 <- -> 5.5.5.5 10000 1.1.1.2 80 + +Hostmap table: +List of active state sessions: +List of configured pools +List of configured hash tables +List of groups configured (set 0) +List of groups configured (set 1) +Rules configured (set 0, in) +Rules configured (set 0, out) +Rules configured (set 1, in) +Rules configured (set 1, out) +Accounting rules configured (set 0, in) +Accounting rules configured (set 0, out) +Accounting rules configured (set 1, in) +Accounting rules configured (set 1, out) +------------------------------- diff --git a/test/h4to6 b/test/h4to6 new file mode 100644 index 0000000000000..e31f7c4224b61 --- /dev/null +++ b/test/h4to6 @@ -0,0 +1,135 @@ +@P=(); +$line = 0; +while (<>) { + s/\=192.168.1.188/\=c0a8:0100::bc/g; + s/\=192.168.1.188/\=c0a8:0100::bc/g; + @F = split; + if (/^#/) { + @P[$nline++] = join(" ",@F); + next; + } + $line = 0 if (/^\[/); + if ($line == 1) { + $len = hex($F[1]) - 20; + $pr = hex($F[4]) & 0xff; + $pr = 58 if ($pr == 1); + $ttl = hex($F[4]) >> 8; + &replaceip($_, $len, $pr, $ttl); + $ipline = $nline; + $err = 0; + } elsif ($line == 2) { + if ($pr == 58) { + # + # Map the ICMP type codes from IPv4 to IPv6 + # and update the checksum to compensate. + # + if ($F[0] =~ /^0800/) { + $F[0] =~ s/^0800/8000/; + $d = 0x7800; + } + if ($F[0] =~ /^0000/) { + $F[0] =~ s/^0000/8100/; + $d = 0x8100; + } + if ($F[0] =~ /^0304/) { + $F[0] =~ s/^0304/0200/; + $d = 0xfefc; + $err = 1; + } + if ($F[0] =~ /^03/) { + $F[0] =~ s/^03/01/; + $d = 0xfe00; + $err = 1; + } + if ($F[0] =~ /^0b/) { + $F[0] =~ s/^0b/03/; + $d = 0xf800; + $err = 1; + } + if ($F[0] =~ /^0c/) { + $F[0] =~ s/^0c/04/; + $d = 0xf800; + $err = 1; + } + $F[1] = sprintf "%04x", hex($F[1]) - $d; + } + @P[$nline++] = join(" ",@F); + } elsif ($line == 3) { + if ($pr == 58 && $err == 1 && $F[0] =~ /^45/) { + local($l) = hex($F[1]) - 20; + local($p) = hex($F[4]) & 0xff; + $p = 58 if ($p == 1); + local($t) = hex($F[4]) >> 8; + &replaceip(join(" ", @F), $l, $p, $t); + @H = split(/ /, $P[$ipline]); + $H[2] += 20; + $P[$ipline] = join(" ",@H); + } else { + @P[$nline++] = join(" ",@F); + } + } else { + @P[$nline++] = join(" ",@F); + } + $line++; +} + +for ($li = 0; $li < $nline; $li++) { + print "$P[$li]\n"; +} + +exit(0); + +sub replaceip { + local(@G) = split(/\s/,$_[0]); + local($p) = ""; + + $p = sprintf "6000 0000 %04x %02x%02x", $_[1], $_[2], $_[3]; + if ($G[6] =~ /^c0a8/) { + $fmt = " %02x%02x %02x00 0000 0000 0000 0000 0000 00%02x"; + } else { + if ($G[6] =~ /^0[4a]../) { + $fmt = " 00%02x 00%02x 00%02x 0000 0000 0000 0000 00%02x"; + } else { + $fmt = " 00%02x 0000 0000 0000 0000 00%02x 00%02x 00%02x"; + } + if ($G[6] =~ /^0a/) { + $G[6] =~ s/^0a/10/; + } + if ($G[6] =~ /0a$/) { + $G[6] =~ s/0a$/10/; + } + if ($G[7] =~ /^0a/) { + $G[7] =~ s/^0a/10/; + } + if ($G[7] =~ /0a$/) { + $G[7] =~ s/0a$/10/; + } + } + $p = $p.sprintf $fmt, hex($G[6]) >> 8, hex($G[6]) & 0xff, + hex($G[7]) >> 8, hex($G[7]) & 0xff; + + if ($G[6] =~ /^c0a8/) { + $fmt = " %02x%02x %02x00 0000 0000 0000 0000 0000 00%02x"; + } else { + if ($G[8] =~ /^0[4a]../) { + $fmt = " 00%02x 00%02x 00%02x 0000 0000 0000 0000 00%02x"; + } else { + $fmt = " 00%02x 0000 0000 0000 0000 00%02x 00%02x 00%02x"; + } + if ($G[8] =~ /^0a/) { + $G[8] =~ s/^0a/10/; + } + if ($G[8] =~ /0a$/) { + $G[8] =~ s/0a$/10/; + } + if ($G[9] =~ /^0a/) { + $G[9] =~ s/^0a/10/; + } + if ($G[9] =~ /0a$/) { + $G[9] =~ s/0a$/10/; + } + } + $p = $p.sprintf $fmt, hex($G[8]) >> 8, hex($G[8]) & 0xff, + hex($G[9]) >> 8, hex($G[9]) & 0xff; + $P[$nline++] = $p; +} diff --git a/test/hextest b/test/hextest deleted file mode 100644 index b7b0b2c75e421..0000000000000 --- a/test/hextest +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/sh -if [ -f /usr/ucb/touch ] ; then - TOUCH=/usr/ucb/touch -else - if [ -f /usr/bin/touch ] ; then - TOUCH=/usr/bin/touch - else - if [ -f /bin/touch ] ; then - TOUCH=/bin/touch - fi - fi -fi -echo "$1..."; -/bin/cp /dev/null results/$1 -( while read rule; do - echo "$rule" | ../ipftest -br - -F hex -i input/$1 >> results/$1; - if [ $? -ne 0 ] ; then - exit 1; - fi - echo "--------" >> results/$1 -done ) < regress/$1 -cmp expected/$1 results/$1 -status=$? -if [ $status = 0 ] ; then - $TOUCH $1 -fi -exit $status diff --git a/test/i4to6 b/test/i4to6 new file mode 100644 index 0000000000000..b1208fd923dd7 --- /dev/null +++ b/test/i4to6 @@ -0,0 +1,12 @@ +sed \ +-e 's/in /in6 /g' \ +-e 's/icmp/58/g' \ +-e 's/out /out6 /g' \ +-e 's/10\.4\.\([0-9]\)\.\([0-9]\)/10:4:\1::\2/g' \ +-e 's/10\.3\.4\.\([0-9]\)/10::3:4:\1/g' \ +-e 's/10\.3\.\([0-9]\)\.\([0-9]\)/10:3:\1::\2/g' \ +-e 's/10\.1\.\([0-9]\)\.\([0-9]\)/10:1:\1::\2/g' \ +-e 's/10\.2\.\([0-9]\)\.\([0-9]\)/10::2:\1:\2/g' \ +-e 's/9\.\([0-9]\)\.\([0-9]\)\.\([0-9]\)/9:\1:\2::\3/g' \ +-e 's/5\.\([0-9]\)\.\([0-9]\)\.\([0-9]\)/5:\1::\2:\3/g' \ +-e 's/2\.\([0-9]\)\.\([0-9]\)\.\([0-9]\)/2::\1:\2:\3/g' diff --git a/test/input/10 b/test/input/10 deleted file mode 100644 index 254cee7316ff5..0000000000000 --- a/test/input/10 +++ /dev/null @@ -1,6 +0,0 @@ -in 1.1.1.1 2.1.1.1 opt lsrr -in 1.1.1.1 2.1.1.1 -in 1.1.1.1 2.1.1.1 opt ts -in 1.1.1.1 2.1.1.1 opt sec-class=topsecret -in 1.1.1.1 2.1.1.1 opt ssrr,sec-class=topsecret -in 1.1.1.1 2.1.1.1 opt sec diff --git a/test/input/11 b/test/input/11 deleted file mode 100644 index 4eda58eac04e9..0000000000000 --- a/test/input/11 +++ /dev/null @@ -1,11 +0,0 @@ -in on e0 tcp 1.1.1.1,1 2.1.2.2,23 S -in on e0 tcp 1.1.1.1,1 2.1.2.2,23 A -in on e1 tcp 2.1.2.2,23 1.1.1.1,1 A -in on e0 tcp 1.1.1.1,1 2.1.2.2,23 F -in on e0 tcp 1.1.1.1,1 2.1.2.2,23 A -in on e0 tcp 1.1.1.1,2 2.1.2.2,23 A -in on e1 udp 1.1.1.1,1 4.4.4.4,53 -in on e1 udp 2.2.2.2,2 4.4.4.4,53 -in on e0 udp 4.4.4.4,53 1.1.1.1,1 -in on e0 udp 4.4.4.4,1023 1.1.1.1,2049 -in on e0 udp 4.4.4.4,2049 1.1.1.1,1023 diff --git a/test/input/12 b/test/input/12 deleted file mode 100644 index 5d9c1de3590dd..0000000000000 --- a/test/input/12 +++ /dev/null @@ -1,35 +0,0 @@ -# 1.1.1.1,1025 -> 2.1.1.1,25 TTL=63 TCP DF SYN -45 00 0028 0000 4000 3f 06 0000 01010101 02010101 -0401 0019 00000000 00000000 50 02 2000 0000 0000 - -# 1.1.1.1,1025 -> 2.1.1.1,25 TTL=63 TCP DF ACK -45 00 0028 0000 4000 3f 06 0000 01010101 02010101 -0401 0019 00000000 00000000 50 10 2000 0000 0000 - -# 1.1.1.1,1025 -> 2.1.1.1,25 TTL=63 TCP DF MF FO=0 ACK -45 00 0028 0000 6000 3f 06 0000 01010101 02010101 -0401 0019 00000000 00000000 50 10 2000 0000 0000 - -# 1.1.1.1,1025 -> 2.1.1.1,25 TTL=63 TCP DF FO=0 -45 00 001c 0000 6000 3f 06 0000 01010101 02010101 -0401 0019 00000000 - -# 1.1.1.1 -> 2.1.1.1 TTL=63 TCP DF FO=1 ACK -45 00 001c 0000 6001 3f 06 0000 01010101 02010101 -00000000 50 10 2000 - -# 1.1.1.1 -> 2.1.1.1 TTL=63 UDP DF MF FO=0 -45 00 0014 0000 6000 3f 11 0000 01010101 02010101 - -# 1.1.1.1,53 -> 2.1.1.1,53 TTL=63 UDP MF FO=0 -45 00 0018 0000 2000 3f 11 0000 01010101 02010101 -0035 0035 - -# 1.1.1.1,1 -> 2.1.1.1,1 TTL=63 UDP MF FO=0 -45 00 001c 0000 2000 3f 11 0000 01010101 02010101 -0001 0001 0004 0000 - -# 1.1.1.1,53 -> 2.1.1.1,53 TTL=63 UDP MF FO=0 -45 00 001c 0000 2000 3f 11 0000 01010101 02010101 -0035 0035 0004 0000 - diff --git a/test/input/13 b/test/input/13 deleted file mode 100644 index 56ec16d99b83f..0000000000000 --- a/test/input/13 +++ /dev/null @@ -1,39 +0,0 @@ -# 1.1.1.1,1025 -> 2.1.1.1,25 TTL=63 TCP DF,MF,FO=0 SYN -45 00 0028 0001 4000 3f 06 0000 01010101 02010101 -0401 0019 00000000 00000000 50 02 2000 0000 0000 - -# 1.1.1.1,1025 -> 2.1.1.1,25 TTL=63 TCP MF ACK -45 00 0024 0002 2000 3f 06 0000 01010101 02010101 -0401001900000000 0000000050102000 - -# 1.1.1.1,1025 -> 2.1.1.1,25 TTL=63 TCP FO=2 ACK -45 00 002c 0002 0002 3f 06 0000 01010101 02010101 -0000000000010203 0405060708090a0b 0c0d0e0f10111213 - -# 1.1.1.1,1025 -> 2.1.1.1,25 TTL=63 TCP DF MF FO=0 SYN -45 00 0028 0003 6000 3f 06 0000 01010101 02010101 -0401 0019 00000000 00000000 50 10 2000 0000 0000 - -# 1.1.1.1,1025 -> 2.1.1.1,25 TTL=63 TCP DF FO=0 -45 00 001c 0004 6000 3f 06 0000 01010101 02010101 -0401 0019 00000000 - -# 1.1.1.1 -> 2.1.1.1 TTL=63 TCP DF FO=1 SYN -45 00 001c 0005 6001 3f 06 0000 01010101 02010101 -00000000 50 10 2000 - -# 1.1.1.1 -> 2.1.1.1 TTL=63 UDP DF MF FO=0 -45 00 0014 0006 6000 3f 11 0000 01010101 02010101 - -# 1.1.1.1,53 -> 2.1.1.1,53 TTL=63 UDP MF FO=0 -45 00 0018 0007 2000 3f 11 0000 01010101 02010101 -0035 0035 - -# 1.1.1.1,1 -> 2.1.1.1,1 TTL=63 UDP MF FO=0 -45 00 001c 0008 2000 3f 11 0000 01010101 02010101 -0035003500040000 - -# 1.1.1.1,53 -> 2.1.1.1,53 TTL=63 UDP FO=1 -45 00 001c 0008 0001 3f 11 0000 01010101 02010101 -0000000000000000 - diff --git a/test/input/14 b/test/input/14 deleted file mode 100644 index 16a806ffec7ba..0000000000000 --- a/test/input/14 +++ /dev/null @@ -1,5 +0,0 @@ -in 127.0.0.1 127.0.0.1 -in 1.1.1.1 1.2.1.1 -in 1.1.1.2 1.2.1.1 -in 1.1.2.2 1.2.1.1 -in 1.2.2.2 1.2.1.1 diff --git a/test/input/2 b/test/input/2 deleted file mode 100644 index d168af0c716ad..0000000000000 --- a/test/input/2 +++ /dev/null @@ -1,6 +0,0 @@ -in tcp 127.0.0.1,1 127.0.0.1,21 -in tcp 1.1.1.1,1 1.2.1.1,21 -in udp 127.0.0.1,1 127.0.0.1,21 -in udp 1.1.1.1,1 1.2.1.1,21 -in icmp 127.0.0.1 127.0.0.1 -in icmp 1.1.1.1 1.2.1.1 diff --git a/test/input/3 b/test/input/3 deleted file mode 100644 index 16a806ffec7ba..0000000000000 --- a/test/input/3 +++ /dev/null @@ -1,5 +0,0 @@ -in 127.0.0.1 127.0.0.1 -in 1.1.1.1 1.2.1.1 -in 1.1.1.2 1.2.1.1 -in 1.1.2.2 1.2.1.1 -in 1.2.2.2 1.2.1.1 diff --git a/test/input/4 b/test/input/4 deleted file mode 100644 index 2956d1b154543..0000000000000 --- a/test/input/4 +++ /dev/null @@ -1,5 +0,0 @@ -in 127.0.0.1 127.0.0.1 -in 1.1.1.1 1.1.1.1 -in 1.1.1.1 1.1.1.2 -in 1.1.1.1 1.1.2.2 -in 1.1.1.1 1.2.2.2 diff --git a/test/input/5 b/test/input/5 deleted file mode 100644 index 41600c10763bb..0000000000000 --- a/test/input/5 +++ /dev/null @@ -1,28 +0,0 @@ -in tcp 1.1.1.1,0 2.2.2.2,2222 -in tcp 1.1.1.1,1 2.2.2.2,2222 -in tcp 1.1.1.1,23 2.2.2.2,2222 -in tcp 1.1.1.1,21 2.2.2.2,2222 -in tcp 1.1.1.1,1023 2.2.2.2,2222 -in tcp 1.1.1.1,1024 2.2.2.2,2222 -in tcp 1.1.1.1,1025 2.2.2.2,2222 -in tcp 1.1.1.1,32767 2.2.2.2,2222 -in tcp 1.1.1.1,32768 2.2.2.2,2222 -in tcp 1.1.1.1,65535 2.2.2.2,2222 -in tcp 1.1.1.1,5999 2.2.2.2,2222 -in tcp 1.1.1.1,6000 2.2.2.2,2222 -in tcp 1.1.1.1,6009 2.2.2.2,2222 -in tcp 1.1.1.1,6010 2.2.2.2,2222 -in udp 1.1.1.1,0 2.2.2.2,2222 -in udp 1.1.1.1,1 2.2.2.2,2222 -in udp 1.1.1.1,23 2.2.2.2,2222 -in udp 1.1.1.1,21 2.2.2.2,2222 -in udp 1.1.1.1,1023 2.2.2.2,2222 -in udp 1.1.1.1,1024 2.2.2.2,2222 -in udp 1.1.1.1,1025 2.2.2.2,2222 -in udp 1.1.1.1,32767 2.2.2.2,2222 -in udp 1.1.1.1,32768 2.2.2.2,2222 -in udp 1.1.1.1,65535 2.2.2.2,2222 -in udp 1.1.1.1,5999 2.2.2.2,2222 -in udp 1.1.1.1,6000 2.2.2.2,2222 -in udp 1.1.1.1,6009 2.2.2.2,2222 -in udp 1.1.1.1,6010 2.2.2.2,2222 diff --git a/test/input/6 b/test/input/6 deleted file mode 100644 index 21f0be3336c5c..0000000000000 --- a/test/input/6 +++ /dev/null @@ -1,28 +0,0 @@ -in tcp 2.2.2.2,2222 1.1.1.1,0 -in tcp 2.2.2.2,2222 1.1.1.1,1 -in tcp 2.2.2.2,2222 1.1.1.1,23 -in tcp 2.2.2.2,2222 1.1.1.1,21 -in tcp 2.2.2.2,2222 1.1.1.1,1023 -in tcp 2.2.2.2,2222 1.1.1.1,1024 -in tcp 2.2.2.2,2222 1.1.1.1,1025 -in tcp 2.2.2.2,2222 1.1.1.1,32767 -in tcp 2.2.2.2,2222 1.1.1.1,32768 -in tcp 2.2.2.2,2222 1.1.1.1,65535 -in tcp 2.2.2.2,2222 1.1.1.1,5999 -in tcp 2.2.2.2,2222 1.1.1.1,6000 -in tcp 2.2.2.2,2222 1.1.1.1,6009 -in tcp 2.2.2.2,2222 1.1.1.1,6010 -in udp 2.2.2.2,2222 1.1.1.1,0 -in udp 2.2.2.2,2222 1.1.1.1,1 -in udp 2.2.2.2,2222 1.1.1.1,23 -in udp 2.2.2.2,2222 1.1.1.1,21 -in udp 2.2.2.2,2222 1.1.1.1,1023 -in udp 2.2.2.2,2222 1.1.1.1,1024 -in udp 2.2.2.2,2222 1.1.1.1,1025 -in udp 2.2.2.2,2222 1.1.1.1,32767 -in udp 2.2.2.2,2222 1.1.1.1,32768 -in udp 2.2.2.2,2222 1.1.1.1,65535 -in udp 2.2.2.2,2222 1.1.1.1,5999 -in udp 2.2.2.2,2222 1.1.1.1,6000 -in udp 2.2.2.2,2222 1.1.1.1,6009 -in udp 2.2.2.2,2222 1.1.1.1,6010 diff --git a/test/input/7 b/test/input/7 deleted file mode 100644 index 2721af2fb71ec..0000000000000 --- a/test/input/7 +++ /dev/null @@ -1,9 +0,0 @@ -in icmp 1.1.1.1 2.1.1.1 echo -in icmp 1.1.1.1 2.1.1.1 echo,1 -in icmp 1.1.1.1 2.1.1.1 echo,3 -in icmp 1.1.1.1 2.1.1.1 unreach -in icmp 1.1.1.1 2.1.1.1 unreach,1 -in icmp 1.1.1.1 2.1.1.1 unreach,3 -in icmp 1.1.1.1 2.1.1.1 echorep -in icmp 1.1.1.1 2.1.1.1 echorep,1 -in icmp 1.1.1.1 2.1.1.1 echorep,3 diff --git a/test/input/8 b/test/input/8 deleted file mode 100644 index cace511fbeb8f..0000000000000 --- a/test/input/8 +++ /dev/null @@ -1,6 +0,0 @@ -in tcp 1.1.1.1,1 2.1.2.2,1 S -in tcp 1.1.1.1,1 2.1.2.2,1 SA -in tcp 1.1.1.1,1 2.1.2.2,1 SF -in tcp 1.1.1.1,1 2.1.2.2,1 SFPAUR -in tcp 1.1.1.1,1 2.1.2.2,1 PAU -in tcp 1.1.1.1,1 2.1.2.2,1 A diff --git a/test/input/9 b/test/input/9 deleted file mode 100644 index 33f3be392a7da..0000000000000 --- a/test/input/9 +++ /dev/null @@ -1,6 +0,0 @@ -in 1.1.1.1 2.1.1.1 opt lsrr -in 1.1.1.1 2.1.1.1 opt lsrr,ssrr -in 1.1.1.1 2.1.1.1 opt ts -in 1.1.1.1 2.1.1.1 opt sec-class=topsecret -in 1.1.1.1 2.1.1.1 opt ssrr,sec-class=topsecret -in 1.1.1.1 2.1.1.1 opt sec diff --git a/test/input/f13 b/test/input/f13 index 77e537e2b6389..ccd370a7230cf 100644 --- a/test/input/f13 +++ b/test/input/f13 @@ -83,7 +83,7 @@ 4500 0028 0003 4000 3f06 36ca 0101 0101 0201 0101 0400 0019 0040 0000 0000 0000 5010 2000 8678 0000 -# 1.1.1.1,1024 -> 2.1.1.1,25 TTL=63 TCP DF ACK +# 1.1.1.1,1024 -> 2.1.1.1,25 TTL=63 TCP DF ACK (out-of-order) [in] 4500 0028 0003 4000 3f06 36ca 0101 0101 0201 0101 0400 0019 7000 0004 0000 0002 5010 2000 16b2 0000 diff --git a/test/input/f21 b/test/input/f21 new file mode 100644 index 0000000000000..1135cbd01c483 --- /dev/null +++ b/test/input/f21 @@ -0,0 +1,31 @@ +# ICMP dest unreachable with 64 bits in payload (in reply to a TCP packet +# going out) +# IP 4.4.4.4 2.2.2.2 TCP(20480,80) +[out,df0] +4500 003c 4706 4000 ff06 28aa 0404 0404 +0202 0202 5000 0050 0000 0001 0000 0000 +a002 16d0 d8e2 0000 0204 05b4 0402 080a +0047 fbb0 0000 0000 0103 0300 + +# IP 3.3.3.3 -> 4.4.4.4 ICMP (IP(4.4.4.4,6.6.6.6) TCP(20480,80)) UNREACH +[in,df0] +4500 0038 809a 0000 ff01 2d1d 0303 0303 +0404 0404 0303 acab 0000 0000 4500 003c +4706 4000 ff06 28aa 0404 0404 0202 0202 +5000 0050 0000 0001 + +# IP 3.3.3.3 -> 4.4.4.4 ICMP (IP(4.4.4.4,6.6.6.6) TCP(20480,80)) REDIRECT +# ICMP dest unreachable with whole packet in payload (40 bytes = 320 bits) +[in,df0] +4500 0038 809a 0000 ff01 2d1d 0303 0303 +0404 0404 0501 9a9d 0808 0808 4500 003c +4706 4000 ff06 28aa 0404 0404 0202 0202 +5000 0050 0000 0001 + +# IP 3.3.3.3 -> 5.5.5.5 ICMP (IP(4.4.4.4,6.6.6.6) TCP(20480,80)) UNREACH +[in,df0] +4500 0038 809a 0000 ff01 2b1b 0303 0303 +0505 0505 0303 acab 0000 0000 4500 003c +4706 4000 ff06 28aa 0404 0404 0202 0202 +5000 0050 0000 0001 + diff --git a/test/input/f22 b/test/input/f22 new file mode 100644 index 0000000000000..a5221c1abdb2a --- /dev/null +++ b/test/input/f22 @@ -0,0 +1,31 @@ +# ICMP dest unreachable with 64 bits in payload (in reply to a TCP packet +# going out) +# IP 4.4.4.4 2.2.2.2 TCP(20480,80) +[in,df0] +4500 003c 4706 4000 ff06 28aa 0404 0404 +0202 0202 5000 0050 0000 0001 0000 0000 +a002 16d0 d8e2 0000 0204 05b4 0402 080a +0047 fbb0 0000 0000 0103 0300 + +# IP 3.3.3.3 -> 4.4.4.4 ICMP (IP(4.4.4.4,6.6.6.6) TCP(20480,80)) UNREACH +[out,df0] +4500 0038 809a 0000 ff01 2d1d 0303 0303 +0404 0404 0303 acab 0000 0000 4500 003c +4706 4000 ff06 28aa 0404 0404 0202 0202 +5000 0050 0000 0001 + +# IP 3.3.3.3 -> 4.4.4.4 ICMP (IP(4.4.4.4,6.6.6.6) TCP(20480,80)) REDIRECT +# ICMP dest unreachable with whole packet in payload (40 bytes = 320 bits) +[out,df0] +4500 0038 809a 0000 ff01 2d1d 0303 0303 +0404 0404 0501 9a9d 0808 0808 4500 003c +4706 4000 ff06 28aa 0404 0404 0202 0202 +5000 0050 0000 0001 + +# IP 3.3.3.3 -> 5.5.5.5 ICMP (IP(4.4.4.4,6.6.6.6) TCP(20480,80)) UNREACH +[out,df0] +4500 0038 809a 0000 ff01 2b1b 0303 0303 +0505 0505 0303 acab 0000 0000 4500 003c +4706 4000 ff06 28aa 0404 0404 0202 0202 +5000 0050 0000 0001 + diff --git a/test/input/f24 b/test/input/f24 index 1d066822561f1..030772b427f7d 100644 --- a/test/input/f24 +++ b/test/input/f24 @@ -12,7 +12,7 @@ c0a8 0101 0035 eb22 00a9 d7b9 4a82 8180 0c00 0100 0100 0000 3c00 0496 [in,hme0] -4500 004c fc96 2006 4011 d9b4 c0a8 01fe +4500 004c fc96 2007 4011 d9b3 c0a8 01fe c0a8 0101 cbe7 50c0 1300 0200 0100 0078 8c00 0603 6e73 31c0 13c0 1300 0200 0100 0078 8c00 0e02 6e73 0861 6465 6c61 6964 diff --git a/test/input/f25 b/test/input/f25 new file mode 100644 index 0000000000000..a4e31398e012c --- /dev/null +++ b/test/input/f25 @@ -0,0 +1,41 @@ +[in,hme0]+mcast +4500 0081 b02d 0000 0411 53b1 c0a8 01eb +efff fffa 1f48 076c 006d 1bd2 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0a + +[out,hme0] +4500 0108 7aca 0000 4011 79e1 c0a8 01fe +c0a8 01eb 076c 1f48 00f4 5218 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 + +[in,hme0]+mcast +4500 0081 b02d 0000 0411 53b1 c0a8 01eb +efff fffa 1f48 076c 006d 1bd2 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0a + diff --git a/test/input/f26 b/test/input/f26 new file mode 100644 index 0000000000000..2151f72e7cb2a --- /dev/null +++ b/test/input/f26 @@ -0,0 +1,13 @@ +in tcp 1.1.1.1,1001 2.2.2.2,22 S +in tcp 1.1.1.1,1002 2.2.2.2,22 S +in tcp 1.1.1.1,1003 2.2.2.2,22 S +in tcp 1.1.1.1,1004 2.2.2.2,22 S +in tcp 1.1.1.2,1002 2.2.2.2,22 S +in tcp 1.1.1.3,1003 2.2.2.2,22 S +in tcp 1.1.1.4,1004 2.2.2.2,22 S +in tcp 1.1.1.2,1005 2.2.2.2,22 S +in tcp 1.1.1.3,1006 2.2.2.2,22 S +in tcp 1.1.1.4,1007 2.2.2.2,22 S +in tcp 1.1.1.2,1008 2.2.2.2,22 S +in tcp 1.1.1.3,1009 2.2.2.2,22 S +in tcp 1.1.1.4,1010 2.2.2.2,22 S diff --git a/test/input/f27 b/test/input/f27 new file mode 100644 index 0000000000000..f01bf7e6ee733 --- /dev/null +++ b/test/input/f27 @@ -0,0 +1,84 @@ +[in,hme0] +45000028 0000 0000 FF06 b5ca +01010101 02020202 +03e9 0016 00000000 00000000 5002 0000 +a5de 0000 + +[in,hme0] +45000028 0000 0000 FF06 b5ca +01010101 02020202 +03ea 0016 00000000 00000000 5002 0000 +a5dd 0000 + +[in,hme0] +45000028 0000 0000 FF06 b5ca +01010101 02020202 +03eb 0016 00000000 00000000 5002 0000 +a5dc 0000 + +[in,hme0] +45000028 0000 0000 FF06 b5ca +01010101 02020202 +03ec 0016 00000000 00000000 5002 0000 +a5db 0000 + +[in,hme0] +45000028 0000 0000 FF06 b5c9 +01010102 02020202 +03ed 0016 00000000 00000000 5002 0000 +a5d9 0000 + +[in,hme0] +45000028 0000 0000 FF06 b5c8 +01010103 02020202 +03ee 0016 00000000 00000000 5002 0000 +a5d7 0000 + +[in,hme0] +45000028 0000 0000 FF06 b5c7 +01010104 02020202 +03ef 0016 00000000 00000000 5002 0000 +a5d5 0000 + +[in,hme0] +45000028 0000 0000 FF06 b5c9 +01010102 02020202 +03f0 0016 00000000 00000000 5002 0000 +a5d6 0000 + +[in,hme0] +45000028 0000 0000 FF06 b5c8 +01010103 02020202 +03f1 0016 00000000 00000000 5002 0000 +a5d4 0000 + +[in,hme0] +45000028 0000 0000 FF06 b5c7 +01010104 02020202 +03f2 0016 00000000 00000000 5002 0000 +a5d2 0000 + +[in,hme0] +45000028 0000 0000 FF06 b5c9 +01010102 02020202 +03f3 0016 00000000 00000000 5002 0000 +a5d3 0000 + +[in,hme0] +45000028 0000 0000 FF06 b5c8 +01010103 02020202 +03f4 0016 00000000 00000000 5002 0000 +a5d1 0000 + +[in,hme0] +45000028 0000 0000 FF06 b5c7 +01010104 02020202 +03f5 0016 00000000 00000000 5002 0000 +a5cf 0000 + +[in,hme0] +6000 0000 0014 06FF +ef00 1001 2002 0001 0000 0000 0000 0070 +2001 1002 3333 0001 0000 0000 0000 0001 +03f6 0016 0000 0000 0000 0000 5002 0000 292a 0000 + diff --git a/test/input/f28 b/test/input/f28 new file mode 100644 index 0000000000000..8849c140f1fa9 --- /dev/null +++ b/test/input/f28 @@ -0,0 +1,7 @@ +in on nic1 4.4.0.1 4.2.0.2 +in on nic2 4.4.1.1 4.2.1.2 +in on nic3 4.4.2.1 4.2.2.2 +in on nic0 4.4.3.1 4.2.3.2 +in on nic0 4.4.1.1 4.2.1.2 +in on nic0 4.4.2.1 4.2.2.2 +in on nic0 4.4.3.1 4.2.3.2 diff --git a/test/input/f29 b/test/input/f29 new file mode 100644 index 0000000000000..2e717af635b83 --- /dev/null +++ b/test/input/f29 @@ -0,0 +1,11 @@ +in on nic1 4.4.0.1 4.2.0.2 +in on nic2 4.4.1.1 4.2.1.2 +in on nic3 4.4.2.1 4.2.2.2 +in on nic0 udp 4.4.3.1,1000 4.2.3.2,2000 +in on nic0 udp 4.4.3.1,1000 4.2.3.2,2000 +in on nic0 udp 4.4.1.1,1001 4.2.1.2,2001 +in on nic0 udp 4.4.1.1,1001 4.2.1.2,2001 +in on nic0 udp 4.4.2.1,1002 4.2.2.2,2002 +in on nic0 udp 4.4.2.1,1002 4.2.2.2,2002 +in on nic0 udp 4.4.3.1,1003 4.2.3.2,2003 +in on nic0 udp 4.4.3.1,1003 4.2.3.2,2003 diff --git a/test/input/f30 b/test/input/f30 new file mode 100644 index 0000000000000..ebf7dc0618095 --- /dev/null +++ b/test/input/f30 @@ -0,0 +1,16 @@ +in on hme0 udp 1.1.1.1,53 2.1.1.1,53 opt lsrr +in on hme1 udp 2.1.1.1,53 1.1.1.1,53 opt ts,lsrr +in on hme1 udp 2.1.1.1,53 1.1.1.1,53 opt lsrr +in on hme0 udp 1.1.1.1,53 2.1.1.1,53 +in on hme1 udp 2.1.1.1,53 1.1.1.1,53 +in on hme0 tcp 1.1.1.1,12345 2.1.1.1,22 S opt rr +in on hme0 tcp 1.1.1.1,12345 2.1.1.1,22 S +in on hme1 tcp 2.1.1.1,22 1.1.1.1,12345 SA opt rr,ts +in on hme1 tcp 2.1.1.1,22 1.1.1.1,12345 SA opt rr +in on hme1 tcp 2.1.1.1,22 1.1.1.1,12345 SA +in on hme0 tcp 1.1.1.1,12346 2.1.1.1,22 S opt sec-class=secret +in on hme0 tcp 1.1.1.1,12346 2.1.1.1,22 S +in on hme1 tcp 2.1.1.1,22 1.1.1.1,12346 SA opt sec-class=topsecret +in on hme1 tcp 2.1.1.1,22 1.1.1.1,12346 SA opt ts,sec-class=secret +in on hme1 tcp 2.1.1.1,22 1.1.1.1,12346 SA opt sec-class=secret +in on hme1 tcp 2.1.1.1,22 1.1.1.1,12346 SA diff --git a/test/input/ipf6-1 b/test/input/ipf6-1 deleted file mode 100644 index 8cc2d175dc247..0000000000000 --- a/test/input/ipf6-1 +++ /dev/null @@ -1,26 +0,0 @@ -[out,de0] -6000 0000 0020 3aff ef00 0000 0000 0000 -0000 0000 0001 0013 ff02 0000 0000 0000 -0000 0001 ff01 000b 8700 ea32 0000 0000 -ef00 0000 0000 0000 0000 0000 0001 000b -0101 0048 5487 5c6f - -[in,de0] -6000 0000 0020 3aff ef00 0000 0000 0000 -0000 0000 0001 000b ef00 0000 0000 0000 -0000 0000 0001 0013 8800 5322 6000 0000 -ef00 0000 0000 0000 0000 0000 0001 000b -0201 0800 2071 cce1 - -[out,de0] -6000 0000 0010 3a40 ef00 0000 0000 0000 -0000 0000 0001 0013 ef00 0000 0000 0000 -0000 0000 0001 000b 8000 3210 06ff 0002 -9ec3 3c3c 8a82 0300 - -[in,de0] -6000 0000 0010 3aff ef00 0000 0000 0000 -0000 0000 0001 000b ef00 0000 0000 0000 -0000 0000 0001 0013 8100 3110 06ff 0002 -9ec3 3c3c 8a82 0300 - diff --git a/test/input/ipv6.1 b/test/input/ipv6.1 index 3f0fd308102f0..6da8da0e4bbca 100644 --- a/test/input/ipv6.1 +++ b/test/input/ipv6.1 @@ -1,3 +1,8 @@ +# +# traceroute simulation +# +# UDP +# [out,gif0] 6000 0000 0018 1101 ef00 1001 2002 0001 0000 0000 0000 0070 2001 1002 3333 0001 0000 0000 0000 0001 @@ -6,10 +11,14 @@ ef00 1001 2002 0001 0000 0000 0000 0070 f4c1 0000 0344 0000 0004 f8f1 9d3c ddba 0e00 +# +# ICMPV6 +# - Time exceeded +# [in,gif0] 6000 0000 0048 3a40 ef00 1001 0880 6cbf 0000 0000 0000 0001 ef00 1001 2002 0001 0000 0000 0000 0070 -0300 7d44 0000 0000 +0300 f86f 0000 0000 6000 0000 0018 1101 ef00 1001 2002 0001 0000 0000 0000 0070 2001 1002 3333 0001 0000 0000 0000 0001 @@ -18,14 +27,18 @@ ef00 1001 2002 0001 0000 0000 0000 0070 f427 0000 0344 0000 0004 f8f1 9d3c ddba 0e00 +# +# ICMPV6 +# - Time exceeded +# [in,gif0] 6000 0000 0048 3a40 ef00 1001 0880 6cbf 0000 0000 0000 0001 ef00 1001 2002 0001 0000 0000 0000 0070 -0300 7d44 0000 0000 +0300 7266 0000 0000 6000 0000 0018 1101 ef00 1001 2002 1001 0000 0000 0000 0070 2001 1002 3333 0001 0000 0000 0000 0001 -8083 829a +8083 f8a3 0018 f427 0000 0344 0000 0004 f8f1 9d3c ddba 0e00 diff --git a/test/input/ipv6.3 b/test/input/ipv6.3 index e8ad9f2f22d35..3b2ef4d325b31 100644 --- a/test/input/ipv6.3 +++ b/test/input/ipv6.3 @@ -7,19 +7,19 @@ [in,gif0] 6000 0000 0010 3a40 3ffe 8280 0000 2001 0000 0000 0000 4393 3ffe 8280 0000 2001 -0000 0000 0000 4395 8100 3e77 085c 0038 +0000 0000 0000 4395 8100 3e78 085c 0038 0c06 b73d 1b3d 0d00 [in,gif0] 6000 0000 0010 3a40 3ffe 8280 0000 2001 0000 0000 0000 4394 3ffe 8280 0000 2001 -0000 0000 0000 4395 8300 3e77 085c 0038 +0000 0000 0000 4395 8300 3c77 085c 0038 0c06 b73d 1b3d 0d00 [in,gif0] 6000 0000 0010 3a40 3ffe 8280 0000 2001 0000 0000 0000 4394 3ffe 8280 0000 2001 -0000 0000 0000 4395 8000 3e77 085c 0038 +0000 0000 0000 4395 8000 3f77 085c 0038 0c06 b73d 1b3d 0d00 [in,gif0] diff --git a/test/input/ipv6.4 b/test/input/ipv6.4 new file mode 100644 index 0000000000000..eb986ae9e36c2 --- /dev/null +++ b/test/input/ipv6.4 @@ -0,0 +1,522 @@ +# fe80::20c:29ff:fe13:6899 > fe80::20c:29ff:fe21:5742: frag (0|1448) icmp6: echo request +[in,eth0] +6000 0000 05b0 2c40 fe80 0000 0000 0000 +020c 29ff fe13 6899 fe80 0000 0000 0000 +020c 29ff fe21 5742 3a00 0001 0000 0008 +8000 f400 2c0a 0001 fd38 4a42 9e59 0900 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f 4041 4243 4445 4647 +4849 4a4b 4c4d 4e4f 5051 5253 5455 5657 +5859 5a5b 5c5d 5e5f 6061 6263 6465 6667 +6869 6a6b 6c6d 6e6f 7071 7273 7475 7677 +7879 7a7b 7c7d 7e7f 8081 8283 8485 8687 +8889 8a8b 8c8d 8e8f 9091 9293 9495 9697 +9899 9a9b 9c9d 9e9f a0a1 a2a3 a4a5 a6a7 +a8a9 aaab acad aeaf b0b1 b2b3 b4b5 b6b7 +b8b9 babb bcbd bebf c0c1 c2c3 c4c5 c6c7 +c8c9 cacb cccd cecf d0d1 d2d3 d4d5 d6d7 +d8d9 dadb dcdd dedf e0e1 e2e3 e4e5 e6e7 +e8e9 eaeb eced eeef f0f1 f2f3 f4f5 f6f7 +f8f9 fafb fcfd feff 0001 0203 0405 0607 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f 4041 4243 4445 4647 +4849 4a4b 4c4d 4e4f 5051 5253 5455 5657 +5859 5a5b 5c5d 5e5f 6061 6263 6465 6667 +6869 6a6b 6c6d 6e6f 7071 7273 7475 7677 +7879 7a7b 7c7d 7e7f 8081 8283 8485 8687 +8889 8a8b 8c8d 8e8f 9091 9293 9495 9697 +9899 9a9b 9c9d 9e9f a0a1 a2a3 a4a5 a6a7 +a8a9 aaab acad aeaf b0b1 b2b3 b4b5 b6b7 +b8b9 babb bcbd bebf c0c1 c2c3 c4c5 c6c7 +c8c9 cacb cccd cecf d0d1 d2d3 d4d5 d6d7 +d8d9 dadb dcdd dedf e0e1 e2e3 e4e5 e6e7 +e8e9 eaeb eced eeef f0f1 f2f3 f4f5 f6f7 +f8f9 fafb fcfd feff 0001 0203 0405 0607 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f 4041 4243 4445 4647 +4849 4a4b 4c4d 4e4f 5051 5253 5455 5657 +5859 5a5b 5c5d 5e5f 6061 6263 6465 6667 +6869 6a6b 6c6d 6e6f 7071 7273 7475 7677 +7879 7a7b 7c7d 7e7f 8081 8283 8485 8687 +8889 8a8b 8c8d 8e8f 9091 9293 9495 9697 +9899 9a9b 9c9d 9e9f a0a1 a2a3 a4a5 a6a7 +a8a9 aaab acad aeaf b0b1 b2b3 b4b5 b6b7 +b8b9 babb bcbd bebf c0c1 c2c3 c4c5 c6c7 +c8c9 cacb cccd cecf d0d1 d2d3 d4d5 d6d7 +d8d9 dadb dcdd dedf e0e1 e2e3 e4e5 e6e7 +e8e9 eaeb eced eeef f0f1 f2f3 f4f5 f6f7 +f8f9 fafb fcfd feff 0001 0203 0405 0607 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f 4041 4243 4445 4647 +4849 4a4b 4c4d 4e4f 5051 5253 5455 5657 +5859 5a5b 5c5d 5e5f 6061 6263 6465 6667 +6869 6a6b 6c6d 6e6f 7071 7273 7475 7677 +7879 7a7b 7c7d 7e7f 8081 8283 8485 8687 +8889 8a8b 8c8d 8e8f 9091 9293 9495 9697 +9899 9a9b 9c9d 9e9f a0a1 a2a3 a4a5 a6a7 +a8a9 aaab acad aeaf b0b1 b2b3 b4b5 b6b7 +b8b9 babb bcbd bebf c0c1 c2c3 c4c5 c6c7 +c8c9 cacb cccd cecf d0d1 d2d3 d4d5 d6d7 +d8d9 dadb dcdd dedf e0e1 e2e3 e4e5 e6e7 +e8e9 eaeb eced eeef f0f1 f2f3 f4f5 f6f7 +f8f9 fafb fcfd feff 0001 0203 0405 0607 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f 4041 4243 4445 4647 +4849 4a4b 4c4d 4e4f 5051 5253 5455 5657 +5859 5a5b 5c5d 5e5f 6061 6263 6465 6667 +6869 6a6b 6c6d 6e6f 7071 7273 7475 7677 +7879 7a7b 7c7d 7e7f 8081 8283 8485 8687 +8889 8a8b 8c8d 8e8f 9091 9293 9495 9697 +9899 9a9b 9c9d 9e9f a0a1 a2a3 a4a5 a6a7 +a8a9 aaab acad aeaf b0b1 b2b3 b4b5 b6b7 +b8b9 babb bcbd bebf c0c1 c2c3 c4c5 c6c7 +c8c9 cacb cccd cecf d0d1 d2d3 d4d5 d6d7 +d8d9 dadb dcdd dedf e0e1 e2e3 e4e5 e6e7 +e8e9 eaeb eced eeef f0f1 f2f3 f4f5 f6f7 +f8f9 fafb fcfd feff 0001 0203 0405 0607 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f 4041 4243 4445 4647 +4849 4a4b 4c4d 4e4f 5051 5253 5455 5657 +5859 5a5b 5c5d 5e5f 6061 6263 6465 6667 +6869 6a6b 6c6d 6e6f 7071 7273 7475 7677 +7879 7a7b 7c7d 7e7f 8081 8283 8485 8687 +8889 8a8b 8c8d 8e8f 9091 9293 9495 9697 +9899 9a9b 9c9d 9e9f + +# fe80::20c:29ff:fe13:6899 > fe80::20c:29ff:fe21:5742: frag (1448|160) +[in,eth0] +6000 0000 00a8 2c40 fe80 0000 0000 0000 +020c 29ff fe13 6899 fe80 0000 0000 0000 +020c 29ff fe21 5742 3a00 05a8 0000 0008 +a0a1 a2a3 a4a5 a6a7 a8a9 aaab acad aeaf +b0b1 b2b3 b4b5 b6b7 b8b9 babb bcbd bebf +c0c1 c2c3 c4c5 c6c7 c8c9 cacb cccd cecf +d0d1 d2d3 d4d5 d6d7 d8d9 dadb dcdd dedf +e0e1 e2e3 e4e5 e6e7 e8e9 eaeb eced eeef +f0f1 f2f3 f4f5 f6f7 f8f9 fafb fcfd feff +0001 0203 0405 0607 0809 0a0b 0c0d 0e0f +1011 1213 1415 1617 1819 1a1b 1c1d 1e1f +2021 2223 2425 2627 2829 2a2b 2c2d 2e2f +3031 3233 3435 3637 3839 3a3b 3c3d 3e3f + +# fe80::20c:29ff:fe21:5742 > fe80::20c:29ff:fe13:6899: frag (0|1232) icmp6: echo reply +[out,eth0] +6000 0000 04d8 2c40 fe80 0000 0000 0000 +020c 29ff fe21 5742 fe80 0000 0000 0000 +020c 29ff fe13 6899 3a00 0001 9c56 86dd +8100 f300 2c0a 0001 fd38 4a42 9e59 0900 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f 4041 4243 4445 4647 +4849 4a4b 4c4d 4e4f 5051 5253 5455 5657 +5859 5a5b 5c5d 5e5f 6061 6263 6465 6667 +6869 6a6b 6c6d 6e6f 7071 7273 7475 7677 +7879 7a7b 7c7d 7e7f 8081 8283 8485 8687 +8889 8a8b 8c8d 8e8f 9091 9293 9495 9697 +9899 9a9b 9c9d 9e9f a0a1 a2a3 a4a5 a6a7 +a8a9 aaab acad aeaf b0b1 b2b3 b4b5 b6b7 +b8b9 babb bcbd bebf c0c1 c2c3 c4c5 c6c7 +c8c9 cacb cccd cecf d0d1 d2d3 d4d5 d6d7 +d8d9 dadb dcdd dedf e0e1 e2e3 e4e5 e6e7 +e8e9 eaeb eced eeef f0f1 f2f3 f4f5 f6f7 +f8f9 fafb fcfd feff 0001 0203 0405 0607 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f 4041 4243 4445 4647 +4849 4a4b 4c4d 4e4f 5051 5253 5455 5657 +5859 5a5b 5c5d 5e5f 6061 6263 6465 6667 +6869 6a6b 6c6d 6e6f 7071 7273 7475 7677 +7879 7a7b 7c7d 7e7f 8081 8283 8485 8687 +8889 8a8b 8c8d 8e8f 9091 9293 9495 9697 +9899 9a9b 9c9d 9e9f a0a1 a2a3 a4a5 a6a7 +a8a9 aaab acad aeaf b0b1 b2b3 b4b5 b6b7 +b8b9 babb bcbd bebf c0c1 c2c3 c4c5 c6c7 +c8c9 cacb cccd cecf d0d1 d2d3 d4d5 d6d7 +d8d9 dadb dcdd dedf e0e1 e2e3 e4e5 e6e7 +e8e9 eaeb eced eeef f0f1 f2f3 f4f5 f6f7 +f8f9 fafb fcfd feff 0001 0203 0405 0607 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f 4041 4243 4445 4647 +4849 4a4b 4c4d 4e4f 5051 5253 5455 5657 +5859 5a5b 5c5d 5e5f 6061 6263 6465 6667 +6869 6a6b 6c6d 6e6f 7071 7273 7475 7677 +7879 7a7b 7c7d 7e7f 8081 8283 8485 8687 +8889 8a8b 8c8d 8e8f 9091 9293 9495 9697 +9899 9a9b 9c9d 9e9f a0a1 a2a3 a4a5 a6a7 +a8a9 aaab acad aeaf b0b1 b2b3 b4b5 b6b7 +b8b9 babb bcbd bebf c0c1 c2c3 c4c5 c6c7 +c8c9 cacb cccd cecf d0d1 d2d3 d4d5 d6d7 +d8d9 dadb dcdd dedf e0e1 e2e3 e4e5 e6e7 +e8e9 eaeb eced eeef f0f1 f2f3 f4f5 f6f7 +f8f9 fafb fcfd feff 0001 0203 0405 0607 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f 4041 4243 4445 4647 +4849 4a4b 4c4d 4e4f 5051 5253 5455 5657 +5859 5a5b 5c5d 5e5f 6061 6263 6465 6667 +6869 6a6b 6c6d 6e6f 7071 7273 7475 7677 +7879 7a7b 7c7d 7e7f 8081 8283 8485 8687 +8889 8a8b 8c8d 8e8f 9091 9293 9495 9697 +9899 9a9b 9c9d 9e9f a0a1 a2a3 a4a5 a6a7 +a8a9 aaab acad aeaf b0b1 b2b3 b4b5 b6b7 +b8b9 babb bcbd bebf c0c1 c2c3 c4c5 c6c7 +c8c9 cacb cccd cecf d0d1 d2d3 d4d5 d6d7 +d8d9 dadb dcdd dedf e0e1 e2e3 e4e5 e6e7 +e8e9 eaeb eced eeef f0f1 f2f3 f4f5 f6f7 +f8f9 fafb fcfd feff 0001 0203 0405 0607 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f 4041 4243 4445 4647 +4849 4a4b 4c4d 4e4f 5051 5253 5455 5657 +5859 5a5b 5c5d 5e5f 6061 6263 6465 6667 +6869 6a6b 6c6d 6e6f 7071 7273 7475 7677 +7879 7a7b 7c7d 7e7f 8081 8283 8485 8687 +8889 8a8b 8c8d 8e8f 9091 9293 9495 9697 +9899 9a9b 9c9d 9e9f a0a1 a2a3 a4a5 a6a7 +a8a9 aaab acad aeaf b0b1 b2b3 b4b5 b6b7 +b8b9 babb bcbd bebf c0c1 c2c3 c4c5 c6c7 + +# fe80::20c:29ff:fe21:5742 > fe80::20c:29ff:fe13:6899: frag (1232|376) +[out,eth0] +6000 0000 0180 2c40 fe80 0000 0000 0000 +020c 29ff fe21 5742 fe80 0000 0000 0000 +020c 29ff fe13 6899 3a00 04d0 9c56 86dd +c8c9 cacb cccd cecf d0d1 d2d3 d4d5 d6d7 +d8d9 dadb dcdd dedf e0e1 e2e3 e4e5 e6e7 +e8e9 eaeb eced eeef f0f1 f2f3 f4f5 f6f7 +f8f9 fafb fcfd feff 0001 0203 0405 0607 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f 4041 4243 4445 4647 +4849 4a4b 4c4d 4e4f 5051 5253 5455 5657 +5859 5a5b 5c5d 5e5f 6061 6263 6465 6667 +6869 6a6b 6c6d 6e6f 7071 7273 7475 7677 +7879 7a7b 7c7d 7e7f 8081 8283 8485 8687 +8889 8a8b 8c8d 8e8f 9091 9293 9495 9697 +9899 9a9b 9c9d 9e9f a0a1 a2a3 a4a5 a6a7 +a8a9 aaab acad aeaf b0b1 b2b3 b4b5 b6b7 +b8b9 babb bcbd bebf c0c1 c2c3 c4c5 c6c7 +c8c9 cacb cccd cecf d0d1 d2d3 d4d5 d6d7 +d8d9 dadb dcdd dedf e0e1 e2e3 e4e5 e6e7 +e8e9 eaeb eced eeef f0f1 f2f3 f4f5 f6f7 +f8f9 fafb fcfd feff 0001 0203 0405 0607 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f + +# fe80::20c:29ff:fe13:6899 > fe80::20c:29ff:fe21:5742: frag (0|1448) icmp6: echo request +[in,eth0] +6000 0000 05b0 2c40 fe80 0000 0000 0000 +020c 29ff fe13 6899 fe80 0000 0000 0000 +020c 29ff fe21 5742 3a00 0001 0000 0009 +8000 80fb 2c0a 0002 fe38 4a42 105e 0900 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f 4041 4243 4445 4647 +4849 4a4b 4c4d 4e4f 5051 5253 5455 5657 +5859 5a5b 5c5d 5e5f 6061 6263 6465 6667 +6869 6a6b 6c6d 6e6f 7071 7273 7475 7677 +7879 7a7b 7c7d 7e7f 8081 8283 8485 8687 +8889 8a8b 8c8d 8e8f 9091 9293 9495 9697 +9899 9a9b 9c9d 9e9f a0a1 a2a3 a4a5 a6a7 +a8a9 aaab acad aeaf b0b1 b2b3 b4b5 b6b7 +b8b9 babb bcbd bebf c0c1 c2c3 c4c5 c6c7 +c8c9 cacb cccd cecf d0d1 d2d3 d4d5 d6d7 +d8d9 dadb dcdd dedf e0e1 e2e3 e4e5 e6e7 +e8e9 eaeb eced eeef f0f1 f2f3 f4f5 f6f7 +f8f9 fafb fcfd feff 0001 0203 0405 0607 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f 4041 4243 4445 4647 +4849 4a4b 4c4d 4e4f 5051 5253 5455 5657 +5859 5a5b 5c5d 5e5f 6061 6263 6465 6667 +6869 6a6b 6c6d 6e6f 7071 7273 7475 7677 +7879 7a7b 7c7d 7e7f 8081 8283 8485 8687 +8889 8a8b 8c8d 8e8f 9091 9293 9495 9697 +9899 9a9b 9c9d 9e9f a0a1 a2a3 a4a5 a6a7 +a8a9 aaab acad aeaf b0b1 b2b3 b4b5 b6b7 +b8b9 babb bcbd bebf c0c1 c2c3 c4c5 c6c7 +c8c9 cacb cccd cecf d0d1 d2d3 d4d5 d6d7 +d8d9 dadb dcdd dedf e0e1 e2e3 e4e5 e6e7 +e8e9 eaeb eced eeef f0f1 f2f3 f4f5 f6f7 +f8f9 fafb fcfd feff 0001 0203 0405 0607 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f 4041 4243 4445 4647 +4849 4a4b 4c4d 4e4f 5051 5253 5455 5657 +5859 5a5b 5c5d 5e5f 6061 6263 6465 6667 +6869 6a6b 6c6d 6e6f 7071 7273 7475 7677 +7879 7a7b 7c7d 7e7f 8081 8283 8485 8687 +8889 8a8b 8c8d 8e8f 9091 9293 9495 9697 +9899 9a9b 9c9d 9e9f a0a1 a2a3 a4a5 a6a7 +a8a9 aaab acad aeaf b0b1 b2b3 b4b5 b6b7 +b8b9 babb bcbd bebf c0c1 c2c3 c4c5 c6c7 +c8c9 cacb cccd cecf d0d1 d2d3 d4d5 d6d7 +d8d9 dadb dcdd dedf e0e1 e2e3 e4e5 e6e7 +e8e9 eaeb eced eeef f0f1 f2f3 f4f5 f6f7 +f8f9 fafb fcfd feff 0001 0203 0405 0607 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f 4041 4243 4445 4647 +4849 4a4b 4c4d 4e4f 5051 5253 5455 5657 +5859 5a5b 5c5d 5e5f 6061 6263 6465 6667 +6869 6a6b 6c6d 6e6f 7071 7273 7475 7677 +7879 7a7b 7c7d 7e7f 8081 8283 8485 8687 +8889 8a8b 8c8d 8e8f 9091 9293 9495 9697 +9899 9a9b 9c9d 9e9f a0a1 a2a3 a4a5 a6a7 +a8a9 aaab acad aeaf b0b1 b2b3 b4b5 b6b7 +b8b9 babb bcbd bebf c0c1 c2c3 c4c5 c6c7 +c8c9 cacb cccd cecf d0d1 d2d3 d4d5 d6d7 +d8d9 dadb dcdd dedf e0e1 e2e3 e4e5 e6e7 +e8e9 eaeb eced eeef f0f1 f2f3 f4f5 f6f7 +f8f9 fafb fcfd feff 0001 0203 0405 0607 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f 4041 4243 4445 4647 +4849 4a4b 4c4d 4e4f 5051 5253 5455 5657 +5859 5a5b 5c5d 5e5f 6061 6263 6465 6667 +6869 6a6b 6c6d 6e6f 7071 7273 7475 7677 +7879 7a7b 7c7d 7e7f 8081 8283 8485 8687 +8889 8a8b 8c8d 8e8f 9091 9293 9495 9697 +9899 9a9b 9c9d 9e9f a0a1 a2a3 a4a5 a6a7 +a8a9 aaab acad aeaf b0b1 b2b3 b4b5 b6b7 +b8b9 babb bcbd bebf c0c1 c2c3 c4c5 c6c7 +c8c9 cacb cccd cecf d0d1 d2d3 d4d5 d6d7 +d8d9 dadb dcdd dedf e0e1 e2e3 e4e5 e6e7 +e8e9 eaeb eced eeef f0f1 f2f3 f4f5 f6f7 +f8f9 fafb fcfd feff 0001 0203 0405 0607 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f 4041 4243 4445 4647 +4849 4a4b 4c4d 4e4f 5051 5253 5455 5657 +5859 5a5b 5c5d 5e5f 6061 6263 6465 6667 +6869 6a6b 6c6d 6e6f 7071 7273 7475 7677 +7879 7a7b 7c7d 7e7f 8081 8283 8485 8687 +8889 8a8b 8c8d 8e8f 9091 9293 9495 9697 +9899 9a9b 9c9d 9e9f + +# fe80::20c:29ff:fe13:6899 > fe80::20c:29ff:fe21:5742: frag (1448|160) +[in,eth0] +6000 0000 00a8 2c40 fe80 0000 0000 0000 +020c 29ff fe13 6899 fe80 0000 0000 0000 +020c 29ff fe21 5742 3a00 05a8 0000 0009 +a0a1 a2a3 a4a5 a6a7 a8a9 aaab acad aeaf +b0b1 b2b3 b4b5 b6b7 b8b9 babb bcbd bebf +c0c1 c2c3 c4c5 c6c7 c8c9 cacb cccd cecf +d0d1 d2d3 d4d5 d6d7 d8d9 dadb dcdd dedf +e0e1 e2e3 e4e5 e6e7 e8e9 eaeb eced eeef +f0f1 f2f3 f4f5 f6f7 f8f9 fafb fcfd feff +0001 0203 0405 0607 0809 0a0b 0c0d 0e0f +1011 1213 1415 1617 1819 1a1b 1c1d 1e1f +2021 2223 2425 2627 2829 2a2b 2c2d 2e2f +3031 3233 3435 3637 3839 3a3b 3c3d 3e3f + +# fe80::20c:29ff:fe21:5742 > fe80::20c:29ff:fe13:6899: frag (0|1232) icmp6: echo reply +[out,eth0] +6000 0000 04d8 2c40 fe80 0000 0000 0000 +020c 29ff fe21 5742 fe80 0000 0000 0000 +020c 29ff fe13 6899 3a00 0001 9889 f4c1 +8100 7ffb 2c0a 0002 fe38 4a42 105e 0900 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f 4041 4243 4445 4647 +4849 4a4b 4c4d 4e4f 5051 5253 5455 5657 +5859 5a5b 5c5d 5e5f 6061 6263 6465 6667 +6869 6a6b 6c6d 6e6f 7071 7273 7475 7677 +7879 7a7b 7c7d 7e7f 8081 8283 8485 8687 +8889 8a8b 8c8d 8e8f 9091 9293 9495 9697 +9899 9a9b 9c9d 9e9f a0a1 a2a3 a4a5 a6a7 +a8a9 aaab acad aeaf b0b1 b2b3 b4b5 b6b7 +b8b9 babb bcbd bebf c0c1 c2c3 c4c5 c6c7 +c8c9 cacb cccd cecf d0d1 d2d3 d4d5 d6d7 +d8d9 dadb dcdd dedf e0e1 e2e3 e4e5 e6e7 +e8e9 eaeb eced eeef f0f1 f2f3 f4f5 f6f7 +f8f9 fafb fcfd feff 0001 0203 0405 0607 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f 4041 4243 4445 4647 +4849 4a4b 4c4d 4e4f 5051 5253 5455 5657 +5859 5a5b 5c5d 5e5f 6061 6263 6465 6667 +6869 6a6b 6c6d 6e6f 7071 7273 7475 7677 +7879 7a7b 7c7d 7e7f 8081 8283 8485 8687 +8889 8a8b 8c8d 8e8f 9091 9293 9495 9697 +9899 9a9b 9c9d 9e9f a0a1 a2a3 a4a5 a6a7 +a8a9 aaab acad aeaf b0b1 b2b3 b4b5 b6b7 +b8b9 babb bcbd bebf c0c1 c2c3 c4c5 c6c7 +c8c9 cacb cccd cecf d0d1 d2d3 d4d5 d6d7 +d8d9 dadb dcdd dedf e0e1 e2e3 e4e5 e6e7 +e8e9 eaeb eced eeef f0f1 f2f3 f4f5 f6f7 +f8f9 fafb fcfd feff 0001 0203 0405 0607 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f 4041 4243 4445 4647 +4849 4a4b 4c4d 4e4f 5051 5253 5455 5657 +5859 5a5b 5c5d 5e5f 6061 6263 6465 6667 +6869 6a6b 6c6d 6e6f 7071 7273 7475 7677 +7879 7a7b 7c7d 7e7f 8081 8283 8485 8687 +8889 8a8b 8c8d 8e8f 9091 9293 9495 9697 +9899 9a9b 9c9d 9e9f a0a1 a2a3 a4a5 a6a7 +a8a9 aaab acad aeaf b0b1 b2b3 b4b5 b6b7 +b8b9 babb bcbd bebf c0c1 c2c3 c4c5 c6c7 +c8c9 cacb cccd cecf d0d1 d2d3 d4d5 d6d7 +d8d9 dadb dcdd dedf e0e1 e2e3 e4e5 e6e7 +e8e9 eaeb eced eeef f0f1 f2f3 f4f5 f6f7 +f8f9 fafb fcfd feff 0001 0203 0405 0607 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f 4041 4243 4445 4647 +4849 4a4b 4c4d 4e4f 5051 5253 5455 5657 +5859 5a5b 5c5d 5e5f 6061 6263 6465 6667 +6869 6a6b 6c6d 6e6f 7071 7273 7475 7677 +7879 7a7b 7c7d 7e7f 8081 8283 8485 8687 +8889 8a8b 8c8d 8e8f 9091 9293 9495 9697 +9899 9a9b 9c9d 9e9f a0a1 a2a3 a4a5 a6a7 +a8a9 aaab acad aeaf b0b1 b2b3 b4b5 b6b7 +b8b9 babb bcbd bebf c0c1 c2c3 c4c5 c6c7 +c8c9 cacb cccd cecf d0d1 d2d3 d4d5 d6d7 +d8d9 dadb dcdd dedf e0e1 e2e3 e4e5 e6e7 +e8e9 eaeb eced eeef f0f1 f2f3 f4f5 f6f7 +f8f9 fafb fcfd feff 0001 0203 0405 0607 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f 4041 4243 4445 4647 +4849 4a4b 4c4d 4e4f 5051 5253 5455 5657 +5859 5a5b 5c5d 5e5f 6061 6263 6465 6667 +6869 6a6b 6c6d 6e6f 7071 7273 7475 7677 +7879 7a7b 7c7d 7e7f 8081 8283 8485 8687 +8889 8a8b 8c8d 8e8f 9091 9293 9495 9697 +9899 9a9b 9c9d 9e9f a0a1 a2a3 a4a5 a6a7 +a8a9 aaab acad aeaf b0b1 b2b3 b4b5 b6b7 +b8b9 babb bcbd bebf c0c1 c2c3 c4c5 c6c7 + +# fe80::20c:29ff:fe21:5742 > fe80::20c:29ff:fe13:6899: frag (1232|376) +[out,eth0] +6000 0000 0180 2c40 fe80 0000 0000 0000 +020c 29ff fe21 5742 fe80 0000 0000 0000 +020c 29ff fe13 6899 3a00 04d0 9889 f4c1 +c8c9 cacb cccd cecf d0d1 d2d3 d4d5 d6d7 +d8d9 dadb dcdd dedf e0e1 e2e3 e4e5 e6e7 +e8e9 eaeb eced eeef f0f1 f2f3 f4f5 f6f7 +f8f9 fafb fcfd feff 0001 0203 0405 0607 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f 4041 4243 4445 4647 +4849 4a4b 4c4d 4e4f 5051 5253 5455 5657 +5859 5a5b 5c5d 5e5f 6061 6263 6465 6667 +6869 6a6b 6c6d 6e6f 7071 7273 7475 7677 +7879 7a7b 7c7d 7e7f 8081 8283 8485 8687 +8889 8a8b 8c8d 8e8f 9091 9293 9495 9697 +9899 9a9b 9c9d 9e9f a0a1 a2a3 a4a5 a6a7 +a8a9 aaab acad aeaf b0b1 b2b3 b4b5 b6b7 +b8b9 babb bcbd bebf c0c1 c2c3 c4c5 c6c7 +c8c9 cacb cccd cecf d0d1 d2d3 d4d5 d6d7 +d8d9 dadb dcdd dedf e0e1 e2e3 e4e5 e6e7 +e8e9 eaeb eced eeef f0f1 f2f3 f4f5 f6f7 +f8f9 fafb fcfd feff 0001 0203 0405 0607 +0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 +1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 +2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 +3839 3a3b 3c3d 3e3f + +# frag: [0-7:nh][8-15:res][16-31:off][32-64:id] +# Case 4: ipv6,fragment[id=10,off=0,m=1],tcp +[in,eth0] +600a af74 0038 2c40 +fe80 0000 0000 0000 020c 29ff fe21 5742 +fe80 0000 0000 0000 020c 29ff fe6e eb5a +0600 0001 0000 0010 +fff3 0017 52ac fbab 0000 0000 c002 8000 d36b 0000 +0204 05a0 0103 0300 0402 0101 0101 080a 0000 0000 0000 0000 0000 0000 + +# Case 5: ipv6,fragment[id=10,off=5,m=1],data +[in,eth0] +600a af74 0010 2c40 +fe80 0000 0000 0000 020c 29ff fe21 5742 +fe80 0000 0000 0000 020c 29ff fe6e eb5a +0600 0030 0000 0010 +0000 0000 0000 0000 + +# Case 3: ipv6,fragment[id=10,off=1,m=0],tcp +[in,eth0] +600a af74 0034 2c40 +fe80 0000 0000 0000 020c 29ff fe21 5742 +fe80 0000 0000 0000 020c 29ff fe6e eb5a +0600 0008 0000 0010 +0000 0000 b002 8000 d36b 0000 +0204 05a0 0103 0300 0402 0101 0101 080a 0000 0000 0000 0000 + +# Case 1: ipv6,fragment[id=11,off=0,m=1],hopopts,ah[next=dstopts] +[in,eth0] +600a af74 0020 2c40 +fe80 0000 0000 0000 020c 29ff fe21 5742 +fe80 0000 0000 0000 020c 29ff fe6e eb5a +0000 0001 0000 0011 +3300 0000 0000 0000 +3c01 0000 0000 0000 0000 0000 0000 0000 + +# Case 2: ipv6,fragment[id=11,off=3,m=0],dstopts,hop,tcp +[in,eth0] +600a af74 002c 2c40 +fe80 0000 0000 0000 020c 29ff fe21 5742 +fe80 0000 0000 0000 020c 29ff fe6e eb5a +3c00 0008 0000 0011 +0000 0000 0000 0000 +0600 0000 0000 0000 +fff3 0017 52ac fbab 0000 0000 5002 8000 d36b 0000 + +# Case 4: ipv6,fragment[id=10,off=0,m=1],tcp +[out,eth0] +6000 0000 001c 2c40 +fe80 0000 0000 0000 020c 29ff fe6e eb5a +fe80 0000 0000 0000 020c 29ff fe21 5742 +0600 0001 0000 0010 +0017 fff3 0000 0000 52ac fbac 5014 0000 cd26 0000 + +# Normal TCP Reset +[out,eth0] +6000 0000 0014 0640 +fe80 0000 0000 0000 020c 29ff fe6e eb5a +fe80 0000 0000 0000 020c 29ff fe21 5742 +0017 fff3 0000 0000 52ac fbac 5014 0000 cd26 0000 + +# Case 4: ipv6,fragment[id=12,off=0,m=1],tcp +[in,eth0] +600a af74 0038 2c40 +fe80 0000 0000 0000 020c 29ff fe21 5742 +fe80 0000 0000 0000 020c 29ff fe6e eb5a +0600 0001 0000 0012 +fff3 0017 52ac fbab 0000 0000 c002 8000 d36b 0000 +0204 05a0 0103 0300 0402 0101 0101 080a 0000 0000 0000 0000 0000 0000 + diff --git a/test/input/ipv6.6 b/test/input/ipv6.6 index 82efeac624da7..fffbad28ccda0 100644 --- a/test/input/ipv6.6 +++ b/test/input/ipv6.6 @@ -15,3 +15,17 @@ ef00 1001 2002 0001 0000 0000 0000 0070 1100 0008 0000 0001 0000 0000 0000 0000 0000 0000 0000 0000 +[out,gif0] +6000 0000 001e 2c01 +ef00 1001 2002 0001 0000 0000 0000 0070 +2001 1002 3333 0001 0000 0000 0000 0001 +1100 0001 0000 0001 +0000 0000 0000 0000 0000 0000 0000 + +[out,gif0] +6000 0000 0020 2c01 +ef00 1001 2002 0001 0000 0000 0000 0070 +2001 1002 3333 0001 0000 0000 0000 0001 +1100 001c 0000 0001 +0000 0000 0000 0000 0000 0000 0000 0000 + diff --git a/test/input/n10 b/test/input/n10 index 321ed0bf94438..1e919cc4b34d0 100644 --- a/test/input/n10 +++ b/test/input/n10 @@ -1,6 +1,6 @@ # TCP SYN packet with an MSS option [out,ppp0] -4500 002c 10c9 4000 ff06 3289 c0a8 0103 -96cb e002 8032 0015 bd6b c9c8 0000 0000 +4500 002c 10c9 4000 ff06 3289 c0a8 0103 96cb e002 +8032 0015 bd6b c9c8 0000 0000 6002 2238 35f9 0000 0204 05b4 diff --git a/test/input/n100 b/test/input/n100 new file mode 100644 index 0000000000000..94ff8c4be6e54 --- /dev/null +++ b/test/input/n100 @@ -0,0 +1,8 @@ +out on zx0 255 1.1.1.1 2.3.2.3 +out on zx0 255 1.1.1.1 2.2.2.3 +out on zx0 255 1.1.1.2 2.2.2.3 +out on zx0 255 1.2.1.2 2.2.2.3 +out on zx0 255 1.1.1.1 2.2.2.4 +out on zx0 255 1.1.1.1 2.2.2.3 +out on zx0 tcp 1.1.1.1,101 2.3.2.3,203 +out on zx0 tcp 1.1.1.1,101 2.2.2.3,203 diff --git a/test/input/n101 b/test/input/n101 new file mode 100644 index 0000000000000..94ff8c4be6e54 --- /dev/null +++ b/test/input/n101 @@ -0,0 +1,8 @@ +out on zx0 255 1.1.1.1 2.3.2.3 +out on zx0 255 1.1.1.1 2.2.2.3 +out on zx0 255 1.1.1.2 2.2.2.3 +out on zx0 255 1.2.1.2 2.2.2.3 +out on zx0 255 1.1.1.1 2.2.2.4 +out on zx0 255 1.1.1.1 2.2.2.3 +out on zx0 tcp 1.1.1.1,101 2.3.2.3,203 +out on zx0 tcp 1.1.1.1,101 2.2.2.3,203 diff --git a/test/input/n102 b/test/input/n102 new file mode 100644 index 0000000000000..94ff8c4be6e54 --- /dev/null +++ b/test/input/n102 @@ -0,0 +1,8 @@ +out on zx0 255 1.1.1.1 2.3.2.3 +out on zx0 255 1.1.1.1 2.2.2.3 +out on zx0 255 1.1.1.2 2.2.2.3 +out on zx0 255 1.2.1.2 2.2.2.3 +out on zx0 255 1.1.1.1 2.2.2.4 +out on zx0 255 1.1.1.1 2.2.2.3 +out on zx0 tcp 1.1.1.1,101 2.3.2.3,203 +out on zx0 tcp 1.1.1.1,101 2.2.2.3,203 diff --git a/test/input/n103 b/test/input/n103 new file mode 100644 index 0000000000000..7957799d071f4 --- /dev/null +++ b/test/input/n103 @@ -0,0 +1,8 @@ +out on zx0 tcp 1.1.1.1,101 2.3.2.3,203 +out on zx0 tcp 1.1.1.1,101 2.2.2.3,203 +out on zx0 tcp 1.1.1.1,101 2.2.2.3,203 +out on zx0 tcp 1.1.1.2,101 2.2.2.3,203 +out on zx0 tcp 10.10.10.10,101 2.2.2.3,203 +out on zx0 tcp 5.5.5.5,101 2.2.2.3,203 +in on zx0 tcp 2.2.2.3,4000 4.4.4.4,1000 +out on zx0 tcp 7.7.7.7,101 2.2.2.3,203 diff --git a/test/input/n104 b/test/input/n104 new file mode 100644 index 0000000000000..bb46b285608f3 --- /dev/null +++ b/test/input/n104 @@ -0,0 +1,48 @@ +[out,zx0] +4500 0028 0001 0000 ff06 b5c9 0101 0101 0202 0202 +0065 00cb 0000 0001 1000 0001 5010 2000 789d 0000 + +[in,zx0] +4500 0028 0002 0000 ff06 b1c2 0606 0001 0404 0001 +0fa0 03e8 0000 0001 1000 0001 5010 2000 623f 0000 + +[out,zx0] +4500 0028 0003 0000 ff06 b5c7 0101 0101 0202 0202 +0066 00cb 0000 0001 1000 0001 5010 2000 789c 0000 + +[in,zx0] +4500 0028 0004 0000 ff06 b1bf 0606 0001 0404 0002 +0fa0 03e8 0000 0001 1000 0001 5010 2000 623e 0000 + +[out,zx0] +4500 0028 0005 0000 ff06 b5c5 0101 0101 0202 0202 +0067 00cb 0000 0001 1000 0001 5010 2000 789b 0000 + +[in,zx0] +4500 0028 0006 0000 ff06 b1bd 0606 0001 0404 0002 +0fa0 03e9 0000 0001 1000 0001 5010 2000 623d 0000 + +[out,zx0] +4500 0028 0007 0000 ff06 b5c3 0101 0101 0202 0202 +0068 00cb 0000 0001 1000 0001 5010 2000 789a 0000 + +[in,zx0] +4500 0028 0008 0000 ff06 b1ba 0606 0002 0404 0002 +0fa0 03e9 0000 0001 1000 0001 5010 2000 623c 0000 + +[out,zx0] +4500 0028 0009 0000 ff06 b5c1 0101 0101 0202 0202 +0069 00cb 0000 0001 1000 0001 5010 2000 7899 0000 + +[in,zx0] +4500 0028 000a 0000 ff06 b1b8 0606 0002 0404 0002 +0fa1 03e9 0000 0001 1000 0001 5010 2000 623b 0000 + +[out,zx0] +4500 0028 000b 0000 ff06 b5bf 0101 0101 0202 0202 +006a 00cb 0000 0001 1000 0001 5010 2000 7898 0000 + +[in,zx0] +4500 0028 000c 0000 ff06 b1b5 0606 0002 0404 0003 +0fa1 03e9 0000 0001 1000 0001 5010 2000 623a 0000 + diff --git a/test/input/n105 b/test/input/n105 new file mode 100644 index 0000000000000..63b68f0301cb3 --- /dev/null +++ b/test/input/n105 @@ -0,0 +1,8 @@ +[in,zx0] +4500 0028 0001 0000 ff06 b5c9 0101 0101 0202 0202 +0065 0050 0000 0001 1000 0001 5010 2000 7918 0000 + +[out,zx0] +4500 0028 0001 0000 ff06 adc0 0606 0001 0404 0404 +0c38 03e8 0000 0001 1000 0001 5010 2000 61a4 0000 + diff --git a/test/input/n106 b/test/input/n106 new file mode 100644 index 0000000000000..4e933785606e7 --- /dev/null +++ b/test/input/n106 @@ -0,0 +1,8 @@ +[out,zx0] +4500 0028 0001 0000 ff06 b5c9 0101 0101 0202 0202 +0065 0050 0000 0001 1000 0001 5010 2000 7918 0000 + +[in,zx0] +4500 0028 0001 0000 ff06 adc0 0606 0001 0404 0404 +0c38 03e8 0000 0001 1000 0001 5010 2000 61a4 0000 + diff --git a/test/input/n10_6 b/test/input/n10_6 new file mode 100644 index 0000000000000..5c1f5af859687 --- /dev/null +++ b/test/input/n10_6 @@ -0,0 +1,6 @@ +# TCP SYN packet with an MSS option +[out,ppp0] +6000 0000 0018 06ff c0a8 0100 0000 0000 0000 0000 0000 0003 96cb e000 0000 0000 0000 0000 0000 0002 +8032 0015 bd6b c9c8 0000 0000 +6002 2238 35f9 0000 0204 05b4 + diff --git a/test/input/n11_6 b/test/input/n11_6 new file mode 100644 index 0000000000000..128e45ae5c5b3 --- /dev/null +++ b/test/input/n11_6 @@ -0,0 +1,16 @@ +out6 on zx0 255 10:1:1::0 10:1:1::2 +out6 on zx0 255 10:1:1::1 10:1:1::2 +out6 on zx0 255 10:1:1::2 10:1:1::1 +out6 on zx0 255 10::2:2:1 10:1:2::1 +out6 on zx0 255 10::2:2:2 10:1:2::1 +in6 on zx0 255 10:1:1::1 10:1:1::2 +in6 on zx0 255 10:1:1::2 10:1:1::1 +in6 on zx0 255 10::2:2:1 10::2:1:1 +in6 on zx0 255 10::2:2:2 10::2:1:1 +in6 on zx0 255 10::2:2:3 10:1:1::1 +in6 on zx0 255 10::2:3:4 10::2:2:2 +in6 on zx0 255 10:1:1::1 10::2:2:2 +in6 on zx0 255 10:1:1::2 10::2:2:2 +in6 on zx0 255 10:1:1::0 10::3:4:5 +in6 on zx0 255 10:1:1::1 10::3:4:5 +in6 on zx0 255 10:1:1::2 10::3:4:5 diff --git a/test/input/n12 b/test/input/n12 index fb4d76de4755d..16e479ed19642 100644 --- a/test/input/n12 +++ b/test/input/n12 @@ -1,18 +1,18 @@ [out,le0=192.168.1.188] -4510 0040 2020 4000 4006 17e1 c0a8 7e53 -c0a8 0303 12c2 0017 4e33 298e 0000 0000 +4510 0040 2020 4000 4006 17e1 c0a8 7e53 c0a8 0303 +12c2 0017 4e33 298e 0000 0000 b002 4000 07af 0000 0204 05b4 0101 0402 0103 0300 0101 080a 0c72 549e 0000 0000 [in,le0] -4500 003c 00b0 4000 fe06 f5fb c0a8 0303 -c0a8 01bc 0017 2710 f674 e02c 4e33 298f +4500 003c 00b0 4000 fe06 f5fb c0a8 0303 c0a8 01bc +0017 2710 f674 e02c 4e33 298f a012 2798 e317 0000 0101 080a 2c05 b797 0c72 549e 0103 0300 0204 05b4 [out,le0] -4510 0034 493b 4000 4006 eed1 c0a8 7e53 -c0a8 0303 12c2 0017 4e33 298f f674 e02d +4510 0034 493b 4000 4006 eed1 c0a8 7e53 c0a8 0303 +12c2 0017 4e33 298f f674 e02d 8010 4000 8e2a 0000 0101 080a 0c72 549e 2c05 b797 diff --git a/test/input/n12_6 b/test/input/n12_6 new file mode 100644 index 0000000000000..8583acbd7196a --- /dev/null +++ b/test/input/n12_6 @@ -0,0 +1,18 @@ +[out,le0=c0a8:0100::bc] +6000 0000 002c 0640 c0a8 7e00 0000 0000 0000 0000 0000 0053 c0a8 0300 0000 0000 0000 0000 0000 0003 +12c2 0017 4e33 298e 0000 0000 +b002 4000 07af 0000 0204 05b4 0101 0402 +0103 0300 0101 080a 0c72 549e 0000 0000 + +[in,le0] +6000 0000 0028 06fe c0a8 0300 0000 0000 0000 0000 0000 0003 c0a8 0100 0000 0000 0000 0000 0000 00bc +0017 2710 f674 e02c 4e33 298f +a012 2798 e317 0000 0101 080a 2c05 b797 +0c72 549e 0103 0300 0204 05b4 + +[out,le0] +6000 0000 0020 0640 c0a8 7e00 0000 0000 0000 0000 0000 0053 c0a8 0300 0000 0000 0000 0000 0000 0003 +12c2 0017 4e33 298f f674 e02d +8010 4000 8e2a 0000 0101 080a 0c72 549e +2c05 b797 + diff --git a/test/input/n13_6 b/test/input/n13_6 new file mode 100644 index 0000000000000..54b262dc8ea1c --- /dev/null +++ b/test/input/n13_6 @@ -0,0 +1,4 @@ +out6 on le0 192:168:1::1 150:1:1::1 +out6 on le0 192:168:1::1 150:1:1::2 +out6 on le0 192:168:1::2 150:1:1::2 +out6 on le0 192:168:1::3 150:1:1::1 diff --git a/test/input/n14_6 b/test/input/n14_6 new file mode 100644 index 0000000000000..f5dd5d359f642 --- /dev/null +++ b/test/input/n14_6 @@ -0,0 +1,4 @@ +in6 on gre0 tcp 10::2:2:5,2000 203:1:1::1,80 +in6 on gre0 tcp 10::2:2:6,2000 203:1:1::1,80 +in6 on gre0 tcp 10::2:2:7,2000 203:1:1::1,80 +in6 on gre0 tcp 10::2:2:5,2001 203:1:1::1,80 diff --git a/test/input/n15 b/test/input/n15 new file mode 100644 index 0000000000000..715848e764d5c --- /dev/null +++ b/test/input/n15 @@ -0,0 +1,2 @@ +in on le0 tcp 9.9.9.9,10011 5.5.5.5,80 +in on le0 tcp 9.9.9.9,10011 2.2.2.2,80 diff --git a/test/input/n15_6 b/test/input/n15_6 new file mode 100644 index 0000000000000..4a56138724b09 --- /dev/null +++ b/test/input/n15_6 @@ -0,0 +1,2 @@ +in6 on le0 tcp 9:9:9::9,10011 5:5::5:5,80 +in6 on le0 tcp 9:9:9::9,10011 2::2:2:2,80 diff --git a/test/input/n16 b/test/input/n16 index 2e77e40d76713..ad09a45f6735e 100644 --- a/test/input/n16 +++ b/test/input/n16 @@ -8,33 +8,33 @@ a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 [out,vlan2] -4520 0068 17e4 0000 6a11 ccba c05b ac33 -ac1f 5318 1194 07dd 0054 0000 a5a5 a5a5 +4520 0068 17e4 0000 6a11 ccba c05b ac33 ac1f 5318 +1194 07dd 0054 0000 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 -a5a5 a5a5 a5a5 a5a5 +a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 [in,vlan2] -4500 0084 ee0f 0000 8001 e0a2 ac1f 5318 -c05b ac33 0303 4ca1 0000 0000 4520 0068 -17e4 0000 6a11 ccba c05b ac33 ac1f 5318 -1194 07dd 0054 0000 a5a5 a5a5 a5a5 a5a5 +4500 0084 ee0f 0000 8001 e0a2 ac1f 5318 c05b ac33 +0303 4ca1 0000 0000 +4520 0068 17e4 0000 6a11 ccba c05b ac33 ac1f 5318 +1194 07dd 0054 0000 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 -a5a5 a5a5 +a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 [out,vlan0] -4500 0084 ee0f 0000 8001 e0a2 ac1f 5318 -c05b ac33 0303 4ca1 0000 0000 4520 0068 -17e4 0000 6a11 ccba c05b ac33 ac1f 5318 -1194 07dd 0054 0000 a5a5 a5a5 a5a5 a5a5 +4500 0084 ee0f 0000 8001 e0a2 ac1f 5318 c05b ac33 +0303 4ca1 0000 0000 +4520 0068 17e4 0000 6a11 ccba c05b ac33 ac1f 5318 +1194 07dd 0054 0000 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 -a5a5 a5a5 +a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 diff --git a/test/input/n17 b/test/input/n17 new file mode 100644 index 0000000000000..29709de53f62c --- /dev/null +++ b/test/input/n17 @@ -0,0 +1,24 @@ +[out,zx0] +4500 00a0 0000 0100 3f06 7555 0101 0101 0201 0101 +0401 0019 0000 0000 0000 0000 5010 2000 86b7 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 + +[in,zx0] +4500 00a0 0000 0100 3f06 7553 0201 0101 0101 0103 +0401 0019 0000 0000 0000 0000 5010 2000 86b7 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 + diff --git a/test/input/n17_6 b/test/input/n17_6 new file mode 100644 index 0000000000000..a176c158ccc17 --- /dev/null +++ b/test/input/n17_6 @@ -0,0 +1,24 @@ +[out,zx0] +6000 0000 008c 063f 0001 0000 0000 0000 0000 0001 0001 0001 0002 0000 0000 0000 0000 0001 0001 0001 +0401 0019 0000 0000 0000 0000 5010 2000 86b7 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 + +[in,zx0] +6000 0000 008c 063f 0002 0000 0000 0000 0000 0001 0001 0001 0001 0000 0000 0000 0000 0001 0001 0003 +0401 0019 0000 0000 0000 0000 5010 2000 86b7 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 + diff --git a/test/input/n18 b/test/input/n18 new file mode 100644 index 0000000000000..a7a610cf8fb8d --- /dev/null +++ b/test/input/n18 @@ -0,0 +1,8 @@ +out on z0 tcp 2.2.2.2,22 3.3.3.3,30 +out on z0 tcp 2.2.2.2,23 3.3.3.3,31 +out on z0 tcp 2.2.2.2,24 3.3.3.3,32 +out on z0 tcp 2.2.2.2,25 3.3.3.3,33 +out on z0 tcp 2.2.2.2,26 3.3.3.3,34 +out on z0 tcp 2.2.2.2,27 3.3.3.3,35 +out on z0 tcp 2.2.2.2,28 3.3.3.3,36 +out on z0 tcp 2.2.2.2,29 3.3.3.3,37 diff --git a/test/input/n1_6 b/test/input/n1_6 new file mode 100644 index 0000000000000..c1badab9a9cb2 --- /dev/null +++ b/test/input/n1_6 @@ -0,0 +1,34 @@ +out6 on zx0 255 10:1:1::0 10:1:1::2 +out6 on zx0 255 10:1:1::1 10:1:1::2 +out6 on zx0 255 10:1:1::2 10:1:1::1 +out6 on zx0 tcp 10:1:1::2,1025 10:1:1::1,1025 +out6 on zx0 tcp 10:1:1::2,1026 10:1:1::1,1025 +out6 on zx0 255 10::2:2:1 10:1:2::1 +out6 on zx0 255 10::2:2:2 10:1:2::1 +in6 on zx0 255 10:1:1::1 10:1:1::2 +in6 on zx0 255 10:1:1::2 10:1:1::1 +in6 on zx0 255 10::2:2:1 10::2:1:1 +in6 on zx0 255 10::2:2:2 10::2:1:1 +in6 on zx0 255 10::2:2:3 10:1:1::1 +in6 on zx0 255 10::2:3:4 10::2:2:2 +in6 on zx0 255 10:1:1::1 10::2:2:2 +in6 on zx0 255 10:1:1::2 10::2:2:2 +in6 on zx0 255 10:1:1::0 10::3:4:5 +in6 on zx0 255 10:1:1::1 10::3:4:5 +in6 on zx0 255 10:1:1::2 10::3:4:5 +in6 on zx0 tcp 10:1:1::1,1025 10::3:4:5,1025 +out6 on zx0 58 10:1:1::1 10:4:3::2 +in6 on zx0 58 10:4:3::2 10::2:2:2 +in6 on zx0 58 10:4:3::2 10::3:4:1 +in6 on zx0 58 10:4:3::2 10::3:4:2 +in6 on zx0 58 10:4:3::2 10::3:4:3 +in6 on zx0 58 10:4:3::2 10::3:4:4 +in6 on zx0 58 10:4:3::2 10::3:4:5 +out6 on zx0 34 10:1:1::2 10:4:3::2 +in6 on zx0 34 10:4:3::2 10::3:4:4 +out6 on zx0 34 10:1:1::2 10:4:3::4 +in6 on zx0 34 10:4:3::4 10::3:4:5 +out6 on zx0 34 10:1:1::3 10:4:3::4 +in6 on zx0 34 10:4:3::4 10::3:4:6 +out6 on zx0 35 10:1:1::3 10:4:3::4 +in6 on zx0 35 10:4:3::4 10::3:4:7 diff --git a/test/input/n200 b/test/input/n200 new file mode 100644 index 0000000000000..9b021581e1319 --- /dev/null +++ b/test/input/n200 @@ -0,0 +1,6 @@ +[in,bar0] +4500 0028 0000 0000 0006 435a 6363 6363 5858 5858 038d 0050 0000 0000 0000 0000 5000 1000 2491 0000 + +[out,bar0] +4500 0044 0000 0000 ff11 bda6 7f00 0001 7f00 0001 2775 2775 0030 0000 4500 0028 0000 0000 0006 435a 6363 6363 5858 5858 038d 0050 0000 0000 0000 0000 5000 1000 2491 0000 + diff --git a/test/input/n2_6 b/test/input/n2_6 new file mode 100644 index 0000000000000..3ea74ff377aba --- /dev/null +++ b/test/input/n2_6 @@ -0,0 +1,19 @@ +out6 on zx0 tcp 10:1:1::1,1025 10:1:1::1,1025 +out6 on zx0 tcp 10:1:1::1,1025 10:1:1::2,1025 +out6 on zx0 10:1:1::0 10:1:1::2 +out6 on zx0 10:1:1::1 10:1:2::1 +out6 on zx0 tcp 10:1:1::2,1025 10:1:1::1,1025 +out6 on zx0 tcp 10:1:1::2,1025 10:1:1::1,1025 +out6 on zx0 tcp 10:1:1::2,1026 10:1:1::1,1025 +out6 on zx0 udp 10:1:1::2,1025 10:1:1::1,1025 +out6 on zx0 tcp 10:1:1::3,2000 10:1:2::1,80 +out6 on zx0 tcp 10:1:1::3,2001 10:1:3::1,80 +out6 on zx0 tcp 10:1:1::3,2002 10:1:4::1,80 +out6 on zx0 tcp 10:1:1::3,2003 10:1:4::1,80 +in6 on zx0 10:1:1::1 10:1:1::2 +in6 on zx0 tcp 10:1:1::1,1025 10:1:1::2,1025 +in6 on zx0 10:1:1::2 10:1:1::1 +in6 on zx0 tcp 10:1:1::1,1026 10::3:4:5,40000 +in6 on zx0 tcp 10:1:1::1,1025 10::3:4:5,40000 +in6 on zx0 udp 10:1:1::2,1025 10::3:4:5,40001 +in6 on zx0 tcp 10:1:2::1,80 10::3:4:5,40001 diff --git a/test/input/n4_6 b/test/input/n4_6 new file mode 100644 index 0000000000000..8f0f423bc27b3 --- /dev/null +++ b/test/input/n4_6 @@ -0,0 +1,10 @@ +in6 on zx0 tcp 10:3:3::3,12345 10:1:1::1,23 +out6 on zx0 tcp 10::2:2:1,10023 10:3:3::3,12345 +in6 on zx0 tcp 10:3:3::3,12345 10:1:1::1,53 +out6 on zx0 tcp 10::2:2:1,10053 10:3:3::3,12345 +in6 on zx0 tcp 10:3:3::3,12346 10:1:0::0,23 +out6 on zx0 tcp 10::2:2:1,10023 10:3:3::3,12346 +in6 on zx0 udp 10:3:3::3,12345 10:1:1::0,53 +out6 on zx0 udp 10::2:2:1,10053 10:3:3::3,12345 +in6 on zx0 tcp 10:3:3::3,12345 10:1:1::0,53 +out6 on zx0 tcp 10::2:2:1,53 10:3:3::3,12345 diff --git a/test/input/n5_6 b/test/input/n5_6 new file mode 100644 index 0000000000000..9ac0c29c4a39d --- /dev/null +++ b/test/input/n5_6 @@ -0,0 +1,54 @@ +out6 on zx0 255 10:1:1::0 10:1:1::2 +out6 on zx0 255 10:1:1::1 10:1:1::2 +out6 on zx0 255 10:1:1::2 10:1:1::1 +out6 on zx0 tcp 10:1:1::2,1025 10:1:1::1,1025 +out6 on zx0 tcp 10:1:1::2,1026 10:1:1::1,1025 +out6 on zx0 255 10::2:2:1 10:1:2::1 +out6 on zx0 255 10::2:2:2 10:1:2::1 +in6 on zx0 255 10:1:1::1 10:1:1::2 +in6 on zx0 255 10:1:1::2 10:1:1::1 +in6 on zx0 255 10::2:2:1 10::2:1:1 +in6 on zx0 255 10::2:2:2 10::2:1:1 +in6 on zx0 255 10::2:2:3 10:1:1::1 +in6 on zx0 255 10::2:3:4 10::2:2:2 +in6 on zx0 255 10:1:1::1 10::2:2:2 +in6 on zx0 255 10:1:1::2 10::2:2:2 +in6 on zx0 255 10:1:1::0 10::3:4:5 +in6 on zx0 255 10:1:1::1 10::3:4:5 +in6 on zx0 255 10:1:1::2 10::3:4:5 +in6 on zx0 tcp 10:1:1::1,1025 10::3:4:5,1025 +out6 on zx0 58 10:1:1::1 10:4:3::2 +in6 on zx0 58 10:4:3::2 10::2:2:2 +in6 on zx0 58 10:4:3::2 10::3:4:3 +in6 on zx0 58 10:4:3::2 10::3:4:5 +out6 on zx0 34 10:1:1::2 10:4:3::2 +in6 on zx0 34 10:4:3::2 10::3:4:4 +out6 on zx0 34 10:1:1::2 10:4:3::4 +in6 on zx0 34 10:4:3::4 10::3:4:5 +out6 on zx0 34 10:1:1::3 10:4:3::4 +in6 on zx0 34 10:4:3::4 10::3:4:6 +out6 on zx0 35 10:1:1::3 10:4:3::4 +in6 on zx0 35 10:4:3::4 10::3:4:7 +out6 on zx0 tcp 10:1:1::1,1025 10:1:1::1,1025 +out6 on zx0 tcp 10:1:1::1,1025 10:1:1::2,1025 +out6 on zx0 10:1:1::0 10:1:1::2 +out6 on zx0 10:1:1::1 10:1:2::1 +out6 on zx0 tcp 10:1:1::2,1025 10:1:1::1,1025 +out6 on zx0 tcp 10:1:1::2,1025 10:1:1::1,1025 +out6 on zx0 tcp 10:1:1::2,1026 10:1:1::1,1025 +out6 on zx0 udp 10:1:1::2,1025 10:1:1::1,1025 +out6 on zx0 tcp 10:1:1::3,2000 10:1:2::1,80 +out6 on zx0 tcp 10:1:1::3,2001 10:1:3::1,80 +out6 on zx0 tcp 10:1:1::3,2002 10:1:4::1,80 +out6 on zx0 tcp 10:1:1::3,2003 10:1:4::1,80 +in6 on zx0 10:1:1::1 10:1:1::2 +in6 on zx0 tcp 10:1:1::1,1025 10:1:1::2,1025 +in6 on zx0 10:1:1::2 10:1:1::1 +out6 on zx0 tcp 10:1:1::1,1026 10::3:4:5,40000 +in6 on zx0 tcp 10:1:1::1,1026 10::3:4:5,40000 +out6 on zx0 tcp 10:1:1::1,1025 10::3:4:5,40000 +in6 on zx0 tcp 10:1:1::1,1025 10::3:4:5,40000 +out6 on zx0 udp 10:1:1::2,1025 10::3:4:5,40001 +in6 on zx0 udp 10:1:1::2,1025 10::3:4:5,40001 +out6 on zx0 tcp 10:1:2::1,80 10::3:4:5,40001 +in6 on zx0 tcp 10:1:2::1,80 10::3:4:5,40001 diff --git a/test/input/n6_6 b/test/input/n6_6 new file mode 100644 index 0000000000000..18300cd145525 --- /dev/null +++ b/test/input/n6_6 @@ -0,0 +1,13 @@ +in6 on zx0 tcp 10::2:2:2,12345 10:1:1::1,23 +in6 on zx0 tcp 10::2:2:2,12345 10:1:1::2,23 +in6 on zx0 tcp 10:3:0::1,12345 10:1:2::2,23 +in6 on zx0 tcp 10:3:0::1,12345 10::2:2:2,23 +in6 on zx0 tcp 10:3:3::3,12345 10:1:1::1,23 +in6 on zx0 tcp 10::2:2:2,12345 10:1:1::1,53 +in6 on zx0 tcp 10:3:3::3,12345 10:1:1::1,53 +in6 on zx0 tcp 10::2:2:2,12345 10:1:0::0,23 +in6 on zx0 tcp 10:3:3::3,12345 10:1:0::0,23 +in6 on zx0 udp 10::2:2:2,12345 10:1:1::0,53 +in6 on zx0 udp 10:3:3::3,12345 10:1:1::0,53 +in6 on zx0 tcp 10::2:2:2,12345 10:1:1::0,53 +in6 on zx0 tcp 10:3:3::3,12345 10:1:1::0,53 diff --git a/test/input/n7_6 b/test/input/n7_6 new file mode 100644 index 0000000000000..b31a1def4f48d --- /dev/null +++ b/test/input/n7_6 @@ -0,0 +1,9 @@ +in6 on zx0 tcp 10::2:3:1,1230 10:1:1::1,22 +in6 on zx0 tcp 10::2:3:1,1231 10:1:1::1,23 +in6 on zx0 tcp 10::2:3:1,1232 10:1:1::1,50 +in6 on zx0 tcp 10::2:3:1,1233 10:1:1::1,79 +in6 on zx0 tcp 10::2:3:1,1234 10:1:1::1,80 +in6 on zx0 tcp 10::2:3:1,1235 10:1:1::2,80 +in6 on zx0 tcp 10::2:3:1,1236 10:1:1::3,80 +in6 on zx0 tcp 10::2:3:1,1237 10:1:1::4,80 +in6 on zx0 tcp 10::2:3:1,1238 10:1:1::4,80 diff --git a/test/input/n8 b/test/input/n8 index 1f5b2130ba28c..c0a5b3fd7dd06 100644 --- a/test/input/n8 +++ b/test/input/n8 @@ -1,27 +1,31 @@ #v tos len id off ttl p sum src dst # ICMP ECHO (ping) exchange -[out,icmp0] 4500 0054 8bc1 0000 ff01 23dc 0202 0202 0404 0404 +[out,icmp0] +4500 0054 8bc1 0000 ff01 23dc 0202 0202 0404 0404 0800 efdf 6220 0000 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 -[in,icmp0] 4500 0054 3fd5 4000 ff01 1fc1 0404 0404 0a0a 0a01 +[in,icmp0] +4500 0054 3fd5 4000 ff01 1fc1 0404 0404 0a0a 0a01 0000 f7df 6220 0000 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 -[out,icmp0] 4500 0054 8bc1 0000 ff01 23dc 0202 0202 0404 0404 +[out,icmp0] +4500 0054 8bc1 0000 ff01 23dc 0202 0202 0404 0404 0800 efde 6220 0001 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 -[in,icmp0] 4500 0054 3fd5 4000 ff01 1fc1 0404 0404 0a0a 0a01 +[in,icmp0] +4500 0054 3fd5 4000 ff01 1fc1 0404 0404 0a0a 0a01 0000 f7de 6220 0001 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 diff --git a/test/input/n8_6 b/test/input/n8_6 new file mode 100644 index 0000000000000..8039f78df638f --- /dev/null +++ b/test/input/n8_6 @@ -0,0 +1,37 @@ +#v tos len id off ttl p sum src dst +# ICMP ECHO (ping) exchange +[out,icmp0] +6000 0000 0040 3aff 0002 0000 0000 0000 0000 0002 0002 0002 0004 0004 0004 0000 0000 0000 0000 0004 +8000 774d 6220 0000 3f6f 6e80 000b +0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 +1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 +2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 +3637 + +# ECHO reply +[in,icmp0] +6000 0000 0040 3aff 0004 0004 0004 0000 0000 0000 0000 0004 0010 0010 0010 0000 0000 0000 0000 0001 +8100 7624 6220 0000 3f6f 6e80 000b +0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 +1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 +2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 +3637 + +# ECHO request +[out,icmp0] +6000 0000 0040 3aff 0002 0000 0000 0000 0000 0002 0002 0002 0004 0004 0004 0000 0000 0000 0000 0004 +8000 774c 6220 0001 3f6f 6e80 000b +0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 +1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 +2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 +3637 + +# ECHO reply +[in,icmp0] +6000 0000 0040 3aff 0004 0004 0004 0000 0000 0000 0000 0004 0010 0010 0010 0000 0000 0000 0000 0001 +8100 7623 6220 0001 3f6f 6e80 000b +0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 +1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 +2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 +3637 + diff --git a/test/input/n9 b/test/input/n9 index c4aada8f2c709..5c2d3c7dfebda 100644 --- a/test/input/n9 +++ b/test/input/n9 @@ -1,27 +1,31 @@ #v tos len id off ttl p sum src dst # ICMP ECHO (ping) exchange -[in,icmp0] 4500 0054 8bc1 0000 ff01 23dc 0202 0202 0404 0404 +[in,icmp0] +4500 0054 8bc1 0000 ff01 23dc 0202 0202 0404 0404 0800 efdf 6220 0000 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 -[out,icmp0] 4500 0054 3fd5 4000 ff01 23c5 0a0a 0a01 0202 0202 +[out,icmp0] +4500 0054 3fd5 4000 ff01 23c5 0a0a 0a01 0202 0202 0000 f7df 6220 0000 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 -[in,icmp0] 4500 0054 8bc1 0000 ff01 23dc 0202 0202 0404 0404 +[in,icmp0] +4500 0054 8bc1 0000 ff01 23dc 0202 0202 0404 0404 0800 efde 6220 0001 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 -[out,icmp0] 4500 0054 3fd5 4000 ff01 23c5 0a0a 0a01 0202 0202 +[out,icmp0] +4500 0054 3fd5 4000 ff01 23c5 0a0a 0a01 0202 0202 0000 f7de 6220 0001 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 diff --git a/test/input/n9_6 b/test/input/n9_6 new file mode 100644 index 0000000000000..42db09dd3653c --- /dev/null +++ b/test/input/n9_6 @@ -0,0 +1,34 @@ +#v tos len id off ttl p sum src dst +# ICMP ECHO (ping) exchange +[in,icmp0] +6000 0000 0040 3aff 0002 0000 0000 0000 0000 0002 0002 0002 0004 0004 0004 0000 0000 0000 0000 0004 +8000 774d 6220 0000 3f6f 6e80 000b +0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 +1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 +2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 +3637 + +[out,icmp0] +6000 0000 0040 3aff 0010 0010 0010 0000 0000 0000 0000 0001 0002 0000 0000 0000 0000 0002 0002 0002 +8100 762c 6220 0000 3f6f 6e80 000b +0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 +1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 +2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 +3637 + +[in,icmp0] +6000 0000 0040 3aff 0002 0000 0000 0000 0000 0002 0002 0002 0004 0004 0004 0000 0000 0000 0000 0004 +8000 774c 6220 0001 3f6f 6e80 000b +0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 +1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 +2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 +3637 + +[out,icmp0] +6000 0000 0040 3aff 0010 0010 0010 0000 0000 0000 0000 0001 0002 0000 0000 0000 0000 0002 0002 0002 +8100 762b 6220 0001 3f6f 6e80 000b +0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 +1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 +2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 +3637 + diff --git a/test/input/ni1 b/test/input/ni1 index fb6b0b63e5f99..519325fc56b4c 100644 --- a/test/input/ni1 +++ b/test/input/ni1 @@ -1,55 +1,58 @@ #v tos len id off ttl p sum src dst # ICMP timeout exceeded in reply to a ICMP packet going out. +# 2.2.2.2,44489 -> 4.4.4.4,33438 [out,df0] -4500 0028 4706 4000 0111 26b4 0202 0202 -0404 0404 afc9 829e 0014 6b10 0402 0000 -3be5 468d 000a cfc3 +4500 0028 4706 4000 0111 26b4 0202 0202 0404 0404 +afc9 829e 0014 6b10 +0402 0000 3be5 468d 000a cfc3 [in,df0] -4500 0038 809a 0000 ff01 2919 0303 0303 -0606 0606 0b00 5f7b 0000 0000 +4500 0038 809a 0000 ff01 2919 0303 0303 0606 0606 +0b00 5f7b 0000 0000 4500 0028 0000 4000 0111 65b2 0606 0606 0404 0404 afc9 829e 0014 6308 [in,df0] -4500 0044 809a 0000 ff01 290d 0303 0303 -0606 0606 0b00 0939 0000 0000 +4500 0044 809a 0000 ff01 290d 0303 0303 0606 0606 +0b00 0939 0000 0000 4500 0028 0000 4000 0111 65b2 0606 0606 0404 0404 afc9 829e 0014 6308 0402 0000 3be5 468d 000a cfc3 +# 2.2.2.2,2048 -> 4.4.4.4,33438 [out,df0] -4500 0028 4706 4000 0111 26b4 0202 0202 -0404 0404 0800 829e 0014 12da 0402 0000 -3be5 468d 000a cfc3 +4500 0028 4706 4000 0111 26b4 0202 0202 0404 0404 +0800 829e 0014 12da +0402 0000 3be5 468d 000a cfc3 [in,df0] -4500 0038 809a 0000 ff01 2918 0303 0303 -0606 0607 0b00 5f7c 0000 0000 +4500 0038 809a 0000 ff01 2918 0303 0303 0606 0607 +0b00 5f7c 0000 0000 4500 0028 0000 4000 0111 65b1 0606 0607 0404 0404 4e20 829e 0014 c4b0 [in,df0] -4500 0044 809a 0000 ff01 290c 0303 0303 -0606 0607 0b00 093a 0000 0000 +4500 0044 809a 0000 ff01 290c 0303 0303 0606 0607 +0b00 093a 0000 0000 4500 0028 0000 4000 0111 65b1 0606 0607 0404 0404 4e20 829e 0014 c4b0 0402 0000 3be5 468d 000a cfc3 +# 2.2.2.2,20480 -> 4.4.4.4,33438 [out,df0] -4500 0028 4706 4000 0111 26b4 0202 0202 -0404 0404 5000 829e 0014 cad9 0402 0000 -3be5 468d 000a cfc3 +4500 0028 4706 4000 0111 26b4 0202 0202 0404 0404 +5000 829e 0014 cad9 +0402 0000 3be5 468d 000a cfc3 [in,df0] -4500 0038 809a 0000 ff01 2917 0303 0303 -0606 0608 0b00 0775 0000 0000 +4500 0038 809a 0000 ff01 2917 0303 0303 0606 0608 +0b00 0775 0000 0000 4500 0028 0000 4000 0111 65b0 0606 0608 0404 0404 07d0 829e 0014 6308 [in,df0] -4500 0044 809a 0000 ff01 290b 0303 0303 -0606 0608 0b00 093b 0000 0000 +4500 0044 809a 0000 ff01 290b 0303 0303 0606 0608 +0b00 093b 0000 0000 4500 0028 0000 4000 0111 65b0 0606 0608 0404 0404 07d0 829e 0014 0b00 0402 0000 3be5 468d 000a cfc3 diff --git a/test/input/ni10 b/test/input/ni10 index 48ac22570283c..636c4f1b2d6ab 100644 --- a/test/input/ni10 +++ b/test/input/ni10 @@ -2,7 +2,9 @@ # ICMP dest unreachable with 64 bits in payload (in reply to a TCP packet # going out) # IP 4.4.4.4 2.2.2.2 TCP(20480,80) -[in,df0] 45 00 00 3c 47 06 40 00 ff 06 28 aa 04 04 04 04 02 02 02 02 50 00 00 50 00 00 00 01 00 00 00 00 a0 02 16 d0 d8 e2 00 00 02 04 05 b4 04 02 08 0a 00 47 fb b0 00 00 00 00 01 03 03 00 +[in,df0] +4500 003c 4706 4000 ff06 28aa 0404 0404 0202 0202 +5000 0050 0000 0001 0000 0000 a002 16d0 d8e2 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 # IP 3.3.3.3 -> 4.4.4.4 ICMP (IP(4.4.4.4,6.6.6.6) TCP(20480,80)) [out,df0] @@ -13,7 +15,11 @@ # IP 3.3.3.3 -> 4.4.4.4 ICMP (IP(4.4.4.4,6.6.6.6) TCP(20480,80)) # ICMP dest unreachable with whole packet in payload (40 bytes = 320 bits) -[out,df0] 45 00 00 58 80 9a 00 00 ff 01 2c fd 03 03 03 03 04 04 04 04 03 03 11 3f 00 00 00 00 45 00 00 3c 47 06 40 00 ff 06 20 a2 04 04 04 04 06 06 06 06 50 00 00 50 00 00 00 01 00 00 00 00 a0 02 16 d0 d0 da 00 00 02 04 05 b4 04 02 08 0a 00 47 fb b0 00 00 00 00 01 03 03 00 +[out,df0] +4500 0058 809a 0000 ff01 2cfd 0303 0303 0404 0404 +0303 113f 0000 0000 +4500 003c 4706 4000 ff06 20a2 0404 0404 0606 0606 +5000 0050 0000 0001 0000 0000 a002 16d0 d0da 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 # IP 3.3.3.3 -> 4.4.4.4 ICMP (IP(4.4.4.4,6.6.6.6) TCP(20480,80)) [out,df0] diff --git a/test/input/ni11 b/test/input/ni11 index 788e6036c4071..0650abb703423 100644 --- a/test/input/ni11 +++ b/test/input/ni11 @@ -1,7 +1,9 @@ #v tos len id off ttl p sum src dst # ICMP dest unreachable with 64 bits in payload (in reply to a TCP packet # going out) -[in,df0] 45 00 00 3c 47 06 40 00 ff 06 20 aa 04 04 04 04 0a 02 02 02 50 00 05 00 00 00 00 01 00 00 00 00 a0 02 16 d0 cc 32 00 00 02 04 05 b4 04 02 08 0a 00 47 fb b0 00 00 00 00 01 03 03 00 +[in,df0] +4500 003c 4706 4000 ff06 20aa 0404 0404 0a02 0202 +5000 0500 0000 0001 0000 0000 a002 16d0 cc32 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 [out,df0] 4500 0038 809a 0000 ff01 2d1d 0303 0303 0404 0404 diff --git a/test/input/ni12 b/test/input/ni12 index 788e6036c4071..c44aacce6da56 100644 --- a/test/input/ni12 +++ b/test/input/ni12 @@ -1,24 +1,26 @@ #v tos len id off ttl p sum src dst # ICMP dest unreachable with 64 bits in payload (in reply to a TCP packet # going out) -[in,df0] 45 00 00 3c 47 06 40 00 ff 06 20 aa 04 04 04 04 0a 02 02 02 50 00 05 00 00 00 00 01 00 00 00 00 a0 02 16 d0 cc 32 00 00 02 04 05 b4 04 02 08 0a 00 47 fb b0 00 00 00 00 01 03 03 00 +[in,df0] +4500 003c 4706 4000 ff06 20aa 0404 0404 0a02 0202 +5000 0500 0000 0001 0000 0000 a002 16d0 cc32 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 [out,df0] 4500 0038 809a 0000 ff01 2d1d 0303 0303 0404 0404 -0303 0fa3 0000 0000 +0303 10bb 0000 0000 4500 003c 4706 4000 ff06 2aac 0404 0404 0101 0101 -5000 9d58 0000 0001 +5000 9c40 0000 0001 # ICMP dest unreachable with whole packet in payload (40 bytes = 320 bits) [out,df0] 4500 0058 809a 0000 ff01 2cfd 0303 0303 0404 0404 0303 0735 0000 0000 4500 003c 4706 4000 ff06 2aac 0404 0404 0101 0101 -5000 9d58 0000 0001 0000 0000 a002 16d0 3ddc 0000 +5000 9c40 0000 0001 0000 0000 a002 16d0 3ef4 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 [out,df0] 4500 0038 809a 0000 ff01 2b1b 0303 0303 0505 0505 -0303 0fa3 0000 0000 -4500 003c 4706 4000 ff06 2aab 0404 0404 0101 0102 5000 9d58 0000 0001 +0303 10bb 0000 0000 +4500 003c 4706 4000 ff06 2aab 0404 0404 0101 0102 5000 9c40 0000 0001 diff --git a/test/input/ni13 b/test/input/ni13 index 77569eead7028..70c19526ba906 100644 --- a/test/input/ni13 +++ b/test/input/ni13 @@ -1,19 +1,17 @@ # 23:18:36.130424 192.168.113.1.1511 > 192.168.113.3.1723: S 2884651685:2884651685(0) win 64240 <mss 1460,nop,nop,sackOK> (DF) [in,pcn1=192.168.113.3] -4500 0030 5e11 4000 8006 3961 c0a8 7101 -c0a8 7103 05e7 06bb abf0 4aa5 0000 0000 -7002 faf0 21a1 0000 0204 05b4 0101 0402 +4500 0030 5e11 4000 8006 3961 c0a8 7101 c0a8 7103 +05e7 06bb abf0 4aa5 0000 0000 7002 faf0 21a1 0000 0204 05b4 0101 0402 # 23:18:36.130778 192.168.113.3.1723 > 192.168.113.1.1511: S 2774821082:2774821082(0) ack 2884651686 win 32768 <mss 1460> (DF) [out,pcn1] -4500 002c 69a6 4000 4006 6dd0 c0a8 7103 -c0a8 7101 06bb 05e7 a564 68da abf0 4aa6 -6012 8000 a348 0000 0204 05b4 +4500 002c 69a6 4000 4006 6dd0 c0a8 7103 c0a8 7101 +06bb 05e7 a564 68da abf0 4aa6 6012 8000 a348 0000 0204 05b4 # 23:18:36.130784 192.168.113.1.1511 > 192.168.113.3.1723: P 1:157(156) ack 1 win 64240: pptp CTRL_MSGTYPE=SCCRQ PROTO_VER(1.0) FRAME_CAP(A) BEARER_CAP(A) MAX_CHAN(0) FIRM_REV(2600) HOSTNAME() VENDOR(Microsoft Windows NT) (DF) [in,pcn1] -4500 00c4 5e12 4000 8006 38cc c0a8 7101 -c0a8 7103 05e7 06bb abf0 4aa6 a564 68db +4500 00c4 5e12 4000 8006 38cc c0a8 7101 c0a8 7103 +05e7 06bb abf0 4aa6 a564 68db 5018 faf0 e2a0 0000 009c 0001 1a2b 3c4d 0001 0000 0100 0000 0000 0001 0000 0001 0000 0a28 0000 0000 0000 0000 0000 0000 @@ -28,8 +26,8 @@ c0a8 7103 05e7 06bb abf0 4aa6 a564 68db # 23:18:36.260235 192.168.113.3.1723 > 192.168.113.1.1511: P 1:157(156) ack 157 win 33580: pptp CTRL_MSGTYPE=SCCRP PROTO_VER(1.0) RESULT_CODE(1) ERR_CODE(0) FRAME_CAP() BEARER_CAP() MAX_CHAN(1) FIRM_REV(1) HOSTNAME(local) VENDOR(linux) (DF) [out,pcn1] -4500 00c4 69a7 4000 4006 6d37 c0a8 7103 -c0a8 7101 06bb 05e7 a564 68db abf0 4b42 +4500 00c4 69a7 4000 4006 6d37 c0a8 7103 c0a8 7101 +06bb 05e7 a564 68db abf0 4b42 5018 832c cecf 0000 009c 0001 1a2b 3c4d 0002 0000 0100 0100 0000 0000 0000 0000 0001 0001 6c6f 6361 6c00 0000 0000 0000 @@ -44,8 +42,8 @@ c0a8 7101 06bb 05e7 a564 68db abf0 4b42 # 23:18:36.260252 192.168.113.1.1511 > 192.168.113.3.1723: P 157:325(168) ack 157 win 64084: pptp CTRL_MSGTYPE=OCRQ CALL_ID(16384) CALL_SER_NUM(4913) MIN_BPS(300) MAX_BPS(100000000) BEARER_TYPE(Any) FRAME_TYPE(E) RECV_WIN(64) PROC_DELAY(0) PHONE_NO_LEN(0) PHONE_NO() SUB_ADDR() (DF) [in,pcn1] -4500 00d0 5e13 4000 8006 38bf c0a8 7101 -c0a8 7103 05e7 06bb abf0 4b42 a564 6977 +4500 00d0 5e13 4000 8006 38bf c0a8 7101 c0a8 7103 +05e7 06bb abf0 4b42 a564 6977 5018 fa54 ac07 0000 00a8 0001 1a2b 3c4d 0007 0000 4000 1331 0000 012c 05f5 e100 0000 0003 0000 0003 0040 0000 0000 0000 @@ -60,176 +58,174 @@ c0a8 7103 05e7 06bb abf0 4b42 a564 6977 # 23:18:36.272856 192.168.113.3.1723 > 192.168.113.1.1511: P 157:189(32) ack 325 win 33580: pptp CTRL_MSGTYPE=OCRP CALL_ID(0) PEER_CALL_ID(16384) RESULT_CODE(1) ERR_CODE(0) CAUSE_CODE(0) CONN_SPEED(100000000) RECV_WIN(64) PROC_DELAY(0) PHY_CHAN_ID(0) (DF) [out,pcn1] -4500 0048 69a8 4000 4006 6db2 c0a8 7103 -c0a8 7101 06bb 05e7 a564 6977 abf0 4bea +4500 0048 69a8 4000 4006 6db2 c0a8 7103 c0a8 7101 +06bb 05e7 a564 6977 abf0 4bea 5018 832c 36fa 0000 0020 0001 1a2b 3c4d 0008 0000 0000 4000 0100 0000 05f5 e100 0040 0000 0000 0000 # 23:18:36.321819 192.168.113.1.1511 > 192.168.113.3.1723: P 325:349(24) ack 189 win 64052: pptp CTRL_MSGTYPE=SLI PEER_CALL_ID(0) SEND_ACCM(0xffffffff) RECV_ACCM(0xffffffff) (DF) [in,pcn1] -4500 0040 5e14 4000 8006 394e c0a8 7101 -c0a8 7103 05e7 06bb abf0 4bea a564 6997 +4500 0040 5e14 4000 8006 394e c0a8 7101 c0a8 7103 +05e7 06bb abf0 4bea a564 6997 5018 fa34 e810 0000 0018 0001 1a2b 3c4d 000f 0000 0000 0000 ffff ffff ffff ffff # 23:18:36.349759 192.168.113.1 > 192.168.113.3: gre [KSv1] ID:0000 S:0 ppp: LCP 25: Conf-Req(0), MRU=1400, Magic-Num=577f7c5b, PFC, ACFC, Call-Back CBCP [in,pcn1] -4500 0039 5e15 0000 802f 792b c0a8 7101 -c0a8 7103 3001 880b 0019 0000 0000 0000 +4500 0039 5e15 0000 802f 792b c0a8 7101 c0a8 7103 +3001 880b 0019 0000 0000 0000 ff03 c021 0100 0015 0104 0578 0506 577f 7c5b 0702 0802 0d03 06 # 23:18:36.389970 192.168.113.3 > 192.168.113.1: gre [KAv1] ID:4000 A:4294967295 [|gre] [out,pcn1] -4500 0020 69a9 0000 ff2f eeaf c0a8 7103 -c0a8 7101 2081 880b 0000 4000 ffff ffff +4500 0020 69a9 0000 ff2f eeaf c0a8 7103 c0a8 7101 +2081 880b 0000 4000 ffff ffff # 23:18:36.518426 192.168.113.3.1723 > 192.168.113.1.1511: . ack 349 win 33580 (DF) [out,pcn1] -4500 0028 69aa 4000 4006 6dd0 c0a8 7103 -c0a8 7101 06bb 05e7 a564 6997 abf0 4c02 -5010 832c b5c1 0000 +4500 0028 69aa 4000 4006 6dd0 c0a8 7103 c0a8 7101 +06bb 05e7 a564 6997 abf0 4c02 5010 832c b5c1 0000 # 23:18:36.555363 192.168.113.3 > 192.168.113.1: gre [KSv1] ID:4000 S:0 ppp: LCP 24: Conf-Req(1), ACCM=00000000, Magic-Num=22d90cfa, PFC, ACFC [out,pcn1] -4500 0038 69ab 0000 ff2f ee95 c0a8 7103 -c0a8 7101 3001 880b 0018 4000 0000 0000 +4500 0038 69ab 0000 ff2f ee95 c0a8 7103 c0a8 7101 +3001 880b 0018 4000 0000 0000 ff03 c021 0101 0014 0206 0000 0000 0506 22d9 0cfa 0702 0802 # 23:18:36.556030 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:1 A:0 ppp: LCP 11: Conf-Rej(0), Call-Back CBCP [out,pcn1] -4500 002f 69ac 0000 ff2f ee9d c0a8 7103 -c0a8 7101 3081 880b 000b 4000 0000 0001 -0000 0000 ff03 c021 0400 0007 0d03 06 +4500 002f 69ac 0000 ff2f ee9d c0a8 7103 c0a8 7101 +3081 880b 000b 4000 0000 0001 0000 0000 ff03 c021 0400 0007 0d03 06 # 23:18:36.557166 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:1 A:1 ppp: LCP 24: Conf-Ack(1), ACCM=00000000, Magic-Num=22d90cfa, PFC, ACFC [in,pcn1] -4500 003c 5e16 0000 802f 7927 c0a8 7101 -c0a8 7103 3081 880b 0018 0000 0000 0001 +4500 003c 5e16 0000 802f 7927 c0a8 7101 c0a8 7103 +3081 880b 0018 0000 0000 0001 0000 0001 ff03 c021 0201 0014 0206 0000 0000 0506 22d9 0cfa 0702 0802 # 23:18:36.557764 192.168.113.1 > 192.168.113.3: gre [KSv1] ID:0000 S:2 ppp: LCP 22: Conf-Req(1), MRU=1400, Magic-Num=577f7c5b, PFC, ACFC [in,pcn1] -4500 0036 5e17 0000 802f 792c c0a8 7101 -c0a8 7103 3001 880b 0016 0000 0000 0002 +4500 0036 5e17 0000 802f 792c c0a8 7101 c0a8 7103 +3001 880b 0016 0000 0000 0002 ff03 c021 0101 0012 0104 0578 0506 577f 7c5b 0702 0802 # 23:18:36.564658 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:2 A:2 ppp: LCP 22: Conf-Ack(1), MRU=1400, Magic-Num=577f7c5b, PFC, ACFC [out,pcn1] -4500 003a 69ad 0000 ff2f ee91 c0a8 7103 -c0a8 7101 3081 880b 0016 4000 0000 0002 +4500 003a 69ad 0000 ff2f ee91 c0a8 7103 c0a8 7101 +3081 880b 0016 4000 0000 0002 0000 0002 ff03 c021 0201 0012 0104 0578 0506 577f 7c5b 0702 0802 # 23:18:36.564803 192.168.113.3 > 192.168.113.1: gre [KSv1] ID:4000 S:3 ppp: IPCP 18: Conf-Req(1), IP-Addr=192.168.0.1, IP-Comp VJ-Comp [out,pcn1] -4500 0032 69ae 0000 ff2f ee98 c0a8 7103 -c0a8 7101 3001 880b 0012 4000 0000 0003 +4500 0032 69ae 0000 ff2f ee98 c0a8 7103 c0a8 7101 +3001 880b 0012 4000 0000 0003 8021 0101 0010 0306 c0a8 0001 0206 002d 0f01 # 23:18:36.570395 192.168.113.1.1511 > 192.168.113.3.1723: P 349:373(24) ack 189 win 64052: pptp CTRL_MSGTYPE=SLI PEER_CALL_ID(0) SEND_ACCM(0x00000000) RECV_ACCM(0xffffffff) (DF) [in,pcn1] -4500 0040 5e18 4000 8006 394a c0a8 7101 -c0a8 7103 05e7 06bb abf0 4c02 a564 6997 +4500 0040 5e18 4000 8006 394a c0a8 7101 c0a8 7103 +05e7 06bb abf0 4c02 a564 6997 5018 fa34 e7f8 0000 0018 0001 1a2b 3c4d 000f 0000 0000 0000 0000 0000 ffff ffff # 23:18:36.573307 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:3 A:3 ppp: LCP 20: Ident(2), Magic-Num=577f7c5b [in,pcn1] -4500 0038 5e19 0000 802f 7928 c0a8 7101 -c0a8 7103 3081 880b 0014 0000 0000 0003 +4500 0038 5e19 0000 802f 7928 c0a8 7101 c0a8 7103 +3081 880b 0014 0000 0000 0003 0000 0003 c021 0c02 0012 577f 7c5b 4d53 5241 5356 352e 3130 # 23:18:36.573856 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:4 A:3 ppp: LCP 26: Code-Rej(2) [out,pcn1] -4500 003e 69af 0000 ff2f ee8b c0a8 7103 -c0a8 7101 3081 880b 001a 4000 0000 0004 +4500 003e 69af 0000 ff2f ee8b c0a8 7103 c0a8 7101 +3081 880b 001a 4000 0000 0004 0000 0003 ff03 c021 0702 0016 0c02 0012 577f 7c5b 4d53 5241 5356 352e 3130 # 23:18:36.584936 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:4 A:4 ppp: LCP 26: Ident(3), Magic-Num=577f7c5b [in,pcn1] -4500 003e 5e1a 0000 802f 7921 c0a8 7101 -c0a8 7103 3081 880b 001a 0000 0000 0004 +4500 003e 5e1a 0000 802f 7921 c0a8 7101 c0a8 7103 +3081 880b 001a 0000 0000 0004 0000 0004 c021 0c03 0018 577f 7c5b 4d53 5241 532d 302d 434c 4159 4d4f 4f52 # 23:18:36.585562 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:5 A:4 ppp: LCP 32: Code-Rej(3) [out,pcn1] -4500 0044 69b0 0000 ff2f ee84 c0a8 7103 -c0a8 7101 3081 880b 0020 4000 0000 0005 +4500 0044 69b0 0000 ff2f ee84 c0a8 7103 c0a8 7101 +3081 880b 0020 4000 0000 0005 0000 0004 ff03 c021 0703 001c 0c03 0018 577f 7c5b 4d53 5241 532d 302d 434c 4159 4d4f 4f52 # 23:18:36.588721 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:5 A:5 ppp: CCP 12: Conf-Req(4), MPPC [in,pcn1] -4500 0030 5e1b 0000 802f 792e c0a8 7101 -c0a8 7103 3081 880b 000c 0000 0000 0005 +4500 0030 5e1b 0000 802f 792e c0a8 7101 c0a8 7103 +3081 880b 000c 0000 0000 0005 0000 0005 80fd 0104 000a 1206 0100 0001 # 23:18:36.589445 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:6 A:5 ppp: CCP 6: Conf-Req(1) [out,pcn1] -4500 002a 69b1 0000 ff2f ee9d c0a8 7103 -c0a8 7101 3081 880b 0006 4000 0000 0006 +4500 002a 69b1 0000 ff2f ee9d c0a8 7103 c0a8 7101 +3081 880b 0006 4000 0000 0006 0000 0005 80fd 0101 0004 # 23:18:36.589540 192.168.113.3 > 192.168.113.1: gre [KSv1] ID:4000 S:7 ppp: CCP 12: Conf-Rej(4), MPPC [out,pcn1] -4500 002c 69b2 0000 ff2f ee9a c0a8 7103 -c0a8 7101 3001 880b 000c 4000 0000 0007 +4500 002c 69b2 0000 ff2f ee9a c0a8 7103 c0a8 7101 +3001 880b 000c 4000 0000 0007 80fd 0404 000a 1206 0100 0001 # 23:18:36.590023 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:6 A:7 ppp: IPCP 36: Conf-Req(5), IP-Addr=0.0.0.0, Pri-DNS=0.0.0.0, Pri-NBNS=0.0.0.0, Sec-DNS=0.0.0.0, Sec-NBNS=0.0.0.0 [in,pcn1] -4500 0048 5e1c 0000 802f 7915 c0a8 7101 -c0a8 7103 3081 880b 0024 0000 0000 0006 +4500 0048 5e1c 0000 802f 7915 c0a8 7101 c0a8 7103 +3081 880b 0024 0000 0000 0006 0000 0007 8021 0105 0022 0306 0000 0000 8106 0000 0000 8206 0000 0000 8306 0000 0000 8406 0000 0000 # 23:18:36.590489 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:8 A:6 ppp: IPCP 30: Conf-Rej(5), Pri-DNS=0.0.0.0, Pri-NBNS=0.0.0.0, Sec-DNS=0.0.0.0, Sec-NBNS=0.0.0.0 [out,pcn1] -4500 0042 69b3 0000 ff2f ee83 c0a8 7103 -c0a8 7101 3081 880b 001e 4000 0000 0008 +4500 0042 69b3 0000 ff2f ee83 c0a8 7103 c0a8 7101 +3081 880b 001e 4000 0000 0008 0000 0006 8021 0405 001c 8106 0000 0000 8206 0000 0000 8306 0000 0000 8406 0000 0000 # 23:18:36.591003 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:7 A:8 ppp: IPCP 12: Conf-Rej(1), IP-Comp VJ-Comp [in,pcn1] -4500 0030 5e1d 0000 802f 792c c0a8 7101 -c0a8 7103 3081 880b 000c 0000 0000 0007 +4500 0030 5e1d 0000 802f 792c c0a8 7101 c0a8 7103 +3081 880b 000c 0000 0000 0007 0000 0008 8021 0401 000a 0206 002d 0f01 # 23:18:36.593819 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:9 A:7 ppp: IPCP 12: Conf-Req(2), IP-Addr=192.168.0.1 [out,pcn1] -4500 0030 69b4 0000 ff2f ee94 c0a8 7103 -c0a8 7101 3081 880b 000c 4000 0000 0009 +4500 0030 69b4 0000 ff2f ee94 c0a8 7103 c0a8 7101 +3081 880b 000c 4000 0000 0009 0000 0007 8021 0102 000a 0306 c0a8 0001 # 23:18:36.594840 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:8 A:9 ppp: CCP 6: Conf-Ack(1) [in,pcn1] -4500 002a 5e1e 0000 802f 7931 c0a8 7101 -c0a8 7103 3081 880b 0006 0000 0000 0008 -0000 0009 80fd 0201 0004 0000 0000 +4500 002a 5e1e 0000 802f 7931 c0a8 7101 c0a8 7103 +3081 880b 0006 0000 0000 0008 +0000 0009 80fd 0201 0004 # 23:18:36.595525 192.168.113.1 > 192.168.113.3: gre [KSv1] ID:0000 S:9 ppp: CCP 18: Term-Req(6) [in,pcn1] -4500 0032 5e1f 0000 802f 7928 c0a8 7101 -c0a8 7103 3001 880b 0012 0000 0000 0009 +4500 0032 5e1f 0000 802f 7928 c0a8 7101 c0a8 7103 +3001 880b 0012 0000 0000 0009 80fd 0506 0010 577f 7c5b 003c cd74 0000 02dc # 23:18:36.595937 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:10 A:9 ppp: CCP 6: Term-Ack(6) [out,pcn1] -4500 002a 69b5 0000 ff2f ee99 c0a8 7103 -c0a8 7101 3081 880b 0006 4000 0000 000a +4500 002a 69b5 0000 ff2f ee99 c0a8 7103 c0a8 7101 +3081 880b 0006 4000 0000 000a 0000 0009 80fd 0606 0004 diff --git a/test/input/ni14 b/test/input/ni14 index 681132120e234..6bc127610f2bc 100644 --- a/test/input/ni14 +++ b/test/input/ni14 @@ -1,19 +1,19 @@ # 23:18:36.130424 192.168.113.1.1511 > 192.168.113.3.1723: S 2884651685:2884651685(0) win 64240 <mss 1460,nop,nop,sackOK> (DF) [in,pcn1=192.168.113.3] -4500 0030 5e11 4000 8006 3961 c0a8 7101 -c0a8 7103 05e7 06bb abf0 4aa5 0000 0000 +4500 0030 5e11 4000 8006 3961 c0a8 7101 c0a8 7103 +05e7 06bb abf0 4aa5 0000 0000 7002 faf0 21a1 0000 0204 05b4 0101 0402 # 23:18:36.130778 192.168.113.3.1723 > 192.168.113.1.1511: S 2774821082:2774821082(0) ack 2884651686 win 32768 <mss 1460> (DF) [out,pcn1] -4500 002c 69a6 4000 4006 207b 7f00 0001 -c0a8 7101 06bb 05e7 a564 68da abf0 4aa6 +4500 002c 69a6 4000 4006 207b 7f00 0001 c0a8 7101 +06bb 05e7 a564 68da abf0 4aa6 6012 8000 55f3 0000 0204 05b4 # 23:18:36.130784 192.168.113.1.1511 > 192.168.113.3.1723: P 1:157(156) ack 1 win 64240: pptp CTRL_MSGTYPE=SCCRQ PROTO_VER(1.0) FRAME_CAP(A) BEARER_CAP(A) MAX_CHAN(0) FIRM_REV(2600) HOSTNAME() VENDOR(Microsoft Windows NT) (DF) [in,pcn1] -4500 00c4 5e12 4000 8006 38cc c0a8 7101 -c0a8 7103 05e7 06bb abf0 4aa6 a564 68db +4500 00c4 5e12 4000 8006 38cc c0a8 7101 c0a8 7103 +05e7 06bb abf0 4aa6 a564 68db 5018 faf0 e2a0 0000 009c 0001 1a2b 3c4d 0001 0000 0100 0000 0000 0001 0000 0001 0000 0a28 0000 0000 0000 0000 0000 0000 @@ -28,8 +28,8 @@ c0a8 7103 05e7 06bb abf0 4aa6 a564 68db # 23:18:36.260235 192.168.113.3.1723 > 192.168.113.1.1511: P 1:157(156) ack 157 win 33580: pptp CTRL_MSGTYPE=SCCRP PROTO_VER(1.0) RESULT_CODE(1) ERR_CODE(0) FRAME_CAP() BEARER_CAP() MAX_CHAN(1) FIRM_REV(1) HOSTNAME(local) VENDOR(linux) (DF) [out,pcn1] -4500 00c4 69a7 4000 4006 1fe2 7f00 0001 -c0a8 7101 06bb 05e7 a564 68db abf0 4b42 +4500 00c4 69a7 4000 4006 1fe2 7f00 0001 c0a8 7101 +06bb 05e7 a564 68db abf0 4b42 5018 832c 817a 0000 009c 0001 1a2b 3c4d 0002 0000 0100 0100 0000 0000 0000 0000 0001 0001 6c6f 6361 6c00 0000 0000 0000 @@ -44,8 +44,8 @@ c0a8 7101 06bb 05e7 a564 68db abf0 4b42 # 23:18:36.260252 192.168.113.1.1511 > 192.168.113.3.1723: P 157:325(168) ack 157 win 64084: pptp CTRL_MSGTYPE=OCRQ CALL_ID(16384) CALL_SER_NUM(4913) MIN_BPS(300) MAX_BPS(100000000) BEARER_TYPE(Any) FRAME_TYPE(E) RECV_WIN(64) PROC_DELAY(0) PHONE_NO_LEN(0) PHONE_NO() SUB_ADDR() (DF) [in,pcn1] -4500 00d0 5e13 4000 8006 38bf c0a8 7101 -c0a8 7103 05e7 06bb abf0 4b42 a564 6977 +4500 00d0 5e13 4000 8006 38bf c0a8 7101 c0a8 7103 +05e7 06bb abf0 4b42 a564 6977 5018 fa54 ac07 0000 00a8 0001 1a2b 3c4d 0007 0000 4000 1331 0000 012c 05f5 e100 0000 0003 0000 0003 0040 0000 0000 0000 @@ -60,176 +60,176 @@ c0a8 7103 05e7 06bb abf0 4b42 a564 6977 # 23:18:36.272856 192.168.113.3.1723 > 192.168.113.1.1511: P 157:189(32) ack 325 win 33580: pptp CTRL_MSGTYPE=OCRP CALL_ID(0) PEER_CALL_ID(16384) RESULT_CODE(1) ERR_CODE(0) CAUSE_CODE(0) CONN_SPEED(100000000) RECV_WIN(64) PROC_DELAY(0) PHY_CHAN_ID(0) (DF) [out,pcn1] -4500 0048 69a8 4000 4006 205d 7f00 0001 -c0a8 7101 06bb 05e7 a564 6977 abf0 4bea +4500 0048 69a8 4000 4006 205d 7f00 0001 c0a8 7101 +06bb 05e7 a564 6977 abf0 4bea 5018 832c e9a4 0000 0020 0001 1a2b 3c4d 0008 0000 0000 4000 0100 0000 05f5 e100 0040 0000 0000 0000 # 23:18:36.321819 192.168.113.1.1511 > 192.168.113.3.1723: P 325:349(24) ack 189 win 64052: pptp CTRL_MSGTYPE=SLI PEER_CALL_ID(0) SEND_ACCM(0xffffffff) RECV_ACCM(0xffffffff) (DF) [in,pcn1] -4500 0040 5e14 4000 8006 394e c0a8 7101 -c0a8 7103 05e7 06bb abf0 4bea a564 6997 +4500 0040 5e14 4000 8006 394e c0a8 7101 c0a8 7103 +05e7 06bb abf0 4bea a564 6997 5018 fa34 e810 0000 0018 0001 1a2b 3c4d 000f 0000 0000 0000 ffff ffff ffff ffff # 23:18:36.349759 192.168.113.1 > 192.168.113.3: gre [KSv1] ID:0000 S:0 ppp: LCP 25: Conf-Req(0), MRU=1400, Magic-Num=577f7c5b, PFC, ACFC, Call-Back CBCP [in,pcn1] -4500 0039 5e15 0000 802f 792b c0a8 7101 -c0a8 7103 3001 880b 0019 0000 0000 0000 +4500 0039 5e15 0000 802f 792b c0a8 7101 c0a8 7103 +3001 880b 0019 0000 0000 0000 ff03 c021 0100 0015 0104 0578 0506 577f 7c5b 0702 0802 0d03 06 # 23:18:36.389970 192.168.113.3 > 192.168.113.1: gre [KAv1] ID:4000 A:4294967295 [|gre] [out,pcn1] -4500 0020 69a9 0000 ff2f a15a 7f00 0001 -c0a8 7101 2081 880b 0000 4000 ffff ffff +4500 0020 69a9 0000 ff2f a15a 7f00 0001 c0a8 7101 +2081 880b 0000 4000 ffff ffff # 23:18:36.518426 192.168.113.3.1723 > 192.168.113.1.1511: . ack 349 win 33580 (DF) [out,pcn1] -4500 0028 69aa 4000 4006 207b 7f00 0001 -c0a8 7101 06bb 05e7 a564 6997 abf0 4c02 +4500 0028 69aa 4000 4006 207b 7f00 0001 c0a8 7101 +06bb 05e7 a564 6997 abf0 4c02 5010 832c 686c 0000 # 23:18:36.555363 192.168.113.3 > 192.168.113.1: gre [KSv1] ID:4000 S:0 ppp: LCP 24: Conf-Req(1), ACCM=00000000, Magic-Num=22d90cfa, PFC, ACFC [out,pcn1] -4500 0038 69ab 0000 ff2f a140 7f00 0001 -c0a8 7101 3001 880b 0018 4000 0000 0000 +4500 0038 69ab 0000 ff2f a140 7f00 0001 c0a8 7101 +3001 880b 0018 4000 0000 0000 ff03 c021 0101 0014 0206 0000 0000 0506 22d9 0cfa 0702 0802 # 23:18:36.556030 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:1 A:0 ppp: LCP 11: Conf-Rej(0), Call-Back CBCP [out,pcn1] -4500 002f 69ac 0000 ff2f a148 7f00 0001 -c0a8 7101 3081 880b 000b 4000 0000 0001 +4500 002f 69ac 0000 ff2f a148 7f00 0001 c0a8 7101 +3081 880b 000b 4000 0000 0001 0000 0000 ff03 c021 0400 0007 0d03 06 # 23:18:36.557166 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:1 A:1 ppp: LCP 24: Conf-Ack(1), ACCM=00000000, Magic-Num=22d90cfa, PFC, ACFC [in,pcn1] -4500 003c 5e16 0000 802f 7927 c0a8 7101 -c0a8 7103 3081 880b 0018 0000 0000 0001 +4500 003c 5e16 0000 802f 7927 c0a8 7101 c0a8 7103 +3081 880b 0018 0000 0000 0001 0000 0001 ff03 c021 0201 0014 0206 0000 0000 0506 22d9 0cfa 0702 0802 # 23:18:36.557764 192.168.113.1 > 192.168.113.3: gre [KSv1] ID:0000 S:2 ppp: LCP 22: Conf-Req(1), MRU=1400, Magic-Num=577f7c5b, PFC, ACFC [in,pcn1] -4500 0036 5e17 0000 802f 792c c0a8 7101 -c0a8 7103 3001 880b 0016 0000 0000 0002 +4500 0036 5e17 0000 802f 792c c0a8 7101 c0a8 7103 +3001 880b 0016 0000 0000 0002 ff03 c021 0101 0012 0104 0578 0506 577f 7c5b 0702 0802 # 23:18:36.564658 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:2 A:2 ppp: LCP 22: Conf-Ack(1), MRU=1400, Magic-Num=577f7c5b, PFC, ACFC [out,pcn1] -4500 003a 69ad 0000 ff2f a13c 7f00 0001 -c0a8 7101 3081 880b 0016 4000 0000 0002 +4500 003a 69ad 0000 ff2f a13c 7f00 0001 c0a8 7101 +3081 880b 0016 4000 0000 0002 0000 0002 ff03 c021 0201 0012 0104 0578 0506 577f 7c5b 0702 0802 # 23:18:36.564803 192.168.113.3 > 192.168.113.1: gre [KSv1] ID:4000 S:3 ppp: IPCP 18: Conf-Req(1), IP-Addr=192.168.0.1, IP-Comp VJ-Comp [out,pcn1] -4500 0032 69ae 0000 ff2f a143 7f00 0001 -c0a8 7101 3001 880b 0012 4000 0000 0003 +4500 0032 69ae 0000 ff2f a143 7f00 0001 c0a8 7101 +3001 880b 0012 4000 0000 0003 8021 0101 0010 0306 c0a8 0001 0206 002d 0f01 # 23:18:36.570395 192.168.113.1.1511 > 192.168.113.3.1723: P 349:373(24) ack 189 win 64052: pptp CTRL_MSGTYPE=SLI PEER_CALL_ID(0) SEND_ACCM(0x00000000) RECV_ACCM(0xffffffff) (DF) [in,pcn1] -4500 0040 5e18 4000 8006 394a c0a8 7101 -c0a8 7103 05e7 06bb abf0 4c02 a564 6997 +4500 0040 5e18 4000 8006 394a c0a8 7101 c0a8 7103 +05e7 06bb abf0 4c02 a564 6997 5018 fa34 e7f8 0000 0018 0001 1a2b 3c4d 000f 0000 0000 0000 0000 0000 ffff ffff # 23:18:36.573307 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:3 A:3 ppp: LCP 20: Ident(2), Magic-Num=577f7c5b [in,pcn1] -4500 0038 5e19 0000 802f 7928 c0a8 7101 -c0a8 7103 3081 880b 0014 0000 0000 0003 +4500 0038 5e19 0000 802f 7928 c0a8 7101 c0a8 7103 +3081 880b 0014 0000 0000 0003 0000 0003 c021 0c02 0012 577f 7c5b 4d53 5241 5356 352e 3130 # 23:18:36.573856 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:4 A:3 ppp: LCP 26: Code-Rej(2) [out,pcn1] -4500 003e 69af 0000 ff2f a136 7f00 0001 -c0a8 7101 3081 880b 001a 4000 0000 0004 +4500 003e 69af 0000 ff2f a136 7f00 0001 c0a8 7101 +3081 880b 001a 4000 0000 0004 0000 0003 ff03 c021 0702 0016 0c02 0012 577f 7c5b 4d53 5241 5356 352e 3130 # 23:18:36.584936 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:4 A:4 ppp: LCP 26: Ident(3), Magic-Num=577f7c5b [in,pcn1] -4500 003e 5e1a 0000 802f 7921 c0a8 7101 -c0a8 7103 3081 880b 001a 0000 0000 0004 +4500 003e 5e1a 0000 802f 7921 c0a8 7101 c0a8 7103 +3081 880b 001a 0000 0000 0004 0000 0004 c021 0c03 0018 577f 7c5b 4d53 5241 532d 302d 434c 4159 4d4f 4f52 # 23:18:36.585562 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:5 A:4 ppp: LCP 32: Code-Rej(3) [out,pcn1] -4500 0044 69b0 0000 ff2f a12f 7f00 0001 -c0a8 7101 3081 880b 0020 4000 0000 0005 +4500 0044 69b0 0000 ff2f a12f 7f00 0001 c0a8 7101 +3081 880b 0020 4000 0000 0005 0000 0004 ff03 c021 0703 001c 0c03 0018 577f 7c5b 4d53 5241 532d 302d 434c 4159 4d4f 4f52 # 23:18:36.588721 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:5 A:5 ppp: CCP 12: Conf-Req(4), MPPC [in,pcn1] -4500 0030 5e1b 0000 802f 792e c0a8 7101 -c0a8 7103 3081 880b 000c 0000 0000 0005 +4500 0030 5e1b 0000 802f 792e c0a8 7101 c0a8 7103 +3081 880b 000c 0000 0000 0005 0000 0005 80fd 0104 000a 1206 0100 0001 # 23:18:36.589445 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:6 A:5 ppp: CCP 6: Conf-Req(1) [out,pcn1] -4500 002a 69b1 0000 ff2f a148 7f00 0001 -c0a8 7101 3081 880b 0006 4000 0000 0006 +4500 002a 69b1 0000 ff2f a148 7f00 0001 c0a8 7101 +3081 880b 0006 4000 0000 0006 0000 0005 80fd 0101 0004 # 23:18:36.589540 192.168.113.3 > 192.168.113.1: gre [KSv1] ID:4000 S:7 ppp: CCP 12: Conf-Rej(4), MPPC [out,pcn1] -4500 002c 69b2 0000 ff2f a145 7f00 0001 -c0a8 7101 3001 880b 000c 4000 0000 0007 +4500 002c 69b2 0000 ff2f a145 7f00 0001 c0a8 7101 +3001 880b 000c 4000 0000 0007 80fd 0404 000a 1206 0100 0001 # 23:18:36.590023 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:6 A:7 ppp: IPCP 36: Conf-Req(5), IP-Addr=0.0.0.0, Pri-DNS=0.0.0.0, Pri-NBNS=0.0.0.0, Sec-DNS=0.0.0.0, Sec-NBNS=0.0.0.0 [in,pcn1] -4500 0048 5e1c 0000 802f 7915 c0a8 7101 -c0a8 7103 3081 880b 0024 0000 0000 0006 +4500 0048 5e1c 0000 802f 7915 c0a8 7101 c0a8 7103 +3081 880b 0024 0000 0000 0006 0000 0007 8021 0105 0022 0306 0000 0000 8106 0000 0000 8206 0000 0000 8306 0000 0000 8406 0000 0000 # 23:18:36.590489 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:8 A:6 ppp: IPCP 30: Conf-Rej(5), Pri-DNS=0.0.0.0, Pri-NBNS=0.0.0.0, Sec-DNS=0.0.0.0, Sec-NBNS=0.0.0.0 [out,pcn1] -4500 0042 69b3 0000 ff2f a12e 7f00 0001 -c0a8 7101 3081 880b 001e 4000 0000 0008 +4500 0042 69b3 0000 ff2f a12e 7f00 0001 c0a8 7101 +3081 880b 001e 4000 0000 0008 0000 0006 8021 0405 001c 8106 0000 0000 8206 0000 0000 8306 0000 0000 8406 0000 0000 # 23:18:36.591003 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:7 A:8 ppp: IPCP 12: Conf-Rej(1), IP-Comp VJ-Comp [in,pcn1] -4500 0030 5e1d 0000 802f 792c c0a8 7101 -c0a8 7103 3081 880b 000c 0000 0000 0007 +4500 0030 5e1d 0000 802f 792c c0a8 7101 c0a8 7103 +3081 880b 000c 0000 0000 0007 0000 0008 8021 0401 000a 0206 002d 0f01 # 23:18:36.593819 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:9 A:7 ppp: IPCP 12: Conf-Req(2), IP-Addr=192.168.0.1 [out,pcn1] -4500 0030 69b4 0000 ff2f a13f 7f00 0001 -c0a8 7101 3081 880b 000c 4000 0000 0009 +4500 0030 69b4 0000 ff2f a13f 7f00 0001 c0a8 7101 +3081 880b 000c 4000 0000 0009 0000 0007 8021 0102 000a 0306 c0a8 0001 # 23:18:36.594840 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:8 A:9 ppp: CCP 6: Conf-Ack(1) [in,pcn1] -4500 002a 5e1e 0000 802f 7931 c0a8 7101 -c0a8 7103 3081 880b 0006 0000 0000 0008 -0000 0009 80fd 0201 0004 0000 0000 +4500 002a 5e1e 0000 802f 7931 c0a8 7101 c0a8 7103 +3081 880b 0006 0000 0000 0008 +0000 0009 80fd 0201 0004 # 23:18:36.595525 192.168.113.1 > 192.168.113.3: gre [KSv1] ID:0000 S:9 ppp: CCP 18: Term-Req(6) [in,pcn1] -4500 0032 5e1f 0000 802f 7928 c0a8 7101 -c0a8 7103 3001 880b 0012 0000 0000 0009 +4500 0032 5e1f 0000 802f 7928 c0a8 7101 c0a8 7103 +3001 880b 0012 0000 0000 0009 80fd 0506 0010 577f 7c5b 003c cd74 0000 02dc # 23:18:36.595937 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:10 A:9 ppp: CCP 6: Term-Ack(6) [out,pcn1] -4500 002a 69b5 0000 ff2f a144 7f00 0001 -c0a8 7101 3081 880b 0006 4000 0000 000a +4500 002a 69b5 0000 ff2f a144 7f00 0001 c0a8 7101 +3081 880b 0006 4000 0000 000a 0000 0009 80fd 0606 0004 diff --git a/test/input/ni15 b/test/input/ni15 index fb445bb93c6fe..7e7aabde1580e 100644 --- a/test/input/ni15 +++ b/test/input/ni15 @@ -218,7 +218,7 @@ c0a8 7101 3081 880b 000c 4000 0000 0009 [out,pcn1] 4500 002a 5e1e 0000 802f 7931 c0a8 7101 c0a8 7103 3081 880b 0006 0000 0000 0008 -0000 0009 80fd 0201 0004 0000 0000 +0000 0009 80fd 0201 0004 # 23:18:36.595525 192.168.113.1 > 192.168.113.3: gre [KSv1] ID:0000 S:9 ppp: CCP 18: Term-Req(6) [out,pcn1] diff --git a/test/input/ni16 b/test/input/ni16 index 24bfcfc3835f5..362b98d09c478 100644 --- a/test/input/ni16 +++ b/test/input/ni16 @@ -218,7 +218,7 @@ c0a8 7101 3081 880b 000c 4000 0000 0009 [out,pcn1] 4500 002a 5e1e 0000 802f 9ed7 0a02 0202 c0a8 7103 3081 880b 0006 0000 0000 0008 -0000 0009 80fd 0201 0004 0000 0000 +0000 0009 80fd 0201 0004 # 23:18:36.595525 192.168.113.1 > 192.168.113.3: gre [KSv1] ID:0000 S:9 ppp: CCP 18: Term-Req(6) [out,pcn1] diff --git a/test/input/ni18 b/test/input/ni18 new file mode 100644 index 0000000000000..4e06f7908442b --- /dev/null +++ b/test/input/ni18 @@ -0,0 +1,4 @@ +in on hme0 tcp 2.2.2.2,3000 192.168.1.2,80 +in on hme0 tcp 2.2.2.2,3000 192.168.1.1,80 +out on hme1 tcp 10.1.2.2,5050 4.5.6.7,80; +out on hme1 tcp 10.1.1.2,5050 4.5.6.7,80; diff --git a/test/input/ni19 b/test/input/ni19 index d95e68afc7b1d..3ea706fcbcd29 100644 --- a/test/input/ni19 +++ b/test/input/ni19 @@ -28,7 +28,7 @@ b002 8000 7d87 0000 0204 05b4 0103 0300 [in,bge0] 4500 0028 7ce5 4000 4006 a7e4 0a01 0104 0a01 0101 0202 03f1 915a a5c5 6523 90b8 -5010 05b4 612b 0000 0000 0000 0000 +5010 05b4 612b 0000 # 10.1.1.4.1023 > 10.1.1.1.1008: SYN win 5840 <mss 1460,sackOK,timestamp 3791140 0,nop,wscale 2> [in,bge0] @@ -61,7 +61,7 @@ b012 8000 1e85 0000 0204 05b4 0103 0300 [in,bge0] 4500 0028 7ce7 4000 4006 a7e2 0a01 0104 0a01 0101 0202 03f1 915a a5c5 6523 90c0 -5010 05b4 6123 0000 0000 0000 0000 +5010 05b4 6123 0000 # 192.168.113.3.1009 > 10.1.1.4.shell [out,bge0] @@ -76,13 +76,13 @@ b012 8000 1e85 0000 0204 05b4 0103 0300 [in,bge0] 4500 0028 7ce9 4000 4006 a7e0 0a01 0104 0a01 0101 0202 03f1 915a a5c5 6523 90eb -5010 05b4 60f8 0000 0000 0000 0000 +5010 05b4 60f8 0000 # 10.1.1.4.shell > 10.1.1.1.1009 [in,bge0] 4500 0029 7ceb 4000 4006 a7dd 0a01 0104 0a01 0101 0202 03f1 915a a5c5 6523 90eb -5018 05b4 60ef 0000 0000 0000 0000 +5018 05b4 60ef 0000 00 # 192.168.113.3.1009 > 10.1.1.4.shell [out,bge0] @@ -94,7 +94,7 @@ b012 8000 1e85 0000 0204 05b4 0103 0300 [in,bge0] 4500 002c 7ced 4000 4006 a7d8 0a01 0104 0a01 0101 0202 03f1 915a a5c6 6523 90eb -5018 05b4 8b71 0000 666f 6f0a 0000 +5018 05b4 8b71 0000 666f 6f0a # 10.1.1.4.1023 > 10.1.1.1.1008 [in,bge0] @@ -107,7 +107,7 @@ b012 8000 1e85 0000 0204 05b4 0103 0300 [in,bge0] 4500 0028 7cef 4000 4006 a7da 0a01 0104 0a01 0101 0202 03f1 915a a5ca 6523 90eb -5011 05b4 60f2 0000 0000 0000 0000 +5011 05b4 60f2 0000 # 10.1.1.4.1023 > 10.1.1.1.1008 [in,bge0] @@ -146,7 +146,7 @@ b012 8000 1e85 0000 0204 05b4 0103 0300 [in,bge0] 4500 0028 0004 4000 4006 24c6 0a01 0104 0a01 0101 0202 03f1 915a a5cb 6523 90ec -5010 05b4 60f1 0000 0000 0000 0000 +5010 05b4 60f1 0000 # 10.1.1.4.1023 > 10.1.1.1.1008 [in,bge0] diff --git a/test/input/ni2 b/test/input/ni2 index 30458212bb035..6dcedb7f0ffe7 100644 --- a/test/input/ni2 +++ b/test/input/ni2 @@ -1,29 +1,21 @@ # Test of fragmentation required coming from the inside. [out,xl0] -4510 002c bd0d 4000 3e06 b1d1 -0a01 0201 -c0a8 0133 +4510 002c bd0d 4000 3e06 b1d1 0a01 0201 c0a8 0133 05f6 0077 a664 2485 0000 0000 6002 4000 b8f2 0000 0204 05b4 [in,xl0] -4500 002c ce83 4000 7e06 606b -c0a8 0133 -0a01 0201 +4500 002c ce83 4000 7e06 606b c0a8 0133 0a01 0201 0077 05f6 fbdf 1a21 a664 2486 -6012 2238 c0a8 0000 0204 05b4 0000 +6012 2238 c0a8 0000 0204 05b4 [out,xl0] -4510 0028 bd0e 4000 3e06 b1d4 -0a01 0201 -c0a8 0133 +4510 0028 bd0e 4000 3e06 b1d4 0a01 0201 c0a8 0133 05f6 0077 a664 2486 fbdf 1a22 5010 4470 b62d 0000 [in,xl0] -4500 005b cf83 4000 7e06 5f3c -c0a8 0133 -0a01 0201 +4500 005b cf83 4000 7e06 5f3c c0a8 0133 0a01 0201 0077 05f6 fbdf 1a22 a664 2486 5018 2238 ce2a 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 @@ -31,32 +23,24 @@ c0a8 0133 0000 0000 0000 0000 0000 0a [out,xl0] -4510 0028 bd18 4000 3e06 b1ca -0a01 0201 -c0a8 0133 +4510 0028 bd18 4000 3e06 b1ca 0a01 0201 c0a8 0133 05f6 0077 a664 2486 fbdf 1a55 5010 4470 b5fa 0000 [out,xl0] -4510 002e bd1e 4000 3e06 b1be -0a01 0201 -c0a8 0133 +4510 002e bd1e 4000 3e06 b1be 0a01 0201 c0a8 0133 05f6 0077 a664 2486 fbdf 1a55 5018 4470 a8e2 0000 0000 0000 0d0a [in,xl0] -4500 0048 e383 4000 7e06 4b4f -c0a8 0133 -0a01 0201 +4500 0048 e383 4000 7e06 4b4f c0a8 0133 0a01 0201 0077 05f6 fbdf 1a55 a664 248c 5018 2232 d80a 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 [in,xl0] -4500 05dc e483 4000 7e06 44bb -c0a8 0133 -0a01 0201 +4500 05dc e483 4000 7e06 44bb c0a8 0133 0a01 0201 0077 05f6 fbdf 1a75 a664 248c 5010 2232 9f2d 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 @@ -152,10 +136,8 @@ c0a8 0133 0000 0000 0000 0000 0000 0000 [out,xl0] -4500 0038 d71d 4000 4001 7d22 -c0a8 6401 -c0a8 0133 -0304 3435 0000 05a0 +4500 0038 d71d 4000 4001 7d22 c0a8 6401 c0a8 0133 +0304 da99 0000 05a0 4500 05dc e483 4000 7e06 44bb c0a8 0133 0a01 0201 -0077 05f6 fbdf 1a75 a664 +0077 05f6 fbdf 1a75 diff --git a/test/input/ni20 b/test/input/ni20 index 4c2b87e4de34f..065ed27ba79a5 100644 --- a/test/input/ni20 +++ b/test/input/ni20 @@ -28,7 +28,7 @@ c0a8 7103 0202 03f1 915a a5c4 6523 90b3 [out,bge0] 4500 0028 7ce5 4000 4006 5a92 c0a8 7104 c0a8 7103 0202 03f1 915a a5c5 6523 90b8 -5010 05b4 13d9 0000 0000 0000 0000 +5010 05b4 13d9 0000 # 192.168.113.4.1023 > 192.168.113.3.1008: SYN win 5840 <mss 1460,sackOK,timestamp 3791140 0,nop,wscale 2> [out,bge0] @@ -44,26 +44,26 @@ a002 16d0 9218 0000 0204 05b4 0402 080a b012 8000 1e85 0000 0204 05b4 0103 0300 0101 080a 0000 0000 0039 d924 0402 0101 -# 192.168.113.4.1023 > 192.168.113.3.1008 +# 192.168.113.4.1023 > 192.168.113.3.1008 ACK [out,bge0] 4500 0034 1188 4000 4006 c5e3 c0a8 7104 c0a8 7103 03ff 03f0 91d4 c8a3 66e5 b811 8010 05b4 b2f3 0000 0101 080a 0039 d925 0000 0000 -# 192.168.113.3.1009 > 10.1.1.4.shell +# 192.168.113.3.1009 > 10.1.1.4.shell PUSH+ACK [in,bge0] 4500 0030 e400 4000 4006 1a17 c0a8 7103 0a01 0104 03f1 0202 6523 90b8 915a a5c5 5018 832c 0eb6 0000 6461 7272 656e 7200 -# 192.168.113.4.shell > 192.168.113.3.1009 +# 192.168.113.4.shell > 192.168.113.3.1009 ACK [out,bge0] 4500 0028 7ce7 4000 4006 5a90 c0a8 7104 c0a8 7103 0202 03f1 915a a5c5 6523 90c0 -5010 05b4 13d1 0000 0000 0000 0000 +5010 05b4 13d1 0000 -# 192.168.113.3.1009 > 10.1.1.4.shell +# 192.168.113.3.1009 > 10.1.1.4.shell PUSH+ACK [in,bge0] 4500 0053 e401 4000 4006 19f3 c0a8 7103 0a01 0104 03f1 0202 6523 90c0 915a a5c5 @@ -72,83 +72,83 @@ c0a8 7103 0202 03f1 915a a5c5 6523 90c0 3e26 313b 2065 6368 6f20 6261 7220 3e26 3222 00 -# 192.168.113.4.shell > 192.168.113.3.1009 +# 192.168.113.4.shell > 192.168.113.3.1009 ACK [out,bge0] 4500 0028 7ce9 4000 4006 5a8e c0a8 7104 c0a8 7103 0202 03f1 915a a5c5 6523 90eb -5010 05b4 13a6 0000 0000 0000 0000 +5010 05b4 13a6 0000 -# 192.168.113.4.shell > 192.168.113.3.1009 +# 192.168.113.4.shell > 192.168.113.3.1009 PUSH+ACK [out,bge0] 4500 0029 7ceb 4000 4006 5a8b c0a8 7104 c0a8 7103 0202 03f1 915a a5c5 6523 90eb -5018 05b4 139d 0000 0000 0000 0000 +5018 05b4 139d 0000 00 -# 192.168.113.3.1009 > 10.1.1.4.shell +# 192.168.113.3.1009 > 10.1.1.4.shell ACK [in,bge0] 4500 0028 e403 4000 4006 1a1c c0a8 7103 0a01 0104 03f1 0202 6523 90eb 915a a5c6 5010 832c bcd4 0000 -# 192.168.113.4.shell > 192.168.113.3.1009 +# 192.168.113.4.shell > 192.168.113.3.1009 PUSH+ACK [out,bge0] 4500 002c 7ced 4000 4006 5a86 c0a8 7104 c0a8 7103 0202 03f1 915a a5c6 6523 90eb -5018 05b4 3e1f 0000 666f 6f0a 0000 +5018 05b4 3e1f 0000 666f 6f0a -# 192.168.113.4.1023 > 192.168.113.3.1008 +# 192.168.113.4.1023 > 192.168.113.3.1008 PUSH+ACK [out,bge0] 4500 0038 118a 4000 4006 c5dd c0a8 7104 c0a8 7103 03ff 03f0 91d4 c8a3 66e5 b811 8018 05b4 da34 0000 0101 080a 0039 dd6c 0000 0000 6261 720a -# 192.168.113.4.shell > 192.168.113.3.1009 +# 192.168.113.4.shell > 192.168.113.3.1009 FIN+ACK [out,bge0] 4500 0028 7cef 4000 4006 5a88 c0a8 7104 c0a8 7103 0202 03f1 915a a5ca 6523 90eb -5011 05b4 13a0 0000 0000 0000 0000 +5011 05b4 13a0 0000 -# 192.168.113.4.1023 > 192.168.113.3.1008 +# 192.168.113.4.1023 > 192.168.113.3.1008 FIN+ACK [out,bge0] 4500 0034 118c 4000 4006 c5df c0a8 7104 c0a8 7103 03ff 03f0 91d4 c8a7 66e5 b811 8011 05b4 aea6 0000 0101 080a 0039 dd6d 0000 0000 -# 192.168.113.3.1009 > 10.1.1.4.shell +# 192.168.113.3.1009 > 10.1.1.4.shell ACK [in,bge0] 4500 0028 e404 4000 4006 1a1b c0a8 7103 0a01 0104 03f1 0202 6523 90eb 915a a5cb 5010 8328 bcd3 0000 -# 192.168.113.3.1008 > 10.1.1.4.1023 +# 192.168.113.3.1008 > 10.1.1.4.1023 ACK [in,bge0] 4500 0034 e405 4000 4006 1a0e c0a8 7103 0a01 0104 03f0 03ff 66e5 b811 91d4 c8a8 8010 8328 57d7 0000 0101 080a 0000 0004 0039 dd6c -# 192.168.113.3.1009 > 10.1.1.4.shell +# 192.168.113.3.1009 > 10.1.1.4.shell FIN+ACK [in,bge0] 4500 0028 e40a 4000 4006 1a15 c0a8 7103 0a01 0104 03f1 0202 6523 90eb 915a a5cb 5011 832c bcce 0000 -# 192.168.113.3.1008 > 10.1.1.4.1023 +# 192.168.113.3.1008 > 10.1.1.4.1023 FIN+ACK [in,bge0] 4500 0034 e40b 4000 4006 1a08 c0a8 7103 0a01 0104 03f0 03ff 66e5 b811 91d4 c8a8 8011 832c 57d2 0000 0101 080a 0000 0004 0039 dd6c -# 192.168.113.4.shell > 192.168.113.3.1009 +# 192.168.113.4.shell > 192.168.113.3.1009 ACK [out,bge0] 4500 0028 0004 4000 4006 d773 c0a8 7104 c0a8 7103 0202 03f1 915a a5cb 6523 90ec -5010 05b4 139f 0000 0000 0000 0000 +5010 05b4 139f 0000 -# 192.168.113.4.1023 > 192.168.113.3.1008 +# 192.168.113.4.1023 > 192.168.113.3.1008 ACK [out,bge0] 4500 0034 118e 4000 4006 c5dd c0a8 7104 c0a8 7103 03ff 03f0 91d4 c8a8 66e5 b812 diff --git a/test/input/ni3 b/test/input/ni3 index 66b22a6d4293f..e4d12fe1dee5e 100644 --- a/test/input/ni3 +++ b/test/input/ni3 @@ -1,10 +1,20 @@ #v tos len id off ttl p sum src dst # ICMP dest unreachable with 64 bits in payload (in reply to a TCP packet # going out) -[out,df0] 45 00 00 3c 47 06 40 00 ff 06 28 aa 02 02 02 02 04 04 04 04 50 00 00 50 00 00 00 01 00 00 00 00 a0 02 16 d0 d8 e2 00 00 02 04 05 b4 04 02 08 0a 00 47 fb b0 00 00 00 00 01 03 03 00 +[out,df0] +4500 003c 4706 4000 ff06 28aa 0202 0202 0404 0404 +5000 0050 0000 0001 0000 0000 a002 16d0 d8e2 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 -[in,df0] 45 00 00 38 80 9a 00 00 ff 01 29 19 03 03 03 03 06 06 06 06 03 03 ac ab 00 00 00 00 45 00 00 3c 47 06 40 00 ff 06 20 a2 06 06 06 06 04 04 04 04 50 00 00 50 00 00 00 01 +[in,df0] +4500 0038 809a 0000 ff01 2919 0303 0303 0606 0606 +0303 acab 0000 0000 +4500 003c 4706 4000 ff06 20a2 0606 0606 0404 0404 +5000 0050 0000 0001 # ICMP dest unreachable with whole packet in payload (40 bytes = 320 bits) -[in,df0] 45 00 00 58 80 9a 00 00 ff 01 28 f9 03 03 03 03 06 06 06 06 03 03 11 3f 00 00 00 00 45 00 00 3c 47 06 40 00 ff 06 20 a2 06 06 06 06 04 04 04 04 50 00 00 50 00 00 00 01 00 00 00 00 a0 02 16 d0 d0 da 00 00 02 04 05 b4 04 02 08 0a 00 47 fb b0 00 00 00 00 01 03 03 00 +[in,df0] +4500 0058 809a 0000 ff01 28f9 0303 0303 0606 0606 +0303 113f 0000 0000 +4500 003c 4706 4000 ff06 20a2 0606 0606 0404 0404 +5000 0050 0000 0001 0000 0000 a002 16d0 d0da 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 diff --git a/test/input/ni4 b/test/input/ni4 index ad5575f953178..dac9f53b8e6a5 100644 --- a/test/input/ni4 +++ b/test/input/ni4 @@ -1,10 +1,18 @@ #v tos len id off ttl p sum src dst # ICMP dest unreachable with 64 bits in payload (in reply to a TCP packet # going out) -[out,df0] 45 00 00 3c 47 06 40 00 ff 06 28 aa 02 02 02 02 04 04 04 04 50 00 00 50 00 00 00 01 00 00 00 00 a0 02 16 d0 d8 e2 00 00 02 04 05 b4 04 02 08 0a 00 47 fb b0 00 00 00 00 01 03 03 00 +[out,df0] +4500 003c 4706 4000 ff06 28aa 0202 0202 0404 0404 +5000 0050 0000 0001 0000 0000 a002 16d0 d8e2 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 -[in,df0] 45 00 00 38 80 9a 00 00 ff 01 29 19 03 03 03 03 06 06 06 06 03 03 60 6b 00 00 00 00 45 00 00 3c 47 06 40 00 ff 06 20 a2 06 06 06 06 04 04 04 04 9c 40 00 50 00 00 00 01 +[in,df0] +4500 0038 809a 0000 ff01 2919 0303 0303 0606 0606 +0303 606b 0000 0000 4500 003c 4706 4000 ff06 20a2 0606 0606 0404 0404 9c40 0050 0000 0001 # ICMP dest unreachable with whole packet in payload (40 bytes = 320 bits) -[in,df0] 45 00 00 58 80 9a 00 00 ff 01 28 f9 03 03 03 03 06 06 06 06 03 03 11 3f 00 00 00 00 45 00 00 3c 47 06 40 00 ff 06 20 a2 06 06 06 06 04 04 04 04 9c 40 00 50 00 00 00 01 00 00 00 00 a0 02 16 d0 84 9a 00 00 02 04 05 b4 04 02 08 0a 00 47 fb b0 00 00 00 00 01 03 03 00 +[in,df0] +4500 0058 809a 0000 ff01 28f9 0303 0303 0606 0606 +0303 113f 0000 0000 +4500 003c 4706 4000 ff06 20a2 0606 0606 0404 0404 +9c40 0050 0000 0001 0000 0000 a002 16d0 849a 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 diff --git a/test/input/ni5 b/test/input/ni5 index c45be54266ff7..4b32e49d0913d 100644 --- a/test/input/ni5 +++ b/test/input/ni5 @@ -203,7 +203,7 @@ 0101 0101 0014 8033 d9f8 11d5 bd78 5c13 5010 269c 8ac7 0000 -# 21,32819 ACK "150 Opening ASCII mode data connection for /bin/ls.\r\n" +# 21,32818 ACK "150 Opening ASCII mode data connection for /bin/ls.\r\n" [in,ppp0] 4500 005d ffe9 4000 ef06 12e1 96cb e002 0101 0101 0015 8032 3786 78d5 bd6b ca16 diff --git a/test/input/ni7 b/test/input/ni7 index 30f247d39ca98..8d07937c12669 100644 --- a/test/input/ni7 +++ b/test/input/ni7 @@ -1,13 +1,13 @@ #v tos len id off ttl p sum src dst # ICMP timeout exceeded in reply to a ICMP packet coming in. [in,df0] -4500 0028 4706 4000 0111 26b4 0404 0404 -0202 0202 afc9 829e 0014 6b10 0402 0000 +4500 0028 4706 4000 0111 26b4 0404 0404 0202 0202 +afc9 829e 0014 6b10 0402 0000 3be5 468d 000a cfc3 [out,df0] -4500 0038 809a 0000 ff01 2d1d 0303 0303 -0404 0404 0b00 0125 0000 0000 4500 0028 -4706 4000 0111 1eac 0404 0404 0606 0606 +4500 0038 809a 0000 ff01 2d1d 0303 0303 0404 0404 +0b00 0125 0000 0000 +4500 0028 4706 4000 0111 1eac 0404 0404 0606 0606 afc9 829e 0014 c15e diff --git a/test/input/ni8 b/test/input/ni8 index 788e6036c4071..72205ee9a79ec 100644 --- a/test/input/ni8 +++ b/test/input/ni8 @@ -1,7 +1,7 @@ #v tos len id off ttl p sum src dst -# ICMP dest unreachable with 64 bits in payload (in reply to a TCP packet -# going out) -[in,df0] 45 00 00 3c 47 06 40 00 ff 06 20 aa 04 04 04 04 0a 02 02 02 50 00 05 00 00 00 00 01 00 00 00 00 a0 02 16 d0 cc 32 00 00 02 04 05 b4 04 02 08 0a 00 47 fb b0 00 00 00 00 01 03 03 00 +[in,df0] +4500 003c 4706 4000 ff06 20aa 0404 0404 0a02 0202 +5000 0500 0000 0001 0000 0000 a002 16d0 cc32 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 [out,df0] 4500 0038 809a 0000 ff01 2d1d 0303 0303 0404 0404 @@ -17,8 +17,11 @@ 5000 9d58 0000 0001 0000 0000 a002 16d0 3ddc 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 +# ICMP dest unreachable with 64 bits in payload (in reply to a TCP packet +# going in) [out,df0] 4500 0038 809a 0000 ff01 2b1b 0303 0303 0505 0505 0303 0fa3 0000 0000 -4500 003c 4706 4000 ff06 2aab 0404 0404 0101 0102 5000 9d58 0000 0001 +4500 003c 4706 4000 ff06 2aab 0404 0404 0101 0102 +5000 9d58 0000 0001 diff --git a/test/input/ni9 b/test/input/ni9 index 788e6036c4071..b8f45991f08d8 100644 --- a/test/input/ni9 +++ b/test/input/ni9 @@ -1,7 +1,9 @@ #v tos len id off ttl p sum src dst # ICMP dest unreachable with 64 bits in payload (in reply to a TCP packet # going out) -[in,df0] 45 00 00 3c 47 06 40 00 ff 06 20 aa 04 04 04 04 0a 02 02 02 50 00 05 00 00 00 00 01 00 00 00 00 a0 02 16 d0 cc 32 00 00 02 04 05 b4 04 02 08 0a 00 47 fb b0 00 00 00 00 01 03 03 00 +[in,df0] +4500 003c 4706 4000 ff06 20aa 0404 0404 0a02 0202 +5000 0500 0000 0001 0000 0000 a002 16d0 cc32 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 [out,df0] 4500 0038 809a 0000 ff01 2d1d 0303 0303 0404 0404 @@ -20,5 +22,6 @@ [out,df0] 4500 0038 809a 0000 ff01 2b1b 0303 0303 0505 0505 0303 0fa3 0000 0000 -4500 003c 4706 4000 ff06 2aab 0404 0404 0101 0102 5000 9d58 0000 0001 +4500 003c 4706 4000 ff06 2aab 0404 0404 0101 0102 +5000 9d58 0000 0001 diff --git a/test/input/p10 b/test/input/p10 new file mode 100644 index 0000000000000..f8162e807b046 --- /dev/null +++ b/test/input/p10 @@ -0,0 +1,10 @@ +in on bge0 tcp 5.5.5.5,10000 9.9.9.9,80 +in on bge0 tcp 5.5.5.6,10000 9.9.9.9,80 +in on bge0 tcp 5.5.5.7,10000 9.9.9.9,80 +in on bge0 tcp 5.5.5.8,10000 9.9.9.9,80 +in on bge0 tcp 5.5.5.9,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.5,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.6,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.7,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.8,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.9,10000 9.9.9.9,80 diff --git a/test/input/p11 b/test/input/p11 new file mode 100644 index 0000000000000..f8162e807b046 --- /dev/null +++ b/test/input/p11 @@ -0,0 +1,10 @@ +in on bge0 tcp 5.5.5.5,10000 9.9.9.9,80 +in on bge0 tcp 5.5.5.6,10000 9.9.9.9,80 +in on bge0 tcp 5.5.5.7,10000 9.9.9.9,80 +in on bge0 tcp 5.5.5.8,10000 9.9.9.9,80 +in on bge0 tcp 5.5.5.9,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.5,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.6,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.7,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.8,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.9,10000 9.9.9.9,80 diff --git a/test/input/p12 b/test/input/p12 new file mode 100644 index 0000000000000..f8162e807b046 --- /dev/null +++ b/test/input/p12 @@ -0,0 +1,10 @@ +in on bge0 tcp 5.5.5.5,10000 9.9.9.9,80 +in on bge0 tcp 5.5.5.6,10000 9.9.9.9,80 +in on bge0 tcp 5.5.5.7,10000 9.9.9.9,80 +in on bge0 tcp 5.5.5.8,10000 9.9.9.9,80 +in on bge0 tcp 5.5.5.9,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.5,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.6,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.7,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.8,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.9,10000 9.9.9.9,80 diff --git a/test/input/1 b/test/input/p13 index 7c3ae8a3a3dbf..f6753fac42647 100644 --- a/test/input/1 +++ b/test/input/p13 @@ -2,3 +2,7 @@ in 127.0.0.1 127.0.0.1 in 1.1.1.1 1.2.1.1 out 127.0.0.1 127.0.0.1 out 1.1.1.1 1.2.1.1 +in 2.3.0.1 1.2.1.1 +in 2.2.2.1 1.2.1.1 +in 2.2.0.1 1.2.1.1 +out 4.4.1.1 1.2.1.1 diff --git a/test/input/p4 b/test/input/p4 new file mode 100644 index 0000000000000..46c0998cb4ed7 --- /dev/null +++ b/test/input/p4 @@ -0,0 +1,12 @@ +in 127.0.0.1 127.0.0.1 +in 1.1.1.1 1.2.1.1 +out 127.0.0.1 127.0.0.1 +out 1.1.1.1 1.2.1.1 +in 2.3.0.1 1.2.1.1 +in 2.2.2.1 1.2.1.1 +in 2.2.0.1 1.2.1.1 +out 2.2.2.1 1.2.1.1 +out 2.2.2.1 1.2.1.2 +out 2.2.0.1 1.2.1.1 +out 2.2.0.1 1.2.1.3 +out 4.4.1.1 1.2.1.1 diff --git a/test/input/p6 b/test/input/p6 new file mode 100644 index 0000000000000..37c26ce3442f9 --- /dev/null +++ b/test/input/p6 @@ -0,0 +1,2 @@ +in 131.107.1.1 10.1.1.1 +out 10.1.1.1 131.107.1.1 diff --git a/test/input/p7 b/test/input/p7 new file mode 100644 index 0000000000000..f8162e807b046 --- /dev/null +++ b/test/input/p7 @@ -0,0 +1,10 @@ +in on bge0 tcp 5.5.5.5,10000 9.9.9.9,80 +in on bge0 tcp 5.5.5.6,10000 9.9.9.9,80 +in on bge0 tcp 5.5.5.7,10000 9.9.9.9,80 +in on bge0 tcp 5.5.5.8,10000 9.9.9.9,80 +in on bge0 tcp 5.5.5.9,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.5,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.6,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.7,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.8,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.9,10000 9.9.9.9,80 diff --git a/test/input/p9 b/test/input/p9 new file mode 100644 index 0000000000000..f8162e807b046 --- /dev/null +++ b/test/input/p9 @@ -0,0 +1,10 @@ +in on bge0 tcp 5.5.5.5,10000 9.9.9.9,80 +in on bge0 tcp 5.5.5.6,10000 9.9.9.9,80 +in on bge0 tcp 5.5.5.7,10000 9.9.9.9,80 +in on bge0 tcp 5.5.5.8,10000 9.9.9.9,80 +in on bge0 tcp 5.5.5.9,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.5,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.6,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.7,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.8,10000 9.9.9.9,80 +in on bge0 tcp 5.5.6.9,10000 9.9.9.9,80 diff --git a/test/intest b/test/intest index e94ca0894e573..bcafe76d0dcdb 100755 --- a/test/intest +++ b/test/intest @@ -1,22 +1,12 @@ #!/bin/sh -mkdir -p results -if [ -f /usr/ucb/touch ] ; then - TOUCH=/usr/ucb/touch -else - if [ -f /usr/bin/touch ] ; then - TOUCH=/usr/bin/touch - else - if [ -f /bin/touch ] ; then - TOUCH=/bin/touch - fi - fi -fi -echo "$1..."; -/bin/cp /dev/null results/$1 -../ipnat -Rnvf regress/$1 2>/dev/null > results/$1 -cmp expected/$1 results/$1 -status=$? -if [ $status = 0 ] ; then - $TOUCH $1 -fi +name=$1 + +. ./ipflib.sh + +test_init + +echo "$name..."; +/bin/cp /dev/null results/$name +../ipnat -Rnvf regress/$name 2>/dev/null > results/$name +check_results $name exit $status diff --git a/test/ipflib.sh b/test/ipflib.sh new file mode 100644 index 0000000000000..82d473d0d36bc --- /dev/null +++ b/test/ipflib.sh @@ -0,0 +1,59 @@ +#!/bin/sh +# +# (C)opyright 2012 by Darren Reed. +# +# See the IPFILTER.LICENCE file for details on licencing. +# +test_init() { + mkdir -p results + find_touch + set_core $name 1 +} + +set_core() { + if [ -n "${FINDLEAKS}" -a -x /bin/mdb ] ; then + _findleaks=1 + else + _findleaks=0 + fi + if [ -x /bin/coreadm ] ; then + _cn="$1.$2.core" + coreadm -p "${PWD}/$_cn" + else + _cn= + fi +} + +test_end_leak() { + if [ $1 -ne 0 ] ; then + if [ ${_findleaks} = 1 -a -f $_cn ] ; then + echo "==== ${name}:${n} ====" >> leaktest + echo '::findleaks' | mdb ../i86/ipftest $_cn >> leaktest + rm $_cn + else + exit 2; + fi + fi +} + +check_results() { + cmp expected/$1 results/$1 + status=$? + if [ $status = 0 ] ; then + $TOUCH $1 + fi +} + +find_touch() { + if [ -f /bin/touch ] ; then + TOUCH=/bin/touch + else + if [ -f /usr/bin/touch ] ; then + TOUCH=/usr/bin/touch + else + if [ -f /usr/ucb/touch ] ; then + TOUCH=/usr/ucb/touch + fi + fi + fi +} diff --git a/test/iptest b/test/iptest index bb3ab5ea86fcc..70fd9d89c7222 100644 --- a/test/iptest +++ b/test/iptest @@ -1,22 +1,12 @@ #!/bin/sh -mkdir -p results -if [ -f /usr/ucb/touch ] ; then - TOUCH=/usr/ucb/touch -else - if [ -f /usr/bin/touch ] ; then - TOUCH=/usr/bin/touch - else - if [ -f /bin/touch ] ; then - TOUCH=/bin/touch - fi - fi -fi -echo "$1..."; -/bin/cp /dev/null results/$1 -../ippool -f regress/$1 -nRv 2>/dev/null > results/$1 -cmp expected/$1 results/$1 -status=$? -if [ $status = 0 ] ; then - $TOUCH $1 -fi +name=$1 + +. ./ipflib.sh + +test_init + +echo "$name..."; +/bin/cp /dev/null results/$name +../ippool -f regress/$name -nRv 2>/dev/null > results/$name +check_results $name exit $status diff --git a/test/itest b/test/itest index 8fefc634bfb9a..84b045454ff32 100644 --- a/test/itest +++ b/test/itest @@ -1,29 +1,30 @@ #!/bin/sh -mkdir -p results -if [ -f /usr/ucb/touch ] ; then - TOUCH=/usr/ucb/touch -else - if [ -f /usr/bin/touch ] ; then - TOUCH=/usr/bin/touch - else - if [ -f /bin/touch ] ; then - TOUCH=/bin/touch - fi - fi -fi -echo "$1..."; -/bin/cp /dev/null results/$1 +name=$1 + +. ./ipflib.sh + +test_init + +echo "$name..."; +/bin/cp /dev/null results/$name case $3 in ipf) - ../ipf -Rnvf regress/$1 2>/dev/null > results/$1 + ../ipf -Rnvf regress/$name 2>/dev/null > results/$name + status=$? + if [ $status -ne 0 ] ; then + echo "ERROR: ../ipf -Rnvf regress/$name" + fi ;; ipftest) - ../ipftest -D -r regress/$1 -i /dev/null > results/$1 + unset FINDLEAKS + ../ipftest -D -r regress/$name -i /dev/null > results/$name + status=$? + if [ $status -ne 0 ] ; then + echo "ERROR: ../ipftest -D -r regress/$name" + fi ;; esac -cmp expected/$1 results/$1 -status=$? -if [ $status = 0 ] ; then - $TOUCH $1 +if [ $status -eq 0 ] ; then + check_results $name fi exit $status diff --git a/test/logtest b/test/logtest index 089f9150f4798..0e9407556413a 100755 --- a/test/logtest +++ b/test/logtest @@ -1,18 +1,12 @@ #!/bin/sh +name=$1 format=$2 -mkdir -p results -if [ -f /usr/ucb/touch ] ; then - TOUCH=/usr/ucb/touch -else - if [ -f /usr/bin/touch ] ; then - TOUCH=/usr/bin/touch - else - if [ -f /bin/touch ] ; then - TOUCH=/bin/touch - fi - fi -fi -echo "$1..."; + +. ./ipflib.sh + +test_init + +echo "$name..."; case `uname -s` in OSF1) @@ -23,16 +17,20 @@ OSF1) ;; esac -/bin/cp /dev/null results/$1 -/bin/cp /dev/null results/$1.b +n=1 +/bin/cp /dev/null results/$name +/bin/cp /dev/null results/$name.b ( while read rule; do - echo $rule >> results/$1 - echo $rule | ../ipftest -br - -F $format -i input/$1 -l logout > /dev/null - if [ $? -ne 0 ] ; then - /bin/rm -f logout - exit 1 - fi + /bin/rm -f logout + set_core $name $n + echo $rule >> results/$name + echo $rule | ../ipftest -br - -F $format -i input/$name -l logout > /dev/null & + back=$! + wait $back + test_end_leak $? + n=`expr $n + 1` + TZ=$GMT ../ipmon -P /dev/null -f logout >> results/$1 echo "--------" >> results/$1 TZ=$GMT ../ipmon -P /dev/null -bf logout >> results/$1.b diff --git a/test/mhtest b/test/mhtest deleted file mode 100755 index a4d48d6934769..0000000000000 --- a/test/mhtest +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh -# multiple rules at the same time - -if [ -f /usr/ucb/touch ] ; then - TOUCH=/usr/ucb/touch -else - if [ -f /usr/bin/touch ] ; then - TOUCH=/usr/bin/touch - else - if [ -f /bin/touch ] ; then - TOUCH=/bin/touch - fi - fi -fi -echo "$1..."; - -/bin/cp /dev/null results/$1 - -../ipftest -br regress/$1 -F hex -i input/$1 > results/$1 -if [ $? -ne 0 ] ; then - exit 1 -fi -echo "--------" >> results/$1 - -cmp expected/$1 results/$1 -status=$? -if [ $status -ne 0 ] ; then - exit $status -fi -cmp expected/$1 results/$1 -status=$? -if [ $status -ne 0 ] ; then - exit $status -fi -$TOUCH $1 -exit 0 diff --git a/test/mtest b/test/mtest index 2a3ed38b34f72..aed9fb9842438 100755 --- a/test/mtest +++ b/test/mtest @@ -1,38 +1,20 @@ #!/bin/sh +name=$1 format=$2 -mkdir -p results -# multiple rules at the same time -if [ -f /usr/ucb/touch ] ; then - TOUCH=/usr/ucb/touch -else - if [ -f /usr/bin/touch ] ; then - TOUCH=/usr/bin/touch - else - if [ -f /bin/touch ] ; then - TOUCH=/bin/touch - fi - fi -fi -echo "$1..."; +. ./ipflib.sh + +test_init + +echo "$name..."; /bin/cp /dev/null results/$1 -../ipftest -F $format -Rbr regress/$1 -i input/$1 > results/$1 -if [ $? -ne 0 ] ; then - exit 1 -fi -echo "--------" >> results/$1 +../ipftest -F $format $4 -Rbr regress/$name -i input/$name > results/$name & +back=$! +wait $back +test_end_leak $? +echo "--------" >> results/$name -cmp expected/$1 results/$1 -status=$? -if [ $status -ne 0 ] ; then - exit $status -fi -cmp expected/$1 results/$1 -status=$? -if [ $status -ne 0 ] ; then - exit $status -fi -$TOUCH $1 -exit 0 +check_results $name +exit $status diff --git a/test/natipftest b/test/natipftest index 5776b4202c955..493f18b43a836 100755 --- a/test/natipftest +++ b/test/natipftest @@ -3,6 +3,12 @@ mode=$1 name=$2 input=$3 output=$4 +n=1 + +. ./ipflib.sh + +test_init + shift if [ $output = hex ] ; then format="-xF $input" @@ -21,51 +27,33 @@ while [ $# -ge 1 ] ; do fi shift done -mkdir -p results -if [ -f /usr/ucb/touch ] ; then - TOUCH=/usr/ucb/touch -else - if [ -f /usr/bin/touch ] ; then - TOUCH=/usr/bin/touch - else - if [ -f /bin/touch ] ; then - TOUCH=/bin/touch - fi - fi -fi case $mode in single) echo "$name..."; /bin/cp /dev/null results/$name ( while read rule; do + set_core $name $n echo "$rule" | ../ipftest -R $format -b -r regress/$name.ipf -N - -i input/$name >> \ - results/$name; - if [ $? -ne 0 ] ; then - exit 1; - fi + results/$name & + back=$! + wait $back + test_end_leak $? + n=`expr $n + 1` echo "-------------------------------" >> results/$name done ) < regress/$name.nat - cmp expected/$name results/$name - status=$? - if [ $status = 0 ] ; then - $TOUCH $name - fi + check_results $name ;; multi) echo "$name..."; /bin/cp /dev/null results/$name ../ipftest -R $format -b -r regress/$name.ipf -N regress/$name.nat \ - -i input/$name >> results/$name; - if [ $? -ne 0 ] ; then - exit 2; - fi + -i input/$name >> results/$name & + back=$! + wait $back + test_end_leak $? echo "-------------------------------" >> results/$name - cmp expected/$name results/$name - status=$? - if [ $status = 0 ] ; then - $TOUCH $name - fi + check_results $name ;; esac exit $status diff --git a/test/nattest b/test/nattest index fece276a6a766..c970877171907 100755 --- a/test/nattest +++ b/test/nattest @@ -1,4 +1,10 @@ #!/bin/sh +name=$1 + +. ./ipflib.sh + +test_init + if [ $3 = hex ] ; then format="-xF $2" else @@ -14,29 +20,18 @@ if [ "$4" != "" ] ; then ;; esac fi -if [ -f /usr/ucb/touch ] ; then - TOUCH=/usr/ucb/touch -else - if [ -f /usr/bin/touch ] ; then - TOUCH=/usr/bin/touch - else - if [ -f /bin/touch ] ; then - TOUCH=/bin/touch - fi - fi -fi -echo "$1..."; -/bin/cp /dev/null results/$1 + +echo "$name..."; +n=1 +/bin/cp /dev/null results/$name ( while read rule; do - echo "$rule" | ../ipftest $format -RbN - -i input/$1 >> results/$1; - if [ $? -ne 0 ] ; then - exit 1; - fi - echo "-------------------------------" >> results/$1 -done ) < regress/$1 -cmp expected/$1 results/$1 -status=$? -if [ $status = 0 ] ; then - $TOUCH $1 -fi + set_core $name $n + echo "$rule" | ../ipftest $format -DRbN - -i input/$name >>results/$name & + back=$! + wait $back + test_end_leak $? + n=`expr $n + 1` + echo "-------------------------------" >> results/$name +done ) < regress/$name +check_results $name exit $status diff --git a/test/ptest b/test/ptest index 7deccd3354f42..87daacc8072a9 100644 --- a/test/ptest +++ b/test/ptest @@ -1,31 +1,24 @@ #!/bin/sh -mkdir -p results -if [ -f /usr/ucb/touch ] ; then - TOUCH=/usr/ucb/touch +name=$1 + +. ./ipflib.sh + +test_init + +echo "$name..."; +/bin/cp /dev/null results/$name +if [ -f regress/$name.pool -a -f regress/$name.ipf ] ; then + ../ipftest -RD -b -P regress/$name.pool -r regress/$name.ipf -i input/$name >> \ + results/$name & +elif [ -f regress/$name.pool -a -f regress/$name.nat ] ; then + ../ipftest -RD -b -P regress/$name.pool -N regress/$name.nat -i input/$name >> \ + results/$name & else - if [ -f /usr/bin/touch ] ; then - TOUCH=/usr/bin/touch - else - if [ -f /bin/touch ] ; then - TOUCH=/bin/touch - fi - fi -fi -echo "$1..."; -/bin/cp /dev/null results/$1 -if [ -f regress/$1.pool ] ; then - ../ipftest -RD -b -P regress/$1.pool -r regress/$1.ipf -i input/$1 >> \ - results/$1 -else - ../ipftest -RD -b -r regress/$1.ipf -i input/$1 >> results/$1 -fi -if [ $? -ne 0 ] ; then - exit 1; -fi -echo "-------------------------------" >> results/$1 -cmp expected/$1 results/$1 -status=$? -if [ $status = 0 ] ; then - $TOUCH $1 + ../ipftest -RD -b -r regress/$name.ipf -i input/$name >> results/$name & fi +back=$! +wait $back +test_end_leak $? +echo "-------------------------------" >> results/$name +check_results $name exit $status diff --git a/test/regress/1 b/test/regress/1 deleted file mode 100644 index 6a2ede9e31c09..0000000000000 --- a/test/regress/1 +++ /dev/null @@ -1,4 +0,0 @@ -block in all -pass in all -block out all -pass out all diff --git a/test/regress/10 b/test/regress/10 deleted file mode 100644 index 355298308e72d..0000000000000 --- a/test/regress/10 +++ /dev/null @@ -1,18 +0,0 @@ -block in from any to any with not ipopts -pass in from any to any with not opt sec-class topsecret -block in from any to any with not opt ssrr,sec-class topsecret -pass in from any to any with not opt ssrr,sec-class topsecret -block in from any to any with not opt ts,sec-class topsecret -pass in from any to any with not opt ts,sec-class topsecret -block in from any to any with not opt sec-class secret -pass in from any to any with not opt sec-class secret -block in from any to any with not opt lsrr,ssrr -pass in from any to any with not opt lsrr,ssrr -pass in from any to any with not ipopts -block in from any to any with not opt lsrr -pass in from any to any with not opt lsrr -block in from any to any with not opt ssrr,ts -pass in from any to any with not opt ssrr,ts -block in from any to any with not opt rr -pass in from any to any with not opt rr -block in from any to any with not opt sec-class topsecret diff --git a/test/regress/11 b/test/regress/11 deleted file mode 100644 index 0bf0a2a7322d3..0000000000000 --- a/test/regress/11 +++ /dev/null @@ -1,6 +0,0 @@ -pass in proto tcp from any to any port = 23 flags S/SA keep state -block in proto tcp from any to any port = 23 flags S/SA keep state -pass in proto udp from any to any port = 53 keep frags -block in proto udp from any to any port = 53 keep frags -pass in proto udp from any to any port = 53 keep state -block in proto udp from any to any port = 53 keep state diff --git a/test/regress/12 b/test/regress/12 deleted file mode 100644 index c29f839aa5021..0000000000000 --- a/test/regress/12 +++ /dev/null @@ -1,6 +0,0 @@ -pass in proto tcp from any port > 1024 to any port = 25 with not short -pass in proto tcp from any port > 1024 to any port = 25 -block in proto tcp from any to any with short -block in proto tcp from any to any with frag -pass in proto udp from any port = 53 to any port = 53 -block in proto udp from any port = 53 to any port = 53 with not short diff --git a/test/regress/13 b/test/regress/13 deleted file mode 100644 index f123e4781c862..0000000000000 --- a/test/regress/13 +++ /dev/null @@ -1,6 +0,0 @@ -pass in proto tcp from any to any port = 25 flags S/SA keep frags -block in proto tcp from any to any port = 25 flags S/SA keep frags -pass in proto udp from any to any port = 53 keep frags -block in proto udp from any to any port = 53 keep frags -pass in proto tcp from any to any port = 25 flags S/SA keep state keep frags -block in proto tcp from any to any port = 25 flags S/SA keep state keep frags diff --git a/test/regress/14 b/test/regress/14 deleted file mode 100644 index aa54af8df11da..0000000000000 --- a/test/regress/14 +++ /dev/null @@ -1,8 +0,0 @@ -block in from !1.1.1.1 to any -pass in from 1.1.1.1 to !any -block in from 1.1.1.1/24 to !any -pass in from !1.1.1.1/24 to any -block in from !1.1.1.1/16 to any -pass in from 1.1.1.1/16 to !any -block in from 1.1.1.1/0 to !any -pass in from !1.1.1.1/0 to any diff --git a/test/regress/2 b/test/regress/2 deleted file mode 100644 index e2f02a46e2839..0000000000000 --- a/test/regress/2 +++ /dev/null @@ -1,6 +0,0 @@ -block in proto tcp from any to any -pass in proto tcp from any to any -block in proto udp from any to any -pass in proto udp from any to any -block in proto icmp from any to any -pass in proto icmp from any to any diff --git a/test/regress/3 b/test/regress/3 deleted file mode 100644 index ee80729cfc9b4..0000000000000 --- a/test/regress/3 +++ /dev/null @@ -1,8 +0,0 @@ -block in from 1.1.1.1 to any -pass in from 1.1.1.1 to any -block in from 1.1.1.1/24 to any -pass in from 1.1.1.1/24 to any -block in from 1.1.1.1/16 to any -pass in from 1.1.1.1/16 to any -block in from 1.1.1.1/0 to any -pass in from 1.1.1.1/0 to any diff --git a/test/regress/4 b/test/regress/4 deleted file mode 100644 index bc8af2f0cae2f..0000000000000 --- a/test/regress/4 +++ /dev/null @@ -1,8 +0,0 @@ -block in from any to 1.1.1.1 -pass in from any to 1.1.1.1 -block in from any to 1.1.1.1/24 -pass in from any to 1.1.1.1/24 -block in from any to 1.1.1.1/16 -pass in from any to 1.1.1.1/16 -block in from any to 1.1.1.1/0 -pass in from any to 1.1.1.1/0 diff --git a/test/regress/5 b/test/regress/5 deleted file mode 100644 index 998eabd4b10bd..0000000000000 --- a/test/regress/5 +++ /dev/null @@ -1,48 +0,0 @@ -block in proto tcp from any port = 23 to any -block in proto udp from any port = 23 to any -block in proto tcp/udp from any port = 23 to any -pass in proto tcp from any port <= 1023 to any -pass in proto udp from any port <= 1023 to any -pass in proto tcp/udp from any port <= 1023 to any -block in proto tcp from any port >= 1024 to any -block in proto udp from any port >= 1024 to any -block in proto tcp/udp from any port >= 1024 to any -pass in proto tcp from any port >= 1024 to any -pass in proto udp from any port >= 1024 to any -pass in proto tcp/udp from any port >= 1024 to any -block in proto tcp from any port 0 >< 512 to any -block in proto udp from any port 0 >< 512 to any -block in proto tcp/udp from any port 0 >< 512 to any -pass in proto tcp from any port 0 >< 512 to any -pass in proto udp from any port 0 >< 512 to any -pass in proto tcp/udp from any port 0 >< 512 to any -block in proto tcp from any port 6000 <> 6009 to any -block in proto udp from any port 6000 <> 6009 to any -block in proto tcp/udp from any port 6000 <> 6009 to any -pass in proto tcp from any port 6000 <> 6009 to any -pass in proto udp from any port 6000 <> 6009 to any -pass in proto tcp/udp from any port 6000 <> 6009 to any -pass in proto tcp from any port = 23 to any -pass in proto udp from any port = 23 to any -pass in proto tcp/udp from any port = 23 to any -block in proto tcp from any port != 21 to any -block in proto udp from any port != 21 to any -block in proto tcp/udp from any port != 21 to any -pass in proto tcp from any port != 21 to any -pass in proto udp from any port != 21 to any -pass in proto tcp/udp from any port != 21 to any -block in proto tcp from any port < 1024 to any -block in proto udp from any port < 1024 to any -block in proto tcp/udp from any port < 1024 to any -pass in proto tcp from any port < 1024 to any -pass in proto udp from any port < 1024 to any -pass in proto tcp/udp from any port < 1024 to any -block in proto tcp from any port > 1023 to any -block in proto udp from any port > 1023 to any -block in proto tcp/udp from any port > 1023 to any -pass in proto tcp from any port > 1023 to any -pass in proto udp from any port > 1023 to any -pass in proto tcp/udp from any port > 1023 to any -block in proto tcp from any port <= 1023 to any -block in proto udp from any port <= 1023 to any -block in proto tcp/udp from any port <= 1023 to any diff --git a/test/regress/6 b/test/regress/6 deleted file mode 100644 index 291f09adcdbcf..0000000000000 --- a/test/regress/6 +++ /dev/null @@ -1,48 +0,0 @@ -block in proto tcp from any to any port = 23 -block in proto udp from any to any port = 23 -block in proto tcp/udp from any to any port = 23 -pass in proto tcp from any to any port <= 1023 -pass in proto udp from any to any port <= 1023 -pass in proto tcp/udp from any to any port <= 1023 -block in proto tcp from any to any port >= 1024 -block in proto udp from any to any port >= 1024 -block in proto tcp/udp from any to any port >= 1024 -pass in proto tcp from any to any port >= 1024 -pass in proto udp from any to any port >= 1024 -pass in proto tcp/udp from any to any port >= 1024 -block in proto tcp from any to any port 0 >< 512 -block in proto udp from any to any port 0 >< 512 -block in proto tcp/udp from any to any port 0 >< 512 -pass in proto tcp from any to any port 0 >< 512 -pass in proto udp from any to any port 0 >< 512 -pass in proto tcp/udp from any to any port 0 >< 512 -block in proto tcp from any to any port 6000 <> 6009 -block in proto udp from any to any port 6000 <> 6009 -block in proto tcp/udp from any to any port 6000 <> 6009 -pass in proto tcp from any to any port 6000 <> 6009 -pass in proto udp from any to any port 6000 <> 6009 -pass in proto tcp/udp from any to any port 6000 <> 6009 -pass in proto tcp from any to any port = 23 -pass in proto udp from any to any port = 23 -pass in proto tcp/udp from any to any port = 23 -block in proto tcp from any to any port != 21 -block in proto udp from any to any port != 21 -block in proto tcp/udp from any to any port != 21 -pass in proto tcp from any to any port != 21 -pass in proto udp from any to any port != 21 -pass in proto tcp/udp from any to any port != 21 -block in proto tcp from any to any port < 1024 -block in proto udp from any to any port < 1024 -block in proto tcp/udp from any to any port < 1024 -pass in proto tcp from any to any port < 1024 -pass in proto udp from any to any port < 1024 -pass in proto tcp/udp from any to any port < 1024 -block in proto tcp from any to any port > 1023 -block in proto udp from any to any port > 1023 -block in proto tcp/udp from any to any port > 1023 -pass in proto tcp from any to any port > 1023 -pass in proto udp from any to any port > 1023 -pass in proto tcp/udp from any to any port > 1023 -block in proto tcp from any to any port <= 1023 -block in proto udp from any to any port <= 1023 -block in proto tcp/udp from any to any port <= 1023 diff --git a/test/regress/7 b/test/regress/7 deleted file mode 100644 index 6848a688a3744..0000000000000 --- a/test/regress/7 +++ /dev/null @@ -1,6 +0,0 @@ -block in proto icmp from any to any icmp-type echo -pass in proto icmp from any to any icmp-type echo -block in proto icmp from any to any icmp-type unreach code 3 -pass in proto icmp from any to any icmp-type unreach code 3 -block in proto icmp from any to any icmp-type echorep -pass in proto icmp from any to any icmp-type echorep diff --git a/test/regress/8 b/test/regress/8 deleted file mode 100644 index 0f28fd2611488..0000000000000 --- a/test/regress/8 +++ /dev/null @@ -1,6 +0,0 @@ -block in proto tcp from any to any flags S -pass in proto tcp from any to any flags S -block in proto tcp from any to any flags S/SA -pass in proto tcp from any to any flags S/SA -block in proto tcp from any to any flags S/APU -pass in proto tcp from any to any flags S/APU diff --git a/test/regress/9 b/test/regress/9 deleted file mode 100644 index 17bc967378775..0000000000000 --- a/test/regress/9 +++ /dev/null @@ -1,18 +0,0 @@ -block in from any to any with ipopts -pass in from any to any with opt sec-class topsecret -block in from any to any with opt ssrr,sec-class topsecret -pass in from any to any with opt ssrr,sec-class topsecret -block in from any to any with opt ts,sec-class topsecret -pass in from any to any with opt ts,sec-class topsecret -block in from any to any with opt sec-class secret -pass in from any to any with opt sec-class secret -block in from any to any with opt lsrr,ssrr -pass in from any to any with opt lsrr,ssrr -pass in from any to any with ipopts -block in from any to any with opt lsrr -pass in from any to any with opt lsrr -block in from any to any with opt ssrr,ts -pass in from any to any with opt ssrr,ts -block in from any to any with opt rr -pass in from any to any with opt rr -block in from any to any with opt sec-class topsecret diff --git a/test/regress/f13 b/test/regress/f13 index 8106419f3e087..393a65e9eff08 100644 --- a/test/regress/f13 +++ b/test/regress/f13 @@ -6,3 +6,4 @@ pass in proto tcp from any to any port = 25 flags S/SA keep state keep frags block in proto tcp from any to any port = 25 flags S/SA keep state keep frags pass in proto udp from any to any port = 53 keep frags(strict) pass in proto tcp from any to any port = 25 keep state(strict) +pass in proto tcp from any to any port = 25 keep state(loose) diff --git a/test/regress/f21 b/test/regress/f21 new file mode 100644 index 0000000000000..26ffa87f23860 --- /dev/null +++ b/test/regress/f21 @@ -0,0 +1,2 @@ +pass out proto tcp all flags S keep state(icmp-head icmpredir) +block in proto icmp all icmp-type redir group icmpredir diff --git a/test/regress/f22 b/test/regress/f22 new file mode 100644 index 0000000000000..10765db18f065 --- /dev/null +++ b/test/regress/f22 @@ -0,0 +1,2 @@ +pass in proto tcp all flags S keep state(icmp-head icmpredir) +block out proto icmp all icmp-type redir group icmpredir diff --git a/test/regress/f25 b/test/regress/f25 new file mode 100644 index 0000000000000..c018b498dd3ae --- /dev/null +++ b/test/regress/f25 @@ -0,0 +1 @@ +pass in on hme0 proto udp all with mcast keep state diff --git a/test/regress/f26 b/test/regress/f26 new file mode 100644 index 0000000000000..22357a475cae0 --- /dev/null +++ b/test/regress/f26 @@ -0,0 +1,6 @@ +pass in quick proto tcp from 1.1.1.0/24 to any port = 22 flags S keep state(max-srcs 3) +pass in quick proto tcp from 1.1.1.0/24 to any port = 22 flags S keep state(max-srcs 3, max-per-src 1/32) +pass in quick proto tcp from 1.1.1.0/24 to any port = 22 flags S keep state(max-srcs 3, max-per-src 1/16) +pass in quick proto tcp all flags S keep state(max-srcs 3) +pass in quick proto tcp all flags S keep state(max-srcs 3, max-per-src 1/32) +pass in quick proto tcp all flags S keep state(max-srcs 3, max-per-src 1/16) diff --git a/test/regress/f27 b/test/regress/f27 new file mode 100644 index 0000000000000..22357a475cae0 --- /dev/null +++ b/test/regress/f27 @@ -0,0 +1,6 @@ +pass in quick proto tcp from 1.1.1.0/24 to any port = 22 flags S keep state(max-srcs 3) +pass in quick proto tcp from 1.1.1.0/24 to any port = 22 flags S keep state(max-srcs 3, max-per-src 1/32) +pass in quick proto tcp from 1.1.1.0/24 to any port = 22 flags S keep state(max-srcs 3, max-per-src 1/16) +pass in quick proto tcp all flags S keep state(max-srcs 3) +pass in quick proto tcp all flags S keep state(max-srcs 3, max-per-src 1/32) +pass in quick proto tcp all flags S keep state(max-srcs 3, max-per-src 1/16) diff --git a/test/regress/f28.ipf b/test/regress/f28.ipf new file mode 100644 index 0000000000000..ca427715ac108 --- /dev/null +++ b/test/regress/f28.ipf @@ -0,0 +1,2 @@ +block in all +pass in on nic0 to dstlist/spread from 4.4.0.0/16 to any diff --git a/test/regress/f28.pool b/test/regress/f28.pool new file mode 100644 index 0000000000000..499b603446625 --- /dev/null +++ b/test/regress/f28.pool @@ -0,0 +1,2 @@ +pool ipf/dstlist (name spread; policy round-robin;) + { nic0:1.1.0.2; nic1:1.1.1.2; nic2:1.1.2.2; nic3:1.1.3.2; }; diff --git a/test/regress/f29.ipf b/test/regress/f29.ipf new file mode 100644 index 0000000000000..e4634cc1fa4d7 --- /dev/null +++ b/test/regress/f29.ipf @@ -0,0 +1,2 @@ +block in all +pass in on nic0 to dstlist/spread from 4.4.0.0/16 to any keep state diff --git a/test/regress/f29.pool b/test/regress/f29.pool new file mode 100644 index 0000000000000..499b603446625 --- /dev/null +++ b/test/regress/f29.pool @@ -0,0 +1,2 @@ +pool ipf/dstlist (name spread; policy round-robin;) + { nic0:1.1.0.2; nic1:1.1.1.2; nic2:1.1.2.2; nic3:1.1.3.2; }; diff --git a/test/regress/f30 b/test/regress/f30 new file mode 100644 index 0000000000000..84a8970eb8605 --- /dev/null +++ b/test/regress/f30 @@ -0,0 +1,4 @@ +pass in on hme0 proto udp all with not ipopts keep state +pass in on hme0 proto udp all with ipopts keep state +pass in on hme0 proto tcp all flags S with opt rr keep state +pass in on hme0 proto tcp all flags S with opt sec-class secret keep state diff --git a/test/regress/i11 b/test/regress/i11 index cb7d68389993a..ca65da313b0b6 100644 --- a/test/regress/i11 +++ b/test/regress/i11 @@ -8,4 +8,5 @@ pass out on ppp0 in-via le0 proto tcp from any to any keep state pass in on ed0,vx0 out-via vx0,ed0 proto udp from any to any keep state pass in proto tcp from any port gt 1024 to localhost port eq 1024 keep state pass in proto tcp all flags S keep state(strict,newisn,no-icmp-err,limit 101,age 600) +pass in proto tcp all flags S keep state(loose,newisn,no-icmp-err,limit 101,age 600) pass in proto udp all keep state(age 10/20,sync) diff --git a/test/regress/i12 b/test/regress/i12 index 5342702353e4a..f42c2d522b5dd 100644 --- a/test/regress/i12 +++ b/test/regress/i12 @@ -1,9 +1,9 @@ pass in from 1.1.1.1/32 to 2.2.2.2/32 -pass in from (2.2.2.2/24,3.3.3.3/32) to 4.4.4.4/32 -pass in from (2.2.2.2/24,3.3.3.3/32) to (5.5.5.5/32,6.6.6.6/32) -pass in from (2.2.2.2/24,3.3.3.3/32) to (5.5.5.5/32,6.6.6.6/32) port = (22,25) -pass in proto tcp from (2.2.2.2/24,3.3.3.3/32) port = (53,9) to (5.5.5.5/32,6.6.6.6/32) -pass in proto udp from (2.2.2.2/24,3.3.3.3/32) to (5.5.5.5/32,6.6.6.6/32) port = (53,9) +pass in from {2.2.2.2/24,3.3.3.3/32} to 4.4.4.4/32 +pass in from {2.2.2.2/24,3.3.3.3/32} to {5.5.5.5/32,6.6.6.6/32} +pass in from {2.2.2.2/24,3.3.3.3/32} to {5.5.5.5/32,6.6.6.6/32} port = {22,25} +pass in proto tcp from {2.2.2.2/24,3.3.3.3/32} port = {53,9} to {5.5.5.5/32,6.6.6.6/32} +pass in proto udp from {2.2.2.2/24,3.3.3.3/32} to {5.5.5.5/32,6.6.6.6/32} port = {53,9} pass in from 10.10.10.10 to 11.11.11.11 pass in from pool/101 to hash/202 pass in from hash/303 to pool/404 diff --git a/test/regress/i14 b/test/regress/i14 index 2cd26130640a2..54613a516706b 100644 --- a/test/regress/i14 +++ b/test/regress/i14 @@ -8,3 +8,5 @@ pass in proto tcp from 1.0.0.1 to 2.0.0.2 group 101 pass in proto udp from 2.0.0.2 to 3.0.0.3 group 101 block in on vm0 proto tcp/udp all head vm0-group pass in from 1.1.1.1 to 2.2.2.2 group vm0-group +block in on vm0 proto tcp/udp all head vm0-group +pass in from 1.1.1.1 to 2.2.2.2 group vm0-group diff --git a/test/regress/i17 b/test/regress/i17 index e399248222a64..139b86a8d84af 100644 --- a/test/regress/i17 +++ b/test/regress/i17 @@ -9,5 +9,5 @@ pass in from localhost to any @0 pass in from 1.1.1.1 to any @1 110 pass in from 2.2.2.2 to any @2 pass in from 3.3.3.3 to any -call fr_srcgrpmap/100 out from 10.1.0.0/16 to any -call now fr_dstgrpmap/200 in from 10.2.0.0/16 to any +call srcgrpmap/100 out from 10.1.0.0/16 to any +call now dstgrpmap/200 in from 10.2.0.0/16 to any diff --git a/test/regress/i18 b/test/regress/i18 index 03ce713b4a549..b55b11a01fe82 100644 --- a/test/regress/i18 +++ b/test/regress/i18 @@ -1,3 +1,3 @@ -pass in tos (80,0x80) all -pass in tos (0x80,80) all -block in ttl (0,1,2,3,4,5,6) all +pass in tos {80,0x80} all +pass out tos {0x80,80} all +block in ttl {0,1,2,3,4,5,6} all diff --git a/test/regress/i2 b/test/regress/i2 index 50f610750bc2d..f69e28edb13da 100644 --- a/test/regress/i2 +++ b/test/regress/i2 @@ -6,3 +6,4 @@ block in proto 17 from any to any block in proto 250 from any to any pass in proto tcp/udp from any to any block in proto tcp-udp from any to any +block in proto tcp-udp from any to any diff --git a/test/regress/i21 b/test/regress/i21 index 9d583ab0894f4..237f8fadb648e 100644 --- a/test/regress/i21 +++ b/test/regress/i21 @@ -2,6 +2,6 @@ pass in from port = 10101 pass out from any to port != 22 block in from port 20:21 block out from any to port 10 <> 100 -pass out from any to port = (3,5,7,9) -block in from port = (20,25) -pass in from any port = (11:12, 21:22) to any port = (1:2, 4:5, 8:9) +pass out from any to port = {3,5,7,9} +block in from port = {20,25} +pass in from any port = {11:12, 21:22} to any port = {1:2, 4:5, 8:9} diff --git a/test/regress/i22 b/test/regress/i22 new file mode 100644 index 0000000000000..1ac8d12ba35fd --- /dev/null +++ b/test/regress/i22 @@ -0,0 +1,5 @@ +pass in exp { "ip.src != 1.1.1.0/24; tcp.dport = 80;" } +pass in exp { "ip.addr = 1.2.3.4,5.6.7.8;" } +block out exp { "ip.dst= 127.0.0.0/8;" } +block in exp { "udp.sport=53;udp.dport=53;" } +pass out exp { "tcp.sport=22; tcp.port=25;" } diff --git a/test/regress/i23 b/test/regress/i23 new file mode 100644 index 0000000000000..792d6005489eb --- /dev/null +++ b/test/regress/i23 @@ -0,0 +1 @@ +# diff --git a/test/regress/i7 b/test/regress/i7 index 1a82940c6c86e..15b88a56dc517 100644 --- a/test/regress/i7 +++ b/test/regress/i7 @@ -7,3 +7,8 @@ block in on lo0 proto tcp from any to any flags 2/18 pass in on lo0 proto tcp from any to any flags 2 block in on lo0 proto tcp from any to any flags /16 pass in on lo0 proto tcp from any to any flags 2/SA +pass in on lo0 proto tcp from any to any flags S/18 +block in on lo0 proto tcp from any to any flags 2/18 +pass in on lo0 proto tcp from any to any flags 2 +block in on lo0 proto tcp from any to any flags /16 +pass in on lo0 proto tcp from any to any flags 2/SA diff --git a/test/regress/i8 b/test/regress/i8 index c30f8bdbd90e5..abf69d9d30bd1 100644 --- a/test/regress/i8 +++ b/test/regress/i8 @@ -11,11 +11,11 @@ pass in proto icmp all icmp-type unreach code host-prohib pass in proto icmp all icmp-type unreach code host-tos pass in proto icmp all icmp-type unreach code host-unk pass in proto icmp all icmp-type unreach code host-unr -pass in proto icmp all icmp-type unreach code (net-unk,net-unr) +pass in proto icmp all icmp-type unreach code {net-unk,net-unr} pass in proto icmp all icmp-type unreach code port-unr pass in proto icmp all icmp-type unreach code proto-unr pass in proto icmp all icmp-type unreach code srcfail -pass in proto icmp all icmp-type (echo,echorep) +pass in proto icmp all icmp-type {echo,echorep} pass in proto icmp all icmp-type inforeq pass in proto icmp all icmp-type inforep pass in proto icmp all icmp-type maskrep @@ -31,3 +31,32 @@ pass in proto icmp all icmp-type timestrep pass in proto icmp all icmp-type timex pass in proto icmp all icmp-type 254 pass in proto icmp all icmp-type 253 code 254 +pass in proto icmp all icmp-type unreach code cutoff-preced +pass in proto icmp all icmp-type unreach code filter-prohib +pass in proto icmp all icmp-type unreach code isolate +pass in proto icmp all icmp-type unreach code needfrag +pass in proto icmp all icmp-type unreach code net-prohib +pass in proto icmp all icmp-type unreach code net-tos +pass in proto icmp all icmp-type unreach code host-preced +pass in proto icmp all icmp-type unreach code host-prohib +pass in proto icmp all icmp-type unreach code host-tos +pass in proto icmp all icmp-type unreach code host-unk +pass in proto icmp all icmp-type unreach code host-unr +pass in proto icmp all icmp-type unreach code {net-unk,net-unr} +pass in proto icmp all icmp-type unreach code port-unr +pass in proto icmp all icmp-type unreach code proto-unr +pass in proto icmp all icmp-type unreach code srcfail +pass in proto icmp all icmp-type {echo,echorep} +pass in proto icmp all icmp-type inforeq +pass in proto icmp all icmp-type inforep +pass in proto icmp all icmp-type maskrep +pass in proto icmp all icmp-type maskreq +pass in proto icmp all icmp-type paramprob +pass in proto icmp all icmp-type redir +pass in proto icmp all icmp-type unreach +pass in proto icmp all icmp-type routerad +pass in proto icmp all icmp-type routersol +pass in proto icmp all icmp-type squench +pass in proto icmp all icmp-type timest +pass in proto icmp all icmp-type timestrep +pass in proto icmp all icmp-type timex diff --git a/test/regress/in100 b/test/regress/in100 new file mode 100644 index 0000000000000..5e2ab6c91730c --- /dev/null +++ b/test/regress/in100 @@ -0,0 +1,3 @@ +rewrite in on bge0 from 1.1.1.1 to 2.2.2.2 -> src 3.3.3.3 dst 4.4.4.4; +rewrite out on bge0 from 1.1.1.1/32 to 2.2.2.2 -> src 3.3.3.0/24 dst 4.4.4.4; +rewrite in on bge0 from 1.1.1.1/32 to 2.2.2.2/32 -> src 3.3.3.0/24 dst 4.4.4.0/24; diff --git a/test/regress/in101 b/test/regress/in101 new file mode 100644 index 0000000000000..afef53bc9ab46 --- /dev/null +++ b/test/regress/in101 @@ -0,0 +1,4 @@ +rewrite in on bge0 proto icmp from 1.1.1.1 to 2.2.2.2 -> src 3.3.3.3 dst 4.4.4.4; +rewrite in on bge0 proto udp from 1.1.1.1 to 2.2.2.2 -> src 3.3.3.3 dst 4.4.4.4; +rewrite out on bge0 proto tcp from 1.1.1.1/32 to 2.2.2.2 -> src 3.3.3.0/24 dst 4.4.4.4; +rewrite in on bge0 proto tcp/udp from 1.1.1.1/32 to 2.2.2.2/32 -> src 3.3.3.0/24,20202 dst 4.4.4.0/24,10101; diff --git a/test/regress/in102 b/test/regress/in102 new file mode 100644 index 0000000000000..57f364566f080 --- /dev/null +++ b/test/regress/in102 @@ -0,0 +1,5 @@ +rewrite in on bge0 proto tcp from any to any -> src 0/0 dst dstlist/a; +rewrite in on bge0 proto tcp from 1.1.1.1 to any -> src 0/0 dst dstlist/bee; +rewrite in on bge0 proto tcp from 1.1.1.1 to 2.2.2.2 -> src 0/0 dst dstlist/cat; +rewrite in on bge0 proto tcp from pool/a to 2.2.2.2 -> src 0/0 dst dstlist/bat; +rewrite in on bge0 proto tcp from pool/a to pool/1 -> src 0/0 dst dstlist/ant; diff --git a/test/regress/in2 b/test/regress/in2 index 83a2ca5acc3cf..58556c0485435 100644 --- a/test/regress/in2 +++ b/test/regress/in2 @@ -67,5 +67,5 @@ rdr ge0 9.8.7.6/32 port 21 -> 1.1.1.1 port 21 tcp proxy ftp rdr le0 9.8.7.6/32 port 1000-2000 -> 1.1.1.1 port 5555 tcp rdr le0 9.8.7.6/32 port 1000-2000 -> 1.1.1.1 port = 5555 tcp rdr le0 0/0 -> test.host.dots -rdr le0 0/0 -> test.host.dots,test.host.dots -rdr adsl0,ppp0 0/0 port 25 -> 127.0.0.1 port 25 +rdr le0 any -> test.host.dots,test.host.dots +rdr adsl0,ppp0 9.8.7.6/32 port 1000-2000 -> 1.1.1.1 port 5555-7777 tcp diff --git a/test/regress/in7 b/test/regress/in7 new file mode 100644 index 0000000000000..792d6005489eb --- /dev/null +++ b/test/regress/in7 @@ -0,0 +1 @@ +# diff --git a/test/regress/ip3 b/test/regress/ip3 new file mode 100644 index 0000000000000..98d2b0b94555e --- /dev/null +++ b/test/regress/ip3 @@ -0,0 +1,14 @@ +pool ipf/dstlist (name fred; policy round-robin;) + { 3.3.3.3; }; +pool ipf/dstlist (name jack; policy weighted connection;) + { 4.4.4.4; bge0:5.5.5.5;}; +pool ipf/dstlist (name jill; policy random;) + { 1.1.1.1; bge0:2.2.2.2;}; +pool nat/hash (name noproxy; size 17;) + { 1.1.1.1; 2.2.2.2;}; +pool nat/tree (name raw;) + { 1.1.1.1; 2.2.2.2;}; +pool all/dstlist (name jill; policy random;) + { 1.1.1.1; bge0:2.2.2.2;}; +pool all/hash (name noproxy; size 17;) + { 1.1.1.1; 2.2.2.2;}; diff --git a/test/regress/ipf6-1 b/test/regress/ipf6-1 deleted file mode 100644 index 814dfd6cd6649..0000000000000 --- a/test/regress/ipf6-1 +++ /dev/null @@ -1,3 +0,0 @@ -block in all -block out all -pass out proto 58 all keep state diff --git a/test/regress/ipv6.4 b/test/regress/ipv6.4 new file mode 100644 index 0000000000000..b2217446d39e7 --- /dev/null +++ b/test/regress/ipv6.4 @@ -0,0 +1,3 @@ +pass in proto ipv6-icmp all icmp-type echo keep frags +pass in proto ipv6-icmp all icmp-type echo keep frags keep state +pass in proto tcp all keep frags keep state diff --git a/test/regress/ipv6.5 b/test/regress/ipv6.5 index ba8cabb501e0e..d9ae23b2fbd77 100644 --- a/test/regress/ipv6.5 +++ b/test/regress/ipv6.5 @@ -1,2 +1,2 @@ -pass out all with v6hdrs routing -block out proto tcp all with v6hdrs routing +pass out family inet6 all with v6hdr routing +block out family inet6 proto tcp all with v6hdr routing diff --git a/test/regress/ipv6.6 b/test/regress/ipv6.6 index f1f904b4eb618..19a4df9723342 100644 --- a/test/regress/ipv6.6 +++ b/test/regress/ipv6.6 @@ -1 +1,2 @@ pass out on gif0 proto udp all keep frag +block out all with bad diff --git a/test/regress/n100 b/test/regress/n100 new file mode 100644 index 0000000000000..a8b6deeb52e3f --- /dev/null +++ b/test/regress/n100 @@ -0,0 +1 @@ +rewrite out on zx0 from 0/0 to 2.2.0.0/16 -> src 4.4.4.4/32 dst 6.6.0.0/16; diff --git a/test/regress/n101 b/test/regress/n101 new file mode 100644 index 0000000000000..2f5fcd98c9cee --- /dev/null +++ b/test/regress/n101 @@ -0,0 +1 @@ +rewrite out on zx0 proto tcp from 0/0 to 2.2.0.0/16 -> src 4.4.4.4/32 dst 6.6.0.0/16; diff --git a/test/regress/n102 b/test/regress/n102 new file mode 100644 index 0000000000000..f056633dd23b2 --- /dev/null +++ b/test/regress/n102 @@ -0,0 +1 @@ +rewrite out on zx0 proto tcp from 0/0 to 2.2.0.0/16 -> src 4.4.4.4/32,1000:2000 dst 6.6.0.0/16; diff --git a/test/regress/n103 b/test/regress/n103 new file mode 100644 index 0000000000000..c3c27d60dd8f1 --- /dev/null +++ b/test/regress/n103 @@ -0,0 +1 @@ +rewrite out on zx0 proto tcp from 0/0 to 2.2.0.0/16 -> src 4.4.4.4/32,1000-1001 dst 6.6.0.0/16,4000:4001; diff --git a/test/regress/n104 b/test/regress/n104 new file mode 100644 index 0000000000000..785f0ada244b6 --- /dev/null +++ b/test/regress/n104 @@ -0,0 +1 @@ +rewrite out on zx0 proto tcp from 0/0 to 2.2.0.0/16 -> src 4.4.0.0/24,1000-1001 dst 6.6.0.0/16,4000:4001; diff --git a/test/regress/n105 b/test/regress/n105 new file mode 100644 index 0000000000000..afe89660a7283 --- /dev/null +++ b/test/regress/n105 @@ -0,0 +1 @@ +rewrite in on zx0 proto tcp from 0/0 to 2.2.0.0/16 port = 80 -> src 4.4.4.4/32,1000-1001 dst 6.6.0.0/16 port = 3128; diff --git a/test/regress/n106 b/test/regress/n106 new file mode 100644 index 0000000000000..6074ab0b4cc4e --- /dev/null +++ b/test/regress/n106 @@ -0,0 +1 @@ +rewrite out on zx0 proto tcp from 0/0 to 2.2.0.0/16 port = 80 -> src 4.4.4.4/32,1000-1001 dst 6.6.0.0/16 port = 3128; diff --git a/test/regress/n10_6 b/test/regress/n10_6 new file mode 100644 index 0000000000000..738152df62ab7 --- /dev/null +++ b/test/regress/n10_6 @@ -0,0 +1,3 @@ +map ppp0 any -> 203.203.203.203/128 mssclamp 100 +map ppp0 any -> 203.203.203.203/128 mssclamp 1000 +map ppp0 any -> 203.203.203.203/128 mssclamp 10000 diff --git a/test/regress/n11_6 b/test/regress/n11_6 new file mode 100644 index 0000000000000..7b428cc23925a --- /dev/null +++ b/test/regress/n11_6 @@ -0,0 +1,3 @@ +bimap zx0 10:1:1::1/128 -> 1::6:7:8/128 +bimap zx0 10:1:1::/112 -> 10::2:2:2/128 +bimap zx0 10:1:1::/112 -> 10::3:4:5/112 diff --git a/test/regress/n12 b/test/regress/n12 index 225675b241da6..933856bc710b1 100644 --- a/test/regress/n12 +++ b/test/regress/n12 @@ -1 +1 @@ -map le0 192.168.126.0/24 -> 0/32 portmap tcp/udp 10000:20000 +map le0 192.168.126.0/24 -> 0/32 portmap tcp/udp 10000:20000 sequential diff --git a/test/regress/n12_6 b/test/regress/n12_6 new file mode 100644 index 0000000000000..bf218489d0511 --- /dev/null +++ b/test/regress/n12_6 @@ -0,0 +1 @@ +map le0 c0a8:7e00::/112 -> 0/128 portmap tcp/udp 10000:20000 diff --git a/test/regress/n13_6 b/test/regress/n13_6 new file mode 100644 index 0000000000000..c1d1646d2ddb5 --- /dev/null +++ b/test/regress/n13_6 @@ -0,0 +1 @@ +map le0 192:168:1::0/48 -> range 203:0:1::1:23-203:0:1::3:45 diff --git a/test/regress/n14_6 b/test/regress/n14_6 new file mode 100644 index 0000000000000..64e88ee4c7fef --- /dev/null +++ b/test/regress/n14_6 @@ -0,0 +1 @@ +rdr gre0 any port 80 -> 10:1:1::254,10:1:1::253 port 80 tcp sticky diff --git a/test/regress/n15 b/test/regress/n15 new file mode 100644 index 0000000000000..062b766c9abad --- /dev/null +++ b/test/regress/n15 @@ -0,0 +1,2 @@ +rdr le0 0/0 port 80 -> 3.3.3.3 port 80 tcp +rdr le0 0/0 port 80 -> 3.3.3.3 port 80-88 tcp diff --git a/test/regress/n15_6 b/test/regress/n15_6 new file mode 100644 index 0000000000000..e82dd82327605 --- /dev/null +++ b/test/regress/n15_6 @@ -0,0 +1,2 @@ +rdr le0 any port 80 -> 3:0:3::3:3 port 80 tcp +rdr le0 any port 80 -> 3:0:3::3:3 port 80-88 tcp diff --git a/test/regress/n16_6 b/test/regress/n16_6 new file mode 100644 index 0000000000000..ff8958cad8693 --- /dev/null +++ b/test/regress/n16_6 @@ -0,0 +1 @@ +rdr vlan0 from any to 69.248.79.193 port = 38136 -> 172.31.83.24 port 2013 udp diff --git a/test/regress/n17 b/test/regress/n17 new file mode 100644 index 0000000000000..213f51f079b54 --- /dev/null +++ b/test/regress/n17 @@ -0,0 +1 @@ +bimap zx0 0/0 -> 1.1.1.3 diff --git a/test/regress/n17_6 b/test/regress/n17_6 new file mode 100644 index 0000000000000..08ef77a488458 --- /dev/null +++ b/test/regress/n17_6 @@ -0,0 +1 @@ +bimap zx0 any -> 1::1:1:3 diff --git a/test/regress/n18 b/test/regress/n18 new file mode 100644 index 0000000000000..792f136b76c1b --- /dev/null +++ b/test/regress/n18 @@ -0,0 +1,3 @@ +map z0 0/0 -> 1.1.1.1/32 portmap tcp/udp 1:4 sequential +map z0 0/0 -> 1.1.1.1/32 portmap tcp/udp 1000:5000 sequential +map z0 0/0 -> 1.1.1.1/32 portmap tcp/udp 1000:50000 sequential diff --git a/test/regress/n1_6 b/test/regress/n1_6 new file mode 100644 index 0000000000000..341f13651b98b --- /dev/null +++ b/test/regress/n1_6 @@ -0,0 +1,3 @@ +map zx0 10:1:1::1/128 -> 10::2:2:2/128 +map zx0 10:1:1::/112 -> 10::3:4:5/128 +map zx0 10:1:1::/112 -> 10::3:4:0/112 diff --git a/test/regress/n2 b/test/regress/n2 index dbce5aa5254a1..39a4d724dedf2 100644 --- a/test/regress/n2 +++ b/test/regress/n2 @@ -1,4 +1,4 @@ -map zx0 10.1.1.1/32 -> 10.2.2.2/32 portmap tcp 10000:20000 -map zx0 10.1.1.0/24 -> 10.3.4.5/32 portmap udp 10000:20000 -map zx0 10.1.0.0/16 -> 10.3.4.0/24 portmap tcp/udp 10000:20000 -map zx0 10.1.1.0/24 -> 10.3.4.5/32 portmap tcp/udp 40000:40001 +map zx0 10.1.1.1/32 -> 10.2.2.2/32 portmap tcp 10000:20000 sequential +map zx0 10.1.1.0/24 -> 10.3.4.5/32 portmap udp 10000:20000 sequential +map zx0 10.1.0.0/16 -> 10.3.4.0/24 portmap tcp/udp 10000:20000 sequential +map zx0 10.1.1.0/24 -> 10.3.4.5/32 portmap tcp/udp 40000:40001 sequential diff --git a/test/regress/n200 b/test/regress/n200 new file mode 100644 index 0000000000000..c792e54067547 --- /dev/null +++ b/test/regress/n200 @@ -0,0 +1 @@ +divert in on bar0 from any to any -> src 127.0.0.1,10101 dst 127.0.0.1,10101 udp; diff --git a/test/regress/n2_6 b/test/regress/n2_6 new file mode 100644 index 0000000000000..3a04f33ae740a --- /dev/null +++ b/test/regress/n2_6 @@ -0,0 +1,4 @@ +map zx0 10:1:1::1/128 -> 10::2:2:2/128 portmap tcp 10000:20000 sequential +map zx0 10:1:1::/112 -> 10::3:4:5/128 portmap udp 10000:20000 sequential +map zx0 10:1::/32 -> 10::3:4:0/112 portmap tcp/udp 10000:20000 sequential +map zx0 10:1:1::/112 -> 10::3:4:5/128 portmap tcp/udp 40000:40001 sequential diff --git a/test/regress/n4_6 b/test/regress/n4_6 new file mode 100644 index 0000000000000..72dad4c112170 --- /dev/null +++ b/test/regress/n4_6 @@ -0,0 +1,6 @@ +rdr zx0 10:1:1::1/128 port 23 -> 10::2:2:1 port 10023 tcp +rdr zx0 10:1:1::/112 port 23 -> 10::2:2:1 port 10023 tcp +rdr zx0 any port 23 -> 10::2:2:1 port 10023 tcp +rdr zx0 10:1:1::/112 port 53 -> 10::2:2:1 port 10053 udp +rdr zx0 10:1:1::/112 port 0 -> 10::2:2:1 port 0 tcp +rdr zx0 10:1:1::/112 port 0 -> 10::2:2:1 port 0 ip diff --git a/test/regress/n5 b/test/regress/n5 index e55cea02a82aa..d9f1a8885f8d8 100644 --- a/test/regress/n5 +++ b/test/regress/n5 @@ -1,6 +1,6 @@ map zx0 10.1.1.1/32 -> 10.2.2.2/32 map zx0 from 10.1.1.0/24 to 10.1.0.0/16 -> 10.3.4.5/32 map zx0 from 10.1.1.0/24 ! to 10.1.0.0/16 -> 10.3.4.0/24 -map zx0 10.1.1.0/24 -> 10.3.4.5/32 portmap udp 10000:20000 -map zx0 10.1.0.0/16 -> 10.3.4.0/24 portmap tcp/udp 10000:20000 -map zx0 10.1.1.0/24 -> 10.3.4.5/32 portmap tcp/udp 40000:40001 +map zx0 10.1.1.0/24 -> 10.3.4.5/32 portmap udp 10000:20000 sequential +map zx0 10.1.0.0/16 -> 10.3.4.0/24 portmap tcp/udp 10000:20000 sequential +map zx0 10.1.1.0/24 -> 10.3.4.5/32 portmap tcp/udp 40000:40001 sequential diff --git a/test/regress/n5_6 b/test/regress/n5_6 new file mode 100644 index 0000000000000..acefd7b18a73f --- /dev/null +++ b/test/regress/n5_6 @@ -0,0 +1,6 @@ +map zx0 10:1:1::1/128 -> 10::2:2:2/128 +map zx0 from 10:1:1::/112 to 10:1::/32 -> 10::3:4:5/128 +map zx0 from 10:1:1::/112 ! to 10:1::/32 -> 10::3:4:0/112 +map zx0 10:1:1::/112 -> 10::3:4:5/128 portmap udp 10000:20000 sequential +map zx0 10:1::/32 -> 10::3:4:0/112 portmap tcp/udp 10000:20000 sequential +map zx0 10:1:1::/112 -> 10::3:4:5/128 portmap tcp/udp 40000:40001 sequential diff --git a/test/regress/n6_6 b/test/regress/n6_6 new file mode 100644 index 0000000000000..3491c6b3e039c --- /dev/null +++ b/test/regress/n6_6 @@ -0,0 +1,5 @@ +rdr zx0 10:1:1::1/128 port 23 -> 10::2:2:1 port 10023 tcp +rdr zx0 from any to 10:1:1::/112 port = 23 -> 10::2:2:1 port 10023 tcp +rdr zx0 from 10::/32 to 10:1:1::/112 port = 23 -> 10::2:2:1 port 10023 tcp +rdr zx0 from 10:3::/32 to 10:1::/32 port = 23 -> 10::2:2:1 port 10023 tcp +rdr zx0 ! from 10::/32 to 10:1:1::/112 port = 53 -> 10::2:2:1 port 10053 udp diff --git a/test/regress/n7_6 b/test/regress/n7_6 new file mode 100644 index 0000000000000..88055f69ab300 --- /dev/null +++ b/test/regress/n7_6 @@ -0,0 +1,3 @@ +rdr zx0 10:1:1::1/128 port 23-79 -> 10::2:2:1 port 10023 tcp +rdr zx0 10:1:1::1/128 port 23-79 -> 10::2:2:1 port = 10023 tcp +rdr zx0 10:1:1::/112 port 80 -> 10::2:2:1,1::2:2:129 port 3128 tcp diff --git a/test/regress/n8_6 b/test/regress/n8_6 new file mode 100644 index 0000000000000..2f96be05d0032 --- /dev/null +++ b/test/regress/n8_6 @@ -0,0 +1 @@ +map icmp0 2::2:2:0/112 -> 10:10:10::/112 diff --git a/test/regress/n9_6 b/test/regress/n9_6 new file mode 100644 index 0000000000000..31e4615f13278 --- /dev/null +++ b/test/regress/n9_6 @@ -0,0 +1 @@ +rdr icmp0 4:4:4::/112 port 0 -> 10:10:10::1 port 0 ip diff --git a/test/regress/ni1.nat b/test/regress/ni1.nat index f38e435bcf7af..077aab1a1f26a 100644 --- a/test/regress/ni1.nat +++ b/test/regress/ni1.nat @@ -1,3 +1,3 @@ -map df0 from 2.2.2.2/32 port 20000 >< 25000 to any -> 6.6.6.8/32 portmap udp 2000:2500 -map df0 from 2.2.2.2/32 port 2000 >< 2500 to any -> 6.6.6.7/32 portmap udp 20000:25000 +map df0 from 2.2.2.2/32 port 20000 >< 25000 to any -> 6.6.6.8/32 portmap udp 2000:2500 sequential +map df0 from 2.2.2.2/32 port 2000 >< 2500 to any -> 6.6.6.7/32 portmap udp 20000:25000 sequential map df0 from 2.2.2.2/32 to any -> 6.6.6.6/32 diff --git a/test/regress/ni13.nat b/test/regress/ni13.nat index 7a879d8cd85a5..ac2be49d61f87 100644 --- a/test/regress/ni13.nat +++ b/test/regress/ni13.nat @@ -1 +1 @@ -rdr pcn1 192.168.113.3/32 port 1723 -> 0.0.0.0 port 1723 proxy pptp +rdr pcn1 192.168.113.3/32 port 1723 -> 0.0.0.0 port 1723 tcp proxy pptp diff --git a/test/regress/ni14.nat b/test/regress/ni14.nat index c546e99029de1..72a8a4a2759e4 100644 --- a/test/regress/ni14.nat +++ b/test/regress/ni14.nat @@ -1 +1 @@ -rdr pcn1 192.168.113.3/32 port 1723 -> 127.0.0.1 port 1723 proxy pptp +rdr pcn1 192.168.113.3/32 port 1723 -> 127.0.0.1 port 1723 tcp proxy pptp diff --git a/test/regress/ni17.ipf b/test/regress/ni17.ipf new file mode 100644 index 0000000000000..e69de29bb2d1d --- /dev/null +++ b/test/regress/ni17.ipf diff --git a/test/regress/ni18.ipf b/test/regress/ni18.ipf new file mode 100644 index 0000000000000..e69de29bb2d1d --- /dev/null +++ b/test/regress/ni18.ipf diff --git a/test/regress/ni18.nat b/test/regress/ni18.nat new file mode 100644 index 0000000000000..40113c1c32c2e --- /dev/null +++ b/test/regress/ni18.nat @@ -0,0 +1,4 @@ +rdr hme0 192.168.1.0/24 port 80 -> 1.1.1.1 port 80 tcp; +no rdr hme0 192.168.1.1 port 80 tcp; +map hme1 10.1.0.0/16 -> 203.1.1.1/32 portmap tcp/udp 10000:20000 +no map hme1 10.1.1.0/24 tcp; diff --git a/test/regress/ni2.nat b/test/regress/ni2.nat index 4ad73c2ed4b8f..43d2c83b0c9be 100644 --- a/test/regress/ni2.nat +++ b/test/regress/ni2.nat @@ -1 +1 @@ -map xl0 10.0.0.0/8 -> 1.1.1.1/32 portmap tcp/udp 40000:60000 +map xl0 10.0.0.0/8 -> 1.1.1.1/32 portmap tcp/udp 40000:60000 sequential diff --git a/test/regress/ni4.nat b/test/regress/ni4.nat index 6eefdc2a988ff..e9d5cc1ce8d35 100644 --- a/test/regress/ni4.nat +++ b/test/regress/ni4.nat @@ -1 +1 @@ -map df0 2.2.2.2/32 -> 6.6.6.6/32 portmap tcp/udp 40000:60000 +map df0 2.2.2.2/32 -> 6.6.6.6/32 portmap tcp/udp 40000:60000 sequential diff --git a/test/regress/p1.pool b/test/regress/p1.pool index 14ae3a3d40dde..aa262a7704ce4 100644 --- a/test/regress/p1.pool +++ b/test/regress/p1.pool @@ -1,2 +1,2 @@ table role = ipf type = tree number = 100 - { 1.1.1.1/32; !2.2.0.0/16; 2.2.2.0/24; }; + { 1.1.1.1/32; !2.2.0.0/16; 2.2.2.0/24; ef00::5/128; }; diff --git a/test/regress/p10.nat b/test/regress/p10.nat new file mode 100644 index 0000000000000..3c3fa7c1874fe --- /dev/null +++ b/test/regress/p10.nat @@ -0,0 +1 @@ +rewrite in on bge0 proto tcp from any to any port = 80 -> src 0/0 dst dstlist/servers; diff --git a/test/regress/p10.pool b/test/regress/p10.pool new file mode 100644 index 0000000000000..2be554aadc823 --- /dev/null +++ b/test/regress/p10.pool @@ -0,0 +1,2 @@ +pool nat/dstlist (name servers; policy hash;) + { 1.1.1.2; 1.1.1.4; 1.1.1.5; 1.1.1.9; }; diff --git a/test/regress/p11.nat b/test/regress/p11.nat new file mode 100644 index 0000000000000..3c3fa7c1874fe --- /dev/null +++ b/test/regress/p11.nat @@ -0,0 +1 @@ +rewrite in on bge0 proto tcp from any to any port = 80 -> src 0/0 dst dstlist/servers; diff --git a/test/regress/p11.pool b/test/regress/p11.pool new file mode 100644 index 0000000000000..a79d9ea580985 --- /dev/null +++ b/test/regress/p11.pool @@ -0,0 +1,2 @@ +pool nat/dstlist (name servers; policy dst-hash;) + { 1.1.1.2; 1.1.1.4; 1.1.1.5; 1.1.1.9; }; diff --git a/test/regress/p12.nat b/test/regress/p12.nat new file mode 100644 index 0000000000000..3c3fa7c1874fe --- /dev/null +++ b/test/regress/p12.nat @@ -0,0 +1 @@ +rewrite in on bge0 proto tcp from any to any port = 80 -> src 0/0 dst dstlist/servers; diff --git a/test/regress/p12.pool b/test/regress/p12.pool new file mode 100644 index 0000000000000..c9afcda840cda --- /dev/null +++ b/test/regress/p12.pool @@ -0,0 +1,2 @@ +pool nat/dstlist (name servers; policy src-hash;) + { 1.1.1.2; 1.1.1.4; 1.1.1.5; 1.1.1.9; }; diff --git a/test/regress/p13.ipf b/test/regress/p13.ipf new file mode 100644 index 0000000000000..acaf639ac1fb0 --- /dev/null +++ b/test/regress/p13.ipf @@ -0,0 +1 @@ +pass in from pool/100 to any diff --git a/test/regress/p13.pool b/test/regress/p13.pool new file mode 100644 index 0000000000000..de80f72d5b8b7 --- /dev/null +++ b/test/regress/p13.pool @@ -0,0 +1,2 @@ +table role = all type = tree number = 100 + { 1.1.1.1/32; !2.2.0.0/16; 2.2.2.0/24; ef00::5/128; }; diff --git a/test/regress/p3.ipf b/test/regress/p3.ipf index aad7cb358b5cf..a598d88168c9d 100644 --- a/test/regress/p3.ipf +++ b/test/regress/p3.ipf @@ -1,5 +1,5 @@ -call now fr_srcgrpmap/1010 in all -call now fr_dstgrpmap/2010 out all +call now srcgrpmap/1010 in all +call now dstgrpmap/2010 out all pass in all group 1020 block in all group 1030 pass out all group 2020 diff --git a/test/regress/p4.nat b/test/regress/p4.nat new file mode 100644 index 0000000000000..d504ac90c4679 --- /dev/null +++ b/test/regress/p4.nat @@ -0,0 +1 @@ +map * from pool/100 to any -> 1.2.3.4/32 diff --git a/test/regress/p4.pool b/test/regress/p4.pool new file mode 100644 index 0000000000000..6ed0e499ac5a3 --- /dev/null +++ b/test/regress/p4.pool @@ -0,0 +1,2 @@ +table role = nat type = tree number = 100 + { 1.1.1.1/32; !2.2.0.0/16; 2.2.2.0/24; }; diff --git a/test/regress/p6.ipf b/test/regress/p6.ipf new file mode 100644 index 0000000000000..b9b89374eede2 --- /dev/null +++ b/test/regress/p6.ipf @@ -0,0 +1 @@ +block in from pool/microsoft to any diff --git a/test/regress/p6.pool b/test/regress/p6.pool new file mode 100644 index 0000000000000..83e818ced5b00 --- /dev/null +++ b/test/regress/p6.pool @@ -0,0 +1 @@ +pool ipf/tree (name microsoft;) { whois file "regress/p6.whois"; }; diff --git a/test/regress/p6.whois b/test/regress/p6.whois new file mode 100644 index 0000000000000..284244e11b8f1 --- /dev/null +++ b/test/regress/p6.whois @@ -0,0 +1,241 @@ +# This query resulted in more than 256 records. Remaining results +# have been truncated. For more specific results, go to +# http://ws.arin.net/whois for help in refining your query. +Microsoft Corp (MSFT) +Microsoft Corp., MSN Operations (MCMO) +MICROSOFT CORPORATION (MICRO-101) +MICROSOFT CORPORATION (MICRO-97) +MICROSOFT CORPORATION (MICRO-100) +Microsoft Corporation (MICRO-111) +MICROSOFT CORPORATION (MICRO-117) +Microsoft Corporation (ZM23-ARIN) noc@microsoft.com +1-425-882-8080 +Microsoft (ZM39-ARIN) noc@microsoft.com +1-425-882-8080 +Microsoft Corp (AS8068) MICROSOFT-CORP---MSN-AS-BLOCK 8068 - 8075 +Microsoft Corp (AS13811) MSLI 13811 +Microsoft Corp (AS14719) MICROSOFT-CORP-BCENTRAL 14719 +Microsoft Corp (AS3598) MICROSOFT-CORP-AS 3598 +Microsoft Corp (AS5761) MICROSOFT-CORP---MSN-AS---SATURN 5761 +Microsoft Corp (AS6182) MICROSOFT-CORP--MSN-AS-4 6182 +Microsoft Corp (AS6194) MICROSOFT-CORP--MSN-AS-3 6194 +Microsoft Corp (AS6291) MICROSOFT-CORP---MSN-AS 6291 +Microsoft Corp (AS13399) MICROSOFT-CORP---MSN-AS-2 13399 +Microsoft Corp (AS23468) MICROSOFT-CORP-XBOX-ONLINE 23468 +Microsoft Corp MICROSOFT (NET-131-107-0-0-1) 131.107.0.0 - 131.107.255.255 +Microsoft Corp MICROSOFT-VEXCEL (NET-192-92-90-0-1) 192.92.90.0 - 192.92.90.255 +Microsoft Corp NETBLK-MSOFT-NET (NET-198-105-232-0-1) 198.105.232.0 - 198.105.235.255 +Microsoft Corp MICROSOFT19-NET58 (NET-204-231-58-0-1) 204.231.58.0 - 204.231.58.255 +Microsoft Corp MICROSOFT15 (NET-204-140-77-0-1) 204.140.77.0 - 204.140.77.255 +Microsoft Corp MICROSOFT16 (NET-204-140-80-0-1) 204.140.80.0 - 204.140.83.255 +Microsoft Corp MICROSOFT-CORP-MSN-1 (NET-199-60-28-0-1) 199.60.28.0 - 199.60.28.255 +Microsoft Corp MICROSOFT-1 (NET-199-103-90-0-1) 199.103.90.0 - 199.103.91.255 +Microsoft Corp MICROSOFT-CORP-MSN-3 (NET-199-103-122-0-1) 199.103.122.0 - 199.103.122.255 +Microsoft Corp MICROSOFT8 (NET-204-79-101-0-1) 204.79.101.0 - 204.79.101.255 +Microsoft Corp MICROSOFT18 (NET-192-237-67-0-1) 192.237.67.0 - 192.237.67.255 +Microsoft Corp MICROSOFT19 (NET-198-137-97-0-1) 198.137.97.0 - 198.137.97.255 +Microsoft Corp MICROSOFT-HK (NET-204-79-135-0-1) 204.79.135.0 - 204.79.135.255 +Microsoft Corp MICROSOFT-PLACEWARE-1 (NET-204-79-179-0-1) 204.79.179.0 - 204.79.179.255 +Microsoft Corp MICROSOFT11 (NET-204-79-180-0-1) 204.79.180.0 - 204.79.181.255 +Microsoft Corp MICROSOFT-PLACEWARE-2 (NET-204-79-188-0-1) 204.79.188.0 - 204.79.188.255 +Microsoft Corp MICROSOFT13 (NET-204-79-195-0-1) 204.79.195.0 - 204.79.197.255 +Microsoft Corp MICROSOFT17 (NET-199-6-92-0-1) 199.6.92.0 - 199.6.94.255 +Microsoft Corp MICROSOFT-2 (NET-204-79-7-0-1) 204.79.7.0 - 204.79.7.255 +Microsoft Corp MICROSOFT-NET1 (NET-204-79-27-0-1) 204.79.27.0 - 204.79.27.255 +Microsoft Corp MICROSOFT2 (NET-198-180-74-0-1) 198.180.74.0 - 198.180.75.255 +Microsoft Corp MICROSOFT3 (NET-198-180-95-0-1) 198.180.95.0 - 198.180.97.255 +Microsoft Corp MICROSOFT28 (NET-204-231-236-0-1) 204.231.236.0 - 204.231.236.255 +Microsoft Corp MICROSOFT29 (NET-205-248-10-0-1) 205.248.10.0 - 205.248.15.255 +Microsoft Corp SPRINT-CDA33F (NET-205-163-63-0-1) 205.163.63.0 - 205.163.63.255 +Microsoft Corp SPRINT-CDA33E (NET-205-163-62-0-1) 205.163.62.0 - 205.163.62.255 +Microsoft Corp SPRINT-CDA39F (NET-205-163-144-0-1) 205.163.144.0 - 205.163.159.255 +Microsoft Corp MICROSOFT30 (NET-205-248-41-0-1) 205.248.41.0 - 205.248.43.255 +Microsoft Corp MICROSOFT31 (NET-205-248-50-0-1) 205.248.50.0 - 205.248.51.255 +Microsoft Corp MICROSOFT32 (NET-205-248-61-0-1) 205.248.61.0 - 205.248.63.255 +Microsoft Corp MICROSOFT34 (NET-205-248-72-0-1) 205.248.72.0 - 205.248.72.255 +Microsoft Corp MICROSOFT35 (NET-205-248-212-0-1) 205.248.212.0 - 205.248.215.255 +Microsoft Corp MICROSOFT36 (NET-205-248-228-0-1) 205.248.228.0 - 205.248.228.255 +Microsoft Corp MICROSOFT37 (NET-205-248-235-0-1) 205.248.235.0 - 205.248.235.255 +Microsoft Corp MICROSOFT20 (NET-204-231-76-0-1) 204.231.76.0 - 204.231.76.255 +Microsoft Corp MICROSOFT26 (NET-204-231-192-0-1) 204.231.192.0 - 204.231.192.255 +Microsoft Corp MICROSOFT27 (NET-204-231-194-0-1) 204.231.194.0 - 204.231.223.255 +Microsoft Corp SOCRATIC (NET-207-78-80-0-1) 207.78.80.0 - 207.78.80.255 +Microsoft Corp DAVELADD (NET-207-78-81-0-1) 207.78.81.0 - 207.78.81.255 +Microsoft Corp RSEGAL (NET-207-78-82-0-1) 207.78.82.0 - 207.78.82.255 +Microsoft Corp MICROSOFT44 (NET-205-248-243-0-1) 205.248.243.0 - 205.248.244.255 +Microsoft Corp MICROSOFT48 (NET-207-117-3-0-1) 207.117.3.0 - 207.117.3.255 +Microsoft Corp UU-207-18-117 (NET-207-18-117-0-1) 207.18.117.0 - 207.18.117.255 +Microsoft Corp CW-208-139-27-B (NET-208-139-27-0-1) 208.139.27.0 - 208.139.27.255 +Microsoft Corp MICROSOFT55 (NET-209-28-213-0-1) 209.28.213.0 - 209.28.213.255 +Microsoft Corp MICROSOFT50 (NET-207-209-68-0-1) 207.209.68.0 - 207.209.68.255 +Microsoft Corp SPRINT-CC5F6F (NET-204-95-96-0-1) 204.95.96.0 - 204.95.111.255 +Microsoft Corp CYBR-LCCLAB (NET-207-158-93-192-1) 207.158.93.192 - 207.158.93.223 +Microsoft Corp MSBPN-2 (NET-207-240-123-192-1) 207.240.123.192 - 207.240.123.223 +Microsoft Corp SPRINT-D01ACD (NET-208-26-205-0-1) 208.26.205.0 - 208.26.205.255 +Microsoft Corp MICROSOFT-CORP-MSN-2 (NET-192-197-157-0-1) 192.197.157.0 - 192.197.157.255 +Microsoft Corp MICROSOFTDENVER (NET-204-133-231-0-1) 204.133.231.0 - 204.133.231.255 +Microsoft Corp MICROSOFTG1-COM (NET-216-72-96-0-1) 216.72.96.0 - 216.72.99.255 +Microsoft Corp EACT-CUST-JLEZNEK (NET-207-229-166-152-1) 207.229.166.152 - 207.229.166.159 +Microsoft Corp SPRINT-CC5F95-8 (NET-204-95-149-0-1) 204.95.149.0 - 204.95.149.255 +Microsoft Corp NET-CSAMSI (NET-209-192-213-72-1) 209.192.213.72 - 209.192.213.79 +Microsoft Corp MICROSOFT57 (NET-206-73-203-0-1) 206.73.203.0 - 206.73.203.255 +Microsoft Corp MICROSOFT56 (NET-206-73-118-0-1) 206.73.118.0 - 206.73.118.255 +Microsoft Corp QWEST-208-45-54-16 (NET-208-45-54-16-1) 208.45.54.16 - 208.45.54.23 +Microsoft Corp QWEST-208-45-54-8 (NET-208-45-54-8-1) 208.45.54.8 - 208.45.54.15 +Microsoft Corp MICROSOFT58 (NET-206-73-31-0-1) 206.73.31.0 - 206.73.31.255 +Microsoft Corp SPRINT-3FA132 (NET-63-161-50-128-1) 63.161.50.128 - 63.161.50.255 +Microsoft Corp SPRINT-3FA132-6 (NET-63-161-50-0-1) 63.161.50.0 - 63.161.50.127 +Microsoft Corp MICROSOFT-8-18 (NET-207-240-8-224-1) 207.240.8.224 - 207.240.8.239 +Microsoft Corp MICROSOFT-BBLK (NET-157-54-0-0-1) 157.54.0.0 - 157.60.255.255 +Microsoft Corp QWEST-208-45-89-248A (NET-208-45-89-248-1) 208.45.89.248 - 208.45.89.255 +Microsoft Corp MICROSOFT61 (NET-206-182-69-0-1) 206.182.69.0 - 206.182.69.255 +Microsoft Corp MICROSOFT63 (NET-206-182-240-0-1) 206.182.240.0 - 206.182.240.255 +Microsoft Corp MICROSOFT64 (NET-206-182-241-0-1) 206.182.241.0 - 206.182.241.255 +Microsoft Corp MICROSOFT59 (NET-206-73-67-0-1) 206.73.67.0 - 206.73.67.255 +Microsoft Corp MICROSOFT66 (NET-206-182-251-0-1) 206.182.251.0 - 206.182.251.255 +Microsoft Corp MICROSOFT65 (NET-206-182-247-0-1) 206.182.247.0 - 206.182.247.255 +Microsoft Corp MICROSOFT62 (NET-206-182-236-0-1) 206.182.236.0 - 206.182.236.255 +Microsoft Corp QWEST-63-236-198-64 (NET-63-236-198-64-1) 63.236.198.64 - 63.236.198.71 +Microsoft Corp QWEST-63-236-198-152 (NET-63-236-198-152-1) 63.236.198.152 - 63.236.198.159 +Microsoft Corp ERMS-6799349 (NET-165-121-253-232-1) 165.121.253.232 - 165.121.253.239 +Microsoft Corp QWEST-63-236-170-64 (NET-63-236-170-64-1) 63.236.170.64 - 63.236.170.71 +Microsoft Corp QWEST-63-236-186-64 (NET-63-236-186-64-1) 63.236.186.64 - 63.236.186.71 +Microsoft Corp QWEST-63-236-187-104 (NET-63-236-187-104-1) 63.236.187.104 - 63.236.187.111 +Microsoft Corp QWEST-63-236-187-128 (NET-63-236-187-128-1) 63.236.187.128 - 63.236.187.135 +Microsoft Corp QWEST-63-236-187-160 (NET-63-236-187-160-1) 63.236.187.160 - 63.236.187.167 +Microsoft Corp FON-3338832128690 (NET-199-2-137-0-1) 199.2.137.0 - 199.2.137.255 +Microsoft Corp CUST-86-24614 (NET-216-222-104-224-1) 216.222.104.224 - 216.222.104.239 +Microsoft Corp QWEST-63-151-87-64 (NET-63-151-87-64-1) 63.151.87.64 - 63.151.87.71 +Microsoft Corp HP-64-77-82-96 (NET-64-77-82-96-1) 64.77.82.96 - 64.77.82.103 +Microsoft Corp HP-64-77-93-80 (NET-64-77-93-80-1) 64.77.93.80 - 64.77.93.95 +Microsoft Corp MICROSOFT-1BLK (NET-65-52-0-0-1) 65.52.0.0 - 65.55.255.255 +Microsoft Corp MICROSOFT-GLOBAL-NET (NET-207-46-0-0-1) 207.46.0.0 - 207.46.255.255 +Microsoft Corp MICROSOFT-CORP-MSN-BLK (NET-207-68-128-0-1) 207.68.128.0 - 207.68.207.255 +Microsoft Corp FON-343451648081865 (NET-204-182-144-0-1) 204.182.144.0 - 204.182.159.255 +Microsoft Corp FON-346312755281299 (NET-206-107-34-0-1) 206.107.34.0 - 206.107.34.255 +Microsoft Corp FON-34550983681918 (NET-205-240-158-0-1) 205.240.158.0 - 205.240.159.255 +Microsoft Corp MICROSOFT-PLACEWARE-2 (NET-204-79-252-0-1) 204.79.252.0 - 204.79.252.255 +Microsoft Corp WLCO-TWC1057147-MICROSOFT (NET-64-200-211-16-1) 64.200.211.16 - 64.200.211.31 +Microsoft Corp MICROSOF81-163-0 (NET-12-178-163-0-1) 12.178.163.0 - 12.178.163.31 +Microsoft Corp WLCO-TWC1057147-MICROSOFT-1 (NET-69-44-126-80-1) 69.44.126.80 - 69.44.126.95 +Microsoft Corp SPRINTLINK (NET-63-173-42-128-1) 63.173.42.128 - 63.173.42.255 +Microsoft Corp MICROSOF33-108-0 (NET-12-28-108-0-1) 12.28.108.0 - 12.28.108.127 +Microsoft Corp SPRINTLINK (NET-65-170-29-0-1) 65.170.29.0 - 65.170.29.7 +Microsoft Corp Q0903-67-132-133-96 (NET-67-132-133-96-1) 67.132.133.96 - 67.132.133.103 +Microsoft Corp MICROSOFT-IPV6-BLK (NET6-2001-4898-1) 2001:4898:0000:0000:0000:0000:0000:0000 - 2001:4898:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF +Microsoft Corp LVLT-MSFT-8-6-176 (NET-8-6-176-0-1) 8.6.176.0 - 8.6.176.255 +Microsoft Corp MICROSOFT33 (NET-205-248-80-0-1) 205.248.80.0 - 205.248.129.255 +Microsoft Corp Q0523-63-148-123-240 (NET-63-148-123-240-1) 63.148.123.240 - 63.148.123.247 +Microsoft Corp SAVV-S233608-1 (NET-64-41-193-0-1) 64.41.193.0 - 64.41.193.255 +Microsoft Corp SAVV-S233053-1 (NET-64-85-70-32-1) 64.85.70.32 - 64.85.70.47 +Microsoft Corp SAVV-S233053-2 (NET-64-85-81-96-1) 64.85.81.96 - 64.85.81.103 +Microsoft Corp SAVV-S233053-3 (NET-64-85-81-104-1) 64.85.81.104 - 64.85.81.111 +Microsoft Corp SAVV-S233053-7 (NET-216-32-168-224-1) 216.32.168.224 - 216.32.168.255 +Microsoft Corp SAVV-S233053-6 (NET-206-79-74-32-1) 206.79.74.32 - 206.79.74.47 +Microsoft Corp SAVV-S233053-8 (NET-216-32-175-224-1) 216.32.175.224 - 216.32.175.255 +Microsoft Corp SAVV-S233053-9 (NET-216-32-180-0-1) 216.32.180.0 - 216.32.183.255 +Microsoft Corp SAVV-S233053-11 (NET-216-33-229-224-1) 216.33.229.224 - 216.33.229.255 +Microsoft Corp SAVV-S233053-12 (NET-216-33-236-0-1) 216.33.236.0 - 216.33.239.255 +Microsoft Corp SAVV-S233053-13 (NET-216-33-240-0-1) 216.33.240.0 - 216.33.243.255 +Microsoft Corp SAVV-S233053-10 (NET-216-32-240-0-1) 216.32.240.0 - 216.32.243.255 +Microsoft Corp SAVV-S233608-3 (NET-216-34-51-0-1) 216.34.51.0 - 216.34.51.255 +Microsoft Corp SAVV-S233053-4 (NET-209-1-112-0-1) 209.1.112.0 - 209.1.112.255 +Microsoft Corp SAVV-S233053-5 (NET-209-1-113-0-1) 209.1.113.0 - 209.1.113.255 +Microsoft Corp SAVV-S233608-2 (NET-209-1-15-0-1) 209.1.15.0 - 209.1.15.255 +Microsoft Corp SAVV-S233608-4 (NET-216-34-53-176-1) 216.34.53.176 - 216.34.53.191 +Microsoft Corp SAVV-S233608-5 (NET-216-35-8-224-1) 216.35.8.224 - 216.35.8.239 +Microsoft Corp SAVV-S233053-14 (NET-209-185-128-0-1) 209.185.128.0 - 209.185.131.255 +Microsoft Corp Q0112-65-114-175-128 (NET-65-114-175-128-1) 65.114.175.128 - 65.114.175.159 +Microsoft Corp SAVV-S233053-15 (NET-64-15-229-96-1) 64.15.229.96 - 64.15.229.127 +Microsoft Corp SAVV-S233050-5 (NET-64-15-177-0-1) 64.15.177.0 - 64.15.177.255 +Microsoft Corp SAVV-S233050-4 (NET-64-15-170-192-1) 64.15.170.192 - 64.15.170.199 +Microsoft Corp SAVV-S233050-2 (NET-209-143-238-0-1) 209.143.238.0 - 209.143.238.255 +Microsoft Corp SAVV-S233050-6 (NET-64-15-178-0-1) 64.15.178.0 - 64.15.178.255 +Microsoft Corp SAVV-S232995-2 (NET-66-35-209-120-1) 66.35.209.120 - 66.35.209.127 +Microsoft Corp SAVV-S232995-3 (NET-66-35-211-128-1) 66.35.211.128 - 66.35.211.191 +Microsoft Corp SAVV-S232995-1 (NET-66-35-208-48-1) 66.35.208.48 - 66.35.208.63 +Microsoft Corp SAVV-S233053-16 (NET-216-33-148-0-1) 216.33.148.0 - 216.33.151.255 +Microsoft Corp., MSN Operations SAVV-S233052-4 (NET-216-35-66-88-1) 216.35.66.88 - 216.35.66.95 +MICROSOFT CORPORATION MICROSOF32-32-160 (NET-12-230-32-160-1) 12.230.32.160 - 12.230.32.167 +MICROSOFT CORPORATION MICROSOF43-124-0 (NET-12-53-124-0-1) 12.53.124.0 - 12.53.124.31 +MICROSOFT CORPORATION MICROSOF82-18-96 (NET-12-232-18-96-1) 12.232.18.96 - 12.232.18.127 +MICROSOFT CORPORATION MICROSOF25-158 (NET-12-190-158-0-1) 12.190.158.0 - 12.190.158.255 +MICROSOFT CORPORATION MICROSOF61-196-32 (NET-12-71-196-32-1) 12.71.196.32 - 12.71.196.47 +Microsoft Corporation MICROSOFT-ONLINE-SERVICES (NET-209-240-192-0-1) 209.240.192.0 - 209.240.223.255 +Microsoft Corporation MICROSOFT-DYNAMIC-HOSTING (NET-70-37-0-0-1) 70.37.0.0 - 70.37.191.255 +Microsoft Corporation MS-ONLINE-SERVICES-NJ (NET-70-37-128-0-1) 70.37.128.0 - 70.37.129.255 +Microsoft Corporation MS-GLOBAL-ONLINE-SERVICES (NET-70-37-135-0-1) 70.37.135.0 - 70.37.135.255 +MICROSOFT CORPORATION MICROSOF82-87-192 (NET-12-49-87-192-1) 12.49.87.192 - 12.49.87.255 +Microsoft MICROSOFT (NET-74-93-205-144-1) 74.93.205.144 - 74.93.205.151 +Microsoft MICROSOFT (NET-74-93-205-152-1) 74.93.205.152 - 74.93.205.159 +Microsoft MICROSOFT (NET-74-93-206-64-1) 74.93.206.64 - 74.93.206.71 +Microsoft MICROSOFT (NET-70-89-139-120-1) 70.89.139.120 - 70.89.139.127 +Microsoft DIRECP-NET1-206-71-11 (NET-206-71-119-0-1) 206.71.119.0 - 206.71.119.255 +Microsoft DIRECP-NET1-117 (NET-206-71-117-0-1) 206.71.117.0 - 206.71.117.255 +Microsoft DIRECP-NET1-118 (NET-206-71-118-0-1) 206.71.118.0 - 206.71.118.255 +Microsoft UUHIL-BLK1-C155-112 (NET-209-154-155-112-1) 209.154.155.112 - 209.154.155.119 +Microsoft SBCIS-101411-164355 (NET-65-68-62-152-1) 65.68.62.152 - 65.68.62.159 +MICROSOFT SBC067039208168020503 (NET-67-39-208-168-1) 67.39.208.168 - 67.39.208.175 +Microsoft UU-65-242-67 (NET-65-242-67-0-1) 65.242.67.0 - 65.242.67.255 +Microsoft CW-204-71-191-0 (NET-204-71-191-0-1) 204.71.191.0 - 204.71.191.255 +Microsoft SBC063194155144021023 (NET-63-194-155-144-1) 63.194.155.144 - 63.194.155.151 +Microsoft SBC066136085192030113 (NET-66-136-85-192-1) 66.136.85.192 - 66.136.85.199 +MICROSOFT MFN-T280-64-124-184-72-29 (NET-64-124-184-72-1) 64.124.184.72 - 64.124.184.79 +MICROSOFT MFN-T133-216-200-206-0-24 (NET-216-200-206-0-1) 216.200.206.0 - 216.200.206.255 +Microsoft UU-63-80-93-D4 (NET-63-80-93-0-1) 63.80.93.0 - 63.80.93.127 +Microsoft RSPC-1218167167199384 (NET-67-192-225-208-1) 67.192.225.208 - 67.192.225.223 +Microsoft CVNET-454AA20 (NET-69-74-162-0-1) 69.74.162.0 - 69.74.162.255 +Microsoft UU-65-221-5 (NET-65-221-5-0-1) 65.221.5.0 - 65.221.5.255 +Microsoft - Partner Campaign Builder (PCB) MICROSOFT-PARTNER-CAMPAIGN-BUILDER-PCB (NET-216-182-89-192-1) 216.182.89.192 - 216.182.89.207 +Microsoft - Partner Campaign Builder (PCB) MICROSOFT-PARTNER-CAMPAIGN-BUILDER-PCB (NET-216-182-89-48-1) 216.182.89.48 - 216.182.89.63 +MICROSOFT AUSTIN-STO UU-65-248-85-D4 (NET-65-248-85-0-1) 65.248.85.0 - 65.248.85.255 +Microsoft Canada MIC0923-CA (NET-199-243-157-192-1) 199.243.157.192 - 199.243.157.223 +Microsoft Canada MIC0702-CA (NET-199-243-157-112-1) 199.243.157.112 - 199.243.157.119 +Microsoft Corp UU-65-194-210-224 (NET-65-194-210-224-1) 65.194.210.224 - 65.194.210.255 +Microsoft Corp UU-208-194-139 (NET-208-194-139-0-1) 208.194.139.0 - 208.194.139.255 +Microsoft Corp UU-208-204-49-128-B (NET-208-204-49-128-1) 208.204.49.128 - 208.204.49.255 +Microsoft Corp UU-208-205-26 (NET-208-205-26-0-1) 208.205.26.0 - 208.205.26.255 +Microsoft Corp UU-208-217-184-D1 (NET-208-217-184-0-1) 208.217.184.0 - 208.217.187.255 +Microsoft Corp UU-208-222-172 (NET-208-222-172-0-1) 208.222.172.0 - 208.222.172.255 +Microsoft Corp UU-208-224-200-64 (NET-208-224-200-64-1) 208.224.200.64 - 208.224.200.95 +Microsoft Corp UU-208-229-100-D1 (NET-208-229-100-0-1) 208.229.100.0 - 208.229.101.255 +Microsoft Corp UU-208-241-19 (NET-208-241-19-0-1) 208.241.19.0 - 208.241.19.15 +Microsoft Corp UU-208-241-19-16 (NET-208-241-19-16-1) 208.241.19.16 - 208.241.19.31 +Microsoft Corp UU-208-241-9-224 (NET-208-241-9-224-1) 208.241.9.224 - 208.241.9.239 +Microsoft Corp UU-208-244-108-D2 (NET-208-244-108-0-1) 208.244.108.0 - 208.244.108.15 +Microsoft Corp UU-208-245-16 (NET-208-245-16-0-1) 208.245.16.0 - 208.245.16.31 +Microsoft Corp UU-208-249-17-160 (NET-208-249-17-160-1) 208.249.17.160 - 208.249.17.175 +Microsoft Corp UU-63-104-216-D2 (NET-63-104-216-0-1) 63.104.216.0 - 63.104.216.127 +Microsoft Corp UU-63-69-245 (NET-63-69-245-0-1) 63.69.245.0 - 63.69.245.255 +Microsoft Corp SBC068090141072031030 (NET-68-90-141-72-1) 68.90.141.72 - 68.90.141.79 +Microsoft Corp 10825385 SBC06319812316029040317151513 (NET-63-198-123-160-1) 63.198.123.160 - 63.198.123.167 +MICROSOFT CORP-040821020257 SBC06824804806429040821020303 (NET-68-248-48-64-1) 68.248.48.64 - 68.248.48.71 +MICROSOFT CORP-040821020338 SBC06824804807229040821020347 (NET-68-248-48-72-1) 68.248.48.72 - 68.248.48.79 +MICROSOFT CORP-081024181821 SBC-99-49-8-248-29-0810241850 (NET-99-49-8-248-1) 99.49.8.248 - 99.49.8.255 +Microsoft Corp. HUGE-65-38-172-72-29 (NET-65-38-172-72-1) 65.38.172.72 - 65.38.172.79 +Microsoft Corp. HUGE-65-38-172-96-28 (NET-65-38-172-96-1) 65.38.172.96 - 65.38.172.111 +Microsoft Corporation MICROSOFT-CORPORATION (NET-75-149-174-16-1) 75.149.174.16 - 75.149.174.23 +Microsoft Corporation MICROSOFT-CORPORATION (NET-75-151-100-240-1) 75.151.100.240 - 75.151.100.255 +Microsoft Corporation SPEK-647057-0 (NET-64-81-8-96-1) 64.81.8.96 - 64.81.8.127 +Microsoft Corporation SBC067112255144030130 (NET-67-112-255-144-1) 67.112.255.144 - 67.112.255.151 +Microsoft Corporation ATTENS-010075-004522 (NET-63-240-201-176-1) 63.240.201.176 - 63.240.201.191 +Microsoft Corporation ATTENS-010075-004523 (NET-206-16-209-208-1) 206.16.209.208 - 206.16.209.223 +Microsoft Corporation ATTENS-010075-004525 (NET-63-240-195-208-1) 63.240.195.208 - 63.240.195.223 +Microsoft Corporation ATTENS-010075-004526 (NET-206-16-204-64-1) 206.16.204.64 - 206.16.204.79 +Microsoft Corporation ATTENS-010075-004450 (NET-206-16-223-0-1) 206.16.223.0 - 206.16.223.255 +Microsoft Corporation ATTENS-010075-005028 (NET-63-240-216-0-1) 63.240.216.0 - 63.240.219.255 +Microsoft Corporation ATTENS-010075-005057 (NET-63-240-220-0-1) 63.240.220.0 - 63.240.223.255 +Microsoft Corporation ATTENS-010075-005135 (NET-206-16-246-24-1) 206.16.246.24 - 206.16.246.31 +Microsoft Corporation ATTENS-010075-004524 (NET-63-240-195-192-1) 63.240.195.192 - 63.240.195.207 +Microsoft Corporation ATTENS-010075-005880 (NET-206-16-224-160-1) 206.16.224.160 - 206.16.224.191 +Microsoft Corporation (managed segment) RSPC-1229444888833780 (NET-98-129-187-144-1) 98.129.187.144 - 98.129.187.151 +Microsoft Corporation - Secure Dimensions ( RSPC-33955-12072007 (NET-67-192-39-48-1) 67.192.39.48 - 67.192.39.63 +Microsoft Corporation - Whale RSPC-108457-1170047010 (NET-72-32-240-160-1) 72.32.240.160 - 72.32.240.175 +Microsoft Corporation - Whale RSPC-108456-1173386392 (NET-72-32-201-152-1) 72.32.201.152 - 72.32.201.159 +MICROSOFT CROP SBC067039081152020503 (NET-67-39-81-152-1) 67.39.81.152 - 67.39.81.159 +Microsoft Education Programs RSPC-48725-1096578571 (NET-69-20-127-32-1) 69.20.127.32 - 69.20.127.39 +Microsoft License PNAP-SFJ-MSLI-RM-01 (NET-216-52-28-0-1) 216.52.28.0 - 216.52.28.255 +Microsoft License INAP-PHX003-MSLICENSE-25271 (NET-70-42-230-0-1) 70.42.230.0 - 70.42.231.255 +Microsoft License INAP-SFJ-MSLICENSE-13982 (NET-63-251-97-0-1) 63.251.97.0 - 63.251.97.255 +Microsoft Licensing SBC067120132128020815 (NET-67-120-132-128-1) 67.120.132.128 - 67.120.132.135 +Microsoft Licensing SBC067120132152020815 (NET-67-120-132-152-1) 67.120.132.152 - 67.120.132.159 +Microsoft Licensing SBC067120132192020816 (NET-67-120-132-192-1) 67.120.132.192 - 67.120.132.207 +Microsoft Licensing SBC0671201322080208 diff --git a/test/regress/p7.nat b/test/regress/p7.nat new file mode 100644 index 0000000000000..3c3fa7c1874fe --- /dev/null +++ b/test/regress/p7.nat @@ -0,0 +1 @@ +rewrite in on bge0 proto tcp from any to any port = 80 -> src 0/0 dst dstlist/servers; diff --git a/test/regress/p7.pool b/test/regress/p7.pool new file mode 100644 index 0000000000000..451b374dfd1f5 --- /dev/null +++ b/test/regress/p7.pool @@ -0,0 +1,2 @@ +pool nat/dstlist (name servers; policy weighted connection;) + { 1.1.1.2; 1.1.1.4; 1.1.1.5; 1.1.1.9; }; diff --git a/test/regress/p9.nat b/test/regress/p9.nat new file mode 100644 index 0000000000000..3c3fa7c1874fe --- /dev/null +++ b/test/regress/p9.nat @@ -0,0 +1 @@ +rewrite in on bge0 proto tcp from any to any port = 80 -> src 0/0 dst dstlist/servers; diff --git a/test/regress/p9.pool b/test/regress/p9.pool new file mode 100644 index 0000000000000..c452ffc681b6b --- /dev/null +++ b/test/regress/p9.pool @@ -0,0 +1,2 @@ +pool nat/dstlist (name servers; policy round-robin;) + { 1.1.1.2; 1.1.1.4; 1.1.1.5; 1.1.1.9; }; diff --git a/test/test.format b/test/test.format index dfc3f35b619a2..64f7d9b3202cb 100644 --- a/test/test.format +++ b/test/test.format @@ -1,6 +1,6 @@ -#test input-format output-format +#test input-format output-format options bpf-f1 text text -bpf1 text ipf +bpf1 text text f1 text text f2 text text f3 text text @@ -18,9 +18,11 @@ f14 text text f15 text text f16 text text f17 hex hex -f18 text text -f19 text text fr_statemax=3 +f18 text text -D +f19 text text state_max=3 f20 text text +f21 hex text +f22 hex text i1 text ipf i2 text ipf i3 text ipf @@ -42,17 +44,26 @@ i18 text ipf i19 text ipf i20 text ipf i21 text ipf +i22 text ipf +i23 text ipf in1 text text in2 text text in3 text text in4 text text in5 text text in6 text text +in7 text text +in8 text text +in100 text text +in101 text text +in102 text text ip1 text text ip2 text text +ip3 text text ipv6.1 hex hex ipv6.2 hex hex ipv6.3 hex hex +ipv6.4 hex hex ipv6.5 hex hex l1 hex hex n1 text text @@ -62,31 +73,40 @@ n4 text text n5 text text n6 text text n7 text text -n8 hex hex fr_update_ipid=0 -n9 hex hex fr_update_ipid=0 -n10 hex hex fr_update_ipid=0 +n8 hex hex update_ipid=0 +n9 hex hex update_ipid=0 +n10 hex hex update_ipid=0 n11 text text -n12 hex hex fr_update_ipid=0 -n13 text text -n14 text text -ni1 hex hex fr_update_ipid=1 -ni2 hex hex fr_update_ipid=1 -ni3 hex hex fr_update_ipid=1 -ni4 hex hex fr_update_ipid=1 -ni5 hex hex fr_update_ipid=1 -ni6 hex hex fr_update_ipid=1 -ni7 hex hex fr_update_ipid=1 -ni8 hex hex fr_update_ipid=1 -ni9 hex hex fr_update_ipid=1 -ni10 hex hex fr_update_ipid=1 -ni11 hex hex fr_update_ipid=1 -ni12 hex hex fr_update_ipid=1 -ni13 hex hex fr_update_ipid=1 -ni14 hex hex fr_update_ipid=1 -ni15 hex hex fr_update_ipid=1 -ni16 hex hex fr_update_ipid=1 -ni19 hex hex fr_update_ipid=0 -ni20 hex hex fr_update_ipid=0 +n12 hex hex update_ipid=0 -v +n15 text text update_ipid=0 +n100 text text +n101 text text +n102 text text +n103 text text +n104 hex hex update_ipid=0 +n105 hex hex update_ipid=0 +n106 hex hex update_ipid=0 +n200 hex hex update_ipid=0 +ni1 hex hex update_ipid=1 +ni2 hex hex update_ipid=1 +ni3 hex hex update_ipid=1 +ni4 hex hex update_ipid=1 +ni5 hex hex update_ipid=1 +ni6 hex text update_ipid=1 -D +ni7 hex hex update_ipid=1 +ni8 hex hex update_ipid=1 +ni9 hex hex update_ipid=1 +ni10 hex hex update_ipid=1 +ni11 hex hex update_ipid=1 +ni12 hex hex update_ipid=1 +ni13 hex hex update_ipid=1 +ni14 hex hex update_ipid=1 +ni15 hex hex update_ipid=1 +ni16 hex hex update_ipid=1 +ni17 text text +ni18 text text +ni19 hex hex update_ipid=0 +ni20 hex hex update_ipid=0 -D ni21 text text ni23 text text -D p1 text text @@ -94,6 +114,35 @@ p2 text text p3 text text p4 text text p5 text text +p6 text text +p7 text text +p9 text text +p10 text text +p11 text text +p12 text text +p13 text text n16 hex hex -D +n17 hex hex -D f24 hex text ipv6.6 hex text +f25 hex text -D +f26 text text +f27 hex text +n1_6 text text -6 +n2_6 text text -6 +n4_6 text text -6 +n5_6 text text -6 +n6_6 text text -6 +n7_6 text text -6 +n8_6 hex hex -6D +n9_6 hex hex -6D +n11_6 text text -6 +n12_6 hex hex -D6 +n15_6 text text -6 +n17_6 hex hex -6 +n13 text text +n14 text text +n18 text text -D +f28 text text +f29 text text +f30 text text diff --git a/test/test.sed b/test/test.sed deleted file mode 100644 index 3ce0cb16415e8..0000000000000 --- a/test/test.sed +++ /dev/null @@ -1,6 +0,0 @@ - Ç. Ä..0þCVSGexpected0ÇinputDG$regress - -.cvsignore -!Makefile -"dotest -#hextest diff --git a/test/vfycksum.pl b/test/vfycksum.pl index b3a20be0cf24f..0272e4b867ce8 100755 --- a/test/vfycksum.pl +++ b/test/vfycksum.pl @@ -19,82 +19,71 @@ sub dosum { local($lsum) = $seed; for ($idx = $start, $lsum = $seed; $idx < $max; $idx++) { +#printf "%#x += %#x\n", $lsum, $bytes[$idx]; $lsum += $bytes[$idx]; } - $lsum = ($lsum & 0xffff) + ($lsum >> 16); + while ($lsum > 0xffff) { + $lsum = ($lsum & 0xffff) + ($lsum >> 16); + } $lsum = ~$lsum & 0xffff; return $lsum; } -sub ipv4check { - local($base) = $_[0]; - $hl = $bytes[$base] / 256; - return if (($hl >> 4) != 4); # IPv4 ? - $hl &= 0xf; - $hl <<= 1; # get the header length in 16bit words - $hs = &dosum(0, $base, $base + $hl); - $osum = $bytes[$base + 5]; +sub ipv4addrsum { + local($b) = $_[0]; + local($as) = 0; - if ($hs != 0) { - $bytes[$base + 5] = 0; - $hs2 = &dosum(0, $base, $base + $hl); - $bytes[$base + 5] = $osum; - printf " IP: ($hl,%x) %x != %x", $hs, $osum, $hs2; - } else { - print " IP($base): ok "; - } - - # - # Recognise TCP & UDP and calculate checksums for each of these. - # - if (($bytes[$base + 4] & 0xff) == 6) { - &tcpcheck($base); - } - - if (($bytes[$base + 4] & 0xff) == 17) { - &udpcheck($base); - } + $as += $bytes[$b + 6]; # source address + $as += $bytes[$b + 7]; + $as += $bytes[$b + 8]; # destination address + $as += $bytes[$b + 9]; + return ($as); +} - if (($bytes[$base + 4] & 0xff) == 1) { - &icmpcheck($base); - } - if ($base == 0) { - print "\n"; - } +sub ipv6addrsum { + local($b) = $_[0]; + local($as) = 0; + + $as += $bytes[$b + 4]; # source address + $as += $bytes[$b + 5]; + $as += $bytes[$b + 6]; + $as += $bytes[$b + 7]; + $as += $bytes[$b + 8]; + $as += $bytes[$b + 9]; + $as += $bytes[$b + 10]; + $as += $bytes[$b + 11]; + $as += $bytes[$b + 12]; # destination address + $as += $bytes[$b + 13]; + $as += $bytes[$b + 14]; + $as += $bytes[$b + 15]; + $as += $bytes[$b + 16]; + $as += $bytes[$b + 17]; + $as += $bytes[$b + 18]; + $as += $bytes[$b + 19]; + return ($as); } -sub tcpcheck { +sub tcpcommon { local($base) = $_[0]; - local($hl) = $bytes[$base] / 256; - return if (($hl >> 4) != 4); - return if ($bytes[$base + 3] & 0x1fff); - $hl &= 0xf; - $hl <<= 1; + local($hl) = $_[1]; + local($hs) = $_[2]; + local($lenoffset) = $_[3]; - local($hs2); - local($hs) = 6; # TCP - local($len) = $bytes[$base + 1] - ($hl << 1); - $hs += $len; - $hs += $bytes[$base + 6]; # source address - $hs += $bytes[$base + 7]; - $hs += $bytes[$base + 8]; # destination address - $hs += $bytes[$base + 9]; - local($tcpsum) = $hs; - - local($thl) = $bytes[$base + $hl + 6] >> 8; + local($thl) = $bytes[$base + $hl + 6]; $thl &= 0xf0; $thl >>= 2; - $x = $bytes[$base + 1]; - $y = ($cnt - $base) * 2; - $z = 0; - if ($bytes[$base + 1] > ($cnt - $base) * 2) { + local($x) = $bytes[$base + $lenoffset]; + local($y) = ($cnt - $base) * 2; + local($z) = 0; + + if ($bytes[$base + $lenoffset] > ($cnt - $base) * 2) { print "[cnt=$cnt base=$base]"; - $x = $bytes[$base + 1]; + $x = $bytes[$base + $lenoffset]; $y = ($cnt - $base) * 2; $z = 1; - } elsif (($cnt - $base) * 2 < $hl + 20) { + } elsif (($cnt - $base) * 2 < $hl + $hl) { $x = ($cnt - $base) * 2; $y = $hl + 20; $z = 2; @@ -106,6 +95,10 @@ sub tcpcheck { $x = ($cnt - $base) * 2; $y = $len; $z = 4; + } elsif (($cnt - $base) * 2 < 20) { + $x = ($cnt - $base) * 2; + $y = $len; + $z = 5; } if ($z) { @@ -115,11 +108,11 @@ sub tcpcheck { } local($tcpat) = $base + $hl; - $hs = &dosum($tcpsum, $tcpat, $cnt); + $hs = &dosum($_[2], $tcpat, $cnt); if ($hs != 0) { local($osum) = $bytes[$tcpat + 8]; $bytes[$base + $hl + 8] = 0; - $hs2 = &dosum($tcpsum, $tcpat, $cnt); + local($hs2) = &dosum($_[2], $tcpat, $cnt); $bytes[$tcpat + 8] = $osum; printf " TCP: (%x) %x != %x", $hs, $osum, $hs2; } else { @@ -127,23 +120,10 @@ sub tcpcheck { } } -sub udpcheck { +sub udpcommon { local($base) = $_[0]; - local($hl) = $bytes[0] / 256; - return if (($hl >> 4) != 4); - return if ($bytes[3] & 0x1fff); - $hl &= 0xf; - $hl <<= 1; - - local($hs2); - local($hs) = 17; # UDP - local($len) = $bytes[$base + 1] - ($hl << 1); - $hs += $len; - $hs += $bytes[$base + 6]; # source address - $hs += $bytes[$base + 7]; - $hs += $bytes[$base + 8]; # destination address - $hs += $bytes[$base + 9]; - local($udpsum) = $hs; + local($hl) = $_[1]; + local($hs) = $_[2]; if ($bytes[$base + 1] > ($cnt - $base) * 2) { print " UDP: missing data(1)"; @@ -168,7 +148,7 @@ sub udpcheck { printf " UDP: => %x", $hs; } elsif ($hs != 0) { $bytes[$udpat + 3] = 0; - $hs2 = &dosum($udpsum, $udpat, $cnt); + local($hs2) = &dosum($udpsum, $udpat, $cnt); $bytes[$udpat + 3] = $osum; printf " UDP: (%x) %x != %x", $hs, $osum, $hs2; } else { @@ -176,6 +156,156 @@ sub udpcheck { } } +sub ipv6check { + local($base) = $_[0]; + $hl = $bytes[$base] / 256; + return if (($hl >> 4) != 6); # IPv4 ? + $hl = 40; + + print " IPv6($base): ok "; + + if (($bytes[$base + 3] >> 8) == 6) { + &tcpcheck6($base); + } elsif (($bytes[$base + 3] >> 8) == 58) { + &icmpcheck6($base); + } + print "\n"; +} + +sub tcpcheck6 { + local($base) = $_[0]; + local($hl) = $bytes[$base] / 256; + return if (($hl >> 4) != 6); + $hl = 20; + + local($hs) = 6; # TCP + local($len) = $bytes[$base + 2]; + $hs += $len; + $hs += &ipv6addrsum($base); + + &tcpcommon($base, $hl, $hs, 2); +} + +sub icmpcheck6 { + local($base) = $_[0]; + local($hl) = 20; + + local($hs) = 58; # ICMP6 + local($len) = $bytes[$base + 2]; + $hs += $len; + $hs += &ipv6addrsum($base); + + local($len) = $bytes[$base + 1] - ($hl << 1); + + if ($bytes[$base + 2] > ($cnt - $base) * 2) { + print " ICMPv6: missing data(1)"; + return; + } elsif ($bytes[$base + 2] < 8) { + print " ICMPv6: missing data(2)"; + return; + } + + local($osum) = $bytes[$base + $hl + 1]; + $bytes[$base + $hl + 1] = 0; + local($hs2) = &dosum($hs, $base + $hl, $cnt); + $bytes[$base + $hl + 1] = $osum; + + if ($osum != $hs2) { + printf " ICMPv6: (%x) %x != %x", $hs, $osum, $hs2; + } else { + print " ICMPv6: ok"; + } +# if ($base == 0) { +# $type = $bytes[$hl] >> 8; +# if ($type == 3 || $type == 4 || $type == 5 || +# $type == 11 || $type == 12) { +# &ipv4check($hl + 4); +# } +# } +} + +sub ipv4check { + local($base) = $_[0]; + $hl = $bytes[$base] / 256; + if (($hl >> 4) == 6) { + &ipv6check($_[0]); + } + return if (($hl >> 4) != 4); # IPv4 ? + $hl &= 0xf; + $hl <<= 1; # get the header length in 16bit words + + $hs = &dosum(0, $base, $base + $hl); + $osum = $bytes[$base + 5]; + + if ($hs != 0) { + $bytes[$base + 5] = 0; + $hs2 = &dosum(0, $base, $base + $hl); + $bytes[$base + 5] = $osum; + printf " IPv4: ($hl,%x) %x != %x", $hs, $osum, $hs2; + } else { + print " IPv4($base): ok "; + } + + # + # Recognise TCP & UDP and calculate checksums for each of these. + # + if (($bytes[$base + 4] & 0xff) == 4) { + &ipv4check($hl); + } + if (($bytes[$base + 4] & 0xff) == 6) { + &tcpcheck($base); + } + + if (($bytes[$base + 4] & 0xff) == 17) { + &udpcheck($base); + } + + if (($bytes[$base + 4] & 0xff) == 1) { + &icmpcheck($base); + } + if ($base == 0) { + print "\n"; + } +} + +sub tcpcheck { + local($base) = $_[0]; + local($hl) = $bytes[$base] / 256; + return if (($hl >> 4) != 4); + if ($bytes[$base + 3] & 0x3fff) { + print " TCP: fragment"; + return; + } + $hl &= 0xf; + $hl <<= 1; + + local($hs) = 6; # TCP + local($len) = $bytes[$base + 1] - ($hl << 1); + $hs += $len; + $hs += &ipv4addrsum($base); + + &tcpcommon($base, $hl, $hs, 1); +} + +sub udpcheck { + local($base) = $_[0]; + local($hl) = $bytes[0] / 256; + return if (($hl >> 4) != 4); + if ($bytes[$base + 3] & 0x3fff) { + print " UDP: fragment"; + return; + } + $hl &= 0xf; + $hl <<= 1; + + local($hs) = 17; # UDP + local($len) = $bytes[$base + 1] - ($hl << 1); + $hs += $len; + $hs += &ipv4addrsum($base); + local($udpsum) = $hs; + &udpcommon($base, $hl, $hs); +} + sub icmpcheck { local($base) = $_[0]; local($hl) = $bytes[$base + 0] / 256; @@ -21,14 +21,6 @@ time permitting: * record buffering for TCP/UDP -* modular application proxying --done - -* allow multiple ip addresses in a source route list for ipsend - -* port IP Filter to Linux -Not in this century. - * document bimap * document NAT rule order processing @@ -56,14 +48,14 @@ I would also love to see a more extensive NAT. It can choose to do rdr and map based on saddr, daddr, sport and dport. (Does the kernel module already have functionality for that and it just needs support in the userland ipnat?) --sort of done +-done - * intrusion detection - detection of port scans + * intrusion detection + detection of port scans detection of multiple connection attempts - + * support for multiple log files - i.e. all connections to ftp and telnet logged to + i.e. all connections to ftp and telnet logged to a seperate log file * multiple levels of log severity with E-mail notification diff --git a/tools/BNF.ipf b/tools/BNF.ipf index 0e8433291d1c3..0740c5855af9e 100644 --- a/tools/BNF.ipf +++ b/tools/BNF.ipf @@ -66,7 +66,7 @@ facility = "kern" | "user" | "mail" | "daemon" | "auth" | "syslog" | "audit" | "logalert" | "local0" | "local1" | "local2" | "local3" | "local4" | "local5" | "local6" | "local7" . priority = "emerg" | "alert" | "crit" | "err" | "warn" | "notice" | - "info" | "debug" . + "info" | "debug" . hexnumber = "0" "x" hexstring . hexstring = hexdigit [ hexstring ] . diff --git a/tools/Makefile b/tools/Makefile index 43ec1a897b831..ce1ab0e6fc22b 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -1,8 +1,5 @@ -# -# Copyright (C) 1993-2001 by Darren Reed. -# -# See the IPFILTER.LICENCE file for details on licencing. -# +YACC=yacc -v + DEST=. all: $(DEST)/ipf_y.c $(DEST)/ipf_y.h $(DEST)/ipf_l.c \ @@ -16,7 +13,7 @@ all: $(DEST)/ipf_y.c $(DEST)/ipf_y.h $(DEST)/ipf_l.c \ $(DEST)/ipf_y.h: $(DEST)/ipf_y.c $(DEST)/ipf_y.c: ipf_y.y - yacc -d ipf_y.y + $(YACC) -d ipf_y.y sed -e 's/yy/ipf_yy/g' -e 's/y.tab.h/ipf_y.c/' \ -e 's/"ipf_y.y"/"..\/tools\/ipf_y.y"/' \ y.tab.c > $(DEST)/ipf_y.c @@ -30,7 +27,7 @@ $(DEST)/ipf_l.c: lexer.c $(DEST)/ipmon_y.n: $(DEST)/ipmon_y.c $(DEST)/ipmon_y.c $(DEST)/ipmon_y.h: ipmon_y.y - yacc -d ipmon_y.y + $(YACC) -d ipmon_y.y sed -e 's/yy/ipmon_yy/g' -e 's/"ipmon_y.y"/"..\/tools\/ipmon_y.y"/' \ y.tab.c > $(DEST)/ipmon_y.c sed -e 's/yy/ipmon_yy/g' y.tab.h > $(DEST)/ipmon_y.h @@ -43,7 +40,7 @@ $(DEST)/ipmon_l.c: lexer.c $(DEST)/ipscan_y.h: $(DEST)/ipscan_y.c $(DEST)/ipscan_y.c $(DEST)/ipscan_y.h: ipscan_y.y - yacc -d ipscan_y.y + $(YACC) -d ipscan_y.y sed -e 's/yy/ipscan_yy/g' \ -e 's/"ipscan_y.y"/"..\/tools\/ipscan_y.y"/' \ y.tab.c > $(DEST)/ipscan_y.c @@ -57,7 +54,7 @@ $(DEST)/ipscan_l.c: lexer.c $(DEST)/ippool_y.h: $(DEST)/ippool_y.c $(DEST)/ippool_y.c $(DEST)/ippool_y.h: ippool_y.y - yacc -d ippool_y.y + $(YACC) -d ippool_y.y sed -e 's/yy/ippool_yy/g' -e 's/"ippool_y.y"/"..\/tools\/ippool_y.y"/' \ y.tab.c > $(DEST)/ippool_y.c sed -e 's/yy/ippool_yy/g' y.tab.h > $(DEST)/ippool_y.h @@ -70,7 +67,7 @@ $(DEST)/ippool_l.c: lexer.c $(DEST)/ipnat_y.h: $(DEST)/ipnat_y.c $(DEST)/ipnat_y.c $(DEST)/ipnat_y.h: ipnat_y.y - yacc -d ipnat_y.y + $(YACC) -d ipnat_y.y sed -e 's/yy/ipnat_yy/g' -e 's/y.tab.c/ipnat_y.c/' \ -e s/\"ipnat_y.y\"/\"..\\/tools\\/ipnat_y.y\"/ \ y.tab.c > $(DEST)/ipnat_y.c diff --git a/tools/ipf.c b/tools/ipf.c index 063ecf08e68dd..d2d6053d87a74 100644 --- a/tools/ipf.c +++ b/tools/ipf.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -14,12 +14,13 @@ #endif #include "ipf.h" #include <fcntl.h> +#include <ctype.h> #include <sys/ioctl.h> #include "netinet/ipl.h" #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 1.35.2.8 2007/05/10 06:12:01 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #if !defined(__SVR4) && defined(__GNUC__) @@ -38,17 +39,21 @@ int main __P((int, char *[])); int opts = 0; int outputc = 0; int use_inet6 = 0; - -static void procfile __P((char *, char *)), flushfilter __P((char *)); -static void set_state __P((u_int)), showstats __P((friostat_t *)); -static void packetlogon __P((char *)), swapactive __P((void)); +int exitstatus = 0; + +static void procfile __P((char *)); +static void flushfilter __P((char *, int *)); +static void set_state __P((u_int)); +static void showstats __P((friostat_t *)); +static void packetlogon __P((char *)); +static void swapactive __P((void)); static int opendevice __P((char *, int)); static void closedevice __P((void)); static char *ipfname = IPL_NAME; static void usage __P((void)); static int showversion __P((void)); static int get_flags __P((void)); -static void ipf_interceptadd __P((int, ioctlfunc_t, void *)); +static int ipf_interceptadd __P((int, ioctlfunc_t, void *)); static int fd = -1; static ioctlfunc_t iocfunctions[IPL_LOGSIZE] = { ioctl, ioctl, ioctl, @@ -66,25 +71,28 @@ static void usage() int main(argc,argv) -int argc; -char *argv[]; + int argc; + char *argv[]; { - int c; + int c, *filter = NULL; if (argc < 2) usage(); - while ((c = getopt(argc, argv, "6Ac:dDEf:F:Il:noPrRsT:vVyzZ")) != -1) { + assigndefined(getenv("IPF_PREDEFINED")); + + while ((c = getopt(argc, argv, "46Ac:dDEf:F:Il:m:noPrRsT:vVyzZ")) != -1) { switch (c) { case '?' : usage(); break; -#ifdef USE_INET6 + case '4' : + use_inet6 = -1; + break; case '6' : use_inet6 = 1; break; -#endif case 'A' : opts &= ~OPT_INACTIVE; break; @@ -102,10 +110,10 @@ char *argv[]; opts ^= OPT_DEBUG; break; case 'f' : - procfile(argv[0], optarg); + procfile(optarg); break; case 'F' : - flushfilter(optarg); + flushfilter(optarg, filter); break; case 'I' : opts ^= OPT_INACTIVE; @@ -113,8 +121,11 @@ char *argv[]; case 'l' : packetlogon(optarg); break; + case 'm' : + filter = parseipfexpr(optarg, NULL); + break; case 'n' : - opts ^= OPT_DONOTHING; + opts ^= OPT_DONOTHING|OPT_DONTOPEN; break; case 'o' : break; @@ -159,14 +170,14 @@ char *argv[]; if (fd != -1) (void) close(fd); - return(0); + return(exitstatus); /* NOTREACHED */ } static int opendevice(ipfdev, check) -char *ipfdev; -int check; + char *ipfdev; + int check; { if (opts & OPT_DONOTHING) return -2; @@ -182,7 +193,7 @@ int check; if (fd == -1) if ((fd = open(ipfdev, O_RDWR)) == -1) if ((fd = open(ipfdev, O_RDONLY)) == -1) - perror("open device"); + ipferror(fd, "open device"); return fd; } @@ -200,7 +211,7 @@ static int get_flags() if ((opendevice(ipfname, 1) != -2) && (ioctl(fd, SIOCGETFF, &i) == -1)) { - perror("SIOCGETFF"); + ipferror(fd, "SIOCGETFF"); return 0; } return i; @@ -208,22 +219,24 @@ static int get_flags() static void set_state(enable) -u_int enable; + u_int enable; { - if (opendevice(ipfname, 0) != -2) + if (opendevice(ipfname, 0) != -2) { if (ioctl(fd, SIOCFRENB, &enable) == -1) { - if (errno == EBUSY) + if (errno == EBUSY) { fprintf(stderr, "IP FIlter: already initialized\n"); - else - perror("SIOCFRENB"); + } else { + ipferror(fd, "SIOCFRENB"); + } } + } return; } -static void procfile(name, file) -char *name, *file; +static void procfile(file) + char *file; { (void) opendevice(ipfname, 1); @@ -239,20 +252,22 @@ char *name, *file; } -static void ipf_interceptadd(fd, ioctlfunc, ptr) -int fd; -ioctlfunc_t ioctlfunc; -void *ptr; +static int ipf_interceptadd(fd, ioctlfunc, ptr) + int fd; + ioctlfunc_t ioctlfunc; + void *ptr; { if (outputc) printc(ptr); - ipf_addrule(fd, ioctlfunc, ptr); + if (ipf_addrule(fd, ioctlfunc, ptr) != 0) + exitstatus = 1; + return 0; } static void packetlogon(opt) -char *opt; + char *opt; { int flag, xfd, logopt, change = 0; @@ -291,7 +306,7 @@ char *opt; if (change == 1) { if (opendevice(ipfname, 1) != -2 && (ioctl(fd, SIOCSETFF, &flag) != 0)) - perror("ioctl(SIOCSETFF)"); + ipferror(fd, "ioctl(SIOCSETFF)"); } if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { @@ -306,11 +321,11 @@ char *opt; if (xfd >= 0) { logopt = 0; if (ioctl(xfd, SIOCGETLG, &logopt)) - perror("ioctl(SIOCGETLG)"); + ipferror(fd, "ioctl(SIOCGETLG)"); else { logopt = 1 - logopt; if (ioctl(xfd, SIOCSETLG, &logopt)) - perror("ioctl(SIOCSETLG)"); + ipferror(xfd, "ioctl(SIOCSETLG)"); } close(xfd); } @@ -323,11 +338,11 @@ char *opt; if (xfd >= 0) { logopt = 0; if (ioctl(xfd, SIOCGETLG, &logopt)) - perror("ioctl(SIOCGETLG)"); + ipferror(xfd, "ioctl(SIOCGETLG)"); else { logopt = 1 - logopt; if (ioctl(xfd, SIOCSETLG, &logopt)) - perror("ioctl(SIOCSETLG)"); + ipferror(xfd, "ioctl(SIOCSETLG)"); } close(xfd); } @@ -335,8 +350,9 @@ char *opt; } -static void flushfilter(arg) -char *arg; +static void flushfilter(arg, filter) + char *arg; + int *filter; { int fl = 0, rem; @@ -357,20 +373,33 @@ char *arg; if (!(opts & OPT_DONOTHING)) { if (use_inet6) { - if (ioctl(fd, SIOCIPFL6, &fl) == -1) { - perror("ioctl(SIOCIPFL6)"); - exit(1); + fprintf(stderr, + "IPv6 rules are no longer seperate\n"); + } else if (filter != NULL) { + ipfobj_t obj; + + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_size = filter[0] * sizeof(int); + obj.ipfo_type = IPFOBJ_IPFEXPR; + obj.ipfo_ptr = filter; + if (ioctl(fd, SIOCMATCHFLUSH, &obj) == -1) { + ipferror(fd, "ioctl(SIOCMATCHFLUSH)"); + fl = -1; + } else { + fl = obj.ipfo_retval; } } else { if (ioctl(fd, SIOCIPFFL, &fl) == -1) { - perror("ioctl(SIOCIPFFL)"); + ipferror(fd, "ioctl(SIOCIPFFL)"); exit(1); } } } - if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { + if ((opts & (OPT_DONOTHING|OPT_DEBUG)) == OPT_DEBUG) { printf("remove flags %s (%d)\n", arg, rem); - printf("removed %d entries\n", fl); + } + if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { + printf("%d state entries removed\n", fl); } closedevice(); return; @@ -386,7 +415,7 @@ char *arg; perror("open(IPL_AUTH)"); else { if (ioctl(fd, SIOCIPFFA, &fl) == -1) - perror("ioctl(SIOCIPFFA)"); + ipferror(fd, "ioctl(SIOCIPFFA)"); } closedevice(); return; @@ -409,21 +438,23 @@ char *arg; if (!(opts & OPT_DONOTHING)) { if (use_inet6) { if (ioctl(fd, SIOCIPFL6, &fl) == -1) { - perror("ioctl(SIOCIPFL6)"); + ipferror(fd, "ioctl(SIOCIPFL6)"); exit(1); } } else { if (ioctl(fd, SIOCIPFFL, &fl) == -1) { - perror("ioctl(SIOCIPFFL)"); + ipferror(fd, "ioctl(SIOCIPFFL)"); exit(1); } } } - if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { + if ((opts & (OPT_DONOTHING|OPT_DEBUG)) == OPT_DEBUG) { printf("remove flags %s%s (%d)\n", (rem & FR_INQUE) ? "I" : "", (rem & FR_OUTQUE) ? "O" : "", rem); - printf("removed %d filter rules\n", fl); + } + if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { + printf("%d filter rules removed\n", fl); } return; } @@ -434,7 +465,7 @@ static void swapactive() int in = 2; if (opendevice(ipfname, 1) != -2 && ioctl(fd, SIOCSWAPA, &in) == -1) - perror("ioctl(SIOCSWAPA)"); + ipferror(fd, "ioctl(SIOCSWAPA)"); else printf("Set %d now inactive\n", in); } @@ -445,7 +476,7 @@ void ipf_frsync() int frsyn = 0; if (opendevice(ipfname, 1) != -2 && ioctl(fd, SIOCFRSYN, &frsyn) == -1) - perror("SIOCFRSYN"); + ipferror(fd, "SIOCFRSYN"); else printf("filter sync'd\n"); } @@ -464,7 +495,7 @@ void zerostats() if (opendevice(ipfname, 1) != -2) { if (ioctl(fd, SIOCFRZST, &obj) == -1) { - perror("ioctl(SIOCFRZST)"); + ipferror(fd, "ioctl(SIOCFRZST)"); exit(-1); } showstats(&fio); @@ -477,7 +508,7 @@ void zerostats() * read the kernel stats for packets blocked and passed */ static void showstats(fp) -friostat_t *fp; + friostat_t *fp; { printf("bad packets:\t\tin %lu\tout %lu\n", fp->f_st[0].fr_bad, fp->f_st[1].fr_bad); @@ -493,9 +524,6 @@ friostat_t *fp; fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl); printf("output packets logged:\tblocked %lu passed %lu\n", fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl); - printf(" packets logged:\tinput %lu-%lu output %lu-%lu\n", - fp->f_st[0].fr_pkl, fp->f_st[0].fr_skip, - fp->f_st[1].fr_pkl, fp->f_st[1].fr_skip); } @@ -521,7 +549,7 @@ static int showversion() } if (ioctl(vfd, SIOCGETFS, &ipfo)) { - perror("ioctl(SIOCGETFS)"); + ipferror(vfd, "ioctl(SIOCGETFS)"); close(vfd); return 1; } diff --git a/tools/ipf_y.y b/tools/ipf_y.y index 4156250d0fa19..a1a605210ac3c 100644 --- a/tools/ipf_y.y +++ b/tools/ipf_y.y @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -28,18 +28,29 @@ extern int yydebug; extern FILE *yyin; extern int yylineNum; -static void newrule __P((void)); -static void setipftype __P((void)); -static u_32_t lookuphost __P((char *)); +static int addname __P((frentry_t **, char *)); +static frentry_t *addrule __P((void)); +static frentry_t *allocfr __P((void)); +static void build_dstaddr_af __P((frentry_t *, void *)); +static void build_srcaddr_af __P((frentry_t *, void *)); static void dobpf __P((int, char *)); -static void resetaddr __P((void)); -static struct alist_s *newalist __P((struct alist_s *)); +static void doipfexpr __P((char *)); +static void do_tuneint __P((char *, int)); +static void do_tunestr __P((char *, char *)); +static void fillgroup __P((frentry_t *)); +static int lookuphost __P((char *, i6addr_t *)); static u_int makehash __P((struct alist_s *)); static int makepool __P((struct alist_s *)); -static frentry_t *addrule __P((void)); +static struct alist_s *newalist __P((struct alist_s *)); +static void newrule __P((void)); +static void resetaddr __P((void)); +static void setgroup __P((frentry_t **, char *)); +static void setgrhead __P((frentry_t **, char *)); +static void seticmphead __P((frentry_t **, char *)); +static void setifname __P((frentry_t **, int, char *)); +static void setipftype __P((void)); static void setsyslog __P((void)); static void unsetsyslog __P((void)); -static void fillgroup __P((frentry_t *)); frentry_t *fr = NULL, *frc = NULL, *frtop = NULL, *frold = NULL; @@ -52,52 +63,54 @@ static int nrules = 0; static int newlist = 0; static int added = 0; static int ipffd = -1; -static int *yycont = 0; -static ioctlfunc_t ipfioctl[IPL_LOGSIZE]; +static int *yycont = NULL; +static ioctlfunc_t ipfioctls[IPL_LOGSIZE]; static addfunc_t ipfaddfunc = NULL; -static struct wordtab ipfwords[95]; -static struct wordtab addrwords[4]; -static struct wordtab maskwords[5]; -static struct wordtab icmpcodewords[17]; -static struct wordtab icmptypewords[16]; -static struct wordtab ipv4optwords[25]; -static struct wordtab ipv4secwords[9]; -static struct wordtab ipv6optwords[9]; -static struct wordtab logwords[33]; %} %union { char *str; u_32_t num; - struct in_addr ipa; frentry_t fr; frtuc_t *frt; struct alist_s *alist; u_short port; + struct in_addr ip4; struct { u_short p1; u_short p2; int pc; } pc; - struct { + struct ipp_s { + int type; + int ifpos; + int f; + int v; + int lif; union i6addr a; union i6addr m; + char *name; } ipp; - union i6addr ip6; + struct { + i6addr_t adr; + int f; + } adr; + i6addr_t ip6; struct { char *if1; char *if2; } ifs; + char gname[FR_GROUPLEN]; }; %type <port> portnum %type <num> facility priority icmpcode seclevel secname icmptype %type <num> opt compare range opttype flagset optlist ipv6hdrlist ipv6hdr -%type <num> portc porteq -%type <ipa> hostname ipv4 ipv4mask ipv4_16 ipv4_24 -%type <ip6> ipv6mask +%type <num> portc porteq ipmask maskopts +%type <ip4> ipv4 ipv4_16 ipv4_24 +%type <adr> hostname %type <ipp> addr ipaddr -%type <str> servicename name interfacename +%type <str> servicename name interfacename groupname %type <pc> portrange portcomp %type <alist> addrlist poollist %type <ifs> onname @@ -109,30 +122,32 @@ static struct wordtab logwords[33]; %token YY_RANGE_OUT YY_RANGE_IN %token <ip6> YY_IPV6 +%token IPFY_SET %token IPFY_PASS IPFY_BLOCK IPFY_COUNT IPFY_CALL IPFY_NOMATCH %token IPFY_RETICMP IPFY_RETRST IPFY_RETICMPASDST %token IPFY_IN IPFY_OUT %token IPFY_QUICK IPFY_ON IPFY_OUTVIA IPFY_INVIA %token IPFY_DUPTO IPFY_TO IPFY_FROUTE IPFY_REPLY_TO IPFY_ROUTETO -%token IPFY_TOS IPFY_TTL IPFY_PROTO +%token IPFY_TOS IPFY_TTL IPFY_PROTO IPFY_INET IPFY_INET6 %token IPFY_HEAD IPFY_GROUP %token IPFY_AUTH IPFY_PREAUTH -%token IPFY_LOG IPFY_BODY IPFY_FIRST IPFY_LEVEL IPFY_ORBLOCK -%token IPFY_LOGTAG IPFY_MATCHTAG IPFY_SETTAG IPFY_SKIP +%token IPFY_LOG IPFY_BODY IPFY_FIRST IPFY_LEVEL IPFY_ORBLOCK IPFY_L5AS +%token IPFY_LOGTAG IPFY_MATCHTAG IPFY_SETTAG IPFY_SKIP IPFY_DECAPS %token IPFY_FROM IPFY_ALL IPFY_ANY IPFY_BPFV4 IPFY_BPFV6 IPFY_POOL IPFY_HASH -%token IPFY_PPS +%token IPFY_IPFEXPR IPFY_PPS IPFY_FAMILY IPFY_DSTLIST %token IPFY_ESP IPFY_AH %token IPFY_WITH IPFY_AND IPFY_NOT IPFY_NO IPFY_OPT %token IPFY_TCPUDP IPFY_TCP IPFY_UDP %token IPFY_FLAGS IPFY_MULTICAST %token IPFY_MASK IPFY_BROADCAST IPFY_NETWORK IPFY_NETMASKED IPFY_PEER -%token IPFY_PORT -%token IPFY_NOW +%token IPFY_RPC IPFY_PORT +%token IPFY_NOW IPFY_COMMENT IPFY_RULETTL %token IPFY_ICMP IPFY_ICMPTYPE IPFY_ICMPCODE %token IPFY_IPOPTS IPFY_SHORT IPFY_NAT IPFY_BADSRC IPFY_LOWTTL IPFY_FRAG %token IPFY_MBCAST IPFY_BAD IPFY_BADNAT IPFY_OOW IPFY_NEWISN IPFY_NOICMPERR %token IPFY_KEEP IPFY_STATE IPFY_FRAGS IPFY_LIMIT IPFY_STRICT IPFY_AGE -%token IPFY_SYNC IPFY_FRAGBODY +%token IPFY_SYNC IPFY_FRAGBODY IPFY_ICMPHEAD IPFY_NOLOG IPFY_LOOSE +%token IPFY_MAX_SRCS IPFY_MAX_PER_SRC %token IPFY_IPOPT_NOP IPFY_IPOPT_RR IPFY_IPOPT_ZSU IPFY_IPOPT_MTUP %token IPFY_IPOPT_MTUR IPFY_IPOPT_ENCODE IPFY_IPOPT_TS IPFY_IPOPT_TR %token IPFY_IPOPT_SEC IPFY_IPOPT_LSRR IPFY_IPOPT_ESEC IPFY_IPOPT_CIPSO @@ -140,10 +155,10 @@ static struct wordtab logwords[33]; %token IPFY_IPOPT_IMITD IPFY_IPOPT_EIP IPFY_IPOPT_FINN IPFY_IPOPT_DPS %token IPFY_IPOPT_SDB IPFY_IPOPT_NSAPA IPFY_IPOPT_RTRALRT IPFY_IPOPT_UMP %token IPFY_SECCLASS IPFY_SEC_UNC IPFY_SEC_CONF IPFY_SEC_RSV1 IPFY_SEC_RSV2 -%token IPFY_SEC_RSV4 IPFY_SEC_SEC IPFY_SEC_TS IPFY_SEC_RSV3 +%token IPFY_SEC_RSV4 IPFY_SEC_SEC IPFY_SEC_TS IPFY_SEC_RSV3 IPFY_DOI -%token IPF6_V6HDRS IPFY_IPV6OPT IPFY_IPV6OPT_DSTOPTS IPFY_IPV6OPT_HOPOPTS -%token IPFY_IPV6OPT_IPV6 IPFY_IPV6OPT_NONE IPFY_IPV6OPT_ROUTING +%token IPFY_V6HDRS IPFY_IPV6OPT IPFY_IPV6OPT_DSTOPTS IPFY_IPV6OPT_HOPOPTS +%token IPFY_IPV6OPT_IPV6 IPFY_IPV6OPT_NONE IPFY_IPV6OPT_ROUTING IPFY_V6HDR %token IPFY_IPV6OPT_MOBILITY IPFY_IPV6OPT_ESP IPFY_IPV6OPT_FRAG %token IPFY_ICMPT_UNR IPFY_ICMPT_ECHO IPFY_ICMPT_ECHOR IPFY_ICMPT_SQUENCH @@ -168,16 +183,36 @@ static struct wordtab logwords[33]; %token IPFY_PRI_EMERG IPFY_PRI_ALERT IPFY_PRI_CRIT IPFY_PRI_ERR IPFY_PRI_WARN %token IPFY_PRI_NOTICE IPFY_PRI_INFO IPFY_PRI_DEBUG %% -file: line +file: settings rules + | rules + ; + +settings: + YY_COMMENT + | setting + | settings setting + ; + +rules: line | assign - | file line - | file assign + | rules line + | rules assign + ; + +setting: + IPFY_SET YY_STR YY_NUMBER ';' { do_tuneint($2, $3); } + | IPFY_SET YY_STR YY_HEX ';' { do_tuneint($2, $3); } + | IPFY_SET YY_STR YY_STR ';' { do_tunestr($2, $3); } ; line: rule { while ((fr = frtop) != NULL) { frtop = fr->fr_next; fr->fr_next = NULL; - (*ipfaddfunc)(ipffd, ipfioctl[IPL_LOGIPF], fr); + if ((fr->fr_type == FR_T_IPF) && + (fr->fr_ip.fi_v == 0)) + fr->fr_mip.fi_v = 0; + /* XXX validate ? */ + (*ipfaddfunc)(ipffd, ipfioctls[IPL_LOGIPF], fr); fr->fr_next = frold; frold = fr; } @@ -231,10 +266,37 @@ markout: rulemain: ipfrule | bpfrule + | exprrule ; ipfrule: - tos ttl proto ip + family tos ttl proto ip + ; + +family: | IPFY_FAMILY IPFY_INET { if (use_inet6 == 1) { + YYERROR; + } else { + frc->fr_family = AF_INET; + } + } + | IPFY_INET { if (use_inet6 == 1) { + YYERROR; + } else { + frc->fr_family = AF_INET; + } + } + | IPFY_FAMILY IPFY_INET6 { if (use_inet6 == -1) { + YYERROR; + } else { + frc->fr_family = AF_INET6; + } + } + | IPFY_INET6 { if (use_inet6 == -1) { + YYERROR; + } else { + frc->fr_family = AF_INET6; + } + } ; bpfrule: @@ -242,12 +304,16 @@ bpfrule: | IPFY_BPFV6 '{' YY_STR '}' { dobpf(6, $3); free($3); } ; +exprrule: + IPFY_IPFEXPR '{' YY_STR '}' { doipfexpr($3); } + ; + ruletail: with keep head group ; ruletail2: - pps age new + pps age new rulettl comment ; intag: settagin matchtagin @@ -269,6 +335,7 @@ action: block | IPFY_NOMATCH { fr->fr_flags |= FR_NOMATCH; } | log | IPFY_COUNT { fr->fr_flags |= FR_ACCOUNT; } + | decaps { fr->fr_flags |= FR_DECAPSULATE; } | auth | IPFY_SKIP YY_NUMBER { fr->fr_flags |= FR_SKIP; fr->fr_arg = $2; } @@ -291,6 +358,11 @@ blockreturn: | IPFY_RETRST { fr->fr_flags |= FR_RETRST; } ; +decaps: IPFY_DECAPS + | IPFY_DECAPS IPFY_L5AS '(' YY_STR ')' + { fr->fr_icode = atoi($4); } + ; + log: IPFY_LOG { fr->fr_flags |= FR_LOG; } | IPFY_LOG logoptions { fr->fr_flags |= FR_LOG; } ; @@ -300,10 +372,11 @@ auth: IPFY_AUTH { fr->fr_flags |= FR_AUTH; } | IPFY_PREAUTH { fr->fr_flags |= FR_PREAUTH; } ; -func: YY_STR '/' YY_NUMBER { fr->fr_func = nametokva($1, - ipfioctl[IPL_LOGIPF]); - fr->fr_arg = $3; - free($1); } +func: YY_STR '/' YY_NUMBER + { fr->fr_func = nametokva($1, ipfioctls[IPL_LOGIPF]); + fr->fr_arg = $3; + free($1); + } ; inopts: @@ -330,6 +403,7 @@ outopt: | on | dup | proute + | froute | replyto ; @@ -346,7 +420,7 @@ toslist: | YY_HEX { DOREM(fr->fr_tos = $1; fr->fr_mtos = 0xff;) } | toslist lmore YY_NUMBER { DOREM(fr->fr_tos = $3; fr->fr_mtos = 0xff;) } - | toslist lmore YY_HEX + | toslist lmore YY_HEX { DOREM(fr->fr_tos = $3; fr->fr_mtos = 0xff;) } ; @@ -355,10 +429,10 @@ ttl: | setttl YY_NUMBER | setttl lstart ttllist lend ; -lstart: '(' { newlist = 1; fr = frc; added = 0; } +lstart: '{' { newlist = 1; fr = frc; added = 0; } ; -lend: ')' { nrules += added; } +lend: '}' { nrules += added; } ; lmore: lanother { if (newlist == 1) { @@ -394,20 +468,25 @@ protox: IPFY_PROTO { setipftype(); ip: srcdst flags icmp ; -group: | IPFY_GROUP YY_STR { DOALL(strncpy(fr->fr_group, $2, \ - FR_GROUPLEN); \ - fillgroup(fr);); - free($2); } - | IPFY_GROUP YY_NUMBER { DOALL(sprintf(fr->fr_group, "%d", \ - $2); \ - fillgroup(fr);) } +group: | IPFY_GROUP groupname { DOALL(setgroup(&fr, $2); \ + fillgroup(fr);); + free($2); + } + ; + +head: | IPFY_HEAD groupname { DOALL(setgrhead(&fr, $2);); + free($2); + } ; -head: | IPFY_HEAD YY_STR { DOALL(strncpy(fr->fr_grhead, $2, \ - FR_GROUPLEN);); - free($2); } - | IPFY_HEAD YY_NUMBER { DOALL(sprintf(fr->fr_grhead, "%d", \ - $2);) } +groupname: + YY_STR { $$ = $1; + if (strlen($$) >= FR_GROUPLEN) + $$[FR_GROUPLEN - 1] = '\0'; + } + | YY_NUMBER { $$ = malloc(16); + sprintf($$, "%d", $1); + } ; settagin: @@ -461,6 +540,15 @@ pps: | IPFY_PPS YY_NUMBER { DOALL(fr->fr_pps = $2;) } new: | savegroup file restoregroup ; +rulettl: + | IPFY_RULETTL YY_NUMBER { DOALL(fr->fr_die = $2;) } + ; + +comment: + | IPFY_COMMENT YY_STR { DOALL(fr->fr_comment = addname(&fr, \ + $2);) } + ; + savegroup: '{' ; @@ -472,76 +560,92 @@ restoregroup: logopt: log ; -quick: - IPFY_QUICK { fr->fr_flags |= FR_QUICK; } +quick: IPFY_QUICK { fr->fr_flags |= FR_QUICK; } ; -on: IPFY_ON onname +on: IPFY_ON onname { setifname(&fr, 0, $2.if1); + free($2.if1); + if ($2.if2 != NULL) { + setifname(&fr, 1, + $2.if2); + free($2.if2); + } + } | IPFY_ON lstart onlist lend - | IPFY_ON onname IPFY_INVIA vianame - | IPFY_ON onname IPFY_OUTVIA vianame - ; - -onlist: onname { DOREM(strncpy(fr->fr_ifnames[0], $1.if1, \ - sizeof(fr->fr_ifnames[0])); \ - if ($1.if2 != NULL) { \ - strncpy(fr->fr_ifnames[1], \ - $1.if2, \ - sizeof(fr->fr_ifnames[1]));\ - } \ - ) } - | onlist lmore onname { DOREM(strncpy(fr->fr_ifnames[0], $3.if1, \ - sizeof(fr->fr_ifnames[0])); \ - if ($3.if2 != NULL) { \ - strncpy(fr->fr_ifnames[1], \ - $3.if2, \ - sizeof(fr->fr_ifnames[1]));\ - } \ - ) } - ; - -onname: interfacename - { strncpy(fr->fr_ifnames[0], $1, sizeof(fr->fr_ifnames[0])); - $$.if1 = fr->fr_ifnames[0]; - $$.if2 = NULL; - free($1); - } + | IPFY_ON onname IPFY_INVIA vianame { setifname(&fr, 0, $2.if1); + free($2.if1); + if ($2.if2 != NULL) { + setifname(&fr, 1, + $2.if2); + free($2.if2); + } + } + | IPFY_ON onname IPFY_OUTVIA vianame { setifname(&fr, 0, $2.if1); + free($2.if1); + if ($2.if2 != NULL) { + setifname(&fr, 1, + $2.if2); + free($2.if2); + } + } + ; + +onlist: onname { DOREM(setifname(&fr, 0, $1.if1); \ + if ($1.if2 != NULL) \ + setifname(&fr, 1, $1.if2); \ + ) + free($1.if1); + if ($1.if2 != NULL) + free($1.if2); + } + | onlist lmore onname { DOREM(setifname(&fr, 0, $3.if1); \ + if ($3.if2 != NULL) \ + setifname(&fr, 1, $3.if2); \ + ) + free($3.if1); + if ($3.if2 != NULL) + free($3.if2); + } + ; + +onname: interfacename { $$.if1 = $1; + $$.if2 = NULL; + } | interfacename ',' interfacename - { strncpy(fr->fr_ifnames[0], $1, sizeof(fr->fr_ifnames[0])); - $$.if1 = fr->fr_ifnames[0]; - free($1); - strncpy(fr->fr_ifnames[1], $3, sizeof(fr->fr_ifnames[1])); - $$.if1 = fr->fr_ifnames[1]; - free($3); - } + { $$.if1 = $1; + $$.if2 = $3; + } ; vianame: - name - { strncpy(fr->fr_ifnames[2], $1, sizeof(fr->fr_ifnames[2])); - free($1); - } - | name ',' name - { strncpy(fr->fr_ifnames[2], $1, sizeof(fr->fr_ifnames[2])); - free($1); - strncpy(fr->fr_ifnames[3], $3, sizeof(fr->fr_ifnames[3])); - free($3); - } + name { setifname(&fr, 2, $1); + free($1); + } + | name ',' name { setifname(&fr, 2, $1); + free($1); + setifname(&fr, 3, $3); + free($3); + } ; dup: IPFY_DUPTO name - { strncpy(fr->fr_dif.fd_ifname, $2, sizeof(fr->fr_dif.fd_ifname)); + { int idx = addname(&fr, $2); + fr->fr_dif.fd_name = idx; free($2); } - | IPFY_DUPTO name duptoseparator hostname - { strncpy(fr->fr_dif.fd_ifname, $2, sizeof(fr->fr_dif.fd_ifname)); - fr->fr_dif.fd_ip = $4; - yyexpectaddr = 0; - free($2); + | IPFY_DUPTO IPFY_DSTLIST '/' name + { int idx = addname(&fr, $4); + fr->fr_dif.fd_name = idx; + fr->fr_dif.fd_type = FRD_DSTLIST; + free($4); } - | IPFY_DUPTO name duptoseparator YY_IPV6 - { strncpy(fr->fr_dif.fd_ifname, $2, sizeof(fr->fr_dif.fd_ifname)); - bcopy(&$4, &fr->fr_dif.fd_ip6, sizeof(fr->fr_dif.fd_ip6)); + | IPFY_DUPTO name duptoseparator hostname + { int idx = addname(&fr, $2); + fr->fr_dif.fd_name = idx; + fr->fr_dif.fd_ptr = (void *)-1; + fr->fr_dif.fd_ip6 = $4.adr; + if (fr->fr_family == AF_UNSPEC && $4.f != AF_UNSPEC) + fr->fr_family = $4.f; yyexpectaddr = 0; free($2); } @@ -555,18 +659,23 @@ froute: IPFY_FROUTE { fr->fr_flags |= FR_FASTROUTE; } ; proute: routeto name - { strncpy(fr->fr_tif.fd_ifname, $2, sizeof(fr->fr_tif.fd_ifname)); + { int idx = addname(&fr, $2); + fr->fr_tif.fd_name = idx; free($2); } - | routeto name duptoseparator hostname - { strncpy(fr->fr_tif.fd_ifname, $2, sizeof(fr->fr_tif.fd_ifname)); - fr->fr_tif.fd_ip = $4; - yyexpectaddr = 0; - free($2); + | routeto IPFY_DSTLIST '/' name + { int idx = addname(&fr, $4); + fr->fr_tif.fd_name = idx; + fr->fr_tif.fd_type = FRD_DSTLIST; + free($4); } - | routeto name duptoseparator YY_IPV6 - { strncpy(fr->fr_tif.fd_ifname, $2, sizeof(fr->fr_tif.fd_ifname)); - bcopy(&$4, &fr->fr_tif.fd_ip6, sizeof(fr->fr_tif.fd_ip6)); + | routeto name duptoseparator hostname + { int idx = addname(&fr, $2); + fr->fr_tif.fd_name = idx; + fr->fr_tif.fd_ptr = (void *)-1; + fr->fr_tif.fd_ip6 = $4.adr; + if (fr->fr_family == AF_UNSPEC && $4.f != AF_UNSPEC) + fr->fr_family = $4.f; yyexpectaddr = 0; free($2); } @@ -579,12 +688,22 @@ routeto: replyto: IPFY_REPLY_TO name - { strncpy(fr->fr_rif.fd_ifname, $2, sizeof(fr->fr_rif.fd_ifname)); + { int idx = addname(&fr, $2); + fr->fr_rif.fd_name = idx; free($2); } + | IPFY_REPLY_TO IPFY_DSTLIST '/' name + { fr->fr_rif.fd_name = addname(&fr, $4); + fr->fr_rif.fd_type = FRD_DSTLIST; + free($4); + } | IPFY_REPLY_TO name duptoseparator hostname - { strncpy(fr->fr_rif.fd_ifname, $2, sizeof(fr->fr_rif.fd_ifname)); - fr->fr_rif.fd_ip = $4; + { int idx = addname(&fr, $2); + fr->fr_rif.fd_name = idx; + fr->fr_rif.fd_ptr = (void *)-1; + fr->fr_rif.fd_ip6 = $4.adr; + if (fr->fr_family == AF_UNSPEC && $4.f != AF_UNSPEC) + fr->fr_family = $4.f; free($2); } ; @@ -614,27 +733,29 @@ srcdst: | IPFY_ALL ; protocol: - YY_NUMBER { DOREM(fr->fr_proto = $1; \ - fr->fr_mproto = 0xff;) } + YY_NUMBER { DOALL(fr->fr_proto = $1; \ + fr->fr_mproto = 0xff;) + } | YY_STR { if (!strcmp($1, "tcp-udp")) { - DOREM(fr->fr_flx |= FI_TCPUDP; \ + DOALL(fr->fr_flx |= FI_TCPUDP; \ fr->fr_mflx |= FI_TCPUDP;) } else { int p = getproto($1); if (p == -1) yyerror("protocol unknown"); - DOREM(fr->fr_proto = p; \ + DOALL(fr->fr_proto = p; \ fr->fr_mproto = 0xff;) } free($1); - } + } | YY_STR nextstring YY_STR { if (!strcmp($1, "tcp") && !strcmp($3, "udp")) { DOREM(fr->fr_flx |= FI_TCPUDP; \ fr->fr_mflx |= FI_TCPUDP;) - } else + } else { YYERROR; + } free($1); free($3); } @@ -667,7 +788,8 @@ to: IPFY_TO { if (fr == NULL) printf("set yyexpectaddr\n"); yycont = &yyexpectaddr; yysetdict(addrwords); - resetaddr(); } + resetaddr(); + } ; with: | andwith withlist @@ -678,7 +800,7 @@ andwith: | IPFY_AND { nowith = 0; setipftype(); } ; -flags: | startflags flagset +flags: | startflags flagset { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = FR_TCPFMAX;) } | startflags flagset '/' flagset { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) } @@ -717,35 +839,14 @@ srcobject: ; srcaddr: - addr { DOREM(bcopy(&($1.a), &fr->fr_ip.fi_src, sizeof($1.a)); \ - bcopy(&($1.m), &fr->fr_mip.fi_src, sizeof($1.m)); \ - if (dynamic != -1) { \ - fr->fr_satype = ifpflag; \ - fr->fr_ipf->fri_sifpidx = dynamic; \ - } else if (pooled || hashed) \ - fr->fr_satype = FRI_LOOKUP;) - } + addr { build_srcaddr_af(fr, &$1); } | lstart srcaddrlist lend ; srcaddrlist: - addr { DOREM(bcopy(&($1.a), &fr->fr_ip.fi_src, sizeof($1.a)); \ - bcopy(&($1.m), &fr->fr_mip.fi_src, sizeof($1.m)); \ - if (dynamic != -1) { \ - fr->fr_satype = ifpflag; \ - fr->fr_ipf->fri_sifpidx = dynamic; \ - } else if (pooled || hashed) \ - fr->fr_satype = FRI_LOOKUP;) - } + addr { build_srcaddr_af(fr, &$1); } | srcaddrlist lmore addr - { DOREM(bcopy(&($3.a), &fr->fr_ip.fi_src, sizeof($3.a)); \ - bcopy(&($3.m), &fr->fr_mip.fi_src, sizeof($3.m)); \ - if (dynamic != -1) { \ - fr->fr_satype = ifpflag; \ - fr->fr_ipf->fri_sifpidx = dynamic; \ - } else if (pooled || hashed) \ - fr->fr_satype = FRI_LOOKUP;) - } + { build_srcaddr_af(fr, &$3); } ; srcport: @@ -770,10 +871,10 @@ fromport: srcportlist: portnum { DOREM(fr->fr_scmp = FR_EQUAL; fr->fr_sport = $1;) } - | portnum ':' portnum + | portnum ':' portnum { DOREM(fr->fr_scmp = FR_INCRANGE; fr->fr_sport = $1; \ fr->fr_stop = $3;) } - | portnum YY_RANGE_IN portnum + | portnum YY_RANGE_IN portnum { DOREM(fr->fr_scmp = FR_INRANGE; fr->fr_sport = $1; \ fr->fr_stop = $3;) } | srcportlist lmore portnum @@ -794,34 +895,25 @@ dstobject: ; dstaddr: - addr { DOREM(bcopy(&($1.a), &fr->fr_ip.fi_dst, sizeof($1.a)); \ - bcopy(&($1.m), &fr->fr_mip.fi_dst, sizeof($1.m)); \ - if (dynamic != -1) { \ - fr->fr_datype = ifpflag; \ - fr->fr_ipf->fri_difpidx = dynamic; \ - } else if (pooled || hashed) \ - fr->fr_datype = FRI_LOOKUP;) + addr { if (($1.f != AF_UNSPEC) && (frc->fr_family != AF_UNSPEC) && + ($1.f != frc->fr_family)) + yyerror("1.src/dst address family mismatch"); + build_dstaddr_af(fr, &$1); } | lstart dstaddrlist lend ; dstaddrlist: - addr { DOREM(bcopy(&($1.a), &fr->fr_ip.fi_dst, sizeof($1.a)); \ - bcopy(&($1.m), &fr->fr_mip.fi_dst, sizeof($1.m)); \ - if (dynamic != -1) { \ - fr->fr_datype = ifpflag; \ - fr->fr_ipf->fri_difpidx = dynamic; \ - } else if (pooled || hashed) \ - fr->fr_datype = FRI_LOOKUP;) + addr { if (($1.f != AF_UNSPEC) && (frc->fr_family != AF_UNSPEC) && + ($1.f != frc->fr_family)) + yyerror("2.src/dst address family mismatch"); + build_dstaddr_af(fr, &$1); } | dstaddrlist lmore addr - { DOREM(bcopy(&($3.a), &fr->fr_ip.fi_dst, sizeof($3.a)); \ - bcopy(&($3.m), &fr->fr_mip.fi_dst, sizeof($3.m)); \ - if (dynamic != -1) { \ - fr->fr_datype = ifpflag; \ - fr->fr_ipf->fri_difpidx = dynamic; \ - } else if (pooled || hashed) \ - fr->fr_datype = FRI_LOOKUP;) + { if (($3.f != AF_UNSPEC) && (frc->fr_family != AF_UNSPEC) && + ($3.f != frc->fr_family)) + yyerror("3.src/dst address family mismatch"); + build_dstaddr_af(fr, &$3); } ; @@ -848,10 +940,10 @@ toport: dstportlist: portnum { DOREM(fr->fr_dcmp = FR_EQUAL; fr->fr_dport = $1;) } - | portnum ':' portnum + | portnum ':' portnum { DOREM(fr->fr_dcmp = FR_INCRANGE; fr->fr_dport = $1; \ fr->fr_dtop = $3;) } - | portnum YY_RANGE_IN portnum + | portnum YY_RANGE_IN portnum { DOREM(fr->fr_dcmp = FR_INRANGE; fr->fr_dport = $1; \ fr->fr_dtop = $3;) } | dstportlist lmore portnum @@ -865,141 +957,234 @@ dstportlist: ; addr: pool '/' YY_NUMBER { pooled = 1; + yyexpectaddr = 0; + $$.type = FRI_LOOKUP; + $$.v = 0; + $$.ifpos = -1; + $$.f = AF_UNSPEC; $$.a.iplookuptype = IPLT_POOL; $$.a.iplookupsubtype = 0; $$.a.iplookupnum = $3; } | pool '/' YY_STR { pooled = 1; + $$.ifpos = -1; + $$.f = AF_UNSPEC; + $$.type = FRI_LOOKUP; $$.a.iplookuptype = IPLT_POOL; $$.a.iplookupsubtype = 1; - strncpy($$.a.iplookupname, $3, - sizeof($$.a.iplookupname)); + $$.a.iplookupname = addname(&fr, $3); + } + | pool '=' '(' { yyexpectaddr = 1; + pooled = 1; } - | pool '=' '(' poollist ')' { pooled = 1; + poollist ')' { yyexpectaddr = 0; + $$.v = 0; + $$.ifpos = -1; + $$.f = AF_UNSPEC; + $$.type = FRI_LOOKUP; $$.a.iplookuptype = IPLT_POOL; $$.a.iplookupsubtype = 0; - $$.a.iplookupnum = makepool($4); } + $$.a.iplookupnum = makepool($5); + } | hash '/' YY_NUMBER { hashed = 1; + yyexpectaddr = 0; + $$.v = 0; + $$.ifpos = -1; + $$.f = AF_UNSPEC; + $$.type = FRI_LOOKUP; $$.a.iplookuptype = IPLT_HASH; $$.a.iplookupsubtype = 0; - $$.a.iplookupnum = $3; } - | hash '/' YY_STR { pooled = 1; + $$.a.iplookupnum = $3; + } + | hash '/' YY_STR { hashed = 1; + $$.type = FRI_LOOKUP; + $$.v = 0; + $$.ifpos = -1; + $$.f = AF_UNSPEC; $$.a.iplookuptype = IPLT_HASH; $$.a.iplookupsubtype = 1; - strncpy($$.a.iplookupname, $3, - sizeof($$.a.iplookupname)); + $$.a.iplookupname = addname(&fr, $3); + } + | hash '=' '(' { hashed = 1; + yyexpectaddr = 1; } - | hash '=' '(' addrlist ')' { hashed = 1; + addrlist ')' { yyexpectaddr = 0; + $$.v = 0; + $$.ifpos = -1; + $$.f = AF_UNSPEC; + $$.type = FRI_LOOKUP; $$.a.iplookuptype = IPLT_HASH; $$.a.iplookupsubtype = 0; - $$.a.iplookupnum = makehash($4); } - | ipaddr { bcopy(&$1, &$$, sizeof($$)); + $$.a.iplookupnum = makehash($5); + } + | ipaddr { $$ = $1; yyexpectaddr = 0; } ; ipaddr: IPFY_ANY { bzero(&($$), sizeof($$)); + $$.type = FRI_NORMAL; + $$.ifpos = -1; + yyexpectaddr = 0; + } + | hostname { $$.a = $1.adr; + $$.f = $1.f; + if ($1.f == AF_INET6) + fill6bits(128, $$.m.i6); + else if ($1.f == AF_INET) + fill6bits(32, $$.m.i6); + $$.v = ftov($1.f); + $$.ifpos = dynamic; + $$.type = FRI_NORMAL; + } + | hostname { yyresetdict(); } + maskspace { yysetdict(maskwords); + yyexpectaddr = 2; } + ipmask { ntomask($1.f, $5, $$.m.i6); + $$.a = $1.adr; + $$.a.i6[0] &= $$.m.i6[0]; + $$.a.i6[1] &= $$.m.i6[1]; + $$.a.i6[2] &= $$.m.i6[2]; + $$.a.i6[3] &= $$.m.i6[3]; + $$.f = $1.f; + $$.v = ftov($1.f); + $$.type = ifpflag; + $$.ifpos = dynamic; + if (ifpflag != 0 && $$.v == 0) { + if (frc->fr_family == AF_INET6){ + $$.v = 6; + $$.f = AF_INET6; + } else { + $$.v = 4; + $$.f = AF_INET; + } + } yyresetdict(); - yyexpectaddr = 0; } - | hostname { $$.a.in4 = $1; - $$.m.in4_addr = 0xffffffff; - yyexpectaddr = 0; } - | hostname { yyresetdict(); - $$.a.in4_addr = $1.s_addr; } - maskspace { yysetdict(maskwords); } - ipv4mask { $$.m.in4_addr = $5.s_addr; - $$.a.in4_addr &= $5.s_addr; - yyresetdict(); - yyexpectaddr = 0; } - | YY_IPV6 { bcopy(&$1, &$$.a, sizeof($$.a)); - fill6bits(128, (u_32_t *)&$$.m); + yyexpectaddr = 0; + } + | '(' YY_STR ')' { $$.type = FRI_DYNAMIC; + ifpflag = FRI_DYNAMIC; + $$.ifpos = addname(&fr, $2); + $$.lif = 0; + } + | '(' YY_STR ')' '/' + { ifpflag = FRI_DYNAMIC; yysetdict(maskwords); } + maskopts + { $$.type = ifpflag; + $$.ifpos = addname(&fr, $2); + $$.lif = 0; + if (frc->fr_family == AF_UNSPEC) + frc->fr_family = AF_INET; + if (ifpflag == FRI_DYNAMIC) { + ntomask(frc->fr_family, + $6, $$.m.i6); + } yyresetdict(); - yyexpectaddr = 0; } - | YY_IPV6 { yyresetdict(); - bcopy(&$1, &$$.a, sizeof($$.a)); } - maskspace { yysetdict(maskwords); } - ipv6mask { bcopy(&$5, &$$.m, sizeof($$.m)); + yyexpectaddr = 0; + } + | '(' YY_STR ':' YY_NUMBER ')' '/' + { ifpflag = FRI_DYNAMIC; yysetdict(maskwords); } + maskopts + { $$.type = ifpflag; + $$.ifpos = addname(&fr, $2); + $$.lif = $4; + if (frc->fr_family == AF_UNSPEC) + frc->fr_family = AF_INET; + if (ifpflag == FRI_DYNAMIC) { + ntomask(frc->fr_family, + $8, $$.m.i6); + } yyresetdict(); - yyexpectaddr = 0; } + yyexpectaddr = 0; + } ; + maskspace: '/' | IPFY_MASK ; -ipv4mask: - ipv4 { $$ = $1; } - | YY_HEX { $$.s_addr = htonl($1); } - | YY_NUMBER { ntomask(4, $1, (u_32_t *)&$$); } - | IPFY_BROADCAST { if (ifpflag == FRI_DYNAMIC) { - $$.s_addr = 0; +ipmask: ipv4 { $$ = count4bits($1.s_addr); } + | YY_HEX { $$ = count4bits(htonl($1)); } + | YY_NUMBER { $$ = $1; } + | YY_IPV6 { $$ = count6bits($1.i6); } + | maskopts { $$ = $1; } + ; + +maskopts: + IPFY_BROADCAST { if (ifpflag == FRI_DYNAMIC) { ifpflag = FRI_BROADCAST; - } else + } else { YYERROR; + } + $$ = 0; } | IPFY_NETWORK { if (ifpflag == FRI_DYNAMIC) { - $$.s_addr = 0; ifpflag = FRI_NETWORK; - } else + } else { YYERROR; + } + $$ = 0; } | IPFY_NETMASKED { if (ifpflag == FRI_DYNAMIC) { - $$.s_addr = 0; ifpflag = FRI_NETMASKED; - } else + } else { YYERROR; + } + $$ = 0; } | IPFY_PEER { if (ifpflag == FRI_DYNAMIC) { - $$.s_addr = 0; ifpflag = FRI_PEERADDR; - } else + } else { YYERROR; + } + $$ = 0; } + | YY_NUMBER { $$ = $1; } ; -ipv6mask: - YY_NUMBER { ntomask(6, $1, $$.i6); } - | IPFY_BROADCAST { if (ifpflag == FRI_DYNAMIC) { - bzero(&$$, sizeof($$)); - ifpflag = FRI_BROADCAST; - } else - YYERROR; - } - | IPFY_NETWORK { if (ifpflag == FRI_DYNAMIC) { - bzero(&$$, sizeof($$)); - ifpflag = FRI_BROADCAST; - } else +hostname: + ipv4 { $$.adr.in4 = $1; + if (frc->fr_family == AF_INET6) YYERROR; + $$.f = AF_INET; + yyexpectaddr = 2; } - | IPFY_NETMASKED { if (ifpflag == FRI_DYNAMIC) { - bzero(&$$, sizeof($$)); - ifpflag = FRI_BROADCAST; - } else + | YY_NUMBER { if (frc->fr_family == AF_INET6) YYERROR; + $$.adr.in4_addr = $1; + $$.f = AF_INET; + yyexpectaddr = 2; } - | IPFY_PEER { if (ifpflag == FRI_DYNAMIC) { - bzero(&$$, sizeof($$)); - ifpflag = FRI_BROADCAST; - } else + | YY_HEX { if (frc->fr_family == AF_INET6) YYERROR; + $$.adr.in4_addr = $1; + $$.f = AF_INET; + yyexpectaddr = 2; } - ; - -hostname: - ipv4 { $$ = $1; } - | YY_NUMBER { $$.s_addr = $1; } - | YY_HEX { $$.s_addr = $1; } - | YY_STR { $$.s_addr = lookuphost($1); + | YY_STR { if (lookuphost($1, &$$.adr) == 0) + $$.f = AF_INET; free($1); + yyexpectaddr = 2; + } + | YY_IPV6 { if (frc->fr_family == AF_INET) + YYERROR; + $$.adr = $1; + $$.f = AF_INET6; + yyexpectaddr = 2; } ; addrlist: ipaddr { $$ = newalist(NULL); - bcopy(&($1.a), &($$->al_i6addr), sizeof($1.a)); - bcopy(&($1.m), &($$->al_i6mask), sizeof($1.m)); } - | addrlist ',' ipaddr - { $$ = newalist($1); - bcopy(&($3.a), &($$->al_i6addr), sizeof($3.a)); - bcopy(&($3.m), &($$->al_i6mask), sizeof($3.m)); } + $$->al_family = $1.f; + $$->al_i6addr = $1.a; + $$->al_i6mask = $1.m; + } + | ipaddr ',' { yyexpectaddr = 1; } addrlist + { $$ = newalist($4); + $$->al_family = $1.f; + $$->al_i6addr = $1.a; + $$->al_i6mask = $1.m; + } ; pool: IPFY_POOL { yyexpectaddr = 0; yycont = NULL; yyresetdict(); } @@ -1010,53 +1195,70 @@ hash: IPFY_HASH { yyexpectaddr = 0; yycont = NULL; yyresetdict(); } poollist: ipaddr { $$ = newalist(NULL); - bcopy(&($1.a), &($$->al_i6addr), sizeof($1.a)); - bcopy(&($1.m), &($$->al_i6mask), sizeof($1.m)); } + $$->al_family = $1.f; + $$->al_i6addr = $1.a; + $$->al_i6mask = $1.m; + } | '!' ipaddr { $$ = newalist(NULL); $$->al_not = 1; - bcopy(&($2.a), &($$->al_i6addr), sizeof($2.a)); - bcopy(&($2.m), &($$->al_i6mask), sizeof($2.m)); } + $$->al_family = $2.f; + $$->al_i6addr = $2.a; + $$->al_i6mask = $2.m; + } | poollist ',' ipaddr { $$ = newalist($1); - bcopy(&($3.a), &($$->al_i6addr), sizeof($3.a)); - bcopy(&($3.m), &($$->al_i6mask), sizeof($3.m)); } + $$->al_family = $3.f; + $$->al_i6addr = $3.a; + $$->al_i6mask = $3.m; + } | poollist ',' '!' ipaddr { $$ = newalist($1); $$->al_not = 1; - bcopy(&($4.a), &($$->al_i6addr), sizeof($4.a)); - bcopy(&($4.m), &($$->al_i6mask), sizeof($4.m)); } + $$->al_family = $4.f; + $$->al_i6addr = $4.a; + $$->al_i6mask = $4.m; + } ; port: IPFY_PORT { yyexpectaddr = 0; yycont = NULL; + if (frc->fr_proto != 0 && + frc->fr_proto != IPPROTO_UDP && + frc->fr_proto != IPPROTO_TCP) + yyerror("port use incorrect"); } ; portc: port compare { $$ = $2; - yysetdict(NULL); } + yysetdict(NULL); + } | porteq { $$ = $1; } ; porteq: port '=' { $$ = FR_EQUAL; - yysetdict(NULL); } + yysetdict(NULL); + } ; portr: IPFY_PORT { yyexpectaddr = 0; yycont = NULL; - yysetdict(NULL); } + yysetdict(NULL); + } ; portcomp: portc portnum { $$.pc = $1; $$.p1 = $2; - yyresetdict(); } + yyresetdict(); + } ; portrange: portr portnum range portnum { $$.p1 = $2; $$.pc = $3; $$.p2 = $4; - yyresetdict(); } + yyresetdict(); + } ; icmp: | itype icode @@ -1070,8 +1272,30 @@ itype: seticmptype icmptype ; seticmptype: - IPFY_ICMPTYPE { setipftype(); - yysetdict(icmptypewords); } + IPFY_ICMPTYPE { if (frc->fr_family == AF_UNSPEC) + frc->fr_family = AF_INET; + if (frc->fr_family == AF_INET && + frc->fr_type == FR_T_IPF && + frc->fr_proto != IPPROTO_ICMP) { + yyerror("proto not icmp"); + } + if (frc->fr_family == AF_INET6 && + frc->fr_type == FR_T_IPF && + frc->fr_proto != IPPROTO_ICMPV6) { + yyerror("proto not ipv6-icmp"); + } + setipftype(); + DOALL(if (fr->fr_family == AF_INET) { \ + fr->fr_ip.fi_v = 4; \ + fr->fr_mip.fi_v = 0xf; \ + } + if (fr->fr_family == AF_INET6) { \ + fr->fr_ip.fi_v = 6; \ + fr->fr_mip.fi_v = 0xf; \ + } + ) + yysetdict(NULL); + } ; icode: | seticmpcode icmpcode @@ -1146,9 +1370,18 @@ stateopt: IPFY_LIMIT YY_NUMBER { DOALL(fr->fr_statemax = $2;) } | IPFY_STRICT { DOALL(if (fr->fr_proto != IPPROTO_TCP) { \ YYERROR; \ - } else \ + } else if (fr->fr_flags & FR_STLOOSE) {\ + YYERROR; \ + } else \ fr->fr_flags |= FR_STSTRICT;) } + | IPFY_LOOSE { DOALL(if (fr->fr_proto != IPPROTO_TCP) { \ + YYERROR; \ + } else if (fr->fr_flags & FR_STSTRICT){\ + YYERROR; \ + } else \ + fr->fr_flags |= FR_STLOOSE;) + } | IPFY_NEWISN { DOALL(if (fr->fr_proto != IPPROTO_TCP) { \ YYERROR; \ } else \ @@ -1162,10 +1395,32 @@ stateopt: | IPFY_AGE YY_NUMBER '/' YY_NUMBER { DOALL(fr->fr_age[0] = $2; \ fr->fr_age[1] = $4;) } + | IPFY_ICMPHEAD groupname + { DOALL(seticmphead(&fr, $2);) + free($2); + } + | IPFY_NOLOG + { DOALL(fr->fr_nostatelog = 1;) } + | IPFY_RPC + { DOALL(fr->fr_rpc = 1;) } + | IPFY_RPC IPFY_IN YY_STR + { DOALL(fr->fr_rpc = 1;) } + | IPFY_MAX_SRCS YY_NUMBER + { DOALL(fr->fr_srctrack.ht_max_nodes = $2;) } + | IPFY_MAX_PER_SRC YY_NUMBER + { DOALL(fr->fr_srctrack.ht_max_per_node = $2; \ + fr->fr_srctrack.ht_netmask = \ + fr->fr_family == AF_INET ? 32: 128;) + } + | IPFY_MAX_PER_SRC YY_NUMBER '/' YY_NUMBER + { DOALL(fr->fr_srctrack.ht_max_per_node = $2; \ + fr->fr_srctrack.ht_netmask = $4;) + } ; portnum: - servicename { if (getport(frc, $1, &($$)) == -1) + servicename { if (getport(frc, $1, + &($$), NULL) == -1) yyerror("service unknown"); $$ = ntohs($$); free($1); @@ -1188,14 +1443,14 @@ withopt: | notwith opttype { DOALL(fr->fr_mflx |= $2;) } | ipopt ipopts { yyresetdict(); } | notwith ipopt ipopts { yyresetdict(); } - | startv6hdrs ipv6hdrs { yyresetdict(); } + | startv6hdr ipv6hdrs { yyresetdict(); } ; ipopt: IPFY_OPT { yysetdict(ipv4optwords); } ; -startv6hdrs: - IPF6_V6HDRS { if (use_inet6 == 0) +startv6hdr: + IPFY_V6HDR { if (frc->fr_family != AF_INET6) yyerror("only available with IPv6"); yysetdict(ipv6optwords); } @@ -1222,9 +1477,18 @@ opttype: | IPFY_BROADCAST { $$ = FI_BROADCAST; } | IPFY_STATE { $$ = FI_STATE; } | IPFY_OOW { $$ = FI_OOW; } + | IPFY_AH { $$ = FI_AH; } + | IPFY_V6HDRS { $$ = FI_V6EXTHDR; } ; ipopts: optlist { DOALL(fr->fr_mip.fi_optmsk |= $1; + if (fr->fr_family == AF_UNSPEC) { + fr->fr_family = AF_INET; + fr->fr_ip.fi_v = 4; + fr->fr_mip.fi_v = 0xf; + } else if (fr->fr_family != AF_INET) { + YYERROR; + } if (!nowith) fr->fr_ip.fi_optmsk |= $1;) } @@ -1264,22 +1528,11 @@ seclevel: ; icmptype: - YY_NUMBER { $$ = $1; } - | IPFY_ICMPT_UNR { $$ = ICMP_UNREACH; } - | IPFY_ICMPT_ECHO { $$ = ICMP_ECHO; } - | IPFY_ICMPT_ECHOR { $$ = ICMP_ECHOREPLY; } - | IPFY_ICMPT_SQUENCH { $$ = ICMP_SOURCEQUENCH; } - | IPFY_ICMPT_REDIR { $$ = ICMP_REDIRECT; } - | IPFY_ICMPT_TIMEX { $$ = ICMP_TIMXCEED; } - | IPFY_ICMPT_PARAMP { $$ = ICMP_PARAMPROB; } - | IPFY_ICMPT_TIMEST { $$ = ICMP_TSTAMP; } - | IPFY_ICMPT_TIMESTREP { $$ = ICMP_TSTAMPREPLY; } - | IPFY_ICMPT_INFOREQ { $$ = ICMP_IREQ; } - | IPFY_ICMPT_INFOREP { $$ = ICMP_IREQREPLY; } - | IPFY_ICMPT_MASKREQ { $$ = ICMP_MASKREQ; } - | IPFY_ICMPT_MASKREP { $$ = ICMP_MASKREPLY; } - | IPFY_ICMPT_ROUTERAD { $$ = ICMP_ROUTERADVERT; } - | IPFY_ICMPT_ROUTERSOL { $$ = ICMP_ROUTERSOLICIT; } + YY_NUMBER { $$ = $1; } + | YY_STR { $$ = geticmptype(frc->fr_family, $1); + if ($$ == -1) + yyerror("unrecognised icmp type"); + } ; icmpcode: @@ -1314,7 +1567,8 @@ opt: | IPFY_IPOPT_SEC { $$ = getoptbyvalue(IPOPT_SECURITY); } | IPFY_IPOPT_LSRR { $$ = getoptbyvalue(IPOPT_LSRR); } | IPFY_IPOPT_ESEC { $$ = getoptbyvalue(IPOPT_E_SEC); } - | IPFY_IPOPT_CIPSO { $$ = getoptbyvalue(IPOPT_CIPSO); } + | IPFY_IPOPT_CIPSO { $$ = getoptbyvalue(IPOPT_CIPSO); } + | IPFY_IPOPT_CIPSO doi { $$ = getoptbyvalue(IPOPT_CIPSO); } | IPFY_IPOPT_SATID { $$ = getoptbyvalue(IPOPT_SATID); } | IPFY_IPOPT_SSRR { $$ = getoptbyvalue(IPOPT_SSRR); } | IPFY_IPOPT_ADDEXT { $$ = getoptbyvalue(IPOPT_ADDEXT); } @@ -1329,6 +1583,13 @@ opt: | IPFY_IPOPT_UMP { $$ = getoptbyvalue(IPOPT_UMP); } | setsecclass secname { DOALL(fr->fr_mip.fi_secmsk |= $2; + if (fr->fr_family == AF_UNSPEC) { + fr->fr_family = AF_INET; + fr->fr_ip.fi_v = 4; + fr->fr_mip.fi_v = 0xf; + } else if (fr->fr_family != AF_INET) { + YYERROR; + } if (!nowith) fr->fr_ip.fi_secmsk |= $2;) $$ = 0; @@ -1337,7 +1598,15 @@ opt: ; setsecclass: - IPFY_SECCLASS { yysetdict(ipv4secwords); } + IPFY_SECCLASS { yysetdict(ipv4secwords); } + ; + +doi: IPFY_DOI YY_NUMBER { DOALL(fr->fr_doimask = 0xffffffff; \ + if (!nowith) \ + fr->fr_doi = $2;) } + | IPFY_DOI YY_HEX { DOALL(fr->fr_doimask = 0xffffffff; \ + if (!nowith) \ + fr->fr_doi = $2;) } ; ipv6hdr: @@ -1463,7 +1732,7 @@ ipv4: ipv4_24 '.' YY_NUMBER %% -static struct wordtab ipfwords[95] = { +static struct wordtab ipfwords[] = { { "age", IPFY_AGE }, { "ah", IPFY_AH }, { "all", IPFY_ALL }, @@ -1481,10 +1750,16 @@ static struct wordtab ipfwords[95] = { #endif { "call", IPFY_CALL }, { "code", IPFY_ICMPCODE }, + { "comment", IPFY_COMMENT }, { "count", IPFY_COUNT }, + { "decapsulate", IPFY_DECAPS }, + { "dstlist", IPFY_DSTLIST }, + { "doi", IPFY_DOI }, { "dup-to", IPFY_DUPTO }, { "eq", YY_CMP_EQ }, { "esp", IPFY_ESP }, + { "exp", IPFY_IPFEXPR }, + { "family", IPFY_FAMILY }, { "fastroute", IPFY_FROUTE }, { "first", IPFY_FIRST }, { "flags", IPFY_FLAGS }, @@ -1497,20 +1772,27 @@ static struct wordtab ipfwords[95] = { { "gt", YY_CMP_GT }, { "head", IPFY_HEAD }, { "icmp", IPFY_ICMP }, + { "icmp-head", IPFY_ICMPHEAD }, { "icmp-type", IPFY_ICMPTYPE }, { "in", IPFY_IN }, { "in-via", IPFY_INVIA }, + { "inet", IPFY_INET }, + { "inet6", IPFY_INET6 }, { "ipopt", IPFY_IPOPTS }, { "ipopts", IPFY_IPOPTS }, { "keep", IPFY_KEEP }, + { "l5-as", IPFY_L5AS }, { "le", YY_CMP_LE }, { "level", IPFY_LEVEL }, { "limit", IPFY_LIMIT }, { "log", IPFY_LOG }, + { "loose", IPFY_LOOSE }, { "lowttl", IPFY_LOWTTL }, { "lt", YY_CMP_LT }, { "mask", IPFY_MASK }, { "match-tag", IPFY_MATCHTAG }, + { "max-per-src", IPFY_MAX_PER_SRC }, + { "max-srcs", IPFY_MAX_SRCS }, { "mbcast", IPFY_MBCAST }, { "mcast", IPFY_MULTICAST }, { "multicast", IPFY_MULTICAST }, @@ -1520,6 +1802,7 @@ static struct wordtab ipfwords[95] = { { "newisn", IPFY_NEWISN }, { "no", IPFY_NO }, { "no-icmp-err", IPFY_NOICMPERR }, + { "nolog", IPFY_NOLOG }, { "nomatch", IPFY_NOMATCH }, { "now", IPFY_NOW }, { "not", IPFY_NOT }, @@ -1540,7 +1823,10 @@ static struct wordtab ipfwords[95] = { { "return-icmp-as-dest", IPFY_RETICMPASDST }, { "return-rst", IPFY_RETRST }, { "route-to", IPFY_ROUTETO }, + { "rule-ttl", IPFY_RULETTL }, + { "rpc", IPFY_RPC }, { "sec-class", IPFY_SECCLASS }, + { "set", IPFY_SET }, { "set-tag", IPFY_SETTAG }, { "skip", IPFY_SKIP }, { "short", IPFY_SHORT }, @@ -1554,19 +1840,20 @@ static struct wordtab ipfwords[95] = { { "to", IPFY_TO }, { "ttl", IPFY_TTL }, { "udp", IPFY_UDP }, - { "v6hdrs", IPF6_V6HDRS }, + { "v6hdr", IPFY_V6HDR }, + { "v6hdrs", IPFY_V6HDRS }, { "with", IPFY_WITH }, { NULL, 0 } }; -static struct wordtab addrwords[4] = { +static struct wordtab addrwords[] = { { "any", IPFY_ANY }, { "hash", IPFY_HASH }, { "pool", IPFY_POOL }, { NULL, 0 } }; -static struct wordtab maskwords[5] = { +static struct wordtab maskwords[] = { { "broadcast", IPFY_BROADCAST }, { "netmasked", IPFY_NETMASKED }, { "network", IPFY_NETWORK }, @@ -1574,26 +1861,7 @@ static struct wordtab maskwords[5] = { { NULL, 0 } }; -static struct wordtab icmptypewords[16] = { - { "echo", IPFY_ICMPT_ECHO }, - { "echorep", IPFY_ICMPT_ECHOR }, - { "inforeq", IPFY_ICMPT_INFOREQ }, - { "inforep", IPFY_ICMPT_INFOREP }, - { "maskrep", IPFY_ICMPT_MASKREP }, - { "maskreq", IPFY_ICMPT_MASKREQ }, - { "paramprob", IPFY_ICMPT_PARAMP }, - { "redir", IPFY_ICMPT_REDIR }, - { "unreach", IPFY_ICMPT_UNR }, - { "routerad", IPFY_ICMPT_ROUTERAD }, - { "routersol", IPFY_ICMPT_ROUTERSOL }, - { "squench", IPFY_ICMPT_SQUENCH }, - { "timest", IPFY_ICMPT_TIMEST }, - { "timestrep", IPFY_ICMPT_TIMESTREP }, - { "timex", IPFY_ICMPT_TIMEX }, - { NULL, 0 }, -}; - -static struct wordtab icmpcodewords[17] = { +static struct wordtab icmpcodewords[] = { { "cutoff-preced", IPFY_ICMPC_CUTPRE }, { "filter-prohib", IPFY_ICMPC_FLTPRO }, { "isolate", IPFY_ICMPC_ISOLATE }, @@ -1613,7 +1881,7 @@ static struct wordtab icmpcodewords[17] = { { NULL, 0 }, }; -static struct wordtab ipv4optwords[25] = { +static struct wordtab ipv4optwords[] = { { "addext", IPFY_IPOPT_ADDEXT }, { "cipso", IPFY_IPOPT_CIPSO }, { "dps", IPFY_IPOPT_DPS }, @@ -1641,7 +1909,7 @@ static struct wordtab ipv4optwords[25] = { { NULL, 0 }, }; -static struct wordtab ipv4secwords[9] = { +static struct wordtab ipv4secwords[] = { { "confid", IPFY_SEC_CONF }, { "reserv-1", IPFY_SEC_RSV1 }, { "reserv-2", IPFY_SEC_RSV2 }, @@ -1653,7 +1921,7 @@ static struct wordtab ipv4secwords[9] = { { NULL, 0 }, }; -static struct wordtab ipv6optwords[9] = { +static struct wordtab ipv6optwords[] = { { "dstopts", IPFY_IPV6OPT_DSTOPTS }, { "esp", IPFY_IPV6OPT_ESP }, { "frag", IPFY_IPV6OPT_FRAG }, @@ -1665,7 +1933,7 @@ static struct wordtab ipv6optwords[9] = { { NULL, 0 }, }; -static struct wordtab logwords[33] = { +static struct wordtab logwords[] = { { "kern", IPFY_FAC_KERN }, { "user", IPFY_FAC_USER }, { "mail", IPFY_FAC_MAIL }, @@ -1751,7 +2019,7 @@ FILE *fp; ipffd = fd; for (i = 0; i <= IPL_LOGMAX; i++) - ipfioctl[i] = iocfuncs[i]; + ipfioctls[i] = iocfuncs[i]; ipfaddfunc = addfunc; if (feof(fp)) @@ -1779,23 +2047,29 @@ static void newrule() { frentry_t *frn; - frn = (frentry_t *)calloc(1, sizeof(frentry_t)); + frn = allocfr(); for (fr = frtop; fr != NULL && fr->fr_next != NULL; fr = fr->fr_next) ; - if (fr != NULL) + if (fr != NULL) { fr->fr_next = frn; - if (frtop == NULL) + frn->fr_pnext = &fr->fr_next; + } + if (frtop == NULL) { frtop = frn; + frn->fr_pnext = &frtop; + } fr = frn; frc = frn; fr->fr_loglevel = 0xffff; fr->fr_isc = (void *)-1; fr->fr_logtag = FR_NOLOGTAG; fr->fr_type = FR_T_NONE; - if (use_inet6 != 0) - fr->fr_v = 6; - else - fr->fr_v = 4; + fr->fr_flineno = yylineNum; + + if (use_inet6 == 1) + fr->fr_family = AF_INET6; + else if (use_inet6 == -1) + fr->fr_family = AF_INET; nrules = 1; } @@ -1808,7 +2082,13 @@ static void setipftype() fr->fr_type = FR_T_IPF; fr->fr_data = (void *)calloc(sizeof(fripf_t), 1); fr->fr_dsize = sizeof(fripf_t); - fr->fr_ip.fi_v = frc->fr_v; + fr->fr_family = frc->fr_family; + if (fr->fr_family == AF_INET) { + fr->fr_ip.fi_v = 4; + } + else if (fr->fr_family == AF_INET6) { + fr->fr_ip.fi_v = 6; + } fr->fr_mip.fi_v = 0xf; fr->fr_ipf->fri_sifpidx = -1; fr->fr_ipf->fri_difpidx = -1; @@ -1831,10 +2111,13 @@ static frentry_t *addrule() count = nrules; f = f2; for (f1 = frc; count > 0; count--, f1 = f1->fr_next) { - f->fr_next = (frentry_t *)calloc(sizeof(*f), 1); + f->fr_next = allocfr(); + if (f->fr_next == NULL) + return NULL; + f->fr_next->fr_pnext = &f->fr_next; added++; f = f->fr_next; - bcopy(f1, f, sizeof(*f)); + *f = *f1; f->fr_next = NULL; if (f->fr_caddr != NULL) { f->fr_caddr = malloc(f->fr_dsize); @@ -1846,10 +2129,11 @@ static frentry_t *addrule() } -static u_32_t lookuphost(name) -char *name; +static int +lookuphost(name, addrp) + char *name; + i6addr_t *addrp; { - u_32_t addr; int i; hashed = 0; @@ -1857,19 +2141,20 @@ char *name; dynamic = -1; for (i = 0; i < 4; i++) { - if (strncmp(name, frc->fr_ifnames[i], - sizeof(frc->fr_ifnames[i])) == 0) { + if (fr->fr_ifnames[i] == -1) + continue; + if (strcmp(name, fr->fr_names + fr->fr_ifnames[i]) == 0) { ifpflag = FRI_DYNAMIC; - dynamic = i; - return 0; + dynamic = addname(&fr, name); + return 1; } } - if (gethost(name, &addr) == -1) { + if (gethost(AF_INET, name, addrp) == -1) { fprintf(stderr, "unknown name \"%s\"\n", name); - return 0; + return -1; } - return addr; + return 0; } @@ -1891,7 +2176,7 @@ char *phrase; fprintf(stderr, "cannot mix IPF and BPF matching\n"); return; } - fr->fr_v = v; + fr->fr_family = vtof(v); fr->fr_type = FR_T_BPFOPC; if (!strncmp(phrase, "0x", 2)) { @@ -1986,8 +2271,9 @@ alist_t *ptr; } -static int makepool(list) -alist_t *list; +static int +makepool(list) + alist_t *list; { ip_pool_node_t *n, *top; ip_pool_t pool; @@ -1999,10 +2285,30 @@ alist_t *list; top = calloc(1, sizeof(*top)); if (top == NULL) return 0; - + for (n = top, a = list; (n != NULL) && (a != NULL); a = a->al_next) { - n->ipn_addr.adf_addr.in4.s_addr = a->al_1; - n->ipn_mask.adf_addr.in4.s_addr = a->al_2; + if (use_inet6 == 1) { +#ifdef AF_INET6 + n->ipn_addr.adf_family = AF_INET6; + n->ipn_addr.adf_addr = a->al_i6addr; + n->ipn_addr.adf_len = offsetof(addrfamily_t, + adf_addr) + 16; + n->ipn_mask.adf_family = AF_INET6; + n->ipn_mask.adf_addr = a->al_i6mask; + n->ipn_mask.adf_len = offsetof(addrfamily_t, + adf_addr) + 16; + +#endif + } else { + n->ipn_addr.adf_family = AF_INET; + n->ipn_addr.adf_addr.in4.s_addr = a->al_1; + n->ipn_addr.adf_len = offsetof(addrfamily_t, + adf_addr) + 4; + n->ipn_mask.adf_family = AF_INET; + n->ipn_mask.adf_addr.in4.s_addr = a->al_2; + n->ipn_mask.adf_len = offsetof(addrfamily_t, + adf_addr) + 4; + } n->ipn_info = a->al_not; if (a->al_next != NULL) { n->ipn_next = calloc(1, sizeof(*n)); @@ -2013,7 +2319,7 @@ alist_t *list; bzero((char *)&pool, sizeof(pool)); pool.ipo_unit = IPL_LOGIPF; pool.ipo_list = top; - num = load_pool(&pool, ipfioctl[IPL_LOGLOOKUP]); + num = load_pool(&pool, ipfioctls[IPL_LOGLOOKUP]); while ((n = top) != NULL) { top = n->ipn_next; @@ -2036,10 +2342,17 @@ alist_t *list; top = calloc(1, sizeof(*top)); if (top == NULL) return 0; - + for (n = top, a = list; (n != NULL) && (a != NULL); a = a->al_next) { - n->ipe_addr.in4_addr = a->al_1; - n->ipe_mask.in4_addr = a->al_2; + if (a->al_family == AF_INET6) { + n->ipe_family = AF_INET6; + n->ipe_addr = a->al_i6addr; + n->ipe_mask = a->al_i6mask; + } else { + n->ipe_family = AF_INET; + n->ipe_addr.in4_addr = a->al_1; + n->ipe_mask.in4_addr = a->al_2; + } n->ipe_value = 0; if (a->al_next != NULL) { n->ipe_next = calloc(1, sizeof(*n)); @@ -2052,7 +2365,7 @@ alist_t *list; iph.iph_type = IPHASH_LOOKUP; *iph.iph_name = '\0'; - if (load_hash(&iph, top, ipfioctl[IPL_LOGLOOKUP]) == 0) + if (load_hash(&iph, top, ipfioctls[IPL_LOGLOOKUP]) == 0) sscanf(iph.iph_name, "%u", &num); else num = 0; @@ -2065,7 +2378,7 @@ alist_t *list; } -void ipf_addrule(fd, ioctlfunc, ptr) +int ipf_addrule(fd, ioctlfunc, ptr) int fd; ioctlfunc_t ioctlfunc; void *ptr; @@ -2075,7 +2388,7 @@ void *ptr; ipfobj_t obj; if (ptr == NULL) - return; + return 0; fr = ptr; add = 0; @@ -2083,7 +2396,7 @@ void *ptr; bzero((char *)&obj, sizeof(obj)); obj.ipfo_rev = IPFILTER_VERSION; - obj.ipfo_size = sizeof(*fr); + obj.ipfo_size = fr->fr_size; obj.ipfo_type = IPFOBJ_FRENTRY; obj.ipfo_ptr = ptr; @@ -2118,8 +2431,11 @@ void *ptr; if ((opts & OPT_ZERORULEST) != 0) { if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { if ((opts & OPT_DONOTHING) == 0) { - fprintf(stderr, "%d:", yylineNum); - perror("ioctl(SIOCZRLST)"); + char msg[80]; + + sprintf(msg, "%d:ioctl(zero rule)", + fr->fr_flineno); + return ipf_perror_fd(fd, ioctlfunc, msg); } } else { #ifdef USE_QUAD_T @@ -2134,19 +2450,26 @@ void *ptr; } } else if ((opts & OPT_REMOVE) != 0) { if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) { - if ((opts & OPT_DONOTHING) != 0) { - fprintf(stderr, "%d:", yylineNum); - perror("ioctl(delete rule)"); + if ((opts & OPT_DONOTHING) == 0) { + char msg[80]; + + sprintf(msg, "%d:ioctl(delete rule)", + fr->fr_flineno); + return ipf_perror_fd(fd, ioctlfunc, msg); } } } else { if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { - if (!(opts & OPT_DONOTHING)) { - fprintf(stderr, "%d:", yylineNum); - perror("ioctl(add/insert rule)"); + if ((opts & OPT_DONOTHING) == 0) { + char msg[80]; + + sprintf(msg, "%d:ioctl(add/insert rule)", + fr->fr_flineno); + return ipf_perror_fd(fd, ioctlfunc, msg); } } } + return 0; } static void setsyslog() @@ -2168,9 +2491,16 @@ frentry_t *fr; { frentry_t *f; - for (f = frold; f != NULL; f = f->fr_next) - if (strncmp(f->fr_grhead, fr->fr_group, FR_GROUPLEN) == 0) + for (f = frold; f != NULL; f = f->fr_next) { + if (f->fr_grhead == -1 && fr->fr_group == -1) + break; + if (f->fr_grhead == -1 || fr->fr_group == -1) + continue; + if (strcmp(f->fr_names + f->fr_grhead, + fr->fr_names + fr->fr_group) == 0) break; + } + if (f == NULL) return; @@ -2183,8 +2513,8 @@ frentry_t *fr; if (f->fr_type != fr->fr_type || f->fr_type != FR_T_IPF) return; - if (fr->fr_v == 0 && f->fr_v != 0) - fr->fr_v = f->fr_v; + if (fr->fr_family == 0 && f->fr_family != 0) + fr->fr_family = f->fr_family; if (fr->fr_mproto == 0 && f->fr_mproto != 0) fr->fr_mproto = f->fr_mproto; @@ -2192,6 +2522,218 @@ frentry_t *fr; fr->fr_proto = f->fr_proto; if ((fr->fr_mproto == 0) && ((fr->fr_flx & FI_TCPUDP) == 0) && - ((f->fr_flx & FI_TCPUDP) != 0)) + ((f->fr_flx & FI_TCPUDP) != 0)) { fr->fr_flx |= FI_TCPUDP; + fr->fr_mflx |= FI_TCPUDP; + } +} + + +static void doipfexpr(line) +char *line; +{ + int *array; + char *error; + + array = parseipfexpr(line, &error); + if (array == NULL) { + fprintf(stderr, "%s:", error); + yyerror("error parsing ipf matching expression"); + return; + } + + fr->fr_type = FR_T_IPFEXPR; + fr->fr_data = array; + fr->fr_dsize = array[0] * sizeof(*array); +} + + +static void do_tuneint(varname, value) +char *varname; +int value; +{ + char buffer[80]; + + strncpy(buffer, varname, 60); + buffer[59] = '\0'; + strcat(buffer, "="); + sprintf(buffer, "%u", value); + ipf_dotuning(ipffd, buffer, ioctl); +} + + +static void do_tunestr(varname, value) +char *varname, *value; +{ + + if (!strcasecmp(value, "true")) { + do_tuneint(varname, 1); + } else if (!strcasecmp(value, "false")) { + do_tuneint(varname, 0); + } else { + yyerror("did not find true/false where expected"); + } +} + + +static void setifname(frp, idx, name) +frentry_t **frp; +int idx; +char *name; +{ + int pos; + + pos = addname(frp, name); + if (pos == -1) + return; + (*frp)->fr_ifnames[idx] = pos; +} + + +static int addname(frp, name) +frentry_t **frp; +char *name; +{ + frentry_t *f; + int nlen; + int pos; + + nlen = strlen(name) + 1; + f = realloc(*frp, (*frp)->fr_size + nlen); + if (*frp == frc) + frc = f; + *frp = f; + if (f == NULL) + return -1; + if (f->fr_pnext != NULL) + *f->fr_pnext = f; + f->fr_size += nlen; + pos = f->fr_namelen; + f->fr_namelen += nlen; + strcpy(f->fr_names + pos, name); + f->fr_names[f->fr_namelen] = '\0'; + return pos; +} + + +static frentry_t *allocfr() +{ + frentry_t *fr; + + fr = calloc(1, sizeof(*fr)); + if (fr != NULL) { + fr->fr_size = sizeof(*fr); + fr->fr_comment = -1; + fr->fr_group = -1; + fr->fr_grhead = -1; + fr->fr_icmphead = -1; + fr->fr_ifnames[0] = -1; + fr->fr_ifnames[1] = -1; + fr->fr_ifnames[2] = -1; + fr->fr_ifnames[3] = -1; + fr->fr_tif.fd_name = -1; + fr->fr_rif.fd_name = -1; + fr->fr_dif.fd_name = -1; + } + return fr; +} + + +static void setgroup(frp, name) +frentry_t **frp; +char *name; +{ + int pos; + + pos = addname(frp, name); + if (pos == -1) + return; + (*frp)->fr_group = pos; +} + + +static void setgrhead(frp, name) +frentry_t **frp; +char *name; +{ + int pos; + + pos = addname(frp, name); + if (pos == -1) + return; + (*frp)->fr_grhead = pos; +} + + +static void seticmphead(frp, name) +frentry_t **frp; +char *name; +{ + int pos; + + pos = addname(frp, name); + if (pos == -1) + return; + (*frp)->fr_icmphead = pos; +} + + +static void +build_dstaddr_af(fp, ptr) + frentry_t *fp; + void *ptr; +{ + struct ipp_s *ipp = ptr; + frentry_t *f = fp; + + if (f->fr_family != AF_UNSPEC && ipp->f == AF_UNSPEC) { + ipp->f = f->fr_family; + ipp->v = f->fr_ip.fi_v; + } + if (ipp->f == AF_INET) + ipp->v = 4; + else if (ipp->f == AF_INET6) + ipp->v = 6; + + for (; f != NULL; f = f->fr_next) { + f->fr_ip.fi_dst = ipp->a; + f->fr_mip.fi_dst = ipp->m; + f->fr_family = ipp->f; + f->fr_ip.fi_v = ipp->v; + f->fr_mip.fi_v = 0xf; + f->fr_datype = ipp->type; + if (ipp->ifpos != -1) + f->fr_ipf->fri_difpidx = ipp->ifpos; + } + fr = NULL; +} + + +static void +build_srcaddr_af(fp, ptr) + frentry_t *fp; + void *ptr; +{ + struct ipp_s *ipp = ptr; + frentry_t *f = fp; + + if (f->fr_family != AF_UNSPEC && ipp->f == AF_UNSPEC) { + ipp->f = f->fr_family; + ipp->v = f->fr_ip.fi_v; + } + if (ipp->f == AF_INET) + ipp->v = 4; + else if (ipp->f == AF_INET6) + ipp->v = 6; + + for (; f != NULL; f = f->fr_next) { + f->fr_ip.fi_src = ipp->a; + f->fr_mip.fi_src = ipp->m; + f->fr_family = ipp->f; + f->fr_ip.fi_v = ipp->v; + f->fr_mip.fi_v = 0xf; + f->fr_satype = ipp->type; + f->fr_ipf->fri_sifpidx = ipp->ifpos; + } + fr = NULL; } diff --git a/tools/ipfcomp.c b/tools/ipfcomp.c index aa25c774e9586..da9d11afefd15 100644 --- a/tools/ipfcomp.c +++ b/tools/ipfcomp.c @@ -1,11 +1,11 @@ /* - * Copyright (C) 2001-2005 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #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: ipfcomp.c,v 1.24.2.7 2007/05/01 22:15:00 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #include "ipf.h" @@ -61,7 +61,7 @@ static FILE *cfile = NULL; * required. */ void printc(fr) -frentry_t *fr; + frentry_t *fr; { fripf_t *ipf; u_long *ulp; @@ -69,7 +69,7 @@ frentry_t *fr; FILE *fp; int i; - if (fr->fr_v != 4) + if (fr->fr_family == 6) return; if ((fr->fr_type != FR_T_IPF) && (fr->fr_type != FR_T_NONE)) return; @@ -85,7 +85,7 @@ frentry_t *fr; fp = cfile; if (count == 0) { fprintf(fp, "/*\n"); - fprintf(fp, "* Copyright (C) 1993-2000 by Darren Reed.\n"); + fprintf(fp, "* Copyright (C) 2012 by Darren Reed.\n"); fprintf(fp, "*\n"); fprintf(fp, "* Redistribution and use in source and binary forms are permitted\n"); fprintf(fp, "* provided that this notice is preserved and due credit is given\n"); @@ -134,6 +134,9 @@ frentry_t *fr; fprintf(fp, "#endif /* _KERNEL */\n"); fprintf(fp, "\n"); fprintf(fp, "#ifdef IPFILTER_COMPILED\n"); + fprintf(fp, "\n"); + fprintf(fp, "extern ipf_main_softc_t ipfmain;\n"); + fprintf(fp, "\n"); } addrule(fp, fr); @@ -160,12 +163,14 @@ static frgroup_t *groups = NULL; static void addrule(fp, fr) -FILE *fp; -frentry_t *fr; + FILE *fp; + frentry_t *fr; { frentry_t *f, **fpp; frgroup_t *g; u_long *ulp; + char *ghead; + char *gname; char *and; int i; @@ -178,8 +183,10 @@ frentry_t *fr; } f->fr_next = NULL; + gname = FR_NAME(fr, fr_group); + for (g = groups; g != NULL; g = g->fg_next) - if ((strncmp(g->fg_name, f->fr_group, FR_GROUPLEN) == 0) && + if ((strncmp(g->fg_name, gname, FR_GROUPLEN) == 0) && (g->fg_flags == (f->fr_flags & FR_INOUT))) break; @@ -188,7 +195,7 @@ frentry_t *fr; g->fg_next = groups; groups = g; g->fg_head = f; - bcopy(f->fr_group, g->fg_name, FR_GROUPLEN); + strncpy(g->fg_name, gname, FR_GROUPLEN); g->fg_ref = 0; g->fg_flags = f->fr_flags & FR_INOUT; } @@ -217,10 +224,10 @@ static u_long ipf%s_rule_data_%s_%u[] = {\n", g->fg_ref++; - if (f->fr_grhead != 0) { + if (f->fr_grhead != -1) { + ghead = FR_NAME(f, fr_grhead); for (g = groups; g != NULL; g = g->fg_next) - if ((strncmp(g->fg_name, f->fr_grhead, - FR_GROUPLEN) == 0) && + if ((strncmp(g->fg_name, ghead, FR_GROUPLEN) == 0) && g->fg_flags == (f->fr_flags & FR_INOUT)) break; if (g == NULL) { @@ -228,7 +235,7 @@ static u_long ipf%s_rule_data_%s_%u[] = {\n", g->fg_next = groups; groups = g; g->fg_head = f; - bcopy(f->fr_grhead, g->fg_name, FR_GROUPLEN); + strncpy(g->fg_name, ghead, FR_GROUPLEN); g->fg_ref = 0; g->fg_flags = f->fr_flags & FR_INOUT; } @@ -237,7 +244,7 @@ static u_long ipf%s_rule_data_%s_%u[] = {\n", int intcmp(c1, c2) -const void *c1, *c2; + const void *c1, *c2; { const mc_t *i1 = (const mc_t *)c1, *i2 = (const mc_t *)c2; @@ -249,17 +256,17 @@ const void *c1, *c2; static void indent(fp, in) -FILE *fp; -int in; + FILE *fp; + int in; { for (; in; in--) fputc('\t', fp); } static void printeq(fp, var, m, max, v) -FILE *fp; -char *var; -int m, max, v; + FILE *fp; + char *var; + int m, max, v; { if (m == max) fprintf(fp, "%s == %#x) {\n", var, v); @@ -274,9 +281,9 @@ int m, max, v; * v - required address */ static void printipeq(fp, var, fl, m, v) -FILE *fp; -char *var; -int fl, m, v; + FILE *fp; + char *var; + int fl, m, v; { if (m == 0xffffffff) fprintf(fp, "%s ", var); @@ -288,9 +295,9 @@ int fl, m, v; void emit(num, dir, v, fr) -int num, dir; -void *v; -frentry_t *fr; + int num, dir; + void *v; + frentry_t *fr; { u_int incnt, outcnt; frgroup_t *g; @@ -340,8 +347,8 @@ frentry_t *fr; static void emitheader(grp, incount, outcount) -frgroup_t *grp; -u_int incount, outcount; + frgroup_t *grp; + u_int incount, outcount; { static FILE *fph = NULL; frgroup_t *g; @@ -380,7 +387,7 @@ extern frentry_t *ipfrule_match_out_%s __P((fr_info_t *, u_32_t *));\n\ extern frentry_t *ipf_rules_out_%s[%d];\n", grp->fg_name, grp->fg_name, outcount); - for (g = groups; g != g; g = g->fg_next) + for (g = groups; g != grp; g = g->fg_next) if ((strncmp(g->fg_name, grp->fg_name, FR_GROUPLEN) == 0) && g->fg_flags == grp->fg_flags) @@ -432,11 +439,11 @@ int ipfrule_remove()\n\ static void emitGroup(num, dir, v, fr, group, incount, outcount) -int num, dir; -void *v; -frentry_t *fr; -char *group; -u_int incount, outcount; + int num, dir; + void *v; + frentry_t *fr; + char *group; + u_int incount, outcount; { static FILE *fp = NULL; static int header[2] = { 0, 0 }; @@ -512,9 +519,8 @@ u_int incount, outcount; if ((i & 1) == 0) { fprintf(fp, "\n\t"); } - fprintf(fp, - "(frentry_t *)&in_rule_%s_%d", - f->fr_group, i); + fprintf(fp, "(frentry_t *)&in_rule_%s_%d", + FR_NAME(f, fr_group), i); if (i + 1 < incount) fprintf(fp, ", "); i++; @@ -532,9 +538,8 @@ u_int incount, outcount; if ((i & 1) == 0) { fprintf(fp, "\n\t"); } - fprintf(fp, - "(frentry_t *)&out_rule_%s_%d", - f->fr_group, i); + fprintf(fp, "(frentry_t *)&out_rule_%s_%d", + FR_NAME(f, fr_group), i); if (i + 1 < outcount) fprintf(fp, ", "); i++; @@ -584,7 +589,7 @@ u_int incount, outcount; switch(m[i].c) { case FRC_IFN : - if (*fr->fr_ifname) + if (fr->fr_ifnames[0] != -1) m[i].s = 1; break; case FRC_V : @@ -938,11 +943,11 @@ u_int incount, outcount; if (fr->fr_flags & FR_QUICK) { fprintf(fp, "return (frentry_t *)&%s_rule_%s_%d;\n", fr->fr_flags & FR_INQUE ? "in" : "out", - fr->fr_group, num); + FR_NAME(fr, fr_group), num); } else { fprintf(fp, "fr = (frentry_t *)&%s_rule_%s_%d;\n", fr->fr_flags & FR_INQUE ? "in" : "out", - fr->fr_group, num); + FR_NAME(fr, fr_group), num); } if (n == NULL) n = (mc_t *)malloc(sizeof(*n) * FRC_MAX); @@ -952,7 +957,7 @@ u_int incount, outcount; void printC(dir) -int dir; + int dir; { static mc_t *m = NULL; frgroup_t *g; @@ -975,10 +980,10 @@ int dir; * Now print out code to implement all of the rules. */ static void printCgroup(dir, top, m, group) -int dir; -frentry_t *top; -mc_t *m; -char *group; + int dir; + frentry_t *top; + mc_t *m; + char *group; { frentry_t *fr, *fr1; int i, n, rn; @@ -1025,13 +1030,14 @@ char *group; continue; if ((n & 0x0001) && - !strcmp(fr1->fr_ifname, fr->fr_ifname)) { + !strcmp(fr1->fr_names + fr1->fr_ifnames[0], + fr->fr_names + fr->fr_ifnames[0])) { m[FRC_IFN].e++; m[FRC_IFN].n++; } else n &= ~0x0001; - if ((n & 0x0002) && (fr1->fr_v == fr->fr_v)) { + if ((n & 0x0002) && (fr1->fr_family == fr->fr_family)) { m[FRC_V].e++; m[FRC_V].n++; } else @@ -1224,10 +1230,10 @@ char *group; } static void printhooks(fp, in, out, grp) -FILE *fp; -int in; -int out; -frgroup_t *grp; + FILE *fp; + int in; + int out; + frgroup_t *grp; { frentry_t *fr; char *group; @@ -1235,7 +1241,7 @@ frgroup_t *grp; char *instr; group = grp->fg_name; - dogrp = *group ? 1 : 0; + dogrp = 0; if (in && out) { fprintf(stderr, @@ -1281,18 +1287,24 @@ int ipfrule_add_%s_%s()\n", instr, group); fprintf(fp, "\ for (j = i + 1; j < max; j++)\n\ - if (strncmp(fp->fr_group,\n\ + if (strncmp(fp->fr_names + fp->fr_group,\n\ + ipf_rules_%s_%s[j]->fr_names +\n\ ipf_rules_%s_%s[j]->fr_group,\n\ FR_GROUPLEN) == 0) {\n\ + if (ipf_rules_%s_%s[j] != NULL)\n\ + ipf_rules_%s_%s[j]->fr_pnext =\n\ + &fp->fr_next;\n\ + fp->fr_pnext = &ipf_rules_%s_%s[j];\n\ fp->fr_next = ipf_rules_%s_%s[j];\n\ break;\n\ - }\n", instr, group, instr, group); + }\n", instr, group, instr, group, instr, group, + instr, group, instr, group, instr, group); if (dogrp) fprintf(fp, "\ \n\ - if (fp->fr_grhead != 0) {\n\ - fg = fr_addgroup(fp->fr_grhead, fp, FR_INQUE,\n\ - IPL_LOGIPF, 0);\n\ + if (fp->fr_grhead != -1) {\n\ + fg = fr_addgroup(fp->fr_names + fp->fr_grhead,\n\ + fp, FR_INQUE, IPL_LOGIPF, 0);\n\ if (fg != NULL)\n\ fp->fr_grp = &fg->fg_start;\n\ }\n"); @@ -1302,7 +1314,7 @@ int ipfrule_add_%s_%s()\n", instr, group); fp = &ipfrule_%s_%s;\n", instr, group); fprintf(fp, "\ bzero((char *)fp, sizeof(*fp));\n\ - fp->fr_type = FR_T_CALLFUNC|FR_T_BUILTIN;\n\ + fp->fr_type = FR_T_CALLFUNC_BUILTIN;\n\ fp->fr_flags = FR_%sQUE|FR_NOMATCH;\n\ fp->fr_data = (void *)ipf_rules_%s_%s[0];\n", (in != 0) ? "IN" : "OUT", instr, group); @@ -1311,9 +1323,10 @@ int ipfrule_add_%s_%s()\n", instr, group); instr, group); fprintf(fp, "\ - fp->fr_v = 4;\n\ + fp->fr_family = AF_INET;\n\ fp->fr_func = (ipfunc_t)ipfrule_match_%s_%s;\n\ - err = frrequest(IPL_LOGIPF, SIOCADDFR, (caddr_t)fp, fr_active, 0);\n", + err = frrequest(&ipfmain, IPL_LOGIPF, SIOCADDFR, (caddr_t)fp,\n\ + ipfmain.ipf_active, 0);\n", instr, group); fprintf(fp, "\treturn err;\n}\n"); @@ -1346,8 +1359,9 @@ int ipfrule_remove_%s_%s()\n", instr, group); }\n\ }\n\ if (err == 0)\n\ - err = frrequest(IPL_LOGIPF, SIOCDELFR,\n\ - (caddr_t)&ipfrule_%s_%s, fr_active, 0);\n", + err = frrequest(&ipfmain, IPL_LOGIPF, SIOCDELFR,\n\ + (caddr_t)&ipfrule_%s_%s,\n\ + ipfmain.ipf_active, 0);\n", instr, group, instr, group, instr, group); fprintf(fp, "\ if (err)\n\ diff --git a/tools/ipfs.c b/tools/ipfs.c index 3acb5d45e21f1..5b78e99882776 100644 --- a/tools/ipfs.c +++ b/tools/ipfs.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -42,7 +42,7 @@ #include "netinet/ipl.h" #if !defined(lint) -static const char rcsid[] = "@(#)Id: ipfs.c,v 1.12 2003/12/01 01:56:53 darrenr Exp"; +static const char rcsid[] = "@(#)$Id$"; #endif #ifndef IPF_SAVEDIR @@ -98,7 +98,7 @@ void usage() * Change interface names in state information saved out to disk. */ int changestateif(ifs, fname) -char *ifs, *fname; + char *ifs, *fname; { int fd, olen, nlen, rw; ipstate_save_t ips; @@ -161,7 +161,7 @@ char *ifs, *fname; * Change interface names in NAT information saved out to disk. */ int changenatif(ifs, fname) -char *ifs, *fname; + char *ifs, *fname; { int fd, olen, nlen, rw; nat_save_t ipn; @@ -196,14 +196,6 @@ char *ifs, *fname; strcpy(nat->nat_ifnames[1], s); rw = 1; } - if (!strncmp(nat->nat_ifnames[2], ifs, olen + 1)) { - strcpy(nat->nat_ifnames[2], s); - rw = 1; - } - if (!strncmp(nat->nat_ifnames[3], ifs, olen + 1)) { - strcpy(nat->nat_ifnames[3], s); - rw = 1; - } if (rw == 1) { if (lseek(fd, pos, SEEK_SET) != pos) { perror("lseek"); @@ -223,8 +215,8 @@ char *ifs, *fname; int main(argc,argv) -int argc; -char *argv[]; + int argc; + char *argv[]; { int c, lock = -1, devfd = -1, err = 0, rw = -1, ns = -1, set = 0; char *dirname = NULL, *filename = NULL, *ifs = NULL; @@ -354,7 +346,7 @@ char *argv[]; int opendevice(ipfdev) -char *ipfdev; + char *ipfdev; { int fd = -1; @@ -372,14 +364,14 @@ char *ipfdev; void closedevice(fd) -int fd; + int fd; { close(fd); } int setlock(fd, lock) -int fd, lock; + int fd, lock; { if (opts & OPT_VERBOSE) printf("Turn lock %s\n", lock ? "on" : "off"); @@ -396,8 +388,8 @@ int fd, lock; int writestate(fd, file) -int fd; -char *file; + int fd; + char *file; { ipstate_save_t ips, *ipsp; ipfobj_t obj; @@ -448,8 +440,8 @@ char *file; int readstate(fd, file) -int fd; -char *file; + int fd; + char *file; { ipstate_save_t ips, *is, *ipshead = NULL, *is1, *ipstail = NULL; int sfd = -1, i; @@ -565,8 +557,8 @@ freeipshead: int readnat(fd, file) -int fd; -char *file; + int fd; + char *file; { nat_save_t ipn, *in, *ipnhead = NULL, *in1, *ipntail = NULL; ipfobj_t obj; @@ -712,8 +704,8 @@ freenathead: int writenat(fd, file) -int fd; -char *file; + int fd; + char *file; { nat_save_t *ipnp = NULL, *next = NULL; ipfobj_t obj; @@ -796,7 +788,7 @@ char *file; int writeall(dirname) -char *dirname; + char *dirname; { int fd, devfd; @@ -847,7 +839,7 @@ bad: int readall(dirname) -char *dirname; + char *dirname; { int fd, devfd; diff --git a/tools/ipfstat.c b/tools/ipfstat.c index e28fe4c347e8c..5c47dcc7613a8 100644 --- a/tools/ipfstat.c +++ b/tools/ipfstat.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -13,6 +13,7 @@ # endif #endif #include <sys/ioctl.h> +#include <ctype.h> #include <fcntl.h> #ifdef linux # include <linux/a.out.h> @@ -69,7 +70,7 @@ #if !defined(lint) static const char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipfstat.c,v 1.44.2.25 2007/06/30 09:48:50 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #ifdef __hpux @@ -85,7 +86,9 @@ extern int opterr; static char *filters[4] = { "ipfilter(in)", "ipfilter(out)", "ipacct(in)", "ipacct(out)" }; static int state_logging = -1; +static wordtab_t *state_fields = NULL; +int nohdrfields = 0; int opts = 0; int use_inet6 = 0; int live_kernel = 1; @@ -96,6 +99,26 @@ int nat_fd = -1; frgroup_t *grtop = NULL; frgroup_t *grtail = NULL; +char *blockreasons[FRB_MAX_VALUE + 1] = { + "packet blocked", + "log rule failure", + "pps rate exceeded", + "jumbogram", + "makefrip failed", + "cannot add state", + "IP ID update failed", + "log-or-block failed", + "decapsulate failure", + "cannot create new auth entry", + "packet queued for auth", + "buffer coalesce failure", + "buffer pullup failure", + "auth feedback", + "bad fragment", + "IPv4 NAT failure", + "IPv6 NAT failure" +}; + #ifdef STATETOP #define STSTRSIZE 80 #define STGROWSIZE 16 @@ -133,22 +156,27 @@ static int fetchfrag __P((int, int, ipfr_t *)); static void showstats __P((friostat_t *, u_32_t)); static void showfrstates __P((ipfrstat_t *, u_long)); static void showlist __P((friostat_t *)); -static void showipstates __P((ips_stat_t *)); -static void showauthstates __P((fr_authstat_t *)); +static void showstatestats __P((ips_stat_t *)); +static void showipstates __P((ips_stat_t *, int *)); +static void showauthstates __P((ipf_authstat_t *)); +static void showtqtable_live __P((int)); static void showgroups __P((friostat_t *)); static void usage __P((char *)); -static void showtqtable_live __P((int)); -static void printlivelist __P((int, int, frentry_t *, char *, char *)); -static void printdeadlist __P((int, int, frentry_t *, char *, char *)); +static int state_matcharray __P((ipstate_t *, int *)); +static int printlivelist __P((friostat_t *, int, int, frentry_t *, + char *, char *)); +static void printdeadlist __P((friostat_t *, int, int, frentry_t *, + char *, char *)); +static void printside __P((char *, ipf_statistics_t *)); static void parse_ipportstr __P((const char *, i6addr_t *, int *)); static void ipfstate_live __P((char *, friostat_t **, ips_stat_t **, - ipfrstat_t **, fr_authstat_t **, u_32_t *)); + ipfrstat_t **, ipf_authstat_t **, u_32_t *)); static void ipfstate_dead __P((char *, friostat_t **, ips_stat_t **, - ipfrstat_t **, fr_authstat_t **, u_32_t *)); + ipfrstat_t **, ipf_authstat_t **, u_32_t *)); static ipstate_t *fetchstate __P((ipstate_t *, ipstate_t *)); #ifdef STATETOP static void topipstates __P((i6addr_t, i6addr_t, int, int, int, - int, int, int)); + int, int, int, int *)); static void sig_break __P((int)); static void sig_resize __P((int)); static char *getip __P((int, i6addr_t *)); @@ -165,7 +193,7 @@ static int sort_dstpt __P((const void *, const void *)); static void usage(name) -char *name; + char *name; { #ifdef USE_INET6 fprintf(stderr, "Usage: %s [-6aAdfghIilnoRsv]\n", name); @@ -184,20 +212,23 @@ char *name; int main(argc,argv) -int argc; -char *argv[]; + int argc; + char *argv[]; { - fr_authstat_t frauthst; - fr_authstat_t *frauthstp = &frauthst; + ipf_authstat_t frauthst; + ipf_authstat_t *frauthstp = &frauthst; friostat_t fio; friostat_t *fiop = &fio; ips_stat_t ipsst; ips_stat_t *ipsstp = &ipsst; ipfrstat_t ifrst; ipfrstat_t *ifrstp = &ifrst; - char *memf = NULL; - char *options, *kern = NULL; - int c, myoptind; + char *options; + char *kern = NULL; + char *memf = NULL; + int c; + int myoptind; + int *filter = NULL; int protocol = -1; /* -1 = wild card for any protocol */ int refreshtime = 1; /* default update time */ @@ -208,9 +239,9 @@ char *argv[]; u_32_t frf; #ifdef USE_INET6 - options = "6aACdfghIilnostvD:M:N:P:RS:T:"; + options = "6aACdfghIilnostvD:m:M:N:O:P:RS:T:"; #else - options = "aACdfghIilnostvD:M:N:P:RS:T:"; + options = "aACdfghIilnostvD:m:M:N:O:P:RS:T:"; #endif saddr.in4.s_addr = INADDR_ANY; /* default any v4 source addr */ @@ -322,6 +353,14 @@ char *argv[]; case 'l' : opts |= OPT_SHOWLIST; break; + case 'm' : + filter = parseipfexpr(optarg, NULL); + if (filter == NULL) { + fprintf(stderr, "Error parseing '%s'\n", + optarg); + exit(1); + } + break; case 'M' : break; case 'N' : @@ -332,6 +371,9 @@ char *argv[]; case 'o' : opts |= OPT_OUTQUE|OPT_SHOWLIST; break; + case 'O' : + state_fields = parsefields(statefields, optarg); + break; case 'P' : protocol = getproto(optarg); if (protocol == -1) { @@ -384,11 +426,12 @@ char *argv[]; ipfstate_live(IPL_NAME, &fiop, &ipsstp, &ifrstp, &frauthstp, &frf); - } else + } else { ipfstate_dead(kern, &fiop, &ipsstp, &ifrstp, &frauthstp, &frf); + } if (opts & OPT_IPSTATES) { - showipstates(ipsstp); + showipstates(ipsstp, filter); } else if (opts & OPT_SHOWLIST) { showlist(fiop); if ((opts & OPT_OUTQUE) && (opts & OPT_INQUE)){ @@ -400,7 +443,7 @@ char *argv[]; #ifdef STATETOP else if (opts & OPT_STATETOP) topipstates(saddr, daddr, sport, dport, protocol, - use_inet6 ? 6 : 4, refreshtime, topclosed); + use_inet6 ? 6 : 4, refreshtime, topclosed, filter); #endif else if (opts & OPT_AUTHSTATS) showauthstates(frauthstp); @@ -418,12 +461,12 @@ char *argv[]; * of ioctl's and copying directly from kernel memory. */ static void ipfstate_live(device, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp) -char *device; -friostat_t **fiopp; -ips_stat_t **ipsstpp; -ipfrstat_t **ifrstpp; -fr_authstat_t **frauthstpp; -u_32_t *frfp; + char *device; + friostat_t **fiopp; + ips_stat_t **ipsstpp; + ipfrstat_t **ifrstpp; + ipf_authstat_t **frauthstpp; + u_32_t *frfp; { ipfobj_t ipfo; @@ -440,12 +483,12 @@ u_32_t *frfp; ipfo.ipfo_ptr = (void *)*fiopp; if (ioctl(ipf_fd, SIOCGETFS, &ipfo) == -1) { - perror("ioctl(ipf:SIOCGETFS)"); + ipferror(ipf_fd, "ioctl(ipf:SIOCGETFS)"); exit(-1); } if (ioctl(ipf_fd, SIOCGETFF, frfp) == -1) - perror("ioctl(SIOCGETFF)"); + ipferror(ipf_fd, "ioctl(SIOCGETFF)"); } if ((opts & OPT_IPSTATES) != 0) { @@ -457,11 +500,11 @@ u_32_t *frfp; ipfo.ipfo_ptr = (void *)*ipsstpp; if ((ioctl(state_fd, SIOCGETFS, &ipfo) == -1)) { - perror("ioctl(state:SIOCGETFS)"); + ipferror(state_fd, "ioctl(state:SIOCGETFS)"); exit(-1); } if (ioctl(state_fd, SIOCGETLG, &state_logging) == -1) { - perror("ioctl(state:SIOCGETLG)"); + ipferror(state_fd, "ioctl(state:SIOCGETLG)"); exit(-1); } } @@ -472,9 +515,9 @@ u_32_t *frfp; ipfo.ipfo_type = IPFOBJ_FRAGSTAT; ipfo.ipfo_size = sizeof(ipfrstat_t); ipfo.ipfo_ptr = (void *)*ifrstpp; - + if (ioctl(ipf_fd, SIOCGFRST, &ipfo) == -1) { - perror("ioctl(SIOCGFRST)"); + ipferror(ipf_fd, "ioctl(SIOCGFRST)"); exit(-1); } } @@ -486,11 +529,11 @@ u_32_t *frfp; bzero((caddr_t)&ipfo, sizeof(ipfo)); ipfo.ipfo_rev = IPFILTER_VERSION; ipfo.ipfo_type = IPFOBJ_AUTHSTAT; - ipfo.ipfo_size = sizeof(fr_authstat_t); + ipfo.ipfo_size = sizeof(ipf_authstat_t); ipfo.ipfo_ptr = (void *)*frauthstpp; if (ioctl(auth_fd, SIOCATHST, &ipfo) == -1) { - perror("ioctl(SIOCATHST)"); + ipferror(auth_fd, "ioctl(SIOCATHST)"); exit(-1); } } @@ -503,66 +546,64 @@ u_32_t *frfp; * just won't work any more. */ static void ipfstate_dead(kernel, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp) -char *kernel; -friostat_t **fiopp; -ips_stat_t **ipsstpp; -ipfrstat_t **ifrstpp; -fr_authstat_t **frauthstpp; -u_32_t *frfp; + char *kernel; + friostat_t **fiopp; + ips_stat_t **ipsstpp; + ipfrstat_t **ifrstpp; + ipf_authstat_t **frauthstpp; + u_32_t *frfp; { - static fr_authstat_t frauthst, *frauthstp; + static ipf_authstat_t frauthst, *frauthstp; + static ipftq_t ipstcptab[IPF_TCP_NSTATES]; static ips_stat_t ipsst, *ipsstp; static ipfrstat_t ifrst, *ifrstp; static friostat_t fio, *fiop; - static ipftq_t ipssttab[IPF_TCP_NSTATES]; int temp; void *rules[2][2]; struct nlist deadlist[44] = { - { "fr_authstats" }, /* 0 */ - { "fae_list" }, - { "ipauth" }, - { "fr_authlist" }, - { "fr_authstart" }, - { "fr_authend" }, /* 5 */ - { "fr_authnext" }, - { "fr_auth" }, - { "fr_authused" }, - { "fr_authsize" }, - { "fr_defaultauthage" }, /* 10 */ - { "fr_authpkts" }, - { "fr_auth_lock" }, - { "frstats" }, - { "ips_stats" }, - { "ips_num" }, /* 15 */ - { "ips_wild" }, - { "ips_list" }, - { "ips_table" }, - { "fr_statemax" }, - { "fr_statesize" }, /* 20 */ - { "fr_state_doflush" }, - { "fr_state_lock" }, - { "ipfr_heads" }, - { "ipfr_nattab" }, - { "ipfr_stats" }, /* 25 */ - { "ipfr_inuse" }, - { "fr_ipfrttl" }, - { "fr_frag_lock" }, - { "ipfr_timer_id" }, - { "fr_nat_lock" }, /* 30 */ - { "ipfilter" }, - { "ipfilter6" }, - { "ipacct" }, - { "ipacct6" }, - { "ipl_frouteok" }, /* 35 */ - { "fr_running" }, - { "ipfgroups" }, - { "fr_active" }, - { "fr_pass" }, - { "fr_flags" }, /* 40 */ - { "ipstate_logging" }, - { "ips_tqtqb" }, - { NULL } + { "ipf_auth_stats", 0, 0, 0, 0 }, /* 0 */ + { "fae_list", 0, 0, 0, 0 }, + { "ipauth", 0, 0, 0, 0 }, + { "ipf_auth_list", 0, 0, 0, 0 }, + { "ipf_auth_start", 0, 0, 0, 0 }, + { "ipf_auth_end", 0, 0, 0, 0 }, /* 5 */ + { "ipf_auth_next", 0, 0, 0, 0 }, + { "ipf_auth", 0, 0, 0, 0 }, + { "ipf_auth_used", 0, 0, 0, 0 }, + { "ipf_auth_size", 0, 0, 0, 0 }, + { "ipf_auth_defaultage", 0, 0, 0, 0 }, /* 10 */ + { "ipf_auth_pkts", 0, 0, 0, 0 }, + { "ipf_auth_lock", 0, 0, 0, 0 }, + { "frstats", 0, 0, 0, 0 }, + { "ips_stats", 0, 0, 0, 0 }, + { "ips_num", 0, 0, 0, 0 }, /* 15 */ + { "ips_wild", 0, 0, 0, 0 }, + { "ips_list", 0, 0, 0, 0 }, + { "ips_table", 0, 0, 0, 0 }, + { "ipf_state_max", 0, 0, 0, 0 }, + { "ipf_state_size", 0, 0, 0, 0 }, /* 20 */ + { "ipf_state_doflush", 0, 0, 0, 0 }, + { "ipf_state_lock", 0, 0, 0, 0 }, + { "ipfr_heads", 0, 0, 0, 0 }, + { "ipfr_nattab", 0, 0, 0, 0 }, + { "ipfr_stats", 0, 0, 0, 0 }, /* 25 */ + { "ipfr_inuse", 0, 0, 0, 0 }, + { "ipf_ipfrttl", 0, 0, 0, 0 }, + { "ipf_frag_lock", 0, 0, 0, 0 }, + { "ipfr_timer_id", 0, 0, 0, 0 }, + { "ipf_nat_lock", 0, 0, 0, 0 }, /* 30 */ + { "ipf_rules", 0, 0, 0, 0 }, + { "ipf_acct", 0, 0, 0, 0 }, + { "ipl_frouteok", 0, 0, 0, 0 }, + { "ipf_running", 0, 0, 0, 0 }, + { "ipf_groups", 0, 0, 0, 0 }, /* 35 */ + { "ipf_active", 0, 0, 0, 0 }, + { "ipf_pass", 0, 0, 0, 0 }, + { "ipf_flags", 0, 0, 0, 0 }, + { "ipf_state_logging", 0, 0, 0, 0 }, + { "ips_tqtqb", 0, 0, 0, 0 }, /* 40 */ + { NULL, 0, 0, 0, 0 } }; @@ -616,23 +657,6 @@ u_32_t *frfp; fiop->f_fout[1] = rules[1][1]; /* - * Same for IPv6, except make them null if support for it is not - * being compiled in. - */ -#ifdef USE_INET6 - kmemcpy((char *)&rules, (u_long)deadlist[32].n_value, sizeof(rules)); - fiop->f_fin6[0] = rules[0][0]; - fiop->f_fin6[1] = rules[0][1]; - fiop->f_fout6[0] = rules[1][0]; - fiop->f_fout6[1] = rules[1][1]; -#else - fiop->f_fin6[0] = NULL; - fiop->f_fin6[1] = NULL; - fiop->f_fout6[0] = NULL; - fiop->f_fout6[1] = NULL; -#endif - - /* * Now get accounting rules pointers. */ kmemcpy((char *)&rules, (u_long)deadlist[33].n_value, sizeof(rules)); @@ -641,32 +665,19 @@ u_32_t *frfp; fiop->f_acctout[0] = rules[1][0]; fiop->f_acctout[1] = rules[1][1]; -#ifdef USE_INET6 - kmemcpy((char *)&rules, (u_long)deadlist[34].n_value, sizeof(rules)); - fiop->f_acctin6[0] = rules[0][0]; - fiop->f_acctin6[1] = rules[0][1]; - fiop->f_acctout6[0] = rules[1][0]; - fiop->f_acctout6[1] = rules[1][1]; -#else - fiop->f_acctin6[0] = NULL; - fiop->f_acctin6[1] = NULL; - fiop->f_acctout6[0] = NULL; - fiop->f_acctout6[1] = NULL; -#endif - /* * A collection of "global" variables used inside the kernel which * are all collected in friostat_t via ioctl. */ - kmemcpy((char *)&fiop->f_froute, (u_long)deadlist[35].n_value, + kmemcpy((char *)&fiop->f_froute, (u_long)deadlist[33].n_value, sizeof(fiop->f_froute)); - kmemcpy((char *)&fiop->f_running, (u_long)deadlist[36].n_value, + kmemcpy((char *)&fiop->f_running, (u_long)deadlist[34].n_value, sizeof(fiop->f_running)); - kmemcpy((char *)&fiop->f_groups, (u_long)deadlist[37].n_value, + kmemcpy((char *)&fiop->f_groups, (u_long)deadlist[35].n_value, sizeof(fiop->f_groups)); - kmemcpy((char *)&fiop->f_active, (u_long)deadlist[38].n_value, + kmemcpy((char *)&fiop->f_active, (u_long)deadlist[36].n_value, sizeof(fiop->f_active)); - kmemcpy((char *)&fiop->f_defpass, (u_long)deadlist[39].n_value, + kmemcpy((char *)&fiop->f_defpass, (u_long)deadlist[37].n_value, sizeof(fiop->f_defpass)); /* @@ -674,12 +685,12 @@ u_32_t *frfp; */ kmemcpy((char *)ipsstp, (u_long)deadlist[14].n_value, sizeof(*ipsstp)); kmemcpy((char *)&temp, (u_long)deadlist[15].n_value, sizeof(temp)); - kmemcpy((char *)ipssttab, (u_long)deadlist[42].n_value, - sizeof(ipssttab)); + kmemcpy((char *)ipstcptab, (u_long)deadlist[40].n_value, + sizeof(ipstcptab)); ipsstp->iss_active = temp; ipsstp->iss_table = (void *)deadlist[18].n_value; ipsstp->iss_list = (void *)deadlist[17].n_value; - ipsstp->iss_tcptab = ipssttab; + ipsstp->iss_tcptab = ipstcptab; /* * Build up the authentiation information stats structure. @@ -706,65 +717,62 @@ u_32_t *frfp; } +static void printside(side, frs) + char *side; + ipf_statistics_t *frs; +{ + int i; + + PRINTF("%lu\t%s bad packets\n", frs->fr_bad, side); +#ifdef USE_INET6 + PRINTF("%lu\t%s IPv6 packets\n", frs->fr_ipv6, side); +#endif + PRINTF("%lu\t%s packets blocked\n", frs->fr_block, side); + PRINTF("%lu\t%s packets passed\n", frs->fr_pass, side); + PRINTF("%lu\t%s packets not matched\n", frs->fr_nom, side); + PRINTF("%lu\t%s packets counted\n", frs->fr_acct, side); + PRINTF("%lu\t%s packets short\n", frs->fr_short, side); + PRINTF("%lu\t%s packets logged and blocked\n", frs->fr_bpkl, side); + PRINTF("%lu\t%s packets logged and passed\n", frs->fr_ppkl, side); + PRINTF("%lu\t%s fragment state kept\n", frs->fr_nfr, side); + PRINTF("%lu\t%s fragment state lost\n", frs->fr_bnfr, side); + PRINTF("%lu\t%s packet state kept\n", frs->fr_ads, side); + PRINTF("%lu\t%s packet state lost\n", frs->fr_bads, side); + PRINTF("%lu\t%s invalid source\n", frs->fr_v4_badsrc, side); + PRINTF("%lu\t%s cache hits\n", frs->fr_chit, side); + PRINTF("%lu\t%s cache misses\n", frs->fr_cmiss, side); + PRINTF("%lu\t%s bad coalesces\n", frs->fr_badcoalesces, side); + PRINTF("%lu\t%s pullups succeeded\n", frs->fr_pull[0], side); + PRINTF("%lu\t%s pullups failed\n", frs->fr_pull[1], side); + PRINTF("%lu\t%s TCP checksum failures\n", frs->fr_tcpbad, side); + for (i = 0; i <= FRB_MAX_VALUE; i++) + PRINTF("%lu\t%s block reason %s\n", + frs->fr_blocked[i], side, blockreasons[i]); +} + + /* * Display the kernel stats for packets blocked and passed and other * associated running totals which are kept. */ static void showstats(fp, frf) -struct friostat *fp; -u_32_t frf; + struct friostat *fp; + u_32_t frf; { - - PRINTF("bad packets:\t\tin %lu\tout %lu\n", - fp->f_st[0].fr_bad, fp->f_st[1].fr_bad); -#ifdef USE_INET6 - PRINTF(" IPv6 packets:\t\tin %lu out %lu\n", - fp->f_st[0].fr_ipv6, fp->f_st[1].fr_ipv6); -#endif - PRINTF(" input packets:\t\tblocked %lu passed %lu nomatch %lu", - fp->f_st[0].fr_block, fp->f_st[0].fr_pass, - fp->f_st[0].fr_nom); - PRINTF(" counted %lu short %lu\n", - fp->f_st[0].fr_acct, fp->f_st[0].fr_short); - PRINTF("output packets:\t\tblocked %lu passed %lu nomatch %lu", - fp->f_st[1].fr_block, fp->f_st[1].fr_pass, - fp->f_st[1].fr_nom); - PRINTF(" counted %lu short %lu\n", - fp->f_st[1].fr_acct, fp->f_st[1].fr_short); - PRINTF(" input packets logged:\tblocked %lu passed %lu\n", - fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl); - PRINTF("output packets logged:\tblocked %lu passed %lu\n", - fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl); - PRINTF(" packets logged:\tinput %lu output %lu\n", - fp->f_st[0].fr_pkl, fp->f_st[1].fr_pkl); - PRINTF(" log failures:\t\tinput %lu output %lu\n", - fp->f_st[0].fr_skip, fp->f_st[1].fr_skip); - PRINTF("fragment state(in):\tkept %lu\tlost %lu\tnot fragmented %lu\n", - fp->f_st[0].fr_nfr, fp->f_st[0].fr_bnfr, - fp->f_st[0].fr_cfr); - PRINTF("fragment state(out):\tkept %lu\tlost %lu\tnot fragmented %lu\n", - fp->f_st[1].fr_nfr, fp->f_st[1].fr_bnfr, - fp->f_st[0].fr_cfr); - PRINTF("packet state(in):\tkept %lu\tlost %lu\n", - fp->f_st[0].fr_ads, fp->f_st[0].fr_bads); - PRINTF("packet state(out):\tkept %lu\tlost %lu\n", - fp->f_st[1].fr_ads, fp->f_st[1].fr_bads); - PRINTF("ICMP replies:\t%lu\tTCP RSTs sent:\t%lu\n", - fp->f_st[0].fr_ret, fp->f_st[1].fr_ret); - PRINTF("Invalid source(in):\t%lu\n", fp->f_st[0].fr_badsrc); - PRINTF("Result cache hits(in):\t%lu\t(out):\t%lu\n", - fp->f_st[0].fr_chit, fp->f_st[1].fr_chit); - PRINTF("IN Pullups succeeded:\t%lu\tfailed:\t%lu\n", - fp->f_st[0].fr_pull[0], fp->f_st[0].fr_pull[1]); - PRINTF("OUT Pullups succeeded:\t%lu\tfailed:\t%lu\n", - fp->f_st[1].fr_pull[0], fp->f_st[1].fr_pull[1]); - PRINTF("Fastroute successes:\t%lu\tfailures:\t%lu\n", - fp->f_froute[0], fp->f_froute[1]); - PRINTF("TCP cksum fails(in):\t%lu\t(out):\t%lu\n", - fp->f_st[0].fr_tcpbad, fp->f_st[1].fr_tcpbad); - PRINTF("IPF Ticks:\t%lu\n", fp->f_ticks); - - PRINTF("Packet log flags set: (%#x)\n", frf); + printside("input", &fp->f_st[0]); + printside("output", &fp->f_st[1]); + + PRINTF("%lu\tpackets logged\n", fp->f_log_ok); + PRINTF("%lu\tlog failures\n", fp->f_log_fail); + PRINTF("%lu\tred-black no memory\n", fp->f_rb_no_mem); + PRINTF("%lu\tred-black node maximum\n", fp->f_rb_node_max); + PRINTF("%lu\tICMP replies sent\n", fp->f_st[0].fr_ret); + PRINTF("%lu\tTCP RSTs sent\n", fp->f_st[1].fr_ret); + PRINTF("%lu\tfastroute successes\n", fp->f_froute[0]); + PRINTF("%lu\tfastroute failures\n", fp->f_froute[1]); + PRINTF("%u\tIPF Ticks\n", fp->f_ticks); + + PRINTF("%x\tPacket log flags set:\n", frf); if (frf & FF_LOGPASS) PRINTF("\tpackets passed through filter\n"); if (frf & FF_LOGBLOCK) @@ -779,30 +787,27 @@ u_32_t frf; /* * Print out a list of rules from the kernel, starting at the one passed. */ -static void printlivelist(out, set, fp, group, comment) -int out, set; -frentry_t *fp; -char *group, *comment; +static int +printlivelist(fiop, out, set, fp, group, comment) + struct friostat *fiop; + int out, set; + frentry_t *fp; + char *group, *comment; { struct frentry fb; ipfruleiter_t rule; frentry_t zero; frgroup_t *g; ipfobj_t obj; - int n; + int rules; + int num; - if (use_inet6 == 1) - fb.fr_v = 6; - else - fb.fr_v = 4; - fb.fr_next = fp; - n = 0; + rules = 0; rule.iri_inout = out; rule.iri_active = set; rule.iri_rule = &fb; rule.iri_nrules = 1; - rule.iri_v = use_inet6 ? 6 : 4; if (group != NULL) strncpy(rule.iri_group, group, FR_GROUPLEN); else @@ -816,49 +821,65 @@ char *group, *comment; obj.ipfo_size = sizeof(rule); obj.ipfo_ptr = &rule; - do { + while (rule.iri_rule != NULL) { u_long array[1000]; memset(array, 0xff, sizeof(array)); fp = (frentry_t *)array; rule.iri_rule = fp; if (ioctl(ipf_fd, SIOCIPFITER, &obj) == -1) { - perror("ioctl(SIOCIPFITER)"); - n = IPFGENITER_IPF; - ioctl(ipf_fd, SIOCIPFDELTOK, &n); - return; + ipferror(ipf_fd, "ioctl(SIOCIPFITER)"); + num = IPFGENITER_IPF; + (void) ioctl(ipf_fd,SIOCIPFDELTOK, &num); + return rules; } if (bcmp(fp, &zero, sizeof(zero)) == 0) break; + if (rule.iri_rule == NULL) + break; +#ifdef USE_INET6 + if (use_inet6 != 0) { + if (fp->fr_family != 0 && fp->fr_family != AF_INET6) + continue; + } else +#endif + { + if (fp->fr_family != 0 && fp->fr_family != AF_INET) + continue; + } if (fp->fr_data != NULL) - fp->fr_data = (char *)fp + sizeof(*fp); + fp->fr_data = (char *)fp + fp->fr_size; - n++; + rules++; - if (opts & (OPT_HITS|OPT_VERBOSE)) + if (opts & (OPT_HITS|OPT_DEBUG)) #ifdef USE_QUAD_T - PRINTF("%qu ", (unsigned long long) fp->fr_hits); + PRINTF("%"PRIu64" ", (unsigned long long) fp->fr_hits); #else PRINTF("%lu ", fp->fr_hits); #endif - if (opts & (OPT_ACCNT|OPT_VERBOSE)) + if (opts & (OPT_ACCNT|OPT_DEBUG)) #ifdef USE_QUAD_T - PRINTF("%qu ", (unsigned long long) fp->fr_bytes); + PRINTF("%"PRIu64" ", (unsigned long long) fp->fr_bytes); #else PRINTF("%lu ", fp->fr_bytes); #endif if (opts & OPT_SHOWLINENO) - PRINTF("@%d ", n); + PRINTF("@%d ", rules); + + if (fp->fr_die != 0) + fp->fr_die -= fiop->f_ticks; printfr(fp, ioctl); if (opts & OPT_DEBUG) { - binprint(fp, sizeof(*fp)); + binprint(fp, fp->fr_size); if (fp->fr_data != NULL && fp->fr_dsize > 0) binprint(fp->fr_data, fp->fr_dsize); } - if (fp->fr_grhead[0] != '\0') { + if (fp->fr_grhead != -1) { for (g = grtop; g != NULL; g = g->fg_next) { - if (!strncmp(fp->fr_grhead, g->fg_name, + if (!strncmp(fp->fr_names + fp->fr_grhead, + g->fg_name, FR_GROUPLEN)) break; } @@ -866,7 +887,8 @@ char *group, *comment; g = calloc(1, sizeof(*g)); if (g != NULL) { - strncpy(g->fg_name, fp->fr_grhead, + strncpy(g->fg_name, + fp->fr_names + fp->fr_grhead, FR_GROUPLEN); if (grtop == NULL) { grtop = g; @@ -879,29 +901,23 @@ char *group, *comment; } } if (fp->fr_type == FR_T_CALLFUNC) { - printlivelist(out, set, fp->fr_data, group, - "# callfunc: "); + rules += printlivelist(fiop, out, set, fp->fr_data, + group, "# callfunc: "); } - } while (fp->fr_next != NULL); + } - n = IPFGENITER_IPF; - ioctl(ipf_fd, SIOCIPFDELTOK, &n); + num = IPFGENITER_IPF; + (void) ioctl(ipf_fd,SIOCIPFDELTOK, &num); - if (group == NULL) { - while ((g = grtop) != NULL) { - printf("# Group %s\n", g->fg_name); - printlivelist(out, set, NULL, g->fg_name, comment); - grtop = g->fg_next; - free(g); - } - } + return rules; } -static void printdeadlist(out, set, fp, group, comment) -int out, set; -frentry_t *fp; -char *group, *comment; +static void printdeadlist(fiop, out, set, fp, group, comment) + friostat_t *fiop; + int out, set; + frentry_t *fp; + char *group, *comment; { frgroup_t *grtop, *grtail, *g; struct frentry fb; @@ -914,13 +930,20 @@ char *group, *comment; grtop = NULL; grtail = NULL; - do { - fp = fb.fr_next; + for (n = 1; fp; fp = fb.fr_next, n++) { if (kmemcpy((char *)&fb, (u_long)fb.fr_next, - sizeof(fb)) == -1) { + fb.fr_size) == -1) { perror("kmemcpy"); return; } + fp = &fb; + if (use_inet6 != 0) { + if (fp->fr_family != 0 && fp->fr_family != 6) + continue; + } else { + if (fp->fr_family != 0 && fp->fr_family != 4) + continue; + } data = NULL; type = fb.fr_type & ~FR_T_BUILTIN; @@ -937,17 +960,15 @@ char *group, *comment; } } - n++; - - if (opts & (OPT_HITS|OPT_VERBOSE)) + if (opts & OPT_HITS) #ifdef USE_QUAD_T - PRINTF("%qu ", (unsigned long long) fb.fr_hits); + PRINTF("%"PRIu64" ", (unsigned long long) fb.fr_hits); #else PRINTF("%lu ", fb.fr_hits); #endif - if (opts & (OPT_ACCNT|OPT_VERBOSE)) + if (opts & OPT_ACCNT) #ifdef USE_QUAD_T - PRINTF("%qu ", (unsigned long long) fb.fr_bytes); + PRINTF("%"PRIu64" ", (unsigned long long) fb.fr_bytes); #else PRINTF("%lu ", fb.fr_bytes); #endif @@ -956,17 +977,17 @@ char *group, *comment; printfr(fp, ioctl); if (opts & OPT_DEBUG) { - binprint(fp, sizeof(*fp)); + binprint(fp, fp->fr_size); if (fb.fr_data != NULL && fb.fr_dsize > 0) binprint(fb.fr_data, fb.fr_dsize); } if (data != NULL) free(data); - if (fb.fr_grhead[0] != '\0') { + if (fb.fr_grhead != -1) { g = calloc(1, sizeof(*g)); if (g != NULL) { - strncpy(g->fg_name, fb.fr_grhead, + strncpy(g->fg_name, fb.fr_names + fb.fr_grhead, FR_GROUPLEN); if (grtop == NULL) { grtop = g; @@ -978,13 +999,13 @@ char *group, *comment; } } if (type == FR_T_CALLFUNC) { - printdeadlist(out, set, fb.fr_data, group, + printdeadlist(fiop, out, set, fb.fr_data, group, "# callfunc: "); } - } while (fb.fr_next != NULL); + } while ((g = grtop) != NULL) { - printdeadlist(out, set, NULL, g->fg_name, comment); + printdeadlist(fiop, out, set, NULL, g->fg_name, comment); grtop = g->fg_next; free(g); } @@ -995,7 +1016,7 @@ char *group, *comment; * the base from which to get the pointers. */ static void showlist(fiop) -struct friostat *fiop; + struct friostat *fiop; { struct frentry *fp = NULL; int i, set; @@ -1004,15 +1025,6 @@ struct friostat *fiop; if (opts & OPT_INACTIVE) set = 1 - set; if (opts & OPT_ACCNT) { -#ifdef USE_INET6 - if ((use_inet6) && (opts & OPT_OUTQUE)) { - i = F_ACOUT; - fp = (struct frentry *)fiop->f_acctout6[set]; - } else if ((use_inet6) && (opts & OPT_INQUE)) { - i = F_ACIN; - fp = (struct frentry *)fiop->f_acctin6[set]; - } else -#endif if (opts & OPT_OUTQUE) { i = F_ACOUT; fp = (struct frentry *)fiop->f_acctout[set]; @@ -1024,15 +1036,6 @@ struct friostat *fiop; return; } } else { -#ifdef USE_INET6 - if ((use_inet6) && (opts & OPT_OUTQUE)) { - i = F_OUT; - fp = (struct frentry *)fiop->f_fout6[set]; - } else if ((use_inet6) && (opts & OPT_INQUE)) { - i = F_IN; - fp = (struct frentry *)fiop->f_fin6[set]; - } else -#endif if (opts & OPT_OUTQUE) { i = F_OUT; fp = (struct frentry *)fiop->f_fout[set]; @@ -1047,139 +1050,243 @@ struct friostat *fiop; if (opts & OPT_DEBUG) PRINTF("fp %p set %d\n", fp, set); - if (!fp) { - FPRINTF(stderr, "empty list for %s%s\n", - (opts & OPT_INACTIVE) ? "inactive " : "", filters[i]); - return; + + if (live_kernel == 1) { + int printed; + + printed = printlivelist(fiop, i, set, fp, NULL, NULL); + if (printed == 0) { + FPRINTF(stderr, "# empty list for %s%s\n", + (opts & OPT_INACTIVE) ? "inactive " : "", + filters[i]); + } + } else { + if (!fp) { + FPRINTF(stderr, "# empty list for %s%s\n", + (opts & OPT_INACTIVE) ? "inactive " : "", + filters[i]); + } else { + printdeadlist(fiop, i, set, fp, NULL, NULL); + } } - if (live_kernel == 1) - printlivelist(i, set, fp, NULL, NULL); - else - printdeadlist(i, set, fp, NULL, NULL); } /* * Display ipfilter stateful filtering information */ -static void showipstates(ipsp) -ips_stat_t *ipsp; +static void showipstates(ipsp, filter) + ips_stat_t *ipsp; + int *filter; { - u_long minlen, maxlen, totallen, *buckets; - ipftable_t table; - ipfobj_t obj; - int i, sz; + ipstate_t *is; + int i; /* * If a list of states hasn't been asked for, only print out stats */ if (!(opts & OPT_SHOWLIST)) { + showstatestats(ipsp); + return; + } - sz = sizeof(*buckets) * ipsp->iss_statesize; - buckets = (u_long *)malloc(sz); + if ((state_fields != NULL) && (nohdrfields == 0)) { + for (i = 0; state_fields[i].w_value != 0; i++) { + printfieldhdr(statefields, state_fields + i); + if (state_fields[i + 1].w_value != 0) + printf("\t"); + } + printf("\n"); + } - obj.ipfo_rev = IPFILTER_VERSION; - obj.ipfo_type = IPFOBJ_GTABLE; - obj.ipfo_size = sizeof(table); - obj.ipfo_ptr = &table; + /* + * Print out all the state information currently held in the kernel. + */ + for (is = ipsp->iss_list; is != NULL; ) { + ipstate_t ips; - table.ita_type = IPFTABLE_BUCKETS; - table.ita_table = buckets; + is = fetchstate(is, &ips); - if (live_kernel == 1) { - if (ioctl(state_fd, SIOCGTABL, &obj) != 0) { - free(buckets); - return; + if (is == NULL) + break; + + is = ips.is_next; + if ((filter != NULL) && + (state_matcharray(&ips, filter) == 0)) { + continue; + } + if (state_fields != NULL) { + for (i = 0; state_fields[i].w_value != 0; i++) { + printstatefield(&ips, state_fields[i].w_value); + if (state_fields[i + 1].w_value != 0) + printf("\t"); } + printf("\n"); } else { - if (kmemcpy((char *)buckets, - (u_long)ipsp->iss_bucketlen, sz)) { - free(buckets); - return; - } + printstate(&ips, opts, ipsp->iss_ticks); } + } +} - PRINTF("IP states added:\n\t%lu TCP\n\t%lu UDP\n\t%lu ICMP\n", - ipsp->iss_tcp, ipsp->iss_udp, ipsp->iss_icmp); - PRINTF("\t%lu hits\n\t%lu misses\n", ipsp->iss_hits, - ipsp->iss_miss); - PRINTF("\t%lu bucket full\n", ipsp->iss_bucketfull); - PRINTF("\t%lu maximum rule references\n", ipsp->iss_maxref); - PRINTF("\t%lu maximum\n\t%lu no memory\n\t%lu bkts in use\n", - ipsp->iss_max, ipsp->iss_nomem, ipsp->iss_inuse); - PRINTF("\t%lu active\n\t%lu expired\n\t%lu closed\n", - ipsp->iss_active, ipsp->iss_expire, ipsp->iss_fin); - - PRINTF("State logging %sabled\n", - state_logging ? "en" : "dis"); - - PRINTF("\nState table bucket statistics:\n"); - PRINTF("\t%lu in use\t\n", ipsp->iss_inuse); - PRINTF("\t%u%% hash efficiency\n", ipsp->iss_active ? - (u_int)(ipsp->iss_inuse * 100 / ipsp->iss_active) : 0); - - minlen = ipsp->iss_inuse; - totallen = 0; - maxlen = 0; - - for (i = 0; i < ipsp->iss_statesize; i++) { - if (buckets[i] > maxlen) - maxlen = buckets[i]; - if (buckets[i] < minlen) - minlen = buckets[i]; - totallen += buckets[i]; - } - PRINTF("\t%2.2f%% bucket usage\n\t%lu minimal length\n", - ((float)ipsp->iss_inuse / ipsp->iss_statesize) * 100.0, - minlen); - PRINTF("\t%lu maximal length\n\t%.3f average length\n", - maxlen, - ipsp->iss_inuse ? (float) totallen/ ipsp->iss_inuse : - 0.0); +static void showstatestats(ipsp) + ips_stat_t *ipsp; +{ + int minlen, maxlen, totallen; + ipftable_t table; + u_int *buckets; + ipfobj_t obj; + int i, sz; -#define ENTRIES_PER_LINE 5 + /* + * If a list of states hasn't been asked for, only print out stats + */ - if (opts & OPT_VERBOSE) { - PRINTF("\nCurrent bucket sizes :\n"); - for (i = 0; i < ipsp->iss_statesize; i++) { - if ((i % ENTRIES_PER_LINE) == 0) - PRINTF("\t"); - PRINTF("%4d -> %4lu", i, buckets[i]); - if ((i % ENTRIES_PER_LINE) == - (ENTRIES_PER_LINE - 1)) - PRINTF("\n"); - else - PRINTF(" "); - } - PRINTF("\n"); - } - PRINTF("\n"); + sz = sizeof(*buckets) * ipsp->iss_state_size; + buckets = (u_int *)malloc(sz); - free(buckets); + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_type = IPFOBJ_GTABLE; + obj.ipfo_size = sizeof(table); + obj.ipfo_ptr = &table; - if (live_kernel == 1) { - showtqtable_live(state_fd); - } else { - printtqtable(ipsp->iss_tcptab); + table.ita_type = IPFTABLE_BUCKETS; + table.ita_table = buckets; + + if (live_kernel == 1) { + if (ioctl(state_fd, SIOCGTABL, &obj) != 0) { + free(buckets); + return; } + } else { + if (kmemcpy((char *)buckets, + (u_long)ipsp->iss_bucketlen, sz)) { + free(buckets); + return; + } + } - return; + PRINTF("%u\tactive state table entries\n",ipsp->iss_active); + PRINTF("%lu\tadd bad\n", ipsp->iss_add_bad); + PRINTF("%lu\tadd duplicate\n", ipsp->iss_add_dup); + PRINTF("%lu\tadd locked\n", ipsp->iss_add_locked); + PRINTF("%lu\tadd oow\n", ipsp->iss_add_oow); + PRINTF("%lu\tbucket full\n", ipsp->iss_bucket_full); + PRINTF("%lu\tcheck bad\n", ipsp->iss_check_bad); + PRINTF("%lu\tcheck miss\n", ipsp->iss_check_miss); + PRINTF("%lu\tcheck nattag\n", ipsp->iss_check_nattag); + PRINTF("%lu\tclone nomem\n", ipsp->iss_clone_nomem); + PRINTF("%lu\tcheck notag\n", ipsp->iss_check_notag); + PRINTF("%lu\tcheck success\n", ipsp->iss_hits); + PRINTF("%lu\tcloned\n", ipsp->iss_cloned); + PRINTF("%lu\texpired\n", ipsp->iss_expire); + PRINTF("%lu\tflush all\n", ipsp->iss_flush_all); + PRINTF("%lu\tflush closing\n", ipsp->iss_flush_closing); + PRINTF("%lu\tflush queue\n", ipsp->iss_flush_queue); + PRINTF("%lu\tflush state\n", ipsp->iss_flush_state); + PRINTF("%lu\tflush timeout\n", ipsp->iss_flush_timeout); + PRINTF("%u\thash buckets in use\n", ipsp->iss_inuse); + PRINTF("%lu\tICMP bad\n", ipsp->iss_icmp_bad); + PRINTF("%lu\tICMP banned\n", ipsp->iss_icmp_banned); + PRINTF("%lu\tICMP errors\n", ipsp->iss_icmp_icmperr); + PRINTF("%lu\tICMP head block\n", ipsp->iss_icmp_headblock); + PRINTF("%lu\tICMP hits\n", ipsp->iss_icmp_hits); + PRINTF("%lu\tICMP not query\n", ipsp->iss_icmp_notquery); + PRINTF("%lu\tICMP short\n", ipsp->iss_icmp_short); + PRINTF("%lu\tICMP too many\n", ipsp->iss_icmp_toomany); + PRINTF("%lu\tICMPv6 errors\n", ipsp->iss_icmp6_icmperr); + PRINTF("%lu\tICMPv6 miss\n", ipsp->iss_icmp6_miss); + PRINTF("%lu\tICMPv6 not info\n", ipsp->iss_icmp6_notinfo); + PRINTF("%lu\tICMPv6 not query\n", ipsp->iss_icmp6_notquery); + PRINTF("%lu\tlog fail\n", ipsp->iss_log_fail); + PRINTF("%lu\tlog ok\n", ipsp->iss_log_ok); + PRINTF("%lu\tlookup interface mismatch\n", ipsp->iss_lookup_badifp); + PRINTF("%lu\tlookup mask mismatch\n", ipsp->iss_miss_mask); + PRINTF("%lu\tlookup port mismatch\n", ipsp->iss_lookup_badport); + PRINTF("%lu\tlookup miss\n", ipsp->iss_lookup_miss); + PRINTF("%lu\tmaximum rule references\n", ipsp->iss_max_ref); + PRINTF("%lu\tmaximum hosts per rule\n", ipsp->iss_max_track); + PRINTF("%lu\tno memory\n", ipsp->iss_nomem); + PRINTF("%lu\tout of window\n", ipsp->iss_oow); + PRINTF("%lu\torphans\n", ipsp->iss_orphan); + PRINTF("%lu\tscan block\n", ipsp->iss_scan_block); + PRINTF("%lu\tstate table maximum reached\n", ipsp->iss_max); + PRINTF("%lu\tTCP closing\n", ipsp->iss_tcp_closing); + PRINTF("%lu\tTCP OOW\n", ipsp->iss_tcp_oow); + PRINTF("%lu\tTCP RST add\n", ipsp->iss_tcp_rstadd); + PRINTF("%lu\tTCP too small\n", ipsp->iss_tcp_toosmall); + PRINTF("%lu\tTCP bad options\n", ipsp->iss_tcp_badopt); + PRINTF("%lu\tTCP removed\n", ipsp->iss_fin); + PRINTF("%lu\tTCP FSM\n", ipsp->iss_tcp_fsm); + PRINTF("%lu\tTCP strict\n", ipsp->iss_tcp_strict); + PRINTF("%lu\tTCP wild\n", ipsp->iss_wild); + PRINTF("%lu\tMicrosoft Windows SACK\n", ipsp->iss_winsack); + + PRINTF("State logging %sabled\n", state_logging ? "en" : "dis"); + + PRINTF("IP states added:\n"); + for (i = 0; i < 256; i++) { + if (ipsp->iss_proto[i] != 0) { + struct protoent *proto; + + proto = getprotobynumber(i); + PRINTF("%lu", ipsp->iss_proto[i]); + if (proto != NULL) + PRINTF("\t%s\n", proto->p_name); + else + PRINTF("\t%d\n", i); + } + } + + PRINTF("\nState table bucket statistics:\n"); + PRINTF("%u\tin use\n", ipsp->iss_inuse); + + minlen = ipsp->iss_max; + totallen = 0; + maxlen = 0; + for (i = 0; i < ipsp->iss_state_size; i++) { + if (buckets[i] > maxlen) + maxlen = buckets[i]; + if (buckets[i] < minlen) + minlen = buckets[i]; + totallen += buckets[i]; } - /* - * Print out all the state information currently held in the kernel. - */ - while (ipsp->iss_list != NULL) { - ipstate_t ips; + PRINTF("%d\thash efficiency\n", + totallen ? ipsp->iss_inuse * 100 / totallen : 0); + PRINTF("%2.2f%%\tbucket usage\n%u\tminimal length\n", + ((float)ipsp->iss_inuse / ipsp->iss_state_size) * 100.0, + minlen); + PRINTF("%u\tmaximal length\n%.3f\taverage length\n", + maxlen, + ipsp->iss_inuse ? (float) totallen/ ipsp->iss_inuse : + 0.0); - ipsp->iss_list = fetchstate(ipsp->iss_list, &ips); +#define ENTRIES_PER_LINE 5 - if (ipsp->iss_list != NULL) { - ipsp->iss_list = ips.is_next; - printstate(&ips, opts, ipsp->iss_ticks); + if (opts & OPT_VERBOSE) { + PRINTF("\nCurrent bucket sizes :\n"); + for (i = 0; i < ipsp->iss_state_size; i++) { + if ((i % ENTRIES_PER_LINE) == 0) + PRINTF("\t"); + PRINTF("%4d -> %4u", i, buckets[i]); + if ((i % ENTRIES_PER_LINE) == + (ENTRIES_PER_LINE - 1)) + PRINTF("\n"); + else + PRINTF(" "); } + PRINTF("\n"); + } + PRINTF("\n"); + + free(buckets); + + if (live_kernel == 1) { + showtqtable_live(state_fd); + } else { + printtqtable(ipsp->iss_tcptab); } } @@ -1188,21 +1295,23 @@ ips_stat_t *ipsp; static int handle_resize = 0, handle_break = 0; static void topipstates(saddr, daddr, sport, dport, protocol, ver, - refreshtime, topclosed) -i6addr_t saddr; -i6addr_t daddr; -int sport; -int dport; -int protocol; -int ver; -int refreshtime; -int topclosed; + refreshtime, topclosed, filter) + i6addr_t saddr; + i6addr_t daddr; + int sport; + int dport; + int protocol; + int ver; + int refreshtime; + int topclosed; + int *filter; { char str1[STSTRSIZE], str2[STSTRSIZE], str3[STSTRSIZE], str4[STSTRSIZE]; int maxtsentries = 0, reverse = 0, sorting = STSORT_DEFAULT; int i, j, winy, tsentry, maxx, maxy, redraw = 0, ret = 0; int len, srclen, dstlen, forward = 1, c = 0; ips_stat_t ipsst, *ipsstp = &ipsst; + int token_type = IPFGENITER_STATE; statetop_t *tstable = NULL, *tp; const char *errstr = ""; ipstate_t ips; @@ -1265,6 +1374,10 @@ int topclosed; if (ips.is_v != ver) continue; + if ((filter != NULL) && + (state_matcharray(&ips, filter) == 0)) + continue; + /* check v4 src/dest addresses */ if (ips.is_v == 4) { if ((saddr.in4.s_addr != INADDR_ANY && @@ -1346,6 +1459,7 @@ int topclosed; } } + (void) ioctl(state_fd, SIOCIPFDELTOK, &token_type); /* sort the array */ if (tsentry != -1) { @@ -1483,14 +1597,14 @@ int topclosed; printw("Src: %s, Dest: %s, Proto: %s, Sorted by: %s\n\n", str1, str2, str3, str4); - /* + /* * For an IPv4 IP address we need at most 15 characters, * 4 tuples of 3 digits, separated by 3 dots. Enforce this * length, so the colums do not change positions based * on the size of the IP address. This length makes the - * output fit in a 80 column terminal. + * output fit in a 80 column terminal. * We are lacking a good solution for IPv6 addresses (that - * can be longer that 15 characters), so we do not enforce + * can be longer that 15 characters), so we do not enforce * a maximum on the IP field size. */ if (srclen < 15) @@ -1627,8 +1741,8 @@ out: * Show fragment cache information that's held in the kernel. */ static void showfrstates(ifsp, ticks) -ipfrstat_t *ifsp; -u_long ticks; + ipfrstat_t *ifsp; + u_long ticks; { struct ipfr *ipfrtab[IPFT_SIZE], ifr; int i; @@ -1636,13 +1750,13 @@ u_long ticks; /* * print out the numeric statistics */ - PRINTF("IP fragment states:\n\t%lu new\n\t%lu expired\n\t%lu hits\n", + PRINTF("IP fragment states:\n%lu\tnew\n%lu\texpired\n%lu\thits\n", ifsp->ifs_new, ifsp->ifs_expire, ifsp->ifs_hits); - PRINTF("\t%lu retrans\n\t%lu too short\n", + PRINTF("%lu\tretrans\n%lu\ttoo short\n", ifsp->ifs_retrans0, ifsp->ifs_short); - PRINTF("\t%lu no memory\n\t%lu already exist\n", + PRINTF("%lu\tno memory\n%lu\talready exist\n", ifsp->ifs_nomem, ifsp->ifs_exists); - PRINTF("\t%lu inuse\n", ifsp->ifs_inuse); + PRINTF("%lu\tinuse\n", ifsp->ifs_inuse); PRINTF("\n"); if (live_kernel == 0) { @@ -1662,7 +1776,7 @@ u_long ticks; break; ifr.ipfr_ttl -= ticks; printfraginfo("", &ifr); - } while (1); + } while (ifr.ipfr_next != NULL); } else { for (i = 0; i < IPFT_SIZE; i++) while (ipfrtab[i] != NULL) { @@ -1691,7 +1805,7 @@ u_long ticks; break; ifr.ipfr_ttl -= ticks; printfraginfo("NAT: ", &ifr); - } while (1); + } while (ifr.ipfr_next != NULL); } else { for (i = 0; i < IPFT_SIZE; i++) while (ipfrtab[i] != NULL) { @@ -1709,7 +1823,7 @@ u_long ticks; * Show stats on how auth within IPFilter has been used */ static void showauthstates(asp) -fr_authstat_t *asp; + ipf_authstat_t *asp; { frauthent_t *frap, fra; ipfgeniter_t auth; @@ -1725,7 +1839,7 @@ fr_authstat_t *asp; auth.igi_data = &fra; #ifdef USE_QUAD_T - printf("Authorisation hits: %qu\tmisses %qu\n", + printf("Authorisation hits: %"PRIu64"\tmisses %"PRIu64"\n", (unsigned long long) asp->fas_hits, (unsigned long long) asp->fas_miss); #else @@ -1760,7 +1874,7 @@ fr_authstat_t *asp; * authentication, separately. */ static void showgroups(fiop) -struct friostat *fiop; + struct friostat *fiop; { static char *gnames[3] = { "Filter", "Accounting", "Authentication" }; static int gnums[3] = { IPL_LOGIPF, IPL_LOGCOUNT, IPL_LOGAUTH }; @@ -1788,10 +1902,11 @@ struct friostat *fiop; } } + static void parse_ipportstr(argument, ip, port) -const char *argument; -i6addr_t *ip; -int *port; + const char *argument; + i6addr_t *ip; + int *port; { char *s, *comma; int ok = 0; @@ -1843,20 +1958,20 @@ int *port; #ifdef STATETOP static void sig_resize(s) -int s; + int s; { handle_resize = 1; } static void sig_break(s) -int s; + int s; { handle_break = 1; } static char *getip(v, addr) -int v; -i6addr_t *addr; + int v; + i6addr_t *addr; { #ifdef USE_INET6 static char hostbuf[MAXHOSTNAMELEN+1]; @@ -1876,7 +1991,7 @@ i6addr_t *addr; static char *ttl_to_string(ttl) -long int ttl; + long int ttl; { static char ttlbuf[STSTRSIZE]; int hours, minutes, seconds; @@ -1898,8 +2013,8 @@ long int ttl; static int sort_pkts(a, b) -const void *a; -const void *b; + const void *a; + const void *b; { register const statetop_t *ap = a; @@ -1914,8 +2029,8 @@ const void *b; static int sort_bytes(a, b) -const void *a; -const void *b; + const void *a; + const void *b; { register const statetop_t *ap = a; register const statetop_t *bp = b; @@ -1929,8 +2044,8 @@ const void *b; static int sort_p(a, b) -const void *a; -const void *b; + const void *a; + const void *b; { register const statetop_t *ap = a; register const statetop_t *bp = b; @@ -1944,8 +2059,8 @@ const void *b; static int sort_ttl(a, b) -const void *a; -const void *b; + const void *a; + const void *b; { register const statetop_t *ap = a; register const statetop_t *bp = b; @@ -1958,8 +2073,8 @@ const void *b; } static int sort_srcip(a, b) -const void *a; -const void *b; + const void *a; + const void *b; { register const statetop_t *ap = a; register const statetop_t *bp = b; @@ -1984,8 +2099,8 @@ const void *b; } static int sort_srcpt(a, b) -const void *a; -const void *b; + const void *a; + const void *b; { register const statetop_t *ap = a; register const statetop_t *bp = b; @@ -1998,8 +2113,8 @@ const void *b; } static int sort_dstip(a, b) -const void *a; -const void *b; + const void *a; + const void *b; { register const statetop_t *ap = a; register const statetop_t *bp = b; @@ -2024,8 +2139,8 @@ const void *b; } static int sort_dstpt(a, b) -const void *a; -const void *b; + const void *a; + const void *b; { register const statetop_t *ap = a; register const statetop_t *bp = b; @@ -2041,9 +2156,8 @@ const void *b; ipstate_t *fetchstate(src, dst) -ipstate_t *src, *dst; + ipstate_t *src, *dst; { - int i; if (live_kernel == 1) { ipfgeniter_t state; @@ -2061,8 +2175,8 @@ ipstate_t *src, *dst; if (ioctl(state_fd, SIOCGENITER, &obj) != 0) return NULL; if (dst->is_next == NULL) { - i = IPFGENITER_STATE; - ioctl(state_fd, SIOCIPFDELTOK, &i); + int n = IPFGENITER_STATE; + (void) ioctl(ipf_fd,SIOCIPFDELTOK, &n); } } else { if (kmemcpy((char *)dst, (u_long)src, sizeof(*dst))) @@ -2073,8 +2187,8 @@ ipstate_t *src, *dst; static int fetchfrag(fd, type, frp) -int fd, type; -ipfr_t *frp; + int fd, type; + ipfr_t *frp; { ipfgeniter_t frag; ipfobj_t obj; @@ -2094,8 +2208,155 @@ ipfr_t *frp; } +static int state_matcharray(stp, array) + ipstate_t *stp; + int *array; +{ + int i, n, *x, rv, p; + ipfexp_t *e; + + rv = 0; + + for (n = array[0], x = array + 1; n > 0; x += e->ipfe_size) { + e = (ipfexp_t *)x; + if (e->ipfe_cmd == IPF_EXP_END) + break; + n -= e->ipfe_size; + + rv = 0; + /* + * The upper 16 bits currently store the protocol value. + * This is currently used with TCP and UDP port compares and + * allows "tcp.port = 80" without requiring an explicit + " "ip.pr = tcp" first. + */ + p = e->ipfe_cmd >> 16; + if ((p != 0) && (p != stp->is_p)) + break; + + switch (e->ipfe_cmd) + { + case IPF_EXP_IP_PR : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (stp->is_p == e->ipfe_arg0[i]); + } + break; + + case IPF_EXP_IP_SRCADDR : + if (stp->is_v != 4) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= ((stp->is_saddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]); + } + break; + + case IPF_EXP_IP_DSTADDR : + if (stp->is_v != 4) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= ((stp->is_daddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]); + } + break; + + case IPF_EXP_IP_ADDR : + if (stp->is_v != 4) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= ((stp->is_saddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]) || + ((stp->is_daddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]); + } + break; + +#ifdef USE_INET6 + case IPF_EXP_IP6_SRCADDR : + if (stp->is_v != 6) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= IP6_MASKEQ(&stp->is_src, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]); + } + break; + + case IPF_EXP_IP6_DSTADDR : + if (stp->is_v != 6) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= IP6_MASKEQ(&stp->is_dst, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]); + } + break; + + case IPF_EXP_IP6_ADDR : + if (stp->is_v != 6) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= IP6_MASKEQ(&stp->is_src, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]) || + IP6_MASKEQ(&stp->is_dst, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]); + } + break; +#endif + + case IPF_EXP_UDP_PORT : + case IPF_EXP_TCP_PORT : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (stp->is_sport == e->ipfe_arg0[i]) || + (stp->is_dport == e->ipfe_arg0[i]); + } + break; + + case IPF_EXP_UDP_SPORT : + case IPF_EXP_TCP_SPORT : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (stp->is_sport == e->ipfe_arg0[i]); + } + break; + + case IPF_EXP_UDP_DPORT : + case IPF_EXP_TCP_DPORT : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (stp->is_dport == e->ipfe_arg0[i]); + } + break; + + case IPF_EXP_IDLE_GT : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (stp->is_die < e->ipfe_arg0[i]); + } + break; + + case IPF_EXP_TCP_STATE : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (stp->is_state[0] == e->ipfe_arg0[i]) || + (stp->is_state[1] == e->ipfe_arg0[i]); + } + break; + } + rv ^= e->ipfe_not; + + if (rv == 0) + break; + } + + return rv; +} + + static void showtqtable_live(fd) -int fd; + int fd; { ipftq_t table[IPF_TCP_NSTATES]; ipfobj_t obj; diff --git a/tools/ipfsyncd.c b/tools/ipfsyncd.c new file mode 100644 index 0000000000000..d4671e409d638 --- /dev/null +++ b/tools/ipfsyncd.c @@ -0,0 +1,671 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ +#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: ipfsyncd.c,v 1.1.2.2 2012/07/22 08:04:24 darren_r Exp $"; +#endif +#include <sys/types.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <sys/sockio.h> +#include <sys/errno.h> + +#include <netinet/in.h> +#include <net/if.h> + +#include <arpa/inet.h> + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <syslog.h> +#include <signal.h> + +#include "ipf.h" +#include "opts.h" + + +#define R_IO_ERROR -1 +#define R_OKAY 0 +#define R_MORE 1 +#define R_SKIP 2 +#if defined(sun) && !defined(SOLARIS2) +# define STRERROR(x) sys_errlist[x] +extern char *sys_errlist[]; +#else +# define STRERROR(x) strerror(x) +#endif + + +int main __P((int, char *[])); +void usage __P((char *)); +void printsynchdr __P((synchdr_t *)); +void printtable __P((int)); +void printsmcproto __P((char *)); +void printcommand __P((int)); +int do_kbuff __P((int, char *, int *)); +int do_packet __P((int, char *)); +int buildsocket __P((char *, struct sockaddr_in *)); +void do_io __P((void)); +void handleterm __P((int)); + +int terminate = 0; +int igmpfd = -1; +int nfd = -1; +int lfd = -1; +int opts = 0; + +void +usage(progname) + char *progname; +{ + fprintf(stderr, + "Usage: %s [-d] [-p port] [-i address] -I <interface>\n", + progname); +} + +void +handleterm(sig) + int sig; +{ + terminate = sig; +} + + +/* should be large enough to hold header + any datatype */ +#define BUFFERLEN 1400 + +int +main(argc, argv) + int argc; + char *argv[]; +{ + struct sockaddr_in sin; + char *interface; + char *progname; + int opt, tries; + + progname = strrchr(argv[0], '/'); + if (progname) { + progname++; + } else { + progname = argv[0]; + } + + opts = 0; + tries = 0; + interface = NULL; + + bzero((char *)&sin, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(0xaf6c); + sin.sin_addr.s_addr = htonl(INADDR_UNSPEC_GROUP | 0x697066); + + while ((opt = getopt(argc, argv, "di:I:p:")) != -1) + switch (opt) + { + case 'd' : + debuglevel++; + break; + case 'I' : + interface = optarg; + break; + case 'i' : + sin.sin_addr.s_addr = inet_addr(optarg); + break; + case 'p' : + sin.sin_port = htons(atoi(optarg)); + break; + } + + if (interface == NULL) { + usage(progname); + exit(1); + } + + if (!debuglevel) { + +#if BSD >= 199306 + daemon(0, 0); +#else + int fd = open("/dev/null", O_RDWR); + + switch (fork()) + { + case 0 : + break; + + case -1 : + fprintf(stderr, "%s: fork() failed: %s\n", + argv[0], STRERROR(errno)); + exit(1); + /* NOTREACHED */ + + default : + exit(0); + /* NOTREACHED */ + } + + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + close(fd); + + setsid(); +#endif + } + + signal(SIGHUP, handleterm); + signal(SIGINT, handleterm); + signal(SIGTERM, handleterm); + + openlog(progname, LOG_PID, LOG_SECURITY); + + while (!terminate) { + if (lfd != -1) { + close(lfd); + lfd = -1; + } + if (nfd != -1) { + close(nfd); + nfd = -1; + } + if (igmpfd != -1) { + close(igmpfd); + igmpfd = -1; + } + + if (buildsocket(interface, &sin) == -1) + goto tryagain; + + lfd = open(IPSYNC_NAME, O_RDWR); + if (lfd == -1) { + syslog(LOG_ERR, "open(%s):%m", IPSYNC_NAME); + debug(1, "open(%s): %s\n", IPSYNC_NAME, + STRERROR(errno)); + goto tryagain; + } + + tries = -1; + do_io(); +tryagain: + tries++; + syslog(LOG_INFO, "retry in %d seconds", 1 << tries); + debug(1, "wait %d seconds\n", 1 << tries); + sleep(1 << tries); + } + + + /* terminate */ + if (lfd != -1) + close(lfd); + if (nfd != -1) + close(nfd); + + syslog(LOG_ERR, "signal %d received, exiting...", terminate); + debug(1, "signal %d received, exiting...", terminate); + + exit(1); +} + + +void +do_io() +{ + char nbuff[BUFFERLEN]; + char buff[BUFFERLEN]; + fd_set mrd, rd; + int maxfd; + int inbuf; + int n1; + int left; + + FD_ZERO(&mrd); + FD_SET(lfd, &mrd); + FD_SET(nfd, &mrd); + maxfd = nfd; + if (lfd > maxfd) + maxfd = lfd; + debug(2, "nfd %d lfd %d maxfd %d\n", nfd, lfd, maxfd); + + inbuf = 0; + /* + * A threaded approach to this loop would have one thread + * work on reading lfd (only) all the time and another thread + * working on reading nfd all the time. + */ + while (!terminate) { + int n; + + rd = mrd; + + n = select(maxfd + 1, &rd, NULL, NULL, NULL); + if (n < 0) { + switch (errno) + { + case EINTR : + continue; + default : + syslog(LOG_ERR, "select error: %m"); + debug(1, "select error: %s\n", STRERROR(errno)); + return; + } + } + + if (FD_ISSET(lfd, &rd)) { + n1 = read(lfd, buff+inbuf, BUFFERLEN-inbuf); + + debug(3, "read(K):%d\n", n1); + + if (n1 <= 0) { + syslog(LOG_ERR, "read error (k-header): %m"); + debug(1, "read error (k-header): %s\n", + STRERROR(errno)); + return; + } + + left = 0; + + switch (do_kbuff(n1, buff, &left)) + { + case R_IO_ERROR : + return; + case R_MORE : + inbuf += left; + break; + default : + inbuf = 0; + break; + } + } + + if (FD_ISSET(nfd, &rd)) { + n1 = recv(nfd, nbuff, sizeof(nbuff), 0); + + debug(3, "read(N):%d\n", n1); + + if (n1 <= 0) { + syslog(LOG_ERR, "read error (n-header): %m"); + debug(1, "read error (n-header): %s\n", + STRERROR(errno)); + return; + } + + switch (do_packet(n1, nbuff)) + { + case R_IO_ERROR : + return; + default : + break; + } + } + } +} + + +int +buildsocket(nicname, sinp) + char *nicname; + struct sockaddr_in *sinp; +{ + struct sockaddr_in *reqip; + struct ifreq req; + char opt; + + debug(2, "binding to %s:%s\n", nicname, inet_ntoa(sinp->sin_addr)); + + if (IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) { + struct in_addr addr; + struct ip_mreq mreq; + + igmpfd = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP); + if (igmpfd == -1) { + syslog(LOG_ERR, "socket:%m"); + debug(1, "socket:%s\n", STRERROR(errno)); + return -1; + } + + bzero((char *)&req, sizeof(req)); + strncpy(req.ifr_name, nicname, sizeof(req.ifr_name)); + req.ifr_name[sizeof(req.ifr_name) - 1] = '\0'; + if (ioctl(igmpfd, SIOCGIFADDR, &req) == -1) { + syslog(LOG_ERR, "ioctl(SIOCGIFADDR):%m"); + debug(1, "ioctl(SIOCGIFADDR):%s\n", STRERROR(errno)); + close(igmpfd); + igmpfd = -1; + return -1; + } + reqip = (struct sockaddr_in *)&req.ifr_addr; + + addr = reqip->sin_addr; + if (setsockopt(igmpfd, IPPROTO_IP, IP_MULTICAST_IF, + (char *)&addr, sizeof(addr)) == -1) { + syslog(LOG_ERR, "setsockopt(IP_MULTICAST_IF(%s)):%m", + inet_ntoa(addr)); + debug(1, "setsockopt(IP_MULTICAST_IF(%s)):%s\n", + inet_ntoa(addr), STRERROR(errno)); + close(igmpfd); + igmpfd = -1; + return -1; + } + + opt = 0; + if (setsockopt(igmpfd, IPPROTO_IP, IP_MULTICAST_LOOP, + (char *)&opt, sizeof(opt)) == -1) { + syslog(LOG_ERR, "setsockopt(IP_MULTICAST_LOOP=0):%m"); + debug(1, "setsockopt(IP_MULTICAST_LOOP=0):%s\n", + STRERROR(errno)); + close(igmpfd); + igmpfd = -1; + return -1; + } + + opt = 63; + if (setsockopt(igmpfd, IPPROTO_IP, IP_MULTICAST_TTL, + (char *)&opt, sizeof(opt)) == -1) { + syslog(LOG_ERR, "setsockopt(IP_MULTICAST_TTL=%d):%m", + opt); + debug(1, "setsockopt(IP_MULTICAST_TTL=%d):%s\n", opt, + STRERROR(errno)); + close(igmpfd); + igmpfd = -1; + return -1; + } + + mreq.imr_multiaddr.s_addr = sinp->sin_addr.s_addr; + mreq.imr_interface.s_addr = reqip->sin_addr.s_addr; + + if (setsockopt(igmpfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, + (char *)&mreq, sizeof(mreq)) == -1) { + char buffer[80]; + + sprintf(buffer, "%s,", inet_ntoa(sinp->sin_addr)); + strcat(buffer, inet_ntoa(reqip->sin_addr)); + + syslog(LOG_ERR, + "setsockpt(IP_ADD_MEMBERSHIP,%s):%m", buffer); + debug(1, "setsockpt(IP_ADD_MEMBERSHIP,%s):%s\n", + buffer, STRERROR(errno)); + close(igmpfd); + igmpfd = -1; + return -1; + } + } + nfd = socket(AF_INET, SOCK_DGRAM, 0); + if (nfd == -1) { + syslog(LOG_ERR, "socket:%m"); + if (igmpfd != -1) { + close(igmpfd); + igmpfd = -1; + } + return -1; + } + bzero((char *)&req, sizeof(req)); + strncpy(req.ifr_name, nicname, sizeof(req.ifr_name)); + req.ifr_name[sizeof(req.ifr_name) - 1] = '\0'; + if (ioctl(nfd, SIOCGIFADDR, &req) == -1) { + syslog(LOG_ERR, "ioctl(SIOCGIFADDR):%m"); + debug(1, "ioctl(SIOCGIFADDR):%s\n", STRERROR(errno)); + close(igmpfd); + igmpfd = -1; + return -1; + } + + if (bind(nfd, (struct sockaddr *)&req.ifr_addr, + sizeof(req.ifr_addr)) == -1) { + syslog(LOG_ERR, "bind:%m"); + debug(1, "bind:%s\n", STRERROR(errno)); + close(nfd); + if (igmpfd != -1) { + close(igmpfd); + igmpfd = -1; + } + nfd = -1; + return -1; + } + + if (connect(nfd, (struct sockaddr *)sinp, sizeof(*sinp)) == -1) { + syslog(LOG_ERR, "connect:%m"); + debug(1, "connect:%s\n", STRERROR(errno)); + close(nfd); + if (igmpfd != -1) { + close(igmpfd); + igmpfd = -1; + } + nfd = -1; + return -1; + } + syslog(LOG_INFO, "Sending data to %s", inet_ntoa(sinp->sin_addr)); + debug(3, "Sending data to %s\n", inet_ntoa(sinp->sin_addr)); + + return nfd; +} + + +int +do_packet(pklen, buff) + int pklen; + char *buff; +{ + synchdr_t *sh; + u_32_t magic; + int len; + int n2; + int n3; + + while (pklen > 0) { + if (pklen < sizeof(*sh)) { + syslog(LOG_ERR, "packet length too short:%d", pklen); + debug(2, "packet length too short:%d\n", pklen); + return R_SKIP; + } + + sh = (synchdr_t *)buff; + len = ntohl(sh->sm_len); + magic = ntohl(sh->sm_magic); + + if (magic != SYNHDRMAGIC) { + syslog(LOG_ERR, "invalid header magic %x", magic); + debug(2, "invalid header magic %x\n", magic); + return R_SKIP; + } + + if (pklen < len + sizeof(*sh)) { + syslog(LOG_ERR, "packet length too short:%d", pklen); + debug(2, "packet length too short:%d\n", pklen); + return R_SKIP; + } + + if (debuglevel > 3) { + printsynchdr(sh); + printcommand(sh->sm_cmd); + printtable(sh->sm_table); + printsmcproto(buff); + } + + n2 = sizeof(*sh) + len; + + do { + n3 = write(lfd, buff, n2); + if (n3 <= 0) { + syslog(LOG_ERR, "write error: %m"); + debug(1, "write error: %s\n", STRERROR(errno)); + return R_IO_ERROR; + } + + n2 -= n3; + buff += n3; + pklen -= n3; + } while (n3 != 0); + } + + return R_OKAY; +} + + + +int +do_kbuff(inbuf, buf, left) + int inbuf, *left; + char *buf; +{ + synchdr_t *sh; + u_32_t magic; + int complete; + int sendlen; + int error; + int bytes; + int len; + int n2; + int n3; + + sendlen = 0; + bytes = inbuf; + error = R_OKAY; + sh = (synchdr_t *)buf; + + for (complete = 0; bytes > 0; complete++) { + len = ntohl(sh->sm_len); + magic = ntohl(sh->sm_magic); + + if (magic != SYNHDRMAGIC) { + syslog(LOG_ERR, + "read invalid header magic 0x%x, flushing", + magic); + debug(2, "read invalid header magic 0x%x, flushing\n", + magic); + n2 = SMC_RLOG; + (void) ioctl(lfd, SIOCIPFFL, &n2); + break; + } + + if (debuglevel > 3) { + printsynchdr(sh); + printcommand(sh->sm_cmd); + printtable(sh->sm_table); + putchar('\n'); + } + + if (bytes < sizeof(*sh) + len) { + debug(3, "Not enough bytes %d < %d\n", bytes, + sizeof(*sh) + len); + error = R_MORE; + break; + } + + if (debuglevel > 3) { + printsmcproto(buf); + } + + sendlen += len + sizeof(*sh); + sh = (synchdr_t *)(buf + sendlen); + bytes -= sendlen; + } + + if (complete) { + n3 = send(nfd, buf, sendlen, 0); + if (n3 <= 0) { + syslog(LOG_ERR, "write error: %m"); + debug(1, "write error: %s\n", STRERROR(errno)); + return R_IO_ERROR; + } + debug(3, "send on %d len %d = %d\n", nfd, sendlen, n3); + error = R_OKAY; + } + + /* move buffer to the front,we might need to make + * this more efficient, by using a rolling pointer + * over the buffer and only copying it, when + * we are reaching the end + */ + if (bytes > 0) { + bcopy(buf + bytes, buf, bytes); + error = R_MORE; + } + debug(4, "complete %d bytes %d error %d\n", complete, bytes, error); + + *left = bytes; + + return error; +} + + +void +printcommand(cmd) + int cmd; +{ + + switch (cmd) + { + case SMC_CREATE : + printf(" cmd:CREATE"); + break; + case SMC_UPDATE : + printf(" cmd:UPDATE"); + break; + default : + printf(" cmd:Unknown(%d)", cmd); + break; + } +} + + +void +printtable(table) + int table; +{ + switch (table) + { + case SMC_NAT : + printf(" table:NAT"); + break; + case SMC_STATE : + printf(" table:STATE"); + break; + default : + printf(" table:Unknown(%d)", table); + break; + } +} + + +void +printsmcproto(buff) + char *buff; +{ + syncupdent_t *su; + synchdr_t *sh; + + sh = (synchdr_t *)buff; + + if (sh->sm_cmd == SMC_CREATE) { + ; + + } else if (sh->sm_cmd == SMC_UPDATE) { + su = (syncupdent_t *)buff; + if (sh->sm_p == IPPROTO_TCP) { + printf(" TCP Update: age %lu state %d/%d\n", + su->sup_tcp.stu_age, + su->sup_tcp.stu_state[0], + su->sup_tcp.stu_state[1]); + } + } else { + printf("Unknown command\n"); + } +} + + +void +printsynchdr(sh) + synchdr_t *sh; +{ + + printf("v:%d p:%d num:%d len:%d magic:%x", sh->sm_v, sh->sm_p, + ntohl(sh->sm_num), ntohl(sh->sm_len), ntohl(sh->sm_magic)); +} diff --git a/tools/ipftest.c b/tools/ipftest.c index 8343b2c3b27c1..495bdf4755594 100644 --- a/tools/ipftest.c +++ b/tools/ipftest.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -10,24 +10,23 @@ #if !defined(lint) static const char sccsid[] = "@(#)ipt.c 1.19 6/3/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipftest.c,v 1.44.2.13 2006/12/12 16:13:01 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif extern char *optarg; -extern struct frentry *ipfilter[2][2]; -extern struct ipread snoop, etherf, tcpd, pcap, iptext, iphex; +extern struct ipread pcap, iptext, iphex; extern struct ifnet *get_unit __P((char *, int)); extern void init_ifp __P((void)); extern ipnat_t *natparse __P((char *, int)); -extern int fr_running; extern hostmap_t **ipf_hm_maptable; extern hostmap_t *ipf_hm_maplist; -ipfmutex_t ipl_mutex, ipf_authmx, ipf_rw, ipf_stinsert; +ipfmutex_t ipl_mutex, ipf_auth_mx, ipf_rw, ipf_stinsert; ipfmutex_t ipf_nat_new, ipf_natio, ipf_timeoutlock; ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag, ip_poolrw, ipf_frcache; -ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth, ipf_tokens; -int opts = OPT_DONOTHING; +ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_authlk; +ipfrwlock_t ipf_tokens; +int opts = OPT_DONTOPEN; int use_inet6 = 0; int docksum = 0; int pfil_delayed_copy = 0; @@ -35,10 +34,10 @@ int main __P((int, char *[])); int loadrules __P((char *, int)); int kmemcpy __P((char *, long, int)); int kstrncpy __P((char *, long, int n)); -void dumpnat __P((void)); -void dumpstate __P((void)); -void dumplookups __P((void)); -void dumpgroups __P((void)); +int blockreason; +void dumpnat __P((void *)); +void dumpgroups __P((ipf_main_softc_t *)); +void dumprules __P((frentry_t *)); void drain_log __P((char *)); void fixv4sums __P((mb_t *, ip_t *)); @@ -70,18 +69,20 @@ static ioctlfunc_t iocfunctions[IPL_LOGSIZE] = { ipftestioctl, ipscantestioctl, ipooltestioctl, NULL }; +static ipf_main_softc_t *softc = NULL; -int main(argc,argv) -int argc; -char *argv[]; +int +main(argc,argv) + int argc; + char *argv[]; { char *datain, *iface, *ifname, *logout; int fd, i, dir, c, loaded, dump, hlen; struct in_addr sip; struct ifnet *ifp; struct ipread *r; - mb_t mb, *m; + mb_t mb, *m, *n; ip_t *ip; m = &mb; @@ -96,18 +97,20 @@ char *argv[]; sip.s_addr = 0; ifname = "anon0"; - MUTEX_INIT(&ipf_rw, "ipf rw mutex"); - MUTEX_INIT(&ipf_timeoutlock, "ipf timeout lock"); - RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex"); - RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock"); - RWLOCK_INIT(&ipf_ipidfrag, "ipf IP NAT-Frag rwlock"); - RWLOCK_INIT(&ipf_frcache, "ipf filter cache"); - RWLOCK_INIT(&ipf_tokens, "ipf token rwlock"); - initparse(); - if (fr_initialise() == -1) - abort(); - fr_running = 1; + + ipf_load_all(); + + softc = ipf_create_all(NULL); + if (softc == NULL) + exit(1); + + if (ipf_init_all(softc) == -1) + exit(1); + + i = 1; + if (ipftestioctl(IPL_LOGIPF, SIOCFRENB, &i) != 0) + exit(1); while ((c = getopt(argc, argv, "6bCdDF:i:I:l:N:P:or:RS:T:vxX")) != -1) switch (c) @@ -135,12 +138,6 @@ char *argv[]; case 'F' : if (strcasecmp(optarg, "pcap") == 0) r = &pcap; - else if (strcasecmp(optarg, "etherfind") == 0) - r = ðerf; - else if (strcasecmp(optarg, "snoop") == 0) - r = &snoop; - else if (strcasecmp(optarg, "tcpdump") == 0) - r = &tcpd; else if (strcasecmp(optarg, "hex") == 0) r = &iphex; else if (strcasecmp(optarg, "text") == 0) @@ -206,18 +203,21 @@ char *argv[]; else fd = (*r->r_open)("-"); - if (fd < 0) + if (fd < 0) { + perror("error opening input"); exit(-1); + } + + m->m_data = (char *)m->mb_buf; + while ((i = (*r->r_readip)(m, &iface, &dir)) > 0) { - ip = MTOD(m, ip_t *); - while ((i = (*r->r_readip)(MTOD(m, char *), sizeof(m->mb_buf), - &iface, &dir)) > 0) { if ((iface == NULL) || (*iface == '\0')) iface = ifname; + + ip = MTOD(m, ip_t *); ifp = get_unit(iface, IP_V(ip)); - if (!use_inet6) { - ip->ip_off = ntohs(ip->ip_off); - ip->ip_len = ntohs(ip->ip_len); + + if (IP_V(ip) == 4) { if ((r->r_flags & R_DO_CKSUM) || docksum) fixv4sums(m, ip); hlen = IP_HL(ip) << 2; @@ -229,9 +229,11 @@ char *argv[]; hlen = sizeof(ip6_t); #endif /* ipfr_slowtimer(); */ + blockreason = 0; m = &mb; + m->mb_ifp = ifp; m->mb_len = i; - i = fr_check(ip, hlen, ifp, dir, &m); + i = ipf_check(softc, ip, hlen, ifp, dir, &m); if ((opts & OPT_NAT) == 0) switch (i) { @@ -269,17 +271,24 @@ char *argv[]; (void)printf("recognised return %#x\n", i); break; } - if (!use_inet6) { - ip->ip_off = htons(ip->ip_off); - ip->ip_len = htons(ip->ip_len); - } if (!(opts & OPT_BRIEF)) { putchar(' '); - printpacket(ip); + if (m != NULL) + printpacket(dir, m); + else + printpacket(dir, &mb); printf("--------------"); - } else if ((opts & (OPT_BRIEF|OPT_NAT)) == (OPT_NAT|OPT_BRIEF)) - printpacket(ip); + } else if ((opts & (OPT_BRIEF|OPT_NAT)) == + (OPT_NAT|OPT_BRIEF)) { + if (m != NULL) + printpacket(dir, m); + else + PRINTF("%d\n", blockreason); + } + + ipf_state_flush(softc, 1, 0); + if (dir && (ifp != NULL) && IP_V(ip) && (m != NULL)) #if defined(__sgi) && (IRIX < 60500) (*ifp->if_output)(ifp, (void *)m, NULL); @@ -290,6 +299,13 @@ char *argv[]; (*ifp->if_output)(ifp, (void *)m, NULL, 0); # endif #endif + + while ((m != NULL) && (m != &mb)) { + n = m->mb_next; + freembt(m); + m = n; + } + if ((opts & (OPT_BRIEF|OPT_NAT)) != (OPT_NAT|OPT_BRIEF)) putchar('\n'); dir = 0; @@ -298,6 +314,7 @@ char *argv[]; iface = ifname; } m = &mb; + m->mb_data = (char *)m->mb_buf; } if (i != 0) @@ -309,14 +326,25 @@ char *argv[]; } if (dump == 1) { - dumpnat(); - dumpstate(); - dumplookups(); - dumpgroups(); + dumpnat(softc->ipf_nat_soft); + ipf_state_dump(softc, softc->ipf_state_soft); + ipf_lookup_dump(softc, softc->ipf_state_soft); + dumpgroups(softc); } - fr_deinitialise(); + ipf_fini_all(softc); + + ipf_destroy_all(softc); + + ipf_unload_all(); + ipf_mutex_clean(); + ipf_rwlock_clean(); + + if (getenv("FINDLEAKS")) { + fflush(stdout); + abort(); + } return 0; } @@ -330,14 +358,15 @@ int ipftestioctl(int dev, ioctlcmd_t cmd, ...) va_list ap; int i; + dev = dev; /* gcc -Wextra */ va_start(ap, cmd); data = va_arg(ap, caddr_t); va_end(ap); - i = iplioctl(IPL_LOGIPF, cmd, data, FWRITE|FREAD); + i = ipfioctl(softc, IPL_LOGIPF, cmd, data, FWRITE|FREAD); if (opts & OPT_DEBUG) - fprintf(stderr, "iplioctl(IPF,%#x,%p) = %d\n", - (u_int)cmd, data, i); + fprintf(stderr, "ipfioctl(IPF,%#x,%p) = %d (%d)\n", + (u_int)cmd, data, i, softc->ipf_interror); if (i != 0) { errno = i; return -1; @@ -352,13 +381,14 @@ int ipnattestioctl(int dev, ioctlcmd_t cmd, ...) va_list ap; int i; + dev = dev; /* gcc -Wextra */ va_start(ap, cmd); data = va_arg(ap, caddr_t); va_end(ap); - i = iplioctl(IPL_LOGNAT, cmd, data, FWRITE|FREAD); + i = ipfioctl(softc, IPL_LOGNAT, cmd, data, FWRITE|FREAD); if (opts & OPT_DEBUG) - fprintf(stderr, "iplioctl(NAT,%#x,%p) = %d\n", + fprintf(stderr, "ipfioctl(NAT,%#x,%p) = %d\n", (u_int)cmd, data, i); if (i != 0) { errno = i; @@ -374,13 +404,14 @@ int ipstatetestioctl(int dev, ioctlcmd_t cmd, ...) va_list ap; int i; + dev = dev; /* gcc -Wextra */ va_start(ap, cmd); data = va_arg(ap, caddr_t); va_end(ap); - i = iplioctl(IPL_LOGSTATE, cmd, data, FWRITE|FREAD); + i = ipfioctl(softc, IPL_LOGSTATE, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) - fprintf(stderr, "iplioctl(STATE,%#x,%p) = %d\n", + fprintf(stderr, "ipfioctl(STATE,%#x,%p) = %d\n", (u_int)cmd, data, i); if (i != 0) { errno = i; @@ -396,13 +427,14 @@ int ipauthtestioctl(int dev, ioctlcmd_t cmd, ...) va_list ap; int i; + dev = dev; /* gcc -Wextra */ va_start(ap, cmd); data = va_arg(ap, caddr_t); va_end(ap); - i = iplioctl(IPL_LOGAUTH, cmd, data, FWRITE|FREAD); + i = ipfioctl(softc, IPL_LOGAUTH, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) - fprintf(stderr, "iplioctl(AUTH,%#x,%p) = %d\n", + fprintf(stderr, "ipfioctl(AUTH,%#x,%p) = %d\n", (u_int)cmd, data, i); if (i != 0) { errno = i; @@ -418,13 +450,14 @@ int ipscantestioctl(int dev, ioctlcmd_t cmd, ...) va_list ap; int i; + dev = dev; /* gcc -Wextra */ va_start(ap, cmd); data = va_arg(ap, caddr_t); va_end(ap); - i = iplioctl(IPL_LOGSCAN, cmd, data, FWRITE|FREAD); + i = ipfioctl(softc, IPL_LOGSCAN, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) - fprintf(stderr, "iplioctl(SCAN,%#x,%p) = %d\n", + fprintf(stderr, "ipfioctl(SCAN,%#x,%p) = %d\n", (u_int)cmd, data, i); if (i != 0) { errno = i; @@ -440,13 +473,14 @@ int ipsynctestioctl(int dev, ioctlcmd_t cmd, ...) va_list ap; int i; + dev = dev; /* gcc -Wextra */ va_start(ap, cmd); data = va_arg(ap, caddr_t); va_end(ap); - i = iplioctl(IPL_LOGSYNC, cmd, data, FWRITE|FREAD); + i = ipfioctl(softc, IPL_LOGSYNC, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) - fprintf(stderr, "iplioctl(SYNC,%#x,%p) = %d\n", + fprintf(stderr, "ipfioctl(SYNC,%#x,%p) = %d\n", (u_int)cmd, data, i); if (i != 0) { errno = i; @@ -462,14 +496,15 @@ int ipooltestioctl(int dev, ioctlcmd_t cmd, ...) va_list ap; int i; + dev = dev; /* gcc -Wextra */ va_start(ap, cmd); data = va_arg(ap, caddr_t); va_end(ap); - i = iplioctl(IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD); + i = ipfioctl(softc, IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) - fprintf(stderr, "iplioctl(POOL,%#x,%p) = %d\n", - (u_int)cmd, data, i); + fprintf(stderr, "ipfioctl(POOL,%#x,%p) = %d (%d)\n", + (u_int)cmd, data, i, softc->ipf_interror); if (i != 0) { errno = i; return -1; @@ -478,15 +513,17 @@ int ipooltestioctl(int dev, ioctlcmd_t cmd, ...) } #else int ipftestioctl(dev, cmd, data) -dev_t dev; -ioctlcmd_t cmd; -void *data; + dev_t dev; + ioctlcmd_t cmd; + void *data; { int i; - i = iplioctl(IPL_LOGIPF, cmd, data, FWRITE|FREAD); + dev = dev; /* gcc -Wextra */ + i = ipfioctl(softc, IPL_LOGIPF, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) - fprintf(stderr, "iplioctl(IPF,%#x,%p) = %d\n", cmd, data, i); + fprintf(stderr, "ipfioctl(IPF,%#x,%p) = %d (%d)\n", + cmd, data, i, softc->ipf_interror); if (i != 0) { errno = i; return -1; @@ -496,15 +533,16 @@ void *data; int ipnattestioctl(dev, cmd, data) -dev_t dev; -ioctlcmd_t cmd; -void *data; + dev_t dev; + ioctlcmd_t cmd; + void *data; { int i; - i = iplioctl(IPL_LOGNAT, cmd, data, FWRITE|FREAD); + dev = dev; /* gcc -Wextra */ + i = ipfioctl(softc, IPL_LOGNAT, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) - fprintf(stderr, "iplioctl(NAT,%#x,%p) = %d\n", cmd, data, i); + fprintf(stderr, "ipfioctl(NAT,%#x,%p) = %d\n", cmd, data, i); if (i != 0) { errno = i; return -1; @@ -514,15 +552,16 @@ void *data; int ipstatetestioctl(dev, cmd, data) -dev_t dev; -ioctlcmd_t cmd; -void *data; + dev_t dev; + ioctlcmd_t cmd; + void *data; { int i; - i = iplioctl(IPL_LOGSTATE, cmd, data, FWRITE|FREAD); + dev = dev; /* gcc -Wextra */ + i = ipfioctl(softc, IPL_LOGSTATE, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) - fprintf(stderr, "iplioctl(STATE,%#x,%p) = %d\n", cmd, data, i); + fprintf(stderr, "ipfioctl(STATE,%#x,%p) = %d\n", cmd, data, i); if (i != 0) { errno = i; return -1; @@ -532,15 +571,16 @@ void *data; int ipauthtestioctl(dev, cmd, data) -dev_t dev; -ioctlcmd_t cmd; -void *data; + dev_t dev; + ioctlcmd_t cmd; + void *data; { int i; - i = iplioctl(IPL_LOGAUTH, cmd, data, FWRITE|FREAD); + dev = dev; /* gcc -Wextra */ + i = ipfioctl(softc, IPL_LOGAUTH, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) - fprintf(stderr, "iplioctl(AUTH,%#x,%p) = %d\n", cmd, data, i); + fprintf(stderr, "ipfioctl(AUTH,%#x,%p) = %d\n", cmd, data, i); if (i != 0) { errno = i; return -1; @@ -550,15 +590,16 @@ void *data; int ipsynctestioctl(dev, cmd, data) -dev_t dev; -ioctlcmd_t cmd; -void *data; + dev_t dev; + ioctlcmd_t cmd; + void *data; { int i; - i = iplioctl(IPL_LOGSYNC, cmd, data, FWRITE|FREAD); + dev = dev; /* gcc -Wextra */ + i = ipfioctl(softc, IPL_LOGSYNC, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) - fprintf(stderr, "iplioctl(SYNC,%#x,%p) = %d\n", cmd, data, i); + fprintf(stderr, "ipfioctl(SYNC,%#x,%p) = %d\n", cmd, data, i); if (i != 0) { errno = i; return -1; @@ -568,15 +609,16 @@ void *data; int ipscantestioctl(dev, cmd, data) -dev_t dev; -ioctlcmd_t cmd; -void *data; + dev_t dev; + ioctlcmd_t cmd; + void *data; { int i; - i = iplioctl(IPL_LOGSCAN, cmd, data, FWRITE|FREAD); + dev = dev; /* gcc -Wextra */ + i = ipfioctl(softc, IPL_LOGSCAN, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) - fprintf(stderr, "iplioctl(SCAN,%#x,%p) = %d\n", cmd, data, i); + fprintf(stderr, "ipfioctl(SCAN,%#x,%p) = %d\n", cmd, data, i); if (i != 0) { errno = i; return -1; @@ -586,15 +628,17 @@ void *data; int ipooltestioctl(dev, cmd, data) -dev_t dev; -ioctlcmd_t cmd; -void *data; + dev_t dev; + ioctlcmd_t cmd; + void *data; { int i; - i = iplioctl(IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD); + dev = dev; /* gcc -Wextra */ + i = ipfioctl(softc, IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD); if (opts & OPT_DEBUG) - fprintf(stderr, "iplioctl(POOL,%#x,%p) = %d\n", cmd, data, i); + fprintf(stderr, "ipfioctl(POOL,%#x,%p) = %d (%d)\n", + cmd, data, i, softc->ipf_interror); if (i != 0) { errno = i; return -1; @@ -605,9 +649,9 @@ void *data; int kmemcpy(addr, offset, size) -char *addr; -long offset; -int size; + char *addr; + long offset; + int size; { bcopy((char *)offset, addr, size); return 0; @@ -615,9 +659,9 @@ int size; int kstrncpy(buf, pos, n) -char *buf; -long pos; -int n; + char *buf; + long pos; + int n; { char *ptr; @@ -632,100 +676,91 @@ int n; /* * Display the built up NAT table rules and mapping entries. */ -void dumpnat() +void dumpnat(arg) + void *arg; { + ipf_nat_softc_t *softn = arg; hostmap_t *hm; ipnat_t *ipn; nat_t *nat; printf("List of active MAP/Redirect filters:\n"); - for (ipn = nat_list; ipn != NULL; ipn = ipn->in_next) + for (ipn = softn->ipf_nat_list; ipn != NULL; ipn = ipn->in_next) printnat(ipn, opts & (OPT_DEBUG|OPT_VERBOSE)); printf("\nList of active sessions:\n"); - for (nat = nat_instances; nat; nat = nat->nat_next) { - printactivenat(nat, opts, 0, 0); + for (nat = softn->ipf_nat_instances; nat; nat = nat->nat_next) { + printactivenat(nat, opts, 0); if (nat->nat_aps) - printaps(nat->nat_aps, opts); + printf("\tproxy active\n"); } printf("\nHostmap table:\n"); - for (hm = ipf_hm_maplist; hm != NULL; hm = hm->hm_next) - printhostmap(hm, 0); + for (hm = softn->ipf_hm_maplist; hm != NULL; hm = hm->hm_next) + printhostmap(hm, hm->hm_hv); } -/* - * Display the built up state table rules and mapping entries. - */ -void dumpstate() -{ - ipstate_t *ips; - - printf("List of active state sessions:\n"); - for (ips = ips_list; ips != NULL; ) - ips = printstate(ips, opts & (OPT_DEBUG|OPT_VERBOSE), - fr_ticks); -} - - -void dumplookups() -{ - iphtable_t *iph; - ip_pool_t *ipl; - int i; - - printf("List of configured pools\n"); - for (i = 0; i < IPL_LOGSIZE; i++) - for (ipl = ip_pool_list[i]; ipl != NULL; ipl = ipl->ipo_next) - printpool(ipl, bcopywrap, NULL, opts); - - printf("List of configured hash tables\n"); - for (i = 0; i < IPL_LOGSIZE; i++) - for (iph = ipf_htables[i]; iph != NULL; iph = iph->iph_next) - printhash(iph, bcopywrap, NULL, opts); -} - - -void dumpgroups() +void dumpgroups(softc) + ipf_main_softc_t *softc; { frgroup_t *fg; - frentry_t *fr; int i; printf("List of groups configured (set 0)\n"); for (i = 0; i < IPL_LOGSIZE; i++) - for (fg = ipfgroups[i][0]; fg != NULL; fg = fg->fg_next) { + for (fg = softc->ipf_groups[i][0]; fg != NULL; + fg = fg->fg_next) { printf("Dev.%d. Group %s Ref %d Flags %#x\n", i, fg->fg_name, fg->fg_ref, fg->fg_flags); - for (fr = fg->fg_start; fr != NULL; fr = fr->fr_next) { -#ifdef USE_QUAD_T - printf("%qu ",(unsigned long long)fr->fr_hits); -#else - printf("%ld ", fr->fr_hits); -#endif - printfr(fr, ipftestioctl); - } + dumprules(fg->fg_start); } printf("List of groups configured (set 1)\n"); for (i = 0; i < IPL_LOGSIZE; i++) - for (fg = ipfgroups[i][1]; fg != NULL; fg = fg->fg_next) { + for (fg = softc->ipf_groups[i][1]; fg != NULL; + fg = fg->fg_next) { printf("Dev.%d. Group %s Ref %d Flags %#x\n", i, fg->fg_name, fg->fg_ref, fg->fg_flags); - for (fr = fg->fg_start; fr != NULL; fr = fr->fr_next) { + dumprules(fg->fg_start); + } + + printf("Rules configured (set 0, in)\n"); + dumprules(softc->ipf_rules[0][0]); + printf("Rules configured (set 0, out)\n"); + dumprules(softc->ipf_rules[1][0]); + printf("Rules configured (set 1, in)\n"); + dumprules(softc->ipf_rules[0][1]); + printf("Rules configured (set 1, out)\n"); + dumprules(softc->ipf_rules[1][1]); + + printf("Accounting rules configured (set 0, in)\n"); + dumprules(softc->ipf_acct[0][0]); + printf("Accounting rules configured (set 0, out)\n"); + dumprules(softc->ipf_acct[0][1]); + printf("Accounting rules configured (set 1, in)\n"); + dumprules(softc->ipf_acct[1][0]); + printf("Accounting rules configured (set 1, out)\n"); + dumprules(softc->ipf_acct[1][1]); +} + +void dumprules(rulehead) + frentry_t *rulehead; +{ + frentry_t *fr; + + for (fr = rulehead; fr != NULL; fr = fr->fr_next) { #ifdef USE_QUAD_T - printf("%qu ",(unsigned long long)fr->fr_hits); + printf("%"PRIu64" ",(unsigned long long)fr->fr_hits); #else - printf("%ld ", fr->fr_hits); + printf("%ld ", fr->fr_hits); #endif - printfr(fr, ipftestioctl); - } - } + printfr(fr, ipftestioctl); + } } void drain_log(filename) -char *filename; + char *filename; { char buffer[DEFAULT_IPFLOGSIZE]; struct iovec iov; @@ -751,7 +786,7 @@ char *filename; uio.uio_resid = iov.iov_len; resid = uio.uio_resid; - if (ipflog_read(i, &uio) == 0) { + if (ipf_log_read(softc, i, &uio) == 0) { /* * If nothing was read then break out. */ @@ -767,18 +802,38 @@ char *filename; void fixv4sums(m, ip) -mb_t *m; -ip_t *ip; + mb_t *m; + ip_t *ip; { - u_char *csump, *hdr; + u_char *csump, *hdr, p; + fr_info_t tmp; + int len; - ip->ip_sum = 0; - ip->ip_sum = ipf_cksum((u_short *)ip, IP_HL(ip) << 2); + p = 0; + len = 0; + bzero((char *)&tmp, sizeof(tmp)); csump = (u_char *)ip; - csump += IP_HL(ip) << 2; + if (IP_V(ip) == 4) { + ip->ip_sum = 0; + ip->ip_sum = ipf_cksum((u_short *)ip, IP_HL(ip) << 2); + tmp.fin_hlen = IP_HL(ip) << 2; + csump += IP_HL(ip) << 2; + p = ip->ip_p; + len = ntohs(ip->ip_len); +#ifdef USE_INET6 + } else if (IP_V(ip) == 6) { + tmp.fin_hlen = sizeof(ip6_t); + csump += sizeof(ip6_t); + p = ((ip6_t *)ip)->ip6_nxt; + len = ntohs(((ip6_t *)ip)->ip6_plen); + len += sizeof(ip6_t); +#endif + } + tmp.fin_plen = len; + tmp.fin_dlen = len - tmp.fin_hlen; - switch (ip->ip_p) + switch (p) { case IPPROTO_TCP : hdr = csump; @@ -798,7 +853,12 @@ ip_t *ip; break; } if (hdr != NULL) { + tmp.fin_m = m; + tmp.fin_mp = &m; + tmp.fin_dp = hdr; + tmp.fin_ip = ip; + tmp.fin_plen = len; *csump = 0; - *(u_short *)csump = fr_cksum(m, ip, ip->ip_p, hdr, ip->ip_len); + *(u_short *)csump = fr_cksum(&tmp, ip, p, hdr); } } diff --git a/tools/ipmon.c b/tools/ipmon.c index f07396dbbcb0a..72dba03a0723e 100644 --- a/tools/ipmon.c +++ b/tools/ipmon.c @@ -1,82 +1,20 @@ /* - * Copyright (C) 2001-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ -#ifndef SOLARIS -#define SOLARIS (defined(__SVR4) || defined(__svr4__)) && defined(sun) -#endif - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/param.h> -#include <sys/file.h> -#include <sys/time.h> -#define _KERNEL -#include <sys/uio.h> -#undef _KERNEL -#include <sys/socket.h> +#include "ipf.h" +#include "ipmon.h" #include <sys/ioctl.h> - -#include <stdio.h> -#include <unistd.h> -#include <string.h> +#include <sys/stat.h> +#include <syslog.h> +#include <ctype.h> #include <fcntl.h> -#include <errno.h> -#include <time.h> -#if !defined(__SVR4) && !defined(__svr4__) -# if (__FreeBSD_version >= 300000) -# include <sys/dirent.h> -# else -# include <sys/dir.h> -# endif -#else -# include <sys/filio.h> -# include <sys/byteorder.h> -#endif -#if !defined(__hpux) && (!defined(__SVR4) && !defined(__GNUC__)) -# include <strings.h> -#endif #include <signal.h> -#include <stdlib.h> -#include <stddef.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <net/if.h> -#include <netinet/ip.h> -#if !defined(__hpux) && !defined(linux) -# include <netinet/tcp_fsm.h> -#endif -#include <netdb.h> -#include <arpa/inet.h> -#include <arpa/nameser.h> -#ifdef __hpux -# undef NOERROR -#endif -#include <resolv.h> - -#if !defined(linux) -# include <sys/protosw.h> -# include <netinet/ip_var.h> -#endif - -#include <netinet/tcp.h> -#include <netinet/ip_icmp.h> - -#include <ctype.h> -#include <syslog.h> - -#include "netinet/ip_compat.h" -#include <netinet/tcpip.h> -#include "netinet/ip_fil.h" -#include "netinet/ip_nat.h" -#include "netinet/ip_state.h" -#include "netinet/ip_proxy.h" -#include "ipmon.h" #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 1.33.2.20 2007/09/20 12:51:56 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif @@ -87,12 +25,41 @@ extern char *sys_errlist[]; #define STRERROR(x) strerror(x) #endif +extern int optind; +extern char *optarg; + +extern ipmon_saver_t executesaver; +extern ipmon_saver_t filesaver; +extern ipmon_saver_t nothingsaver; +extern ipmon_saver_t snmpv1saver; +extern ipmon_saver_t snmpv2saver; +extern ipmon_saver_t syslogsaver; + struct flags { int value; char flag; }; +typedef struct logsource { + int fd; + int logtype; + char *file; + int regular; + size_t size; +} logsource_t; + +typedef struct config { + int opts; + int maxfd; + logsource_t logsrc[3]; + fd_set fdmr; + FILE *blog; + char *bfile; + FILE *log; + char *file; + char *cfile; +} config_t; typedef struct icmp_subtype { int ist_val; @@ -122,6 +89,28 @@ struct flags tcpfl[] = { { 0, '\0' } }; +char *reasons[] = { + "filter-rule", + "log-or-block_1", + "pps-rate", + "jumbogram", + "makefrip-fail", + "state_add-fail", + "updateipid-fail", + "log-or-block_2", + "decap-fail", + "auth_new-fail", + "auth_captured", + "coalesce-fail", + "pullup-fail", + "auth-feedback", + "bad-frag", + "natv4_out-fail", + "natv4_in-fail", + "natv6_out-fail", + "natv6_in-fail", +}; + #ifdef MENTAT static char *pidfile = "/etc/opt/ipf/ipmon.pid"; #else @@ -133,18 +122,14 @@ static char *pidfile = "/etc/ipmon.pid"; #endif static char line[2048]; -static int opts = 0; -static char *logfile = NULL; -static FILE *binarylog = NULL; -static char *binarylogfile = NULL; static int donehup = 0; static void usage __P((char *)); static void handlehup __P((int)); static void flushlogs __P((char *, FILE *)); -static void print_log __P((int, FILE *, char *, int)); -static void print_ipflog __P((FILE *, char *, int)); -static void print_natlog __P((FILE *, char *, int)); -static void print_statelog __P((FILE *, char *, int)); +static void print_log __P((config_t *, logsource_t *, char *, int)); +static void print_ipflog __P((config_t *, char *, int)); +static void print_natlog __P((config_t *, char *, int)); +static void print_statelog __P((config_t *, char *, int)); static int read_log __P((int, int *, char *, int)); static void write_pid __P((char *)); static char *icmpname __P((u_int, u_int)); @@ -157,39 +142,30 @@ static struct tm *get_tm __P((u_32_t)); static struct tm *get_tm __P((time_t)); #endif -char *hostname __P((int, int, u_32_t *)); -char *portname __P((int, char *, u_int)); +char *portlocalname __P((int, char *, u_int)); int main __P((int, char *[])); static void logopts __P((int, char *)); static void init_tabs __P((void)); -static char *getproto __P((u_int)); +static char *getlocalproto __P((u_int)); +static void openlogs __P((config_t *conf)); +static int read_loginfo __P((config_t *conf)); +static void initconfig __P((config_t *conf)); static char **protocols = NULL; static char **udp_ports = NULL; static char **tcp_ports = NULL; -static char *conf_file = NULL; - -#define OPT_SYSLOG 0x001 -#define OPT_RESOLVE 0x002 -#define OPT_HEXBODY 0x004 -#define OPT_VERBOSE 0x008 -#define OPT_HEXHDR 0x010 -#define OPT_TAIL 0x020 -#define OPT_NAT 0x080 -#define OPT_STATE 0x100 -#define OPT_FILTER 0x200 -#define OPT_PORTNUM 0x400 -#define OPT_LOGALL (OPT_NAT|OPT_STATE|OPT_FILTER) -#define OPT_LOGBODY 0x800 -#define HOSTNAME_V4(a,b) hostname((a), 4, (u_32_t *)&(b)) +#define HOSTNAMEV4(b) hostname(AF_INET, (u_32_t *)&(b)) #ifndef LOGFAC #define LOGFAC LOG_LOCAL0 #endif int logfac = LOGFAC; +int ipmonopts = 0; +int opts = OPT_NORESOLVE; +int use_inet6 = 0; static icmp_subtype_t icmpunreachnames[] = { @@ -231,7 +207,7 @@ static icmp_subtype_t paramnames[] = { { -2, NULL } }; -static icmp_type_t icmptypes[] = { +static icmp_type_t icmptypes4[] = { { ICMP_ECHOREPLY, NULL, 0, "echoreply" }, { -1, NULL, 0, NULL }, { -1, NULL, 0, NULL }, @@ -336,9 +312,9 @@ static icmp_type_t icmptypes6[] = { }; static icmp_subtype_t *find_icmpsubtype(type, table, tablesz) -int type; -icmp_subtype_t *table; -size_t tablesz; + int type; + icmp_subtype_t *table; + size_t tablesz; { icmp_subtype_t *ist; int i; @@ -361,9 +337,9 @@ size_t tablesz; static icmp_type_t *find_icmptype(type, table, tablesz) -int type; -icmp_type_t *table; -size_t tablesz; + int type; + icmp_type_t *table; + size_t tablesz; { icmp_type_t *it; int i; @@ -386,7 +362,7 @@ size_t tablesz; static void handlehup(sig) -int sig; + int sig; { signal(SIGHUP, handlehup); donehup = 1; @@ -419,12 +395,12 @@ static void init_tabs() p->p_name != NULL && protocols[p->p_proto] == NULL) protocols[p->p_proto] = strdup(p->p_name); endprotoent(); -#if defined(_AIX51) if (protocols[0]) free(protocols[0]); + protocols[0] = strdup("ip"); +#if defined(_AIX51) if (protocols[252]) free(protocols[252]); - protocols[0] = "ip"; protocols[252] = NULL; #endif } @@ -478,8 +454,8 @@ static void init_tabs() } -static char *getproto(p) -u_int p; +static char *getlocalproto(p) + u_int p; { static char pnum[4]; char *s; @@ -495,11 +471,14 @@ u_int p; static int read_log(fd, lenp, buf, bufsize) -int fd, bufsize, *lenp; -char *buf; + int fd, bufsize, *lenp; + char *buf; { int nr; + if (bufsize > IPFILTER_LOGSIZE) + bufsize = IPFILTER_LOGSIZE; + nr = read(fd, buf, bufsize); if (!nr) return 2; @@ -510,51 +489,18 @@ char *buf; } -char *hostname(res, v, ip) -int res, v; -u_32_t *ip; +char *portlocalname(res, proto, port) + int res; + char *proto; + u_int port; { -# define MAX_INETA 16 - static char hname[MAXHOSTNAMELEN + MAX_INETA + 3]; -#ifdef USE_INET6 - static char hostbuf[MAXHOSTNAMELEN+1]; -#endif - struct hostent *hp; - struct in_addr ipa; - - if (v == 4) { - ipa.s_addr = *ip; - if (!res) - return inet_ntoa(ipa); - hp = gethostbyaddr((char *)ip, sizeof(*ip), AF_INET); - if (!hp) - return inet_ntoa(ipa); - sprintf(hname, "%.*s[%s]", MAXHOSTNAMELEN, hp->h_name, - inet_ntoa(ipa)); - return hname; - } -#ifdef USE_INET6 - (void) inet_ntop(AF_INET6, ip, hostbuf, sizeof(hostbuf) - 1); - hostbuf[MAXHOSTNAMELEN] = '\0'; - return hostbuf; -#else - return "IPv6"; -#endif -} - - -char *portname(res, proto, port) -int res; -char *proto; -u_int port; -{ - static char pname[8]; - char *s; + static char pname[8]; + char *s; port = ntohs(port); port &= 0xffff; - (void) sprintf(pname, "%u", port); - if (!res || (opts & OPT_PORTNUM)) + sprintf(pname, "%u", port); + if (!res || (ipmonopts & IPMON_PORTNUM)) return pname; s = NULL; if (!strcmp(proto, "tcp")) @@ -567,9 +513,9 @@ u_int port; } -static char *icmpname(type, code) -u_int type; -u_int code; +static char *icmpname(type, code) + u_int type; + u_int code; { static char name[80]; icmp_subtype_t *ist; @@ -577,7 +523,7 @@ u_int code; char *s; s = NULL; - it = find_icmptype(type, icmptypes, sizeof(icmptypes) / sizeof(*it)); + it = find_icmptype(type, icmptypes4, sizeof(icmptypes4) / sizeof(*it)); if (it != NULL) s = it->it_name; @@ -598,9 +544,9 @@ u_int code; return name; } -static char *icmpname6(type, code) -u_int type; -u_int code; +static char *icmpname6(type, code) + u_int type; + u_int code; { static char name[80]; icmp_subtype_t *ist; @@ -630,11 +576,11 @@ u_int code; } -void dumphex(log, dopts, buf, len) -FILE *log; -int dopts; -char *buf; -int len; +void dumphex(log, dopts, buf, len) + FILE *log; + int dopts; + char *buf; + int len; { char hline[80]; int i, j, k; @@ -649,7 +595,7 @@ int len; if (j && !(j & 0xf)) { *t++ = '\n'; *t = '\0'; - if ((dopts & OPT_SYSLOG)) + if ((dopts & IPMON_SYSLOG)) syslog(LOG_INFO, "%s", hline); else if (log != NULL) fputs(hline, log); @@ -663,10 +609,10 @@ int len; sprintf((char *)t, " "); t += 8; for (k = 16; k; k--, s++) - *t++ = (ISPRINT(*s) ? *s : '.'); + *t++ = (isprint(*s) ? *s : '.'); s--; } - + if ((j + 1) & 0xf) *t++ = ' ';; } @@ -681,11 +627,11 @@ int len; t += 7; s -= j & 0xf; for (k = j & 0xf; k; k--, s++) - *t++ = (ISPRINT(*s) ? *s : '.'); + *t++ = (isprint(*s) ? *s : '.'); *t++ = '\n'; *t = '\0'; } - if ((dopts & OPT_SYSLOG) != 0) + if ((dopts & IPMON_SYSLOG) != 0) syslog(LOG_INFO, "%s", hline); else if (log != NULL) { fputs(hline, log); @@ -694,11 +640,11 @@ int len; } -static struct tm *get_tm(sec) +static struct tm *get_tm(sec) #ifdef __hpux -u_32_t sec; + u_32_t sec; #else -time_t sec; + time_t sec; #endif { struct tm *tm; @@ -709,23 +655,44 @@ time_t sec; return tm; } -static void print_natlog(log, buf, blen) -FILE *log; -char *buf; -int blen; +static void print_natlog(conf, buf, blen) + config_t *conf; + char *buf; + int blen; { - struct natlog *nl; - iplog_t *ipl = (iplog_t *)buf; - char *t = line; - struct tm *tm; - int res, i, len; - char *proto; + static u_32_t seqnum = 0; + int res, i, len, family; + struct natlog *nl; + struct tm *tm; + iplog_t *ipl; + char *proto; + int simple; + char *t; + + t = line; + simple = 0; + ipl = (iplog_t *)buf; + if (ipl->ipl_seqnum != seqnum) { + if ((ipmonopts & IPMON_SYSLOG) != 0) { + syslog(LOG_WARNING, + "missed %u NAT log entries: %u %u", + ipl->ipl_seqnum - seqnum, seqnum, + ipl->ipl_seqnum); + } else { + (void) fprintf(conf->log, + "missed %u NAT log entries: %u %u\n", + ipl->ipl_seqnum - seqnum, seqnum, + ipl->ipl_seqnum); + } + } + seqnum = ipl->ipl_seqnum + ipl->ipl_count; nl = (struct natlog *)((char *)ipl + sizeof(*ipl)); - res = (opts & OPT_RESOLVE) ? 1 : 0; + res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0; tm = get_tm(ipl->ipl_sec); len = sizeof(line); - if (!(opts & OPT_SYSLOG)) { + + if (!(ipmonopts & IPMON_SYSLOG)) { (void) strftime(t, len, "%d/%m/%Y ", tm); i = strlen(t); len -= i; @@ -733,81 +700,184 @@ int blen; } (void) strftime(t, len, "%T", tm); t += strlen(t); - (void) sprintf(t, ".%-.6ld @%hd ", ipl->ipl_usec, nl->nl_rule + 1); + sprintf(t, ".%-.6ld @%hd ", (long)ipl->ipl_usec, nl->nl_rule + 1); t += strlen(t); - if (nl->nl_type == NL_NEWMAP) - strcpy(t, "NAT:MAP "); - else if (nl->nl_type == NL_NEWRDR) - strcpy(t, "NAT:RDR "); - else if (nl->nl_type == NL_FLUSH) - strcpy(t, "NAT:FLUSH "); - else if (nl->nl_type == NL_EXPIRE) - strcpy(t, "NAT:EXPIRE "); - else if (nl->nl_type == NL_NEWBIMAP) - strcpy(t, "NAT:BIMAP "); - else if (nl->nl_type == NL_NEWBLOCK) - strcpy(t, "NAT:MAPBLOCK "); - else if (nl->nl_type == NL_CLONE) - strcpy(t, "NAT:CLONE "); - else if (nl->nl_type == NL_DESTROY) - strcpy(t, "NAT:DESTROY "); - else - sprintf(t, "Type: %d ", nl->nl_type); + switch (nl->nl_action) + { + case NL_NEW : + strcpy(t, "NAT:NEW"); + break; + + case NL_FLUSH : + strcpy(t, "NAT:FLUSH"); + break; + + case NL_CLONE : + strcpy(t, "NAT:CLONE"); + break; + + case NL_EXPIRE : + strcpy(t, "NAT:EXPIRE"); + break; + + case NL_DESTROY : + strcpy(t, "NAT:DESTROY"); + break; + + case NL_PURGE : + strcpy(t, "NAT:PURGE"); + break; + + default : + sprintf(t, "NAT:Action(%d)", nl->nl_action); + break; + } t += strlen(t); - proto = getproto(nl->nl_p); - (void) sprintf(t, "%s,%s <- -> ", HOSTNAME_V4(res, nl->nl_inip), - portname(res, proto, (u_int)nl->nl_inport)); + switch (nl->nl_type) + { + case NAT_MAP : + strcpy(t, "-MAP "); + simple = 1; + break; + + case NAT_REDIRECT : + strcpy(t, "-RDR "); + simple = 1; + break; + + case NAT_BIMAP : + strcpy(t, "-BIMAP "); + simple = 1; + break; + + case NAT_MAPBLK : + strcpy(t, "-MAPBLOCK "); + simple = 1; + break; + + case NAT_REWRITE|NAT_MAP : + strcpy(t, "-RWR_MAP "); + break; + + case NAT_REWRITE|NAT_REDIRECT : + strcpy(t, "-RWR_RDR "); + break; + + case NAT_ENCAP|NAT_MAP : + strcpy(t, "-ENC_MAP "); + break; + + case NAT_ENCAP|NAT_REDIRECT : + strcpy(t, "-ENC_RDR "); + break; + + case NAT_DIVERTUDP|NAT_MAP : + strcpy(t, "-DIV_MAP "); + break; + + case NAT_DIVERTUDP|NAT_REDIRECT : + strcpy(t, "-DIV_RDR "); + break; + + default : + sprintf(t, "-Type(%d) ", nl->nl_type); + break; + } t += strlen(t); - (void) sprintf(t, "%s,%s ", HOSTNAME_V4(res, nl->nl_outip), - portname(res, proto, (u_int)nl->nl_outport)); + + proto = getlocalproto(nl->nl_p[0]); + + family = vtof(nl->nl_v[0]); + + if (simple == 1) { + sprintf(t, "%s,%s <- -> ", hostname(family, nl->nl_osrcip.i6), + portlocalname(res, proto, (u_int)nl->nl_osrcport)); + t += strlen(t); + sprintf(t, "%s,%s ", hostname(family, nl->nl_nsrcip.i6), + portlocalname(res, proto, (u_int)nl->nl_nsrcport)); + t += strlen(t); + sprintf(t, "[%s,%s] ", hostname(family, nl->nl_odstip.i6), + portlocalname(res, proto, (u_int)nl->nl_odstport)); + } else { + sprintf(t, "%s,%s ", hostname(family, nl->nl_osrcip.i6), + portlocalname(res, proto, (u_int)nl->nl_osrcport)); + t += strlen(t); + sprintf(t, "%s,%s <- -> ", hostname(family, nl->nl_odstip.i6), + portlocalname(res, proto, (u_int)nl->nl_odstport)); + t += strlen(t); + sprintf(t, "%s,%s ", hostname(family, nl->nl_nsrcip.i6), + portlocalname(res, proto, (u_int)nl->nl_nsrcport)); + t += strlen(t); + sprintf(t, "%s,%s ", hostname(family, nl->nl_ndstip.i6), + portlocalname(res, proto, (u_int)nl->nl_ndstport)); + } t += strlen(t); - (void) sprintf(t, "[%s,%s PR %s]", HOSTNAME_V4(res, nl->nl_origip), - portname(res, proto, (u_int)nl->nl_origport), - getproto(nl->nl_p)); + + strcpy(t, getlocalproto(nl->nl_p[0])); t += strlen(t); - if (nl->nl_type == NL_EXPIRE) { + + if (nl->nl_action == NL_EXPIRE || nl->nl_action == NL_FLUSH) { #ifdef USE_QUAD_T - (void) sprintf(t, " Pkts %qd/%qd Bytes %qd/%qd", - (long long)nl->nl_pkts[0], - (long long)nl->nl_pkts[1], - (long long)nl->nl_bytes[0], - (long long)nl->nl_bytes[1]); +# ifdef PRId64 + sprintf(t, " Pkts %" PRId64 "/%" PRId64 " Bytes %" PRId64 "/%" + PRId64, +# else + sprintf(t, " Pkts %qd/%qd Bytes %qd/%qd", +# endif #else - (void) sprintf(t, " Pkts %ld/%ld Bytes %ld/%ld", + sprintf(t, " Pkts %ld/%ld Bytes %ld/%ld", +#endif nl->nl_pkts[0], nl->nl_pkts[1], nl->nl_bytes[0], nl->nl_bytes[1]); -#endif t += strlen(t); } *t++ = '\n'; *t++ = '\0'; - if (opts & OPT_SYSLOG) + if (ipmonopts & IPMON_SYSLOG) syslog(LOG_INFO, "%s", line); - else if (log != NULL) - (void) fprintf(log, "%s", line); + else if (conf->log != NULL) + (void) fprintf(conf->log, "%s", line); } -static void print_statelog(log, buf, blen) -FILE *log; -char *buf; -int blen; +static void print_statelog(conf, buf, blen) + config_t *conf; + char *buf; + int blen; { - struct ipslog *sl; - iplog_t *ipl = (iplog_t *)buf; - char *t = line, *proto; - struct tm *tm; - int res, i, len; + static u_32_t seqnum = 0; + int res, i, len, family; + struct ipslog *sl; + char *t, *proto; + struct tm *tm; + iplog_t *ipl; + + t = line; + ipl = (iplog_t *)buf; + if (ipl->ipl_seqnum != seqnum) { + if ((ipmonopts & IPMON_SYSLOG) != 0) { + syslog(LOG_WARNING, + "missed %u state log entries: %u %u", + ipl->ipl_seqnum - seqnum, seqnum, + ipl->ipl_seqnum); + } else { + (void) fprintf(conf->log, + "missed %u state log entries: %u %u\n", + ipl->ipl_seqnum - seqnum, seqnum, + ipl->ipl_seqnum); + } + } + seqnum = ipl->ipl_seqnum + ipl->ipl_count; sl = (struct ipslog *)((char *)ipl + sizeof(*ipl)); - res = (opts & OPT_RESOLVE) ? 1 : 0; + res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0; tm = get_tm(ipl->ipl_sec); len = sizeof(line); - if (!(opts & OPT_SYSLOG)) { + if (!(ipmonopts & IPMON_SYSLOG)) { (void) strftime(t, len, "%d/%m/%Y ", tm); i = strlen(t); len -= i; @@ -815,9 +885,11 @@ int blen; } (void) strftime(t, len, "%T", tm); t += strlen(t); - (void) sprintf(t, ".%-.6ld ", ipl->ipl_usec); + sprintf(t, ".%-.6ld ", (long)ipl->ipl_usec); t += strlen(t); + family = vtof(sl->isl_v); + switch (sl->isl_type) { case ISL_NEW : @@ -863,41 +935,37 @@ int blen; } t += strlen(t); - proto = getproto(sl->isl_p); + proto = getlocalproto(sl->isl_p); if (sl->isl_p == IPPROTO_TCP || sl->isl_p == IPPROTO_UDP) { - (void) sprintf(t, "%s,%s -> ", - hostname(res, sl->isl_v, (u_32_t *)&sl->isl_src), - portname(res, proto, (u_int)sl->isl_sport)); + sprintf(t, "%s,%s -> ", + hostname(family, (u_32_t *)&sl->isl_src), + portlocalname(res, proto, (u_int)sl->isl_sport)); t += strlen(t); - (void) sprintf(t, "%s,%s PR %s", - hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), - portname(res, proto, (u_int)sl->isl_dport), proto); + sprintf(t, "%s,%s PR %s", + hostname(family, (u_32_t *)&sl->isl_dst), + portlocalname(res, proto, (u_int)sl->isl_dport), proto); } else if (sl->isl_p == IPPROTO_ICMP) { - (void) sprintf(t, "%s -> ", hostname(res, sl->isl_v, - (u_32_t *)&sl->isl_src)); + sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src)); t += strlen(t); - (void) sprintf(t, "%s PR icmp %d", - hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), + sprintf(t, "%s PR icmp %d", + hostname(family, (u_32_t *)&sl->isl_dst), sl->isl_itype); } else if (sl->isl_p == IPPROTO_ICMPV6) { - (void) sprintf(t, "%s -> ", hostname(res, sl->isl_v, - (u_32_t *)&sl->isl_src)); + sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src)); t += strlen(t); - (void) sprintf(t, "%s PR icmpv6 %d", - hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), + sprintf(t, "%s PR icmpv6 %d", + hostname(family, (u_32_t *)&sl->isl_dst), sl->isl_itype); } else { - (void) sprintf(t, "%s -> ", - hostname(res, sl->isl_v, (u_32_t *)&sl->isl_src)); + sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src)); t += strlen(t); - (void) sprintf(t, "%s PR %s", - hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), - proto); + sprintf(t, "%s PR %s", + hostname(family, (u_32_t *)&sl->isl_dst), proto); } t += strlen(t); if (sl->isl_tag != FR_NOLOGTAG) { - (void) sprintf(t, " tag %u", sl->isl_tag); + sprintf(t, " tag %u", sl->isl_tag); t += strlen(t); } if (sl->isl_type != ISL_NEW) { @@ -924,22 +992,26 @@ int blen; *t++ = '\n'; *t++ = '\0'; - if (opts & OPT_SYSLOG) + if (ipmonopts & IPMON_SYSLOG) syslog(LOG_INFO, "%s", line); - else if (log != NULL) - (void) fprintf(log, "%s", line); + else if (conf->log != NULL) + (void) fprintf(conf->log, "%s", line); } -static void print_log(logtype, log, buf, blen) -FILE *log; -char *buf; -int logtype, blen; +static void print_log(conf, log, buf, blen) + config_t *conf; + logsource_t *log; + char *buf; + int blen; { + char *bp, *bpo; iplog_t *ipl; - char *bp = NULL, *bpo = NULL; int psize; + bp = NULL; + bpo = NULL; + while (blen > 0) { ipl = (iplog_t *)buf; if ((u_long)ipl & (sizeof(long)-1)) { @@ -959,22 +1031,22 @@ int logtype, blen; if (psize > blen) break; - if (binarylog) { - fwrite(buf, psize, 1, binarylog); - fflush(binarylog); + if (conf->blog != NULL) { + fwrite(buf, psize, 1, conf->blog); + fflush(conf->blog); } - if (logtype == IPL_LOGIPF) { + if (log->logtype == IPL_LOGIPF) { if (ipl->ipl_magic == IPL_MAGIC) - print_ipflog(log, buf, psize); + print_ipflog(conf, buf, psize); - } else if (logtype == IPL_LOGNAT) { + } else if (log->logtype == IPL_LOGNAT) { if (ipl->ipl_magic == IPL_MAGIC_NAT) - print_natlog(log, buf, psize); + print_natlog(conf, buf, psize); - } else if (logtype == IPL_LOGSTATE) { + } else if (log->logtype == IPL_LOGSTATE) { if (ipl->ipl_magic == IPL_MAGIC_STATE) - print_statelog(log, buf, psize); + print_statelog(conf, buf, psize); } blen -= psize; @@ -986,22 +1058,23 @@ int logtype, blen; } -static void print_ipflog(log, buf, blen) -FILE *log; -char *buf; -int blen; +static void print_ipflog(conf, buf, blen) + config_t *conf; + char *buf; + int blen; { - tcphdr_t *tp; - struct icmp *ic; - struct icmp *icmp; - struct tm *tm; - char *t, *proto; - int i, v, lvl, res, len, off, plen, ipoff, defaction; - ip_t *ipc, *ip; - u_32_t *s, *d; - u_short hl, p; + static u_32_t seqnum = 0; + int i, f, lvl, res, len, off, plen, ipoff, defaction; + struct icmp *icmp; + struct icmp *ic; + char *t, *proto; + ip_t *ipc, *ip; + struct tm *tm; + u_32_t *s, *d; + u_short hl, p; ipflog_t *ipf; - iplog_t *ipl; + iplog_t *ipl; + tcphdr_t *tp; #ifdef USE_INET6 struct ip6_ext *ehp; u_short ehl; @@ -1010,16 +1083,31 @@ int blen; #endif ipl = (iplog_t *)buf; + if (ipl->ipl_seqnum != seqnum) { + if ((ipmonopts & IPMON_SYSLOG) != 0) { + syslog(LOG_WARNING, + "missed %u ipf log entries: %u %u", + ipl->ipl_seqnum - seqnum, seqnum, + ipl->ipl_seqnum); + } else { + (void) fprintf(conf->log, + "missed %u ipf log entries: %u %u\n", + ipl->ipl_seqnum - seqnum, seqnum, + ipl->ipl_seqnum); + } + } + seqnum = ipl->ipl_seqnum + ipl->ipl_count; + ipf = (ipflog_t *)((char *)buf + sizeof(*ipl)); ip = (ip_t *)((char *)ipf + sizeof(*ipf)); - v = IP_V(ip); - res = (opts & OPT_RESOLVE) ? 1 : 0; + f = ipf->fl_family; + res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0; t = line; *t = '\0'; tm = get_tm(ipl->ipl_sec); len = sizeof(line); - if (!(opts & OPT_SYSLOG)) { + if (!(ipmonopts & IPMON_SYSLOG)) { (void) strftime(t, len, "%d/%m/%Y ", tm); i = strlen(t); len -= i; @@ -1027,10 +1115,10 @@ int blen; } (void) strftime(t, len, "%T", tm); t += strlen(t); - (void) sprintf(t, ".%-.6ld ", ipl->ipl_usec); + sprintf(t, ".%-.6ld ", (long)ipl->ipl_usec); t += strlen(t); if (ipl->ipl_count > 1) { - (void) sprintf(t, "%dx ", ipl->ipl_count); + sprintf(t, "%dx ", ipl->ipl_count); t += strlen(t); } #if (defined(MENTAT) || \ @@ -1042,13 +1130,19 @@ int blen; strncpy(ifname, ipf->fl_ifname, sizeof(ipf->fl_ifname)); ifname[sizeof(ipf->fl_ifname)] = '\0'; - (void) sprintf(t, "%s", ifname); + sprintf(t, "%s", ifname); t += strlen(t); # if defined(MENTAT) || defined(linux) - if (ISALPHA(*(t - 1))) { - sprintf(t, "%d", ipf->fl_unit); - t += strlen(t); - } +# if defined(linux) + /* + * On Linux, the loopback interface is just "lo", not "lo0". + */ + if (strcmp(ifname, "lo") != 0) +# endif + if (ISALPHA(*(t - 1))) { + sprintf(t, "%d", ipf->fl_unit); + t += strlen(t); + } # endif } #else @@ -1057,7 +1151,7 @@ int blen; break; if (ipf->fl_ifname[len]) len++; - (void) sprintf(t, "%*.*s%u", len, len, ipf->fl_ifname, ipf->fl_unit); + sprintf(t, "%*.*s%u", len, len, ipf->fl_ifname, ipf->fl_unit); t += strlen(t); #endif if ((ipf->fl_group[0] == (char)~0) && (ipf->fl_group[1] == '\0')) @@ -1065,12 +1159,12 @@ int blen; else if (ipf->fl_group[0] == '\0') (void) strcpy(t, " @0:"); else - (void) sprintf(t, " @%s:", ipf->fl_group); + sprintf(t, " @%s:", ipf->fl_group); t += strlen(t); if (ipf->fl_rule == 0xffffffff) strcat(t, "-1 "); else - (void) sprintf(t, "%u ", ipf->fl_rule + 1); + sprintf(t, "%u ", ipf->fl_rule + 1); t += strlen(t); lvl = LOG_NOTICE; @@ -1105,8 +1199,17 @@ int blen; *t++ = ' '; *t = '\0'; - if (v == 6) { + if (f == AF_INET) { + hl = IP_HL(ip) << 2; + ipoff = ntohs(ip->ip_off); + off = ipoff & IP_OFFMASK; + 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); + } else #ifdef USE_INET6 + if (f == AF_INET6) { off = 0; ipoff = 0; hl = sizeof(ip6_t); @@ -1138,32 +1241,22 @@ int blen; break; } } -#else - sprintf(t, "ipv6"); - goto printipflog; + } else #endif - } else if (v == 4) { - hl = IP_HL(ip) << 2; - ipoff = ip->ip_off; - off = ipoff & IP_OFFMASK; - p = (u_short)ip->ip_p; - s = (u_32_t *)&ip->ip_src; - d = (u_32_t *)&ip->ip_dst; - plen = ip->ip_len; - } else { + { goto printipflog; } - proto = getproto(p); + proto = getlocalproto(p); if ((p == IPPROTO_TCP || p == IPPROTO_UDP) && !off) { tp = (tcphdr_t *)((char *)ip + hl); if (!(ipf->fl_lflags & FI_SHORT)) { - (void) sprintf(t, "%s,%s -> ", hostname(res, v, s), - portname(res, proto, (u_int)tp->th_sport)); + sprintf(t, "%s,%s -> ", hostname(f, s), + portlocalname(res, proto, (u_int)tp->th_sport)); t += strlen(t); - (void) sprintf(t, "%s,%s PR %s len %hu %hu", - hostname(res, v, d), - portname(res, proto, (u_int)tp->th_dport), + sprintf(t, "%s,%s PR %s len %hu %hu", + hostname(f, d), + portlocalname(res, proto, (u_int)tp->th_dport), proto, hl, plen); t += strlen(t); @@ -1173,8 +1266,8 @@ int blen; for (i = 0; tcpfl[i].value; i++) if (tp->th_flags & tcpfl[i].value) *t++ = tcpfl[i].flag; - if (opts & OPT_VERBOSE) { - (void) sprintf(t, " %lu %lu %hu", + if (ipmonopts & IPMON_VERBOSE) { + sprintf(t, " %lu %lu %hu", (u_long)(ntohl(tp->th_seq)), (u_long)(ntohl(tp->th_ack)), ntohs(tp->th_win)); @@ -1183,24 +1276,26 @@ int blen; } *t = '\0'; } else { - (void) sprintf(t, "%s -> ", hostname(res, v, s)); + sprintf(t, "%s -> ", hostname(f, s)); t += strlen(t); - (void) sprintf(t, "%s PR %s len %hu %hu", - hostname(res, v, d), proto, hl, plen); + sprintf(t, "%s PR %s len %hu %hu", + hostname(f, d), proto, hl, plen); } - } else if ((p == IPPROTO_ICMPV6) && !off && (v == 6)) { +#if defined(AF_INET6) && defined(IPPROTO_ICMPV6) + } else if ((p == IPPROTO_ICMPV6) && !off && (f == AF_INET6)) { ic = (struct icmp *)((char *)ip + hl); - (void) sprintf(t, "%s -> ", hostname(res, v, s)); + sprintf(t, "%s -> ", hostname(f, s)); t += strlen(t); - (void) sprintf(t, "%s PR icmpv6 len %hu %hu icmpv6 %s", - hostname(res, v, d), hl, plen, + sprintf(t, "%s PR icmpv6 len %hu %hu icmpv6 %s", + hostname(f, d), hl, plen, icmpname6(ic->icmp_type, ic->icmp_code)); - } else if ((p == IPPROTO_ICMP) && !off && (v == 4)) { +#endif + } else if ((p == IPPROTO_ICMP) && !off && (f == AF_INET)) { ic = (struct icmp *)((char *)ip + hl); - (void) sprintf(t, "%s -> ", hostname(res, v, s)); + sprintf(t, "%s -> ", hostname(f, s)); t += strlen(t); - (void) sprintf(t, "%s PR icmp len %hu %hu icmp %s", - hostname(res, v, d), hl, plen, + sprintf(t, "%s PR icmp len %hu %hu icmp %s", + hostname(f, d), hl, plen, icmpname(ic->icmp_type, ic->icmp_code)); if (ic->icmp_type == ICMP_UNREACH || ic->icmp_type == ICMP_SOURCEQUENCH || @@ -1216,21 +1311,21 @@ int blen; if (i > 1500) i = ipc->ip_len; ipoff = ntohs(ipc->ip_off); - proto = getproto(ipc->ip_p); + proto = getlocalproto(ipc->ip_p); if (!(ipoff & IP_OFFMASK) && ((ipc->ip_p == IPPROTO_TCP) || (ipc->ip_p == IPPROTO_UDP))) { tp = (tcphdr_t *)((char *)ipc + hl); t += strlen(t); - (void) sprintf(t, " for %s,%s -", - HOSTNAME_V4(res, ipc->ip_src), - portname(res, proto, + sprintf(t, " for %s,%s -", + HOSTNAMEV4(ipc->ip_src), + portlocalname(res, proto, (u_int)tp->th_sport)); t += strlen(t); - (void) sprintf(t, " %s,%s PR %s len %hu %hu", - HOSTNAME_V4(res, ipc->ip_dst), - portname(res, proto, + sprintf(t, " %s,%s PR %s len %hu %hu", + HOSTNAMEV4(ipc->ip_dst), + portlocalname(res, proto, (u_int)tp->th_dport), proto, IP_HL(ipc) << 2, i); } else if (!(ipoff & IP_OFFMASK) && @@ -1238,26 +1333,25 @@ int blen; icmp = (icmphdr_t *)((char *)ipc + hl); t += strlen(t); - (void) sprintf(t, " for %s -", - HOSTNAME_V4(res, ipc->ip_src)); + sprintf(t, " for %s -", + HOSTNAMEV4(ipc->ip_src)); t += strlen(t); - (void) sprintf(t, + sprintf(t, " %s PR icmp len %hu %hu icmp %d/%d", - HOSTNAME_V4(res, ipc->ip_dst), + HOSTNAMEV4(ipc->ip_dst), IP_HL(ipc) << 2, i, icmp->icmp_type, icmp->icmp_code); } else { t += strlen(t); - (void) sprintf(t, " for %s -", - HOSTNAME_V4(res, ipc->ip_src)); + sprintf(t, " for %s -", + HOSTNAMEV4(ipc->ip_src)); t += strlen(t); - (void) sprintf(t, " %s PR %s len %hu (%hu)", - HOSTNAME_V4(res, ipc->ip_dst), proto, + sprintf(t, " %s PR %s len %hu (%hu)", + HOSTNAMEV4(ipc->ip_dst), proto, IP_HL(ipc) << 2, i); t += strlen(t); if (ipoff & IP_OFFMASK) { - (void) sprintf(t, - "(frag %d:%hu@%hu%s%s)", + sprintf(t, "(frag %d:%hu@%hu%s%s)", ntohs(ipc->ip_id), i - (IP_HL(ipc) << 2), (ipoff & IP_OFFMASK) << 3, @@ -1268,13 +1362,13 @@ int blen; } } else { - (void) sprintf(t, "%s -> ", hostname(res, v, s)); + sprintf(t, "%s -> ", hostname(f, s)); t += strlen(t); - (void) sprintf(t, "%s PR %s len %hu (%hu)", - hostname(res, v, d), proto, hl, plen); + sprintf(t, "%s PR %s len %hu (%hu)", + hostname(f, d), proto, hl, plen); t += strlen(t); if (off & IP_OFFMASK) - (void) sprintf(t, " (frag %d:%hu@%hu%s%s)", + sprintf(t, " (frag %d:%hu@%hu%s%s)", ntohs(ip->ip_id), plen - hl, (off & IP_OFFMASK) << 3, ipoff & IP_MF ? "+" : "", @@ -1345,32 +1439,43 @@ printipflog: strcpy(t, " mbcast"); t += 7; } + if (ipf->fl_breason != 0) { + strcpy(t, " reason:"); + t += 8; + strcpy(t, reasons[ipf->fl_breason]); + t += strlen(reasons[ipf->fl_breason]); + } *t++ = '\n'; *t++ = '\0'; defaction = 0; - if (conf_file != NULL) - defaction = check_action(buf, line, opts, lvl); + if (conf->cfile != NULL) + defaction = check_action(buf, line, ipmonopts, lvl); + if (defaction == 0) { - if (opts & OPT_SYSLOG) + if (ipmonopts & IPMON_SYSLOG) { syslog(lvl, "%s", line); - else if (log != NULL) - (void) fprintf(log, "%s", line); + } else if (conf->log != NULL) { + (void) fprintf(conf->log, "%s", line); + } - if (opts & OPT_HEXHDR) - dumphex(log, opts, buf, + if (ipmonopts & IPMON_HEXHDR) { + dumphex(conf->log, ipmonopts, buf, sizeof(iplog_t) + sizeof(*ipf)); - if (opts & OPT_HEXBODY) - dumphex(log, opts, (char *)ip, + } + if (ipmonopts & IPMON_HEXBODY) { + dumphex(conf->log, ipmonopts, (char *)ip, ipf->fl_plen + ipf->fl_hlen); - else if ((opts & OPT_LOGBODY) && (ipf->fl_flags & FR_LOGBODY)) - dumphex(log, opts, (char *)ip + ipf->fl_hlen, + } else if ((ipmonopts & IPMON_LOGBODY) && + (ipf->fl_flags & FR_LOGBODY)) { + dumphex(conf->log, ipmonopts, (char *)ip + ipf->fl_hlen, ipf->fl_plen); + } } } static void usage(prog) -char *prog; + char *prog; { fprintf(stderr, "%s: [-NFhstvxX] [-f <logfile>]\n", prog); exit(1); @@ -1378,7 +1483,7 @@ char *prog; static void write_pid(file) -char *file; + char *file; { FILE *fp = NULL; int fd; @@ -1398,8 +1503,8 @@ char *file; static void flushlogs(file, log) -char *file; -FILE *log; + char *file; + FILE *log; { int fd, flushed = 0; @@ -1414,11 +1519,11 @@ FILE *log; flushed); fflush(stdout); } else - perror("SIOCIPFFB"); + ipferror(fd, "SIOCIPFFB"); (void) close(fd); if (flushed) { - if (opts & OPT_SYSLOG) { + if (ipmonopts & IPMON_SYSLOG) { syslog(LOG_INFO, "%d bytes flushed from log\n", flushed); } else if ((log != stdout) && (log != NULL)) { @@ -1429,8 +1534,8 @@ FILE *log; static void logopts(turnon, options) -int turnon; -char *options; + int turnon; + char *options; { int flags = 0; char *s; @@ -1440,13 +1545,13 @@ char *options; switch (*s) { case 'N' : - flags |= OPT_NAT; + flags |= IPMON_NAT; break; case 'S' : - flags |= OPT_STATE; + flags |= IPMON_STATE; break; case 'I' : - flags |= OPT_FILTER; + flags |= IPMON_FILTER; break; default : fprintf(stderr, "Unknown log option %c\n", *s); @@ -1455,64 +1560,87 @@ char *options; } if (turnon) - opts |= flags; + ipmonopts |= flags; else - opts &= ~(flags); + ipmonopts &= ~(flags); +} + +static void initconfig(config_t *conf) +{ + int i; + + memset(conf, 0, sizeof(*conf)); + + conf->log = stdout; + conf->maxfd = -1; + + for (i = 0; i < 3; i++) { + conf->logsrc[i].fd = -1; + conf->logsrc[i].logtype = -1; + conf->logsrc[i].regular = -1; + } + + conf->logsrc[0].file = IPL_NAME; + conf->logsrc[1].file = IPNAT_NAME; + conf->logsrc[2].file = IPSTATE_NAME; + + add_doing(&executesaver); + add_doing(&snmpv1saver); + add_doing(&snmpv2saver); + add_doing(&syslogsaver); + add_doing(&filesaver); + add_doing(¬hingsaver); } int main(argc, argv) -int argc; -char *argv[]; + int argc; + char *argv[]; { - struct stat sb; - FILE *log = stdout; - FILE *fp; - int fd[3], doread, n, i; - int tr, nr, regular[3], c; - int fdt[3], devices = 0, make_daemon = 0; - char buf[DEFAULT_IPFLOGSIZE], *iplfile[3], *s; - extern int optind; - extern char *optarg; - - fd[0] = fd[1] = fd[2] = -1; - fdt[0] = fdt[1] = fdt[2] = -1; - iplfile[0] = IPL_NAME; - iplfile[1] = IPNAT_NAME; - iplfile[2] = IPSTATE_NAME; + int doread, c, make_daemon = 0; + char *prog; + config_t config; + + prog = strrchr(argv[0], '/'); + if (prog == NULL) + prog = argv[0]; + else + prog++; + + initconfig(&config); while ((c = getopt(argc, argv, "?abB:C:Df:FhL:nN:o:O:pP:sS:tvxX")) != -1) switch (c) { case 'a' : - opts |= OPT_LOGALL; - fdt[0] = IPL_LOGIPF; - fdt[1] = IPL_LOGNAT; - fdt[2] = IPL_LOGSTATE; + ipmonopts |= IPMON_LOGALL; + config.logsrc[0].logtype = IPL_LOGIPF; + config.logsrc[1].logtype = IPL_LOGNAT; + config.logsrc[2].logtype = IPL_LOGSTATE; break; case 'b' : - opts |= OPT_LOGBODY; + ipmonopts |= IPMON_LOGBODY; break; case 'B' : - binarylogfile = optarg; - binarylog = fopen(optarg, "a"); + config.bfile = optarg; + config.blog = fopen(optarg, "a"); break; case 'C' : - conf_file = optarg; + config.cfile = optarg; break; case 'D' : make_daemon = 1; break; case 'f' : case 'I' : - opts |= OPT_FILTER; - fdt[0] = IPL_LOGIPF; - iplfile[0] = optarg; + ipmonopts |= IPMON_FILTER; + config.logsrc[0].logtype = IPL_LOGIPF; + config.logsrc[0].file = optarg; break; case 'F' : - flushlogs(iplfile[0], log); - flushlogs(iplfile[1], log); - flushlogs(iplfile[2], log); + flushlogs(config.logsrc[0].file, config.log); + flushlogs(config.logsrc[1].file, config.log); + flushlogs(config.logsrc[2].file, config.log); break; case 'L' : logfac = fac_findname(optarg); @@ -1524,56 +1652,49 @@ char *argv[]; } break; case 'n' : - opts |= OPT_RESOLVE; + ipmonopts |= IPMON_RESOLVE; + opts &= ~OPT_NORESOLVE; break; case 'N' : - opts |= OPT_NAT; - fdt[1] = IPL_LOGNAT; - iplfile[1] = optarg; + ipmonopts |= IPMON_NAT; + config.logsrc[1].logtype = IPL_LOGNAT; + config.logsrc[1].file = optarg; break; case 'o' : case 'O' : logopts(c == 'o', optarg); - fdt[0] = fdt[1] = fdt[2] = -1; - if (opts & OPT_FILTER) - fdt[0] = IPL_LOGIPF; - if (opts & OPT_NAT) - fdt[1] = IPL_LOGNAT; - if (opts & OPT_STATE) - fdt[2] = IPL_LOGSTATE; + if (ipmonopts & IPMON_FILTER) + config.logsrc[0].logtype = IPL_LOGIPF; + if (ipmonopts & IPMON_NAT) + config.logsrc[1].logtype = IPL_LOGNAT; + if (ipmonopts & IPMON_STATE) + config.logsrc[2].logtype = IPL_LOGSTATE; break; case 'p' : - opts |= OPT_PORTNUM; + ipmonopts |= IPMON_PORTNUM; break; case 'P' : pidfile = optarg; break; case 's' : - s = strrchr(argv[0], '/'); - if (s == NULL) - s = argv[0]; - else - s++; - openlog(s, LOG_NDELAY|LOG_PID, logfac); - s = NULL; - opts |= OPT_SYSLOG; - log = NULL; + ipmonopts |= IPMON_SYSLOG; + config.log = NULL; break; case 'S' : - opts |= OPT_STATE; - fdt[2] = IPL_LOGSTATE; - iplfile[2] = optarg; + ipmonopts |= IPMON_STATE; + config.logsrc[2].logtype = IPL_LOGSTATE; + config.logsrc[2].file = optarg; break; case 't' : - opts |= OPT_TAIL; + ipmonopts |= IPMON_TAIL; break; case 'v' : - opts |= OPT_VERBOSE; + ipmonopts |= IPMON_VERBOSE; break; case 'x' : - opts |= OPT_HEXBODY; + ipmonopts |= IPMON_HEXBODY; break; case 'X' : - opts |= OPT_HEXHDR; + ipmonopts |= IPMON_HEXHDR; break; default : case 'h' : @@ -1581,69 +1702,62 @@ char *argv[]; usage(argv[0]); } + if (ipmonopts & IPMON_SYSLOG) + openlog(prog, LOG_NDELAY|LOG_PID, logfac); + init_tabs(); - if (conf_file) - if (load_config(conf_file) == -1) + if (config.cfile) + if (load_config(config.cfile) == -1) { + unload_config(); exit(1); + } /* * Default action is to only open the filter log file. */ - if ((fdt[0] == -1) && (fdt[1] == -1) && (fdt[2] == -1)) - fdt[0] = IPL_LOGIPF; + if ((config.logsrc[0].logtype == -1) && + (config.logsrc[0].logtype == -1) && + (config.logsrc[0].logtype == -1)) + config.logsrc[0].logtype = IPL_LOGIPF; - for (i = 0; i < 3; i++) { - if (fdt[i] == -1) - continue; - if (!strcmp(iplfile[i], "-")) - fd[i] = 0; - else { - if ((fd[i] = open(iplfile[i], O_RDONLY)) == -1) { - (void) fprintf(stderr, - "%s: open: %s\n", iplfile[i], - STRERROR(errno)); - exit(1); - /* NOTREACHED */ - } - if (fstat(fd[i], &sb) == -1) { - (void) fprintf(stderr, "%d: fstat: %s\n", - fd[i], STRERROR(errno)); - exit(1); - /* NOTREACHED */ - } - if (!(regular[i] = !S_ISCHR(sb.st_mode))) - devices++; - } - } + openlogs(&config); - if (!(opts & OPT_SYSLOG)) { - logfile = argv[optind]; - log = logfile ? fopen(logfile, "a") : stdout; - if (log == NULL) { + if (!(ipmonopts & IPMON_SYSLOG)) { + config.file = argv[optind]; + config.log = config.file ? fopen(config.file, "a") : stdout; + if (config.log == NULL) { (void) fprintf(stderr, "%s: fopen: %s\n", argv[optind], STRERROR(errno)); exit(1); /* NOTREACHED */ } - setvbuf(log, NULL, _IONBF, 0); - } else - log = NULL; + setvbuf(config.log, NULL, _IONBF, 0); + } else { + config.log = NULL; + } - if (make_daemon && ((log != stdout) || (opts & OPT_SYSLOG))) { + if (make_daemon && + ((config.log != stdout) || (ipmonopts & IPMON_SYSLOG))) { #if BSD >= 199306 - daemon(0, !(opts & OPT_SYSLOG)); + daemon(0, !(ipmonopts & IPMON_SYSLOG)); #else int pid; - if ((pid = fork()) > 0) - exit(0); - if (pid < 0) { + + switch (fork()) + { + case -1 : (void) fprintf(stderr, "%s: fork() failed: %s\n", argv[0], STRERROR(errno)); exit(1); /* NOTREACHED */ + case 0 : + break; + default : + exit(0); } + setsid(); - if ((opts & OPT_SYSLOG)) + if ((ipmonopts & IPMON_SYSLOG)) close(2); #endif /* !BSD */ close(0); @@ -1653,80 +1767,142 @@ char *argv[]; signal(SIGHUP, handlehup); - for (doread = 1; doread; ) { - nr = 0; - - for (i = 0; i < 3; i++) { - tr = 0; - if (fdt[i] == -1) - continue; - if (!regular[i]) { - if (ioctl(fd[i], FIONREAD, &tr) == -1) { - if (opts & OPT_SYSLOG) - syslog(LOG_CRIT, - "ioctl(FIONREAD): %m"); - else - perror("ioctl(FIONREAD)"); - exit(1); - /* NOTREACHED */ - } - } else { - tr = (lseek(fd[i], 0, SEEK_CUR) < sb.st_size); - if (!tr && !(opts & OPT_TAIL)) - doread = 0; + for (doread = 1; doread; ) + doread = read_loginfo(&config); + + unload_config(); + + return(0); + /* NOTREACHED */ +} + + +static void openlogs(config_t *conf) +{ + logsource_t *l; + struct stat sb; + int i; + + for (i = 0; i < 3; i++) { + l = &conf->logsrc[i]; + if (l->logtype == -1) + continue; + if (!strcmp(l->file, "-")) + l->fd = 0; + else { + if ((l->fd= open(l->file, O_RDONLY)) == -1) { + (void) fprintf(stderr, + "%s: open: %s\n", l->file, + STRERROR(errno)); + exit(1); + /* NOTREACHED */ } - if (!tr) - continue; - nr += tr; - n = 0; - tr = read_log(fd[i], &n, buf, sizeof(buf)); - if (donehup) { - if (logfile && (fp = fopen(logfile, "a"))) { - fclose(log); - log = fp; - } - if (binarylogfile && - (fp = fopen(binarylogfile, "a"))) { - fclose(binarylog); - binarylog = fp; + if (fstat(l->fd, &sb) == -1) { + (void) fprintf(stderr, "%d: fstat: %s\n", + l->fd, STRERROR(errno)); + exit(1); + /* NOTREACHED */ + } + + l->regular = !S_ISCHR(sb.st_mode); + if (l->regular) + l->size = sb.st_size; + + FD_SET(l->fd, &conf->fdmr); + if (l->fd > conf->maxfd) + conf->maxfd = l->fd; + } + } +} + + +static int read_loginfo(config_t *conf) +{ + iplog_t buf[DEFAULT_IPFLOGSIZE/sizeof(iplog_t)+1]; + int n, tr, nr, i; + logsource_t *l; + fd_set fdr; + + fdr = conf->fdmr; + + n = select(conf->maxfd + 1, &fdr, NULL, NULL, NULL); + if (n == 0) + return 1; + if (n == -1) { + if (errno == EINTR) + return 1; + return -1; + } + + for (i = 0, nr = 0; i < 3; i++) { + l = &conf->logsrc[i]; + + if ((l->logtype == -1) || !FD_ISSET(l->fd, &fdr)) + continue; + + tr = 0; + if (l->regular) { + tr = (lseek(l->fd, 0, SEEK_CUR) < l->size); + if (!tr && !(ipmonopts & IPMON_TAIL)) + return 0; + } + + n = 0; + tr = read_log(l->fd, &n, (char *)buf, sizeof(buf)); + if (donehup) { + if (conf->file != NULL) { + if (conf->log != NULL) { + fclose(conf->log); + conf->log = NULL; } - init_tabs(); - if (conf_file != NULL) - load_config(conf_file); - donehup = 0; + conf->log = fopen(conf->file, "a"); } - switch (tr) - { - case -1 : - if (opts & OPT_SYSLOG) - syslog(LOG_CRIT, "read: %m\n"); - else - perror("read"); - doread = 0; - break; - case 1 : - if (opts & OPT_SYSLOG) - syslog(LOG_CRIT, "aborting logging\n"); - else if (log != NULL) - fprintf(log, "aborting logging\n"); - doread = 0; - break; - case 2 : - break; - case 0 : - if (n > 0) { - print_log(fdt[i], log, buf, n); - if (!(opts & OPT_SYSLOG)) - fflush(log); + if (conf->bfile != NULL) { + if (conf->blog != NULL) { + fclose(conf->blog); + conf->blog = NULL; } - break; + conf->blog = fopen(conf->bfile, "a"); } + + init_tabs(); + if (conf->cfile != NULL) + load_config(conf->cfile); + donehup = 0; + } + + switch (tr) + { + case -1 : + if (ipmonopts & IPMON_SYSLOG) + syslog(LOG_CRIT, "read: %m\n"); + else { + ipferror(l->fd, "read"); + } + return 0; + case 1 : + if (ipmonopts & IPMON_SYSLOG) + syslog(LOG_CRIT, "aborting logging\n"); + else if (conf->log != NULL) + fprintf(conf->log, "aborting logging\n"); + return 0; + case 2 : + break; + case 0 : + nr += tr; + if (n > 0) { + print_log(conf, l, (char *)buf, n); + if (!(ipmonopts & IPMON_SYSLOG)) + fflush(conf->log); + } + break; } - if (!nr && ((opts & OPT_TAIL) || devices)) - sleep(1); } - return(0); - /* NOTREACHED */ + + if (!nr && (ipmonopts & IPMON_TAIL)) + sleep(1); + + return 1; } diff --git a/tools/ipmon_y.y b/tools/ipmon_y.y index bc3ec6ddfa31f..d11470882c121 100644 --- a/tools/ipmon_y.y +++ b/tools/ipmon_y.y @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001-2004 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -11,6 +11,8 @@ #include "ipmon_l.h" #include "ipmon.h" +#include <dlfcn.h> + #define YYDEBUG 1 extern void yyerror __P((char *)); @@ -19,69 +21,88 @@ extern int yylex __P((void)); extern int yydebug; extern FILE *yyin; extern int yylineNum; +extern int ipmonopts; -typedef struct opt { - struct opt *o_next; +typedef struct opt_s { + struct opt_s *o_next; int o_line; int o_type; int o_num; char *o_str; struct in_addr o_ip; + int o_logfac; + int o_logpri; } opt_t; -static void build_action __P((struct opt *)); +static void build_action __P((opt_t *, ipmon_doing_t *)); static opt_t *new_opt __P((int)); static void free_action __P((ipmon_action_t *)); +static void print_action __P((ipmon_action_t *)); +static int find_doing __P((char *)); +static ipmon_doing_t *build_doing __P((char *, char *)); +static void print_match __P((ipmon_action_t *)); +static int install_saver __P((char *, char *)); static ipmon_action_t *alist = NULL; + +ipmon_saver_int_t *saverlist = NULL; %} %union { char *str; u_32_t num; struct in_addr addr; - struct opt *opt; + struct opt_s *opt; union i6addr ip6; + struct ipmon_doing_s *ipmd; } %token <num> YY_NUMBER YY_HEX %token <str> YY_STR %token <ip6> YY_IPV6 -%token YY_COMMENT +%token YY_COMMENT %token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT %token YY_RANGE_OUT YY_RANGE_IN %token IPM_MATCH IPM_BODY IPM_COMMENT IPM_DIRECTION IPM_DSTIP IPM_DSTPORT -%token IPM_EVERY IPM_EXECUTE IPM_GROUP IPM_INTERFACE IPM_IN IPM_NO IPM_OUT +%token IPM_EVERY IPM_GROUP IPM_INTERFACE IPM_IN IPM_NO IPM_OUT IPM_LOADACTION %token IPM_PACKET IPM_PACKETS IPM_POOL IPM_PROTOCOL IPM_RESULT IPM_RULE %token IPM_SECOND IPM_SECONDS IPM_SRCIP IPM_SRCPORT IPM_LOGTAG IPM_WITH -%token IPM_DO IPM_SAVE IPM_SYSLOG IPM_NOTHING IPM_RAW IPM_TYPE IPM_NAT +%token IPM_DO IPM_DOING IPM_TYPE IPM_NAT %token IPM_STATE IPM_NATTAG IPM_IPF %type <addr> ipv4 -%type <opt> direction dstip dstport every execute group interface +%type <opt> direction dstip dstport every group interface %type <opt> protocol result rule srcip srcport logtag matching -%type <opt> matchopt nattag type doopt doing save syslog nothing -%type <num> saveopts saveopt typeopt +%type <opt> matchopt nattag type +%type <num> typeopt +%type <ipmd> doopt doing %% -file: line - | assign - | file line - | file assign +file: action + | file action ; -line: IPM_MATCH '{' matching '}' IPM_DO '{' doing '}' ';' - { build_action($3); resetlexer(); } +action: line ';' + | assign ';' | IPM_COMMENT | YY_COMMENT ; -assign: YY_STR assigning YY_STR ';' { set_variable($1, $3); +line: IPM_MATCH '{' matching ';' '}' IPM_DO '{' doing ';' '}' + { build_action($3, $8); + resetlexer(); + } + | IPM_LOADACTION YY_STR YY_STR { if (install_saver($2, $3)) + yyerror("install saver"); + } + ; + +assign: YY_STR assigning YY_STR { set_variable($1, $3); resetlexer(); free($1); free($3); yyvarnext = 0; - } + } ; assigning: @@ -112,14 +133,20 @@ matchopt: doing: doopt { $$ = $1; } - | doopt ',' doing { $1->o_next = $3; $$ = $1; } + | doopt ',' doing { $1->ipmd_next = $3; $$ = $1; } ; doopt: - execute { $$ = $1; } - | save { $$ = $1; } - | syslog { $$ = $1; } - | nothing { $$ = $1; } + YY_STR { if (find_doing($1) != IPM_DOING) + yyerror("unknown action"); + } + '(' YY_STR ')' { $$ = build_doing($1, $4); + if ($$ == NULL) + yyerror("action building"); + } + | YY_STR { if (find_doing($1) == IPM_DOING) + $$ = build_doing($1, NULL); + } ; direction: @@ -209,31 +236,7 @@ typeopt: | IPM_STATE { $$ = IPL_MAGIC_STATE; } ; -execute: - IPM_EXECUTE YY_STR { $$ = new_opt(IPM_EXECUTE); - $$->o_str = $2; } - ; -save: IPM_SAVE saveopts YY_STR { $$ = new_opt(IPM_SAVE); - $$->o_num = $2; - $$->o_str = $3; } - ; - -saveopts: { $$ = 0; } - | saveopt { $$ = $1; } - | saveopt ',' saveopts { $$ = $1 | $3; } - ; - -saveopt: - IPM_RAW { $$ = IPMDO_SAVERAW; } - ; - -syslog: IPM_SYSLOG { $$ = new_opt(IPM_SYSLOG); } - ; - -nothing: - IPM_NOTHING { $$ = 0; } - ; ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) { @@ -251,30 +254,27 @@ static struct wordtab yywords[] = { { "dstip", IPM_DSTIP }, { "dstport", IPM_DSTPORT }, { "every", IPM_EVERY }, - { "execute", IPM_EXECUTE }, { "group", IPM_GROUP }, { "in", IPM_IN }, { "interface", IPM_INTERFACE }, { "ipf", IPM_IPF }, + { "load_action",IPM_LOADACTION }, { "logtag", IPM_LOGTAG }, { "match", IPM_MATCH }, { "nat", IPM_NAT }, { "nattag", IPM_NATTAG }, { "no", IPM_NO }, - { "nothing", IPM_NOTHING }, { "out", IPM_OUT }, { "packet", IPM_PACKET }, { "packets", IPM_PACKETS }, { "protocol", IPM_PROTOCOL }, { "result", IPM_RESULT }, { "rule", IPM_RULE }, - { "save", IPM_SAVE }, { "second", IPM_SECOND }, { "seconds", IPM_SECONDS }, { "srcip", IPM_SRCIP }, { "srcport", IPM_SRCPORT }, { "state", IPM_STATE }, - { "syslog", IPM_SYSLOG }, { "with", IPM_WITH }, { NULL, 0 } }; @@ -299,31 +299,33 @@ static int macflags[17][2] = { { 0, 0 } }; -static opt_t *new_opt(type) -int type; +static opt_t * +new_opt(type) + int type; { opt_t *o; - o = (opt_t *)malloc(sizeof(*o)); + o = (opt_t *)calloc(1, sizeof(*o)); o->o_type = type; o->o_line = yylineNum; - o->o_num = 0; - o->o_str = (char *)0; - o->o_next = NULL; + o->o_logfac = -1; + o->o_logpri = -1; return o; } -static void build_action(olist) -opt_t *olist; +static void +build_action(olist, todo) + opt_t *olist; + ipmon_doing_t *todo; { ipmon_action_t *a; opt_t *o; - char c; int i; a = (ipmon_action_t *)calloc(1, sizeof(*a)); if (a == NULL) return; + while ((o = olist) != NULL) { /* * Check to see if the same comparator is being used more than @@ -356,24 +358,11 @@ opt_t *olist; case IPM_DSTPORT : a->ac_dport = htons(o->o_num); break; - case IPM_EXECUTE : - a->ac_exec = o->o_str; - c = *o->o_str; - if (c== '"'|| c == '\'') { - if (o->o_str[strlen(o->o_str) - 1] == c) { - a->ac_run = strdup(o->o_str + 1); - a->ac_run[strlen(a->ac_run) - 1] ='\0'; - } else - a->ac_run = o->o_str; - } else - a->ac_run = o->o_str; - o->o_str = NULL; - break; case IPM_INTERFACE : a->ac_iface = o->o_str; o->o_str = NULL; break; - case IPM_GROUP : + case IPM_GROUP : if (o->o_str != NULL) strncpy(a->ac_group, o->o_str, FR_GROUPLEN); else @@ -414,24 +403,6 @@ opt_t *olist; case IPM_SRCPORT : a->ac_sport = htons(o->o_num); break; - case IPM_SAVE : - if (a->ac_savefile != NULL) { - fprintf(stderr, "%s redfined on line %d\n", - yykeytostr(o->o_type), yylineNum); - break; - } - a->ac_savefile = strdup(o->o_str); - a->ac_savefp = fopen(o->o_str, "a"); - a->ac_dflag |= o->o_num & IPMDO_SAVERAW; - break; - case IPM_SYSLOG : - if (a->ac_syslog != 0) { - fprintf(stderr, "%s redfined on line %d\n", - yykeytostr(o->o_type), yylineNum); - break; - } - a->ac_syslog = 1; - break; case IPM_TYPE : a->ac_type = o->o_num; break; @@ -446,17 +417,25 @@ opt_t *olist; free(o->o_str); free(o); } + + a->ac_doing = todo; a->ac_next = alist; alist = a; + + if (ipmonopts & IPMON_VERBOSE) + print_action(a); } -int check_action(buf, log, opts, lvl) -char *buf, *log; -int opts, lvl; +int +check_action(buf, log, opts, lvl) + char *buf, *log; + int opts, lvl; { ipmon_action_t *a; struct timeval tv; + ipmon_doing_t *d; + ipmon_msg_t msg; ipflog_t *ipf; tcphdr_t *tcp; iplog_t *ipl; @@ -470,19 +449,33 @@ int opts, lvl; ip = (ip_t *)(ipf + 1); tcp = (tcphdr_t *)((char *)ip + (IP_HL(ip) << 2)); + msg.imm_data = ipl; + msg.imm_dsize = ipl->ipl_dsize; + msg.imm_when = ipl->ipl_time.tv_sec; + msg.imm_msg = log; + msg.imm_msglen = strlen(log); + msg.imm_loglevel = lvl; + for (a = alist; a != NULL; a = a->ac_next) { + verbose(0, "== checking config rule\n"); if ((a->ac_mflag & IPMAC_DIRECTION) != 0) { if (a->ac_direction == IPM_IN) { - if ((ipf->fl_flags & FR_INQUE) == 0) + if ((ipf->fl_flags & FR_INQUE) == 0) { + verbose(8, "-- direction not in\n"); continue; + } } else if (a->ac_direction == IPM_OUT) { - if ((ipf->fl_flags & FR_OUTQUE) == 0) + if ((ipf->fl_flags & FR_OUTQUE) == 0) { + verbose(8, "-- direction not out\n"); continue; + } } } - if ((a->ac_type != 0) && (a->ac_type != ipl->ipl_magic)) + if ((a->ac_type != 0) && (a->ac_type != ipl->ipl_magic)) { + verbose(8, "-- type mismatch\n"); continue; + } if ((a->ac_mflag & IPMAC_EVERY) != 0) { gettimeofday(&tv, NULL); @@ -490,8 +483,10 @@ int opts, lvl; if (tv.tv_usec <= a->ac_lastusec) t1--; if (a->ac_second != 0) { - if (t1 < a->ac_second) + if (t1 < a->ac_second) { + verbose(8, "-- too soon\n"); continue; + } a->ac_lastsec = tv.tv_sec; a->ac_lastusec = tv.tv_usec; } @@ -501,159 +496,149 @@ int opts, lvl; a->ac_pktcnt++; else if (a->ac_pktcnt == a->ac_packet) { a->ac_pktcnt = 0; + verbose(8, "-- packet count\n"); continue; } else { a->ac_pktcnt++; + verbose(8, "-- packet count\n"); continue; } } } if ((a->ac_mflag & IPMAC_DSTIP) != 0) { - if ((ip->ip_dst.s_addr & a->ac_dmsk) != a->ac_dip) + if ((ip->ip_dst.s_addr & a->ac_dmsk) != a->ac_dip) { + verbose(8, "-- dstip wrong\n"); continue; + } } if ((a->ac_mflag & IPMAC_DSTPORT) != 0) { - if (ip->ip_p != IPPROTO_UDP && ip->ip_p != IPPROTO_TCP) + if (ip->ip_p != IPPROTO_UDP && + ip->ip_p != IPPROTO_TCP) { + verbose(8, "-- not port protocol\n"); continue; - if (tcp->th_dport != a->ac_dport) + } + if (tcp->th_dport != a->ac_dport) { + verbose(8, "-- dport mismatch\n"); continue; + } } if ((a->ac_mflag & IPMAC_GROUP) != 0) { if (strncmp(a->ac_group, ipf->fl_group, - FR_GROUPLEN) != 0) + FR_GROUPLEN) != 0) { + verbose(8, "-- group mismatch\n"); continue; + } } if ((a->ac_mflag & IPMAC_INTERFACE) != 0) { - if (strcmp(a->ac_iface, ipf->fl_ifname)) + if (strcmp(a->ac_iface, ipf->fl_ifname)) { + verbose(8, "-- ifname mismatch\n"); continue; + } } if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) { - if (a->ac_proto != ip->ip_p) + if (a->ac_proto != ip->ip_p) { + verbose(8, "-- protocol mismatch\n"); continue; + } } if ((a->ac_mflag & IPMAC_RESULT) != 0) { if ((ipf->fl_flags & FF_LOGNOMATCH) != 0) { - if (a->ac_result != IPMR_NOMATCH) + if (a->ac_result != IPMR_NOMATCH) { + verbose(8, "-- ff-flags mismatch\n"); continue; + } } else if (FR_ISPASS(ipf->fl_flags)) { - if (a->ac_result != IPMR_PASS) + if (a->ac_result != IPMR_PASS) { + verbose(8, "-- pass mismatch\n"); continue; + } } else if (FR_ISBLOCK(ipf->fl_flags)) { - if (a->ac_result != IPMR_BLOCK) + if (a->ac_result != IPMR_BLOCK) { + verbose(8, "-- block mismatch\n"); continue; + } } else { /* Log only */ - if (a->ac_result != IPMR_LOG) + if (a->ac_result != IPMR_LOG) { + verbose(8, "-- log mismatch\n"); continue; + } } } if ((a->ac_mflag & IPMAC_RULE) != 0) { - if (a->ac_rule != ipf->fl_rule) + if (a->ac_rule != ipf->fl_rule) { + verbose(8, "-- rule mismatch\n"); continue; + } } if ((a->ac_mflag & IPMAC_SRCIP) != 0) { - if ((ip->ip_src.s_addr & a->ac_smsk) != a->ac_sip) + if ((ip->ip_src.s_addr & a->ac_smsk) != a->ac_sip) { + verbose(8, "-- srcip mismatch\n"); continue; + } } if ((a->ac_mflag & IPMAC_SRCPORT) != 0) { - if (ip->ip_p != IPPROTO_UDP && ip->ip_p != IPPROTO_TCP) + if (ip->ip_p != IPPROTO_UDP && + ip->ip_p != IPPROTO_TCP) { + verbose(8, "-- port protocol mismatch\n"); continue; - if (tcp->th_sport != a->ac_sport) + } + if (tcp->th_sport != a->ac_sport) { + verbose(8, "-- sport mismatch\n"); continue; + } } if ((a->ac_mflag & IPMAC_LOGTAG) != 0) { - if (a->ac_logtag != ipf->fl_logtag) + if (a->ac_logtag != ipf->fl_logtag) { + verbose(8, "-- logtag %d != %d\n", + a->ac_logtag, ipf->fl_logtag); continue; + } } if ((a->ac_mflag & IPMAC_NATTAG) != 0) { if (strncmp(a->ac_nattag, ipf->fl_nattag.ipt_tag, - IPFTAG_LEN) != 0) + IPFTAG_LEN) != 0) { + verbose(8, "-- nattag mismatch\n"); continue; + } } matched = 1; + verbose(8, "++ matched\n"); /* - * It matched so now execute the command + * It matched so now perform the saves */ - if (a->ac_syslog != 0) { - syslog(lvl, "%s", log); - } - - if (a->ac_savefp != NULL) { - if (a->ac_dflag & IPMDO_SAVERAW) - fwrite(ipl, 1, ipl->ipl_dsize, a->ac_savefp); - else - fputs(log, a->ac_savefp); - } - - if (a->ac_exec != NULL) { - switch (fork()) - { - case 0 : - { - FILE *pi; - - pi = popen(a->ac_run, "w"); - if (pi != NULL) { - fprintf(pi, "%s\n", log); - if ((opts & OPT_HEXHDR) != 0) { - dumphex(pi, 0, buf, - sizeof(*ipl) + - sizeof(*ipf)); - } - if ((opts & OPT_HEXBODY) != 0) { - dumphex(pi, 0, (char *)ip, - ipf->fl_hlen + - ipf->fl_plen); - } - pclose(pi); - } - exit(1); - } - case -1 : - break; - default : - break; - } - } + for (d = a->ac_doing; d != NULL; d = d->ipmd_next) + (*d->ipmd_store)(d->ipmd_token, &msg); } return matched; } -static void free_action(a) -ipmon_action_t *a; +static void +free_action(a) + ipmon_action_t *a; { - if (a->ac_savefile != NULL) { - free(a->ac_savefile); - a->ac_savefile = NULL; - } - if (a->ac_savefp != NULL) { - fclose(a->ac_savefp); - a->ac_savefp = NULL; - } - if (a->ac_exec != NULL) { - free(a->ac_exec); - if (a->ac_run == a->ac_exec) - a->ac_run = NULL; - a->ac_exec = NULL; - } - if (a->ac_run != NULL) { - free(a->ac_run); - a->ac_run = NULL; + ipmon_doing_t *d; + + while ((d = a->ac_doing) != NULL) { + a->ac_doing = d->ipmd_next; + (*d->ipmd_saver->ims_destroy)(d->ipmd_token); + free(d); } + if (a->ac_iface != NULL) { free(a->ac_iface); a->ac_iface = NULL; @@ -663,24 +648,21 @@ ipmon_action_t *a; } -int load_config(file) -char *file; +int +load_config(file) + char *file; { - ipmon_action_t *a; FILE *fp; char *s; + unload_config(); + s = getenv("YYDEBUG"); if (s != NULL) yydebug = atoi(s); else yydebug = 0; - while ((a = alist) != NULL) { - alist = a->ac_next; - free_action(a); - } - yylineNum = 1; (void) yysettab(yywords); @@ -696,3 +678,373 @@ char *file; fclose(fp); return 0; } + + +void +unload_config() +{ + ipmon_saver_int_t *sav, **imsip; + ipmon_saver_t *is; + ipmon_action_t *a; + + while ((a = alist) != NULL) { + alist = a->ac_next; + free_action(a); + } + + /* + * Look for savers that have been added in dynamically from the + * configuration file. + */ + for (imsip = &saverlist; (sav = *imsip) != NULL; ) { + if (sav->imsi_handle == NULL) + imsip = &sav->imsi_next; + else { + dlclose(sav->imsi_handle); + + *imsip = sav->imsi_next; + is = sav->imsi_stor; + free(sav); + + free(is->ims_name); + free(is); + } + } +} + + +void +dump_config() +{ + ipmon_action_t *a; + + for (a = alist; a != NULL; a = a->ac_next) { + print_action(a); + + printf("#\n"); + } +} + + +static void +print_action(a) + ipmon_action_t *a; +{ + ipmon_doing_t *d; + + printf("match { "); + print_match(a); + printf("; }\n"); + printf("do {"); + for (d = a->ac_doing; d != NULL; d = d->ipmd_next) { + printf("%s", d->ipmd_saver->ims_name); + if (d->ipmd_saver->ims_print != NULL) { + printf("(\""); + (*d->ipmd_saver->ims_print)(d->ipmd_token); + printf("\")"); + } + printf(";"); + } + printf("};\n"); +} + + +void * +add_doing(saver) + ipmon_saver_t *saver; +{ + ipmon_saver_int_t *it; + + if (find_doing(saver->ims_name) == IPM_DOING) + return NULL; + + it = calloc(1, sizeof(*it)); + if (it == NULL) + return NULL; + it->imsi_stor = saver; + it->imsi_next = saverlist; + saverlist = it; + return it; +} + + +static int +find_doing(string) + char *string; +{ + ipmon_saver_int_t *it; + + for (it = saverlist; it != NULL; it = it->imsi_next) { + if (!strcmp(it->imsi_stor->ims_name, string)) + return IPM_DOING; + } + return 0; +} + + +static ipmon_doing_t * +build_doing(target, options) + char *target; + char *options; +{ + ipmon_saver_int_t *it; + char *strarray[2]; + ipmon_doing_t *d, *d1; + ipmon_action_t *a; + ipmon_saver_t *save; + + d = calloc(1, sizeof(*d)); + if (d == NULL) + return NULL; + + for (it = saverlist; it != NULL; it = it->imsi_next) { + if (!strcmp(it->imsi_stor->ims_name, target)) + break; + } + if (it == NULL) { + free(d); + return NULL; + } + + strarray[0] = options; + strarray[1] = NULL; + + d->ipmd_token = (*it->imsi_stor->ims_parse)(strarray); + if (d->ipmd_token == NULL) { + free(d); + return NULL; + } + + save = it->imsi_stor; + d->ipmd_saver = save; + d->ipmd_store = it->imsi_stor->ims_store; + + /* + * Look for duplicate do-things that need to be dup'd + */ + for (a = alist; a != NULL; a = a->ac_next) { + for (d1 = a->ac_doing; d1 != NULL; d1 = d1->ipmd_next) { + if (save != d1->ipmd_saver) + continue; + if (save->ims_match == NULL || save->ims_dup == NULL) + continue; + if ((*save->ims_match)(d->ipmd_token, d1->ipmd_token)) + continue; + + (*d->ipmd_saver->ims_destroy)(d->ipmd_token); + d->ipmd_token = (*save->ims_dup)(d1->ipmd_token); + break; + } + } + + return d; +} + + +static void +print_match(a) + ipmon_action_t *a; +{ + char *coma = ""; + + if ((a->ac_mflag & IPMAC_DIRECTION) != 0) { + printf("direction = "); + if (a->ac_direction == IPM_IN) + printf("in"); + else if (a->ac_direction == IPM_OUT) + printf("out"); + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_DSTIP) != 0) { + printf("%sdstip = ", coma); + printhostmask(AF_INET, &a->ac_dip, &a->ac_dmsk); + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_DSTPORT) != 0) { + printf("%sdstport = %hu", coma, ntohs(a->ac_dport)); + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_GROUP) != 0) { + char group[FR_GROUPLEN+1]; + + strncpy(group, a->ac_group, FR_GROUPLEN); + group[FR_GROUPLEN] = '\0'; + printf("%sgroup = %s", coma, group); + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_INTERFACE) != 0) { + printf("%siface = %s", coma, a->ac_iface); + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_LOGTAG) != 0) { + printf("%slogtag = %u", coma, a->ac_logtag); + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_NATTAG) != 0) { + char tag[17]; + + strncpy(tag, a->ac_nattag, 16); + tag[16] = '\0'; + printf("%snattag = %s", coma, tag); + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) { + printf("%sprotocol = %u", coma, a->ac_proto); + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_RESULT) != 0) { + printf("%sresult = ", coma); + switch (a->ac_result) + { + case IPMR_LOG : + printf("log"); + break; + case IPMR_PASS : + printf("pass"); + break; + case IPMR_BLOCK : + printf("block"); + break; + case IPMR_NOMATCH : + printf("nomatch"); + break; + } + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_RULE) != 0) { + printf("%srule = %u", coma, a->ac_rule); + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_EVERY) != 0) { + if (a->ac_packet > 1) { + printf("%severy %d packets", coma, a->ac_packet); + coma = ", "; + } else if (a->ac_packet == 1) { + printf("%severy packet", coma); + coma = ", "; + } + if (a->ac_second > 1) { + printf("%severy %d seconds", coma, a->ac_second); + coma = ", "; + } else if (a->ac_second == 1) { + printf("%severy second", coma); + coma = ", "; + } + } + + if ((a->ac_mflag & IPMAC_SRCIP) != 0) { + printf("%ssrcip = ", coma); + printhostmask(AF_INET, &a->ac_sip, &a->ac_smsk); + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_SRCPORT) != 0) { + printf("%ssrcport = %hu", coma, ntohs(a->ac_sport)); + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_TYPE) != 0) { + printf("%stype = ", coma); + switch (a->ac_type) + { + case IPL_LOGIPF : + printf("ipf"); + break; + case IPL_LOGSTATE : + printf("state"); + break; + case IPL_LOGNAT : + printf("nat"); + break; + } + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_WITH) != 0) { + printf("%swith ", coma); + coma = ", "; + } +} + + +static int +install_saver(name, path) + char *name, *path; +{ + ipmon_saver_int_t *isi; + ipmon_saver_t *is; + char nbuf[80]; + + if (find_doing(name) == IPM_DOING) + return -1; + + isi = calloc(1, sizeof(*isi)); + if (isi == NULL) + return -1; + + is = calloc(1, sizeof(*is)); + if (is == NULL) + goto loaderror; + + is->ims_name = name; + +#ifdef RTLD_LAZY + isi->imsi_handle = dlopen(path, RTLD_LAZY); +#endif +#ifdef DL_LAZY + isi->imsi_handle = dlopen(path, DL_LAZY); +#endif + + if (isi->imsi_handle == NULL) + goto loaderror; + + snprintf(nbuf, sizeof(nbuf), "%sdup", name); + is->ims_dup = (ims_dup_func_t)dlsym(isi->imsi_handle, nbuf); + + snprintf(nbuf, sizeof(nbuf), "%sdestroy", name); + is->ims_destroy = (ims_destroy_func_t)dlsym(isi->imsi_handle, nbuf); + if (is->ims_destroy == NULL) + goto loaderror; + + snprintf(nbuf, sizeof(nbuf), "%smatch", name); + is->ims_match = (ims_match_func_t)dlsym(isi->imsi_handle, nbuf); + + snprintf(nbuf, sizeof(nbuf), "%sparse", name); + is->ims_parse = (ims_parse_func_t)dlsym(isi->imsi_handle, nbuf); + if (is->ims_parse == NULL) + goto loaderror; + + snprintf(nbuf, sizeof(nbuf), "%sprint", name); + is->ims_print = (ims_print_func_t)dlsym(isi->imsi_handle, nbuf); + if (is->ims_print == NULL) + goto loaderror; + + snprintf(nbuf, sizeof(nbuf), "%sstore", name); + is->ims_store = (ims_store_func_t)dlsym(isi->imsi_handle, nbuf); + if (is->ims_store == NULL) + goto loaderror; + + isi->imsi_stor = is; + isi->imsi_next = saverlist; + saverlist = isi; + + return 0; + +loaderror: + if (isi->imsi_handle != NULL) + dlclose(isi->imsi_handle); + free(isi); + if (is != NULL) + free(is); + return -1; +} diff --git a/tools/ipnat.c b/tools/ipnat.c index 038df6d069c95..e7378bcd483ac 100644 --- a/tools/ipnat.c +++ b/tools/ipnat.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * @@ -65,7 +65,7 @@ extern char *sys_errlist[]; #if !defined(lint) static const char sccsid[] ="@(#)ipnat.c 1.9 6/5/96 (C) 1993 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipnat.c,v 1.24.2.11 2007/09/25 08:27:34 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif @@ -77,23 +77,25 @@ char thishost[MAXHOSTNAMELEN]; extern char *optarg; -void dostats __P((int, natstat_t *, int, int)); -void dotable __P((natstat_t *, int, int)); -void flushtable __P((int, int)); +void dostats __P((int, natstat_t *, int, int, int *)); +void dotable __P((natstat_t *, int, int, int, char *)); +void flushtable __P((int, int, int *)); void usage __P((char *)); int main __P((int, char*[])); void showhostmap __P((natstat_t *nsp)); void natstat_dead __P((natstat_t *, char *)); -void dostats_live __P((int, natstat_t *, int)); +void dostats_live __P((int, natstat_t *, int, int *)); void showhostmap_dead __P((natstat_t *)); void showhostmap_live __P((int, natstat_t *)); -void dostats_dead __P((natstat_t *, int)); -void showtqtable_live __P((int)); +void dostats_dead __P((natstat_t *, int, int *)); +int nat_matcharray __P((nat_t *, int *)); -int opts; +int opts; +int nohdrfields = 0; +wordtab_t *nat_fields = NULL; void usage(name) -char *name; + char *name; { fprintf(stderr, "Usage: %s [-CFhlnrRsv] [-f filename]\n", name); exit(1); @@ -101,12 +103,12 @@ char *name; int main(argc, argv) -int argc; -char *argv[]; + int argc; + char *argv[]; { + int fd, c, mode, *natfilter; char *file, *core, *kernel; natstat_t ns, *nsp; - int fd, c, mode; ipfobj_t obj; fd = -1; @@ -116,8 +118,11 @@ char *argv[]; core = NULL; kernel = NULL; mode = O_RDWR; + natfilter = NULL; - while ((c = getopt(argc, argv, "CdFf:hlM:N:nrRsv")) != -1) + assigndefined(getenv("IPNAT_PREDEFINED")); + + while ((c = getopt(argc, argv, "CdFf:hlm:M:N:nO:prRsv")) != -1) switch (c) { case 'C' : @@ -139,6 +144,9 @@ char *argv[]; opts |= OPT_LIST; mode = O_RDONLY; break; + case 'm' : + natfilter = parseipfexpr(optarg, NULL); + break; case 'M' : core = optarg; break; @@ -146,9 +154,15 @@ char *argv[]; kernel = optarg; break; case 'n' : - opts |= OPT_DONOTHING; + opts |= OPT_DONOTHING|OPT_DONTOPEN; mode = O_RDONLY; break; + case 'O' : + nat_fields = parsefields(natfields, optarg); + break; + case 'p' : + opts |= OPT_PURGE; + break; case 'R' : opts |= OPT_NORESOLVE; break; @@ -166,6 +180,12 @@ char *argv[]; usage(argv[0]); } + if (((opts & OPT_PURGE) != 0) && ((opts & OPT_REMOVE) == 0)) { + (void) fprintf(stderr, "%s: -p must be used with -r\n", + argv[0]); + exit(1); + } + initparse(); if ((kernel != NULL) || (core != NULL)) { @@ -198,7 +218,7 @@ char *argv[]; obj.ipfo_size = sizeof(*nsp); obj.ipfo_ptr = (void *)nsp; if (ioctl(fd, SIOCGNATS, &obj) == -1) { - perror("ioctl(SIOCGNATS)"); + ipferror(fd, "ioctl(SIOCGNATS)"); exit(1); } (void) setgid(getgid()); @@ -209,17 +229,17 @@ char *argv[]; natstat_dead(nsp, kernel); if (opts & (OPT_LIST|OPT_STAT)) - dostats(fd, nsp, opts, 0); + dostats(fd, nsp, opts, 0, natfilter); exit(0); } if (opts & (OPT_FLUSH|OPT_CLEAR)) - flushtable(fd, opts); + flushtable(fd, opts, natfilter); if (file) { - ipnat_parsefile(fd, ipnat_addrule, ioctl, file); + return ipnat_parsefile(fd, ipnat_addrule, ioctl, file); } if (opts & (OPT_LIST|OPT_STAT)) - dostats(fd, nsp, opts, 1); + dostats(fd, nsp, opts, 1, natfilter); return 0; } @@ -229,8 +249,8 @@ char *argv[]; * rather than doing ioctl's. */ void natstat_dead(nsp, kernel) -natstat_t *nsp; -char *kernel; + natstat_t *nsp; + char *kernel; { struct nlist nat_nlist[10] = { { "nat_table" }, /* 0 */ @@ -241,7 +261,6 @@ char *kernel; { "ipf_rdrrules_sz" }, /* 5 */ { "ipf_hostmap_sz" }, { "nat_instances" }, - { "ap_sess_list" }, { NULL } }; void *tables[2]; @@ -257,8 +276,8 @@ char *kernel; * one in individually. */ kmemcpy((char *)&tables, nat_nlist[0].n_value, sizeof(tables)); - nsp->ns_table[0] = tables[0]; - nsp->ns_table[1] = tables[1]; + nsp->ns_side[0].ns_table = tables[0]; + nsp->ns_side[1].ns_table = tables[1]; kmemcpy((char *)&nsp->ns_list, nat_nlist[1].n_value, sizeof(nsp->ns_list)); @@ -274,8 +293,6 @@ char *kernel; sizeof(nsp->ns_hostmap_sz)); kmemcpy((char *)&nsp->ns_instances, nat_nlist[7].n_value, sizeof(nsp->ns_instances)); - kmemcpy((char *)&nsp->ns_apslist, nat_nlist[8].n_value, - sizeof(nsp->ns_apslist)); } @@ -283,23 +300,40 @@ char *kernel; * Issue an ioctl to flush either the NAT rules table or the active mapping * table or both. */ -void flushtable(fd, opts) -int fd, opts; +void flushtable(fd, opts, match) + int fd, opts, *match; { int n = 0; if (opts & OPT_FLUSH) { n = 0; - if (!(opts & OPT_DONOTHING) && ioctl(fd, SIOCIPFFL, &n) == -1) - perror("ioctl(SIOCFLNAT)"); - else + if (!(opts & OPT_DONOTHING)) { + if (match != NULL) { + ipfobj_t obj; + + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_size = match[0] * sizeof(int); + obj.ipfo_type = IPFOBJ_IPFEXPR; + obj.ipfo_ptr = match; + if (ioctl(fd, SIOCMATCHFLUSH, &obj) == -1) { + ipferror(fd, "ioctl(SIOCMATCHFLUSH)"); + n = -1; + } else { + n = obj.ipfo_retval; + } + } else if (ioctl(fd, SIOCIPFFL, &n) == -1) { + ipferror(fd, "ioctl(SIOCIPFFL)"); + n = -1; + } + } + if (n >= 0) printf("%d entries flushed from NAT table\n", n); } if (opts & OPT_CLEAR) { n = 1; if (!(opts & OPT_DONOTHING) && ioctl(fd, SIOCIPFFL, &n) == -1) - perror("ioctl(SIOCCNATL)"); + ipferror(fd, "ioctl(SIOCCNATL)"); else printf("%d entries flushed from NAT list\n", n); } @@ -309,34 +343,65 @@ int fd, opts; /* * Display NAT statistics. */ -void dostats_dead(nsp, opts) -natstat_t *nsp; -int opts; +void dostats_dead(nsp, opts, filter) + natstat_t *nsp; + int opts, *filter; { nat_t *np, nat; ipnat_t ipn; - - printf("List of active MAP/Redirect filters:\n"); - while (nsp->ns_list) { - if (kmemcpy((char *)&ipn, (long)nsp->ns_list, - sizeof(ipn))) { - perror("kmemcpy"); - break; + int i; + + if (nat_fields == NULL) { + printf("List of active MAP/Redirect filters:\n"); + while (nsp->ns_list) { + if (kmemcpy((char *)&ipn, (long)nsp->ns_list, + sizeof(ipn))) { + perror("kmemcpy"); + break; + } + if (opts & OPT_HITS) + printf("%lu ", ipn.in_hits); + printnat(&ipn, opts & (OPT_DEBUG|OPT_VERBOSE)); + nsp->ns_list = ipn.in_next; } - if (opts & OPT_HITS) - printf("%lu ", ipn.in_hits); - printnat(&ipn, opts & (OPT_DEBUG|OPT_VERBOSE)); - nsp->ns_list = ipn.in_next; } - printf("\nList of active sessions:\n"); + if (nat_fields == NULL) { + printf("\nList of active sessions:\n"); + + } else if (nohdrfields == 0) { + for (i = 0; nat_fields[i].w_value != 0; i++) { + printfieldhdr(natfields, nat_fields + i); + if (nat_fields[i + 1].w_value != 0) + printf("\t"); + } + printf("\n"); + } for (np = nsp->ns_instances; np; np = nat.nat_next) { if (kmemcpy((char *)&nat, (long)np, sizeof(nat))) break; - printactivenat(&nat, opts, 0, nsp->ns_ticks); - if (nat.nat_aps) - printaps(nat.nat_aps, opts); + if ((filter != NULL) && (nat_matcharray(&nat, filter) == 0)) + continue; + if (nat_fields != NULL) { + for (i = 0; nat_fields[i].w_value != 0; i++) { + printnatfield(&nat, nat_fields[i].w_value); + if (nat_fields[i + 1].w_value != 0) + printf("\t"); + } + printf("\n"); + } else { + printactivenat(&nat, opts, nsp->ns_ticks); + if (nat.nat_aps) { + int proto; + + if (nat.nat_dir & NAT_OUTBOUND) + proto = nat.nat_pr[1]; + else + proto = nat.nat_pr[0]; + printaps(nat.nat_aps, opts, proto); + } + } } if (opts & OPT_VERBOSE) @@ -344,62 +409,39 @@ int opts; } -void dostats(fd, nsp, opts, alive) -natstat_t *nsp; -int fd, opts, alive; -{ - /* - * Show statistics ? - */ - if (opts & OPT_STAT) { - printf("mapped\tin\t%lu\tout\t%lu\n", - nsp->ns_mapped[0], nsp->ns_mapped[1]); - printf("added\t%lu\texpired\t%lu\n", - nsp->ns_added, nsp->ns_expire); - printf("no memory\t%lu\tbad nat\t%lu\n", - nsp->ns_memfail, nsp->ns_badnat); - printf("inuse\t%lu\norphans\t%u\nrules\t%lu\n", - nsp->ns_inuse, nsp->ns_orphans, nsp->ns_rules); - printf("wilds\t%u\n", nsp->ns_wilds); - dotable(nsp, fd, alive); - if (opts & OPT_VERBOSE) - printf("table %p list %p\n", - nsp->ns_table, nsp->ns_list); - if (alive) - showtqtable_live(fd); - } - - if (opts & OPT_LIST) { - if (alive) - dostats_live(fd, nsp, opts); - else - dostats_dead(nsp, opts); - } -} - - -void dotable(nsp, fd, alive) -natstat_t *nsp; -int fd, alive; +void dotable(nsp, fd, alive, which, side) + natstat_t *nsp; + int fd, alive, which; + char *side; { - int sz, i, used, totallen, maxlen, minlen; + int sz, i, used, maxlen, minlen, totallen; ipftable_t table; - u_long *buckets; + u_int *buckets; ipfobj_t obj; sz = sizeof(*buckets) * nsp->ns_nattab_sz; - buckets = (u_long *)malloc(sz); + buckets = (u_int *)malloc(sz); + if (buckets == NULL) { + fprintf(stderr, + "cannot allocate memory (%d) for buckets\n", sz); + return; + } obj.ipfo_rev = IPFILTER_VERSION; obj.ipfo_type = IPFOBJ_GTABLE; obj.ipfo_size = sizeof(table); obj.ipfo_ptr = &table; - table.ita_type = IPFTABLE_BUCKETS_NATIN; + if (which == 0) { + table.ita_type = IPFTABLE_BUCKETS_NATIN; + } else if (which == 1) { + table.ita_type = IPFTABLE_BUCKETS_NATOUT; + } table.ita_table = buckets; if (alive) { if (ioctl(fd, SIOCGTABL, &obj) != 0) { + ipferror(fd, "SIOCFTABL"); free(buckets); return; } @@ -410,9 +452,9 @@ int fd, alive; } } + minlen = nsp->ns_side[which].ns_inuse; totallen = 0; maxlen = 0; - minlen = nsp->ns_inuse; used = 0; for (i = 0; i < nsp->ns_nattab_sz; i++) { @@ -425,27 +467,84 @@ int fd, alive; totallen += buckets[i]; } - printf("hash efficiency\t%2.2f%%\n", - totallen ? ((float)used / totallen) * 100.0 : 0.0); - printf("bucket usage\t%2.2f%%\n", - ((float)used / nsp->ns_nattab_sz) * 100.0); - printf("minimal length\t%d\n", minlen); - printf("maximal length\t%d\n", maxlen); - printf("average length\t%.3f\n", used ? (float)totallen / used : 0.0); + printf("%d%%\thash efficiency %s\n", + totallen ? used * 100 / totallen : 0, side); + printf("%2.2f%%\tbucket usage %s\n", + ((float)used / nsp->ns_nattab_sz) * 100.0, side); + printf("%d\tminimal length %s\n", minlen, side); + printf("%d\tmaximal length %s\n", maxlen, side); + printf("%.3f\taverage length %s\n", + used ? ((float)totallen / used) : 0.0, side); + + free(buckets); +} + + +void dostats(fd, nsp, opts, alive, filter) + natstat_t *nsp; + int fd, opts, alive, *filter; +{ + /* + * Show statistics ? + */ + if (opts & OPT_STAT) { + printnatside("in", &nsp->ns_side[0]); + dotable(nsp, fd, alive, 0, "in"); + + printnatside("out", &nsp->ns_side[1]); + dotable(nsp, fd, alive, 1, "out"); + + printf("%lu\tlog successes\n", nsp->ns_side[0].ns_log); + printf("%lu\tlog failures\n", nsp->ns_side[1].ns_log); + printf("%lu\tadded in\n%lu\tadded out\n", + nsp->ns_side[0].ns_added, + nsp->ns_side[1].ns_added); + printf("%u\tactive\n", nsp->ns_active); + printf("%lu\ttransparent adds\n", nsp->ns_addtrpnt); + printf("%lu\tdivert build\n", nsp->ns_divert_build); + printf("%lu\texpired\n", nsp->ns_expire); + printf("%lu\tflush all\n", nsp->ns_flush_all); + printf("%lu\tflush closing\n", nsp->ns_flush_closing); + printf("%lu\tflush queue\n", nsp->ns_flush_queue); + printf("%lu\tflush state\n", nsp->ns_flush_state); + printf("%lu\tflush timeout\n", nsp->ns_flush_timeout); + printf("%lu\thostmap new\n", nsp->ns_hm_new); + printf("%lu\thostmap fails\n", nsp->ns_hm_newfail); + printf("%lu\thostmap add\n", nsp->ns_hm_addref); + printf("%lu\thostmap NULL rule\n", nsp->ns_hm_nullnp); + printf("%lu\tlog ok\n", nsp->ns_log_ok); + printf("%lu\tlog fail\n", nsp->ns_log_fail); + printf("%u\torphan count\n", nsp->ns_orphans); + printf("%u\trule count\n", nsp->ns_rules); + printf("%u\tmap rules\n", nsp->ns_rules_map); + printf("%u\trdr rules\n", nsp->ns_rules_rdr); + printf("%u\twilds\n", nsp->ns_wilds); + if (opts & OPT_VERBOSE) + printf("list %p\n", nsp->ns_list); + } + + if (opts & OPT_LIST) { + if (alive) + dostats_live(fd, nsp, opts, filter); + else + dostats_dead(nsp, opts, filter); + } } /* * Display NAT statistics. */ -void dostats_live(fd, nsp, opts) -natstat_t *nsp; -int fd, opts; +void dostats_live(fd, nsp, opts, filter) + natstat_t *nsp; + int fd, opts, *filter; { ipfgeniter_t iter; + char buffer[2000]; ipfobj_t obj; - ipnat_t ipn; + ipnat_t *ipn; nat_t nat; + int i; bzero((char *)&obj, sizeof(obj)); obj.ipfo_rev = IPFILTER_VERSION; @@ -455,22 +554,39 @@ int fd, opts; iter.igi_type = IPFGENITER_IPNAT; iter.igi_nitems = 1; - iter.igi_data = &ipn; + iter.igi_data = buffer; + ipn = (ipnat_t *)buffer; /* * Show list of NAT rules and NAT sessions ? */ - printf("List of active MAP/Redirect filters:\n"); - while (nsp->ns_list) { - if (ioctl(fd, SIOCGENITER, &obj) == -1) - break; - if (opts & OPT_HITS) - printf("%lu ", ipn.in_hits); - printnat(&ipn, opts & (OPT_DEBUG|OPT_VERBOSE)); - nsp->ns_list = ipn.in_next; + if (nat_fields == NULL) { + printf("List of active MAP/Redirect filters:\n"); + while (nsp->ns_list) { + if (ioctl(fd, SIOCGENITER, &obj) == -1) + break; + if (opts & OPT_HITS) + printf("%lu ", ipn->in_hits); + printnat(ipn, opts & (OPT_DEBUG|OPT_VERBOSE)); + nsp->ns_list = ipn->in_next; + } } - printf("\nList of active sessions:\n"); + if (nat_fields == NULL) { + printf("\nList of active sessions:\n"); + + } else if (nohdrfields == 0) { + for (i = 0; nat_fields[i].w_value != 0; i++) { + printfieldhdr(natfields, nat_fields + i); + if (nat_fields[i + 1].w_value != 0) + printf("\t"); + } + printf("\n"); + } + + i = IPFGENITER_IPNAT; + (void) ioctl(fd,SIOCIPFDELTOK, &i); + iter.igi_type = IPFGENITER_NAT; iter.igi_nitems = 1; @@ -479,14 +595,35 @@ int fd, opts; while (nsp->ns_instances != NULL) { if (ioctl(fd, SIOCGENITER, &obj) == -1) break; - printactivenat(&nat, opts, 1, nsp->ns_ticks); - if (nat.nat_aps) - printaps(nat.nat_aps, opts); + if ((filter != NULL) && (nat_matcharray(&nat, filter) == 0)) + continue; + if (nat_fields != NULL) { + for (i = 0; nat_fields[i].w_value != 0; i++) { + printnatfield(&nat, nat_fields[i].w_value); + if (nat_fields[i + 1].w_value != 0) + printf("\t"); + } + printf("\n"); + } else { + printactivenat(&nat, opts, nsp->ns_ticks); + if (nat.nat_aps) { + int proto; + + if (nat.nat_dir & NAT_OUTBOUND) + proto = nat.nat_pr[1]; + else + proto = nat.nat_pr[0]; + printaps(nat.nat_aps, opts, proto); + } + } nsp->ns_instances = nat.nat_next; } if (opts & OPT_VERBOSE) showhostmap_live(fd, nsp); + + i = IPFGENITER_NAT; + (void) ioctl(fd,SIOCIPFDELTOK, &i); } @@ -494,7 +631,7 @@ int fd, opts; * Display the active host mapping table. */ void showhostmap_dead(nsp) -natstat_t *nsp; + natstat_t *nsp; { hostmap_t hm, *hmp, **maptable; u_int hv; @@ -530,12 +667,13 @@ natstat_t *nsp; * Display the active host mapping table. */ void showhostmap_live(fd, nsp) -int fd; -natstat_t *nsp; + int fd; + natstat_t *nsp; { ipfgeniter_t iter; hostmap_t hm; ipfobj_t obj; + int i; bzero((char *)&obj, sizeof(obj)); obj.ipfo_rev = IPFILTER_VERSION; @@ -552,25 +690,167 @@ natstat_t *nsp; while (nsp->ns_maplist != NULL) { if (ioctl(fd, SIOCGENITER, &obj) == -1) break; - printhostmap(&hm, 0); + printhostmap(&hm, hm.hm_hv); nsp->ns_maplist = hm.hm_next; } + + i = IPFGENITER_HOSTMAP; + (void) ioctl(fd,SIOCIPFDELTOK, &i); } -void showtqtable_live(fd) -int fd; +int nat_matcharray(nat, array) + nat_t *nat; + int *array; { - ipftq_t table[IPF_TCP_NSTATES]; - ipfobj_t obj; + int i, n, *x, rv, p; + ipfexp_t *e; - bzero((char *)&obj, sizeof(obj)); - obj.ipfo_rev = IPFILTER_VERSION; - obj.ipfo_size = sizeof(table); - obj.ipfo_ptr = (void *)table; - obj.ipfo_type = IPFOBJ_STATETQTAB; + rv = 0; + n = array[0]; + x = array + 1; + + for (; n > 0; x += 3 + x[3], rv = 0) { + e = (ipfexp_t *)x; + if (e->ipfe_cmd == IPF_EXP_END) + break; + n -= e->ipfe_size; + + p = e->ipfe_cmd >> 16; + if ((p != 0) && (p != nat->nat_pr[1])) + break; + + switch (e->ipfe_cmd) + { + case IPF_EXP_IP_PR : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (nat->nat_pr[1] == e->ipfe_arg0[i]); + } + break; - if (ioctl(fd, SIOCGTQTAB, &obj) == 0) { - printtqtable(table); + case IPF_EXP_IP_SRCADDR : + if (nat->nat_v[0] != 4) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= ((nat->nat_osrcaddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]) || + ((nat->nat_nsrcaddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]); + } + break; + + case IPF_EXP_IP_DSTADDR : + if (nat->nat_v[0] != 4) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= ((nat->nat_odstaddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]) || + ((nat->nat_ndstaddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]); + } + break; + + case IPF_EXP_IP_ADDR : + if (nat->nat_v[0] != 4) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= ((nat->nat_osrcaddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]) || + ((nat->nat_nsrcaddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]) || + ((nat->nat_odstaddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]) || + ((nat->nat_ndstaddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]); + } + break; + +#ifdef USE_INET6 + case IPF_EXP_IP6_SRCADDR : + if (nat->nat_v[0] != 6) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= IP6_MASKEQ(&nat->nat_osrc6, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]) || + IP6_MASKEQ(&nat->nat_nsrc6, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]); + } + break; + + case IPF_EXP_IP6_DSTADDR : + if (nat->nat_v[0] != 6) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= IP6_MASKEQ(&nat->nat_odst6, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]) || + IP6_MASKEQ(&nat->nat_ndst6, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]); + } + break; + + case IPF_EXP_IP6_ADDR : + if (nat->nat_v[0] != 6) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= IP6_MASKEQ(&nat->nat_osrc6, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]) || + IP6_MASKEQ(&nat->nat_nsrc6, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]) || + IP6_MASKEQ(&nat->nat_odst6, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]) || + IP6_MASKEQ(&nat->nat_ndst6, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]); + } + break; +#endif + + case IPF_EXP_UDP_PORT : + case IPF_EXP_TCP_PORT : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (nat->nat_osport == e->ipfe_arg0[i]) || + (nat->nat_nsport == e->ipfe_arg0[i]) || + (nat->nat_odport == e->ipfe_arg0[i]) || + (nat->nat_ndport == e->ipfe_arg0[i]); + } + break; + + case IPF_EXP_UDP_SPORT : + case IPF_EXP_TCP_SPORT : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (nat->nat_osport == e->ipfe_arg0[i]) || + (nat->nat_nsport == e->ipfe_arg0[i]); + } + break; + + case IPF_EXP_UDP_DPORT : + case IPF_EXP_TCP_DPORT : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (nat->nat_odport == e->ipfe_arg0[i]) || + (nat->nat_ndport == e->ipfe_arg0[i]); + } + break; + } + rv ^= e->ipfe_not; + + if (rv == 0) + break; } + + return rv; } diff --git a/tools/ipnat_y.y b/tools/ipnat_y.y index 6208c989774b8..6042a0871c5df 100644 --- a/tools/ipnat_y.y +++ b/tools/ipnat_y.y @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -58,33 +58,58 @@ static int natfd = -1; static ioctlfunc_t natioctlfunc = NULL; static addfunc_t nataddfunc = NULL; static int suggest_port = 0; +static proxyrule_t *prules = NULL; +static int parser_error = 0; static void newnatrule __P((void)); static void setnatproto __P((int)); - +static void setmapifnames __P((void)); +static void setrdrifnames __P((void)); +static void proxy_setconfig __P((int)); +static void proxy_unsetconfig __P((void)); +static namelist_t *proxy_dns_add_pass __P((char *, char *)); +static namelist_t *proxy_dns_add_block __P((char *, char *)); +static void proxy_addconfig __P((char *, int, char *, namelist_t *)); +static void proxy_loadconfig __P((int, ioctlfunc_t, char *, int, + char *, namelist_t *)); +static void proxy_loadrules __P((int, ioctlfunc_t, proxyrule_t *)); +static void setmapifnames __P((void)); +static void setrdrifnames __P((void)); +static void setifname __P((ipnat_t **, int, char *)); +static int addname __P((ipnat_t **, char *)); %} %union { char *str; u_32_t num; - struct in_addr ipa; + struct { + i6addr_t a; + int f; + } ipa; frentry_t fr; frtuc_t *frt; u_short port; struct { - u_short p1; - u_short p2; + int p1; + int p2; int pc; } pc; struct { - struct in_addr a; - struct in_addr m; + i6addr_t a; + i6addr_t m; + int t; /* Address type */ + int u; + int f; /* Family */ + int v; /* IP version */ + int s; /* 0 = number, 1 = text */ + int n; /* number */ } ipp; union i6addr ip6; + namelist_t *names; }; %token <num> YY_NUMBER YY_HEX %token <str> YY_STR -%token YY_COMMENT +%token YY_COMMENT %token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT %token YY_RANGE_OUT YY_RANGE_IN %token <ip6> YY_IPV6 @@ -93,23 +118,42 @@ static void setnatproto __P((int)); %token IPNY_MAP IPNY_BIMAP IPNY_FROM IPNY_TO IPNY_MASK IPNY_PORTMAP IPNY_ANY %token IPNY_ROUNDROBIN IPNY_FRAG IPNY_AGE IPNY_ICMPIDMAP IPNY_PROXY %token IPNY_TCP IPNY_UDP IPNY_TCPUDP IPNY_STICKY IPNY_MSSCLAMP IPNY_TAG -%token IPNY_TLATE +%token IPNY_TLATE IPNY_POOL IPNY_HASH IPNY_NO IPNY_REWRITE IPNY_PROTO +%token IPNY_ON IPNY_SRC IPNY_DST IPNY_IN IPNY_OUT IPNY_DIVERT +%token IPNY_CONFIG IPNY_ALLOW IPNY_DENY IPNY_DNS IPNY_INET IPNY_INET6 +%token IPNY_SEQUENTIAL IPNY_DSTLIST IPNY_PURGE %type <port> portspec %type <num> hexnumber compare range proto -%type <ipa> hostname ipv4 -%type <ipp> addr nummask rhaddr -%type <pc> portstuff +%type <num> saddr daddr sobject dobject mapfrom rdrfrom dip +%type <ipa> hostname ipv4 ipaddr +%type <ipp> addr rhsaddr rhdaddr erhdaddr +%type <pc> portstuff portpair comaports srcports dstports +%type <names> dnslines dnsline %% file: line | assign | file line | file assign + | file pconf ';' ; -line: xx rule { while ((nat = nattop) != NULL) { +line: xx rule { int err; + while ((nat = nattop) != NULL) { + if (nat->in_v[0] == 0) + nat->in_v[0] = 4; + if (nat->in_v[1] == 0) + nat->in_v[1] = nat->in_v[0]; nattop = nat->in_next; - (*nataddfunc)(natfd, natioctlfunc, nat); + err = (*nataddfunc)(natfd, natioctlfunc, nat); free(nat); + if (err != 0) { + parser_error = err; + break; + } + } + if (parser_error == 0 && prules != NULL) { + proxy_loadrules(natfd, natioctlfunc, prules); + prules = NULL; } resetlexer(); } @@ -134,206 +178,541 @@ xx: { newnatrule(); } rule: map eol | mapblock eol | redir eol + | rewrite ';' + | divert ';' + ; + +no: IPNY_NO { nat->in_flags |= IPN_NO; } ; eol: | ';' ; -map: mapit ifnames addr IPNY_TLATE rhaddr proxy mapoptions - { nat->in_v = 4; - nat->in_inip = $3.a.s_addr; - nat->in_inmsk = $3.m.s_addr; - nat->in_outip = $5.a.s_addr; - nat->in_outmsk = $5.m.s_addr; - if (nat->in_ifnames[1][0] == '\0') - strncpy(nat->in_ifnames[1], - nat->in_ifnames[0], - sizeof(nat->in_ifnames[0])); - if ((nat->in_flags & IPN_TCPUDP) == 0) - setnatproto(nat->in_p); - if (((nat->in_redir & NAT_MAPBLK) != 0) || - ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) - nat_setgroupmap(nat); +map: mapit ifnames addr tlate rhsaddr proxy mapoptions + { if ($3.f != 0 && $3.f != $5.f && $5.f != 0) + yyerror("3.address family mismatch"); + if (nat->in_v[0] == 0 && $5.v != 0) + nat->in_v[0] = $5.v; + else if (nat->in_v[0] == 0 && $3.v != 0) + nat->in_v[0] = $3.v; + if (nat->in_v[1] == 0 && $5.v != 0) + nat->in_v[1] = $5.v; + else if (nat->in_v[1] == 0 && $3.v != 0) + nat->in_v[1] = $3.v; + nat->in_osrcatype = $3.t; + bcopy(&$3.a, &nat->in_osrc.na_addr[0], + sizeof($3.a)); + bcopy(&$3.m, &nat->in_osrc.na_addr[1], + sizeof($3.a)); + nat->in_nsrcatype = $5.t; + nat->in_nsrcafunc = $5.u; + bcopy(&$5.a, &nat->in_nsrc.na_addr[0], + sizeof($5.a)); + bcopy(&$5.m, &nat->in_nsrc.na_addr[1], + sizeof($5.a)); + + setmapifnames(); + } + | mapit ifnames addr tlate rhsaddr mapport mapoptions + { if ($3.f != $5.f && $3.f != 0 && $5.f != 0) + yyerror("4.address family mismatch"); + if (nat->in_v[1] == 0 && $5.v != 0) + nat->in_v[1] = $5.v; + else if (nat->in_v[0] == 0 && $3.v != 0) + nat->in_v[0] = $3.v; + if (nat->in_v[0] == 0 && $5.v != 0) + nat->in_v[0] = $5.v; + else if (nat->in_v[1] == 0 && $3.v != 0) + nat->in_v[1] = $3.v; + nat->in_osrcatype = $3.t; + bcopy(&$3.a, &nat->in_osrc.na_addr[0], + sizeof($3.a)); + bcopy(&$3.m, &nat->in_osrc.na_addr[1], + sizeof($3.a)); + nat->in_nsrcatype = $5.t; + nat->in_nsrcafunc = $5.u; + bcopy(&$5.a, &nat->in_nsrc.na_addr[0], + sizeof($5.a)); + bcopy(&$5.m, &nat->in_nsrc.na_addr[1], + sizeof($5.a)); + + setmapifnames(); } - | mapit ifnames addr IPNY_TLATE rhaddr mapport mapoptions - { nat->in_v = 4; - nat->in_inip = $3.a.s_addr; - nat->in_inmsk = $3.m.s_addr; - nat->in_outip = $5.a.s_addr; - nat->in_outmsk = $5.m.s_addr; - if (nat->in_ifnames[1][0] == '\0') - strncpy(nat->in_ifnames[1], - nat->in_ifnames[0], - sizeof(nat->in_ifnames[0])); - if (((nat->in_redir & NAT_MAPBLK) != 0) || - ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) - nat_setgroupmap(nat); + | no mapit ifnames addr setproto ';' + { if (nat->in_v[0] == 0) + nat->in_v[0] = $4.v; + nat->in_osrcatype = $4.t; + bcopy(&$4.a, &nat->in_osrc.na_addr[0], + sizeof($4.a)); + bcopy(&$4.m, &nat->in_osrc.na_addr[1], + sizeof($4.a)); + + setmapifnames(); } - | mapit ifnames mapfrom IPNY_TLATE rhaddr proxy mapoptions - { nat->in_v = 4; - nat->in_outip = $5.a.s_addr; - nat->in_outmsk = $5.m.s_addr; - if (nat->in_ifnames[1][0] == '\0') - strncpy(nat->in_ifnames[1], - nat->in_ifnames[0], - sizeof(nat->in_ifnames[0])); - if ((suggest_port == 1) && - (nat->in_flags & IPN_TCPUDP) == 0) - nat->in_flags |= IPN_TCPUDP; - if ((nat->in_flags & IPN_TCPUDP) == 0) - setnatproto(nat->in_p); - if (((nat->in_redir & NAT_MAPBLK) != 0) || - ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) - nat_setgroupmap(nat); + | mapit ifnames mapfrom tlate rhsaddr proxy mapoptions + { if ($3 != 0 && $5.f != 0 && $3 != $5.f) + yyerror("5.address family mismatch"); + if (nat->in_v[0] == 0 && $5.v != 0) + nat->in_v[0] = $5.v; + else if (nat->in_v[0] == 0 && $3 != 0) + nat->in_v[0] = ftov($3); + if (nat->in_v[1] == 0 && $5.v != 0) + nat->in_v[1] = $5.v; + else if (nat->in_v[1] == 0 && $3 != 0) + nat->in_v[1] = ftov($3); + nat->in_nsrcatype = $5.t; + nat->in_nsrcafunc = $5.u; + bcopy(&$5.a, &nat->in_nsrc.na_addr[0], + sizeof($5.a)); + bcopy(&$5.m, &nat->in_nsrc.na_addr[1], + sizeof($5.a)); + + setmapifnames(); } - | mapit ifnames mapfrom IPNY_TLATE rhaddr mapport mapoptions - { nat->in_v = 4; - nat->in_outip = $5.a.s_addr; - nat->in_outmsk = $5.m.s_addr; - if (nat->in_ifnames[1][0] == '\0') - strncpy(nat->in_ifnames[1], - nat->in_ifnames[0], - sizeof(nat->in_ifnames[0])); - if ((suggest_port == 1) && - (nat->in_flags & IPN_TCPUDP) == 0) - nat->in_flags |= IPN_TCPUDP; - if (((nat->in_redir & NAT_MAPBLK) != 0) || - ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) - nat_setgroupmap(nat); + | no mapit ifnames mapfrom setproto ';' + { nat->in_v[0] = ftov($4); + setmapifnames(); + } + | mapit ifnames mapfrom tlate rhsaddr mapport mapoptions + { if ($3 != 0 && $5.f != 0 && $3 != $5.f) + yyerror("6.address family mismatch"); + if (nat->in_v[0] == 0 && $5.v != 0) + nat->in_v[0] = $5.v; + else if (nat->in_v[0] == 0 && $3 != 0) + nat->in_v[0] = ftov($3); + if (nat->in_v[1] == 0 && $5.v != 0) + nat->in_v[1] = $5.v; + else if (nat->in_v[1] == 0 && $3 != 0) + nat->in_v[1] = ftov($3); + nat->in_nsrcatype = $5.t; + nat->in_nsrcafunc = $5.u; + bcopy(&$5.a, &nat->in_nsrc.na_addr[0], + sizeof($5.a)); + bcopy(&$5.m, &nat->in_nsrc.na_addr[1], + sizeof($5.a)); + + setmapifnames(); } ; mapblock: - mapblockit ifnames addr IPNY_TLATE addr ports mapoptions - { nat->in_v = 4; - nat->in_inip = $3.a.s_addr; - nat->in_inmsk = $3.m.s_addr; - nat->in_outip = $5.a.s_addr; - nat->in_outmsk = $5.m.s_addr; - if (nat->in_ifnames[1][0] == '\0') - strncpy(nat->in_ifnames[1], - nat->in_ifnames[0], - sizeof(nat->in_ifnames[0])); - if ((nat->in_flags & IPN_TCPUDP) == 0) - setnatproto(nat->in_p); - if (((nat->in_redir & NAT_MAPBLK) != 0) || - ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) - nat_setgroupmap(nat); + mapblockit ifnames addr tlate addr ports mapoptions + { if ($3.f != 0 && $5.f != 0 && $3.f != $5.f) + yyerror("7.address family mismatch"); + if (nat->in_v[0] == 0 && $5.v != 0) + nat->in_v[0] = $5.v; + else if (nat->in_v[0] == 0 && $3.v != 0) + nat->in_v[0] = $3.v; + if (nat->in_v[1] == 0 && $5.v != 0) + nat->in_v[1] = $5.v; + else if (nat->in_v[1] == 0 && $3.v != 0) + nat->in_v[1] = $3.v; + nat->in_osrcatype = $3.t; + bcopy(&$3.a, &nat->in_osrc.na_addr[0], + sizeof($3.a)); + bcopy(&$3.m, &nat->in_osrc.na_addr[1], + sizeof($3.a)); + nat->in_nsrcatype = $5.t; + nat->in_nsrcafunc = $5.u; + bcopy(&$5.a, &nat->in_nsrc.na_addr[0], + sizeof($5.a)); + bcopy(&$5.m, &nat->in_nsrc.na_addr[1], + sizeof($5.a)); + + setmapifnames(); + } + | no mapblockit ifnames { yyexpectaddr = 1; } addr setproto ';' + { if (nat->in_v[0] == 0) + nat->in_v[0] = $5.v; + if (nat->in_v[1] == 0) + nat->in_v[1] = $5.v; + nat->in_osrcatype = $5.t; + bcopy(&$5.a, &nat->in_osrc.na_addr[0], + sizeof($5.a)); + bcopy(&$5.m, &nat->in_osrc.na_addr[1], + sizeof($5.a)); + + setmapifnames(); } ; -redir: rdrit ifnames addr dport IPNY_TLATE dip nport setproto rdroptions - { nat->in_v = 4; - nat->in_outip = $3.a.s_addr; - nat->in_outmsk = $3.m.s_addr; - if (nat->in_ifnames[1][0] == '\0') - strncpy(nat->in_ifnames[1], - nat->in_ifnames[0], - sizeof(nat->in_ifnames[0])); - if ((nat->in_p == 0) && - ((nat->in_flags & IPN_TCPUDP) == 0) && - (nat->in_pmin != 0 || - nat->in_pmax != 0 || - nat->in_pnext != 0)) - setnatproto(IPPROTO_TCP); +redir: rdrit ifnames addr dport tlate dip nport setproto rdroptions + { if ($6 != 0 && $3.f != 0 && $6 != $3.f) + yyerror("21.address family mismatch"); + if (nat->in_v[0] == 0) { + if ($3.v != AF_UNSPEC) + nat->in_v[0] = ftov($3.f); + else + nat->in_v[0] = ftov($6); + } + nat->in_odstatype = $3.t; + bcopy(&$3.a, &nat->in_odst.na_addr[0], + sizeof($3.a)); + bcopy(&$3.m, &nat->in_odst.na_addr[1], + sizeof($3.a)); + + setrdrifnames(); + } + | no rdrit ifnames addr dport setproto ';' + { if (nat->in_v[0] == 0) + nat->in_v[0] = ftov($4.f); + nat->in_odstatype = $4.t; + bcopy(&$4.a, &nat->in_odst.na_addr[0], + sizeof($4.a)); + bcopy(&$4.m, &nat->in_odst.na_addr[1], + sizeof($4.a)); + + setrdrifnames(); + } + | rdrit ifnames rdrfrom tlate dip nport setproto rdroptions + { if ($5 != 0 && $3 != 0 && $5 != $3) + yyerror("20.address family mismatch"); + if (nat->in_v[0] == 0) { + if ($3 != AF_UNSPEC) + nat->in_v[0] = ftov($3); + else + nat->in_v[0] = ftov($5); + } + setrdrifnames(); } - | rdrit ifnames rdrfrom IPNY_TLATE dip nport setproto rdroptions - { nat->in_v = 4; - if ((nat->in_p == 0) && - ((nat->in_flags & IPN_TCPUDP) == 0) && - (nat->in_pmin != 0 || - nat->in_pmax != 0 || - nat->in_pnext != 0)) - setnatproto(IPPROTO_TCP); - if ((suggest_port == 1) && - (nat->in_flags & IPN_TCPUDP) == 0) - nat->in_flags |= IPN_TCPUDP; - if (nat->in_ifnames[1][0] == '\0') - strncpy(nat->in_ifnames[1], - nat->in_ifnames[0], - sizeof(nat->in_ifnames[0])); + | no rdrit ifnames rdrfrom setproto ';' + { nat->in_v[0] = ftov($4); + + setrdrifnames(); + } + ; + +rewrite: + IPNY_REWRITE oninout rwrproto mapfrom tlate newdst newopts + { if (nat->in_v[0] == 0) + nat->in_v[0] = ftov($4); + if (nat->in_redir & NAT_MAP) + setmapifnames(); + else + setrdrifnames(); + nat->in_redir |= NAT_REWRITE; } - | rdrit ifnames addr IPNY_TLATE dip setproto rdroptions - { nat->in_v = 4; - nat->in_outip = $3.a.s_addr; - nat->in_outmsk = $3.m.s_addr; - if (nat->in_ifnames[1][0] == '\0') - strncpy(nat->in_ifnames[1], - nat->in_ifnames[0], - sizeof(nat->in_ifnames[0])); + ; + +divert: IPNY_DIVERT oninout rwrproto mapfrom tlate divdst newopts + { if (nat->in_v[0] == 0) + nat->in_v[0] = ftov($4); + if (nat->in_redir & NAT_MAP) { + setmapifnames(); + nat->in_pr[0] = IPPROTO_UDP; + } else { + setrdrifnames(); + nat->in_pr[1] = IPPROTO_UDP; + } + nat->in_flags &= ~IPN_TCP; } - | rdrit ifnames rdrfrom IPNY_TLATE dip setproto rdroptions - { nat->in_v = 4; - if ((suggest_port == 1) && - (nat->in_flags & IPN_TCPUDP) == 0) - nat->in_flags |= IPN_TCPUDP; - if (nat->in_ifnames[1][0] == '\0') - strncpy(nat->in_ifnames[1], - nat->in_ifnames[0], - sizeof(nat->in_ifnames[0])); + ; + +tlate: IPNY_TLATE { yyexpectaddr = 1; } + ; + +pconf: IPNY_PROXY { yysetdict(proxies); } + IPNY_DNS '/' proto IPNY_CONFIG YY_STR '{' + { proxy_setconfig(IPNY_DNS); } + dnslines ';' '}' + { proxy_addconfig("dns", $5, $7, $10); + proxy_unsetconfig(); + } + ; + +dnslines: + dnsline { $$ = $1; } + | dnslines ';' dnsline { $$ = $1; $1->na_next = $3; } + ; + +dnsline: + IPNY_ALLOW YY_STR { $$ = proxy_dns_add_pass(NULL, $2); } + | IPNY_DENY YY_STR { $$ = proxy_dns_add_block(NULL, $2); } + | IPNY_ALLOW '.' YY_STR { $$ = proxy_dns_add_pass(".", $3); } + | IPNY_DENY '.' YY_STR { $$ = proxy_dns_add_block(".", $3); } + ; + +oninout: + inout IPNY_ON ifnames { ; } + ; + +inout: IPNY_IN { nat->in_redir = NAT_REDIRECT; } + | IPNY_OUT { nat->in_redir = NAT_MAP; } + ; + +rwrproto: + | IPNY_PROTO setproto + ; + +newdst: src rhsaddr srcports dst erhdaddr dstports + { nat->in_nsrc.na_addr[0] = $2.a; + nat->in_nsrc.na_addr[1] = $2.m; + nat->in_nsrc.na_atype = $2.t; + if ($2.t == FRI_LOOKUP) { + nat->in_nsrc.na_type = $2.u; + nat->in_nsrc.na_subtype = $2.s; + nat->in_nsrc.na_num = $2.n; + } + nat->in_nsports[0] = $3.p1; + nat->in_nsports[1] = $3.p2; + nat->in_ndst.na_addr[0] = $5.a; + nat->in_ndst.na_addr[1] = $5.m; + nat->in_ndst.na_atype = $5.t; + if ($5.t == FRI_LOOKUP) { + nat->in_ndst.na_type = $5.u; + nat->in_ndst.na_subtype = $5.s; + nat->in_ndst.na_num = $5.n; + } + nat->in_ndports[0] = $6.p1; + nat->in_ndports[1] = $6.p2; + } + ; + +divdst: src addr ',' portspec dst addr ',' portspec IPNY_UDP + { nat->in_nsrc.na_addr[0] = $2.a; + if ($2.m.in4.s_addr != 0xffffffff) + yyerror("divert must have /32 dest"); + nat->in_nsrc.na_addr[1] = $2.m; + nat->in_nsports[0] = $4; + nat->in_nsports[1] = $4; + + nat->in_ndst.na_addr[0] = $6.a; + nat->in_ndst.na_addr[1] = $6.m; + if ($6.m.in4.s_addr != 0xffffffff) + yyerror("divert must have /32 dest"); + nat->in_ndports[0] = $8; + nat->in_ndports[1] = $8; + + nat->in_redir |= NAT_DIVERTUDP; + } + ; + +src: IPNY_SRC { yyexpectaddr = 1; } + ; + +dst: IPNY_DST { yyexpectaddr = 1; } + ; + +srcports: + comaports { $$.p1 = $1.p1; + $$.p2 = $1.p2; + } + | IPNY_PORT '=' portspec + { $$.p1 = $3; + $$.p2 = $3; + nat->in_flags |= IPN_FIXEDSPORT; + } + ; + +dstports: + comaports { $$.p1 = $1.p1; + $$.p2 = $1.p2; + } + | IPNY_PORT '=' portspec + { $$.p1 = $3; + $$.p2 = $3; + nat->in_flags |= IPN_FIXEDDPORT; + } + ; + +comaports: + { $$.p1 = 0; + $$.p2 = 0; + } + | ',' { if (!(nat->in_flags & IPN_TCPUDP)) + yyerror("must be TCP/UDP for ports"); + } + portpair { $$.p1 = $3.p1; + $$.p2 = $3.p2; } ; proxy: | IPNY_PROXY port portspec YY_STR '/' proto - { strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel)); + { int pos; + pos = addname(&nat, $4); + nat->in_plabel = pos; if (nat->in_dcmp == 0) { - nat->in_dport = htons($3); - } else if ($3 != nat->in_dport) { + nat->in_odport = $3; + } else if ($3 != nat->in_odport) { yyerror("proxy port numbers not consistant"); } + nat->in_ndport = $3; setnatproto($6); free($4); } | IPNY_PROXY port YY_STR YY_STR '/' proto - { int pnum; - strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel)); + { int pnum, pos; + pos = addname(&nat, $4); + nat->in_plabel = pos; + pnum = getportproto($3, $6); + if (pnum == -1) + yyerror("invalid port number"); + nat->in_odport = ntohs(pnum); + nat->in_ndport = ntohs(pnum); + setnatproto($6); + free($3); + free($4); + } + | IPNY_PROXY port portspec YY_STR '/' proto IPNY_CONFIG YY_STR + { int pos; + pos = addname(&nat, $4); + nat->in_plabel = pos; + if (nat->in_dcmp == 0) { + nat->in_odport = $3; + } else if ($3 != nat->in_odport) { + yyerror("proxy port numbers not consistant"); + } + nat->in_ndport = $3; + setnatproto($6); + nat->in_pconfig = addname(&nat, $8); + free($4); + free($8); + } + | IPNY_PROXY port YY_STR YY_STR '/' proto IPNY_CONFIG YY_STR + { int pnum, pos; + pos = addname(&nat, $4); + nat->in_plabel = pos; pnum = getportproto($3, $6); if (pnum == -1) yyerror("invalid port number"); - nat->in_dport = pnum; + nat->in_odport = ntohs(pnum); + nat->in_ndport = ntohs(pnum); setnatproto($6); + pos = addname(&nat, $8); + nat->in_pconfig = pos; free($3); free($4); + free($8); } ; - setproto: - | proto { if (nat->in_p != 0 || + | proto { if (nat->in_pr[0] != 0 || + nat->in_pr[1] != 0 || nat->in_flags & IPN_TCPUDP) yyerror("protocol set twice"); setnatproto($1); } - | IPNY_TCPUDP { if (nat->in_p != 0 || + | IPNY_TCPUDP { if (nat->in_pr[0] != 0 || + nat->in_pr[1] != 0 || nat->in_flags & IPN_TCPUDP) yyerror("protocol set twice"); nat->in_flags |= IPN_TCPUDP; - nat->in_p = 0; + nat->in_pr[0] = 0; + nat->in_pr[1] = 0; } - | IPNY_TCP '/' IPNY_UDP { if (nat->in_p != 0 || + | IPNY_TCP '/' IPNY_UDP { if (nat->in_pr[0] != 0 || + nat->in_pr[1] != 0 || nat->in_flags & IPN_TCPUDP) yyerror("protocol set twice"); nat->in_flags |= IPN_TCPUDP; - nat->in_p = 0; + nat->in_pr[0] = 0; + nat->in_pr[1] = 0; } ; -rhaddr: addr { $$.a = $1.a; $$.m = $1.m; } - | IPNY_RANGE ipv4 '-' ipv4 - { $$.a = $2; $$.m = $4; - nat->in_flags |= IPN_IPRANGE; } +rhsaddr: + addr { $$ = $1; + yyexpectaddr = 0; + } + | hostname '-' { yyexpectaddr = 1; } hostname + { $$.t = FRI_RANGE; + if ($1.f != $4.f) + yyerror("8.address family " + "mismatch"); + $$.f = $1.f; + $$.v = ftov($1.f); + $$.a = $1.a; + $$.m = $4.a; + nat->in_flags |= IPN_SIPRANGE; + yyexpectaddr = 0; + } + | IPNY_RANGE hostname '-' { yyexpectaddr = 1; } hostname + { $$.t = FRI_RANGE; + if ($2.f != $5.f) + yyerror("9.address family " + "mismatch"); + $$.f = $2.f; + $$.v = ftov($2.f); + $$.a = $2.a; + $$.m = $5.a; + nat->in_flags |= IPN_SIPRANGE; + yyexpectaddr = 0; + } ; dip: - hostname { nat->in_inip = $1.s_addr; - nat->in_inmsk = 0xffffffff; } - | hostname '/' YY_NUMBER { if ($3 != 0 || $1.s_addr != 0) - yyerror("Only 0/0 supported"); - nat->in_inip = 0; - nat->in_inmsk = 0; + hostname ',' { yyexpectaddr = 1; } hostname + { nat->in_flags |= IPN_SPLIT; + if ($1.f != $4.f) + yyerror("10.address family " + "mismatch"); + $$ = $1.f; + nat->in_ndstip6 = $1.a; + nat->in_ndstmsk6 = $4.a; + nat->in_ndstatype = FRI_SPLIT; + yyexpectaddr = 0; + } + | rhdaddr { int bits; + nat->in_ndstip6 = $1.a; + nat->in_ndstmsk6 = $1.m; + nat->in_ndst.na_atype = $1.t; + yyexpectaddr = 0; + if ($1.f == AF_INET) + bits = count4bits($1.m.in4.s_addr); + else + bits = count6bits($1.m.i6); + if (($1.f == AF_INET) && (bits != 0) && + (bits != 32)) { + yyerror("dest ip bitmask not /32"); + } else if (($1.f == AF_INET6) && + (bits != 0) && (bits != 128)) { + yyerror("dest ip bitmask not /128"); + } + $$ = $1.f; + } + ; + +rhdaddr: + addr { $$ = $1; + yyexpectaddr = 0; + } + | hostname '-' hostname { bzero(&$$, sizeof($$)); + $$.t = FRI_RANGE; + if ($1.f != 0 && $3.f != 0 && + $1.f != $3.f) + yyerror("11.address family " + "mismatch"); + $$.a = $1.a; + $$.m = $3.a; + nat->in_flags |= IPN_DIPRANGE; + yyexpectaddr = 0; + } + | IPNY_RANGE hostname '-' hostname + { bzero(&$$, sizeof($$)); + $$.t = FRI_RANGE; + if ($2.f != 0 && $4.f != 0 && + $2.f != $4.f) + yyerror("12.address family " + "mismatch"); + $$.a = $2.a; + $$.m = $4.a; + nat->in_flags |= IPN_DIPRANGE; + yyexpectaddr = 0; + } + ; + +erhdaddr: + rhdaddr { $$ = $1; } + | IPNY_DSTLIST '/' YY_NUMBER { $$.t = FRI_LOOKUP; + $$.u = IPLT_DSTLIST; + $$.s = 0; + $$.n = $3; + } + | IPNY_DSTLIST '/' YY_STR { $$.t = FRI_LOOKUP; + $$.u = IPLT_DSTLIST; + $$.s = 1; + $$.n = addname(&nat, $3); } - | hostname ',' hostname { nat->in_flags |= IPN_SPLIT; - nat->in_inip = $1.s_addr; - nat->in_inmsk = $3.s_addr; } ; port: IPNY_PORT { suggest_port = 1; } @@ -345,27 +724,44 @@ portspec: else $$ = $1; } - | YY_STR { if (getport(NULL, $1, &($$)) == -1) + | YY_STR { if (getport(NULL, $1, + &($$), NULL) == -1) yyerror("invalid port number"); $$ = ntohs($$); } ; -dport: | port portspec { nat->in_pmin = htons($2); - nat->in_pmax = htons($2); } - | port portspec '-' portspec { nat->in_pmin = htons($2); - nat->in_pmax = htons($4); } - | port portspec ':' portspec { nat->in_pmin = htons($2); - nat->in_pmax = htons($4); } +portpair: + portspec { $$.p1 = $1; $$.p2 = $1; } + | portspec '-' portspec { $$.p1 = $1; $$.p2 = $3; } + | portspec ':' portspec { $$.p1 = $1; $$.p2 = $3; } + ; + +dport: | port portpair { nat->in_odport = $2.p1; + if ($2.p2 == 0) + nat->in_dtop = $2.p1; + else + nat->in_dtop = $2.p2; + } ; -nport: port portspec { nat->in_pnext = htons($2); } - | port '=' portspec { nat->in_pnext = htons($3); +nport: | port portpair { nat->in_dpmin = $2.p1; + nat->in_dpnext = $2.p1; + nat->in_dpmax = $2.p2; + nat->in_ndport = $2.p1; + if (nat->in_dtop == 0) + nat->in_dtop = $2.p2; + } + | port '=' portspec { nat->in_dpmin = $3; + nat->in_dpnext = $3; + nat->in_ndport = $3; + if (nat->in_dtop == 0) + nat->in_dtop = nat->in_odport; nat->in_flags |= IPN_FIXEDDPORT; } ; -ports: | IPNY_PORTS YY_NUMBER { nat->in_pmin = $2; } +ports: | IPNY_PORTS YY_NUMBER { nat->in_spmin = $2; } | IPNY_PORTS IPNY_AUTO { nat->in_flags |= IPN_AUTOPORTMAP; } ; @@ -381,124 +777,282 @@ mapblockit: ; mapfrom: - from sobject IPNY_TO dobject - | from sobject '!' IPNY_TO dobject - { nat->in_flags |= IPN_NOTDST; } - | from sobject IPNY_TO '!' dobject - { nat->in_flags |= IPN_NOTDST; } + from sobject to dobject { if ($2 != 0 && $4 != 0 && $2 != $4) + yyerror("13.address family " + "mismatch"); + $$ = $2; + } + | from sobject '!' to dobject + { if ($2 != 0 && $5 != 0 && $2 != $5) + yyerror("14.address family " + "mismatch"); + nat->in_flags |= IPN_NOTDST; + $$ = $2; + } + | from sobject to '!' dobject + { if ($2 != 0 && $5 != 0 && $2 != $5) + yyerror("15.address family " + "mismatch"); + nat->in_flags |= IPN_NOTDST; + $$ = $2; + } ; rdrfrom: - from sobject IPNY_TO dobject - | '!' from sobject IPNY_TO dobject - { nat->in_flags |= IPN_NOTSRC; } - | from '!' sobject IPNY_TO dobject - { nat->in_flags |= IPN_NOTSRC; } + from sobject to dobject { if ($2 != 0 && $4 != 0 && $2 != $4) + yyerror("16.address family " + "mismatch"); + $$ = $2; + } + | '!' from sobject to dobject + { if ($3 != 0 && $5 != 0 && $3 != $5) + yyerror("17.address family " + "mismatch"); + nat->in_flags |= IPN_NOTSRC; + $$ = $3; + } + | from '!' sobject to dobject + { if ($3 != 0 && $5 != 0 && $3 != $5) + yyerror("18.address family " + "mismatch"); + nat->in_flags |= IPN_NOTSRC; + $$ = $3; + } ; -from: IPNY_FROM { nat->in_flags |= IPN_FILTER; } +from: IPNY_FROM { nat->in_flags |= IPN_FILTER; + yyexpectaddr = 1; + } + ; + +to: IPNY_TO { yyexpectaddr = 1; } ; ifnames: - ifname - | ifname ',' otherifname + ifname family { yyexpectaddr = 1; } + | ifname ',' otherifname family { yyexpectaddr = 1; } ; -ifname: YY_STR { strncpy(nat->in_ifnames[0], $1, - sizeof(nat->in_ifnames[0])); - nat->in_ifnames[0][LIFNAMSIZ - 1] = '\0'; - free($1); - } +ifname: YY_STR { setifname(&nat, 0, $1); + free($1); + } + ; + +family: | IPNY_INET { nat->in_v[0] = 4; nat->in_v[1] = 4; } + | IPNY_INET6 { nat->in_v[0] = 6; nat->in_v[1] = 6; } ; otherifname: - YY_STR { strncpy(nat->in_ifnames[1], $1, - sizeof(nat->in_ifnames[1])); - nat->in_ifnames[1][LIFNAMSIZ - 1] = '\0'; - free($1); - } + YY_STR { setifname(&nat, 1, $1); + free($1); + } ; mapport: - IPNY_PORTMAP tcpudp portspec ':' portspec - { nat->in_pmin = htons($3); - nat->in_pmax = htons($5); - } - | IPNY_PORTMAP tcpudp IPNY_AUTO - { nat->in_flags |= IPN_AUTOPORTMAP; - nat->in_pmin = htons(1024); - nat->in_pmax = htons(65535); - } - | IPNY_ICMPIDMAP YY_STR YY_NUMBER ':' YY_NUMBER - { if (strcmp($2, "icmp") != 0) { + IPNY_PORTMAP tcpudp portpair sequential + { nat->in_spmin = $3.p1; + nat->in_spmax = $3.p2; + } + | IPNY_PORTMAP portpair tcpudp sequential + { nat->in_spmin = $2.p1; + nat->in_spmax = $2.p2; + } + | IPNY_PORTMAP tcpudp IPNY_AUTO sequential + { nat->in_flags |= IPN_AUTOPORTMAP; + nat->in_spmin = 1024; + nat->in_spmax = 65535; + } + | IPNY_ICMPIDMAP YY_STR portpair sequential + { if (strcmp($2, "icmp") != 0 && + strcmp($2, "ipv6-icmp") != 0) { yyerror("icmpidmap not followed by icmp"); } free($2); - if ($3 < 0 || $3 > 65535) + if ($3.p1 < 0 || $3.p1 > 65535) yyerror("invalid ICMP Id number"); - if ($5 < 0 || $5 > 65535) + if ($3.p2 < 0 || $3.p2 > 65535) yyerror("invalid ICMP Id number"); + if (strcmp($2, "ipv6-icmp") == 0) { + nat->in_pr[0] = IPPROTO_ICMPV6; + nat->in_pr[1] = IPPROTO_ICMPV6; + } else { + nat->in_pr[0] = IPPROTO_ICMP; + nat->in_pr[1] = IPPROTO_ICMP; + } nat->in_flags = IPN_ICMPQUERY; - nat->in_pmin = htons($3); - nat->in_pmax = htons($5); + nat->in_spmin = $3.p1; + nat->in_spmax = $3.p2; } ; sobject: - saddr - | saddr port portstuff { nat->in_sport = $3.p1; + saddr { $$ = $1; } + | saddr port portstuff { nat->in_osport = $3.p1; nat->in_stop = $3.p2; - nat->in_scmp = $3.pc; } + nat->in_scmp = $3.pc; + $$ = $1; + } ; -saddr: addr { if (nat->in_redir == NAT_REDIRECT) { - nat->in_srcip = $1.a.s_addr; - nat->in_srcmsk = $1.m.s_addr; - } else { - nat->in_inip = $1.a.s_addr; - nat->in_inmsk = $1.m.s_addr; - } +saddr: addr { nat->in_osrcatype = $1.t; + bcopy(&$1.a, + &nat->in_osrc.na_addr[0], + sizeof($1.a)); + bcopy(&$1.m, + &nat->in_osrc.na_addr[1], + sizeof($1.m)); + $$ = $1.f; } ; dobject: - daddr - | daddr port portstuff { nat->in_dport = $3.p1; + daddr { $$ = $1; } + | daddr port portstuff { nat->in_odport = $3.p1; nat->in_dtop = $3.p2; nat->in_dcmp = $3.pc; - if (nat->in_redir == NAT_REDIRECT) - nat->in_pmin = htons($3.p1); + $$ = $1; } ; -daddr: addr { if (nat->in_redir == NAT_REDIRECT) { - nat->in_outip = $1.a.s_addr; - nat->in_outmsk = $1.m.s_addr; - } else { - nat->in_srcip = $1.a.s_addr; - nat->in_srcmsk = $1.m.s_addr; +daddr: addr { nat->in_odstatype = $1.t; + bcopy(&$1.a, + &nat->in_odst.na_addr[0], + sizeof($1.a)); + bcopy(&$1.m, + &nat->in_odst.na_addr[1], + sizeof($1.m)); + $$ = $1.f; + } + ; + +addr: IPNY_ANY { yyexpectaddr = 0; + bzero(&$$, sizeof($$)); + $$.t = FRI_NORMAL; + } + | hostname { bzero(&$$, sizeof($$)); + $$.a = $1.a; + $$.t = FRI_NORMAL; + $$.v = ftov($1.f); + $$.f = $1.f; + if ($$.f == AF_INET) { + $$.m.in4.s_addr = 0xffffffff; + } else if ($$.f == AF_INET6) { + $$.m.i6[0] = 0xffffffff; + $$.m.i6[1] = 0xffffffff; + $$.m.i6[2] = 0xffffffff; + $$.m.i6[3] = 0xffffffff; } + yyexpectaddr = 0; + } + | hostname slash YY_NUMBER + { bzero(&$$, sizeof($$)); + $$.a = $1.a; + $$.f = $1.f; + $$.v = ftov($1.f); + $$.t = FRI_NORMAL; + ntomask($$.f, $3, (u_32_t *)&$$.m); + $$.a.i6[0] &= $$.m.i6[0]; + $$.a.i6[1] &= $$.m.i6[1]; + $$.a.i6[2] &= $$.m.i6[2]; + $$.a.i6[3] &= $$.m.i6[3]; + yyexpectaddr = 0; + } + | hostname slash ipaddr { bzero(&$$, sizeof($$)); + if ($1.f != $3.f) { + yyerror("1.address family " + "mismatch"); + } + $$.a = $1.a; + $$.m = $3.a; + $$.t = FRI_NORMAL; + $$.a.i6[0] &= $$.m.i6[0]; + $$.a.i6[1] &= $$.m.i6[1]; + $$.a.i6[2] &= $$.m.i6[2]; + $$.a.i6[3] &= $$.m.i6[3]; + $$.f = $1.f; + $$.v = ftov($1.f); + yyexpectaddr = 0; + } + | hostname slash hexnumber { bzero(&$$, sizeof($$)); + $$.a = $1.a; + $$.m.in4.s_addr = htonl($3); + $$.t = FRI_NORMAL; + $$.a.in4.s_addr &= $$.m.in4.s_addr; + $$.f = $1.f; + $$.v = ftov($1.f); + if ($$.f == AF_INET6) + yyerror("incorrect inet6 mask"); + } + | hostname mask ipaddr { bzero(&$$, sizeof($$)); + if ($1.f != $3.f) { + yyerror("2.address family " + "mismatch"); + } + $$.a = $1.a; + $$.m = $3.a; + $$.t = FRI_NORMAL; + $$.a.i6[0] &= $$.m.i6[0]; + $$.a.i6[1] &= $$.m.i6[1]; + $$.a.i6[2] &= $$.m.i6[2]; + $$.a.i6[3] &= $$.m.i6[3]; + $$.f = $1.f; + $$.v = ftov($1.f); + yyexpectaddr = 0; + } + | hostname mask hexnumber { bzero(&$$, sizeof($$)); + $$.a = $1.a; + $$.m.in4.s_addr = htonl($3); + $$.t = FRI_NORMAL; + $$.a.in4.s_addr &= $$.m.in4.s_addr; + $$.f = AF_INET; + $$.v = 4; + } + | pool slash YY_NUMBER { bzero(&$$, sizeof($$)); + $$.a.iplookupnum = $3; + $$.a.iplookuptype = IPLT_POOL; + $$.a.iplookupsubtype = 0; + $$.t = FRI_LOOKUP; } + | pool slash YY_STR { bzero(&$$, sizeof($$)); + $$.a.iplookupname = addname(&nat,$3); + $$.a.iplookuptype = IPLT_POOL; + $$.a.iplookupsubtype = 1; + $$.t = FRI_LOOKUP; + } + | hash slash YY_NUMBER { bzero(&$$, sizeof($$)); + $$.a.iplookupnum = $3; + $$.a.iplookuptype = IPLT_HASH; + $$.a.iplookupsubtype = 0; + $$.t = FRI_LOOKUP; + } + | hash slash YY_STR { bzero(&$$, sizeof($$)); + $$.a.iplookupname = addname(&nat,$3); + $$.a.iplookuptype = IPLT_HASH; + $$.a.iplookupsubtype = 1; + $$.t = FRI_LOOKUP; + } + ; + +slash: '/' { yyexpectaddr = 0; } + ; + +mask: IPNY_MASK { yyexpectaddr = 0; } ; -addr: IPNY_ANY { $$.a.s_addr = 0; $$.m.s_addr = 0; } - | nummask { $$.a = $1.a; $$.m = $1.m; - $$.a.s_addr &= $$.m.s_addr; } - | hostname '/' ipv4 { $$.a = $1; $$.m = $3; - $$.a.s_addr &= $$.m.s_addr; } - | hostname '/' hexnumber { $$.a = $1; $$.m.s_addr = htonl($3); - $$.a.s_addr &= $$.m.s_addr; } - | hostname IPNY_MASK ipv4 { $$.a = $1; $$.m = $3; - $$.a.s_addr &= $$.m.s_addr; } - | hostname IPNY_MASK hexnumber { $$.a = $1; $$.m.s_addr = htonl($3); - $$.a.s_addr &= $$.m.s_addr; } +pool: IPNY_POOL { if (!(nat->in_flags & IPN_FILTER)) { + yyerror("Can only use pool with from/to rules\n"); + } + yyexpectaddr = 0; + yyresetdict(); + } ; -nummask: - hostname { $$.a = $1; - $$.m.s_addr = 0xffffffff; } - | hostname '/' YY_NUMBER { $$.a = $1; - ntomask(4, $3, &$$.m.s_addr); } +hash: IPNY_HASH { if (!(nat->in_flags & IPN_FILTER)) { + yyerror("Can only use hash with from/to rules\n"); + } + yyexpectaddr = 0; + yyresetdict(); + } ; portstuff: @@ -507,11 +1061,11 @@ portstuff: ; mapoptions: - rr frag age mssclamp nattag setproto + rr frag age mssclamp nattag setproto purge ; rdroptions: - rr frag age sticky mssclamp rdrproxy nattag + rr frag age sticky mssclamp rdrproxy nattag purge ; nattag: | IPNY_TAG YY_STR { strncpy(nat->in_tag.ipt_tag, $2, @@ -529,9 +1083,9 @@ age: | IPNY_AGE YY_NUMBER { nat->in_age[0] = $2; nat->in_age[1] = $4; } ; -sticky: | IPNY_STICKY { if (!(nat->in_flags & IPN_ROUNDR) && +sticky: | IPNY_STICKY { if (!(nat->in_flags & IPN_ROUNDR) && !(nat->in_flags & IPN_SPLIT)) { - fprintf(stderr, + FPRINTF(stderr, "'sticky' for use with round-robin/IP splitting only\n"); } else nat->in_flags |= IPN_STICKY; @@ -542,30 +1096,47 @@ mssclamp: | IPNY_MSSCLAMP YY_NUMBER { nat->in_mssclamp = $2; } ; -tcpudp: | IPNY_TCP { setnatproto(IPPROTO_TCP); } +tcpudp: IPNY_TCP { setnatproto(IPPROTO_TCP); } | IPNY_UDP { setnatproto(IPPROTO_UDP); } | IPNY_TCPUDP { nat->in_flags |= IPN_TCPUDP; - nat->in_p = 0; + nat->in_pr[0] = 0; + nat->in_pr[1] = 0; } | IPNY_TCP '/' IPNY_UDP { nat->in_flags |= IPN_TCPUDP; - nat->in_p = 0; + nat->in_pr[0] = 0; + nat->in_pr[1] = 0; } ; +sequential: + | IPNY_SEQUENTIAL { nat->in_flags |= IPN_SEQUENTIAL; } + ; + +purge: + | IPNY_PURGE { nat->in_flags |= IPN_PURGE; } + ; + rdrproxy: IPNY_PROXY YY_STR - { strncpy(nat->in_plabel, $2, - sizeof(nat->in_plabel)); - nat->in_dport = nat->in_pnext; - nat->in_dport = htons(nat->in_dport); + { int pos; + pos = addname(&nat, $2); + nat->in_plabel = pos; + nat->in_odport = nat->in_dpnext; + nat->in_dtop = nat->in_odport; free($2); } - | proxy { if (nat->in_plabel[0] != '\0') { - nat->in_pmin = nat->in_dport; - nat->in_pmax = nat->in_pmin; - nat->in_pnext = nat->in_pmin; - } - } + | proxy { if (nat->in_plabel != -1) { + nat->in_ndport = nat->in_odport; + nat->in_dpmin = nat->in_odport; + nat->in_dpmax = nat->in_dpmin; + nat->in_dtop = nat->in_dpmin; + nat->in_dpnext = nat->in_dpmin; + } + } + ; + +newopts: + | IPNY_PURGE { nat->in_flags |= IPN_PURGE; } ; proto: YY_NUMBER { $$ = $1; @@ -575,7 +1146,10 @@ proto: YY_NUMBER { $$ = $1; } | IPNY_TCP { $$ = IPPROTO_TCP; } | IPNY_UDP { $$ = IPPROTO_UDP; } - | YY_STR { $$ = getproto($1); free($1); + | YY_STR { $$ = getproto($1); + free($1); + if ($$ == -1) + yyerror("unknwon protocol"); if ($$ != IPPROTO_TCP && $$ != IPPROTO_UDP) suggest_port = 0; @@ -587,14 +1161,39 @@ hexnumber: ; hostname: - YY_STR { if (gethost($1, &$$.s_addr) == -1) - fprintf(stderr, + YY_STR { i6addr_t addr; + + bzero(&$$, sizeof($$)); + if (gethost(AF_INET, $1, + &addr) == 0) { + $$.a = addr; + $$.f = AF_INET; + } else + if (gethost(AF_INET6, $1, + &addr) == 0) { + $$.a = addr; + $$.f = AF_INET6; + } else { + FPRINTF(stderr, "Unknown host '%s'\n", $1); + } free($1); } - | YY_NUMBER { $$.s_addr = htonl($1); } - | ipv4 { $$.s_addr = $1.s_addr; } + | YY_NUMBER { bzero(&$$, sizeof($$)); + $$.a.in4.s_addr = htonl($1); + if ($$.a.in4.s_addr != 0) + $$.f = AF_INET; + } + | ipv4 { $$ = $1; } + | YY_IPV6 { bzero(&$$, sizeof($$)); + $$.a = $1; + $$.f = AF_INET6; + } + | YY_NUMBER YY_IPV6 { bzero(&$$, sizeof($$)); + $$.a = $2; + $$.f = AF_INET6; + } ; compare: @@ -612,39 +1211,77 @@ range: | ':' { $$ = FR_INCRANGE; } ; +ipaddr: ipv4 { $$ = $1; } + | YY_IPV6 { $$.a = $1; + $$.f = AF_INET6; + } + ; + ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) { yyerror("Invalid octet string for IP address"); return 0; } - $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7; - $$.s_addr = htonl($$.s_addr); + bzero((char *)&$$, sizeof($$)); + $$.a.in4.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7; + $$.a.in4.s_addr = htonl($$.a.in4.s_addr); + $$.f = AF_INET; } ; %% +static wordtab_t proxies[] = { + { "dns", IPNY_DNS } +}; + +static wordtab_t dnswords[] = { + { "allow", IPNY_ALLOW }, + { "block", IPNY_DENY }, + { "deny", IPNY_DENY }, + { "drop", IPNY_DENY }, + { "pass", IPNY_ALLOW }, + +}; + static wordtab_t yywords[] = { { "age", IPNY_AGE }, { "any", IPNY_ANY }, { "auto", IPNY_AUTO }, { "bimap", IPNY_BIMAP }, + { "config", IPNY_CONFIG }, + { "divert", IPNY_DIVERT }, + { "dst", IPNY_DST }, + { "dstlist", IPNY_DSTLIST }, { "frag", IPNY_FRAG }, { "from", IPNY_FROM }, + { "hash", IPNY_HASH }, { "icmpidmap", IPNY_ICMPIDMAP }, + { "in", IPNY_IN }, + { "inet", IPNY_INET }, + { "inet6", IPNY_INET6 }, { "mask", IPNY_MASK }, { "map", IPNY_MAP }, { "map-block", IPNY_MAPBLOCK }, { "mssclamp", IPNY_MSSCLAMP }, { "netmask", IPNY_MASK }, + { "no", IPNY_NO }, + { "on", IPNY_ON }, + { "out", IPNY_OUT }, + { "pool", IPNY_POOL }, { "port", IPNY_PORT }, { "portmap", IPNY_PORTMAP }, { "ports", IPNY_PORTS }, + { "proto", IPNY_PROTO }, { "proxy", IPNY_PROXY }, + { "purge", IPNY_PURGE }, { "range", IPNY_RANGE }, + { "rewrite", IPNY_REWRITE }, { "rdr", IPNY_RDR }, { "round-robin",IPNY_ROUNDROBIN }, + { "sequential", IPNY_SEQUENTIAL }, + { "src", IPNY_SRC }, { "sticky", IPNY_STICKY }, { "tag", IPNY_TAG }, { "tcp", IPNY_TCP }, @@ -663,15 +1300,19 @@ static wordtab_t yywords[] = { }; -int ipnat_parsefile(fd, addfunc, ioctlfunc, filename) -int fd; -addfunc_t addfunc; -ioctlfunc_t ioctlfunc; -char *filename; +int +ipnat_parsefile(fd, addfunc, ioctlfunc, filename) + int fd; + addfunc_t addfunc; + ioctlfunc_t ioctlfunc; + char *filename; { FILE *fp = NULL; + int rval; char *s; + yylineNum = 1; + (void) yysettab(yywords); s = getenv("YYDEBUG"); @@ -683,45 +1324,49 @@ char *filename; if (strcmp(filename, "-")) { fp = fopen(filename, "r"); if (!fp) { - fprintf(stderr, "fopen(%s) failed: %s\n", filename, + FPRINTF(stderr, "fopen(%s) failed: %s\n", filename, STRERROR(errno)); return -1; } } else fp = stdin; - while (ipnat_parsesome(fd, addfunc, ioctlfunc, fp) == 1) + while ((rval = ipnat_parsesome(fd, addfunc, ioctlfunc, fp)) == 0) ; if (fp != NULL) fclose(fp); - return 0; + if (rval == -1) + rval = 0; + else if (rval != 0) + rval = 1; + return rval; } -int ipnat_parsesome(fd, addfunc, ioctlfunc, fp) -int fd; -addfunc_t addfunc; -ioctlfunc_t ioctlfunc; -FILE *fp; +int +ipnat_parsesome(fd, addfunc, ioctlfunc, fp) + int fd; + addfunc_t addfunc; + ioctlfunc_t ioctlfunc; + FILE *fp; { char *s; int i; - yylineNum = 1; - natfd = fd; + parser_error = 0; nataddfunc = addfunc; natioctlfunc = ioctlfunc; if (feof(fp)) - return 0; + return -1; i = fgetc(fp); if (i == EOF) - return 0; + return -1; if (ungetc(i, fp) == EOF) - return 0; + return -1; if (feof(fp)) - return 0; + return -1; s = getenv("YYDEBUG"); if (s) yydebug = atoi(s); @@ -730,11 +1375,12 @@ FILE *fp; yyin = fp; yyparse(); - return 1; + return parser_error; } -static void newnatrule() +static void +newnatrule() { ipnat_t *n; @@ -742,21 +1388,32 @@ static void newnatrule() if (n == NULL) return; - if (nat == NULL) + if (nat == NULL) { nattop = nat = n; - else { + n->in_pnext = &nattop; + } else { nat->in_next = n; + n->in_pnext = &nat->in_next; nat = n; } + n->in_flineno = yylineNum; + n->in_ifnames[0] = -1; + n->in_ifnames[1] = -1; + n->in_plabel = -1; + n->in_pconfig = -1; + n->in_size = sizeof(*n); + suggest_port = 0; } -static void setnatproto(p) -int p; +static void +setnatproto(p) + int p; { - nat->in_p = p; + nat->in_pr[0] = p; + nat->in_pr[1] = p; switch (p) { @@ -770,12 +1427,16 @@ int p; break; case IPPROTO_ICMP : nat->in_flags &= ~IPN_TCPUDP; - if (!(nat->in_flags & IPN_ICMPQUERY)) { + if (!(nat->in_flags & IPN_ICMPQUERY) && + !(nat->in_redir & NAT_DIVERTUDP)) { nat->in_dcmp = 0; nat->in_scmp = 0; - nat->in_pmin = 0; - nat->in_pmax = 0; - nat->in_pnext = 0; + nat->in_dpmin = 0; + nat->in_dpmax = 0; + nat->in_dpnext = 0; + nat->in_spmin = 0; + nat->in_spmax = 0; + nat->in_spnext = 0; } break; default : @@ -783,22 +1444,36 @@ int p; nat->in_flags &= ~IPN_TCPUDP; nat->in_dcmp = 0; nat->in_scmp = 0; - nat->in_pmin = 0; - nat->in_pmax = 0; - nat->in_pnext = 0; + nat->in_dpmin = 0; + nat->in_dpmax = 0; + nat->in_dpnext = 0; + nat->in_spmin = 0; + nat->in_spmax = 0; + nat->in_spnext = 0; } break; } + if ((nat->in_flags & (IPN_TCP|IPN_UDP)) == 0) { + nat->in_stop = 0; + nat->in_dtop = 0; + nat->in_osport = 0; + nat->in_odport = 0; + nat->in_stop = 0; + nat->in_osport = 0; + nat->in_dtop = 0; + nat->in_odport = 0; + } if ((nat->in_flags & (IPN_TCPUDP|IPN_FIXEDDPORT)) == IPN_FIXEDDPORT) nat->in_flags &= ~IPN_FIXEDDPORT; } -void ipnat_addrule(fd, ioctlfunc, ptr) -int fd; -ioctlfunc_t ioctlfunc; -void *ptr; +int +ipnat_addrule(fd, ioctlfunc, ptr) + int fd; + ioctlfunc_t ioctlfunc; + void *ptr; { ioctlcmd_t add, del; ipfobj_t obj; @@ -807,20 +1482,19 @@ void *ptr; ipn = ptr; bzero((char *)&obj, sizeof(obj)); obj.ipfo_rev = IPFILTER_VERSION; - obj.ipfo_size = sizeof(ipnat_t); + obj.ipfo_size = ipn->in_size; obj.ipfo_type = IPFOBJ_IPNAT; obj.ipfo_ptr = ptr; - add = 0; - del = 0; if ((opts & OPT_DONOTHING) != 0) fd = -1; if (opts & OPT_ZERORULEST) { add = SIOCZRLST; - } else if (opts & OPT_INACTIVE) { - add = SIOCADNAT; - del = SIOCRMNAT; + del = 0; + } else if (opts & OPT_PURGE) { + add = 0; + del = SIOCPURGENAT; } else { add = SIOCADNAT; del = SIOCRMNAT; @@ -835,37 +1509,269 @@ void *ptr; if ((opts & OPT_ZERORULEST) != 0) { if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { if ((opts & OPT_DONOTHING) == 0) { - fprintf(stderr, "%d:", yylineNum); - perror("ioctl(SIOCZRLST)"); + char msg[80]; + + sprintf(msg, "%d:ioctl(zero nat rule)", + ipn->in_flineno); + return ipf_perror_fd(fd, ioctlfunc, msg); } } else { -#ifdef USE_QUAD_T -/* - printf("hits %qd bytes %qd ", - (long long)fr->fr_hits, - (long long)fr->fr_bytes); -*/ + PRINTF("hits %lu ", ipn->in_hits); +#ifdef USE_QUAD_T + PRINTF("bytes %"PRIu64" ", + ipn->in_bytes[0] + ipn->in_bytes[1]); #else -/* - printf("hits %ld bytes %ld ", - fr->fr_hits, fr->fr_bytes); -*/ + PRINTF("bytes %lu ", + ipn->in_bytes[0] + ipn->in_bytes[1]); #endif printnat(ipn, opts); } } else if ((opts & OPT_REMOVE) != 0) { if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) { if ((opts & OPT_DONOTHING) == 0) { - fprintf(stderr, "%d:", yylineNum); - perror("ioctl(delete nat rule)"); + char msg[80]; + + sprintf(msg, "%d:ioctl(delete nat rule)", + ipn->in_flineno); + return ipf_perror_fd(fd, ioctlfunc, msg); } } } else { if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { if ((opts & OPT_DONOTHING) == 0) { - fprintf(stderr, "%d:", yylineNum); - perror("ioctl(add/insert nat rule)"); + char msg[80]; + + sprintf(msg, "%d:ioctl(add/insert nat rule)", + ipn->in_flineno); + if (errno == EEXIST) { + sprintf(msg + strlen(msg), "(line %d)", + ipn->in_flineno); + } + return ipf_perror_fd(fd, ioctlfunc, msg); } } } + return 0; +} + + +static void +setmapifnames() +{ + if (nat->in_ifnames[1] == -1) + nat->in_ifnames[1] = nat->in_ifnames[0]; + + if ((suggest_port == 1) && (nat->in_flags & IPN_TCPUDP) == 0) + nat->in_flags |= IPN_TCPUDP; + + if ((nat->in_flags & IPN_TCPUDP) == 0) + setnatproto(nat->in_pr[1]); + + if (((nat->in_redir & NAT_MAPBLK) != 0) || + ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) + nat_setgroupmap(nat); +} + + +static void +setrdrifnames() +{ + if ((suggest_port == 1) && (nat->in_flags & IPN_TCPUDP) == 0) + nat->in_flags |= IPN_TCPUDP; + + if ((nat->in_pr[0] == 0) && ((nat->in_flags & IPN_TCPUDP) == 0) && + (nat->in_dpmin != 0 || nat->in_dpmax != 0 || nat->in_dpnext != 0)) + setnatproto(IPPROTO_TCP); + + if (nat->in_ifnames[1] == -1) + nat->in_ifnames[1] = nat->in_ifnames[0]; +} + + +static void +proxy_setconfig(proxy) + int proxy; +{ + if (proxy == IPNY_DNS) { + yysetfixeddict(dnswords); + } +} + + +static void +proxy_unsetconfig() +{ + yyresetdict(); +} + + +static namelist_t * +proxy_dns_add_pass(prefix, name) + char *prefix, *name; +{ + namelist_t *n; + + n = calloc(1, sizeof(*n)); + if (n != NULL) { + if (prefix == NULL || *prefix == '\0') { + n->na_name = strdup(name); + } else { + n->na_name = malloc(strlen(name) + strlen(prefix) + 1); + strcpy(n->na_name, prefix); + strcat(n->na_name, name); + } + } + return n; +} + + +static namelist_t * +proxy_dns_add_block(prefix, name) + char *prefix, *name; +{ + namelist_t *n; + + n = calloc(1, sizeof(*n)); + if (n != NULL) { + if (prefix == NULL || *prefix == '\0') { + n->na_name = strdup(name); + } else { + n->na_name = malloc(strlen(name) + strlen(prefix) + 1); + strcpy(n->na_name, prefix); + strcat(n->na_name, name); + } + n->na_value = 1; + } + return n; +} + + +static void +proxy_addconfig(proxy, proto, conf, list) + char *proxy, *conf; + int proto; + namelist_t *list; +{ + proxyrule_t *pr; + + pr = calloc(1, sizeof(*pr)); + if (pr != NULL) { + pr->pr_proto = proto; + pr->pr_proxy = proxy; + pr->pr_conf = conf; + pr->pr_names = list; + pr->pr_next = prules; + prules = pr; + } +} + + +static void +proxy_loadrules(fd, ioctlfunc, rules) + int fd; + ioctlfunc_t ioctlfunc; + proxyrule_t *rules; +{ + proxyrule_t *pr; + + while ((pr = rules) != NULL) { + proxy_loadconfig(fd, ioctlfunc, pr->pr_proxy, pr->pr_proto, + pr->pr_conf, pr->pr_names); + rules = pr->pr_next; + free(pr->pr_conf); + free(pr); + } +} + + +static void +proxy_loadconfig(fd, ioctlfunc, proxy, proto, conf, list) + int fd; + ioctlfunc_t ioctlfunc; + char *proxy, *conf; + int proto; + namelist_t *list; +{ + namelist_t *na; + ipfobj_t obj; + ap_ctl_t pcmd; + + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_type = IPFOBJ_PROXYCTL; + obj.ipfo_size = sizeof(pcmd); + obj.ipfo_ptr = &pcmd; + + while ((na = list) != NULL) { + if ((opts & OPT_REMOVE) != 0) + pcmd.apc_cmd = APC_CMD_DEL; + else + pcmd.apc_cmd = APC_CMD_ADD; + pcmd.apc_dsize = strlen(na->na_name) + 1; + pcmd.apc_data = na->na_name; + pcmd.apc_arg = na->na_value; + pcmd.apc_p = proto; + + strncpy(pcmd.apc_label, proxy, APR_LABELLEN); + pcmd.apc_label[APR_LABELLEN - 1] = '\0'; + + strncpy(pcmd.apc_config, conf, APR_LABELLEN); + pcmd.apc_config[APR_LABELLEN - 1] = '\0'; + + if ((*ioctlfunc)(fd, SIOCPROXY, (void *)&obj) == -1) { + if ((opts & OPT_DONOTHING) == 0) { + char msg[80]; + + sprintf(msg, "%d:ioctl(add/remove proxy rule)", + yylineNum); + ipf_perror_fd(fd, ioctlfunc, msg); + return; + } + } + + list = na->na_next; + free(na->na_name); + free(na); + } +} + + +static void +setifname(np, idx, name) + ipnat_t **np; + int idx; + char *name; +{ + int pos; + + pos = addname(np, name); + if (pos == -1) + return; + (*np)->in_ifnames[idx] = pos; +} + + +static int +addname(np, name) + ipnat_t **np; + char *name; +{ + ipnat_t *n; + int nlen; + int pos; + + nlen = strlen(name) + 1; + n = realloc(*np, (*np)->in_size + nlen); + if (*np == nattop) + nattop = n; + *np = n; + if (n == NULL) + return -1; + if (n->in_pnext != NULL) + *n->in_pnext = n; + n->in_size += nlen; + pos = n->in_namelen; + n->in_namelen += nlen; + strcpy(n->in_names + pos, name); + n->in_names[n->in_namelen] = '\0'; + return pos; } diff --git a/tools/ippool.c b/tools/ippool.c index cbdfd69fff382..2063456dc2d00 100644 --- a/tools/ippool.c +++ b/tools/ippool.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -59,41 +59,48 @@ int poolflush __P((int, char *[])); int poolstats __P((int, char *[])); int gettype __P((char *, u_int *)); int getrole __P((char *)); -int setnodeaddr __P((ip_pool_node_t *node, char *arg)); -void showpools_live __P((int, int, ip_pool_stat_t *, char *)); +int setnodeaddr __P((int, int, void *ptr, char *arg)); +void showpools_live __P((int, int, ipf_pool_stat_t *, char *)); void showhashs_live __P((int, int, iphtstat_t *, char *)); +void showdstls_live __P((int, int, ipf_dstl_stat_t *, char *)); int opts = 0; int fd = -1; int use_inet6 = 0; +wordtab_t *pool_fields = NULL; +int nohdrfields = 0; -void usage(prog) -char *prog; +void +usage(prog) + char *prog; { fprintf(stderr, "Usage:\t%s\n", prog); - fprintf(stderr, "\t\t\t-a [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n"); - fprintf(stderr, "\t\t\t-A [-dnv] [-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n"); - fprintf(stderr, "\t\t\t-f <file> [-dnuv]\n"); - fprintf(stderr, "\t\t\t-F [-dv] [-o <role>] [-t <type>]\n"); - fprintf(stderr, "\t\t\t-l [-dv] [-m <name>] [-t <type>]\n"); - fprintf(stderr, "\t\t\t-r [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n"); - fprintf(stderr, "\t\t\t-R [-dnv] [-m <name>] [-o <role>] [-t <type>]\n"); - fprintf(stderr, "\t\t\t-s [-dtv] [-M <core>] [-N <namelist>]\n"); + fprintf(stderr, "\t-a [-dnv] [-m <name>] [-o <role>] [-t type] [-T ttl] -i <ipaddr>[/netmask]\n"); + fprintf(stderr, "\t-A [-dnv] [-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n"); + fprintf(stderr, "\t-f <file> [-dnuv]\n"); + fprintf(stderr, "\t-F [-dv] [-o <role>] [-t <type>]\n"); + fprintf(stderr, "\t-l [-dv] [-m <name>] [-t <type>] [-O <fields>]\n"); + fprintf(stderr, "\t-r [-dnv] [-m <name>] [-o <role>] [-t type] -i <ipaddr>[/netmask]\n"); + fprintf(stderr, "\t-R [-dnv] [-m <name>] [-o <role>] [-t <type>]\n"); + fprintf(stderr, "\t-s [-dtv] [-M <core>] [-N <namelist>]\n"); exit(1); } -int main(argc, argv) -int argc; -char *argv[]; +int +main(argc, argv) + int argc; + char *argv[]; { - int err; + int err = 1; if (argc < 2) usage(argv[0]); - switch (getopt(argc, argv, "aAf:FlrRs")) + assigndefined(getenv("IPPOOL_PREDEFINED")); + + switch (getopt(argc, argv, "aAf:FlnrRsv")) { case 'a' : err = poolnodecommand(0, argc, argv); @@ -110,6 +117,9 @@ char *argv[]; case 'l' : err = poollist(argc, argv); break; + case 'n' : + opts |= OPT_DONOTHING|OPT_DONTOPEN; + break; case 'r' : err = poolnodecommand(1, argc, argv); break; @@ -119,6 +129,9 @@ char *argv[]; case 's' : err = poolstats(argc, argv); break; + case 'v' : + opts |= OPT_VERBOSE; + break; default : exit(1); } @@ -129,19 +142,23 @@ char *argv[]; } -int poolnodecommand(remove, argc, argv) -int remove, argc; -char *argv[]; +int +poolnodecommand(remove, argc, argv) + int remove, argc; + char *argv[]; { - int err, c, ipset, role; + int err = 0, c, ipset, role, type = IPLT_POOL, ttl = 0; char *poolname = NULL; - ip_pool_node_t node; + ip_pool_node_t pnode; + iphtent_t hnode; + void *ptr = &pnode; ipset = 0; role = IPL_LOGIPF; - bzero((char *)&node, sizeof(node)); + bzero((char *)&pnode, sizeof(pnode)); + bzero((char *)&hnode, sizeof(hnode)); - while ((c = getopt(argc, argv, "di:m:no:Rv")) != -1) + while ((c = getopt(argc, argv, "di:m:no:Rt:T:v")) != -1) switch (c) { case 'd' : @@ -149,16 +166,21 @@ char *argv[]; ippool_yydebug++; break; case 'i' : - if (setnodeaddr(&node, optarg) == 0) + if (setnodeaddr(type, role, ptr, optarg) == 0) ipset = 1; break; case 'm' : poolname = optarg; break; case 'n' : - opts |= OPT_DONOTHING; + opts |= OPT_DONOTHING|OPT_DONTOPEN; break; case 'o' : + if (ipset == 1) { + fprintf(stderr, + "cannot set role after ip address\n"); + return -1; + } role = getrole(optarg); if (role == IPL_LOGNONE) return -1; @@ -166,13 +188,39 @@ char *argv[]; case 'R' : opts |= OPT_NORESOLVE; break; + case 't' : + if (ipset == 1) { + fprintf(stderr, + "cannot set type after ip address\n"); + return -1; + } + type = gettype(optarg, NULL); + switch (type) { + case IPLT_NONE : + fprintf(stderr, "unknown type '%s'\n", optarg); + return -1; + case IPLT_HASH : + ptr = &hnode; + break; + case IPLT_POOL : + default : + break; + } + break; + case 'T' : + ttl = atoi(optarg); + if (ttl < 0) { + fprintf(stderr, "cannot set negative ttl\n"); + return -1; + } + break; case 'v' : opts |= OPT_VERBOSE; break; } if (argv[optind] != NULL && ipset == 0) { - if (setnodeaddr(&node, argv[optind]) == 0) + if (setnodeaddr(type, role, ptr, argv[optind]) == 0) ipset = 1; } @@ -189,17 +237,30 @@ char *argv[]; return -1; } - if (remove == 0) - err = load_poolnode(0, poolname, &node, ioctl); - else - err = remove_poolnode(0, poolname, &node, ioctl); + switch (type) { + case IPLT_POOL : + if (remove == 0) + err = load_poolnode(role, poolname, &pnode, ttl, ioctl); + else + err = remove_poolnode(role, poolname, &pnode, ioctl); + break; + case IPLT_HASH : + if (remove == 0) + err = load_hashnode(role, poolname, &hnode, ttl, ioctl); + else + err = remove_hashnode(role, poolname, &hnode, ioctl); + break; + default : + break; + } return err; } -int poolcommand(remove, argc, argv) -int remove, argc; -char *argv[]; +int +poolcommand(remove, argc, argv) + int remove, argc; + char *argv[]; { int type, role, c, err; char *poolname; @@ -214,7 +275,7 @@ char *argv[]; bzero((char *)&iph, sizeof(iph)); bzero((char *)&pool, sizeof(pool)); - while ((c = getopt(argc, argv, "dm:no:RSt:v")) != -1) + while ((c = getopt(argc, argv, "dm:no:RSv")) != -1) switch (c) { case 'd' : @@ -225,7 +286,7 @@ char *argv[]; poolname = optarg; break; case 'n' : - opts |= OPT_DONOTHING; + opts |= OPT_DONOTHING|OPT_DONTOPEN; break; case 'o' : role = getrole(optarg); @@ -240,13 +301,6 @@ char *argv[]; case 'S' : iph.iph_seed = atoi(optarg); break; - case 't' : - type = gettype(optarg, &iph.iph_type); - if (type == IPLT_NONE) { - fprintf(stderr, "unknown type '%s'\n", optarg); - return -1; - } - break; case 'v' : opts |= OPT_VERBOSE; break; @@ -260,6 +314,12 @@ char *argv[]; return -1; } + type = gettype(argv[optind], &iph.iph_type); + if (type == IPLT_NONE) { + fprintf(stderr, "unknown type '%s'\n", argv[optind]); + return -1; + } + if (type == IPLT_HASH) { strncpy(iph.iph_name, poolname, sizeof(iph.iph_name)); iph.iph_name[sizeof(iph.iph_name) - 1] = '\0'; @@ -295,9 +355,10 @@ char *argv[]; } -int loadpoolfile(argc, argv, infile) -int argc; -char *argv[], *infile; +int +loadpoolfile(argc, argv, infile) + int argc; + char *argv[], *infile; { int c; @@ -311,7 +372,7 @@ char *argv[], *infile; ippool_yydebug++; break; case 'n' : - opts |= OPT_DONOTHING; + opts |= OPT_DONOTHING|OPT_DONTOPEN; break; case 'R' : opts |= OPT_NORESOLVE; @@ -327,7 +388,7 @@ char *argv[], *infile; if (opts & OPT_DEBUG) fprintf(stderr, "loadpoolfile: opts = %#x\n", opts); - if (!(opts & OPT_DONOTHING) && (fd == -1)) { + if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) { fd = open(IPLOOKUP_NAME, O_RDWR); if (fd == -1) { perror("open(IPLOOKUP_NAME)"); @@ -341,12 +402,14 @@ char *argv[], *infile; } -int poolstats(argc, argv) -int argc; -char *argv[]; +int +poolstats(argc, argv) + int argc; + char *argv[]; { int c, type, role, live_kernel; - ip_pool_stat_t plstat; + ipf_pool_stat_t plstat; + ipf_dstl_stat_t dlstat; char *kernel, *core; iphtstat_t htstat; iplookupop_t op; @@ -396,7 +459,7 @@ char *argv[]; if (opts & OPT_DEBUG) fprintf(stderr, "poolstats: opts = %#x\n", opts); - if (!(opts & OPT_DONOTHING) && (fd == -1)) { + if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) { fd = open(IPLOOKUP_NAME, O_RDWR); if (fd == -1) { perror("open(IPLOOKUP_NAME)"); @@ -408,14 +471,14 @@ char *argv[]; op.iplo_type = IPLT_POOL; op.iplo_struct = &plstat; op.iplo_size = sizeof(plstat); - if (!(opts & OPT_DONOTHING)) { + if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) { c = ioctl(fd, SIOCLOOKUPSTAT, &op); if (c == -1) { - perror("ioctl(SIOCLOOKUPSTAT)"); + ipferror(fd, "ioctl(S0IOCLOOKUPSTAT)"); return -1; } - printf("Pools:\t%lu\n", plstat.ipls_pools); - printf("Nodes:\t%lu\n", plstat.ipls_nodes); + printf("%lu\taddress pools\n", plstat.ipls_pools); + printf("%lu\taddress pool nodes\n", plstat.ipls_nodes); } } @@ -423,24 +486,49 @@ char *argv[]; op.iplo_type = IPLT_HASH; op.iplo_struct = &htstat; op.iplo_size = sizeof(htstat); - if (!(opts & OPT_DONOTHING)) { + if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) { + c = ioctl(fd, SIOCLOOKUPSTAT, &op); + if (c == -1) { + ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); + return -1; + } + printf("%lu\thash tables\n", htstat.iphs_numtables); + printf("%lu\thash table nodes\n", htstat.iphs_numnodes); + printf("%lu\thash table no memory \n", + htstat.iphs_nomem); + } + } + + if (type == IPLT_ALL || type == IPLT_DSTLIST) { + op.iplo_type = IPLT_DSTLIST; + op.iplo_struct = &dlstat; + op.iplo_size = sizeof(dlstat); + if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) { c = ioctl(fd, SIOCLOOKUPSTAT, &op); if (c == -1) { - perror("ioctl(SIOCLOOKUPSTAT)"); + ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); return -1; } - printf("Hash Tables:\t%lu\n", htstat.iphs_numtables); - printf("Nodes:\t%lu\n", htstat.iphs_numnodes); - printf("Out of Memory:\t%lu\n", htstat.iphs_nomem); + printf("%u\tdestination lists\n", + dlstat.ipls_numlists); + printf("%u\tdestination list nodes\n", + dlstat.ipls_numnodes); + printf("%lu\tdestination list no memory\n", + dlstat.ipls_nomem); + printf("%u\tdestination list zombies\n", + dlstat.ipls_numdereflists); + printf("%u\tdesetination list node zombies\n", + dlstat.ipls_numderefnodes); } } return 0; } -int poolflush(argc, argv) -int argc; -char *argv[]; +int +poolflush(argc, argv) + int argc; + char *argv[]; { int c, role, type, arg; iplookupflush_t flush; @@ -477,7 +565,7 @@ char *argv[]; if (opts & OPT_DEBUG) fprintf(stderr, "poolflush: opts = %#x\n", opts); - if (!(opts & OPT_DONOTHING) && (fd == -1)) { + if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) { fd = open(IPLOOKUP_NAME, O_RDWR); if (fd == -1) { perror("open(IPLOOKUP_NAME)"); @@ -490,9 +578,9 @@ char *argv[]; flush.iplf_unit = role; flush.iplf_arg = arg; - if (!(opts & OPT_DONOTHING)) { + if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) { if (ioctl(fd, SIOCLOOKUPFLUSH, &flush) == -1) { - perror("ioctl(SIOCLOOKUPFLUSH)"); + ipferror(fd, "ioctl(SIOCLOOKUPFLUSH)"); exit(1); } @@ -504,8 +592,9 @@ char *argv[]; } -int getrole(rolename) -char *rolename; +int +getrole(rolename) + char *rolename; { int role; @@ -535,19 +624,20 @@ char *rolename; } -int gettype(typename, minor) -char *typename; -u_int *minor; +int +gettype(typename, minor) + char *typename; + u_int *minor; { int type; - if (!strcasecmp(optarg, "tree") || !strcasecmp(optarg, "pool")) { + if (!strcasecmp(typename, "tree") || !strcasecmp(typename, "pool")) { type = IPLT_POOL; - } else if (!strcasecmp(optarg, "hash")) { + } else if (!strcasecmp(typename, "hash")) { type = IPLT_HASH; if (minor != NULL) *minor = IPHASH_LOOKUP; - } else if (!strcasecmp(optarg, "group-map")) { + } else if (!strcasecmp(typename, "group-map")) { type = IPLT_HASH; if (minor != NULL) *minor = IPHASH_GROUPMAP; @@ -558,9 +648,10 @@ u_int *minor; } -int poollist(argc, argv) -int argc; -char *argv[]; +int +poollist(argc, argv) + int argc; + char *argv[]; { char *kernel, *core, *poolname; int c, role, type, live_kernel; @@ -597,6 +688,9 @@ char *argv[]; return -1; } break; + case 'O' : + pool_fields = parsefields(poolfields, optarg); + break; case 'R' : opts |= OPT_NORESOLVE; break; @@ -615,7 +709,7 @@ char *argv[]; if (opts & OPT_DEBUG) fprintf(stderr, "poollist: opts = %#x\n", opts); - if (!(opts & OPT_DONOTHING) && (fd == -1)) { + if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) { fd = open(IPLOOKUP_NAME, O_RDWR); if (fd == -1) { perror("open(IPLOOKUP_NAME)"); @@ -638,9 +732,10 @@ char *argv[]; } -void poollist_dead(role, poolname, type, kernel, core) -int role, type; -char *poolname, *kernel, *core; +void +poollist_dead(role, poolname, type, kernel, core) + int role, type; + char *poolname, *kernel, *core; { iphtable_t *hptr; ip_pool_t *ptr; @@ -663,14 +758,15 @@ char *poolname, *kernel, *core; ptr = pools[role]; while (ptr != NULL) { ptr = printpool(ptr, kmemcpywrap, poolname, - opts); + opts, pool_fields); } } else { for (role = 0; role <= IPL_LOGMAX; role++) { ptr = pools[role]; while (ptr != NULL) { ptr = printpool(ptr, kmemcpywrap, - poolname, opts); + poolname, opts, + pool_fields); } } role = IPL_LOGALL; @@ -691,14 +787,15 @@ char *poolname, *kernel, *core; hptr = tables[role]; while (hptr != NULL) { hptr = printhash(hptr, kmemcpywrap, - poolname, opts); + poolname, opts, pool_fields); } } else { for (role = 0; role <= IPL_LOGMAX; role++) { hptr = tables[role]; while (hptr != NULL) { hptr = printhash(hptr, kmemcpywrap, - poolname, opts); + poolname, opts, + pool_fields); } } } @@ -706,12 +803,12 @@ char *poolname, *kernel, *core; } -void poollist_live(role, poolname, type, fd) -int role, type, fd; -char *poolname; +void +poollist_live(role, poolname, type, fd) + int role, type, fd; + char *poolname; { - ip_pool_stat_t plstat; - iphtstat_t htstat; + ipf_pool_stat_t plstat; iplookupop_t op; int c; @@ -727,18 +824,18 @@ char *poolname; c = ioctl(fd, SIOCLOOKUPSTAT, &op); if (c == -1) { - perror("ioctl(SIOCLOOKUPSTAT)"); + ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); return; } showpools_live(fd, role, &plstat, poolname); } else { - for (role = 0; role <= IPL_LOGMAX; role++) { + for (role = -1; role <= IPL_LOGMAX; role++) { op.iplo_unit = role; c = ioctl(fd, SIOCLOOKUPSTAT, &op); if (c == -1) { - perror("ioctl(SIOCLOOKUPSTAT)"); + ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); return; } @@ -750,6 +847,8 @@ char *poolname; } if (type == IPLT_ALL || type == IPLT_HASH) { + iphtstat_t htstat; + op.iplo_type = IPLT_HASH; op.iplo_size = sizeof(htstat); op.iplo_struct = &htstat; @@ -761,7 +860,7 @@ char *poolname; c = ioctl(fd, SIOCLOOKUPSTAT, &op); if (c == -1) { - perror("ioctl(SIOCLOOKUPSTAT)"); + ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); return; } showhashs_live(fd, role, &htstat, poolname); @@ -771,21 +870,57 @@ char *poolname; op.iplo_unit = role; c = ioctl(fd, SIOCLOOKUPSTAT, &op); if (c == -1) { - perror("ioctl(SIOCLOOKUPSTAT)"); + ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); return; } showhashs_live(fd, role, &htstat, poolname); } + role = IPL_LOGALL; + } + } + + if (type == IPLT_ALL || type == IPLT_DSTLIST) { + ipf_dstl_stat_t dlstat; + + op.iplo_type = IPLT_DSTLIST; + op.iplo_size = sizeof(dlstat); + op.iplo_struct = &dlstat; + op.iplo_name[0] = '\0'; + op.iplo_arg = 0; + + if (role != IPL_LOGALL) { + op.iplo_unit = role; + + c = ioctl(fd, SIOCLOOKUPSTAT, &op); + if (c == -1) { + ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); + return; + } + showdstls_live(fd, role, &dlstat, poolname); + } else { + for (role = 0; role <= IPL_LOGMAX; role++) { + + op.iplo_unit = role; + c = ioctl(fd, SIOCLOOKUPSTAT, &op); + if (c == -1) { + ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); + return; + } + + showdstls_live(fd, role, &dlstat, poolname); + } + role = IPL_LOGALL; } } } -void showpools_live(fd, role, plstp, poolname) -int fd, role; -ip_pool_stat_t *plstp; -char *poolname; +void +showpools_live(fd, role, plstp, poolname) + int fd, role; + ipf_pool_stat_t *plstp; + char *poolname; { ipflookupiter_t iter; ip_pool_t pool; @@ -804,22 +939,27 @@ char *poolname; iter.ili_unit = role; *iter.ili_name = '\0'; - while (plstp->ipls_list[role] != NULL) { + bzero((char *)&pool, sizeof(pool)); + + while (plstp->ipls_list[role + 1] != NULL) { if (ioctl(fd, SIOCLOOKUPITER, &obj)) { - perror("ioctl(SIOCLOOKUPITER)"); + ipferror(fd, "ioctl(SIOCLOOKUPITER)"); break; } - printpool_live(&pool, fd, poolname, opts); + if (((pool.ipo_flags & IPOOL_DELETE) == 0) || + ((opts & OPT_DEBUG) != 0)) + printpool_live(&pool, fd, poolname, opts, pool_fields); - plstp->ipls_list[role] = pool.ipo_next; + plstp->ipls_list[role + 1] = pool.ipo_next; } } -void showhashs_live(fd, role, htstp, poolname) -int fd, role; -iphtstat_t *htstp; -char *poolname; +void +showhashs_live(fd, role, htstp, poolname) + int fd, role; + iphtstat_t *htstp; + char *poolname; { ipflookupiter_t iter; iphtable_t table; @@ -840,18 +980,55 @@ char *poolname; while (htstp->iphs_tables != NULL) { if (ioctl(fd, SIOCLOOKUPITER, &obj)) { - perror("ioctl(SIOCLOOKUPITER)"); + ipferror(fd, "ioctl(SIOCLOOKUPITER)"); break; } - printhash_live(&table, fd, poolname, opts); + printhash_live(&table, fd, poolname, opts, pool_fields); htstp->iphs_tables = table.iph_next; } } -int setnodeaddr(ip_pool_node_t *node, char *arg) +void +showdstls_live(fd, role, dlstp, poolname) + int fd, role; + ipf_dstl_stat_t *dlstp; + char *poolname; +{ + ipflookupiter_t iter; + ippool_dst_t table; + ipfobj_t obj; + + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_type = IPFOBJ_LOOKUPITER; + obj.ipfo_size = sizeof(iter); + obj.ipfo_ptr = &iter; + + iter.ili_type = IPLT_DSTLIST; + iter.ili_otype = IPFLOOKUPITER_LIST; + iter.ili_ival = IPFGENITER_LOOKUP; + iter.ili_nitems = 1; + iter.ili_data = &table; + iter.ili_unit = role; + *iter.ili_name = '\0'; + + while (dlstp->ipls_list[role] != NULL) { + if (ioctl(fd, SIOCLOOKUPITER, &obj)) { + ipferror(fd, "ioctl(SIOCLOOKUPITER)"); + break; + } + + printdstl_live(&table, fd, poolname, opts, pool_fields); + + dlstp->ipls_list[role] = table.ipld_next; + } +} + + +int +setnodeaddr(int type, int role, void *ptr, char *arg) { struct in_addr mask; char *s; @@ -860,17 +1037,38 @@ int setnodeaddr(ip_pool_node_t *node, char *arg) if (s == NULL) mask.s_addr = 0xffffffff; else if (strchr(s, '.') == NULL) { - if (ntomask(4, atoi(s + 1), &mask.s_addr) != 0) + if (ntomask(AF_INET, atoi(s + 1), &mask.s_addr) != 0) return -1; } else { mask.s_addr = inet_addr(s + 1); } if (s != NULL) *s = '\0'; - node->ipn_addr.adf_len = sizeof(node->ipn_addr); - node->ipn_addr.adf_addr.in4.s_addr = inet_addr(arg); - node->ipn_mask.adf_len = sizeof(node->ipn_mask); - node->ipn_mask.adf_addr.in4.s_addr = mask.s_addr; + + if (type == IPLT_POOL) { + ip_pool_node_t *node = ptr; + + if (node->ipn_addr.adf_family == AF_INET) + node->ipn_addr.adf_len = offsetof(addrfamily_t, + adf_addr) + + sizeof(struct in_addr); +#ifdef USE_INET6 + else + node->ipn_addr.adf_len = offsetof(addrfamily_t, + adf_addr) + + sizeof(struct in6_addr); +#endif + node->ipn_addr.adf_addr.in4.s_addr = inet_addr(arg); + node->ipn_mask.adf_len = node->ipn_addr.adf_len; + node->ipn_mask.adf_addr.in4.s_addr = mask.s_addr; + } else if (type == IPLT_HASH) { + iphtent_t *node = ptr; + + node->ipe_addr.in4.s_addr = inet_addr(arg); + node->ipe_mask.in4.s_addr = mask.s_addr; + node->ipe_family = AF_INET; + node->ipe_unit = role; + } return 0; } diff --git a/tools/ippool_y.y b/tools/ippool_y.y index 4aa51081090fb..60b9819444478 100644 --- a/tools/ippool_y.y +++ b/tools/ippool_y.y @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -33,6 +33,7 @@ #include "netinet/ip_lookup.h" #include "netinet/ip_pool.h" #include "netinet/ip_htable.h" +#include "netinet/ip_dstlist.h" #include "ippool_l.h" #include "kmem.h" @@ -46,43 +47,52 @@ extern FILE *yyin; static iphtable_t ipht; static iphtent_t iphte; static ip_pool_t iplo; +static ippool_dst_t ipld; static ioctlfunc_t poolioctl = NULL; static char poolname[FR_GROUPLEN]; static iphtent_t *add_htablehosts __P((char *)); static ip_pool_node_t *add_poolhosts __P((char *)); +static ip_pool_node_t *read_whoisfile __P((char *)); +static void setadflen __P((addrfamily_t *)); %} %union { char *str; u_32_t num; - struct in_addr addr; + struct in_addr ip4; struct alist_s *alist; - struct in_addr adrmsk[2]; + addrfamily_t adrmsk[2]; iphtent_t *ipe; ip_pool_node_t *ipp; - union i6addr ip6; + ipf_dstnode_t *ipd; + addrfamily_t ipa; + i6addr_t ip6; } -%token <num> YY_NUMBER YY_HEX -%token <str> YY_STR -%token YY_COMMENT -%token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT -%token YY_RANGE_OUT YY_RANGE_IN -%token <ip6> YY_IPV6 - -%token IPT_IPF IPT_NAT IPT_COUNT IPT_AUTH IPT_IN IPT_OUT -%token IPT_TABLE IPT_GROUPMAP IPT_HASH +%token <num> YY_NUMBER YY_HEX +%token <str> YY_STR +%token <ip6> YY_IPV6 +%token YY_COMMENT +%token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT +%token YY_RANGE_OUT YY_RANGE_IN +%token IPT_IPF IPT_NAT IPT_COUNT IPT_AUTH IPT_IN IPT_OUT IPT_ALL +%token IPT_TABLE IPT_GROUPMAP IPT_HASH IPT_SRCHASH IPT_DSTHASH %token IPT_ROLE IPT_TYPE IPT_TREE -%token IPT_GROUP IPT_SIZE IPT_SEED IPT_NUM IPT_NAME -%type <num> role table inout +%token IPT_GROUP IPT_SIZE IPT_SEED IPT_NUM IPT_NAME IPT_POLICY +%token IPT_POOL IPT_DSTLIST IPT_ROUNDROBIN +%token IPT_WEIGHTED IPT_RANDOM IPT_CONNECTION +%token IPT_WHOIS IPT_FILE +%type <num> role table inout unit dstopts weighting %type <ipp> ipftree range addrlist %type <adrmsk> addrmask %type <ipe> ipfgroup ipfhash hashlist hashentry %type <ipe> groupentry setgrouplist grouplist -%type <addr> ipaddr mask ipv4 -%type <str> number setgroup +%type <ipa> ipaddr mask +%type <ip4> ipv4 +%type <str> number setgroup name +%type <ipd> dstentry dstentries dstlist %% file: line @@ -91,25 +101,44 @@ file: line | file assign ; -line: table role ipftree eol { iplo.ipo_unit = $2; +line: table role ipftree eol { ip_pool_node_t *n; + iplo.ipo_unit = $2; iplo.ipo_list = $3; load_pool(&iplo, poolioctl); + while ((n = $3) != NULL) { + $3 = n->ipn_next; + free(n); + } resetlexer(); + use_inet6 = 0; } - | table role ipfhash eol { ipht.iph_unit = $2; + | table role ipfhash eol { iphtent_t *h; + ipht.iph_unit = $2; ipht.iph_type = IPHASH_LOOKUP; load_hash(&ipht, $3, poolioctl); + while ((h = $3) != NULL) { + $3 = h->ipe_next; + free(h); + } resetlexer(); + use_inet6 = 0; } | groupmap role number ipfgroup eol - { ipht.iph_unit = $2; + { iphtent_t *h; + ipht.iph_unit = $2; strncpy(ipht.iph_name, $3, sizeof(ipht.iph_name)); ipht.iph_type = IPHASH_GROUPMAP; load_hash(&ipht, $4, poolioctl); + while ((h = $4) != NULL) { + $4 = h->ipe_next; + free(h); + } resetlexer(); + use_inet6 = 0; } | YY_COMMENT + | poolline eol ; eol: ';' @@ -130,6 +159,7 @@ assigning: table: IPT_TABLE { bzero((char *)&ipht, sizeof(ipht)); bzero((char *)&iphte, sizeof(iphte)); bzero((char *)&iplo, sizeof(iplo)); + bzero((char *)&ipld, sizeof(ipld)); *ipht.iph_name = '\0'; iplo.ipo_flags = IPHASH_ANON; iplo.ipo_name[0] = '\0'; @@ -148,11 +178,15 @@ groupmap: inout: IPT_IN { $$ = FR_INQUE; } | IPT_OUT { $$ = FR_OUTQUE; } ; -role: - IPT_ROLE '=' IPT_IPF { $$ = IPL_LOGIPF; } - | IPT_ROLE '=' IPT_NAT { $$ = IPL_LOGNAT; } - | IPT_ROLE '=' IPT_AUTH { $$ = IPL_LOGAUTH; } - | IPT_ROLE '=' IPT_COUNT { $$ = IPL_LOGCOUNT; } + +role: IPT_ROLE '=' unit { $$ = $3; } + ; + +unit: IPT_IPF { $$ = IPL_LOGIPF; } + | IPT_NAT { $$ = IPL_LOGNAT; } + | IPT_AUTH { $$ = IPL_LOGAUTH; } + | IPT_COUNT { $$ = IPL_LOGCOUNT; } + | IPT_ALL { $$ = IPL_LOGALL; } ; ipftree: @@ -181,14 +215,21 @@ ipfgroup: $1, FR_GROUPLEN); $$ = $4; + free($1); } - | hashopts start setgrouplist end { $$ = $3; } + | hashopts start setgrouplist end + { $$ = $3; } ; number: IPT_NUM '=' YY_NUMBER { sprintf(poolname, "%u", $3); $$ = poolname; } - | IPT_NAME '=' YY_STR { $$ = $3; } + | IPT_NAME '=' YY_STR { strncpy(poolname, $3, + FR_GROUPLEN); + poolname[FR_GROUPLEN-1]='\0'; + free($3); + $$ = poolname; + } | { $$ = ""; } ; @@ -196,6 +237,7 @@ setgroup: IPT_GROUP '=' YY_STR { char tmp[FR_GROUPLEN+1]; strncpy(tmp, $3, FR_GROUPLEN); $$ = strdup(tmp); + free($3); } | IPT_GROUP '=' YY_NUMBER { char tmp[FR_GROUPLEN+1]; sprintf(tmp, "%u", $3); @@ -210,119 +252,162 @@ hashopts: ; addrlist: - next { $$ = NULL; } - | range next addrlist { $1->ipn_next = $3; $$ = $1; } + ';' { $$ = NULL; } + | range next addrlist { $$ = $1; + while ($1->ipn_next != NULL) + $1 = $1->ipn_next; + $1->ipn_next = $3; + } | range next { $$ = $1; } ; grouplist: - next { $$ = NULL; } + ';' { $$ = NULL; } | groupentry next grouplist { $$ = $1; $1->ipe_next = $3; } | addrmask next grouplist { $$ = calloc(1, sizeof(iphtent_t)); - bcopy((char *)&($1[0]), - (char *)&($$->ipe_addr), - sizeof($$->ipe_addr)); - bcopy((char *)&($1[1]), - (char *)&($$->ipe_mask), - sizeof($$->ipe_mask)); + $$->ipe_addr = $1[0].adf_addr; + $$->ipe_mask = $1[1].adf_addr; + $$->ipe_family = $1[0].adf_family; $$->ipe_next = $3; } | groupentry next { $$ = $1; } | addrmask next { $$ = calloc(1, sizeof(iphtent_t)); - bcopy((char *)&($1[0]), - (char *)&($$->ipe_addr), - sizeof($$->ipe_addr)); - bcopy((char *)&($1[1]), - (char *)&($$->ipe_mask), - sizeof($$->ipe_mask)); + $$->ipe_addr = $1[0].adf_addr; + $$->ipe_mask = $1[1].adf_addr; +#ifdef AF_INET6 + if (use_inet6) + $$->ipe_family = AF_INET6; + else +#endif + $$->ipe_family = AF_INET; + } + | YY_STR { $$ = add_htablehosts($1); + free($1); } ; setgrouplist: - next { $$ = NULL; } + ';' { $$ = NULL; } | groupentry next { $$ = $1; } | groupentry next setgrouplist { $1->ipe_next = $3; $$ = $1; } ; groupentry: addrmask ',' setgroup { $$ = calloc(1, sizeof(iphtent_t)); - bcopy((char *)&($1[0]), - (char *)&($$->ipe_addr), - sizeof($$->ipe_addr)); - bcopy((char *)&($1[1]), - (char *)&($$->ipe_mask), - sizeof($$->ipe_mask)); + $$->ipe_addr = $1[0].adf_addr; + $$->ipe_mask = $1[1].adf_addr; strncpy($$->ipe_group, $3, FR_GROUPLEN); +#ifdef AF_INET6 + if (use_inet6) + $$->ipe_family = AF_INET6; + else +#endif + $$->ipe_family = AF_INET; free($3); } - | YY_STR { $$ = add_htablehosts($1); } ; -range: addrmask { $$ = calloc(1, sizeof(*$$)); - $$->ipn_info = 0; - $$->ipn_addr.adf_len = sizeof($$->ipn_addr); - $$->ipn_addr.adf_addr.in4.s_addr = $1[0].s_addr; - $$->ipn_mask.adf_len = sizeof($$->ipn_mask); - $$->ipn_mask.adf_addr.in4.s_addr = $1[1].s_addr; - } - | '!' addrmask { $$ = calloc(1, sizeof(*$$)); - $$->ipn_info = 1; - $$->ipn_addr.adf_len = sizeof($$->ipn_addr); - $$->ipn_addr.adf_addr.in4.s_addr = $2[0].s_addr; - $$->ipn_mask.adf_len = sizeof($$->ipn_mask); - $$->ipn_mask.adf_addr.in4.s_addr = $2[1].s_addr; - } - | YY_STR { $$ = add_poolhosts($1); } +range: addrmask { $$ = calloc(1, sizeof(*$$)); + $$->ipn_info = 0; + $$->ipn_addr = $1[0]; + $$->ipn_mask = $1[1]; + } + | '!' addrmask { $$ = calloc(1, sizeof(*$$)); + $$->ipn_info = 1; + $$->ipn_addr = $2[0]; + $$->ipn_mask = $2[1]; + } + | YY_STR { $$ = add_poolhosts($1); + free($1); + } + | IPT_WHOIS IPT_FILE YY_STR { $$ = read_whoisfile($3); + free($3); + } + ; hashlist: - next { $$ = NULL; } + ';' { $$ = NULL; } | hashentry next { $$ = $1; } | hashentry next hashlist { $1->ipe_next = $3; $$ = $1; } ; hashentry: - addrmask { $$ = calloc(1, sizeof(iphtent_t)); - bcopy((char *)&($1[0]), - (char *)&($$->ipe_addr), - sizeof($$->ipe_addr)); - bcopy((char *)&($1[1]), - (char *)&($$->ipe_mask), - sizeof($$->ipe_mask)); - } - | YY_STR { $$ = add_htablehosts($1); } + addrmask { $$ = calloc(1, sizeof(iphtent_t)); + $$->ipe_addr = $1[0].adf_addr; + $$->ipe_mask = $1[1].adf_addr; +#ifdef USE_INET6 + if (use_inet6) + $$->ipe_family = AF_INET6; + else +#endif + $$->ipe_family = AF_INET; + } + | YY_STR { $$ = add_htablehosts($1); + free($1); + } ; addrmask: - ipaddr '/' mask { $$[0] = $1; $$[1].s_addr = $3.s_addr; - yyexpectaddr = 0; + ipaddr '/' mask { $$[0] = $1; + setadflen(&$$[0]); + $$[1] = $3; + $$[1].adf_len = $$[0].adf_len; } - | ipaddr { $$[0] = $1; $$[1].s_addr = 0xffffffff; - yyexpectaddr = 0; + | ipaddr { $$[0] = $1; + setadflen(&$$[1]); + $$[1].adf_len = $$[0].adf_len; +#ifdef USE_INET6 + if (use_inet6) + memset(&$$[1].adf_addr, 0xff, + sizeof($$[1].adf_addr.in6)); + else +#endif + memset(&$$[1].adf_addr, 0xff, + sizeof($$[1].adf_addr.in4)); } ; -ipaddr: ipv4 { $$ = $1; } - | YY_NUMBER { $$.s_addr = htonl($1); } - ; - -mask: YY_NUMBER { ntomask(4, $1, (u_32_t *)&$$.s_addr); } - | ipv4 { $$ = $1; } - ; - -start: '{' { yyexpectaddr = 1; } - ; - -end: '}' { yyexpectaddr = 0; } +ipaddr: ipv4 { $$.adf_addr.in4 = $1; + $$.adf_family = AF_INET; + setadflen(&$$); + use_inet6 = 0; + } + | YY_NUMBER { $$.adf_addr.in4.s_addr = htonl($1); + $$.adf_family = AF_INET; + setadflen(&$$); + use_inet6 = 0; + } + | YY_IPV6 { $$.adf_addr = $1; + $$.adf_family = AF_INET6; + setadflen(&$$); + use_inet6 = 1; + } ; -next: ';' { yyexpectaddr = 1; } +mask: YY_NUMBER { bzero(&$$, sizeof($$)); + if (use_inet6) { + if (ntomask(AF_INET6, $1, + (u_32_t *)&$$.adf_addr) == -1) + yyerror("bad bitmask"); + } else { + if (ntomask(AF_INET, $1, + (u_32_t *)&$$.adf_addr.in4) == -1) + yyerror("bad bitmask"); + } + } + | ipv4 { bzero(&$$, sizeof($$)); + $$.adf_addr.in4 = $1; + } + | YY_IPV6 { bzero(&$$, sizeof($$)); + $$.adf_addr = $1; + } ; -size: IPT_SIZE '=' YY_NUMBER { ipht.iph_size = $3; } +size: IPT_SIZE '=' YY_NUMBER { ipht.iph_size = $3; } ; -seed: IPT_SEED '=' YY_NUMBER { ipht.iph_seed = $3; } +seed: IPT_SEED '=' YY_NUMBER { ipht.iph_seed = $3; } ; ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER @@ -334,26 +419,180 @@ ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER $$.s_addr = htonl($$.s_addr); } ; + +next: ';' { yyexpectaddr = 1; } + ; + +start: '{' { yyexpectaddr = 1; } + ; + +end: '}' { yyexpectaddr = 0; } + ; + +poolline: + IPT_POOL unit '/' IPT_DSTLIST '(' name ';' dstopts ')' + start dstlist end + { bzero((char *)&ipld, sizeof(ipld)); + strncpy(ipld.ipld_name, $6, + sizeof(ipld.ipld_name)); + ipld.ipld_unit = $2; + ipld.ipld_policy = $8; + load_dstlist(&ipld, poolioctl, $11); + resetlexer(); + use_inet6 = 0; + free($6); + } + | IPT_POOL unit '/' IPT_TREE '(' name ';' ')' + start addrlist end + { bzero((char *)&iplo, sizeof(iplo)); + strncpy(iplo.ipo_name, $6, + sizeof(iplo.ipo_name)); + iplo.ipo_list = $10; + iplo.ipo_unit = $2; + load_pool(&iplo, poolioctl); + resetlexer(); + use_inet6 = 0; + free($6); + } + | IPT_POOL '(' name ';' ')' start addrlist end + { bzero((char *)&iplo, sizeof(iplo)); + strncpy(iplo.ipo_name, $3, + sizeof(iplo.ipo_name)); + iplo.ipo_list = $7; + iplo.ipo_unit = IPL_LOGALL; + load_pool(&iplo, poolioctl); + resetlexer(); + use_inet6 = 0; + free($3); + } + | IPT_POOL unit '/' IPT_HASH '(' name ';' hashoptlist ')' + start hashlist end + { iphtent_t *h; + bzero((char *)&ipht, sizeof(ipht)); + strncpy(ipht.iph_name, $6, + sizeof(ipht.iph_name)); + ipht.iph_unit = $2; + load_hash(&ipht, $11, poolioctl); + while ((h = ipht.iph_list) != NULL) { + ipht.iph_list = h->ipe_next; + free(h); + } + resetlexer(); + use_inet6 = 0; + free($6); + } + | IPT_GROUPMAP '(' name ';' inout ';' ')' + start setgrouplist end + { iphtent_t *h; + bzero((char *)&ipht, sizeof(ipht)); + strncpy(ipht.iph_name, $3, + sizeof(ipht.iph_name)); + ipht.iph_type = IPHASH_GROUPMAP; + ipht.iph_unit = IPL_LOGIPF; + ipht.iph_flags = $5; + load_hash(&ipht, $9, poolioctl); + while ((h = ipht.iph_list) != NULL) { + ipht.iph_list = h->ipe_next; + free(h); + } + resetlexer(); + use_inet6 = 0; + free($3); + } + ; + +name: IPT_NAME YY_STR { $$ = $2; } + | IPT_NUM YY_NUMBER { char name[80]; + sprintf(name, "%d", $2); + $$ = strdup(name); + } + ; + +hashoptlist: + | hashopt ';' + | hashoptlist ';' hashopt ';' + ; +hashopt: + IPT_SIZE YY_NUMBER + | IPT_SEED YY_NUMBER + ; + +dstlist: + dstentries { $$ = $1; } + | ';' { $$ = NULL; } + ; + +dstentries: + dstentry next { $$ = $1; } + | dstentry next dstentries { $1->ipfd_next = $3; $$ = $1; } + ; + +dstentry: + YY_STR ':' ipaddr { int size = sizeof(*$$) + strlen($1) + 1; + $$ = calloc(1, size); + if ($$ != NULL) { + $$->ipfd_dest.fd_name = strlen($1) + 1; + bcopy($1, $$->ipfd_names, + $$->ipfd_dest.fd_name); + $$->ipfd_dest.fd_addr = $3; + $$->ipfd_size = size; + } + free($1); + } + | ipaddr { $$ = calloc(1, sizeof(*$$)); + if ($$ != NULL) { + $$->ipfd_dest.fd_name = -1; + $$->ipfd_dest.fd_addr = $1; + $$->ipfd_size = sizeof(*$$); + } + } + ; + +dstopts: + { $$ = IPLDP_NONE; } + | IPT_POLICY IPT_ROUNDROBIN ';' { $$ = IPLDP_ROUNDROBIN; } + | IPT_POLICY IPT_WEIGHTED weighting ';' { $$ = $3; } + | IPT_POLICY IPT_RANDOM ';' { $$ = IPLDP_RANDOM; } + | IPT_POLICY IPT_HASH ';' { $$ = IPLDP_HASHED; } + | IPT_POLICY IPT_SRCHASH ';' { $$ = IPLDP_SRCHASH; } + | IPT_POLICY IPT_DSTHASH ';' { $$ = IPLDP_DSTHASH; } + ; + +weighting: + IPT_CONNECTION { $$ = IPLDP_CONNECTION; } + ; %% static wordtab_t yywords[] = { - { "auth", IPT_AUTH }, - { "count", IPT_COUNT }, - { "group", IPT_GROUP }, - { "group-map", IPT_GROUPMAP }, - { "hash", IPT_HASH }, - { "in", IPT_IN }, - { "ipf", IPT_IPF }, - { "name", IPT_NAME }, - { "nat", IPT_NAT }, - { "number", IPT_NUM }, - { "out", IPT_OUT }, - { "role", IPT_ROLE }, - { "seed", IPT_SEED }, - { "size", IPT_SIZE }, - { "table", IPT_TABLE }, - { "tree", IPT_TREE }, - { "type", IPT_TYPE }, - { NULL, 0 } + { "all", IPT_ALL }, + { "auth", IPT_AUTH }, + { "connection", IPT_CONNECTION }, + { "count", IPT_COUNT }, + { "dst-hash", IPT_DSTHASH }, + { "dstlist", IPT_DSTLIST }, + { "file", IPT_FILE }, + { "group", IPT_GROUP }, + { "group-map", IPT_GROUPMAP }, + { "hash", IPT_HASH }, + { "in", IPT_IN }, + { "ipf", IPT_IPF }, + { "name", IPT_NAME }, + { "nat", IPT_NAT }, + { "number", IPT_NUM }, + { "out", IPT_OUT }, + { "policy", IPT_POLICY }, + { "pool", IPT_POOL }, + { "random", IPT_RANDOM }, + { "round-robin", IPT_ROUNDROBIN }, + { "role", IPT_ROLE }, + { "seed", IPT_SEED }, + { "size", IPT_SIZE }, + { "src-hash", IPT_SRCHASH }, + { "table", IPT_TABLE }, + { "tree", IPT_TREE }, + { "type", IPT_TYPE }, + { "weighted", IPT_WEIGHTED }, + { "whois", IPT_WHOIS }, + { NULL, 0 } }; @@ -439,8 +678,9 @@ char *url; if (hlist == NULL) return NULL; - if (gethost(url, &hlist->al_addr) == -1) + if (gethost(hlist->al_family, url, &hlist->al_i6addr) == -1) { yyerror("Unknown hostname"); + } } hbot = NULL; @@ -451,10 +691,9 @@ char *url; if (h == NULL) break; - bcopy((char *)&a->al_addr, (char *)&h->ipe_addr, - sizeof(h->ipe_addr)); - bcopy((char *)&a->al_mask, (char *)&h->ipe_mask, - sizeof(h->ipe_mask)); + h->ipe_family = a->al_family; + h->ipe_addr = a->al_i6addr; + h->ipe_mask = a->al_i6mask; if (hbot != NULL) hbot->ipe_next = h; @@ -485,8 +724,9 @@ char *url; if (hlist == NULL) return NULL; - if (gethost(url, &hlist->al_addr) == -1) + if (gethost(hlist->al_family, url, &hlist->al_i6addr) == -1) { yyerror("Unknown hostname"); + } } pbot = NULL; @@ -496,16 +736,19 @@ char *url; p = calloc(1, sizeof(*p)); if (p == NULL) break; + p->ipn_mask.adf_addr = a->al_i6mask; - p->ipn_addr.adf_len = 8; - p->ipn_mask.adf_len = 8; - + if (a->al_family == AF_INET) { + p->ipn_addr.adf_family = AF_INET; +#ifdef USE_INET6 + } else if (a->al_family == AF_INET6) { + p->ipn_addr.adf_family = AF_INET6; +#endif + } + setadflen(&p->ipn_addr); + p->ipn_addr.adf_addr = a->al_i6addr; p->ipn_info = a->al_not; - - bcopy((char *)&a->al_addr, (char *)&p->ipn_addr.adf_addr, - sizeof(p->ipn_addr.adf_addr)); - bcopy((char *)&a->al_mask, (char *)&p->ipn_mask.adf_addr, - sizeof(p->ipn_mask.adf_addr)); + p->ipn_mask.adf_len = p->ipn_addr.adf_len; if (pbot != NULL) pbot->ipn_next = p; @@ -518,3 +761,59 @@ char *url; return ptop; } + + +ip_pool_node_t * +read_whoisfile(file) + char *file; +{ + ip_pool_node_t *ntop, *ipn, node, *last; + char line[1024]; + FILE *fp; + + fp = fopen(file, "r"); + if (fp == NULL) + return NULL; + + last = NULL; + ntop = NULL; + while (fgets(line, sizeof(line) - 1, fp) != NULL) { + line[sizeof(line) - 1] = '\0'; + + if (parsewhoisline(line, &node.ipn_addr, &node.ipn_mask)) + continue; + ipn = calloc(1, sizeof(*ipn)); + if (ipn == NULL) + continue; + ipn->ipn_addr = node.ipn_addr; + ipn->ipn_mask = node.ipn_mask; + if (last == NULL) + ntop = ipn; + else + last->ipn_next = ipn; + last = ipn; + } + fclose(fp); + return ntop; +} + + +static void +setadflen(afp) + addrfamily_t *afp; +{ + afp->adf_len = offsetof(addrfamily_t, adf_addr); + switch (afp->adf_family) + { + case AF_INET : + afp->adf_len += sizeof(struct in_addr); + break; +#ifdef USE_INET6 + case AF_INET6 : + afp->adf_len += sizeof(struct in6_addr); + break; +#endif + default : + break; + } +} diff --git a/tools/ipscan_y.y b/tools/ipscan_y.y index 5d7e7e66bcd9c..c3fc0eb2fa68d 100644 --- a/tools/ipscan_y.y +++ b/tools/ipscan_y.y @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001-2004 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -11,6 +11,7 @@ #include "kmem.h" #include "ipscan_l.h" #include "netinet/ip_scan.h" +#include <ctype.h> #define YYDEBUG 1 @@ -58,7 +59,7 @@ int fd = -1; %token <num> YY_NUMBER YY_HEX %token <str> YY_STR -%token YY_COMMENT +%token YY_COMMENT %token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT %token YY_RANGE_OUT YY_RANGE_IN %token <ip6> YY_IPV6 diff --git a/tools/ipsyncm.c b/tools/ipsyncm.c index fc79abb9a11f6..5aa43832b3262 100644 --- a/tools/ipsyncm.c +++ b/tools/ipsyncm.c @@ -1,11 +1,11 @@ /* - * Copyright (C) 2001-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #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: ipsyncm.c,v 1.4.2.5 2006/08/26 11:21:14 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #include <sys/types.h> #include <sys/time.h> @@ -47,13 +47,13 @@ static void handleterm(int sig) } #endif - + /* should be large enough to hold header + any datatype */ #define BUFFERLEN 1400 int main(argc, argv) -int argc; -char *argv[]; + int argc; + char *argv[]; { struct sockaddr_in sin; char buff[BUFFERLEN]; @@ -64,14 +64,14 @@ char *argv[]; u_32_t magic; synchdr_t *sh; char *progname; - + progname = strrchr(argv[0], '/'); if (progname) { progname++; } else { progname = argv[0]; } - + if (argc < 2) { usage(progname); @@ -106,13 +106,13 @@ char *argv[]; syslog(LOG_ERR, "Opening %s :%m", IPSYNC_NAME); goto tryagain; } - + nfd = socket(AF_INET, SOCK_DGRAM, 0); if (nfd == -1) { syslog(LOG_ERR, "Socket :%m"); goto tryagain; } - + if (connect(nfd, (struct sockaddr *)&sin, sizeof(sin)) == -1) { syslog(LOG_ERR, "Connect: %m"); goto tryagain; @@ -120,15 +120,15 @@ char *argv[]; syslog(LOG_INFO, "Sending data to %s", inet_ntoa(sin.sin_addr)); - - inbuf = 0; + + inbuf = 0; while (1) { n1 = read(lfd, buff+inbuf, BUFFERLEN-inbuf); - + printf("header : %d bytes read (header = %d bytes)\n", - n1, sizeof(*sh)); - + n1, (int) sizeof(*sh)); + if (n1 < 0) { syslog(LOG_ERR, "Read error (header): %m"); goto tryagain; @@ -141,8 +141,8 @@ char *argv[]; sleep(1); continue; } - - inbuf += n1; + + inbuf += n1; moreinbuf: if (inbuf < sizeof(*sh)) { @@ -151,7 +151,7 @@ moreinbuf: sh = (synchdr_t *)buff; len = ntohl(sh->sm_len); - magic = ntohl(sh->sm_magic); + magic = ntohl(sh->sm_magic); if (magic != SYNHDRMAGIC) { syslog(LOG_ERR, @@ -179,8 +179,8 @@ moreinbuf: printf(" table:Unknown(%d)", sh->sm_table); printf(" num:%d\n", (u_32_t)ntohl(sh->sm_num)); -#endif - +#endif + if (inbuf < sizeof(*sh) + len) { continue; /* need more data */ goto tryagain; @@ -193,9 +193,9 @@ moreinbuf: } else if (sh->sm_cmd == SMC_UPDATE) { su = (syncupdent_t *)buff; if (sh->sm_p == IPPROTO_TCP) { - printf(" TCP Update: age %lu state %d/%d\n", + printf(" TCP Update: age %lu state %d/%d\n", su->sup_tcp.stu_age, - su->sup_tcp.stu_state[0], + su->sup_tcp.stu_state[0], su->sup_tcp.stu_state[1]); } } else { @@ -210,7 +210,7 @@ moreinbuf: goto tryagain; } - + if (n3 != n2) { syslog(LOG_ERR, "Incomplete write (%d/%d)", n3, n2); @@ -224,7 +224,7 @@ moreinbuf: /* move buffer to the front,we might need to make * this more efficient, by using a rolling pointer * over the buffer and only copying it, when - * we are reaching the end + * we are reaching the end */ inbuf -= n2; if (inbuf) { diff --git a/tools/ipsyncs.c b/tools/ipsyncs.c index 3a8270fc4b2f8..9bec21b0acdd7 100644 --- a/tools/ipsyncs.c +++ b/tools/ipsyncs.c @@ -1,11 +1,11 @@ /* - * Copyright (C) 2001-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #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: ipsyncs.c,v 1.5.2.4 2006/08/26 11:21:15 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #include <sys/types.h> #include <sys/time.h> @@ -52,10 +52,10 @@ static void handleterm(int sig) #define BUFFERLEN 1400 int main(argc, argv) -int argc; -char *argv[]; + int argc; + char *argv[]; { - int nfd = -1 , lfd = -1; + int nfd = -1 , lfd = -1; int n1, n2, n3, magic, len, inbuf; struct sockaddr_in sin; struct sockaddr_in in; @@ -64,14 +64,14 @@ char *argv[]; syncupdent_t *su; synchdr_t *sh; char *progname; - + progname = strrchr(argv[0], '/'); if (progname) { progname++; } else { progname = argv[0]; } - + if (argc < 2) { usage(progname); exit(1); @@ -84,7 +84,7 @@ char *argv[]; #endif openlog(progname, LOG_PID, LOG_SECURITY); - + lfd = open(IPSYNC_NAME, O_WRONLY); if (lfd == -1) { syslog(LOG_ERR, "Opening %s :%m", IPSYNC_NAME); @@ -99,14 +99,14 @@ char *argv[]; sin.sin_port = htons(atoi(argv[2])); else sin.sin_port = htons(43434); - if (argc > 3) + if (argc > 3) in.sin_addr.s_addr = inet_addr(argv[3]); else in.sin_addr.s_addr = 0; in.sin_port = 0; while(1) { - + if (lfd != -1) close(lfd); if (nfd != -1) @@ -117,7 +117,7 @@ char *argv[]; syslog(LOG_ERR, "Opening %s :%m", IPSYNC_NAME); goto tryagain; } - + nfd = socket(AF_INET, SOCK_DGRAM, 0); if (nfd == -1) { syslog(LOG_ERR, "Socket :%m"); @@ -133,20 +133,20 @@ char *argv[]; } syslog(LOG_INFO, "Listening to %s", inet_ntoa(sin.sin_addr)); - - inbuf = 0; + + inbuf = 0; while (1) { - /* + /* * XXX currently we do not check the source address * of a datagram, this can be a security risk */ n1 = read(nfd, buff+inbuf, BUFFERLEN-inbuf); - + printf("header : %d bytes read (header = %d bytes)\n", - n1, sizeof(*sh)); - + n1, (int) sizeof(*sh)); + if (n1 < 0) { syslog(LOG_ERR, "Read error (header): %m"); goto tryagain; @@ -159,8 +159,8 @@ char *argv[]; sleep(1); continue; } - - inbuf += n1; + + inbuf += n1; moreinbuf: if (inbuf < sizeof(*sh)) { @@ -169,7 +169,7 @@ moreinbuf: sh = (synchdr_t *)buff; len = ntohl(sh->sm_len); - magic = ntohl(sh->sm_magic); + magic = ntohl(sh->sm_magic); if (magic != SYNHDRMAGIC) { syslog(LOG_ERR, "Invalid header magic %x", @@ -197,8 +197,8 @@ moreinbuf: printf(" table:Unknown(%d)", sh->sm_table); printf(" num:%d\n", (u_32_t)ntohl(sh->sm_num)); -#endif - +#endif + if (inbuf < sizeof(*sh) + len) { continue; /* need more data */ goto tryagain; @@ -211,9 +211,9 @@ moreinbuf: } else if (sh->sm_cmd == SMC_UPDATE) { su = (syncupdent_t *)buff; if (sh->sm_p == IPPROTO_TCP) { - printf(" TCP Update: age %lu state %d/%d\n", + printf(" TCP Update: age %lu state %d/%d\n", su->sup_tcp.stu_age, - su->sup_tcp.stu_state[0], + su->sup_tcp.stu_state[0], su->sup_tcp.stu_state[1]); } } else { @@ -229,7 +229,7 @@ moreinbuf: goto tryagain; } - + if (n3 != n2) { syslog(LOG_ERR, "%s: Incomplete write (%d/%d)", IPSYNC_NAME, n3, n2); @@ -243,7 +243,7 @@ moreinbuf: /* move buffer to the front,we might need to make * this more efficient, by using a rolling pointer * over the buffer and only copying it, when - * we are reaching the end + * we are reaching the end */ inbuf -= n2; if (inbuf) { diff --git a/tools/lex_var.h b/tools/lex_var.h index a6f9cf6a78e56..094be9a8530a9 100644 --- a/tools/lex_var.h +++ b/tools/lex_var.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ diff --git a/tools/lexer.c b/tools/lexer.c index 1ad00c4c06f7d..06d93ab1dc649 100644 --- a/tools/lexer.c +++ b/tools/lexer.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -40,6 +40,7 @@ char yychars[YYBUFSIZ+1]; int yylineNum = 1; int yypos = 0; int yylast = -1; +int yydictfixed = 0; int yyexpectaddr = 0; int yybreakondot = 0; int yyvarnext = 0; @@ -58,7 +59,7 @@ static void yystrtotext __P((char *)); static char *yytexttochar __P((void)); static int yygetc(docont) -int docont; + int docont; { int c; @@ -96,7 +97,7 @@ int docont; static void yyunputc(c) -int c; + int c; { if (c == '\n') yylineNum--; @@ -105,7 +106,7 @@ int c; static int yyswallow(last) -int last; + int last; { int c; @@ -132,7 +133,7 @@ static char *yytexttochar() static void yystrtotext(str) -char *str; + char *str; { int len; char *s; @@ -148,7 +149,7 @@ char *str; static char *yytexttostr(offset, max) -int offset, max; + int offset, max; { char *str; int i; @@ -173,8 +174,11 @@ int offset, max; int yylex() { + static int prior = 0; + static int priornum = 0; int c, n, isbuilding, rval, lnext, nokey = 0; char *name; + int triedv6 = 0; isbuilding = 0; lnext = 0; @@ -188,7 +192,8 @@ int yylex() nextchar: c = yygetc(0); if (yydebug > 1) - printf("yygetc = (%x) %c [%*.*s]\n", c, c, yypos, yypos, yytexttochar()); + printf("yygetc = (%x) %c [%*.*s]\n", + c, c, yypos, yypos, yytexttochar()); switch (c) { @@ -207,6 +212,8 @@ nextchar: sizeof(yytext[0]) * (yylast - yypos + 1)); } yylast -= yypos; + if (yyexpectaddr == 2) + yyexpectaddr = 0; yypos = 0; lnext = 0; nokey = 0; @@ -230,6 +237,7 @@ nextchar: if (lnext == 1) { lnext = 0; if ((isbuilding == 0) && !ISALNUM(c)) { + prior = c; return c; } goto nextchar; @@ -244,7 +252,7 @@ nextchar: } yyswallow('\n'); rval = YY_COMMENT; - goto nextchar; + goto done; case '$' : if (isbuilding == 1) { @@ -318,6 +326,9 @@ nextchar: yybreakondot = 0; yyvarnext = 0; yytokentype = 0; + if (yydebug) + fprintf(stderr, "reset at EOF\n"); + prior = 0; return 0; } @@ -342,16 +353,21 @@ nextchar: switch (c) { case '-' : - if (yyexpectaddr) - break; - if (isbuilding == 1) - break; n = yygetc(0); if (n == '>') { isbuilding = 1; goto done; } yyunputc(n); + if (yyexpectaddr) { + if (isbuilding == 1) + yyunputc(c); + else + rval = '-'; + goto done; + } + if (isbuilding == 1) + break; rval = '-'; goto done; @@ -418,14 +434,21 @@ nextchar: * 0000:0000:0000:0000:0000:0000:0000:0000 */ #ifdef USE_INET6 - if (yyexpectaddr == 1 && isbuilding == 0 && (ishex(c) || c == ':')) { + if (yyexpectaddr != 0 && isbuilding == 0 && + (ishex(c) || isdigit(c) || c == ':')) { char ipv6buf[45 + 1], *s, oc; int start; +buildipv6: start = yypos; s = ipv6buf; oc = c; + if (prior == YY_NUMBER && c == ':') { + sprintf(s, "%d", priornum); + s += strlen(s); + } + /* * Perhaps we should implement stricter controls on what we * swallow up here, but surely it would just be duplicating @@ -449,7 +472,25 @@ nextchar: } #endif - if (c == ':') { + if ((c == ':') && (rval != YY_IPV6) && (triedv6 == 0)) { +#ifdef USE_INET6 + yystr = yytexttostr(0, yypos - 1); + if (yystr != NULL) { + char *s; + + for (s = yystr; *s && ishex(*s); s++) + ; + if (!*s && *yystr) { + isbuilding = 0; + c = *yystr; + free(yystr); + triedv6 = 1; + yypos = 1; + goto buildipv6; + } + free(yystr); + } +#endif if (isbuilding == 1) { yyunputc(c); goto done; @@ -490,8 +531,8 @@ done: yystr = yytexttostr(0, yypos); if (yydebug) - printf("isbuilding %d yyvarnext %d nokey %d\n", - isbuilding, yyvarnext, nokey); + printf("isbuilding %d yyvarnext %d nokey %d fixed %d addr %d\n", + isbuilding, yyvarnext, nokey, yydictfixed, yyexpectaddr); if (isbuilding == 1) { wordtab_t *w; @@ -500,7 +541,7 @@ done: if ((yyvarnext == 0) && (nokey == 0)) { w = yyfindkey(yystr); - if (w == NULL && yywordtab != NULL) { + if (w == NULL && yywordtab != NULL && !yydictfixed) { yyresetdict(); w = yyfindkey(yystr); } @@ -512,14 +553,19 @@ done: rval = YY_STR; } - if (rval == YY_STR && yysavedepth > 0) - yyresetdict(); + if (rval == YY_STR) { + if (yysavedepth > 0 && !yydictfixed) + yyresetdict(); + if (yyexpectaddr != 0) + yyexpectaddr = 0; + } yytokentype = rval; if (yydebug) - printf("lexed(%s) [%d,%d,%d] => %d @%d\n", yystr, string_start, - string_end, pos, rval, yysavedepth); + printf("lexed(%s) %d,%d,%d [%d,%d,%d] => %d @%d\n", + yystr, isbuilding, yyexpectaddr, yysavedepth, + string_start, string_end, pos, rval, yysavedepth); switch (rval) { @@ -546,12 +592,15 @@ done: yypos = 0; } + if (rval == YY_NUMBER) + priornum = yylval.num; + prior = rval; return rval; } static wordtab_t *yyfindkey(key) -char *key; + char *key; { wordtab_t *w; @@ -566,7 +615,7 @@ char *key; char *yykeytostr(num) -int num; + int num; { wordtab_t *w; @@ -581,7 +630,7 @@ int num; wordtab_t *yysettab(words) -wordtab_t *words; + wordtab_t *words; { wordtab_t *save; @@ -592,7 +641,7 @@ wordtab_t *words; void yyerror(msg) -char *msg; + char *msg; { char *txt, letter[2]; int freetxt = 0; @@ -618,9 +667,31 @@ char *msg; } +void yysetfixeddict(newdict) + wordtab_t *newdict; +{ + if (yydebug) + printf("yysetfixeddict(%lx)\n", (u_long)newdict); + + if (yysavedepth == sizeof(yysavewords)/sizeof(yysavewords[0])) { + fprintf(stderr, "%d: at maximum dictionary depth\n", + yylineNum); + return; + } + + yysavewords[yysavedepth++] = yysettab(newdict); + if (yydebug) + printf("yysavedepth++ => %d\n", yysavedepth); + yydictfixed = 1; +} + + void yysetdict(newdict) -wordtab_t *newdict; + wordtab_t *newdict; { + if (yydebug) + printf("yysetdict(%lx)\n", (u_long)newdict); + if (yysavedepth == sizeof(yysavewords)/sizeof(yysavewords[0])) { fprintf(stderr, "%d: at maximum dictionary depth\n", yylineNum); @@ -641,14 +712,15 @@ void yyresetdict() if (yydebug) printf("yysavedepth-- => %d\n", yysavedepth); } + yydictfixed = 0; } #ifdef TEST_LEXER int main(argc, argv) -int argc; -char *argv[]; + int argc; + char *argv[]; { int n; diff --git a/tools/lexer.h b/tools/lexer.h index b838d41571c97..38ad3f077d24e 100644 --- a/tools/lexer.h +++ b/tools/lexer.h @@ -1,14 +1,9 @@ /* - * Copyright (C) 2002-2004 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ -typedef struct wordtab { - char *w_word; - int w_value; -} wordtab_t; - #ifdef NO_YACC #define YY_COMMENT 1000 #define YY_CMP_NE 1001 @@ -27,6 +22,7 @@ typedef struct wordtab { extern wordtab_t *yysettab __P((wordtab_t *)); extern void yysetdict __P((wordtab_t *)); +extern void yysetfixeddict __P((wordtab_t *)); extern int yylex __P((void)); extern void yyerror __P((char *)); extern char *yykeytostr __P((int)); diff --git a/tru64.c b/tru64.c new file mode 100644 index 0000000000000..3aeb2854d4c23 --- /dev/null +++ b/tru64.c @@ -0,0 +1,1281 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ +#if !defined(lint) +static const char rcsid[] = "@(#)$Id$"; +#endif +#include <sys/types.h> +#include <sys/conf.h> +#include <sys/sysconfig.h> +#include <machine/machlimits.h> +#include <net/net_globals.h> +#include <io/common/iotypes.h> +#include <sys/errno.h> +#include <sys/buf.h> +#include <sys/secdefines.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/fcntl.h> +#include <sys/ioctl.h> +#include <sys/disklabel.h> +#include <sys/user.h> +#include <sys/socket.h> +#include <sys/sysmacros.h> +#include <sys/syslog.h> +#include <sys/select.h> +#include <io/common/pt.h> +#include <io/common/devdriver.h> +#include <io/common/devio.h> +#include <io/common/devgetinfo.h> + +#include <net/if.h> +#include <netinet/ip.h> +#include <netinet/ip_stat.h> +#include <netinet/in.h> +#include <netinet/firewall.h> + +#include <netinet/if_ether.h> +#include <net/ether_driver.h> + +#include "ip_compat.h" +#include "ip_fil.h" +#include "ip_nat.h" +#include "ip_state.h" +#include "ip_frag.h" +#include "ip_auth.h" +#include "ip_compat.h" +#include "ip_fil.h" + +/* #undef IPFDEBUG */ + +static int ipfopen(dev_t dev, int flags); +static int ipfclose(dev_t dev, int flags); +static int ipfread(dev_t dev, struct uio *); + +/* function prototypes */ +int ipfilter_attach(void); +int ipfilter_detach(void); +void ipfilter_ifattach(void); +void ipfilter_ifdetach(void); +int ipfilter_ifioctl(struct ifnet *, unsigned int, caddr_t); +#if TRU64 >= 1885 +int ipfilter_ifoutput(struct ifnet *, struct mbuf *, struct sockaddr *, + struct rtentry *, char *); +#else +int ipfilter_ifoutput(struct ifnet *, struct mbuf *, struct sockaddr *, + struct rtentry *); +#endif +void ipfilter_in_control(struct socket *, u_int, caddr_t *, struct ifnet *); +void ipfilter_ip_input(struct mbuf *m); +int ipfilter_ip_output(struct ifnet *, struct mbuf *, struct in_route *, + int, struct ip_moptions *); +void ipfilter_configure_callback __P((int, int, int, int)); +void ipfilter_timer(void); +void ipfilter_clock(void *arg); +int ipfilteropen(dev_t, int, int); +int ipfilterread(dev_t, struct uio *, int); +int ipfilterclose(dev_t, int, int); +int ipfilterwrite(dev_t, struct uio *); +int ipfilterioctl(dev_t, u_int, caddr_t, int); + +extern int nodev(), nulldev(); +extern task_t first_task; +extern ipfrwlock_t ipf_tru64; +extern void ipf_timer_func __P((void *)); + +struct dsent ipfilter_devsw_entry = { + ipfilteropen, + ipfilterclose, + nodev, /* d_strategy */ + ipfilterread, + ipfilterwrite, + ipfilterioctl, + nodev, /* d_dump */ + nodev, /* d_psize */ + nulldev, /* d_stop */ + nulldev, /* d_reset */ + nulldev, /* d_select */ + 0, /* d_mmap */ + 0, /* d_segmap */ + NULL, /* d_ttys */ + DEV_FUNNEL_NULL,/* SMP-safe */ + 0, /* d_bflags */ + 0 /* d_cflags */ +}; + +ipf_main_softc_t ipfmain; + +struct controller *ipfilter_info[IPL_LOGSIZE]; +static char ipfilter_name[] = "ipfilter"; + +struct driver ipfdriver = { + NULL, /* probe */ + NULL, /* slave */ + NULL, /* cattach */ + NULL, /* dattach */ + 0, /* go */ + 0, /* addr_list */ + 0, /* dev_name */ + 0, /* dev_list */ + ipfilter_name, /* ctlr_name */ + ipfilter_info, /* ctlr_list */ + 0, /* Want exclusive use of bdp's flag */ + 0, /* Size of first csr area */ + 0, /* Address space of first csr area */ + 0, /* Size of second csr area */ + 0, /* Address space of second csr area */ + NULL, /* controller unattach routine */ + + NULL, /* dev_unattach */ +}; + +#define NO_DEV -1 +#define MAJOR_INSTANCE 1 +#define IPF_NAME "ipf" + +int ipfilter_config = FALSE; +int ipfilter_devno = NO_DEV; +int ipfilter_num_units=1; +int ipfilter_dev_number = NO_DEV; +int callback_return_status = ESUCCESS; +int driver_cfg_state; +int ipfilter_is_dynamic; + +/* Variables referenced by attributes. 'majnum' must + * be present to inform cfgmgr that this is a 5.0A + * driver. 'ipfilter_version' is used to keep track of the version + * numbers during development. It is printed out after + * configure to indicate which version is being loaded. + */ +static int majnum = NO_DEV; +static int ipfilter_num_installed = 1; +static u_char ipfilter_desc[100] = "IPFilter firewall"; +static u_char ipfilter_unused[300] = ""; +static thread_t ipf_timeout = 0; + +/* protos for functions used in configuration */ +void ipfilter_print_attr_error __P((cfg_attr_t *)); +void ipfilter_preconfig_callback __P((int, int, ulong, ulong)); +void ipfilter_postconfig_callback __P((int, int, ulong, ulong)); + + +struct firewall_stat { + u_long in_control_called; + u_long ip_input_mbufs; + u_long ip_input_accept; + u_long ip_input_reject; + u_long ip_input_tooshort; + u_long ip_input_toosmall; + u_long ip_input_badlen; + u_long ip_input_badhlen; + u_long ip_input_badvers; + u_long ip_input_badsum; + u_long ip_output_mbufs; + u_long ip_output_accept; + u_long ip_output_reject; +}; +struct firewall_stat ipfilter_stat; +static int ipfilter_registered = 0; +static int ipftru64_inited = 0; + + +cfg_subsys_attr_t ipfilter_attributes[] = { + +{ "Subsystem_Description",CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE | CFG_OP_QUERY, + (caddr_t)ipfilter_desc, 2, 300, 0 }, +{ "Module_Config_Name", CFG_ATTR_STRTYPE, CFG_OP_QUERY, + (caddr_t)"ipfilter", 2, CFG_ATTR_NAME_SZ, 0 }, +{ "majnum", CFG_ATTR_INTTYPE, CFG_OP_QUERY, + (caddr_t)&majnum, 0, 512, 0 }, +{ "Num_Installed", CFG_ATTR_INTTYPE, CFG_OP_QUERY, + (caddr_t)&ipfilter_num_installed, 1, 1, 1 }, +{ "Num_Units", CFG_ATTR_INTTYPE, CFG_OP_QUERY | CFG_OP_CONFIGURE, + (caddr_t)&ipfilter_num_units, + 1, IPL_LOGSIZE, 0 }, +{ "Module_Type", CFG_ATTR_STRTYPE, CFG_OP_QUERY | CFG_OP_CONFIGURE, + (caddr_t)ipfilter_unused, + 2, CFG_ATTR_NAME_SZ, 0 }, +{ "Device_Major_Req", CFG_ATTR_STRTYPE, CFG_OP_QUERY | CFG_OP_CONFIGURE, + (caddr_t)ipfilter_unused, + 0, sizeof(ipfilter_unused), 0 }, +{ "Device_Char_Major", CFG_ATTR_STRTYPE, CFG_OP_QUERY | CFG_OP_CONFIGURE, + (caddr_t)ipfilter_unused, + 0, sizeof(ipfilter_unused), 0 }, +{ "Device_Char_Files", CFG_ATTR_STRTYPE, CFG_OP_QUERY | CFG_OP_CONFIGURE, + (caddr_t)ipfilter_unused, + 0, sizeof(ipfilter_unused), 0 }, +{ "Device_Char_Minor", CFG_ATTR_STRTYPE, CFG_OP_QUERY | CFG_OP_CONFIGURE, + (caddr_t)ipfilter_unused, 0, + sizeof(ipfilter_unused), 0 }, +{ "version", CFG_ATTR_STRTYPE, CFG_OP_QUERY, + (caddr_t)ipfilter_version, 0, 5, 0 }, +{ "ipf_chksrc", CFG_ATTR_INTTYPE, CFG_OP_QUERY | + CFG_OP_CONFIGURE | CFG_OP_RECONFIGURE, + (caddr_t)&ipfmain.ipf_chksrc, + 0, 1, 0 }, +{ "ipf_minttl", CFG_ATTR_INTTYPE, CFG_OP_QUERY | + CFG_OP_CONFIGURE | CFG_OP_RECONFIGURE, + (caddr_t)&ipfmain.ipf_minttl, + 0, 255, 0 }, +{ "ipf_pass", CFG_ATTR_INTTYPE, CFG_OP_QUERY | + CFG_OP_CONFIGURE | CFG_OP_RECONFIGURE, + (caddr_t)&ipfmain.ipf_minttl, + 0, 0xffffffff, 0 }, +{ "ipf_flags", CFG_ATTR_INTTYPE, CFG_OP_QUERY | + CFG_OP_CONFIGURE | CFG_OP_RECONFIGURE, + (caddr_t)&ipfmain.ipf_flags, + 0, 0xffffffff, 0 }, +{ "ipf_active", CFG_ATTR_INTTYPE, CFG_OP_QUERY, + (caddr_t)&ipfmain.ipf_minttl, + 0, 1, 0 }, +{ "ipf_running", CFG_ATTR_INTTYPE, CFG_OP_QUERY, + (caddr_t)&ipfmain.ipf_minttl, + 0, 1, 0 }, +{ "ipf_control_forwarding", + CFG_ATTR_INTTYPE, CFG_OP_QUERY | + CFG_OP_CONFIGURE | CFG_OP_RECONFIGURE, + (caddr_t) &ipfmain.ipf_control_forwarding, + 0, 1, 0 }, +{ "ipf_update_ipid", CFG_ATTR_INTTYPE, CFG_OP_QUERY | + CFG_OP_CONFIGURE | CFG_OP_RECONFIGURE, + (caddr_t) &ipfmain.ipf_update_ipid, + 0, 1, 0 }, +{ "", 0, 0, 0, 0, 0, 0 } +}; + + +/*--------------------------------------------------------- + * Configure interface + * 1 - Handle attribute verification. + * 2 - Handle the differences between static and dynamic + * configuration. + * Returns: EBUSY,EINVAL,ENOTSUP,ESRCH for fail, + * ESUCCESS for success + *--------------------------------------------------------*/ +cfg_status_t ipfilter_configure(op, indata, indata_size, outdata, outdata_size) + cfg_op_t op; + caddr_t indata; + ulong indata_size; + caddr_t outdata; + ulong outdata_size; +{ + int ipfilter_cfg_state; + cfg_attr_t *attr_ptr; + int status, i; + +#ifdef IPFDEBUG + printf("ipfilter_configure(%x,%x,%d,%x,%d)\n", + op, indata, indata_size, outdata, outdata_size); +#endif + + status = ESUCCESS; + + if (cfgmgr_get_state("ipfilter", &ipfilter_cfg_state) != ESUCCESS) { + printf("ipfilter cfgmgr_get_state failed\n"); + return EINVAL; + } + + switch (op) + { + case CFG_OP_CONFIGURE : +#ifdef IPFDEBUG + printf("ipfilter_config=%d\n",ipfilter_config); + printf("driver_cfg_state=%d\n",driver_cfg_state); +#endif + if (ipfilter_config == TRUE) { + /* + * We have already been configured + */ + return EINVAL; + } + /* + * cfgmgr takes care of error checking, but we have to + * investigate what happened and report to user. + */ + attr_ptr = (cfg_attr_t *)indata; + for(i = 0; i < indata_size; i++) { + switch(attr_ptr->type) + { + case CFG_ATTR_STRTYPE: + break; + default: + switch(attr_ptr->status) + { + case CFG_FRAME_SUCCESS: + break; + default: + ipfilter_print_attr_error(attr_ptr); + break; + } + } + attr_ptr++; + } + + if (cfgmgr_get_state((char *)ipfilter_name, + &driver_cfg_state) != ESUCCESS) { + printf("ipfilter_conf:Error determining state of ipf subsystem\n"); + /* + * Error determining state of the "ipf" subs.. + */ + return(EINVAL); + } + + if (driver_cfg_state == SUBSYSTEM_STATICALLY_CONFIGURED) { + callback_return_status = ESUCCESS; + ipfilter_is_dynamic = 0; + status = register_callback(ipfilter_configure_callback, + CFG_PT_OLD_CONF_ALL, + CFG_ORD_DONTCARE, 0L); + if (status != ESUCCESS) + break; + status = register_callback(ipfilter_preconfig_callback, + CFG_PT_PRECONFIG, + CFG_ORD_NOMINAL, 0L); + if (status != ESUCCESS) + break; + status = register_callback(ipfilter_postconfig_callback, + CFG_PT_POSTCONFIG, + CFG_ORD_NOMINAL, 0L); + } else { + /* + * ipf.mod is getting loaded dynamically. + */ + ipfilter_is_dynamic = 1; + status = ipfilter_preconfig(); + if (status != ESUCCESS) { + printf("ipfilter_conf:preconfig failed\n"); + return (status); + } + + status = ipfilter_postconfig(); + if (status != ESUCCESS) { + printf("ipfilter_conf:postconfig failed\n"); + return (status); + } + status = ipfilter_attach(); +#ifdef IPFDEBUG + printf("ipfilter_attach=%d\n",status); +#endif + } + break; + + case CFG_OP_QUERY : + break; + + case CFG_OP_RECONFIGURE : + break; + + case CFG_OP_UNCONFIGURE : + if (ipfilter_is_dynamic) { + + status = devsw_del(ipfilter_name, MAJOR_INSTANCE); + if (status == NO_DEV) { + printf("ipfilter_configure: call to devsw_del failed\n"); + return ESRCH; + } + + ipfilter_is_dynamic = 0; + ipfilter_config = FALSE; + + printf("ipfilter_configure: dynamic module unconfigured\n"); + } else { + /* static configuration */ + printf("ipfilter_configure: Can't unconfigure a static mod\n"); + return ESUCCESS; + } + if (ipfilter_cfg_state & SUBSYSTEM_STATICALLY_CONFIGURED) { + status = EINVAL; + break; + } + status = ipfilter_detach(); + break; + + default : + status = ENOTSUP; + break; + } + +#ifdef IPFDEBUG + printf("ipfilter_configure(%d)=%d\n",op,status); +#endif + return status; +} + + +void ipfilter_configure_callback(conf, order, arg, evarg) + int conf, order, arg, evarg; +{ + int status; + +#ifdef IPFDEBUG + printf("ipfilter_configure_callback(%x,%x,%x,%x)\n", + conf, order, arg, evarg); +#endif + + status = ipfilter_attach(); + + if (status != ESUCCESS) { + cfgmgr_set_status("ipfilter"); + } +} + + +/* + * This hook intercepts mbufs directly off the IP input + * queue(s) and gives them to the routine at (*ip_input_hook)(m). + * The hook must either free the mbuf, or enqueue it back to + * an IP input queue by calling ip_continue_input(m). It is + * assumed that the hook returns to the caller in a timely + * manner, enqueuing the mbuf on its own list for further + * processing at a later time (if necesary). +*/ +void ipfilter_ip_input(m) + struct mbuf *m; +{ + struct mbuf *m0; + struct ip *ip; + int hlen, len; + +#ifdef IPFDEBUG + printf("ipfilter_ip_input(%x)\n", m); +#endif + READ_ENTER(&ipf_tru64); + if (ipfilter_registered < 1 || ipftru64_inited == 0) { + RWLOCK_EXIT(&ipf_tru64); + ip_continue_input(m); + return; + } + + ipfilter_stat.ip_input_mbufs++; + + ip = mtod(m, struct ip *); + + /* + * Because this gets packets directly off the IP input queue, we need + * to do all of the input packet checking. This is IPv4 only. + */ + if (m->m_len < sizeof(struct ip) && + (m = m_pullup(m, sizeof (struct ip))) == 0) { + ipfilter_stat.ip_input_toosmall++; + RWLOCK_EXIT(&ipf_tru64); + return; + } + + if (IP_V(ip) != IPVERSION) { + ipfilter_stat.ip_input_badvers++; + goto bad; + } + + hlen = IP_HL(ip) << 2; + if (hlen < sizeof(*ip)) { + ipfilter_stat.ip_input_badhlen++; + goto bad; + } + + if (hlen > m->m_len) { + if ((m = m_pullup(m, hlen)) == 0) { + RWLOCK_EXIT(&ipf_tru64); + return; + } + ip = mtod(m, struct ip *); + } + + /* + * If header checksum verification fails, do no more. + */ + if (in_cksum(m, hlen) != 0) { + ipfilter_stat.ip_input_badsum++; + goto bad; + } + + /* + * Convert fields to host representation. + */ + len = ntohs(ip->ip_len); + if (len < hlen) { + ipfilter_stat.ip_input_badlen++; + goto bad; + } + if (m->m_pkthdr.len < len) { + ipfilter_stat.ip_input_tooshort++; + goto bad; + } + if (m->m_pkthdr.len > len) { + if (m->m_len == m->m_pkthdr.len) { + m->m_len = len; + m->m_pkthdr.len = len; + } else + m_adj(m, len - m->m_pkthdr.len); + } + + if (ipf_check(&ipfmain, ip, hlen, m->m_pkthdr.rcvif, 0, &m) == 0) { + if (m != NULL) { + m->m_flags &= ~M_PROTOCOL_SUM|M_NOCHECKSUM|M_CHECKSUM; + + ipfilter_stat.ip_input_accept++; + RWLOCK_EXIT(&ipf_tru64); + ip_continue_input(m); + return; + } + } +bad: + RWLOCK_EXIT(&ipf_tru64); + if (m != NULL) + m_freem(m); + return; +} + + +/* + * This hook intercepts mbufs directly from the IP output + * routine and gives them to the routine at + * (*ip_output_hook)(ifp, m, in_ro, flags, imo). The + * hook must either free the mbuf, or set an mbuf flag + * (m->m_flags |= M_OUTPUT_PROCESSING_DONE) and call + * ip_output() again to transmit it. It is assumed that + * the hook returns to the caller in a timely manner, enqueuing + * the mbuf on its own list for further processing at a later + * time (if necesary). + */ +int ipfilter_ip_output(ifp, m, in_ro, flags, imo) + struct ifnet *ifp; + struct mbuf *m; + struct in_route *in_ro; + int flags; + struct ip_moptions *imo; +{ + struct ip *ip; + int hlen; + +#ifdef IPFDEBUG + printf("ipfilter_ip_output(%x,%x,%x,%x,%x)\n", + ifp, m, in_ro, flags, imo); +#endif + READ_ENTER(&ipf_tru64); + if (ipfilter_registered < 1 || ipftru64_inited == 0) { + RWLOCK_EXIT(&ipf_tru64); + return (ip_output(m, NULL, in_ro, flags, imo)); + } + + ipfilter_stat.ip_output_mbufs++; + + ip = mtod(m, struct ip *); + hlen = IP_HL(ip); + hlen <<= 2; + + if (ipf_check(&ipfmain, ip, hlen, ifp, 1, &m) == 0) { + if (m != NULL) { + m->m_flags |= M_OUTPUT_PROCESSING_DONE; + RWLOCK_EXIT(&ipf_tru64); + return (ip_output(m, NULL, in_ro, flags, imo)); + } + } + RWLOCK_EXIT(&ipf_tru64); + return 0; +} + + +/* + * This is a passive routine. It does not implement any ioctl's, just merely + * "snoops" ioctls being sent so that we can be aware of things like address + * changes on the interfaces. + */ +void ipfilter_in_control(so, cmd, data, ifp) + struct socket *so; + u_int cmd; + caddr_t *data; + struct ifnet *ifp; +{ +#ifdef IPFDEBUG + printf("ipfilter_in_control(%x,%x,%x,%x)\n", so, cmd, data, ifp); +#endif + + ipfilter_stat.in_control_called++; + + READ_ENTER(&ipf_tru64); + if (ipfilter_registered < 1 || ipftru64_inited == 0) { + RWLOCK_EXIT(&ipf_tru64); + return; + } + + if (cmd == (ioctlcmd_t)SIOCAIFADDR) + ipf_sync(&ipfmain, NULL); + + RWLOCK_EXIT(&ipf_tru64); +} + + +/* "protocol" ifnet structure for accessing ipf statistics */ +static struct { + struct ifnet ifnet; + char pad[sizeof(struct ether_driver) - sizeof(ifnet)]; +} ipfilter_if; + + +/* + * Routine to attach ipf module + */ +int +ipfilter_attach(void) +{ + struct firewall ipf; + int status; + + bzero((char *)&ipfmain, sizeof(ipfmain)); + +#ifdef IPFDEBUG + printf("ipfilter_attach(void)\n"); +#endif + + if ((status = ipf_load_all()) != 0) { +#ifdef IPFDEBUG + printf("ipf_load_all() == %d\n", status); +#endif + return EIO; + } + + if (ipf_create_all(&ipfmain) == NULL) { + SPL_X(s); +#ifdef IPFDEBUG + printf("ipf_create_all() == %d\n", status); +#endif + return EIO; + } + + status = ipfattach(&ipfmain); +#ifdef IPFDEBUG + printf("ipfattach() = %d\n", status); +#endif + if (status != ESUCCESS) { + (void) ipfdetach(&ipfmain); + return status; + } + + ipfilter_registered = 1; + + /* + * Initialize the struct, else the kernel might interpret + * a field as being valid when it's not, which would probably + * be fatal. + */ + bzero(&ipf, sizeof(struct firewall)); + + /* + * Tell which version of the ipf structure we are passing-in. + * The only currently supported version is #1. + */ + ipf.version = FIREWALL_VERSION1; + + /* + * Tell which protocol family we wish to register. + * The only currently supported family is PF_INET. + */ + ipf.pf = PF_INET; + + /* + * Tell the kernel to disable the RPC/NFS "fastpath" code and + * send all NFS output packets through the "slow" IP output code. + */ + ipf.flags = FW_DISABLE_RPC_FASTPATH; + + /* + * Fill-in the hooks we wish to register. At a minumum there + * must be an input and output hook. + */ + ipf.in_control_hook = ipfilter_in_control; + ipf.fw_ip_input_hook = ipfilter_ip_input; + ipf.fw_ip_output_hook = ipfilter_ip_output; + + /* make the call */ + status = register_firewall(&ipf); + + /* + * Additionally, if we wish to attach a protocol statistics structure, + * do it now. We will only attach to counter ioctls on success. + */ + if (status == ESUCCESS) { + char *defpass; + + ipfilter_registered = 2; + ipfilter_ifattach(); + ipfmain.ipf_running = 1; + + /* + * Start timeout thread + */ + ipf_timeout = kernel_thread_w_arg(first_task, ipfilter_timer, + &ipfmain); + timeout(ipfilter_clock, &ipfmain, + (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT); + + if (FR_ISPASS(ipfmain.ipf_pass)) + defpass = "pass"; + else if (FR_ISBLOCK(ipfmain.ipf_pass)) + defpass = "block"; + else + defpass = "no-match -> block"; + + printf("%s initialized. Default = %s all, Logging = %s%s\n", + ipfilter_version, defpass, +#ifdef IPFILTER_LOG + "enabled", +#else + "disabled", +#endif +#ifdef IPFILTER_COMPILED + " (COMPILED)" +#else + "" +#endif + ); + } + + return (status); +} + + +/* + * Routine to detach ipf module + */ +int +ipfilter_detach(void) +{ + int status; + struct firewall ipf; + +#ifdef IPFDEBUG + printf("ipfilter_detach(void)\n"); +#endif + + WRITE_ENTER(&ipf_tru64); + /* + * Initialize the struct, else the kernel might interpret + * a field as being valid when it's not, which would probably + * be fatal. + */ + bzero(&ipf, sizeof(struct firewall)); + + /* + * If we had attached a protocol statistics structure, detach it now. + * We do this before un-registering our hooks. + */ + ipfilter_ifdetach(); + + /* + * Tell which version of the ipf structure we are passing-in. + * The only currently supported version is #1. + */ + ipf.version = FIREWALL_VERSION1; + + /* + * Tell which protocol family we wish to register. + * The only currently supported family is PF_INET. + */ + ipf.pf = PF_INET; + + /* + * Tell the kernel to re-enable the RPC/NFS "fastpath" code and stop + * sending all NFS output packets through the "slow" IP output code. + */ + ipf.flags = FW_ENABLE_RPC_FASTPATH; + + /* + * We don't need to fill-in the hook pointers as they + * are not used in the unregister_ipf() routine. + */ + + /* make the call */ + status = ESUCCESS; + if (ipfilter_registered > 1) { + status = unregister_firewall(&ipf); + ipfilter_registered = 1; + } + + if ((status == ESUCCESS) && (ipfilter_registered > 0)) { + status = ipfdetach(&ipfmain); +#ifdef IPFDEBUG + printf("ipfdetach() = %d\n", status); +#endif + ipfilter_registered = 0; + } + + if (status == ESUCCESS) { + ipfmain.ipf_running = 0; +#if 0 + if (ipf_timeout != 0) { + thread_terminate(ipf_timeout); + ipf_timeout = 0; + } +#else + /* + * Deschedule the timeout, kill the thread that is wiating on + * it and then wait one second for that thread to die. + */ + untimeout(ipfilter_clock, &ipfmain); + thread_wakeup_one((vm_offset_t)&ipf_timeout); + + while (ipf_timeout != 0) { + assert_wait_mesg((vm_offset_t)&ipf_timeout, + TRUE, "ipftimeout"); + thread_set_timeout(hz); + thread_block(); + } +#endif + printf("%s unloaded\n", ipfilter_version); + + ipf_destroy_all(&ipfmain); + + ipf_unload_all(); + } else { + RWLOCK_EXIT(&ipf_tru64); + } + + return (status); +} + + +/* + * Routine to attach protocol statistics structure + */ +void ipfilter_ifattach(void) +{ + struct ifnet *ifp = &(ipfilter_if.ifnet); + +#ifdef IPFDEBUG + printf("ipfilter_ifattach(void)\n"); +#endif + + ifp->if_name = "ipf"; + ifp->if_version = "Network Packet Filter"; + ifp->if_mtu = IP_MAXPACKET; + ifp->if_flags = IFF_UP; + ifp->if_ioctl = ipfilter_ifioctl; + ifp->if_output = ipfilter_ifoutput; + ifp->if_type = IFT_OTHER; + ifp->if_hdrlen = 8; + ifp->if_affinity = NETALLCPU; + ifp->if_addrlen = 0; + + if_proto_attach(ifp); +} + + +/* + * Routine to detach protocol statistics structure + */ +void ipfilter_ifdetach(void) +{ + struct ifnet *ifp = &(ipfilter_if.ifnet); + +#ifdef IPFDEBUG + printf("ipfilter_ifdetach(void)\n"); +#endif + + if_proto_detach(ifp); +} + + +/* + * Routine to handle protocol ioctls + */ +int ipfilter_ifioctl(ifp, cmd, data) + register struct ifnet *ifp; + unsigned int cmd; + caddr_t data; +{ + return (EOPNOTSUPP); +} + +/* Stub output routine. Should never be called, but just in case... */ +#if TRU64 >= 1885 +int ipfilter_ifoutput(ifp, m0, dst, rt, cp) + char *cp; +#else +int ipfilter_ifoutput(ifp, m0, dst, rt) +#endif + struct ifnet *ifp; + struct mbuf *m0; + struct sockaddr *dst; + struct rtentry *rt; +{ + return (EOPNOTSUPP); +} + + +/* called from ipfilter_configure(CFG_OP_CONFIGURE,...) */ +void ipfilter_print_attr_error(cfg_attr_t *attr_ptr) +{ + printf("%s:", attr_ptr->name); + + switch(attr_ptr->status) + { + case CFG_ATTR_EEXISTS: + printf("Attribute does not exist\n"); + break; + case CFG_ATTR_EOP: + printf("Attribute does not support operation\n"); + break; + case CFG_ATTR_ESUBSYS: + printf("Subsystem Failure\n"); + break; + case CFG_ATTR_ESMALL: + printf("Attribute size/value too small\n"); + break; + case CFG_ATTR_ELARGE: + printf("Attribute size/value too large\n"); + break; + case CFG_ATTR_ETYPE: + printf("Attribute invalid type\n"); + break; + case CFG_ATTR_EINDEX: + printf("Attribute invalid index\n"); + break; + case CFG_ATTR_EMEM: + printf("Attribute memory allocation error\n"); + break; + default: + printf("**Unknown attribute: "); + printf("%x\n", attr_ptr->status); + } +} + +/*--------------------------------------------------------- +* pre-configuration +* Returns: ENOMEM for fail. +* ESUCCESS for success. +*--------------------------------------------------------*/ +int ipfilter_preconfig() +{ + int status; + + return ESUCCESS; +} + +void +ipfilter_preconfig_callback(int point, int order, ulong argument, ulong event_arg) +{ + int status; + struct hwconfig *hwc; + hwc = create_hwconfig_struct(); + + if (hwc == NULL) + return; + + /* + * Add ourselves to the switch table. + */ + majnum = devsw_add(ipfilter_name, MAJOR_INSTANCE, + NO_DEV, &ipfilter_devsw_entry); + if (majnum == NO_DEV) { + printf("devsw_add_failed\n"); + (void)cfgmgr_set_status(ipfilter_name); + callback_return_status = ENODEV; + return; + } + printf("devsw_add_majnum=%d\n", majnum); + + hwc->type = HWCONFIG_CONTROLLER_ALL | HWCONFIG_CONFIGURE_REQUEST; + + hwc->parent_bus = HWCONFIG_ALL; + hwc->parent_bus_instance = DRIVER_WILDNUM; + hwc->driver_name = ipfilter_name; + hwc->driver_struct = &ipfdriver; + hwc->instance_info = -1; + + status = driver_framework(hwc); + free_hwconfig_struct(hwc); + + if (status != ESUCCESS) { + printf("Cannot configure driver %s-- status = %d\n", + ipfilter_name, status); + return; + } + +} + +/*--------------------------------------------------------- +* post configure +* Return: ENODEV on fail. +* ESUCCESS on success. +*--------------------------------------------------------*/ +int ipfilter_postconfig() +{ + + majnum = devsw_add(ipfilter_name,MAJOR_INSTANCE, majnum, + &ipfilter_devsw_entry); + + if (majnum == ENODEV) { + printf("ipfilter_postconfig: call to devsw_add failed\n"); + return ENODEV; + } + + printf("ipfilter_postconfig:major # = %d\n",majnum); + + ipfilter_devno = majnum; + ipfilter_config = TRUE; + + printf("%s configured\n", ipfilter_version); + + return ESUCCESS; +} + +void +ipfilter_postconfig_callback(int point, int order, ulong argument, + ulong event_arg) +{ + int status; + + if (callback_return_status != ESUCCESS) + return; + + status = ipfilter_postconfig(); + if (status != ESUCCESS) { + cfgmgr_set_status(ipfilter_name); + callback_return_status = status; + } +} + + +/*--------------------------------------------------------- + * Open + * Return: ENXIO on fail. + * ESUCCESS on success. + *--------------------------------------------------------*/ +int ipfilteropen(dev_t dev, int flag, int format) +{ + int unit; + int error; + + unit = minor(dev); + + if ((IPL_LOGMAX < unit) || (unit < 0)) { + error = ENXIO; + } else { + switch (unit) + { + case IPL_LOGIPF : + case IPL_LOGNAT : + case IPL_LOGSTATE : + case IPL_LOGAUTH : + case IPL_LOGLOOKUP : + case IPL_LOGSYNC : +#ifdef IPFILTER_SCAN + case IPL_LOGSCAN : +#endif + error = ESUCCESS; + break; + default : + error = ENXIO; + break; + } + } + + return error; +} + +/*--------------------------------------------------------- +* Close +* Return: ESUCCESS on success. +* ENXIO on fail. +*--------------------------------------------------------*/ +int ipfilterclose(dev_t dev, int flag, int format) +{ + int unit; + +#ifdef IPFDEBUG + printf("ipfilter_close(%x,%x,%x)\n", dev, flag, format); +#endif + + unit = minor(dev); + + if ((IPL_LOGMAX < unit) || (unit < 0)) + unit = ENXIO; + else + unit = ESUCCESS; + + return unit; +} + + +/*--------------------------------------------------------- +* Read - +* return: ESUCCESS on success. +* fail: An error number from errno.h +*--------------------------------------------------------*/ +int ipfilterread(dev_t dev, struct uio *uio, int flag) +{ +#ifdef IPFILTER_LOG + int unit, status; + + unit = minor(dev); + +# ifdef IPFDEBUG + printf("ipfread(%x,%lx,%x)\n", dev, uio, flag); +# endif + status = ipflog_read(&ipfmain, unit, uio); + + return status; +#else + return ENXIO; +#endif +} + + +/*--------------------------------------------------------- +* Write - +* return: ESUCCESS on success. +* fail: An error number from errno.h +*--------------------------------------------------------*/ +int +ipfilterwrite(dev_t dev, struct uio *uio) +{ + int unit; + +# ifdef IPFDEBUG + printf("ipfilter_write(%x,%lx)\n", dev, uio); +# endif + if (getminor(dev) != IPL_LOGSYNC) + return ENXIO; + return ipfsync_write(&ipfmain, uio); + +} + + +/*--------------------------------------------------------- +* IOCTL +* Return: ESUCCESS on success. +* fail: An error number from errno.h +*--------------------------------------------------------*/ +int ipfilterioctl(dev_t dev, unsigned int cmd, caddr_t data, int flag) +{ + int err; + +#ifdef IPFDEBUG + printf("ipfilterioctl(%d(%d),%x,%lx,%x)\n", dev, + getminor(dev), cmd, data, flag); +#endif + READ_ENTER(&ipf_tru64); + if (ipfilter_registered < 1 || ipftru64_inited == 0) { + RWLOCK_EXIT(&ipf_tru64); +#ifdef IPFDEBUG + printf("ipfilter_registered %d ipftru64_inited %d\n", + ipfilter_registered, ipftru64_inited); +#endif + return EIO; + } + err = ipfioctl(dev, cmd, data, flag); + RWLOCK_EXIT(&ipf_tru64); + return err; +} + + +void ipfilter_clock(void *arg) +{ + thread_wakeup_one((vm_offset_t)&ipf_timeout); + if (ipfmain.ipf_running != 0) { + timeout(ipfilter_clock, &ipfmain, + (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT); + } +} + + +void ipfilter_timer() +{ +#if 0 + lock_data_t ipfdelaylock; + + lock_init(&ipfdelaylock, TRUE); +#else + simple_lock_data_t ipfdelaylock; + + simple_lock_init(&ipfdelaylock); + simple_lock(&ipfdelaylock); +#endif + + while (1) { +#if 0 + lock_write(&ipfdelaylock); + assert_wait_mesg((vm_offset_t)&ipfdelaylock, TRUE, "ipftimer"); + lock_done(&ipfdelaylock); + + thread_set_timeout((hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT); + + thread_block(); +#else + if (ipfmain.ipf_running == 0) + break; + mpsleep((vm_offset_t)&ipf_timeout, PCATCH, + "ipftimer", 0, &ipfdelaylock, + MS_LOCK_SIMPLE | MS_LOCK_ON_ERROR); +#endif + + if (ipfmain.ipf_running == 0) + break; + simple_unlock(&ipfdelaylock); + ipf_timer_func(&ipfmain); + simple_lock(&ipfdelaylock); + } + + simple_unlock(&ipfdelaylock); + simple_lock_terminate(&ipfdelaylock); + + if (ipf_timeout != 0) { + thread_terminate(ipf_timeout); + ipf_timeout = 0; + } + thread_halt_self(); +} + + +/* + * routines below for saving IP headers to buffer + */ +static int ipfopen(dev, flags) + dev_t dev; + int flags; +{ + u_int min = minor(dev); + + if (IPL_LOGMAX < min) + min = ENXIO; + else + min = 0; + return min; +} + + +static int ipfclose(dev, flags) + dev_t dev; + int flags; +{ + u_int min = minor(dev); + + if (IPL_LOGMAX < min) + min = ENXIO; + else + min = 0; + return min; +} + +/* + * ipfread/ipllog + * both of these must operate with at least splnet() lest they be + * called during packet processing and cause an inconsistancy to appear in + * the filter lists. + */ +static int ipfread(dev, uio) + dev_t dev; + register struct uio *uio; +{ + + if (ipfmain.ipf_running < 1) + return EIO; + +#ifdef IPFILTER_LOG + return ipflog_read(minor(dev), uio); +#else + return ENXIO; +#endif +} |