diff options
| author | martin <martin@NetBSD.org> | 2007-04-14 20:34:18 +0000 |
|---|---|---|
| committer | martin <martin@NetBSD.org> | 2007-04-14 20:34:18 +0000 |
| commit | 8ebafcc992c87f63d42ac87f05b5ed2a93ee0441 (patch) | |
| tree | 399341879f3fc28c45a3cbf2967a29878b17375d | |
| parent | 993d757ec66b11a7a0ee07fe78aa89effb476ab0 (diff) | |
Update IPFilter to version 4.1.19
98 files changed, 5118 insertions, 4155 deletions
diff --git a/dist/ipf/HISTORY b/dist/ipf/HISTORY index 996f883501f..adb3cd6b700 100644 --- a/dist/ipf/HISTORY +++ b/dist/ipf/HISTORY @@ -10,6 +10,95 @@ # and especially those who have found the time to port IP Filter to new # platforms. # +4.1.19 - Released 22 February 2007 + +Fix up compilation problems with NetBSD and Solaris. + +4.1.18 - Released 18 February 2007 + +fix compiling on Tru64 + +fix listing out filter rules with ipfstat (delete token at end of +the list and detect zero rule being returned.) + +fix extended flushing of NAT tables (was clearing out state tables) + +fix null-pointer deref in hash table lookup + +fix NAT and stateful filtering with to/reply-to on destination interface + +4.1.17 - Released 20 January 2007 + +make flushing pools that are still in use mark them for deletion and +have attempting to recreate them clear the delete flag + +walking through the NAT tables with ioctls caused lock recursion + +fix tracking TCP window scaling in the state code + +4.1.16 - Released 20 December 2006 + +allow rdr rules to only differ on the new port number + +when creating state entry orphans, leave them on the linked list but not +attached to the hash table and mark them visible as orphans in "ipfstat -sl" + +log state removed when unloading differently to allow visible cues + +return ipf ticks via SIOCGETGS for /dev/ipnat so "ipnat -l" can display ttl + +abort logging a packet if the mbuf pointer is null when ipflog is called + +Some NetBSD's have a selinfo.h instead of select.h + +SIOCIPFFL was using copyoutptr and should have been using bcopy for /dev/ipauth + +listing accounting rules using ioctl interface wasn't possible + +fix leakage of state entries due to packets not matching up with NAT + +improve ICMP error packet matching with state/NAT + +fix problems with parsing and printing "-" as an interface name in ipnat.conf + +4.1.15 - Released 03 November 2006 + +Add in automatic flushing of NAT, like state, table if it fills up too much + +Update comments in the code for NAT checksum adjustments + +Fix compiling on FreeBSD 5.4 and 6.0 + +prevent panics from read/write IOs trying to use uninitialised structures + +Newer NetBSD should use malloc() instead of MALLOC() in the kernel where +the size is not staticly defined + +Some gcc warning message cleanup from NetBSD + +Missing include for <sys/filio.h> on Solaris for poll work + +NetBSD now uses opt_ipfilter.h, not opt_ipfilter_log.h + +4.1.14 - Released 04 October 2006 + +rewrite checksum alteration for ICMP packets being NAT'd to use a sane +algorithm that can be understood...now it needs better comments + +fix 1 byte error in checksum validation perl script + +remove unused files in lib directory + +ipftest will say "bad-packet" if it has been freed rather than just "blocked" + +make it possible to load IP address pools from external files in ippool.conf + +update copyright messages in tools directory + +consolidate ioctl hanlding source code into fil.c + +make ipfstat, ippool, ipnat retrieve information via ioctls rather than /dev/kmem + 4.1.13 - Released 4 April 2006 fix bug where null pointers introduced by proxies could cause a crash @@ -39,6 +128,7 @@ add missing ipfsync_canread() and ipfsync_canwrite() behaviour of \ on the end of a line in ipf.conf does not match older behaviour remove duplicate statistics line output with "ipfstat -s" + 4.1.11 - Released 19 March 2006 Patch for NAT with ipfsync from N. Ersen (SESCI) - www.enderunix.org diff --git a/dist/ipf/ip_fil.c b/dist/ipf/ip_fil.c index dbc17940547..ccfcf1e5c06 100644 --- a/dist/ipf/ip_fil.c +++ b/dist/ipf/ip_fil.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_fil.c,v 1.10 2007/03/04 20:04:14 jnemeth Exp $ */ +/* $NetBSD: ip_fil.c,v 1.11 2007/04/14 20:34:18 martin Exp $ */ /* * Copyright (C) 1993-2001 by Darren Reed. @@ -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.14 2007/02/17 12:41:42 darrenr Exp"; #endif #ifndef SOLARIS @@ -85,7 +85,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) @@ -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) @@ -190,23 +191,6 @@ int ipldetach() } -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. */ @@ -216,210 +200,20 @@ ioctlcmd_t cmd; void *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; } @@ -1013,3 +807,9 @@ struct in_addr *inp, *inpmask; } return 0; } + + +int ipfsync() +{ + return 0; +} diff --git a/dist/ipf/ip_lookup.c b/dist/ipf/ip_lookup.c index d5120bb1e7f..788903b8b72 100644 --- a/dist/ipf/ip_lookup.c +++ b/dist/ipf/ip_lookup.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_lookup.c,v 1.2 2006/09/17 14:49:46 christos Exp $ */ +/* $NetBSD: ip_lookup.c,v 1.3 2007/04/14 20:34:18 martin Exp $ */ /* * Copyright (C) 2002-2003 by Darren Reed. @@ -36,9 +36,6 @@ struct file; #endif #include <sys/socket.h> #if (defined(__osf__) || defined(AIX) || defined(__hpux) || defined(__sgi)) && defined(_KERNEL) -# ifdef __osf__ -# include <net/radix.h> -# endif # include "radix_ipf_local.h" # define _RADIX_H_ #endif @@ -63,7 +60,7 @@ struct file; /* END OF INCLUDES */ #if !defined(lint) -static const char rcsid[] = "@(#)Id: ip_lookup.c,v 2.35.2.8 2005/11/13 15:35:45 darrenr Exp"; +static const char rcsid[] = "@(#)Id: ip_lookup.c,v 2.35.2.14 2007/02/17 12:41:42 darrenr Exp"; #endif #ifdef IPFILTER_LOOKUP @@ -131,10 +128,11 @@ void ip_lookup_unload() /* involves just calling another function to handle the specifics of each */ /* command. */ /* ------------------------------------------------------------------------ */ -int ip_lookup_ioctl(data, cmd, mode) +int ip_lookup_ioctl(data, cmd, mode, uid, ctx) caddr_t data; ioctlcmd_t cmd; -int mode; +int mode, uid; +void *ctx; { int err; SPL_INT(s); @@ -184,6 +182,10 @@ int mode; RWLOCK_EXIT(&ip_poolrw); break; + case SIOCLOOKUPITER : + err = ip_lookup_iterate(data, uid, ctx); + break; + default : err = EINVAL; break; @@ -212,8 +214,13 @@ caddr_t data; ip_pool_t *p; int err; - err = 0; - BCOPYIN(data, &op, sizeof(op)); + err = BCOPYIN(data, &op, sizeof(op)); + if (err != 0) + return EFAULT; + + if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) + return EINVAL; + op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; switch (op.iplo_type) @@ -285,6 +292,9 @@ caddr_t data; err = 0; BCOPYIN(data, &op, sizeof(op)); + if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) + return EINVAL; + op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; switch (op.iplo_type) @@ -343,8 +353,12 @@ caddr_t data; iplookupop_t op; int err; - err = 0; - BCOPYIN(data, &op, sizeof(op)); + err = BCOPYIN(data, &op, sizeof(op)); + if (err != 0) + return EFAULT; + + if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) + return EINVAL; op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; @@ -373,8 +387,10 @@ caddr_t data; * For anonymous pools, copy back the operation struct because in the * case of success it will contain the new table's name. */ - if ((err == 0) && ((op.iplo_arg & IPOOL_ANON) != 0)) { - BCOPYOUT(&op, data, sizeof(op)); + if ((err == 0) && ((op.iplo_arg & LOOKUP_ANON) != 0)) { + err = BCOPYOUT(&op, data, sizeof(op)); + if (err != 0) + err = EFAULT; } return err; @@ -395,11 +411,14 @@ caddr_t data; iplookupop_t op; int err; - BCOPYIN(data, &op, sizeof(op)); - op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; + err = BCOPYIN(data, &op, sizeof(op)); + if (err != 0) + return EFAULT; - if (op.iplo_arg & IPLT_ANON) - op.iplo_arg &= IPLT_ANON; + if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) + return EINVAL; + + op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; /* * create a new pool - fail if one already exists with @@ -408,11 +427,11 @@ caddr_t data; switch (op.iplo_type) { case IPLT_POOL : - err = ip_pool_destroy(&op); + err = ip_pool_destroy(op.iplo_unit, op.iplo_name); break; case IPLT_HASH : - err = fr_removehtable(&op); + err = fr_removehtable(op.iplo_unit, op.iplo_name); break; default : @@ -436,8 +455,12 @@ caddr_t data; iplookupop_t op; int err; - err = 0; - BCOPYIN(data, &op, sizeof(op)); + err = BCOPYIN(data, &op, sizeof(op)); + if (err != 0) + return EFAULT; + + if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) + return EINVAL; switch (op.iplo_type) { @@ -471,15 +494,16 @@ caddr_t data; int err, unit, num, type; iplookupflush_t flush; - err = 0; - BCOPYIN(data, &flush, sizeof(flush)); - - flush.iplf_name[sizeof(flush.iplf_name) - 1] = '\0'; + err = BCOPYIN(data, &flush, sizeof(flush)); + if (err != 0) + return EFAULT; unit = flush.iplf_unit; if ((unit < 0 || unit > IPL_LOGMAX) && (unit != IPLT_ALL)) return EINVAL; + flush.iplf_name[sizeof(flush.iplf_name) - 1] = '\0'; + type = flush.iplf_type; err = EINVAL; num = 0; @@ -496,12 +520,23 @@ caddr_t data; if (err == 0) { flush.iplf_count = num; - BCOPYOUT(&flush, data, sizeof(flush)); + err = BCOPYOUT(&flush, data, sizeof(flush)); + if (err != 0) + err = EFAULT; } return err; } +/* ------------------------------------------------------------------------ */ +/* Function: ip_lookup_delref */ +/* Returns: void */ +/* Parameters: type(I) - table type to operate on */ +/* ptr(I) - pointer to object to remove reference for */ +/* */ +/* This function organises calling the correct deref function for a given */ +/* type of object being passed into it. */ +/* ------------------------------------------------------------------------ */ void ip_lookup_deref(type, ptr) int type; void *ptr; @@ -524,13 +559,98 @@ void *ptr; } +/* ------------------------------------------------------------------------ */ +/* Function: ip_lookup_iterate */ +/* Returns: int - 0 = success, else error */ +/* Parameters: data(I) - pointer to data from ioctl call */ +/* */ +/* Decodes ioctl request to step through either hash tables or pools. */ +/* ------------------------------------------------------------------------ */ +int ip_lookup_iterate(data, uid, ctx) +void *data; +int uid; +void *ctx; +{ + ipflookupiter_t iter; + ipftoken_t *token; + int err; + + err = fr_inobj(data, &iter, IPFOBJ_LOOKUPITER); + if (err != 0) + return err; + + if (iter.ili_unit < 0 || iter.ili_unit > IPL_LOGMAX) + return EINVAL; + + if (iter.ili_ival != IPFGENITER_LOOKUP) + return EINVAL; + + token = ipf_findtoken(iter.ili_key, uid, ctx); + if (token == NULL) { + RWLOCK_EXIT(&ipf_tokens); + return ESRCH; + } + + switch (iter.ili_type) + { + case IPLT_POOL : + err = ip_pool_getnext(token, &iter); + break; + case IPLT_HASH : + err = fr_htable_getnext(token, &iter); + break; + default : + err = EINVAL; + break; + } + RWLOCK_EXIT(&ipf_tokens); + + return err; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: iplookup_iterderef */ +/* Returns: int - 0 = success, else error */ +/* Parameters: data(I) - pointer to data from ioctl call */ +/* */ +/* Decodes ioctl request to remove a particular hash table or pool and */ +/* calls the relevant function to do the cleanup. */ +/* ------------------------------------------------------------------------ */ +void ip_lookup_iterderef(type, data) +u_32_t type; +void *data; +{ + iplookupiterkey_t key; + + key.ilik_key = type; + + if (key.ilik_unstr.ilik_ival != IPFGENITER_LOOKUP) + return; + + switch (key.ilik_unstr.ilik_type) + { + case IPLT_HASH : + fr_htable_iterderef((u_int)key.ilik_unstr.ilik_otype, + (int)key.ilik_unstr.ilik_unit, data); + break; + case IPLT_POOL : + ip_pool_iterderef((u_int)key.ilik_unstr.ilik_otype, + (int)key.ilik_unstr.ilik_unit, data); + break; + } +} + + + #else /* IPFILTER_LOOKUP */ /*ARGSUSED*/ -int ip_lookup_ioctl(data, cmd, mode) +int ip_lookup_ioctl(data, cmd, mode, uid, ctx) caddr_t data; ioctlcmd_t cmd; -int mode; +int mode, uid; +void *ctx; { return EIO; } diff --git a/dist/ipf/ipf.h b/dist/ipf/ipf.h index a2e58d7a77b..699073a57f8 100644 --- a/dist/ipf/ipf.h +++ b/dist/ipf/ipf.h @@ -1,4 +1,4 @@ -/* $NetBSD: ipf.h,v 1.11 2006/04/04 16:17:18 martti Exp $ */ +/* $NetBSD: ipf.h,v 1.12 2007/04/14 20:34:18 martin Exp $ */ /* * Copyright (C) 1993-2001, 2003 by Darren Reed. @@ -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.13 2007/01/14 14:06:12 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,8 @@ 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 set_variable __P((char *, char *)); extern char *get_variable __P((char *, char **, int)); diff --git a/dist/ipf/iplang/iplang_y.y b/dist/ipf/iplang/iplang_y.y index 45cb5f3d948..b097a3fa5ed 100644 --- a/dist/ipf/iplang/iplang_y.y +++ b/dist/ipf/iplang/iplang_y.y @@ -1,4 +1,4 @@ -/* $NetBSD: iplang_y.y,v 1.9 2006/04/04 16:17:18 martti Exp $ */ +/* $NetBSD: iplang_y.y,v 1.10 2007/04/14 20:34:19 martin Exp $ */ %{ /* @@ -6,16 +6,16 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Id: iplang_y.y,v 2.9.2.4 2006/03/17 12:11:29 darrenr Exp + * Id: iplang_y.y,v 2.9.2.5 2007/02/17 12:41:48 darrenr Exp */ #include <stdio.h> #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> @@ -29,11 +29,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/dist/ipf/ipsend/44arp.c b/dist/ipf/ipsend/44arp.c index 6475c8399d9..a42cba35e76 100644 --- a/dist/ipf/ipsend/44arp.c +++ b/dist/ipf/ipsend/44arp.c @@ -1,4 +1,4 @@ -/* $NetBSD: 44arp.c,v 1.5 2005/02/08 07:01:53 martti Exp $ */ +/* $NetBSD: 44arp.c,v 1.6 2007/04/14 20:34:19 martin Exp $ */ /* * Based upon 4.4BSD's /usr/sbin/arp @@ -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/dist/ipf/ipsend/arp.c b/dist/ipf/ipsend/arp.c index 1a8d9ed0c19..5741f832357 100644 --- a/dist/ipf/ipsend/arp.c +++ b/dist/ipf/ipsend/arp.c @@ -1,4 +1,4 @@ -/* $NetBSD: arp.c,v 1.5 2006/04/04 16:17:18 martti Exp $ */ +/* $NetBSD: arp.c,v 1.6 2007/04/14 20:34:19 martin Exp $ */ /* * arp.c (C) 1995-1998 Darren Reed @@ -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/dist/ipf/ipsend/ip.c b/dist/ipf/ipsend/ip.c index 4ab4c4a6e87..3094f77e9d9 100644 --- a/dist/ipf/ipsend/ip.c +++ b/dist/ipf/ipsend/ip.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip.c,v 1.7 2005/02/08 07:01:53 martti Exp $ */ +/* $NetBSD: ip.c,v 1.8 2007/04/14 20:34:22 martin Exp $ */ /* * ip.c (C) 1995-1998 Darren Reed @@ -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/dist/ipf/ipsend/iptests.c b/dist/ipf/ipsend/iptests.c index d933195b48c..fd912f923c3 100644 --- a/dist/ipf/ipsend/iptests.c +++ b/dist/ipf/ipsend/iptests.c @@ -1,4 +1,4 @@ -/* $NetBSD: iptests.c,v 1.11 2007/02/20 15:40:08 matt Exp $ */ +/* $NetBSD: iptests.c,v 1.12 2007/04/14 20:34:22 martin Exp $ */ /* * Copyright (C) 1993-1998 by Darren Reed. @@ -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> @@ -67,6 +67,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/dist/ipf/ipsend/resend.c b/dist/ipf/ipsend/resend.c index dba81c2a483..be1b9337d71 100644 --- a/dist/ipf/ipsend/resend.c +++ b/dist/ipf/ipsend/resend.c @@ -1,4 +1,4 @@ -/* $NetBSD: resend.c,v 1.7 2006/04/04 16:17:18 martti Exp $ */ +/* $NetBSD: resend.c,v 1.8 2007/04/14 20:34:22 martin Exp $ */ /* * resend.c (C) 1995-1998 Darren Reed @@ -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/dist/ipf/ipsend/sdlpi.c b/dist/ipf/ipsend/sdlpi.c index 570738910e2..47ede033f83 100644 --- a/dist/ipf/ipsend/sdlpi.c +++ b/dist/ipf/ipsend/sdlpi.c @@ -1,4 +1,4 @@ -/* $NetBSD: sdlpi.c,v 1.5 2005/02/08 07:01:53 martti Exp $ */ +/* $NetBSD: sdlpi.c,v 1.6 2007/04/14 20:34:22 martin Exp $ */ /* * (C)opyright 1992-1998 Darren Reed. (from tcplog) @@ -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/dist/ipf/ipsend/sock.c b/dist/ipf/ipsend/sock.c index 588ec4c37fd..f0db512dc9c 100644 --- a/dist/ipf/ipsend/sock.c +++ b/dist/ipf/ipsend/sock.c @@ -1,4 +1,4 @@ -/* $NetBSD: sock.c,v 1.11 2007/02/20 15:40:08 matt Exp $ */ +/* $NetBSD: sock.c,v 1.12 2007/04/14 20:34:22 martin Exp $ */ /* * sock.c (C) 1995-1998 Darren Reed @@ -8,7 +8,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> @@ -70,7 +70,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> diff --git a/dist/ipf/lib/addicmp.c b/dist/ipf/lib/addicmp.c index f54d08123e0..1c994204320 100644 --- a/dist/ipf/lib/addicmp.c +++ b/dist/ipf/lib/addicmp.c @@ -1,11 +1,11 @@ -/* $NetBSD: addicmp.c,v 1.8 2006/04/04 16:17:18 martti Exp $ */ +/* $NetBSD: addicmp.c,v 1.9 2007/04/14 20:34:23 martin Exp $ */ /* - * 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/dist/ipf/lib/extras.c b/dist/ipf/lib/extras.c deleted file mode 100644 index af0e7d55a74..00000000000 --- a/dist/ipf/lib/extras.c +++ /dev/null @@ -1,114 +0,0 @@ -/* $NetBSD: extras.c,v 1.1.1.1 2004/03/28 08:56:18 martti Exp $ */ - -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * Id: extras.c,v 1.12 2002/07/13 12:06:49 darrenr Exp - */ - -#include "ipf.h" - - -/* - * deal with extra bits on end of the line - */ -int extras(cp, fr, linenum) -char ***cp; -struct frentry *fr; -int linenum; -{ - u_short secmsk; - u_long opts; - int notopt; - - opts = 0; - secmsk = 0; - notopt = 0; - (*cp)++; - if (!**cp) - return -1; - - while (**cp) { - if (!strcasecmp(**cp, "not") || !strcasecmp(**cp, "no")) { - notopt = 1; - (*cp)++; - continue; - } else if (!strncasecmp(**cp, "ipopt", 5)) { - if (!notopt) - fr->fr_flx |= FI_OPTIONS; - fr->fr_mflx |= FI_OPTIONS; - goto nextopt; - } else if (!strcasecmp(**cp, "lowttl")) { - if (!notopt) - fr->fr_flx |= FI_LOWTTL; - fr->fr_mflx |= FI_LOWTTL; - goto nextopt; - } else if (!strcasecmp(**cp, "bad-src")) { - if (!notopt) - fr->fr_flx |= FI_BADSRC; - fr->fr_mflx |= FI_BADSRC; - goto nextopt; - } else if (!strncasecmp(**cp, "mbcast", 6)) { - if (!notopt) - fr->fr_flx |= FI_MBCAST; - fr->fr_mflx |= FI_MBCAST; - goto nextopt; - } else if (!strncasecmp(**cp, "nat", 3)) { - if (!notopt) - fr->fr_flx |= FI_NATED; - fr->fr_mflx |= FI_NATED; - goto nextopt; - } else if (!strncasecmp(**cp, "frag", 4)) { - if (!notopt) - fr->fr_flx |= FI_FRAG; - fr->fr_mflx |= FI_FRAG; - goto nextopt; - } else if (!strncasecmp(**cp, "opt", 3)) { - if (!*(*cp + 1)) { - fprintf(stderr, "%d: opt missing arguements\n", - linenum); - return -1; - } - (*cp)++; - if (!(opts = optname(cp, &secmsk, linenum))) - return -1; - - if (notopt) { - if (!secmsk) { - fr->fr_optmask |= opts; - } else { - fr->fr_optmask |= (opts & ~0x0100); - fr->fr_secmask |= secmsk; - } - fr->fr_secbits &= ~secmsk; - fr->fr_optbits &= ~opts; - } else { - fr->fr_optmask |= opts; - fr->fr_secmask |= secmsk; - fr->fr_optbits |= opts; - fr->fr_secbits |= secmsk; - } - } else if (!strncasecmp(**cp, "short", 5)) { - if (fr->fr_tcpf) { - fprintf(stderr, - "%d: short cannot be used with TCP flags\n", - linenum); - return -1; - } - - if (!notopt) - fr->fr_flx |= FI_SHORT; - fr->fr_mflx |= FI_SHORT; - goto nextopt; - } else - return -1; -nextopt: - notopt = 0; - opts = 0; - secmsk = 0; - (*cp)++; - } - return 0; -} diff --git a/dist/ipf/lib/facpri.c b/dist/ipf/lib/facpri.c index d6fc8d6b8fd..e656d1a83a8 100644 --- a/dist/ipf/lib/facpri.c +++ b/dist/ipf/lib/facpri.c @@ -1,11 +1,11 @@ -/* $NetBSD: facpri.c,v 1.3 2006/04/04 16:17:18 martti Exp $ */ +/* $NetBSD: facpri.c,v 1.4 2007/04/14 20:34:23 martin Exp $ */ /* - * 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/dist/ipf/lib/genmask.c b/dist/ipf/lib/genmask.c deleted file mode 100644 index c66694b9c2c..00000000000 --- a/dist/ipf/lib/genmask.c +++ /dev/null @@ -1,56 +0,0 @@ -/* $NetBSD: genmask.c,v 1.1.1.1 2004/03/28 08:56:18 martti Exp $ */ - -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * Id: genmask.c,v 1.7 2003/11/11 13:40:15 darrenr Exp - */ - -#include "ipf.h" - - -int genmask(msk, mskp) -char *msk; -u_32_t *mskp; -{ - char *endptr = 0L; - int bits; - - if (strchr(msk, '.') || strchr(msk, 'x') || strchr(msk, ':')) { - /* possibly of the form xxx.xxx.xxx.xxx - * or 0xYYYYYYYY */ -#ifdef USE_INET6 - if (use_inet6) { - if (inet_pton(AF_INET6, msk, mskp) != 1) - return -1; - } else -#endif - if (inet_aton(msk, (struct in_addr *)mskp) == 0) - return -1; - } else { - /* - * set x most significant bits - */ - bits = (int)strtol(msk, &endptr, 0); -#ifdef USE_INET6 - if ((*endptr != '\0') || - ((bits > 32) && !use_inet6) || (bits < 0) || - ((bits > 128) && use_inet6)) -#else - if (*endptr != '\0' || bits > 32 || bits < 0) -#endif - return -1; -#ifdef USE_INET6 - if (use_inet6) - fill6bits(bits, mskp); - else -#endif - if (bits == 0) - *mskp = 0; - else - *mskp = htonl(0xffffffff << (32 - bits)); - } - return 0; -} diff --git a/dist/ipf/lib/getline.c b/dist/ipf/lib/getline.c deleted file mode 100644 index f5c1d787c6d..00000000000 --- a/dist/ipf/lib/getline.c +++ /dev/null @@ -1,58 +0,0 @@ -/* $NetBSD: getline.c,v 1.1.1.1 2004/03/28 08:56:18 martti Exp $ */ - -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * Id: getline.c,v 1.3 2001/06/09 17:09:24 darrenr Exp - */ - -#include <stdio.h> -#if !defined(__SVR4) && !defined(__GNUC__) -#include <strings.h> -#endif -#include <string.h> -#include "ipf.h" - - -/* - * Similar to fgets(3) but can handle '\\' and NL is converted to NUL. - * Returns NULL if error occured, EOF encounterd or input line is too long. - */ -char *getline(str, size, file, linenum) -register char *str; -size_t size; -FILE *file; -int *linenum; -{ - char *p; - int s, len; - - do { - for (p = str, s = size;; p += (len - 1), s -= (len - 1)) { - /* - * if an error occured, EOF was encounterd, or there - * was no room to put NUL, return NULL. - */ - if (fgets(p, s, file) == NULL) - return (NULL); - len = strlen(p); - if (p[len - 1] != '\n') { - p[len] = '\0'; - break; - } - (*linenum)++; - p[len - 1] = '\0'; - if (len < 2 || p[len - 2] != '\\') - break; - else - /* - * Convert '\\' to a space so words don't - * run together - */ - p[len - 2] = ' '; - } - } while (*str == '\0'); - return (str); -} diff --git a/dist/ipf/lib/getport.c b/dist/ipf/lib/getport.c index bb14fb30068..f62dd26ad1e 100644 --- a/dist/ipf/lib/getport.c +++ b/dist/ipf/lib/getport.c @@ -1,3 +1,13 @@ +/* $NetBSD: getport.c,v 1.6 2007/04/14 20:34:24 martin Exp $ */ + +/* + * 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/dist/ipf/lib/getportproto.c b/dist/ipf/lib/getportproto.c index ee579d9297c..5280c6f2b4e 100644 --- a/dist/ipf/lib/getportproto.c +++ b/dist/ipf/lib/getportproto.c @@ -1,4 +1,12 @@ -/* $NetBSD: getportproto.c,v 1.5 2005/02/19 21:30:25 martti Exp $ */ +/* $NetBSD: getportproto.c,v 1.6 2007/04/14 20:34:24 martin Exp $ */ + +/* + * 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/dist/ipf/lib/getproto.c b/dist/ipf/lib/getproto.c index 06022d37392..4659f37fce8 100644 --- a/dist/ipf/lib/getproto.c +++ b/dist/ipf/lib/getproto.c @@ -1,4 +1,12 @@ -/* $NetBSD: getproto.c,v 1.3 2006/04/04 16:17:18 martti Exp $ */ +/* $NetBSD: getproto.c,v 1.4 2007/04/14 20:34:24 martin Exp $ */ + +/* + * 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" diff --git a/dist/ipf/lib/hexdump.c b/dist/ipf/lib/hexdump.c deleted file mode 100644 index 577dcac96a3..00000000000 --- a/dist/ipf/lib/hexdump.c +++ /dev/null @@ -1,30 +0,0 @@ -/* $NetBSD: hexdump.c,v 1.2 2004/11/13 19:16:10 he Exp $ */ - -#include <ctype.h> - -#include "ipf.h" - -void hexdump(out, addr, len, ascii) -FILE *out; -void *addr; -int len, ascii; -{ - FILE *fpout; - u_char *s, *t; - int i; - - fpout = out ? out : stdout; - for (i = 0, s = addr; i < len; i++, s++) { - fprintf(fpout, "%02x", *s); - if (i % 16 == 15) { - if (ascii != 0) { - fputc('\t', fpout); - for (t = s - 15; t<= s; t++) - fputc(ISPRINT(*t) ? *t : '.', fpout); - } - fputc('\n', fpout); - } else if (i % 4 == 3) { - fputc(' ', fpout); - } - } -} diff --git a/dist/ipf/lib/hostmask.c b/dist/ipf/lib/hostmask.c deleted file mode 100644 index e19eca554d4..00000000000 --- a/dist/ipf/lib/hostmask.c +++ /dev/null @@ -1,95 +0,0 @@ -/* $NetBSD: hostmask.c,v 1.1.1.1 2004/03/28 08:56:18 martti Exp $ */ - -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * Id: hostmask.c,v 1.10 2002/01/28 06:50:46 darrenr Exp - */ - -#include "ipf.h" - - -/* - * returns -1 if neither "hostmask/num" or "hostmask mask addr" are - * found in the line segments, there is an error processing this information, - * or there is an error processing ports information. - */ -int hostmask(seg, proto, ifname, sa, msk, linenum) -char ***seg, *proto, *ifname; -u_32_t *sa, *msk; -int linenum; -{ - struct in_addr maskaddr; - char *s; - - if ((s = strchr(**seg, '='))) { - *s++ = '\0'; - if (!strcmp(**seg, "pool")) { - *sa = atoi(s); - return 1; - } - } - - /* - * is it possibly hostname/num ? - */ - if ((s = strchr(**seg, '/')) || - ((s = strchr(**seg, ':')) && !strchr(s + 1, ':'))) { - *s++ ='\0'; - if (genmask(s, msk) == -1) { - fprintf(stderr, "%d: bad mask (%s)\n", linenum, s); - return -1; - } - if (hostnum(sa, **seg, linenum, ifname) == -1) { - fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg); - return -1; - } - *sa &= *msk; - (*seg)++; - return 0; - } - - /* - * look for extra segments if "mask" found in right spot - */ - if (*(*seg+1) && *(*seg+2) && !strcasecmp(*(*seg+1), "mask")) { - if (hostnum(sa, **seg, linenum, ifname) == -1) { - fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg); - return -1; - } - (*seg)++; - (*seg)++; - if (inet_aton(**seg, &maskaddr) == 0) { - fprintf(stderr, "%d: bad mask (%s)\n", linenum, **seg); - return -1; - } - *msk = maskaddr.s_addr; - (*seg)++; - *sa &= *msk; - return 0; - } - - if (**seg) { - u_32_t k; - - if (hostnum(sa, **seg, linenum, ifname) == -1) { - fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg); - return -1; - } - (*seg)++; - k = *sa ? 0xffffffff : 0; -#ifdef USE_INET6 - if (use_inet6) { - msk[1] = k; - msk[2] = k; - msk[3] = k; - } -#endif - *msk = k; - return 0; - } - fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg); - return -1; -} diff --git a/dist/ipf/lib/hostname.c b/dist/ipf/lib/hostname.c index 45720d7391b..ebff56d42f9 100644 --- a/dist/ipf/lib/hostname.c +++ b/dist/ipf/lib/hostname.c @@ -1,5 +1,12 @@ -/* $NetBSD: hostname.c,v 1.2 2006/05/10 21:53:14 mrg Exp $ */ +/* $NetBSD: hostname.c,v 1.3 2007/04/14 20:34:26 martin Exp $ */ +/* + * 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,7 +19,7 @@ void *ip; struct in_addr ipa; struct netent *np; - memset(&ipa, 0, sizeof ipa); /* XXX gcc */ + memset(&ipa, 0, sizeof(ipa)); /* XXX gcc */ if (v == 4) { ipa.s_addr = *(u_32_t *)ip; diff --git a/dist/ipf/lib/hostnum.c b/dist/ipf/lib/hostnum.c deleted file mode 100644 index 7fac92a8153..00000000000 --- a/dist/ipf/lib/hostnum.c +++ /dev/null @@ -1,49 +0,0 @@ -/* $NetBSD: hostnum.c,v 1.5 2005/02/08 07:01:53 martti Exp $ */ - -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * Id: hostnum.c,v 1.10.2.1 2004/12/09 19:41:20 darrenr Exp - */ - -#include <ctype.h> - -#include "ipf.h" - - -/* - * returns an ip address as a long var as a result of either a DNS lookup or - * straight inet_addr() call - */ -int hostnum(ipa, host, linenum, ifname) -u_32_t *ipa; -char *host; -int linenum; -char *ifname; -{ - struct in_addr ip; - - if (!strcasecmp("any", host) || - (ifname && *ifname && !strcasecmp(ifname, host))) - return 0; - -#ifdef USE_INET6 - if (use_inet6) { - if (inet_pton(AF_INET6, host, ipa) == 1) - return 0; - else - return -1; - } -#endif - if (ISDIGIT(*host) && inet_aton(host, &ip)) { - *ipa = ip.s_addr; - return 0; - } - - if (!strcasecmp("<thishost>", host)) - host = thishost; - - return gethost(host, ipa); -} diff --git a/dist/ipf/lib/icmpcode.c b/dist/ipf/lib/icmpcode.c index 895b5cbedc9..7f8cc80f35c 100644 --- a/dist/ipf/lib/icmpcode.c +++ b/dist/ipf/lib/icmpcode.c @@ -1,11 +1,11 @@ -/* $NetBSD: icmpcode.c,v 1.6 2006/04/04 16:17:18 martti Exp $ */ +/* $NetBSD: icmpcode.c,v 1.7 2007/04/14 20:34:27 martin Exp $ */ /* - * 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/dist/ipf/lib/ipf_dotuning.c b/dist/ipf/lib/ipf_dotuning.c index ad0df594e10..64f18711bf9 100644 --- a/dist/ipf/lib/ipf_dotuning.c +++ b/dist/ipf/lib/ipf_dotuning.c @@ -1,4 +1,12 @@ -/* $NetBSD: ipf_dotuning.c,v 1.3 2006/04/04 16:17:18 martti Exp $ */ +/* $NetBSD: ipf_dotuning.c,v 1.4 2007/04/14 20:34:27 martin Exp $ */ + +/* + * 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" diff --git a/dist/ipf/lib/ipft_ef.c b/dist/ipf/lib/ipft_ef.c index 02aaa783682..936227c8574 100644 --- a/dist/ipf/lib/ipft_ef.c +++ b/dist/ipf/lib/ipft_ef.c @@ -1,11 +1,11 @@ -/* $NetBSD: ipft_ef.c,v 1.2 2006/12/25 23:55:47 alc Exp $ */ +/* $NetBSD: ipft_ef.c,v 1.3 2007/04/14 20:34:27 martin Exp $ */ /* - * 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,14 +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, " :"); - if (s) - 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/dist/ipf/lib/ipft_hx.c b/dist/ipf/lib/ipft_hx.c index 6fc83a83d2a..d3a50cab028 100644 --- a/dist/ipf/lib/ipft_hx.c +++ b/dist/ipf/lib/ipft_hx.c @@ -1,13 +1,13 @@ -/* $NetBSD: ipft_hx.c,v 1.6 2006/04/04 16:17:18 martti Exp $ */ +/* $NetBSD: ipft_hx.c,v 1.7 2007/04/14 20:34:27 martin Exp $ */ /* - * 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/dist/ipf/lib/ipft_td.c b/dist/ipf/lib/ipft_td.c index 245b0bbfba7..222dd01252d 100644 --- a/dist/ipf/lib/ipft_td.c +++ b/dist/ipf/lib/ipft_td.c @@ -1,11 +1,11 @@ -/* $NetBSD: ipft_td.c,v 1.2 2006/12/25 23:57:00 alc Exp $ */ +/* $NetBSD: ipft_td.c,v 1.3 2007/04/14 20:34:27 martin Exp $ */ /* - * 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,8 +153,9 @@ int cnt, *dir; case IPPROTO_TCP : case IPPROTO_UDP : s = strtok(NULL, " :"); - if (s) - ip->ip_len += atoi(s); + if (s == NULL) + return 0; + ip->ip_len += atoi(s); if (ip->ip_p == IPPROTO_TCP) extra = sizeof(struct tcphdr); else if (ip->ip_p == IPPROTO_UDP) diff --git a/dist/ipf/lib/ipft_tx.c b/dist/ipf/lib/ipft_tx.c index f0dbe5c24e0..9410a378774 100644 --- a/dist/ipf/lib/ipft_tx.c +++ b/dist/ipf/lib/ipft_tx.c @@ -1,15 +1,15 @@ -/* $NetBSD: ipft_tx.c,v 1.6 2006/04/04 16:17:18 martti Exp $ */ +/* $NetBSD: ipft_tx.c,v 1.7 2007/04/14 20:34:28 martin Exp $ */ /* - * 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/dist/ipf/lib/kmem.c b/dist/ipf/lib/kmem.c index 5c31db4dc51..e30e2708475 100644 --- a/dist/ipf/lib/kmem.c +++ b/dist/ipf/lib/kmem.c @@ -1,7 +1,7 @@ -/* $NetBSD: kmem.c,v 1.4 2006/04/04 16:17:18 martti Exp $ */ +/* $NetBSD: kmem.c,v 1.5 2007/04/14 20:34:28 martin Exp $ */ /* - * 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/dist/ipf/lib/loglevel.c b/dist/ipf/lib/loglevel.c deleted file mode 100644 index 4930cc411dd..00000000000 --- a/dist/ipf/lib/loglevel.c +++ /dev/null @@ -1,55 +0,0 @@ -/* $NetBSD: loglevel.c,v 1.1.1.1 2004/03/28 08:56:19 martti Exp $ */ - -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * Id: loglevel.c,v 1.5 2001/06/09 17:09:24 darrenr Exp - */ - -#include "ipf.h" - - -int loglevel(cpp, facpri, linenum) -char **cpp; -u_int *facpri; -int linenum; -{ - int fac, pri; - char *s; - - fac = 0; - pri = 0; - if (!*++cpp) { - fprintf(stderr, "%d: %s\n", linenum, - "missing identifier after level"); - return -1; - } - - s = strchr(*cpp, '.'); - if (s) { - *s++ = '\0'; - fac = fac_findname(*cpp); - if (fac == -1) { - fprintf(stderr, "%d: %s %s\n", linenum, - "Unknown facility", *cpp); - return -1; - } - pri = pri_findname(s); - if (pri == -1) { - fprintf(stderr, "%d: %s %s\n", linenum, - "Unknown priority", s); - return -1; - } - } else { - pri = pri_findname(*cpp); - if (pri == -1) { - fprintf(stderr, "%d: %s %s\n", linenum, - "Unknown priority", *cpp); - return -1; - } - } - *facpri = fac|pri; - return 0; -} diff --git a/dist/ipf/lib/natparse.c b/dist/ipf/lib/natparse.c deleted file mode 100644 index 73c23c725af..00000000000 --- a/dist/ipf/lib/natparse.c +++ /dev/null @@ -1,730 +0,0 @@ -/* $NetBSD: natparse.c,v 1.3 2005/02/08 07:01:54 martti Exp $ */ - -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - */ -#if !defined(lint) -static const char sccsid[] ="@(#)ipnat.c 1.9 6/5/96 (C) 1993 Darren Reed"; -static const char rcsid[] = "@(#)Id: natparse.c,v 1.8.2.1 2004/12/09 19:41:21 darrenr Exp"; -#endif - -#include <sys/ioctl.h> -#include <errno.h> -#include <ctype.h> - -#include "ipf.h" -#include "opts.h" - - -void nat_setgroupmap(n) -ipnat_t *n; -{ - if (n->in_outmsk == n->in_inmsk) - n->in_ippip = 1; - else if (n->in_flags & IPN_AUTOPORTMAP) { - n->in_ippip = ~ntohl(n->in_inmsk); - if (n->in_outmsk != 0xffffffff) - n->in_ippip /= (~ntohl(n->in_outmsk) + 1); - n->in_ippip++; - if (n->in_ippip == 0) - n->in_ippip = 1; - n->in_ppip = USABLE_PORTS / n->in_ippip; - } else { - n->in_space = USABLE_PORTS * ~ntohl(n->in_outmsk); - n->in_nip = 0; - if (!(n->in_ppip = n->in_pmin)) - n->in_ppip = 1; - n->in_ippip = USABLE_PORTS / n->in_ppip; - } -} - - - -ipnat_t *natparse(line, linenum) -char *line; -int linenum; -{ - static ipnat_t ipn; - struct protoent *pr; - char *dnetm = NULL, *dport = NULL, *proto = NULL; - char *s, *t, *cps[31], **cpp; - int i, cnt; - - - if ((s = strchr(line, '\n'))) - *s = '\0'; - if ((s = strchr(line, '#'))) - *s = '\0'; - while (*line && ISSPACE(*line)) - line++; - if (!*line) - return NULL; - - bzero((char *)&ipn, sizeof(ipn)); - cnt = 0; - - for (i = 0, *cps = strtok(line, " \b\t\r\n"); cps[i] && i < 30; cnt++) - cps[++i] = strtok(NULL, " \b\t\r\n"); - - cps[i] = NULL; - - if (cnt < 3) { - fprintf(stderr, "%d: not enough segments in line\n", linenum); - return NULL; - } - - cpp = cps; - - if (!strcasecmp(*cpp, "map")) - ipn.in_redir = NAT_MAP; - else if (!strcasecmp(*cpp, "map-block")) - ipn.in_redir = NAT_MAPBLK; - else if (!strcasecmp(*cpp, "rdr")) - ipn.in_redir = NAT_REDIRECT; - else if (!strcasecmp(*cpp, "bimap")) - ipn.in_redir = NAT_BIMAP; - else { - fprintf(stderr, "%d: unknown mapping: \"%s\"\n", - linenum, *cpp); - return NULL; - } - - cpp++; - - strncpy(ipn.in_ifnames[0], *cpp, sizeof(ipn.in_ifnames[0]) - 1); - ipn.in_ifnames[0][sizeof(ipn.in_ifnames[0]) - 1] = '\0'; - cpp++; - - if (!strcasecmp(*cpp, "from") || (**cpp == '!')) { - if (!strcmp(*cpp, "!")) { - cpp++; - if (strcasecmp(*cpp, "from")) { - fprintf(stderr, "Missing from after !\n"); - return NULL; - } - ipn.in_flags |= IPN_NOTSRC; - } else if (**cpp == '!') { - if (strcasecmp(*cpp + 1, "from")) { - fprintf(stderr, "Missing from after !\n"); - return NULL; - } - ipn.in_flags |= IPN_NOTSRC; - } - if ((ipn.in_flags & IPN_NOTSRC) && - (ipn.in_redir & (NAT_MAP|NAT_MAPBLK))) { - fprintf(stderr, "Cannot use '! from' with map\n"); - return NULL; - } - - ipn.in_flags |= IPN_FILTER; - cpp++; - if (ipn.in_redir == NAT_REDIRECT) { - if (hostmask(&cpp, proto, NULL, - (u_32_t *)&ipn.in_srcip, - (u_32_t *)&ipn.in_srcmsk, linenum) == -1) - return NULL; - - if (ports(&cpp, proto, &ipn.in_sport, - &ipn.in_scmp, &ipn.in_stop, linenum)) - return NULL; - } else { - if (hostmask(&cpp, proto, NULL, - (u_32_t *)&ipn.in_inip, - (u_32_t *)&ipn.in_inmsk, linenum) == -1) - return NULL; - - if (ports(&cpp, proto, &ipn.in_dport, - &ipn.in_dcmp, &ipn.in_dtop, linenum)) - return NULL; - } - - if (!strcmp(*cpp, "!")) { - cpp++; - ipn.in_flags |= IPN_NOTDST; - } else if (**cpp == '!') { - (*cpp)++; - ipn.in_flags |= IPN_NOTDST; - } - - if (strcasecmp(*cpp, "to")) { - fprintf(stderr, "%d: unexpected keyword (%s) - to\n", - linenum, *cpp); - return NULL; - } - if ((ipn.in_flags & IPN_NOTDST) && - (ipn.in_redir & (NAT_REDIRECT))) { - fprintf(stderr, "Cannot use '! to' with rdr\n"); - return NULL; - } - - if (!*++cpp) { - fprintf(stderr, "%d: missing host after to\n", linenum); - return NULL; - } - if (ipn.in_redir == NAT_REDIRECT) { - if (hostmask(&cpp, proto, NULL, - (u_32_t *)&ipn.in_outip, - (u_32_t *)&ipn.in_outmsk, linenum)) - return NULL; - - if (ports(&cpp, proto, &ipn.in_dport, - &ipn.in_dcmp, &ipn.in_dtop, linenum)) - return NULL; - ipn.in_pmin = htons(ipn.in_dport); - } else { - if (hostmask(&cpp, proto, NULL, - (u_32_t *)&ipn.in_srcip, - (u_32_t *)&ipn.in_srcmsk, linenum)) - return NULL; - - if (ports(&cpp, proto, &ipn.in_sport, - &ipn.in_scmp, &ipn.in_stop, linenum)) - return NULL; - } - } else { - s = *cpp; - if (!s) - return NULL; - t = strchr(s, '/'); - if (!t) - return NULL; - *t++ = '\0'; - if (ipn.in_redir == NAT_REDIRECT) { - if (hostnum((u_32_t *)&ipn.in_outip, s, linenum, NULL)) - return NULL; - if (genmask(t, (u_32_t *)&ipn.in_outmsk) == -1) { - return NULL; - } - } else { - if (hostnum((u_32_t *)&ipn.in_inip, s, linenum, NULL)) - return NULL; - if (genmask(t, (u_32_t *)&ipn.in_inmsk) == -1) { - return NULL; - } - } - cpp++; - if (!*cpp) - return NULL; - } - - if ((ipn.in_redir == NAT_REDIRECT) && !(ipn.in_flags & IPN_FILTER)) { - if (strcasecmp(*cpp, "port")) { - fprintf(stderr, "%d: missing fields - 1st port\n", - linenum); - return NULL; - } - - cpp++; - - if (!*cpp) { - fprintf(stderr, - "%d: missing fields (destination port)\n", - linenum); - return NULL; - } - - if (ISDIGIT(**cpp) && (s = strchr(*cpp, '-'))) - *s++ = '\0'; - else - s = NULL; - - if (!portnum(*cpp, proto, &ipn.in_pmin, linenum)) - return NULL; - ipn.in_pmin = htons(ipn.in_pmin); - cpp++; - - if (!strcmp(*cpp, "-")) { - cpp++; - s = *cpp++; - } - - if (s) { - if (!portnum(s, proto, &ipn.in_pmax, linenum)) - return NULL; - ipn.in_pmax = htons(ipn.in_pmax); - } else - ipn.in_pmax = ipn.in_pmin; - } - - if (!*cpp) { - fprintf(stderr, "%d: missing fields (->)\n", linenum); - return NULL; - } - if (strcmp(*cpp, "->")) { - fprintf(stderr, "%d: missing ->\n", linenum); - return NULL; - } - cpp++; - - if (!*cpp) { - fprintf(stderr, "%d: missing fields (%s)\n", - linenum, ipn.in_redir ? "destination" : "target"); - return NULL; - } - - if (ipn.in_redir == NAT_MAP) { - if (!strcasecmp(*cpp, "range")) { - cpp++; - ipn.in_flags |= IPN_IPRANGE; - if (!*cpp) { - fprintf(stderr, "%d: missing fields (%s)\n", - linenum, - ipn.in_redir ? "destination":"target"); - return NULL; - } - } - } - - if (ipn.in_flags & IPN_IPRANGE) { - dnetm = strrchr(*cpp, '-'); - if (dnetm == NULL) { - cpp++; - if (*cpp && !strcmp(*cpp, "-") && *(cpp + 1)) - dnetm = *(cpp + 1); - } else - *dnetm++ = '\0'; - if (dnetm == NULL || *dnetm == '\0') { - fprintf(stderr, - "%d: desination range not specified\n", - linenum); - return NULL; - } - } else if (ipn.in_redir != NAT_REDIRECT) { - dnetm = strrchr(*cpp, '/'); - if (dnetm == NULL) { - cpp++; - if (*cpp && !strcasecmp(*cpp, "netmask")) - dnetm = *++cpp; - } - if (dnetm == NULL) { - fprintf(stderr, - "%d: missing fields (dest netmask)\n", - linenum); - return NULL; - } - if (*dnetm == '/') - *dnetm++ = '\0'; - } - - if (ipn.in_redir == NAT_REDIRECT) { - dnetm = strchr(*cpp, ','); - if (dnetm != NULL) { - ipn.in_flags |= IPN_SPLIT; - *dnetm++ = '\0'; - } - if (hostnum((u_32_t *)&ipn.in_inip, *cpp, linenum, NULL)) - return NULL; - } else { - if (hostnum((u_32_t *)&ipn.in_outip, *cpp, linenum, NULL)) - return NULL; - } - cpp++; - - if (ipn.in_redir & NAT_MAPBLK) { - if (*cpp && strcasecmp(*cpp, "ports")) { - fprintf(stderr, - "%d: expected \"ports\" - got \"%s\"\n", - linenum, *cpp); - return NULL; - } - cpp++; - if (*cpp) { - ipn.in_pmin = atoi(*cpp); - cpp++; - } else - ipn.in_pmin = 0; - } else if ((ipn.in_redir & NAT_BIMAP) == NAT_REDIRECT) { - if (*cpp && strrchr(*cpp, '/') != NULL) { - fprintf(stderr, "%d: No netmask supported in %s\n", - linenum, "destination host for redirect"); - return NULL; - } - /* If it's a in_redir, expect target port */ - - if (!*cpp || strcasecmp(*cpp, "port")) { - fprintf(stderr, "%d: missing fields - 2nd port (%s)\n", - linenum, *cpp); - return NULL; - } - cpp++; - if (!*cpp) { - fprintf(stderr, - "%d: missing fields (destination port)\n", - linenum); - return NULL; - } - if (!portnum(*cpp, proto, &ipn.in_pnext, linenum)) - return NULL; - ipn.in_pnext = htons(ipn.in_pnext); - cpp++; - } - if (dnetm && *dnetm == '/') - *dnetm++ = '\0'; - - if (ipn.in_redir & (NAT_MAP|NAT_MAPBLK)) { - if (ipn.in_flags & IPN_IPRANGE) { - if (hostnum((u_32_t *)&ipn.in_outmsk, dnetm, - linenum, NULL) == -1) - return NULL; - } else if (genmask(dnetm, (u_32_t *)&ipn.in_outmsk)) - return NULL; - } else { - if (ipn.in_flags & IPN_SPLIT) { - if (hostnum((u_32_t *)&ipn.in_inmsk, dnetm, - linenum, NULL) == -1) - return NULL; - } else if (genmask("255.255.255.255", (u_32_t *)&ipn.in_inmsk)) - return NULL; - if (!*cpp) { - ipn.in_flags |= IPN_TCP; /* XXX- TCP only by default */ - proto = "tcp"; - } else { - if (!strcasecmp(*cpp, "tcp")) - ipn.in_flags |= IPN_TCP; - else if (!strcasecmp(*cpp, "udp")) - ipn.in_flags |= IPN_UDP; - else if (!strcasecmp(*cpp, "tcp/udp")) - ipn.in_flags |= IPN_TCPUDP; - else if (!strcasecmp(*cpp, "tcpudp")) - ipn.in_flags |= IPN_TCPUDP; - else if (!strcasecmp(*cpp, "ip")) - ipn.in_flags |= IPN_ANY; - else { - ipn.in_flags |= IPN_ANY; - ipn.in_p = getproto(*cpp); - } - proto = *cpp; - cpp++; - - if (*cpp && !strcasecmp(*cpp, "round-robin")) { - cpp++; - ipn.in_flags |= IPN_ROUNDR; - } - - if (*cpp && !strcasecmp(*cpp, "frag")) { - cpp++; - ipn.in_flags |= IPN_FRAG; - } - - if (*cpp && !strcasecmp(*cpp, "age")) { - cpp++; - if (!*cpp) { - fprintf(stderr, - "%d: age with no parameters\n", - linenum); - return NULL; - } - - ipn.in_age[0] = atoi(*cpp); - s = strchr(*cpp, '/'); - if (s != NULL) - ipn.in_age[1] = atoi(s + 1); - else - ipn.in_age[1] = ipn.in_age[0]; - cpp++; - } - - if (*cpp && !strcasecmp(*cpp, "mssclamp")) { - cpp++; - if (*cpp) { - ipn.in_mssclamp = atoi(*cpp); - cpp++; - } else { - fprintf(stderr, - "%d: mssclamp with no parameters\n", - linenum); - return NULL; - } - } - - if (*cpp) { - fprintf(stderr, - "%d: extra junk at the end of rdr: %s\n", - linenum, *cpp); - return NULL; - } - } - } - - if (!(ipn.in_flags & IPN_SPLIT)) - ipn.in_inip &= ipn.in_inmsk; - if ((ipn.in_flags & IPN_IPRANGE) == 0) - ipn.in_outip &= ipn.in_outmsk; - ipn.in_srcip &= ipn.in_srcmsk; - - if ((ipn.in_redir & NAT_MAPBLK) != 0) - nat_setgroupmap(&ipn); - - if (*cpp && !strcasecmp(*cpp, "frag")) { - cpp++; - ipn.in_flags |= IPN_ROUNDR; - } - - if (!*cpp) - return &ipn; - - if (ipn.in_redir != NAT_BIMAP && !strcasecmp(*cpp, "proxy")) { - if (ipn.in_redir == NAT_BIMAP) { - fprintf(stderr, "%d: cannot use proxy with bimap\n", - linenum); - return NULL; - } - - cpp++; - if (!*cpp) { - fprintf(stderr, - "%d: missing parameter for \"proxy\"\n", - linenum); - return NULL; - } - dport = NULL; - - if (!strcasecmp(*cpp, "port")) { - cpp++; - if (!*cpp) { - fprintf(stderr, - "%d: missing parameter for \"port\"\n", - linenum); - return NULL; - } - - dport = *cpp; - cpp++; - - if (!*cpp) { - fprintf(stderr, - "%d: missing parameter for \"proxy\"\n", - linenum); - return NULL; - } - } else { - fprintf(stderr, - "%d: missing keyword \"port\"\n", linenum); - return NULL; - } - - if ((proto = strchr(*cpp, '/'))) { - *proto++ = '\0'; - ipn.in_p = getproto(proto); - } else - ipn.in_p = 0; - - if (dport && !portnum(dport, proto, &ipn.in_dport, linenum)) - return NULL; - ipn.in_dport = htons(ipn.in_dport); - - (void) strncpy(ipn.in_plabel, *cpp, sizeof(ipn.in_plabel)); - cpp++; - - if (*cpp) { - fprintf(stderr, - "%d: too many parameters for \"proxy\"\n", - linenum); - return NULL; - } - return &ipn; - } - - - if (!strcasecmp(*cpp, "icmpidmap")) { - - cpp++; - if (!*cpp) { - fprintf(stderr, - "%d: icmpidmap misses protocol and range\n", - linenum); - return NULL; - }; - - if (!strcasecmp(*cpp, "icmp")) - ipn.in_flags = IPN_ICMPQUERY; - else { - fprintf(stderr, "%d: icmpidmap only valid for icmp\n", - linenum); - return NULL; - } - cpp++; - - if (!*cpp) { - fprintf(stderr, "%d: no icmp id argument found\n", - linenum); - return NULL; - } - - if (!(t = strchr(*cpp, ':'))) { - fprintf(stderr, - "%d: no icmp id range detected in \"%s\"\n", - linenum, *cpp); - return NULL; - } - *t++ = '\0'; - - if (!icmpidnum(*cpp, &ipn.in_pmin, linenum) || - !icmpidnum(t, &ipn.in_pmax, linenum)) - return NULL; - } else if (!strcasecmp(*cpp, "portmap")) { - if (ipn.in_redir == NAT_BIMAP) { - fprintf(stderr, "%d: cannot use proxy with bimap\n", - linenum); - return NULL; - } - cpp++; - if (!*cpp) { - fprintf(stderr, - "%d: missing expression following portmap\n", - linenum); - return NULL; - } - - if (!strcasecmp(*cpp, "tcp")) - ipn.in_flags |= IPN_TCP; - else if (!strcasecmp(*cpp, "udp")) - ipn.in_flags |= IPN_UDP; - else if (!strcasecmp(*cpp, "tcpudp")) - ipn.in_flags |= IPN_TCPUDP; - else if (!strcasecmp(*cpp, "tcp/udp")) - ipn.in_flags |= IPN_TCPUDP; - else { - fprintf(stderr, - "%d: expected protocol name - got \"%s\"\n", - linenum, *cpp); - return NULL; - } - proto = *cpp; - cpp++; - - if (!*cpp) { - fprintf(stderr, "%d: no port range found\n", linenum); - return NULL; - } - - if (!strcasecmp(*cpp, "auto")) { - ipn.in_flags |= IPN_AUTOPORTMAP; - ipn.in_pmin = htons(1024); - ipn.in_pmax = htons(65535); - nat_setgroupmap(&ipn); - } else { - if (!(t = strchr(*cpp, ':'))) { - fprintf(stderr, - "%d: no port range in \"%s\"\n", - linenum, *cpp); - return NULL; - } - *t++ = '\0'; - if (!portnum(*cpp, proto, &ipn.in_pmin, linenum) || - !portnum(t, proto, &ipn.in_pmax, linenum)) - return NULL; - } - cpp++; - } - - if (*cpp && !strcasecmp(*cpp, "round-robin")) { - cpp++; - ipn.in_flags |= IPN_ROUNDR; - } - - if (*cpp && !strcasecmp(*cpp, "age")) { - cpp++; - if (!*cpp) { - fprintf(stderr, "%d: age with no parameters\n", - linenum); - return NULL; - } - s = strchr(*cpp, '/'); - if (s != NULL) - ipn.in_age[1] = atoi(s + 1); - else - ipn.in_age[1] = ipn.in_age[0]; - cpp++; - } - - if (*cpp && !strcasecmp(*cpp, "mssclamp")) { - cpp++; - if (*cpp) { - ipn.in_mssclamp = atoi(*cpp); - cpp++; - } else { - fprintf(stderr, "%d: mssclamp with no parameters\n", - linenum); - return NULL; - } - } - - if (*cpp) { - fprintf(stderr, "%d: extra junk at the end of the line: %s\n", - linenum, *cpp); - return NULL; - } - - ipn.in_pmin = htons(ipn.in_pmin); - ipn.in_pmax = htons(ipn.in_pmax); - return &ipn; -} - - -void natparsefile(fd, file, opts) -int fd; -char *file; -int opts; -{ - char line[512], *s; - ipnat_t *np; - FILE *fp; - int linenum = 0; - - if (strcmp(file, "-")) { - if (!(fp = fopen(file, "r"))) { - fprintf(stderr, "%s: open: %s\n", file, - STRERROR(errno)); - exit(1); - } - } else - fp = stdin; - - while (getline(line, sizeof(line) - 1, fp, &linenum)) { - line[sizeof(line) - 1] = '\0'; - if ((s = strchr(line, '\n'))) - *s = '\0'; - - if (!(np = natparse(line, linenum))) { - if (*line) - fprintf(stderr, "%d: syntax error in \"%s\"\n", - linenum, line); - } else { - if ((opts & OPT_VERBOSE) && np) - printnat(np, opts); - if (!(opts & OPT_DONOTHING)) { - if (!(opts & OPT_REMOVE)) { - if (ioctl(fd, SIOCADNAT, &np) == -1) - perror("ioctl(SIOCADNAT)"); - } else if (ioctl(fd, SIOCRMNAT, &np) == -1) - perror("ioctl(SIOCRMNAT)"); - } - } - } - if (fp != stdin) - fclose(fp); -} - - -int icmpidnum(str, id, linenum) -char *str; -u_short *id; -int linenum; -{ - int i; - - - i = atoi(str); - - if ((i<0) || (i>65535)) { - fprintf(stderr, "%d: invalid icmp id\"%s\".\n", linenum, str); - return 0; - } - - *id = (u_short)i; - - return 1; -} diff --git a/dist/ipf/lib/parse.c b/dist/ipf/lib/parse.c deleted file mode 100644 index 647fad573cb..00000000000 --- a/dist/ipf/lib/parse.c +++ /dev/null @@ -1,754 +0,0 @@ -/* $NetBSD: parse.c,v 1.3 2005/02/08 07:01:54 martti Exp $ */ - -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * Id: parse.c,v 1.34.2.1 2004/12/09 19:41:21 darrenr Exp - */ -#include <ctype.h> -#include "ipf.h" -#include "opts.h" - -static frentry_t *fp = NULL; - -/* parse() - * - * parse a line read from the input filter rule file - */ -struct frentry *parse(line, linenum) -char *line; -int linenum; -{ - static fripf_t fip; - char *cps[31], **cpp, *endptr, *proto = NULL, *s; - struct protoent *p = NULL; - int i, cnt = 1, j; - u_int k; - - if (fp == NULL) { - fp = malloc(sizeof(*fp)); - if (fp == NULL) - return NULL; - } - - while (*line && ISSPACE(*line)) - line++; - if (!*line) - return NULL; - - bzero((char *)fp, sizeof(*fp)); - bzero((char *)&fip, sizeof(fip)); - fp->fr_v = use_inet6 ? 6 : 4; - fp->fr_ipf = &fip; - fp->fr_dsize = sizeof(fip); - fp->fr_ip.fi_v = fp->fr_v; - fp->fr_mip.fi_v = 0xf; - fp->fr_type = FR_T_NONE; - fp->fr_loglevel = 0xffff; - fp->fr_isc = (void *)-1; - fp->fr_tag = FR_NOTAG; - - /* - * break line up into max of 20 segments - */ - if (opts & OPT_DEBUG) - fprintf(stderr, "parse [%s]\n", line); - for (i = 0, *cps = strtok(line, " \b\t\r\n"); cps[i] && i < 30; cnt++) - cps[++i] = strtok(NULL, " \b\t\r\n"); - cps[i] = NULL; - - if (cnt < 3) { - fprintf(stderr, "%d: not enough segments in line\n", linenum); - return NULL; - } - - cpp = cps; - /* - * The presence of an '@' followed by a number gives the position in - * the current rule list to insert this one. - */ - if (**cpp == '@') - fp->fr_hits = (U_QUAD_T)atoi(*cpp++ + 1) + 1; - - /* - * Check the first keyword in the rule and any options that are - * expected to follow it. - */ - if (!strcasecmp("block", *cpp)) { - fp->fr_flags |= FR_BLOCK; - if (!strncasecmp(*(cpp+1), "return-icmp-as-dest", 19) && - (i = 19)) - fp->fr_flags |= FR_FAKEICMP; - else if (!strncasecmp(*(cpp+1), "return-icmp", 11) && (i = 11)) - fp->fr_flags |= FR_RETICMP; - if (fp->fr_flags & FR_RETICMP) { - cpp++; - if (strlen(*cpp) == i) { - if (*(cpp + 1) && **(cpp +1) == '(') { - cpp++; - i = 0; - } else - i = -1; - } - - /* - * The ICMP code is not required to follow in ()'s - */ - if ((i >= 0) && (*(*cpp + i) == '(')) { - i++; - j = icmpcode(*cpp + i); - if (j == -1) { - fprintf(stderr, - "%d: unrecognised icmp code %s\n", - linenum, *cpp + 20); - return NULL; - } - fp->fr_icode = j; - } - } else if (!strncasecmp(*(cpp+1), "return-rst", 10)) { - fp->fr_flags |= FR_RETRST; - cpp++; - } - } else if (!strcasecmp("count", *cpp)) { - fp->fr_flags |= FR_ACCOUNT; - } else if (!strcasecmp("pass", *cpp)) { - fp->fr_flags |= FR_PASS; - } else if (!strcasecmp("auth", *cpp)) { - fp->fr_flags |= FR_AUTH; - } else if (fp->fr_arg != 0) { - printf("skip %u", fp->fr_arg); - } else if (!strcasecmp("preauth", *cpp)) { - fp->fr_flags |= FR_PREAUTH; - } else if (!strcasecmp("nomatch", *cpp)) { - fp->fr_flags |= FR_NOMATCH; - } else if (!strcasecmp("skip", *cpp)) { - cpp++; - if (ratoui(*cpp, &k, 0, UINT_MAX)) - fp->fr_arg = k; - else { - fprintf(stderr, "%d: integer must follow skip\n", - linenum); - return NULL; - } - } else if (!strcasecmp("log", *cpp)) { - fp->fr_flags |= FR_LOG; - if (!strcasecmp(*(cpp+1), "body")) { - fp->fr_flags |= FR_LOGBODY; - cpp++; - } - if (!strcasecmp(*(cpp+1), "first")) { - fp->fr_flags |= FR_LOGFIRST; - cpp++; - } - if (*cpp && !strcasecmp(*(cpp+1), "or-block")) { - fp->fr_flags |= FR_LOGORBLOCK; - cpp++; - } - if (!strcasecmp(*(cpp+1), "level")) { - cpp++; - if (loglevel(cpp, &fp->fr_loglevel, linenum) == -1) - return NULL; - cpp++; - } - } else { - /* - * Doesn't start with one of the action words - */ - fprintf(stderr, "%d: unknown keyword (%s)\n", linenum, *cpp); - return NULL; - } - if (!*++cpp) { - fprintf(stderr, "%d: missing 'in'/'out' keyword\n", linenum); - return NULL; - } - - /* - * Get the direction for filtering. Impose restrictions on direction - * if blocking with returning ICMP or an RST has been requested. - */ - if (!strcasecmp("in", *cpp)) - fp->fr_flags |= FR_INQUE; - else if (!strcasecmp("out", *cpp)) { - fp->fr_flags |= FR_OUTQUE; - if (fp->fr_flags & FR_RETICMP) { - fprintf(stderr, - "%d: Can only use return-icmp with 'in'\n", - linenum); - return NULL; - } else if (fp->fr_flags & FR_RETRST) { - fprintf(stderr, - "%d: Can only use return-rst with 'in'\n", - linenum); - return NULL; - } - } - if (!*++cpp) { - fprintf(stderr, "%d: missing source specification\n", linenum); - return NULL; - } - - if (!strcasecmp("log", *cpp)) { - if (!*++cpp) { - fprintf(stderr, "%d: missing source specification\n", - linenum); - return NULL; - } - if (FR_ISPASS(fp->fr_flags)) - fp->fr_flags |= FR_LOGP; - else if (FR_ISBLOCK(fp->fr_flags)) - fp->fr_flags |= FR_LOGB; - if (*cpp && !strcasecmp(*cpp, "body")) { - fp->fr_flags |= FR_LOGBODY; - cpp++; - } - if (*cpp && !strcasecmp(*cpp, "first")) { - fp->fr_flags |= FR_LOGFIRST; - cpp++; - } - if (*cpp && !strcasecmp(*cpp, "or-block")) { - if (!FR_ISPASS(fp->fr_flags)) { - fprintf(stderr, - "%d: or-block must be used with pass\n", - linenum); - return NULL; - } - fp->fr_flags |= FR_LOGORBLOCK; - cpp++; - } - if (*cpp && !strcasecmp(*cpp, "level")) { - if (loglevel(cpp, &fp->fr_loglevel, linenum) == -1) - return NULL; - cpp++; - cpp++; - } - } - - if (*cpp && !strcasecmp("quick", *cpp)) { - if (fp->fr_arg != 0) { - fprintf(stderr, "%d: cannot use skip with quick\n", - linenum); - return NULL; - } - cpp++; - fp->fr_flags |= FR_QUICK; - } - - /* - * Parse rule options that are available if a rule is tied to an - * interface. - */ - *fp->fr_ifname = '\0'; - *fp->fr_oifname = '\0'; - if (*cpp && !strcasecmp(*cpp, "on")) { - if (!*++cpp) { - fprintf(stderr, "%d: interface name missing\n", - linenum); - return NULL; - } - (void)strncpy(fp->fr_ifname, *cpp, IFNAMSIZ-1); - fp->fr_ifname[IFNAMSIZ-1] = '\0'; - cpp++; - if (!*cpp) { - if ((fp->fr_flags & FR_RETMASK) == FR_RETRST) { - fprintf(stderr, - "%d: %s can only be used with TCP\n", - linenum, "return-rst"); - return NULL; - } - return fp; - } - - if (!strcasecmp(*cpp, "out-via")) { - if (fp->fr_flags & FR_OUTQUE) { - fprintf(stderr, - "out-via must be used with in\n"); - return NULL; - } - cpp++; - (void)strncpy(fp->fr_oifname, *cpp, IFNAMSIZ-1); - fp->fr_oifname[IFNAMSIZ-1] = '\0'; - cpp++; - } else if (!strcasecmp(*cpp, "in-via")) { - if (fp->fr_flags & FR_INQUE) { - fprintf(stderr, - "in-via must be used with out\n"); - return NULL; - } - cpp++; - (void)strncpy(fp->fr_oifname, *cpp, IFNAMSIZ-1); - fp->fr_oifname[IFNAMSIZ-1] = '\0'; - cpp++; - } - - if (!strcasecmp(*cpp, "dup-to") && *(cpp + 1)) { - cpp++; - if (to_interface(&fp->fr_dif, *cpp, linenum)) - return NULL; - cpp++; - } - if (*cpp && !strcasecmp(*cpp, "to") && *(cpp + 1)) { - cpp++; - if (to_interface(&fp->fr_tif, *cpp, linenum)) - return NULL; - cpp++; - } else if (*cpp && !strcasecmp(*cpp, "fastroute")) { - if (!(fp->fr_flags & FR_INQUE)) { - fprintf(stderr, - "can only use %s with 'in'\n", - "fastroute"); - return NULL; - } - fp->fr_flags |= FR_FASTROUTE; - cpp++; - } - - /* - * Set the "other" interface name. Lets you specify both - * inbound and outbound interfaces for state rules. Do not - * prevent both interfaces from being the same. - */ - strcpy(fp->fr_ifnames[3], "*"); - if ((*cpp != NULL) && (*(cpp + 1) != NULL) && - ((((fp->fr_flags & FR_INQUE) != 0) && - (strcasecmp(*cpp, "out-via") == 0)) || - (((fp->fr_flags & FR_OUTQUE) != 0) && - (strcasecmp(*cpp, "in-via") == 0)))) { - cpp++; - - s = strchr(*cpp, ','); - if (s != NULL) { - *s++ = '\0'; - (void)strncpy(fp->fr_ifnames[3], s, - IFNAMSIZ - 1); - fp->fr_ifnames[3][IFNAMSIZ - 1] = '\0'; - } - - (void)strncpy(fp->fr_ifnames[2], *cpp, IFNAMSIZ - 1); - fp->fr_ifnames[2][IFNAMSIZ - 1] = '\0'; - cpp++; - } else - strcpy(fp->fr_ifnames[2], "*"); - - } - - if (*cpp && !strcasecmp(*cpp, "tos")) { - if (!*++cpp) { - fprintf(stderr, "%d: tos missing value\n", linenum); - return NULL; - } - fp->fr_tos = strtol(*cpp, NULL, 0); - fp->fr_mip.fi_tos = 0xff; - cpp++; - } - - if (*cpp && !strcasecmp(*cpp, "ttl")) { - if (!*++cpp) { - fprintf(stderr, "%d: ttl missing hopcount value\n", - linenum); - return NULL; - } - if (ratoi(*cpp, &i, 0, 255)) - fp->fr_ttl = i; - else { - fprintf(stderr, "%d: invalid ttl (%s)\n", - linenum, *cpp); - return NULL; - } - fp->fr_mip.fi_ttl = 0xff; - cpp++; - } - - /* - * check for "proto <protoname>" only decode udp/tcp/icmp as protoname - */ - if (*cpp && !strcasecmp(*cpp, "proto")) { - if (!*++cpp) { - fprintf(stderr, "%d: protocol name missing\n", linenum); - return NULL; - } - fp->fr_type = FR_T_IPF; - proto = *cpp++; - if (!strcasecmp(proto, "tcp/udp")) { - fp->fr_flx |= FI_TCPUDP; - fp->fr_mflx |= FI_TCPUDP; - } else if (use_inet6 && !strcasecmp(proto, "icmp")) { - fprintf(stderr, -"%d: use proto ipv6-icmp with IPv6 (or use proto 1 if you really mean icmp)\n", - linenum); - return NULL; - } else { - fp->fr_proto = getproto(proto); - fp->fr_mip.fi_p = 0xff; - } - } - if ((fp->fr_proto != IPPROTO_TCP) && - ((fp->fr_flags & FR_RETMASK) == FR_RETRST)) { - fprintf(stderr, "%d: %s can only be used with TCP\n", - linenum, "return-rst"); - return NULL; - } - - /* - * get the from host and bit mask to use against packets - */ - - if (!*cpp) { - fprintf(stderr, "%d: missing source specification\n", linenum); - return NULL; - } - if (!strcasecmp(*cpp, "all")) { - cpp++; - if (!*cpp) { - if (fp->fr_type == FR_T_NONE) { - fp->fr_dsize = 0; - fp->fr_data = NULL; - } - return fp; - } - fp->fr_type = FR_T_IPF; -#ifdef IPFILTER_BPF - } else if (!strcmp(*cpp, "{")) { - struct bpf_program bpf; - struct pcap *p; - char **cp; - u_32_t l; - - if (fp->fr_type != FR_T_NONE) { - fprintf(stderr, - "%d: cannot mix BPF/ipf matching\n", linenum); - return NULL; - } - fp->fr_type = FR_T_BPFOPC; - cpp++; - if (!strncmp(*cpp, "0x", 2)) { - fp->fr_data = malloc(4); - for (cp = cpp, i = 0; *cp; cp++, i++) { - if (!strcmp(*cp, "}")) - break; - fp->fr_data = realloc(fp->fr_data, - (i + 1) * 4); - l = strtoul(*cp, NULL, 0); - ((u_32_t *)fp->fr_data)[i] = l; - } - if (!*cp) { - fprintf(stderr, "Missing closing '}'\n"); - return NULL; - } - fp->fr_dsize = i * sizeof(l); - bpf.bf_insns = fp->fr_data; - bpf.bf_len = fp->fr_dsize / sizeof(struct bpf_insn); - } else { - for (cp = cpp; *cp; cp++) { - if (!strcmp(*cp, "}")) - break; - (*cp)[-1] = ' '; - } - if (!*cp) { - fprintf(stderr, "Missing closing '}'\n"); - return NULL; - } - - bzero((char *)&bpf, sizeof(bpf)); - p = pcap_open_dead(DLT_RAW, 1); - if (!p) { - fprintf(stderr, "pcap_open_dead failed\n"); - return NULL; - } - - if (pcap_compile(p, &bpf, *cpp, 1, 0xffffffff)) { - pcap_perror(p, "ipf"); - pcap_close(p); - fprintf(stderr, "pcap parsing failed\n"); - return NULL; - } - pcap_close(p); - fp->fr_dsize = bpf.bf_len * sizeof(struct bpf_insn); - fp->fr_data = bpf.bf_insns; - if (!bpf_validate(fp->fr_data, bpf.bf_len)) { - fprintf(stderr, "BPF validation failed\n"); - return NULL; - } - if (opts & OPT_DEBUG) - bpf_dump(&bpf, 0); - } - cpp = cp; - (*cpp)++; -#endif - } else { - fp->fr_type = FR_T_IPF; - - if (strcasecmp(*cpp, "from")) { - fprintf(stderr, "%d: unexpected keyword (%s) - from\n", - linenum, *cpp); - return NULL; - } - if (!*++cpp) { - fprintf(stderr, "%d: missing host after from\n", - linenum); - return NULL; - } - if (**cpp == '!') { - fp->fr_flags |= FR_NOTSRCIP; - (*cpp)++; - } else if (!strcmp(*cpp, "!")) { - fp->fr_flags |= FR_NOTSRCIP; - cpp++; - } - - s = *cpp; - i = hostmask(&cpp, proto, fp->fr_ifname, (u_32_t *)&fp->fr_src, - (u_32_t *)&fp->fr_smsk, linenum); - if (i == -1) - return NULL; - if (*fp->fr_ifname && !strcasecmp(s, fp->fr_ifname)) - fp->fr_satype = FRI_DYNAMIC; - if (i == 1) { - if (fp->fr_v == 6) { - fprintf(stderr, - "can only use pools with ipv4\n"); - return NULL; - } - fp->fr_satype = FRI_LOOKUP; - } - - if (ports(&cpp, proto, &fp->fr_sport, &fp->fr_scmp, - &fp->fr_stop, linenum)) - return NULL; - - if (!*cpp) { - fprintf(stderr, "%d: missing to fields\n", linenum); - return NULL; - } - - /* - * do the same for the to field (destination host) - */ - if (strcasecmp(*cpp, "to")) { - fprintf(stderr, "%d: unexpected keyword (%s) - to\n", - linenum, *cpp); - return NULL; - } - if (!*++cpp) { - fprintf(stderr, "%d: missing host after to\n", linenum); - return NULL; - } - - if (**cpp == '!') { - fp->fr_flags |= FR_NOTDSTIP; - (*cpp)++; - } else if (!strcmp(*cpp, "!")) { - fp->fr_flags |= FR_NOTDSTIP; - cpp++; - } - - s = *cpp; - i = hostmask(&cpp, proto, fp->fr_ifname, (u_32_t *)&fp->fr_dst, - (u_32_t *)&fp->fr_dmsk, linenum); - if (i == -1) - return NULL; - if (*fp->fr_ifname && !strcasecmp(s, fp->fr_ifname)) - fp->fr_datype = FRI_DYNAMIC; - if (i == 1) { - if (fp->fr_v == 6) { - fprintf(stderr, - "can only use pools with ipv4\n"); - return NULL; - } - fp->fr_datype = FRI_LOOKUP; - } - - if (ports(&cpp, proto, &fp->fr_dport, &fp->fr_dcmp, - &fp->fr_dtop, linenum)) - return NULL; - } - - if (fp->fr_type == FR_T_IPF) { - /* - * check some sanity, make sure we don't have icmp checks - * with tcp or udp or visa versa. - */ - if (fp->fr_proto && (fp->fr_dcmp || fp->fr_scmp) && - fp->fr_proto != IPPROTO_TCP && - fp->fr_proto != IPPROTO_UDP) { - fprintf(stderr, - "%d: port operation on non tcp/udp\n",linenum); - return NULL; - } - if (fp->fr_icmp && fp->fr_proto != IPPROTO_ICMP) { - fprintf(stderr, - "%d: icmp comparisons on wrong protocol\n", - linenum); - return NULL; - } - - if (!*cpp) - return fp; - - if (*cpp && (fp->fr_type == FR_T_IPF) && - !strcasecmp(*cpp, "flags")) { - if (!*++cpp) { - fprintf(stderr, "%d: no flags present\n", - linenum); - return NULL; - } - fp->fr_tcpf = tcp_flags(*cpp, &fp->fr_tcpfm, linenum); - cpp++; - } - - /* - * extras... - */ - if ((fp->fr_v == 4) && *cpp && (!strcasecmp(*cpp, "with") || - !strcasecmp(*cpp, "and"))) - if (extras(&cpp, fp, linenum)) - return NULL; - - /* - * icmp types for use with the icmp protocol - */ - if (*cpp && !strcasecmp(*cpp, "icmp-type")) { - if (fp->fr_proto != IPPROTO_ICMP && - fp->fr_proto != IPPROTO_ICMPV6) { - fprintf(stderr, - "%d: icmp with wrong protocol (%d)\n", - linenum, fp->fr_proto); - return NULL; - } - if (addicmp(&cpp, fp, linenum)) - return NULL; - fp->fr_icmp = htons(fp->fr_icmp); - fp->fr_icmpm = htons(fp->fr_icmpm); - } - } - - /* - * Keep something... - */ - while (*cpp && !strcasecmp(*cpp, "keep")) - if (addkeep(&cpp, fp, linenum)) - return NULL; - - /* - * This is here to enforce the old interface binding behaviour. - * That is, "on X" is equivalent to "<dir> on X <!dir>-via -,X" - */ - if (fp->fr_flags & FR_KEEPSTATE) { - if (*fp->fr_ifnames[0] && !*fp->fr_ifnames[3]) { - bcopy(fp->fr_ifnames[0], fp->fr_ifnames[3], - sizeof(fp->fr_ifnames[3])); - strncpy(fp->fr_ifnames[2], "*", - sizeof(fp->fr_ifnames[3])); - } - } - - /* - * head of a new group ? - */ - if (*cpp && !strcasecmp(*cpp, "head")) { - if (fp->fr_arg != 0) { - fprintf(stderr, "%d: cannot use skip with head\n", - linenum); - return NULL; - } - if (!*++cpp) { - fprintf(stderr, "%d: head without group #\n", linenum); - return NULL; - } - if (strlen(*cpp) > FR_GROUPLEN) { - fprintf(stderr, "%d: head name too long #\n", linenum); - return NULL; - } - strncpy(fp->fr_grhead, *cpp, FR_GROUPLEN); - cpp++; - } - - /* - * reference to an already existing group ? - */ - if (*cpp && !strcasecmp(*cpp, "group")) { - if (!*++cpp) { - fprintf(stderr, "%d: group without group #\n", - linenum); - return NULL; - } - if (strlen(*cpp) > FR_GROUPLEN) { - fprintf(stderr, "%d: group name too long #\n", linenum); - return NULL; - } - strncpy(fp->fr_group, *cpp, FR_GROUPLEN); - cpp++; - } - - if (*cpp && !strcasecmp(*cpp, "tag")) { - if (!*++cpp) { - fprintf(stderr, "%d: tag id missing value\n", linenum); - return NULL; - } - fp->fr_tag = strtol(*cpp, NULL, 0); - cpp++; - } - - /* - * pps counter - */ - if (*cpp && !strcasecmp(*cpp, "pps")) { - if (!*++cpp) { - fprintf(stderr, "%d: pps without rate\n", linenum); - return NULL; - } - if (ratoui(*cpp, &k, 0, INT_MAX)) - fp->fr_pps = k; - else { - fprintf(stderr, "%d: invalid pps rate (%s)\n", - linenum, *cpp); - return NULL; - } - cpp++; - } - - /* - * leftovers...yuck - */ - if (*cpp && **cpp) { - fprintf(stderr, "%d: unknown words at end: [", linenum); - for (; *cpp; cpp++) - fprintf(stderr, "%s ", *cpp); - fprintf(stderr, "]\n"); - return NULL; - } - - /* - * lazy users... - */ - if (fp->fr_type == FR_T_IPF) { - if ((fp->fr_tcpf || fp->fr_tcpfm) && - (fp->fr_proto != IPPROTO_TCP)) { - fprintf(stderr, - "%d: TCP protocol not specified\n", linenum); - return NULL; - } - if (!(fp->fr_flx & FI_TCPUDP) && - (fp->fr_proto != IPPROTO_TCP) && - (fp->fr_proto != IPPROTO_UDP) && - (fp->fr_dcmp || fp->fr_scmp)) { - if (!fp->fr_proto) { - fp->fr_flx |= FI_TCPUDP; - fp->fr_mflx |= FI_TCPUDP; - } else { - fprintf(stderr, - "%d: port check for non-TCP/UDP\n", - linenum); - return NULL; - } - } - } - if (*fp->fr_oifname && strcmp(fp->fr_oifname, "*") && - !(fp->fr_flags & FR_KEEPSTATE)) { - fprintf(stderr, "%d: *-via <if> must be used %s\n", - linenum, "with keep-state"); - return NULL; - } - return fp; -} diff --git a/dist/ipf/lib/portnum.c b/dist/ipf/lib/portnum.c deleted file mode 100644 index f9fddb51609..00000000000 --- a/dist/ipf/lib/portnum.c +++ /dev/null @@ -1,64 +0,0 @@ -/* $NetBSD: portnum.c,v 1.5 2005/02/08 07:01:54 martti Exp $ */ - -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * - * Id: portnum.c,v 1.6.4.1 2004/12/09 19:41:22 darrenr Exp - */ - -#include <ctype.h> - -#include "ipf.h" - - -/* - * find the port number given by the name, either from getservbyname() or - * straight atoi(). Return 1 on success, 0 on failure - */ -int portnum(name, proto, port, linenum) -char *name, *proto; -u_short *port; -int linenum; -{ - struct servent *sp, *sp2; - u_short p1 = 0; - int i; - - if (ISDIGIT(*name)) { - if (ratoi(name, &i, 0, USHRT_MAX)) { - *port = (u_short)i; - return 1; - } - fprintf(stderr, "%d: unknown port \"%s\"\n", linenum, name); - return 0; - } - if (proto != NULL && strcasecmp(proto, "tcp/udp") != 0) { - sp = getservbyname(name, proto); - if (sp) { - *port = ntohs(sp->s_port); - return 1; - } - fprintf(stderr, "%d: unknown service \"%s\".\n", linenum, name); - return 0; - } - sp = getservbyname(name, "tcp"); - if (sp) - p1 = sp->s_port; - sp2 = getservbyname(name, "udp"); - if (!sp || !sp2) { - fprintf(stderr, "%d: unknown tcp/udp service \"%s\".\n", - linenum, name); - return 0; - } - if (p1 != sp2->s_port) { - fprintf(stderr, "%d: %s %d/tcp is a different port to ", - linenum, name, p1); - fprintf(stderr, "%d: %s %d/udp\n", linenum, name, sp->s_port); - return 0; - } - *port = ntohs(p1); - return 1; -} diff --git a/dist/ipf/lib/ports.c b/dist/ipf/lib/ports.c deleted file mode 100644 index 2acd268da4c..00000000000 --- a/dist/ipf/lib/ports.c +++ /dev/null @@ -1,81 +0,0 @@ -/* $NetBSD: ports.c,v 1.5 2005/02/08 07:01:54 martti Exp $ */ - -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * Id: ports.c,v 1.9.4.1 2004/12/09 19:41:22 darrenr Exp - */ - -#include <ctype.h> - -#include "ipf.h" - - -/* - * check for possible presence of the port fields in the line - */ -int ports(seg, proto, pp, cp, tp, linenum) -char ***seg; -char *proto; -u_short *pp; -int *cp; -u_short *tp; -int linenum; -{ - int comp = -1; - - if (!*seg || !**seg || !***seg) - return 0; - if (!strcasecmp(**seg, "port") && *(*seg + 1) && *(*seg + 2)) { - (*seg)++; - if (ISALNUM(***seg) && *(*seg + 2)) { - if (portnum(**seg, proto, pp, linenum) == 0) - return -1; - (*seg)++; - if (!strcmp(**seg, "<>")) - comp = FR_OUTRANGE; - else if (!strcmp(**seg, "><")) - comp = FR_INRANGE; - else { - fprintf(stderr, - "%d: unknown range operator (%s)\n", - linenum, **seg); - return -1; - } - (*seg)++; - if (**seg == NULL) { - fprintf(stderr, "%d: missing 2nd port value\n", - linenum); - return -1; - } - if (portnum(**seg, proto, tp, linenum) == 0) - return -1; - } else if (!strcmp(**seg, "=") || !strcasecmp(**seg, "eq")) - comp = FR_EQUAL; - else if (!strcmp(**seg, "!=") || !strcasecmp(**seg, "ne")) - comp = FR_NEQUAL; - else if (!strcmp(**seg, "<") || !strcasecmp(**seg, "lt")) - comp = FR_LESST; - else if (!strcmp(**seg, ">") || !strcasecmp(**seg, "gt")) - comp = FR_GREATERT; - else if (!strcmp(**seg, "<=") || !strcasecmp(**seg, "le")) - comp = FR_LESSTE; - else if (!strcmp(**seg, ">=") || !strcasecmp(**seg, "ge")) - comp = FR_GREATERTE; - else { - fprintf(stderr, "%d: unknown comparator (%s)\n", - linenum, **seg); - return -1; - } - if (comp != FR_OUTRANGE && comp != FR_INRANGE) { - (*seg)++; - if (portnum(**seg, proto, pp, linenum) == 0) - return -1; - } - *cp = comp; - (*seg)++; - } - return 0; -} diff --git a/dist/ipf/lib/printbuf.c b/dist/ipf/lib/printbuf.c index 82a9ed7e0c5..4ab8728d896 100644 --- a/dist/ipf/lib/printbuf.c +++ b/dist/ipf/lib/printbuf.c @@ -1,11 +1,11 @@ -/* $NetBSD: printbuf.c,v 1.5 2005/02/08 07:01:54 martti Exp $ */ +/* $NetBSD: printbuf.c,v 1.6 2007/04/14 20:34:31 martin Exp $ */ /* - * 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/dist/ipf/lib/printsbuf.c b/dist/ipf/lib/printsbuf.c index 5641ce7db5d..1a0e025f1a2 100644 --- a/dist/ipf/lib/printsbuf.c +++ b/dist/ipf/lib/printsbuf.c @@ -1,4 +1,12 @@ -/* $NetBSD: printsbuf.c,v 1.2 2004/11/13 19:16:10 he Exp $ */ +/* $NetBSD: printsbuf.c,v 1.3 2007/04/14 20:34:31 martin Exp $ */ + +/* + * 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 diff --git a/dist/ipf/lib/ratoi.c b/dist/ipf/lib/ratoi.c deleted file mode 100644 index 427b3f1bfb0..00000000000 --- a/dist/ipf/lib/ratoi.c +++ /dev/null @@ -1,26 +0,0 @@ -/* $NetBSD: ratoi.c,v 1.1.1.1 2004/03/28 08:56:20 martti Exp $ */ - -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * Id: ratoi.c,v 1.4 2001/06/09 17:09:25 darrenr Exp - */ - -#include "ipf.h" - - -int ratoi(ps, pi, min, max) -char *ps; -int *pi, min, max; -{ - int i; - char *pe; - - i = (int)strtol(ps, &pe, 0); - if (*pe != '\0' || i < min || i > max) - return 0; - *pi = i; - return 1; -} diff --git a/dist/ipf/lib/ratoui.c b/dist/ipf/lib/ratoui.c deleted file mode 100644 index 40c52b4000e..00000000000 --- a/dist/ipf/lib/ratoui.c +++ /dev/null @@ -1,26 +0,0 @@ -/* $NetBSD: ratoui.c,v 1.1.1.1 2004/03/28 08:56:20 martti Exp $ */ - -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * Id: ratoui.c,v 1.4 2001/06/09 17:09:25 darrenr Exp - */ - -#include "ipf.h" - - -int ratoui(ps, pi, min, max) -char *ps; -u_int *pi, min, max; -{ - u_int i; - char *pe; - - i = (u_int)strtol(ps, &pe, 0); - if (*pe != '\0' || i < min || i > max) - return 0; - *pi = i; - return 1; -} diff --git a/dist/ipf/lib/to_interface.c b/dist/ipf/lib/to_interface.c deleted file mode 100644 index 23c504f2ab8..00000000000 --- a/dist/ipf/lib/to_interface.c +++ /dev/null @@ -1,31 +0,0 @@ -/* $NetBSD: to_interface.c,v 1.1.1.1 2004/03/28 08:56:21 martti Exp $ */ - -/* - * Copyright (C) 1993-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - * - * Id: to_interface.c,v 1.8 2002/01/28 06:50:48 darrenr Exp - */ - -#include "ipf.h" - - -int to_interface(fdp, to, linenum) -frdest_t *fdp; -char *to; -int linenum; -{ - char *s; - - s = strchr(to, ':'); - fdp->fd_ifp = NULL; - if (s) { - *s++ = '\0'; - if (hostnum((u_32_t *)&fdp->fd_ip, s, linenum, NULL) == -1) - return -1; - } - (void) strncpy(fdp->fd_ifname, to, sizeof(fdp->fd_ifname) - 1); - fdp->fd_ifname[sizeof(fdp->fd_ifname) - 1] = '\0'; - return 0; -} diff --git a/dist/ipf/lib/v6ionames.c b/dist/ipf/lib/v6ionames.c index 653efee835d..42cb8a73b0c 100644 --- a/dist/ipf/lib/v6ionames.c +++ b/dist/ipf/lib/v6ionames.c @@ -1,11 +1,11 @@ -/* $NetBSD: v6ionames.c,v 1.5 2006/04/04 16:17:18 martti Exp $ */ +/* $NetBSD: v6ionames.c,v 1.6 2007/04/14 20:34:33 martin Exp $ */ /* - * 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/dist/ipf/lib/var.c b/dist/ipf/lib/var.c index 35d95e09155..4d5f17e2149 100644 --- a/dist/ipf/lib/var.c +++ b/dist/ipf/lib/var.c @@ -1,4 +1,12 @@ -/* $NetBSD: var.c,v 1.4 2004/11/13 19:16:10 he Exp $ */ +/* $NetBSD: var.c,v 1.5 2007/04/14 20:34:33 martin Exp $ */ + +/* + * 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> diff --git a/dist/ipf/tools/ipf.c b/dist/ipf/tools/ipf.c index 058c384eb04..6ef96f012fa 100644 --- a/dist/ipf/tools/ipf.c +++ b/dist/ipf/tools/ipf.c @@ -1,7 +1,7 @@ -/* $NetBSD: ipf.c,v 1.2 2006/04/18 12:40:49 darrenr Exp $ */ +/* $NetBSD: ipf.c,v 1.3 2007/04/14 20:34:34 martin Exp $ */ /* - * 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.6 2006/08/26 11:21:13 darrenr Exp"; #endif #if !defined(__SVR4) && defined(__GNUC__) diff --git a/dist/ipf/tools/ipf_y.y b/dist/ipf/tools/ipf_y.y index 4aa1207e8bd..da6c140250e 100644 --- a/dist/ipf/tools/ipf_y.y +++ b/dist/ipf/tools/ipf_y.y @@ -1,3 +1,10 @@ +/* $NetBSD: ipf_y.y,v 1.21 2007/04/14 20:34:34 martin Exp $ */ + +/* + * Copyright (C) 2001-2006 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ %{ #include "ipf.h" #include <sys/ioctl.h> @@ -169,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); @@ -188,6 +195,7 @@ assign: YY_STR assigning YY_STR ';' { set_variable($1, $3); resetlexer(); free($1); free($3); + yyvarnext = 0; } ; @@ -211,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; } @@ -835,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; } @@ -1373,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", @@ -1383,6 +1403,7 @@ interfacename: YY_STR { $$ = $1; } ; name: YY_STR { $$ = $1; } + | '-' { $$ = strdup("-"); } ; ipv4_16: diff --git a/dist/ipf/tools/ipfcomp.c b/dist/ipf/tools/ipfcomp.c index c0d912be25a..a04e47cbe3a 100644 --- a/dist/ipf/tools/ipfcomp.c +++ b/dist/ipf/tools/ipfcomp.c @@ -1,13 +1,13 @@ -/* $NetBSD: ipfcomp.c,v 1.2 2006/04/28 19:49:13 christos Exp $ */ +/* $NetBSD: ipfcomp.c,v 1.3 2007/04/14 20:34:34 martin Exp $ */ /* - * 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.6 2007/02/18 15:56:32 darrenr Exp"; #endif #include "ipf.h" @@ -94,11 +94,15 @@ 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 (__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"); @@ -513,7 +517,7 @@ u_int incount, outcount; fprintf(fp, "\n};\n"); } - if (g != NULL && num == -2 && dir == 1 && header[1] == 0 && + if (g != NULL && num == -2 && dir == 1 && header[0] == 0 && outcount != 0) { fprintf(fp, "\nfrentry_t *ipf_rules_out_%s[%d] = {", group, outcount); diff --git a/dist/ipf/tools/ipfs.c b/dist/ipf/tools/ipfs.c index 5ccc28a29c3..354e3f5faf3 100644 --- a/dist/ipf/tools/ipfs.c +++ b/dist/ipf/tools/ipfs.c @@ -1,7 +1,7 @@ -/* $NetBSD: ipfs.c,v 1.7 2006/04/04 16:17:19 martti Exp $ */ +/* $NetBSD: ipfs.c,v 1.8 2007/04/14 20:34:34 martin Exp $ */ /* - * Copyright (C) 1999-2001, 2003 by Darren Reed. + * Copyright (C) 2001-2006 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ diff --git a/dist/ipf/tools/ipfstat.c b/dist/ipf/tools/ipfstat.c index f9678fdf246..ae0a47e2efb 100644 --- a/dist/ipf/tools/ipfstat.c +++ b/dist/ipf/tools/ipfstat.c @@ -1,7 +1,7 @@ -/* $NetBSD: ipfstat.c,v 1.12 2006/04/04 16:17:19 martti Exp $ */ +/* $NetBSD: ipfstat.c,v 1.13 2007/04/14 20:34:34 martin Exp $ */ /* - * 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.19 2007/02/08 22:04:52 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,8 @@ int use_inet6 = 0; int live_kernel = 1; int state_fd = -1; int ipf_fd = -1; +int auth_fd = -1; +int nat_fd = -1; #ifdef STATETOP #define STSTRSIZE 80 @@ -130,19 +129,22 @@ 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 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 +194,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 +247,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 +267,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 +381,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 +395,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 +434,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 +451,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 +468,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)"); @@ -470,23 +482,13 @@ u_32_t *frfp; 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); } @@ -771,21 +773,64 @@ 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"); + frgroup_t *grtop, *grtail, *g; + struct frentry fb; + ipfruleiter_t rule; + frentry_t zero; + ipfobj_t obj; + int n; + + if (use_inet6 == 1) + fb.fr_v = 6; + else + fb.fr_v = 4; + fb.fr_next = fp; + n = 0; + + grtop = NULL; + grtail = NULL; + 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 +845,135 @@ 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') { + 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); + + 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); } } @@ -897,7 +1039,10 @@ struct friostat *fiop; (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,19 +1053,39 @@ 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, @@ -982,11 +1147,15 @@ ips_stat_t *ipsp; * 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; - free(buckets); + ipsp->iss_list = fetchstate(ipsp->iss_list, &ips); + + if (ipsp->iss_list != NULL) { + ipsp->iss_list = ips.is_next; + printstate(&ips, opts, ipsp->iss_ticks); + } + } } @@ -1040,9 +1209,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 +1233,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 +1601,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 +1618,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 +1687,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 +1715,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 +2012,57 @@ 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; +} diff --git a/dist/ipf/tools/ipmon.c b/dist/ipf/tools/ipmon.c index 5f61ab801d3..de1c6a551af 100644 --- a/dist/ipf/tools/ipmon.c +++ b/dist/ipf/tools/ipmon.c @@ -1,7 +1,7 @@ -/* $NetBSD: ipmon.c,v 1.8 2006/05/10 21:53:14 mrg Exp $ */ +/* $NetBSD: ipmon.c,v 1.9 2007/04/14 20:34:34 martin Exp $ */ /* - * 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.17 2006/12/18 15:27:58 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); diff --git a/dist/ipf/tools/ipnat_y.y b/dist/ipf/tools/ipnat_y.y index 28fe6ed3de2..2729329f9c0 100644 --- a/dist/ipf/tools/ipnat_y.y +++ b/dist/ipf/tools/ipnat_y.y @@ -1,5 +1,10 @@ -/* $NetBSD: ipnat_y.y,v 1.14 2006/04/04 16:17:19 martti Exp $ */ +/* $NetBSD: ipnat_y.y,v 1.15 2007/04/14 20:34:35 martin Exp $ */ +/* + * 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/dist/ipf/tools/ippool.c b/dist/ipf/tools/ippool.c index c8797974672..4ba0040b266 100644 --- a/dist/ipf/tools/ippool.c +++ b/dist/ipf/tools/ippool.c @@ -1,7 +1,7 @@ -/* $NetBSD: ippool.c,v 1.4 2005/02/19 21:30:25 martti Exp $ */ +/* $NetBSD: ippool.c,v 1.5 2007/04/14 20:34:35 martin Exp $ */ /* - * 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 "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/dist/ipf/tools/ippool_y.y b/dist/ipf/tools/ippool_y.y index 86ee75b27b1..f9ddc7a122b 100644 --- a/dist/ipf/tools/ippool_y.y +++ b/dist/ipf/tools/ippool_y.y @@ -1,5 +1,10 @@ -/* $NetBSD: ippool_y.y,v 1.2 2006/08/26 23:20:56 christos Exp $ */ +/* $NetBSD: ippool_y.y,v 1.3 2007/04/14 20:34:35 martin Exp $ */ +/* + * 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,7 +39,7 @@ #include "kmem.h" #define YYDEBUG 1 -#define YYSTACKSIZE 0x00ffffff +#define YYSTACKSIZE 0x00ffffff extern int yyparse __P((void)); extern int yydebug; @@ -46,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 { @@ -113,6 +121,7 @@ assign: YY_STR assigning YY_STR ';' { set_variable($1, $3); resetlexer(); free($1); free($3); + yyvarnext = 0; } ; @@ -249,6 +258,7 @@ groupentry: FR_GROUPLEN); free($3); } + | YY_STR { $$ = add_htablehosts($1); } ; range: addrmask { $$ = calloc(1, sizeof(*$$)); @@ -265,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; } @@ -281,6 +292,7 @@ hashentry: (char *)&($$->ipe_mask), sizeof($$->ipe_mask)); } + | YY_STR { $$ = add_htablehosts($1); } ; addrmask: @@ -294,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); } @@ -414,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/dist/ipf/tools/ipscan_y.y b/dist/ipf/tools/ipscan_y.y index 46e07c6a311..c9a6771fda2 100644 --- a/dist/ipf/tools/ipscan_y.y +++ b/dist/ipf/tools/ipscan_y.y @@ -1,5 +1,10 @@ -/* $NetBSD: ipscan_y.y,v 1.2 2004/11/13 19:16:10 he Exp $ */ +/* $NetBSD: ipscan_y.y,v 1.3 2007/04/14 20:34:35 martin Exp $ */ +/* + * 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/dist/ipf/tools/lexer.c b/dist/ipf/tools/lexer.c index 49eeb51ef2a..9810345540c 100644 --- a/dist/ipf/tools/lexer.c +++ b/dist/ipf/tools/lexer.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003 by Darren Reed. + * Copyright (C) 2002-2006 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -283,8 +283,9 @@ nextchar: yypos++; } } while (n != c); - yyunputc(n); - break; + rval = YY_STR; + goto done; + /* NOTREACHED */ case EOF : yylineNum = 1; @@ -465,6 +466,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; @@ -491,8 +495,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) { @@ -607,6 +611,8 @@ wordtab_t *newdict; void yyresetdict() { + if (yydebug) + printf("yyresetdict(%d)\n", yysavedepth); if (yysavedepth > 0) { yysettab(yysavewords[--yysavedepth]); if (yydebug) diff --git a/dist/ipf/tools/lexer.h b/dist/ipf/tools/lexer.h index a296cb0bc39..8349fb8aece 100644 --- a/dist/ipf/tools/lexer.h +++ b/dist/ipf/tools/lexer.h @@ -1,3 +1,10 @@ +/* $NetBSD: lexer.h,v 1.4 2007/04/14 20:34:35 martin Exp $ */ + +/* + * 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/regress/sys/kern/ipf/Makefile b/regress/sys/kern/ipf/Makefile index 059f359d461..e45941baa27 100644 --- a/regress/sys/kern/ipf/Makefile +++ b/regress/sys/kern/ipf/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.11 2006/04/04 16:17:19 martti Exp $ +# $NetBSD: Makefile,v 1.12 2007/04/14 20:34:40 martin Exp $ # # (C)opyright 1993-1996 by Darren Reed. # @@ -30,13 +30,13 @@ ptests: i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 i16 i17 i18 i19 \ ntests: n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12 n13 n14 nitests: ni1 ni2 ni3 ni4 ni5 ni6 ni7 ni8 ni9 ni10 ni11 ni12 ni13 ni14 ni15 \ - ni16 ni19 ni20 ni21 + ni16 ni19 ni20 ni21 ni23 intests: in1 in2 in3 in4 in5 in6 logtests: l1 -pools: p1 p2 p3 ip1 +pools: p1 p2 p3 p5 ip1 ip2 ipv6: ipv6.1 ipv6.2 ipv6.3 @@ -58,11 +58,11 @@ n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12 n13 n14: @${HOST_SH} ${.CURDIR}/nattest ${.CURDIR} \ `${AWK} "/^$@ / { print; } " ${.CURDIR}/test.format` -ni1 ni2 ni3 ni4 ni5 ni7 ni8 ni9 ni10 ni11 ni12 ni13 ni14 ni15 ni16 ni19 ni20: +ni2 ni3 ni4 ni5 ni7 ni8 ni9 ni10 ni11 ni12 ni13 ni14 ni15 ni16 ni19 ni20: @${HOST_SH} ${.CURDIR}/natipftest ${.CURDIR} single \ `${AWK} "/^$@ / { print; } " ${.CURDIR}/test.format` -ni6 ni21: +ni1 ni6 ni21 ni23: @${HOST_SH} ${.CURDIR}/natipftest ${.CURDIR} multi \ `${AWK} "/^$@ / { print; } " ${.CURDIR}/test.format` @@ -78,11 +78,11 @@ ipv6.1 ipv6.2 ipv6.3: @${HOST_SH} ${.CURDIR}/dotest6 ${.CURDIR} \ `${AWK} "/^$@ / { print; } " ${.CURDIR}/test.format` -p1 p2 p3: +p1 p2 p3 p5: @${HOST_SH} ${.CURDIR}/ptest ${.CURDIR} \ `${AWK} "/^$@ / { print; } " ${.CURDIR}/test.format` -ip1: +ip1 ip2: @${HOST_SH} ${.CURDIR}/iptest ${.CURDIR} \ `${AWK} "/^$@ / { print; } " ${.CURDIR}/test.format` @@ -95,9 +95,9 @@ clean: /bin/rm -f i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 i16 i17 i18 i19 i20 i21 /bin/rm -f n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12 n13 n14 /bin/rm -f ni1 ni2 ni3 ni4 ni5 ni6 ni7 ni8 ni9 - /bin/rm -f ni10 ni11 ni12 ni13 ni14 ni15 ni16 ni19 ni20 ni21 + /bin/rm -f ni10 ni11 ni12 ni13 ni14 ni15 ni16 ni19 ni20 ni21 ni23 /bin/rm -f in1 in2 in3 in4 in5 in6 - /bin/rm -f p1 p2 p3 ip1 + /bin/rm -f p1 p2 p3 p5 ip1 ip2 /bin/rm -f l1 /bin/rm -f ipv6.1 ipv6.2 ipv6.3 /bin/rm -f bpf1 bpf-f1 diff --git a/regress/sys/kern/ipf/expected/i12 b/regress/sys/kern/ipf/expected/i12 index e21724c7a25..dadf597fc3d 100644 --- a/regress/sys/kern/ipf/expected/i12 +++ b/regress/sys/kern/ipf/expected/i12 @@ -32,8 +32,8 @@ pass in proto udp from 3.3.3.3/32 to 6.6.6.6/32 port = 9 pass in from 10.10.10.10/32 to 11.11.11.11/32 pass in from pool/101(!) to hash/202(!) pass in from hash/303(!) to pool/404(!) -table role = ipf type = tree number = +table role = ipf type = tree name = { ! 1.1.1.1/32; 2.2.2.2/32; ! 2.2.0.0/16; }; -table role = ipf type = tree number = +table role = ipf type = tree name = { 1.1.0.0/16; }; pass in from pool/0(!) to pool/0(!) diff --git a/regress/sys/kern/ipf/expected/ni10 b/regress/sys/kern/ipf/expected/ni10 index df7b03f83fe..3ee63fb8ddd 100644 --- a/regress/sys/kern/ipf/expected/ni10 +++ b/regress/sys/kern/ipf/expected/ni10 @@ -1,5 +1,9 @@ 4500 003c 4706 4000 ff06 20a2 0404 0404 0606 0606 5000 0050 0000 0001 0000 0000 a002 16d0 d0da 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 + 4500 0038 0000 0000 ff01 afb9 0202 0202 0404 0404 0303 acab 0000 0000 4500 003c 4706 4000 ff06 28aa 0404 0404 0202 0202 5000 0050 0000 0001 + 4500 0058 0001 0000 ff01 af98 0202 0202 0404 0404 0303 0937 0000 0000 4500 003c 4706 4000 ff06 28aa 0404 0404 0202 0202 5000 0050 0000 0001 0000 0000 a002 16d0 d8e2 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 + 4500 0038 809a 0000 ff01 2b1b 0303 0303 0505 0505 0303 acab 0000 0000 4500 003c 4706 4000 ff06 28ab 0404 0404 0202 0201 5000 0050 0000 0001 + ------------------------------- diff --git a/regress/sys/kern/ipf/expected/ni11 b/regress/sys/kern/ipf/expected/ni11 index d6db012a2ab..88d6406e6ee 100644 --- a/regress/sys/kern/ipf/expected/ni11 +++ b/regress/sys/kern/ipf/expected/ni11 @@ -1,5 +1,9 @@ 4500 003c 4706 4000 ff06 2aac 0404 0404 0101 0101 5000 9d58 0000 0001 0000 0000 a002 16d0 3ddc 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 + 4500 0038 0000 0000 ff01 a7b9 0a02 0202 0404 0404 0303 a7fb 0000 0000 4500 003c 4706 4000 ff06 20aa 0404 0404 0a02 0202 5000 0500 0000 0001 + 4500 0058 0001 0000 ff01 a798 0a02 0202 0404 0404 0303 1137 0000 0000 4500 003c 4706 4000 ff06 20aa 0404 0404 0a02 0202 5000 0500 0000 0001 0000 0000 a002 16d0 cc32 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 + 4500 0038 809a 0000 ff01 2b1b 0303 0303 0505 0505 0303 0fa3 0000 0000 4500 003c 4706 4000 ff06 2aab 0404 0404 0101 0102 5000 9d58 0000 0001 + ------------------------------- diff --git a/regress/sys/kern/ipf/expected/ni3 b/regress/sys/kern/ipf/expected/ni3 index 600b6249a3e..107d5d93934 100644 --- a/regress/sys/kern/ipf/expected/ni3 +++ b/regress/sys/kern/ipf/expected/ni3 @@ -1,4 +1,7 @@ 4500 003c 0000 4000 ff06 67a8 0606 0606 0404 0404 5000 0050 0000 0001 0000 0000 a002 16d0 d0da 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 + 4500 0038 809a 0000 ff01 3121 0303 0303 0202 0202 0303 acab 0000 0000 4500 003c 4706 4000 ff06 28aa 0202 0202 0404 0404 5000 0050 0000 0001 + 4500 0058 809a 0000 ff01 3101 0303 0303 0202 0202 0303 0937 0000 0000 4500 003c 4706 4000 ff06 28aa 0202 0202 0404 0404 5000 0050 0000 0001 0000 0000 a002 16d0 d8e2 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300 + ------------------------------- diff --git a/regress/sys/kern/ipf/expected/ni5 b/regress/sys/kern/ipf/expected/ni5 index a64d8129820..72d72235a46 100644 --- a/regress/sys/kern/ipf/expected/ni5 +++ b/regress/sys/kern/ipf/expected/ni5 @@ -1,47 +1,93 @@ 4500 002c 0000 4000 ff06 02fc 0101 0101 96cb e002 8032 0015 bd6b c9c8 0000 0000 6002 2238 f5a2 0000 0204 05b4 + 4500 002c ffdd 4000 ef06 5374 96cb e002 c0a8 0103 0015 8032 3786 76c4 bd6b c9c9 6012 269c 8369 0000 0204 0584 + 4500 0028 0001 4000 ff06 02ff 0101 0101 96cb e002 8032 0015 bd6b c9c9 3786 76c5 5010 269c 5aa0 0000 + 4500 006f ffde 4000 ef06 5330 96cb e002 c0a8 0103 0015 8032 3786 76c5 bd6b c9c9 5018 269c 967e 0000 3232 302d 636f 6f6d 6273 2e61 6e75 2e65 6475 2e61 7520 4e63 4654 5064 2053 6572 7665 7220 2866 7265 6520 6564 7563 6174 696f 6e61 6c20 6c69 6365 6e73 6529 2072 6561 6479 2e0d 0a + 4500 0028 0002 4000 ff06 02fe 0101 0101 96cb e002 8032 0015 bd6b c9c9 3786 770c 5010 269c 5a59 0000 + 4500 00c7 ffdf 4000 ef06 52d7 96cb e002 c0a8 0103 0015 8032 3786 770c bd6b c9c9 5018 269c 1087 0000 3232 302d 0d0a 3232 302d 4d61 696e 7461 696e 6564 2062 7920 5253 5353 2061 6e64 2052 5350 4153 2049 5420 5374 6166 6620 2870 7265 7669 6f75 736c 7920 6b6e 6f77 6e20 6173 2043 6f6f 6d62 7320 436f 6d70 7574 696e 6720 556e 6974 290d 0a32 3230 2d41 6e79 2070 726f 626c 656d 7320 636f 6e74 6163 7420 6674 706d 6173 7465 7240 636f 6f6d 6273 2e61 6e75 2e65 6475 2e61 750d 0a32 3230 2d0d 0a32 3230 200d 0a + 4500 0028 0003 4000 ff06 02fd 0101 0101 96cb e002 8032 0015 bd6b c9c9 3786 77ab 5010 269c 59ba 0000 + 4500 0038 0004 4000 ff06 02ec 0101 0101 96cb e002 8032 0015 bd6b c9c9 3786 77ab 5018 269c d1c5 0000 5553 4552 2061 6e6f 6e79 6d6f 7573 0d0a + 4500 0028 ffe0 4000 ef06 5375 96cb e002 c0a8 0103 0015 8032 3786 77ab bd6b c9d9 5010 269c 9a00 0000 + 4500 006c ffe1 4000 ef06 5330 96cb e002 c0a8 0103 0015 8032 3786 77ab bd6b c9d9 5018 269c b00f 0000 3333 3120 4775 6573 7420 6c6f 6769 6e20 6f6b 2c20 7365 6e64 2079 6f75 7220 636f 6d70 6c65 7465 2065 2d6d 6169 6c20 6164 6472 6573 7320 6173 2070 6173 7377 6f72 642e 0d0a + 4500 0028 0005 4000 ff06 02fb 0101 0101 96cb e002 8032 0015 bd6b c9d9 3786 77ef 5010 269c 5966 0000 + 4500 0036 0006 4000 ff06 02ec 0101 0101 96cb e002 8032 0015 bd6b c9d9 3786 77ef 5018 269c 373f 0000 5041 5353 2061 7661 6c6f 6e40 0d0a + 4500 005f ffe2 4000 ef06 533c 96cb e002 c0a8 0103 0015 8032 3786 77ef bd6b c9e7 5018 269c 895e 0000 3233 302d 596f 7520 6172 6520 7573 6572 2023 3420 6f66 2035 3020 7369 6d75 6c74 616e 656f 7573 2075 7365 7273 2061 6c6c 6f77 6564 2e0d 0a + 4500 0028 0007 4000 ff06 02f9 0101 0101 96cb e002 8032 0015 bd6b c9e7 3786 7826 5010 269c 5921 0000 + 4500 0099 ffe3 4000 ef06 5301 96cb e002 c0a8 0103 0015 8032 3786 7826 bd6b c9e7 5018 269c d399 0000 3233 302d 0d0a 3233 302d 0d0a 3233 302d 4869 2e20 2057 6527 7265 2063 6c65 616e 696e 6720 7570 2e20 2041 6e79 2066 6565 6462 6163 6b20 6d6f 7374 2077 656c 636f 6d65 2e20 3130 2041 7567 2030 300d 0a32 3330 2d0d 0a32 3330 204c 6f67 6765 6420 696e 2061 6e6f 6e79 6d6f 7573 6c79 2e0d 0a + 4500 0028 0008 4000 ff06 02f8 0101 0101 96cb e002 8032 0015 bd6b c9e7 3786 7897 5010 269c 58b0 0000 + 4500 0030 0009 4000 ff06 02ef 0101 0101 96cb e002 8032 0015 bd6b c9e7 3786 7897 5018 269c 86ae 0000 5459 5045 2049 0d0a + 4500 0038 ffe4 4000 ef06 5361 96cb e002 c0a8 0103 0015 8032 3786 7897 bd6b c9ef 5018 269c 5fae 0000 3230 3020 5479 7065 206f 6b61 792e 0d0a + 4500 0028 000a 4000 ff06 02f6 0101 0101 96cb e002 8032 0015 bd6b c9ef 3786 78a7 5010 269c 5898 0000 + 4500 003d 000b 4000 ff06 02e0 0101 0101 96cb e002 8032 0015 bd6b c9ef 3786 78a7 5018 269c 4b67 0000 504f 5254 2031 2c31 2c31 2c31 2c31 3238 2c35 310d 0a + 4500 0046 ffe5 4000 ef06 5352 96cb e002 c0a8 0103 0015 8032 3786 78a7 bd6b ca0c 5018 269c dbc3 0000 3230 3020 504f 5254 2063 6f6d 6d61 6e64 2073 7563 6365 7373 6675 6c2e 0d0a + 4500 0030 000c 4000 ff06 02ec 0101 0101 96cb e002 8032 0015 bd6b ca04 3786 78c5 5018 269c 866b 0000 5459 5045 2041 0d0a + 4500 0038 ffe6 4000 ef06 535f 96cb e002 c0a8 0103 0015 8032 3786 78c5 bd6b ca14 5018 269c 5f5b 0000 3230 3020 5479 7065 206f 6b61 792e 0d0a + 4500 002e 000d 4000 ff06 02ed 0101 0101 96cb e002 8032 0015 bd6b ca0c 3786 78d5 5018 269c a994 0000 4e4c 5354 0d0a + 4500 002c ffe7 4000 ef06 536a 96cb e002 c0a8 0103 0014 8033 d9f8 11d4 0000 0000 6002 2238 d190 0000 0204 0584 + 4500 002c 000e 4000 ff06 02ee 0101 0101 96cb e002 8033 0014 bd78 5c12 d9f8 11d5 6012 02f8 96de 0000 0204 0584 + 4500 0028 ffe8 4000 ef06 536d 96cb e002 c0a8 0103 0014 8033 d9f8 11d5 bd78 5c13 5010 269c cb1d 0000 + 4500 005d ffe9 4000 ef06 5337 96cb e002 c0a8 0103 0015 8032 3786 78d5 bd6b ca1a 5018 269c eed0 0000 3135 3020 4f70 656e 696e 6720 4153 4349 4920 6d6f 6465 2064 6174 6120 636f 6e6e 6563 7469 6f6e 2066 6f72 202f 6269 6e2f 6c73 2e0d 0a + 4500 0028 000f 4000 ff06 02f1 0101 0101 96cb e002 8033 0014 bd78 5c13 d9f8 11d5 5010 6348 4e1b 0000 + 4500 0063 ffea 4000 ef06 5330 96cb e002 c0a8 0103 0014 8033 d9f8 11d5 bd78 5c13 5018 269c a315 0000 636f 6f6d 6273 7061 7065 7273 0d0a 6465 7074 730d 0a66 6f75 6e64 2d66 696c 6573 0d0a 696e 636f 6d69 6e67 0d0a 6e6c 632d 7465 7374 0d0a 7075 620d 0a + 4500 0028 0010 4000 ff06 02f0 0101 0101 96cb e002 8033 0014 bd78 5c13 d9f8 1210 5010 6348 4de0 0000 + 4500 0028 ffeb 4000 ef06 536a 96cb e002 c0a8 0103 0014 8033 d9f8 1210 bd78 5c13 5011 269c cae1 0000 + 4500 0028 10da 4000 ff06 327c c0a8 0103 96cb e002 8033 0014 bd78 5c13 d9f8 1211 5010 6348 8e35 0000 + 4500 0028 10db 4000 ff06 327b c0a8 0103 96cb e002 8033 0014 bd78 5c13 d9f8 1211 5011 6348 8e34 0000 + 4500 0028 ffec 4000 ef06 5369 96cb e002 c0a8 0103 0014 8033 d9f8 1211 bd78 5c14 5010 269c cae0 0000 + 4500 0028 0011 4000 ff06 02ef 0101 0101 96cb e002 8032 0015 bd6b ca12 3786 790a 5010 269c 5812 0000 + 4500 0040 ffed 4000 ef06 5350 96cb e002 c0a8 0103 0015 8032 3786 790a bd6b ca1a 5018 269c 7c9e 0000 3232 3620 4c69 7374 696e 6720 636f 6d70 6c65 7465 642e 0d0a + 4500 0030 0012 4000 ff06 02e6 0101 0101 96cb e002 8032 0015 bd6b ca12 3786 7922 5018 269c 85f8 0000 5459 5045 2049 0d0a + 4500 0038 ffee 4000 ef06 5357 96cb e002 c0a8 0103 0015 8032 3786 7922 bd6b ca22 5018 269c 5ef0 0000 3230 3020 5479 7065 206f 6b61 792e 0d0a + 4500 0028 0013 4000 ff06 02ed 0101 0101 96cb e002 8032 0015 bd6b ca1a 3786 7932 5010 269c 57e2 0000 + 4500 002e 0014 4000 ff06 02e6 0101 0101 96cb e002 8032 0015 bd6b ca1a 3786 7932 5018 269c b020 0000 5155 4954 0d0a + 4500 0036 ffef 4000 ef06 5358 96cb e002 c0a8 0103 0015 8032 3786 7932 bd6b ca28 5018 269c a93c 0000 3232 3120 476f 6f64 6279 652e 0d0a + 4500 0028 0015 4000 ff06 02eb 0101 0101 96cb e002 8032 0015 bd6b ca20 3786 7940 5011 269c 57cd 0000 + 4500 0028 fff0 4000 ef06 5365 96cb e002 c0a8 0103 0015 8032 3786 7940 bd6b ca28 5011 269c 981b 0000 + 4500 0028 10e1 4000 ff06 3275 c0a8 0103 96cb e002 8032 0015 bd6b ca25 3786 7941 5010 269c 981e 0000 + 4500 0028 fff1 4000 ef06 5364 96cb e002 c0a8 0103 0015 8032 3786 7941 bd6b ca29 5010 269c 981a 0000 + ------------------------------- diff --git a/regress/sys/kern/ipf/input/ipv6.1 b/regress/sys/kern/ipf/input/ipv6.1 index 39208103edd..3f0fd308102 100644 --- a/regress/sys/kern/ipf/input/ipv6.1 +++ b/regress/sys/kern/ipf/input/ipv6.1 @@ -18,3 +18,15 @@ ef00 1001 2002 0001 0000 0000 0000 0070 f427 0000 0344 0000 0004 f8f1 9d3c ddba 0e00 +[in,gif0] 6000 0000 0048 3a40 +ef00 1001 0880 6cbf 0000 0000 0000 0001 +ef00 1001 2002 0001 0000 0000 0000 0070 +0300 7d44 0000 0000 +6000 0000 0018 1101 +ef00 1001 2002 1001 0000 0000 0000 0070 +2001 1002 3333 0001 0000 0000 0000 0001 +8083 829a +0018 +f427 +0000 0344 0000 0004 f8f1 9d3c ddba 0e00 + diff --git a/regress/sys/kern/ipf/input/ni3 b/regress/sys/kern/ipf/input/ni3 index feb4b29b1ec..66b22a6d429 100644 --- a/regress/sys/kern/ipf/input/ni3 +++ b/regress/sys/kern/ipf/input/ni3 @@ -3,7 +3,7 @@ # going out) [out,df0] 45 00 00 3c 47 06 40 00 ff 06 28 aa 02 02 02 02 04 04 04 04 50 00 00 50 00 00 00 01 00 00 00 00 a0 02 16 d0 d8 e2 00 00 02 04 05 b4 04 02 08 0a 00 47 fb b0 00 00 00 00 01 03 03 00 -[in,df0] 45 00 00 38 80 9a 00 00 ff 01 29 19 03 03 03 03 06 06 06 06 03 03 ac ac 00 00 00 00 45 00 00 3c 47 06 40 00 ff 06 20 a2 06 06 06 06 04 04 04 04 50 00 00 50 00 00 00 01 +[in,df0] 45 00 00 38 80 9a 00 00 ff 01 29 19 03 03 03 03 06 06 06 06 03 03 ac ab 00 00 00 00 45 00 00 3c 47 06 40 00 ff 06 20 a2 06 06 06 06 04 04 04 04 50 00 00 50 00 00 00 01 # ICMP dest unreachable with whole packet in payload (40 bytes = 320 bits) [in,df0] 45 00 00 58 80 9a 00 00 ff 01 28 f9 03 03 03 03 06 06 06 06 03 03 11 3f 00 00 00 00 45 00 00 3c 47 06 40 00 ff 06 20 a2 06 06 06 06 04 04 04 04 50 00 00 50 00 00 00 01 00 00 00 00 a0 02 16 d0 d0 da 00 00 02 04 05 b4 04 02 08 0a 00 47 fb b0 00 00 00 00 01 03 03 00 diff --git a/regress/sys/kern/ipf/natipftest b/regress/sys/kern/ipf/natipftest index 0d0a064b54f..d0b0974377b 100644 --- a/regress/sys/kern/ipf/natipftest +++ b/regress/sys/kern/ipf/natipftest @@ -1,20 +1,32 @@ #!/bin/sh # -# $NetBSD: natipftest,v 1.4 2006/04/04 16:17:19 martti Exp $ +# $NetBSD: natipftest,v 1.5 2007/04/14 20:34:40 martin Exp $ # TESTDIR=$1 shift mode=$1 +name=$2 +input=$3 +output=$4 shift -if [ $3 = hex ] ; then - format="-xF $2" +if [ $output = hex ] ; then + format="-xF $input" else - format="-F $2" -fi -if [ "$4" != "" ] ; then - format="-T $4 $format" + format="-F $input" fi +shift +shift +shift +while [ $# -ge 1 ] ; do + l=`echo $1 | cut -c1` + if [ "$l" = "-" ] ; then + format="$format $1" + else + format="-T $1 $format" + fi + shift +done mkdir -p results if [ -f /usr/ucb/touch ] ; then TOUCH=/usr/ucb/touch @@ -30,35 +42,35 @@ fi case $mode in single) - echo "$1..."; - /bin/cp /dev/null results/$1 + echo "$name..."; + /bin/cp /dev/null results/$name ( while read rule; do - echo "$rule" | ipftest -R $format -b -r ${TESTDIR}/regress/$1.ipf -N - -i ${TESTDIR}/input/$1 >> \ - results/$1; + echo "$rule" | ipftest -R $format -b -r ${TESTDIR}/regress/$name.ipf -N - -i ${TESTDIR}/input/$name >> \ + results/$name; if [ $? -ne 0 ] ; then exit 1; fi - echo "-------------------------------" >> results/$1 - done ) < ${TESTDIR}/regress/$1.nat - cmp ${TESTDIR}/expected/$1 results/$1 + echo "-------------------------------" >> results/$name + done ) < ${TESTDIR}/regress/$name.nat + cmp ${TESTDIR}/expected/$name results/$name status=$? if [ $status = 0 ] ; then - $TOUCH $1 + $TOUCH $name fi ;; multi) - echo "$1..."; - /bin/cp /dev/null results/$1 - ipftest -R $format -b -r ${TESTDIR}/regress/$1.ipf -N ${TESTDIR}/regress/$1.nat \ - -i ${TESTDIR}/input/$1 >> results/$1; + echo "$name..."; + /bin/cp /dev/null results/$name + ipftest -R $format -b -r ${TESTDIR}/regress/$name.ipf -N ${TESTDIR}/regress/$name.nat \ + -i ${TESTDIR}/input/$name >> results/$name; if [ $? -ne 0 ] ; then exit 2; fi - echo "-------------------------------" >> results/$1 - cmp ${TESTDIR}/expected/$1 results/$1 + echo "-------------------------------" >> results/$name + cmp ${TESTDIR}/expected/$name results/$name status=$? if [ $status = 0 ] ; then - $TOUCH $1 + $TOUCH $name fi ;; esac diff --git a/sys/dist/ipf/netinet/fil.c b/sys/dist/ipf/netinet/fil.c index 2cd40661b59..8e6da883eb6 100644 --- a/sys/dist/ipf/netinet/fil.c +++ b/sys/dist/ipf/netinet/fil.c @@ -1,4 +1,4 @@ -/* $NetBSD: fil.c,v 1.29 2007/03/04 06:02:54 christos Exp $ */ +/* $NetBSD: fil.c,v 1.30 2007/04/14 20:34:35 martin Exp $ */ /* * Copyright (C) 1993-2003 by Darren Reed. @@ -17,7 +17,11 @@ #include <sys/time.h> #if defined(__NetBSD__) # if (NetBSD >= 199905) && !defined(IPFILTER_LKM) && defined(_KERNEL) -# include "opt_ipfilter.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> @@ -140,10 +154,10 @@ struct file; #if !defined(lint) #if defined(__NetBSD__) #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: fil.c,v 1.29 2007/03/04 06:02:54 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fil.c,v 1.30 2007/04/14 20:34:35 martin Exp $"); #else static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)Id: fil.c,v 2.243.2.78 2006/03/29 11:19:54 darrenr Exp"; +static const char rcsid[] = "@(#)Id: fil.c,v 2.243.2.99 2007/02/17 12:41:41 darrenr Exp"; #endif #endif @@ -237,11 +251,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 *)); /* @@ -708,6 +725,8 @@ fr_info_t *fin; return; if (fin->fin_dlen > 1) { + ip6_t *ip6; + icmp6 = fin->fin_dp; fin->fin_data[0] = *(u_short *)icmp6; @@ -722,12 +741,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 : @@ -864,18 +897,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; } @@ -989,6 +1030,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; @@ -1509,18 +1566,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; @@ -1682,7 +1745,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; @@ -1693,7 +1756,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; @@ -1716,20 +1779,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; @@ -1758,20 +1821,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; @@ -2299,9 +2362,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 @@ -2397,13 +2457,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 { @@ -2411,7 +2468,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) { @@ -2441,8 +2497,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; } @@ -2466,8 +2521,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) @@ -2509,8 +2563,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); @@ -2522,20 +2575,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; } /* @@ -3075,7 +3134,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.99 2007/02/17 12:41:41 darrenr Exp */ /* * Copy data from an mbuf chain starting "off" bytes from the beginning, @@ -3666,13 +3725,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 @@ -3744,17 +3805,19 @@ void *src, *dst; size_t size; { void *ca; - int err; + int error; # if SOLARIS - err = COPYIN(src, (void *)&ca, sizeof(ca)); - if (err != 0) - return err; + error = COPYIN(src, (caddr_t)&ca, sizeof(ca)); + if (error != 0) + return error; # else bcopy(src, (void *)&ca, sizeof(ca)); # endif - err = COPYIN(ca, dst, size); - return err; + error = COPYIN(ca, dst, size); + if (error != 0) + error = EFAULT; + return error; } @@ -3774,11 +3837,13 @@ void *src, *dst; size_t size; { void *ca; - int err; + int error; - bcopy(dst, (void *)&ca, sizeof(ca)); - err = COPYOUT(src, ca, size); - return err; + bcopy(dst, &ca, sizeof(ca)); + error = COPYOUT(src, ca, size); + if (error != 0) + error = EFAULT; + return error; } #endif @@ -3798,8 +3863,8 @@ int *lockp; { int arg; - BCOPYIN(data, (void *)&arg, sizeof(arg)); - BCOPYOUT((void *)lockp, data, sizeof(*lockp)); + BCOPYIN(data, &arg, sizeof(arg)); + BCOPYOUT(lockp, data, sizeof(*lockp)); *lockp = arg; } @@ -3954,7 +4019,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. */ /* */ @@ -3963,20 +4029,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); @@ -4148,16 +4229,6 @@ void *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. */ @@ -4167,6 +4238,8 @@ void *data; if (!ptr) return ENOMEM; error = COPYIN(uptr, ptr, fp->fr_dsize); + if (error != 0) + error = EFAULT; } else { ptr = uptr; error = 0; @@ -4225,8 +4298,11 @@ void *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 : @@ -4250,8 +4326,11 @@ void *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 : @@ -4292,6 +4371,20 @@ void *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) { @@ -4335,6 +4428,8 @@ void *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; @@ -4431,7 +4526,7 @@ void *data; fr_fixskip(ftail, f, -1); *ftail = f->fr_next; f->fr_next = NULL; - (void)fr_derefrule(&f); + (void) fr_derefrule(&f); } } else { /* @@ -4645,6 +4740,7 @@ frentry_t **frp; frentry_t *fr; fr = *frp; + *frp = NULL; MUTEX_ENTER(&fr->fr_lock); fr->fr_ref--; @@ -4670,7 +4766,6 @@ frentry_t **frp; } else { MUTEX_EXIT(&fr->fr_lock); } - *frp = NULL; return -1; } @@ -5200,55 +5295,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; @@ -5256,7 +5343,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; @@ -5264,7 +5351,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; @@ -5282,9 +5369,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) }, @@ -5298,7 +5383,12 @@ 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) } }; @@ -5321,7 +5411,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((void *)data, (void *)&obj, sizeof(obj)); @@ -5333,8 +5423,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 */ @@ -5355,6 +5446,8 @@ int type; error = COPYIN((void *)obj.ipfo_ptr, (void *)ptr, obj.ipfo_size); } + if (error != 0) + error = EFAULT; return error; } @@ -5381,7 +5474,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; @@ -5404,6 +5497,8 @@ int type, sz; #endif error = COPYIN((void *)obj.ipfo_ptr, (void *)ptr, sz); + if (error != 0) + error = EFAULT; return error; } @@ -5430,7 +5525,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; @@ -5453,6 +5548,8 @@ int type, sz; #endif error = COPYOUT((void *)ptr, (void *)obj.ipfo_ptr, sz); + if (error != 0) + error = EFAULT; return error; } @@ -5476,7 +5573,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((void *)data, (void *)&obj, sizeof(obj)); @@ -5504,6 +5601,8 @@ int type; #endif error = COPYOUT((void *)ptr, (void *)obj.ipfo_ptr, obj.ipfo_size); + if (error != 0) + error = EFAULT; return error; } @@ -5781,98 +5880,98 @@ fr_info_t *fin; ipftuneable_t ipf_tuneables[] = { /* filtering */ { { &fr_flags }, "fr_flags", 0, 0xffffffff, - sizeof(fr_flags), 0, NULL }, + sizeof(fr_flags), 0, NULL }, { { &fr_active }, "fr_active", 0, 0, - sizeof(fr_active), IPFT_RDONLY, NULL }, + sizeof(fr_active), IPFT_RDONLY, NULL }, { { &fr_control_forwarding }, "fr_control_forwarding", 0, 1, - sizeof(fr_control_forwarding), 0, NULL }, + sizeof(fr_control_forwarding), 0, NULL }, { { &fr_update_ipid }, "fr_update_ipid", 0, 1, - sizeof(fr_update_ipid), 0, NULL }, + sizeof(fr_update_ipid), 0, NULL }, { { &fr_chksrc }, "fr_chksrc", 0, 1, - sizeof(fr_chksrc), 0, NULL }, + sizeof(fr_chksrc), 0, NULL }, { { &fr_minttl }, "fr_minttl", 0, 1, - sizeof(fr_minttl), 0, NULL }, + sizeof(fr_minttl), 0, NULL }, { { &fr_icmpminfragmtu }, "fr_icmpminfragmtu", 0, 1, - sizeof(fr_icmpminfragmtu), 0, NULL }, + sizeof(fr_icmpminfragmtu), 0, NULL }, { { &fr_pass }, "fr_pass", 0, 0xffffffff, - sizeof(fr_pass), 0, NULL }, + sizeof(fr_pass), 0, NULL }, /* state */ { { &fr_tcpidletimeout }, "fr_tcpidletimeout", 1, 0x7fffffff, - sizeof(fr_tcpidletimeout), IPFT_WRDISABLED, NULL }, + sizeof(fr_tcpidletimeout), IPFT_WRDISABLED, NULL }, { { &fr_tcpclosewait }, "fr_tcpclosewait", 1, 0x7fffffff, - sizeof(fr_tcpclosewait), IPFT_WRDISABLED, NULL }, + sizeof(fr_tcpclosewait), IPFT_WRDISABLED, NULL }, { { &fr_tcplastack }, "fr_tcplastack", 1, 0x7fffffff, - sizeof(fr_tcplastack), IPFT_WRDISABLED, NULL }, + sizeof(fr_tcplastack), IPFT_WRDISABLED, NULL }, { { &fr_tcptimeout }, "fr_tcptimeout", 1, 0x7fffffff, - sizeof(fr_tcptimeout), IPFT_WRDISABLED, NULL }, + sizeof(fr_tcptimeout), IPFT_WRDISABLED, NULL }, { { &fr_tcpclosed }, "fr_tcpclosed", 1, 0x7fffffff, - sizeof(fr_tcpclosed), IPFT_WRDISABLED, NULL }, + sizeof(fr_tcpclosed), IPFT_WRDISABLED, NULL }, { { &fr_tcphalfclosed }, "fr_tcphalfclosed", 1, 0x7fffffff, - sizeof(fr_tcphalfclosed), IPFT_WRDISABLED, NULL }, + sizeof(fr_tcphalfclosed), IPFT_WRDISABLED, NULL }, { { &fr_udptimeout }, "fr_udptimeout", 1, 0x7fffffff, - sizeof(fr_udptimeout), IPFT_WRDISABLED, NULL }, + sizeof(fr_udptimeout), IPFT_WRDISABLED, NULL }, { { &fr_udpacktimeout }, "fr_udpacktimeout", 1, 0x7fffffff, - sizeof(fr_udpacktimeout), IPFT_WRDISABLED, NULL }, + sizeof(fr_udpacktimeout), IPFT_WRDISABLED, NULL }, { { &fr_icmptimeout }, "fr_icmptimeout", 1, 0x7fffffff, - sizeof(fr_icmptimeout), IPFT_WRDISABLED, NULL }, + sizeof(fr_icmptimeout), IPFT_WRDISABLED, NULL }, { { &fr_icmpacktimeout }, "fr_icmpacktimeout", 1, 0x7fffffff, - sizeof(fr_icmpacktimeout), IPFT_WRDISABLED, NULL }, + sizeof(fr_icmpacktimeout), IPFT_WRDISABLED, NULL }, { { &fr_iptimeout }, "fr_iptimeout", 1, 0x7fffffff, - sizeof(fr_iptimeout), IPFT_WRDISABLED, NULL }, + sizeof(fr_iptimeout), IPFT_WRDISABLED, NULL }, { { &fr_statemax }, "fr_statemax", 1, 0x7fffffff, - sizeof(fr_statemax), 0, NULL }, + sizeof(fr_statemax), 0, NULL }, { { &fr_statesize }, "fr_statesize", 1, 0x7fffffff, - sizeof(fr_statesize), IPFT_WRDISABLED, NULL }, + sizeof(fr_statesize), IPFT_WRDISABLED, NULL }, { { &fr_state_lock }, "fr_state_lock", 0, 1, - sizeof(fr_state_lock), IPFT_RDONLY, NULL }, + sizeof(fr_state_lock), IPFT_RDONLY, NULL }, { { &fr_state_maxbucket }, "fr_state_maxbucket", 1, 0x7fffffff, - sizeof(fr_state_maxbucket), IPFT_WRDISABLED, NULL }, + sizeof(fr_state_maxbucket), IPFT_WRDISABLED, NULL }, { { &fr_state_maxbucket_reset }, "fr_state_maxbucket_reset", 0, 1, - sizeof(fr_state_maxbucket_reset), IPFT_WRDISABLED, NULL }, + sizeof(fr_state_maxbucket_reset), IPFT_WRDISABLED, NULL }, { { &ipstate_logging }, "ipstate_logging", 0, 1, - sizeof(ipstate_logging), 0, NULL }, + sizeof(ipstate_logging), 0, NULL }, /* nat */ { { &fr_nat_lock }, "fr_nat_lock", 0, 1, - sizeof(fr_nat_lock), IPFT_RDONLY, NULL }, + sizeof(fr_nat_lock), IPFT_RDONLY, NULL }, { { &ipf_nattable_sz }, "ipf_nattable_sz", 1, 0x7fffffff, - sizeof(ipf_nattable_sz), IPFT_WRDISABLED, NULL }, + sizeof(ipf_nattable_sz), IPFT_WRDISABLED, NULL }, { { &ipf_nattable_max }, "ipf_nattable_max", 1, 0x7fffffff, - sizeof(ipf_nattable_max), 0, NULL }, + sizeof(ipf_nattable_max), 0, NULL }, { { &ipf_natrules_sz }, "ipf_natrules_sz", 1, 0x7fffffff, - sizeof(ipf_natrules_sz), IPFT_WRDISABLED, NULL }, + sizeof(ipf_natrules_sz), IPFT_WRDISABLED, NULL }, { { &ipf_rdrrules_sz }, "ipf_rdrrules_sz", 1, 0x7fffffff, - sizeof(ipf_rdrrules_sz), IPFT_WRDISABLED, NULL }, + sizeof(ipf_rdrrules_sz), IPFT_WRDISABLED, NULL }, { { &ipf_hostmap_sz }, "ipf_hostmap_sz", 1, 0x7fffffff, - sizeof(ipf_hostmap_sz), IPFT_WRDISABLED, NULL }, + sizeof(ipf_hostmap_sz), IPFT_WRDISABLED, NULL }, { { &fr_nat_maxbucket }, "fr_nat_maxbucket", 1, 0x7fffffff, - sizeof(fr_nat_maxbucket), IPFT_WRDISABLED, NULL }, + sizeof(fr_nat_maxbucket), IPFT_WRDISABLED, NULL }, { { &fr_nat_maxbucket_reset }, "fr_nat_maxbucket_reset", 0, 1, - sizeof(fr_nat_maxbucket_reset), IPFT_WRDISABLED, NULL }, + sizeof(fr_nat_maxbucket_reset), IPFT_WRDISABLED, NULL }, { { &nat_logging }, "nat_logging", 0, 1, - sizeof(nat_logging), 0, NULL }, + sizeof(nat_logging), 0, NULL }, { { &fr_defnatage }, "fr_defnatage", 1, 0x7fffffff, - sizeof(fr_defnatage), IPFT_WRDISABLED, NULL }, + sizeof(fr_defnatage), IPFT_WRDISABLED, NULL }, { { &fr_defnatipage }, "fr_defnatipage", 1, 0x7fffffff, - sizeof(fr_defnatipage), IPFT_WRDISABLED, NULL }, + sizeof(fr_defnatipage), IPFT_WRDISABLED, NULL }, { { &fr_defnaticmpage }, "fr_defnaticmpage", 1, 0x7fffffff, - sizeof(fr_defnaticmpage), IPFT_WRDISABLED, NULL }, + sizeof(fr_defnaticmpage), IPFT_WRDISABLED, NULL }, + { { &fr_nat_doflush }, "fr_nat_doflush", 0, 1, + sizeof(fr_nat_doflush), 0, NULL }, /* frag */ { { &ipfr_size }, "ipfr_size", 1, 0x7fffffff, - sizeof(ipfr_size), IPFT_WRDISABLED, NULL }, + sizeof(ipfr_size), IPFT_WRDISABLED, NULL }, { { &fr_ipfrttl }, "fr_ipfrttl", 1, 0x7fffffff, - sizeof(fr_ipfrttl), IPFT_WRDISABLED, NULL }, + sizeof(fr_ipfrttl), IPFT_WRDISABLED, NULL }, #ifdef IPFILTER_LOG /* log */ { { &ipl_suppress }, "ipl_suppress", 0, 1, - sizeof(ipl_suppress), 0, NULL }, - { { &ipl_buffer_sz }, "ipl_buffer_sz", 0, 0, - sizeof(ipl_buffer_sz), IPFT_RDONLY, NULL }, + sizeof(ipl_suppress), 0, NULL }, { { &ipl_logmax }, "ipl_logmax", 0, 0x7fffffff, - sizeof(ipl_logmax), IPFT_WRDISABLED, NULL }, + sizeof(ipl_logmax), IPFT_WRDISABLED, NULL }, { { &ipl_logall }, "ipl_logall", 0, 1, - sizeof(ipl_logall), 0, NULL }, + sizeof(ipl_logall), 0, NULL }, { { &ipl_logsize }, "ipl_logsize", 0, 0x80000, - sizeof(ipl_logsize), 0, NULL }, + sizeof(ipl_logsize), 0, NULL }, #endif { { NULL }, NULL, 0, 0, 0, 0, NULL } @@ -6371,3 +6470,636 @@ void *fr_resolvenic(char *name, 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. */ +/* ------------------------------------------------------------------------ */ +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; + count = 1; + t->ipt_data = next; + } + 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) +#if __NetBSD_Version__ >= 499001000 +void *data; +#else +caddr_t data; +#endif +ioctlcmd_t cmd; +int mode, uid; +void *ctx; +{ + friostat_t fio; + int error = 0, tmp; + + switch (cmd) + { + case SIOCFRENB : + if (!(mode & FWRITE)) + error = EPERM; + else { + BCOPYIN(data, &tmp, sizeof(tmp)); + + RWLOCK_EXIT(&ipf_global); + WRITE_ENTER(&ipf_global); + if (tmp) { + if (fr_running > 0) + error = 0; + else + error = iplattach(); + if (error == 0) + fr_running = 1; + else + (void) ipldetach(); + } else { + error = ipldetach(); + if (error == 0) + fr_running = -1; + } + } + break; + + case SIOCIPFSET : + if (!(mode & FWRITE)) { + error = EPERM; + break; + } + /* FALLTHRU */ + case SIOCIPFGETNEXT : + case SIOCIPFGET : + error = fr_ipftune(cmd, (void *)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((void *)data); + break; + + case SIOCINAFR : + case SIOCRMAFR : + case SIOCADAFR : + case SIOCZRLST : + if (!(mode & FWRITE)) + error = EPERM; + else + error = frrequest(IPL_LOGIPF, cmd, data, + fr_active, 1); + break; + + case SIOCINIFR : + case SIOCRMIFR : + case SIOCADIFR : + if (!(mode & FWRITE)) + error = EPERM; + else + error = frrequest(IPL_LOGIPF, cmd, 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); + BCOPYOUT(&fr_active, data, sizeof(fr_active)); + 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(data); + break; + + case SIOCIPFFL : + if (!(mode & FWRITE)) + error = EPERM; + else { + BCOPYIN(data, &tmp, sizeof(tmp)); + tmp = frflush(IPL_LOGIPF, 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(IPL_LOGIPF, 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 { + tmp = ipflog_clear(IPL_LOGIPF); + BCOPYOUT(&tmp, data, sizeof(tmp)); + } + 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]; + + BCOPYOUT(&tmp, data, sizeof(tmp)); + break; +#endif + + case SIOCIPFITER : + error = ipf_frruleiter(data, uid, ctx); + break; + + case SIOCGENITER : + error = ipf_genericiter(data, uid, ctx); + break; + + case SIOCIPFDELTOK : + BCOPYIN(data, &tmp, sizeof(tmp)); + error = ipf_deltoken(tmp, uid, ctx); + break; + + default : + error = EINVAL; + break; + } + + return error; +} diff --git a/sys/dist/ipf/netinet/ip_auth.c b/sys/dist/ipf/netinet/ip_auth.c index 899528eade0..4f752a7bc6d 100644 --- a/sys/dist/ipf/netinet/ip_auth.c +++ b/sys/dist/ipf/netinet/ip_auth.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_auth.c,v 1.9 2007/03/04 06:02:55 christos Exp $ */ +/* $NetBSD: ip_auth.c,v 1.10 2007/04/14 20:34:35 martin Exp $ */ /* * Copyright (C) 1998-2003 by Darren Reed & Guido van Rooij. @@ -121,9 +121,9 @@ extern struct ifqueue ipintrq; /* ip packet input queue */ #if !defined(lint) #if defined(__NetBSD__) #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ip_auth.c,v 1.9 2007/03/04 06:02:55 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_auth.c,v 1.10 2007/04/14 20:34:35 martin Exp $"); #else -static const char rcsid[] = "@(#)Id: ip_auth.c,v 2.73.2.13 2006/03/29 11:19:55 darrenr Exp"; +static const char rcsid[] = "@(#)Id: ip_auth.c,v 2.73.2.18 2006/12/16 17:12:56 darrenr Exp"; #endif #endif @@ -149,7 +149,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)); @@ -179,11 +191,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; @@ -240,7 +257,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; @@ -282,11 +304,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; @@ -366,23 +393,57 @@ 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) void *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; + + token = ipf_findtoken(IPFGENITER_AUTH, uid, ctx); + if (token != NULL) + error = fr_authgeniter(token, &iter); + else + error = ESRCH; + RWLOCK_EXIT(&ipf_tokens); + + 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; @@ -402,206 +463,15 @@ int mode; i = fr_authflush(); RWLOCK_EXIT(&ipf_auth); SPL_X(s); - error = copyoutptr((char *)&i, data, sizeof(i)); + BCOPYOUT((char *)&i, data, sizeof(i)); 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 INET -# 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 (_BSDI_VERSION >= 199802) || defined(__OpenBSD__) || \ - (defined(__sgi) && (IRIX >= 60500) || defined(AIX) || \ - (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 */ -#endif - if (error != 0) - fr_authstats.fas_sendfail++; - else - fr_authstats.fas_sendok++; - } else if (m) { -#ifdef INET -# 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 */ -#endif - 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 : @@ -612,9 +482,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; @@ -668,17 +542,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) @@ -697,11 +575,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; @@ -722,6 +602,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; @@ -732,7 +621,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; @@ -766,6 +655,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; @@ -780,11 +670,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; @@ -816,7 +713,336 @@ 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); + } 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); + } + token->ipt_data = next; + + /* + * 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/dist/ipf/netinet/ip_auth.h b/sys/dist/ipf/netinet/ip_auth.h index eb72a983687..2589e90804d 100644 --- a/sys/dist/ipf/netinet/ip_auth.h +++ b/sys/dist/ipf/netinet/ip_auth.h @@ -1,11 +1,11 @@ -/* $NetBSD: ip_auth.h,v 1.4 2007/03/04 06:02:55 christos Exp $ */ +/* $NetBSD: ip_auth.h,v 1.5 2007/04/14 20:34:36 martin Exp $ */ /* * Copyright (C) 1997-2001 by Darren Reed & Guido Van Rooij. * * See the IPFILTER.LICENCE file for details on licencing. * - * Id: ip_auth.h,v 2.16.2.2 2006/03/16 06:45:49 darrenr Exp + * Id: ip_auth.h,v 2.16.2.3 2006/07/14 06:12:05 darrenr Exp * */ #ifndef _NETINET_IP_AUTH_H_ @@ -29,7 +29,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 { @@ -62,7 +64,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((void *, ioctlcmd_t, int)); +extern int fr_auth_ioctl __P((void *, ioctlcmd_t, int, int, void *)); extern int fr_auth_waiting __P((void)); #endif /* __IP_AUTH_H__ */ diff --git a/sys/dist/ipf/netinet/ip_compat.h b/sys/dist/ipf/netinet/ip_compat.h index a1eb83b9dd1..fe2058920df 100644 --- a/sys/dist/ipf/netinet/ip_compat.h +++ b/sys/dist/ipf/netinet/ip_compat.h @@ -1,4 +1,4 @@ -/* $NetBSD: ip_compat.h,v 1.12 2007/03/04 06:02:55 christos Exp $ */ +/* $NetBSD: ip_compat.h,v 1.13 2007/04/14 20:34:36 martin Exp $ */ /* * Copyright (C) 1993-2001, 2003 by Darren Reed. @@ -6,7 +6,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_compat.h 1.8 1/14/96 - * Id: ip_compat.h,v 2.142.2.36 2006/03/26 05:50:29 darrenr Exp + * Id: ip_compat.h,v 2.142.2.41 2007/01/17 11:34:54 darrenr Exp */ #ifndef _NETINET_IP_COMPAT_H_ @@ -238,11 +238,11 @@ typedef unsigned int u_32_t; # define MUTEX_DESTROY(x) mutex_destroy(&(x)->ipf_lk) # define MUTEX_NUKE(x) bzero((x), sizeof(*(x))) # define MUTEX_EXIT(x) mutex_exit(&(x)->ipf_lk) -# define COPYIN(a,b,c) copyin((void *)(a), (void *)(b), (c)) -# define COPYOUT(a,b,c) copyout((void *)(a), (void *)(b), (c)) -# define BCOPYIN(a,b,c) (void) copyin((void *)(a), (void *)(b), (c)) -# define BCOPYOUT(a,b,c) (void) copyout((void *)(a), (void *)(b), (c)) -# define UIOMOVE(a,b,c,d) uiomove((void *)a,b,c,d) +# 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) 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_NET(x) ; @@ -415,15 +415,8 @@ typedef struct iplog_select_s { # define RWLOCK_EXIT(x) MUTEX_EXIT(x) # endif # define RW_DESTROY(x) -# define COPYIN(a,b,c) copyin((void *)(a), (void *)(b), (c)) -# define COPYOUT(a,b,c) copyout((void *)(a), (void *)(b), (c)) -# if HPUXREV >= 1111 -# define BCOPYIN(a,b,c) 0; bcopy((void *)(a), (void *)(b), (c)) -# define BCOPYOUT(a,b,c) 0; bcopy((void *)(a), (void *)(b), (c)) -# else -# define BCOPYIN(a,b,c) bcopy((void *)(a), (void *)(b), (c)) -# define BCOPYOUT(a,b,c) bcopy((void *)(a), (void *)(b), (c)) -# 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 SPL_NET(x) ; # define SPL_IMP(x) ; # undef SPL_X @@ -574,11 +567,9 @@ typedef struct { # define MUTEX_NUKE(x) bzero((x), sizeof(*(x))) # define FREE_MB_T(m) m_freem(m) # define MTOD(m,t) mtod(m,t) -# define COPYIN(a,b,c) (bcopy((void *)(a), (void *)(b), (c)), 0) -# define COPYOUT(a,b,c) (bcopy((void *)(a), (void *)(b), (c)), 0) -# define BCOPYIN(a,b,c) (bcopy((void *)(a), (void *)(b), (c)), 0) -# define BCOPYOUT(a,b,c) (bcopy((void *)(a), (void *)(b), (c)), 0) -# define UIOMOVE(a,b,c,d) uiomove((void *)a,b,c,d) +# 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 UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,c,d) # define SLEEP(id, n) sleep((id), PZERO+1) # define WAKEUP(id,x) wakeup(id+x) # define POLLWAKEUP(x) ; @@ -664,10 +655,8 @@ typedef struct mbuf mb_t; # define GET_MINOR getminor # define WAKEUP(id,x) wakeup(id + x) # define POLLWAKEUP(x) ; -# define COPYIN(a,b,c) copyin((void *)(a), (void *)(b), (c)) -# define COPYOUT(a,b,c) copyout((void *)(a), (void *)(b), (c)) -# define BCOPYIN(a,b,c) bcopy((void *)(a), (void *)(b), (c)) -# define BCOPYOUT(a,b,c) bcopy((void *)(a), (void *)(b), (c)) +# define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c)) +# define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c)) # define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), M_PFILT, M_NOWAIT) # define KMALLOCS(a, b, c) (a) = (b)malloc((c), M_PFILT, \ ((c) > 4096) ? M_WAITOK : M_NOWAIT) @@ -734,15 +723,25 @@ typedef unsigned int u_32_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) # define GETKTIME(x) microtime((struct timeval *)x) # define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); } -# define COPYIN(a,b,c) copyin((void *)(a), (void *)(b), (c)) -# define COPYOUT(a,b,c) copyout((void *)(a), (void *)(b), (c)) -# define BCOPYIN(a,b,c) bcopy((void *)(a), (void *)(b), (c)) -# define BCOPYOUT(a,b,c) bcopy((void *)(a), (void *)(b), (c)) +#if __NetBSD_Version__ >= 499001000 +# define COPYIN(a,b,c) copyin((a), (b), (c)) +# define COPYOUT(a,b,c) copyout((a), (b), (c)) +# define BCOPYIN(a,b,c) bcopy((a), (b), (c)) +# define BCOPYOUT(a,b,c) bcopy((a), (b), (c)) +#else +# 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)) +#endif typedef struct mbuf mb_t; # endif /* _KERNEL */ # if (NetBSD <= 1991011) && (NetBSD >= 199606) @@ -756,7 +755,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; @@ -796,10 +794,8 @@ typedef u_int32_t u_32_t; # if !defined(IPFILTER_LKM) && (__FreeBSD_version >= 300000) # include "opt_ipfilter.h" # endif -# define COPYIN(a,b,c) copyin((void *)(a), (void *)(b), (c)) -# define COPYOUT(a,b,c) copyout((void *)(a), (void *)(b), (c)) -# define BCOPYIN(a,b,c) bcopy((void *)(a), (void *)(b), (c)) -# define BCOPYOUT(a,b,c) bcopy((void *)(a), (void *)(b), (c)) +# 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 (__FreeBSD_version >= 500043) # define NETBSD_PF @@ -955,10 +951,8 @@ typedef u_int32_t u_32_t; # if (OpenBSD >= 200012) # define HAVE_M_PULLDOWN 1 # endif -# define COPYIN(a,b,c) copyin((void *)(a), (void *)(b), (c)) -# define COPYOUT(a,b,c) copyout((void *)(a), (void *)(b), (c)) -# define BCOPYIN(a,b,c) bcopy((void *)(a), (void *)(b), (c)) -# define BCOPYOUT(a,b,c) bcopy((void *)(a), (void *)(b), (c)) +# 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 GETKTIME(x) microtime((struct timeval *)x) # define MSGDSIZE(x) mbufchainlen(x) # define M_LEN(x) (x)->m_len @@ -1060,7 +1054,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 @@ -1073,15 +1067,17 @@ struct ip6_ext { # ifdef _KERNEL # define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); } -# define BCOPYIN(a,b,c) bcopy((void *)(a), (void *)(b), (c)) -# define BCOPYOUT(a,b,c) bcopy((void *)(a), (void *)(b), (c)) -# define COPYIN(a,b,c) copy_from_user((void *)(b), (void *)(a), (c)) -# define COPYOUT(a,b,c) copy_to_user((void *)(b), (void *)(a), (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 @@ -1093,7 +1089,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) @@ -1273,10 +1269,8 @@ extern void* getifp __P((char *, int)); # define SLEEP(id, n) sleepx((id), PZERO+1, 0) # define WAKEUP(id,x) wakeup(id) # define POLLWAKEUP(x) ; -# define COPYIN(a,b,c) copyin((void *)(a), (void *)(b), (c)) -# define COPYOUT(a,b,c) copyout((void *)(a), (void *)(b), (c)) -# define BCOPYIN(a,b,c) bcopy((void *)(a), (void *)(b), (c)) -# define BCOPYOUT(a,b,c) bcopy((void *)(a), (void *)(b), (c)) +# define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c)) +# define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c)) # define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), M_TEMP, M_NOWAIT) # define KMALLOCS(a, b, c) MALLOC((a), b, (c), M_TEMP, \ ((c) > 4096) ? M_WAITOK : M_NOWAIT) @@ -1353,7 +1347,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; @@ -1412,6 +1406,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 @@ -1450,8 +1445,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), \ @@ -1616,10 +1609,8 @@ MALLOC_DECLARE(M_IPFILTER); # endif # ifndef COPYIN -# define COPYIN(a,b,c) (bcopy((void *)(a), (void *)(b), (c)), 0) -# define COPYOUT(a,b,c) (bcopy((void *)(a), (void *)(b), (c)), 0) -# define BCOPYIN(a,b,c) (bcopy((void *)(a), (void *)(b), (c)), 0) -# define BCOPYOUT(a,b,c) (bcopy((void *)(a), (void *)(b), (c)), 0) +# 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) # endif # ifndef KMALLOC @@ -1648,6 +1639,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. diff --git a/sys/dist/ipf/netinet/ip_fil.h b/sys/dist/ipf/netinet/ip_fil.h index 982fc422009..efd73c5f752 100644 --- a/sys/dist/ipf/netinet/ip_fil.h +++ b/sys/dist/ipf/netinet/ip_fil.h @@ -1,4 +1,4 @@ -/* $NetBSD: ip_fil.h,v 1.7 2007/03/04 06:02:55 christos Exp $ */ +/* $NetBSD: ip_fil.h,v 1.8 2007/04/14 20:34:36 martin Exp $ */ /* * Copyright (C) 1993-2001, 2003 by Darren Reed. @@ -6,7 +6,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_fil.h 1.35 6/5/96 - * Id: ip_fil.h,v 2.170.2.29 2006/03/29 11:19:55 darrenr Exp + * Id: ip_fil.h,v 2.170.2.40 2007/02/17 12:41:42 darrenr Exp */ #ifndef _NETINET_IP_FIL_H_ @@ -45,12 +45,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) @@ -58,6 +58,11 @@ # 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) #else # define SIOCADAFR _IOW(r, 60, struct ipfobj) # define SIOCRMAFR _IOW(r, 61, struct ipfobj) @@ -77,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) @@ -90,10 +95,17 @@ # 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) #endif #define SIOCADDFR SIOCADAFR #define SIOCDELFR SIOCRMAFR #define SIOCINSFR SIOCINAFR +#define SIOCATHST SIOCSTAT1 +#define SIOCGFRST SIOCSTAT2 struct ipscan; @@ -113,6 +125,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 { @@ -120,12 +137,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. */ @@ -251,8 +275,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 @@ -331,8 +359,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 *)); @@ -442,9 +470,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 */ @@ -470,6 +502,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 */ @@ -496,7 +535,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 # */ @@ -556,8 +594,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 @@ -1055,6 +1099,12 @@ 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_COUNT 19 /* How many #defines are above this? */ typedef union ipftunevalptr { @@ -1106,6 +1156,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 @@ -1164,11 +1274,21 @@ 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__) +# 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 **)); @@ -1191,7 +1311,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 **)); @@ -1204,7 +1323,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)); @@ -1223,7 +1341,13 @@ extern int iplioctl __P((struct cdev*, u_long, void *, int, struct thread *)); extern int iplioctl __P((dev_t, u_long, void *, int, struct thread *)); # endif /* __FreeBSD_version >= 502116 */ # else -extern int iplioctl __P((dev_t, u_long, void *, int, struct lwp *)); +# if (__NetBSD_Version__ >= 499001000) +extern int iplioctl __P((dev_t, u_long, void*, int, struct lwp *)); +# elif (__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 /* __FreeBSD_version >= 500024 */ # else extern int iplioctl __P((dev_t, int, void *, int, struct lwp *)); @@ -1237,8 +1361,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 @@ -1272,7 +1401,7 @@ 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)); @@ -1286,7 +1415,12 @@ 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 *)); +#if __NetBSD_Version__ >= 499001000 +extern int fr_ipf_ioctl __P((void*, ioctlcmd_t, int, int, void *)); +#else +extern int fr_ipf_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *)); +#endif 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)); @@ -1364,6 +1498,13 @@ 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((void *)); +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]; @@ -1378,7 +1519,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/dist/ipf/netinet/ip_fil_netbsd.c b/sys/dist/ipf/netinet/ip_fil_netbsd.c index bde0b09643f..36c0d58d101 100644 --- a/sys/dist/ipf/netinet/ip_fil_netbsd.c +++ b/sys/dist/ipf/netinet/ip_fil_netbsd.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_fil_netbsd.c,v 1.31 2007/03/04 06:02:55 christos Exp $ */ +/* $NetBSD: ip_fil_netbsd.c,v 1.32 2007/04/14 20:34:36 martin Exp $ */ /* * Copyright (C) 1993-2003 by Darren Reed. @@ -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_netbsd.c,v 2.55.2.38 2006/03/25 13:03:02 darrenr Exp"; +static const char rcsid[] = "@(#)Id: ip_fil_netbsd.c,v 2.55.2.47 2007/02/08 19:59:52 darrenr Exp"; #endif #if defined(KERNEL) || defined(_KERNEL) @@ -18,7 +18,11 @@ static const char rcsid[] = "@(#)Id: ip_fil_netbsd.c,v 2.55.2.38 2006/03/25 13:0 #endif #include <sys/param.h> #if (NetBSD >= 199905) && !defined(IPFILTER_LKM) && defined(_KERNEL) -# include "opt_ipfilter.h" +# if (__NetBSD_Version__ < 399001400) +# include "opt_ipfilter_log.h" +# else +# include "opt_ipfilter.h" +# endif # include "opt_pfil_hooks.h" # include "opt_ipsec.h" #endif @@ -498,8 +502,14 @@ int iplioctl(dev, cmd, data, mode , p) # if (__NetBSD_Version__ >= 399001400) struct lwp *p; +# if (__NetBSD_Version__ >= 399002000) +# define UID(l) kauth_cred_getuid((l)->l_cred) +# else +# define UID(l) ((l)->l_proc->p_cred->p_ruid) +# endif # else struct proc *p; +# define UID(p) ((p)->p_cred->p_ruid) # endif #else ) @@ -509,9 +519,8 @@ u_long cmd; void *data; int mode; { - int s; - int error = 0, unit = 0, tmp; - friostat_t fio; + int error = 0, unit = 0; + SPL_INT(s); #if (__NetBSD_Version__ >= 399002000) if ((mode & FWRITE) && kauth_authorize_network(p->l_cred, @@ -537,148 +546,8 @@ int mode; SPL_NET(s); - error = fr_ioctlswitch(unit, data, cmd, mode); - if (error != -1) { - SPL_X(s); - return error; - } - error = 0; + error = fr_ioctlswitch(unit, data, cmd, mode, UID(p), p); - switch (cmd) - { - case FIONREAD : -#ifdef IPFILTER_LOG - BCOPYOUT(&iplused[IPL_LOGIPF], (void *)data, - sizeof(iplused[IPL_LOGIPF])); -#endif - break; - case SIOCFRENB : - if (!(mode & FWRITE)) - error = EPERM; - else { - BCOPYIN(data, &tmp, sizeof(tmp)); - if (tmp) { - if (fr_running > 0) - error = 0; - else - error = iplattach(); - if (error == 0) - fr_running = 1; - else - (void) ipldetach(); - } else { - error = ipldetach(); - if (error == 0) - fr_running = -1; - } - } - break; - case SIOCIPFSET : - if (!(mode & FWRITE)) { - error = EPERM; - break; - } - case SIOCIPFGETNEXT : - case SIOCIPFGET : - error = fr_ipftune(cmd, data); - break; - case SIOCSETFF : - if (!(mode & FWRITE)) - error = EPERM; - else - BCOPYIN(data, &fr_flags, sizeof(fr_flags)); - break; - case SIOCGETFF : - BCOPYOUT(&fr_flags, data, sizeof(fr_flags)); - break; - case SIOCFUNCL : - error = fr_resolvefunc(data); - break; - case SIOCINAFR : - case SIOCRMAFR : - case SIOCADAFR : - case SIOCZRLST : - if (!(mode & FWRITE)) - error = EPERM; - else - error = frrequest(unit, cmd, data, fr_active, 1); - break; - case SIOCINIFR : - case SIOCRMIFR : - case SIOCADIFR : - if (!(mode & FWRITE)) - error = EPERM; - else - error = frrequest(unit, cmd, data, 1 - fr_active, 1); - break; - case SIOCSWAPA : - if (!(mode & FWRITE)) - error = EPERM; - else { - bzero((char *)frcache, sizeof(frcache[0]) * 2); - *(u_int *)data = fr_active; - fr_active = 1 - fr_active; - } - break; - case SIOCGETFS : - fr_getstat(&fio); - error = fr_outobj(data, &fio, IPFOBJ_IPFSTAT); - break; - case SIOCFRZST : - if (!(mode & FWRITE)) - error = EPERM; - else - error = fr_zerostats(data); - break; - case SIOCIPFFL : - if (!(mode & FWRITE)) - error = EPERM; - else { - BCOPYIN(data, &tmp, sizeof(tmp)); - tmp = frflush(unit, 4, tmp); - BCOPYOUT(&tmp, data, sizeof(tmp)); - } - break; -#ifdef USE_INET6 - case SIOCIPFL6 : - if (!(mode & FWRITE)) - error = EPERM; - else { - BCOPYIN(data, &tmp, sizeof(tmp)); - tmp = frflush(unit, 6, tmp); - BCOPYOUT(&tmp, data, sizeof(tmp)); - } - break; -#endif - case SIOCSTLCK : - BCOPYIN(data, &tmp, sizeof(tmp)); - fr_state_lock = tmp; - fr_nat_lock = tmp; - fr_frag_lock = tmp; - fr_auth_lock = tmp; - break; -#ifdef IPFILTER_LOG - case SIOCIPFFB : - if (!(mode & FWRITE)) - error = EPERM; - else - *(int *)data = ipflog_clear(unit); - break; -#endif /* IPFILTER_LOG */ - case SIOCGFRST : - error = fr_outobj(data, fr_fragstats(), IPFOBJ_FRAGSTAT); - break; - case SIOCFRSYN : - if (!(mode & FWRITE)) - error = EPERM; - else { - frsync(NULL); - } - break; - default : - error = EINVAL; - break; - } SPL_X(s); return error; } @@ -786,6 +655,9 @@ int iplread( ) { + if (fr_running < 1) + return EIO; + # ifdef IPFILTER_SYNC if (GET_MINOR(dev) == IPL_LOGSYNC) return ipfsync_read(uio); @@ -814,6 +686,9 @@ int iplwrite( ) { + if (fr_running < 1) + return EIO; + #ifdef IPFILTER_SYNC if (GET_MINOR(dev) == IPL_LOGSYNC) return ipfsync_write(uio); @@ -1264,9 +1139,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; @@ -1283,6 +1160,7 @@ frdest_t *fdp; case 0 : break; case 1 : + fr_natderef((nat_t **)&fin->fin_nat); ip->ip_sum = 0; break; case -1 : @@ -1477,10 +1355,6 @@ frdest_t *fdp; else ifp = fin->fin_ifp; - if ((fr != NULL) && (fin->fin_rev != 0)) { - if ((ifp != NULL) && (fdp == &fr->fr_tif)) - return 0; - } if (fdp != NULL) { if (IP6_NOTZERO(&fdp->fd_ip6)) dst6->sin6_addr = fdp->fd_ip6.in6; @@ -1503,14 +1377,29 @@ frdest_t *fdp; dst6->sin6_addr.s6_addr16[1] = htons(ifp->if_index); { +#if (__NetBSD_Version__ >= 106010000) +# if (__NetBSD_Version__ >= 399001400) struct in6_ifextra *ife; - +# else + struct in6_addr finaldst = fin->fin_dst6; + int frag; +# endif +#endif if (ro->ro_rt->rt_flags & RTF_GATEWAY) dst6 = (struct sockaddr_in6 *)ro->ro_rt->rt_gateway; ro->ro_rt->rt_use++; + /* Determine path MTU. */ +#if (__NetBSD_Version__ <= 106009999) + mtu = nd_ifinfo[ifp->if_index].linkmtu; +#else +# if (__NetBSD_Version__ >= 399001400) ife = (struct in6_ifextra *)(ifp)->if_afdata[AF_INET6]; mtu = ife->nd_ifinfo[ifp->if_index].linkmtu; +# else + error = ip6_getpmtu(ro, ro, ifp, &finaldst, &mtu, &frag); +# endif +#endif if ((error == 0) && (m0->m_pkthdr.len <= mtu)) { *mpp = NULL; error = nd6_output(ifp, ifp, m0, dst6, rt); @@ -1958,3 +1847,30 @@ struct proc *p; selrecord(p, &ipfselwait[xmin]); return revents; } + + +int ipf_inject(fin, m) +fr_info_t *fin; +mb_t *m; +{ + int error; + + if (fin->fin_out == 0) { + struct ifqueue *ifq; + + ifq = &ipintrq; + + if (IF_QFULL(ifq)) { + IF_DROP(ifq); + FREE_MB_T(m); + error = ENOBUFS; + } else { + IF_ENQUEUE(ifq, m); + error = 0; + } + } else { + error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL); + } + + return error; +} diff --git a/sys/dist/ipf/netinet/ip_frag.c b/sys/dist/ipf/netinet/ip_frag.c index 8fe0f3228bf..6caabff3116 100644 --- a/sys/dist/ipf/netinet/ip_frag.c +++ b/sys/dist/ipf/netinet/ip_frag.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_frag.c,v 1.5 2006/11/16 01:33:34 christos Exp $ */ +/* $NetBSD: ip_frag.c,v 1.6 2007/04/14 20:34:36 martin Exp $ */ /* * Copyright (C) 1993-2003 by Darren Reed. @@ -103,24 +103,25 @@ extern struct timeout fr_slowtimer_ch; #if !defined(lint) #if defined(__NetBSD__) #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ip_frag.c,v 1.5 2006/11/16 01:33:34 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_frag.c,v 1.6 2007/04/14 20:34:36 martin Exp $"); #else static const char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)Id: ip_frag.c,v 2.77.2.5 2006/02/26 08:26:54 darrenr Exp"; +static const char rcsid[] = "@(#)Id: ip_frag.c,v 2.77.2.8 2006/09/01 14:09:33 darrenr Exp"; #endif #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; @@ -136,6 +137,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 *)); /* ------------------------------------------------------------------------ */ @@ -312,6 +314,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; @@ -692,11 +695,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; @@ -707,7 +705,22 @@ 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); +} + + +static void fr_fragfree(fra) +ipfr_t *fra; +{ KFREE(fra); + ipfr_stats.ifs_expire++; + ipfr_inuse--; } @@ -725,8 +738,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); @@ -738,6 +753,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; @@ -771,9 +787,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); @@ -781,9 +796,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); @@ -793,23 +807,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); } @@ -832,6 +850,7 @@ int fr_slowtimer() { READ_ENTER(&ipf_global); + ipf_expiretokens(); fr_fragexpire(); fr_timeoutstate(); fr_natexpire(); @@ -865,3 +884,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/dist/ipf/netinet/ip_frag.h b/sys/dist/ipf/netinet/ip_frag.h index ba58cdbf685..87f7ae5769f 100644 --- a/sys/dist/ipf/netinet/ip_frag.h +++ b/sys/dist/ipf/netinet/ip_frag.h @@ -1,4 +1,4 @@ -/* $NetBSD: ip_frag.h,v 1.3 2006/04/04 16:17:19 martti Exp $ */ +/* $NetBSD: ip_frag.h,v 1.4 2007/04/14 20:34:36 martin Exp $ */ /* * Copyright (C) 1993-2001 by Darren Reed. @@ -6,7 +6,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_frag.h 1.5 3/24/96 - * Id: ip_frag.h,v 2.23.2.2 2005/06/10 18:02:37 darrenr Exp + * Id: ip_frag.h,v 2.23.2.5 2006/12/23 11:11:47 darrenr Exp */ #ifndef _NETINET_IP_FRAG_H_ @@ -18,6 +18,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; @@ -28,10 +38,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; @@ -51,6 +57,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; @@ -66,6 +74,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/dist/ipf/netinet/ip_ftp_pxy.c b/sys/dist/ipf/netinet/ip_ftp_pxy.c index 514c79bbafc..8d1de22b9ae 100644 --- a/sys/dist/ipf/netinet/ip_ftp_pxy.c +++ b/sys/dist/ipf/netinet/ip_ftp_pxy.c @@ -1,7 +1,7 @@ -/* $NetBSD: ip_ftp_pxy.c,v 1.10 2006/04/04 16:17:19 martti Exp $ */ +/* $NetBSD: ip_ftp_pxy.c,v 1.11 2007/04/14 20:34:36 martin Exp $ */ #include <sys/cdefs.h> -__KERNEL_RCSID(1, "$NetBSD: ip_ftp_pxy.c,v 1.10 2006/04/04 16:17:19 martti Exp $"); +__KERNEL_RCSID(1, "$NetBSD: ip_ftp_pxy.c,v 1.11 2007/04/14 20:34:36 martin Exp $"); /* * Copyright (C) 1997-2003 by Darren Reed @@ -11,7 +11,7 @@ __KERNEL_RCSID(1, "$NetBSD: ip_ftp_pxy.c,v 1.10 2006/04/04 16:17:19 martti Exp $ * Simple FTP transparent proxy for in-kernel use. For use with the NAT * code. * - * Id: ip_ftp_pxy.c,v 2.88.2.19 2006/04/01 10:14:53 darrenr Exp + * Id: ip_ftp_pxy.c,v 2.88.2.20 2006/07/14 06:12:12 darrenr Exp */ #define IPF_FTP_PROXY @@ -373,7 +373,7 @@ 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; @@ -735,7 +735,7 @@ 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; diff --git a/sys/dist/ipf/netinet/ip_h323_pxy.c b/sys/dist/ipf/netinet/ip_h323_pxy.c index 5ae913e34cc..4f90bd3b7a8 100644 --- a/sys/dist/ipf/netinet/ip_h323_pxy.c +++ b/sys/dist/ipf/netinet/ip_h323_pxy.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_h323_pxy.c,v 1.5 2007/03/04 06:02:55 christos Exp $ */ +/* $NetBSD: ip_h323_pxy.c,v 1.6 2007/04/14 20:34:36 martin Exp $ */ /* * Copyright 2001, QNX Software Systems Ltd. All Rights Reserved @@ -34,7 +34,7 @@ #include "opt_ipfilter.h" #endif -__KERNEL_RCSID(1, "$NetBSD: ip_h323_pxy.c,v 1.5 2007/03/04 06:02:55 christos Exp $"); +__KERNEL_RCSID(1, "$NetBSD: ip_h323_pxy.c,v 1.6 2007/04/14 20:34:36 martin Exp $"); #define IPF_H323_PROXY @@ -142,8 +142,13 @@ ap_session_t *aps; * We are lucky here because this function is not * called with ipf_nat locked. */ +#if __NetBSD_Version__ >= 499001000 if (fr_nat_ioctl((void *)ipn, SIOCRMNAT, NAT_SYSSPACE| - NAT_LOCKHELD|FWRITE) == -1) { + NAT_LOCKHELD|FWRITE, 0, NULL) == -1) { +#else + if (fr_nat_ioctl((caddr_t)ipn, SIOCRMNAT, NAT_SYSSPACE| + NAT_LOCKHELD|FWRITE, 0, NULL) == -1) { +#endif /*EMPTY*/; /* log the error */ } @@ -206,8 +211,13 @@ nat_t *nat; * of calling fr_nat_ioctl(), we add the nat rule ourself. */ RWLOCK_EXIT(&ipf_nat); +#if __NetBSD_Version__ >= 499001000 if (fr_nat_ioctl((void *)ipn, SIOCADNAT, - NAT_SYSSPACE|FWRITE) == -1) { + NAT_SYSSPACE|FWRITE, 0, NULL) == -1) { +#else + if (fr_nat_ioctl((caddr_t)ipn, SIOCADNAT, + NAT_SYSSPACE|FWRITE, 0, NULL) == -1) { +#endif READ_ENTER(&ipf_nat); return -1; } @@ -275,6 +285,8 @@ nat_t *nat; udp.uh_sport = port; memcpy(&fi, fin, sizeof(fi)); + fi.fin_state = NULL; + fi.fin_nat = NULL; fi.fin_fi.fi_p = IPPROTO_UDP; fi.fin_data[0] = port; fi.fin_data[1] = 0; diff --git a/sys/dist/ipf/netinet/ip_htable.c b/sys/dist/ipf/netinet/ip_htable.c index 07726ad37d0..7e8b7ba42dd 100644 --- a/sys/dist/ipf/netinet/ip_htable.c +++ b/sys/dist/ipf/netinet/ip_htable.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_htable.c,v 1.6 2006/09/17 13:43:15 yamt Exp $ */ +/* $NetBSD: ip_htable.c,v 1.7 2007/04/14 20:34:37 martin Exp $ */ /* * Copyright (C) 1993-2001, 2003 by Darren Reed. @@ -58,7 +58,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 @@ -108,30 +108,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++; @@ -152,24 +158,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; } @@ -177,22 +192,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); @@ -201,40 +218,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; { @@ -247,6 +330,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; { @@ -259,8 +356,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; + } } } } @@ -292,13 +392,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; @@ -316,44 +423,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; } @@ -384,9 +455,9 @@ 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. */ /* ------------------------------------------------------------------------ */ @@ -433,7 +504,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; @@ -456,4 +527,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/dist/ipf/netinet/ip_htable.h b/sys/dist/ipf/netinet/ip_htable.h index 6e2e8c20c05..ca60e446b43 100644 --- a/sys/dist/ipf/netinet/ip_htable.h +++ b/sys/dist/ipf/netinet/ip_htable.h @@ -1,4 +1,4 @@ -/* $NetBSD: ip_htable.h,v 1.2 2005/12/11 12:24:21 christos Exp $ */ +/* $NetBSD: ip_htable.h,v 1.3 2007/04/14 20:34:37 martin Exp $ */ #ifndef __IP_HTABLE_H__ #define __IP_HTABLE_H__ @@ -7,10 +7,12 @@ typedef struct iphtent_s { struct iphtent_s *ipe_next, **ipe_pnext; + struct iphtent_s *ipe_hnext, **ipe_phnext; void *ipe_ptr; i6addr_t ipe_addr; i6addr_t ipe_mask; int ipe_ref; + int ipe_unit; union { char ipeu_char[16]; u_long ipeu_long; @@ -28,6 +30,7 @@ typedef struct iphtable_s { ipfrwlock_t iph_rwlock; struct iphtable_s *iph_next, **iph_pnext; struct iphtent_s **iph_table; + struct iphtent_s *iph_list; size_t iph_size; /* size of hash table */ u_long iph_seed; /* hashing seed */ u_32_t iph_flags; @@ -41,6 +44,7 @@ typedef struct iphtable_s { /* iph_type */ #define IPHASH_LOOKUP 0 #define IPHASH_GROUPMAP 1 +#define IPHASH_DELETE 2 #define IPHASH_ANON 0x80000000 @@ -55,17 +59,22 @@ typedef struct iphtstat_s { extern iphtable_t *ipf_htables[IPL_LOGSIZE]; +extern iphtable_t *fr_existshtable __P((int, char *)); +extern int fr_clearhtable __P((iphtable_t *)); extern void fr_htable_unload __P((void)); extern int fr_newhtable __P((iplookupop_t *)); extern iphtable_t *fr_findhtable __P((int, char *)); -extern int fr_removehtable __P((iplookupop_t *)); +extern int fr_removehtable __P((int, char *)); extern size_t fr_flushhtable __P((iplookupflush_t *)); extern int fr_addhtent __P((iphtable_t *, iphtent_t *)); extern int fr_delhtent __P((iphtable_t *, iphtent_t *)); -extern void fr_derefhtable __P((iphtable_t *)); -extern void fr_delhtable __P((iphtable_t *)); +extern int fr_derefhtable __P((iphtable_t *)); +extern int fr_derefhtent __P((iphtent_t *)); +extern int fr_delhtable __P((iphtable_t *)); extern void *fr_iphmfindgroup __P((void *, void *)); extern int fr_iphmfindip __P((void *, int, void *)); extern int fr_gethtablestat __P((iplookupop_t *)); +extern int fr_htable_getnext __P((ipftoken_t *, ipflookupiter_t *)); +extern void fr_htable_iterderef __P((u_int, int, void *)); #endif /* __IP_HTABLE_H__ */ diff --git a/sys/dist/ipf/netinet/ip_ipsec_pxy.c b/sys/dist/ipf/netinet/ip_ipsec_pxy.c index 310938b2b6b..982450b553d 100644 --- a/sys/dist/ipf/netinet/ip_ipsec_pxy.c +++ b/sys/dist/ipf/netinet/ip_ipsec_pxy.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_ipsec_pxy.c,v 1.5 2006/04/04 16:17:19 martti Exp $ */ +/* $NetBSD: ip_ipsec_pxy.c,v 1.6 2007/04/14 20:34:37 martin Exp $ */ /* * Copyright (C) 2001-2003 by Darren Reed @@ -8,11 +8,11 @@ * Simple ISAKMP transparent proxy for in-kernel use. For use with the NAT * code. * - * Id: ip_ipsec_pxy.c,v 2.20.2.7 2005/08/20 13:48:22 darrenr Exp + * Id: ip_ipsec_pxy.c,v 2.20.2.8 2006/07/14 06:12:14 darrenr Exp * */ -__KERNEL_RCSID(1, "$NetBSD: ip_ipsec_pxy.c,v 1.5 2006/04/04 16:17:19 martti Exp $"); +__KERNEL_RCSID(1, "$NetBSD: ip_ipsec_pxy.c,v 1.6 2007/04/14 20:34:37 martin Exp $"); #define IPF_IPSEC_PROXY @@ -182,7 +182,7 @@ nat_t *nat; ipsec->ipsc_state = fr_addstate(&fi, &ipsec->ipsc_state, SI_WILDP); if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); + fr_statederef((ipstate_t **)&fi.fin_state); } ip->ip_p = p & 0xff; return 0; @@ -261,7 +261,7 @@ nat_t *nat; &ipsec->ipsc_state, SI_WILDP); if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); + fr_statederef((ipstate_t **)&fi.fin_state); } ip->ip_p = p; } diff --git a/sys/dist/ipf/netinet/ip_irc_pxy.c b/sys/dist/ipf/netinet/ip_irc_pxy.c index f939bd9dd5d..7c171c66ee3 100644 --- a/sys/dist/ipf/netinet/ip_irc_pxy.c +++ b/sys/dist/ipf/netinet/ip_irc_pxy.c @@ -1,11 +1,11 @@ -/* $NetBSD: ip_irc_pxy.c,v 1.8 2007/03/04 06:02:56 christos Exp $ */ +/* $NetBSD: ip_irc_pxy.c,v 1.9 2007/04/14 20:34:37 martin Exp $ */ /* * Copyright (C) 2000-2003 Darren Reed * * See the IPFILTER.LICENCE file for details on licencing. * - * Id: ip_irc_pxy.c,v 2.39.2.5 2005/12/04 23:39:27 darrenr Exp + * Id: ip_irc_pxy.c,v 2.39.2.6 2006/07/14 06:12:14 darrenr Exp */ #define IPF_IRC_PROXY @@ -417,7 +417,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_src = swip; } diff --git a/sys/dist/ipf/netinet/ip_log.c b/sys/dist/ipf/netinet/ip_log.c index 1766d611d5b..c7e287ad836 100644 --- a/sys/dist/ipf/netinet/ip_log.c +++ b/sys/dist/ipf/netinet/ip_log.c @@ -1,15 +1,15 @@ -/* $NetBSD: ip_log.c,v 1.6 2007/03/04 06:02:56 christos Exp $ */ +/* $NetBSD: ip_log.c,v 1.7 2007/04/14 20:34:37 martin Exp $ */ /* * Copyright (C) 1997-2003 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * Id: ip_log.c,v 2.75.2.11 2006/03/26 13:50:47 darrenr Exp + * Id: ip_log.c,v 2.75.2.15 2007/02/03 00:49:30 darrenr Exp */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ip_log.c,v 1.6 2007/03/04 06:02:56 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_log.c,v 1.7 2007/04/14 20:34:37 martin Exp $"); #include <sys/param.h> #if defined(KERNEL) || defined(_KERNEL) @@ -20,7 +20,11 @@ __KERNEL_RCSID(0, "$NetBSD: ip_log.c,v 1.6 2007/03/04 06:02:56 christos Exp $"); #endif #if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ defined(_KERNEL) -# include "opt_ipfilter.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) @@ -153,7 +157,7 @@ extern int selwait; # 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 +166,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 +268,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/dist/ipf/netinet/ip_lookup.c b/sys/dist/ipf/netinet/ip_lookup.c index 6a27c370b31..1504cb0ad13 100644 --- a/sys/dist/ipf/netinet/ip_lookup.c +++ b/sys/dist/ipf/netinet/ip_lookup.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_lookup.c,v 1.8 2007/03/04 06:02:56 christos Exp $ */ +/* $NetBSD: ip_lookup.c,v 1.9 2007/04/14 20:34:37 martin Exp $ */ /* * Copyright (C) 2002-2003 by Darren Reed. @@ -41,9 +41,6 @@ struct file; #endif #include <sys/socket.h> #if (defined(__osf__) || defined(AIX) || defined(__hpux) || defined(__sgi)) && defined(_KERNEL) -# ifdef __osf__ -# include <net/radix.h> -# endif # include "radix_ipf_local.h" # define _RADIX_H_ #endif @@ -68,7 +65,7 @@ struct file; /* END OF INCLUDES */ #if !defined(lint) -static const char rcsid[] = "@(#)Id: ip_lookup.c,v 2.35.2.8 2005/11/13 15:35:45 darrenr Exp"; +static const char rcsid[] = "@(#)Id: ip_lookup.c,v 2.35.2.14 2007/02/17 12:41:42 darrenr Exp"; #endif #ifdef IPFILTER_LOOKUP @@ -136,11 +133,15 @@ void ip_lookup_unload() /* involves just calling another function to handle the specifics of each */ /* command. */ /* ------------------------------------------------------------------------ */ -int ip_lookup_ioctl( -void *data, -ioctlcmd_t cmd, -int mode -) +int ip_lookup_ioctl(data, cmd, mode, uid, ctx) +#if __NetBSD_Version__ >= 499001000 +void *data; +#else +caddr_t data; +#endif +ioctlcmd_t cmd; +int mode, uid; +void *ctx; { int err; SPL_INT(s); @@ -190,6 +191,10 @@ int mode RWLOCK_EXIT(&ip_poolrw); break; + case SIOCLOOKUPITER : + err = ip_lookup_iterate(data, uid, ctx); + break; + default : err = EINVAL; break; @@ -220,6 +225,10 @@ void *data; err = 0; BCOPYIN(data, &op, sizeof(op)); + + if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) + return EINVAL; + op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; switch (op.iplo_type) @@ -291,6 +300,9 @@ void *data; err = 0; BCOPYIN(data, &op, sizeof(op)); + if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) + return EINVAL; + op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; switch (op.iplo_type) @@ -351,6 +363,11 @@ void *data; err = 0; BCOPYIN(data, &op, sizeof(op)); + if (err != 0) + return EFAULT; + + if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) + return EINVAL; op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; @@ -379,7 +396,7 @@ void *data; * For anonymous pools, copy back the operation struct because in the * case of success it will contain the new table's name. */ - if ((err == 0) && ((op.iplo_arg & IPOOL_ANON) != 0)) { + if ((err == 0) && ((op.iplo_arg & LOOKUP_ANON) != 0)) { BCOPYOUT(&op, data, sizeof(op)); } @@ -401,11 +418,13 @@ void *data; iplookupop_t op; int err; + err = 0; BCOPYIN(data, &op, sizeof(op)); - op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; - if (op.iplo_arg & IPLT_ANON) - op.iplo_arg &= IPLT_ANON; + if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) + return EINVAL; + + op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; /* * create a new pool - fail if one already exists with @@ -414,11 +433,11 @@ void *data; switch (op.iplo_type) { case IPLT_POOL : - err = ip_pool_destroy(&op); + err = ip_pool_destroy(op.iplo_unit, op.iplo_name); break; case IPLT_HASH : - err = fr_removehtable(&op); + err = fr_removehtable(op.iplo_unit, op.iplo_name); break; default : @@ -445,6 +464,9 @@ void *data; err = 0; BCOPYIN(data, &op, sizeof(op)); + if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) + return EINVAL; + switch (op.iplo_type) { case IPLT_POOL : @@ -480,12 +502,12 @@ void *data; err = 0; BCOPYIN(data, &flush, sizeof(flush)); - flush.iplf_name[sizeof(flush.iplf_name) - 1] = '\0'; - unit = flush.iplf_unit; if ((unit < 0 || unit > IPL_LOGMAX) && (unit != IPLT_ALL)) return EINVAL; + flush.iplf_name[sizeof(flush.iplf_name) - 1] = '\0'; + type = flush.iplf_type; err = EINVAL; num = 0; @@ -508,6 +530,15 @@ void *data; } +/* ------------------------------------------------------------------------ */ +/* Function: ip_lookup_delref */ +/* Returns: void */ +/* Parameters: type(I) - table type to operate on */ +/* ptr(I) - pointer to object to remove reference for */ +/* */ +/* This function organises calling the correct deref function for a given */ +/* type of object being passed into it. */ +/* ------------------------------------------------------------------------ */ void ip_lookup_deref(type, ptr) int type; void *ptr; @@ -530,13 +561,102 @@ void *ptr; } +/* ------------------------------------------------------------------------ */ +/* Function: ip_lookup_iterate */ +/* Returns: int - 0 = success, else error */ +/* Parameters: data(I) - pointer to data from ioctl call */ +/* */ +/* Decodes ioctl request to step through either hash tables or pools. */ +/* ------------------------------------------------------------------------ */ +int ip_lookup_iterate(data, uid, ctx) +void *data; +int uid; +void *ctx; +{ + ipflookupiter_t iter; + ipftoken_t *token; + int err; + + err = fr_inobj(data, &iter, IPFOBJ_LOOKUPITER); + if (err != 0) + return err; + + if (iter.ili_unit < 0 || iter.ili_unit > IPL_LOGMAX) + return EINVAL; + + if (iter.ili_ival != IPFGENITER_LOOKUP) + return EINVAL; + + token = ipf_findtoken(iter.ili_key, uid, ctx); + if (token == NULL) { + RWLOCK_EXIT(&ipf_tokens); + return ESRCH; + } + + switch (iter.ili_type) + { + case IPLT_POOL : + err = ip_pool_getnext(token, &iter); + break; + case IPLT_HASH : + err = fr_htable_getnext(token, &iter); + break; + default : + err = EINVAL; + break; + } + RWLOCK_EXIT(&ipf_tokens); + + return err; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: iplookup_iterderef */ +/* Returns: int - 0 = success, else error */ +/* Parameters: data(I) - pointer to data from ioctl call */ +/* */ +/* Decodes ioctl request to remove a particular hash table or pool and */ +/* calls the relevant function to do the cleanup. */ +/* ------------------------------------------------------------------------ */ +void ip_lookup_iterderef(type, data) +u_32_t type; +void *data; +{ + iplookupiterkey_t key; + + key.ilik_key = type; + + if (key.ilik_unstr.ilik_ival != IPFGENITER_LOOKUP) + return; + + switch (key.ilik_unstr.ilik_type) + { + case IPLT_HASH : + fr_htable_iterderef((u_int)key.ilik_unstr.ilik_otype, + (int)key.ilik_unstr.ilik_unit, data); + break; + case IPLT_POOL : + ip_pool_iterderef((u_int)key.ilik_unstr.ilik_otype, + (int)key.ilik_unstr.ilik_unit, data); + break; + } +} + + + #else /* IPFILTER_LOOKUP */ /*ARGSUSED*/ -int ip_lookup_ioctl(data, cmd, mode) -void *data; +int ip_lookup_ioctl(data, cmd, mode, uid, ctx) +#if __NetBSD_Version__ >= 499001000 +void * data; +#else +caddr_t data; +#endif ioctlcmd_t cmd; -int mode; +int mode, uid; +void *ctx; { return EIO; } diff --git a/sys/dist/ipf/netinet/ip_lookup.h b/sys/dist/ipf/netinet/ip_lookup.h index 1bb11f21977..ae32f71341b 100644 --- a/sys/dist/ipf/netinet/ip_lookup.h +++ b/sys/dist/ipf/netinet/ip_lookup.h @@ -1,4 +1,4 @@ -/* $NetBSD: ip_lookup.h,v 1.4 2007/03/04 06:02:56 christos Exp $ */ +/* $NetBSD: ip_lookup.h,v 1.5 2007/04/14 20:34:37 martin Exp $ */ #ifndef __IP_LOOKUP_H__ @@ -35,6 +35,9 @@ typedef struct iplookupop { void *iplo_struct; } iplookupop_t; +#define LOOKUP_ANON 0x80000000 + + typedef struct iplookupflush { int iplf_type; /* IPLT_* */ int iplf_unit; /* IPL_LOG* */ @@ -57,9 +60,43 @@ typedef struct iplookuplink { #define IPLT_ANON 0x80000000 + +typedef union { + struct iplookupiterkey { + char ilik_ival; + u_char ilik_type; /* IPLT_* */ + u_char ilik_otype; + char ilik_unit; /* IPL_LOG* */ + } ilik_unstr; + u_32_t ilik_key; +} iplookupiterkey_t; + +typedef struct ipflookupiter { + int ili_nitems; + iplookupiterkey_t ili_lkey; + char ili_name[FR_GROUPLEN]; + void *ili_data; +} ipflookupiter_t; + +#define ili_key ili_lkey.ilik_key +#define ili_ival ili_lkey.ilik_unstr.ilik_ival +#define ili_unit ili_lkey.ilik_unstr.ilik_unit +#define ili_type ili_lkey.ilik_unstr.ilik_type +#define ili_otype ili_lkey.ilik_unstr.ilik_otype + +#define IPFLOOKUPITER_LIST 0 +#define IPFLOOKUPITER_NODE 1 + + extern int ip_lookup_init __P((void)); -extern int ip_lookup_ioctl __P((void *, ioctlcmd_t, int)); +#if __NetBSD_Version__ >= 499001000 +extern int ip_lookup_ioctl __P((void*, ioctlcmd_t, int, int, void *)); +#else +extern int ip_lookup_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *)); +#endif extern void ip_lookup_unload __P((void)); extern void ip_lookup_deref __P((int, void *)); +extern int ip_lookup_iterate __P((void *, int, void *)); +extern void ip_lookup_iterderef __P((u_32_t, void *)); #endif /* __IP_LOOKUP_H__ */ diff --git a/sys/dist/ipf/netinet/ip_nat.c b/sys/dist/ipf/netinet/ip_nat.c index 70aaedbd172..234bbcbbc0e 100644 --- a/sys/dist/ipf/netinet/ip_nat.c +++ b/sys/dist/ipf/netinet/ip_nat.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_nat.c,v 1.21 2007/03/04 06:02:56 christos Exp $ */ +/* $NetBSD: ip_nat.c,v 1.22 2007/04/14 20:34:37 martin Exp $ */ /* * Copyright (C) 1995-2003 by Darren Reed. @@ -16,13 +16,17 @@ #include <sys/param.h> #include <sys/time.h> #include <sys/file.h> -#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ - defined(_KERNEL) -# include "opt_ipfilter.h" -#endif #if (__NetBSD_Version__ >= 399002000) #include <sys/kauth.h> #endif +#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ + defined(_KERNEL) +# if (__NetBSD_Version__ < 399001400) +# include "opt_ipfilter_log.h" +# else +# include "opt_ipfilter.h" +# endif +#endif #if !defined(_KERNEL) # include <stdio.h> # include <string.h> @@ -112,7 +116,7 @@ extern struct ifnet vpnif; #if !defined(lint) static const char sccsid[] = "@(#)ip_nat.c 1.11 6/5/96 (C) 1995 Darren Reed"; -static const char rcsid[] = "@(#)Id: ip_nat.c,v 2.195.2.56 2006/04/01 10:15:34 darrenr Exp"; +static const char rcsid[] = "@(#)Id: ip_nat.c,v 2.195.2.73 2007/02/02 23:53:33 darrenr Exp"; #endif @@ -150,14 +154,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 @@ -181,16 +188,22 @@ static void nat_addrdr __P((struct ipnat *)); static void nat_delete __P((struct nat *, int)); static void nat_delrdr __P((struct ipnat *)); static void nat_delnat __P((struct ipnat *)); +#if __NetBSD_Version__ >= 499001000 static int fr_natgetent __P((void *)); static int fr_natgetsz __P((void *)); static int fr_natputent __P((void *, int)); +#else +static int fr_natgetent __P((caddr_t)); +static int fr_natgetsz __P((caddr_t)); +static int fr_natputent __P((caddr_t, int)); +#endif +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)); @@ -200,6 +213,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 *)); /* ------------------------------------------------------------------------ */ @@ -237,11 +252,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)); @@ -441,7 +459,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)) && @@ -455,11 +473,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; @@ -472,19 +495,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; @@ -614,10 +645,15 @@ 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; +#if __NetBSD_Version__ >= 499001000 void *data; -int mode; +#else +caddr_t data; +#endif +int mode, uid; +void *ctx; { ipnat_t *nat, *nt, *n = NULL, **np = NULL; int error = 0, ret, arg, getlock; @@ -654,9 +690,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) @@ -678,13 +711,32 @@ 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) { + case SIOCGENITER : + { + ipfgeniter_t iter; + ipftoken_t *token; + + error = fr_inobj(data, &iter, IPFOBJ_GENITER); + if (error != 0) + break; + + token = ipf_findtoken(iter.igi_type, uid, ctx); + if (token != NULL) + error = nat_iterator(token, &iter); + RWLOCK_EXIT(&ipf_tokens); + break; + } #ifdef IPFILTER_LOG case SIOCIPFFB : { @@ -698,18 +750,21 @@ int mode; } break; } + case SIOCSETLG : if (!(mode & FWRITE)) error = EPERM; else { BCOPYIN((char *)data, (char *)&nat_logging, - sizeof(nat_logging)); + sizeof(nat_logging)); } break; + case SIOCGETLG : BCOPYOUT((char *)&nat_logging, (char *)data, - sizeof(nat_logging)); + sizeof(nat_logging)); break; + case FIONREAD : arg = iplused[IPL_LOGNAT]; BCOPYOUT(&arg, data, sizeof(arg)); @@ -733,6 +788,7 @@ int mode; if (error == 0) nt = NULL; break; + case SIOCRMNAT : if (!(mode & FWRITE)) { error = EPERM; @@ -750,11 +806,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; @@ -762,8 +820,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; @@ -784,6 +844,7 @@ int mode; } break; } + case SIOCIPFFL : /* old SIOCFLNAT & SIOCCNATL */ if (!(mode & FWRITE)) { error = EPERM; @@ -792,13 +853,17 @@ int mode; if (getlock) { WRITE_ENTER(&ipf_nat); } - error = 0; + + BCOPYIN(data, &arg, sizeof(arg)); if (arg == 0) ret = nat_flushtable(); else if (arg == 1) ret = nat_clearlist(); + else if (arg >=2 && arg <= 4) + ret = nat_extraflush(arg - 2); else error = EINVAL; + if (getlock) { RWLOCK_EXIT(&ipf_nat); } @@ -806,9 +871,11 @@ int mode; 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; @@ -816,6 +883,7 @@ int mode; fr_lock(data, &fr_nat_lock); } break; + case SIOCSTPUT : if ((mode & FWRITE) != 0) { error = fr_natputent(data, getlock); @@ -823,6 +891,7 @@ int mode; error = EACCES; } break; + case SIOCSTGSZ : if (fr_nat_lock) { if (getlock) { @@ -835,6 +904,7 @@ int mode; } else error = EACCES; break; + case SIOCSTGET : if (fr_nat_lock) { if (getlock) { @@ -847,12 +917,18 @@ int mode; } else error = EACCES; break; + + case SIOCIPFDELTOK : + BCOPYIN(data, &arg, sizeof(arg)); + error = ipf_deltoken(arg, uid, ctx); + break; + default : error = EINVAL; break; } done: - if (nt) + if (nt != NULL) KFREE(nt); return error; } @@ -980,6 +1056,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 @@ -1297,7 +1375,6 @@ int getlock; if (error != 0) goto junkput; - /* * New entry, copy in the rest of the NAT entry if it's size is more * than just the nat_t structure. @@ -1381,6 +1458,7 @@ int getlock; if (nat->nat_dir == NAT_OUTBOUND) { fin->fin_data[0] = ntohs(nat->nat_oport); fin->fin_data[1] = ntohs(nat->nat_outport); + fin->fin_ifp = nat->nat_ifps[0]; if (getlock) { READ_ENTER(&ipf_nat); } @@ -1396,6 +1474,7 @@ int getlock; } else if (nat->nat_dir == NAT_INBOUND) { fin->fin_data[0] = ntohs(nat->nat_outport); fin->fin_data[1] = ntohs(nat->nat_oport); + fin->fin_ifp = nat->nat_ifps[0]; if (getlock) { READ_ENTER(&ipf_nat); } @@ -1523,7 +1602,7 @@ junkput: if (fin != NULL) KFREE(fin); if (fr != NULL) - fr_derefrule(&fr); + (void) fr_derefrule(&fr); if ((ipnn != NULL) && (ipnn != ipn)) { KFREES(ipnn, ipn->ipn_dsize); @@ -1607,7 +1686,8 @@ int logtype; nat->nat_me = NULL; } - fr_deletequeueentry(&nat->nat_tqe); + if (nat->nat_tqe.tqe_ifq != NULL) + fr_deletequeueentry(&nat->nat_tqe); nat->nat_ref--; if (nat->nat_ref > 0) { @@ -1624,10 +1704,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 @@ -1636,18 +1716,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); @@ -1803,8 +1872,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); @@ -2025,10 +2093,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; @@ -2138,6 +2208,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; @@ -2223,6 +2310,7 @@ int direction; if (nat_stats.ns_inuse >= ipf_nattable_max) { nat_stats.ns_memfail++; + fr_nat_doflush = 1; return NULL; } @@ -2276,6 +2364,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); @@ -2388,7 +2477,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: @@ -2716,7 +2805,7 @@ u_int *nflags; int dir; { u_32_t sum1, sum2, sumd, sumd2; - struct in_addr in; + struct in_addr a1, a2; icmphdr_t *icmp; int flags, dlen; u_short *csump; @@ -2769,33 +2858,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 @@ -2806,185 +2869,102 @@ int dir; * two changes cancel each other out (if the delta for * the IP address is x, then the delta for ip_sum is minus x), * so no change in the icmp_cksum is necessary. - * - * Be careful that nat_dir refers to the direction of the - * offending IP packet (oip), not to its ICMP response (icmp) */ - fix_datacksum(&oip->ip_sum, sumd); - /* Fix icmp cksum : IP Addr + Cksum */ - sumd2 = (sumd >> 16); - /* - * Fix UDP pseudo header checksum to compensate for the - * IP address change. - */ - if ((oip->ip_p == IPPROTO_UDP) && (dlen >= 8) && (*csump != 0)) { - /* - * The UDP checksum is optional, only adjust it - * if it has been set. - */ - sum1 = ntohs(*csump); - fix_datacksum(csump, sumd); - sum2 = ntohs(*csump); - - /* - * Fix ICMP checksum to compensate the UDP - * checksum adjustment. - */ - sumd2 = sumd << 1; - CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd; + if (nat->nat_dir == NAT_OUTBOUND) { + 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 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 - */ - else if (oip->ip_p == IPPROTO_TCP && dlen >= 18) { - 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 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; + fix_datacksum(&oip->ip_sum, sumd); } - if (((flags & IPN_TCPUDP) != 0) && (dlen >= 4)) { - int mode = 0; + sumd2 = sumd; + sum1 = 0; + sum2 = 0; + /* + * Fix UDP pseudo header checksum to compensate for the + * IP address change. + */ + if (((flags & IPN_TCPUDP) != 0) && (dlen >= 4)) { /* * 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 (nat->nat_dir == NAT_OUTBOUND) { + 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; @@ -3662,9 +3642,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)) { @@ -4314,9 +4296,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], @@ -4395,6 +4377,11 @@ void fr_natexpire() } } + if (fr_nat_doflush != 0) { + nat_extraflush(2); + fr_nat_doflush = 0; + } + RWLOCK_EXIT(&ipf_nat); SPL_X(s); } @@ -4604,6 +4591,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 */ @@ -4884,3 +4900,388 @@ 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) { + /*MUTEX_ENTER(&nexthm->hm_lock);*/ + nexthm->hm_ref++; + /*MUTEX_EXIT(&nextipnat->hm_lock);*/ + } + } 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; + ipftqent_t *tqe, *tqn; + int delete, removed; + nat_t *nat, **natp; + long try, maxtick; + u_long interval; + SPL_INT(s); + + removed = 0; + + SPL_NET(s); + for (natp = &nat_instances; ((nat = *natp) != NULL); ) { + delete = 0; + + switch (which) + { + case 0 : + delete = 1; + break; + case 1 : + case 2 : + if (nat->nat_p != IPPROTO_TCP) + break; + if ((nat->nat_tcpstate[0] != IPF_TCPS_ESTABLISHED) || + (nat->nat_tcpstate[1] != IPF_TCPS_ESTABLISHED)) + delete = 1; + break; + } + + if (delete) { + nat_delete(nat, ISL_FLUSH); + removed++; + } else + natp = &nat->nat_next; + } + + if (which != 2) { + SPL_X(s); + return removed; + } + + /* + * Asked to remove inactive entries because the table is full, try + * again, 3 times, if first attempt failed with a different criteria + * each time. The order tried in must be in decreasing age. + * Another alternative is to implement random drop and drop N entries + * at random until N have been freed up. + */ + if (fr_ticks - nat_last_force_flush < IPF_TTLVAL(5)) + goto force_flush_skipped; + nat_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 = nat_tqb; ifq != NULL; + ifq = ifq->ifq_next) { + for (tqn = ifq->ifq_head; + ((tqe = tqn) != NULL); ) { + if (tqe->tqe_die > try) + break; + tqn = tqe->tqe_next; + nat = tqe->tqe_parent; + nat_delete(nat, ISL_EXPIRE); + removed++; + } + } + + for (ifq = nat_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; + nat = tqe->tqe_parent; + nat_delete(nat, 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; + } + } + } +force_flush_skipped: + SPL_X(s); + return removed; +} diff --git a/sys/dist/ipf/netinet/ip_nat.h b/sys/dist/ipf/netinet/ip_nat.h index 0e2cf7b7e1a..135cd5c1ec5 100644 --- a/sys/dist/ipf/netinet/ip_nat.h +++ b/sys/dist/ipf/netinet/ip_nat.h @@ -1,4 +1,4 @@ -/* $NetBSD: ip_nat.h,v 1.8 2007/03/04 06:02:56 christos Exp $ */ +/* $NetBSD: ip_nat.h,v 1.9 2007/04/14 20:34:37 martin Exp $ */ /* * Copyright (C) 1995-2001, 2003 by Darren Reed. @@ -6,7 +6,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_nat.h 1.5 2/4/96 - * Id: ip_nat.h,v 2.90.2.11 2005/06/18 02:41:32 darrenr Exp + * Id: ip_nat.h,v 2.90.2.16 2006/12/19 01:59:45 darrenr Exp */ #ifndef __IP_NAT_H__ @@ -123,6 +123,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 @@ -151,7 +152,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) @@ -170,6 +171,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 */ @@ -295,25 +297,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: @@ -321,6 +304,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; @@ -372,8 +357,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 { @@ -426,6 +412,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; @@ -443,7 +430,11 @@ extern natstat_t nat_stats; #if defined(__OpenBSD__) extern void nat_ifdetach __P((void *)); #endif -extern int fr_nat_ioctl __P((void *, ioctlcmd_t, int)); +#if __NetBSD_Version__ >= 499001000 +extern int fr_nat_ioctl __P((void*, ioctlcmd_t, int, int, void *)); +#else +extern int fr_nat_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *)); +#endif 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, @@ -468,9 +459,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/dist/ipf/netinet/ip_pool.c b/sys/dist/ipf/netinet/ip_pool.c index 24fb01f58bb..4849cfbf257 100644 --- a/sys/dist/ipf/netinet/ip_pool.c +++ b/sys/dist/ipf/netinet/ip_pool.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_pool.c,v 1.7 2006/09/17 13:43:15 yamt Exp $ */ +/* $NetBSD: ip_pool.c,v 1.8 2007/04/14 20:34:37 martin Exp $ */ /* * Copyright (C) 1993-2001, 2003 by Darren Reed. @@ -62,9 +62,6 @@ struct file; #if defined(_KERNEL) && (defined(__osf__) || defined(AIX) || \ defined(__hpux) || defined(__sgi)) -# ifdef __osf__ -# include <net/radix.h> -# endif # include "radix_ipf_local.h" # define _RADIX_H_ #endif @@ -85,7 +82,7 @@ static int rn_freenode __P((struct radix_node *, void *)); #if !defined(lint) static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)Id: ip_pool.c,v 2.55.2.15 2005/11/13 15:38:37 darrenr Exp"; +static const char rcsid[] = "@(#)Id: ip_pool.c,v 2.55.2.19 2007/02/17 12:41:42 darrenr Exp"; #endif #ifdef IPFILTER_LOOKUP @@ -97,6 +94,9 @@ static const char rcsid[] = "@(#)Id: ip_pool.c,v 2.55.2.15 2005/11/13 15:38:37 d # define RADIX_NODE_HEAD_UNLOCK(x) ; # endif +static void ip_pool_clearnodes __P((ip_pool_t *)); +static void *ip_pool_exists __P((int, char *)); + ip_pool_stat_t ipoolstat; ipfrwlock_t ip_poolrw; @@ -144,7 +144,7 @@ main(argc, argv) strlcpy(op.iplo_name, "0", sizeof(op.iplo_name)); if (ip_pool_create(&op) == 0) - ipo = ip_pool_find(0, "0"); + ipo = ip_pool_exists(0, "0"); a.adf_addr.in4.s_addr = 0x0a010203; b.adf_addr.in4.s_addr = 0xffffffff; @@ -269,18 +269,14 @@ int ip_pool_init() void ip_pool_fini() { ip_pool_t *p, *q; - iplookupop_t op; int i; ASSERT(rw_read_locked(&ipf_global.ipf_lk) == 0); for (i = 0; i <= IPL_LOGMAX; i++) { for (q = ip_pool_list[i]; (p = q) != NULL; ) { - op.iplo_unit = i; - (void)strncpy(op.iplo_name, p->ipo_name, - sizeof(op.iplo_name)); q = p->ipo_next; - (void) ip_pool_destroy(&op); + (void) ip_pool_destroy(i, p->ipo_name); } } @@ -314,8 +310,8 @@ iplookupop_t *op; stats.ipls_list[i] = ip_pool_list[i]; } else if (unit >= 0 && unit < IPL_LOGSIZE) { if (op->iplo_name[0] != '\0') - stats.ipls_list[unit] = ip_pool_find(unit, - op->iplo_name); + stats.ipls_list[unit] = ip_pool_exists(unit, + op->iplo_name); else stats.ipls_list[unit] = ip_pool_list[unit]; } else @@ -326,16 +322,15 @@ iplookupop_t *op; } - /* ------------------------------------------------------------------------ */ -/* Function: ip_pool_find */ +/* Function: ip_pool_exists */ /* Returns: int - 0 = success, else error */ /* Parameters: ipo(I) - pointer to the pool getting the new node. */ /* */ /* Find a matching pool inside the collection of pools for a particular */ /* device, indicated by the unit number. */ /* ------------------------------------------------------------------------ */ -void *ip_pool_find(unit, name) +static void *ip_pool_exists(unit, name) int unit; char *name; { @@ -349,6 +344,29 @@ char *name; /* ------------------------------------------------------------------------ */ +/* Function: ip_pool_find */ +/* Returns: int - 0 = success, else error */ +/* Parameters: ipo(I) - pointer to the pool getting the new node. */ +/* */ +/* Find a matching pool inside the collection of pools for a particular */ +/* device, indicated by the unit number. If it is marked for deletion then */ +/* pretend it does not exist. */ +/* ------------------------------------------------------------------------ */ +void *ip_pool_find(unit, name) +int unit; +char *name; +{ + ip_pool_t *p; + + p = ip_pool_exists(unit, name); + if ((p != NULL) && (p->ipo_flags & IPOOL_DELETE)) + return NULL; + + return p; +} + + +/* ------------------------------------------------------------------------ */ /* Function: ip_pool_findeq */ /* Returns: int - 0 = success, else error */ /* Parameters: ipo(I) - pointer to the pool getting the new node. */ @@ -482,6 +500,7 @@ int info; return ENOMEM; } + x->ipn_ref = 1; x->ipn_next = ipo->ipo_list; x->ipn_pnext = &ipo->ipo_list; if (ipo->ipo_list != NULL) @@ -505,6 +524,10 @@ int info; /* when being inserted - assume this has already been done. If the pool is */ /* marked as being anonymous, give it a new, unique, identifier. Call any */ /* other functions required to initialise the structure. */ +/* */ +/* If the structure is flagged for deletion then reset the flag and return, */ +/* as this likely means we've tried to free a pool that is in use (flush) */ +/* and now want to repopulate it with "new" data. */ /* ------------------------------------------------------------------------ */ int ip_pool_create(op) iplookupop_t *op; @@ -515,23 +538,37 @@ iplookupop_t *op; ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0); - KMALLOC(h, ip_pool_t *); - if (h == NULL) - return ENOMEM; - bzero(h, sizeof(*h)); + unit = op->iplo_unit; - if (rn_inithead((void **)&h->ipo_head, - offsetof(addrfamily_t, adf_addr) << 3) == 0) { - KFREE(h); - return ENOMEM; - } + if ((op->iplo_arg & LOOKUP_ANON) == 0) + h = ip_pool_exists(unit, op->iplo_name); + else + h = NULL; - unit = op->iplo_unit; + if (h != NULL) { + if ((h->ipo_flags & IPOOL_DELETE) != 0) { + h->ipo_flags &= ~IPOOL_DELETE; + return 0; + } + return EEXIST; + } else { + KMALLOC(h, ip_pool_t *); + if (h == NULL) + return ENOMEM; + bzero(h, sizeof(*h)); + + if (rn_inithead((void **)&h->ipo_head, + offsetof(addrfamily_t, adf_addr) << 3) == 0) { + KFREE(h); + return ENOMEM; + } + } - if ((op->iplo_arg & IPOOL_ANON) != 0) { + if ((op->iplo_arg & LOOKUP_ANON) != 0) { ip_pool_t *p; - poolnum = IPOOL_ANON; + h->ipo_flags |= IPOOL_ANON; + poolnum = LOOKUP_ANON; #if defined(SNPRINTF) && defined(_KERNEL) SNPRINTF(name, sizeof(name), "%x", poolnum); @@ -556,19 +593,21 @@ iplookupop_t *op; (void)strncpy(h->ipo_name, name, sizeof(h->ipo_name)); (void)strncpy(op->iplo_name, name, sizeof(op->iplo_name)); } else { - (void) strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name)); + (void)strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name)); } - h->ipo_ref = 1; - h->ipo_list = NULL; - h->ipo_unit = unit; - h->ipo_next = ip_pool_list[unit]; - if (ip_pool_list[unit] != NULL) - ip_pool_list[unit]->ipo_pnext = &h->ipo_next; - h->ipo_pnext = &ip_pool_list[unit]; - ip_pool_list[unit] = h; - - ipoolstat.ipls_pools++; + if ((h->ipo_flags & IPOOL_DELETE) == 0) { + h->ipo_ref = 1; + h->ipo_list = NULL; + h->ipo_unit = unit; + h->ipo_next = ip_pool_list[unit]; + if (ip_pool_list[unit] != NULL) + ip_pool_list[unit]->ipo_pnext = &h->ipo_next; + h->ipo_pnext = &ip_pool_list[unit]; + ip_pool_list[unit] = h; + + ipoolstat.ipls_pools++; + } return 0; } @@ -581,36 +620,26 @@ iplookupop_t *op; /* ipe(I) - address being deleted as a node */ /* Locks: WRITE(ip_poolrw) */ /* */ -/* Add another node to the pool given by ipo. The three parameters passed */ -/* in (addr, mask, info) shold all be stored in the node. */ +/* Remove a node from the pool given by ipo. */ /* ------------------------------------------------------------------------ */ int ip_pool_remove(ipo, ipe) ip_pool_t *ipo; ip_pool_node_t *ipe; { - ip_pool_node_t **ipp, *n; ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0); - for (ipp = &ipo->ipo_list; (n = *ipp) != NULL; ipp = &n->ipn_next) { - if (ipe == n) { - *n->ipn_pnext = n->ipn_next; - if (n->ipn_next) - n->ipn_next->ipn_pnext = n->ipn_pnext; - break; - } - } - - if (n == NULL) - return ENOENT; + if (ipe->ipn_pnext != NULL) + *ipe->ipn_pnext = ipe->ipn_next; + if (ipe->ipn_next != NULL) + ipe->ipn_next->ipn_pnext = ipe->ipn_pnext; RADIX_NODE_HEAD_LOCK(ipo->ipo_head); - ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask, + ipo->ipo_head->rnh_deladdr(&ipe->ipn_addr, &ipe->ipn_mask, ipo->ipo_head); RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head); - KFREE(n); - ipoolstat.ipls_nodes--; + ip_pool_node_deref(ipe); return 0; } @@ -623,23 +652,28 @@ ip_pool_node_t *ipe; /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ /* */ /* Search for a pool using paramters passed in and if it's not otherwise */ -/* busy, free it. */ +/* busy, free it. If it is busy, clear all of its nodes, mark it for being */ +/* deleted and return an error saying it is busy. */ /* */ -/* NOTE: Because this function is called out of ipldetach() where ip_poolrw */ +/* NOTE: Because this function is called out of ipfdetach() where ip_poolrw */ /* may not be initialised, we can't use an ASSERT to enforce the locking */ /* assertion that one of the two (ip_poolrw,ipf_global) is held. */ /* ------------------------------------------------------------------------ */ -int ip_pool_destroy(op) -iplookupop_t *op; +int ip_pool_destroy(unit, name) +int unit; +char *name; { ip_pool_t *ipo; - ipo = ip_pool_find(op->iplo_unit, op->iplo_name); + ipo = ip_pool_exists(unit, name); if (ipo == NULL) return ESRCH; - if (ipo->ipo_ref != 1) - return EBUSY; + if (ipo->ipo_ref != 1) { + ip_pool_clearnodes(ipo); + ipo->ipo_flags |= IPOOL_DELETE; + return 0; + } ip_pool_free(ipo); return 0; @@ -655,7 +689,7 @@ iplookupop_t *op; /* Free all pools associated with the device that matches the unit number */ /* passed in with operation. */ /* */ -/* NOTE: Because this function is called out of ipldetach() where ip_poolrw */ +/* NOTE: Because this function is called out of ipfdetach() where ip_poolrw */ /* may not be initialised, we can't use an ASSERT to enforce the locking */ /* assertion that one of the two (ip_poolrw,ipf_global) is held. */ /* ------------------------------------------------------------------------ */ @@ -676,7 +710,7 @@ iplookupflush_t *fp; (void)strncpy(op.iplo_name, p->ipo_name, sizeof(op.iplo_name)); q = p->ipo_next; - err = ip_pool_destroy(&op); + err = ip_pool_destroy(op.iplo_unit, op.iplo_name); if (err == 0) num++; else @@ -697,13 +731,37 @@ iplookupflush_t *fp; /* all of the address information stored in it, including any tree data */ /* structures also allocated. */ /* */ -/* NOTE: Because this function is called out of ipldetach() where ip_poolrw */ +/* NOTE: Because this function is called out of ipfdetach() where ip_poolrw */ /* may not be initialised, we can't use an ASSERT to enforce the locking */ /* assertion that one of the two (ip_poolrw,ipf_global) is held. */ /* ------------------------------------------------------------------------ */ void ip_pool_free(ipo) ip_pool_t *ipo; { + + ip_pool_clearnodes(ipo); + + if (ipo->ipo_next != NULL) + ipo->ipo_next->ipo_pnext = ipo->ipo_pnext; + *ipo->ipo_pnext = ipo->ipo_next; + rn_freehead(ipo->ipo_head); + KFREE(ipo); + + ipoolstat.ipls_pools--; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ip_pool_clearnodes */ +/* Returns: void */ +/* Parameters: ipo(I) - pointer to pool structure */ +/* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ +/* */ +/* Deletes all nodes stored in a pool structure. */ +/* ------------------------------------------------------------------------ */ +static void ip_pool_clearnodes(ipo) +ip_pool_t *ipo; +{ ip_pool_node_t *n; RADIX_NODE_HEAD_LOCK(ipo->ipo_head); @@ -722,13 +780,6 @@ ip_pool_t *ipo; RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head); ipo->ipo_list = NULL; - if (ipo->ipo_next != NULL) - ipo->ipo_next->ipo_pnext = ipo->ipo_pnext; - *ipo->ipo_pnext = ipo->ipo_next; - rn_freehead(ipo->ipo_head); - KFREE(ipo); - - ipoolstat.ipls_pools--; } @@ -748,8 +799,179 @@ ip_pool_t *ipo; ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0); ipo->ipo_ref--; + if (ipo->ipo_ref == 0) ip_pool_free(ipo); + + else if ((ipo->ipo_ref == 1) && (ipo->ipo_flags & IPOOL_DELETE)) + ip_pool_destroy(ipo->ipo_unit, ipo->ipo_name); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ip_pool_node_deref */ +/* Returns: void */ +/* Parameters: ipn(I) - pointer to pool structure */ +/* Locks: WRITE(ip_poolrw) */ +/* */ +/* Drop a reference to the pool node passed in and if we're the last, free */ +/* it all up and adjust the stats accordingly. */ +/* ------------------------------------------------------------------------ */ +void ip_pool_node_deref(ipn) +ip_pool_node_t *ipn; +{ + + ipn->ipn_ref--; + + if (ipn->ipn_ref == 0) { + KFREE(ipn); + ipoolstat.ipls_nodes--; + } +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ip_pool_getnext */ +/* Returns: void */ +/* Parameters: token(I) - pointer to pool structure */ +/* Parameters: ilp(IO) - pointer to pool iterating structure */ +/* */ +/* ------------------------------------------------------------------------ */ +int ip_pool_getnext(token, ilp) +ipftoken_t *token; +ipflookupiter_t *ilp; +{ + ip_pool_node_t *node, zn, *nextnode; + ip_pool_t *ipo, zp, *nextipo; + int err; + + err = 0; + node = NULL; + nextnode = NULL; + ipo = NULL; + nextipo = NULL; + + READ_ENTER(&ip_poolrw); + + switch (ilp->ili_otype) + { + case IPFLOOKUPITER_LIST : + ipo = token->ipt_data; + if (ipo == NULL) { + nextipo = ip_pool_list[(int)ilp->ili_unit]; + } else { + nextipo = ipo->ipo_next; + } + + if (nextipo != NULL) { + ATOMIC_INC(nextipo->ipo_ref); + if (nextipo->ipo_next == NULL) + token->ipt_alive = 0; + } else { + bzero((char *)&zp, sizeof(zp)); + nextipo = &zp; + } + break; + + case IPFLOOKUPITER_NODE : + node = token->ipt_data; + if (node == NULL) { + ipo = ip_pool_exists(ilp->ili_unit, ilp->ili_name); + if (ipo == NULL) + err = ESRCH; + else { + nextnode = ipo->ipo_list; + ipo = NULL; + } + } else { + nextnode = node->ipn_next; + } + + if (nextnode != NULL) { + ATOMIC_INC(nextnode->ipn_ref); + if (nextnode->ipn_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 (ipo != NULL) { + WRITE_ENTER(&ip_poolrw); + ip_pool_deref(ipo); + RWLOCK_EXIT(&ip_poolrw); + } + token->ipt_data = nextipo; + err = COPYOUT(nextipo, ilp->ili_data, sizeof(*nextipo)); + if (err != 0) + err = EFAULT; + break; + + case IPFLOOKUPITER_NODE : + if (node != NULL) { + WRITE_ENTER(&ip_poolrw); + ip_pool_node_deref(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; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ip_pool_iterderef */ +/* Returns: void */ +/* Parameters: ipn(I) - pointer to pool structure */ +/* Locks: WRITE(ip_poolrw) */ +/* */ +/* ------------------------------------------------------------------------ */ +void ip_pool_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); + ip_pool_deref((ip_pool_t *)data); + RWLOCK_EXIT(&ip_poolrw); + break; + + case IPFLOOKUPITER_NODE : + WRITE_ENTER(&ip_poolrw); + ip_pool_node_deref((ip_pool_node_t *)data); + RWLOCK_EXIT(&ip_poolrw); + break; + default : + break; + } } @@ -787,5 +1009,4 @@ rn_freehead(rnh) Free(rnh); } # endif - #endif /* IPFILTER_LOOKUP */ diff --git a/sys/dist/ipf/netinet/ip_pool.h b/sys/dist/ipf/netinet/ip_pool.h index 20c40ef0a3b..2fea0ade31b 100644 --- a/sys/dist/ipf/netinet/ip_pool.h +++ b/sys/dist/ipf/netinet/ip_pool.h @@ -1,11 +1,11 @@ -/* $NetBSD: ip_pool.h,v 1.3 2006/04/04 16:17:19 martti Exp $ */ +/* $NetBSD: ip_pool.h,v 1.4 2007/04/14 20:34:38 martin Exp $ */ /* * Copyright (C) 1993-2001, 2003 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * Id: ip_pool.h,v 2.26.2.3 2005/06/12 07:18:27 darrenr Exp + * Id: ip_pool.h,v 2.26.2.5 2007/01/14 14:06:12 darrenr Exp */ #ifndef __IP_POOL_H__ @@ -37,8 +37,9 @@ typedef struct ip_pool_node { addrfamily_t ipn_addr; addrfamily_t ipn_mask; int ipn_info; - char ipn_name[FR_GROUPLEN]; - u_long ipn_hits; + int ipn_ref; +char ipn_name[FR_GROUPLEN]; +u_long ipn_hits; struct ip_pool_node *ipn_next, **ipn_pnext; } ip_pool_node_t; @@ -55,7 +56,8 @@ typedef struct ip_pool_s { char ipo_name[FR_GROUPLEN]; } ip_pool_t; -#define IPOOL_ANON 0x80000000 +#define IPOOL_DELETE 0x01 +#define IPOOL_ANON 0x02 typedef struct ip_pool_stat { @@ -75,13 +77,16 @@ extern void ip_pool_fini __P((void)); extern int ip_pool_create __P((iplookupop_t *)); extern int ip_pool_insert __P((ip_pool_t *, i6addr_t *, i6addr_t *, int)); extern int ip_pool_remove __P((ip_pool_t *, ip_pool_node_t *)); -extern int ip_pool_destroy __P((iplookupop_t *)); +extern int ip_pool_destroy __P((int, char *)); extern void ip_pool_free __P((ip_pool_t *)); extern void ip_pool_deref __P((ip_pool_t *)); +extern void ip_pool_node_deref __P((ip_pool_node_t *)); extern void *ip_pool_find __P((int, char *)); extern ip_pool_node_t *ip_pool_findeq __P((ip_pool_t *, addrfamily_t *, addrfamily_t *)); extern int ip_pool_flush __P((iplookupflush_t *)); extern int ip_pool_statistics __P((iplookupop_t *)); +extern int ip_pool_getnext __P((ipftoken_t *, ipflookupiter_t *)); +extern void ip_pool_iterderef __P((u_int, int, void *)); #endif /* __IP_POOL_H__ */ diff --git a/sys/dist/ipf/netinet/ip_pptp_pxy.c b/sys/dist/ipf/netinet/ip_pptp_pxy.c index 887851f548e..ab45d9441c5 100644 --- a/sys/dist/ipf/netinet/ip_pptp_pxy.c +++ b/sys/dist/ipf/netinet/ip_pptp_pxy.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_pptp_pxy.c,v 1.6 2006/04/04 16:17:19 martti Exp $ */ +/* $NetBSD: ip_pptp_pxy.c,v 1.7 2007/04/14 20:34:38 martin Exp $ */ /* * Copyright (C) 2002-2003 by Darren Reed @@ -6,7 +6,7 @@ * Simple PPTP transparent proxy for in-kernel use. For use with the NAT * code. * - * Id: ip_pptp_pxy.c,v 2.10.2.13 2006/03/17 10:40:05 darrenr Exp + * Id: ip_pptp_pxy.c,v 2.10.2.15 2006/10/31 12:11:23 darrenr Exp * */ #define IPF_PPTP_PROXY @@ -80,6 +80,9 @@ void ippr_pptp_fini() /* * Setup for a new PPTP proxy. + * + * NOTE: The printf's are broken up with %s in them to prevent them being + * optimised into puts statements on FreeBSD (this doesn't exist in the kernel) */ int ippr_pptp_new(fin, aps, nat) fr_info_t *fin; @@ -222,7 +225,7 @@ pptp_pxy_t *pptp; pptp->pptp_state = fr_addstate(&fi, &pptp->pptp_state, 0); if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); + fr_statederef((ipstate_t **)&fi.fin_state); } ip->ip_p = p; return; diff --git a/sys/dist/ipf/netinet/ip_proxy.c b/sys/dist/ipf/netinet/ip_proxy.c index 58c2f678ed0..42fc753477f 100644 --- a/sys/dist/ipf/netinet/ip_proxy.c +++ b/sys/dist/ipf/netinet/ip_proxy.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_proxy.c,v 1.12 2007/03/04 06:02:56 christos Exp $ */ +/* $NetBSD: ip_proxy.c,v 1.13 2007/04/14 20:34:38 martin Exp $ */ /* * Copyright (C) 1997-2003 by Darren Reed. @@ -105,7 +105,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.18 2006/07/14 06:12:17 darrenr Exp"; #endif #ifdef INET @@ -195,7 +195,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))) { @@ -292,10 +292,15 @@ ipnat_t *nat; } -int appr_ioctl(data, cmd, mode) +int appr_ioctl(data, cmd, mode, ctx) +#if __NetBSD_Version__ >= 499001000 void *data; +#else +caddr_t data; +#endif ioctlcmd_t cmd; int mode; +void *ctx; { ap_ctl_t ctl; void *ptr; diff --git a/sys/dist/ipf/netinet/ip_proxy.h b/sys/dist/ipf/netinet/ip_proxy.h index 06348452ea5..3afc5bb1129 100644 --- a/sys/dist/ipf/netinet/ip_proxy.h +++ b/sys/dist/ipf/netinet/ip_proxy.h @@ -1,11 +1,11 @@ -/* $NetBSD: ip_proxy.h,v 1.5 2007/03/04 06:02:57 christos Exp $ */ +/* $NetBSD: ip_proxy.h,v 1.6 2007/04/14 20:34:38 martin Exp $ */ /* * Copyright (C) 1997-2001 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * Id: ip_proxy.h,v 2.31.2.3 2005/06/18 02:41:33 darrenr Exp + * Id: ip_proxy.h,v 2.31.2.4 2006/07/14 06:12:17 darrenr Exp */ #ifndef _NETINET_IP_PROXY_H_ @@ -455,6 +455,10 @@ 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((void *, ioctlcmd_t, int)); +#if __NetBSD_Version__ >= 499001000 +extern int appr_ioctl __P((void *, ioctlcmd_t, int, void *)); +#else +extern int appr_ioctl __P((caddr_t, ioctlcmd_t, int, void *)); +#endif #endif /* _NETINET_IP_PROXY_H_ */ diff --git a/sys/dist/ipf/netinet/ip_raudio_pxy.c b/sys/dist/ipf/netinet/ip_raudio_pxy.c index 85ba3c81c15..4a4a6bf4e9e 100644 --- a/sys/dist/ipf/netinet/ip_raudio_pxy.c +++ b/sys/dist/ipf/netinet/ip_raudio_pxy.c @@ -1,14 +1,14 @@ -/* $NetBSD: ip_raudio_pxy.c,v 1.3 2005/12/11 12:24:21 christos Exp $ */ +/* $NetBSD: ip_raudio_pxy.c,v 1.4 2007/04/14 20:34:38 martin Exp $ */ #include <sys/cdefs.h> -__KERNEL_RCSID(1, "$NetBSD: ip_raudio_pxy.c,v 1.3 2005/12/11 12:24:21 christos Exp $"); +__KERNEL_RCSID(1, "$NetBSD: ip_raudio_pxy.c,v 1.4 2007/04/14 20:34:38 martin Exp $"); /* * Copyright (C) 1998-2003 by Darren Reed * * See the IPFILTER.LICENCE file for details on licencing. * - * Id: ip_raudio_pxy.c,v 1.40.2.3 2005/02/04 10:22:55 darrenr Exp + * Id: ip_raudio_pxy.c,v 1.40.2.4 2006/07/14 06:12:17 darrenr Exp */ #define IPF_RAUDIO_PROXY @@ -309,7 +309,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); } } @@ -329,7 +329,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/dist/ipf/netinet/ip_rcmd_pxy.c b/sys/dist/ipf/netinet/ip_rcmd_pxy.c index 086c7f40590..ed59a3eb7ed 100644 --- a/sys/dist/ipf/netinet/ip_rcmd_pxy.c +++ b/sys/dist/ipf/netinet/ip_rcmd_pxy.c @@ -1,14 +1,14 @@ -/* $NetBSD: ip_rcmd_pxy.c,v 1.8 2006/04/04 16:17:19 martti Exp $ */ +/* $NetBSD: ip_rcmd_pxy.c,v 1.9 2007/04/14 20:34:38 martin Exp $ */ #include <sys/cdefs.h> -__KERNEL_RCSID(1, "$NetBSD: ip_rcmd_pxy.c,v 1.8 2006/04/04 16:17:19 martti Exp $"); +__KERNEL_RCSID(1, "$NetBSD: ip_rcmd_pxy.c,v 1.9 2007/04/14 20:34:38 martin Exp $"); /* * Copyright (C) 1998-2003 by Darren Reed * * 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. @@ -209,7 +209,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/dist/ipf/netinet/ip_rpcb_pxy.c b/sys/dist/ipf/netinet/ip_rpcb_pxy.c index 605008ba822..77fc91e4ec9 100644 --- a/sys/dist/ipf/netinet/ip_rpcb_pxy.c +++ b/sys/dist/ipf/netinet/ip_rpcb_pxy.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_rpcb_pxy.c,v 1.10 2007/03/04 06:02:57 christos Exp $ */ +/* $NetBSD: ip_rpcb_pxy.c,v 1.11 2007/04/14 20:34:38 martin Exp $ */ /* * Copyright (C) 2002-2003 by Ryan Beasley <ryanb@goddamnbastard.org> @@ -39,7 +39,7 @@ * o The enclosed hack of STREAMS support is pretty sick and most likely * broken. * - * Id: ip_rpcb_pxy.c,v 2.25.2.3 2005/02/04 10:22:56 darrenr Exp + * Id: ip_rpcb_pxy.c,v 2.25.2.6 2007/01/17 11:34:54 darrenr Exp */ #define IPF_RPCB_PROXY @@ -311,6 +311,8 @@ ippr_rpcb_out(fin, aps, nat) COPYDATA(m, off, dlen, (void *)&rm->rm_msgbuf); rm->rm_buflen = dlen; + rx = NULL; /* XXX gcc */ + /* Send off to decode reply. */ rv = ippr_rpcb_decoderep(fin, nat, rs, rm, &rx); @@ -1160,6 +1162,8 @@ ippr_rpcb_getnat(fin, nat, proto, port) /* Generate dummy fr_info */ bcopy((char *)fin, (char *)&fi, sizeof(fi)); + fi.fin_state = NULL; + fi.fin_nat = NULL; fi.fin_out = 0; fi.fin_src = fin->fin_dst; fi.fin_dst = nat->nat_outip; @@ -1276,7 +1280,7 @@ ippr_rpcb_getnat(fin, nat, proto, port) return(-1); } if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); + fr_statederef((ipstate_t **)&fi.fin_state); } return(0); diff --git a/sys/dist/ipf/netinet/ip_scan.c b/sys/dist/ipf/netinet/ip_scan.c index 26dd79b898a..26b5014a9f6 100644 --- a/sys/dist/ipf/netinet/ip_scan.c +++ b/sys/dist/ipf/netinet/ip_scan.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_scan.c,v 1.8 2007/03/04 06:02:57 christos Exp $ */ +/* $NetBSD: ip_scan.c,v 1.9 2007/04/14 20:34:39 martin Exp $ */ /* * Copyright (C) 1995-2001 by Darren Reed. @@ -60,7 +60,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_scan.c,v 2.40.2.6 2006/03/26 23:06:49 darrenr Exp"; +static const char rcsid[] = "@(#)Id: ip_scan.c,v 2.40.2.8 2007/01/16 02:25:20 darrenr Exp"; #endif #ifdef IPFILTER_SCAN /* endif at bottom of file */ @@ -572,10 +572,15 @@ ipstate_t *is; } -int fr_scan_ioctl(data, cmd, mode) +int fr_scan_ioctl(data, cmd, mode, uid, ctx) +#if __NetBSD_Version__ >= 499001000 void *data; +#else +caddr_t data; +#endif ioctlcmd_t cmd; -int mode; +int mode, uid; +void *ctx; { ipscanstat_t ipscs; int err = 0; diff --git a/sys/dist/ipf/netinet/ip_scan.h b/sys/dist/ipf/netinet/ip_scan.h index 3cbae341037..8e21f2644ce 100644 --- a/sys/dist/ipf/netinet/ip_scan.h +++ b/sys/dist/ipf/netinet/ip_scan.h @@ -1,4 +1,4 @@ -/* $NetBSD: ip_scan.h,v 1.4 2007/03/04 06:02:57 christos Exp $ */ +/* $NetBSD: ip_scan.h,v 1.5 2007/04/14 20:34:39 martin Exp $ */ /* * Copyright (C) 1993-2001 by Darren Reed. @@ -6,7 +6,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_fil.h 1.35 6/5/96 - * Id: ip_scan.h,v 2.9.2.1 2005/06/12 07:18:29 darrenr Exp + * Id: ip_scan.h,v 2.9.2.2 2006/07/14 06:12:19 darrenr Exp */ #ifndef __IP_SCAN_H__ @@ -96,7 +96,11 @@ typedef struct ipscanstat { } ipscanstat_t; -extern int fr_scan_ioctl __P((void *, ioctlcmd_t, int)); +#if __NetBSD_Version__ >= 499001000 +extern int fr_scan_ioctl __P((void*, ioctlcmd_t, int, int, void *)); +#else +extern int fr_scan_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *)); +#endif extern int ipsc_init __P((void)); extern int ipsc_attachis __P((struct ipstate *)); extern int ipsc_attachfr __P((struct frentry *)); diff --git a/sys/dist/ipf/netinet/ip_state.c b/sys/dist/ipf/netinet/ip_state.c index fb45abd2e6b..d30ca537214 100644 --- a/sys/dist/ipf/netinet/ip_state.c +++ b/sys/dist/ipf/netinet/ip_state.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_state.c,v 1.17 2007/03/04 06:02:57 christos Exp $ */ +/* $NetBSD: ip_state.c,v 1.18 2007/04/14 20:34:39 martin Exp $ */ /* * Copyright (C) 1995-2003 by Darren Reed. @@ -17,7 +17,11 @@ #include <sys/file.h> #if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ defined(_KERNEL) -# include "opt_ipfilter.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) @@ -110,10 +114,10 @@ struct file; #if !defined(lint) #if defined(__NetBSD__) #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ip_state.c,v 1.17 2007/03/04 06:02:57 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_state.c,v 1.18 2007/04/14 20:34:39 martin Exp $"); #else 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.52 2007/02/02 22:50:32 darrenr Exp"; #endif #endif @@ -131,8 +135,12 @@ static ipstate_t *fr_matchsrcdst __P((fr_info_t *, ipstate_t *, i6addr_t *, static ipstate_t *fr_checkicmpmatchingstate __P((fr_info_t *)); static int fr_state_flush __P((int, int)); static ips_stat_t *fr_statetstats __P((void)); -static void fr_delstate __P((ipstate_t *, int)); -static int fr_state_remove __P((void *)); +static int fr_delstate __P((ipstate_t *, int)); +#if __NetBSD_Version__ >= 499001000 +static int fr_state_remove __P((void*)); +#else +static int fr_state_remove __P((caddr_t)); +#endif static void fr_ipsmove __P((ipstate_t *, u_int)); static int fr_tcpstate __P((fr_info_t *, tcphdr_t *, ipstate_t *)); static int fr_tcpoptions __P((fr_info_t *, tcphdr_t *, tcpdata_t *)); @@ -140,6 +148,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((void *)); int fr_stgetent __P((void *)); @@ -302,7 +312,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 @@ -421,10 +431,15 @@ void *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) +#if __NetBSD_Version__ >= 499001000 void *data; +#else +caddr_t data; +#endif ioctlcmd_t cmd; -int mode; +int mode, uid; +void *ctx; { int arg, ret, error = 0; @@ -436,6 +451,7 @@ int mode; case SIOCDELST : error = fr_state_remove(data); break; + /* * Flush the state table */ @@ -446,9 +462,11 @@ int mode; ret = fr_state_flush(arg, 4); RWLOCK_EXIT(&ipf_state); BCOPYOUT((char *)&ret, data, sizeof(ret)); - } else + } else { error = EINVAL; + } break; + #ifdef USE_INET6 case SIOCIPFL6 : BCOPYIN(data, (char *)&arg, sizeof(arg)); @@ -457,8 +475,9 @@ int mode; ret = fr_state_flush(arg, 6); RWLOCK_EXIT(&ipf_state); BCOPYOUT((char *)&ret, data, sizeof(ret)); - } else + } else { error = EINVAL; + } break; #endif #ifdef IPFILTER_LOG @@ -475,6 +494,7 @@ int mode; BCOPYOUT((char *)&tmp, data, sizeof(tmp)); } break; + /* * Turn logging of state information on/off. */ @@ -483,16 +503,18 @@ int mode; error = EPERM; else { BCOPYIN((char *)data, (char *)&ipstate_logging, - sizeof(ipstate_logging)); + sizeof(ipstate_logging)); } break; + /* * Return the current state of logging. */ case SIOCGETLG : BCOPYOUT((char *)&ipstate_logging, (char *)data, - sizeof(ipstate_logging)); + sizeof(ipstate_logging)); break; + /* * Return the number of bytes currently waiting to be read. */ @@ -501,12 +523,14 @@ int mode; BCOPYOUT((char *)&arg, data, sizeof(arg)); 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). @@ -518,6 +542,7 @@ int mode; fr_lock(data, &fr_state_lock); } break; + /* * Add an entry to the current state table. */ @@ -528,6 +553,7 @@ int mode; } error = fr_stputent(data); break; + /* * Get a state table entry. */ @@ -538,6 +564,42 @@ int mode; } error = fr_stgetent(data); break; + + /* + * Return a copy of the hash table bucket lengths + */ + case SIOCSTAT1 : + BCOPYOUT(ips_stats.iss_bucketlen, data, + fr_statesize * sizeof(u_long)); + break; + + case SIOCGENITER : + { + ipftoken_t *token; + ipfgeniter_t iter; + + error = fr_inobj(data, &iter, IPFOBJ_GENITER); + if (error != 0) + break; + + token = ipf_findtoken(IPFGENITER_STATE, uid, ctx); + if (token != NULL) + error = fr_stateiter(token, &iter); + else + error = ESRCH; + RWLOCK_EXIT(&ipf_tokens); + break; + } + + case SIOCGTABL : + error = fr_stgettable(data); + break; + + case SIOCIPFDELTOK : + BCOPYIN(data, (char *)&arg, sizeof(arg)); + error = ipf_deltoken(arg, uid, ctx); + break; + default : error = EINVAL; break; @@ -677,7 +739,8 @@ void *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); /* @@ -826,7 +889,6 @@ u_int flags; frentry_t *fr; tcphdr_t *tcp; grehdr_t *gre; - void *ifp; int out; if (fr_state_lock || @@ -1092,21 +1154,16 @@ u_int flags; is->is_tag = fr->fr_logtag; 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; @@ -1728,9 +1785,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) @@ -2000,7 +2057,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 @@ -2030,7 +2087,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; @@ -2619,8 +2675,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; @@ -2765,7 +2819,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; { @@ -2776,16 +2830,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) @@ -2813,7 +2857,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; @@ -2822,11 +2867,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) @@ -2845,6 +2894,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); @@ -2855,12 +2917,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; } @@ -2978,8 +3042,10 @@ int which, proto; } if (delete) { - fr_delstate(is, ISL_FLUSH); - removed++; + if (fr_delstate(is, ISL_FLUSH) == 0) + removed++; + else + isp = &is->is_next; } else isp = &is->is_next; } @@ -3026,8 +3092,8 @@ int which, proto; break; tqn = tqe->tqe_next; is = tqe->tqe_parent; - fr_delstate(is, ISL_EXPIRE); - removed++; + if (fr_delstate(is, ISL_EXPIRE) == 0) + removed++; } } @@ -3040,8 +3106,8 @@ int which, proto; break; tqn = tqe->tqe_next; is = tqe->tqe_parent; - fr_delstate(is, ISL_EXPIRE); - removed++; + if (fr_delstate(is, ISL_EXPIRE) == 0) + removed++; } } if (try + interval > maxtick) @@ -3546,7 +3612,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; @@ -3567,7 +3633,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; @@ -3759,40 +3824,11 @@ void fr_sttab_destroy(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); @@ -3801,15 +3837,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 } @@ -3884,3 +3913,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/dist/ipf/netinet/ip_state.h b/sys/dist/ipf/netinet/ip_state.h index c59323aa286..5af358a5041 100644 --- a/sys/dist/ipf/netinet/ip_state.h +++ b/sys/dist/ipf/netinet/ip_state.h @@ -1,4 +1,4 @@ -/* $NetBSD: ip_state.h,v 1.6 2007/03/04 06:02:57 christos Exp $ */ +/* $NetBSD: ip_state.h,v 1.7 2007/04/14 20:34:39 martin Exp $ */ /* * Copyright (C) 1995-2001 by Darren Reed. @@ -6,7 +6,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_state.h 1.3 1/12/96 (C) 1995 Darren Reed - * Id: ip_state.h,v 2.68.2.5 2005/08/20 13:48:25 darrenr Exp + * Id: ip_state.h,v 2.68.2.7 2006/12/18 15:53:40 darrenr Exp */ #ifndef _NETINET_IP_STATE_H_ #define _NETINET_IP_STATE_H_ @@ -41,7 +41,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; @@ -189,6 +188,7 @@ typedef struct ipslog { #define ISL_INTERMEDIATE 0xfffc #define ISL_KILLED 0xfffb #define ISL_ORPHAN 0xfffa +#define ISL_UNLOAD 0xfff9 typedef struct ips_stat { @@ -250,12 +250,16 @@ 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((void *, ioctlcmd_t, int)); +#if __NetBSD_Version__ >= 499001000 +extern int fr_state_ioctl __P((void*, ioctlcmd_t, int, int, void *)); +#else +extern int fr_state_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *)); +#endif 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 /* _NETINET_IP_STATE_H_ */ diff --git a/sys/dist/ipf/netinet/ip_sync.c b/sys/dist/ipf/netinet/ip_sync.c index a7a77dce59d..b1e2e7c2cd1 100644 --- a/sys/dist/ipf/netinet/ip_sync.c +++ b/sys/dist/ipf/netinet/ip_sync.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_sync.c,v 1.6 2007/03/04 06:02:57 christos Exp $ */ +/* $NetBSD: ip_sync.c,v 1.7 2007/04/14 20:34:39 martin Exp $ */ /* * Copyright (C) 1995-1998 by Darren Reed. @@ -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,15 @@ 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) +#if __NetBSD_Version__ >= 499001000 void *data; +#else +caddr_t data; +#endif ioctlcmd_t cmd; -int mode; +int mode, uid; +void *ctx; { return EINVAL; } diff --git a/sys/dist/ipf/netinet/ip_sync.h b/sys/dist/ipf/netinet/ip_sync.h index 15ced7a527e..e2af83a88b7 100644 --- a/sys/dist/ipf/netinet/ip_sync.h +++ b/sys/dist/ipf/netinet/ip_sync.h @@ -1,4 +1,4 @@ -/* $NetBSD: ip_sync.h,v 1.5 2007/03/04 06:02:58 christos Exp $ */ +/* $NetBSD: ip_sync.h,v 1.6 2007/04/14 20:34:39 martin Exp $ */ /* * Copyright (C) 1993-2001 by Darren Reed. @@ -6,7 +6,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_fil.h 1.35 6/5/96 - * Id: ip_sync.h,v 2.11.2.3 2006/03/19 14:59:39 darrenr Exp + * Id: ip_sync.h,v 2.11.2.4 2006/07/14 06:12:20 darrenr Exp */ #ifndef __IP_SYNC_H__ @@ -104,16 +104,20 @@ typedef struct syncupdent { /* 28 or 32 bytes */ extern synclogent_t synclog[SYNCLOG_SZ]; -extern int fr_sync_ioctl __P((void *, ioctlcmd_t, int)); -extern synclist_t *ipfsync_new __P((int, fr_info_t *, void *)); -extern void ipfsync_del __P((synclist_t *)); -extern void ipfsync_update __P((int, fr_info_t *, synclist_t *)); -extern int ipfsync_init __P((void)); -extern int ipfsync_nat __P((synchdr_t *sp, void *data)); -extern int ipfsync_state __P((synchdr_t *sp, void *data)); -extern int ipfsync_read __P((struct uio *uio)); -extern int ipfsync_write __P((struct uio *uio)); -extern int ipfsync_canread __P((void)); -extern int ipfsync_canwrite __P((void)); +#if __NetBSD_Version__ >= 499001000 +extern int fr_sync_ioctl __P((void*, ioctlcmd_t, int, int, void *)); +#else +extern int fr_sync_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *)); +#endif +extern synclist_t *ipfsync_new __P((int, fr_info_t *, void *)); +extern void ipfsync_del __P((synclist_t *)); +extern void ipfsync_update __P((int, fr_info_t *, synclist_t *)); +extern int ipfsync_init __P((void)); +extern int ipfsync_nat __P((synchdr_t *sp, void *data)); +extern int ipfsync_state __P((synchdr_t *sp, void *data)); +extern int ipfsync_read __P((struct uio *uio)); +extern int ipfsync_write __P((struct uio *uio)); +extern int ipfsync_canread __P((void)); +extern int ipfsync_canwrite __P((void)); #endif /* IP_SYNC */ diff --git a/sys/dist/ipf/netinet/ipl.h b/sys/dist/ipf/netinet/ipl.h index 387f03ccdae..ece15a44ccf 100644 --- a/sys/dist/ipf/netinet/ipl.h +++ b/sys/dist/ipf/netinet/ipl.h @@ -1,4 +1,4 @@ -/* $NetBSD: ipl.h,v 1.6 2006/04/04 16:17:19 martti Exp $ */ +/* $NetBSD: ipl.h,v 1.7 2007/04/14 20:34:40 martin Exp $ */ /* * Copyright (C) 1993-2001, 2003 by Darren Reed. @@ -6,14 +6,14 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ipl.h 1.21 6/5/96 - * Id: ipl.h,v 2.52.2.14 2006/04/01 20:09:42 darrenr Exp + * Id: ipl.h,v 2.52.2.21 2007/02/23 15:04:53 darrenr Exp */ #ifndef __IPL_H__ #define __IPL_H__ -#define IPL_VERSION "IP Filter: v4.1.13" +#define IPL_VERSION "IP Filter: v4.1.19" -#define IPFILTER_VERSION 4011300 +#define IPFILTER_VERSION 4011900 #endif |
