[Midnightbsd-cvs] src: ipfilter/netinet: Sync ipfilter with freebsd
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Thu Sep 18 22:15:16 EDT 2008
Log Message:
-----------
Sync ipfilter with freebsd
Modified Files:
--------------
src/sys/contrib/ipfilter/netinet:
fil.c (r1.1.1.1 -> r1.2)
ip_auth.c (r1.1.1.1 -> r1.2)
ip_auth.h (r1.1.1.1 -> r1.2)
ip_compat.h (r1.1.1.1 -> r1.2)
ip_fil.h (r1.1.1.1 -> r1.2)
ip_fil_freebsd.c (r1.1.1.1 -> r1.2)
ip_frag.c (r1.1.1.1 -> r1.2)
ip_frag.h (r1.1.1.1 -> r1.2)
ip_ftp_pxy.c (r1.1.1.1 -> r1.2)
ip_htable.c (r1.1.1.1 -> r1.2)
ip_htable.h (r1.1.1.1 -> r1.2)
ip_ipsec_pxy.c (r1.1.1.1 -> r1.2)
ip_irc_pxy.c (r1.1.1.1 -> r1.2)
ip_log.c (r1.1.1.1 -> r1.2)
ip_lookup.c (r1.1.1.1 -> r1.2)
ip_lookup.h (r1.1.1.1 -> r1.2)
ip_nat.c (r1.1.1.1 -> r1.2)
ip_nat.h (r1.1.1.1 -> r1.2)
ip_netbios_pxy.c (r1.1.1.1 -> r1.2)
ip_pool.c (r1.1.1.1 -> r1.2)
ip_pool.h (r1.1.1.1 -> r1.2)
ip_pptp_pxy.c (r1.1.1.1 -> r1.2)
ip_proxy.c (r1.1.1.1 -> r1.2)
ip_proxy.h (r1.1.1.1 -> r1.2)
ip_raudio_pxy.c (r1.1.1.1 -> r1.2)
ip_rcmd_pxy.c (r1.1.1.1 -> r1.2)
ip_rpcb_pxy.c (r1.1.1.1 -> r1.2)
ip_scan.c (r1.1.1.1 -> r1.2)
ip_scan.h (r1.1.1.1 -> r1.2)
ip_state.c (r1.1.1.1 -> r1.2)
ip_state.h (r1.1.1.1 -> r1.2)
ip_sync.c (r1.1.1.1 -> r1.2)
ip_sync.h (r1.1.1.1 -> r1.2)
ipl.h (r1.1.1.1 -> r1.2)
mlfk_ipl.c (r1.1.1.1 -> r1.2)
-------------- next part --------------
Index: ipl.h
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ipl.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ipl.h -L sys/contrib/ipfilter/netinet/ipl.h -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ipl.h
+++ sys/contrib/ipfilter/netinet/ipl.h
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ipl.h,v 1.23 2005/04/25 18:43:14 darrenr Exp $ */
+/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ipl.h,v 1.26.2.1 2007/10/31 05:00:38 darrenr Exp $ */
/*
* Copyright (C) 1993-2001, 2003 by Darren Reed.
@@ -6,15 +6,15 @@
* See the IPFILTER.LICENCE file for details on licencing.
*
* @(#)ipl.h 1.21 6/5/96
- * $FreeBSD: src/sys/contrib/ipfilter/netinet/ipl.h,v 1.23 2005/04/25 18:43:14 darrenr Exp $
- * Id: ipl.h,v 2.52.2.9 2005/03/30 14:14:05 darrenr Exp
+ * $FreeBSD: src/sys/contrib/ipfilter/netinet/ipl.h,v 1.26.2.1 2007/10/31 05:00:38 darrenr Exp $
+ * Id: ipl.h,v 2.52.2.30 2007/10/16 09:41:00 darrenr Exp $
*/
#ifndef __IPL_H__
#define __IPL_H__
-#define IPL_VERSION "IP Filter: v4.1.8"
+#define IPL_VERSION "IP Filter: v4.1.28"
-#define IPFILTER_VERSION 4010800
+#define IPFILTER_VERSION 4012800
#endif
Index: ip_log.c
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_log.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_log.c -L sys/contrib/ipfilter/netinet/ip_log.c -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_log.c
+++ sys/contrib/ipfilter/netinet/ip_log.c
@@ -1,12 +1,12 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_log.c,v 1.29 2005/04/25 18:43:14 darrenr Exp $ */
+/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_log.c,v 1.33.2.1 2007/10/31 05:00:38 darrenr Exp $ */
/*
* Copyright (C) 1997-2003 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
- * $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_log.c,v 1.29 2005/04/25 18:43:14 darrenr Exp $
- * Id: ip_log.c,v 2.75.2.6 2004/10/16 07:59:27 darrenr Exp
+ * $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_log.c,v 1.33.2.1 2007/10/31 05:00:38 darrenr Exp $
+ * Id: ip_log.c,v 2.75.2.19 2007/09/09 11:32:06 darrenr Exp $
*/
#include <sys/param.h>
#if defined(KERNEL) || defined(_KERNEL)
@@ -17,7 +17,11 @@
#endif
#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \
defined(_KERNEL)
-# include "opt_ipfilter_log.h"
+# if (__NetBSD_Version__ < 399001400)
+# include "opt_ipfilter_log.h"
+# else
+# include "opt_ipfilter.h"
+# endif
#endif
#if defined(__FreeBSD__) && !defined(IPFILTER_LKM)
# if defined(_KERNEL)
@@ -62,12 +66,18 @@
# endif
#endif /* _KERNEL */
#if !SOLARIS && !defined(__hpux) && !defined(linux)
-# if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000)
+# if (defined(NetBSD) && NetBSD > 199609) || \
+ (defined(OpenBSD) && OpenBSD > 199603) || \
+ (__FreeBSD_version >= 300000)
# include <sys/dirent.h>
# else
# include <sys/dir.h>
# endif
# include <sys/mbuf.h>
+# include <sys/select.h>
+# if __FreeBSD_version >= 500000
+# include <sys/selinfo.h>
+# endif
#else
# if !defined(__hpux) && defined(_KERNEL)
# include <sys/filio.h>
@@ -146,15 +156,15 @@
# 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
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;
@@ -251,16 +261,23 @@
ipflog_t ipfl;
u_char p;
mb_t *m;
-# if (SOLARIS || defined(__hpux)) && defined(_KERNEL)
+# if (SOLARIS || defined(__hpux)) && defined(_KERNEL) && \
+ !defined(_INET_IP_STACK_H)
qif_t *ifp;
# else
struct ifnet *ifp;
# endif /* SOLARIS || __hpux */
- ipfl.fl_nattag.ipt_num[0] = 0;
m = fin->fin_m;
+ if (m == NULL)
+ return -1;
+
+ ipfl.fl_nattag.ipt_num[0] = 0;
ifp = fin->fin_ifp;
- hlen = fin->fin_hlen;
+ if (fin->fin_exthdr != NULL)
+ hlen = (char *)fin->fin_dp - (char *)fin->fin_ip;
+ else
+ hlen = fin->fin_hlen;
/*
* calculate header size.
*/
@@ -321,14 +338,16 @@
* Get the interface number and name to which this packet is
* currently associated.
*/
-# if (SOLARIS || defined(__hpux)) && defined(_KERNEL)
+# if (SOLARIS || defined(__hpux)) && defined(_KERNEL) && \
+ !defined(_INET_IP_STACK_H)
ipfl.fl_unit = (u_int)ifp->qf_ppa;
- COPYIFNAME(ifp, ipfl.fl_ifname);
+ COPYIFNAME(fin->fin_v, ifp, ipfl.fl_ifname);
# else
# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \
(defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
- (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
- COPYIFNAME(ifp, ipfl.fl_ifname);
+ (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) || \
+ (SOLARIS && defined(_INET_IP_STACK_H))
+ COPYIFNAME(fin->fin_v, ifp, ipfl.fl_ifname);
# else
ipfl.fl_unit = (u_int)ifp->if_unit;
# if defined(_KERNEL)
@@ -337,7 +356,7 @@
if ((ipfl.fl_ifname[2] = ifp->if_name[2]))
ipfl.fl_ifname[3] = ifp->if_name[3];
# else
- (void) strncpy(ipfl.fl_ifname, IFNAME(ifp), sizeof(ipfl.fl_ifname));
+ COPYIFNAME(fin->fin_v, ifp, ipfl.fl_ifname);
ipfl.fl_ifname[sizeof(ipfl.fl_ifname) - 1] = '\0';
# endif
# endif
@@ -413,13 +432,11 @@
size_t *itemsz;
int *types, cnt;
{
- caddr_t buf, ptr;
+ u_char *buf, *ptr;
iplog_t *ipl;
size_t len;
int i;
-# if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL)
- int s;
-# endif
+ SPL_INT(s);
/*
* Check to see if this log record has a CRC which matches the last
@@ -452,7 +469,7 @@
* check that we have space to record this information and can
* allocate that much.
*/
- KMALLOCS(buf, caddr_t, len);
+ KMALLOCS(buf, u_char *, len);
if (buf == NULL)
return -1;
SPL_NET(s);
@@ -491,7 +508,7 @@
if (types[i] == 0) {
bcopy(items[i], ptr, itemsz[i]);
} else if (types[i] == 1) {
- COPYDATA(items[i], 0, itemsz[i], ptr);
+ COPYDATA(items[i], 0, itemsz[i], (char *)ptr);
}
ptr += itemsz[i];
}
@@ -508,9 +525,11 @@
# if SOLARIS && defined(_KERNEL)
cv_signal(&iplwait);
MUTEX_EXIT(&ipl_mutex);
+ pollwakeup(&iplpollhead[dev], POLLRDNORM);
# else
MUTEX_EXIT(&ipl_mutex);
- WAKEUP(iplh,dev);
+ WAKEUP(iplh, dev);
+ POLLWAKEUP(dev);
# endif
SPL_X(s);
# ifdef IPL_SELECT
@@ -539,9 +558,7 @@
size_t dlen, copied;
int error = 0;
iplog_t *ipl;
-# if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL)
- int s;
-# endif
+ SPL_INT(s);
/*
* Sanity checks. Make sure the minor # is valid and we're copying
@@ -616,7 +633,7 @@
iplused[unit] -= dlen;
MUTEX_EXIT(&ipl_mutex);
SPL_X(s);
- error = UIOMOVE((caddr_t)ipl, dlen, UIO_READ, uio);
+ error = UIOMOVE(ipl, dlen, UIO_READ, uio);
if (error) {
SPL_NET(s);
MUTEX_ENTER(&ipl_mutex);
@@ -626,7 +643,7 @@
break;
}
MUTEX_ENTER(&ipl_mutex);
- KFREES((caddr_t)ipl, dlen);
+ KFREES(ipl, dlen);
SPL_NET(s);
}
if (!iplt[unit]) {
@@ -653,15 +670,13 @@
{
iplog_t *ipl;
int used;
-# if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL)
- int s;
-# endif
+ SPL_INT(s);
SPL_NET(s);
MUTEX_ENTER(&ipl_mutex);
while ((ipl = iplt[unit]) != NULL) {
iplt[unit] = ipl->ipl_next;
- KFREES((caddr_t)ipl, ipl->ipl_dsize);
+ KFREES(ipl, ipl->ipl_dsize);
}
iplh[unit] = &iplt[unit];
ipll[unit] = NULL;
@@ -672,4 +687,19 @@
SPL_X(s);
return used;
}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipflog_canread */
+/* Returns: int - 0 == no data to read, 1 = data present */
+/* Parameters: unit(I) - device we are reading from */
+/* */
+/* Returns an indication of whether or not there is data present in the */
+/* current buffer for the selected ipf device. */
+/* ------------------------------------------------------------------------ */
+int ipflog_canread(unit)
+int unit;
+{
+ return iplt[unit] != NULL;
+}
#endif /* IPFILTER_LOG */
Index: ip_compat.h
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_compat.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_compat.h -L sys/contrib/ipfilter/netinet/ip_compat.h -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_compat.h
+++ sys/contrib/ipfilter/netinet/ip_compat.h
@@ -1,13 +1,11 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_compat.h,v 1.28 2005/05/16 16:22:55 darrenr Exp $ */
-
/*
* Copyright (C) 1993-2001, 2003 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* @(#)ip_compat.h 1.8 1/14/96
- * $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_compat.h,v 1.28 2005/05/16 16:22:55 darrenr Exp $
- * Id: ip_compat.h,v 2.142.2.25 2005/03/28 09:33:36 darrenr Exp
+ * $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_compat.h,v 1.33.2.1 2007/10/31 05:00:37 darrenr Exp $
+ * Id: ip_compat.h,v 2.142.2.57 2007/10/10 09:51:42 darrenr Exp $
*/
#ifndef __IP_COMPAT_H__
@@ -37,7 +35,7 @@
#ifndef SOLARIS
#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
#endif
-#if SOLARIS2 >= 8
+#if defined(SOLARIS2) && SOLARIS2 >= 8
# ifndef USE_INET6
# define USE_INET6
# endif
@@ -142,7 +140,7 @@
# include <sys/ioccom.h>
# include <sys/sysmacros.h>
# include <sys/kmem.h>
-# if SOLARIS2 >= 10
+# if defined(SOLARIS2) && SOLARIS2 >= 10
# include <sys/procset.h>
# include <sys/proc.h>
# include <sys/devops.h>
@@ -156,7 +154,7 @@
# undef RES_INIT
# endif /* _KERNEL */
-# if SOLARIS2 >= 8
+# if defined(SOLARIS2) && SOLARIS2 >= 8
# include <netinet/ip6.h>
# include <netinet/icmp6.h>
# endif
@@ -171,13 +169,18 @@
# ifdef i386
# define _SYS_PROMIF_H
# endif
+# ifndef _KERNEL
+# include "radix_ipf.h"
+# else
+# include "radix_ipf_local.h"
+# endif
# include <inet/ip.h>
# undef COPYOUT
# include <inet/ip_ire.h>
# ifndef KERNEL
# undef _KERNEL
# endif
-# if SOLARIS2 >= 8
+# if defined(SOLARIS2) && SOLARIS2 >= 8
# define SNPRINTF snprintf
# include <inet/ip_if.h>
@@ -192,7 +195,7 @@
};
# endif /* SOLARIS2 >= 8 */
-# if SOLARIS2 >= 6
+# if defined(SOLARIS2) && SOLARIS2 >= 6
# include <sys/atomic.h>
typedef uint32_t u_32_t;
# else
@@ -203,8 +206,28 @@
# ifdef _KERNEL
# define KRWLOCK_T krwlock_t
# define KMUTEX_T kmutex_t
-# include "qif.h"
-# include "pfil.h"
+
+# if !defined(FW_HOOKS)
+# include "qif.h"
+# include "pfil.h"
+# else
+# include <sys/neti.h>
+
+extern net_data_t ipfipv4;
+extern net_data_t ipfipv6;
+
+typedef struct qpktinfo {
+ void *qpi_data;
+ mblk_t **qpi_mp;
+ mblk_t *qpi_m;
+ uintptr_t qpi_real;
+ int qpi_flags;
+ int qpi_num;
+ int qpi_off;
+} qpktinfo_t;
+# define QF_GROUP 0x01
+# endif
+
# if SOLARIS2 >= 6
# if SOLARIS2 == 6
# define ATOMIC_INCL(x) atomic_add_long((uint32_t*)&(x), 1)
@@ -241,11 +264,12 @@
# define MUTEX_EXIT(x) mutex_exit(&(x)->ipf_lk)
# define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c))
# define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c))
-# define BCOPYIN(a,b,c) (void) copyin((caddr_t)(a), (caddr_t)(b), (c))
-# define BCOPYOUT(a,b,c) (void) copyout((caddr_t)(a), (caddr_t)(b), (c))
+# define BCOPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c))
+# define BCOPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c))
# define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,c,d)
# define KFREE(x) kmem_free((char *)(x), sizeof(*(x)))
# define KFREES(x,s) kmem_free((char *)(x), (s))
+# define SPL_SCHED(x) ;
# define SPL_NET(x) ;
# define SPL_IMP(x) ;
# undef SPL_X
@@ -261,10 +285,24 @@
# define GET_MINOR(x) getminor(x)
extern void *get_unit __P((char *, int));
# define GETIFP(n, v) get_unit(n, v)
-# define IFNAME(x) ((qif_t *)x)->qf_name
-# define COPYIFNAME(x, b) \
+# if defined(_INET_IP_STACK_H)
+# define COPYIFNAME(v, x, b) \
+ do { \
+ if ((v) == 4) { \
+ (void) net_getifname(ipfipv4,\
+ (uintptr_t)x, b, \
+ LIFNAMSIZ); \
+ } else { \
+ (void) net_getifname(ipfipv6,\
+ (uintptr_t)x, b, \
+ LIFNAMSIZ); \
+ } \
+ } while (0)
+# else
+# define COPYIFNAME(v, x, b) \
(void) strncpy(b, ((qif_t *)x)->qf_name, \
LIFNAMSIZ)
+# endif
# define GETKTIME(x) uniqtime((struct timeval *)x)
# define MSGDSIZE(x) msgdsize(x)
# define M_LEN(x) ((x)->b_wptr - (x)->b_rptr)
@@ -273,12 +311,16 @@
# define MTYPE(m) ((m)->b_datap->db_type)
# define FREE_MB_T(m) freemsg(m)
# define m_next b_cont
-# define CACHE_HASH(x) (((qpktinfo_t *)(x)->fin_qpi)->qpi_num & 7)
+# if !defined(_INET_IP_STACK_H)
+# define CACHE_HASH(x) (((qpktinfo_t *)(x)->fin_qpi)->qpi_num & 7)
+# else
+# define CACHE_HASH(x) ((uintptr_t)(x)->fin_ifp & 7)
+# endif
# define IPF_PANIC(x,y) if (x) { printf y; cmn_err(CE_PANIC, "ipf_panic"); }
typedef mblk_t mb_t;
# endif /* _KERNEL */
-# if (SOLARIS2 >= 7)
+# if defined(SOLARIS2) && (SOLARIS2 >= 7)
# ifdef lint
# define ALIGN32(ptr) (ptr ? 0L : 0L)
# define ALIGN16(ptr) (ptr ? 0L : 0L)
@@ -288,7 +330,7 @@
# endif
# endif
-# if SOLARIS2 < 6
+# if defined(SOLARIS2) && SOLARIS2 < 6
typedef struct uio uio_t;
# endif
typedef int ioctlcmd_t;
@@ -418,21 +460,14 @@
# define RW_DESTROY(x)
# define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c))
# define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c))
-# if HPUXREV >= 1111
-# define BCOPYIN(a,b,c) 0; bcopy((caddr_t)(a), (caddr_t)(b), (c))
-# define BCOPYOUT(a,b,c) 0; bcopy((caddr_t)(a), (caddr_t)(b), (c))
-# else
-# define BCOPYIN(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c))
-# define BCOPYOUT(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c))
-# endif
+# define SPL_SCHED(x) ;
# define SPL_NET(x) ;
# define SPL_IMP(x) ;
# undef SPL_X
# define SPL_X(x) ;
extern void *get_unit __P((char *, int));
# define GETIFP(n, v) get_unit(n, v)
-# define IFNAME(x, b) ((ill_t *)x)->ill_name
-# define COPYIFNAME(x, b) \
+# define COPYIFNAME(v, x, b) \
(void) strncpy(b, ((qif_t *)x)->qf_name, \
LIFNAMSIZ)
# define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,c,d)
@@ -444,6 +479,7 @@
wakeup(id + x); \
spinunlock(_l); \
}
+# define POLLWAKEUP(x) ;
# define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), M_IOSYS, M_NOWAIT)
# define KMALLOCS(a, b, c) MALLOC((a), b, (c), M_IOSYS, M_NOWAIT)
# define KFREE(x) kmem_free((char *)(x), sizeof(*(x)))
@@ -576,11 +612,10 @@
# define MTOD(m,t) mtod(m,t)
# define COPYIN(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0)
# define COPYOUT(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0)
-# define BCOPYIN(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0)
-# define BCOPYOUT(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0)
# define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,c,d)
# define SLEEP(id, n) sleep((id), PZERO+1)
# define WAKEUP(id,x) wakeup(id+x)
+# define POLLWAKEUP(x) ;
# define KFREE(x) kmem_free((char *)(x), sizeof(*(x)))
# define KFREES(x,s) kmem_free((char *)(x), (s))
# define GETIFP(n,v) ifunit(n)
@@ -592,6 +627,7 @@
# define USE_SPL 1
# define SPL_IMP(x) (x) = splimp()
# define SPL_NET(x) (x) = splnet()
+# define SPL_SCHED(x) (x) = splsched()
# define SPL_X(x) (void) splx(x)
extern void m_copydata __P((struct mbuf *, int, int, caddr_t));
extern void m_copyback __P((struct mbuf *, int, int, caddr_t));
@@ -599,6 +635,7 @@
# 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 IFNAME(x) ((struct ifnet *)x)->if_name
# define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \
((struct ifnet *)fin->fin_ifp)->if_unit) & 7)
# define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); }
@@ -652,6 +689,7 @@
simple_unlock(&ipf_rw); }
# define ATOMIC_DEC(x) { simple_lock(&ipf_rw); (x)--; \
simple_unlock(&ipf_rw); }
+# define SPL_SCHED(x) ;
# define SPL_NET(x) ;
# define SPL_IMP(x) ;
# undef SPL_X
@@ -662,10 +700,9 @@
# define GETIFP(n, v) ifunit(n)
# define GET_MINOR getminor
# define WAKEUP(id,x) wakeup(id + x)
+# define POLLWAKEUP(x) ;
# define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c))
# define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c))
-# define BCOPYIN(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c))
-# define BCOPYOUT(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c))
# define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), M_PFILT, M_NOWAIT)
# define KMALLOCS(a, b, c) MALLOC((a), b, (c), M_PFILT, \
((c) > 4096) ? M_WAITOK : M_NOWAIT)
@@ -675,6 +712,7 @@
# 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 IFNAME(x) ((struct ifnet *)x)->if_name
# define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \
((struct ifnet *)fin->fin_ifp)->if_unit) & 7)
# define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); }
@@ -718,6 +756,14 @@
/* N E T B S D */
/* ----------------------------------------------------------------------- */
#ifdef __NetBSD__
+# if (NetBSD >= 199905) && !defined(IPFILTER_LKM) && defined(_KERNEL)
+# include "opt_ipfilter.h"
+# endif
+# if defined(_KERNEL)
+# include <sys/systm.h>
+# else
+# include <stddef.h>
+# endif
# if defined(_KERNEL) && !defined(IPFILTER_LKM)
# include "bpfilter.h"
# if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 104110000)
@@ -731,7 +777,14 @@
# endif
# endif
+# if (__NetBSD_Version__ >= 499000000)
+typedef char * caddr_t;
+# endif
+
# ifdef _KERNEL
+# if (__NetBSD_Version__ >= 399001400)
+# define KMALLOCS(a, b, c) (a) = (b)malloc((c), _M_IPF, M_NOWAIT)
+# endif
# define MSGDSIZE(x) mbufchainlen(x)
# define M_LEN(x) (x)->m_len
# define M_DUPLICATE(x) m_copy((x), 0, M_COPYALL)
@@ -739,22 +792,20 @@
# define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); }
# define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c))
# define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c))
-# define BCOPYIN(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c))
-# define BCOPYOUT(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c))
typedef struct mbuf mb_t;
# endif /* _KERNEL */
# if (NetBSD <= 1991011) && (NetBSD >= 199606)
# define IFNAME(x) ((struct ifnet *)x)->if_xname
-# define COPYIFNAME(x, b) \
+# define COPYIFNAME(v, x, b) \
(void) strncpy(b, \
((struct ifnet *)x)->if_xname, \
LIFNAMSIZ)
# define CACHE_HASH(x) ((((struct ifnet *)fin->fin_ifp)->if_index)&7)
# else
+# define IFNAME(x) ((struct ifnet *)x)->if_name
# 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,8 +847,6 @@
# endif
# define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c))
# define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c))
-# define BCOPYIN(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c))
-# define BCOPYOUT(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c))
# if (__FreeBSD_version >= 500043)
# define NETBSD_PF
@@ -806,24 +855,66 @@
# if (__FreeBSD_version >= 500043)
# include <sys/mutex.h>
-# include <sys/sx.h>
+# if (__FreeBSD_version > 700014)
+# include <sys/rwlock.h>
+# define KRWLOCK_T struct rwlock
+# ifdef _KERNEL
+# define READ_ENTER(x) rw_rlock(&(x)->ipf_lk)
+# define WRITE_ENTER(x) rw_wlock(&(x)->ipf_lk)
+# define MUTEX_DOWNGRADE(x) rw_downgrade(&(x)->ipf_lk)
+# define RWLOCK_INIT(x, y) rw_init(&(x)->ipf_lk, (y))
+# define RW_DESTROY(x) rw_destroy(&(x)->ipf_lk)
+# define RWLOCK_EXIT(x) do { \
+ if (rw_wowned(&(x)->ipf_lk)) \
+ rw_wunlock(&(x)->ipf_lk); \
+ else \
+ rw_runlock(&(x)->ipf_lk); \
+ } while (0)
+# endif
+# else
+# include <sys/sx.h>
/*
* Whilst the sx(9) locks on FreeBSD have the right semantics and interface
* for what we want to use them for, despite testing showing they work -
* with a WITNESS kernel, it generates LOR messages.
*/
-# define KMUTEX_T struct mtx
-# if 1
-# define KRWLOCK_T struct mtx
-# else
-# define KRWLOCK_T struct sx
+# ifdef _KERNEL
+# if (__FreeBSD_version < 700000)
+# define KRWLOCK_T struct mtx
+# define READ_ENTER(x) mtx_lock(&(x)->ipf_lk)
+# define WRITE_ENTER(x) mtx_lock(&(x)->ipf_lk)
+# define RWLOCK_EXIT(x) mtx_unlock(&(x)->ipf_lk)
+# define MUTEX_DOWNGRADE(x) ;
+# define RWLOCK_INIT(x,y) mtx_init(&(x)->ipf_lk, (y), NULL,\
+ MTX_DEF)
+# define RW_DESTROY(x) mtx_destroy(&(x)->ipf_lk)
+# else
+# define KRWLOCK_T struct sx
+# define READ_ENTER(x) sx_slock(&(x)->ipf_lk)
+# define WRITE_ENTER(x) sx_xlock(&(x)->ipf_lk)
+# define MUTEX_DOWNGRADE(x) sx_downgrade(&(x)->ipf_lk)
+# define RWLOCK_INIT(x, y) sx_init(&(x)->ipf_lk, (y))
+# define RW_DESTROY(x) sx_destroy(&(x)->ipf_lk)
+# ifdef sx_unlock
+# define RWLOCK_EXIT(x) sx_unlock(&(x)->ipf_lk)
+# else
+# define RWLOCK_EXIT(x) do { \
+ if ((x)->ipf_lk.sx_cnt < 0) \
+ sx_xunlock(&(x)->ipf_lk); \
+ else \
+ sx_sunlock(&(x)->ipf_lk); \
+ } while (0)
+# endif
+# endif
+# endif
# endif
+# define KMUTEX_T struct mtx
# endif
# if (__FreeBSD_version >= 501113)
# include <net/if_var.h>
# define IFNAME(x) ((struct ifnet *)x)->if_xname
-# define COPYIFNAME(x, b) \
+# define COPYIFNAME(v, x, b) \
(void) strncpy(b, \
((struct ifnet *)x)->if_xname, \
LIFNAMSIZ)
@@ -831,6 +922,7 @@
# if (__FreeBSD_version >= 500043)
# define CACHE_HASH(x) ((((struct ifnet *)fin->fin_ifp)->if_index) & 7)
# else
+# define IFNAME(x) ((struct ifnet *)x)->if_name
# define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \
((struct ifnet *)fin->fin_ifp)->if_unit) & 7)
# endif
@@ -852,36 +944,6 @@
MTX_DEF)
# define MUTEX_DESTROY(x) mtx_destroy(&(x)->ipf_lk)
# define MUTEX_NUKE(x) bzero((x), sizeof(*(x)))
-/*
- * Whilst the sx(9) locks on FreeBSD have the right semantics and interface
- * for what we want to use them for, despite testing showing they work -
- * with a WITNESS kernel, it generates LOR messages.
- */
-# if 1
-# define READ_ENTER(x) mtx_lock(&(x)->ipf_lk)
-# define WRITE_ENTER(x) mtx_lock(&(x)->ipf_lk)
-# define RWLOCK_EXIT(x) mtx_unlock(&(x)->ipf_lk)
-# define MUTEX_DOWNGRADE(x) ;
-# define RWLOCK_INIT(x,y) mtx_init(&(x)->ipf_lk, (y), NULL,\
- MTX_DEF)
-# define RW_DESTROY(x) mtx_destroy(&(x)->ipf_lk)
-# else
-# define READ_ENTER(x) sx_slock(&(x)->ipf_lk)
-# define WRITE_ENTER(x) sx_xlock(&(x)->ipf_lk)
-# define MUTEX_DOWNGRADE(x) sx_downgrade(&(x)->ipf_lk)
-# define RWLOCK_INIT(x, y) sx_init(&(x)->ipf_lk, (y))
-# define RW_DESTROY(x) sx_destroy(&(x)->ipf_lk)
-# ifdef sx_unlock
-# define RWLOCK_EXIT(x) sx_unlock(x)
-# else
-# define RWLOCK_EXIT(x) do { \
- if ((x)->ipf_lk.sx_cnt < 0) \
- sx_xunlock(&(x)->ipf_lk); \
- else \
- sx_sunlock(&(x)->ipf_lk); \
- } while (0)
-# endif
-# endif
# include <machine/atomic.h>
# define ATOMIC_INC(x) { mtx_lock(&ipf_rw.ipf_lk); (x)++; \
mtx_unlock(&ipf_rw.ipf_lk); }
@@ -889,16 +951,19 @@
mtx_unlock(&ipf_rw.ipf_lk); }
# define ATOMIC_INCL(x) atomic_add_long(&(x), 1)
# define ATOMIC_INC64(x) ATOMIC_INC(x)
-# define ATOMIC_INC32(x) atomic_add_32(&(x), 1)
+# define ATOMIC_INC32(x) atomic_add_32((u_int *)&(x), 1)
# define ATOMIC_INC16(x) atomic_add_16(&(x), 1)
# define ATOMIC_DECL(x) atomic_add_long(&(x), -1)
# define ATOMIC_DEC64(x) ATOMIC_DEC(x)
-# define ATOMIC_DEC32(x) atomic_add_32(&(x), -1)
+# define ATOMIC_DEC32(x) atomic_add_32((u_int *)&(x), -1)
# define ATOMIC_DEC16(x) atomic_add_16(&(x), -1)
# define SPL_X(x) ;
# define SPL_NET(x) ;
# define SPL_IMP(x) ;
+# define SPL_SCHED(x) ;
extern int in_cksum __P((struct mbuf *, int));
+# else
+# define SPL_SCHED(x) x = splhigh()
# endif /* __FreeBSD_version >= 500043 */
# define MSGDSIZE(x) mbufchainlen(x)
# define M_LEN(x) (x)->m_len
@@ -955,8 +1020,6 @@
# endif
# define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c))
# define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c))
-# define BCOPYIN(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c))
-# define BCOPYOUT(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c))
# define GETKTIME(x) microtime((struct timeval *)x)
# define MSGDSIZE(x) mbufchainlen(x)
# define M_LEN(x) (x)->m_len
@@ -966,12 +1029,13 @@
# endif /* _KERNEL */
# if (OpenBSD >= 199603)
# define IFNAME(x, b) ((struct ifnet *)x)->if_xname
-# define COPYIFNAME(x, b) \
+# define COPYIFNAME(v, x, b) \
(void) strncpy(b, \
((struct ifnet *)x)->if_xname, \
LIFNAMSIZ)
# define CACHE_HASH(x) ((((struct ifnet *)fin->fin_ifp)->if_index)&7)
# else
+# define IFNAME(x, b) ((struct ifnet *)x)->if_name
# define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \
((struct ifnet *)fin->fin_ifp)->if_unit) & 7)
# endif
@@ -999,6 +1063,7 @@
# define MSGDSIZE(x) mbufchainlen(x)
# define M_LEN(x) (x)->m_len
# define M_DUPLICATE(x) m_copy((x), 0, M_COPYALL)
+# define IFNAME(x, b) ((struct ifnet *)x)->if_name
# define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \
((struct ifnet *)fin->fin_ifp)->if_unit) & 7)
typedef struct mbuf mb_t;
@@ -1025,6 +1090,7 @@
# define MSGDSIZE(x) mbufchainlen(x)
# define M_LEN(x) (x)->m_len
# define M_DUPLICATE(x) m_copy((x), 0, M_COPYALL)
+# define IFNAME(x, b) ((struct ifnet *)x)->if_name
# define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \
((struct ifnet *)fin->fin_ifp)->if_unit) & 7)
# define GETIFP(n, v) ifunit(n, IFNAMSIZ)
@@ -1032,6 +1098,7 @@
# define KFREES(x,s) kmem_free((char *)(x), (s))
# define SLEEP(id, n) sleep((id), PZERO+1)
# define WAKEUP(id,x) wakeup(id + x)
+# define POLLWAKEUP(x) ;
# define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,c,d)
# define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); }
@@ -1057,7 +1124,7 @@
#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
@@ -1070,15 +1137,18 @@
# ifdef _KERNEL
# define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); }
-# define BCOPYIN(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c))
-# define BCOPYOUT(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c))
# define COPYIN(a,b,c) copy_from_user((caddr_t)(b), (caddr_t)(a), (c))
# define COPYOUT(a,b,c) copy_to_user((caddr_t)(b), (caddr_t)(a), (c))
# define FREE_MB_T(m) kfree_skb(m)
# define GETKTIME(x) do_gettimeofday((struct timeval *)x)
-# define SLEEP(x,s) 0, interruptible_sleep_on(x##_linux)
-# define WAKEUP(x,y) wake_up(x##_linux + y)
-# define UIOMOVE(a,b,c,d) uiomove(a,b,c,d)
+# define POLLWAKEUP(x) ;
+# ifdef wait_event_interruptible
+# define SLEEP(x,s) wait_event_interruptible((*(x##_linux)), 0)
+# else
+# define SLEEP(x,s) 0, interruptible_sleep_on(x##_linux)
+# endif
+# define WAKEUP(x,y) wake_up(x##_linux + y)
+# define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,c,d)
# define USE_MUTEXES
# define KRWLOCK_T rwlock_t
# define KMUTEX_T spinlock_t
@@ -1089,7 +1159,7 @@
# 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)
@@ -1109,6 +1179,7 @@
MUTEX_EXIT(&ipf_rw)
# define ATOMIC_DEC16(x) MUTEX_ENTER(&ipf_rw); (x)--; \
MUTEX_EXIT(&ipf_rw)
+# define SPL_SCHED(x) do { } while (0)
# define SPL_IMP(x) do { } while (0)
# define SPL_NET(x) do { } while (0)
# define SPL_X(x) do { } while (0)
@@ -1123,6 +1194,7 @@
# define mbuf sk_buff
# define mtod(m, t) ((t)(m)->data)
+# define m_data data
# define m_len len
# define m_next next
# define M_DUPLICATE(m) skb_clone((m), in_interrupt() ? GFP_ATOMIC : \
@@ -1170,7 +1242,7 @@
# endif /* _KERNEL */
-# define COPYIFNAME(x, b) \
+# define COPYIFNAME(v, x, b) \
(void) strncpy(b, \
((struct ifnet *)x)->if_xname, \
LIFNAMSIZ)
@@ -1207,6 +1279,116 @@
#endif
+/* ----------------------------------------------------------------------- */
+/* A I X */
+/* ----------------------------------------------------------------------- */
+#if defined(_AIX51)
+# undef MENTAT
+
+# include <sys/lock.h>
+# include <sys/sysmacros.h>
+
+# ifdef _KERNEL
+# define rw_read_locked(x) 0
+# include <net/net_globals.h>
+# include <net/net_malloc.h>
+# define KMUTEX_T simple_lock_t
+# define KRWLOCK_T complex_lock_t
+# define USE_MUTEXES 1
+# define USE_SPL 1
+# define READ_ENTER(x) lock_read((x)->ipf_lk)
+# define WRITE_ENTER(x) lock_write((x)->ipf_lk)
+# define MUTEX_DOWNGRADE(x) lock_write_to_read((x)->ipf_lk)
+# define RWLOCK_INIT(x, y) lock_alloc(&(x)->ipf_lk, \
+ LOCK_ALLOC_PIN, \
+ (u_short)y, 0); \
+ lock_init((x)->ipf_lk, TRUE)
+# define RWLOCK_EXIT(x) lock_done((x)->ipf_lk)
+# define RW_DESTROY(x) lock_free(&(x)->ipf_lk)
+# define MUTEX_ENTER(x) simple_lock((x)->ipf_lk)
+# define MUTEX_INIT(x, y) lock_alloc(&(x)->ipf_lk, \
+ LOCK_ALLOC_PIN, \
+ (u_short)y, 0); \
+ simple_lock_init((x)->ipf_lk)
+# define MUTEX_DESTROY(x) lock_free(&(x)->ipf_lk)
+# define MUTEX_EXIT(x) simple_unlock((x)->ipf_lk)
+# define MUTEX_NUKE(x) bzero(&(x)->ipf_lk, sizeof((x)->ipf_lk))
+# define ATOMIC_INC64(x) { MUTEX_ENTER(&ipf_rw); (x)++; \
+ MUTEX_EXIT(&ipf_rw); }
+# define ATOMIC_DEC64(x) { MUTEX_ENTER(&ipf_rw); (x)--; \
+ MUTEX_EXIT(&ipf_rw); }
+# define ATOMIC_INC32(x) { MUTEX_ENTER(&ipf_rw); (x)++; \
+ MUTEX_EXIT(&ipf_rw); }
+# define ATOMIC_DEC32(x) { MUTEX_ENTER(&ipf_rw); (x)--; \
+ MUTEX_EXIT(&ipf_rw); }
+# define ATOMIC_INCL(x) { MUTEX_ENTER(&ipf_rw); (x)++; \
+ MUTEX_EXIT(&ipf_rw); }
+# define ATOMIC_DECL(x) { MUTEX_ENTER(&ipf_rw); (x)--; \
+ MUTEX_EXIT(&ipf_rw); }
+# define ATOMIC_INC(x) { MUTEX_ENTER(&ipf_rw); (x)++; \
+ MUTEX_EXIT(&ipf_rw); }
+# define ATOMIC_DEC(x) { MUTEX_ENTER(&ipf_rw); (x)--; \
+ MUTEX_EXIT(&ipf_rw); }
+# define SPL_SCHED(x) x = splsched()
+# define SPL_NET(x) x = splnet()
+# define SPL_IMP(x) x = splimp()
+# undef SPL_X
+# define SPL_X(x) splx(x)
+# define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,c,d)
+extern void* getifp __P((char *, int));
+# define GETIFP(n, v) getifp(n, v)
+# define GET_MINOR minor
+# define SLEEP(id, n) sleepx((id), PZERO+1, 0)
+# define WAKEUP(id,x) wakeup(id)
+# define POLLWAKEUP(x) ;
+# define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c))
+# define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c))
+# define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), M_TEMP, M_NOWAIT)
+# define KMALLOCS(a, b, c) MALLOC((a), b, (c), M_TEMP, \
+ ((c) > 4096) ? M_WAITOK : M_NOWAIT)
+# define KFREE(x) FREE((x), M_TEMP)
+# define KFREES(x,s) FREE((x), M_TEMP)
+# define MSGDSIZE(x) mbufchainlen(x)
+# define M_LEN(x) (x)->m_len
+# define M_DUPLICATE(x) m_copy((x), 0, M_COPYALL)
+# define GETKTIME(x)
+# define IFNAME(x, b) ((struct ifnet *)x)->if_name
+# define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \
+ ((struct ifnet *)fin->fin_ifp)->if_unit) & 7)
+# define IPF_PANIC(x,y)
+typedef struct mbuf mb_t;
+# endif /* _KERNEL */
+
+/*
+ * These are from's Solaris' #defines for little endian.
+ */
+#if !defined(IP6F_MORE_FRAG)
+# define IP6F_MORE_FRAG 0x0100
+#endif
+#if !defined(IP6F_RESERVED_MASK)
+# define IP6F_RESERVED_MASK 0x0600
+#endif
+#if !defined(IP6F_OFF_MASK)
+# define IP6F_OFF_MASK 0xf8ff
+#endif
+
+struct ip6_ext {
+ u_char ip6e_nxt;
+ u_char ip6e_len;
+};
+
+typedef int ioctlcmd_t;
+typedef int minor_t;
+/*
+ * Really, any arch where sizeof(long) != sizeof(int).
+ */
+typedef unsigned int u_32_t;
+# define U_32_T 1
+
+# define OS_RECOGNISED 1
+#endif /* _AIX51 */
+
+
#ifndef OS_RECOGNISED
#error ip_compat.h does not recognise this platform/OS.
#endif
@@ -1222,8 +1404,11 @@
* For BSD kernels, if bpf is in the kernel, enable ipfilter to use bpf in
* filter rules.
*/
-#if !defined(IPFILTER_BPF) && ((NBPF > 0) || (NBPFILTER > 0) || (DEV_BPF >0))
-# define IPFILTER_BPF
+#if !defined(IPFILTER_BPF)
+# if (defined(NBPF) && (NBPF > 0)) || (defined(DEV_BPF) && (DEV_BPF > 0)) || \
+ (defined(NBPFILTER) && (NBPFILTER > 0))
+# define IPFILTER_BPF
+# endif
#endif
/*
@@ -1235,7 +1420,7 @@
u_int eMm_magic;
int eMm_held;
int eMm_heldat;
-#ifdef __hpux
+#if defined(__hpux) || defined(__linux)
char eMm_fill[8];
#endif
} eMmutex_t;
@@ -1291,10 +1476,11 @@
#endif
#if defined(linux) && defined(_KERNEL)
-extern INLINE void ipf_read_enter __P((ipfrwlock_t *));
-extern INLINE void ipf_write_enter __P((ipfrwlock_t *));
-extern INLINE void ipf_rw_exit __P((ipfrwlock_t *));
-extern INLINE void ipf_rw_downgrade __P((ipfrwlock_t *));
+extern void ipf_read_enter __P((ipfrwlock_t *));
+extern void ipf_write_enter __P((ipfrwlock_t *));
+extern void ipf_rw_exit __P((ipfrwlock_t *));
+extern void ipf_rw_init __P((ipfrwlock_t *, char *));
+extern void ipf_rw_downgrade __P((ipfrwlock_t *));
#endif
/*
@@ -1314,12 +1500,15 @@
# define M_LEN(x) (x)->mb_len
# define M_DUPLICATE(x) (x)
# define GETKTIME(x) gettimeofday((struct timeval *)(x), NULL)
+# undef MTOD
# define MTOD(m, t) ((t)(m)->mb_buf)
# define FREE_MB_T(x)
# define SLEEP(x,y) 1;
# define WAKEUP(x,y) ;
+# define POLLWAKEUP(y) ;
# define IPF_PANIC(x,y) ;
# define PANIC(x,y) ;
+# define SPL_SCHED(x) ;
# define SPL_NET(x) ;
# define SPL_IMP(x) ;
# define SPL_X(x) ;
@@ -1328,18 +1517,17 @@
# define KFREE(x) free(x)
# define KFREES(x,s) free(x)
# define GETIFP(x, v) get_unit(x,v)
-# define COPYIN(a,b,c) (bcopy((a), (b), (c)), 0)
-# define COPYOUT(a,b,c) (bcopy((a), (b), (c)), 0)
-# define BCOPYIN(a,b,c) (bcopy((a), (b), (c)), 0)
-# define BCOPYOUT(a,b,c) (bcopy((a), (b), (c)), 0)
+# define COPYIN(a,b,c) bcopywrap((a), (b), (c))
+# define COPYOUT(a,b,c) bcopywrap((a), (b), (c))
# define COPYDATA(m, o, l, b) bcopy(MTOD((mb_t *)m, char *) + (o), \
(b), (l))
# define COPYBACK(m, o, l, b) bcopy((b), \
MTOD((mb_t *)m, char *) + (o), \
(l))
-# define UIOMOVE(a,b,c,d) ipfuiomove(a,b,c,d)
+# define UIOMOVE(a,b,c,d) ipfuiomove((caddr_t)a,b,c,d)
extern void m_copydata __P((mb_t *, int, int, caddr_t));
extern int ipfuiomove __P((caddr_t, int, int, struct uio *));
+extern int bcopywrap __P((void *, void *, size_t));
# ifndef CACHE_HASH
# define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \
((struct ifnet *)fin->fin_ifp)->if_unit) & 7)
@@ -1461,12 +1649,15 @@
# endif /* M_PFIL */
# endif /* IPFILTER_M_IPFILTER */
# define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), _M_IPF, M_NOWAIT)
-# define KMALLOCS(a, b, c) MALLOC((a), b, (c), _M_IPF, M_NOWAIT)
+# if !defined(KMALLOCS)
+# define KMALLOCS(a, b, c) MALLOC((a), b, (c), _M_IPF, M_NOWAIT)
+# endif
# define KFREE(x) FREE((x), _M_IPF)
# define KFREES(x,s) FREE((x), _M_IPF)
-# define UIOMOVE(a,b,c,d) uiomove(a,b,d)
+# define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,d)
# define SLEEP(id, n) tsleep((id), PPAUSE|PCATCH, n, 0)
# define WAKEUP(id,x) wakeup(id+x)
+# define POLLWAKEUP(x) selwakeup(ipfselwait+x)
# define GETIFP(n, v) ifunit(n)
# endif /* (Free)BSD */
@@ -1478,6 +1669,9 @@
# define SPL_IMP(x) x = splimp()
# define SPL_NET(x) x = splnet()
# endif /* NetBSD && (NetBSD <= 1991011) && (NetBSD >= 199407) */
+# if !defined(SPL_SCHED)
+# define SPL_SCHED(x) x = splsched()
+# endif
# define SPL_X(x) (void) splx(x)
# endif /* !USE_MUTEXES */
@@ -1492,8 +1686,6 @@
# ifndef COPYIN
# define COPYIN(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0)
# define COPYOUT(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0)
-# define BCOPYIN(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0)
-# define BCOPYOUT(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0)
# endif
# ifndef KMALLOC
@@ -1508,18 +1700,27 @@
# define PANIC(x,y) if (x) panic y
#endif /* _KERNEL */
-#ifndef IFNAME
+#if !defined(IFNAME) && !defined(_KERNEL)
# define IFNAME(x) ((struct ifnet *)x)->if_name
#endif
#ifndef COPYIFNAME
# define NEED_FRGETIFNAME
extern char *fr_getifname __P((struct ifnet *, char *));
-# define COPYIFNAME(x, b) \
+# define COPYIFNAME(v, x, b) \
fr_getifname((struct ifnet *)x, b)
#endif
#ifndef ASSERT
-# define ASSERT(x)
+# ifdef _KERNEL
+# define ASSERT(x)
+# else
+# define ASSERT(x) do { if (!(x)) abort(); } while (0)
+# endif
+#endif
+
+#ifndef BCOPYIN
+# define BCOPYIN(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0)
+# define BCOPYOUT(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0)
#endif
/*
@@ -1564,6 +1765,12 @@
# define ATOMIC_DEC(x) (x)--
#endif
+#if defined(USE_SPL) && defined(_KERNEL)
+# define SPL_INT(x) int x
+#else
+# define SPL_INT(x)
+#endif
+
/*
* If there are no atomic operations for bit sizes defined, define them to all
* use a generic one that works for all sizes.
@@ -1592,9 +1799,6 @@
# define FR_GROUPLEN 16
#endif
-#ifdef offsetof
-# undef offsetof
-#endif
#ifndef offsetof
# define offsetof(t,m) (int)((&((t *)0L)->m))
#endif
@@ -1614,7 +1818,7 @@
# define IP_HL(x) (x)->ip_hl
#endif
#ifndef IP_HL_A
-# define IP_HL_A(x,y) (x)->ip_hl = (y)
+# define IP_HL_A(x,y) (x)->ip_hl = ((y) & 0xf)
#endif
#ifndef TCP_X2
# define TCP_X2(x) (x)->th_x2
@@ -2038,9 +2242,10 @@
#ifndef IPPROTO_DSTOPTS
# define IPPROTO_DSTOPTS 60
#endif
-#ifndef IPPROTO_FRAGMENT
-# define IPPROTO_FRAGMENT 44
+#ifndef IPPROTO_MOBILITY
+# define IPPROTO_MOBILITY 135
#endif
+
#ifndef ICMP_ROUTERADVERT
# define ICMP_ROUTERADVERT 9
#endif
@@ -2221,21 +2426,21 @@
/*
* TCP States
*/
-#define IPF_TCPS_CLOSED 0 /* closed */
-#define IPF_TCPS_LISTEN 1 /* listening for connection */
-#define IPF_TCPS_SYN_SENT 2 /* active, have sent syn */
-#define IPF_TCPS_SYN_RECEIVED 3 /* have send and received syn */
-#define IPF_TCPS_HALF_ESTAB 4 /* for connections not fully "up" */
+#define IPF_TCPS_LISTEN 0 /* listening for connection */
+#define IPF_TCPS_SYN_SENT 1 /* active, have sent syn */
+#define IPF_TCPS_SYN_RECEIVED 2 /* have send and received syn */
+#define IPF_TCPS_HALF_ESTAB 3 /* for connections not fully "up" */
/* states < IPF_TCPS_ESTABLISHED are those where connections not established */
-#define IPF_TCPS_ESTABLISHED 5 /* established */
-#define IPF_TCPS_CLOSE_WAIT 6 /* rcvd fin, waiting for close */
+#define IPF_TCPS_ESTABLISHED 4 /* established */
+#define IPF_TCPS_CLOSE_WAIT 5 /* rcvd fin, waiting for close */
/* states > IPF_TCPS_CLOSE_WAIT are those where user has closed */
-#define IPF_TCPS_FIN_WAIT_1 7 /* have closed, sent fin */
-#define IPF_TCPS_CLOSING 8 /* closed xchd FIN; await FIN ACK */
-#define IPF_TCPS_LAST_ACK 9 /* had fin and close; await FIN ACK */
+#define IPF_TCPS_FIN_WAIT_1 6 /* have closed, sent fin */
+#define IPF_TCPS_CLOSING 7 /* closed xchd FIN; await FIN ACK */
+#define IPF_TCPS_LAST_ACK 8 /* had fin and close; await FIN ACK */
/* states > IPF_TCPS_CLOSE_WAIT && < IPF_TCPS_FIN_WAIT_2 await ACK of FIN */
-#define IPF_TCPS_FIN_WAIT_2 10 /* have closed, fin is acked */
-#define IPF_TCPS_TIME_WAIT 11 /* in 2*msl quiet wait after close */
+#define IPF_TCPS_FIN_WAIT_2 9 /* have closed, fin is acked */
+#define IPF_TCPS_TIME_WAIT 10 /* in 2*msl quiet wait after close */
+#define IPF_TCPS_CLOSED 11 /* closed */
#define IPF_TCP_NSTATES 12
#define TCP_MSL 120
@@ -2274,7 +2479,7 @@
/*
* ICMP error replies have an IP header (20 bytes), 8 bytes of ICMP data,
* another IP header and then 64 bits of data, totalling 56. Of course,
- * the last 64 bits is dependant on that being available.
+ * the last 64 bits is dependent on that being available.
*/
#define ICMPERR_ICMPHLEN 8
#define ICMPERR_IPICMPHLEN (20 + 8)
Index: fil.c
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/fil.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/fil.c -L sys/contrib/ipfilter/netinet/fil.c -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/fil.c
+++ sys/contrib/ipfilter/netinet/fil.c
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/fil.c,v 1.46 2005/06/23 14:19:02 darrenr Exp $ */
+/* $FreeBSD: src/sys/contrib/ipfilter/netinet/fil.c,v 1.52.2.2 2007/12/01 00:53:41 darrenr 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_log.h"
+# if (__NetBSD_Version__ < 301000000)
+# include "opt_ipfilter_log.h"
+# else
+# include "opt_ipfilter.h"
+# endif
# endif
#endif
#if defined(_KERNEL) && defined(__FreeBSD_version) && \
@@ -34,7 +38,12 @@
#else
# include <sys/ioctl.h>
#endif
-#include <sys/fcntl.h>
+#if (defined(__SVR4) || defined(__svr4__)) && defined(sun)
+# include <sys/filio.h>
+#endif
+#if !defined(_AIX51)
+# include <sys/fcntl.h>
+#endif
#if defined(_KERNEL)
# include <sys/systm.h>
# include <sys/file.h>
@@ -73,10 +82,17 @@
#ifdef sun
# include <net/af.h>
#endif
-#if !defined(_KERNEL) && defined(__FreeBSD__)
+#if !defined(_KERNEL) && (defined(__FreeBSD__) || defined(SOLARIS2))
+# if (__FreeBSD_version >= 504000)
+# undef _RADIX_H_
+# endif
+# include "radix_ipf.h"
+#endif
+#ifdef __osf__
# include "radix_ipf.h"
+#else
+# include <net/route.h>
#endif
-#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
@@ -88,13 +104,16 @@
# include <netinet/in_var.h>
#endif
#include <netinet/tcp.h>
-#if !defined(__sgi) || defined(_KERNEL)
+#if (!defined(__sgi) && !defined(AIX)) || defined(_KERNEL)
# include <netinet/udp.h>
# include <netinet/ip_icmp.h>
#endif
#ifdef __hpux
# undef _NET_ROUTE_INCLUDED
#endif
+#ifdef __osf__
+# undef _RADIX_H_
+#endif
#include "netinet/ip_compat.h"
#ifdef USE_INET6
# include <netinet/icmp6.h>
@@ -136,8 +155,8 @@
#if !defined(lint)
static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)$FreeBSD: src/sys/contrib/ipfilter/netinet/fil.c,v 1.46 2005/06/23 14:19:02 darrenr Exp $";
-/* static const char rcsid[] = "@(#)Id: fil.c,v 2.243.2.57 2005/03/28 10:47:50 darrenr Exp"; */
+static const char rcsid[] = "@(#)$FreeBSD: src/sys/contrib/ipfilter/netinet/fil.c,v 1.52.2.2 2007/12/01 00:53:41 darrenr Exp $";
+/* static const char rcsid[] = "@(#)$Id: fil.c,v 2.243.2.125 2007/10/10 09:27:20 darrenr Exp $"; */
#endif
#ifndef _KERNEL
@@ -145,17 +164,11 @@
# include "ipt.h"
# include "bpf-ipf.h"
extern int opts;
-
-# define FR_VERBOSE(verb_pr) verbose verb_pr
-# define FR_DEBUG(verb_pr) debug verb_pr
-#else /* #ifndef _KERNEL */
-# define FR_VERBOSE(verb_pr)
-# define FR_DEBUG(verb_pr)
#endif /* _KERNEL */
fr_info_t frcache[2][8];
-struct filterstats frstats[2] = { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 } };
+struct filterstats frstats[2];
struct frentry *ipfilter[2][2] = { { NULL, NULL }, { NULL, NULL } },
*ipfilter6[2][2] = { { NULL, NULL }, { NULL, NULL } },
*ipacct6[2][2] = { { NULL, NULL }, { NULL, NULL } },
@@ -176,6 +189,7 @@
u_short fr_ip_id = 0;
int fr_chksrc = 0; /* causes a system crash if enabled */
int fr_minttl = 4;
+int fr_icmpminfragmtu = 68;
u_long fr_frouteok[2] = {0, 0};
u_long fr_userifqs = 0;
u_long fr_badcoalesces[2] = {0, 0};
@@ -221,6 +235,7 @@
static ipfunc_t fr_findfunc __P((ipfunc_t));
static frentry_t *fr_firewall __P((fr_info_t *, u_32_t *));
static int fr_funcinit __P((frentry_t *fr));
+static INLINE void frpr_ah __P((fr_info_t *));
static INLINE void frpr_esp __P((fr_info_t *));
static INLINE void frpr_gre __P((fr_info_t *));
static INLINE void frpr_udp __P((fr_info_t *));
@@ -229,16 +244,19 @@
static INLINE void frpr_ipv4hdr __P((fr_info_t *));
static INLINE int frpr_pullup __P((fr_info_t *, int));
static INLINE void frpr_short __P((fr_info_t *, int));
-static INLINE void frpr_tcpcommon __P((fr_info_t *));
-static INLINE void frpr_udpcommon __P((fr_info_t *));
-static INLINE int fr_updateipid __P((fr_info_t *));
+static INLINE int frpr_tcpcommon __P((fr_info_t *));
+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((char *));
+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 *));
/*
@@ -280,6 +298,7 @@
{ IPPROTO_AH, 0x000020 },
{ IPPROTO_NONE, 0x000040 },
{ IPPROTO_DSTOPTS, 0x000080 },
+ { IPPROTO_MOBILITY, 0x000100 },
{ 0, 0 }
};
#endif
@@ -317,7 +336,7 @@
{ "fr_srcgrpmap", fr_srcgrpmap, fr_grpmapinit },
{ "fr_dstgrpmap", fr_dstgrpmap, fr_grpmapinit },
#endif
- { "", NULL }
+ { "", NULL, NULL }
};
@@ -331,15 +350,20 @@
* adding more code to a growing switch statement.
*/
#ifdef USE_INET6
+static INLINE int frpr_ah6 __P((fr_info_t *));
+static INLINE void frpr_esp6 __P((fr_info_t *));
+static INLINE void frpr_gre6 __P((fr_info_t *));
static INLINE void frpr_udp6 __P((fr_info_t *));
static INLINE void frpr_tcp6 __P((fr_info_t *));
static INLINE void frpr_icmp6 __P((fr_info_t *));
-static INLINE void frpr_ipv6hdr __P((fr_info_t *));
+static INLINE int frpr_ipv6hdr __P((fr_info_t *));
static INLINE void frpr_short6 __P((fr_info_t *, int));
static INLINE int frpr_hopopts6 __P((fr_info_t *));
+static INLINE int frpr_mobility6 __P((fr_info_t *));
static INLINE int frpr_routing6 __P((fr_info_t *));
static INLINE int frpr_dstopts6 __P((fr_info_t *));
static INLINE int frpr_fragment6 __P((fr_info_t *));
+static INLINE int frpr_ipv6exthdr __P((fr_info_t *, int, int));
/* ------------------------------------------------------------------------ */
@@ -352,37 +376,32 @@
/* for IPv6 and marks the packet with FI_SHORT if so. See function comment */
/* for frpr_short() for more details. */
/* ------------------------------------------------------------------------ */
-static INLINE void frpr_short6(fin, min)
+static INLINE void frpr_short6(fin, xmin)
fr_info_t *fin;
-int min;
+int xmin;
{
- fr_ip_t *fi = &fin->fin_fi;
- int off;
- off = fin->fin_off;
- if (off == 0) {
- if (fin->fin_plen < fin->fin_hlen + min)
- fi->fi_flx |= FI_SHORT;
- } else if (off < min) {
- fi->fi_flx |= FI_SHORT;
- }
+ if (fin->fin_dlen < xmin)
+ fin->fin_flx |= FI_SHORT;
}
/* ------------------------------------------------------------------------ */
/* Function: frpr_ipv6hdr */
-/* Returns: void */
+/* Returns: int - 0 = IPv6 packet intact, -1 = packet lost */
/* Parameters: fin(I) - pointer to packet information */
/* */
/* IPv6 Only */
/* Copy values from the IPv6 header into the fr_info_t struct and call the */
-/* per-protocol analyzer if it exists. */
+/* per-protocol analyzer if it exists. In validating the packet, a protocol*/
+/* analyzer may pullup or free the packet itself so we need to be vigiliant */
+/* of that possibility arising. */
/* ------------------------------------------------------------------------ */
-static INLINE void frpr_ipv6hdr(fin)
+static INLINE int frpr_ipv6hdr(fin)
fr_info_t *fin;
{
- int p, go = 1, i, hdrcount, coalesced;
ip6_t *ip6 = (ip6_t *)fin->fin_ip;
+ int p, go = 1, i, hdrcount;
fr_ip_t *fi = &fin->fin_fi;
fin->fin_off = 0;
@@ -392,7 +411,6 @@
fi->fi_secmsk = 0;
fi->fi_auth = 0;
- coalesced = (fin->fin_flx & FI_COALESCE) ? 1 : 0;
p = ip6->ip6_nxt;
fi->fi_ttl = ip6->ip6_hlim;
fi->fi_src.in6 = ip6->ip6_src;
@@ -419,48 +437,35 @@
break;
case IPPROTO_GRE :
- frpr_gre(fin);
+ frpr_gre6(fin);
go = 0;
break;
case IPPROTO_HOPOPTS :
- /*
- * Actually, hop by hop header is only allowed right
- * after IPv6 header!
- */
- if (hdrcount != 0)
- fin->fin_flx |= FI_BAD;
-
- if (coalesced == 0) {
- coalesced = fr_coalesce(fin);
- if (coalesced != 1)
- return;
- }
p = frpr_hopopts6(fin);
break;
+ case IPPROTO_MOBILITY :
+ p = frpr_mobility6(fin);
+ break;
+
case IPPROTO_DSTOPTS :
- if (coalesced == 0) {
- coalesced = fr_coalesce(fin);
- if (coalesced != 1)
- return;
- }
p = frpr_dstopts6(fin);
break;
case IPPROTO_ROUTING :
- if (coalesced == 0) {
- coalesced = fr_coalesce(fin);
- if (coalesced != 1)
- return;
- }
p = frpr_routing6(fin);
break;
- case IPPROTO_ESP :
- frpr_esp(fin);
- /*FALLTHROUGH*/
case IPPROTO_AH :
+ p = frpr_ah6(fin);
+ break;
+
+ case IPPROTO_ESP :
+ frpr_esp6(fin);
+ go = 0;
+ break;
+
case IPPROTO_IPV6 :
for (i = 0; ip6exthdr[i].ol_bit != 0; i++)
if (ip6exthdr[i].ol_val == p) {
@@ -475,12 +480,9 @@
break;
case IPPROTO_FRAGMENT :
- if (coalesced == 0) {
- coalesced = fr_coalesce(fin);
- if (coalesced != 1)
- return;
- }
p = frpr_fragment6(fin);
+ if (fin->fin_off != 0)
+ go = 0;
break;
default :
@@ -494,9 +496,9 @@
* extension headers (go != 0), the entire header may not have
* been pulled up when the code gets to this point. This is
* only done for "go != 0" because the other header handlers
- * will all pullup their complete header and the other
- * indicator of an incomplete header is that this eas just an
- * extension header.
+ * will all pullup their complete header. The other indicator
+ * of an incomplete packet is that this was just an extension
+ * header.
*/
if ((go != 0) && (p != IPPROTO_NONE) &&
(frpr_pullup(fin, 0) == -1)) {
@@ -505,19 +507,32 @@
}
}
fi->fi_p = p;
+
+ /*
+ * Some of the above functions, like frpr_esp6(), can call fr_pullup
+ * and destroy whatever packet was here. The caller of this function
+ * expects us to return -1 if there is a problem with fr_pullup.
+ */
+ if (fin->fin_m == NULL)
+ return -1;
+
+ return 0;
}
/* ------------------------------------------------------------------------ */
-/* Function: frpr_hopopts6 */
+/* Function: frpr_ipv6exthdr */
/* Returns: int - value of the next header or IPPROTO_NONE if error */
-/* Parameters: fin(I) - pointer to packet information */
+/* Parameters: fin(I) - pointer to packet information */
+/* multiple(I) - flag indicating yes/no if multiple occurances */
+/* of this extension header are allowed. */
+/* proto(I) - protocol number for this extension header */
/* */
/* IPv6 Only */
-/* This is function checks pending hop by hop options extension header */
/* ------------------------------------------------------------------------ */
-static INLINE int frpr_hopopts6(fin)
+static INLINE int frpr_ipv6exthdr(fin, multiple, proto)
fr_info_t *fin;
+int multiple, proto;
{
struct ip6_ext *hdr;
u_short shift;
@@ -535,18 +550,35 @@
return IPPROTO_NONE;
hdr = fin->fin_dp;
- shift = 8 + (hdr->ip6e_len << 3);
+ switch (proto)
+ {
+ case IPPROTO_FRAGMENT :
+ shift = 8;
+ break;
+ default :
+ shift = 8 + (hdr->ip6e_len << 3);
+ break;
+ }
+
if (shift > fin->fin_dlen) { /* Nasty extension header length? */
fin->fin_flx |= FI_BAD;
return IPPROTO_NONE;
}
for (i = 0; ip6exthdr[i].ol_bit != 0; i++)
- if (ip6exthdr[i].ol_val == IPPROTO_HOPOPTS) {
- fin->fin_optmsk |= ip6exthdr[i].ol_bit;
+ if (ip6exthdr[i].ol_val == proto) {
+ /*
+ * Most IPv6 extension headers are only allowed once.
+ */
+ if ((multiple == 0) &&
+ ((fin->fin_optmsk & ip6exthdr[i].ol_bit) != 0))
+ fin->fin_flx |= FI_BAD;
+ else
+ fin->fin_optmsk |= ip6exthdr[i].ol_bit;
break;
}
+ fin->fin_exthdr = fin->fin_dp;
fin->fin_dp = (char *)fin->fin_dp + shift;
fin->fin_dlen -= shift;
@@ -555,6 +587,36 @@
/* ------------------------------------------------------------------------ */
+/* Function: frpr_hopopts6 */
+/* Returns: int - value of the next header or IPPROTO_NONE if error */
+/* Parameters: fin(I) - pointer to packet information */
+/* */
+/* IPv6 Only */
+/* This is function checks pending hop by hop options extension header */
+/* ------------------------------------------------------------------------ */
+static INLINE int frpr_hopopts6(fin)
+fr_info_t *fin;
+{
+ return frpr_ipv6exthdr(fin, 0, IPPROTO_HOPOPTS);
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: frpr_mobility6 */
+/* Returns: int - value of the next header or IPPROTO_NONE if error */
+/* Parameters: fin(I) - pointer to packet information */
+/* */
+/* IPv6 Only */
+/* This is function checks the IPv6 mobility extension header */
+/* ------------------------------------------------------------------------ */
+static INLINE int frpr_mobility6(fin)
+fr_info_t *fin;
+{
+ return frpr_ipv6exthdr(fin, 0, IPPROTO_MOBILITY);
+}
+
+
+/* ------------------------------------------------------------------------ */
/* Function: frpr_routing6 */
/* Returns: int - value of the next header or IPPROTO_NONE if error */
/* Parameters: fin(I) - pointer to packet information */
@@ -566,40 +628,25 @@
fr_info_t *fin;
{
struct ip6_ext *hdr;
- u_short shift;
- int i;
-
- fin->fin_flx |= FI_V6EXTHDR;
-
- /* 8 is default length of extension hdr */
- if ((fin->fin_dlen - 8) < 0) {
- fin->fin_flx |= FI_SHORT;
- return IPPROTO_NONE;
- }
- if (frpr_pullup(fin, 8) == -1)
+ if (frpr_ipv6exthdr(fin, 0, IPPROTO_ROUTING) == IPPROTO_NONE)
return IPPROTO_NONE;
- hdr = fin->fin_dp;
+ hdr = fin->fin_exthdr;
- shift = 8 + (hdr->ip6e_len << 3);
- /*
- * Nasty extension header length?
- */
- if ((shift > fin->fin_dlen) || (shift < sizeof(struct ip6_hdr)) ||
- ((shift - sizeof(struct ip6_hdr)) & 15)) {
+ if ((hdr->ip6e_len & 1) != 0) {
+ /*
+ * The routing header data is made up of 128 bit IPv6 addresses
+ * which means it must be a multiple of 2 lots of 8 in length.
+ */
fin->fin_flx |= FI_BAD;
+ /*
+ * Compensate for the changes made in frpr_ipv6exthdr()
+ */
+ fin->fin_dlen += 8 + (hdr->ip6e_len << 3);
+ fin->fin_dp = hdr;
return IPPROTO_NONE;
}
- for (i = 0; ip6exthdr[i].ol_bit != 0; i++)
- if (ip6exthdr[i].ol_val == IPPROTO_ROUTING) {
- fin->fin_optmsk |= ip6exthdr[i].ol_bit;
- break;
- }
-
- fin->fin_dp = (char *)fin->fin_dp + shift;
- fin->fin_dlen -= shift;
-
return hdr->ip6e_nxt;
}
@@ -611,56 +658,40 @@
/* */
/* IPv6 Only */
/* Examine the IPv6 fragment header and extract fragment offset information.*/
+/* */
+/* We don't know where the transport layer header (or whatever is next is), */
+/* as it could be behind destination options (amongst others). Because */
+/* there is no fragment cache, there is no knowledge about whether or not an*/
+/* upper layer header has been seen (or where it ends) and thus we are not */
+/* able to continue processing beyond this header with any confidence. */
/* ------------------------------------------------------------------------ */
static INLINE int frpr_fragment6(fin)
fr_info_t *fin;
{
struct ip6_frag *frag;
- struct ip6_ext *hdr;
- int i;
-
- fin->fin_flx |= (FI_FRAG|FI_V6EXTHDR);
+ int extoff;
- /* 8 is default length of extension hdr */
- if ((fin->fin_dlen - 8) < 0) {
- fin->fin_flx |= FI_SHORT;
- return IPPROTO_NONE;
- }
-
- /*
- * Only one frgament header is allowed per IPv6 packet but it need
- * not be the first nor last (not possible in some cases.)
- */
- for (i = 0; ip6exthdr[i].ol_bit != 0; i++)
- if (ip6exthdr[i].ol_val == IPPROTO_FRAGMENT)
- break;
+ fin->fin_flx |= FI_FRAG;
- if (fin->fin_optmsk & ip6exthdr[i].ol_bit) {
- fin->fin_flx |= FI_BAD;
+ if (frpr_ipv6exthdr(fin, 0, IPPROTO_FRAGMENT) == IPPROTO_NONE)
return IPPROTO_NONE;
- }
- fin->fin_optmsk |= ip6exthdr[i].ol_bit;
+ extoff = (char *)fin->fin_exthdr - (char *)fin->fin_dp;
if (frpr_pullup(fin, sizeof(*frag)) == -1)
return IPPROTO_NONE;
- hdr = fin->fin_dp;
+ fin->fin_exthdr = (char *)fin->fin_dp + extoff;
+ frag = fin->fin_exthdr;
/*
- * Length must be zero, i.e. it has no length.
+ * Fragment but no fragmentation info set? Bad packet...
*/
- if (hdr->ip6e_len != 0) {
+ if (frag->ip6f_offlg == 0) {
fin->fin_flx |= FI_BAD;
return IPPROTO_NONE;
}
- if ((int)(fin->fin_dlen - sizeof(*frag)) < 0) {
- fin->fin_flx |= FI_SHORT;
- return IPPROTO_NONE;
- }
-
- frag = fin->fin_dp;
- fin->fin_off = frag->ip6f_offlg & IP6F_OFF_MASK;
+ fin->fin_off = ntohs(frag->ip6f_offlg & IP6F_OFF_MASK);
fin->fin_off <<= 3;
if (fin->fin_off != 0)
fin->fin_flx |= FI_FRAGBODY;
@@ -684,34 +715,7 @@
static INLINE int frpr_dstopts6(fin)
fr_info_t *fin;
{
- struct ip6_ext *hdr;
- u_short shift;
- int i;
-
- /* 8 is default length of extension hdr */
- if ((fin->fin_dlen - 8) < 0) {
- fin->fin_flx |= FI_SHORT;
- return IPPROTO_NONE;
- }
-
- if (frpr_pullup(fin, 8) == -1)
- return IPPROTO_NONE;
- hdr = fin->fin_dp;
-
- shift = 8 + (hdr->ip6e_len << 3);
- if (shift > fin->fin_dlen) { /* Nasty extension header length? */
- fin->fin_flx |= FI_BAD;
- return IPPROTO_NONE;
- }
-
- for (i = 0; ip6exthdr[i].ol_bit != 0; i++)
- if (ip6exthdr[i].ol_val == IPPROTO_DSTOPTS)
- break;
- fin->fin_optmsk |= ip6exthdr[i].ol_bit;
- fin->fin_dp = (char *)fin->fin_dp + shift;
- fin->fin_dlen -= shift;
-
- return hdr->ip6e_nxt;
+ return frpr_ipv6exthdr(fin, 1, IPPROTO_DSTOPTS);
}
@@ -730,10 +734,12 @@
int minicmpsz = sizeof(struct icmp6_hdr);
struct icmp6_hdr *icmp6;
- if (frpr_pullup(fin, ICMP6ERR_MINPKTLEN + 8 - sizeof(ip6_t)) == -1)
+ if (frpr_pullup(fin, ICMP6ERR_MINPKTLEN - sizeof(ip6_t)) == -1)
return;
if (fin->fin_dlen > 1) {
+ ip6_t *ip6;
+
icmp6 = fin->fin_dp;
fin->fin_data[0] = *(u_short *)icmp6;
@@ -748,20 +754,34 @@
case ICMP6_PACKET_TOO_BIG :
case ICMP6_TIME_EXCEEDED :
case ICMP6_PARAM_PROB :
- if ((fin->fin_m != NULL) &&
- (M_LEN(fin->fin_m) < fin->fin_plen)) {
+ fin->fin_flx |= FI_ICMPERR;
+ minicmpsz = ICMP6ERR_IPICMPHLEN - sizeof(ip6_t);
+ if (fin->fin_plen < ICMP6ERR_IPICMPHLEN)
+ break;
+
+ if (M_LEN(fin->fin_m) < fin->fin_plen) {
if (fr_coalesce(fin) != 1)
return;
}
- fin->fin_flx |= FI_ICMPERR;
- minicmpsz = ICMP6ERR_IPICMPHLEN - sizeof(ip6_t);
+
+ /*
+ * If the destination of this packet doesn't match the
+ * source of the original packet then this packet is
+ * not correct.
+ */
+ icmp6 = fin->fin_dp;
+ ip6 = (ip6_t *)((char *)icmp6 + ICMPERR_ICMPHLEN);
+ if (IP6_NEQ(&fin->fin_fi.fi_dst,
+ (i6addr_t *)&ip6->ip6_src))
+ fin->fin_flx |= FI_BAD;
+
break;
default :
break;
}
}
- frpr_short(fin, minicmpsz);
+ frpr_short6(fin, minicmpsz);
}
@@ -772,16 +792,21 @@
/* */
/* IPv6 Only */
/* Analyse the packet for IPv6/UDP properties. */
+/* Is not expected to be called for fragmented packets. */
/* ------------------------------------------------------------------------ */
static INLINE void frpr_udp6(fin)
fr_info_t *fin;
{
- fr_checkv6sum(fin);
+ frpr_short6(fin, sizeof(struct udphdr));
- frpr_short(fin, sizeof(struct udphdr));
+ if (frpr_udpcommon(fin) == 0) {
+ u_char p = fin->fin_p;
- frpr_udpcommon(fin);
+ fin->fin_p = IPPROTO_UDP;
+ fr_checkv6sum(fin);
+ fin->fin_p = p;
+ }
}
@@ -792,16 +817,91 @@
/* */
/* IPv6 Only */
/* Analyse the packet for IPv6/TCP properties. */
+/* Is not expected to be called for fragmented packets. */
/* ------------------------------------------------------------------------ */
static INLINE void frpr_tcp6(fin)
fr_info_t *fin;
{
- fr_checkv6sum(fin);
+ frpr_short6(fin, sizeof(struct tcphdr));
+
+ if (frpr_tcpcommon(fin) == 0) {
+ u_char p = fin->fin_p;
+
+ fin->fin_p = IPPROTO_TCP;
+ fr_checkv6sum(fin);
+ fin->fin_p = p;
+ }
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: frpr_esp6 */
+/* Returns: void */
+/* Parameters: fin(I) - pointer to packet information */
+/* */
+/* IPv6 Only */
+/* Analyse the packet for ESP properties. */
+/* The minimum length is taken to be the SPI (32bits) plus a tail (32bits) */
+/* even though the newer ESP packets must also have a sequence number that */
+/* is 32bits as well, it is not possible(?) to determine the version from a */
+/* simple packet header. */
+/* ------------------------------------------------------------------------ */
+static INLINE void frpr_esp6(fin)
+fr_info_t *fin;
+{
+
+ frpr_short6(fin, sizeof(grehdr_t));
+
+ (void) frpr_pullup(fin, 8);
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: frpr_ah6 */
+/* Returns: void */
+/* Parameters: fin(I) - pointer to packet information */
+/* */
+/* IPv6 Only */
+/* Analyse the packet for AH properties. */
+/* The minimum length is taken to be the combination of all fields in the */
+/* header being present and no authentication data (null algorithm used.) */
+/* ------------------------------------------------------------------------ */
+static INLINE int frpr_ah6(fin)
+fr_info_t *fin;
+{
+ authhdr_t *ah;
+
+ frpr_short6(fin, 12);
+
+ if (frpr_pullup(fin, sizeof(*ah)) == -1)
+ return IPPROTO_NONE;
+
+ ah = (authhdr_t *)fin->fin_dp;
+ return ah->ah_next;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: frpr_gre6 */
+/* Returns: void */
+/* Parameters: fin(I) - pointer to packet information */
+/* */
+/* Analyse the packet for GRE properties. */
+/* ------------------------------------------------------------------------ */
+static INLINE void frpr_gre6(fin)
+fr_info_t *fin;
+{
+ grehdr_t *gre;
+
+ frpr_short6(fin, sizeof(grehdr_t));
- frpr_short(fin, sizeof(struct tcphdr));
+ if (frpr_pullup(fin, sizeof(grehdr_t)) == -1)
+ return;
- frpr_tcpcommon(fin);
+ gre = fin->fin_dp;
+ if (GRE_REV(gre->gr_flags) == 1)
+ fin->fin_data[0] = gre->gr_call;
}
#endif /* USE_INET6 */
@@ -815,23 +915,39 @@
/* Short inline function to cut down on code duplication to perform a call */
/* to fr_pullup to ensure there is the required amount of data, */
/* consecutively in the packet buffer. */
+/* */
+/* This function pulls up 'extra' data at the location of fin_dp. fin_dp */
+/* points to the first byte after the complete layer 3 header, which will */
+/* include all of the known extension headers for IPv6 or options for IPv4. */
+/* */
+/* Since fr_pullup() expects the total length of bytes to be pulled up, it */
+/* is necessary to add those we can already assume to be pulled up (fin_dp */
+/* - fin_ip) to what is passed through. */
/* ------------------------------------------------------------------------ */
static INLINE int frpr_pullup(fin, plen)
fr_info_t *fin;
int plen;
{
-#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;
}
@@ -839,28 +955,25 @@
/* ------------------------------------------------------------------------ */
/* Function: frpr_short */
/* Returns: void */
-/* Parameters: fin(I) - pointer to packet information */
-/* min(I) - minimum header size */
+/* Parameters: fin(I) - pointer to packet information */
+/* xmin(I) - minimum header size */
/* */
-/* Check if a packet is "short" as defined by min. The rule we are */
+/* Check if a packet is "short" as defined by xmin. The rule we are */
/* applying here is that the packet must not be fragmented within the layer */
/* 4 header. That is, it must not be a fragment that has its offset set to */
/* start within the layer 4 header (hdrmin) or if it is at offset 0, the */
/* entire layer 4 header must be present (min). */
/* ------------------------------------------------------------------------ */
-static INLINE void frpr_short(fin, min)
+static INLINE void frpr_short(fin, xmin)
fr_info_t *fin;
-int min;
+int xmin;
{
- fr_ip_t *fi = &fin->fin_fi;
- int off;
- off = fin->fin_off;
- if (off == 0) {
- if (fin->fin_plen < fin->fin_hlen + min)
- fi->fi_flx |= FI_SHORT;
- } else if (off < min) {
- fi->fi_flx |= FI_SHORT;
+ if (fin->fin_off == 0) {
+ if (fin->fin_dlen < xmin)
+ fin->fin_flx |= FI_SHORT;
+ } else if (fin->fin_off < xmin) {
+ fin->fin_flx |= FI_SHORT;
}
}
@@ -873,7 +986,7 @@
/* IPv4 Only */
/* Do a sanity check on the packet for ICMP (v4). In nearly all cases, */
/* except extrememly bad packets, both type and code will be present. */
-/* The expected minimum size of an ICMP packet is very much dependant on */
+/* The expected minimum size of an ICMP packet is very much dependent on */
/* the type of it. */
/* */
/* XXX - other ICMP sanity checks? */
@@ -883,17 +996,24 @@
{
int minicmpsz = sizeof(struct icmp);
icmphdr_t *icmp;
+ ip_t *oip;
- if (frpr_pullup(fin, ICMPERR_ICMPHLEN) == -1)
+ if (fin->fin_off != 0) {
+ frpr_short(fin, ICMPERR_ICMPHLEN);
return;
+ }
- fr_checkv4sum(fin);
+ if (frpr_pullup(fin, ICMPERR_ICMPHLEN) == -1)
+ return;
- if (!fin->fin_off && (fin->fin_dlen > 1)) {
+ if (fin->fin_dlen > 1) {
icmp = fin->fin_dp;
fin->fin_data[0] = *(u_short *)icmp;
+ if (fin->fin_dlen >= 6) /* ID field */
+ fin->fin_data[1] = icmp->icmp_id;
+
switch (icmp->icmp_type)
{
case ICMP_ECHOREPLY :
@@ -923,29 +1043,59 @@
* type(1) + code(1) + cksum(2) + id(2) seq(2) + ip(20+)
*/
case ICMP_UNREACH :
+#ifdef icmp_nextmtu
+ if (icmp->icmp_code == ICMP_UNREACH_NEEDFRAG) {
+ if (icmp->icmp_nextmtu < fr_icmpminfragmtu)
+ fin->fin_flx |= FI_BAD;
+ }
+#endif
case ICMP_SOURCEQUENCH :
case ICMP_REDIRECT :
case ICMP_TIMXCEED :
case ICMP_PARAMPROB :
+ fin->fin_flx |= FI_ICMPERR;
if (fr_coalesce(fin) != 1)
return;
- fin->fin_flx |= FI_ICMPERR;
- break;
- default :
- break;
- }
-
- if (fin->fin_dlen >= 6) /* ID field */
- fin->fin_data[1] = icmp->icmp_id;
+ /*
+ * ICMP error packets should not be generated for IP
+ * packets that are a fragment that isn't the first
+ * fragment.
+ */
+ 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;
+ }
}
frpr_short(fin, minicmpsz);
+
+ if ((fin->fin_flx & FI_FRAG) == 0)
+ fr_checkv4sum(fin);
}
/* ------------------------------------------------------------------------ */
/* Function: frpr_tcpcommon */
-/* Returns: void */
+/* Returns: int - 0 = header ok, 1 = bad packet, -1 = buffer error */
/* Parameters: fin(I) - pointer to packet information */
/* */
/* TCP header sanity checking. Look for bad combinations of TCP flags, */
@@ -953,20 +1103,18 @@
/* If compiled with IPFILTER_CKSUM, check to see if the TCP checksum is */
/* valid and mark the packet as bad if not. */
/* ------------------------------------------------------------------------ */
-static INLINE void frpr_tcpcommon(fin)
+static INLINE int frpr_tcpcommon(fin)
fr_info_t *fin;
{
int flags, tlen;
tcphdr_t *tcp;
- fr_ip_t *fi;
- fi = &fin->fin_fi;
- fi->fi_flx |= FI_TCPUDP;
+ fin->fin_flx |= FI_TCPUDP;
if (fin->fin_off != 0)
- return;
+ return 0;
if (frpr_pullup(fin, sizeof(*tcp)) == -1)
- return;
+ return -1;
tcp = fin->fin_dp;
if (fin->fin_dlen > 3) {
@@ -974,8 +1122,8 @@
fin->fin_dport = ntohs(tcp->th_dport);
}
- if ((fi->fi_flx & FI_SHORT) != 0)
- return;
+ if ((fin->fin_flx & FI_SHORT) != 0)
+ return 1;
/*
* Use of the TCP data offset *must* result in a value that is at
@@ -984,7 +1132,7 @@
tlen = TCP_OFF(tcp) << 2;
if (tlen < sizeof(tcphdr_t)) {
fin->fin_flx |= FI_BAD;
- return;
+ return 1;
}
flags = tcp->th_flags;
@@ -997,14 +1145,27 @@
*/
if ((flags & TH_URG) != 0 && (tcp->th_urp == 0)) {
fin->fin_flx |= FI_BAD;
+#if 0
} else if ((flags & TH_URG) == 0 && (tcp->th_urp != 0)) {
- /* Ignore this case, it shows up in "real" traffic with */
- /* bogus values in the urgent pointer field. */
- ;
+ /*
+ * Ignore this case (#if 0) as it shows up in "real"
+ * traffic with bogus values in the urgent pointer field.
+ */
+ fin->fin_flx |= FI_BAD;
+#endif
} else if (((flags & (TH_SYN|TH_FIN)) != 0) &&
((flags & (TH_RST|TH_ACK)) == TH_RST)) {
/* TH_FIN|TH_RST|TH_ACK seems to appear "naturally" */
fin->fin_flx |= FI_BAD;
+#if 1
+ } else if (((flags & TH_SYN) != 0) &&
+ ((flags & (TH_URG|TH_PUSH)) != 0)) {
+ /*
+ * SYN with URG and PUSH set is not for normal TCP but it is
+ * possible(?) with T/TCP...but who uses T/TCP?
+ */
+ fin->fin_flx |= FI_BAD;
+#endif
} else if (!(flags & TH_ACK)) {
/*
* If the ack bit isn't set, then either the SYN or
@@ -1038,12 +1199,13 @@
* then that might add some weight to adding this...
*/
if (tlen == sizeof(tcphdr_t))
- return;
+ return 0;
if (frpr_pullup(fin, tlen) == -1)
- return;
+ return -1;
#if 0
+ tcp = fin->fin_dp;
ip = fin->fin_ip;
s = (u_char *)(tcp + 1);
off = IP_HL(ip) << 2;
@@ -1080,31 +1242,31 @@
s += ol;
}
#endif /* 0 */
+
+ return 0;
}
/* ------------------------------------------------------------------------ */
/* Function: frpr_udpcommon */
-/* Returns: void */
+/* Returns: int - 0 = header ok, 1 = bad packet */
/* Parameters: fin(I) - pointer to packet information */
/* */
/* Extract the UDP source and destination ports, if present. If compiled */
/* with IPFILTER_CKSUM, check to see if the UDP checksum is valid. */
/* ------------------------------------------------------------------------ */
-static INLINE void frpr_udpcommon(fin)
+static INLINE int frpr_udpcommon(fin)
fr_info_t *fin;
{
udphdr_t *udp;
- fr_ip_t *fi;
- fi = &fin->fin_fi;
- fi->fi_flx |= FI_TCPUDP;
+ fin->fin_flx |= FI_TCPUDP;
if (!fin->fin_off && (fin->fin_dlen > 3)) {
if (frpr_pullup(fin, sizeof(*udp)) == -1) {
- fi->fi_flx |= FI_SHORT;
- return;
+ fin->fin_flx |= FI_SHORT;
+ return 1;
}
udp = fin->fin_dp;
@@ -1112,6 +1274,8 @@
fin->fin_sport = ntohs(udp->uh_sport);
fin->fin_dport = ntohs(udp->uh_dport);
}
+
+ return 0;
}
@@ -1127,11 +1291,12 @@
fr_info_t *fin;
{
- fr_checkv4sum(fin);
-
frpr_short(fin, sizeof(tcphdr_t));
- frpr_tcpcommon(fin);
+ if (frpr_tcpcommon(fin) == 0) {
+ if ((fin->fin_flx & FI_FRAG) == 0)
+ fr_checkv4sum(fin);
+ }
}
@@ -1147,11 +1312,12 @@
fr_info_t *fin;
{
- fr_checkv4sum(fin);
-
frpr_short(fin, sizeof(udphdr_t));
- frpr_udpcommon(fin);
+ if (frpr_udpcommon(fin) == 0) {
+ if ((fin->fin_flx & FI_FRAG) == 0)
+ fr_checkv4sum(fin);
+ }
}
@@ -1169,15 +1335,42 @@
static INLINE void frpr_esp(fin)
fr_info_t *fin;
{
- if (frpr_pullup(fin, 8) == -1)
- return;
- if (fin->fin_v == 4)
+ if (fin->fin_off == 0) {
frpr_short(fin, 8);
-#ifdef USE_INET6
- else if (fin->fin_v == 6)
- frpr_short6(fin, sizeof(grehdr_t));
-#endif
+ (void) frpr_pullup(fin, 8);
+ }
+
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: frpr_ah */
+/* Returns: void */
+/* Parameters: fin(I) - pointer to packet information */
+/* */
+/* Analyse the packet for AH properties. */
+/* The minimum length is taken to be the combination of all fields in the */
+/* header being present and no authentication data (null algorithm used.) */
+/* ------------------------------------------------------------------------ */
+static INLINE void frpr_ah(fin)
+fr_info_t *fin;
+{
+ authhdr_t *ah;
+ int len;
+
+ frpr_short(fin, sizeof(*ah));
+
+ if (((fin->fin_flx & FI_SHORT) != 0) || (fin->fin_off != 0))
+ return;
+
+ if (frpr_pullup(fin, sizeof(*ah)) == -1)
+ return;
+
+ ah = (authhdr_t *)fin->fin_dp;
+
+ len = (ah->ah_plen + 2) << 2;
+ frpr_short(fin, len);
}
@@ -1193,18 +1386,19 @@
{
grehdr_t *gre;
- if (frpr_pullup(fin, sizeof(grehdr_t)) == -1)
+ frpr_short(fin, sizeof(*gre));
+
+ if (fin->fin_off != 0)
return;
- if (fin->fin_v == 4)
- frpr_short(fin, sizeof(grehdr_t));
-#ifdef USE_INET6
- else if (fin->fin_v == 6)
- frpr_short6(fin, sizeof(grehdr_t));
-#endif
- gre = fin->fin_dp;
- if (GRE_REV(gre->gr_flags) == 1)
- fin->fin_data[0] = gre->gr_call;
+ if (frpr_pullup(fin, sizeof(*gre)) == -1)
+ return;
+
+ if (fin->fin_off == 0) {
+ gre = fin->fin_dp;
+ if (GRE_REV(gre->gr_flags) == 1)
+ fin->fin_data[0] = gre->gr_call;
+ }
}
@@ -1260,20 +1454,27 @@
* set packet attribute flags based on the offset and
* calculate the byte offset that it represents.
*/
- if ((off & IP_MF) != 0) {
- fi->fi_flx |= FI_FRAG;
- if (fin->fin_dlen == 0)
- fi->fi_flx |= FI_BAD;
- }
-
off &= IP_MF|IP_OFFMASK;
if (off != 0) {
+ int morefrag = off & IP_MF;
+
fi->fi_flx |= FI_FRAG;
off &= IP_OFFMASK;
if (off != 0) {
fin->fin_flx |= FI_FRAGBODY;
off <<= 3;
- if (off + fin->fin_dlen > 0xffff) {
+ if ((off + fin->fin_dlen > 65535) ||
+ (fin->fin_dlen == 0) ||
+ ((morefrag != 0) && ((fin->fin_dlen & 7) != 0))) {
+ /*
+ * The length of the packet, starting at its
+ * offset cannot exceed 65535 (0xffff) as the
+ * length of an IP packet is only 16 bits.
+ *
+ * Any fragment that isn't the last fragment
+ * must have a length greater than 0 and it
+ * must be an even multiple of 8.
+ */
fi->fi_flx |= FI_BAD;
}
}
@@ -1294,6 +1495,9 @@
case IPPROTO_ICMP :
frpr_icmp(fin);
break;
+ case IPPROTO_AH :
+ frpr_ah(fin);
+ break;
case IPPROTO_ESP :
frpr_esp(fin);
break;
@@ -1415,16 +1619,24 @@
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)
- frpr_ipv6hdr(fin);
+ } else if (v == 6) {
+ fin->fin_plen = ntohs(((ip6_t *)ip)->ip6_plen);
+ fin->fin_dlen = fin->fin_plen;
+ fin->fin_plen += hlen;
+
+ if (frpr_ipv6hdr(fin) == -1)
+ return -1;
#endif
+ }
if (fin->fin_ip == NULL)
return -1;
return 0;
@@ -1551,6 +1763,7 @@
}
+
/* ------------------------------------------------------------------------ */
/* Function: fr_ipfcheck */
/* Returns: int - 0 == match, 1 == no match */
@@ -1585,7 +1798,7 @@
*/
i = ((*lip & *lm) != *ld);
FR_DEBUG(("0. %#08x & %#08x != %#08x\n",
- *lip, *lm, *ld));
+ ntohl(*lip), ntohl(*lm), ntohl(*ld)));
if (i)
return 1;
@@ -1596,7 +1809,7 @@
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;
@@ -1619,20 +1832,20 @@
#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;
@@ -1661,20 +1874,20 @@
#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;
@@ -1754,9 +1967,9 @@
fr_info_t *fin;
u_32_t pass;
{
- int rulen, portcmp, off, logged, skip;
+ int rulen, portcmp, off, skip;
struct frentry *fr, *fnext;
- u_32_t passt;
+ u_32_t passt, passo;
/*
* Do not allow nesting deeper than 16 levels.
@@ -1773,7 +1986,6 @@
return pass;
skip = 0;
- logged = 0;
portcmp = 0;
fin->fin_depth++;
fin->fin_fr = NULL;
@@ -1824,15 +2036,13 @@
case FR_T_BPFOPC|FR_T_BUILTIN :
{
u_char *mc;
- int wlen;
if (*fin->fin_mp == NULL)
continue;
if (fin->fin_v != fr->fr_v)
continue;
mc = (u_char *)fin->fin_m;
- wlen = fin->fin_dlen + fin->fin_hlen;
- if (!bpf_filter(fr->fr_data, mc, wlen, 0))
+ if (!bpf_filter(fr->fr_data, mc, fin->fin_plen, 0))
continue;
break;
}
@@ -1878,24 +2088,23 @@
* it, except for increasing the hit counter.
*/
if ((passt & FR_CALLNOW) != 0) {
+ frentry_t *frs;
+
ATOMIC_INC64(fr->fr_hits);
if ((fr->fr_func != NULL) &&
- (fr->fr_func != (ipfunc_t)-1)) {
- frentry_t *frs;
+ (fr->fr_func == (ipfunc_t)-1))
+ continue;
- frs = fin->fin_fr;
- fin->fin_fr = fr;
- fr = (*fr->fr_func)(fin, &passt);
- if (fr == NULL) {
- fin->fin_fr = frs;
- continue;
- }
- passt = fr->fr_flags;
- fin->fin_fr = fr;
- }
- } else {
+ frs = fin->fin_fr;
fin->fin_fr = fr;
+ fr = (*fr->fr_func)(fin, &passt);
+ if (fr == NULL) {
+ fin->fin_fr = frs;
+ continue;
+ }
+ passt = fr->fr_flags;
}
+ fin->fin_fr = fr;
#ifdef IPFILTER_LOG
/*
@@ -1910,10 +2119,11 @@
ATOMIC_INCL(frstats[fin->fin_out].fr_skip);
}
ATOMIC_INCL(frstats[fin->fin_out].fr_pkl);
- logged = 1;
+ fin->fin_flx |= FI_DONTCACHE;
}
#endif /* IPFILTER_LOG */
fr->fr_bytes += (U_QUAD_T)fin->fin_plen;
+ passo = pass;
if (FR_ISSKIP(passt))
skip = fr->fr_arg;
else if ((passt & FR_LOGMASK) != FR_LOG)
@@ -1926,21 +2136,41 @@
(void) strncpy(fin->fin_group, fr->fr_group, FR_GROUPLEN);
if (fr->fr_grp != NULL) {
fin->fin_fr = *fr->fr_grp;
- pass = fr_scanlist(fin, pass);
+ passt = fr_scanlist(fin, pass);
if (fin->fin_fr == NULL) {
fin->fin_rule = rulen;
(void) strncpy(fin->fin_group, fr->fr_group,
FR_GROUPLEN);
fin->fin_fr = fr;
+ passt = pass;
}
- if (fin->fin_flx & FI_DONTCACHE)
- logged = 1;
+ pass = passt;
}
- if (pass & FR_QUICK)
+
+ if (passt & FR_QUICK) {
+ /*
+ * Finally, if we've asked to track state for this
+ * packet, set it up. Add state for "quick" rules
+ * here so that if the action fails we can consider
+ * the rule to "not match" and keep on processing
+ * filter rules.
+ */
+ if ((pass & FR_KEEPSTATE) &&
+ !(fin->fin_flx & FI_STATE)) {
+ int out = fin->fin_out;
+
+ fin->fin_fr = fr;
+ if (fr_addstate(fin, NULL, 0) != NULL) {
+ ATOMIC_INCL(frstats[out].fr_ads);
+ } else {
+ ATOMIC_INCL(frstats[out].fr_bads);
+ pass = passo;
+ continue;
+ }
+ }
break;
+ }
}
- if (logged)
- fin->fin_flx |= FI_DONTCACHE;
fin->fin_depth--;
return pass;
}
@@ -2022,18 +2252,22 @@
* the result as if it were from the ACL's.
*/
fc = &frcache[out][CACHE_HASH(fin)];
+ READ_ENTER(&ipf_frcache);
if (!bcmp((char *)fin, (char *)fc, FI_CSIZE)) {
/*
- * copy cached data so we can unlock the mutex
- * earlier.
+ * copy cached data so we can unlock the mutexes earlier.
*/
bcopy((char *)fc, (char *)fin, FI_COPYSIZE);
+ RWLOCK_EXIT(&ipf_frcache);
ATOMIC_INCL(frstats[out].fr_chit);
+
if ((fr = fin->fin_fr) != NULL) {
ATOMIC_INC64(fr->fr_hits);
pass = fr->fr_flags;
}
} else {
+ RWLOCK_EXIT(&ipf_frcache);
+
#ifdef USE_INET6
if (fin->fin_v == 6)
fin->fin_fr = ipfilter6[out][fr_active];
@@ -2042,9 +2276,13 @@
fin->fin_fr = ipfilter[out][fr_active];
if (fin->fin_fr != NULL)
pass = fr_scanlist(fin, fr_pass);
+
if (((pass & FR_KEEPSTATE) == 0) &&
- ((fin->fin_flx & FI_DONTCACHE) == 0))
+ ((fin->fin_flx & FI_DONTCACHE) == 0)) {
+ WRITE_ENTER(&ipf_frcache);
bcopy((char *)fin, (char *)fc, FI_COPYSIZE);
+ RWLOCK_EXIT(&ipf_frcache);
+ }
if ((pass & FR_NOMATCH)) {
ATOMIC_INCL(frstats[out].fr_nom);
}
@@ -2109,21 +2347,6 @@
}
}
- /*
- * Finally, if we've asked to track state for this packet, set it up.
- */
- if ((pass & FR_KEEPSTATE) && !(fin->fin_flx & FI_STATE)) {
- if (fr_addstate(fin, NULL, 0) != NULL) {
- ATOMIC_INCL(frstats[out].fr_ads);
- } else {
- ATOMIC_INCL(frstats[out].fr_bads);
- if (FR_ISPASS(pass)) {
- pass &= ~FR_CMDMASK;
- pass |= FR_BLOCK;
- }
- }
- }
-
fr = fin->fin_fr;
if (passp != NULL)
@@ -2139,7 +2362,7 @@
/* User space: */
/* -1 == packet blocked */
/* 1 == packet not matched */
-/* -2 == requires authantication */
+/* -2 == requires authentication */
/* Kernel: */
/* > 0 == filter error # for packet */
/* Parameters: ip(I) - pointer to start of IPv4/6 packet */
@@ -2186,10 +2409,6 @@
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
@@ -2201,8 +2420,12 @@
# ifdef MENTAT
qpktinfo_t *qpi = qif;
+# if !defined(_INET_IP_STACK_H)
if ((u_int)ip & 0x3)
return 2;
+# endif
+# else
+ SPL_INT(s);
# endif
READ_ENTER(&ipf_global);
@@ -2228,6 +2451,10 @@
if ((m->m_flags & M_MCAST) != 0)
fin->fin_flx |= FI_MBCAST|FI_MULTICAST;
# endif
+# if defined(M_MLOOP)
+ if ((m->m_flags & M_MLOOP) != 0)
+ fin->fin_flx |= FI_MBCAST|FI_MULTICAST;
+# endif
# if defined(M_BCAST)
if ((m->m_flags & M_BCAST) != 0)
fin->fin_flx |= FI_MBCAST|FI_BROADCAST;
@@ -2264,11 +2491,13 @@
fin->fin_out = out;
fin->fin_ifp = ifp;
fin->fin_error = ENETUNREACH;
- fin->fin_hlen = (u_short )hlen;
+ fin->fin_hlen = (u_short)hlen;
fin->fin_dp = (char *)ip + hlen;
fin->fin_ipoff = (char *)ip - MTOD(m, char *);
+ SPL_NET(s);
+
#ifdef USE_INET6
if (v == 6) {
ATOMIC_INCL(frstats[out].fr_ipv6);
@@ -2277,25 +2506,23 @@
* 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 filtered;
+ goto finished;
}
- fin->fin_plen += sizeof(ip6_t);
} else
#endif
{
-#if (OpenBSD >= 200311) && defined(_KERNEL)
+#if (defined(OpenBSD) && OpenBSD >= 200311) && defined(_KERNEL)
ip->ip_len = ntohs(ip->ip_len);
ip->ip_off = ntohs(ip->ip_off);
#endif
- fin->fin_plen = ip->ip_len;
}
- if (fr_makefrip(hlen, ip, fin) == -1)
+ if (fr_makefrip(hlen, ip, fin) == -1) {
+ pass = FR_BLOCK|FR_NOMATCH;
goto finished;
+ }
/*
* For at least IPv6 packets, if a m_pullup() fails then this pointer
@@ -2319,8 +2546,7 @@
}
#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;
}
@@ -2344,22 +2570,48 @@
fr = fr_checkauth(fin, &pass);
if (!out) {
if (fr_checknatin(fin, &pass) == -1) {
- RWLOCK_EXIT(&ipf_mutex);
- goto finished;
+ goto filterdone;
}
}
if (!out)
(void) fr_acctpkt(fin, NULL);
- if (fr == NULL)
- if ((fin->fin_flx & (FI_FRAG|FI_BAD)) == FI_FRAG)
+ if (fr == NULL) {
+ if ((fin->fin_flx & (FI_FRAG|FI_BAD)) == FI_FRAG) {
fr = fr_knownfrag(fin, &pass);
- if (fr == NULL)
- fr = fr_checkstate(fin, &pass);
+ /*
+ * Reset the keep state flag here so that we don't
+ * try and add a new state entry because of it, leading
+ * to a blocked packet because the add will fail.
+ */
+ if (fr != NULL)
+ pass &= ~FR_KEEPSTATE;
+ }
+ if (fr == NULL)
+ fr = fr_checkstate(fin, &pass);
+ }
if ((pass & FR_NOMATCH) || (fr == NULL))
fr = fr_firewall(fin, &pass);
+ /*
+ * If we've asked to track state for this packet, set it up.
+ * Here rather than fr_firewall because fr_checkauth may decide
+ * to return a packet for "keep state"
+ */
+ if ((pass & FR_KEEPSTATE) && (fin->fin_m != NULL) &&
+ !(fin->fin_flx & FI_STATE)) {
+ if (fr_addstate(fin, NULL, 0) != NULL) {
+ ATOMIC_INCL(frstats[out].fr_ads);
+ } else {
+ ATOMIC_INCL(frstats[out].fr_bads);
+ if (FR_ISPASS(pass)) {
+ pass &= ~FR_CMDMASK;
+ pass |= FR_BLOCK;
+ }
+ }
+ }
+
fin->fin_fr = fr;
/*
@@ -2370,8 +2622,7 @@
(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);
@@ -2383,29 +2634,51 @@
}
}
+filterdone:
#ifdef IPFILTER_LOG
if ((fr_flags & FF_LOGGING) || (pass & FR_LOGMASK)) {
(void) fr_dolog(fin, &pass);
}
#endif
- if (fin->fin_state != NULL)
- fr_statederef(fin, (ipstate_t **)&fin->fin_state);
-
- if (fin->fin_nat != NULL)
- fr_natderef((nat_t **)&fin->fin_nat);
+ /*
+ * The FI_STATE flag is cleared here so that calling 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((ipstate_t **)&fin->fin_state);
+ fin->fin_flx ^= FI_STATE;
+ }
+
+ if (fin->fin_nat != NULL) {
+ if (FR_ISBLOCK(pass) && (fin->fin_flx & FI_NEWNAT)) {
+ WRITE_ENTER(&ipf_nat);
+ nat_delete((nat_t *)fin->fin_nat, NL_DESTROY);
+ RWLOCK_EXIT(&ipf_nat);
+ fin->fin_nat = NULL;
+ } else {
+ fr_natderef((nat_t **)&fin->fin_nat);
+ }
+ }
/*
- * Only allow FR_DUP to work if a rule matched - it makes no sense to
- * set FR_DUP as a "default" as there are no instructions about where
- * to send the packet. Use fin_m here because it may have changed
- * (without an update of 'm') in prior processing.
+ * Up the reference on fr_lock and exit ipf_mutex. fr_fastroute
+ * only frees up the lock on ipf_global and the generation of a
+ * packet below could cause a recursive call into IPFilter.
+ * Hang onto the filter rule just in case someone decides to remove
+ * or flush it in the meantime.
*/
- if ((fr != NULL) && (pass & FR_DUP)) {
- mc = M_DUPLICATE(fin->fin_m);
+ if (fr != NULL) {
+ MUTEX_ENTER(&fr->fr_lock);
+ fr->fr_ref++;
+ MUTEX_EXIT(&fr->fr_lock);
}
- if (pass & (FR_RETRST|FR_RETICMP)) {
+ RWLOCK_EXIT(&ipf_mutex);
+
+ if ((pass & FR_RETMASK) != 0) {
/*
* Should we return an ICMP packet to indicate error
* status passing through the packet filter ?
@@ -2426,10 +2699,19 @@
ATOMIC_INCL(frstats[0].fr_ret);
} else if (((pass & FR_RETMASK) == FR_RETRST) &&
!(fin->fin_flx & FI_SHORT)) {
- if (fr_send_reset(fin) == 0) {
+ if (((fin->fin_flx & FI_OOW) != 0) ||
+ (fr_send_reset(fin) == 0)) {
ATOMIC_INCL(frstats[1].fr_ret);
}
}
+
+ /*
+ * When using return-* with auth rules, the auth code
+ * takes over disposing of this packet.
+ */
+ if (FR_ISAUTH(pass) && (fin->fin_m != NULL)) {
+ fin->fin_m = *fin->fin_mp = NULL;
+ }
} else {
if (pass & FR_RETRST)
fin->fin_error = ECONNRESET;
@@ -2442,13 +2724,7 @@
* instructions about what to do with a packet.
* Once we're finished return to our caller, freeing the packet if
* we are dropping it (* BSD ONLY *).
- * Reassign m from fin_m as we may have a new buffer, now.
*/
-#if defined(USE_INET6) || (defined(__sgi) && defined(_KERNEL))
-filtered:
-#endif
- m = fin->fin_m;
-
if (fr != NULL) {
frdest_t *fdp;
@@ -2459,26 +2735,26 @@
* For fastroute rule, no destioation interface defined
* so pass NULL as the frdest_t parameter
*/
- (void) fr_fastroute(m, mp, fin, NULL);
+ (void) fr_fastroute(fin->fin_m, mp, fin, NULL);
m = *mp = NULL;
} else if ((fdp->fd_ifp != NULL) &&
(fdp->fd_ifp != (struct ifnet *)-1)) {
/* this is for to rules: */
- (void) fr_fastroute(m, mp, fin, fdp);
+ (void) fr_fastroute(fin->fin_m, mp, fin, fdp);
m = *mp = NULL;
}
/*
* Generate a duplicated packet.
*/
- if (mc != NULL)
- (void) fr_fastroute(mc, &mc, fin, &fr->fr_dif);
- }
+ if ((pass & FR_DUP) != 0) {
+ mc = M_DUPLICATE(fin->fin_m);
+ if (mc != NULL)
+ (void) fr_fastroute(mc, &mc, fin, &fr->fr_dif);
+ }
- /*
- * This late because the likes of fr_fastroute() use fin_fr.
- */
- RWLOCK_EXIT(&ipf_mutex);
+ (void) fr_derefrule(&fr);
+ }
finished:
if (!FR_ISPASS(pass)) {
@@ -2492,14 +2768,16 @@
#if defined(_KERNEL) && defined(__sgi)
if ((fin->fin_hbuf != NULL) &&
(mtod(fin->fin_m, struct ip *) != fin->fin_ip)) {
- COPYBACK(m, 0, fin->fin_plen, fin->fin_hbuf);
+ COPYBACK(fin->fin_m, 0, fin->fin_plen, fin->fin_hbuf);
}
#endif
}
+ SPL_X(s);
RWLOCK_EXIT(&ipf_global);
+
#ifdef _KERNEL
-# if OpenBSD >= 200311
+# if defined(OpenBSD) && OpenBSD >= 200311
if (FR_ISPASS(pass) && (v == 4)) {
ip = fin->fin_ip;
ip->ip_len = ntohs(ip->ip_len);
@@ -2637,6 +2915,7 @@
/* ip(I) - pointer to IP header */
/* l4proto(I) - protocol to caclulate checksum for */
/* l4hdr(I) - pointer to layer 4 header */
+/* l3len(I) - length of layer 4 data plus layer 3 header */
/* */
/* Calculates the TCP checksum for the packet held in "m", using the data */
/* in the IP header "ip" to seed it. */
@@ -2645,12 +2924,14 @@
/* and the TCP header. We also assume that data blocks aren't allocated in */
/* odd sizes. */
/* */
+/* For IPv6, l3len excludes extension header size. */
+/* */
/* Expects ip_len to be in host byte order when called. */
/* ------------------------------------------------------------------------ */
-u_short fr_cksum(m, ip, l4proto, l4hdr)
+u_short fr_cksum(m, ip, l4proto, l4hdr, l3len)
mb_t *m;
ip_t *ip;
-int l4proto;
+int l4proto, l3len;
void *l4hdr;
{
u_short *sp, slen, sumsave, l4hlen, *csump;
@@ -2675,7 +2956,7 @@
if (IP_V(ip) == 4) {
#endif
hlen = IP_HL(ip) << 2;
- slen = ip->ip_len - hlen;
+ slen = l3len - hlen;
sum = htons((u_short)l4proto);
sum += htons(slen);
sp = (u_short *)&ip->ip_src;
@@ -2687,7 +2968,7 @@
} else if (IP_V(ip) == 6) {
ip6 = (ip6_t *)ip;
hlen = sizeof(*ip6);
- slen = ntohs(ip6->ip6_plen);
+ slen = l3len - hlen;
sum = htons((u_short)l4proto);
sum += htons(slen);
sp = (u_short *)&ip6->ip6_src;
@@ -2819,8 +3100,8 @@
* In case we had to copy the IP & TCP header out of mbufs,
* skip over the mbuf bits which are the header
*/
- if ((caddr_t)ip != mtod(m, caddr_t)) {
- hlen = (caddr_t)sp - (caddr_t)ip;
+ if ((char *)ip != mtod(m, char *)) {
+ hlen = (char *)sp - (char *)ip;
while (hlen) {
add = MIN(hlen, m->m_len);
sp = (u_short *)(mtod(m, caddr_t) + add);
@@ -2843,12 +3124,12 @@
goto nodata;
while (len > 1) {
- if (((caddr_t)sp - mtod(m, caddr_t)) >= m->m_len) {
+ if (((char *)sp - mtod(m, char *)) >= m->m_len) {
m = m->m_next;
PANIC((!m),("fr_cksum(2): not enough data"));
sp = mtod(m, u_short *);
}
- if (((caddr_t)(sp + 1) - mtod(m, caddr_t)) > m->m_len) {
+ if (((char *)(sp + 1) - mtod(m, char *)) > m->m_len) {
bytes.c[0] = *(u_char *)sp;
m = m->m_next;
PANIC((!m),("fr_cksum(3): not enough data"));
@@ -2875,6 +3156,12 @@
# endif /* defined(BSD) || defined(sun) */
# endif /* MENTAT */
#else /* _KERNEL */
+ /*
+ * Add up IP Header portion
+ */
+ if (sp != (u_short *)l4hdr)
+ sp = (u_short *)l4hdr;
+
for (; slen > 1; slen -= 2)
sum += *sp++;
if (slen)
@@ -2890,7 +3177,7 @@
#if defined(_KERNEL) && ( ((BSD < 199103) && !defined(MENTAT)) || \
- defined(__sgi) ) && !defined(linux)
+ defined(__sgi) ) && !defined(linux) && !defined(_AIX51)
/*
* Copyright (c) 1982, 1986, 1988, 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -2920,7 +3207,7 @@
* SUCH DAMAGE.
*
* @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
- * Id: fil.c,v 2.243.2.57 2005/03/28 10:47:50 darrenr Exp
+ * $Id: fil.c,v 2.243.2.125 2007/10/10 09:27:20 darrenr Exp $
*/
/*
* Copy data from an mbuf chain starting "off" bytes from the beginning,
@@ -2989,7 +3276,7 @@
m = m->m_next;
}
while (len > 0) {
- mlen = min (m->m_len - off, len);
+ mlen = min(m->m_len - off, len);
bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
cp += mlen;
len -= mlen;
@@ -3038,7 +3325,7 @@
frgroup_t *fg, **fgp;
/*
- * Which list of groups to search in is dependant on which list of
+ * Which list of groups to search in is dependent on which list of
* rules are being operated on.
*/
fgp = &ipfgroups[unit][set];
@@ -3226,7 +3513,7 @@
int *nfreedp;
frentry_t **listp;
{
- int freed = 0, i;
+ int freed = 0;
frentry_t *fp;
while ((fp = *listp) != NULL) {
@@ -3237,8 +3524,7 @@
}
*listp = fp->fr_next;
if (fp->fr_grp != NULL) {
- i = frflushlist(set, unit, nfreedp, fp->fr_grp);
- fp->fr_ref -= i;
+ (void) frflushlist(set, unit, nfreedp, fp->fr_grp);
}
if (fp->fr_grhead != NULL) {
@@ -3331,8 +3617,9 @@
/* slen bytes. */
/* ------------------------------------------------------------------------ */
char *memstr(src, dst, slen, dlen)
-char *src, *dst;
-int slen, dlen;
+const char *src;
+char *dst;
+size_t slen, dlen;
{
char *s = NULL;
@@ -3510,13 +3797,15 @@
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
@@ -3588,17 +3877,19 @@
size_t size;
{
caddr_t ca;
- int err;
+ int error;
# if SOLARIS
- err = COPYIN(src, (caddr_t)&ca, sizeof(ca));
- if (err != 0)
- return err;
+ error = COPYIN(src, &ca, sizeof(ca));
+ if (error != 0)
+ return error;
# else
bcopy(src, (caddr_t)&ca, sizeof(ca));
# endif
- err = COPYIN(ca, dst, size);
- return err;
+ error = COPYIN(ca, dst, size);
+ if (error != 0)
+ error = EFAULT;
+ return error;
}
@@ -3618,39 +3909,40 @@
size_t size;
{
caddr_t ca;
- int err;
+ int error;
-# if SOLARIS
- err = COPYIN(dst, (caddr_t)&ca, sizeof(ca));
- if (err != 0)
- return err;
-# else
bcopy(dst, (caddr_t)&ca, sizeof(ca));
-# endif
- err = COPYOUT(src, ca, size);
- return err;
+ error = COPYOUT(src, ca, size);
+ if (error != 0)
+ error = EFAULT;
+ return error;
}
#endif
/* ------------------------------------------------------------------------ */
/* Function: fr_lock */
-/* Returns: (void) */
+/* Returns: int - 0 = success, else error */
/* Parameters: data(I) - pointer to lock value to set */
/* lockp(O) - pointer to location to store old lock value */
/* */
/* Get the new value for the lock integer, set it and return the old value */
/* in *lockp. */
/* ------------------------------------------------------------------------ */
-void fr_lock(data, lockp)
+int fr_lock(data, lockp)
caddr_t data;
int *lockp;
{
- int arg;
+ int arg, err;
- BCOPYIN(data, (caddr_t)&arg, sizeof(arg));
- BCOPYOUT((caddr_t)lockp, data, sizeof(*lockp));
+ err = BCOPYIN(data, &arg, sizeof(arg));
+ if (err != 0)
+ return EFAULT;
+ err = BCOPYOUT(lockp, data, sizeof(*lockp));
+ if (err != 0)
+ return EFAULT;
*lockp = arg;
+ return 0;
}
@@ -3804,7 +4096,8 @@
/* 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. */
/* */
@@ -3813,20 +4106,35 @@
/* 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);
@@ -3998,16 +4306,6 @@
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.
*/
@@ -4017,6 +4315,8 @@
if (!ptr)
return ENOMEM;
error = COPYIN(uptr, ptr, fp->fr_dsize);
+ if (error != 0)
+ error = EFAULT;
} else {
ptr = uptr;
error = 0;
@@ -4075,8 +4375,11 @@
#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 :
@@ -4100,12 +4403,14 @@
#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 :
-
break;
}
break;
@@ -4143,10 +4448,24 @@
fp->fr_cksum += *p;
WRITE_ENTER(&ipf_mutex);
- bzero((char *)frcache, sizeof(frcache));
- for (; (f = *ftail) != NULL; ftail = &f->fr_next) {
- if ((fp->fr_cksum != f->fr_cksum) ||
+ /*
+ * 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) {
+ if ((fp->fr_cksum != f->fr_cksum) ||
(f->fr_dsize != fp->fr_dsize))
continue;
if (bcmp((char *)&f->fr_func, (char *)&fp->fr_func, FR_CMPSIZ))
@@ -4186,6 +4505,8 @@
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;
@@ -4260,7 +4581,7 @@
/*
* Return EBUSY if the rule is being reference by
- * something else (eg state information.
+ * something else (eg state information.)
*/
if (f->fr_ref > 1) {
error = EBUSY;
@@ -4271,8 +4592,6 @@
(f->fr_isc != (struct ipscan *)-1))
ipsc_detachfr(f);
#endif
- if ((fg != NULL) && (fg->fg_head != NULL))
- fg->fg_head->fr_ref--;
if (unit == IPL_LOGAUTH) {
error = fr_preauthcmd(req, f, ftail);
goto done;
@@ -4282,7 +4601,7 @@
fr_fixskip(ftail, f, -1);
*ftail = f->fr_next;
f->fr_next = NULL;
- (void)fr_derefrule(&f);
+ (void) fr_derefrule(&f);
}
} else {
/*
@@ -4300,8 +4619,6 @@
} else
f = fp;
if (f != NULL) {
- if (fg != NULL && fg->fg_head!= NULL )
- fg->fg_head->fr_ref++;
if (fp != f)
bcopy((char *)fp, (char *)f,
sizeof(*f));
@@ -4401,8 +4718,11 @@
void *data;
{
ipfunc_resolve_t res, *ft;
+ int err;
- BCOPYIN(data, &res, sizeof(res));
+ err = BCOPYIN(data, &res, sizeof(res));
+ if (err != 0)
+ return EFAULT;
if (res.ipfu_addr == NULL && res.ipfu_name[0] != '\0') {
for (ft = fr_availfuncs; ft->ipfu_addr != NULL; ft++)
@@ -4431,7 +4751,7 @@
#if !defined(_KERNEL) || (!defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__FreeBSD__)) || \
- (defined(__FreeBSD__) && (__FreeBSD_version < 490000)) || \
+ (defined(__FreeBSD__) && (__FreeBSD_version < 501000)) || \
(defined(__NetBSD__) && (__NetBSD_Version__ < 105000000)) || \
(defined(__OpenBSD__) && (OpenBSD < 200006))
/*
@@ -4496,6 +4816,7 @@
frentry_t *fr;
fr = *frp;
+ *frp = NULL;
MUTEX_ENTER(&fr->fr_lock);
fr->fr_ref--;
@@ -4521,7 +4842,6 @@
} else {
MUTEX_EXIT(&fr->fr_lock);
}
- *frp = NULL;
return -1;
}
@@ -4747,7 +5067,7 @@
ifq->ifq_next->ifq_pnext = ifq->ifq_pnext;
MUTEX_DESTROY(&ifq->ifq_lock);
- fr_userifqs--;
+ ATOMIC_DEC(fr_userifqs);
KFREE(ifq);
}
@@ -4769,8 +5089,6 @@
ipftq_t *ifq;
ifq = tqe->tqe_ifq;
- if (ifq == NULL)
- return;
MUTEX_ENTER(&ifq->ifq_lock);
@@ -4842,24 +5160,21 @@
tqe->tqe_die = fr_ticks + ifq->ifq_ttl;
MUTEX_ENTER(&ifq->ifq_lock);
- if (tqe->tqe_next == NULL) { /* at the end already ? */
- MUTEX_EXIT(&ifq->ifq_lock);
- return;
- }
-
- /*
- * Remove from list
- */
- *tqe->tqe_pnext = tqe->tqe_next;
- tqe->tqe_next->tqe_pnext = tqe->tqe_pnext;
+ if (tqe->tqe_next != NULL) { /* at the end already ? */
+ /*
+ * Remove from list
+ */
+ *tqe->tqe_pnext = tqe->tqe_next;
+ tqe->tqe_next->tqe_pnext = tqe->tqe_pnext;
- /*
- * Make it the last entry.
- */
- tqe->tqe_next = NULL;
- tqe->tqe_pnext = ifq->ifq_tail;
- *ifq->ifq_tail = tqe;
- ifq->ifq_tail = &tqe->tqe_next;
+ /*
+ * Make it the last entry.
+ */
+ tqe->tqe_next = NULL;
+ tqe->tqe_pnext = ifq->ifq_tail;
+ *ifq->ifq_tail = tqe;
+ ifq->ifq_tail = &tqe->tqe_next;
+ }
MUTEX_EXIT(&ifq->ifq_lock);
}
@@ -4911,46 +5226,44 @@
* Is the operation here going to be a no-op ?
*/
MUTEX_ENTER(&oifq->ifq_lock);
- if (oifq == nifq && *oifq->ifq_tail == tqe) {
- MUTEX_EXIT(&oifq->ifq_lock);
- return;
- }
+ if ((oifq != nifq) || (*oifq->ifq_tail != tqe)) {
+ /*
+ * Remove from the old queue
+ */
+ *tqe->tqe_pnext = tqe->tqe_next;
+ if (tqe->tqe_next)
+ tqe->tqe_next->tqe_pnext = tqe->tqe_pnext;
+ else
+ oifq->ifq_tail = tqe->tqe_pnext;
+ tqe->tqe_next = NULL;
- /*
- * Remove from the old queue
- */
- *tqe->tqe_pnext = tqe->tqe_next;
- if (tqe->tqe_next)
- tqe->tqe_next->tqe_pnext = tqe->tqe_pnext;
- else
- oifq->ifq_tail = tqe->tqe_pnext;
- tqe->tqe_next = NULL;
+ /*
+ * If we're moving from one queue to another, release the
+ * lock on the old queue and get a lock on the new queue.
+ * For user defined queues, if we're moving off it, call
+ * delete in case it can now be freed.
+ */
+ if (oifq != nifq) {
+ tqe->tqe_ifq = NULL;
- /*
- * If we're moving from one queue to another, release the lock on the
- * old queue and get a lock on the new queue. For user defined queues,
- * if we're moving off it, call delete in case it can now be freed.
- */
- if (oifq != nifq) {
- tqe->tqe_ifq = NULL;
+ (void) fr_deletetimeoutqueue(oifq);
- (void) fr_deletetimeoutqueue(oifq);
+ MUTEX_EXIT(&oifq->ifq_lock);
- MUTEX_EXIT(&oifq->ifq_lock);
+ MUTEX_ENTER(&nifq->ifq_lock);
- MUTEX_ENTER(&nifq->ifq_lock);
+ tqe->tqe_ifq = nifq;
+ nifq->ifq_ref++;
+ }
- tqe->tqe_ifq = nifq;
- nifq->ifq_ref++;
+ /*
+ * Add to the bottom of the new queue
+ */
+ tqe->tqe_die = fr_ticks + nifq->ifq_ttl;
+ tqe->tqe_pnext = nifq->ifq_tail;
+ *nifq->ifq_tail = tqe;
+ nifq->ifq_tail = &tqe->tqe_next;
}
-
- /*
- * Add to the bottom of the new queue
- */
- tqe->tqe_die = fr_ticks + nifq->ifq_ttl;
- tqe->tqe_pnext = nifq->ifq_tail;
- *nifq->ifq_tail = tqe;
- nifq->ifq_tail = &tqe->tqe_next;
MUTEX_EXIT(&nifq->ifq_lock);
}
@@ -4967,7 +5280,7 @@
/* the fragment cache for non-leading fragments. If a non-leading fragment */
/* has no match in the cache, return an error. */
/* ------------------------------------------------------------------------ */
-static INLINE int fr_updateipid(fin)
+static int fr_updateipid(fin)
fr_info_t *fin;
{
u_short id, ido, sums;
@@ -5019,7 +5332,7 @@
{
static char namebuf[LIFNAMSIZ];
# if defined(MENTAT) || defined(__FreeBSD__) || defined(__osf__) || \
- defined(__sgi) || defined(linux) || \
+ defined(__sgi) || defined(linux) || defined(_AIX51) || \
(defined(sun) && !defined(__SVR4) && !defined(__svr4__))
int unit, space;
char temp[20];
@@ -5031,7 +5344,7 @@
(void) strncpy(buffer, ifp->if_name, LIFNAMSIZ);
buffer[LIFNAMSIZ - 1] = '\0';
# if defined(MENTAT) || defined(__FreeBSD__) || defined(__osf__) || \
- defined(__sgi) || \
+ defined(__sgi) || defined(_AIX51) || \
(defined(sun) && !defined(__SVR4) && !defined(__svr4__))
for (s = buffer; *s; s++)
;
@@ -5058,55 +5371,47 @@
/* 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;
@@ -5114,7 +5419,7 @@
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;
@@ -5122,7 +5427,7 @@
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;
@@ -5140,9 +5445,7 @@
* 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) },
@@ -5156,7 +5459,13 @@
{ 1, sizeof(struct ipstate) }, /* ipstate */
{ 0, sizeof(struct ips_stat) },
{ 0, sizeof(struct frauth) },
- { 0, sizeof(struct ipftune) }
+ { 0, sizeof(struct ipftune) },
+ { 0, sizeof(struct nat) }, /* nat_t */
+ { 0, sizeof(struct ipfruleiter) },
+ { 0, sizeof(struct ipfgeniter) },
+ { 0, sizeof(struct ipftable) },
+ { 0, sizeof(struct ipflookupiter) },
+ { 0, sizeof(struct ipftq) * IPF_TCP_NSTATES },
};
@@ -5179,10 +5488,12 @@
ipfobj_t obj;
int error = 0;
- if ((type < 0) || (type > NUM_OBJ_TYPES-1))
+ if ((type < 0) || (type >= IPFOBJ_COUNT))
return EINVAL;
- BCOPYIN((caddr_t)data, (caddr_t)&obj, sizeof(obj));
+ error = BCOPYIN(data, &obj, sizeof(obj));
+ if (error != 0)
+ return EFAULT;
if (obj.ipfo_type != type)
return EINVAL;
@@ -5191,8 +5502,9 @@
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 */
@@ -5207,12 +5519,12 @@
#endif
if ((fr_objbytes[type][0] & 1) != 0) {
- error = COPYIN((caddr_t)obj.ipfo_ptr, (caddr_t)ptr,
- fr_objbytes[type][1]);
+ error = COPYIN(obj.ipfo_ptr, ptr, fr_objbytes[type][1]);
} else {
- error = COPYIN((caddr_t)obj.ipfo_ptr, (caddr_t)ptr,
- obj.ipfo_size);
+ error = COPYIN(obj.ipfo_ptr, ptr, obj.ipfo_size);
}
+ if (error != 0)
+ error = EFAULT;
return error;
}
@@ -5239,12 +5551,14 @@
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;
- BCOPYIN((caddr_t)data, (caddr_t)&obj, sizeof(obj));
+ error = BCOPYIN(data, &obj, sizeof(obj));
+ if (error != 0)
+ return EFAULT;
if (obj.ipfo_type != type)
return EINVAL;
@@ -5261,7 +5575,9 @@
return EINVAL;
#endif
- error = COPYIN((caddr_t)obj.ipfo_ptr, (caddr_t)ptr, sz);
+ error = COPYIN(obj.ipfo_ptr, ptr, sz);
+ if (error != 0)
+ error = EFAULT;
return error;
}
@@ -5288,12 +5604,14 @@
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;
- BCOPYIN((caddr_t)data, (caddr_t)&obj, sizeof(obj));
+ error = BCOPYIN(data, &obj, sizeof(obj));
+ if (error != 0)
+ return EFAULT;
if (obj.ipfo_type != type)
return EINVAL;
@@ -5310,7 +5628,9 @@
return EINVAL;
#endif
- error = COPYOUT((caddr_t)ptr, (caddr_t)obj.ipfo_ptr, sz);
+ error = COPYOUT(ptr, obj.ipfo_ptr, sz);
+ if (error != 0)
+ error = EFAULT;
return error;
}
@@ -5334,10 +5654,12 @@
ipfobj_t obj;
int error;
- if ((type < 0) || (type > NUM_OBJ_TYPES-1))
+ if ((type < 0) || (type >= IPFOBJ_COUNT))
return EINVAL;
- BCOPYIN((caddr_t)data, (caddr_t)&obj, sizeof(obj));
+ error = BCOPYIN(data, &obj, sizeof(obj));
+ if (error != 0)
+ return EFAULT;
if (obj.ipfo_type != type)
return EINVAL;
@@ -5361,7 +5683,9 @@
return EINVAL;
#endif
- error = COPYOUT((caddr_t)ptr, (caddr_t)obj.ipfo_ptr, obj.ipfo_size);
+ error = COPYOUT(ptr, obj.ipfo_ptr, obj.ipfo_size);
+ if (error != 0)
+ error = EFAULT;
return error;
}
@@ -5385,6 +5709,12 @@
if ((fin->fin_flx & FI_NOCKSUM) != 0)
return 0;
+ if (fin->fin_cksum == 1)
+ return 0;
+
+ if (fin->fin_cksum == -1)
+ return -1;
+
/*
* If the TCP packet isn't a fragment, isn't too short and otherwise
* isn't already considered "bad", then validate the checksum. If
@@ -5432,9 +5762,11 @@
if (csump != NULL)
hdrsum = *csump;
- if (dosum)
+ if (dosum) {
sum = fr_cksum(fin->fin_m, fin->fin_ip,
- fin->fin_p, fin->fin_dp);
+ fin->fin_p, fin->fin_dp,
+ fin->fin_dlen + fin->fin_hlen);
+ }
#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) && defined(ICK_VALID)
}
#endif
@@ -5445,8 +5777,11 @@
FR_DEBUG(("checkl4sum: %hx != %hx\n", sum, hdrsum));
}
#endif
- if (hdrsum == sum)
+ if (hdrsum == sum) {
+ fin->fin_cksum = 1;
return 0;
+ }
+ fin->fin_cksum = -1;
return -1;
}
@@ -5635,96 +5970,104 @@
ipftuneable_t ipf_tuneables[] = {
/* filtering */
{ { &fr_flags }, "fr_flags", 0, 0xffffffff,
- sizeof(fr_flags), 0 },
+ sizeof(fr_flags), 0, NULL },
{ { &fr_active }, "fr_active", 0, 0,
- sizeof(fr_active), IPFT_RDONLY },
+ sizeof(fr_active), IPFT_RDONLY, NULL },
{ { &fr_control_forwarding }, "fr_control_forwarding", 0, 1,
- sizeof(fr_control_forwarding), 0 },
+ sizeof(fr_control_forwarding), 0, NULL },
{ { &fr_update_ipid }, "fr_update_ipid", 0, 1,
- sizeof(fr_update_ipid), 0 },
+ sizeof(fr_update_ipid), 0, NULL },
{ { &fr_chksrc }, "fr_chksrc", 0, 1,
- sizeof(fr_chksrc), 0 },
+ sizeof(fr_chksrc), 0, NULL },
+ { { &fr_minttl }, "fr_minttl", 0, 1,
+ sizeof(fr_minttl), 0, NULL },
+ { { &fr_icmpminfragmtu }, "fr_icmpminfragmtu", 0, 1,
+ sizeof(fr_icmpminfragmtu), 0, NULL },
{ { &fr_pass }, "fr_pass", 0, 0xffffffff,
- sizeof(fr_pass), 0 },
+ sizeof(fr_pass), 0, NULL },
/* state */
{ { &fr_tcpidletimeout }, "fr_tcpidletimeout", 1, 0x7fffffff,
- sizeof(fr_tcpidletimeout), IPFT_WRDISABLED },
+ sizeof(fr_tcpidletimeout), IPFT_WRDISABLED, NULL },
{ { &fr_tcpclosewait }, "fr_tcpclosewait", 1, 0x7fffffff,
- sizeof(fr_tcpclosewait), IPFT_WRDISABLED },
+ sizeof(fr_tcpclosewait), IPFT_WRDISABLED, NULL },
{ { &fr_tcplastack }, "fr_tcplastack", 1, 0x7fffffff,
- sizeof(fr_tcplastack), IPFT_WRDISABLED },
+ sizeof(fr_tcplastack), IPFT_WRDISABLED, NULL },
{ { &fr_tcptimeout }, "fr_tcptimeout", 1, 0x7fffffff,
- sizeof(fr_tcptimeout), IPFT_WRDISABLED },
+ sizeof(fr_tcptimeout), IPFT_WRDISABLED, NULL },
{ { &fr_tcpclosed }, "fr_tcpclosed", 1, 0x7fffffff,
- sizeof(fr_tcpclosed), IPFT_WRDISABLED },
+ sizeof(fr_tcpclosed), IPFT_WRDISABLED, NULL },
{ { &fr_tcphalfclosed }, "fr_tcphalfclosed", 1, 0x7fffffff,
- sizeof(fr_tcphalfclosed), IPFT_WRDISABLED },
+ sizeof(fr_tcphalfclosed), IPFT_WRDISABLED, NULL },
{ { &fr_udptimeout }, "fr_udptimeout", 1, 0x7fffffff,
- sizeof(fr_udptimeout), IPFT_WRDISABLED },
+ sizeof(fr_udptimeout), IPFT_WRDISABLED, NULL },
{ { &fr_udpacktimeout }, "fr_udpacktimeout", 1, 0x7fffffff,
- sizeof(fr_udpacktimeout), IPFT_WRDISABLED },
+ sizeof(fr_udpacktimeout), IPFT_WRDISABLED, NULL },
{ { &fr_icmptimeout }, "fr_icmptimeout", 1, 0x7fffffff,
- sizeof(fr_icmptimeout), IPFT_WRDISABLED },
+ sizeof(fr_icmptimeout), IPFT_WRDISABLED, NULL },
{ { &fr_icmpacktimeout }, "fr_icmpacktimeout", 1, 0x7fffffff,
- sizeof(fr_icmpacktimeout), IPFT_WRDISABLED },
+ sizeof(fr_icmpacktimeout), IPFT_WRDISABLED, NULL },
{ { &fr_iptimeout }, "fr_iptimeout", 1, 0x7fffffff,
- sizeof(fr_iptimeout), IPFT_WRDISABLED },
+ sizeof(fr_iptimeout), IPFT_WRDISABLED, NULL },
{ { &fr_statemax }, "fr_statemax", 1, 0x7fffffff,
- sizeof(fr_statemax), 0 },
+ sizeof(fr_statemax), 0, NULL },
{ { &fr_statesize }, "fr_statesize", 1, 0x7fffffff,
- sizeof(fr_statesize), IPFT_WRDISABLED },
+ sizeof(fr_statesize), IPFT_WRDISABLED, NULL },
{ { &fr_state_lock }, "fr_state_lock", 0, 1,
- sizeof(fr_state_lock), IPFT_RDONLY },
+ sizeof(fr_state_lock), IPFT_RDONLY, NULL },
{ { &fr_state_maxbucket }, "fr_state_maxbucket", 1, 0x7fffffff,
- sizeof(fr_state_maxbucket), IPFT_WRDISABLED },
+ sizeof(fr_state_maxbucket), IPFT_WRDISABLED, NULL },
{ { &fr_state_maxbucket_reset }, "fr_state_maxbucket_reset", 0, 1,
- sizeof(fr_state_maxbucket_reset), IPFT_WRDISABLED },
+ sizeof(fr_state_maxbucket_reset), IPFT_WRDISABLED, NULL },
{ { &ipstate_logging }, "ipstate_logging", 0, 1,
- sizeof(ipstate_logging), 0 },
+ sizeof(ipstate_logging), 0, NULL },
/* nat */
{ { &fr_nat_lock }, "fr_nat_lock", 0, 1,
- sizeof(fr_nat_lock), IPFT_RDONLY },
+ sizeof(fr_nat_lock), IPFT_RDONLY, NULL },
{ { &ipf_nattable_sz }, "ipf_nattable_sz", 1, 0x7fffffff,
- sizeof(ipf_nattable_sz), IPFT_WRDISABLED },
+ sizeof(ipf_nattable_sz), IPFT_WRDISABLED, NULL },
{ { &ipf_nattable_max }, "ipf_nattable_max", 1, 0x7fffffff,
- sizeof(ipf_nattable_max), 0 },
+ sizeof(ipf_nattable_max), 0, NULL },
{ { &ipf_natrules_sz }, "ipf_natrules_sz", 1, 0x7fffffff,
- sizeof(ipf_natrules_sz), IPFT_WRDISABLED },
+ sizeof(ipf_natrules_sz), IPFT_WRDISABLED, NULL },
{ { &ipf_rdrrules_sz }, "ipf_rdrrules_sz", 1, 0x7fffffff,
- sizeof(ipf_rdrrules_sz), IPFT_WRDISABLED },
+ sizeof(ipf_rdrrules_sz), IPFT_WRDISABLED, NULL },
{ { &ipf_hostmap_sz }, "ipf_hostmap_sz", 1, 0x7fffffff,
- sizeof(ipf_hostmap_sz), IPFT_WRDISABLED },
+ sizeof(ipf_hostmap_sz), IPFT_WRDISABLED, NULL },
{ { &fr_nat_maxbucket }, "fr_nat_maxbucket", 1, 0x7fffffff,
- sizeof(fr_nat_maxbucket), IPFT_WRDISABLED },
+ sizeof(fr_nat_maxbucket), 0, NULL },
{ { &fr_nat_maxbucket_reset }, "fr_nat_maxbucket_reset", 0, 1,
- sizeof(fr_nat_maxbucket_reset), IPFT_WRDISABLED },
+ sizeof(fr_nat_maxbucket_reset), IPFT_WRDISABLED, NULL },
{ { &nat_logging }, "nat_logging", 0, 1,
- sizeof(nat_logging), 0 },
+ sizeof(nat_logging), 0, NULL },
{ { &fr_defnatage }, "fr_defnatage", 1, 0x7fffffff,
- sizeof(fr_defnatage), IPFT_WRDISABLED },
+ sizeof(fr_defnatage), IPFT_WRDISABLED, NULL },
{ { &fr_defnatipage }, "fr_defnatipage", 1, 0x7fffffff,
- sizeof(fr_defnatipage), IPFT_WRDISABLED },
+ sizeof(fr_defnatipage), IPFT_WRDISABLED, NULL },
{ { &fr_defnaticmpage }, "fr_defnaticmpage", 1, 0x7fffffff,
- sizeof(fr_defnaticmpage), IPFT_WRDISABLED },
+ sizeof(fr_defnaticmpage), IPFT_WRDISABLED, NULL },
+ { { &fr_nat_doflush }, "fr_nat_doflush", 0, 1,
+ sizeof(fr_nat_doflush), 0, NULL },
+ /* proxy */
+ { { &ipf_proxy_debug }, "ipf_proxy_debug", 0, 10,
+ sizeof(ipf_proxy_debug), 0, 0 },
/* frag */
{ { &ipfr_size }, "ipfr_size", 1, 0x7fffffff,
- sizeof(ipfr_size), IPFT_WRDISABLED },
+ sizeof(ipfr_size), IPFT_WRDISABLED, NULL },
{ { &fr_ipfrttl }, "fr_ipfrttl", 1, 0x7fffffff,
- sizeof(fr_ipfrttl), IPFT_WRDISABLED },
+ sizeof(fr_ipfrttl), IPFT_WRDISABLED, NULL },
#ifdef IPFILTER_LOG
/* log */
{ { &ipl_suppress }, "ipl_suppress", 0, 1,
- sizeof(ipl_suppress), 0 },
- { { &ipl_buffer_sz }, "ipl_buffer_sz", 0, 0,
- sizeof(ipl_buffer_sz), IPFT_RDONLY },
+ sizeof(ipl_suppress), 0, NULL },
{ { &ipl_logmax }, "ipl_logmax", 0, 0x7fffffff,
- sizeof(ipl_logmax), IPFT_WRDISABLED },
+ sizeof(ipl_logmax), IPFT_WRDISABLED, NULL },
{ { &ipl_logall }, "ipl_logall", 0, 1,
- sizeof(ipl_logall), 0 },
+ sizeof(ipl_logall), 0, NULL },
{ { &ipl_logsize }, "ipl_logsize", 0, 0x80000,
- sizeof(ipl_logsize), 0 },
+ sizeof(ipl_logsize), 0, NULL },
#endif
- { { NULL }, NULL, 0, 0 }
+ { { NULL }, NULL, 0, 0,
+ 0, 0, NULL }
};
static ipftuneable_t *ipf_tunelist = NULL;
@@ -5789,7 +6132,7 @@
/* to the matching structure. */
/* ------------------------------------------------------------------------ */
static ipftuneable_t *fr_findtunebyname(name)
-char *name;
+const char *name;
{
ipftuneable_t *ta;
@@ -6035,6 +6378,8 @@
{
int i;
+ bzero(&frstats, sizeof(frstats));
+
#ifdef IPFILTER_LOG
i = fr_loginit();
if (i < 0)
@@ -6132,18 +6477,18 @@
/* the copyout may result in paging (ie network activity.) */
/* ------------------------------------------------------------------------ */
int fr_zerostats(data)
-caddr_t data;
+void *data;
{
friostat_t fio;
int error;
fr_getstat(&fio);
- error = copyoutptr(&fio, data, sizeof(fio));
+ error = fr_outobj(data, &fio, IPFOBJ_IPFSTAT);
if (error)
return EFAULT;
WRITE_ENTER(&ipf_mutex);
- bzero((char *)frstats, sizeof(*frstats) * 2);
+ bzero(&frstats, sizeof(frstats));
RWLOCK_EXIT(&ipf_mutex);
return 0;
@@ -6181,31 +6526,6 @@
/* ------------------------------------------------------------------------ */
-/* Function: fr_icmp4errortype */
-/* Returns: int - 1 == success, 0 == failure */
-/* Parameters: icmptype(I) - ICMP type number */
-/* */
-/* Tests to see if the ICMP type number passed is an error type or not. */
-/* ------------------------------------------------------------------------ */
-int fr_icmp4errortype(icmptype)
-int icmptype;
-{
-
- switch (icmptype)
- {
- case ICMP_SOURCEQUENCH :
- case ICMP_PARAMPROB :
- case ICMP_REDIRECT :
- case ICMP_TIMXCEED :
- case ICMP_UNREACH :
- return 1;
- default:
- return 0;
- }
-}
-
-
-/* ------------------------------------------------------------------------ */
/* Function: fr_resolvenic */
/* Returns: void* - NULL = wildcard name, -1 = failed to find NIC, else */
/* pointer to interface structure for NIC */
@@ -6247,3 +6567,792 @@
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;
+
+ WRITE_ENTER(&ipf_tokens);
+ while ((it = ipftokenhead) != NULL) {
+ if (it->ipt_die > fr_ticks)
+ break;
+
+ ipf_freetoken(it);
+ }
+ RWLOCK_EXIT(&ipf_tokens);
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipf_deltoken */
+/* Returns: int - 0 = success, else error */
+/* Parameters: type(I) - the token type to match */
+/* uid(I) - uid owning the token */
+/* ptr(I) - context pointer for the token */
+/* */
+/* This function looks for a a token in the current list that matches up */
+/* the fields (type, uid, ptr). If none is found, ESRCH is returned, else */
+/* call ipf_freetoken() to remove it from the list. */
+/* ------------------------------------------------------------------------ */
+int ipf_deltoken(type, uid, ptr)
+int type, uid;
+void *ptr;
+{
+ ipftoken_t *it;
+ int error = ESRCH;
+
+ WRITE_ENTER(&ipf_tokens);
+ for (it = ipftokenhead; it != NULL; it = it->ipt_next)
+ if (ptr == it->ipt_ctx && type == it->ipt_type &&
+ uid == it->ipt_uid) {
+ ipf_freetoken(it);
+ error = 0;
+ break;
+ }
+ RWLOCK_EXIT(&ipf_tokens);
+
+ return error;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipf_findtoken */
+/* Returns: ipftoken_t * - NULL if no memory, else pointer to token */
+/* Parameters: type(I) - the token type to match */
+/* uid(I) - uid owning the token */
+/* ptr(I) - context pointer for the token */
+/* */
+/* This function looks for a live token in the list of current tokens that */
+/* matches the tuple (type, uid, ptr). If one cannot be found then one is */
+/* allocated. If one is found then it is moved to the top of the list of */
+/* currently active tokens. */
+/* */
+/* NOTE: It is by design that this function returns holding a read lock on */
+/* ipf_tokens. Callers must make sure they release it! */
+/* ------------------------------------------------------------------------ */
+ipftoken_t *ipf_findtoken(type, uid, ptr)
+int type, uid;
+void *ptr;
+{
+ ipftoken_t *it, *new;
+
+ KMALLOC(new, ipftoken_t *);
+
+ WRITE_ENTER(&ipf_tokens);
+ for (it = ipftokenhead; it != NULL; it = it->ipt_next) {
+ if (it->ipt_alive == 0)
+ continue;
+ if (ptr == it->ipt_ctx && type == it->ipt_type &&
+ uid == it->ipt_uid)
+ break;
+ }
+
+ if (it == NULL) {
+ it = new;
+ new = NULL;
+ if (it == NULL)
+ return NULL;
+ it->ipt_data = NULL;
+ it->ipt_ctx = ptr;
+ it->ipt_uid = uid;
+ it->ipt_type = type;
+ it->ipt_next = NULL;
+ it->ipt_alive = 1;
+ } else {
+ if (new != NULL) {
+ KFREE(new);
+ new = NULL;
+ }
+
+ ipf_unlinktoken(it);
+ }
+ it->ipt_pnext = ipftokentail;
+ *ipftokentail = it;
+ ipftokentail = &it->ipt_next;
+ it->ipt_next = NULL;
+
+ it->ipt_die = fr_ticks + 2;
+
+ MUTEX_DOWNGRADE(&ipf_tokens);
+
+ return it;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipf_unlinktoken */
+/* Returns: None. */
+/* Parameters: token(I) - pointer to token structure */
+/* */
+/* This function unlinks a token structure from the linked list of tokens */
+/* that "own" it. The head pointer never needs to be explicitly adjusted */
+/* but the tail does due to the linked list implementation. */
+/* ------------------------------------------------------------------------ */
+static void ipf_unlinktoken(token)
+ipftoken_t *token;
+{
+
+ if (ipftokentail == &token->ipt_next)
+ ipftokentail = token->ipt_pnext;
+
+ *token->ipt_pnext = token->ipt_next;
+ if (token->ipt_next != NULL)
+ token->ipt_next->ipt_pnext = token->ipt_pnext;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipf_freetoken */
+/* Returns: None. */
+/* Parameters: token(I) - pointer to token structure */
+/* */
+/* This function unlinks a token from the linked list and on the path to */
+/* free'ing the data, it calls the dereference function that is associated */
+/* with the type of data pointed to by the token as it is considered to */
+/* hold a reference to it. */
+/* ------------------------------------------------------------------------ */
+void ipf_freetoken(token)
+ipftoken_t *token;
+{
+ void *data, **datap;
+
+ ipf_unlinktoken(token);
+
+ data = token->ipt_data;
+ datap = &data;
+
+ if ((data != NULL) && (data != (void *)-1)) {
+ switch (token->ipt_type)
+ {
+ case IPFGENITER_IPF :
+ (void) fr_derefrule((frentry_t **)datap);
+ break;
+ case IPFGENITER_IPNAT :
+ WRITE_ENTER(&ipf_nat);
+ fr_ipnatderef((ipnat_t **)datap);
+ RWLOCK_EXIT(&ipf_nat);
+ break;
+ case IPFGENITER_NAT :
+ fr_natderef((nat_t **)datap);
+ break;
+ case IPFGENITER_STATE :
+ fr_statederef((ipstate_t **)datap);
+ break;
+ case IPFGENITER_FRAG :
+#ifdef USE_MUTEXES
+ fr_fragderef((ipfr_t **)datap, &ipf_frag);
+#else
+ fr_fragderef((ipfr_t **)datap);
+#endif
+ break;
+ case IPFGENITER_NATFRAG :
+#ifdef USE_MUTEXES
+ fr_fragderef((ipfr_t **)datap, &ipf_natfrag);
+#else
+ fr_fragderef((ipfr_t **)datap);
+#endif
+ break;
+ case IPFGENITER_HOSTMAP :
+ WRITE_ENTER(&ipf_nat);
+ fr_hostmapdel((hostmap_t **)datap);
+ RWLOCK_EXIT(&ipf_nat);
+ 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;
+ count = it.iri_nrules;
+ /*
+ * 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 (;;) {
+ if (next != NULL) {
+ if (count == 1) {
+ MUTEX_ENTER(&next->fr_lock);
+ next->fr_ref++;
+ MUTEX_EXIT(&next->fr_lock);
+ t->ipt_data = next;
+ }
+ } else {
+ bzero(&zero, sizeof(zero));
+ next = &zero;
+ count = 1;
+ t->ipt_data = NULL;
+ }
+ RWLOCK_EXIT(&ipf_mutex);
+
+ 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) || (error != 0))
+ break;
+
+ count--;
+
+ READ_ENTER(&ipf_mutex);
+ next = next->fr_next;
+ }
+
+ if (fr != NULL) {
+ (void) fr_derefrule(&fr);
+ }
+
+ return error;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: fr_frruleiter */
+/* Returns: int - 0 = success, else error */
+/* Parameters: data(I) - the token type to match */
+/* uid(I) - uid owning the token */
+/* ptr(I) - context pointer for the token */
+/* */
+/* This function serves as a stepping stone between fr_ipf_ioctl and */
+/* ipf_getnextrule. It's role is to find the right token in the kernel for */
+/* the process doing the ioctl and use that to ask for the next rule. */
+/* ------------------------------------------------------------------------ */
+static int ipf_frruleiter(data, uid, ctx)
+void *data, *ctx;
+int uid;
+{
+ ipftoken_t *token;
+ int error;
+
+ token = ipf_findtoken(IPFGENITER_IPF, uid, ctx);
+ if (token != NULL)
+ error = ipf_getnextrule(token, data);
+ else
+ error = EFAULT;
+ RWLOCK_EXIT(&ipf_tokens);
+
+ return error;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: fr_geniter */
+/* Returns: int - 0 = success, else error */
+/* Parameters: token(I) - pointer to ipftoken_t structure */
+/* itp(I) - */
+/* */
+/* ------------------------------------------------------------------------ */
+static int ipf_geniter(token, itp)
+ipftoken_t *token;
+ipfgeniter_t *itp;
+{
+ int error;
+
+ switch (itp->igi_type)
+ {
+ case IPFGENITER_FRAG :
+#ifdef USE_MUTEXES
+ error = fr_nextfrag(token, itp,
+ &ipfr_list, &ipfr_tail, &ipf_frag);
+#else
+ error = fr_nextfrag(token, itp, &ipfr_list, &ipfr_tail);
+#endif
+ break;
+ default :
+ error = EINVAL;
+ break;
+ }
+
+ return error;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: fr_genericiter */
+/* Returns: int - 0 = success, else error */
+/* Parameters: data(I) - the token type to match */
+/* uid(I) - uid owning the token */
+/* ptr(I) - context pointer for the token */
+/* */
+/* ------------------------------------------------------------------------ */
+int ipf_genericiter(data, uid, ctx)
+void *data, *ctx;
+int uid;
+{
+ ipftoken_t *token;
+ ipfgeniter_t iter;
+ int error;
+
+ error = fr_inobj(data, &iter, IPFOBJ_GENITER);
+ if (error != 0)
+ return error;
+
+ token = ipf_findtoken(iter.igi_type, uid, ctx);
+ if (token != NULL) {
+ token->ipt_subtype = iter.igi_type;
+ error = ipf_geniter(token, &iter);
+ } else
+ error = EFAULT;
+ RWLOCK_EXIT(&ipf_tokens);
+
+ return error;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: fr_ipf_ioctl */
+/* Returns: int - 0 = success, else error */
+/* Parameters: data(I) - the token type to match */
+/* cmd(I) - the ioctl command number */
+/* mode(I) - mode flags for the ioctl */
+/* uid(I) - uid owning the token */
+/* ptr(I) - context pointer for the token */
+/* */
+/* This function handles all of the ioctl command that are actually isssued */
+/* to the /dev/ipl device. */
+/* ------------------------------------------------------------------------ */
+int fr_ipf_ioctl(data, cmd, mode, uid, ctx)
+caddr_t data;
+ioctlcmd_t cmd;
+int mode, uid;
+void *ctx;
+{
+ friostat_t fio;
+ int error, tmp;
+ SPL_INT(s);
+
+ switch (cmd)
+ {
+ case SIOCFRENB :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else {
+ error = BCOPYIN(data, &tmp, sizeof(tmp));
+ if (error != 0) {
+ error = EFAULT;
+ break;
+ }
+
+ RWLOCK_EXIT(&ipf_global);
+ WRITE_ENTER(&ipf_global);
+ if (tmp) {
+ if (fr_running > 0)
+ error = 0;
+ else
+ error = ipfattach();
+ if (error == 0)
+ fr_running = 1;
+ else
+ (void) ipfdetach();
+ } else {
+ error = ipfdetach();
+ if (error == 0)
+ fr_running = -1;
+ }
+ }
+ break;
+
+ case SIOCIPFSET :
+ if (!(mode & FWRITE)) {
+ error = EPERM;
+ break;
+ }
+ /* FALLTHRU */
+ case SIOCIPFGETNEXT :
+ case SIOCIPFGET :
+ error = fr_ipftune(cmd, (void *)data);
+ break;
+
+ case SIOCSETFF :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else {
+ error = BCOPYIN(data, &fr_flags, sizeof(fr_flags));
+ if (error != 0)
+ error = EFAULT;
+ }
+ break;
+
+ case SIOCGETFF :
+ error = BCOPYOUT(&fr_flags, data, sizeof(fr_flags));
+ if (error != 0)
+ error = EFAULT;
+ break;
+
+ case SIOCFUNCL :
+ error = fr_resolvefunc((void *)data);
+ break;
+
+ case SIOCINAFR :
+ case SIOCRMAFR :
+ case SIOCADAFR :
+ case SIOCZRLST :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else
+ error = frrequest(IPL_LOGIPF, cmd, 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);
+ error = BCOPYOUT(&fr_active, data, sizeof(fr_active));
+ if (error != 0)
+ error = EFAULT;
+ else
+ fr_active = 1 - fr_active;
+ RWLOCK_EXIT(&ipf_mutex);
+ }
+ break;
+
+ case SIOCGETFS :
+ fr_getstat(&fio);
+ error = fr_outobj((void *)data, &fio, IPFOBJ_IPFSTAT);
+ break;
+
+ case SIOCFRZST :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else
+ error = fr_zerostats(data);
+ break;
+
+ case SIOCIPFFL :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else {
+ error = BCOPYIN(data, &tmp, sizeof(tmp));
+ if (!error) {
+ tmp = frflush(IPL_LOGIPF, 4, tmp);
+ error = BCOPYOUT(&tmp, data, sizeof(tmp));
+ if (error != 0)
+ error = EFAULT;
+ } else
+ error = EFAULT;
+ }
+ break;
+
+#ifdef USE_INET6
+ case SIOCIPFL6 :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else {
+ error = BCOPYIN(data, &tmp, sizeof(tmp));
+ if (!error) {
+ tmp = frflush(IPL_LOGIPF, 6, tmp);
+ error = BCOPYOUT(&tmp, data, sizeof(tmp));
+ if (error != 0)
+ error = EFAULT;
+ } else
+ error = EFAULT;
+ }
+ break;
+#endif
+
+ case SIOCSTLCK :
+ error = BCOPYIN(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 {
+ tmp = ipflog_clear(IPL_LOGIPF);
+ error = BCOPYOUT(&tmp, data, sizeof(tmp));
+ if (error)
+ error = EFAULT;
+ }
+ break;
+#endif /* IPFILTER_LOG */
+
+ case SIOCFRSYN :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else {
+ RWLOCK_EXIT(&ipf_global);
+ WRITE_ENTER(&ipf_global);
+#ifdef MENTAT
+ error = ipfsync();
+#else
+ frsync(NULL);
+ error = 0;
+#endif
+
+ }
+ break;
+
+ case SIOCGFRST :
+ error = fr_outobj((void *)data, fr_fragstats(),
+ IPFOBJ_FRAGSTAT);
+ break;
+
+#ifdef IPFILTER_LOG
+ case FIONREAD :
+ tmp = (int)iplused[IPL_LOGIPF];
+
+ error = BCOPYOUT(&tmp, data, sizeof(tmp));
+ break;
+#endif
+
+ case SIOCIPFITER :
+ SPL_SCHED(s);
+ error = ipf_frruleiter(data, uid, ctx);
+ SPL_X(s);
+ break;
+
+ case SIOCGENITER :
+ SPL_SCHED(s);
+ error = ipf_genericiter(data, uid, ctx);
+ SPL_X(s);
+ break;
+
+ case SIOCIPFDELTOK :
+ SPL_SCHED(s);
+ error = BCOPYIN(data, &tmp, sizeof(tmp));
+ if (error == 0)
+ error = ipf_deltoken(tmp, uid, ctx);
+ SPL_X(s);
+ break;
+
+ default :
+ error = EINVAL;
+ break;
+ }
+
+ return error;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipf_queueflush */
+/* Returns: int - number of entries flushed (0 = none) */
+/* Parameters: deletefn(I) - function to call to delete entry */
+/* ipfqs(I) - top of the list of ipf internal queues */
+/* userqs(I) - top of the list of user defined timeouts */
+/* */
+/* This fucntion gets called when the state/NAT hash tables fill up and we */
+/* need to try a bit harder to free up some space. The algorithm used is */
+/* to look for the oldest entries on each timeout queue and free them if */
+/* they are within the given window we are considering. Where the window */
+/* starts and the steps taken to increase its size depend upon how long ipf */
+/* has been running (fr_ticks.) Anything modified in the last 30 seconds */
+/* is not touched. */
+/* touched */
+/* die fr_ticks 30*1.5 1800*1.5 | 43200*1.5 */
+/* | | | | | | */
+/* future <--+----------+--------+-----------+-----+-----+-----------> past */
+/* now \_int=30s_/ \_int=1hr_/ \_int=12hr */
+/* */
+/* Points to note: */
+/* - tqe_die is the time, in the future, when entries die. */
+/* - tqe_die - fr_ticks is how long left the connection has to live in ipf */
+/* ticks. */
+/* - tqe_touched is when the entry was last used by NAT/state */
+/* - the closer tqe_touched is to fr_ticks, the further tqe_die will be for */
+/* any given timeout queue and vice versa. */
+/* - both tqe_die and tqe_touched increase over time */
+/* - timeout queues are sorted with the highest value of tqe_die at the */
+/* bottom and therefore the smallest values of each are at the top */
+/* */
+/* We start by setting up a maximum range to scan for things to move of */
+/* iend (newest) to istart (oldest) in chunks of "interval". If nothing is */
+/* found in that range, "interval" is adjusted (so long as it isn't 30) and */
+/* we start again with a new value for "iend" and "istart". The downside */
+/* of the current implementation is that it may return removing just 1 entry*/
+/* every time (pathological case) where it could remove more. */
+/* ------------------------------------------------------------------------ */
+int ipf_queueflush(deletefn, ipfqs, userqs)
+ipftq_delete_fn_t deletefn;
+ipftq_t *ipfqs, *userqs;
+{
+ u_long interval, istart, iend;
+ ipftq_t *ifq, *ifqnext;
+ ipftqent_t *tqe, *tqn;
+ int removed;
+
+ /*
+ * NOTE: Use of "* 15 / 10" is required here because if "* 1.5" is
+ * used then the operations are upgraded to floating point
+ * and kernels don't like floating point...
+ */
+ if (fr_ticks > IPF_TTLVAL(43200 * 15 / 10)) {
+ istart = IPF_TTLVAL(86400 * 4);
+ interval = IPF_TTLVAL(43200);
+ } else if (fr_ticks > IPF_TTLVAL(1800 * 15 / 10)) {
+ istart = IPF_TTLVAL(43200);
+ interval = IPF_TTLVAL(1800);
+ } else if (fr_ticks > IPF_TTLVAL(30 * 15 / 10)) {
+ istart = IPF_TTLVAL(1800);
+ interval = IPF_TTLVAL(30);
+ } else {
+ return 0;
+ }
+ if (istart > fr_ticks) {
+ if (fr_ticks - interval < interval)
+ istart = interval;
+ else
+ istart = (fr_ticks / interval) * interval;
+ }
+
+ iend = fr_ticks - interval;
+ removed = 0;
+
+ for (;;) {
+ u_long try;
+
+ try = fr_ticks - istart;
+
+ for (ifq = ipfqs; ifq != NULL; ifq = ifq->ifq_next) {
+ for (tqn = ifq->ifq_head; ((tqe = tqn) != NULL); ) {
+ if (try < tqe->tqe_touched)
+ break;
+ tqn = tqe->tqe_next;
+ if ((*deletefn)(tqe->tqe_parent) == 0)
+ removed++;
+ }
+ }
+
+ for (ifq = userqs; ifq != NULL; ifq = ifqnext) {
+ ifqnext = ifq->ifq_next;
+
+ for (tqn = ifq->ifq_head; ((tqe = tqn) != NULL); ) {
+ if (try < tqe->tqe_touched)
+ break;
+ tqn = tqe->tqe_next;
+ if ((*deletefn)(tqe->tqe_parent) == 0)
+ removed++;
+ }
+ }
+
+ if (try >= iend) {
+ if (removed > 0)
+ break;
+ if (interval == IPF_TTLVAL(43200)) {
+ interval = IPF_TTLVAL(1800);
+ } else if (interval == IPF_TTLVAL(1800)) {
+ interval = IPF_TTLVAL(30);
+ } else {
+ break;
+ }
+ if (interval >= fr_ticks)
+ break;
+
+ iend = fr_ticks - interval;
+ }
+ istart -= interval;
+ }
+
+ return removed;
+}
Index: ip_irc_pxy.c
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_irc_pxy.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_irc_pxy.c -L sys/contrib/ipfilter/netinet/ip_irc_pxy.c -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_irc_pxy.c
+++ sys/contrib/ipfilter/netinet/ip_irc_pxy.c
@@ -1,11 +1,9 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_irc_pxy.c,v 1.1.1.1 2005/04/25 18:15:19 darrenr 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.4 2005/02/04 10:22:55 darrenr Exp
+ * $Id: ip_irc_pxy.c,v 2.39.2.6 2006/07/14 06:12:14 darrenr Exp $
*/
#define IPF_IRC_PROXY
@@ -50,7 +48,7 @@
}
-char *ippr_irc_dcctypes[] = {
+const char *ippr_irc_dcctypes[] = {
"CHAT ", /* CHAT chat ipnumber portnumber */
"SEND ", /* SEND filename ipnumber portnumber */
"MOVE ",
@@ -417,7 +415,7 @@
(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;
}
Index: ip_ipsec_pxy.c
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_ipsec_pxy.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_ipsec_pxy.c -L sys/contrib/ipfilter/netinet/ip_ipsec_pxy.c -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_ipsec_pxy.c
+++ sys/contrib/ipfilter/netinet/ip_ipsec_pxy.c
@@ -1,5 +1,3 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_ipsec_pxy.c,v 1.1.1.2 2005/04/25 18:15:18 darrenr Exp $ */
-
/*
* Copyright (C) 2001-2003 by Darren Reed
*
@@ -8,7 +6,7 @@
* Simple ISAKMP transparent proxy for in-kernel use. For use with the NAT
* code.
*
- * Id: ip_ipsec_pxy.c,v 2.20.2.6 2005/03/28 10:47:53 darrenr Exp
+ * $Id: ip_ipsec_pxy.c,v 2.20.2.8 2006/07/14 06:12:14 darrenr Exp $
*
*/
#define IPF_IPSEC_PROXY
@@ -96,8 +94,8 @@
mb_t *m;
ip_t *ip;
+ off = fin->fin_plen - fin->fin_dlen + fin->fin_ipoff;
bzero(ipsec_buffer, sizeof(ipsec_buffer));
- off = fin->fin_hlen + sizeof(udphdr_t);
ip = fin->fin_ip;
m = fin->fin_m;
@@ -179,7 +177,7 @@
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;
@@ -258,7 +256,7 @@
&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;
}
@@ -287,8 +285,8 @@
if ((fin->fin_dlen < sizeof(cookies)) || (fin->fin_flx & FI_FRAG))
return -1;
+ off = fin->fin_plen - fin->fin_dlen + fin->fin_ipoff;
ipsec = aps->aps_data;
- off = fin->fin_hlen + sizeof(udphdr_t);
m = fin->fin_m;
COPYDATA(m, off, sizeof(cookies), (char *)cookies);
Index: ip_auth.h
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_auth.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_auth.h -L sys/contrib/ipfilter/netinet/ip_auth.h -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_auth.h
+++ sys/contrib/ipfilter/netinet/ip_auth.h
@@ -1,12 +1,12 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_auth.h,v 1.14 2005/04/25 18:43:13 darrenr Exp $ */
+/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_auth.h,v 1.16 2007/06/04 02:54:35 darrenr Exp $ */
/*
* Copyright (C) 1997-2001 by Darren Reed & Guido Van Rooij.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
- * $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_auth.h,v 1.14 2005/04/25 18:43:13 darrenr Exp $
- * Id: ip_auth.h,v 2.16 2003/07/25 12:29:56 darrenr Exp
+ * $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_auth.h,v 1.16 2007/06/04 02:54:35 darrenr Exp $
+ * Id: ip_auth.h,v 2.16.2.2 2006/03/16 06:45:49 darrenr Exp $
*
*/
#ifndef __IP_AUTH_H__
@@ -23,13 +23,16 @@
char *fra_buf;
#ifdef MENTAT
queue_t *fra_q;
+ mb_t *fra_m;
#endif
} frauth_t;
typedef struct frauthent {
struct frentry fae_fr;
struct frauthent *fae_next;
+ struct frauthent **fae_pnext;
u_long fae_age;
+ int fae_ref;
} frauthent_t;
typedef struct fr_authstat {
@@ -62,6 +65,7 @@
extern mb_t **fr_authpkts;
extern int fr_newauth __P((mb_t *, fr_info_t *));
extern int fr_preauthcmd __P((ioctlcmd_t, frentry_t *, frentry_t **));
-extern int fr_auth_ioctl __P((caddr_t, ioctlcmd_t, int));
+extern int fr_auth_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *));
+extern int fr_auth_waiting __P((void));
#endif /* __IP_AUTH_H__ */
Index: ip_pptp_pxy.c
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_pptp_pxy.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_pptp_pxy.c -L sys/contrib/ipfilter/netinet/ip_pptp_pxy.c -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_pptp_pxy.c
+++ sys/contrib/ipfilter/netinet/ip_pptp_pxy.c
@@ -1,12 +1,10 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_pptp_pxy.c,v 1.1.1.1 2005/04/25 18:15:30 darrenr Exp $ */
-
/*
* Copyright (C) 2002-2003 by Darren Reed
*
* Simple PPTP transparent proxy for in-kernel use. For use with the NAT
* code.
*
- * Id: ip_pptp_pxy.c,v 2.10.2.9 2005/03/16 18:17:34 darrenr Exp
+ * $Id: ip_pptp_pxy.c,v 2.10.2.15 2006/10/31 12:11:23 darrenr Exp $
*
*/
#define IPF_PPTP_PROXY
@@ -80,6 +78,9 @@
/*
* 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;
@@ -89,15 +90,14 @@
pptp_pxy_t *pptp;
ipnat_t *ipn;
ip_t *ip;
- int off;
ip = fin->fin_ip;
- off = fin->fin_hlen + sizeof(udphdr_t);
if (nat_outlookup(fin, 0, IPPROTO_GRE, nat->nat_inip,
ip->ip_dst) != NULL) {
if (ippr_pptp_debug > 0)
- printf("ippr_pptp_new: GRE session already exists\n");
+ printf("ippr_pptp_new: GRE session %s\n",
+ "already exists");
return -1;
}
@@ -105,7 +105,8 @@
KMALLOCS(aps->aps_data, pptp_pxy_t *, sizeof(*pptp));
if (aps->aps_data == NULL) {
if (ippr_pptp_debug > 0)
- printf("ippr_pptp_new: malloc for aps_data failed\n");
+ printf("ippr_pptp_new: malloc for aps_data %s\n",
+ "failed");
return -1;
}
@@ -212,15 +213,17 @@
RWLOCK_EXIT(&ipf_state);
} else {
RWLOCK_EXIT(&ipf_state);
- if (nat->nat_dir == NAT_INBOUND)
- fi.fin_fi.fi_daddr = nat2->nat_inip.s_addr;
- else
- fi.fin_fi.fi_saddr = nat2->nat_inip.s_addr;
+ if (nat2 != NULL) {
+ if (nat->nat_dir == NAT_INBOUND)
+ fi.fin_fi.fi_daddr = nat2->nat_inip.s_addr;
+ else
+ fi.fin_fi.fi_saddr = nat2->nat_inip.s_addr;
+ }
fi.fin_ifp = NULL;
pptp->pptp_state = fr_addstate(&fi, &pptp->pptp_state,
0);
if (fi.fin_state != NULL)
- fr_statederef(&fi, (ipstate_t **)&fi.fin_state);
+ fr_statederef((ipstate_t **)&fi.fin_state);
}
ip->ip_p = p;
return;
@@ -238,7 +241,7 @@
pptp_pxy_t *pptp;
int rev;
{
- static char *funcname = "ippr_pptp_nextmessage";
+ static const char *funcname = "ippr_pptp_nextmessage";
pptp_side_t *pptps;
u_32_t start, end;
pptp_hdr_t *hdr;
Index: ip_sync.h
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_sync.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_sync.h -L sys/contrib/ipfilter/netinet/ip_sync.h -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_sync.h
+++ sys/contrib/ipfilter/netinet/ip_sync.h
@@ -1,12 +1,10 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_sync.h,v 1.1.1.1 2005/04/25 18:15:41 darrenr Exp $ */
-
/*
* Copyright (C) 1993-2001 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* @(#)ip_fil.h 1.35 6/5/96
- * Id: ip_sync.h,v 2.11.2.2 2004/11/04 19:29:07 darrenr Exp
+ * $Id: ip_sync.h,v 2.11.2.4 2006/07/14 06:12:20 darrenr Exp $
*/
#ifndef __IP_SYNC_H__
@@ -104,14 +102,16 @@
extern synclogent_t synclog[SYNCLOG_SZ];
-extern int fr_sync_ioctl __P((caddr_t, ioctlcmd_t, int));
-extern synclist_t *ipfsync_new __P((int, fr_info_t *, void *));
-extern void ipfsync_del __P((synclist_t *));
-extern void ipfsync_update __P((int, fr_info_t *, synclist_t *));
-extern int ipfsync_init __P((void));
-extern int ipfsync_nat __P((synchdr_t *sp, void *data));
-extern int ipfsync_state __P((synchdr_t *sp, void *data));
-extern int ipfsync_read __P((struct uio *uio));
-extern int ipfsync_write __P((struct uio *uio));
+extern int fr_sync_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *));
+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 */
Index: ip_lookup.c
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_lookup.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_lookup.c -L sys/contrib/ipfilter/netinet/ip_lookup.c -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_lookup.c
+++ sys/contrib/ipfilter/netinet/ip_lookup.c
@@ -1,5 +1,3 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_lookup.c,v 1.1.1.1 2005/04/25 18:15:23 darrenr Exp $ */
-
/*
* Copyright (C) 2002-2003 by Darren Reed.
*
@@ -35,10 +33,7 @@
# undef _KERNEL
#endif
#include <sys/socket.h>
-#if (defined(__osf__) || defined(__hpux) || defined(__sgi)) && defined(_KERNEL)
-# ifdef __osf__
-# include <net/radix.h>
-# endif
+#if (defined(__osf__) || defined(AIX) || defined(__hpux) || defined(__sgi)) && defined(_KERNEL)
# include "radix_ipf_local.h"
# define _RADIX_H_
#endif
@@ -63,7 +58,7 @@
/* END OF INCLUDES */
#if !defined(lint)
-static const char rcsid[] = "@(#)Id: ip_lookup.c,v 2.35.2.5 2004/07/06 11:16:25 darrenr Exp";
+static const char rcsid[] = "@(#)$Id: ip_lookup.c,v 2.35.2.19 2007/10/11 09:05:51 darrenr Exp $";
#endif
#ifdef IPFILTER_LOOKUP
@@ -75,6 +70,8 @@
static int iplookup_deltable __P((caddr_t));
static int iplookup_stats __P((caddr_t));
static int iplookup_flush __P((caddr_t));
+static int iplookup_iterate __P((void *, int, void *));
+static int iplookup_deltok __P((void *, int, void *));
/* ------------------------------------------------------------------------ */
@@ -131,15 +128,14 @@
/* 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;
-# if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL)
- int s;
-# endif
+ SPL_INT(s);
mode = mode; /* LINT */
@@ -186,6 +182,14 @@
RWLOCK_EXIT(&ip_poolrw);
break;
+ case SIOCLOOKUPITER :
+ err = iplookup_iterate(data, uid, ctx);
+ break;
+
+ case SIOCIPFDELTOK :
+ err = iplookup_deltok(data, uid, ctx);
+ break;
+
default :
err = EINVAL;
break;
@@ -214,8 +218,13 @@
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)
@@ -284,8 +293,12 @@
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';
@@ -345,8 +358,12 @@
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';
@@ -370,6 +387,17 @@
err = EINVAL;
break;
}
+
+ /*
+ * For anonymous pools, copy back the operation struct because in the
+ * case of success it will contain the new table's name.
+ */
+ if ((err == 0) && ((op.iplo_arg & LOOKUP_ANON) != 0)) {
+ err = BCOPYOUT(&op, data, sizeof(op));
+ if (err != 0)
+ err = EFAULT;
+ }
+
return err;
}
@@ -388,11 +416,14 @@
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
@@ -401,11 +432,11 @@
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 :
@@ -429,8 +460,12 @@
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)
{
@@ -464,15 +499,16 @@
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;
@@ -489,12 +525,23 @@
if (err == 0) {
flush.iplf_count = num;
- err = COPYOUT(&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;
@@ -517,13 +564,131 @@
}
+/* ------------------------------------------------------------------------ */
+/* Function: iplookup_iterate */
+/* Returns: int - 0 = success, else error */
+/* Parameters: data(I) - pointer to data from ioctl call */
+/* uid(I) - uid of caller */
+/* ctx(I) - pointer to give the uid context */
+/* */
+/* Decodes ioctl request to step through either hash tables or pools. */
+/* ------------------------------------------------------------------------ */
+static int iplookup_iterate(data, uid, ctx)
+void *data;
+int uid;
+void *ctx;
+{
+ ipflookupiter_t iter;
+ ipftoken_t *token;
+ int err;
+ SPL_INT(s);
+
+ err = fr_inobj(data, &iter, IPFOBJ_LOOKUPITER);
+ if (err != 0)
+ return err;
+
+ if (iter.ili_unit > IPL_LOGMAX)
+ return EINVAL;
+
+ if (iter.ili_ival != IPFGENITER_LOOKUP)
+ return EINVAL;
+
+ SPL_SCHED(s);
+ token = ipf_findtoken(iter.ili_key, uid, ctx);
+ if (token == NULL) {
+ RWLOCK_EXIT(&ipf_tokens);
+ SPL_X(s);
+ 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);
+ SPL_X(s);
+
+ 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;
+ }
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: iplookup_deltok */
+/* Returns: int - 0 = success, else error */
+/* Parameters: data(I) - pointer to data from ioctl call */
+/* uid(I) - uid of caller */
+/* ctx(I) - pointer to give the uid context */
+/* */
+/* Deletes the token identified by the combination of (type,uid,ctx) */
+/* "key" is a combination of the table type, iterator type and the unit for */
+/* which the token was being used. */
+/* ------------------------------------------------------------------------ */
+static int iplookup_deltok(data, uid, ctx)
+void *data;
+int uid;
+void *ctx;
+{
+ int error, key;
+ SPL_INT(s);
+
+ SPL_SCHED(s);
+ error = BCOPYIN(data, &key, sizeof(key));
+ if (error == 0)
+ error = ipf_deltoken(key, uid, ctx);
+ SPL_X(s);
+ return error;
+}
+
+
#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;
}
Index: ip_proxy.c
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_proxy.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_proxy.c -L sys/contrib/ipfilter/netinet/ip_proxy.c -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_proxy.c
+++ sys/contrib/ipfilter/netinet/ip_proxy.c
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_proxy.c,v 1.25 2005/04/27 05:53:12 darrenr Exp $ */
+/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_proxy.c,v 1.29.2.1 2007/10/31 05:00:38 darrenr Exp $ */
/*
* Copyright (C) 1997-2003 by Darren Reed.
@@ -16,7 +16,9 @@
#include <sys/param.h>
#include <sys/time.h>
#include <sys/file.h>
-#include <sys/fcntl.h>
+#if !defined(AIX)
+# include <sys/fcntl.h>
+#endif
#if !defined(_KERNEL) && !defined(__KERNEL__)
# include <stdio.h>
# include <string.h>
@@ -35,7 +37,8 @@
#include <sys/socket.h>
#if defined(_KERNEL)
# if !defined(__NetBSD__) && !defined(sun) && !defined(__osf__) && \
- !defined(__OpenBSD__) && !defined(__hpux) && !defined(__sgi)
+ !defined(__OpenBSD__) && !defined(__hpux) && !defined(__sgi) && \
+ !defined(AIX)
# include <sys/ctype.h>
# endif
# include <sys/systm.h>
@@ -93,12 +96,6 @@
#if defined(_KERNEL)
# include "netinet/ip_irc_pxy.c"
# include "netinet/ip_raudio_pxy.c"
-# ifdef IPFILTER_H323
-# include "netinet/ip_h323_pxy.c"
-# endif
-# ifdef IPFILTER_PRO
-# include "netinet/ip_msnrpc_pxy.c"
-# endif
# include "netinet/ip_netbios_pxy.c"
#endif
#include "netinet/ip_ipsec_pxy.c"
@@ -107,7 +104,7 @@
/* END OF INCLUDES */
#if !defined(lint)
-static const char rcsid[] = "@(#)Id: ip_proxy.c,v 2.62.2.12 2005/03/03 14:28:24 darrenr Exp";
+static const char rcsid[] = "@(#)$Id: ip_proxy.c,v 2.62.2.21 2007/06/02 21:22:28 darrenr Exp $";
#endif
static int appr_fixseqack __P((fr_info_t *, ip_t *, ap_session_t *, int ));
@@ -125,7 +122,7 @@
aproxy_t ap_proxies[] = {
#ifdef IPF_FTP_PROXY
{ NULL, "ftp", (char)IPPROTO_TCP, 0, 0, ippr_ftp_init, ippr_ftp_fini,
- ippr_ftp_new, NULL, ippr_ftp_in, ippr_ftp_out, NULL },
+ ippr_ftp_new, NULL, ippr_ftp_in, ippr_ftp_out, NULL, NULL },
#endif
#ifdef IPF_IRC_PROXY
{ NULL, "irc", (char)IPPROTO_TCP, 0, 0, ippr_irc_init, ippr_irc_fini,
@@ -159,9 +156,9 @@
#endif
#ifdef IPF_H323_PROXY
{ NULL, "h323", (char)IPPROTO_TCP, 0, 0, ippr_h323_init, ippr_h323_fini,
- ippr_h323_new, ippr_h323_del, ippr_h323_in, NULL, NULL },
+ ippr_h323_new, ippr_h323_del, ippr_h323_in, NULL, NULL, NULL },
{ NULL, "h245", (char)IPPROTO_TCP, 0, 0, NULL, NULL,
- ippr_h245_new, NULL, NULL, ippr_h245_out, NULL },
+ ippr_h245_new, NULL, NULL, ippr_h245_out, NULL, NULL },
#endif
#ifdef IPF_RPCB_PROXY
# if 0
@@ -173,7 +170,7 @@
ippr_rpcb_init, ippr_rpcb_fini, ippr_rpcb_new, ippr_rpcb_del,
ippr_rpcb_in, ippr_rpcb_out, NULL, NULL },
#endif
- { NULL, "", '\0', 0, 0, NULL, NULL, NULL, NULL }
+ { NULL, "", '\0', 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
/*
@@ -195,7 +192,7 @@
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,13 +289,14 @@
}
-int appr_ioctl(data, cmd, mode)
+int appr_ioctl(data, cmd, mode, ctx)
caddr_t data;
ioctlcmd_t cmd;
int mode;
+void *ctx;
{
ap_ctl_t ctl;
- caddr_t ptr;
+ u_char *ptr;
int error;
mode = mode; /* LINT */
@@ -306,11 +304,13 @@
switch (cmd)
{
case SIOCPROXY :
- BCOPYIN(data, &ctl, sizeof(ctl));
+ error = BCOPYIN(data, &ctl, sizeof(ctl));
+ if (error != 0)
+ return EFAULT;
ptr = NULL;
if (ctl.apc_dsize > 0) {
- KMALLOCS(ptr, caddr_t, ctl.apc_dsize);
+ KMALLOCS(ptr, u_char *, ctl.apc_dsize);
if (ptr == NULL)
error = ENOMEM;
else {
@@ -327,8 +327,7 @@
if (error == 0)
error = appr_ctl(&ctl);
- if ((ctl.apc_dsize > 0) && (ptr != NULL) &&
- (ctl.apc_data == ptr)) {
+ if (ptr != NULL) {
KFREES(ptr, ctl.apc_dsize);
}
break;
@@ -567,8 +566,8 @@
if (err != 0) {
short adjlen = err & 0xffff;
- s1 = LONG_SUM(ip->ip_len - adjlen);
- s2 = LONG_SUM(ip->ip_len);
+ s1 = LONG_SUM(fin->fin_plen - adjlen);
+ s2 = LONG_SUM(fin->fin_plen);
CALC_SUMD(s1, s2, sd);
fix_outcksum(fin, &ip->ip_sum, sd);
}
@@ -588,19 +587,23 @@
#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
if (dosum)
tcp->th_sum = fr_cksum(fin->fin_qfm, ip,
- IPPROTO_TCP, tcp);
+ IPPROTO_TCP, tcp,
+ fin->fin_plen);
#else
tcp->th_sum = fr_cksum(fin->fin_m, ip,
- IPPROTO_TCP, tcp);
+ IPPROTO_TCP, tcp,
+ fin->fin_plen);
#endif
} else if ((udp != NULL) && (udp->uh_sum != 0)) {
#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
if (dosum)
udp->uh_sum = fr_cksum(fin->fin_qfm, ip,
- IPPROTO_UDP, udp);
+ IPPROTO_UDP, udp,
+ fin->fin_plen);
#else
udp->uh_sum = fr_cksum(fin->fin_m, ip,
- IPPROTO_UDP, udp);
+ IPPROTO_UDP, udp,
+ fin->fin_plen);
#endif
}
aps->aps_bytes += fin->fin_plen;
@@ -691,9 +694,9 @@
tcp = (tcphdr_t *)fin->fin_dp;
out = fin->fin_out;
/*
- * ip_len has already been adjusted by 'inc'.
+ * fin->fin_plen has already been adjusted by 'inc'.
*/
- nlen = ip->ip_len;
+ nlen = fin->fin_plen;
nlen -= (IP_HL(ip) << 2) + (TCP_OFF(tcp) << 2);
inc2 = inc;
@@ -814,7 +817,7 @@
if (ipf_proxy_debug > 8)
printf("appr_fixseqack: seq %x ack %x\n",
- ntohl(tcp->th_seq), ntohl(tcp->th_ack));
+ (u_32_t)ntohl(tcp->th_seq), (u_32_t)ntohl(tcp->th_ack));
return ch ? 2 : 0;
}
Index: ip_nat.c
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_nat.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_nat.c -L sys/contrib/ipfilter/netinet/ip_nat.c -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_nat.c
+++ sys/contrib/ipfilter/netinet/ip_nat.c
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_nat.c,v 1.39 2005/04/27 03:48:09 darrenr Exp $ */
+/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_nat.c,v 1.42.2.1 2007/10/31 05:00:38 darrenr Exp $ */
/*
* Copyright (C) 1995-2003 by Darren Reed.
@@ -16,9 +16,17 @@
#include <sys/param.h>
#include <sys/time.h>
#include <sys/file.h>
+#if defined(_KERNEL) && defined(__NetBSD_Version__) && \
+ (__NetBSD_Version__ >= 399002000)
+# include <sys/kauth.h>
+#endif
#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \
defined(_KERNEL)
-# include "opt_ipfilter_log.h"
+#if defined(__NetBSD_Version__) && (__NetBSD_Version__ < 399001400)
+# include "opt_ipfilter_log.h"
+# else
+# include "opt_ipfilter.h"
+# endif
#endif
#if !defined(_KERNEL)
# include <stdio.h>
@@ -37,7 +45,9 @@
#else
# include <sys/ioctl.h>
#endif
-#include <sys/fcntl.h>
+#if !defined(AIX)
+# include <sys/fcntl.h>
+#endif
#if !defined(linux)
# include <sys/protosw.h>
#endif
@@ -107,8 +117,8 @@
#if !defined(lint)
static const char sccsid[] = "@(#)ip_nat.c 1.11 6/5/96 (C) 1995 Darren Reed";
-static const char rcsid[] = "@(#)$FreeBSD: src/sys/contrib/ipfilter/netinet/ip_nat.c,v 1.39 2005/04/27 03:48:09 darrenr Exp $";
-/* static const char rcsid[] = "@(#)Id: ip_nat.c,v 2.195.2.38 2005/03/28 11:09:54 darrenr Exp"; */
+static const char rcsid[] = "@(#)$FreeBSD: src/sys/contrib/ipfilter/netinet/ip_nat.c,v 1.42.2.1 2007/10/31 05:00:38 darrenr Exp $";
+/* static const char rcsid[] = "@(#)$Id: ip_nat.c,v 2.195.2.102 2007/10/16 10:08:10 darrenr Exp $"; */
#endif
@@ -146,14 +156,17 @@
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
@@ -166,36 +179,39 @@
natstat_t nat_stats;
int fr_nat_lock = 0;
int fr_nat_init = 0;
-#if SOLARIS
+#if SOLARIS && !defined(_INET_IP_STACK_H)
extern int pfil_delayed_copy;
#endif
+static int nat_flush_entry __P((void *));
static int nat_flushtable __P((void));
static int nat_clearlist __P((void));
static void nat_addnat __P((struct ipnat *));
static void nat_addrdr __P((struct ipnat *));
-static void nat_delete __P((struct nat *, int));
static void nat_delrdr __P((struct ipnat *));
static void nat_delnat __P((struct ipnat *));
static int fr_natgetent __P((caddr_t));
static int fr_natgetsz __P((caddr_t));
static int fr_natputent __P((caddr_t, int));
+static int nat_extraflush __P((int));
+static int nat_gettable __P((char *));
static void nat_tabmove __P((nat_t *));
static int nat_match __P((fr_info_t *, ipnat_t *));
static INLINE int nat_newmap __P((fr_info_t *, nat_t *, natinfo_t *));
static INLINE int nat_newrdr __P((fr_info_t *, nat_t *, natinfo_t *));
static hostmap_t *nat_hostmap __P((ipnat_t *, struct in_addr,
struct in_addr, struct in_addr, u_32_t));
-static void nat_hostmapdel __P((struct hostmap *));
-static INLINE int nat_icmpquerytype4 __P((int));
+static int nat_icmpquerytype4 __P((int));
static int nat_siocaddnat __P((ipnat_t *, ipnat_t **, int));
static void nat_siocdelnat __P((ipnat_t *, ipnat_t **, int));
-static INLINE int nat_finalise __P((fr_info_t *, nat_t *, natinfo_t *,
+static int nat_finalise __P((fr_info_t *, nat_t *, natinfo_t *,
tcphdr_t *, nat_t **, int));
-static void nat_resolverule __P((ipnat_t *));
+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 INLINE int nat_wildok __P((nat_t *, int, int, int, int));
+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 *));
/* ------------------------------------------------------------------------ */
@@ -233,11 +249,14 @@
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));
@@ -437,7 +456,7 @@
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)) &&
@@ -451,11 +470,16 @@
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;
@@ -468,19 +492,27 @@
/* ------------------------------------------------------------------------ */
-/* 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;
@@ -610,18 +642,30 @@
/* */
/* Processes an ioctl call made to operate on the IP Filter NAT device. */
/* ------------------------------------------------------------------------ */
-int fr_nat_ioctl(data, cmd, mode)
+int fr_nat_ioctl(data, cmd, mode, uid, ctx)
ioctlcmd_t cmd;
caddr_t data;
-int mode;
+int mode, uid;
+void *ctx;
{
ipnat_t *nat, *nt, *n = NULL, **np = NULL;
int error = 0, ret, arg, getlock;
ipnat_t natd;
+ SPL_INT(s);
#if (BSD >= 199306) && defined(_KERNEL)
- if ((securelevel >= 3) && (mode & FWRITE))
+# if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 399002000)
+ if ((mode & FWRITE) &&
+ kauth_authorize_network(curlwp->l_cred, KAUTH_NETWORK_FIREWALL,
+ KAUTH_REQ_NETWORK_FIREWALL_FW,
+ NULL, NULL, NULL)) {
return EPERM;
+ }
+# else
+ if ((securelevel >= 3) && (mode & FWRITE)) {
+ return EPERM;
+ }
+# endif
#endif
#if defined(__osf__) && defined(_KERNEL)
@@ -644,9 +688,6 @@
} else {
error = fr_inobj(data, &natd, IPFOBJ_IPNAT);
}
-
- } else if (cmd == (ioctlcmd_t)SIOCIPFFL) { /* SIOCFLNAT & SIOCCNATL */
- BCOPYIN(data, &arg, sizeof(arg));
}
if (error != 0)
@@ -668,9 +709,13 @@
}
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)
@@ -684,25 +729,37 @@
error = EPERM;
else {
tmp = ipflog_clear(IPL_LOGNAT);
- BCOPYOUT((char *)&tmp, (char *)data, sizeof(tmp));
+ error = BCOPYOUT((char *)&tmp, (char *)data,
+ sizeof(tmp));
+ if (error != 0)
+ error = EFAULT;
}
break;
}
+
case SIOCSETLG :
if (!(mode & FWRITE))
error = EPERM;
else {
- BCOPYIN((char *)data, (char *)&nat_logging,
- sizeof(nat_logging));
+ error = BCOPYIN((char *)data, (char *)&nat_logging,
+ sizeof(nat_logging));
+ if (error != 0)
+ error = EFAULT;
}
break;
+
case SIOCGETLG :
- BCOPYOUT((char *)&nat_logging, (char *)data,
- sizeof(nat_logging));
+ error = BCOPYOUT((char *)&nat_logging, (char *)data,
+ sizeof(nat_logging));
+ if (error != 0)
+ error = EFAULT;
break;
+
case FIONREAD :
arg = iplused[IPL_LOGNAT];
- BCOPYOUT(&arg, data, sizeof(arg));
+ error = BCOPYOUT(&arg, data, sizeof(arg));
+ if (error != 0)
+ error = EFAULT;
break;
#endif
case SIOCADNAT :
@@ -723,6 +780,7 @@
if (error == 0)
nt = NULL;
break;
+
case SIOCRMNAT :
if (!(mode & FWRITE)) {
error = EPERM;
@@ -740,11 +798,13 @@
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;
@@ -752,8 +812,10 @@
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;
@@ -774,6 +836,7 @@
}
break;
}
+
case SIOCIPFFL : /* old SIOCFLNAT & SIOCCNATL */
if (!(mode & FWRITE)) {
error = EPERM;
@@ -782,33 +845,47 @@
if (getlock) {
WRITE_ENTER(&ipf_nat);
}
- error = 0;
- if (arg == 0)
- ret = nat_flushtable();
- else if (arg == 1)
- ret = nat_clearlist();
- else
- error = EINVAL;
+
+ error = BCOPYIN(data, &arg, sizeof(arg));
+ if (error != 0)
+ error = EFAULT;
+ else {
+ if (arg == 0)
+ ret = nat_flushtable();
+ else if (arg == 1)
+ ret = nat_clearlist();
+ else
+ ret = nat_extraflush(arg);
+ }
+
if (getlock) {
RWLOCK_EXIT(&ipf_nat);
}
if (error == 0) {
- BCOPYOUT(&ret, data, sizeof(ret));
+ error = BCOPYOUT(&ret, data, sizeof(ret));
}
break;
+
case SIOCPROXY :
- error = appr_ioctl(data, cmd, mode);
+ error = appr_ioctl(data, cmd, mode, ctx);
break;
+
case SIOCSTLCK :
- fr_lock(data, &fr_nat_lock);
+ if (!(mode & FWRITE)) {
+ error = EPERM;
+ } else {
+ error = fr_lock(data, &fr_nat_lock);
+ }
break;
+
case SIOCSTPUT :
- if (fr_nat_lock) {
+ if ((mode & FWRITE) != 0) {
error = fr_natputent(data, getlock);
} else {
error = EACCES;
}
break;
+
case SIOCSTGSZ :
if (fr_nat_lock) {
if (getlock) {
@@ -821,6 +898,7 @@
} else
error = EACCES;
break;
+
case SIOCSTGET :
if (fr_nat_lock) {
if (getlock) {
@@ -833,12 +911,50 @@
} else
error = EACCES;
break;
+
+ case SIOCGENITER :
+ {
+ ipfgeniter_t iter;
+ ipftoken_t *token;
+
+ SPL_SCHED(s);
+ error = fr_inobj(data, &iter, IPFOBJ_GENITER);
+ if (error == 0) {
+ token = ipf_findtoken(iter.igi_type, uid, ctx);
+ if (token != NULL) {
+ error = nat_iterator(token, &iter);
+ }
+ RWLOCK_EXIT(&ipf_tokens);
+ }
+ SPL_X(s);
+ break;
+ }
+
+ case SIOCIPFDELTOK :
+ error = BCOPYIN((caddr_t)data, (caddr_t)&arg, sizeof(arg));
+ if (error == 0) {
+ SPL_SCHED(s);
+ error = ipf_deltoken(arg, uid, ctx);
+ SPL_X(s);
+ } else {
+ error = EFAULT;
+ }
+ break;
+
+ case SIOCGTQTAB :
+ error = fr_outobj(data, nat_tqb, IPFOBJ_STATETQTAB);
+ break;
+
+ case SIOCGTABL :
+ error = nat_gettable(data);
+ break;
+
default :
error = EINVAL;
break;
}
done:
- if (nt)
+ if (nt != NULL)
KFREE(nt);
return error;
}
@@ -862,11 +978,8 @@
{
int error = 0, i, j;
- nat_resolverule(n);
- if (n->in_plabel[0] != '\0') {
- if (n->in_apr == NULL)
- return ENOENT;
- }
+ if (nat_resolverule(n) != 0)
+ return ENOENT;
if ((n->in_age[0] == 0) && (n->in_age[1] != 0))
return EINVAL;
@@ -969,9 +1082,11 @@
n->in_flags &= ~IPN_NOTSRC;
nat_addnat(n);
}
+ MUTEX_INIT(&n->in_lock, "ipnat rule lock");
+
n = NULL;
nat_stats.ns_rules++;
-#if SOLARIS
+#if SOLARIS && !defined(_INET_IP_STACK_H)
pfil_delayed_copy = 0;
#endif
if (getlock) {
@@ -991,7 +1106,7 @@
/* from information passed to the kernel, then add it to the appropriate */
/* NAT rule table(s). */
/* ------------------------------------------------------------------------ */
-static void nat_resolverule(n)
+static int nat_resolverule(n)
ipnat_t *n;
{
n->in_ifnames[0][LIFNAMSIZ - 1] = '\0';
@@ -1002,12 +1117,15 @@
(void) strncpy(n->in_ifnames[1], n->in_ifnames[0], LIFNAMSIZ);
n->in_ifps[1] = n->in_ifps[0];
} else {
- n->in_ifps[1] = fr_resolvenic(n->in_ifnames[0], 4);
+ n->in_ifps[1] = fr_resolvenic(n->in_ifnames[1], 4);
}
if (n->in_plabel[0] != '\0') {
n->in_apr = appr_lookup(n->in_p, n->in_plabel);
+ if (n->in_apr == NULL)
+ return -1;
}
+ return 0;
}
@@ -1056,9 +1174,10 @@
if (n->in_use == 0) {
if (n->in_apr)
appr_free(n->in_apr);
+ MUTEX_DESTROY(&n->in_lock);
KFREE(n);
nat_stats.ns_rules--;
-#if SOLARIS
+#if SOLARIS && !defined(_INET_IP_STACK_H)
if (nat_stats.ns_rules == 0)
pfil_delayed_copy = 1;
#endif
@@ -1090,7 +1209,8 @@
nat_t *nat, *n;
natget_t ng;
- BCOPYIN(data, &ng, sizeof(ng));
+ if (BCOPYIN(data, &ng, sizeof(ng)) != 0)
+ return EFAULT;
nat = ng.ng_ptr;
if (!nat) {
@@ -1100,7 +1220,8 @@
* Empty list so the size returned is 0. Simple.
*/
if (nat == NULL) {
- BCOPYOUT(&ng, data, sizeof(ng));
+ if (BCOPYOUT(&ng, data, sizeof(ng)) != 0)
+ return EFAULT;
return 0;
}
} else {
@@ -1127,7 +1248,8 @@
ng.ng_sz += aps->aps_psiz;
}
- BCOPYOUT(&ng, data, sizeof(ng));
+ if (BCOPYOUT(&ng, data, sizeof(ng)) != 0)
+ return EFAULT;
return 0;
}
@@ -1277,12 +1399,12 @@
aps = NULL;
nat = NULL;
ipnn = NULL;
+ fr = NULL;
/*
* New entry, copy in the rest of the NAT entry if it's size is more
* than just the nat_t structure.
*/
- fr = NULL;
if (ipn.ipn_dsize > sizeof(ipn)) {
if (ipn.ipn_dsize > 81920) {
error = ENOMEM;
@@ -1335,29 +1457,51 @@
ATOMIC_INC(nat_stats.ns_rules);
- nat_resolverule(in);
+ if (nat_resolverule(in) != 0) {
+ error = ESRCH;
+ goto junkput;
+ }
}
/*
* Check that the NAT entry doesn't already exist in the kernel.
+ *
+ * For NAT_OUTBOUND, we're lookup for a duplicate MAP entry. To do
+ * this, we check to see if the inbound combination of addresses and
+ * ports is already known. Similar logic is applied for NAT_INBOUND.
+ *
*/
bzero((char *)&fin, sizeof(fin));
fin.fin_p = nat->nat_p;
if (nat->nat_dir == NAT_OUTBOUND) {
+ fin.fin_ifp = nat->nat_ifps[0];
fin.fin_data[0] = ntohs(nat->nat_oport);
fin.fin_data[1] = ntohs(nat->nat_outport);
- fin.fin_ifp = nat->nat_ifps[1];
- if (nat_inlookup(&fin, 0, fin.fin_p, nat->nat_oip,
- nat->nat_inip) != NULL) {
+ if (getlock) {
+ READ_ENTER(&ipf_nat);
+ }
+ n = nat_inlookup(&fin, nat->nat_flags, fin.fin_p,
+ nat->nat_oip, nat->nat_inip);
+ if (getlock) {
+ RWLOCK_EXIT(&ipf_nat);
+ }
+ if (n != NULL) {
error = EEXIST;
goto junkput;
}
} else if (nat->nat_dir == NAT_INBOUND) {
+ fin.fin_ifp = nat->nat_ifps[0];
fin.fin_data[0] = ntohs(nat->nat_outport);
fin.fin_data[1] = ntohs(nat->nat_oport);
- fin.fin_ifp = nat->nat_ifps[0];
- if (nat_outlookup(&fin, 0, fin.fin_p, nat->nat_outip,
- nat->nat_oip) != NULL) {
+ if (getlock) {
+ READ_ENTER(&ipf_nat);
+ }
+ n = nat_outlookup(&fin, nat->nat_flags, fin.fin_p,
+ nat->nat_outip, nat->nat_oip);
+ if (getlock) {
+ RWLOCK_EXIT(&ipf_nat);
+ }
+ if (n != NULL) {
error = EEXIST;
goto junkput;
}
@@ -1418,10 +1562,18 @@
fr->fr_ref = 1;
(void) fr_outobj(data, ipnn, IPFOBJ_NATSAVE);
bcopy((char *)&ipnn->ipn_fr, (char *)fr, sizeof(*fr));
+
+ fr->fr_ref = 1;
+ fr->fr_dsize = 0;
+ fr->fr_data = NULL;
+ fr->fr_type = FR_T_NONE;
+
MUTEX_NUKE(&fr->fr_lock);
MUTEX_INIT(&fr->fr_lock, "nat-filter rule lock");
} else {
- READ_ENTER(&ipf_nat);
+ if (getlock) {
+ READ_ENTER(&ipf_nat);
+ }
for (n = nat_instances; n; n = n->nat_next)
if (n->nat_fr == fr)
break;
@@ -1431,7 +1583,9 @@
fr->fr_ref++;
MUTEX_EXIT(&fr->fr_lock);
}
- RWLOCK_EXIT(&ipf_nat);
+ if (getlock) {
+ RWLOCK_EXIT(&ipf_nat);
+ }
if (!n) {
error = ESRCH;
@@ -1464,7 +1618,7 @@
junkput:
if (fr != NULL)
- fr_derefrule(&fr);
+ (void) fr_derefrule(&fr);
if ((ipnn != NULL) && (ipnn != &ipn)) {
KFREES(ipnn, ipn.ipn_dsize);
@@ -1497,22 +1651,23 @@
/* Delete a nat entry from the various lists and table. If NAT logging is */
/* enabled then generate a NAT log record for this event. */
/* ------------------------------------------------------------------------ */
-static void nat_delete(nat, logtype)
+void nat_delete(nat, logtype)
struct nat *nat;
int logtype;
{
struct ipnat *ipn;
+ int removed = 0;
if (logtype != 0 && nat_logging != 0)
nat_log(nat, logtype);
- MUTEX_ENTER(&ipf_nat_new);
-
/*
* Take it as a general indication that all the pointers are set if
* nat_pnext is set.
*/
if (nat->nat_pnext != NULL) {
+ removed = 1;
+
nat_stats.ns_bucketlen[0][nat->nat_hv[0]]--;
nat_stats.ns_bucketlen[1][nat->nat_hv[1]]--;
@@ -1546,13 +1701,41 @@
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) {
- MUTEX_EXIT(&ipf_nat_new);
+ if (logtype == NL_EXPIRE)
+ nat_stats.ns_expire++;
+
+ MUTEX_ENTER(&nat->nat_lock);
+ /*
+ * NL_DESTROY should only be passed in when we've got nat_ref >= 2.
+ * This happens when a nat'd packet is blocked and we want to throw
+ * away the NAT session.
+ */
+ if (logtype == NL_DESTROY) {
+ if (nat->nat_ref > 2) {
+ nat->nat_ref -= 2;
+ MUTEX_EXIT(&nat->nat_lock);
+ if (removed)
+ nat_stats.ns_orphans++;
+ return;
+ }
+ } else if (nat->nat_ref > 1) {
+ nat->nat_ref--;
+ MUTEX_EXIT(&nat->nat_lock);
+ if (removed)
+ nat_stats.ns_orphans++;
return;
}
+ MUTEX_EXIT(&nat->nat_lock);
+
+ /*
+ * At this point, nat_ref is 1, doing "--" would make it 0..
+ */
+ nat->nat_ref = 0;
+ if (!removed)
+ nat_stats.ns_orphans--;
#ifdef IPFILTER_SYNC
if (nat->nat_sync)
@@ -1560,10 +1743,10 @@
#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
@@ -1572,25 +1755,13 @@
*/
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);
aps_free(nat->nat_aps);
nat_stats.ns_inuse--;
- MUTEX_EXIT(&ipf_nat_new);
/*
* If there's a fragment table entry too for this nat entry, then
@@ -1664,6 +1835,7 @@
if (n->in_use == 0) {
if (n->in_apr != NULL)
appr_free(n->in_apr);
+ MUTEX_DESTROY(&n->in_lock);
KFREE(n);
nat_stats.ns_rules--;
} else {
@@ -1672,7 +1844,7 @@
}
i++;
}
-#if SOLARIS
+#if SOLARIS && !defined(_INET_IP_STACK_H)
pfil_delayed_copy = 1;
#endif
nat_masks = 0;
@@ -1739,8 +1911,7 @@
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);
@@ -1961,10 +2132,12 @@
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;
@@ -1982,8 +2155,8 @@
* packet might match a different one to the previous connection but
* we want the same destination to be used.
*/
- if ((np->in_flags & (IPN_ROUNDR|IPN_STICKY)) ==
- (IPN_ROUNDR|IPN_STICKY)) {
+ if (((np->in_flags & (IPN_ROUNDR|IPN_SPLIT)) != 0) &&
+ ((np->in_flags & IPN_STICKY) != 0)) {
hm = nat_hostmap(NULL, fin->fin_src, fin->fin_dst, in,
(u_32_t)dport);
if (hm != NULL) {
@@ -2004,7 +2177,7 @@
in.s_addr = np->in_nip;
if ((np->in_flags & (IPN_ROUNDR|IPN_STICKY)) == IPN_STICKY) {
- hm = nat_hostmap(np, fin->fin_src, fin->fin_dst,
+ hm = nat_hostmap(NULL, fin->fin_src, fin->fin_dst,
in, (u_32_t)dport);
if (hm != NULL) {
in.s_addr = hm->hm_mapip.s_addr;
@@ -2074,9 +2247,29 @@
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;
+ if ((nat->nat_hm == NULL) && ((np->in_flags & IPN_STICKY) != 0))
+ nat->nat_hm = nat_hostmap(np, fin->fin_src, fin->fin_dst, in,
+ (u_32_t)dport);
ni->nai_sum1 = LONG_SUM(ntohl(fin->fin_daddr)) + ntohs(dport);
ni->nai_sum2 = LONG_SUM(in.s_addr) + ntohs(nport);
@@ -2128,6 +2321,9 @@
/* structure for a "MAP" rule (outgoing NAT translation); (2) deal with */
/* creating a new NAT structure for a "RDR" rule (incoming NAT translation) */
/* and (3) building that structure and putting it into the NAT table(s). */
+/* */
+/* NOTE: natsave should NOT be used top point back to an ipstate_t struct */
+/* as it can result in memory being corrupted. */
/* ------------------------------------------------------------------------ */
nat_t *nat_new(fin, np, natsave, flags, direction)
fr_info_t *fin;
@@ -2151,6 +2347,7 @@
if (nat_stats.ns_inuse >= ipf_nattable_max) {
nat_stats.ns_memfail++;
+ fr_nat_doflush = 1;
return NULL;
}
@@ -2161,6 +2358,8 @@
ni.nai_np = np;
ni.nai_nflags = nflags;
ni.nai_flags = flags;
+ ni.nai_dport = 0;
+ ni.nai_sport = 0;
/* Give me a new nat */
KMALLOC(nat, nat_t *);
@@ -2204,6 +2403,7 @@
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);
@@ -2221,6 +2421,7 @@
natl = nat_outlookup(fin, nflags, (u_int)fin->fin_p,
fin->fin_src, fin->fin_dst);
if (natl != NULL) {
+ KFREE(nat);
nat = natl;
goto done;
}
@@ -2238,6 +2439,7 @@
natl = nat_inlookup(fin, nflags, (u_int)fin->fin_p,
fin->fin_src, fin->fin_dst);
if (natl != NULL) {
+ KFREE(nat);
nat = natl;
goto done;
}
@@ -2306,15 +2508,17 @@
}
if (nat_finalise(fin, nat, &ni, tcp, natsave, direction) == -1) {
+ fr_nat_doflush = 1;
goto badnat;
}
if (flags & SI_WILDP)
nat_stats.ns_wilds++;
+ fin->fin_flx |= FI_NEWNAT;
goto done;
badnat:
nat_stats.ns_badnat++;
if ((hm = nat->nat_hm) != NULL)
- nat_hostmapdel(hm);
+ fr_hostmapdel(&hm);
KFREE(nat);
nat = NULL;
done:
@@ -2338,7 +2542,7 @@
/* for both IPv4 and IPv6. */
/* ------------------------------------------------------------------------ */
/*ARGSUSED*/
-static INLINE int nat_finalise(fin, nat, ni, tcp, natsave, direction)
+static int nat_finalise(fin, nat, ni, tcp, natsave, direction)
fr_info_t *fin;
nat_t *nat;
natinfo_t *ni;
@@ -2351,7 +2555,12 @@
np = ni->nai_np;
- COPYIFNAME(fin->fin_ifp, nat->nat_ifnames[0]);
+ if (np->in_ifps[0] != NULL) {
+ COPYIFNAME(4, np->in_ifps[0], nat->nat_ifnames[0]);
+ }
+ if (np->in_ifps[1] != NULL) {
+ COPYIFNAME(4, np->in_ifps[1], nat->nat_ifnames[1]);
+ }
#ifdef IPFILTER_SYNC
if ((nat->nat_flags & SI_CLONE) == 0)
nat->nat_sync = ipfsync_new(SMC_NAT, fin, nat);
@@ -2359,12 +2568,13 @@
nat->nat_me = natsave;
nat->nat_dir = direction;
- nat->nat_ifps[0] = fin->fin_ifp;
+ nat->nat_ifps[0] = np->in_ifps[0];
+ nat->nat_ifps[1] = np->in_ifps[1];
nat->nat_ptr = np;
nat->nat_p = fin->fin_p;
nat->nat_mssclamp = np->in_mssclamp;
- fr = fin->fin_fr;
- nat->nat_fr = fr;
+ if (nat->nat_p == IPPROTO_TCP)
+ nat->nat_seqnext[0] = ntohl(tcp->th_seq);
if ((np->in_apr != NULL) && ((ni->nai_flags & NAT_SLAVE) == 0))
if (appr_new(fin, nat) == -1)
@@ -2374,6 +2584,8 @@
if (nat_logging)
nat_log(nat, (u_int)np->in_redir);
np->in_use++;
+ fr = fin->fin_fr;
+ nat->nat_fr = fr;
if (fr != NULL) {
MUTEX_ENTER(&fr->fr_lock);
fr->fr_ref++;
@@ -2446,7 +2658,7 @@
nat->nat_ifnames[0][LIFNAMSIZ - 1] = '\0';
nat->nat_ifps[0] = fr_resolvenic(nat->nat_ifnames[0], 4);
- if (nat->nat_ifnames[1][0] !='\0') {
+ if (nat->nat_ifnames[1][0] != '\0') {
nat->nat_ifnames[1][LIFNAMSIZ - 1] = '\0';
nat->nat_ifps[1] = fr_resolvenic(nat->nat_ifnames[1], 4);
} else {
@@ -2515,8 +2727,7 @@
* Only a basic IP header (no options) should be with an ICMP error
* header. Also, if it's not an error type, then return.
*/
- if ((fin->fin_hlen != sizeof(ip_t)) ||
- !fr_icmp4errortype(type))
+ if ((fin->fin_hlen != sizeof(ip_t)) || !(fin->fin_flx & FI_ICMPERR))
return NULL;
/*
@@ -2636,9 +2847,9 @@
int dir;
{
u_32_t sum1, sum2, sumd, sumd2;
- struct in_addr in;
+ struct in_addr a1, a2;
+ int flags, dlen, odst;
icmphdr_t *icmp;
- int flags, dlen;
u_short *csump;
tcphdr_t *tcp;
nat_t *nat;
@@ -2689,33 +2900,7 @@
/*
* 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
@@ -2727,217 +2912,134 @@
* 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.
+ * Inbound ICMP
+ * ------------
+ * MAP rule, SRC=a,DST=b -> SRC=c,DST=b
+ * - response to outgoing packet (a,b)=>(c,b) (OIP_SRC=c,OIP_DST=b)
+ * - OIP_SRC(c)=nat_outip, OIP_DST(b)=nat_oip
+ *
+ * RDR rule, SRC=a,DST=b -> SRC=a,DST=c
+ * - response to outgoing packet (c,a)=>(b,a) (OIP_SRC=b,OIP_DST=a)
+ * - OIP_SRC(b)=nat_outip, OIP_DST(a)=nat_oip
+ *
+ * Outbound ICMP
+ * -------------
+ * MAP rule, SRC=a,DST=b -> SRC=c,DST=b
+ * - response to incoming packet (b,c)=>(b,a) (OIP_SRC=b,OIP_DST=a)
+ * - OIP_SRC(a)=nat_oip, OIP_DST(c)=nat_inip
+ *
+ * RDR rule, SRC=a,DST=b -> SRC=a,DST=c
+ * - response to incoming packet (a,b)=>(a,c) (OIP_SRC=a,OIP_DST=c)
+ * - OIP_SRC(a)=nat_oip, OIP_DST(c)=nat_inip
+ *
*/
- 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;
+ odst = (oip->ip_dst.s_addr == nat->nat_oip.s_addr) ? 1 : 0;
+ if (odst == 1) {
+ a1.s_addr = ntohl(nat->nat_inip.s_addr);
+ a2.s_addr = ntohl(oip->ip_src.s_addr);
+ oip->ip_src.s_addr = htonl(a1.s_addr);
+ } else {
+ a1.s_addr = ntohl(nat->nat_outip.s_addr);
+ a2.s_addr = ntohl(oip->ip_dst.s_addr);
+ oip->ip_dst.s_addr = htonl(a1.s_addr);
}
- /*
- * Fix 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... but, if you change, you must change the icmp
- * checksum *again*, to reflect that change.
- *
- * To further complicate: the TCP checksum is not in the first
- * 8 bytes of the offending ip packet, so it most likely is not
- * available. Some OSses like Solaris return enough bytes to
- * include the TCP checksum. So we have to check if the
- * ip->ip_len actually holds the TCP checksum of the oip!
+ * as well... except that the change in the port numbers should
+ * be offset by the checksum change. However, the TCP/UDP
+ * checksum will also need to change if there has been an
+ * IP address change.
*/
+ if (odst == 1) {
+ sum1 = ntohs(nat->nat_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) &&
- (dlen >= 8) && (*csump != 0)) {
- sumd = sum1 - sum2;
- sumd2 += sumd;
-
- sum1 = ntohs(*csump);
- fix_datacksum(csump, sumd);
- sum2 = ntohs(*csump);
-
- /*
- * Fix ICMP checksum to compenstate
- * UDP checksum adjustment.
- */
- CALC_SUMD(sum1, sum2, sumd);
- sumd2 += sumd;
- }
-
- /*
- * Fix TCP checksum (if present) to compensate port
- * adjustment. NOTE : the offending IP packet flows
- * the other direction compared to the ICMP message.
- */
- if (oip->ip_p == IPPROTO_TCP) {
+ if (oip->ip_p == IPPROTO_UDP) {
+ if ((dlen >= 8) && (*csump != 0)) {
+ fix_datacksum(csump, sumd);
+ } else {
+ sumd2 = sum1 - sum2;
+ if (sum2 > sum1)
+ sumd2--;
+ }
+ } else if (oip->ip_p == IPPROTO_TCP) {
if (dlen >= 18) {
- sumd = sum1 - sum2;
- sumd2 += sumd;
-
- sum1 = ntohs(*csump);
fix_datacksum(csump, sumd);
- sum2 = ntohs(*csump);
-
- /*
- * Fix ICMP checksum to compensate
- * TCP checksum adjustment.
- */
- CALC_SUMD(sum1, sum2, sumd);
- sumd2 += sumd;
} else {
- sumd = sum2 - sum1 + 1;
- sumd2 += sumd;
+ sumd2 = sum2 - sum1;
+ if (sum1 > sum2)
+ sumd2--;
}
}
- } else if (mode == 2) {
- /*
- * Fix ICMP checksum to compensate port adjustment.
- */
- tcp->th_dport = htons(sum1);
-
- /*
- * Fix UDP checksum to compensate port adjustment.
- * NOTE : the offending IP packet flows the other
- * direction compared to the ICMP message.
- *
- * The UDP checksum is optional, only adjust
- * it if it has been set.
- */
- if ((oip->ip_p == IPPROTO_UDP) &&
- (dlen >= 8) && (*csump != 0)) {
- sumd = sum1 - sum2;
- sumd2 += sumd;
-
- sum1 = ntohs(*csump);
- fix_datacksum(csump, sumd);
- sum2 = ntohs(*csump);
-
- /*
- * Fix ICMP checksum to compensate
- * UDP checksum adjustment.
- */
- CALC_SUMD(sum1, sum2, sumd);
- sumd2 += sumd;
- }
- /*
- * Fix TCP checksum (if present) to compensate port
- * adjustment. NOTE : the offending IP packet flows
- * the other direction compared to the ICMP message.
- */
- if (oip->ip_p == IPPROTO_TCP) {
- if (dlen >= 18) {
- sumd = sum1 - sum2;
- sumd2 += sumd;
+ if (sumd2 != 0) {
+ ipnat_t *np;
- sum1 = ntohs(*csump);
- fix_datacksum(csump, sumd);
- sum2 = ntohs(*csump);
-
- /*
- * Fix ICMP checksum to compensate
- * TCP checksum adjustment.
- */
- CALC_SUMD(sum1, sum2, sumd);
- sumd2 += sumd;
+ np = nat->nat_ptr;
+ sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16);
+ sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16);
+ sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16);
+
+ if ((odst == 0) && (dir == NAT_OUTBOUND) &&
+ (fin->fin_rev == 0) && (np != NULL) &&
+ (np->in_redir & NAT_REDIRECT)) {
+ fix_outcksum(fin, &icmp->icmp_cksum,
+ sumd2);
} else {
- if (nat->nat_dir == NAT_INBOUND)
- sumd = sum2 - sum1;
- else
- sumd = sum2 - sum1 + 1;
- sumd2 += sumd;
+ 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;
@@ -2947,7 +3049,7 @@
*/
orgicmp = (icmphdr_t *)dp;
- if (nat->nat_dir == NAT_OUTBOUND) {
+ if (odst == 1) {
if (orgicmp->icmp_id != nat->nat_inport) {
/*
@@ -3016,10 +3118,7 @@
void *ifp;
u_int hv;
- if (fin != NULL)
- ifp = fin->fin_ifp;
- else
- ifp = NULL;
+ ifp = fin->fin_ifp;
sport = 0;
dport = 0;
gre = NULL;
@@ -3051,17 +3150,13 @@
hv = NAT_HASH_FN(src.s_addr, hv + sport, ipf_nattable_sz);
nat = nat_table[1][hv];
for (; nat; nat = nat->nat_hnext[1]) {
- nflags = nat->nat_flags;
+ if (nat->nat_ifps[0] != NULL) {
+ if ((ifp != NULL) && (ifp != nat->nat_ifps[0]))
+ continue;
+ } else if (ifp != NULL)
+ nat->nat_ifps[0] = ifp;
- if (ifp != NULL) {
- if (nat->nat_dir == NAT_REDIRECT) {
- if (ifp != nat->nat_ifps[0])
- continue;
- } else {
- if (ifp != nat->nat_ifps[1])
- continue;
- }
- }
+ nflags = nat->nat_flags;
if (nat->nat_oip.s_addr == src.s_addr &&
nat->nat_outip.s_addr == dst &&
@@ -3126,15 +3221,11 @@
nat = nat_table[1][hv];
for (; nat; nat = nat->nat_hnext[1]) {
- if (ifp != NULL) {
- if (nat->nat_dir == NAT_REDIRECT) {
- if (ifp != nat->nat_ifps[0])
- continue;
- } else {
- if (ifp != nat->nat_ifps[1])
- continue;
- }
- }
+ if (nat->nat_ifps[0] != NULL) {
+ if ((ifp != NULL) && (ifp != nat->nat_ifps[0]))
+ continue;
+ } else if (ifp != NULL)
+ nat->nat_ifps[0] = ifp;
if (nat->nat_p != fin->fin_p)
continue;
@@ -3301,17 +3392,13 @@
hv = NAT_HASH_FN(dst.s_addr, hv + dport, ipf_nattable_sz);
nat = nat_table[0][hv];
for (; nat; nat = nat->nat_hnext[0]) {
- nflags = nat->nat_flags;
+ if (nat->nat_ifps[1] != NULL) {
+ if ((ifp != NULL) && (ifp != nat->nat_ifps[1]))
+ continue;
+ } else if (ifp != NULL)
+ nat->nat_ifps[1] = ifp;
- if (ifp != NULL) {
- if (nat->nat_dir == NAT_REDIRECT) {
- if (ifp != nat->nat_ifps[1])
- continue;
- } else {
- if (ifp != nat->nat_ifps[0])
- continue;
- }
- }
+ nflags = nat->nat_flags;
if (nat->nat_inip.s_addr == srcip &&
nat->nat_oip.s_addr == dst.s_addr &&
@@ -3366,15 +3453,11 @@
nat = nat_table[0][hv];
for (; nat; nat = nat->nat_hnext[0]) {
- if (ifp != NULL) {
- if (nat->nat_dir == NAT_REDIRECT) {
- if (ifp != nat->nat_ifps[1])
- continue;
- } else {
- if (ifp != nat->nat_ifps[0])
- continue;
- }
- }
+ if (nat->nat_ifps[1] != NULL) {
+ if ((ifp != NULL) && (ifp != nat->nat_ifps[1]))
+ continue;
+ } else if (ifp != NULL)
+ nat->nat_ifps[1] = ifp;
if (nat->nat_p != fin->fin_p)
continue;
@@ -3423,6 +3506,16 @@
/* entry for. */
/* */
/* Lookup the NAT tables to search for a matching redirect */
+/* The contents of natlookup_t should imitate those found in a packet that */
+/* would be translated - ie a packet coming in for RDR or going out for MAP.*/
+/* We can do the lookup in one of two ways, imitating an inbound or */
+/* outbound packet. By default we assume outbound, unless IPN_IN is set. */
+/* For IN, the fields are set as follows: */
+/* nl_real* = source information */
+/* nl_out* = destination information (translated) */
+/* For an out packet, the fields are set like this: */
+/* nl_in* = source information (untranslated) */
+/* nl_out* = destination information (translated) */
/* ------------------------------------------------------------------------ */
nat_t *nat_lookupredir(np)
natlookup_t *np;
@@ -3571,6 +3664,26 @@
ifq2 = NULL;
if (nat->nat_p == IPPROTO_TCP && ifq2 == NULL) {
+ u_32_t end, ack;
+ u_char tcpflags;
+ tcphdr_t *tcp;
+ int dsize;
+
+ tcp = fin->fin_dp;
+ tcpflags = tcp->th_flags;
+ dsize = fin->fin_dlen - (TCP_OFF(tcp) << 2) +
+ ((tcpflags & TH_SYN) ? 1 : 0) +
+ ((tcpflags & TH_FIN) ? 1 : 0);
+
+ ack = ntohl(tcp->th_ack);
+ end = ntohl(tcp->th_seq) + dsize;
+
+ if (SEQ_GT(ack, nat->nat_seqnext[1 - fin->fin_rev]))
+ nat->nat_seqnext[1 - fin->fin_rev] = ack;
+
+ if (nat->nat_seqnext[fin->fin_rev] == 0)
+ nat->nat_seqnext[fin->fin_rev] = end;
+
(void) fr_tcp_age(&nat->nat_tqe, fin, nat_tqb, 0);
} else {
if (ifq2 == NULL) {
@@ -3624,9 +3737,11 @@
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)) {
@@ -3684,7 +3799,7 @@
hv = NAT_HASH_FN(iph, 0, ipf_natrules_sz);
for (np = nat_rules[hv]; np; np = np->in_mnext)
{
- if ((np->in_ifps[0] && (np->in_ifps[0] != ifp)))
+ if ((np->in_ifps[1] && (np->in_ifps[1] != ifp)))
continue;
if (np->in_v != fin->fin_v)
continue;
@@ -3738,6 +3853,7 @@
MUTEX_ENTER(&nat->nat_lock);
nat->nat_ref++;
MUTEX_EXIT(&nat->nat_lock);
+ nat->nat_touched = fr_ticks;
fin->fin_nat = nat;
}
} else
@@ -3806,8 +3922,15 @@
CALC_SUMD(s1, s2, sumd);
fix_outcksum(fin, &fin->fin_ip->ip_sum, sumd);
}
-#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) || defined(linux)
+#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) || \
+ defined(linux) || defined(BRIDGE_IPF)
else {
+ /*
+ * Strictly speaking, this isn't necessary on BSD
+ * kernels because they do checksum calculation after
+ * this code has run BUT if ipfilter is being used
+ * to do NAT as a bridge, that code doesn't exist.
+ */
if (nat->nat_dir == NAT_OUTBOUND)
fix_outcksum(fin, &fin->fin_ip->ip_sum,
nat->nat_ipsumd);
@@ -4024,8 +4147,8 @@
MUTEX_ENTER(&nat->nat_lock);
nat->nat_ref++;
MUTEX_EXIT(&nat->nat_lock);
+ nat->nat_touched = fr_ticks;
fin->fin_nat = nat;
- fin->fin_state = nat->nat_state;
}
} else
rval = natfailed;
@@ -4269,9 +4392,9 @@
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],
@@ -4316,10 +4439,8 @@
{
ipftq_t *ifq, *ifqnext;
ipftqent_t *tqe, *tqn;
-#if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL)
- int s;
-#endif
int i;
+ SPL_INT(s);
SPL_NET(s);
WRITE_ENTER(&ipf_nat);
@@ -4352,6 +4473,11 @@
}
}
+ if (fr_nat_doflush != 0) {
+ nat_extraflush(2);
+ fr_nat_doflush = 0;
+ }
+
RWLOCK_EXIT(&ipf_nat);
SPL_X(s);
}
@@ -4373,9 +4499,7 @@
ipnat_t *n;
nat_t *nat;
void *ifp2;
-#if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL)
- int s;
-#endif
+ SPL_INT(s);
if (fr_running <= 0)
return;
@@ -4457,7 +4581,7 @@
/* Tests to see if the ICMP type number passed is a query/response type or */
/* not. */
/* ------------------------------------------------------------------------ */
-static INLINE int nat_icmpquerytype4(icmptype)
+static int nat_icmpquerytype4(icmptype)
int icmptype;
{
@@ -4563,12 +4687,50 @@
/* ------------------------------------------------------------------------ */
+/* 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);
+ MUTEX_DESTROY(&in->in_lock);
+ KFREE(in);
+ nat_stats.ns_rules--;
+#if SOLARIS && !defined(_INET_IP_STACK_H)
+ 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 */
/* */
/* Decrement the reference counter for this NAT table entry and free it if */
/* there are no more things using it. */
+/* */
+/* IF nat_ref == 1 when this function is called, then we have an orphan nat */
+/* structure *because* it only gets called on paths _after_ nat_ref has been*/
+/* incremented. If nat_ref == 1 then we shouldn't decrement it here */
+/* because nat_delete() will do that and send nat_ref to -1. */
+/* */
+/* Holding the lock on nat_lock is required to serialise nat_delete() being */
+/* called from a NAT flush ioctl with a deref happening because of a packet.*/
/* ------------------------------------------------------------------------ */
void fr_natderef(natp)
nat_t **natp;
@@ -4577,10 +4739,17 @@
nat = *natp;
*natp = NULL;
+
+ MUTEX_ENTER(&nat->nat_lock);
+ if (nat->nat_ref > 1) {
+ nat->nat_ref--;
+ MUTEX_EXIT(&nat->nat_lock);
+ return;
+ }
+ MUTEX_EXIT(&nat->nat_lock);
+
WRITE_ENTER(&ipf_nat);
- nat->nat_ref--;
- if (nat->nat_ref == 0)
- nat_delete(nat, NL_EXPIRE);
+ nat_delete(nat, NL_EXPIRE);
RWLOCK_EXIT(&ipf_nat);
}
@@ -4610,9 +4779,20 @@
MUTEX_NUKE(&clone->nat_lock);
+ clone->nat_aps = NULL;
+ /*
+ * Initialize all these so that nat_delete() doesn't cause a crash.
+ */
+ clone->nat_tqe.tqe_pnext = NULL;
+ clone->nat_tqe.tqe_next = NULL;
+ clone->nat_tqe.tqe_ifq = NULL;
+ clone->nat_tqe.tqe_parent = clone;
+
clone->nat_flags &= ~SI_CLONE;
clone->nat_flags |= SI_CLONED;
+ if (clone->nat_hm)
+ clone->nat_hm->hm_ref++;
if (nat_insert(clone, fin->fin_rev) == -1) {
KFREE(clone);
@@ -4631,14 +4811,13 @@
MUTEX_EXIT(&fr->fr_lock);
}
-
/*
* Because the clone is created outside the normal loop of things and
* TCP has special needs in terms of state, initialise the timeout
* state of the new NAT from here.
*/
if (clone->nat_p == IPPROTO_TCP) {
- (void) fr_tcp_age(&clone->nat_tqe, fin, nat_tqb, \
+ (void) fr_tcp_age(&clone->nat_tqe, fin, nat_tqb,
clone->nat_flags);
}
#ifdef IPFILTER_SYNC
@@ -4663,7 +4842,7 @@
/* Use NAT entry and packet direction to determine which combination of */
/* wildcard flags should be used. */
/* ------------------------------------------------------------------------ */
-static INLINE int nat_wildok(nat, sport, dport, flags, dir)
+static int nat_wildok(nat, sport, dport, flags, dir)
nat_t *nat;
int sport;
int dport;
@@ -4833,3 +5012,449 @@
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;
+ char *dst;
+
+ count = itp->igi_nitems;
+ if (count < 1)
+ return ENOSPC;
+
+ 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 (;;) {
+ switch (itp->igi_type)
+ {
+ case IPFGENITER_HOSTMAP :
+ if (nexthm != NULL) {
+ if (count == 1) {
+ ATOMIC_INC32(nexthm->hm_ref);
+ t->ipt_data = nexthm;
+ }
+ } else {
+ bzero(&zerohm, sizeof(zerohm));
+ nexthm = &zerohm;
+ count = 1;
+ t->ipt_data = NULL;
+ }
+ break;
+
+ case IPFGENITER_IPNAT :
+ if (nextipnat != NULL) {
+ if (count == 1) {
+ MUTEX_ENTER(&nextipnat->in_lock);
+ nextipnat->in_use++;
+ MUTEX_EXIT(&nextipnat->in_lock);
+ t->ipt_data = nextipnat;
+ }
+ } else {
+ bzero(&zeroipn, sizeof(zeroipn));
+ nextipnat = &zeroipn;
+ count = 1;
+ t->ipt_data = NULL;
+ }
+ break;
+
+ case IPFGENITER_NAT :
+ if (nextnat != NULL) {
+ if (count == 1) {
+ MUTEX_ENTER(&nextnat->nat_lock);
+ nextnat->nat_ref++;
+ MUTEX_EXIT(&nextnat->nat_lock);
+ t->ipt_data = nextnat;
+ }
+ } else {
+ bzero(&zeronat, sizeof(zeronat));
+ nextnat = &zeronat;
+ count = 1;
+ t->ipt_data = NULL;
+ }
+ break;
+ default :
+ break;
+ }
+ RWLOCK_EXIT(&ipf_nat);
+
+ /*
+ * Copying out to user space needs to be done without the lock.
+ */
+ switch (itp->igi_type)
+ {
+ case IPFGENITER_HOSTMAP :
+ error = COPYOUT(nexthm, dst, sizeof(*nexthm));
+ if (error != 0)
+ error = EFAULT;
+ else
+ dst += sizeof(*nexthm);
+ break;
+
+ case IPFGENITER_IPNAT :
+ error = COPYOUT(nextipnat, dst, sizeof(*nextipnat));
+ if (error != 0)
+ error = EFAULT;
+ else
+ dst += sizeof(*nextipnat);
+ break;
+
+ case IPFGENITER_NAT :
+ error = COPYOUT(nextnat, dst, sizeof(*nextnat));
+ if (error != 0)
+ error = EFAULT;
+ else
+ dst += sizeof(*nextnat);
+ break;
+ }
+
+ if ((count == 1) || (error != 0))
+ break;
+
+ count--;
+
+ READ_ENTER(&ipf_nat);
+
+ /*
+ * We need to have the lock again here to make sure that
+ * using _next is consistent.
+ */
+ switch (itp->igi_type)
+ {
+ case IPFGENITER_HOSTMAP :
+ nexthm = nexthm->hm_next;
+ break;
+ case IPFGENITER_IPNAT :
+ nextipnat = nextipnat->in_next;
+ break;
+ case IPFGENITER_NAT :
+ nextnat = nextnat->nat_next;
+ break;
+ }
+ }
+
+
+ switch (itp->igi_type)
+ {
+ case IPFGENITER_HOSTMAP :
+ if (hm != NULL) {
+ WRITE_ENTER(&ipf_nat);
+ fr_hostmapdel(&hm);
+ RWLOCK_EXIT(&ipf_nat);
+ }
+ break;
+ case IPFGENITER_IPNAT :
+ if (ipn != NULL) {
+ fr_ipnatderef(&ipn);
+ }
+ break;
+ case IPFGENITER_NAT :
+ if (nat != NULL) {
+ fr_natderef(&nat);
+ }
+ break;
+ default :
+ break;
+ }
+
+ return error;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: nat_iterator */
+/* Returns: int - 0 == ok, else error */
+/* Parameters: token(I) - pointer to ipftoken structure */
+/* itp(I) - pointer to ipfgeniter_t structure */
+/* */
+/* This function acts as a handler for the SIOCGENITER ioctls that use a */
+/* generic structure to iterate through a list. There are three different */
+/* linked lists of NAT related information to go through: NAT rules, active */
+/* NAT mappings and the NAT fragment cache. */
+/* ------------------------------------------------------------------------ */
+static int nat_iterator(token, itp)
+ipftoken_t *token;
+ipfgeniter_t *itp;
+{
+ int error;
+
+ if (itp->igi_data == NULL)
+ return EFAULT;
+
+ token->ipt_subtype = itp->igi_type;
+
+ switch (itp->igi_type)
+ {
+ case IPFGENITER_HOSTMAP :
+ case IPFGENITER_IPNAT :
+ case IPFGENITER_NAT :
+ error = nat_getnext(token, itp);
+ break;
+
+ case IPFGENITER_NATFRAG :
+#ifdef USE_MUTEXES
+ error = fr_nextfrag(token, itp, &ipfr_natlist,
+ &ipfr_nattail, &ipf_natfrag);
+#else
+ error = fr_nextfrag(token, itp, &ipfr_natlist, &ipfr_nattail);
+#endif
+ break;
+ default :
+ error = EINVAL;
+ break;
+ }
+
+ return error;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: nat_extraflush */
+/* Returns: int - 0 == success, -1 == failure */
+/* Parameters: which(I) - how to flush the active NAT table */
+/* Write Locks: ipf_nat */
+/* */
+/* Flush nat tables. Three actions currently defined: */
+/* which == 0 : flush all nat table entries */
+/* which == 1 : flush TCP connections which have started to close but are */
+/* stuck for some reason. */
+/* which == 2 : flush TCP connections which have been idle for a long time, */
+/* starting at > 4 days idle and working back in successive half-*/
+/* days to at most 12 hours old. If this fails to free enough */
+/* slots then work backwards in half hour slots to 30 minutes. */
+/* If that too fails, then work backwards in 30 second intervals */
+/* for the last 30 minutes to at worst 30 seconds idle. */
+/* ------------------------------------------------------------------------ */
+static int nat_extraflush(which)
+int which;
+{
+ ipftq_t *ifq, *ifqnext;
+ nat_t *nat, **natp;
+ ipftqent_t *tqn;
+ int removed;
+ SPL_INT(s);
+
+ removed = 0;
+
+ SPL_NET(s);
+
+ switch (which)
+ {
+ case 0 :
+ /*
+ * Style 0 flush removes everything...
+ */
+ for (natp = &nat_instances; ((nat = *natp) != NULL); ) {
+ nat_delete(nat, NL_FLUSH);
+ removed++;
+ }
+ break;
+
+ case 1 :
+ /*
+ * Since we're only interested in things that are closing,
+ * we can start with the appropriate timeout queue.
+ */
+ for (ifq = nat_tqb + IPF_TCPS_CLOSE_WAIT; ifq != NULL;
+ ifq = ifq->ifq_next) {
+
+ for (tqn = ifq->ifq_head; tqn != NULL; ) {
+ nat = tqn->tqe_parent;
+ tqn = tqn->tqe_next;
+ if (nat->nat_p != IPPROTO_TCP)
+ break;
+ nat_delete(nat, NL_EXPIRE);
+ removed++;
+ }
+ }
+
+ /*
+ * Also need to look through the user defined queues.
+ */
+ for (ifq = nat_utqe; ifq != NULL; ifq = ifqnext) {
+ ifqnext = ifq->ifq_next;
+ for (tqn = ifq->ifq_head; tqn != NULL; ) {
+ nat = tqn->tqe_parent;
+ tqn = tqn->tqe_next;
+ if (nat->nat_p != IPPROTO_TCP)
+ continue;
+
+ if ((nat->nat_tcpstate[0] >
+ IPF_TCPS_ESTABLISHED) &&
+ (nat->nat_tcpstate[1] >
+ IPF_TCPS_ESTABLISHED)) {
+ nat_delete(nat, NL_EXPIRE);
+ removed++;
+ }
+ }
+ }
+ break;
+
+ /*
+ * Args 5-11 correspond to flushing those particular states
+ * for TCP connections.
+ */
+ case IPF_TCPS_CLOSE_WAIT :
+ case IPF_TCPS_FIN_WAIT_1 :
+ case IPF_TCPS_CLOSING :
+ case IPF_TCPS_LAST_ACK :
+ case IPF_TCPS_FIN_WAIT_2 :
+ case IPF_TCPS_TIME_WAIT :
+ case IPF_TCPS_CLOSED :
+ tqn = nat_tqb[which].ifq_head;
+ while (tqn != NULL) {
+ nat = tqn->tqe_parent;
+ tqn = tqn->tqe_next;
+ nat_delete(nat, NL_FLUSH);
+ removed++;
+ }
+ break;
+
+ default :
+ if (which < 30)
+ break;
+
+ /*
+ * Take a large arbitrary number to mean the number of seconds
+ * for which which consider to be the maximum value we'll allow
+ * the expiration to be.
+ */
+ which = IPF_TTLVAL(which);
+ for (natp = &nat_instances; ((nat = *natp) != NULL); ) {
+ if (fr_ticks - nat->nat_touched > which) {
+ nat_delete(nat, NL_FLUSH);
+ removed++;
+ } else
+ natp = &nat->nat_next;
+ }
+ break;
+ }
+
+ if (which != 2) {
+ SPL_X(s);
+ return removed;
+ }
+
+ /*
+ * Asked to remove inactive entries because the table is full.
+ */
+ if (fr_ticks - nat_last_force_flush > IPF_TTLVAL(5)) {
+ nat_last_force_flush = fr_ticks;
+ removed = ipf_queueflush(nat_flush_entry, nat_tqb, nat_utqe);
+ }
+
+ SPL_X(s);
+ return removed;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: nat_flush_entry */
+/* Returns: 0 - always succeeds */
+/* Parameters: entry(I) - pointer to NAT entry */
+/* Write Locks: ipf_nat */
+/* */
+/* This function is a stepping stone between ipf_queueflush() and */
+/* nat_dlete(). It is used so we can provide a uniform interface via the */
+/* ipf_queueflush() function. Since the nat_delete() function returns void */
+/* we translate that to mean it always succeeds in deleting something. */
+/* ------------------------------------------------------------------------ */
+static int nat_flush_entry(entry)
+void *entry;
+{
+ nat_delete(entry, NL_FLUSH);
+ return 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: nat_gettable */
+/* Returns: int - 0 = success, else error */
+/* Parameters: data(I) - pointer to ioctl data */
+/* */
+/* This function handles ioctl requests for tables of nat information. */
+/* At present the only table it deals with is the hash bucket statistics. */
+/* ------------------------------------------------------------------------ */
+static int nat_gettable(data)
+char *data;
+{
+ ipftable_t table;
+ int error;
+
+ error = fr_inobj(data, &table, IPFOBJ_GTABLE);
+ if (error != 0)
+ return error;
+
+ switch (table.ita_type)
+ {
+ case IPFTABLE_BUCKETS_NATIN :
+ error = COPYOUT(nat_stats.ns_bucketlen[0], table.ita_table,
+ ipf_nattable_sz * sizeof(u_long));
+ break;
+
+ case IPFTABLE_BUCKETS_NATOUT :
+ error = COPYOUT(nat_stats.ns_bucketlen[1], table.ita_table,
+ ipf_nattable_sz * sizeof(u_long));
+ break;
+
+ default :
+ return EINVAL;
+ }
+
+ if (error != 0) {
+ error = EFAULT;
+ }
+ return error;
+}
Index: ip_ftp_pxy.c
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_ftp_pxy.c -L sys/contrib/ipfilter/netinet/ip_ftp_pxy.c -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_ftp_pxy.c
+++ sys/contrib/ipfilter/netinet/ip_ftp_pxy.c
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c,v 1.25 2005/04/25 18:43:14 darrenr Exp $ */
+/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c,v 1.28 2007/06/04 02:54:35 darrenr Exp $ */
/*
* Copyright (C) 1997-2003 by Darren Reed
@@ -8,8 +8,8 @@
* Simple FTP transparent proxy for in-kernel use. For use with the NAT
* code.
*
- * $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c,v 1.25 2005/04/25 18:43:14 darrenr Exp $
- * Id: ip_ftp_pxy.c,v 2.88.2.15 2005/03/19 19:38:10 darrenr Exp
+ * $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c,v 1.28 2007/06/04 02:54:35 darrenr Exp $
+ * Id: ip_ftp_pxy.c,v 2.88.2.19 2006/04/01 10:14:53 darrenr Exp $
*/
#define IPF_FTP_PROXY
@@ -369,26 +369,13 @@
fi.fin_fi.fi_daddr = nat->nat_inip.s_addr;
ip->ip_dst = nat->nat_inip;
}
- (void) fr_addstate(&fi, &nat2->nat_state, SI_W_DPORT);
+ (void) fr_addstate(&fi, NULL, SI_W_DPORT);
if (fi.fin_state != NULL)
- fr_statederef(&fi, (ipstate_t **)&fi.fin_state);
+ fr_statederef((ipstate_t **)&fi.fin_state);
}
ip->ip_len = slen;
ip->ip_src = swip;
ip->ip_dst = swip2;
- } else {
- ipstate_t *is;
-
- nat_update(&fi, nat2, nat->nat_ptr);
- READ_ENTER(&ipf_state);
- is = nat2->nat_state;
- if (is != NULL) {
- MUTEX_ENTER(&is->is_lock);
- (void)fr_tcp_age(&is->is_sti, &fi, ips_tqtqb,
- is->is_flags);
- MUTEX_EXIT(&is->is_lock);
- }
- RWLOCK_EXIT(&ipf_state);
}
return APR_INC(inc);
}
@@ -474,9 +461,10 @@
{
u_int a1, a2, a3, a4, data_ip;
char newbuf[IPF_FTPBUFSZ];
- char *s, *brackets[2];
+ const char *brackets[2];
u_short a5, a6;
ftpside_t *f;
+ char *s;
if (ippr_ftp_forcepasv != 0 &&
ftp->ftp_side[0].ftps_cmds != FTPXY_C_PASV) {
@@ -730,27 +718,14 @@
fi.fin_fi.fi_daddr = nat->nat_inip.s_addr;
ip->ip_dst = nat->nat_inip;
}
- (void) fr_addstate(&fi, &nat2->nat_state, sflags);
+ (void) fr_addstate(&fi, NULL, sflags);
if (fi.fin_state != NULL)
- fr_statederef(&fi, (ipstate_t **)&fi.fin_state);
+ fr_statederef((ipstate_t **)&fi.fin_state);
}
ip->ip_len = slen;
ip->ip_src = swip;
ip->ip_dst = swip2;
- } else {
- ipstate_t *is;
-
- nat_update(&fi, nat2, nat->nat_ptr);
- READ_ENTER(&ipf_state);
- is = nat2->nat_state;
- if (is != NULL) {
- MUTEX_ENTER(&is->is_lock);
- (void)fr_tcp_age(&is->is_sti, &fi, ips_tqtqb,
- is->is_flags);
- MUTEX_EXIT(&is->is_lock);
- }
- RWLOCK_EXIT(&ipf_state);
}
return inc;
}
@@ -1029,13 +1004,14 @@
if (ippr_ftp_debug > 4)
printf("ippr_ftp_process: mlen %d\n", mlen);
- if (mlen <= 0) {
- if ((tcp->th_flags & TH_OPENING) == TH_OPENING) {
- f->ftps_seq[0] = thseq + 1;
- t->ftps_seq[0] = thack;
- }
+ if ((mlen == 0) && ((tcp->th_flags & TH_OPENING) == TH_OPENING)) {
+ f->ftps_seq[0] = thseq + 1;
+ t->ftps_seq[0] = thack;
+ return 0;
+ } else if (mlen < 0) {
return 0;
}
+
aps = nat->nat_aps;
sel = aps->aps_sel[1 - rv];
@@ -1142,8 +1118,8 @@
f->ftps_seq[1] = thseq + 1 - seqoff;
} else {
if (ippr_ftp_debug > 1) {
- printf("FIN: thseq %x seqoff %d ftps_seq %x\n",
- thseq, seqoff, f->ftps_seq[0]);
+ printf("FIN: thseq %x seqoff %d ftps_seq %x %x\n",
+ thseq, seqoff, f->ftps_seq[0], f->ftps_seq[1]);
}
return APR_ERR(1);
}
@@ -1425,7 +1401,7 @@
ap += *s++ - '0';
}
- if (!s)
+ if (!*s)
return 0;
if (*s == '|')
Index: mlfk_ipl.c
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/mlfk_ipl.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/mlfk_ipl.c -L sys/contrib/ipfilter/netinet/mlfk_ipl.c -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/mlfk_ipl.c
+++ sys/contrib/ipfilter/netinet/mlfk_ipl.c
@@ -1,9 +1,9 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/mlfk_ipl.c,v 1.16 2005/04/25 18:43:14 darrenr Exp $ */
+/* $FreeBSD: src/sys/contrib/ipfilter/netinet/mlfk_ipl.c,v 1.19.2.1 2007/10/31 05:00:38 darrenr Exp $ */
/*
* Copyright (C) 2000 by Darren Reed.
*
- * $FreeBSD: src/sys/contrib/ipfilter/netinet/mlfk_ipl.c,v 1.16 2005/04/25 18:43:14 darrenr Exp $
+ * $FreeBSD: src/sys/contrib/ipfilter/netinet/mlfk_ipl.c,v 1.19.2.1 2007/10/31 05:00:38 darrenr Exp $
* See the IPFILTER.LICENCE file for details on licencing.
*/
@@ -15,6 +15,10 @@
#include <sys/conf.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
+#include <sys/select.h>
+#if __FreeBSD_version >= 500000
+# include <sys/selinfo.h>
+#endif
#include <net/if.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
@@ -27,6 +31,7 @@
#include <netinet/ip_nat.h>
#include <netinet/ip_auth.h>
#include <netinet/ip_frag.h>
+#include <netinet/ip_sync.h>
#if __FreeBSD_version >= 502116
static struct cdev *ipf_devs[IPL_LOGSIZE];
@@ -94,7 +99,11 @@
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &fr_minttl, 0, "");
#define CDEV_MAJOR 79
-#if __FreeBSD_version >= 501000
+#include <sys/poll.h>
+#if __FreeBSD_version >= 500043
+# include <sys/select.h>
+static int iplpoll(struct cdev *dev, int events, struct thread *td);
+
static struct cdevsw ipl_cdevsw = {
# if __FreeBSD_version >= 502103
.d_version = D_VERSION,
@@ -103,20 +112,26 @@
.d_open = iplopen,
.d_close = iplclose,
.d_read = iplread,
+ .d_write = iplwrite,
.d_ioctl = iplioctl,
.d_name = "ipl",
+# if __FreeBSD_version >= 500043
+ .d_poll = iplpoll,
+# endif
# if __FreeBSD_version < 600000
.d_maj = CDEV_MAJOR,
# endif
};
#else
+static int iplpoll(dev_t dev, int events, struct proc *p);
+
static struct cdevsw ipl_cdevsw = {
/* open */ iplopen,
/* close */ iplclose,
/* read */ iplread,
/* write */ iplwrite,
/* ioctl */ iplioctl,
- /* poll */ nopoll,
+ /* poll */ iplpoll,
/* mmap */ nommap,
/* strategy */ nostrategy,
/* name */ "ipl",
@@ -127,7 +142,9 @@
# if (__FreeBSD_version < 500043)
/* bmaj */ -1,
# endif
+# if (__FreeBSD_version > 430000)
/* kqfilter */ NULL
+# endif
};
#endif
@@ -163,9 +180,17 @@
char *defpass, *c, *str;
int i, j, error;
- error = iplattach();
- if (error)
+ RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex");
+ RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock");
+ RWLOCK_INIT(&ipf_frcache, "ipf cache rwlock");
+
+ error = ipfattach();
+ if (error) {
+ RW_DESTROY(&ipf_global);
+ RW_DESTROY(&ipf_mutex);
+ RW_DESTROY(&ipf_frcache);
return error;
+ }
for (i = 0; i < IPL_LOGSIZE; i++)
ipf_devs[i] = NULL;
@@ -182,6 +207,11 @@
ipf_devs[i] = make_dev(&ipl_cdevsw, i, 0, 0, 0600, c);
}
+ error = ipf_pfil_hook();
+ if (error != 0)
+ return error;
+ ipf_event_reg();
+
if (FR_ISPASS(fr_pass))
defpass = "pass";
else if (FR_ISBLOCK(fr_pass))
@@ -215,12 +245,20 @@
return EBUSY;
if (fr_running >= 0) {
- error = ipldetach();
+ ipf_pfil_unhook();
+ ipf_event_dereg();
+ WRITE_ENTER(&ipf_global);
+ error = ipfdetach();
+ RWLOCK_EXIT(&ipf_global);
if (error != 0)
return error;
} else
error = 0;
+ RW_DESTROY(&ipf_global);
+ RW_DESTROY(&ipf_mutex);
+ RW_DESTROY(&ipf_frcache);
+
fr_running = -2;
for (i = 0; ipf_devfiles[i]; i++) {
@@ -272,3 +310,53 @@
return (error);
}
#endif
+
+
+static int
+#if __FreeBSD_version >= 500043
+iplpoll(struct cdev *dev, int events, struct thread *td)
+#else
+iplpoll(dev_t dev, int events, struct proc *td)
+#endif
+{
+ u_int xmin = GET_MINOR(dev);
+ int revents;
+
+ if (xmin < 0 || xmin > IPL_LOGMAX)
+ return 0;
+
+ revents = 0;
+
+ switch (xmin)
+ {
+ case IPL_LOGIPF :
+ case IPL_LOGNAT :
+ case IPL_LOGSTATE :
+#ifdef IPFILTER_LOG
+ if ((events & (POLLIN | POLLRDNORM)) && ipflog_canread(xmin))
+ revents |= events & (POLLIN | POLLRDNORM);
+#endif
+ break;
+ case IPL_LOGAUTH :
+ if ((events & (POLLIN | POLLRDNORM)) && fr_auth_waiting())
+ revents |= events & (POLLIN | POLLRDNORM);
+ break;
+ case IPL_LOGSYNC :
+#ifdef IPFILTER_SYNC
+ if ((events & (POLLIN | POLLRDNORM)) && ipfsync_canread())
+ revents |= events & (POLLIN | POLLRDNORM);
+ if ((events & (POLLOUT | POLLWRNORM)) && ipfsync_canwrite())
+ revents |= events & (POLLOUT | POLLWRNORM);
+#endif
+ break;
+ case IPL_LOGSCAN :
+ case IPL_LOGLOOKUP :
+ default :
+ break;
+ }
+
+ if ((revents == 0) && ((events & (POLLIN|POLLRDNORM)) != 0))
+ selrecord(td, &ipfselwait[xmin]);
+
+ return revents;
+}
Index: ip_pool.h
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_pool.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_pool.h -L sys/contrib/ipfilter/netinet/ip_pool.h -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_pool.h
+++ sys/contrib/ipfilter/netinet/ip_pool.h
@@ -1,24 +1,22 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_pool.h,v 1.1.1.1 2005/04/25 18:15:28 darrenr 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.2 2004/03/23 12:44:34 darrenr Exp
+ * $Id: ip_pool.h,v 2.26.2.6 2007/10/10 09:51:43 darrenr Exp $
*/
#ifndef __IP_POOL_H__
#define __IP_POOL_H__
#if defined(_KERNEL) && !defined(__osf__) && !defined(__hpux) && \
- !defined(linux) && !defined(sun)
+ !defined(linux) && !defined(sun) && !defined(AIX)
# include <net/radix.h>
extern void rn_freehead __P((struct radix_node_head *));
# define FreeS(p, z) KFREES(p, z)
extern int max_keylen;
#else
-# if defined(__osf__) || defined(__hpux)
+# if defined(__osf__) || defined(__hpux) || defined(sun)
# include "radix_ipf_local.h"
# define radix_mask ipf_radix_mask
# define radix_node ipf_radix_node
@@ -37,8 +35,9 @@
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 +54,8 @@
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 +75,16 @@
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__ */
Index: ip_fil_freebsd.c
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_fil_freebsd.c -L sys/contrib/ipfilter/netinet/ip_fil_freebsd.c -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_fil_freebsd.c
+++ sys/contrib/ipfilter/netinet/ip_fil_freebsd.c
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c,v 1.1.1.1 2005/04/25 18:15:15 darrenr Exp $ */
+/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c,v 1.6.2.2 2007/12/01 00:53:41 darrenr 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_freebsd.c,v 2.53.2.25 2005/02/01 03:15:56 darrenr Exp";
+static const char rcsid[] = "@(#)$Id: ip_fil_freebsd.c,v 2.53.2.50 2007/09/20 12:51:50 darrenr Exp $";
#endif
#if defined(KERNEL) || defined(_KERNEL)
@@ -57,10 +57,18 @@
#endif
#include <sys/protosw.h>
#include <sys/socket.h>
+#if __FreeBSD_version >= 500043
+# include <sys/selinfo.h>
+#else
+# include <sys/select.h>
+#endif
#include <net/if.h>
#if __FreeBSD_version >= 300000
# include <net/if_var.h>
+# if __FreeBSD_version >= 500043
+# include <net/netisr.h>
+# endif
# if !defined(IPFILTER_LKM)
# include "opt_ipfilter.h"
# endif
@@ -112,7 +120,7 @@
#endif
# ifdef IPFILTER_M_IPFILTER
-MALLOC_DEFINE(M_IPFILTER, "IP Filter", "IP Filter packet filter data structures");
+MALLOC_DEFINE(M_IPFILTER, "ipfilter", "IP Filter packet filter data structures");
# endif
@@ -125,7 +133,7 @@
# ifdef USE_MUTEXES
ipfmutex_t ipl_mutex, ipf_authmx, ipf_rw, ipf_stinsert;
ipfmutex_t ipf_nat_new, ipf_natio, ipf_timeoutlock;
-ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag;
+ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag, ipf_frcache, ipf_tokens;
ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth;
# endif
int ipf_locks_done = 0;
@@ -133,6 +141,7 @@
#if (__FreeBSD_version >= 300000)
struct callout_handle fr_slowtimer_ch;
#endif
+struct selinfo ipfselwait[IPL_LOGSIZE];
#if (__FreeBSD_version >= 500011)
# include <sys/conf.h>
@@ -147,6 +156,19 @@
#endif /* __FreeBSD_version >= 500011 */
+#if (__FreeBSD_version >= 502103)
+static eventhandler_tag ipf_arrivetag, ipf_departtag, ipf_clonetag;
+
+static void ipf_ifevent(void *arg);
+
+static void ipf_ifevent(arg)
+void *arg;
+{
+ frsync(NULL);
+}
+#endif
+
+
#if (__FreeBSD_version >= 501108) && defined(_KERNEL)
static int
@@ -178,20 +200,11 @@
#endif /* IPFILTER_LKM */
-int iplattach()
+int ipfattach()
{
#ifdef USE_SPL
int s;
#endif
-#if defined(NETBSD_PF) && (__FreeBSD_version >= 500011)
- int error = 0;
-# if __FreeBSD_version >= 501108
- struct pfil_head *ph_inet;
-# ifdef USE_INET6
- struct pfil_head *ph_inet6;
-# endif
-# endif
-#endif
SPL_NET(s);
if (fr_running > 0) {
@@ -200,10 +213,9 @@
}
MUTEX_INIT(&ipf_rw, "ipf rw mutex");
- RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex");
MUTEX_INIT(&ipf_timeoutlock, "ipf timeout queue mutex");
- RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock");
RWLOCK_INIT(&ipf_ipidfrag, "ipf IP NAT-Frag rwlock");
+ RWLOCK_INIT(&ipf_tokens, "ipf token rwlock");
ipf_locks_done = 1;
if (fr_initialise() < 0) {
@@ -212,70 +224,12 @@
}
-# ifdef NETBSD_PF
-# if __FreeBSD_version >= 500011
-# if __FreeBSD_version >= 501108
- ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
-# ifdef USE_INET6
- ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
-# endif
- if (ph_inet == NULL
-# ifdef USE_INET6
- && ph_inet6 == NULL
-# endif
- )
- return ENODEV;
-
- if (ph_inet != NULL)
- error = pfil_add_hook((void *)fr_check_wrapper, NULL,
- PFIL_IN|PFIL_OUT, ph_inet);
- else
- error = 0;
-# else
- error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
- &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
-# endif
- if (error) {
-# ifdef USE_INET6
- goto pfil_error;
-# else
- fr_deinitialise();
- SPL_X(s);
- return error;
-# endif
- }
-# else
- pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT);
-# endif
-# ifdef USE_INET6
-# if __FreeBSD_version >= 501108
- if (ph_inet6 != NULL)
- error = pfil_add_hook((void *)fr_check_wrapper6, NULL,
- PFIL_IN|PFIL_OUT, ph_inet6);
- else
- error = 0;
- if (error) {
- pfil_remove_hook((void *)fr_check_wrapper6, NULL,
- PFIL_IN|PFIL_OUT, ph_inet6);
-# else
- error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
- &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
- if (error) {
- pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
- &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
-# endif
-pfil_error:
- fr_deinitialise();
- SPL_X(s);
- return error;
- }
-# endif
-# endif
if (fr_checkp != fr_check) {
fr_savep = fr_checkp;
fr_checkp = fr_check;
}
+ bzero((char *)ipfselwait, sizeof(ipfselwait));
bzero((char *)frcache, sizeof(frcache));
fr_running = 1;
@@ -297,21 +251,11 @@
* Disable the filter by removing the hooks from the IP input/output
* stream.
*/
-int ipldetach()
+int ipfdetach()
{
#ifdef USE_SPL
int s;
#endif
-#if defined(NETBSD_PF) && (__FreeBSD_version >= 500011)
- int error = 0;
-# if __FreeBSD_version >= 501108
- struct pfil_head *ph_inet;
-# ifdef USE_INET6
- struct pfil_head *ph_inet6;
-# endif
-# endif
-#endif
-
if (fr_control_forwarding & 2)
ipforwarding = 0;
@@ -331,44 +275,6 @@
fr_savep = NULL;
#endif
-#ifdef NETBSD_PF
-# if (__FreeBSD_version >= 500011)
-# if (__FreeBSD_version >= 501108)
- ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
- if (ph_inet != NULL)
- error = pfil_remove_hook((void *)fr_check_wrapper, NULL,
- PFIL_IN|PFIL_OUT, ph_inet);
- else
- error = 0;
-# else
- error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
- &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
-# endif
- if (error) {
- SPL_X(s);
- return error;
- }
-# else
- pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT);
-# endif
-# ifdef USE_INET6
-# if (__FreeBSD_version >= 501108)
- ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
- if (ph_inet6 != NULL)
- error = pfil_remove_hook((void *)fr_check_wrapper6, NULL,
- PFIL_IN|PFIL_OUT, ph_inet6);
- else
- error = 0;
-# else
- error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
- &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
-# endif
- if (error) {
- SPL_X(s);
- return error;
- }
-# endif
-#endif
fr_deinitialise();
fr_running = -2;
@@ -379,9 +285,8 @@
if (ipf_locks_done == 1) {
MUTEX_DESTROY(&ipf_timeoutlock);
MUTEX_DESTROY(&ipf_rw);
- RW_DESTROY(&ipf_mutex);
RW_DESTROY(&ipf_ipidfrag);
- RW_DESTROY(&ipf_global);
+ RW_DESTROY(&ipf_tokens);
ipf_locks_done = 0;
}
@@ -399,8 +304,14 @@
, p)
# if (__FreeBSD_version >= 500024)
struct thread *p;
+# if (__FreeBSD_version >= 500043)
+# define p_uid td_ucred->cr_ruid
+# else
+# define p_uid t_proc->p_cred->p_ruid
+# endif
# else
struct proc *p;
+# define p_uid p_cred->p_ruid
# endif /* __FreeBSD_version >= 500024 */
# else
)
@@ -414,14 +325,11 @@
caddr_t data;
int mode;
{
-#ifdef USE_SPL
- int s;
-#endif
- int error = 0, unit = 0, tmp;
- friostat_t fio;
+ int error = 0, unit = 0;
+ SPL_INT(s);
#if (BSD >= 199306) && defined(_KERNEL)
- if ((securelevel >= 2) && (mode & FWRITE))
+ if ((securelevel >= 3) && (mode & FWRITE))
return EPERM;
#endif
@@ -439,150 +347,18 @@
}
SPL_NET(s);
+ READ_ENTER(&ipf_global);
- error = fr_ioctlswitch(unit, data, cmd, mode);
+ error = fr_ioctlswitch(unit, data, cmd, mode, p->p_uid, p);
if (error != -1) {
+ RWLOCK_EXIT(&ipf_global);
SPL_X(s);
return error;
}
- error = 0;
- switch (cmd)
- {
- case FIONREAD :
-#ifdef IPFILTER_LOG
- BCOPYOUT(&iplused[IPL_LOGIPF], (caddr_t)data,
- sizeof(iplused[IPL_LOGIPF]));
-#endif
- break;
- case SIOCFRENB :
- if (!(mode & FWRITE))
- error = EPERM;
- else {
- BCOPYIN(data, &tmp, sizeof(tmp));
- if (tmp) {
- if (fr_running > 0)
- error = 0;
- else
- error = iplattach();
- if (error == 0)
- fr_running = 1;
- else
- (void) ipldetach();
- } else {
- 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;
- }
+ RWLOCK_EXIT(&ipf_global);
SPL_X(s);
+
return error;
}
@@ -705,14 +481,21 @@
#endif
register struct uio *uio;
{
+ u_int xmin = GET_MINOR(dev);
+
+ if (fr_running < 1)
+ return EIO;
+
+ if (xmin < 0)
+ return ENXIO;
# ifdef IPFILTER_SYNC
- if (GET_MINOR(dev) == IPL_LOGSYNC)
+ if (xmin == IPL_LOGSYNC)
return ipfsync_read(uio);
# endif
#ifdef IPFILTER_LOG
- return ipflog_read(GET_MINOR(dev), uio);
+ return ipflog_read(xmin, uio);
#else
return ENXIO;
#endif
@@ -739,6 +522,9 @@
register struct uio *uio;
{
+ if (fr_running < 1)
+ return EIO;
+
#ifdef IPFILTER_SYNC
if (GET_MINOR(dev) == IPL_LOGSYNC)
return ipfsync_write(uio);
@@ -766,10 +552,8 @@
if (tcp->th_flags & TH_RST)
return -1; /* feedback loop */
-#ifndef IPFILTER_CKSUM
if (fr_checkl4sum(fin) == -1)
return -1;
-#endif
tlen = fin->fin_dlen - (TCP_OFF(tcp) << 2) +
((tcp->th_flags & TH_SYN) ? 1 : 0) +
@@ -928,7 +712,7 @@
#endif
ip_t *ip, *ip2;
- if ((type < 0) || (type > ICMP_MAXTYPE))
+ if ((type < 0) || (type >= ICMP_MAXTYPE))
return -1;
code = fin->fin_icode;
@@ -937,10 +721,8 @@
return -1;
#endif
-#ifndef IPFILTER_CKSUM
if (fr_checkl4sum(fin) == -1)
return -1;
-#endif
#ifdef MGETHDR
MGETHDR(m, M_DONTWAIT, MT_HEADER);
#else
@@ -1096,7 +878,7 @@
# endif
iplinit()
{
- if (iplattach() != 0)
+ if (ipfattach() != 0)
printf("IP Filter failed to attach\n");
ip_init();
}
@@ -1118,6 +900,8 @@
u_short ip_off;
frentry_t *fr;
+ ro = NULL;
+
#ifdef M_WRITABLE
/*
* HOT FIX/KLUDGE:
@@ -1131,15 +915,15 @@
* problem.
*/
if (M_WRITABLE(m) == 0) {
- if ((m0 = m_dup(m, M_DONTWAIT)) != 0) {
+ m0 = m_dup(m, M_DONTWAIT);
+ if (m0 != 0) {
FREE_MB_T(m);
m = m0;
*mpp = m;
} else {
error = ENOBUFS;
FREE_MB_T(m);
- *mpp = NULL;
- fr_frouteok[1]++;
+ goto done;
}
}
#endif
@@ -1181,18 +965,8 @@
goto bad;
}
- /*
- * In case we're here due to "to <if>" being used with "keep state",
- * check that we're going in the correct direction.
- */
- if ((fr != NULL) && (fin->fin_rev != 0)) {
- if ((ifp != NULL) && (fdp == &fr->fr_tif))
- return -1;
- }
- if (fdp != NULL) {
- if (fdp->fd_ip.s_addr != 0)
- dst->sin_addr = fdp->fd_ip;
- }
+ if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0))
+ dst->sin_addr = fdp->fd_ip;
dst->sin_len = sizeof(*dst);
rtalloc(ro);
@@ -1215,9 +989,11 @@
/*
* 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;
@@ -1226,7 +1002,8 @@
if (!fr || !(fr->fr_flags & FR_RETMASK)) {
u_32_t pass;
- (void) fr_checkstate(fin, &pass);
+ if (fr_checkstate(fin, &pass) != NULL)
+ fr_statederef((ipstate_t **)&fin->fin_state);
}
switch (fr_checknatout(fin, NULL))
@@ -1234,6 +1011,7 @@
case 0 :
break;
case 1 :
+ fr_natderef((nat_t **)&fin->fin_nat);
ip->ip_sum = 0;
break;
case -1 :
@@ -1309,6 +1087,7 @@
else
mhip->ip_off |= IP_MF;
mhip->ip_len = htons((u_short)(len + mhlen));
+ *mnext = m;
m->m_next = m_copy(m0, off, len);
if (m->m_next == 0) {
error = ENOBUFS; /* ??? */
@@ -1319,7 +1098,6 @@
mhip->ip_off = htons((u_short)mhip->ip_off);
mhip->ip_sum = 0;
mhip->ip_sum = in_cksum(m, mhlen);
- *mnext = m;
mnext = &m->m_act;
}
/*
@@ -1348,7 +1126,7 @@
else
fr_frouteok[1]++;
- if (ro->ro_rt) {
+ if ((ro != NULL) && (ro->ro_rt != NULL)) {
RTFREE(ro->ro_rt);
}
*mpp = NULL;
@@ -1451,6 +1229,9 @@
else if (atype == FRI_PEERADDR)
sock = ifa->ifa_dstaddr;
+ if (sock == NULL)
+ return -1;
+
#ifdef USE_INET6
if (v == 6) {
return fr_ifpfillv6addr(atype, (struct sockaddr_in6 *)sock,
@@ -1545,6 +1326,9 @@
if ((fin->fin_flx & FI_NOCKSUM) != 0)
return;
+ if (fin->fin_cksum != 0)
+ return;
+
m = fin->fin_m;
if (m == NULL) {
manual = 1;
@@ -1560,8 +1344,12 @@
htonl(m->m_pkthdr.csum_data +
fin->fin_ip->ip_len + fin->fin_p));
sum ^= 0xffff;
- if (sum != 0)
+ if (sum != 0) {
fin->fin_flx |= FI_BAD;
+ fin->fin_cksum = -1;
+ } else {
+ fin->fin_cksum = 1;
+ }
} else
manual = 1;
skipauto:
@@ -1673,11 +1461,16 @@
m = m_pullup(m, len);
}
*fin->fin_mp = m;
- fin->fin_m = m;
if (m == NULL) {
+ fin->fin_m = NULL;
ATOMIC_INCL(frstats[out].fr_pull[1]);
return NULL;
}
+
+ while (M_LEN(m) == 0) {
+ m = m->m_next;
+ }
+ fin->fin_m = m;
ip = MTOD(m, char *) + ipoff;
}
@@ -1690,3 +1483,167 @@
fin->fin_flx |= FI_COALESCE;
return ip;
}
+
+
+int ipf_inject(fin, m)
+fr_info_t *fin;
+mb_t *m;
+{
+ int error = 0;
+
+ if (fin->fin_out == 0) {
+#if (__FreeBSD_version >= 501000)
+ netisr_dispatch(NETISR_IP, m);
+#else
+ struct ifqueue *ifq;
+
+ ifq = &ipintrq;
+
+# ifdef _IF_QFULL
+ if (_IF_QFULL(ifq))
+# else
+ if (IF_QFULL(ifq))
+# endif
+ {
+# ifdef _IF_DROP
+ _IF_DROP(ifq);
+# else
+ IF_DROP(ifq);
+# endif
+ FREE_MB_T(m);
+ error = ENOBUFS;
+ } else {
+ IF_ENQUEUE(ifq, m);
+ }
+#endif
+ } else {
+ fin->fin_ip->ip_len = ntohs(fin->fin_ip->ip_len);
+ fin->fin_ip->ip_off = ntohs(fin->fin_ip->ip_off);
+#if (__FreeBSD_version >= 470102)
+ error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL);
+#else
+ error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL);
+#endif
+ }
+
+ return error;
+}
+
+int ipf_pfil_unhook(void) {
+#if defined(NETBSD_PF) && (__FreeBSD_version >= 500011)
+# if __FreeBSD_version >= 501108
+ struct pfil_head *ph_inet;
+# ifdef USE_INET6
+ struct pfil_head *ph_inet6;
+# endif
+# endif
+#endif
+
+#ifdef NETBSD_PF
+# if (__FreeBSD_version >= 500011)
+# if (__FreeBSD_version >= 501108)
+ ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
+ if (ph_inet != NULL)
+ pfil_remove_hook((void *)fr_check_wrapper, NULL,
+ PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet);
+# else
+ pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK,
+ &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
+# endif
+# else
+ pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK);
+# endif
+# ifdef USE_INET6
+# if (__FreeBSD_version >= 501108)
+ ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
+ if (ph_inet6 != NULL)
+ pfil_remove_hook((void *)fr_check_wrapper6, NULL,
+ PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet6);
+# else
+ pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK,
+ &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
+# endif
+# endif
+#endif
+
+ return (0);
+}
+
+int ipf_pfil_hook(void) {
+#if defined(NETBSD_PF) && (__FreeBSD_version >= 500011)
+# if __FreeBSD_version >= 501108
+ struct pfil_head *ph_inet;
+# ifdef USE_INET6
+ struct pfil_head *ph_inet6;
+# endif
+# endif
+#endif
+
+# ifdef NETBSD_PF
+# if __FreeBSD_version >= 500011
+# if __FreeBSD_version >= 501108
+ ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
+# ifdef USE_INET6
+ ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
+# endif
+ if (ph_inet == NULL
+# ifdef USE_INET6
+ && ph_inet6 == NULL
+# endif
+ )
+ return ENODEV;
+
+ if (ph_inet != NULL)
+ pfil_add_hook((void *)fr_check_wrapper, NULL,
+ PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet);
+# else
+ pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK,
+ &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
+# endif
+# else
+ pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK);
+# endif
+# ifdef USE_INET6
+# if __FreeBSD_version >= 501108
+ if (ph_inet6 != NULL)
+ pfil_add_hook((void *)fr_check_wrapper6, NULL,
+ PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet6);
+# else
+ pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK,
+ &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
+# endif
+# endif
+# endif
+ return (0);
+}
+
+void
+ipf_event_reg(void)
+{
+#if (__FreeBSD_version >= 502103)
+ ipf_arrivetag = EVENTHANDLER_REGISTER(ifnet_arrival_event, \
+ ipf_ifevent, NULL, \
+ EVENTHANDLER_PRI_ANY);
+ ipf_departtag = EVENTHANDLER_REGISTER(ifnet_departure_event, \
+ ipf_ifevent, NULL, \
+ EVENTHANDLER_PRI_ANY);
+ ipf_clonetag = EVENTHANDLER_REGISTER(if_clone_event, ipf_ifevent, \
+ NULL, EVENTHANDLER_PRI_ANY);
+#endif
+}
+
+void
+ipf_event_dereg(void)
+{
+#if (__FreeBSD_version >= 502103)
+ if (ipf_arrivetag != NULL) {
+ EVENTHANDLER_DEREGISTER(ifnet_arrival_event, ipf_arrivetag);
+ }
+ if (ipf_departtag != NULL) {
+ EVENTHANDLER_DEREGISTER(ifnet_departure_event, ipf_departtag);
+ }
+ if (ipf_clonetag != NULL) {
+ EVENTHANDLER_DEREGISTER(if_clone_event, ipf_clonetag);
+ }
+#endif
+}
Index: ip_auth.c
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_auth.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_auth.c -L sys/contrib/ipfilter/netinet/ip_auth.c -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_auth.c
+++ sys/contrib/ipfilter/netinet/ip_auth.c
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_auth.c,v 1.40 2005/04/27 03:48:09 darrenr Exp $ */
+/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_auth.c,v 1.44.2.2 2007/12/01 00:53:41 darrenr Exp $ */
/*
* Copyright (C) 1998-2003 by Darren Reed & Guido van Rooij.
@@ -52,7 +52,8 @@
# include <sys/stream.h>
# include <sys/kmem.h>
#endif
-#if (_BSDI_VERSION >= 199802) || (__FreeBSD_version >= 400000)
+#if (defined(_BSDI_VERSION) && _BSDI_VERSION >= 199802) || \
+ (__FreeBSD_version >= 400000)
# include <sys/queue.h>
#endif
#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(bsdi)
@@ -119,13 +120,14 @@
/* END OF INCLUDES */
#if !defined(lint)
-static const char rcsid[] = "@(#)$FreeBSD: src/sys/contrib/ipfilter/netinet/ip_auth.c,v 1.40 2005/04/27 03:48:09 darrenr Exp $";
-/* static const char rcsid[] = "@(#)Id: ip_auth.c,v 2.73.2.3 2004/08/26 11:25:21 darrenr Exp"; */
+static const char rcsid[] = "@(#)$FreeBSD: src/sys/contrib/ipfilter/netinet/ip_auth.c,v 1.44.2.2 2007/12/01 00:53:41 darrenr Exp $";
+/* static const char rcsid[] = "@(#)$Id: ip_auth.c,v 2.73.2.24 2007/09/09 11:32:04 darrenr Exp $"; */
#endif
-#if SOLARIS
+#if SOLARIS && defined(_KERNEL)
extern kcondvar_t ipfauthwait;
+extern struct pollhead iplpollhead[IPL_LOGSIZE];
#endif /* SOLARIS */
#if defined(linux) && defined(_KERNEL)
wait_queue_head_t fr_authnext_linux;
@@ -144,7 +146,19 @@
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));
@@ -174,11 +188,16 @@
}
-/*
- * 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;
@@ -235,7 +254,12 @@
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;
@@ -277,11 +301,16 @@
}
-/*
- * 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 - 1 == success, 0 = did not put packet on auth queue */
+/* Parameters: m(I) - pointer to mb_t with packet in it */
+/* fin(I) - pointer to packet information */
+/* */
+/* Check if we have room in the auth array to hold details for another */
+/* packet. If we do, store it and wake up any user programs which are */
+/* waiting to hear about these events. */
+/* ------------------------------------------------------------------------ */
int fr_newauth(m, fin)
mb_t *m;
fr_info_t *fin;
@@ -299,16 +328,10 @@
return 0;
WRITE_ENTER(&ipf_auth);
- if (fr_authstart > fr_authend) {
+ if (((fr_authend + 1) % fr_authsize) == fr_authstart) {
fr_authstats.fas_nospace++;
RWLOCK_EXIT(&ipf_auth);
return 0;
- } else {
- if (fr_authused == fr_authsize) {
- fr_authstats.fas_nospace++;
- RWLOCK_EXIT(&ipf_auth);
- return 0;
- }
}
fr_authstats.fas_added++;
@@ -316,11 +339,14 @@
i = fr_authend++;
if (fr_authend == fr_authsize)
fr_authend = 0;
- RWLOCK_EXIT(&ipf_auth);
-
fra = fr_auth + i;
fra->fra_index = i;
- fra->fra_pass = 0;
+ RWLOCK_EXIT(&ipf_auth);
+
+ if (fin->fin_fr != NULL)
+ fra->fra_pass = fin->fin_fr->fr_flags;
+ else
+ fra->fra_pass = 0;
fra->fra_age = fr_defaultauthage;
bcopy((char *)fin, (char *)&fra->fra_info, sizeof(*fin));
#if !defined(sparc) && !defined(m68k)
@@ -342,17 +368,17 @@
}
#endif
#if SOLARIS && defined(_KERNEL)
+ COPYIFNAME(fin->fin_v, fin->fin_ifp, fra->fra_info.fin_ifname);
m->b_rptr -= qpi->qpi_off;
fr_authpkts[i] = *(mblk_t **)fin->fin_mp;
+# if !defined(_INET_IP_STACK_H)
fra->fra_q = qpi->qpi_q; /* The queue can disappear! */
+# endif
+ fra->fra_m = *fin->fin_mp;
+ fra->fra_info.fin_mp = &fra->fra_m;
cv_signal(&ipfauthwait);
+ pollwakeup(&iplpollhead[IPL_LOGAUTH], POLLIN|POLLRDNORM);
#else
-# if defined(BSD) && !defined(sparc) && (BSD >= 199306)
- if (!fin->fin_out) {
- ip->ip_len = htons(ip->ip_len);
- ip->ip_off = htons(ip->ip_off);
- }
-# endif
fr_authpkts[i] = m;
WAKEUP(&fr_authnext,0);
#endif
@@ -360,31 +386,65 @@
}
-int fr_auth_ioctl(data, cmd, mode)
+/* ------------------------------------------------------------------------ */
+/* Function: fr_auth_ioctl */
+/* Returns: int - 0 == success, else error */
+/* Parameters: data(IO) - pointer to ioctl data */
+/* cmd(I) - ioctl command */
+/* mode(I) - mode flags associated with open descriptor */
+/* uid(I) - uid associatd with application making the call */
+/* ctx(I) - pointer for context */
+/* */
+/* This function handles all of the ioctls recognised by the auth component */
+/* in IPFilter - ie ioctls called on an open fd for /dev/ipauth */
+/* ------------------------------------------------------------------------ */
+int fr_auth_ioctl(data, cmd, mode, uid, ctx)
caddr_t data;
ioctlcmd_t cmd;
-int mode;
+int mode, uid;
+void *ctx;
{
- mb_t *m;
-#if defined(_KERNEL) && !defined(MENTAT) && !defined(linux) && \
- (!defined(__FreeBSD_version) || (__FreeBSD_version < 501000))
- struct ifqueue *ifq;
-# ifdef USE_SPL
- int s;
-# endif /* USE_SPL */
-#endif
- frauth_t auth, *au = &auth, *fra;
- int i, error = 0, len;
- char *t;
+ int error = 0, i;
+ SPL_INT(s);
switch (cmd)
{
+ case SIOCGENITER :
+ {
+ ipftoken_t *token;
+ ipfgeniter_t iter;
+
+ error = fr_inobj(data, &iter, IPFOBJ_GENITER);
+ if (error != 0)
+ break;
+
+ SPL_SCHED(s);
+ token = ipf_findtoken(IPFGENITER_AUTH, uid, ctx);
+ if (token != NULL)
+ error = fr_authgeniter(token, &iter);
+ else
+ error = ESRCH;
+ RWLOCK_EXIT(&ipf_tokens);
+ SPL_X(s);
+
+ break;
+ }
+
+ case SIOCADAFR :
+ case SIOCRMAFR :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else
+ error = frrequest(IPL_LOGAUTH, cmd, data,
+ fr_active, 1);
+ break;
+
case SIOCSTLCK :
if (!(mode & FWRITE)) {
error = EPERM;
break;
}
- fr_lock(data, &fr_auth_lock);
+ error = fr_lock(data, &fr_auth_lock);
break;
case SIOCATHST:
@@ -398,195 +458,17 @@
i = fr_authflush();
RWLOCK_EXIT(&ipf_auth);
SPL_X(s);
- error = copyoutptr((char *)&i, data, sizeof(i));
+ error = BCOPYOUT((char *)&i, data, sizeof(i));
+ if (error != 0)
+ error = EFAULT;
break;
case SIOCAUTHW:
-fr_authioctlloop:
- error = fr_inobj(data, au, IPFOBJ_FRAUTH);
- READ_ENTER(&ipf_auth);
- if ((fr_authnext != fr_authend) && fr_authpkts[fr_authnext]) {
- error = fr_outobj(data, &fr_auth[fr_authnext],
- IPFOBJ_FRAUTH);
- if (auth.fra_len != 0 && auth.fra_buf != NULL) {
- /*
- * Copy packet contents out to user space if
- * requested. Bail on an error.
- */
- m = fr_authpkts[fr_authnext];
- len = MSGDSIZE(m);
- if (len > auth.fra_len)
- len = auth.fra_len;
- auth.fra_len = len;
- for (t = auth.fra_buf; m && (len > 0); ) {
- i = MIN(M_LEN(m), len);
- error = copyoutptr(MTOD(m, char *),
- t, i);
- len -= i;
- t += i;
- if (error != 0)
- break;
- }
- }
- RWLOCK_EXIT(&ipf_auth);
- if (error != 0)
- break;
- SPL_NET(s);
- WRITE_ENTER(&ipf_auth);
- fr_authnext++;
- if (fr_authnext == fr_authsize)
- fr_authnext = 0;
- RWLOCK_EXIT(&ipf_auth);
- SPL_X(s);
- return 0;
- }
- RWLOCK_EXIT(&ipf_auth);
- /*
- * We exit ipf_global here because a program that enters in
- * here will have a lock on it and goto sleep having this lock.
- * If someone were to do an 'ipf -D' the system would then
- * deadlock. The catch with releasing it here is that the
- * caller of this function expects it to be held when we
- * return so we have to reacquire it in here.
- */
- RWLOCK_EXIT(&ipf_global);
-
- MUTEX_ENTER(&ipf_authmx);
-#ifdef _KERNEL
-# if SOLARIS
- error = 0;
- if (!cv_wait_sig(&ipfauthwait, &ipf_authmx.ipf_lk))
- error = EINTR;
-# else /* SOLARIS */
-# ifdef __hpux
- {
- lock_t *l;
-
- l = get_sleep_lock(&fr_authnext);
- error = sleep(&fr_authnext, PZERO+1);
- spinunlock(l);
- }
-# else
-# ifdef __osf__
- error = mpsleep(&fr_authnext, PSUSP|PCATCH, "fr_authnext", 0,
- &ipf_authmx, MS_LOCK_SIMPLE);
-# else
- error = SLEEP(&fr_authnext, "fr_authnext");
-# endif /* __osf__ */
-# endif /* __hpux */
-# endif /* SOLARIS */
-#endif
- MUTEX_EXIT(&ipf_authmx);
- READ_ENTER(&ipf_global);
- if (error == 0) {
- READ_ENTER(&ipf_auth);
- goto fr_authioctlloop;
- }
+ error = 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;
- if ((i < 0) || (i >= fr_authsize) ||
- (fra->fra_info.fin_id != au->fra_info.fin_id)) {
- RWLOCK_EXIT(&ipf_auth);
- SPL_X(s);
- return ESRCH;
- }
- m = fr_authpkts[i];
- fra->fra_index = -2;
- fra->fra_pass = au->fra_pass;
- fr_authpkts[i] = NULL;
- RWLOCK_EXIT(&ipf_auth);
-#ifdef _KERNEL
- if ((m != NULL) && (au->fra_info.fin_out != 0)) {
-# ifdef MENTAT
- error = !putq(fra->fra_q, m);
-# else /* MENTAT */
-# ifdef linux
-# else
-# if (_BSDI_VERSION >= 199802) || defined(__OpenBSD__) || \
- (defined(__sgi) && (IRIX >= 60500) || \
- (defined(__FreeBSD__) && (__FreeBSD_version >= 470102)))
- error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL,
- NULL);
-# else
- error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL);
-# endif
-# endif /* Linux */
-# endif /* MENTAT */
- if (error != 0)
- fr_authstats.fas_sendfail++;
- else
- fr_authstats.fas_sendok++;
- } else if (m) {
-# ifdef MENTAT
- error = !putq(fra->fra_q, m);
-# else /* MENTAT */
-# ifdef linux
-# else
-# if __FreeBSD_version >= 501000
- netisr_dispatch(NETISR_IP, m);
-# else
-# if IRIX >= 60516
- ifq = &((struct ifnet *)fra->fra_info.fin_ifp)->if_snd;
-# else
- ifq = &ipintrq;
-# endif
- if (IF_QFULL(ifq)) {
- IF_DROP(ifq);
- FREE_MB_T(m);
- error = ENOBUFS;
- } else {
- IF_ENQUEUE(ifq, m);
-# if IRIX < 60500
- schednetisr(NETISR_IP);
-# endif
- }
-# endif
-# endif /* Linux */
-# endif /* MENTAT */
- if (error != 0)
- fr_authstats.fas_quefail++;
- else
- fr_authstats.fas_queok++;
- } else
- error = EINVAL;
-# ifdef MENTAT
- if (error != 0)
- error = EINVAL;
-# else /* MENTAT */
- /*
- * If we experience an error which will result in the packet
- * not being processed, make sure we advance to the next one.
- */
- if (error == ENOBUFS) {
- fr_authused--;
- fra->fra_index = -1;
- fra->fra_pass = 0;
- if (i == fr_authstart) {
- while (fra->fra_index == -1) {
- i++;
- if (i == fr_authsize)
- i = 0;
- fr_authstart = i;
- if (i == fr_authend)
- break;
- }
- if (fr_authstart == fr_authend) {
- fr_authnext = 0;
- fr_authstart = fr_authend = 0;
- }
- }
- }
-# endif /* MENTAT */
-#endif /* _KERNEL */
- SPL_X(s);
+ error = fr_authreply(data);
break;
default :
@@ -597,9 +479,13 @@
}
-/*
- * 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;
@@ -653,20 +539,22 @@
}
-/*
- * 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;
-# if !defined(MENAT) && defined(_KERNEL) && defined(USE_SPL)
- int s;
-# endif
+ int i;
+ SPL_INT(s);
if (fr_auth_lock)
return;
@@ -684,11 +572,13 @@
}
}
+ /*
+ * 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;
@@ -709,19 +599,26 @@
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;
{
frauthent_t *fae, **faep;
int error = 0;
-# if !defined(MENAT) && defined(_KERNEL) && defined(USE_SPL)
- int s;
-#endif
+ SPL_INT(s);
if ((cmd != SIOCADAFR) && (cmd != SIOCRMAFR))
return EIO;
-
+
for (faep = &fae_list; ((fae = *faep) != NULL); ) {
if (&fae->fae_fr == fr)
break;
@@ -755,6 +652,7 @@
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;
@@ -769,11 +667,18 @@
}
-/*
- * 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;
@@ -803,3 +708,336 @@
return num_flushed;
}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: fr_auth_waiting */
+/* Returns: int - 0 = no pakcets wiating, 1 = packets waiting. */
+/* Parameters: None */
+/* */
+/* Simple truth check to see if there are any packets waiting in the auth */
+/* queue. */
+/* ------------------------------------------------------------------------ */
+int fr_auth_waiting()
+{
+ return (fr_authused != 0);
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: fr_authgeniter */
+/* Returns: int - 0 == success, else error */
+/* Parameters: token(I) - pointer to ipftoken structure */
+/* itp(I) - pointer to ipfgeniter structure */
+/* */
+/* ------------------------------------------------------------------------ */
+int fr_authgeniter(token, itp)
+ipftoken_t *token;
+ipfgeniter_t *itp;
+{
+ frauthent_t *fae, *next, zero;
+ int error;
+
+ if (itp->igi_data == NULL)
+ return EFAULT;
+
+ if (itp->igi_type != IPFGENITER_AUTH)
+ return EINVAL;
+
+ fae = token->ipt_data;
+ READ_ENTER(&ipf_auth);
+ if (fae == NULL) {
+ next = fae_list;
+ } else {
+ next = fae->fae_next;
+ }
+
+ if (next != NULL) {
+ /*
+ * If we find an auth entry to use, bump its reference count
+ * so that it can be used for is_next when we come back.
+ */
+ ATOMIC_INC(next->fae_ref);
+ if (next->fae_next == NULL) {
+ ipf_freetoken(token);
+ token = NULL;
+ } else {
+ token->ipt_data = next;
+ }
+ } else {
+ bzero(&zero, sizeof(zero));
+ next = &zero;
+ }
+ RWLOCK_EXIT(&ipf_auth);
+
+ /*
+ * If we had a prior pointer to an auth entry, release it.
+ */
+ if (fae != NULL) {
+ WRITE_ENTER(&ipf_auth);
+ fr_authderef(&fae);
+ RWLOCK_EXIT(&ipf_auth);
+ }
+
+ /*
+ * This should arguably be via fr_outobj() so that the auth
+ * structure can (if required) be massaged going out.
+ */
+ error = COPYOUT(next, itp->igi_data, sizeof(*next));
+ if (error != 0)
+ error = EFAULT;
+
+ return error;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: fr_authderef */
+/* Returns: None */
+/* Parameters: faep(IO) - pointer to caller's frauthent_t pointer */
+/* Locks: WRITE(ipf_auth) */
+/* */
+/* This function unconditionally sets the pointer in the caller to NULL, */
+/* to make it clear that it should no longer use that pointer, and drops */
+/* the reference count on the structure by 1. If it reaches 0, free it up. */
+/* ------------------------------------------------------------------------ */
+void fr_authderef(faep)
+frauthent_t **faep;
+{
+ frauthent_t *fae;
+
+ fae = *faep;
+ *faep = NULL;
+
+ fae->fae_ref--;
+ if (fae->fae_ref == 0) {
+ KFREE(fae);
+ }
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: fr_authwait */
+/* Returns: int - 0 == success, else error */
+/* Parameters: data(I) - pointer to data from ioctl call */
+/* */
+/* This function is called when an application is waiting for a packet to */
+/* match an "auth" rule by issuing an SIOCAUTHW ioctl. If there is already */
+/* a packet waiting on the queue then we will return that _one_ immediately.*/
+/* If there are no packets present in the queue (fr_authpkts) then we go to */
+/* sleep. */
+/* ------------------------------------------------------------------------ */
+int fr_authwait(data)
+char *data;
+{
+ frauth_t auth, *au = &auth;
+ int error, len, i;
+ mb_t *m;
+ char *t;
+#if defined(_KERNEL) && !defined(MENTAT) && !defined(linux) && \
+ (!defined(__FreeBSD_version) || (__FreeBSD_version < 501000))
+ SPL_INT(s);
+#endif
+
+fr_authioctlloop:
+ error = fr_inobj(data, au, IPFOBJ_FRAUTH);
+ if (error != 0)
+ return error;
+
+ /*
+ * XXX Locks are held below over calls to copyout...a better
+ * solution needs to be found so this isn't necessary. The situation
+ * we are trying to guard against here is an error in the copyout
+ * steps should not cause the packet to "disappear" from the queue.
+ */
+ READ_ENTER(&ipf_auth);
+
+ /*
+ * If fr_authnext is not equal to fr_authend it will be because there
+ * is a packet waiting to be delt with in the fr_authpkts array. We
+ * copy as much of that out to user space as requested.
+ */
+ if (fr_authused > 0) {
+ while (fr_authpkts[fr_authnext] == NULL) {
+ fr_authnext++;
+ if (fr_authnext == fr_authsize)
+ fr_authnext = 0;
+ }
+
+ 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);
+
+ 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);
+
+ 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);
+ 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) {
+ WRITE_ENTER(&ipf_auth);
+ 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;
+ }
+ }
+ RWLOCK_EXIT(&ipf_auth);
+ }
+#endif /* _KERNEL */
+ SPL_X(s);
+
+ return 0;
+}
Index: ip_fil.h
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_fil.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_fil.h -L sys/contrib/ipfilter/netinet/ip_fil.h -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_fil.h
+++ sys/contrib/ipfilter/netinet/ip_fil.h
@@ -1,13 +1,11 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_fil.h,v 1.31 2005/04/26 17:58:05 darrenr Exp $ */
-
/*
* Copyright (C) 1993-2001, 2003 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* @(#)ip_fil.h 1.35 6/5/96
- * $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_fil.h,v 1.31 2005/04/26 17:58:05 darrenr Exp $
- * Id: ip_fil.h,v 2.170.2.18 2005/03/28 10:47:52 darrenr Exp
+ * $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_fil.h,v 1.35.2.1 2007/10/31 05:00:37 darrenr Exp $
+ * Id: ip_fil.h,v 2.170.2.51 2007/10/10 09:48:03 darrenr Exp $
*/
#ifndef __IP_FIL_H__
@@ -27,7 +25,7 @@
# endif
#endif
-#if defined(__STDC__) || defined(__GNUC__)
+#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51)
# define SIOCADAFR _IOW('r', 60, struct ipfobj)
# define SIOCRMAFR _IOW('r', 61, struct ipfobj)
# define SIOCSETFF _IOW('r', 62, u_int)
@@ -46,12 +44,12 @@
# define SIOCZRLST _IOWR('r', 75, struct ipfobj)
# define SIOCAUTHW _IOWR('r', 76, struct ipfobj)
# define SIOCAUTHR _IOWR('r', 77, struct ipfobj)
-# define SIOCATHST _IOWR('r', 78, struct ipfobj)
+# define SIOCSTAT1 _IOWR('r', 78, struct ipfobj)
# define SIOCSTLCK _IOWR('r', 79, u_int)
# define SIOCSTPUT _IOWR('r', 80, struct ipfobj)
# define SIOCSTGET _IOWR('r', 81, struct ipfobj)
# define SIOCSTGSZ _IOWR('r', 82, struct ipfobj)
-# define SIOCGFRST _IOWR('r', 83, struct ipfobj)
+# define SIOCSTAT2 _IOWR('r', 83, struct ipfobj)
# define SIOCSETLG _IOWR('r', 84, int)
# define SIOCGETLG _IOWR('r', 85, int)
# define SIOCFUNCL _IOWR('r', 86, struct ipfunc_resolve)
@@ -59,6 +57,12 @@
# define SIOCIPFGET _IOWR('r', 88, struct ipfobj)
# define SIOCIPFSET _IOWR('r', 89, struct ipfobj)
# define SIOCIPFL6 _IOWR('r', 90, int)
+# define SIOCIPFITER _IOWR('r', 91, struct ipfobj)
+# define SIOCGENITER _IOWR('r', 92, struct ipfobj)
+# define SIOCGTABL _IOWR('r', 93, struct ipfobj)
+# define SIOCIPFDELTOK _IOWR('r', 94, int)
+# define SIOCLOOKUPITER _IOWR('r', 95, struct ipfobj)
+# define SIOCGTQTAB _IOWR('r', 96, struct ipfobj)
#else
# define SIOCADAFR _IOW(r, 60, struct ipfobj)
# define SIOCRMAFR _IOW(r, 61, struct ipfobj)
@@ -78,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)
@@ -91,10 +95,18 @@
# define SIOCIPFGET _IOWR(r, 88, struct ipfobj)
# define SIOCIPFSET _IOWR(r, 89, struct ipfobj)
# define SIOCIPFL6 _IOWR(r, 90, int)
+# define SIOCIPFITER _IOWR(r, 91, struct ipfobj)
+# define SIOCGENITER _IOWR(r, 92, struct ipfobj)
+# define SIOCGTABL _IOWR(r, 93, struct ipfobj)
+# define SIOCIPFDELTOK _IOWR(r, 94, int)
+# define SIOCLOOKUPITER _IOWR(r, 95, struct ipfobj)
+# define SIOCGTQTAB _IOWR(r, 96, struct ipfobj)
#endif
#define SIOCADDFR SIOCADAFR
#define SIOCDELFR SIOCRMAFR
#define SIOCINSFR SIOCINAFR
+#define SIOCATHST SIOCSTAT1
+#define SIOCGFRST SIOCSTAT2
struct ipscan;
@@ -114,6 +126,11 @@
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 {
@@ -121,26 +138,33 @@
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.
*/
#define iplookupptr vptr[0]
#define iplookupfunc lptr[1]
-#define I60(x) (((i6addr_t *)(x))->i6[0])
-#define I61(x) (((i6addr_t *)(x))->i6[1])
-#define I62(x) (((i6addr_t *)(x))->i6[2])
-#define I63(x) (((i6addr_t *)(x))->i6[3])
-#define HI60(x) ntohl(((i6addr_t *)(x))->i6[0])
-#define HI61(x) ntohl(((i6addr_t *)(x))->i6[1])
-#define HI62(x) ntohl(((i6addr_t *)(x))->i6[2])
-#define HI63(x) ntohl(((i6addr_t *)(x))->i6[3])
+#define I60(x) (((u_32_t *)(x))[0])
+#define I61(x) (((u_32_t *)(x))[1])
+#define I62(x) (((u_32_t *)(x))[2])
+#define I63(x) (((u_32_t *)(x))[3])
+#define HI60(x) ntohl(((u_32_t *)(x))[0])
+#define HI61(x) ntohl(((u_32_t *)(x))[1])
+#define HI62(x) ntohl(((u_32_t *)(x))[2])
+#define HI63(x) ntohl(((u_32_t *)(x))[3])
#define IP6_EQ(a,b) ((I63(a) == I63(b)) && (I62(a) == I62(b)) && \
(I61(a) == I61(b)) && (I60(a) == I60(b)))
@@ -158,14 +182,14 @@
HI63(a) < HI63(b)))))))
#define NLADD(n,x) htonl(ntohl(n) + (x))
#define IP6_INC(a) \
- { i6addr_t *_i6 = (i6addr_t *)(a); \
- _i6->i6[0] = NLADD(_i6->i6[0], 1); \
- if (_i6->i6[0] == 0) { \
- _i6->i6[0] = NLADD(_i6->i6[1], 1); \
- if (_i6->i6[1] == 0) { \
- _i6->i6[0] = NLADD(_i6->i6[2], 1); \
- if (_i6->i6[2] == 0) { \
- _i6->i6[0] = NLADD(_i6->i6[3], 1); \
+ { u_32_t *_i6 = (u_32_t *)(a); \
+ _i6[3] = NLADD(_i6[3], 1); \
+ if (_i6[3] == 0) { \
+ _i6[2] = NLADD(_i6[2], 1); \
+ if (_i6[2] == 0) { \
+ _i6[1] = NLADD(_i6[1], 1); \
+ if (_i6[1] == 0) { \
+ _i6[0] = NLADD(_i6[0], 1); \
} \
} \
} \
@@ -239,11 +263,12 @@
#define FI_FRAGBODY 0x2000
#define FI_BADSRC 0x4000
#define FI_LOWTTL 0x8000
-#define FI_CMP 0xcfe3 /* Not FI_FRAG,FI_NATED,FI_FRAGTAIL */
+#define FI_CMP 0xcf03 /* Not FI_FRAG,FI_NATED,FI_FRAGTAIL,broadcast */
#define FI_ICMPCMP 0x0003 /* Flags we can check for ICMP error packets */
#define FI_WITH 0xeffe /* Not FI_TCPUDP */
#define FI_V6EXTHDR 0x10000
#define FI_COALESCE 0x20000
+#define FI_NEWNAT 0x40000
#define FI_NOCKSUM 0x20000000 /* don't do a L4 checksum validation */
#define FI_DONTCACHE 0x40000000 /* don't cache the result */
#define FI_IGNORE 0x80000000
@@ -252,8 +277,12 @@
#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
@@ -299,15 +328,18 @@
u_short fin_off;
int fin_depth; /* Group nesting depth */
int fin_error; /* Error code to return */
+ int fin_cksum; /* -1 bad, 1 good, 0 not done */
void *fin_nat;
void *fin_state;
void *fin_nattag;
+ void *fin_exthdr;
ip_t *fin_ip;
mb_t **fin_mp; /* pointer to pointer to mbuf */
mb_t *fin_m; /* pointer to mbuf */
#ifdef MENTAT
mb_t *fin_qfm; /* pointer to mblk where pkt starts */
void *fin_qpi;
+ char fin_ifname[LIFNAMSIZ];
#endif
#ifdef __sgi
void *fin_hbuf;
@@ -331,8 +363,8 @@
#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 +474,13 @@
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 +506,13 @@
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 +539,6 @@
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 +598,14 @@
#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
@@ -907,6 +955,7 @@
#define TCP_WSCALE_SEEN 0x00000001
#define TCP_WSCALE_FIRST 0x00000002
+#define TCP_SACK_PERMIT 0x00000004
typedef struct tcpinfo {
@@ -916,6 +965,9 @@
} tcpinfo_t;
+/*
+ * Structures to define a GRE header as seen in a packet.
+ */
struct grebits {
u_32_t grb_C:1;
u_32_t grb_R:1;
@@ -950,7 +1002,9 @@
#define gr_A gr_bits.grb_A
#define gr_ver gr_bits.grb_ver
-
+/*
+ * GRE information tracked by "keep state"
+ */
typedef struct greinfo {
u_short gs_call[2];
u_short gs_flags;
@@ -961,6 +1015,20 @@
/*
+ * Format of an Authentication header
+ */
+typedef struct authhdr {
+ u_char ah_next;
+ u_char ah_plen;
+ u_short ah_reserved;
+ u_32_t ah_spi;
+ u_32_t ah_seq;
+ /* Following the sequence number field is 0 or more bytes of */
+ /* authentication data, as specified by ah_plen - RFC 2402. */
+} authhdr_t;
+
+
+/*
* Timeout tail queue list member
*/
typedef struct ipftqent {
@@ -1000,6 +1068,8 @@
/* checks its timeout queues. */
#define IPF_TTLVAL(x) (((x) / IPF_HZ_MULT) * IPF_HZ_DIVIDE)
+typedef int (*ipftq_delete_fn_t)(void *);
+
/*
* Structure to define address for pool lookups.
*/
@@ -1035,6 +1105,13 @@
#define IPFOBJ_STATESTAT 11 /* struct ips_stat */
#define IPFOBJ_FRAUTH 12 /* struct frauth */
#define IPFOBJ_TUNEABLE 13 /* struct ipftune */
+#define IPFOBJ_NAT 14 /* struct nat */
+#define IPFOBJ_IPFITER 15 /* struct ipfruleiter */
+#define IPFOBJ_GENITER 16 /* struct ipfgeniter */
+#define IPFOBJ_GTABLE 17 /* struct ipftable */
+#define IPFOBJ_LOOKUPITER 18 /* struct ipflookupiter */
+#define IPFOBJ_STATETQTAB 19 /* struct ipftq [NSTATES] */
+#define IPFOBJ_COUNT 20 /* How many #defines are above this? */
typedef union ipftunevalptr {
@@ -1047,7 +1124,7 @@
typedef struct ipftuneable {
ipftunevalptr_t ipft_una;
- char *ipft_name;
+ const char *ipft_name;
u_long ipft_min;
u_long ipft_max;
int ipft_sz;
@@ -1086,6 +1163,68 @@
#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
+#define IPFTABLE_BUCKETS_NATIN 2
+#define IPFTABLE_BUCKETS_NATOUT 3
+
+
+/*
+ *
+ */
+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
@@ -1108,7 +1247,7 @@
#if (defined(NetBSD) && (NetBSD > 199609) && (NetBSD <= 1991011)) || \
(defined(NetBSD1_2) && NetBSD1_2 > 1) || \
(defined(__FreeBSD__) && (__FreeBSD_version >= 500043))
-# if (NetBSD >= 199905)
+# if defined(NetBSD) && (NetBSD >= 199905)
# define PFIL_HOOKS
# endif
# ifdef PFIL_HOOKS
@@ -1116,6 +1255,17 @@
# endif
#endif
+#ifdef _KERNEL
+# define FR_VERBOSE(verb_pr)
+# define FR_DEBUG(verb_pr)
+#else
+extern void debug __P((char *, ...));
+extern void verbose __P((char *, ...));
+# define FR_VERBOSE(verb_pr) verbose verb_pr
+# define FR_DEBUG(verb_pr) debug verb_pr
+#endif
+
+
#ifndef _KERNEL
extern int fr_check __P((struct ip *, int, void *, int, mb_t **));
extern int (*fr_checkp) __P((ip_t *, int, void *, int, mb_t **));
@@ -1131,12 +1281,24 @@
extern int iplopen __P((dev_t, int));
extern int iplclose __P((dev_t, int));
extern void m_freem __P((mb_t *));
+extern int bcopywrap __P((void *, void *, size_t));
#else /* #ifndef _KERNEL */
+# ifdef BSD
+# if (defined(__NetBSD__) && (__NetBSD_Version__ < 399000000)) || \
+ defined(__osf__) || \
+ (defined(__FreeBSD_version) && (__FreeBSD_version < 500043))
+# include <sys/select.h>
+# else
+# include <sys/selinfo.h>
+# endif
+extern struct selinfo ipfselwait[IPL_LOGSIZE];
+# endif
# if defined(__NetBSD__) && defined(PFIL_HOOKS)
extern void ipfilterattach __P((int));
# endif
extern int ipl_enable __P((void));
extern int ipl_disable __P((void));
+extern int ipf_inject __P((fr_info_t *, mb_t *));
# ifdef MENTAT
extern int fr_check __P((struct ip *, int, void *, int, void *,
mblk_t **));
@@ -1159,7 +1321,6 @@
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 **));
@@ -1172,7 +1333,6 @@
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));
@@ -1180,9 +1340,11 @@
# ifdef IPFILTER_LKM
extern int iplidentify __P((char *));
# endif
-# if (_BSDI_VERSION >= 199510) || (__FreeBSD_version >= 220000) || \
+# if (defined(_BSDI_VERSION) && _BSDI_VERSION >= 199510) || \
+ (__FreeBSD_version >= 220000) || \
(NetBSD >= 199511) || defined(__OpenBSD__)
-# if defined(__NetBSD__) || (_BSDI_VERSION >= 199701) || \
+# if defined(__NetBSD__) || \
+ (defined(_BSDI_VERSION) && _BSDI_VERSION >= 199701) || \
defined(__OpenBSD__) || (__FreeBSD_version >= 300000)
# if (__FreeBSD_version >= 500024)
# if (__FreeBSD_version >= 502116)
@@ -1191,7 +1353,15 @@
extern int iplioctl __P((dev_t, u_long, caddr_t, int, struct thread *));
# endif /* __FreeBSD_version >= 502116 */
# else
+# if (__NetBSD_Version__ >= 499001000)
+extern int iplioctl __P((dev_t, u_long, void *, int, struct lwp *));
+# else
+# if (__NetBSD_Version__ >= 399001400)
+extern int iplioctl __P((dev_t, u_long, caddr_t, int, struct lwp *));
+# else
extern int iplioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
+# endif
+# endif
# endif /* __FreeBSD_version >= 500024 */
# else
extern int iplioctl __P((dev_t, int, caddr_t, int, struct thread *));
@@ -1205,8 +1375,13 @@
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
@@ -1234,26 +1409,35 @@
# endif /* __ sgi */
# endif /* MENTAT */
+# if defined(__FreeBSD_version)
+extern int ipf_pfil_hook __P((void));
+extern int ipf_pfil_unhook __P((void));
+extern void ipf_event_reg __P((void));
+extern void ipf_event_dereg __P((void));
+# endif
+
#endif /* #ifndef _KERNEL */
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, ipf_tokens;
-extern char *memstr __P((char *, char *, int, int));
+extern char *memstr __P((const char *, char *, size_t, size_t));
extern int count4bits __P((u_32_t));
extern int frrequest __P((int, ioctlcmd_t, caddr_t, int, int));
extern char *getifname __P((struct ifnet *));
-extern int iplattach __P((void));
-extern int ipldetach __P((void));
+extern int ipfattach __P((void));
+extern int ipfdetach __P((void));
extern u_short ipf_cksum __P((u_short *, int));
extern int copyinptr __P((void *, void *, size_t));
extern int copyoutptr __P((void *, void *, size_t));
extern int fr_fastroute __P((mb_t *, mb_t **, fr_info_t *, frdest_t *));
extern int fr_inobj __P((void *, void *, int));
extern int fr_inobjsz __P((void *, void *, int, int));
-extern int fr_ioctlswitch __P((int, void *, ioctlcmd_t, int));
+extern int fr_ioctlswitch __P((int, void *, ioctlcmd_t, int, int, void *));
+extern int fr_ipf_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *));
extern int fr_ipftune __P((ioctlcmd_t, void *));
extern int fr_outobj __P((void *, void *, int));
extern int fr_outobjsz __P((void *, void *, int, int));
@@ -1263,7 +1447,7 @@
extern void *fr_resolvenic __P((char *, int));
extern int fr_send_icmp_err __P((int, fr_info_t *, int));
extern int fr_send_reset __P((fr_info_t *));
-#if (__FreeBSD_version < 490000) || !defined(_KERNEL)
+#if (__FreeBSD_version < 501000) || !defined(_KERNEL)
extern int ppsratecheck __P((struct timeval *, int *, int));
#endif
extern ipftq_t *fr_addtimeoutqueue __P((ipftq_t **, u_int));
@@ -1298,6 +1482,7 @@
extern frgroup_t *fr_findgroup __P((char *, minor_t, int, frgroup_t ***));
extern int fr_loginit __P((void));
+extern int ipflog_canread __P((int));
extern int ipflog_clear __P((minor_t));
extern int ipflog_read __P((minor_t, uio_t *));
extern int ipflog __P((fr_info_t *, u_int));
@@ -1306,7 +1491,7 @@
extern frentry_t *fr_acctpkt __P((fr_info_t *, u_32_t *));
extern int fr_copytolog __P((int, char *, int));
-extern u_short fr_cksum __P((mb_t *, ip_t *, int, void *));
+extern u_short fr_cksum __P((mb_t *, ip_t *, int, void *, int));
extern void fr_deinitialise __P((void));
extern frentry_t *fr_dolog __P((fr_info_t *, u_32_t *));
extern frentry_t *fr_dstgrpmap __P((fr_info_t *, u_32_t *));
@@ -1314,23 +1499,30 @@
extern void fr_forgetifp __P((void *));
extern frentry_t *fr_getrulen __P((int, char *, u_32_t));
extern void fr_getstat __P((struct friostat *));
-extern int fr_icmp4errortype __P((int));
extern int fr_ifpaddr __P((int, int, void *,
struct in_addr *, struct in_addr *));
extern int fr_initialise __P((void));
-extern void fr_lock __P((caddr_t, int *));
+extern int fr_lock __P((caddr_t, int *));
extern int fr_makefrip __P((int, ip_t *, fr_info_t *));
extern int fr_matchtag __P((ipftag_t *, ipftag_t *));
extern int fr_matchicmpqueryreply __P((int, icmpinfo_t *,
struct icmp *, int));
extern u_32_t fr_newisn __P((fr_info_t *));
extern u_short fr_nextipid __P((fr_info_t *));
+extern int ipf_queueflush __P((ipftq_delete_fn_t, ipftq_t *, ipftq_t *));
extern int fr_rulen __P((int, frentry_t *));
extern int fr_scanlist __P((fr_info_t *, u_32_t));
extern frentry_t *fr_srcgrpmap __P((fr_info_t *, u_32_t *));
extern int fr_tcpudpchk __P((fr_info_t *, frtuc_t *));
extern int fr_verifysrc __P((fr_info_t *fin));
-extern int fr_zerostats __P((char *));
+extern 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];
@@ -1345,7 +1537,6 @@
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;
Index: ip_frag.h
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_frag.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_frag.h -L sys/contrib/ipfilter/netinet/ip_frag.h -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_frag.h
+++ sys/contrib/ipfilter/netinet/ip_frag.h
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_frag.h,v 1.17 2005/04/25 18:43:14 darrenr Exp $ */
+/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_frag.h,v 1.19 2007/06/04 02:54:35 darrenr 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
- * $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_frag.h,v 1.17 2005/04/25 18:43:14 darrenr Exp $
+ * $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_frag.h,v 1.19 2007/06/04 02:54:35 darrenr Exp $
* Id: ip_frag.h,v 2.23.2.1 2004/03/29 16:21:56 darrenr Exp
*/
@@ -19,6 +19,16 @@
struct ipfr *ipfr_hnext, **ipfr_hprev;
struct ipfr *ipfr_next, **ipfr_prev;
void *ipfr_data;
+ frentry_t *ipfr_rule;
+ u_long ipfr_ttl;
+ int ipfr_ref;
+ u_short ipfr_off;
+ u_short ipfr_seen0;
+ /*
+ * All of the fields, from ipfr_ifp to ipfr_pass, are compared
+ * using bcmp to see if an identical entry is present. It is
+ * therefore important for this set to remain together.
+ */
void *ipfr_ifp;
struct in_addr ipfr_src;
struct in_addr ipfr_dst;
@@ -29,10 +39,6 @@
u_char ipfr_p;
u_char ipfr_tos;
u_32_t ipfr_pass;
- u_short ipfr_off;
- u_char ipfr_ttl;
- u_char ipfr_seen0;
- frentry_t *ipfr_rule;
} ipfr_t;
@@ -52,6 +58,8 @@
#define IPFR_CMPSZ (offsetof(ipfr_t, ipfr_pass) - \
offsetof(ipfr_t, ipfr_ifp))
+extern ipfr_t *ipfr_list, **ipfr_tail;
+extern ipfr_t *ipfr_natlist, **ipfr_nattail;
extern int ipfr_size;
extern int fr_ipfrttl;
extern int fr_frag_lock;
@@ -67,6 +75,15 @@
extern 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 *));
@@ -81,7 +98,11 @@
extern void fr_slowtimer __P((void *));
# endif
#else
+# if defined(linux) && defined(_KERNEL)
+extern void fr_slowtimer __P((long));
+# else
extern int fr_slowtimer __P((void));
+# endif
#endif
#endif /* __IP_FRAG_H__ */
Index: ip_sync.c
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_sync.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_sync.c -L sys/contrib/ipfilter/netinet/ip_sync.c -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_sync.c
+++ sys/contrib/ipfilter/netinet/ip_sync.c
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_sync.c,v 1.2 2005/06/14 09:18:26 darrenr Exp $ */
+/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_sync.c,v 1.5.2.1 2007/10/31 05:00:38 darrenr Exp $ */
/*
* Copyright (C) 1995-1998 by Darren Reed.
@@ -98,7 +98,7 @@
/* END OF INCLUDES */
#if !defined(lint)
-static const char rcsid[] = "@(#)Id: ip_sync.c,v 2.40.2.3 2005/02/18 13:06:29 darrenr Exp";
+static const char rcsid[] = "@(#)$Id: ip_sync.c,v 2.40.2.9 2007/06/02 21:22:28 darrenr Exp $";
#endif
#define SYNC_STATETABSZ 256
@@ -231,8 +231,10 @@
ips->is_die = htonl(ips->is_die);
ips->is_pass = htonl(ips->is_pass);
ips->is_flags = htonl(ips->is_flags);
- ips->is_opt = htonl(ips->is_opt);
- ips->is_optmsk = htonl(ips->is_optmsk);
+ ips->is_opt[0] = htonl(ips->is_opt[0]);
+ ips->is_opt[1] = htonl(ips->is_opt[1]);
+ ips->is_optmsk[0] = htonl(ips->is_optmsk[0]);
+ ips->is_optmsk[1] = htonl(ips->is_optmsk[1]);
ips->is_sec = htons(ips->is_sec);
ips->is_secmsk = htons(ips->is_secmsk);
ips->is_auth = htons(ips->is_auth);
@@ -246,8 +248,10 @@
ips->is_die = ntohl(ips->is_die);
ips->is_pass = ntohl(ips->is_pass);
ips->is_flags = ntohl(ips->is_flags);
- ips->is_opt = ntohl(ips->is_opt);
- ips->is_optmsk = ntohl(ips->is_optmsk);
+ ips->is_opt[0] = ntohl(ips->is_opt[0]);
+ ips->is_opt[1] = ntohl(ips->is_opt[1]);
+ ips->is_optmsk[0] = ntohl(ips->is_optmsk[0]);
+ ips->is_optmsk[1] = ntohl(ips->is_optmsk[1]);
ips->is_sec = ntohs(ips->is_sec);
ips->is_secmsk = ntohs(ips->is_secmsk);
ips->is_auth = ntohs(ips->is_auth);
@@ -297,7 +301,7 @@
if (uio->uio_resid >= sizeof(sh)) {
- err = UIOMOVE((caddr_t)&sh, sizeof(sh), UIO_WRITE, uio);
+ err = UIOMOVE(&sh, sizeof(sh), UIO_WRITE, uio);
if (err) {
if (ipf_sync_debug > 2)
@@ -369,7 +373,7 @@
if (uio->uio_resid >= sh.sm_len) {
- err = UIOMOVE((caddr_t)data, sh.sm_len, UIO_WRITE, uio);
+ err = UIOMOVE(data, sh.sm_len, UIO_WRITE, uio);
if (err) {
if (ipf_sync_debug > 2)
@@ -469,7 +473,7 @@
READ_ENTER(&ipf_syncstate);
while ((sl_tail < sl_idx) && (uio->uio_resid > sizeof(*sl))) {
sl = synclog + sl_tail++;
- err = UIOMOVE((caddr_t)sl, sizeof(*sl), UIO_READ, uio);
+ err = UIOMOVE(sl, sizeof(*sl), UIO_READ, uio);
if (err != 0)
break;
}
@@ -477,7 +481,7 @@
while ((su_tail < su_idx) && (uio->uio_resid > sizeof(*su))) {
su = syncupd + su_tail;
su_tail++;
- err = UIOMOVE((caddr_t)su, sizeof(*su), UIO_READ, uio);
+ err = UIOMOVE(su, sizeof(*su), UIO_READ, uio);
if (err != 0)
break;
if (su->sup_hdr.sm_sl != NULL)
@@ -700,7 +704,6 @@
synchdr_t *sp;
void *data;
{
- synclogent_t sle;
syncupdent_t su;
nat_t *n, *nat;
synclist_t *sl;
@@ -712,8 +715,6 @@
switch (sp->sm_cmd)
{
case SMC_CREATE :
- bcopy(data, &sle, sizeof(sle));
-
KMALLOC(n, nat_t *);
if (n == NULL) {
err = ENOMEM;
@@ -727,9 +728,7 @@
break;
}
- WRITE_ENTER(&ipf_nat);
-
- nat = &sle.sle_un.sleu_ipn;
+ nat = (nat_t *)data;
bzero((char *)n, offsetof(nat_t, nat_age));
bcopy((char *)&nat->nat_age, (char *)&n->nat_age,
sizeof(*n) - offsetof(nat_t, nat_age));
@@ -739,6 +738,8 @@
sl->sl_idx = -1;
sl->sl_ipn = n;
sl->sl_num = ntohl(sp->sm_num);
+
+ WRITE_ENTER(&ipf_nat);
sl->sl_pnext = syncstatetab + hv;
sl->sl_next = syncstatetab[hv];
if (syncstatetab[hv] != NULL)
@@ -996,11 +997,24 @@
/* This function currently does not handle any ioctls and so just returns */
/* EINVAL on all occasions. */
/* ------------------------------------------------------------------------ */
-int fr_sync_ioctl(data, cmd, mode)
+int fr_sync_ioctl(data, cmd, mode, uid, ctx)
caddr_t data;
ioctlcmd_t cmd;
-int mode;
+int mode, uid;
+void *ctx;
{
return EINVAL;
}
+
+
+int ipfsync_canread()
+{
+ return !((sl_tail == sl_idx) && (su_tail == su_idx));
+}
+
+
+int ipfsync_canwrite()
+{
+ return 1;
+}
#endif /* IPFILTER_SYNC */
Index: ip_state.h
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_state.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_state.h -L sys/contrib/ipfilter/netinet/ip_state.h -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_state.h
+++ sys/contrib/ipfilter/netinet/ip_state.h
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_state.h,v 1.17 2005/04/25 18:43:14 darrenr Exp $ */
+/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_state.h,v 1.19.2.1 2007/10/31 05:00:38 darrenr Exp $ */
/*
* Copyright (C) 1995-2001 by Darren Reed.
@@ -6,13 +6,13 @@
* See the IPFILTER.LICENCE file for details on licencing.
*
* @(#)ip_state.h 1.3 1/12/96 (C) 1995 Darren Reed
- * $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_state.h,v 1.17 2005/04/25 18:43:14 darrenr Exp $
- * Id: ip_state.h,v 2.68.2.3 2005/03/03 14:24:11 darrenr Exp
+ * $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_state.h,v 1.19.2.1 2007/10/31 05:00:38 darrenr Exp $
+ * Id: ip_state.h,v 2.68.2.10 2007/10/16 09:33:24 darrenr Exp $
*/
#ifndef __IP_STATE_H__
#define __IP_STATE_H__
-#if defined(__STDC__) || defined(__GNUC__)
+#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51)
# define SIOCDELST _IOW('r', 61, struct ipfobj)
#else
# define SIOCDELST _IOW(r, 61, struct ipfobj)
@@ -27,10 +27,8 @@
# define IPSTATE_MAX 4013 /* Maximum number of states held */
#endif
-#define PAIRS(s1,d1,s2,d2) ((((s1) == (s2)) && ((d1) == (d2))) ||\
- (((s1) == (d2)) && ((d1) == (s2))))
-#define IPPAIR(s1,d1,s2,d2) PAIRS((s1).s_addr, (d1).s_addr, \
- (s2).s_addr, (d2).s_addr)
+#define SEQ_GE(a,b) ((int)((a) - (b)) >= 0)
+#define SEQ_GT(a,b) ((int)((a) - (b)) > 0)
typedef struct ipstate {
@@ -42,7 +40,6 @@
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;
@@ -61,8 +58,8 @@
u_char is_v;
u_32_t is_hv;
u_32_t is_tag;
- u_32_t is_opt; /* packet options set */
- u_32_t is_optmsk; /* " " mask */
+ u_32_t is_opt[2]; /* packet options set */
+ u_32_t is_optmsk[2]; /* " " mask */
u_short is_sec; /* security options set */
u_short is_secmsk; /* " " mask */
u_short is_auth; /* authentication options set */
@@ -190,6 +187,7 @@
#define ISL_INTERMEDIATE 0xfffc
#define ISL_KILLED 0xfffb
#define ISL_ORPHAN 0xfffa
+#define ISL_UNLOAD 0xfff9
typedef struct ips_stat {
@@ -216,6 +214,7 @@
ipstate_t **iss_table;
ipstate_t *iss_list;
u_long *iss_bucketlen;
+ ipftq_t *iss_tcptab;
} ips_stat_t;
@@ -251,12 +250,12 @@
struct tcpdata *, tcphdr_t *, int));
extern void fr_stateunload __P((void));
extern void ipstate_log __P((struct ipstate *, u_int));
-extern int fr_state_ioctl __P((caddr_t, ioctlcmd_t, int));
+extern int fr_state_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *));
extern void fr_stinsert __P((struct ipstate *, int));
extern void fr_sttab_init __P((struct ipftq *));
extern void fr_sttab_destroy __P((struct ipftq *));
extern void fr_updatestate __P((fr_info_t *, ipstate_t *, ipftq_t *));
-extern void fr_statederef __P((fr_info_t *, ipstate_t **));
+extern void fr_statederef __P((ipstate_t **));
extern void fr_setstatequeue __P((ipstate_t *, int));
#endif /* __IP_STATE_H__ */
Index: ip_lookup.h
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_lookup.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_lookup.h -L sys/contrib/ipfilter/netinet/ip_lookup.h -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_lookup.h
+++ sys/contrib/ipfilter/netinet/ip_lookup.h
@@ -1,10 +1,8 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_lookup.h,v 1.1.1.1 2005/04/25 18:15:23 darrenr Exp $ */
-
#ifndef __IP_LOOKUP_H__
#define __IP_LOOKUP_H__
-#if defined(__STDC__) || defined(__GNUC__)
+#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51)
# define SIOCLOOKUPADDTABLE _IOWR('r', 60, struct iplookupop)
# define SIOCLOOKUPDELTABLE _IOWR('r', 61, struct iplookupop)
# define SIOCLOOKUPSTAT _IOWR('r', 64, struct iplookupop)
@@ -35,6 +33,9 @@
void *iplo_struct;
} iplookupop_t;
+#define LOOKUP_ANON 0x80000000
+
+
typedef struct iplookupflush {
int iplf_type; /* IPLT_* */
int iplf_unit; /* IPL_LOG* */
@@ -57,9 +58,38 @@
#define IPLT_ANON 0x80000000
+
+typedef union {
+ struct iplookupiterkey {
+ char ilik_ival;
+ u_char ilik_type; /* IPLT_* */
+ u_char ilik_otype;
+ u_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((caddr_t, ioctlcmd_t, int));
+extern int ip_lookup_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *));
extern void ip_lookup_unload __P((void));
extern void ip_lookup_deref __P((int, void *));
+extern void ip_lookup_iterderef __P((u_32_t, void *));
#endif /* __IP_LOOKUP_H__ */
Index: ip_state.c
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_state.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_state.c -L sys/contrib/ipfilter/netinet/ip_state.c -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_state.c
+++ sys/contrib/ipfilter/netinet/ip_state.c
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_state.c,v 1.35 2005/04/25 18:43:14 darrenr Exp $ */
+/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_state.c,v 1.39.2.1 2007/10/31 05:00:38 darrenr 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_log.h"
+# if (__NetBSD_Version__ < 399001400)
+# include "opt_ipfilter_log.h"
+# else
+# include "opt_ipfilter.h"
+# endif
#endif
#if defined(_KERNEL) && defined(__FreeBSD_version) && \
(__FreeBSD_version >= 400000) && !defined(KLD_MODULE)
@@ -109,7 +113,7 @@
#if !defined(lint)
static const char sccsid[] = "@(#)ip_state.c 1.8 6/5/96 (C) 1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)Id: ip_state.c,v 2.186.2.29 2005/03/28 10:47:54 darrenr Exp";
+static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.186.2.80 2007/10/16 09:33:23 darrenr Exp $";
#endif
static ipstate_t **ips_table = NULL;
@@ -125,8 +129,9 @@
i6addr_t *, tcphdr_t *, u_32_t));
static ipstate_t *fr_checkicmpmatchingstate __P((fr_info_t *));
static int fr_state_flush __P((int, int));
+static int fr_state_flush_entry __P((void *));
static ips_stat_t *fr_statetstats __P((void));
-static void fr_delstate __P((ipstate_t *, int));
+static int fr_delstate __P((ipstate_t *, int));
static int fr_state_remove __P((caddr_t));
static void fr_ipsmove __P((ipstate_t *, u_int));
static int fr_tcpstate __P((fr_info_t *, tcphdr_t *, ipstate_t *));
@@ -135,6 +140,8 @@
static void fr_fixinisn __P((fr_info_t *, ipstate_t *));
static void fr_fixoutisn __P((fr_info_t *, ipstate_t *));
static void fr_checknewisn __P((fr_info_t *, ipstate_t *));
+static int fr_stateiter __P((ipftoken_t *, ipfgeniter_t *));
+static int fr_stgettable __P((char *));
int fr_stputent __P((caddr_t));
int fr_stgetent __P((caddr_t));
@@ -145,9 +152,10 @@
u_long fr_tcpidletimeout = FIVE_DAYS,
fr_tcpclosewait = IPF_TTLVAL(2 * TCP_MSL),
- fr_tcplastack = IPF_TTLVAL(2 * TCP_MSL),
+ fr_tcplastack = IPF_TTLVAL(30),
fr_tcptimeout = IPF_TTLVAL(2 * TCP_MSL),
- fr_tcpclosed = IPF_TTLVAL(60),
+ fr_tcptimewait = IPF_TTLVAL(2 * TCP_MSL),
+ fr_tcpclosed = IPF_TTLVAL(30),
fr_tcphalfclosed = IPF_TTLVAL(2 * 3600), /* 2 hours */
fr_udptimeout = IPF_TTLVAL(120),
fr_udpacktimeout = IPF_TTLVAL(12),
@@ -167,6 +175,7 @@
ips_iptq,
ips_icmptq,
ips_icmpacktq,
+ ips_deletetq,
*ips_utqe = NULL;
#ifdef IPFILTER_LOG
int ipstate_logging = 1;
@@ -241,6 +250,7 @@
fr_state_maxbucket *= 2;
}
+ ips_stats.iss_tcptab = ips_tqtqb;
fr_sttab_init(ips_tqtqb);
ips_tqtqb[IPF_TCP_NSTATES - 1].ifq_next = &ips_udptq;
ips_udptq.ifq_ttl = (u_long)fr_udptimeout;
@@ -272,7 +282,13 @@
ips_iptq.ifq_head = NULL;
ips_iptq.ifq_tail = &ips_iptq.ifq_head;
MUTEX_INIT(&ips_iptq.ifq_lock, "ipftq ip tab");
- ips_iptq.ifq_next = NULL;
+ ips_iptq.ifq_next = &ips_deletetq;
+ ips_deletetq.ifq_ttl = (u_long)1;
+ ips_deletetq.ifq_ref = 1;
+ ips_deletetq.ifq_head = NULL;
+ ips_deletetq.ifq_tail = &ips_deletetq.ifq_head;
+ MUTEX_INIT(&ips_deletetq.ifq_lock, "state delete queue");
+ ips_deletetq.ifq_next = NULL;
RWLOCK_INIT(&ipf_state, "ipf IP state rwlock");
MUTEX_INIT(&ipf_stinsert, "ipf state insert mutex");
@@ -297,7 +313,7 @@
ipstate_t *is;
while ((is = ips_list) != NULL)
- fr_delstate(is, 0);
+ fr_delstate(is, ISL_UNLOAD);
/*
* Proxy timeout queues are not cleaned here because although they
@@ -323,6 +339,7 @@
MUTEX_DESTROY(&ips_udpacktq.ifq_lock);
MUTEX_DESTROY(&ips_icmpacktq.ifq_lock);
MUTEX_DESTROY(&ips_iptq.ifq_lock);
+ MUTEX_DESTROY(&ips_deletetq.ifq_lock);
}
if (ips_table != NULL) {
@@ -416,12 +433,14 @@
/* */
/* Processes an ioctl call made to operate on the IP Filter state device. */
/* ------------------------------------------------------------------------ */
-int fr_state_ioctl(data, cmd, mode)
+int fr_state_ioctl(data, cmd, mode, uid, ctx)
caddr_t data;
ioctlcmd_t cmd;
-int mode;
+int mode, uid;
+void *ctx;
{
int arg, ret, error = 0;
+ SPL_INT(s);
switch (cmd)
{
@@ -431,29 +450,37 @@
case SIOCDELST :
error = fr_state_remove(data);
break;
+
/*
* Flush the state table
*/
case SIOCIPFFL :
- BCOPYIN(data, (char *)&arg, sizeof(arg));
- if (arg == 0 || arg == 1) {
+ error = BCOPYIN(data, (char *)&arg, sizeof(arg));
+ if (error != 0) {
+ error = EFAULT;
+ } else {
WRITE_ENTER(&ipf_state);
ret = fr_state_flush(arg, 4);
RWLOCK_EXIT(&ipf_state);
- BCOPYOUT((char *)&ret, data, sizeof(ret));
- } else
- error = EINVAL;
+ error = BCOPYOUT((char *)&ret, data, sizeof(ret));
+ if (error != 0)
+ error = EFAULT;
+ }
break;
+
#ifdef USE_INET6
case SIOCIPFL6 :
- BCOPYIN(data, (char *)&arg, sizeof(arg));
- if (arg == 0 || arg == 1) {
+ error = BCOPYIN(data, (char *)&arg, sizeof(arg));
+ if (error != 0) {
+ error = EFAULT;
+ } else {
WRITE_ENTER(&ipf_state);
ret = fr_state_flush(arg, 6);
RWLOCK_EXIT(&ipf_state);
- BCOPYOUT((char *)&ret, data, sizeof(ret));
- } else
- error = EINVAL;
+ error = BCOPYOUT((char *)&ret, data, sizeof(ret));
+ if (error != 0)
+ error = EFAULT;
+ }
break;
#endif
#ifdef IPFILTER_LOG
@@ -467,9 +494,12 @@
int tmp;
tmp = ipflog_clear(IPL_LOGSTATE);
- BCOPYOUT((char *)&tmp, data, sizeof(tmp));
+ error = BCOPYOUT((char *)&tmp, data, sizeof(tmp));
+ if (error != 0)
+ error = EFAULT;
}
break;
+
/*
* Turn logging of state information on/off.
*/
@@ -477,48 +507,64 @@
if (!(mode & FWRITE))
error = EPERM;
else {
- BCOPYIN((char *)data, (char *)&ipstate_logging,
- sizeof(ipstate_logging));
+ error = BCOPYIN((char *)data, (char *)&ipstate_logging,
+ sizeof(ipstate_logging));
+ if (error != 0)
+ error = EFAULT;
}
break;
+
/*
* Return the current state of logging.
*/
case SIOCGETLG :
- BCOPYOUT((char *)&ipstate_logging, (char *)data,
- sizeof(ipstate_logging));
+ error = BCOPYOUT((char *)&ipstate_logging, (char *)data,
+ sizeof(ipstate_logging));
+ if (error != 0)
+ error = EFAULT;
break;
+
/*
* Return the number of bytes currently waiting to be read.
*/
case FIONREAD :
arg = iplused[IPL_LOGSTATE]; /* returned in an int */
- BCOPYOUT((char *)&arg, data, sizeof(arg));
+ error = BCOPYOUT((char *)&arg, data, sizeof(arg));
+ if (error != 0)
+ error = EFAULT;
break;
#endif
+
/*
* Get the current state statistics.
*/
case SIOCGETFS :
error = fr_outobj(data, fr_statetstats(), IPFOBJ_STATESTAT);
break;
+
/*
* Lock/Unlock the state table. (Locking prevents any changes, which
* means no packets match).
*/
case SIOCSTLCK :
- fr_lock(data, &fr_state_lock);
+ if (!(mode & FWRITE)) {
+ error = EPERM;
+ } else {
+ error = fr_lock(data, &fr_state_lock);
+ }
break;
+
/*
* Add an entry to the current state table.
*/
case SIOCSTPUT :
- if (!fr_state_lock) {
+ if (!fr_state_lock || !(mode &FWRITE)) {
error = EACCES;
break;
}
error = fr_stputent(data);
break;
+
/*
* Get a state table entry.
*/
@@ -529,6 +575,56 @@
}
error = fr_stgetent(data);
break;
+
+ /*
+ * Return a copy of the hash table bucket lengths
+ */
+ case SIOCSTAT1 :
+ error = BCOPYOUT(ips_stats.iss_bucketlen, data,
+ fr_statesize * sizeof(u_long));
+ if (error != 0)
+ error = EFAULT;
+ break;
+
+ case SIOCGENITER :
+ {
+ ipftoken_t *token;
+ ipfgeniter_t iter;
+
+ error = fr_inobj(data, &iter, IPFOBJ_GENITER);
+ if (error != 0)
+ break;
+
+ SPL_SCHED(s);
+ token = ipf_findtoken(IPFGENITER_STATE, uid, ctx);
+ if (token != NULL)
+ error = fr_stateiter(token, &iter);
+ else
+ error = ESRCH;
+ RWLOCK_EXIT(&ipf_tokens);
+ SPL_X(s);
+ break;
+ }
+
+ case SIOCGTABL :
+ error = fr_stgettable(data);
+ break;
+
+ case SIOCIPFDELTOK :
+ error = BCOPYIN(data, (char *)&arg, sizeof(arg));
+ if (error != 0) {
+ error = EFAULT;
+ } else {
+ SPL_SCHED(s);
+ error = ipf_deltoken(arg, uid, ctx);
+ SPL_X(s);
+ }
+ break;
+
+ case SIOCGTQTAB :
+ error = fr_outobj(data, ips_tqtqb, IPFOBJ_STATETQTAB);
+ break;
+
default :
error = EINVAL;
break;
@@ -556,8 +652,8 @@
int error;
error = fr_inobj(data, &ips, IPFOBJ_STATESAVE);
- if (error)
- return EFAULT;
+ if (error != 0)
+ return error;
isn = ips.ips_next;
if (isn == NULL) {
@@ -586,9 +682,7 @@
bcopy((char *)isn->is_rule, (char *)&ips.ips_fr,
sizeof(ips.ips_fr));
error = fr_outobj(data, &ips, IPFOBJ_STATESAVE);
- if (error)
- return EFAULT;
- return 0;
+ return error;
}
@@ -635,6 +729,7 @@
if (fr == NULL) {
READ_ENTER(&ipf_state);
fr_stinsert(isn, 0);
+ MUTEX_EXIT(&isn->is_lock);
RWLOCK_EXIT(&ipf_state);
return 0;
}
@@ -665,8 +760,10 @@
fr->fr_ref = 0;
fr->fr_dsize = 0;
fr->fr_data = NULL;
+ fr->fr_type = FR_T_NONE;
- fr_resolvedest(&fr->fr_tif, fr->fr_v);
+ fr_resolvedest(&fr->fr_tifs[0], fr->fr_v);
+ fr_resolvedest(&fr->fr_tifs[1], fr->fr_v);
fr_resolvedest(&fr->fr_dif, fr->fr_v);
/*
@@ -682,6 +779,7 @@
}
READ_ENTER(&ipf_state);
fr_stinsert(isn, 0);
+ MUTEX_EXIT(&isn->is_lock);
RWLOCK_EXIT(&ipf_state);
} else {
@@ -689,6 +787,7 @@
for (is = ips_list; is; is = is->is_next)
if (is->is_rule == fr) {
fr_stinsert(isn, 0);
+ MUTEX_EXIT(&isn->is_lock);
break;
}
@@ -716,6 +815,7 @@
/* to pointers and adjusts running stats for the hash table as appropriate. */
/* */
/* Locking: it is assumed that some kind of lock on ipf_state is held. */
+/* Exits with is_lock initialised and held. */
/* ------------------------------------------------------------------------ */
void fr_stinsert(is, rev)
ipstate_t *is;
@@ -780,7 +880,6 @@
MUTEX_EXIT(&ipf_stinsert);
fr_setstatequeue(is, rev);
- MUTEX_EXIT(&is->is_lock);
}
@@ -796,6 +895,11 @@
/* Inserts it into the state table and appends to the bottom of the active */
/* list. If the capacity of the table has reached the maximum allowed then */
/* the call will fail and a flush is scheduled for the next timeout call. */
+/* */
+/* NOTE: The use of stsave to point to nat_state will result in memory */
+/* corruption. It should only be used to point to objects that will */
+/* either outlive this (not expired) or will deref the ip_state_t */
+/* when they are deleted. */
/* ------------------------------------------------------------------------ */
ipstate_t *fr_addstate(fin, stsave, flags)
fr_info_t *fin;
@@ -808,7 +912,6 @@
frentry_t *fr;
tcphdr_t *tcp;
grehdr_t *gre;
- void *ifp;
int out;
if (fr_state_lock ||
@@ -818,24 +921,28 @@
if ((fin->fin_flx & FI_OOW) && !(fin->fin_tcpf & TH_SYN))
return NULL;
- fr = fin->fin_fr;
- if ((fr->fr_statemax == 0) && (ips_num == fr_statemax)) {
- ATOMIC_INCL(ips_stats.iss_max);
- fr_state_doflush = 1;
- return NULL;
- }
-
/*
* If a "keep state" rule has reached the maximum number of references
* to it, then schedule an automatic flush in case we can clear out
- * some "dead old wood".
+ * some "dead old wood". Note that because the lock isn't held on
+ * fr it is possible that we could overflow. The cost of overflowing
+ * is being ignored here as the number by which it can overflow is
+ * a product of the number of simultaneous threads that could be
+ * executing in here, so a limit of 100 won't result in 200, but could
+ * result in 101 or 102.
*/
- if ((fr != NULL) && (fr->fr_statemax != 0) &&
- (fr->fr_statecnt >= fr->fr_statemax)) {
- MUTEX_EXIT(&fr->fr_lock);
- ATOMIC_INCL(ips_stats.iss_maxref);
- fr_state_doflush = 1;
- return NULL;
+ fr = fin->fin_fr;
+ if (fr != NULL) {
+ if ((ips_num >= fr_statemax) && (fr->fr_statemax == 0)) {
+ ATOMIC_INCL(ips_stats.iss_max);
+ fr_state_doflush = 1;
+ return NULL;
+ }
+ if ((fr->fr_statemax != 0) &&
+ (fr->fr_statecnt >= fr->fr_statemax)) {
+ ATOMIC_INCL(ips_stats.iss_maxref);
+ return NULL;
+ }
}
pass = (fr == NULL) ? 0 : fr->fr_flags;
@@ -884,6 +991,16 @@
hv += is->is_src.i6[3];
}
#endif
+ if ((fin->fin_v == 4) &&
+ (fin->fin_flx & (FI_MULTICAST|FI_BROADCAST|FI_MBCAST))) {
+ if (fin->fin_out == 0) {
+ flags |= SI_W_DADDR|SI_CLONE;
+ hv -= is->is_daddr;
+ } else {
+ flags |= SI_W_SADDR|SI_CLONE;
+ hv -= is->is_saddr;
+ }
+ }
switch (is->is_p)
{
@@ -979,9 +1096,9 @@
TH_SYN &&
(TCP_OFF(tcp) > (sizeof(tcphdr_t) >> 2))) {
if (fr_tcpoptions(fin, tcp,
- &is->is_tcp.ts_data[0]))
- is->is_swinflags = TCP_WSCALE_SEEN|
- TCP_WSCALE_FIRST;
+ &is->is_tcp.ts_data[0]) == -1) {
+ fin->fin_flx |= FI_BAD;
+ }
}
if ((fin->fin_out != 0) && (pass & FR_NEWISN) != 0) {
@@ -1068,30 +1185,43 @@
is->is_tag = fr->fr_logtag;
+ /*
+ * The name '-' is special for network interfaces and causes
+ * a NULL name to be present, always, allowing packets to
+ * match it, regardless of their interface.
+ */
+ if ((fin->fin_ifp == NULL) ||
+ (fr->fr_ifnames[out << 1][0] == '-' &&
+ fr->fr_ifnames[out << 1][1] == '\0')) {
+ is->is_ifp[out << 1] = fr->fr_ifas[0];
+ strncpy(is->is_ifname[out << 1], fr->fr_ifnames[0],
+ sizeof(fr->fr_ifnames[0]));
+ } else {
+ is->is_ifp[out << 1] = fin->fin_ifp;
+ COPYIFNAME(is->is_v, fin->fin_ifp,
+ is->is_ifname[out << 1]);
+ }
+
is->is_ifp[(out << 1) + 1] = fr->fr_ifas[1];
+ strncpy(is->is_ifname[(out << 1) + 1], fr->fr_ifnames[1],
+ sizeof(fr->fr_ifnames[1]));
+
is->is_ifp[(1 - out) << 1] = fr->fr_ifas[2];
- is->is_ifp[((1 - out) << 1) + 1] = fr->fr_ifas[3];
+ strncpy(is->is_ifname[((1 - out) << 1)], fr->fr_ifnames[2],
+ sizeof(fr->fr_ifnames[2]));
- if (((ifp = fr->fr_ifas[1]) != NULL) &&
- (ifp != (void *)-1)) {
- COPYIFNAME(ifp, is->is_ifname[(out << 1) + 1]);
- }
- if (((ifp = fr->fr_ifas[2]) != NULL) &&
- (ifp != (void *)-1)) {
- COPYIFNAME(ifp, is->is_ifname[(1 - out) << 1]);
- }
- if (((ifp = fr->fr_ifas[3]) != NULL) &&
- (ifp != (void *)-1)) {
- COPYIFNAME(ifp, is->is_ifname[((1 - out) << 1) + 1]);
- }
+ is->is_ifp[((1 - out) << 1) + 1] = fr->fr_ifas[3];
+ strncpy(is->is_ifname[((1 - out) << 1) + 1], fr->fr_ifnames[3],
+ sizeof(fr->fr_ifnames[3]));
} else {
pass = fr_flags;
is->is_tag = FR_NOLOGTAG;
- }
- is->is_ifp[out << 1] = fin->fin_ifp;
- if (fin->fin_ifp != NULL) {
- COPYIFNAME(fin->fin_ifp, is->is_ifname[out << 1]);
+ if (fin->fin_ifp != NULL) {
+ is->is_ifp[out << 1] = fin->fin_ifp;
+ COPYIFNAME(is->is_v, fin->fin_ifp,
+ is->is_ifname[out << 1]);
+ }
}
/*
@@ -1124,8 +1254,15 @@
* this may change.
*/
is->is_v = fin->fin_v;
- is->is_opt = fin->fin_optmsk;
- is->is_optmsk = 0xffffffff;
+ is->is_opt[0] = fin->fin_optmsk;
+ is->is_optmsk[0] = 0xffffffff;
+ is->is_optmsk[1] = 0xffffffff;
+ if (is->is_v == 6) {
+ is->is_opt[0] &= ~0x8;
+ is->is_optmsk[0] &= ~0x8;
+ is->is_optmsk[1] &= ~0x8;
+ }
+ is->is_me = stsave;
is->is_sec = fin->fin_secmsk;
is->is_secmsk = 0xffff;
is->is_auth = fin->fin_auth;
@@ -1140,7 +1277,6 @@
is->is_pass &= ~(FR_LOGFIRST|FR_LOG);
READ_ENTER(&ipf_state);
- is->is_me = stsave;
fr_stinsert(is, fin->fin_rev);
@@ -1150,13 +1286,14 @@
* timer on it as we'll never see an error if it fails to
* connect.
*/
- MUTEX_ENTER(&is->is_lock);
(void) fr_tcp_age(&is->is_sti, fin, ips_tqtqb, is->is_flags);
MUTEX_EXIT(&is->is_lock);
#ifdef IPFILTER_SCAN
if ((is->is_flags & SI_CLONE) == 0)
(void) ipsc_attachis(is);
#endif
+ } else {
+ MUTEX_EXIT(&is->is_lock);
}
#ifdef IPFILTER_SYNC
if ((is->is_flags & IS_STATESYNC) && ((is->is_flags & SI_CLONE) == 0))
@@ -1178,7 +1315,8 @@
/* ------------------------------------------------------------------------ */
/* Function: fr_tcpoptions */
-/* Returns: int - 1 == packet matches state entry, 0 == it does not */
+/* Returns: int - 1 == packet matches state entry, 0 == it does not, */
+/* -1 == packet has bad TCP options data */
/* Parameters: fin(I) - pointer to packet information */
/* tcp(I) - pointer to TCP packet header */
/* td(I) - pointer to TCP data held as part of the state */
@@ -1195,13 +1333,14 @@
char buf[64], *s, opt;
mb_t *m = NULL;
- off = fin->fin_hlen + sizeof(*tcp);
- len = (TCP_OFF(tcp) << 2) - sizeof(*tcp);
- if (fin->fin_plen < off + len)
+ len = (TCP_OFF(tcp) << 2);
+ if (fin->fin_dlen < len)
return 0;
+ len -= sizeof(*tcp);
+
+ off = fin->fin_plen - fin->fin_dlen + sizeof(*tcp) + fin->fin_ipoff;
m = fin->fin_m;
- off += fin->fin_ipoff;
mlen = MSGDSIZE(m) - off;
if (len > mlen) {
len = mlen;
@@ -1239,7 +1378,10 @@
else if (i < 0)
i = 0;
td->td_winscale = i;
- }
+ td->td_winflags |= TCP_WSCALE_SEEN|
+ TCP_WSCALE_FIRST;
+ } else
+ retval = -1;
break;
case TCPOPT_MAXSEG :
/*
@@ -1251,7 +1393,14 @@
i <<= 8;
i += (int)*(s + 3);
td->td_maxseg = i;
- }
+ } else
+ retval = -1;
+ break;
+ case TCPOPT_SACK_PERMITTED :
+ if (ol == TCPOLEN_SACK_PERMITTED)
+ td->td_winflags |= TCP_SACK_PERMIT;
+ else
+ retval = -1;
break;
}
}
@@ -1289,7 +1438,24 @@
tdata = &is->is_tcp.ts_data[source];
MUTEX_ENTER(&is->is_lock);
- if (fr_tcpinwindow(fin, fdata, tdata, tcp, is->is_flags)) {
+
+ /*
+ * If a SYN packet is received for a connection that is on the way out
+ * but hasn't yet departed then advance this session along the way.
+ */
+ if ((tcp->th_flags & TH_OPENING) == TH_SYN) {
+ if ((is->is_state[0] > IPF_TCPS_ESTABLISHED) &&
+ (is->is_state[1] > IPF_TCPS_ESTABLISHED)) {
+ is->is_state[!source] = IPF_TCPS_CLOSED;
+ fr_movequeue(&is->is_sti, is->is_sti.tqe_ifq,
+ &ips_deletetq);
+ MUTEX_EXIT(&is->is_lock);
+ return 0;
+ }
+ }
+
+ ret = fr_tcpinwindow(fin, fdata, tdata, tcp, is->is_flags);
+ if (ret > 0) {
#ifdef IPFILTER_SCAN
if (is->is_flags & (IS_SC_CLIENT|IS_SC_SERVER)) {
ipsc_packet(fin, is);
@@ -1321,33 +1487,27 @@
if (flags == (TH_SYN|TH_ACK)) {
is->is_s0[source] = ntohl(tcp->th_ack);
is->is_s0[!source] = ntohl(tcp->th_seq) + 1;
- if ((TCP_OFF(tcp) > (sizeof(tcphdr_t) >> 2)) &&
- tdata->td_winscale) {
- if (fr_tcpoptions(fin, tcp, fdata)) {
- fdata->td_winflags = TCP_WSCALE_SEEN|
- TCP_WSCALE_FIRST;
- } else {
- if (!fdata->td_winscale)
- tdata->td_winscale = 0;
- }
+ if ((TCP_OFF(tcp) > (sizeof(tcphdr_t) >> 2))) {
+ if (fr_tcpoptions(fin, tcp, fdata) == -1)
+ fin->fin_flx |= FI_BAD;
}
if ((fin->fin_out != 0) && (is->is_pass & FR_NEWISN))
fr_checknewisn(fin, is);
} else if (flags == TH_SYN) {
is->is_s0[source] = ntohl(tcp->th_seq) + 1;
- if ((TCP_OFF(tcp) > (sizeof(tcphdr_t) >> 2)))
- if (fr_tcpoptions(fin, tcp, tdata)) {
- tdata->td_winflags = TCP_WSCALE_SEEN|
- TCP_WSCALE_FIRST;
- }
+ if ((TCP_OFF(tcp) > (sizeof(tcphdr_t) >> 2))) {
+ if (fr_tcpoptions(fin, tcp, fdata) == -1)
+ fin->fin_flx |= FI_BAD;
+ }
if ((fin->fin_out != 0) && (is->is_pass & FR_NEWISN))
fr_checknewisn(fin, is);
}
ret = 1;
- } else
+ } else {
fin->fin_flx |= FI_OOW;
+ }
MUTEX_EXIT(&is->is_lock);
return ret;
}
@@ -1391,7 +1551,8 @@
/* ------------------------------------------------------------------------ */
/* Function: fr_tcpinwindow */
-/* Returns: int - 1 == packet inside TCP "window", 0 == not inside. */
+/* Returns: int - 1 == packet inside TCP "window", 0 == not inside, */
+/* 2 == packet seq number matches next expected */
/* Parameters: fin(I) - pointer to packet information */
/* fdata(I) - pointer to tcp state informatio (forward) */
/* tdata(I) - pointer to tcp state informatio (reverse) */
@@ -1410,6 +1571,7 @@
tcp_seq seq, ack, end;
int ackskew, tcpflags;
u_32_t win, maxwin;
+ int dsize, inseq;
/*
* Find difference between last checked packet and this packet.
@@ -1421,9 +1583,16 @@
win = ntohs(tcp->th_win);
else
win = ntohs(tcp->th_win) << fdata->td_winscale;
+
+ /*
+ * A window of 0 produces undesirable behaviour from this function.
+ */
if (win == 0)
win = 1;
+ dsize = fin->fin_dlen - (TCP_OFF(tcp) << 2) +
+ ((tcpflags & TH_SYN) ? 1 : 0) + ((tcpflags & TH_FIN) ? 1 : 0);
+
/*
* if window scaling is present, the scaling is only allowed
* for windows not in the first SYN packet. In that packet the
@@ -1436,19 +1605,11 @@
* the receiver also does window scaling)
*/
if (!(tcpflags & TH_SYN) && (fdata->td_winflags & TCP_WSCALE_FIRST)) {
- if (tdata->td_winflags & TCP_WSCALE_SEEN) {
- fdata->td_winflags &= ~TCP_WSCALE_FIRST;
- fdata->td_maxwin = win;
- } else {
- fdata->td_winscale = 0;
- fdata->td_winflags = 0;
- tdata->td_winscale = 0;
- tdata->td_winflags = 0;
- }
+ fdata->td_winflags &= ~TCP_WSCALE_FIRST;
+ fdata->td_maxwin = win;
}
- end = seq + fin->fin_dlen - (TCP_OFF(tcp) << 2) +
- ((tcpflags & TH_SYN) ? 1 : 0) + ((tcpflags & TH_FIN) ? 1 : 0);
+ end = seq + dsize;
if ((fdata->td_end == 0) &&
(!(flags & IS_TCPFSM) ||
@@ -1456,7 +1617,7 @@
/*
* Must be a (outgoing) SYN-ACK in reply to a SYN.
*/
- fdata->td_end = end;
+ fdata->td_end = end - 1;
fdata->td_maxwin = 1;
fdata->td_maxend = end + win;
}
@@ -1469,33 +1630,72 @@
ack = tdata->td_end;
}
- if (seq == end)
- seq = end = fdata->td_end;
-
maxwin = tdata->td_maxwin;
ackskew = tdata->td_end - ack;
/*
* Strict sequencing only allows in-order delivery.
*/
- if ((flags & IS_STRICT) != 0) {
- if (seq != fdata->td_end) {
+ if (seq != fdata->td_end) {
+ if ((flags & IS_STRICT) != 0) {
return 0;
}
}
-#define SEQ_GE(a,b) ((int)((a) - (b)) >= 0)
-#define SEQ_GT(a,b) ((int)((a) - (b)) > 0)
- if (
-#if defined(_KERNEL)
- (SEQ_GE(fdata->td_maxend, end)) &&
+ inseq = 0;
+ if ((SEQ_GE(fdata->td_maxend, end)) &&
(SEQ_GE(seq, fdata->td_end - maxwin)) &&
-#endif
/* XXX what about big packets */
#define MAXACKWINDOW 66000
- (-ackskew <= (MAXACKWINDOW << fdata->td_winscale)) &&
+ (-ackskew <= (MAXACKWINDOW)) &&
( ackskew <= (MAXACKWINDOW << fdata->td_winscale))) {
+ inseq = 1;
+ /*
+ * Microsoft Windows will send the next packet to the right of the
+ * window if SACK is in use.
+ */
+ } else if ((seq == fdata->td_maxend) && (ackskew == 0) &&
+ (fdata->td_winflags & TCP_SACK_PERMIT) &&
+ (tdata->td_winflags & TCP_SACK_PERMIT)) {
+ inseq = 1;
+ /*
+ * Sometimes a TCP RST will be generated with only the ACK field
+ * set to non-zero.
+ */
+ } else if ((seq == 0) && (tcpflags == (TH_RST|TH_ACK)) &&
+ (ackskew >= -1) && (ackskew <= 1)) {
+ inseq = 1;
+ } else if (!(flags & IS_TCPFSM)) {
+ int i;
+ i = (fin->fin_rev << 1) + fin->fin_out;
+
+#if 0
+ if (is_pkts[i]0 == 0) {
+ /*
+ * Picking up a connection in the middle, the "next"
+ * packet seen from a direction that is new should be
+ * accepted, even if it appears out of sequence.
+ */
+ inseq = 1;
+ } else
+#endif
+ if (!(fdata->td_winflags &
+ (TCP_WSCALE_SEEN|TCP_WSCALE_FIRST))) {
+ /*
+ * No TCPFSM and no window scaling, so make some
+ * extra guesses.
+ */
+ if ((seq == fdata->td_maxend) && (ackskew == 0))
+ inseq = 1;
+ else if (SEQ_GE(seq + maxwin, fdata->td_end - maxwin))
+ inseq = 1;
+ }
+ }
+
+ /* TRACE(inseq, fdata, tdata, seq, end, ack, ackskew, win, maxwin) */
+
+ if (inseq) {
/* if ackskew < 0 then this should be due to fragmented
* packets. There is no way to know the length of the
* total packet in advance.
@@ -1584,8 +1784,7 @@
clone->is_flags &= ~SI_CLONE;
clone->is_flags |= SI_CLONED;
fr_stinsert(clone, fin->fin_rev);
- MUTEX_ENTER(&clone->is_lock);
- clone->is_ref = 1;
+ clone->is_ref = 2;
if (clone->is_p == IPPROTO_TCP) {
(void) fr_tcp_age(&clone->is_sti, fin, ips_tqtqb,
clone->is_flags);
@@ -1653,9 +1852,9 @@
* 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)
@@ -1770,7 +1969,7 @@
* Match up any flags set from IP options.
*/
if ((cflx && (flx != (cflx & cmask))) ||
- ((fin->fin_optmsk & is->is_optmsk) != is->is_opt) ||
+ ((fin->fin_optmsk & is->is_optmsk[rev]) != is->is_opt[rev]) ||
((fin->fin_secmsk & is->is_secmsk) != is->is_sec) ||
((fin->fin_auth & is->is_authmsk) != is->is_auth))
return NULL;
@@ -1787,9 +1986,12 @@
if ((flags & (SI_W_SPORT|SI_W_DPORT))) {
if ((flags & SI_CLONE) != 0) {
- is = fr_stclone(fin, tcp, is);
- if (is == NULL)
+ ipstate_t *clone;
+
+ clone = fr_stclone(fin, tcp, is);
+ if (clone == NULL)
return NULL;
+ is = clone;
} else {
ATOMIC_DECL(ips_stats.iss_wild);
}
@@ -1820,8 +2022,14 @@
ret = -1;
- if (is->is_flx[out][rev] == 0)
+ if (is->is_flx[out][rev] == 0) {
is->is_flx[out][rev] = flx;
+ is->is_opt[rev] = fin->fin_optmsk;
+ if (is->is_v == 6) {
+ is->is_opt[rev] &= ~0x8;
+ is->is_optmsk[rev] &= ~0x8;
+ }
+ }
/*
* Check if the interface name for this "direction" is set and if not,
@@ -1830,7 +2038,7 @@
if (is->is_ifp[idx] == NULL &&
(*is->is_ifname[idx] == '\0' || *is->is_ifname[idx] == '*')) {
is->is_ifp[idx] = ifp;
- COPYIFNAME(ifp, is->is_ifname[idx]);
+ COPYIFNAME(is->is_v, ifp, is->is_ifname[idx]);
}
fin->fin_rev = rev;
return is;
@@ -1867,21 +2075,16 @@
/*
* Does it at least have the return (basic) IP header ?
+ * Is it an actual recognised ICMP error type?
* Only a basic IP header (no options) should be with
* an ICMP error header.
*/
if ((fin->fin_v != 4) || (fin->fin_hlen != sizeof(ip_t)) ||
- (fin->fin_plen < ICMPERR_MINPKTLEN))
+ (fin->fin_plen < ICMPERR_MINPKTLEN) ||
+ !(fin->fin_flx & FI_ICMPERR))
return NULL;
ic = fin->fin_dp;
type = ic->icmp_type;
- /*
- * If it's not an error type, then return
- */
- if ((type != ICMP_UNREACH) && (type != ICMP_SOURCEQUENCH) &&
- (type != ICMP_REDIRECT) && (type != ICMP_TIMXCEED) &&
- (type != ICMP_PARAMPROB))
- return NULL;
oip = (ip_t *)((char *)ic + ICMPERR_ICMPHLEN);
/*
@@ -1921,7 +2124,7 @@
# 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
@@ -1944,14 +2147,13 @@
*/
savelen = oip->ip_len;
oip->ip_len = len;
- oip->ip_off = htons(oip->ip_off);
+ oip->ip_off = ntohs(oip->ip_off);
ofin.fin_flx = FI_NOCKSUM;
ofin.fin_v = 4;
ofin.fin_ip = oip;
ofin.fin_m = NULL; /* if dereferenced, panic XXX */
ofin.fin_mp = NULL; /* if dereferenced, panic XXX */
- ofin.fin_plen = fin->fin_dlen - ICMPERR_ICMPHLEN;
(void) fr_makefrip(IP_HL(oip) << 2, oip, &ofin);
ofin.fin_ifp = fin->fin_ifp;
ofin.fin_out = !fin->fin_out;
@@ -1972,8 +2174,6 @@
switch (oip->ip_p)
{
case IPPROTO_ICMP :
- icmp = (icmphdr_t *)((char *)oip + (IP_HL(oip) << 2));
-
/*
* an ICMP error can only be generated as a result of an
* ICMP query, not as the response on an ICMP error
@@ -1981,15 +2181,13 @@
* XXX theoretically ICMP_ECHOREP and the other reply's are
* ICMP query's as well, but adding them here seems strange XXX
*/
- if ((icmp->icmp_type != ICMP_ECHO) &&
- (icmp->icmp_type != ICMP_TSTAMP) &&
- (icmp->icmp_type != ICMP_IREQ) &&
- (icmp->icmp_type != ICMP_MASKREQ))
+ if ((ofin.fin_flx & FI_ICMPERR) != 0)
return NULL;
/*
* perform a lookup of the ICMP packet in the state table
*/
+ icmp = (icmphdr_t *)((char *)oip + (IP_HL(oip) << 2));
hv = (pr = oip->ip_p);
src.in4 = oip->ip_src;
hv += src.in4.s_addr;
@@ -2008,10 +2206,6 @@
is = fr_matchsrcdst(&ofin, is, &src, &dst,
NULL, FI_ICMPCMP);
if (is != NULL) {
- if ((is->is_pass & FR_NOICMPERR) != 0) {
- RWLOCK_EXIT(&ipf_state);
- return NULL;
- }
/*
* i : the index of this packet (the icmp
* unreachable)
@@ -2115,8 +2309,6 @@
ipstate_t **isp;
u_int hvm;
- ASSERT(rw_read_locked(&ipf_state.ipf_lk) == 0);
-
hvm = is->is_hv;
/*
* Remove the hash from the old location...
@@ -2199,6 +2391,14 @@
}
}
#endif
+ if ((v == 4) &&
+ (fin->fin_flx & (FI_MULTICAST|FI_BROADCAST|FI_MBCAST))) {
+ if (fin->fin_out == 0) {
+ hv -= src.in4.s_addr;
+ } else {
+ hv -= dst.in4.s_addr;
+ }
+ }
/*
* Search the hash table for matching packet header info.
@@ -2219,6 +2419,13 @@
hvm = DOUBLE_HASH(hv);
for (isp = &ips_table[hvm]; ((is = *isp) != NULL); ) {
isp = &is->is_hnext;
+ /*
+ * If a connection is about to be deleted, no packets
+ * are allowed to match it.
+ */
+ if (is->is_sti.tqe_ifq == &ips_deletetq)
+ continue;
+
if ((is->is_p != pr) || (is->is_v != v))
continue;
is = fr_matchsrcdst(fin, is, &src, &dst, NULL, FI_CMP);
@@ -2284,7 +2491,8 @@
if ((is->is_p != pr) || (is->is_v != v))
continue;
is = fr_matchsrcdst(fin, is, &src, &dst, NULL, FI_CMP);
- if (is != NULL &&
+ if ((is != NULL) &&
+ (ic->icmp_id == is->is_icmp.ici_id) &&
fr_matchicmpqueryreply(v, &is->is_icmp,
ic, fin->fin_rev)) {
if (fin->fin_rev)
@@ -2339,12 +2547,31 @@
}
RWLOCK_EXIT(&ipf_state);
- if (!tryagain && ips_stats.iss_wild) {
- hv -= dport;
- hv -= sport;
- tryagain = 1;
- WRITE_ENTER(&ipf_state);
- goto retry_tcpudp;
+ if (ips_stats.iss_wild) {
+ if (tryagain == 0) {
+ hv -= dport;
+ hv -= sport;
+ } else if (tryagain == 1) {
+ hv = fin->fin_fi.fi_p;
+ /*
+ * If we try to pretend this is a reply to a
+ * multicast/broadcast packet then we need to
+ * exclude part of the address from the hash
+ * calculation.
+ */
+ if (fin->fin_out == 0) {
+ hv += src.in4.s_addr;
+ } else {
+ hv += dst.in4.s_addr;
+ }
+ hv += dport;
+ hv += sport;
+ }
+ tryagain++;
+ if (tryagain <= 2) {
+ WRITE_ENTER(&ipf_state);
+ goto retry_tcpudp;
+ }
}
fin->fin_flx |= oow;
break;
@@ -2377,11 +2604,13 @@
break;
}
- if ((is != NULL) && ((is->is_sti.tqe_flags & TQE_RULEBASED) != 0) &&
- (is->is_tqehead[fin->fin_rev] != NULL))
- ifq = is->is_tqehead[fin->fin_rev];
- if (ifq != NULL && ifqp != NULL)
- *ifqp = ifq;
+ if (is != NULL) {
+ if (((is->is_sti.tqe_flags & TQE_RULEBASED) != 0) &&
+ (is->is_tqehead[fin->fin_rev] != NULL))
+ ifq = is->is_tqehead[fin->fin_rev];
+ if (ifq != NULL && ifqp != NULL)
+ *ifqp = ifq;
+ }
return is;
}
@@ -2545,8 +2774,6 @@
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;
@@ -2682,7 +2909,7 @@
/* ------------------------------------------------------------------------ */
/* Function: fr_delstate */
-/* Returns: Nil */
+/* Returns: int - 0 = entry deleted, else reference count on struct */
/* Parameters: is(I) - pointer to state structure to delete */
/* why(I) - if not 0, log reason why it was deleted */
/* Write Locks: ipf_state */
@@ -2691,27 +2918,15 @@
/* 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;
{
- ASSERT(rw_read_locked(&ipf_state.ipf_lk) == 0);
-
/*
* 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)
@@ -2739,7 +2954,8 @@
/*
* 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;
@@ -2748,11 +2964,21 @@
/*
* 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;
+ MUTEX_ENTER(&is->is_lock);
+ if (is->is_ref > 1) {
+ is->is_ref--;
+ MUTEX_EXIT(&is->is_lock);
+ return is->is_ref;
+ }
+ MUTEX_EXIT(&is->is_lock);
+
+ is->is_ref = 0;
if (is->is_tqehead[0] != NULL) {
if (fr_deletetimeoutqueue(is->is_tqehead[0]) == 0)
@@ -2771,17 +2997,37 @@
(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);
+ if (is->is_p == IPPROTO_TCP)
+ ips_stats.iss_fin++;
+ else
+ ips_stats.iss_expire++;
+
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;
}
@@ -2800,9 +3046,7 @@
ipftq_t *ifq, *ifqnext;
ipftqent_t *tqe, *tqn;
ipstate_t *is;
-#if defined(USE_SPL) && defined(_KERNEL)
- int s;
-#endif
+ SPL_INT(s);
SPL_NET(s);
WRITE_ENTER(&ipf_state);
@@ -2869,48 +3113,115 @@
ipftq_t *ifq, *ifqnext;
ipftqent_t *tqe, *tqn;
ipstate_t *is, **isp;
- int delete, removed;
- long try, maxtick;
- u_long interval;
-#if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL)
- int s;
-#endif
+ int removed;
+ SPL_INT(s);
removed = 0;
SPL_NET(s);
- for (isp = &ips_list; ((is = *isp) != NULL); ) {
- delete = 0;
- if ((proto != 0) && (is->is_v != proto)) {
- isp = &is->is_next;
- continue;
+ switch (which)
+ {
+ case 0 :
+ /*
+ * Style 0 flush removes everything...
+ */
+ for (isp = &ips_list; ((is = *isp) != NULL); ) {
+ if ((proto != 0) && (is->is_v != proto)) {
+ isp = &is->is_next;
+ continue;
+ }
+ if (fr_delstate(is, ISL_FLUSH) == 0)
+ removed++;
+ else
+ isp = &is->is_next;
}
+ break;
- switch (which)
- {
- case 0 :
- delete = 1;
- break;
- case 1 :
- case 2 :
- if (is->is_p != IPPROTO_TCP)
- break;
- if ((is->is_state[0] != IPF_TCPS_ESTABLISHED) ||
- (is->is_state[1] != IPF_TCPS_ESTABLISHED))
- delete = 1;
- break;
+ case 1 :
+ /*
+ * Since we're only interested in things that are closing,
+ * we can start with the appropriate timeout queue.
+ */
+ for (ifq = ips_tqtqb + IPF_TCPS_CLOSE_WAIT; ifq != NULL;
+ ifq = ifq->ifq_next) {
+
+ for (tqn = ifq->ifq_head; ((tqe = tqn) != NULL); ) {
+ tqn = tqe->tqe_next;
+ is = tqe->tqe_parent;
+ if (is->is_p != IPPROTO_TCP)
+ break;
+ if (fr_delstate(is, ISL_EXPIRE) == 0)
+ removed++;
+ }
}
- if (delete) {
- if (is->is_p == IPPROTO_TCP)
- ips_stats.iss_fin++;
- else
- ips_stats.iss_expire++;
- fr_delstate(is, ISL_FLUSH);
- removed++;
- } else
+ /*
+ * Also need to look through the user defined queues.
+ */
+ for (ifq = ips_utqe; ifq != NULL; ifq = ifqnext) {
+ ifqnext = ifq->ifq_next;
+ for (tqn = ifq->ifq_head; ((tqe = tqn) != NULL); ) {
+ tqn = tqe->tqe_next;
+ is = tqe->tqe_parent;
+ if (is->is_p != IPPROTO_TCP)
+ continue;
+
+ if ((is->is_state[0] > IPF_TCPS_ESTABLISHED) &&
+ (is->is_state[1] > IPF_TCPS_ESTABLISHED)) {
+ if (fr_delstate(is, ISL_EXPIRE) == 0)
+ removed++;
+ }
+ }
+ }
+ break;
+
+ case 2 :
+ break;
+
+ /*
+ * Args 5-11 correspond to flushing those particular states
+ * for TCP connections.
+ */
+ case IPF_TCPS_CLOSE_WAIT :
+ case IPF_TCPS_FIN_WAIT_1 :
+ case IPF_TCPS_CLOSING :
+ case IPF_TCPS_LAST_ACK :
+ case IPF_TCPS_FIN_WAIT_2 :
+ case IPF_TCPS_TIME_WAIT :
+ case IPF_TCPS_CLOSED :
+ tqn = ips_tqtqb[which].ifq_head;
+ while (tqn != NULL) {
+ tqe = tqn;
+ tqn = tqe->tqe_next;
+ is = tqe->tqe_parent;
+ if (fr_delstate(is, ISL_FLUSH) == 0)
+ removed++;
+ }
+ break;
+
+ default :
+ if (which < 30)
+ break;
+
+ /*
+ * Take a large arbitrary number to mean the number of seconds
+ * for which which consider to be the maximum value we'll allow
+ * the expiration to be.
+ */
+ which = IPF_TTLVAL(which);
+ for (isp = &ips_list; ((is = *isp) != NULL); ) {
+ if ((proto == 0) || (is->is_v == proto)) {
+ if (fr_ticks - is->is_touched > which) {
+ if (fr_delstate(is, ISL_FLUSH) == 0) {
+ removed++;
+ continue;
+ }
+ }
+ }
isp = &is->is_next;
+ }
+ break;
}
if (which != 2) {
@@ -2919,83 +3230,35 @@
}
/*
- * Asked to remove inactive entries because the table is full, try
- * again, 3 times, if first attempt failed with a different criteria
- * each time. The order tried in must be in decreasing age.
- * Another alternative is to implement random drop and drop N entries
- * at random until N have been freed up.
+ * Asked to remove inactive entries because the table is full.
*/
- if (fr_ticks - ips_last_force_flush < IPF_TTLVAL(5))
- goto force_flush_skipped;
- ips_last_force_flush = fr_ticks;
-
- if (fr_ticks > IPF_TTLVAL(43200))
- interval = IPF_TTLVAL(43200);
- else if (fr_ticks > IPF_TTLVAL(1800))
- interval = IPF_TTLVAL(1800);
- else if (fr_ticks > IPF_TTLVAL(30))
- interval = IPF_TTLVAL(30);
- else
- interval = IPF_TTLVAL(10);
- try = fr_ticks - (fr_ticks - interval);
- if (try < 0)
- goto force_flush_skipped;
-
- while (removed == 0) {
- maxtick = fr_ticks - interval;
- if (maxtick < 0)
- break;
-
- while (try < maxtick) {
- for (ifq = ips_tqtqb; ifq != NULL;
- ifq = ifq->ifq_next) {
- for (tqn = ifq->ifq_head;
- ((tqe = tqn) != NULL); ) {
- if (tqe->tqe_die > try)
- break;
- tqn = tqe->tqe_next;
- is = tqe->tqe_parent;
- fr_delstate(is, ISL_EXPIRE);
- removed++;
- }
- }
-
- for (ifq = ips_utqe; ifq != NULL; ifq = ifqnext) {
- ifqnext = ifq->ifq_next;
-
- for (tqn = ifq->ifq_head;
- ((tqe = tqn) != NULL); ) {
- if (tqe->tqe_die > try)
- break;
- tqn = tqe->tqe_next;
- is = tqe->tqe_parent;
- fr_delstate(is, ISL_EXPIRE);
- removed++;
- }
- }
- if (try + interval > maxtick)
- break;
- try += interval;
- }
-
- if (removed == 0) {
- if (interval == IPF_TTLVAL(43200)) {
- interval = IPF_TTLVAL(1800);
- } else if (interval == IPF_TTLVAL(1800)) {
- interval = IPF_TTLVAL(30);
- } else if (interval == IPF_TTLVAL(30)) {
- interval = IPF_TTLVAL(10);
- } else {
- break;
- }
- }
+ if (fr_ticks - ips_last_force_flush > IPF_TTLVAL(5)) {
+ ips_last_force_flush = fr_ticks;
+ removed = ipf_queueflush(fr_state_flush_entry, ips_tqtqb,
+ ips_utqe);
}
-force_flush_skipped:
+
SPL_X(s);
return removed;
}
+/* ------------------------------------------------------------------------ */
+/* Function: fr_state_flush_entry */
+/* Returns: int - 0 = entry deleted, else not deleted */
+/* Parameters: entry(I) - pointer to state structure to delete */
+/* Write Locks: ipf_state */
+/* */
+/* This function is a stepping stone between ipf_queueflush() and */
+/* fr_delstate(). It is used so we can provide a uniform interface via the */
+/* ipf_queueflush() function. */
+/* ------------------------------------------------------------------------ */
+static int fr_state_flush_entry(entry)
+void *entry;
+{
+ return fr_delstate(entry, ISL_FLUSH);
+}
+
/* ------------------------------------------------------------------------ */
/* Function: fr_tcp_age */
@@ -3025,6 +3288,25 @@
/* dir == 0 : a packet from source to dest */
/* dir == 1 : a packet from dest to source */
/* */
+/* A typical procession for a connection is as follows: */
+/* */
+/* +--------------+-------------------+ */
+/* | Side '0' | Side '1' | */
+/* +--------------+-------------------+ */
+/* | 0 -> 1 (SYN) | | */
+/* | | 0 -> 2 (SYN-ACK) | */
+/* | 1 -> 3 (ACK) | | */
+/* | | 2 -> 4 (ACK-PUSH) | */
+/* | 3 -> 4 (ACK) | | */
+/* | ... | ... | */
+/* | | 4 -> 6 (FIN-ACK) | */
+/* | 4 -> 5 (ACK) | | */
+/* | | 6 -> 6 (ACK-PUSH) | */
+/* | 5 -> 5 (ACK) | | */
+/* | 5 -> 8 (FIN) | | */
+/* | | 6 -> 10 (ACK) | */
+/* +--------------+-------------------+ */
+/* */
/* Locking: it is assumed that the parent of the tqe structure is locked. */
/* ------------------------------------------------------------------------ */
int fr_tcp_age(tqe, fin, tqtab, flags)
@@ -3042,7 +3324,7 @@
rval = 0;
dir = fin->fin_rev;
tcpflags = tcp->th_flags;
- dlen = fin->fin_plen - fin->fin_hlen - (TCP_OFF(tcp) << 2);
+ dlen = fin->fin_dlen - (TCP_OFF(tcp) << 2);
if (tcpflags & TH_RST) {
if (!(tcpflags & TH_PUSH) && !dlen)
@@ -3056,16 +3338,16 @@
switch (nstate)
{
- case IPF_TCPS_CLOSED: /* 0 */
+ case IPF_TCPS_LISTEN: /* 0 */
if ((tcpflags & TH_OPENING) == TH_OPENING) {
/*
* 'dir' received an S and sends SA in
- * response, CLOSED -> SYN_RECEIVED
+ * response, LISTEN -> SYN_RECEIVED
*/
nstate = IPF_TCPS_SYN_RECEIVED;
rval = 1;
} else if ((tcpflags & TH_OPENING) == TH_SYN) {
- /* 'dir' sent S, CLOSED -> SYN_SENT */
+ /* 'dir' sent S, LISTEN -> SYN_SENT */
nstate = IPF_TCPS_SYN_SENT;
rval = 1;
}
@@ -3084,7 +3366,7 @@
*/
switch (ostate)
{
- case IPF_TCPS_CLOSED :
+ case IPF_TCPS_LISTEN :
case IPF_TCPS_SYN_RECEIVED :
nstate = IPF_TCPS_HALF_ESTAB;
rval = 1;
@@ -3105,11 +3387,7 @@
*/
break;
- case IPF_TCPS_LISTEN: /* 1 */
- /* NOT USED */
- break;
-
- case IPF_TCPS_SYN_SENT: /* 2 */
+ case IPF_TCPS_SYN_SENT: /* 1 */
if ((tcpflags & ~(TH_ECN|TH_CWR)) == TH_SYN) {
/*
* A retransmitted SYN packet. We do not reset
@@ -3150,7 +3428,7 @@
}
break;
- case IPF_TCPS_SYN_RECEIVED: /* 3 */
+ case IPF_TCPS_SYN_RECEIVED: /* 2 */
if ((tcpflags & (TH_SYN|TH_FIN|TH_ACK)) == TH_ACK) {
/*
* we see an A from 'dir' which was in
@@ -3179,17 +3457,38 @@
}
break;
- case IPF_TCPS_HALF_ESTAB: /* 4 */
- if (ostate >= IPF_TCPS_HALF_ESTAB) {
- if ((tcpflags & TH_ACKMASK) == TH_ACK) {
+ case IPF_TCPS_HALF_ESTAB: /* 3 */
+ if (tcpflags & TH_FIN) {
+ nstate = IPF_TCPS_FIN_WAIT_1;
+ rval = 1;
+ } else if ((tcpflags & TH_ACKMASK) == TH_ACK) {
+ /*
+ * If we've picked up a connection in mid
+ * flight, we could be looking at a follow on
+ * packet from the same direction as the one
+ * that created this state. Recognise it but
+ * do not advance the entire connection's
+ * state.
+ */
+ switch (ostate)
+ {
+ case IPF_TCPS_LISTEN :
+ case IPF_TCPS_SYN_SENT :
+ case IPF_TCPS_SYN_RECEIVED :
+ rval = 1;
+ break;
+ case IPF_TCPS_HALF_ESTAB :
+ case IPF_TCPS_ESTABLISHED :
nstate = IPF_TCPS_ESTABLISHED;
rval = 1;
+ break;
+ default :
+ break;
}
}
-
break;
- case IPF_TCPS_ESTABLISHED: /* 5 */
+ case IPF_TCPS_ESTABLISHED: /* 4 */
rval = 1;
if (tcpflags & TH_FIN) {
/*
@@ -3197,7 +3496,11 @@
* this gives us a half-closed connection;
* ESTABLISHED -> FIN_WAIT_1
*/
- nstate = IPF_TCPS_FIN_WAIT_1;
+ if (ostate == IPF_TCPS_FIN_WAIT_1) {
+ nstate = IPF_TCPS_CLOSING;
+ } else {
+ nstate = IPF_TCPS_FIN_WAIT_1;
+ }
} else if (tcpflags & TH_ACK) {
/*
* an ACK, should we exclude other flags here?
@@ -3222,7 +3525,7 @@
}
break;
- case IPF_TCPS_CLOSE_WAIT: /* 6 */
+ case IPF_TCPS_CLOSE_WAIT: /* 5 */
rval = 1;
if (tcpflags & TH_FIN) {
/*
@@ -3240,7 +3543,7 @@
}
break;
- case IPF_TCPS_FIN_WAIT_1: /* 7 */
+ case IPF_TCPS_FIN_WAIT_1: /* 6 */
rval = 1;
if ((tcpflags & TH_ACK) &&
ostate > IPF_TCPS_CLOSE_WAIT) {
@@ -3268,11 +3571,14 @@
}
break;
- case IPF_TCPS_CLOSING: /* 8 */
- /* NOT USED */
+ case IPF_TCPS_CLOSING: /* 7 */
+ if ((tcpflags & (TH_FIN|TH_ACK)) == TH_ACK) {
+ nstate = IPF_TCPS_TIME_WAIT;
+ }
+ rval = 2;
break;
- case IPF_TCPS_LAST_ACK: /* 9 */
+ case IPF_TCPS_LAST_ACK: /* 8 */
if (tcpflags & TH_ACK) {
if ((tcpflags & TH_PUSH) || dlen)
/*
@@ -3291,19 +3597,22 @@
*/
break;
- case IPF_TCPS_FIN_WAIT_2: /* 10 */
- rval = 1;
- if ((tcpflags & TH_OPENING) == TH_OPENING)
- nstate = IPF_TCPS_SYN_RECEIVED;
- else if (tcpflags & TH_SYN)
- nstate = IPF_TCPS_SYN_SENT;
+ case IPF_TCPS_FIN_WAIT_2: /* 9 */
+ /* NOT USED */
break;
- case IPF_TCPS_TIME_WAIT: /* 11 */
+ case IPF_TCPS_TIME_WAIT: /* 10 */
/* we're in 2MSL timeout now */
+ if (ostate == IPF_TCPS_LAST_ACK) {
+ nstate = IPF_TCPS_CLOSED;
+ }
rval = 1;
break;
+ case IPF_TCPS_CLOSED: /* 11 */
+ rval = 2;
+ break;
+
default :
#if defined(_KERNEL)
# if SOLARIS
@@ -3316,9 +3625,6 @@
(u_long)tcp, tcpflags, (u_long)tqe,
nstate, ostate);
# endif
-# ifdef DIAGNOSTIC
- panic("invalid TCP state");
-# endif
#else
abort();
#endif
@@ -3442,26 +3748,22 @@
/*
* Does it at least have the return (basic) IP header ?
+ * Is it an actual recognised ICMP error type?
* Only a basic IP header (no options) should be with
* an ICMP error header.
*/
- if ((fin->fin_v != 6) || (fin->fin_plen < ICMP6ERR_MINPKTLEN))
+ if ((fin->fin_v != 6) || (fin->fin_plen < ICMP6ERR_MINPKTLEN) ||
+ !(fin->fin_flx & FI_ICMPERR))
return NULL;
ic6 = fin->fin_dp;
type = ic6->icmp6_type;
- /*
- * If it's not an error type, then return
- */
- if ((type != ICMP6_DST_UNREACH) && (type != ICMP6_PACKET_TOO_BIG) &&
- (type != ICMP6_TIME_EXCEEDED) && (type != ICMP6_PARAM_PROB))
- return NULL;
oip6 = (ip6_t *)((char *)ic6 + ICMPERR_ICMPHLEN);
if (fin->fin_plen < sizeof(*oip6))
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;
@@ -3482,7 +3784,6 @@
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;
@@ -3629,7 +3930,7 @@
tqp[IPF_TCPS_CLOSING].ifq_ttl = fr_tcptimeout;
tqp[IPF_TCPS_LAST_ACK].ifq_ttl = fr_tcplastack;
tqp[IPF_TCPS_FIN_WAIT_2].ifq_ttl = fr_tcpclosewait;
- tqp[IPF_TCPS_TIME_WAIT].ifq_ttl = fr_tcptimeout;
+ tqp[IPF_TCPS_TIME_WAIT].ifq_ttl = fr_tcptimewait;
tqp[IPF_TCPS_HALF_ESTAB].ifq_ttl = fr_tcptimeout;
}
@@ -3660,6 +3961,14 @@
/* Decrement the reference counter for this state table entry and free it */
/* if there are no more things using it. */
/* */
+/* This function is only called when cleaning up after increasing is_ref by */
+/* one earlier in the 'code path' so if is_ref is 1 when entering, we do */
+/* have an orphan, otherwise not. However there is a possible race between */
+/* the entry being deleted via flushing with an ioctl call (that calls the */
+/* delete function directly) and the tail end of packet processing so we */
+/* need to grab is_lock before doing the check to synchronise the two code */
+/* paths. */
+/* */
/* When operating in userland (ipftest), we have no timers to clear a state */
/* entry. Therefore, we make a few simple tests before deleting an entry */
/* outright. We compare states on each side looking for a combination of */
@@ -3675,60 +3984,30 @@
/* 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);
- is->is_ref--;
- if (is->is_ref == 0) {
- is->is_ref++; /* To counter ref-- in fr_delstate() */
- fr_delstate(is, ISL_EXPIRE);
+
+ MUTEX_ENTER(&is->is_lock);
+ if (is->is_ref > 1) {
+ is->is_ref--;
+ MUTEX_EXIT(&is->is_lock);
#ifndef _KERNEL
-#if 0
- } else if (((fin->fin_out == 1) || (eol == 1)) &&
- ((ostate == IPF_TCPS_LAST_ACK) &&
- (nstate == IPF_TCPS_TIME_WAIT))) {
- ;
-#else
- } else if ((is->is_sti.tqe_state[0] > IPF_TCPS_ESTABLISHED) ||
+ if ((is->is_sti.tqe_state[0] > IPF_TCPS_ESTABLISHED) ||
(is->is_sti.tqe_state[1] > IPF_TCPS_ESTABLISHED)) {
+ fr_delstate(is, ISL_ORPHAN);
+ }
#endif
- fr_delstate(is, ISL_ORPHAN);
-#endif
+ return;
}
+ MUTEX_EXIT(&is->is_lock);
+
+ WRITE_ENTER(&ipf_state);
+ fr_delstate(is, ISL_EXPIRE);
RWLOCK_EXIT(&ipf_state);
}
@@ -3800,3 +4079,121 @@
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 < 1)
+ 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;
+ }
+
+ count = itp->igi_nitems;
+ for (;;) {
+ 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.
+ */
+ if (count == 1) {
+ MUTEX_ENTER(&next->is_lock);
+ next->is_ref++;
+ MUTEX_EXIT(&next->is_lock);
+ token->ipt_data = next;
+ }
+ } else {
+ bzero(&zero, sizeof(zero));
+ next = &zero;
+ count = 1;
+ token->ipt_data = NULL;
+ }
+ RWLOCK_EXIT(&ipf_state);
+
+ /*
+ * 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);
+ count--;
+
+ READ_ENTER(&ipf_state);
+ next = next->is_next;
+ }
+
+ if (is != NULL) {
+ fr_statederef(&is);
+ }
+
+ 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;
+}
Index: ip_scan.h
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_scan.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_scan.h -L sys/contrib/ipfilter/netinet/ip_scan.h -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_scan.h
+++ sys/contrib/ipfilter/netinet/ip_scan.h
@@ -1,12 +1,10 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_scan.h,v 1.1.1.1 2005/04/25 18:15:35 darrenr Exp $ */
-
/*
* Copyright (C) 1993-2001 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* @(#)ip_fil.h 1.35 6/5/96
- * Id: ip_scan.h,v 2.9 2003/07/25 22:05:01 darrenr Exp
+ * $Id: ip_scan.h,v 2.9.2.2 2006/07/14 06:12:19 darrenr Exp $
*/
#ifndef __IP_SCAN_H__
@@ -27,7 +25,7 @@
struct ipstate;
-#if defined(__STDC__) || defined(__GNUC__)
+#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51)
# define SIOCADSCA _IOWR('r', 60, struct ipscan *)
# define SIOCRMSCA _IOWR('r', 61, struct ipscan *)
# define SIOCGSCST _IOWR('r', 62, struct ipscan *)
@@ -96,7 +94,7 @@
} ipscanstat_t;
-extern int fr_scan_ioctl __P((caddr_t, ioctlcmd_t, int));
+extern int fr_scan_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *));
extern int ipsc_init __P((void));
extern int ipsc_attachis __P((struct ipstate *));
extern int ipsc_attachfr __P((struct frentry *));
Index: ip_nat.h
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_nat.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_nat.h -L sys/contrib/ipfilter/netinet/ip_nat.h -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_nat.h
+++ sys/contrib/ipfilter/netinet/ip_nat.h
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_nat.h,v 1.24 2005/04/27 03:48:10 darrenr Exp $ */
+/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_nat.h,v 1.26.2.1 2007/10/31 05:00:38 darrenr Exp $ */
/*
* Copyright (C) 1995-2001, 2003 by Darren Reed.
@@ -6,8 +6,8 @@
* See the IPFILTER.LICENCE file for details on licencing.
*
* @(#)ip_nat.h 1.5 2/4/96
- * $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_nat.h,v 1.24 2005/04/27 03:48:10 darrenr Exp $
- * Id: ip_nat.h,v 2.90.2.9 2005/03/28 11:09:55 darrenr Exp
+ * $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_nat.h,v 1.26.2.1 2007/10/31 05:00:38 darrenr Exp $
+ * Id: ip_nat.h,v 2.90.2.20 2007/09/25 08:27:32 darrenr Exp $
*/
#ifndef __IP_NAT_H__
@@ -17,18 +17,16 @@
#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
#endif
-#if defined(__STDC__) || defined(__GNUC__)
+#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51)
#define SIOCADNAT _IOW('r', 60, struct ipfobj)
#define SIOCRMNAT _IOW('r', 61, struct ipfobj)
#define SIOCGNATS _IOWR('r', 62, struct ipfobj)
#define SIOCGNATL _IOWR('r', 63, struct ipfobj)
-/* SIOCPROXY _IOWR('r', 64, struct ap_control) */
#else
#define SIOCADNAT _IOW(r, 60, struct ipfobj)
#define SIOCRMNAT _IOW(r, 61, struct ipfobj)
#define SIOCGNATS _IOWR(r, 62, struct ipfobj)
#define SIOCGNATL _IOWR(r, 63, struct ipfobj)
-/* SIOCPROXY _IOWR(r, 64, struct ap_control) */
#endif
#undef LARGE_NAT /* define this if you're setting up a system to NAT
@@ -126,6 +124,8 @@
int nat_hv[2];
char nat_ifnames[2][LIFNAMSIZ];
int nat_rev; /* 0 = forward, 1 = reverse */
+ int nat_redir; /* copy of in_redir */
+ u_32_t nat_seqnext[2];
} nat_t;
#define nat_inip nat_inip6.in4
@@ -138,6 +138,8 @@
#define nat_seq nat_un.nat_uni.ici_seq
#define nat_id nat_un.nat_uni.ici_id
#define nat_tcpstate nat_tqe.tqe_state
+#define nat_die nat_tqe.tqe_die
+#define nat_touched nat_tqe.tqe_touched
/*
* Values for nat_dir
@@ -154,7 +156,7 @@
#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)
@@ -173,6 +175,7 @@
#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 */
@@ -298,24 +301,6 @@
} natget_t;
-typedef struct nattrpnt {
- struct in_addr tr_dstip; /* real destination IP# */
- struct in_addr tr_srcip; /* real source IP# */
- struct in_addr tr_locip; /* local source IP# */
- u_int tr_flags;
- int tr_expire;
- u_short tr_dstport; /* real destination port# */
- u_short tr_srcport; /* real source port# */
- u_short tr_locport; /* local source port# */
- struct nattrpnt *tr_hnext;
- struct nattrpnt **tr_phnext;
- struct nattrpnt *tr_next;
- struct nattrpnt **tr_pnext; /* previous next */
-} nattrpnt_t;
-
-#define TN_CMPSIZ offsetof(nattrpnt_t, tr_hnext)
-
-
/*
* This structure gets used to help NAT sessions keep the same NAT rule (and
* thus translation for IP address) when:
@@ -323,6 +308,8 @@
* (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;
@@ -374,8 +361,10 @@
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;
+ u_int ns_orphans;
} natstat_t;
typedef struct natlog {
@@ -397,6 +386,7 @@
#define NL_NEWRDR NAT_REDIRECT
#define NL_NEWBIMAP NAT_BIMAP
#define NL_NEWBLOCK NAT_MAPBLK
+#define NL_DESTROY 0xfffc
#define NL_CLONE 0xfffd
#define NL_FLUSH 0xfffe
#define NL_EXPIRE 0xffff
@@ -428,6 +418,7 @@
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;
@@ -445,7 +436,7 @@
#if defined(__OpenBSD__)
extern void nat_ifdetach __P((void *));
#endif
-extern int fr_nat_ioctl __P((caddr_t, ioctlcmd_t, int));
+extern int fr_nat_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *));
extern int fr_natinit __P((void));
extern nat_t *nat_new __P((fr_info_t *, ipnat_t *, nat_t **, u_int, int));
extern nat_t *nat_outlookup __P((fr_info_t *, u_int, u_int, struct in_addr,
@@ -459,6 +450,7 @@
extern nat_t *nat_lookupredir __P((natlookup_t *));
extern nat_t *nat_icmperrorlookup __P((fr_info_t *, int));
extern nat_t *nat_icmperror __P((fr_info_t *, u_int *, int));
+extern void nat_delete __P((struct nat *, int));
extern int nat_insert __P((nat_t *, int));
extern int fr_checknatout __P((fr_info_t *, u_32_t *));
@@ -470,9 +462,11 @@
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__ */
Index: ip_pool.c
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_pool.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_pool.c -L sys/contrib/ipfilter/netinet/ip_pool.c -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_pool.c
+++ sys/contrib/ipfilter/netinet/ip_pool.c
@@ -1,5 +1,3 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_pool.c,v 1.1.1.1 2005/04/25 18:15:28 darrenr Exp $ */
-
/*
* Copyright (C) 1993-2001, 2003 by Darren Reed.
*
@@ -55,10 +53,11 @@
# include <sys/malloc.h>
#endif
-#if (defined(__osf__) || defined(__hpux) || defined(__sgi)) && defined(_KERNEL)
-# ifdef __osf__
-# include <net/radix.h>
-# endif
+#if defined(SOLARIS2) && !defined(_KERNEL)
+# include "radix_ipf.h"
+#endif
+#if defined(_KERNEL) && (defined(__osf__) || defined(AIX) || \
+ defined(__hpux) || defined(__sgi))
# include "radix_ipf_local.h"
# define _RADIX_H_
#endif
@@ -79,18 +78,22 @@
#if !defined(lint)
static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)Id: ip_pool.c,v 2.55.2.12 2005/02/01 04:04:46 darrenr Exp";
+static const char rcsid[] = "@(#)$Id: ip_pool.c,v 2.55.2.24 2007/10/10 09:45:37 darrenr Exp $";
#endif
#ifdef IPFILTER_LOOKUP
-# ifndef RADIX_NODE_HEAD_LOCK
+# if !defined(RADIX_NODE_HEAD_LOCK) || !defined(RADIX_NODE_HEAD_UNLOCK) || \
+ !defined(_KERNEL)
+# undef RADIX_NODE_HEAD_LOCK
+# undef RADIX_NODE_HEAD_UNLOCK
# define RADIX_NODE_HEAD_LOCK(x) ;
-# endif
-# ifndef RADIX_NODE_HEAD_UNLOCK
# 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;
@@ -138,7 +141,7 @@
strcpy(op.iplo_name, "0");
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;
@@ -263,18 +266,12 @@
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);
}
}
@@ -308,8 +305,8 @@
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
@@ -320,16 +317,15 @@
}
-
/* ------------------------------------------------------------------------ */
-/* 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;
{
@@ -343,6 +339,29 @@
/* ------------------------------------------------------------------------ */
+/* 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. */
@@ -356,11 +375,9 @@
addrfamily_t *addr, *mask;
{
struct radix_node *n;
-#ifdef USE_SPL
- int s;
+ SPL_INT(s);
SPL_NET(s);
-#endif
RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
n = ipo->ipo_head->rnh_lookup(addr, mask, ipo->ipo_head);
RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
@@ -378,9 +395,9 @@
/* */
/* Search the pool for a given address and return a search result. */
/* ------------------------------------------------------------------------ */
-int ip_pool_search(tptr, version, dptr)
+int ip_pool_search(tptr, ipversion, dptr)
void *tptr;
-int version;
+int ipversion;
void *dptr;
{
struct radix_node *rn;
@@ -400,11 +417,11 @@
bzero(&v, sizeof(v));
v.adf_len = offsetof(addrfamily_t, adf_addr);
- if (version == 4) {
+ if (ipversion == 4) {
v.adf_len += sizeof(addr->in4);
v.adf_addr.in4 = addr->in4;
#ifdef USE_INET6
- } else if (version == 6) {
+ } else if (ipversion == 6) {
v.adf_len += sizeof(addr->in6);
v.adf_addr.in6 = addr->in6;
#endif
@@ -448,8 +465,6 @@
struct radix_node *rn;
ip_pool_node_t *x;
- ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0);
-
KMALLOC(x, ip_pool_node_t *);
if (x == NULL) {
return ENOMEM;
@@ -478,6 +493,7 @@
return ENOMEM;
}
+ x->ipn_ref = 1;
x->ipn_next = ipo->ipo_list;
x->ipn_pnext = &ipo->ipo_list;
if (ipo->ipo_list != NULL)
@@ -501,6 +517,10 @@
/* 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;
@@ -509,7 +529,17 @@
int poolnum, unit;
ip_pool_t *h;
- ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0);
+ unit = op->iplo_unit;
+
+ if ((op->iplo_arg & LOOKUP_ANON) == 0) {
+ h = ip_pool_exists(unit, op->iplo_name);
+ if (h != NULL) {
+ if ((h->ipo_flags & IPOOL_DELETE) == 0)
+ return EEXIST;
+ h->ipo_flags &= ~IPOOL_DELETE;
+ return 0;
+ }
+ }
KMALLOC(h, ip_pool_t *);
if (h == NULL)
@@ -522,12 +552,11 @@
return ENOMEM;
}
- unit = op->iplo_unit;
-
- if ((op->iplo_arg & IPOOL_ANON) != 0) {
+ if ((op->iplo_arg & LOOKUP_ANON) != 0) {
ip_pool_t *p;
- poolnum = IPOOL_ANON;
+ h->ipo_flags |= IPOOL_ANON;
+ poolnum = LOOKUP_ANON;
#if defined(SNPRINTF) && defined(_KERNEL)
SNPRINTF(name, sizeof(name), "%x", poolnum);
@@ -550,8 +579,9 @@
}
(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;
@@ -576,36 +606,24 @@
/* 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;
}
@@ -618,23 +636,28 @@
/* 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;
@@ -650,7 +673,7 @@
/* 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. */
/* ------------------------------------------------------------------------ */
@@ -671,7 +694,7 @@
(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
@@ -692,13 +715,37 @@
/* 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);
@@ -717,13 +764,6 @@
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--;
}
@@ -740,11 +780,178 @@
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);
+ token->ipt_data = nextipo;
+ } else {
+ bzero((char *)&zp, sizeof(zp));
+ nextipo = &zp;
+ token->ipt_data = NULL;
+ }
+ 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);
+ token->ipt_data = nextnode;
+ } else {
+ bzero((char *)&zn, sizeof(zn));
+ nextnode = &zn;
+ token->ipt_data = NULL;
+ }
+ 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);
+ }
+ 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);
+ }
+ 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;
+ }
}
@@ -782,5 +989,4 @@
Free(rnh);
}
# endif
-
#endif /* IPFILTER_LOOKUP */
Index: ip_netbios_pxy.c
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_netbios_pxy.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_netbios_pxy.c -L sys/contrib/ipfilter/netinet/ip_netbios_pxy.c -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_netbios_pxy.c
+++ sys/contrib/ipfilter/netinet/ip_netbios_pxy.c
@@ -1,9 +1,7 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_netbios_pxy.c,v 1.1.1.2 2005/04/25 18:15:27 darrenr Exp $ */
-
/*
* Simple netbios-dgm transparent proxy for in-kernel use.
* For use with the NAT code.
- * Id: ip_netbios_pxy.c,v 2.8 2003/12/01 02:52:16 darrenr Exp
+ * $Id: ip_netbios_pxy.c,v 2.8.2.1 2005/08/20 13:48:23 darrenr Exp $
*/
/*-
@@ -31,7 +29,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * Id: ip_netbios_pxy.c,v 2.8 2003/12/01 02:52:16 darrenr Exp
+ * $Id: ip_netbios_pxy.c,v 2.8.2.1 2005/08/20 13:48:23 darrenr Exp $
*/
#define IPF_NETBIOS_PROXY
@@ -82,19 +80,17 @@
aps = aps; /* LINT */
nat = nat; /* LINT */
- ip = fin->fin_ip;
- m = *(mb_t **)fin->fin_mp;
- off = fin->fin_hlen + sizeof(udphdr_t);
- dlen = M_LEN(m);
- dlen -= off;
-
+ m = fin->fin_m;
+ dlen = fin->fin_dlen - sizeof(*udp);
/*
* no net bios datagram could possibly be shorter than this
*/
if (dlen < 11)
return 0;
+ ip = fin->fin_ip;
udp = (udphdr_t *)fin->fin_dp;
+ off = (char *)udp - (char *)ip + sizeof(*udp) + fin->fin_ipoff;
/*
* move past the
Index: ip_frag.c
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_frag.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_frag.c -L sys/contrib/ipfilter/netinet/ip_frag.c -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_frag.c
+++ sys/contrib/ipfilter/netinet/ip_frag.c
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_frag.c,v 1.29 2005/04/29 05:57:17 ru Exp $ */
+/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_frag.c,v 1.32.2.1 2007/10/31 05:00:37 darrenr Exp $ */
/*
* Copyright (C) 1993-2003 by Darren Reed.
@@ -47,7 +47,7 @@
# endif
#endif
#if !defined(__SVR4) && !defined(__svr4__)
-# if defined(_KERNEL) && !defined(__sgi)
+# if defined(_KERNEL) && !defined(__sgi) && !defined(AIX)
# include <sys/kernel.h>
# endif
#else
@@ -102,21 +102,22 @@
#if !defined(lint)
static const char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)$FreeBSD: src/sys/contrib/ipfilter/netinet/ip_frag.c,v 1.29 2005/04/29 05:57:17 ru Exp $";
-/* static const char rcsid[] = "@(#)Id: ip_frag.c,v 2.77 2004/01/27 00:24:54 darrenr Exp"; */
+static const char rcsid[] = "@(#)$FreeBSD: src/sys/contrib/ipfilter/netinet/ip_frag.c,v 1.32.2.1 2007/10/31 05:00:37 darrenr Exp $";
+/* static const char rcsid[] = "@(#)$Id: ip_frag.c,v 2.77.2.12 2007/09/20 12:51:51 darrenr Exp $"; */
#endif
-static ipfr_t *ipfr_list = NULL;
-static ipfr_t **ipfr_tail = &ipfr_list;
-static ipfr_t **ipfr_heads;
+ipfr_t *ipfr_list = NULL;
+ipfr_t **ipfr_tail = &ipfr_list;
-static ipfr_t *ipfr_natlist = NULL;
-static ipfr_t **ipfr_nattail = &ipfr_natlist;
-static ipfr_t **ipfr_nattab;
+ipfr_t *ipfr_natlist = NULL;
+ipfr_t **ipfr_nattail = &ipfr_natlist;
-static ipfr_t *ipfr_ipidlist = NULL;
-static ipfr_t **ipfr_ipidtail = &ipfr_ipidlist;
+ipfr_t *ipfr_ipidlist = NULL;
+ipfr_t **ipfr_ipidtail = &ipfr_ipidlist;
+
+static ipfr_t **ipfr_heads;
+static ipfr_t **ipfr_nattab;
static ipfr_t **ipfr_ipidtab;
static ipfrstat_t ipfr_stats;
@@ -132,6 +133,7 @@
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 *));
/* ------------------------------------------------------------------------ */
@@ -227,6 +229,7 @@
{
ipfr_t *fra, frag;
u_int idx, off;
+ frentry_t *fr;
ip_t *ip;
if (ipfr_inuse >= IPFT_SIZE)
@@ -238,7 +241,7 @@
ip = fin->fin_ip;
if (pass & FR_FRSTRICT)
- if ((ip->ip_off & IP_OFFMASK) != 0)
+ if (fin->fin_off != 0)
return NULL;
frag.ipfr_p = ip->ip_p;
@@ -278,8 +281,13 @@
return NULL;
}
- if ((fra->ipfr_rule = fin->fin_fr) != NULL)
- fin->fin_fr->fr_ref++;
+ fr = fin->fin_fr;
+ fra->ipfr_rule = fr;
+ if (fr != NULL) {
+ MUTEX_ENTER(&fr->fr_lock);
+ fr->fr_ref++;
+ MUTEX_EXIT(&fr->fr_lock);
+ }
/*
* Insert the fragment into the fragment table, copy the struct used
@@ -302,6 +310,7 @@
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;
@@ -682,11 +691,6 @@
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;
@@ -697,7 +701,30 @@
if (fra->ipfr_hnext)
fra->ipfr_hnext->ipfr_hprev = fra->ipfr_hprev;
*fra->ipfr_hprev = fra->ipfr_hnext;
+
+ if (fra->ipfr_rule != NULL) {
+ (void) fr_derefrule(&fra->ipfr_rule);
+ }
+
+ if (fra->ipfr_ref <= 0)
+ fr_fragfree(fra);
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: fr_fragfree */
+/* Returns: Nil */
+/* Parameters: fra - pointer to frag structure to free */
+/* */
+/* Take care of the details associated with deleting an entry from the frag */
+/* cache. Currently this just means bumping stats correctly after freeing */
+/* ------------------------------------------------------------------------ */
+static void fr_fragfree(fra)
+ipfr_t *fra;
+{
KFREE(fra);
+ ipfr_stats.ifs_expire++;
+ ipfr_inuse--;
}
@@ -715,8 +742,10 @@
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);
@@ -728,6 +757,7 @@
if (nat->nat_data == fra)
nat->nat_data = NULL;
}
+ fra->ipfr_ref--;
fr_fragdelete(fra, &ipfr_nattail);
}
ipfr_nattail = &ipfr_natlist;
@@ -747,9 +777,7 @@
{
ipfr_t **fp, *fra;
nat_t *nat;
-#if defined(USE_SPL) && defined(_KERNEL)
- int s;
-#endif
+ SPL_INT(s);
if (fr_frag_lock)
return;
@@ -763,9 +791,8 @@
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);
@@ -773,9 +800,8 @@
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);
@@ -785,23 +811,27 @@
* 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);
}
@@ -815,7 +845,7 @@
/* expectation of this being called twice per second. */
/* ------------------------------------------------------------------------ */
#if !defined(_KERNEL) || (!SOLARIS && !defined(__hpux) && !defined(__sgi) && \
- !defined(__osf__))
+ !defined(__osf__) && !defined(linux))
# if defined(_KERNEL) && ((BSD >= 199103) || defined(__sgi))
void fr_slowtimer __P((void *ptr))
# else
@@ -824,6 +854,7 @@
{
READ_ENTER(&ipf_global);
+ ipf_expiretokens();
fr_fragexpire();
fr_timeoutstate();
fr_natexpire();
@@ -857,3 +888,106 @@
# 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 = NULL;
+ }
+ RWLOCK_EXIT(lock);
+
+ if (frag != NULL) {
+#ifdef USE_MUTEXES
+ fr_fragderef(&frag, lock);
+#else
+ fr_fragderef(&frag);
+#endif
+ }
+
+ 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);
+}
Index: ip_scan.c
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_scan.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_scan.c -L sys/contrib/ipfilter/netinet/ip_scan.c -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_scan.c
+++ sys/contrib/ipfilter/netinet/ip_scan.c
@@ -1,5 +1,3 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_scan.c,v 1.1.1.1 2005/04/25 18:15:35 darrenr Exp $ */
-
/*
* Copyright (C) 1995-2001 by Darren Reed.
*
@@ -34,7 +32,7 @@
# endif
#endif
#include <sys/socket.h>
-#if !defined(__hpux) && !defined(__osf__) && !defined(linux)
+#if !defined(__hpux) && !defined(__osf__) && !defined(linux) && !defined(AIX)
# include <sys/ioccom.h>
#endif
#ifdef __FreeBSD__
@@ -60,7 +58,7 @@
#if !defined(lint)
static const char sccsid[] = "@(#)ip_state.c 1.8 6/5/96 (C) 1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)Id: ip_scan.c,v 2.40.2.2 2005/01/18 10:13:16 darrenr Exp";
+static const char rcsid[] = "@(#)$Id: ip_scan.c,v 2.40.2.10 2007/06/02 21:22:28 darrenr Exp $";
#endif
#ifdef IPFILTER_SCAN /* endif at bottom of file */
@@ -86,18 +84,23 @@
int ipsc_matchisc __P((ipscan_t *, ipstate_t *, int, int, int *));
int ipsc_match __P((ipstate_t *));
+static int ipsc_inited = 0;
int ipsc_init()
{
RWLOCK_INIT(&ipsc_rwlock, "ip scan rwlock");
+ ipsc_inited = 1;
return 0;
}
void fr_scanunload()
{
- RW_DESTROY(&ipsc_rwlock);
+ if (ipsc_inited == 1) {
+ RW_DESTROY(&ipsc_rwlock);
+ ipsc_inited = 0;
+ }
}
@@ -112,8 +115,10 @@
return ENOMEM;
err = copyinptr(data, isc, sizeof(*isc));
- if (err)
+ if (err) {
+ KFREE(isc);
return err;
+ }
WRITE_ENTER(&ipsc_rwlock);
@@ -227,20 +232,17 @@
fr = is->is_rule;
if (fr) {
i = fr->fr_isc;
- if (!i || (i != (ipscan_t *)-1)) {
+ if ((i != NULL) && (i != (ipscan_t *)-1)) {
is->is_isc = i;
- if (i) {
- ATOMIC_INC32(i->ipsc_sref);
- if (i->ipsc_clen)
- is->is_flags |= IS_SC_CLIENT;
- else
- is->is_flags |= IS_SC_MATCHC;
- if (i->ipsc_slen)
- is->is_flags |= IS_SC_SERVER;
- else
- is->is_flags |= IS_SC_MATCHS;
- } else
- is->is_flags |= (IS_SC_CLIENT|IS_SC_SERVER);
+ ATOMIC_INC32(i->ipsc_sref);
+ if (i->ipsc_clen)
+ is->is_flags |= IS_SC_CLIENT;
+ else
+ is->is_flags |= IS_SC_MATCHC;
+ if (i->ipsc_slen)
+ is->is_flags |= IS_SC_SERVER;
+ else
+ is->is_flags |= IS_SC_MATCHS;
}
}
RWLOCK_EXIT(&ipsc_rwlock);
@@ -433,6 +435,8 @@
}
if (k == 1)
isc = lm;
+ if (isc == NULL)
+ return 0;
/*
* No matches or partial matches, so reset the respective
@@ -539,8 +543,8 @@
j = 0xffff >> (16 - dlen);
i = (0xffff & j) << off;
#ifdef _KERNEL
- COPYDATA(*(mb_t **)fin->fin_mp, fin->fin_hlen + thoff, dlen,
- (caddr_t)is->is_sbuf[rv] + off);
+ COPYDATA(*(mb_t **)fin->fin_mp, fin->fin_plen - fin->fin_dlen + thoff,
+ dlen, (caddr_t)is->is_sbuf[rv] + off);
#endif
is->is_smsk[rv] |= i;
for (j = 0, i = is->is_smsk[rv]; i & 1; i >>= 1)
@@ -563,10 +567,11 @@
}
-int fr_scan_ioctl(data, cmd, mode)
+int fr_scan_ioctl(data, cmd, mode, uid, ctx)
caddr_t data;
ioctlcmd_t cmd;
-int mode;
+int mode, uid;
+void *ctx;
{
ipscanstat_t ipscs;
int err = 0;
@@ -582,7 +587,9 @@
case SIOCGSCST :
bcopy((char *)&ipsc_stat, (char *)&ipscs, sizeof(ipscs));
ipscs.iscs_list = ipsc_list;
- BCOPYOUT(&ipscs, data, sizeof(ipscs));
+ err = BCOPYOUT(&ipscs, data, sizeof(ipscs));
+ if (err != 0)
+ err = EFAULT;
break;
default :
err = EINVAL;
Index: ip_htable.h
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_htable.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_htable.h -L sys/contrib/ipfilter/netinet/ip_htable.h -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_htable.h
+++ sys/contrib/ipfilter/netinet/ip_htable.h
@@ -1,5 +1,3 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_htable.h,v 1.1.1.1 2005/04/25 18:15:18 darrenr Exp $ */
-
#ifndef __IP_HTABLE_H__
#define __IP_HTABLE_H__
@@ -7,10 +5,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 +28,7 @@
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 +42,7 @@
/* iph_type */
#define IPHASH_LOOKUP 0
#define IPHASH_GROUPMAP 1
+#define IPHASH_DELETE 2
#define IPHASH_ANON 0x80000000
@@ -55,17 +57,22 @@
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__ */
Index: ip_raudio_pxy.c
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_raudio_pxy.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_raudio_pxy.c -L sys/contrib/ipfilter/netinet/ip_raudio_pxy.c -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_raudio_pxy.c
+++ sys/contrib/ipfilter/netinet/ip_raudio_pxy.c
@@ -1,12 +1,12 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_raudio_pxy.c,v 1.11 2005/04/25 18:43:14 darrenr Exp $ */
+/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_raudio_pxy.c,v 1.13 2007/06/04 02:54:36 darrenr Exp $ */
/*
- * $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_raudio_pxy.c,v 1.11 2005/04/25 18:43:14 darrenr Exp $
+ * $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_raudio_pxy.c,v 1.13 2007/06/04 02:54:36 darrenr 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
@@ -307,7 +307,7 @@
(void) fr_addstate(&fi, NULL, (sp ? 0 : SI_W_SPORT));
if (fi.fin_state != NULL)
- fr_statederef(&fi, (ipstate_t **)&fi.fin_state);
+ fr_statederef((ipstate_t **)&fi.fin_state);
}
}
@@ -327,7 +327,7 @@
(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);
}
}
Index: ip_rcmd_pxy.c
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c -L sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c
+++ sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c
@@ -1,15 +1,15 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c,v 1.12 2005/04/25 18:43:14 darrenr Exp $ */
+/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c,v 1.15 2007/06/04 02:54:36 darrenr 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.4 2005/02/04 10:22:55 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.
- * $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c,v 1.12 2005/04/25 18:43:14 darrenr Exp $
+ * $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c,v 1.15 2007/06/04 02:54:36 darrenr Exp $
*/
#define IPF_RCMD_PROXY
@@ -154,6 +154,8 @@
* other way.
*/
bcopy((char *)fin, (char *)&fi, sizeof(fi));
+ fi.fin_state = NULL;
+ fi.fin_nat = NULL;
fi.fin_flx |= FI_IGNORE;
fi.fin_data[0] = sp;
fi.fin_data[1] = 0;
@@ -203,9 +205,9 @@
fi.fin_fi.fi_daddr = nat->nat_inip.s_addr;
ip->ip_dst = nat->nat_inip;
}
- (void) fr_addstate(&fi, &nat2->nat_state, SI_W_DPORT);
+ (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;
Index: ip_proxy.h
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_proxy.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_proxy.h -L sys/contrib/ipfilter/netinet/ip_proxy.h -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_proxy.h
+++ sys/contrib/ipfilter/netinet/ip_proxy.h
@@ -1,11 +1,11 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_proxy.h,v 1.15 2005/04/27 03:48:10 darrenr Exp $ */
+/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_proxy.h,v 1.17 2007/06/04 02:54:35 darrenr Exp $ */
/*
* Copyright (C) 1997-2001 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
- * $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_proxy.h,v 1.15 2005/04/27 03:48:10 darrenr Exp $
+ * $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_proxy.h,v 1.17 2007/06/04 02:54:35 darrenr Exp $
* Id: ip_proxy.h,v 2.31.2.2 2005/03/12 19:33:48 darrenr Exp
*/
@@ -16,7 +16,7 @@
#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
#endif
-#if defined(__STDC__) || defined(__GNUC__)
+#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51)
#define SIOCPROXY _IOWR('r', 64, struct ap_control)
#else
#define SIOCPROXY _IOWR(r, 64, struct ap_control)
@@ -443,6 +443,7 @@
extern ap_session_t *ap_sess_list;
extern aproxy_t ap_proxies[];
extern int ippr_ftp_pasvonly;
+extern int ipf_proxy_debug;
extern int appr_add __P((aproxy_t *));
extern int appr_ctl __P((ap_ctl_t *));
@@ -456,6 +457,6 @@
extern int appr_check __P((fr_info_t *, struct nat *));
extern aproxy_t *appr_lookup __P((u_int, char *));
extern int appr_new __P((fr_info_t *, struct nat *));
-extern int appr_ioctl __P((caddr_t, ioctlcmd_t, int));
+extern int appr_ioctl __P((caddr_t, ioctlcmd_t, int, void *));
#endif /* __IP_PROXY_H__ */
Index: ip_htable.c
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_htable.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_htable.c -L sys/contrib/ipfilter/netinet/ip_htable.c -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_htable.c
+++ sys/contrib/ipfilter/netinet/ip_htable.c
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_htable.c,v 1.2 2005/06/23 14:19:02 darrenr Exp $ */
+/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_htable.c,v 1.4.2.1 2007/10/31 05:00:37 darrenr Exp $ */
/*
* Copyright (C) 1993-2001, 2003 by Darren Reed.
@@ -53,7 +53,7 @@
/* END OF INCLUDES */
#if !defined(lint)
-static const char rcsid[] = "@(#)Id: ip_htable.c,v 2.34.2.2 2004/10/17 15:49:15 darrenr Exp";
+static const char rcsid[] = "@(#)$Id: ip_htable.c,v 2.34.2.11 2007/09/20 12:51:51 darrenr Exp $";
#endif
#ifdef IPFILTER_LOOKUP
@@ -103,30 +103,34 @@
char name[FR_GROUPLEN];
int err, i, unit;
+ unit = op->iplo_unit;
+ if ((op->iplo_arg & IPHASH_ANON) == 0) {
+ iph = fr_existshtable(unit, op->iplo_name);
+ if (iph != NULL) {
+ if ((iph->iph_flags & IPHASH_DELETE) == 0)
+ return EEXIST;
+ iph->iph_flags &= ~IPHASH_DELETE;
+ return 0;
+ }
+ }
+
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;
}
- unit = op->iplo_unit;
if (iph->iph_unit != unit) {
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++;
@@ -141,12 +145,9 @@
sizeof(oiph->iph_name)) == 0)
break;
} while (oiph != NULL);
+
(void)strncpy(iph->iph_name, name, sizeof(iph->iph_name));
- err = COPYOUT(iph, op->iplo_struct, sizeof(*iph));
- if (err != 0) {
- KFREE(iph);
- return EFAULT;
- }
+ (void)strncpy(op->iplo_name, name, sizeof(op->iplo_name));
iph->iph_type |= IPHASH_ANON;
}
@@ -160,13 +161,14 @@
bzero((char *)iph->iph_table, iph->iph_size * sizeof(*iph->iph_table));
iph->iph_masks = 0;
+ iph->iph_list = NULL;
+ 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]++;
return 0;
@@ -175,22 +177,24 @@
/*
*/
-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);
@@ -199,40 +203,106 @@
}
-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;
{
@@ -245,6 +315,20 @@
}
+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;
{
@@ -257,8 +341,11 @@
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;
+ }
}
}
}
@@ -290,13 +377,20 @@
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;
@@ -314,44 +408,8 @@
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;
}
@@ -382,22 +440,22 @@
/* ------------------------------------------------------------------------ */
/* Function: fr_iphmfindip */
/* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */
-/* Parameters: tptr(I) - pointer to the pool to search */
-/* version(I) - IP protocol version (4 or 6) */
-/* aptr(I) - pointer to address information */
+/* Parameters: tptr(I) - pointer to the pool to search */
+/* ipversion(I) - IP protocol version (4 or 6) */
+/* aptr(I) - pointer to address information */
/* */
/* Search the hash table for a given address and return a search result. */
/* ------------------------------------------------------------------------ */
-int fr_iphmfindip(tptr, version, aptr)
+int fr_iphmfindip(tptr, ipversion, aptr)
void *tptr, *aptr;
-int version;
+int ipversion;
{
struct in_addr *addr;
iphtable_t *iph;
iphtent_t *ipe;
int rval;
- if (version != 4)
+ if (ipversion != 4)
return -1;
if (tptr == NULL || aptr == NULL)
@@ -431,7 +489,7 @@
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;
@@ -454,4 +512,131 @@
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);
+ token->ipt_data = nextiph;
+ } else {
+ bzero((char *)&zp, sizeof(zp));
+ nextiph = &zp;
+ token->ipt_data = NULL;
+ }
+ 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);
+ token->ipt_data = nextnode;
+ } else {
+ bzero((char *)&zn, sizeof(zn));
+ nextnode = &zn;
+ token->ipt_data = NULL;
+ }
+ 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);
+ }
+ 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);
+ }
+ 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 */
Index: ip_rpcb_pxy.c
===================================================================
RCS file: /home/cvs/src/sys/contrib/ipfilter/netinet/ip_rpcb_pxy.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/contrib/ipfilter/netinet/ip_rpcb_pxy.c -L sys/contrib/ipfilter/netinet/ip_rpcb_pxy.c -u -r1.1.1.1 -r1.2
--- sys/contrib/ipfilter/netinet/ip_rpcb_pxy.c
+++ sys/contrib/ipfilter/netinet/ip_rpcb_pxy.c
@@ -1,5 +1,3 @@
-/* $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_rpcb_pxy.c,v 1.1.1.1 2005/04/25 18:15:34 darrenr Exp $ */
-
/*
* Copyright (C) 2002-2003 by Ryan Beasley <ryanb at goddamnbastard.org>
*
@@ -39,7 +37,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.7 2007/06/04 09:16:31 darrenr Exp $
*/
#define IPF_RPCB_PROXY
@@ -292,6 +290,7 @@
/* Perform basic variable initialization. */
rs = (rpcb_session_t *)aps->aps_data;
+ rx = NULL;
m = fin->fin_m;
off = (char *)fin->fin_dp - (char *)fin->fin_ip;
@@ -309,6 +308,8 @@
COPYDATA(m, off, dlen, (caddr_t)&rm->rm_msgbuf);
rm->rm_buflen = dlen;
+ rx = NULL; /* XXX gcc */
+
/* Send off to decode reply. */
rv = ippr_rpcb_decoderep(fin, nat, rs, rm, &rx);
@@ -1158,6 +1159,8 @@
/* 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;
@@ -1193,8 +1196,9 @@
* no use for this lock, so simply unlock it if necessary.
*/
is = fr_stlookup(&fi, &tcp, NULL);
- if (is != NULL)
+ if (is != NULL) {
RWLOCK_EXIT(&ipf_state);
+ }
RWLOCK_EXIT(&ipf_nat);
@@ -1273,7 +1277,7 @@
return(-1);
}
if (fi.fin_state != NULL)
- fr_statederef(&fi, (ipstate_t **)&fi.fin_state);
+ fr_statederef((ipstate_t **)&fi.fin_state);
}
return(0);
More information about the Midnightbsd-cvs
mailing list