1997-07-07 02:32:34 +04:00
|
|
|
/* $NetBSD: ip_fil.c,v 1.23 1997/07/06 22:32:34 thorpej Exp $ */
|
1997-01-06 00:32:18 +03:00
|
|
|
|
1997-01-05 16:47:59 +03:00
|
|
|
/*
|
1997-05-25 16:40:11 +04:00
|
|
|
* (C)opyright 1993-1997 by Darren Reed.
|
1997-01-05 16:47:59 +03:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
#if !defined(lint) && defined(LIBC_SCCS)
|
|
|
|
static char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-1995 Darren Reed";
|
1997-07-06 09:29:13 +04:00
|
|
|
static char rcsid[] = "Id: ip_fil.c,v 2.0.2.25 1997/07/05 04:38:41 darrenr Exp";
|
1997-01-05 16:47:59 +03:00
|
|
|
#endif
|
|
|
|
|
1997-03-29 03:54:55 +03:00
|
|
|
#ifndef SOLARIS
|
1997-05-28 04:17:11 +04:00
|
|
|
#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
|
1997-03-29 03:54:55 +03:00
|
|
|
#endif
|
|
|
|
|
1997-05-25 16:40:11 +04:00
|
|
|
#ifdef __FreeBSD__
|
|
|
|
# if defined(KERNEL) && !defined(_KERNEL)
|
|
|
|
# define _KERNEL
|
|
|
|
# endif
|
|
|
|
# if defined(_KERNEL) && !defined(IPFILTER_LKM)
|
|
|
|
# include <sys/osreldate.h>
|
|
|
|
# else
|
|
|
|
# include <osreldate.h>
|
|
|
|
# endif
|
|
|
|
#endif
|
1997-03-29 03:54:55 +03:00
|
|
|
#ifndef _KERNEL
|
1997-07-05 09:38:14 +04:00
|
|
|
# include <stdio.h>
|
|
|
|
# include <string.h>
|
|
|
|
# include <stdlib.h>
|
|
|
|
# include <ctype.h>
|
1997-03-29 03:54:55 +03:00
|
|
|
#endif
|
1997-01-05 16:47:59 +03:00
|
|
|
#include <sys/errno.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/file.h>
|
1997-05-25 16:40:11 +04:00
|
|
|
#if __FreeBSD_version >= 220000 && defined(_KERNEL)
|
|
|
|
# include <sys/fcntl.h>
|
|
|
|
# include <sys/filio.h>
|
|
|
|
#else
|
|
|
|
# include <sys/ioctl.h>
|
|
|
|
#endif
|
|
|
|
#include <sys/time.h>
|
1997-03-29 03:54:55 +03:00
|
|
|
#ifdef _KERNEL
|
1997-07-05 09:38:14 +04:00
|
|
|
# include <sys/systm.h>
|
1997-03-29 03:54:55 +03:00
|
|
|
#endif
|
1997-01-05 16:47:59 +03:00
|
|
|
#include <sys/uio.h>
|
1997-03-29 03:54:55 +03:00
|
|
|
#if !SOLARIS
|
1997-07-05 09:38:14 +04:00
|
|
|
# if NetBSD > 199609
|
1997-04-15 04:44:42 +04:00
|
|
|
# include <sys/dirent.h>
|
|
|
|
# else
|
|
|
|
# include <sys/dir.h>
|
|
|
|
# endif
|
1997-07-05 09:38:14 +04:00
|
|
|
# include <sys/mbuf.h>
|
1997-03-29 03:54:55 +03:00
|
|
|
#else
|
1997-07-05 09:38:14 +04:00
|
|
|
# include <sys/filio.h>
|
1997-03-29 03:54:55 +03:00
|
|
|
#endif
|
1997-01-05 16:47:59 +03:00
|
|
|
#include <sys/protosw.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
|
|
|
#include <net/if.h>
|
|
|
|
#ifdef sun
|
1997-07-05 09:38:14 +04:00
|
|
|
# include <net/af.h>
|
1997-05-25 16:40:11 +04:00
|
|
|
#endif
|
|
|
|
#if __FreeBSD_version >= 300000
|
|
|
|
# include <net/if_var.h>
|
1997-01-05 16:47:59 +03:00
|
|
|
#endif
|
|
|
|
#include <net/route.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <netinet/in_var.h>
|
|
|
|
#include <netinet/in_systm.h>
|
|
|
|
#include <netinet/ip.h>
|
|
|
|
#include <netinet/ip_var.h>
|
|
|
|
#include <netinet/tcp.h>
|
|
|
|
#include <netinet/udp.h>
|
|
|
|
#include <netinet/tcpip.h>
|
|
|
|
#include <netinet/ip_icmp.h>
|
1997-05-25 16:40:11 +04:00
|
|
|
#ifndef _KERNEL
|
1997-04-15 04:44:42 +04:00
|
|
|
# include <syslog.h>
|
1997-01-05 16:47:59 +03:00
|
|
|
#endif
|
1997-05-25 16:40:11 +04:00
|
|
|
#include "netinet/ip_compat.h"
|
|
|
|
#include "netinet/ip_fil.h"
|
|
|
|
#include "netinet/ip_proxy.h"
|
|
|
|
#include "netinet/ip_nat.h"
|
|
|
|
#include "netinet/ip_frag.h"
|
|
|
|
#include "netinet/ip_state.h"
|
1997-07-05 09:38:14 +04:00
|
|
|
#include "netinet/ip_auth.h"
|
1997-01-05 16:47:59 +03:00
|
|
|
#ifndef MIN
|
1997-05-25 16:40:11 +04:00
|
|
|
#define MIN(a,b) (((a)<(b))?(a):(b))
|
|
|
|
#endif
|
|
|
|
#if !SOLARIS && defined(_KERNEL)
|
|
|
|
extern int ip_optcopy __P((struct ip *, struct ip *));
|
1997-01-05 16:47:59 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
1997-05-25 16:40:11 +04:00
|
|
|
extern struct protosw inetsw[];
|
1997-07-05 09:38:14 +04:00
|
|
|
|
|
|
|
#ifndef _KERNEL
|
|
|
|
# include "ipt.h"
|
|
|
|
static struct ifnet **ifneta = NULL;
|
|
|
|
static int nifs = 0;
|
|
|
|
#else
|
|
|
|
# if BSD < 199306
|
1997-03-29 03:54:55 +03:00
|
|
|
static int (*fr_saveslowtimo) __P((void));
|
1997-01-05 16:47:59 +03:00
|
|
|
extern int tcp_ttl;
|
1997-07-05 09:38:14 +04:00
|
|
|
# else
|
1997-01-05 16:47:59 +03:00
|
|
|
static void (*fr_saveslowtimo) __P((void));
|
1997-07-05 09:38:14 +04:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
int ipl_inited = 0;
|
|
|
|
int ipl_unreach = ICMP_UNREACH_FILTER;
|
|
|
|
|
|
|
|
#ifdef IPFILTER_LOG
|
1997-07-05 09:38:14 +04:00
|
|
|
char iplbuf[IPL_LOGMAX+1][IPLLOGSIZE];
|
|
|
|
caddr_t iplh[IPL_LOGMAX+1], iplt[IPL_LOGMAX+1];
|
|
|
|
int iplused[IPL_LOGMAX+1] = {0,0,0};
|
1997-01-05 16:47:59 +03:00
|
|
|
#endif /* IPFILTER_LOG */
|
1997-03-29 03:54:55 +03:00
|
|
|
static void frflush __P((caddr_t));
|
1997-07-05 09:38:14 +04:00
|
|
|
#ifdef __NetBSD__
|
|
|
|
static int frrequest __P((int, u_long, caddr_t, int));
|
1997-05-28 04:17:11 +04:00
|
|
|
#else
|
1997-07-05 09:38:14 +04:00
|
|
|
static int frrequest __P((int, int, caddr_t, int));
|
1997-05-28 04:17:11 +04:00
|
|
|
#endif
|
1997-03-29 03:54:55 +03:00
|
|
|
static void frzerostats __P((caddr_t));
|
1997-07-06 09:13:00 +04:00
|
|
|
static void fixskip __P((frentry_t **, frentry_t *, int));
|
1997-03-29 03:54:55 +03:00
|
|
|
#ifdef _KERNEL
|
|
|
|
static int (*fr_savep) __P((struct ip *, int, struct ifnet *,
|
|
|
|
int, struct mbuf **));
|
|
|
|
#else
|
|
|
|
void init_ifp __P((void));
|
1997-07-05 09:38:14 +04:00
|
|
|
/*
|
1997-03-29 03:54:55 +03:00
|
|
|
static int (*fr_savep) __P((struct ip *, int, struct ifnet *,
|
|
|
|
int, char *));
|
1997-07-05 09:38:14 +04:00
|
|
|
*/
|
1997-03-29 03:54:55 +03:00
|
|
|
static int no_output __P((struct ifnet *, struct mbuf *,
|
|
|
|
struct sockaddr *, struct rtentry *));
|
|
|
|
static int write_output __P((struct ifnet *, struct mbuf *,
|
|
|
|
struct sockaddr *, struct rtentry *));
|
|
|
|
#endif
|
1997-01-05 16:47:59 +03:00
|
|
|
|
1997-03-29 03:54:55 +03:00
|
|
|
#if (_BSDI_VERSION >= 199510) && defined(_KERNEL)
|
1997-01-05 16:47:59 +03:00
|
|
|
# include <sys/device.h>
|
|
|
|
# include <sys/conf.h>
|
|
|
|
|
|
|
|
struct cfdriver iplcd = {
|
|
|
|
NULL, "ipl", NULL, NULL, DV_DULL, 0
|
|
|
|
};
|
|
|
|
|
|
|
|
struct devsw iplsw = {
|
|
|
|
&iplcd,
|
|
|
|
iplopen, iplclose, iplread, nowrite, iplioctl, noselect, nommap,
|
|
|
|
nostrat, nodump, nopsize, 0,
|
|
|
|
nostop
|
|
|
|
};
|
1997-03-29 03:54:55 +03:00
|
|
|
#endif /* _BSDI_VERSION >= 199510 && _KERNEL */
|
1997-01-05 16:47:59 +03:00
|
|
|
|
1997-03-29 03:54:55 +03:00
|
|
|
#if defined(__NetBSD__)
|
1997-04-15 04:44:42 +04:00
|
|
|
# include <sys/conf.h>
|
|
|
|
# if defined(NETBSD_PF)
|
|
|
|
# include <net/pfil.h>
|
1997-03-29 06:05:14 +03:00
|
|
|
/*
|
|
|
|
* We provide the fr_checkp name just to minimize changes later.
|
|
|
|
*/
|
1997-03-29 07:39:15 +03:00
|
|
|
int (*fr_checkp) __P((ip_t *ip, int hlen, struct ifnet *ifp, int out,
|
1997-07-07 02:32:34 +04:00
|
|
|
mb_t **mp));
|
1997-04-15 04:44:42 +04:00
|
|
|
# endif /* NETBSD_PF */
|
1997-03-29 06:05:14 +03:00
|
|
|
#endif /* __NetBSD__ */
|
1997-01-05 16:47:59 +03:00
|
|
|
|
1997-03-29 03:54:55 +03:00
|
|
|
#ifdef _KERNEL
|
|
|
|
# ifdef IPFILTER_LKM
|
1997-01-05 16:47:59 +03:00
|
|
|
int iplidentify(s)
|
|
|
|
char *s;
|
|
|
|
{
|
|
|
|
if (strcmp(s, "ipl") == 0)
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
1997-03-29 03:54:55 +03:00
|
|
|
# endif /* IPFILTER_LKM */
|
1997-01-05 16:47:59 +03:00
|
|
|
|
|
|
|
|
Fix an ... interesting bug that resulted from namespace collision.
Description:
- A BSD pseudo-device initialization routine is declared as
void <pseudo-device name>attach __P((int count));
in ioconf.c by config(8). main() calls these functions
from a table.
- IP Filter has functions iplattach() and ipldetach() (or,
in the NetBSD case, were erroneously renamed ipfilterattach()
and ipfilterdetach()). These functions are used to establish
and disestablish the IP Filter "filter rule check" hook in
the IP input/output stream. They are declared:
int iplattach __P((void));
int ipldetach __P((void));
..and are expected to return a value by iplioctl().
- When main() calls (by sheer coincidence!) iplattach(),
the filter hook is established, and the IP Filter machinery
labeled as "initialized". This causes all packets, whether or
not the user intents to use filter rules, to be passed to
the filter rule checker if "ipfilter" is configured into the
kernel.
- As a result of the above, a kludge existed to default to
passing all packets (I can only assume that when this was
originally committed, the symptom of the bug was noticed by
the integrator, but the bug not actually found/fixed).
- In iplioctl(), if the SIOCFRENB ioctl is issued with an
argument of "enable" (i.e. user executed "ipf -E"), iplattach()
will notice that the machinery is already initialized and
return EBUSY.
Fix:
- Rename iplattach()/ipldetach() to ipl_enable() and ipl_disable().
- Create a pseudo-device entry stub named ipfilterattach()
(NetBSD case) or iplattach() (all other). This is a noop; none
of the machinery should be initialized until the caller expicitly
enables the filter with ipf -E. Add a comment to note that.
1997-03-29 04:57:55 +03:00
|
|
|
/*
|
1997-07-06 09:13:00 +04:00
|
|
|
* BSD pseudo-device attach routine; this is a no-op.
|
Fix an ... interesting bug that resulted from namespace collision.
Description:
- A BSD pseudo-device initialization routine is declared as
void <pseudo-device name>attach __P((int count));
in ioconf.c by config(8). main() calls these functions
from a table.
- IP Filter has functions iplattach() and ipldetach() (or,
in the NetBSD case, were erroneously renamed ipfilterattach()
and ipfilterdetach()). These functions are used to establish
and disestablish the IP Filter "filter rule check" hook in
the IP input/output stream. They are declared:
int iplattach __P((void));
int ipldetach __P((void));
..and are expected to return a value by iplioctl().
- When main() calls (by sheer coincidence!) iplattach(),
the filter hook is established, and the IP Filter machinery
labeled as "initialized". This causes all packets, whether or
not the user intents to use filter rules, to be passed to
the filter rule checker if "ipfilter" is configured into the
kernel.
- As a result of the above, a kludge existed to default to
passing all packets (I can only assume that when this was
originally committed, the symptom of the bug was noticed by
the integrator, but the bug not actually found/fixed).
- In iplioctl(), if the SIOCFRENB ioctl is issued with an
argument of "enable" (i.e. user executed "ipf -E"), iplattach()
will notice that the machinery is already initialized and
return EBUSY.
Fix:
- Rename iplattach()/ipldetach() to ipl_enable() and ipl_disable().
- Create a pseudo-device entry stub named ipfilterattach()
(NetBSD case) or iplattach() (all other). This is a noop; none
of the machinery should be initialized until the caller expicitly
enables the filter with ipf -E. Add a comment to note that.
1997-03-29 04:57:55 +03:00
|
|
|
*/
|
1997-07-06 09:13:00 +04:00
|
|
|
/* ARGSUSED */
|
|
|
|
# if defined(__NetBSD__)
|
Fix an ... interesting bug that resulted from namespace collision.
Description:
- A BSD pseudo-device initialization routine is declared as
void <pseudo-device name>attach __P((int count));
in ioconf.c by config(8). main() calls these functions
from a table.
- IP Filter has functions iplattach() and ipldetach() (or,
in the NetBSD case, were erroneously renamed ipfilterattach()
and ipfilterdetach()). These functions are used to establish
and disestablish the IP Filter "filter rule check" hook in
the IP input/output stream. They are declared:
int iplattach __P((void));
int ipldetach __P((void));
..and are expected to return a value by iplioctl().
- When main() calls (by sheer coincidence!) iplattach(),
the filter hook is established, and the IP Filter machinery
labeled as "initialized". This causes all packets, whether or
not the user intents to use filter rules, to be passed to
the filter rule checker if "ipfilter" is configured into the
kernel.
- As a result of the above, a kludge existed to default to
passing all packets (I can only assume that when this was
originally committed, the symptom of the bug was noticed by
the integrator, but the bug not actually found/fixed).
- In iplioctl(), if the SIOCFRENB ioctl is issued with an
argument of "enable" (i.e. user executed "ipf -E"), iplattach()
will notice that the machinery is already initialized and
return EBUSY.
Fix:
- Rename iplattach()/ipldetach() to ipl_enable() and ipl_disable().
- Create a pseudo-device entry stub named ipfilterattach()
(NetBSD case) or iplattach() (all other). This is a noop; none
of the machinery should be initialized until the caller expicitly
enables the filter with ipf -E. Add a comment to note that.
1997-03-29 04:57:55 +03:00
|
|
|
void
|
|
|
|
ipfilterattach(count)
|
1997-07-06 09:13:00 +04:00
|
|
|
# else
|
|
|
|
void
|
|
|
|
iplattach(count)
|
|
|
|
# endif /* __NetBSD__ */
|
|
|
|
int count;
|
1997-05-27 05:15:21 +04:00
|
|
|
{
|
|
|
|
|
1997-07-06 09:13:00 +04:00
|
|
|
/*
|
|
|
|
* Do nothing here, really. The filter will be enabled
|
|
|
|
* by the SIOCFRENB ioctl.
|
|
|
|
*/
|
|
|
|
}
|
1997-05-27 05:15:21 +04:00
|
|
|
|
1997-07-06 09:13:00 +04:00
|
|
|
int ipl_enable()
|
Fix an ... interesting bug that resulted from namespace collision.
Description:
- A BSD pseudo-device initialization routine is declared as
void <pseudo-device name>attach __P((int count));
in ioconf.c by config(8). main() calls these functions
from a table.
- IP Filter has functions iplattach() and ipldetach() (or,
in the NetBSD case, were erroneously renamed ipfilterattach()
and ipfilterdetach()). These functions are used to establish
and disestablish the IP Filter "filter rule check" hook in
the IP input/output stream. They are declared:
int iplattach __P((void));
int ipldetach __P((void));
..and are expected to return a value by iplioctl().
- When main() calls (by sheer coincidence!) iplattach(),
the filter hook is established, and the IP Filter machinery
labeled as "initialized". This causes all packets, whether or
not the user intents to use filter rules, to be passed to
the filter rule checker if "ipfilter" is configured into the
kernel.
- As a result of the above, a kludge existed to default to
passing all packets (I can only assume that when this was
originally committed, the symptom of the bug was noticed by
the integrator, but the bug not actually found/fixed).
- In iplioctl(), if the SIOCFRENB ioctl is issued with an
argument of "enable" (i.e. user executed "ipf -E"), iplattach()
will notice that the machinery is already initialized and
return EBUSY.
Fix:
- Rename iplattach()/ipldetach() to ipl_enable() and ipl_disable().
- Create a pseudo-device entry stub named ipfilterattach()
(NetBSD case) or iplattach() (all other). This is a noop; none
of the machinery should be initialized until the caller expicitly
enables the filter with ipf -E. Add a comment to note that.
1997-03-29 04:57:55 +03:00
|
|
|
{
|
1997-05-25 16:40:11 +04:00
|
|
|
char *defpass;
|
1997-05-27 05:15:21 +04:00
|
|
|
int s;
|
1997-07-05 09:38:14 +04:00
|
|
|
# ifdef IPFILTER_LOG
|
1997-05-27 05:15:21 +04:00
|
|
|
int i;
|
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
|
|
|
|
SPLNET(s);
|
|
|
|
if (ipl_inited || (fr_checkp == fr_check)) {
|
1997-03-29 03:54:55 +03:00
|
|
|
printf("IP Filter: already initialized\n");
|
1997-01-05 16:47:59 +03:00
|
|
|
SPLX(s);
|
|
|
|
return EBUSY;
|
|
|
|
}
|
Fix an ... interesting bug that resulted from namespace collision.
Description:
- A BSD pseudo-device initialization routine is declared as
void <pseudo-device name>attach __P((int count));
in ioconf.c by config(8). main() calls these functions
from a table.
- IP Filter has functions iplattach() and ipldetach() (or,
in the NetBSD case, were erroneously renamed ipfilterattach()
and ipfilterdetach()). These functions are used to establish
and disestablish the IP Filter "filter rule check" hook in
the IP input/output stream. They are declared:
int iplattach __P((void));
int ipldetach __P((void));
..and are expected to return a value by iplioctl().
- When main() calls (by sheer coincidence!) iplattach(),
the filter hook is established, and the IP Filter machinery
labeled as "initialized". This causes all packets, whether or
not the user intents to use filter rules, to be passed to
the filter rule checker if "ipfilter" is configured into the
kernel.
- As a result of the above, a kludge existed to default to
passing all packets (I can only assume that when this was
originally committed, the symptom of the bug was noticed by
the integrator, but the bug not actually found/fixed).
- In iplioctl(), if the SIOCFRENB ioctl is issued with an
argument of "enable" (i.e. user executed "ipf -E"), iplattach()
will notice that the machinery is already initialized and
return EBUSY.
Fix:
- Rename iplattach()/ipldetach() to ipl_enable() and ipl_disable().
- Create a pseudo-device entry stub named ipfilterattach()
(NetBSD case) or iplattach() (all other). This is a noop; none
of the machinery should be initialized until the caller expicitly
enables the filter with ipf -E. Add a comment to note that.
1997-03-29 04:57:55 +03:00
|
|
|
|
1997-04-15 04:44:42 +04:00
|
|
|
# ifdef NETBSD_PF
|
1997-01-05 16:47:59 +03:00
|
|
|
pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT);
|
1997-04-15 04:44:42 +04:00
|
|
|
# endif
|
1997-03-29 03:54:55 +03:00
|
|
|
|
1997-01-05 16:47:59 +03:00
|
|
|
ipl_inited = 1;
|
1997-03-29 03:54:55 +03:00
|
|
|
bzero((char *)nat_table, sizeof(nat_t *) * NAT_SIZE * 2);
|
1997-01-05 16:47:59 +03:00
|
|
|
fr_savep = fr_checkp;
|
|
|
|
fr_checkp = fr_check;
|
|
|
|
fr_saveslowtimo = inetsw[0].pr_slowtimo;
|
|
|
|
inetsw[0].pr_slowtimo = ipfr_slowtimer;
|
1997-03-29 03:54:55 +03:00
|
|
|
|
1997-07-05 09:38:14 +04:00
|
|
|
# ifdef IPFILTER_LOG
|
1997-03-29 03:54:55 +03:00
|
|
|
/*
|
|
|
|
* Set log buffer pointers for each of the log buffers
|
|
|
|
*/
|
|
|
|
for (i = 0; i <= 2; i++) {
|
|
|
|
iplh[i] = iplbuf[i];
|
|
|
|
iplt[i] = iplbuf[i];
|
|
|
|
}
|
1997-07-05 09:38:14 +04:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
SPLX(s);
|
1997-05-25 16:40:11 +04:00
|
|
|
if (fr_pass & FR_PASS)
|
|
|
|
defpass = "pass";
|
|
|
|
else if (fr_pass & FR_BLOCK)
|
|
|
|
defpass = "block";
|
|
|
|
else
|
|
|
|
defpass = "no-match -> block";
|
|
|
|
|
|
|
|
printf("IP Filter: initialized. Default = %s all\n", defpass);
|
1997-01-05 16:47:59 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Fix an ... interesting bug that resulted from namespace collision.
Description:
- A BSD pseudo-device initialization routine is declared as
void <pseudo-device name>attach __P((int count));
in ioconf.c by config(8). main() calls these functions
from a table.
- IP Filter has functions iplattach() and ipldetach() (or,
in the NetBSD case, were erroneously renamed ipfilterattach()
and ipfilterdetach()). These functions are used to establish
and disestablish the IP Filter "filter rule check" hook in
the IP input/output stream. They are declared:
int iplattach __P((void));
int ipldetach __P((void));
..and are expected to return a value by iplioctl().
- When main() calls (by sheer coincidence!) iplattach(),
the filter hook is established, and the IP Filter machinery
labeled as "initialized". This causes all packets, whether or
not the user intents to use filter rules, to be passed to
the filter rule checker if "ipfilter" is configured into the
kernel.
- As a result of the above, a kludge existed to default to
passing all packets (I can only assume that when this was
originally committed, the symptom of the bug was noticed by
the integrator, but the bug not actually found/fixed).
- In iplioctl(), if the SIOCFRENB ioctl is issued with an
argument of "enable" (i.e. user executed "ipf -E"), iplattach()
will notice that the machinery is already initialized and
return EBUSY.
Fix:
- Rename iplattach()/ipldetach() to ipl_enable() and ipl_disable().
- Create a pseudo-device entry stub named ipfilterattach()
(NetBSD case) or iplattach() (all other). This is a noop; none
of the machinery should be initialized until the caller expicitly
enables the filter with ipf -E. Add a comment to note that.
1997-03-29 04:57:55 +03:00
|
|
|
/*
|
|
|
|
* Disable the filter by removing the hooks from the IP input/output
|
|
|
|
* stream.
|
|
|
|
*/
|
1997-07-06 09:13:00 +04:00
|
|
|
int ipl_disable()
|
1997-01-05 16:47:59 +03:00
|
|
|
{
|
|
|
|
int s, i = FR_INQUE|FR_OUTQUE;
|
|
|
|
|
|
|
|
SPLNET(s);
|
|
|
|
if (!ipl_inited)
|
|
|
|
{
|
1997-03-29 03:54:55 +03:00
|
|
|
printf("IP Filter: not initialized\n");
|
1997-01-05 16:47:59 +03:00
|
|
|
SPLX(s);
|
|
|
|
return EBUSY;
|
|
|
|
}
|
|
|
|
|
|
|
|
fr_checkp = fr_savep;
|
|
|
|
inetsw[0].pr_slowtimo = fr_saveslowtimo;
|
|
|
|
frflush((caddr_t)&i);
|
|
|
|
ipl_inited = 0;
|
|
|
|
|
1997-04-15 04:44:42 +04:00
|
|
|
# ifdef NETBSD_PF
|
1997-01-05 16:47:59 +03:00
|
|
|
pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT);
|
1997-04-15 04:44:42 +04:00
|
|
|
# endif
|
1997-03-29 03:54:55 +03:00
|
|
|
|
1997-01-05 16:47:59 +03:00
|
|
|
ipfr_unload();
|
|
|
|
ip_natunload();
|
|
|
|
fr_stateunload();
|
1997-07-05 09:38:14 +04:00
|
|
|
fr_authunload();
|
1997-01-05 16:47:59 +03:00
|
|
|
|
|
|
|
SPLX(s);
|
|
|
|
return 0;
|
|
|
|
}
|
1997-03-29 03:54:55 +03:00
|
|
|
#endif /* _KERNEL */
|
|
|
|
|
1997-01-05 16:47:59 +03:00
|
|
|
|
|
|
|
static void frzerostats(data)
|
|
|
|
caddr_t data;
|
|
|
|
{
|
|
|
|
struct friostat fio;
|
|
|
|
|
|
|
|
bcopy((char *)frstats, (char *)fio.f_st,
|
|
|
|
sizeof(struct filterstats) * 2);
|
|
|
|
fio.f_fin[0] = ipfilter[0][0];
|
|
|
|
fio.f_fin[1] = ipfilter[0][1];
|
|
|
|
fio.f_fout[0] = ipfilter[1][0];
|
|
|
|
fio.f_fout[1] = ipfilter[1][1];
|
|
|
|
fio.f_acctin[0] = ipacct[0][0];
|
|
|
|
fio.f_acctin[1] = ipacct[0][1];
|
|
|
|
fio.f_acctout[0] = ipacct[1][0];
|
|
|
|
fio.f_acctout[1] = ipacct[1][1];
|
|
|
|
fio.f_active = fr_active;
|
|
|
|
IWCOPY((caddr_t)&fio, data, sizeof(fio));
|
|
|
|
bzero((char *)frstats, sizeof(*frstats) * 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void frflush(data)
|
|
|
|
caddr_t data;
|
|
|
|
{
|
|
|
|
struct frentry *f, **fp;
|
|
|
|
int flags = *(int *)data, flushed = 0, set = fr_active;
|
|
|
|
|
|
|
|
bzero((char *)frcache, sizeof(frcache[0]) * 2);
|
|
|
|
|
|
|
|
if (flags & FR_INACTIVE)
|
|
|
|
set = 1 - set;
|
|
|
|
if (flags & FR_OUTQUE) {
|
|
|
|
for (fp = &ipfilter[1][set]; (f = *fp); ) {
|
|
|
|
*fp = f->fr_next;
|
|
|
|
KFREE(f);
|
|
|
|
flushed++;
|
|
|
|
}
|
|
|
|
for (fp = &ipacct[1][set]; (f = *fp); ) {
|
|
|
|
*fp = f->fr_next;
|
|
|
|
KFREE(f);
|
|
|
|
flushed++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (flags & FR_INQUE) {
|
|
|
|
for (fp = &ipfilter[0][set]; (f = *fp); ) {
|
|
|
|
*fp = f->fr_next;
|
|
|
|
KFREE(f);
|
|
|
|
flushed++;
|
|
|
|
}
|
|
|
|
for (fp = &ipacct[0][set]; (f = *fp); ) {
|
|
|
|
*fp = f->fr_next;
|
|
|
|
KFREE(f);
|
|
|
|
flushed++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*(int *)data = flushed;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Filter ioctl interface.
|
|
|
|
*/
|
|
|
|
int iplioctl(dev, cmd, data, mode
|
1997-05-25 16:40:11 +04:00
|
|
|
#if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \
|
|
|
|
(__FreeBSD_version >= 220000)) && defined(_KERNEL)
|
1997-01-05 16:47:59 +03:00
|
|
|
, p)
|
|
|
|
struct proc *p;
|
|
|
|
#else
|
|
|
|
)
|
|
|
|
#endif
|
|
|
|
dev_t dev;
|
1997-07-05 09:38:14 +04:00
|
|
|
#ifdef __NetBSD__
|
1997-01-05 16:47:59 +03:00
|
|
|
u_long cmd;
|
1997-03-29 03:54:55 +03:00
|
|
|
#else
|
|
|
|
int cmd;
|
|
|
|
#endif
|
1997-01-05 16:47:59 +03:00
|
|
|
caddr_t data;
|
|
|
|
int mode;
|
|
|
|
{
|
1997-07-05 09:38:14 +04:00
|
|
|
#if defined(_KERNEL) && !SOLARIS
|
|
|
|
int s;
|
|
|
|
#endif
|
|
|
|
int error = 0, unit;
|
1997-01-05 16:47:59 +03:00
|
|
|
|
1997-03-29 03:54:55 +03:00
|
|
|
#ifdef _KERNEL
|
1997-01-05 16:47:59 +03:00
|
|
|
unit = minor(dev);
|
1997-07-05 09:38:14 +04:00
|
|
|
if ((IPL_LOGMAX < unit) || (unit < 0))
|
1997-01-05 16:47:59 +03:00
|
|
|
return ENXIO;
|
1997-03-29 03:54:55 +03:00
|
|
|
#endif
|
1997-01-05 16:47:59 +03:00
|
|
|
|
|
|
|
SPLNET(s);
|
1997-05-25 16:40:11 +04:00
|
|
|
|
|
|
|
if (unit == IPL_LOGNAT) {
|
|
|
|
error = nat_ioctl(data, cmd, mode);
|
|
|
|
SPLX(s);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
if (unit == IPL_LOGSTATE) {
|
|
|
|
error = fr_state_ioctl(data, cmd, mode);
|
|
|
|
SPLX(s);
|
|
|
|
return error;
|
|
|
|
}
|
1997-01-05 16:47:59 +03:00
|
|
|
switch (cmd) {
|
|
|
|
case FIONREAD :
|
|
|
|
#ifdef IPFILTER_LOG
|
1997-05-25 16:40:11 +04:00
|
|
|
*(int *)data = iplused[IPL_LOGIPF];
|
1997-01-05 16:47:59 +03:00
|
|
|
#endif
|
|
|
|
break;
|
Fix an ... interesting bug that resulted from namespace collision.
Description:
- A BSD pseudo-device initialization routine is declared as
void <pseudo-device name>attach __P((int count));
in ioconf.c by config(8). main() calls these functions
from a table.
- IP Filter has functions iplattach() and ipldetach() (or,
in the NetBSD case, were erroneously renamed ipfilterattach()
and ipfilterdetach()). These functions are used to establish
and disestablish the IP Filter "filter rule check" hook in
the IP input/output stream. They are declared:
int iplattach __P((void));
int ipldetach __P((void));
..and are expected to return a value by iplioctl().
- When main() calls (by sheer coincidence!) iplattach(),
the filter hook is established, and the IP Filter machinery
labeled as "initialized". This causes all packets, whether or
not the user intents to use filter rules, to be passed to
the filter rule checker if "ipfilter" is configured into the
kernel.
- As a result of the above, a kludge existed to default to
passing all packets (I can only assume that when this was
originally committed, the symptom of the bug was noticed by
the integrator, but the bug not actually found/fixed).
- In iplioctl(), if the SIOCFRENB ioctl is issued with an
argument of "enable" (i.e. user executed "ipf -E"), iplattach()
will notice that the machinery is already initialized and
return EBUSY.
Fix:
- Rename iplattach()/ipldetach() to ipl_enable() and ipl_disable().
- Create a pseudo-device entry stub named ipfilterattach()
(NetBSD case) or iplattach() (all other). This is a noop; none
of the machinery should be initialized until the caller expicitly
enables the filter with ipf -E. Add a comment to note that.
1997-03-29 04:57:55 +03:00
|
|
|
#if defined(_KERNEL)
|
1997-01-05 16:47:59 +03:00
|
|
|
case SIOCFRENB :
|
|
|
|
{
|
|
|
|
u_int enable;
|
|
|
|
|
|
|
|
if (!(mode & FWRITE))
|
|
|
|
error = EPERM;
|
|
|
|
else {
|
|
|
|
IRCOPY(data, (caddr_t)&enable, sizeof(enable));
|
1997-03-29 03:54:55 +03:00
|
|
|
if (enable)
|
Fix an ... interesting bug that resulted from namespace collision.
Description:
- A BSD pseudo-device initialization routine is declared as
void <pseudo-device name>attach __P((int count));
in ioconf.c by config(8). main() calls these functions
from a table.
- IP Filter has functions iplattach() and ipldetach() (or,
in the NetBSD case, were erroneously renamed ipfilterattach()
and ipfilterdetach()). These functions are used to establish
and disestablish the IP Filter "filter rule check" hook in
the IP input/output stream. They are declared:
int iplattach __P((void));
int ipldetach __P((void));
..and are expected to return a value by iplioctl().
- When main() calls (by sheer coincidence!) iplattach(),
the filter hook is established, and the IP Filter machinery
labeled as "initialized". This causes all packets, whether or
not the user intents to use filter rules, to be passed to
the filter rule checker if "ipfilter" is configured into the
kernel.
- As a result of the above, a kludge existed to default to
passing all packets (I can only assume that when this was
originally committed, the symptom of the bug was noticed by
the integrator, but the bug not actually found/fixed).
- In iplioctl(), if the SIOCFRENB ioctl is issued with an
argument of "enable" (i.e. user executed "ipf -E"), iplattach()
will notice that the machinery is already initialized and
return EBUSY.
Fix:
- Rename iplattach()/ipldetach() to ipl_enable() and ipl_disable().
- Create a pseudo-device entry stub named ipfilterattach()
(NetBSD case) or iplattach() (all other). This is a noop; none
of the machinery should be initialized until the caller expicitly
enables the filter with ipf -E. Add a comment to note that.
1997-03-29 04:57:55 +03:00
|
|
|
error = ipl_enable();
|
1997-03-29 03:54:55 +03:00
|
|
|
else
|
Fix an ... interesting bug that resulted from namespace collision.
Description:
- A BSD pseudo-device initialization routine is declared as
void <pseudo-device name>attach __P((int count));
in ioconf.c by config(8). main() calls these functions
from a table.
- IP Filter has functions iplattach() and ipldetach() (or,
in the NetBSD case, were erroneously renamed ipfilterattach()
and ipfilterdetach()). These functions are used to establish
and disestablish the IP Filter "filter rule check" hook in
the IP input/output stream. They are declared:
int iplattach __P((void));
int ipldetach __P((void));
..and are expected to return a value by iplioctl().
- When main() calls (by sheer coincidence!) iplattach(),
the filter hook is established, and the IP Filter machinery
labeled as "initialized". This causes all packets, whether or
not the user intents to use filter rules, to be passed to
the filter rule checker if "ipfilter" is configured into the
kernel.
- As a result of the above, a kludge existed to default to
passing all packets (I can only assume that when this was
originally committed, the symptom of the bug was noticed by
the integrator, but the bug not actually found/fixed).
- In iplioctl(), if the SIOCFRENB ioctl is issued with an
argument of "enable" (i.e. user executed "ipf -E"), iplattach()
will notice that the machinery is already initialized and
return EBUSY.
Fix:
- Rename iplattach()/ipldetach() to ipl_enable() and ipl_disable().
- Create a pseudo-device entry stub named ipfilterattach()
(NetBSD case) or iplattach() (all other). This is a noop; none
of the machinery should be initialized until the caller expicitly
enables the filter with ipf -E. Add a comment to note that.
1997-03-29 04:57:55 +03:00
|
|
|
error = ipl_disable();
|
1997-01-05 16:47:59 +03:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
case SIOCSETFF :
|
|
|
|
if (!(mode & FWRITE))
|
|
|
|
error = EPERM;
|
|
|
|
else
|
|
|
|
IRCOPY(data, (caddr_t)&fr_flags, sizeof(fr_flags));
|
|
|
|
break;
|
|
|
|
case SIOCGETFF :
|
|
|
|
IWCOPY((caddr_t)&fr_flags, data, sizeof(fr_flags));
|
|
|
|
break;
|
|
|
|
case SIOCINAFR :
|
|
|
|
case SIOCRMAFR :
|
|
|
|
case SIOCADAFR :
|
|
|
|
case SIOCZRLST :
|
|
|
|
if (!(mode & FWRITE))
|
|
|
|
error = EPERM;
|
|
|
|
else
|
1997-07-05 09:38:14 +04:00
|
|
|
error = frrequest(unit, cmd, data, fr_active);
|
1997-01-05 16:47:59 +03:00
|
|
|
break;
|
|
|
|
case SIOCINIFR :
|
|
|
|
case SIOCRMIFR :
|
|
|
|
case SIOCADIFR :
|
|
|
|
if (!(mode & FWRITE))
|
|
|
|
error = EPERM;
|
|
|
|
else
|
1997-07-05 09:38:14 +04:00
|
|
|
error = frrequest(unit, cmd, data, 1 - fr_active);
|
1997-01-05 16:47:59 +03:00
|
|
|
break;
|
|
|
|
case SIOCSWAPA :
|
|
|
|
if (!(mode & FWRITE))
|
|
|
|
error = EPERM;
|
|
|
|
else {
|
|
|
|
bzero((char *)frcache, sizeof(frcache[0]) * 2);
|
|
|
|
*(u_int *)data = fr_active;
|
|
|
|
fr_active = 1 - fr_active;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SIOCGETFS :
|
|
|
|
{
|
|
|
|
struct friostat fio;
|
|
|
|
|
|
|
|
bcopy((char *)frstats, (char *)fio.f_st,
|
|
|
|
sizeof(struct filterstats) * 2);
|
|
|
|
fio.f_fin[0] = ipfilter[0][0];
|
|
|
|
fio.f_fin[1] = ipfilter[0][1];
|
|
|
|
fio.f_fout[0] = ipfilter[1][0];
|
|
|
|
fio.f_fout[1] = ipfilter[1][1];
|
|
|
|
fio.f_acctin[0] = ipacct[0][0];
|
|
|
|
fio.f_acctin[1] = ipacct[0][1];
|
|
|
|
fio.f_acctout[0] = ipacct[1][0];
|
|
|
|
fio.f_acctout[1] = ipacct[1][1];
|
1997-07-05 09:38:14 +04:00
|
|
|
fio.f_auth = ipauth;
|
1997-01-05 16:47:59 +03:00
|
|
|
fio.f_active = fr_active;
|
|
|
|
IWCOPY((caddr_t)&fio, data, sizeof(fio));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SIOCFRZST :
|
|
|
|
if (!(mode & FWRITE))
|
|
|
|
error = EPERM;
|
|
|
|
else
|
|
|
|
frzerostats(data);
|
|
|
|
break;
|
|
|
|
case SIOCIPFFL :
|
|
|
|
if (!(mode & FWRITE))
|
|
|
|
error = EPERM;
|
|
|
|
else
|
|
|
|
frflush(data);
|
|
|
|
break;
|
|
|
|
#ifdef IPFILTER_LOG
|
|
|
|
case SIOCIPFFB :
|
|
|
|
if (!(mode & FWRITE))
|
|
|
|
error = EPERM;
|
|
|
|
else {
|
1997-03-29 03:54:55 +03:00
|
|
|
*(int *)data = iplused[unit];
|
|
|
|
iplh[unit] = iplt[unit] = iplbuf[unit];
|
1997-04-03 04:57:03 +04:00
|
|
|
iplused[unit] = 0;
|
1997-01-05 16:47:59 +03:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif /* IPFILTER_LOG */
|
|
|
|
case SIOCGFRST :
|
|
|
|
IWCOPY((caddr_t)ipfr_fragstats(), data, sizeof(ipfrstat_t));
|
|
|
|
break;
|
1997-07-05 09:38:14 +04:00
|
|
|
case SIOCAUTHW:
|
|
|
|
case SIOCAUTHR:
|
|
|
|
if (!(mode & FWRITE)) {
|
|
|
|
error = EPERM;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SIOCATHST:
|
|
|
|
error = fr_auth_ioctl(data, cmd, NULL, NULL);
|
|
|
|
break;
|
1997-01-05 16:47:59 +03:00
|
|
|
default :
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
SPLX(s);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
1997-07-05 09:38:14 +04:00
|
|
|
static void fixskip(listp, rp, addremove)
|
|
|
|
frentry_t **listp, *rp;
|
|
|
|
int addremove;
|
|
|
|
{
|
|
|
|
frentry_t *fp;
|
|
|
|
int rules = 0, rn = 0;
|
|
|
|
|
|
|
|
for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rules++)
|
|
|
|
;
|
|
|
|
|
|
|
|
if (!fp)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rn++)
|
|
|
|
if (fp->fr_skip && (rn + fp->fr_skip >= rules))
|
|
|
|
fp->fr_skip += addremove;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int frrequest(unit, req, data, set)
|
|
|
|
int unit;
|
|
|
|
#ifdef __NetBSD__
|
1997-03-18 10:14:45 +03:00
|
|
|
u_long req;
|
1997-05-28 04:17:11 +04:00
|
|
|
#else
|
|
|
|
int req;
|
|
|
|
#endif
|
1997-03-18 10:14:45 +03:00
|
|
|
int set;
|
1997-01-05 16:47:59 +03:00
|
|
|
caddr_t data;
|
|
|
|
{
|
|
|
|
register frentry_t *fp, *f, **fprev;
|
|
|
|
register frentry_t **ftail;
|
1997-03-29 03:54:55 +03:00
|
|
|
frentry_t frd;
|
1997-01-05 16:47:59 +03:00
|
|
|
frdest_t *fdp;
|
|
|
|
int error = 0, in;
|
|
|
|
|
1997-03-29 03:54:55 +03:00
|
|
|
fp = &frd;
|
1997-01-05 16:47:59 +03:00
|
|
|
IRCOPY(data, (caddr_t)fp, sizeof(*fp));
|
|
|
|
|
|
|
|
in = (fp->fr_flags & FR_INQUE) ? 0 : 1;
|
1997-07-05 09:38:14 +04:00
|
|
|
if (unit == IPL_LOGAUTH)
|
|
|
|
ftail = fprev = &ipauth;
|
|
|
|
else if (fp->fr_flags & FR_ACCOUNT)
|
1997-01-05 16:47:59 +03:00
|
|
|
ftail = fprev = &ipacct[in][set];
|
1997-07-05 09:38:14 +04:00
|
|
|
else if (fp->fr_flags & (FR_OUTQUE|FR_INQUE))
|
1997-01-05 16:47:59 +03:00
|
|
|
ftail = fprev = &ipfilter[in][set];
|
|
|
|
else
|
|
|
|
return ESRCH;
|
|
|
|
|
1997-03-29 03:54:55 +03:00
|
|
|
bzero((char *)frcache, sizeof(frcache[0]) * 2);
|
|
|
|
|
1997-01-05 16:47:59 +03:00
|
|
|
if (*fp->fr_ifname) {
|
|
|
|
fp->fr_ifa = GETUNIT(fp->fr_ifname);
|
|
|
|
if (!fp->fr_ifa)
|
|
|
|
fp->fr_ifa = (struct ifnet *)-1;
|
|
|
|
}
|
|
|
|
|
|
|
|
fdp = &fp->fr_dif;
|
|
|
|
fp->fr_flags &= ~FR_DUP;
|
|
|
|
if (*fdp->fd_ifname) {
|
|
|
|
fdp->fd_ifp = GETUNIT(fdp->fd_ifname);
|
|
|
|
if (!fdp->fd_ifp)
|
|
|
|
fdp->fd_ifp = (struct ifnet *)-1;
|
|
|
|
else
|
|
|
|
fp->fr_flags |= FR_DUP;
|
|
|
|
}
|
|
|
|
|
|
|
|
fdp = &fp->fr_tif;
|
|
|
|
if (*fdp->fd_ifname) {
|
|
|
|
fdp->fd_ifp = GETUNIT(fdp->fd_ifname);
|
|
|
|
if (!fdp->fd_ifp)
|
|
|
|
fdp->fd_ifp = (struct ifnet *)-1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Look for a matching filter rule, but don't include the next or
|
|
|
|
* interface pointer in the comparison (fr_next, fr_ifa).
|
|
|
|
*/
|
|
|
|
for (; (f = *ftail); ftail = &f->fr_next)
|
|
|
|
if (bcmp((char *)&f->fr_ip, (char *)&fp->fr_ip,
|
|
|
|
FR_CMPSIZ) == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If zero'ing statistics, copy current to caller and zero.
|
|
|
|
*/
|
|
|
|
if (req == SIOCZRLST) {
|
|
|
|
if (!f)
|
|
|
|
return ESRCH;
|
|
|
|
IWCOPY((caddr_t)f, data, sizeof(*f));
|
|
|
|
f->fr_hits = 0;
|
|
|
|
f->fr_bytes = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!f) {
|
|
|
|
ftail = fprev;
|
|
|
|
if (req != SIOCINAFR && req != SIOCINIFR)
|
|
|
|
while ((f = *ftail))
|
|
|
|
ftail = &f->fr_next;
|
|
|
|
else if (fp->fr_hits)
|
|
|
|
while (--fp->fr_hits && (f = *ftail))
|
|
|
|
ftail = &f->fr_next;
|
|
|
|
f = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (req == SIOCDELFR || req == SIOCRMIFR) {
|
|
|
|
if (!f)
|
|
|
|
error = ESRCH;
|
|
|
|
else {
|
1997-07-05 09:38:14 +04:00
|
|
|
if (unit == IPL_LOGAUTH)
|
|
|
|
return fr_auth_ioctl(data, req, f, ftail);
|
|
|
|
fixskip(fprev, f, -1);
|
1997-01-05 16:47:59 +03:00
|
|
|
*ftail = f->fr_next;
|
1997-04-01 04:07:07 +04:00
|
|
|
KFREE(f);
|
1997-01-05 16:47:59 +03:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (f)
|
|
|
|
error = EEXIST;
|
|
|
|
else {
|
1997-07-05 09:38:14 +04:00
|
|
|
if (unit == IPL_LOGAUTH)
|
|
|
|
return fr_auth_ioctl(data, req, f, ftail);
|
1997-03-29 03:54:55 +03:00
|
|
|
KMALLOC(f, frentry_t *, sizeof(*f));
|
|
|
|
if (f != NULL) {
|
1997-01-05 16:47:59 +03:00
|
|
|
bcopy((char *)fp, (char *)f, sizeof(*f));
|
|
|
|
f->fr_hits = 0;
|
|
|
|
f->fr_next = *ftail;
|
|
|
|
*ftail = f;
|
1997-07-05 09:38:14 +04:00
|
|
|
if (req == SIOCINIFR || req == SIOCINAFR)
|
|
|
|
fixskip(fprev, f, 1);
|
1997-01-05 16:47:59 +03:00
|
|
|
} else
|
|
|
|
error = ENOMEM;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1997-03-29 03:54:55 +03:00
|
|
|
#ifdef _KERNEL
|
1997-01-05 16:47:59 +03:00
|
|
|
/*
|
|
|
|
* routines below for saving IP headers to buffer
|
|
|
|
*/
|
|
|
|
int iplopen(dev, flags
|
1997-07-05 09:38:14 +04:00
|
|
|
# if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \
|
1997-05-25 16:40:11 +04:00
|
|
|
(__FreeBSD_version >= 220000)) && defined(_KERNEL)
|
1997-01-05 16:47:59 +03:00
|
|
|
, devtype, p)
|
|
|
|
int devtype;
|
|
|
|
struct proc *p;
|
1997-03-29 03:54:55 +03:00
|
|
|
# else
|
1997-01-05 16:47:59 +03:00
|
|
|
)
|
1997-03-29 03:54:55 +03:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
dev_t dev;
|
|
|
|
int flags;
|
|
|
|
{
|
|
|
|
u_int min = minor(dev);
|
|
|
|
|
1997-05-25 16:40:11 +04:00
|
|
|
if (2 < min)
|
1997-01-05 16:47:59 +03:00
|
|
|
min = ENXIO;
|
1997-03-29 03:54:55 +03:00
|
|
|
else
|
|
|
|
min = 0;
|
1997-01-05 16:47:59 +03:00
|
|
|
return min;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int iplclose(dev, flags
|
1997-07-05 09:38:14 +04:00
|
|
|
# if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \
|
1997-05-25 16:40:11 +04:00
|
|
|
(__FreeBSD_version >= 220000)) && defined(_KERNEL)
|
1997-01-05 16:47:59 +03:00
|
|
|
, devtype, p)
|
|
|
|
int devtype;
|
|
|
|
struct proc *p;
|
1997-03-29 03:54:55 +03:00
|
|
|
# else
|
1997-01-05 16:47:59 +03:00
|
|
|
)
|
1997-03-29 03:54:55 +03:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
dev_t dev;
|
|
|
|
int flags;
|
|
|
|
{
|
|
|
|
u_int min = minor(dev);
|
|
|
|
|
1997-05-25 16:40:11 +04:00
|
|
|
if (2 < min)
|
1997-01-05 16:47:59 +03:00
|
|
|
min = ENXIO;
|
1997-03-29 03:54:55 +03:00
|
|
|
else
|
|
|
|
min = 0;
|
1997-01-05 16:47:59 +03:00
|
|
|
return min;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* iplread/ipllog
|
|
|
|
* both of these must operate with at least splnet() lest they be
|
|
|
|
* called during packet processing and cause an inconsistancy to appear in
|
|
|
|
* the filter lists.
|
|
|
|
*/
|
1997-05-28 04:17:11 +04:00
|
|
|
# if BSD >= 199306
|
1997-01-05 16:47:59 +03:00
|
|
|
int iplread(dev, uio, ioflag)
|
|
|
|
int ioflag;
|
1997-05-28 04:17:11 +04:00
|
|
|
# else
|
1997-01-05 16:47:59 +03:00
|
|
|
int iplread(dev, uio)
|
1997-05-28 04:17:11 +04:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
dev_t dev;
|
|
|
|
register struct uio *uio;
|
|
|
|
{
|
1997-07-05 09:38:14 +04:00
|
|
|
# ifdef IPFILTER_LOG
|
|
|
|
register int ret, unit;
|
1997-01-05 16:47:59 +03:00
|
|
|
register size_t sz, sx;
|
|
|
|
int error;
|
1997-07-05 09:38:14 +04:00
|
|
|
# if defined(_KERNEL) && !SOLARIS
|
|
|
|
int s;
|
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
|
1997-03-29 03:54:55 +03:00
|
|
|
unit = minor(dev);
|
1997-05-25 16:40:11 +04:00
|
|
|
if ((2 < unit) || (unit < 0))
|
1997-03-29 03:54:55 +03:00
|
|
|
return ENXIO;
|
|
|
|
|
1997-01-05 16:47:59 +03:00
|
|
|
if (!uio->uio_resid)
|
|
|
|
return 0;
|
1997-03-29 03:54:55 +03:00
|
|
|
|
|
|
|
while (!iplused[unit]) {
|
1997-05-25 16:40:11 +04:00
|
|
|
error = SLEEP(iplbuf[unit], "ipl sleep");
|
1997-01-05 16:47:59 +03:00
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
SPLNET(s);
|
|
|
|
|
1997-03-29 03:54:55 +03:00
|
|
|
sx = sz = MIN(uio->uio_resid, iplused[unit]);
|
|
|
|
if (iplh[unit] < iplt[unit])
|
1997-05-25 16:40:11 +04:00
|
|
|
sz = MIN(sz, IPLLOGSIZE - (iplt[unit] - iplbuf[unit]));
|
1997-01-05 16:47:59 +03:00
|
|
|
sx -= sz;
|
|
|
|
|
|
|
|
# if BSD >= 199306 || defined(__FreeBSD__)
|
|
|
|
uio->uio_rw = UIO_READ;
|
|
|
|
# endif
|
1997-03-29 03:54:55 +03:00
|
|
|
if (!(ret = UIOMOVE(iplt[unit], sz, UIO_READ, uio))) {
|
|
|
|
iplt[unit] += sz;
|
|
|
|
iplused[unit] -= sz;
|
1997-05-25 16:40:11 +04:00
|
|
|
if ((iplh[unit] < iplt[unit]) && (iplt[unit] == iplbuf[unit] + IPLLOGSIZE))
|
1997-03-29 03:54:55 +03:00
|
|
|
iplt[unit] = iplbuf[unit];
|
|
|
|
|
|
|
|
if (sx && !(ret = UIOMOVE(iplt[unit], sx, UIO_READ, uio))) {
|
|
|
|
iplt[unit] += sx;
|
|
|
|
iplused[unit] -= sx;
|
1997-05-25 16:40:11 +04:00
|
|
|
if ((iplh[unit] < iplt[unit]) && (iplt[unit] == iplbuf[unit] + IPLLOGSIZE))
|
1997-03-29 03:54:55 +03:00
|
|
|
iplt[unit] = iplbuf[unit];
|
1997-01-05 16:47:59 +03:00
|
|
|
}
|
1997-03-29 03:54:55 +03:00
|
|
|
if (!iplused[unit]) /* minimise wrapping around the end */
|
|
|
|
iplh[unit] = iplt[unit] = iplbuf[unit];
|
1997-01-05 16:47:59 +03:00
|
|
|
}
|
|
|
|
SPLX(s);
|
|
|
|
return ret;
|
1997-07-05 09:38:14 +04:00
|
|
|
# else
|
1997-04-15 04:44:42 +04:00
|
|
|
return ENXIO;
|
1997-07-05 09:38:14 +04:00
|
|
|
# endif
|
1997-04-15 04:44:42 +04:00
|
|
|
}
|
1997-01-05 16:47:59 +03:00
|
|
|
|
|
|
|
|
1997-03-29 03:54:55 +03:00
|
|
|
# ifdef IPFILTER_LOG
|
|
|
|
int ipllog(flags, dev, ip, fin, m)
|
1997-01-05 16:47:59 +03:00
|
|
|
u_int flags;
|
1997-03-29 03:54:55 +03:00
|
|
|
int dev;
|
1997-01-05 16:47:59 +03:00
|
|
|
ip_t *ip;
|
|
|
|
register fr_info_t *fin;
|
|
|
|
struct mbuf *m;
|
|
|
|
{
|
|
|
|
struct ipl_ci iplci;
|
|
|
|
register int len, mlen, hlen;
|
|
|
|
struct ifnet *ifp = fin->fin_ifp;
|
|
|
|
|
|
|
|
hlen = fin->fin_hlen;
|
|
|
|
if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
|
|
|
|
hlen += MIN(sizeof(tcphdr_t), fin->fin_dlen);
|
|
|
|
else if (ip->ip_p == IPPROTO_ICMP) {
|
|
|
|
struct icmp *icmp = (struct icmp *)((char *)ip + hlen);
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mlen = (flags & FR_LOGBODY) ? MIN(ip->ip_len - hlen, 128) : 0;
|
|
|
|
len = hlen + sizeof(iplci) + mlen;
|
1997-05-25 16:40:11 +04:00
|
|
|
if (iplused[dev] + len > IPLLOGSIZE)
|
1997-01-05 16:47:59 +03:00
|
|
|
return 0;
|
1997-03-29 03:54:55 +03:00
|
|
|
iplused[dev] += len;
|
1997-01-05 16:47:59 +03:00
|
|
|
|
1997-03-29 03:54:55 +03:00
|
|
|
# ifdef sun
|
1997-01-05 16:47:59 +03:00
|
|
|
uniqtime(&iplci);
|
1997-03-29 03:54:55 +03:00
|
|
|
# endif
|
|
|
|
# if BSD >= 199306 || defined(__FreeBSD__)
|
1997-01-05 16:47:59 +03:00
|
|
|
microtime((struct timeval *)&iplci);
|
1997-03-29 03:54:55 +03:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
iplci.flags = flags;
|
|
|
|
iplci.hlen = (u_char)hlen;
|
|
|
|
iplci.plen = (u_char)mlen;
|
|
|
|
iplci.rule = fin->fin_rule;
|
1997-07-05 09:38:14 +04:00
|
|
|
# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603))
|
1997-01-05 16:47:59 +03:00
|
|
|
strncpy(iplci.ifname, ifp->if_xname, IFNAMSIZ);
|
1997-07-05 09:38:14 +04:00
|
|
|
# else
|
1997-01-05 16:47:59 +03:00
|
|
|
iplci.unit = (u_char)ifp->if_unit;
|
|
|
|
if ((iplci.ifname[0] = ifp->if_name[0]))
|
|
|
|
if ((iplci.ifname[1] = ifp->if_name[1]))
|
|
|
|
if ((iplci.ifname[2] = ifp->if_name[2]))
|
|
|
|
iplci.ifname[3] = ifp->if_name[3];
|
1997-03-29 03:54:55 +03:00
|
|
|
# endif
|
1997-05-25 16:40:11 +04:00
|
|
|
if (iplh[dev] == iplbuf[dev] + IPLLOGSIZE)
|
1997-03-29 03:54:55 +03:00
|
|
|
iplh[dev] = iplbuf[dev];
|
|
|
|
|
1997-01-05 16:47:59 +03:00
|
|
|
/*
|
|
|
|
* Gauranteed to succeed from above
|
|
|
|
*/
|
1997-03-29 03:54:55 +03:00
|
|
|
(void) fr_copytolog(dev, (char *)&iplci, sizeof(iplci));
|
1997-01-05 16:47:59 +03:00
|
|
|
|
|
|
|
for (len -= sizeof(iplci); m && len > 0; m = m->m_next, len -= hlen) {
|
|
|
|
hlen = MIN(len, m->m_len);
|
1997-03-29 03:54:55 +03:00
|
|
|
if (fr_copytolog(dev, mtod(m, char *), hlen))
|
1997-01-05 16:47:59 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
1997-03-29 03:54:55 +03:00
|
|
|
wakeup(iplbuf[dev]);
|
1997-01-05 16:47:59 +03:00
|
|
|
return 1;
|
|
|
|
}
|
1997-03-29 03:54:55 +03:00
|
|
|
# endif /* IPFILTER_LOG */
|
1997-01-05 16:47:59 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* send_reset - this could conceivably be a call to tcp_respond(), but that
|
|
|
|
* requires a large amount of setting up and isn't any more efficient.
|
|
|
|
*/
|
|
|
|
int send_reset(ti)
|
|
|
|
struct tcpiphdr *ti;
|
|
|
|
{
|
|
|
|
struct tcpiphdr *tp;
|
|
|
|
struct ip *ip;
|
|
|
|
struct tcphdr *tcp;
|
|
|
|
struct mbuf *m;
|
|
|
|
int tlen = 0;
|
1997-07-05 09:38:14 +04:00
|
|
|
# if defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)
|
1997-05-25 16:40:11 +04:00
|
|
|
struct route ro;
|
1997-07-05 09:38:14 +04:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
|
|
|
|
if (ti->ti_flags & TH_RST)
|
|
|
|
return -1; /* feedback loop */
|
1997-03-29 03:54:55 +03:00
|
|
|
# if BSD < 199306
|
1997-01-05 16:47:59 +03:00
|
|
|
m = m_get(M_DONTWAIT, MT_HEADER);
|
1997-03-29 03:54:55 +03:00
|
|
|
# else
|
1997-01-05 16:47:59 +03:00
|
|
|
m = m_gethdr(M_DONTWAIT, MT_HEADER);
|
|
|
|
m->m_data += max_linkhdr;
|
1997-03-29 03:54:55 +03:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
if (m == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (ti->ti_flags & TH_SYN)
|
|
|
|
tlen = 1;
|
|
|
|
m->m_len = sizeof (struct tcpiphdr);
|
1997-03-29 03:54:55 +03:00
|
|
|
# if BSD >= 199306
|
1997-01-05 16:47:59 +03:00
|
|
|
m->m_pkthdr.len = sizeof (struct tcpiphdr);
|
|
|
|
m->m_pkthdr.rcvif = (struct ifnet *)0;
|
1997-03-29 03:54:55 +03:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
bzero(mtod(m, char *), sizeof(struct tcpiphdr));
|
|
|
|
ip = mtod(m, struct ip *);
|
|
|
|
tp = mtod(m, struct tcpiphdr *);
|
|
|
|
tcp = (struct tcphdr *)((char *)ip + sizeof(struct ip));
|
|
|
|
|
|
|
|
ip->ip_src.s_addr = ti->ti_dst.s_addr;
|
|
|
|
ip->ip_dst.s_addr = ti->ti_src.s_addr;
|
|
|
|
tcp->th_dport = ti->ti_sport;
|
|
|
|
tcp->th_sport = ti->ti_dport;
|
|
|
|
tcp->th_ack = htonl(ntohl(ti->ti_seq) + tlen);
|
|
|
|
tcp->th_off = sizeof(struct tcphdr) >> 2;
|
|
|
|
tcp->th_flags = TH_RST|TH_ACK;
|
|
|
|
tp->ti_pr = ((struct ip *)ti)->ip_p;
|
|
|
|
tp->ti_len = htons(sizeof(struct tcphdr));
|
|
|
|
tcp->th_sum = in_cksum(m, sizeof(struct tcpiphdr));
|
|
|
|
|
|
|
|
ip->ip_tos = ((struct ip *)ti)->ip_tos;
|
|
|
|
ip->ip_p = ((struct ip *)ti)->ip_p;
|
|
|
|
ip->ip_len = sizeof (struct tcpiphdr);
|
1997-03-29 03:54:55 +03:00
|
|
|
# if BSD < 199306
|
1997-01-05 16:47:59 +03:00
|
|
|
ip->ip_ttl = tcp_ttl;
|
1997-03-29 03:54:55 +03:00
|
|
|
# else
|
1997-01-05 16:47:59 +03:00
|
|
|
ip->ip_ttl = ip_defttl;
|
1997-03-29 03:54:55 +03:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
|
1997-07-05 09:38:14 +04:00
|
|
|
# if defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)
|
1997-05-25 16:40:11 +04:00
|
|
|
bzero((char *)&ro, sizeof(ro));
|
|
|
|
(void) ip_output(m, (struct mbuf *)0, &ro, 0, 0);
|
|
|
|
if (ro.ro_rt)
|
|
|
|
RTFREE(ro.ro_rt);
|
1997-07-05 09:38:14 +04:00
|
|
|
# else
|
1997-01-05 16:47:59 +03:00
|
|
|
/*
|
|
|
|
* extra 0 in case of multicast
|
|
|
|
*/
|
|
|
|
(void) ip_output(m, (struct mbuf *)0, 0, 0, 0);
|
1997-07-05 09:38:14 +04:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1997-05-25 16:40:11 +04:00
|
|
|
# if !defined(IPFILTER_LKM) && !(__FreeBSD_version >= 300000)
|
|
|
|
# if BSD < 199306
|
|
|
|
int iplinit __P((void));
|
|
|
|
|
1997-03-29 03:54:55 +03:00
|
|
|
int
|
1997-05-25 16:40:11 +04:00
|
|
|
# else
|
|
|
|
void iplinit __P((void));
|
|
|
|
|
1997-03-29 03:54:55 +03:00
|
|
|
void
|
1997-05-25 16:40:11 +04:00
|
|
|
# endif
|
1997-03-29 03:54:55 +03:00
|
|
|
iplinit()
|
1997-01-05 16:47:59 +03:00
|
|
|
{
|
1997-05-27 05:15:21 +04:00
|
|
|
(void) ipl_enable();
|
1997-01-05 16:47:59 +03:00
|
|
|
ip_init();
|
|
|
|
}
|
1997-04-15 04:44:42 +04:00
|
|
|
# endif /* ! __NetBSD__ */
|
1997-03-29 03:54:55 +03:00
|
|
|
|
1997-01-05 16:47:59 +03:00
|
|
|
|
|
|
|
void ipfr_fastroute(m0, fin, fdp)
|
|
|
|
struct mbuf *m0;
|
|
|
|
fr_info_t *fin;
|
|
|
|
frdest_t *fdp;
|
|
|
|
{
|
|
|
|
register struct ip *ip, *mhip;
|
|
|
|
register struct mbuf *m = m0;
|
|
|
|
register struct route *ro;
|
|
|
|
struct ifnet *ifp = fdp->fd_ifp;
|
|
|
|
int len, off, error = 0;
|
|
|
|
int hlen = fin->fin_hlen;
|
|
|
|
struct route iproute;
|
|
|
|
struct sockaddr_in *dst;
|
|
|
|
|
|
|
|
ip = mtod(m0, struct ip *);
|
|
|
|
/*
|
|
|
|
* Route packet.
|
|
|
|
*/
|
|
|
|
ro = &iproute;
|
|
|
|
bzero((caddr_t)ro, sizeof (*ro));
|
|
|
|
dst = (struct sockaddr_in *)&ro->ro_dst;
|
|
|
|
dst->sin_family = AF_INET;
|
|
|
|
dst->sin_addr = fdp->fd_ip.s_addr ? fdp->fd_ip : ip->ip_dst;
|
1997-07-05 09:38:14 +04:00
|
|
|
# ifdef __bsdi__
|
1997-03-29 03:54:55 +03:00
|
|
|
dst->sin_len = sizeof(*dst);
|
1997-07-05 09:38:14 +04:00
|
|
|
# endif
|
|
|
|
# if (BSD >= 199306) && !defined(__NetBSD__) && !defined(__bsdi__)
|
1997-05-28 04:17:11 +04:00
|
|
|
# ifdef RTF_CLONING
|
1997-01-05 16:47:59 +03:00
|
|
|
rtalloc_ign(ro, RTF_CLONING);
|
1997-03-29 03:54:55 +03:00
|
|
|
# else
|
1997-01-05 16:47:59 +03:00
|
|
|
rtalloc_ign(ro, RTF_PRCLONING);
|
1997-03-29 03:54:55 +03:00
|
|
|
# endif
|
|
|
|
# else
|
1997-01-05 16:47:59 +03:00
|
|
|
rtalloc(ro);
|
1997-03-29 03:54:55 +03:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
if (!ifp) {
|
|
|
|
if (!(fin->fin_fr->fr_flags & FR_FASTROUTE)) {
|
|
|
|
error = -2;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) {
|
|
|
|
if (in_localaddr(ip->ip_dst))
|
|
|
|
error = EHOSTUNREACH;
|
|
|
|
else
|
|
|
|
error = ENETUNREACH;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
if (ro->ro_rt->rt_flags & RTF_GATEWAY)
|
|
|
|
dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway;
|
|
|
|
}
|
|
|
|
ro->ro_rt->rt_use++;
|
|
|
|
|
1997-03-29 03:54:55 +03:00
|
|
|
/*
|
|
|
|
* For input packets which are being "fastrouted", they won't
|
|
|
|
* go back through output filtering and miss their chance to get
|
|
|
|
* NAT'd.
|
|
|
|
*/
|
|
|
|
(void) ip_natout(ip, hlen, fin);
|
|
|
|
if (fin->fin_out)
|
|
|
|
ip->ip_sum = 0;
|
|
|
|
/*
|
1997-01-05 16:47:59 +03:00
|
|
|
* If small enough for interface, can just send directly.
|
|
|
|
*/
|
|
|
|
if (ip->ip_len <= ifp->if_mtu) {
|
1997-03-29 03:54:55 +03:00
|
|
|
# ifndef sparc
|
1997-01-05 16:47:59 +03:00
|
|
|
ip->ip_id = htons(ip->ip_id);
|
|
|
|
ip->ip_len = htons(ip->ip_len);
|
|
|
|
ip->ip_off = htons(ip->ip_off);
|
1997-03-29 03:54:55 +03:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
if (!ip->ip_sum)
|
|
|
|
ip->ip_sum = in_cksum(m, hlen);
|
1997-03-29 03:54:55 +03:00
|
|
|
# if BSD >= 199306
|
1997-01-05 16:47:59 +03:00
|
|
|
error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst,
|
|
|
|
ro->ro_rt);
|
1997-03-29 03:54:55 +03:00
|
|
|
# else
|
1997-01-05 16:47:59 +03:00
|
|
|
error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst);
|
1997-03-29 03:54:55 +03:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Too large for interface; fragment if possible.
|
|
|
|
* Must be able to put at least 8 bytes per fragment.
|
|
|
|
*/
|
|
|
|
if (ip->ip_off & IP_DF) {
|
|
|
|
error = EMSGSIZE;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
len = (ifp->if_mtu - hlen) &~ 7;
|
|
|
|
if (len < 8) {
|
|
|
|
error = EMSGSIZE;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
int mhlen, firstlen = len;
|
|
|
|
struct mbuf **mnext = &m->m_act;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Loop through length of segment after first fragment,
|
|
|
|
* make new header and copy data of each part and link onto chain.
|
|
|
|
*/
|
|
|
|
m0 = m;
|
|
|
|
mhlen = sizeof (struct ip);
|
|
|
|
for (off = hlen + len; off < ip->ip_len; off += len) {
|
|
|
|
MGET(m, M_DONTWAIT, MT_HEADER);
|
|
|
|
if (m == 0) {
|
|
|
|
error = ENOBUFS;
|
|
|
|
goto bad;
|
|
|
|
}
|
1997-03-29 03:54:55 +03:00
|
|
|
# if BSD >= 199306
|
1997-01-05 16:47:59 +03:00
|
|
|
m->m_data += max_linkhdr;
|
1997-03-29 03:54:55 +03:00
|
|
|
# else
|
1997-01-05 16:47:59 +03:00
|
|
|
m->m_off = MMAXOFF - hlen;
|
1997-03-29 03:54:55 +03:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
mhip = mtod(m, struct ip *);
|
|
|
|
bcopy((char *)ip, (char *)mhip, sizeof(*ip));
|
|
|
|
if (hlen > sizeof (struct ip)) {
|
|
|
|
mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
|
|
|
|
mhip->ip_hl = mhlen >> 2;
|
|
|
|
}
|
|
|
|
m->m_len = mhlen;
|
|
|
|
mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
|
|
|
|
if (ip->ip_off & IP_MF)
|
|
|
|
mhip->ip_off |= IP_MF;
|
|
|
|
if (off + len >= ip->ip_len)
|
|
|
|
len = ip->ip_len - off;
|
|
|
|
else
|
|
|
|
mhip->ip_off |= IP_MF;
|
|
|
|
mhip->ip_len = htons((u_short)(len + mhlen));
|
|
|
|
m->m_next = m_copy(m0, off, len);
|
|
|
|
if (m->m_next == 0) {
|
|
|
|
error = ENOBUFS; /* ??? */
|
|
|
|
goto sendorfree;
|
|
|
|
}
|
1997-03-29 03:54:55 +03:00
|
|
|
# ifndef sparc
|
1997-01-05 16:47:59 +03:00
|
|
|
mhip->ip_off = htons((u_short)mhip->ip_off);
|
1997-03-29 03:54:55 +03:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
mhip->ip_sum = 0;
|
|
|
|
mhip->ip_sum = in_cksum(m, mhlen);
|
|
|
|
*mnext = m;
|
|
|
|
mnext = &m->m_act;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Update first fragment by trimming what's been copied out
|
|
|
|
* and updating header, then send each fragment (in order).
|
|
|
|
*/
|
|
|
|
m_adj(m0, hlen + firstlen - ip->ip_len);
|
|
|
|
ip->ip_len = htons((u_short)(hlen + firstlen));
|
|
|
|
ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
|
|
|
|
ip->ip_sum = 0;
|
|
|
|
ip->ip_sum = in_cksum(m0, hlen);
|
|
|
|
sendorfree:
|
|
|
|
for (m = m0; m; m = m0) {
|
|
|
|
m0 = m->m_act;
|
|
|
|
m->m_act = 0;
|
|
|
|
if (error == 0)
|
1997-03-29 03:54:55 +03:00
|
|
|
# if BSD >= 199306
|
1997-01-05 16:47:59 +03:00
|
|
|
error = (*ifp->if_output)(ifp, m,
|
|
|
|
(struct sockaddr *)dst, ro->ro_rt);
|
1997-03-29 03:54:55 +03:00
|
|
|
# else
|
1997-01-05 16:47:59 +03:00
|
|
|
error = (*ifp->if_output)(ifp, m,
|
|
|
|
(struct sockaddr *)dst);
|
1997-03-29 03:54:55 +03:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
else
|
|
|
|
m_freem(m);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
done:
|
|
|
|
if (ro->ro_rt) {
|
|
|
|
RTFREE(ro->ro_rt);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
bad:
|
|
|
|
m_freem(m);
|
|
|
|
goto done;
|
|
|
|
}
|
1997-03-29 03:54:55 +03:00
|
|
|
#else /* #ifdef _KERNEL */
|
|
|
|
|
|
|
|
|
|
|
|
static int no_output __P((struct ifnet *ifp, struct mbuf *m,
|
|
|
|
struct sockaddr *s, struct rtentry *rt))
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# ifdef __STDC__
|
|
|
|
static int write_output __P((struct ifnet *ifp, struct mbuf *m,
|
|
|
|
struct sockaddr *s, struct rtentry *rt))
|
|
|
|
{
|
1997-07-05 09:38:14 +04:00
|
|
|
# if !defined(NetBSD) || (NetBSD < 199606) || (NetBSD > 1991011)
|
1997-03-29 03:54:55 +03:00
|
|
|
ip_t *ip = (ip_t *)m;
|
1997-07-05 09:38:14 +04:00
|
|
|
# endif
|
1997-03-29 03:54:55 +03:00
|
|
|
# else
|
|
|
|
static int write_output(ifp, ip)
|
|
|
|
struct ifnet *ifp;
|
|
|
|
ip_t *ip;
|
|
|
|
{
|
|
|
|
# endif
|
|
|
|
FILE *fp;
|
|
|
|
char fname[32];
|
|
|
|
|
1997-07-05 09:38:14 +04:00
|
|
|
# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606))
|
1997-03-29 03:54:55 +03:00
|
|
|
sprintf(fname, "/tmp/%s", ifp->if_xname);
|
|
|
|
if ((fp = fopen(fname, "a"))) {
|
|
|
|
fclose(fp);
|
|
|
|
}
|
1997-07-05 09:38:14 +04:00
|
|
|
# else
|
1997-03-29 03:54:55 +03:00
|
|
|
sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
|
|
|
|
if ((fp = fopen(fname, "a"))) {
|
|
|
|
fwrite((char *)ip, ntohs(ip->ip_len), 1, fp);
|
|
|
|
fclose(fp);
|
|
|
|
}
|
1997-07-05 09:38:14 +04:00
|
|
|
# endif
|
|
|
|
return 0;
|
1997-03-29 03:54:55 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct ifnet *get_unit(name)
|
|
|
|
char *name;
|
|
|
|
{
|
|
|
|
struct ifnet *ifp, **ifa;
|
1997-07-05 09:38:14 +04:00
|
|
|
# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606))
|
1997-03-29 03:54:55 +03:00
|
|
|
for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
|
|
|
|
if (!strcmp(name, ifp->if_xname))
|
|
|
|
return ifp;
|
|
|
|
}
|
1997-07-05 09:38:14 +04:00
|
|
|
# else
|
1997-03-29 03:54:55 +03:00
|
|
|
char ifname[32], *s;
|
|
|
|
|
|
|
|
for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
|
|
|
|
(void) sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit);
|
|
|
|
if (!strcmp(name, ifname))
|
|
|
|
return ifp;
|
|
|
|
}
|
1997-07-05 09:38:14 +04:00
|
|
|
# endif
|
1997-03-29 03:54:55 +03:00
|
|
|
|
|
|
|
if (!ifneta) {
|
|
|
|
ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2);
|
|
|
|
ifneta[1] = NULL;
|
|
|
|
ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp));
|
|
|
|
nifs = 1;
|
|
|
|
} else {
|
|
|
|
nifs++;
|
|
|
|
ifneta = (struct ifnet **)realloc(ifneta,
|
|
|
|
(nifs + 1) * sizeof(*ifa));
|
|
|
|
ifneta[nifs] = NULL;
|
|
|
|
ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp));
|
|
|
|
}
|
|
|
|
ifp = ifneta[nifs - 1];
|
|
|
|
|
1997-07-05 09:38:14 +04:00
|
|
|
# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606))
|
1997-03-29 03:54:55 +03:00
|
|
|
strncpy(ifp->if_xname, name, sizeof(ifp->if_xname));
|
1997-07-05 09:38:14 +04:00
|
|
|
# else
|
1997-03-29 03:54:55 +03:00
|
|
|
for (s = name; *s && !isdigit(*s); s++)
|
|
|
|
;
|
|
|
|
if (*s && isdigit(*s)) {
|
|
|
|
ifp->if_unit = atoi(s);
|
|
|
|
ifp->if_name = (char *)malloc(s - name + 1);
|
|
|
|
strncpy(ifp->if_name, name, s - name);
|
|
|
|
ifp->if_name[s - name] = '\0';
|
|
|
|
} else {
|
|
|
|
ifp->if_name = strdup(name);
|
|
|
|
ifp->if_unit = -1;
|
|
|
|
}
|
1997-07-05 09:38:14 +04:00
|
|
|
# endif
|
1997-03-29 03:54:55 +03:00
|
|
|
ifp->if_output = no_output;
|
|
|
|
return ifp;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1997-07-05 09:38:14 +04:00
|
|
|
|
1997-03-29 03:54:55 +03:00
|
|
|
void init_ifp()
|
|
|
|
{
|
|
|
|
FILE *fp;
|
|
|
|
struct ifnet *ifp, **ifa;
|
|
|
|
char fname[32];
|
1997-07-05 09:38:14 +04:00
|
|
|
# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606))
|
1997-03-29 03:54:55 +03:00
|
|
|
for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
|
|
|
|
ifp->if_output = write_output;
|
|
|
|
sprintf(fname, "/tmp/%s", ifp->if_xname);
|
|
|
|
if ((fp = fopen(fname, "w")))
|
|
|
|
fclose(fp);
|
|
|
|
}
|
1997-07-05 09:38:14 +04:00
|
|
|
# else
|
1997-03-29 03:54:55 +03:00
|
|
|
|
|
|
|
for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
|
|
|
|
ifp->if_output = write_output;
|
|
|
|
sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
|
|
|
|
if ((fp = fopen(fname, "w")))
|
|
|
|
fclose(fp);
|
|
|
|
}
|
1997-07-05 09:38:14 +04:00
|
|
|
# endif
|
1997-03-29 03:54:55 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ipfr_fastroute(ip, fin, fdp)
|
|
|
|
ip_t *ip;
|
|
|
|
fr_info_t *fin;
|
|
|
|
frdest_t *fdp;
|
|
|
|
{
|
|
|
|
struct ifnet *ifp = fdp->fd_ifp;
|
|
|
|
|
|
|
|
if (!ifp)
|
|
|
|
return; /* no routing table out here */
|
|
|
|
|
|
|
|
ip->ip_len = htons((u_short)ip->ip_len);
|
|
|
|
ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
|
|
|
|
ip->ip_sum = 0;
|
|
|
|
(*ifp->if_output)(ifp, (void *)ip, NULL, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1997-03-29 07:39:15 +03:00
|
|
|
int ipllog __P((void))
|
1997-03-29 03:54:55 +03:00
|
|
|
{
|
|
|
|
verbose("l");
|
1997-03-29 07:39:15 +03:00
|
|
|
return 0;
|
1997-03-29 03:54:55 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int send_reset(ip, ifp)
|
|
|
|
ip_t *ip;
|
|
|
|
struct ifnet *ifp;
|
|
|
|
{
|
|
|
|
verbose("- TCP RST sent\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int icmp_error(ip, ifp)
|
|
|
|
ip_t *ip;
|
|
|
|
struct ifnet *ifp;
|
|
|
|
{
|
|
|
|
verbose("- TCP RST sent\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif /* _KERNEL */
|