2002-09-19 12:12:43 +04:00
|
|
|
/* $NetBSD: ip_fil.c,v 1.86 2002/09/19 08:12:47 martti Exp $ */
|
1997-01-06 00:32:18 +03:00
|
|
|
|
1997-01-05 16:47:59 +03:00
|
|
|
/*
|
2002-01-24 11:21:30 +03:00
|
|
|
* Copyright (C) 1993-2001 by Darren Reed.
|
1997-01-05 16:47:59 +03:00
|
|
|
*
|
2002-01-24 11:21:30 +03:00
|
|
|
* See the IPFILTER.LICENCE file for details on licencing.
|
1997-01-05 16:47:59 +03:00
|
|
|
*/
|
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
|
|
|
|
|
2002-01-24 11:23:40 +03:00
|
|
|
#if defined(KERNEL) && !defined(_KERNEL)
|
1997-11-14 15:40:06 +03:00
|
|
|
# define _KERNEL
|
|
|
|
#endif
|
2000-05-03 15:12:03 +04:00
|
|
|
#if defined(_KERNEL) && defined(__FreeBSD_version) && \
|
|
|
|
(__FreeBSD_version >= 400000) && !defined(KLD_MODULE)
|
|
|
|
#include "opt_inet6.h"
|
|
|
|
#endif
|
1999-12-12 14:11:15 +03:00
|
|
|
#include <sys/param.h>
|
2000-05-03 15:12:03 +04:00
|
|
|
#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \
|
2002-01-24 11:21:30 +03:00
|
|
|
defined(_KERNEL) && !defined(_LKM)
|
2000-05-03 15:12:03 +04:00
|
|
|
# include "opt_ipfilter_log.h"
|
|
|
|
#endif
|
|
|
|
#if defined(__FreeBSD__) && !defined(__FreeBSD_version)
|
|
|
|
# if !defined(_KERNEL) || defined(IPFILTER_LKM)
|
1997-05-25 16:40:11 +04:00
|
|
|
# include <osreldate.h>
|
|
|
|
# endif
|
|
|
|
#endif
|
2002-03-14 15:32:36 +03:00
|
|
|
#ifdef __sgi
|
2002-05-02 21:11:37 +04:00
|
|
|
# define _KMEMUSER
|
2002-03-14 15:32:36 +03:00
|
|
|
# include <sys/ptimers.h>
|
|
|
|
#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>
|
1999-12-12 14:11:15 +03:00
|
|
|
# include <fcntl.h>
|
1997-03-29 03:54:55 +03:00
|
|
|
#endif
|
1997-01-05 16:47:59 +03:00
|
|
|
#include <sys/errno.h>
|
2002-01-24 11:23:40 +03:00
|
|
|
#include <sys/types.h>
|
1997-01-05 16:47:59 +03:00
|
|
|
#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
|
|
|
|
#if !SOLARIS
|
1999-12-12 14:11:15 +03:00
|
|
|
# if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000)
|
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>
|
1999-12-12 14:11:15 +03:00
|
|
|
# if defined(_KERNEL) && !defined(IPFILTER_LKM)
|
|
|
|
# include "opt_ipfilter.h"
|
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
#endif
|
1997-10-30 19:08:54 +03:00
|
|
|
#ifdef __sgi
|
|
|
|
#include <sys/debug.h>
|
|
|
|
# ifdef IFF_DRVRLOCK /* IRIX6 */
|
|
|
|
#include <sys/hashing.h>
|
|
|
|
# endif
|
|
|
|
#endif
|
1997-01-05 16:47:59 +03:00
|
|
|
#include <net/route.h>
|
|
|
|
#include <netinet/in.h>
|
1997-10-30 19:08:54 +03:00
|
|
|
#if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */
|
1999-12-12 14:11:15 +03:00
|
|
|
# include <netinet/in_var.h>
|
1997-10-30 19:08:54 +03:00
|
|
|
#endif
|
1997-01-05 16:47:59 +03:00
|
|
|
#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
|
1999-12-12 14:11:15 +03:00
|
|
|
# include <unistd.h>
|
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"
|
2000-05-03 15:12:03 +04:00
|
|
|
#ifdef USE_INET6
|
|
|
|
# include <netinet/icmp6.h>
|
2002-01-24 11:21:30 +03:00
|
|
|
# if !SOLARIS
|
|
|
|
# include <netinet6/ip6protosw.h>
|
|
|
|
# include <netinet6/nd6.h>
|
|
|
|
# endif
|
2000-05-03 15:12:03 +04:00
|
|
|
#endif
|
1997-05-25 16:40:11 +04:00
|
|
|
#include "netinet/ip_fil.h"
|
|
|
|
#include "netinet/ip_nat.h"
|
|
|
|
#include "netinet/ip_frag.h"
|
|
|
|
#include "netinet/ip_state.h"
|
2002-01-24 11:21:30 +03:00
|
|
|
#include "netinet/ip_proxy.h"
|
1997-07-05 09:38:14 +04:00
|
|
|
#include "netinet/ip_auth.h"
|
1999-12-12 14:11:15 +03:00
|
|
|
#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
|
|
|
|
# include <sys/malloc.h>
|
|
|
|
#endif
|
2002-01-24 11:23:40 +03:00
|
|
|
#ifndef MIN
|
|
|
|
# define MIN(a,b) (((a)<(b))?(a):(b))
|
|
|
|
#endif
|
1999-12-12 14:11:15 +03:00
|
|
|
#if !SOLARIS && defined(_KERNEL) && !defined(__sgi)
|
|
|
|
# include <sys/kernel.h>
|
1997-05-25 16:40:11 +04:00
|
|
|
extern int ip_optcopy __P((struct ip *, struct ip *));
|
1997-01-05 16:47:59 +03:00
|
|
|
#endif
|
|
|
|
|
2002-01-24 11:21:30 +03:00
|
|
|
#if !defined(lint)
|
2002-01-24 11:23:40 +03:00
|
|
|
#if defined(__NetBSD__)
|
|
|
|
#include <sys/cdefs.h>
|
2002-09-19 12:12:43 +04:00
|
|
|
__KERNEL_RCSID(0, "$NetBSD: ip_fil.c,v 1.86 2002/09/19 08:12:47 martti Exp $");
|
2002-01-24 11:23:40 +03:00
|
|
|
#else
|
2002-01-24 11:21:30 +03:00
|
|
|
static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
|
2002-09-19 12:08:14 +04:00
|
|
|
static const char rcsid[] = "@(#)Id: ip_fil.c,v 2.42.2.60 2002/08/28 12:40:39 darrenr Exp";
|
2002-01-24 11:23:40 +03:00
|
|
|
#endif
|
2002-05-02 21:13:27 +04:00
|
|
|
#endif
|
2002-01-24 11:21:30 +03:00
|
|
|
|
1997-01-05 16:47:59 +03:00
|
|
|
|
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
|
1997-10-30 19:08:54 +03:00
|
|
|
# if (BSD < 199306) || defined(__sgi)
|
|
|
|
extern int tcp_ttl;
|
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
#endif
|
|
|
|
|
2002-01-24 11:21:30 +03:00
|
|
|
#ifdef ICMP_UNREACH_FILTER_PROHIB
|
|
|
|
int ipl_unreach = ICMP_UNREACH_FILTER_PROHIB;
|
|
|
|
#else
|
1997-01-05 16:47:59 +03:00
|
|
|
int ipl_unreach = ICMP_UNREACH_FILTER;
|
2002-01-24 11:21:30 +03:00
|
|
|
#endif
|
1997-10-30 19:08:54 +03:00
|
|
|
u_long ipl_frouteok[2] = {0, 0};
|
1997-01-05 16:47:59 +03:00
|
|
|
|
2000-05-03 15:12:03 +04:00
|
|
|
static int frzerostats __P((caddr_t));
|
|
|
|
#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003)
|
1997-07-05 09:38:14 +04:00
|
|
|
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
|
|
|
#ifdef _KERNEL
|
1997-11-14 15:40:06 +03:00
|
|
|
static int (*fr_savep) __P((ip_t *, int, void *, int, struct mbuf **));
|
2002-01-24 11:21:30 +03:00
|
|
|
static int send_ip __P((ip_t *, fr_info_t *, struct mbuf **));
|
|
|
|
# ifdef USE_INET6
|
|
|
|
static int ipfr_fastroute6 __P((struct mbuf *, struct mbuf **,
|
|
|
|
fr_info_t *, frdest_t *));
|
|
|
|
# endif
|
1998-11-22 18:17:18 +03:00
|
|
|
# ifdef __sgi
|
2002-09-19 12:08:14 +04:00
|
|
|
extern int tcp_mtudisc;
|
1998-11-22 18:17:18 +03:00
|
|
|
extern kmutex_t ipf_rw;
|
1999-12-12 14:11:15 +03:00
|
|
|
extern KRWLOCK_T ipf_mutex;
|
1998-11-22 18:17:18 +03:00
|
|
|
# endif
|
1997-03-29 03:54:55 +03:00
|
|
|
#else
|
|
|
|
void init_ifp __P((void));
|
2002-03-14 15:32:36 +03:00
|
|
|
# if defined(__sgi) && (IRIX < 605)
|
1997-10-30 19:08:54 +03:00
|
|
|
static int no_output __P((struct ifnet *, struct mbuf *,
|
|
|
|
struct sockaddr *));
|
|
|
|
static int write_output __P((struct ifnet *, struct mbuf *,
|
|
|
|
struct sockaddr *));
|
|
|
|
# else
|
1997-03-29 03:54:55 +03:00
|
|
|
static int no_output __P((struct ifnet *, struct mbuf *,
|
|
|
|
struct sockaddr *, struct rtentry *));
|
1997-09-21 22:00:54 +04:00
|
|
|
static int write_output __P((struct ifnet *, struct mbuf *,
|
|
|
|
struct sockaddr *, struct rtentry *));
|
1997-10-30 19:08:54 +03:00
|
|
|
# endif
|
1997-03-29 03:54:55 +03:00
|
|
|
#endif
|
1999-12-12 14:11:15 +03:00
|
|
|
int fr_running = 0;
|
|
|
|
|
|
|
|
#if (__FreeBSD_version >= 300000) && defined(_KERNEL)
|
|
|
|
struct callout_handle ipfr_slowtimer_ch;
|
|
|
|
#endif
|
2000-05-11 23:46:05 +04:00
|
|
|
#if defined(__NetBSD__) && (__NetBSD_Version__ >= 104230000)
|
|
|
|
# include <sys/callout.h>
|
|
|
|
struct callout ipfr_slowtimer_ch;
|
|
|
|
#endif
|
2002-01-24 11:21:30 +03:00
|
|
|
#if defined(__OpenBSD__)
|
|
|
|
# include <sys/timeout.h>
|
|
|
|
struct timeout ipfr_slowtimer_ch;
|
|
|
|
#endif
|
2001-03-26 10:11:46 +04:00
|
|
|
#if defined(__sgi) && defined(_KERNEL)
|
|
|
|
toid_t ipfr_slowtimer_ch;
|
|
|
|
#endif
|
1997-01-05 16:47:59 +03:00
|
|
|
|
2002-09-19 12:12:43 +04:00
|
|
|
#if defined(__NetBSD__) && (__NetBSD_Version__ >= 106080000) && \
|
|
|
|
defined(_KERNEL)
|
|
|
|
#include <sys/conf.h>
|
|
|
|
const struct cdevsw ipl_cdevsw = {
|
|
|
|
iplopen, iplclose, iplread, nowrite, iplioctl,
|
|
|
|
nostop, notty, nopoll, nommap,
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
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
|
|
|
|
1998-05-17 20:50:15 +04:00
|
|
|
#if defined(__NetBSD__) || defined(__OpenBSD__) || (_BSDI_VERSION >= 199701)
|
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-09-21 22:00:54 +04:00
|
|
|
int (*fr_checkp) __P((ip_t *ip, int hlen, void *ifp, int out, 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
|
|
|
|
2002-01-24 11:21:30 +03:00
|
|
|
|
|
|
|
#if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000) && \
|
|
|
|
defined(_KERNEL)
|
|
|
|
# include <net/pfil.h>
|
|
|
|
|
|
|
|
static int fr_check_wrapper(void *, struct mbuf **, struct ifnet *, int );
|
|
|
|
|
|
|
|
static int fr_check_wrapper(arg, mp, ifp, dir)
|
|
|
|
void *arg;
|
|
|
|
struct mbuf **mp;
|
|
|
|
struct ifnet *ifp;
|
|
|
|
int dir;
|
|
|
|
{
|
|
|
|
struct ip *ip = mtod(*mp, struct ip *);
|
|
|
|
int rv, hlen = ip->ip_hl << 2;
|
|
|
|
|
|
|
|
#if defined(M_CSUM_TCPv4)
|
|
|
|
/*
|
|
|
|
* If the packet is out-bound, we can't delay checksums
|
|
|
|
* here. For in-bound, the checksum has already been
|
|
|
|
* validated.
|
|
|
|
*/
|
|
|
|
if (dir == PFIL_OUT) {
|
|
|
|
if ((*mp)->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_UDPv4)) {
|
|
|
|
in_delayed_cksum(*mp);
|
|
|
|
(*mp)->m_pkthdr.csum_flags &=
|
|
|
|
~(M_CSUM_TCPv4|M_CSUM_UDPv4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* M_CSUM_TCPv4 */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We get the packet with all fields in network byte
|
|
|
|
* order. We expect ip_len and ip_off to be in host
|
|
|
|
* order. We frob them, call the filter, then frob
|
|
|
|
* them back.
|
|
|
|
*
|
|
|
|
* Note, we don't need to update the checksum, because
|
|
|
|
* it has already been verified.
|
|
|
|
*/
|
|
|
|
NTOHS(ip->ip_len);
|
|
|
|
NTOHS(ip->ip_off);
|
|
|
|
|
|
|
|
rv = fr_check(ip, hlen, ifp, (dir == PFIL_OUT), mp);
|
|
|
|
|
|
|
|
if (rv == 0 && *mp != NULL) {
|
|
|
|
ip = mtod(*mp, struct ip *);
|
|
|
|
HTONS(ip->ip_len);
|
|
|
|
HTONS(ip->ip_off);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
# ifdef USE_INET6
|
|
|
|
# include <netinet/ip6.h>
|
|
|
|
|
|
|
|
static int fr_check_wrapper6(void *, struct mbuf **, struct ifnet *, int );
|
|
|
|
|
|
|
|
static int fr_check_wrapper6(arg, mp, ifp, dir)
|
|
|
|
void *arg;
|
|
|
|
struct mbuf **mp;
|
|
|
|
struct ifnet *ifp;
|
|
|
|
int dir;
|
|
|
|
{
|
2002-09-19 12:12:43 +04:00
|
|
|
|
2002-01-24 11:21:30 +03:00
|
|
|
return (fr_check(mtod(*mp, struct ip *), sizeof(struct ip6_hdr),
|
|
|
|
ifp, (dir == PFIL_OUT), mp));
|
|
|
|
}
|
|
|
|
# endif
|
|
|
|
#endif /* __NetBSD_Version >= 105110000 && _KERNEL */
|
1997-03-29 03:54:55 +03:00
|
|
|
#ifdef _KERNEL
|
1997-10-30 19:08:54 +03:00
|
|
|
# if defined(IPFILTER_LKM) && !defined(__sgi)
|
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
|
|
|
/*
|
2002-01-24 11:23:40 +03:00
|
|
|
* Try to detect the case when compiling for NetBSD with pseudo-device
|
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
|
|
|
*/
|
2002-01-24 11:23:40 +03:00
|
|
|
# if defined(__NetBSD__) && defined(PFIL_HOOKS)
|
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-09-21 22:00:54 +04:00
|
|
|
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-09-21 22:00:54 +04:00
|
|
|
# endif
|
|
|
|
|
1997-05-27 05:15:21 +04:00
|
|
|
|
1997-09-21 22:00:54 +04:00
|
|
|
# if defined(__NetBSD__)
|
1997-07-06 09:13:00 +04:00
|
|
|
int ipl_enable()
|
1997-09-21 22:00:54 +04:00
|
|
|
# else
|
|
|
|
int iplattach()
|
|
|
|
# endif
|
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;
|
2000-05-03 15:12:03 +04:00
|
|
|
# if defined(__sgi) || (defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000))
|
|
|
|
int error = 0;
|
1997-10-30 19:08:54 +03:00
|
|
|
# endif
|
Restructure the PFIL_HOOKS mechanism a bit:
- All packets are passed to PFIL_HOOKS as they come off the wire, i.e.
fields in protocol headers in network order, etc.
- Allow for multiple hooks to be registered, using a "key" and a "dlt".
The "dlt" is a BPF data link type, indicating what type of header is
present.
- INET and INET6 register with key == AF_INET or AF_INET6, and
dlt == DLT_RAW.
- PFIL_HOOKS now take an argument for the filter hook, and mbuf **,
an ifnet *, and a direction (PFIL_IN or PFIL_OUT), thus making them
less IP (really, IP Filter) centric.
Maintain compatibility with IP Filter by adding wrapper functions for
IP Filter.
2000-11-11 03:52:36 +03:00
|
|
|
#if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000)
|
|
|
|
struct pfil_head *ph_inet;
|
2002-01-24 11:21:30 +03:00
|
|
|
# ifdef USE_INET6
|
Restructure the PFIL_HOOKS mechanism a bit:
- All packets are passed to PFIL_HOOKS as they come off the wire, i.e.
fields in protocol headers in network order, etc.
- Allow for multiple hooks to be registered, using a "key" and a "dlt".
The "dlt" is a BPF data link type, indicating what type of header is
present.
- INET and INET6 register with key == AF_INET or AF_INET6, and
dlt == DLT_RAW.
- PFIL_HOOKS now take an argument for the filter hook, and mbuf **,
an ifnet *, and a direction (PFIL_IN or PFIL_OUT), thus making them
less IP (really, IP Filter) centric.
Maintain compatibility with IP Filter by adding wrapper functions for
IP Filter.
2000-11-11 03:52:36 +03:00
|
|
|
struct pfil_head *ph_inet6;
|
2002-01-24 11:21:30 +03:00
|
|
|
# endif
|
Restructure the PFIL_HOOKS mechanism a bit:
- All packets are passed to PFIL_HOOKS as they come off the wire, i.e.
fields in protocol headers in network order, etc.
- Allow for multiple hooks to be registered, using a "key" and a "dlt".
The "dlt" is a BPF data link type, indicating what type of header is
present.
- INET and INET6 register with key == AF_INET or AF_INET6, and
dlt == DLT_RAW.
- PFIL_HOOKS now take an argument for the filter hook, and mbuf **,
an ifnet *, and a direction (PFIL_IN or PFIL_OUT), thus making them
less IP (really, IP Filter) centric.
Maintain compatibility with IP Filter by adding wrapper functions for
IP Filter.
2000-11-11 03:52:36 +03:00
|
|
|
#endif
|
1997-01-05 16:47:59 +03:00
|
|
|
|
1997-10-30 19:08:54 +03:00
|
|
|
SPL_NET(s);
|
2000-02-02 00:29:15 +03:00
|
|
|
if (fr_running || (fr_checkp == fr_check)) {
|
1997-03-29 03:54:55 +03:00
|
|
|
printf("IP Filter: already initialized\n");
|
1997-10-30 19:08:54 +03:00
|
|
|
SPL_X(s);
|
1997-01-05 16:47:59 +03:00
|
|
|
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
|
|
|
|
1999-12-12 14:11:15 +03:00
|
|
|
# ifdef IPFILTER_LOG
|
|
|
|
ipflog_init();
|
|
|
|
# endif
|
2002-01-24 11:21:30 +03:00
|
|
|
if (nat_init() == -1) {
|
|
|
|
SPL_X(s);
|
2000-08-01 07:46:09 +04:00
|
|
|
return EIO;
|
2002-01-24 11:21:30 +03:00
|
|
|
}
|
|
|
|
if (fr_stateinit() == -1) {
|
|
|
|
SPL_X(s);
|
2000-08-01 07:46:09 +04:00
|
|
|
return EIO;
|
2002-01-24 11:21:30 +03:00
|
|
|
}
|
|
|
|
if (appr_init() == -1) {
|
|
|
|
SPL_X(s);
|
2000-08-01 07:46:09 +04:00
|
|
|
return EIO;
|
2002-01-24 11:21:30 +03:00
|
|
|
}
|
1999-12-12 14:11:15 +03:00
|
|
|
|
1997-04-15 04:44:42 +04:00
|
|
|
# ifdef NETBSD_PF
|
2002-05-02 21:11:37 +04:00
|
|
|
# if (__NetBSD_Version__ >= 104200000) || (__FreeBSD_version >= 500011)
|
Restructure the PFIL_HOOKS mechanism a bit:
- All packets are passed to PFIL_HOOKS as they come off the wire, i.e.
fields in protocol headers in network order, etc.
- Allow for multiple hooks to be registered, using a "key" and a "dlt".
The "dlt" is a BPF data link type, indicating what type of header is
present.
- INET and INET6 register with key == AF_INET or AF_INET6, and
dlt == DLT_RAW.
- PFIL_HOOKS now take an argument for the filter hook, and mbuf **,
an ifnet *, and a direction (PFIL_IN or PFIL_OUT), thus making them
less IP (really, IP Filter) centric.
Maintain compatibility with IP Filter by adding wrapper functions for
IP Filter.
2000-11-11 03:52:36 +03:00
|
|
|
# if __NetBSD_Version__ >= 105110000
|
2002-01-24 11:24:59 +03:00
|
|
|
ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
|
2002-01-24 11:21:30 +03:00
|
|
|
# ifdef USE_INET6
|
2002-01-24 11:24:59 +03:00
|
|
|
ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
|
2002-01-24 11:21:30 +03:00
|
|
|
# endif
|
2002-01-24 11:24:59 +03:00
|
|
|
if (ph_inet == NULL
|
|
|
|
# ifdef USE_INET6
|
|
|
|
&& ph_inet6 == NULL
|
|
|
|
# endif
|
|
|
|
)
|
2002-01-24 11:21:30 +03:00
|
|
|
return ENODEV;
|
|
|
|
|
Restructure the PFIL_HOOKS mechanism a bit:
- All packets are passed to PFIL_HOOKS as they come off the wire, i.e.
fields in protocol headers in network order, etc.
- Allow for multiple hooks to be registered, using a "key" and a "dlt".
The "dlt" is a BPF data link type, indicating what type of header is
present.
- INET and INET6 register with key == AF_INET or AF_INET6, and
dlt == DLT_RAW.
- PFIL_HOOKS now take an argument for the filter hook, and mbuf **,
an ifnet *, and a direction (PFIL_IN or PFIL_OUT), thus making them
less IP (really, IP Filter) centric.
Maintain compatibility with IP Filter by adding wrapper functions for
IP Filter.
2000-11-11 03:52:36 +03:00
|
|
|
if (ph_inet != NULL)
|
|
|
|
error = pfil_add_hook((void *)fr_check_wrapper, NULL,
|
2002-01-24 11:21:30 +03:00
|
|
|
PFIL_IN|PFIL_OUT, ph_inet);
|
Restructure the PFIL_HOOKS mechanism a bit:
- All packets are passed to PFIL_HOOKS as they come off the wire, i.e.
fields in protocol headers in network order, etc.
- Allow for multiple hooks to be registered, using a "key" and a "dlt".
The "dlt" is a BPF data link type, indicating what type of header is
present.
- INET and INET6 register with key == AF_INET or AF_INET6, and
dlt == DLT_RAW.
- PFIL_HOOKS now take an argument for the filter hook, and mbuf **,
an ifnet *, and a direction (PFIL_IN or PFIL_OUT), thus making them
less IP (really, IP Filter) centric.
Maintain compatibility with IP Filter by adding wrapper functions for
IP Filter.
2000-11-11 03:52:36 +03:00
|
|
|
else
|
|
|
|
error = 0;
|
2002-01-24 11:21:30 +03:00
|
|
|
# else
|
|
|
|
error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
|
2000-05-03 15:12:03 +04:00
|
|
|
&inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
|
2002-01-24 11:21:30 +03:00
|
|
|
# endif
|
2000-05-03 15:12:03 +04:00
|
|
|
if (error) {
|
|
|
|
# ifdef USE_INET6
|
|
|
|
goto pfil_error;
|
|
|
|
# else
|
2002-01-24 11:21:30 +03:00
|
|
|
SPL_X(s);
|
2000-05-03 15:12:03 +04:00
|
|
|
appr_unload();
|
|
|
|
ip_natunload();
|
|
|
|
fr_stateunload();
|
|
|
|
return error;
|
|
|
|
# endif
|
|
|
|
}
|
|
|
|
# else
|
|
|
|
pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT);
|
|
|
|
# endif
|
|
|
|
# ifdef USE_INET6
|
Restructure the PFIL_HOOKS mechanism a bit:
- All packets are passed to PFIL_HOOKS as they come off the wire, i.e.
fields in protocol headers in network order, etc.
- Allow for multiple hooks to be registered, using a "key" and a "dlt".
The "dlt" is a BPF data link type, indicating what type of header is
present.
- INET and INET6 register with key == AF_INET or AF_INET6, and
dlt == DLT_RAW.
- PFIL_HOOKS now take an argument for the filter hook, and mbuf **,
an ifnet *, and a direction (PFIL_IN or PFIL_OUT), thus making them
less IP (really, IP Filter) centric.
Maintain compatibility with IP Filter by adding wrapper functions for
IP Filter.
2000-11-11 03:52:36 +03:00
|
|
|
# if __NetBSD_Version__ >= 105110000
|
|
|
|
if (ph_inet6 != NULL)
|
|
|
|
error = pfil_add_hook((void *)fr_check_wrapper6, NULL,
|
2002-01-24 11:24:59 +03:00
|
|
|
PFIL_IN|PFIL_OUT, ph_inet6);
|
Restructure the PFIL_HOOKS mechanism a bit:
- All packets are passed to PFIL_HOOKS as they come off the wire, i.e.
fields in protocol headers in network order, etc.
- Allow for multiple hooks to be registered, using a "key" and a "dlt".
The "dlt" is a BPF data link type, indicating what type of header is
present.
- INET and INET6 register with key == AF_INET or AF_INET6, and
dlt == DLT_RAW.
- PFIL_HOOKS now take an argument for the filter hook, and mbuf **,
an ifnet *, and a direction (PFIL_IN or PFIL_OUT), thus making them
less IP (really, IP Filter) centric.
Maintain compatibility with IP Filter by adding wrapper functions for
IP Filter.
2000-11-11 03:52:36 +03:00
|
|
|
else
|
|
|
|
error = 0;
|
2000-05-03 15:12:03 +04:00
|
|
|
if (error) {
|
2002-01-24 11:21:30 +03:00
|
|
|
pfil_remove_hook((void *)fr_check_wrapper6, NULL,
|
|
|
|
PFIL_IN|PFIL_OUT, ph_inet6);
|
Restructure the PFIL_HOOKS mechanism a bit:
- All packets are passed to PFIL_HOOKS as they come off the wire, i.e.
fields in protocol headers in network order, etc.
- Allow for multiple hooks to be registered, using a "key" and a "dlt".
The "dlt" is a BPF data link type, indicating what type of header is
present.
- INET and INET6 register with key == AF_INET or AF_INET6, and
dlt == DLT_RAW.
- PFIL_HOOKS now take an argument for the filter hook, and mbuf **,
an ifnet *, and a direction (PFIL_IN or PFIL_OUT), thus making them
less IP (really, IP Filter) centric.
Maintain compatibility with IP Filter by adding wrapper functions for
IP Filter.
2000-11-11 03:52:36 +03:00
|
|
|
# else
|
2002-01-24 11:21:30 +03:00
|
|
|
error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
|
|
|
|
&inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
|
|
|
|
if (error) {
|
|
|
|
pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
|
2000-05-03 15:12:03 +04:00
|
|
|
&inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
|
Restructure the PFIL_HOOKS mechanism a bit:
- All packets are passed to PFIL_HOOKS as they come off the wire, i.e.
fields in protocol headers in network order, etc.
- Allow for multiple hooks to be registered, using a "key" and a "dlt".
The "dlt" is a BPF data link type, indicating what type of header is
present.
- INET and INET6 register with key == AF_INET or AF_INET6, and
dlt == DLT_RAW.
- PFIL_HOOKS now take an argument for the filter hook, and mbuf **,
an ifnet *, and a direction (PFIL_IN or PFIL_OUT), thus making them
less IP (really, IP Filter) centric.
Maintain compatibility with IP Filter by adding wrapper functions for
IP Filter.
2000-11-11 03:52:36 +03:00
|
|
|
# endif
|
2000-05-03 15:12:03 +04:00
|
|
|
pfil_error:
|
2002-01-24 11:21:30 +03:00
|
|
|
SPL_X(s);
|
2000-05-03 15:12:03 +04:00
|
|
|
appr_unload();
|
|
|
|
ip_natunload();
|
|
|
|
fr_stateunload();
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
# endif
|
1997-04-15 04:44:42 +04:00
|
|
|
# endif
|
1997-03-29 03:54:55 +03:00
|
|
|
|
1997-10-30 19:08:54 +03:00
|
|
|
# ifdef __sgi
|
|
|
|
error = ipfilter_sgi_attach();
|
|
|
|
if (error) {
|
|
|
|
SPL_X(s);
|
2000-05-03 15:12:03 +04:00
|
|
|
appr_unload();
|
|
|
|
ip_natunload();
|
|
|
|
fr_stateunload();
|
1997-10-30 19:08:54 +03:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
# endif
|
|
|
|
|
1997-09-21 22:00:54 +04:00
|
|
|
bzero((char *)frcache, sizeof(frcache));
|
1997-01-05 16:47:59 +03:00
|
|
|
fr_savep = fr_checkp;
|
|
|
|
fr_checkp = fr_check;
|
2000-05-03 15:12:03 +04:00
|
|
|
fr_running = 1;
|
1997-03-29 03:54:55 +03:00
|
|
|
|
1997-10-30 19:08:54 +03:00
|
|
|
SPL_X(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";
|
|
|
|
|
2000-02-02 00:41:36 +03:00
|
|
|
printf("%s initialized. Default = %s all, Logging = %s\n",
|
|
|
|
ipfilter_version, defpass,
|
1997-11-14 15:40:06 +03:00
|
|
|
# ifdef IPFILTER_LOG
|
|
|
|
"enabled");
|
|
|
|
# else
|
|
|
|
"disabled");
|
|
|
|
# endif
|
2000-05-11 23:46:05 +04:00
|
|
|
#ifdef _KERNEL
|
|
|
|
# if defined(__NetBSD__) && (__NetBSD_Version__ >= 104230000)
|
2000-03-23 10:01:25 +03:00
|
|
|
callout_init(&ipfr_slowtimer_ch);
|
|
|
|
callout_reset(&ipfr_slowtimer_ch, hz / 2, ipfr_slowtimer, NULL);
|
2000-05-11 23:46:05 +04:00
|
|
|
# else
|
2002-01-24 11:21:30 +03:00
|
|
|
# if defined(__OpenBSD__)
|
|
|
|
timeout_set(&ipfr_slowtimer_ch, ipfr_slowtimer, NULL);
|
|
|
|
timeout_add(&ipfr_slowtimer_ch, hz/2);
|
2000-03-23 10:01:25 +03:00
|
|
|
# else
|
2002-01-24 11:21:30 +03:00
|
|
|
# if (__FreeBSD_version >= 300000) || defined(__sgi)
|
|
|
|
ipfr_slowtimer_ch = timeout(ipfr_slowtimer, NULL, hz/2);
|
|
|
|
# else
|
1999-12-12 14:11:15 +03:00
|
|
|
timeout(ipfr_slowtimer, NULL, hz/2);
|
2002-01-24 11:21:30 +03:00
|
|
|
# endif
|
2000-03-23 10:01:25 +03:00
|
|
|
# endif
|
1999-12-12 14:11:15 +03:00
|
|
|
# endif
|
|
|
|
#endif
|
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-09-21 22:00:54 +04:00
|
|
|
# if defined(__NetBSD__)
|
1997-07-06 09:13:00 +04:00
|
|
|
int ipl_disable()
|
1997-09-21 22:00:54 +04:00
|
|
|
# else
|
|
|
|
int ipldetach()
|
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
{
|
2002-09-19 12:08:14 +04:00
|
|
|
int s, i;
|
2000-05-03 15:12:03 +04:00
|
|
|
#if defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000)
|
2002-01-24 11:21:30 +03:00
|
|
|
int error = 0;
|
2000-12-29 00:40:59 +03:00
|
|
|
# if __NetBSD_Version__ >= 105150000
|
2002-01-24 11:21:30 +03:00
|
|
|
struct pfil_head *ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
|
|
|
|
# ifdef USE_INET6
|
|
|
|
struct pfil_head *ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
|
|
|
|
# endif
|
Restructure the PFIL_HOOKS mechanism a bit:
- All packets are passed to PFIL_HOOKS as they come off the wire, i.e.
fields in protocol headers in network order, etc.
- Allow for multiple hooks to be registered, using a "key" and a "dlt".
The "dlt" is a BPF data link type, indicating what type of header is
present.
- INET and INET6 register with key == AF_INET or AF_INET6, and
dlt == DLT_RAW.
- PFIL_HOOKS now take an argument for the filter hook, and mbuf **,
an ifnet *, and a direction (PFIL_IN or PFIL_OUT), thus making them
less IP (really, IP Filter) centric.
Maintain compatibility with IP Filter by adding wrapper functions for
IP Filter.
2000-11-11 03:52:36 +03:00
|
|
|
# endif
|
2000-05-03 15:12:03 +04:00
|
|
|
#endif
|
1997-01-05 16:47:59 +03:00
|
|
|
|
2000-05-11 23:46:05 +04:00
|
|
|
#ifdef _KERNEL
|
|
|
|
# if defined(__NetBSD__) && (__NetBSD_Version__ >= 104230000)
|
|
|
|
callout_stop(&ipfr_slowtimer_ch);
|
1999-12-12 14:11:15 +03:00
|
|
|
# else
|
2000-05-11 23:46:05 +04:00
|
|
|
# if (__FreeBSD_version >= 300000)
|
|
|
|
untimeout(ipfr_slowtimer, NULL, ipfr_slowtimer_ch);
|
|
|
|
# else
|
1999-12-12 14:11:15 +03:00
|
|
|
# ifdef __sgi
|
2001-03-26 10:11:46 +04:00
|
|
|
untimeout(ipfr_slowtimer_ch);
|
2000-03-23 10:01:25 +03:00
|
|
|
# else
|
2002-01-24 11:21:30 +03:00
|
|
|
# if defined(__OpenBSD__)
|
|
|
|
timeout_del(&ipfr_slowtimer_ch);
|
|
|
|
# else
|
1999-12-12 14:11:15 +03:00
|
|
|
untimeout(ipfr_slowtimer, NULL);
|
2002-01-24 11:21:30 +03:00
|
|
|
# endif /* OpenBSD */
|
|
|
|
# endif /* __sgi */
|
2000-05-11 23:46:05 +04:00
|
|
|
# endif /* FreeBSD */
|
|
|
|
# endif /* NetBSD */
|
1999-12-12 14:11:15 +03:00
|
|
|
#endif
|
1997-10-30 19:08:54 +03:00
|
|
|
SPL_NET(s);
|
2000-02-02 00:29:15 +03:00
|
|
|
if (!fr_running)
|
1997-01-05 16:47:59 +03:00
|
|
|
{
|
1997-03-29 03:54:55 +03:00
|
|
|
printf("IP Filter: not initialized\n");
|
1997-10-30 19:08:54 +03:00
|
|
|
SPL_X(s);
|
|
|
|
return 0;
|
1997-01-05 16:47:59 +03:00
|
|
|
}
|
|
|
|
|
2000-05-03 15:12:03 +04:00
|
|
|
printf("%s unloaded\n", ipfilter_version);
|
|
|
|
|
1997-01-05 16:47:59 +03:00
|
|
|
fr_checkp = fr_savep;
|
2002-09-19 12:08:14 +04:00
|
|
|
i = frflush(IPL_LOGIPF, FR_INQUE|FR_OUTQUE|FR_INACTIVE);
|
|
|
|
i += frflush(IPL_LOGIPF, FR_INQUE|FR_OUTQUE);
|
2000-02-02 00:29:15 +03:00
|
|
|
fr_running = 0;
|
1997-01-05 16:47:59 +03:00
|
|
|
|
1997-04-15 04:44:42 +04:00
|
|
|
# ifdef NETBSD_PF
|
2002-05-02 21:11:37 +04:00
|
|
|
# if ((__NetBSD_Version__ >= 104200000) || (__FreeBSD_version >= 500011))
|
Restructure the PFIL_HOOKS mechanism a bit:
- All packets are passed to PFIL_HOOKS as they come off the wire, i.e.
fields in protocol headers in network order, etc.
- Allow for multiple hooks to be registered, using a "key" and a "dlt".
The "dlt" is a BPF data link type, indicating what type of header is
present.
- INET and INET6 register with key == AF_INET or AF_INET6, and
dlt == DLT_RAW.
- PFIL_HOOKS now take an argument for the filter hook, and mbuf **,
an ifnet *, and a direction (PFIL_IN or PFIL_OUT), thus making them
less IP (really, IP Filter) centric.
Maintain compatibility with IP Filter by adding wrapper functions for
IP Filter.
2000-11-11 03:52:36 +03:00
|
|
|
# if __NetBSD_Version__ >= 105110000
|
|
|
|
if (ph_inet != NULL)
|
|
|
|
error = pfil_remove_hook((void *)fr_check_wrapper, NULL,
|
2002-01-24 11:21:30 +03:00
|
|
|
PFIL_IN|PFIL_OUT, ph_inet);
|
Restructure the PFIL_HOOKS mechanism a bit:
- All packets are passed to PFIL_HOOKS as they come off the wire, i.e.
fields in protocol headers in network order, etc.
- Allow for multiple hooks to be registered, using a "key" and a "dlt".
The "dlt" is a BPF data link type, indicating what type of header is
present.
- INET and INET6 register with key == AF_INET or AF_INET6, and
dlt == DLT_RAW.
- PFIL_HOOKS now take an argument for the filter hook, and mbuf **,
an ifnet *, and a direction (PFIL_IN or PFIL_OUT), thus making them
less IP (really, IP Filter) centric.
Maintain compatibility with IP Filter by adding wrapper functions for
IP Filter.
2000-11-11 03:52:36 +03:00
|
|
|
else
|
|
|
|
error = 0;
|
|
|
|
# else
|
2002-01-24 11:21:30 +03:00
|
|
|
error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
|
2000-05-03 15:12:03 +04:00
|
|
|
&inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
|
Restructure the PFIL_HOOKS mechanism a bit:
- All packets are passed to PFIL_HOOKS as they come off the wire, i.e.
fields in protocol headers in network order, etc.
- Allow for multiple hooks to be registered, using a "key" and a "dlt".
The "dlt" is a BPF data link type, indicating what type of header is
present.
- INET and INET6 register with key == AF_INET or AF_INET6, and
dlt == DLT_RAW.
- PFIL_HOOKS now take an argument for the filter hook, and mbuf **,
an ifnet *, and a direction (PFIL_IN or PFIL_OUT), thus making them
less IP (really, IP Filter) centric.
Maintain compatibility with IP Filter by adding wrapper functions for
IP Filter.
2000-11-11 03:52:36 +03:00
|
|
|
# endif
|
2002-01-24 11:21:30 +03:00
|
|
|
if (error) {
|
|
|
|
SPL_X(s);
|
2000-05-03 15:12:03 +04:00
|
|
|
return error;
|
2002-01-24 11:21:30 +03:00
|
|
|
}
|
2000-05-03 15:12:03 +04:00
|
|
|
# else
|
|
|
|
pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT);
|
|
|
|
# endif
|
|
|
|
# ifdef USE_INET6
|
Restructure the PFIL_HOOKS mechanism a bit:
- All packets are passed to PFIL_HOOKS as they come off the wire, i.e.
fields in protocol headers in network order, etc.
- Allow for multiple hooks to be registered, using a "key" and a "dlt".
The "dlt" is a BPF data link type, indicating what type of header is
present.
- INET and INET6 register with key == AF_INET or AF_INET6, and
dlt == DLT_RAW.
- PFIL_HOOKS now take an argument for the filter hook, and mbuf **,
an ifnet *, and a direction (PFIL_IN or PFIL_OUT), thus making them
less IP (really, IP Filter) centric.
Maintain compatibility with IP Filter by adding wrapper functions for
IP Filter.
2000-11-11 03:52:36 +03:00
|
|
|
# if __NetBSD_Version__ >= 105110000
|
|
|
|
if (ph_inet6 != NULL)
|
|
|
|
error = pfil_remove_hook((void *)fr_check_wrapper6, NULL,
|
2002-01-24 11:21:30 +03:00
|
|
|
PFIL_IN|PFIL_OUT, ph_inet6);
|
Restructure the PFIL_HOOKS mechanism a bit:
- All packets are passed to PFIL_HOOKS as they come off the wire, i.e.
fields in protocol headers in network order, etc.
- Allow for multiple hooks to be registered, using a "key" and a "dlt".
The "dlt" is a BPF data link type, indicating what type of header is
present.
- INET and INET6 register with key == AF_INET or AF_INET6, and
dlt == DLT_RAW.
- PFIL_HOOKS now take an argument for the filter hook, and mbuf **,
an ifnet *, and a direction (PFIL_IN or PFIL_OUT), thus making them
less IP (really, IP Filter) centric.
Maintain compatibility with IP Filter by adding wrapper functions for
IP Filter.
2000-11-11 03:52:36 +03:00
|
|
|
else
|
|
|
|
error = 0;
|
|
|
|
# else
|
2002-01-24 11:21:30 +03:00
|
|
|
error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
|
|
|
|
&inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
|
Restructure the PFIL_HOOKS mechanism a bit:
- All packets are passed to PFIL_HOOKS as they come off the wire, i.e.
fields in protocol headers in network order, etc.
- Allow for multiple hooks to be registered, using a "key" and a "dlt".
The "dlt" is a BPF data link type, indicating what type of header is
present.
- INET and INET6 register with key == AF_INET or AF_INET6, and
dlt == DLT_RAW.
- PFIL_HOOKS now take an argument for the filter hook, and mbuf **,
an ifnet *, and a direction (PFIL_IN or PFIL_OUT), thus making them
less IP (really, IP Filter) centric.
Maintain compatibility with IP Filter by adding wrapper functions for
IP Filter.
2000-11-11 03:52:36 +03:00
|
|
|
# endif
|
2002-01-24 11:21:30 +03:00
|
|
|
if (error) {
|
|
|
|
SPL_X(s);
|
2000-05-03 15:12:03 +04:00
|
|
|
return error;
|
2002-01-24 11:21:30 +03:00
|
|
|
}
|
2000-05-03 15:12:03 +04:00
|
|
|
# endif
|
1997-04-15 04:44:42 +04:00
|
|
|
# endif
|
1997-03-29 03:54:55 +03:00
|
|
|
|
1997-10-30 19:08:54 +03:00
|
|
|
# ifdef __sgi
|
|
|
|
ipfilter_sgi_detach();
|
|
|
|
# endif
|
|
|
|
|
2000-05-03 15:12:03 +04:00
|
|
|
appr_unload();
|
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
|
|
|
|
1997-10-30 19:08:54 +03:00
|
|
|
SPL_X(s);
|
1997-01-05 16:47:59 +03:00
|
|
|
return 0;
|
|
|
|
}
|
1997-03-29 03:54:55 +03:00
|
|
|
#endif /* _KERNEL */
|
|
|
|
|
1997-01-05 16:47:59 +03:00
|
|
|
|
2000-05-03 15:12:03 +04:00
|
|
|
static int frzerostats(data)
|
1997-01-05 16:47:59 +03:00
|
|
|
caddr_t data;
|
|
|
|
{
|
1999-12-12 14:11:15 +03:00
|
|
|
friostat_t fio;
|
2000-05-03 15:12:03 +04:00
|
|
|
int error;
|
|
|
|
|
|
|
|
fr_getstat(&fio);
|
|
|
|
error = IWCOPYPTR((caddr_t)&fio, data, sizeof(fio));
|
|
|
|
if (error)
|
|
|
|
return EFAULT;
|
1997-01-05 16:47:59 +03:00
|
|
|
|
|
|
|
bzero((char *)frstats, sizeof(*frstats) * 2);
|
2000-05-03 15:12:03 +04:00
|
|
|
|
|
|
|
return 0;
|
1997-01-05 16:47:59 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Filter ioctl interface.
|
|
|
|
*/
|
1997-10-30 19:08:54 +03:00
|
|
|
#ifdef __sgi
|
|
|
|
int IPL_EXTERN(ioctl)(dev_t dev, int cmd, caddr_t data, int mode
|
|
|
|
# ifdef _KERNEL
|
|
|
|
, cred_t *cp, int *rp
|
|
|
|
# endif
|
|
|
|
)
|
|
|
|
#else
|
|
|
|
int IPL_EXTERN(ioctl)(dev, cmd, data, mode
|
2000-05-03 15:12:03 +04:00
|
|
|
# if (defined(_KERNEL) && ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || \
|
|
|
|
(NetBSD >= 199511) || (__FreeBSD_version >= 220000) || \
|
|
|
|
defined(__OpenBSD__)))
|
1997-01-05 16:47:59 +03:00
|
|
|
, p)
|
|
|
|
struct proc *p;
|
2000-05-03 15:12:03 +04:00
|
|
|
# else
|
1997-01-05 16:47:59 +03:00
|
|
|
)
|
2000-05-03 15:12:03 +04:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
dev_t dev;
|
2000-05-03 15:12:03 +04:00
|
|
|
# if defined(__NetBSD__) || defined(__OpenBSD__) || \
|
|
|
|
(_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000)
|
1997-01-05 16:47:59 +03:00
|
|
|
u_long cmd;
|
2000-05-03 15:12:03 +04:00
|
|
|
# else
|
1997-03-29 03:54:55 +03:00
|
|
|
int cmd;
|
2000-05-03 15:12:03 +04:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
caddr_t data;
|
|
|
|
int mode;
|
1997-10-30 19:08:54 +03:00
|
|
|
#endif /* __sgi */
|
1997-01-05 16:47:59 +03:00
|
|
|
{
|
1997-07-05 09:38:14 +04:00
|
|
|
#if defined(_KERNEL) && !SOLARIS
|
|
|
|
int s;
|
|
|
|
#endif
|
1998-05-17 20:50:15 +04:00
|
|
|
int error = 0, unit = 0, tmp;
|
1997-01-05 16:47:59 +03:00
|
|
|
|
1999-12-12 14:11:15 +03:00
|
|
|
#if (BSD >= 199306) && defined(_KERNEL)
|
|
|
|
if ((securelevel >= 2) && (mode & FWRITE))
|
|
|
|
return EPERM;
|
|
|
|
#endif
|
1997-03-29 03:54:55 +03:00
|
|
|
#ifdef _KERNEL
|
1997-10-30 19:08:54 +03:00
|
|
|
unit = GET_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;
|
1999-12-12 14:11:15 +03:00
|
|
|
#else
|
|
|
|
unit = dev;
|
1997-03-29 03:54:55 +03:00
|
|
|
#endif
|
1997-01-05 16:47:59 +03:00
|
|
|
|
2002-09-19 12:08:14 +04:00
|
|
|
if (fr_running == 0 && (cmd != SIOCFRENB || unit != IPL_LOGIPF))
|
|
|
|
return ENODEV;
|
|
|
|
|
1997-10-30 19:08:54 +03:00
|
|
|
SPL_NET(s);
|
1997-05-25 16:40:11 +04:00
|
|
|
|
|
|
|
if (unit == IPL_LOGNAT) {
|
2000-08-01 07:46:09 +04:00
|
|
|
/*
|
|
|
|
* If we're doing a NAT operation, implicitly enable
|
|
|
|
* IP Filter if not already enabled. We do this
|
|
|
|
* because filtering and NAT are really separate
|
|
|
|
* operations, and it's not entirely obvious from
|
|
|
|
* a user's point of view that you need to enable
|
|
|
|
* the filter in order to enable NAT.
|
|
|
|
*
|
|
|
|
* Since the default rule is to pass all packets,
|
|
|
|
* this shouldn't cause any noticeable side-effects.
|
|
|
|
*/
|
2000-08-01 19:03:51 +04:00
|
|
|
if (fr_running == 0) {
|
|
|
|
#if defined(_KERNEL)
|
2000-08-01 07:46:09 +04:00
|
|
|
error = ipl_enable();
|
2000-08-01 19:03:51 +04:00
|
|
|
#else
|
|
|
|
error = EIO;
|
|
|
|
#endif
|
|
|
|
}
|
2000-08-01 07:46:09 +04:00
|
|
|
if (error == 0)
|
2000-03-07 07:58:35 +03:00
|
|
|
error = nat_ioctl(data, cmd, mode);
|
1997-10-30 19:08:54 +03:00
|
|
|
SPL_X(s);
|
1997-05-25 16:40:11 +04:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
if (unit == IPL_LOGSTATE) {
|
2000-05-03 15:12:03 +04:00
|
|
|
if (fr_running)
|
2000-03-07 07:58:35 +03:00
|
|
|
error = fr_state_ioctl(data, cmd, mode);
|
2000-05-03 15:12:03 +04:00
|
|
|
else
|
|
|
|
error = EIO;
|
|
|
|
SPL_X(s);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
if (unit == IPL_LOGAUTH) {
|
|
|
|
if (!fr_running)
|
2002-01-24 11:21:30 +03:00
|
|
|
error = EIO;
|
|
|
|
else
|
|
|
|
error = fr_auth_ioctl(data, mode, cmd, NULL, NULL);
|
1997-10-30 19:08:54 +03:00
|
|
|
SPL_X(s);
|
1997-05-25 16:40:11 +04:00
|
|
|
return error;
|
|
|
|
}
|
2000-05-03 15:12:03 +04:00
|
|
|
|
1997-01-05 16:47:59 +03:00
|
|
|
switch (cmd) {
|
|
|
|
case FIONREAD :
|
|
|
|
#ifdef IPFILTER_LOG
|
2000-05-03 15:12:03 +04:00
|
|
|
error = IWCOPY((caddr_t)&iplused[IPL_LOGIPF], (caddr_t)data,
|
|
|
|
sizeof(iplused[IPL_LOGIPF]));
|
1997-01-05 16:47:59 +03:00
|
|
|
#endif
|
|
|
|
break;
|
1997-09-21 22:00:54 +04:00
|
|
|
#if (!defined(IPFILTER_LKM) || defined(__NetBSD__)) && defined(_KERNEL)
|
1997-01-05 16:47:59 +03:00
|
|
|
case SIOCFRENB :
|
|
|
|
{
|
|
|
|
u_int enable;
|
|
|
|
|
|
|
|
if (!(mode & FWRITE))
|
|
|
|
error = EPERM;
|
|
|
|
else {
|
2000-05-03 15:12:03 +04:00
|
|
|
error = IRCOPY(data, (caddr_t)&enable, sizeof(enable));
|
|
|
|
if (error)
|
|
|
|
break;
|
2000-02-02 00:29:15 +03:00
|
|
|
if (enable)
|
1997-09-21 22:00:54 +04:00
|
|
|
# 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
|
|
|
error = ipl_enable();
|
2002-01-24 11:21:30 +03:00
|
|
|
# else
|
2000-02-02 00:29:15 +03:00
|
|
|
error = iplattach();
|
2002-01-24 11:21:30 +03:00
|
|
|
# endif
|
2000-02-02 00:29:15 +03:00
|
|
|
else
|
2002-01-24 11:21:30 +03:00
|
|
|
# if defined(__NetBSD__)
|
|
|
|
error = ipl_disable();
|
|
|
|
# else
|
1997-09-21 22:00:54 +04:00
|
|
|
error = ipldetach();
|
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
case SIOCSETFF :
|
|
|
|
if (!(mode & FWRITE))
|
|
|
|
error = EPERM;
|
|
|
|
else
|
2000-05-03 15:12:03 +04:00
|
|
|
error = IRCOPY(data, (caddr_t)&fr_flags,
|
|
|
|
sizeof(fr_flags));
|
1997-01-05 16:47:59 +03:00
|
|
|
break;
|
|
|
|
case SIOCGETFF :
|
2000-05-03 15:12:03 +04:00
|
|
|
error = IWCOPY((caddr_t)&fr_flags, data, sizeof(fr_flags));
|
1997-01-05 16:47:59 +03:00
|
|
|
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 :
|
|
|
|
{
|
2000-05-03 15:12:03 +04:00
|
|
|
friostat_t fio;
|
|
|
|
|
|
|
|
fr_getstat(&fio);
|
|
|
|
error = IWCOPYPTR((caddr_t)&fio, data, sizeof(fio));
|
|
|
|
if (error)
|
2002-01-24 11:21:30 +03:00
|
|
|
error = EFAULT;
|
1997-01-05 16:47:59 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SIOCFRZST :
|
|
|
|
if (!(mode & FWRITE))
|
|
|
|
error = EPERM;
|
|
|
|
else
|
2000-05-03 15:12:03 +04:00
|
|
|
error = frzerostats(data);
|
1997-01-05 16:47:59 +03:00
|
|
|
break;
|
|
|
|
case SIOCIPFFL :
|
|
|
|
if (!(mode & FWRITE))
|
|
|
|
error = EPERM;
|
1998-05-17 20:50:15 +04:00
|
|
|
else {
|
2000-05-03 15:12:03 +04:00
|
|
|
error = IRCOPY(data, (caddr_t)&tmp, sizeof(tmp));
|
|
|
|
if (!error) {
|
|
|
|
tmp = frflush(unit, tmp);
|
|
|
|
error = IWCOPY((caddr_t)&tmp, data,
|
|
|
|
sizeof(tmp));
|
|
|
|
}
|
1998-05-17 20:50:15 +04:00
|
|
|
}
|
1997-01-05 16:47:59 +03:00
|
|
|
break;
|
2000-05-03 15:12:03 +04:00
|
|
|
case SIOCSTLCK :
|
|
|
|
error = IRCOPY(data, (caddr_t)&tmp, sizeof(tmp));
|
|
|
|
if (!error) {
|
|
|
|
fr_state_lock = tmp;
|
|
|
|
fr_nat_lock = tmp;
|
|
|
|
fr_frag_lock = tmp;
|
|
|
|
fr_auth_lock = tmp;
|
|
|
|
} else
|
|
|
|
error = EFAULT;
|
|
|
|
break;
|
1997-01-05 16:47:59 +03:00
|
|
|
#ifdef IPFILTER_LOG
|
|
|
|
case SIOCIPFFB :
|
|
|
|
if (!(mode & FWRITE))
|
|
|
|
error = EPERM;
|
1997-09-21 22:00:54 +04:00
|
|
|
else
|
|
|
|
*(int *)data = ipflog_clear(unit);
|
1997-01-05 16:47:59 +03:00
|
|
|
break;
|
|
|
|
#endif /* IPFILTER_LOG */
|
|
|
|
case SIOCGFRST :
|
2000-05-03 15:12:03 +04:00
|
|
|
error = IWCOPYPTR((caddr_t)ipfr_fragstats(), data,
|
|
|
|
sizeof(ipfrstat_t));
|
|
|
|
if (error)
|
2002-01-24 11:21:30 +03:00
|
|
|
error = EFAULT;
|
1997-01-05 16:47:59 +03:00
|
|
|
break;
|
1997-09-21 22:00:54 +04:00
|
|
|
case SIOCAUTHW :
|
|
|
|
case SIOCAUTHR :
|
1997-07-05 09:38:14 +04:00
|
|
|
if (!(mode & FWRITE)) {
|
|
|
|
error = EPERM;
|
|
|
|
break;
|
|
|
|
}
|
1997-09-21 22:00:54 +04:00
|
|
|
case SIOCFRSYN :
|
|
|
|
if (!(mode & FWRITE))
|
|
|
|
error = EPERM;
|
1997-10-30 19:08:54 +03:00
|
|
|
else {
|
|
|
|
#if defined(_KERNEL) && defined(__sgi)
|
1997-09-21 22:00:54 +04:00
|
|
|
ipfsync();
|
1997-10-30 19:08:54 +03:00
|
|
|
#endif
|
|
|
|
frsync();
|
|
|
|
}
|
1997-09-21 22:00:54 +04:00
|
|
|
break;
|
1997-01-05 16:47:59 +03:00
|
|
|
default :
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
1997-10-30 19:08:54 +03:00
|
|
|
SPL_X(s);
|
1997-01-05 16:47:59 +03:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
1997-09-21 22:00:54 +04:00
|
|
|
|
1999-12-12 14:11:15 +03:00
|
|
|
void fr_forgetifp(ifp)
|
|
|
|
void *ifp;
|
1997-09-21 22:00:54 +04:00
|
|
|
{
|
2002-01-24 11:23:40 +03:00
|
|
|
register frentry_t *f;
|
1999-12-12 14:11:15 +03:00
|
|
|
|
|
|
|
WRITE_ENTER(&ipf_mutex);
|
|
|
|
for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next)
|
|
|
|
if (f->fr_ifa == ifp)
|
|
|
|
f->fr_ifa = (void *)-1;
|
|
|
|
for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next)
|
|
|
|
if (f->fr_ifa == ifp)
|
|
|
|
f->fr_ifa = (void *)-1;
|
|
|
|
for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next)
|
|
|
|
if (f->fr_ifa == ifp)
|
|
|
|
f->fr_ifa = (void *)-1;
|
|
|
|
for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next)
|
|
|
|
if (f->fr_ifa == ifp)
|
|
|
|
f->fr_ifa = (void *)-1;
|
2000-05-03 15:12:03 +04:00
|
|
|
#ifdef USE_INET6
|
|
|
|
for (f = ipacct6[0][fr_active]; (f != NULL); f = f->fr_next)
|
|
|
|
if (f->fr_ifa == ifp)
|
|
|
|
f->fr_ifa = (void *)-1;
|
|
|
|
for (f = ipacct6[1][fr_active]; (f != NULL); f = f->fr_next)
|
|
|
|
if (f->fr_ifa == ifp)
|
|
|
|
f->fr_ifa = (void *)-1;
|
|
|
|
for (f = ipfilter6[0][fr_active]; (f != NULL); f = f->fr_next)
|
|
|
|
if (f->fr_ifa == ifp)
|
|
|
|
f->fr_ifa = (void *)-1;
|
|
|
|
for (f = ipfilter6[1][fr_active]; (f != NULL); f = f->fr_next)
|
|
|
|
if (f->fr_ifa == ifp)
|
|
|
|
f->fr_ifa = (void *)-1;
|
|
|
|
#endif
|
1999-12-12 14:11:15 +03:00
|
|
|
RWLOCK_EXIT(&ipf_mutex);
|
|
|
|
ip_natsync(ifp);
|
1997-07-05 09:38:14 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int frrequest(unit, req, data, set)
|
|
|
|
int unit;
|
2000-05-03 15:12:03 +04:00
|
|
|
#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003)
|
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;
|
|
|
|
{
|
2002-01-24 11:21:30 +03:00
|
|
|
register frentry_t *fp, *f, **fprev;
|
|
|
|
register frentry_t **ftail;
|
1997-09-21 22:00:54 +04:00
|
|
|
frgroup_t *fg = NULL;
|
2002-01-24 11:21:30 +03:00
|
|
|
int error = 0, in, i;
|
2000-05-03 15:12:03 +04:00
|
|
|
u_int *p, *pp;
|
2002-01-24 11:21:30 +03:00
|
|
|
frentry_t frd;
|
|
|
|
frdest_t *fdp;
|
1999-12-12 14:11:15 +03:00
|
|
|
u_int group;
|
1997-01-05 16:47:59 +03:00
|
|
|
|
1997-03-29 03:54:55 +03:00
|
|
|
fp = &frd;
|
2000-05-03 15:12:03 +04:00
|
|
|
error = IRCOPYPTR(data, (caddr_t)fp, sizeof(*fp));
|
|
|
|
if (error)
|
|
|
|
return EFAULT;
|
1999-12-12 14:11:15 +03:00
|
|
|
fp->fr_ref = 0;
|
2000-08-10 01:00:39 +04:00
|
|
|
#if (BSD >= 199306) && defined(_KERNEL)
|
|
|
|
if ((securelevel > 0) && (fp->fr_func != NULL))
|
|
|
|
return EPERM;
|
|
|
|
#endif
|
1997-01-05 16:47:59 +03:00
|
|
|
|
1997-09-21 22:00:54 +04:00
|
|
|
/*
|
|
|
|
* Check that the group number does exist and that if a head group
|
|
|
|
* has been specified, doesn't exist.
|
|
|
|
*/
|
2002-09-19 12:08:14 +04:00
|
|
|
if ((req != SIOCZRLST) && ((req == SIOCINAFR) || (req == SIOCINIFR) ||
|
|
|
|
(req == SIOCADAFR) || (req == SIOCADIFR)) && fp->fr_grhead &&
|
1999-12-12 14:11:15 +03:00
|
|
|
fr_findgroup((u_int)fp->fr_grhead, fp->fr_flags, unit, set, NULL))
|
1997-09-21 22:00:54 +04:00
|
|
|
return EEXIST;
|
1999-12-12 14:11:15 +03:00
|
|
|
if ((req != SIOCZRLST) && fp->fr_group &&
|
|
|
|
!fr_findgroup((u_int)fp->fr_group, fp->fr_flags, unit, set, NULL))
|
1997-09-21 22:00:54 +04:00
|
|
|
return ESRCH;
|
|
|
|
|
1997-01-05 16:47:59 +03:00
|
|
|
in = (fp->fr_flags & FR_INQUE) ? 0 : 1;
|
1997-09-21 22:00:54 +04:00
|
|
|
|
1997-07-05 09:38:14 +04:00
|
|
|
if (unit == IPL_LOGAUTH)
|
|
|
|
ftail = fprev = &ipauth;
|
2000-05-03 15:12:03 +04:00
|
|
|
else if ((fp->fr_flags & FR_ACCOUNT) && (fp->fr_v == 4))
|
1997-01-05 16:47:59 +03:00
|
|
|
ftail = fprev = &ipacct[in][set];
|
2000-05-03 15:12:03 +04:00
|
|
|
else if ((fp->fr_flags & (FR_OUTQUE|FR_INQUE)) && (fp->fr_v == 4))
|
1997-01-05 16:47:59 +03:00
|
|
|
ftail = fprev = &ipfilter[in][set];
|
2000-05-03 15:12:03 +04:00
|
|
|
#ifdef USE_INET6
|
|
|
|
else if ((fp->fr_flags & FR_ACCOUNT) && (fp->fr_v == 6))
|
|
|
|
ftail = fprev = &ipacct6[in][set];
|
|
|
|
else if ((fp->fr_flags & (FR_OUTQUE|FR_INQUE)) && (fp->fr_v == 6))
|
|
|
|
ftail = fprev = &ipfilter6[in][set];
|
|
|
|
#endif
|
1997-01-05 16:47:59 +03:00
|
|
|
else
|
|
|
|
return ESRCH;
|
|
|
|
|
1997-09-21 22:00:54 +04:00
|
|
|
if ((group = fp->fr_group)) {
|
|
|
|
if (!(fg = fr_findgroup(group, fp->fr_flags, unit, set, NULL)))
|
|
|
|
return ESRCH;
|
|
|
|
ftail = fprev = fg->fg_start;
|
|
|
|
}
|
|
|
|
|
1997-03-29 03:54:55 +03:00
|
|
|
bzero((char *)frcache, sizeof(frcache[0]) * 2);
|
|
|
|
|
2002-01-24 11:21:30 +03:00
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
if ((fp->fr_ifnames[i][1] == '\0') &&
|
|
|
|
((fp->fr_ifnames[i][0] == '-') ||
|
|
|
|
(fp->fr_ifnames[i][0] == '*'))) {
|
|
|
|
fp->fr_ifas[i] = NULL;
|
|
|
|
} else if (*fp->fr_ifnames[i]) {
|
|
|
|
fp->fr_ifas[i] = GETUNIT(fp->fr_ifnames[i], fp->fr_v);
|
|
|
|
if (!fp->fr_ifas[i])
|
|
|
|
fp->fr_ifas[i] = (void *)-1;
|
|
|
|
}
|
1999-12-12 14:11:15 +03:00
|
|
|
}
|
1997-01-05 16:47:59 +03:00
|
|
|
|
|
|
|
fdp = &fp->fr_dif;
|
|
|
|
fp->fr_flags &= ~FR_DUP;
|
|
|
|
if (*fdp->fd_ifname) {
|
2000-05-03 15:12:03 +04:00
|
|
|
fdp->fd_ifp = GETUNIT(fdp->fd_ifname, fp->fr_v);
|
1997-01-05 16:47:59 +03:00
|
|
|
if (!fdp->fd_ifp)
|
|
|
|
fdp->fd_ifp = (struct ifnet *)-1;
|
|
|
|
else
|
|
|
|
fp->fr_flags |= FR_DUP;
|
|
|
|
}
|
|
|
|
|
|
|
|
fdp = &fp->fr_tif;
|
|
|
|
if (*fdp->fd_ifname) {
|
2000-05-03 15:12:03 +04:00
|
|
|
fdp->fd_ifp = GETUNIT(fdp->fd_ifname, fp->fr_v);
|
1997-01-05 16:47:59 +03:00
|
|
|
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).
|
|
|
|
*/
|
2000-05-03 15:12:03 +04:00
|
|
|
for (fp->fr_cksum = 0, p = (u_int *)&fp->fr_ip, pp = &fp->fr_cksum;
|
2000-08-10 01:00:39 +04:00
|
|
|
p < pp; p++)
|
2000-05-03 15:12:03 +04:00
|
|
|
fp->fr_cksum += *p;
|
|
|
|
|
1997-01-05 16:47:59 +03:00
|
|
|
for (; (f = *ftail); ftail = &f->fr_next)
|
2000-05-03 15:12:03 +04:00
|
|
|
if ((fp->fr_cksum == f->fr_cksum) &&
|
|
|
|
!bcmp((char *)&f->fr_ip, (char *)&fp->fr_ip, FR_CMPSIZ))
|
1997-01-05 16:47:59 +03:00
|
|
|
break;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If zero'ing statistics, copy current to caller and zero.
|
|
|
|
*/
|
|
|
|
if (req == SIOCZRLST) {
|
|
|
|
if (!f)
|
|
|
|
return ESRCH;
|
2000-05-03 15:12:03 +04:00
|
|
|
error = IWCOPYPTR((caddr_t)f, data, sizeof(*f));
|
|
|
|
if (error)
|
|
|
|
return EFAULT;
|
1997-01-05 16:47:59 +03:00
|
|
|
f->fr_hits = 0;
|
|
|
|
f->fr_bytes = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!f) {
|
2000-02-02 00:29:15 +03:00
|
|
|
if (req != SIOCINAFR && req != SIOCINIFR)
|
1997-01-05 16:47:59 +03:00
|
|
|
while ((f = *ftail))
|
|
|
|
ftail = &f->fr_next;
|
1999-12-12 14:11:15 +03:00
|
|
|
else {
|
2000-02-02 00:29:15 +03:00
|
|
|
if (fp->fr_hits) {
|
|
|
|
ftail = fprev;
|
1999-12-12 14:11:15 +03:00
|
|
|
while (--fp->fr_hits && (f = *ftail))
|
|
|
|
ftail = &f->fr_next;
|
2000-02-02 00:29:15 +03:00
|
|
|
}
|
1999-12-12 14:11:15 +03:00
|
|
|
f = NULL;
|
|
|
|
}
|
1997-01-05 16:47:59 +03:00
|
|
|
}
|
|
|
|
|
2000-05-03 15:12:03 +04:00
|
|
|
if (req == SIOCRMAFR || req == SIOCRMIFR) {
|
1997-01-05 16:47:59 +03:00
|
|
|
if (!f)
|
|
|
|
error = ESRCH;
|
|
|
|
else {
|
2000-05-03 15:12:03 +04:00
|
|
|
/*
|
|
|
|
* Only return EBUSY if there is a group list, else
|
|
|
|
* it's probably just state information referencing
|
|
|
|
* the rule.
|
|
|
|
*/
|
|
|
|
if ((f->fr_ref > 1) && f->fr_grp)
|
1997-09-21 22:00:54 +04:00
|
|
|
return EBUSY;
|
|
|
|
if (fg && fg->fg_head)
|
|
|
|
fg->fg_head->fr_ref--;
|
|
|
|
if (f->fr_grhead)
|
1999-12-12 14:11:15 +03:00
|
|
|
fr_delgroup((u_int)f->fr_grhead, fp->fr_flags,
|
|
|
|
unit, set);
|
1997-07-05 09:38:14 +04:00
|
|
|
fixskip(fprev, f, -1);
|
1997-01-05 16:47:59 +03:00
|
|
|
*ftail = f->fr_next;
|
2000-05-03 15:12:03 +04:00
|
|
|
f->fr_next = NULL;
|
2002-01-24 11:21:30 +03:00
|
|
|
f->fr_ref--;
|
2000-05-03 15:12:03 +04:00
|
|
|
if (f->fr_ref == 0)
|
|
|
|
KFREE(f);
|
1997-01-05 16:47:59 +03:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (f)
|
|
|
|
error = EEXIST;
|
|
|
|
else {
|
1999-12-12 14:11:15 +03:00
|
|
|
KMALLOC(f, frentry_t *);
|
1997-03-29 03:54:55 +03:00
|
|
|
if (f != NULL) {
|
1997-09-21 22:00:54 +04:00
|
|
|
if (fg && fg->fg_head)
|
|
|
|
fg->fg_head->fr_ref++;
|
1997-01-05 16:47:59 +03:00
|
|
|
bcopy((char *)fp, (char *)f, sizeof(*f));
|
1997-09-21 22:00:54 +04:00
|
|
|
f->fr_ref = 1;
|
1997-01-05 16:47:59 +03:00
|
|
|
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-09-21 22:00:54 +04:00
|
|
|
f->fr_grp = NULL;
|
|
|
|
if ((group = f->fr_grhead))
|
|
|
|
fg = fr_addgroup(group, f, unit, set);
|
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
|
|
|
|
*/
|
1999-12-12 14:11:15 +03:00
|
|
|
# ifdef __sgi
|
|
|
|
# ifdef _KERNEL
|
1997-10-30 19:08:54 +03:00
|
|
|
int IPL_EXTERN(open)(dev_t *pdev, int flags, int devtype, cred_t *cp)
|
1999-12-12 14:11:15 +03:00
|
|
|
# else
|
1997-10-30 19:08:54 +03:00
|
|
|
int IPL_EXTERN(open)(dev_t dev, int flags)
|
1999-12-12 14:11:15 +03:00
|
|
|
# endif
|
|
|
|
# else
|
1997-10-30 19:08:54 +03:00
|
|
|
int IPL_EXTERN(open)(dev, flags
|
1999-12-12 14:11:15 +03:00
|
|
|
# if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \
|
|
|
|
(__FreeBSD_version >= 220000) || defined(__OpenBSD__)) && defined(_KERNEL)
|
1997-01-05 16:47:59 +03:00
|
|
|
, devtype, p)
|
|
|
|
int devtype;
|
|
|
|
struct proc *p;
|
1999-12-12 14:11:15 +03:00
|
|
|
# else
|
1997-01-05 16:47:59 +03:00
|
|
|
)
|
1999-12-12 14:11:15 +03:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
dev_t dev;
|
|
|
|
int flags;
|
1999-12-12 14:11:15 +03:00
|
|
|
# endif /* __sgi */
|
1997-01-05 16:47:59 +03:00
|
|
|
{
|
1999-12-12 14:11:15 +03:00
|
|
|
# if defined(__sgi) && defined(_KERNEL)
|
1997-10-30 19:08:54 +03:00
|
|
|
u_int min = geteminor(*pdev);
|
1999-12-12 14:11:15 +03:00
|
|
|
# else
|
1997-10-30 19:08:54 +03:00
|
|
|
u_int min = GET_MINOR(dev);
|
1999-12-12 14:11:15 +03:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
|
1999-12-12 14:11:15 +03:00
|
|
|
if (IPL_LOGMAX < 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-12-12 14:11:15 +03:00
|
|
|
# ifdef __sgi
|
1997-10-30 19:08:54 +03:00
|
|
|
int IPL_EXTERN(close)(dev_t dev, int flags, int devtype, cred_t *cp)
|
|
|
|
#else
|
|
|
|
int IPL_EXTERN(close)(dev, flags
|
1999-12-12 14:11:15 +03:00
|
|
|
# if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \
|
|
|
|
(__FreeBSD_version >= 220000) || defined(__OpenBSD__)) && defined(_KERNEL)
|
1997-01-05 16:47:59 +03:00
|
|
|
, devtype, p)
|
|
|
|
int devtype;
|
|
|
|
struct proc *p;
|
1999-12-12 14:11:15 +03:00
|
|
|
# else
|
1997-01-05 16:47:59 +03:00
|
|
|
)
|
1999-12-12 14:11:15 +03:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
dev_t dev;
|
|
|
|
int flags;
|
1999-12-12 14:11:15 +03:00
|
|
|
# endif /* __sgi */
|
1997-01-05 16:47:59 +03:00
|
|
|
{
|
1997-10-30 19:08:54 +03:00
|
|
|
u_int min = GET_MINOR(dev);
|
1997-01-05 16:47:59 +03:00
|
|
|
|
1999-12-12 14:11:15 +03:00
|
|
|
if (IPL_LOGMAX < 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.
|
|
|
|
*/
|
1999-12-12 14:11:15 +03:00
|
|
|
# ifdef __sgi
|
1997-10-30 19:08:54 +03:00
|
|
|
int IPL_EXTERN(read)(dev_t dev, uio_t *uio, cred_t *crp)
|
1999-12-12 14:11:15 +03:00
|
|
|
# else
|
1997-05-28 04:17:11 +04:00
|
|
|
# if BSD >= 199306
|
1997-10-30 19:08:54 +03:00
|
|
|
int IPL_EXTERN(read)(dev, uio, ioflag)
|
1997-01-05 16:47:59 +03:00
|
|
|
int ioflag;
|
1997-05-28 04:17:11 +04:00
|
|
|
# else
|
1997-10-30 19:08:54 +03:00
|
|
|
int IPL_EXTERN(read)(dev, uio)
|
1997-05-28 04:17:11 +04:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
dev_t dev;
|
2002-01-24 11:23:40 +03:00
|
|
|
register struct uio *uio;
|
1999-12-12 14:11:15 +03:00
|
|
|
# endif /* __sgi */
|
1997-01-05 16:47:59 +03:00
|
|
|
{
|
1999-12-12 14:11:15 +03:00
|
|
|
# ifdef IPFILTER_LOG
|
1997-10-30 19:08:54 +03:00
|
|
|
return ipflog_read(GET_MINOR(dev), uio);
|
1999-12-12 14:11:15 +03:00
|
|
|
# else
|
1997-04-15 04:44:42 +04:00
|
|
|
return ENXIO;
|
1999-12-12 14:11:15 +03:00
|
|
|
# endif
|
1997-04-15 04:44:42 +04:00
|
|
|
}
|
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.
|
|
|
|
*/
|
2000-05-23 10:07:42 +04:00
|
|
|
int send_reset(oip, fin)
|
1999-12-12 14:11:15 +03:00
|
|
|
struct ip *oip;
|
2000-05-23 10:07:42 +04:00
|
|
|
fr_info_t *fin;
|
1997-01-05 16:47:59 +03:00
|
|
|
{
|
1999-12-12 14:11:15 +03:00
|
|
|
struct tcphdr *tcp, *tcp2;
|
2000-05-03 15:12:03 +04:00
|
|
|
int tlen = 0, hlen;
|
1997-01-05 16:47:59 +03:00
|
|
|
struct mbuf *m;
|
2000-05-03 15:12:03 +04:00
|
|
|
#ifdef USE_INET6
|
|
|
|
ip6_t *ip6, *oip6 = (ip6_t *)oip;
|
|
|
|
#endif
|
1997-11-14 15:40:06 +03:00
|
|
|
ip_t *ip;
|
1997-01-05 16:47:59 +03:00
|
|
|
|
1999-12-12 14:11:15 +03:00
|
|
|
tcp = (struct tcphdr *)fin->fin_dp;
|
|
|
|
if (tcp->th_flags & TH_RST)
|
1997-01-05 16:47:59 +03:00
|
|
|
return -1; /* feedback loop */
|
1997-10-30 19:08:54 +03:00
|
|
|
# if (BSD < 199306) || defined(__sgi)
|
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);
|
1997-03-29 03:54:55 +03:00
|
|
|
# endif
|
1999-12-12 14:11:15 +03:00
|
|
|
if (m == NULL)
|
|
|
|
return ENOBUFS;
|
1997-01-05 16:47:59 +03:00
|
|
|
if (m == NULL)
|
|
|
|
return -1;
|
|
|
|
|
2002-03-14 15:32:36 +03:00
|
|
|
tlen = fin->fin_dlen - (tcp->th_off << 2) +
|
2001-03-26 10:11:46 +04:00
|
|
|
((tcp->th_flags & TH_SYN) ? 1 : 0) +
|
|
|
|
((tcp->th_flags & TH_FIN) ? 1 : 0);
|
|
|
|
|
2000-05-03 15:12:03 +04:00
|
|
|
#ifdef USE_INET6
|
|
|
|
hlen = (fin->fin_v == 6) ? sizeof(ip6_t) : sizeof(ip_t);
|
|
|
|
#else
|
|
|
|
hlen = sizeof(ip_t);
|
|
|
|
#endif
|
|
|
|
m->m_len = sizeof(*tcp2) + hlen;
|
1997-03-29 03:54:55 +03:00
|
|
|
# if BSD >= 199306
|
1999-12-12 14:11:15 +03:00
|
|
|
m->m_data += max_linkhdr;
|
|
|
|
m->m_pkthdr.len = m->m_len;
|
1997-01-05 16:47:59 +03:00
|
|
|
m->m_pkthdr.rcvif = (struct ifnet *)0;
|
1997-03-29 03:54:55 +03:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
ip = mtod(m, struct ip *);
|
2000-05-03 15:12:03 +04:00
|
|
|
# ifdef USE_INET6
|
|
|
|
ip6 = (ip6_t *)ip;
|
|
|
|
# endif
|
2000-05-21 22:47:00 +04:00
|
|
|
bzero((char *)ip, sizeof(*tcp2) + hlen);
|
2000-05-03 15:12:03 +04:00
|
|
|
tcp2 = (struct tcphdr *)((char *)ip + hlen);
|
1999-12-12 14:11:15 +03:00
|
|
|
|
|
|
|
tcp2->th_sport = tcp->th_dport;
|
2000-05-03 15:12:03 +04:00
|
|
|
tcp2->th_dport = tcp->th_sport;
|
2001-03-26 10:11:46 +04:00
|
|
|
if (tcp->th_flags & TH_ACK) {
|
|
|
|
tcp2->th_seq = tcp->th_ack;
|
|
|
|
tcp2->th_flags = TH_RST;
|
|
|
|
} else {
|
|
|
|
tcp2->th_ack = ntohl(tcp->th_seq);
|
|
|
|
tcp2->th_ack += tlen;
|
|
|
|
tcp2->th_ack = htonl(tcp2->th_ack);
|
|
|
|
tcp2->th_flags = TH_RST|TH_ACK;
|
|
|
|
}
|
1999-12-12 14:11:15 +03:00
|
|
|
tcp2->th_off = sizeof(*tcp2) >> 2;
|
2000-05-03 15:12:03 +04:00
|
|
|
# ifdef USE_INET6
|
|
|
|
if (fin->fin_v == 6) {
|
|
|
|
ip6->ip6_plen = htons(sizeof(struct tcphdr));
|
|
|
|
ip6->ip6_nxt = IPPROTO_TCP;
|
|
|
|
ip6->ip6_src = oip6->ip6_dst;
|
|
|
|
ip6->ip6_dst = oip6->ip6_src;
|
|
|
|
tcp2->th_sum = in6_cksum(m, IPPROTO_TCP,
|
|
|
|
sizeof(*ip6), sizeof(*tcp2));
|
2002-01-24 11:21:30 +03:00
|
|
|
return send_ip(oip, fin, &m);
|
2000-05-03 15:12:03 +04:00
|
|
|
}
|
|
|
|
# endif
|
|
|
|
ip->ip_p = IPPROTO_TCP;
|
|
|
|
ip->ip_len = htons(sizeof(struct tcphdr));
|
|
|
|
ip->ip_src.s_addr = oip->ip_dst.s_addr;
|
|
|
|
ip->ip_dst.s_addr = oip->ip_src.s_addr;
|
|
|
|
tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2));
|
2000-05-23 10:07:42 +04:00
|
|
|
ip->ip_len = hlen + sizeof(*tcp2);
|
2002-01-24 11:21:30 +03:00
|
|
|
return send_ip(oip, fin, &m);
|
1999-12-12 14:11:15 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-01-24 11:21:30 +03:00
|
|
|
/*
|
|
|
|
* Send an IP(v4/v6) datagram out into the network
|
|
|
|
*/
|
|
|
|
static int send_ip(oip, fin, mp)
|
2000-05-03 15:12:03 +04:00
|
|
|
ip_t *oip;
|
|
|
|
fr_info_t *fin;
|
2002-01-24 11:21:30 +03:00
|
|
|
struct mbuf **mp;
|
1999-12-12 14:11:15 +03:00
|
|
|
{
|
2002-01-24 11:21:30 +03:00
|
|
|
struct mbuf *m = *mp;
|
2002-09-19 12:08:14 +04:00
|
|
|
int error, hlen;
|
|
|
|
fr_info_t frn;
|
2000-05-03 15:12:03 +04:00
|
|
|
ip_t *ip;
|
|
|
|
|
2002-09-19 12:08:14 +04:00
|
|
|
bzero((char *)&frn, sizeof(frn));
|
|
|
|
frn.fin_ifp = fin->fin_ifp;
|
|
|
|
frn.fin_v = fin->fin_v;
|
|
|
|
frn.fin_out = fin->fin_out;
|
|
|
|
frn.fin_mp = fin->fin_mp;
|
2002-01-24 11:21:30 +03:00
|
|
|
|
2000-05-03 15:12:03 +04:00
|
|
|
ip = mtod(m, ip_t *);
|
2002-09-19 12:08:14 +04:00
|
|
|
hlen = sizeof(*ip);
|
1997-01-05 16:47:59 +03:00
|
|
|
|
2000-05-03 15:12:03 +04:00
|
|
|
ip->ip_v = fin->fin_v;
|
|
|
|
if (ip->ip_v == 4) {
|
|
|
|
ip->ip_hl = (sizeof(*oip) >> 2);
|
|
|
|
ip->ip_v = IPVERSION;
|
|
|
|
ip->ip_tos = oip->ip_tos;
|
|
|
|
ip->ip_id = oip->ip_id;
|
2002-09-19 12:08:14 +04:00
|
|
|
|
|
|
|
# if defined(__NetBSD__) || defined(__OpenBSD__)
|
|
|
|
if (ip_mtudisc != 0)
|
|
|
|
ip->ip_off = IP_DF;
|
|
|
|
# else
|
|
|
|
# if defined(__sgi)
|
|
|
|
if (ip->ip_p == IPPROTO_TCP && tcp_mtudisc != 0)
|
|
|
|
ip->ip_off = IP_DF;
|
|
|
|
# endif
|
|
|
|
# endif
|
|
|
|
|
1997-10-30 19:08:54 +03:00
|
|
|
# if (BSD < 199306) || defined(__sgi)
|
2000-05-03 15:12:03 +04:00
|
|
|
ip->ip_ttl = tcp_ttl;
|
1997-03-29 03:54:55 +03:00
|
|
|
# else
|
2000-05-03 15:12:03 +04:00
|
|
|
ip->ip_ttl = ip_defttl;
|
1997-03-29 03:54:55 +03:00
|
|
|
# endif
|
2000-05-03 15:12:03 +04:00
|
|
|
ip->ip_sum = 0;
|
2002-09-19 12:08:14 +04:00
|
|
|
frn.fin_dp = (char *)(ip + 1);
|
2000-05-03 15:12:03 +04:00
|
|
|
}
|
|
|
|
# ifdef USE_INET6
|
|
|
|
else if (ip->ip_v == 6) {
|
|
|
|
ip6_t *ip6 = (ip6_t *)ip;
|
1997-01-05 16:47:59 +03:00
|
|
|
|
2002-09-19 12:08:14 +04:00
|
|
|
hlen = sizeof(*ip6);
|
2000-05-03 15:12:03 +04:00
|
|
|
ip6->ip6_hlim = 127;
|
2002-09-19 12:08:14 +04:00
|
|
|
frn.fin_dp = (char *)(ip6 + 1);
|
2000-05-03 15:12:03 +04:00
|
|
|
}
|
|
|
|
# endif
|
|
|
|
# ifdef IPSEC
|
|
|
|
m->m_pkthdr.rcvif = NULL;
|
|
|
|
# endif
|
2002-09-19 12:08:14 +04:00
|
|
|
|
|
|
|
fr_makefrip(hlen, ip, &frn);
|
|
|
|
|
|
|
|
error = ipfr_fastroute(m, mp, &frn, NULL);
|
2002-01-24 11:21:30 +03:00
|
|
|
return error;
|
1999-12-12 14:11:15 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-05-23 10:07:42 +04:00
|
|
|
int send_icmp_err(oip, type, fin, dst)
|
1999-12-12 14:11:15 +03:00
|
|
|
ip_t *oip;
|
2000-05-23 10:07:42 +04:00
|
|
|
int type;
|
2000-05-03 15:12:03 +04:00
|
|
|
fr_info_t *fin;
|
|
|
|
int dst;
|
1999-12-12 14:11:15 +03:00
|
|
|
{
|
2000-05-23 10:07:42 +04:00
|
|
|
int err, hlen = 0, xtra = 0, iclen, ohlen = 0, avail, code;
|
2002-01-24 11:21:30 +03:00
|
|
|
u_short shlen, slen = 0, soff = 0;
|
2000-05-03 15:12:03 +04:00
|
|
|
struct in_addr dst4;
|
1999-12-12 14:11:15 +03:00
|
|
|
struct icmp *icmp;
|
|
|
|
struct mbuf *m;
|
2000-05-03 15:12:03 +04:00
|
|
|
void *ifp;
|
|
|
|
#ifdef USE_INET6
|
|
|
|
ip6_t *ip6, *oip6 = (ip6_t *)oip;
|
|
|
|
struct in6_addr dst6;
|
|
|
|
#endif
|
|
|
|
ip_t *ip;
|
|
|
|
|
|
|
|
if ((type < 0) || (type > ICMP_MAXTYPE))
|
|
|
|
return -1;
|
1999-12-12 14:11:15 +03:00
|
|
|
|
2000-05-23 10:07:42 +04:00
|
|
|
code = fin->fin_icode;
|
2000-05-03 15:12:03 +04:00
|
|
|
#ifdef USE_INET6
|
|
|
|
if ((code < 0) || (code > sizeof(icmptoicmp6unreach)/sizeof(int)))
|
|
|
|
return -1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
avail = 0;
|
|
|
|
m = NULL;
|
|
|
|
ifp = fin->fin_ifp;
|
|
|
|
if (fin->fin_v == 4) {
|
2000-06-12 14:28:20 +04:00
|
|
|
if ((oip->ip_p == IPPROTO_ICMP) &&
|
|
|
|
!(fin->fin_fi.fi_fl & FI_SHORT))
|
|
|
|
switch (ntohs(fin->fin_data[0]) >> 8)
|
|
|
|
{
|
|
|
|
case ICMP_ECHO :
|
|
|
|
case ICMP_TSTAMP :
|
|
|
|
case ICMP_IREQ :
|
|
|
|
case ICMP_MASKREQ :
|
|
|
|
break;
|
|
|
|
default :
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1999-12-12 14:11:15 +03:00
|
|
|
# if (BSD < 199306) || defined(__sgi)
|
2000-05-03 15:12:03 +04:00
|
|
|
avail = MLEN;
|
|
|
|
m = m_get(M_DONTWAIT, MT_HEADER);
|
1999-12-12 14:11:15 +03:00
|
|
|
# else
|
2000-05-03 15:12:03 +04:00
|
|
|
avail = MHLEN;
|
|
|
|
m = m_gethdr(M_DONTWAIT, MT_HEADER);
|
1999-12-12 14:11:15 +03:00
|
|
|
# endif
|
2000-05-03 15:12:03 +04:00
|
|
|
if (m == NULL)
|
|
|
|
return ENOBUFS;
|
|
|
|
|
|
|
|
if (dst == 0) {
|
|
|
|
if (fr_ifpaddr(4, ifp, &dst4) == -1)
|
|
|
|
return -1;
|
|
|
|
} else
|
|
|
|
dst4.s_addr = oip->ip_dst.s_addr;
|
|
|
|
|
|
|
|
hlen = sizeof(ip_t);
|
|
|
|
ohlen = oip->ip_hl << 2;
|
|
|
|
xtra = 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef USE_INET6
|
2000-05-23 10:07:42 +04:00
|
|
|
else if (fin->fin_v == 6) {
|
2000-05-03 15:12:03 +04:00
|
|
|
hlen = sizeof(ip6_t);
|
|
|
|
ohlen = sizeof(ip6_t);
|
|
|
|
type = icmptoicmp6types[type];
|
|
|
|
if (type == ICMP6_DST_UNREACH)
|
|
|
|
code = icmptoicmp6unreach[code];
|
|
|
|
|
|
|
|
MGETHDR(m, M_DONTWAIT, MT_HEADER);
|
|
|
|
if (!m)
|
|
|
|
return ENOBUFS;
|
|
|
|
|
|
|
|
MCLGET(m, M_DONTWAIT);
|
2000-08-10 01:00:39 +04:00
|
|
|
if ((m->m_flags & M_EXT) == 0) {
|
|
|
|
m_freem(m);
|
2000-05-03 15:12:03 +04:00
|
|
|
return ENOBUFS;
|
2000-08-10 01:00:39 +04:00
|
|
|
}
|
2001-03-26 10:11:46 +04:00
|
|
|
# ifdef M_TRAILINGSPACE
|
|
|
|
m->m_len = 0;
|
|
|
|
avail = M_TRAILINGSPACE(m);
|
|
|
|
# else
|
2000-05-03 15:12:03 +04:00
|
|
|
avail = (m->m_flags & M_EXT) ? MCLBYTES : MHLEN;
|
2001-03-26 10:11:46 +04:00
|
|
|
# endif
|
2000-05-03 15:12:03 +04:00
|
|
|
xtra = MIN(ntohs(oip6->ip6_plen) + sizeof(ip6_t),
|
|
|
|
avail - hlen - sizeof(*icmp) - max_linkhdr);
|
|
|
|
if (dst == 0) {
|
|
|
|
if (fr_ifpaddr(6, ifp, (struct in_addr *)&dst6) == -1)
|
|
|
|
return -1;
|
|
|
|
} else
|
|
|
|
dst6 = oip6->ip6_dst;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
iclen = hlen + sizeof(*icmp);
|
1999-12-12 14:11:15 +03:00
|
|
|
# if BSD >= 199306
|
2000-05-03 15:12:03 +04:00
|
|
|
avail -= (max_linkhdr + iclen);
|
1999-12-12 14:11:15 +03:00
|
|
|
m->m_data += max_linkhdr;
|
|
|
|
m->m_pkthdr.rcvif = (struct ifnet *)0;
|
2000-05-03 15:12:03 +04:00
|
|
|
if (xtra > avail)
|
|
|
|
xtra = avail;
|
|
|
|
iclen += xtra;
|
|
|
|
m->m_pkthdr.len = iclen;
|
|
|
|
#else
|
|
|
|
avail -= (m->m_off + iclen);
|
|
|
|
if (xtra > avail)
|
|
|
|
xtra = avail;
|
|
|
|
iclen += xtra;
|
|
|
|
#endif
|
|
|
|
m->m_len = iclen;
|
|
|
|
ip = mtod(m, ip_t *);
|
|
|
|
icmp = (struct icmp *)((char *)ip + hlen);
|
|
|
|
bzero((char *)ip, iclen);
|
1999-12-12 14:11:15 +03:00
|
|
|
|
|
|
|
icmp->icmp_type = type;
|
2000-05-23 10:07:42 +04:00
|
|
|
icmp->icmp_code = fin->fin_icode;
|
1999-12-12 14:11:15 +03:00
|
|
|
icmp->icmp_cksum = 0;
|
2001-03-26 10:11:46 +04:00
|
|
|
#ifdef icmp_nextmtu
|
2000-08-22 20:02:16 +04:00
|
|
|
if (type == ICMP_UNREACH &&
|
|
|
|
fin->fin_icode == ICMP_UNREACH_NEEDFRAG && ifp)
|
|
|
|
icmp->icmp_nextmtu = htons(((struct ifnet *) ifp)->if_mtu);
|
2001-03-26 10:11:46 +04:00
|
|
|
#endif
|
|
|
|
|
2000-05-03 15:12:03 +04:00
|
|
|
if (avail) {
|
|
|
|
bcopy((char *)oip, (char *)&icmp->icmp_ip, MIN(ohlen, avail));
|
|
|
|
avail -= MIN(ohlen, avail);
|
|
|
|
}
|
1999-12-12 14:11:15 +03:00
|
|
|
|
2000-05-03 15:12:03 +04:00
|
|
|
#ifdef USE_INET6
|
|
|
|
ip6 = (ip6_t *)ip;
|
|
|
|
if (fin->fin_v == 6) {
|
|
|
|
ip6->ip6_flow = 0;
|
|
|
|
ip6->ip6_plen = htons(iclen - hlen);
|
|
|
|
ip6->ip6_nxt = IPPROTO_ICMPV6;
|
|
|
|
ip6->ip6_hlim = 0;
|
|
|
|
ip6->ip6_src = dst6;
|
|
|
|
ip6->ip6_dst = oip6->ip6_src;
|
|
|
|
if (avail)
|
|
|
|
bcopy((char *)oip + ohlen,
|
|
|
|
(char *)&icmp->icmp_ip + ohlen, avail);
|
|
|
|
icmp->icmp_cksum = in6_cksum(m, IPPROTO_ICMPV6,
|
|
|
|
sizeof(*ip6), iclen - hlen);
|
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
2002-01-24 11:21:30 +03:00
|
|
|
slen = oip->ip_len;
|
|
|
|
oip->ip_len = htons(oip->ip_len);
|
|
|
|
soff = oip->ip_off;
|
|
|
|
oip->ip_off = htons(ip->ip_off);
|
|
|
|
|
2000-05-03 15:12:03 +04:00
|
|
|
ip->ip_src.s_addr = dst4.s_addr;
|
|
|
|
ip->ip_dst.s_addr = oip->ip_src.s_addr;
|
|
|
|
|
|
|
|
if (avail > 8)
|
|
|
|
avail = 8;
|
|
|
|
if (avail)
|
|
|
|
bcopy((char *)oip + ohlen,
|
|
|
|
(char *)&icmp->icmp_ip + ohlen, avail);
|
|
|
|
icmp->icmp_cksum = ipf_cksum((u_short *)icmp,
|
|
|
|
sizeof(*icmp) + 8);
|
2000-05-23 10:07:42 +04:00
|
|
|
ip->ip_len = iclen;
|
|
|
|
ip->ip_p = IPPROTO_ICMP;
|
1999-12-12 14:11:15 +03:00
|
|
|
}
|
2002-01-24 11:21:30 +03:00
|
|
|
|
|
|
|
shlen = fin->fin_hlen;
|
|
|
|
fin->fin_hlen = hlen;
|
|
|
|
err = send_ip(oip, fin, &m);
|
|
|
|
fin->fin_hlen = shlen;
|
|
|
|
#ifdef USE_INET6
|
|
|
|
if (fin->fin_v == 4)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
oip->ip_len = slen;
|
|
|
|
oip->ip_off = soff;
|
|
|
|
}
|
2000-05-03 15:12:03 +04:00
|
|
|
return err;
|
1997-01-05 16:47:59 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-03-14 15:32:36 +03:00
|
|
|
# if !defined(IPFILTER_LKM) && !defined(__sgi) && \
|
|
|
|
(!defined(__FreeBSD_version) || (__FreeBSD_version < 300000))
|
1997-10-30 19:08:54 +03:00
|
|
|
# if (BSD < 199306)
|
1997-05-25 16:40:11 +04:00
|
|
|
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
|
|
|
{
|
2002-01-24 11:21:30 +03:00
|
|
|
|
1997-09-21 22:00:54 +04:00
|
|
|
# if defined(__NetBSD__)
|
2002-01-24 11:21:30 +03:00
|
|
|
if (ipl_enable() != 0)
|
1997-09-21 22:00:54 +04:00
|
|
|
# else
|
2002-01-24 11:21:30 +03:00
|
|
|
if (iplattach() != 0)
|
1997-09-21 22:00:54 +04:00
|
|
|
# endif
|
2002-01-24 11:21:30 +03:00
|
|
|
{
|
1999-12-12 14:11:15 +03:00
|
|
|
printf("IP Filter failed to attach\n");
|
|
|
|
}
|
1997-01-05 16:47:59 +03:00
|
|
|
ip_init();
|
|
|
|
}
|
2002-01-24 11:23:40 +03:00
|
|
|
# endif /* ! __NetBSD__ */
|
1997-03-29 03:54:55 +03:00
|
|
|
|
1997-01-05 16:47:59 +03:00
|
|
|
|
2002-01-24 11:21:30 +03:00
|
|
|
/*
|
|
|
|
* Return the length of the entire mbuf.
|
|
|
|
*/
|
1997-10-30 19:08:54 +03:00
|
|
|
size_t mbufchainlen(m0)
|
2002-01-24 11:23:40 +03:00
|
|
|
register struct mbuf *m0;
|
1997-10-30 19:08:54 +03:00
|
|
|
{
|
2002-01-24 11:21:30 +03:00
|
|
|
#if BSD >= 199306
|
|
|
|
return m0->m_pkthdr.len;
|
|
|
|
#else
|
|
|
|
register size_t len = 0;
|
1997-10-30 19:08:54 +03:00
|
|
|
|
|
|
|
for (; m0; m0 = m0->m_next)
|
|
|
|
len += m0->m_len;
|
|
|
|
return len;
|
2002-01-24 11:21:30 +03:00
|
|
|
#endif
|
1997-10-30 19:08:54 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-01-24 11:21:30 +03:00
|
|
|
int ipfr_fastroute(m0, mpp, fin, fdp)
|
|
|
|
struct mbuf *m0, **mpp;
|
1997-01-05 16:47:59 +03:00
|
|
|
fr_info_t *fin;
|
|
|
|
frdest_t *fdp;
|
|
|
|
{
|
2002-01-24 11:23:40 +03:00
|
|
|
register struct ip *ip, *mhip;
|
|
|
|
register struct mbuf *m = m0;
|
|
|
|
register struct route *ro;
|
2000-05-23 10:07:42 +04:00
|
|
|
int len, off, error = 0, hlen, code;
|
|
|
|
struct ifnet *ifp, *sifp;
|
1997-01-05 16:47:59 +03:00
|
|
|
struct sockaddr_in *dst;
|
1999-12-12 14:11:15 +03:00
|
|
|
struct route iproute;
|
|
|
|
frentry_t *fr;
|
1997-01-05 16:47:59 +03:00
|
|
|
|
2002-01-24 11:21:30 +03:00
|
|
|
ip = NULL;
|
|
|
|
ro = NULL;
|
|
|
|
ifp = NULL;
|
|
|
|
ro = &iproute;
|
|
|
|
ro->ro_rt = NULL;
|
|
|
|
|
|
|
|
#ifdef USE_INET6
|
|
|
|
if (fin->fin_v == 6) {
|
|
|
|
error = ipfr_fastroute6(m0, mpp, fin, fdp);
|
|
|
|
if (error != 0)
|
|
|
|
goto bad;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
if (fin->fin_v == 6)
|
|
|
|
goto bad;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef M_WRITABLE
|
|
|
|
/*
|
|
|
|
* HOT FIX/KLUDGE:
|
|
|
|
*
|
|
|
|
* If the mbuf we're about to send is not writable (because of
|
|
|
|
* a cluster reference, for example) we'll need to make a copy
|
|
|
|
* of it since this routine modifies the contents.
|
|
|
|
*
|
|
|
|
* If you have non-crappy network hardware that can transmit data
|
|
|
|
* from the mbuf, rather than making a copy, this is gonna be a
|
|
|
|
* problem.
|
|
|
|
*/
|
|
|
|
if (M_WRITABLE(m) == 0) {
|
|
|
|
if ((m0 = m_dup(m, M_DONTWAIT)) != NULL) {
|
|
|
|
m_freem(*mpp);
|
|
|
|
*mpp = m0;
|
|
|
|
m = m0;
|
|
|
|
} else {
|
|
|
|
error = ENOBUFS;
|
|
|
|
m_freem(*mpp);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
hlen = fin->fin_hlen;
|
|
|
|
ip = mtod(m0, struct ip *);
|
|
|
|
|
2001-06-02 20:17:09 +04:00
|
|
|
#if defined(__NetBSD__) && defined(M_CSUM_IPv4)
|
|
|
|
/*
|
|
|
|
* Clear any in-bound checksum flags for this packet.
|
|
|
|
*/
|
2002-01-24 11:21:30 +03:00
|
|
|
# if (__NetBSD_Version__ > 105009999)
|
2001-06-02 20:17:09 +04:00
|
|
|
m0->m_pkthdr.csum_flags = 0;
|
2002-01-24 11:21:30 +03:00
|
|
|
# else
|
|
|
|
m0->m_pkthdr.csuminfo = 0;
|
|
|
|
# endif
|
2001-06-02 20:17:09 +04:00
|
|
|
#endif /* __NetBSD__ && M_CSUM_IPv4 */
|
|
|
|
|
1997-01-05 16:47:59 +03:00
|
|
|
/*
|
|
|
|
* Route packet.
|
|
|
|
*/
|
2002-09-19 12:08:14 +04:00
|
|
|
#ifdef __sgi
|
|
|
|
ROUTE_RDLOCK();
|
|
|
|
#endif
|
1997-01-05 16:47:59 +03:00
|
|
|
bzero((caddr_t)ro, sizeof (*ro));
|
|
|
|
dst = (struct sockaddr_in *)&ro->ro_dst;
|
|
|
|
dst->sin_family = AF_INET;
|
2002-01-24 11:21:30 +03:00
|
|
|
dst->sin_addr = ip->ip_dst;
|
1999-12-12 14:11:15 +03:00
|
|
|
|
|
|
|
fr = fin->fin_fr;
|
2002-01-24 11:21:30 +03:00
|
|
|
if (fdp != NULL)
|
2000-05-23 10:07:42 +04:00
|
|
|
ifp = fdp->fd_ifp;
|
2002-01-24 11:21:30 +03:00
|
|
|
else
|
2000-05-23 10:07:42 +04:00
|
|
|
ifp = fin->fin_ifp;
|
|
|
|
|
1999-12-12 14:11:15 +03:00
|
|
|
/*
|
|
|
|
* In case we're here due to "to <if>" being used with "keep state",
|
|
|
|
* check that we're going in the correct direction.
|
|
|
|
*/
|
|
|
|
if ((fr != NULL) && (fin->fin_rev != 0)) {
|
|
|
|
if ((ifp != NULL) && (fdp == &fr->fr_tif))
|
2002-01-24 11:21:30 +03:00
|
|
|
return 0;
|
|
|
|
} else if (fdp != NULL) {
|
|
|
|
if (fdp->fd_ip.s_addr != 0)
|
|
|
|
dst->sin_addr = fdp->fd_ip;
|
|
|
|
}
|
2000-05-23 10:07:42 +04:00
|
|
|
|
|
|
|
# if BSD >= 199306
|
1997-03-29 03:54:55 +03:00
|
|
|
dst->sin_len = sizeof(*dst);
|
1997-07-05 09:38:14 +04:00
|
|
|
# endif
|
1997-10-30 19:08:54 +03:00
|
|
|
# if (BSD >= 199306) && !defined(__NetBSD__) && !defined(__bsdi__) && \
|
|
|
|
!defined(__OpenBSD__)
|
1999-12-12 14:11:15 +03: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
|
2002-09-19 12:08:14 +04:00
|
|
|
|
|
|
|
#ifdef __sgi
|
|
|
|
ROUTE_UNLOCK();
|
|
|
|
#endif
|
|
|
|
|
1997-01-05 16:47:59 +03:00
|
|
|
if (!ifp) {
|
2000-05-23 10:07:42 +04:00
|
|
|
if (!fr || !(fr->fr_flags & FR_FASTROUTE)) {
|
1997-01-05 16:47:59 +03:00
|
|
|
error = -2;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
}
|
2002-01-24 11:21:30 +03:00
|
|
|
|
|
|
|
if ((ifp == NULL) && (ro->ro_rt != NULL))
|
|
|
|
ifp = ro->ro_rt->rt_ifp;
|
|
|
|
|
|
|
|
if ((ro->ro_rt == NULL) || (ifp == NULL)) {
|
|
|
|
if (in_localaddr(ip->ip_dst))
|
|
|
|
error = EHOSTUNREACH;
|
|
|
|
else
|
|
|
|
error = ENETUNREACH;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ro->ro_rt->rt_flags & RTF_GATEWAY) {
|
|
|
|
#if BSD >= 199306
|
|
|
|
dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway;
|
|
|
|
#else
|
|
|
|
dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
ro->ro_rt->rt_use++;
|
1997-01-05 16:47:59 +03:00
|
|
|
|
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
|
1998-11-22 18:17:18 +03:00
|
|
|
* NAT'd and counted.
|
1997-03-29 03:54:55 +03:00
|
|
|
*/
|
1998-11-22 18:17:18 +03:00
|
|
|
if (fin->fin_out == 0) {
|
2002-01-24 11:21:30 +03:00
|
|
|
sifp = fin->fin_ifp;
|
|
|
|
fin->fin_ifp = ifp;
|
1999-12-12 14:11:15 +03:00
|
|
|
fin->fin_out = 1;
|
1998-11-22 18:17:18 +03:00
|
|
|
if ((fin->fin_fr = ipacct[1][fr_active]) &&
|
1999-12-12 14:11:15 +03:00
|
|
|
(fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
|
2000-05-03 15:12:03 +04:00
|
|
|
ATOMIC_INCL(frstats[1].fr_acct);
|
1998-11-22 18:17:18 +03:00
|
|
|
}
|
|
|
|
fin->fin_fr = NULL;
|
2000-08-10 01:00:39 +04:00
|
|
|
if (!fr || !(fr->fr_flags & FR_RETMASK))
|
2000-05-23 10:07:42 +04:00
|
|
|
(void) fr_checkstate(ip, fin);
|
2000-08-10 01:00:39 +04:00
|
|
|
(void) ip_natout(ip, fin);
|
2002-01-24 11:21:30 +03:00
|
|
|
fin->fin_ifp = sifp;
|
1999-12-12 14:11:15 +03:00
|
|
|
} else
|
1997-03-29 03:54:55 +03:00
|
|
|
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) {
|
2002-01-24 11:21:30 +03:00
|
|
|
# ifndef sparc
|
2002-09-19 12:08:14 +04:00
|
|
|
# if (!defined(__FreeBSD__) && !(_BSDI_VERSION >= 199510)) && \
|
|
|
|
!(__NetBSD_Version__ >= 105110000)
|
1997-01-05 16:47:59 +03:00
|
|
|
ip->ip_id = htons(ip->ip_id);
|
2002-01-24 11:21:30 +03:00
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
ip->ip_len = htons(ip->ip_len);
|
|
|
|
ip->ip_off = htons(ip->ip_off);
|
2002-01-24 11:21:30 +03:00
|
|
|
# endif
|
2001-06-02 20:17:09 +04:00
|
|
|
# if defined(__NetBSD__) && defined(M_CSUM_IPv4)
|
2002-01-24 11:21:30 +03:00
|
|
|
# if (__NetBSD_Version__ > 105009999)
|
|
|
|
if (ifp->if_csum_flags_tx & IFCAP_CSUM_IPv4)
|
2001-06-02 20:17:09 +04:00
|
|
|
m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
|
|
|
|
else if (ip->ip_sum == 0)
|
|
|
|
ip->ip_sum = in_cksum(m, hlen);
|
2002-01-24 11:21:30 +03:00
|
|
|
# else
|
|
|
|
if (ifp->if_capabilities & IFCAP_CSUM_IPv4)
|
|
|
|
m->m_pkthdr.csuminfo |= M_CSUM_IPv4;
|
|
|
|
else if (ip->ip_sum == 0)
|
|
|
|
ip->ip_sum = in_cksum(m, hlen);
|
|
|
|
# endif
|
2001-06-02 20:17:09 +04:00
|
|
|
# else
|
1997-01-05 16:47:59 +03:00
|
|
|
if (!ip->ip_sum)
|
|
|
|
ip->ip_sum = in_cksum(m, hlen);
|
2001-06-02 20:17:09 +04:00
|
|
|
# endif /* __NetBSD__ && M_CSUM_IPv4 */
|
2002-03-14 15:32:36 +03:00
|
|
|
# if (BSD >= 199306) || (defined(IRIX) && (IRIX >= 605))
|
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;
|
|
|
|
}
|
2002-01-24 11:21:30 +03:00
|
|
|
|
1997-01-05 16:47:59 +03:00
|
|
|
/*
|
|
|
|
* 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;
|
2002-01-24 11:23:40 +03:00
|
|
|
struct mbuf **mnext = &m->m_act;
|
1997-01-05 16:47:59 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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) {
|
1999-12-12 14:11:15 +03:00
|
|
|
# ifdef MGETHDR
|
1998-11-26 00:13:58 +03:00
|
|
|
MGETHDR(m, M_DONTWAIT, MT_HEADER);
|
1999-12-12 14:11:15 +03:00
|
|
|
# else
|
|
|
|
MGET(m, M_DONTWAIT, MT_HEADER);
|
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
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;
|
|
|
|
}
|
1999-12-12 14:11:15 +03:00
|
|
|
# if BSD >= 199306
|
1999-08-26 06:15:35 +04:00
|
|
|
m->m_pkthdr.len = mhlen + len;
|
1999-12-12 14:11:15 +03:00
|
|
|
m->m_pkthdr.rcvif = NULL;
|
|
|
|
# endif
|
1997-01-05 16:47:59 +03:00
|
|
|
mhip->ip_off = htons((u_short)mhip->ip_off);
|
|
|
|
mhip->ip_sum = 0;
|
|
|
|
mhip->ip_sum = in_cksum(m, mhlen);
|
|
|
|
*mnext = m;
|
2002-01-24 11:23:40 +03:00
|
|
|
mnext = &m->m_act;
|
1997-01-05 16:47:59 +03:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* 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) {
|
2002-01-24 11:23:40 +03:00
|
|
|
m0 = m->m_act;
|
|
|
|
m->m_act = 0;
|
1997-01-05 16:47:59 +03:00
|
|
|
if (error == 0)
|
2002-03-14 15:32:36 +03:00
|
|
|
# if (BSD >= 199306) || (defined(IRIX) && (IRIX >= 605))
|
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);
|
|
|
|
}
|
2002-09-19 12:12:43 +04:00
|
|
|
}
|
1997-01-05 16:47:59 +03:00
|
|
|
done:
|
1997-10-30 19:08:54 +03:00
|
|
|
if (!error)
|
|
|
|
ipl_frouteok[0]++;
|
|
|
|
else
|
|
|
|
ipl_frouteok[1]++;
|
|
|
|
|
2002-01-24 11:21:30 +03:00
|
|
|
if (ro->ro_rt != NULL) {
|
1997-01-05 16:47:59 +03:00
|
|
|
RTFREE(ro->ro_rt);
|
2002-01-24 11:21:30 +03:00
|
|
|
}
|
|
|
|
*mpp = NULL;
|
|
|
|
return error;
|
1997-01-05 16:47:59 +03:00
|
|
|
bad:
|
2002-01-24 11:21:30 +03:00
|
|
|
if ((error == EMSGSIZE) && (fin->fin_v == 4)) {
|
2000-05-23 10:07:42 +04:00
|
|
|
sifp = fin->fin_ifp;
|
|
|
|
code = fin->fin_icode;
|
|
|
|
fin->fin_icode = ICMP_UNREACH_NEEDFRAG;
|
2000-05-03 15:12:03 +04:00
|
|
|
fin->fin_ifp = ifp;
|
2000-05-23 10:07:42 +04:00
|
|
|
(void) send_icmp_err(ip, ICMP_UNREACH, fin, 1);
|
|
|
|
fin->fin_ifp = sifp;
|
|
|
|
fin->fin_icode = code;
|
2000-05-03 15:12:03 +04:00
|
|
|
}
|
1997-01-05 16:47:59 +03:00
|
|
|
m_freem(m);
|
|
|
|
goto done;
|
|
|
|
}
|
2000-05-03 15:12:03 +04:00
|
|
|
|
|
|
|
|
2002-01-24 11:21:30 +03:00
|
|
|
/*
|
|
|
|
* Return true or false depending on whether the route to the
|
|
|
|
* given IP address uses the same interface as the one passed.
|
|
|
|
*/
|
2000-05-03 15:12:03 +04:00
|
|
|
int fr_verifysrc(ipa, ifp)
|
|
|
|
struct in_addr ipa;
|
|
|
|
void *ifp;
|
|
|
|
{
|
|
|
|
struct sockaddr_in *dst;
|
|
|
|
struct route iproute;
|
|
|
|
|
|
|
|
bzero((char *)&iproute, sizeof(iproute));
|
|
|
|
dst = (struct sockaddr_in *)&iproute.ro_dst;
|
2002-01-24 11:21:30 +03:00
|
|
|
# if (BSD >= 199306)
|
|
|
|
dst->sin_len = sizeof(*dst);
|
|
|
|
# endif
|
2000-05-03 15:12:03 +04:00
|
|
|
dst->sin_family = AF_INET;
|
|
|
|
dst->sin_addr = ipa;
|
|
|
|
# if (BSD >= 199306) && !defined(__NetBSD__) && !defined(__bsdi__) && \
|
|
|
|
!defined(__OpenBSD__)
|
|
|
|
# ifdef RTF_CLONING
|
|
|
|
rtalloc_ign(&iproute, RTF_CLONING);
|
|
|
|
# else
|
|
|
|
rtalloc_ign(&iproute, RTF_PRCLONING);
|
|
|
|
# endif
|
|
|
|
# else
|
|
|
|
rtalloc(&iproute);
|
|
|
|
# endif
|
|
|
|
if (iproute.ro_rt == NULL)
|
|
|
|
return 0;
|
|
|
|
return (ifp == iproute.ro_rt->rt_ifp);
|
|
|
|
}
|
|
|
|
|
2002-01-24 11:21:30 +03:00
|
|
|
|
|
|
|
# ifdef USE_GETIFNAME
|
|
|
|
char *
|
|
|
|
get_ifname(ifp)
|
|
|
|
struct ifnet *ifp;
|
|
|
|
{
|
|
|
|
static char workbuf[64];
|
|
|
|
|
|
|
|
sprintf(workbuf, "%s%d", ifp->if_name, ifp->if_unit);
|
|
|
|
return workbuf;
|
|
|
|
}
|
|
|
|
# endif
|
|
|
|
|
|
|
|
|
|
|
|
# if defined(USE_INET6)
|
|
|
|
/*
|
|
|
|
* This is the IPv6 specific fastroute code. It doesn't clean up the mbuf's
|
|
|
|
* or ensure that it is an IPv6 packet that is being forwarded, those are
|
|
|
|
* expected to be done by the called (ipfr_fastroute).
|
|
|
|
*/
|
|
|
|
static int ipfr_fastroute6(m0, mpp, fin, fdp)
|
|
|
|
struct mbuf *m0, **mpp;
|
|
|
|
fr_info_t *fin;
|
|
|
|
frdest_t *fdp;
|
|
|
|
{
|
|
|
|
struct route_in6 ip6route;
|
|
|
|
struct sockaddr_in6 *dst6;
|
|
|
|
struct route_in6 *ro;
|
|
|
|
struct ifnet *ifp;
|
|
|
|
frentry_t *fr;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
ifp = NULL;
|
|
|
|
ro = &ip6route;
|
|
|
|
fr = fin->fin_fr;
|
|
|
|
bzero((caddr_t)ro, sizeof(*ro));
|
|
|
|
dst6 = (struct sockaddr_in6 *)&ro->ro_dst;
|
|
|
|
dst6->sin6_family = AF_INET6;
|
|
|
|
dst6->sin6_len = sizeof(struct sockaddr_in6);
|
|
|
|
dst6->sin6_addr = fin->fin_fi.fi_src.in6;
|
|
|
|
|
|
|
|
if (fdp != NULL)
|
|
|
|
ifp = fdp->fd_ifp;
|
|
|
|
|
|
|
|
if ((fr != NULL) && (fin->fin_rev != 0)) {
|
|
|
|
if ((ifp != NULL) && (fdp == &fr->fr_tif))
|
|
|
|
return 0;
|
|
|
|
} else if (fdp != NULL) {
|
|
|
|
if (IP6_NOTZERO(&fdp->fd_ip6))
|
|
|
|
dst6->sin6_addr = fdp->fd_ip6.in6;
|
|
|
|
}
|
|
|
|
if ((ifp == NULL) && ((fr == NULL) || !(fr->fr_flags & FR_FASTROUTE)))
|
|
|
|
return -2;
|
|
|
|
|
|
|
|
rtalloc((struct route *)ro);
|
|
|
|
|
|
|
|
if ((ifp == NULL) && (ro->ro_rt != NULL))
|
|
|
|
ifp = ro->ro_rt->rt_ifp;
|
|
|
|
|
|
|
|
if ((ro->ro_rt == NULL) || (ifp == NULL) ||
|
|
|
|
(ifp != ro->ro_rt->rt_ifp)) {
|
|
|
|
error = EHOSTUNREACH;
|
|
|
|
} else {
|
|
|
|
if (ro->ro_rt->rt_flags & RTF_GATEWAY)
|
|
|
|
dst6 = (struct sockaddr_in6 *)ro->ro_rt->rt_gateway;
|
|
|
|
ro->ro_rt->rt_use++;
|
|
|
|
|
2002-05-29 11:53:39 +04:00
|
|
|
if (m0->m_pkthdr.len <= IN6_LINKMTU(ifp))
|
2002-01-24 11:21:30 +03:00
|
|
|
error = nd6_output(ifp, fin->fin_ifp, m0, dst6,
|
|
|
|
ro->ro_rt);
|
|
|
|
else
|
|
|
|
error = EMSGSIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ro->ro_rt != NULL) {
|
|
|
|
RTFREE(ro->ro_rt);
|
|
|
|
}
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
# endif
|
1997-03-29 03:54:55 +03:00
|
|
|
#else /* #ifdef _KERNEL */
|
|
|
|
|
|
|
|
|
2002-03-14 15:32:36 +03:00
|
|
|
# if defined(__sgi) && (IRIX < 605)
|
1997-10-30 19:08:54 +03:00
|
|
|
static int no_output __P((struct ifnet *ifp, struct mbuf *m,
|
|
|
|
struct sockaddr *s))
|
1999-12-12 14:11:15 +03:00
|
|
|
# else
|
1997-03-29 03:54:55 +03:00
|
|
|
static int no_output __P((struct ifnet *ifp, struct mbuf *m,
|
|
|
|
struct sockaddr *s, struct rtentry *rt))
|
1999-12-12 14:11:15 +03:00
|
|
|
# endif
|
1997-03-29 03:54:55 +03:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# ifdef __STDC__
|
2002-03-14 15:32:36 +03:00
|
|
|
# if defined(__sgi) && (IRIX < 605)
|
1997-10-30 19:08:54 +03:00
|
|
|
static int write_output __P((struct ifnet *ifp, struct mbuf *m,
|
|
|
|
struct sockaddr *s))
|
1999-12-12 14:11:15 +03:00
|
|
|
# else
|
1997-03-29 03:54:55 +03:00
|
|
|
static int write_output __P((struct ifnet *ifp, struct mbuf *m,
|
|
|
|
struct sockaddr *s, struct rtentry *rt))
|
1999-12-12 14:11:15 +03:00
|
|
|
# endif
|
1997-03-29 03:54:55 +03:00
|
|
|
{
|
|
|
|
ip_t *ip = (ip_t *)m;
|
|
|
|
# else
|
|
|
|
static int write_output(ifp, ip)
|
|
|
|
struct ifnet *ifp;
|
|
|
|
ip_t *ip;
|
|
|
|
{
|
|
|
|
# endif
|
|
|
|
char fname[32];
|
1999-12-12 14:11:15 +03:00
|
|
|
int fd;
|
1997-03-29 03:54:55 +03:00
|
|
|
|
1997-10-30 19:08:54 +03:00
|
|
|
# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
|
|
|
|
(defined(OpenBSD) && (OpenBSD >= 199603))
|
2002-01-24 11:21:30 +03:00
|
|
|
sprintf(fname, "%s", ifp->if_xname);
|
1997-07-05 09:38:14 +04:00
|
|
|
# else
|
2002-01-24 11:21:30 +03:00
|
|
|
sprintf(fname, "%s%d", ifp->if_name, ifp->if_unit);
|
1997-07-05 09:38:14 +04:00
|
|
|
# endif
|
1999-12-12 14:11:15 +03:00
|
|
|
fd = open(fname, O_WRONLY|O_APPEND);
|
|
|
|
if (fd == -1) {
|
|
|
|
perror("open");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
write(fd, (char *)ip, ntohs(ip->ip_len));
|
|
|
|
close(fd);
|
1997-07-05 09:38:14 +04:00
|
|
|
return 0;
|
1997-03-29 03:54:55 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-01-24 11:21:30 +03:00
|
|
|
char *get_ifname(ifp)
|
|
|
|
struct ifnet *ifp;
|
1997-03-29 03:54:55 +03:00
|
|
|
{
|
1997-10-30 19:08:54 +03:00
|
|
|
# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
|
2002-01-24 11:21:30 +03:00
|
|
|
(defined(OpenBSD) && (OpenBSD >= 199603))
|
|
|
|
return ifp->if_xname;
|
1997-07-05 09:38:14 +04:00
|
|
|
# else
|
2002-03-14 15:32:36 +03:00
|
|
|
static char fullifname[LIFNAMSIZ];
|
|
|
|
|
|
|
|
sprintf(fullifname, "%s%d", ifp->if_name, ifp->if_unit);
|
|
|
|
return fullifname;
|
1997-07-05 09:38:14 +04:00
|
|
|
# endif
|
2002-01-24 11:21:30 +03:00
|
|
|
}
|
1997-03-29 03:54:55 +03:00
|
|
|
|
2001-05-12 23:21:57 +04:00
|
|
|
|
2002-01-24 11:21:30 +03:00
|
|
|
struct ifnet *get_unit(ifname, v)
|
|
|
|
char *ifname;
|
|
|
|
int v;
|
|
|
|
{
|
|
|
|
struct ifnet *ifp, **ifa, **old_ifneta;
|
2001-05-12 23:21:57 +04:00
|
|
|
|
2002-01-24 11:21:30 +03:00
|
|
|
for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
|
|
|
|
# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
|
|
|
|
(defined(OpenBSD) && (OpenBSD >= 199603))
|
|
|
|
if (!strncmp(ifname, ifp->if_xname, sizeof(ifp->if_xname)))
|
|
|
|
# else
|
2002-03-14 15:32:36 +03:00
|
|
|
char fullname[LIFNAMSIZ];
|
|
|
|
|
|
|
|
sprintf(fullname, "%s%d", ifp->if_name, ifp->if_unit);
|
|
|
|
if (!strcmp(ifname, fullname))
|
2002-01-24 11:21:30 +03:00
|
|
|
# endif
|
|
|
|
return ifp;
|
1997-03-29 03:54:55 +03:00
|
|
|
}
|
2001-05-12 23:21:57 +04:00
|
|
|
|
2002-01-24 11:21:30 +03:00
|
|
|
if (!ifneta) {
|
|
|
|
ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2);
|
|
|
|
if (!ifneta)
|
|
|
|
return NULL;
|
|
|
|
ifneta[1] = NULL;
|
|
|
|
ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp));
|
|
|
|
if (!ifneta[0]) {
|
|
|
|
free(ifneta);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
nifs = 1;
|
|
|
|
} else {
|
|
|
|
old_ifneta = ifneta;
|
|
|
|
nifs++;
|
|
|
|
ifneta = (struct ifnet **)realloc(ifneta,
|
|
|
|
(nifs + 1) * sizeof(*ifa));
|
|
|
|
if (!ifneta) {
|
|
|
|
free(old_ifneta);
|
|
|
|
nifs = 0;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
ifneta[nifs] = NULL;
|
|
|
|
ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp));
|
|
|
|
if (!ifneta[nifs - 1]) {
|
|
|
|
nifs--;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ifp = ifneta[nifs - 1];
|
1997-03-29 03:54:55 +03:00
|
|
|
|
1997-10-30 19:08:54 +03:00
|
|
|
# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
|
2002-01-24 11:21:30 +03:00
|
|
|
(defined(OpenBSD) && (OpenBSD >= 199603))
|
|
|
|
strncpy(ifp->if_xname, ifname, sizeof(ifp->if_xname));
|
1997-07-05 09:38:14 +04:00
|
|
|
# else
|
2002-01-24 11:21:30 +03:00
|
|
|
ifp->if_name = strdup(ifname);
|
|
|
|
|
2002-03-14 15:32:36 +03:00
|
|
|
ifname = ifp->if_name;
|
2002-01-24 11:21:30 +03:00
|
|
|
while (*ifname && !isdigit(*ifname))
|
|
|
|
ifname++;
|
2002-03-14 15:32:36 +03:00
|
|
|
if (*ifname && isdigit(*ifname)) {
|
2002-01-24 11:21:30 +03:00
|
|
|
ifp->if_unit = atoi(ifname);
|
2002-03-14 15:32:36 +03:00
|
|
|
*ifname = '\0';
|
|
|
|
} else
|
1997-03-29 03:54:55 +03:00
|
|
|
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()
|
|
|
|
{
|
|
|
|
struct ifnet *ifp, **ifa;
|
|
|
|
char fname[32];
|
1999-12-12 14:11:15 +03:00
|
|
|
int fd;
|
|
|
|
|
1997-10-30 19:08:54 +03:00
|
|
|
# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
|
|
|
|
(defined(OpenBSD) && (OpenBSD >= 199603))
|
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);
|
1999-12-12 14:11:15 +03:00
|
|
|
fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
|
|
|
|
if (fd == -1)
|
|
|
|
perror("open");
|
|
|
|
else
|
|
|
|
close(fd);
|
1997-03-29 03:54:55 +03:00
|
|
|
}
|
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);
|
1999-12-12 14:11:15 +03:00
|
|
|
fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
|
|
|
|
if (fd == -1)
|
|
|
|
perror("open");
|
|
|
|
else
|
|
|
|
close(fd);
|
1997-03-29 03:54:55 +03:00
|
|
|
}
|
1997-07-05 09:38:14 +04:00
|
|
|
# endif
|
1997-03-29 03:54:55 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-01-24 11:21:30 +03:00
|
|
|
int send_reset(ip, fin)
|
1997-03-29 03:54:55 +03:00
|
|
|
ip_t *ip;
|
2002-01-24 11:21:30 +03:00
|
|
|
fr_info_t *fin;
|
1997-03-29 03:54:55 +03:00
|
|
|
{
|
|
|
|
verbose("- TCP RST sent\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-01-24 11:21:30 +03:00
|
|
|
int send_icmp_err(ip, code, fin, dst)
|
1997-03-29 03:54:55 +03:00
|
|
|
ip_t *ip;
|
2002-01-24 11:21:30 +03:00
|
|
|
int code;
|
|
|
|
fr_info_t *fin;
|
|
|
|
int dst;
|
1997-03-29 03:54:55 +03:00
|
|
|
{
|
2002-09-19 12:08:14 +04:00
|
|
|
verbose("- ICMP UNREACHABLE sent\n");
|
1997-03-29 03:54:55 +03:00
|
|
|
return 0;
|
|
|
|
}
|
1999-12-12 14:11:15 +03:00
|
|
|
|
|
|
|
|
|
|
|
void frsync()
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2002-03-14 15:32:36 +03:00
|
|
|
|
|
|
|
void m_copydata(m, off, len, cp)
|
|
|
|
mb_t *m;
|
|
|
|
int off, len;
|
|
|
|
caddr_t cp;
|
|
|
|
{
|
|
|
|
bcopy((char *)m + off, cp, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int ipfuiomove(buf, len, rwflag, uio)
|
|
|
|
caddr_t buf;
|
|
|
|
int len, rwflag;
|
|
|
|
struct uio *uio;
|
|
|
|
{
|
|
|
|
int left, ioc, num, offset;
|
|
|
|
struct iovec *io;
|
|
|
|
char *start;
|
|
|
|
|
|
|
|
if (rwflag == UIO_READ) {
|
|
|
|
left = len;
|
|
|
|
ioc = 0;
|
|
|
|
|
|
|
|
offset = uio->uio_offset;
|
|
|
|
|
|
|
|
while ((left > 0) && (ioc < uio->uio_iovcnt)) {
|
|
|
|
io = uio->uio_iov + ioc;
|
|
|
|
num = io->iov_len;
|
|
|
|
if (num > left)
|
|
|
|
num = left;
|
2002-03-14 15:34:29 +03:00
|
|
|
start = (char *)io->iov_base + offset;
|
|
|
|
if (start > (char *)io->iov_base + io->iov_len) {
|
2002-03-14 15:32:36 +03:00
|
|
|
offset -= io->iov_len;
|
|
|
|
ioc++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
bcopy(buf, start, num);
|
|
|
|
uio->uio_resid -= num;
|
|
|
|
uio->uio_offset += num;
|
|
|
|
left -= num;
|
|
|
|
if (left > 0)
|
|
|
|
ioc++;
|
|
|
|
}
|
|
|
|
if (left > 0)
|
|
|
|
return EFAULT;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
1997-03-29 03:54:55 +03:00
|
|
|
#endif /* _KERNEL */
|