Changeset View
Changeset View
Standalone View
Standalone View
sys/netipsec/ipsec_input.c
Show First 20 Lines • Show All 222 Lines • ▼ Show 20 Lines | #endif /* INET6 */ | ||||
* Call appropriate transform and return -- callback takes care of | * Call appropriate transform and return -- callback takes care of | ||||
* everything else. | * everything else. | ||||
*/ | */ | ||||
error = (*sav->tdb_xform->xf_input)(m, sav, skip, protoff); | error = (*sav->tdb_xform->xf_input)(m, sav, skip, protoff); | ||||
return (error); | return (error); | ||||
} | } | ||||
#ifdef INET | #ifdef INET | ||||
extern struct protosw inetsw[]; | |||||
/* | /* | ||||
* IPSEC_INPUT() method implementation for IPv4. | * IPSEC_INPUT() method implementation for IPv4. | ||||
* 0 - Permitted by inbound security policy for further processing. | * 0 - Permitted by inbound security policy for further processing. | ||||
* EACCES - Forbidden by inbound security policy. | * EACCES - Forbidden by inbound security policy. | ||||
* EINPROGRESS - consumed by IPsec. | * EINPROGRESS - consumed by IPsec. | ||||
*/ | */ | ||||
int | int | ||||
ipsec4_input(struct mbuf *m, int offset, int proto) | ipsec4_input(struct mbuf *m, int offset, int proto) | ||||
{ | { | ||||
switch (proto) { | switch (proto) { | ||||
case IPPROTO_AH: | case IPPROTO_AH: | ||||
case IPPROTO_ESP: | case IPPROTO_ESP: | ||||
case IPPROTO_IPCOMP: | case IPPROTO_IPCOMP: | ||||
/* Do inbound IPsec processing for AH/ESP/IPCOMP */ | /* Do inbound IPsec processing for AH/ESP/IPCOMP */ | ||||
ipsec_common_input(m, offset, | ipsec_common_input(m, offset, | ||||
offsetof(struct ip, ip_p), AF_INET, proto); | offsetof(struct ip, ip_p), AF_INET, proto); | ||||
return (EINPROGRESS); /* mbuf consumed by IPsec */ | return (EINPROGRESS); /* mbuf consumed by IPsec */ | ||||
default: | default: | ||||
/* | /* | ||||
* Protocols with further headers get their IPsec treatment | * Protocols with further headers get their IPsec treatment | ||||
* within the protocol specific processing. | * within the protocol specific processing. | ||||
*/ | */ | ||||
if ((inetsw[ip_protox[proto]].pr_flags & PR_LASTHDR) == 0) | switch (proto) { | ||||
case IPPROTO_ICMP: | |||||
case IPPROTO_IGMP: | |||||
case IPPROTO_IPV4: | |||||
case IPPROTO_IPV6: | |||||
case IPPROTO_RSVP: | |||||
case IPPROTO_GRE: | |||||
case IPPROTO_MOBILE: | |||||
case IPPROTO_ETHERIP: | |||||
case IPPROTO_PIM: | |||||
case IPPROTO_SCTP: | |||||
break; | |||||
default: | |||||
return (0); | return (0); | ||||
/* FALLTHROUGH */ | } | ||||
}; | }; | ||||
/* | /* | ||||
* Enforce IPsec policy checking if we are seeing last header. | * Enforce IPsec policy checking if we are seeing last header. | ||||
*/ | */ | ||||
if (ipsec4_in_reject(m, NULL) != 0) { | if (ipsec4_in_reject(m, NULL) != 0) { | ||||
/* Forbidden by inbound security policy */ | /* Forbidden by inbound security policy */ | ||||
m_freem(m); | m_freem(m); | ||||
return (EACCES); | return (EACCES); | ||||
▲ Show 20 Lines • Show All 229 Lines • ▼ Show 20 Lines | bad_noepoch: | ||||
key_freesav(&sav); | key_freesav(&sav); | ||||
if (m != NULL) | if (m != NULL) | ||||
m_freem(m); | m_freem(m); | ||||
return (error); | return (error); | ||||
} | } | ||||
#endif /* INET */ | #endif /* INET */ | ||||
#ifdef INET6 | #ifdef INET6 | ||||
static bool | |||||
ipsec6_lasthdr(int proto) | |||||
{ | |||||
switch (proto) { | |||||
case IPPROTO_IPV4: | |||||
case IPPROTO_IPV6: | |||||
case IPPROTO_GRE: | |||||
case IPPROTO_ICMPV6: | |||||
case IPPROTO_ETHERIP: | |||||
case IPPROTO_PIM: | |||||
case IPPROTO_SCTP: | |||||
return (true); | |||||
default: | |||||
return (false); | |||||
}; | |||||
} | |||||
/* | /* | ||||
* IPSEC_INPUT() method implementation for IPv6. | * IPSEC_INPUT() method implementation for IPv6. | ||||
* 0 - Permitted by inbound security policy for further processing. | * 0 - Permitted by inbound security policy for further processing. | ||||
* EACCES - Forbidden by inbound security policy. | * EACCES - Forbidden by inbound security policy. | ||||
* EINPROGRESS - consumed by IPsec. | * EINPROGRESS - consumed by IPsec. | ||||
*/ | */ | ||||
int | int | ||||
ipsec6_input(struct mbuf *m, int offset, int proto) | ipsec6_input(struct mbuf *m, int offset, int proto) | ||||
{ | { | ||||
switch (proto) { | switch (proto) { | ||||
case IPPROTO_AH: | case IPPROTO_AH: | ||||
case IPPROTO_ESP: | case IPPROTO_ESP: | ||||
case IPPROTO_IPCOMP: | case IPPROTO_IPCOMP: | ||||
/* Do inbound IPsec processing for AH/ESP/IPCOMP */ | /* Do inbound IPsec processing for AH/ESP/IPCOMP */ | ||||
ipsec_common_input(m, offset, | ipsec_common_input(m, offset, | ||||
offsetof(struct ip6_hdr, ip6_nxt), AF_INET6, proto); | offsetof(struct ip6_hdr, ip6_nxt), AF_INET6, proto); | ||||
return (EINPROGRESS); /* mbuf consumed by IPsec */ | return (EINPROGRESS); /* mbuf consumed by IPsec */ | ||||
default: | default: | ||||
/* | /* | ||||
* Protocols with further headers get their IPsec treatment | * Protocols with further headers get their IPsec treatment | ||||
* within the protocol specific processing. | * within the protocol specific processing. | ||||
*/ | */ | ||||
if ((inet6sw[ip6_protox[proto]].pr_flags & PR_LASTHDR) == 0) | if (!ipsec6_lasthdr(proto)) | ||||
return (0); | return (0); | ||||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
}; | }; | ||||
/* | /* | ||||
* Enforce IPsec policy checking if we are seeing last header. | * Enforce IPsec policy checking if we are seeing last header. | ||||
*/ | */ | ||||
if (ipsec6_in_reject(m, NULL) != 0) { | if (ipsec6_in_reject(m, NULL) != 0) { | ||||
/* Forbidden by inbound security policy */ | /* Forbidden by inbound security policy */ | ||||
▲ Show 20 Lines • Show All 187 Lines • ▼ Show 20 Lines | if (m->m_pkthdr.len < skip) { | ||||
error = EINVAL; | error = EINVAL; | ||||
goto bad; | goto bad; | ||||
} | } | ||||
/* | /* | ||||
* 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 (ipsec6_lasthdr(nxt) && ipsec6_in_reject(m, NULL)) { | ||||
ipsec6_in_reject(m, NULL)) { | |||||
error = EINVAL; | error = EINVAL; | ||||
goto bad; | goto bad; | ||||
} | } | ||||
nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &skip, nxt); | nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &skip, nxt); | ||||
} | } | ||||
NET_EPOCH_EXIT(et); | NET_EPOCH_EXIT(et); | ||||
key_freesav(&sav); | key_freesav(&sav); | ||||
return (0); | return (0); | ||||
bad: | bad: | ||||
NET_EPOCH_EXIT(et); | NET_EPOCH_EXIT(et); | ||||
key_freesav(&sav); | key_freesav(&sav); | ||||
if (m) | if (m) | ||||
m_freem(m); | m_freem(m); | ||||
return (error); | return (error); | ||||
} | } | ||||
#endif /* INET6 */ | #endif /* INET6 */ |