Merge the changes from 3.4.35 to 4.1.8 into the kernel source tree

This commit is contained in:
Darren Reed 2005-04-25 18:43:14 +00:00
parent 42559cd2af
commit 6eab6ed50f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=145522
20 changed files with 17527 additions and 9514 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,39 +1,49 @@
/* $FreeBSD$ */
/*
* Copyright (C) 1998-2001 by Darren Reed & Guido van Rooij.
* Copyright (C) 1998-2003 by Darren Reed & Guido van Rooij.
*
* See the IPFILTER.LICENCE file for details on licencing.
*/
#if defined(__sgi) && (IRIX > 602)
# include <sys/ptimers.h>
#if defined(KERNEL) || defined(_KERNEL)
# undef KERNEL
# undef _KERNEL
# define KERNEL 1
# define _KERNEL 1
#endif
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/file.h>
#if !defined(_KERNEL) && !defined(KERNEL)
#if !defined(_KERNEL)
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# define _KERNEL
# ifdef __OpenBSD__
struct file;
# endif
# include <sys/uio.h>
# undef _KERNEL
#endif
#if (defined(KERNEL) || defined(_KERNEL)) && (__FreeBSD_version >= 220000)
#if defined(_KERNEL) && (__FreeBSD_version >= 220000)
# include <sys/filio.h>
# include <sys/fcntl.h>
#else
# include <sys/ioctl.h>
#endif
#ifndef linux
#if !defined(linux)
# include <sys/protosw.h>
#endif
#include <sys/socket.h>
#if (defined(_KERNEL) || defined(KERNEL)) && !defined(linux)
#if defined(_KERNEL)
# include <sys/systm.h>
#endif
#if !defined(__SVR4) && !defined(__svr4__)
# ifndef linux
# if !defined(__SVR4) && !defined(__svr4__) && !defined(linux)
# include <sys/mbuf.h>
# endif
#else
#endif
#if defined(__SVR4) || defined(__svr4__)
# include <sys/filio.h>
# include <sys/byteorder.h>
# ifdef _KERNEL
@ -48,6 +58,9 @@
#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(bsdi)
# include <machine/cpu.h>
#endif
#if defined(_KERNEL) && defined(__NetBSD__) && (__NetBSD_Version__ >= 104000000)
# include <sys/proc.h>
#endif
#include <net/if.h>
#ifdef sun
# include <net/af.h>
@ -56,28 +69,29 @@
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#ifndef KERNEL
#if !defined(_KERNEL) && !defined(__osf__) && !defined(__sgi)
# define KERNEL
# define _KERNEL
# define NOT_KERNEL
#endif
#ifndef linux
#if !defined(linux)
# include <netinet/ip_var.h>
#endif
#ifdef NOT_KERNEL
# undef _KERNEL
# undef KERNEL
#endif
#ifdef __sgi
# ifdef IFF_DRVRLOCK /* IRIX6 */
# include <sys/hashing.h>
# endif
#endif
#include <netinet/tcp.h>
#if defined(__sgi) && !defined(IFF_DRVRLOCK) /* IRIX < 6 */
#if defined(IRIX) && (IRIX < 60516) /* IRIX < 6 */
extern struct ifqueue ipintrq; /* ip packet input queue */
#else
# ifndef linux
# if !defined(__hpux) && !defined(linux)
# if __FreeBSD_version >= 300000
# include <net/if_var.h>
# if __FreeBSD_version >= 500042
# define IF_QFULL _IF_QFULL
# define IF_DROP _IF_DROP
# endif /* __FreeBSD_version >= 500042 */
# endif
# include <netinet/in_var.h>
# include <netinet/tcp_fsm.h>
@ -89,7 +103,7 @@ extern struct ifqueue ipintrq; /* ip packet input queue */
#include <netinet/tcpip.h>
#include "netinet/ip_fil.h"
#include "netinet/ip_auth.h"
#if !SOLARIS && !defined(linux)
#if !defined(MENTAT) && !defined(linux)
# include <net/netisr.h>
# ifdef __FreeBSD__
# include <machine/cpufunc.h>
@ -97,59 +111,90 @@ extern struct ifqueue ipintrq; /* ip packet input queue */
#endif
#if (__FreeBSD_version >= 300000)
# include <sys/malloc.h>
# if (defined(_KERNEL) || defined(KERNEL)) && !defined(IPFILTER_LKM)
# if defined(_KERNEL) && !defined(IPFILTER_LKM)
# include <sys/libkern.h>
# include <sys/systm.h>
# endif
#endif
/* END OF INCLUDES */
#if !defined(lint)
/* static const char rcsid[] = "@(#)$Id: ip_auth.c,v 2.11.2.12 2001/07/18 14:57:08 darrenr Exp $"; */
static const char rcsid[] = "@(#)$FreeBSD$";
static const char rcsid[] = "@(#)Id: ip_auth.c,v 2.73.2.3 2004/08/26 11:25:21 darrenr Exp";
#endif
#ifdef USE_MUTEX
extern KRWLOCK_T ipf_auth, ipf_mutex;
extern kmutex_t ipf_authmx;
# if SOLARIS
#if SOLARIS
extern kcondvar_t ipfauthwait;
# endif
#endif
#ifdef linux
static struct wait_queue *ipfauthwait = NULL;
#endif /* SOLARIS */
#if defined(linux) && defined(_KERNEL)
wait_queue_head_t fr_authnext_linux;
#endif
int fr_authsize = FR_NUMAUTH;
int fr_authused = 0;
int fr_defaultauthage = 600;
int fr_auth_lock = 0;
int fr_auth_init = 0;
fr_authstat_t fr_authstats;
static frauth_t fr_auth[FR_NUMAUTH];
mb_t *fr_authpkts[FR_NUMAUTH];
static int fr_authstart = 0, fr_authend = 0, fr_authnext = 0;
static frauthent_t *fae_list = NULL;
static frauth_t *fr_auth = NULL;
mb_t **fr_authpkts = NULL;
int fr_authstart = 0, fr_authend = 0, fr_authnext = 0;
frauthent_t *fae_list = NULL;
frentry_t *ipauth = NULL,
*fr_authlist = NULL;
int fr_authinit()
{
KMALLOCS(fr_auth, frauth_t *, fr_authsize * sizeof(*fr_auth));
if (fr_auth != NULL)
bzero((char *)fr_auth, fr_authsize * sizeof(*fr_auth));
else
return -1;
KMALLOCS(fr_authpkts, mb_t **, fr_authsize * sizeof(*fr_authpkts));
if (fr_authpkts != NULL)
bzero((char *)fr_authpkts, fr_authsize * sizeof(*fr_authpkts));
else
return -2;
MUTEX_INIT(&ipf_authmx, "ipf auth log mutex");
RWLOCK_INIT(&ipf_auth, "ipf IP User-Auth rwlock");
#if SOLARIS && defined(_KERNEL)
cv_init(&ipfauthwait, "ipf auth condvar", CV_DRIVER, NULL);
#endif
#if defined(linux) && defined(_KERNEL)
init_waitqueue_head(&fr_authnext_linux);
#endif
fr_auth_init = 1;
return 0;
}
/*
* Check if a packet has authorization. If the packet is found to match an
* authorization result and that would result in a feedback loop (i.e. it
* will end up returning FR_AUTH) then return FR_BLOCK instead.
*/
u_32_t fr_checkauth(ip, fin)
ip_t *ip;
frentry_t *fr_checkauth(fin, passp)
fr_info_t *fin;
u_32_t *passp;
{
u_short id = ip->ip_id;
frentry_t *fr;
frauth_t *fra;
u_32_t pass;
u_short id;
ip_t *ip;
int i;
if (fr_auth_lock || !fr_authused)
return 0;
return NULL;
ip = fin->fin_ip;
id = ip->ip_id;
READ_ENTER(&ipf_auth);
for (i = fr_authstart; i != fr_authend; ) {
@ -164,7 +209,7 @@ fr_info_t *fin;
/*
* Avoid feedback loop.
*/
if (!(pass = fra->fra_pass) || (pass & FR_AUTH))
if (!(pass = fra->fra_pass) || (FR_ISAUTH(pass)))
pass = FR_BLOCK;
/*
* Create a dummy rule for the stateful checking to
@ -172,26 +217,26 @@ fr_info_t *fin;
* trust from userland!
*/
if ((pass & FR_KEEPSTATE) || ((pass & FR_KEEPFRAG) &&
(fin->fin_fi.fi_fl & FI_FRAG))) {
(fin->fin_flx & FI_FRAG))) {
KMALLOC(fr, frentry_t *);
if (fr) {
bcopy((char *)fra->fra_info.fin_fr,
fr, sizeof(*fr));
(char *)fr, sizeof(*fr));
fr->fr_grp = NULL;
fr->fr_ifa = fin->fin_ifp;
fr->fr_func = NULL;
fr->fr_ref = 1;
fr->fr_flags = pass;
#if BSD >= 199306
fr->fr_oifa = NULL;
#endif
fr->fr_ifas[1] = NULL;
fr->fr_ifas[2] = NULL;
fr->fr_ifas[3] = NULL;
}
} else
fr = fra->fra_info.fin_fr;
fin->fin_fr = fr;
RWLOCK_EXIT(&ipf_auth);
WRITE_ENTER(&ipf_auth);
if (fr && fr != fra->fra_info.fin_fr) {
if ((fr != NULL) && (fr != fra->fra_info.fin_fr)) {
fr->fr_next = fr_authlist;
fr_authlist = fr;
}
@ -202,7 +247,7 @@ fr_info_t *fin;
while (fra->fra_index == -1) {
i++;
fra++;
if (i == FR_NUMAUTH) {
if (i == fr_authsize) {
i = 0;
fra = fr_auth;
}
@ -216,15 +261,19 @@ fr_info_t *fin;
}
}
RWLOCK_EXIT(&ipf_auth);
return pass;
if (passp != NULL)
*passp = pass;
ATOMIC_INC64(fr_authstats.fas_hits);
return fr;
}
i++;
if (i == FR_NUMAUTH)
if (i == fr_authsize)
i = 0;
}
fr_authstats.fas_miss++;
RWLOCK_EXIT(&ipf_auth);
return 0;
ATOMIC_INC64(fr_authstats.fas_miss);
return NULL;
}
@ -233,15 +282,17 @@ fr_info_t *fin;
* If we do, store it and wake up any user programs which are waiting to
* hear about these events.
*/
int fr_newauth(m, fin, ip)
int fr_newauth(m, fin)
mb_t *m;
fr_info_t *fin;
ip_t *ip;
{
#if defined(_KERNEL) && SOLARIS
qif_t *qif = fin->fin_qif;
#if defined(_KERNEL) && defined(MENTAT)
qpktinfo_t *qpi = fin->fin_qpi;
#endif
frauth_t *fra;
#if !defined(sparc) && !defined(m68k)
ip_t *ip;
#endif
int i;
if (fr_auth_lock)
@ -253,7 +304,7 @@ ip_t *ip;
RWLOCK_EXIT(&ipf_auth);
return 0;
} else {
if (fr_authused == FR_NUMAUTH) {
if (fr_authused == fr_authsize) {
fr_authstats.fas_nospace++;
RWLOCK_EXIT(&ipf_auth);
return 0;
@ -263,21 +314,24 @@ ip_t *ip;
fr_authstats.fas_added++;
fr_authused++;
i = fr_authend++;
if (fr_authend == FR_NUMAUTH)
if (fr_authend == fr_authsize)
fr_authend = 0;
RWLOCK_EXIT(&ipf_auth);
fra = fr_auth + i;
fra->fra_index = i;
fra->fra_pass = 0;
fra->fra_age = fr_defaultauthage;
bcopy((char *)fin, (char *)&fra->fra_info, sizeof(*fin));
#if SOLARIS && defined(_KERNEL)
# if !defined(sparc)
#if !defined(sparc) && !defined(m68k)
/*
* No need to copyback here as we want to undo the changes, not keep
* them.
*/
if ((ip == (ip_t *)m->b_rptr) && (ip->ip_v == 4))
ip = fin->fin_ip;
# if defined(MENTAT) && defined(_KERNEL)
if ((ip == (ip_t *)m->b_rptr) && (fin->fin_v == 4))
# endif
{
register u_short bo;
@ -286,43 +340,42 @@ ip_t *ip;
bo = ip->ip_off;
ip->ip_off = htons(bo);
}
# endif
m->b_rptr -= qif->qf_off;
#endif
#if SOLARIS && defined(_KERNEL)
m->b_rptr -= qpi->qpi_off;
fr_authpkts[i] = *(mblk_t **)fin->fin_mp;
fra->fra_q = qif->qf_q;
fra->fra_q = qpi->qpi_q; /* The queue can disappear! */
cv_signal(&ipfauthwait);
#else
# if defined(BSD) && !defined(sparc) && (BSD >= 199306)
if (fin->fin_out == 0) {
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);
WAKEUP(&fr_authnext,0);
#endif
return 1;
}
int fr_auth_ioctl(data, mode, cmd)
int fr_auth_ioctl(data, cmd, mode)
caddr_t data;
ioctlcmd_t cmd;
int mode;
#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003)
u_long cmd;
#else
int cmd;
#endif
{
mb_t *m;
#if defined(_KERNEL) && !SOLARIS
# if !defined(__FreeBSD_version) || (__FreeBSD_version < 501104)
#if defined(_KERNEL) && !defined(MENTAT) && !defined(linux) && \
(!defined(__FreeBSD_version) || (__FreeBSD_version < 501000))
struct ifqueue *ifq;
# endif
# ifdef USE_SPL
int s;
# endif /* USE_SPL */
#endif
frauth_t auth, *au = &auth, *fra;
int i, error = 0;
int i, error = 0, len;
char *t;
switch (cmd)
{
@ -331,81 +384,119 @@ int cmd;
error = EPERM;
break;
}
error = fr_lock(data, &fr_auth_lock);
break;
case SIOCINIFR :
case SIOCRMIFR :
case SIOCADIFR :
error = EINVAL;
break;
case SIOCINAFR :
error = EINVAL;
break;
case SIOCRMAFR :
case SIOCADAFR :
/* These commands go via request to fr_preauthcmd */
error = EINVAL;
fr_lock(data, &fr_auth_lock);
break;
case SIOCATHST:
fr_authstats.fas_faelist = fae_list;
error = IWCOPYPTR((char *)&fr_authstats, data,
sizeof(fr_authstats));
error = fr_outobj(data, &fr_authstats, IPFOBJ_AUTHSTAT);
break;
case SIOCIPFFL:
SPL_NET(s);
WRITE_ENTER(&ipf_auth);
i = fr_authflush();
RWLOCK_EXIT(&ipf_auth);
SPL_X(s);
error = copyoutptr((char *)&i, data, sizeof(i));
break;
case SIOCAUTHW:
if (!(mode & FWRITE)) {
error = EPERM;
break;
}
fr_authioctlloop:
error = fr_inobj(data, au, IPFOBJ_FRAUTH);
READ_ENTER(&ipf_auth);
if ((fr_authnext != fr_authend) && fr_authpkts[fr_authnext]) {
error = IWCOPYPTR((char *)&fr_auth[fr_authnext], data,
sizeof(frauth_t));
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)
if (error != 0)
break;
WRITE_ENTER(&ipf_auth);
SPL_NET(s);
WRITE_ENTER(&ipf_auth);
fr_authnext++;
if (fr_authnext == FR_NUMAUTH)
if (fr_authnext == fr_authsize)
fr_authnext = 0;
SPL_X(s);
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
mutex_enter(&ipf_authmx);
if (!cv_wait_sig(&ipfauthwait, &ipf_authmx)) {
mutex_exit(&ipf_authmx);
return EINTR;
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);
}
mutex_exit(&ipf_authmx);
# else
# 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
# endif /* __osf__ */
# endif /* __hpux */
# endif /* SOLARIS */
#endif
if (!error)
MUTEX_EXIT(&ipf_authmx);
READ_ENTER(&ipf_global);
if (error == 0) {
READ_ENTER(&ipf_auth);
goto fr_authioctlloop;
break;
case SIOCAUTHR:
if (!(mode & FWRITE)) {
error = EPERM;
break;
}
error = IRCOPYPTR(data, (caddr_t)&auth, sizeof(auth));
if (error)
break;
case SIOCAUTHR:
error = fr_inobj(data, &auth, IPFOBJ_FRAUTH);
if (error != 0)
return error;
WRITE_ENTER(&ipf_auth);
SPL_NET(s);
WRITE_ENTER(&ipf_auth);
i = au->fra_index;
fra = fr_auth + i;
if ((i < 0) || (i > FR_NUMAUTH) ||
if ((i < 0) || (i >= fr_authsize) ||
(fra->fra_info.fin_id != au->fra_info.fin_id)) {
SPL_X(s);
RWLOCK_EXIT(&ipf_auth);
return EINVAL;
SPL_X(s);
return ESRCH;
}
m = fr_authpkts[i];
fra->fra_index = -2;
@ -413,50 +504,67 @@ int cmd;
fr_authpkts[i] = NULL;
RWLOCK_EXIT(&ipf_auth);
#ifdef _KERNEL
if (m && au->fra_info.fin_out) {
# if SOLARIS
error = (fr_qout(fra->fra_q, m) == 0) ? EINVAL : 0;
# else /* SOLARIS */
struct route ro;
bzero((char *)&ro, sizeof(ro));
# if ((_BSDI_VERSION >= 199802) && (_BSDI_VERSION < 200005)) || \
defined(__OpenBSD__) || (defined(IRIX) && (IRIX >= 605)) || \
(__FreeBSD_version >= 470102)
error = ip_output(m, NULL, &ro, IP_FORWARDING, NULL,
NULL);
if ((m != NULL) && (au->fra_info.fin_out != 0)) {
# ifdef MENTAT
error = !putq(fra->fra_q, m);
# else /* MENTAT */
# ifdef linux
# else
error = ip_output(m, NULL, &ro, IP_FORWARDING, NULL);
# endif
if (ro.ro_rt) {
RTFREE(ro.ro_rt);
}
# endif /* SOLARIS */
if (error)
# 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) {
# if SOLARIS
error = (fr_qin(fra->fra_q, m) == 0) ? EINVAL : 0;
# else /* SOLARIS */
if (! netisr_queue(NETISR_IP, 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;
# endif /* SOLARIS */
if (error)
} else {
IF_ENQUEUE(ifq, m);
# if IRIX < 60500
schednetisr(NETISR_IP);
# endif
}
# endif
# endif /* Linux */
# endif /* MENTAT */
if (error != 0)
fr_authstats.fas_quefail++;
else
fr_authstats.fas_queok++;
} else
error = EINVAL;
# if SOLARIS
if (error)
# ifdef MENTAT
if (error != 0)
error = EINVAL;
# else
# 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;
@ -464,7 +572,7 @@ int cmd;
if (i == fr_authstart) {
while (fra->fra_index == -1) {
i++;
if (i == FR_NUMAUTH)
if (i == fr_authsize)
i = 0;
fr_authstart = i;
if (i == fr_authend)
@ -476,10 +584,11 @@ int cmd;
}
}
}
# endif
# endif /* MENTAT */
#endif /* _KERNEL */
SPL_X(s);
break;
default :
error = EINVAL;
break;
@ -498,41 +607,48 @@ void fr_authunload()
frentry_t *fr, **frp;
mb_t *m;
WRITE_ENTER(&ipf_auth);
for (i = 0; i < FR_NUMAUTH; i++) {
if ((m = fr_authpkts[i])) {
FREE_MB_T(m);
fr_authpkts[i] = NULL;
fr_auth[i].fra_index = -1;
}
if (fr_auth != NULL) {
KFREES(fr_auth, fr_authsize * sizeof(*fr_auth));
fr_auth = NULL;
}
if (fr_authpkts != NULL) {
for (i = 0; i < fr_authsize; i++) {
m = fr_authpkts[i];
if (m != NULL) {
FREE_MB_T(m);
fr_authpkts[i] = NULL;
}
}
KFREES(fr_authpkts, fr_authsize * sizeof(*fr_authpkts));
fr_authpkts = NULL;
}
for (faep = &fae_list; (fae = *faep); ) {
faep = &fae_list;
while ((fae = *faep) != NULL) {
*faep = fae->fae_next;
KFREE(fae);
}
ipauth = NULL;
RWLOCK_EXIT(&ipf_auth);
if (fr_authlist) {
/*
* We *MuST* reget ipf_auth because otherwise we won't get the
* locks in the right order and risk deadlock.
* We need ipf_mutex here to prevent a rule from using it
* inside fr_check().
*/
WRITE_ENTER(&ipf_mutex);
WRITE_ENTER(&ipf_auth);
for (frp = &fr_authlist; (fr = *frp); ) {
if (fr_authlist != NULL) {
for (frp = &fr_authlist; ((fr = *frp) != NULL); ) {
if (fr->fr_ref == 1) {
*frp = fr->fr_next;
KFREE(fr);
} else
frp = &fr->fr_next;
}
RWLOCK_EXIT(&ipf_auth);
RWLOCK_EXIT(&ipf_mutex);
}
if (fr_auth_init == 1) {
# if SOLARIS && defined(_KERNEL)
cv_destroy(&ipfauthwait);
# endif
MUTEX_DESTROY(&ipf_authmx);
RW_DESTROY(&ipf_auth);
fr_auth_init = 0;
}
}
@ -548,17 +664,18 @@ void fr_authexpire()
register frauthent_t *fae, **faep;
register frentry_t *fr, **frp;
mb_t *m;
#if !SOLARIS && defined(_KERNEL)
# if !defined(MENAT) && defined(_KERNEL) && defined(USE_SPL)
int s;
#endif
# endif
if (fr_auth_lock)
return;
SPL_NET(s);
WRITE_ENTER(&ipf_auth);
for (i = 0, fra = fr_auth; i < FR_NUMAUTH; i++, fra++) {
if ((!--fra->fra_age) && (m = fr_authpkts[i])) {
for (i = 0, fra = fr_auth; i < fr_authsize; i++, fra++) {
fra->fra_age--;
if ((fra->fra_age == 0) && (m = fr_authpkts[i])) {
FREE_MB_T(m);
fr_authpkts[i] = NULL;
fr_auth[i].fra_index = -1;
@ -567,8 +684,9 @@ void fr_authexpire()
}
}
for (faep = &fae_list; (fae = *faep); ) {
if (!--fae->fae_age) {
for (faep = &fae_list; ((fae = *faep) != NULL); ) {
fae->fae_age--;
if (fae->fae_age == 0) {
*faep = fae->fae_next;
KFREE(fae);
fr_authstats.fas_expire++;
@ -580,7 +698,7 @@ void fr_authexpire()
else
ipauth = NULL;
for (frp = &fr_authlist; (fr = *frp); ) {
for (frp = &fr_authlist; ((fr = *frp) != NULL); ) {
if (fr->fr_ref == 1) {
*frp = fr->fr_next;
KFREE(fr);
@ -592,52 +710,48 @@ void fr_authexpire()
}
int fr_preauthcmd(cmd, fr, frptr)
#if defined(__NetBSD__) || defined(__OpenBSD__) || \
(_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000)
u_long cmd;
#else
int cmd;
#endif
ioctlcmd_t cmd;
frentry_t *fr, **frptr;
{
frauthent_t *fae, **faep;
int error = 0;
#if defined(KERNEL) && !SOLARIS
# if !defined(MENAT) && defined(_KERNEL) && defined(USE_SPL)
int s;
#endif
if ((cmd != SIOCADAFR) && (cmd != SIOCRMAFR)) {
/* Should not happen */
printf("fr_preauthcmd called with bad cmd 0x%lx", (u_long)cmd);
if ((cmd != SIOCADAFR) && (cmd != SIOCRMAFR))
return EIO;
}
for (faep = &fae_list; (fae = *faep); )
for (faep = &fae_list; ((fae = *faep) != NULL); ) {
if (&fae->fae_fr == fr)
break;
else
faep = &fae->fae_next;
if (cmd == SIOCRMAFR) {
if (!fr || !frptr)
}
if (cmd == (ioctlcmd_t)SIOCRMAFR) {
if (fr == NULL || frptr == NULL)
error = EINVAL;
else if (!fae)
else if (fae == NULL)
error = ESRCH;
else {
WRITE_ENTER(&ipf_auth);
SPL_NET(s);
WRITE_ENTER(&ipf_auth);
*faep = fae->fae_next;
*frptr = fr->fr_next;
SPL_X(s);
if (ipauth == &fae->fae_fr)
ipauth = fae_list ? &fae_list->fae_fr : NULL;
RWLOCK_EXIT(&ipf_auth);
SPL_X(s);
KFREE(fae);
}
} else if (fr && frptr) {
} else if (fr != NULL && frptr != NULL) {
KMALLOC(fae, frauthent_t *);
if (fae != NULL) {
bcopy((char *)fr, (char *)&fae->fae_fr,
sizeof(*fr));
WRITE_ENTER(&ipf_auth);
SPL_NET(s);
WRITE_ENTER(&ipf_auth);
fae->fae_age = fr_defaultauthage;
fae->fae_fr.fr_hits = 0;
fae->fae_fr.fr_next = *frptr;
@ -645,11 +759,47 @@ frentry_t *fr, **frptr;
fae->fae_next = *faep;
*faep = fae;
ipauth = &fae_list->fae_fr;
SPL_X(s);
RWLOCK_EXIT(&ipf_auth);
SPL_X(s);
} else
error = ENOMEM;
} else
error = EINVAL;
return error;
}
/*
* Flush held packets.
* Must already be properly SPL'ed and Locked on &ipf_auth.
*
*/
int fr_authflush()
{
register int i, num_flushed;
mb_t *m;
if (fr_auth_lock)
return -1;
num_flushed = 0;
for (i = 0 ; i < fr_authsize; i++) {
m = fr_authpkts[i];
if (m != NULL) {
FREE_MB_T(m);
fr_authpkts[i] = NULL;
fr_auth[i].fra_index = -1;
/* perhaps add & use a flush counter inst.*/
fr_authstats.fas_expire++;
fr_authused--;
num_flushed++;
}
}
fr_authstart = 0;
fr_authend = 0;
fr_authnext = 0;
return num_flushed;
}

View File

@ -1,9 +1,12 @@
/* $FreeBSD$ */
/*
* Copyright (C) 1997-2001 by Darren Reed & Guido Van Rooij.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* $FreeBSD$
* Id: ip_auth.h,v 2.16 2003/07/25 12:29:56 darrenr Exp
*
*/
#ifndef __IP_AUTH_H__
@ -13,10 +16,12 @@
typedef struct frauth {
int fra_age;
int fra_len;
int fra_index;
u_32_t fra_pass;
fr_info_t fra_info;
#if SOLARIS
char *fra_buf;
#ifdef MENTAT
queue_t *fra_q;
#endif
} frauth_t;
@ -44,20 +49,19 @@ typedef struct fr_authstat {
extern frentry_t *ipauth;
extern struct fr_authstat fr_authstats;
extern int fr_defaultauthage;
extern int fr_authstart;
extern int fr_authend;
extern int fr_authsize;
extern int fr_authused;
extern int fr_auth_lock;
extern u_32_t fr_checkauth __P((ip_t *, fr_info_t *));
extern frentry_t *fr_checkauth __P((fr_info_t *, u_32_t *));
extern void fr_authexpire __P((void));
extern int fr_authinit __P((void));
extern void fr_authunload __P((void));
extern mb_t *fr_authpkts[];
extern int fr_newauth __P((mb_t *, fr_info_t *, ip_t *));
#if defined(__NetBSD__) || defined(__OpenBSD__) || \
(__FreeBSD_version >= 300003)
extern int fr_preauthcmd __P((u_long, frentry_t *, frentry_t **));
extern int fr_auth_ioctl __P((caddr_t, int, u_long));
#else
extern int fr_preauthcmd __P((int, frentry_t *, frentry_t **));
extern int fr_auth_ioctl __P((caddr_t, int, int));
#endif
extern int fr_authflush __P((void));
extern mb_t **fr_authpkts;
extern int fr_newauth __P((mb_t *, fr_info_t *));
extern int fr_preauthcmd __P((ioctlcmd_t, frentry_t *, frentry_t **));
extern int fr_auth_ioctl __P((caddr_t, ioctlcmd_t, int));
#endif /* __IP_AUTH_H__ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,13 @@
/* $FreeBSD$ */
/*
* Copyright (C) 1993-2001 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* @(#)ip_frag.h 1.5 3/24/96
* $Id: ip_frag.h,v 2.4.2.2 2000/11/10 13:10:54 darrenr Exp $
* $FreeBSD$
* Id: ip_frag.h,v 2.23.2.1 2004/03/29 16:21:56 darrenr Exp
*/
#ifndef __IP_FRAG_H__
@ -14,17 +16,19 @@
#define IPFT_SIZE 257
typedef struct ipfr {
struct ipfr *ipfr_next, *ipfr_prev;
struct ipfr *ipfr_hnext, **ipfr_hprev;
struct ipfr *ipfr_next, **ipfr_prev;
void *ipfr_data;
void *ipfr_ifp;
struct in_addr ipfr_src;
struct in_addr ipfr_dst;
void *ipfr_ifp;
u_32_t ipfr_optmsk;
u_short ipfr_secmsk;
u_short ipfr_auth;
u_short ipfr_id;
u_char ipfr_p;
u_char ipfr_tos;
u_32_t ipfr_pass;
u_short ipfr_off;
u_char ipfr_ttl;
u_char ipfr_seen0;
@ -39,37 +43,45 @@ typedef struct ipfrstat {
u_long ifs_hits;
u_long ifs_expire;
u_long ifs_inuse;
u_long ifs_retrans0;
u_long ifs_short;
struct ipfr **ifs_table;
struct ipfr **ifs_nattab;
} ipfrstat_t;
#define IPFR_CMPSZ (offsetof(ipfr_t, ipfr_off) - \
offsetof(ipfr_t, ipfr_src))
#define IPFR_CMPSZ (offsetof(ipfr_t, ipfr_pass) - \
offsetof(ipfr_t, ipfr_ifp))
extern int ipfr_size;
extern int fr_ipfrttl;
extern int fr_frag_lock;
extern ipfrstat_t *ipfr_fragstats __P((void));
extern int ipfr_newfrag __P((ip_t *, fr_info_t *));
extern int ipfr_nat_newfrag __P((ip_t *, fr_info_t *, struct nat *));
extern nat_t *ipfr_nat_knownfrag __P((ip_t *, fr_info_t *));
extern frentry_t *ipfr_knownfrag __P((ip_t *, fr_info_t *));
extern void ipfr_forget __P((void *));
extern void ipfr_forgetnat __P((void *));
extern void ipfr_unload __P((void));
extern void ipfr_fragexpire __P((void));
extern int fr_fraginit __P((void));
extern void fr_fragunload __P((void));
extern ipfrstat_t *fr_fragstats __P((void));
#ifdef _KERNEL
# if (BSD >= 199306) || SOLARIS || defined(__sgi)
# if defined(SOLARIS2) && (SOLARIS2 < 7)
extern void ipfr_slowtimer __P((void));
# else
extern void ipfr_slowtimer __P((void *));
# endif
extern int fr_newfrag __P((fr_info_t *, u_32_t));
extern frentry_t *fr_knownfrag __P((fr_info_t *, u_32_t *));
extern int fr_nat_newfrag __P((fr_info_t *, u_32_t, struct nat *));
extern nat_t *fr_nat_knownfrag __P((fr_info_t *));
extern int fr_ipid_newfrag __P((fr_info_t *, u_32_t));
extern u_32_t fr_ipid_knownfrag __P((fr_info_t *));
extern void fr_forget __P((void *));
extern void fr_forgetnat __P((void *));
extern void fr_fragclear __P((void));
extern void fr_fragexpire __P((void));
#if defined(_KERNEL) && ((BSD >= 199306) || SOLARIS || defined(__sgi) \
|| defined(__osf__) || (defined(__sgi) && (IRIX >= 60500)))
# if defined(SOLARIS2) && (SOLARIS2 < 7)
extern void fr_slowtimer __P((void));
# else
extern int ipfr_slowtimer __P((void));
# endif /* (BSD >= 199306) || SOLARIS */
extern void fr_slowtimer __P((void *));
# endif
#else
extern void ipfr_slowtimer __P((void));
#endif /* _KERNEL */
extern int fr_slowtimer __P((void));
#endif
#endif /* __IP_FIL_H__ */
#endif /* __IP_FRAG_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,150 +1,178 @@
/* $FreeBSD$ */
/*
* Copyright (C) 1997-2001 by Darren Reed.
* Copyright (C) 1997-2003 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* $Id: ip_log.c,v 2.5.2.1 2000/07/19 13:11:47 darrenr Exp $
* $FreeBSD$
* Id: ip_log.c,v 2.75.2.6 2004/10/16 07:59:27 darrenr Exp
*/
#include <sys/param.h>
#if defined(KERNEL) && !defined(_KERNEL)
# define _KERNEL
#if defined(KERNEL) || defined(_KERNEL)
# undef KERNEL
# undef _KERNEL
# define KERNEL 1
# define _KERNEL 1
#endif
#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \
defined(_KERNEL)
# include "opt_ipfilter_log.h"
#endif
#ifdef __FreeBSD__
# if defined(IPFILTER_LKM) || defined(_KERNEL)
# if !defined(__FreeBSD_version)
# include <sys/osreldate.h>
# endif
# if !defined(IPFILTER_LKM)
# if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
# include "opt_ipfilter.h"
# endif
#if defined(__FreeBSD__) && !defined(IPFILTER_LKM)
# if defined(_KERNEL)
# if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
# include "opt_ipfilter.h"
# endif
# else
# ifdef KLD_MODULE
# ifndef __FreeBSD_cc_version
# include <osreldate.h>
# else
# if __FreeBSD_cc_version < 430000
# include <osreldate.h>
# endif
# endif
# endif
# include <osreldate.h>
# endif
#endif
#ifdef IPFILTER_LOG
# ifndef SOLARIS
# define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
#ifndef SOLARIS
# define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
#endif
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/file.h>
#ifndef _KERNEL
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# include <ctype.h>
# define _KERNEL
# define KERNEL
# ifdef __OpenBSD__
struct file;
# endif
# ifndef _KERNEL
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# include <ctype.h>
# include <sys/uio.h>
# undef _KERNEL
# undef KERNEL
#endif
#if __FreeBSD_version >= 220000 && defined(_KERNEL)
# include <sys/fcntl.h>
# include <sys/filio.h>
#else
# include <sys/ioctl.h>
#endif
#include <sys/time.h>
#if defined(_KERNEL)
# include <sys/systm.h>
# if defined(NetBSD) && (__NetBSD_Version__ >= 104000000)
# include <sys/proc.h>
# endif
# include <sys/errno.h>
# include <sys/types.h>
# include <sys/file.h>
# if __FreeBSD_version >= 220000 && defined(_KERNEL)
# include <sys/fcntl.h>
# include <sys/filio.h>
#endif /* _KERNEL */
#if !SOLARIS && !defined(__hpux) && !defined(linux)
# if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000)
# include <sys/dirent.h>
# else
# include <sys/ioctl.h>
# include <sys/dir.h>
# endif
# include <sys/time.h>
# if defined(_KERNEL)
# include <sys/systm.h>
# endif
# if !SOLARIS
# if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000)
# include <sys/dirent.h>
# else
# include <sys/dir.h>
# endif
# include <sys/mbuf.h>
# else
# include <sys/mbuf.h>
#else
# if !defined(__hpux) && defined(_KERNEL)
# include <sys/filio.h>
# include <sys/cred.h>
# include <sys/kmem.h>
# ifdef _KERNEL
# include <sys/ddi.h>
# include <sys/sunddi.h>
# include <sys/ksynch.h>
# include <sys/dditypes.h>
# include <sys/cmn_err.h>
# endif
# endif
# include <sys/protosw.h>
# include <sys/socket.h>
# include <net/if.h>
# ifdef sun
# include <net/af.h>
# endif
# if __FreeBSD_version >= 300000
# include <net/if_var.h>
# endif
# include <net/route.h>
# include <netinet/in.h>
# ifdef __sgi
# define _KMEMUSER
# include <sys/ddi.h>
# ifdef IFF_DRVRLOCK /* IRIX6 */
# include <sys/hashing.h>
# endif
# endif
# if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /*IRIX<6*/
# include <netinet/in_var.h>
# endif
# include <netinet/in_systm.h>
# include <netinet/ip.h>
# include <netinet/tcp.h>
# include <netinet/udp.h>
# include <netinet/ip_icmp.h>
# ifdef USE_INET6
# include <netinet/icmp6.h>
# include <sys/sunddi.h>
# include <sys/ksynch.h>
# include <sys/kmem.h>
# include <sys/mkdev.h>
# include <sys/dditypes.h>
# include <sys/cmn_err.h>
# endif /* !__hpux */
#endif /* !SOLARIS && !__hpux */
#if !defined(linux)
# include <sys/protosw.h>
#endif
#include <sys/socket.h>
#include <net/if.h>
#ifdef sun
# include <net/af.h>
#endif
#if __FreeBSD_version >= 300000
# include <net/if_var.h>
#endif
#include <net/route.h>
#include <netinet/in.h>
#ifdef __sgi
# include <sys/ddi.h>
# ifdef IFF_DRVRLOCK /* IRIX6 */
# include <sys/hashing.h>
# endif
#endif
#if !defined(__hpux) && !defined(linux) && \
!(defined(__sgi) && !defined(IFF_DRVRLOCK)) /*IRIX<6*/
# include <netinet/in_var.h>
#endif
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#ifdef USE_INET6
# include <netinet/icmp6.h>
#endif
#if !defined(linux)
# include <netinet/ip_var.h>
# ifndef _KERNEL
# include <syslog.h>
# endif
# include "netinet/ip_compat.h"
# include <netinet/tcpip.h>
# include "netinet/ip_fil.h"
# if (__FreeBSD_version >= 300000)
# include <sys/malloc.h>
# endif
#endif
#ifndef _KERNEL
# include <syslog.h>
#endif
#include "netinet/ip_compat.h"
#include <netinet/tcpip.h>
#include "netinet/ip_fil.h"
#include "netinet/ip_nat.h"
#include "netinet/ip_frag.h"
#include "netinet/ip_state.h"
#include "netinet/ip_auth.h"
#if (__FreeBSD_version >= 300000) || defined(__NetBSD__)
# include <sys/malloc.h>
#endif
/* END OF INCLUDES */
# ifndef MIN
# define MIN(a,b) (((a)<(b))?(a):(b))
# endif
# ifdef IPFILTER_LOGSIZE
# undef IPLLOGSIZE
# define IPLLOGSIZE IPFILTER_LOGSIZE
# endif
#ifdef IPFILTER_LOG
# if defined(IPL_SELECT)
# include <machine/sys/user.h>
# include <sys/kthread_iface.h>
# define READ_COLLISION 0x001
# if USE_MUTEX
extern kmutex_t ipl_mutex;
# if SOLARIS
iplog_select_t iplog_ss[IPL_LOGMAX+1];
extern int selwait;
# endif /* IPL_SELECT */
# if defined(linux) && defined(_KERNEL)
wait_queue_head_t iplh_linux[IPL_LOGSIZE];
# endif
# if SOLARIS
extern kcondvar_t iplwait;
# endif
# endif
iplog_t **iplh[IPL_LOGMAX+1], *iplt[IPL_LOGMAX+1], *ipll[IPL_LOGMAX+1];
size_t iplused[IPL_LOGMAX+1];
static fr_info_t iplcrc[IPL_LOGMAX+1];
iplog_t **iplh[IPL_LOGSIZE], *iplt[IPL_LOGSIZE], *ipll[IPL_LOGSIZE];
int iplused[IPL_LOGSIZE];
static fr_info_t iplcrc[IPL_LOGSIZE];
int ipl_suppress = 1;
int ipl_buffer_sz;
int ipl_logmax = IPL_LOGMAX;
int ipl_logall = 0;
int ipl_log_init = 0;
int ipl_logsize = IPFILTER_LOGSIZE;
int ipl_magic[IPL_LOGSIZE] = { IPL_MAGIC, IPL_MAGIC_NAT, IPL_MAGIC_STATE,
IPL_MAGIC, IPL_MAGIC, IPL_MAGIC,
IPL_MAGIC, IPL_MAGIC };
/*
* Initialise log buffers & pointers. Also iniialised the CRC to a local
* secret for use in calculating the "last log checksum".
*/
void ipflog_init()
/* ------------------------------------------------------------------------ */
/* Function: fr_loginit */
/* Returns: int - 0 == success (always returned) */
/* Parameters: Nil */
/* */
/* Initialise log buffers & pointers. Also iniialised the CRC to a local */
/* secret for use in calculating the "last log checksum". */
/* ------------------------------------------------------------------------ */
int fr_loginit()
{
int i;
@ -154,40 +182,88 @@ void ipflog_init()
iplh[i] = &iplt[i];
iplused[i] = 0;
bzero((char *)&iplcrc[i], sizeof(iplcrc[i]));
# ifdef IPL_SELECT
iplog_ss[i].read_waiter = 0;
iplog_ss[i].state = 0;
# endif
# if defined(linux) && defined(_KERNEL)
init_waitqueue_head(iplh_linux + i);
# endif
}
# if SOLARIS && defined(_KERNEL)
cv_init(&iplwait, "ipl condvar", CV_DRIVER, NULL);
# endif
MUTEX_INIT(&ipl_mutex, "ipf log mutex");
ipl_log_init = 1;
return 0;
}
/*
* ipflog
* Create a log record for a packet given that it has been triggered by a
* rule (or the default setting). Calculate the transport protocol header
* size using predetermined size of a couple of popular protocols and thus
* how much data to copy into the log, including part of the data body if
* requested.
*/
int ipflog(flags, ip, fin, m)
u_int flags;
ip_t *ip;
fr_info_t *fin;
mb_t *m;
/* ------------------------------------------------------------------------ */
/* Function: fr_logunload */
/* Returns: Nil */
/* Parameters: Nil */
/* */
/* Clean up any log data that has accumulated without being read. */
/* ------------------------------------------------------------------------ */
void fr_logunload()
{
ipflog_t ipfl;
register size_t mlen, hlen;
int i;
if (ipl_log_init == 0)
return;
for (i = IPL_LOGMAX; i >= 0; i--)
(void) ipflog_clear(i);
# if SOLARIS && defined(_KERNEL)
cv_destroy(&iplwait);
# endif
MUTEX_DESTROY(&ipl_mutex);
ipl_log_init = 0;
}
/* ------------------------------------------------------------------------ */
/* Function: ipflog */
/* Returns: int - 0 == success, -1 == failure */
/* Parameters: fin(I) - pointer to packet information */
/* flags(I) - flags from filter rules */
/* */
/* Create a log record for a packet given that it has been triggered by a */
/* rule (or the default setting). Calculate the transport protocol header */
/* size using predetermined size of a couple of popular protocols and thus */
/* how much data to copy into the log, including part of the data body if */
/* requested. */
/* ------------------------------------------------------------------------ */
int ipflog(fin, flags)
fr_info_t *fin;
u_int flags;
{
register size_t hlen;
int types[2], mlen;
size_t sizes[2];
void *ptrs[2];
int types[2];
ipflog_t ipfl;
u_char p;
# if SOLARIS && defined(_KERNEL)
ill_t *ifp = fin->fin_ifp;
mb_t *m;
# if (SOLARIS || defined(__hpux)) && defined(_KERNEL)
qif_t *ifp;
# else
struct ifnet *ifp = fin->fin_ifp;
# endif
struct ifnet *ifp;
# endif /* SOLARIS || __hpux */
ipfl.fl_nattag.ipt_num[0] = 0;
m = fin->fin_m;
ifp = fin->fin_ifp;
hlen = fin->fin_hlen;
/*
* calculate header size.
*/
hlen = fin->fin_hlen;
if (fin->fin_off == 0) {
p = fin->fin_fi.fi_p;
if (p == IPPROTO_TCP)
@ -198,7 +274,7 @@ mb_t *m;
struct icmp *icmp;
icmp = (struct icmp *)fin->fin_dp;
/*
* For ICMP, if the packet is an error packet, also
* include the information about the packet which
@ -220,12 +296,12 @@ mb_t *m;
break;
}
}
#ifdef USE_INET6
# ifdef USE_INET6
else if (p == IPPROTO_ICMPV6) {
struct icmp6_hdr *icmp;
icmp = (struct icmp6_hdr *)fin->fin_dp;
/*
* For ICMPV6, if the packet is an error packet, also
* include the information about the packet which
@ -239,53 +315,71 @@ mb_t *m;
fin->fin_dlen);
}
}
#endif
# endif
}
/*
* Get the interface number and name to which this packet is
* currently associated.
*/
bzero((char *)ipfl.fl_ifname, sizeof(ipfl.fl_ifname));
# if SOLARIS && defined(_KERNEL)
ipfl.fl_unit = (u_int)ifp->ill_ppa;
bcopy(ifp->ill_name, ipfl.fl_ifname,
MIN(ifp->ill_name_length, sizeof(ipfl.fl_ifname)));
mlen = (flags & FR_LOGBODY) ? MIN(msgdsize(m) - hlen, 128) : 0;
# if (SOLARIS || defined(__hpux)) && defined(_KERNEL)
ipfl.fl_unit = (u_int)ifp->qf_ppa;
COPYIFNAME(ifp, ipfl.fl_ifname);
# else
# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \
(defined(OpenBSD) && (OpenBSD >= 199603)) || \
(defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
(defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
strncpy(ipfl.fl_ifname, ifp->if_xname, IFNAMSIZ);
COPYIFNAME(ifp, ipfl.fl_ifname);
# else
ipfl.fl_unit = (u_int)ifp->if_unit;
strncpy(ipfl.fl_ifname, ifp->if_name, MIN(sizeof(ipfl.fl_ifname),
sizeof(ifp->if_name)));
# if defined(_KERNEL)
if ((ipfl.fl_ifname[0] = ifp->if_name[0]))
if ((ipfl.fl_ifname[1] = ifp->if_name[1]))
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));
ipfl.fl_ifname[sizeof(ipfl.fl_ifname) - 1] = '\0';
# endif
# endif
mlen = (flags & FR_LOGBODY) ? MIN(fin->fin_plen - hlen, 128) : 0;
# endif
# endif /* __hpux || SOLARIS */
mlen = fin->fin_plen - hlen;
if (!ipl_logall) {
mlen = (flags & FR_LOGBODY) ? MIN(mlen, 128) : 0;
} else if ((flags & FR_LOGBODY) == 0) {
mlen = 0;
}
if (mlen < 0)
mlen = 0;
ipfl.fl_plen = (u_char)mlen;
ipfl.fl_hlen = (u_char)hlen;
ipfl.fl_rule = fin->fin_rule;
ipfl.fl_group = fin->fin_group;
if (fin->fin_fr != NULL)
(void) strncpy(ipfl.fl_group, fin->fin_group, FR_GROUPLEN);
if (fin->fin_fr != NULL) {
ipfl.fl_loglevel = fin->fin_fr->fr_loglevel;
else
ipfl.fl_logtag = fin->fin_fr->fr_logtag;
} else {
ipfl.fl_loglevel = 0xffff;
ipfl.fl_logtag = FR_NOLOGTAG;
}
if (fin->fin_nattag != NULL)
bcopy(fin->fin_nattag, (void *)&ipfl.fl_nattag,
sizeof(ipfl.fl_nattag));
ipfl.fl_flags = flags;
ipfl.fl_dir = fin->fin_out;
ipfl.fl_lflags = fin->fin_flx;
ptrs[0] = (void *)&ipfl;
sizes[0] = sizeof(ipfl);
types[0] = 0;
# if SOLARIS && defined(_KERNEL)
# if defined(MENTAT) && defined(_KERNEL)
/*
* Are we copied from the mblk or an aligned array ?
*/
if (ip == (ip_t *)m->b_rptr) {
if (fin->fin_ip == (ip_t *)m->b_rptr) {
ptrs[1] = m;
sizes[1] = hlen + mlen;
types[1] = 1;
} else {
ptrs[1] = ip;
ptrs[1] = fin->fin_ip;
sizes[1] = hlen + mlen;
types[1] = 0;
}
@ -293,14 +387,25 @@ mb_t *m;
ptrs[1] = m;
sizes[1] = hlen + mlen;
types[1] = 1;
# endif
# endif /* MENTAT */
return ipllog(IPL_LOGIPF, fin, ptrs, sizes, types, 2);
}
/*
* ipllog
*/
/* ------------------------------------------------------------------------ */
/* Function: ipllog */
/* Returns: int - 0 == success, -1 == failure */
/* Parameters: dev(I) - device that owns this log record */
/* fin(I) - pointer to packet information */
/* items(I) - array of pointers to log data */
/* itemsz(I) - array of size of valid memory pointed to */
/* types(I) - type of data pointed to by items pointers */
/* cnt(I) - number of elements in arrays items/itemsz/types */
/* */
/* Takes an array of parameters and constructs one record to include the */
/* miscellaneous packet information, as well as packet data, for reading */
/* from the log device. */
/* ------------------------------------------------------------------------ */
int ipllog(dev, fin, items, itemsz, types, cnt)
int dev;
fr_info_t *fin;
@ -308,33 +413,39 @@ void **items;
size_t *itemsz;
int *types, cnt;
{
caddr_t buf, s;
caddr_t buf, ptr;
iplog_t *ipl;
size_t len;
int i;
# if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL)
int s;
# endif
/*
* Check to see if this log record has a CRC which matches the last
* record logged. If it does, just up the count on the previous one
* rather than create a new one.
*/
MUTEX_ENTER(&ipl_mutex);
if ((fin != NULL) && (fin->fin_off == 0)) {
if ((ipll[dev] != NULL) &&
bcmp((char *)fin, (char *)&iplcrc[dev], FI_LCSIZE) == 0) {
ipll[dev]->ipl_count++;
MUTEX_EXIT(&ipl_mutex);
return 1;
}
bcopy((char *)fin, (char *)&iplcrc[dev], FI_LCSIZE);
} else
bzero((char *)&iplcrc[dev], FI_LCSIZE);
MUTEX_EXIT(&ipl_mutex);
if (ipl_suppress) {
MUTEX_ENTER(&ipl_mutex);
if ((fin != NULL) && (fin->fin_off == 0)) {
if ((ipll[dev] != NULL) &&
bcmp((char *)fin, (char *)&iplcrc[dev],
FI_LCSIZE) == 0) {
ipll[dev]->ipl_count++;
MUTEX_EXIT(&ipl_mutex);
return 0;
}
bcopy((char *)fin, (char *)&iplcrc[dev], FI_LCSIZE);
} else
bzero((char *)&iplcrc[dev], FI_CSIZE);
MUTEX_EXIT(&ipl_mutex);
}
/*
* Get the total amount of data to be logged.
*/
for (i = 0, len = IPLOG_SIZE; i < cnt; i++)
for (i = 0, len = sizeof(iplog_t); i < cnt; i++)
len += itemsz[i];
/*
@ -342,70 +453,85 @@ int *types, cnt;
* allocate that much.
*/
KMALLOCS(buf, caddr_t, len);
if (!buf)
return 0;
if (buf == NULL)
return -1;
SPL_NET(s);
MUTEX_ENTER(&ipl_mutex);
if ((iplused[dev] + len) > IPLLOGSIZE) {
if ((iplused[dev] + len) > ipl_logsize) {
MUTEX_EXIT(&ipl_mutex);
SPL_X(s);
KFREES(buf, len);
return 0;
return -1;
}
iplused[dev] += len;
MUTEX_EXIT(&ipl_mutex);
SPL_X(s);
/*
* advance the log pointer to the next empty record and deduct the
* amount of space we're going to use.
*/
ipl = (iplog_t *)buf;
ipl->ipl_magic = IPL_MAGIC;
ipl->ipl_magic = ipl_magic[dev];
ipl->ipl_count = 1;
ipl->ipl_next = NULL;
ipl->ipl_dsize = len;
# ifdef _KERNEL
# if SOLARIS || defined(sun)
uniqtime(&ipl->ipl_tv);
# else
# if BSD >= 199306 || defined(__FreeBSD__) || defined(__sgi)
microtime(&ipl->ipl_tv);
# endif
# endif
# else
#ifdef _KERNEL
GETKTIME(&ipl->ipl_sec);
#else
ipl->ipl_sec = 0;
ipl->ipl_usec = 0;
# endif
#endif
/*
* Loop through all the items to be logged, copying each one to the
* buffer. Use bcopy for normal data or the mb_t copyout routine.
*/
for (i = 0, s = buf + IPLOG_SIZE; i < cnt; i++) {
if (types[i] == 0)
bcopy(items[i], s, itemsz[i]);
else if (types[i] == 1) {
# if SOLARIS && defined(_KERNEL)
copyout_mblk(items[i], 0, itemsz[i], s);
# else
m_copydata(items[i], 0, itemsz[i], s);
# endif
for (i = 0, ptr = buf + sizeof(*ipl); i < cnt; i++) {
if (types[i] == 0) {
bcopy(items[i], ptr, itemsz[i]);
} else if (types[i] == 1) {
COPYDATA(items[i], 0, itemsz[i], ptr);
}
s += itemsz[i];
ptr += itemsz[i];
}
SPL_NET(s);
MUTEX_ENTER(&ipl_mutex);
ipll[dev] = ipl;
*iplh[dev] = ipl;
iplh[dev] = &ipl->ipl_next;
/*
* Now that the log record has been completed and added to the queue,
* wake up any listeners who may want to read it.
*/
# if SOLARIS && defined(_KERNEL)
cv_signal(&iplwait);
mutex_exit(&ipl_mutex);
MUTEX_EXIT(&ipl_mutex);
# else
MUTEX_EXIT(&ipl_mutex);
WAKEUP(&iplh[dev]);
WAKEUP(iplh,dev);
# endif
return 1;
SPL_X(s);
# ifdef IPL_SELECT
iplog_input_ready(dev);
# endif
return 0;
}
/* ------------------------------------------------------------------------ */
/* Function: ipflog_read */
/* Returns: int - 0 == success, else error value. */
/* Parameters: unit(I) - device we are reading from */
/* uio(O) - pointer to information about where to store data */
/* */
/* Called to handle a read on an IPFilter device. Returns only complete */
/* log messages - will not partially copy a log record out to userland. */
/* */
/* NOTE: This function will block and wait for a signal to return data if */
/* there is none present. Asynchronous I/O is not implemented. */
/* ------------------------------------------------------------------------ */
int ipflog_read(unit, uio)
minor_t unit;
struct uio *uio;
@ -413,7 +539,7 @@ struct uio *uio;
size_t dlen, copied;
int error = 0;
iplog_t *ipl;
# if defined(_KERNEL) && !SOLARIS
# if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL)
int s;
# endif
@ -423,11 +549,12 @@ struct uio *uio;
*/
if (IPL_LOGMAX < unit)
return ENXIO;
if (!uio->uio_resid)
if (uio->uio_resid == 0)
return 0;
if (uio->uio_resid < IPLOG_SIZE)
if ((uio->uio_resid < sizeof(iplog_t)) ||
(uio->uio_resid > ipl_logsize))
return EINVAL;
/*
* Lock the log so we can snapshot the variables. Wait for a signal
* if the log is empty.
@ -437,26 +564,48 @@ struct uio *uio;
while (iplt[unit] == NULL) {
# if SOLARIS && defined(_KERNEL)
if (!cv_wait_sig(&iplwait, &ipl_mutex)) {
if (!cv_wait_sig(&iplwait, &ipl_mutex.ipf_lk)) {
MUTEX_EXIT(&ipl_mutex);
return EINTR;
}
# else
MUTEX_EXIT(&ipl_mutex);
error = SLEEP(&iplh[unit], "ipl sleep");
if (error) {
SPL_X(s);
return error;
# if defined(__hpux) && defined(_KERNEL)
lock_t *l;
# ifdef IPL_SELECT
if (uio->uio_fpflags & (FNBLOCK|FNDELAY)) {
/* this is no blocking system call */
MUTEX_EXIT(&ipl_mutex);
return 0;
}
# endif
MUTEX_EXIT(&ipl_mutex);
l = get_sleep_lock(&iplh[unit]);
error = sleep(&iplh[unit], PZERO+1);
spinunlock(l);
# else
# if defined(__osf__) && defined(_KERNEL)
error = mpsleep(&iplh[unit], PSUSP|PCATCH, "iplread", 0,
&ipl_mutex, MS_LOCK_SIMPLE);
# else
MUTEX_EXIT(&ipl_mutex);
SPL_X(s);
error = SLEEP(unit + iplh, "ipl sleep");
# endif /* __osf__ */
# endif /* __hpux */
if (error)
return error;
SPL_NET(s);
MUTEX_ENTER(&ipl_mutex);
# endif /* SOLARIS */
}
# if BSD >= 199306 || defined(__FreeBSD__)
# if (BSD >= 199101) || defined(__FreeBSD__) || defined(__osf__)
uio->uio_rw = UIO_READ;
# endif
for (copied = 0; (ipl = iplt[unit]); copied += dlen) {
for (copied = 0; (ipl = iplt[unit]) != NULL; copied += dlen) {
dlen = ipl->ipl_dsize;
if (dlen > uio->uio_resid)
break;
@ -466,15 +615,19 @@ struct uio *uio;
iplt[unit] = ipl->ipl_next;
iplused[unit] -= dlen;
MUTEX_EXIT(&ipl_mutex);
SPL_X(s);
error = UIOMOVE((caddr_t)ipl, dlen, UIO_READ, uio);
MUTEX_ENTER(&ipl_mutex);
if (error) {
SPL_NET(s);
MUTEX_ENTER(&ipl_mutex);
ipl->ipl_next = iplt[unit];
iplt[unit] = ipl;
iplused[unit] += dlen;
break;
}
MUTEX_ENTER(&ipl_mutex);
KFREES((caddr_t)ipl, dlen);
SPL_NET(s);
}
if (!iplt[unit]) {
iplused[unit] = 0;
@ -488,14 +641,25 @@ struct uio *uio;
}
/* ------------------------------------------------------------------------ */
/* Function: ipflog_clear */
/* Returns: int - number of log bytes cleared. */
/* Parameters: unit(I) - device we are reading from */
/* */
/* Deletes all queued up log records for a given output device. */
/* ------------------------------------------------------------------------ */
int ipflog_clear(unit)
minor_t unit;
{
iplog_t *ipl;
int used;
# if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL)
int s;
# endif
SPL_NET(s);
MUTEX_ENTER(&ipl_mutex);
while ((ipl = iplt[unit])) {
while ((ipl = iplt[unit]) != NULL) {
iplt[unit] = ipl->ipl_next;
KFREES((caddr_t)ipl, ipl->ipl_dsize);
}
@ -503,8 +667,9 @@ minor_t unit;
ipll[unit] = NULL;
used = iplused[unit];
iplused[unit] = 0;
bzero((char *)&iplcrc[unit], FI_LCSIZE);
bzero((char *)&iplcrc[unit], FI_CSIZE);
MUTEX_EXIT(&ipl_mutex);
SPL_X(s);
return used;
}
#endif /* IPFILTER_LOG */

File diff suppressed because it is too large Load Diff

View File

@ -1,69 +1,77 @@
/* $FreeBSD$ */
/*
* Copyright (C) 1995-2001 by Darren Reed.
* Copyright (C) 1995-2001, 2003 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* @(#)ip_nat.h 1.5 2/4/96
* $Id: ip_nat.h,v 2.17.2.14 2000/11/18 03:58:04 darrenr Exp $
* $FreeBSD$
* Id: ip_nat.h,v 2.90.2.9 2005/03/28 11:09:55 darrenr Exp
*/
#ifndef __IP_NAT_H__
#define __IP_NAT_H__
#ifndef SOLARIS
#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
#endif
#if defined(__STDC__) || defined(__GNUC__)
#define SIOCADNAT _IOW('r', 60, struct ipnat *)
#define SIOCRMNAT _IOW('r', 61, struct ipnat *)
#define SIOCGNATS _IOWR('r', 62, struct natstat *)
#define SIOCGNATL _IOWR('r', 63, struct natlookup *)
#define SIOCADNAT _IOW('r', 60, struct ipfobj)
#define SIOCRMNAT _IOW('r', 61, struct ipfobj)
#define SIOCGNATS _IOWR('r', 62, struct ipfobj)
#define SIOCGNATL _IOWR('r', 63, struct ipfobj)
#define SIOCPROXY _IOWR('r', 64, struct ap_control)
#else
#define SIOCADNAT _IOW(r, 60, struct ipnat *)
#define SIOCRMNAT _IOW(r, 61, struct ipnat *)
#define SIOCGNATS _IOWR(r, 62, struct natstat *)
#define SIOCGNATL _IOWR(r, 63, struct natlookup *)
#define SIOCADNAT _IOW(r, 60, struct ipfobj)
#define SIOCRMNAT _IOW(r, 61, struct ipfobj)
#define SIOCGNATS _IOWR(r, 62, struct ipfobj)
#define SIOCGNATL _IOWR(r, 63, struct ipfobj)
#define SIOCPROXY _IOWR(r, 64, struct ap_control)
#endif
#undef LARGE_NAT /* define this if you're setting up a system to NAT
#undef LARGE_NAT /* define this if you're setting up a system to NAT
* LARGE numbers of networks/hosts - i.e. in the
* hundreds or thousands. In such a case, you should
* also change the RDR_SIZE and NAT_SIZE below to more
* appropriate sizes. The figures below were used for
* a setup with 1000-2000 networks to NAT.
*/
#ifndef NAT_SIZE
# ifdef LARGE_NAT
#ifndef NAT_SIZE
# ifdef LARGE_NAT
# define NAT_SIZE 2047
# else
# define NAT_SIZE 127
# endif
#endif
#ifndef RDR_SIZE
# ifdef LARGE_NAT
#ifndef RDR_SIZE
# ifdef LARGE_NAT
# define RDR_SIZE 2047
# else
# define RDR_SIZE 127
# endif
#endif
#ifndef HOSTMAP_SIZE
# ifdef LARGE_NAT
#ifndef HOSTMAP_SIZE
# ifdef LARGE_NAT
# define HOSTMAP_SIZE 8191
# else
# define HOSTMAP_SIZE 2047
# endif
#endif
#ifndef NAT_TABLE_MAX
/*
* This is newly introduced and for the sake of "least surprise", the numbers
* present aren't what we'd normally use for creating a proper hash table.
*/
# ifdef LARGE_NAT
# define NAT_TABLE_MAX 180000
# else
# define NAT_TABLE_MAX 30000
# endif
#endif
#ifndef NAT_TABLE_SZ
# ifdef LARGE_NAT
#ifndef NAT_TABLE_SZ
# ifdef LARGE_NAT
# define NAT_TABLE_SZ 16383
# else
# define NAT_TABLE_SZ 2047
@ -76,82 +84,141 @@
#define DEF_NAT_AGE 1200 /* 10 minutes (600 seconds) */
struct ipstate;
struct ap_session;
typedef struct nat {
u_long nat_age;
int nat_flags;
u_32_t nat_sumd[2];
u_32_t nat_ipsumd;
void *nat_data;
struct ap_session *nat_aps; /* proxy session */
struct frentry *nat_fr; /* filter rule ptr if appropriate */
struct in_addr nat_inip;
struct in_addr nat_outip;
struct in_addr nat_oip; /* other ip */
U_QUAD_T nat_pkts;
U_QUAD_T nat_bytes;
u_int nat_drop[2];
u_short nat_oport; /* other port */
u_short nat_inport;
u_short nat_outport;
u_short nat_use;
u_char nat_tcpstate[2];
u_char nat_p; /* protocol for NAT */
u_32_t nat_mssclamp; /* if != zero clamp MSS to this */
struct ipnat *nat_ptr; /* pointer back to the rule */
struct hostmap *nat_hm;
ipfmutex_t nat_lock;
struct nat *nat_next;
struct nat **nat_pnext;
struct nat *nat_hnext[2];
struct nat **nat_phnext[2];
struct hostmap *nat_hm;
void *nat_data;
struct nat **nat_me;
void *nat_ifp;
int nat_dir;
char nat_ifname[IFNAMSIZ];
#if SOLARIS || defined(__sgi) || (__FreeBSD_version >= 500043)
kmutex_t nat_lock;
#endif
struct ipstate *nat_state;
struct ap_session *nat_aps; /* proxy session */
frentry_t *nat_fr; /* filter rule ptr if appropriate */
struct ipnat *nat_ptr; /* pointer back to the rule */
void *nat_ifps[2];
void *nat_sync;
ipftqent_t nat_tqe;
u_32_t nat_flags;
u_32_t nat_sumd[2]; /* ip checksum delta for data segment*/
u_32_t nat_ipsumd; /* ip checksum delta for ip header */
u_32_t nat_mssclamp; /* if != zero clamp MSS to this */
i6addr_t nat_inip6;
i6addr_t nat_outip6;
i6addr_t nat_oip6; /* other ip */
U_QUAD_T nat_pkts[2];
U_QUAD_T nat_bytes[2];
union {
udpinfo_t nat_unu;
tcpinfo_t nat_unt;
icmpinfo_t nat_uni;
greinfo_t nat_ugre;
} nat_un;
u_short nat_oport; /* other port */
u_short nat_use;
u_char nat_p; /* protocol for NAT */
int nat_dir;
int nat_ref; /* reference count */
int nat_hv[2];
char nat_ifnames[2][LIFNAMSIZ];
int nat_rev; /* 0 = forward, 1 = reverse */
} nat_t;
#define nat_inip nat_inip6.in4
#define nat_outip nat_outip6.in4
#define nat_oip nat_oip6.in4
#define nat_age nat_tqe.tqe_die
#define nat_inport nat_un.nat_unt.ts_sport
#define nat_outport nat_un.nat_unt.ts_dport
#define nat_type nat_un.nat_uni.ici_type
#define nat_seq nat_un.nat_uni.ici_seq
#define nat_id nat_un.nat_uni.ici_id
#define nat_tcpstate nat_tqe.tqe_state
/*
* Values for nat_dir
*/
#define NAT_INBOUND 0
#define NAT_OUTBOUND 1
/*
* Definitions for nat_flags
*/
#define NAT_TCP 0x0001 /* IPN_TCP */
#define NAT_UDP 0x0002 /* IPN_UDP */
#define NAT_ICMPERR 0x0004 /* IPN_ICMPERR */
#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_TCPUDP (NAT_TCP|NAT_UDP)
#define NAT_TCPUDPICMP (NAT_TCP|NAT_UDP|NAT_ICMPERR)
#define NAT_TCPUDPICMPQ (NAT_TCP|NAT_UDP|NAT_ICMPQUERY)
#define NAT_FROMRULE (NAT_TCP|NAT_UDP)
/* 0x0100 reserved for FI_W_SPORT */
/* 0x0200 reserved for FI_W_DPORT */
/* 0x0400 reserved for FI_W_SADDR */
/* 0x0800 reserved for FI_W_DADDR */
/* 0x1000 reserved for FI_W_NEWFR */
/* 0x2000 reserved for SI_CLONE */
/* 0x4000 reserved for SI_CLONED */
/* 0x8000 reserved for SI_IGNOREPKT */
#define NAT_DEBUG 0x800000
typedef struct ipnat {
struct ipnat *in_next;
struct ipnat *in_rnext;
struct ipnat **in_prnext;
struct ipnat *in_mnext;
struct ipnat **in_pmnext;
void *in_ifp;
void *in_apr;
u_long in_space;
u_int in_use;
u_int in_hits;
struct in_addr in_nextip;
u_short in_pnext;
u_short in_ippip; /* IP #'s per IP# */
u_32_t in_flags; /* From here to in_dport must be reflected */
u_32_t in_mssclamp; /* if != zero clamp MSS to this */
u_short in_spare;
u_short in_ppip; /* ports per IP */
u_short in_port[2]; /* correctly in IPN_CMPSIZ */
struct in_addr in_in[2];
struct in_addr in_out[2];
struct in_addr in_src[2];
struct frtuc in_tuc;
u_int in_age[2]; /* Aging for NAT entries. Not for TCP */
int in_redir; /* 0 if it's a mapping, 1 if it's a hard redir */
char in_ifname[IFNAMSIZ];
char in_plabel[APR_LABELLEN]; /* proxy label */
char in_p; /* protocol */
struct ipnat *in_next; /* NAT rule list next */
struct ipnat *in_rnext; /* rdr rule hash next */
struct ipnat **in_prnext; /* prior rdr next ptr */
struct ipnat *in_mnext; /* map rule hash next */
struct ipnat **in_pmnext; /* prior map next ptr */
struct ipftq *in_tqehead[2];
void *in_ifps[2];
void *in_apr;
char *in_comment;
i6addr_t in_next6;
u_long in_space;
u_long in_hits;
u_int in_use;
u_int in_hv;
int in_flineno; /* conf. file line number */
u_short in_pnext;
u_char in_v;
u_char in_xxx;
/* From here to the end is covered by IPN_CMPSIZ */
u_32_t in_flags;
u_32_t in_mssclamp; /* if != 0 clamp MSS to this */
u_int in_age[2];
int in_redir; /* see below for values */
int in_p; /* protocol. */
i6addr_t in_in[2];
i6addr_t in_out[2];
i6addr_t in_src[2];
frtuc_t in_tuc;
u_short in_port[2];
u_short in_ppip; /* ports per IP. */
u_short in_ippip; /* IP #'s per IP# */
char in_ifnames[2][LIFNAMSIZ];
char in_plabel[APR_LABELLEN]; /* proxy label. */
ipftag_t in_tag;
} ipnat_t;
#define in_pmin in_port[0] /* Also holds static redir port */
#define in_pmax in_port[1]
#define in_nip in_nextip.s_addr
#define in_inip in_in[0].s_addr
#define in_inmsk in_in[1].s_addr
#define in_outip in_out[0].s_addr
#define in_outmsk in_out[1].s_addr
#define in_srcip in_src[0].s_addr
#define in_srcmsk in_src[1].s_addr
#define in_nextip in_next6.in4
#define in_nip in_next6.in4.s_addr
#define in_inip in_in[0].in4.s_addr
#define in_inmsk in_in[1].in4.s_addr
#define in_outip in_out[0].in4.s_addr
#define in_outmsk in_out[1].in4.s_addr
#define in_srcip in_src[0].in4.s_addr
#define in_srcmsk in_src[1].in4.s_addr
#define in_scmp in_tuc.ftu_scmp
#define in_dcmp in_tuc.ftu_dcmp
#define in_stop in_tuc.ftu_stop
@ -159,18 +226,44 @@ typedef struct ipnat {
#define in_sport in_tuc.ftu_sport
#define in_dport in_tuc.ftu_dport
#define NAT_OUTBOUND 0
#define NAT_INBOUND 1
/*
* Bit definitions for in_flags
*/
#define IPN_ANY 0x00000
#define IPN_TCP 0x00001
#define IPN_UDP 0x00002
#define IPN_TCPUDP (IPN_TCP|IPN_UDP)
#define IPN_ICMPERR 0x00004
#define IPN_TCPUDPICMP (IPN_TCP|IPN_UDP|IPN_ICMPERR)
#define IPN_ICMPQUERY 0x00008
#define IPN_TCPUDPICMPQ (IPN_TCP|IPN_UDP|IPN_ICMPQUERY)
#define IPN_RF (IPN_TCPUDP|IPN_DELETE|IPN_ICMPERR)
#define IPN_AUTOPORTMAP 0x00010
#define IPN_IPRANGE 0x00020
#define IPN_FILTER 0x00040
#define IPN_SPLIT 0x00080
#define IPN_ROUNDR 0x00100
#define IPN_NOTSRC 0x04000
#define IPN_NOTDST 0x08000
#define IPN_DYNSRCIP 0x10000 /* dynamic src IP# */
#define IPN_DYNDSTIP 0x20000 /* dynamic dst IP# */
#define IPN_DELETE 0x40000
#define IPN_STICKY 0x80000
#define IPN_FRAG 0x100000
#define IPN_FIXEDDPORT 0x200000
#define IPN_FINDFORWARD 0x400000
#define IPN_IN 0x800000
#define IPN_USERFLAGS (IPN_TCPUDP|IPN_AUTOPORTMAP|IPN_IPRANGE|IPN_SPLIT|\
IPN_ROUNDR|IPN_FILTER|IPN_NOTSRC|IPN_NOTDST|\
IPN_FRAG|IPN_STICKY|IPN_FIXEDDPORT|IPN_ICMPQUERY)
/*
* Values for in_redir
*/
#define NAT_MAP 0x01
#define NAT_REDIRECT 0x02
#define NAT_BIMAP (NAT_MAP|NAT_REDIRECT)
#define NAT_MAPBLK 0x04
/* 0x100 reserved for FI_W_SPORT */
/* 0x200 reserved for FI_W_DPORT */
/* 0x400 reserved for FI_W_SADDR */
/* 0x800 reserved for FI_W_DADDR */
/* 0x1000 reserved for FI_W_NEWFR */
#define MAPBLK_MINPORT 1024 /* don't use reserved ports for src port */
#define USABLE_PORTS (65536 - MAPBLK_MINPORT)
@ -205,16 +298,59 @@ typedef struct natget {
} natget_t;
typedef struct nattrpnt {
struct in_addr tr_dstip; /* real destination IP# */
struct in_addr tr_srcip; /* real source IP# */
struct in_addr tr_locip; /* local source IP# */
u_int tr_flags;
int tr_expire;
u_short tr_dstport; /* real destination port# */
u_short tr_srcport; /* real source port# */
u_short tr_locport; /* local source port# */
struct nattrpnt *tr_hnext;
struct nattrpnt **tr_phnext;
struct nattrpnt *tr_next;
struct nattrpnt **tr_pnext; /* previous next */
} nattrpnt_t;
#define TN_CMPSIZ offsetof(nattrpnt_t, tr_hnext)
/*
* This structure gets used to help NAT sessions keep the same NAT rule (and
* thus translation for IP address) when:
* (a) round-robin redirects are in use
* (b) different IP add
*/
typedef struct hostmap {
struct hostmap *hm_next;
struct hostmap **hm_pnext;
struct ipnat *hm_ipnat;
struct in_addr hm_realip;
struct in_addr hm_srcip;
struct in_addr hm_dstip;
struct in_addr hm_mapip;
int hm_ref;
u_32_t hm_port;
int hm_ref;
} hostmap_t;
/*
* Structure used to pass information in to nat_newmap and nat_newrdr.
*/
typedef struct natinfo {
ipnat_t *nai_np;
u_32_t nai_sum1;
u_32_t nai_sum2;
u_32_t nai_nflags;
u_32_t nai_flags;
struct in_addr nai_ip;
u_short nai_port;
u_short nai_nport;
u_short nai_sport;
u_short nai_dport;
} natinfo_t;
typedef struct natstat {
u_long ns_mapped[2];
u_long ns_rules;
@ -225,37 +361,23 @@ typedef struct natstat {
u_long ns_logfail;
u_long ns_memfail;
u_long ns_badnat;
u_long ns_addtrpnt;
nat_t **ns_table[2];
hostmap_t **ns_maptable;
ipnat_t *ns_list;
void *ns_apslist;
u_int ns_wilds;
u_int ns_nattab_sz;
u_int ns_nattab_max;
u_int ns_rultab_sz;
u_int ns_rdrtab_sz;
u_int ns_trpntab_sz;
u_int ns_hostmap_sz;
nat_t *ns_instances;
u_int ns_wilds;
nattrpnt_t *ns_trpntlist;
u_long *ns_bucketlen[2];
} natstat_t;
#define IPN_ANY 0x000
#define IPN_TCP 0x001
#define IPN_UDP 0x002
#define IPN_TCPUDP (IPN_TCP|IPN_UDP)
#define IPN_DELETE 0x004
#define IPN_ICMPERR 0x008
#define IPN_RF (IPN_TCPUDP|IPN_DELETE|IPN_ICMPERR)
#define IPN_AUTOPORTMAP 0x010
#define IPN_IPRANGE 0x020
#define IPN_USERFLAGS (IPN_TCPUDP|IPN_AUTOPORTMAP|IPN_IPRANGE|IPN_SPLIT|\
IPN_ROUNDR|IPN_FILTER|IPN_NOTSRC|IPN_NOTDST|IPN_FRAG)
#define IPN_FILTER 0x040
#define IPN_SPLIT 0x080
#define IPN_ROUNDR 0x100
#define IPN_NOTSRC 0x080000
#define IPN_NOTDST 0x100000
#define IPN_FRAG 0x200000
typedef struct natlog {
struct in_addr nl_origip;
struct in_addr nl_outip;
@ -265,8 +387,8 @@ typedef struct natlog {
u_short nl_inport;
u_short nl_type;
int nl_rule;
U_QUAD_T nl_pkts;
U_QUAD_T nl_bytes;
U_QUAD_T nl_pkts[2];
U_QUAD_T nl_bytes[2];
u_char nl_p;
} natlog_t;
@ -275,6 +397,7 @@ typedef struct natlog {
#define NL_NEWRDR NAT_REDIRECT
#define NL_NEWBIMAP NAT_BIMAP
#define NL_NEWBLOCK NAT_MAPBLK
#define NL_CLONE 0xfffd
#define NL_FLUSH 0xfffe
#define NL_EXPIRE 0xffff
@ -296,46 +419,60 @@ typedef struct natlog {
#define NAT_SYSSPACE 0x80000000
#define NAT_LOCKHELD 0x40000000
extern u_int ipf_nattable_sz;
extern u_int ipf_nattable_max;
extern u_int ipf_natrules_sz;
extern u_int ipf_rdrrules_sz;
extern u_int ipf_hostmap_sz;
extern u_int fr_nat_maxbucket;
extern u_int fr_nat_maxbucket_reset;
extern int fr_nat_lock;
extern void ip_natsync __P((void *));
extern void fr_natsync __P((void *));
extern u_long fr_defnatage;
extern u_long fr_defnaticmpage;
extern u_long fr_defnatipage;
/* nat_table[0] -> hashed list sorted by inside (ip, port) */
/* nat_table[1] -> hashed list sorted by outside (ip, port) */
extern nat_t **nat_table[2];
extern nat_t *nat_instances;
extern ipnat_t *nat_list;
extern ipnat_t **nat_rules;
extern ipnat_t **rdr_rules;
extern ipnat_t *nat_list;
extern ipftq_t *nat_utqe;
extern natstat_t nat_stats;
#if defined(__OpenBSD__)
extern void nat_ifdetach __P((void *));
#endif
#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003)
extern int nat_ioctl __P((caddr_t, u_long, int));
#else
extern int nat_ioctl __P((caddr_t, int, int));
#endif
extern int nat_init __P((void));
extern nat_t *nat_new __P((fr_info_t *, ip_t *, ipnat_t *, nat_t **,
u_int, int));
extern int fr_nat_ioctl __P((caddr_t, ioctlcmd_t, int));
extern int fr_natinit __P((void));
extern nat_t *nat_new __P((fr_info_t *, ipnat_t *, nat_t **, u_int, int));
extern nat_t *nat_outlookup __P((fr_info_t *, u_int, u_int, struct in_addr,
struct in_addr, int));
struct in_addr));
extern void fix_datacksum __P((u_short *, u_32_t));
extern nat_t *nat_inlookup __P((fr_info_t *, u_int, u_int, struct in_addr,
struct in_addr, int));
struct in_addr));
extern nat_t *nat_tnlookup __P((fr_info_t *, int));
extern nat_t *nat_maplookup __P((void *, u_int, struct in_addr,
struct in_addr));
extern nat_t *nat_lookupredir __P((natlookup_t *));
extern nat_t *nat_icmplookup __P((ip_t *, fr_info_t *, int));
extern nat_t *nat_icmp __P((ip_t *, fr_info_t *, u_int *, int));
extern int nat_clearlist __P((void));
extern void nat_insert __P((nat_t *));
extern nat_t *nat_icmperrorlookup __P((fr_info_t *, int));
extern nat_t *nat_icmperror __P((fr_info_t *, u_int *, int));
extern int nat_insert __P((nat_t *, int));
extern int ip_natout __P((ip_t *, fr_info_t *));
extern int ip_natin __P((ip_t *, fr_info_t *));
extern void ip_natunload __P((void)), ip_natexpire __P((void));
extern int fr_checknatout __P((fr_info_t *, u_32_t *));
extern int fr_natout __P((fr_info_t *, nat_t *, int, u_32_t));
extern int fr_checknatin __P((fr_info_t *, u_32_t *));
extern int fr_natin __P((fr_info_t *, nat_t *, int, u_32_t));
extern void fr_natunload __P((void));
extern void fr_natexpire __P((void));
extern void nat_log __P((struct nat *, u_int));
extern void fix_incksum __P((fr_info_t *, u_short *, u_32_t));
extern void fix_outcksum __P((fr_info_t *, u_short *, u_32_t));
extern void fix_datacksum __P((u_short *, u_32_t));
extern void fr_natderef __P((nat_t **));
extern u_short *nat_proto __P((fr_info_t *, nat_t *, u_int));
extern void nat_update __P((fr_info_t *, nat_t *, ipnat_t *));
extern void fr_setnatqueue __P((nat_t *, int));
#endif /* __IP_NAT_H__ */

View File

@ -1,46 +1,58 @@
/* $FreeBSD$ */
/*
* Copyright (C) 1997-2002 by Darren Reed.
* Copyright (C) 1997-2003 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*/
#if defined(__FreeBSD__) && defined(KERNEL) && !defined(_KERNEL)
# define _KERNEL
#endif
#if defined(__sgi) && (IRIX > 602)
# include <sys/ptimers.h>
#if defined(KERNEL) || defined(_KERNEL)
# undef KERNEL
# undef _KERNEL
# define KERNEL 1
# define _KERNEL 1
#endif
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/file.h>
#if !defined(__FreeBSD_version)
# include <sys/ioctl.h>
#endif
#include <sys/fcntl.h>
#if !defined(_KERNEL) && !defined(KERNEL)
#if !defined(_KERNEL) && !defined(__KERNEL__)
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# include <ctype.h>
# define _KERNEL
# ifdef __OpenBSD__
struct file;
# endif
# include <sys/uio.h>
# undef _KERNEL
#endif
#ifndef linux
#if !defined(linux)
# include <sys/protosw.h>
#endif
#include <sys/socket.h>
#if defined(_KERNEL)
# if !defined(linux)
# include <sys/systm.h>
# else
# include <linux/string.h>
# if !defined(__NetBSD__) && !defined(sun) && !defined(__osf__) && \
!defined(__OpenBSD__) && !defined(__hpux) && !defined(__sgi)
# include <sys/ctype.h>
# endif
#endif
#if !defined(__SVR4) && !defined(__svr4__)
# ifndef linux
# include <sys/systm.h>
# if !defined(__SVR4) && !defined(__svr4__)
# include <sys/mbuf.h>
# endif
#endif
#if defined(_KERNEL) && (__FreeBSD_version >= 220000)
# include <sys/filio.h>
# include <sys/fcntl.h>
# if (__FreeBSD_version >= 300000) && !defined(IPFILTER_LKM)
# include "opt_ipfilter.h"
# endif
#else
# include <sys/ioctl.h>
#endif
#if defined(__SVR4) || defined(__svr4__)
# include <sys/byteorder.h>
# ifdef _KERNEL
# include <sys/dditypes.h>
@ -75,65 +87,93 @@
# include <sys/malloc.h>
#endif
#if !defined(lint)
/* static const char rcsid[] = "@(#)$Id: ip_proxy.c,v 2.9.2.6 2001/07/15 22:06:15 darrenr Exp $"; */
static const char rcsid[] = "@(#)$FreeBSD$";
#include "netinet/ip_ftp_pxy.c"
#include "netinet/ip_rcmd_pxy.c"
# include "netinet/ip_pptp_pxy.c"
#if defined(_KERNEL)
# include "netinet/ip_irc_pxy.c"
# include "netinet/ip_raudio_pxy.c"
# include "netinet/ip_h323_pxy.c"
# ifdef IPFILTER_PRO
# include "netinet/ip_msnrpc_pxy.c"
# endif
# include "netinet/ip_netbios_pxy.c"
#endif
#include "netinet/ip_ipsec_pxy.c"
#include "netinet/ip_rpcb_pxy.c"
#ifdef USE_MUTEX
extern KRWLOCK_T ipf_nat, ipf_state;
/* 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";
#endif
static int appr_fixseqack __P((fr_info_t *, ip_t *, ap_session_t *, int ));
#define PROXY_DEBUG 0
#define AP_SESS_SIZE 53
#include "netinet/ip_ftp_pxy.c"
#if defined(_KERNEL)
#include "netinet/ip_rcmd_pxy.c"
#include "netinet/ip_raudio_pxy.c"
#include "netinet/ip_netbios_pxy.c"
#include "netinet/ip_ipsec_pxy.c"
int ipf_proxy_debug = 0;
#else
int ipf_proxy_debug = 2;
#endif
ap_session_t *ap_sess_tab[AP_SESS_SIZE];
ap_session_t *ap_sess_list = NULL;
aproxy_t *ap_proxylist = NULL;
aproxy_t ap_proxies[] = {
#ifdef IPF_FTP_PROXY
{ NULL, "ftp", (char)IPPROTO_TCP, 0, 0, ippr_ftp_init, NULL,
{ NULL, "ftp", (char)IPPROTO_TCP, 0, 0, ippr_ftp_init, ippr_ftp_fini,
ippr_ftp_new, NULL, ippr_ftp_in, ippr_ftp_out, NULL },
#endif
#ifdef IPF_IRC_PROXY
{ NULL, "irc", (char)IPPROTO_TCP, 0, 0, ippr_irc_init, ippr_irc_fini,
ippr_irc_new, NULL, NULL, ippr_irc_out, NULL, NULL },
#endif
#ifdef IPF_RCMD_PROXY
{ NULL, "rcmd", (char)IPPROTO_TCP, 0, 0, ippr_rcmd_init, NULL,
ippr_rcmd_new, NULL, NULL, ippr_rcmd_out, NULL },
{ NULL, "rcmd", (char)IPPROTO_TCP, 0, 0, ippr_rcmd_init, ippr_rcmd_fini,
ippr_rcmd_new, NULL, ippr_rcmd_in, ippr_rcmd_out, NULL, NULL },
#endif
#ifdef IPF_RAUDIO_PROXY
{ NULL, "raudio", (char)IPPROTO_TCP, 0, 0, ippr_raudio_init, NULL,
ippr_raudio_new, NULL, ippr_raudio_in, ippr_raudio_out, NULL },
{ NULL, "raudio", (char)IPPROTO_TCP, 0, 0, ippr_raudio_init, ippr_raudio_fini,
ippr_raudio_new, NULL, ippr_raudio_in, ippr_raudio_out, NULL, NULL },
#endif
#ifdef IPF_IPSEC_PROXY
{ NULL, "ipsec", (char)IPPROTO_UDP, 0, 0, ippr_ipsec_init, NULL,
ippr_ipsec_new, ippr_ipsec_del, NULL, ippr_ipsec_out,
ippr_ipsec_match },
#ifdef IPF_MSNRPC_PROXY
{ NULL, "msnrpc", (char)IPPROTO_TCP, 0, 0, ippr_msnrpc_init, ippr_msnrpc_fini,
ippr_msnrpc_new, NULL, ippr_msnrpc_in, ippr_msnrpc_out, NULL, NULL },
#endif
#ifdef IPF_NETBIOS_PROXY
{ NULL, "netbios", (char)IPPROTO_UDP, 0, 0, ippr_netbios_init, NULL,
NULL, NULL, NULL, ippr_netbios_out, NULL },
{ NULL, "netbios", (char)IPPROTO_UDP, 0, 0, ippr_netbios_init, ippr_netbios_fini,
NULL, NULL, NULL, ippr_netbios_out, NULL, NULL },
#endif
#ifdef IPF_IPSEC_PROXY
{ NULL, "ipsec", (char)IPPROTO_UDP, 0, 0,
ippr_ipsec_init, ippr_ipsec_fini, ippr_ipsec_new, ippr_ipsec_del,
ippr_ipsec_inout, ippr_ipsec_inout, ippr_ipsec_match, NULL },
#endif
#ifdef IPF_PPTP_PROXY
{ NULL, "pptp", (char)IPPROTO_TCP, 0, 0,
ippr_pptp_init, ippr_pptp_fini, ippr_pptp_new, ippr_pptp_del,
ippr_pptp_inout, ippr_pptp_inout, NULL, NULL },
#endif
#ifdef IPF_H323_PROXY
{ NULL, "h323", (char)IPPROTO_TCP, 0, 0, ippr_h323_init, NULL,
ippr_h323_new, ippr_h323_del, ippr_h323_in, ippr_h323_out, NULL },
{ NULL, "h245", (char)IPPROTO_TCP, 0, 0, ippr_h245_init, NULL,
ippr_h245_new, NULL, NULL, ippr_h245_out, NULL },
#endif
{ NULL, "", '\0', 0, 0, NULL, NULL, NULL }
{ NULL, "h323", (char)IPPROTO_TCP, 0, 0, ippr_h323_init, ippr_h323_fini,
ippr_h323_new, ippr_h323_del, ippr_h323_in, NULL, NULL },
{ NULL, "h245", (char)IPPROTO_TCP, 0, 0, NULL, NULL,
ippr_h245_new, NULL, NULL, ippr_h245_out, NULL },
#endif
#ifdef IPF_RPCB_PROXY
# if 0
{ NULL, "rpcbt", (char)IPPROTO_TCP, 0, 0,
ippr_rpcb_init, ippr_rpcb_fini, ippr_rpcb_new, ippr_rpcb_del,
ippr_rpcb_in, ippr_rpcb_out, NULL, NULL },
# endif
{ NULL, "rpcbu", (char)IPPROTO_UDP, 0, 0,
ippr_rpcb_init, ippr_rpcb_fini, ippr_rpcb_new, ippr_rpcb_del,
ippr_rpcb_in, ippr_rpcb_out, NULL, NULL },
#endif
{ NULL, "", '\0', 0, 0, NULL, NULL, NULL, NULL }
};
/*
* Dynamically add a new kernel proxy. Ensure that it is unique in the
* collection compiled in and dynamically added.
@ -146,17 +186,59 @@ aproxy_t *ap;
for (a = ap_proxies; a->apr_p; a++)
if ((a->apr_p == ap->apr_p) &&
!strncmp(a->apr_label, ap->apr_label,
sizeof(ap->apr_label)))
sizeof(ap->apr_label))) {
if (ipf_proxy_debug > 1)
printf("appr_add: %s/%d already present (B)\n",
a->apr_label, a->apr_p);
return -1;
}
for (a = ap_proxylist; a && a->apr_p; a = a->apr_next)
for (a = ap_proxylist; a->apr_p; a = a->apr_next)
if ((a->apr_p == ap->apr_p) &&
!strncmp(a->apr_label, ap->apr_label,
sizeof(ap->apr_label)))
sizeof(ap->apr_label))) {
if (ipf_proxy_debug > 1)
printf("appr_add: %s/%d already present (D)\n",
a->apr_label, a->apr_p);
return -1;
}
ap->apr_next = ap_proxylist;
ap_proxylist = ap;
return (*ap->apr_init)();
if (ap->apr_init != NULL)
return (*ap->apr_init)();
return 0;
}
/*
* Check to see if the proxy this control request has come through for
* exists, and if it does and it has a control function then invoke that
* control function.
*/
int appr_ctl(ctl)
ap_ctl_t *ctl;
{
aproxy_t *a;
int error;
a = appr_lookup(ctl->apc_p, ctl->apc_label);
if (a == NULL) {
if (ipf_proxy_debug > 1)
printf("appr_ctl: can't find %s/%d\n",
ctl->apc_label, ctl->apc_p);
error = ESRCH;
} else if (a->apr_ctl == NULL) {
if (ipf_proxy_debug > 1)
printf("appr_ctl: no ctl function for %s/%d\n",
ctl->apc_label, ctl->apc_p);
error = ENXIO;
} else {
error = (*a->apr_ctl)(a, ctl);
if ((error != 0) && (ipf_proxy_debug > 1))
printf("appr_ctl: %s/%d ctl error %d\n",
a->apr_label, a->apr_p, error);
}
return error;
}
@ -170,14 +252,20 @@ aproxy_t *ap;
{
aproxy_t *a, **app;
for (app = &ap_proxylist; (a = *app); app = &a->apr_next)
for (app = &ap_proxylist; ((a = *app) != NULL); app = &a->apr_next)
if (a == ap) {
a->apr_flags |= APR_DELETE;
*app = a->apr_next;
if (ap->apr_ref != 0)
if (ap->apr_ref != 0) {
if (ipf_proxy_debug > 2)
printf("appr_del: orphaning %s/%d\n",
ap->apr_label, ap->apr_p);
return 1;
}
return 0;
}
if (ipf_proxy_debug > 1)
printf("appr_del: proxy %lx not found\n", (u_long)ap);
return -1;
}
@ -185,8 +273,8 @@ aproxy_t *ap;
/*
* Return 1 if the packet is a good match against a proxy, else 0.
*/
int appr_ok(ip, tcp, nat)
ip_t *ip;
int appr_ok(fin, tcp, nat)
fr_info_t *fin;
tcphdr_t *tcp;
ipnat_t *nat;
{
@ -194,14 +282,62 @@ ipnat_t *nat;
u_short dport = nat->in_dport;
if ((apr == NULL) || (apr->apr_flags & APR_DELETE) ||
(ip->ip_p != apr->apr_p))
(fin->fin_p != apr->apr_p))
return 0;
if (((tcp != NULL) && (tcp->th_dport != dport)) || (!tcp && dport))
if ((tcp == NULL) && dport)
return 0;
return 1;
}
int appr_ioctl(data, cmd, mode)
caddr_t data;
ioctlcmd_t cmd;
int mode;
{
ap_ctl_t ctl;
caddr_t ptr;
int error;
mode = mode; /* LINT */
switch (cmd)
{
case SIOCPROXY :
BCOPYIN(data, &ctl, sizeof(ctl));
ptr = NULL;
if (ctl.apc_dsize > 0) {
KMALLOCS(ptr, caddr_t, ctl.apc_dsize);
if (ptr == NULL)
error = ENOMEM;
else {
error = copyinptr(ctl.apc_data, ptr,
ctl.apc_dsize);
if (error == 0)
ctl.apc_data = ptr;
}
} else {
ctl.apc_data = NULL;
error = 0;
}
if (error == 0)
error = appr_ctl(&ctl);
if ((ctl.apc_dsize > 0) && (ptr != NULL) &&
(ctl.apc_data == ptr)) {
KFREES(ptr, ctl.apc_dsize);
}
break;
default :
error = EINVAL;
}
return error;
}
/*
* If a proxy has a match function, call that to do extended packet
* matching.
@ -212,17 +348,37 @@ nat_t *nat;
{
aproxy_t *apr;
ipnat_t *ipn;
int result;
ipn = nat->nat_ptr;
if (ipn == NULL)
if (ipf_proxy_debug > 8)
printf("appr_match(%lx,%lx) aps %lx ptr %lx\n",
(u_long)fin, (u_long)nat, (u_long)nat->nat_aps,
(u_long)ipn);
if ((fin->fin_flx & (FI_SHORT|FI_BAD)) != 0) {
if (ipf_proxy_debug > 0)
printf("appr_match: flx 0x%x (BAD|SHORT)\n",
fin->fin_flx);
return -1;
}
apr = ipn->in_apr;
if ((apr == NULL) || (apr->apr_flags & APR_DELETE) ||
(nat->nat_aps == NULL))
if ((apr == NULL) || (apr->apr_flags & APR_DELETE)) {
if (ipf_proxy_debug > 0)
printf("appr_match:apr %lx apr_flags 0x%x\n",
(u_long)apr, apr ? apr->apr_flags : 0);
return -1;
if (apr->apr_match != NULL)
if ((*apr->apr_match)(fin, nat->nat_aps, nat) != 0)
}
if (apr->apr_match != NULL) {
result = (*apr->apr_match)(fin, nat->nat_aps, nat);
if (result != 0) {
if (ipf_proxy_debug > 4)
printf("appr_match: result %d\n", result);
return -1;
}
}
return 0;
}
@ -232,36 +388,55 @@ nat_t *nat;
* relevant details. call the init function once complete, prior to
* returning.
*/
int appr_new(fin, ip, nat)
int appr_new(fin, nat)
fr_info_t *fin;
ip_t *ip;
nat_t *nat;
{
register ap_session_t *aps;
aproxy_t *apr;
if ((nat->nat_ptr == NULL) || (nat->nat_aps != NULL))
if (ipf_proxy_debug > 8)
printf("appr_new(%lx,%lx) \n", (u_long)fin, (u_long)nat);
if ((nat->nat_ptr == NULL) || (nat->nat_aps != NULL)) {
if (ipf_proxy_debug > 0)
printf("appr_new: nat_ptr %lx nat_aps %lx\n",
(u_long)nat->nat_ptr, (u_long)nat->nat_aps);
return -1;
}
apr = nat->nat_ptr->in_apr;
if (!apr || (apr->apr_flags & APR_DELETE) || (ip->ip_p != apr->apr_p))
if ((apr->apr_flags & APR_DELETE) ||
(fin->fin_p != apr->apr_p)) {
if (ipf_proxy_debug > 2)
printf("appr_new: apr_flags 0x%x p %d/%d\n",
apr->apr_flags, fin->fin_p, apr->apr_p);
return -1;
}
KMALLOC(aps, ap_session_t *);
if (!aps)
if (!aps) {
if (ipf_proxy_debug > 0)
printf("appr_new: malloc failed (%lu)\n",
(u_long)sizeof(ap_session_t));
return -1;
}
bzero((char *)aps, sizeof(*aps));
aps->aps_p = ip->ip_p;
aps->aps_p = fin->fin_p;
aps->aps_data = NULL;
aps->aps_apr = apr;
aps->aps_psiz = 0;
if (apr->apr_new != NULL)
if ((*apr->apr_new)(fin, ip, aps, nat) == -1) {
if ((*apr->apr_new)(fin, aps, nat) == -1) {
if ((aps->aps_data != NULL) && (aps->aps_psiz != 0)) {
KFREES(aps->aps_data, aps->aps_psiz);
}
KFREE(aps);
if (ipf_proxy_debug > 2)
printf("appr_new: new(%lx) failed\n",
(u_long)apr->apr_new);
return -1;
}
aps->aps_nat = nat;
@ -274,95 +449,159 @@ nat_t *nat;
/*
* check to see if a packet should be passed through an active proxy routine
* if one has been setup for it.
* Check to see if a packet should be passed through an active proxy routine
* if one has been setup for it. We don't need to check the checksum here if
* IPFILTER_CKSUM is defined because if it is, a failed check causes FI_BAD
* to be set.
*/
int appr_check(ip, fin, nat)
ip_t *ip;
int appr_check(fin, nat)
fr_info_t *fin;
nat_t *nat;
{
#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
mb_t *m = fin->fin_qfm;
# if defined(ICK_VALID)
mb_t *m;
# endif
int dosum = 1;
#endif
tcphdr_t *tcp = NULL;
udphdr_t *udp = NULL;
ap_session_t *aps;
aproxy_t *apr;
u_32_t sum;
ip_t *ip;
short rv;
int err;
#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi)
u_32_t s1, s2, sd;
#endif
if (fin->fin_flx & FI_BAD) {
if (ipf_proxy_debug > 0)
printf("appr_check: flx 0x%x (BAD)\n", fin->fin_flx);
return -1;
}
#ifndef IPFILTER_CKSUM
if ((fin->fin_out == 0) && (fr_checkl4sum(fin) == -1)) {
if (ipf_proxy_debug > 0)
printf("appr_check: l4 checksum failure %d\n",
fin->fin_p);
if (fin->fin_p == IPPROTO_TCP)
frstats[fin->fin_out].fr_tcpbad++;
return -1;
}
#endif
aps = nat->nat_aps;
if ((aps != NULL) && (aps->aps_p == ip->ip_p)) {
if (ip->ip_p == IPPROTO_TCP) {
tcp = (tcphdr_t *)fin->fin_dp;
/*
* verify that the checksum is correct. If not, then
* don't do anything with this packet.
*/
#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
if (dohwcksum && (m->b_ick_flag == ICK_VALID)) {
sum = tcp->th_sum;
dosum = 0;
}
if (dosum)
sum = fr_tcpsum(fin->fin_qfm, ip, tcp);
#else
sum = fr_tcpsum(*(mb_t **)fin->fin_mp, ip, tcp);
#endif
if (sum != tcp->th_sum) {
#if PROXY_DEBUG || (!defined(_KERNEL) && !defined(KERNEL))
printf("proxy tcp checksum failure\n");
#endif
frstats[fin->fin_out].fr_tcpbad++;
if ((aps != NULL) && (aps->aps_p == fin->fin_p)) {
/*
* If there is data in this packet to be proxied then try and
* get it all into the one buffer, else drop it.
*/
#if defined(MENTAT) || defined(HAVE_M_PULLDOWN)
if ((fin->fin_dlen > 0) && !(fin->fin_flx & FI_COALESCE))
if (fr_coalesce(fin) == -1) {
if (ipf_proxy_debug > 0)
printf("appr_check: fr_coalesce failed %x\n", fin->fin_flx);
return -1;
}
#endif
ip = fin->fin_ip;
switch (fin->fin_p)
{
case IPPROTO_TCP :
tcp = (tcphdr_t *)fin->fin_dp;
#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) && defined(ICK_VALID)
m = fin->fin_qfm;
if (dohwcksum && (m->b_ick_flag == ICK_VALID))
dosum = 0;
#endif
/*
* Don't bother the proxy with these...or in fact,
* should we free up proxy stuff when seen?
*/
if ((tcp->th_flags & TH_RST) != 0)
return 0;
if ((fin->fin_tcpf & TH_RST) != 0)
break;
/*FALLTHROUGH*/
case IPPROTO_UDP :
udp = (udphdr_t *)fin->fin_dp;
break;
default :
break;
}
apr = aps->aps_apr;
err = 0;
if (fin->fin_out != 0) {
if (apr->apr_outpkt != NULL)
err = (*apr->apr_outpkt)(fin, ip, aps, nat);
err = (*apr->apr_outpkt)(fin, aps, nat);
} else {
if (apr->apr_inpkt != NULL)
err = (*apr->apr_inpkt)(fin, ip, aps, nat);
err = (*apr->apr_inpkt)(fin, aps, nat);
}
rv = APR_EXIT(err);
if (rv == 1) {
#if PROXY_DEBUG || (!defined(_KERNEL) && !defined(KERNEL))
printf("proxy says bad packet received\n");
#endif
if (((ipf_proxy_debug > 0) && (rv != 0)) ||
(ipf_proxy_debug > 8))
printf("appr_check: out %d err %x rv %d\n",
fin->fin_out, err, rv);
if (rv == 1)
return -1;
}
if (rv == 2) {
#if PROXY_DEBUG || (!defined(_KERNEL) && !defined(KERNEL))
printf("proxy says free app proxy data\n");
#endif
appr_free(apr);
nat->nat_aps = NULL;
return -1;
}
/*
* If err != 0 then the data size of the packet has changed
* so we need to recalculate the header checksums for the
* packet.
*/
#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi)
if (err != 0) {
short adjlen = err & 0xffff;
s1 = LONG_SUM(ip->ip_len - adjlen);
s2 = LONG_SUM(ip->ip_len);
CALC_SUMD(s1, s2, sd);
fix_outcksum(fin, &ip->ip_sum, sd);
}
#endif
/*
* For TCP packets, we may need to adjust the sequence and
* acknowledgement numbers to reflect changes in size of the
* data stream.
*
* For both TCP and UDP, recalculate the layer 4 checksum,
* regardless, as we can't tell (here) if data has been
* changed or not.
*/
if (tcp != NULL) {
err = appr_fixseqack(fin, ip, aps, APR_INC(err));
#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
if (dosum)
tcp->th_sum = fr_tcpsum(fin->fin_qfm, ip, tcp);
tcp->th_sum = fr_cksum(fin->fin_qfm, ip,
IPPROTO_TCP, tcp);
#else
tcp->th_sum = fr_tcpsum(*(mb_t **)fin->fin_mp, ip, tcp);
tcp->th_sum = fr_cksum(fin->fin_m, ip,
IPPROTO_TCP, tcp);
#endif
} else if ((udp != NULL) && (udp->uh_sum != 0)) {
#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
if (dosum)
udp->uh_sum = fr_cksum(fin->fin_qfm, ip,
IPPROTO_UDP, udp);
#else
udp->uh_sum = fr_cksum(fin->fin_m, ip,
IPPROTO_UDP, udp);
#endif
}
aps->aps_bytes += ip->ip_len;
aps->aps_bytes += fin->fin_plen;
aps->aps_pkts++;
return 1;
}
@ -379,6 +618,9 @@ char *name;
{
aproxy_t *ap;
if (ipf_proxy_debug > 8)
printf("appr_lookup(%d,%s)\n", pr, name);
for (ap = ap_proxies; ap->apr_p; ap++)
if ((ap->apr_p == pr) &&
!strncmp(name, ap->apr_label, sizeof(ap->apr_label))) {
@ -392,6 +634,8 @@ char *name;
ap->apr_ref++;
return ap;
}
if (ipf_proxy_debug > 2)
printf("appr_lookup: failed for %d/%s\n", pr, name);
return NULL;
}
@ -412,7 +656,7 @@ ap_session_t *aps;
if (!aps)
return;
for (ap = &ap_sess_list; (a = *ap); ap = &a->aps_next)
for (ap = &ap_sess_list; ((a = *ap) != NULL); ap = &a->aps_next)
if (a == aps) {
*ap = a->aps_next;
break;
@ -448,7 +692,7 @@ int inc;
* ip_len has already been adjusted by 'inc'.
*/
nlen = ip->ip_len;
nlen -= (ip->ip_hl << 2) + (tcp->th_off << 2);
nlen -= (IP_HL(ip) << 2) + (TCP_OFF(tcp) << 2);
inc2 = inc;
inc = (int)inc2;
@ -460,10 +704,10 @@ int inc;
/* switch to other set ? */
if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) &&
(seq1 > aps->aps_seqmin[!sel])) {
#if PROXY_DEBUG
printf("proxy out switch set seq %d -> %d %x > %x\n",
sel, !sel, seq1, aps->aps_seqmin[!sel]);
#endif
if (ipf_proxy_debug > 7)
printf("proxy out switch set seq %d -> %d %x > %x\n",
sel, !sel, seq1,
aps->aps_seqmin[!sel]);
sel = aps->aps_sel[out] = !sel;
}
@ -480,11 +724,10 @@ int inc;
if (inc && (seq1 > aps->aps_seqmin[!sel])) {
aps->aps_seqmin[sel] = seq1 + nlen - 1;
aps->aps_seqoff[sel] = aps->aps_seqoff[sel] + inc;
#if PROXY_DEBUG
printf("proxy seq set %d at %x to %d + %d\n", sel,
aps->aps_seqmin[sel], aps->aps_seqoff[sel],
inc);
#endif
if (ipf_proxy_debug > 7)
printf("proxy seq set %d at %x to %d + %d\n",
sel, aps->aps_seqmin[sel],
aps->aps_seqoff[sel], inc);
}
/***/
@ -495,10 +738,10 @@ int inc;
/* switch to other set ? */
if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) &&
(seq1 > aps->aps_ackmin[!sel])) {
#if PROXY_DEBUG
printf("proxy out switch set ack %d -> %d %x > %x\n",
sel, !sel, seq1, aps->aps_ackmin[!sel]);
#endif
if (ipf_proxy_debug > 7)
printf("proxy out switch set ack %d -> %d %x > %x\n",
sel, !sel, seq1,
aps->aps_ackmin[!sel]);
sel = aps->aps_sel[1 - out] = !sel;
}
@ -514,10 +757,9 @@ int inc;
/* switch to other set ? */
if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) &&
(seq1 > aps->aps_ackmin[!sel])) {
#if PROXY_DEBUG
printf("proxy in switch set ack %d -> %d %x > %x\n",
sel, !sel, seq1, aps->aps_ackmin[!sel]);
#endif
if (ipf_proxy_debug > 7)
printf("proxy in switch set ack %d -> %d %x > %x\n",
sel, !sel, seq1, aps->aps_ackmin[!sel]);
sel = aps->aps_sel[out] = !sel;
}
@ -534,11 +776,11 @@ int inc;
if (inc && (seq1 > aps->aps_ackmin[!sel])) {
aps->aps_ackmin[!sel] = seq1 + nlen - 1;
aps->aps_ackoff[!sel] = aps->aps_ackoff[sel] + inc;
#if PROXY_DEBUG
printf("proxy ack set %d at %x to %d + %d\n", !sel,
aps->aps_seqmin[!sel], aps->aps_seqoff[sel],
inc);
#endif
if (ipf_proxy_debug > 7)
printf("proxy ack set %d at %x to %d + %d\n",
!sel, aps->aps_seqmin[!sel],
aps->aps_seqoff[sel], inc);
}
/***/
@ -549,19 +791,17 @@ int inc;
/* switch to other set ? */
if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) &&
(seq1 > aps->aps_seqmin[!sel])) {
#if PROXY_DEBUG
printf("proxy in switch set seq %d -> %d %x > %x\n",
sel, !sel, seq1, aps->aps_seqmin[!sel]);
#endif
if (ipf_proxy_debug > 7)
printf("proxy in switch set seq %d -> %d %x > %x\n",
sel, !sel, seq1, aps->aps_seqmin[!sel]);
sel = aps->aps_sel[1 - out] = !sel;
}
if (aps->aps_seqoff[sel] != 0) {
#if PROXY_DEBUG
printf("sel %d seqoff %d seq1 %x seqmin %x\n", sel,
aps->aps_seqoff[sel], seq1,
aps->aps_seqmin[sel]);
#endif
if (ipf_proxy_debug > 7)
printf("sel %d seqoff %d seq1 %x seqmin %x\n",
sel, aps->aps_seqoff[sel], seq1,
aps->aps_seqmin[sel]);
if (seq1 > aps->aps_seqmin[sel]) {
seq2 = aps->aps_seqoff[sel];
tcp->th_ack = htonl(seq1 - seq2);
@ -569,10 +809,10 @@ int inc;
}
}
}
#if PROXY_DEBUG
printf("appr_fixseqack: seq %x ack %x\n", ntohl(tcp->th_seq),
ntohl(tcp->th_ack));
#endif
if (ipf_proxy_debug > 8)
printf("appr_fixseqack: seq %x ack %x\n",
ntohl(tcp->th_seq), ntohl(tcp->th_ack));
return ch ? 2 : 0;
}
@ -587,9 +827,11 @@ int appr_init()
int err = 0;
for (ap = ap_proxies; ap->apr_p; ap++) {
err = (*ap->apr_init)();
if (err != 0)
break;
if (ap->apr_init != NULL) {
err = (*ap->apr_init)();
if (err != 0)
break;
}
}
return err;
}
@ -604,9 +846,9 @@ void appr_unload()
aproxy_t *ap;
for (ap = ap_proxies; ap->apr_p; ap++)
if (ap->apr_fini)
if (ap->apr_fini != NULL)
(*ap->apr_fini)();
for (ap = ap_proxylist; ap; ap = ap->apr_next)
if (ap->apr_fini)
if (ap->apr_fini != NULL)
(*ap->apr_fini)();
}

View File

@ -1,10 +1,12 @@
/* $FreeBSD$ */
/*
* Copyright (C) 1997-2001 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* $Id: ip_proxy.h,v 2.8.2.4 2000/12/02 00:15:03 darrenr Exp $
* $FreeBSD$
* Id: ip_proxy.h,v 2.31.2.2 2005/03/12 19:33:48 darrenr Exp
*/
#ifndef __IP_PROXY_H__
@ -65,6 +67,26 @@ typedef struct ap_session {
#define aps_ackmin aps_un.apu_tcp.apt_ackmin
typedef struct ap_control {
char apc_label[APR_LABELLEN];
u_char apc_p;
/*
* The following fields are upto the proxy's apr_ctl routine to deal
* with. When the proxy gets this in kernel space, apc_data will
* point to a malloc'd region of memory of apc_dsize bytes. If the
* proxy wants to keep that memory, it must set apc_data to NULL
* before it returns. It is expected if this happens that it will
* take care to free it in apr_fini or otherwise as appropriate.
* apc_cmd is provided as a standard place to put simple commands,
* with apc_arg being available to put a simple arg.
*/
u_long apc_cmd;
u_long apc_arg;
void *apc_data;
size_t apc_dsize;
} ap_ctl_t;
typedef struct aproxy {
struct aproxy *apr_next;
char apr_label[APR_LABELLEN]; /* Proxy label # */
@ -73,34 +95,65 @@ typedef struct aproxy {
int apr_flags;
int (* apr_init) __P((void));
void (* apr_fini) __P((void));
int (* apr_new) __P((fr_info_t *, ip_t *,
ap_session_t *, struct nat *));
int (* apr_new) __P((fr_info_t *, ap_session_t *, struct nat *));
void (* apr_del) __P((ap_session_t *));
int (* apr_inpkt) __P((fr_info_t *, ip_t *,
ap_session_t *, struct nat *));
int (* apr_outpkt) __P((fr_info_t *, ip_t *,
ap_session_t *, struct nat *));
int (* apr_inpkt) __P((fr_info_t *, ap_session_t *, struct nat *));
int (* apr_outpkt) __P((fr_info_t *, ap_session_t *, struct nat *));
int (* apr_match) __P((fr_info_t *, ap_session_t *, struct nat *));
int (* apr_ctl) __P((struct aproxy *, struct ap_control *));
} aproxy_t;
#define APR_DELETE 1
#define APR_ERR(x) (((x) & 0xffff) << 16)
#define APR_ERR(x) ((x) << 16)
#define APR_EXIT(x) (((x) >> 16) & 0xffff)
#define APR_INC(x) ((x) & 0xffff)
#define FTP_BUFSZ 160
/*
* For the ftp proxy.
* Generic #define's to cover missing things in the kernel
*/
#ifndef isdigit
#define isdigit(x) ((x) >= '0' && (x) <= '9')
#endif
#ifndef isupper
#define isupper(x) (((unsigned)(x) >= 'A') && ((unsigned)(x) <= 'Z'))
#endif
#ifndef islower
#define islower(x) (((unsigned)(x) >= 'a') && ((unsigned)(x) <= 'z'))
#endif
#ifndef isalpha
#define isalpha(x) (isupper(x) || islower(x))
#endif
#ifndef toupper
#define toupper(x) (isupper(x) ? (x) : (x) - 'a' + 'A')
#endif
#ifndef isspace
#define isspace(x) (((x) == ' ') || ((x) == '\r') || ((x) == '\n') || \
((x) == '\t') || ((x) == '\b'))
#endif
/*
* This is the scratch buffer size used to hold strings from the TCP stream
* that we may want to parse. It's an arbitrary size, really, but it must
* be at least as large as IPF_FTPBUFSZ.
*/
#define FTP_BUFSZ 120
/*
* This buffer, however, doesn't need to be nearly so big. It just needs to
* be able to squeeze in the largest command it needs to rewrite, Which ones
* does it rewrite? EPRT, PORT, 227 replies.
*/
#define IPF_FTPBUFSZ 80 /* This *MUST* be >= 53! */
typedef struct ftpside {
char *ftps_rptr;
char *ftps_wptr;
void *ftps_ifp;
u_32_t ftps_seq[2];
u_32_t ftps_len;
int ftps_junk;
int ftps_junk; /* 2 = no cr/lf yet, 1 = cannot parse */
int ftps_cmds;
int ftps_cmd;
char ftps_buf[FTP_BUFSZ];
} ftpside_t;
@ -110,6 +163,22 @@ typedef struct ftpinfo {
ftpside_t ftp_side[2];
} ftpinfo_t;
/*
* For the irc proxy.
*/
typedef struct ircinfo {
size_t irc_len;
char *irc_snick;
char *irc_dnick;
char *irc_type;
char *irc_arg;
char *irc_addr;
u_32_t irc_ipnum;
u_short irc_port;
} ircinfo_t;
/*
* Real audio proxy structure and #defines
*/
@ -141,6 +210,19 @@ typedef struct raudio_s {
#define RAP_M_TCP 4
#define RAP_M_UDP_ROBUST (RAP_M_UDP|RAP_M_ROBUST)
/*
* MSN RPC proxy
*/
typedef struct msnrpcinfo {
u_int mri_flags;
int mri_cmd[2];
u_int mri_valid;
struct in_addr mri_raddr;
u_short mri_rport;
} msnrpcinfo_t;
/*
* IPSec proxy
*/
@ -155,21 +237,218 @@ typedef struct ipsec_pxy {
ipstate_t *ipsc_state;
} ipsec_pxy_t;
/*
* PPTP proxy
*/
typedef struct pptp_side {
u_32_t pptps_nexthdr;
u_32_t pptps_next;
int pptps_state;
int pptps_gothdr;
int pptps_len;
int pptps_bytes;
char *pptps_wptr;
char pptps_buffer[512];
} pptp_side_t;
typedef struct pptp_pxy {
ipnat_t pptp_rule;
nat_t *pptp_nat;
ipstate_t *pptp_state;
u_short pptp_call[2];
pptp_side_t pptp_side[2];
} pptp_pxy_t;
/*
* Sun RPCBIND proxy
*/
#define RPCB_MAXMSG 888
#define RPCB_RES_PMAP 0 /* Response contains a v2 port. */
#define RPCB_RES_STRING 1 /* " " " v3 (GETADDR) string. */
#define RPCB_RES_LIST 2 /* " " " v4 (GETADDRLIST) list. */
#define RPCB_MAXREQS 32 /* Arbitrary limit on tracked transactions */
#define RPCB_REQMIN 40
#define RPCB_REQMAX 888
#define RPCB_REPMIN 20
#define RPCB_REPMAX 604 /* XXX double check this! */
/*
* These macros determine the number of bytes between p and the end of
* r->rs_buf relative to l.
*/
#define RPCB_BUF_END(r) (char *)((r)->rm_msgbuf + (r)->rm_buflen)
#define RPCB_BUF_GEQ(r, p, l) \
((RPCB_BUF_END((r)) > (char *)(p)) && \
((RPCB_BUF_END((r)) - (char *)(p)) >= (l)))
#define RPCB_BUF_EQ(r, p, l) \
(RPCB_BUF_END((r)) == ((char *)(p) + (l)))
/*
* The following correspond to RPC(B) detailed in RFC183[13].
*/
#define RPCB_CALL 0
#define RPCB_REPLY 1
#define RPCB_MSG_VERSION 2
#define RPCB_PROG 100000
#define RPCB_GETPORT 3
#define RPCB_GETADDR 3
#define RPCB_GETADDRLIST 11
#define RPCB_MSG_ACCEPTED 0
#define RPCB_MSG_DENIED 1
/* BEGIN (Generic XDR structures) */
typedef struct xdr_string {
u_32_t *xs_len;
char *xs_str;
} xdr_string_t;
typedef struct xdr_auth {
/* u_32_t xa_flavor; */
xdr_string_t xa_string;
} xdr_auth_t;
typedef struct xdr_uaddr {
u_32_t xu_ip;
u_short xu_port;
xdr_string_t xu_str;
} xdr_uaddr_t;
typedef struct xdr_proto {
u_int xp_proto;
xdr_string_t xp_str;
} xdr_proto_t;
#define xu_xslen xu_str.xs_len
#define xu_xsstr xu_str.xs_str
#define xp_xslen xp_str.xs_len
#define xp_xsstr xp_str.xs_str
/* END (Generic XDR structures) */
/* BEGIN (RPC call structures) */
typedef struct pmap_args {
/* u_32_t pa_prog; */
/* u_32_t pa_vers; */
u_32_t *pa_prot;
/* u_32_t pa_port; */
} pmap_args_t;
typedef struct rpcb_args {
/* u_32_t *ra_prog; */
/* u_32_t *ra_vers; */
xdr_proto_t ra_netid;
xdr_uaddr_t ra_maddr;
/* xdr_string_t ra_owner; */
} rpcb_args_t;
typedef struct rpc_call {
/* u_32_t rc_rpcvers; */
/* u_32_t rc_prog; */
u_32_t *rc_vers;
u_32_t *rc_proc;
xdr_auth_t rc_authcred;
xdr_auth_t rc_authverf;
union {
pmap_args_t ra_pmapargs;
rpcb_args_t ra_rpcbargs;
} rpcb_args;
} rpc_call_t;
#define rc_pmapargs rpcb_args.ra_pmapargs
#define rc_rpcbargs rpcb_args.ra_rpcbargs
/* END (RPC call structures) */
/* BEGIN (RPC reply structures) */
typedef struct rpcb_entry {
xdr_uaddr_t re_maddr;
xdr_proto_t re_netid;
/* u_32_t re_semantics; */
xdr_string_t re_family;
xdr_proto_t re_proto;
u_32_t *re_more; /* 1 == another entry follows */
} rpcb_entry_t;
typedef struct rpcb_listp {
u_32_t *rl_list; /* 1 == list follows */
int rl_cnt;
rpcb_entry_t rl_entries[2]; /* TCP / UDP only */
} rpcb_listp_t;
typedef struct rpc_resp {
/* u_32_t rr_acceptdeny; */
/* Omitted 'message denied' fork; we don't care about rejects. */
xdr_auth_t rr_authverf;
/* u_32_t *rr_astat; */
union {
u_32_t *resp_pmap;
xdr_uaddr_t resp_getaddr;
rpcb_listp_t resp_getaddrlist;
} rpcb_reply;
} rpc_resp_t;
#define rr_v2 rpcb_reply.resp_pmap
#define rr_v3 rpcb_reply.resp_getaddr
#define rr_v4 rpcb_reply.resp_getaddrlist
/* END (RPC reply structures) */
/* BEGIN (RPC message structure & macros) */
typedef struct rpc_msg {
char rm_msgbuf[RPCB_MAXMSG]; /* RPCB data buffer */
u_int rm_buflen;
u_32_t *rm_xid;
/* u_32_t Call vs Reply */
union {
rpc_call_t rb_call;
rpc_resp_t rb_resp;
} rm_body;
} rpc_msg_t;
#define rm_call rm_body.rb_call
#define rm_resp rm_body.rb_resp
/* END (RPC message structure & macros) */
/*
* These code paths aren't hot enough to warrant per transaction
* mutexes.
*/
typedef struct rpcb_xact {
struct rpcb_xact *rx_next;
struct rpcb_xact **rx_pnext;
u_32_t rx_xid; /* RPC transmission ID */
u_int rx_type; /* RPCB response type */
u_int rx_ref; /* reference count */
u_int rx_proto; /* transport protocol (v2 only) */
} rpcb_xact_t;
typedef struct rpcb_session {
ipfmutex_t rs_rxlock;
rpcb_xact_t *rs_rxlist;
} rpcb_session_t;
/*
* For an explanation, please see the following:
* RFC1832 - Sections 3.11, 4.4, and 4.5.
*/
#define XDRALIGN(x) ((((x) % 4) != 0) ? ((((x) + 3) / 4) * 4) : (x))
extern ap_session_t *ap_sess_tab[AP_SESS_SIZE];
extern ap_session_t *ap_sess_list;
extern aproxy_t ap_proxies[];
extern int ippr_ftp_pasvonly;
extern int appr_add __P((aproxy_t *));
extern int appr_ctl __P((ap_ctl_t *));
extern int appr_del __P((aproxy_t *));
extern int appr_init __P((void));
extern void appr_unload __P((void));
extern int appr_ok __P((ip_t *, tcphdr_t *, struct ipnat *));
extern int appr_ok __P((fr_info_t *, tcphdr_t *, struct ipnat *));
extern int appr_match __P((fr_info_t *, struct nat *));
extern void appr_free __P((aproxy_t *));
extern void aps_free __P((ap_session_t *));
extern int appr_check __P((ip_t *, fr_info_t *, struct nat *));
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 *, ip_t *, struct nat *));
extern int appr_new __P((fr_info_t *, struct nat *));
extern int appr_ioctl __P((caddr_t, ioctlcmd_t, int));
#endif /* __IP_PROXY_H__ */

View File

@ -1,20 +1,27 @@
/* $FreeBSD$ */
/*
* $FreeBSD$
* 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
*/
#if SOLARIS && defined(_KERNEL)
extern kmutex_t ipf_rw;
#endif
#define IPF_RAUDIO_PROXY
int ippr_raudio_init __P((void));
int ippr_raudio_new __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *));
int ippr_raudio_in __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *));
int ippr_raudio_out __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *));
void ippr_raudio_fini __P((void));
int ippr_raudio_new __P((fr_info_t *, ap_session_t *, nat_t *));
int ippr_raudio_in __P((fr_info_t *, ap_session_t *, nat_t *));
int ippr_raudio_out __P((fr_info_t *, ap_session_t *, nat_t *));
static frentry_t raudiofr;
int raudio_proxy_init = 0;
/*
* Real Audio application proxy initialization.
@ -24,26 +31,39 @@ int ippr_raudio_init()
bzero((char *)&raudiofr, sizeof(raudiofr));
raudiofr.fr_ref = 1;
raudiofr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
MUTEX_INIT(&raudiofr.fr_lock, "Real Audio proxy rule lock");
raudio_proxy_init = 1;
return 0;
}
void ippr_raudio_fini()
{
if (raudio_proxy_init == 1) {
MUTEX_DESTROY(&raudiofr.fr_lock);
raudio_proxy_init = 0;
}
}
/*
* Setup for a new proxy to handle Real Audio.
*/
int ippr_raudio_new(fin, ip, aps, nat)
int ippr_raudio_new(fin, aps, nat)
fr_info_t *fin;
ip_t *ip;
ap_session_t *aps;
nat_t *nat;
{
raudio_t *rap;
KMALLOCS(aps->aps_data, void *, sizeof(raudio_t));
if (aps->aps_data == NULL)
return -1;
fin = fin; /* LINT */
nat = nat; /* LINT */
bzero(aps->aps_data, sizeof(raudio_t));
rap = aps->aps_data;
aps->aps_psiz = sizeof(raudio_t);
@ -53,20 +73,21 @@ nat_t *nat;
int ippr_raudio_out(fin, ip, aps, nat)
int ippr_raudio_out(fin, aps, nat)
fr_info_t *fin;
ip_t *ip;
ap_session_t *aps;
nat_t *nat;
{
raudio_t *rap = aps->aps_data;
unsigned char membuf[512 + 1], *s;
u_short id = 0;
int off, dlen;
tcphdr_t *tcp;
int off, dlen;
int len = 0;
mb_t *m;
nat = nat; /* LINT */
/*
* If we've already processed the start messages, then nothing left
* for the proxy to do.
@ -74,26 +95,24 @@ nat_t *nat;
if (rap->rap_eos == 1)
return 0;
m = fin->fin_m;
tcp = (tcphdr_t *)fin->fin_dp;
off = fin->fin_hlen + (tcp->th_off << 2);
bzero(membuf, sizeof(membuf));
#if SOLARIS
m = fin->fin_qfm;
off = (char *)tcp - (char *)fin->fin_ip;
off += (TCP_OFF(tcp) << 2) + fin->fin_ipoff;
dlen = msgdsize(m) - off;
if (dlen <= 0)
return 0;
dlen = MIN(sizeof(membuf), dlen);
copyout_mblk(m, off, dlen, (char *)membuf);
#ifdef __sgi
dlen = fin->fin_plen - off;
#else
m = *(mb_t **)fin->fin_mp;
dlen = mbufchainlen(m) - off;
dlen = MSGDSIZE(m) - off;
#endif
if (dlen <= 0)
return 0;
dlen = MIN(sizeof(membuf), dlen);
m_copydata(m, off, dlen, (char *)membuf);
#endif
if (dlen > sizeof(membuf))
dlen = sizeof(membuf);
bzero((char *)membuf, sizeof(membuf));
COPYDATA(m, off, dlen, (char *)membuf);
/*
* In all the startup parsing, ensure that we don't go outside
* the packet buffer boundary.
@ -160,23 +179,23 @@ nat_t *nat;
}
int ippr_raudio_in(fin, ip, aps, nat)
int ippr_raudio_in(fin, aps, nat)
fr_info_t *fin;
ip_t *ip;
ap_session_t *aps;
nat_t *nat;
{
unsigned char membuf[IPF_MAXPORTLEN + 1], *s;
tcphdr_t *tcp, tcph, *tcp2 = &tcph;
raudio_t *rap = aps->aps_data;
int off, dlen, slen, clen;
struct in_addr swa, swb;
int off, dlen, slen;
int a1, a2, a3, a4;
u_short sp, dp;
fr_info_t fi;
tcp_seq seq;
nat_t *ipn;
nat_t *nat2;
u_char swp;
ip_t *ip;
mb_t *m;
/*
@ -187,27 +206,24 @@ nat_t *nat;
if (rap->rap_sdone != 0)
return 0;
m = fin->fin_m;
tcp = (tcphdr_t *)fin->fin_dp;
off = fin->fin_hlen + (tcp->th_off << 2);
m = *(mb_t **)fin->fin_mp;
off = (char *)tcp - (char *)fin->fin_ip;
off += (TCP_OFF(tcp) << 2) + fin->fin_ipoff;
#if SOLARIS
m = fin->fin_qfm;
dlen = msgdsize(m) - off;
if (dlen <= 0)
return 0;
bzero(membuf, sizeof(membuf));
clen = MIN(sizeof(membuf), dlen);
copyout_mblk(m, off, clen, (char *)membuf);
#ifdef __sgi
dlen = fin->fin_plen - off;
#else
dlen = mbufchainlen(m) - off;
dlen = MSGDSIZE(m) - off;
#endif
if (dlen <= 0)
return 0;
bzero(membuf, sizeof(membuf));
clen = MIN(sizeof(membuf), dlen);
m_copydata(m, off, clen, (char *)membuf);
#endif
if (dlen > sizeof(membuf))
dlen = sizeof(membuf);
bzero((char *)membuf, sizeof(membuf));
COPYDATA(m, off, dlen, (char *)membuf);
seq = ntohl(tcp->th_seq);
/*
@ -215,7 +231,7 @@ nat_t *nat;
* We only care for the first 19 bytes coming back from the server.
*/
if (rap->rap_sseq == 0) {
s = (u_char *)memstr("PNA", (char *)membuf, 3, clen);
s = (u_char *)memstr("PNA", (char *)membuf, 3, dlen);
if (s == NULL)
return 0;
a1 = s - membuf;
@ -250,6 +266,7 @@ nat_t *nat;
rap->rap_srport = (*s << 8) | *(s + 1);
}
ip = fin->fin_ip;
swp = ip->ip_p;
swa = ip->ip_src;
swb = ip->ip_dst;
@ -260,10 +277,14 @@ nat_t *nat;
bcopy((char *)fin, (char *)&fi, sizeof(fi));
bzero((char *)tcp2, sizeof(*tcp2));
tcp2->th_off = 5;
TCP_OFF_A(tcp2, 5);
fi.fin_state = NULL;
fi.fin_nat = NULL;
fi.fin_flx |= FI_IGNORE;
fi.fin_dp = (char *)tcp2;
fi.fin_fr = &raudiofr;
fi.fin_dlen = sizeof(*tcp2);
fi.fin_plen = fi.fin_hlen + sizeof(*tcp2);
tcp2->th_win = htons(8192);
slen = ip->ip_len;
ip->ip_len = fin->fin_hlen + sizeof(*tcp);
@ -277,13 +298,16 @@ nat_t *nat;
fi.fin_data[0] = dp;
fi.fin_data[1] = sp;
fi.fin_out = 0;
ipn = nat_new(&fi, ip, nat->nat_ptr, NULL,
IPN_UDP | (sp ? 0 : FI_W_SPORT), NAT_OUTBOUND);
if (ipn != NULL) {
ipn->nat_age = fr_defnatage;
(void) fr_addstate(ip, &fi, NULL,
FI_IGNOREPKT|FI_NORULE|
(sp ? 0 : FI_W_SPORT));
nat2 = nat_new(&fi, nat->nat_ptr, NULL,
NAT_SLAVE|IPN_UDP | (sp ? 0 : SI_W_SPORT),
NAT_OUTBOUND);
if (nat2 != NULL) {
(void) nat_proto(&fi, nat2, IPN_UDP);
nat_update(&fi, nat2, nat2->nat_ptr);
(void) fr_addstate(&fi, NULL, (sp ? 0 : SI_W_SPORT));
if (fi.fin_state != NULL)
fr_statederef(&fi, (ipstate_t **)&fi.fin_state);
}
}
@ -294,12 +318,16 @@ nat_t *nat;
fi.fin_data[0] = sp;
fi.fin_data[1] = 0;
fi.fin_out = 1;
ipn = nat_new(&fi, ip, nat->nat_ptr, NULL, IPN_UDP|FI_W_DPORT,
NAT_OUTBOUND);
if (ipn != NULL) {
ipn->nat_age = fr_defnatage;
(void) fr_addstate(ip, &fi, NULL,
FI_W_DPORT|FI_IGNOREPKT|FI_NORULE);
nat2 = nat_new(&fi, nat->nat_ptr, NULL,
NAT_SLAVE|IPN_UDP|SI_W_DPORT,
NAT_OUTBOUND);
if (nat2 != NULL) {
(void) nat_proto(&fi, nat2, IPN_UDP);
nat_update(&fi, nat2, nat2->nat_ptr);
(void) fr_addstate(&fi, NULL, SI_W_DPORT);
if (fi.fin_state != NULL)
fr_statederef(&fi, (ipstate_t **)&fi.fin_state);
}
}

View File

@ -1,28 +1,32 @@
/* $FreeBSD$ */
/*
* $Id: ip_rcmd_pxy.c,v 1.4.2.7 2003/04/26 05:59:39 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
*
* Simple RCMD transparent proxy for in-kernel use. For use with the NAT
* code.
* $FreeBSD$
*/
#if SOLARIS && defined(_KERNEL)
extern kmutex_t ipf_rw;
#endif
#define isdigit(x) ((x) >= '0' && (x) <= '9')
#define IPF_RCMD_PROXY
int ippr_rcmd_init __P((void));
int ippr_rcmd_new __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *));
int ippr_rcmd_out __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *));
void ippr_rcmd_fini __P((void));
int ippr_rcmd_new __P((fr_info_t *, ap_session_t *, nat_t *));
int ippr_rcmd_out __P((fr_info_t *, ap_session_t *, nat_t *));
int ippr_rcmd_in __P((fr_info_t *, ap_session_t *, nat_t *));
u_short ipf_rcmd_atoi __P((char *));
int ippr_rcmd_portmsg __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *));
int ippr_rcmd_portmsg __P((fr_info_t *, ap_session_t *, nat_t *));
static frentry_t rcmdfr;
int rcmd_proxy_init = 0;
/*
* RCMD application proxy initialization.
@ -32,25 +36,43 @@ int ippr_rcmd_init()
bzero((char *)&rcmdfr, sizeof(rcmdfr));
rcmdfr.fr_ref = 1;
rcmdfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
MUTEX_INIT(&rcmdfr.fr_lock, "RCMD proxy rule lock");
rcmd_proxy_init = 1;
return 0;
}
void ippr_rcmd_fini()
{
if (rcmd_proxy_init == 1) {
MUTEX_DESTROY(&rcmdfr.fr_lock);
rcmd_proxy_init = 0;
}
}
/*
* Setup for a new RCMD proxy.
*/
int ippr_rcmd_new(fin, ip, aps, nat)
int ippr_rcmd_new(fin, aps, nat)
fr_info_t *fin;
ip_t *ip;
ap_session_t *aps;
nat_t *nat;
{
tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp;
fin = fin; /* LINT */
nat = nat; /* LINT */
aps->aps_psiz = sizeof(u_32_t);
KMALLOCS(aps->aps_data, u_32_t *, sizeof(u_32_t));
if (aps->aps_data == NULL)
if (aps->aps_data == NULL) {
#ifdef IP_RCMD_PROXY_DEBUG
printf("ippr_rcmd_new:KMALLOCS(%d) failed\n", sizeof(u_32_t));
#endif
return -1;
}
*(u_32_t *)aps->aps_data = 0;
aps->aps_sport = tcp->th_sport;
aps->aps_dport = tcp->th_dport;
@ -67,7 +89,7 @@ char *ptr;
register char *s = ptr, c;
register u_short i = 0;
while ((c = *s++) && isdigit(c)) {
while (((c = *s++) != '\0') && ISDIGIT(c)) {
i *= 10;
i += c - '0';
}
@ -75,19 +97,19 @@ char *ptr;
}
int ippr_rcmd_portmsg(fin, ip, aps, nat)
int ippr_rcmd_portmsg(fin, aps, nat)
fr_info_t *fin;
ip_t *ip;
ap_session_t *aps;
nat_t *nat;
{
char portbuf[8], *s;
struct in_addr swip;
int off, dlen;
tcphdr_t *tcp, tcph, *tcp2 = &tcph;
struct in_addr swip, swip2;
int off, dlen, nflags;
char portbuf[8], *s;
fr_info_t fi;
u_short sp;
nat_t *ipn;
nat_t *nat2;
ip_t *ip;
mb_t *m;
tcp = (tcphdr_t *)fin->fin_dp;
@ -101,37 +123,47 @@ nat_t *nat;
(tcp->th_seq != *(u_32_t *)aps->aps_data))
return 0;
off = fin->fin_hlen + (tcp->th_off << 2);
m = fin->fin_m;
ip = fin->fin_ip;
off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff;
#if SOLARIS
m = fin->fin_qfm;
dlen = msgdsize(m) - off;
bzero(portbuf, sizeof(portbuf));
copyout_mblk(m, off, MIN(sizeof(portbuf), dlen), portbuf);
#ifdef __sgi
dlen = fin->fin_plen - off;
#else
m = *(mb_t **)fin->fin_mp;
dlen = mbufchainlen(m) - off;
bzero(portbuf, sizeof(portbuf));
m_copydata(m, off, MIN(sizeof(portbuf), dlen), portbuf);
dlen = MSGDSIZE(m) - off;
#endif
if (dlen <= 0)
return 0;
bzero(portbuf, sizeof(portbuf));
COPYDATA(m, off, MIN(sizeof(portbuf), dlen), portbuf);
portbuf[sizeof(portbuf) - 1] = '\0';
s = portbuf;
sp = ipf_rcmd_atoi(s);
if (!sp)
if (sp == 0) {
#ifdef IP_RCMD_PROXY_DEBUG
printf("ippr_rcmd_portmsg:sp == 0 dlen %d [%s]\n",
dlen, portbuf);
#endif
return 0;
}
/*
* Add skeleton NAT entry for connection which will come back the
* other way.
*/
bcopy((char *)fin, (char *)&fi, sizeof(fi));
fi.fin_flx |= FI_IGNORE;
fi.fin_data[0] = sp;
fi.fin_data[1] = fin->fin_data[1];
ipn = nat_outlookup(&fi, IPN_TCP, nat->nat_p, nat->nat_inip,
ip->ip_dst, 0);
if (ipn == NULL) {
fi.fin_data[1] = 0;
if (nat->nat_dir == NAT_OUTBOUND)
nat2 = nat_outlookup(&fi, NAT_SEARCH|IPN_TCP, nat->nat_p,
nat->nat_inip, nat->nat_oip);
else
nat2 = nat_inlookup(&fi, NAT_SEARCH|IPN_TCP, nat->nat_p,
nat->nat_inip, nat->nat_oip);
if (nat2 == NULL) {
int slen;
slen = ip->ip_len;
@ -140,33 +172,66 @@ nat_t *nat;
tcp2->th_win = htons(8192);
tcp2->th_sport = htons(sp);
tcp2->th_dport = 0; /* XXX - don't specify remote port */
tcp2->th_off = 5;
TCP_OFF_A(tcp2, 5);
tcp2->th_flags = TH_SYN;
fi.fin_data[1] = 0;
fi.fin_dp = (char *)tcp2;
fi.fin_fr = &rcmdfr;
fi.fin_dlen = sizeof(*tcp2);
fi.fin_plen = fi.fin_hlen + sizeof(*tcp2);
fi.fin_flx &= FI_LOWTTL|FI_FRAG|FI_TCPUDP|FI_OPTIONS|FI_IGNORE;
nflags = NAT_SLAVE|IPN_TCP|SI_W_DPORT;
swip = ip->ip_src;
ip->ip_src = nat->nat_inip;
ipn = nat_new(&fi, ip, nat->nat_ptr, NULL, IPN_TCP|FI_W_DPORT,
NAT_OUTBOUND);
if (ipn != NULL) {
ipn->nat_age = fr_defnatage;
fi.fin_fr = &rcmdfr;
(void) fr_addstate(ip, &fi, NULL,
FI_W_DPORT|FI_IGNOREPKT);
swip2 = ip->ip_dst;
if (nat->nat_dir == NAT_OUTBOUND) {
fi.fin_fi.fi_saddr = nat->nat_inip.s_addr;
ip->ip_src = nat->nat_inip;
} else {
fi.fin_fi.fi_saddr = nat->nat_oip.s_addr;
ip->ip_src = nat->nat_oip;
nflags |= NAT_NOTRULEPORT;
}
nat2 = nat_new(&fi, nat->nat_ptr, NULL, nflags, nat->nat_dir);
if (nat2 != NULL) {
(void) nat_proto(&fi, nat2, IPN_TCP);
nat_update(&fi, nat2, nat2->nat_ptr);
fi.fin_ifp = NULL;
if (nat->nat_dir == NAT_INBOUND) {
fi.fin_fi.fi_daddr = nat->nat_inip.s_addr;
ip->ip_dst = nat->nat_inip;
}
(void) fr_addstate(&fi, &nat2->nat_state, SI_W_DPORT);
if (fi.fin_state != NULL)
fr_statederef(&fi, (ipstate_t **)&fi.fin_state);
}
ip->ip_len = slen;
ip->ip_src = swip;
ip->ip_dst = swip2;
}
return 0;
}
int ippr_rcmd_out(fin, ip, aps, nat)
int ippr_rcmd_out(fin, aps, nat)
fr_info_t *fin;
ip_t *ip;
ap_session_t *aps;
nat_t *nat;
{
return ippr_rcmd_portmsg(fin, ip, aps, nat);
if (nat->nat_dir == NAT_OUTBOUND)
return ippr_rcmd_portmsg(fin, aps, nat);
return 0;
}
int ippr_rcmd_in(fin, aps, nat)
fr_info_t *fin;
ap_session_t *aps;
nat_t *nat;
{
if (nat->nat_dir == NAT_INBOUND)
return ippr_rcmd_portmsg(fin, aps, nat);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +1,25 @@
/* $FreeBSD$ */
/*
* Copyright (C) 1995-2001 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* @(#)ip_state.h 1.3 1/12/96 (C) 1995 Darren Reed
* $Id: ip_state.h,v 2.13.2.1 2000/07/08 02:15:35 darrenr Exp $
* $FreeBSD$
* Id: ip_state.h,v 2.68.2.3 2005/03/03 14:24:11 darrenr Exp
*/
#ifndef __IP_STATE_H__
#define __IP_STATE_H__
#if defined(__STDC__) || defined(__GNUC__)
# define SIOCDELST _IOW('r', 61, struct ipstate *)
# define SIOCDELST _IOW('r', 61, struct ipfobj)
#else
# define SIOCDELST _IOW(r, 61, struct ipstate *)
# define SIOCDELST _IOW(r, 61, struct ipfobj)
#endif
struct ipscan;
#ifndef IPSTATE_SIZE
# define IPSTATE_SIZE 5737
#endif
@ -29,54 +33,34 @@
(s2).s_addr, (d2).s_addr)
typedef struct udpstate {
u_short us_sport;
u_short us_dport;
} udpstate_t;
typedef struct icmpstate {
u_short ics_id;
u_short ics_seq;
u_char ics_type;
} icmpstate_t;
typedef struct tcpdata {
u_32_t td_end;
u_32_t td_maxend;
u_32_t td_maxwin;
u_char td_wscale;
} tcpdata_t;
typedef struct tcpstate {
u_short ts_sport;
u_short ts_dport;
tcpdata_t ts_data[2];
u_char ts_state[2];
} tcpstate_t;
typedef struct ipstate {
ipfmutex_t is_lock;
struct ipstate *is_next;
struct ipstate **is_pnext;
struct ipstate *is_hnext;
struct ipstate **is_phnext;
struct ipstate **is_me;
void *is_ifp[4];
void *is_sync;
struct nat *is_nat[2];
frentry_t *is_rule;
U_QUAD_T is_pkts;
U_QUAD_T is_bytes;
U_QUAD_T is_icmppkts;
union i6addr is_src;
union i6addr is_dst;
void *is_ifp[4];
u_long is_age;
u_int is_frage[2]; /* age from filter rule, forward & reverse */
struct ipftq *is_tqehead[2];
struct ipscan *is_isc;
U_QUAD_T is_pkts[4];
U_QUAD_T is_bytes[4];
U_QUAD_T is_icmppkts[4];
struct ipftqent is_sti;
u_int is_frage[2];
int is_ref; /* reference count */
int is_isninc[2];
u_short is_sumd[2];
i6addr_t is_src;
i6addr_t is_dst;
u_int is_pass;
u_char is_p; /* Protocol */
u_char is_v; /* IP version */
u_char is_fsm; /* 1 = following FSM, 0 = not */
u_char is_xxx; /* pad */
u_int is_hv; /* hash value for this in the table */
u_32_t is_rulen; /* rule number */
u_32_t is_flags; /* flags for this structure */
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_short is_sec; /* security options set */
@ -84,37 +68,74 @@ typedef struct ipstate {
u_short is_auth; /* authentication options set */
u_short is_authmsk; /* " " mask */
union {
icmpstate_t is_ics;
tcpstate_t is_ts;
udpstate_t is_us;
icmpinfo_t is_ics;
tcpinfo_t is_ts;
udpinfo_t is_us;
greinfo_t is_ug;
} is_ps;
u_32_t is_group;
char is_ifname[4][IFNAMSIZ];
#if SOLARIS || defined(__sgi) || (__FreeBSD_version >= 500043)
kmutex_t is_lock;
#endif
u_32_t is_flags;
int is_flx[2][2];
u_32_t is_rulen; /* rule number when created */
u_32_t is_s0[2];
u_short is_smsk[2];
char is_group[FR_GROUPLEN];
char is_sbuf[2][16];
char is_ifname[4][LIFNAMSIZ];
} ipstate_t;
#define is_die is_sti.tqe_die
#define is_state is_sti.tqe_state
#define is_touched is_sti.tqe_touched
#define is_saddr is_src.in4.s_addr
#define is_daddr is_dst.in4.s_addr
#define is_icmp is_ps.is_ics
#define is_type is_icmp.ics_type
#define is_code is_icmp.ics_code
#define is_type is_icmp.ici_type
#define is_code is_icmp.ici_code
#define is_tcp is_ps.is_ts
#define is_udp is_ps.is_us
#define is_send is_tcp.ts_data[0].td_end
#define is_dend is_tcp.ts_data[1].td_end
#define is_maxswin is_tcp.ts_data[0].td_maxwin
#define is_maxdwin is_tcp.ts_data[1].td_maxwin
#define is_swscale is_tcp.ts_data[0].td_wscale
#define is_dwscale is_tcp.ts_data[1].td_wscale
#define is_maxsend is_tcp.ts_data[0].td_maxend
#define is_maxdend is_tcp.ts_data[1].td_maxend
#define is_swinscale is_tcp.ts_data[0].td_winscale
#define is_dwinscale is_tcp.ts_data[1].td_winscale
#define is_swinflags is_tcp.ts_data[0].td_winflags
#define is_dwinflags is_tcp.ts_data[1].td_winflags
#define is_sport is_tcp.ts_sport
#define is_dport is_tcp.ts_dport
#define is_state is_tcp.ts_state
#define is_ifpin is_ifp[0]
#define is_ifpout is_ifp[2]
#define is_gre is_ps.is_ug
#define is_call is_gre.gs_call
#define IS_WSPORT SI_W_SPORT /* 0x00100 */
#define IS_WDPORT SI_W_DPORT /* 0x00200 */
#define IS_WSADDR SI_W_SADDR /* 0x00400 */
#define IS_WDADDR SI_W_DADDR /* 0x00800 */
#define IS_NEWFR SI_NEWFR /* 0x01000 */
#define IS_CLONE SI_CLONE /* 0x02000 */
#define IS_CLONED SI_CLONED /* 0x04000 */
#define IS_TCPFSM 0x10000
#define IS_STRICT 0x20000
#define IS_ISNSYN 0x40000
#define IS_ISNACK 0x80000
#define IS_STATESYNC 0x100000
/*
* IS_SC flags are for scan-operations that need to be recognised in state.
*/
#define IS_SC_CLIENT 0x10000000
#define IS_SC_SERVER 0x20000000
#define IS_SC_MATCHC 0x40000000
#define IS_SC_MATCHS 0x80000000
#define IS_SC_MATCHALL (IS_SC_MATCHC|IS_SC_MATCHC)
#define IS_SC_ALL (IS_SC_MATCHC|IS_SC_MATCHC|IS_SC_CLIENT|IS_SC_SERVER)
/*
* Flags that can be passed into fr_addstate
*/
#define IS_INHERITED 0x0fffff00
#define TH_OPENING (TH_SYN|TH_ACK)
/*
@ -124,6 +145,8 @@ typedef struct ipstate {
* Bits 4 - 7 are set from the initial packet and contain what the packet
* anded with bits 0-3 must match.
* Bits 8,9 are used to indicate wildcard source/destination port matching.
* Bits 10,11 are reserved for other wildcard flag compatibility.
* Bits 12,13 are for scaning.
*/
typedef struct ipstate_save {
@ -136,10 +159,11 @@ typedef struct ipstate_save {
typedef struct ipslog {
U_QUAD_T isl_pkts;
U_QUAD_T isl_bytes;
union i6addr isl_src;
union i6addr isl_dst;
U_QUAD_T isl_pkts[4];
U_QUAD_T isl_bytes[4];
i6addr_t isl_src;
i6addr_t isl_dst;
u_32_t isl_tag;
u_short isl_type;
union {
u_short isl_filler[2];
@ -151,23 +175,28 @@ typedef struct ipslog {
u_char isl_flags;
u_char isl_state[2];
u_32_t isl_rulen;
u_32_t isl_group;
char isl_group[FR_GROUPLEN];
} ipslog_t;
#define isl_sport isl_ps.isl_ports[0]
#define isl_dport isl_ps.isl_ports[1]
#define isl_itype isl_ps.isl_icmp
#define ISL_NEW 0
#define ISL_EXPIRE 0xffff
#define ISL_FLUSH 0xfffe
#define ISL_REMOVE 0xfffd
#define ISL_NEW 0
#define ISL_CLONE 1
#define ISL_EXPIRE 0xffff
#define ISL_FLUSH 0xfffe
#define ISL_REMOVE 0xfffd
#define ISL_INTERMEDIATE 0xfffc
#define ISL_KILLED 0xfffb
#define ISL_ORPHAN 0xfffa
typedef struct ips_stat {
u_long iss_hits;
u_long iss_miss;
u_long iss_max;
u_long iss_maxref;
u_long iss_tcp;
u_long iss_udp;
u_long iss_icmp;
@ -178,8 +207,15 @@ typedef struct ips_stat {
u_long iss_logged;
u_long iss_logfail;
u_long iss_inuse;
u_long iss_wild;
u_long iss_killed;
u_long iss_ticks;
u_long iss_bucketfull;
int iss_statesize;
int iss_statemax;
ipstate_t **iss_table;
ipstate_t *iss_list;
u_long *iss_bucketlen;
} ips_stat_t;
@ -193,21 +229,34 @@ extern u_long fr_udptimeout;
extern u_long fr_udpacktimeout;
extern u_long fr_icmptimeout;
extern u_long fr_icmpacktimeout;
extern ipstate_t *ips_list;
extern u_long fr_iptimeout;
extern int fr_statemax;
extern int fr_statesize;
extern int fr_state_lock;
extern int fr_state_maxbucket;
extern int fr_state_maxbucket_reset;
extern ipstate_t *ips_list;
extern ipftq_t *ips_utqe;
extern ipftq_t ips_tqtqb[IPF_TCP_NSTATES];
extern int fr_stateinit __P((void));
extern int fr_tcpstate __P((ipstate_t *, fr_info_t *, ip_t *, tcphdr_t *));
extern ipstate_t *fr_addstate __P((ip_t *, fr_info_t *, ipstate_t **, u_int));
extern frentry_t *fr_checkstate __P((ip_t *, fr_info_t *));
extern void ip_statesync __P((void *));
extern ipstate_t *fr_addstate __P((fr_info_t *, ipstate_t **, u_int));
extern frentry_t *fr_checkstate __P((struct fr_info *, u_32_t *));
extern ipstate_t *fr_stlookup __P((fr_info_t *, tcphdr_t *, ipftq_t **));
extern void fr_statesync __P((void *));
extern void fr_timeoutstate __P((void));
extern int fr_tcp_age __P((u_long *, u_char *, fr_info_t *, int, int));
extern int fr_tcp_age __P((struct ipftqent *, struct fr_info *,
struct ipftq *, int));
extern int fr_tcpinwindow __P((struct fr_info *, struct tcpdata *,
struct tcpdata *, tcphdr_t *, int));
extern void fr_stateunload __P((void));
extern void ipstate_log __P((struct ipstate *, u_int));
#if defined(__NetBSD__) || defined(__OpenBSD__)
extern int fr_state_ioctl __P((caddr_t, u_long, int));
#else
extern int fr_state_ioctl __P((caddr_t, int, int));
#endif
extern int fr_state_ioctl __P((caddr_t, ioctlcmd_t, int));
extern void fr_stinsert __P((struct ipstate *, int));
extern void fr_sttab_init __P((struct ipftq *));
extern void fr_sttab_destroy __P((struct ipftq *));
extern void fr_updatestate __P((fr_info_t *, ipstate_t *, ipftq_t *));
extern void fr_statederef __P((fr_info_t *, ipstate_t **));
extern void fr_setstatequeue __P((ipstate_t *, int));
#endif /* __IP_STATE_H__ */

View File

@ -1,15 +1,20 @@
/* $FreeBSD$ */
/*
* Copyright (C) 1993-2002 by Darren Reed.
* Copyright (C) 1993-2001, 2003 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* @(#)ipl.h 1.21 6/5/96
* $FreeBSD$
* Id: ipl.h,v 2.52.2.9 2005/03/30 14:14:05 darrenr Exp
*/
#ifndef __IPL_H__
#define __IPL_H__
#define IPL_VERSION "IP Filter: v3.4.35"
#define IPL_VERSION "IP Filter: v4.1.8"
#define IPFILTER_VERSION 4010800
#endif

View File

@ -1,29 +1,10 @@
/* $FreeBSD$ */
/*
* Copyright 1999 Guido van Rooij. All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* Copyright (C) 2000 by Darren Reed.
*
* $FreeBSD$
* See the IPFILTER.LICENCE file for details on licencing.
*/
@ -37,13 +18,6 @@
#include <net/if.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#if (__FreeBSD_version >= 199511)
# include <net/route.h>
# include <netinet/ip_var.h>
# include <netinet/tcp.h>
# include <netinet/tcpip.h>
#endif
#include <netinet/ipl.h>
@ -53,145 +27,127 @@
#include <netinet/ip_nat.h>
#include <netinet/ip_auth.h>
#include <netinet/ip_frag.h>
#include <netinet/ip_proxy.h>
static struct cdev *ipf_devs[IPL_LOGMAX + 1];
#if __FreeBSD_version >= 502116
static struct cdev *ipf_devs[IPL_LOGSIZE];
#else
static dev_t ipf_devs[IPL_LOGSIZE];
#endif
static int sysctl_ipf_int ( SYSCTL_HANDLER_ARGS );
static int ipf_modload(void);
static int ipf_modunload(void);
SYSCTL_DECL(_net_inet);
#define SYSCTL_IPF(parent, nbr, name, access, ptr, val, descr) \
SYSCTL_OID(parent, nbr, name, CTLTYPE_INT|access, \
ptr, val, sysctl_ipf_int, "I", descr);
#define CTLFLAG_OFF 0x00800000 /* IPFilter must be disabled */
#define CTLFLAG_RWO (CTLFLAG_RW|CTLFLAG_OFF)
SYSCTL_NODE(_net_inet, OID_AUTO, ipf, CTLFLAG_RW, 0, "IPF");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &fr_flags, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_pass, CTLFLAG_RW, &fr_pass, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &fr_active, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RW,
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &fr_flags, 0, "");
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_pass, CTLFLAG_RW, &fr_pass, 0, "");
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &fr_active, 0, "");
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RWO,
&fr_tcpidletimeout, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RW,
&fr_tcpclosewait, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RW,
&fr_tcplastack, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RW,
&fr_tcptimeout, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RW,
&fr_tcpclosed, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RW,
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RWO,
&fr_tcphalfclosed, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RW,
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RWO,
&fr_tcpclosewait, 0, "");
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RWO,
&fr_tcplastack, 0, "");
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RWO,
&fr_tcptimeout, 0, "");
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RWO,
&fr_tcpclosed, 0, "");
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RWO,
&fr_udptimeout, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_udpacktimeout, CTLFLAG_RW,
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udpacktimeout, CTLFLAG_RWO,
&fr_udpacktimeout, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RW,
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RWO,
&fr_icmptimeout, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_icmpacktimeout, CTLFLAG_RW,
&fr_icmpacktimeout, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_defnatage, CTLFLAG_RW,
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defnatage, CTLFLAG_RWO,
&fr_defnatage, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_ipfrttl, CTLFLAG_RW,
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_ipfrttl, CTLFLAG_RW,
&fr_ipfrttl, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, ipl_unreach, CTLFLAG_RW,
&ipl_unreach, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_running, CTLFLAG_RD,
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_running, CTLFLAG_RD,
&fr_running, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_authsize, CTLFLAG_RD,
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statesize, CTLFLAG_RWO,
&fr_statesize, 0, "");
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statemax, CTLFLAG_RWO,
&fr_statemax, 0, "");
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_nattable_sz, CTLFLAG_RWO,
&ipf_nattable_sz, 0, "");
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_natrules_sz, CTLFLAG_RWO,
&ipf_natrules_sz, 0, "");
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_rdrrules_sz, CTLFLAG_RWO,
&ipf_rdrrules_sz, 0, "");
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_hostmap_sz, CTLFLAG_RWO,
&ipf_hostmap_sz, 0, "");
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authsize, CTLFLAG_RWO,
&fr_authsize, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_authused, CTLFLAG_RD,
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authused, CTLFLAG_RD,
&fr_authused, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_defaultauthage, CTLFLAG_RW,
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defaultauthage, CTLFLAG_RW,
&fr_defaultauthage, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &fr_chksrc, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, ippr_ftp_pasvonly, CTLFLAG_RW,
&ippr_ftp_pasvonly, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &fr_minttl, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_minttllog, CTLFLAG_RW,
&fr_minttllog, 0, "");
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &fr_chksrc, 0, "");
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &fr_minttl, 0, "");
#define CDEV_MAJOR 79
#if __FreeBSD_version >= 501000
static struct cdevsw ipl_cdevsw = {
# if __FreeBSD_version >= 502103
.d_version = D_VERSION,
.d_flags = 0,
.d_flags = 0, /* D_NEEDGIANT - Should be SMP safe */
# endif
.d_open = iplopen,
.d_close = iplclose,
.d_read = iplread,
.d_ioctl = iplioctl,
.d_name = "ipl",
# if __FreeBSD_version < 600000
.d_maj = CDEV_MAJOR,
# endif
};
#else
static struct cdevsw ipl_cdevsw = {
/* open */ iplopen,
/* close */ iplclose,
/* read */ iplread,
/* write */ iplwrite,
/* ioctl */ iplioctl,
/* poll */ nopoll,
/* mmap */ nommap,
/* strategy */ nostrategy,
/* name */ "ipl",
/* maj */ CDEV_MAJOR,
/* dump */ nodump,
/* psize */ nopsize,
/* flags */ 0,
# if (__FreeBSD_version < 500043)
/* bmaj */ -1,
# endif
/* kqfilter */ NULL
};
#if (__FreeBSD_version >= 500000)
kmutex_t ipl_mutex, ipf_rw;
KRWLOCK_T ipf_mutex, ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth;
#endif
static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, IPAUTH_NAME,
IPSYNC_NAME, IPSCAN_NAME, IPLOOKUP_NAME, NULL };
static int
ipfilter_modevent(module_t mod, int type, void *unused)
{
char *c;
int i, error = 0;
int error = 0;
switch (type) {
switch (type)
{
case MOD_LOAD :
error = iplattach();
if (error)
break;
#if (__FreeBSD_version >= 500000)
MUTEX_INIT(&ipl_mutex, "ipf log mutex", NULL);
MUTEX_INIT(&ipf_rw, "ipf rw mutex", NULL);
RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock", NULL);
RWLOCK_INIT(&ipf_frag, "ipf fragment rwlock", NULL);
RWLOCK_INIT(&ipf_state, "ipf IP state rwlock", NULL);
RWLOCK_INIT(&ipf_nat, "ipf IP NAT rwlock", NULL);
RWLOCK_INIT(&ipf_natfrag, "ipf IP NAT-Frag rwlock", NULL);
RWLOCK_INIT(&ipf_auth, "ipf User-Auth rwlock", NULL);
#endif
c = NULL;
for(i = strlen(IPL_NAME); i > 0; i--)
if (IPL_NAME[i] == '/') {
c = &IPL_NAME[i + 1];
break;
}
if (!c)
c = IPL_NAME;
ipf_devs[IPL_LOGIPF] =
make_dev(&ipl_cdevsw, IPL_LOGIPF, 0, 0, 0600, c);
c = NULL;
for(i = strlen(IPL_NAT); i > 0; i--)
if (IPL_NAT[i] == '/') {
c = &IPL_NAT[i + 1];
break;
}
if (!c)
c = IPL_NAT;
ipf_devs[IPL_LOGNAT] =
make_dev(&ipl_cdevsw, IPL_LOGNAT, 0, 0, 0600, c);
c = NULL;
for(i = strlen(IPL_STATE); i > 0; i--)
if (IPL_STATE[i] == '/') {
c = &IPL_STATE[i + 1];
break;
}
if (!c)
c = IPL_STATE;
ipf_devs[IPL_LOGSTATE] =
make_dev(&ipl_cdevsw, IPL_LOGSTATE, 0, 0, 0600, c);
c = NULL;
for(i = strlen(IPL_AUTH); i > 0; i--)
if (IPL_AUTH[i] == '/') {
c = &IPL_AUTH[i + 1];
break;
}
if (!c)
c = IPL_AUTH;
ipf_devs[IPL_LOGAUTH] =
make_dev(&ipl_cdevsw, IPL_LOGAUTH, 0, 0, 0600, c);
error = ipf_modload();
break;
case MOD_UNLOAD :
destroy_dev(ipf_devs[IPL_LOGIPF]);
destroy_dev(ipf_devs[IPL_LOGNAT]);
destroy_dev(ipf_devs[IPL_LOGSTATE]);
destroy_dev(ipf_devs[IPL_LOGAUTH]);
error = ipldetach();
error = ipf_modunload();
break;
default:
error = EINVAL;
@ -200,9 +156,119 @@ ipfilter_modevent(module_t mod, int type, void *unused)
return error;
}
static int
ipf_modload()
{
char *defpass, *c, *str;
int i, j, error;
error = iplattach();
if (error)
return error;
for (i = 0; i < IPL_LOGSIZE; i++)
ipf_devs[i] = NULL;
for (i = 0; (str = ipf_devfiles[i]); i++) {
c = NULL;
for(j = strlen(str); j > 0; j--)
if (str[j] == '/') {
c = str + j + 1;
break;
}
if (!c)
c = str;
ipf_devs[i] = make_dev(&ipl_cdevsw, i, 0, 0, 0600, c);
}
if (FR_ISPASS(fr_pass))
defpass = "pass";
else if (FR_ISBLOCK(fr_pass))
defpass = "block";
else
defpass = "no-match -> block";
printf("%s initialized. Default = %s all, Logging = %s%s\n",
ipfilter_version, defpass,
#ifdef IPFILTER_LOG
"enabled",
#else
"disabled",
#endif
#ifdef IPFILTER_COMPILED
" (COMPILED)"
#else
""
#endif
);
return 0;
}
static int
ipf_modunload()
{
int error, i;
if (fr_refcnt)
return EBUSY;
if (fr_running >= 0) {
error = ipldetach();
if (error != 0)
return error;
} else
error = 0;
fr_running = -2;
for (i = 0; ipf_devfiles[i]; i++) {
if (ipf_devs[i] != NULL)
destroy_dev(ipf_devs[i]);
}
printf("%s unloaded\n", ipfilter_version);
return error;
}
static moduledata_t ipfiltermod = {
IPL_VERSION,
"ipfilter",
ipfilter_modevent,
0
0
};
DECLARE_MODULE(ipfilter, ipfiltermod, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY);
#ifdef MODULE_VERSION
MODULE_VERSION(ipfilter, 1);
#endif
#ifdef SYSCTL_IPF
int
sysctl_ipf_int ( SYSCTL_HANDLER_ARGS )
{
int error = 0;
if (arg1)
error = SYSCTL_OUT(req, arg1, sizeof(int));
else
error = SYSCTL_OUT(req, &arg2, sizeof(int));
if (error || !req->newptr)
return (error);
if (!arg1)
error = EPERM;
else {
if ((oidp->oid_kind & CTLFLAG_OFF) && (fr_running > 0))
error = EBUSY;
else
error = SYSCTL_IN(req, arg1, sizeof(int));
}
return (error);
}
#endif