Print this page
9832 Original bug discovered as 9560 has friends IPv4 packets coming in as IPv6 creating chaos
Reviewed by: Robert Mustacchi <rm@joyent.com>

@@ -19,12 +19,12 @@
  * CDDL HEADER END
  */
 /*
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
- * Copyright 2017 Joyent, Inc.
  * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2019 Joyent, Inc.
  */
 
 /*
  * MAC data path
  *

@@ -1713,10 +1713,11 @@
         uint8_t         nexthdr;
         uint16_t        hdr_len;
         uint32_t        src_val, dst_val;
         boolean_t       modifiable = B_TRUE;
         boolean_t       v6;
+        int             errno;
 
         ASSERT(MBLKL(mp) >= hdrsize);
 
         if (sap == ETHERTYPE_IPV6) {
                 v6 = B_TRUE;

@@ -1787,19 +1788,31 @@
                 /*
                  * Do src based fanout if below tunable is set to B_TRUE or
                  * when mac_ip_hdr_length_v6() fails because of malformed
                  * packets or because mblks need to be concatenated using
                  * pullupmsg().
-                 *
-                 * Perform a version check to prevent parsing weirdness...
                  */
-                if (IPH_HDR_VERSION(ip6h) != IPV6_VERSION ||
-                    !mac_ip_hdr_length_v6(ip6h, mp->b_wptr, &hdr_len, &nexthdr,
-                    NULL)) {
+                errno = mac_ip_hdr_length_v6(ip6h, mp->b_wptr, &hdr_len,
+                    &nexthdr, NULL);
+                switch (errno) {
+                case EINVAL:
+                        /* Bad version. */
+                        *indx = 0;
+                        *type = OTH;
+                        return (0);
+                case 0:
+                        break;
+                default:
                         goto src_dst_based_fanout;
                 }
         } else {
+                if (IPH_HDR_VERSION(ipha) != IPV4_VERSION) {
+                        /* Bad version. */
+                        *indx = 0;
+                        *type = OTH;
+                        return (0);
+                }
                 hdr_len = IPH_HDR_LENGTH(ipha);
                 remlen = ntohs(ipha->ipha_length) - hdr_len;
                 nexthdr = ipha->ipha_protocol;
                 src_val = (uint32_t)ipha->ipha_src;
                 dst_val = (uint32_t)ipha->ipha_dst;