Add to if_enc(4) ability to capture packets via BPF after pfil processing.

New flag 0x4 can be configured in net.enc.[in|out].ipsec_bpf_mask.
When it is set, if_enc(4) additionally captures a packet via BPF after
invoking pfil hook. This may be useful for debugging.

MFC after:	2 weeks
Sponsored by:	Yandex LLC
Differential Revision:	https://reviews.freebsd.org/D11804
This commit is contained in:
Andrey V. Elsukov 2017-08-09 12:24:07 +00:00
parent 6750c3d0fa
commit 95e8b991ca
2 changed files with 46 additions and 17 deletions

View File

@ -31,7 +31,7 @@
.\" .\"
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd November 28, 2007 .Dd August 9, 2017
.Dt ENC 4 .Dt ENC 4
.Os .Os
.Sh NAME .Sh NAME
@ -44,6 +44,13 @@ kernel configuration file:
.Bd -ragged -offset indent .Bd -ragged -offset indent
.Cd "device enc" .Cd "device enc"
.Ed .Ed
.Pp
Alternatively, to load the driver as a
module at boot time, place the following line in
.Xr loader.conf 5 :
.Bd -literal -offset indent
if_enc_load="YES"
.Ed
.Sh DESCRIPTION .Sh DESCRIPTION
The The
.Nm .Nm
@ -115,6 +122,11 @@ outgoing path |------|
Most people will want to run with the suggested defaults for Most people will want to run with the suggested defaults for
.Cm ipsec_filter_mask .Cm ipsec_filter_mask
and rely on the security policy database for the outer headers. and rely on the security policy database for the outer headers.
.Pp
Note that packets are captured by BPF before firewall processing.
The special value 0x4 can be configured in the
.Ar ipsec_bpf_mask
and packets will be also captured after firewall processing.
.Sh EXAMPLES .Sh EXAMPLES
To see the packets the processed via To see the packets the processed via
.Xr ipsec 4 , .Xr ipsec 4 ,

View File

@ -99,9 +99,15 @@ static void enc_remove_hhooks(struct enc_softc *);
static const char encname[] = "enc"; static const char encname[] = "enc";
#define IPSEC_ENC_AFTER_PFIL 0x04
/* /*
* Before and after are relative to when we are stripping the * Before and after are relative to when we are stripping the
* outer IP header. * outer IP header.
*
* AFTER_PFIL flag used only for bpf_mask_*. It enables BPF capturing
* after PFIL hook execution. It might be useful when PFIL hook does
* some changes to the packet, e.g. address translation. If PFIL hook
* consumes mbuf, nothing will be captured.
*/ */
static VNET_DEFINE(int, filter_mask_in) = IPSEC_ENC_BEFORE; static VNET_DEFINE(int, filter_mask_in) = IPSEC_ENC_BEFORE;
static VNET_DEFINE(int, bpf_mask_in) = IPSEC_ENC_BEFORE; static VNET_DEFINE(int, bpf_mask_in) = IPSEC_ENC_BEFORE;
@ -194,6 +200,30 @@ enc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
return (0); return (0);
} }
static void
enc_bpftap(struct ifnet *ifp, struct mbuf *m, const struct secasvar *sav,
int32_t hhook_type, uint8_t enc, uint8_t af)
{
struct enchdr hdr;
if (hhook_type == HHOOK_TYPE_IPSEC_IN &&
(enc & V_bpf_mask_in) == 0)
return;
else if (hhook_type == HHOOK_TYPE_IPSEC_OUT &&
(enc & V_bpf_mask_out) == 0)
return;
if (bpf_peers_present(ifp->if_bpf) == 0)
return;
hdr.af = af;
hdr.spi = sav->spi;
hdr.flags = 0;
if (sav->alg_enc != SADB_EALG_NONE)
hdr.flags |= M_CONF;
if (sav->alg_auth != SADB_AALG_NONE)
hdr.flags |= M_AUTH;
bpf_mtap2(ifp->if_bpf, &hdr, sizeof(hdr), m);
}
/* /*
* One helper hook function is used by any hook points. * One helper hook function is used by any hook points.
* + from hhook_type we can determine the packet direction: * + from hhook_type we can determine the packet direction:
@ -206,7 +236,6 @@ static int
enc_hhook(int32_t hhook_type, int32_t hhook_id, void *udata, void *ctx_data, enc_hhook(int32_t hhook_type, int32_t hhook_id, void *udata, void *ctx_data,
void *hdata, struct osd *hosd) void *hdata, struct osd *hosd)
{ {
struct enchdr hdr;
struct ipsec_ctx_data *ctx; struct ipsec_ctx_data *ctx;
struct enc_softc *sc; struct enc_softc *sc;
struct ifnet *ifp, *rcvif; struct ifnet *ifp, *rcvif;
@ -223,21 +252,7 @@ enc_hhook(int32_t hhook_type, int32_t hhook_id, void *udata, void *ctx_data,
if (ctx->af != hhook_id) if (ctx->af != hhook_id)
return (EPFNOSUPPORT); return (EPFNOSUPPORT);
if (((hhook_type == HHOOK_TYPE_IPSEC_IN && enc_bpftap(ifp, *ctx->mp, ctx->sav, hhook_type, ctx->enc, ctx->af);
(ctx->enc & V_bpf_mask_in) != 0) ||
(hhook_type == HHOOK_TYPE_IPSEC_OUT &&
(ctx->enc & V_bpf_mask_out) != 0)) &&
bpf_peers_present(ifp->if_bpf) != 0) {
hdr.af = ctx->af;
hdr.spi = ctx->sav->spi;
hdr.flags = 0;
if (ctx->sav->alg_enc != SADB_EALG_NONE)
hdr.flags |= M_CONF;
if (ctx->sav->alg_auth != SADB_AALG_NONE)
hdr.flags |= M_AUTH;
bpf_mtap2(ifp->if_bpf, &hdr, sizeof(hdr), *ctx->mp);
}
switch (hhook_type) { switch (hhook_type) {
case HHOOK_TYPE_IPSEC_IN: case HHOOK_TYPE_IPSEC_IN:
if (ctx->enc == IPSEC_ENC_BEFORE) { if (ctx->enc == IPSEC_ENC_BEFORE) {
@ -290,6 +305,8 @@ enc_hhook(int32_t hhook_type, int32_t hhook_id, void *udata, void *ctx_data,
return (EACCES); return (EACCES);
} }
(*ctx->mp)->m_pkthdr.rcvif = rcvif; (*ctx->mp)->m_pkthdr.rcvif = rcvif;
enc_bpftap(ifp, *ctx->mp, ctx->sav, hhook_type,
IPSEC_ENC_AFTER_PFIL, ctx->af);
return (0); return (0);
} }