diff options
Diffstat (limited to 'usr/src/uts/common/inet/ip/ip.c')
| -rw-r--r-- | usr/src/uts/common/inet/ip/ip.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/usr/src/uts/common/inet/ip/ip.c b/usr/src/uts/common/inet/ip/ip.c index 925d06c62b..274bf9b2eb 100644 --- a/usr/src/uts/common/inet/ip/ip.c +++ b/usr/src/uts/common/inet/ip/ip.c @@ -24,7 +24,8 @@ * Copyright (c) 1990 Mentat Inc. * Copyright (c) 2017 OmniTI Computer Consulting, Inc. All rights reserved. * Copyright (c) 2016 by Delphix. All rights reserved. - * Copyright (c) 2019 Joyent, Inc. All rights reserved. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. + * Copyright 2021 Joyent, Inc. */ #include <sys/types.h> @@ -2844,6 +2845,20 @@ icmp_pkt(mblk_t *mp, void *stuff, size_t len, ip_recv_attr_t *ira) len_needed = IPH_HDR_LENGTH(ipha); if (ipha->ipha_protocol == IPPROTO_ENCAP || ipha->ipha_protocol == IPPROTO_IPV6) { + /* + * NOTE: It is posssible that the inner packet is poorly + * formed (e.g. IP version is corrupt, or v6 extension headers + * got cut off). The receiver of the ICMP message should see + * what we saw. In the absence of a sane inner-packet (which + * protocol types IPPPROTO_ENCAP and IPPROTO_IPV6 indicate + * would be an IP header), we should send the size of what is + * normally expected to be there (either sizeof (ipha_t) or + * sizeof (ip6_t). It may be useful for diagnostic purposes. + * + * ALSO NOTE: "inner_ip6h" is the inner packet header, v4 or v6. + */ + ip6_t *inner_ip6h = (ip6_t *)((uchar_t *)ipha + len_needed); + if (!pullupmsg(mp, -1)) { BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutDiscards); ip_drop_output("ipIfStatsOutDiscards", mp, NULL); @@ -2853,13 +2868,20 @@ icmp_pkt(mblk_t *mp, void *stuff, size_t len, ip_recv_attr_t *ira) ipha = (ipha_t *)mp->b_rptr; if (ipha->ipha_protocol == IPPROTO_ENCAP) { - len_needed += IPH_HDR_LENGTH(((uchar_t *)ipha + - len_needed)); + /* + * Check the inner IP version here to guard against + * bogons. + */ + if (IPH_HDR_VERSION(inner_ip6h) == IPV4_VERSION) { + len_needed += + IPH_HDR_LENGTH(((uchar_t *)inner_ip6h)); + } else { + len_needed = sizeof (ipha_t); + } } else { - ip6_t *ip6h = (ip6_t *)((uchar_t *)ipha + len_needed); - ASSERT(ipha->ipha_protocol == IPPROTO_IPV6); - len_needed += ip_hdr_length_v6(mp, ip6h); + /* function called next-line checks inner IP version */ + len_needed += ip_hdr_length_v6(mp, inner_ip6h); } } len_needed += ipst->ips_ip_icmp_return; @@ -5791,7 +5813,7 @@ ip_net_mask(ipaddr_t addr) ipaddr_t mask = 0; uchar_t *maskp = (uchar_t *)&mask; -#if defined(__i386) || defined(__amd64) +#if defined(__x86) #define TOTALLY_BRAIN_DAMAGED_C_COMPILER #endif #ifdef TOTALLY_BRAIN_DAMAGED_C_COMPILER @@ -13923,6 +13945,7 @@ ip_kstat2_init(netstackid_t stackid, ip_stat_t *ip_statisticsp) { "conn_in_recvslla", KSTAT_DATA_UINT64 }, { "conn_in_recvucred", KSTAT_DATA_UINT64 }, { "conn_in_recvttl", KSTAT_DATA_UINT64 }, + { "conn_in_recvtos", KSTAT_DATA_UINT64 }, { "conn_in_recvhopopts", KSTAT_DATA_UINT64 }, { "conn_in_recvhoplimit", KSTAT_DATA_UINT64 }, { "conn_in_recvdstopts", KSTAT_DATA_UINT64 }, |
