Print this page
dccp: conn_t

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 ↓ 59 lines elided ↑ open up ↑
  60   60   *
  61   61   * Classifier uses several hash tables:
  62   62   *
  63   63   *      ipcl_conn_fanout:       contains all TCP connections in CONNECTED state
  64   64   *      ipcl_bind_fanout:       contains all connections in BOUND state
  65   65   *      ipcl_proto_fanout:      IPv4 protocol fanout
  66   66   *      ipcl_proto_fanout_v6:   IPv6 protocol fanout
  67   67   *      ipcl_udp_fanout:        contains all UDP connections
  68   68   *      ipcl_iptun_fanout:      contains all IP tunnel connections
  69   69   *      ipcl_globalhash_fanout: contains all connections
       70 + *`     ipcl_dccp_conn_fanout:  contains all DCCP connections in CONNECTED state
       71 + *      ipcl_dccp_bind_fanout:  contains all DCCP connections in BOUND state
  70   72   *
  71   73   * The ipcl_globalhash_fanout is used for any walkers (like snmp and Clustering)
  72   74   * which need to view all existing connections.
  73   75   *
  74   76   * All tables are protected by per-bucket locks. When both per-bucket lock and
  75   77   * connection lock need to be held, the per-bucket lock should be acquired
  76   78   * first, followed by the connection lock.
  77   79   *
  78   80   * All functions doing search in one of these tables increment a reference
  79   81   * counter on the connection found (if any). This reference should be dropped
↓ open down ↓ 136 lines elided ↑ open up ↑
 216  218   *      Creates a new conn based on the type flag, inserts it into
 217  219   *      globalhash table.
 218  220   *
 219  221   *      type:   This flag determines the type of conn_t which needs to be
 220  222   *              created i.e., which kmem_cache it comes from.
 221  223   *              IPCL_TCPCONN    indicates a TCP connection
 222  224   *              IPCL_SCTPCONN   indicates a SCTP connection
 223  225   *              IPCL_UDPCONN    indicates a UDP conn_t.
 224  226   *              IPCL_RAWIPCONN  indicates a RAWIP/ICMP conn_t.
 225  227   *              IPCL_RTSCONN    indicates a RTS conn_t.
      228 + *              IPCL_DCCPCONN   indicates a DCCP conn_t.
 226  229   *              IPCL_IPCCONN    indicates all other connections.
 227  230   *
 228  231   * void ipcl_conn_destroy(connp)
 229  232   *
 230  233   *      Destroys the connection state, removes it from the global
 231  234   *      connection hash table and frees its memory.
 232  235   */
 233  236  
 234  237  #include <sys/types.h>
 235  238  #include <sys/stream.h>
↓ open down ↓ 14 lines elided ↑ open up ↑
 250  253  #include <netinet/ip6.h>
 251  254  #include <netinet/icmp6.h>
 252  255  
 253  256  #include <inet/ip.h>
 254  257  #include <inet/ip_if.h>
 255  258  #include <inet/ip_ire.h>
 256  259  #include <inet/ip6.h>
 257  260  #include <inet/ip_ndp.h>
 258  261  #include <inet/ip_impl.h>
 259  262  #include <inet/udp_impl.h>
      263 +#include <inet/dccp_impl.h>
 260  264  #include <inet/sctp_ip.h>
 261  265  #include <inet/sctp/sctp_impl.h>
 262  266  #include <inet/rawip_impl.h>
 263  267  #include <inet/rts_impl.h>
 264  268  #include <inet/iptun/iptun_impl.h>
 265  269  
 266  270  #include <sys/cpuvar.h>
 267  271  
 268  272  #include <inet/ipclassifier.h>
 269  273  #include <inet/tcp.h>
↓ open down ↓ 7 lines elided ↑ open up ↑
 277  281  
 278  282  /* New value. Zero means choose automatically.  Setable in /etc/system */
 279  283  uint_t ipcl_conn_hash_size = 0;
 280  284  uint_t ipcl_conn_hash_memfactor = 8192;
 281  285  uint_t ipcl_conn_hash_maxsize = 82500;
 282  286  
 283  287  /* bind/udp fanout table size */
 284  288  uint_t ipcl_bind_fanout_size = 512;
 285  289  uint_t ipcl_udp_fanout_size = 16384;
 286  290  
      291 +/* Fanout table sizes for dccp */
      292 +uint_t ipcl_dccp_conn_fanout_size = 512;
      293 +uint_t ipcl_dccp_bind_fanout_size = 512;
      294 +
 287  295  /* Raw socket fanout size.  Must be a power of 2. */
 288  296  uint_t ipcl_raw_fanout_size = 256;
 289  297  
 290  298  /*
 291  299   * The IPCL_IPTUN_HASH() function works best with a prime table size.  We
 292  300   * expect that most large deployments would have hundreds of tunnels, and
 293  301   * thousands in the extreme case.
 294  302   */
 295  303  uint_t ipcl_iptun_fanout_size = 6143;
 296  304  
↓ open down ↓ 15 lines elided ↑ open up ↑
 312  320          conn_t  itc_conn;
 313  321          char    itcu_filler[CACHE_ALIGN(conn_s)];
 314  322  } itc_t;
 315  323  
 316  324  struct kmem_cache  *tcp_conn_cache;
 317  325  struct kmem_cache  *ip_conn_cache;
 318  326  extern struct kmem_cache  *sctp_conn_cache;
 319  327  struct kmem_cache  *udp_conn_cache;
 320  328  struct kmem_cache  *rawip_conn_cache;
 321  329  struct kmem_cache  *rts_conn_cache;
      330 +struct kmem_cache  *dccp_conn_cache;
 322  331  
 323  332  extern void     tcp_timermp_free(tcp_t *);
 324  333  extern mblk_t   *tcp_timermp_alloc(int);
 325  334  
 326  335  static int      ip_conn_constructor(void *, void *, int);
 327  336  static void     ip_conn_destructor(void *, void *);
 328  337  
 329  338  static int      tcp_conn_constructor(void *, void *, int);
 330  339  static void     tcp_conn_destructor(void *, void *);
 331  340  
 332  341  static int      udp_conn_constructor(void *, void *, int);
 333  342  static void     udp_conn_destructor(void *, void *);
 334  343  
 335  344  static int      rawip_conn_constructor(void *, void *, int);
 336  345  static void     rawip_conn_destructor(void *, void *);
 337  346  
 338  347  static int      rts_conn_constructor(void *, void *, int);
 339  348  static void     rts_conn_destructor(void *, void *);
 340  349  
      350 +static int      dccp_conn_constructor(void *, void *, int);
      351 +static void     dccp_conn_destructor(void *, void *);
      352 +
 341  353  /*
 342  354   * Global (for all stack instances) init routine
 343  355   */
 344  356  void
 345  357  ipcl_g_init(void)
 346  358  {
 347  359          ip_conn_cache = kmem_cache_create("ip_conn_cache",
 348  360              sizeof (conn_t), CACHE_ALIGN_SIZE,
 349  361              ip_conn_constructor, ip_conn_destructor,
 350  362              NULL, NULL, NULL, 0);
↓ open down ↓ 10 lines elided ↑ open up ↑
 361  373  
 362  374          rawip_conn_cache = kmem_cache_create("rawip_conn_cache",
 363  375              sizeof (itc_t) + sizeof (icmp_t), CACHE_ALIGN_SIZE,
 364  376              rawip_conn_constructor, rawip_conn_destructor,
 365  377              NULL, NULL, NULL, 0);
 366  378  
 367  379          rts_conn_cache = kmem_cache_create("rts_conn_cache",
 368  380              sizeof (itc_t) + sizeof (rts_t), CACHE_ALIGN_SIZE,
 369  381              rts_conn_constructor, rts_conn_destructor,
 370  382              NULL, NULL, NULL, 0);
      383 +
      384 +        /* XXX:DCCP reclaim */
      385 +        dccp_conn_cache = kmem_cache_create("dccp_conn_cache",
      386 +            sizeof (itc_t) + sizeof (dccp_t), CACHE_ALIGN_SIZE,
      387 +            dccp_conn_constructor, dccp_conn_destructor,
      388 +            NULL, NULL, NULL, 0);
 371  389  }
 372  390  
 373  391  /*
 374  392   * ipclassifier intialization routine, sets up hash tables.
 375  393   */
 376  394  void
 377  395  ipcl_init(ip_stack_t *ipst)
 378  396  {
 379  397          int i;
 380  398          int sizes[] = P2Ps();
↓ open down ↓ 22 lines elided ↑ open up ↑
 403  421                          break;
 404  422                  }
 405  423          }
 406  424          if ((ipst->ips_ipcl_conn_fanout_size = sizes[i]) == 0) {
 407  425                  /* Out of range, use the 2^16 value */
 408  426                  ipst->ips_ipcl_conn_fanout_size = sizes[16];
 409  427          }
 410  428  
 411  429          /* Take values from /etc/system */
 412  430          ipst->ips_ipcl_bind_fanout_size = ipcl_bind_fanout_size;
      431 +        ipst->ips_ipcl_dccp_conn_fanout_size = ipcl_dccp_conn_fanout_size;
      432 +        ipst->ips_ipcl_dccp_bind_fanout_size = ipcl_dccp_bind_fanout_size;
 413  433          ipst->ips_ipcl_udp_fanout_size = ipcl_udp_fanout_size;
 414  434          ipst->ips_ipcl_raw_fanout_size = ipcl_raw_fanout_size;
 415  435          ipst->ips_ipcl_iptun_fanout_size = ipcl_iptun_fanout_size;
 416  436  
 417  437          ASSERT(ipst->ips_ipcl_conn_fanout == NULL);
 418  438  
 419  439          ipst->ips_ipcl_conn_fanout = kmem_zalloc(
 420  440              ipst->ips_ipcl_conn_fanout_size * sizeof (connf_t), KM_SLEEP);
 421  441  
 422  442          for (i = 0; i < ipst->ips_ipcl_conn_fanout_size; i++) {
↓ open down ↓ 47 lines elided ↑ open up ↑
 470  490                  mutex_init(&ipst->ips_ipcl_raw_fanout[i].connf_lock, NULL,
 471  491                      MUTEX_DEFAULT, NULL);
 472  492          }
 473  493  
 474  494          ipst->ips_ipcl_globalhash_fanout = kmem_zalloc(
 475  495              sizeof (connf_t) * CONN_G_HASH_SIZE, KM_SLEEP);
 476  496          for (i = 0; i < CONN_G_HASH_SIZE; i++) {
 477  497                  mutex_init(&ipst->ips_ipcl_globalhash_fanout[i].connf_lock,
 478  498                      NULL, MUTEX_DEFAULT, NULL);
 479  499          }
      500 +
      501 +        ipst->ips_ipcl_dccp_conn_fanout = kmem_zalloc(
      502 +            ipst->ips_ipcl_dccp_conn_fanout_size * sizeof (connf_t), KM_SLEEP);
      503 +        for (i = 0; i < ipst->ips_ipcl_dccp_conn_fanout_size; i++) {
      504 +                mutex_init(&ipst->ips_ipcl_dccp_conn_fanout[i].connf_lock, NULL,
      505 +                    MUTEX_DEFAULT, NULL);
      506 +        }
      507 +
      508 +        ipst->ips_ipcl_dccp_bind_fanout = kmem_zalloc(
      509 +            ipst->ips_ipcl_dccp_bind_fanout_size * sizeof (connf_t), KM_SLEEP);
      510 +        for (i = 0; i < ipst->ips_ipcl_dccp_bind_fanout_size; i++) {
      511 +                mutex_init(&ipst->ips_ipcl_dccp_bind_fanout[i].connf_lock, NULL,
      512 +                    MUTEX_DEFAULT, NULL);
      513 +        }
 480  514  }
 481  515  
 482  516  void
 483  517  ipcl_g_destroy(void)
 484  518  {
 485  519          kmem_cache_destroy(ip_conn_cache);
 486  520          kmem_cache_destroy(tcp_conn_cache);
 487  521          kmem_cache_destroy(udp_conn_cache);
 488  522          kmem_cache_destroy(rawip_conn_cache);
 489  523          kmem_cache_destroy(rts_conn_cache);
      524 +        kmem_cache_destroy(dccp_conn_cache);
 490  525  }
 491  526  
 492  527  /*
 493  528   * All user-level and kernel use of the stack must be gone
 494  529   * by now.
 495  530   */
 496  531  void
 497  532  ipcl_destroy(ip_stack_t *ipst)
 498  533  {
 499  534          int i;
↓ open down ↓ 55 lines elided ↑ open up ↑
 555  590          ipst->ips_ipcl_raw_fanout = NULL;
 556  591  
 557  592          for (i = 0; i < CONN_G_HASH_SIZE; i++) {
 558  593                  ASSERT(ipst->ips_ipcl_globalhash_fanout[i].connf_head == NULL);
 559  594                  mutex_destroy(&ipst->ips_ipcl_globalhash_fanout[i].connf_lock);
 560  595          }
 561  596          kmem_free(ipst->ips_ipcl_globalhash_fanout,
 562  597              sizeof (connf_t) * CONN_G_HASH_SIZE);
 563  598          ipst->ips_ipcl_globalhash_fanout = NULL;
 564  599  
      600 +        for (i = 0; i < ipst->ips_ipcl_dccp_conn_fanout_size; i++) {
      601 +                ASSERT(ipst->ips_ipcl_dccp_conn_fanout[i].connf_head == NULL);
      602 +                mutex_destroy(&ipst->ips_ipcl_dccp_conn_fanout[i].connf_lock);
      603 +        }
      604 +        kmem_free(ipst->ips_ipcl_dccp_conn_fanout,
      605 +            ipst->ips_ipcl_dccp_conn_fanout_size * sizeof (connf_t));
      606 +        ipst->ips_ipcl_dccp_conn_fanout = NULL;
      607 +
      608 +        for (i = 0; i < ipst->ips_ipcl_dccp_bind_fanout_size; i++) {
      609 +                ASSERT(ipst->ips_ipcl_dccp_bind_fanout[i].connf_head == NULL);
      610 +                mutex_destroy(&ipst->ips_ipcl_dccp_bind_fanout[i].connf_lock);
      611 +        }
      612 +        kmem_free(ipst->ips_ipcl_dccp_bind_fanout,
      613 +            ipst->ips_ipcl_dccp_bind_fanout_size * sizeof (connf_t));
      614 +        ipst->ips_ipcl_dccp_bind_fanout = NULL;
      615 +
 565  616          ASSERT(ipst->ips_rts_clients->connf_head == NULL);
 566  617          mutex_destroy(&ipst->ips_rts_clients->connf_lock);
 567  618          kmem_free(ipst->ips_rts_clients, sizeof (connf_t));
 568  619          ipst->ips_rts_clients = NULL;
 569  620  }
 570  621  
 571  622  /*
 572  623   * conn creation routine. initialize the conn, sets the reference
 573  624   * and inserts it in the global hash table.
 574  625   */
↓ open down ↓ 28 lines elided ↑ open up ↑
 603  654                  break;
 604  655  
 605  656          case IPCL_RTSCONN:
 606  657                  conn_cache = rts_conn_cache;
 607  658                  break;
 608  659  
 609  660          case IPCL_IPCCONN:
 610  661                  conn_cache = ip_conn_cache;
 611  662                  break;
 612  663  
      664 +        case IPCL_DCCPCONN:
      665 +                conn_cache = dccp_conn_cache;
      666 +                break;
      667 +
 613  668          default:
 614  669                  connp = NULL;
 615  670                  ASSERT(0);
 616  671          }
 617  672  
 618  673          if ((connp = kmem_cache_alloc(conn_cache, sleep)) == NULL)
 619  674                  return (NULL);
 620  675  
 621  676          connp->conn_ref = 1;
 622  677          netstack_hold(ns);
↓ open down ↓ 90 lines elided ↑ open up ↑
 713  768                  kmem_cache_free(tcp_conn_cache, connp);
 714  769                  return;
 715  770          }
 716  771  
 717  772          if (connp->conn_flags & IPCL_SCTPCONN) {
 718  773                  ASSERT(ns != NULL);
 719  774                  sctp_free(connp);
 720  775                  return;
 721  776          }
 722  777  
      778 +        if (connp->conn_flags & IPCL_DCCPCONN) {
      779 +                dccp_t  *dccp = connp->conn_dccp;
      780 +
      781 +                cmn_err(CE_NOTE, "ipclassifier: conn_flags DCCP cache_free");
      782 +
      783 +                dccp_free(dccp);
      784 +                mp = dccp->dccp_timercache;
      785 +
      786 +                dccp->dccp_dccps = NULL;
      787 +
      788 +                ipcl_conn_cleanup(connp);
      789 +                connp->conn_flags = IPCL_DCCPCONN;
      790 +                if (ns != NULL) {
      791 +                        ASSERT(dccp->dccps == NULL);
      792 +                        connp->conn_netstack = NULL;
      793 +                        connp->conn_ixa->ixa_ipst = NULL;
      794 +                        netstack_rele(ns);
      795 +                }
      796 +
      797 +                bzero(dccp, sizeof (dccp_t));
      798 +
      799 +                dccp->dccp_timercache = mp;
      800 +                dccp->dccp_connp = connp;
      801 +                kmem_cache_free(dccp_conn_cache, connp);
      802 +                return;
      803 +        }
      804 +
 723  805          ipcl_conn_cleanup(connp);
 724  806          if (ns != NULL) {
 725  807                  connp->conn_netstack = NULL;
 726  808                  connp->conn_ixa->ixa_ipst = NULL;
 727  809                  netstack_rele(ns);
 728  810          }
 729  811  
 730  812          /* leave conn_priv aka conn_udp, conn_icmp, etc in place. */
 731  813          if (connp->conn_flags & IPCL_UDPCONN) {
 732  814                  connp->conn_flags = IPCL_UDPCONN;
↓ open down ↓ 496 lines elided ↑ open up ↑
1229 1311                          (*cl_inet_listen)(
1230 1312                              connp->conn_netstack->netstack_stackid,
1231 1313                              IPPROTO_TCP, AF_INET,
1232 1314                              (uint8_t *)&connp->conn_bound_addr_v4, lport, NULL);
1233 1315                  }
1234 1316                  break;
1235 1317  
1236 1318          case IPPROTO_SCTP:
1237 1319                  ret = ipcl_sctp_hash_insert(connp, lport);
1238 1320                  break;
     1321 +
     1322 +        case IPPROTO_DCCP:
     1323 +                cmn_err(CE_NOTE, "ipclassifier.c: ipcl_bind_insert_v4");
     1324 +                ASSERT(connp->conn_zoneid != ALL_ZONES);
     1325 +                connfp = &ipst->ips_ipcl_dccp_bind_fanout[
     1326 +                    IPCL_DCCP_BIND_HASH(lport, ipst)];
     1327 +                if (connp->conn_laddr_v4 != INADDR_ANY) {
     1328 +                        IPCL_HASH_INSERT_BOUND(connfp, connp);
     1329 +                } else {
     1330 +                        IPCL_HASH_INSERT_WILDCARD(connfp, connp);
     1331 +                }
     1332 +                break;
1239 1333          }
1240 1334  
     1335 +
1241 1336          return (ret);
1242 1337  }
1243 1338  
1244 1339  int
1245 1340  ipcl_bind_insert_v6(conn_t *connp)
1246 1341  {
1247 1342          connf_t         *connfp;
1248 1343          int             ret = 0;
1249 1344          ip_stack_t      *ipst = connp->conn_netstack->netstack_ip;
1250 1345          uint16_t        lport = connp->conn_lport;
↓ open down ↓ 51 lines elided ↑ open up ↑
1302 1397                          connp->conn_flags |= IPCL_CL_LISTENER;
1303 1398                          (*cl_inet_listen)(
1304 1399                              connp->conn_netstack->netstack_stackid,
1305 1400                              IPPROTO_TCP, addr_family, laddrp, lport, NULL);
1306 1401                  }
1307 1402                  break;
1308 1403  
1309 1404          case IPPROTO_SCTP:
1310 1405                  ret = ipcl_sctp_hash_insert(connp, lport);
1311 1406                  break;
     1407 +
     1408 +        case IPPROTO_DCCP:
     1409 +                cmn_err(CE_NOTE, "ipclassifier.c: ipcl_bind_insert_v6");
     1410 +                ASSERT(connp->conn_zoneid != ALL_ZONES);
     1411 +                connfp = &ipst->ips_ipcl_dccp_bind_fanout[
     1412 +                    IPCL_DCCP_BIND_HASH(lport, ipst)];
     1413 +                if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6)) {
     1414 +                        IPCL_HASH_INSERT_BOUND(connfp, connp);
     1415 +                } else {
     1416 +                        IPCL_HASH_INSERT_WILDCARD(connfp, connp);
     1417 +                }
     1418 +                break;
1312 1419          }
1313 1420  
1314 1421          return (ret);
1315 1422  }
1316 1423  
1317 1424  /*
1318 1425   * ipcl_conn_hash insertion routines.
1319 1426   * The caller has already set conn_proto and the addresses/ports in the conn_t.
1320 1427   */
1321 1428  
↓ open down ↓ 64 lines elided ↑ open up ↑
1386 1493  
1387 1494          case IPPROTO_SCTP:
1388 1495                  /*
1389 1496                   * The raw socket may have already been bound, remove it
1390 1497                   * from the hash first.
1391 1498                   */
1392 1499                  IPCL_HASH_REMOVE(connp);
1393 1500                  ret = ipcl_sctp_hash_insert(connp, lport);
1394 1501                  break;
1395 1502  
     1503 +        case IPPROTO_DCCP:
     1504 +                cmn_err(CE_NOTE, "ipclassifier.c: ipcl_conn_insert_v4");
     1505 +                connfp = &ipst->ips_ipcl_dccp_conn_fanout[IPCL_DCCP_CONN_HASH(
     1506 +                    connp->conn_faddr_v4, connp->conn_ports, ipst)];
     1507 +                mutex_enter(&connfp->connf_lock);
     1508 +                for (tconnp = connfp->connf_head; tconnp != NULL;
     1509 +                    tconnp = tconnp->conn_next) {
     1510 +                        if (IPCL_CONN_MATCH(tconnp, connp->conn_proto,
     1511 +                            connp->conn_faddr_v4, connp->conn_laddr_v4,
     1512 +                            connp->conn_ports) &&
     1513 +                            IPCL_ZONE_MATCH(tconnp, connp->conn_zoneid)) {
     1514 +                                /* Already have a conn. bail out */
     1515 +                                mutex_exit(&connfp->connf_lock);
     1516 +                                return (EADDRINUSE);
     1517 +                        }
     1518 +                }
     1519 +
     1520 +                /* XXX:DCCP XTI/TLI application? */
     1521 +
     1522 +                ASSERT(connp->conn_recv != NULL);
     1523 +                ASSERT(connp->conn_recvicmp != NULL);
     1524 +
     1525 +                IPCL_HASH_INSERT_CONNECTED_LOCKED(connfp, connp);
     1526 +                mutex_exit(&connfp->connf_lock);
     1527 +                break;
     1528 +
1396 1529          default:
1397 1530                  /*
1398 1531                   * Check for conflicts among MAC exempt bindings.  For
1399 1532                   * transports with port numbers, this is done by the upper
1400 1533                   * level per-transport binding logic.  For all others, it's
1401 1534                   * done here.
1402 1535                   */
1403 1536                  if (is_system_labeled() &&
1404 1537                      check_exempt_conflict_v4(connp, ipst))
1405 1538                          return (EADDRINUSE);
↓ open down ↓ 75 lines elided ↑ open up ↑
1481 1614                  }
1482 1615                  IPCL_HASH_INSERT_CONNECTED_LOCKED(connfp, connp);
1483 1616                  mutex_exit(&connfp->connf_lock);
1484 1617                  break;
1485 1618  
1486 1619          case IPPROTO_SCTP:
1487 1620                  IPCL_HASH_REMOVE(connp);
1488 1621                  ret = ipcl_sctp_hash_insert(connp, lport);
1489 1622                  break;
1490 1623  
     1624 +        case IPPROTO_DCCP:
     1625 +                cmn_err(CE_NOTE, "ipclassifier.c: ipcl_conn_insert_v6");
     1626 +                connfp = &ipst->ips_ipcl_dccp_conn_fanout[
     1627 +                    IPCL_DCCP_CONN_HASH_V6(connp->conn_faddr_v6,
     1628 +                    connp->conn_ports, ipst)];
     1629 +                mutex_enter(&connfp->connf_lock);
     1630 +                for (tconnp = connfp->connf_head; tconnp != NULL;
     1631 +                    tconnp = tconnp->conn_next) {
     1632 +                        /* NOTE: need to match zoneid. Bug in onnv-gate */
     1633 +                        if (IPCL_CONN_MATCH_V6(tconnp, connp->conn_proto,
     1634 +                            connp->conn_faddr_v6, connp->conn_laddr_v6,
     1635 +                            connp->conn_ports) &&
     1636 +                            (tconnp->conn_bound_if == 0 ||
     1637 +                            tconnp->conn_bound_if == ifindex) &&
     1638 +                            IPCL_ZONE_MATCH(tconnp, connp->conn_zoneid)) {
     1639 +                                /* Already have a conn. bail out */
     1640 +                                mutex_exit(&connfp->connf_lock);
     1641 +                                return (EADDRINUSE);
     1642 +                        }
     1643 +                }
     1644 +
     1645 +                /* XXX:DCCP XTI/TLI? */
     1646 +                IPCL_HASH_INSERT_CONNECTED_LOCKED(connfp, connp);
     1647 +                mutex_exit(&connfp->connf_lock);
     1648 +                break;
     1649 +
1491 1650          default:
1492 1651                  if (is_system_labeled() &&
1493 1652                      check_exempt_conflict_v6(connp, ipst))
1494 1653                          return (EADDRINUSE);
1495 1654                  /* FALLTHROUGH */
1496 1655          case IPPROTO_UDP:
1497 1656                  if (protocol == IPPROTO_UDP) {
1498 1657                          connfp = &ipst->ips_ipcl_udp_fanout[
1499 1658                              IPCL_UDP_HASH(lport, ipst)];
1500 1659                  } else {
↓ open down ↓ 147 lines elided ↑ open up ↑
1648 1807                          return (connp);
1649 1808                  }
1650 1809  
1651 1810                  /*
1652 1811                   * We shouldn't come here for multicast/broadcast packets
1653 1812                   */
1654 1813                  mutex_exit(&connfp->connf_lock);
1655 1814  
1656 1815                  break;
1657 1816  
     1817 +        case IPPROTO_DCCP:
     1818 +                ports = *(uint32_t *)up;
     1819 +
     1820 +                /*
     1821 +                 * Search for fully-bound connection.
     1822 +                 */
     1823 +                connfp = &ipst->ips_ipcl_dccp_conn_fanout[IPCL_DCCP_CONN_HASH(
     1824 +                    ipha->ipha_src, ports, ipst)];
     1825 +                mutex_enter(&connfp->connf_lock);
     1826 +                for (connp = connfp->connf_head; connp != NULL;
     1827 +                    connp = connp->conn_next) {
     1828 +                        /* XXX:DCCP */
     1829 +                        if (IPCL_CONN_MATCH(connp, protocol,
     1830 +                            ipha->ipha_src, ipha->ipha_dst, ports)) {
     1831 +                                /* XXX */
     1832 +                                cmn_err(CE_NOTE, "ipclassifier.c: fully bound connection found");
     1833 +                                break;
     1834 +                        }
     1835 +                }
     1836 +
     1837 +                if (connp != NULL) {
     1838 +                        /*
     1839 +                         * We have a fully-bound DCCP connection.
     1840 +                         */
     1841 +                        CONN_INC_REF(connp);
     1842 +                        mutex_exit(&connfp->connf_lock);
     1843 +                        return (connp);
     1844 +                }
     1845 +
     1846 +                mutex_exit(&connfp->connf_lock);
     1847 +                lport = up[1];
     1848 +
     1849 +                /*
     1850 +                 * Fully-bound connection was not found, search for listener.
     1851 +                 */
     1852 +                bind_connfp = &ipst->ips_ipcl_dccp_bind_fanout[
     1853 +                    IPCL_DCCP_BIND_HASH(lport, ipst)];
     1854 +                mutex_enter(&bind_connfp->connf_lock);
     1855 +                for (connp = bind_connfp->connf_head; connp != NULL;
     1856 +                    connp = connp->conn_next) {
     1857 +                        if (IPCL_BIND_MATCH(connp, protocol, ipha->ipha_dst,
     1858 +                            lport) &&
     1859 +                            (connp->conn_zoneid == zoneid ||
     1860 +                            connp->conn_allzones ||
     1861 +                            ((connp->conn_mac_mode != CONN_MAC_DEFAULT) &&
     1862 +                            (ira->ira_flags & IRAF_TX_MAC_EXEMPTABLE) &&
     1863 +                            (ira->ira_flags & IRAF_TX_SHARED_ADDR))))
     1864 +                                break;
     1865 +                }
     1866 +
     1867 +                if (connp != NULL) {
     1868 +                        cmn_err(CE_NOTE, "ipclassifier.c: half-bound bind listener");
     1869 +                        /* Have a listener at least */
     1870 +                        CONN_INC_REF(connp);
     1871 +                        mutex_exit(&bind_connfp->connf_lock);
     1872 +                        return (connp);
     1873 +                }
     1874 +
     1875 +                mutex_exit(&bind_connfp->connf_lock);
     1876 +                break;
     1877 +
1658 1878          case IPPROTO_ENCAP:
1659 1879          case IPPROTO_IPV6:
1660 1880                  return (ipcl_iptun_classify_v4(&ipha->ipha_src,
1661 1881                      &ipha->ipha_dst, ipst));
1662 1882          }
1663 1883  
1664 1884          return (NULL);
1665 1885  }
1666 1886  
1667 1887  conn_t *
↓ open down ↓ 500 lines elided ↑ open up ↑
2168 2388  
2169 2389          /* Can be NULL if constructor failed */
2170 2390          if (connp->conn_ixa != NULL) {
2171 2391                  ASSERT(connp->conn_ixa->ixa_refcnt == 1);
2172 2392                  ASSERT(connp->conn_ixa->ixa_ire == NULL);
2173 2393                  ASSERT(connp->conn_ixa->ixa_nce == NULL);
2174 2394                  ixa_refrele(connp->conn_ixa);
2175 2395          }
2176 2396  }
2177 2397  
     2398 +/* ARGSUSED */
     2399 +static int
     2400 +dccp_conn_constructor(void *buf, void *cdrarg, int kmflags)
     2401 +{
     2402 +        itc_t   *itc = (itc_t *)buf;
     2403 +        conn_t  *connp = &itc->itc_conn;
     2404 +        dccp_t  *dccp = (dccp_t *)&itc[1];
     2405 +
     2406 +        bzero(connp, sizeof (conn_t));
     2407 +        bzero(dccp, sizeof (dccp_t));
     2408 +
     2409 +        mutex_init(&connp->conn_lock, NULL, MUTEX_DEFAULT, NULL);
     2410 +        cv_init(&connp->conn_cv, NULL, CV_DEFAULT, NULL);
     2411 +        rw_init(&connp->conn_ilg_lock, NULL, RW_DEFAULT, NULL);
     2412 +
     2413 +        dccp->dccp_timercache = dccp_timermp_alloc(kmflags);
     2414 +        if (dccp->dccp_timercache == NULL) {
     2415 +                return (ENOMEM);
     2416 +        }
     2417 +
     2418 +        connp->conn_dccp = dccp;
     2419 +        connp->conn_flags = IPCL_DCCPCONN;
     2420 +        connp->conn_proto = IPPROTO_DCCP;
     2421 +        dccp->dccp_connp = connp;
     2422 +
     2423 +        connp->conn_ixa = kmem_zalloc(sizeof (ip_xmit_attr_t), kmflags);
     2424 +        if (connp->conn_ixa == NULL) {
     2425 +                return (NULL);
     2426 +        }
     2427 +
     2428 +        connp->conn_ixa->ixa_refcnt = 1;
     2429 +        connp->conn_ixa->ixa_protocol = connp->conn_proto;
     2430 +        connp->conn_ixa->ixa_xmit_hint = CONN_TO_XMIT_HINT(connp);
     2431 +
     2432 +        return (0);
     2433 +}
     2434 +
     2435 +/* ARGSUSED */
     2436 +static void
     2437 +dccp_conn_destructor(void *buf, void *cdrarg)
     2438 +{
     2439 +        itc_t   *itc = (itc_t *)buf;
     2440 +        conn_t  *connp = &itc->itc_conn;
     2441 +        dccp_t  *dccp = (dccp_t *)&itc[1];
     2442 +
     2443 +        ASSERT(connp->conn_flags & IPCL_DCCPCONN);
     2444 +        ASSERT(dccp->dccp_connp == connp);
     2445 +        ASSERT(connp->conn_dccp == dccp);
     2446 +
     2447 +        dccp_timermp_free(dccp);
     2448 +
     2449 +        mutex_destroy(&connp->conn_lock);
     2450 +        cv_destroy(&connp->conn_cv);
     2451 +        rw_destroy(&connp->conn_ilg_lock);
     2452 +
     2453 +        if (connp->conn_ixa != NULL) {
     2454 +                ASSERT(connp->conn_ixa->ixa_refcnt == 1);
     2455 +                ASSERT(connp->conn_ixa->ixa_ire == NULL);
     2456 +                ASSERT(connp->conn_ixa->ixa_nce == NULL);
     2457 +
     2458 +                ixa_refrele(connp->conn_ixa);
     2459 +        }
     2460 +}
     2461 +
2178 2462  /*
2179 2463   * Called as part of ipcl_conn_destroy to assert and clear any pointers
2180 2464   * in the conn_t.
2181 2465   *
2182 2466   * Below we list all the pointers in the conn_t as a documentation aid.
2183 2467   * The ones that we can not ASSERT to be NULL are #ifdef'ed out.
2184 2468   * If you add any pointers to the conn_t please add an ASSERT here
2185 2469   * and #ifdef it out if it can't be actually asserted to be NULL.
2186 2470   * In any case, we bzero most of the conn_t at the end of the function.
2187 2471   */
↓ open down ↓ 359 lines elided ↑ open up ↑
2547 2831                          CONN_INC_REF(tconnp);
2548 2832                          mutex_exit(&connfp->connf_lock);
2549 2833                          return (tconnp);
2550 2834                  }
2551 2835          }
2552 2836          mutex_exit(&connfp->connf_lock);
2553 2837          return (NULL);
2554 2838  }
2555 2839  
2556 2840  /*
     2841 + * Same as ipcl_tcp_lookup_reversed_ipv4.
     2842 + */
     2843 +conn_t *
     2844 +ipcl_dccp_lookup_reversed_ipv4(ipha_t *ipha, dccpha_t *dccpha, int min_state,
     2845 +    ip_stack_t *ipst)
     2846 +{
     2847 +        conn_t          *tconnp;
     2848 +        connf_t         *connfp;
     2849 +        uint16_t        *pports;
     2850 +        uint32_t        ports;
     2851 +
     2852 +        pports = (uint16_t *)&ports;
     2853 +        pports[0] = dccpha->dha_fport;
     2854 +        pports[1] = dccpha->dha_lport;
     2855 +
     2856 +        connfp = &ipst->ips_ipcl_dccp_conn_fanout[IPCL_DCCP_CONN_HASH(
     2857 +            ipha->ipha_dst, ports, ipst)];
     2858 +
     2859 +        mutex_enter(&connfp->connf_lock);
     2860 +        for (tconnp = connfp->connf_head; tconnp != NULL;
     2861 +            tconnp = tconnp->conn_next) {
     2862 +                if (IPCL_CONN_MATCH(tconnp, IPPROTO_DCCP,
     2863 +                    ipha->ipha_dst, ipha->ipha_src, ports) &&
     2864 +                    tconnp->conn_dccp->dccp_state >= min_state) {
     2865 +                        CONN_INC_REF(tconnp);
     2866 +                        mutex_exit(&connfp->connf_lock);
     2867 +                        return (tconnp);
     2868 +                }
     2869 +        }
     2870 +        mutex_exit(&connfp->connf_lock);
     2871 +
     2872 +        return (NULL);
     2873 +}
     2874 +
     2875 +/*
     2876 + * Same as ipcl_tcp_lookup_reversed_ipv6.
     2877 + */
     2878 +conn_t *
     2879 +ipcl_dccp_lookup_reversed_ipv6(ip6_t *ip6h, dccpha_t *dccpha, int min_state,
     2880 +    uint_t ifindex, ip_stack_t *ipst)
     2881 +{
     2882 +        conn_t          *tconnp;
     2883 +        tcp_t           *tcp;
     2884 +        connf_t         *connfp;
     2885 +        uint32_t         ports;
     2886 +        uint16_t         *pports;
     2887 +
     2888 +        pports = (uint16_t *)&ports;
     2889 +        pports[0] = dccpha->dha_fport;
     2890 +        pports[1] = dccpha->dha_lport;
     2891 +/*
     2892 +        connfp = &ipst->ips_ipcl_conn_fanout[IPCL_CONN_HASH_V6(ip6h->ip6_dst,
     2893 +            ports, ipst)];
     2894 +
     2895 +        mutex_enter(&connfp->connf_lock);
     2896 +        for (tconnp = connfp->connf_head; tconnp != NULL;
     2897 +            tconnp = tconnp->conn_next) {
     2898 +
     2899 +                tcp = tconnp->conn_tcp;
     2900 +                if (IPCL_CONN_MATCH_V6(tconnp, IPPROTO_TCP,
     2901 +                    ip6h->ip6_dst, ip6h->ip6_src, ports) &&
     2902 +                    tcp->tcp_state >= min_state &&
     2903 +                    (tconnp->conn_bound_if == 0 ||
     2904 +                    tconnp->conn_bound_if == ifindex)) {
     2905 +
     2906 +                        CONN_INC_REF(tconnp);
     2907 +                        mutex_exit(&connfp->connf_lock);
     2908 +                        return (tconnp);
     2909 +                }
     2910 +        }
     2911 +        mutex_exit(&connfp->connf_lock);
     2912 +*/
     2913 +        return (NULL);
     2914 +}
     2915 +
     2916 +/*
2557 2917   * Finds a TCP/IPv4 listening connection; called by tcp_disconnect to locate
2558 2918   * a listener when changing state.
2559 2919   */
2560 2920  conn_t *
2561 2921  ipcl_lookup_listener_v4(uint16_t lport, ipaddr_t laddr, zoneid_t zoneid,
2562 2922      ip_stack_t *ipst)
2563 2923  {
2564 2924          connf_t         *bind_connfp;
2565 2925          conn_t          *connp;
2566 2926          tcp_t           *tcp;
↓ open down ↓ 158 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX