Changeset View
Changeset View
Standalone View
Standalone View
sys/netipsec/ipsec_output.c
Show First 20 Lines • Show All 190 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
ipsec4_perform_request(struct ifnet *ifp, struct mbuf *m, struct secpolicy *sp, | ipsec4_perform_request(struct ifnet *ifp, struct mbuf *m, struct secpolicy *sp, | ||||
struct inpcb *inp, u_int idx, u_long mtu) | struct inpcb *inp, u_int idx, u_long mtu) | ||||
{ | { | ||||
struct ipsec_ctx_data ctx; | struct ipsec_ctx_data ctx; | ||||
union sockaddr_union *dst; | union sockaddr_union *dst; | ||||
struct secasvar *sav; | struct secasvar *sav; | ||||
struct ip *ip; | struct ip *ip; | ||||
int error, i, off; | int error, hwassist, i, off; | ||||
bool accel; | |||||
IPSEC_ASSERT(idx < sp->tcount, ("Wrong IPsec request index %d", idx)); | IPSEC_ASSERT(idx < sp->tcount, ("Wrong IPsec request index %d", idx)); | ||||
/* | /* | ||||
* We hold the reference to SP. Content of SP couldn't be changed. | * We hold the reference to SP. Content of SP couldn't be changed. | ||||
* Craft secasindex and do lookup for suitable SA. | * Craft secasindex and do lookup for suitable SA. | ||||
* Then do encapsulation if needed and call xform's output. | * Then do encapsulation if needed and call xform's output. | ||||
* We need to store SP in the xform callback parameters. | * We need to store SP in the xform callback parameters. | ||||
* In xform callback we will extract SP and it can be used to | * In xform callback we will extract SP and it can be used to | ||||
* determine next transform. At the end of transform we can | * determine next transform. At the end of transform we can | ||||
* release reference to SP. | * release reference to SP. | ||||
*/ | */ | ||||
sav = ipsec4_allocsa(ifp, m, sp, &idx, &error); | sav = ipsec4_allocsa(ifp, m, sp, &idx, &error); | ||||
if (sav == NULL) { | if (sav == NULL) { | ||||
if (error == EJUSTRETURN) { /* No IPsec required */ | if (error == EJUSTRETURN) { /* No IPsec required */ | ||||
(void)ipsec_accel_output(ifp, m, inp, sp, NULL, | (void)ipsec_accel_output(ifp, m, inp, sp, NULL, | ||||
AF_INET, mtu); | AF_INET, mtu, &hwassist); | ||||
key_freesp(&sp); | key_freesp(&sp); | ||||
return (error); | return (error); | ||||
} | } | ||||
goto bad; | goto bad; | ||||
} | } | ||||
/* | /* | ||||
* XXXAE: most likely ip_sum at this point is wrong. | * XXXAE: most likely ip_sum at this point is wrong. | ||||
*/ | */ | ||||
IPSEC_INIT_CTX(&ctx, &m, inp, sav, AF_INET, IPSEC_ENC_BEFORE); | IPSEC_INIT_CTX(&ctx, &m, inp, sav, AF_INET, IPSEC_ENC_BEFORE); | ||||
if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0) | if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0) | ||||
goto bad; | goto bad; | ||||
if (ipsec_accel_output(ifp, m, inp, sp, sav, AF_INET, mtu)) | hwassist = 0; | ||||
accel = ipsec_accel_output(ifp, m, inp, sp, sav, AF_INET, mtu, | |||||
&hwassist); | |||||
/* | |||||
* Do delayed checksums now because we send before | |||||
* this is done in the normal processing path. | |||||
*/ | |||||
if ((m->m_pkthdr.csum_flags & CSUM_DELAY_DATA & ~hwassist) != 0) { | |||||
in_delayed_cksum(m); | |||||
m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; | |||||
} | |||||
#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)); | |||||
m->m_pkthdr.csum_flags &= ~CSUM_SCTP; | |||||
} | |||||
#endif | |||||
if (accel) | |||||
return (EJUSTRETURN); | return (EJUSTRETURN); | ||||
ip = mtod(m, struct ip *); | ip = mtod(m, struct ip *); | ||||
dst = &sav->sah->saidx.dst; | dst = &sav->sah->saidx.dst; | ||||
/* Do the appropriate encapsulation, if necessary */ | /* Do the appropriate encapsulation, if necessary */ | ||||
if (sp->req[idx]->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */ | if (sp->req[idx]->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */ | ||||
dst->sa.sa_family != AF_INET || /* PF mismatch */ | dst->sa.sa_family != AF_INET || /* PF mismatch */ | ||||
(dst->sa.sa_family == AF_INET && /* Proxy */ | (dst->sa.sa_family == AF_INET && /* Proxy */ | ||||
▲ Show 20 Lines • Show All 159 Lines • ▼ Show 20 Lines | ipsec4_common_output(struct ifnet *ifp, struct mbuf *m, struct inpcb *inp, | ||||
/* | /* | ||||
* Usually we have to have tunnel mode IPsec security policy | * Usually we have to have tunnel mode IPsec security policy | ||||
* when we are forwarding a packet. Otherwise we could not handle | * when we are forwarding a packet. Otherwise we could not handle | ||||
* encrypted replies, because they are not destined for us. But | * encrypted replies, because they are not destined for us. But | ||||
* some users are doing source address translation for forwarded | * some users are doing source address translation for forwarded | ||||
* packets, and thus, even if they are forwarded, the replies will | * packets, and thus, even if they are forwarded, the replies will | ||||
* return back to us. | * return back to us. | ||||
*/ | */ | ||||
if (!forwarding) { | |||||
/* | |||||
* Do delayed checksums now because we send before | |||||
* this is done in the normal processing path. | |||||
*/ | |||||
if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { | |||||
in_delayed_cksum(m); | |||||
m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; | |||||
} | |||||
#if defined(SCTP) || defined(SCTP_SUPPORT) | |||||
if (m->m_pkthdr.csum_flags & CSUM_SCTP) { | |||||
struct ip *ip; | |||||
ip = mtod(m, struct ip *); | |||||
sctp_delayed_cksum(m, (uint32_t)(ip->ip_hl << 2)); | |||||
m->m_pkthdr.csum_flags &= ~CSUM_SCTP; | |||||
} | |||||
#endif | |||||
} | |||||
/* NB: callee frees mbuf and releases reference to SP */ | /* NB: callee frees mbuf and releases reference to SP */ | ||||
error = ipsec4_check_pmtu(ifp, m, sp, forwarding); | error = ipsec4_check_pmtu(ifp, m, sp, forwarding); | ||||
if (error != 0) { | if (error != 0) { | ||||
if (error == EJUSTRETURN) | if (error == EJUSTRETURN) | ||||
return (0); | return (0); | ||||
return (error); | return (error); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 161 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
ipsec6_perform_request(struct ifnet *ifp, struct mbuf *m, struct secpolicy *sp, | ipsec6_perform_request(struct ifnet *ifp, struct mbuf *m, struct secpolicy *sp, | ||||
struct inpcb *inp, u_int idx, u_long mtu) | struct inpcb *inp, u_int idx, u_long mtu) | ||||
{ | { | ||||
struct ipsec_ctx_data ctx; | struct ipsec_ctx_data ctx; | ||||
union sockaddr_union *dst; | union sockaddr_union *dst; | ||||
struct secasvar *sav; | struct secasvar *sav; | ||||
struct ip6_hdr *ip6; | struct ip6_hdr *ip6; | ||||
int error, i, off; | int error, hwassist, i, off; | ||||
bool accel; | |||||
IPSEC_ASSERT(idx < sp->tcount, ("Wrong IPsec request index %d", idx)); | IPSEC_ASSERT(idx < sp->tcount, ("Wrong IPsec request index %d", idx)); | ||||
sav = ipsec6_allocsa(ifp, m, sp, &idx, &error); | sav = ipsec6_allocsa(ifp, m, sp, &idx, &error); | ||||
if (sav == NULL) { | if (sav == NULL) { | ||||
if (error == EJUSTRETURN) { /* No IPsec required */ | if (error == EJUSTRETURN) { /* No IPsec required */ | ||||
(void)ipsec_accel_output(ifp, m, inp, sp, NULL, | (void)ipsec_accel_output(ifp, m, inp, sp, NULL, | ||||
AF_INET6, mtu); | AF_INET6, mtu, &hwassist); | ||||
key_freesp(&sp); | key_freesp(&sp); | ||||
return (error); | return (error); | ||||
} | } | ||||
goto bad; | goto bad; | ||||
} | } | ||||
/* Fix IP length in case if it is not set yet. */ | /* Fix IP length in case if it is not set yet. */ | ||||
ip6 = mtod(m, struct ip6_hdr *); | ip6 = mtod(m, struct ip6_hdr *); | ||||
ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6)); | ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6)); | ||||
IPSEC_INIT_CTX(&ctx, &m, inp, sav, AF_INET6, IPSEC_ENC_BEFORE); | IPSEC_INIT_CTX(&ctx, &m, inp, sav, AF_INET6, IPSEC_ENC_BEFORE); | ||||
if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0) | if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0) | ||||
goto bad; | goto bad; | ||||
if (ipsec_accel_output(ifp, m, inp, sp, sav, AF_INET6, mtu)) | hwassist = 0; | ||||
accel = ipsec_accel_output(ifp, m, inp, sp, sav, AF_INET6, mtu, | |||||
&hwassist); | |||||
/* | |||||
* Do delayed checksums now because we send before | |||||
* this is done in the normal processing path. | |||||
*/ | |||||
if ((m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6 & ~hwassist) != 0) { | |||||
in6_delayed_cksum(m, m->m_pkthdr.len - | |||||
sizeof(struct ip6_hdr), sizeof(struct ip6_hdr)); | |||||
m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6; | |||||
} | |||||
#if defined(SCTP) || defined(SCTP_SUPPORT) | |||||
if ((m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6 & ~hwassist) != 0) { | |||||
sctp_delayed_cksum(m, sizeof(struct ip6_hdr)); | |||||
m->m_pkthdr.csum_flags &= ~CSUM_SCTP_IPV6; | |||||
} | |||||
#endif | |||||
if (accel) | |||||
return (EJUSTRETURN); | return (EJUSTRETURN); | ||||
ip6 = mtod(m, struct ip6_hdr *); /* pfil can change mbuf */ | ip6 = mtod(m, struct ip6_hdr *); /* pfil can change mbuf */ | ||||
dst = &sav->sah->saidx.dst; | dst = &sav->sah->saidx.dst; | ||||
/* Do the appropriate encapsulation, if necessary */ | /* Do the appropriate encapsulation, if necessary */ | ||||
if (sp->req[idx]->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */ | if (sp->req[idx]->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */ | ||||
dst->sa.sa_family != AF_INET6 || /* PF mismatch */ | dst->sa.sa_family != AF_INET6 || /* PF mismatch */ | ||||
▲ Show 20 Lines • Show All 140 Lines • ▼ Show 20 Lines | ipsec6_common_output(struct ifnet *ifp, struct mbuf *m, struct inpcb *inp, | ||||
sp = ipsec6_checkpolicy(m, inp, &error, !forwarding); | sp = ipsec6_checkpolicy(m, inp, &error, !forwarding); | ||||
if (sp == NULL) { | if (sp == NULL) { | ||||
if (error == -EINVAL) { | if (error == -EINVAL) { | ||||
/* Discarded by policy. */ | /* Discarded by policy. */ | ||||
m_freem(m); | m_freem(m); | ||||
return (EACCES); | return (EACCES); | ||||
} | } | ||||
return (0); /* No IPsec required. */ | return (0); /* No IPsec required. */ | ||||
} | |||||
if (!forwarding) { | |||||
/* | |||||
* Do delayed checksums now because we send before | |||||
* this is done in the normal processing path. | |||||
*/ | |||||
if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) { | |||||
in6_delayed_cksum(m, m->m_pkthdr.len - | |||||
sizeof(struct ip6_hdr), sizeof(struct ip6_hdr)); | |||||
m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6; | |||||
} | |||||
#if defined(SCTP) || defined(SCTP_SUPPORT) | |||||
if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6) { | |||||
sctp_delayed_cksum(m, sizeof(struct ip6_hdr)); | |||||
m->m_pkthdr.csum_flags &= ~CSUM_SCTP_IPV6; | |||||
} | |||||
#endif | |||||
} | } | ||||
error = ipsec6_check_pmtu(ifp, m, sp, forwarding); | error = ipsec6_check_pmtu(ifp, m, sp, forwarding); | ||||
if (error != 0) { | if (error != 0) { | ||||
if (error == EJUSTRETURN) | if (error == EJUSTRETURN) | ||||
return (0); | return (0); | ||||
return (error); | return (error); | ||||
▲ Show 20 Lines • Show All 399 Lines • Show Last 20 Lines |