summaryrefslogtreecommitdiffstats
path: root/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/ipfilter/netinet/ip_fil_freebsd.c')
-rw-r--r--sys/contrib/ipfilter/netinet/ip_fil_freebsd.c248
1 files changed, 82 insertions, 166 deletions
diff --git a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c
index 64421e0..aeefb03 100644
--- a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c
+++ b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c
@@ -7,7 +7,7 @@
*/
#if !defined(lint)
static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)$Id: ip_fil_freebsd.c,v 2.53.2.32 2006/03/25 13:03:01 darrenr Exp $";
+static const char rcsid[] = "@(#)$Id: ip_fil_freebsd.c,v 2.53.2.46 2007/05/11 13:41:53 darrenr Exp $";
#endif
#if defined(KERNEL) || defined(_KERNEL)
@@ -57,11 +57,18 @@ static const char rcsid[] = "@(#)$Id: ip_fil_freebsd.c,v 2.53.2.32 2006/03/25 13
#endif
#include <sys/protosw.h>
#include <sys/socket.h>
-#include <sys/selinfo.h>
+#if __FreeBSD_version >= 500043
+# include <sys/selinfo.h>
+#else
+# include <sys/select.h>
+#endif
#include <net/if.h>
#if __FreeBSD_version >= 300000
# include <net/if_var.h>
+# if __FreeBSD_version >= 500043
+# include <net/netisr.h>
+# endif
# if !defined(IPFILTER_LKM)
# include "opt_ipfilter.h"
# endif
@@ -126,7 +133,7 @@ static int fr_send_ip __P((fr_info_t *, mb_t *, mb_t **));
# ifdef USE_MUTEXES
ipfmutex_t ipl_mutex, ipf_authmx, ipf_rw, ipf_stinsert;
ipfmutex_t ipf_nat_new, ipf_natio, ipf_timeoutlock;
-ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag, ipf_frcache;
+ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag, ipf_frcache, ipf_tokens;
ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth;
# endif
int ipf_locks_done = 0;
@@ -193,7 +200,7 @@ char *s;
#endif /* IPFILTER_LKM */
-int iplattach()
+int ipfattach()
{
#ifdef USE_SPL
int s;
@@ -215,11 +222,9 @@ int iplattach()
}
MUTEX_INIT(&ipf_rw, "ipf rw mutex");
- RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex");
MUTEX_INIT(&ipf_timeoutlock, "ipf timeout queue mutex");
- RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock");
- RWLOCK_INIT(&ipf_frcache, "ipf cache rwlock");
RWLOCK_INIT(&ipf_ipidfrag, "ipf IP NAT-Frag rwlock");
+ RWLOCK_INIT(&ipf_tokens, "ipf token rwlock");
ipf_locks_done = 1;
if (fr_initialise() < 0) {
@@ -326,7 +331,7 @@ pfil_error:
* Disable the filter by removing the hooks from the IP input/output
* stream.
*/
-int ipldetach()
+int ipfdetach()
{
#ifdef USE_SPL
int s;
@@ -420,10 +425,8 @@ int ipldetach()
if (ipf_locks_done == 1) {
MUTEX_DESTROY(&ipf_timeoutlock);
MUTEX_DESTROY(&ipf_rw);
- RW_DESTROY(&ipf_mutex);
- RW_DESTROY(&ipf_frcache);
RW_DESTROY(&ipf_ipidfrag);
- RW_DESTROY(&ipf_global);
+ RW_DESTROY(&ipf_tokens);
ipf_locks_done = 0;
}
@@ -441,8 +444,14 @@ int iplioctl(dev, cmd, data, mode
, p)
# if (__FreeBSD_version >= 500024)
struct thread *p;
+# if (__FreeBSD_version >= 500043)
+# define p_uid td_ucred->cr_ruid
+# else
+# define p_uid t_proc->p_cred->p_ruid
+# endif
# else
struct proc *p;
+# define p_uid p_cred->p_ruid
# endif /* __FreeBSD_version >= 500024 */
# else
)
@@ -456,11 +465,8 @@ ioctlcmd_t cmd;
caddr_t data;
int mode;
{
-#ifdef USE_SPL
- int s;
-#endif
- int error = 0, unit = 0, tmp;
- friostat_t fio;
+ int error = 0, unit = 0;
+ SPL_INT(s);
#if (BSD >= 199306) && defined(_KERNEL)
if ((securelevel >= 3) && (mode & FWRITE))
@@ -481,159 +487,16 @@ int mode;
}
SPL_NET(s);
- if (fr_running > 0)
- READ_ENTER(&ipf_global);
+ READ_ENTER(&ipf_global);
- error = fr_ioctlswitch(unit, data, cmd, mode);
+ error = fr_ioctlswitch(unit, data, cmd, mode, p->p_uid, p);
if (error != -1) {
RWLOCK_EXIT(&ipf_global);
SPL_X(s);
return error;
}
- error = 0;
-
- switch (cmd)
- {
- case FIONREAD :
-#ifdef IPFILTER_LOG
- BCOPYOUT(&iplused[IPL_LOGIPF], (caddr_t)data,
- sizeof(iplused[IPL_LOGIPF]));
-#endif
- break;
- case SIOCFRENB :
- if (!(mode & FWRITE))
- error = EPERM;
- else {
- BCOPYIN(data, &tmp, sizeof(tmp));
- if (tmp) {
- if (fr_running > 0)
- error = 0;
- else
- error = iplattach();
- if (error == 0)
- fr_running = 1;
- else
- (void) ipldetach();
- } else {
- if (fr_running <= 0)
- error = 0;
- else
- error = ipldetach();
- if (error == 0)
- fr_running = -1;
- }
- }
- break;
- case SIOCIPFSET :
- if (!(mode & FWRITE)) {
- error = EPERM;
- break;
- }
- case SIOCIPFGETNEXT :
- case SIOCIPFGET :
- error = fr_ipftune(cmd, data);
- break;
- case SIOCSETFF :
- if (!(mode & FWRITE))
- error = EPERM;
- else
- BCOPYIN(data, &fr_flags, sizeof(fr_flags));
- break;
- case SIOCGETFF :
- BCOPYOUT(&fr_flags, data, sizeof(fr_flags));
- break;
- case SIOCFUNCL :
- error = fr_resolvefunc(data);
- break;
- case SIOCINAFR :
- case SIOCRMAFR :
- case SIOCADAFR :
- case SIOCZRLST :
- if (!(mode & FWRITE))
- error = EPERM;
- else
- error = frrequest(unit, cmd, data, fr_active, 1);
- break;
- case SIOCINIFR :
- case SIOCRMIFR :
- case SIOCADIFR :
- if (!(mode & FWRITE))
- error = EPERM;
- else
- error = frrequest(unit, cmd, data, 1 - fr_active, 1);
- break;
- case SIOCSWAPA :
- if (!(mode & FWRITE))
- error = EPERM;
- else {
- bzero((char *)frcache, sizeof(frcache[0]) * 2);
- *(u_int *)data = fr_active;
- fr_active = 1 - fr_active;
- }
- break;
- case SIOCGETFS :
- fr_getstat(&fio);
- error = fr_outobj(data, &fio, IPFOBJ_IPFSTAT);
- break;
- case SIOCFRZST :
- if (!(mode & FWRITE))
- error = EPERM;
- else
- error = fr_zerostats(data);
- break;
- case SIOCIPFFL :
- if (!(mode & FWRITE))
- error = EPERM;
- else {
- BCOPYIN(data, &tmp, sizeof(tmp));
- tmp = frflush(unit, 4, tmp);
- BCOPYOUT(&tmp, data, sizeof(tmp));
- }
- break;
-#ifdef USE_INET6
- case SIOCIPFL6 :
- if (!(mode & FWRITE))
- error = EPERM;
- else {
- BCOPYIN(data, &tmp, sizeof(tmp));
- tmp = frflush(unit, 6, tmp);
- BCOPYOUT(&tmp, data, sizeof(tmp));
- }
- break;
-#endif
- case SIOCSTLCK :
- BCOPYIN(data, &tmp, sizeof(tmp));
- fr_state_lock = tmp;
- fr_nat_lock = tmp;
- fr_frag_lock = tmp;
- fr_auth_lock = tmp;
- break;
-#ifdef IPFILTER_LOG
- case SIOCIPFFB :
- if (!(mode & FWRITE))
- error = EPERM;
- else
- *(int *)data = ipflog_clear(unit);
- break;
-#endif /* IPFILTER_LOG */
- case SIOCGFRST :
- error = fr_outobj(data, fr_fragstats(), IPFOBJ_FRAGSTAT);
- break;
- case SIOCFRSYN :
- if (!(mode & FWRITE))
- error = EPERM;
- else {
- frsync(NULL);
- }
- break;
- default :
- error = EINVAL;
- break;
- }
- if (fr_running > 0)
- if (mtx_owned(&(&ipf_global)->ipf_lk))
- RWLOCK_EXIT(&ipf_global);
+ RWLOCK_EXIT(&ipf_global);
SPL_X(s);
return error;
@@ -760,6 +623,9 @@ register struct uio *uio;
{
u_int xmin = GET_MINOR(dev);
+ if (fr_running < 1)
+ return EIO;
+
if (xmin < 0)
return ENXIO;
@@ -796,6 +662,9 @@ dev_t dev;
register struct uio *uio;
{
+ if (fr_running < 1)
+ return EIO;
+
#ifdef IPFILTER_SYNC
if (GET_MINOR(dev) == IPL_LOGSYNC)
return ipfsync_write(uio);
@@ -1153,7 +1022,7 @@ void
# endif
iplinit()
{
- if (iplattach() != 0)
+ if (ipfattach() != 0)
printf("IP Filter failed to attach\n");
ip_init();
}
@@ -1264,9 +1133,11 @@ frdest_t *fdp;
/*
* For input packets which are being "fastrouted", they won't
* go back through output filtering and miss their chance to get
- * NAT'd and counted.
+ * NAT'd and counted. Duplicated packets aren't considered to be
+ * part of the normal packet stream, so do not NAT them or pass
+ * them through stateful checking, etc.
*/
- if (fin->fin_out == 0) {
+ if ((fdp != &fr->fr_dif) && (fin->fin_out == 0)) {
sifp = fin->fin_ifp;
fin->fin_ifp = ifp;
fin->fin_out = 1;
@@ -1275,7 +1146,8 @@ frdest_t *fdp;
if (!fr || !(fr->fr_flags & FR_RETMASK)) {
u_32_t pass;
- (void) fr_checkstate(fin, &pass);
+ if (fr_checkstate(fin, &pass) != NULL)
+ fr_statederef((ipstate_t **)&fin->fin_state);
}
switch (fr_checknatout(fin, NULL))
@@ -1283,6 +1155,7 @@ frdest_t *fdp;
case 0 :
break;
case 1 :
+ fr_natderef((nat_t **)&fin->fin_nat);
ip->ip_sum = 0;
break;
case -1 :
@@ -1742,3 +1615,46 @@ int len;
fin->fin_flx |= FI_COALESCE;
return ip;
}
+
+
+int ipf_inject(fin, m)
+fr_info_t *fin;
+mb_t *m;
+{
+ int error = 0;
+
+ if (fin->fin_out == 0) {
+#if (__FreeBSD_version >= 501000)
+ netisr_dispatch(NETISR_IP, m);
+#else
+ struct ifqueue *ifq;
+
+ ifq = &ipintrq;
+
+# ifdef _IF_QFULL
+ if (_IF_QFULL(ifq))
+# else
+ if (IF_QFULL(ifq))
+# endif
+ {
+# ifdef _IF_DROP
+ _IF_DROP(ifq);
+# else
+ IF_DROP(ifq);
+# endif
+ FREE_MB_T(m);
+ error = ENOBUFS;
+ } else {
+ IF_ENQUEUE(ifq, m);
+ }
+#endif
+ } else {
+#if (__FreeBSD_version >= 470102)
+ error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL);
+#else
+ error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL);
+#endif
+ }
+
+ return error;
+}
OpenPOWER on IntegriCloud