diff options
author | darrenr <darrenr@FreeBSD.org> | 2007-06-04 02:54:36 +0000 |
---|---|---|
committer | darrenr <darrenr@FreeBSD.org> | 2007-06-04 02:54:36 +0000 |
commit | a33069b5324be7fb6d5c0a0d785bb0e10eb0aa36 (patch) | |
tree | 28d6fb710df6e0ddec4933e69ec29d2ecd78a134 | |
parent | 1dd4fa592dfed4984b91696b53e64e8c075f63eb (diff) | |
download | FreeBSD-src-a33069b5324be7fb6d5c0a0d785bb0e10eb0aa36.zip FreeBSD-src-a33069b5324be7fb6d5c0a0d785bb0e10eb0aa36.tar.gz |
Merge IPFilter 4.1.23 back to HEAD
See src/contrib/ipfilter/HISTORY for details of changes since 4.1.13
142 files changed, 5511 insertions, 2404 deletions
diff --git a/contrib/ipfilter/Makefile b/contrib/ipfilter/Makefile index 4b45a0a..9b4673e 100644 --- a/contrib/ipfilter/Makefile +++ b/contrib/ipfilter/Makefile @@ -188,7 +188,7 @@ freebsd22: include fi make freebsd20 -freebsd5 freebsd6: include +freebsd5 freebsd6 freebsd7: include if [ x$(INET6) = x ] ; then \ echo "#undef INET6" > opt_inet6.h; \ else \ @@ -230,6 +230,15 @@ freebsd3 freebsd30: include netbsd: include make setup "TARGOS=BSD" "CPUDIR=$(CPUDIR)" + @if [ ! -d /sys -o ! -d /sys/arch ] ; then \ + echo "*****************************************************"; \ + echo "* *"; \ + echo "* Please extract source code to create /sys and *";\ + echo "* /sys/arch and run 'config GENERIC' *"; \ + echo "* *"; \ + echo "*****************************************************"; \ + 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 ..) diff --git a/contrib/ipfilter/bpf_filter.c b/contrib/ipfilter/bpf_filter.c index 9291163..d75570e 100644 --- a/contrib/ipfilter/bpf_filter.c +++ b/contrib/ipfilter/bpf_filter.c @@ -42,7 +42,7 @@ #if !(defined(lint) || defined(KERNEL) || defined(_KERNEL)) static const char rcsid[] = - "@(#) $Header: /devel/CVS/IP-Filter/bpf_filter.c,v 2.2.2.2 2005/12/30 12:57:28 darrenr Exp $ (LBL)"; + "@(#) $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> @@ -195,7 +195,8 @@ bpf_filter(pc, p, wirelen, buflen) register int k; int32 mem[BPF_MEMWORDS]; mb_t *m, *n; - int merr, len; + int merr = 0; /* XXX: GCC */ + int len; if (buflen == 0) { m = (mb_t *)p; diff --git a/contrib/ipfilter/ip_fil.c b/contrib/ipfilter/ip_fil.c index 2bb4f5a..45bbf94 100644 --- a/contrib/ipfilter/ip_fil.c +++ b/contrib/ipfilter/ip_fil.c @@ -7,7 +7,7 @@ */ #if !defined(lint) static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.133.2.11 2006/03/25 11:15:30 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.133.2.16 2007/05/28 11:56:22 darrenr Exp $"; #endif #ifndef SOLARIS @@ -64,7 +64,6 @@ struct file; #include <stdlib.h> #include <ctype.h> #include <fcntl.h> -#include <arpa/inet.h> #ifdef __hpux # define _NET_ROUTE_INCLUDED @@ -85,7 +84,9 @@ struct file; #if defined(__FreeBSD__) # include "radix_ipf.h" #endif -#include <net/route.h> +#ifndef __osf__ +# include <net/route.h> +#endif #include <netinet/in.h> #if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */ && \ !defined(__hpux) && !defined(linux) @@ -109,6 +110,7 @@ struct file; #include <netinet/ip_icmp.h> #include <unistd.h> #include <syslog.h> +#include <arpa/inet.h> #ifdef __hpux # undef _NET_ROUTE_INCLUDED #endif @@ -146,7 +148,6 @@ extern struct protosw inetsw[]; static struct ifnet **ifneta = NULL; static int nifs = 0; -static int frzerostats __P((caddr_t)); static void fr_setifpaddr __P((struct ifnet *, char *)); void init_ifp __P((void)); #if defined(__sgi) && (IRIX < 60500) @@ -169,37 +170,20 @@ static int write_output __P((struct ifnet *, struct mbuf *, #endif -int iplattach() +int ipfattach() { fr_running = 1; return 0; } -int ipldetach() +int ipfdetach() { fr_running = -1; return 0; } -static int frzerostats(data) -caddr_t data; -{ - friostat_t fio; - int error; - - fr_getstat(&fio); - error = copyoutptr(&fio, data, sizeof(fio)); - if (error) - return EFAULT; - - bzero((char *)frstats, sizeof(*frstats) * 2); - - return 0; -} - - /* * Filter ioctl interface. */ @@ -209,210 +193,20 @@ ioctlcmd_t cmd; caddr_t data; int mode; { - int error = 0, unit = 0, tmp; - friostat_t fio; + int error = 0, unit = 0, uid; + SPL_INT(s); + uid = getuid(); unit = dev; SPL_NET(s); - if (unit == IPL_LOGNAT) { - if (fr_running > 0) - error = fr_nat_ioctl(data, cmd, mode); - else - error = EIO; - SPL_X(s); - return error; - } - if (unit == IPL_LOGSTATE) { - if (fr_running > 0) - error = fr_state_ioctl(data, cmd, mode); - else - error = EIO; - SPL_X(s); - return error; - } - if (unit == 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, mode, cmd); - } - } else - error = EIO; - SPL_X(s); - return error; - } - if (unit == IPL_LOGSYNC) { -#ifdef IPFILTER_SYNC - if (fr_running > 0) - error = fr_sync_ioctl(data, cmd, mode); - else -#endif - error = EIO; - SPL_X(s); - return error; - } - if (unit == IPL_LOGSCAN) { -#ifdef IPFILTER_SCAN - if (fr_running > 0) - error = fr_scan_ioctl(data, cmd, mode); - else -#endif - error = EIO; - SPL_X(s); - return error; - } - if (unit == IPL_LOGLOOKUP) { - if (fr_running > 0) - error = ip_lookup_ioctl(data, cmd, mode); - else - error = EIO; + error = fr_ioctlswitch(unit, data, cmd, mode, uid, NULL); + if (error != -1) { SPL_X(s); return error; } - switch (cmd) - { - case FIONREAD : -#ifdef IPFILTER_LOG - error = COPYOUT(&iplused[IPL_LOGIPF], (caddr_t)data, - sizeof(iplused[IPL_LOGIPF])); -#endif - break; - case SIOCFRENB : - if (!(mode & FWRITE)) - error = EPERM; - else { - error = COPYIN(data, &tmp, sizeof(tmp)); - if (error) - break; - if (tmp) - error = iplattach(); - else - error = ipldetach(); - } - break; - case SIOCIPFSET : - if (!(mode & FWRITE)) { - error = EPERM; - break; - } - case SIOCIPFGETNEXT : - case SIOCIPFGET : - error = fr_ipftune(cmd, (void *)data); - break; - case SIOCSETFF : - if (!(mode & FWRITE)) - error = EPERM; - else - error = COPYIN(data, &fr_flags, sizeof(fr_flags)); - break; - case SIOCGETFF : - error = COPYOUT(&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 = frzerostats(data); - break; - case SIOCIPFFL : - if (!(mode & FWRITE)) - error = EPERM; - else { - error = COPYIN(data, &tmp, sizeof(tmp)); - if (!error) { - tmp = frflush(unit, 4, tmp); - error = COPYOUT(&tmp, data, sizeof(tmp)); - } - } - break; -#ifdef USE_INET6 - case SIOCIPFL6 : - if (!(mode & FWRITE)) - error = EPERM; - else { - error = COPYIN(data, &tmp, sizeof(tmp)); - if (!error) { - tmp = frflush(unit, 6, tmp); - error = COPYOUT(&tmp, data, sizeof(tmp)); - } - } - break; -#endif - case SIOCSTLCK : - error = COPYIN(data, &tmp, sizeof(tmp)); - if (error == 0) { - 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 - *(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; } @@ -652,7 +446,7 @@ int v; ifp->if_unit = -1; } #endif - ifp->if_output = no_output; + ifp->if_output = (void *)no_output; if (addr != NULL) { fr_setifpaddr(ifp, addr); @@ -688,7 +482,7 @@ void init_ifp() (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { - ifp->if_output = write_output; + ifp->if_output = (void *)write_output; sprintf(fname, "/tmp/%s", ifp->if_xname); fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); if (fd == -1) @@ -998,3 +792,9 @@ struct in_addr *inp, *inpmask; } return 0; } + + +int ipfsync() +{ + return 0; +} diff --git a/contrib/ipfilter/ipf.h b/contrib/ipfilter/ipf.h index 25401c4..ae05ca7 100644 --- a/contrib/ipfilter/ipf.h +++ b/contrib/ipfilter/ipf.h @@ -6,7 +6,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ipf.h 1.12 6/5/96 - * $Id: ipf.h,v 2.71.2.8 2005/12/30 07:03:21 darrenr Exp $ + * $Id: ipf.h,v 2.71.2.15 2007/05/11 10:44:14 darrenr Exp $ */ #ifndef __IPF_H__ @@ -183,14 +183,14 @@ extern struct ipopt_names v6ionames[]; extern int addicmp __P((char ***, struct frentry *, int)); extern int addipopt __P((char *, struct ipopt_names *, int, char *)); -extern int addkeep __P((char ***, struct frentry *, int)); +extern void alist_free __P((alist_t *)); +extern alist_t *alist_new __P((int, 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 count6bits __P((u_32_t *)); extern int count4bits __P((u_32_t)); -extern int extras __P((char ***, struct frentry *, int)); extern char *fac_toname __P((int)); extern int fac_findname __P((char *)); extern void fill6bits __P((int, u_int *)); @@ -198,19 +198,12 @@ extern int gethost __P((char *, u_32_t *)); extern int getport __P((struct frentry *, char *, u_short *)); extern int getportproto __P((char *, int)); extern int getproto __P((char *)); -extern char *getline __P((char *, size_t, FILE *, int *)); -extern int genmask __P((char *, u_32_t *)); -extern char *getnattype __P((struct ipnat *)); +extern char *getnattype __P((struct nat *, int)); 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 void hexdump __P((FILE *, void *, int, int)); -extern int hostmask __P((char ***, char *, char *, u_32_t *, u_32_t *, int)); -extern int hostnum __P((u_32_t *, char *, int, char *)); -extern int icmpcode __P((char *)); -extern int icmpidnum __P((char *, u_short *, int)); extern void initparse __P((void)); extern void ipf_dotuning __P((int, char *, ioctlfunc_t)); extern void ipf_addrule __P((int, ioctlfunc_t, void *)); @@ -225,23 +218,21 @@ 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 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 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 loglevel __P((char **, u_int *, int)); +extern alist_t *load_url __P((char *)); extern alist_t *make_range __P((int, struct in_addr, struct in_addr)); extern ipfunc_t nametokva __P((char *, ioctlfunc_t)); -extern ipnat_t *natparse __P((char *, int)); -extern void natparsefile __P((int, char *, int)); 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 char *portname __P((int, int)); -extern int portnum __P((char *, char *, u_short *, int)); -extern int ports __P((char ***, char *, u_short *, int *, u_short *, int)); extern int pri_findname __P((char *)); extern char *pri_toname __P((int)); extern void print_toif __P((char *, struct frdest *)); @@ -251,6 +242,8 @@ 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)); +extern void printhashdata __P((iphtable_t *, int)); extern struct iphtent_s *printhashnode __P((struct iphtable_s *, struct iphtent_s *, copyfunc_t, int)); @@ -263,6 +256,9 @@ extern void printpacket __P((struct ip *)); extern void printpacket6 __P((struct ip *)); extern struct ip_pool_s *printpool __P((struct ip_pool_s *, copyfunc_t, char *, int)); +extern struct ip_pool_s *printpool_live __P((struct ip_pool_s *, int, + char *, int)); +extern void printpooldata __P((ip_pool_t *, int)); extern struct ip_pool_node *printpoolnode __P((struct ip_pool_node *, int)); extern void printproto __P((struct protoent *, int, struct ipnat *)); extern void printportcmp __P((int, struct frpcmp *)); @@ -270,15 +266,12 @@ extern void optprint __P((u_short *, u_long, u_long)); #ifdef USE_INET6 extern void optprintv6 __P((u_short *, u_long, u_long)); #endif -extern int ratoi __P((char *, int *, int, int)); -extern int ratoui __P((char *, u_int *, u_int, u_int)); 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 int to_interface __P((struct frdest *, char *, int)); extern void printc __P((struct frentry *)); extern void printC __P((int)); extern void emit __P((int, int, void *, struct frentry *)); @@ -290,9 +283,9 @@ 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)); +extern void printactivenat __P((struct nat *, int, int, u_long)); extern void printhostmap __P((struct hostmap *, u_int)); -extern void printpacket __P((struct ip *)); +extern void printtqtable __P((ipftq_t *)); extern void set_variable __P((char *, char *)); extern char *get_variable __P((char *, char **, int)); diff --git a/contrib/ipfilter/iplang/iplang_y.y b/contrib/ipfilter/iplang/iplang_y.y index 34a980f..773f27f 100644 --- a/contrib/ipfilter/iplang/iplang_y.y +++ b/contrib/ipfilter/iplang/iplang_y.y @@ -14,9 +14,9 @@ #include <string.h> #include <fcntl.h> #if !defined(__SVR4) && !defined(__svr4__) -#include <strings.h> +# include <strings.h> #else -#include <sys/byteorder.h> +# include <sys/byteorder.h> #endif #include <sys/types.h> #include <sys/stat.h> @@ -30,11 +30,14 @@ #include <netinet/in_systm.h> #include <netinet/ip.h> #ifndef linux -#include <netinet/ip_var.h> +# include <netinet/ip_var.h> +#endif +#ifdef __osf__ +# include "radix_ipf_local.h" #endif #include <net/if.h> #ifndef linux -#include <netinet/if_ether.h> +# include <netinet/if_ether.h> #endif #include <netdb.h> #include <arpa/nameser.h> diff --git a/contrib/ipfilter/ipsend/44arp.c b/contrib/ipfilter/ipsend/44arp.c index 1063d3a..6ee4f1b 100644 --- a/contrib/ipfilter/ipsend/44arp.c +++ b/contrib/ipfilter/ipsend/44arp.c @@ -16,7 +16,9 @@ #if defined(__FreeBSD__) # include "radix_ipf.h" #endif -#include <net/route.h> +#ifndef __osf__ +# include <net/route.h> +#endif #include <netinet/in.h> #include <netinet/if_ether.h> #include <arpa/inet.h> diff --git a/contrib/ipfilter/ipsend/arp.c b/contrib/ipfilter/ipsend/arp.c index d519a54..8670bda 100644 --- a/contrib/ipfilter/ipsend/arp.c +++ b/contrib/ipfilter/ipsend/arp.c @@ -7,20 +7,23 @@ */ #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.1 2005/06/12 07:18:38 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: arp.c,v 2.8.2.2 2007/02/17 12:41:50 darrenr Exp $"; #endif #include <sys/types.h> #include <sys/socket.h> #if !defined(ultrix) && !defined(hpux) && !defined(__hpux) && !defined(__osf__) && !defined(_AIX51) -#include <sys/sockio.h> +# include <sys/sockio.h> #endif #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 -#include <net/if_arp.h> +# include <net/if_arp.h> #endif #include <netinet/in.h> #include <netinet/ip.h> diff --git a/contrib/ipfilter/ipsend/ip.c b/contrib/ipfilter/ipsend/ip.c index 8d469ef..26a7a89 100644 --- a/contrib/ipfilter/ipsend/ip.c +++ b/contrib/ipfilter/ipsend/ip.c @@ -7,12 +7,15 @@ */ #if !defined(lint) static const char sccsid[] = "%W% %G% (C)1995"; -static const char rcsid[] = "@(#)$Id: ip.c,v 2.8.2.1 2004/10/19 12:31:48 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip.c,v 2.8.2.2 2007/02/17 12:41:51 darrenr Exp $"; #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> diff --git a/contrib/ipfilter/ipsend/iptests.c b/contrib/ipfilter/ipsend/iptests.c index ea358df..a58131d 100644 --- a/contrib/ipfilter/ipsend/iptests.c +++ b/contrib/ipfilter/ipsend/iptests.c @@ -8,7 +8,7 @@ */ #if !defined(lint) static const char sccsid[] = "%W% %G% (C)1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: iptests.c,v 2.8.2.7 2006/03/21 16:10:55 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: iptests.c,v 2.8.2.8 2007/02/17 12:41:51 darrenr Exp $"; #endif #include <sys/param.h> #include <sys/types.h> @@ -64,6 +64,9 @@ 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> diff --git a/contrib/ipfilter/ipsend/resend.c b/contrib/ipfilter/ipsend/resend.c index da5c2bf..b988e9b 100644 --- a/contrib/ipfilter/ipsend/resend.c +++ b/contrib/ipfilter/ipsend/resend.c @@ -8,12 +8,15 @@ */ #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.2 2006/03/17 13:45:34 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: resend.c,v 2.8.2.3 2007/02/17 12:41:51 darrenr Exp $"; #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> diff --git a/contrib/ipfilter/ipsend/sdlpi.c b/contrib/ipfilter/ipsend/sdlpi.c index 5b58359..f48fd06 100644 --- a/contrib/ipfilter/ipsend/sdlpi.c +++ b/contrib/ipfilter/ipsend/sdlpi.c @@ -27,6 +27,7 @@ #endif #ifdef __osf__ # include <sys/dlpihdr.h> +# include "radix_ipf_local.h" #else # include <sys/dlpi.h> #endif @@ -48,7 +49,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.1 2004/12/09 19:41:13 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: sdlpi.c,v 2.8.2.2 2007/02/17 12:41:51 darrenr Exp $"; #endif #define CHUNKSIZE 8192 diff --git a/contrib/ipfilter/ipsend/sock.c b/contrib/ipfilter/ipsend/sock.c index f6edbd2..7aac448 100644 --- a/contrib/ipfilter/ipsend/sock.c +++ b/contrib/ipfilter/ipsend/sock.c @@ -7,7 +7,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.4 2006/03/21 16:10:56 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: sock.c,v 2.8.4.6 2007/02/17 12:41:51 darrenr Exp $"; #endif #include <sys/param.h> #include <sys/types.h> @@ -66,7 +66,9 @@ typedef int boolean_t; #if defined(__FreeBSD__) # include "radix_ipf.h" #endif -#include <net/route.h> +#ifndef __osf__ +# include <net/route.h> +#endif #include <netinet/ip_var.h> #include <netinet/in_pcb.h> #include <netinet/tcp_timer.h> @@ -294,11 +296,14 @@ struct tcpiphdr *ti; return NULL; fd = (struct filedesc *)malloc(sizeof(*fd)); + if (fd == NULL) + return NULL; #if defined( __FreeBSD_version) && __FreeBSD_version >= 500013 if (KMCPY(fd, p->ki_fd, sizeof(*fd)) == -1) { fprintf(stderr, "read(%#lx,%#lx) failed\n", (u_long)p, (u_long)p->ki_fd); + free(fd); return NULL; } #else @@ -306,6 +311,7 @@ struct tcpiphdr *ti; { fprintf(stderr, "read(%#lx,%#lx) failed\n", (u_long)p, (u_long)p->kp_proc.p_fd); + free(fd); return NULL; } #endif diff --git a/contrib/ipfilter/lib/addicmp.c b/contrib/ipfilter/lib/addicmp.c index 39b6fd4..ef9abfe 100644 --- a/contrib/ipfilter/lib/addicmp.c +++ b/contrib/ipfilter/lib/addicmp.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2006 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: addicmp.c,v 1.10.2.4 2006/02/25 17:41:57 darrenr Exp $ + * $Id: addicmp.c,v 1.10.2.5 2006/06/16 17:20:55 darrenr Exp $ */ #include <ctype.h> diff --git a/contrib/ipfilter/lib/addipopt.c b/contrib/ipfilter/lib/addipopt.c index 6dc7f48..79155e7 100644 --- a/contrib/ipfilter/lib/addipopt.c +++ b/contrib/ipfilter/lib/addipopt.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2002 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: addipopt.c,v 1.7 2002/01/28 06:50:45 darrenr Exp $ + * $Id: addipopt.c,v 1.7.4.1 2006/06/16 17:20:56 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/bcopywrap.c b/contrib/ipfilter/lib/bcopywrap.c index 4c68930..b2e8427 100644 --- a/contrib/ipfilter/lib/bcopywrap.c +++ b/contrib/ipfilter/lib/bcopywrap.c @@ -1,5 +1,13 @@ /* $FreeBSD$ */ +/* + * Copyright (C) 2002 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 $ + */ + #include "ipf.h" int bcopywrap(from, to, size) diff --git a/contrib/ipfilter/lib/binprint.c b/contrib/ipfilter/lib/binprint.c index b475aa1..fcb47ed 100644 --- a/contrib/ipfilter/lib/binprint.c +++ b/contrib/ipfilter/lib/binprint.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2002 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: binprint.c,v 1.8 2002/05/14 15:18:56 darrenr Exp $ + * $Id: binprint.c,v 1.8.4.1 2006/06/16 17:20:56 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/buildopts.c b/contrib/ipfilter/lib/buildopts.c index 7a8df09..bdd0538 100644 --- a/contrib/ipfilter/lib/buildopts.c +++ b/contrib/ipfilter/lib/buildopts.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2002 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: buildopts.c,v 1.6 2002/01/28 06:50:45 darrenr Exp $ + * $Id: buildopts.c,v 1.6.4.1 2006/06/16 17:20:56 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/checkrev.c b/contrib/ipfilter/lib/checkrev.c index 97ed689..9e584cc 100644 --- a/contrib/ipfilter/lib/checkrev.c +++ b/contrib/ipfilter/lib/checkrev.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2004 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: checkrev.c,v 1.12.2.1 2004/03/09 14:44:39 darrenr Exp $ + * $Id: checkrev.c,v 1.12.2.2 2006/06/16 17:20:56 darrenr Exp $ */ #include <sys/ioctl.h> diff --git a/contrib/ipfilter/lib/count4bits.c b/contrib/ipfilter/lib/count4bits.c index b2aaa3b..38e5742 100644 --- a/contrib/ipfilter/lib/count4bits.c +++ b/contrib/ipfilter/lib/count4bits.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2002 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: count4bits.c,v 1.1 2002/06/15 04:46:39 darrenr Exp $ + * $Id: count4bits.c,v 1.1.4.1 2006/06/16 17:20:57 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/count6bits.c b/contrib/ipfilter/lib/count6bits.c index 6011e96..15538c3 100644 --- a/contrib/ipfilter/lib/count6bits.c +++ b/contrib/ipfilter/lib/count6bits.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2001 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: count6bits.c,v 1.4 2001/06/09 17:09:23 darrenr Exp $ + * $Id: count6bits.c,v 1.4.4.1 2006/06/16 17:20:57 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/debug.c b/contrib/ipfilter/lib/debug.c index d5f6ab2..3181e78 100644 --- a/contrib/ipfilter/lib/debug.c +++ b/contrib/ipfilter/lib/debug.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2001 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: debug.c,v 1.6 2001/06/09 17:09:24 darrenr Exp $ + * $Id: debug.c,v 1.6.4.1 2006/06/16 17:20:57 darrenr Exp $ */ #if defined(__STDC__) diff --git a/contrib/ipfilter/lib/facpri.c b/contrib/ipfilter/lib/facpri.c index a9bae6d..b89e0f8 100644 --- a/contrib/ipfilter/lib/facpri.c +++ b/contrib/ipfilter/lib/facpri.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2006 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: facpri.c,v 1.6.2.4 2006/03/17 22:28:41 darrenr Exp $ + * $Id: facpri.c,v 1.6.2.5 2006/06/16 17:20:58 darrenr Exp $ */ #include <stdio.h> @@ -22,7 +22,7 @@ #include "facpri.h" #if !defined(lint) -static const char rcsid[] = "@(#)$Id: facpri.c,v 1.6.2.4 2006/03/17 22:28:41 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: facpri.c,v 1.6.2.5 2006/06/16 17:20:58 darrenr Exp $"; #endif diff --git a/contrib/ipfilter/lib/facpri.h b/contrib/ipfilter/lib/facpri.h index 212cd15..ca53e05 100644 --- a/contrib/ipfilter/lib/facpri.h +++ b/contrib/ipfilter/lib/facpri.h @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1999-2001 by Darren Reed. + * Copyright (C) 2000-2001 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: facpri.h,v 1.3 2001/06/09 17:19:50 darrenr Exp $ + * $Id: facpri.h,v 1.3.4.1 2006/06/16 17:20:58 darrenr Exp $ */ #ifndef __FACPRI_H__ diff --git a/contrib/ipfilter/lib/fill6bits.c b/contrib/ipfilter/lib/fill6bits.c index ec34d4e..c0faf6a 100644 --- a/contrib/ipfilter/lib/fill6bits.c +++ b/contrib/ipfilter/lib/fill6bits.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2002 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: fill6bits.c,v 1.5 2002/03/27 15:09:57 darrenr Exp $ + * $Id: fill6bits.c,v 1.5.4.1 2006/06/16 17:20:58 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/flags.c b/contrib/ipfilter/lib/flags.c index 1b9dc72..200484c 100644 --- a/contrib/ipfilter/lib/flags.c +++ b/contrib/ipfilter/lib/flags.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2001-2002 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: flags.c,v 1.4 2002/11/02 07:16:36 darrenr Exp $ + * $Id: flags.c,v 1.4.4.1 2006/06/16 17:20:58 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/gethost.c b/contrib/ipfilter/lib/gethost.c index f9034cc..be536c1 100644 --- a/contrib/ipfilter/lib/gethost.c +++ b/contrib/ipfilter/lib/gethost.c @@ -1,5 +1,13 @@ /* $FreeBSD$ */ +/* + * 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 $ + */ + #include "ipf.h" int gethost(name, hostp) diff --git a/contrib/ipfilter/lib/getifname.c b/contrib/ipfilter/lib/getifname.c index 35acb32..7246fbb 100644 --- a/contrib/ipfilter/lib/getifname.c +++ b/contrib/ipfilter/lib/getifname.c @@ -1,5 +1,13 @@ /* $FreeBSD$ */ +/* + * 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 $ + */ + #include "ipf.h" #include "kmem.h" @@ -8,6 +16,7 @@ * Given a pointer to an interface in the kernel, return a pointer to a * string which is the interface name. */ +#if 0 char *getifname(ptr) struct ifnet *ptr; { @@ -74,3 +83,10 @@ struct ifnet *ptr; # endif #endif } +#else +char *getifname(ptr) +struct ifnet *ptr; +{ + return "X"; +} +#endif diff --git a/contrib/ipfilter/lib/getnattype.c b/contrib/ipfilter/lib/getnattype.c index beb0a8a..2fb5d17 100644 --- a/contrib/ipfilter/lib/getnattype.c +++ b/contrib/ipfilter/lib/getnattype.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2002-2004 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * @@ -11,26 +11,34 @@ #include "kmem.h" #if !defined(lint) -static const char rcsid[] = "@(#)$Id: getnattype.c,v 1.3 2004/01/17 17:26:07 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: getnattype.c,v 1.3.2.2 2006/07/14 06:12:24 darrenr Exp $"; #endif /* * Get a nat filter type given its kernel address. */ -char *getnattype(ipnat) -ipnat_t *ipnat; +char *getnattype(nat, alive) +nat_t *nat; +int alive; { static char unknownbuf[20]; - ipnat_t ipnatbuff; + ipnat_t *ipn, ipnat; char *which; + int type; - if (!ipnat) + if (!nat) return "???"; - if (kmemcpy((char *)&ipnatbuff, (long)ipnat, sizeof(ipnatbuff))) - 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 (ipnatbuff.in_redir) + switch (type) { case NAT_MAP : which = "MAP"; @@ -45,8 +53,7 @@ ipnat_t *ipnat; which = "BIMAP"; break; default : - sprintf(unknownbuf, "unknown(%04x)", - ipnatbuff.in_redir & 0xffffffff); + sprintf(unknownbuf, "unknown(%04x)", type & 0xffffffff); which = unknownbuf; break; } diff --git a/contrib/ipfilter/lib/getport.c b/contrib/ipfilter/lib/getport.c index 51c39b1..69e897c 100644 --- a/contrib/ipfilter/lib/getport.c +++ b/contrib/ipfilter/lib/getport.c @@ -1,5 +1,13 @@ /* $FreeBSD$ */ +/* + * 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 $ + */ + #include "ipf.h" int getport(fr, name, port) diff --git a/contrib/ipfilter/lib/getportproto.c b/contrib/ipfilter/lib/getportproto.c index 02e3c20..23e5fb1 100644 --- a/contrib/ipfilter/lib/getportproto.c +++ b/contrib/ipfilter/lib/getportproto.c @@ -1,5 +1,13 @@ /* $FreeBSD$ */ +/* + * 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 $ + */ + #include <ctype.h> #include "ipf.h" diff --git a/contrib/ipfilter/lib/getproto.c b/contrib/ipfilter/lib/getproto.c index ec87490..33f6f47 100644 --- a/contrib/ipfilter/lib/getproto.c +++ b/contrib/ipfilter/lib/getproto.c @@ -1,5 +1,13 @@ /* $FreeBSD$ */ +/* + * 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 $ + */ + #include "ipf.h" int getproto(name) diff --git a/contrib/ipfilter/lib/getsumd.c b/contrib/ipfilter/lib/getsumd.c index 44ff3aa..fdad461 100644 --- a/contrib/ipfilter/lib/getsumd.c +++ b/contrib/ipfilter/lib/getsumd.c @@ -1,5 +1,13 @@ /* $FreeBSD$ */ +/* + * 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 $ + */ + #include "ipf.h" char *getsumd(sum) diff --git a/contrib/ipfilter/lib/hostname.c b/contrib/ipfilter/lib/hostname.c index c4950e9..e8fde98 100644 --- a/contrib/ipfilter/lib/hostname.c +++ b/contrib/ipfilter/lib/hostname.c @@ -1,5 +1,12 @@ /* $FreeBSD$ */ +/* + * 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 $ + */ #include "ipf.h" @@ -12,6 +19,8 @@ void *ip; struct in_addr ipa; struct netent *np; + memset(&ipa, 0, sizeof(ipa)); /* XXX gcc */ + if (v == 4) { ipa.s_addr = *(u_32_t *)ip; if (ipa.s_addr == htonl(0xfedcba98)) diff --git a/contrib/ipfilter/lib/icmpcode.c b/contrib/ipfilter/lib/icmpcode.c index 864fac1..d558beb 100644 --- a/contrib/ipfilter/lib/icmpcode.c +++ b/contrib/ipfilter/lib/icmpcode.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2006 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: icmpcode.c,v 1.7.2.4 2006/02/25 17:40:22 darrenr Exp $ + * $Id: icmpcode.c,v 1.7.2.5 2006/06/16 17:21:02 darrenr Exp $ */ #include <ctype.h> diff --git a/contrib/ipfilter/lib/initparse.c b/contrib/ipfilter/lib/initparse.c index 5f52f95..6fdfc8a 100644 --- a/contrib/ipfilter/lib/initparse.c +++ b/contrib/ipfilter/lib/initparse.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2002 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: initparse.c,v 1.6 2002/01/28 06:50:46 darrenr Exp $ + * $Id: initparse.c,v 1.6.4.1 2006/06/16 17:21:02 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/ionames.c b/contrib/ipfilter/lib/ionames.c index 5d7d2ac..d2fc977 100644 --- a/contrib/ipfilter/lib/ionames.c +++ b/contrib/ipfilter/lib/ionames.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2005 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ionames.c,v 1.7 2002/01/28 06:50:46 darrenr Exp $ + * $Id: ionames.c,v 1.7.4.1 2006/06/16 17:21:02 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/ipf_dotuning.c b/contrib/ipfilter/lib/ipf_dotuning.c index 3f146d7..6508a26 100644 --- a/contrib/ipfilter/lib/ipf_dotuning.c +++ b/contrib/ipfilter/lib/ipf_dotuning.c @@ -1,5 +1,13 @@ /* $FreeBSD$ */ +/* + * 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 $ + */ + #include "ipf.h" #include "netinet/ipl.h" #include <sys/ioctl.h> diff --git a/contrib/ipfilter/lib/ipft_ef.c b/contrib/ipfilter/lib/ipft_ef.c index 9e2093f..2d50f07 100644 --- a/contrib/ipfilter/lib/ipft_ef.c +++ b/contrib/ipfilter/lib/ipft_ef.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2006 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ipft_ef.c,v 1.14 2004/01/08 13:34:31 darrenr Exp $ + * $Id: ipft_ef.c,v 1.14.2.2 2006/06/16 17:21:02 darrenr Exp $ */ /* @@ -33,7 +33,7 @@ etherfind -n -t #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 2004/01/08 13:34:31 darrenr Exp $"; +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 *)); @@ -98,13 +98,18 @@ int cnt, *dir; 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 : - s = strtok(NULL, " :"); - 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); + 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 : diff --git a/contrib/ipfilter/lib/ipft_hx.c b/contrib/ipfilter/lib/ipft_hx.c index efc0a413..d295c21 100644 --- a/contrib/ipfilter/lib/ipft_hx.c +++ b/contrib/ipfilter/lib/ipft_hx.c @@ -1,13 +1,13 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1995-2001 by Darren Reed. + * Copyright (C) 2000-2005 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.3 2005/12/04 10:07:21 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ipft_hx.c,v 1.11.4.4 2006/06/16 17:21:03 darrenr Exp $"; #endif #include <ctype.h> diff --git a/contrib/ipfilter/lib/ipft_pc.c b/contrib/ipfilter/lib/ipft_pc.c index e3e2bd3..0f31a10 100644 --- a/contrib/ipfilter/lib/ipft_pc.c +++ b/contrib/ipfilter/lib/ipft_pc.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2005 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ipft_pc.c,v 1.10.2.1 2005/12/04 09:55:10 darrenr Exp $ + * $Id: ipft_pc.c,v 1.10.2.2 2006/06/16 17:21:03 darrenr Exp $ */ #include "ipf.h" #include "pcap-ipf.h" @@ -13,7 +13,7 @@ #include "ipt.h" #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ipft_pc.c,v 1.10.2.1 2005/12/04 09:55:10 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ipft_pc.c,v 1.10.2.2 2006/06/16 17:21:03 darrenr Exp $"; #endif struct llc { diff --git a/contrib/ipfilter/lib/ipft_sn.c b/contrib/ipfilter/lib/ipft_sn.c index 5841ed5..2beb6ee 100644 --- a/contrib/ipfilter/lib/ipft_sn.c +++ b/contrib/ipfilter/lib/ipft_sn.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2003 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ipft_sn.c,v 1.7 2003/02/16 02:32:36 darrenr Exp $ + * $Id: ipft_sn.c,v 1.7.4.1 2006/06/16 17:21:03 darrenr Exp $ */ /* @@ -16,7 +16,7 @@ #include "ipt.h" #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ipft_sn.c,v 1.7 2003/02/16 02:32:36 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ipft_sn.c,v 1.7.4.1 2006/06/16 17:21:03 darrenr Exp $"; #endif struct llc { diff --git a/contrib/ipfilter/lib/ipft_td.c b/contrib/ipfilter/lib/ipft_td.c index 758eb51..d571ada 100644 --- a/contrib/ipfilter/lib/ipft_td.c +++ b/contrib/ipfilter/lib/ipft_td.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2006 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ipft_td.c,v 1.15 2004/01/08 13:34:31 darrenr Exp $ + * $Id: ipft_td.c,v 1.15.2.2 2006/06/16 17:21:03 darrenr Exp $ */ /* @@ -42,7 +42,7 @@ tcpdump -nqte #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 2004/01/08 13:34:31 darrenr Exp $"; +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 *)); @@ -144,6 +144,8 @@ int cnt, *dir; IP_HL_A(ip, sizeof(ip_t)); s = strtok(misc, " :"); + if (s == NULL) + return 0; ip->ip_p = getproto(s); switch (ip->ip_p) @@ -151,6 +153,8 @@ int cnt, *dir; 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); diff --git a/contrib/ipfilter/lib/ipft_tx.c b/contrib/ipfilter/lib/ipft_tx.c index 36d89be..c613d6b 100644 --- a/contrib/ipfilter/lib/ipft_tx.c +++ b/contrib/ipfilter/lib/ipft_tx.c @@ -1,15 +1,15 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1995-2001 by Darren Reed. + * Copyright (C) 2000-2006 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ipft_tx.c,v 1.15.2.7 2005/12/18 14:53:39 darrenr Exp $ + * $Id: ipft_tx.c,v 1.15.2.9 2006/06/16 17:21:04 darrenr Exp $ */ #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.7 2005/12/18 14:53:39 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ipft_tx.c,v 1.15.2.9 2006/06/16 17:21:04 darrenr Exp $"; #endif #include <ctype.h> @@ -129,6 +129,7 @@ int cnt, *dir; { register char *s; char line[513]; + ip_t *ip; *ifn = NULL; while (fgets(line, sizeof(line)-1, tfp)) { @@ -144,12 +145,10 @@ int cnt, *dir; 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 + if (!parseline(line, (ip_t *)buf, ifn, dir)) { + ip = (ip_t *)buf; + return ntohs(ip->ip_len); + } } if (feof(tfp)) return 0; diff --git a/contrib/ipfilter/lib/ipoptsec.c b/contrib/ipfilter/lib/ipoptsec.c index 5990170..66a55c8 100644 --- a/contrib/ipfilter/lib/ipoptsec.c +++ b/contrib/ipfilter/lib/ipoptsec.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2001-2002 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ipoptsec.c,v 1.2 2002/01/28 06:50:46 darrenr Exp $ + * $Id: ipoptsec.c,v 1.2.4.1 2006/06/16 17:21:04 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/kmem.c b/contrib/ipfilter/lib/kmem.c index 04a64d1..26da2d0 100644 --- a/contrib/ipfilter/lib/kmem.c +++ b/contrib/ipfilter/lib/kmem.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2005 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -44,7 +44,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.2 2005/06/12 07:18:41 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: kmem.c,v 1.16.2.3 2006/06/16 17:21:04 darrenr Exp $"; #endif diff --git a/contrib/ipfilter/lib/kmem.h b/contrib/ipfilter/lib/kmem.h index c1dd7f9..bcfde06 100644 --- a/contrib/ipfilter/lib/kmem.h +++ b/contrib/ipfilter/lib/kmem.h @@ -1,10 +1,10 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2002 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. - * $Id: kmem.h,v 1.2 2002/08/21 22:57:36 darrenr Exp $ + * $Id: kmem.h,v 1.2.4.1 2006/06/16 17:21:04 darrenr Exp $ */ #ifndef __KMEM_H__ diff --git a/contrib/ipfilter/lib/kmemcpywrap.c b/contrib/ipfilter/lib/kmemcpywrap.c index 4eeb62d..8747491 100644 --- a/contrib/ipfilter/lib/kmemcpywrap.c +++ b/contrib/ipfilter/lib/kmemcpywrap.c @@ -1,5 +1,13 @@ /* $FreeBSD$ */ +/* + * 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 $ + */ + #include "ipf.h" #include "kmem.h" diff --git a/contrib/ipfilter/lib/kvatoname.c b/contrib/ipfilter/lib/kvatoname.c index a3764e4..c8c0d8f 100644 --- a/contrib/ipfilter/lib/kvatoname.c +++ b/contrib/ipfilter/lib/kvatoname.c @@ -1,5 +1,13 @@ /* $FreeBSD$ */ +/* + * 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 $ + */ + #include "ipf.h" #include <fcntl.h> diff --git a/contrib/ipfilter/lib/load_hash.c b/contrib/ipfilter/lib/load_hash.c index ff093c9..7683470 100644 --- a/contrib/ipfilter/lib/load_hash.c +++ b/contrib/ipfilter/lib/load_hash.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2002 by Darren Reed. + * Copyright (C) 2002-2005 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: load_hash.c,v 1.11.2.3 2005/11/13 15:41:12 darrenr Exp $ + * $Id: load_hash.c,v 1.11.2.5 2006/07/14 06:12:25 darrenr Exp $ */ #include <fcntl.h> @@ -62,6 +62,7 @@ ioctlfunc_t iocfunc; 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) { @@ -85,9 +86,10 @@ ioctlfunc_t iocfunc; perror("calloc(size, sizeof(*iph.iph_table))"); return -1; } - iph.iph_table[0] = list; + iph.iph_list = list; printhash(&iph, bcopywrap, iph.iph_name, opts); 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); diff --git a/contrib/ipfilter/lib/load_hashnode.c b/contrib/ipfilter/lib/load_hashnode.c index 083bea8..3c3416d 100644 --- a/contrib/ipfilter/lib/load_hashnode.c +++ b/contrib/ipfilter/lib/load_hashnode.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2002 by Darren Reed. + * Copyright (C) 2003-2005 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: load_hashnode.c,v 1.2.4.1 2004/03/06 14:33:28 darrenr Exp $ + * $Id: load_hashnode.c,v 1.2.4.2 2006/06/16 17:21:05 darrenr Exp $ */ #include <fcntl.h> diff --git a/contrib/ipfilter/lib/load_pool.c b/contrib/ipfilter/lib/load_pool.c index 574cd2c..08baae7 100644 --- a/contrib/ipfilter/lib/load_pool.c +++ b/contrib/ipfilter/lib/load_pool.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2002 by Darren Reed. + * Copyright (C) 2002-2005 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: load_pool.c,v 1.14.2.3 2005/11/13 15:41:13 darrenr Exp $ + * $Id: load_pool.c,v 1.14.2.4 2006/06/16 17:21:06 darrenr Exp $ */ #include <fcntl.h> diff --git a/contrib/ipfilter/lib/load_poolnode.c b/contrib/ipfilter/lib/load_poolnode.c index e8a6fe6..110a8b9 100644 --- a/contrib/ipfilter/lib/load_poolnode.c +++ b/contrib/ipfilter/lib/load_poolnode.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2002 by Darren Reed. + * Copyright (C) 2003-2004 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: load_poolnode.c,v 1.3.2.1 2004/03/06 14:33:29 darrenr Exp $ + * $Id: load_poolnode.c,v 1.3.2.3 2006/06/16 17:21:06 darrenr Exp $ */ #include <fcntl.h> @@ -54,7 +54,7 @@ ioctlfunc_t iocfunc; if (err != 0) { if ((opts & OPT_DONOTHING) == 0) { - perror("load_pool:SIOCLOOKUP*NODE"); + perror("load_poolnode:SIOCLOOKUP*NODE"); return -1; } } diff --git a/contrib/ipfilter/lib/mutex_emul.c b/contrib/ipfilter/lib/mutex_emul.c index 10472e5..3983f04 100644 --- a/contrib/ipfilter/lib/mutex_emul.c +++ b/contrib/ipfilter/lib/mutex_emul.c @@ -1,5 +1,13 @@ /* $FreeBSD$ */ +/* + * 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 $ + */ + #include "ipf.h" #define EMM_MAGIC 0x9d7adba3 diff --git a/contrib/ipfilter/lib/nametokva.c b/contrib/ipfilter/lib/nametokva.c index b2854d6..deee439 100644 --- a/contrib/ipfilter/lib/nametokva.c +++ b/contrib/ipfilter/lib/nametokva.c @@ -1,5 +1,13 @@ /* $FreeBSD$ */ +/* + * 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 $ + */ + #include "ipf.h" #include <sys/ioctl.h> diff --git a/contrib/ipfilter/lib/nat_setgroupmap.c b/contrib/ipfilter/lib/nat_setgroupmap.c index d4e637e..08b1a0a 100644 --- a/contrib/ipfilter/lib/nat_setgroupmap.c +++ b/contrib/ipfilter/lib/nat_setgroupmap.c @@ -1,12 +1,12 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2003 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 2003/04/13 06:40:14 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: nat_setgroupmap.c,v 1.1.4.1 2006/06/16 17:21:07 darrenr Exp $"; #endif #include "ipf.h" diff --git a/contrib/ipfilter/lib/ntomask.c b/contrib/ipfilter/lib/ntomask.c index c95f78f..ba91a65 100644 --- a/contrib/ipfilter/lib/ntomask.c +++ b/contrib/ipfilter/lib/ntomask.c @@ -1,5 +1,13 @@ /* $FreeBSD$ */ +/* + * 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 $ + */ + #include "ipf.h" int ntomask(v, nbits, ap) diff --git a/contrib/ipfilter/lib/optname.c b/contrib/ipfilter/lib/optname.c index 813a0df..f41cab1 100644 --- a/contrib/ipfilter/lib/optname.c +++ b/contrib/ipfilter/lib/optname.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2001 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: optname.c,v 1.3 2001/06/09 17:09:24 darrenr Exp $ + * $Id: optname.c,v 1.3.4.1 2006/06/16 17:21:07 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/optprint.c b/contrib/ipfilter/lib/optprint.c index 7f18318..81a3287 100644 --- a/contrib/ipfilter/lib/optprint.c +++ b/contrib/ipfilter/lib/optprint.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2005 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: optprint.c,v 1.6.4.1 2005/12/18 14:51:28 darrenr Exp $ + * $Id: optprint.c,v 1.6.4.2 2006/06/16 17:21:08 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/optprintv6.c b/contrib/ipfilter/lib/optprintv6.c index 086496d..f6ea6ec 100644 --- a/contrib/ipfilter/lib/optprintv6.c +++ b/contrib/ipfilter/lib/optprintv6.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2003 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: optprintv6.c,v 1.2 2003/04/30 00:39:39 darrenr Exp $ + * $Id: optprintv6.c,v 1.2.4.1 2006/06/16 17:21:08 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/optvalue.c b/contrib/ipfilter/lib/optvalue.c index 3609448..aa1ef2e 100644 --- a/contrib/ipfilter/lib/optvalue.c +++ b/contrib/ipfilter/lib/optvalue.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2001-2002 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: optvalue.c,v 1.2 2002/01/28 06:50:47 darrenr Exp $ + * $Id: optvalue.c,v 1.2.4.1 2006/06/16 17:21:08 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/portname.c b/contrib/ipfilter/lib/portname.c index 4bf1c09..f0c8625 100644 --- a/contrib/ipfilter/lib/portname.c +++ b/contrib/ipfilter/lib/portname.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2003 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: portname.c,v 1.7 2003/08/14 14:27:43 darrenr Exp $ + * $Id: portname.c,v 1.7.2.1 2006/06/16 17:21:09 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/print_toif.c b/contrib/ipfilter/lib/print_toif.c index 4431004..94a4618 100644 --- a/contrib/ipfilter/lib/print_toif.c +++ b/contrib/ipfilter/lib/print_toif.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2002 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: print_toif.c,v 1.8 2002/01/28 06:50:47 darrenr Exp $ + * $Id: print_toif.c,v 1.8.4.1 2006/06/16 17:21:09 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/printactivenat.c b/contrib/ipfilter/lib/printactivenat.c index 2155378..a2e2924 100644 --- a/contrib/ipfilter/lib/printactivenat.c +++ b/contrib/ipfilter/lib/printactivenat.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2002-2004 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * @@ -12,16 +12,17 @@ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: printactivenat.c,v 1.3.2.4 2004/05/11 16:07:32 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: printactivenat.c,v 1.3.2.7 2006/12/12 16:13:00 darrenr Exp $"; #endif -void printactivenat(nat, opts) +void printactivenat(nat, opts, alive, now) nat_t *nat; -int opts; +int opts, alive; +u_long now; { - printf("%s", getnattype(nat->nat_ptr)); + printf("%s", getnattype(nat, alive)); if (nat->nat_flags & SI_CLONE) printf(" CLONE"); @@ -42,8 +43,9 @@ int opts; printf("]"); if (opts & OPT_VERBOSE) { - printf("\n\tage %lu use %hu sumd %s/", - nat->nat_age, nat->nat_use, getsumd(nat->nat_sumd[0])); + printf("\n\tttl %lu use %hu sumd %s/", + nat->nat_age - now, 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, nat->nat_hv[0], nat->nat_hv[1], nat->nat_flags); diff --git a/contrib/ipfilter/lib/printaps.c b/contrib/ipfilter/lib/printaps.c index 235a5fd..87a12cd4 100644 --- a/contrib/ipfilter/lib/printaps.c +++ b/contrib/ipfilter/lib/printaps.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2002-2004 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * @@ -13,7 +13,7 @@ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: printaps.c,v 1.4 2004/01/08 13:34:32 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: printaps.c,v 1.4.2.1 2006/06/16 17:21:10 darrenr Exp $"; #endif diff --git a/contrib/ipfilter/lib/printbuf.c b/contrib/ipfilter/lib/printbuf.c index 1f0763e..b2e209a 100644 --- a/contrib/ipfilter/lib/printbuf.c +++ b/contrib/ipfilter/lib/printbuf.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2004 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: printbuf.c,v 1.5.4.1 2004/12/09 19:41:22 darrenr Exp $ + * $Id: printbuf.c,v 1.5.4.2 2006/06/16 17:21:10 darrenr Exp $ */ #include <ctype.h> diff --git a/contrib/ipfilter/lib/printfr.c b/contrib/ipfilter/lib/printfr.c index 6ad81e1..587d8cb 100644 --- a/contrib/ipfilter/lib/printfr.c +++ b/contrib/ipfilter/lib/printfr.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2006 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: printfr.c,v 1.43.2.16 2006/03/29 11:19:59 darrenr Exp $ + * $Id: printfr.c,v 1.43.2.18 2007/05/07 06:55:38 darrenr Exp $ */ #include "ipf.h" @@ -470,7 +470,12 @@ ioctlfunc_t iocfunc; } printf(")"); } + if (fp->fr_pps) printf(" pps %d", fp->fr_pps); + + if ((fp->fr_flags & FR_KEEPSTATE) && (opts & OPT_VERBOSE)) { + printf(" # count %d", fp->fr_statecnt); + } (void)putchar('\n'); } diff --git a/contrib/ipfilter/lib/printfraginfo.c b/contrib/ipfilter/lib/printfraginfo.c index 05c0399..d9317e8 100644 --- a/contrib/ipfilter/lib/printfraginfo.c +++ b/contrib/ipfilter/lib/printfraginfo.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2004 by Darren Reed. + * Copyright (C) 2004-2005 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: printfraginfo.c,v 1.1.2.2 2004/03/23 15:15:45 darrenr Exp $ + * $Id: printfraginfo.c,v 1.1.2.5 2006/12/25 15:10:37 darrenr Exp $ */ #include "ipf.h" #include "kmem.h" @@ -19,11 +19,12 @@ struct ipfr *ifr; fr.fr_flags = 0xffffffff; printf("%s%s -> ", prefix, hostname(4, &ifr->ipfr_src)); +/* if (kmemcpy((char *)&fr, (u_long)ifr->ipfr_rule, sizeof(fr)) == -1) return; - printf("%s id %d ttl %d pr %d seen0 %d ifp %p tos %#02x = %#x\n", - hostname(4, &ifr->ipfr_dst), ifr->ipfr_id, ifr->ipfr_seen0, - ifr->ipfr_ttl, ifr->ipfr_p, ifr->ipfr_ifp, ifr->ipfr_tos, - fr.fr_flags); +*/ + 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); } diff --git a/contrib/ipfilter/lib/printhash.c b/contrib/ipfilter/lib/printhash.c index fab0659..975b60e 100644 --- a/contrib/ipfilter/lib/printhash.c +++ b/contrib/ipfilter/lib/printhash.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2002 by Darren Reed. + * Copyright (C) 2002-2005 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -20,7 +20,7 @@ int opts; { iphtent_t *ipep, **table; iphtable_t iph; - int i, printed; + int printed; size_t sz; if ((*copyfunc)((char *)hp, (char *)&iph, sizeof(iph))) @@ -29,94 +29,10 @@ int opts; if ((name != NULL) && strncmp(name, iph.iph_name, FR_GROUPLEN)) return iph.iph_next; - if ((opts & OPT_DEBUG) == 0) { - if ((iph.iph_type & IPHASH_ANON) == IPHASH_ANON) - PRINTF("# 'anonymous' table\n"); - switch (iph.iph_type & ~IPHASH_ANON) - { - case IPHASH_LOOKUP : - PRINTF("table"); - break; - case IPHASH_GROUPMAP : - PRINTF("group-map"); - if (iph.iph_flags & FR_INQUE) - PRINTF(" in"); - else if (iph.iph_flags & FR_OUTQUE) - PRINTF(" out"); - else - PRINTF(" ???"); - break; - default : - PRINTF("%#x", iph.iph_type); - break; - } - PRINTF(" role = "); - } else { - PRINTF("Hash Table Number: %s", iph.iph_name); - if ((iph.iph_type & IPHASH_ANON) == IPHASH_ANON) - PRINTF("(anon)"); - putchar(' '); - PRINTF("Role: "); - } - - switch (iph.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", iph.iph_unit); - break; - } - - if ((opts & OPT_DEBUG) == 0) { - if ((iph.iph_type & ~IPHASH_ANON) == IPHASH_LOOKUP) - PRINTF(" type = hash"); - PRINTF(" number = %s size = %lu", - iph.iph_name, (u_long)iph.iph_size); - if (iph.iph_seed != 0) - PRINTF(" seed = %lu", iph.iph_seed); - putchar('\n'); - } else { - PRINTF(" Type: "); - switch (iph.iph_type & ~IPHASH_ANON) - { - case IPHASH_LOOKUP : - PRINTF("lookup"); - break; - case IPHASH_GROUPMAP : - PRINTF("groupmap Group. %s", iph.iph_name); - break; - default : - break; - } + printhashdata(hp, opts); - putchar('\n'); - PRINTF("\t\tSize: %lu\tSeed: %lu", - (u_long)iph.iph_size, iph.iph_seed); - PRINTF("\tRef. Count: %d\tMasks: %#x\n", iph.iph_ref, - iph.iph_masks); - } - - if ((opts & OPT_DEBUG) != 0) { - struct in_addr m; - - for (i = 0; i < 32; i++) { - if ((1 << i) & iph.iph_masks) { - ntomask(4, i, &m.s_addr); - PRINTF("\t\tMask: %s\n", inet_ntoa(m)); - } - } - } + if ((hp->iph_flags & IPHASH_DELETE) != 0) + PRINTF("# "); if ((opts & OPT_DEBUG) == 0) PRINTF("\t{"); @@ -126,11 +42,9 @@ int opts; if ((*copyfunc)((char *)iph.iph_table, (char *)table, sz)) return NULL; - for (i = 0, printed = 0; i < iph.iph_size; i++) { - for (ipep = table[i]; ipep != NULL; ) { - ipep = printhashnode(&iph, ipep, copyfunc, opts); - printed++; - } + for (printed = 0, ipep = iph.iph_list; ipep != NULL; ) { + ipep = printhashnode(&iph, ipep, copyfunc, opts); + printed++; } if (printed == 0) putchar(';'); diff --git a/contrib/ipfilter/lib/printhashnode.c b/contrib/ipfilter/lib/printhashnode.c index b5eda15..ed83c39 100644 --- a/contrib/ipfilter/lib/printhashnode.c +++ b/contrib/ipfilter/lib/printhashnode.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2002 by Darren Reed. + * Copyright (C) 2002-2005 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -47,6 +47,7 @@ int opts; } putchar(';'); } + ipep = ipe.ipe_next; return ipep; } diff --git a/contrib/ipfilter/lib/printhostmap.c b/contrib/ipfilter/lib/printhostmap.c index cb5f8e7..0c9242f 100644 --- a/contrib/ipfilter/lib/printhostmap.c +++ b/contrib/ipfilter/lib/printhostmap.c @@ -1,16 +1,22 @@ /* $FreeBSD$ */ +/* + * 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 $ + */ + #include "ipf.h" void printhostmap(hmp, hv) hostmap_t *hmp; u_int hv; { - struct in_addr in; printf("%s,", inet_ntoa(hmp->hm_srcip)); printf("%s -> ", inet_ntoa(hmp->hm_dstip)); - in.s_addr = htonl(hmp->hm_mapip.s_addr); - printf("%s ", inet_ntoa(in)); + printf("%s ", inet_ntoa(hmp->hm_mapip)); printf("(use = %d hv = %u)\n", hmp->hm_ref, hv); } diff --git a/contrib/ipfilter/lib/printhostmask.c b/contrib/ipfilter/lib/printhostmask.c index 19f87a6..44703c4 100644 --- a/contrib/ipfilter/lib/printhostmask.c +++ b/contrib/ipfilter/lib/printhostmask.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2005 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: printhostmask.c,v 1.8 2002/04/11 15:01:19 darrenr Exp $ + * $Id: printhostmask.c,v 1.8.4.1 2006/06/16 17:21:12 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/printifname.c b/contrib/ipfilter/lib/printifname.c index bc74a34..2f7d912 100644 --- a/contrib/ipfilter/lib/printifname.c +++ b/contrib/ipfilter/lib/printifname.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2002 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: printifname.c,v 1.2 2002/01/28 06:50:47 darrenr Exp $ + * $Id: printifname.c,v 1.2.4.1 2006/06/16 17:21:12 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/printip.c b/contrib/ipfilter/lib/printip.c index 8841f0a..8c008af 100644 --- a/contrib/ipfilter/lib/printip.c +++ b/contrib/ipfilter/lib/printip.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2002-2005 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: printip.c,v 1.3 2002/07/13 12:10:27 darrenr Exp $ + * $Id: printip.c,v 1.3.4.1 2006/06/16 17:21:12 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/printlog.c b/contrib/ipfilter/lib/printlog.c index dd18e98..82c0400 100644 --- a/contrib/ipfilter/lib/printlog.c +++ b/contrib/ipfilter/lib/printlog.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2005 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: printlog.c,v 1.6.4.2 2005/12/18 14:49:06 darrenr Exp $ + * $Id: printlog.c,v 1.6.4.3 2006/06/16 17:21:12 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/printmask.c b/contrib/ipfilter/lib/printmask.c index 195b9a9..9230dc0 100644 --- a/contrib/ipfilter/lib/printmask.c +++ b/contrib/ipfilter/lib/printmask.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2005 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: printmask.c,v 1.5 2002/06/15 04:48:33 darrenr Exp $ + * $Id: printmask.c,v 1.5.4.1 2006/06/16 17:21:13 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/printnat.c b/contrib/ipfilter/lib/printnat.c index 67b5a27..06ed9a3 100644 --- a/contrib/ipfilter/lib/printnat.c +++ b/contrib/ipfilter/lib/printnat.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2002-2005 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * @@ -13,7 +13,7 @@ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: printnat.c,v 1.22.2.11 2005/11/14 17:45:06 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: printnat.c,v 1.22.2.13 2006/12/09 10:37:47 darrenr Exp $"; #endif /* @@ -48,10 +48,16 @@ int opts; break; } - printf(" %s", np->in_ifnames[0]); + if (!strcmp(np->in_ifnames[0], "-")) + printf(" \"%s\"", 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)) { - printf(",%s", np->in_ifnames[1]); + if (!strcmp(np->in_ifnames[1], "-")) + printf(",\"%s\"", np->in_ifnames[1]); + else + printf(",%s", np->in_ifnames[1]); } putchar(' '); diff --git a/contrib/ipfilter/lib/printpacket.c b/contrib/ipfilter/lib/printpacket.c index 7090e38..cff13eb 100644 --- a/contrib/ipfilter/lib/printpacket.c +++ b/contrib/ipfilter/lib/printpacket.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2005 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: printpacket.c,v 1.12.4.2 2005/12/04 09:33:06 darrenr Exp $ + * $Id: printpacket.c,v 1.12.4.4 2006/09/30 21:44:43 darrenr Exp $ */ #include "ipf.h" @@ -43,6 +43,7 @@ struct ip *ip; putchar(' '); } putchar('\n'); + putchar('\n'); return; } diff --git a/contrib/ipfilter/lib/printpacket6.c b/contrib/ipfilter/lib/printpacket6.c index 2ddffed..ca3b421 100644 --- a/contrib/ipfilter/lib/printpacket6.c +++ b/contrib/ipfilter/lib/printpacket6.c @@ -1,5 +1,13 @@ /* $FreeBSD$ */ +/* + * 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 $ + */ + #include "ipf.h" /* diff --git a/contrib/ipfilter/lib/printpool.c b/contrib/ipfilter/lib/printpool.c index 4bd48aa..4ab85fa 100644 --- a/contrib/ipfilter/lib/printpool.c +++ b/contrib/ipfilter/lib/printpool.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2002 by Darren Reed. + * Copyright (C) 2002-2005 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -26,58 +26,12 @@ int opts; if ((name != NULL) && strncmp(name, ipp.ipo_name, FR_GROUPLEN)) return ipp.ipo_next; - if ((opts & OPT_DEBUG) == 0) { - if ((ipp.ipo_flags & IPOOL_ANON) != 0) - PRINTF("# 'anonymous' tree %s\n", ipp.ipo_name); - PRINTF("table role = "); - } else { - PRINTF("Name: %s", ipp.ipo_name); - if ((ipp.ipo_flags & IPOOL_ANON) == IPOOL_ANON) - PRINTF("(anon)"); - putchar(' '); - PRINTF("Role: "); - } - - switch (ipp.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)", ipp.ipo_unit); - } + printpooldata(&ipp, opts); - if ((opts & OPT_DEBUG) == 0) { - PRINTF(" type = tree number = %s\n", ipp.ipo_name); + if ((ipp.ipo_flags & IPOOL_DELETE) != 0) + PRINTF("# "); + if ((opts & OPT_DEBUG) == 0) PRINTF("\t{"); - } else { - putchar(' '); - - PRINTF("\tReferences: %d\tHits: %lu\n", ipp.ipo_ref, - ipp.ipo_hits); - PRINTF("\tNodes Starting at %p\n", ipp.ipo_list); - } ipnpn = ipp.ipo_list; ipp.ipo_list = NULL; diff --git a/contrib/ipfilter/lib/printpoolnode.c b/contrib/ipfilter/lib/printpoolnode.c index ec8ac3e..3327b8a 100644 --- a/contrib/ipfilter/lib/printpoolnode.c +++ b/contrib/ipfilter/lib/printpoolnode.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2002 by Darren Reed. + * Copyright (C) 2002-2005 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -23,11 +23,11 @@ int opts; printip((u_32_t *)&np->ipn_addr.adf_addr.in4); printmask((u_32_t *)&np->ipn_mask.adf_addr); } else { - PRINTF("\t\t%s%s", np->ipn_info ? "! " : "", + 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("\n\t\tHits %lu\tName %s\n", - np->ipn_hits, np->ipn_name); + PRINTF("\t\tHits %lu\tName %s\tRef %d\n", + np->ipn_hits, np->ipn_name, np->ipn_ref); } return np->ipn_next; } diff --git a/contrib/ipfilter/lib/printportcmp.c b/contrib/ipfilter/lib/printportcmp.c index 3f00db7..6a1a461 100644 --- a/contrib/ipfilter/lib/printportcmp.c +++ b/contrib/ipfilter/lib/printportcmp.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2003 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: printportcmp.c,v 1.7 2003/02/16 02:31:05 darrenr Exp $ + * $Id: printportcmp.c,v 1.7.4.1 2006/06/16 17:21:14 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/printsbuf.c b/contrib/ipfilter/lib/printsbuf.c index cfa9171..f6c633c 100644 --- a/contrib/ipfilter/lib/printsbuf.c +++ b/contrib/ipfilter/lib/printsbuf.c @@ -1,5 +1,13 @@ /* $FreeBSD$ */ +/* + * 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 $ + */ + #ifdef IPFILTER_SCAN #include <ctype.h> diff --git a/contrib/ipfilter/lib/printstate.c b/contrib/ipfilter/lib/printstate.c index c8e238d..43621ef 100644 --- a/contrib/ipfilter/lib/printstate.c +++ b/contrib/ipfilter/lib/printstate.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2002 by Darren Reed. + * Copyright (C) 2002-2005 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -17,64 +17,64 @@ ipstate_t *sp; int opts; u_long now; { - ipstate_t ips; synclist_t ipsync; - if (kmemcpy((char *)&ips, (u_long)sp, sizeof(ips))) - return NULL; - - PRINTF("%s -> ", hostname(ips.is_v, &ips.is_src.in4)); - PRINTF("%s pass %#x pr %d state %d/%d bkt %d\n", - hostname(ips.is_v, &ips.is_dst.in4), ips.is_pass, ips.is_p, - ips.is_state[0], ips.is_state[1], ips.is_hv); - PRINTF("\ttag %u ttl %lu", ips.is_tag, ips.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); - if (ips.is_p == IPPROTO_TCP) { + if (sp->is_p == IPPROTO_TCP) { PRINTF("\n\t%hu -> %hu %x:%x %hu<<%d:%hu<<%d\n", - ntohs(ips.is_sport), ntohs(ips.is_dport), - ips.is_send, ips.is_dend, - ips.is_maxswin, ips.is_swinscale, - ips.is_maxdwin, ips.is_dwinscale); + ntohs(sp->is_sport), ntohs(sp->is_dport), + sp->is_send, sp->is_dend, + sp->is_maxswin, sp->is_swinscale, + sp->is_maxdwin, sp->is_dwinscale); PRINTF("\tcmsk %04x smsk %04x isc %p s0 %08x/%08x\n", - ips.is_smsk[0], ips.is_smsk[1], ips.is_isc, - ips.is_s0[0], ips.is_s0[1]); + 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", - ips.is_isninc[0], ips.is_sumd[0]); + sp->is_isninc[0], sp->is_sumd[0]); PRINTF("\tREV:ISN inc %x sumd %x\n", - ips.is_isninc[1], ips.is_sumd[1]); + sp->is_isninc[1], sp->is_sumd[1]); #ifdef IPFILTER_SCAN PRINTF("\tsbuf[0] ["); - printsbuf(ips.is_sbuf[0]); + printsbuf(sp->is_sbuf[0]); PRINTF("] sbuf[1] ["); - printsbuf(ips.is_sbuf[1]); + printsbuf(sp->is_sbuf[1]); PRINTF("]\n"); #endif - } else if (ips.is_p == IPPROTO_UDP) { - PRINTF(" %hu -> %hu\n", ntohs(ips.is_sport), - ntohs(ips.is_dport)); - } else if (ips.is_p == IPPROTO_GRE) { - PRINTF(" call %hx/%hx\n", ntohs(ips.is_gre.gs_call[0]), - ntohs(ips.is_gre.gs_call[1])); - } else if (ips.is_p == IPPROTO_ICMP + } 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]), + ntohs(sp->is_gre.gs_call[1])); + } else if (sp->is_p == IPPROTO_ICMP #ifdef USE_INET6 - || ips.is_p == IPPROTO_ICMPV6 + || sp->is_p == IPPROTO_ICMPV6 #endif ) - PRINTF(" id %hu seq %hu type %d\n", ips.is_icmp.ici_id, - ips.is_icmp.ici_seq, ips.is_icmp.ici_type); + PRINTF(" id %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 %lld bytes in %lld pkts out %lld bytes out %lld\n\tbackward: pkts in %lld bytes in %lld pkts out %lld bytes out %lld\n", - ips.is_pkts[0], ips.is_bytes[0], - ips.is_pkts[1], ips.is_bytes[1], - ips.is_pkts[2], ips.is_bytes[2], - ips.is_pkts[3], ips.is_bytes[3]); + 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", - ips.is_pkts[0], ips.is_bytes[0], - ips.is_pkts[1], ips.is_bytes[1], - ips.is_pkts[2], ips.is_bytes[2], - ips.is_pkts[3], ips.is_bytes[3]); + 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"); @@ -83,11 +83,11 @@ u_long now; * Print out bits set in the result code for the state being * kept as they would for a rule. */ - if (FR_ISPASS(ips.is_pass)) { + if (FR_ISPASS(sp->is_pass)) { PRINTF("pass"); - } else if (FR_ISBLOCK(ips.is_pass)) { + } else if (FR_ISBLOCK(sp->is_pass)) { PRINTF("block"); - switch (ips.is_pass & FR_RETMASK) + switch (sp->is_pass & FR_RETMASK) { case FR_RETICMP : PRINTF(" return-icmp"); @@ -101,77 +101,77 @@ u_long now; default : break; } - } else if ((ips.is_pass & FR_LOGMASK) == FR_LOG) { + } else if ((sp->is_pass & FR_LOGMASK) == FR_LOG) { PRINTF("log"); - if (ips.is_pass & FR_LOGBODY) + if (sp->is_pass & FR_LOGBODY) PRINTF(" body"); - if (ips.is_pass & FR_LOGFIRST) + if (sp->is_pass & FR_LOGFIRST) PRINTF(" first"); - } else if (FR_ISACCOUNT(ips.is_pass)) { + } else if (FR_ISACCOUNT(sp->is_pass)) { PRINTF("count"); - } else if (FR_ISPREAUTH(ips.is_pass)) { + } else if (FR_ISPREAUTH(sp->is_pass)) { PRINTF("preauth"); - } else if (FR_ISAUTH(ips.is_pass)) + } else if (FR_ISAUTH(sp->is_pass)) PRINTF("auth"); - if (ips.is_pass & FR_OUTQUE) + if (sp->is_pass & FR_OUTQUE) PRINTF(" out"); else PRINTF(" in"); - if ((ips.is_pass & FR_LOG) != 0) { + if ((sp->is_pass & FR_LOG) != 0) { PRINTF(" log"); - if (ips.is_pass & FR_LOGBODY) + if (sp->is_pass & FR_LOGBODY) PRINTF(" body"); - if (ips.is_pass & FR_LOGFIRST) + if (sp->is_pass & FR_LOGFIRST) PRINTF(" first"); - if (ips.is_pass & FR_LOGORBLOCK) + if (sp->is_pass & FR_LOGORBLOCK) PRINTF(" or-block"); } - if (ips.is_pass & FR_QUICK) + if (sp->is_pass & FR_QUICK) PRINTF(" quick"); - if (ips.is_pass & FR_KEEPFRAG) + if (sp->is_pass & FR_KEEPFRAG) PRINTF(" keep frags"); /* a given; no? */ - if (ips.is_pass & FR_KEEPSTATE) { + if (sp->is_pass & FR_KEEPSTATE) { PRINTF(" keep state"); - if (ips.is_pass & FR_STATESYNC) + if (sp->is_pass & FR_STATESYNC) PRINTF(" ( sync )"); } - PRINTF("\tIPv%d", ips.is_v); + PRINTF("\tIPv%d", sp->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, %x = %x \n", ips.is_optmsk[0], - ips.is_opt[0], ips.is_optmsk[1], ips.is_opt[1]); + 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", - ips.is_secmsk, ips.is_sec, ips.is_authmsk, - ips.is_auth); - PRINTF("\tis_flx %#x %#x %#x %#x\n", ips.is_flx[0][0], ips.is_flx[0][1], - ips.is_flx[1][0], ips.is_flx[1][1]); - PRINTF("\tinterfaces: in %s[%s", getifname(ips.is_ifp[0]), - ips.is_ifname[0]); + 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) - PRINTF("/%p", ips.is_ifp[0]); + PRINTF("/%p", sp->is_ifp[0]); putchar(']'); - PRINTF(",%s[%s", getifname(ips.is_ifp[1]), ips.is_ifname[1]); + PRINTF(",%s[%s", getifname(sp->is_ifp[1]), sp->is_ifname[1]); if (opts & OPT_DEBUG) - PRINTF("/%p", ips.is_ifp[1]); + PRINTF("/%p", sp->is_ifp[1]); putchar(']'); - PRINTF(" out %s[%s", getifname(ips.is_ifp[2]), ips.is_ifname[2]); + PRINTF(" out %s[%s", getifname(sp->is_ifp[2]), sp->is_ifname[2]); if (opts & OPT_DEBUG) - PRINTF("/%p", ips.is_ifp[2]); + PRINTF("/%p", sp->is_ifp[2]); putchar(']'); - PRINTF(",%s[%s", getifname(ips.is_ifp[3]), ips.is_ifname[3]); + PRINTF(",%s[%s", getifname(sp->is_ifp[3]), sp->is_ifname[3]); if (opts & OPT_DEBUG) - PRINTF("/%p", ips.is_ifp[3]); + PRINTF("/%p", sp->is_ifp[3]); PRINTF("]\n"); - if (ips.is_sync != NULL) { + if (sp->is_sync != NULL) { - if (kmemcpy((char *)&ipsync, (u_long)ips.is_sync, sizeof(ipsync))) { + if (kmemcpy((char *)&ipsync, (u_long)sp->is_sync, sizeof(ipsync))) { PRINTF("\tSync status: status could not be retrieved\n"); return NULL; @@ -185,5 +185,5 @@ u_long now; PRINTF("\tSync status: not synchronized\n"); } - return ips.is_next; + return sp->is_next; } diff --git a/contrib/ipfilter/lib/printtunable.c b/contrib/ipfilter/lib/printtunable.c index 12e019d..aa7ae5d 100644 --- a/contrib/ipfilter/lib/printtunable.c +++ b/contrib/ipfilter/lib/printtunable.c @@ -1,5 +1,13 @@ /* $FreeBSD$ */ +/* + * 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 $ + */ + #include "ipf.h" void printtunable(tup) diff --git a/contrib/ipfilter/lib/remove_hash.c b/contrib/ipfilter/lib/remove_hash.c index a60bdd3..297db48 100644 --- a/contrib/ipfilter/lib/remove_hash.c +++ b/contrib/ipfilter/lib/remove_hash.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2002 by Darren Reed. + * Copyright (C) 2003 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: remove_hash.c,v 1.1 2003/04/13 06:40:14 darrenr Exp $ + * $Id: remove_hash.c,v 1.1.4.1 2006/06/16 17:21:16 darrenr Exp $ */ #include <fcntl.h> diff --git a/contrib/ipfilter/lib/remove_hashnode.c b/contrib/ipfilter/lib/remove_hashnode.c index 0b2098c..47a19dc 100644 --- a/contrib/ipfilter/lib/remove_hashnode.c +++ b/contrib/ipfilter/lib/remove_hashnode.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2002 by Darren Reed. + * Copyright (C) 2003 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: remove_hashnode.c,v 1.1 2003/04/13 06:40:14 darrenr Exp $ + * $Id: remove_hashnode.c,v 1.1.4.1 2006/06/16 17:21:16 darrenr Exp $ */ #include <fcntl.h> diff --git a/contrib/ipfilter/lib/remove_pool.c b/contrib/ipfilter/lib/remove_pool.c index 8fbad2e..1e7fe5f 100644 --- a/contrib/ipfilter/lib/remove_pool.c +++ b/contrib/ipfilter/lib/remove_pool.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2002 by Darren Reed. + * Copyright (C) 2003 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: remove_pool.c,v 1.1 2003/04/13 06:40:14 darrenr Exp $ + * $Id: remove_pool.c,v 1.1.4.1 2006/06/16 17:21:16 darrenr Exp $ */ #include <fcntl.h> diff --git a/contrib/ipfilter/lib/remove_poolnode.c b/contrib/ipfilter/lib/remove_poolnode.c index 51649ba..c80ff70 100644 --- a/contrib/ipfilter/lib/remove_poolnode.c +++ b/contrib/ipfilter/lib/remove_poolnode.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2002 by Darren Reed. + * Copyright (C) 2003 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: remove_poolnode.c,v 1.3 2003/11/22 10:14:36 darrenr Exp $ + * $Id: remove_poolnode.c,v 1.3.2.1 2006/06/16 17:21:16 darrenr Exp $ */ #include <fcntl.h> diff --git a/contrib/ipfilter/lib/resetlexer.c b/contrib/ipfilter/lib/resetlexer.c index 19eb161..8ea83f1 100644 --- a/contrib/ipfilter/lib/resetlexer.c +++ b/contrib/ipfilter/lib/resetlexer.c @@ -1,5 +1,13 @@ /* $FreeBSD$ */ +/* + * 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 $ + */ + #include "ipf.h" long string_start = -1; diff --git a/contrib/ipfilter/lib/rwlock_emul.c b/contrib/ipfilter/lib/rwlock_emul.c index d3beb60..1ee2475 100644 --- a/contrib/ipfilter/lib/rwlock_emul.c +++ b/contrib/ipfilter/lib/rwlock_emul.c @@ -1,5 +1,13 @@ /* $FreeBSD$ */ +/* + * 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 $ + */ + #include "ipf.h" #define EMM_MAGIC 0x97dd8b3a diff --git a/contrib/ipfilter/lib/tcp_flags.c b/contrib/ipfilter/lib/tcp_flags.c index d6b5034..0b602e6 100644 --- a/contrib/ipfilter/lib/tcp_flags.c +++ b/contrib/ipfilter/lib/tcp_flags.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2004 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: tcp_flags.c,v 1.8 2004/02/07 18:15:54 darrenr Exp $ + * $Id: tcp_flags.c,v 1.8.2.1 2006/06/16 17:21:17 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/tcpflags.c b/contrib/ipfilter/lib/tcpflags.c index e5763d7..f01d7dc 100644 --- a/contrib/ipfilter/lib/tcpflags.c +++ b/contrib/ipfilter/lib/tcpflags.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2001-2002 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: tcpflags.c,v 1.3 2002/11/02 07:18:01 darrenr Exp $ + * $Id: tcpflags.c,v 1.3.4.1 2006/06/16 17:21:17 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/tcpoptnames.c b/contrib/ipfilter/lib/tcpoptnames.c index a215c55..25e3b27 100644 --- a/contrib/ipfilter/lib/tcpoptnames.c +++ b/contrib/ipfilter/lib/tcpoptnames.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2002 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: tcpoptnames.c,v 1.5 2002/01/28 06:50:48 darrenr Exp $ + * $Id: tcpoptnames.c,v 1.5.4.1 2006/06/16 17:21:17 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/v6ionames.c b/contrib/ipfilter/lib/v6ionames.c index 224a815..b57b301 100644 --- a/contrib/ipfilter/lib/v6ionames.c +++ b/contrib/ipfilter/lib/v6ionames.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2003-2005 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: v6ionames.c,v 1.1.4.2 2005/10/17 18:31:09 darrenr Exp $ + * $Id: v6ionames.c,v 1.1.4.3 2006/06/16 17:21:18 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/v6optvalue.c b/contrib/ipfilter/lib/v6optvalue.c index a2e0139..a60d076 100644 --- a/contrib/ipfilter/lib/v6optvalue.c +++ b/contrib/ipfilter/lib/v6optvalue.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2003 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: v6optvalue.c,v 1.1 2003/04/26 04:55:58 darrenr Exp $ + * $Id: v6optvalue.c,v 1.1.4.1 2006/06/16 17:21:18 darrenr Exp $ */ #include "ipf.h" diff --git a/contrib/ipfilter/lib/var.c b/contrib/ipfilter/lib/var.c index 5f3e015..4a62d7a 100644 --- a/contrib/ipfilter/lib/var.c +++ b/contrib/ipfilter/lib/var.c @@ -1,5 +1,13 @@ /* $FreeBSD$ */ +/* + * 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 $ + */ + #include <ctype.h> #include "ipf.h" diff --git a/contrib/ipfilter/lib/verbose.c b/contrib/ipfilter/lib/verbose.c index bd01bcd..f1b4516 100644 --- a/contrib/ipfilter/lib/verbose.c +++ b/contrib/ipfilter/lib/verbose.c @@ -1,11 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2000-2001 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: verbose.c,v 1.6 2001/06/09 17:09:25 darrenr Exp $ + * $Id: verbose.c,v 1.6.4.1 2006/06/16 17:21:18 darrenr Exp $ */ #if defined(__STDC__) diff --git a/contrib/ipfilter/man/ipf.8 b/contrib/ipfilter/man/ipf.8 index bcf9307..678010f 100644 --- a/contrib/ipfilter/man/ipf.8 +++ b/contrib/ipfilter/man/ipf.8 @@ -74,6 +74,17 @@ one of the two options may be given. A fully established connection will show up in \fBipfstat -s\fP output as 5/5, with deviations either way indicating it is not fully established any more. .TP +.BR \-F <5|6|7|8|9|10|11> +For the TCP states that represent the closing of a connection has begun, +be it only one side or the complete connection, it is possible to flush +those states directly using the number corresponding to that state. +The numbers relate to the states as follows: 5 = close-wait, 6 = fin-wait-1, +7 = closing, 8 = last-ack, 9 = fin-wait-2, 10 = time-wait, 11 = closed. +.TP +.BR \-F <number> +If the argument supplied to \fB-F\fP is greater than 30, then state table +entries that have been idle for more than this many seconds will be flushed. +.TP .BR \-f \0<filename> This option specifies which files \fBipf\fP should use to get input from for modifying the packet filter rule @@ -105,6 +116,7 @@ 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 \-T <optionlist> This option allows run-time changing of IPFilter kernel variables. Some variables require IPFilter to be in a disabled state (\fB-D\fP) for changing, diff --git a/contrib/ipfilter/man/ipfstat.8 b/contrib/ipfilter/man/ipfstat.8 index d0cb2a9..44ba8ba 100644 --- a/contrib/ipfilter/man/ipfstat.8 +++ b/contrib/ipfilter/man/ipfstat.8 @@ -124,7 +124,11 @@ seconds between an update. Any positive integer can be used. The default (and minimal update time) is 1. .TP .B \-v -Turn verbose mode on. Displays more debugging information. +Turn verbose mode on. Displays more debugging information. When used with +either \fB-i\fP or \fB-o\fP, counters associated with the rule, such as the +number of times it has been matched and the number of bytes from such packets +is displayed. For "keep state" rules, a count of the number of state sessions +active against the rule is also displayed. .SH SYNOPSIS The role of \fBipfstat\fP is to display current kernel statistics gathered as a result of applying the filters in place (if any) to packets going in and diff --git a/contrib/ipfilter/man/ipmon.8 b/contrib/ipfilter/man/ipmon.8 index 2a35d16..1082e06 100644 --- a/contrib/ipfilter/man/ipmon.8 +++ b/contrib/ipfilter/man/ipmon.8 @@ -107,6 +107,7 @@ even should the result be zero. .B \-L <facility> Using this option allows you to change the default syslog facility that ipmon uses for syslog messages. The default is local0. +.TP .B \-n IP addresses and port numbers will be mapped, where possible, back into hostnames and service names. diff --git a/contrib/ipfilter/radix_ipf.h b/contrib/ipfilter/radix_ipf.h index 294407b..220a389 100644 --- a/contrib/ipfilter/radix_ipf.h +++ b/contrib/ipfilter/radix_ipf.h @@ -42,7 +42,7 @@ # endif #endif -#if defined(__sgi) +#if defined(__sgi) || defined(__osf__) # define radix_mask ipf_radix_mask # define radix_node ipf_radix_node # define radix_node_head ipf_radix_node_head diff --git a/contrib/ipfilter/tools/ipf.c b/contrib/ipfilter/tools/ipf.c index b923f58..fe9fec2 100644 --- a/contrib/ipfilter/tools/ipf.c +++ b/contrib/ipfilter/tools/ipf.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2001-2006 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -21,7 +21,7 @@ #if !defined(lint) static const char sccsid[] = "@(#)ipf.c 1.23 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipf.c,v 1.35.2.4 2006/03/17 11:48:08 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ipf.c,v 1.35.2.8 2007/05/10 06:12:01 darrenr Exp $"; #endif #if !defined(__SVR4) && defined(__GNUC__) @@ -344,11 +344,13 @@ char *arg; if (!arg || !*arg) return; - if (!strcmp(arg, "s") || !strcmp(arg, "S")) { + if (!strcmp(arg, "s") || !strcmp(arg, "S") || ISDIGIT(*arg)) { if (*arg == 'S') fl = 0; - else + else if (*arg == 's') fl = 1; + else + fl = atoi(arg); rem = fl; closedevice(); @@ -370,7 +372,7 @@ char *arg; } if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { printf("remove flags %s (%d)\n", arg, rem); - printf("removed %d filter rules\n", fl); + printf("removed %d entries\n", fl); } closedevice(); return; diff --git a/contrib/ipfilter/tools/ipf_y.y b/contrib/ipfilter/tools/ipf_y.y index 5a24592..e8789e0 100644 --- a/contrib/ipfilter/tools/ipf_y.y +++ b/contrib/ipfilter/tools/ipf_y.y @@ -1,5 +1,10 @@ /* $FreeBSD$ */ +/* + * Copyright (C) 2001-2006 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ %{ #include "ipf.h" #include <sys/ioctl.h> @@ -171,7 +176,7 @@ file: line | file assign ; -line: xx rule { while ((fr = frtop) != NULL) { +line: rule { while ((fr = frtop) != NULL) { frtop = fr->fr_next; fr->fr_next = NULL; (*ipfaddfunc)(ipffd, ipfioctl[IPL_LOGIPF], fr); @@ -190,6 +195,7 @@ assign: YY_STR assigning YY_STR ';' { set_variable($1, $3); resetlexer(); free($1); free($3); + yyvarnext = 0; } ; @@ -213,8 +219,8 @@ outrule: ; rulehead: - collection action - | insert collection action + xx collection action + | xx insert collection action ; markin: IPFY_IN { fr->fr_flags |= FR_INQUE; } @@ -837,20 +843,32 @@ dstportlist: ; addr: pool '/' YY_NUMBER { pooled = 1; - yyexpectaddr = 0; $$.a.iplookuptype = IPLT_POOL; + $$.a.iplookupsubtype = 0; $$.a.iplookupnum = $3; } + | pool '/' YY_STR { pooled = 1; + $$.a.iplookuptype = IPLT_POOL; + $$.a.iplookupsubtype = 1; + strncpy($$.a.iplookupname, $3, + sizeof($$.a.iplookupname)); + } | pool '=' '(' poollist ')' { pooled = 1; - yyexpectaddr = 0; $$.a.iplookuptype = IPLT_POOL; + $$.a.iplookupsubtype = 0; $$.a.iplookupnum = makepool($4); } | hash '/' YY_NUMBER { hashed = 1; - yyexpectaddr = 0; $$.a.iplookuptype = IPLT_HASH; + $$.a.iplookupsubtype = 0; $$.a.iplookupnum = $3; } + | hash '/' YY_STR { pooled = 1; + $$.a.iplookuptype = IPLT_HASH; + $$.a.iplookupsubtype = 1; + strncpy($$.a.iplookupname, $3, + sizeof($$.a.iplookupname)); + } | hash '=' '(' addrlist ')' { hashed = 1; - yyexpectaddr = 0; $$.a.iplookuptype = IPLT_HASH; + $$.a.iplookupsubtype = 0; $$.a.iplookupnum = makehash($4); } | ipaddr { bcopy(&$1, &$$, sizeof($$)); yyexpectaddr = 0; } @@ -1375,8 +1393,8 @@ servicename: YY_STR { $$ = $1; } ; -interfacename: YY_STR { $$ = $1; } - | YY_STR ':' YY_NUMBER +interfacename: name { $$ = $1; } + | name ':' YY_NUMBER { $$ = $1; fprintf(stderr, "%d: Logical interface %s:%d unsupported, " "use the physical interface %s instead.\n", @@ -1385,6 +1403,7 @@ interfacename: YY_STR { $$ = $1; } ; name: YY_STR { $$ = $1; } + | '-' { $$ = strdup("-"); } ; ipv4_16: @@ -2033,6 +2052,9 @@ void *ptr; frentry_t *fr; ipfobj_t obj; + if (ptr == NULL) + return; + fr = ptr; add = 0; del = 0; @@ -2062,10 +2084,10 @@ void *ptr; fr->fr_flags |= FR_OUTQUE; if (fr->fr_hits) fr->fr_hits--; - if (fr && (opts & OPT_VERBOSE)) + if ((opts & OPT_VERBOSE) != 0) printfr(fr, ioctlfunc); - if (opts & OPT_DEBUG) { + if ((opts & OPT_DEBUG) != 0) { binprint(fr, sizeof(*fr)); if (fr->fr_data != NULL) binprint(fr->fr_data, fr->fr_dsize); diff --git a/contrib/ipfilter/tools/ipfcomp.c b/contrib/ipfilter/tools/ipfcomp.c index da80da8..1e26de5 100644 --- a/contrib/ipfilter/tools/ipfcomp.c +++ b/contrib/ipfilter/tools/ipfcomp.c @@ -1,13 +1,13 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2001-2005 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.3 2006/03/17 22:31:57 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ipfcomp.c,v 1.24.2.7 2007/05/01 22:15:00 darrenr Exp $"; #endif #include "ipf.h" @@ -94,11 +94,22 @@ frentry_t *fr; fprintf(fp, "* to the original author and the contributors.\n"); fprintf(fp, "*/\n\n"); + fprintf(fp, "#include <sys/param.h>\n"); fprintf(fp, "#include <sys/types.h>\n"); fprintf(fp, "#include <sys/time.h>\n"); fprintf(fp, "#include <sys/socket.h>\n"); - fprintf(fp, "#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__sgi)\n"); - fprintf(fp, "# include <sys/systm.h>\n"); + fprintf(fp, "#if (__FreeBSD_version >= 40000)\n"); + fprintf(fp, "# if defined(_KERNEL)\n"); + fprintf(fp, "# include <sys/libkern.h>\n"); + fprintf(fp, "# else\n"); + fprintf(fp, "# include <sys/unistd.h>\n"); + fprintf(fp, "# endif\n"); + fprintf(fp, "#endif\n"); + fprintf(fp, "#if (__NetBSD_Version__ >= 399000000)\n"); + fprintf(fp, "#else\n"); + fprintf(fp, "# if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__sgi)\n"); + fprintf(fp, "# include <sys/systm.h>\n"); + fprintf(fp, "# endif\n"); fprintf(fp, "#endif\n"); fprintf(fp, "#include <sys/errno.h>\n"); fprintf(fp, "#include <sys/param.h>\n"); @@ -493,7 +504,8 @@ u_int incount, outcount; /* * Output the array of pointers to rules for this group. */ - if (num == -2 && dir == 0 && header[0] == 0 && incount != 0) { + if (g != NULL && num == -2 && dir == 0 && header[0] == 0 && + incount != 0) { fprintf(fp, "\nfrentry_t *ipf_rules_in_%s[%d] = {", group, incount); for (f = g->fg_start, i = 0; f != NULL; f = f->fr_next) { @@ -512,7 +524,8 @@ u_int incount, outcount; fprintf(fp, "\n};\n"); } - if (num == -2 && dir == 1 && header[1] == 0 && outcount != 0) { + if (g != NULL && num == -2 && dir == 1 && header[0] == 0 && + outcount != 0) { fprintf(fp, "\nfrentry_t *ipf_rules_out_%s[%d] = {", group, outcount); for (f = g->fg_start, i = 0; f != NULL; f = f->fr_next) { @@ -541,7 +554,7 @@ u_int incount, outcount; /* * If the function header has not been printed then print it now. */ - if (header[dir] == 0) { + if (g != NULL && header[dir] == 0) { int pdst = 0, psrc = 0; openfunc = 1; diff --git a/contrib/ipfilter/tools/ipfs.c b/contrib/ipfilter/tools/ipfs.c index a89ea0b..eab650a 100644 --- a/contrib/ipfilter/tools/ipfs.c +++ b/contrib/ipfilter/tools/ipfs.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1999-2001, 2003 by Darren Reed. + * Copyright (C) 2001-2006 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -133,6 +133,14 @@ char *ifs, *fname; strcpy(ips.ips_is.is_ifname[1], s); rw = 1; } + if (!strncmp(ips.ips_is.is_ifname[2], ifs, olen + 1)) { + strcpy(ips.ips_is.is_ifname[2], s); + rw = 1; + } + if (!strncmp(ips.ips_is.is_ifname[3], ifs, olen + 1)) { + strcpy(ips.ips_is.is_ifname[3], s); + rw = 1; + } if (rw == 1) { if (lseek(fd, pos, SEEK_SET) != pos) { perror("lseek"); @@ -190,6 +198,14 @@ 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"); @@ -216,7 +232,7 @@ char *argv[]; char *dirname = NULL, *filename = NULL, *ifs = NULL; progname = argv[0]; - while ((c = getopt(argc, argv, "d:f:lNnSRruvWw")) != -1) + while ((c = getopt(argc, argv, "d:f:i:lNnSRruvWw")) != -1) switch (c) { case 'd' : diff --git a/contrib/ipfilter/tools/ipfstat.c b/contrib/ipfilter/tools/ipfstat.c index 85eba20..db362d2 100644 --- a/contrib/ipfilter/tools/ipfstat.c +++ b/contrib/ipfilter/tools/ipfstat.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001, 2003 by Darren Reed. + * Copyright (C) 2002-2006 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -53,6 +53,7 @@ #ifdef STATETOP # include <ctype.h> # include <signal.h> +# include <time.h> # if SOLARIS || defined(__NetBSD__) || defined(_BSDI_VERSION) || \ defined(__sgi) # ifdef ERR @@ -70,7 +71,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.14 2006/03/21 16:09:58 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ipfstat.c,v 1.44.2.23 2007/05/31 13:13:02 darrenr Exp $"; #endif #ifdef __hpux @@ -83,10 +84,6 @@ extern int opterr; #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)" }; static int state_logging = -1; @@ -96,6 +93,10 @@ int use_inet6 = 0; int live_kernel = 1; int state_fd = -1; int ipf_fd = -1; +int auth_fd = -1; +int nat_fd = -1; +frgroup_t *grtop = NULL; +frgroup_t *grtail = NULL; #ifdef STATETOP #define STSTRSIZE 80 @@ -130,19 +131,23 @@ typedef struct statetop { int main __P((int, char *[])); +static int fetchfrag __P((int, int, ipfr_t *)); static void showstats __P((friostat_t *, u_32_t)); -static void showfrstates __P((ipfrstat_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 showgroups __P((friostat_t *)); static void usage __P((char *)); -static void printlist __P((frentry_t *, 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 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 *)); static void ipfstate_dead __P((char *, friostat_t **, ips_stat_t **, ipfrstat_t **, fr_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)); @@ -192,7 +197,7 @@ char *argv[]; ips_stat_t *ipsstp = &ipsst; ipfrstat_t ifrst; ipfrstat_t *ifrstp = &ifrst; - char *device = IPL_NAME, *memf = NULL; + char *memf = NULL; char *options, *kern = NULL; int c, myoptind; @@ -245,8 +250,16 @@ char *argv[]; perror("open(IPSTATE_NAME)"); exit(-1); } - if ((ipf_fd = open(device, O_RDONLY)) == -1) { - fprintf(stderr, "open(%s)", device); + if ((auth_fd = open(IPAUTH_NAME, O_RDONLY)) == -1) { + perror("open(IPAUTH_NAME)"); + exit(-1); + } + if ((nat_fd = open(IPNAT_NAME, O_RDONLY)) == -1) { + perror("open(IPAUTH_NAME)"); + exit(-1); + } + if ((ipf_fd = open(IPL_NAME, O_RDONLY)) == -1) { + fprintf(stderr, "open(%s)", IPL_NAME); perror(""); exit(-1); } @@ -257,10 +270,12 @@ char *argv[]; (void)setuid(getuid()); } - if (live_kernel == 1) - (void) checkrev(device); - if (openkmem(kern, memf) == -1) - exit(-1); + if (live_kernel == 1) { + (void) checkrev(IPL_NAME); + } else { + if (openkmem(kern, memf) == -1) + exit(-1); + } (void)setgid(getgid()); (void)setuid(getuid()); @@ -369,7 +384,7 @@ char *argv[]; bzero((char *)&ipsst, sizeof(ipsst)); bzero((char *)&ifrst, sizeof(ifrst)); - ipfstate_live(device, &fiop, &ipsstp, &ifrstp, + ipfstate_live(IPL_NAME, &fiop, &ipsstp, &ifrstp, &frauthstp, &frf); } else ipfstate_dead(kern, &fiop, &ipsstp, &ifrstp, &frauthstp, &frf); @@ -383,7 +398,7 @@ char *argv[]; showlist(fiop); } } else if (opts & OPT_FRSTATES) - showfrstates(ifrstp); + showfrstates(ifrstp, fiop->f_ticks); #ifdef STATETOP else if (opts & OPT_STATETOP) topipstates(saddr, daddr, sport, dport, protocol, @@ -422,9 +437,9 @@ u_32_t *frfp; if ((opts & OPT_AUTHSTATS) == 0) { bzero((caddr_t)&ipfo, sizeof(ipfo)); ipfo.ipfo_rev = IPFILTER_VERSION; + ipfo.ipfo_type = IPFOBJ_IPFSTAT; ipfo.ipfo_size = sizeof(friostat_t); ipfo.ipfo_ptr = (void *)*fiopp; - ipfo.ipfo_type = IPFOBJ_IPFSTAT; if (ioctl(ipf_fd, SIOCGETFS, &ipfo) == -1) { perror("ioctl(ipf:SIOCGETFS)"); @@ -439,9 +454,9 @@ u_32_t *frfp; bzero((caddr_t)&ipfo, sizeof(ipfo)); ipfo.ipfo_rev = IPFILTER_VERSION; + ipfo.ipfo_type = IPFOBJ_STATESTAT; ipfo.ipfo_size = sizeof(ips_stat_t); ipfo.ipfo_ptr = (void *)*ipsstpp; - ipfo.ipfo_type = IPFOBJ_STATESTAT; if ((ioctl(state_fd, SIOCGETFS, &ipfo) == -1)) { perror("ioctl(state:SIOCGETFS)"); @@ -456,9 +471,9 @@ u_32_t *frfp; if ((opts & OPT_FRSTATES) != 0) { bzero((caddr_t)&ipfo, sizeof(ipfo)); ipfo.ipfo_rev = IPFILTER_VERSION; + ipfo.ipfo_type = IPFOBJ_FRAGSTAT; ipfo.ipfo_size = sizeof(ipfrstat_t); ipfo.ipfo_ptr = (void *)*ifrstpp; - ipfo.ipfo_type = IPFOBJ_FRAGSTAT; if (ioctl(ipf_fd, SIOCGFRST, &ipfo) == -1) { perror("ioctl(SIOCGFRST)"); @@ -466,27 +481,17 @@ u_32_t *frfp; } } - if (opts & OPT_VERBOSE) + if (opts & OPT_DEBUG) PRINTF("opts %#x name %s\n", opts, device); if ((opts & OPT_AUTHSTATS) != 0) { - if (ipf_fd >= 0) { - close(ipf_fd); - ipf_fd = -1; - } - device = IPAUTH_NAME; - if ((ipf_fd = open(device, O_RDONLY)) == -1) { - perror("open"); - exit(-1); - } - 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_ptr = (void *)*frauthstpp; - ipfo.ipfo_type = IPFOBJ_AUTHSTAT; - if (ioctl(ipf_fd, SIOCATHST, &ipfo) == -1) { + if (ioctl(auth_fd, SIOCATHST, &ipfo) == -1) { perror("ioctl(SIOCATHST)"); exit(-1); } @@ -511,10 +516,11 @@ u_32_t *frfp; 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[43] = { + struct nlist deadlist[44] = { { "fr_authstats" }, /* 0 */ { "fae_list" }, { "ipauth" }, @@ -557,6 +563,7 @@ u_32_t *frfp; { "fr_pass" }, { "fr_flags" }, /* 40 */ { "ipstate_logging" }, + { "ips_tqtqb" }, { NULL } }; @@ -669,9 +676,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)); ipsstp->iss_active = temp; ipsstp->iss_table = (void *)deadlist[18].n_value; ipsstp->iss_list = (void *)deadlist[17].n_value; + ipsstp->iss_tcptab = ipssttab; /* * Build up the authentiation information stats structure. @@ -771,21 +781,62 @@ u_32_t frf; /* * Print out a list of rules from the kernel, starting at the one passed. */ -static void printlist(fp, comment) +static void printlivelist(out, set, fp, group, comment) +int out, set; frentry_t *fp; -char *comment; +char *group, *comment; { - struct frentry fb, *fg; - char *data; - u_32_t type; - int n; - - for (n = 1; fp; n++) { - if (kmemcpy((char *)&fb, (u_long)fp, sizeof(fb)) == -1) { - perror("kmemcpy"); + struct frentry fb; + ipfruleiter_t rule; + frentry_t zero; + frgroup_t *g; + ipfobj_t obj; + int n; + + if (use_inet6 == 1) + fb.fr_v = 6; + else + fb.fr_v = 4; + fb.fr_next = fp; + n = 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 + rule.iri_group[0] = '\0'; + + bzero((char *)&zero, sizeof(zero)); + + bzero((char *)&obj, sizeof(obj)); + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_type = IPFOBJ_IPFITER; + obj.ipfo_size = sizeof(rule); + obj.ipfo_ptr = &rule; + + do { + 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; } - fp = &fb; + if (bcmp(fp, &zero, sizeof(zero)) == 0) + break; + if (fp->fr_data != NULL) + fp->fr_data = (char *)fp + sizeof(*fp); + + n++; + if (opts & (OPT_HITS|OPT_VERBOSE)) #ifdef USE_QUAD_T PRINTF("%qu ", (unsigned long long) fp->fr_hits); @@ -800,38 +851,144 @@ char *comment; #endif if (opts & OPT_SHOWLINENO) PRINTF("@%d ", n); + + printfr(fp, ioctl); + if (opts & OPT_DEBUG) { + binprint(fp, sizeof(*fp)); + if (fp->fr_data != NULL && fp->fr_dsize > 0) + binprint(fp->fr_data, fp->fr_dsize); + } + if (fp->fr_grhead[0] != '\0') { + for (g = grtop; g != NULL; g = g->fg_next) { + if (!strncmp(fp->fr_grhead, g->fg_name, + FR_GROUPLEN)) + break; + } + if (g == NULL) { + g = calloc(1, sizeof(*g)); + + if (g != NULL) { + strncpy(g->fg_name, fp->fr_grhead, + FR_GROUPLEN); + if (grtop == NULL) { + grtop = g; + grtail = g; + } else { + grtail->fg_next = g; + grtail = g; + } + } + } + } + if (fp->fr_type == FR_T_CALLFUNC) { + printlivelist(out, set, fp->fr_data, group, + "# callfunc: "); + } + } while (fp->fr_next != NULL); + + n = IPFGENITER_IPF; + ioctl(ipf_fd, SIOCIPFDELTOK, &n); + + 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); + } + } +} + + +static void printdeadlist(out, set, fp, group, comment) +int out, set; +frentry_t *fp; +char *group, *comment; +{ + frgroup_t *grtop, *grtail, *g; + struct frentry fb; + char *data; + u_32_t type; + int n; + + fb.fr_next = fp; + n = 0; + grtop = NULL; + grtail = NULL; + + do { + fp = fb.fr_next; + if (kmemcpy((char *)&fb, (u_long)fb.fr_next, + sizeof(fb)) == -1) { + perror("kmemcpy"); + return; + } + data = NULL; - type = fp->fr_type & ~FR_T_BUILTIN; + type = fb.fr_type & ~FR_T_BUILTIN; if (type == FR_T_IPF || type == FR_T_BPFOPC) { - if (fp->fr_dsize) { - data = malloc(fp->fr_dsize); + if (fb.fr_dsize) { + data = malloc(fb.fr_dsize); - if (kmemcpy(data, (u_long)fp->fr_data, - fp->fr_dsize) == -1) { + if (kmemcpy(data, (u_long)fb.fr_data, + fb.fr_dsize) == -1) { perror("kmemcpy"); return; } - fp->fr_data = data; + fb.fr_data = data; } } + n++; + + if (opts & (OPT_HITS|OPT_VERBOSE)) +#ifdef USE_QUAD_T + PRINTF("%qu ", (unsigned long long) fb.fr_hits); +#else + PRINTF("%lu ", fb.fr_hits); +#endif + if (opts & (OPT_ACCNT|OPT_VERBOSE)) +#ifdef USE_QUAD_T + PRINTF("%qu ", (unsigned long long) fb.fr_bytes); +#else + PRINTF("%lu ", fb.fr_bytes); +#endif + if (opts & OPT_SHOWLINENO) + PRINTF("@%d ", n); + printfr(fp, ioctl); if (opts & OPT_DEBUG) { binprint(fp, sizeof(*fp)); - if (fp->fr_data != NULL && fp->fr_dsize > 0) - binprint(fp->fr_data, fp->fr_dsize); + if (fb.fr_data != NULL && fb.fr_dsize > 0) + binprint(fb.fr_data, fb.fr_dsize); } if (data != NULL) free(data); - if (fp->fr_grp != NULL) { - if (!kmemcpy((char *)&fg, (u_long)fp->fr_grp, - sizeof(fg))) - printlist(fg, comment); + if (fb.fr_grhead[0] != '\0') { + g = calloc(1, sizeof(*g)); + + if (g != NULL) { + strncpy(g->fg_name, fb.fr_grhead, + FR_GROUPLEN); + if (grtop == NULL) { + grtop = g; + grtail = g; + } else { + grtail->fg_next = g; + grtail = g; + } + } } if (type == FR_T_CALLFUNC) { - printlist(fp->fr_data, "# callfunc: "); + printdeadlist(out, set, fb.fr_data, group, + "# callfunc: "); } - fp = fp->fr_next; + } while (fb.fr_next != NULL); + + while ((g = grtop) != NULL) { + printdeadlist(out, set, NULL, g->fg_name, comment); + grtop = g->fg_next; + free(g); } } @@ -887,17 +1044,20 @@ struct friostat *fiop; } else return; } - if (opts & OPT_VERBOSE) + if (opts & OPT_DEBUG) FPRINTF(stderr, "showlist:opts %#x i %d\n", opts, i); - if (opts & OPT_VERBOSE) + 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; } - printlist(fp, NULL); + if (live_kernel == 1) + printlivelist(i, set, fp, NULL, NULL); + else + printdeadlist(i, set, fp, NULL, NULL); } @@ -908,23 +1068,45 @@ static void showipstates(ipsp) ips_stat_t *ipsp; { u_long minlen, maxlen, totallen, *buckets; + ipftable_t table; + ipfobj_t obj; int i, sz; - sz = sizeof(*buckets) * ipsp->iss_statesize; - buckets = (u_long *)malloc(sz); - if (kmemcpy((char *)buckets, (u_long)ipsp->iss_bucketlen, sz)) { - free(buckets); - return; - } - /* * If a list of states hasn't been asked for, only print out stats */ if (!(opts & OPT_SHOWLIST)) { + + sz = sizeof(*buckets) * ipsp->iss_statesize; + buckets = (u_long *)malloc(sz); + + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_type = IPFOBJ_GTABLE; + obj.ipfo_size = sizeof(table); + obj.ipfo_ptr = &table; + + 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; + } + } + 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", @@ -935,6 +1117,8 @@ ips_stat_t *ipsp; 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_max; totallen = 0; @@ -975,18 +1159,30 @@ ips_stat_t *ipsp; PRINTF("\n"); free(buckets); + + if (live_kernel == 1) { + showtqtable_live(state_fd); + } else { + printtqtable(ipsp->iss_tcptab); + } + 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, - ipsp->iss_ticks); - } + ipstate_t ips; + + ipsp->iss_list = fetchstate(ipsp->iss_list, &ips); - free(buckets); + if (ipsp->iss_list != NULL) { + ipsp->iss_list = ips.is_next; + printstate(&ips, opts, ipsp->iss_ticks); + } + } } @@ -1040,9 +1236,9 @@ int topclosed; /* init ipfobj_t stuff */ bzero((caddr_t)&ipfo, sizeof(ipfo)); ipfo.ipfo_rev = IPFILTER_VERSION; + ipfo.ipfo_type = IPFOBJ_STATESTAT; ipfo.ipfo_size = sizeof(*ipsstp); ipfo.ipfo_ptr = (void *)ipsstp; - ipfo.ipfo_type = IPFOBJ_STATESTAT; /* repeat until user aborts */ while ( 1 ) { @@ -1064,8 +1260,8 @@ int topclosed; /* read the state table and store in tstable */ for (; ipsstp->iss_list; ipsstp->iss_list = ips.is_next) { - if (kmemcpy((char *)&ips, (u_long)ipsstp->iss_list, - sizeof(ips))) + ipsstp->iss_list = fetchstate(ipsstp->iss_list, &ips); + if (ipsstp->iss_list == NULL) break; if (ips.is_v != ver) @@ -1432,8 +1628,9 @@ out: /* * Show fragment cache information that's held in the kernel. */ -static void showfrstates(ifsp) +static void showfrstates(ifsp, ticks) ipfrstat_t *ifsp; +u_long ticks; { struct ipfr *ipfrtab[IPFT_SIZE], ifr; int i; @@ -1448,34 +1645,65 @@ ipfrstat_t *ifsp; 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; + PRINTF("\n"); + + if (live_kernel == 0) { + 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] != NULL) { - if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], - sizeof(ifr)) == -1) + if (live_kernel == 1) { + do { + if (fetchfrag(ipf_fd, IPFGENITER_FRAG, &ifr) != 0) + break; + if (ifr.ipfr_ifp == NULL) break; + ifr.ipfr_ttl -= ticks; printfraginfo("", &ifr); - ipfrtab[i] = ifr.ipfr_next; - } + } while (1); + } else { + for (i = 0; i < IPFT_SIZE; i++) + while (ipfrtab[i] != NULL) { + if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], + sizeof(ifr)) == -1) + break; + printfraginfo("", &ifr); + ipfrtab[i] = ifr.ipfr_next; + } + } /* * Print out the contents (if any) of the NAT fragment cache table. */ - if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_nattab,sizeof(ipfrtab))) - return; - for (i = 0; i < IPFT_SIZE; i++) - while (ipfrtab[i] != NULL) { - if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], - sizeof(ifr)) == -1) + + if (live_kernel == 0) { + if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_nattab, + sizeof(ipfrtab))) + return; + } + + if (live_kernel == 1) { + do { + if (fetchfrag(nat_fd, IPFGENITER_NATFRAG, &ifr) != 0) + break; + if (ifr.ipfr_ifp == NULL) break; + ifr.ipfr_ttl -= ticks; printfraginfo("NAT: ", &ifr); - ipfrtab[i] = ifr.ipfr_next; - } + } while (1); + } else { + for (i = 0; i < IPFT_SIZE; i++) + while (ipfrtab[i] != NULL) { + if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], + sizeof(ifr)) == -1) + break; + printfraginfo("NAT: ", &ifr); + ipfrtab[i] = ifr.ipfr_next; + } + } } @@ -1486,6 +1714,17 @@ static void showauthstates(asp) fr_authstat_t *asp; { frauthent_t *frap, fra; + ipfgeniter_t auth; + ipfobj_t obj; + + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_type = IPFOBJ_GENITER; + obj.ipfo_size = sizeof(auth); + obj.ipfo_ptr = &auth; + + auth.igi_type = IPFGENITER_AUTH; + auth.igi_nitems = 1; + auth.igi_data = &fra; #ifdef USE_QUAD_T printf("Authorisation hits: %qu\tmisses %qu\n", @@ -1503,9 +1742,14 @@ fr_authstat_t *asp; frap = asp->fas_faelist; while (frap) { - if (kmemcpy((char *)&fra, (u_long)frap, sizeof(fra)) == -1) - break; - + if (live_kernel == 1) { + if (ioctl(auth_fd, SIOCGENITER, &obj)) + break; + } else { + if (kmemcpy((char *)&fra, (u_long)frap, + sizeof(fra)) == -1) + break; + } printf("age %ld\t", fra.fae_age); printfr(&fra.fae_fr, ioctl); frap = fra.fae_next; @@ -1795,3 +2039,75 @@ const void *b; } #endif + + +ipstate_t *fetchstate(src, dst) +ipstate_t *src, *dst; +{ + int i; + + if (live_kernel == 1) { + ipfgeniter_t state; + ipfobj_t obj; + + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_type = IPFOBJ_GENITER; + obj.ipfo_size = sizeof(state); + obj.ipfo_ptr = &state; + + state.igi_type = IPFGENITER_STATE; + state.igi_nitems = 1; + state.igi_data = dst; + + if (ioctl(state_fd, SIOCGENITER, &obj) != 0) + return NULL; + if (dst->is_next == NULL) { + i = IPFGENITER_STATE; + ioctl(state_fd, SIOCIPFDELTOK, &i); + } + } else { + if (kmemcpy((char *)dst, (u_long)src, sizeof(*dst))) + return NULL; + } + return dst; +} + + +static int fetchfrag(fd, type, frp) +int fd, type; +ipfr_t *frp; +{ + ipfgeniter_t frag; + ipfobj_t obj; + + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_type = IPFOBJ_GENITER; + obj.ipfo_size = sizeof(frag); + obj.ipfo_ptr = &frag; + + frag.igi_type = type; + frag.igi_nitems = 1; + frag.igi_data = frp; + + if (ioctl(fd, SIOCGENITER, &obj)) + return EFAULT; + return 0; +} + + +static void showtqtable_live(fd) +int fd; +{ + ipftq_t table[IPF_TCP_NSTATES]; + ipfobj_t obj; + + 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; + + if (ioctl(fd, SIOCGTQTAB, &obj) == 0) { + printtqtable(table); + } +} diff --git a/contrib/ipfilter/tools/ipftest.c b/contrib/ipfilter/tools/ipftest.c index 3b99a0b..963ed19 100644 --- a/contrib/ipfilter/tools/ipftest.c +++ b/contrib/ipfilter/tools/ipftest.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2002-2006 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -12,7 +12,7 @@ #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.9 2006/03/29 11:21:13 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ipftest.c,v 1.44.2.13 2006/12/12 16:13:01 darrenr Exp $"; #endif extern char *optarg; @@ -22,12 +22,13 @@ 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 **maptable; +extern hostmap_t **ipf_hm_maptable; +extern hostmap_t *ipf_hm_maplist; 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, ip_poolrw, ipf_frcache; -ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth; +ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth, ipf_tokens; int opts = OPT_DONOTHING; int use_inet6 = 0; int docksum = 0; @@ -103,6 +104,7 @@ char *argv[]; 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) @@ -251,7 +253,10 @@ char *argv[]; (void)printf("pass"); break; case 1 : - (void)printf("nomatch"); + if (m == NULL) + (void)printf("bad-packet"); + else + (void)printf("nomatch"); break; case 3 : (void)printf("block return-rst"); @@ -631,26 +636,23 @@ int n; */ void dumpnat() { - ipnat_t *ipn; - nat_t *nat; hostmap_t *hm; - int i; + 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); + printactivenat(nat, opts, 0, 0); if (nat->nat_aps) printaps(nat->nat_aps, opts); } printf("\nHostmap table:\n"); - for (i = 0; i < ipf_hostmap_sz; i++) { - for (hm = maptable[i]; hm != NULL; hm = hm->hm_next) - printhostmap(hm, i); - } + for (hm = ipf_hm_maplist; hm != NULL; hm = hm->hm_next) + printhostmap(hm, 0); } diff --git a/contrib/ipfilter/tools/ipmon.c b/contrib/ipfilter/tools/ipmon.c index fea09f3..f651f86 100644 --- a/contrib/ipfilter/tools/ipmon.c +++ b/contrib/ipfilter/tools/ipmon.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001, 2003 by Darren Reed. + * Copyright (C) 2001-2006 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -78,7 +78,7 @@ #if !defined(lint) static const char sccsid[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipmon.c,v 1.33.2.15 2006/03/18 06:59:39 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ipmon.c,v 1.33.2.18 2007/05/27 11:12:12 darrenr Exp $"; #endif @@ -817,27 +817,49 @@ int blen; (void) sprintf(t, ".%-.6ld ", ipl->ipl_usec); t += strlen(t); - if (sl->isl_type == ISL_NEW) + switch (sl->isl_type) + { + case ISL_NEW : strcpy(t, "STATE:NEW "); - else if (sl->isl_type == ISL_CLONE) + break; + + case ISL_CLONE : strcpy(t, "STATE:CLONED "); - else if (sl->isl_type == ISL_EXPIRE) { + break; + + case ISL_EXPIRE : if ((sl->isl_p == IPPROTO_TCP) && (sl->isl_state[0] > IPF_TCPS_ESTABLISHED || sl->isl_state[1] > IPF_TCPS_ESTABLISHED)) strcpy(t, "STATE:CLOSE "); else strcpy(t, "STATE:EXPIRE "); - } else if (sl->isl_type == ISL_FLUSH) + break; + + case ISL_FLUSH : strcpy(t, "STATE:FLUSH "); - else if (sl->isl_type == ISL_INTERMEDIATE) + break; + + case ISL_INTERMEDIATE : strcpy(t, "STATE:INTERMEDIATE "); - else if (sl->isl_type == ISL_REMOVE) + break; + + case ISL_REMOVE : strcpy(t, "STATE:REMOVE "); - else if (sl->isl_type == ISL_KILLED) + break; + + case ISL_KILLED : strcpy(t, "STATE:KILLED "); - else + break; + + case ISL_UNLOAD : + strcpy(t, "STATE:UNLOAD "); + break; + + default : sprintf(t, "Type: %d ", sl->isl_type); + break; + } t += strlen(t); proto = getproto(sl->isl_p); @@ -1629,6 +1651,7 @@ char *argv[]; if (!tr) continue; nr += tr; + n = 0; tr = read_log(fd[i], &n, buf, sizeof(buf)); if (donehup) { diff --git a/contrib/ipfilter/tools/ipmon_y.y b/contrib/ipfilter/tools/ipmon_y.y index e1aa812..98042d8 100644 --- a/contrib/ipfilter/tools/ipmon_y.y +++ b/contrib/ipfilter/tools/ipmon_y.y @@ -1,5 +1,10 @@ /* $FreeBSD$ */ +/* + * Copyright (C) 2001-2004 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ %{ #include "ipf.h" #include <syslog.h> @@ -77,6 +82,7 @@ assign: YY_STR assigning YY_STR ';' { set_variable($1, $3); resetlexer(); free($1); free($3); + yyvarnext = 0; } ; diff --git a/contrib/ipfilter/tools/ipnat.c b/contrib/ipfilter/tools/ipnat.c index 5ebea45..c9954ab 100644 --- a/contrib/ipfilter/tools/ipnat.c +++ b/contrib/ipfilter/tools/ipnat.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2001-2006 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * @@ -67,7 +67,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.2 2005/05/10 21:19:30 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ipnat.c,v 1.24.2.6 2007/05/11 11:16:55 darrenr Exp $"; #endif @@ -79,11 +79,17 @@ char thishost[MAXHOSTNAMELEN]; extern char *optarg; -void dostats __P((natstat_t *, int)), flushtable __P((int, int)); +void dostats __P((int, natstat_t *, int, int)); +void flushtable __P((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 showhostmap_dead __P((natstat_t *)); +void showhostmap_live __P((int, natstat_t *)); +void dostats_dead __P((natstat_t *, int)); +void showtqtable_live __P((int)); int opts; @@ -168,6 +174,15 @@ char *argv[]; (void) setuid(getuid()); } + if (!(opts & OPT_DONOTHING)) { + if (((fd = open(IPNAT_NAME, mode)) == -1) && + ((fd = open(IPNAT_NAME, O_RDONLY)) == -1)) { + (void) fprintf(stderr, "%s: open: %s\n", IPNAT_NAME, + STRERROR(errno)); + exit(1); + } + } + bzero((char *)&ns, sizeof(ns)); if ((opts & OPT_DONOTHING) == 0) { @@ -177,22 +192,11 @@ char *argv[]; } } - if (!(opts & OPT_DONOTHING) && (kernel == NULL) && (core == NULL)) { - if (openkmem(kernel, core) == -1) - exit(1); - - if (((fd = open(IPNAT_NAME, mode)) == -1) && - ((fd = open(IPNAT_NAME, O_RDONLY)) == -1)) { - (void) fprintf(stderr, "%s: open: %s\n", IPNAT_NAME, - STRERROR(errno)); - exit(1); - } - bzero((char *)&obj, sizeof(obj)); obj.ipfo_rev = IPFILTER_VERSION; - obj.ipfo_size = sizeof(*nsp); obj.ipfo_type = IPFOBJ_NATSTAT; + obj.ipfo_size = sizeof(*nsp); obj.ipfo_ptr = (void *)nsp; if (ioctl(fd, SIOCGNATS, &obj) == -1) { perror("ioctl(SIOCGNATS)"); @@ -206,7 +210,7 @@ char *argv[]; natstat_dead(nsp, kernel); if (opts & (OPT_LIST|OPT_STAT)) - dostats(nsp, opts); + dostats(fd, nsp, opts, 0); exit(0); } @@ -216,7 +220,7 @@ char *argv[]; ipnat_parsefile(fd, ipnat_addrule, ioctl, file); } if (opts & (OPT_LIST|OPT_STAT)) - dostats(nsp, opts); + dostats(fd, nsp, opts, 1); return 0; } @@ -277,15 +281,74 @@ 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; +{ + int n = 0; + + if (opts & OPT_FLUSH) { + n = 0; + if (!(opts & OPT_DONOTHING) && ioctl(fd, SIOCIPFFL, &n) == -1) + perror("ioctl(SIOCFLNAT)"); + else + 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)"); + else + printf("%d entries flushed from NAT list\n", n); + } +} + + +/* * Display NAT statistics. */ -void dostats(nsp, opts) +void dostats_dead(nsp, opts) natstat_t *nsp; int opts; { 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; + } + 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"); + + 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 (opts & OPT_VERBOSE) + showhostmap_dead(nsp); +} + + +void dostats(fd, nsp, opts, alive) +natstat_t *nsp; +int fd, opts, alive; +{ /* * Show statistics ? */ @@ -302,45 +365,78 @@ int opts; 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); } +} + + +/* + * Display NAT statistics. + */ +void dostats_live(fd, nsp, opts) +natstat_t *nsp; +int fd, opts; +{ + ipfgeniter_t iter; + ipfobj_t obj; + ipnat_t ipn; + nat_t nat; + + bzero((char *)&obj, sizeof(obj)); + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_type = IPFOBJ_GENITER; + obj.ipfo_size = sizeof(iter); + obj.ipfo_ptr = &iter; + + iter.igi_type = IPFGENITER_IPNAT; + iter.igi_nitems = 1; + iter.igi_data = &ipn; /* * 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"); - break; - } - if (opts & OPT_HITS) - printf("%lu ", ipn.in_hits); - printnat(&ipn, opts & (OPT_DEBUG|OPT_VERBOSE)); - nsp->ns_list = ipn.in_next; - } + 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"); + printf("\nList of active sessions:\n"); - for (np = nsp->ns_instances; np; np = nat.nat_next) { - if (kmemcpy((char *)&nat, (long)np, sizeof(nat))) - break; - printactivenat(&nat, opts); - if (nat.nat_aps) - printaps(nat.nat_aps, opts); - } + iter.igi_type = IPFGENITER_NAT; + iter.igi_nitems = 1; + iter.igi_data = &nat; - if (opts & OPT_VERBOSE) - showhostmap(nsp); + 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); + nsp->ns_instances = nat.nat_next; } + + if (opts & OPT_VERBOSE) + showhostmap_live(fd, nsp); } /* * Display the active host mapping table. */ -void showhostmap(nsp) +void showhostmap_dead(nsp) natstat_t *nsp; { hostmap_t hm, *hmp, **maptable; @@ -374,27 +470,50 @@ natstat_t *nsp; /* - * Issue an ioctl to flush either the NAT rules table or the active mapping - * table or both. + * Display the active host mapping table. */ -void flushtable(fd, opts) -int fd, opts; +void showhostmap_live(fd, nsp) +int fd; +natstat_t *nsp; { - int n = 0; + ipfgeniter_t iter; + hostmap_t hm; + ipfobj_t obj; - if (opts & OPT_FLUSH) { - n = 0; - if (!(opts & OPT_DONOTHING) && ioctl(fd, SIOCIPFFL, &n) == -1) - perror("ioctl(SIOCFLNAT)"); - else - printf("%d entries flushed from NAT table\n", n); + bzero((char *)&obj, sizeof(obj)); + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_type = IPFOBJ_GENITER; + obj.ipfo_size = sizeof(iter); + obj.ipfo_ptr = &iter; + + iter.igi_type = IPFGENITER_HOSTMAP; + iter.igi_nitems = 1; + iter.igi_data = &hm; + + printf("\nList of active host mappings:\n"); + + while (nsp->ns_maplist != NULL) { + if (ioctl(fd, SIOCGENITER, &obj) == -1) + break; + printhostmap(&hm, 0); + nsp->ns_maplist = hm.hm_next; } +} - if (opts & OPT_CLEAR) { - n = 1; - if (!(opts & OPT_DONOTHING) && ioctl(fd, SIOCIPFFL, &n) == -1) - perror("ioctl(SIOCCNATL)"); - else - printf("%d entries flushed from NAT list\n", n); + +void showtqtable_live(fd) +int fd; +{ + ipftq_t table[IPF_TCP_NSTATES]; + ipfobj_t obj; + + 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; + + if (ioctl(fd, SIOCGTQTAB, &obj) == 0) { + printtqtable(table); } } diff --git a/contrib/ipfilter/tools/ipnat_y.y b/contrib/ipfilter/tools/ipnat_y.y index a01ec56..1857219 100644 --- a/contrib/ipfilter/tools/ipnat_y.y +++ b/contrib/ipfilter/tools/ipnat_y.y @@ -1,5 +1,10 @@ /* $FreeBSD$ */ +/* + * Copyright (C) 2001-2006 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ %{ #ifdef __FreeBSD__ # ifndef __FreeBSD_cc_version @@ -117,6 +122,7 @@ assign: YY_STR assigning YY_STR ';' { set_variable($1, $3); resetlexer(); free($1); free($3); + yyvarnext = 0; } ; @@ -348,11 +354,11 @@ portspec: ; dport: | port portspec { nat->in_pmin = htons($2); - nat->in_pmax = htons($2); } + nat->in_pmax = htons($2); } | port portspec '-' portspec { nat->in_pmin = htons($2); - nat->in_pmax = htons($4); } + nat->in_pmax = htons($4); } | port portspec ':' portspec { nat->in_pmin = htons($2); - nat->in_pmax = htons($4); } + nat->in_pmax = htons($4); } ; nport: port portspec { nat->in_pnext = htons($2); } diff --git a/contrib/ipfilter/tools/ippool.c b/contrib/ipfilter/tools/ippool.c index 5cefc66..8b70960 100644 --- a/contrib/ipfilter/tools/ippool.c +++ b/contrib/ipfilter/tools/ippool.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2003 by Darren Reed. + * Copyright (C) 2002-2006 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -29,8 +29,14 @@ #include <netdb.h> #include <ctype.h> #include <unistd.h> +#ifdef linux +# include <linux/a.out.h> +#else +# include <nlist.h> +#endif #include "ipf.h" +#include "netinet/ipl.h" #include "netinet/ip_lookup.h" #include "netinet/ip_pool.h" #include "netinet/ip_htable.h" @@ -43,17 +49,21 @@ extern FILE *ippool_yyin; extern char *optarg; extern int lineNum; -void showpools __P((ip_pool_stat_t *)); void usage __P((char *)); int main __P((int, char **)); int poolcommand __P((int, int, char *[])); int poolnodecommand __P((int, int, char *[])); int loadpoolfile __P((int, char *[], char *)); int poollist __P((int, char *[])); +void poollist_dead __P((int, char *, int, char *, char *)); +void poollist_live __P((int, char *, int, int)); 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 *)); +void showhashs_live __P((int, int, iphtstat_t *, char *)); int opts = 0; int fd = -1; @@ -115,7 +125,9 @@ char *argv[]; exit(1); } - return err; + if (err != 0) + exit(1); + return 0; } @@ -123,10 +135,9 @@ int poolnodecommand(remove, argc, argv) int remove, argc; char *argv[]; { - char *poolname = NULL, *s; int err, c, ipset, role; + char *poolname = NULL; ip_pool_node_t node; - struct in_addr mask; ipset = 0; role = IPL_LOGIPF; @@ -140,22 +151,8 @@ char *argv[]; ippool_yydebug++; break; case 'i' : - s = strchr(optarg, '/'); - if (s == NULL) - mask.s_addr = 0xffffffff; - else if (strchr(s, '.') == NULL) { - if (ntomask(4, atoi(s + 1), &mask.s_addr) != 0) - return -1; - } else { - mask.s_addr = inet_addr(s + 1); - } - if (s != NULL) - *s = '\0'; - ipset = 1; - node.ipn_addr.adf_len = sizeof(node.ipn_addr); - node.ipn_addr.adf_addr.in4.s_addr = inet_addr(optarg); - node.ipn_mask.adf_len = sizeof(node.ipn_mask); - node.ipn_mask.adf_addr.in4.s_addr = mask.s_addr; + if (setnodeaddr(&node, optarg) == 0) + ipset = 1; break; case 'm' : poolname = optarg; @@ -176,11 +173,19 @@ char *argv[]; break; } + if (argv[optind] != NULL && ipset == 0) { + if (setnodeaddr(&node, argv[optind]) == 0) + ipset = 1; + } + if (opts & OPT_DEBUG) fprintf(stderr, "poolnodecommand: opts = %#x\n", opts); - if (ipset == 0) + if (ipset == 0) { + fprintf(stderr, "no IP address given with -i\n"); return -1; + } + if (poolname == NULL) { fprintf(stderr, "poolname not given with add/remove node\n"); return -1; @@ -338,151 +343,6 @@ char *argv[], *infile; } -int poollist(argc, argv) -int argc; -char *argv[]; -{ - char *kernel, *core, *poolname; - int c, role, type, live_kernel; - ip_pool_stat_t *plstp, plstat; - iphtstat_t *htstp, htstat; - iphtable_t *hptr; - iplookupop_t op; - ip_pool_t *ptr; - - core = NULL; - kernel = NULL; - live_kernel = 1; - type = IPLT_ALL; - poolname = NULL; - role = IPL_LOGALL; - - while ((c = getopt(argc, argv, "dm:M:N:o:Rt:v")) != -1) - switch (c) - { - case 'd' : - opts |= OPT_DEBUG; - break; - case 'm' : - poolname = optarg; - break; - case 'M' : - live_kernel = 0; - core = optarg; - break; - case 'N' : - live_kernel = 0; - kernel = optarg; - break; - case 'o' : - role = getrole(optarg); - if (role == IPL_LOGNONE) { - fprintf(stderr, "unknown role '%s'\n", optarg); - return -1; - } - break; - case 'R' : - opts |= OPT_NORESOLVE; - break; - case 't' : - type = gettype(optarg, NULL); - if (type == IPLT_NONE) { - fprintf(stderr, "unknown type '%s'\n", optarg); - return -1; - } - break; - case 'v' : - opts |= OPT_VERBOSE; - break; - } - - if (opts & OPT_DEBUG) - fprintf(stderr, "poollist: opts = %#x\n", opts); - - if (!(opts & OPT_DONOTHING) && (fd == -1)) { - fd = open(IPLOOKUP_NAME, O_RDWR); - if (fd == -1) { - perror("open(IPLOOKUP_NAME)"); - exit(1); - } - } - - bzero((char *)&op, sizeof(op)); - if (poolname != NULL) { - strncpy(op.iplo_name, poolname, sizeof(op.iplo_name)); - op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; - } - op.iplo_unit = role; - - if (openkmem(kernel, core) == -1) - exit(-1); - - if (type == IPLT_ALL || type == IPLT_POOL) { - plstp = &plstat; - op.iplo_type = IPLT_POOL; - op.iplo_size = sizeof(plstat); - op.iplo_struct = &plstat; - c = ioctl(fd, SIOCLOOKUPSTAT, &op); - if (c == -1) { - perror("ioctl(SIOCLOOKUPSTAT)"); - return -1; - } - - if (role != IPL_LOGALL) { - ptr = plstp->ipls_list[role]; - while (ptr != NULL) { - ptr = printpool(ptr, kmemcpywrap, poolname, - opts); - } - } else { - for (role = 0; role <= IPL_LOGMAX; role++) { - ptr = plstp->ipls_list[role]; - while (ptr != NULL) { - ptr = printpool(ptr, kmemcpywrap, - poolname, opts); - } - } - role = IPL_LOGALL; - } - } - if (type == IPLT_ALL || type == IPLT_HASH) { - htstp = &htstat; - op.iplo_type = IPLT_HASH; - op.iplo_size = sizeof(htstat); - op.iplo_struct = &htstat; - c = ioctl(fd, SIOCLOOKUPSTAT, &op); - if (c == -1) { - perror("ioctl(SIOCLOOKUPSTAT)"); - return -1; - } - - if (role != IPL_LOGALL) { - hptr = htstp->iphs_tables; - while (hptr != NULL) { - hptr = printhash(hptr, kmemcpywrap, - poolname, opts); - } - } else { - for (role = 0; role <= IPL_LOGMAX; role++) { - hptr = htstp->iphs_tables; - while (hptr != NULL) { - hptr = printhash(hptr, kmemcpywrap, - poolname, opts); - } - - op.iplo_unit = role; - c = ioctl(fd, SIOCLOOKUPSTAT, &op); - if (c == -1) { - perror("ioctl(SIOCLOOKUPSTAT)"); - return -1; - } - } - } - } - return 0; -} - - int poolstats(argc, argv) int argc; char *argv[]; @@ -683,7 +543,7 @@ u_int *minor; { int type; - if (!strcasecmp(optarg, "tree")) { + if (!strcasecmp(optarg, "tree") || !strcasecmp(optarg, "pool")) { type = IPLT_POOL; } else if (!strcasecmp(optarg, "hash")) { type = IPLT_HASH; @@ -698,3 +558,321 @@ u_int *minor; } return type; } + + +int poollist(argc, argv) +int argc; +char *argv[]; +{ + char *kernel, *core, *poolname; + int c, role, type, live_kernel; + iplookupop_t op; + + core = NULL; + kernel = NULL; + live_kernel = 1; + type = IPLT_ALL; + poolname = NULL; + role = IPL_LOGALL; + + while ((c = getopt(argc, argv, "dm:M:N:o:Rt:v")) != -1) + switch (c) + { + case 'd' : + opts |= OPT_DEBUG; + break; + case 'm' : + poolname = optarg; + break; + case 'M' : + live_kernel = 0; + core = optarg; + break; + case 'N' : + live_kernel = 0; + kernel = optarg; + break; + case 'o' : + role = getrole(optarg); + if (role == IPL_LOGNONE) { + fprintf(stderr, "unknown role '%s'\n", optarg); + return -1; + } + break; + case 'R' : + opts |= OPT_NORESOLVE; + break; + case 't' : + type = gettype(optarg, NULL); + if (type == IPLT_NONE) { + fprintf(stderr, "unknown type '%s'\n", optarg); + return -1; + } + break; + case 'v' : + opts |= OPT_VERBOSE; + break; + } + + if (opts & OPT_DEBUG) + fprintf(stderr, "poollist: opts = %#x\n", opts); + + if (!(opts & OPT_DONOTHING) && (fd == -1)) { + fd = open(IPLOOKUP_NAME, O_RDWR); + if (fd == -1) { + perror("open(IPLOOKUP_NAME)"); + exit(1); + } + } + + bzero((char *)&op, sizeof(op)); + if (poolname != NULL) { + strncpy(op.iplo_name, poolname, sizeof(op.iplo_name)); + op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; + } + op.iplo_unit = role; + + if (live_kernel) + poollist_live(role, poolname, type, fd); + else + poollist_dead(role, poolname, type, kernel, core); + return 0; +} + + +void poollist_dead(role, poolname, type, kernel, core) +int role, type; +char *poolname, *kernel, *core; +{ + iphtable_t *hptr; + ip_pool_t *ptr; + + if (openkmem(kernel, core) == -1) + exit(-1); + + if (type == IPLT_ALL || type == IPLT_POOL) { + ip_pool_t *pools[IPL_LOGSIZE]; + struct nlist names[2] = { { "ip_pool_list" } , { "" } }; + + if (nlist(kernel, names) != 1) + return; + + bzero(&pools, sizeof(pools)); + if (kmemcpy((char *)&pools, names[0].n_value, sizeof(pools))) + return; + + if (role != IPL_LOGALL) { + ptr = pools[role]; + while (ptr != NULL) { + ptr = printpool(ptr, kmemcpywrap, poolname, + opts); + } + } else { + for (role = 0; role <= IPL_LOGMAX; role++) { + ptr = pools[role]; + while (ptr != NULL) { + ptr = printpool(ptr, kmemcpywrap, + poolname, opts); + } + } + role = IPL_LOGALL; + } + } + if (type == IPLT_ALL || type == IPLT_HASH) { + iphtable_t *tables[IPL_LOGSIZE]; + struct nlist names[2] = { { "ipf_htables" } , { "" } }; + + if (nlist(kernel, names) != 1) + return; + + bzero(&tables, sizeof(tables)); + if (kmemcpy((char *)&tables, names[0].n_value, sizeof(tables))) + return; + + if (role != IPL_LOGALL) { + hptr = tables[role]; + while (hptr != NULL) { + hptr = printhash(hptr, kmemcpywrap, + poolname, opts); + } + } else { + for (role = 0; role <= IPL_LOGMAX; role++) { + hptr = tables[role]; + while (hptr != NULL) { + hptr = printhash(hptr, kmemcpywrap, + poolname, opts); + } + } + } + } +} + + +void poollist_live(role, poolname, type, fd) +int role, type, fd; +char *poolname; +{ + ip_pool_stat_t plstat; + iphtstat_t htstat; + iplookupop_t op; + int c; + + if (type == IPLT_ALL || type == IPLT_POOL) { + op.iplo_type = IPLT_POOL; + op.iplo_size = sizeof(plstat); + op.iplo_struct = &plstat; + 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) { + perror("ioctl(SIOCLOOKUPSTAT)"); + return; + } + + showpools_live(fd, role, &plstat, poolname); + } else { + for (role = 0; role <= IPL_LOGMAX; role++) { + op.iplo_unit = role; + + c = ioctl(fd, SIOCLOOKUPSTAT, &op); + if (c == -1) { + perror("ioctl(SIOCLOOKUPSTAT)"); + return; + } + + showpools_live(fd, role, &plstat, poolname); + } + + role = IPL_LOGALL; + } + } + + if (type == IPLT_ALL || type == IPLT_HASH) { + op.iplo_type = IPLT_HASH; + op.iplo_size = sizeof(htstat); + op.iplo_struct = &htstat; + 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) { + perror("ioctl(SIOCLOOKUPSTAT)"); + return; + } + showhashs_live(fd, role, &htstat, poolname); + } else { + for (role = 0; role <= IPL_LOGMAX; role++) { + + op.iplo_unit = role; + c = ioctl(fd, SIOCLOOKUPSTAT, &op); + if (c == -1) { + perror("ioctl(SIOCLOOKUPSTAT)"); + return; + } + + showhashs_live(fd, role, &htstat, poolname); + } + } + } +} + + +void showpools_live(fd, role, plstp, poolname) +int fd, role; +ip_pool_stat_t *plstp; +char *poolname; +{ + ipflookupiter_t iter; + ip_pool_t pool; + 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_POOL; + iter.ili_otype = IPFLOOKUPITER_LIST; + iter.ili_ival = IPFGENITER_LOOKUP; + iter.ili_nitems = 1; + iter.ili_data = &pool; + iter.ili_unit = role; + *iter.ili_name = '\0'; + + while (plstp->ipls_list[role] != NULL) { + if (ioctl(fd, SIOCLOOKUPITER, &obj)) { + perror("ioctl(SIOCLOOKUPITER)"); + break; + } + printpool_live(&pool, fd, poolname, opts); + + plstp->ipls_list[role] = pool.ipo_next; + } +} + + +void showhashs_live(fd, role, htstp, poolname) +int fd, role; +iphtstat_t *htstp; +char *poolname; +{ + ipflookupiter_t iter; + iphtable_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_HASH; + 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 (htstp->iphs_tables != NULL) { + if (ioctl(fd, SIOCLOOKUPITER, &obj)) { + perror("ioctl(SIOCLOOKUPITER)"); + break; + } + + printhash_live(&table, fd, poolname, opts); + + htstp->iphs_tables = table.iph_next; + } +} + + +int setnodeaddr(ip_pool_node_t *node, char *arg) +{ + struct in_addr mask; + char *s; + + s = strchr(arg, '/'); + if (s == NULL) + mask.s_addr = 0xffffffff; + else if (strchr(s, '.') == NULL) { + if (ntomask(4, 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; + + return 0; +} diff --git a/contrib/ipfilter/tools/ippool_y.y b/contrib/ipfilter/tools/ippool_y.y index f0ba451..24f683b 100644 --- a/contrib/ipfilter/tools/ippool_y.y +++ b/contrib/ipfilter/tools/ippool_y.y @@ -1,5 +1,10 @@ /* $FreeBSD$ */ +/* + * Copyright (C) 2001-2006 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ %{ #include <sys/types.h> #include <sys/time.h> @@ -34,6 +39,7 @@ #include "kmem.h" #define YYDEBUG 1 +#define YYSTACKSIZE 0x00ffffff extern int yyparse __P((void)); extern int yydebug; @@ -45,6 +51,9 @@ static ip_pool_t iplo; 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 *)); + %} %union { @@ -112,6 +121,7 @@ assign: YY_STR assigning YY_STR ';' { set_variable($1, $3); resetlexer(); free($1); free($3); + yyvarnext = 0; } ; @@ -248,6 +258,7 @@ groupentry: FR_GROUPLEN); free($3); } + | YY_STR { $$ = add_htablehosts($1); } ; range: addrmask { $$ = calloc(1, sizeof(*$$)); @@ -264,6 +275,7 @@ range: addrmask { $$ = calloc(1, sizeof(*$$)); $$->ipn_mask.adf_len = sizeof($$->ipn_mask); $$->ipn_mask.adf_addr.in4.s_addr = $2[1].s_addr; } + | YY_STR { $$ = add_poolhosts($1); } hashlist: next { $$ = NULL; } @@ -280,6 +292,7 @@ hashentry: (char *)&($$->ipe_mask), sizeof($$->ipe_mask)); } + | YY_STR { $$ = add_htablehosts($1); } ; addrmask: @@ -293,9 +306,6 @@ addrmask: ipaddr: ipv4 { $$ = $1; } | YY_NUMBER { $$.s_addr = htonl($1); } - | YY_STR { if (gethost($1, &($$.s_addr)) == -1) - yyerror("Unknown hostname"); - } ; mask: YY_NUMBER { ntomask(4, $1, (u_32_t *)&$$.s_addr); } @@ -413,3 +423,100 @@ ioctlfunc_t iocfunc; yyparse(); return 1; } + + +static iphtent_t * +add_htablehosts(url) +char *url; +{ + iphtent_t *htop, *hbot, *h; + alist_t *a, *hlist; + + if (!strncmp(url, "file://", 7) || !strncmp(url, "http://", 7)) { + hlist = load_url(url); + } else { + use_inet6 = 0; + + hlist = calloc(1, sizeof(*hlist)); + if (hlist == NULL) + return NULL; + + if (gethost(url, &hlist->al_addr) == -1) + yyerror("Unknown hostname"); + } + + hbot = NULL; + htop = NULL; + + for (a = hlist; a != NULL; a = a->al_next) { + h = calloc(1, sizeof(*h)); + 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)); + + if (hbot != NULL) + hbot->ipe_next = h; + else + htop = h; + hbot = h; + } + + alist_free(hlist); + + return htop; +} + + +static ip_pool_node_t * +add_poolhosts(url) +char *url; +{ + ip_pool_node_t *ptop, *pbot, *p; + alist_t *a, *hlist; + + if (!strncmp(url, "file://", 7) || !strncmp(url, "http://", 7)) { + hlist = load_url(url); + } else { + use_inet6 = 0; + + hlist = calloc(1, sizeof(*hlist)); + if (hlist == NULL) + return NULL; + + if (gethost(url, &hlist->al_addr) == -1) + yyerror("Unknown hostname"); + } + + pbot = NULL; + ptop = NULL; + + for (a = hlist; a != NULL; a = a->al_next) { + p = calloc(1, sizeof(*p)); + if (p == NULL) + break; + + p->ipn_addr.adf_len = 8; + p->ipn_mask.adf_len = 8; + + 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)); + + if (pbot != NULL) + pbot->ipn_next = p; + else + ptop = p; + pbot = p; + } + + alist_free(hlist); + + return ptop; +} diff --git a/contrib/ipfilter/tools/ipscan_y.y b/contrib/ipfilter/tools/ipscan_y.y index af360d4..5dbefd6 100644 --- a/contrib/ipfilter/tools/ipscan_y.y +++ b/contrib/ipfilter/tools/ipscan_y.y @@ -1,5 +1,10 @@ /* $FreeBSD$ */ +/* + * Copyright (C) 2001-2004 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ %{ #include <sys/types.h> #include <sys/ioctl.h> @@ -94,6 +99,7 @@ assign: YY_STR assigning YY_STR resetlexer(); free($1); free($3); + yyvarnext = 0; } ; diff --git a/contrib/ipfilter/tools/ipsyncm.c b/contrib/ipfilter/tools/ipsyncm.c index c712435..600d39a 100644 --- a/contrib/ipfilter/tools/ipsyncm.c +++ b/contrib/ipfilter/tools/ipsyncm.c @@ -1,13 +1,13 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2001-2006 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.4 2006/03/27 02:09:46 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ipsyncm.c,v 1.4.2.5 2006/08/26 11:21:14 darrenr Exp $"; #endif #include <sys/types.h> #include <sys/time.h> diff --git a/contrib/ipfilter/tools/ipsyncs.c b/contrib/ipfilter/tools/ipsyncs.c index c6662b7..887eeab 100644 --- a/contrib/ipfilter/tools/ipsyncs.c +++ b/contrib/ipfilter/tools/ipsyncs.c @@ -1,13 +1,13 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 2001-2006 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.3 2006/03/27 02:09:47 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ipsyncs.c,v 1.5.2.4 2006/08/26 11:21:15 darrenr Exp $"; #endif #include <sys/types.h> #include <sys/time.h> diff --git a/contrib/ipfilter/tools/lex_var.h b/contrib/ipfilter/tools/lex_var.h index 547ebf3..78c5efc 100644 --- a/contrib/ipfilter/tools/lex_var.h +++ b/contrib/ipfilter/tools/lex_var.h @@ -1,5 +1,10 @@ /* $FreeBSD$ */ +/* + * Copyright (C) 2002 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ extern long string_start; extern long string_end; diff --git a/contrib/ipfilter/tools/lexer.c b/contrib/ipfilter/tools/lexer.c index 3969a5f..2969f86 100644 --- a/contrib/ipfilter/tools/lexer.c +++ b/contrib/ipfilter/tools/lexer.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2003 by Darren Reed. + * Copyright (C) 2002-2006 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -285,8 +285,9 @@ nextchar: yypos++; } } while (n != c); - yyunputc(n); - break; + rval = YY_STR; + goto done; + /* NOTREACHED */ case EOF : yylineNum = 1; @@ -467,6 +468,9 @@ nextchar: done: yystr = yytexttostr(0, yypos); + if (yydebug) + printf("isbuilding %d yyvarnext %d nokey %d\n", + isbuilding, yyvarnext, nokey); if (isbuilding == 1) { wordtab_t *w; @@ -493,8 +497,8 @@ done: yytokentype = rval; if (yydebug) - printf("lexed(%s) [%d,%d,%d] => %d\n", yystr, string_start, - string_end, pos, rval); + printf("lexed(%s) [%d,%d,%d] => %d @%d\n", yystr, string_start, + string_end, pos, rval, yysavedepth); switch (rval) { @@ -609,6 +613,8 @@ wordtab_t *newdict; void yyresetdict() { + if (yydebug) + printf("yyresetdict(%d)\n", yysavedepth); if (yysavedepth > 0) { yysettab(yysavewords[--yysavedepth]); if (yydebug) diff --git a/contrib/ipfilter/tools/lexer.h b/contrib/ipfilter/tools/lexer.h index b172c93..d973ea4 100644 --- a/contrib/ipfilter/tools/lexer.h +++ b/contrib/ipfilter/tools/lexer.h @@ -1,5 +1,10 @@ /* $FreeBSD$ */ +/* + * Copyright (C) 2002-2004 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ typedef struct wordtab { char *w_word; diff --git a/sbin/ipf/libipf/Makefile b/sbin/ipf/libipf/Makefile index 33c3563..d099c35 100644 --- a/sbin/ipf/libipf/Makefile +++ b/sbin/ipf/libipf/Makefile @@ -3,27 +3,27 @@ LIB= ipf INTERNALLIB= -SRCS= addicmp.c addipopt.c bcopywrap.c binprint.c \ - buildopts.c checkrev.c count6bits.c count4bits.c debug.c \ - extras.c facpri.c flags.c fill6bits.c genmask.c gethost.c \ - getifname.c getline.c getnattype.c getport.c getportproto.c \ - getproto.c getsumd.c hexdump.c hostmask.c hostname.c \ - hostnum.c icmpcode.c initparse.c ionames.c \ - ipoptsec.c ipf_dotuning.c ipft_ef.c ipft_hx.c ipft_pc.c \ - ipft_sn.c ipft_td.c ipft_tx.c kmem.c kmemcpywrap.c \ - kvatoname.c load_hash.c load_hashnode.c load_pool.c \ - load_poolnode.c mutex_emul.c \ - nametokva.c nat_setgroupmap.c ntomask.c optname.c \ - optprint.c optprintv6.c optvalue.c portname.c portnum.c \ - ports.c print_toif.c printactivenat.c printaps.c printbuf.c \ - printhash.c printhashnode.c printip.c printpool.c \ - printpoolnode.c printfr.c printfraginfo.c printhostmap.c \ - printifname.c printhostmask.c printlog.c printmask.c \ - printnat.c printportcmp.c printpacket.c printpacket6.c \ - printproto.c printsbuf.c printstate.c printtunable.c ratoi.c \ - ratoui.c remove_hash.c remove_hashnode.c remove_pool.c \ - remove_poolnode.c resetlexer.c rwlock_emul.c tcpflags.c \ - tcp_flags.c to_interface.c var.c verbose.c v6ionames.c \ - v6optvalue.c +SRCS= addicmp.c addipopt.c alist_free.c alist_new.c bcopywrap.c \ + binprint.c buildopts.c checkrev.c count4bits.c count6bits.c \ + debug.c facpri.c fill6bits.c flags.c gethost.c getifname.c \ + getnattype.c getport.c getportproto.c getproto.c getsumd.c \ + hostname.c icmpcode.c inet_addr.c initparse.c ionames.c \ + ipf_dotuning.c ipft_ef.c ipft_hx.c ipft_pc.c ipft_sn.c \ + ipft_td.c ipft_tx.c ipoptsec.c kmem.c kmemcpywrap.c \ + kvatoname.c load_file.c load_hash.c load_hashnode.c \ + load_http.c load_pool.c load_poolnode.c load_url.c \ + mutex_emul.c nametokva.c nat_setgroupmap.c ntomask.c \ + optname.c optprint.c optprintv6.c optvalue.c portname.c \ + print_toif.c printactivenat.c printaps.c printbuf.c \ + printfr.c printfraginfo.c printhash.c printhash_live.c \ + printhashdata.c printhashnode.c printhostmap.c \ + printhostmask.c printifname.c printip.c printlog.c \ + printmask.c printnat.c printpacket.c printpacket6.c \ + printpool.c printpool_live.c printpooldata.c printpoolnode.c \ + printportcmp.c printproto.c printsbuf.c printstate.c \ + printtqtable.c printtunable.c remove_hash.c remove_hashnode.c \ + remove_pool.c remove_poolnode.c resetlexer.c rwlock_emul.c \ + tcp_flags.c tcpflags.c tcpoptnames.c v6ionames.c v6optvalue.c \ + var.c verbose.c .include <bsd.lib.mk> diff --git a/sys/contrib/ipfilter/netinet/fil.c b/sys/contrib/ipfilter/netinet/fil.c index ee21a94..7c015ea 100644 --- a/sys/contrib/ipfilter/netinet/fil.c +++ b/sys/contrib/ipfilter/netinet/fil.c @@ -17,7 +17,11 @@ #include <sys/time.h> #if defined(__NetBSD__) # if (NetBSD >= 199905) && !defined(IPFILTER_LKM) && defined(_KERNEL) -# include "opt_ipfilter_log.h" +# if (__NetBSD_Version__ < 399001400) +# include "opt_ipfilter_log.h" +# else +# include "opt_ipfilter.h" +# endif # endif #endif #if defined(_KERNEL) && defined(__FreeBSD_version) && \ @@ -34,6 +38,9 @@ #else # include <sys/ioctl.h> #endif +#if (defined(__SVR4) || defined(__svr4__)) && defined(sun) +# include <sys/filio.h> +#endif #if !defined(_AIX51) # include <sys/fcntl.h> #endif @@ -81,7 +88,11 @@ struct file; # endif # include "radix_ipf.h" #endif -#include <net/route.h> +#ifdef __osf__ +# include "radix_ipf.h" +#else +# include <net/route.h> +#endif #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> @@ -100,6 +111,9 @@ struct file; #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> @@ -154,7 +168,7 @@ extern int opts; fr_info_t frcache[2][8]; -struct filterstats frstats[2] = { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 } }; +struct filterstats frstats[2]; struct frentry *ipfilter[2][2] = { { NULL, NULL }, { NULL, NULL } }, *ipfilter6[2][2] = { { NULL, NULL }, { NULL, NULL } }, *ipacct6[2][2] = { { NULL, NULL }, { NULL, NULL } }, @@ -235,11 +249,14 @@ static INLINE int frpr_udpcommon __P((fr_info_t *)); static 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 *)); +static INLINE void *fr_resolvelookup __P((u_int, u_int, i6addr_t *, lookupfunc_t *)); #endif static void frsynclist __P((frentry_t *, void *)); static ipftuneable_t *fr_findtunebyname __P((const char *)); static ipftuneable_t *fr_findtunebycookie __P((void *, void **)); +static int ipf_geniter __P((ipftoken_t *, ipfgeniter_t *)); +static int ipf_frruleiter __P((void *, int, void *)); +static void ipf_unlinktoken __P((ipftoken_t *)); /* @@ -319,7 +336,7 @@ static ipfunc_resolve_t fr_availfuncs[] = { { "fr_srcgrpmap", fr_srcgrpmap, fr_grpmapinit }, { "fr_dstgrpmap", fr_dstgrpmap, fr_grpmapinit }, #endif - { "", NULL } + { "", NULL, NULL } }; @@ -532,7 +549,16 @@ int multiple, proto; return IPPROTO_NONE; 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; @@ -551,6 +577,7 @@ int multiple, proto; break; } + fin->fin_exthdr = fin->fin_dp; fin->fin_dp = (char *)fin->fin_dp + shift; fin->fin_dlen -= shift; @@ -600,24 +627,22 @@ static INLINE int frpr_routing6(fin) fr_info_t *fin; { struct ip6_ext *hdr; - int shift; if (frpr_ipv6exthdr(fin, 0, IPPROTO_ROUTING) == IPPROTO_NONE) return IPPROTO_NONE; + hdr = fin->fin_exthdr; - hdr = fin->fin_dp; - shift = 8 + (hdr->ip6e_len << 3); - /* - * Nasty extension header length? - */ - if ((shift < sizeof(struct ip6_hdr)) || - ((shift - sizeof(struct ip6_hdr)) & 15)) { + if ((hdr->ip6e_len & 1) != 0) { + /* + * The routing header data is made up of 128 bit IPv6 addresses + * which means it must be a multiple of 2 lots of 8 in length. + */ fin->fin_flx |= FI_BAD; /* * Compensate for the changes made in frpr_ipv6exthdr() */ - fin->fin_dlen += shift; - fin->fin_dp = (char *)fin->fin_dp - shift; + fin->fin_dlen += 8 + (hdr->ip6e_len << 3); + fin->fin_dp = hdr; return IPPROTO_NONE; } @@ -643,16 +668,20 @@ static INLINE void frpr_fragment6(fin) fr_info_t *fin; { struct ip6_frag *frag; + int extoff; fin->fin_flx |= FI_FRAG; if (frpr_ipv6exthdr(fin, 0, IPPROTO_FRAGMENT) == IPPROTO_NONE) return; + extoff = (char *)fin->fin_exthdr - (char *)fin->fin_dp; + if (frpr_pullup(fin, sizeof(*frag)) == -1) return; - frag = fin->fin_dp; + fin->fin_exthdr = (char *)fin->fin_dp + extoff; + frag = fin->fin_exthdr; /* * Fragment but no fragmentation info set? Bad packet... */ @@ -702,10 +731,12 @@ 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 (frpr_pullup(fin, ICMP6ERR_MINPKTLEN - sizeof(ip6_t)) == -1) return; if (fin->fin_dlen > 1) { + ip6_t *ip6; + icmp6 = fin->fin_dp; fin->fin_data[0] = *(u_short *)icmp6; @@ -720,12 +751,26 @@ fr_info_t *fin; case ICMP6_PACKET_TOO_BIG : case ICMP6_TIME_EXCEEDED : case ICMP6_PARAM_PROB : + fin->fin_flx |= FI_ICMPERR; if ((fin->fin_m != NULL) && (M_LEN(fin->fin_m) < fin->fin_plen)) { if (fr_coalesce(fin) != 1) return; } - fin->fin_flx |= FI_ICMPERR; + + if (frpr_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. + */ + 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; + minicmpsz = ICMP6ERR_IPICMPHLEN - sizeof(ip6_t); break; default : @@ -752,8 +797,13 @@ fr_info_t *fin; frpr_short6(fin, sizeof(struct udphdr)); - if (frpr_udpcommon(fin) == 0) + if (frpr_udpcommon(fin) == 0) { + u_char p = fin->fin_p; + + fin->fin_p = IPPROTO_UDP; fr_checkv6sum(fin); + fin->fin_p = p; + } } @@ -772,8 +822,13 @@ fr_info_t *fin; frpr_short6(fin, sizeof(struct tcphdr)); - if (frpr_tcpcommon(fin) == 0) + if (frpr_tcpcommon(fin) == 0) { + u_char p = fin->fin_p; + + fin->fin_p = IPPROTO_TCP; fr_checkv6sum(fin); + fin->fin_p = p; + } } @@ -862,18 +917,26 @@ static INLINE int frpr_pullup(fin, plen) fr_info_t *fin; int plen; { -#if defined(_KERNEL) 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 defined(_KERNEL) if (fr_pullup(fin->fin_m, fin, plen) == NULL) return -1; +#else + /* + * Fake fr_pullup failing + */ + *fin->fin_mp = NULL; + fin->fin_m = NULL; + fin->fin_ip = NULL; + return -1; +#endif } } -#endif return 0; } @@ -987,6 +1050,22 @@ fr_info_t *fin; oip = (ip_t *)((char *)fin->fin_dp + ICMPERR_ICMPHLEN); if ((ntohs(oip->ip_off) & IP_OFFMASK) != 0) fin->fin_flx |= FI_BAD; + + /* + * If the destination of this packet doesn't match the + * source of the original packet then this packet is + * not correct. + */ + if (oip->ip_src.s_addr != fin->fin_daddr) + fin->fin_flx |= FI_BAD; + + /* + * If the destination of this packet doesn't match the + * source of the original packet then this packet is + * not correct. + */ + if (oip->ip_src.s_addr != fin->fin_daddr) + fin->fin_flx |= FI_BAD; break; default : break; @@ -1054,14 +1133,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 @@ -1347,13 +1439,16 @@ fr_info_t *fin; */ 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 > 65535) || - (fin->fin_dlen == 0) || (fin->fin_dlen & 7)) { + (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 @@ -1507,18 +1602,24 @@ fr_info_t *fin; 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) + if (v == 4) { + fin->fin_plen = ip->ip_len; + fin->fin_dlen = fin->fin_plen - hlen; + frpr_ipv4hdr(fin); #ifdef USE_INET6 - else if (v == 6) { + } else if (v == 6) { + fin->fin_plen = ntohs(((ip6_t *)ip)->ip6_plen); + fin->fin_dlen = fin->fin_plen; + fin->fin_plen += hlen; + if (frpr_ipv6hdr(fin) == -1) return -1; - } #endif + } if (fin->fin_ip == NULL) return -1; return 0; @@ -1680,7 +1781,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; @@ -1691,7 +1792,7 @@ int portcmp; lip++, lm++, ld++; i |= ((*lip & *lm) != *ld); FR_DEBUG(("1. %#08x & %#08x != %#08x\n", - *lip, *lm, *ld)); + ntohl(*lip), ntohl(*lm), ntohl(*ld))); if (i) return 1; @@ -1714,20 +1815,20 @@ int portcmp; #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; @@ -1756,20 +1857,20 @@ int portcmp; #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; @@ -2297,9 +2398,6 @@ int out; 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 * into the filtering engine makes some sense. Information about the @@ -2395,13 +2493,10 @@ int out; * 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) { pass = FR_BLOCK|FR_NOMATCH; goto finished; } - fin->fin_plen += sizeof(ip6_t); } else #endif { @@ -2409,7 +2504,6 @@ int out; ip->ip_len = ntohs(ip->ip_len); ip->ip_off = ntohs(ip->ip_off); #endif - fin->fin_plen = ip->ip_len; } if (fr_makefrip(hlen, ip, fin) == -1) { @@ -2439,8 +2533,7 @@ int out; } #ifdef USE_INET6 else if (v == 6) { - ip6 = (ip6_t *)ip; - if (ip6->ip6_hlim < fr_minttl) { + if (((ip6_t *)ip)->ip6_hlim < fr_minttl) { ATOMIC_INCL(frstats[0].fr_badttl); fin->fin_flx |= FI_LOWTTL; } @@ -2464,8 +2557,7 @@ int out; fr = fr_checkauth(fin, &pass); if (!out) { if (fr_checknatin(fin, &pass) == -1) { - RWLOCK_EXIT(&ipf_mutex); - goto finished; + goto filterdone; } } if (!out) @@ -2507,8 +2599,7 @@ int out; (void) fr_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); @@ -2520,20 +2611,26 @@ int out; } } +filterdone: #ifdef IPFILTER_LOG if ((fr_flags & FF_LOGGING) || (pass & FR_LOGMASK)) { (void) fr_dolog(fin, &pass); } #endif + /* + * The FI_STATE flag is cleared here so that calling fr_checkstate + * 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. + */ if (fin->fin_state != NULL) { - fr_statederef(fin, (ipstate_t **)&fin->fin_state); - fin->fin_state = NULL; + fr_statederef((ipstate_t **)&fin->fin_state); + fin->fin_flx ^= FI_STATE; } if (fin->fin_nat != NULL) { fr_natderef((nat_t **)&fin->fin_nat); - fin->fin_nat = NULL; } /* @@ -2788,6 +2885,7 @@ int len; /* ip(I) - pointer to IP header */ /* l4proto(I) - protocol to caclulate checksum for */ /* l4hdr(I) - pointer to layer 4 header */ +/* l3len(I) - length of layer 4 data plus layer 3 header */ /* */ /* Calculates the TCP checksum for the packet held in "m", using the data */ /* in the IP header "ip" to seed it. */ @@ -2796,6 +2894,8 @@ int len; /* and the TCP header. We also assume that data blocks aren't allocated in */ /* odd sizes. */ /* */ +/* For IPv6, l3len excludes extension header size. */ +/* */ /* Expects ip_len to be in host byte order when called. */ /* ------------------------------------------------------------------------ */ u_short fr_cksum(m, ip, l4proto, l4hdr, l3len) @@ -2838,9 +2938,9 @@ void *l4hdr; } else if (IP_V(ip) == 6) { ip6 = (ip6_t *)ip; hlen = sizeof(*ip6); - slen = ntohs(l3len); + slen = l3len - hlen; sum = htons((u_short)l4proto); - sum += slen; + sum += htons(slen); sp = (u_short *)&ip6->ip6_src; sum += *sp++; /* ip6_src */ sum += *sp++; @@ -3026,6 +3126,12 @@ nodata: # endif /* defined(BSD) || defined(sun) */ # endif /* MENTAT */ #else /* _KERNEL */ + /* + * Add up IP Header portion + */ + if (sp != (u_short *)l4hdr) + sp = (u_short *)l4hdr; + for (; slen > 1; slen -= 2) sum += *sp++; if (slen) @@ -3071,7 +3177,7 @@ nodata: * SUCH DAMAGE. * * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 - * $Id: fil.c,v 2.243.2.78 2006/03/29 11:19:54 darrenr Exp $ + * $Id: fil.c,v 2.243.2.109 2007/05/31 12:27:33 darrenr Exp $ */ /* * Copy data from an mbuf chain starting "off" bytes from the beginning, @@ -3662,13 +3768,15 @@ void *ifp; 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_srcsubtype, + &fr->fr_slookup, &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_dstsubtype, + &fr->fr_dlookup, &fr->fr_dstfunc); } #endif @@ -3740,17 +3848,19 @@ 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, (caddr_t)&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) + error = EFAULT; + return error; } @@ -3770,11 +3880,13 @@ void *src, *dst; size_t size; { caddr_t ca; - int err; + int error; bcopy(dst, (caddr_t)&ca, sizeof(ca)); - err = COPYOUT(src, ca, size); - return err; + error = COPYOUT(src, ca, size); + if (error != 0) + error = EFAULT; + return error; } #endif @@ -3950,7 +4062,8 @@ int rev; /* 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 */ +/* subtype(I) - whether the info below contains number/name */ +/* info(I) - pointer to name/number of the lookup data */ /* funcptr(IO) - pointer to pointer for storing IP address */ /* searching function. */ /* */ @@ -3959,20 +4072,35 @@ int rev; /* 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; +static void *fr_resolvelookup(type, subtype, info, funcptr) +u_int type, subtype; +i6addr_t *info; lookupfunc_t *funcptr; { - char name[FR_GROUPLEN]; + char label[FR_GROUPLEN], *name; iphtable_t *iph; ip_pool_t *ipo; void *ptr; + if (subtype == 0) { #if defined(SNPRINTF) && defined(_KERNEL) - SNPRINTF(name, sizeof(name), "%u", number); + SNPRINTF(label, sizeof(label), "%u", info->iplookupnum); #else - (void) sprintf(name, "%u", number); + (void) sprintf(label, "%u", info->iplookupnum); #endif + name = label; + } else if (subtype == 1) { + /* + * Because iplookupname is currently only a 12 character + * string and FR_GROUPLEN is 16, copy all of it into the + * label buffer and add on a NULL at the end. + */ + strncpy(label, info->iplookupname, sizeof(info->iplookupname)); + label[sizeof(info->iplookupname)] = '\0'; + name = label; + } else { + return NULL; + } READ_ENTER(&ip_poolrw); @@ -4144,16 +4272,6 @@ caddr_t data; fprev = &fg->fg_start; } - 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; - } - /* * Copy in extra data for the rule. */ @@ -4163,6 +4281,8 @@ caddr_t data; if (!ptr) return ENOMEM; error = COPYIN(uptr, ptr, fp->fr_dsize); + if (error != 0) + error = EFAULT; } else { ptr = uptr; error = 0; @@ -4221,8 +4341,11 @@ caddr_t data; #ifdef IPFILTER_LOOKUP case FRI_LOOKUP : fp->fr_srcptr = fr_resolvelookup(fp->fr_srctype, - fp->fr_srcnum, + fp->fr_srcsubtype, + &fp->fr_slookup, &fp->fr_srcfunc); + if (fp->fr_srcptr == NULL) + return ESRCH; break; #endif default : @@ -4246,8 +4369,11 @@ caddr_t data; #ifdef IPFILTER_LOOKUP case FRI_LOOKUP : fp->fr_dstptr = fr_resolvelookup(fp->fr_dsttype, - fp->fr_dstnum, + fp->fr_dstsubtype, + &fp->fr_dlookup, &fp->fr_dstfunc); + if (fp->fr_dstptr == NULL) + return ESRCH; break; #endif default : @@ -4288,6 +4414,20 @@ caddr_t data; fp->fr_cksum += *p; WRITE_ENTER(&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; + } bzero((char *)frcache, sizeof(frcache)); for (; (f = *ftail) != NULL; ftail = &f->fr_next) { @@ -4331,6 +4471,8 @@ caddr_t data; if ((f->fr_dsize != 0) && (uptr != NULL)) error = COPYOUT(f->fr_data, uptr, f->fr_dsize); + if (error != 0) + error = EFAULT; if (error == 0) { f->fr_hits = 0; f->fr_bytes = 0; @@ -4427,7 +4569,7 @@ caddr_t data; fr_fixskip(ftail, f, -1); *ftail = f->fr_next; f->fr_next = NULL; - (void)fr_derefrule(&f); + (void) fr_derefrule(&f); } } else { /* @@ -4576,7 +4718,7 @@ void *data; #if !defined(_KERNEL) || (!defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__FreeBSD__)) || \ - (defined(__FreeBSD__) && (__FreeBSD_version < 490000)) || \ + (defined(__FreeBSD__) && (__FreeBSD_version < 501000)) || \ (defined(__NetBSD__) && (__NetBSD_Version__ < 105000000)) || \ (defined(__OpenBSD__) && (OpenBSD < 200006)) /* @@ -4641,6 +4783,7 @@ frentry_t **frp; frentry_t *fr; fr = *frp; + *frp = NULL; MUTEX_ENTER(&fr->fr_lock); fr->fr_ref--; @@ -4666,7 +4809,6 @@ frentry_t **frp; } else { MUTEX_EXIT(&fr->fr_lock); } - *frp = NULL; return -1; } @@ -5196,55 +5338,47 @@ char *buffer; /* 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. */ /* ------------------------------------------------------------------------ */ -int fr_ioctlswitch(unit, data, cmd, mode) -int unit, mode; +int fr_ioctlswitch(unit, data, cmd, mode, uid, ctx) +int unit, mode, uid; ioctlcmd_t cmd; -void *data; +void *data, *ctx; { int error = 0; switch (unit) { case IPL_LOGIPF : - error = -1; + error = fr_ipf_ioctl(data, cmd, mode, uid, ctx); break; case IPL_LOGNAT : if (fr_running > 0) - error = fr_nat_ioctl(data, cmd, mode); + error = fr_nat_ioctl(data, cmd, mode, uid, ctx); else error = EIO; break; case IPL_LOGSTATE : if (fr_running > 0) - error = fr_state_ioctl(data, cmd, mode); + error = fr_state_ioctl(data, cmd, mode, uid, ctx); else 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 (fr_running > 0) + error = fr_auth_ioctl(data, cmd, mode, uid, ctx); + else error = EIO; break; case IPL_LOGSYNC : #ifdef IPFILTER_SYNC if (fr_running > 0) - error = fr_sync_ioctl(data, cmd, mode); + error = fr_sync_ioctl(data, cmd, mode, uid, ctx); else #endif error = EIO; @@ -5252,7 +5386,7 @@ void *data; case IPL_LOGSCAN : #ifdef IPFILTER_SCAN if (fr_running > 0) - error = fr_scan_ioctl(data, cmd, mode); + error = fr_scan_ioctl(data, cmd, mode, uid, ctx); else #endif error = EIO; @@ -5260,7 +5394,7 @@ void *data; case IPL_LOGLOOKUP : #ifdef IPFILTER_LOOKUP if (fr_running > 0) - error = ip_lookup_ioctl(data, cmd, mode); + error = ip_lookup_ioctl(data, cmd, mode, uid, ctx); else #endif error = EIO; @@ -5278,9 +5412,7 @@ void *data; * This array defines the expected size of objects coming into the kernel * for the various recognised object types. */ -#define NUM_OBJ_TYPES 14 - -static int fr_objbytes[NUM_OBJ_TYPES][2] = { +static int fr_objbytes[IPFOBJ_COUNT][2] = { { 1, sizeof(struct frentry) }, /* frentry */ { 0, sizeof(struct friostat) }, { 0, sizeof(struct fr_info) }, @@ -5294,7 +5426,13 @@ static int fr_objbytes[NUM_OBJ_TYPES][2] = { { 1, sizeof(struct ipstate) }, /* ipstate */ { 0, sizeof(struct ips_stat) }, { 0, sizeof(struct frauth) }, - { 0, sizeof(struct ipftune) } + { 0, sizeof(struct ipftune) }, + { 0, sizeof(struct nat) }, /* nat_t */ + { 0, sizeof(struct ipfruleiter) }, + { 0, sizeof(struct ipfgeniter) }, + { 0, sizeof(struct ipftable) }, + { 0, sizeof(struct ipflookupiter) }, + { 0, sizeof(struct ipftq) * IPF_TCP_NSTATES }, }; @@ -5317,7 +5455,7 @@ int type; ipfobj_t obj; int error = 0; - if ((type < 0) || (type > NUM_OBJ_TYPES-1)) + if ((type < 0) || (type >= IPFOBJ_COUNT)) return EINVAL; BCOPYIN((caddr_t)data, (caddr_t)&obj, sizeof(obj)); @@ -5329,8 +5467,9 @@ int type; if ((fr_objbytes[type][0] & 1) != 0) { if (obj.ipfo_size < fr_objbytes[type][1]) return EINVAL; - } else if (obj.ipfo_size != fr_objbytes[type][1]) + } else if (obj.ipfo_size != fr_objbytes[type][1]) { return EINVAL; + } #else if (obj.ipfo_rev != IPFILTER_VERSION) /* XXX compatibility hook here */ @@ -5351,6 +5490,8 @@ int type; error = COPYIN((caddr_t)obj.ipfo_ptr, (caddr_t)ptr, obj.ipfo_size); } + if (error != 0) + error = EFAULT; return error; } @@ -5377,7 +5518,7 @@ int type, sz; ipfobj_t obj; int error; - if ((type < 0) || (type > NUM_OBJ_TYPES-1)) + if ((type < 0) || (type >= IPFOBJ_COUNT)) return EINVAL; if (((fr_objbytes[type][0] & 1) == 0) || (sz < fr_objbytes[type][1])) return EINVAL; @@ -5400,6 +5541,8 @@ int type, sz; #endif error = COPYIN((caddr_t)obj.ipfo_ptr, (caddr_t)ptr, sz); + if (error != 0) + error = EFAULT; return error; } @@ -5426,7 +5569,7 @@ int type, sz; ipfobj_t obj; int error; - if ((type < 0) || (type > NUM_OBJ_TYPES-1) || + if ((type < 0) || (type > IPFOBJ_COUNT) || ((fr_objbytes[type][0] & 1) == 0) || (sz < fr_objbytes[type][1])) return EINVAL; @@ -5449,6 +5592,8 @@ int type, sz; #endif error = COPYOUT((caddr_t)ptr, (caddr_t)obj.ipfo_ptr, sz); + if (error != 0) + error = EFAULT; return error; } @@ -5472,7 +5617,7 @@ int type; ipfobj_t obj; int error; - if ((type < 0) || (type > NUM_OBJ_TYPES-1)) + if ((type < 0) || (type > IPFOBJ_COUNT)) return EINVAL; BCOPYIN((caddr_t)data, (caddr_t)&obj, sizeof(obj)); @@ -5500,6 +5645,8 @@ int type; #endif error = COPYOUT((caddr_t)ptr, (caddr_t)obj.ipfo_ptr, obj.ipfo_size); + if (error != 0) + error = EFAULT; return error; } @@ -5570,9 +5717,11 @@ fr_info_t *fin; if (csump != NULL) hdrsum = *csump; - if (dosum) + if (dosum) { sum = fr_cksum(fin->fin_m, fin->fin_ip, - fin->fin_p, fin->fin_dp, fin->fin_plen); + fin->fin_p, fin->fin_dp, + fin->fin_dlen + fin->fin_hlen); + } #if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) && defined(ICK_VALID) } #endif @@ -5773,100 +5922,104 @@ fr_info_t *fin; ipftuneable_t ipf_tuneables[] = { /* filtering */ { { &fr_flags }, "fr_flags", 0, 0xffffffff, - sizeof(fr_flags), 0 }, + sizeof(fr_flags), 0, NULL }, { { &fr_active }, "fr_active", 0, 0, - sizeof(fr_active), IPFT_RDONLY }, + sizeof(fr_active), IPFT_RDONLY, NULL }, { { &fr_control_forwarding }, "fr_control_forwarding", 0, 1, - sizeof(fr_control_forwarding), 0 }, + sizeof(fr_control_forwarding), 0, NULL }, { { &fr_update_ipid }, "fr_update_ipid", 0, 1, - sizeof(fr_update_ipid), 0 }, + sizeof(fr_update_ipid), 0, NULL }, { { &fr_chksrc }, "fr_chksrc", 0, 1, - sizeof(fr_chksrc), 0 }, + sizeof(fr_chksrc), 0, NULL }, { { &fr_minttl }, "fr_minttl", 0, 1, - sizeof(fr_minttl), 0 }, + sizeof(fr_minttl), 0, NULL }, { { &fr_icmpminfragmtu }, "fr_icmpminfragmtu", 0, 1, - sizeof(fr_icmpminfragmtu), 0 }, + sizeof(fr_icmpminfragmtu), 0, NULL }, { { &fr_pass }, "fr_pass", 0, 0xffffffff, - sizeof(fr_pass), 0 }, + sizeof(fr_pass), 0, NULL }, /* state */ { { &fr_tcpidletimeout }, "fr_tcpidletimeout", 1, 0x7fffffff, - sizeof(fr_tcpidletimeout), IPFT_WRDISABLED }, + sizeof(fr_tcpidletimeout), IPFT_WRDISABLED, NULL }, { { &fr_tcpclosewait }, "fr_tcpclosewait", 1, 0x7fffffff, - sizeof(fr_tcpclosewait), IPFT_WRDISABLED }, + sizeof(fr_tcpclosewait), IPFT_WRDISABLED, NULL }, { { &fr_tcplastack }, "fr_tcplastack", 1, 0x7fffffff, - sizeof(fr_tcplastack), IPFT_WRDISABLED }, + sizeof(fr_tcplastack), IPFT_WRDISABLED, NULL }, { { &fr_tcptimeout }, "fr_tcptimeout", 1, 0x7fffffff, - sizeof(fr_tcptimeout), IPFT_WRDISABLED }, + sizeof(fr_tcptimeout), IPFT_WRDISABLED, NULL }, { { &fr_tcpclosed }, "fr_tcpclosed", 1, 0x7fffffff, - sizeof(fr_tcpclosed), IPFT_WRDISABLED }, + sizeof(fr_tcpclosed), IPFT_WRDISABLED, NULL }, { { &fr_tcphalfclosed }, "fr_tcphalfclosed", 1, 0x7fffffff, - sizeof(fr_tcphalfclosed), IPFT_WRDISABLED }, + sizeof(fr_tcphalfclosed), IPFT_WRDISABLED, NULL }, { { &fr_udptimeout }, "fr_udptimeout", 1, 0x7fffffff, - sizeof(fr_udptimeout), IPFT_WRDISABLED }, + sizeof(fr_udptimeout), IPFT_WRDISABLED, NULL }, { { &fr_udpacktimeout }, "fr_udpacktimeout", 1, 0x7fffffff, - sizeof(fr_udpacktimeout), IPFT_WRDISABLED }, + sizeof(fr_udpacktimeout), IPFT_WRDISABLED, NULL }, { { &fr_icmptimeout }, "fr_icmptimeout", 1, 0x7fffffff, - sizeof(fr_icmptimeout), IPFT_WRDISABLED }, + sizeof(fr_icmptimeout), IPFT_WRDISABLED, NULL }, { { &fr_icmpacktimeout }, "fr_icmpacktimeout", 1, 0x7fffffff, - sizeof(fr_icmpacktimeout), IPFT_WRDISABLED }, + sizeof(fr_icmpacktimeout), IPFT_WRDISABLED, NULL }, { { &fr_iptimeout }, "fr_iptimeout", 1, 0x7fffffff, - sizeof(fr_iptimeout), IPFT_WRDISABLED }, + sizeof(fr_iptimeout), IPFT_WRDISABLED, NULL }, { { &fr_statemax }, "fr_statemax", 1, 0x7fffffff, - sizeof(fr_statemax), 0 }, + sizeof(fr_statemax), 0, NULL }, { { &fr_statesize }, "fr_statesize", 1, 0x7fffffff, - sizeof(fr_statesize), IPFT_WRDISABLED }, + sizeof(fr_statesize), IPFT_WRDISABLED, NULL }, { { &fr_state_lock }, "fr_state_lock", 0, 1, - sizeof(fr_state_lock), IPFT_RDONLY }, + sizeof(fr_state_lock), IPFT_RDONLY, NULL }, { { &fr_state_maxbucket }, "fr_state_maxbucket", 1, 0x7fffffff, - sizeof(fr_state_maxbucket), IPFT_WRDISABLED }, + sizeof(fr_state_maxbucket), IPFT_WRDISABLED, NULL }, { { &fr_state_maxbucket_reset }, "fr_state_maxbucket_reset", 0, 1, - sizeof(fr_state_maxbucket_reset), IPFT_WRDISABLED }, + sizeof(fr_state_maxbucket_reset), IPFT_WRDISABLED, NULL }, { { &ipstate_logging }, "ipstate_logging", 0, 1, - sizeof(ipstate_logging), 0 }, + sizeof(ipstate_logging), 0, NULL }, /* nat */ { { &fr_nat_lock }, "fr_nat_lock", 0, 1, - sizeof(fr_nat_lock), IPFT_RDONLY }, + sizeof(fr_nat_lock), IPFT_RDONLY, NULL }, { { &ipf_nattable_sz }, "ipf_nattable_sz", 1, 0x7fffffff, - sizeof(ipf_nattable_sz), IPFT_WRDISABLED }, + sizeof(ipf_nattable_sz), IPFT_WRDISABLED, NULL }, { { &ipf_nattable_max }, "ipf_nattable_max", 1, 0x7fffffff, - sizeof(ipf_nattable_max), 0 }, + sizeof(ipf_nattable_max), 0, NULL }, { { &ipf_natrules_sz }, "ipf_natrules_sz", 1, 0x7fffffff, - sizeof(ipf_natrules_sz), IPFT_WRDISABLED }, + sizeof(ipf_natrules_sz), IPFT_WRDISABLED, NULL }, { { &ipf_rdrrules_sz }, "ipf_rdrrules_sz", 1, 0x7fffffff, - sizeof(ipf_rdrrules_sz), IPFT_WRDISABLED }, + sizeof(ipf_rdrrules_sz), IPFT_WRDISABLED, NULL }, { { &ipf_hostmap_sz }, "ipf_hostmap_sz", 1, 0x7fffffff, - sizeof(ipf_hostmap_sz), IPFT_WRDISABLED }, + sizeof(ipf_hostmap_sz), IPFT_WRDISABLED, NULL }, { { &fr_nat_maxbucket }, "fr_nat_maxbucket", 1, 0x7fffffff, - sizeof(fr_nat_maxbucket), IPFT_WRDISABLED }, + sizeof(fr_nat_maxbucket), IPFT_WRDISABLED, NULL }, { { &fr_nat_maxbucket_reset }, "fr_nat_maxbucket_reset", 0, 1, - sizeof(fr_nat_maxbucket_reset), IPFT_WRDISABLED }, + sizeof(fr_nat_maxbucket_reset), IPFT_WRDISABLED, NULL }, { { &nat_logging }, "nat_logging", 0, 1, - sizeof(nat_logging), 0 }, + sizeof(nat_logging), 0, NULL }, { { &fr_defnatage }, "fr_defnatage", 1, 0x7fffffff, - sizeof(fr_defnatage), IPFT_WRDISABLED }, + sizeof(fr_defnatage), IPFT_WRDISABLED, NULL }, { { &fr_defnatipage }, "fr_defnatipage", 1, 0x7fffffff, - sizeof(fr_defnatipage), IPFT_WRDISABLED }, + sizeof(fr_defnatipage), IPFT_WRDISABLED, NULL }, { { &fr_defnaticmpage }, "fr_defnaticmpage", 1, 0x7fffffff, - sizeof(fr_defnaticmpage), IPFT_WRDISABLED }, + sizeof(fr_defnaticmpage), IPFT_WRDISABLED, NULL }, + { { &fr_nat_doflush }, "fr_nat_doflush", 0, 1, + sizeof(fr_nat_doflush), 0, NULL }, + /* proxy */ + { { &ipf_proxy_debug }, "ipf_proxy_debug", 0, 10, + sizeof(ipf_proxy_debug), 0, 0 }, /* frag */ { { &ipfr_size }, "ipfr_size", 1, 0x7fffffff, - sizeof(ipfr_size), IPFT_WRDISABLED }, + sizeof(ipfr_size), IPFT_WRDISABLED, NULL }, { { &fr_ipfrttl }, "fr_ipfrttl", 1, 0x7fffffff, - sizeof(fr_ipfrttl), IPFT_WRDISABLED }, + sizeof(fr_ipfrttl), IPFT_WRDISABLED, NULL }, #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 }, + sizeof(ipl_suppress), 0, NULL }, { { &ipl_logmax }, "ipl_logmax", 0, 0x7fffffff, - sizeof(ipl_logmax), IPFT_WRDISABLED }, + sizeof(ipl_logmax), IPFT_WRDISABLED, NULL }, { { &ipl_logall }, "ipl_logall", 0, 1, - sizeof(ipl_logall), 0 }, + sizeof(ipl_logall), 0, NULL }, { { &ipl_logsize }, "ipl_logsize", 0, 0x80000, - sizeof(ipl_logsize), 0 }, + sizeof(ipl_logsize), 0, NULL }, #endif - { { NULL }, NULL, 0, 0 } + { { NULL }, NULL, 0, 0, + 0, 0, NULL } }; static ipftuneable_t *ipf_tunelist = NULL; @@ -6177,6 +6330,8 @@ int fr_initialise() { int i; + bzero(&frstats, sizeof(frstats)); + #ifdef IPFILTER_LOG i = fr_loginit(); if (i < 0) @@ -6285,7 +6440,7 @@ caddr_t data; return EFAULT; WRITE_ENTER(&ipf_mutex); - bzero((char *)frstats, sizeof(*frstats) * 2); + bzero(&frstats, sizeof(frstats)); RWLOCK_EXIT(&ipf_mutex); return 0; @@ -6364,3 +6519,800 @@ int v; nic = (void *)-1; return nic; } + + +ipftoken_t *ipftokenhead = NULL, **ipftokentail = &ipftokenhead; + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_expiretokens */ +/* Returns: None. */ +/* Parameters: None. */ +/* */ +/* 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_expiretokens() +{ + ipftoken_t *it; + void *data; + + WRITE_ENTER(&ipf_tokens); + while ((it = ipftokenhead) != NULL) { + if (it->ipt_die > fr_ticks) + break; + + data = it->ipt_data; + + ipf_freetoken(it); + } + RWLOCK_EXIT(&ipf_tokens); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_deltoken */ +/* Returns: int - 0 = success, else error */ +/* Parameters: 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_freetoken() to remove it from the list. */ +/* ------------------------------------------------------------------------ */ +int ipf_deltoken(type, uid, ptr) +int type, uid; +void *ptr; +{ + ipftoken_t *it; + int error = ESRCH; + + WRITE_ENTER(&ipf_tokens); + for (it = ipftokenhead; it != NULL; it = it->ipt_next) + if (ptr == it->ipt_ctx && type == it->ipt_type && + uid == it->ipt_uid) { + ipf_freetoken(it); + error = 0; + break; + } + RWLOCK_EXIT(&ipf_tokens); + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_findtoken */ +/* Returns: ipftoken_t * - NULL if no memory, else pointer to token */ +/* Parameters: 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. */ +/* */ +/* NOTE: It is by design that this function returns holding a read lock on */ +/* ipf_tokens. Callers must make sure they release it! */ +/* ------------------------------------------------------------------------ */ +ipftoken_t *ipf_findtoken(type, uid, ptr) +int type, uid; +void *ptr; +{ + ipftoken_t *it, *new; + + KMALLOC(new, ipftoken_t *); + + WRITE_ENTER(&ipf_tokens); + for (it = ipftokenhead; it != NULL; it = it->ipt_next) { + if (it->ipt_alive == 0) + continue; + if (ptr == it->ipt_ctx && type == it->ipt_type && + uid == it->ipt_uid) + break; + } + + if (it == NULL) { + it = new; + new = NULL; + if (it == NULL) + return NULL; + it->ipt_data = NULL; + it->ipt_ctx = ptr; + it->ipt_uid = uid; + it->ipt_type = type; + it->ipt_next = NULL; + it->ipt_alive = 1; + } else { + if (new != NULL) { + KFREE(new); + new = NULL; + } + + ipf_unlinktoken(it); + } + it->ipt_pnext = ipftokentail; + *ipftokentail = it; + ipftokentail = &it->ipt_next; + it->ipt_next = NULL; + + it->ipt_die = fr_ticks + 2; + + MUTEX_DOWNGRADE(&ipf_tokens); + + return it; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_unlinktoken */ +/* Returns: None. */ +/* Parameters: token(I) - pointer to token structure */ +/* */ +/* 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_unlinktoken(token) +ipftoken_t *token; +{ + + if (ipftokentail == &token->ipt_next) + ipftokentail = token->ipt_pnext; + + *token->ipt_pnext = token->ipt_next; + if (token->ipt_next != NULL) + token->ipt_next->ipt_pnext = token->ipt_pnext; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_freetoken */ +/* Returns: None. */ +/* Parameters: token(I) - pointer to token structure */ +/* */ +/* This function unlinks a token from the linked list and on the path to */ +/* free'ing the data, it calls the dereference function that is associated */ +/* with the type of data pointed to by the token as it is considered to */ +/* hold a reference to it. */ +/* ------------------------------------------------------------------------ */ +void ipf_freetoken(token) +ipftoken_t *token; +{ + void *data, **datap; + + ipf_unlinktoken(token); + + data = token->ipt_data; + datap = &data; + + if ((data != NULL) && (data != (void *)-1)) { + switch (token->ipt_type) + { + case IPFGENITER_IPF : + (void) fr_derefrule((frentry_t **)datap); + break; + case IPFGENITER_IPNAT : + WRITE_ENTER(&ipf_nat); + fr_ipnatderef((ipnat_t **)datap); + RWLOCK_EXIT(&ipf_nat); + break; + case IPFGENITER_NAT : + fr_natderef((nat_t **)datap); + break; + case IPFGENITER_STATE : + fr_statederef((ipstate_t **)datap); + break; + case IPFGENITER_FRAG : +#ifdef USE_MUTEXES + fr_fragderef((ipfr_t **)datap, &ipf_frag); +#else + fr_fragderef((ipfr_t **)datap); +#endif + break; + case IPFGENITER_NATFRAG : +#ifdef USE_MUTEXES + fr_fragderef((ipfr_t **)datap, &ipf_natfrag); +#else + fr_fragderef((ipfr_t **)datap); +#endif + break; + case IPFGENITER_HOSTMAP : + fr_hostmapdel((hostmap_t **)datap); + break; + default : +#ifdef IPFILTER_LOOKUP + ip_lookup_iterderef(token->ipt_type, data); +#endif + break; + } + } + + KFREE(token); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_getnextrule */ +/* Returns: int - 0 = success, else error */ +/* Parameters: 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(ipftoken_t *t, void *ptr) +{ + frentry_t *fr, *next, zero; + int error, count, out; + ipfruleiter_t it; + frgroup_t *fg; + char *dst; + + if (t == NULL || ptr == NULL) + return EFAULT; + error = fr_inobj(ptr, &it, IPFOBJ_IPFITER); + if (error != 0) + return error; + if ((it.iri_inout < 0) || (it.iri_inout > 3)) + return EINVAL; + if ((it.iri_active != 0) && (it.iri_active != 1)) + return EINVAL; + if (it.iri_nrules == 0) + return ENOSPC; + if (it.iri_rule == NULL) + return EFAULT; + + out = it.iri_inout & F_OUT; + fr = t->ipt_data; + READ_ENTER(&ipf_mutex); + if (fr == NULL) { + if (*it.iri_group == '\0') { + if ((it.iri_inout & F_ACIN) != 0) { + if (it.iri_v == 4) + next = ipacct[out][it.iri_active]; + else + next = ipacct6[out][it.iri_active]; + } else { + if (it.iri_v == 4) + next = ipfilter[out][it.iri_active]; + else + next = ipfilter6[out][it.iri_active]; + } + } else { + fg = fr_findgroup(it.iri_group, IPL_LOGIPF, + it.iri_active, NULL); + if (fg != NULL) + next = fg->fg_start; + else + next = NULL; + } + } else { + next = fr->fr_next; + } + + dst = (char *)it.iri_rule; + /* + * The ipfruleiter may ask for more than 1 rule at a time to be + * copied out, so long as that many exist in the list to start with! + */ + for (count = it.iri_nrules; count > 0; count--) { + if (next != NULL) { + MUTEX_ENTER(&next->fr_lock); + next->fr_ref++; + MUTEX_EXIT(&next->fr_lock); + t->ipt_data = next; + } else { + bzero(&zero, sizeof(zero)); + next = &zero; + ipf_freetoken(t); + fr = NULL; + t = NULL; + count = 1; + } + RWLOCK_EXIT(&ipf_mutex); + + if (fr != NULL) { + (void) fr_derefrule(&fr); + } + + error = COPYOUT(next, dst, sizeof(*next)); + if (error != 0) + return EFAULT; + + if (next->fr_data != NULL) { + dst += sizeof(*next); + error = COPYOUT(next->fr_data, dst, next->fr_dsize); + if (error != 0) + error = EFAULT; + else + dst += next->fr_dsize; + } + + if ((count == 1) || (next->fr_next == NULL) || (error != 0)) + break; + + READ_ENTER(&ipf_mutex); + fr = next; + next = fr->fr_next; + } + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_frruleiter */ +/* Returns: int - 0 = success, else error */ +/* Parameters: 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 fr_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(data, uid, ctx) +void *data, *ctx; +int uid; +{ + ipftoken_t *token; + int error; + + token = ipf_findtoken(IPFGENITER_IPF, uid, ctx); + if (token != NULL) + error = ipf_getnextrule(token, data); + else + error = EFAULT; + RWLOCK_EXIT(&ipf_tokens); + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_geniter */ +/* Returns: int - 0 = success, else error */ +/* Parameters: token(I) - pointer to ipftoken_t structure */ +/* itp(I) - */ +/* */ +/* ------------------------------------------------------------------------ */ +static int ipf_geniter(token, itp) +ipftoken_t *token; +ipfgeniter_t *itp; +{ + int error; + + switch (itp->igi_type) + { + case IPFGENITER_FRAG : +#ifdef USE_MUTEXES + error = fr_nextfrag(token, itp, + &ipfr_list, &ipfr_tail, &ipf_frag); +#else + error = fr_nextfrag(token, itp, &ipfr_list, &ipfr_tail); +#endif + break; + default : + error = EINVAL; + break; + } + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_genericiter */ +/* Returns: int - 0 = success, else error */ +/* Parameters: data(I) - the token type to match */ +/* uid(I) - uid owning the token */ +/* ptr(I) - context pointer for the token */ +/* */ +/* ------------------------------------------------------------------------ */ +int ipf_genericiter(data, uid, ctx) +void *data, *ctx; +int uid; +{ + ipftoken_t *token; + ipfgeniter_t iter; + int error; + + error = fr_inobj(data, &iter, IPFOBJ_GENITER); + if (error != 0) + return error; + + token = ipf_findtoken(iter.igi_type, uid, ctx); + if (token != NULL) { + token->ipt_subtype = iter.igi_type; + error = ipf_geniter(token, &iter); + } else + error = EFAULT; + RWLOCK_EXIT(&ipf_tokens); + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_ipf_ioctl */ +/* Returns: int - 0 = success, else error */ +/* Parameters: 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 fr_ipf_ioctl(data, cmd, mode, uid, ctx) +caddr_t data; +ioctlcmd_t cmd; +int mode, uid; +void *ctx; +{ + friostat_t fio; + int error, tmp; + SPL_INT(s); + + switch (cmd) + { + case SIOCFRENB : + if (!(mode & FWRITE)) + error = EPERM; + else { + error = BCOPYIN((caddr_t)data, (caddr_t)&tmp, + sizeof(tmp)); + if (error != 0) { + error = EFAULT; + break; + } + + RWLOCK_EXIT(&ipf_global); + WRITE_ENTER(&ipf_global); + if (tmp) { + if (fr_running > 0) + error = 0; + else + error = ipfattach(); + if (error == 0) + fr_running = 1; + else + (void) ipfdetach(); + } else { + error = ipfdetach(); + if (error == 0) + fr_running = -1; + } + } + break; + + case SIOCIPFSET : + if (!(mode & FWRITE)) { + error = EPERM; + break; + } + /* FALLTHRU */ + case SIOCIPFGETNEXT : + case SIOCIPFGET : + error = fr_ipftune(cmd, (void *)data); + break; + + case SIOCSETFF : + if (!(mode & FWRITE)) + error = EPERM; + else { + error = BCOPYIN((caddr_t)data, (caddr_t)&fr_flags, + sizeof(fr_flags)); + if (error != 0) + error = EFAULT; + } + break; + + case SIOCGETFF : + error = BCOPYOUT((caddr_t)&fr_flags, (caddr_t)data, + sizeof(fr_flags)); + if (error != 0) + error = EFAULT; + break; + + case SIOCFUNCL : + error = fr_resolvefunc((void *)data); + break; + + case SIOCINAFR : + case SIOCRMAFR : + case SIOCADAFR : + case SIOCZRLST : + if (!(mode & FWRITE)) + error = EPERM; + else + error = frrequest(IPL_LOGIPF, cmd, (caddr_t)data, + fr_active, 1); + break; + + case SIOCINIFR : + case SIOCRMIFR : + case SIOCADIFR : + if (!(mode & FWRITE)) + error = EPERM; + else + error = frrequest(IPL_LOGIPF, cmd, (caddr_t)data, + 1 - fr_active, 1); + break; + + case SIOCSWAPA : + if (!(mode & FWRITE)) + error = EPERM; + else { + WRITE_ENTER(&ipf_mutex); + bzero((char *)frcache, sizeof(frcache[0]) * 2); + error = BCOPYOUT((caddr_t)&fr_active, (caddr_t)data, + sizeof(fr_active)); + if (error != 0) + error = EFAULT; + else + fr_active = 1 - fr_active; + RWLOCK_EXIT(&ipf_mutex); + } + break; + + case SIOCGETFS : + fr_getstat(&fio); + error = fr_outobj((void *)data, &fio, IPFOBJ_IPFSTAT); + break; + + case SIOCFRZST : + if (!(mode & FWRITE)) + error = EPERM; + else + error = fr_zerostats((caddr_t)data); + break; + + case SIOCIPFFL : + if (!(mode & FWRITE)) + error = EPERM; + else { + error = BCOPYIN((caddr_t)data, (caddr_t)&tmp, + sizeof(tmp)); + if (!error) { + tmp = frflush(IPL_LOGIPF, 4, tmp); + error = BCOPYOUT((caddr_t)&tmp, (caddr_t)data, + sizeof(tmp)); + if (error != 0) + error = EFAULT; + } else + error = EFAULT; + } + break; + +#ifdef USE_INET6 + case SIOCIPFL6 : + if (!(mode & FWRITE)) + error = EPERM; + else { + error = BCOPYIN((caddr_t)data, (caddr_t)&tmp, + sizeof(tmp)); + if (!error) { + tmp = frflush(IPL_LOGIPF, 6, tmp); + error = BCOPYOUT((caddr_t)&tmp, (caddr_t)data, + sizeof(tmp)); + if (error != 0) + error = EFAULT; + } else + error = EFAULT; + } + break; +#endif + + case SIOCSTLCK : + error = BCOPYIN((caddr_t)data, (caddr_t)&tmp, sizeof(tmp)); + if (error == 0) { + 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(IPL_LOGIPF); + error = BCOPYOUT((caddr_t)&tmp, (caddr_t)data, + sizeof(tmp)); + if (error) + error = EFAULT; + } + break; +#endif /* IPFILTER_LOG */ + + case SIOCFRSYN : + if (!(mode & FWRITE)) + error = EPERM; + else { + RWLOCK_EXIT(&ipf_global); + WRITE_ENTER(&ipf_global); +#ifdef MENTAT + error = ipfsync(); +#else + frsync(NULL); + error = 0; +#endif + + } + break; + + case SIOCGFRST : + error = fr_outobj((void *)data, fr_fragstats(), + IPFOBJ_FRAGSTAT); + break; + +#ifdef IPFILTER_LOG + case FIONREAD : + tmp = (int)iplused[IPL_LOGIPF]; + + error = BCOPYOUT((caddr_t)&tmp, (caddr_t)data, sizeof(tmp)); + break; +#endif + + case SIOCIPFITER : + SPL_SCHED(s); + error = ipf_frruleiter(data, uid, ctx); + SPL_X(s); + break; + + case SIOCGENITER : + SPL_SCHED(s); + error = ipf_genericiter(data, uid, ctx); + SPL_X(s); + break; + break; + + case SIOCIPFDELTOK : + SPL_SCHED(s); + error = BCOPYIN((caddr_t)data, (caddr_t)&tmp, sizeof(tmp)); + if (error == 0) + error = ipf_deltoken(tmp, uid, ctx); + SPL_X(s); + break; + break; + + default : + error = EINVAL; + break; + } + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ipf_queueflush */ +/* Returns: int - number of entries flushed (0 = none) */ +/* Parameters: 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 is */ +/* to 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 (fr_ticks.) Anything modified in the last 30 seconds */ +/* is not touched. */ +/* touched */ +/* die fr_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 - fr_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 fr_ticks, the further tqe_die will be for */ +/* 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 */ +/* */ +/* 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". The downside */ +/* of the current implementation is that it may return removing just 1 entry*/ +/* every time (pathological case) where it could remove more. */ +/* ------------------------------------------------------------------------ */ +int ipf_queueflush(deletefn, ipfqs, userqs) +ipftq_delete_fn_t deletefn; +ipftq_t *ipfqs, *userqs; +{ + u_long interval, istart, iend; + ipftq_t *ifq, *ifqnext; + ipftqent_t *tqe, *tqn; + int 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 (fr_ticks > IPF_TTLVAL(43200 * 15 / 10)) { + istart = IPF_TTLVAL(86400 * 4); + interval = IPF_TTLVAL(43200); + } else if (fr_ticks > IPF_TTLVAL(1800 * 15 / 10)) { + istart = IPF_TTLVAL(43200); + interval = IPF_TTLVAL(1800); + } else if (fr_ticks > IPF_TTLVAL(30 * 15 / 10)) { + istart = IPF_TTLVAL(1800); + interval = IPF_TTLVAL(30); + } else { + return 0; + } + if (istart > fr_ticks) { + istart = (fr_ticks / interval) * interval; + } + + iend = fr_ticks - interval; + if (istart > iend) + istart = iend - interval; + removed = 0; + + while (removed == 0) { + u_long try; + + try = fr_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)(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)(tqe->tqe_parent) == 0) + removed++; + } + } + + istart -= interval; + 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 >= fr_ticks) + break; + + iend = fr_ticks - interval; + } + } + + return removed; +} diff --git a/sys/contrib/ipfilter/netinet/ip_auth.c b/sys/contrib/ipfilter/netinet/ip_auth.c index 3f82d25..e6d3d50 100644 --- a/sys/contrib/ipfilter/netinet/ip_auth.c +++ b/sys/contrib/ipfilter/netinet/ip_auth.c @@ -146,7 +146,19 @@ frauthent_t *fae_list = NULL; frentry_t *ipauth = NULL, *fr_authlist = NULL; +void fr_authderef __P((frauthent_t **)); +int fr_authgeniter __P((ipftoken_t *, ipfgeniter_t *)); +int fr_authreply __P((char *)); +int fr_authwait __P((char *)); +/* ------------------------------------------------------------------------ */ +/* Function: fr_authinit */ +/* Returns: int - 0 == success, else error */ +/* Parameters: None */ +/* */ +/* Allocate memory and initialise data structures used in handling auth */ +/* rules. */ +/* ------------------------------------------------------------------------ */ int fr_authinit() { KMALLOCS(fr_auth, frauth_t *, fr_authsize * sizeof(*fr_auth)); @@ -176,11 +188,16 @@ int fr_authinit() } -/* - * 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. - */ +/* ------------------------------------------------------------------------ */ +/* Function: fr_checkauth */ +/* 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 *fr_checkauth(fin, passp) fr_info_t *fin; u_32_t *passp; @@ -237,7 +254,12 @@ u_32_t *passp; fr = fra->fra_info.fin_fr; fin->fin_fr = fr; RWLOCK_EXIT(&ipf_auth); + WRITE_ENTER(&ipf_auth); + /* + * fr_authlist 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; @@ -279,11 +301,16 @@ u_32_t *passp; } -/* - * 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. - */ +/* ------------------------------------------------------------------------ */ +/* Function: fr_newauth */ +/* Returns: int - 0 == success, else error */ +/* 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 fr_newauth(m, fin) mb_t *m; fr_info_t *fin; @@ -322,7 +349,10 @@ fr_info_t *fin; fra = fr_auth + i; fra->fra_index = i; - fra->fra_pass = fin->fin_fr->fr_flags; + if (fin->fin_fr != NULL) + fra->fra_pass = fin->fin_fr->fr_flags; + else + fra->fra_pass = 0; fra->fra_age = fr_defaultauthage; bcopy((char *)fin, (char *)&fra->fra_info, sizeof(*fin)); #if !defined(sparc) && !defined(m68k) @@ -360,23 +390,59 @@ fr_info_t *fin; } -int fr_auth_ioctl(data, cmd, mode) +/* ------------------------------------------------------------------------ */ +/* Function: fr_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/ipauth */ +/* ------------------------------------------------------------------------ */ +int fr_auth_ioctl(data, cmd, mode, uid, ctx) caddr_t data; ioctlcmd_t cmd; -int mode; +int mode, uid; +void *ctx; { - frauth_t auth, *au = &auth, *fra; - int i, error = 0, len; - char *t; - mb_t *m; -#if defined(_KERNEL) && !defined(MENTAT) && !defined(linux) && \ - (!defined(__FreeBSD_version) || (__FreeBSD_version < 501000)) - struct ifqueue *ifq; + int error = 0, i; SPL_INT(s); -#endif switch (cmd) { + case SIOCGENITER : + { + ipftoken_t *token; + ipfgeniter_t iter; + + error = fr_inobj(data, &iter, IPFOBJ_GENITER); + if (error != 0) + break; + + SPL_SCHED(s); + token = ipf_findtoken(IPFGENITER_AUTH, uid, ctx); + if (token != NULL) + error = fr_authgeniter(token, &iter); + else + error = ESRCH; + RWLOCK_EXIT(&ipf_tokens); + SPL_X(s); + + break; + } + + case SIOCADAFR : + case SIOCRMAFR : + if (!(mode & FWRITE)) + error = EPERM; + else + error = frrequest(IPL_LOGAUTH, cmd, data, + fr_active, 1); + break; + case SIOCSTLCK : if (!(mode & FWRITE)) { error = EPERM; @@ -396,203 +462,17 @@ int mode; i = fr_authflush(); RWLOCK_EXIT(&ipf_auth); SPL_X(s); - error = copyoutptr((char *)&i, data, sizeof(i)); + error = BCOPYOUT((char *)&i, data, sizeof(i)); + if (error != 0) + error = EFAULT; break; case SIOCAUTHW: -fr_authioctlloop: - error = fr_inobj(data, au, IPFOBJ_FRAUTH); - if (error != 0) - break; - READ_ENTER(&ipf_auth); - if ((fr_authnext != fr_authend) && fr_authpkts[fr_authnext]) { - error = fr_outobj(data, &fr_auth[fr_authnext], - IPFOBJ_FRAUTH); - if (error != 0) - break; - 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; - m = m->m_next; - } - } - 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) - goto fr_authioctlloop; + error = fr_authwait(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; - error = 0; - 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 = ipf_inject(&fra->fra_info); - if (error != 0) { - FREE_MB_T(m); - error = ENOBUFS; - } -# else /* MENTAT */ -# if defined(linux) || defined(AIX) -# else -# if (defined(_BSDI_VERSION) && _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 = ipf_inject(&fra->fra_info); - if (error != 0) { - FREE_MB_T(m); - error = ENOBUFS; - } -# else /* MENTAT */ -# if defined(linux) || defined(AIX) -# 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; - /* - * 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 /* _KERNEL */ - SPL_X(s); + error = fr_authreply(data); break; default : @@ -603,9 +483,13 @@ fr_authioctlloop: } -/* - * Free all network buffer memory used to keep saved packets. - */ +/* ------------------------------------------------------------------------ */ +/* Function: fr_authunload */ +/* Returns: None */ +/* Parameters: None */ +/* */ +/* Free all network buffer memory used to keep saved packets. */ +/* ------------------------------------------------------------------------ */ void fr_authunload() { register int i; @@ -659,17 +543,21 @@ void fr_authunload() } -/* - * Slowly expire held auth records. Timeouts are set - * in expectation of this being called twice per second. - */ +/* ------------------------------------------------------------------------ */ +/* Function: fr_authexpire */ +/* Returns: None */ +/* Parameters: None */ +/* */ +/* 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; + frauthent_t *fae, **faep; + frentry_t *fr, **frp; + frauth_t *fra; mb_t *m; + int i; SPL_INT(s); if (fr_auth_lock) @@ -688,11 +576,13 @@ void fr_authexpire() } } + /* + * Expire pre-auth rules + */ for (faep = &fae_list; ((fae = *faep) != NULL); ) { fae->fae_age--; if (fae->fae_age == 0) { - *faep = fae->fae_next; - KFREE(fae); + fr_authderef(&fae); fr_authstats.fas_expire++; } else faep = &fae->fae_next; @@ -713,6 +603,15 @@ void fr_authexpire() SPL_X(s); } + +/* ------------------------------------------------------------------------ */ +/* Function: fr_preauthcmd */ +/* 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 fr_preauthcmd(cmd, fr, frptr) ioctlcmd_t cmd; frentry_t *fr, **frptr; @@ -723,7 +622,7 @@ frentry_t *fr, **frptr; if ((cmd != SIOCADAFR) && (cmd != SIOCRMAFR)) return EIO; - + for (faep = &fae_list; ((fae = *faep) != NULL); ) { if (&fae->fae_fr == fr) break; @@ -757,6 +656,7 @@ frentry_t *fr, **frptr; fae->fae_age = fr_defaultauthage; 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; @@ -771,11 +671,18 @@ frentry_t *fr, **frptr; } -/* - * Flush held packets. - * Must already be properly SPL'ed and Locked on &ipf_auth. - * - */ +/* ------------------------------------------------------------------------ */ +/* Function: fr_authflush */ +/* Returns: int - number of auth entries flushed */ +/* Parameters: None */ +/* Locks: WRITE(ipf_auth) */ +/* */ +/* This function flushs the fr_authpkts 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. */ +/* ------------------------------------------------------------------------ */ int fr_authflush() { register int i, num_flushed; @@ -807,7 +714,339 @@ int fr_authflush() } +/* ------------------------------------------------------------------------ */ +/* Function: fr_auth_waiting */ +/* Returns: int - number of packets in the auth queue */ +/* Parameters: None */ +/* */ +/* Returns the numbers of packets queued up, waiting to be processed with */ +/* a pair of SIOCAUTHW and SIOCAUTHR calls. */ +/* ------------------------------------------------------------------------ */ int fr_auth_waiting() { return (fr_authnext != fr_authend) && fr_authpkts[fr_authnext]; } + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_authgeniter */ +/* Returns: int - 0 == success, else error */ +/* Parameters: token(I) - pointer to ipftoken structure */ +/* itp(I) - pointer to ipfgeniter structure */ +/* */ +/* ------------------------------------------------------------------------ */ +int fr_authgeniter(token, itp) +ipftoken_t *token; +ipfgeniter_t *itp; +{ + frauthent_t *fae, *next, zero; + int error; + + if (itp->igi_data == NULL) + return EFAULT; + + if (itp->igi_type != IPFGENITER_AUTH) + return EINVAL; + + fae = token->ipt_data; + READ_ENTER(&ipf_auth); + if (fae == NULL) { + next = fae_list; + } else { + next = fae->fae_next; + } + + if (next != NULL) { + /* + * If we find an auth entry to use, bump its reference count + * so that it can be used for is_next when we come back. + */ + ATOMIC_INC(next->fae_ref); + if (next->fae_next == NULL) { + ipf_freetoken(token); + token = NULL; + } else { + token->ipt_data = next; + } + } else { + bzero(&zero, sizeof(zero)); + next = &zero; + } + RWLOCK_EXIT(&ipf_auth); + + /* + * If we had a prior pointer to an auth entry, release it. + */ + if (fae != NULL) { + WRITE_ENTER(&ipf_auth); + fr_authderef(&fae); + RWLOCK_EXIT(&ipf_auth); + } + + /* + * This should arguably be via fr_outobj() so that the auth + * structure can (if required) be massaged going out. + */ + error = COPYOUT(next, itp->igi_data, sizeof(*next)); + if (error != 0) + error = EFAULT; + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_authderef */ +/* Returns: None */ +/* Parameters: faep(IO) - pointer to caller's frauthent_t pointer */ +/* Locks: WRITE(ipf_auth) */ +/* */ +/* 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. */ +/* ------------------------------------------------------------------------ */ +void fr_authderef(faep) +frauthent_t **faep; +{ + frauthent_t *fae; + + fae = *faep; + *faep = NULL; + + fae->fae_ref--; + if (fae->fae_ref == 0) { + KFREE(fae); + } +} + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_authwait */ +/* 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 (fr_authpkts) then we go to */ +/* sleep. */ +/* ------------------------------------------------------------------------ */ +int fr_authwait(data) +char *data; +{ + frauth_t auth, *au = &auth; + int error, len, i; + mb_t *m; + char *t; +#if defined(_KERNEL) && !defined(MENTAT) && !defined(linux) && \ + (!defined(__FreeBSD_version) || (__FreeBSD_version < 501000)) + SPL_INT(s); +#endif + +fr_authioctlloop: + error = fr_inobj(data, 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. + */ + READ_ENTER(&ipf_auth); + + /* + * If fr_authnext is not equal to fr_authend it will be because there + * is a packet waiting to be delt with in the fr_authpkts array. We + * copy as much of that out to user space as requested. + */ + if ((fr_authnext != fr_authend) && fr_authpkts[fr_authnext]) { + error = fr_outobj(data, &fr_auth[fr_authnext], IPFOBJ_FRAUTH); + if (error != 0) + 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 = 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) + return error; + m = m->m_next; + } + } + RWLOCK_EXIT(&ipf_auth); + if (error != 0) + return error; + + 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) + goto fr_authioctlloop; + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_authreply */ +/* 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. */ +/* ------------------------------------------------------------------------ */ +int fr_authreply(data) +char *data; +{ + frauth_t auth, *au = &auth, *fra; + int error, i; + mb_t *m; + SPL_INT(s); + + 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; + 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 >= 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); + + /* + * 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(&fra->fra_info, m); + if (error != 0) { + error = ENOBUFS; + fr_authstats.fas_sendfail++; + } else { + fr_authstats.fas_sendok++; + } + } else if (m) { + error = ipf_inject(&fra->fra_info, m); + if (error != 0) { + error = ENOBUFS; + fr_authstats.fas_quefail++; + } else { + fr_authstats.fas_queok++; + } + } else { + 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) { + 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 /* _KERNEL */ + SPL_X(s); + + return 0; +} diff --git a/sys/contrib/ipfilter/netinet/ip_auth.h b/sys/contrib/ipfilter/netinet/ip_auth.h index a480c5d..36c4bac 100644 --- a/sys/contrib/ipfilter/netinet/ip_auth.h +++ b/sys/contrib/ipfilter/netinet/ip_auth.h @@ -30,7 +30,9 @@ typedef struct frauth { 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 { @@ -63,7 +65,7 @@ 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 int fr_auth_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *)); extern int fr_auth_waiting __P((void)); #endif /* __IP_AUTH_H__ */ diff --git a/sys/contrib/ipfilter/netinet/ip_compat.h b/sys/contrib/ipfilter/netinet/ip_compat.h index ebf8fbe..93ac208 100644 --- a/sys/contrib/ipfilter/netinet/ip_compat.h +++ b/sys/contrib/ipfilter/netinet/ip_compat.h @@ -239,11 +239,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 @@ -416,13 +417,7 @@ 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 @@ -575,8 +570,6 @@ 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) @@ -592,6 +585,7 @@ 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)); @@ -652,6 +646,7 @@ typedef struct mbuf mb_t; simple_unlock(&ipf_rw); } # define ATOMIC_DEC(x) { simple_lock(&ipf_rw); (x)--; \ simple_unlock(&ipf_rw); } +# define SPL_SCHED(x) ; # define SPL_NET(x) ; # define SPL_IMP(x) ; # undef SPL_X @@ -665,8 +660,6 @@ typedef struct mbuf mb_t; # 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) @@ -719,6 +712,14 @@ typedef unsigned int u_32_t; /* N E T B S D */ /* ----------------------------------------------------------------------- */ #ifdef __NetBSD__ +# if (NetBSD >= 199905) && !defined(IPFILTER_LKM) && defined(_KERNEL) +# include "opt_ipfilter.h" +# endif +# if defined(_KERNEL) +# include <sys/systm.h> +# else +# include <stddef.h> +# endif # if defined(_KERNEL) && !defined(IPFILTER_LKM) # include "bpfilter.h" # if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 104110000) @@ -732,7 +733,14 @@ typedef unsigned int u_32_t; # endif # endif +# if (__NetBSD_Version__ >= 499000000) +typedef char * caddr_t; +# endif + # ifdef _KERNEL +# if (__NetBSD_Version__ >= 399001400) +# define KMALLOCS(a, b, c) (a) = (b)malloc((c), _M_IPF, M_NOWAIT) +# endif # define MSGDSIZE(x) mbufchainlen(x) # define M_LEN(x) (x)->m_len # define M_DUPLICATE(x) m_copy((x), 0, M_COPYALL) @@ -740,8 +748,6 @@ typedef unsigned int u_32_t; # 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)) typedef struct mbuf mb_t; # endif /* _KERNEL */ # if (NetBSD <= 1991011) && (NetBSD >= 199606) @@ -755,7 +761,6 @@ typedef struct mbuf mb_t; # define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) # endif - typedef struct uio uio_t; typedef u_long ioctlcmd_t; typedef int minor_t; @@ -797,8 +802,6 @@ 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 @@ -814,7 +817,7 @@ typedef u_int32_t u_32_t; * with a WITNESS kernel, it generates LOR messages. */ # define KMUTEX_T struct mtx -# if 1 +# if (__FreeBSD_version < 700000) # define KRWLOCK_T struct mtx # else # define KRWLOCK_T struct sx @@ -858,7 +861,7 @@ 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 +# if (__FreeBSD_version < 700000) # 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) @@ -873,7 +876,7 @@ typedef u_int32_t u_32_t; # 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) +# define RWLOCK_EXIT(x) sx_unlock(&(x)->ipf_lk) # else # define RWLOCK_EXIT(x) do { \ if ((x)->ipf_lk.sx_cnt < 0) \ @@ -890,15 +893,16 @@ typedef u_int32_t u_32_t; mtx_unlock(&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_INC32(x) atomic_add_32((u_int *)&(x), 1) # define ATOMIC_INC16(x) atomic_add_16(&(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_DEC32(x) atomic_add_32((u_int *)&(x), -1) # define ATOMIC_DEC16(x) atomic_add_16(&(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)); # endif /* __FreeBSD_version >= 500043 */ # define MSGDSIZE(x) mbufchainlen(x) @@ -956,8 +960,6 @@ 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 @@ -1059,7 +1061,7 @@ typedef unsigned int u_32_t; #if defined(linux) && !defined(OS_RECOGNISED) #include <linux/config.h> #include <linux/version.h> -# if LINUX >= 20600 +# if (LINUX >= 20600) && defined(_KERNEL) # define HDR_T_PRIVATE 1 # endif # undef USE_INET6 @@ -1072,15 +1074,17 @@ struct ip6_ext { # ifdef _KERNEL # 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 POLLWAKEUP(x) ; -# define WAKEUP(x,y) wake_up(x##_linux + y) +# 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(a,b,c,d) # define USE_MUTEXES # define KRWLOCK_T rwlock_t @@ -1092,7 +1096,7 @@ struct ip6_ext { # 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) @@ -1112,6 +1116,7 @@ struct ip6_ext { MUTEX_EXIT(&ipf_rw) # define ATOMIC_DEC16(x) MUTEX_ENTER(&ipf_rw); (x)--; \ MUTEX_EXIT(&ipf_rw) +# 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) @@ -1261,6 +1266,7 @@ typedef u_int32_t u_32_t; MUTEX_EXIT(&ipf_rw); } # define ATOMIC_DEC(x) { MUTEX_ENTER(&ipf_rw); (x)--; \ MUTEX_EXIT(&ipf_rw); } +# define SPL_SCHED(x) x = splsched() # define SPL_NET(x) x = splnet() # define SPL_IMP(x) x = splimp() # undef SPL_X @@ -1274,8 +1280,6 @@ extern void* getifp __P((char *, int)); # 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_TEMP, M_NOWAIT) # define KMALLOCS(a, b, c) MALLOC((a), b, (c), M_TEMP, \ ((c) > 4096) ? M_WAITOK : M_NOWAIT) @@ -1352,7 +1356,7 @@ typedef struct { u_int eMm_magic; int eMm_held; int eMm_heldat; -#ifdef __hpux +#if defined(__hpux) || defined(__linux) char eMm_fill[8]; #endif } eMmutex_t; @@ -1411,6 +1415,7 @@ typedef union { 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 @@ -1439,6 +1444,7 @@ typedef struct mb_s { # 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) ; @@ -1449,8 +1455,6 @@ typedef struct mb_s { # define GETIFP(x, v) get_unit(x,v) # define COPYIN(a,b,c) bcopywrap((a), (b), (c)) # define COPYOUT(a,b,c) bcopywrap((a), (b), (c)) -# define BCOPYIN(a,b,c) (bcopy((a), (b), (c)), 0) -# define BCOPYOUT(a,b,c) (bcopy((a), (b), (c)), 0) # define COPYDATA(m, o, l, b) bcopy(MTOD((mb_t *)m, char *) + (o), \ (b), (l)) # define COPYBACK(m, o, l, b) bcopy((b), \ @@ -1581,7 +1585,9 @@ MALLOC_DECLARE(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) +# if !defined(KMALLOCS) +# define KMALLOCS(a, b, c) MALLOC((a), b, (c), _M_IPF, M_NOWAIT) +# endif # define KFREE(x) FREE((x), _M_IPF) # define KFREES(x,s) FREE((x), _M_IPF) # define UIOMOVE(a,b,c,d) uiomove(a,b,d) @@ -1599,6 +1605,7 @@ MALLOC_DECLARE(M_IPFILTER); # define SPL_IMP(x) x = splimp() # define SPL_NET(x) x = splnet() # endif /* NetBSD && (NetBSD <= 1991011) && (NetBSD >= 199407) */ +# define SPL_SCHED(x) x = splsched() # define SPL_X(x) (void) splx(x) # endif /* !USE_MUTEXES */ @@ -1613,8 +1620,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 @@ -1643,6 +1648,11 @@ extern char *fr_getifname __P((struct ifnet *, char *)); # define ASSERT(x) #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 + /* * Because the ctype(3) posix definition, if used "safely" in code everywhere, * would mean all normal code that walks through strings needed casts. Yuck. @@ -1719,9 +1729,6 @@ 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)) #endif @@ -1741,7 +1748,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 @@ -2349,21 +2356,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 diff --git a/sys/contrib/ipfilter/netinet/ip_fil.h b/sys/contrib/ipfilter/netinet/ip_fil.h index 568453d..dc5a473 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil.h +++ b/sys/contrib/ipfilter/netinet/ip_fil.h @@ -44,12 +44,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) @@ -57,6 +57,12 @@ # 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) #else # define SIOCADAFR _IOW(r, 60, struct ipfobj) # define SIOCRMAFR _IOW(r, 61, struct ipfobj) @@ -76,12 +82,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) @@ -89,10 +95,18 @@ # 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) #endif #define SIOCADDFR SIOCADAFR #define SIOCDELFR SIOCRMAFR #define SIOCINSFR SIOCINAFR +#define SIOCATHST SIOCSTAT1 +#define SIOCGFRST SIOCSTAT2 struct ipscan; @@ -112,6 +126,11 @@ typedef union i6addr { struct in6_addr in6; void *vptr[2]; lookupfunc_t lptr[2]; + struct { + u_short type; + u_short subtype; + char label[12]; + } i6un; } i6addr_t; #else typedef union i6addr { @@ -119,12 +138,19 @@ typedef union i6addr { struct in_addr in4; void *vptr[2]; lookupfunc_t lptr[2]; + struct { + u_short type; + u_short subtype; + char label[12]; + } 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.label +#define iplookuptype i6un.type +#define iplookupsubtype i6un.subtype /* * NOTE: These DO overlap the above on 64bit systems and this IS recognised. */ @@ -250,8 +276,12 @@ typedef struct fr_ip { #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 @@ -300,6 +330,7 @@ typedef struct fr_info { void *fin_nat; void *fin_state; void *fin_nattag; + void *fin_exthdr; ip_t *fin_ip; mb_t **fin_mp; /* pointer to pointer to mbuf */ mb_t *fin_m; /* pointer to mbuf */ @@ -330,8 +361,8 @@ typedef struct fr_info { #define fin_dport fin_dat.fid_16[1] #define fin_ports fin_dat.fid_32 -#define IPF_IN 0 -#define IPF_OUT 1 +#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 *)); @@ -441,9 +472,13 @@ typedef struct fripf { 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 */ @@ -469,6 +504,13 @@ typedef struct frentry { int fr_ref; /* reference count - for grouping */ int fr_statecnt; /* state count - for limit rules */ /* + * 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 */ @@ -495,7 +537,6 @@ typedef struct frentry { 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; u_32_t fr_flags; /* per-rule flags && options (see below) */ u_32_t fr_logtag; /* user defined log tag # */ @@ -555,8 +596,14 @@ typedef struct frentry { #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 @@ -1019,6 +1066,8 @@ typedef struct ipftq { /* checks its timeout queues. */ #define IPF_TTLVAL(x) (((x) / IPF_HZ_MULT) * IPF_HZ_DIVIDE) +typedef int (*ipftq_delete_fn_t)(void *); + /* * Structure to define address for pool lookups. */ @@ -1054,6 +1103,13 @@ 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_COUNT 20 /* How many #defines are above this? */ typedef union ipftunevalptr { @@ -1066,7 +1122,7 @@ typedef union ipftunevalptr { 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; @@ -1105,6 +1161,66 @@ typedef struct ipftune { #define ipft_vshort ipft_un.ipftu_short #define ipft_vchar ipft_un.ipftu_char +/* + * + */ +typedef struct ipfruleiter { + int iri_inout; + char iri_group[FR_GROUPLEN]; + int iri_active; + int iri_nrules; + int iri_v; + 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 + + +/* + * + */ +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_alive; +} ipftoken_t; + /* ** HPUX Port @@ -1163,11 +1279,22 @@ extern int iplclose __P((dev_t, int)); extern void m_freem __P((mb_t *)); extern int bcopywrap __P((void *, void *, size_t)); #else /* #ifndef _KERNEL */ +# ifdef BSD +# if (defined(__NetBSD__) && (__NetBSD_Version__ < 399000000)) || \ + defined(__osf__) || \ + (defined(__FreeBSD_version) && (__FreeBSD_version < 500043)) +# include <sys/select.h> +# else +# include <sys/selinfo.h> +# endif +extern struct selinfo ipfselwait[IPL_LOGSIZE]; +# endif # if defined(__NetBSD__) && defined(PFIL_HOOKS) extern void ipfilterattach __P((int)); # endif extern int ipl_enable __P((void)); extern int ipl_disable __P((void)); +extern int ipf_inject __P((fr_info_t *, mb_t *)); # ifdef MENTAT extern int fr_check __P((struct ip *, int, void *, int, void *, mblk_t **)); @@ -1190,7 +1317,6 @@ extern int iplread __P((dev_t, uio_t *)); extern int iplwrite __P((dev_t, uio_t *)); extern int iplselect __P((dev_t, int)); # endif -extern int ipfsync __P((void)); extern int fr_qout __P((queue_t *, mblk_t *)); # else /* MENTAT */ extern int fr_check __P((struct ip *, int, void *, int, mb_t **)); @@ -1203,7 +1329,6 @@ 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 ipfilter_sgi_attach __P((void)); extern void ipfilter_sgi_detach __P((void)); extern void ipfilter_sgi_intfsync __P((void)); @@ -1224,7 +1349,15 @@ extern int iplioctl __P((struct cdev*, u_long, caddr_t, int, struct thread *)); extern int iplioctl __P((dev_t, u_long, caddr_t, int, struct thread *)); # endif /* __FreeBSD_version >= 502116 */ # else +# if (__NetBSD_Version__ >= 499001000) +extern int iplioctl __P((dev_t, u_long, void *, int, struct lwp *)); +# else +# if (__NetBSD_Version__ >= 399001400) +extern int iplioctl __P((dev_t, u_long, caddr_t, int, struct lwp *)); +# else extern int iplioctl __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 thread *)); @@ -1238,8 +1371,13 @@ 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 +# if (__NetBSD_Version__ >= 399001400) +extern int iplopen __P((dev_t, int, int, struct lwp *)); +extern int iplclose __P((dev_t, int, int, struct lwp *)); +# else extern int iplopen __P((dev_t, int, int, struct proc *)); extern int iplclose __P((dev_t, int, int, struct proc *)); +# endif /* __NetBSD_Version__ >= 399001400 */ # endif /* __FreeBSD_version >= 500024 */ # else # ifdef linux @@ -1273,21 +1411,22 @@ 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; -extern ipfrwlock_t ipf_frcache; +extern ipfrwlock_t ipf_frcache, ipf_tokens; 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)); extern char *getifname __P((struct ifnet *)); -extern int iplattach __P((void)); -extern int ipldetach __P((void)); +extern int ipfattach __P((void)); +extern int ipfdetach __P((void)); 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_ioctlswitch __P((int, void *, ioctlcmd_t, int, int, void *)); +extern int fr_ipf_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *)); 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)); @@ -1297,7 +1436,7 @@ 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) +#if (__FreeBSD_version < 501000) || !defined(_KERNEL) extern int ppsratecheck __P((struct timeval *, int *, int)); #endif extern ipftq_t *fr_addtimeoutqueue __P((ipftq_t **, u_int)); @@ -1359,12 +1498,20 @@ 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 ipf_queueflush __P((ipftq_delete_fn_t, ipftq_t *, ipftq_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 ipftoken_t *ipf_findtoken __P((int, int, void *)); +extern int ipf_getnextrule __P((ipftoken_t *, void *)); +extern void ipf_expiretokens __P((void)); +extern void ipf_freetoken __P((ipftoken_t *)); +extern int ipf_deltoken __P((int,int, void *)); +extern int ipfsync __P((void)); +extern int ipf_genericiter __P((void *, int, void *)); extern int fr_running; extern u_long fr_frouteok[2]; @@ -1379,7 +1526,6 @@ 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; diff --git a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c index 64421e0..aeefb03 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c +++ b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c @@ -7,7 +7,7 @@ */ #if !defined(lint) static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_fil_freebsd.c,v 2.53.2.32 2006/03/25 13:03:01 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_fil_freebsd.c,v 2.53.2.46 2007/05/11 13:41:53 darrenr Exp $"; #endif #if defined(KERNEL) || defined(_KERNEL) @@ -57,11 +57,18 @@ static const char rcsid[] = "@(#)$Id: ip_fil_freebsd.c,v 2.53.2.32 2006/03/25 13 #endif #include <sys/protosw.h> #include <sys/socket.h> -#include <sys/selinfo.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 __FreeBSD_version >= 500043 +# include <net/netisr.h> +# endif # if !defined(IPFILTER_LKM) # include "opt_ipfilter.h" # endif @@ -126,7 +133,7 @@ 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, ipf_frcache; +ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag, ipf_frcache, ipf_tokens; ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth; # endif int ipf_locks_done = 0; @@ -193,7 +200,7 @@ char *s; #endif /* IPFILTER_LKM */ -int iplattach() +int ipfattach() { #ifdef USE_SPL int s; @@ -215,11 +222,9 @@ int iplattach() } 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_frcache, "ipf cache rwlock"); RWLOCK_INIT(&ipf_ipidfrag, "ipf IP NAT-Frag rwlock"); + RWLOCK_INIT(&ipf_tokens, "ipf token rwlock"); ipf_locks_done = 1; if (fr_initialise() < 0) { @@ -326,7 +331,7 @@ pfil_error: * Disable the filter by removing the hooks from the IP input/output * stream. */ -int ipldetach() +int ipfdetach() { #ifdef USE_SPL int s; @@ -420,10 +425,8 @@ int ipldetach() if (ipf_locks_done == 1) { MUTEX_DESTROY(&ipf_timeoutlock); MUTEX_DESTROY(&ipf_rw); - RW_DESTROY(&ipf_mutex); - RW_DESTROY(&ipf_frcache); RW_DESTROY(&ipf_ipidfrag); - RW_DESTROY(&ipf_global); + RW_DESTROY(&ipf_tokens); ipf_locks_done = 0; } @@ -441,8 +444,14 @@ int iplioctl(dev, cmd, data, mode , p) # if (__FreeBSD_version >= 500024) 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; +# define p_uid p_cred->p_ruid # endif /* __FreeBSD_version >= 500024 */ # else ) @@ -456,11 +465,8 @@ 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 >= 3) && (mode & FWRITE)) @@ -481,159 +487,16 @@ int mode; } SPL_NET(s); - if (fr_running > 0) - READ_ENTER(&ipf_global); + READ_ENTER(&ipf_global); - error = fr_ioctlswitch(unit, data, cmd, mode); + error = fr_ioctlswitch(unit, data, cmd, mode, p->p_uid, p); if (error != -1) { RWLOCK_EXIT(&ipf_global); 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 { - if (fr_running <= 0) - error = 0; - 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; - } - if (fr_running > 0) - if (mtx_owned(&(&ipf_global)->ipf_lk)) - RWLOCK_EXIT(&ipf_global); + RWLOCK_EXIT(&ipf_global); SPL_X(s); return error; @@ -760,6 +623,9 @@ register struct uio *uio; { u_int xmin = GET_MINOR(dev); + if (fr_running < 1) + return EIO; + if (xmin < 0) return ENXIO; @@ -796,6 +662,9 @@ dev_t dev; register struct uio *uio; { + if (fr_running < 1) + return EIO; + #ifdef IPFILTER_SYNC if (GET_MINOR(dev) == IPL_LOGSYNC) return ipfsync_write(uio); @@ -1153,7 +1022,7 @@ void # endif iplinit() { - if (iplattach() != 0) + if (ipfattach() != 0) printf("IP Filter failed to attach\n"); ip_init(); } @@ -1264,9 +1133,11 @@ 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; @@ -1275,7 +1146,8 @@ frdest_t *fdp; if (!fr || !(fr->fr_flags & FR_RETMASK)) { u_32_t pass; - (void) fr_checkstate(fin, &pass); + if (fr_checkstate(fin, &pass) != NULL) + fr_statederef((ipstate_t **)&fin->fin_state); } switch (fr_checknatout(fin, NULL)) @@ -1283,6 +1155,7 @@ frdest_t *fdp; case 0 : break; case 1 : + fr_natderef((nat_t **)&fin->fin_nat); ip->ip_sum = 0; break; case -1 : @@ -1742,3 +1615,46 @@ int len; 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 { +#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; +} diff --git a/sys/contrib/ipfilter/netinet/ip_frag.c b/sys/contrib/ipfilter/netinet/ip_frag.c index 5a93295..02e7bd1 100644 --- a/sys/contrib/ipfilter/netinet/ip_frag.c +++ b/sys/contrib/ipfilter/netinet/ip_frag.c @@ -107,16 +107,17 @@ static const char rcsid[] = "@(#)$FreeBSD$"; #endif -static ipfr_t *ipfr_list = NULL; -static ipfr_t **ipfr_tail = &ipfr_list; -static ipfr_t **ipfr_heads; +ipfr_t *ipfr_list = NULL; +ipfr_t **ipfr_tail = &ipfr_list; -static ipfr_t *ipfr_natlist = NULL; -static ipfr_t **ipfr_nattail = &ipfr_natlist; -static ipfr_t **ipfr_nattab; +ipfr_t *ipfr_natlist = NULL; +ipfr_t **ipfr_nattail = &ipfr_natlist; -static ipfr_t *ipfr_ipidlist = NULL; -static ipfr_t **ipfr_ipidtail = &ipfr_ipidlist; +ipfr_t *ipfr_ipidlist = NULL; +ipfr_t **ipfr_ipidtail = &ipfr_ipidlist; + +static ipfr_t **ipfr_heads; +static ipfr_t **ipfr_nattab; static ipfr_t **ipfr_ipidtab; static ipfrstat_t ipfr_stats; @@ -132,6 +133,7 @@ u_long fr_ticks = 0; 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 ***)); +static void fr_fragfree __P((ipfr_t *)); /* ------------------------------------------------------------------------ */ @@ -308,6 +310,7 @@ ipfr_t *table[]; fra->ipfr_seen0 = 1; fra->ipfr_off = off + (fin->fin_dlen >> 3); fra->ipfr_pass = pass; + fra->ipfr_ref = 1; ipfr_stats.ifs_new++; ipfr_inuse++; return fra; @@ -688,11 +691,6 @@ void *ptr; static void fr_fragdelete(fra, tail) ipfr_t *fra, ***tail; { - frentry_t *fr; - - fr = fra->ipfr_rule; - if (fr != NULL) - (void)fr_derefrule(&fr); if (fra->ipfr_next) fra->ipfr_next->ipfr_prev = fra->ipfr_prev; @@ -703,7 +701,30 @@ 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) fr_derefrule(&fra->ipfr_rule); + } + + if (fra->ipfr_ref <= 0) + fr_fragfree(fra); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_fragfree */ +/* Returns: Nil */ +/* Parameters: fra - pointer to frag structure to free */ +/* */ +/* Take care of the details associated with deleting an entry from the frag */ +/* cache. Currently this just means bumping stats correctly after freeing */ +/* ------------------------------------------------------------------------ */ +static void fr_fragfree(fra) +ipfr_t *fra; +{ KFREE(fra); + ipfr_stats.ifs_expire++; + ipfr_inuse--; } @@ -721,8 +742,10 @@ void fr_fragclear() nat_t *nat; WRITE_ENTER(&ipf_frag); - while ((fra = ipfr_list) != NULL) + while ((fra = ipfr_list) != NULL) { + fra->ipfr_ref--; fr_fragdelete(fra, &ipfr_tail); + } ipfr_tail = &ipfr_list; RWLOCK_EXIT(&ipf_frag); @@ -734,6 +757,7 @@ void fr_fragclear() if (nat->nat_data == fra) nat->nat_data = NULL; } + fra->ipfr_ref--; fr_fragdelete(fra, &ipfr_nattail); } ipfr_nattail = &ipfr_natlist; @@ -767,9 +791,8 @@ void fr_fragexpire() for (fp = &ipfr_list; ((fra = *fp) != NULL); ) { if (fra->ipfr_ttl > fr_ticks) break; + fra->ipfr_ref--; fr_fragdelete(fra, &ipfr_tail); - ipfr_stats.ifs_expire++; - ipfr_inuse--; } RWLOCK_EXIT(&ipf_frag); @@ -777,9 +800,8 @@ void fr_fragexpire() for (fp = &ipfr_ipidlist; ((fra = *fp) != NULL); ) { if (fra->ipfr_ttl > fr_ticks) break; + fra->ipfr_ref--; fr_fragdelete(fra, &ipfr_ipidtail); - ipfr_stats.ifs_expire++; - ipfr_inuse--; } RWLOCK_EXIT(&ipf_ipidfrag); @@ -789,23 +811,27 @@ 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 (ipfr_natlist != NULL) { + 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; + } + fra->ipfr_ref--; + fr_fragdelete(fra, &ipfr_nattail); } - fr_fragdelete(fra, &ipfr_nattail); - ipfr_stats.ifs_expire++; - ipfr_inuse--; + RWLOCK_EXIT(&ipf_natfrag); + RWLOCK_EXIT(&ipf_nat); } - RWLOCK_EXIT(&ipf_natfrag); - RWLOCK_EXIT(&ipf_nat); SPL_X(s); } @@ -828,6 +854,7 @@ int fr_slowtimer() { READ_ENTER(&ipf_global); + ipf_expiretokens(); fr_fragexpire(); fr_timeoutstate(); fr_natexpire(); @@ -861,3 +888,106 @@ done: # endif } #endif /* !SOLARIS && !defined(__hpux) && !defined(__sgi) */ + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_nextfrag */ +/* 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 */ +/* tail(I) - tail 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, tail and lock. */ +/* ------------------------------------------------------------------------ */ +int fr_nextfrag(token, itp, top, tail +#ifdef USE_MUTEXES +, lock +#endif +) +ipftoken_t *token; +ipfgeniter_t *itp; +ipfr_t **top, ***tail; +#ifdef USE_MUTEXES +ipfrwlock_t *lock; +#endif +{ + ipfr_t *frag, *next, zero; + int error = 0; + + frag = token->ipt_data; + if (frag == (ipfr_t *)-1) { + ipf_freetoken(token); + return ESRCH; + } + + 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 = (void *)-1; + } + RWLOCK_EXIT(lock); + + if (frag != NULL) { + WRITE_ENTER(lock); + frag->ipfr_ref--; + if (frag->ipfr_ref <= 0) + fr_fragfree(frag); + RWLOCK_EXIT(lock); + } + + error = COPYOUT(next, itp->igi_data, sizeof(*next)); + if (error != 0) + error = EFAULT; + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_fragderef */ +/* 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. */ +/* ------------------------------------------------------------------------ */ +void fr_fragderef(frp +#ifdef USE_MUTEXES +, lock +#endif +) +ipfr_t **frp; +#ifdef USE_MUTEXES +ipfrwlock_t *lock; +#endif +{ + ipfr_t *fra; + + fra = *frp; + *frp = NULL; + + WRITE_ENTER(lock); + fra->ipfr_ref--; + if (fra->ipfr_ref <= 0) + fr_fragfree(fra); + RWLOCK_EXIT(lock); +} diff --git a/sys/contrib/ipfilter/netinet/ip_frag.h b/sys/contrib/ipfilter/netinet/ip_frag.h index 88b5882..227dbcd 100644 --- a/sys/contrib/ipfilter/netinet/ip_frag.h +++ b/sys/contrib/ipfilter/netinet/ip_frag.h @@ -19,6 +19,16 @@ 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; + int ipfr_ref; + u_short ipfr_off; + u_short 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; @@ -29,10 +39,6 @@ typedef struct ipfr { u_char ipfr_p; u_char ipfr_tos; u_32_t ipfr_pass; - u_short ipfr_off; - u_char ipfr_ttl; - u_char ipfr_seen0; - frentry_t *ipfr_rule; } ipfr_t; @@ -52,6 +58,8 @@ typedef struct ipfrstat { #define IPFR_CMPSZ (offsetof(ipfr_t, ipfr_pass) - \ offsetof(ipfr_t, ipfr_ifp)) +extern ipfr_t *ipfr_list, **ipfr_tail; +extern ipfr_t *ipfr_natlist, **ipfr_nattail; extern int ipfr_size; extern int fr_ipfrttl; extern int fr_frag_lock; @@ -67,6 +75,15 @@ 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 *)); +#ifdef USE_MUTEXES +extern void fr_fragderef __P((ipfr_t **, ipfrwlock_t *)); +extern int fr_nextfrag __P((ipftoken_t *, ipfgeniter_t *, ipfr_t **, \ + ipfr_t ***, ipfrwlock_t *)); +#else +extern void fr_fragderef __P((ipfr_t **)); +extern int fr_nextfrag __P((ipftoken_t *, ipfgeniter_t *, ipfr_t **, \ + ipfr_t ***)); +#endif extern void fr_forget __P((void *)); extern void fr_forgetnat __P((void *)); diff --git a/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c b/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c index 6718f85..f56a690 100644 --- a/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c @@ -371,24 +371,11 @@ int dlen; } (void) fr_addstate(&fi, NULL, SI_W_DPORT); if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); + fr_statederef((ipstate_t **)&fi.fin_state); } 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); - } - RWLOCK_EXIT(&ipf_state); } return APR_INC(inc); } @@ -733,25 +720,12 @@ u_int data_ip; } (void) fr_addstate(&fi, NULL, sflags); if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); + fr_statederef((ipstate_t **)&fi.fin_state); } 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); - } - RWLOCK_EXIT(&ipf_state); } return inc; } @@ -1144,8 +1118,8 @@ int rv; f->ftps_seq[1] = thseq + 1 - seqoff; } else { if (ippr_ftp_debug > 1) { - printf("FIN: thseq %x seqoff %d ftps_seq %x\n", - thseq, seqoff, f->ftps_seq[0]); + printf("FIN: thseq %x seqoff %d ftps_seq %x %x\n", + thseq, seqoff, f->ftps_seq[0], f->ftps_seq[1]); } return APR_ERR(1); } diff --git a/sys/contrib/ipfilter/netinet/ip_htable.c b/sys/contrib/ipfilter/netinet/ip_htable.c index aaecaa6..3882156 100644 --- a/sys/contrib/ipfilter/netinet/ip_htable.c +++ b/sys/contrib/ipfilter/netinet/ip_htable.c @@ -53,7 +53,7 @@ struct file; /* END OF INCLUDES */ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_htable.c,v 2.34.2.4 2005/11/13 15:38:37 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_htable.c,v 2.34.2.9 2007/02/02 23:06:16 darrenr Exp $"; #endif #ifdef IPFILTER_LOOKUP @@ -103,30 +103,36 @@ iplookupop_t *op; char name[FR_GROUPLEN]; int err, i, unit; - KMALLOC(iph, iphtable_t *); - if (iph == NULL) { - ipht_nomem[op->iplo_unit]++; - return ENOMEM; - } + unit = op->iplo_unit; + if ((op->iplo_arg & IPHASH_ANON) == 0) + iph = fr_existshtable(unit, op->iplo_name); + else + iph = NULL; - err = COPYIN(op->iplo_struct, iph, sizeof(*iph)); - if (err != 0) { - KFREE(iph); - return EFAULT; + if (iph == NULL) { + KMALLOC(iph, iphtable_t *); + if (iph == NULL) { + ipht_nomem[op->iplo_unit]++; + return ENOMEM; + } + err = COPYIN(op->iplo_struct, iph, sizeof(*iph)); + if (err != 0) { + KFREE(iph); + return EFAULT; + } + } else { + if ((iph->iph_flags & IPHASH_DELETE) == 0) + return EEXIST; } - unit = op->iplo_unit; if (iph->iph_unit != unit) { - KFREE(iph); + if ((iph->iph_flags & IPHASH_DELETE) == 0) { + KFREE(iph); + } return EINVAL; } - if ((op->iplo_arg & IPHASH_ANON) == 0) { - if (fr_findhtable(op->iplo_unit, op->iplo_name) != NULL) { - KFREE(iph); - return EEXIST; - } - } else { + if ((op->iplo_arg & IPHASH_ANON) != 0) { i = IPHASH_ANON; do { i++; @@ -147,24 +153,33 @@ iplookupop_t *op; iph->iph_type |= IPHASH_ANON; } - KMALLOCS(iph->iph_table, iphtent_t **, - iph->iph_size * sizeof(*iph->iph_table)); - if (iph->iph_table == NULL) { - KFREE(iph); - ipht_nomem[unit]++; - return ENOMEM; - } + if ((iph->iph_flags & IPHASH_DELETE) == 0) { + KMALLOCS(iph->iph_table, iphtent_t **, + iph->iph_size * sizeof(*iph->iph_table)); + if (iph->iph_table == NULL) { + if ((iph->iph_flags & IPHASH_DELETE) == 0) { + KFREE(iph); + } + ipht_nomem[unit]++; + return ENOMEM; + } - bzero((char *)iph->iph_table, iph->iph_size * sizeof(*iph->iph_table)); - iph->iph_masks = 0; + bzero((char *)iph->iph_table, + iph->iph_size * sizeof(*iph->iph_table)); + iph->iph_masks = 0; + iph->iph_list = NULL; - 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; + iph->iph_ref = 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; - ipf_nhtables[unit]++; + ipf_nhtables[unit]++; + } + + iph->iph_flags &= ~IPHASH_DELETE; return 0; } @@ -172,22 +187,24 @@ iplookupop_t *op; /* */ -int fr_removehtable(op) -iplookupop_t *op; +int fr_removehtable(unit, name) +int unit; +char *name; { iphtable_t *iph; - - iph = fr_findhtable(op->iplo_unit, op->iplo_name); + iph = fr_findhtable(unit, name); if (iph == NULL) return ESRCH; - if (iph->iph_unit != op->iplo_unit) { + if (iph->iph_unit != unit) { return EINVAL; } if (iph->iph_ref != 0) { - return EBUSY; + (void) fr_clearhtable(iph); + iph->iph_flags |= IPHASH_DELETE; + return 0; } fr_delhtable(iph); @@ -196,40 +213,106 @@ iplookupop_t *op; } -void fr_delhtable(iph) +int fr_clearhtable(iph) 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 (fr_delhtent(iph, ipe) != 0) + return 1; + return 0; +} + - *iph->iph_pnext = iph->iph_next; +int fr_delhtable(iph) +iphtable_t *iph; +{ + + if (fr_clearhtable(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; ipf_nhtables[iph->iph_unit]--; + return fr_derefhtable(iph); +} + + +/* + * Delete an entry from a hash table. + */ +int fr_delhtent(iph, ipe) +iphtable_t *iph; +iphtent_t *ipe; +{ + + if (ipe->ipe_phnext != NULL) + *ipe->ipe_phnext = ipe->ipe_hnext; + if (ipe->ipe_hnext != NULL) + ipe->ipe_hnext->ipe_phnext = ipe->ipe_phnext; + + if (ipe->ipe_pnext != NULL) + *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; + + default : + ipe->ipe_ptr = NULL; + ipe->ipe_value = 0; + break; + } + + return fr_derefhtent(ipe); +} + + +int fr_derefhtable(iph) +iphtable_t *iph; +{ + int refs; + + iph->iph_ref--; + refs = iph->iph_ref; + if (iph->iph_ref == 0) { KFREES(iph->iph_table, iph->iph_size * sizeof(*iph->iph_table)); KFREE(iph); } + + return refs; } -void fr_derefhtable(iph) -iphtable_t *iph; +int fr_derefhtent(ipe) +iphtent_t *ipe; { - iph->iph_ref--; - if (iph->iph_ref == 0) - fr_delhtable(iph); + + ipe->ipe_ref--; + if (ipe->ipe_ref == 0) { + ipf_nhtnodes[ipe->ipe_unit]--; + + KFREE(ipe); + + return 0; + } + + return ipe->ipe_ref; } -iphtable_t *fr_findhtable(unit, name) +iphtable_t *fr_existshtable(unit, name) int unit; char *name; { @@ -242,6 +325,20 @@ char *name; } +iphtable_t *fr_findhtable(unit, name) +int unit; +char *name; +{ + iphtable_t *iph; + + iph = fr_existshtable(unit, name); + if ((iph != NULL) && (iph->iph_flags & IPHASH_DELETE) == 0) + return iph; + + return NULL; +} + + size_t fr_flushhtable(op) iplookupflush_t *op; { @@ -254,8 +351,11 @@ iplookupflush_t *op; for (i = 0; i <= IPL_LOGMAX; i++) { if (op->iplf_unit == i || op->iplf_unit == IPL_LOGALL) { while ((iph = ipf_htables[i]) != NULL) { - fr_delhtable(iph); - freed++; + if (fr_delhtable(iph) == 0) { + freed++; + } else { + iph->iph_flags |= IPHASH_DELETE; + } } } } @@ -287,13 +387,20 @@ iphtent_t *ipeo; 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_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; + + ipe->ipe_next = iph->iph_list; + ipe->ipe_pnext = &iph->iph_list; + if (ipe->ipe_next != NULL) + ipe->ipe_next->ipe_pnext = &ipe->ipe_next; + iph->iph_list = ipe; + if ((bits >= 0) && (bits != 32)) iph->iph_masks |= 1 << bits; @@ -311,44 +418,8 @@ iphtent_t *ipeo; break; } - ipf_nhtnodes[iph->iph_unit]++; - - return 0; -} - - -/* - * Delete an entry from a hash table. - */ -int fr_delhtent(iph, ipe) -iphtable_t *iph; -iphtent_t *ipe; -{ - - 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; - - default : - ipe->ipe_ptr = NULL; - ipe->ipe_value = 0; - break; - } - - KFREE(ipe); - - ipf_nhtnodes[iph->iph_unit]--; + ipe->ipe_unit = iph->iph_unit; + ipf_nhtnodes[ipe->ipe_unit]++; return 0; } @@ -379,22 +450,22 @@ void *tptr, *aptr; /* ------------------------------------------------------------------------ */ /* Function: fr_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: tptr(I) - pointer to the pool to search */ +/* ipversion(I) - IP protocol version (4 or 6) */ +/* aptr(I) - pointer to address information */ /* */ /* Search the hash table for a given address and return a search result. */ /* ------------------------------------------------------------------------ */ -int fr_iphmfindip(tptr, version, aptr) +int fr_iphmfindip(tptr, ipversion, aptr) void *tptr, *aptr; -int version; +int ipversion; { struct in_addr *addr; iphtable_t *iph; iphtent_t *ipe; int rval; - if (version != 4) + if (ipversion != 4) return -1; if (tptr == NULL || aptr == NULL) @@ -428,7 +499,7 @@ struct in_addr *addr; 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) { + for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_hnext) { if (ipe->ipe_mask.in4_addr != msk || ipe->ipe_addr.in4_addr != ips) { continue; @@ -451,4 +522,133 @@ maskloop: return ipe; } + +int fr_htable_getnext(token, ilp) +ipftoken_t *token; +ipflookupiter_t *ilp; +{ + iphtent_t *node, zn, *nextnode; + iphtable_t *iph, zp, *nextiph; + int err; + + err = 0; + iph = NULL; + node = NULL; + nextiph = NULL; + nextnode = NULL; + + READ_ENTER(&ip_poolrw); + + switch (ilp->ili_otype) + { + case IPFLOOKUPITER_LIST : + iph = token->ipt_data; + if (iph == NULL) { + nextiph = ipf_htables[(int)ilp->ili_unit]; + } else { + nextiph = iph->iph_next; + } + + if (nextiph != NULL) { + ATOMIC_INC(nextiph->iph_ref); + if (nextiph->iph_next == NULL) + token->ipt_alive = 0; + } else { + bzero((char *)&zp, sizeof(zp)); + nextiph = &zp; + } + break; + + case IPFLOOKUPITER_NODE : + node = token->ipt_data; + if (node == NULL) { + iph = fr_findhtable(ilp->ili_unit, ilp->ili_name); + if (iph == NULL) + err = ESRCH; + else { + nextnode = iph->iph_list; + } + } else { + nextnode = node->ipe_next; + } + + if (nextnode != NULL) { + ATOMIC_INC(nextnode->ipe_ref); + if (nextnode->ipe_next == NULL) + token->ipt_alive = 0; + } else { + bzero((char *)&zn, sizeof(zn)); + nextnode = &zn; + } + break; + default : + err = EINVAL; + break; + } + + RWLOCK_EXIT(&ip_poolrw); + if (err != 0) + return err; + + switch (ilp->ili_otype) + { + case IPFLOOKUPITER_LIST : + if (iph != NULL) { + WRITE_ENTER(&ip_poolrw); + fr_derefhtable(iph); + RWLOCK_EXIT(&ip_poolrw); + } + token->ipt_data = nextiph; + err = COPYOUT(nextiph, ilp->ili_data, sizeof(*nextiph)); + if (err != 0) + err = EFAULT; + break; + + case IPFLOOKUPITER_NODE : + if (node != NULL) { + WRITE_ENTER(&ip_poolrw); + fr_derefhtent(node); + RWLOCK_EXIT(&ip_poolrw); + } + token->ipt_data = nextnode; + err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode)); + if (err != 0) + err = EFAULT; + break; + } + + return err; +} + + +void fr_htable_iterderef(otype, unit, data) +u_int otype; +int unit; +void *data; +{ + + if (data == NULL) + return; + + if (unit < 0 || unit > IPL_LOGMAX) + return; + + switch (otype) + { + case IPFLOOKUPITER_LIST : + WRITE_ENTER(&ip_poolrw); + fr_derefhtable((iphtable_t *)data); + RWLOCK_EXIT(&ip_poolrw); + break; + + case IPFLOOKUPITER_NODE : + WRITE_ENTER(&ip_poolrw); + fr_derefhtent((iphtent_t *)data); + RWLOCK_EXIT(&ip_poolrw); + break; + default : + break; + } +} + #endif /* IPFILTER_LOOKUP */ diff --git a/sys/contrib/ipfilter/netinet/ip_log.c b/sys/contrib/ipfilter/netinet/ip_log.c index 83dcb70..83454f0 100644 --- a/sys/contrib/ipfilter/netinet/ip_log.c +++ b/sys/contrib/ipfilter/netinet/ip_log.c @@ -17,7 +17,11 @@ #endif #if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ defined(_KERNEL) -# include "opt_ipfilter_log.h" +# if (__NetBSD_Version__ < 399001400) +# include "opt_ipfilter_log.h" +# else +# include "opt_ipfilter.h" +# endif #endif #if defined(__FreeBSD__) && !defined(IPFILTER_LKM) # if defined(_KERNEL) @@ -148,12 +152,11 @@ iplog_select_t iplog_ss[IPL_LOGMAX+1]; extern int selwait; # endif /* IPL_SELECT */ -extern struct selinfo ipfselwait[IPL_LOGSIZE]; # if defined(linux) && defined(_KERNEL) wait_queue_head_t iplh_linux[IPL_LOGSIZE]; # endif -# if SOLARIS +# if SOLARIS && defined(_KERNEL) extern kcondvar_t iplwait; extern struct pollhead iplpollhead[IPL_LOGSIZE]; # endif @@ -162,7 +165,6 @@ 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; @@ -265,8 +267,11 @@ u_int flags; 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; /* diff --git a/sys/contrib/ipfilter/netinet/ip_nat.c b/sys/contrib/ipfilter/netinet/ip_nat.c index 063f557..a6a77dc 100644 --- a/sys/contrib/ipfilter/netinet/ip_nat.c +++ b/sys/contrib/ipfilter/netinet/ip_nat.c @@ -16,9 +16,17 @@ #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(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ defined(_KERNEL) -# include "opt_ipfilter_log.h" +#if defined(__NetBSD_Version__) && (__NetBSD_Version__ < 399001400) +# include "opt_ipfilter_log.h" +# else +# include "opt_ipfilter.h" +# endif #endif #if !defined(_KERNEL) # include <stdio.h> @@ -148,14 +156,17 @@ u_int fr_nat_maxbucket = 0, fr_nat_maxbucket_reset = 1; u_32_t nat_masks = 0; u_32_t rdr_masks = 0; +u_long nat_last_force_flush = 0; ipnat_t **nat_rules = NULL; ipnat_t **rdr_rules = NULL; -hostmap_t **maptable = NULL; +hostmap_t **ipf_hm_maptable = NULL; +hostmap_t *ipf_hm_maplist = 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; +int fr_nat_doflush = 0; #ifdef IPFILTER_LOG int nat_logging = 1; #else @@ -172,6 +183,7 @@ int fr_nat_init = 0; extern int pfil_delayed_copy; #endif +static int nat_flush_entry __P((void *)); static int nat_flushtable __P((void)); static int nat_clearlist __P((void)); static void nat_addnat __P((struct ipnat *)); @@ -182,13 +194,13 @@ 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 int nat_extraflush __P((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 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)); @@ -198,6 +210,8 @@ static int 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 int nat_wildok __P((nat_t *, int, int, int, int)); +static int nat_getnext __P((ipftoken_t *, ipfgeniter_t *)); +static int nat_iterator __P((ipftoken_t *, ipfgeniter_t *)); /* ------------------------------------------------------------------------ */ @@ -235,11 +249,14 @@ int fr_natinit() 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); + KMALLOCS(ipf_hm_maptable, hostmap_t **, \ + sizeof(hostmap_t *) * ipf_hostmap_sz); + if (ipf_hm_maptable != NULL) + bzero((char *)ipf_hm_maptable, + sizeof(hostmap_t *) * ipf_hostmap_sz); else return -5; + ipf_hm_maplist = NULL; KMALLOCS(nat_stats.ns_bucketlen[0], u_long *, ipf_nattable_sz * sizeof(u_long)); @@ -439,7 +456,7 @@ u_32_t port; hv += src.s_addr; hv += dst.s_addr; hv %= HOSTMAP_SIZE; - for (hm = maptable[hv]; hm; hm = hm->hm_next) + for (hm = ipf_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) && ((np == NULL) || (np == hm->hm_ipnat)) && @@ -453,11 +470,16 @@ u_32_t port; 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 = ipf_hm_maplist; + hm->hm_pnext = &ipf_hm_maplist; + if (ipf_hm_maplist != NULL) + ipf_hm_maplist->hm_pnext = &hm->hm_next; + ipf_hm_maplist = hm; + hm->hm_hnext = ipf_hm_maptable[hv]; + hm->hm_phnext = ipf_hm_maptable + hv; + if (ipf_hm_maptable[hv] != NULL) + ipf_hm_maptable[hv]->hm_phnext = &hm->hm_hnext; + ipf_hm_maptable[hv] = hm; hm->hm_ipnat = np; hm->hm_srcip = src; hm->hm_dstip = dst; @@ -470,19 +492,27 @@ u_32_t port; /* ------------------------------------------------------------------------ */ -/* Function: nat_hostmapdel */ +/* Function: fr_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 fr_hostmapdel(hmp) +struct hostmap **hmp; { + struct hostmap *hm; + + hm = *hmp; + *hmp = NULL; + hm->hm_ref--; if (hm->hm_ref == 0) { + 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; @@ -612,18 +642,30 @@ u_32_t n; /* */ /* Processes an ioctl call made to operate on the IP Filter NAT device. */ /* ------------------------------------------------------------------------ */ -int fr_nat_ioctl(data, cmd, mode) +int fr_nat_ioctl(data, cmd, mode, uid, ctx) ioctlcmd_t cmd; caddr_t data; -int mode; +int mode, uid; +void *ctx; { ipnat_t *nat, *nt, *n = NULL, **np = NULL; int error = 0, ret, arg, getlock; ipnat_t natd; + SPL_INT(s); #if (BSD >= 199306) && defined(_KERNEL) - if ((securelevel >= 3) && (mode & FWRITE)) +# if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 399002000) + if ((mode & FWRITE) && + kauth_authorize_network(curlwp->l_cred, KAUTH_NETWORK_FIREWALL, + KAUTH_REQ_NETWORK_FIREWALL_FW, + NULL, NULL, NULL)) { return EPERM; + } +# else + if ((securelevel >= 3) && (mode & FWRITE)) { + return EPERM; + } +# endif #endif #if defined(__osf__) && defined(_KERNEL) @@ -646,9 +688,6 @@ int mode; } else { error = fr_inobj(data, &natd, IPFOBJ_IPNAT); } - - } else if (cmd == (ioctlcmd_t)SIOCIPFFL) { /* SIOCFLNAT & SIOCCNATL */ - BCOPYIN(data, &arg, sizeof(arg)); } if (error != 0) @@ -670,9 +709,13 @@ int mode; } 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 (bcmp((char *)&nat->in_flags, (char *)&n->in_flags, + IPN_CMPSIZ) == 0) { + if (nat->in_redir == NAT_REDIRECT && + nat->in_pnext != n->in_pnext) + continue; break; + } } switch (cmd) @@ -686,25 +729,37 @@ int mode; error = EPERM; else { tmp = ipflog_clear(IPL_LOGNAT); - BCOPYOUT((char *)&tmp, (char *)data, sizeof(tmp)); + error = BCOPYOUT((char *)&tmp, (char *)data, + sizeof(tmp)); + if (error != 0) + error = EFAULT; } break; } + case SIOCSETLG : if (!(mode & FWRITE)) error = EPERM; else { - BCOPYIN((char *)data, (char *)&nat_logging, - sizeof(nat_logging)); + error = BCOPYIN((char *)data, (char *)&nat_logging, + sizeof(nat_logging)); + if (error != 0) + error = EFAULT; } break; + case SIOCGETLG : - BCOPYOUT((char *)&nat_logging, (char *)data, - sizeof(nat_logging)); + error = BCOPYOUT((char *)&nat_logging, (char *)data, + sizeof(nat_logging)); + if (error != 0) + error = EFAULT; break; + case FIONREAD : arg = iplused[IPL_LOGNAT]; - BCOPYOUT(&arg, data, sizeof(arg)); + error = BCOPYOUT(&arg, data, sizeof(arg)); + if (error != 0) + error = EFAULT; break; #endif case SIOCADNAT : @@ -725,6 +780,7 @@ int mode; if (error == 0) nt = NULL; break; + case SIOCRMNAT : if (!(mode & FWRITE)) { error = EPERM; @@ -742,11 +798,13 @@ int mode; MUTEX_EXIT(&ipf_natio); 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_maptable = ipf_hm_maptable; + nat_stats.ns_maplist = ipf_hm_maplist; nat_stats.ns_nattab_sz = ipf_nattable_sz; nat_stats.ns_nattab_max = ipf_nattable_max; nat_stats.ns_rultab_sz = ipf_natrules_sz; @@ -754,8 +812,10 @@ int mode; nat_stats.ns_hostmap_sz = ipf_hostmap_sz; nat_stats.ns_instances = nat_instances; nat_stats.ns_apslist = ap_sess_list; + nat_stats.ns_ticks = fr_ticks; error = fr_outobj(data, &nat_stats, IPFOBJ_NATSTAT); break; + case SIOCGNATL : { natlookup_t nl; @@ -776,6 +836,7 @@ int mode; } break; } + case SIOCIPFFL : /* old SIOCFLNAT & SIOCCNATL */ if (!(mode & FWRITE)) { error = EPERM; @@ -784,23 +845,31 @@ int mode; if (getlock) { WRITE_ENTER(&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) + error = EFAULT; + else { + if (arg == 0) + ret = nat_flushtable(); + else if (arg == 1) + ret = nat_clearlist(); + else + ret = nat_extraflush(arg); + } + if (getlock) { RWLOCK_EXIT(&ipf_nat); } if (error == 0) { - BCOPYOUT(&ret, data, sizeof(ret)); + error = BCOPYOUT(&ret, data, sizeof(ret)); } break; + case SIOCPROXY : - error = appr_ioctl(data, cmd, mode); + error = appr_ioctl(data, cmd, mode, ctx); break; + case SIOCSTLCK : if (!(mode & FWRITE)) { error = EPERM; @@ -808,6 +877,7 @@ int mode; fr_lock(data, &fr_nat_lock); } break; + case SIOCSTPUT : if ((mode & FWRITE) != 0) { error = fr_natputent(data, getlock); @@ -815,6 +885,7 @@ int mode; error = EACCES; } break; + case SIOCSTGSZ : if (fr_nat_lock) { if (getlock) { @@ -827,6 +898,7 @@ int mode; } else error = EACCES; break; + case SIOCSTGET : if (fr_nat_lock) { if (getlock) { @@ -839,12 +911,46 @@ int mode; } else error = EACCES; break; + + case SIOCGENITER : + { + ipfgeniter_t iter; + ipftoken_t *token; + + SPL_SCHED(s); + error = fr_inobj(data, &iter, IPFOBJ_GENITER); + if (error == 0) { + token = ipf_findtoken(iter.igi_type, uid, ctx); + if (token != NULL) { + error = nat_iterator(token, &iter); + } + RWLOCK_EXIT(&ipf_tokens); + } + SPL_X(s); + break; + } + + case SIOCIPFDELTOK : + error = BCOPYIN((caddr_t)data, (caddr_t)&arg, sizeof(arg)); + if (error == 0) { + SPL_SCHED(s); + error = ipf_deltoken(arg, uid, ctx); + SPL_X(s); + } else { + error = EFAULT; + } + break; + + case SIOCGTQTAB : + error = fr_outobj(data, nat_tqb, IPFOBJ_STATETQTAB); + break; + default : error = EINVAL; break; } done: - if (nt) + if (nt != NULL) KFREE(nt); return error; } @@ -972,6 +1078,8 @@ int getlock; n->in_flags &= ~IPN_NOTSRC; nat_addnat(n); } + MUTEX_INIT(&n->in_lock, "ipnat rule lock"); + n = NULL; nat_stats.ns_rules++; #if SOLARIS @@ -1096,7 +1204,8 @@ caddr_t data; nat_t *nat, *n; natget_t ng; - BCOPYIN(data, &ng, sizeof(ng)); + if (BCOPYIN(data, &ng, sizeof(ng)) != 0) + return EFAULT; nat = ng.ng_ptr; if (!nat) { @@ -1106,7 +1215,8 @@ caddr_t data; * Empty list so the size returned is 0. Simple. */ if (nat == NULL) { - BCOPYOUT(&ng, data, sizeof(ng)); + if (BCOPYOUT(&ng, data, sizeof(ng)) != 0) + return EFAULT; return 0; } } else { @@ -1133,7 +1243,8 @@ caddr_t data; ng.ng_sz += aps->aps_psiz; } - BCOPYOUT(&ng, data, sizeof(ng)); + if (BCOPYOUT(&ng, data, sizeof(ng)) != 0) + return EFAULT; return 0; } @@ -1283,12 +1394,12 @@ int getlock; 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) { error = ENOMEM; @@ -1357,8 +1468,8 @@ int getlock; */ bzero((char *)&fin, sizeof(fin)); fin.fin_p = nat->nat_p; - fin.fin_ifp = nat->nat_ifps[0]; if (nat->nat_dir == NAT_OUTBOUND) { + fin.fin_ifp = nat->nat_ifps[0]; fin.fin_data[0] = ntohs(nat->nat_oport); fin.fin_data[1] = ntohs(nat->nat_outport); if (getlock) { @@ -1374,6 +1485,7 @@ int getlock; goto junkput; } } else if (nat->nat_dir == NAT_INBOUND) { + fin.fin_ifp = nat->nat_ifps[0]; fin.fin_data[0] = ntohs(nat->nat_outport); fin.fin_data[1] = ntohs(nat->nat_oport); if (getlock) { @@ -1501,7 +1613,7 @@ int getlock; junkput: if (fr != NULL) - fr_derefrule(&fr); + (void) fr_derefrule(&fr); if ((ipnn != NULL) && (ipnn != &ipn)) { KFREES(ipnn, ipn.ipn_dsize); @@ -1583,13 +1695,18 @@ int logtype; nat->nat_me = NULL; } - fr_deletequeueentry(&nat->nat_tqe); + if (nat->nat_tqe.tqe_ifq != NULL) + fr_deletequeueentry(&nat->nat_tqe); + + if (logtype == NL_EXPIRE) + nat_stats.ns_expire++; nat->nat_ref--; if (nat->nat_ref > 0) { MUTEX_EXIT(&ipf_nat_new); return; } + /* * At this point, nat_ref can be either 0 or -1 */ @@ -1600,10 +1717,10 @@ int logtype; #endif if (nat->nat_fr != NULL) - (void)fr_derefrule(&nat->nat_fr); + (void) fr_derefrule(&nat->nat_fr); if (nat->nat_hm != NULL) - nat_hostmapdel(nat->nat_hm); + fr_hostmapdel(&nat->nat_hm); /* * If there is an active reference from the nat entry to its parent @@ -1612,18 +1729,7 @@ int logtype; */ ipn = nat->nat_ptr; 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 - } + fr_ipnatderef(&ipn); } MUTEX_DESTROY(&nat->nat_lock); @@ -1779,8 +1885,7 @@ natinfo_t *ni; if (hm != NULL) in.s_addr = hm->hm_mapip.s_addr; } else if ((l == 1) && (hm != NULL)) { - nat_hostmapdel(hm); - hm = NULL; + fr_hostmapdel(&hm); } in.s_addr = ntohl(in.s_addr); @@ -2001,10 +2106,12 @@ nat_t *nat; natinfo_t *ni; { 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; @@ -2114,6 +2221,23 @@ natinfo_t *ni; in.s_addr = ntohl(fin->fin_daddr); } + /* + * 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 = 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) + return -1; + nat->nat_inip.s_addr = htonl(in.s_addr); nat->nat_outip = fin->fin_dst; nat->nat_oip = fin->fin_src; @@ -2197,6 +2321,7 @@ int direction; if (nat_stats.ns_inuse >= ipf_nattable_max) { nat_stats.ns_memfail++; + fr_nat_doflush = 1; return NULL; } @@ -2207,6 +2332,8 @@ int direction; 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 *); @@ -2250,6 +2377,7 @@ int direction; bzero((char *)nat, sizeof(*nat)); nat->nat_flags = flags; + nat->nat_redir = np->in_redir; if ((flags & NAT_SLAVE) == 0) { MUTEX_ENTER(&ipf_nat_new); @@ -2362,7 +2490,7 @@ int direction; badnat: nat_stats.ns_badnat++; if ((hm = nat->nat_hm) != NULL) - nat_hostmapdel(hm); + fr_hostmapdel(&hm); KFREE(nat); nat = NULL; done: @@ -2689,9 +2817,9 @@ u_int *nflags; int dir; { u_32_t sum1, sum2, sumd, sumd2; - struct in_addr in; + struct in_addr a1, a2; + int flags, dlen, odst; icmphdr_t *icmp; - int flags, dlen; u_short *csump; tcphdr_t *tcp; nat_t *nat; @@ -2742,33 +2870,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 @@ -2780,184 +2882,122 @@ 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_outip, OIP_DST(b)=nat_oip + * + * 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_outip, OIP_DST(a)=nat_oip + * + * 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(a)=nat_oip, OIP_DST(c)=nat_inip + * + * 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_oip, OIP_DST(c)=nat_inip + * */ - fix_datacksum(&oip->ip_sum, sumd); - /* Fix icmp cksum : IP Addr + Cksum */ - sumd2 = (sumd >> 16); + odst = (oip->ip_dst.s_addr == nat->nat_oip.s_addr) ? 1 : 0; + if (odst == 1) { + a1.s_addr = ntohl(nat->nat_inip.s_addr); + a2.s_addr = ntohl(oip->ip_src.s_addr); + oip->ip_src.s_addr = htonl(a1.s_addr); + } else { + a1.s_addr = ntohl(nat->nat_outip.s_addr); + a2.s_addr = ntohl(oip->ip_dst.s_addr); + oip->ip_dst.s_addr = htonl(a1.s_addr); + } - /* - * 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); + sumd = a2.s_addr - a1.s_addr; + if (sumd != 0) { + if (a1.s_addr > a2.s_addr) + sumd--; + sumd = ~sumd; - /* - * Fix ICMP checksum to compensate the UDP - * checksum adjustment. - */ - sumd2 = sumd << 1; - CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd; + 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; - /* * 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... except that the change in the port numbers should - * be offset by the checksum change, so we only need to change - * the ICMP checksum if we only change the ports. - * - * 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! + * 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_inport); + sum2 = ntohs(tcp->th_sport); - 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; + tcp->th_sport = htons(sum1); + } else { sum1 = ntohs(nat->nat_outport); sum2 = ntohs(tcp->th_dport); - } - if (mode == 1) { - /* - * Fix ICMP checksum to compensate port adjustment. - */ - tcp->th_sport = htons(sum1); + tcp->th_dport = htons(sum1); + } + sumd += sum1 - sum2; + 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 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_UDP) { - sumd = sum1 - sum2; - if ((dlen >= 8) && (*csump != 0)) { fix_datacksum(csump, sumd); } else { - sumd2 += sumd; + sumd2 = sum1 - sum2; + if (sum2 > sum1) + sumd2--; } - } - - /* - * 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) { - sumd = sum1 - sum2; - + } else if (oip->ip_p == IPPROTO_TCP) { if (dlen >= 18) { fix_datacksum(csump, sumd); } else { - sumd = sum2 - sum1 + 1; - sumd2 += sumd; - } - } - } 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) { - sumd = sum1 - sum2; - - if ((dlen >= 8) && (*csump != 0)) { - fix_datacksum(csump, sumd); - } else { - sumd2 += sumd; + sumd2 = sum2 - sum1; + if (sum1 > sum2) + sumd2--; } } - /* - * 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) { - sumd = sum1 - sum2; - - if (dlen >= 18) { - fix_datacksum(csump, sumd); - } else { - if (nat->nat_dir == NAT_INBOUND) - sumd = sum2 - sum1; - else - sumd = sum2 - sum1 + 1; - sumd2 += sumd; - } + if (sumd2 != 0) { + sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16); + 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); - fix_incksum(fin, &icmp->icmp_cksum, sumd2); - } } else if (((flags & IPN_ICMPQUERY) != 0) && (dlen >= 8)) { icmphdr_t *orgicmp; @@ -2967,7 +3007,7 @@ int dir; */ orgicmp = (icmphdr_t *)dp; - if (nat->nat_dir == NAT_OUTBOUND) { + if (odst == 1) { if (orgicmp->icmp_id != nat->nat_inport) { /* @@ -3635,9 +3675,11 @@ u_32_t *passp; 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_ifp; + if ((ifp != NULL) && (ifp != (void *)-1)) + fin->fin_ifp = ifp; + } ifp = fin->fin_ifp; if (!(fin->fin_flx & FI_SHORT) && (fin->fin_off == 0)) { @@ -3749,6 +3791,7 @@ maskloop: MUTEX_ENTER(&nat->nat_lock); nat->nat_ref++; MUTEX_EXIT(&nat->nat_lock); + nat->nat_touched = fr_ticks; fin->fin_nat = nat; } } else @@ -4042,8 +4085,8 @@ maskloop: MUTEX_ENTER(&nat->nat_lock); nat->nat_ref++; MUTEX_EXIT(&nat->nat_lock); + nat->nat_touched = fr_ticks; fin->fin_nat = nat; - fin->fin_state = nat->nat_state; } } else rval = natfailed; @@ -4287,9 +4330,9 @@ void fr_natunload() 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 (ipf_hm_maptable != NULL) { + KFREES(ipf_hm_maptable, sizeof(hostmap_t *) * ipf_hostmap_sz); + ipf_hm_maptable = NULL; } if (nat_stats.ns_bucketlen[0] != NULL) { KFREES(nat_stats.ns_bucketlen[0], @@ -4368,6 +4411,11 @@ void fr_natexpire() } } + if (fr_nat_doflush != 0) { + nat_extraflush(2); + fr_nat_doflush = 0; + } + RWLOCK_EXIT(&ipf_nat); SPL_X(s); } @@ -4577,6 +4625,35 @@ void *ifp; /* ------------------------------------------------------------------------ */ +/* Function: fr_ipnatderef */ +/* Returns: Nil */ +/* Parameters: isp(I) - pointer to pointer to NAT rule */ +/* Write Locks: ipf_nat */ +/* */ +/* ------------------------------------------------------------------------ */ +void fr_ipnatderef(inp) +ipnat_t **inp; +{ + ipnat_t *in; + + in = *inp; + *inp = NULL; + in->in_space++; + in->in_use--; + if (in->in_use == 0 && (in->in_flags & IPN_DELETE)) { + if (in->in_apr) + appr_free(in->in_apr); + KFREE(in); + nat_stats.ns_rules--; +#if SOLARIS + if (nat_stats.ns_rules == 0) + pfil_delayed_copy = 1; +#endif + } +} + + +/* ------------------------------------------------------------------------ */ /* Function: fr_natderef */ /* Returns: Nil */ /* Parameters: isp(I) - pointer to pointer to NAT table entry */ @@ -4857,3 +4934,407 @@ int rev; fr_queueappend(&nat->nat_tqe, nifq, nat); return; } + + +/* ------------------------------------------------------------------------ */ +/* Function: nat_getnext */ +/* Returns: int - 0 == ok, else error */ +/* Parameters: 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. */ +/* If we call ipf_freetoken, the accompanying pointer is set to NULL because*/ +/* ipf_freetoken will call a deref function for us and we dont want to call */ +/* that twice (second time would be in the second switch statement below. */ +/* ------------------------------------------------------------------------ */ +static int nat_getnext(t, itp) +ipftoken_t *t; +ipfgeniter_t *itp; +{ + hostmap_t *hm, *nexthm = NULL, zerohm; + ipnat_t *ipn, *nextipnat = NULL, zeroipn; + nat_t *nat, *nextnat = NULL, zeronat; + int error = 0, count; + ipftoken_t *freet; + char *dst; + + freet = NULL; + + READ_ENTER(&ipf_nat); + + switch (itp->igi_type) + { + case IPFGENITER_HOSTMAP : + hm = t->ipt_data; + if (hm == NULL) { + nexthm = ipf_hm_maplist; + } else { + nexthm = hm->hm_next; + } + break; + + case IPFGENITER_IPNAT : + ipn = t->ipt_data; + if (ipn == NULL) { + nextipnat = nat_list; + } else { + nextipnat = ipn->in_next; + } + break; + + case IPFGENITER_NAT : + nat = t->ipt_data; + if (nat == NULL) { + nextnat = nat_instances; + } else { + nextnat = nat->nat_next; + } + break; + default : + RWLOCK_EXIT(&ipf_nat); + return EINVAL; + } + + dst = itp->igi_data; + for (count = itp->igi_nitems; count > 0; count--) { + switch (itp->igi_type) + { + case IPFGENITER_HOSTMAP : + if (nexthm != NULL) { + if (nexthm->hm_next == NULL) { + freet = t; + count = 1; + hm = NULL; + } + if (count == 1) { + ATOMIC_INC32(nexthm->hm_ref); + } + } else { + bzero(&zerohm, sizeof(zerohm)); + nexthm = &zerohm; + count = 1; + } + break; + + case IPFGENITER_IPNAT : + if (nextipnat != NULL) { + if (nextipnat->in_next == NULL) { + freet = t; + count = 1; + ipn = NULL; + } + if (count == 1) { + MUTEX_ENTER(&nextipnat->in_lock); + nextipnat->in_use++; + MUTEX_EXIT(&nextipnat->in_lock); + } + } else { + bzero(&zeroipn, sizeof(zeroipn)); + nextipnat = &zeroipn; + count = 1; + } + break; + + case IPFGENITER_NAT : + if (nextnat != NULL) { + if (nextnat->nat_next == NULL) { + count = 1; + freet = t; + nat = NULL; + } + if (count == 1) { + MUTEX_ENTER(&nextnat->nat_lock); + nextnat->nat_ref++; + MUTEX_EXIT(&nextnat->nat_lock); + } + } else { + bzero(&zeronat, sizeof(zeronat)); + nextnat = &zeronat; + count = 1; + } + break; + default : + break; + } + RWLOCK_EXIT(&ipf_nat); + + if (freet != NULL) { + ipf_freetoken(freet); + freet = NULL; + } + + switch (itp->igi_type) + { + case IPFGENITER_HOSTMAP : + if (hm != NULL) { + WRITE_ENTER(&ipf_nat); + fr_hostmapdel(&hm); + RWLOCK_EXIT(&ipf_nat); + } + t->ipt_data = nexthm; + error = COPYOUT(nexthm, dst, sizeof(*nexthm)); + if (error != 0) + error = EFAULT; + else + dst += sizeof(*nexthm); + break; + + case IPFGENITER_IPNAT : + if (ipn != NULL) + fr_ipnatderef(&ipn); + t->ipt_data = nextipnat; + error = COPYOUT(nextipnat, dst, sizeof(*nextipnat)); + if (error != 0) + error = EFAULT; + else + dst += sizeof(*nextipnat); + break; + + case IPFGENITER_NAT : + if (nat != NULL) + fr_natderef(&nat); + t->ipt_data = nextnat; + error = COPYOUT(nextnat, dst, sizeof(*nextnat)); + if (error != 0) + error = EFAULT; + else + dst += sizeof(*nextnat); + break; + } + + if ((count == 1) || (error != 0)) + break; + + READ_ENTER(&ipf_nat); + + switch (itp->igi_type) + { + case IPFGENITER_HOSTMAP : + hm = nexthm; + nexthm = hm->hm_next; + break; + + case IPFGENITER_IPNAT : + ipn = nextipnat; + nextipnat = ipn->in_next; + break; + + case IPFGENITER_NAT : + nat = nextnat; + nextnat = nat->nat_next; + break; + default : + break; + } + } + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: nat_iterator */ +/* Returns: int - 0 == ok, else error */ +/* Parameters: token(I) - pointer to ipftoken structure */ +/* itp(I) - pointer to ipfgeniter_t 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 nat_iterator(token, itp) +ipftoken_t *token; +ipfgeniter_t *itp; +{ + int error; + + if (itp->igi_data == NULL) + return EFAULT; + + token->ipt_subtype = itp->igi_type; + + switch (itp->igi_type) + { + case IPFGENITER_HOSTMAP : + case IPFGENITER_IPNAT : + case IPFGENITER_NAT : + error = nat_getnext(token, itp); + break; + + case IPFGENITER_NATFRAG : +#ifdef USE_MUTEXES + error = fr_nextfrag(token, itp, &ipfr_natlist, + &ipfr_nattail, &ipf_natfrag); +#else + error = fr_nextfrag(token, itp, &ipfr_natlist, &ipfr_nattail); +#endif + break; + default : + error = EINVAL; + break; + } + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: nat_extraflush */ +/* Returns: int - 0 == success, -1 == failure */ +/* Parameters: 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 nat_extraflush(which) +int which; +{ + ipftq_t *ifq, *ifqnext; + nat_t *nat, **natp; + ipftqent_t *tqn; + int removed; + SPL_INT(s); + + removed = 0; + + SPL_NET(s); + + switch (which) + { + case 0 : + /* + * Style 0 flush removes everything... + */ + for (natp = &nat_instances; ((nat = *natp) != NULL); ) { + nat_delete(nat, NL_FLUSH); + removed++; + } + break; + + case 1 : + /* + * Since we're only interested in things that are closing, + * we can start with the appropriate timeout queue. + */ + for (ifq = nat_tqb + 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_p != IPPROTO_TCP) + break; + nat_delete(nat, NL_EXPIRE); + removed++; + } + } + + /* + * Also need to look through the user defined queues. + */ + for (ifq = nat_utqe; ifq != NULL; ifq = ifqnext) { + ifqnext = ifq->ifq_next; + for (tqn = ifq->ifq_head; tqn != NULL; ) { + nat = tqn->tqe_parent; + tqn = tqn->tqe_next; + if (nat->nat_p != IPPROTO_TCP) + continue; + + if ((nat->nat_tcpstate[0] > + IPF_TCPS_ESTABLISHED) && + (nat->nat_tcpstate[1] > + IPF_TCPS_ESTABLISHED)) { + nat_delete(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 : + tqn = nat_tqb[which].ifq_head; + while (tqn != NULL) { + nat = tqn->tqe_parent; + tqn = tqn->tqe_next; + nat_delete(nat, NL_FLUSH); + removed++; + } + break; + + default : + if (which < 30) + break; + + /* + * 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 = &nat_instances; ((nat = *natp) != NULL); ) { + if (fr_ticks - nat->nat_touched > which) { + nat_delete(nat, NL_FLUSH); + removed++; + } else + natp = &nat->nat_next; + } + break; + } + + if (which != 2) { + SPL_X(s); + return removed; + } + + /* + * Asked to remove inactive entries because the table is full. + */ + if (fr_ticks - nat_last_force_flush > IPF_TTLVAL(5)) { + nat_last_force_flush = fr_ticks; + removed = ipf_queueflush(nat_flush_entry, nat_tqb, nat_utqe); + } + + SPL_X(s); + return removed; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: nat_flush_entry */ +/* Returns: 0 - always succeeds */ +/* Parameters: 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 nat_flush_entry(entry) +void *entry; +{ + nat_delete(entry, NL_FLUSH); + return 0; +} diff --git a/sys/contrib/ipfilter/netinet/ip_nat.h b/sys/contrib/ipfilter/netinet/ip_nat.h index e1bec96..5484eac 100644 --- a/sys/contrib/ipfilter/netinet/ip_nat.h +++ b/sys/contrib/ipfilter/netinet/ip_nat.h @@ -124,6 +124,7 @@ typedef struct nat { int nat_hv[2]; char nat_ifnames[2][LIFNAMSIZ]; int nat_rev; /* 0 = forward, 1 = reverse */ + int nat_redir; /* copy of in_redir */ } nat_t; #define nat_inip nat_inip6.in4 @@ -136,6 +137,8 @@ typedef struct nat { #define nat_seq nat_un.nat_uni.ici_seq #define nat_id nat_un.nat_uni.ici_id #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 @@ -152,7 +155,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,6 +174,7 @@ typedef struct nat { #define NAT_DEBUG 0x800000 typedef struct ipnat { + 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 */ @@ -296,25 +300,6 @@ typedef struct natget { } natget_t; -#undef tr_flags -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,6 +307,8 @@ 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; @@ -373,8 +360,9 @@ typedef struct natstat { u_int ns_trpntab_sz; u_int ns_hostmap_sz; nat_t *ns_instances; - nattrpnt_t *ns_trpntlist; + hostmap_t *ns_maplist; u_long *ns_bucketlen[2]; + u_long ns_ticks; } natstat_t; typedef struct natlog { @@ -427,6 +415,7 @@ 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 int fr_nat_doflush; extern void fr_natsync __P((void *)); extern u_long fr_defnatage; extern u_long fr_defnaticmpage; @@ -444,7 +433,7 @@ extern natstat_t nat_stats; #if defined(__OpenBSD__) extern void nat_ifdetach __P((void *)); #endif -extern int fr_nat_ioctl __P((caddr_t, ioctlcmd_t, int)); +extern int fr_nat_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *)); 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, @@ -469,9 +458,11 @@ 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_ipnatderef __P((ipnat_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 void fr_hostmapdel __P((hostmap_t **)); #endif /* __IP_NAT_H__ */ diff --git a/sys/contrib/ipfilter/netinet/ip_proxy.c b/sys/contrib/ipfilter/netinet/ip_proxy.c index eb84cd1..b04331e 100644 --- a/sys/contrib/ipfilter/netinet/ip_proxy.c +++ b/sys/contrib/ipfilter/netinet/ip_proxy.c @@ -104,7 +104,7 @@ struct file; /* END OF INCLUDES */ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_proxy.c,v 2.62.2.16 2006/03/29 11:19:56 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_proxy.c,v 2.62.2.20 2007/05/31 12:27:36 darrenr Exp $"; #endif static int appr_fixseqack __P((fr_info_t *, ip_t *, ap_session_t *, int )); @@ -122,7 +122,7 @@ aproxy_t *ap_proxylist = NULL; aproxy_t ap_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 }, + ippr_ftp_new, NULL, ippr_ftp_in, ippr_ftp_out, NULL, NULL }, #endif #ifdef IPF_IRC_PROXY { NULL, "irc", (char)IPPROTO_TCP, 0, 0, ippr_irc_init, ippr_irc_fini, @@ -156,9 +156,9 @@ aproxy_t ap_proxies[] = { #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 }, + ippr_h323_new, ippr_h323_del, ippr_h323_in, NULL, NULL, NULL }, { NULL, "h245", (char)IPPROTO_TCP, 0, 0, NULL, NULL, - ippr_h245_new, NULL, NULL, ippr_h245_out, NULL }, + ippr_h245_new, NULL, NULL, ippr_h245_out, NULL, NULL }, #endif #ifdef IPF_RPCB_PROXY # if 0 @@ -170,7 +170,7 @@ aproxy_t ap_proxies[] = { ippr_rpcb_init, ippr_rpcb_fini, ippr_rpcb_new, ippr_rpcb_del, ippr_rpcb_in, ippr_rpcb_out, NULL, NULL }, #endif - { NULL, "", '\0', 0, 0, NULL, NULL, NULL, NULL } + { NULL, "", '\0', 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } }; /* @@ -192,7 +192,7 @@ aproxy_t *ap; 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))) { @@ -289,10 +289,11 @@ ipnat_t *nat; } -int appr_ioctl(data, cmd, mode) +int appr_ioctl(data, cmd, mode, ctx) caddr_t data; ioctlcmd_t cmd; int mode; +void *ctx; { ap_ctl_t ctl; caddr_t ptr; @@ -814,7 +815,7 @@ int inc; if (ipf_proxy_debug > 8) printf("appr_fixseqack: seq %x ack %x\n", - ntohl(tcp->th_seq), ntohl(tcp->th_ack)); + (u_32_t)ntohl(tcp->th_seq), (u_32_t)ntohl(tcp->th_ack)); return ch ? 2 : 0; } diff --git a/sys/contrib/ipfilter/netinet/ip_proxy.h b/sys/contrib/ipfilter/netinet/ip_proxy.h index 71c1b81..1bcfc60 100644 --- a/sys/contrib/ipfilter/netinet/ip_proxy.h +++ b/sys/contrib/ipfilter/netinet/ip_proxy.h @@ -443,6 +443,7 @@ 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 ipf_proxy_debug; extern int appr_add __P((aproxy_t *)); extern int appr_ctl __P((ap_ctl_t *)); @@ -456,6 +457,6 @@ 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 appr_ioctl __P((caddr_t, ioctlcmd_t, int, void *)); #endif /* __IP_PROXY_H__ */ diff --git a/sys/contrib/ipfilter/netinet/ip_raudio_pxy.c b/sys/contrib/ipfilter/netinet/ip_raudio_pxy.c index 607fd74..2729dc6 100644 --- a/sys/contrib/ipfilter/netinet/ip_raudio_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_raudio_pxy.c @@ -6,7 +6,7 @@ * * 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: ip_raudio_pxy.c,v 1.40.2.4 2006/07/14 06:12:17 darrenr Exp $ */ #define IPF_RAUDIO_PROXY @@ -307,7 +307,7 @@ nat_t *nat; (void) fr_addstate(&fi, NULL, (sp ? 0 : SI_W_SPORT)); if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); + fr_statederef((ipstate_t **)&fi.fin_state); } } @@ -327,7 +327,7 @@ nat_t *nat; (void) fr_addstate(&fi, NULL, SI_W_DPORT); if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); + fr_statederef((ipstate_t **)&fi.fin_state); } } diff --git a/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c b/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c index c0d755a..dc92bf5 100644 --- a/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c @@ -5,7 +5,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ip_rcmd_pxy.c,v 1.41.2.6 2006/04/01 10:14:54 darrenr Exp $ + * $Id: ip_rcmd_pxy.c,v 1.41.2.7 2006/07/14 06:12:18 darrenr Exp $ * * Simple RCMD transparent proxy for in-kernel use. For use with the NAT * code. @@ -207,7 +207,7 @@ nat_t *nat; } (void) fr_addstate(&fi, NULL, SI_W_DPORT); if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); + fr_statederef((ipstate_t **)&fi.fin_state); } ip->ip_len = slen; ip->ip_src = swip; diff --git a/sys/contrib/ipfilter/netinet/ip_state.c b/sys/contrib/ipfilter/netinet/ip_state.c index ae17dbb..39a094a 100644 --- a/sys/contrib/ipfilter/netinet/ip_state.c +++ b/sys/contrib/ipfilter/netinet/ip_state.c @@ -17,7 +17,11 @@ #include <sys/file.h> #if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ defined(_KERNEL) -# include "opt_ipfilter_log.h" +# if (__NetBSD_Version__ < 399001400) +# include "opt_ipfilter_log.h" +# else +# include "opt_ipfilter.h" +# endif #endif #if defined(_KERNEL) && defined(__FreeBSD_version) && \ (__FreeBSD_version >= 400000) && !defined(KLD_MODULE) @@ -109,7 +113,7 @@ 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.41 2006/04/01 10:16:28 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.186.2.69 2007/05/26 13:05:14 darrenr Exp $"; #endif static ipstate_t **ips_table = NULL; @@ -125,8 +129,9 @@ static ipstate_t *fr_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 int fr_state_flush_entry __P((void *)); static ips_stat_t *fr_statetstats __P((void)); -static void fr_delstate __P((ipstate_t *, int)); +static int 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 *)); @@ -135,6 +140,8 @@ 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 *)); +static int fr_stateiter __P((ipftoken_t *, ipfgeniter_t *)); +static int fr_stgettable __P((char *)); int fr_stputent __P((caddr_t)); int fr_stgetent __P((caddr_t)); @@ -145,9 +152,10 @@ int fr_stgetent __P((caddr_t)); u_long fr_tcpidletimeout = FIVE_DAYS, fr_tcpclosewait = IPF_TTLVAL(2 * TCP_MSL), - fr_tcplastack = IPF_TTLVAL(2 * TCP_MSL), + fr_tcplastack = IPF_TTLVAL(30), fr_tcptimeout = IPF_TTLVAL(2 * TCP_MSL), - fr_tcpclosed = IPF_TTLVAL(60), + fr_tcptimewait = IPF_TTLVAL(2 * TCP_MSL), + fr_tcpclosed = IPF_TTLVAL(30), fr_tcphalfclosed = IPF_TTLVAL(2 * 3600), /* 2 hours */ fr_udptimeout = IPF_TTLVAL(120), fr_udpacktimeout = IPF_TTLVAL(12), @@ -167,6 +175,7 @@ ipftq_t ips_tqtqb[IPF_TCP_NSTATES], ips_iptq, ips_icmptq, ips_icmpacktq, + ips_deletetq, *ips_utqe = NULL; #ifdef IPFILTER_LOG int ipstate_logging = 1; @@ -241,6 +250,7 @@ int fr_stateinit() fr_state_maxbucket *= 2; } + ips_stats.iss_tcptab = ips_tqtqb; fr_sttab_init(ips_tqtqb); ips_tqtqb[IPF_TCP_NSTATES - 1].ifq_next = &ips_udptq; ips_udptq.ifq_ttl = (u_long)fr_udptimeout; @@ -272,7 +282,13 @@ int fr_stateinit() 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; + ips_iptq.ifq_next = &ips_deletetq; + ips_deletetq.ifq_ttl = (u_long)1; + ips_deletetq.ifq_ref = 1; + ips_deletetq.ifq_head = NULL; + ips_deletetq.ifq_tail = &ips_deletetq.ifq_head; + MUTEX_INIT(&ips_deletetq.ifq_lock, "state delete queue"); + ips_deletetq.ifq_next = NULL; RWLOCK_INIT(&ipf_state, "ipf IP state rwlock"); MUTEX_INIT(&ipf_stinsert, "ipf state insert mutex"); @@ -297,7 +313,7 @@ void fr_stateunload() ipstate_t *is; while ((is = ips_list) != NULL) - fr_delstate(is, 0); + fr_delstate(is, ISL_UNLOAD); /* * Proxy timeout queues are not cleaned here because although they @@ -323,6 +339,7 @@ void fr_stateunload() MUTEX_DESTROY(&ips_udpacktq.ifq_lock); MUTEX_DESTROY(&ips_icmpacktq.ifq_lock); MUTEX_DESTROY(&ips_iptq.ifq_lock); + MUTEX_DESTROY(&ips_deletetq.ifq_lock); } if (ips_table != NULL) { @@ -416,12 +433,14 @@ caddr_t data; /* */ /* Processes an ioctl call made to operate on the IP Filter state device. */ /* ------------------------------------------------------------------------ */ -int fr_state_ioctl(data, cmd, mode) +int fr_state_ioctl(data, cmd, mode, uid, ctx) caddr_t data; ioctlcmd_t cmd; -int mode; +int mode, uid; +void *ctx; { int arg, ret, error = 0; + SPL_INT(s); switch (cmd) { @@ -431,29 +450,37 @@ int mode; case SIOCDELST : error = fr_state_remove(data); break; + /* * Flush the state table */ case SIOCIPFFL : - BCOPYIN(data, (char *)&arg, sizeof(arg)); - if (arg == 0 || arg == 1) { + error = BCOPYIN(data, (char *)&arg, sizeof(arg)); + if (error != 0) { + error = EFAULT; + } else { WRITE_ENTER(&ipf_state); ret = fr_state_flush(arg, 4); RWLOCK_EXIT(&ipf_state); - BCOPYOUT((char *)&ret, data, sizeof(ret)); - } else - error = EINVAL; + error = BCOPYOUT((char *)&ret, data, sizeof(ret)); + if (error != 0) + error = EFAULT; + } break; + #ifdef USE_INET6 case SIOCIPFL6 : - BCOPYIN(data, (char *)&arg, sizeof(arg)); - if (arg == 0 || arg == 1) { + error = BCOPYIN(data, (char *)&arg, sizeof(arg)); + if (error != 0) { + error = EFAULT; + } else { WRITE_ENTER(&ipf_state); ret = fr_state_flush(arg, 6); RWLOCK_EXIT(&ipf_state); - BCOPYOUT((char *)&ret, data, sizeof(ret)); - } else - error = EINVAL; + error = BCOPYOUT((char *)&ret, data, sizeof(ret)); + if (error != 0) + error = EFAULT; + } break; #endif #ifdef IPFILTER_LOG @@ -467,9 +494,12 @@ int mode; int tmp; tmp = ipflog_clear(IPL_LOGSTATE); - BCOPYOUT((char *)&tmp, data, sizeof(tmp)); + error = BCOPYOUT((char *)&tmp, data, sizeof(tmp)); + if (error != 0) + error = EFAULT; } break; + /* * Turn logging of state information on/off. */ @@ -477,31 +507,41 @@ int mode; if (!(mode & FWRITE)) error = EPERM; else { - BCOPYIN((char *)data, (char *)&ipstate_logging, - sizeof(ipstate_logging)); + error = BCOPYIN((char *)data, (char *)&ipstate_logging, + sizeof(ipstate_logging)); + if (error != 0) + error = EFAULT; } break; + /* * Return the current state of logging. */ case SIOCGETLG : - BCOPYOUT((char *)&ipstate_logging, (char *)data, - sizeof(ipstate_logging)); + error = BCOPYOUT((char *)&ipstate_logging, (char *)data, + sizeof(ipstate_logging)); + if (error != 0) + 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)); + error = BCOPYOUT((char *)&arg, data, sizeof(arg)); + if (error != 0) + error = EFAULT; break; #endif + /* * Get the current state statistics. */ case SIOCGETFS : error = fr_outobj(data, fr_statetstats(), IPFOBJ_STATESTAT); break; + /* * Lock/Unlock the state table. (Locking prevents any changes, which * means no packets match). @@ -513,6 +553,7 @@ int mode; fr_lock(data, &fr_state_lock); } break; + /* * Add an entry to the current state table. */ @@ -523,6 +564,7 @@ int mode; } error = fr_stputent(data); break; + /* * Get a state table entry. */ @@ -533,6 +575,56 @@ int mode; } error = fr_stgetent(data); break; + + /* + * Return a copy of the hash table bucket lengths + */ + case SIOCSTAT1 : + error = BCOPYOUT(ips_stats.iss_bucketlen, data, + fr_statesize * sizeof(u_long)); + if (error != 0) + error = EFAULT; + break; + + case SIOCGENITER : + { + ipftoken_t *token; + ipfgeniter_t iter; + + error = fr_inobj(data, &iter, IPFOBJ_GENITER); + if (error != 0) + break; + + SPL_SCHED(s); + token = ipf_findtoken(IPFGENITER_STATE, uid, ctx); + if (token != NULL) + error = fr_stateiter(token, &iter); + else + error = ESRCH; + RWLOCK_EXIT(&ipf_tokens); + SPL_X(s); + break; + } + + case SIOCGTABL : + error = fr_stgettable(data); + break; + + case SIOCIPFDELTOK : + error = BCOPYIN(data, (char *)&arg, sizeof(arg)); + if (error != 0) { + error = EFAULT; + } else { + SPL_SCHED(s); + error = ipf_deltoken(arg, uid, ctx); + SPL_X(s); + } + break; + + case SIOCGTQTAB : + error = fr_outobj(data, ips_tqtqb, IPFOBJ_STATETQTAB); + break; + default : error = EINVAL; break; @@ -672,7 +764,8 @@ caddr_t data; fr->fr_data = NULL; fr->fr_type = FR_T_NONE; - fr_resolvedest(&fr->fr_tif, fr->fr_v); + fr_resolvedest(&fr->fr_tifs[0], fr->fr_v); + fr_resolvedest(&fr->fr_tifs[1], fr->fr_v); fr_resolvedest(&fr->fr_dif, fr->fr_v); /* @@ -821,7 +914,6 @@ u_int flags; frentry_t *fr; tcphdr_t *tcp; grehdr_t *gre; - void *ifp; int out; if (fr_state_lock || @@ -843,7 +935,7 @@ u_int flags; */ fr = fin->fin_fr; if (fr != NULL) { - if ((ips_num == fr_statemax) && (fr->fr_statemax == 0)) { + if ((ips_num >= fr_statemax) && (fr->fr_statemax == 0)) { ATOMIC_INCL(ips_stats.iss_max); fr_state_doflush = 1; return NULL; @@ -851,7 +943,6 @@ u_int flags; if ((fr->fr_statemax != 0) && (fr->fr_statecnt >= fr->fr_statemax)) { ATOMIC_INCL(ips_stats.iss_maxref); - fr_state_doflush = 1; return NULL; } } @@ -1086,30 +1177,41 @@ u_int flags; is->is_tag = fr->fr_logtag; + /* + * 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][0] == '-' && + fr->fr_ifnames[out << 1][1] == '\0')) { + is->is_ifp[out << 1] = fr->fr_ifas[0]; + strncpy(is->is_ifname[out << 1], fr->fr_ifnames[0], + sizeof(fr->fr_ifnames[0])); + } else { + is->is_ifp[out << 1] = fin->fin_ifp; + COPYIFNAME(fin->fin_ifp, is->is_ifname[out << 1]); + } + is->is_ifp[(out << 1) + 1] = fr->fr_ifas[1]; + strncpy(is->is_ifname[(out << 1) + 1], fr->fr_ifnames[1], + sizeof(fr->fr_ifnames[1])); + is->is_ifp[(1 - out) << 1] = fr->fr_ifas[2]; - is->is_ifp[((1 - out) << 1) + 1] = fr->fr_ifas[3]; + strncpy(is->is_ifname[((1 - out) << 1)], fr->fr_ifnames[2], + sizeof(fr->fr_ifnames[2])); - 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]); - } + is->is_ifp[((1 - out) << 1) + 1] = fr->fr_ifas[3]; + strncpy(is->is_ifname[((1 - out) << 1) + 1], fr->fr_ifnames[3], + sizeof(fr->fr_ifnames[3])); } 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]); + if (fin->fin_ifp != NULL) { + is->is_ifp[out << 1] = fin->fin_ifp; + COPYIFNAME(fin->fin_ifp, is->is_ifname[out << 1]); + } } /* @@ -1326,6 +1428,22 @@ ipstate_t *is; tdata = &is->is_tcp.ts_data[source]; MUTEX_ENTER(&is->is_lock); + + /* + * 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; + fr_movequeue(&is->is_sti, is->is_sti.tqe_ifq, + &ips_deletetq); + MUTEX_ENTER(&is->is_lock); + return 0; + } + } + if (fr_tcpinwindow(fin, fdata, tdata, tcp, is->is_flags)) { #ifdef IPFILTER_SCAN if (is->is_flags & (IS_SC_CLIENT|IS_SC_SERVER)) { @@ -1376,8 +1494,9 @@ ipstate_t *is; } ret = 1; - } else + } else { fin->fin_flx |= FI_OOW; + } MUTEX_EXIT(&is->is_lock); return ret; } @@ -1723,9 +1842,9 @@ 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) @@ -1995,7 +2114,7 @@ fr_info_t *fin; # 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 @@ -2025,7 +2144,6 @@ fr_info_t *fin; 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); ofin.fin_ifp = fin->fin_ifp; ofin.fin_out = !fin->fin_out; @@ -2285,6 +2403,13 @@ icmp6again: hvm = DOUBLE_HASH(hv); for (isp = &ips_table[hvm]; ((is = *isp) != NULL); ) { isp = &is->is_hnext; + /* + * If a connection is about to be deleted, no packets + * are allowed to match it. + */ + if (is->is_sti.tqe_ifq == &ips_deletetq) + continue; + if ((is->is_p != pr) || (is->is_v != v)) continue; is = fr_matchsrcdst(fin, is, &src, &dst, NULL, FI_CMP); @@ -2614,8 +2739,6 @@ matched: 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_state = is; is->is_touched = fr_ticks; @@ -2751,7 +2874,7 @@ void *ifp; /* ------------------------------------------------------------------------ */ /* Function: fr_delstate */ -/* Returns: Nil */ +/* Returns: int - 0 = entry deleted, else reference count on struct */ /* Parameters: is(I) - pointer to state structure to delete */ /* why(I) - if not 0, log reason why it was deleted */ /* Write Locks: ipf_state */ @@ -2760,7 +2883,7 @@ void *ifp; /* and timeout queue lists. Make adjustments to hash table statistics and */ /* global counters as required. */ /* ------------------------------------------------------------------------ */ -static void fr_delstate(is, why) +static int fr_delstate(is, why) ipstate_t *is; int why; { @@ -2771,16 +2894,6 @@ int why; * 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) @@ -2808,7 +2921,8 @@ int why; /* * Next, remove it from the timeout queue it is in. */ - fr_deletequeueentry(&is->is_sti); + if (is->is_sti.tqe_ifq != NULL) + fr_deletequeueentry(&is->is_sti); if (is->is_me != NULL) { *is->is_me = NULL; @@ -2817,11 +2931,15 @@ int why; /* * 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. + * but note that at this point it is now an orphan. How can this + * be? fr_state_flush() calls fr_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. */ is->is_ref--; if (is->is_ref > 0) - return; + return is->is_ref; if (is->is_tqehead[0] != NULL) { if (fr_deletetimeoutqueue(is->is_tqehead[0]) == 0) @@ -2840,6 +2958,19 @@ int why; (void) ipsc_detachis(is); #endif + /* + * Now remove it from the linked list of known states + */ + 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 (ipstate_logging != 0 && why != 0) ipstate_log(is, why); @@ -2850,12 +2981,14 @@ int why; if (is->is_rule != NULL) { is->is_rule->fr_statecnt--; - (void)fr_derefrule(&is->is_rule); + (void) fr_derefrule(&is->is_rule); } MUTEX_DESTROY(&is->is_lock); KFREE(is); ips_num--; + + return 0; } @@ -2941,42 +3074,115 @@ int which, proto; ipftq_t *ifq, *ifqnext; ipftqent_t *tqe, *tqn; ipstate_t *is, **isp; - int delete, removed; - long try, maxtick; - u_long interval; + 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 : + /* + * Style 0 flush removes everything... + */ + for (isp = &ips_list; ((is = *isp) != NULL); ) { + if ((proto != 0) && (is->is_v != proto)) { + isp = &is->is_next; + continue; + } + if (fr_delstate(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 : + /* + * Since we're only interested in things that are closing, + * we can start with the appropriate timeout queue. + */ + for (ifq = ips_tqtqb + 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 (fr_delstate(is, ISL_EXPIRE) == 0) + removed++; + } } - if (delete) { - fr_delstate(is, ISL_FLUSH); - removed++; - } else + /* + * Also need to look through the user defined queues. + */ + for (ifq = ips_utqe; ifq != NULL; ifq = ifqnext) { + ifqnext = 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 (fr_delstate(is, ISL_EXPIRE) == 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 : + tqn = ips_tqtqb[which].ifq_head; + while (tqn != NULL) { + tqe = tqn; + tqn = tqe->tqe_next; + is = tqe->tqe_parent; + if (fr_delstate(is, ISL_FLUSH) == 0) + removed++; + } + break; + + default : + if (which < 30) + break; + + /* + * 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 = &ips_list; ((is = *isp) != NULL); ) { + if ((proto == 0) || (is->is_v == proto)) { + if (fr_ticks - is->is_touched > which) { + if (fr_delstate(is, ISL_FLUSH) == 0) { + removed++; + continue; + } + } + } isp = &is->is_next; + } + break; } if (which != 2) { @@ -2985,83 +3191,35 @@ int which, proto; } /* - * 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. + * Asked to remove inactive entries because the table is full. */ - 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 (fr_ticks - ips_last_force_flush > IPF_TTLVAL(5)) { + ips_last_force_flush = fr_ticks; + removed = ipf_queueflush(fr_state_flush_entry, ips_tqtqb, + ips_utqe); } -force_flush_skipped: + SPL_X(s); return removed; } +/* ------------------------------------------------------------------------ */ +/* Function: fr_state_flush_entry */ +/* Returns: int - 0 = entry deleted, else not deleted */ +/* Parameters: entry(I) - pointer to state structure to delete */ +/* Write Locks: ipf_state */ +/* */ +/* This function is a stepping stone between ipf_queueflush() and */ +/* fr_delstate(). It is used so we can provide a uniform interface via the */ +/* ipf_queueflush() function. */ +/* ------------------------------------------------------------------------ */ +static int fr_state_flush_entry(entry) +void *entry; +{ + return fr_delstate(entry, ISL_FLUSH); +} + /* ------------------------------------------------------------------------ */ /* Function: fr_tcp_age */ @@ -3091,6 +3249,25 @@ 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) @@ -3122,16 +3299,16 @@ int flags; 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; } @@ -3150,7 +3327,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; @@ -3171,11 +3348,7 @@ 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 @@ -3216,7 +3389,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 @@ -3245,7 +3418,7 @@ int flags; } break; - case IPF_TCPS_HALF_ESTAB: /* 4 */ + case IPF_TCPS_HALF_ESTAB: /* 3 */ if (tcpflags & TH_FIN) { nstate = IPF_TCPS_FIN_WAIT_1; rval = 1; @@ -3260,7 +3433,7 @@ int flags; */ switch (ostate) { - case IPF_TCPS_CLOSED : + case IPF_TCPS_LISTEN : case IPF_TCPS_SYN_SENT : case IPF_TCPS_SYN_RECEIVED : rval = 1; @@ -3276,7 +3449,7 @@ int flags; } break; - case IPF_TCPS_ESTABLISHED: /* 5 */ + case IPF_TCPS_ESTABLISHED: /* 4 */ rval = 1; if (tcpflags & TH_FIN) { /* @@ -3284,7 +3457,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? @@ -3309,7 +3486,7 @@ int flags; } break; - case IPF_TCPS_CLOSE_WAIT: /* 6 */ + case IPF_TCPS_CLOSE_WAIT: /* 5 */ rval = 1; if (tcpflags & TH_FIN) { /* @@ -3327,7 +3504,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) { @@ -3355,11 +3532,14 @@ 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) /* @@ -3378,17 +3558,30 @@ int flags; */ break; - case IPF_TCPS_FIN_WAIT_2: /* 10 */ + case IPF_TCPS_FIN_WAIT_2: /* 9 */ + /* NOT USED */ +#if 0 rval = 1; - if ((tcpflags & TH_OPENING) == TH_OPENING) + if ((tcpflags & TH_OPENING) == TH_OPENING) { nstate = IPF_TCPS_SYN_RECEIVED; - else if (tcpflags & TH_SYN) + } else if (tcpflags & TH_SYN) { nstate = IPF_TCPS_SYN_SENT; + } else if ((tcpflags & (TH_FIN|TH_ACK)) != 0) { + nstate = IPF_TCPS_TIME_WAIT; + } +#endif break; - case IPF_TCPS_TIME_WAIT: /* 11 */ + case IPF_TCPS_TIME_WAIT: /* 10 */ /* we're in 2MSL timeout now */ - rval = 1; + rval = 2; + if (ostate == IPF_TCPS_LAST_ACK) { + nstate = IPF_TCPS_CLOSED; + } + break; + + case IPF_TCPS_CLOSED: /* 11 */ + rval = 2; break; default : @@ -3541,7 +3734,7 @@ fr_info_t *fin; if (fin->fin_plen < sizeof(*oip6)) 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; @@ -3562,7 +3755,6 @@ fr_info_t *fin; oip6->ip6_plen = 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); ofin.fin_flx &= ~(FI_BAD|FI_SHORT); oip6->ip6_plen = savelen; @@ -3709,7 +3901,7 @@ ipftq_t *tqp; 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_TIME_WAIT].ifq_ttl = fr_tcptimewait; tqp[IPF_TCPS_HALF_ESTAB].ifq_ttl = fr_tcptimeout; } @@ -3755,40 +3947,11 @@ 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; +void fr_statederef(isp) 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 + ipstate_t *is; - fin = fin; /* LINT */ is = *isp; *isp = NULL; WRITE_ENTER(&ipf_state); @@ -3797,15 +3960,8 @@ ipstate_t **isp; is->is_ref++; /* To counter ref-- in fr_delstate() */ fr_delstate(is, ISL_EXPIRE); #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); #endif } @@ -3880,3 +4036,120 @@ int rev; fr_queueappend(&is->is_sti, nifq, is); return; } + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_stateiter */ +/* Returns: int - 0 == success, else error */ +/* Parameters: token(I) - pointer to ipftoken structure */ +/* itp(I) - pointer to ipfgeniter structure */ +/* */ +/* This function handles the SIOCGENITER ioctl for the state tables and */ +/* walks through the list of entries in the state table list (ips_list.) */ +/* ------------------------------------------------------------------------ */ +static int fr_stateiter(token, itp) +ipftoken_t *token; +ipfgeniter_t *itp; +{ + ipstate_t *is, *next, zero; + int error, count; + char *dst; + + if (itp->igi_data == NULL) + return EFAULT; + + if (itp->igi_nitems == 0) + return ENOSPC; + + if (itp->igi_type != IPFGENITER_STATE) + return EINVAL; + + is = token->ipt_data; + if (is == (void *)-1) { + ipf_freetoken(token); + return ESRCH; + } + + error = 0; + dst = itp->igi_data; + + READ_ENTER(&ipf_state); + if (is == NULL) { + next = ips_list; + } else { + next = is->is_next; + } + + for (count = itp->igi_nitems; count > 0; count--) { + if (next != NULL) { + /* + * 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. + */ + 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 = (void *)-1; + count = 1; + } + RWLOCK_EXIT(&ipf_state); + + /* + * If we had a prior pointer to a state entry, release it. + */ + if (is != NULL) { + fr_statederef(&is); + } + + /* + * This should arguably be via fr_outobj() so that the state + * structure can (if required) be massaged going out. + */ + error = COPYOUT(next, dst, sizeof(*next)); + if (error != 0) + error = EFAULT; + if ((count == 1) || (error != 0)) + break; + + dst += sizeof(*next); + READ_ENTER(&ipf_state); + is = next; + next = is->is_next; + } + + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_stgettable */ +/* Returns: int - 0 = success, else error */ +/* Parameters: 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 fr_stgettable(data) +char *data; +{ + ipftable_t table; + int error; + + error = fr_inobj(data, &table, IPFOBJ_GTABLE); + if (error != 0) + return error; + + if (table.ita_type != IPFTABLE_BUCKETS) + return EINVAL; + + error = COPYOUT(ips_stats.iss_bucketlen, table.ita_table, + fr_statesize * sizeof(u_long)); + if (error != 0) + error = EFAULT; + return error; +} diff --git a/sys/contrib/ipfilter/netinet/ip_state.h b/sys/contrib/ipfilter/netinet/ip_state.h index 9c457cf..ca7e454 100644 --- a/sys/contrib/ipfilter/netinet/ip_state.h +++ b/sys/contrib/ipfilter/netinet/ip_state.h @@ -42,7 +42,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; @@ -190,6 +189,7 @@ typedef struct ipslog { #define ISL_INTERMEDIATE 0xfffc #define ISL_KILLED 0xfffb #define ISL_ORPHAN 0xfffa +#define ISL_UNLOAD 0xfff9 typedef struct ips_stat { @@ -216,6 +216,7 @@ typedef struct ips_stat { ipstate_t **iss_table; ipstate_t *iss_list; u_long *iss_bucketlen; + ipftq_t *iss_tcptab; } ips_stat_t; @@ -251,12 +252,12 @@ extern int fr_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 int fr_state_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *)); 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_statederef __P((ipstate_t **)); extern void fr_setstatequeue __P((ipstate_t *, int)); #endif /* __IP_STATE_H__ */ diff --git a/sys/contrib/ipfilter/netinet/ip_sync.c b/sys/contrib/ipfilter/netinet/ip_sync.c index d41091a..6b277ae 100644 --- a/sys/contrib/ipfilter/netinet/ip_sync.c +++ b/sys/contrib/ipfilter/netinet/ip_sync.c @@ -98,7 +98,7 @@ struct file; /* END OF INCLUDES */ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_sync.c,v 2.40.2.7 2006/03/19 14:59:39 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_sync.c,v 2.40.2.8 2006/07/14 06:12:20 darrenr Exp $"; #endif #define SYNC_STATETABSZ 256 @@ -997,10 +997,11 @@ 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) +int fr_sync_ioctl(data, cmd, mode, uid, ctx) caddr_t data; ioctlcmd_t cmd; -int mode; +int mode, uid; +void *ctx; { return EINVAL; } diff --git a/sys/contrib/ipfilter/netinet/ipl.h b/sys/contrib/ipfilter/netinet/ipl.h index cdbf3d0..22b8d51 100644 --- a/sys/contrib/ipfilter/netinet/ipl.h +++ b/sys/contrib/ipfilter/netinet/ipl.h @@ -13,8 +13,8 @@ #ifndef __IPL_H__ #define __IPL_H__ -#define IPL_VERSION "IP Filter: v4.1.13" +#define IPL_VERSION "IP Filter: v4.1.23" -#define IPFILTER_VERSION 4011300 +#define IPFILTER_VERSION 4012300 #endif diff --git a/sys/contrib/ipfilter/netinet/mlfk_ipl.c b/sys/contrib/ipfilter/netinet/mlfk_ipl.c index 2048df4..9166712 100644 --- a/sys/contrib/ipfilter/netinet/mlfk_ipl.c +++ b/sys/contrib/ipfilter/netinet/mlfk_ipl.c @@ -33,8 +33,6 @@ #include <netinet/ip_frag.h> #include <netinet/ip_sync.h> -extern struct selinfo ipfselwait[IPL_LOGSIZE]; - #if __FreeBSD_version >= 502116 static struct cdev *ipf_devs[IPL_LOGSIZE]; #else @@ -101,8 +99,8 @@ 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, ""); #define CDEV_MAJOR 79 -#if __FreeBSD_version >= 501000 -# include <sys/poll.h> +#include <sys/poll.h> +#if __FreeBSD_version >= 500043 # include <sys/select.h> static int iplpoll(struct cdev *dev, int events, struct thread *td); @@ -117,12 +115,16 @@ static struct cdevsw ipl_cdevsw = { .d_write = iplwrite, .d_ioctl = iplioctl, .d_name = "ipl", +# if __FreeBSD_version >= 500043 .d_poll = iplpoll, +# endif # if __FreeBSD_version < 600000 .d_maj = CDEV_MAJOR, # endif }; #else +static int iplpoll(dev_t dev, int events, struct proc *p); + static struct cdevsw ipl_cdevsw = { /* open */ iplopen, /* close */ iplclose, @@ -140,7 +142,9 @@ static struct cdevsw ipl_cdevsw = { # if (__FreeBSD_version < 500043) /* bmaj */ -1, # endif +# if (__FreeBSD_version > 430000) /* kqfilter */ NULL +# endif }; #endif @@ -176,9 +180,17 @@ ipf_modload() char *defpass, *c, *str; int i, j, error; - error = iplattach(); - if (error) + RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex"); + RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock"); + RWLOCK_INIT(&ipf_frcache, "ipf cache rwlock"); + + error = ipfattach(); + if (error) { + RW_DESTROY(&ipf_global); + RW_DESTROY(&ipf_mutex); + RW_DESTROY(&ipf_frcache); return error; + } for (i = 0; i < IPL_LOGSIZE; i++) ipf_devs[i] = NULL; @@ -228,12 +240,16 @@ ipf_modunload() return EBUSY; if (fr_running >= 0) { - error = ipldetach(); + error = ipfdetach(); if (error != 0) return error; } else error = 0; + RW_DESTROY(&ipf_global); + RW_DESTROY(&ipf_mutex); + RW_DESTROY(&ipf_frcache); + fr_running = -2; for (i = 0; ipf_devfiles[i]; i++) { @@ -287,9 +303,12 @@ sysctl_ipf_int ( SYSCTL_HANDLER_ARGS ) #endif -#if __FreeBSD_version >= 501000 static int +#if __FreeBSD_version >= 500043 iplpoll(struct cdev *dev, int events, struct thread *td) +#else +iplpoll(dev_t dev, int events, struct proc *td) +#endif { u_int xmin = GET_MINOR(dev); int revents; @@ -332,4 +351,3 @@ iplpoll(struct cdev *dev, int events, struct thread *td) return revents; } -#endif |