Changeset View
Changeset View
Standalone View
Standalone View
head/sys/netipsec/ipsec_input.c
Show First 20 Lines • Show All 272 Lines • ▼ Show 20 Lines | |||||
* Takes care of filtering and other sanity checks on | * Takes care of filtering and other sanity checks on | ||||
* the processed packet. | * the processed packet. | ||||
*/ | */ | ||||
int | int | ||||
ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, | ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, | ||||
int protoff) | int protoff) | ||||
{ | { | ||||
IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]); | IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]); | ||||
struct epoch_tracker et; | |||||
struct ipsec_ctx_data ctx; | struct ipsec_ctx_data ctx; | ||||
struct xform_history *xh; | struct xform_history *xh; | ||||
struct secasindex *saidx; | struct secasindex *saidx; | ||||
struct m_tag *mtag; | struct m_tag *mtag; | ||||
struct ip *ip; | struct ip *ip; | ||||
int error, prot, af, sproto, isr_prot; | int error, prot, af, sproto, isr_prot; | ||||
IPSEC_ASSERT(sav != NULL, ("null SA")); | IPSEC_ASSERT(sav != NULL, ("null SA")); | ||||
▲ Show 20 Lines • Show All 130 Lines • ▼ Show 20 Lines | #endif | ||||
IPSEC_INIT_CTX(&ctx, &m, NULL, sav, af, IPSEC_ENC_AFTER); | IPSEC_INIT_CTX(&ctx, &m, NULL, sav, af, IPSEC_ENC_AFTER); | ||||
if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0) | if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0) | ||||
goto bad; | goto bad; | ||||
/* Handle virtual tunneling interfaces */ | /* Handle virtual tunneling interfaces */ | ||||
if (saidx->mode == IPSEC_MODE_TUNNEL) | if (saidx->mode == IPSEC_MODE_TUNNEL) | ||||
error = ipsec_if_input(m, sav, af); | error = ipsec_if_input(m, sav, af); | ||||
if (error == 0) { | if (error == 0) { | ||||
NET_EPOCH_ENTER(et); | |||||
error = netisr_queue_src(isr_prot, (uintptr_t)sav->spi, m); | error = netisr_queue_src(isr_prot, (uintptr_t)sav->spi, m); | ||||
NET_EPOCH_EXIT(et); | |||||
if (error) { | if (error) { | ||||
IPSEC_ISTAT(sproto, qfull); | IPSEC_ISTAT(sproto, qfull); | ||||
DPRINTF(("%s: queue full; proto %u packet dropped\n", | DPRINTF(("%s: queue full; proto %u packet dropped\n", | ||||
__func__, sproto)); | __func__, sproto)); | ||||
} | } | ||||
} | } | ||||
key_freesav(&sav); | key_freesav(&sav); | ||||
return (error); | return (error); | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | |||||
* IPsec input callback, called by the transform callback. Takes care of | * IPsec input callback, called by the transform callback. Takes care of | ||||
* filtering and other sanity checks on the processed packet. | * filtering and other sanity checks on the processed packet. | ||||
*/ | */ | ||||
int | int | ||||
ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, | ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, | ||||
int protoff) | int protoff) | ||||
{ | { | ||||
IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]); | IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]); | ||||
struct epoch_tracker et; | |||||
struct ipsec_ctx_data ctx; | struct ipsec_ctx_data ctx; | ||||
struct xform_history *xh; | struct xform_history *xh; | ||||
struct secasindex *saidx; | struct secasindex *saidx; | ||||
struct ip6_hdr *ip6; | struct ip6_hdr *ip6; | ||||
struct m_tag *mtag; | struct m_tag *mtag; | ||||
int prot, af, sproto; | int prot, af, sproto; | ||||
int nxt, isr_prot; | int nxt, isr_prot; | ||||
int error, nest; | int error, nest; | ||||
▲ Show 20 Lines • Show All 116 Lines • ▼ Show 20 Lines | default: | ||||
IPSEC_ISTAT(sproto, nopf); | IPSEC_ISTAT(sproto, nopf); | ||||
error = EPFNOSUPPORT; | error = EPFNOSUPPORT; | ||||
goto bad; | goto bad; | ||||
} | } | ||||
/* Handle virtual tunneling interfaces */ | /* Handle virtual tunneling interfaces */ | ||||
if (saidx->mode == IPSEC_MODE_TUNNEL) | if (saidx->mode == IPSEC_MODE_TUNNEL) | ||||
error = ipsec_if_input(m, sav, af); | error = ipsec_if_input(m, sav, af); | ||||
if (error == 0) { | if (error == 0) { | ||||
NET_EPOCH_ENTER(et); | |||||
error = netisr_queue_src(isr_prot, | error = netisr_queue_src(isr_prot, | ||||
(uintptr_t)sav->spi, m); | (uintptr_t)sav->spi, m); | ||||
NET_EPOCH_EXIT(et); | |||||
if (error) { | if (error) { | ||||
IPSEC_ISTAT(sproto, qfull); | IPSEC_ISTAT(sproto, qfull); | ||||
DPRINTF(("%s: queue full; proto %u packet" | DPRINTF(("%s: queue full; proto %u packet" | ||||
" dropped\n", __func__, sproto)); | " dropped\n", __func__, sproto)); | ||||
} | } | ||||
} | } | ||||
key_freesav(&sav); | key_freesav(&sav); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* See the end of ip6_input for this logic. | * See the end of ip6_input for this logic. | ||||
* IPPROTO_IPV[46] case will be processed just like other ones | * IPPROTO_IPV[46] case will be processed just like other ones | ||||
*/ | */ | ||||
nest = 0; | nest = 0; | ||||
nxt = nxt8; | nxt = nxt8; | ||||
NET_EPOCH_ENTER(et); | |||||
while (nxt != IPPROTO_DONE) { | while (nxt != IPPROTO_DONE) { | ||||
if (V_ip6_hdrnestlimit && (++nest > V_ip6_hdrnestlimit)) { | if (V_ip6_hdrnestlimit && (++nest > V_ip6_hdrnestlimit)) { | ||||
IP6STAT_INC(ip6s_toomanyhdr); | IP6STAT_INC(ip6s_toomanyhdr); | ||||
error = EINVAL; | error = EINVAL; | ||||
goto bad; | goto bad_epoch; | ||||
} | } | ||||
/* | /* | ||||
* Protection against faulty packet - there should be | * Protection against faulty packet - there should be | ||||
* more sanity checks in header chain processing. | * more sanity checks in header chain processing. | ||||
*/ | */ | ||||
if (m->m_pkthdr.len < skip) { | if (m->m_pkthdr.len < skip) { | ||||
IP6STAT_INC(ip6s_tooshort); | IP6STAT_INC(ip6s_tooshort); | ||||
in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated); | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated); | ||||
error = EINVAL; | error = EINVAL; | ||||
goto bad; | goto bad_epoch; | ||||
} | } | ||||
/* | /* | ||||
* Enforce IPsec policy checking if we are seeing last header. | * Enforce IPsec policy checking if we are seeing last header. | ||||
* note that we do not visit this with protocols with pcb layer | * note that we do not visit this with protocols with pcb layer | ||||
* code - like udp/tcp/raw ip. | * code - like udp/tcp/raw ip. | ||||
*/ | */ | ||||
if ((inet6sw[ip6_protox[nxt]].pr_flags & PR_LASTHDR) != 0 && | if ((inet6sw[ip6_protox[nxt]].pr_flags & PR_LASTHDR) != 0 && | ||||
ipsec6_in_reject(m, NULL)) { | ipsec6_in_reject(m, NULL)) { | ||||
error = EINVAL; | error = EINVAL; | ||||
goto bad; | goto bad_epoch; | ||||
} | } | ||||
nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &skip, nxt); | nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &skip, nxt); | ||||
} | } | ||||
NET_EPOCH_EXIT(et); | |||||
key_freesav(&sav); | key_freesav(&sav); | ||||
return (0); | return (0); | ||||
bad_epoch: | |||||
NET_EPOCH_EXIT(et); | |||||
bad: | bad: | ||||
key_freesav(&sav); | key_freesav(&sav); | ||||
if (m) | if (m) | ||||
m_freem(m); | m_freem(m); | ||||
return (error); | return (error); | ||||
} | } | ||||
#endif /* INET6 */ | #endif /* INET6 */ |