summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/inet/ip/ip.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/inet/ip/ip.c')
-rw-r--r--usr/src/uts/common/inet/ip/ip.c37
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 },