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 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/systm.h> 29 #include <sys/stream.h> 30 #include <sys/cmn_err.h> 31 #include <sys/kmem.h> 32 #define _SUN_TPI_VERSION 2 33 #include <sys/tihdr.h> 34 #include <sys/stropts.h> 35 #include <sys/strsubr.h> 36 #include <sys/socket.h> 37 #include <sys/tsol/tndb.h> 38 39 #include <netinet/in.h> 40 #include <netinet/ip6.h> 41 42 #include <inet/common.h> 43 #include <inet/ip.h> 44 #include <inet/ip6.h> 45 #include <inet/ipclassifier.h> 46 #include <inet/ipsec_impl.h> 47 48 #include "sctp_impl.h" 49 #include "sctp_addr.h" 50 51 /* 52 * Common accept code. Called by sctp_conn_request. 53 * cr_pkt is the INIT / INIT ACK packet. 54 */ 55 static int 56 sctp_accept_comm(sctp_t *listener, sctp_t *acceptor, mblk_t *cr_pkt, 57 uint_t ip_hdr_len, sctp_init_chunk_t *iack) 58 { 59 60 sctp_hdr_t *sctph; 61 sctp_chunk_hdr_t *ich; 62 sctp_init_chunk_t *init; 63 int err; 64 uint_t sctp_options; 65 conn_t *aconnp; 66 conn_t *lconnp; 67 cred_t *cr; 68 sctp_stack_t *sctps = listener->sctp_sctps; 69 70 sctph = (sctp_hdr_t *)(cr_pkt->b_rptr + ip_hdr_len); 71 ASSERT(OK_32PTR(sctph)); 72 73 acceptor->sctp_lport = listener->sctp_lport; 74 acceptor->sctp_fport = sctph->sh_sport; 75 76 ich = (sctp_chunk_hdr_t *)(iack + 1); 77 init = (sctp_init_chunk_t *)(ich + 1); 78 79 /* acceptor isn't in any fanouts yet, so don't need to hold locks */ 80 ASSERT(acceptor->sctp_faddrs == NULL); 81 err = sctp_get_addrparams(acceptor, listener, cr_pkt, ich, 82 &sctp_options); 83 if (err != 0) 84 return (err); 85 86 aconnp = acceptor->sctp_connp; 87 lconnp = listener->sctp_connp; 88 if (lconnp->conn_mlp_type != mlptSingle) { 89 cr = aconnp->conn_peercred = msg_getcred(cr_pkt, NULL); 90 if (cr != NULL) 91 crhold(cr); 92 } 93 94 if ((err = sctp_set_hdraddrs(acceptor)) != 0) 95 return (err); 96 97 if ((sctp_options & SCTP_PRSCTP_OPTION) && 98 listener->sctp_prsctp_aware && sctps->sctps_prsctp_enabled) { 99 acceptor->sctp_prsctp_aware = B_TRUE; 100 } else { 101 acceptor->sctp_prsctp_aware = B_FALSE; 102 } 103 /* The new sctp_t is fully bound now. */ 104 acceptor->sctp_connp->conn_fully_bound = B_TRUE; 105 106 /* Get initial TSNs */ 107 acceptor->sctp_ltsn = ntohl(iack->sic_inittsn); 108 acceptor->sctp_recovery_tsn = acceptor->sctp_lastack_rxd = 109 acceptor->sctp_ltsn - 1; 110 acceptor->sctp_adv_pap = acceptor->sctp_lastack_rxd; 111 /* Serial numbers are initialized to the same value as the TSNs */ 112 acceptor->sctp_lcsn = acceptor->sctp_ltsn; 113 114 if (!sctp_initialize_params(acceptor, init, iack)) 115 return (ENOMEM); 116 117 /* 118 * Copy sctp_secret from the listener in case we need to validate 119 * a possibly delayed cookie. 120 */ 121 bcopy(listener->sctp_secret, acceptor->sctp_secret, SCTP_SECRET_LEN); 122 bcopy(listener->sctp_old_secret, acceptor->sctp_old_secret, 123 SCTP_SECRET_LEN); 124 acceptor->sctp_last_secret_update = lbolt64; 125 126 /* 127 * After acceptor is inserted in the hash list, it can be found. 128 * So we need to lock it here. 129 */ 130 RUN_SCTP(acceptor); 131 132 sctp_conn_hash_insert(&sctps->sctps_conn_fanout[ 133 SCTP_CONN_HASH(sctps, acceptor->sctp_ports)], acceptor, 0); 134 sctp_bind_hash_insert(&sctps->sctps_bind_fanout[ 135 SCTP_BIND_HASH(ntohs(acceptor->sctp_lport))], acceptor, 0); 136 137 /* 138 * No need to check for multicast destination since ip will only pass 139 * up multicasts to those that have expressed interest 140 * TODO: what about rejecting broadcasts? 141 * Also check that source is not a multicast or broadcast address. 142 */ 143 /* XXXSCTP */ 144 acceptor->sctp_state = SCTPS_ESTABLISHED; 145 acceptor->sctp_assoc_start_time = (uint32_t)lbolt; 146 /* 147 * listener->sctp_rwnd should be the default window size or a 148 * window size changed via SO_RCVBUF option. 149 */ 150 acceptor->sctp_rwnd = listener->sctp_rwnd; 151 acceptor->sctp_irwnd = acceptor->sctp_rwnd; 152 acceptor->sctp_pd_point = acceptor->sctp_rwnd; 153 acceptor->sctp_upcalls = listener->sctp_upcalls; 154 #if 0 155 bcopy(&listener->sctp_upcalls, &acceptor->sctp_upcalls, 156 sizeof (sctp_upcalls_t)); 157 #endif 158 159 return (0); 160 } 161 162 /* Process the COOKIE packet, mp, directed at the listener 'sctp' */ 163 sctp_t * 164 sctp_conn_request(sctp_t *sctp, mblk_t *mp, uint_t ifindex, uint_t ip_hdr_len, 165 sctp_init_chunk_t *iack, mblk_t *ipsec_mp) 166 { 167 sctp_t *eager; 168 uint_t ipvers; 169 ip6_t *ip6h; 170 int err; 171 conn_t *connp, *econnp; 172 sctp_stack_t *sctps; 173 struct sock_proto_props sopp; 174 cred_t *cr; 175 pid_t cpid; 176 177 /* 178 * No need to check for duplicate as this is the listener 179 * and we are holding the lock. This means that no new 180 * connection can be created out of it. And since the 181 * fanout already done cannot find a match, it means that 182 * there is no duplicate. 183 */ 184 ipvers = IPH_HDR_VERSION(mp->b_rptr); 185 ASSERT(ipvers == IPV6_VERSION || ipvers == IPV4_VERSION); 186 ASSERT(OK_32PTR(mp->b_rptr)); 187 188 if ((eager = sctp_create_eager(sctp)) == NULL) { 189 return (NULL); 190 } 191 192 if (ipvers != IPV4_VERSION) { 193 ip6h = (ip6_t *)mp->b_rptr; 194 if (IN6_IS_ADDR_LINKLOCAL(&ip6h->ip6_src)) 195 eager->sctp_linklocal = 1; 196 /* 197 * Record ifindex (might be zero) to tie this connection to 198 * that interface if either the listener was bound or 199 * if the connection is using link-local addresses. 200 */ 201 if (sctp->sctp_bound_if == ifindex || 202 IN6_IS_ADDR_LINKLOCAL(&ip6h->ip6_src)) 203 eager->sctp_bound_if = ifindex; 204 /* 205 * XXX broken. bound_if is always overwritten by statement 206 * below. What is the right thing to do here? 207 */ 208 eager->sctp_bound_if = sctp->sctp_bound_if; 209 } 210 211 connp = sctp->sctp_connp; 212 sctps = sctp->sctp_sctps; 213 econnp = eager->sctp_connp; 214 215 if (connp->conn_policy != NULL) { 216 ipsec_in_t *ii; 217 218 ASSERT(ipsec_mp != NULL); 219 ii = (ipsec_in_t *)(ipsec_mp->b_rptr); 220 ASSERT(ii->ipsec_in_policy == NULL); 221 IPPH_REFHOLD(connp->conn_policy); 222 ii->ipsec_in_policy = connp->conn_policy; 223 224 ipsec_mp->b_datap->db_type = IPSEC_POLICY_SET; 225 if (!ip_bind_ipsec_policy_set(econnp, ipsec_mp)) { 226 sctp_close_eager(eager); 227 BUMP_MIB(&sctps->sctps_mib, sctpListenDrop); 228 return (NULL); 229 } 230 } 231 232 if (ipsec_mp != NULL) { 233 /* 234 * XXX need to fix the cached policy issue here. 235 * We temporarily set the conn_src/conn_rem here so 236 * that IPsec can use it for the latched policy 237 * selector. This is obvioursly wrong as SCTP can 238 * use different addresses... 239 */ 240 if (ipvers == IPV4_VERSION) { 241 ipha_t *ipha; 242 243 ipha = (ipha_t *)mp->b_rptr; 244 econnp->conn_src = ipha->ipha_dst; 245 econnp->conn_rem = ipha->ipha_src; 246 } else { 247 econnp->conn_srcv6 = ip6h->ip6_dst; 248 econnp->conn_remv6 = ip6h->ip6_src; 249 } 250 } 251 if (ipsec_conn_cache_policy(econnp, ipvers == IPV4_VERSION) != 0) { 252 sctp_close_eager(eager); 253 BUMP_MIB(&sctps->sctps_mib, sctpListenDrop); 254 return (NULL); 255 } 256 257 /* Save for getpeerucred */ 258 cr = msg_getcred(mp, &cpid); 259 260 err = sctp_accept_comm(sctp, eager, mp, ip_hdr_len, iack); 261 if (err) { 262 sctp_close_eager(eager); 263 BUMP_MIB(&sctps->sctps_mib, sctpListenDrop); 264 return (NULL); 265 } 266 267 /* 268 * On a clustered note send this notification to the clustering 269 * subsystem. 270 */ 271 if (cl_sctp_connect != NULL) { 272 uchar_t *slist; 273 uchar_t *flist; 274 size_t fsize; 275 size_t ssize; 276 277 fsize = sizeof (in6_addr_t) * eager->sctp_nfaddrs; 278 ssize = sizeof (in6_addr_t) * eager->sctp_nsaddrs; 279 slist = kmem_alloc(ssize, KM_NOSLEEP); 280 flist = kmem_alloc(fsize, KM_NOSLEEP); 281 if (slist == NULL || flist == NULL) { 282 if (slist != NULL) 283 kmem_free(slist, ssize); 284 if (flist != NULL) 285 kmem_free(flist, fsize); 286 sctp_close_eager(eager); 287 BUMP_MIB(&sctps->sctps_mib, sctpListenDrop); 288 SCTP_KSTAT(sctps, sctp_cl_connect); 289 return (NULL); 290 } 291 /* The clustering module frees these list */ 292 sctp_get_saddr_list(eager, slist, ssize); 293 sctp_get_faddr_list(eager, flist, fsize); 294 (*cl_sctp_connect)(eager->sctp_family, slist, 295 eager->sctp_nsaddrs, eager->sctp_lport, flist, 296 eager->sctp_nfaddrs, eager->sctp_fport, B_FALSE, 297 (cl_sctp_handle_t)eager); 298 } 299 300 /* Connection established, so send up the conn_ind */ 301 if ((eager->sctp_ulpd = sctp->sctp_ulp_newconn(sctp->sctp_ulpd, 302 (sock_lower_handle_t)eager, NULL, cr, cpid, 303 &eager->sctp_upcalls)) == NULL) { 304 sctp_close_eager(eager); 305 BUMP_MIB(&sctps->sctps_mib, sctpListenDrop); 306 return (NULL); 307 } 308 ASSERT(SCTP_IS_DETACHED(eager)); 309 eager->sctp_detached = B_FALSE; 310 bzero(&sopp, sizeof (sopp)); 311 sopp.sopp_flags = SOCKOPT_MAXBLK|SOCKOPT_WROFF; 312 sopp.sopp_maxblk = strmsgsz; 313 if (eager->sctp_family == AF_INET) { 314 sopp.sopp_wroff = sctps->sctps_wroff_xtra + 315 sizeof (sctp_data_hdr_t) + sctp->sctp_hdr_len; 316 } else { 317 sopp.sopp_wroff = sctps->sctps_wroff_xtra + 318 sizeof (sctp_data_hdr_t) + sctp->sctp_hdr6_len; 319 } 320 eager->sctp_ulp_prop(eager->sctp_ulpd, &sopp); 321 return (eager); 322 } 323 324 /* 325 * Connect to a peer - this function inserts the sctp in the 326 * bind and conn fanouts, sends the INIT, and replies to the client 327 * with an OK ack. 328 */ 329 int 330 sctp_connect(sctp_t *sctp, const struct sockaddr *dst, uint32_t addrlen) 331 { 332 sin_t *sin; 333 sin6_t *sin6; 334 in6_addr_t dstaddr; 335 in_port_t dstport; 336 mblk_t *initmp; 337 sctp_tf_t *tbf; 338 sctp_t *lsctp; 339 char buf[INET6_ADDRSTRLEN]; 340 int sleep = sctp->sctp_cansleep ? KM_SLEEP : KM_NOSLEEP; 341 int hdrlen; 342 ip6_rthdr_t *rth; 343 int err; 344 sctp_faddr_t *cur_fp; 345 sctp_stack_t *sctps = sctp->sctp_sctps; 346 struct sock_proto_props sopp; 347 348 /* 349 * Determine packet type based on type of address passed in 350 * the request should contain an IPv4 or IPv6 address. 351 * Make sure that address family matches the type of 352 * family of the the address passed down 353 */ 354 if (addrlen < sizeof (sin_t)) { 355 return (EINVAL); 356 } 357 switch (dst->sa_family) { 358 case AF_INET: 359 sin = (sin_t *)dst; 360 361 /* Check for attempt to connect to non-unicast */ 362 if (CLASSD(sin->sin_addr.s_addr) || 363 (sin->sin_addr.s_addr == INADDR_BROADCAST)) { 364 ip0dbg(("sctp_connect: non-unicast\n")); 365 return (EINVAL); 366 } 367 if (sctp->sctp_connp->conn_ipv6_v6only) 368 return (EAFNOSUPPORT); 369 370 /* convert to v6 mapped */ 371 /* Check for attempt to connect to INADDR_ANY */ 372 if (sin->sin_addr.s_addr == INADDR_ANY) { 373 struct in_addr v4_addr; 374 /* 375 * SunOS 4.x and 4.3 BSD allow an application 376 * to connect a TCP socket to INADDR_ANY. 377 * When they do this, the kernel picks the 378 * address of one interface and uses it 379 * instead. The kernel usually ends up 380 * picking the address of the loopback 381 * interface. This is an undocumented feature. 382 * However, we provide the same thing here 383 * in case any TCP apps that use this feature 384 * are being ported to SCTP... 385 */ 386 v4_addr.s_addr = htonl(INADDR_LOOPBACK); 387 IN6_INADDR_TO_V4MAPPED(&v4_addr, &dstaddr); 388 } else { 389 IN6_INADDR_TO_V4MAPPED(&sin->sin_addr, &dstaddr); 390 } 391 dstport = sin->sin_port; 392 if (sin->sin_family == AF_INET) { 393 hdrlen = sctp->sctp_hdr_len; 394 } else { 395 hdrlen = sctp->sctp_hdr6_len; 396 } 397 break; 398 case AF_INET6: 399 sin6 = (sin6_t *)dst; 400 /* Check for attempt to connect to non-unicast. */ 401 if ((addrlen < sizeof (sin6_t)) || 402 IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { 403 ip0dbg(("sctp_connect: non-unicast\n")); 404 return (EINVAL); 405 } 406 if (sctp->sctp_connp->conn_ipv6_v6only && 407 IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 408 return (EAFNOSUPPORT); 409 } 410 /* check for attempt to connect to unspec */ 411 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 412 dstaddr = ipv6_loopback; 413 } else { 414 dstaddr = sin6->sin6_addr; 415 if (IN6_IS_ADDR_LINKLOCAL(&dstaddr)) 416 sctp->sctp_linklocal = 1; 417 } 418 dstport = sin6->sin6_port; 419 hdrlen = sctp->sctp_hdr6_len; 420 break; 421 default: 422 dprint(1, ("sctp_connect: unknown family %d\n", 423 dst->sa_family)); 424 return (EAFNOSUPPORT); 425 } 426 427 (void) inet_ntop(AF_INET6, &dstaddr, buf, sizeof (buf)); 428 dprint(1, ("sctp_connect: attempting connect to %s...\n", buf)); 429 430 RUN_SCTP(sctp); 431 432 if (sctp->sctp_family != dst->sa_family || 433 (sctp->sctp_connp->conn_state_flags & CONN_CLOSING)) { 434 WAKE_SCTP(sctp); 435 return (EINVAL); 436 } 437 438 switch (sctp->sctp_state) { 439 case SCTPS_IDLE: { 440 struct sockaddr_storage ss; 441 442 /* 443 * We support a quick connect capability here, allowing 444 * clients to transition directly from IDLE to COOKIE_WAIT. 445 * sctp_bindi will pick an unused port, insert the connection 446 * in the bind hash and transition to BOUND state. SCTP 447 * picks and uses what it considers the optimal local address 448 * set (just like specifiying INADDR_ANY to bind()). 449 */ 450 dprint(1, ("sctp_connect: idle, attempting bind...\n")); 451 ASSERT(sctp->sctp_nsaddrs == 0); 452 453 bzero(&ss, sizeof (ss)); 454 ss.ss_family = sctp->sctp_family; 455 WAKE_SCTP(sctp); 456 if ((err = sctp_bind(sctp, (struct sockaddr *)&ss, 457 sizeof (ss))) != 0) { 458 return (err); 459 } 460 RUN_SCTP(sctp); 461 /* FALLTHRU */ 462 } 463 464 case SCTPS_BOUND: 465 ASSERT(sctp->sctp_nsaddrs > 0); 466 467 /* do the connect */ 468 /* XXX check for attempt to connect to self */ 469 sctp->sctp_fport = dstport; 470 471 ASSERT(sctp->sctp_iphc); 472 ASSERT(sctp->sctp_iphc6); 473 474 /* 475 * Don't allow this connection to completely duplicate 476 * an existing connection. 477 * 478 * Ensure that the duplicate check and insertion is atomic. 479 */ 480 sctp_conn_hash_remove(sctp); 481 tbf = &sctps->sctps_conn_fanout[SCTP_CONN_HASH(sctps, 482 sctp->sctp_ports)]; 483 mutex_enter(&tbf->tf_lock); 484 lsctp = sctp_lookup(sctp, &dstaddr, tbf, &sctp->sctp_ports, 485 SCTPS_COOKIE_WAIT); 486 if (lsctp != NULL) { 487 /* found a duplicate connection */ 488 mutex_exit(&tbf->tf_lock); 489 SCTP_REFRELE(lsctp); 490 WAKE_SCTP(sctp); 491 return (EADDRINUSE); 492 } 493 /* 494 * OK; set up the peer addr (this may grow after we get 495 * the INIT ACK from the peer with additional addresses). 496 */ 497 if ((err = sctp_add_faddr(sctp, &dstaddr, sleep, 498 B_FALSE)) != 0) { 499 mutex_exit(&tbf->tf_lock); 500 WAKE_SCTP(sctp); 501 return (err); 502 } 503 cur_fp = sctp->sctp_faddrs; 504 505 /* No valid src addr, return. */ 506 if (cur_fp->state == SCTP_FADDRS_UNREACH) { 507 mutex_exit(&tbf->tf_lock); 508 WAKE_SCTP(sctp); 509 return (EADDRNOTAVAIL); 510 } 511 512 sctp->sctp_primary = cur_fp; 513 sctp->sctp_current = cur_fp; 514 sctp->sctp_mss = cur_fp->sfa_pmss; 515 sctp_conn_hash_insert(tbf, sctp, 1); 516 mutex_exit(&tbf->tf_lock); 517 518 /* initialize composite headers */ 519 if ((err = sctp_set_hdraddrs(sctp)) != 0) { 520 sctp_conn_hash_remove(sctp); 521 WAKE_SCTP(sctp); 522 return (err); 523 } 524 525 /* 526 * Massage a routing header (if present) putting the first hop 527 * in ip6_dst. 528 */ 529 rth = ip_find_rthdr_v6(sctp->sctp_ip6h, 530 (uint8_t *)sctp->sctp_sctph6); 531 if (rth != NULL) { 532 (void) ip_massage_options_v6(sctp->sctp_ip6h, rth, 533 sctps->sctps_netstack); 534 } 535 536 /* 537 * Turn off the don't fragment bit on the (only) faddr, 538 * so that if one of the messages exchanged during the 539 * initialization sequence exceeds the path mtu, it 540 * at least has a chance to get there. SCTP does no 541 * fragmentation of initialization messages. The DF bit 542 * will be turned on again in sctp_send_cookie_echo() 543 * (but the cookie echo will still be sent with the df bit 544 * off). 545 */ 546 cur_fp->df = B_FALSE; 547 548 /* Mark this address as alive */ 549 cur_fp->state = SCTP_FADDRS_ALIVE; 550 551 /* This sctp_t is fully bound now. */ 552 sctp->sctp_connp->conn_fully_bound = B_TRUE; 553 554 /* Send the INIT to the peer */ 555 SCTP_FADDR_TIMER_RESTART(sctp, cur_fp, cur_fp->rto); 556 sctp->sctp_state = SCTPS_COOKIE_WAIT; 557 /* 558 * sctp_init_mp() could result in modifying the source 559 * address list, so take the hash lock. 560 */ 561 mutex_enter(&tbf->tf_lock); 562 initmp = sctp_init_mp(sctp); 563 if (initmp == NULL) { 564 mutex_exit(&tbf->tf_lock); 565 /* 566 * It may happen that all the source addresses 567 * (loopback/link local) are removed. In that case, 568 * faile the connect. 569 */ 570 if (sctp->sctp_nsaddrs == 0) { 571 sctp_conn_hash_remove(sctp); 572 SCTP_FADDR_TIMER_STOP(cur_fp); 573 WAKE_SCTP(sctp); 574 return (EADDRNOTAVAIL); 575 } 576 577 /* Otherwise, let the retransmission timer retry */ 578 WAKE_SCTP(sctp); 579 goto notify_ulp; 580 } 581 mutex_exit(&tbf->tf_lock); 582 583 /* 584 * On a clustered note send this notification to the clustering 585 * subsystem. 586 */ 587 if (cl_sctp_connect != NULL) { 588 uchar_t *slist; 589 uchar_t *flist; 590 size_t ssize; 591 size_t fsize; 592 593 fsize = sizeof (in6_addr_t) * sctp->sctp_nfaddrs; 594 ssize = sizeof (in6_addr_t) * sctp->sctp_nsaddrs; 595 slist = kmem_alloc(ssize, KM_SLEEP); 596 flist = kmem_alloc(fsize, KM_SLEEP); 597 /* The clustering module frees the lists */ 598 sctp_get_saddr_list(sctp, slist, ssize); 599 sctp_get_faddr_list(sctp, flist, fsize); 600 (*cl_sctp_connect)(sctp->sctp_family, slist, 601 sctp->sctp_nsaddrs, sctp->sctp_lport, 602 flist, sctp->sctp_nfaddrs, sctp->sctp_fport, 603 B_TRUE, (cl_sctp_handle_t)sctp); 604 } 605 WAKE_SCTP(sctp); 606 /* OK to call IP_PUT() here instead of sctp_add_sendq(). */ 607 CONN_INC_REF(sctp->sctp_connp); 608 initmp->b_flag |= MSGHASREF; 609 IP_PUT(initmp, sctp->sctp_connp, sctp->sctp_current->isv4); 610 BUMP_LOCAL(sctp->sctp_opkts); 611 612 notify_ulp: 613 bzero(&sopp, sizeof (sopp)); 614 sopp.sopp_flags = SOCKOPT_WROFF; 615 sopp.sopp_wroff = sctps->sctps_wroff_xtra + hdrlen + 616 sizeof (sctp_data_hdr_t); 617 sctp->sctp_ulp_prop(sctp->sctp_ulpd, &sopp); 618 619 return (0); 620 default: 621 ip0dbg(("sctp_connect: invalid state. %d\n", sctp->sctp_state)); 622 WAKE_SCTP(sctp); 623 return (EINVAL); 624 } 625 } 626