As per the developers handbook (5.3.1 step 1), prepare the vendor trees for

import of new ipfilter vendor sources by flattening them.

To keep the tags consistent with dist, the tags are also flattened.

Approved by:	glebius (Mentor)
This commit is contained in:
Cy Schubert
2013-07-19 05:41:57 +00:00
parent e8e48c1c7b
commit 850b82f47b
45 changed files with 0 additions and 762 deletions
@@ -1,29 +0,0 @@
/*
* Copyright (C) 1993-2001 by Darren Reed.
*
* The author accepts no responsibility for the use of this software and
* provides it on an ``as is'' basis without express or implied warranty.
*
* Redistribution and use, with or without modification, in source and binary
* forms, are permitted provided that this notice is preserved in its entirety
* and due credit is given to the original author and the contributors.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied, in part or in whole, and put under another distribution licence
* [including the GNU Public Licence.]
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 AUTHOR 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.
*
* I hate legalese, don't you ?
*/
-275
View File
@@ -1,275 +0,0 @@
End User License Certificate (EULA) End User License Certificate
(EULA)
Support Support
QNX Source Licenses QNX Source Licenses
License of the month
Confidential Source License
Version 1.0
QNX Open Community License Version 1.0
THIS QNX OPEN COMMUNITY LICENSE ( "THE OCL", OR "THIS AGREEMENT")
APPLIES TO PROGRAMS THAT QNX SOFTWARE SYSTEMS LTD. ("QSS") EXPRESSLY
ELECTS TO LICENSE UNDER THE OCL TERMS. IT ALSO APPLIES TO DERIVATIVE
WORKS CREATED UNDER THIS AGREEMENT THAT CREATORS ELECT TO LICENSE TO
OTHERS IN SOURCE CODE FORM. ANY USE, REPRODUCTION, MODIFICATION OR
DISTRIBUTION OF SUCH PROGRAMS CONSTITUTES RECIPIENT'S ACCEPTANCE OF
THE OCL. THE LICENSE RIGHTS GRANTED BELOW ARE CONDITIONAL UPON
RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT AND THE FORMATION OF A
BINDING CONTRACT. NOTHING ELSE GRANTS PERMISSION TO USE, REPRODUCE,
MODIFY OR DISTRIBUTE SUCH PROGRAMS OR THEIR DERIVATIVE WORKS. THESE
ACTIONS ARE OTHERWISE PROHIBITED. CONTACT QSS IF OTHER STEPS ARE
REQUIRED LOCALLY TO CREATE A BINDING CONTRACT.
The OCL is intended to promote the development, use and distribution
of derivative works created from QSS source code. This includes
commercial distribution of object code versions under the terms of
Recipient's own license agreement and, at Recipient's option, sharing
of source code modifications within the QNX developer's community. The
license granted under the OCL is royalty free. Recipient is entitled
to charge royalties for object code versions of derivative works that
originate with Recipient. If Recipient elects to license source code
for its derivative works to others, then it must be licensed under the
OCL. The terms of the OCL are as follows:
1. DEFINITIONS
"Contribution" means:
a. in the case of QSS: (i) the Original Program, where the Original
Program originates from QSS, (ii) changes and/or additions to
Unrestricted Open Source, where the Original Program originates
from Unrestricted Open Source and where such changes and/or
additions originate from QSS, and (iii) changes and/or additions
to the Program where such changes and/or additions originate from
QSS.
b. in the case of each Contributor, changes and/or additions to the
Program, where such changes and/or additions originate from and
are distributed by that particular Contributor.
A Contribution 'originates' from a Contributor if it was added to the
Program by such Contributor itself or anyone acting on such
Contributor's behalf. Contributions do not include additions to the
Program which: (i) are separate modules of software distributed in
conjunction with the Program under their own license agreement, and
(ii) are not derivative works of the Program.
"Contributor" means QSS and any other entity that distributes the
Program.
"Licensed Patents " mean patent claims licensable by Contributor to
others, which are necessarily infringed by the use or sale of its
Contribution alone or when combined with the Program.
"Unrestricted Open Source" means published source code that is
licensed for free use and distribution under an unrestricted licensing
and distribution model, such as the Berkley Software Design ("BSD")
and "BSD-like" licenses. It specifically excludes any source code
licensed under any version of the GNU General Public License (GPL) or
the GNU Lesser/Library GPL. All "Unrestricted Open Source" license
terms appear or are clearly identified in the header of any affected
source code for the Original Program.
"Original Program" means the original version of the software
accompanying this Agreement as released by QSS, including source code,
object code and documentation, if any.
"Program" means the Original Program and Contributions.
"Recipient" means anyone who receives the Program under this
Agreement, including all Contributors.
2. GRANT OF RIGHTS
a. Subject to the terms of this Agreement, each Contributor hereby
grants Recipient a non-exclusive, worldwide, royalty-free
copyright license to reproduce, prepare derivative works of,
publicly display, publicly perform, and directly and indirectly
sublicense and distribute the Contribution of such Contributor, if
any, and such derivative works, in source code and object code
form.
b. Subject to the terms of this Agreement, each Contributor hereby
grants Recipient a non-exclusive, worldwide, royalty-free patent
license under Licensed Patents to make, use, sell, offer to sell,
import and otherwise transfer the Contribution of such
Contributor, if any, in source code and object code form. This
patent license shall apply to the combination of the Contribution
and the Program if, at the time the Contribution is added by the
Contributor, such addition of the Contribution causes such
combination to be covered by the Licensed Patents. The patent
license shall not apply to any other combinations which include
the Contribution.
c. Recipient understands that although each Contributor grants the
licenses to its Contributions set forth herein, no assurances are
provided by any Contributor that the Program does not infringe the
patent or other intellectual property rights of any other entity.
Each Contributor disclaims any liability to Recipient for claims
brought by any other entity based on infringement of intellectual
property rights or otherwise. As a condition to exercising the
rights and licenses granted hereunder, each Recipient hereby
assumes sole responsibility to secure any other intellectual
property rights needed, if any. For example, if a third party
patent license is required to allow Recipient to distribute the
Program, it is Recipient's responsibility to acquire that license
before distributing the Program.
d. Each Contributor represents that to its knowledge it has
sufficient copyright rights in its Contribution, if any, to grant
the copyright license set forth in this Agreement.
3. REQUIREMENTS
A Contributor may choose to distribute the Program in object code form
under its own license agreement, provided that:
a. it complies with the terms and conditions of this Agreement; and
b. its license agreement:
i. effectively disclaims on behalf of all Contributors all
warranties and conditions, express and implied, including
warranties or conditions of title and non-infringement, and
implied warranties or conditions of merchantability and
fitness for a particular purpose;
ii. effectively excludes on behalf of all Contributors all
liability for damages, including direct, indirect, special,
incidental and consequential damages, such as lost profits;
and
iii. states that any provisions which differ from this Agreement
are offered by that Contributor alone and not by any other
party.
If the Program is made available in source code form:
a. it must be made available under this Agreement; and
b. a copy of this Agreement must be included with each copy of the
Program. Each Contributor must include the following in a
conspicuous location in the Program along with any other copyright
or attribution statements required by the terms of any applicable
Unrestricted Open Source license:
Copyright {date here}, QNX Software Systems Ltd. and others. All
Rights Reserved.
In addition, each Contributor must identify itself as the originator
of its Contribution, if any, in a manner that reasonably allows
subsequent Recipients to identify the originator of the Contribution.
4. COMMERCIAL DISTRIBUTION
Commercial distributors of software may accept certain
responsibilities with respect to end users, business partners and the
like. While this license is intended to facilitate the commercial use
of the Program, the Contributor who includes the Program in a
commercial product offering should do so in a manner which does not
create potential liability for other Contributors. Therefore, if a
Contributor includes the Program in a commercial product offering,
such Contributor ("Commercial Contributor") hereby agrees to defend
and indemnify every other Contributor ("Indemnified Contributor")
against any losses, damages and costs (collectively "Losses") arising
from claims, lawsuits and other legal actions brought by a third party
against the Indemnified Contributor to the extent caused by the acts
or omissions of such Commercial Contributor in connection with its
distribution of the Program in a commercial product offering. The
obligations in this section do not apply to any claims or Losses
relating to any actual or alleged intellectual property infringement.
In order to qualify, an Indemnified Contributor must: a) promptly
notify the Commercial Contributor in writing of such claim, and b)
allow the Commercial Contributor to control, and cooperate with the
Commercial Contributor in, the defense and any related settlement
negotiations. The Indemnified Contributor may participate in any such
claim at its own expense.
For example, a Contributor might include the Program in a commercial
product offering, Product X. That Contributor is then a Commercial
Contributor. If that Commercial Contributor then makes performance
claims, or offers warranties related to Product X, those performance
claims and warranties are such Commercial Contributor's responsibility
alone. Under this section, the Commercial Contributor would have to
defend claims against the other Contributors related to those
performance claims and warranties, and if a court requires any other
Contributor to pay any damages as a result, the Commercial Contributor
must pay those damages.
5. NO WARRANTY
Recipient acknowledges that there may be errors or bugs in the Program
and that it is imperative that Recipient conduct thorough testing to
identify and correct any problems prior to the productive use or
commercial release of any products that use the Program, and prior to
the release of any modifications, updates or enhancements thereto.
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
WARRANTIES OR CONDITIONS OF TITLE, NON- INFRINGEMENT, MERCHANTABILITY
OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
responsible for determining the appropriateness of using and
distributing the Program and assumes all risks associated with its
exercise of rights under this Agreement, including but not limited to
the risks and costs of program errors, compliance with applicable
laws, damage to or loss of data, programs or equipment, and
unavailability or interruption of operations.
6. DISCLAIMER OF LIABILITY
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
WITHOUT LIMITATION LOST PROFITS), 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 OR
DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
7. GENERAL
If any provision of this Agreement is invalid or unenforceable under
applicable law, it shall not affect the validity or enforceability of
the remainder of the terms of this Agreement, and without further
action by the parties hereto, such provision shall be reformed to the
minimum extent necessary to make such provision valid and enforceable.
If Recipient institutes patent litigation against a Contributor with
respect to a patent applicable to software (including a cross-claim or
counterclaim in a lawsuit), then any patent licenses granted by that
Contributor to such recipient under this Agreement shall terminate as
of the date such litigation is filed. In addition, If Recipient
institutes patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Program
itself (excluding combinations of the Program with other software or
hardware) infringes such Recipient's patent(s), then such Recipient's
rights granted under Section 2(b) shall terminate as of the date such
litigation is filed.
All Recipient's rights under this Agreement shall terminate if it
fails to comply with any of the material terms or conditions of this
Agreement and does not cure such failure in a reasonable period of
time after becoming aware of such noncompliance. If all Recipient's
rights under this Agreement terminate, Recipient agrees to cease use
and distribution of the Program as soon as reasonably practicable.
However, Recipient's obligations under this Agreement and any licenses
granted by Recipient relating to the Program shall continue and
survive.
QSS may publish new versions (including revisions) of this Agreement
from time to time. Each new version of the Agreement will be given a
distinguishing version number. The Program (including Contributions)
may always be distributed subject to the version of the Agreement
under which it was received. In addition, after a new version of the
Agreement is published, Contributor may elect to distribute the
Program (including its Contributions) under the new version. No one
other than QSS has the right to modify this Agreement. Except as
expressly stated in Sections 2(a) and 2(b) above, Recipient receives
no rights or licenses to the intellectual property of any Contributor
under this Agreement, whether expressly, by implication, estoppel or
otherwise. All rights in the Program not expressly granted under this
Agreement are reserved.
This Agreement is governed by the laws in force in the Province of
Ontario, Canada without regard to the conflict of law provisions
therein. The parties expressly disclaim the provisions of the United
Nations Convention on Contracts for the International Sale of Goods.
No party to this Agreement will bring a legal action under this
Agreement more than one year after the cause of action arose. Each
party waives its rights to a jury trial in any resulting litigation.
* QNX is a registered trademark of QNX Software Systems Ltd.
Document Version: ocl1_00
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-68
View File
@@ -1,68 +0,0 @@
/*
* Copyright (C) 1997-2001 by Darren Reed & Guido Van Rooij.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* $Id: ip_auth.h,v 2.16.2.3 2006/07/14 06:12:05 darrenr Exp $
*
*/
#ifndef __IP_AUTH_H__
#define __IP_AUTH_H__
#define FR_NUMAUTH 32
typedef struct frauth {
int fra_age;
int fra_len;
int fra_index;
u_32_t fra_pass;
fr_info_t fra_info;
char *fra_buf;
#ifdef MENTAT
queue_t *fra_q;
mb_t *fra_m;
#endif
} frauth_t;
typedef struct frauthent {
struct frentry fae_fr;
struct frauthent *fae_next;
struct frauthent **fae_pnext;
u_long fae_age;
int fae_ref;
} frauthent_t;
typedef struct fr_authstat {
U_QUAD_T fas_hits;
U_QUAD_T fas_miss;
u_long fas_nospace;
u_long fas_added;
u_long fas_sendfail;
u_long fas_sendok;
u_long fas_queok;
u_long fas_quefail;
u_long fas_expire;
frauthent_t *fas_faelist;
} fr_authstat_t;
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 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 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, int, void *));
extern int fr_auth_waiting __P((void));
#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
-990
View File
@@ -1,990 +0,0 @@
/*
* Copyright (C) 1993-2003 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*/
#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>
#ifdef __hpux
# include <sys/timeout.h>
#endif
#if !defined(_KERNEL)
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# define _KERNEL
# ifdef __OpenBSD__
struct file;
# endif
# include <sys/uio.h>
# undef _KERNEL
#endif
#if defined(_KERNEL) && (__FreeBSD_version >= 220000)
# include <sys/filio.h>
# include <sys/fcntl.h>
#else
# include <sys/ioctl.h>
#endif
#if !defined(linux)
# include <sys/protosw.h>
#endif
#include <sys/socket.h>
#if defined(_KERNEL)
# include <sys/systm.h>
# if !defined(__SVR4) && !defined(__svr4__)
# include <sys/mbuf.h>
# endif
#endif
#if !defined(__SVR4) && !defined(__svr4__)
# if defined(_KERNEL) && !defined(__sgi) && !defined(AIX)
# include <sys/kernel.h>
# endif
#else
# include <sys/byteorder.h>
# ifdef _KERNEL
# include <sys/dditypes.h>
# endif
# include <sys/stream.h>
# include <sys/kmem.h>
#endif
#include <net/if.h>
#ifdef sun
# include <net/af.h>
#endif
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#if !defined(linux)
# include <netinet/ip_var.h>
#endif
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#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"
#include "netinet/ip_proxy.h"
#if (__FreeBSD_version >= 300000)
# include <sys/malloc.h>
# if defined(_KERNEL)
# ifndef IPFILTER_LKM
# include <sys/libkern.h>
# include <sys/systm.h>
# endif
extern struct callout_handle fr_slowtimer_ch;
# endif
#endif
#if defined(__NetBSD__) && (__NetBSD_Version__ >= 104230000)
# include <sys/callout.h>
extern struct callout fr_slowtimer_ch;
#endif
#if defined(__OpenBSD__)
# include <sys/timeout.h>
extern struct timeout fr_slowtimer_ch;
#endif
/* END OF INCLUDES */
#if !defined(lint)
static const char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-2000 Darren Reed";
static const char rcsid[] = "@(#)$Id: ip_frag.c,v 2.77.2.12 2007/09/20 12:51:51 darrenr Exp $";
#endif
ipfr_t *ipfr_list = NULL;
ipfr_t **ipfr_tail = &ipfr_list;
ipfr_t *ipfr_natlist = NULL;
ipfr_t **ipfr_nattail = &ipfr_natlist;
ipfr_t *ipfr_ipidlist = NULL;
ipfr_t **ipfr_ipidtail = &ipfr_ipidlist;
static ipfr_t **ipfr_heads;
static ipfr_t **ipfr_nattab;
static ipfr_t **ipfr_ipidtab;
static ipfrstat_t ipfr_stats;
static int ipfr_inuse = 0;
int ipfr_size = IPFT_SIZE;
int fr_ipfrttl = 120; /* 60 seconds */
int fr_frag_lock = 0;
int fr_frag_init = 0;
u_long fr_ticks = 0;
static ipfr_t *ipfr_newfrag __P((fr_info_t *, u_32_t, ipfr_t **));
static ipfr_t *fr_fraglookup __P((fr_info_t *, ipfr_t **));
static void fr_fragdelete __P((ipfr_t *, ipfr_t ***));
static void fr_fragfree __P((ipfr_t *));
/* ------------------------------------------------------------------------ */
/* Function: fr_fraginit */
/* Returns: int - 0 == success, -1 == error */
/* Parameters: Nil */
/* */
/* Initialise the hash tables for the fragment cache lookups. */
/* ------------------------------------------------------------------------ */
int fr_fraginit()
{
KMALLOCS(ipfr_heads, ipfr_t **, ipfr_size * sizeof(ipfr_t *));
if (ipfr_heads == NULL)
return -1;
bzero((char *)ipfr_heads, ipfr_size * sizeof(ipfr_t *));
KMALLOCS(ipfr_nattab, ipfr_t **, ipfr_size * sizeof(ipfr_t *));
if (ipfr_nattab == NULL)
return -1;
bzero((char *)ipfr_nattab, ipfr_size * sizeof(ipfr_t *));
KMALLOCS(ipfr_ipidtab, ipfr_t **, ipfr_size * sizeof(ipfr_t *));
if (ipfr_ipidtab == NULL)
return -1;
bzero((char *)ipfr_ipidtab, ipfr_size * sizeof(ipfr_t *));
RWLOCK_INIT(&ipf_frag, "ipf fragment rwlock");
fr_frag_init = 1;
return 0;
}
/* ------------------------------------------------------------------------ */
/* Function: fr_fragunload */
/* Returns: Nil */
/* Parameters: Nil */
/* */
/* Free all memory allocated whilst running and from initialisation. */
/* ------------------------------------------------------------------------ */
void fr_fragunload()
{
if (fr_frag_init == 1) {
fr_fragclear();
RW_DESTROY(&ipf_frag);
fr_frag_init = 0;
}
if (ipfr_heads != NULL)
KFREES(ipfr_heads, ipfr_size * sizeof(ipfr_t *));
ipfr_heads = NULL;
if (ipfr_nattab != NULL)
KFREES(ipfr_nattab, ipfr_size * sizeof(ipfr_t *));
ipfr_nattab = NULL;
if (ipfr_ipidtab != NULL)
KFREES(ipfr_ipidtab, ipfr_size * sizeof(ipfr_t *));
ipfr_ipidtab = NULL;
}
/* ------------------------------------------------------------------------ */
/* Function: fr_fragstats */
/* Returns: ipfrstat_t* - pointer to struct with current frag stats */
/* Parameters: Nil */
/* */
/* Updates ipfr_stats with current information and returns a pointer to it */
/* ------------------------------------------------------------------------ */
ipfrstat_t *fr_fragstats()
{
ipfr_stats.ifs_table = ipfr_heads;
ipfr_stats.ifs_nattab = ipfr_nattab;
ipfr_stats.ifs_inuse = ipfr_inuse;
return &ipfr_stats;
}
/* ------------------------------------------------------------------------ */
/* Function: ipfr_newfrag */
/* Returns: ipfr_t * - pointer to fragment cache state info or NULL */
/* Parameters: fin(I) - pointer to packet information */
/* table(I) - pointer to frag table to add to */
/* */
/* Add a new entry to the fragment cache, registering it as having come */
/* through this box, with the result of the filter operation. */
/* ------------------------------------------------------------------------ */
static ipfr_t *ipfr_newfrag(fin, pass, table)
fr_info_t *fin;
u_32_t pass;
ipfr_t *table[];
{
ipfr_t *fra, frag;
u_int idx, off;
frentry_t *fr;
ip_t *ip;
if (ipfr_inuse >= IPFT_SIZE)
return NULL;
if ((fin->fin_flx & (FI_FRAG|FI_BAD)) != FI_FRAG)
return NULL;
ip = fin->fin_ip;
if (pass & FR_FRSTRICT)
if (fin->fin_off != 0)
return NULL;
frag.ipfr_p = ip->ip_p;
idx = ip->ip_p;
frag.ipfr_id = ip->ip_id;
idx += ip->ip_id;
frag.ipfr_tos = ip->ip_tos;
frag.ipfr_src.s_addr = ip->ip_src.s_addr;
idx += ip->ip_src.s_addr;
frag.ipfr_dst.s_addr = ip->ip_dst.s_addr;
idx += ip->ip_dst.s_addr;
frag.ipfr_ifp = fin->fin_ifp;
idx *= 127;
idx %= IPFT_SIZE;
frag.ipfr_optmsk = fin->fin_fi.fi_optmsk & IPF_OPTCOPY;
frag.ipfr_secmsk = fin->fin_fi.fi_secmsk;
frag.ipfr_auth = fin->fin_fi.fi_auth;
/*
* first, make sure it isn't already there...
*/
for (fra = table[idx]; (fra != NULL); fra = fra->ipfr_hnext)
if (!bcmp((char *)&frag.ipfr_ifp, (char *)&fra->ipfr_ifp,
IPFR_CMPSZ)) {
ipfr_stats.ifs_exists++;
return NULL;
}
/*
* allocate some memory, if possible, if not, just record that we
* failed to do so.
*/
KMALLOC(fra, ipfr_t *);
if (fra == NULL) {
ipfr_stats.ifs_nomem++;
return NULL;
}
fr = fin->fin_fr;
fra->ipfr_rule = fr;
if (fr != NULL) {
MUTEX_ENTER(&fr->fr_lock);
fr->fr_ref++;
MUTEX_EXIT(&fr->fr_lock);
}
/*
* Insert the fragment into the fragment table, copy the struct used
* in the search using bcopy rather than reassign each field.
* Set the ttl to the default.
*/
if ((fra->ipfr_hnext = table[idx]) != NULL)
table[idx]->ipfr_hprev = &fra->ipfr_hnext;
fra->ipfr_hprev = table + idx;
fra->ipfr_data = NULL;
table[idx] = fra;
bcopy((char *)&frag.ipfr_ifp, (char *)&fra->ipfr_ifp, IPFR_CMPSZ);
fra->ipfr_ttl = fr_ticks + fr_ipfrttl;
/*
* Compute the offset of the expected start of the next packet.
*/
off = ip->ip_off & IP_OFFMASK;
if (off == 0)
fra->ipfr_seen0 = 1;
fra->ipfr_off = off + (fin->fin_dlen >> 3);
fra->ipfr_pass = pass;
fra->ipfr_ref = 1;
ipfr_stats.ifs_new++;
ipfr_inuse++;
return fra;
}
/* ------------------------------------------------------------------------ */
/* Function: fr_newfrag */
/* Returns: int - 0 == success, -1 == error */
/* Parameters: fin(I) - pointer to packet information */
/* */
/* Add a new entry to the fragment cache table based on the current packet */
/* ------------------------------------------------------------------------ */
int fr_newfrag(fin, pass)
u_32_t pass;
fr_info_t *fin;
{
ipfr_t *fra;
if ((fin->fin_v != 4) || (fr_frag_lock != 0))
return -1;
WRITE_ENTER(&ipf_frag);
fra = ipfr_newfrag(fin, pass, ipfr_heads);
if (fra != NULL) {
*ipfr_tail = fra;
fra->ipfr_prev = ipfr_tail;
ipfr_tail = &fra->ipfr_next;
if (ipfr_list == NULL)
ipfr_list = fra;
fra->ipfr_next = NULL;
}
RWLOCK_EXIT(&ipf_frag);
return fra ? 0 : -1;
}
/* ------------------------------------------------------------------------ */
/* Function: fr_nat_newfrag */
/* Returns: int - 0 == success, -1 == error */
/* Parameters: fin(I) - pointer to packet information */
/* nat(I) - pointer to NAT structure */
/* */
/* Create a new NAT fragment cache entry based on the current packet and */
/* the NAT structure for this "session". */
/* ------------------------------------------------------------------------ */
int fr_nat_newfrag(fin, pass, nat)
fr_info_t *fin;
u_32_t pass;
nat_t *nat;
{
ipfr_t *fra;
if ((fin->fin_v != 4) || (fr_frag_lock != 0))
return 0;
WRITE_ENTER(&ipf_natfrag);
fra = ipfr_newfrag(fin, pass, ipfr_nattab);
if (fra != NULL) {
fra->ipfr_data = nat;
nat->nat_data = fra;
*ipfr_nattail = fra;
fra->ipfr_prev = ipfr_nattail;
ipfr_nattail = &fra->ipfr_next;
fra->ipfr_next = NULL;
}
RWLOCK_EXIT(&ipf_natfrag);
return fra ? 0 : -1;
}
/* ------------------------------------------------------------------------ */
/* Function: fr_ipid_newfrag */
/* Returns: int - 0 == success, -1 == error */
/* Parameters: fin(I) - pointer to packet information */
/* ipid(I) - new IP ID for this fragmented packet */
/* */
/* Create a new fragment cache entry for this packet and store, as a data */
/* pointer, the new IP ID value. */
/* ------------------------------------------------------------------------ */
int fr_ipid_newfrag(fin, ipid)
fr_info_t *fin;
u_32_t ipid;
{
ipfr_t *fra;
if ((fin->fin_v != 4) || (fr_frag_lock))
return 0;
WRITE_ENTER(&ipf_ipidfrag);
fra = ipfr_newfrag(fin, 0, ipfr_ipidtab);
if (fra != NULL) {
fra->ipfr_data = (void *)((u_long)ipid);
*ipfr_ipidtail = fra;
fra->ipfr_prev = ipfr_ipidtail;
ipfr_ipidtail = &fra->ipfr_next;
fra->ipfr_next = NULL;
}
RWLOCK_EXIT(&ipf_ipidfrag);
return fra ? 0 : -1;
}
/* ------------------------------------------------------------------------ */
/* Function: fr_fraglookup */
/* Returns: ipfr_t * - pointer to ipfr_t structure if there's a */
/* matching entry in the frag table, else NULL */
/* Parameters: fin(I) - pointer to packet information */
/* table(I) - pointer to fragment cache table to search */
/* */
/* Check the fragment cache to see if there is already a record of this */
/* packet with its filter result known. */
/* ------------------------------------------------------------------------ */
static ipfr_t *fr_fraglookup(fin, table)
fr_info_t *fin;
ipfr_t *table[];
{
ipfr_t *f, frag;
u_int idx;
ip_t *ip;
if ((fin->fin_flx & (FI_FRAG|FI_BAD)) != FI_FRAG)
return NULL;
/*
* For fragments, we record protocol, packet id, TOS and both IP#'s
* (these should all be the same for all fragments of a packet).
*
* build up a hash value to index the table with.
*/
ip = fin->fin_ip;
frag.ipfr_p = ip->ip_p;
idx = ip->ip_p;
frag.ipfr_id = ip->ip_id;
idx += ip->ip_id;
frag.ipfr_tos = ip->ip_tos;
frag.ipfr_src.s_addr = ip->ip_src.s_addr;
idx += ip->ip_src.s_addr;
frag.ipfr_dst.s_addr = ip->ip_dst.s_addr;
idx += ip->ip_dst.s_addr;
frag.ipfr_ifp = fin->fin_ifp;
idx *= 127;
idx %= IPFT_SIZE;
frag.ipfr_optmsk = fin->fin_fi.fi_optmsk & IPF_OPTCOPY;
frag.ipfr_secmsk = fin->fin_fi.fi_secmsk;
frag.ipfr_auth = fin->fin_fi.fi_auth;
/*
* check the table, careful to only compare the right amount of data
*/
for (f = table[idx]; f; f = f->ipfr_hnext)
if (!bcmp((char *)&frag.ipfr_ifp, (char *)&f->ipfr_ifp,
IPFR_CMPSZ)) {
u_short off;
/*
* We don't want to let short packets match because
* they could be compromising the security of other
* rules that want to match on layer 4 fields (and
* can't because they have been fragmented off.)
* Why do this check here? The counter acts as an
* indicator of this kind of attack, whereas if it was
* elsewhere, it wouldn't know if other matching
* packets had been seen.
*/
if (fin->fin_flx & FI_SHORT) {
ATOMIC_INCL(ipfr_stats.ifs_short);
continue;
}
/*
* XXX - We really need to be guarding against the
* retransmission of (src,dst,id,offset-range) here
* because a fragmented packet is never resent with
* the same IP ID# (or shouldn't).
*/
off = ip->ip_off & IP_OFFMASK;
if (f->ipfr_seen0) {
if (off == 0) {
ATOMIC_INCL(ipfr_stats.ifs_retrans0);
continue;
}
} else if (off == 0)
f->ipfr_seen0 = 1;
if (f != table[idx]) {
ipfr_t **fp;
/*
* Move fragment info. to the top of the list
* to speed up searches. First, delink...
*/
fp = f->ipfr_hprev;
(*fp) = f->ipfr_hnext;
if (f->ipfr_hnext != NULL)
f->ipfr_hnext->ipfr_hprev = fp;
/*
* Then put back at the top of the chain.
*/
f->ipfr_hnext = table[idx];
table[idx]->ipfr_hprev = &f->ipfr_hnext;
f->ipfr_hprev = table + idx;
table[idx] = f;
}
/*
* If we've follwed the fragments, and this is the
* last (in order), shrink expiration time.
*/
if (off == f->ipfr_off) {
if (!(ip->ip_off & IP_MF))
f->ipfr_ttl = fr_ticks + 1;
f->ipfr_off = (fin->fin_dlen >> 3) + off;
} else if (f->ipfr_pass & FR_FRSTRICT)
continue;
ATOMIC_INCL(ipfr_stats.ifs_hits);
return f;
}
return NULL;
}
/* ------------------------------------------------------------------------ */
/* Function: fr_nat_knownfrag */
/* Returns: nat_t* - pointer to 'parent' NAT structure if frag table */
/* match found, else NULL */
/* Parameters: fin(I) - pointer to packet information */
/* */
/* Functional interface for NAT lookups of the NAT fragment cache */
/* ------------------------------------------------------------------------ */
nat_t *fr_nat_knownfrag(fin)
fr_info_t *fin;
{
nat_t *nat;
ipfr_t *ipf;
if ((fin->fin_v != 4) || (fr_frag_lock) || !ipfr_natlist)
return NULL;
READ_ENTER(&ipf_natfrag);
ipf = fr_fraglookup(fin, ipfr_nattab);
if (ipf != NULL) {
nat = ipf->ipfr_data;
/*
* This is the last fragment for this packet.
*/
if ((ipf->ipfr_ttl == fr_ticks + 1) && (nat != NULL)) {
nat->nat_data = NULL;
ipf->ipfr_data = NULL;
}
} else
nat = NULL;
RWLOCK_EXIT(&ipf_natfrag);
return nat;
}
/* ------------------------------------------------------------------------ */
/* Function: fr_ipid_knownfrag */
/* Returns: u_32_t - IPv4 ID for this packet if match found, else */
/* return 0xfffffff to indicate no match. */
/* Parameters: fin(I) - pointer to packet information */
/* */
/* Functional interface for IP ID lookups of the IP ID fragment cache */
/* ------------------------------------------------------------------------ */
u_32_t fr_ipid_knownfrag(fin)
fr_info_t *fin;
{
ipfr_t *ipf;
u_32_t id;
if ((fin->fin_v != 4) || (fr_frag_lock) || !ipfr_ipidlist)
return 0xffffffff;
READ_ENTER(&ipf_ipidfrag);
ipf = fr_fraglookup(fin, ipfr_ipidtab);
if (ipf != NULL)
id = (u_32_t)((u_long)ipf->ipfr_data & 0xffffffff);
else
id = 0xffffffff;
RWLOCK_EXIT(&ipf_ipidfrag);
return id;
}
/* ------------------------------------------------------------------------ */
/* Function: fr_knownfrag */
/* Returns: frentry_t* - pointer to filter rule if a match is found in */
/* the frag cache table, else NULL. */
/* Parameters: fin(I) - pointer to packet information */
/* passp(O) - pointer to where to store rule flags resturned */
/* */
/* Functional interface for normal lookups of the fragment cache. If a */
/* match is found, return the rule pointer and flags from the rule, except */
/* that if FR_LOGFIRST is set, reset FR_LOG. */
/* ------------------------------------------------------------------------ */
frentry_t *fr_knownfrag(fin, passp)
fr_info_t *fin;
u_32_t *passp;
{
frentry_t *fr = NULL;
ipfr_t *fra;
u_32_t pass;
if ((fin->fin_v != 4) || (fr_frag_lock) || (ipfr_list == NULL))
return NULL;
READ_ENTER(&ipf_frag);
fra = fr_fraglookup(fin, ipfr_heads);
if (fra != NULL) {
fr = fra->ipfr_rule;
fin->fin_fr = fr;
if (fr != NULL) {
pass = fr->fr_flags;
if ((pass & FR_LOGFIRST) != 0)
pass &= ~(FR_LOGFIRST|FR_LOG);
*passp = pass;
}
}
RWLOCK_EXIT(&ipf_frag);
return fr;
}
/* ------------------------------------------------------------------------ */
/* Function: fr_forget */
/* Returns: Nil */
/* Parameters: ptr(I) - pointer to data structure */
/* */
/* Search through all of the fragment cache entries and wherever a pointer */
/* is found to match ptr, reset it to NULL. */
/* ------------------------------------------------------------------------ */
void fr_forget(ptr)
void *ptr;
{
ipfr_t *fr;
WRITE_ENTER(&ipf_frag);
for (fr = ipfr_list; fr; fr = fr->ipfr_next)
if (fr->ipfr_data == ptr)
fr->ipfr_data = NULL;
RWLOCK_EXIT(&ipf_frag);
}
/* ------------------------------------------------------------------------ */
/* Function: fr_forgetnat */
/* Returns: Nil */
/* Parameters: ptr(I) - pointer to data structure */
/* */
/* Search through all of the fragment cache entries for NAT and wherever a */
/* pointer is found to match ptr, reset it to NULL. */
/* ------------------------------------------------------------------------ */
void fr_forgetnat(ptr)
void *ptr;
{
ipfr_t *fr;
WRITE_ENTER(&ipf_natfrag);
for (fr = ipfr_natlist; fr; fr = fr->ipfr_next)
if (fr->ipfr_data == ptr)
fr->ipfr_data = NULL;
RWLOCK_EXIT(&ipf_natfrag);
}
/* ------------------------------------------------------------------------ */
/* Function: fr_fragdelete */
/* Returns: Nil */
/* Parameters: fra(I) - pointer to fragment structure to delete */
/* tail(IO) - pointer to the pointer to the tail of the frag */
/* list */
/* */
/* Remove a fragment cache table entry from the table & list. Also free */
/* the filter rule it is associated with it if it is no longer used as a */
/* result of decreasing the reference count. */
/* ------------------------------------------------------------------------ */
static void fr_fragdelete(fra, tail)
ipfr_t *fra, ***tail;
{
if (fra->ipfr_next)
fra->ipfr_next->ipfr_prev = fra->ipfr_prev;
*fra->ipfr_prev = fra->ipfr_next;
if (*tail == &fra->ipfr_next)
*tail = fra->ipfr_prev;
if (fra->ipfr_hnext)
fra->ipfr_hnext->ipfr_hprev = fra->ipfr_hprev;
*fra->ipfr_hprev = fra->ipfr_hnext;
if (fra->ipfr_rule != NULL) {
(void) fr_derefrule(&fra->ipfr_rule);
}
if (fra->ipfr_ref <= 0)
fr_fragfree(fra);
}
/* ------------------------------------------------------------------------ */
/* Function: fr_fragfree */
/* Returns: Nil */
/* Parameters: fra - pointer to frag structure to free */
/* */
/* Take care of the details associated with deleting an entry from the frag */
/* cache. Currently this just means bumping stats correctly after freeing */
/* ------------------------------------------------------------------------ */
static void fr_fragfree(fra)
ipfr_t *fra;
{
KFREE(fra);
ipfr_stats.ifs_expire++;
ipfr_inuse--;
}
/* ------------------------------------------------------------------------ */
/* Function: fr_fragclear */
/* Returns: Nil */
/* Parameters: Nil */
/* */
/* Free memory in use by fragment state information kept. Do the normal */
/* fragment state stuff first and then the NAT-fragment table. */
/* ------------------------------------------------------------------------ */
void fr_fragclear()
{
ipfr_t *fra;
nat_t *nat;
WRITE_ENTER(&ipf_frag);
while ((fra = ipfr_list) != NULL) {
fra->ipfr_ref--;
fr_fragdelete(fra, &ipfr_tail);
}
ipfr_tail = &ipfr_list;
RWLOCK_EXIT(&ipf_frag);
WRITE_ENTER(&ipf_nat);
WRITE_ENTER(&ipf_natfrag);
while ((fra = ipfr_natlist) != NULL) {
nat = fra->ipfr_data;
if (nat != NULL) {
if (nat->nat_data == fra)
nat->nat_data = NULL;
}
fra->ipfr_ref--;
fr_fragdelete(fra, &ipfr_nattail);
}
ipfr_nattail = &ipfr_natlist;
RWLOCK_EXIT(&ipf_natfrag);
RWLOCK_EXIT(&ipf_nat);
}
/* ------------------------------------------------------------------------ */
/* Function: fr_fragexpire */
/* Returns: Nil */
/* Parameters: Nil */
/* */
/* Expire entries in the fragment cache table that have been there too long */
/* ------------------------------------------------------------------------ */
void fr_fragexpire()
{
ipfr_t **fp, *fra;
nat_t *nat;
SPL_INT(s);
if (fr_frag_lock)
return;
SPL_NET(s);
WRITE_ENTER(&ipf_frag);
/*
* Go through the entire table, looking for entries to expire,
* which is indicated by the ttl being less than or equal to fr_ticks.
*/
for (fp = &ipfr_list; ((fra = *fp) != NULL); ) {
if (fra->ipfr_ttl > fr_ticks)
break;
fra->ipfr_ref--;
fr_fragdelete(fra, &ipfr_tail);
}
RWLOCK_EXIT(&ipf_frag);
WRITE_ENTER(&ipf_ipidfrag);
for (fp = &ipfr_ipidlist; ((fra = *fp) != NULL); ) {
if (fra->ipfr_ttl > fr_ticks)
break;
fra->ipfr_ref--;
fr_fragdelete(fra, &ipfr_ipidtail);
}
RWLOCK_EXIT(&ipf_ipidfrag);
/*
* Same again for the NAT table, except that if the structure also
* still points to a NAT structure, and the NAT structure points back
* at the one to be free'd, NULL the reference from the NAT struct.
* NOTE: We need to grab both mutex's early, and in this order so as
* to prevent a deadlock if both try to expire at the same time.
* The extra if() statement here is because it locks out all NAT
* operations - no need to do that if there are no entries in this
* list, right?
*/
if (ipfr_natlist != NULL) {
WRITE_ENTER(&ipf_nat);
WRITE_ENTER(&ipf_natfrag);
for (fp = &ipfr_natlist; ((fra = *fp) != NULL); ) {
if (fra->ipfr_ttl > fr_ticks)
break;
nat = fra->ipfr_data;
if (nat != NULL) {
if (nat->nat_data == fra)
nat->nat_data = NULL;
}
fra->ipfr_ref--;
fr_fragdelete(fra, &ipfr_nattail);
}
RWLOCK_EXIT(&ipf_natfrag);
RWLOCK_EXIT(&ipf_nat);
}
SPL_X(s);
}
/* ------------------------------------------------------------------------ */
/* Function: fr_slowtimer */
/* Returns: Nil */
/* Parameters: Nil */
/* */
/* Slowly expire held state for fragments. Timeouts are set * in */
/* expectation of this being called twice per second. */
/* ------------------------------------------------------------------------ */
#if !defined(_KERNEL) || (!SOLARIS && !defined(__hpux) && !defined(__sgi) && \
!defined(__osf__) && !defined(linux))
# if defined(_KERNEL) && ((BSD >= 199103) || defined(__sgi))
void fr_slowtimer __P((void *ptr))
# else
int fr_slowtimer()
# endif
{
READ_ENTER(&ipf_global);
ipf_expiretokens();
fr_fragexpire();
fr_timeoutstate();
fr_natexpire();
fr_authexpire();
fr_ticks++;
if (fr_running <= 0)
goto done;
# ifdef _KERNEL
# if defined(__NetBSD__) && (__NetBSD_Version__ >= 104240000)
callout_reset(&fr_slowtimer_ch, hz / 2, fr_slowtimer, NULL);
# else
# if defined(__OpenBSD__)
timeout_add(&fr_slowtimer_ch, hz/2);
# else
# if (__FreeBSD_version >= 300000)
fr_slowtimer_ch = timeout(fr_slowtimer, NULL, hz/2);
# else
# ifdef linux
;
# else
timeout(fr_slowtimer, NULL, hz/2);
# endif
# endif /* FreeBSD */
# endif /* OpenBSD */
# endif /* NetBSD */
# endif
done:
RWLOCK_EXIT(&ipf_global);
# if (BSD < 199103) || !defined(_KERNEL)
return 0;
# endif
}
#endif /* !SOLARIS && !defined(__hpux) && !defined(__sgi) */
/* ------------------------------------------------------------------------ */
/* Function: fr_nextfrag */
/* Returns: int - 0 == success, else error */
/* Parameters: token(I) - pointer to token information for this caller */
/* itp(I) - pointer to generic iterator from caller */
/* top(I) - top of the fragment list */
/* tail(I) - tail of the fragment list */
/* lock(I) - fragment cache lock */
/* */
/* This function is used to interate through the list of entries in the */
/* fragment cache. It increases the reference count on the one currently */
/* being returned so that the caller can come back and resume from it later.*/
/* */
/* This function is used for both the NAT fragment cache as well as the ipf */
/* fragment cache - hence the reason for passing in top, tail and lock. */
/* ------------------------------------------------------------------------ */
int fr_nextfrag(token, itp, top, tail
#ifdef USE_MUTEXES
, lock
#endif
)
ipftoken_t *token;
ipfgeniter_t *itp;
ipfr_t **top, ***tail;
#ifdef USE_MUTEXES
ipfrwlock_t *lock;
#endif
{
ipfr_t *frag, *next, zero;
int error = 0;
frag = token->ipt_data;
if (frag == (ipfr_t *)-1) {
ipf_freetoken(token);
return ESRCH;
}
READ_ENTER(lock);
if (frag == NULL)
next = *top;
else
next = frag->ipfr_next;
if (next != NULL) {
ATOMIC_INC(next->ipfr_ref);
token->ipt_data = next;
} else {
bzero(&zero, sizeof(zero));
next = &zero;
token->ipt_data = NULL;
}
RWLOCK_EXIT(lock);
if (frag != NULL) {
#ifdef USE_MUTEXES
fr_fragderef(&frag, lock);
#else
fr_fragderef(&frag);
#endif
}
error = COPYOUT(next, itp->igi_data, sizeof(*next));
if (error != 0)
error = EFAULT;
return error;
}
/* ------------------------------------------------------------------------ */
/* Function: fr_fragderef */
/* Returns: Nil */
/* Parameters: frp(IO) - pointer to fragment structure to deference */
/* lock(I) - lock associated with the fragment */
/* */
/* This function dereferences a fragment structure (ipfr_t). The pointer */
/* passed in will always be reset back to NULL, even if the structure is */
/* not freed, to enforce the notion that the caller is no longer entitled */
/* to use the pointer it is dropping the reference to. */
/* ------------------------------------------------------------------------ */
void fr_fragderef(frp
#ifdef USE_MUTEXES
, lock
#endif
)
ipfr_t **frp;
#ifdef USE_MUTEXES
ipfrwlock_t *lock;
#endif
{
ipfr_t *fra;
fra = *frp;
*frp = NULL;
WRITE_ENTER(lock);
fra->ipfr_ref--;
if (fra->ipfr_ref <= 0)
fr_fragfree(fra);
RWLOCK_EXIT(lock);
}
-105
View File
@@ -1,105 +0,0 @@
/*
* 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.23.2.5 2006/12/23 11:11:47 darrenr Exp $
*/
#ifndef __IP_FRAG_H__
#define __IP_FRAG_H__
#define IPFT_SIZE 257
typedef struct ipfr {
struct ipfr *ipfr_hnext, **ipfr_hprev;
struct ipfr *ipfr_next, **ipfr_prev;
void *ipfr_data;
frentry_t *ipfr_rule;
u_long ipfr_ttl;
int ipfr_ref;
u_short ipfr_off;
u_short ipfr_seen0;
/*
* All of the fields, from ipfr_ifp to ipfr_pass, are compared
* using bcmp to see if an identical entry is present. It is
* therefore important for this set to remain together.
*/
void *ipfr_ifp;
struct in_addr ipfr_src;
struct in_addr ipfr_dst;
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;
} ipfr_t;
typedef struct ipfrstat {
u_long ifs_exists; /* add & already exists */
u_long ifs_nomem;
u_long ifs_new;
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_pass) - \
offsetof(ipfr_t, ipfr_ifp))
extern ipfr_t *ipfr_list, **ipfr_tail;
extern ipfr_t *ipfr_natlist, **ipfr_nattail;
extern int ipfr_size;
extern int fr_ipfrttl;
extern int fr_frag_lock;
extern int fr_fraginit __P((void));
extern void fr_fragunload __P((void));
extern ipfrstat_t *fr_fragstats __P((void));
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 *));
#ifdef USE_MUTEXES
extern void fr_fragderef __P((ipfr_t **, ipfrwlock_t *));
extern int fr_nextfrag __P((ipftoken_t *, ipfgeniter_t *, ipfr_t **, \
ipfr_t ***, ipfrwlock_t *));
#else
extern void fr_fragderef __P((ipfr_t **));
extern int fr_nextfrag __P((ipftoken_t *, ipfgeniter_t *, ipfr_t **, \
ipfr_t ***));
#endif
extern void fr_forget __P((void *));
extern void fr_forgetnat __P((void *));
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 void fr_slowtimer __P((void *));
# endif
#else
# if defined(linux) && defined(_KERNEL)
extern void fr_slowtimer __P((long));
# else
extern int fr_slowtimer __P((void));
# endif
#endif
#endif /* __IP_FRAG_H__ */
File diff suppressed because it is too large Load Diff
-294
View File
@@ -1,294 +0,0 @@
/*
* Copyright 2001, QNX Software Systems Ltd. All Rights Reserved
*
* This source code has been published by QNX Software Systems Ltd. (QSSL).
* However, any use, reproduction, modification, distribution or transfer of
* this software, or any software which includes or is based upon any of this
* code, is only permitted under the terms of the QNX Open Community License
* version 1.0 (see licensing.qnx.com for details) or as otherwise expressly
* authorized by a written license agreement from QSSL. For more information,
* please email licensing@qnx.com.
*
* For more details, see QNX_OCL.txt provided with this distribution.
*/
/*
* Simple H.323 proxy
*
* by xtang@canada.com
* ported to ipfilter 3.4.20 by Michael Grant mg-ipf@grant.org
*/
#if __FreeBSD_version >= 220000 && defined(_KERNEL)
# include <sys/fcntl.h>
# include <sys/filio.h>
#else
# ifndef linux
# include <sys/ioctl.h>
# endif
#endif
#define IPF_H323_PROXY
int ippr_h323_init __P((void));
void ippr_h323_fini __P((void));
int ippr_h323_new __P((fr_info_t *, ap_session_t *, nat_t *));
void ippr_h323_del __P((ap_session_t *));
int ippr_h323_out __P((fr_info_t *, ap_session_t *, nat_t *));
int ippr_h323_in __P((fr_info_t *, ap_session_t *, nat_t *));
int ippr_h245_new __P((fr_info_t *, ap_session_t *, nat_t *));
int ippr_h245_out __P((fr_info_t *, ap_session_t *, nat_t *));
int ippr_h245_in __P((fr_info_t *, ap_session_t *, nat_t *));
static frentry_t h323_fr;
int h323_proxy_init = 0;
static int find_port __P((int, caddr_t, int datlen, int *, u_short *));
static int find_port(ipaddr, data, datlen, off, port)
int ipaddr;
caddr_t data;
int datlen, *off;
unsigned short *port;
{
u_32_t addr, netaddr;
u_char *dp;
int offset;
if (datlen < 6)
return -1;
*port = 0;
offset = *off;
dp = (u_char *)data;
netaddr = ntohl(ipaddr);
for (offset = 0; offset <= datlen - 6; offset++, dp++) {
addr = (dp[0] << 24) | (dp[1] << 16) | (dp[2] << 8) | dp[3];
if (netaddr == addr)
{
*port = (*(dp + 4) << 8) | *(dp + 5);
break;
}
}
*off = offset;
return (offset > datlen - 6) ? -1 : 0;
}
/*
* Initialize local structures.
*/
int ippr_h323_init()
{
bzero((char *)&h323_fr, sizeof(h323_fr));
h323_fr.fr_ref = 1;
h323_fr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
MUTEX_INIT(&h323_fr.fr_lock, "H323 proxy rule lock");
h323_proxy_init = 1;
return 0;
}
void ippr_h323_fini()
{
if (h323_proxy_init == 1) {
MUTEX_DESTROY(&h323_fr.fr_lock);
h323_proxy_init = 0;
}
}
int ippr_h323_new(fin, aps, nat)
fr_info_t *fin;
ap_session_t *aps;
nat_t *nat;
{
fin = fin; /* LINT */
nat = nat; /* LINT */
aps->aps_data = NULL;
aps->aps_psiz = 0;
return 0;
}
void ippr_h323_del(aps)
ap_session_t *aps;
{
int i;
ipnat_t *ipn;
if (aps->aps_data) {
for (i = 0, ipn = aps->aps_data;
i < (aps->aps_psiz / sizeof(ipnat_t));
i++, ipn = (ipnat_t *)((char *)ipn + sizeof(*ipn)))
{
/*
* Check the comment in ippr_h323_in() function,
* just above fr_nat_ioctl() call.
* We are lucky here because this function is not
* called with ipf_nat locked.
*/
if (fr_nat_ioctl((caddr_t)ipn, SIOCRMNAT, NAT_SYSSPACE|
NAT_LOCKHELD|FWRITE) == -1) {
/*EMPTY*/;
/* log the error */
}
}
KFREES(aps->aps_data, aps->aps_psiz);
/* avoid double free */
aps->aps_data = NULL;
aps->aps_psiz = 0;
}
return;
}
int ippr_h323_in(fin, aps, nat)
fr_info_t *fin;
ap_session_t *aps;
nat_t *nat;
{
int ipaddr, off, datlen;
unsigned short port;
caddr_t data;
tcphdr_t *tcp;
ip_t *ip;
ip = fin->fin_ip;
tcp = (tcphdr_t *)fin->fin_dp;
ipaddr = ip->ip_src.s_addr;
data = (caddr_t)tcp + (TCP_OFF(tcp) << 2);
datlen = fin->fin_dlen - (TCP_OFF(tcp) << 2);
if (find_port(ipaddr, data, datlen, &off, &port) == 0) {
ipnat_t *ipn;
char *newarray;
/* setup a nat rule to set a h245 proxy on tcp-port "port"
* it's like:
* map <if> <inter_ip>/<mask> -> <gate_ip>/<mask> proxy port <port> <port>/tcp
*/
KMALLOCS(newarray, char *, aps->aps_psiz + sizeof(*ipn));
if (newarray == NULL) {
return -1;
}
ipn = (ipnat_t *)&newarray[aps->aps_psiz];
bcopy((caddr_t)nat->nat_ptr, (caddr_t)ipn, sizeof(ipnat_t));
(void) strncpy(ipn->in_plabel, "h245", APR_LABELLEN);
ipn->in_inip = nat->nat_inip.s_addr;
ipn->in_inmsk = 0xffffffff;
ipn->in_dport = htons(port);
/*
* we got a problem here. we need to call fr_nat_ioctl() to add
* the h245 proxy rule, but since we already hold (READ locked)
* the nat table rwlock (ipf_nat), if we go into fr_nat_ioctl(),
* it will try to WRITE lock it. This will causing dead lock
* on RTP.
*
* The quick & dirty solution here is release the read lock,
* call fr_nat_ioctl() and re-lock it.
* A (maybe better) solution is do a UPGRADE(), and instead
* of calling fr_nat_ioctl(), we add the nat rule ourself.
*/
RWLOCK_EXIT(&ipf_nat);
if (fr_nat_ioctl((caddr_t)ipn, SIOCADNAT,
NAT_SYSSPACE|FWRITE) == -1) {
READ_ENTER(&ipf_nat);
return -1;
}
READ_ENTER(&ipf_nat);
if (aps->aps_data != NULL && aps->aps_psiz > 0) {
bcopy(aps->aps_data, newarray, aps->aps_psiz);
KFREES(aps->aps_data, aps->aps_psiz);
}
aps->aps_data = newarray;
aps->aps_psiz += sizeof(*ipn);
}
return 0;
}
int ippr_h245_new(fin, aps, nat)
fr_info_t *fin;
ap_session_t *aps;
nat_t *nat;
{
fin = fin; /* LINT */
nat = nat; /* LINT */
aps->aps_data = NULL;
aps->aps_psiz = 0;
return 0;
}
int ippr_h245_out(fin, aps, nat)
fr_info_t *fin;
ap_session_t *aps;
nat_t *nat;
{
int ipaddr, off, datlen;
tcphdr_t *tcp;
caddr_t data;
u_short port;
ip_t *ip;
aps = aps; /* LINT */
ip = fin->fin_ip;
tcp = (tcphdr_t *)fin->fin_dp;
ipaddr = nat->nat_inip.s_addr;
data = (caddr_t)tcp + (TCP_OFF(tcp) << 2);
datlen = fin->fin_dlen - (TCP_OFF(tcp) << 2);
if (find_port(ipaddr, data, datlen, &off, &port) == 0) {
fr_info_t fi;
nat_t *nat2;
/* port = htons(port); */
nat2 = nat_outlookup(fin->fin_ifp, IPN_UDP, IPPROTO_UDP,
ip->ip_src, ip->ip_dst);
if (nat2 == NULL) {
struct ip newip;
struct udphdr udp;
bcopy((caddr_t)ip, (caddr_t)&newip, sizeof(newip));
newip.ip_len = fin->fin_hlen + sizeof(udp);
newip.ip_p = IPPROTO_UDP;
newip.ip_src = nat->nat_inip;
bzero((char *)&udp, sizeof(udp));
udp.uh_sport = port;
bcopy((caddr_t)fin, (caddr_t)&fi, sizeof(fi));
fi.fin_fi.fi_p = IPPROTO_UDP;
fi.fin_data[0] = port;
fi.fin_data[1] = 0;
fi.fin_dp = (char *)&udp;
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);
nat2->nat_ptr->in_hits++;
#ifdef IPFILTER_LOG
nat_log(nat2, (u_int)(nat->nat_ptr->in_redir));
#endif
bcopy((caddr_t)&ip->ip_src.s_addr,
data + off, 4);
bcopy((caddr_t)&nat2->nat_outport,
data + off + 4, 2);
}
}
}
return 0;
}
-640
View File
@@ -1,640 +0,0 @@
/*
* Copyright (C) 1993-2001, 2003 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*/
#if defined(KERNEL) || defined(_KERNEL)
# undef KERNEL
# undef _KERNEL
# define KERNEL 1
# define _KERNEL 1
#endif
#include <sys/param.h>
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/time.h>
#include <sys/file.h>
#if !defined(_KERNEL)
# include <stdlib.h>
# include <string.h>
# define _KERNEL
# ifdef __OpenBSD__
struct file;
# endif
# include <sys/uio.h>
# undef _KERNEL
#endif
#include <sys/socket.h>
#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
# include <sys/malloc.h>
#endif
#if defined(__FreeBSD__)
# include <sys/cdefs.h>
# include <sys/proc.h>
#endif
#if !defined(__svr4__) && !defined(__SVR4) && !defined(__hpux) && \
!defined(linux)
# include <sys/mbuf.h>
#endif
#if defined(_KERNEL)
# include <sys/systm.h>
#else
# include <stdio.h>
#endif
#include <netinet/in.h>
#include <net/if.h>
#include "netinet/ip_compat.h"
#include "netinet/ip_fil.h"
#include "netinet/ip_lookup.h"
#include "netinet/ip_htable.h"
/* END OF INCLUDES */
#if !defined(lint)
static const char rcsid[] = "@(#)$Id: ip_htable.c,v 2.34.2.11 2007/09/20 12:51:51 darrenr Exp $";
#endif
#ifdef IPFILTER_LOOKUP
static iphtent_t *fr_iphmfind __P((iphtable_t *, struct in_addr *));
static u_long ipht_nomem[IPL_LOGSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0 };
static u_long ipf_nhtables[IPL_LOGSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0 };
static u_long ipf_nhtnodes[IPL_LOGSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0 };
iphtable_t *ipf_htables[IPL_LOGSIZE] = { NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL };
void fr_htable_unload()
{
iplookupflush_t fop;
fop.iplf_unit = IPL_LOGALL;
(void)fr_flushhtable(&fop);
}
int fr_gethtablestat(op)
iplookupop_t *op;
{
iphtstat_t stats;
if (op->iplo_size != sizeof(stats))
return EINVAL;
stats.iphs_tables = ipf_htables[op->iplo_unit];
stats.iphs_numtables = ipf_nhtables[op->iplo_unit];
stats.iphs_numnodes = ipf_nhtnodes[op->iplo_unit];
stats.iphs_nomem = ipht_nomem[op->iplo_unit];
return COPYOUT(&stats, op->iplo_struct, sizeof(stats));
}
/*
* Create a new hash table using the template passed.
*/
int fr_newhtable(op)
iplookupop_t *op;
{
iphtable_t *iph, *oiph;
char name[FR_GROUPLEN];
int err, i, unit;
unit = op->iplo_unit;
if ((op->iplo_arg & IPHASH_ANON) == 0) {
iph = fr_existshtable(unit, op->iplo_name);
if (iph != NULL) {
if ((iph->iph_flags & IPHASH_DELETE) == 0)
return EEXIST;
iph->iph_flags &= ~IPHASH_DELETE;
return 0;
}
}
KMALLOC(iph, iphtable_t *);
if (iph == NULL) {
ipht_nomem[op->iplo_unit]++;
return ENOMEM;
}
err = COPYIN(op->iplo_struct, iph, sizeof(*iph));
if (err != 0) {
KFREE(iph);
return EFAULT;
}
if (iph->iph_unit != unit) {
KFREE(iph);
return EINVAL;
}
if ((op->iplo_arg & IPHASH_ANON) != 0) {
i = IPHASH_ANON;
do {
i++;
#if defined(SNPRINTF) && defined(_KERNEL)
SNPRINTF(name, sizeof(name), "%u", i);
#else
(void)sprintf(name, "%u", i);
#endif
for (oiph = ipf_htables[unit]; oiph != NULL;
oiph = oiph->iph_next)
if (strncmp(oiph->iph_name, name,
sizeof(oiph->iph_name)) == 0)
break;
} while (oiph != NULL);
(void)strncpy(iph->iph_name, name, sizeof(iph->iph_name));
(void)strncpy(op->iplo_name, name, sizeof(op->iplo_name));
iph->iph_type |= IPHASH_ANON;
}
KMALLOCS(iph->iph_table, iphtent_t **,
iph->iph_size * sizeof(*iph->iph_table));
if (iph->iph_table == NULL) {
KFREE(iph);
ipht_nomem[unit]++;
return ENOMEM;
}
bzero((char *)iph->iph_table, iph->iph_size * sizeof(*iph->iph_table));
iph->iph_masks = 0;
iph->iph_list = NULL;
iph->iph_ref = 1;
iph->iph_next = ipf_htables[unit];
iph->iph_pnext = &ipf_htables[unit];
if (ipf_htables[unit] != NULL)
ipf_htables[unit]->iph_pnext = &iph->iph_next;
ipf_htables[unit] = iph;
ipf_nhtables[unit]++;
return 0;
}
/*
*/
int fr_removehtable(unit, name)
int unit;
char *name;
{
iphtable_t *iph;
iph = fr_findhtable(unit, name);
if (iph == NULL)
return ESRCH;
if (iph->iph_unit != unit) {
return EINVAL;
}
if (iph->iph_ref != 0) {
(void) fr_clearhtable(iph);
iph->iph_flags |= IPHASH_DELETE;
return 0;
}
fr_delhtable(iph);
return 0;
}
int fr_clearhtable(iph)
iphtable_t *iph;
{
iphtent_t *ipe;
while ((ipe = iph->iph_list) != NULL)
if (fr_delhtent(iph, ipe) != 0)
return 1;
return 0;
}
int fr_delhtable(iph)
iphtable_t *iph;
{
if (fr_clearhtable(iph) != 0)
return 1;
if (iph->iph_pnext != NULL)
*iph->iph_pnext = iph->iph_next;
if (iph->iph_next != NULL)
iph->iph_next->iph_pnext = iph->iph_pnext;
ipf_nhtables[iph->iph_unit]--;
return fr_derefhtable(iph);
}
/*
* Delete an entry from a hash table.
*/
int fr_delhtent(iph, ipe)
iphtable_t *iph;
iphtent_t *ipe;
{
if (ipe->ipe_phnext != NULL)
*ipe->ipe_phnext = ipe->ipe_hnext;
if (ipe->ipe_hnext != NULL)
ipe->ipe_hnext->ipe_phnext = ipe->ipe_phnext;
if (ipe->ipe_pnext != NULL)
*ipe->ipe_pnext = ipe->ipe_next;
if (ipe->ipe_next != NULL)
ipe->ipe_next->ipe_pnext = ipe->ipe_pnext;
switch (iph->iph_type & ~IPHASH_ANON)
{
case IPHASH_GROUPMAP :
if (ipe->ipe_group != NULL)
fr_delgroup(ipe->ipe_group, IPL_LOGIPF, fr_active);
break;
default :
ipe->ipe_ptr = NULL;
ipe->ipe_value = 0;
break;
}
return fr_derefhtent(ipe);
}
int fr_derefhtable(iph)
iphtable_t *iph;
{
int refs;
iph->iph_ref--;
refs = iph->iph_ref;
if (iph->iph_ref == 0) {
KFREES(iph->iph_table, iph->iph_size * sizeof(*iph->iph_table));
KFREE(iph);
}
return refs;
}
int fr_derefhtent(ipe)
iphtent_t *ipe;
{
ipe->ipe_ref--;
if (ipe->ipe_ref == 0) {
ipf_nhtnodes[ipe->ipe_unit]--;
KFREE(ipe);
return 0;
}
return ipe->ipe_ref;
}
iphtable_t *fr_existshtable(unit, name)
int unit;
char *name;
{
iphtable_t *iph;
for (iph = ipf_htables[unit]; iph != NULL; iph = iph->iph_next)
if (strncmp(iph->iph_name, name, sizeof(iph->iph_name)) == 0)
break;
return iph;
}
iphtable_t *fr_findhtable(unit, name)
int unit;
char *name;
{
iphtable_t *iph;
iph = fr_existshtable(unit, name);
if ((iph != NULL) && (iph->iph_flags & IPHASH_DELETE) == 0)
return iph;
return NULL;
}
size_t fr_flushhtable(op)
iplookupflush_t *op;
{
iphtable_t *iph;
size_t freed;
int i;
freed = 0;
for (i = 0; i <= IPL_LOGMAX; i++) {
if (op->iplf_unit == i || op->iplf_unit == IPL_LOGALL) {
while ((iph = ipf_htables[i]) != NULL) {
if (fr_delhtable(iph) == 0) {
freed++;
} else {
iph->iph_flags |= IPHASH_DELETE;
}
}
}
}
return freed;
}
/*
* Add an entry to a hash table.
*/
int fr_addhtent(iph, ipeo)
iphtable_t *iph;
iphtent_t *ipeo;
{
iphtent_t *ipe;
u_int hv;
int bits;
KMALLOC(ipe, iphtent_t *);
if (ipe == NULL)
return -1;
bcopy((char *)ipeo, (char *)ipe, sizeof(*ipe));
ipe->ipe_addr.in4_addr &= ipe->ipe_mask.in4_addr;
ipe->ipe_addr.in4_addr = ntohl(ipe->ipe_addr.in4_addr);
bits = count4bits(ipe->ipe_mask.in4_addr);
ipe->ipe_mask.in4_addr = ntohl(ipe->ipe_mask.in4_addr);
hv = IPE_HASH_FN(ipe->ipe_addr.in4_addr, ipe->ipe_mask.in4_addr,
iph->iph_size);
ipe->ipe_ref = 1;
ipe->ipe_hnext = iph->iph_table[hv];
ipe->ipe_phnext = iph->iph_table + hv;
if (iph->iph_table[hv] != NULL)
iph->iph_table[hv]->ipe_phnext = &ipe->ipe_hnext;
iph->iph_table[hv] = ipe;
ipe->ipe_next = iph->iph_list;
ipe->ipe_pnext = &iph->iph_list;
if (ipe->ipe_next != NULL)
ipe->ipe_next->ipe_pnext = &ipe->ipe_next;
iph->iph_list = ipe;
if ((bits >= 0) && (bits != 32))
iph->iph_masks |= 1 << bits;
switch (iph->iph_type & ~IPHASH_ANON)
{
case IPHASH_GROUPMAP :
ipe->ipe_ptr = fr_addgroup(ipe->ipe_group, NULL,
iph->iph_flags, IPL_LOGIPF,
fr_active);
break;
default :
ipe->ipe_ptr = NULL;
ipe->ipe_value = 0;
break;
}
ipe->ipe_unit = iph->iph_unit;
ipf_nhtnodes[ipe->ipe_unit]++;
return 0;
}
void *fr_iphmfindgroup(tptr, aptr)
void *tptr, *aptr;
{
struct in_addr *addr;
iphtable_t *iph;
iphtent_t *ipe;
void *rval;
READ_ENTER(&ip_poolrw);
iph = tptr;
addr = aptr;
ipe = fr_iphmfind(iph, addr);
if (ipe != NULL)
rval = ipe->ipe_ptr;
else
rval = NULL;
RWLOCK_EXIT(&ip_poolrw);
return rval;
}
/* ------------------------------------------------------------------------ */
/* Function: fr_iphmfindip */
/* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */
/* Parameters: tptr(I) - pointer to the pool to search */
/* ipversion(I) - IP protocol version (4 or 6) */
/* aptr(I) - pointer to address information */
/* */
/* Search the hash table for a given address and return a search result. */
/* ------------------------------------------------------------------------ */
int fr_iphmfindip(tptr, ipversion, aptr)
void *tptr, *aptr;
int ipversion;
{
struct in_addr *addr;
iphtable_t *iph;
iphtent_t *ipe;
int rval;
if (ipversion != 4)
return -1;
if (tptr == NULL || aptr == NULL)
return -1;
iph = tptr;
addr = aptr;
READ_ENTER(&ip_poolrw);
ipe = fr_iphmfind(iph, addr);
if (ipe != NULL)
rval = 0;
else
rval = 1;
RWLOCK_EXIT(&ip_poolrw);
return rval;
}
/* Locks: ip_poolrw */
static iphtent_t *fr_iphmfind(iph, addr)
iphtable_t *iph;
struct in_addr *addr;
{
u_32_t hmsk, msk, ips;
iphtent_t *ipe;
u_int hv;
hmsk = iph->iph_masks;
msk = 0xffffffff;
maskloop:
ips = ntohl(addr->s_addr) & msk;
hv = IPE_HASH_FN(ips, msk, iph->iph_size);
for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_hnext) {
if (ipe->ipe_mask.in4_addr != msk ||
ipe->ipe_addr.in4_addr != ips) {
continue;
}
break;
}
if ((ipe == NULL) && (hmsk != 0)) {
while (hmsk != 0) {
msk <<= 1;
if (hmsk & 0x80000000)
break;
hmsk <<= 1;
}
if (hmsk != 0) {
hmsk <<= 1;
goto maskloop;
}
}
return ipe;
}
int fr_htable_getnext(token, ilp)
ipftoken_t *token;
ipflookupiter_t *ilp;
{
iphtent_t *node, zn, *nextnode;
iphtable_t *iph, zp, *nextiph;
int err;
err = 0;
iph = NULL;
node = NULL;
nextiph = NULL;
nextnode = NULL;
READ_ENTER(&ip_poolrw);
switch (ilp->ili_otype)
{
case IPFLOOKUPITER_LIST :
iph = token->ipt_data;
if (iph == NULL) {
nextiph = ipf_htables[(int)ilp->ili_unit];
} else {
nextiph = iph->iph_next;
}
if (nextiph != NULL) {
ATOMIC_INC(nextiph->iph_ref);
token->ipt_data = nextiph;
} else {
bzero((char *)&zp, sizeof(zp));
nextiph = &zp;
token->ipt_data = NULL;
}
break;
case IPFLOOKUPITER_NODE :
node = token->ipt_data;
if (node == NULL) {
iph = fr_findhtable(ilp->ili_unit, ilp->ili_name);
if (iph == NULL)
err = ESRCH;
else {
nextnode = iph->iph_list;
}
} else {
nextnode = node->ipe_next;
}
if (nextnode != NULL) {
ATOMIC_INC(nextnode->ipe_ref);
token->ipt_data = nextnode;
} else {
bzero((char *)&zn, sizeof(zn));
nextnode = &zn;
token->ipt_data = NULL;
}
break;
default :
err = EINVAL;
break;
}
RWLOCK_EXIT(&ip_poolrw);
if (err != 0)
return err;
switch (ilp->ili_otype)
{
case IPFLOOKUPITER_LIST :
if (iph != NULL) {
WRITE_ENTER(&ip_poolrw);
fr_derefhtable(iph);
RWLOCK_EXIT(&ip_poolrw);
}
err = COPYOUT(nextiph, ilp->ili_data, sizeof(*nextiph));
if (err != 0)
err = EFAULT;
break;
case IPFLOOKUPITER_NODE :
if (node != NULL) {
WRITE_ENTER(&ip_poolrw);
fr_derefhtent(node);
RWLOCK_EXIT(&ip_poolrw);
}
err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode));
if (err != 0)
err = EFAULT;
break;
}
return err;
}
void fr_htable_iterderef(otype, unit, data)
u_int otype;
int unit;
void *data;
{
if (data == NULL)
return;
if (unit < 0 || unit > IPL_LOGMAX)
return;
switch (otype)
{
case IPFLOOKUPITER_LIST :
WRITE_ENTER(&ip_poolrw);
fr_derefhtable((iphtable_t *)data);
RWLOCK_EXIT(&ip_poolrw);
break;
case IPFLOOKUPITER_NODE :
WRITE_ENTER(&ip_poolrw);
fr_derefhtent((iphtent_t *)data);
RWLOCK_EXIT(&ip_poolrw);
break;
default :
break;
}
}
#endif /* IPFILTER_LOOKUP */
-78
View File
@@ -1,78 +0,0 @@
#ifndef __IP_HTABLE_H__
#define __IP_HTABLE_H__
#include "netinet/ip_lookup.h"
typedef struct iphtent_s {
struct iphtent_s *ipe_next, **ipe_pnext;
struct iphtent_s *ipe_hnext, **ipe_phnext;
void *ipe_ptr;
i6addr_t ipe_addr;
i6addr_t ipe_mask;
int ipe_ref;
int ipe_unit;
union {
char ipeu_char[16];
u_long ipeu_long;
u_int ipeu_int;
}ipe_un;
} iphtent_t;
#define ipe_value ipe_un.ipeu_int
#define ipe_group ipe_un.ipeu_char
#define IPE_HASH_FN(a, m, s) (((a) * (m)) % (s))
typedef struct iphtable_s {
ipfrwlock_t iph_rwlock;
struct iphtable_s *iph_next, **iph_pnext;
struct iphtent_s **iph_table;
struct iphtent_s *iph_list;
size_t iph_size; /* size of hash table */
u_long iph_seed; /* hashing seed */
u_32_t iph_flags;
u_int iph_unit; /* IPL_LOG* */
u_int iph_ref;
u_int iph_type; /* lookup or group map - IPHASH_* */
u_int iph_masks; /* IPv4 netmasks in use */
char iph_name[FR_GROUPLEN]; /* hash table number */
} iphtable_t;
/* iph_type */
#define IPHASH_LOOKUP 0
#define IPHASH_GROUPMAP 1
#define IPHASH_DELETE 2
#define IPHASH_ANON 0x80000000
typedef struct iphtstat_s {
iphtable_t *iphs_tables;
u_long iphs_numtables;
u_long iphs_numnodes;
u_long iphs_nomem;
u_long iphs_pad[16];
} iphtstat_t;
extern iphtable_t *ipf_htables[IPL_LOGSIZE];
extern iphtable_t *fr_existshtable __P((int, char *));
extern int fr_clearhtable __P((iphtable_t *));
extern void fr_htable_unload __P((void));
extern int fr_newhtable __P((iplookupop_t *));
extern iphtable_t *fr_findhtable __P((int, char *));
extern int fr_removehtable __P((int, char *));
extern size_t fr_flushhtable __P((iplookupflush_t *));
extern int fr_addhtent __P((iphtable_t *, iphtent_t *));
extern int fr_delhtent __P((iphtable_t *, iphtent_t *));
extern int fr_derefhtable __P((iphtable_t *));
extern int fr_derefhtent __P((iphtent_t *));
extern int fr_delhtable __P((iphtable_t *));
extern void *fr_iphmfindgroup __P((void *, void *));
extern int fr_iphmfindip __P((void *, int, void *));
extern int fr_gethtablestat __P((iplookupop_t *));
extern int fr_htable_getnext __P((ipftoken_t *, ipflookupiter_t *));
extern void fr_htable_iterderef __P((u_int, int, void *));
#endif /* __IP_HTABLE_H__ */
-341
View File
@@ -1,341 +0,0 @@
/*
* Copyright (C) 2001-2003 by Darren Reed
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* Simple ISAKMP transparent proxy for in-kernel use. For use with the NAT
* code.
*
* $Id: ip_ipsec_pxy.c,v 2.20.2.8 2006/07/14 06:12:14 darrenr Exp $
*
*/
#define IPF_IPSEC_PROXY
int ippr_ipsec_init __P((void));
void ippr_ipsec_fini __P((void));
int ippr_ipsec_new __P((fr_info_t *, ap_session_t *, nat_t *));
void ippr_ipsec_del __P((ap_session_t *));
int ippr_ipsec_inout __P((fr_info_t *, ap_session_t *, nat_t *));
int ippr_ipsec_match __P((fr_info_t *, ap_session_t *, nat_t *));
static frentry_t ipsecfr;
static ipftq_t *ipsecnattqe;
static ipftq_t *ipsecstatetqe;
static char ipsec_buffer[1500];
int ipsec_proxy_init = 0;
int ipsec_proxy_ttl = 60;
/*
* IPSec application proxy initialization.
*/
int ippr_ipsec_init()
{
bzero((char *)&ipsecfr, sizeof(ipsecfr));
ipsecfr.fr_ref = 1;
ipsecfr.fr_flags = FR_OUTQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
MUTEX_INIT(&ipsecfr.fr_lock, "IPsec proxy rule lock");
ipsec_proxy_init = 1;
ipsecnattqe = fr_addtimeoutqueue(&nat_utqe, ipsec_proxy_ttl);
if (ipsecnattqe == NULL)
return -1;
ipsecstatetqe = fr_addtimeoutqueue(&ips_utqe, ipsec_proxy_ttl);
if (ipsecstatetqe == NULL) {
if (fr_deletetimeoutqueue(ipsecnattqe) == 0)
fr_freetimeoutqueue(ipsecnattqe);
ipsecnattqe = NULL;
return -1;
}
ipsecnattqe->ifq_flags |= IFQF_PROXY;
ipsecstatetqe->ifq_flags |= IFQF_PROXY;
ipsecfr.fr_age[0] = ipsec_proxy_ttl;
ipsecfr.fr_age[1] = ipsec_proxy_ttl;
return 0;
}
void ippr_ipsec_fini()
{
if (ipsecnattqe != NULL) {
if (fr_deletetimeoutqueue(ipsecnattqe) == 0)
fr_freetimeoutqueue(ipsecnattqe);
}
ipsecnattqe = NULL;
if (ipsecstatetqe != NULL) {
if (fr_deletetimeoutqueue(ipsecstatetqe) == 0)
fr_freetimeoutqueue(ipsecstatetqe);
}
ipsecstatetqe = NULL;
if (ipsec_proxy_init == 1) {
MUTEX_DESTROY(&ipsecfr.fr_lock);
ipsec_proxy_init = 0;
}
}
/*
* Setup for a new IPSEC proxy.
*/
int ippr_ipsec_new(fin, aps, nat)
fr_info_t *fin;
ap_session_t *aps;
nat_t *nat;
{
ipsec_pxy_t *ipsec;
fr_info_t fi;
ipnat_t *ipn;
char *ptr;
int p, off, dlen, ttl;
mb_t *m;
ip_t *ip;
off = fin->fin_plen - fin->fin_dlen + fin->fin_ipoff;
bzero(ipsec_buffer, sizeof(ipsec_buffer));
ip = fin->fin_ip;
m = fin->fin_m;
dlen = M_LEN(m) - off;
if (dlen < 16)
return -1;
COPYDATA(m, off, MIN(sizeof(ipsec_buffer), dlen), ipsec_buffer);
if (nat_outlookup(fin, 0, IPPROTO_ESP, nat->nat_inip,
ip->ip_dst) != NULL)
return -1;
aps->aps_psiz = sizeof(*ipsec);
KMALLOCS(aps->aps_data, ipsec_pxy_t *, sizeof(*ipsec));
if (aps->aps_data == NULL)
return -1;
ipsec = aps->aps_data;
bzero((char *)ipsec, sizeof(*ipsec));
/*
* Create NAT rule against which the tunnel/transport mapping is
* created. This is required because the current NAT rule does not
* describe ESP but UDP instead.
*/
ipn = &ipsec->ipsc_rule;
ttl = IPF_TTLVAL(ipsecnattqe->ifq_ttl);
ipn->in_tqehead[0] = fr_addtimeoutqueue(&nat_utqe, ttl);
ipn->in_tqehead[1] = fr_addtimeoutqueue(&nat_utqe, ttl);
ipn->in_ifps[0] = fin->fin_ifp;
ipn->in_apr = NULL;
ipn->in_use = 1;
ipn->in_hits = 1;
ipn->in_nip = ntohl(nat->nat_outip.s_addr);
ipn->in_ippip = 1;
ipn->in_inip = nat->nat_inip.s_addr;
ipn->in_inmsk = 0xffffffff;
ipn->in_outip = fin->fin_saddr;
ipn->in_outmsk = nat->nat_outip.s_addr;
ipn->in_srcip = fin->fin_saddr;
ipn->in_srcmsk = 0xffffffff;
ipn->in_redir = NAT_MAP;
bcopy(nat->nat_ptr->in_ifnames[0], ipn->in_ifnames[0],
sizeof(ipn->in_ifnames[0]));
ipn->in_p = IPPROTO_ESP;
bcopy((char *)fin, (char *)&fi, sizeof(fi));
fi.fin_state = NULL;
fi.fin_nat = NULL;
fi.fin_fi.fi_p = IPPROTO_ESP;
fi.fin_fr = &ipsecfr;
fi.fin_data[0] = 0;
fi.fin_data[1] = 0;
p = ip->ip_p;
ip->ip_p = IPPROTO_ESP;
fi.fin_flx &= ~(FI_TCPUDP|FI_STATE|FI_FRAG);
fi.fin_flx |= FI_IGNORE;
ptr = ipsec_buffer;
bcopy(ptr, (char *)ipsec->ipsc_icookie, sizeof(ipsec_cookie_t));
ptr += sizeof(ipsec_cookie_t);
bcopy(ptr, (char *)ipsec->ipsc_rcookie, sizeof(ipsec_cookie_t));
/*
* The responder cookie should only be non-zero if the initiator
* cookie is non-zero. Therefore, it is safe to assume(!) that the
* cookies are both set after copying if the responder is non-zero.
*/
if ((ipsec->ipsc_rcookie[0]|ipsec->ipsc_rcookie[1]) != 0)
ipsec->ipsc_rckset = 1;
ipsec->ipsc_nat = nat_new(&fi, ipn, &ipsec->ipsc_nat,
NAT_SLAVE|SI_WILDP, NAT_OUTBOUND);
if (ipsec->ipsc_nat != NULL) {
(void) nat_proto(&fi, ipsec->ipsc_nat, 0);
nat_update(&fi, ipsec->ipsc_nat, ipn);
fi.fin_data[0] = 0;
fi.fin_data[1] = 0;
ipsec->ipsc_state = fr_addstate(&fi, &ipsec->ipsc_state,
SI_WILDP);
if (fi.fin_state != NULL)
fr_statederef((ipstate_t **)&fi.fin_state);
}
ip->ip_p = p & 0xff;
return 0;
}
/*
* For outgoing IKE packets. refresh timeouts for NAT & state entries, if
* we can. If they have disappeared, recreate them.
*/
int ippr_ipsec_inout(fin, aps, nat)
fr_info_t *fin;
ap_session_t *aps;
nat_t *nat;
{
ipsec_pxy_t *ipsec;
fr_info_t fi;
ip_t *ip;
int p;
if ((fin->fin_out == 1) && (nat->nat_dir == NAT_INBOUND))
return 0;
if ((fin->fin_out == 0) && (nat->nat_dir == NAT_OUTBOUND))
return 0;
ipsec = aps->aps_data;
if (ipsec != NULL) {
ip = fin->fin_ip;
p = ip->ip_p;
if ((ipsec->ipsc_nat == NULL) || (ipsec->ipsc_state == NULL)) {
bcopy((char *)fin, (char *)&fi, sizeof(fi));
fi.fin_state = NULL;
fi.fin_nat = NULL;
fi.fin_fi.fi_p = IPPROTO_ESP;
fi.fin_fr = &ipsecfr;
fi.fin_data[0] = 0;
fi.fin_data[1] = 0;
ip->ip_p = IPPROTO_ESP;
fi.fin_flx &= ~(FI_TCPUDP|FI_STATE|FI_FRAG);
fi.fin_flx |= FI_IGNORE;
}
/*
* Update NAT timeout/create NAT if missing.
*/
if (ipsec->ipsc_nat != NULL)
fr_queueback(&ipsec->ipsc_nat->nat_tqe);
else {
ipsec->ipsc_nat = nat_new(&fi, &ipsec->ipsc_rule,
&ipsec->ipsc_nat,
NAT_SLAVE|SI_WILDP,
nat->nat_dir);
if (ipsec->ipsc_nat != NULL) {
(void) nat_proto(&fi, ipsec->ipsc_nat, 0);
nat_update(&fi, ipsec->ipsc_nat,
&ipsec->ipsc_rule);
}
}
/*
* Update state timeout/create state if missing.
*/
READ_ENTER(&ipf_state);
if (ipsec->ipsc_state != NULL) {
fr_queueback(&ipsec->ipsc_state->is_sti);
ipsec->ipsc_state->is_die = nat->nat_age;
RWLOCK_EXIT(&ipf_state);
} else {
RWLOCK_EXIT(&ipf_state);
fi.fin_data[0] = 0;
fi.fin_data[1] = 0;
ipsec->ipsc_state = fr_addstate(&fi,
&ipsec->ipsc_state,
SI_WILDP);
if (fi.fin_state != NULL)
fr_statederef((ipstate_t **)&fi.fin_state);
}
ip->ip_p = p;
}
return 0;
}
/*
* This extends the NAT matching to be based on the cookies associated with
* a session and found at the front of IKE packets. The cookies are always
* in the same order (not reversed depending on packet flow direction as with
* UDP/TCP port numbers).
*/
int ippr_ipsec_match(fin, aps, nat)
fr_info_t *fin;
ap_session_t *aps;
nat_t *nat;
{
ipsec_pxy_t *ipsec;
u_32_t cookies[4];
mb_t *m;
int off;
nat = nat; /* LINT */
if ((fin->fin_dlen < sizeof(cookies)) || (fin->fin_flx & FI_FRAG))
return -1;
off = fin->fin_plen - fin->fin_dlen + fin->fin_ipoff;
ipsec = aps->aps_data;
m = fin->fin_m;
COPYDATA(m, off, sizeof(cookies), (char *)cookies);
if ((cookies[0] != ipsec->ipsc_icookie[0]) ||
(cookies[1] != ipsec->ipsc_icookie[1]))
return -1;
if (ipsec->ipsc_rckset == 0) {
if ((cookies[2]|cookies[3]) == 0) {
return 0;
}
ipsec->ipsc_rckset = 1;
ipsec->ipsc_rcookie[0] = cookies[2];
ipsec->ipsc_rcookie[1] = cookies[3];
return 0;
}
if ((cookies[2] != ipsec->ipsc_rcookie[0]) ||
(cookies[3] != ipsec->ipsc_rcookie[1]))
return -1;
return 0;
}
/*
* clean up after ourselves.
*/
void ippr_ipsec_del(aps)
ap_session_t *aps;
{
ipsec_pxy_t *ipsec;
ipsec = aps->aps_data;
if (ipsec != NULL) {
/*
* Don't bother changing any of the NAT structure details,
* *_del() is on a callback from aps_free(), from nat_delete()
*/
READ_ENTER(&ipf_state);
if (ipsec->ipsc_state != NULL) {
ipsec->ipsc_state->is_die = fr_ticks + 1;
ipsec->ipsc_state->is_me = NULL;
fr_queuefront(&ipsec->ipsc_state->is_sti);
}
RWLOCK_EXIT(&ipf_state);
ipsec->ipsc_state = NULL;
ipsec->ipsc_nat = NULL;
}
}
-433
View File
@@ -1,433 +0,0 @@
/*
* Copyright (C) 2000-2003 Darren Reed
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* $Id: ip_irc_pxy.c,v 2.39.2.6 2006/07/14 06:12:14 darrenr Exp $
*/
#define IPF_IRC_PROXY
#define IPF_IRCBUFSZ 96 /* This *MUST* be >= 64! */
int ippr_irc_init __P((void));
void ippr_irc_fini __P((void));
int ippr_irc_new __P((fr_info_t *, ap_session_t *, nat_t *));
int ippr_irc_out __P((fr_info_t *, ap_session_t *, nat_t *));
int ippr_irc_send __P((fr_info_t *, nat_t *));
int ippr_irc_complete __P((ircinfo_t *, char *, size_t));
u_short ipf_irc_atoi __P((char **));
static frentry_t ircnatfr;
int irc_proxy_init = 0;
/*
* Initialize local structures.
*/
int ippr_irc_init()
{
bzero((char *)&ircnatfr, sizeof(ircnatfr));
ircnatfr.fr_ref = 1;
ircnatfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
MUTEX_INIT(&ircnatfr.fr_lock, "IRC proxy rule lock");
irc_proxy_init = 1;
return 0;
}
void ippr_irc_fini()
{
if (irc_proxy_init == 1) {
MUTEX_DESTROY(&ircnatfr.fr_lock);
irc_proxy_init = 0;
}
}
const char *ippr_irc_dcctypes[] = {
"CHAT ", /* CHAT chat ipnumber portnumber */
"SEND ", /* SEND filename ipnumber portnumber */
"MOVE ",
"TSEND ",
"SCHAT ",
NULL,
};
/*
* :A PRIVMSG B :^ADCC CHAT chat 0 0^A\r\n
* PRIVMSG B ^ADCC CHAT chat 0 0^A\r\n
*/
int ippr_irc_complete(ircp, buf, len)
ircinfo_t *ircp;
char *buf;
size_t len;
{
register char *s, c;
register size_t i;
u_32_t l;
int j, k;
ircp->irc_ipnum = 0;
ircp->irc_port = 0;
if (len < 31)
return 0;
s = buf;
c = *s++;
i = len - 1;
if ((c != ':') && (c != 'P'))
return 0;
if (c == ':') {
/*
* Loosely check that the source is a nickname of some sort
*/
s++;
c = *s;
ircp->irc_snick = s;
if (!ISALPHA(c))
return 0;
i--;
for (c = *s; !ISSPACE(c) && (i > 0); i--)
c = *s++;
if (i < 31)
return 0;
if (c != 'P')
return 0;
} else
ircp->irc_snick = NULL;
/*
* Check command string
*/
if (strncmp(s, "PRIVMSG ", 8))
return 0;
i -= 8;
s += 8;
c = *s;
ircp->irc_dnick = s;
/*
* Loosely check that the destination is a nickname of some sort
*/
if (!ISALPHA(c))
return 0;
for (; !ISSPACE(c) && (i > 0); i--)
c = *s++;
if (i < 20)
return 0;
s++,
i--;
/*
* Look for a ^A to start the DCC
*/
c = *s;
if (c == ':') {
s++;
c = *s;
}
if (strncmp(s, "\001DCC ", 4))
return 0;
i -= 4;
s += 4;
/*
* Check for a recognised DCC command
*/
for (j = 0, k = 0; ippr_irc_dcctypes[j]; j++) {
k = MIN(strlen(ippr_irc_dcctypes[j]), i);
if (!strncmp(ippr_irc_dcctypes[j], s, k))
break;
}
if (!ippr_irc_dcctypes[j])
return 0;
ircp->irc_type = s;
i -= k;
s += k;
if (i < 11)
return 0;
/*
* Check for the arg
*/
c = *s;
if (ISSPACE(c))
return 0;
ircp->irc_arg = s;
for (; (c != ' ') && (c != '\001') && (i > 0); i--)
c = *s++;
if (c == '\001') /* In reality a ^A can quote another ^A...*/
return 0;
if (i < 5)
return 0;
s++;
i--;
c = *s;
if (!ISDIGIT(c))
return 0;
ircp->irc_addr = s;
/*
* Get the IP#
*/
for (l = 0; ISDIGIT(c) && (i > 0); i--) {
l *= 10;
l += c - '0';
c = *s++;
}
if (i < 4)
return 0;
if (c != ' ')
return 0;
ircp->irc_ipnum = l;
s++;
i--;
c = *s;
if (!ISDIGIT(c))
return 0;
/*
* Get the port#
*/
for (l = 0; ISDIGIT(c) && (i > 0); i--) {
l *= 10;
l += c - '0';
c = *s++;
}
if (i < 3)
return 0;
if (strncmp(s, "\001\r\n", 3))
return 0;
s += 3;
ircp->irc_len = s - buf;
ircp->irc_port = l;
return 1;
}
int ippr_irc_new(fin, aps, nat)
fr_info_t *fin;
ap_session_t *aps;
nat_t *nat;
{
ircinfo_t *irc;
KMALLOC(irc, ircinfo_t *);
if (irc == NULL)
return -1;
fin = fin; /* LINT */
nat = nat; /* LINT */
aps->aps_data = irc;
aps->aps_psiz = sizeof(ircinfo_t);
bzero((char *)irc, sizeof(*irc));
return 0;
}
int ippr_irc_send(fin, nat)
fr_info_t *fin;
nat_t *nat;
{
char ctcpbuf[IPF_IRCBUFSZ], newbuf[IPF_IRCBUFSZ];
tcphdr_t *tcp, tcph, *tcp2 = &tcph;
int off, inc = 0, i, dlen;
size_t nlen = 0, olen;
struct in_addr swip;
u_short a5, sp;
ircinfo_t *irc;
fr_info_t fi;
nat_t *nat2;
u_int a1;
ip_t *ip;
mb_t *m;
#ifdef MENTAT
mb_t *m1;
#endif
m = fin->fin_m;
ip = fin->fin_ip;
tcp = (tcphdr_t *)fin->fin_dp;
bzero(ctcpbuf, sizeof(ctcpbuf));
off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff;
#ifdef __sgi
dlen = fin->fin_plen - off;
#else
dlen = MSGDSIZE(m) - off;
#endif
if (dlen <= 0)
return 0;
COPYDATA(m, off, MIN(sizeof(ctcpbuf), dlen), ctcpbuf);
if (dlen <= 0)
return 0;
ctcpbuf[sizeof(ctcpbuf) - 1] = '\0';
*newbuf = '\0';
irc = nat->nat_aps->aps_data;
if (ippr_irc_complete(irc, ctcpbuf, dlen) == 0)
return 0;
/*
* check that IP address in the PORT/PASV reply is the same as the
* sender of the command - prevents using PORT for port scanning.
*/
if (irc->irc_ipnum != ntohl(nat->nat_inip.s_addr))
return 0;
a5 = irc->irc_port;
/*
* Calculate new address parts for the DCC command
*/
a1 = ntohl(ip->ip_src.s_addr);
olen = irc->irc_len;
i = irc->irc_addr - ctcpbuf;
i++;
(void) strncpy(newbuf, ctcpbuf, i);
/* DO NOT change these! */
#if defined(SNPRINTF) && defined(KERNEL)
SNPRINTF(newbuf, sizeof(newbuf) - i, "%u %u\001\r\n", a1, a5);
#else
(void) sprintf(newbuf, "%u %u\001\r\n", a1, a5);
#endif
nlen = strlen(newbuf);
inc = nlen - olen;
if ((inc + ip->ip_len) > 65535)
return 0;
#ifdef MENTAT
for (m1 = m; m1->b_cont; m1 = m1->b_cont)
;
if ((inc > 0) && (m1->b_datap->db_lim - m1->b_wptr < inc)) {
mblk_t *nm;
/* alloc enough to keep same trailer space for lower driver */
nm = allocb(nlen, BPRI_MED);
PANIC((!nm),("ippr_irc_out: allocb failed"));
nm->b_band = m1->b_band;
nm->b_wptr += nlen;
m1->b_wptr -= olen;
PANIC((m1->b_wptr < m1->b_rptr),
("ippr_irc_out: cannot handle fragmented data block"));
linkb(m1, nm);
} else {
# if SOLARIS && defined(ICK_VALID)
if (m1->b_datap->db_struiolim == m1->b_wptr)
m1->b_datap->db_struiolim += inc;
m1->b_datap->db_struioflag &= ~STRUIO_IP;
# endif
m1->b_wptr += inc;
}
#else
if (inc < 0)
m_adj(m, inc);
/* the mbuf chain will be extended if necessary by m_copyback() */
#endif
COPYBACK(m, off, nlen, newbuf);
if (inc != 0) {
#if defined(MENTAT) || defined(__sgi)
register u_32_t sum1, sum2;
sum1 = ip->ip_len;
sum2 = ip->ip_len + inc;
/* Because ~1 == -2, We really need ~1 == -1 */
if (sum1 > sum2)
sum2--;
sum2 -= sum1;
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
fix_outcksum(fin, &ip->ip_sum, sum2);
#endif
ip->ip_len += inc;
}
/*
* Add skeleton NAT entry for connection which will come back the
* other way.
*/
sp = htons(a5);
/*
* Don't allow the PORT command to specify a port < 1024 due to
* security crap.
*/
if (ntohs(sp) < 1024)
return 0;
/*
* The server may not make the connection back from port 20, but
* it is the most likely so use it here to check for a conflicting
* mapping.
*/
bcopy((caddr_t)fin, (caddr_t)&fi, sizeof(fi));
fi.fin_data[0] = sp;
fi.fin_data[1] = fin->fin_data[1];
nat2 = nat_outlookup(fin, IPN_TCP, nat->nat_p, nat->nat_inip,
ip->ip_dst);
if (nat2 == NULL) {
bcopy((caddr_t)fin, (caddr_t)&fi, sizeof(fi));
bzero((char *)tcp2, sizeof(*tcp2));
tcp2->th_win = htons(8192);
tcp2->th_sport = sp;
tcp2->th_dport = 0; /* XXX - don't specify remote port */
fi.fin_state = NULL;
fi.fin_nat = NULL;
fi.fin_data[0] = ntohs(sp);
fi.fin_data[1] = 0;
fi.fin_dp = (char *)tcp2;
fi.fin_fr = &ircnatfr;
fi.fin_dlen = sizeof(*tcp2);
fi.fin_plen = fi.fin_hlen + sizeof(*tcp2);
swip = ip->ip_src;
ip->ip_src = nat->nat_inip;
nat2 = nat_new(&fi, nat->nat_ptr, NULL,
NAT_SLAVE|IPN_TCP|SI_W_DPORT, NAT_OUTBOUND);
if (nat2 != NULL) {
(void) nat_proto(&fi, nat2, 0);
nat_update(&fi, nat2, nat2->nat_ptr);
(void) fr_addstate(&fi, NULL, SI_W_DPORT);
if (fi.fin_state != NULL)
fr_statederef((ipstate_t **)&fi.fin_state);
}
ip->ip_src = swip;
}
return inc;
}
int ippr_irc_out(fin, aps, nat)
fr_info_t *fin;
ap_session_t *aps;
nat_t *nat;
{
aps = aps; /* LINT */
return ippr_irc_send(fin, nat);
}
-700
View File
@@ -1,700 +0,0 @@
/*
* Copyright (C) 1997-2003 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* $Id: ip_log.c,v 2.75.2.19 2007/09/09 11:32:06 darrenr Exp $
*/
#include <sys/param.h>
#if defined(KERNEL) || defined(_KERNEL)
# undef KERNEL
# undef _KERNEL
# define KERNEL 1
# define _KERNEL 1
#endif
#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \
defined(_KERNEL)
# if (__NetBSD_Version__ < 399001400)
# include "opt_ipfilter_log.h"
# else
# include "opt_ipfilter.h"
# endif
#endif
#if defined(__FreeBSD__) && !defined(IPFILTER_LKM)
# if defined(_KERNEL)
# if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
# include "opt_ipfilter.h"
# endif
# else
# include <osreldate.h>
# endif
#endif
#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
# 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
#endif /* _KERNEL */
#if !SOLARIS && !defined(__hpux) && !defined(linux)
# if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000)
# include <sys/dirent.h>
# else
# include <sys/dir.h>
# endif
# include <sys/mbuf.h>
# include <sys/select.h>
# if __FreeBSD_version >= 500000
# include <sys/selinfo.h>
# endif
#else
# if !defined(__hpux) && defined(_KERNEL)
# include <sys/filio.h>
# include <sys/cred.h>
# include <sys/ddi.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>
#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 */
#ifdef IPFILTER_LOG
# if defined(IPL_SELECT)
# include <machine/sys/user.h>
# include <sys/kthread_iface.h>
# define READ_COLLISION 0x001
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 && defined(_KERNEL)
extern kcondvar_t iplwait;
extern struct pollhead iplpollhead[IPL_LOGSIZE];
# endif
iplog_t **iplh[IPL_LOGSIZE], *iplt[IPL_LOGSIZE], *ipll[IPL_LOGSIZE];
int iplused[IPL_LOGSIZE];
static fr_info_t iplcrc[IPL_LOGSIZE];
int ipl_suppress = 1;
int ipl_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 };
/* ------------------------------------------------------------------------ */
/* 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;
for (i = IPL_LOGMAX; i >= 0; i--) {
iplt[i] = NULL;
ipll[i] = NULL;
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;
}
/* ------------------------------------------------------------------------ */
/* Function: fr_logunload */
/* Returns: Nil */
/* Parameters: Nil */
/* */
/* Clean up any log data that has accumulated without being read. */
/* ------------------------------------------------------------------------ */
void fr_logunload()
{
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];
ipflog_t ipfl;
u_char p;
mb_t *m;
# if (SOLARIS || defined(__hpux)) && defined(_KERNEL) && \
!defined(_INET_IP_STACK_H)
qif_t *ifp;
# else
struct ifnet *ifp;
# endif /* SOLARIS || __hpux */
m = fin->fin_m;
if (m == NULL)
return -1;
ipfl.fl_nattag.ipt_num[0] = 0;
ifp = fin->fin_ifp;
if (fin->fin_exthdr != NULL)
hlen = (char *)fin->fin_dp - (char *)fin->fin_ip;
else
hlen = fin->fin_hlen;
/*
* calculate header size.
*/
if (fin->fin_off == 0) {
p = fin->fin_fi.fi_p;
if (p == IPPROTO_TCP)
hlen += MIN(sizeof(tcphdr_t), fin->fin_dlen);
else if (p == IPPROTO_UDP)
hlen += MIN(sizeof(udphdr_t), fin->fin_dlen);
else if (p == IPPROTO_ICMP) {
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
* caused the error.
*/
switch (icmp->icmp_type)
{
case ICMP_UNREACH :
case ICMP_SOURCEQUENCH :
case ICMP_REDIRECT :
case ICMP_TIMXCEED :
case ICMP_PARAMPROB :
hlen += MIN(sizeof(struct icmp) + 8,
fin->fin_dlen);
break;
default :
hlen += MIN(sizeof(struct icmp),
fin->fin_dlen);
break;
}
}
# 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
* caused the error.
*/
if (icmp->icmp6_type < 128) {
hlen += MIN(sizeof(struct icmp6_hdr) + 8,
fin->fin_dlen);
} else {
hlen += MIN(sizeof(struct icmp6_hdr),
fin->fin_dlen);
}
}
# endif
}
/*
* Get the interface number and name to which this packet is
* currently associated.
*/
# if (SOLARIS || defined(__hpux)) && defined(_KERNEL) && \
!defined(_INET_IP_STACK_H)
ipfl.fl_unit = (u_int)ifp->qf_ppa;
COPYIFNAME(fin->fin_v, ifp, ipfl.fl_ifname);
# else
# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \
(defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
(defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) || \
(SOLARIS && defined(_INET_IP_STACK_H))
COPYIFNAME(fin->fin_v, ifp, ipfl.fl_ifname);
# else
ipfl.fl_unit = (u_int)ifp->if_unit;
# if defined(_KERNEL)
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
COPYIFNAME(fin->fin_v, ifp, ipfl.fl_ifname);
ipfl.fl_ifname[sizeof(ipfl.fl_ifname) - 1] = '\0';
# endif
# 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;
(void) strncpy(ipfl.fl_group, fin->fin_group, FR_GROUPLEN);
if (fin->fin_fr != NULL) {
ipfl.fl_loglevel = fin->fin_fr->fr_loglevel;
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 defined(MENTAT) && defined(_KERNEL)
/*
* Are we copied from the mblk or an aligned array ?
*/
if (fin->fin_ip == (ip_t *)m->b_rptr) {
ptrs[1] = m;
sizes[1] = hlen + mlen;
types[1] = 1;
} else {
ptrs[1] = fin->fin_ip;
sizes[1] = hlen + mlen;
types[1] = 0;
}
# else
ptrs[1] = m;
sizes[1] = hlen + mlen;
types[1] = 1;
# endif /* MENTAT */
return ipllog(IPL_LOGIPF, fin, ptrs, sizes, types, 2);
}
/* ------------------------------------------------------------------------ */
/* 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;
void **items;
size_t *itemsz;
int *types, cnt;
{
u_char *buf, *ptr;
iplog_t *ipl;
size_t len;
int i;
SPL_INT(s);
/*
* 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.
*/
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 = sizeof(iplog_t); i < cnt; i++)
len += itemsz[i];
/*
* check that we have space to record this information and can
* allocate that much.
*/
KMALLOCS(buf, u_char *, len);
if (buf == NULL)
return -1;
SPL_NET(s);
MUTEX_ENTER(&ipl_mutex);
if ((iplused[dev] + len) > ipl_logsize) {
MUTEX_EXIT(&ipl_mutex);
SPL_X(s);
KFREES(buf, len);
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[dev];
ipl->ipl_count = 1;
ipl->ipl_next = NULL;
ipl->ipl_dsize = len;
#ifdef _KERNEL
GETKTIME(&ipl->ipl_sec);
#else
ipl->ipl_sec = 0;
ipl->ipl_usec = 0;
#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, 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], (char *)ptr);
}
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);
pollwakeup(&iplpollhead[dev], POLLRDNORM);
# else
MUTEX_EXIT(&ipl_mutex);
WAKEUP(iplh, dev);
POLLWAKEUP(dev);
# endif
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;
{
size_t dlen, copied;
int error = 0;
iplog_t *ipl;
SPL_INT(s);
/*
* Sanity checks. Make sure the minor # is valid and we're copying
* a valid chunk of data.
*/
if (IPL_LOGMAX < unit)
return ENXIO;
if (uio->uio_resid == 0)
return 0;
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.
*/
SPL_NET(s);
MUTEX_ENTER(&ipl_mutex);
while (iplt[unit] == NULL) {
# if SOLARIS && defined(_KERNEL)
if (!cv_wait_sig(&iplwait, &ipl_mutex.ipf_lk)) {
MUTEX_EXIT(&ipl_mutex);
return EINTR;
}
# else
# 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 >= 199101) || defined(__FreeBSD__) || defined(__osf__)
uio->uio_rw = UIO_READ;
# endif
for (copied = 0; (ipl = iplt[unit]) != NULL; copied += dlen) {
dlen = ipl->ipl_dsize;
if (dlen > uio->uio_resid)
break;
/*
* Don't hold the mutex over the uiomove call.
*/
iplt[unit] = ipl->ipl_next;
iplused[unit] -= dlen;
MUTEX_EXIT(&ipl_mutex);
SPL_X(s);
error = UIOMOVE(ipl, dlen, UIO_READ, uio);
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(ipl, dlen);
SPL_NET(s);
}
if (!iplt[unit]) {
iplused[unit] = 0;
iplh[unit] = &iplt[unit];
ipll[unit] = NULL;
}
MUTEX_EXIT(&ipl_mutex);
SPL_X(s);
return error;
}
/* ------------------------------------------------------------------------ */
/* 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;
SPL_INT(s);
SPL_NET(s);
MUTEX_ENTER(&ipl_mutex);
while ((ipl = iplt[unit]) != NULL) {
iplt[unit] = ipl->ipl_next;
KFREES(ipl, ipl->ipl_dsize);
}
iplh[unit] = &iplt[unit];
ipll[unit] = NULL;
used = iplused[unit];
iplused[unit] = 0;
bzero((char *)&iplcrc[unit], FI_CSIZE);
MUTEX_EXIT(&ipl_mutex);
SPL_X(s);
return used;
}
/* ------------------------------------------------------------------------ */
/* Function: ipflog_canread */
/* Returns: int - 0 == no data to read, 1 = data present */
/* Parameters: unit(I) - device we are reading from */
/* */
/* Returns an indication of whether or not there is data present in the */
/* current buffer for the selected ipf device. */
/* ------------------------------------------------------------------------ */
int ipflog_canread(unit)
int unit;
{
return iplt[unit] != NULL;
}
#endif /* IPFILTER_LOG */
-695
View File
@@ -1,695 +0,0 @@
/*
* Copyright (C) 2002-2003 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*/
#if defined(KERNEL) || defined(_KERNEL)
# undef KERNEL
# undef _KERNEL
# define KERNEL 1
# define _KERNEL 1
#endif
#if defined(__osf__)
# define _PROTO_NET_H_
#endif
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/file.h>
#if __FreeBSD_version >= 220000 && defined(_KERNEL)
# include <sys/fcntl.h>
# include <sys/filio.h>
#else
# include <sys/ioctl.h>
#endif
#if !defined(_KERNEL)
# include <string.h>
# define _KERNEL
# ifdef __OpenBSD__
struct file;
# endif
# include <sys/uio.h>
# undef _KERNEL
#endif
#include <sys/socket.h>
#if (defined(__osf__) || defined(AIX) || defined(__hpux) || defined(__sgi)) && defined(_KERNEL)
# include "radix_ipf_local.h"
# define _RADIX_H_
#endif
#include <net/if.h>
#if defined(__FreeBSD__)
# include <sys/cdefs.h>
# include <sys/proc.h>
#endif
#if defined(_KERNEL)
# include <sys/systm.h>
# if !defined(__SVR4) && !defined(__svr4__)
# include <sys/mbuf.h>
# endif
#endif
#include <netinet/in.h>
#include "netinet/ip_compat.h"
#include "netinet/ip_fil.h"
#include "netinet/ip_pool.h"
#include "netinet/ip_htable.h"
#include "netinet/ip_lookup.h"
/* END OF INCLUDES */
#if !defined(lint)
static const char rcsid[] = "@(#)$Id: ip_lookup.c,v 2.35.2.19 2007/10/11 09:05:51 darrenr Exp $";
#endif
#ifdef IPFILTER_LOOKUP
int ip_lookup_inited = 0;
static int iplookup_addnode __P((caddr_t));
static int iplookup_delnode __P((caddr_t data));
static int iplookup_addtable __P((caddr_t));
static int iplookup_deltable __P((caddr_t));
static int iplookup_stats __P((caddr_t));
static int iplookup_flush __P((caddr_t));
static int iplookup_iterate __P((void *, int, void *));
static int iplookup_deltok __P((void *, int, void *));
/* ------------------------------------------------------------------------ */
/* Function: iplookup_init */
/* Returns: int - 0 = success, else error */
/* Parameters: Nil */
/* */
/* Initialise all of the subcomponents of the lookup infrstructure. */
/* ------------------------------------------------------------------------ */
int ip_lookup_init()
{
if (ip_pool_init() == -1)
return -1;
RWLOCK_INIT(&ip_poolrw, "ip pool rwlock");
ip_lookup_inited = 1;
return 0;
}
/* ------------------------------------------------------------------------ */
/* Function: iplookup_unload */
/* Returns: int - 0 = success, else error */
/* Parameters: Nil */
/* */
/* Free up all pool related memory that has been allocated whilst IPFilter */
/* has been running. Also, do any other deinitialisation required such */
/* ip_lookup_init() can be called again, safely. */
/* ------------------------------------------------------------------------ */
void ip_lookup_unload()
{
ip_pool_fini();
fr_htable_unload();
if (ip_lookup_inited == 1) {
RW_DESTROY(&ip_poolrw);
ip_lookup_inited = 0;
}
}
/* ------------------------------------------------------------------------ */
/* Function: iplookup_ioctl */
/* Returns: int - 0 = success, else error */
/* Parameters: data(IO) - pointer to ioctl data to be copied to/from user */
/* space. */
/* cmd(I) - ioctl command number */
/* mode(I) - file mode bits used with open */
/* */
/* Handle ioctl commands sent to the ioctl device. For the most part, this */
/* involves just calling another function to handle the specifics of each */
/* command. */
/* ------------------------------------------------------------------------ */
int ip_lookup_ioctl(data, cmd, mode, uid, ctx)
caddr_t data;
ioctlcmd_t cmd;
int mode, uid;
void *ctx;
{
int err;
SPL_INT(s);
mode = mode; /* LINT */
SPL_NET(s);
switch (cmd)
{
case SIOCLOOKUPADDNODE :
case SIOCLOOKUPADDNODEW :
WRITE_ENTER(&ip_poolrw);
err = iplookup_addnode(data);
RWLOCK_EXIT(&ip_poolrw);
break;
case SIOCLOOKUPDELNODE :
case SIOCLOOKUPDELNODEW :
WRITE_ENTER(&ip_poolrw);
err = iplookup_delnode(data);
RWLOCK_EXIT(&ip_poolrw);
break;
case SIOCLOOKUPADDTABLE :
WRITE_ENTER(&ip_poolrw);
err = iplookup_addtable(data);
RWLOCK_EXIT(&ip_poolrw);
break;
case SIOCLOOKUPDELTABLE :
WRITE_ENTER(&ip_poolrw);
err = iplookup_deltable(data);
RWLOCK_EXIT(&ip_poolrw);
break;
case SIOCLOOKUPSTAT :
case SIOCLOOKUPSTATW :
WRITE_ENTER(&ip_poolrw);
err = iplookup_stats(data);
RWLOCK_EXIT(&ip_poolrw);
break;
case SIOCLOOKUPFLUSH :
WRITE_ENTER(&ip_poolrw);
err = iplookup_flush(data);
RWLOCK_EXIT(&ip_poolrw);
break;
case SIOCLOOKUPITER :
err = iplookup_iterate(data, uid, ctx);
break;
case SIOCIPFDELTOK :
err = iplookup_deltok(data, uid, ctx);
break;
default :
err = EINVAL;
break;
}
SPL_X(s);
return err;
}
/* ------------------------------------------------------------------------ */
/* Function: iplookup_addnode */
/* Returns: int - 0 = success, else error */
/* Parameters: data(I) - pointer to data from ioctl call */
/* */
/* Add a new data node to a lookup structure. First, check to see if the */
/* parent structure refered to by name exists and if it does, then go on to */
/* add a node to it. */
/* ------------------------------------------------------------------------ */
static int iplookup_addnode(data)
caddr_t data;
{
ip_pool_node_t node, *m;
iplookupop_t op;
iphtable_t *iph;
iphtent_t hte;
ip_pool_t *p;
int err;
err = BCOPYIN(data, &op, sizeof(op));
if (err != 0)
return EFAULT;
if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX)
return EINVAL;
op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
switch (op.iplo_type)
{
case IPLT_POOL :
if (op.iplo_size != sizeof(node))
return EINVAL;
err = COPYIN(op.iplo_struct, &node, sizeof(node));
if (err != 0)
return EFAULT;
p = ip_pool_find(op.iplo_unit, op.iplo_name);
if (p == NULL)
return ESRCH;
/*
* add an entry to a pool - return an error if it already
* exists remove an entry from a pool - if it exists
* - in both cases, the pool *must* exist!
*/
m = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask);
if (m)
return EEXIST;
err = ip_pool_insert(p, &node.ipn_addr.adf_addr,
&node.ipn_mask.adf_addr, node.ipn_info);
break;
case IPLT_HASH :
if (op.iplo_size != sizeof(hte))
return EINVAL;
err = COPYIN(op.iplo_struct, &hte, sizeof(hte));
if (err != 0)
return EFAULT;
iph = fr_findhtable(op.iplo_unit, op.iplo_name);
if (iph == NULL)
return ESRCH;
err = fr_addhtent(iph, &hte);
break;
default :
err = EINVAL;
break;
}
return err;
}
/* ------------------------------------------------------------------------ */
/* Function: iplookup_delnode */
/* Returns: int - 0 = success, else error */
/* Parameters: data(I) - pointer to data from ioctl call */
/* */
/* Delete a node from a lookup table by first looking for the table it is */
/* in and then deleting the entry that gets found. */
/* ------------------------------------------------------------------------ */
static int iplookup_delnode(data)
caddr_t data;
{
ip_pool_node_t node, *m;
iplookupop_t op;
iphtable_t *iph;
iphtent_t hte;
ip_pool_t *p;
int err;
err = BCOPYIN(data, &op, sizeof(op));
if (err != 0)
return EFAULT;
if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX)
return EINVAL;
op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
switch (op.iplo_type)
{
case IPLT_POOL :
if (op.iplo_size != sizeof(node))
return EINVAL;
err = COPYIN(op.iplo_struct, &node, sizeof(node));
if (err != 0)
return EFAULT;
p = ip_pool_find(op.iplo_unit, op.iplo_name);
if (!p)
return ESRCH;
m = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask);
if (m == NULL)
return ENOENT;
err = ip_pool_remove(p, m);
break;
case IPLT_HASH :
if (op.iplo_size != sizeof(hte))
return EINVAL;
err = COPYIN(op.iplo_struct, &hte, sizeof(hte));
if (err != 0)
return EFAULT;
iph = fr_findhtable(op.iplo_unit, op.iplo_name);
if (iph == NULL)
return ESRCH;
err = fr_delhtent(iph, &hte);
break;
default :
err = EINVAL;
break;
}
return err;
}
/* ------------------------------------------------------------------------ */
/* Function: iplookup_addtable */
/* Returns: int - 0 = success, else error */
/* Parameters: data(I) - pointer to data from ioctl call */
/* */
/* Create a new lookup table, if one doesn't already exist using the name */
/* for this one. */
/* ------------------------------------------------------------------------ */
static int iplookup_addtable(data)
caddr_t data;
{
iplookupop_t op;
int err;
err = BCOPYIN(data, &op, sizeof(op));
if (err != 0)
return EFAULT;
if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX)
return EINVAL;
op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
switch (op.iplo_type)
{
case IPLT_POOL :
if (ip_pool_find(op.iplo_unit, op.iplo_name) != NULL)
err = EEXIST;
else
err = ip_pool_create(&op);
break;
case IPLT_HASH :
if (fr_findhtable(op.iplo_unit, op.iplo_name) != NULL)
err = EEXIST;
else
err = fr_newhtable(&op);
break;
default :
err = EINVAL;
break;
}
/*
* For anonymous pools, copy back the operation struct because in the
* case of success it will contain the new table's name.
*/
if ((err == 0) && ((op.iplo_arg & LOOKUP_ANON) != 0)) {
err = BCOPYOUT(&op, data, sizeof(op));
if (err != 0)
err = EFAULT;
}
return err;
}
/* ------------------------------------------------------------------------ */
/* Function: iplookup_deltable */
/* Returns: int - 0 = success, else error */
/* Parameters: data(I) - pointer to data from ioctl call */
/* */
/* Decodes ioctl request to remove a particular hash table or pool and */
/* calls the relevant function to do the cleanup. */
/* ------------------------------------------------------------------------ */
static int iplookup_deltable(data)
caddr_t data;
{
iplookupop_t op;
int err;
err = BCOPYIN(data, &op, sizeof(op));
if (err != 0)
return EFAULT;
if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX)
return EINVAL;
op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
/*
* create a new pool - fail if one already exists with
* the same #
*/
switch (op.iplo_type)
{
case IPLT_POOL :
err = ip_pool_destroy(op.iplo_unit, op.iplo_name);
break;
case IPLT_HASH :
err = fr_removehtable(op.iplo_unit, op.iplo_name);
break;
default :
err = EINVAL;
break;
}
return err;
}
/* ------------------------------------------------------------------------ */
/* Function: iplookup_stats */
/* Returns: int - 0 = success, else error */
/* Parameters: data(I) - pointer to data from ioctl call */
/* */
/* Copy statistical information from inside the kernel back to user space. */
/* ------------------------------------------------------------------------ */
static int iplookup_stats(data)
caddr_t data;
{
iplookupop_t op;
int err;
err = BCOPYIN(data, &op, sizeof(op));
if (err != 0)
return EFAULT;
if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX)
return EINVAL;
switch (op.iplo_type)
{
case IPLT_POOL :
err = ip_pool_statistics(&op);
break;
case IPLT_HASH :
err = fr_gethtablestat(&op);
break;
default :
err = EINVAL;
break;
}
return err;
}
/* ------------------------------------------------------------------------ */
/* Function: iplookup_flush */
/* Returns: int - 0 = success, else error */
/* Parameters: data(I) - pointer to data from ioctl call */
/* */
/* A flush is called when we want to flush all the nodes from a particular */
/* entry in the hash table/pool or want to remove all groups from those. */
/* ------------------------------------------------------------------------ */
static int iplookup_flush(data)
caddr_t data;
{
int err, unit, num, type;
iplookupflush_t flush;
err = BCOPYIN(data, &flush, sizeof(flush));
if (err != 0)
return EFAULT;
unit = flush.iplf_unit;
if ((unit < 0 || unit > IPL_LOGMAX) && (unit != IPLT_ALL))
return EINVAL;
flush.iplf_name[sizeof(flush.iplf_name) - 1] = '\0';
type = flush.iplf_type;
err = EINVAL;
num = 0;
if (type == IPLT_POOL || type == IPLT_ALL) {
err = 0;
num = ip_pool_flush(&flush);
}
if (type == IPLT_HASH || type == IPLT_ALL) {
err = 0;
num += fr_flushhtable(&flush);
}
if (err == 0) {
flush.iplf_count = num;
err = BCOPYOUT(&flush, data, sizeof(flush));
if (err != 0)
err = EFAULT;
}
return err;
}
/* ------------------------------------------------------------------------ */
/* Function: ip_lookup_delref */
/* Returns: void */
/* Parameters: type(I) - table type to operate on */
/* ptr(I) - pointer to object to remove reference for */
/* */
/* This function organises calling the correct deref function for a given */
/* type of object being passed into it. */
/* ------------------------------------------------------------------------ */
void ip_lookup_deref(type, ptr)
int type;
void *ptr;
{
if (ptr == NULL)
return;
WRITE_ENTER(&ip_poolrw);
switch (type)
{
case IPLT_POOL :
ip_pool_deref(ptr);
break;
case IPLT_HASH :
fr_derefhtable(ptr);
break;
}
RWLOCK_EXIT(&ip_poolrw);
}
/* ------------------------------------------------------------------------ */
/* Function: iplookup_iterate */
/* Returns: int - 0 = success, else error */
/* Parameters: data(I) - pointer to data from ioctl call */
/* uid(I) - uid of caller */
/* ctx(I) - pointer to give the uid context */
/* */
/* Decodes ioctl request to step through either hash tables or pools. */
/* ------------------------------------------------------------------------ */
static int iplookup_iterate(data, uid, ctx)
void *data;
int uid;
void *ctx;
{
ipflookupiter_t iter;
ipftoken_t *token;
int err;
SPL_INT(s);
err = fr_inobj(data, &iter, IPFOBJ_LOOKUPITER);
if (err != 0)
return err;
if (iter.ili_unit > IPL_LOGMAX)
return EINVAL;
if (iter.ili_ival != IPFGENITER_LOOKUP)
return EINVAL;
SPL_SCHED(s);
token = ipf_findtoken(iter.ili_key, uid, ctx);
if (token == NULL) {
RWLOCK_EXIT(&ipf_tokens);
SPL_X(s);
return ESRCH;
}
switch (iter.ili_type)
{
case IPLT_POOL :
err = ip_pool_getnext(token, &iter);
break;
case IPLT_HASH :
err = fr_htable_getnext(token, &iter);
break;
default :
err = EINVAL;
break;
}
RWLOCK_EXIT(&ipf_tokens);
SPL_X(s);
return err;
}
/* ------------------------------------------------------------------------ */
/* Function: iplookup_iterderef */
/* Returns: int - 0 = success, else error */
/* Parameters: data(I) - pointer to data from ioctl call */
/* */
/* Decodes ioctl request to remove a particular hash table or pool and */
/* calls the relevant function to do the cleanup. */
/* ------------------------------------------------------------------------ */
void ip_lookup_iterderef(type, data)
u_32_t type;
void *data;
{
iplookupiterkey_t key;
key.ilik_key = type;
if (key.ilik_unstr.ilik_ival != IPFGENITER_LOOKUP)
return;
switch (key.ilik_unstr.ilik_type)
{
case IPLT_HASH :
fr_htable_iterderef((u_int)key.ilik_unstr.ilik_otype,
(int)key.ilik_unstr.ilik_unit, data);
break;
case IPLT_POOL :
ip_pool_iterderef((u_int)key.ilik_unstr.ilik_otype,
(int)key.ilik_unstr.ilik_unit, data);
break;
}
}
/* ------------------------------------------------------------------------ */
/* Function: iplookup_deltok */
/* Returns: int - 0 = success, else error */
/* Parameters: data(I) - pointer to data from ioctl call */
/* uid(I) - uid of caller */
/* ctx(I) - pointer to give the uid context */
/* */
/* Deletes the token identified by the combination of (type,uid,ctx) */
/* "key" is a combination of the table type, iterator type and the unit for */
/* which the token was being used. */
/* ------------------------------------------------------------------------ */
static int iplookup_deltok(data, uid, ctx)
void *data;
int uid;
void *ctx;
{
int error, key;
SPL_INT(s);
SPL_SCHED(s);
error = BCOPYIN(data, &key, sizeof(key));
if (error == 0)
error = ipf_deltoken(key, uid, ctx);
SPL_X(s);
return error;
}
#else /* IPFILTER_LOOKUP */
/*ARGSUSED*/
int ip_lookup_ioctl(data, cmd, mode, uid, ctx)
caddr_t data;
ioctlcmd_t cmd;
int mode, uid;
void *ctx;
{
return EIO;
}
#endif /* IPFILTER_LOOKUP */
-95
View File
@@ -1,95 +0,0 @@
#ifndef __IP_LOOKUP_H__
#define __IP_LOOKUP_H__
#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51)
# define SIOCLOOKUPADDTABLE _IOWR('r', 60, struct iplookupop)
# define SIOCLOOKUPDELTABLE _IOWR('r', 61, struct iplookupop)
# define SIOCLOOKUPSTAT _IOWR('r', 64, struct iplookupop)
# define SIOCLOOKUPSTATW _IOW('r', 64, struct iplookupop)
# define SIOCLOOKUPFLUSH _IOWR('r', 65, struct iplookupflush)
# define SIOCLOOKUPADDNODE _IOWR('r', 67, struct iplookupop)
# define SIOCLOOKUPADDNODEW _IOW('r', 67, struct iplookupop)
# define SIOCLOOKUPDELNODE _IOWR('r', 68, struct iplookupop)
# define SIOCLOOKUPDELNODEW _IOW('r', 68, struct iplookupop)
#else
# define SIOCLOOKUPADDTABLE _IOWR(r, 60, struct iplookupop)
# define SIOCLOOKUPDELTABLE _IOWR(r, 61, struct iplookupop)
# define SIOCLOOKUPSTAT _IOWR(r, 64, struct iplookupop)
# define SIOCLOOKUPSTATW _IOW(r, 64, struct iplookupop)
# define SIOCLOOKUPFLUSH _IOWR(r, 65, struct iplookupflush)
# define SIOCLOOKUPADDNODE _IOWR(r, 67, struct iplookupop)
# define SIOCLOOKUPADDNODEW _IOW(r, 67, struct iplookupop)
# define SIOCLOOKUPDELNODE _IOWR(r, 68, struct iplookupop)
# define SIOCLOOKUPDELNODEW _IOW(r, 68, struct iplookupop)
#endif
typedef struct iplookupop {
int iplo_type; /* IPLT_* */
int iplo_unit; /* IPL_LOG* */
u_int iplo_arg;
char iplo_name[FR_GROUPLEN];
size_t iplo_size; /* sizeof struct at iplo_struct */
void *iplo_struct;
} iplookupop_t;
#define LOOKUP_ANON 0x80000000
typedef struct iplookupflush {
int iplf_type; /* IPLT_* */
int iplf_unit; /* IPL_LOG* */
u_int iplf_arg;
size_t iplf_count;
char iplf_name[FR_GROUPLEN];
} iplookupflush_t;
typedef struct iplookuplink {
int ipll_type; /* IPLT_* */
int ipll_unit; /* IPL_LOG* */
u_int ipll_num;
char ipll_group[FR_GROUPLEN];
} iplookuplink_t;
#define IPLT_ALL -1
#define IPLT_NONE 0
#define IPLT_POOL 1
#define IPLT_HASH 2
#define IPLT_ANON 0x80000000
typedef union {
struct iplookupiterkey {
char ilik_ival;
u_char ilik_type; /* IPLT_* */
u_char ilik_otype;
u_char ilik_unit; /* IPL_LOG* */
} ilik_unstr;
u_32_t ilik_key;
} iplookupiterkey_t;
typedef struct ipflookupiter {
int ili_nitems;
iplookupiterkey_t ili_lkey;
char ili_name[FR_GROUPLEN];
void *ili_data;
} ipflookupiter_t;
#define ili_key ili_lkey.ilik_key
#define ili_ival ili_lkey.ilik_unstr.ilik_ival
#define ili_unit ili_lkey.ilik_unstr.ilik_unit
#define ili_type ili_lkey.ilik_unstr.ilik_type
#define ili_otype ili_lkey.ilik_unstr.ilik_otype
#define IPFLOOKUPITER_LIST 0
#define IPFLOOKUPITER_NODE 1
extern int ip_lookup_init __P((void));
extern int ip_lookup_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *));
extern void ip_lookup_unload __P((void));
extern void ip_lookup_deref __P((int, void *));
extern void ip_lookup_iterderef __P((u_32_t, void *));
#endif /* __IP_LOOKUP_H__ */
File diff suppressed because it is too large Load Diff
-469
View File
@@ -1,469 +0,0 @@
/*
* 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.90.2.20 2007/09/25 08:27:32 darrenr Exp $
*/
#ifndef __IP_NAT_H__
#define __IP_NAT_H__
#ifndef SOLARIS
#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
#endif
#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51)
#define SIOCADNAT _IOW('r', 60, struct ipfobj)
#define SIOCRMNAT _IOW('r', 61, struct ipfobj)
#define SIOCGNATS _IOWR('r', 62, struct ipfobj)
#define SIOCGNATL _IOWR('r', 63, struct ipfobj)
#else
#define SIOCADNAT _IOW(r, 60, struct ipfobj)
#define SIOCRMNAT _IOW(r, 61, struct ipfobj)
#define SIOCGNATS _IOWR(r, 62, struct ipfobj)
#define SIOCGNATL _IOWR(r, 63, struct ipfobj)
#endif
#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
# define NAT_SIZE 2047
# else
# define NAT_SIZE 127
# endif
#endif
#ifndef RDR_SIZE
# ifdef LARGE_NAT
# define RDR_SIZE 2047
# else
# define RDR_SIZE 127
# endif
#endif
#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
# define NAT_TABLE_SZ 16383
# else
# define NAT_TABLE_SZ 2047
# endif
#endif
#ifndef APR_LABELLEN
#define APR_LABELLEN 16
#endif
#define NAT_HW_CKSUM 0x80000000
#define DEF_NAT_AGE 1200 /* 10 minutes (600 seconds) */
struct ipstate;
struct ap_session;
typedef struct nat {
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;
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 */
int nat_redir; /* copy of in_redir */
u_32_t nat_seqnext[2];
} 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
#define nat_die nat_tqe.tqe_die
#define nat_touched nat_tqe.tqe_touched
/*
* 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 /* Don't use the port # in the NAT rule */
#define NAT_TCPUDP (NAT_TCP|NAT_UDP)
#define NAT_TCPUDPICMP (NAT_TCP|NAT_UDP|NAT_ICMPERR)
#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 {
ipfmutex_t in_lock;
struct ipnat *in_next; /* NAT rule list next */
struct ipnat *in_rnext; /* rdr rule hash next */
struct ipnat **in_prnext; /* prior rdr next ptr */
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_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
#define in_dtop in_tuc.ftu_dtop
#define in_sport in_tuc.ftu_sport
#define in_dport in_tuc.ftu_dport
/*
* 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
#define MAPBLK_MINPORT 1024 /* don't use reserved ports for src port */
#define USABLE_PORTS (65536 - MAPBLK_MINPORT)
#define IPN_CMPSIZ (sizeof(ipnat_t) - offsetof(ipnat_t, in_flags))
typedef struct natlookup {
struct in_addr nl_inip;
struct in_addr nl_outip;
struct in_addr nl_realip;
int nl_flags;
u_short nl_inport;
u_short nl_outport;
u_short nl_realport;
} natlookup_t;
typedef struct nat_save {
void *ipn_next;
struct nat ipn_nat;
struct ipnat ipn_ipnat;
struct frentry ipn_fr;
int ipn_dsize;
char ipn_data[4];
} nat_save_t;
#define ipn_rule ipn_nat.nat_fr
typedef struct natget {
void *ng_ptr;
int ng_sz;
} natget_t;
/*
* 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_hnext;
struct hostmap **hm_phnext;
struct hostmap *hm_next;
struct hostmap **hm_pnext;
struct ipnat *hm_ipnat;
struct in_addr hm_srcip;
struct in_addr hm_dstip;
struct in_addr hm_mapip;
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;
u_long ns_added;
u_long ns_expire;
u_long ns_inuse;
u_long ns_logged;
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;
hostmap_t *ns_maplist;
u_long *ns_bucketlen[2];
u_long ns_ticks;
u_int ns_orphans;
} natstat_t;
typedef struct natlog {
struct in_addr nl_origip;
struct in_addr nl_outip;
struct in_addr nl_inip;
u_short nl_origport;
u_short nl_outport;
u_short nl_inport;
u_short nl_type;
int nl_rule;
U_QUAD_T nl_pkts[2];
U_QUAD_T nl_bytes[2];
u_char nl_p;
} natlog_t;
#define NL_NEWMAP NAT_MAP
#define NL_NEWRDR NAT_REDIRECT
#define NL_NEWBIMAP NAT_BIMAP
#define NL_NEWBLOCK NAT_MAPBLK
#define NL_DESTROY 0xfffc
#define NL_CLONE 0xfffd
#define NL_FLUSH 0xfffe
#define NL_EXPIRE 0xffff
#define NAT_HASH_FN(k,l,m) (((k) + ((k) >> 12) + l) % (m))
#define LONG_SUM(in) (((in) & 0xffff) + ((in) >> 16))
#define CALC_SUMD(s1, s2, sd) { \
(s1) = ((s1) & 0xffff) + ((s1) >> 16); \
(s2) = ((s2) & 0xffff) + ((s2) >> 16); \
/* Do it twice */ \
(s1) = ((s1) & 0xffff) + ((s1) >> 16); \
(s2) = ((s2) & 0xffff) + ((s2) >> 16); \
/* Because ~1 == -2, We really need ~1 == -1 */ \
if ((s1) > (s2)) (s2)--; \
(sd) = (s2) - (s1); \
(sd) = ((sd) & 0xffff) + ((sd) >> 16); }
#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 int fr_nat_doflush;
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 ipftq_t *nat_utqe;
extern natstat_t nat_stats;
#if defined(__OpenBSD__)
extern void nat_ifdetach __P((void *));
#endif
extern int fr_nat_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *));
extern int fr_natinit __P((void));
extern nat_t *nat_new __P((fr_info_t *, ipnat_t *, nat_t **, u_int, int));
extern nat_t *nat_outlookup __P((fr_info_t *, u_int, u_int, struct in_addr,
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));
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_icmperrorlookup __P((fr_info_t *, int));
extern nat_t *nat_icmperror __P((fr_info_t *, u_int *, int));
extern void nat_delete __P((struct nat *, int));
extern int nat_insert __P((nat_t *, int));
extern int fr_checknatout __P((fr_info_t *, u_32_t *));
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 fr_ipnatderef __P((ipnat_t **));
extern void fr_natderef __P((nat_t **));
extern u_short *nat_proto __P((fr_info_t *, nat_t *, u_int));
extern void nat_update __P((fr_info_t *, nat_t *, ipnat_t *));
extern void fr_setnatqueue __P((nat_t *, int));
extern void fr_hostmapdel __P((hostmap_t **));
#endif /* __IP_NAT_H__ */
@@ -1,118 +0,0 @@
/*
* Simple netbios-dgm transparent proxy for in-kernel use.
* For use with the NAT code.
* $Id: ip_netbios_pxy.c,v 2.8.2.1 2005/08/20 13:48:23 darrenr Exp $
*/
/*-
* Copyright (c) 2002-2003 Paul J. Ledbetter III
* 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 AUTHOR AND CONTRIBUTORS ``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 AUTHOR 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.
*
* $Id: ip_netbios_pxy.c,v 2.8.2.1 2005/08/20 13:48:23 darrenr Exp $
*/
#define IPF_NETBIOS_PROXY
int ippr_netbios_init __P((void));
void ippr_netbios_fini __P((void));
int ippr_netbios_out __P((fr_info_t *, ap_session_t *, nat_t *));
static frentry_t netbiosfr;
int netbios_proxy_init = 0;
/*
* Initialize local structures.
*/
int ippr_netbios_init()
{
bzero((char *)&netbiosfr, sizeof(netbiosfr));
netbiosfr.fr_ref = 1;
netbiosfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
MUTEX_INIT(&netbiosfr.fr_lock, "NETBIOS proxy rule lock");
netbios_proxy_init = 1;
return 0;
}
void ippr_netbios_fini()
{
if (netbios_proxy_init == 1) {
MUTEX_DESTROY(&netbiosfr.fr_lock);
netbios_proxy_init = 0;
}
}
int ippr_netbios_out(fin, aps, nat)
fr_info_t *fin;
ap_session_t *aps;
nat_t *nat;
{
char dgmbuf[6];
int off, dlen;
udphdr_t *udp;
ip_t *ip;
mb_t *m;
aps = aps; /* LINT */
nat = nat; /* LINT */
m = fin->fin_m;
dlen = fin->fin_dlen - sizeof(*udp);
/*
* no net bios datagram could possibly be shorter than this
*/
if (dlen < 11)
return 0;
ip = fin->fin_ip;
udp = (udphdr_t *)fin->fin_dp;
off = (char *)udp - (char *)ip + sizeof(*udp) + fin->fin_ipoff;
/*
* move past the
* ip header;
* udp header;
* 4 bytes into the net bios dgm header.
* According to rfc1002, this should be the exact location of
* the source address/port
*/
off += 4;
/* Copy NATed source Address/port*/
dgmbuf[0] = (char)((ip->ip_src.s_addr ) &0xFF);
dgmbuf[1] = (char)((ip->ip_src.s_addr >> 8) &0xFF);
dgmbuf[2] = (char)((ip->ip_src.s_addr >> 16)&0xFF);
dgmbuf[3] = (char)((ip->ip_src.s_addr >> 24)&0xFF);
dgmbuf[4] = (char)((udp->uh_sport )&0xFF);
dgmbuf[5] = (char)((udp->uh_sport >> 8)&0xFF);
/* replace data in packet */
COPYBACK(m, off, sizeof(dgmbuf), dgmbuf);
return 0;
}
-992
View File
@@ -1,992 +0,0 @@
/*
* Copyright (C) 1993-2001, 2003 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*/
#if defined(KERNEL) || defined(_KERNEL)
# undef KERNEL
# undef _KERNEL
# define KERNEL 1
# define _KERNEL 1
#endif
#if defined(__osf__)
# define _PROTO_NET_H_
#endif
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/file.h>
#if !defined(_KERNEL) && !defined(__KERNEL__)
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# define _KERNEL
# ifdef __OpenBSD__
struct file;
# endif
# include <sys/uio.h>
# undef _KERNEL
#else
# include <sys/systm.h>
# if defined(NetBSD) && (__NetBSD_Version__ >= 104000000)
# include <sys/proc.h>
# endif
#endif
#include <sys/time.h>
#if !defined(linux)
# include <sys/protosw.h>
#endif
#include <sys/socket.h>
#if defined(_KERNEL) && (!defined(__SVR4) && !defined(__svr4__))
# include <sys/mbuf.h>
#endif
#if defined(__SVR4) || defined(__svr4__)
# include <sys/filio.h>
# include <sys/byteorder.h>
# ifdef _KERNEL
# include <sys/dditypes.h>
# endif
# include <sys/stream.h>
# include <sys/kmem.h>
#endif
#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
# include <sys/malloc.h>
#endif
#if defined(SOLARIS2) && !defined(_KERNEL)
# include "radix_ipf.h"
#endif
#if defined(_KERNEL) && (defined(__osf__) || defined(AIX) || \
defined(__hpux) || defined(__sgi))
# include "radix_ipf_local.h"
# define _RADIX_H_
#endif
#include <net/if.h>
#include <netinet/in.h>
#include "netinet/ip_compat.h"
#include "netinet/ip_fil.h"
#include "netinet/ip_pool.h"
#if defined(IPFILTER_LOOKUP) && defined(_KERNEL) && \
((BSD >= 198911) && !defined(__osf__) && \
!defined(__hpux) && !defined(__sgi))
static int rn_freenode __P((struct radix_node *, void *));
#endif
/* END OF INCLUDES */
#if !defined(lint)
static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
static const char rcsid[] = "@(#)$Id: ip_pool.c,v 2.55.2.24 2007/10/10 09:45:37 darrenr Exp $";
#endif
#ifdef IPFILTER_LOOKUP
# if !defined(RADIX_NODE_HEAD_LOCK) || !defined(RADIX_NODE_HEAD_UNLOCK) || \
!defined(_KERNEL)
# undef RADIX_NODE_HEAD_LOCK
# undef RADIX_NODE_HEAD_UNLOCK
# define RADIX_NODE_HEAD_LOCK(x) ;
# define RADIX_NODE_HEAD_UNLOCK(x) ;
# endif
static void ip_pool_clearnodes __P((ip_pool_t *));
static void *ip_pool_exists __P((int, char *));
ip_pool_stat_t ipoolstat;
ipfrwlock_t ip_poolrw;
/*
* Binary tree routines from Sedgewick and enhanced to do ranges of addresses.
* NOTE: Insertion *MUST* be from greatest range to least for it to work!
* These should be replaced, eventually, by something else - most notably a
* interval searching method. The important feature is to be able to find
* the best match.
*
* So why not use a radix tree for this? As the first line implies, it
* has been written to work with a _range_ of addresses. A range is not
* necessarily a match with any given netmask so what we end up dealing
* with is an interval tree. Implementations of these are hard to find
* and the one herein is far from bug free.
*
* Sigh, in the end I became convinced that the bugs the code contained did
* not make it worthwhile not using radix trees. For now the radix tree from
* 4.4 BSD is used, but this is not viewed as a long term solution.
*/
ip_pool_t *ip_pool_list[IPL_LOGSIZE] = { NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL };
#ifdef TEST_POOL
void treeprint __P((ip_pool_t *));
int
main(argc, argv)
int argc;
char *argv[];
{
addrfamily_t a, b;
iplookupop_t op;
ip_pool_t *ipo;
i6addr_t ip;
RWLOCK_INIT(&ip_poolrw, "poolrw");
ip_pool_init();
bzero((char *)&a, sizeof(a));
bzero((char *)&b, sizeof(b));
bzero((char *)&ip, sizeof(ip));
bzero((char *)&op, sizeof(op));
strcpy(op.iplo_name, "0");
if (ip_pool_create(&op) == 0)
ipo = ip_pool_exists(0, "0");
a.adf_addr.in4.s_addr = 0x0a010203;
b.adf_addr.in4.s_addr = 0xffffffff;
ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
a.adf_addr.in4.s_addr = 0x0a000000;
b.adf_addr.in4.s_addr = 0xff000000;
ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0);
ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0);
a.adf_addr.in4.s_addr = 0x0a010100;
b.adf_addr.in4.s_addr = 0xffffff00;
ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
a.adf_addr.in4.s_addr = 0x0a010200;
b.adf_addr.in4.s_addr = 0xffffff00;
ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0);
ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0);
a.adf_addr.in4.s_addr = 0x0a010000;
b.adf_addr.in4.s_addr = 0xffff0000;
ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
a.adf_addr.in4.s_addr = 0x0a01020f;
b.adf_addr.in4.s_addr = 0xffffffff;
ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
#ifdef DEBUG_POOL
treeprint(ipo);
#endif
ip.in4.s_addr = 0x0a00aabb;
printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
ip_pool_search(ipo, 4, &ip));
ip.in4.s_addr = 0x0a000001;
printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
ip_pool_search(ipo, 4, &ip));
ip.in4.s_addr = 0x0a000101;
printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
ip_pool_search(ipo, 4, &ip));
ip.in4.s_addr = 0x0a010001;
printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
ip_pool_search(ipo, 4, &ip));
ip.in4.s_addr = 0x0a010101;
printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
ip_pool_search(ipo, 4, &ip));
ip.in4.s_addr = 0x0a010201;
printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
ip_pool_search(ipo, 4, &ip));
ip.in4.s_addr = 0x0a010203;
printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
ip_pool_search(ipo, 4, &ip));
ip.in4.s_addr = 0x0a01020f;
printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
ip_pool_search(ipo, 4, &ip));
ip.in4.s_addr = 0x0b00aabb;
printf("search(%#x) = %d (-1)\n", ip.in4.s_addr,
ip_pool_search(ipo, 4, &ip));
#ifdef DEBUG_POOL
treeprint(ipo);
#endif
ip_pool_fini();
return 0;
}
void
treeprint(ipo)
ip_pool_t *ipo;
{
ip_pool_node_t *c;
for (c = ipo->ipo_list; c != NULL; c = c->ipn_next)
printf("Node %p(%s) (%#x/%#x) = %d hits %lu\n",
c, c->ipn_name, c->ipn_addr.adf_addr.in4.s_addr,
c->ipn_mask.adf_addr.in4.s_addr,
c->ipn_info, c->ipn_hits);
}
#endif /* TEST_POOL */
/* ------------------------------------------------------------------------ */
/* Function: ip_pool_init */
/* Returns: int - 0 = success, else error */
/* */
/* Initialise the routing table data structures where required. */
/* ------------------------------------------------------------------------ */
int ip_pool_init()
{
bzero((char *)&ipoolstat, sizeof(ipoolstat));
#if (!defined(_KERNEL) || (BSD < 199306))
rn_init();
#endif
return 0;
}
/* ------------------------------------------------------------------------ */
/* Function: ip_pool_fini */
/* Returns: int - 0 = success, else error */
/* Locks: WRITE(ipf_global) */
/* */
/* Clean up all the pool data structures allocated and call the cleanup */
/* function for the radix tree that supports the pools. ip_pool_destroy() is*/
/* used to delete the pools one by one to ensure they're properly freed up. */
/* ------------------------------------------------------------------------ */
void ip_pool_fini()
{
ip_pool_t *p, *q;
int i;
for (i = 0; i <= IPL_LOGMAX; i++) {
for (q = ip_pool_list[i]; (p = q) != NULL; ) {
q = p->ipo_next;
(void) ip_pool_destroy(i, p->ipo_name);
}
}
#if (!defined(_KERNEL) || (BSD < 199306))
rn_fini();
#endif
}
/* ------------------------------------------------------------------------ */
/* Function: ip_pool_statistics */
/* Returns: int - 0 = success, else error */
/* Parameters: op(I) - pointer to lookup operation arguments */
/* */
/* Copy the current statistics out into user space, collecting pool list */
/* pointers as appropriate for later use. */
/* ------------------------------------------------------------------------ */
int ip_pool_statistics(op)
iplookupop_t *op;
{
ip_pool_stat_t stats;
int unit, i, err = 0;
if (op->iplo_size != sizeof(ipoolstat))
return EINVAL;
bcopy((char *)&ipoolstat, (char *)&stats, sizeof(stats));
unit = op->iplo_unit;
if (unit == IPL_LOGALL) {
for (i = 0; i < IPL_LOGSIZE; i++)
stats.ipls_list[i] = ip_pool_list[i];
} else if (unit >= 0 && unit < IPL_LOGSIZE) {
if (op->iplo_name[0] != '\0')
stats.ipls_list[unit] = ip_pool_exists(unit,
op->iplo_name);
else
stats.ipls_list[unit] = ip_pool_list[unit];
} else
err = EINVAL;
if (err == 0)
err = COPYOUT(&stats, op->iplo_struct, sizeof(stats));
return err;
}
/* ------------------------------------------------------------------------ */
/* Function: ip_pool_exists */
/* Returns: int - 0 = success, else error */
/* Parameters: ipo(I) - pointer to the pool getting the new node. */
/* */
/* Find a matching pool inside the collection of pools for a particular */
/* device, indicated by the unit number. */
/* ------------------------------------------------------------------------ */
static void *ip_pool_exists(unit, name)
int unit;
char *name;
{
ip_pool_t *p;
for (p = ip_pool_list[unit]; p != NULL; p = p->ipo_next)
if (strncmp(p->ipo_name, name, sizeof(p->ipo_name)) == 0)
break;
return p;
}
/* ------------------------------------------------------------------------ */
/* Function: ip_pool_find */
/* Returns: int - 0 = success, else error */
/* Parameters: ipo(I) - pointer to the pool getting the new node. */
/* */
/* Find a matching pool inside the collection of pools for a particular */
/* device, indicated by the unit number. If it is marked for deletion then */
/* pretend it does not exist. */
/* ------------------------------------------------------------------------ */
void *ip_pool_find(unit, name)
int unit;
char *name;
{
ip_pool_t *p;
p = ip_pool_exists(unit, name);
if ((p != NULL) && (p->ipo_flags & IPOOL_DELETE))
return NULL;
return p;
}
/* ------------------------------------------------------------------------ */
/* Function: ip_pool_findeq */
/* Returns: int - 0 = success, else error */
/* Parameters: ipo(I) - pointer to the pool getting the new node. */
/* addr(I) - pointer to address information to delete */
/* mask(I) - */
/* */
/* Searches for an exact match of an entry in the pool. */
/* ------------------------------------------------------------------------ */
ip_pool_node_t *ip_pool_findeq(ipo, addr, mask)
ip_pool_t *ipo;
addrfamily_t *addr, *mask;
{
struct radix_node *n;
SPL_INT(s);
SPL_NET(s);
RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
n = ipo->ipo_head->rnh_lookup(addr, mask, ipo->ipo_head);
RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
SPL_X(s);
return (ip_pool_node_t *)n;
}
/* ------------------------------------------------------------------------ */
/* Function: ip_pool_search */
/* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */
/* Parameters: tptr(I) - pointer to the pool to search */
/* version(I) - IP protocol version (4 or 6) */
/* dptr(I) - pointer to address information */
/* */
/* Search the pool for a given address and return a search result. */
/* ------------------------------------------------------------------------ */
int ip_pool_search(tptr, ipversion, dptr)
void *tptr;
int ipversion;
void *dptr;
{
struct radix_node *rn;
ip_pool_node_t *m;
i6addr_t *addr;
addrfamily_t v;
ip_pool_t *ipo;
int rv;
ipo = tptr;
if (ipo == NULL)
return -1;
rv = 1;
m = NULL;
addr = (i6addr_t *)dptr;
bzero(&v, sizeof(v));
v.adf_len = offsetof(addrfamily_t, adf_addr);
if (ipversion == 4) {
v.adf_len += sizeof(addr->in4);
v.adf_addr.in4 = addr->in4;
#ifdef USE_INET6
} else if (ipversion == 6) {
v.adf_len += sizeof(addr->in6);
v.adf_addr.in6 = addr->in6;
#endif
} else
return -1;
READ_ENTER(&ip_poolrw);
RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
rn = ipo->ipo_head->rnh_matchaddr(&v, ipo->ipo_head);
RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
if ((rn != NULL) && ((rn->rn_flags & RNF_ROOT) == 0)) {
m = (ip_pool_node_t *)rn;
ipo->ipo_hits++;
m->ipn_hits++;
rv = m->ipn_info;
}
RWLOCK_EXIT(&ip_poolrw);
return rv;
}
/* ------------------------------------------------------------------------ */
/* Function: ip_pool_insert */
/* Returns: int - 0 = success, else error */
/* Parameters: ipo(I) - pointer to the pool getting the new node. */
/* addr(I) - address being added as a node */
/* mask(I) - netmask to with the node being added */
/* info(I) - extra information to store in this node. */
/* Locks: WRITE(ip_poolrw) */
/* */
/* Add another node to the pool given by ipo. The three parameters passed */
/* in (addr, mask, info) shold all be stored in the node. */
/* ------------------------------------------------------------------------ */
int ip_pool_insert(ipo, addr, mask, info)
ip_pool_t *ipo;
i6addr_t *addr, *mask;
int info;
{
struct radix_node *rn;
ip_pool_node_t *x;
KMALLOC(x, ip_pool_node_t *);
if (x == NULL) {
return ENOMEM;
}
bzero(x, sizeof(*x));
x->ipn_info = info;
(void)strncpy(x->ipn_name, ipo->ipo_name, sizeof(x->ipn_name));
bcopy(addr, &x->ipn_addr.adf_addr, sizeof(*addr));
x->ipn_addr.adf_len = sizeof(x->ipn_addr);
bcopy(mask, &x->ipn_mask.adf_addr, sizeof(*mask));
x->ipn_mask.adf_len = sizeof(x->ipn_mask);
RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
rn = ipo->ipo_head->rnh_addaddr(&x->ipn_addr, &x->ipn_mask,
ipo->ipo_head, x->ipn_nodes);
RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
#ifdef DEBUG_POOL
printf("Added %p at %p\n", x, rn);
#endif
if (rn == NULL) {
KFREE(x);
return ENOMEM;
}
x->ipn_ref = 1;
x->ipn_next = ipo->ipo_list;
x->ipn_pnext = &ipo->ipo_list;
if (ipo->ipo_list != NULL)
ipo->ipo_list->ipn_pnext = &x->ipn_next;
ipo->ipo_list = x;
ipoolstat.ipls_nodes++;
return 0;
}
/* ------------------------------------------------------------------------ */
/* Function: ip_pool_create */
/* Returns: int - 0 = success, else error */
/* Parameters: op(I) - pointer to iplookup struct with call details */
/* Locks: WRITE(ip_poolrw) */
/* */
/* Creates a new group according to the paramters passed in via the */
/* iplookupop structure. Does not check to see if the group already exists */
/* when being inserted - assume this has already been done. If the pool is */
/* marked as being anonymous, give it a new, unique, identifier. Call any */
/* other functions required to initialise the structure. */
/* */
/* If the structure is flagged for deletion then reset the flag and return, */
/* as this likely means we've tried to free a pool that is in use (flush) */
/* and now want to repopulate it with "new" data. */
/* ------------------------------------------------------------------------ */
int ip_pool_create(op)
iplookupop_t *op;
{
char name[FR_GROUPLEN];
int poolnum, unit;
ip_pool_t *h;
unit = op->iplo_unit;
if ((op->iplo_arg & LOOKUP_ANON) == 0) {
h = ip_pool_exists(unit, op->iplo_name);
if (h != NULL) {
if ((h->ipo_flags & IPOOL_DELETE) == 0)
return EEXIST;
h->ipo_flags &= ~IPOOL_DELETE;
return 0;
}
}
KMALLOC(h, ip_pool_t *);
if (h == NULL)
return ENOMEM;
bzero(h, sizeof(*h));
if (rn_inithead((void **)&h->ipo_head,
offsetof(addrfamily_t, adf_addr) << 3) == 0) {
KFREE(h);
return ENOMEM;
}
if ((op->iplo_arg & LOOKUP_ANON) != 0) {
ip_pool_t *p;
h->ipo_flags |= IPOOL_ANON;
poolnum = LOOKUP_ANON;
#if defined(SNPRINTF) && defined(_KERNEL)
SNPRINTF(name, sizeof(name), "%x", poolnum);
#else
(void)sprintf(name, "%x", poolnum);
#endif
for (p = ip_pool_list[unit]; p != NULL; ) {
if (strncmp(name, p->ipo_name,
sizeof(p->ipo_name)) == 0) {
poolnum++;
#if defined(SNPRINTF) && defined(_KERNEL)
SNPRINTF(name, sizeof(name), "%x", poolnum);
#else
(void)sprintf(name, "%x", poolnum);
#endif
p = ip_pool_list[unit];
} else
p = p->ipo_next;
}
(void)strncpy(h->ipo_name, name, sizeof(h->ipo_name));
(void)strncpy(op->iplo_name, name, sizeof(op->iplo_name));
} else {
(void)strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name));
}
h->ipo_ref = 1;
h->ipo_list = NULL;
h->ipo_unit = unit;
h->ipo_next = ip_pool_list[unit];
if (ip_pool_list[unit] != NULL)
ip_pool_list[unit]->ipo_pnext = &h->ipo_next;
h->ipo_pnext = &ip_pool_list[unit];
ip_pool_list[unit] = h;
ipoolstat.ipls_pools++;
return 0;
}
/* ------------------------------------------------------------------------ */
/* Function: ip_pool_remove */
/* Returns: int - 0 = success, else error */
/* Parameters: ipo(I) - pointer to the pool to remove the node from. */
/* ipe(I) - address being deleted as a node */
/* Locks: WRITE(ip_poolrw) */
/* */
/* Remove a node from the pool given by ipo. */
/* ------------------------------------------------------------------------ */
int ip_pool_remove(ipo, ipe)
ip_pool_t *ipo;
ip_pool_node_t *ipe;
{
if (ipe->ipn_pnext != NULL)
*ipe->ipn_pnext = ipe->ipn_next;
if (ipe->ipn_next != NULL)
ipe->ipn_next->ipn_pnext = ipe->ipn_pnext;
RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
ipo->ipo_head->rnh_deladdr(&ipe->ipn_addr, &ipe->ipn_mask,
ipo->ipo_head);
RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
ip_pool_node_deref(ipe);
return 0;
}
/* ------------------------------------------------------------------------ */
/* Function: ip_pool_destroy */
/* Returns: int - 0 = success, else error */
/* Parameters: op(I) - information about the pool to remove */
/* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
/* */
/* Search for a pool using paramters passed in and if it's not otherwise */
/* busy, free it. If it is busy, clear all of its nodes, mark it for being */
/* deleted and return an error saying it is busy. */
/* */
/* NOTE: Because this function is called out of ipfdetach() where ip_poolrw */
/* may not be initialised, we can't use an ASSERT to enforce the locking */
/* assertion that one of the two (ip_poolrw,ipf_global) is held. */
/* ------------------------------------------------------------------------ */
int ip_pool_destroy(unit, name)
int unit;
char *name;
{
ip_pool_t *ipo;
ipo = ip_pool_exists(unit, name);
if (ipo == NULL)
return ESRCH;
if (ipo->ipo_ref != 1) {
ip_pool_clearnodes(ipo);
ipo->ipo_flags |= IPOOL_DELETE;
return 0;
}
ip_pool_free(ipo);
return 0;
}
/* ------------------------------------------------------------------------ */
/* Function: ip_pool_flush */
/* Returns: int - number of pools deleted */
/* Parameters: fp(I) - which pool(s) to flush */
/* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
/* */
/* Free all pools associated with the device that matches the unit number */
/* passed in with operation. */
/* */
/* NOTE: Because this function is called out of ipfdetach() where ip_poolrw */
/* may not be initialised, we can't use an ASSERT to enforce the locking */
/* assertion that one of the two (ip_poolrw,ipf_global) is held. */
/* ------------------------------------------------------------------------ */
int ip_pool_flush(fp)
iplookupflush_t *fp;
{
int i, num = 0, unit, err;
ip_pool_t *p, *q;
iplookupop_t op;
unit = fp->iplf_unit;
for (i = 0; i <= IPL_LOGMAX; i++) {
if (unit != IPLT_ALL && i != unit)
continue;
for (q = ip_pool_list[i]; (p = q) != NULL; ) {
op.iplo_unit = i;
(void)strncpy(op.iplo_name, p->ipo_name,
sizeof(op.iplo_name));
q = p->ipo_next;
err = ip_pool_destroy(op.iplo_unit, op.iplo_name);
if (err == 0)
num++;
else
break;
}
}
return num;
}
/* ------------------------------------------------------------------------ */
/* Function: ip_pool_free */
/* Returns: void */
/* Parameters: ipo(I) - pointer to pool structure */
/* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
/* */
/* Deletes the pool strucutre passed in from the list of pools and deletes */
/* all of the address information stored in it, including any tree data */
/* structures also allocated. */
/* */
/* NOTE: Because this function is called out of ipfdetach() where ip_poolrw */
/* may not be initialised, we can't use an ASSERT to enforce the locking */
/* assertion that one of the two (ip_poolrw,ipf_global) is held. */
/* ------------------------------------------------------------------------ */
void ip_pool_free(ipo)
ip_pool_t *ipo;
{
ip_pool_clearnodes(ipo);
if (ipo->ipo_next != NULL)
ipo->ipo_next->ipo_pnext = ipo->ipo_pnext;
*ipo->ipo_pnext = ipo->ipo_next;
rn_freehead(ipo->ipo_head);
KFREE(ipo);
ipoolstat.ipls_pools--;
}
/* ------------------------------------------------------------------------ */
/* Function: ip_pool_clearnodes */
/* Returns: void */
/* Parameters: ipo(I) - pointer to pool structure */
/* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
/* */
/* Deletes all nodes stored in a pool structure. */
/* ------------------------------------------------------------------------ */
static void ip_pool_clearnodes(ipo)
ip_pool_t *ipo;
{
ip_pool_node_t *n;
RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
while ((n = ipo->ipo_list) != NULL) {
ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask,
ipo->ipo_head);
*n->ipn_pnext = n->ipn_next;
if (n->ipn_next)
n->ipn_next->ipn_pnext = n->ipn_pnext;
KFREE(n);
ipoolstat.ipls_nodes--;
}
RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
ipo->ipo_list = NULL;
}
/* ------------------------------------------------------------------------ */
/* Function: ip_pool_deref */
/* Returns: void */
/* Parameters: ipo(I) - pointer to pool structure */
/* Locks: WRITE(ip_poolrw) */
/* */
/* Drop the number of known references to this pool structure by one and if */
/* we arrive at zero known references, free it. */
/* ------------------------------------------------------------------------ */
void ip_pool_deref(ipo)
ip_pool_t *ipo;
{
ipo->ipo_ref--;
if (ipo->ipo_ref == 0)
ip_pool_free(ipo);
else if ((ipo->ipo_ref == 1) && (ipo->ipo_flags & IPOOL_DELETE))
ip_pool_destroy(ipo->ipo_unit, ipo->ipo_name);
}
/* ------------------------------------------------------------------------ */
/* Function: ip_pool_node_deref */
/* Returns: void */
/* Parameters: ipn(I) - pointer to pool structure */
/* Locks: WRITE(ip_poolrw) */
/* */
/* Drop a reference to the pool node passed in and if we're the last, free */
/* it all up and adjust the stats accordingly. */
/* ------------------------------------------------------------------------ */
void ip_pool_node_deref(ipn)
ip_pool_node_t *ipn;
{
ipn->ipn_ref--;
if (ipn->ipn_ref == 0) {
KFREE(ipn);
ipoolstat.ipls_nodes--;
}
}
/* ------------------------------------------------------------------------ */
/* Function: ip_pool_getnext */
/* Returns: void */
/* Parameters: token(I) - pointer to pool structure */
/* Parameters: ilp(IO) - pointer to pool iterating structure */
/* */
/* ------------------------------------------------------------------------ */
int ip_pool_getnext(token, ilp)
ipftoken_t *token;
ipflookupiter_t *ilp;
{
ip_pool_node_t *node, zn, *nextnode;
ip_pool_t *ipo, zp, *nextipo;
int err;
err = 0;
node = NULL;
nextnode = NULL;
ipo = NULL;
nextipo = NULL;
READ_ENTER(&ip_poolrw);
switch (ilp->ili_otype)
{
case IPFLOOKUPITER_LIST :
ipo = token->ipt_data;
if (ipo == NULL) {
nextipo = ip_pool_list[(int)ilp->ili_unit];
} else {
nextipo = ipo->ipo_next;
}
if (nextipo != NULL) {
ATOMIC_INC(nextipo->ipo_ref);
token->ipt_data = nextipo;
} else {
bzero((char *)&zp, sizeof(zp));
nextipo = &zp;
token->ipt_data = NULL;
}
break;
case IPFLOOKUPITER_NODE :
node = token->ipt_data;
if (node == NULL) {
ipo = ip_pool_exists(ilp->ili_unit, ilp->ili_name);
if (ipo == NULL)
err = ESRCH;
else {
nextnode = ipo->ipo_list;
ipo = NULL;
}
} else {
nextnode = node->ipn_next;
}
if (nextnode != NULL) {
ATOMIC_INC(nextnode->ipn_ref);
token->ipt_data = nextnode;
} else {
bzero((char *)&zn, sizeof(zn));
nextnode = &zn;
token->ipt_data = NULL;
}
break;
default :
err = EINVAL;
break;
}
RWLOCK_EXIT(&ip_poolrw);
if (err != 0)
return err;
switch (ilp->ili_otype)
{
case IPFLOOKUPITER_LIST :
if (ipo != NULL) {
WRITE_ENTER(&ip_poolrw);
ip_pool_deref(ipo);
RWLOCK_EXIT(&ip_poolrw);
}
err = COPYOUT(nextipo, ilp->ili_data, sizeof(*nextipo));
if (err != 0)
err = EFAULT;
break;
case IPFLOOKUPITER_NODE :
if (node != NULL) {
WRITE_ENTER(&ip_poolrw);
ip_pool_node_deref(node);
RWLOCK_EXIT(&ip_poolrw);
}
err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode));
if (err != 0)
err = EFAULT;
break;
}
return err;
}
/* ------------------------------------------------------------------------ */
/* Function: ip_pool_iterderef */
/* Returns: void */
/* Parameters: ipn(I) - pointer to pool structure */
/* Locks: WRITE(ip_poolrw) */
/* */
/* ------------------------------------------------------------------------ */
void ip_pool_iterderef(otype, unit, data)
u_int otype;
int unit;
void *data;
{
if (data == NULL)
return;
if (unit < 0 || unit > IPL_LOGMAX)
return;
switch (otype)
{
case IPFLOOKUPITER_LIST :
WRITE_ENTER(&ip_poolrw);
ip_pool_deref((ip_pool_t *)data);
RWLOCK_EXIT(&ip_poolrw);
break;
case IPFLOOKUPITER_NODE :
WRITE_ENTER(&ip_poolrw);
ip_pool_node_deref((ip_pool_node_t *)data);
RWLOCK_EXIT(&ip_poolrw);
break;
default :
break;
}
}
# if defined(_KERNEL) && ((BSD >= 198911) && !defined(__osf__) && \
!defined(__hpux) && !defined(__sgi))
static int
rn_freenode(struct radix_node *n, void *p)
{
struct radix_node_head *rnh = p;
struct radix_node *d;
d = rnh->rnh_deladdr(n->rn_key, NULL, rnh);
if (d != NULL) {
FreeS(d, max_keylen + 2 * sizeof (*d));
}
return 0;
}
void
rn_freehead(rnh)
struct radix_node_head *rnh;
{
RADIX_NODE_HEAD_LOCK(rnh);
(*rnh->rnh_walktree)(rnh, rn_freenode, rnh);
rnh->rnh_addaddr = NULL;
rnh->rnh_deladdr = NULL;
rnh->rnh_matchaddr = NULL;
rnh->rnh_lookup = NULL;
rnh->rnh_walktree = NULL;
RADIX_NODE_HEAD_UNLOCK(rnh);
Free(rnh);
}
# endif
#endif /* IPFILTER_LOOKUP */
-90
View File
@@ -1,90 +0,0 @@
/*
* Copyright (C) 1993-2001, 2003 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* $Id: ip_pool.h,v 2.26.2.6 2007/10/10 09:51:43 darrenr Exp $
*/
#ifndef __IP_POOL_H__
#define __IP_POOL_H__
#if defined(_KERNEL) && !defined(__osf__) && !defined(__hpux) && \
!defined(linux) && !defined(sun) && !defined(AIX)
# include <net/radix.h>
extern void rn_freehead __P((struct radix_node_head *));
# define FreeS(p, z) KFREES(p, z)
extern int max_keylen;
#else
# if defined(__osf__) || defined(__hpux) || defined(sun)
# include "radix_ipf_local.h"
# define radix_mask ipf_radix_mask
# define radix_node ipf_radix_node
# define radix_node_head ipf_radix_node_head
# else
# include "radix_ipf.h"
# endif
#endif
#include "netinet/ip_lookup.h"
#define IP_POOL_NOMATCH 0
#define IP_POOL_POSITIVE 1
typedef struct ip_pool_node {
struct radix_node ipn_nodes[2];
addrfamily_t ipn_addr;
addrfamily_t ipn_mask;
int ipn_info;
int ipn_ref;
char ipn_name[FR_GROUPLEN];
u_long ipn_hits;
struct ip_pool_node *ipn_next, **ipn_pnext;
} ip_pool_node_t;
typedef struct ip_pool_s {
struct ip_pool_s *ipo_next;
struct ip_pool_s **ipo_pnext;
struct radix_node_head *ipo_head;
ip_pool_node_t *ipo_list;
u_long ipo_hits;
int ipo_unit;
int ipo_flags;
int ipo_ref;
char ipo_name[FR_GROUPLEN];
} ip_pool_t;
#define IPOOL_DELETE 0x01
#define IPOOL_ANON 0x02
typedef struct ip_pool_stat {
u_long ipls_pools;
u_long ipls_tables;
u_long ipls_nodes;
ip_pool_t *ipls_list[IPL_LOGSIZE];
} ip_pool_stat_t;
extern ip_pool_stat_t ipoolstat;
extern ip_pool_t *ip_pool_list[IPL_LOGSIZE];
extern int ip_pool_search __P((void *, int, void *));
extern int ip_pool_init __P((void));
extern void ip_pool_fini __P((void));
extern int ip_pool_create __P((iplookupop_t *));
extern int ip_pool_insert __P((ip_pool_t *, i6addr_t *, i6addr_t *, int));
extern int ip_pool_remove __P((ip_pool_t *, ip_pool_node_t *));
extern int ip_pool_destroy __P((int, char *));
extern void ip_pool_free __P((ip_pool_t *));
extern void ip_pool_deref __P((ip_pool_t *));
extern void ip_pool_node_deref __P((ip_pool_node_t *));
extern void *ip_pool_find __P((int, char *));
extern ip_pool_node_t *ip_pool_findeq __P((ip_pool_t *,
addrfamily_t *, addrfamily_t *));
extern int ip_pool_flush __P((iplookupflush_t *));
extern int ip_pool_statistics __P((iplookupop_t *));
extern int ip_pool_getnext __P((ipftoken_t *, ipflookupiter_t *));
extern void ip_pool_iterderef __P((u_int, int, void *));
#endif /* __IP_POOL_H__ */
-530
View File
@@ -1,530 +0,0 @@
/*
* Copyright (C) 2002-2003 by Darren Reed
*
* Simple PPTP transparent proxy for in-kernel use. For use with the NAT
* code.
*
* $Id: ip_pptp_pxy.c,v 2.10.2.15 2006/10/31 12:11:23 darrenr Exp $
*
*/
#define IPF_PPTP_PROXY
typedef struct pptp_hdr {
u_short pptph_len;
u_short pptph_type;
u_32_t pptph_cookie;
} pptp_hdr_t;
#define PPTP_MSGTYPE_CTL 1
#define PPTP_MTCTL_STARTREQ 1
#define PPTP_MTCTL_STARTREP 2
#define PPTP_MTCTL_STOPREQ 3
#define PPTP_MTCTL_STOPREP 4
#define PPTP_MTCTL_ECHOREQ 5
#define PPTP_MTCTL_ECHOREP 6
#define PPTP_MTCTL_OUTREQ 7
#define PPTP_MTCTL_OUTREP 8
#define PPTP_MTCTL_INREQ 9
#define PPTP_MTCTL_INREP 10
#define PPTP_MTCTL_INCONNECT 11
#define PPTP_MTCTL_CLEAR 12
#define PPTP_MTCTL_DISCONNECT 13
#define PPTP_MTCTL_WANERROR 14
#define PPTP_MTCTL_LINKINFO 15
int ippr_pptp_init __P((void));
void ippr_pptp_fini __P((void));
int ippr_pptp_new __P((fr_info_t *, ap_session_t *, nat_t *));
void ippr_pptp_del __P((ap_session_t *));
int ippr_pptp_inout __P((fr_info_t *, ap_session_t *, nat_t *));
void ippr_pptp_donatstate __P((fr_info_t *, nat_t *, pptp_pxy_t *));
int ippr_pptp_message __P((fr_info_t *, nat_t *, pptp_pxy_t *, pptp_side_t *));
int ippr_pptp_nextmessage __P((fr_info_t *, nat_t *, pptp_pxy_t *, int));
int ippr_pptp_mctl __P((fr_info_t *, nat_t *, pptp_pxy_t *, pptp_side_t *));
static frentry_t pptpfr;
int pptp_proxy_init = 0;
int ippr_pptp_debug = 0;
int ippr_pptp_gretimeout = IPF_TTLVAL(120); /* 2 minutes */
/*
* PPTP application proxy initialization.
*/
int ippr_pptp_init()
{
bzero((char *)&pptpfr, sizeof(pptpfr));
pptpfr.fr_ref = 1;
pptpfr.fr_age[0] = ippr_pptp_gretimeout;
pptpfr.fr_age[1] = ippr_pptp_gretimeout;
pptpfr.fr_flags = FR_OUTQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
MUTEX_INIT(&pptpfr.fr_lock, "PPTP proxy rule lock");
pptp_proxy_init = 1;
return 0;
}
void ippr_pptp_fini()
{
if (pptp_proxy_init == 1) {
MUTEX_DESTROY(&pptpfr.fr_lock);
pptp_proxy_init = 0;
}
}
/*
* Setup for a new PPTP proxy.
*
* NOTE: The printf's are broken up with %s in them to prevent them being
* optimised into puts statements on FreeBSD (this doesn't exist in the kernel)
*/
int ippr_pptp_new(fin, aps, nat)
fr_info_t *fin;
ap_session_t *aps;
nat_t *nat;
{
pptp_pxy_t *pptp;
ipnat_t *ipn;
ip_t *ip;
ip = fin->fin_ip;
if (nat_outlookup(fin, 0, IPPROTO_GRE, nat->nat_inip,
ip->ip_dst) != NULL) {
if (ippr_pptp_debug > 0)
printf("ippr_pptp_new: GRE session %s\n",
"already exists");
return -1;
}
aps->aps_psiz = sizeof(*pptp);
KMALLOCS(aps->aps_data, pptp_pxy_t *, sizeof(*pptp));
if (aps->aps_data == NULL) {
if (ippr_pptp_debug > 0)
printf("ippr_pptp_new: malloc for aps_data %s\n",
"failed");
return -1;
}
/*
* Create NAT rule against which the tunnel/transport mapping is
* created. This is required because the current NAT rule does not
* describe GRE but TCP instead.
*/
pptp = aps->aps_data;
bzero((char *)pptp, sizeof(*pptp));
ipn = &pptp->pptp_rule;
ipn->in_ifps[0] = fin->fin_ifp;
ipn->in_apr = NULL;
ipn->in_use = 1;
ipn->in_hits = 1;
ipn->in_ippip = 1;
if (nat->nat_dir == NAT_OUTBOUND) {
ipn->in_nip = ntohl(nat->nat_outip.s_addr);
ipn->in_outip = fin->fin_saddr;
ipn->in_redir = NAT_MAP;
} else if (nat->nat_dir == NAT_INBOUND) {
ipn->in_nip = 0;
ipn->in_outip = nat->nat_outip.s_addr;
ipn->in_redir = NAT_REDIRECT;
}
ipn->in_inip = nat->nat_inip.s_addr;
ipn->in_inmsk = 0xffffffff;
ipn->in_outmsk = 0xffffffff;
ipn->in_srcip = fin->fin_saddr;
ipn->in_srcmsk = 0xffffffff;
bcopy(nat->nat_ptr->in_ifnames[0], ipn->in_ifnames[0],
sizeof(ipn->in_ifnames[0]));
ipn->in_p = IPPROTO_GRE;
pptp->pptp_side[0].pptps_wptr = pptp->pptp_side[0].pptps_buffer;
pptp->pptp_side[1].pptps_wptr = pptp->pptp_side[1].pptps_buffer;
return 0;
}
void ippr_pptp_donatstate(fin, nat, pptp)
fr_info_t *fin;
nat_t *nat;
pptp_pxy_t *pptp;
{
fr_info_t fi;
grehdr_t gre;
nat_t *nat2;
u_char p;
ip_t *ip;
ip = fin->fin_ip;
p = ip->ip_p;
nat2 = pptp->pptp_nat;
if ((nat2 == NULL) || (pptp->pptp_state == NULL)) {
bcopy((char *)fin, (char *)&fi, sizeof(fi));
bzero((char *)&gre, sizeof(gre));
fi.fin_state = NULL;
fi.fin_nat = NULL;
fi.fin_fi.fi_p = IPPROTO_GRE;
fi.fin_fr = &pptpfr;
if ((nat->nat_dir == NAT_OUTBOUND && fin->fin_out) ||
(nat->nat_dir == NAT_INBOUND && !fin->fin_out)) {
fi.fin_data[0] = pptp->pptp_call[0];
fi.fin_data[1] = pptp->pptp_call[1];
} else {
fi.fin_data[0] = pptp->pptp_call[1];
fi.fin_data[1] = pptp->pptp_call[0];
}
ip = fin->fin_ip;
ip->ip_p = IPPROTO_GRE;
fi.fin_flx &= ~(FI_TCPUDP|FI_STATE|FI_FRAG);
fi.fin_flx |= FI_IGNORE;
fi.fin_dp = &gre;
gre.gr_flags = htons(1 << 13);
if (fin->fin_out && nat->nat_dir == NAT_INBOUND) {
fi.fin_fi.fi_saddr = fin->fin_fi.fi_daddr;
fi.fin_fi.fi_daddr = nat->nat_outip.s_addr;
} else if (!fin->fin_out && nat->nat_dir == NAT_OUTBOUND) {
fi.fin_fi.fi_saddr = nat->nat_inip.s_addr;
fi.fin_fi.fi_daddr = fin->fin_fi.fi_saddr;
}
}
/*
* Update NAT timeout/create NAT if missing.
*/
if (nat2 != NULL)
fr_queueback(&nat2->nat_tqe);
else {
nat2 = nat_new(&fi, &pptp->pptp_rule, &pptp->pptp_nat,
NAT_SLAVE, nat->nat_dir);
pptp->pptp_nat = nat2;
if (nat2 != NULL) {
(void) nat_proto(&fi, nat2, 0);
nat_update(&fi, nat2, nat2->nat_ptr);
}
}
READ_ENTER(&ipf_state);
if (pptp->pptp_state != NULL) {
fr_queueback(&pptp->pptp_state->is_sti);
RWLOCK_EXIT(&ipf_state);
} else {
RWLOCK_EXIT(&ipf_state);
if (nat2 != NULL) {
if (nat->nat_dir == NAT_INBOUND)
fi.fin_fi.fi_daddr = nat2->nat_inip.s_addr;
else
fi.fin_fi.fi_saddr = nat2->nat_inip.s_addr;
}
fi.fin_ifp = NULL;
pptp->pptp_state = fr_addstate(&fi, &pptp->pptp_state,
0);
if (fi.fin_state != NULL)
fr_statederef((ipstate_t **)&fi.fin_state);
}
ip->ip_p = p;
return;
}
/*
* Try and build up the next PPTP message in the TCP stream and if we can
* build it up completely (fits in our buffer) then pass it off to the message
* parsing function.
*/
int ippr_pptp_nextmessage(fin, nat, pptp, rev)
fr_info_t *fin;
nat_t *nat;
pptp_pxy_t *pptp;
int rev;
{
static const char *funcname = "ippr_pptp_nextmessage";
pptp_side_t *pptps;
u_32_t start, end;
pptp_hdr_t *hdr;
tcphdr_t *tcp;
int dlen, off;
u_short len;
char *msg;
tcp = fin->fin_dp;
dlen = fin->fin_dlen - (TCP_OFF(tcp) << 2);
start = ntohl(tcp->th_seq);
pptps = &pptp->pptp_side[rev];
off = (char *)tcp - (char *)fin->fin_ip + (TCP_OFF(tcp) << 2) +
fin->fin_ipoff;
if (dlen <= 0)
return 0;
/*
* If the complete data packet is before what we expect to see
* "next", just ignore it as the chances are we've already seen it.
* The next if statement following this one really just causes packets
* ahead of what we've seen to be dropped, implying that something in
* the middle went missing and we want to see that first.
*/
end = start + dlen;
if (pptps->pptps_next > end && pptps->pptps_next > start)
return 0;
if (pptps->pptps_next != start) {
if (ippr_pptp_debug > 5)
printf("%s: next (%x) != start (%x)\n", funcname,
pptps->pptps_next, start);
return -1;
}
msg = (char *)fin->fin_dp + (TCP_OFF(tcp) << 2);
while (dlen > 0) {
off += pptps->pptps_bytes;
if (pptps->pptps_gothdr == 0) {
/*
* PPTP has an 8 byte header that inclues the cookie.
* The start of every message should include one and
* it should match 1a2b3c4d. Byte order is ignored,
* deliberately, when printing out the error.
*/
len = MIN(8 - pptps->pptps_bytes, dlen);
COPYDATA(fin->fin_m, off, len, pptps->pptps_wptr);
pptps->pptps_bytes += len;
pptps->pptps_wptr += len;
hdr = (pptp_hdr_t *)pptps->pptps_buffer;
if (pptps->pptps_bytes == 8) {
pptps->pptps_next += 8;
if (ntohl(hdr->pptph_cookie) != 0x1a2b3c4d) {
if (ippr_pptp_debug > 1)
printf("%s: bad cookie (%x)\n",
funcname,
hdr->pptph_cookie);
return -1;
}
}
dlen -= len;
msg += len;
off += len;
pptps->pptps_gothdr = 1;
len = ntohs(hdr->pptph_len);
pptps->pptps_len = len;
pptps->pptps_nexthdr += len;
/*
* If a message is too big for the buffer, just set
* the fields for the next message to come along.
* The messages defined in RFC 2637 will not exceed
* 512 bytes (in total length) so this is likely a
* bad data packet, anyway.
*/
if (len > sizeof(pptps->pptps_buffer)) {
if (ippr_pptp_debug > 3)
printf("%s: message too big (%d)\n",
funcname, len);
pptps->pptps_next = pptps->pptps_nexthdr;
pptps->pptps_wptr = pptps->pptps_buffer;
pptps->pptps_gothdr = 0;
pptps->pptps_bytes = 0;
pptps->pptps_len = 0;
break;
}
}
len = MIN(pptps->pptps_len - pptps->pptps_bytes, dlen);
COPYDATA(fin->fin_m, off, len, pptps->pptps_wptr);
pptps->pptps_bytes += len;
pptps->pptps_wptr += len;
pptps->pptps_next += len;
if (pptps->pptps_len > pptps->pptps_bytes)
break;
ippr_pptp_message(fin, nat, pptp, pptps);
pptps->pptps_wptr = pptps->pptps_buffer;
pptps->pptps_gothdr = 0;
pptps->pptps_bytes = 0;
pptps->pptps_len = 0;
start += len;
msg += len;
dlen -= len;
}
return 0;
}
/*
* handle a complete PPTP message
*/
int ippr_pptp_message(fin, nat, pptp, pptps)
fr_info_t *fin;
nat_t *nat;
pptp_pxy_t *pptp;
pptp_side_t *pptps;
{
pptp_hdr_t *hdr = (pptp_hdr_t *)pptps->pptps_buffer;
switch (ntohs(hdr->pptph_type))
{
case PPTP_MSGTYPE_CTL :
ippr_pptp_mctl(fin, nat, pptp, pptps);
break;
default :
break;
}
return 0;
}
/*
* handle a complete PPTP control message
*/
int ippr_pptp_mctl(fin, nat, pptp, pptps)
fr_info_t *fin;
nat_t *nat;
pptp_pxy_t *pptp;
pptp_side_t *pptps;
{
u_short *buffer = (u_short *)(pptps->pptps_buffer);
pptp_side_t *pptpo;
if (pptps == &pptp->pptp_side[0])
pptpo = &pptp->pptp_side[1];
else
pptpo = &pptp->pptp_side[0];
/*
* Breakout to handle all the various messages. Most are just state
* transition.
*/
switch (ntohs(buffer[4]))
{
case PPTP_MTCTL_STARTREQ :
pptps->pptps_state = PPTP_MTCTL_STARTREQ;
break;
case PPTP_MTCTL_STARTREP :
if (pptpo->pptps_state == PPTP_MTCTL_STARTREQ)
pptps->pptps_state = PPTP_MTCTL_STARTREP;
break;
case PPTP_MTCTL_STOPREQ :
pptps->pptps_state = PPTP_MTCTL_STOPREQ;
break;
case PPTP_MTCTL_STOPREP :
if (pptpo->pptps_state == PPTP_MTCTL_STOPREQ)
pptps->pptps_state = PPTP_MTCTL_STOPREP;
break;
case PPTP_MTCTL_ECHOREQ :
pptps->pptps_state = PPTP_MTCTL_ECHOREQ;
break;
case PPTP_MTCTL_ECHOREP :
if (pptpo->pptps_state == PPTP_MTCTL_ECHOREQ)
pptps->pptps_state = PPTP_MTCTL_ECHOREP;
break;
case PPTP_MTCTL_OUTREQ :
pptps->pptps_state = PPTP_MTCTL_OUTREQ;
break;
case PPTP_MTCTL_OUTREP :
if (pptpo->pptps_state == PPTP_MTCTL_OUTREQ) {
pptps->pptps_state = PPTP_MTCTL_OUTREP;
pptp->pptp_call[0] = buffer[7];
pptp->pptp_call[1] = buffer[6];
ippr_pptp_donatstate(fin, nat, pptp);
}
break;
case PPTP_MTCTL_INREQ :
pptps->pptps_state = PPTP_MTCTL_INREQ;
break;
case PPTP_MTCTL_INREP :
if (pptpo->pptps_state == PPTP_MTCTL_INREQ) {
pptps->pptps_state = PPTP_MTCTL_INREP;
pptp->pptp_call[0] = buffer[7];
pptp->pptp_call[1] = buffer[6];
ippr_pptp_donatstate(fin, nat, pptp);
}
break;
case PPTP_MTCTL_INCONNECT :
pptps->pptps_state = PPTP_MTCTL_INCONNECT;
break;
case PPTP_MTCTL_CLEAR :
pptps->pptps_state = PPTP_MTCTL_CLEAR;
break;
case PPTP_MTCTL_DISCONNECT :
pptps->pptps_state = PPTP_MTCTL_DISCONNECT;
break;
case PPTP_MTCTL_WANERROR :
pptps->pptps_state = PPTP_MTCTL_WANERROR;
break;
case PPTP_MTCTL_LINKINFO :
pptps->pptps_state = PPTP_MTCTL_LINKINFO;
break;
}
return 0;
}
/*
* For outgoing PPTP packets. refresh timeouts for NAT & state entries, if
* we can. If they have disappeared, recreate them.
*/
int ippr_pptp_inout(fin, aps, nat)
fr_info_t *fin;
ap_session_t *aps;
nat_t *nat;
{
pptp_pxy_t *pptp;
tcphdr_t *tcp;
int rev;
if ((fin->fin_out == 1) && (nat->nat_dir == NAT_INBOUND))
rev = 1;
else if ((fin->fin_out == 0) && (nat->nat_dir == NAT_OUTBOUND))
rev = 1;
else
rev = 0;
tcp = (tcphdr_t *)fin->fin_dp;
if ((tcp->th_flags & TH_OPENING) == TH_OPENING) {
pptp = (pptp_pxy_t *)aps->aps_data;
pptp->pptp_side[1 - rev].pptps_next = ntohl(tcp->th_ack);
pptp->pptp_side[1 - rev].pptps_nexthdr = ntohl(tcp->th_ack);
pptp->pptp_side[rev].pptps_next = ntohl(tcp->th_seq) + 1;
pptp->pptp_side[rev].pptps_nexthdr = ntohl(tcp->th_seq) + 1;
}
return ippr_pptp_nextmessage(fin, nat, (pptp_pxy_t *)aps->aps_data,
rev);
}
/*
* clean up after ourselves.
*/
void ippr_pptp_del(aps)
ap_session_t *aps;
{
pptp_pxy_t *pptp;
pptp = aps->aps_data;
if (pptp != NULL) {
/*
* Don't bother changing any of the NAT structure details,
* *_del() is on a callback from aps_free(), from nat_delete()
*/
READ_ENTER(&ipf_state);
if (pptp->pptp_state != NULL) {
pptp->pptp_state->is_die = fr_ticks + 1;
pptp->pptp_state->is_me = NULL;
fr_queuefront(&pptp->pptp_state->is_sti);
}
RWLOCK_EXIT(&ipf_state);
pptp->pptp_state = NULL;
pptp->pptp_nat = NULL;
}
}
-858
View File
@@ -1,858 +0,0 @@
/*
* Copyright (C) 1997-2003 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*/
#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(AIX)
# include <sys/fcntl.h>
#endif
#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
#if !defined(linux)
# include <sys/protosw.h>
#endif
#include <sys/socket.h>
#if defined(_KERNEL)
# if !defined(__NetBSD__) && !defined(sun) && !defined(__osf__) && \
!defined(__OpenBSD__) && !defined(__hpux) && !defined(__sgi) && \
!defined(AIX)
# include <sys/ctype.h>
# endif
# 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>
# endif
# include <sys/stream.h>
# include <sys/kmem.h>
#endif
#if __FreeBSD__ > 2
# include <sys/queue.h>
#endif
#include <net/if.h>
#ifdef sun
# include <net/af.h>
#endif
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#ifndef linux
# include <netinet/ip_var.h>
#endif
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#include "netinet/ip_compat.h"
#include <netinet/tcpip.h>
#include "netinet/ip_fil.h"
#include "netinet/ip_nat.h"
#include "netinet/ip_state.h"
#include "netinet/ip_proxy.h"
#if (__FreeBSD_version >= 300000)
# include <sys/malloc.h>
#endif
#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"
# include "netinet/ip_netbios_pxy.c"
#endif
#include "netinet/ip_ipsec_pxy.c"
#include "netinet/ip_rpcb_pxy.c"
/* END OF INCLUDES */
#if !defined(lint)
static const char rcsid[] = "@(#)$Id: ip_proxy.c,v 2.62.2.21 2007/06/02 21:22:28 darrenr Exp $";
#endif
static int appr_fixseqack __P((fr_info_t *, ip_t *, ap_session_t *, int ));
#define AP_SESS_SIZE 53
#if defined(_KERNEL)
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, ippr_ftp_fini,
ippr_ftp_new, NULL, ippr_ftp_in, ippr_ftp_out, NULL, NULL },
#endif
#ifdef IPF_IRC_PROXY
{ NULL, "irc", (char)IPPROTO_TCP, 0, 0, ippr_irc_init, ippr_irc_fini,
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, 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, ippr_raudio_fini,
ippr_raudio_new, NULL, ippr_raudio_in, ippr_raudio_out, NULL, NULL },
#endif
#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, 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, ippr_h323_fini,
ippr_h323_new, ippr_h323_del, ippr_h323_in, NULL, NULL, NULL },
{ NULL, "h245", (char)IPPROTO_TCP, 0, 0, NULL, NULL,
ippr_h245_new, NULL, NULL, ippr_h245_out, NULL, 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, NULL, NULL, NULL, NULL }
};
/*
* Dynamically add a new kernel proxy. Ensure that it is unique in the
* collection compiled in and dynamically added.
*/
int appr_add(ap)
aproxy_t *ap;
{
aproxy_t *a;
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))) {
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 != NULL); a = a->apr_next)
if ((a->apr_p == ap->apr_p) &&
!strncmp(a->apr_label, 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;
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;
}
/*
* Delete a proxy that has been added dynamically from those available.
* If it is in use, return 1 (do not destroy NOW), not in use 0 or -1
* if it cannot be matched.
*/
int appr_del(ap)
aproxy_t *ap;
{
aproxy_t *a, **app;
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 (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;
}
/*
* Return 1 if the packet is a good match against a proxy, else 0.
*/
int appr_ok(fin, tcp, nat)
fr_info_t *fin;
tcphdr_t *tcp;
ipnat_t *nat;
{
aproxy_t *apr = nat->in_apr;
u_short dport = nat->in_dport;
if ((apr == NULL) || (apr->apr_flags & APR_DELETE) ||
(fin->fin_p != apr->apr_p))
return 0;
if ((tcp == NULL) && dport)
return 0;
return 1;
}
int appr_ioctl(data, cmd, mode, ctx)
caddr_t data;
ioctlcmd_t cmd;
int mode;
void *ctx;
{
ap_ctl_t ctl;
u_char *ptr;
int error;
mode = mode; /* LINT */
switch (cmd)
{
case SIOCPROXY :
error = BCOPYIN(data, &ctl, sizeof(ctl));
if (error != 0)
return EFAULT;
ptr = NULL;
if (ctl.apc_dsize > 0) {
KMALLOCS(ptr, u_char *, 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 (ptr != NULL) {
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.
*/
int appr_match(fin, nat)
fr_info_t *fin;
nat_t *nat;
{
aproxy_t *apr;
ipnat_t *ipn;
int result;
ipn = nat->nat_ptr;
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)) {
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) {
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;
}
/*
* Allocate a new application proxy structure and fill it in with the
* relevant details. call the init function once complete, prior to
* returning.
*/
int appr_new(fin, nat)
fr_info_t *fin;
nat_t *nat;
{
register ap_session_t *aps;
aproxy_t *apr;
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_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 (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 = 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, 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;
aps->aps_next = ap_sess_list;
ap_sess_list = aps;
nat->nat_aps = aps;
return 0;
}
/*
* 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(fin, nat)
fr_info_t *fin;
nat_t *nat;
{
#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
# 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;
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 == 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 ((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, aps, nat);
} else {
if (apr->apr_inpkt != NULL)
err = (*apr->apr_inpkt)(fin, aps, nat);
}
rv = APR_EXIT(err);
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) {
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(fin->fin_plen - adjlen);
s2 = LONG_SUM(fin->fin_plen);
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_cksum(fin->fin_qfm, ip,
IPPROTO_TCP, tcp,
fin->fin_plen);
#else
tcp->th_sum = fr_cksum(fin->fin_m, ip,
IPPROTO_TCP, tcp,
fin->fin_plen);
#endif
} else if ((udp != NULL) && (udp->uh_sum != 0)) {
#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
if (dosum)
udp->uh_sum = fr_cksum(fin->fin_qfm, ip,
IPPROTO_UDP, udp,
fin->fin_plen);
#else
udp->uh_sum = fr_cksum(fin->fin_m, ip,
IPPROTO_UDP, udp,
fin->fin_plen);
#endif
}
aps->aps_bytes += fin->fin_plen;
aps->aps_pkts++;
return 1;
}
return 0;
}
/*
* Search for an proxy by the protocol it is being used with and its name.
*/
aproxy_t *appr_lookup(pr, name)
u_int pr;
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))) {
ap->apr_ref++;
return ap;
}
for (ap = ap_proxylist; ap; ap = ap->apr_next)
if ((ap->apr_p == pr) &&
!strncmp(name, ap->apr_label, sizeof(ap->apr_label))) {
ap->apr_ref++;
return ap;
}
if (ipf_proxy_debug > 2)
printf("appr_lookup: failed for %d/%s\n", pr, name);
return NULL;
}
void appr_free(ap)
aproxy_t *ap;
{
ap->apr_ref--;
}
void aps_free(aps)
ap_session_t *aps;
{
ap_session_t *a, **ap;
aproxy_t *apr;
if (!aps)
return;
for (ap = &ap_sess_list; ((a = *ap) != NULL); ap = &a->aps_next)
if (a == aps) {
*ap = a->aps_next;
break;
}
apr = aps->aps_apr;
if ((apr != NULL) && (apr->apr_del != NULL))
(*apr->apr_del)(aps);
if ((aps->aps_data != NULL) && (aps->aps_psiz != 0))
KFREES(aps->aps_data, aps->aps_psiz);
KFREE(aps);
}
/*
* returns 2 if ack or seq number in TCP header is changed, returns 0 otherwise
*/
static int appr_fixseqack(fin, ip, aps, inc)
fr_info_t *fin;
ip_t *ip;
ap_session_t *aps;
int inc;
{
int sel, ch = 0, out, nlen;
u_32_t seq1, seq2;
tcphdr_t *tcp;
short inc2;
tcp = (tcphdr_t *)fin->fin_dp;
out = fin->fin_out;
/*
* fin->fin_plen has already been adjusted by 'inc'.
*/
nlen = fin->fin_plen;
nlen -= (IP_HL(ip) << 2) + (TCP_OFF(tcp) << 2);
inc2 = inc;
inc = (int)inc2;
if (out != 0) {
seq1 = (u_32_t)ntohl(tcp->th_seq);
sel = aps->aps_sel[out];
/* switch to other set ? */
if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) &&
(seq1 > aps->aps_seqmin[!sel])) {
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;
}
if (aps->aps_seqoff[sel]) {
seq2 = aps->aps_seqmin[sel] - aps->aps_seqoff[sel];
if (seq1 > seq2) {
seq2 = aps->aps_seqoff[sel];
seq1 += seq2;
tcp->th_seq = htonl(seq1);
ch = 1;
}
}
if (inc && (seq1 > aps->aps_seqmin[!sel])) {
aps->aps_seqmin[sel] = seq1 + nlen - 1;
aps->aps_seqoff[sel] = aps->aps_seqoff[sel] + inc;
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);
}
/***/
seq1 = ntohl(tcp->th_ack);
sel = aps->aps_sel[1 - out];
/* switch to other set ? */
if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) &&
(seq1 > aps->aps_ackmin[!sel])) {
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;
}
if (aps->aps_ackoff[sel] && (seq1 > aps->aps_ackmin[sel])) {
seq2 = aps->aps_ackoff[sel];
tcp->th_ack = htonl(seq1 - seq2);
ch = 1;
}
} else {
seq1 = ntohl(tcp->th_seq);
sel = aps->aps_sel[out];
/* switch to other set ? */
if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) &&
(seq1 > aps->aps_ackmin[!sel])) {
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;
}
if (aps->aps_ackoff[sel]) {
seq2 = aps->aps_ackmin[sel] - aps->aps_ackoff[sel];
if (seq1 > seq2) {
seq2 = aps->aps_ackoff[sel];
seq1 += seq2;
tcp->th_seq = htonl(seq1);
ch = 1;
}
}
if (inc && (seq1 > aps->aps_ackmin[!sel])) {
aps->aps_ackmin[!sel] = seq1 + nlen - 1;
aps->aps_ackoff[!sel] = aps->aps_ackoff[sel] + inc;
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);
}
/***/
seq1 = ntohl(tcp->th_ack);
sel = aps->aps_sel[1 - out];
/* switch to other set ? */
if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) &&
(seq1 > aps->aps_seqmin[!sel])) {
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 (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);
ch = 1;
}
}
}
if (ipf_proxy_debug > 8)
printf("appr_fixseqack: seq %x ack %x\n",
(u_32_t)ntohl(tcp->th_seq), (u_32_t)ntohl(tcp->th_ack));
return ch ? 2 : 0;
}
/*
* Initialise hook for kernel application proxies.
* Call the initialise routine for all the compiled in kernel proxies.
*/
int appr_init()
{
aproxy_t *ap;
int err = 0;
for (ap = ap_proxies; ap->apr_p; ap++) {
if (ap->apr_init != NULL) {
err = (*ap->apr_init)();
if (err != 0)
break;
}
}
return err;
}
/*
* Unload hook for kernel application proxies.
* Call the finialise routine for all the compiled in kernel proxies.
*/
void appr_unload()
{
aproxy_t *ap;
for (ap = ap_proxies; ap->apr_p; ap++)
if (ap->apr_fini != NULL)
(*ap->apr_fini)();
for (ap = ap_proxylist; ap; ap = ap->apr_next)
if (ap->apr_fini != NULL)
(*ap->apr_fini)();
}
-459
View File
@@ -1,459 +0,0 @@
/*
* Copyright (C) 1997-2001 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* $Id: ip_proxy.h,v 2.31.2.5 2007/04/16 21:06:52 darrenr Exp $
*/
#ifndef __IP_PROXY_H__
#define __IP_PROXY_H__
#ifndef SOLARIS
#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
#endif
#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51)
#define SIOCPROXY _IOWR('r', 64, struct ap_control)
#else
#define SIOCPROXY _IOWR(r, 64, struct ap_control)
#endif
#ifndef APR_LABELLEN
#define APR_LABELLEN 16
#endif
#define AP_SESS_SIZE 53
struct nat;
struct ipnat;
struct ipstate;
typedef struct ap_tcp {
u_short apt_sport; /* source port */
u_short apt_dport; /* destination port */
short apt_sel[2]; /* {seq,ack}{off,min} set selector */
short apt_seqoff[2]; /* sequence # difference */
u_32_t apt_seqmin[2]; /* don't change seq-off until after this */
short apt_ackoff[2]; /* sequence # difference */
u_32_t apt_ackmin[2]; /* don't change seq-off until after this */
u_char apt_state[2]; /* connection state */
} ap_tcp_t;
typedef struct ap_udp {
u_short apu_sport; /* source port */
u_short apu_dport; /* destination port */
} ap_udp_t;
typedef struct ap_session {
struct aproxy *aps_apr;
union {
struct ap_tcp apu_tcp;
struct ap_udp apu_udp;
} aps_un;
u_int aps_flags;
U_QUAD_T aps_bytes; /* bytes sent */
U_QUAD_T aps_pkts; /* packets sent */
void *aps_nat; /* pointer back to nat struct */
void *aps_data; /* private data */
int aps_p; /* protocol */
int aps_psiz; /* size of private data */
struct ap_session *aps_hnext;
struct ap_session *aps_next;
} ap_session_t;
#define aps_sport aps_un.apu_tcp.apt_sport
#define aps_dport aps_un.apu_tcp.apt_dport
#define aps_sel aps_un.apu_tcp.apt_sel
#define aps_seqoff aps_un.apu_tcp.apt_seqoff
#define aps_seqmin aps_un.apu_tcp.apt_seqmin
#define aps_state aps_un.apu_tcp.apt_state
#define aps_ackoff aps_un.apu_tcp.apt_ackoff
#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 # */
u_char apr_p; /* protocol */
int apr_ref; /* +1 per rule referencing it */
int apr_flags;
int (* apr_init) __P((void));
void (* apr_fini) __P((void));
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 *, 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) << 16)
#define APR_EXIT(x) (((x) >> 16) & 0xffff)
#define APR_INC(x) ((x) & 0xffff)
/*
* 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; /* 2 = no cr/lf yet, 1 = cannot parse */
int ftps_cmds;
char ftps_buf[FTP_BUFSZ];
} ftpside_t;
typedef struct ftpinfo {
int ftp_passok;
int ftp_incok;
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
*/
typedef struct raudio_s {
int rap_seenpna;
int rap_seenver;
int rap_version;
int rap_eos; /* End Of Startup */
int rap_gotid;
int rap_gotlen;
int rap_mode;
int rap_sdone;
u_short rap_plport;
u_short rap_prport;
u_short rap_srport;
char rap_svr[19];
u_32_t rap_sbf; /* flag to indicate which of the 19 bytes have
* been filled
*/
u_32_t rap_sseq;
} raudio_t;
#define RA_ID_END 0
#define RA_ID_UDP 1
#define RA_ID_ROBUST 7
#define RAP_M_UDP 1
#define RAP_M_ROBUST 2
#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
*/
typedef u_32_t ipsec_cookie_t[2];
typedef struct ipsec_pxy {
ipsec_cookie_t ipsc_icookie;
ipsec_cookie_t ipsc_rcookie;
int ipsc_rckset;
ipnat_t ipsc_rule;
nat_t *ipsc_nat;
struct ipstate *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;
struct ipstate *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 ipf_proxy_debug;
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((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((fr_info_t *, struct nat *));
extern aproxy_t *appr_lookup __P((u_int, char *));
extern int appr_new __P((fr_info_t *, struct nat *));
extern int appr_ioctl __P((caddr_t, ioctlcmd_t, int, void *));
#endif /* __IP_PROXY_H__ */
@@ -1,336 +0,0 @@
/*
* 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.4 2006/07/14 06:12:17 darrenr Exp $
*/
#define IPF_RAUDIO_PROXY
int ippr_raudio_init __P((void));
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.
*/
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, aps, nat)
fr_info_t *fin;
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);
rap->rap_mode = RAP_M_TCP; /* default is for TCP */
return 0;
}
int ippr_raudio_out(fin, aps, nat)
fr_info_t *fin;
ap_session_t *aps;
nat_t *nat;
{
raudio_t *rap = aps->aps_data;
unsigned char membuf[512 + 1], *s;
u_short id = 0;
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.
*/
if (rap->rap_eos == 1)
return 0;
m = fin->fin_m;
tcp = (tcphdr_t *)fin->fin_dp;
off = (char *)tcp - (char *)fin->fin_ip;
off += (TCP_OFF(tcp) << 2) + fin->fin_ipoff;
#ifdef __sgi
dlen = fin->fin_plen - off;
#else
dlen = MSGDSIZE(m) - off;
#endif
if (dlen <= 0)
return 0;
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.
*/
/*
* Look for the start of connection "PNA" string if not seen yet.
*/
if (rap->rap_seenpna == 0) {
s = (u_char *)memstr("PNA", (char *)membuf, 3, dlen);
if (s == NULL)
return 0;
s += 3;
rap->rap_seenpna = 1;
} else
s = membuf;
/*
* Directly after the PNA will be the version number of this
* connection.
*/
if (rap->rap_seenpna == 1 && rap->rap_seenver == 0) {
if ((s + 1) - membuf < dlen) {
rap->rap_version = (*s << 8) | *(s + 1);
s += 2;
rap->rap_seenver = 1;
} else
return 0;
}
/*
* Now that we've been past the PNA and version number, we're into the
* startup messages block. This ends when a message with an ID of 0.
*/
while ((rap->rap_eos == 0) && ((s + 1) - membuf < dlen)) {
if (rap->rap_gotid == 0) {
id = (*s << 8) | *(s + 1);
s += 2;
rap->rap_gotid = 1;
if (id == RA_ID_END) {
rap->rap_eos = 1;
break;
}
} else if (rap->rap_gotlen == 0) {
len = (*s << 8) | *(s + 1);
s += 2;
rap->rap_gotlen = 1;
}
if (rap->rap_gotid == 1 && rap->rap_gotlen == 1) {
if (id == RA_ID_UDP) {
rap->rap_mode &= ~RAP_M_TCP;
rap->rap_mode |= RAP_M_UDP;
rap->rap_plport = (*s << 8) | *(s + 1);
} else if (id == RA_ID_ROBUST) {
rap->rap_mode |= RAP_M_ROBUST;
rap->rap_prport = (*s << 8) | *(s + 1);
}
s += len;
rap->rap_gotlen = 0;
rap->rap_gotid = 0;
}
}
return 0;
}
int ippr_raudio_in(fin, aps, nat)
fr_info_t *fin;
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;
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 *nat2;
u_char swp;
ip_t *ip;
mb_t *m;
/*
* Wait until we've seen the end of the start messages and even then
* only proceed further if we're using UDP. If they want to use TCP
* then data is sent back on the same channel that is already open.
*/
if (rap->rap_sdone != 0)
return 0;
m = fin->fin_m;
tcp = (tcphdr_t *)fin->fin_dp;
off = (char *)tcp - (char *)fin->fin_ip;
off += (TCP_OFF(tcp) << 2) + fin->fin_ipoff;
#ifdef __sgi
dlen = fin->fin_plen - off;
#else
dlen = MSGDSIZE(m) - off;
#endif
if (dlen <= 0)
return 0;
if (dlen > sizeof(membuf))
dlen = sizeof(membuf);
bzero((char *)membuf, sizeof(membuf));
COPYDATA(m, off, dlen, (char *)membuf);
seq = ntohl(tcp->th_seq);
/*
* Check to see if the data in this packet is of interest to us.
* 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, dlen);
if (s == NULL)
return 0;
a1 = s - membuf;
dlen -= a1;
a1 = 0;
rap->rap_sseq = seq;
a2 = MIN(dlen, sizeof(rap->rap_svr));
} else if (seq <= rap->rap_sseq + sizeof(rap->rap_svr)) {
/*
* seq # which is the start of data and from that the offset
* into the buffer array.
*/
a1 = seq - rap->rap_sseq;
a2 = MIN(dlen, sizeof(rap->rap_svr));
a2 -= a1;
s = membuf;
} else
return 0;
for (a3 = a1, a4 = a2; (a4 > 0) && (a3 < 19) && (a3 >= 0); a4--,a3++) {
rap->rap_sbf |= (1 << a3);
rap->rap_svr[a3] = *s++;
}
if ((rap->rap_sbf != 0x7ffff) || (!rap->rap_eos)) /* 19 bits */
return 0;
rap->rap_sdone = 1;
s = (u_char *)rap->rap_svr + 11;
if (((*s << 8) | *(s + 1)) == RA_ID_ROBUST) {
s += 2;
rap->rap_srport = (*s << 8) | *(s + 1);
}
ip = fin->fin_ip;
swp = ip->ip_p;
swa = ip->ip_src;
swb = ip->ip_dst;
ip->ip_p = IPPROTO_UDP;
ip->ip_src = nat->nat_inip;
ip->ip_dst = nat->nat_oip;
bcopy((char *)fin, (char *)&fi, sizeof(fi));
bzero((char *)tcp2, sizeof(*tcp2));
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);
if (((rap->rap_mode & RAP_M_UDP_ROBUST) == RAP_M_UDP_ROBUST) &&
(rap->rap_srport != 0)) {
dp = rap->rap_srport;
sp = rap->rap_prport;
tcp2->th_sport = htons(sp);
tcp2->th_dport = htons(dp);
fi.fin_data[0] = dp;
fi.fin_data[1] = sp;
fi.fin_out = 0;
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((ipstate_t **)&fi.fin_state);
}
}
if ((rap->rap_mode & RAP_M_UDP) == RAP_M_UDP) {
sp = rap->rap_plport;
tcp2->th_sport = htons(sp);
tcp2->th_dport = 0; /* XXX - don't specify remote port */
fi.fin_data[0] = sp;
fi.fin_data[1] = 0;
fi.fin_out = 1;
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((ipstate_t **)&fi.fin_state);
}
}
ip->ip_p = swp;
ip->ip_len = slen;
ip->ip_src = swa;
ip->ip_dst = swb;
return 0;
}
-236
View File
@@ -1,236 +0,0 @@
/*
* 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.7 2006/07/14 06:12:18 darrenr Exp $
*
* Simple RCMD transparent proxy for in-kernel use. For use with the NAT
* code.
*/
#define IPF_RCMD_PROXY
int ippr_rcmd_init __P((void));
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 *, ap_session_t *, nat_t *));
static frentry_t rcmdfr;
int rcmd_proxy_init = 0;
/*
* RCMD application proxy initialization.
*/
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, aps, nat)
fr_info_t *fin;
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) {
#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;
return 0;
}
/*
* ipf_rcmd_atoi - implement a simple version of atoi
*/
u_short ipf_rcmd_atoi(ptr)
char *ptr;
{
register char *s = ptr, c;
register u_short i = 0;
while (((c = *s++) != '\0') && ISDIGIT(c)) {
i *= 10;
i += c - '0';
}
return i;
}
int ippr_rcmd_portmsg(fin, aps, nat)
fr_info_t *fin;
ap_session_t *aps;
nat_t *nat;
{
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 *nat2;
ip_t *ip;
mb_t *m;
tcp = (tcphdr_t *)fin->fin_dp;
if (tcp->th_flags & TH_SYN) {
*(u_32_t *)aps->aps_data = htonl(ntohl(tcp->th_seq) + 1);
return 0;
}
if ((*(u_32_t *)aps->aps_data != 0) &&
(tcp->th_seq != *(u_32_t *)aps->aps_data))
return 0;
m = fin->fin_m;
ip = fin->fin_ip;
off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff;
#ifdef __sgi
dlen = fin->fin_plen - off;
#else
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 == 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_state = NULL;
fi.fin_nat = NULL;
fi.fin_flx |= FI_IGNORE;
fi.fin_data[0] = sp;
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;
ip->ip_len = fin->fin_hlen + sizeof(*tcp);
bzero((char *)tcp2, sizeof(*tcp2));
tcp2->th_win = htons(8192);
tcp2->th_sport = htons(sp);
tcp2->th_dport = 0; /* XXX - don't specify remote port */
TCP_OFF_A(tcp2, 5);
tcp2->th_flags = TH_SYN;
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;
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, NULL, SI_W_DPORT);
if (fi.fin_state != NULL)
fr_statederef((ipstate_t **)&fi.fin_state);
}
ip->ip_len = slen;
ip->ip_src = swip;
ip->ip_dst = swip2;
}
return 0;
}
int ippr_rcmd_out(fin, aps, nat)
fr_info_t *fin;
ap_session_t *aps;
nat_t *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
-229
View File
@@ -1,229 +0,0 @@
/* $FreeBSD$ */
/*
* Copyright (C) 1993-2000 by Darren Reed.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
* to the original author and the contributors.
*/
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__sgi)
# include <sys/systm.h>
#endif
#include <sys/errno.h>
#include <sys/param.h>
#if !defined(__SVR4) && !defined(__svr4__) && !defined(__hpux)
# include <sys/mbuf.h>
#endif
#if defined(__FreeBSD__) && (__FreeBSD_version > 220000)
# include <sys/sockio.h>
#else
# include <sys/ioctl.h>
#endif /* FreeBSD */
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include "netinet/ip_compat.h"
#include "netinet/ip_fil.h"
#include "netinet/ip_rules.h"
#ifndef _KERNEL
# include <string.h>
#endif /* _KERNEL */
#ifdef IPFILTER_COMPILED
static u_long in_rule__0[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xffffffff, 0, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80000000, 0x8002, 0, 0, 0, 0xffff, 0, 0, 0x4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static u_long out_rule__0[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xffffffff, 0, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80000000, 0x4002, 0, 0, 0, 0xffff, 0, 0, 0x4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
frentry_t *ipf_rules_in_[1] = {
(frentry_t *)&in_rule__0
};
frentry_t *ipfrule_match_in_(fin, passp)
fr_info_t *fin;
u_32_t *passp;
{
frentry_t *fr = NULL;
fr = (frentry_t *)&in_rule__0;
return fr;
}
frentry_t *ipf_rules_out_[1] = {
(frentry_t *)&out_rule__0
};
frentry_t *ipfrule_match_out_(fin, passp)
fr_info_t *fin;
u_32_t *passp;
{
frentry_t *fr = NULL;
fr = (frentry_t *)&out_rule__0;
return fr;
}
static frentry_t ipfrule_out_;
int ipfrule_add_out_()
{
int i, j, err = 0, max;
frentry_t *fp;
max = sizeof(ipf_rules_out_)/sizeof(frentry_t *);
for (i = 0; i < max; i++) {
fp = ipf_rules_out_[i];
fp->fr_next = NULL;
for (j = i + 1; j < max; j++)
if (strncmp(fp->fr_group,
ipf_rules_out_[j]->fr_group,
FR_GROUPLEN) == 0) {
fp->fr_next = ipf_rules_out_[j];
break;
}
}
fp = &ipfrule_out_;
bzero((char *)fp, sizeof(*fp));
fp->fr_type = FR_T_CALLFUNC|FR_T_BUILTIN;
fp->fr_flags = FR_OUTQUE|FR_NOMATCH;
fp->fr_data = (void *)ipf_rules_out_[0];
fp->fr_dsize = sizeof(ipf_rules_out_[0]);
fp->fr_v = 4;
fp->fr_func = (ipfunc_t)ipfrule_match_out_;
err = frrequest(IPL_LOGIPF, SIOCADDFR, (caddr_t)fp, fr_active, 0);
return err;
}
int ipfrule_remove_out_()
{
int err = 0, i;
frentry_t *fp;
/*
* Try to remove the outbound rule.
*/
if (ipfrule_out_.fr_ref > 0) {
err = EBUSY;
} else {
i = sizeof(ipf_rules_out_)/sizeof(frentry_t *) - 1;
for (; i >= 0; i--) {
fp = ipf_rules_out_[i];
if (fp->fr_ref > 1) {
err = EBUSY;
break;
}
}
}
if (err == 0)
err = frrequest(IPL_LOGIPF, SIOCDELFR,
(caddr_t)&ipfrule_out_, fr_active, 0);
if (err)
return err;
return err;
}
static frentry_t ipfrule_in_;
int ipfrule_add_in_()
{
int i, j, err = 0, max;
frentry_t *fp;
max = sizeof(ipf_rules_in_)/sizeof(frentry_t *);
for (i = 0; i < max; i++) {
fp = ipf_rules_in_[i];
fp->fr_next = NULL;
for (j = i + 1; j < max; j++)
if (strncmp(fp->fr_group,
ipf_rules_in_[j]->fr_group,
FR_GROUPLEN) == 0) {
fp->fr_next = ipf_rules_in_[j];
break;
}
}
fp = &ipfrule_in_;
bzero((char *)fp, sizeof(*fp));
fp->fr_type = FR_T_CALLFUNC|FR_T_BUILTIN;
fp->fr_flags = FR_INQUE|FR_NOMATCH;
fp->fr_data = (void *)ipf_rules_in_[0];
fp->fr_dsize = sizeof(ipf_rules_in_[0]);
fp->fr_v = 4;
fp->fr_func = (ipfunc_t)ipfrule_match_in_;
err = frrequest(IPL_LOGIPF, SIOCADDFR, (caddr_t)fp, fr_active, 0);
return err;
}
int ipfrule_remove_in_()
{
int err = 0, i;
frentry_t *fp;
/*
* Try to remove the inbound rule.
*/
if (ipfrule_in_.fr_ref > 0) {
err = EBUSY;
} else {
i = sizeof(ipf_rules_in_)/sizeof(frentry_t *) - 1;
for (; i >= 0; i--) {
fp = ipf_rules_in_[i];
if (fp->fr_ref > 1) {
err = EBUSY;
break;
}
}
}
if (err == 0)
err = frrequest(IPL_LOGIPF, SIOCDELFR,
(caddr_t)&ipfrule_in_, fr_active, 0);
if (err)
return err;
return err;
}
int ipfrule_add()
{
int err;
err = ipfrule_add_out_();
if (err != 0)
return err;
err = ipfrule_add_in_();
if (err != 0)
return err;
return 0;
}
int ipfrule_remove()
{
int err;
err = ipfrule_remove_out_();
if (err != 0)
return err;
err = ipfrule_remove_in_();
if (err != 0)
return err;
return 0;
}
#endif /* IPFILTER_COMPILED */
-16
View File
@@ -1,16 +0,0 @@
/* $FreeBSD$ */
extern int ipfrule_add __P((void));
extern int ipfrule_remove __P((void));
extern frentry_t *ipfrule_match_out_ __P((fr_info_t *, u_32_t *));
extern frentry_t *ipf_rules_out_[1];
extern int ipfrule_add_out_ __P((void));
extern int ipfrule_remove_out_ __P((void));
extern frentry_t *ipfrule_match_in_ __P((fr_info_t *, u_32_t *));
extern frentry_t *ipf_rules_in_[1];
extern int ipfrule_add_in_ __P((void));
extern int ipfrule_remove_in_ __P((void));
-601
View File
@@ -1,601 +0,0 @@
/*
* Copyright (C) 1995-2001 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*/
#if defined(KERNEL) || defined(_KERNEL)
# undef KERNEL
# undef _KERNEL
# define KERNEL 1
# define _KERNEL 1
#endif
#include <sys/param.h>
#if defined(__hpux) && (HPUXREV >= 1111) && !defined(_KERNEL)
# include <sys/kern_svcs.h>
#endif
#include <sys/types.h>
#include <sys/time.h>
#include <sys/errno.h>
#if !defined(_KERNEL)
# include <stdlib.h>
# include <string.h>
# define _KERNEL
# ifdef __OpenBSD__
struct file;
# endif
# include <sys/uio.h>
# undef _KERNEL
#else
# include <sys/systm.h>
# if !defined(__svr4__) && !defined(__SVR4)
# include <sys/mbuf.h>
# endif
#endif
#include <sys/socket.h>
#if !defined(__hpux) && !defined(__osf__) && !defined(linux) && !defined(AIX)
# include <sys/ioccom.h>
#endif
#ifdef __FreeBSD__
# include <sys/filio.h>
# include <sys/malloc.h>
#else
# include <sys/ioctl.h>
#endif
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <net/if.h>
#include "netinet/ip_compat.h"
#include "netinet/ip_fil.h"
#include "netinet/ip_state.h"
#include "netinet/ip_scan.h"
/* END OF INCLUDES */
#if !defined(lint)
static const char sccsid[] = "@(#)ip_state.c 1.8 6/5/96 (C) 1993-2000 Darren Reed";
static const char rcsid[] = "@(#)$Id: ip_scan.c,v 2.40.2.10 2007/06/02 21:22:28 darrenr Exp $";
#endif
#ifdef IPFILTER_SCAN /* endif at bottom of file */
ipscan_t *ipsc_list = NULL,
*ipsc_tail = NULL;
ipscanstat_t ipsc_stat;
# ifdef USE_MUTEXES
ipfrwlock_t ipsc_rwlock;
# endif
# ifndef isalpha
# define isalpha(x) (((x) >= 'A' && 'Z' >= (x)) || \
((x) >= 'a' && 'z' >= (x)))
# endif
int ipsc_add __P((caddr_t));
int ipsc_delete __P((caddr_t));
struct ipscan *ipsc_lookup __P((char *));
int ipsc_matchstr __P((sinfo_t *, char *, int));
int ipsc_matchisc __P((ipscan_t *, ipstate_t *, int, int, int *));
int ipsc_match __P((ipstate_t *));
static int ipsc_inited = 0;
int ipsc_init()
{
RWLOCK_INIT(&ipsc_rwlock, "ip scan rwlock");
ipsc_inited = 1;
return 0;
}
void fr_scanunload()
{
if (ipsc_inited == 1) {
RW_DESTROY(&ipsc_rwlock);
ipsc_inited = 0;
}
}
int ipsc_add(data)
caddr_t data;
{
ipscan_t *i, *isc;
int err;
KMALLOC(isc, ipscan_t *);
if (!isc)
return ENOMEM;
err = copyinptr(data, isc, sizeof(*isc));
if (err) {
KFREE(isc);
return err;
}
WRITE_ENTER(&ipsc_rwlock);
i = ipsc_lookup(isc->ipsc_tag);
if (i) {
RWLOCK_EXIT(&ipsc_rwlock);
KFREE(isc);
return EEXIST;
}
if (ipsc_tail) {
ipsc_tail->ipsc_next = isc;
isc->ipsc_pnext = &ipsc_tail->ipsc_next;
ipsc_tail = isc;
} else {
ipsc_list = isc;
ipsc_tail = isc;
isc->ipsc_pnext = &ipsc_list;
}
isc->ipsc_next = NULL;
isc->ipsc_hits = 0;
isc->ipsc_fref = 0;
isc->ipsc_sref = 0;
isc->ipsc_active = 0;
ipsc_stat.iscs_entries++;
RWLOCK_EXIT(&ipsc_rwlock);
return 0;
}
int ipsc_delete(data)
caddr_t data;
{
ipscan_t isc, *i;
int err;
err = copyinptr(data, &isc, sizeof(isc));
if (err)
return err;
WRITE_ENTER(&ipsc_rwlock);
i = ipsc_lookup(isc.ipsc_tag);
if (i == NULL)
err = ENOENT;
else {
if (i->ipsc_fref) {
RWLOCK_EXIT(&ipsc_rwlock);
return EBUSY;
}
*i->ipsc_pnext = i->ipsc_next;
if (i->ipsc_next)
i->ipsc_next->ipsc_pnext = i->ipsc_pnext;
else {
if (i->ipsc_pnext == &ipsc_list)
ipsc_tail = NULL;
else
ipsc_tail = *(*i->ipsc_pnext)->ipsc_pnext;
}
ipsc_stat.iscs_entries--;
KFREE(i);
}
RWLOCK_EXIT(&ipsc_rwlock);
return err;
}
struct ipscan *ipsc_lookup(tag)
char *tag;
{
ipscan_t *i;
for (i = ipsc_list; i; i = i->ipsc_next)
if (!strcmp(i->ipsc_tag, tag))
return i;
return NULL;
}
int ipsc_attachfr(fr)
struct frentry *fr;
{
ipscan_t *i;
if (fr->fr_isctag[0]) {
READ_ENTER(&ipsc_rwlock);
i = ipsc_lookup(fr->fr_isctag);
if (i != NULL) {
ATOMIC_INC32(i->ipsc_fref);
}
RWLOCK_EXIT(&ipsc_rwlock);
if (i == NULL)
return ENOENT;
fr->fr_isc = i;
}
return 0;
}
int ipsc_attachis(is)
struct ipstate *is;
{
frentry_t *fr;
ipscan_t *i;
READ_ENTER(&ipsc_rwlock);
fr = is->is_rule;
if (fr) {
i = fr->fr_isc;
if ((i != NULL) && (i != (ipscan_t *)-1)) {
is->is_isc = i;
ATOMIC_INC32(i->ipsc_sref);
if (i->ipsc_clen)
is->is_flags |= IS_SC_CLIENT;
else
is->is_flags |= IS_SC_MATCHC;
if (i->ipsc_slen)
is->is_flags |= IS_SC_SERVER;
else
is->is_flags |= IS_SC_MATCHS;
}
}
RWLOCK_EXIT(&ipsc_rwlock);
return 0;
}
int ipsc_detachfr(fr)
struct frentry *fr;
{
ipscan_t *i;
i = fr->fr_isc;
if (i != NULL) {
ATOMIC_DEC32(i->ipsc_fref);
}
return 0;
}
int ipsc_detachis(is)
struct ipstate *is;
{
ipscan_t *i;
READ_ENTER(&ipsc_rwlock);
if ((i = is->is_isc) && (i != (ipscan_t *)-1)) {
ATOMIC_DEC32(i->ipsc_sref);
is->is_isc = NULL;
is->is_flags &= ~(IS_SC_CLIENT|IS_SC_SERVER);
}
RWLOCK_EXIT(&ipsc_rwlock);
return 0;
}
/*
* 'string' compare for scanning
*/
int ipsc_matchstr(sp, str, n)
sinfo_t *sp;
char *str;
int n;
{
char *s, *t, *up;
int i = n;
if (i > sp->s_len)
i = sp->s_len;
up = str;
for (s = sp->s_txt, t = sp->s_msk; i; i--, s++, t++, up++)
switch ((int)*t)
{
case '.' :
if (*s != *up)
return 1;
break;
case '?' :
if (!ISALPHA(*up) || ((*s & 0x5f) != (*up & 0x5f)))
return 1;
break;
case '*' :
break;
}
return 0;
}
/*
* Returns 3 if both server and client match, 2 if just server,
* 1 if just client
*/
int ipsc_matchisc(isc, is, cl, sl, maxm)
ipscan_t *isc;
ipstate_t *is;
int cl, sl, maxm[2];
{
int i, j, k, n, ret = 0, flags;
flags = is->is_flags;
/*
* If we've already matched more than what is on offer, then
* assume we have a better match already and forget this one.
*/
if (maxm != NULL) {
if (isc->ipsc_clen < maxm[0])
return 0;
if (isc->ipsc_slen < maxm[1])
return 0;
j = maxm[0];
k = maxm[1];
} else {
j = 0;
k = 0;
}
if (!isc->ipsc_clen)
ret = 1;
else if (((flags & (IS_SC_MATCHC|IS_SC_CLIENT)) == IS_SC_CLIENT) &&
cl && isc->ipsc_clen) {
i = 0;
n = MIN(cl, isc->ipsc_clen);
if ((n > 0) && (!maxm || (n >= maxm[1]))) {
if (!ipsc_matchstr(&isc->ipsc_cl, is->is_sbuf[0], n)) {
i++;
ret |= 1;
if (n > j)
j = n;
}
}
}
if (!isc->ipsc_slen)
ret |= 2;
else if (((flags & (IS_SC_MATCHS|IS_SC_SERVER)) == IS_SC_SERVER) &&
sl && isc->ipsc_slen) {
i = 0;
n = MIN(cl, isc->ipsc_slen);
if ((n > 0) && (!maxm || (n >= maxm[1]))) {
if (!ipsc_matchstr(&isc->ipsc_sl, is->is_sbuf[1], n)) {
i++;
ret |= 2;
if (n > k)
k = n;
}
}
}
if (maxm && (ret == 3)) {
maxm[0] = j;
maxm[1] = k;
}
return ret;
}
int ipsc_match(is)
ipstate_t *is;
{
int i, j, k, n, cl, sl, maxm[2];
ipscan_t *isc, *lm;
tcpdata_t *t;
for (cl = 0, n = is->is_smsk[0]; n & 1; n >>= 1)
cl++;
for (sl = 0, n = is->is_smsk[1]; n & 1; n >>= 1)
sl++;
j = 0;
isc = is->is_isc;
if (isc != NULL) {
/*
* Known object to scan for.
*/
i = ipsc_matchisc(isc, is, cl, sl, NULL);
if (i & 1) {
is->is_flags |= IS_SC_MATCHC;
is->is_flags &= ~IS_SC_CLIENT;
} else if (cl >= isc->ipsc_clen)
is->is_flags &= ~IS_SC_CLIENT;
if (i & 2) {
is->is_flags |= IS_SC_MATCHS;
is->is_flags &= ~IS_SC_SERVER;
} else if (sl >= isc->ipsc_slen)
is->is_flags &= ~IS_SC_SERVER;
} else {
i = 0;
lm = NULL;
maxm[0] = 0;
maxm[1] = 0;
for (k = 0, isc = ipsc_list; isc; isc = isc->ipsc_next) {
i = ipsc_matchisc(isc, is, cl, sl, maxm);
if (i) {
/*
* We only want to remember the best match
* and the number of times we get a best
* match.
*/
if ((j == 3) && (i < 3))
continue;
if ((i == 3) && (j != 3))
k = 1;
else
k++;
j = i;
lm = isc;
}
}
if (k == 1)
isc = lm;
if (isc == NULL)
return 0;
/*
* No matches or partial matches, so reset the respective
* search flag.
*/
if (!(j & 1))
is->is_flags &= ~IS_SC_CLIENT;
if (!(j & 2))
is->is_flags &= ~IS_SC_SERVER;
/*
* If we found the best match, then set flags appropriately.
*/
if ((j == 3) && (k == 1)) {
is->is_flags &= ~(IS_SC_SERVER|IS_SC_CLIENT);
is->is_flags |= (IS_SC_MATCHS|IS_SC_MATCHC);
}
}
/*
* If the acknowledged side of a connection has moved past the data in
* which we are interested, then reset respective flag.
*/
t = &is->is_tcp.ts_data[0];
if (t->td_end > is->is_s0[0] + 15)
is->is_flags &= ~IS_SC_CLIENT;
t = &is->is_tcp.ts_data[1];
if (t->td_end > is->is_s0[1] + 15)
is->is_flags &= ~IS_SC_SERVER;
/*
* Matching complete ?
*/
j = ISC_A_NONE;
if ((is->is_flags & IS_SC_MATCHALL) == IS_SC_MATCHALL) {
j = isc->ipsc_action;
ipsc_stat.iscs_acted++;
} else if ((is->is_isc != NULL) &&
((is->is_flags & IS_SC_MATCHALL) != IS_SC_MATCHALL) &&
!(is->is_flags & (IS_SC_CLIENT|IS_SC_SERVER))) {
/*
* Matching failed...
*/
j = isc->ipsc_else;
ipsc_stat.iscs_else++;
}
switch (j)
{
case ISC_A_CLOSE :
/*
* If as a result of a successful match we are to
* close a connection, change the "keep state" info.
* to block packets and generate TCP RST's.
*/
is->is_pass &= ~FR_RETICMP;
is->is_pass |= FR_RETRST;
break;
default :
break;
}
return i;
}
/*
* check if a packet matches what we're scanning for
*/
int ipsc_packet(fin, is)
fr_info_t *fin;
ipstate_t *is;
{
int i, j, rv, dlen, off, thoff;
u_32_t seq, s0;
tcphdr_t *tcp;
rv = !IP6_EQ(&fin->fin_fi.fi_src, &is->is_src);
tcp = fin->fin_dp;
seq = ntohl(tcp->th_seq);
if (!is->is_s0[rv])
return 1;
/*
* check if this packet has more data that falls within the first
* 16 bytes sent in either direction.
*/
s0 = is->is_s0[rv];
off = seq - s0;
if ((off > 15) || (off < 0))
return 1;
thoff = TCP_OFF(tcp) << 2;
dlen = fin->fin_dlen - thoff;
if (dlen <= 0)
return 1;
if (dlen > 16)
dlen = 16;
if (off + dlen > 16)
dlen = 16 - off;
j = 0xffff >> (16 - dlen);
i = (0xffff & j) << off;
#ifdef _KERNEL
COPYDATA(*(mb_t **)fin->fin_mp, fin->fin_plen - fin->fin_dlen + thoff,
dlen, (caddr_t)is->is_sbuf[rv] + off);
#endif
is->is_smsk[rv] |= i;
for (j = 0, i = is->is_smsk[rv]; i & 1; i >>= 1)
j++;
if (j == 0)
return 1;
(void) ipsc_match(is);
#if 0
/*
* There is the potential here for plain text passwords to get
* buffered and stored for some time...
*/
if (!(is->is_flags & IS_SC_CLIENT))
bzero(is->is_sbuf[0], sizeof(is->is_sbuf[0]));
if (!(is->is_flags & IS_SC_SERVER))
bzero(is->is_sbuf[1], sizeof(is->is_sbuf[1]));
#endif
return 0;
}
int fr_scan_ioctl(data, cmd, mode, uid, ctx)
caddr_t data;
ioctlcmd_t cmd;
int mode, uid;
void *ctx;
{
ipscanstat_t ipscs;
int err = 0;
switch (cmd)
{
case SIOCADSCA :
err = ipsc_add(data);
break;
case SIOCRMSCA :
err = ipsc_delete(data);
break;
case SIOCGSCST :
bcopy((char *)&ipsc_stat, (char *)&ipscs, sizeof(ipscs));
ipscs.iscs_list = ipsc_list;
err = BCOPYOUT(&ipscs, data, sizeof(ipscs));
if (err != 0)
err = EFAULT;
break;
default :
err = EINVAL;
break;
}
return err;
}
#endif /* IPFILTER_SCAN */
-106
View File
@@ -1,106 +0,0 @@
/*
* Copyright (C) 1993-2001 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* @(#)ip_fil.h 1.35 6/5/96
* $Id: ip_scan.h,v 2.9.2.2 2006/07/14 06:12:19 darrenr Exp $
*/
#ifndef __IP_SCAN_H__
#define __IP_SCAN_H__ 1
#ifdef sun
# include <sys/ioccom.h>
#endif
#define IPSCAN_NAME "/dev/ipscan"
#define IPL_SCAN IPSCAN_NAME
#define ISC_TLEN 16
struct fr_info;
struct frentry;
struct ip;
struct ipstate;
#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51)
# define SIOCADSCA _IOWR('r', 60, struct ipscan *)
# define SIOCRMSCA _IOWR('r', 61, struct ipscan *)
# define SIOCGSCST _IOWR('r', 62, struct ipscan *)
#else
# define SIOCADSCA _IOWR(r, 60, struct ipscan *)
# define SIOCRMSCA _IOWR(r, 61, struct ipscan *)
# define SIOCGSCST _IOWR(r, 62, struct ipscan *)
#endif
struct action {
int act_val; /* what to do */
struct in_addr act_ip; /* redirect IP# */
u_short act_port; /* redirect port number */
int act_else; /* what to do */
struct in_addr act_eip; /* redirect IP# */
u_short act_eport; /* redirect port number */
};
typedef struct sinfo {
char s_txt[ISC_TLEN]; /* text to match */
char s_msk[ISC_TLEN]; /* mask of the above to check */
int s_len; /* length of server text */
} sinfo_t;
typedef struct ipscan {
struct ipscan *ipsc_next;
struct ipscan **ipsc_pnext;
char ipsc_tag[ISC_TLEN]; /* table entry protocol tag */
sinfo_t ipsc_si[2]; /* client/server side information */
int ipsc_hits; /* times this has been matched */
int ipsc_active; /* # of active matches */
int ipsc_fref; /* # of references from filter rules */
int ipsc_sref; /* # of references from state entries */
struct action ipsc_act;
} ipscan_t;
#define ipsc_cl ipsc_si[0]
#define ipsc_sl ipsc_si[1]
#define ipsc_ctxt ipsc_cl.s_txt
#define ipsc_cmsk ipsc_cl.s_msk
#define ipsc_clen ipsc_cl.s_len
#define ipsc_stxt ipsc_sl.s_txt
#define ipsc_smsk ipsc_sl.s_msk
#define ipsc_slen ipsc_sl.s_len
#define ipsc_action ipsc_act.act_val
#define ipsc_ip ipsc_act.act_ip
#define ipsc_port ipsc_act.act_port
#define ipsc_else ipsc_act.act_else
#define ipsc_eip ipsc_act.act_eip
#define ipsc_eport ipsc_act.act_eport
#define ISC_A_NONE 0
#define ISC_A_TRACK 1
#define ISC_A_CLOSE 2
#define ISC_A_REDIRECT 3
typedef struct ipscanstat {
struct ipscan *iscs_list;
u_long iscs_acted;
u_long iscs_else;
int iscs_entries;
} ipscanstat_t;
extern int fr_scan_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *));
extern int ipsc_init __P((void));
extern int ipsc_attachis __P((struct ipstate *));
extern int ipsc_attachfr __P((struct frentry *));
extern int ipsc_detachis __P((struct ipstate *));
extern int ipsc_detachfr __P((struct frentry *));
extern int ipsc_packet __P((struct fr_info *, struct ipstate *));
extern void fr_scanunload __P((void));
#endif /* __IP_SCAN_H__ */
File diff suppressed because it is too large Load Diff
-258
View File
@@ -1,258 +0,0 @@
/*
* 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.68.2.10 2007/10/16 09:33:24 darrenr Exp $
*/
#ifndef __IP_STATE_H__
#define __IP_STATE_H__
#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51)
# define SIOCDELST _IOW('r', 61, struct ipfobj)
#else
# define SIOCDELST _IOW(r, 61, struct ipfobj)
#endif
struct ipscan;
#ifndef IPSTATE_SIZE
# define IPSTATE_SIZE 5737
#endif
#ifndef IPSTATE_MAX
# define IPSTATE_MAX 4013 /* Maximum number of states held */
#endif
#define SEQ_GE(a,b) ((int)((a) - (b)) >= 0)
#define SEQ_GT(a,b) ((int)((a) - (b)) > 0)
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;
frentry_t *is_rule;
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;
u_32_t is_hv;
u_32_t is_tag;
u_32_t is_opt[2]; /* packet options set */
u_32_t is_optmsk[2]; /* " " mask */
u_short is_sec; /* security options set */
u_short is_secmsk; /* " " mask */
u_short is_auth; /* authentication options set */
u_short is_authmsk; /* " " mask */
union {
icmpinfo_t is_ics;
tcpinfo_t is_ts;
udpinfo_t is_us;
greinfo_t is_ug;
} is_ps;
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.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_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_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)
/*
* is_flags:
* Bits 0 - 3 are use as a mask with the current packet's bits to check for
* whether it is short, tcp/udp, a fragment or the presence of IP options.
* 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 {
void *ips_next;
struct ipstate ips_is;
struct frentry ips_fr;
} ipstate_save_t;
#define ips_rule ips_is.is_rule
typedef struct ipslog {
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];
u_short isl_ports[2];
u_short isl_icmp;
} isl_ps;
u_char isl_v;
u_char isl_p;
u_char isl_flags;
u_char isl_state[2];
u_32_t isl_rulen;
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_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
#define ISL_UNLOAD 0xfff9
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;
u_long iss_nomem;
u_long iss_expire;
u_long iss_fin;
u_long iss_active;
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;
ipftq_t *iss_tcptab;
} ips_stat_t;
extern u_long fr_tcpidletimeout;
extern u_long fr_tcpclosewait;
extern u_long fr_tcplastack;
extern u_long fr_tcptimeout;
extern u_long fr_tcpclosed;
extern u_long fr_tcphalfclosed;
extern u_long fr_udptimeout;
extern u_long fr_udpacktimeout;
extern u_long fr_icmptimeout;
extern u_long fr_icmpacktimeout;
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 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((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));
extern int fr_state_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *));
extern void fr_stinsert __P((struct ipstate *, int));
extern void fr_sttab_init __P((struct ipftq *));
extern void fr_sttab_destroy __P((struct ipftq *));
extern void fr_updatestate __P((fr_info_t *, ipstate_t *, ipftq_t *));
extern void fr_statederef __P((ipstate_t **));
extern void fr_setstatequeue __P((ipstate_t *, int));
#endif /* __IP_STATE_H__ */
File diff suppressed because it is too large Load Diff
-117
View File
@@ -1,117 +0,0 @@
/*
* Copyright (C) 1993-2001 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* @(#)ip_fil.h 1.35 6/5/96
* $Id: ip_sync.h,v 2.11.2.4 2006/07/14 06:12:20 darrenr Exp $
*/
#ifndef __IP_SYNC_H__
#define __IP_SYNC_H__
typedef struct synchdr {
u_32_t sm_magic; /* magic */
u_char sm_v; /* version: 4,6 */
u_char sm_p; /* protocol */
u_char sm_cmd; /* command */
u_char sm_table; /* NAT, STATE, etc */
u_int sm_num; /* table entry number */
int sm_rev; /* forward/reverse */
int sm_len; /* length of the data section */
struct synclist *sm_sl; /* back pointer to parent */
} synchdr_t;
#define SYNHDRMAGIC 0x0FF51DE5
/*
* Commands
* No delete required as expirey will take care of that!
*/
#define SMC_CREATE 0 /* pass ipstate_t after synchdr_t */
#define SMC_UPDATE 1
#define SMC_MAXCMD 1
/*
* Tables
*/
#define SMC_NAT 0
#define SMC_STATE 1
#define SMC_MAXTBL 1
/*
* Only TCP requires "more" information than just a reference to the entry
* for which an update is being made.
*/
typedef struct synctcp_update {
u_long stu_age;
tcpdata_t stu_data[2];
int stu_state[2];
} synctcp_update_t;
typedef struct synclist {
struct synclist *sl_next;
struct synclist **sl_pnext;
int sl_idx; /* update index */
struct synchdr sl_hdr;
union {
struct ipstate *slu_ips;
struct nat *slu_ipn;
void *slu_ptr;
} sl_un;
} synclist_t;
#define sl_ptr sl_un.slu_ptr
#define sl_ips sl_un.slu_ips
#define sl_ipn sl_un.slu_ipn
#define sl_magic sl_hdr.sm_magic
#define sl_v sl_hdr.sm_v
#define sl_p sl_hdr.sm_p
#define sl_cmd sl_hdr.sm_cmd
#define sl_rev sl_hdr.sm_rev
#define sl_table sl_hdr.sm_table
#define sl_num sl_hdr.sm_num
#define sl_len sl_hdr.sm_len
/*
* NOTE: SYNCLOG_SZ is defined *low*. It should be the next power of two
* up for whatever number of packets per second you expect to see. Be
* warned: this index's a table of large elements (upto 272 bytes in size
* each), and thus a size of 8192, for example, results in a 2MB table.
* The lesson here is not to use small machines for running fast firewalls
* (100BaseT) in sync, where you might have upwards of 10k pps.
*/
#define SYNCLOG_SZ 256
typedef struct synclogent {
struct synchdr sle_hdr;
union {
struct ipstate sleu_ips;
struct nat sleu_ipn;
} sle_un;
} synclogent_t;
typedef struct syncupdent { /* 28 or 32 bytes */
struct synchdr sup_hdr;
struct synctcp_update sup_tcp;
} syncupdent_t;
extern synclogent_t synclog[SYNCLOG_SZ];
extern int fr_sync_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *));
extern synclist_t *ipfsync_new __P((int, fr_info_t *, void *));
extern void ipfsync_del __P((synclist_t *));
extern void ipfsync_update __P((int, fr_info_t *, synclist_t *));
extern int ipfsync_init __P((void));
extern int ipfsync_nat __P((synchdr_t *sp, void *data));
extern int ipfsync_state __P((synchdr_t *sp, void *data));
extern int ipfsync_read __P((struct uio *uio));
extern int ipfsync_write __P((struct uio *uio));
extern int ipfsync_canread __P((void));
extern int ipfsync_canwrite __P((void));
#endif /* IP_SYNC */
-17
View File
@@ -1,17 +0,0 @@
/*
* Copyright (C) 1993-2001, 2003 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* @(#)ipl.h 1.21 6/5/96
* $Id: ipl.h,v 2.52.2.30 2007/10/16 09:41:00 darrenr Exp $
*/
#ifndef __IPL_H__
#define __IPL_H__
#define IPL_VERSION "IP Filter: v4.1.28"
#define IPFILTER_VERSION 4012800
#endif
-385
View File
@@ -1,385 +0,0 @@
/*
* Copyright (C) 1993-1997 by Darren Reed.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
* to the original author and the contributors.
*/
/*
* 29/12/94 Added code from Marc Huber <huber@fzi.de> to allow it to allocate
* its own major char number! Way cool patch!
*/
#include <sys/param.h>
#if defined(__FreeBSD__) && (__FreeBSD__ > 1)
# ifdef IPFILTER_LKM
# include <osreldate.h>
# define ACTUALLY_LKM_NOT_KERNEL
# else
# include <sys/osreldate.h>
# endif
#endif
#include <sys/systm.h>
#if defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)
# include <sys/conf.h>
# include <sys/kernel.h>
# ifdef DEVFS
# include <sys/devfsext.h>
# if defined(IPFILTER) && defined(_KERNEL)
# include "opt_devfs.h"
# endif
# endif /*DEVFS*/
#endif
#include <sys/conf.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/proc.h>
#include <sys/uio.h>
#include <sys/kernel.h>
#include <sys/vnode.h>
#include <sys/namei.h>
#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/exec.h>
#include <sys/mbuf.h>
#if BSD >= 199506
# include <sys/sysctl.h>
#endif
#if (__FreeBSD_version >= 199511)
#include <net/if.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <net/route.h>
#include <netinet/ip_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#endif
#if (__FreeBSD__ > 1)
# include <sys/sysent.h>
#endif
#include <sys/lkm.h>
#include "netinet/ipl.h"
#include "netinet/ip_compat.h"
#include "netinet/ip_fil.h"
#include "netinet/ip_state.h"
#include "netinet/ip_nat.h"
#include "netinet/ip_auth.h"
#include "netinet/ip_frag.h"
#if !defined(VOP_LEASE) && defined(LEASE_CHECK)
#define VOP_LEASE LEASE_CHECK
#endif
#ifndef MIN
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif
extern int lkmenodev __P((void));
static char *ipf_devfiles[] = { IPL_NAME, IPL_NAT, IPL_STATE, IPL_AUTH,
NULL };
static int if_ipl_unload __P((struct lkm_table *, int));
static int if_ipl_load __P((struct lkm_table *, int));
static int if_ipl_remove __P((void));
int xxxinit __P((struct lkm_table *, int, int));
struct cdevsw ipldevsw =
{
iplopen, /* open */
iplclose, /* close */
iplread, /* read */
(void *)nullop, /* write */
iplioctl, /* ioctl */
(void *)nullop, /* stop */
(void *)nullop, /* reset */
(void *)NULL, /* tty */
(void *)nullop, /* select */
(void *)nullop, /* mmap */
NULL /* strategy */
};
#ifdef SYSCTL_INT
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,
&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_udptimeout, CTLFLAG_RW,
&fr_udptimeout, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RW,
&fr_icmptimeout, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_defnatage, CTLFLAG_RW,
&fr_defnatage, 0, "");
SYSCTL_INT(_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, ipl_inited, CTLFLAG_RD,
&ipl_inited, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_authsize, CTLFLAG_RD,
&fr_authsize, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_authused, CTLFLAG_RD,
&fr_authused, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_defaultauthage, CTLFLAG_RW,
&fr_defaultauthage, 0, "");
#endif
#ifdef DEVFS
void *ipf_devfs[IPL_LOGMAX + 1];
#endif
#if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000)
int ipl_major = 0;
MOD_DEV(IPL_VERSION, LM_DT_CHAR, -1, &ipldevsw);
extern struct cdevsw cdevsw[];
extern int vd_unuseddev __P((void));
extern int nchrdev;
#else
int ipl_major = CDEV_MAJOR;
static struct cdevsw ipl_cdevsw = {
iplopen, iplclose, iplread, nowrite, /* 79 */
iplioctl, nostop, noreset, nodevtotty,
noselect, nommap, nostrategy, "ipl",
NULL, -1
};
#endif
static int iplaction __P((struct lkm_table *, int));
static void ipl_drvinit __P((void *));
static int iplaction(lkmtp, cmd)
struct lkm_table *lkmtp;
int cmd;
{
#if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000)
int i = ipl_major;
struct lkm_dev *args = lkmtp->private.lkm_dev;
#endif
int err = 0;
switch (cmd)
{
case LKM_E_LOAD :
if (lkmexists(lkmtp))
return EEXIST;
#if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000)
for (i = 0; i < nchrdev; i++)
if (cdevsw[i].d_open == lkmenodev ||
cdevsw[i].d_open == iplopen)
break;
if (i == nchrdev) {
printf("IP Filter: No free cdevsw slots\n");
return ENODEV;
}
ipl_major = i;
args->lkm_offset = i; /* slot in cdevsw[] */
#endif
printf("IP Filter: loaded into slot %d\n", ipl_major);
err = if_ipl_load(lkmtp, cmd);
if (!err)
ipl_drvinit((void *)NULL);
return err;
break;
case LKM_E_UNLOAD :
err = if_ipl_unload(lkmtp, cmd);
if (!err) {
printf("IP Filter: unloaded from slot %d\n",
ipl_major);
# ifdef DEVFS
if (ipf_devfs[IPL_LOGIPF])
devfs_remove_dev(ipf_devfs[IPL_LOGIPF]);
if (ipf_devfs[IPL_LOGNAT])
devfs_remove_dev(ipf_devfs[IPL_LOGNAT]);
if (ipf_devfs[IPL_LOGSTATE])
devfs_remove_dev(ipf_devfs[IPL_LOGSTATE]);
if (ipf_devfs[IPL_LOGAUTH])
devfs_remove_dev(ipf_devfs[IPL_LOGAUTH]);
# endif
}
return err;
case LKM_E_STAT :
break;
default:
err = EIO;
break;
}
return 0;
}
static int if_ipl_remove __P((void))
{
char *name;
struct nameidata nd;
int error, i;
for (i = 0; (name = ipf_devfiles[i]); i++) {
NDINIT(&nd, DELETE, LOCKPARENT, UIO_SYSSPACE, name, curproc);
if ((error = namei(&nd)))
return (error);
VOP_LEASE(nd.ni_vp, curproc, curproc->p_ucred, LEASE_WRITE);
VOP_LOCK(nd.ni_vp);
VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
(void) VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
}
return 0;
}
static int if_ipl_unload(lkmtp, cmd)
struct lkm_table *lkmtp;
int cmd;
{
int error = 0;
error = ipldetach();
if (!error)
error = if_ipl_remove();
return error;
}
static int if_ipl_load(lkmtp, cmd)
struct lkm_table *lkmtp;
int cmd;
{
struct nameidata nd;
struct vattr vattr;
int error = 0, fmode = S_IFCHR|0600, i;
char *name;
error = iplattach();
if (error)
return error;
(void) if_ipl_remove();
for (i = 0; (name = ipf_devfiles[i]); i++) {
NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, name, curproc);
if ((error = namei(&nd)))
return error;
if (nd.ni_vp != NULL) {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
if (nd.ni_dvp == nd.ni_vp)
vrele(nd.ni_dvp);
else
vput(nd.ni_dvp);
vrele(nd.ni_vp);
return (EEXIST);
}
VATTR_NULL(&vattr);
vattr.va_type = VCHR;
vattr.va_mode = (fmode & 07777);
vattr.va_rdev = (ipl_major << 8) | i;
VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
if (error)
return error;
}
return 0;
}
#if defined(__FreeBSD_version) && (__FreeBSD_version < 220000)
/*
* strlen isn't present in 2.1.* kernels.
*/
size_t strlen(string)
char *string;
{
register char *s;
for (s = string; *s; s++)
;
return (size_t)(s - string);
}
int xxxinit(lkmtp, cmd, ver)
struct lkm_table *lkmtp;
int cmd, ver;
{
DISPATCH(lkmtp, cmd, ver, iplaction, iplaction, iplaction);
}
#else
# ifdef IPFILTER_LKM
# include <sys/exec.h>
MOD_DECL(if_ipl);
static struct lkm_dev _module = {
LM_DEV,
LKM_VERSION,
IPL_VERSION,
CDEV_MAJOR,
LM_DT_CHAR,
{ (void *)&ipl_cdevsw }
};
int if_ipl __P((struct lkm_table *, int, int));
int if_ipl(lkmtp, cmd, ver)
struct lkm_table *lkmtp;
int cmd, ver;
{
DISPATCH(lkmtp, cmd, ver, iplaction, iplaction, iplaction);
}
# endif
static ipl_devsw_installed = 0;
static void ipl_drvinit __P((void *unused))
{
dev_t dev;
# ifdef DEVFS
void **tp = ipf_devfs;
# endif
if (!ipl_devsw_installed ) {
dev = makedev(CDEV_MAJOR, 0);
cdevsw_add(&dev, &ipl_cdevsw, NULL);
ipl_devsw_installed = 1;
# ifdef DEVFS
tp[IPL_LOGIPF] = devfs_add_devswf(&ipl_cdevsw, IPL_LOGIPF,
DV_CHR, 0, 0, 0600, "ipf");
tp[IPL_LOGNAT] = devfs_add_devswf(&ipl_cdevsw, IPL_LOGNAT,
DV_CHR, 0, 0, 0600, "ipnat");
tp[IPL_LOGSTATE] = devfs_add_devswf(&ipl_cdevsw, IPL_LOGSTATE,
DV_CHR, 0, 0, 0600,
"ipstate");
tp[IPL_LOGAUTH] = devfs_add_devswf(&ipl_cdevsw, IPL_LOGAUTH,
DV_CHR, 0, 0, 0600,
"ipauth");
# endif
}
}
# if defined(IPFILTER_LKM) || \
defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)
SYSINIT(ipldev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ipl_drvinit,NULL)
# endif /* IPFILTER_LKM */
#endif /* _FreeBSD_version */
-359
View File
@@ -1,359 +0,0 @@
/*
* Copyright (C) 2000 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/conf.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/select.h>
#if __FreeBSD_version >= 500000
# include <sys/selinfo.h>
#endif
#include <net/if.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ipl.h>
#include <netinet/ip_compat.h>
#include <netinet/ip_fil.h>
#include <netinet/ip_state.h>
#include <netinet/ip_nat.h>
#include <netinet/ip_auth.h>
#include <netinet/ip_frag.h>
#include <netinet/ip_sync.h>
#if __FreeBSD_version >= 502116
static struct cdev *ipf_devs[IPL_LOGSIZE];
#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_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_IPF(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RWO,
&fr_tcphalfclosed, 0, "");
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_IPF(_net_inet_ipf, OID_AUTO, fr_udpacktimeout, CTLFLAG_RWO,
&fr_udpacktimeout, 0, "");
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RWO,
&fr_icmptimeout, 0, "");
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defnatage, CTLFLAG_RWO,
&fr_defnatage, 0, "");
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_ipfrttl, CTLFLAG_RW,
&fr_ipfrttl, 0, "");
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_running, CTLFLAG_RD,
&fr_running, 0, "");
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_IPF(_net_inet_ipf, OID_AUTO, fr_authused, CTLFLAG_RD,
&fr_authused, 0, "");
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defaultauthage, CTLFLAG_RW,
&fr_defaultauthage, 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
#include <sys/poll.h>
#if __FreeBSD_version >= 500043
# include <sys/select.h>
static int iplpoll(struct cdev *dev, int events, struct thread *td);
static struct cdevsw ipl_cdevsw = {
# if __FreeBSD_version >= 502103
.d_version = D_VERSION,
.d_flags = 0, /* D_NEEDGIANT - Should be SMP safe */
# endif
.d_open = iplopen,
.d_close = iplclose,
.d_read = iplread,
.d_write = iplwrite,
.d_ioctl = iplioctl,
.d_name = "ipl",
# if __FreeBSD_version >= 500043
.d_poll = iplpoll,
# endif
# if __FreeBSD_version < 600000
.d_maj = CDEV_MAJOR,
# endif
};
#else
static int iplpoll(dev_t dev, int events, struct proc *p);
static struct cdevsw ipl_cdevsw = {
/* open */ iplopen,
/* close */ iplclose,
/* read */ iplread,
/* write */ iplwrite,
/* ioctl */ iplioctl,
/* poll */ iplpoll,
/* mmap */ nommap,
/* strategy */ nostrategy,
/* name */ "ipl",
/* maj */ CDEV_MAJOR,
/* dump */ nodump,
/* psize */ nopsize,
/* flags */ 0,
# if (__FreeBSD_version < 500043)
/* bmaj */ -1,
# endif
# if (__FreeBSD_version > 430000)
/* kqfilter */ NULL
# endif
};
#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)
{
int error = 0;
switch (type)
{
case MOD_LOAD :
error = ipf_modload();
break;
case MOD_UNLOAD :
error = ipf_modunload();
break;
default:
error = EINVAL;
break;
}
return error;
}
static int
ipf_modload()
{
char *defpass, *c, *str;
int i, j, error;
RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex");
RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock");
RWLOCK_INIT(&ipf_frcache, "ipf cache rwlock");
error = ipfattach();
if (error) {
RW_DESTROY(&ipf_global);
RW_DESTROY(&ipf_mutex);
RW_DESTROY(&ipf_frcache);
return error;
}
for (i = 0; i < IPL_LOGSIZE; i++)
ipf_devs[i] = NULL;
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);
}
error = ipf_pfil_hook();
if (error != 0)
return error;
ipf_event_reg();
if (FR_ISPASS(fr_pass))
defpass = "pass";
else if (FR_ISBLOCK(fr_pass))
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) {
ipf_pfil_unhook();
ipf_event_dereg();
WRITE_ENTER(&ipf_global);
error = ipfdetach();
RWLOCK_EXIT(&ipf_global);
if (error != 0)
return error;
} else
error = 0;
RW_DESTROY(&ipf_global);
RW_DESTROY(&ipf_mutex);
RW_DESTROY(&ipf_frcache);
fr_running = -2;
for (i = 0; ipf_devfiles[i]; i++) {
if (ipf_devs[i] != NULL)
destroy_dev(ipf_devs[i]);
}
printf("%s unloaded\n", ipfilter_version);
return error;
}
static moduledata_t ipfiltermod = {
"ipfilter",
ipfilter_modevent,
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
static int
#if __FreeBSD_version >= 500043
iplpoll(struct cdev *dev, int events, struct thread *td)
#else
iplpoll(dev_t dev, int events, struct proc *td)
#endif
{
u_int xmin = GET_MINOR(dev);
int revents;
if (xmin < 0 || xmin > IPL_LOGMAX)
return 0;
revents = 0;
switch (xmin)
{
case IPL_LOGIPF :
case IPL_LOGNAT :
case IPL_LOGSTATE :
#ifdef IPFILTER_LOG
if ((events & (POLLIN | POLLRDNORM)) && ipflog_canread(xmin))
revents |= events & (POLLIN | POLLRDNORM);
#endif
break;
case IPL_LOGAUTH :
if ((events & (POLLIN | POLLRDNORM)) && fr_auth_waiting())
revents |= events & (POLLIN | POLLRDNORM);
break;
case IPL_LOGSYNC :
#ifdef IPFILTER_SYNC
if ((events & (POLLIN | POLLRDNORM)) && ipfsync_canread())
revents |= events & (POLLIN | POLLRDNORM);
if ((events & (POLLOUT | POLLWRNORM)) && ipfsync_canwrite())
revents |= events & (POLLOUT | POLLWRNORM);
#endif
break;
case IPL_LOGSCAN :
case IPL_LOGLOOKUP :
default :
break;
}
if ((revents == 0) && ((events & (POLLIN|POLLRDNORM)) != 0))
selrecord(td, &ipfselwait[xmin]);
return revents;
}
-377
View File
@@ -1,377 +0,0 @@
/*
* (C)opyright 1993,1994,1995 by Darren Reed.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
* to the original author and the contributors.
*/
/*
* 29/12/94 Added code from Marc Huber <huber@fzi.de> to allow it to allocate
* its own major char number! Way cool patch!
*/
#include <sys/param.h>
#if defined(__FreeBSD__) && (__FreeBSD__ > 1)
# ifdef IPFILTER_LKM
# include <osreldate.h>
# define ACTUALLY_LKM_NOT_KERNEL
# else
# include <sys/osreldate.h>
# endif
#endif
#include <sys/systm.h>
#if defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)
# include <sys/conf.h>
# include <sys/kernel.h>
# ifdef DEVFS
# include <sys/devfsext.h>
# endif /*DEVFS*/
#endif
#include <sys/conf.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/proc.h>
#include <sys/uio.h>
#include <sys/kernel.h>
#include <sys/vnode.h>
#include <sys/namei.h>
#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/exec.h>
#include <sys/mbuf.h>
#if BSD >= 199506
# include <sys/sysctl.h>
#endif
#if (__FreeBSD_version >= 199511)
#include <net/if.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <net/route.h>
#include <netinet/ip_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#endif
#if (__FreeBSD__ > 1)
# include <sys/sysent.h>
#endif
#include <sys/lkm.h>
#include "netinet/ipl.h"
#include "netinet/ip_compat.h"
#include "netinet/ip_fil.h"
#ifndef IPL_NAME
#define IPL_NAME "/dev/ipl"
#endif
#define IPL_NAT "/dev/ipnat"
#define IPL_STATE "/dev/ipstate"
#if !defined(VOP_LEASE) && defined(LEASE_CHECK)
#define VOP_LEASE LEASE_CHECK
#endif
#ifndef MIN
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif
extern int lkmenodev __P((void));
static int ipl_unload __P((void));
static int ipl_load __P((void));
static int ipl_remove __P((void));
int xxxinit __P((struct lkm_table *, int, int));
struct cdevsw ipldevsw =
{
iplopen, /* open */
iplclose, /* close */
iplread, /* read */
(void *)nullop, /* write */
iplioctl, /* ioctl */
(void *)nullop, /* stop */
(void *)nullop, /* reset */
(void *)NULL, /* tty */
(void *)nullop, /* select */
(void *)nullop, /* mmap */
NULL /* strategy */
};
#ifdef SYSCTL_INT
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, ipl_unreach, CTLFLAG_RW,
&ipl_unreach, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, ipl_inited, CTLFLAG_RD,
&ipl_inited, 0, "");
#endif
#if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000)
int ipl_major = 0;
MOD_DEV(IPL_VERSION, LM_DT_CHAR, -1, &ipldevsw);
extern struct cdevsw cdevsw[];
extern int vd_unuseddev __P((void));
extern int nchrdev;
#else
int ipl_major = CDEV_MAJOR;
static struct cdevsw ipl_cdevsw = {
iplopen, iplclose, iplread, nowrite, /* 79 */
iplioctl, nostop, noreset, nodevtotty,
noselect, nommap, nostrategy, "ipl",
NULL, -1
};
#endif
static int iplaction __P((struct lkm_table *, int));
static int iplaction(lkmtp, cmd)
struct lkm_table *lkmtp;
int cmd;
{
int i = ipl_major;
struct lkm_dev *args = lkmtp->private.lkm_dev;
int err = 0;
switch (cmd)
{
case LKM_E_LOAD :
if (lkmexists(lkmtp))
return EEXIST;
#if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000)
for (i = 0; i < nchrdev; i++)
if (cdevsw[i].d_open == lkmenodev ||
cdevsw[i].d_open == iplopen)
break;
if (i == nchrdev) {
printf("IP Filter: No free cdevsw slots\n");
return ENODEV;
}
ipl_major = i;
args->lkm_offset = i; /* slot in cdevsw[] */
#endif
printf("IP Filter: loaded into slot %d\n", ipl_major);
return ipl_load();
break;
case LKM_E_UNLOAD :
printf("IP Filter: unloaded from slot %d\n", ipl_major);
return ipl_unload();
case LKM_E_STAT :
break;
default:
err = EIO;
break;
}
return 0;
}
static int ipl_remove __P((void))
{
struct nameidata nd;
int error;
NDINIT(&nd, DELETE, LOCKPARENT, UIO_SYSSPACE, IPL_NAME, curproc);
if ((error = namei(&nd)))
return (error);
VOP_LEASE(nd.ni_vp, curproc, curproc->p_ucred, LEASE_WRITE);
VOP_LOCK(nd.ni_vp);
VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
(void) VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
NDINIT(&nd, DELETE, LOCKPARENT, UIO_SYSSPACE, IPL_NAT, curproc);
if ((error = namei(&nd)))
return (error);
VOP_LEASE(nd.ni_vp, curproc, curproc->p_ucred, LEASE_WRITE);
VOP_LOCK(nd.ni_vp);
VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
(void) VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
NDINIT(&nd, DELETE, LOCKPARENT, UIO_SYSSPACE, IPL_STATE, curproc);
if ((error = namei(&nd)))
return (error);
VOP_LEASE(nd.ni_vp, curproc, curproc->p_ucred, LEASE_WRITE);
VOP_LOCK(nd.ni_vp);
VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
(void) VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
return 0;
}
static int ipl_unload()
{
int error = 0;
error = ipldetach();
if (!error)
error = ipl_remove();
return error;
}
static int ipl_load()
{
struct nameidata nd;
struct vattr vattr;
int error = 0, fmode = S_IFCHR|0600;
error = iplattach();
if (error)
return error;
(void) ipl_remove();
NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, IPL_NAME, curproc);
if (error = namei(&nd))
return error;
if (nd.ni_vp != NULL) {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
if (nd.ni_dvp == nd.ni_vp)
vrele(nd.ni_dvp);
else
vput(nd.ni_dvp);
vrele(nd.ni_vp);
return (EEXIST);
}
VATTR_NULL(&vattr);
vattr.va_type = VCHR;
vattr.va_mode = (fmode & 07777);
vattr.va_rdev = ipl_major<<8;
VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
if (error)
return error;
NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, IPL_NAT, curproc);
if (error = namei(&nd))
return error;
if (nd.ni_vp != NULL) {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
if (nd.ni_dvp == nd.ni_vp)
vrele(nd.ni_dvp);
else
vput(nd.ni_dvp);
vrele(nd.ni_vp);
return (EEXIST);
}
VATTR_NULL(&vattr);
vattr.va_type = VCHR;
vattr.va_mode = (fmode & 07777);
vattr.va_rdev = (ipl_major<<8)|1;
VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
if (error)
return error;
NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, IPL_STATE, curproc);
if (error = namei(&nd))
return error;
if (nd.ni_vp != NULL) {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
if (nd.ni_dvp == nd.ni_vp)
vrele(nd.ni_dvp);
else
vput(nd.ni_dvp);
vrele(nd.ni_vp);
return (EEXIST);
}
VATTR_NULL(&vattr);
vattr.va_type = VCHR;
vattr.va_mode = (fmode & 07777);
vattr.va_rdev = (ipl_major<<8)|2;
VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
if (error)
return error;
return 0;
}
#if defined(__FreeBSD_version) && (__FreeBSD_version < 220000)
/*
* strlen isn't present in 2.1.* kernels.
*/
size_t strlen(string)
char *string;
{
register char *s;
for (s = string; *s; s++)
;
return (size_t)(s - string);
}
int xxxinit(lkmtp, cmd, ver)
struct lkm_table *lkmtp;
int cmd, ver;
{
DISPATCH(lkmtp, cmd, ver, iplaction, iplaction, iplaction);
}
#else
# ifdef IPFILTER_LKM
# include <sys/exec.h>
MOD_DECL(if_ipl);
static struct lkm_dev _module = {
LM_DEV,
LKM_VERSION,
IPL_VERSION,
CDEV_MAJOR,
LM_DT_CHAR,
(void *)&ipl_cdevsw
};
int if_ipl(lkmtp, cmd, ver)
struct lkm_table *lkmtp;
int cmd, ver;
{
DISPATCH(lkmtp, cmd, ver, iplaction, iplaction, iplaction);
}
# else
#ifdef DEVFS
static void *ipf_devfs_token[3];
#endif
static ipl_devsw_installed = 0;
static void ipl_drvinit __P((void *unused))
{
dev_t dev;
#ifdef DEVFS
void **tp = ipf_devfs_token;
#endif
if (!ipl_devsw_installed ) {
dev = makedev(CDEV_MAJOR, 0);
cdevsw_add(&dev, &ipl_cdevsw, NULL);
ipl_devsw_installed = 1;
#ifdef DEVFS
tp[IPL_LOGIPF] = devfs_add_devswf(&ipl_cdevsw, IPL_LOGIPF,
DV_CHR, 0, 0, 0600,
"ipf", IPL_LOGIPF);
tp[IPL_LOGNAT] = devfs_add_devswf(&ipl_cdevsw, IPL_LOGNAT,
DV_CHR, 0, 0, 0600,
"ipnat", IPL_LOGNAT);
tp[IPL_LOGSTATE] = devfs_add_devswf(&ipl_cdevsw, IPL_LOGSTATE,
DV_CHR, 0, 0, 0600,
"ipstate", IPL_LOGSTATE);
#endif
}
}
SYSINIT(ipldev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ipl_drvinit,NULL)
# endif /* IPFILTER_LKM */
#endif /* _FreeBSD_version */
-12
View File
@@ -1,12 +0,0 @@
-----BEGIN DSA PRIVATE KEY-----
MIIBuwIBAAKBgQCXGsxsgDt2euTDP/IQGY4O4CsKH9NXzI3dQ44L0w3PLYr/JQuY
kB8TLuCFZPIO/nlkubnCQGNnmcyUBlIA654Y7FEPBhLa4BWT6cpF4rfVzCQMq4W9
ZqXv549OZ0Ejg6ciJ/Udhhjx/TMn6sIojEZmHBdToTtK54119hC6eOxnQwIVAIO3
p+t6ASypQY8M+h96GZlVmkHRAoGAfK41snqWLcHspLYsIHu2tUwip7GqPPNe7Iej
CX17PiPbt9S5ph8aI6hPVmAUoKpfEb8OMDak3sFAFoDnve/FgOsZS+HKRpJRqUtW
PbBrhvRkQ5N4SWOzK54GXt/aWRTcUoVDz29QiakTfrZtdHeiJTbVNR36JdQ/nIHO
VWTWpcMCgYA4oHMrfK7/LMrjKWOLW8bXanvgL+nMoFVChYqzfBptvd492chAokKa
cr8NJDeT10i98TYooi0AvEthor9PVBDFMA0fj+LdM95HZTr6NIMAtxik8Ici4e7X
S4xWlsjTJQO6Kx7Hfuyt9EH2QkraLXFiFFKudGdvHqHeZ0q3iJ5JXwIVAIGBuoE0
wrpIyJQuIMYL5HJxQ8wt
-----END DSA PRIVATE KEY-----
-1
View File
@@ -1 +0,0 @@
ssh-dss AAAAB3NzaC1kc3MAAACBAJcazGyAO3Z65MM/8hAZjg7gKwof01fMjd1DjgvTDc8tiv8lC5iQHxMu4IVk8g7+eWS5ucJAY2eZzJQGUgDrnhjsUQ8GEtrgFZPpykXit9XMJAyrhb1mpe/nj05nQSODpyIn9R2GGPH9MyfqwiiMRmYcF1OhO0rnjXX2ELp47GdDAAAAFQCDt6fregEsqUGPDPofehmZVZpB0QAAAIB8rjWyepYtweyktiwge7a1TCKnsao8817sh6MJfXs+I9u31LmmHxojqE9WYBSgql8Rvw4wNqTewUAWgOe978WA6xlL4cpGklGpS1Y9sGuG9GRDk3hJY7MrngZe39pZFNxShUPPb1CJqRN+tm10d6IlNtU1Hfol1D+cgc5VZNalwwAAAIA4oHMrfK7/LMrjKWOLW8bXanvgL+nMoFVChYqzfBptvd492chAokKacr8NJDeT10i98TYooi0AvEthor9PVBDFMA0fj+LdM95HZTr6NIMAtxik8Ici4e7XS4xWlsjTJQO6Kx7Hfuyt9EH2QkraLXFiFFKudGdvHqHeZ0q3iJ5JXw== darrenr@freefall.freebsd.org