1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Copyright 2012 David Hoeppner. All rights reserved. 29 */ 30 31 /* 32 * This file implements the Data Congestion Control Protocol (DCCP). 33 */ 34 35 #include <sys/types.h> 36 #include <sys/stream.h> 37 #include <sys/stropts.h> 38 #include <sys/strlog.h> 39 #include <sys/strsun.h> 40 #define _SUN_TPI_VERSION 2 41 #include <sys/tihdr.h> 42 #include <sys/socket.h> 43 #include <sys/socketvar.h> 44 #include <sys/sockio.h> 45 #include <sys/priv.h> 46 #include <sys/vtrace.h> 47 #include <sys/sdt.h> 48 #include <sys/debug.h> 49 #include <sys/ddi.h> 50 #include <sys/isa_defs.h> 51 #include <sys/policy.h> 52 #include <sys/tsol/label.h> 53 #include <sys/tsol/tnet.h> 54 55 #include <inet/common.h> 56 #include <inet/ip.h> 57 #include <inet/ip_impl.h> 58 #include <inet/ip6.h> 59 #include <inet/dccp.h> 60 #include <inet/dccp_impl.h> 61 #include <inet/dccp_stack.h> 62 #include <inet/kstatcom.h> 63 #include <inet/snmpcom.h> 64 65 #include <sys/cmn_err.h> 66 67 int dccp_squeue_flag; 68 69 /* Setable in /etc/system */ 70 uint_t dccp_bind_fanout_size = DCCP_BIND_FANOUT_SIZE; 71 72 static void dccp_notify(void *, ip_xmit_attr_t *, ixa_notify_type_t, 73 ixa_notify_arg_t); 74 75 /* Functions to register netstack */ 76 static void *dccp_stack_init(netstackid_t, netstack_t *); 77 static void dccp_stack_fini(netstackid_t, void *); 78 79 /* Stream device open functions */ 80 static int dccp_openv4(queue_t *, dev_t *, int, int, cred_t *); 81 static int dccp_openv6(queue_t *, dev_t *, int, int, cred_t *); 82 static int dccp_open(queue_t *, dev_t *, int, int, cred_t *, 83 boolean_t); 84 85 /* Write service routine */ 86 static void dccp_wsrv(queue_t *); 87 88 /* Connection related functions */ 89 static int dccp_connect_ipv4(dccp_t *, ipaddr_t *, in_port_t, uint_t); 90 static int dccp_connect_ipv6(dccp_t *, in6_addr_t *, in_port_t, uint32_t, 91 uint_t, uint32_t); 92 93 /* Initialise ISS */ 94 static void dccp_iss_init(dccp_t *); 95 static void dccp_reinit(dccp_t *); 96 97 struct module_info dccp_rinfo = { 98 DCCP_MOD_ID, DCCP_MOD_NAME, 0, INFPSZ, DCCP_RECV_HIWATER, 99 DCCP_RECV_LOWATER 100 }; 101 102 static struct module_info dccp_winfo = { 103 DCCP_MOD_ID, DCCP_MOD_NAME, 0, INFPSZ, 127, 16 104 }; 105 106 /* 107 * Queue information structure with DCCP entry points. 108 */ 109 struct qinit dccp_rinitv4 = { 110 NULL, (pfi_t)dccp_rsrv, dccp_openv4, dccp_tpi_close, NULL, &dccp_rinfo 111 }; 112 113 struct qinit dccp_rinitv6 = { 114 NULL, (pfi_t)dccp_rsrv, dccp_openv6, dccp_tpi_close, NULL, &dccp_rinfo 115 }; 116 117 struct qinit dccp_winit = { 118 (pfi_t)dccp_wput, (pfi_t)dccp_wsrv, NULL, NULL, NULL, &dccp_winfo 119 }; 120 121 /* Initial entry point for TCP in socket mode */ 122 struct qinit dccp_sock_winit = { 123 (pfi_t)dccp_wput_sock, (pfi_t)dccp_wsrv, NULL, NULL, NULL, &dccp_winfo 124 }; 125 126 struct qinit dccp_fallback_sock_winit = { 127 (pfi_t)dccp_wput_fallback, NULL, NULL, NULL, NULL, &dccp_winfo 128 }; 129 /* 130 * DCCP as acceptor STREAM. 131 */ 132 struct qinit dccp_acceptor_rinit = { 133 NULL, (pfi_t)dccp_rsrv, NULL, dccp_tpi_close_accept, NULL, &dccp_winfo 134 }; 135 136 struct qinit dccp_acceptor_winit = { 137 (pfi_t)dccp_tpi_accept, NULL, NULL, NULL, NULL, &dccp_winfo 138 }; 139 140 /* AF_INET /dev/dccp */ 141 struct streamtab dccpinfov4 = { 142 &dccp_rinitv4, &dccp_winit 143 }; 144 145 /* AF_INET6 /dev/dccp6 */ 146 struct streamtab dccpinfov6 = { 147 &dccp_rinitv6, &dccp_winit 148 }; 149 150 /* Template for response to info request */ 151 struct T_info_ack dccp_g_t_info_ack = { 152 T_INFO_ACK, /* PRIM_type */ 153 0, /* TSDU_size */ 154 T_INFINITE, /* ETSDU_size */ 155 T_INVALID, /* CDATA_size */ 156 T_INVALID, /* DDATA_size */ 157 sizeof (sin_t), /* ADDR_size */ 158 0, /* OPT_size - not initialized here */ 159 TIDUSZ, /* TIDU_size */ 160 T_COTS_ORD, /* SERV_type */ 161 DCCPS_CLOSED, /* CURRENT_state */ 162 (XPG4_1|EXPINLINE) /* PROVIDER_flag */ 163 }; 164 165 struct T_info_ack dccp_g_t_info_ack_v6 = { 166 T_INFO_ACK, /* PRIM_type */ 167 0, /* TSDU_size */ 168 T_INFINITE, /* ETSDU_size */ 169 T_INVALID, /* CDATA_size */ 170 T_INVALID, /* DDATA_size */ 171 sizeof (sin6_t), /* ADDR_size */ 172 0, /* OPT_size - not initialized here */ 173 TIDUSZ, /* TIDU_size */ 174 T_COTS_ORD, /* SERV_type */ 175 DCCPS_CLOSED, /* CURRENT_state */ 176 (XPG4_1|EXPINLINE) /* PROVIDER_flag */ 177 }; 178 179 /* 180 * DCCP Tunables. 181 */ 182 extern mod_prop_info_t dccp_propinfo_tbl[]; 183 extern int dccp_propinfo_count; 184 185 /* 186 * Register DCCP in ip netstack. 187 */ 188 void 189 dccp_ddi_g_init(void) 190 { 191 /* Global timer cache */ 192 dccp_timercache = kmem_cache_create("dccp_timercache", 193 sizeof (dccp_timer_t) + sizeof (mblk_t), 0, 194 NULL, NULL, NULL, NULL, NULL, 0); 195 196 netstack_register(NS_DCCP, dccp_stack_init, NULL, dccp_stack_fini); 197 } 198 199 /* 200 * Unregister DCCP from ip netstack. 201 */ 202 void 203 dccp_ddi_g_destroy(void) 204 { 205 /* Global timer cache */ 206 kmem_cache_destroy(dccp_timercache); 207 208 netstack_unregister(NS_DCCP); 209 } 210 211 #define INET_NAME "ip" 212 213 /* 214 * Initialize this DCCP stack instance. 215 */ 216 static void * 217 dccp_stack_init(netstackid_t stackid, netstack_t *ns) 218 { 219 dccp_stack_t *dccps; 220 major_t major; 221 size_t arrsz; 222 int error; 223 int i; 224 225 dccps = kmem_zalloc(sizeof (*dccps), KM_SLEEP); 226 if (dccps == NULL) { 227 return (NULL); 228 } 229 dccps->dccps_netstack = ns; 230 231 /* Ports */ 232 mutex_init(&dccps->dccps_epriv_port_lock, NULL, MUTEX_DEFAULT, NULL); 233 dccps->dccps_num_epriv_ports = DCCP_NUM_EPRIV_PORTS; 234 dccps->dccps_epriv_ports[0] = ULP_DEF_EPRIV_PORT1; 235 dccps->dccps_epriv_ports[1] = ULP_DEF_EPRIV_PORT2; 236 dccps->dccps_min_anonpriv_port = 512; 237 238 dccps->dccps_bind_fanout_size = dccp_bind_fanout_size; 239 240 /* Bind fanout */ 241 dccps->dccps_bind_fanout = kmem_zalloc(dccps->dccps_bind_fanout_size * 242 sizeof (dccp_df_t), KM_SLEEP); 243 for (i = 0; i < dccps->dccps_bind_fanout_size; i++) { 244 mutex_init(&dccps->dccps_bind_fanout[i].df_lock, NULL, 245 MUTEX_DEFAULT, NULL); 246 } 247 248 /* Tunable properties */ 249 arrsz = dccp_propinfo_count * sizeof (mod_prop_info_t); 250 dccps->dccps_propinfo_tbl = kmem_alloc(arrsz, KM_SLEEP); 251 if (dccps->dccps_propinfo_tbl == NULL) { 252 kmem_free(dccps, sizeof (*dccps)); 253 return (NULL); 254 } 255 bcopy(dccp_propinfo_tbl, dccps->dccps_propinfo_tbl, arrsz); 256 257 /* Allocate per netstack cpu stats */ 258 mutex_enter(&cpu_lock); 259 dccps->dccps_sc_cnt = MAX(ncpus, boot_ncpus); 260 mutex_exit(&cpu_lock); 261 262 dccps->dccps_sc = kmem_zalloc(max_ncpus * sizeof (dccp_stats_cpu_t *), 263 KM_SLEEP); 264 for (i = 0; i < dccps->dccps_sc_cnt; i++) { 265 dccps->dccps_sc[i] = kmem_zalloc(sizeof (dccp_stats_cpu_t), 266 KM_SLEEP); 267 } 268 269 /* Kernel statistics */ 270 //dccps->dccps_kstat = dccp_kstat2_init(stackid); 271 //dccps->dccps_mibkp = dccp_kstat_init(stackid); 272 273 /* Driver major number */ 274 major = mod_name_to_major(INET_NAME); 275 error = ldi_ident_from_major(major, &dccps->dccps_ldi_ident); 276 ASSERT(error == 0); 277 278 return (dccps); 279 } 280 281 /* 282 * Destroy this DCCP netstack instance. 283 */ 284 static void 285 dccp_stack_fini(netstackid_t stackid, void *arg) 286 { 287 dccp_stack_t *dccps = (dccp_stack_t *)arg; 288 int i; 289 290 /* Free cpu stats */ 291 for (i = 0; i < dccps->dccps_sc_cnt; i++) { 292 kmem_free(dccps->dccps_sc[i], sizeof (dccp_stats_cpu_t)); 293 } 294 kmem_free(dccps->dccps_sc, max_ncpus * sizeof (dccp_stats_cpu_t *)); 295 296 /* Free tunable properties */ 297 kmem_free(dccps->dccps_propinfo_tbl, 298 dccp_propinfo_count * sizeof (mod_prop_info_t)); 299 dccps->dccps_propinfo_tbl = NULL; 300 301 /* Free bind fanout */ 302 for (i = 0; i < dccps->dccps_bind_fanout_size; i++) { 303 ASSERT(dccps->dccps_bind_fanout[i].df_dccp == NULL); 304 mutex_destroy(&dccps->dccps_bind_fanout[i].df_lock); 305 } 306 kmem_free(dccps->dccps_bind_fanout, dccps->dccps_bind_fanout_size * 307 sizeof (dccp_df_t)); 308 dccps->dccps_bind_fanout = NULL; 309 310 /* Kernel statistics */ 311 dccp_kstat_fini(stackid, dccps->dccps_mibkp); 312 dccps->dccps_mibkp = NULL; 313 dccp_kstat2_fini(stackid, dccps->dccps_kstat); 314 dccps->dccps_kstat = NULL; 315 316 ldi_ident_release(dccps->dccps_ldi_ident); 317 318 kmem_free(dccps, sizeof (*dccps)); 319 } 320 321 /* /dev/dccp */ 322 static int 323 dccp_openv4(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp) 324 { 325 cmn_err(CE_NOTE, "dccp.c: dccp_openv4\n"); 326 327 return (dccp_open(q, devp, flag, sflag, credp, B_FALSE)); 328 } 329 330 /* /dev/dccp6 */ 331 static int 332 dccp_openv6(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp) 333 { 334 cmn_err(CE_NOTE, "dccp.c: dccp_openv6\n"); 335 336 return (dccp_open(q, devp, flag, sflag, credp, B_TRUE)); 337 } 338 339 /* 340 * Common open function for v4 and v6 devices. 341 */ 342 static int 343 dccp_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp, 344 boolean_t isv6) 345 { 346 conn_t *connp; 347 dccp_t *dccp; 348 vmem_t *minor_arena; 349 dev_t conn_dev; 350 boolean_t issocket; 351 int error; 352 353 cmn_err(CE_NOTE, "dccp.c: dccp_open"); 354 355 /* If the stream is already open, return immediately */ 356 if (q->q_ptr != NULL) { 357 return (0); 358 } 359 360 if (sflag == MODOPEN) { 361 return (EINVAL); 362 } 363 364 if ((ip_minor_arena_la != NULL) && (flag & SO_SOCKSTR) && 365 ((conn_dev = inet_minor_alloc(ip_minor_arena_la)) != 0)) { 366 minor_arena = ip_minor_arena_la; 367 } else { 368 /* 369 * Either minor numbers in the large arena were exhausted 370 * or a non socket application is doing the open. 371 * Try to allocate from the small arena. 372 */ 373 if ((conn_dev = inet_minor_alloc(ip_minor_arena_sa)) == 0) { 374 return (EBUSY); 375 } 376 minor_arena = ip_minor_arena_sa; 377 } 378 379 ASSERT(minor_arena != NULL); 380 381 *devp = makedevice(getmajor(*devp), (minor_t)conn_dev); 382 383 if (flag & SO_FALLBACK) { 384 /* 385 * Non streams socket needs a stream to fallback to. 386 */ 387 RD(q)->q_ptr = (void *)conn_dev; 388 WR(q)->q_qinfo = &dccp_fallback_sock_winit; 389 WR(q)->q_ptr = (void *)minor_arena; 390 qprocson(q); 391 return (0); 392 } else if (flag & SO_ACCEPTOR) { 393 q->q_qinfo = &dccp_acceptor_rinit; 394 /* 395 * The conn_dev and minor_arena will be subsequently used by 396 * dccp_tli_accept() and dccp_tpi_close_accept() to figure out 397 * the minor device number for this connection from the q_ptr. 398 */ 399 RD(q)->q_ptr = (void *)conn_dev; 400 WR(q)->q_qinfo = &dccp_acceptor_winit; 401 WR(q)->q_ptr = (void *)minor_arena; 402 qprocson(q); 403 return (0); 404 } 405 406 issocket = flag & SO_SOCKSTR; 407 connp = dccp_create_common(credp, isv6, issocket, &error); 408 if (connp == NULL) { 409 inet_minor_free(minor_arena, conn_dev); 410 q->q_ptr = WR(q)->q_ptr = NULL; 411 return (error); 412 } 413 414 connp->conn_rq = q; 415 connp->conn_wq = WR(q); 416 q->q_ptr = WR(q)->q_ptr = connp; 417 418 connp->conn_dev = conn_dev; 419 connp->conn_minor_arena = minor_arena; 420 421 ASSERT(q->q_qinfo == &dccp_rinitv4 || q->q_qinfo == &dccp_rinitv6); 422 ASSERT(WR(q)->q_qinfo == &dccp_winit); 423 424 dccp = connp->conn_dccp; 425 426 if (issocket) { 427 WR(q)->q_qinfo = &dccp_sock_winit; 428 } else { 429 #ifdef _ILP32 430 dccp->dccp_acceptor_id = (t_uscalar_t)RD(q); 431 #else 432 dccp->dccp_acceptor_id = conn_dev; 433 #endif /* _ILP32 */ 434 } 435 436 /* 437 * Put the ref for DCCP. Ref for IP was already put 438 * by ipcl_conn_create. Also Make the conn_t globally 439 * visible to walkers. 440 */ 441 mutex_enter(&connp->conn_lock); 442 CONN_INC_REF_LOCKED(connp); 443 ASSERT(connp->conn_ref == 2); 444 connp->conn_state_flags &= ~CONN_INCIPIENT; 445 mutex_exit(&connp->conn_lock); 446 447 qprocson(q); 448 449 return (0); 450 } 451 452 /* 453 * IXA notify 454 */ 455 static void 456 dccp_notify(void *arg, ip_xmit_attr_t *ixa, ixa_notify_type_t ntype, 457 ixa_notify_arg_t narg) 458 { 459 cmn_err(CE_NOTE, "dccp.c: dccp_notify"); 460 } 461 462 /* 463 * Build the template headers. 464 */ 465 int 466 dccp_build_hdrs(dccp_t *dccp) 467 { 468 dccp_stack_t *dccps = dccp->dccp_dccps; 469 conn_t *connp = dccp->dccp_connp; 470 dccpha_t *dccpha; 471 uint32_t cksum; 472 char buf[DCCP_MAX_HDR_LENGTH]; 473 uint_t buflen; 474 uint_t ulplen = 12; 475 uint_t extralen = 0; 476 int error; 477 478 cmn_err(CE_NOTE, "dccp.c: dccp_build_hdrs"); 479 480 buflen = connp->conn_ht_ulp_len; 481 if (buflen != 0) { 482 cmn_err(CE_NOTE, "buflen != 0"); 483 bcopy(connp->conn_ht_ulp, buf, buflen); 484 extralen -= buflen - ulplen; 485 ulplen = buflen; 486 } 487 488 mutex_enter(&connp->conn_lock); 489 error = conn_build_hdr_template(connp, ulplen, extralen, 490 &connp->conn_laddr_v6, &connp->conn_faddr_v6, connp->conn_flowinfo); 491 mutex_exit(&connp->conn_lock); 492 if (error != 0) { 493 cmn_err(CE_NOTE, "conn_build_hdr_template failed"); 494 return (error); 495 } 496 497 dccpha = (dccpha_t *)connp->conn_ht_ulp; 498 dccp->dccp_dccpha = dccpha; 499 500 if (buflen != 0) { 501 bcopy(buf, connp->conn_ht_ulp, buflen); 502 } else { 503 dccpha->dha_sum = 0; 504 dccpha->dha_lport = connp->conn_lport; 505 dccpha->dha_fport = connp->conn_fport; 506 } 507 508 cksum = sizeof (dccpha_t) + connp->conn_sum; 509 cksum = (cksum >> 16) + (cksum & 0xFFFF); 510 dccpha->dha_sum = htons(cksum); 511 dccpha->dha_offset = 7; 512 dccpha->dha_x = 1; 513 514 if (connp->conn_ipversion == IPV4_VERSION) { 515 dccp->dccp_ipha = (ipha_t *)connp->conn_ht_iphc; 516 } else { 517 dccp->dccp_ip6h = (ip6_t *)connp->conn_ht_iphc; 518 } 519 520 /* XXX */ 521 522 return (0); 523 } 524 525 /* 526 * DCCP write service routine. 527 */ 528 static void 529 dccp_wsrv(queue_t *q) 530 { 531 dccp_stack_t *dccps = Q_TO_DCCP(q)->dccp_dccps; 532 533 DCCP_STAT(dccps, dccp_wsrv_called); 534 } 535 536 /* 537 * Common create function for streams and sockets. 538 */ 539 conn_t * 540 dccp_create_common(cred_t *credp, boolean_t isv6, boolean_t issocket, 541 int *errorp) 542 { 543 conn_t *connp; 544 dccp_t *dccp; 545 dccp_stack_t *dccps; 546 netstack_t *ns; 547 squeue_t *sqp; 548 zoneid_t zoneid; 549 int error; 550 551 cmn_err(CE_NOTE, "dccp.c: dccp_create_common\n"); 552 553 ASSERT(errorp != NULL); 554 555 error = secpolicy_basic_net_access(credp); 556 if (error != 0) { 557 *errorp = error; 558 return (NULL); 559 } 560 561 /* 562 * Find the right netstack. 563 */ 564 ns = netstack_find_by_cred(credp); 565 ASSERT(ns != NULL); 566 dccps = ns->netstack_dccp; 567 ASSERT(dccps != NULL); 568 569 /* 570 * For exclusive stacks we set the zoneid to zero 571 * to make TCP operate as if in the global zone. 572 */ 573 if (ns->netstack_stackid != GLOBAL_NETSTACKID) { 574 zoneid = GLOBAL_ZONEID; 575 } else { 576 zoneid = crgetzoneid(credp); 577 } 578 579 sqp = IP_SQUEUE_GET((uint_t)gethrtime()); 580 connp = (conn_t *)dccp_get_conn(sqp, dccps); 581 netstack_rele(dccps->dccps_netstack); 582 if (connp == NULL) { 583 *errorp = ENOSR; 584 return (NULL); 585 } 586 ASSERT(connp->conn_ixa->ixa_protocol == connp->conn_proto); 587 588 connp->conn_sqp = sqp; 589 connp->conn_initial_sqp = connp->conn_sqp; 590 connp->conn_ixa->ixa_sqp = connp->conn_sqp; 591 dccp = connp->conn_dccp; 592 593 /* Setting flags for ip output */ 594 connp->conn_ixa->ixa_flags |= IXAF_SET_ULP_CKSUM | IXAF_VERIFY_SOURCE | 595 IXAF_VERIFY_PMTU | IXAF_VERIFY_LSO; 596 597 ASSERT(connp->conn_proto == IPPROTO_DCCP); 598 ASSERT(connp->conn_dccp == dccp); 599 ASSERT(dccp->dccp_connp == connp); 600 601 if (isv6) { 602 connp->conn_ixa->ixa_src_preferences = IPV6_PREFER_SRC_DEFAULT; 603 connp->conn_ipversion = IPV6_VERSION; 604 connp->conn_family = AF_INET6; 605 /* XXX mms, ttl */ 606 } else { 607 connp->conn_ipversion = IPV4_VERSION; 608 connp->conn_family = AF_INET; 609 /* XXX mms, ttl */ 610 } 611 connp->conn_xmit_ipp.ipp_unicast_hops = connp->conn_default_ttl; 612 613 crhold(credp); 614 connp->conn_cred = credp; 615 connp->conn_cpid = curproc->p_pid; 616 connp->conn_open_time = ddi_get_lbolt64(); 617 618 ASSERT(!(connp->conn_ixa->ixa_free_flags & IXA_FREE_CRED)); 619 connp->conn_ixa->ixa_cred = credp; 620 connp->conn_ixa->ixa_cpid = connp->conn_cpid; 621 622 connp->conn_zoneid = zoneid; 623 connp->conn_zone_is_global = (crgetzoneid(credp) == GLOBAL_ZONEID); 624 connp->conn_ixa->ixa_zoneid = zoneid; 625 connp->conn_mlp_type = mlptSingle; 626 627 dccp->dccp_dccps = dccps; 628 dccp->dccp_state = DCCPS_CLOSED; 629 630 ASSERT(connp->conn_netstack == dccps->dccps_netstack); 631 ASSERT(dccp->dccp_dccps == dccps); 632 633 /* 634 * If the caller has the process-wide flag set, then default to MAC 635 * exempt mode. This allows read-down to unlabeled hosts. 636 */ 637 if (getpflags(NET_MAC_AWARE, credp) != 0) { 638 connp->conn_mac_mode = CONN_MAC_AWARE; 639 } 640 641 if (issocket) { 642 dccp->dccp_issocket = 1; 643 } 644 645 /* XXX rcvbuf, sndbuf etc */ 646 647 connp->conn_so_type = SOCK_STREAM; 648 649 SOCK_CONNID_INIT(dccp->dccp_connid); 650 dccp_init_values(dccp, NULL); 651 652 return (connp); 653 } 654 655 /* 656 * Common close function for streams and sockets. 657 */ 658 void 659 dccp_close_common(conn_t *connp, int flags) 660 { 661 dccp_t *dccp = connp->conn_dccp; 662 mblk_t *mp; 663 boolean_t conn_ioctl_cleanup_reqd = B_FALSE; 664 665 cmn_err(CE_NOTE, "dccp.c: dccp_close_common"); 666 667 ASSERT(connp->conn_ref >= 2); 668 669 /* 670 * Mark the conn as closing. ipsq_pending_mp_add will not 671 * add any mp to the pending mp list, after this conn has 672 * started closing. 673 */ 674 mutex_enter(&connp->conn_lock); 675 connp->conn_state_flags |= CONN_CLOSING; 676 677 if (connp->conn_oper_pending_ill != NULL) { 678 conn_ioctl_cleanup_reqd = B_TRUE; 679 } 680 681 CONN_INC_REF_LOCKED(connp); 682 mutex_exit(&connp->conn_lock); 683 684 ASSERT(connp->conn_ref >= 3); 685 686 /* 687 * Cleanup any queued ioctls here. This must be done before the wq/rq 688 * are re-written by dccp_close_output(). 689 */ 690 if (conn_ioctl_cleanup_reqd) { 691 conn_ioctl_cleanup(connp); 692 } 693 694 mutex_enter(&connp->conn_lock); 695 while (connp->conn_ioctlref > 0) { 696 cv_wait(&connp->conn_cv, &connp->conn_lock); 697 } 698 ASSERT(connp->conn_ioctlref == 0); 699 ASSERT(connp->conn_oper_pending_ill == NULL); 700 mutex_exit(&connp->conn_lock); 701 702 /* generate close */ 703 /* 704 SQUEUE_ENTER_ONE(connp->conn_sqp, mp, dccp_close_output, connp, 705 NULL, dccp_squeue_flag, SQTAG_IP_DCCP_CLOSE); 706 707 */ 708 709 nowait: 710 connp->conn_cpid = NOPID; 711 } 712 713 /* 714 * Common bind function. 715 */ 716 int 717 dccp_do_bind(conn_t *connp, struct sockaddr *sa, socklen_t len, cred_t *cr, 718 boolean_t bind_to_req_port_only) 719 { 720 dccp_t *dccp = connp->conn_dccp; 721 int error; 722 723 cmn_err(CE_NOTE, "dccp.c: dccp_do_bind"); 724 725 if (dccp->dccp_state >= DCCPS_BOUND) { 726 if (connp->conn_debug) { 727 (void) strlog(DCCP_MOD_ID, 0, 1, SL_ERROR|SL_TRACE, 728 "dccp_bind: bad state, %d", dccp->dccp_state); 729 } 730 return (-TOUTSTATE); 731 } 732 733 error = dccp_bind_check(connp, sa, len, cr, bind_to_req_port_only); 734 if (error != 0) { 735 return (error); 736 } 737 738 ASSERT(dccp->dccp_state == DCCPS_LISTEN); 739 /* XXX dccp_conn_req_max = 0 */ 740 741 return (0); 742 } 743 744 /* 745 * Common unbind function. 746 */ 747 int 748 dccp_do_unbind(conn_t *connp) 749 { 750 dccp_t *dccp = connp->conn_dccp; 751 int32_t oldstate; 752 753 cmn_err(CE_NOTE, "dccp.c: dccp_do_unbind"); 754 755 switch (dccp->dccp_state) { 756 case DCCPS_OPEN: 757 case DCCPS_LISTEN: 758 break; 759 default: 760 return (-TOUTSTATE); 761 } 762 763 connp->conn_laddr_v6 = ipv6_all_zeros; 764 connp->conn_saddr_v6 = ipv6_all_zeros; 765 766 dccp_bind_hash_remove(dccp); 767 768 oldstate = dccp->dccp_state; 769 dccp->dccp_state = DCCPS_CLOSED; 770 DTRACE_DCCP6(state__change, void, NULL, ip_xmit_attr_t *, 771 connp->conn_ixa, void, NULL, dccp_t *, dccp, void, NULL, 772 int32_t, oldstate); 773 774 ip_unbind(connp); 775 bzero(&connp->conn_ports, sizeof (connp->conn_ports)); 776 777 return (0); 778 } 779 780 /* 781 * Common listen function. 782 */ 783 int 784 dccp_do_listen(conn_t *connp, struct sockaddr *sa, socklen_t len, 785 int backlog, cred_t *cr, boolean_t bind_to_req_port_only) 786 { 787 dccp_t *dccp = connp->conn_dccp; 788 dccp_stack_t *dccps = dccp->dccp_dccps; 789 int32_t oldstate; 790 int error; 791 792 cmn_err(CE_NOTE, "dccp.c: dccp_do_listen"); 793 794 /* All Solaris components should pass a cred for this operation */ 795 ASSERT(cr != NULL); 796 797 if (dccp->dccp_state >= DCCPS_BOUND) { 798 799 if ((dccp->dccp_state == DCCPS_BOUND || 800 dccp->dccp_state == DCCPS_LISTEN) && backlog > 0) { 801 goto do_listen; 802 } 803 cmn_err(CE_NOTE, "DCCPS_BOUND, bad state"); 804 805 if (connp->conn_debug) { 806 (void) strlog(DCCP_MOD_ID, 0, 1, SL_ERROR|SL_TRACE, 807 "dccp_listen: bad state, %d", dccp->dccp_state); 808 } 809 return (-TOUTSTATE); 810 } else { 811 if (sa == NULL) { 812 sin6_t addr; 813 sin6_t *sin6; 814 sin_t *sin; 815 816 ASSERT(IPCL_IS_NONSTR(connp)); 817 818 if (connp->conn_family == AF_INET) { 819 len = sizeof (sin_t); 820 sin = (sin_t *)&addr; 821 *sin = sin_null; 822 sin->sin_family = AF_INET; 823 } else { 824 ASSERT(connp->conn_family == AF_INET6); 825 826 len = sizeof (sin6_t); 827 sin6 = (sin6_t *)&addr; 828 *sin6 = sin6_null; 829 sin6->sin6_family = AF_INET6; 830 } 831 832 sa = (struct sockaddr *)&addr; 833 } 834 835 error = dccp_bind_check(connp, sa, len, cr, 836 bind_to_req_port_only); 837 if (error != 0) { 838 cmn_err(CE_NOTE, "dccp_bind_check failed"); 839 return (error); 840 } 841 /* Fall through and do the fanout insertion */ 842 } 843 844 do_listen: 845 ASSERT(dccp->dccp_state == DCCPS_BOUND || 846 dccp->dccp_state == DCCPS_LISTEN); 847 848 dccp->dccp_conn_req_max = backlog; 849 if (dccp->dccp_conn_req_max) { 850 if (dccp->dccp_state != DCCPS_LISTEN) { 851 dccp->dccp_state = DCCPS_LISTEN; 852 DTRACE_DCCP6(state__change, void, NULL, 853 ip_xmit_attr_t *, connp->conn_ixa, void, NULL, 854 dccp_t *, dccp, void, NULL, int32_t, DCCPS_BOUND); 855 856 dccp->dccp_second_ctimer_threshold = 857 dccps->dccps_ip_abort_linterval; 858 } 859 } 860 861 /* XXX */ 862 863 connp->conn_recv = dccp_input_listener_unbound; 864 865 /* Insert into the classifier table */ 866 error = ip_laddr_fanout_insert(connp); 867 if (error != 0) { 868 /* Error - undo the bind */ 869 oldstate = dccp->dccp_state; 870 dccp->dccp_state = DCCPS_CLOSED; 871 DTRACE_DCCP6(state__change, void, NULL, ip_xmit_attr_t *, 872 connp->conn_ixa, void, NULL, dccp_t *, dccp, void, NULL, 873 int32_t, oldstate); 874 875 connp->conn_bound_addr_v6 = ipv6_all_zeros; 876 connp->conn_laddr_v6 = ipv6_all_zeros; 877 connp->conn_saddr_v6 = ipv6_all_zeros; 878 connp->conn_ports = 0; 879 880 if (connp->conn_anon_port) { 881 zone_t *zone; 882 883 zone = crgetzone(cr); 884 connp->conn_anon_port = B_FALSE; 885 (void) tsol_mlp_anon(zone, connp->conn_mlp_type, 886 connp->conn_proto, connp->conn_lport, B_FALSE); 887 } 888 connp->conn_mlp_type = mlptSingle; 889 890 dccp_bind_hash_remove(dccp); 891 892 return (error); 893 } else { 894 /* XXX connection limits */ 895 } 896 897 return (error); 898 } 899 900 /* 901 * Common connect function. 902 */ 903 int 904 dccp_do_connect(conn_t *connp, const struct sockaddr *sa, socklen_t len, 905 cred_t *cr, pid_t pid) 906 { 907 dccp_t *dccp = connp->conn_dccp; 908 dccp_stack_t *dccps = dccp->dccp_dccps; 909 ip_xmit_attr_t *ixa = connp->conn_ixa; 910 mblk_t *req_mp; 911 sin_t *sin = (sin_t *)sa; 912 sin6_t *sin6 = (sin6_t *)sa; 913 ipaddr_t *dstaddrp; 914 in_port_t dstport; 915 uint_t srcid; 916 int32_t oldstate; 917 int error; 918 919 cmn_err(CE_NOTE, "dccp.c: dccp_do_connect"); 920 921 oldstate = dccp->dccp_state; 922 923 switch (len) { 924 case sizeof (sin_t): 925 sin = (sin_t *)sa; 926 if (sin->sin_port == 0) { 927 return (-TBADADDR); 928 } 929 if (connp->conn_ipv6_v6only) { 930 return (EAFNOSUPPORT); 931 } 932 break; 933 934 case sizeof (sin6_t): 935 sin6 = (sin6_t *)sa; 936 if (sin6->sin6_port == 0) { 937 return (-TBADADDR); 938 } 939 break; 940 941 default: 942 return (EINVAL); 943 } 944 945 if (connp->conn_family == AF_INET6 && 946 connp->conn_ipversion == IPV6_VERSION && 947 IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 948 if (connp->conn_ipv6_v6only) { 949 return (EADDRNOTAVAIL); 950 } 951 952 connp->conn_ipversion = IPV4_VERSION; 953 } 954 955 switch (dccp->dccp_state) { 956 case DCCPS_LISTEN: 957 /* 958 * Listening sockets are not allowed to issue connect(). 959 */ 960 if (IPCL_IS_NONSTR(connp)) { 961 return (EOPNOTSUPP); 962 } 963 964 case DCCPS_CLOSED: 965 /* 966 * We support quick connect. 967 */ 968 /* FALLTHRU */ 969 case DCCPS_OPEN: 970 break; 971 972 default: 973 return (-TOUTSTATE); 974 } 975 976 /* 977 * We update our cred/cpid based on the caller of connect. 978 */ 979 if (connp->conn_cred != cr) { 980 crhold(cr); 981 crfree(connp->conn_cred); 982 connp->conn_cred = cr; 983 } 984 connp->conn_cpid = pid; 985 986 /* Cache things in the ixa without any refhold */ 987 ASSERT(!(ixa->ixa_free_flags & IXA_FREE_CRED)); 988 ixa->ixa_cred = cr; 989 ixa->ixa_cpid = pid; 990 991 if (is_system_labeled()) { 992 ip_xmit_attr_restore_tsl(ixa, ixa->ixa_cred); 993 } 994 995 if (connp->conn_family == AF_INET6) { 996 if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 997 error = dccp_connect_ipv6(dccp, &sin6->sin6_addr, 998 sin6->sin6_port, sin6->sin6_flowinfo, 999 sin6->__sin6_src_id, sin6->sin6_scope_id); 1000 } else { 1001 /* 1002 * Destination adress is mapped IPv6 address. 1003 * Source bound address should be unspecified or 1004 * IPv6 mapped address as well. 1005 */ 1006 if (!IN6_IS_ADDR_UNSPECIFIED( 1007 &connp->conn_bound_addr_v6) && 1008 !IN6_IS_ADDR_V4MAPPED(&connp->conn_bound_addr_v6)) { 1009 return (EADDRNOTAVAIL); 1010 } 1011 1012 dstaddrp = &V4_PART_OF_V6((sin6->sin6_addr)); 1013 dstport = sin6->sin6_port; 1014 srcid = sin6->__sin6_src_id; 1015 error = dccp_connect_ipv4(dccp, dstaddrp, dstport, 1016 srcid); 1017 } 1018 } else { 1019 dstaddrp = &sin->sin_addr.s_addr; 1020 dstport = sin->sin_port; 1021 srcid = 0; 1022 error = dccp_connect_ipv4(dccp, dstaddrp, dstport, srcid); 1023 } 1024 1025 if (error != 0) { 1026 cmn_err(CE_NOTE, "dccp_connect_ip failed"); 1027 goto connect_failed; 1028 } 1029 1030 /* XXX cluster */ 1031 1032 /* Connect succeeded */ 1033 DCCPS_BUMP_MIB(dccps, dccpActiveOpens); 1034 dccp->dccp_active_open = 1; 1035 1036 DTRACE_DCCP6(state__change, void, NULL, ip_xmit_attr_t *, 1037 connp->conn_ixa, void, NULL, dccp_t *, dccp, void, NULL, 1038 int32_t, DCCPS_BOUND); 1039 1040 DCCP_TIMER_RESTART(dccp, 100); 1041 req_mp = dccp_generate_request(connp); 1042 if (req_mp != NULL) { 1043 /* 1044 * We must bump the generation before sending the request 1045 * to ensure that we use the right generation in case 1046 * this thread issues a "connected" up call. 1047 */ 1048 SOCK_CONNID_BUMP(dccp->dccp_connid); 1049 1050 DTRACE_DCCP5(connect__request, mblk_t *, NULL, 1051 ip_xmit_attr_t *, connp->conn_ixa, 1052 void_ip_t *, req_mp->b_rptr, dccp_t *, dccp, 1053 dccpha_t *, 1054 &req_mp->b_rptr[connp->conn_ixa->ixa_ip_hdr_length]); 1055 1056 dccp_send_data(dccp, req_mp); 1057 } 1058 1059 return (0); 1060 1061 connect_failed: 1062 cmn_err(CE_NOTE, "dccp_do_connect failed"); 1063 1064 connp->conn_faddr_v6 = ipv6_all_zeros; 1065 connp->conn_fport = 0; 1066 dccp->dccp_state = oldstate; 1067 1068 /* XXX */ 1069 return (error); 1070 } 1071 1072 /* 1073 * Init values of a connection. 1074 */ 1075 void 1076 dccp_init_values(dccp_t *dccp, dccp_t *parent) 1077 { 1078 conn_t *connp = dccp->dccp_connp; 1079 dccp_stack_t *dccps = dccp->dccp_dccps; 1080 1081 ASSERT((connp->conn_family == AF_INET && 1082 connp->conn_ipversion == IPV4_VERSION) || 1083 (connp->conn_family == AF_INET6 && 1084 (connp->conn_ipversion == IPV4_VERSION || 1085 connp->conn_ipversion == IPV6_VERSION))); 1086 1087 if (parent == NULL) { 1088 1089 dccp->dccp_first_ctimer_threshold = 1090 dccps->dccps_ip_notify_cinterval; 1091 dccp->dccp_second_ctimer_threshold = 1092 dccps->dccps_ip_abort_cinterval; 1093 dccp->dccp_first_timer_threshold = 1094 dccps->dccps_ip_notify_interval; 1095 dccp->dccp_second_timer_threshold = 1096 dccps->dccps_ip_abort_interval; 1097 1098 dccp->dccp_ka_interval = 1099 dccps->dccps_keepalive_interval; 1100 dccp->dccp_ka_abort_thres = 1101 dccps->dccps_keepalive_abort_interval; 1102 dccp->dccp_ka_cnt = 0; 1103 dccp->dccp_ka_rinterval = 0; 1104 } else { 1105 /* Inherit various DCCP parameters from the parent */ 1106 dccp->dccp_first_ctimer_threshold = 1107 parent->dccp_first_ctimer_threshold; 1108 dccp->dccp_second_ctimer_threshold = 1109 parent->dccp_second_ctimer_threshold; 1110 dccp->dccp_first_timer_threshold = 1111 parent->dccp_first_timer_threshold; 1112 dccp->dccp_second_timer_threshold = 1113 parent->dccp_second_timer_threshold; 1114 1115 dccp->dccp_ka_interval = parent->dccp_ka_interval; 1116 dccp->dccp_ka_abort_thres = parent->dccp_ka_abort_thres; 1117 dccp->dccp_ka_cnt = parent->dccp_ka_cnt; 1118 dccp->dccp_ka_rinterval = parent->dccp_ka_rinterval; 1119 } 1120 1121 dccp->dccp_last_recv_time = ddi_get_lbolt(); 1122 dccp->dccp_sequence_window = 100; 1123 1124 connp->conn_mlp_type = mlptSingle; 1125 1126 if (!connp->conn_debug) { 1127 connp->conn_debug = dccps->dccps_dbg; 1128 } 1129 } 1130 1131 /* 1132 * Free dccp structure. 1133 */ 1134 void 1135 dccp_free(dccp_t *dccp) 1136 { 1137 conn_t *connp = dccp->dccp_connp; 1138 1139 cmn_err(CE_NOTE, "dccp.c: dccp_free"); 1140 1141 connp->conn_rq = NULL; 1142 connp->conn_wq = NULL; 1143 1144 if (connp->conn_upper_handle != NULL) { 1145 if (IPCL_IS_NONSTR(connp)) { 1146 (*connp->conn_upcalls->su_closed)( 1147 connp->conn_upper_handle); 1148 dccp->dccp_detached = B_TRUE; 1149 } 1150 1151 connp->conn_upper_handle = NULL; 1152 connp->conn_upcalls = NULL; 1153 } 1154 } 1155 1156 void * 1157 dccp_get_conn(void *arg, dccp_stack_t *dccps) 1158 { 1159 conn_t *connp; 1160 dccp_t *dccp = NULL; 1161 squeue_t *sqp = (squeue_t *)arg; 1162 netstack_t *ns; 1163 1164 /* XXX timewait */ 1165 1166 connp = ipcl_conn_create(IPCL_DCCPCONN, KM_NOSLEEP, 1167 dccps->dccps_netstack); 1168 if (connp == NULL) { 1169 return (NULL); 1170 } 1171 1172 dccp = connp->conn_dccp; 1173 dccp->dccp_dccps = dccps; 1174 1175 /* List of features being negotated */ 1176 list_create(&dccp->dccp_features, sizeof (dccp_feature_t), 1177 offsetof(dccp_feature_t, df_next)); 1178 1179 connp->conn_recv = dccp_input_data; 1180 connp->conn_recvicmp = dccp_icmp_input; 1181 connp->conn_verifyicmp = dccp_verifyicmp; 1182 1183 connp->conn_ixa->ixa_notify = dccp_notify; 1184 connp->conn_ixa->ixa_notify_cookie = dccp; 1185 1186 return ((void *)connp); 1187 } 1188 1189 /* 1190 * Collect protocol properties to send to the upper handle. 1191 */ 1192 void 1193 dccp_get_proto_props(dccp_t *dccp, struct sock_proto_props *sopp) 1194 { 1195 conn_t *connp = dccp->dccp_connp; 1196 1197 cmn_err(CE_NOTE, "dccp.c: dccp_get_proto_props"); 1198 1199 sopp->sopp_flags = SOCKOPT_RCVHIWAT | SOCKOPT_MAXBLK | SOCKOPT_WROFF; 1200 } 1201 1202 /* 1203 * IPv4 connect. 1204 */ 1205 static int 1206 dccp_connect_ipv4(dccp_t *dccp, ipaddr_t *dstaddrp, in_port_t dstport, 1207 uint_t srcid) 1208 { 1209 conn_t *connp = dccp->dccp_connp; 1210 dccp_stack_t *dccps = dccp->dccp_dccps; 1211 ipaddr_t dstaddr = *dstaddrp; 1212 uint16_t lport; 1213 int error; 1214 1215 cmn_err(CE_NOTE, "dccp.c: dccp_connect_ipv4"); 1216 1217 ASSERT(connp->conn_ipversion == IPV4_VERSION); 1218 1219 if (dstaddr == INADDR_ANY) { 1220 dstaddr = htonl(INADDR_LOOPBACK); 1221 *dstaddrp = dstaddr; 1222 } 1223 1224 /* Handle __sin6_src_id if socket not bound to an IP address */ 1225 if (srcid != 0 && connp->conn_laddr_v4 == INADDR_ANY) { 1226 ip_srcid_find_id(srcid, &connp->conn_laddr_v6, 1227 IPCL_ZONEID(connp), dccps->dccps_netstack); 1228 connp->conn_saddr_v6 = connp->conn_laddr_v6; 1229 } 1230 1231 IN6_IPADDR_TO_V4MAPPED(dstaddr, &connp->conn_faddr_v6); 1232 connp->conn_fport = dstport; 1233 1234 if (dccp->dccp_state == DCCPS_CLOSED) { 1235 lport = dccp_update_next_port(dccps->dccps_next_port_to_try, 1236 dccp, B_TRUE); 1237 lport = dccp_bindi(dccp, lport, &connp->conn_laddr_v6, 0, 1238 B_TRUE, B_FALSE, B_FALSE); 1239 if (lport == 0) { 1240 return (-TNOADDR); 1241 } 1242 } 1243 1244 error = dccp_set_destination(dccp); 1245 if (error != 0) { 1246 return (error); 1247 } 1248 1249 /* 1250 * Don't connect to oneself. 1251 */ 1252 if (connp->conn_faddr_v4 == connp->conn_laddr_v4 && 1253 connp->conn_fport == connp->conn_lport) { 1254 return (-TBADADDR); 1255 } 1256 1257 dccp->dccp_state = DCCPS_REQUEST; 1258 1259 return (ipcl_conn_insert_v4(connp)); 1260 } 1261 1262 /* 1263 * IPv6 connect. 1264 */ 1265 static int 1266 dccp_connect_ipv6(dccp_t *dccp, in6_addr_t *dstaddrp, in_port_t dstport, 1267 uint32_t flowinfo, uint_t srcid, uint32_t scope_id) 1268 { 1269 cmn_err(CE_NOTE, "dccp.c: dccp_connect_ipv6"); 1270 1271 return (0); 1272 } 1273 1274 /* 1275 * Set the ports via conn_connect and build the template 1276 * header. 1277 */ 1278 int 1279 dccp_set_destination(dccp_t *dccp) 1280 { 1281 conn_t *connp = dccp->dccp_connp; 1282 dccp_stack_t *dccps = dccp->dccp_dccps; 1283 iulp_t uinfo; 1284 uint32_t flags; 1285 int error; 1286 1287 flags = IPDF_LSO | IPDF_ZCOPY; 1288 flags |= IPDF_UNIQUE_DCE; 1289 1290 mutex_enter(&connp->conn_lock); 1291 error = conn_connect(connp, &uinfo, flags); 1292 mutex_exit(&connp->conn_lock); 1293 if (error != 0) { 1294 cmn_err(CE_NOTE, "conn_connect failed"); 1295 return (error); 1296 } 1297 1298 error = dccp_build_hdrs(dccp); 1299 if (error != 0) { 1300 cmn_err(CE_NOTE, "dccp_build_hdrs failed"); 1301 return (error); 1302 } 1303 1304 /* XXX */ 1305 1306 /* Initialise the ISS */ 1307 dccp_iss_init(dccp); 1308 1309 mutex_enter(&connp->conn_lock); 1310 connp->conn_state_flags &= ~CONN_INCIPIENT; 1311 mutex_exit(&connp->conn_lock); 1312 1313 return (0); 1314 } 1315 1316 /* 1317 * Clean up. 1318 */ 1319 int 1320 dccp_clean_death(dccp_t *dccp, int error) 1321 { 1322 conn_t *connp = dccp->dccp_connp; 1323 dccp_stack_t *dccps = dccp->dccp_dccps; 1324 1325 ASSERT(dccp != NULL); 1326 ASSERT((connp->conn_family == AF_INET && 1327 connp->conn_ipversion == IPV4_VERSION) || 1328 (connp->conn_family == AF_INET6 && 1329 (connp->conn_ipversion == IPV4_VERSION || 1330 connp->conn_ipversion == IPV6_VERSION))); 1331 1332 dccp_reinit(dccp); 1333 if (IPCL_IS_NONSTR(connp)) { 1334 (void) dccp_do_unbind(connp); 1335 } 1336 1337 return (-1); 1338 } 1339 1340 /* 1341 * Init the ISS. 1342 */ 1343 static void 1344 dccp_iss_init(dccp_t *dccp) 1345 { 1346 cmn_err(CE_NOTE, "dccp.c: dccp_iss_init"); 1347 1348 dccp->dccp_iss += gethrtime(); 1349 dccp->dccp_gss = dccp->dccp_iss; 1350 } 1351 1352 /* 1353 * Reinitialization of a dccp structure. 1354 */ 1355 static void 1356 dccp_reinit(dccp_t *dccp) 1357 { 1358 conn_t *connp = dccp->dccp_connp; 1359 dccp_stack_t *dccps = dccp->dccp_dccps; 1360 1361 ASSERT(dccp->dccp_listener == NULL); 1362 ASSERT((connp->conn_family == AF_INET && 1363 connp->conn_ipversion == IPV4_VERSION) || 1364 (connp->conn_family == AF_INET6 && 1365 (connp->conn_ipversion == IPV4_VERSION || 1366 connp->conn_ipversion == IPV6_VERSION))); 1367 1368 /* Cancel outstanding timers */ 1369 dccp_timers_stop(dccp); 1370 }