1bdea400fSAndrew Thompson /*- 2bdea400fSAndrew Thompson * Copyright (c) 2006 The FreeBSD Project. 3bdea400fSAndrew Thompson * All rights reserved. 4bdea400fSAndrew Thompson * 5bdea400fSAndrew Thompson * Redistribution and use in source and binary forms, with or without 6bdea400fSAndrew Thompson * modification, are permitted provided that the following conditions 7bdea400fSAndrew Thompson * are met: 8bdea400fSAndrew Thompson * 9bdea400fSAndrew Thompson * 1. Redistributions of source code must retain the above copyright 10bdea400fSAndrew Thompson * notice, this list of conditions and the following disclaimer. 11bdea400fSAndrew Thompson * 2. Redistributions in binary form must reproduce the above copyright 12bdea400fSAndrew Thompson * notice, this list of conditions and the following disclaimer in the 13bdea400fSAndrew Thompson * documentation and/or other materials provided with the distribution. 14bdea400fSAndrew Thompson * 15bdea400fSAndrew Thompson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16bdea400fSAndrew Thompson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17bdea400fSAndrew Thompson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18bdea400fSAndrew Thompson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19bdea400fSAndrew Thompson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20bdea400fSAndrew Thompson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21bdea400fSAndrew Thompson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22bdea400fSAndrew Thompson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23bdea400fSAndrew Thompson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24bdea400fSAndrew Thompson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25bdea400fSAndrew Thompson * SUCH DAMAGE. 26bdea400fSAndrew Thompson * 27bdea400fSAndrew Thompson * $FreeBSD$ 28bdea400fSAndrew Thompson */ 29bdea400fSAndrew Thompson 30*a0ae8f04SBjoern A. Zeeb #include "opt_inet.h" 31*a0ae8f04SBjoern A. Zeeb #include "opt_inet6.h" 32*a0ae8f04SBjoern A. Zeeb #include "opt_enc.h" 33*a0ae8f04SBjoern A. Zeeb 34bdea400fSAndrew Thompson #include <sys/param.h> 35bdea400fSAndrew Thompson #include <sys/systm.h> 36bdea400fSAndrew Thompson #include <sys/kernel.h> 37bdea400fSAndrew Thompson #include <sys/malloc.h> 38bdea400fSAndrew Thompson #include <sys/mbuf.h> 39bdea400fSAndrew Thompson #include <sys/module.h> 40bdea400fSAndrew Thompson #include <machine/bus.h> 41bdea400fSAndrew Thompson #include <sys/rman.h> 42bdea400fSAndrew Thompson #include <sys/socket.h> 43bdea400fSAndrew Thompson #include <sys/sockio.h> 44bdea400fSAndrew Thompson #include <sys/sysctl.h> 45bdea400fSAndrew Thompson 46bdea400fSAndrew Thompson #include <net/if.h> 47bdea400fSAndrew Thompson #include <net/if_clone.h> 48bdea400fSAndrew Thompson #include <net/if_types.h> 49bdea400fSAndrew Thompson #include <net/pfil.h> 50bdea400fSAndrew Thompson #include <net/route.h> 51bdea400fSAndrew Thompson #include <net/netisr.h> 52bdea400fSAndrew Thompson #include <net/bpf.h> 53eddfbb76SRobert Watson #include <net/vnet.h> 54bdea400fSAndrew Thompson 55bdea400fSAndrew Thompson #include <netinet/in.h> 56bdea400fSAndrew Thompson #include <netinet/in_systm.h> 57bdea400fSAndrew Thompson #include <netinet/ip.h> 58bdea400fSAndrew Thompson #include <netinet/ip_var.h> 59bdea400fSAndrew Thompson #include <netinet/in_var.h> 60bdea400fSAndrew Thompson 61bdea400fSAndrew Thompson #ifdef INET6 62bdea400fSAndrew Thompson #include <netinet/ip6.h> 63bdea400fSAndrew Thompson #include <netinet6/ip6_var.h> 64bdea400fSAndrew Thompson #endif 65bdea400fSAndrew Thompson 66bdea400fSAndrew Thompson #include <netipsec/ipsec.h> 6719ad9831SBjoern A. Zeeb #include <netipsec/xform.h> 68bdea400fSAndrew Thompson 69bdea400fSAndrew Thompson #define ENCMTU (1024+512) 70bdea400fSAndrew Thompson 71bdea400fSAndrew Thompson /* XXX this define must have the same value as in OpenBSD */ 72bdea400fSAndrew Thompson #define M_CONF 0x0400 /* payload was encrypted (ESP-transport) */ 73bdea400fSAndrew Thompson #define M_AUTH 0x0800 /* payload was authenticated (AH or ESP auth) */ 74bdea400fSAndrew Thompson #define M_AUTH_AH 0x2000 /* header was authenticated (AH) */ 75bdea400fSAndrew Thompson 76bdea400fSAndrew Thompson struct enchdr { 77bdea400fSAndrew Thompson u_int32_t af; 78bdea400fSAndrew Thompson u_int32_t spi; 79bdea400fSAndrew Thompson u_int32_t flags; 80bdea400fSAndrew Thompson }; 81bdea400fSAndrew Thompson 8297c2a697SVANHULLEBUS Yvan struct ifnet *encif; 83bdea400fSAndrew Thompson static struct mtx enc_mtx; 84bdea400fSAndrew Thompson 85bdea400fSAndrew Thompson struct enc_softc { 86bdea400fSAndrew Thompson struct ifnet *sc_ifp; 87bdea400fSAndrew Thompson }; 88bdea400fSAndrew Thompson 89bdea400fSAndrew Thompson static int enc_ioctl(struct ifnet *, u_long, caddr_t); 90bdea400fSAndrew Thompson static int enc_output(struct ifnet *ifp, struct mbuf *m, 91279aa3d4SKip Macy struct sockaddr *dst, struct route *ro); 9207ed9a88SAndrew Thompson static int enc_clone_create(struct if_clone *, int, caddr_t); 93bac89dceSAndrew Thompson static void enc_clone_destroy(struct ifnet *); 94bdea400fSAndrew Thompson 95bdea400fSAndrew Thompson IFC_SIMPLE_DECLARE(enc, 1); 96bdea400fSAndrew Thompson 9719ad9831SBjoern A. Zeeb /* 9819ad9831SBjoern A. Zeeb * Sysctls. 9919ad9831SBjoern A. Zeeb */ 10019ad9831SBjoern A. Zeeb 10119ad9831SBjoern A. Zeeb /* 10219ad9831SBjoern A. Zeeb * Before and after are relative to when we are stripping the 10319ad9831SBjoern A. Zeeb * outer IP header. 10419ad9831SBjoern A. Zeeb */ 10519ad9831SBjoern A. Zeeb SYSCTL_NODE(_net, OID_AUTO, enc, CTLFLAG_RW, 0, "enc sysctl"); 10619ad9831SBjoern A. Zeeb 10719ad9831SBjoern A. Zeeb SYSCTL_NODE(_net_enc, OID_AUTO, in, CTLFLAG_RW, 0, "enc input sysctl"); 10819ad9831SBjoern A. Zeeb static int ipsec_filter_mask_in = ENC_BEFORE; 109f8e4b4efSMatthew D Fleming SYSCTL_INT(_net_enc_in, OID_AUTO, ipsec_filter_mask, CTLFLAG_RW, 11019ad9831SBjoern A. Zeeb &ipsec_filter_mask_in, 0, "IPsec input firewall filter mask"); 11119ad9831SBjoern A. Zeeb static int ipsec_bpf_mask_in = ENC_BEFORE; 112f8e4b4efSMatthew D Fleming SYSCTL_INT(_net_enc_in, OID_AUTO, ipsec_bpf_mask, CTLFLAG_RW, 11319ad9831SBjoern A. Zeeb &ipsec_bpf_mask_in, 0, "IPsec input bpf mask"); 11419ad9831SBjoern A. Zeeb 11519ad9831SBjoern A. Zeeb SYSCTL_NODE(_net_enc, OID_AUTO, out, CTLFLAG_RW, 0, "enc output sysctl"); 11619ad9831SBjoern A. Zeeb static int ipsec_filter_mask_out = ENC_BEFORE; 117f8e4b4efSMatthew D Fleming SYSCTL_INT(_net_enc_out, OID_AUTO, ipsec_filter_mask, CTLFLAG_RW, 11819ad9831SBjoern A. Zeeb &ipsec_filter_mask_out, 0, "IPsec output firewall filter mask"); 11919ad9831SBjoern A. Zeeb static int ipsec_bpf_mask_out = ENC_BEFORE|ENC_AFTER; 120f8e4b4efSMatthew D Fleming SYSCTL_INT(_net_enc_out, OID_AUTO, ipsec_bpf_mask, CTLFLAG_RW, 12119ad9831SBjoern A. Zeeb &ipsec_bpf_mask_out, 0, "IPsec output bpf mask"); 12219ad9831SBjoern A. Zeeb 123bac89dceSAndrew Thompson static void 124bdea400fSAndrew Thompson enc_clone_destroy(struct ifnet *ifp) 125bdea400fSAndrew Thompson { 126bac89dceSAndrew Thompson KASSERT(ifp != encif, ("%s: destroying encif", __func__)); 127bdea400fSAndrew Thompson 128bdea400fSAndrew Thompson bpfdetach(ifp); 129bdea400fSAndrew Thompson if_detach(ifp); 130bdea400fSAndrew Thompson if_free(ifp); 131bdea400fSAndrew Thompson } 132bdea400fSAndrew Thompson 133bdea400fSAndrew Thompson static int 13407ed9a88SAndrew Thompson enc_clone_create(struct if_clone *ifc, int unit, caddr_t params) 135bdea400fSAndrew Thompson { 136bdea400fSAndrew Thompson struct ifnet *ifp; 137bdea400fSAndrew Thompson struct enc_softc *sc; 138bdea400fSAndrew Thompson 139bdea400fSAndrew Thompson sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); 140bdea400fSAndrew Thompson ifp = sc->sc_ifp = if_alloc(IFT_ENC); 141bdea400fSAndrew Thompson if (ifp == NULL) { 142bdea400fSAndrew Thompson free(sc, M_DEVBUF); 143bdea400fSAndrew Thompson return (ENOSPC); 144bdea400fSAndrew Thompson } 145bdea400fSAndrew Thompson 146bdea400fSAndrew Thompson if_initname(ifp, ifc->ifc_name, unit); 147bdea400fSAndrew Thompson ifp->if_mtu = ENCMTU; 148bdea400fSAndrew Thompson ifp->if_ioctl = enc_ioctl; 149bdea400fSAndrew Thompson ifp->if_output = enc_output; 150bdea400fSAndrew Thompson ifp->if_snd.ifq_maxlen = ifqmaxlen; 151bdea400fSAndrew Thompson ifp->if_softc = sc; 152bdea400fSAndrew Thompson if_attach(ifp); 153f0ac1eedSAndrew Thompson bpfattach(ifp, DLT_ENC, sizeof(struct enchdr)); 154bdea400fSAndrew Thompson 155bdea400fSAndrew Thompson mtx_lock(&enc_mtx); 156ae4748adSAndrew Thompson /* grab a pointer to enc0, ignore the rest */ 157ae4748adSAndrew Thompson if (encif == NULL) 158bdea400fSAndrew Thompson encif = ifp; 159bdea400fSAndrew Thompson mtx_unlock(&enc_mtx); 160bdea400fSAndrew Thompson 161bdea400fSAndrew Thompson return (0); 162bdea400fSAndrew Thompson } 163bdea400fSAndrew Thompson 164bdea400fSAndrew Thompson static int 165bdea400fSAndrew Thompson enc_modevent(module_t mod, int type, void *data) 166bdea400fSAndrew Thompson { 167bdea400fSAndrew Thompson switch (type) { 168bdea400fSAndrew Thompson case MOD_LOAD: 169bdea400fSAndrew Thompson mtx_init(&enc_mtx, "enc mtx", NULL, MTX_DEF); 170bdea400fSAndrew Thompson if_clone_attach(&enc_cloner); 171bdea400fSAndrew Thompson break; 172bdea400fSAndrew Thompson case MOD_UNLOAD: 173bdea400fSAndrew Thompson printf("enc module unload - not possible for this module\n"); 174bdea400fSAndrew Thompson return (EINVAL); 175bdea400fSAndrew Thompson default: 176bdea400fSAndrew Thompson return (EOPNOTSUPP); 177bdea400fSAndrew Thompson } 178bdea400fSAndrew Thompson return (0); 179bdea400fSAndrew Thompson } 180bdea400fSAndrew Thompson 181bdea400fSAndrew Thompson static moduledata_t enc_mod = { 182bdea400fSAndrew Thompson "enc", 183bdea400fSAndrew Thompson enc_modevent, 184bdea400fSAndrew Thompson 0 185bdea400fSAndrew Thompson }; 186bdea400fSAndrew Thompson 187bdea400fSAndrew Thompson DECLARE_MODULE(enc, enc_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY); 188bdea400fSAndrew Thompson 189bdea400fSAndrew Thompson static int 190bdea400fSAndrew Thompson enc_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 191279aa3d4SKip Macy struct route *ro) 192bdea400fSAndrew Thompson { 193bdea400fSAndrew Thompson m_freem(m); 194bdea400fSAndrew Thompson return (0); 195bdea400fSAndrew Thompson } 196bdea400fSAndrew Thompson 197bdea400fSAndrew Thompson /* 198bdea400fSAndrew Thompson * Process an ioctl request. 199bdea400fSAndrew Thompson */ 200bdea400fSAndrew Thompson /* ARGSUSED */ 201bdea400fSAndrew Thompson static int 202bdea400fSAndrew Thompson enc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 203bdea400fSAndrew Thompson { 204bdea400fSAndrew Thompson int error = 0; 205bdea400fSAndrew Thompson 206ae4748adSAndrew Thompson mtx_lock(&enc_mtx); 207ae4748adSAndrew Thompson 208bdea400fSAndrew Thompson switch (cmd) { 209bdea400fSAndrew Thompson 210bdea400fSAndrew Thompson case SIOCSIFFLAGS: 211bdea400fSAndrew Thompson if (ifp->if_flags & IFF_UP) 212bdea400fSAndrew Thompson ifp->if_drv_flags |= IFF_DRV_RUNNING; 213bdea400fSAndrew Thompson else 214bdea400fSAndrew Thompson ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 215bdea400fSAndrew Thompson 216bdea400fSAndrew Thompson break; 217bdea400fSAndrew Thompson 218bdea400fSAndrew Thompson default: 219bdea400fSAndrew Thompson error = EINVAL; 220bdea400fSAndrew Thompson } 221ae4748adSAndrew Thompson 222ae4748adSAndrew Thompson mtx_unlock(&enc_mtx); 223bdea400fSAndrew Thompson return (error); 224bdea400fSAndrew Thompson } 225bdea400fSAndrew Thompson 226bdea400fSAndrew Thompson int 22719ad9831SBjoern A. Zeeb ipsec_filter(struct mbuf **mp, int dir, int flags) 228bdea400fSAndrew Thompson { 229bdea400fSAndrew Thompson int error, i; 230bdea400fSAndrew Thompson struct ip *ip; 231bdea400fSAndrew Thompson 232ae4748adSAndrew Thompson KASSERT(encif != NULL, ("%s: encif is null", __func__)); 23319ad9831SBjoern A. Zeeb KASSERT(flags & (ENC_IN|ENC_OUT), 23419ad9831SBjoern A. Zeeb ("%s: invalid flags: %04x", __func__, flags)); 235ae4748adSAndrew Thompson 236ae4748adSAndrew Thompson if ((encif->if_drv_flags & IFF_DRV_RUNNING) == 0) 237bdea400fSAndrew Thompson return (0); 238bdea400fSAndrew Thompson 23919ad9831SBjoern A. Zeeb if (flags & ENC_IN) { 24019ad9831SBjoern A. Zeeb if ((flags & ipsec_filter_mask_in) == 0) 24119ad9831SBjoern A. Zeeb return (0); 24219ad9831SBjoern A. Zeeb } else { 24319ad9831SBjoern A. Zeeb if ((flags & ipsec_filter_mask_out) == 0) 24419ad9831SBjoern A. Zeeb return (0); 24519ad9831SBjoern A. Zeeb } 24619ad9831SBjoern A. Zeeb 247bdea400fSAndrew Thompson /* Skip pfil(9) if no filters are loaded */ 248*a0ae8f04SBjoern A. Zeeb if (1 249*a0ae8f04SBjoern A. Zeeb #ifdef INET 250*a0ae8f04SBjoern A. Zeeb && !PFIL_HOOKED(&V_inet_pfil_hook) 251bdea400fSAndrew Thompson #endif 252*a0ae8f04SBjoern A. Zeeb #ifdef INET6 253*a0ae8f04SBjoern A. Zeeb && !PFIL_HOOKED(&V_inet6_pfil_hook) 254*a0ae8f04SBjoern A. Zeeb #endif 255*a0ae8f04SBjoern A. Zeeb ) { 256bdea400fSAndrew Thompson return (0); 257bdea400fSAndrew Thompson } 258bdea400fSAndrew Thompson 259bdea400fSAndrew Thompson i = min((*mp)->m_pkthdr.len, max_protohdr); 260bdea400fSAndrew Thompson if ((*mp)->m_len < i) { 261bdea400fSAndrew Thompson *mp = m_pullup(*mp, i); 262bdea400fSAndrew Thompson if (*mp == NULL) { 263bdea400fSAndrew Thompson printf("%s: m_pullup failed\n", __func__); 264bdea400fSAndrew Thompson return (-1); 265bdea400fSAndrew Thompson } 266bdea400fSAndrew Thompson } 267bdea400fSAndrew Thompson 268bdea400fSAndrew Thompson error = 0; 269bdea400fSAndrew Thompson ip = mtod(*mp, struct ip *); 270bdea400fSAndrew Thompson switch (ip->ip_v) { 271*a0ae8f04SBjoern A. Zeeb #ifdef INET 272bdea400fSAndrew Thompson case 4: 273bdea400fSAndrew Thompson /* 274bdea400fSAndrew Thompson * before calling the firewall, swap fields the same as 275bdea400fSAndrew Thompson * IP does. here we assume the header is contiguous 276bdea400fSAndrew Thompson */ 277bdea400fSAndrew Thompson ip->ip_len = ntohs(ip->ip_len); 278bdea400fSAndrew Thompson ip->ip_off = ntohs(ip->ip_off); 279bdea400fSAndrew Thompson 280382e8b5aSBjoern A. Zeeb error = pfil_run_hooks(&V_inet_pfil_hook, mp, 281bdea400fSAndrew Thompson encif, dir, NULL); 282bdea400fSAndrew Thompson 283bdea400fSAndrew Thompson if (*mp == NULL || error != 0) 284bdea400fSAndrew Thompson break; 285bdea400fSAndrew Thompson 286bdea400fSAndrew Thompson /* restore byte ordering */ 287bdea400fSAndrew Thompson ip = mtod(*mp, struct ip *); 288bdea400fSAndrew Thompson ip->ip_len = htons(ip->ip_len); 289bdea400fSAndrew Thompson ip->ip_off = htons(ip->ip_off); 290bdea400fSAndrew Thompson break; 291*a0ae8f04SBjoern A. Zeeb #endif 292bdea400fSAndrew Thompson #ifdef INET6 293bdea400fSAndrew Thompson case 6: 294382e8b5aSBjoern A. Zeeb error = pfil_run_hooks(&V_inet6_pfil_hook, mp, 295bdea400fSAndrew Thompson encif, dir, NULL); 296bdea400fSAndrew Thompson break; 297bdea400fSAndrew Thompson #endif 298bdea400fSAndrew Thompson default: 299bdea400fSAndrew Thompson printf("%s: unknown IP version\n", __func__); 300bdea400fSAndrew Thompson } 301bdea400fSAndrew Thompson 302e361d7d4SAndrew Thompson /* 303e361d7d4SAndrew Thompson * If the mbuf was consumed by the filter for requeueing (dummynet, etc) 304e361d7d4SAndrew Thompson * then error will be zero but we still want to return an error to our 305e361d7d4SAndrew Thompson * caller so the null mbuf isn't forwarded further. 306e361d7d4SAndrew Thompson */ 307e361d7d4SAndrew Thompson if (*mp == NULL && error == 0) 308e361d7d4SAndrew Thompson return (-1); /* Consumed by the filter */ 309bdea400fSAndrew Thompson if (*mp == NULL) 310bdea400fSAndrew Thompson return (error); 311bdea400fSAndrew Thompson if (error != 0) 312bdea400fSAndrew Thompson goto bad; 313bdea400fSAndrew Thompson 314bdea400fSAndrew Thompson return (error); 315bdea400fSAndrew Thompson 316bdea400fSAndrew Thompson bad: 317bdea400fSAndrew Thompson m_freem(*mp); 318bdea400fSAndrew Thompson *mp = NULL; 319bdea400fSAndrew Thompson return (error); 320bdea400fSAndrew Thompson } 321bdea400fSAndrew Thompson 322bdea400fSAndrew Thompson void 32319ad9831SBjoern A. Zeeb ipsec_bpf(struct mbuf *m, struct secasvar *sav, int af, int flags) 324bdea400fSAndrew Thompson { 32519ad9831SBjoern A. Zeeb int mflags; 326bdea400fSAndrew Thompson struct enchdr hdr; 327bdea400fSAndrew Thompson 328ae4748adSAndrew Thompson KASSERT(encif != NULL, ("%s: encif is null", __func__)); 32919ad9831SBjoern A. Zeeb KASSERT(flags & (ENC_IN|ENC_OUT), 33019ad9831SBjoern A. Zeeb ("%s: invalid flags: %04x", __func__, flags)); 331bdea400fSAndrew Thompson 332ae4748adSAndrew Thompson if ((encif->if_drv_flags & IFF_DRV_RUNNING) == 0) 333bdea400fSAndrew Thompson return; 334bdea400fSAndrew Thompson 33519ad9831SBjoern A. Zeeb if (flags & ENC_IN) { 33619ad9831SBjoern A. Zeeb if ((flags & ipsec_bpf_mask_in) == 0) 33719ad9831SBjoern A. Zeeb return; 33819ad9831SBjoern A. Zeeb } else { 33919ad9831SBjoern A. Zeeb if ((flags & ipsec_bpf_mask_out) == 0) 34019ad9831SBjoern A. Zeeb return; 34119ad9831SBjoern A. Zeeb } 34219ad9831SBjoern A. Zeeb 3430dea849aSJohn Baldwin if (bpf_peers_present(encif->if_bpf)) { 34419ad9831SBjoern A. Zeeb mflags = 0; 34519ad9831SBjoern A. Zeeb hdr.spi = 0; 34619ad9831SBjoern A. Zeeb if (!sav) { 34719ad9831SBjoern A. Zeeb struct m_tag *mtag; 34819ad9831SBjoern A. Zeeb mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); 34919ad9831SBjoern A. Zeeb if (mtag != NULL) { 35019ad9831SBjoern A. Zeeb struct tdb_ident *tdbi; 35119ad9831SBjoern A. Zeeb tdbi = (struct tdb_ident *) (mtag + 1); 35219ad9831SBjoern A. Zeeb if (tdbi->alg_enc != SADB_EALG_NONE) 35319ad9831SBjoern A. Zeeb mflags |= M_CONF; 35419ad9831SBjoern A. Zeeb if (tdbi->alg_auth != SADB_AALG_NONE) 35519ad9831SBjoern A. Zeeb mflags |= M_AUTH; 35619ad9831SBjoern A. Zeeb hdr.spi = tdbi->spi; 35719ad9831SBjoern A. Zeeb } 35819ad9831SBjoern A. Zeeb } else { 359bdea400fSAndrew Thompson if (sav->alg_enc != SADB_EALG_NONE) 36019ad9831SBjoern A. Zeeb mflags |= M_CONF; 361bdea400fSAndrew Thompson if (sav->alg_auth != SADB_AALG_NONE) 36219ad9831SBjoern A. Zeeb mflags |= M_AUTH; 36319ad9831SBjoern A. Zeeb hdr.spi = sav->spi; 36419ad9831SBjoern A. Zeeb } 365bdea400fSAndrew Thompson 366bdea400fSAndrew Thompson /* 367bdea400fSAndrew Thompson * We need to prepend the address family as a four byte 368bdea400fSAndrew Thompson * field. Cons up a dummy header to pacify bpf. This 369bdea400fSAndrew Thompson * is safe because bpf will only read from the mbuf 370bdea400fSAndrew Thompson * (i.e., it won't try to free it or keep a pointer a 371bdea400fSAndrew Thompson * to it). 372bdea400fSAndrew Thompson */ 373bdea400fSAndrew Thompson hdr.af = af; 37419ad9831SBjoern A. Zeeb /* hdr.spi already set above */ 37519ad9831SBjoern A. Zeeb hdr.flags = mflags; 376bdea400fSAndrew Thompson 377f0ac1eedSAndrew Thompson bpf_mtap2(encif->if_bpf, &hdr, sizeof(hdr), m); 378bdea400fSAndrew Thompson } 379bdea400fSAndrew Thompson } 380