o update PFIL_HOOKS support to current API used by netbsd

o revamp IPv4+IPv6+bridge usage to match API changes
o remove pfil_head instances from protosw entries (no longer used)
o add locking
o bump FreeBSD version for 3rd party modules

Heavy lifting by:	"Max Laier" <max@love2party.net>
Supported by:		FreeBSD Foundation
Obtained from:		NetBSD (bits of pfil.h and pfil.c)
This commit is contained in:
Sam Leffler 2003-09-23 17:54:04 +00:00
parent 6c7aa7fe1b
commit 134ea22494
14 changed files with 427 additions and 236 deletions

View File

@ -3,5 +3,15 @@
.PATH: ${.CURDIR}/../../net
KMOD= bridge
SRCS= bridge.c
SRCS+= opt_pfil_hooks.h
#
# By default don't enable pfil hooks support. This means you
# cannot use ipfilter together with the bridge. To enable it
# uncomment the line below
#
opt_pfil_hooks.h:
# echo "#define PFIL_HOOKS 1" > opt_pfil_hooks.h
touch opt_pfil_hooks.h
.include <bsd.kmod.mk>

View File

@ -87,6 +87,7 @@
* - be very careful when bridging VLANs
* - loop detection is still not very robust.
*/
#include "opt_pfil_hooks.h"
#include <sys/param.h>
#include <sys/mbuf.h>
@ -98,7 +99,6 @@
#include <sys/kernel.h>
#include <sys/sysctl.h>
#include <net/pfil.h> /* for ipfilter */
#include <net/if.h>
#include <net/if_types.h>
#include <net/if_var.h>
@ -109,6 +109,11 @@
#include <netinet/ip.h>
#include <netinet/if_ether.h> /* for struct arpcom */
#ifdef PFIL_HOOKS
#include <net/pfil.h>
#include <netinet/ip_var.h>
#endif
#include <net/route.h>
#include <netinet/ip_fw.h>
#include <netinet/ip_dummynet.h>
@ -160,7 +165,6 @@ struct cluster_softc {
extern struct protosw inetsw[]; /* from netinet/ip_input.c */
extern u_char ip_protox[]; /* from netinet/ip_input.c */
static int n_clusters; /* number of clusters */
static struct cluster_softc *clusters;
@ -715,6 +719,7 @@ bridge_dst_lookup(struct ether_header *eh, struct cluster_softc *c)
* Lookup local addresses in case one matches. We optimize
* for the common case of two interfaces.
*/
KASSERT(c->ports != 0, ("lookup with no ports!"));
switch (c->ports) {
int i;
default:
@ -914,10 +919,6 @@ bdg_forward(struct mbuf *m0, struct ifnet *dst)
int shared = bdg_copy; /* someone else is using the mbuf */
struct ifnet *real_dst = dst; /* real dst from ether_output */
struct ip_fw_args args;
#ifdef PFIL_HOOKS
struct packet_filter_hook *pfh;
int rv;
#endif /* PFIL_HOOKS */
struct ether_header save_eh;
struct mbuf *m;
@ -969,7 +970,7 @@ bdg_forward(struct mbuf *m0, struct ifnet *dst)
*/
if (src != NULL && (
#ifdef PFIL_HOOKS
((pfh = pfil_hook_get(PFIL_IN, &inetsw[ip_protox[IPPROTO_IP]].pr_pfh)) != NULL && bdg_ipf !=0) ||
(inet_pfil_hook.ph_busy_count >= 0 && bdg_ipf != 0) ||
#endif
(IPFW_LOADED && bdg_ipfw != 0))) {
@ -1006,8 +1007,9 @@ bdg_forward(struct mbuf *m0, struct ifnet *dst)
* NetBSD-style generic packet filter, pfil(9), hooks.
* Enables ipf(8) in bridging.
*/
if (pfh != NULL && m0->m_pkthdr.len >= sizeof(struct ip) &&
ntohs(save_eh.ether_type) == ETHERTYPE_IP) {
if (inet_pfil_hook.ph_busy_count >= 0 &&
m0->m_pkthdr.len >= sizeof(struct ip) &&
ntohs(save_eh.ether_type) == ETHERTYPE_IP) {
/*
* before calling the firewall, swap fields the same as IP does.
* here we assume the pkt is an IP one and the header is contiguous
@ -1017,20 +1019,14 @@ bdg_forward(struct mbuf *m0, struct ifnet *dst)
ip->ip_len = ntohs(ip->ip_len);
ip->ip_off = ntohs(ip->ip_off);
do {
if (pfh->pfil_func) {
rv = pfh->pfil_func(ip, ip->ip_hl << 2, src, 0, &m0);
if (m0 == NULL) {
bdg_dropped++;
return NULL;
}
if (rv != 0) {
EH_RESTORE(m0); /* restore Ethernet header */
return m0;
}
ip = mtod(m0, struct ip *);
}
} while ((pfh = TAILQ_NEXT(pfh, pfil_link)) != NULL);
if (pfil_run_hooks(&inet_pfil_hook, &m0, src, PFIL_IN) != 0) {
EH_RESTORE(m0); /* restore Ethernet header */
return m0;
}
if (m0 == NULL) {
bdg_dropped++;
return NULL;
}
/*
* If we get here, the firewall has passed the pkt, but the mbuf
* pointer might have changed. Restore ip and the fields ntohs()'d.

View File

@ -1,4 +1,5 @@
/* $FreeBSD$ */
/* $FreeBSD$ */
/* $NetBSD: pfil.c,v 1.20 2001/11/12 23:49:46 lukem Exp $ */
/*
* Copyright (c) 1996 Matthew R. Green
@ -29,30 +30,198 @@
*/
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/errno.h>
#include <sys/malloc.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/systm.h>
#include <sys/condvar.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/queue.h>
#include <net/if.h>
#include <net/pfil.h>
static void pfil_init(struct pfil_head *);
static int pfil_list_add(pfil_list_t *,
int (*)(void *, int, struct ifnet *, int, struct mbuf **), int);
static int pfil_list_remove(pfil_list_t *,
int (*)(void *, int, struct ifnet *, int, struct mbuf **));
static struct mtx pfil_global_lock;
static void
pfil_init(ph)
struct pfil_head *ph;
MTX_SYSINIT(pfil_heads_lock, &pfil_global_lock, "pfil_head_list lock", MTX_DEF);
static int pfil_list_add(pfil_list_t *, struct packet_filter_hook *, int);
static int pfil_list_remove(pfil_list_t *,
int (*)(void *, struct mbuf **, struct ifnet *, int), void *);
LIST_HEAD(, pfil_head) pfil_head_list =
LIST_HEAD_INITIALIZER(&pfil_head_list);
static __inline void
PFIL_RLOCK(struct pfil_head *ph)
{
mtx_lock(&ph->ph_mtx);
ph->ph_busy_count++;
mtx_unlock(&ph->ph_mtx);
}
static __inline void
PFIL_RUNLOCK(struct pfil_head *ph)
{
mtx_lock(&ph->ph_mtx);
ph->ph_busy_count--;
if (ph->ph_busy_count == 0 && ph->ph_want_write)
cv_signal(&ph->ph_cv);
mtx_unlock(&ph->ph_mtx);
}
static __inline void
PFIL_WLOCK(struct pfil_head *ph)
{
mtx_lock(&ph->ph_mtx);
ph->ph_want_write = 1;
while (ph->ph_busy_count > 0)
cv_wait(&ph->ph_cv, &ph->ph_mtx);
}
static __inline int
PFIL_TRY_WLOCK(struct pfil_head *ph)
{
mtx_lock(&ph->ph_mtx);
ph->ph_want_write = 1;
if (ph->ph_busy_count > 0) {
ph->ph_want_write = 0;
mtx_unlock(&ph->ph_mtx);
return EBUSY;
}
return 0;
}
static __inline void
PFIL_WUNLOCK(struct pfil_head *ph)
{
ph->ph_want_write = 0; \
mtx_unlock(&ph->ph_mtx);
cv_signal(&ph->ph_cv);
}
#define PFIL_LIST_LOCK() mtx_lock(&pfil_global_lock)
#define PFIL_LIST_UNLOCK() mtx_unlock(&pfil_global_lock)
/*
* pfil_run_hooks() runs the specified packet filter hooks.
*/
int
pfil_run_hooks(struct pfil_head *ph, struct mbuf **mp, struct ifnet *ifp,
int dir)
{
struct packet_filter_hook *pfh;
struct mbuf *m = *mp;
int rv = 0;
if (ph->ph_busy_count == -1 || ph->ph_want_write)
return (0);
PFIL_RLOCK(ph);
for (pfh = pfil_hook_get(dir, ph); pfh != NULL;
pfh = TAILQ_NEXT(pfh, pfil_link)) {
if (pfh->pfil_func != NULL) {
rv = (*pfh->pfil_func)(pfh->pfil_arg, &m, ifp, dir);
if (rv != 0 || m == NULL)
break;
}
}
PFIL_RUNLOCK(ph);
*mp = m;
return (rv);
}
/*
* pfil_head_register() registers a pfil_head with the packet filter
* hook mechanism.
*/
int
pfil_head_register(struct pfil_head *ph)
{
struct pfil_head *lph;
PFIL_LIST_LOCK();
LIST_FOREACH(lph, &pfil_head_list, ph_list)
if (ph->ph_type == lph->ph_type &&
ph->ph_un.phu_val == lph->ph_un.phu_val) {
PFIL_LIST_UNLOCK();
return EEXIST;
}
PFIL_LIST_UNLOCK();
if (mtx_initialized(&ph->ph_mtx)) { /* should not happen */
KASSERT((0), ("%s: allready initialized!", __func__));
return EBUSY;
} else {
ph->ph_busy_count = -1;
ph->ph_want_write = 1;
mtx_init(&ph->ph_mtx, "pfil_head_mtx", NULL, MTX_DEF);
cv_init(&ph->ph_cv, "pfil_head_cv");
mtx_lock(&ph->ph_mtx); /* XXX: race? */
}
TAILQ_INIT(&ph->ph_in);
TAILQ_INIT(&ph->ph_out);
ph->ph_init = 1;
PFIL_LIST_LOCK();
LIST_INSERT_HEAD(&pfil_head_list, ph, ph_list);
PFIL_LIST_UNLOCK();
PFIL_WUNLOCK(ph);
return (0);
}
/*
* pfil_head_unregister() removes a pfil_head from the packet filter
* hook mechanism.
*/
int
pfil_head_unregister(struct pfil_head *ph)
{
struct packet_filter_hook *pfh, *pfnext;
PFIL_LIST_LOCK();
/*
* LIST_REMOVE is safe for unlocked pfil_heads in ph_list.
* No need to WLOCK all of them.
*/
LIST_REMOVE(ph, ph_list);
PFIL_LIST_UNLOCK();
PFIL_WLOCK(ph); /* XXX: may sleep (cv_wait)! */
TAILQ_FOREACH_SAFE(pfh, &ph->ph_in, pfil_link, pfnext)
free(pfh, M_IFADDR);
TAILQ_FOREACH_SAFE(pfh, &ph->ph_out, pfil_link, pfnext)
free(pfh, M_IFADDR);
cv_destroy(&ph->ph_cv);
mtx_destroy(&ph->ph_mtx);
return (0);
}
/*
* pfil_head_get() returns the pfil_head for a given key/dlt.
*/
struct pfil_head *
pfil_head_get(int type, u_long val)
{
struct pfil_head *ph;
PFIL_LIST_LOCK();
LIST_FOREACH(ph, &pfil_head_list, ph_list)
if (ph->ph_type == type && ph->ph_un.phu_val == val)
break;
PFIL_LIST_UNLOCK();
return (ph);
}
/*
@ -64,53 +233,71 @@ pfil_init(ph)
* PFIL_WAITOK OK to call malloc with M_WAITOK.
*/
int
pfil_add_hook(func, flags, ph)
int (*func)(void *, int, struct ifnet *, int, struct mbuf **);
int flags;
struct pfil_head *ph;
pfil_add_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int),
void *arg, int flags, struct pfil_head *ph)
{
int err = 0;
struct packet_filter_hook *pfh1 = NULL;
struct packet_filter_hook *pfh2 = NULL;
int err;
if (ph->ph_init == 0)
pfil_init(ph);
if (flags & PFIL_IN)
err = pfil_list_add(&ph->ph_in, func, flags & ~PFIL_OUT);
if (err)
return err;
if (flags & PFIL_OUT)
err = pfil_list_add(&ph->ph_out, func, flags & ~PFIL_IN);
if (err) {
if (flags & PFIL_IN)
pfil_list_remove(&ph->ph_in, func);
return err;
/* Get memory */
if (flags & PFIL_IN) {
pfh1 = (struct packet_filter_hook *)malloc(sizeof(*pfh1),
M_IFADDR, (flags & PFIL_WAITOK) ? M_WAITOK : M_NOWAIT);
if (pfh1 == NULL) {
err = ENOMEM;
goto error;
}
}
if (flags & PFIL_OUT) {
pfh2 = (struct packet_filter_hook *)malloc(sizeof(*pfh1),
M_IFADDR, (flags & PFIL_WAITOK) ? M_WAITOK : M_NOWAIT);
if (pfh2 == NULL) {
err = ENOMEM;
goto error;
}
}
return 0;
}
static int
pfil_list_add(list, func, flags)
pfil_list_t *list;
int (*func)(void *, int, struct ifnet *, int, struct mbuf **);
int flags;
{
struct packet_filter_hook *pfh;
/* Lock */
if (flags & PFIL_WAITOK)
PFIL_WLOCK(ph);
else {
err = PFIL_TRY_WLOCK(ph);
if (err)
goto error;
}
/* Add */
if (flags & PFIL_IN) {
pfh1->pfil_func = func;
pfh1->pfil_arg = arg;
err = pfil_list_add(&ph->ph_in, pfh1, flags & ~PFIL_OUT);
if (err)
goto done;
}
if (flags & PFIL_OUT) {
pfh2->pfil_func = func;
pfh2->pfil_arg = arg;
err = pfil_list_add(&ph->ph_out, pfh2, flags & ~PFIL_IN);
if (err) {
if (flags & PFIL_IN)
pfil_list_remove(&ph->ph_in, func, arg);
goto done;
}
}
ph->ph_busy_count = 0;
PFIL_WUNLOCK(ph);
pfh = (struct packet_filter_hook *)malloc(sizeof(*pfh), M_IFADDR,
flags & PFIL_WAITOK ? M_WAITOK : M_NOWAIT);
if (pfh == NULL)
return ENOMEM;
pfh->pfil_func = func;
/*
* insert the input list in reverse order of the output list
* so that the same path is followed in or out of the kernel.
*/
if (flags & PFIL_IN)
TAILQ_INSERT_HEAD(list, pfh, pfil_link);
else
TAILQ_INSERT_TAIL(list, pfh, pfil_link);
return 0;
done:
PFIL_WUNLOCK(ph);
error:
if (pfh1 != NULL)
free(pfh1, M_IFADDR);
if (pfh2 != NULL)
free(pfh2, M_IFADDR);
return err;
}
/*
@ -118,54 +305,71 @@ pfil_list_add(list, func, flags)
* hook list.
*/
int
pfil_remove_hook(func, flags, ph)
int (*func)(void *, int, struct ifnet *, int, struct mbuf **);
int flags;
struct pfil_head *ph;
pfil_remove_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int),
void *arg, int flags, struct pfil_head *ph)
{
int err = 0;
if (ph->ph_init == 0)
pfil_init(ph);
if (flags & PFIL_WAITOK)
PFIL_WLOCK(ph);
else {
err = PFIL_TRY_WLOCK(ph);
if (err)
return err;
}
if (flags & PFIL_IN)
err = pfil_list_remove(&ph->ph_in, func);
err = pfil_list_remove(&ph->ph_in, func, arg);
if ((err == 0) && (flags & PFIL_OUT))
err = pfil_list_remove(&ph->ph_out, func);
err = pfil_list_remove(&ph->ph_out, func, arg);
if (TAILQ_EMPTY(&ph->ph_in) && TAILQ_EMPTY(&ph->ph_out))
ph->ph_busy_count = -1;
PFIL_WUNLOCK(ph);
return err;
}
static int
pfil_list_add(pfil_list_t *list, struct packet_filter_hook *pfh1, int flags)
{
struct packet_filter_hook *pfh;
/*
* First make sure the hook is not already there.
*/
TAILQ_FOREACH(pfh, list, pfil_link)
if (pfh->pfil_func == pfh1->pfil_func &&
pfh->pfil_arg == pfh1->pfil_arg)
return EEXIST;
/*
* insert the input list in reverse order of the output list
* so that the same path is followed in or out of the kernel.
*/
if (flags & PFIL_IN)
TAILQ_INSERT_HEAD(list, pfh1, pfil_link);
else
TAILQ_INSERT_TAIL(list, pfh1, pfil_link);
return 0;
}
/*
* pfil_list_remove is an internal function that takes a function off the
* specified list.
*/
static int
pfil_list_remove(list, func)
pfil_list_t *list;
int (*func)(void *, int, struct ifnet *, int, struct mbuf **);
pfil_list_remove(pfil_list_t *list,
int (*func)(void *, struct mbuf **, struct ifnet *, int), void *arg)
{
struct packet_filter_hook *pfh;
TAILQ_FOREACH(pfh, list, pfil_link)
if (pfh->pfil_func == func) {
if (pfh->pfil_func == func && pfh->pfil_arg == arg) {
TAILQ_REMOVE(list, pfh, pfil_link);
free(pfh, M_IFADDR);
return 0;
}
return ENOENT;
}
struct packet_filter_hook *
pfil_hook_get(flag, ph)
int flag;
struct pfil_head *ph;
{
if (ph->ph_init != 0)
switch (flag) {
case PFIL_IN:
return (TAILQ_FIRST(&ph->ph_in));
case PFIL_OUT:
return (TAILQ_FIRST(&ph->ph_out));
}
return NULL;
}

View File

@ -1,4 +1,5 @@
/* $FreeBSD$ */
/* $FreeBSD$ */
/* $NetBSD: pfil.h,v 1.22 2003/06/23 12:57:08 martin Exp $ */
/*
* Copyright (c) 1996 Matthew R. Green
@ -31,6 +32,10 @@
#ifndef _NET_PFIL_H_
#define _NET_PFIL_H_
#include <sys/systm.h>
#include <sys/_lock.h>
#include <sys/_mutex.h>
#include <sys/condvar.h> /* XXX */
#include <sys/queue.h>
struct mbuf;
@ -42,7 +47,8 @@ struct ifnet;
*/
struct packet_filter_hook {
TAILQ_ENTRY(packet_filter_hook) pfil_link;
int (*pfil_func)(void *, int, struct ifnet *, int, struct mbuf **);
int (*pfil_func)(void *, struct mbuf **, struct ifnet *, int);
void *pfil_arg;
int pfil_flags;
};
@ -53,28 +59,54 @@ struct packet_filter_hook {
typedef TAILQ_HEAD(pfil_list, packet_filter_hook) pfil_list_t;
#define PFIL_TYPE_AF 1 /* key is AF_* type */
#define PFIL_TYPE_IFNET 2 /* key is ifnet pointer */
struct pfil_head {
pfil_list_t ph_in;
pfil_list_t ph_out;
int ph_init;
int ph_type;
/*
* Locking: use a busycounter per pfil_head.
* Use ph_busy_count = -1 to indicate pfil_head is empty.
*/
int ph_busy_count; /* count of threads with read lock */
int ph_want_write; /* want write lock flag */
struct cv ph_cv; /* for waking up writers */
struct mtx ph_mtx; /* mutex on locking state */
union {
u_long phu_val;
void *phu_ptr;
} ph_un;
#define ph_af ph_un.phu_val
#define ph_ifnet ph_un.phu_ptr
LIST_ENTRY(pfil_head) ph_list;
};
struct packet_filter_hook *pfil_hook_get(int, struct pfil_head *);
int pfil_add_hook(int (*func)(void *, int,
struct ifnet *, int, struct mbuf **), int, struct pfil_head *);
int pfil_remove_hook(int (*func)(void *, int,
struct ifnet *, int, struct mbuf **), int, struct pfil_head *);
int pfil_run_hooks(struct pfil_head *, struct mbuf **, struct ifnet *,
int);
/* XXX */
#if defined(_KERNEL) && !defined(KLD_MODULE)
#include "opt_ipfilter.h"
#endif
int pfil_add_hook(int (*func)(void *, struct mbuf **,
struct ifnet *, int), void *, int, struct pfil_head *);
int pfil_remove_hook(int (*func)(void *, struct mbuf **,
struct ifnet *, int), void *, int, struct pfil_head *);
#if IPFILTER > 0
#ifdef PFIL_HOOKS
#undef PFIL_HOOKS
#endif
#define PFIL_HOOKS
#endif /* IPFILTER */
int pfil_head_register(struct pfil_head *);
int pfil_head_unregister(struct pfil_head *);
struct pfil_head *pfil_head_get(int, u_long);
static __inline struct packet_filter_hook *
pfil_hook_get(int dir, struct pfil_head *ph)
{
KASSERT(ph->ph_busy_count > 0,
("pfil_hook_get: called on unbusy pfil_head"));
if (dir == PFIL_IN)
return (TAILQ_FIRST(&ph->ph_in));
else if (dir == PFIL_OUT)
return (TAILQ_FIRST(&ph->ph_out));
else
return (NULL);
}
#endif /* _NET_PFIL_H_ */

View File

@ -154,6 +154,9 @@ SYSCTL_INT(_net_inet_ip, OID_AUTO, check_interface, CTLFLAG_RW,
#ifdef DIAGNOSTIC
static int ipprintfs = 0;
#endif
#ifdef PFIL_HOOKS
struct pfil_head inet_pfil_hook;
#endif
static struct ifqueue ipintrq;
static int ipqmaxlen = IFQ_MAXLEN;
@ -263,6 +266,14 @@ ip_init()
pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
ip_protox[pr->pr_protocol] = pr - inetsw;
#ifdef PFIL_HOOKS
inet_pfil_hook.ph_type = PFIL_TYPE_AF;
inet_pfil_hook.ph_af = AF_INET;
if ((i = pfil_head_register(&inet_pfil_hook)) != 0)
printf("%s: WARNING: unable to register pfil hook, "
"error %d\n", __func__, i);
#endif /* PFIL_HOOKS */
IPQ_LOCK_INIT();
for (i = 0; i < IPREASS_NHASH; i++)
TAILQ_INIT(&ipq[i]);
@ -301,11 +312,6 @@ ip_input(struct mbuf *m)
struct in_addr pkt_dst;
u_int32_t divert_info = 0; /* packet divert/tee info */
struct ip_fw_args args;
#ifdef PFIL_HOOKS
struct packet_filter_hook *pfh;
struct mbuf *m0;
int rv;
#endif /* PFIL_HOOKS */
#ifdef FAST_IPSEC
struct m_tag *mtag;
struct tdb_ident *tdbi;
@ -461,25 +467,14 @@ ip_input(struct mbuf *m)
#ifdef PFIL_HOOKS
/*
* Run through list of hooks for input packets. If there are any
* filters which require that additional packets in the flow are
* not fast-forwarded, they must clear the M_CANFASTFWD flag.
* Note that filters must _never_ set this flag, as another filter
* in the list may have previously cleared it.
* Run through list of hooks for input packets.
*/
m0 = m;
pfh = pfil_hook_get(PFIL_IN, &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
for (; pfh; pfh = TAILQ_NEXT(pfh, pfil_link))
if (pfh->pfil_func) {
rv = pfh->pfil_func(ip, hlen,
m->m_pkthdr.rcvif, 0, &m0);
if (rv)
return;
m = m0;
if (m == NULL)
return;
ip = mtod(m, struct ip *);
}
if (pfil_run_hooks(&inet_pfil_hook, &m, m->m_pkthdr.rcvif,
PFIL_IN) != 0)
return;
if (m == NULL) /* consumed by filter */
return;
ip = mtod(m, struct ip *);
#endif /* PFIL_HOOKS */
if (fw_enable && IPFW_LOADED) {

View File

@ -65,6 +65,10 @@
#include <netinet/in_var.h>
#include <netinet/ip_var.h>
#ifdef PFIL_HOOKS
#include <net/pfil.h>
#endif
#include <machine/in_cksum.h>
static MALLOC_DEFINE(M_IPMOPTS, "ip_moptions", "internet multicast options");
@ -149,11 +153,6 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro,
#endif /* FAST_IPSEC */
struct ip_fw_args args;
int src_was_INADDR_ANY = 0; /* as the name says... */
#ifdef PFIL_HOOKS
struct packet_filter_hook *pfh;
struct mbuf *m1;
int rv;
#endif /* PFIL_HOOKS */
args.eh = NULL;
args.rule = NULL;
@ -741,20 +740,10 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro,
/*
* Run through list of hooks for output packets.
*/
m1 = m;
pfh = pfil_hook_get(PFIL_OUT, &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
for (; pfh; pfh = TAILQ_NEXT(pfh, pfil_link))
if (pfh->pfil_func) {
rv = pfh->pfil_func(ip, hlen, ifp, 1, &m1);
if (rv) {
error = EHOSTUNREACH;
goto done;
}
m = m1;
if (m == NULL)
goto done;
ip = mtod(m, struct ip *);
}
error = pfil_run_hooks(&inet_pfil_hook, &m, ifp, PFIL_OUT);
if (error != 0 || m == NULL)
goto done;
ip = mtod(m, struct ip *);
#endif /* PFIL_HOOKS */
/*

View File

@ -207,6 +207,10 @@ void divert_packet(struct mbuf *m, int incoming, int port, int rule);
extern struct pr_usrreqs div_usrreqs;
#endif
#ifdef PFIL_HOOKS
extern struct pfil_head inet_pfil_hook;
#endif
void in_delayed_cksum(struct mbuf *m);
#endif /* _KERNEL */

View File

@ -34,6 +34,7 @@
#include "opt_inet.h"
#include "opt_inet6.h"
#include "opt_ipsec.h"
#include "opt_pfil_hooks.h"
#include <sys/param.h>
#include <sys/systm.h>
@ -113,11 +114,6 @@ ip6_forward(m, srcrt)
int error, type = 0, code = 0;
struct mbuf *mcopy = NULL;
struct ifnet *origifp; /* maybe unnecessary */
#ifdef PFIL_HOOKS
struct packet_filter_hook *pfh;
struct mbuf *m1;
int rv;
#endif /* PFIL_HOOKS */
#ifdef IPSEC
struct secpolicy *sp = NULL;
#endif
@ -526,21 +522,13 @@ ip6_forward(m, srcrt)
/*
* Run through list of hooks for output packets.
*/
m1 = m;
pfh = pfil_hook_get(PFIL_OUT, &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
for (; pfh; pfh = pfh->pfil_link.tqe_next)
if (pfh->pfil_func) {
rv = pfh->pfil_func(ip6, sizeof(*ip6),
rt->rt_ifp, 1, &m1);
if (rv) {
error = EHOSTUNREACH;
goto freecopy;
}
m = m1;
if (m == NULL)
goto freecopy;
ip6 = mtod(m, struct ip6_hdr *);
}
if (pfil_run_hooks(&inet6_pfil_hook, &m, rt->rt_ifp, PFIL_OUT) != 0) {
error = EHOSTUNREACH;
goto freecopy;
}
if (m == NULL)
goto freecopy;
ip6 = mtod(m, struct ip6_hdr *);
#endif /* PFIL_HOOKS */
error = nd6_output(rt->rt_ifp, origifp, m, dst, rt);

View File

@ -143,6 +143,9 @@ int ip6_sourcecheck_interval; /* XXX */
int ip6_ours_check_algorithm;
#ifdef PFIL_HOOKS
struct pfil_head inet6_pfil_hook;
#endif
/* firewall hooks */
ip6_fw_chk_t *ip6_fw_chk_ptr;
@ -184,6 +187,13 @@ ip6_init()
if (pr->pr_domain->dom_family == PF_INET6 &&
pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
ip6_protox[pr->pr_protocol] = pr - inet6sw;
#ifdef PFIL_HOOKS
inet6_pfil_hook.ph_type = PFIL_TYPE_AF;
inet6_pfil_hook.ph_af = AF_INET6;
if ((i = pfil_head_register(&inet6_pfil_hook)) != 0)
printf("%s: WARNING: unable to register pfil hook, "
"error %d\n", __func__, i);
#endif /* PFIL_HOOKS */
ip6intrq.ifq_maxlen = ip6qmaxlen;
mtx_init(&ip6intrq.ifq_mtx, "ip6_inq", NULL, MTX_DEF);
netisr_register(NETISR_IPV6, ip6_input, &ip6intrq);
@ -241,11 +251,6 @@ ip6_input(m)
u_int32_t rtalert = ~0;
int nxt, ours = 0;
struct ifnet *deliverifp = NULL;
#ifdef PFIL_HOOKS
struct packet_filter_hook *pfh;
struct mbuf *m0;
int rv;
#endif /* PFIL_HOOKS */
#ifdef IPSEC
/*
@ -340,25 +345,13 @@ ip6_input(m)
#ifdef PFIL_HOOKS
/*
* Run through list of hooks for input packets. If there are any
* filters which require that additional packets in the flow are
* not fast-forwarded, they must clear the M_CANFASTFWD flag.
* Note that filters must _never_ set this flag, as another filter
* in the list may have previously cleared it.
* Run through list of hooks for input packets.
*/
m0 = m;
pfh = pfil_hook_get(PFIL_IN, &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
for (; pfh; pfh = pfh->pfil_link.tqe_next)
if (pfh->pfil_func) {
rv = pfh->pfil_func(ip6, sizeof(*ip6),
m->m_pkthdr.rcvif, 0, &m0);
if (rv)
return;
m = m0;
if (m == NULL)
return;
ip6 = mtod(m, struct ip6_hdr *);
}
if (pfil_run_hooks(&inet6_pfil_hook, &m, m->m_pkthdr.rcvif, PFIL_IN))
return;
if (m == NULL) /* consumed by filter */
return;
ip6 = mtod(m, struct ip6_hdr *);
#endif /* PFIL_HOOKS */
ip6stat.ip6s_nxthist[ip6->ip6_nxt]++;

View File

@ -173,11 +173,6 @@ ip6_output(m0, opt, ro, flags, im6o, ifpp, inp)
struct route_in6 *ro_pmtu = NULL;
int hdrsplit = 0;
int needipsec = 0;
#ifdef PFIL_HOOKS
struct packet_filter_hook *pfh;
struct mbuf *m1;
int rv;
#endif /* PFIL_HOOKS */
#ifdef IPSEC
int needipsectun = 0;
struct secpolicy *sp = NULL;
@ -931,20 +926,13 @@ skip_ipsec2:;
/*
* Run through list of hooks for output packets.
*/
m1 = m;
pfh = pfil_hook_get(PFIL_OUT, &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
for (; pfh; pfh = pfh->pfil_link.tqe_next)
if (pfh->pfil_func) {
rv = pfh->pfil_func(ip6, sizeof(*ip6), ifp, 1, &m1);
if (rv) {
error = EHOSTUNREACH;
goto done;
}
m = m1;
if (m == NULL)
goto done;
ip6 = mtod(m, struct ip6_hdr *);
}
if (pfil_run_hooks(&inet6_pfil_hook, &m, ifp, PFIL_OUT) != 0) {
error = EHOSTUNREACH;
goto done;
}
if (m == NULL)
goto done;
ip6 = mtod(m, struct ip6_hdr *);
#endif /* PFIL_HOOKS */
/*
* Send the packet to the outgoing interface.

View File

@ -285,6 +285,10 @@ extern int ip6_lowportmax; /* maximum reserved port */
extern int ip6_use_tempaddr; /* whether to use temporary addresses. */
#ifdef PFIL_HOOKS
extern struct pfil_head inet6_pfil_hook;
#endif
extern struct pr_usrreqs rip6_usrreqs;
struct sockopt;

View File

@ -71,11 +71,6 @@
#ifndef _NETINET6_IP6PROTOSW_H_
#define _NETINET6_IP6PROTOSW_H_
/*
* For pfil_head structure.
*/
#include <net/pfil.h>
/*
* Protocol switch table for IPv6.
* All other definitions should refer to sys/protosw.h
@ -153,7 +148,6 @@ struct ip6protosw {
void (*pr_drain) /* flush any excess space possible */
__P((void));
struct pr_usrreqs *pr_usrreqs; /* supersedes pr_usrreq() */
struct pfil_head pr_pfh;
};
#ifdef _KERNEL

View File

@ -57,7 +57,7 @@
* scheme is: <major><two digit minor><0 if release branch, otherwise 1>xx
*/
#undef __FreeBSD_version
#define __FreeBSD_version 501107 /* Master, propagated to newvers */
#define __FreeBSD_version 501108 /* Master, propagated to newvers */
#ifndef NULL
#define NULL 0

View File

@ -37,11 +37,6 @@
#ifndef _SYS_PROTOSW_H_
#define _SYS_PROTOSW_H_
/*
* For pfil_head structure.
*/
#include <net/pfil.h>
/* Forward declare these structures referenced from prototypes below. */
struct mbuf;
struct thread;
@ -107,7 +102,6 @@ struct protosw {
pr_drain_t *pr_drain; /* flush any excess space possible */
struct pr_usrreqs *pr_usrreqs; /* supersedes pr_usrreq() */
struct pfil_head pr_pfh;
};
/*#endif*/