netpfil: Introduce PFIL_FWD flag
Forwarded packets passed through PFIL_OUT, which made it difficult for firewalls to figure out if they were forwarding or producing packets. This in turn is an issue for pf for IPv6 fragment handling: it needs to call ip6_output() or ip6_forward() to handle the fragments. Figuring out which was difficult (and until now, incorrect). Having pfil distinguish the two removes an ugly piece of code from pf. Introduce a new variant of the netpfil callbacks with a flags variable, which has PFIL_FWD set for forwarded packets. This allows pf to reliably work out if a packet is forwarded. Reviewed by: ae, kevans Differential Revision: https://reviews.freebsd.org/D13715
This commit is contained in:
parent
6a6c0d5844
commit
effaab8861
@ -28,7 +28,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd March 27, 2017
|
||||
.Dd March 10, 2018
|
||||
.Dt PFIL 9
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -37,7 +37,9 @@
|
||||
.Nm pfil_head_unregister ,
|
||||
.Nm pfil_head_get ,
|
||||
.Nm pfil_add_hook ,
|
||||
.Nm pfil_add_hook_flags ,
|
||||
.Nm pfil_remove_hook ,
|
||||
.Nm pfil_remove_hook_flags ,
|
||||
.Nm pfil_run_hooks ,
|
||||
.Nm pfil_rlock ,
|
||||
.Nm pfil_runlock ,
|
||||
@ -51,6 +53,8 @@
|
||||
.In net/pfil.h
|
||||
.Bd -literal
|
||||
typedef int (*pfil_func_t)(void *arg, struct mbuf **mp, struct ifnet *, int dir, struct inpcb);
|
||||
.Bd -literal
|
||||
typedef int (*pfil_func_flags_t)(void *arg, struct mbuf **mp, struct ifnet *, int dir, int flags, struct inpcb);
|
||||
.Ft int
|
||||
.Fn pfil_head_register "struct pfil_head *head"
|
||||
.Ft int
|
||||
@ -58,11 +62,15 @@ typedef int (*pfil_func_t)(void *arg, struct mbuf **mp, struct ifnet *, int dir,
|
||||
.Ft "struct pfil_head *"
|
||||
.Fn pfil_head_get "int af" "u_long dlt"
|
||||
.Ft int
|
||||
.Fn pfil_add_hook "pfil_func_t" "void *arg" "int flags" "struct pfil_head *"
|
||||
.Fn pfil_add_hook "pfil_func_t" "void *arg" "struct pfil_head *"
|
||||
.Ft int
|
||||
.Fn pfil_remove_hook "pfil_func_t" "void *arg" "int flags" "struct pfil_head *"
|
||||
.Fn pfil_add_hook_flags "pfil_func_flags_t" "void *arg" "int flags" "struct pfil_head *"
|
||||
.Ft int
|
||||
.Fn pfil_run_hooks "struct pfil_head *head" "struct mbuf **mp" "struct ifnet *" "int dir" "struct inpcb *"
|
||||
.Fn pfil_remove_hook "pfil_func_t" "void *arg" "struct pfil_head *"
|
||||
.Ft int
|
||||
.Fn pfil_remove_hook_flags "pfil_func_flags_t" "void *arg" "int flags" "struct pfil_head *"
|
||||
.Ft int
|
||||
.Fn pfil_run_hooks "struct pfil_head *head" "struct mbuf **mp" "struct ifnet *" "int dir" "int flags" "struct inpcb *"
|
||||
.Ft void
|
||||
.Fn pfil_rlock "struct pfil_head *" "struct rm_priotracker *"
|
||||
.Ft void
|
||||
@ -116,6 +124,7 @@ with the
|
||||
and
|
||||
.Fn pfil_remove_hook
|
||||
functions, respectively.
|
||||
.I
|
||||
The head is looked up using the
|
||||
.Fn pfil_head_get
|
||||
function, which takes the key and data link type that the packet filter
|
||||
@ -135,6 +144,10 @@ interface that the packet is traversing, and the direction
|
||||
or
|
||||
.Dv PFIL_OUT )
|
||||
that the packet is traveling.
|
||||
The
|
||||
.Vt flags
|
||||
argument will indicate if an outgoing packet is simply being forwarded with the
|
||||
value PFIL_FWD.
|
||||
The filter may change which mbuf the
|
||||
.Vt "mbuf\ **"
|
||||
argument references.
|
||||
|
@ -3176,7 +3176,8 @@ bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir)
|
||||
if (PFIL_HOOKED(&V_link_pfil_hook) && V_pfil_ipfw != 0 &&
|
||||
dir == PFIL_OUT && ifp != NULL) {
|
||||
|
||||
error = pfil_run_hooks(&V_link_pfil_hook, mp, ifp, dir, NULL);
|
||||
error = pfil_run_hooks(&V_link_pfil_hook, mp, ifp, dir, 0,
|
||||
NULL);
|
||||
|
||||
if (*mp == NULL || error != 0) /* packet consumed by filter */
|
||||
return (error);
|
||||
@ -3228,21 +3229,21 @@ bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir)
|
||||
*/
|
||||
if (V_pfil_bridge && dir == PFIL_OUT && bifp != NULL)
|
||||
error = pfil_run_hooks(&V_inet_pfil_hook, mp, bifp,
|
||||
dir, NULL);
|
||||
dir, 0, NULL);
|
||||
|
||||
if (*mp == NULL || error != 0) /* filter may consume */
|
||||
break;
|
||||
|
||||
if (V_pfil_member && ifp != NULL)
|
||||
error = pfil_run_hooks(&V_inet_pfil_hook, mp, ifp,
|
||||
dir, NULL);
|
||||
dir, 0, NULL);
|
||||
|
||||
if (*mp == NULL || error != 0) /* filter may consume */
|
||||
break;
|
||||
|
||||
if (V_pfil_bridge && dir == PFIL_IN && bifp != NULL)
|
||||
error = pfil_run_hooks(&V_inet_pfil_hook, mp, bifp,
|
||||
dir, NULL);
|
||||
dir, 0, NULL);
|
||||
|
||||
if (*mp == NULL || error != 0) /* filter may consume */
|
||||
break;
|
||||
@ -3282,21 +3283,21 @@ bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir)
|
||||
case ETHERTYPE_IPV6:
|
||||
if (V_pfil_bridge && dir == PFIL_OUT && bifp != NULL)
|
||||
error = pfil_run_hooks(&V_inet6_pfil_hook, mp, bifp,
|
||||
dir, NULL);
|
||||
dir, 0, NULL);
|
||||
|
||||
if (*mp == NULL || error != 0) /* filter may consume */
|
||||
break;
|
||||
|
||||
if (V_pfil_member && ifp != NULL)
|
||||
error = pfil_run_hooks(&V_inet6_pfil_hook, mp, ifp,
|
||||
dir, NULL);
|
||||
dir, 0, NULL);
|
||||
|
||||
if (*mp == NULL || error != 0) /* filter may consume */
|
||||
break;
|
||||
|
||||
if (V_pfil_bridge && dir == PFIL_IN && bifp != NULL)
|
||||
error = pfil_run_hooks(&V_inet6_pfil_hook, mp, bifp,
|
||||
dir, NULL);
|
||||
dir, 0, NULL);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
|
@ -301,7 +301,7 @@ enc_hhook(int32_t hhook_type, int32_t hhook_id, void *udata, void *ctx_data,
|
||||
/* Make a packet looks like it was received on enc(4) */
|
||||
rcvif = (*ctx->mp)->m_pkthdr.rcvif;
|
||||
(*ctx->mp)->m_pkthdr.rcvif = ifp;
|
||||
if (pfil_run_hooks(ph, ctx->mp, ifp, pdir, ctx->inp) != 0 ||
|
||||
if (pfil_run_hooks(ph, ctx->mp, ifp, pdir, 0, ctx->inp) != 0 ||
|
||||
*ctx->mp == NULL) {
|
||||
*ctx->mp = NULL; /* consumed by filter */
|
||||
return (EACCES);
|
||||
|
@ -449,7 +449,8 @@ ether_output_frame(struct ifnet *ifp, struct mbuf *m)
|
||||
int i;
|
||||
|
||||
if (PFIL_HOOKED(&V_link_pfil_hook)) {
|
||||
i = pfil_run_hooks(&V_link_pfil_hook, &m, ifp, PFIL_OUT, NULL);
|
||||
i = pfil_run_hooks(&V_link_pfil_hook, &m, ifp, PFIL_OUT, 0,
|
||||
NULL);
|
||||
|
||||
if (i != 0)
|
||||
return (EACCES);
|
||||
@ -782,7 +783,8 @@ ether_demux(struct ifnet *ifp, struct mbuf *m)
|
||||
|
||||
/* Do not grab PROMISC frames in case we are re-entered. */
|
||||
if (PFIL_HOOKED(&V_link_pfil_hook) && !(m->m_flags & M_PROMISC)) {
|
||||
i = pfil_run_hooks(&V_link_pfil_hook, &m, ifp, PFIL_IN, NULL);
|
||||
i = pfil_run_hooks(&V_link_pfil_hook, &m, ifp, PFIL_IN, 0,
|
||||
NULL);
|
||||
|
||||
if (i != 0 || m == NULL)
|
||||
return;
|
||||
|
@ -57,7 +57,8 @@ MTX_SYSINIT(pfil_heads_lock, &pfil_global_lock, "pfil_head_list lock",
|
||||
|
||||
static struct packet_filter_hook *pfil_chain_get(int, struct pfil_head *);
|
||||
static int pfil_chain_add(pfil_chain_t *, struct packet_filter_hook *, int);
|
||||
static int pfil_chain_remove(pfil_chain_t *, pfil_func_t, void *);
|
||||
static int pfil_chain_remove(pfil_chain_t *, void *, void *);
|
||||
static int pfil_add_hook_priv(void *, void *, int, struct pfil_head *, bool);
|
||||
|
||||
LIST_HEAD(pfilheadhead, pfil_head);
|
||||
VNET_DEFINE(struct pfilheadhead, pfil_head_list);
|
||||
@ -95,7 +96,7 @@ VNET_DEFINE(struct rmlock, pfil_lock);
|
||||
*/
|
||||
int
|
||||
pfil_run_hooks(struct pfil_head *ph, struct mbuf **mp, struct ifnet *ifp,
|
||||
int dir, struct inpcb *inp)
|
||||
int dir, int flags, struct inpcb *inp)
|
||||
{
|
||||
struct rm_priotracker rmpt;
|
||||
struct packet_filter_hook *pfh;
|
||||
@ -106,6 +107,12 @@ pfil_run_hooks(struct pfil_head *ph, struct mbuf **mp, struct ifnet *ifp,
|
||||
KASSERT(ph->ph_nhooks >= 0, ("Pfil hook count dropped < 0"));
|
||||
for (pfh = pfil_chain_get(dir, ph); pfh != NULL;
|
||||
pfh = TAILQ_NEXT(pfh, pfil_chain)) {
|
||||
if (pfh->pfil_func_flags != NULL) {
|
||||
rv = (*pfh->pfil_func_flags)(pfh->pfil_arg, &m, ifp,
|
||||
dir, flags, inp);
|
||||
if (rv != 0 || m == NULL)
|
||||
break;
|
||||
}
|
||||
if (pfh->pfil_func != NULL) {
|
||||
rv = (*pfh->pfil_func)(pfh->pfil_arg, &m, ifp, dir,
|
||||
inp);
|
||||
@ -255,6 +262,21 @@ pfil_head_get(int type, u_long val)
|
||||
return (ph);
|
||||
}
|
||||
|
||||
/*
|
||||
* pfil_add_hook_flags() adds a function to the packet filter hook. the
|
||||
* flags are:
|
||||
* PFIL_IN call me on incoming packets
|
||||
* PFIL_OUT call me on outgoing packets
|
||||
* PFIL_ALL call me on all of the above
|
||||
* PFIL_WAITOK OK to call malloc with M_WAITOK.
|
||||
*/
|
||||
int
|
||||
pfil_add_hook_flags(pfil_func_flags_t func, void *arg, int flags,
|
||||
struct pfil_head *ph)
|
||||
{
|
||||
return (pfil_add_hook_priv(func, arg, flags, ph, true));
|
||||
}
|
||||
|
||||
/*
|
||||
* pfil_add_hook() adds a function to the packet filter hook. the
|
||||
* flags are:
|
||||
@ -265,6 +287,13 @@ pfil_head_get(int type, u_long val)
|
||||
*/
|
||||
int
|
||||
pfil_add_hook(pfil_func_t func, void *arg, int flags, struct pfil_head *ph)
|
||||
{
|
||||
return (pfil_add_hook_priv(func, arg, flags, ph, false));
|
||||
}
|
||||
|
||||
static int
|
||||
pfil_add_hook_priv(void *func, void *arg, int flags,
|
||||
struct pfil_head *ph, bool hasflags)
|
||||
{
|
||||
struct packet_filter_hook *pfh1 = NULL;
|
||||
struct packet_filter_hook *pfh2 = NULL;
|
||||
@ -288,7 +317,8 @@ pfil_add_hook(pfil_func_t func, void *arg, int flags, struct pfil_head *ph)
|
||||
}
|
||||
PFIL_WLOCK(ph);
|
||||
if (flags & PFIL_IN) {
|
||||
pfh1->pfil_func = func;
|
||||
pfh1->pfil_func_flags = hasflags ? func : NULL;
|
||||
pfh1->pfil_func = hasflags ? NULL : func;
|
||||
pfh1->pfil_arg = arg;
|
||||
err = pfil_chain_add(&ph->ph_in, pfh1, flags & ~PFIL_OUT);
|
||||
if (err)
|
||||
@ -296,7 +326,8 @@ pfil_add_hook(pfil_func_t func, void *arg, int flags, struct pfil_head *ph)
|
||||
ph->ph_nhooks++;
|
||||
}
|
||||
if (flags & PFIL_OUT) {
|
||||
pfh2->pfil_func = func;
|
||||
pfh2->pfil_func_flags = hasflags ? func : NULL;
|
||||
pfh2->pfil_func = hasflags ? NULL : func;
|
||||
pfh2->pfil_arg = arg;
|
||||
err = pfil_chain_add(&ph->ph_out, pfh2, flags & ~PFIL_IN);
|
||||
if (err) {
|
||||
@ -318,6 +349,17 @@ error:
|
||||
return (err);
|
||||
}
|
||||
|
||||
/*
|
||||
* pfil_remove_hook_flags removes a specific function from the packet filter hook
|
||||
* chain.
|
||||
*/
|
||||
int
|
||||
pfil_remove_hook_flags(pfil_func_flags_t func, void *arg, int flags,
|
||||
struct pfil_head *ph)
|
||||
{
|
||||
return (pfil_remove_hook((pfil_func_t)func, arg, flags, ph));
|
||||
}
|
||||
|
||||
/*
|
||||
* pfil_remove_hook removes a specific function from the packet filter hook
|
||||
* chain.
|
||||
@ -354,7 +396,9 @@ pfil_chain_add(pfil_chain_t *chain, struct packet_filter_hook *pfh1, int flags)
|
||||
* First make sure the hook is not already there.
|
||||
*/
|
||||
TAILQ_FOREACH(pfh, chain, pfil_chain)
|
||||
if (pfh->pfil_func == pfh1->pfil_func &&
|
||||
if (((pfh->pfil_func != NULL && pfh->pfil_func == pfh1->pfil_func) ||
|
||||
(pfh->pfil_func_flags != NULL &&
|
||||
pfh->pfil_func_flags == pfh1->pfil_func_flags)) &&
|
||||
pfh->pfil_arg == pfh1->pfil_arg)
|
||||
return (EEXIST);
|
||||
|
||||
@ -373,12 +417,13 @@ pfil_chain_add(pfil_chain_t *chain, struct packet_filter_hook *pfh1, int flags)
|
||||
* Internal: Remove a pfil hook from a hook chain.
|
||||
*/
|
||||
static int
|
||||
pfil_chain_remove(pfil_chain_t *chain, pfil_func_t func, void *arg)
|
||||
pfil_chain_remove(pfil_chain_t *chain, void *func, void *arg)
|
||||
{
|
||||
struct packet_filter_hook *pfh;
|
||||
|
||||
TAILQ_FOREACH(pfh, chain, pfil_chain)
|
||||
if (pfh->pfil_func == func && pfh->pfil_arg == arg) {
|
||||
if ((pfh->pfil_func == func || pfh->pfil_func_flags == func) &&
|
||||
pfh->pfil_arg == arg) {
|
||||
TAILQ_REMOVE(chain, pfh, pfil_chain);
|
||||
free(pfh, M_IFADDR);
|
||||
return (0);
|
||||
|
@ -48,6 +48,8 @@ struct inpcb;
|
||||
|
||||
typedef int (*pfil_func_t)(void *, struct mbuf **, struct ifnet *, int,
|
||||
struct inpcb *);
|
||||
typedef int (*pfil_func_flags_t)(void *, struct mbuf **, struct ifnet *,
|
||||
int, int, struct inpcb *);
|
||||
|
||||
/*
|
||||
* The packet filter hooks are designed for anything to call them to
|
||||
@ -56,13 +58,15 @@ typedef int (*pfil_func_t)(void *, struct mbuf **, struct ifnet *, int,
|
||||
*/
|
||||
struct packet_filter_hook {
|
||||
TAILQ_ENTRY(packet_filter_hook) pfil_chain;
|
||||
pfil_func_t pfil_func;
|
||||
void *pfil_arg;
|
||||
pfil_func_t pfil_func;
|
||||
pfil_func_flags_t pfil_func_flags;
|
||||
void *pfil_arg;
|
||||
};
|
||||
|
||||
#define PFIL_IN 0x00000001
|
||||
#define PFIL_OUT 0x00000002
|
||||
#define PFIL_WAITOK 0x00000004
|
||||
#define PFIL_FWD 0x00000008
|
||||
#define PFIL_ALL (PFIL_IN|PFIL_OUT)
|
||||
|
||||
typedef TAILQ_HEAD(pfil_chain, packet_filter_hook) pfil_chain_t;
|
||||
@ -102,13 +106,15 @@ VNET_DECLARE(struct rmlock, pfil_lock);
|
||||
|
||||
/* Public functions for pfil hook management by packet filters. */
|
||||
struct pfil_head *pfil_head_get(int, u_long);
|
||||
int pfil_add_hook_flags(pfil_func_flags_t, void *, int, struct pfil_head *);
|
||||
int pfil_add_hook(pfil_func_t, void *, int, struct pfil_head *);
|
||||
int pfil_remove_hook_flags(pfil_func_flags_t, void *, int, struct pfil_head *);
|
||||
int pfil_remove_hook(pfil_func_t, void *, int, struct pfil_head *);
|
||||
#define PFIL_HOOKED(p) ((p)->ph_nhooks > 0)
|
||||
|
||||
/* Public functions to run the packet inspection by protocols. */
|
||||
int pfil_run_hooks(struct pfil_head *, struct mbuf **, struct ifnet *,
|
||||
int, struct inpcb *inp);
|
||||
int pfil_run_hooks(struct pfil_head *, struct mbuf **, struct ifnet *, int,
|
||||
int, struct inpcb *inp);
|
||||
|
||||
/* Public functions for pfil head management by protocols. */
|
||||
int pfil_head_register(struct pfil_head *);
|
||||
|
@ -1578,13 +1578,13 @@ extern void pf_addrcpy(struct pf_addr *, struct pf_addr *,
|
||||
void pf_free_rule(struct pf_rule *);
|
||||
|
||||
#ifdef INET
|
||||
int pf_test(int, struct ifnet *, struct mbuf **, struct inpcb *);
|
||||
int pf_test(int, int, struct ifnet *, struct mbuf **, struct inpcb *);
|
||||
int pf_normalize_ip(struct mbuf **, int, struct pfi_kif *, u_short *,
|
||||
struct pf_pdesc *);
|
||||
#endif /* INET */
|
||||
|
||||
#ifdef INET6
|
||||
int pf_test6(int, struct ifnet *, struct mbuf **, struct inpcb *);
|
||||
int pf_test6(int, int, struct ifnet *, struct mbuf **, struct inpcb *);
|
||||
int pf_normalize_ip6(struct mbuf **, int, struct pfi_kif *, u_short *,
|
||||
struct pf_pdesc *);
|
||||
void pf_poolmask(struct pf_addr *, struct pf_addr*,
|
||||
|
@ -232,7 +232,7 @@ ip_tryforward(struct mbuf *m)
|
||||
goto passin;
|
||||
|
||||
if (pfil_run_hooks(
|
||||
&V_inet_pfil_hook, &m, m->m_pkthdr.rcvif, PFIL_IN, NULL) ||
|
||||
&V_inet_pfil_hook, &m, m->m_pkthdr.rcvif, PFIL_IN, 0, NULL) ||
|
||||
m == NULL)
|
||||
goto drop;
|
||||
|
||||
@ -305,8 +305,8 @@ passin:
|
||||
if (!PFIL_HOOKED(&V_inet_pfil_hook))
|
||||
goto passout;
|
||||
|
||||
if (pfil_run_hooks(&V_inet_pfil_hook, &m, nh.nh_ifp, PFIL_OUT, NULL) ||
|
||||
m == NULL) {
|
||||
if (pfil_run_hooks(&V_inet_pfil_hook, &m, nh.nh_ifp, PFIL_OUT, PFIL_FWD,
|
||||
NULL) || m == NULL) {
|
||||
goto drop;
|
||||
}
|
||||
|
||||
|
@ -600,7 +600,7 @@ tooshort:
|
||||
goto passin;
|
||||
|
||||
odst = ip->ip_dst;
|
||||
if (pfil_run_hooks(&V_inet_pfil_hook, &m, ifp, PFIL_IN, NULL) != 0)
|
||||
if (pfil_run_hooks(&V_inet_pfil_hook, &m, ifp, PFIL_IN, 0, NULL) != 0)
|
||||
return;
|
||||
if (m == NULL) /* consumed by filter */
|
||||
return;
|
||||
|
@ -117,7 +117,7 @@ ip_output_pfil(struct mbuf **mp, struct ifnet *ifp, struct inpcb *inp,
|
||||
|
||||
/* Run through list of hooks for output packets. */
|
||||
odst.s_addr = ip->ip_dst.s_addr;
|
||||
*error = pfil_run_hooks(&V_inet_pfil_hook, mp, ifp, PFIL_OUT, inp);
|
||||
*error = pfil_run_hooks(&V_inet_pfil_hook, mp, ifp, PFIL_OUT, 0, inp);
|
||||
m = *mp;
|
||||
if ((*error) != 0 || m == NULL)
|
||||
return 1; /* Finished */
|
||||
|
@ -157,7 +157,7 @@ ip6_tryforward(struct mbuf *m)
|
||||
*/
|
||||
if (!PFIL_HOOKED(&V_inet6_pfil_hook))
|
||||
goto passin;
|
||||
if (pfil_run_hooks(&V_inet6_pfil_hook, &m, rcvif, PFIL_IN,
|
||||
if (pfil_run_hooks(&V_inet6_pfil_hook, &m, rcvif, PFIL_IN, 0,
|
||||
NULL) != 0 || m == NULL)
|
||||
goto dropin;
|
||||
/*
|
||||
@ -201,7 +201,7 @@ passin:
|
||||
if (!PFIL_HOOKED(&V_inet6_pfil_hook))
|
||||
goto passout;
|
||||
if (pfil_run_hooks(&V_inet6_pfil_hook, &m, nh.nh_ifp, PFIL_OUT,
|
||||
NULL) != 0 || m == NULL)
|
||||
PFIL_FWD, NULL) != 0 || m == NULL)
|
||||
goto dropout;
|
||||
|
||||
/*
|
||||
|
@ -324,8 +324,9 @@ again2:
|
||||
goto pass;
|
||||
|
||||
odst = ip6->ip6_dst;
|
||||
/* Run through list of hooks for output packets. */
|
||||
error = pfil_run_hooks(&V_inet6_pfil_hook, &m, rt->rt_ifp, PFIL_OUT, NULL);
|
||||
/* Run through list of hooks for forwarded packets. */
|
||||
error = pfil_run_hooks(&V_inet6_pfil_hook, &m, rt->rt_ifp, PFIL_OUT,
|
||||
PFIL_FWD, NULL);
|
||||
if (error != 0 || m == NULL)
|
||||
goto freecopy; /* consumed by filter */
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
|
@ -761,7 +761,7 @@ ip6_input(struct mbuf *m)
|
||||
|
||||
odst = ip6->ip6_dst;
|
||||
if (pfil_run_hooks(&V_inet6_pfil_hook, &m,
|
||||
m->m_pkthdr.rcvif, PFIL_IN, NULL))
|
||||
m->m_pkthdr.rcvif, PFIL_IN, 0, NULL))
|
||||
return;
|
||||
if (m == NULL) /* consumed by filter */
|
||||
return;
|
||||
|
@ -785,7 +785,7 @@ again:
|
||||
|
||||
odst = ip6->ip6_dst;
|
||||
/* Run through list of hooks for output packets. */
|
||||
error = pfil_run_hooks(&V_inet6_pfil_hook, &m, ifp, PFIL_OUT, inp);
|
||||
error = pfil_run_hooks(&V_inet6_pfil_hook, &m, ifp, PFIL_OUT, 0, inp);
|
||||
if (error != 0 || m == NULL)
|
||||
goto done;
|
||||
/* adjust pointer */
|
||||
|
@ -70,6 +70,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <net/radix_mpath.h>
|
||||
#include <net/vnet.h>
|
||||
|
||||
#include <net/pfil.h>
|
||||
#include <net/pfvar.h>
|
||||
#include <net/if_pflog.h>
|
||||
#include <net/if_pfsync.h>
|
||||
@ -5506,7 +5507,7 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
|
||||
goto bad;
|
||||
|
||||
if (oifp != ifp) {
|
||||
if (pf_test(PF_OUT, ifp, &m0, NULL) != PF_PASS)
|
||||
if (pf_test(PF_OUT, 0, ifp, &m0, NULL) != PF_PASS)
|
||||
goto bad;
|
||||
else if (m0 == NULL)
|
||||
goto done;
|
||||
@ -5668,7 +5669,7 @@ pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
|
||||
goto bad;
|
||||
|
||||
if (oifp != ifp) {
|
||||
if (pf_test6(PF_FWD, ifp, &m0, NULL) != PF_PASS)
|
||||
if (pf_test6(PF_OUT, PFIL_FWD, ifp, &m0, NULL) != PF_PASS)
|
||||
goto bad;
|
||||
else if (m0 == NULL)
|
||||
goto done;
|
||||
@ -5858,7 +5859,7 @@ pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p, sa_family_t a
|
||||
|
||||
#ifdef INET
|
||||
int
|
||||
pf_test(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp)
|
||||
pf_test(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp)
|
||||
{
|
||||
struct pfi_kif *kif;
|
||||
u_short action, reason = 0, log = 0;
|
||||
@ -6245,7 +6246,7 @@ done:
|
||||
|
||||
#ifdef INET6
|
||||
int
|
||||
pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp)
|
||||
pf_test6(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp)
|
||||
{
|
||||
struct pfi_kif *kif;
|
||||
u_short action, reason = 0, log = 0;
|
||||
@ -6257,28 +6258,9 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp)
|
||||
struct pf_ruleset *ruleset = NULL;
|
||||
struct pf_pdesc pd;
|
||||
int off, terminal = 0, dirndx, rh_cnt = 0, pqid = 0;
|
||||
int fwdir = dir;
|
||||
|
||||
M_ASSERTPKTHDR(m);
|
||||
|
||||
/* Detect packet forwarding.
|
||||
* If the input interface is different from the output interface we're
|
||||
* forwarding.
|
||||
* We do need to be careful about bridges. If the
|
||||
* net.link.bridge.pfil_bridge sysctl is set we can be filtering on a
|
||||
* bridge, so if the input interface is a bridge member and the output
|
||||
* interface is its bridge or a member of the same bridge we're not
|
||||
* actually forwarding but bridging.
|
||||
*/
|
||||
if (dir == PF_OUT && m->m_pkthdr.rcvif && ifp != m->m_pkthdr.rcvif &&
|
||||
(m->m_pkthdr.rcvif->if_bridge == NULL ||
|
||||
(m->m_pkthdr.rcvif->if_bridge != ifp->if_softc &&
|
||||
m->m_pkthdr.rcvif->if_bridge != ifp->if_bridge)))
|
||||
fwdir = PF_FWD;
|
||||
|
||||
if (dir == PF_FWD)
|
||||
dir = PF_OUT;
|
||||
|
||||
if (!V_pf_status.running)
|
||||
return (PF_PASS);
|
||||
|
||||
@ -6656,7 +6638,7 @@ done:
|
||||
PF_STATE_UNLOCK(s);
|
||||
|
||||
/* If reassembled packet passed, create new fragments. */
|
||||
if (action == PF_PASS && *m0 && fwdir == PF_FWD &&
|
||||
if (action == PF_PASS && *m0 && (pflags & PFIL_FWD) &&
|
||||
(mtag = m_tag_find(m, PF_REASSEMBLED, NULL)) != NULL)
|
||||
action = pf_refragment6(ifp, m0, mtag);
|
||||
|
||||
|
@ -45,7 +45,7 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
enum { PF_INOUT, PF_IN, PF_OUT, PF_FWD };
|
||||
enum { PF_INOUT, PF_IN, PF_OUT };
|
||||
enum { PF_PASS, PF_DROP, PF_SCRUB, PF_NOSCRUB, PF_NAT, PF_NONAT,
|
||||
PF_BINAT, PF_NOBINAT, PF_RDR, PF_NORDR, PF_SYNPROXY_DROP, PF_DEFER };
|
||||
enum { PF_RULESET_SCRUB, PF_RULESET_FILTER, PF_RULESET_NAT,
|
||||
|
@ -165,15 +165,15 @@ static void pf_tbladdr_copyout(struct pf_addr_wrap *);
|
||||
*/
|
||||
#ifdef INET
|
||||
static int pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp,
|
||||
int dir, struct inpcb *inp);
|
||||
int dir, int flags, struct inpcb *inp);
|
||||
static int pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp,
|
||||
int dir, struct inpcb *inp);
|
||||
int dir, int flags, struct inpcb *inp);
|
||||
#endif
|
||||
#ifdef INET6
|
||||
static int pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp,
|
||||
int dir, struct inpcb *inp);
|
||||
int dir, int flags, struct inpcb *inp);
|
||||
static int pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp,
|
||||
int dir, struct inpcb *inp);
|
||||
int dir, int flags, struct inpcb *inp);
|
||||
#endif
|
||||
|
||||
static int hook_pf(void);
|
||||
@ -3649,12 +3649,12 @@ shutdown_pf(void)
|
||||
|
||||
#ifdef INET
|
||||
static int
|
||||
pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
|
||||
pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir, int flags,
|
||||
struct inpcb *inp)
|
||||
{
|
||||
int chk;
|
||||
|
||||
chk = pf_test(PF_IN, ifp, m, inp);
|
||||
chk = pf_test(PF_IN, flags, ifp, m, inp);
|
||||
if (chk && *m) {
|
||||
m_freem(*m);
|
||||
*m = NULL;
|
||||
@ -3666,12 +3666,12 @@ pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
|
||||
}
|
||||
|
||||
static int
|
||||
pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
|
||||
pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir, int flags,
|
||||
struct inpcb *inp)
|
||||
{
|
||||
int chk;
|
||||
|
||||
chk = pf_test(PF_OUT, ifp, m, inp);
|
||||
chk = pf_test(PF_OUT, flags, ifp, m, inp);
|
||||
if (chk && *m) {
|
||||
m_freem(*m);
|
||||
*m = NULL;
|
||||
@ -3685,7 +3685,7 @@ pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
|
||||
|
||||
#ifdef INET6
|
||||
static int
|
||||
pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
|
||||
pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir, int flags,
|
||||
struct inpcb *inp)
|
||||
{
|
||||
int chk;
|
||||
@ -3696,7 +3696,7 @@ pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
|
||||
* filtering we have change this to lo0 as it is the case in IPv4.
|
||||
*/
|
||||
CURVNET_SET(ifp->if_vnet);
|
||||
chk = pf_test6(PF_IN, (*m)->m_flags & M_LOOP ? V_loif : ifp, m, inp);
|
||||
chk = pf_test6(PF_IN, flags, (*m)->m_flags & M_LOOP ? V_loif : ifp, m, inp);
|
||||
CURVNET_RESTORE();
|
||||
if (chk && *m) {
|
||||
m_freem(*m);
|
||||
@ -3708,13 +3708,13 @@ pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
|
||||
}
|
||||
|
||||
static int
|
||||
pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
|
||||
pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir, int flags,
|
||||
struct inpcb *inp)
|
||||
{
|
||||
int chk;
|
||||
|
||||
CURVNET_SET(ifp->if_vnet);
|
||||
chk = pf_test6(PF_OUT, ifp, m, inp);
|
||||
chk = pf_test6(PF_OUT, flags, ifp, m, inp);
|
||||
CURVNET_RESTORE();
|
||||
if (chk && *m) {
|
||||
m_freem(*m);
|
||||
@ -3743,22 +3743,22 @@ hook_pf(void)
|
||||
pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
|
||||
if (pfh_inet == NULL)
|
||||
return (ESRCH); /* XXX */
|
||||
pfil_add_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet);
|
||||
pfil_add_hook(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet);
|
||||
pfil_add_hook_flags(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet);
|
||||
pfil_add_hook_flags(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet);
|
||||
#endif
|
||||
#ifdef INET6
|
||||
pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
|
||||
if (pfh_inet6 == NULL) {
|
||||
#ifdef INET
|
||||
pfil_remove_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK,
|
||||
pfil_remove_hook_flags(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK,
|
||||
pfh_inet);
|
||||
pfil_remove_hook(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
|
||||
pfil_remove_hook_flags(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
|
||||
pfh_inet);
|
||||
#endif
|
||||
return (ESRCH); /* XXX */
|
||||
}
|
||||
pfil_add_hook(pf_check6_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet6);
|
||||
pfil_add_hook(pf_check6_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet6);
|
||||
pfil_add_hook_flags(pf_check6_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet6);
|
||||
pfil_add_hook_flags(pf_check6_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet6);
|
||||
#endif
|
||||
|
||||
V_pf_pfil_hooked = 1;
|
||||
@ -3782,18 +3782,18 @@ dehook_pf(void)
|
||||
pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
|
||||
if (pfh_inet == NULL)
|
||||
return (ESRCH); /* XXX */
|
||||
pfil_remove_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK,
|
||||
pfil_remove_hook_flags(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK,
|
||||
pfh_inet);
|
||||
pfil_remove_hook(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
|
||||
pfil_remove_hook_flags(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
|
||||
pfh_inet);
|
||||
#endif
|
||||
#ifdef INET6
|
||||
pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
|
||||
if (pfh_inet6 == NULL)
|
||||
return (ESRCH); /* XXX */
|
||||
pfil_remove_hook(pf_check6_in, NULL, PFIL_IN | PFIL_WAITOK,
|
||||
pfil_remove_hook_flags(pf_check6_in, NULL, PFIL_IN | PFIL_WAITOK,
|
||||
pfh_inet6);
|
||||
pfil_remove_hook(pf_check6_out, NULL, PFIL_OUT | PFIL_WAITOK,
|
||||
pfil_remove_hook_flags(pf_check6_out, NULL, PFIL_OUT | PFIL_WAITOK,
|
||||
pfh_inet6);
|
||||
#endif
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user