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>
        
*** 18,27 ****
--- 18,28 ----
   *
   * CDDL HEADER END
   */
  /*
   * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+  * Copyright 2016 Joyent, Inc.
   */
  
  /*
   * IP PACKET CLASSIFIER
   *
*** 866,936 ****
          mutex_enter(&(connfp)->connf_lock);                             \
          IPCL_HASH_INSERT_CONNECTED_LOCKED(connfp, connp);               \
          mutex_exit(&(connfp)->connf_lock);                              \
  }
  
! #define IPCL_HASH_INSERT_BOUND(connfp, connp) {                         \
!         conn_t *pconnp = NULL, *nconnp;                                 \
!         IPCL_HASH_REMOVE((connp));                                      \
!         mutex_enter(&(connfp)->connf_lock);                             \
!         nconnp = (connfp)->connf_head;                                  \
!         while (nconnp != NULL &&                                        \
!             !_IPCL_V4_MATCH_ANY(nconnp->conn_laddr_v6)) {               \
!                 pconnp = nconnp;                                        \
!                 nconnp = nconnp->conn_next;                             \
!         }                                                               \
!         if (pconnp != NULL) {                                           \
!                 pconnp->conn_next = (connp);                            \
!                 (connp)->conn_prev = pconnp;                            \
!         } else {                                                        \
!                 (connfp)->connf_head = (connp);                         \
!         }                                                               \
!         if (nconnp != NULL) {                                           \
!                 (connp)->conn_next = nconnp;                            \
!                 nconnp->conn_prev = (connp);                            \
!         }                                                               \
!         (connp)->conn_fanout = (connfp);                                \
!         (connp)->conn_flags = ((connp)->conn_flags & ~IPCL_REMOVED) |   \
!             IPCL_BOUND;                                                 \
!         CONN_INC_REF(connp);                                            \
!         mutex_exit(&(connfp)->connf_lock);                              \
! }
  
! #define IPCL_HASH_INSERT_WILDCARD(connfp, connp) {                      \
!         conn_t **list, *prev, *next;                                    \
!         boolean_t isv4mapped =                                          \
!             IN6_IS_ADDR_V4MAPPED(&(connp)->conn_laddr_v6);              \
!         IPCL_HASH_REMOVE((connp));                                      \
!         mutex_enter(&(connfp)->connf_lock);                             \
!         list = &(connfp)->connf_head;                                   \
!         prev = NULL;                                                    \
!         while ((next = *list) != NULL) {                                \
!                 if (isv4mapped &&                                       \
!                     IN6_IS_ADDR_UNSPECIFIED(&next->conn_laddr_v6) &&    \
!                     connp->conn_zoneid == next->conn_zoneid) {          \
!                         (connp)->conn_next = next;                      \
!                         if (prev != NULL)                               \
!                                 prev = next->conn_prev;                 \
!                         next->conn_prev = (connp);                      \
!                         break;                                          \
!                 }                                                       \
!                 list = &next->conn_next;                                \
!                 prev = next;                                            \
!         }                                                               \
!         (connp)->conn_prev = prev;                                      \
!         *list = (connp);                                                \
!         (connp)->conn_fanout = (connfp);                                \
!         (connp)->conn_flags = ((connp)->conn_flags & ~IPCL_REMOVED) |   \
!             IPCL_BOUND;                                                 \
!         CONN_INC_REF((connp));                                          \
!         mutex_exit(&(connfp)->connf_lock);                              \
  }
  
  void
  ipcl_hash_insert_wildcard(connf_t *connfp, conn_t *connp)
  {
!         IPCL_HASH_INSERT_WILDCARD(connfp, connp);
  }
  
  /*
   * Because the classifier is used to classify inbound packets, the destination
   * address is meant to be our local tunnel address (tunnel source), and the
--- 867,960 ----
          mutex_enter(&(connfp)->connf_lock);                             \
          IPCL_HASH_INSERT_CONNECTED_LOCKED(connfp, connp);               \
          mutex_exit(&(connfp)->connf_lock);                              \
  }
  
! /*
!  * When inserting bound or wildcard entries into the hash, ordering rules are
!  * used to facilitate timely and correct lookups.  The order is as follows:
!  * 1. Entries bound to a specific address
!  * 2. Entries bound to INADDR_ANY
!  * 3. Entries bound to ADDR_UNSPECIFIED
!  * Entries in a category which share conn_lport (such as those using
!  * SO_REUSEPORT) will be ordered such that the newest inserted is first.
!  */
  
! void
! ipcl_hash_insert_bound(connf_t *connfp, conn_t *connp)
! {
!         conn_t *pconnp, *nconnp;
! 
!         IPCL_HASH_REMOVE(connp);
!         mutex_enter(&connfp->connf_lock);
!         nconnp = connfp->connf_head;
!         pconnp = NULL;
!         while (nconnp != NULL) {
!                 /*
!                  * Walk though entries associated with the fanout until one is
!                  * found which fulfills any of these conditions:
!                  * 1. Listen address of ADDR_ANY/ADDR_UNSPECIFIED
!                  * 2. Listen port the same as connp
!                  */
!                 if (_IPCL_V4_MATCH_ANY(nconnp->conn_laddr_v6) ||
!                     connp->conn_lport == nconnp->conn_lport)
!                         break;
!                 pconnp = nconnp;
!                 nconnp = nconnp->conn_next;
!         }
!         if (pconnp != NULL) {
!                 pconnp->conn_next = connp;
!                 connp->conn_prev = pconnp;
!         } else {
!                 connfp->connf_head = connp;
!         }
!         if (nconnp != NULL) {
!                 connp->conn_next = nconnp;
!                 nconnp->conn_prev = connp;
!         }
!         connp->conn_fanout = connfp;
!         connp->conn_flags = (connp->conn_flags & ~IPCL_REMOVED) | IPCL_BOUND;
!         CONN_INC_REF(connp);
!         mutex_exit(&connfp->connf_lock);
  }
  
  void
  ipcl_hash_insert_wildcard(connf_t *connfp, conn_t *connp)
  {
!         conn_t *pconnp = NULL, *nconnp;
!         boolean_t isv4mapped = IN6_IS_ADDR_V4MAPPED(&connp->conn_laddr_v6);
! 
!         IPCL_HASH_REMOVE(connp);
!         mutex_enter(&connfp->connf_lock);
!         nconnp = connfp->connf_head;
!         pconnp = NULL;
!         while (nconnp != NULL) {
!                 if (IN6_IS_ADDR_V4MAPPED_ANY(&nconnp->conn_laddr_v6) &&
!                     isv4mapped && connp->conn_lport == nconnp->conn_lport)
!                         break;
!                 if (IN6_IS_ADDR_UNSPECIFIED(&nconnp->conn_laddr_v6) &&
!                     (isv4mapped ||
!                     connp->conn_lport == nconnp->conn_lport))
!                         break;
! 
!                 pconnp = nconnp;
!                 nconnp = nconnp->conn_next;
!         }
!         if (pconnp != NULL) {
!                 pconnp->conn_next = connp;
!                 connp->conn_prev = pconnp;
!         } else {
!                 connfp->connf_head = connp;
!         }
!         if (nconnp != NULL) {
!                 connp->conn_next = nconnp;
!                 nconnp->conn_prev = connp;
!         }
!         connp->conn_fanout = connfp;
!         connp->conn_flags = (connp->conn_flags & ~IPCL_REMOVED) | IPCL_BOUND;
!         CONN_INC_REF(connp);
!         mutex_exit(&connfp->connf_lock);
  }
  
  /*
   * Because the classifier is used to classify inbound packets, the destination
   * address is meant to be our local tunnel address (tunnel source), and the
*** 1032,1044 ****
  
          if (IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6) ||
              IN6_IS_ADDR_V4MAPPED_ANY(&connp->conn_faddr_v6)) {
                  if (IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6) ||
                      IN6_IS_ADDR_V4MAPPED_ANY(&connp->conn_laddr_v6)) {
!                         IPCL_HASH_INSERT_WILDCARD(connfp, connp);
                  } else {
!                         IPCL_HASH_INSERT_BOUND(connfp, connp);
                  }
          } else {
                  IPCL_HASH_INSERT_CONNECTED(connfp, connp);
          }
          return (0);
--- 1056,1068 ----
  
          if (IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6) ||
              IN6_IS_ADDR_V4MAPPED_ANY(&connp->conn_faddr_v6)) {
                  if (IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6) ||
                      IN6_IS_ADDR_V4MAPPED_ANY(&connp->conn_laddr_v6)) {
!                         ipcl_hash_insert_wildcard(connfp, connp);
                  } else {
!                         ipcl_hash_insert_bound(connfp, connp);
                  }
          } else {
                  IPCL_HASH_INSERT_CONNECTED(connfp, connp);
          }
          return (0);
*** 1203,1215 ****
                  }
  
                  if (connp->conn_faddr_v4 != INADDR_ANY) {
                          IPCL_HASH_INSERT_CONNECTED(connfp, connp);
                  } else if (connp->conn_laddr_v4 != INADDR_ANY) {
!                         IPCL_HASH_INSERT_BOUND(connfp, connp);
                  } else {
!                         IPCL_HASH_INSERT_WILDCARD(connfp, connp);
                  }
                  if (protocol == IPPROTO_RSVP)
                          ill_set_inputfn_all(ipst);
                  break;
  
--- 1227,1239 ----
                  }
  
                  if (connp->conn_faddr_v4 != INADDR_ANY) {
                          IPCL_HASH_INSERT_CONNECTED(connfp, connp);
                  } else if (connp->conn_laddr_v4 != INADDR_ANY) {
!                         ipcl_hash_insert_bound(connfp, connp);
                  } else {
!                         ipcl_hash_insert_wildcard(connfp, connp);
                  }
                  if (protocol == IPPROTO_RSVP)
                          ill_set_inputfn_all(ipst);
                  break;
  
*** 1217,1229 ****
                  /* Insert it in the Bind Hash */
                  ASSERT(connp->conn_zoneid != ALL_ZONES);
                  connfp = &ipst->ips_ipcl_bind_fanout[
                      IPCL_BIND_HASH(lport, ipst)];
                  if (connp->conn_laddr_v4 != INADDR_ANY) {
!                         IPCL_HASH_INSERT_BOUND(connfp, connp);
                  } else {
!                         IPCL_HASH_INSERT_WILDCARD(connfp, connp);
                  }
                  if (cl_inet_listen != NULL) {
                          ASSERT(connp->conn_ipversion == IPV4_VERSION);
                          connp->conn_flags |= IPCL_CL_LISTENER;
                          (*cl_inet_listen)(
--- 1241,1253 ----
                  /* Insert it in the Bind Hash */
                  ASSERT(connp->conn_zoneid != ALL_ZONES);
                  connfp = &ipst->ips_ipcl_bind_fanout[
                      IPCL_BIND_HASH(lport, ipst)];
                  if (connp->conn_laddr_v4 != INADDR_ANY) {
!                         ipcl_hash_insert_bound(connfp, connp);
                  } else {
!                         ipcl_hash_insert_wildcard(connfp, connp);
                  }
                  if (cl_inet_listen != NULL) {
                          ASSERT(connp->conn_ipversion == IPV4_VERSION);
                          connp->conn_flags |= IPCL_CL_LISTENER;
                          (*cl_inet_listen)(
*** 1269,1293 ****
                  }
  
                  if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6)) {
                          IPCL_HASH_INSERT_CONNECTED(connfp, connp);
                  } else if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6)) {
!                         IPCL_HASH_INSERT_BOUND(connfp, connp);
                  } else {
!                         IPCL_HASH_INSERT_WILDCARD(connfp, connp);
                  }
                  break;
  
          case IPPROTO_TCP:
                  /* Insert it in the Bind Hash */
                  ASSERT(connp->conn_zoneid != ALL_ZONES);
                  connfp = &ipst->ips_ipcl_bind_fanout[
                      IPCL_BIND_HASH(lport, ipst)];
                  if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6)) {
!                         IPCL_HASH_INSERT_BOUND(connfp, connp);
                  } else {
!                         IPCL_HASH_INSERT_WILDCARD(connfp, connp);
                  }
                  if (cl_inet_listen != NULL) {
                          sa_family_t     addr_family;
                          uint8_t         *laddrp;
  
--- 1293,1317 ----
                  }
  
                  if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6)) {
                          IPCL_HASH_INSERT_CONNECTED(connfp, connp);
                  } else if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6)) {
!                         ipcl_hash_insert_bound(connfp, connp);
                  } else {
!                         ipcl_hash_insert_wildcard(connfp, connp);
                  }
                  break;
  
          case IPPROTO_TCP:
                  /* Insert it in the Bind Hash */
                  ASSERT(connp->conn_zoneid != ALL_ZONES);
                  connfp = &ipst->ips_ipcl_bind_fanout[
                      IPCL_BIND_HASH(lport, ipst)];
                  if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6)) {
!                         ipcl_hash_insert_bound(connfp, connp);
                  } else {
!                         ipcl_hash_insert_wildcard(connfp, connp);
                  }
                  if (cl_inet_listen != NULL) {
                          sa_family_t     addr_family;
                          uint8_t         *laddrp;
  
*** 1414,1426 ****
                  }
  
                  if (connp->conn_faddr_v4 != INADDR_ANY) {
                          IPCL_HASH_INSERT_CONNECTED(connfp, connp);
                  } else if (connp->conn_laddr_v4 != INADDR_ANY) {
!                         IPCL_HASH_INSERT_BOUND(connfp, connp);
                  } else {
!                         IPCL_HASH_INSERT_WILDCARD(connfp, connp);
                  }
                  break;
          }
  
          return (ret);
--- 1438,1450 ----
                  }
  
                  if (connp->conn_faddr_v4 != INADDR_ANY) {
                          IPCL_HASH_INSERT_CONNECTED(connfp, connp);
                  } else if (connp->conn_laddr_v4 != INADDR_ANY) {
!                         ipcl_hash_insert_bound(connfp, connp);
                  } else {
!                         ipcl_hash_insert_wildcard(connfp, connp);
                  }
                  break;
          }
  
          return (ret);
*** 1502,1514 ****
                  }
  
                  if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6)) {
                          IPCL_HASH_INSERT_CONNECTED(connfp, connp);
                  } else if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6)) {
!                         IPCL_HASH_INSERT_BOUND(connfp, connp);
                  } else {
!                         IPCL_HASH_INSERT_WILDCARD(connfp, connp);
                  }
                  break;
          }
  
          return (ret);
--- 1526,1538 ----
                  }
  
                  if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6)) {
                          IPCL_HASH_INSERT_CONNECTED(connfp, connp);
                  } else if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6)) {
!                         ipcl_hash_insert_bound(connfp, connp);
                  } else {
!                         ipcl_hash_insert_wildcard(connfp, connp);
                  }
                  break;
          }
  
          return (ret);
*** 2090,2099 ****
--- 2114,2124 ----
          cv_init(&connp->conn_cv, NULL, CV_DEFAULT, NULL);
          connp->conn_icmp = icmp;
          connp->conn_flags = IPCL_RAWIPCONN;
          connp->conn_proto = IPPROTO_ICMP;
          icmp->icmp_connp = connp;
+         rw_init(&icmp->icmp_bpf_lock, NULL, RW_DEFAULT, NULL);
          rw_init(&connp->conn_ilg_lock, NULL, RW_DEFAULT, NULL);
          connp->conn_ixa = kmem_zalloc(sizeof (ip_xmit_attr_t), kmflags);
          if (connp->conn_ixa == NULL)
                  return (ENOMEM);
          connp->conn_ixa->ixa_refcnt = 1;
*** 2114,2123 ****
--- 2139,2149 ----
          ASSERT(icmp->icmp_connp == connp);
          ASSERT(connp->conn_icmp == icmp);
          mutex_destroy(&connp->conn_lock);
          cv_destroy(&connp->conn_cv);
          rw_destroy(&connp->conn_ilg_lock);
+         rw_destroy(&icmp->icmp_bpf_lock);
  
          /* Can be NULL if constructor failed */
          if (connp->conn_ixa != NULL) {
                  ASSERT(connp->conn_ixa->ixa_refcnt == 1);
                  ASSERT(connp->conn_ixa->ixa_ire == NULL);