Print this page
dccp: conn_t


  50  * and when connection is processed via squeue (squeue processing may be
  51  * asynchronous and the reference protects the connection from being destroyed
  52  * before its processing is finished).
  53  *
  54  * conn_recv is used to pass up packets to the ULP.
  55  * For TCP conn_recv changes. It is tcp_input_listener_unbound initially for
  56  * a listener, and changes to tcp_input_listener as the listener has picked a
  57  * good squeue. For other cases it is set to tcp_input_data.
  58  *
  59  * conn_recvicmp is used to pass up ICMP errors to the ULP.
  60  *
  61  * Classifier uses several hash tables:
  62  *
  63  *      ipcl_conn_fanout:       contains all TCP connections in CONNECTED state
  64  *      ipcl_bind_fanout:       contains all connections in BOUND state
  65  *      ipcl_proto_fanout:      IPv4 protocol fanout
  66  *      ipcl_proto_fanout_v6:   IPv6 protocol fanout
  67  *      ipcl_udp_fanout:        contains all UDP connections
  68  *      ipcl_iptun_fanout:      contains all IP tunnel connections
  69  *      ipcl_globalhash_fanout: contains all connections


  70  *
  71  * The ipcl_globalhash_fanout is used for any walkers (like snmp and Clustering)
  72  * which need to view all existing connections.
  73  *
  74  * All tables are protected by per-bucket locks. When both per-bucket lock and
  75  * connection lock need to be held, the per-bucket lock should be acquired
  76  * first, followed by the connection lock.
  77  *
  78  * All functions doing search in one of these tables increment a reference
  79  * counter on the connection found (if any). This reference should be dropped
  80  * when the caller has finished processing the connection.
  81  *
  82  *
  83  * INTERFACES:
  84  * ===========
  85  *
  86  * Connection Lookup:
  87  * ------------------
  88  *
  89  * conn_t *ipcl_classify_v4(mp, protocol, hdr_len, ira, ip_stack)


 206  *
 207  * void ipcl_hash_remove(connp);
 208  *
 209  *      Removes the 'connp' from the connection fanout table.
 210  *
 211  * Connection Creation/Destruction
 212  * -------------------------------
 213  *
 214  * conn_t *ipcl_conn_create(type, sleep, netstack_t *)
 215  *
 216  *      Creates a new conn based on the type flag, inserts it into
 217  *      globalhash table.
 218  *
 219  *      type:   This flag determines the type of conn_t which needs to be
 220  *              created i.e., which kmem_cache it comes from.
 221  *              IPCL_TCPCONN    indicates a TCP connection
 222  *              IPCL_SCTPCONN   indicates a SCTP connection
 223  *              IPCL_UDPCONN    indicates a UDP conn_t.
 224  *              IPCL_RAWIPCONN  indicates a RAWIP/ICMP conn_t.
 225  *              IPCL_RTSCONN    indicates a RTS conn_t.

 226  *              IPCL_IPCCONN    indicates all other connections.
 227  *
 228  * void ipcl_conn_destroy(connp)
 229  *
 230  *      Destroys the connection state, removes it from the global
 231  *      connection hash table and frees its memory.
 232  */
 233 
 234 #include <sys/types.h>
 235 #include <sys/stream.h>
 236 #include <sys/stropts.h>
 237 #include <sys/sysmacros.h>
 238 #include <sys/strsubr.h>
 239 #include <sys/strsun.h>
 240 #define _SUN_TPI_VERSION 2
 241 #include <sys/ddi.h>
 242 #include <sys/cmn_err.h>
 243 #include <sys/debug.h>
 244 
 245 #include <sys/systm.h>
 246 #include <sys/param.h>
 247 #include <sys/kmem.h>
 248 #include <sys/isa_defs.h>
 249 #include <inet/common.h>
 250 #include <netinet/ip6.h>
 251 #include <netinet/icmp6.h>
 252 
 253 #include <inet/ip.h>
 254 #include <inet/ip_if.h>
 255 #include <inet/ip_ire.h>
 256 #include <inet/ip6.h>
 257 #include <inet/ip_ndp.h>
 258 #include <inet/ip_impl.h>
 259 #include <inet/udp_impl.h>

 260 #include <inet/sctp_ip.h>
 261 #include <inet/sctp/sctp_impl.h>
 262 #include <inet/rawip_impl.h>
 263 #include <inet/rts_impl.h>
 264 #include <inet/iptun/iptun_impl.h>
 265 
 266 #include <sys/cpuvar.h>
 267 
 268 #include <inet/ipclassifier.h>
 269 #include <inet/tcp.h>
 270 #include <inet/ipsec_impl.h>
 271 
 272 #include <sys/tsol/tnet.h>
 273 #include <sys/sockio.h>
 274 
 275 /* Old value for compatibility. Setable in /etc/system */
 276 uint_t tcp_conn_hash_size = 0;
 277 
 278 /* New value. Zero means choose automatically.  Setable in /etc/system */
 279 uint_t ipcl_conn_hash_size = 0;
 280 uint_t ipcl_conn_hash_memfactor = 8192;
 281 uint_t ipcl_conn_hash_maxsize = 82500;
 282 
 283 /* bind/udp fanout table size */
 284 uint_t ipcl_bind_fanout_size = 512;
 285 uint_t ipcl_udp_fanout_size = 16384;
 286 




 287 /* Raw socket fanout size.  Must be a power of 2. */
 288 uint_t ipcl_raw_fanout_size = 256;
 289 
 290 /*
 291  * The IPCL_IPTUN_HASH() function works best with a prime table size.  We
 292  * expect that most large deployments would have hundreds of tunnels, and
 293  * thousands in the extreme case.
 294  */
 295 uint_t ipcl_iptun_fanout_size = 6143;
 296 
 297 /*
 298  * Power of 2^N Primes useful for hashing for N of 0-28,
 299  * these primes are the nearest prime <= 2^N - 2^(N-2).
 300  */
 301 
 302 #define P2Ps() {0, 0, 0, 5, 11, 23, 47, 89, 191, 383, 761, 1531, 3067,  \
 303                 6143, 12281, 24571, 49139, 98299, 196597, 393209,       \
 304                 786431, 1572853, 3145721, 6291449, 12582893, 25165813,  \
 305                 50331599, 100663291, 201326557, 0}
 306 
 307 /*
 308  * wrapper structure to ensure that conn and what follows it (tcp_t, etc)
 309  * are aligned on cache lines.
 310  */
 311 typedef union itc_s {
 312         conn_t  itc_conn;
 313         char    itcu_filler[CACHE_ALIGN(conn_s)];
 314 } itc_t;
 315 
 316 struct kmem_cache  *tcp_conn_cache;
 317 struct kmem_cache  *ip_conn_cache;
 318 extern struct kmem_cache  *sctp_conn_cache;
 319 struct kmem_cache  *udp_conn_cache;
 320 struct kmem_cache  *rawip_conn_cache;
 321 struct kmem_cache  *rts_conn_cache;

 322 
 323 extern void     tcp_timermp_free(tcp_t *);
 324 extern mblk_t   *tcp_timermp_alloc(int);
 325 
 326 static int      ip_conn_constructor(void *, void *, int);
 327 static void     ip_conn_destructor(void *, void *);
 328 
 329 static int      tcp_conn_constructor(void *, void *, int);
 330 static void     tcp_conn_destructor(void *, void *);
 331 
 332 static int      udp_conn_constructor(void *, void *, int);
 333 static void     udp_conn_destructor(void *, void *);
 334 
 335 static int      rawip_conn_constructor(void *, void *, int);
 336 static void     rawip_conn_destructor(void *, void *);
 337 
 338 static int      rts_conn_constructor(void *, void *, int);
 339 static void     rts_conn_destructor(void *, void *);
 340 



 341 /*
 342  * Global (for all stack instances) init routine
 343  */
 344 void
 345 ipcl_g_init(void)
 346 {
 347         ip_conn_cache = kmem_cache_create("ip_conn_cache",
 348             sizeof (conn_t), CACHE_ALIGN_SIZE,
 349             ip_conn_constructor, ip_conn_destructor,
 350             NULL, NULL, NULL, 0);
 351 
 352         tcp_conn_cache = kmem_cache_create("tcp_conn_cache",
 353             sizeof (itc_t) + sizeof (tcp_t), CACHE_ALIGN_SIZE,
 354             tcp_conn_constructor, tcp_conn_destructor,
 355             tcp_conn_reclaim, NULL, NULL, 0);
 356 
 357         udp_conn_cache = kmem_cache_create("udp_conn_cache",
 358             sizeof (itc_t) + sizeof (udp_t), CACHE_ALIGN_SIZE,
 359             udp_conn_constructor, udp_conn_destructor,
 360             NULL, NULL, NULL, 0);
 361 
 362         rawip_conn_cache = kmem_cache_create("rawip_conn_cache",
 363             sizeof (itc_t) + sizeof (icmp_t), CACHE_ALIGN_SIZE,
 364             rawip_conn_constructor, rawip_conn_destructor,
 365             NULL, NULL, NULL, 0);
 366 
 367         rts_conn_cache = kmem_cache_create("rts_conn_cache",
 368             sizeof (itc_t) + sizeof (rts_t), CACHE_ALIGN_SIZE,
 369             rts_conn_constructor, rts_conn_destructor,
 370             NULL, NULL, NULL, 0);






 371 }
 372 
 373 /*
 374  * ipclassifier intialization routine, sets up hash tables.
 375  */
 376 void
 377 ipcl_init(ip_stack_t *ipst)
 378 {
 379         int i;
 380         int sizes[] = P2Ps();
 381 
 382         /*
 383          * Calculate size of conn fanout table from /etc/system settings
 384          */
 385         if (ipcl_conn_hash_size != 0) {
 386                 ipst->ips_ipcl_conn_fanout_size = ipcl_conn_hash_size;
 387         } else if (tcp_conn_hash_size != 0) {
 388                 ipst->ips_ipcl_conn_fanout_size = tcp_conn_hash_size;
 389         } else {
 390                 extern pgcnt_t freemem;


 393                     (freemem * PAGESIZE) / ipcl_conn_hash_memfactor;
 394 
 395                 if (ipst->ips_ipcl_conn_fanout_size > ipcl_conn_hash_maxsize) {
 396                         ipst->ips_ipcl_conn_fanout_size =
 397                             ipcl_conn_hash_maxsize;
 398                 }
 399         }
 400 
 401         for (i = 9; i < sizeof (sizes) / sizeof (*sizes) - 1; i++) {
 402                 if (sizes[i] >= ipst->ips_ipcl_conn_fanout_size) {
 403                         break;
 404                 }
 405         }
 406         if ((ipst->ips_ipcl_conn_fanout_size = sizes[i]) == 0) {
 407                 /* Out of range, use the 2^16 value */
 408                 ipst->ips_ipcl_conn_fanout_size = sizes[16];
 409         }
 410 
 411         /* Take values from /etc/system */
 412         ipst->ips_ipcl_bind_fanout_size = ipcl_bind_fanout_size;


 413         ipst->ips_ipcl_udp_fanout_size = ipcl_udp_fanout_size;
 414         ipst->ips_ipcl_raw_fanout_size = ipcl_raw_fanout_size;
 415         ipst->ips_ipcl_iptun_fanout_size = ipcl_iptun_fanout_size;
 416 
 417         ASSERT(ipst->ips_ipcl_conn_fanout == NULL);
 418 
 419         ipst->ips_ipcl_conn_fanout = kmem_zalloc(
 420             ipst->ips_ipcl_conn_fanout_size * sizeof (connf_t), KM_SLEEP);
 421 
 422         for (i = 0; i < ipst->ips_ipcl_conn_fanout_size; i++) {
 423                 mutex_init(&ipst->ips_ipcl_conn_fanout[i].connf_lock, NULL,
 424                     MUTEX_DEFAULT, NULL);
 425         }
 426 
 427         ipst->ips_ipcl_bind_fanout = kmem_zalloc(
 428             ipst->ips_ipcl_bind_fanout_size * sizeof (connf_t), KM_SLEEP);
 429 
 430         for (i = 0; i < ipst->ips_ipcl_bind_fanout_size; i++) {
 431                 mutex_init(&ipst->ips_ipcl_bind_fanout[i].connf_lock, NULL,
 432                     MUTEX_DEFAULT, NULL);


 460         ipst->ips_ipcl_iptun_fanout = kmem_zalloc(
 461             ipst->ips_ipcl_iptun_fanout_size * sizeof (connf_t), KM_SLEEP);
 462         for (i = 0; i < ipst->ips_ipcl_iptun_fanout_size; i++) {
 463                 mutex_init(&ipst->ips_ipcl_iptun_fanout[i].connf_lock, NULL,
 464                     MUTEX_DEFAULT, NULL);
 465         }
 466 
 467         ipst->ips_ipcl_raw_fanout = kmem_zalloc(
 468             ipst->ips_ipcl_raw_fanout_size * sizeof (connf_t), KM_SLEEP);
 469         for (i = 0; i < ipst->ips_ipcl_raw_fanout_size; i++) {
 470                 mutex_init(&ipst->ips_ipcl_raw_fanout[i].connf_lock, NULL,
 471                     MUTEX_DEFAULT, NULL);
 472         }
 473 
 474         ipst->ips_ipcl_globalhash_fanout = kmem_zalloc(
 475             sizeof (connf_t) * CONN_G_HASH_SIZE, KM_SLEEP);
 476         for (i = 0; i < CONN_G_HASH_SIZE; i++) {
 477                 mutex_init(&ipst->ips_ipcl_globalhash_fanout[i].connf_lock,
 478                     NULL, MUTEX_DEFAULT, NULL);
 479         }














 480 }
 481 
 482 void
 483 ipcl_g_destroy(void)
 484 {
 485         kmem_cache_destroy(ip_conn_cache);
 486         kmem_cache_destroy(tcp_conn_cache);
 487         kmem_cache_destroy(udp_conn_cache);
 488         kmem_cache_destroy(rawip_conn_cache);
 489         kmem_cache_destroy(rts_conn_cache);

 490 }
 491 
 492 /*
 493  * All user-level and kernel use of the stack must be gone
 494  * by now.
 495  */
 496 void
 497 ipcl_destroy(ip_stack_t *ipst)
 498 {
 499         int i;
 500 
 501         for (i = 0; i < ipst->ips_ipcl_conn_fanout_size; i++) {
 502                 ASSERT(ipst->ips_ipcl_conn_fanout[i].connf_head == NULL);
 503                 mutex_destroy(&ipst->ips_ipcl_conn_fanout[i].connf_lock);
 504         }
 505         kmem_free(ipst->ips_ipcl_conn_fanout, ipst->ips_ipcl_conn_fanout_size *
 506             sizeof (connf_t));
 507         ipst->ips_ipcl_conn_fanout = NULL;
 508 
 509         for (i = 0; i < ipst->ips_ipcl_bind_fanout_size; i++) {


 545         kmem_free(ipst->ips_ipcl_iptun_fanout,
 546             ipst->ips_ipcl_iptun_fanout_size * sizeof (connf_t));
 547         ipst->ips_ipcl_iptun_fanout = NULL;
 548 
 549         for (i = 0; i < ipst->ips_ipcl_raw_fanout_size; i++) {
 550                 ASSERT(ipst->ips_ipcl_raw_fanout[i].connf_head == NULL);
 551                 mutex_destroy(&ipst->ips_ipcl_raw_fanout[i].connf_lock);
 552         }
 553         kmem_free(ipst->ips_ipcl_raw_fanout, ipst->ips_ipcl_raw_fanout_size *
 554             sizeof (connf_t));
 555         ipst->ips_ipcl_raw_fanout = NULL;
 556 
 557         for (i = 0; i < CONN_G_HASH_SIZE; i++) {
 558                 ASSERT(ipst->ips_ipcl_globalhash_fanout[i].connf_head == NULL);
 559                 mutex_destroy(&ipst->ips_ipcl_globalhash_fanout[i].connf_lock);
 560         }
 561         kmem_free(ipst->ips_ipcl_globalhash_fanout,
 562             sizeof (connf_t) * CONN_G_HASH_SIZE);
 563         ipst->ips_ipcl_globalhash_fanout = NULL;
 564 
















 565         ASSERT(ipst->ips_rts_clients->connf_head == NULL);
 566         mutex_destroy(&ipst->ips_rts_clients->connf_lock);
 567         kmem_free(ipst->ips_rts_clients, sizeof (connf_t));
 568         ipst->ips_rts_clients = NULL;
 569 }
 570 
 571 /*
 572  * conn creation routine. initialize the conn, sets the reference
 573  * and inserts it in the global hash table.
 574  */
 575 conn_t *
 576 ipcl_conn_create(uint32_t type, int sleep, netstack_t *ns)
 577 {
 578         conn_t  *connp;
 579         struct kmem_cache *conn_cache;
 580 
 581         switch (type) {
 582         case IPCL_SCTPCONN:
 583                 if ((connp = kmem_cache_alloc(sctp_conn_cache, sleep)) == NULL)
 584                         return (NULL);


 593         case IPCL_TCPCONN:
 594                 conn_cache = tcp_conn_cache;
 595                 break;
 596 
 597         case IPCL_UDPCONN:
 598                 conn_cache = udp_conn_cache;
 599                 break;
 600 
 601         case IPCL_RAWIPCONN:
 602                 conn_cache = rawip_conn_cache;
 603                 break;
 604 
 605         case IPCL_RTSCONN:
 606                 conn_cache = rts_conn_cache;
 607                 break;
 608 
 609         case IPCL_IPCCONN:
 610                 conn_cache = ip_conn_cache;
 611                 break;
 612 




 613         default:
 614                 connp = NULL;
 615                 ASSERT(0);
 616         }
 617 
 618         if ((connp = kmem_cache_alloc(conn_cache, sleep)) == NULL)
 619                 return (NULL);
 620 
 621         connp->conn_ref = 1;
 622         netstack_hold(ns);
 623         connp->conn_netstack = ns;
 624         connp->conn_ixa->ixa_ipst = ns->netstack_ip;
 625         connp->conn_ixa->ixa_conn_id = (long)connp;
 626         ipcl_globalhash_insert(connp);
 627         return (connp);
 628 }
 629 
 630 void
 631 ipcl_conn_destroy(conn_t *connp)
 632 {


 703                         ASSERT(tcp->tcp_tcps == NULL);
 704                         connp->conn_netstack = NULL;
 705                         connp->conn_ixa->ixa_ipst = NULL;
 706                         netstack_rele(ns);
 707                 }
 708 
 709                 bzero(tcp, sizeof (tcp_t));
 710 
 711                 tcp->tcp_timercache = mp;
 712                 tcp->tcp_connp = connp;
 713                 kmem_cache_free(tcp_conn_cache, connp);
 714                 return;
 715         }
 716 
 717         if (connp->conn_flags & IPCL_SCTPCONN) {
 718                 ASSERT(ns != NULL);
 719                 sctp_free(connp);
 720                 return;
 721         }
 722 



























 723         ipcl_conn_cleanup(connp);
 724         if (ns != NULL) {
 725                 connp->conn_netstack = NULL;
 726                 connp->conn_ixa->ixa_ipst = NULL;
 727                 netstack_rele(ns);
 728         }
 729 
 730         /* leave conn_priv aka conn_udp, conn_icmp, etc in place. */
 731         if (connp->conn_flags & IPCL_UDPCONN) {
 732                 connp->conn_flags = IPCL_UDPCONN;
 733                 kmem_cache_free(udp_conn_cache, connp);
 734         } else if (connp->conn_flags & IPCL_RAWIPCONN) {
 735                 connp->conn_flags = IPCL_RAWIPCONN;
 736                 connp->conn_proto = IPPROTO_ICMP;
 737                 connp->conn_ixa->ixa_protocol = connp->conn_proto;
 738                 kmem_cache_free(rawip_conn_cache, connp);
 739         } else if (connp->conn_flags & IPCL_RTSCONN) {
 740                 connp->conn_flags = IPCL_RTSCONN;
 741                 kmem_cache_free(rts_conn_cache, connp);
 742         } else {


1219                 connfp = &ipst->ips_ipcl_bind_fanout[
1220                     IPCL_BIND_HASH(lport, ipst)];
1221                 if (connp->conn_laddr_v4 != INADDR_ANY) {
1222                         IPCL_HASH_INSERT_BOUND(connfp, connp);
1223                 } else {
1224                         IPCL_HASH_INSERT_WILDCARD(connfp, connp);
1225                 }
1226                 if (cl_inet_listen != NULL) {
1227                         ASSERT(connp->conn_ipversion == IPV4_VERSION);
1228                         connp->conn_flags |= IPCL_CL_LISTENER;
1229                         (*cl_inet_listen)(
1230                             connp->conn_netstack->netstack_stackid,
1231                             IPPROTO_TCP, AF_INET,
1232                             (uint8_t *)&connp->conn_bound_addr_v4, lport, NULL);
1233                 }
1234                 break;
1235 
1236         case IPPROTO_SCTP:
1237                 ret = ipcl_sctp_hash_insert(connp, lport);
1238                 break;












1239         }
1240 

1241         return (ret);
1242 }
1243 
1244 int
1245 ipcl_bind_insert_v6(conn_t *connp)
1246 {
1247         connf_t         *connfp;
1248         int             ret = 0;
1249         ip_stack_t      *ipst = connp->conn_netstack->netstack_ip;
1250         uint16_t        lport = connp->conn_lport;
1251         uint8_t         protocol = connp->conn_proto;
1252 
1253         if (IPCL_IS_IPTUN(connp)) {
1254                 return (ipcl_iptun_hash_insert_v6(connp, ipst));
1255         }
1256 
1257         switch (protocol) {
1258         default:
1259                 if (is_system_labeled() &&
1260                     check_exempt_conflict_v6(connp, ipst))


1292                         uint8_t         *laddrp;
1293 
1294                         if (connp->conn_ipversion == IPV6_VERSION) {
1295                                 addr_family = AF_INET6;
1296                                 laddrp =
1297                                     (uint8_t *)&connp->conn_bound_addr_v6;
1298                         } else {
1299                                 addr_family = AF_INET;
1300                                 laddrp = (uint8_t *)&connp->conn_bound_addr_v4;
1301                         }
1302                         connp->conn_flags |= IPCL_CL_LISTENER;
1303                         (*cl_inet_listen)(
1304                             connp->conn_netstack->netstack_stackid,
1305                             IPPROTO_TCP, addr_family, laddrp, lport, NULL);
1306                 }
1307                 break;
1308 
1309         case IPPROTO_SCTP:
1310                 ret = ipcl_sctp_hash_insert(connp, lport);
1311                 break;












1312         }
1313 
1314         return (ret);
1315 }
1316 
1317 /*
1318  * ipcl_conn_hash insertion routines.
1319  * The caller has already set conn_proto and the addresses/ports in the conn_t.
1320  */
1321 
1322 int
1323 ipcl_conn_insert(conn_t *connp)
1324 {
1325         if (connp->conn_ipversion == IPV6_VERSION)
1326                 return (ipcl_conn_insert_v6(connp));
1327         else
1328                 return (ipcl_conn_insert_v4(connp));
1329 }
1330 
1331 int


1376                         IPCL_HASH_REMOVE(connp);
1377                         mutex_enter(&connfp->connf_lock);
1378                 }
1379 
1380                 ASSERT(connp->conn_recv != NULL);
1381                 ASSERT(connp->conn_recvicmp != NULL);
1382 
1383                 IPCL_HASH_INSERT_CONNECTED_LOCKED(connfp, connp);
1384                 mutex_exit(&connfp->connf_lock);
1385                 break;
1386 
1387         case IPPROTO_SCTP:
1388                 /*
1389                  * The raw socket may have already been bound, remove it
1390                  * from the hash first.
1391                  */
1392                 IPCL_HASH_REMOVE(connp);
1393                 ret = ipcl_sctp_hash_insert(connp, lport);
1394                 break;
1395 


























1396         default:
1397                 /*
1398                  * Check for conflicts among MAC exempt bindings.  For
1399                  * transports with port numbers, this is done by the upper
1400                  * level per-transport binding logic.  For all others, it's
1401                  * done here.
1402                  */
1403                 if (is_system_labeled() &&
1404                     check_exempt_conflict_v4(connp, ipst))
1405                         return (EADDRINUSE);
1406                 /* FALLTHROUGH */
1407 
1408         case IPPROTO_UDP:
1409                 if (protocol == IPPROTO_UDP) {
1410                         connfp = &ipst->ips_ipcl_udp_fanout[
1411                             IPCL_UDP_HASH(lport, ipst)];
1412                 } else {
1413                         connfp = &ipst->ips_ipcl_proto_fanout_v4[protocol];
1414                 }
1415 


1471                         }
1472                 }
1473                 if (connp->conn_fanout != NULL) {
1474                         /*
1475                          * Probably a XTI/TLI application trying to do a
1476                          * rebind. Let it happen.
1477                          */
1478                         mutex_exit(&connfp->connf_lock);
1479                         IPCL_HASH_REMOVE(connp);
1480                         mutex_enter(&connfp->connf_lock);
1481                 }
1482                 IPCL_HASH_INSERT_CONNECTED_LOCKED(connfp, connp);
1483                 mutex_exit(&connfp->connf_lock);
1484                 break;
1485 
1486         case IPPROTO_SCTP:
1487                 IPCL_HASH_REMOVE(connp);
1488                 ret = ipcl_sctp_hash_insert(connp, lport);
1489                 break;
1490 


























1491         default:
1492                 if (is_system_labeled() &&
1493                     check_exempt_conflict_v6(connp, ipst))
1494                         return (EADDRINUSE);
1495                 /* FALLTHROUGH */
1496         case IPPROTO_UDP:
1497                 if (protocol == IPPROTO_UDP) {
1498                         connfp = &ipst->ips_ipcl_udp_fanout[
1499                             IPCL_UDP_HASH(lport, ipst)];
1500                 } else {
1501                         connfp = &ipst->ips_ipcl_proto_fanout_v6[protocol];
1502                 }
1503 
1504                 if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6)) {
1505                         IPCL_HASH_INSERT_CONNECTED(connfp, connp);
1506                 } else if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6)) {
1507                         IPCL_HASH_INSERT_BOUND(connfp, connp);
1508                 } else {
1509                         IPCL_HASH_INSERT_WILDCARD(connfp, connp);
1510                 }


1638                     ira, connp)) {
1639                         DTRACE_PROBE3(tx__ip__log__info__classify__udp,
1640                             char *, "connp(1) could not receive mp(2)",
1641                             conn_t *, connp, mblk_t *, mp);
1642                         connp = NULL;
1643                 }
1644 
1645                 if (connp != NULL) {
1646                         CONN_INC_REF(connp);
1647                         mutex_exit(&connfp->connf_lock);
1648                         return (connp);
1649                 }
1650 
1651                 /*
1652                  * We shouldn't come here for multicast/broadcast packets
1653                  */
1654                 mutex_exit(&connfp->connf_lock);
1655 
1656                 break;
1657 





























































1658         case IPPROTO_ENCAP:
1659         case IPPROTO_IPV6:
1660                 return (ipcl_iptun_classify_v4(&ipha->ipha_src,
1661                     &ipha->ipha_dst, ipst));
1662         }
1663 
1664         return (NULL);
1665 }
1666 
1667 conn_t *
1668 ipcl_classify_v6(mblk_t *mp, uint8_t protocol, uint_t hdr_len,
1669     ip_recv_attr_t *ira, ip_stack_t *ipst)
1670 {
1671         ip6_t           *ip6h;
1672         connf_t         *connfp, *bind_connfp;
1673         uint16_t        lport;
1674         uint16_t        fport;
1675         tcpha_t         *tcpha;
1676         uint32_t        ports;
1677         conn_t          *connp;


2158         itc_t   *itc = (itc_t *)buf;
2159         conn_t  *connp = &itc->itc_conn;
2160         rts_t   *rts = (rts_t *)&itc[1];
2161 
2162         ASSERT(connp->conn_flags & IPCL_RTSCONN);
2163         ASSERT(rts->rts_connp == connp);
2164         ASSERT(connp->conn_rts == rts);
2165         mutex_destroy(&connp->conn_lock);
2166         cv_destroy(&connp->conn_cv);
2167         rw_destroy(&connp->conn_ilg_lock);
2168 
2169         /* Can be NULL if constructor failed */
2170         if (connp->conn_ixa != NULL) {
2171                 ASSERT(connp->conn_ixa->ixa_refcnt == 1);
2172                 ASSERT(connp->conn_ixa->ixa_ire == NULL);
2173                 ASSERT(connp->conn_ixa->ixa_nce == NULL);
2174                 ixa_refrele(connp->conn_ixa);
2175         }
2176 }
2177 
































































2178 /*
2179  * Called as part of ipcl_conn_destroy to assert and clear any pointers
2180  * in the conn_t.
2181  *
2182  * Below we list all the pointers in the conn_t as a documentation aid.
2183  * The ones that we can not ASSERT to be NULL are #ifdef'ed out.
2184  * If you add any pointers to the conn_t please add an ASSERT here
2185  * and #ifdef it out if it can't be actually asserted to be NULL.
2186  * In any case, we bzero most of the conn_t at the end of the function.
2187  */
2188 void
2189 ipcl_conn_cleanup(conn_t *connp)
2190 {
2191         ip_xmit_attr_t  *ixa;
2192 
2193         ASSERT(connp->conn_latch == NULL);
2194         ASSERT(connp->conn_latch_in_policy == NULL);
2195         ASSERT(connp->conn_latch_in_action == NULL);
2196 #ifdef notdef
2197         ASSERT(connp->conn_rq == NULL);


2537         for (tconnp = connfp->connf_head; tconnp != NULL;
2538             tconnp = tconnp->conn_next) {
2539 
2540                 tcp = tconnp->conn_tcp;
2541                 if (IPCL_CONN_MATCH_V6(tconnp, IPPROTO_TCP,
2542                     ip6h->ip6_dst, ip6h->ip6_src, ports) &&
2543                     tcp->tcp_state >= min_state &&
2544                     (tconnp->conn_bound_if == 0 ||
2545                     tconnp->conn_bound_if == ifindex)) {
2546 
2547                         CONN_INC_REF(tconnp);
2548                         mutex_exit(&connfp->connf_lock);
2549                         return (tconnp);
2550                 }
2551         }
2552         mutex_exit(&connfp->connf_lock);
2553         return (NULL);
2554 }
2555 
2556 /*












































































2557  * Finds a TCP/IPv4 listening connection; called by tcp_disconnect to locate
2558  * a listener when changing state.
2559  */
2560 conn_t *
2561 ipcl_lookup_listener_v4(uint16_t lport, ipaddr_t laddr, zoneid_t zoneid,
2562     ip_stack_t *ipst)
2563 {
2564         connf_t         *bind_connfp;
2565         conn_t          *connp;
2566         tcp_t           *tcp;
2567 
2568         /*
2569          * Avoid false matches for packets sent to an IP destination of
2570          * all zeros.
2571          */
2572         if (laddr == 0)
2573                 return (NULL);
2574 
2575         ASSERT(zoneid != ALL_ZONES);
2576 




  50  * and when connection is processed via squeue (squeue processing may be
  51  * asynchronous and the reference protects the connection from being destroyed
  52  * before its processing is finished).
  53  *
  54  * conn_recv is used to pass up packets to the ULP.
  55  * For TCP conn_recv changes. It is tcp_input_listener_unbound initially for
  56  * a listener, and changes to tcp_input_listener as the listener has picked a
  57  * good squeue. For other cases it is set to tcp_input_data.
  58  *
  59  * conn_recvicmp is used to pass up ICMP errors to the ULP.
  60  *
  61  * Classifier uses several hash tables:
  62  *
  63  *      ipcl_conn_fanout:       contains all TCP connections in CONNECTED state
  64  *      ipcl_bind_fanout:       contains all connections in BOUND state
  65  *      ipcl_proto_fanout:      IPv4 protocol fanout
  66  *      ipcl_proto_fanout_v6:   IPv6 protocol fanout
  67  *      ipcl_udp_fanout:        contains all UDP connections
  68  *      ipcl_iptun_fanout:      contains all IP tunnel connections
  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
  72  *
  73  * The ipcl_globalhash_fanout is used for any walkers (like snmp and Clustering)
  74  * which need to view all existing connections.
  75  *
  76  * All tables are protected by per-bucket locks. When both per-bucket lock and
  77  * connection lock need to be held, the per-bucket lock should be acquired
  78  * first, followed by the connection lock.
  79  *
  80  * All functions doing search in one of these tables increment a reference
  81  * counter on the connection found (if any). This reference should be dropped
  82  * when the caller has finished processing the connection.
  83  *
  84  *
  85  * INTERFACES:
  86  * ===========
  87  *
  88  * Connection Lookup:
  89  * ------------------
  90  *
  91  * conn_t *ipcl_classify_v4(mp, protocol, hdr_len, ira, ip_stack)


 208  *
 209  * void ipcl_hash_remove(connp);
 210  *
 211  *      Removes the 'connp' from the connection fanout table.
 212  *
 213  * Connection Creation/Destruction
 214  * -------------------------------
 215  *
 216  * conn_t *ipcl_conn_create(type, sleep, netstack_t *)
 217  *
 218  *      Creates a new conn based on the type flag, inserts it into
 219  *      globalhash table.
 220  *
 221  *      type:   This flag determines the type of conn_t which needs to be
 222  *              created i.e., which kmem_cache it comes from.
 223  *              IPCL_TCPCONN    indicates a TCP connection
 224  *              IPCL_SCTPCONN   indicates a SCTP connection
 225  *              IPCL_UDPCONN    indicates a UDP conn_t.
 226  *              IPCL_RAWIPCONN  indicates a RAWIP/ICMP conn_t.
 227  *              IPCL_RTSCONN    indicates a RTS conn_t.
 228  *              IPCL_DCCPCONN   indicates a DCCP conn_t.
 229  *              IPCL_IPCCONN    indicates all other connections.
 230  *
 231  * void ipcl_conn_destroy(connp)
 232  *
 233  *      Destroys the connection state, removes it from the global
 234  *      connection hash table and frees its memory.
 235  */
 236 
 237 #include <sys/types.h>
 238 #include <sys/stream.h>
 239 #include <sys/stropts.h>
 240 #include <sys/sysmacros.h>
 241 #include <sys/strsubr.h>
 242 #include <sys/strsun.h>
 243 #define _SUN_TPI_VERSION 2
 244 #include <sys/ddi.h>
 245 #include <sys/cmn_err.h>
 246 #include <sys/debug.h>
 247 
 248 #include <sys/systm.h>
 249 #include <sys/param.h>
 250 #include <sys/kmem.h>
 251 #include <sys/isa_defs.h>
 252 #include <inet/common.h>
 253 #include <netinet/ip6.h>
 254 #include <netinet/icmp6.h>
 255 
 256 #include <inet/ip.h>
 257 #include <inet/ip_if.h>
 258 #include <inet/ip_ire.h>
 259 #include <inet/ip6.h>
 260 #include <inet/ip_ndp.h>
 261 #include <inet/ip_impl.h>
 262 #include <inet/udp_impl.h>
 263 #include <inet/dccp_impl.h>
 264 #include <inet/sctp_ip.h>
 265 #include <inet/sctp/sctp_impl.h>
 266 #include <inet/rawip_impl.h>
 267 #include <inet/rts_impl.h>
 268 #include <inet/iptun/iptun_impl.h>
 269 
 270 #include <sys/cpuvar.h>
 271 
 272 #include <inet/ipclassifier.h>
 273 #include <inet/tcp.h>
 274 #include <inet/ipsec_impl.h>
 275 
 276 #include <sys/tsol/tnet.h>
 277 #include <sys/sockio.h>
 278 
 279 /* Old value for compatibility. Setable in /etc/system */
 280 uint_t tcp_conn_hash_size = 0;
 281 
 282 /* New value. Zero means choose automatically.  Setable in /etc/system */
 283 uint_t ipcl_conn_hash_size = 0;
 284 uint_t ipcl_conn_hash_memfactor = 8192;
 285 uint_t ipcl_conn_hash_maxsize = 82500;
 286 
 287 /* bind/udp fanout table size */
 288 uint_t ipcl_bind_fanout_size = 512;
 289 uint_t ipcl_udp_fanout_size = 16384;
 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 
 295 /* Raw socket fanout size.  Must be a power of 2. */
 296 uint_t ipcl_raw_fanout_size = 256;
 297 
 298 /*
 299  * The IPCL_IPTUN_HASH() function works best with a prime table size.  We
 300  * expect that most large deployments would have hundreds of tunnels, and
 301  * thousands in the extreme case.
 302  */
 303 uint_t ipcl_iptun_fanout_size = 6143;
 304 
 305 /*
 306  * Power of 2^N Primes useful for hashing for N of 0-28,
 307  * these primes are the nearest prime <= 2^N - 2^(N-2).
 308  */
 309 
 310 #define P2Ps() {0, 0, 0, 5, 11, 23, 47, 89, 191, 383, 761, 1531, 3067,  \
 311                 6143, 12281, 24571, 49139, 98299, 196597, 393209,       \
 312                 786431, 1572853, 3145721, 6291449, 12582893, 25165813,  \
 313                 50331599, 100663291, 201326557, 0}
 314 
 315 /*
 316  * wrapper structure to ensure that conn and what follows it (tcp_t, etc)
 317  * are aligned on cache lines.
 318  */
 319 typedef union itc_s {
 320         conn_t  itc_conn;
 321         char    itcu_filler[CACHE_ALIGN(conn_s)];
 322 } itc_t;
 323 
 324 struct kmem_cache  *tcp_conn_cache;
 325 struct kmem_cache  *ip_conn_cache;
 326 extern struct kmem_cache  *sctp_conn_cache;
 327 struct kmem_cache  *udp_conn_cache;
 328 struct kmem_cache  *rawip_conn_cache;
 329 struct kmem_cache  *rts_conn_cache;
 330 struct kmem_cache  *dccp_conn_cache;
 331 
 332 extern void     tcp_timermp_free(tcp_t *);
 333 extern mblk_t   *tcp_timermp_alloc(int);
 334 
 335 static int      ip_conn_constructor(void *, void *, int);
 336 static void     ip_conn_destructor(void *, void *);
 337 
 338 static int      tcp_conn_constructor(void *, void *, int);
 339 static void     tcp_conn_destructor(void *, void *);
 340 
 341 static int      udp_conn_constructor(void *, void *, int);
 342 static void     udp_conn_destructor(void *, void *);
 343 
 344 static int      rawip_conn_constructor(void *, void *, int);
 345 static void     rawip_conn_destructor(void *, void *);
 346 
 347 static int      rts_conn_constructor(void *, void *, int);
 348 static void     rts_conn_destructor(void *, void *);
 349 
 350 static int      dccp_conn_constructor(void *, void *, int);
 351 static void     dccp_conn_destructor(void *, void *);
 352 
 353 /*
 354  * Global (for all stack instances) init routine
 355  */
 356 void
 357 ipcl_g_init(void)
 358 {
 359         ip_conn_cache = kmem_cache_create("ip_conn_cache",
 360             sizeof (conn_t), CACHE_ALIGN_SIZE,
 361             ip_conn_constructor, ip_conn_destructor,
 362             NULL, NULL, NULL, 0);
 363 
 364         tcp_conn_cache = kmem_cache_create("tcp_conn_cache",
 365             sizeof (itc_t) + sizeof (tcp_t), CACHE_ALIGN_SIZE,
 366             tcp_conn_constructor, tcp_conn_destructor,
 367             tcp_conn_reclaim, NULL, NULL, 0);
 368 
 369         udp_conn_cache = kmem_cache_create("udp_conn_cache",
 370             sizeof (itc_t) + sizeof (udp_t), CACHE_ALIGN_SIZE,
 371             udp_conn_constructor, udp_conn_destructor,
 372             NULL, NULL, NULL, 0);
 373 
 374         rawip_conn_cache = kmem_cache_create("rawip_conn_cache",
 375             sizeof (itc_t) + sizeof (icmp_t), CACHE_ALIGN_SIZE,
 376             rawip_conn_constructor, rawip_conn_destructor,
 377             NULL, NULL, NULL, 0);
 378 
 379         rts_conn_cache = kmem_cache_create("rts_conn_cache",
 380             sizeof (itc_t) + sizeof (rts_t), CACHE_ALIGN_SIZE,
 381             rts_conn_constructor, rts_conn_destructor,
 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);
 389 }
 390 
 391 /*
 392  * ipclassifier intialization routine, sets up hash tables.
 393  */
 394 void
 395 ipcl_init(ip_stack_t *ipst)
 396 {
 397         int i;
 398         int sizes[] = P2Ps();
 399 
 400         /*
 401          * Calculate size of conn fanout table from /etc/system settings
 402          */
 403         if (ipcl_conn_hash_size != 0) {
 404                 ipst->ips_ipcl_conn_fanout_size = ipcl_conn_hash_size;
 405         } else if (tcp_conn_hash_size != 0) {
 406                 ipst->ips_ipcl_conn_fanout_size = tcp_conn_hash_size;
 407         } else {
 408                 extern pgcnt_t freemem;


 411                     (freemem * PAGESIZE) / ipcl_conn_hash_memfactor;
 412 
 413                 if (ipst->ips_ipcl_conn_fanout_size > ipcl_conn_hash_maxsize) {
 414                         ipst->ips_ipcl_conn_fanout_size =
 415                             ipcl_conn_hash_maxsize;
 416                 }
 417         }
 418 
 419         for (i = 9; i < sizeof (sizes) / sizeof (*sizes) - 1; i++) {
 420                 if (sizes[i] >= ipst->ips_ipcl_conn_fanout_size) {
 421                         break;
 422                 }
 423         }
 424         if ((ipst->ips_ipcl_conn_fanout_size = sizes[i]) == 0) {
 425                 /* Out of range, use the 2^16 value */
 426                 ipst->ips_ipcl_conn_fanout_size = sizes[16];
 427         }
 428 
 429         /* Take values from /etc/system */
 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;
 433         ipst->ips_ipcl_udp_fanout_size = ipcl_udp_fanout_size;
 434         ipst->ips_ipcl_raw_fanout_size = ipcl_raw_fanout_size;
 435         ipst->ips_ipcl_iptun_fanout_size = ipcl_iptun_fanout_size;
 436 
 437         ASSERT(ipst->ips_ipcl_conn_fanout == NULL);
 438 
 439         ipst->ips_ipcl_conn_fanout = kmem_zalloc(
 440             ipst->ips_ipcl_conn_fanout_size * sizeof (connf_t), KM_SLEEP);
 441 
 442         for (i = 0; i < ipst->ips_ipcl_conn_fanout_size; i++) {
 443                 mutex_init(&ipst->ips_ipcl_conn_fanout[i].connf_lock, NULL,
 444                     MUTEX_DEFAULT, NULL);
 445         }
 446 
 447         ipst->ips_ipcl_bind_fanout = kmem_zalloc(
 448             ipst->ips_ipcl_bind_fanout_size * sizeof (connf_t), KM_SLEEP);
 449 
 450         for (i = 0; i < ipst->ips_ipcl_bind_fanout_size; i++) {
 451                 mutex_init(&ipst->ips_ipcl_bind_fanout[i].connf_lock, NULL,
 452                     MUTEX_DEFAULT, NULL);


 480         ipst->ips_ipcl_iptun_fanout = kmem_zalloc(
 481             ipst->ips_ipcl_iptun_fanout_size * sizeof (connf_t), KM_SLEEP);
 482         for (i = 0; i < ipst->ips_ipcl_iptun_fanout_size; i++) {
 483                 mutex_init(&ipst->ips_ipcl_iptun_fanout[i].connf_lock, NULL,
 484                     MUTEX_DEFAULT, NULL);
 485         }
 486 
 487         ipst->ips_ipcl_raw_fanout = kmem_zalloc(
 488             ipst->ips_ipcl_raw_fanout_size * sizeof (connf_t), KM_SLEEP);
 489         for (i = 0; i < ipst->ips_ipcl_raw_fanout_size; i++) {
 490                 mutex_init(&ipst->ips_ipcl_raw_fanout[i].connf_lock, NULL,
 491                     MUTEX_DEFAULT, NULL);
 492         }
 493 
 494         ipst->ips_ipcl_globalhash_fanout = kmem_zalloc(
 495             sizeof (connf_t) * CONN_G_HASH_SIZE, KM_SLEEP);
 496         for (i = 0; i < CONN_G_HASH_SIZE; i++) {
 497                 mutex_init(&ipst->ips_ipcl_globalhash_fanout[i].connf_lock,
 498                     NULL, MUTEX_DEFAULT, NULL);
 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         }
 514 }
 515 
 516 void
 517 ipcl_g_destroy(void)
 518 {
 519         kmem_cache_destroy(ip_conn_cache);
 520         kmem_cache_destroy(tcp_conn_cache);
 521         kmem_cache_destroy(udp_conn_cache);
 522         kmem_cache_destroy(rawip_conn_cache);
 523         kmem_cache_destroy(rts_conn_cache);
 524         kmem_cache_destroy(dccp_conn_cache);
 525 }
 526 
 527 /*
 528  * All user-level and kernel use of the stack must be gone
 529  * by now.
 530  */
 531 void
 532 ipcl_destroy(ip_stack_t *ipst)
 533 {
 534         int i;
 535 
 536         for (i = 0; i < ipst->ips_ipcl_conn_fanout_size; i++) {
 537                 ASSERT(ipst->ips_ipcl_conn_fanout[i].connf_head == NULL);
 538                 mutex_destroy(&ipst->ips_ipcl_conn_fanout[i].connf_lock);
 539         }
 540         kmem_free(ipst->ips_ipcl_conn_fanout, ipst->ips_ipcl_conn_fanout_size *
 541             sizeof (connf_t));
 542         ipst->ips_ipcl_conn_fanout = NULL;
 543 
 544         for (i = 0; i < ipst->ips_ipcl_bind_fanout_size; i++) {


 580         kmem_free(ipst->ips_ipcl_iptun_fanout,
 581             ipst->ips_ipcl_iptun_fanout_size * sizeof (connf_t));
 582         ipst->ips_ipcl_iptun_fanout = NULL;
 583 
 584         for (i = 0; i < ipst->ips_ipcl_raw_fanout_size; i++) {
 585                 ASSERT(ipst->ips_ipcl_raw_fanout[i].connf_head == NULL);
 586                 mutex_destroy(&ipst->ips_ipcl_raw_fanout[i].connf_lock);
 587         }
 588         kmem_free(ipst->ips_ipcl_raw_fanout, ipst->ips_ipcl_raw_fanout_size *
 589             sizeof (connf_t));
 590         ipst->ips_ipcl_raw_fanout = NULL;
 591 
 592         for (i = 0; i < CONN_G_HASH_SIZE; i++) {
 593                 ASSERT(ipst->ips_ipcl_globalhash_fanout[i].connf_head == NULL);
 594                 mutex_destroy(&ipst->ips_ipcl_globalhash_fanout[i].connf_lock);
 595         }
 596         kmem_free(ipst->ips_ipcl_globalhash_fanout,
 597             sizeof (connf_t) * CONN_G_HASH_SIZE);
 598         ipst->ips_ipcl_globalhash_fanout = NULL;
 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 
 616         ASSERT(ipst->ips_rts_clients->connf_head == NULL);
 617         mutex_destroy(&ipst->ips_rts_clients->connf_lock);
 618         kmem_free(ipst->ips_rts_clients, sizeof (connf_t));
 619         ipst->ips_rts_clients = NULL;
 620 }
 621 
 622 /*
 623  * conn creation routine. initialize the conn, sets the reference
 624  * and inserts it in the global hash table.
 625  */
 626 conn_t *
 627 ipcl_conn_create(uint32_t type, int sleep, netstack_t *ns)
 628 {
 629         conn_t  *connp;
 630         struct kmem_cache *conn_cache;
 631 
 632         switch (type) {
 633         case IPCL_SCTPCONN:
 634                 if ((connp = kmem_cache_alloc(sctp_conn_cache, sleep)) == NULL)
 635                         return (NULL);


 644         case IPCL_TCPCONN:
 645                 conn_cache = tcp_conn_cache;
 646                 break;
 647 
 648         case IPCL_UDPCONN:
 649                 conn_cache = udp_conn_cache;
 650                 break;
 651 
 652         case IPCL_RAWIPCONN:
 653                 conn_cache = rawip_conn_cache;
 654                 break;
 655 
 656         case IPCL_RTSCONN:
 657                 conn_cache = rts_conn_cache;
 658                 break;
 659 
 660         case IPCL_IPCCONN:
 661                 conn_cache = ip_conn_cache;
 662                 break;
 663 
 664         case IPCL_DCCPCONN:
 665                 conn_cache = dccp_conn_cache;
 666                 break;
 667 
 668         default:
 669                 connp = NULL;
 670                 ASSERT(0);
 671         }
 672 
 673         if ((connp = kmem_cache_alloc(conn_cache, sleep)) == NULL)
 674                 return (NULL);
 675 
 676         connp->conn_ref = 1;
 677         netstack_hold(ns);
 678         connp->conn_netstack = ns;
 679         connp->conn_ixa->ixa_ipst = ns->netstack_ip;
 680         connp->conn_ixa->ixa_conn_id = (long)connp;
 681         ipcl_globalhash_insert(connp);
 682         return (connp);
 683 }
 684 
 685 void
 686 ipcl_conn_destroy(conn_t *connp)
 687 {


 758                         ASSERT(tcp->tcp_tcps == NULL);
 759                         connp->conn_netstack = NULL;
 760                         connp->conn_ixa->ixa_ipst = NULL;
 761                         netstack_rele(ns);
 762                 }
 763 
 764                 bzero(tcp, sizeof (tcp_t));
 765 
 766                 tcp->tcp_timercache = mp;
 767                 tcp->tcp_connp = connp;
 768                 kmem_cache_free(tcp_conn_cache, connp);
 769                 return;
 770         }
 771 
 772         if (connp->conn_flags & IPCL_SCTPCONN) {
 773                 ASSERT(ns != NULL);
 774                 sctp_free(connp);
 775                 return;
 776         }
 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 
 805         ipcl_conn_cleanup(connp);
 806         if (ns != NULL) {
 807                 connp->conn_netstack = NULL;
 808                 connp->conn_ixa->ixa_ipst = NULL;
 809                 netstack_rele(ns);
 810         }
 811 
 812         /* leave conn_priv aka conn_udp, conn_icmp, etc in place. */
 813         if (connp->conn_flags & IPCL_UDPCONN) {
 814                 connp->conn_flags = IPCL_UDPCONN;
 815                 kmem_cache_free(udp_conn_cache, connp);
 816         } else if (connp->conn_flags & IPCL_RAWIPCONN) {
 817                 connp->conn_flags = IPCL_RAWIPCONN;
 818                 connp->conn_proto = IPPROTO_ICMP;
 819                 connp->conn_ixa->ixa_protocol = connp->conn_proto;
 820                 kmem_cache_free(rawip_conn_cache, connp);
 821         } else if (connp->conn_flags & IPCL_RTSCONN) {
 822                 connp->conn_flags = IPCL_RTSCONN;
 823                 kmem_cache_free(rts_conn_cache, connp);
 824         } else {


1301                 connfp = &ipst->ips_ipcl_bind_fanout[
1302                     IPCL_BIND_HASH(lport, ipst)];
1303                 if (connp->conn_laddr_v4 != INADDR_ANY) {
1304                         IPCL_HASH_INSERT_BOUND(connfp, connp);
1305                 } else {
1306                         IPCL_HASH_INSERT_WILDCARD(connfp, connp);
1307                 }
1308                 if (cl_inet_listen != NULL) {
1309                         ASSERT(connp->conn_ipversion == IPV4_VERSION);
1310                         connp->conn_flags |= IPCL_CL_LISTENER;
1311                         (*cl_inet_listen)(
1312                             connp->conn_netstack->netstack_stackid,
1313                             IPPROTO_TCP, AF_INET,
1314                             (uint8_t *)&connp->conn_bound_addr_v4, lport, NULL);
1315                 }
1316                 break;
1317 
1318         case IPPROTO_SCTP:
1319                 ret = ipcl_sctp_hash_insert(connp, lport);
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;
1333         }
1334 
1335 
1336         return (ret);
1337 }
1338 
1339 int
1340 ipcl_bind_insert_v6(conn_t *connp)
1341 {
1342         connf_t         *connfp;
1343         int             ret = 0;
1344         ip_stack_t      *ipst = connp->conn_netstack->netstack_ip;
1345         uint16_t        lport = connp->conn_lport;
1346         uint8_t         protocol = connp->conn_proto;
1347 
1348         if (IPCL_IS_IPTUN(connp)) {
1349                 return (ipcl_iptun_hash_insert_v6(connp, ipst));
1350         }
1351 
1352         switch (protocol) {
1353         default:
1354                 if (is_system_labeled() &&
1355                     check_exempt_conflict_v6(connp, ipst))


1387                         uint8_t         *laddrp;
1388 
1389                         if (connp->conn_ipversion == IPV6_VERSION) {
1390                                 addr_family = AF_INET6;
1391                                 laddrp =
1392                                     (uint8_t *)&connp->conn_bound_addr_v6;
1393                         } else {
1394                                 addr_family = AF_INET;
1395                                 laddrp = (uint8_t *)&connp->conn_bound_addr_v4;
1396                         }
1397                         connp->conn_flags |= IPCL_CL_LISTENER;
1398                         (*cl_inet_listen)(
1399                             connp->conn_netstack->netstack_stackid,
1400                             IPPROTO_TCP, addr_family, laddrp, lport, NULL);
1401                 }
1402                 break;
1403 
1404         case IPPROTO_SCTP:
1405                 ret = ipcl_sctp_hash_insert(connp, lport);
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;
1419         }
1420 
1421         return (ret);
1422 }
1423 
1424 /*
1425  * ipcl_conn_hash insertion routines.
1426  * The caller has already set conn_proto and the addresses/ports in the conn_t.
1427  */
1428 
1429 int
1430 ipcl_conn_insert(conn_t *connp)
1431 {
1432         if (connp->conn_ipversion == IPV6_VERSION)
1433                 return (ipcl_conn_insert_v6(connp));
1434         else
1435                 return (ipcl_conn_insert_v4(connp));
1436 }
1437 
1438 int


1483                         IPCL_HASH_REMOVE(connp);
1484                         mutex_enter(&connfp->connf_lock);
1485                 }
1486 
1487                 ASSERT(connp->conn_recv != NULL);
1488                 ASSERT(connp->conn_recvicmp != NULL);
1489 
1490                 IPCL_HASH_INSERT_CONNECTED_LOCKED(connfp, connp);
1491                 mutex_exit(&connfp->connf_lock);
1492                 break;
1493 
1494         case IPPROTO_SCTP:
1495                 /*
1496                  * The raw socket may have already been bound, remove it
1497                  * from the hash first.
1498                  */
1499                 IPCL_HASH_REMOVE(connp);
1500                 ret = ipcl_sctp_hash_insert(connp, lport);
1501                 break;
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 
1529         default:
1530                 /*
1531                  * Check for conflicts among MAC exempt bindings.  For
1532                  * transports with port numbers, this is done by the upper
1533                  * level per-transport binding logic.  For all others, it's
1534                  * done here.
1535                  */
1536                 if (is_system_labeled() &&
1537                     check_exempt_conflict_v4(connp, ipst))
1538                         return (EADDRINUSE);
1539                 /* FALLTHROUGH */
1540 
1541         case IPPROTO_UDP:
1542                 if (protocol == IPPROTO_UDP) {
1543                         connfp = &ipst->ips_ipcl_udp_fanout[
1544                             IPCL_UDP_HASH(lport, ipst)];
1545                 } else {
1546                         connfp = &ipst->ips_ipcl_proto_fanout_v4[protocol];
1547                 }
1548 


1604                         }
1605                 }
1606                 if (connp->conn_fanout != NULL) {
1607                         /*
1608                          * Probably a XTI/TLI application trying to do a
1609                          * rebind. Let it happen.
1610                          */
1611                         mutex_exit(&connfp->connf_lock);
1612                         IPCL_HASH_REMOVE(connp);
1613                         mutex_enter(&connfp->connf_lock);
1614                 }
1615                 IPCL_HASH_INSERT_CONNECTED_LOCKED(connfp, connp);
1616                 mutex_exit(&connfp->connf_lock);
1617                 break;
1618 
1619         case IPPROTO_SCTP:
1620                 IPCL_HASH_REMOVE(connp);
1621                 ret = ipcl_sctp_hash_insert(connp, lport);
1622                 break;
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 
1650         default:
1651                 if (is_system_labeled() &&
1652                     check_exempt_conflict_v6(connp, ipst))
1653                         return (EADDRINUSE);
1654                 /* FALLTHROUGH */
1655         case IPPROTO_UDP:
1656                 if (protocol == IPPROTO_UDP) {
1657                         connfp = &ipst->ips_ipcl_udp_fanout[
1658                             IPCL_UDP_HASH(lport, ipst)];
1659                 } else {
1660                         connfp = &ipst->ips_ipcl_proto_fanout_v6[protocol];
1661                 }
1662 
1663                 if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6)) {
1664                         IPCL_HASH_INSERT_CONNECTED(connfp, connp);
1665                 } else if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6)) {
1666                         IPCL_HASH_INSERT_BOUND(connfp, connp);
1667                 } else {
1668                         IPCL_HASH_INSERT_WILDCARD(connfp, connp);
1669                 }


1797                     ira, connp)) {
1798                         DTRACE_PROBE3(tx__ip__log__info__classify__udp,
1799                             char *, "connp(1) could not receive mp(2)",
1800                             conn_t *, connp, mblk_t *, mp);
1801                         connp = NULL;
1802                 }
1803 
1804                 if (connp != NULL) {
1805                         CONN_INC_REF(connp);
1806                         mutex_exit(&connfp->connf_lock);
1807                         return (connp);
1808                 }
1809 
1810                 /*
1811                  * We shouldn't come here for multicast/broadcast packets
1812                  */
1813                 mutex_exit(&connfp->connf_lock);
1814 
1815                 break;
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 
1878         case IPPROTO_ENCAP:
1879         case IPPROTO_IPV6:
1880                 return (ipcl_iptun_classify_v4(&ipha->ipha_src,
1881                     &ipha->ipha_dst, ipst));
1882         }
1883 
1884         return (NULL);
1885 }
1886 
1887 conn_t *
1888 ipcl_classify_v6(mblk_t *mp, uint8_t protocol, uint_t hdr_len,
1889     ip_recv_attr_t *ira, ip_stack_t *ipst)
1890 {
1891         ip6_t           *ip6h;
1892         connf_t         *connfp, *bind_connfp;
1893         uint16_t        lport;
1894         uint16_t        fport;
1895         tcpha_t         *tcpha;
1896         uint32_t        ports;
1897         conn_t          *connp;


2378         itc_t   *itc = (itc_t *)buf;
2379         conn_t  *connp = &itc->itc_conn;
2380         rts_t   *rts = (rts_t *)&itc[1];
2381 
2382         ASSERT(connp->conn_flags & IPCL_RTSCONN);
2383         ASSERT(rts->rts_connp == connp);
2384         ASSERT(connp->conn_rts == rts);
2385         mutex_destroy(&connp->conn_lock);
2386         cv_destroy(&connp->conn_cv);
2387         rw_destroy(&connp->conn_ilg_lock);
2388 
2389         /* Can be NULL if constructor failed */
2390         if (connp->conn_ixa != NULL) {
2391                 ASSERT(connp->conn_ixa->ixa_refcnt == 1);
2392                 ASSERT(connp->conn_ixa->ixa_ire == NULL);
2393                 ASSERT(connp->conn_ixa->ixa_nce == NULL);
2394                 ixa_refrele(connp->conn_ixa);
2395         }
2396 }
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 
2462 /*
2463  * Called as part of ipcl_conn_destroy to assert and clear any pointers
2464  * in the conn_t.
2465  *
2466  * Below we list all the pointers in the conn_t as a documentation aid.
2467  * The ones that we can not ASSERT to be NULL are #ifdef'ed out.
2468  * If you add any pointers to the conn_t please add an ASSERT here
2469  * and #ifdef it out if it can't be actually asserted to be NULL.
2470  * In any case, we bzero most of the conn_t at the end of the function.
2471  */
2472 void
2473 ipcl_conn_cleanup(conn_t *connp)
2474 {
2475         ip_xmit_attr_t  *ixa;
2476 
2477         ASSERT(connp->conn_latch == NULL);
2478         ASSERT(connp->conn_latch_in_policy == NULL);
2479         ASSERT(connp->conn_latch_in_action == NULL);
2480 #ifdef notdef
2481         ASSERT(connp->conn_rq == NULL);


2821         for (tconnp = connfp->connf_head; tconnp != NULL;
2822             tconnp = tconnp->conn_next) {
2823 
2824                 tcp = tconnp->conn_tcp;
2825                 if (IPCL_CONN_MATCH_V6(tconnp, IPPROTO_TCP,
2826                     ip6h->ip6_dst, ip6h->ip6_src, ports) &&
2827                     tcp->tcp_state >= min_state &&
2828                     (tconnp->conn_bound_if == 0 ||
2829                     tconnp->conn_bound_if == ifindex)) {
2830 
2831                         CONN_INC_REF(tconnp);
2832                         mutex_exit(&connfp->connf_lock);
2833                         return (tconnp);
2834                 }
2835         }
2836         mutex_exit(&connfp->connf_lock);
2837         return (NULL);
2838 }
2839 
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 /*
2917  * Finds a TCP/IPv4 listening connection; called by tcp_disconnect to locate
2918  * a listener when changing state.
2919  */
2920 conn_t *
2921 ipcl_lookup_listener_v4(uint16_t lport, ipaddr_t laddr, zoneid_t zoneid,
2922     ip_stack_t *ipst)
2923 {
2924         connf_t         *bind_connfp;
2925         conn_t          *connp;
2926         tcp_t           *tcp;
2927 
2928         /*
2929          * Avoid false matches for packets sent to an IP destination of
2930          * all zeros.
2931          */
2932         if (laddr == 0)
2933                 return (NULL);
2934 
2935         ASSERT(zoneid != ALL_ZONES);
2936