Print this page
Reduce lint
OS-5007 support SO_ATTACH_FILTER on ICMP sockets
Reviewed by: Cody Mello <melloc@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Approved by: Jerry Jelinek <jerry.jelinek@joyent.com>
OS-4018 lxbrand support TCP SO_REUSEPORT
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Cody Mello <cody.mello@joyent.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/inet/ip/ipclassifier.c
          +++ new/usr/src/uts/common/inet/ip/ipclassifier.c
↓ open down ↓ 12 lines elided ↑ open up ↑
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  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   * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
       23 + * Copyright 2016 Joyent, Inc.
  23   24   */
  24   25  
  25   26  /*
  26   27   * IP PACKET CLASSIFIER
  27   28   *
  28   29   * The IP packet classifier provides mapping between IP packets and persistent
  29   30   * connection state for connection-oriented protocols. It also provides
  30   31   * interface for managing connection states.
  31   32   *
  32   33   * The connection state is kept in conn_t data structure and contains, among
↓ open down ↓ 828 lines elided ↑ open up ↑
 861  862          CONN_INC_REF(connp);                                            \
 862  863  }
 863  864  
 864  865  #define IPCL_HASH_INSERT_CONNECTED(connfp, connp) {                     \
 865  866          IPCL_HASH_REMOVE((connp));                                      \
 866  867          mutex_enter(&(connfp)->connf_lock);                             \
 867  868          IPCL_HASH_INSERT_CONNECTED_LOCKED(connfp, connp);               \
 868  869          mutex_exit(&(connfp)->connf_lock);                              \
 869  870  }
 870  871  
 871      -#define IPCL_HASH_INSERT_BOUND(connfp, connp) {                         \
 872      -        conn_t *pconnp = NULL, *nconnp;                                 \
 873      -        IPCL_HASH_REMOVE((connp));                                      \
 874      -        mutex_enter(&(connfp)->connf_lock);                             \
 875      -        nconnp = (connfp)->connf_head;                                  \
 876      -        while (nconnp != NULL &&                                        \
 877      -            !_IPCL_V4_MATCH_ANY(nconnp->conn_laddr_v6)) {               \
 878      -                pconnp = nconnp;                                        \
 879      -                nconnp = nconnp->conn_next;                             \
 880      -        }                                                               \
 881      -        if (pconnp != NULL) {                                           \
 882      -                pconnp->conn_next = (connp);                            \
 883      -                (connp)->conn_prev = pconnp;                            \
 884      -        } else {                                                        \
 885      -                (connfp)->connf_head = (connp);                         \
 886      -        }                                                               \
 887      -        if (nconnp != NULL) {                                           \
 888      -                (connp)->conn_next = nconnp;                            \
 889      -                nconnp->conn_prev = (connp);                            \
 890      -        }                                                               \
 891      -        (connp)->conn_fanout = (connfp);                                \
 892      -        (connp)->conn_flags = ((connp)->conn_flags & ~IPCL_REMOVED) |   \
 893      -            IPCL_BOUND;                                                 \
 894      -        CONN_INC_REF(connp);                                            \
 895      -        mutex_exit(&(connfp)->connf_lock);                              \
 896      -}
      872 +/*
      873 + * When inserting bound or wildcard entries into the hash, ordering rules are
      874 + * used to facilitate timely and correct lookups.  The order is as follows:
      875 + * 1. Entries bound to a specific address
      876 + * 2. Entries bound to INADDR_ANY
      877 + * 3. Entries bound to ADDR_UNSPECIFIED
      878 + * Entries in a category which share conn_lport (such as those using
      879 + * SO_REUSEPORT) will be ordered such that the newest inserted is first.
      880 + */
 897  881  
 898      -#define IPCL_HASH_INSERT_WILDCARD(connfp, connp) {                      \
 899      -        conn_t **list, *prev, *next;                                    \
 900      -        boolean_t isv4mapped =                                          \
 901      -            IN6_IS_ADDR_V4MAPPED(&(connp)->conn_laddr_v6);              \
 902      -        IPCL_HASH_REMOVE((connp));                                      \
 903      -        mutex_enter(&(connfp)->connf_lock);                             \
 904      -        list = &(connfp)->connf_head;                                   \
 905      -        prev = NULL;                                                    \
 906      -        while ((next = *list) != NULL) {                                \
 907      -                if (isv4mapped &&                                       \
 908      -                    IN6_IS_ADDR_UNSPECIFIED(&next->conn_laddr_v6) &&    \
 909      -                    connp->conn_zoneid == next->conn_zoneid) {          \
 910      -                        (connp)->conn_next = next;                      \
 911      -                        if (prev != NULL)                               \
 912      -                                prev = next->conn_prev;                 \
 913      -                        next->conn_prev = (connp);                      \
 914      -                        break;                                          \
 915      -                }                                                       \
 916      -                list = &next->conn_next;                                \
 917      -                prev = next;                                            \
 918      -        }                                                               \
 919      -        (connp)->conn_prev = prev;                                      \
 920      -        *list = (connp);                                                \
 921      -        (connp)->conn_fanout = (connfp);                                \
 922      -        (connp)->conn_flags = ((connp)->conn_flags & ~IPCL_REMOVED) |   \
 923      -            IPCL_BOUND;                                                 \
 924      -        CONN_INC_REF((connp));                                          \
 925      -        mutex_exit(&(connfp)->connf_lock);                              \
      882 +void
      883 +ipcl_hash_insert_bound(connf_t *connfp, conn_t *connp)
      884 +{
      885 +        conn_t *pconnp, *nconnp;
      886 +
      887 +        IPCL_HASH_REMOVE(connp);
      888 +        mutex_enter(&connfp->connf_lock);
      889 +        nconnp = connfp->connf_head;
      890 +        pconnp = NULL;
      891 +        while (nconnp != NULL) {
      892 +                /*
      893 +                 * Walk though entries associated with the fanout until one is
      894 +                 * found which fulfills any of these conditions:
      895 +                 * 1. Listen address of ADDR_ANY/ADDR_UNSPECIFIED
      896 +                 * 2. Listen port the same as connp
      897 +                 */
      898 +                if (_IPCL_V4_MATCH_ANY(nconnp->conn_laddr_v6) ||
      899 +                    connp->conn_lport == nconnp->conn_lport)
      900 +                        break;
      901 +                pconnp = nconnp;
      902 +                nconnp = nconnp->conn_next;
      903 +        }
      904 +        if (pconnp != NULL) {
      905 +                pconnp->conn_next = connp;
      906 +                connp->conn_prev = pconnp;
      907 +        } else {
      908 +                connfp->connf_head = connp;
      909 +        }
      910 +        if (nconnp != NULL) {
      911 +                connp->conn_next = nconnp;
      912 +                nconnp->conn_prev = connp;
      913 +        }
      914 +        connp->conn_fanout = connfp;
      915 +        connp->conn_flags = (connp->conn_flags & ~IPCL_REMOVED) | IPCL_BOUND;
      916 +        CONN_INC_REF(connp);
      917 +        mutex_exit(&connfp->connf_lock);
 926  918  }
 927  919  
 928  920  void
 929  921  ipcl_hash_insert_wildcard(connf_t *connfp, conn_t *connp)
 930  922  {
 931      -        IPCL_HASH_INSERT_WILDCARD(connfp, connp);
      923 +        conn_t *pconnp = NULL, *nconnp;
      924 +        boolean_t isv4mapped = IN6_IS_ADDR_V4MAPPED(&connp->conn_laddr_v6);
      925 +
      926 +        IPCL_HASH_REMOVE(connp);
      927 +        mutex_enter(&connfp->connf_lock);
      928 +        nconnp = connfp->connf_head;
      929 +        pconnp = NULL;
      930 +        while (nconnp != NULL) {
      931 +                if (IN6_IS_ADDR_V4MAPPED_ANY(&nconnp->conn_laddr_v6) &&
      932 +                    isv4mapped && connp->conn_lport == nconnp->conn_lport)
      933 +                        break;
      934 +                if (IN6_IS_ADDR_UNSPECIFIED(&nconnp->conn_laddr_v6) &&
      935 +                    (isv4mapped ||
      936 +                    connp->conn_lport == nconnp->conn_lport))
      937 +                        break;
      938 +
      939 +                pconnp = nconnp;
      940 +                nconnp = nconnp->conn_next;
      941 +        }
      942 +        if (pconnp != NULL) {
      943 +                pconnp->conn_next = connp;
      944 +                connp->conn_prev = pconnp;
      945 +        } else {
      946 +                connfp->connf_head = connp;
      947 +        }
      948 +        if (nconnp != NULL) {
      949 +                connp->conn_next = nconnp;
      950 +                nconnp->conn_prev = connp;
      951 +        }
      952 +        connp->conn_fanout = connfp;
      953 +        connp->conn_flags = (connp->conn_flags & ~IPCL_REMOVED) | IPCL_BOUND;
      954 +        CONN_INC_REF(connp);
      955 +        mutex_exit(&connfp->connf_lock);
 932  956  }
 933  957  
 934  958  /*
 935  959   * Because the classifier is used to classify inbound packets, the destination
 936  960   * address is meant to be our local tunnel address (tunnel source), and the
 937  961   * source the remote tunnel address (tunnel destination).
 938  962   *
 939  963   * Note that conn_proto can't be used for fanout since the upper protocol
 940  964   * can be both 41 and 4 when IPv6 and IPv4 are over the same tunnel.
 941  965   */
↓ open down ↓ 85 lines elided ↑ open up ↑
1027 1051                  }
1028 1052          }
1029 1053          mutex_exit(&connfp->connf_lock);
1030 1054          if (oconnp != NULL)
1031 1055                  return (EADDRNOTAVAIL);
1032 1056  
1033 1057          if (IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6) ||
1034 1058              IN6_IS_ADDR_V4MAPPED_ANY(&connp->conn_faddr_v6)) {
1035 1059                  if (IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6) ||
1036 1060                      IN6_IS_ADDR_V4MAPPED_ANY(&connp->conn_laddr_v6)) {
1037      -                        IPCL_HASH_INSERT_WILDCARD(connfp, connp);
     1061 +                        ipcl_hash_insert_wildcard(connfp, connp);
1038 1062                  } else {
1039      -                        IPCL_HASH_INSERT_BOUND(connfp, connp);
     1063 +                        ipcl_hash_insert_bound(connfp, connp);
1040 1064                  }
1041 1065          } else {
1042 1066                  IPCL_HASH_INSERT_CONNECTED(connfp, connp);
1043 1067          }
1044 1068          return (0);
1045 1069  }
1046 1070  
1047 1071  static int
1048 1072  ipcl_iptun_hash_insert(conn_t *connp, ip_stack_t *ipst)
1049 1073  {
↓ open down ↓ 148 lines elided ↑ open up ↑
1198 1222                  if (protocol == IPPROTO_UDP) {
1199 1223                          connfp = &ipst->ips_ipcl_udp_fanout[
1200 1224                              IPCL_UDP_HASH(lport, ipst)];
1201 1225                  } else {
1202 1226                          connfp = &ipst->ips_ipcl_proto_fanout_v4[protocol];
1203 1227                  }
1204 1228  
1205 1229                  if (connp->conn_faddr_v4 != INADDR_ANY) {
1206 1230                          IPCL_HASH_INSERT_CONNECTED(connfp, connp);
1207 1231                  } else if (connp->conn_laddr_v4 != INADDR_ANY) {
1208      -                        IPCL_HASH_INSERT_BOUND(connfp, connp);
     1232 +                        ipcl_hash_insert_bound(connfp, connp);
1209 1233                  } else {
1210      -                        IPCL_HASH_INSERT_WILDCARD(connfp, connp);
     1234 +                        ipcl_hash_insert_wildcard(connfp, connp);
1211 1235                  }
1212 1236                  if (protocol == IPPROTO_RSVP)
1213 1237                          ill_set_inputfn_all(ipst);
1214 1238                  break;
1215 1239  
1216 1240          case IPPROTO_TCP:
1217 1241                  /* Insert it in the Bind Hash */
1218 1242                  ASSERT(connp->conn_zoneid != ALL_ZONES);
1219 1243                  connfp = &ipst->ips_ipcl_bind_fanout[
1220 1244                      IPCL_BIND_HASH(lport, ipst)];
1221 1245                  if (connp->conn_laddr_v4 != INADDR_ANY) {
1222      -                        IPCL_HASH_INSERT_BOUND(connfp, connp);
     1246 +                        ipcl_hash_insert_bound(connfp, connp);
1223 1247                  } else {
1224      -                        IPCL_HASH_INSERT_WILDCARD(connfp, connp);
     1248 +                        ipcl_hash_insert_wildcard(connfp, connp);
1225 1249                  }
1226 1250                  if (cl_inet_listen != NULL) {
1227 1251                          ASSERT(connp->conn_ipversion == IPV4_VERSION);
1228 1252                          connp->conn_flags |= IPCL_CL_LISTENER;
1229 1253                          (*cl_inet_listen)(
1230 1254                              connp->conn_netstack->netstack_stackid,
1231 1255                              IPPROTO_TCP, AF_INET,
1232 1256                              (uint8_t *)&connp->conn_bound_addr_v4, lport, NULL);
1233 1257                  }
1234 1258                  break;
↓ open down ↓ 29 lines elided ↑ open up ↑
1264 1288                  if (protocol == IPPROTO_UDP) {
1265 1289                          connfp = &ipst->ips_ipcl_udp_fanout[
1266 1290                              IPCL_UDP_HASH(lport, ipst)];
1267 1291                  } else {
1268 1292                          connfp = &ipst->ips_ipcl_proto_fanout_v6[protocol];
1269 1293                  }
1270 1294  
1271 1295                  if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6)) {
1272 1296                          IPCL_HASH_INSERT_CONNECTED(connfp, connp);
1273 1297                  } else if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6)) {
1274      -                        IPCL_HASH_INSERT_BOUND(connfp, connp);
     1298 +                        ipcl_hash_insert_bound(connfp, connp);
1275 1299                  } else {
1276      -                        IPCL_HASH_INSERT_WILDCARD(connfp, connp);
     1300 +                        ipcl_hash_insert_wildcard(connfp, connp);
1277 1301                  }
1278 1302                  break;
1279 1303  
1280 1304          case IPPROTO_TCP:
1281 1305                  /* Insert it in the Bind Hash */
1282 1306                  ASSERT(connp->conn_zoneid != ALL_ZONES);
1283 1307                  connfp = &ipst->ips_ipcl_bind_fanout[
1284 1308                      IPCL_BIND_HASH(lport, ipst)];
1285 1309                  if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6)) {
1286      -                        IPCL_HASH_INSERT_BOUND(connfp, connp);
     1310 +                        ipcl_hash_insert_bound(connfp, connp);
1287 1311                  } else {
1288      -                        IPCL_HASH_INSERT_WILDCARD(connfp, connp);
     1312 +                        ipcl_hash_insert_wildcard(connfp, connp);
1289 1313                  }
1290 1314                  if (cl_inet_listen != NULL) {
1291 1315                          sa_family_t     addr_family;
1292 1316                          uint8_t         *laddrp;
1293 1317  
1294 1318                          if (connp->conn_ipversion == IPV6_VERSION) {
1295 1319                                  addr_family = AF_INET6;
1296 1320                                  laddrp =
1297 1321                                      (uint8_t *)&connp->conn_bound_addr_v6;
1298 1322                          } else {
↓ open down ↓ 110 lines elided ↑ open up ↑
1409 1433                  if (protocol == IPPROTO_UDP) {
1410 1434                          connfp = &ipst->ips_ipcl_udp_fanout[
1411 1435                              IPCL_UDP_HASH(lport, ipst)];
1412 1436                  } else {
1413 1437                          connfp = &ipst->ips_ipcl_proto_fanout_v4[protocol];
1414 1438                  }
1415 1439  
1416 1440                  if (connp->conn_faddr_v4 != INADDR_ANY) {
1417 1441                          IPCL_HASH_INSERT_CONNECTED(connfp, connp);
1418 1442                  } else if (connp->conn_laddr_v4 != INADDR_ANY) {
1419      -                        IPCL_HASH_INSERT_BOUND(connfp, connp);
     1443 +                        ipcl_hash_insert_bound(connfp, connp);
1420 1444                  } else {
1421      -                        IPCL_HASH_INSERT_WILDCARD(connfp, connp);
     1445 +                        ipcl_hash_insert_wildcard(connfp, connp);
1422 1446                  }
1423 1447                  break;
1424 1448          }
1425 1449  
1426 1450          return (ret);
1427 1451  }
1428 1452  
1429 1453  int
1430 1454  ipcl_conn_insert_v6(conn_t *connp)
1431 1455  {
↓ open down ↓ 65 lines elided ↑ open up ↑
1497 1521                  if (protocol == IPPROTO_UDP) {
1498 1522                          connfp = &ipst->ips_ipcl_udp_fanout[
1499 1523                              IPCL_UDP_HASH(lport, ipst)];
1500 1524                  } else {
1501 1525                          connfp = &ipst->ips_ipcl_proto_fanout_v6[protocol];
1502 1526                  }
1503 1527  
1504 1528                  if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6)) {
1505 1529                          IPCL_HASH_INSERT_CONNECTED(connfp, connp);
1506 1530                  } else if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6)) {
1507      -                        IPCL_HASH_INSERT_BOUND(connfp, connp);
     1531 +                        ipcl_hash_insert_bound(connfp, connp);
1508 1532                  } else {
1509      -                        IPCL_HASH_INSERT_WILDCARD(connfp, connp);
     1533 +                        ipcl_hash_insert_wildcard(connfp, connp);
1510 1534                  }
1511 1535                  break;
1512 1536          }
1513 1537  
1514 1538          return (ret);
1515 1539  }
1516 1540  
1517 1541  /*
1518 1542   * v4 packet classifying function. looks up the fanout table to
1519 1543   * find the conn, the packet belongs to. returns the conn with
↓ open down ↓ 565 lines elided ↑ open up ↑
2085 2109  
2086 2110          bzero(connp, sizeof (conn_t));
2087 2111          bzero(icmp, sizeof (icmp_t));
2088 2112  
2089 2113          mutex_init(&connp->conn_lock, NULL, MUTEX_DEFAULT, NULL);
2090 2114          cv_init(&connp->conn_cv, NULL, CV_DEFAULT, NULL);
2091 2115          connp->conn_icmp = icmp;
2092 2116          connp->conn_flags = IPCL_RAWIPCONN;
2093 2117          connp->conn_proto = IPPROTO_ICMP;
2094 2118          icmp->icmp_connp = connp;
     2119 +        rw_init(&icmp->icmp_bpf_lock, NULL, RW_DEFAULT, NULL);
2095 2120          rw_init(&connp->conn_ilg_lock, NULL, RW_DEFAULT, NULL);
2096 2121          connp->conn_ixa = kmem_zalloc(sizeof (ip_xmit_attr_t), kmflags);
2097 2122          if (connp->conn_ixa == NULL)
2098 2123                  return (ENOMEM);
2099 2124          connp->conn_ixa->ixa_refcnt = 1;
2100 2125          connp->conn_ixa->ixa_protocol = connp->conn_proto;
2101 2126          connp->conn_ixa->ixa_xmit_hint = CONN_TO_XMIT_HINT(connp);
2102 2127          return (0);
2103 2128  }
2104 2129  
↓ open down ↓ 4 lines elided ↑ open up ↑
2109 2134          itc_t   *itc = (itc_t *)buf;
2110 2135          conn_t  *connp = &itc->itc_conn;
2111 2136          icmp_t  *icmp = (icmp_t *)&itc[1];
2112 2137  
2113 2138          ASSERT(connp->conn_flags & IPCL_RAWIPCONN);
2114 2139          ASSERT(icmp->icmp_connp == connp);
2115 2140          ASSERT(connp->conn_icmp == icmp);
2116 2141          mutex_destroy(&connp->conn_lock);
2117 2142          cv_destroy(&connp->conn_cv);
2118 2143          rw_destroy(&connp->conn_ilg_lock);
     2144 +        rw_destroy(&icmp->icmp_bpf_lock);
2119 2145  
2120 2146          /* Can be NULL if constructor failed */
2121 2147          if (connp->conn_ixa != NULL) {
2122 2148                  ASSERT(connp->conn_ixa->ixa_refcnt == 1);
2123 2149                  ASSERT(connp->conn_ixa->ixa_ire == NULL);
2124 2150                  ASSERT(connp->conn_ixa->ixa_nce == NULL);
2125 2151                  ixa_refrele(connp->conn_ixa);
2126 2152          }
2127 2153  }
2128 2154  
↓ open down ↓ 596 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX