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>


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  * Copyright 2017 Joyent, Inc.
  25  * Copyright 2013 Nexenta Systems, Inc. All rights reserved.

  26  */
  27 
  28 /*
  29  * MAC data path
  30  *
  31  * The MAC data path is concerned with the flow of traffic from mac clients --
  32  * DLS, IP, etc. -- to various GLDv3 device drivers -- e1000g, vnic, aggr,
  33  * ixgbe, etc. -- and from the GLDv3 device drivers back to clients.
  34  *
  35  * -----------
  36  * Terminology
  37  * -----------
  38  *
  39  * MAC uses a lot of different, but related terms that are associated with the
  40  * design and structure of the data path. Before we cover other aspects, first
  41  * let's review the terminology that MAC uses.
  42  *
  43  * MAC
  44  *
  45  *      This driver. It interfaces with device drivers and provides abstractions


1698  * mac_rx_srs_long_fanout
1699  *
1700  * The fanout routine for VLANs, and for anything else that isn't performing
1701  * explicit dls bypass.  Returns -1 on an error (drop the packet due to a
1702  * malformed packet), 0 on success, with values written in *indx and *type.
1703  */
1704 static int
1705 mac_rx_srs_long_fanout(mac_soft_ring_set_t *mac_srs, mblk_t *mp,
1706     uint32_t sap, size_t hdrsize, enum pkt_type *type, uint_t *indx)
1707 {
1708         ip6_t           *ip6h;
1709         ipha_t          *ipha;
1710         uint8_t         *whereptr;
1711         uint_t          hash;
1712         uint16_t        remlen;
1713         uint8_t         nexthdr;
1714         uint16_t        hdr_len;
1715         uint32_t        src_val, dst_val;
1716         boolean_t       modifiable = B_TRUE;
1717         boolean_t       v6;

1718 
1719         ASSERT(MBLKL(mp) >= hdrsize);
1720 
1721         if (sap == ETHERTYPE_IPV6) {
1722                 v6 = B_TRUE;
1723                 hdr_len = IPV6_HDR_LEN;
1724         } else if (sap == ETHERTYPE_IP) {
1725                 v6 = B_FALSE;
1726                 hdr_len = IP_SIMPLE_HDR_LENGTH;
1727         } else {
1728                 *indx = 0;
1729                 *type = OTH;
1730                 return (0);
1731         }
1732 
1733         ip6h = (ip6_t *)(mp->b_rptr + hdrsize);
1734         ipha = (ipha_t *)ip6h;
1735 
1736         if ((uint8_t *)ip6h == mp->b_wptr) {
1737                 /*


1772                 *indx = 0;
1773                 *type = OTH;
1774                 fanout_unaligned++;
1775                 return (0);
1776         }
1777 
1778         /*
1779          * Extract next-header, full header length, and source-hash value
1780          * using v4/v6 specific fields.
1781          */
1782         if (v6) {
1783                 remlen = ntohs(ip6h->ip6_plen);
1784                 nexthdr = ip6h->ip6_nxt;
1785                 src_val = V4_PART_OF_V6(ip6h->ip6_src);
1786                 dst_val = V4_PART_OF_V6(ip6h->ip6_dst);
1787                 /*
1788                  * Do src based fanout if below tunable is set to B_TRUE or
1789                  * when mac_ip_hdr_length_v6() fails because of malformed
1790                  * packets or because mblks need to be concatenated using
1791                  * pullupmsg().
1792                  *
1793                  * Perform a version check to prevent parsing weirdness...
1794                  */
1795                 if (IPH_HDR_VERSION(ip6h) != IPV6_VERSION ||
1796                     !mac_ip_hdr_length_v6(ip6h, mp->b_wptr, &hdr_len, &nexthdr,
1797                     NULL)) {








1798                         goto src_dst_based_fanout;
1799                 }
1800         } else {






1801                 hdr_len = IPH_HDR_LENGTH(ipha);
1802                 remlen = ntohs(ipha->ipha_length) - hdr_len;
1803                 nexthdr = ipha->ipha_protocol;
1804                 src_val = (uint32_t)ipha->ipha_src;
1805                 dst_val = (uint32_t)ipha->ipha_dst;
1806                 /*
1807                  * Catch IPv4 fragment case here.  IPv6 has nexthdr == FRAG
1808                  * for its equivalent case.
1809                  */
1810                 if ((ntohs(ipha->ipha_fragment_offset_and_flags) &
1811                     (IPH_MF | IPH_OFFSET)) != 0) {
1812                         goto src_dst_based_fanout;
1813                 }
1814         }
1815         if (remlen < MIN_EHDR_LEN)
1816                 return (-1);
1817         whereptr = (uint8_t *)ip6h + hdr_len;
1818 
1819         /* If the transport is one of below, we do port/SPI based fanout */
1820         switch (nexthdr) {




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.

  24  * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
  25  * Copyright 2019 Joyent, Inc.
  26  */
  27 
  28 /*
  29  * MAC data path
  30  *
  31  * The MAC data path is concerned with the flow of traffic from mac clients --
  32  * DLS, IP, etc. -- to various GLDv3 device drivers -- e1000g, vnic, aggr,
  33  * ixgbe, etc. -- and from the GLDv3 device drivers back to clients.
  34  *
  35  * -----------
  36  * Terminology
  37  * -----------
  38  *
  39  * MAC uses a lot of different, but related terms that are associated with the
  40  * design and structure of the data path. Before we cover other aspects, first
  41  * let's review the terminology that MAC uses.
  42  *
  43  * MAC
  44  *
  45  *      This driver. It interfaces with device drivers and provides abstractions


1698  * mac_rx_srs_long_fanout
1699  *
1700  * The fanout routine for VLANs, and for anything else that isn't performing
1701  * explicit dls bypass.  Returns -1 on an error (drop the packet due to a
1702  * malformed packet), 0 on success, with values written in *indx and *type.
1703  */
1704 static int
1705 mac_rx_srs_long_fanout(mac_soft_ring_set_t *mac_srs, mblk_t *mp,
1706     uint32_t sap, size_t hdrsize, enum pkt_type *type, uint_t *indx)
1707 {
1708         ip6_t           *ip6h;
1709         ipha_t          *ipha;
1710         uint8_t         *whereptr;
1711         uint_t          hash;
1712         uint16_t        remlen;
1713         uint8_t         nexthdr;
1714         uint16_t        hdr_len;
1715         uint32_t        src_val, dst_val;
1716         boolean_t       modifiable = B_TRUE;
1717         boolean_t       v6;
1718         int             errno;
1719 
1720         ASSERT(MBLKL(mp) >= hdrsize);
1721 
1722         if (sap == ETHERTYPE_IPV6) {
1723                 v6 = B_TRUE;
1724                 hdr_len = IPV6_HDR_LEN;
1725         } else if (sap == ETHERTYPE_IP) {
1726                 v6 = B_FALSE;
1727                 hdr_len = IP_SIMPLE_HDR_LENGTH;
1728         } else {
1729                 *indx = 0;
1730                 *type = OTH;
1731                 return (0);
1732         }
1733 
1734         ip6h = (ip6_t *)(mp->b_rptr + hdrsize);
1735         ipha = (ipha_t *)ip6h;
1736 
1737         if ((uint8_t *)ip6h == mp->b_wptr) {
1738                 /*


1773                 *indx = 0;
1774                 *type = OTH;
1775                 fanout_unaligned++;
1776                 return (0);
1777         }
1778 
1779         /*
1780          * Extract next-header, full header length, and source-hash value
1781          * using v4/v6 specific fields.
1782          */
1783         if (v6) {
1784                 remlen = ntohs(ip6h->ip6_plen);
1785                 nexthdr = ip6h->ip6_nxt;
1786                 src_val = V4_PART_OF_V6(ip6h->ip6_src);
1787                 dst_val = V4_PART_OF_V6(ip6h->ip6_dst);
1788                 /*
1789                  * Do src based fanout if below tunable is set to B_TRUE or
1790                  * when mac_ip_hdr_length_v6() fails because of malformed
1791                  * packets or because mblks need to be concatenated using
1792                  * pullupmsg().


1793                  */
1794                 errno = mac_ip_hdr_length_v6(ip6h, mp->b_wptr, &hdr_len,
1795                     &nexthdr, NULL);
1796                 switch (errno) {
1797                 case EINVAL:
1798                         /* Bad version. */
1799                         *indx = 0;
1800                         *type = OTH;
1801                         return (0);
1802                 case 0:
1803                         break;
1804                 default:
1805                         goto src_dst_based_fanout;
1806                 }
1807         } else {
1808                 if (IPH_HDR_VERSION(ipha) != IPV4_VERSION) {
1809                         /* Bad version. */
1810                         *indx = 0;
1811                         *type = OTH;
1812                         return (0);
1813                 }
1814                 hdr_len = IPH_HDR_LENGTH(ipha);
1815                 remlen = ntohs(ipha->ipha_length) - hdr_len;
1816                 nexthdr = ipha->ipha_protocol;
1817                 src_val = (uint32_t)ipha->ipha_src;
1818                 dst_val = (uint32_t)ipha->ipha_dst;
1819                 /*
1820                  * Catch IPv4 fragment case here.  IPv6 has nexthdr == FRAG
1821                  * for its equivalent case.
1822                  */
1823                 if ((ntohs(ipha->ipha_fragment_offset_and_flags) &
1824                     (IPH_MF | IPH_OFFSET)) != 0) {
1825                         goto src_dst_based_fanout;
1826                 }
1827         }
1828         if (remlen < MIN_EHDR_LEN)
1829                 return (-1);
1830         whereptr = (uint8_t *)ip6h + hdr_len;
1831 
1832         /* If the transport is one of below, we do port/SPI based fanout */
1833         switch (nexthdr) {