mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 16:50:25 -04:00
ipsec: allow it to work with unmapped mbufs
Only map mbuf when a policy is looked up and indicates that IPSEC needs to transform the packet. If IPSEC is inline offloaded, it is up to the interface driver to request remap if needed. Fetch the IP header using m_copydata() instead of using mtod() to select policy/SA. Reviewed by: markj Sponsored by: NVidia networking Differential revision: https://reviews.freebsd.org/D48265
This commit is contained in:
parent
b0e020764a
commit
0ff2d00d2a
9 changed files with 126 additions and 114 deletions
|
|
@ -353,7 +353,7 @@ ipsec_transmit(struct ifnet *ifp, struct mbuf *m)
|
|||
IPSEC_RLOCK_TRACKER;
|
||||
struct ipsec_softc *sc;
|
||||
struct secpolicy *sp;
|
||||
struct ip *ip;
|
||||
struct ip *ip, iph;
|
||||
uint32_t af;
|
||||
int error;
|
||||
|
||||
|
|
@ -375,7 +375,8 @@ ipsec_transmit(struct ifnet *ifp, struct mbuf *m)
|
|||
}
|
||||
|
||||
/* Determine address family to correctly handle packet in BPF */
|
||||
ip = mtod(m, struct ip *);
|
||||
ip = &iph;
|
||||
m_copydata(m, 0, sizeof(*ip), (char *)ip);
|
||||
switch (ip->ip_v) {
|
||||
#ifdef INET
|
||||
case IPVERSION:
|
||||
|
|
@ -415,7 +416,8 @@ ipsec_transmit(struct ifnet *ifp, struct mbuf *m)
|
|||
switch (af) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
error = ipsec4_process_packet(ifp, m, sp, NULL, ifp->if_mtu);
|
||||
error = ipsec4_process_packet(ifp, m, ip, sp, NULL,
|
||||
ifp->if_mtu);
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
|
|
|
|||
|
|
@ -667,26 +667,19 @@ again:
|
|||
sendit:
|
||||
#if defined(IPSEC) || defined(IPSEC_SUPPORT)
|
||||
if (IPSEC_ENABLED(ipv4)) {
|
||||
struct mbuf *m1;
|
||||
struct ip ip_hdr;
|
||||
|
||||
error = mb_unmapped_to_ext(m, &m1);
|
||||
if (error != 0) {
|
||||
if (error == ENOMEM) {
|
||||
IPSTAT_INC(ips_odropped);
|
||||
error = ENOBUFS;
|
||||
goto bad;
|
||||
}
|
||||
/* XXXKIB */
|
||||
goto no_ipsec;
|
||||
}
|
||||
m = m1;
|
||||
if ((error = IPSEC_OUTPUT(ipv4, ifp, m, inp, mtu)) != 0) {
|
||||
if (error == EINPROGRESS)
|
||||
error = 0;
|
||||
goto done;
|
||||
}
|
||||
no_ipsec:;
|
||||
|
||||
/* Update variables that are affected by ipsec4_output(). */
|
||||
m_copydata(m, 0, sizeof(ip_hdr), (char *)&ip_hdr);
|
||||
hlen = ip_hdr.ip_hl << 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if there was a route for this packet; return error if not.
|
||||
*/
|
||||
|
|
@ -695,9 +688,6 @@ no_ipsec:;
|
|||
error = EHOSTUNREACH;
|
||||
goto bad;
|
||||
}
|
||||
/* Update variables that are affected by ipsec4_output(). */
|
||||
ip = mtod(m, struct ip *);
|
||||
hlen = ip->ip_hl << 2;
|
||||
#endif /* IPSEC */
|
||||
|
||||
/* Jump over all PFIL processing if hooks are not active. */
|
||||
|
|
|
|||
|
|
@ -792,26 +792,12 @@ nonh6lookup:
|
|||
* XXX: need scope argument.
|
||||
*/
|
||||
if (IPSEC_ENABLED(ipv6)) {
|
||||
struct mbuf *m1;
|
||||
|
||||
error = mb_unmapped_to_ext(m, &m1);
|
||||
if (error != 0) {
|
||||
if (error == ENOMEM) {
|
||||
IP6STAT_INC(ip6s_odropped);
|
||||
error = ENOBUFS;
|
||||
goto bad;
|
||||
}
|
||||
/* XXXKIB */
|
||||
goto no_ipsec;
|
||||
}
|
||||
m = m1;
|
||||
if ((error = IPSEC_OUTPUT(ipv6, ifp, m, inp, mtu == 0 ?
|
||||
ifp->if_mtu : mtu)) != 0) {
|
||||
if (error == EINPROGRESS)
|
||||
error = 0;
|
||||
goto done;
|
||||
}
|
||||
no_ipsec:;
|
||||
}
|
||||
#endif /* IPSEC */
|
||||
|
||||
|
|
|
|||
|
|
@ -286,8 +286,9 @@ static int ipsec_in_reject(struct secpolicy *, struct inpcb *,
|
|||
const struct mbuf *);
|
||||
|
||||
#ifdef INET
|
||||
static void ipsec4_get_ulp(const struct mbuf *, struct secpolicyindex *, int);
|
||||
static void ipsec4_setspidx_ipaddr(const struct mbuf *,
|
||||
static void ipsec4_get_ulp(const struct mbuf *, const struct ip *,
|
||||
struct secpolicyindex *, int);
|
||||
static void ipsec4_setspidx_ipaddr(const struct mbuf *, struct ip *,
|
||||
struct secpolicyindex *);
|
||||
#endif
|
||||
#ifdef INET6
|
||||
|
|
@ -488,8 +489,8 @@ ipsec_getpcbpolicy(struct inpcb *inp, u_int dir)
|
|||
|
||||
#ifdef INET
|
||||
static void
|
||||
ipsec4_get_ulp(const struct mbuf *m, struct secpolicyindex *spidx,
|
||||
int needport)
|
||||
ipsec4_get_ulp(const struct mbuf *m, const struct ip *ip1,
|
||||
struct secpolicyindex *spidx, int needport)
|
||||
{
|
||||
uint8_t nxt;
|
||||
int off;
|
||||
|
|
@ -498,21 +499,10 @@ ipsec4_get_ulp(const struct mbuf *m, struct secpolicyindex *spidx,
|
|||
IPSEC_ASSERT(m->m_pkthdr.len >= sizeof(struct ip),
|
||||
("packet too short"));
|
||||
|
||||
if (m->m_len >= sizeof (struct ip)) {
|
||||
const struct ip *ip = mtod(m, const struct ip *);
|
||||
if (ip->ip_off & htons(IP_MF | IP_OFFMASK))
|
||||
goto done;
|
||||
off = ip->ip_hl << 2;
|
||||
nxt = ip->ip_p;
|
||||
} else {
|
||||
struct ip ih;
|
||||
|
||||
m_copydata(m, 0, sizeof (struct ip), (caddr_t) &ih);
|
||||
if (ih.ip_off & htons(IP_MF | IP_OFFMASK))
|
||||
goto done;
|
||||
off = ih.ip_hl << 2;
|
||||
nxt = ih.ip_p;
|
||||
}
|
||||
if (ip1->ip_off & htons(IP_MF | IP_OFFMASK))
|
||||
goto done;
|
||||
off = ip1->ip_hl << 2;
|
||||
nxt = ip1->ip_p;
|
||||
|
||||
while (off < m->m_pkthdr.len) {
|
||||
struct ip6_ext ip6e;
|
||||
|
|
@ -565,17 +555,18 @@ done_proto:
|
|||
}
|
||||
|
||||
static void
|
||||
ipsec4_setspidx_ipaddr(const struct mbuf *m, struct secpolicyindex *spidx)
|
||||
ipsec4_setspidx_ipaddr(const struct mbuf *m, struct ip *ip1,
|
||||
struct secpolicyindex *spidx)
|
||||
{
|
||||
|
||||
ipsec4_setsockaddrs(m, &spidx->src, &spidx->dst);
|
||||
ipsec4_setsockaddrs(m, ip1, &spidx->src, &spidx->dst);
|
||||
spidx->prefs = sizeof(struct in_addr) << 3;
|
||||
spidx->prefd = sizeof(struct in_addr) << 3;
|
||||
}
|
||||
|
||||
static struct secpolicy *
|
||||
ipsec4_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir,
|
||||
int needport)
|
||||
ipsec4_getpolicy(const struct mbuf *m, struct inpcb *inp, struct ip *ip1,
|
||||
u_int dir, int needport)
|
||||
{
|
||||
struct secpolicyindex spidx;
|
||||
struct secpolicy *sp;
|
||||
|
|
@ -583,8 +574,8 @@ ipsec4_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir,
|
|||
sp = ipsec_getpcbpolicy(inp, dir);
|
||||
if (sp == NULL && key_havesp(dir)) {
|
||||
/* Make an index to look for a policy. */
|
||||
ipsec4_setspidx_ipaddr(m, &spidx);
|
||||
ipsec4_get_ulp(m, &spidx, needport);
|
||||
ipsec4_setspidx_ipaddr(m, ip1, &spidx);
|
||||
ipsec4_get_ulp(m, ip1, &spidx, needport);
|
||||
spidx.dir = dir;
|
||||
sp = key_allocsp(&spidx, dir);
|
||||
}
|
||||
|
|
@ -597,13 +588,13 @@ ipsec4_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir,
|
|||
* Check security policy for *OUTBOUND* IPv4 packet.
|
||||
*/
|
||||
struct secpolicy *
|
||||
ipsec4_checkpolicy(const struct mbuf *m, struct inpcb *inp, int *error,
|
||||
int needport)
|
||||
ipsec4_checkpolicy(const struct mbuf *m, struct inpcb *inp, struct ip *ip1,
|
||||
int *error, int needport)
|
||||
{
|
||||
struct secpolicy *sp;
|
||||
|
||||
*error = 0;
|
||||
sp = ipsec4_getpolicy(m, inp, IPSEC_DIR_OUTBOUND, needport);
|
||||
sp = ipsec4_getpolicy(m, inp, ip1, IPSEC_DIR_OUTBOUND, needport);
|
||||
if (sp != NULL)
|
||||
sp = ipsec_checkpolicy(sp, inp, error);
|
||||
if (sp == NULL) {
|
||||
|
|
@ -630,12 +621,13 @@ ipsec4_checkpolicy(const struct mbuf *m, struct inpcb *inp, int *error,
|
|||
* rip_input() and sctp_input().
|
||||
*/
|
||||
int
|
||||
ipsec4_in_reject(const struct mbuf *m, struct inpcb *inp)
|
||||
ipsec4_in_reject1(const struct mbuf *m, struct ip *ip1, struct inpcb *inp)
|
||||
{
|
||||
struct secpolicy *sp;
|
||||
#ifdef IPSEC_OFFLOAD
|
||||
struct ipsec_accel_in_tag *tag;
|
||||
#endif
|
||||
struct ip ip_hdr;
|
||||
int result;
|
||||
|
||||
#ifdef IPSEC_OFFLOAD
|
||||
|
|
@ -643,7 +635,13 @@ ipsec4_in_reject(const struct mbuf *m, struct inpcb *inp)
|
|||
if (tag != NULL)
|
||||
return (0);
|
||||
#endif
|
||||
sp = ipsec4_getpolicy(m, inp, IPSEC_DIR_INBOUND, 0);
|
||||
|
||||
if (ip1 == NULL) {
|
||||
ip1 = &ip_hdr;
|
||||
m_copydata(m, 0, sizeof(*ip1), (char *)ip1);
|
||||
}
|
||||
|
||||
sp = ipsec4_getpolicy(m, inp, ip1, IPSEC_DIR_INBOUND, 0);
|
||||
result = ipsec_in_reject(sp, inp, m);
|
||||
key_freesp(&sp);
|
||||
if (result != 0)
|
||||
|
|
@ -651,6 +649,12 @@ ipsec4_in_reject(const struct mbuf *m, struct inpcb *inp)
|
|||
return (result);
|
||||
}
|
||||
|
||||
int
|
||||
ipsec4_in_reject(const struct mbuf *m, struct inpcb *inp)
|
||||
{
|
||||
return (ipsec4_in_reject1(m, NULL, inp));
|
||||
}
|
||||
|
||||
/*
|
||||
* IPSEC_CAP() method implementation for IPv4.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -325,6 +325,7 @@ VNET_DECLARE(int, natt_cksum_policy);
|
|||
#endif
|
||||
|
||||
struct inpcb;
|
||||
struct ip;
|
||||
struct m_tag;
|
||||
struct secasvar;
|
||||
struct sockopt;
|
||||
|
|
@ -336,7 +337,7 @@ int ipsec_if_input(struct mbuf *, struct secasvar *, uint32_t);
|
|||
struct ipsecrequest *ipsec_newisr(void);
|
||||
void ipsec_delisr(struct ipsecrequest *);
|
||||
struct secpolicy *ipsec4_checkpolicy(const struct mbuf *, struct inpcb *,
|
||||
int *, int);
|
||||
struct ip *, int *, int);
|
||||
|
||||
u_int ipsec_get_reqlevel(struct secpolicy *, u_int);
|
||||
|
||||
|
|
@ -351,12 +352,13 @@ size_t ipsec_hdrsiz_internal(struct secpolicy *);
|
|||
|
||||
void ipsec_setspidx_inpcb(struct inpcb *, struct secpolicyindex *, u_int);
|
||||
|
||||
void ipsec4_setsockaddrs(const struct mbuf *, union sockaddr_union *,
|
||||
union sockaddr_union *);
|
||||
void ipsec4_setsockaddrs(const struct mbuf *, const struct ip *,
|
||||
union sockaddr_union *, union sockaddr_union *);
|
||||
int ipsec4_common_input_cb(struct mbuf *, struct secasvar *, int, int);
|
||||
int ipsec4_check_pmtu(struct ifnet *, struct mbuf *, struct secpolicy *, int);
|
||||
int ipsec4_process_packet(struct ifnet *, struct mbuf *, struct secpolicy *,
|
||||
struct inpcb *, u_long);
|
||||
int ipsec4_check_pmtu(struct ifnet *, struct mbuf *, struct ip *ip1,
|
||||
struct secpolicy *, int);
|
||||
int ipsec4_process_packet(struct ifnet *, struct mbuf *, struct ip *ip1,
|
||||
struct secpolicy *, struct inpcb *, u_long);
|
||||
int ipsec_process_done(struct mbuf *, struct secpolicy *, struct secasvar *,
|
||||
u_int);
|
||||
|
||||
|
|
|
|||
|
|
@ -111,14 +111,13 @@ static size_t ipsec_get_pmtu(struct secasvar *sav);
|
|||
|
||||
#ifdef INET
|
||||
static struct secasvar *
|
||||
ipsec4_allocsa(struct ifnet *ifp, struct mbuf *m, struct secpolicy *sp,
|
||||
u_int *pidx, int *error)
|
||||
ipsec4_allocsa(struct ifnet *ifp, struct mbuf *m, const struct ip *ip,
|
||||
struct secpolicy *sp, u_int *pidx, int *error)
|
||||
{
|
||||
struct secasindex *saidx, tmpsaidx;
|
||||
struct ipsecrequest *isr;
|
||||
struct sockaddr_in *sin;
|
||||
struct secasvar *sav;
|
||||
struct ip *ip;
|
||||
|
||||
/*
|
||||
* Check system global policy controls.
|
||||
|
|
@ -142,7 +141,6 @@ next:
|
|||
if (isr->saidx.mode == IPSEC_MODE_TRANSPORT) {
|
||||
saidx = &tmpsaidx;
|
||||
*saidx = isr->saidx;
|
||||
ip = mtod(m, struct ip *);
|
||||
if (saidx->src.sa.sa_len == 0) {
|
||||
sin = &saidx->src.sin;
|
||||
sin->sin_len = sizeof(*sin);
|
||||
|
|
@ -188,13 +186,14 @@ next:
|
|||
* IPsec output logic for IPv4.
|
||||
*/
|
||||
static int
|
||||
ipsec4_perform_request(struct ifnet *ifp, struct mbuf *m, struct secpolicy *sp,
|
||||
struct inpcb *inp, u_int idx, u_long mtu)
|
||||
ipsec4_perform_request(struct ifnet *ifp, struct mbuf *m, struct ip *ip1,
|
||||
struct secpolicy *sp, struct inpcb *inp, u_int idx, u_long mtu)
|
||||
{
|
||||
struct ipsec_ctx_data ctx;
|
||||
union sockaddr_union *dst;
|
||||
struct secasvar *sav;
|
||||
struct ip *ip;
|
||||
struct mbuf *m1;
|
||||
int error, hwassist, i, off;
|
||||
bool accel;
|
||||
|
||||
|
|
@ -209,7 +208,7 @@ ipsec4_perform_request(struct ifnet *ifp, struct mbuf *m, struct secpolicy *sp,
|
|||
* determine next transform. At the end of transform we can
|
||||
* release reference to SP.
|
||||
*/
|
||||
sav = ipsec4_allocsa(ifp, m, sp, &idx, &error);
|
||||
sav = ipsec4_allocsa(ifp, m, ip1, sp, &idx, &error);
|
||||
if (sav == NULL) {
|
||||
if (error == EJUSTRETURN) { /* No IPsec required */
|
||||
(void)ipsec_accel_output(ifp, m, inp, sp, NULL,
|
||||
|
|
@ -225,6 +224,8 @@ ipsec4_perform_request(struct ifnet *ifp, struct mbuf *m, struct secpolicy *sp,
|
|||
IPSEC_INIT_CTX(&ctx, &m, inp, sav, AF_INET, IPSEC_ENC_BEFORE);
|
||||
if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0)
|
||||
goto bad;
|
||||
/* Re-calculate *ip1 after potential change of m in the hook. */
|
||||
m_copydata(m, 0, sizeof(*ip1), (char *)ip1);
|
||||
|
||||
hwassist = 0;
|
||||
accel = ipsec_accel_output(ifp, m, inp, sp, sav, AF_INET, mtu,
|
||||
|
|
@ -240,16 +241,23 @@ ipsec4_perform_request(struct ifnet *ifp, struct mbuf *m, struct secpolicy *sp,
|
|||
}
|
||||
#if defined(SCTP) || defined(SCTP_SUPPORT)
|
||||
if ((m->m_pkthdr.csum_flags & CSUM_SCTP & ~hwassist) != 0) {
|
||||
struct ip *ip;
|
||||
|
||||
ip = mtod(m, struct ip *);
|
||||
sctp_delayed_cksum(m, (uint32_t)(ip->ip_hl << 2));
|
||||
sctp_delayed_cksum(m, (uint32_t)(ip1->ip_hl << 2));
|
||||
m->m_pkthdr.csum_flags &= ~CSUM_SCTP;
|
||||
}
|
||||
#endif
|
||||
if (accel)
|
||||
return (EJUSTRETURN);
|
||||
|
||||
error = mb_unmapped_to_ext(m, &m1);
|
||||
if (error != 0) {
|
||||
if (error == EINVAL) {
|
||||
if (bootverbose)
|
||||
if_printf(ifp, "Tx TLS+IPSEC packet\n");
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
m = m1;
|
||||
|
||||
ip = mtod(m, struct ip *);
|
||||
dst = &sav->sah->saidx.dst;
|
||||
/* Do the appropriate encapsulation, if necessary */
|
||||
|
|
@ -317,19 +325,18 @@ bad:
|
|||
}
|
||||
|
||||
int
|
||||
ipsec4_process_packet(struct ifnet *ifp, struct mbuf *m, struct secpolicy *sp,
|
||||
struct inpcb *inp, u_long mtu)
|
||||
ipsec4_process_packet(struct ifnet *ifp, struct mbuf *m, struct ip *ip1,
|
||||
struct secpolicy *sp, struct inpcb *inp, u_long mtu)
|
||||
{
|
||||
|
||||
return (ipsec4_perform_request(ifp, m, sp, inp, 0, mtu));
|
||||
return (ipsec4_perform_request(ifp, m, ip1, sp, inp, 0, mtu));
|
||||
}
|
||||
|
||||
int
|
||||
ipsec4_check_pmtu(struct ifnet *ifp, struct mbuf *m, struct secpolicy *sp,
|
||||
int forwarding)
|
||||
ipsec4_check_pmtu(struct ifnet *ifp, struct mbuf *m, struct ip *ip1,
|
||||
struct secpolicy *sp, int forwarding)
|
||||
{
|
||||
struct secasvar *sav;
|
||||
struct ip *ip;
|
||||
size_t hlen, pmtu;
|
||||
uint32_t idx;
|
||||
int error;
|
||||
|
|
@ -341,13 +348,12 @@ ipsec4_check_pmtu(struct ifnet *ifp, struct mbuf *m, struct secpolicy *sp,
|
|||
goto setdf;
|
||||
|
||||
/* V_ip4_ipsec_dfbit > 1 - we will copy it from inner header. */
|
||||
ip = mtod(m, struct ip *);
|
||||
if (!(ip->ip_off & htons(IP_DF)))
|
||||
if ((ip1->ip_off & htons(IP_DF)) == 0)
|
||||
return (0);
|
||||
|
||||
setdf:
|
||||
idx = sp->tcount - 1;
|
||||
sav = ipsec4_allocsa(ifp, m, sp, &idx, &error);
|
||||
sav = ipsec4_allocsa(ifp, m, ip1, sp, &idx, &error);
|
||||
if (sav == NULL) {
|
||||
key_freesp(&sp);
|
||||
/*
|
||||
|
|
@ -398,14 +404,14 @@ setdf:
|
|||
}
|
||||
|
||||
static int
|
||||
ipsec4_common_output(struct ifnet *ifp, struct mbuf *m, struct inpcb *inp,
|
||||
int forwarding, u_long mtu)
|
||||
ipsec4_common_output1(struct ifnet *ifp, struct mbuf *m, struct inpcb *inp,
|
||||
struct ip *ip1, int forwarding, u_long mtu)
|
||||
{
|
||||
struct secpolicy *sp;
|
||||
int error;
|
||||
|
||||
/* Lookup for the corresponding outbound security policy */
|
||||
sp = ipsec4_checkpolicy(m, inp, &error, !forwarding);
|
||||
sp = ipsec4_checkpolicy(m, inp, ip1, &error, !forwarding);
|
||||
if (sp == NULL) {
|
||||
if (error == -EINVAL) {
|
||||
/* Discarded by policy. */
|
||||
|
|
@ -425,7 +431,7 @@ ipsec4_common_output(struct ifnet *ifp, struct mbuf *m, struct inpcb *inp,
|
|||
*/
|
||||
|
||||
/* NB: callee frees mbuf and releases reference to SP */
|
||||
error = ipsec4_check_pmtu(ifp, m, sp, forwarding);
|
||||
error = ipsec4_check_pmtu(ifp, m, ip1, sp, forwarding);
|
||||
if (error != 0) {
|
||||
if (error == EJUSTRETURN)
|
||||
return (0);
|
||||
|
|
@ -433,7 +439,7 @@ ipsec4_common_output(struct ifnet *ifp, struct mbuf *m, struct inpcb *inp,
|
|||
return (error);
|
||||
}
|
||||
|
||||
error = ipsec4_process_packet(ifp, m, sp, inp, mtu);
|
||||
error = ipsec4_process_packet(ifp, m, ip1, sp, inp, mtu);
|
||||
if (error == EJUSTRETURN) {
|
||||
/*
|
||||
* We had a SP with a level of 'use' and no SA. We
|
||||
|
|
@ -447,6 +453,28 @@ ipsec4_common_output(struct ifnet *ifp, struct mbuf *m, struct inpcb *inp,
|
|||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
ipsec4_common_output(struct ifnet *ifp, struct mbuf *m, struct inpcb *inp,
|
||||
struct ip *ip1, int forwarding, u_long mtu)
|
||||
{
|
||||
struct ip ip_hdr;
|
||||
struct ip *ip;
|
||||
|
||||
if (((m->m_flags & M_PKTHDR) != 0 && m->m_pkthdr.len < sizeof(*ip)) ||
|
||||
((m->m_flags & M_PKTHDR) == 0 && m->m_len < sizeof(*ip))) {
|
||||
m_free(m);
|
||||
return (EACCES);
|
||||
}
|
||||
if (ip1 != NULL) {
|
||||
ip = ip1;
|
||||
} else {
|
||||
ip = &ip_hdr;
|
||||
m_copydata(m, 0, sizeof(*ip), (char *)ip);
|
||||
}
|
||||
|
||||
return (ipsec4_common_output1(ifp, m, inp, ip, forwarding, mtu));
|
||||
}
|
||||
|
||||
/*
|
||||
* IPSEC_OUTPUT() method implementation for IPv4.
|
||||
* 0 - no IPsec handling needed
|
||||
|
|
@ -464,7 +492,7 @@ ipsec4_output(struct ifnet *ifp, struct mbuf *m, struct inpcb *inp, u_long mtu)
|
|||
if (m_tag_find(m, PACKET_TAG_IPSEC_OUT_DONE, NULL) != NULL)
|
||||
return (0);
|
||||
|
||||
return (ipsec4_common_output(ifp, m, inp, 0, mtu));
|
||||
return (ipsec4_common_output(ifp, m, inp, NULL, 0, mtu));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -475,16 +503,20 @@ ipsec4_output(struct ifnet *ifp, struct mbuf *m, struct inpcb *inp, u_long mtu)
|
|||
int
|
||||
ipsec4_forward(struct mbuf *m)
|
||||
{
|
||||
struct ip ip_hdr;
|
||||
|
||||
m_copydata(m, 0, sizeof(ip_hdr), (char *)&ip_hdr);
|
||||
|
||||
/*
|
||||
* Check if this packet has an active inbound SP and needs to be
|
||||
* dropped instead of forwarded.
|
||||
*/
|
||||
if (ipsec4_in_reject(m, NULL) != 0) {
|
||||
if (ipsec4_in_reject1(m, &ip_hdr, NULL) != 0) {
|
||||
m_freem(m);
|
||||
return (EACCES);
|
||||
}
|
||||
return (ipsec4_common_output(NULL /* XXXKIB */, m, NULL, 1, 0));
|
||||
return (ipsec4_common_output(NULL /* XXXKIB */, m, NULL, &ip_hdr,
|
||||
1, 0));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -874,6 +906,9 @@ ipsec_process_done(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
|
|||
struct xform_history *xh;
|
||||
struct secasindex *saidx;
|
||||
struct m_tag *mtag;
|
||||
#ifdef INET
|
||||
struct ip *ip;
|
||||
#endif
|
||||
int error;
|
||||
|
||||
if (sav->state >= SADB_SASTATE_DEAD) {
|
||||
|
|
@ -884,8 +919,9 @@ ipsec_process_done(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
|
|||
switch (saidx->dst.sa.sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
ip = mtod(m, struct ip *);
|
||||
/* Fix the header length, for AH processing. */
|
||||
mtod(m, struct ip *)->ip_len = htons(m->m_pkthdr.len);
|
||||
ip->ip_len = htons(m->m_pkthdr.len);
|
||||
break;
|
||||
#endif /* INET */
|
||||
#ifdef INET6
|
||||
|
|
@ -943,7 +979,7 @@ ipsec_process_done(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
|
|||
case AF_INET:
|
||||
key_freesav(&sav);
|
||||
IPSECSTAT_INC(ips_out_bundlesa);
|
||||
return (ipsec4_perform_request(NULL, m, sp, NULL,
|
||||
return (ipsec4_perform_request(NULL, m, ip, sp, NULL,
|
||||
idx, 0));
|
||||
/* NOTREACHED */
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#ifdef _KERNEL
|
||||
#if defined(IPSEC) || defined(IPSEC_SUPPORT)
|
||||
struct ifnet;
|
||||
struct ip;
|
||||
struct mbuf;
|
||||
struct inpcb;
|
||||
struct tcphdr;
|
||||
|
|
@ -56,6 +57,7 @@ int udp_ipsec_pcbctl(struct inpcb *, struct sockopt *);
|
|||
#endif
|
||||
#ifdef INET
|
||||
int ipsec4_in_reject(const struct mbuf *, struct inpcb *);
|
||||
int ipsec4_in_reject1(const struct mbuf *m, struct ip *ip1, struct inpcb *inp);
|
||||
int ipsec4_input(struct mbuf *, int, int);
|
||||
int ipsec4_forward(struct mbuf *);
|
||||
int ipsec4_pcbctl(struct inpcb *, struct sockopt *);
|
||||
|
|
|
|||
|
|
@ -61,8 +61,8 @@
|
|||
|
||||
#ifdef INET
|
||||
void
|
||||
ipsec4_setsockaddrs(const struct mbuf *m, union sockaddr_union *src,
|
||||
union sockaddr_union *dst)
|
||||
ipsec4_setsockaddrs(const struct mbuf *m, const struct ip *ip1,
|
||||
union sockaddr_union *src, union sockaddr_union *dst)
|
||||
{
|
||||
static const struct sockaddr_in template = {
|
||||
sizeof (struct sockaddr_in),
|
||||
|
|
@ -73,18 +73,8 @@ ipsec4_setsockaddrs(const struct mbuf *m, union sockaddr_union *src,
|
|||
src->sin = template;
|
||||
dst->sin = template;
|
||||
|
||||
if (m->m_len < sizeof (struct ip)) {
|
||||
m_copydata(m, offsetof(struct ip, ip_src),
|
||||
sizeof (struct in_addr),
|
||||
(caddr_t) &src->sin.sin_addr);
|
||||
m_copydata(m, offsetof(struct ip, ip_dst),
|
||||
sizeof (struct in_addr),
|
||||
(caddr_t) &dst->sin.sin_addr);
|
||||
} else {
|
||||
const struct ip *ip = mtod(m, const struct ip *);
|
||||
src->sin.sin_addr = ip->ip_src;
|
||||
dst->sin.sin_addr = ip->ip_dst;
|
||||
}
|
||||
src->sin.sin_addr = ip1->ip_src;
|
||||
dst->sin.sin_addr = ip1->ip_dst;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ setsockaddrs(const struct mbuf *m, union sockaddr_union *src,
|
|||
switch (ip->ip_v) {
|
||||
#ifdef INET
|
||||
case IPVERSION:
|
||||
ipsec4_setsockaddrs(m, src, dst);
|
||||
ipsec4_setsockaddrs(m, ip, src, dst);
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
|
|
|
|||
Loading…
Reference in a new issue