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>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/io/mac/mac_flow.c
          +++ new/usr/src/uts/common/io/mac/mac_flow.c
↓ open down ↓ 14 lines elided ↑ open up ↑
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
       25 + *
       26 + * Copyright 2019, Joyent, Inc.
  25   27   */
  26   28  
  27   29  #include <sys/strsun.h>
  28   30  #include <sys/sdt.h>
  29   31  #include <sys/mac.h>
  30   32  #include <sys/mac_impl.h>
  31   33  #include <sys/mac_client_impl.h>
  32   34  #include <sys/mac_stat.h>
  33   35  #include <sys/dls.h>
  34   36  #include <sys/dls_impl.h>
↓ open down ↓ 71 lines elided ↑ open up ↑
 106  108          flow_stats_t            flow_stats;
 107  109          mac_soft_ring_set_t     *mac_srs;
 108  110  
 109  111          if (rw != KSTAT_READ)
 110  112                  return (EACCES);
 111  113  
 112  114          bzero(&flow_stats, sizeof (flow_stats_t));
 113  115  
 114  116          for (i = 0; i < fep->fe_rx_srs_cnt; i++) {
 115  117                  mac_srs = (mac_soft_ring_set_t *)fep->fe_rx_srs[i];
 116      -                if (mac_srs == NULL)            /* Multicast flow */
      118 +                if (mac_srs == NULL)            /* Multicast flow */
 117  119                          break;
 118  120                  mac_rx_stat = &mac_srs->srs_rx.sr_stat;
 119  121  
 120  122                  flow_stats.fs_ibytes += mac_rx_stat->mrs_intrbytes +
 121  123                      mac_rx_stat->mrs_pollbytes + mac_rx_stat->mrs_lclbytes;
 122  124  
 123  125                  flow_stats.fs_ipackets += mac_rx_stat->mrs_intrcnt +
 124  126                      mac_rx_stat->mrs_pollcnt + mac_rx_stat->mrs_lclcnt;
 125  127  
 126  128                  flow_stats.fs_ierrors += mac_rx_stat->mrs_ierrors;
 127  129          }
 128  130  
 129  131          mac_srs = (mac_soft_ring_set_t *)fep->fe_tx_srs;
 130      -        if (mac_srs == NULL)            /* Multicast flow */
      132 +        if (mac_srs == NULL)            /* Multicast flow */
 131  133                  goto done;
 132  134          mac_tx_stat = &mac_srs->srs_tx.st_stat;
 133  135  
 134  136          flow_stats.fs_obytes = mac_tx_stat->mts_obytes;
 135  137          flow_stats.fs_opackets = mac_tx_stat->mts_opackets;
 136  138          flow_stats.fs_oerrors = mac_tx_stat->mts_oerrors;
 137  139  
 138  140  done:
 139  141          for (i = 0; i < FS_SIZE; i++, knp++) {
 140  142                  statp = (uint64_t *)
↓ open down ↓ 1038 lines elided ↑ open up ↑
1179 1181  }
1180 1182  
1181 1183  /*
1182 1184   * mac_link_flow_init()
1183 1185   * Internal flow interface used for allocating SRSs and related
1184 1186   * data structures. Not meant to be used by mac clients.
1185 1187   */
1186 1188  int
1187 1189  mac_link_flow_init(mac_client_handle_t mch, flow_entry_t *sub_flow)
1188 1190  {
1189      -        mac_client_impl_t       *mcip = (mac_client_impl_t *)mch;
     1191 +        mac_client_impl_t       *mcip = (mac_client_impl_t *)mch;
1190 1192          mac_impl_t              *mip = mcip->mci_mip;
1191 1193          int                     err;
1192 1194  
1193 1195          ASSERT(mch != NULL);
1194 1196          ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
1195 1197  
1196 1198          if ((err = mac_datapath_setup(mcip, sub_flow, SRST_FLOW)) != 0)
1197 1199                  return (err);
1198 1200  
1199 1201          sub_flow->fe_mcip = mcip;
↓ open down ↓ 113 lines elided ↑ open up ↑
1313 1315  }
1314 1316  
1315 1317  /*
1316 1318   * mac_link_flow_clean()
1317 1319   * Internal flow interface used for freeing SRSs and related
1318 1320   * data structures. Not meant to be used by mac clients.
1319 1321   */
1320 1322  void
1321 1323  mac_link_flow_clean(mac_client_handle_t mch, flow_entry_t *sub_flow)
1322 1324  {
1323      -        mac_client_impl_t       *mcip = (mac_client_impl_t *)mch;
     1325 +        mac_client_impl_t       *mcip = (mac_client_impl_t *)mch;
1324 1326          mac_impl_t              *mip = mcip->mci_mip;
1325 1327          boolean_t               last_subflow;
1326 1328  
1327 1329          ASSERT(mch != NULL);
1328 1330          ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
1329 1331  
1330 1332          /*
1331 1333           * This sub flow entry may fail to be fully initialized by
1332 1334           * mac_link_flow_init(). If so, simply return.
1333 1335           */
↓ open down ↓ 97 lines elided ↑ open up ↑
1431 1433  }
1432 1434  
1433 1435  /*
1434 1436   * mac_link_flow_modify()
1435 1437   * Modifies the properties of a flow identified by its name.
1436 1438   */
1437 1439  int
1438 1440  mac_link_flow_modify(char *flow_name, mac_resource_props_t *mrp)
1439 1441  {
1440 1442          flow_entry_t            *flent;
1441      -        mac_client_impl_t       *mcip;
     1443 +        mac_client_impl_t       *mcip;
1442 1444          int                     err = 0;
1443 1445          mac_perim_handle_t      mph;
1444 1446          datalink_id_t           linkid;
1445 1447          flow_tab_t              *flow_tab;
1446 1448  
1447 1449          err = mac_validate_props(NULL, mrp);
1448 1450          if (err != 0)
1449 1451                  return (err);
1450 1452  
1451 1453          err = mac_flow_lookup_byname(flow_name, &flent);
↓ open down ↓ 495 lines elided ↑ open up ↑
1947 1949          CHECK_AND_ADJUST_START_PTR(s, l3_start);
1948 1950  
1949 1951          l3info->l3_start = l3_start;
1950 1952          if (!OK_32PTR(l3_start))
1951 1953                  return (EINVAL);
1952 1954  
1953 1955          switch (sap) {
1954 1956          case ETHERTYPE_IP: {
1955 1957                  ipha_t  *ipha = (ipha_t *)l3_start;
1956 1958  
     1959 +                if (IPH_HDR_VERSION(ipha) != IPV4_VERSION)
     1960 +                        return (EINVAL);
1957 1961                  if (PKT_TOO_SMALL(s, l3_start + IP_SIMPLE_HDR_LENGTH))
1958 1962                          return (ENOBUFS);
1959 1963  
1960 1964                  l3info->l3_hdrsize = IPH_HDR_LENGTH(ipha);
1961 1965                  l3info->l3_protocol = ipha->ipha_protocol;
1962 1966                  l3info->l3_version = IPV4_VERSION;
1963 1967                  l3info->l3_fragmented =
1964 1968                      IS_V4_FRAGMENT(ipha->ipha_fragment_offset_and_flags);
1965 1969                  break;
1966 1970          }
1967 1971          case ETHERTYPE_IPV6: {
1968 1972                  ip6_t           *ip6h = (ip6_t *)l3_start;
1969 1973                  ip6_frag_t      *frag = NULL;
1970 1974                  uint16_t        ip6_hdrlen;
1971 1975                  uint8_t         nexthdr;
     1976 +                int             errno;
1972 1977  
1973      -                if (!mac_ip_hdr_length_v6(ip6h, s->fs_mp->b_wptr, &ip6_hdrlen,
1974      -                    &nexthdr, &frag)) {
1975      -                        return (ENOBUFS);
1976      -                }
     1978 +                errno = mac_ip_hdr_length_v6(ip6h, s->fs_mp->b_wptr,
     1979 +                    &ip6_hdrlen, &nexthdr, &frag);
     1980 +                /*
     1981 +                 * ENOBUFS is not ENOSPC, but the semantics are the
     1982 +                 * same for this caller.
     1983 +                 */
     1984 +                if (errno != 0)
     1985 +                        return (errno == ENOSPC ? ENOBUFS : errno);
1977 1986                  l3info->l3_hdrsize = ip6_hdrlen;
1978 1987                  l3info->l3_protocol = nexthdr;
1979 1988                  l3info->l3_version = IPV6_VERSION;
1980 1989                  l3info->l3_fragmented = (frag != NULL);
1981 1990                  break;
1982 1991          }
1983 1992          default:
1984 1993                  return (EINVAL);
1985 1994          }
1986 1995          return (0);
↓ open down ↓ 516 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX