diff options
Diffstat (limited to 'sys/netinet/ipsec_input.c')
-rw-r--r-- | sys/netinet/ipsec_input.c | 262 |
1 files changed, 91 insertions, 171 deletions
diff --git a/sys/netinet/ipsec_input.c b/sys/netinet/ipsec_input.c index 1d8c3fa1201..9711e5213cb 100644 --- a/sys/netinet/ipsec_input.c +++ b/sys/netinet/ipsec_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ipsec_input.c,v 1.188 2021/10/24 17:08:27 bluhm Exp $ */ +/* $OpenBSD: ipsec_input.c,v 1.189 2021/10/24 22:59:47 bluhm Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr) and @@ -793,19 +793,42 @@ ipsec_sysctl_ipsecstat(void *oldp, size_t *oldlenp, void *newp) sizeof(ipsecstat))); } -/* IPv4 AH wrapper. */ int -ah4_input(struct mbuf **mp, int *offp, int proto, int af) +ipsec_input_disabled(struct mbuf **mp, int *offp, int proto, int af) { + switch (af) { + case AF_INET: + return rip_input(mp, offp, proto, af); +#ifdef INET6 + case AF_INET6: + return rip6_input(mp, offp, proto, af); +#endif + default: + unhandled_af(af); + } +} + +int +ah46_input(struct mbuf **mp, int *offp, int proto, int af) +{ + int protoff; + if ( #if NPF > 0 ((*mp)->m_pkthdr.pf.flags & PF_TAG_DIVERTED) || #endif !ah_enable) - return rip_input(mp, offp, proto, af); + return ipsec_input_disabled(mp, offp, proto, af); + + protoff = ipsec_protoff(*mp, *offp, af); + if (protoff < 0) { + DPRINTF("bad packet header chain"); + ahstat_inc(ahs_hdrops); + m_freemp(mp); + return IPPROTO_DONE; + } - ipsec_common_input(mp, *offp, offsetof(struct ip, ip_p), AF_INET, - proto, 0); + ipsec_common_input(mp, *offp, protoff, af, proto, 0); return IPPROTO_DONE; } @@ -819,35 +842,52 @@ ah4_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *v) ipsec_common_ctlinput(rdomain, cmd, sa, v, IPPROTO_AH); } -/* IPv4 ESP wrapper. */ int -esp4_input(struct mbuf **mp, int *offp, int proto, int af) +esp46_input(struct mbuf **mp, int *offp, int proto, int af) { + int protoff; + if ( #if NPF > 0 ((*mp)->m_pkthdr.pf.flags & PF_TAG_DIVERTED) || #endif !esp_enable) - return rip_input(mp, offp, proto, af); + return ipsec_input_disabled(mp, offp, proto, af); + + protoff = ipsec_protoff(*mp, *offp, af); + if (protoff < 0) { + DPRINTF("bad packet header chain"); + espstat_inc(esps_hdrops); + m_freemp(mp); + return IPPROTO_DONE; + } - ipsec_common_input(mp, *offp, offsetof(struct ip, ip_p), AF_INET, - proto, 0); + ipsec_common_input(mp, *offp, protoff, af, proto, 0); return IPPROTO_DONE; } /* IPv4 IPCOMP wrapper */ int -ipcomp4_input(struct mbuf **mp, int *offp, int proto, int af) +ipcomp46_input(struct mbuf **mp, int *offp, int proto, int af) { + int protoff; + if ( #if NPF > 0 ((*mp)->m_pkthdr.pf.flags & PF_TAG_DIVERTED) || #endif !ipcomp_enable) - return rip_input(mp, offp, proto, af); + return ipsec_input_disabled(mp, offp, proto, af); + + protoff = ipsec_protoff(*mp, *offp, af); + if (protoff < 0) { + DPRINTF("bad packet header chain"); + ipcompstat_inc(ipcomps_hdrops); + m_freemp(mp); + return IPPROTO_DONE; + } - ipsec_common_input(mp, *offp, offsetof(struct ip, ip_p), AF_INET, - proto, 0); + ipsec_common_input(mp, *offp, protoff, af, proto, 0); return IPPROTO_DONE; } @@ -969,179 +1009,59 @@ esp4_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *v) ipsec_common_ctlinput(rdomain, cmd, sa, v, IPPROTO_ESP); } -#ifdef INET6 -/* IPv6 AH wrapper. */ +/* Find the offset of the next protocol field in the previous header. */ int -ah6_input(struct mbuf **mp, int *offp, int proto, int af) +ipsec_protoff(struct mbuf *m, int off, int af) { - int l = 0; - int protoff, nxt; struct ip6_ext ip6e; + int protoff, nxt, l; - if ( -#if NPF > 0 - ((*mp)->m_pkthdr.pf.flags & PF_TAG_DIVERTED) || -#endif - !ah_enable) - return rip6_input(mp, offp, proto, af); - - if (*offp < sizeof(struct ip6_hdr)) { - DPRINTF("bad offset"); - ahstat_inc(ahs_hdrops); - m_freemp(mp); - return IPPROTO_DONE; - } else if (*offp == sizeof(struct ip6_hdr)) { - protoff = offsetof(struct ip6_hdr, ip6_nxt); - } else { - /* Chase down the header chain... */ - protoff = sizeof(struct ip6_hdr); - nxt = (mtod(*mp, struct ip6_hdr *))->ip6_nxt; - - do { - protoff += l; - m_copydata(*mp, protoff, sizeof(ip6e), - (caddr_t) &ip6e); - - if (nxt == IPPROTO_AH) - l = (ip6e.ip6e_len + 2) << 2; - else - l = (ip6e.ip6e_len + 1) << 3; -#ifdef DIAGNOSTIC - if (l <= 0) - panic("ah6_input: l went zero or negative"); + switch (af) { + case AF_INET: + return offsetof(struct ip, ip_p); +#ifdef INET6 + case AF_INET6: + break; #endif - - nxt = ip6e.ip6e_nxt; - } while (protoff + l < *offp); - - /* Malformed packet check */ - if (protoff + l != *offp) { - DPRINTF("bad packet header chain"); - ahstat_inc(ahs_hdrops); - m_freemp(mp); - return IPPROTO_DONE; - } - protoff += offsetof(struct ip6_ext, ip6e_nxt); + default: + unhandled_af(af); } - ipsec_common_input(mp, *offp, protoff, AF_INET6, proto, 0); - return IPPROTO_DONE; -} -/* IPv6 ESP wrapper. */ -int -esp6_input(struct mbuf **mp, int *offp, int proto, int af) -{ - int l = 0; - int protoff, nxt; - struct ip6_ext ip6e; + if (off < sizeof(struct ip6_hdr)) + return -1; - if ( -#if NPF > 0 - ((*mp)->m_pkthdr.pf.flags & PF_TAG_DIVERTED) || -#endif - !esp_enable) - return rip6_input(mp, offp, proto, af); + if (off == sizeof(struct ip6_hdr)) + return offsetof(struct ip6_hdr, ip6_nxt); - if (*offp < sizeof(struct ip6_hdr)) { - DPRINTF("bad offset"); - espstat_inc(esps_hdrops); - m_freemp(mp); - return IPPROTO_DONE; - } else if (*offp == sizeof(struct ip6_hdr)) { - protoff = offsetof(struct ip6_hdr, ip6_nxt); - } else { - /* Chase down the header chain... */ - protoff = sizeof(struct ip6_hdr); - nxt = (mtod(*mp, struct ip6_hdr *))->ip6_nxt; - - do { - protoff += l; - m_copydata(*mp, protoff, sizeof(ip6e), - (caddr_t) &ip6e); - - if (nxt == IPPROTO_AH) - l = (ip6e.ip6e_len + 2) << 2; - else - l = (ip6e.ip6e_len + 1) << 3; -#ifdef DIAGNOSTIC - if (l <= 0) - panic("esp6_input: l went zero or negative"); -#endif + /* Chase down the header chain... */ + protoff = sizeof(struct ip6_hdr); + nxt = (mtod(m, struct ip6_hdr *))->ip6_nxt; + l = 0; - nxt = ip6e.ip6e_nxt; - } while (protoff + l < *offp); + do { + protoff += l; + m_copydata(m, protoff, sizeof(ip6e), + (caddr_t) &ip6e); - /* Malformed packet check */ - if (protoff + l != *offp) { - DPRINTF("bad packet header chain"); - espstat_inc(esps_hdrops); - m_freemp(mp); - return IPPROTO_DONE; - } - protoff += offsetof(struct ip6_ext, ip6e_nxt); - } - ipsec_common_input(mp, *offp, protoff, AF_INET6, proto, 0); - return IPPROTO_DONE; - -} - -/* IPv6 IPcomp wrapper */ -int -ipcomp6_input(struct mbuf **mp, int *offp, int proto, int af) -{ - int l = 0; - int protoff, nxt; - struct ip6_ext ip6e; - - if ( -#if NPF > 0 - ((*mp)->m_pkthdr.pf.flags & PF_TAG_DIVERTED) || -#endif - !ipcomp_enable) - return rip6_input(mp, offp, proto, af); - - if (*offp < sizeof(struct ip6_hdr)) { - DPRINTF("bad offset"); - ipcompstat_inc(ipcomps_hdrops); - m_freemp(mp); - return IPPROTO_DONE; - } else if (*offp == sizeof(struct ip6_hdr)) { - protoff = offsetof(struct ip6_hdr, ip6_nxt); - } else { - /* Chase down the header chain... */ - protoff = sizeof(struct ip6_hdr); - nxt = (mtod(*mp, struct ip6_hdr *))->ip6_nxt; - - do { - protoff += l; - m_copydata(*mp, protoff, sizeof(ip6e), - (caddr_t) &ip6e); - if (nxt == IPPROTO_AH) - l = (ip6e.ip6e_len + 2) << 2; - else - l = (ip6e.ip6e_len + 1) << 3; + if (nxt == IPPROTO_AH) + l = (ip6e.ip6e_len + 2) << 2; + else + l = (ip6e.ip6e_len + 1) << 3; #ifdef DIAGNOSTIC - if (l <= 0) - panic("l went zero or negative"); + if (l <= 0) + panic("ah6_input: l went zero or negative"); #endif - nxt = ip6e.ip6e_nxt; - } while (protoff + l < *offp); + nxt = ip6e.ip6e_nxt; + } while (protoff + l < off); - /* Malformed packet check */ - if (protoff + l != *offp) { - DPRINTF("bad packet header chain"); - ipcompstat_inc(ipcomps_hdrops); - m_freemp(mp); - return IPPROTO_DONE; - } + /* Malformed packet check */ + if (protoff + l != off) + return -1; - protoff += offsetof(struct ip6_ext, ip6e_nxt); - } - ipsec_common_input(mp, *offp, protoff, AF_INET6, proto, 0); - return IPPROTO_DONE; + protoff += offsetof(struct ip6_ext, ip6e_nxt); + return protoff; } -#endif /* INET6 */ int ipsec_forward_check(struct mbuf *m, int hlen, int af) |