1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <sys/types.h> 30*0Sstevel@tonic-gate #include <sys/systm.h> 31*0Sstevel@tonic-gate #include <sys/stream.h> 32*0Sstevel@tonic-gate #include <sys/cmn_err.h> 33*0Sstevel@tonic-gate #include <sys/kmem.h> 34*0Sstevel@tonic-gate #define _SUN_TPI_VERSION 2 35*0Sstevel@tonic-gate #include <sys/tihdr.h> 36*0Sstevel@tonic-gate #include <sys/stropts.h> 37*0Sstevel@tonic-gate #include <sys/strsubr.h> 38*0Sstevel@tonic-gate #include <sys/socket.h> 39*0Sstevel@tonic-gate 40*0Sstevel@tonic-gate #include <netinet/in.h> 41*0Sstevel@tonic-gate #include <netinet/ip6.h> 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate #include <inet/common.h> 44*0Sstevel@tonic-gate #include <inet/ip.h> 45*0Sstevel@tonic-gate #include <inet/ip6.h> 46*0Sstevel@tonic-gate #include <inet/ipclassifier.h> 47*0Sstevel@tonic-gate #include <inet/ipsec_impl.h> 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate #include "sctp_impl.h" 50*0Sstevel@tonic-gate #include "sctp_addr.h" 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate /* 53*0Sstevel@tonic-gate * Common accept code. Called by sctp_conn_request. 54*0Sstevel@tonic-gate * cr_pkt is the INIT / INIT ACK packet. 55*0Sstevel@tonic-gate */ 56*0Sstevel@tonic-gate static int 57*0Sstevel@tonic-gate sctp_accept_comm(sctp_t *listener, sctp_t *acceptor, mblk_t *cr_pkt, 58*0Sstevel@tonic-gate uint_t ip_hdr_len, sctp_init_chunk_t *iack) 59*0Sstevel@tonic-gate { 60*0Sstevel@tonic-gate 61*0Sstevel@tonic-gate sctp_hdr_t *sctph; 62*0Sstevel@tonic-gate sctp_chunk_hdr_t *ich; 63*0Sstevel@tonic-gate sctp_init_chunk_t *init; 64*0Sstevel@tonic-gate int err; 65*0Sstevel@tonic-gate uint_t sctp_options; 66*0Sstevel@tonic-gate 67*0Sstevel@tonic-gate sctph = (sctp_hdr_t *)(cr_pkt->b_rptr + ip_hdr_len); 68*0Sstevel@tonic-gate ASSERT(OK_32PTR(sctph)); 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate acceptor->sctp_lport = listener->sctp_lport; 71*0Sstevel@tonic-gate acceptor->sctp_fport = sctph->sh_sport; 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate ich = (sctp_chunk_hdr_t *)(iack + 1); 74*0Sstevel@tonic-gate init = (sctp_init_chunk_t *)(ich + 1); 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate /* acceptor isn't in any fanouts yet, so don't need to hold locks */ 77*0Sstevel@tonic-gate ASSERT(acceptor->sctp_faddrs == NULL); 78*0Sstevel@tonic-gate err = sctp_get_addrparams(acceptor, listener, cr_pkt, ich, 79*0Sstevel@tonic-gate &sctp_options); 80*0Sstevel@tonic-gate if (err != 0) 81*0Sstevel@tonic-gate return (err); 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gate if ((sctp_options & SCTP_PRSCTP_OPTION) && 84*0Sstevel@tonic-gate listener->sctp_prsctp_aware && sctp_prsctp_enabled) { 85*0Sstevel@tonic-gate acceptor->sctp_prsctp_aware = B_TRUE; 86*0Sstevel@tonic-gate } else { 87*0Sstevel@tonic-gate acceptor->sctp_prsctp_aware = B_FALSE; 88*0Sstevel@tonic-gate } 89*0Sstevel@tonic-gate /* The new sctp_t is fully bound now. */ 90*0Sstevel@tonic-gate acceptor->sctp_connp->conn_fully_bound = B_TRUE; 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate sctp_set_hdraddrs(acceptor); 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate /* Get initial TSNs */ 95*0Sstevel@tonic-gate acceptor->sctp_ltsn = ntohl(iack->sic_inittsn); 96*0Sstevel@tonic-gate acceptor->sctp_recovery_tsn = acceptor->sctp_lastack_rxd = 97*0Sstevel@tonic-gate acceptor->sctp_ltsn - 1; 98*0Sstevel@tonic-gate acceptor->sctp_adv_pap = acceptor->sctp_lastack_rxd; 99*0Sstevel@tonic-gate /* Serial numbers are initialized to the same value as the TSNs */ 100*0Sstevel@tonic-gate acceptor->sctp_lcsn = acceptor->sctp_ltsn; 101*0Sstevel@tonic-gate 102*0Sstevel@tonic-gate if (!sctp_initialize_params(acceptor, init, iack)) 103*0Sstevel@tonic-gate return (ENOMEM); 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate /* 106*0Sstevel@tonic-gate * Copy sctp_secret from the listener in case we need to validate 107*0Sstevel@tonic-gate * a possibly delayed cookie. 108*0Sstevel@tonic-gate */ 109*0Sstevel@tonic-gate bcopy(listener->sctp_secret, acceptor->sctp_secret, SCTP_SECRET_LEN); 110*0Sstevel@tonic-gate bcopy(listener->sctp_old_secret, acceptor->sctp_old_secret, 111*0Sstevel@tonic-gate SCTP_SECRET_LEN); 112*0Sstevel@tonic-gate acceptor->sctp_last_secret_update = lbolt64; 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gate /* 115*0Sstevel@tonic-gate * After acceptor is inserted in the hash list, it can be found. 116*0Sstevel@tonic-gate * So we need to lock it here. 117*0Sstevel@tonic-gate */ 118*0Sstevel@tonic-gate RUN_SCTP(acceptor); 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate sctp_conn_hash_insert(&sctp_conn_fanout[ 121*0Sstevel@tonic-gate SCTP_CONN_HASH(acceptor->sctp_ports)], acceptor, 0); 122*0Sstevel@tonic-gate sctp_bind_hash_insert(&sctp_bind_fanout[ 123*0Sstevel@tonic-gate SCTP_BIND_HASH(ntohs(acceptor->sctp_lport))], acceptor, 0); 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate /* 126*0Sstevel@tonic-gate * No need to check for multicast destination since ip will only pass 127*0Sstevel@tonic-gate * up multicasts to those that have expressed interest 128*0Sstevel@tonic-gate * TODO: what about rejecting broadcasts? 129*0Sstevel@tonic-gate * Also check that source is not a multicast or broadcast address. 130*0Sstevel@tonic-gate */ 131*0Sstevel@tonic-gate /* XXXSCTP */ 132*0Sstevel@tonic-gate acceptor->sctp_state = SCTPS_ESTABLISHED; 133*0Sstevel@tonic-gate acceptor->sctp_assoc_start_time = (uint32_t)lbolt; 134*0Sstevel@tonic-gate /* 135*0Sstevel@tonic-gate * listener->sctp_rwnd should be the default window size or a 136*0Sstevel@tonic-gate * window size changed via SO_RCVBUF option. 137*0Sstevel@tonic-gate */ 138*0Sstevel@tonic-gate acceptor->sctp_rwnd = MSS_ROUNDUP(listener->sctp_rwnd, 139*0Sstevel@tonic-gate (acceptor->sctp_mss - sizeof (sctp_data_hdr_t))); 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate bcopy(&listener->sctp_upcalls, &acceptor->sctp_upcalls, 142*0Sstevel@tonic-gate sizeof (sctp_upcalls_t)); 143*0Sstevel@tonic-gate 144*0Sstevel@tonic-gate return (0); 145*0Sstevel@tonic-gate } 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate /* Process the COOKIE packet, mp, directed at the listener 'sctp' */ 148*0Sstevel@tonic-gate sctp_t * 149*0Sstevel@tonic-gate sctp_conn_request(sctp_t *sctp, mblk_t *mp, uint_t ifindex, uint_t ip_hdr_len, 150*0Sstevel@tonic-gate sctp_init_chunk_t *iack, mblk_t *ipsec_mp) 151*0Sstevel@tonic-gate { 152*0Sstevel@tonic-gate sctp_t *eager; 153*0Sstevel@tonic-gate uint_t ipvers; 154*0Sstevel@tonic-gate ip6_t *ip6h; 155*0Sstevel@tonic-gate int err; 156*0Sstevel@tonic-gate conn_t *connp, *econnp; 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gate /* 159*0Sstevel@tonic-gate * No need to check for duplicate as this is the listener 160*0Sstevel@tonic-gate * and we are holding the lock. This means that no new 161*0Sstevel@tonic-gate * connection can be created out of it. And since the 162*0Sstevel@tonic-gate * fanout already done cannot find a match, it means that 163*0Sstevel@tonic-gate * there is no duplicate. 164*0Sstevel@tonic-gate */ 165*0Sstevel@tonic-gate ipvers = IPH_HDR_VERSION(mp->b_rptr); 166*0Sstevel@tonic-gate ASSERT(ipvers == IPV6_VERSION || ipvers == IPV4_VERSION); 167*0Sstevel@tonic-gate ASSERT(OK_32PTR(mp->b_rptr)); 168*0Sstevel@tonic-gate 169*0Sstevel@tonic-gate if ((eager = sctp_create_eager(sctp)) == NULL) { 170*0Sstevel@tonic-gate return (NULL); 171*0Sstevel@tonic-gate } 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate if (ipvers != IPV4_VERSION) { 174*0Sstevel@tonic-gate ip6h = (ip6_t *)mp->b_rptr; 175*0Sstevel@tonic-gate /* 176*0Sstevel@tonic-gate * Record ifindex (might be zero) to tie this connection to 177*0Sstevel@tonic-gate * that interface if either the listener was bound or 178*0Sstevel@tonic-gate * if the connection is using link-local addresses. 179*0Sstevel@tonic-gate */ 180*0Sstevel@tonic-gate if (sctp->sctp_bound_if == ifindex || 181*0Sstevel@tonic-gate IN6_IS_ADDR_LINKLOCAL(&ip6h->ip6_src)) 182*0Sstevel@tonic-gate eager->sctp_bound_if = ifindex; 183*0Sstevel@tonic-gate /* 184*0Sstevel@tonic-gate * XXX broken. bound_if is always overwritten by statement 185*0Sstevel@tonic-gate * below. What is the right thing to do here? 186*0Sstevel@tonic-gate */ 187*0Sstevel@tonic-gate eager->sctp_bound_if = sctp->sctp_bound_if; 188*0Sstevel@tonic-gate } 189*0Sstevel@tonic-gate 190*0Sstevel@tonic-gate connp = sctp->sctp_connp; 191*0Sstevel@tonic-gate econnp = eager->sctp_connp; 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gate if (connp->conn_policy != NULL) { 194*0Sstevel@tonic-gate ipsec_in_t *ii; 195*0Sstevel@tonic-gate 196*0Sstevel@tonic-gate ASSERT(ipsec_mp != NULL); 197*0Sstevel@tonic-gate ii = (ipsec_in_t *)(ipsec_mp->b_rptr); 198*0Sstevel@tonic-gate ASSERT(ii->ipsec_in_policy == NULL); 199*0Sstevel@tonic-gate IPPH_REFHOLD(connp->conn_policy); 200*0Sstevel@tonic-gate ii->ipsec_in_policy = connp->conn_policy; 201*0Sstevel@tonic-gate 202*0Sstevel@tonic-gate ipsec_mp->b_datap->db_type = IPSEC_POLICY_SET; 203*0Sstevel@tonic-gate if (!ip_bind_ipsec_policy_set(econnp, ipsec_mp)) { 204*0Sstevel@tonic-gate sctp_close_eager(eager); 205*0Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpListenDrop); 206*0Sstevel@tonic-gate return (NULL); 207*0Sstevel@tonic-gate } 208*0Sstevel@tonic-gate } 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate if (ipsec_mp != NULL) { 211*0Sstevel@tonic-gate /* 212*0Sstevel@tonic-gate * XXX need to fix the cached policy issue here. 213*0Sstevel@tonic-gate * We temporarily set the conn_src/conn_rem here so 214*0Sstevel@tonic-gate * that IPsec can use it for the latched policy 215*0Sstevel@tonic-gate * selector. This is obvioursly wrong as SCTP can 216*0Sstevel@tonic-gate * use different addresses... 217*0Sstevel@tonic-gate */ 218*0Sstevel@tonic-gate if (ipvers == IPV4_VERSION) { 219*0Sstevel@tonic-gate ipha_t *ipha; 220*0Sstevel@tonic-gate 221*0Sstevel@tonic-gate ipha = (ipha_t *)mp->b_rptr; 222*0Sstevel@tonic-gate econnp->conn_src = ipha->ipha_dst; 223*0Sstevel@tonic-gate econnp->conn_rem = ipha->ipha_src; 224*0Sstevel@tonic-gate } else { 225*0Sstevel@tonic-gate econnp->conn_srcv6 = ip6h->ip6_dst; 226*0Sstevel@tonic-gate econnp->conn_remv6 = ip6h->ip6_src; 227*0Sstevel@tonic-gate } 228*0Sstevel@tonic-gate } 229*0Sstevel@tonic-gate if (ipsec_conn_cache_policy(econnp, ipvers == IPV4_VERSION) != 0) { 230*0Sstevel@tonic-gate sctp_close_eager(eager); 231*0Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpListenDrop); 232*0Sstevel@tonic-gate return (NULL); 233*0Sstevel@tonic-gate } 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate err = sctp_accept_comm(sctp, eager, mp, ip_hdr_len, iack); 236*0Sstevel@tonic-gate if (err) { 237*0Sstevel@tonic-gate sctp_close_eager(eager); 238*0Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpListenDrop); 239*0Sstevel@tonic-gate return (NULL); 240*0Sstevel@tonic-gate } 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate /* Connection established, so send up the conn_ind */ 243*0Sstevel@tonic-gate if ((eager->sctp_ulpd = sctp->sctp_ulp_newconn(sctp->sctp_ulpd, 244*0Sstevel@tonic-gate eager)) == NULL) { 245*0Sstevel@tonic-gate sctp_close_eager(eager); 246*0Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpListenDrop); 247*0Sstevel@tonic-gate return (NULL); 248*0Sstevel@tonic-gate } 249*0Sstevel@tonic-gate ASSERT(SCTP_IS_DETACHED(eager)); 250*0Sstevel@tonic-gate eager->sctp_detached = B_FALSE; 251*0Sstevel@tonic-gate if (eager->sctp_family == AF_INET) { 252*0Sstevel@tonic-gate eager->sctp_ulp_prop(eager->sctp_ulpd, 253*0Sstevel@tonic-gate sctp_wroff_xtra + sizeof (sctp_data_hdr_t) + 254*0Sstevel@tonic-gate sctp->sctp_hdr_len, strmsgsz); 255*0Sstevel@tonic-gate } else { 256*0Sstevel@tonic-gate eager->sctp_ulp_prop(eager->sctp_ulpd, 257*0Sstevel@tonic-gate sctp_wroff_xtra + sizeof (sctp_data_hdr_t) + 258*0Sstevel@tonic-gate sctp->sctp_hdr6_len, strmsgsz); 259*0Sstevel@tonic-gate } 260*0Sstevel@tonic-gate return (eager); 261*0Sstevel@tonic-gate } 262*0Sstevel@tonic-gate 263*0Sstevel@tonic-gate /* 264*0Sstevel@tonic-gate * Connect to a peer - this function inserts the sctp in the 265*0Sstevel@tonic-gate * bind and conn fanouts, sends the INIT, and replies to the client 266*0Sstevel@tonic-gate * with an OK ack. 267*0Sstevel@tonic-gate */ 268*0Sstevel@tonic-gate /* ARGSUSED */ 269*0Sstevel@tonic-gate int 270*0Sstevel@tonic-gate sctp_connect(sctp_t *sctp, const struct sockaddr *dst, uint32_t addrlen) 271*0Sstevel@tonic-gate { 272*0Sstevel@tonic-gate sin_t *sin; 273*0Sstevel@tonic-gate sin6_t *sin6; 274*0Sstevel@tonic-gate in_port_t lport; 275*0Sstevel@tonic-gate in6_addr_t dstaddr; 276*0Sstevel@tonic-gate in_port_t dstport; 277*0Sstevel@tonic-gate mblk_t *initmp; 278*0Sstevel@tonic-gate sctp_tf_t *tbf; 279*0Sstevel@tonic-gate sctp_t *lsctp; 280*0Sstevel@tonic-gate char buf[INET6_ADDRSTRLEN]; 281*0Sstevel@tonic-gate int sleep = sctp->sctp_cansleep ? KM_SLEEP : KM_NOSLEEP; 282*0Sstevel@tonic-gate int hdrlen; 283*0Sstevel@tonic-gate ip6_rthdr_t *rth; 284*0Sstevel@tonic-gate sctp_faddr_t *cur_fp; 285*0Sstevel@tonic-gate 286*0Sstevel@tonic-gate /* 287*0Sstevel@tonic-gate * Determine packet type based on type of address passed in 288*0Sstevel@tonic-gate * the request should contain an IPv4 or IPv6 address. 289*0Sstevel@tonic-gate * Make sure that address family matches the type of 290*0Sstevel@tonic-gate * family of the the address passed down 291*0Sstevel@tonic-gate */ 292*0Sstevel@tonic-gate if (addrlen < sizeof (sin_t)) { 293*0Sstevel@tonic-gate return (EINVAL); 294*0Sstevel@tonic-gate } 295*0Sstevel@tonic-gate switch (dst->sa_family) { 296*0Sstevel@tonic-gate case AF_INET: 297*0Sstevel@tonic-gate sin = (sin_t *)dst; 298*0Sstevel@tonic-gate 299*0Sstevel@tonic-gate /* Check for attempt to connect to non-unicast */ 300*0Sstevel@tonic-gate if (IN_MULTICAST(sin->sin_addr.s_addr) || 301*0Sstevel@tonic-gate (sin->sin_addr.s_addr == INADDR_BROADCAST)) { 302*0Sstevel@tonic-gate ip0dbg(("sctp_connect: non-unicast\n")); 303*0Sstevel@tonic-gate return (EINVAL); 304*0Sstevel@tonic-gate } 305*0Sstevel@tonic-gate if (sctp->sctp_connp->conn_ipv6_v6only) 306*0Sstevel@tonic-gate return (EAFNOSUPPORT); 307*0Sstevel@tonic-gate 308*0Sstevel@tonic-gate /* convert to v6 mapped */ 309*0Sstevel@tonic-gate /* Check for attempt to connect to INADDR_ANY */ 310*0Sstevel@tonic-gate if (sin->sin_addr.s_addr == INADDR_ANY) { 311*0Sstevel@tonic-gate struct in_addr v4_addr; 312*0Sstevel@tonic-gate /* 313*0Sstevel@tonic-gate * SunOS 4.x and 4.3 BSD allow an application 314*0Sstevel@tonic-gate * to connect a TCP socket to INADDR_ANY. 315*0Sstevel@tonic-gate * When they do this, the kernel picks the 316*0Sstevel@tonic-gate * address of one interface and uses it 317*0Sstevel@tonic-gate * instead. The kernel usually ends up 318*0Sstevel@tonic-gate * picking the address of the loopback 319*0Sstevel@tonic-gate * interface. This is an undocumented feature. 320*0Sstevel@tonic-gate * However, we provide the same thing here 321*0Sstevel@tonic-gate * in case any TCP apps that use this feature 322*0Sstevel@tonic-gate * are being ported to SCTP... 323*0Sstevel@tonic-gate */ 324*0Sstevel@tonic-gate v4_addr.s_addr = htonl(INADDR_LOOPBACK); 325*0Sstevel@tonic-gate IN6_INADDR_TO_V4MAPPED(&v4_addr, &dstaddr); 326*0Sstevel@tonic-gate } else { 327*0Sstevel@tonic-gate IN6_INADDR_TO_V4MAPPED(&sin->sin_addr, &dstaddr); 328*0Sstevel@tonic-gate } 329*0Sstevel@tonic-gate dstport = sin->sin_port; 330*0Sstevel@tonic-gate if (sin->sin_family == AF_INET) { 331*0Sstevel@tonic-gate hdrlen = sctp->sctp_hdr_len; 332*0Sstevel@tonic-gate } else { 333*0Sstevel@tonic-gate hdrlen = sctp->sctp_hdr6_len; 334*0Sstevel@tonic-gate } 335*0Sstevel@tonic-gate break; 336*0Sstevel@tonic-gate case AF_INET6: 337*0Sstevel@tonic-gate sin6 = (sin6_t *)dst; 338*0Sstevel@tonic-gate /* Check for attempt to connect to non-unicast. */ 339*0Sstevel@tonic-gate if ((addrlen < sizeof (sin6_t)) || 340*0Sstevel@tonic-gate IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { 341*0Sstevel@tonic-gate ip0dbg(("sctp_connect: non-unicast\n")); 342*0Sstevel@tonic-gate return (EINVAL); 343*0Sstevel@tonic-gate } 344*0Sstevel@tonic-gate if (sctp->sctp_connp->conn_ipv6_v6only && 345*0Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 346*0Sstevel@tonic-gate return (EAFNOSUPPORT); 347*0Sstevel@tonic-gate } 348*0Sstevel@tonic-gate /* check for attempt to connect to unspec */ 349*0Sstevel@tonic-gate if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 350*0Sstevel@tonic-gate dstaddr = ipv6_loopback; 351*0Sstevel@tonic-gate } else { 352*0Sstevel@tonic-gate dstaddr = sin6->sin6_addr; 353*0Sstevel@tonic-gate } 354*0Sstevel@tonic-gate dstport = sin6->sin6_port; 355*0Sstevel@tonic-gate hdrlen = sctp->sctp_hdr6_len; 356*0Sstevel@tonic-gate break; 357*0Sstevel@tonic-gate default: 358*0Sstevel@tonic-gate dprint(1, ("sctp_connect: unknown family %d\n", 359*0Sstevel@tonic-gate dst->sa_family)); 360*0Sstevel@tonic-gate return (EAFNOSUPPORT); 361*0Sstevel@tonic-gate } 362*0Sstevel@tonic-gate 363*0Sstevel@tonic-gate (void) inet_ntop(AF_INET6, &dstaddr, buf, sizeof (buf)); 364*0Sstevel@tonic-gate dprint(1, ("sctp_connect: attempting connect to %s...\n", buf)); 365*0Sstevel@tonic-gate 366*0Sstevel@tonic-gate RUN_SCTP(sctp); 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate if (sctp->sctp_family != dst->sa_family) { 369*0Sstevel@tonic-gate WAKE_SCTP(sctp); 370*0Sstevel@tonic-gate return (EINVAL); 371*0Sstevel@tonic-gate } 372*0Sstevel@tonic-gate 373*0Sstevel@tonic-gate switch (sctp->sctp_state) { 374*0Sstevel@tonic-gate case SCTPS_IDLE: { 375*0Sstevel@tonic-gate int err; 376*0Sstevel@tonic-gate /* 377*0Sstevel@tonic-gate * We support a quick connect capability here, allowing 378*0Sstevel@tonic-gate * clients to transition directly from IDLE to COOKIE_WAIT. 379*0Sstevel@tonic-gate * sctp_bindi will pick an unused port, insert the connection 380*0Sstevel@tonic-gate * in the bind hash and transition to BOUND state. SCTP 381*0Sstevel@tonic-gate * picks and uses what it considers the optimal local address 382*0Sstevel@tonic-gate * set (just like specifiying INADDR_ANY to bind()). 383*0Sstevel@tonic-gate */ 384*0Sstevel@tonic-gate dprint(1, ("sctp_connect: idle, attempting bind...\n")); 385*0Sstevel@tonic-gate ASSERT(sctp->sctp_nsaddrs == 0); 386*0Sstevel@tonic-gate 387*0Sstevel@tonic-gate err = sctp_dup_saddrs(NULL, sctp, sleep); 388*0Sstevel@tonic-gate if (err != 0) { 389*0Sstevel@tonic-gate WAKE_SCTP(sctp); 390*0Sstevel@tonic-gate return (err); 391*0Sstevel@tonic-gate } 392*0Sstevel@tonic-gate lport = sctp_update_next_port(sctp_next_port_to_try); 393*0Sstevel@tonic-gate lport = sctp_bindi(sctp, lport, 0, 0); 394*0Sstevel@tonic-gate if (lport == 0) { 395*0Sstevel@tonic-gate WAKE_SCTP(sctp); 396*0Sstevel@tonic-gate sctp_free_saddrs(sctp); 397*0Sstevel@tonic-gate return (EADDRNOTAVAIL); 398*0Sstevel@tonic-gate } 399*0Sstevel@tonic-gate sctp->sctp_bound_to_all = 1; 400*0Sstevel@tonic-gate /* FALLTHRU */ 401*0Sstevel@tonic-gate } 402*0Sstevel@tonic-gate 403*0Sstevel@tonic-gate case SCTPS_BOUND: 404*0Sstevel@tonic-gate ASSERT(sctp->sctp_nsaddrs > 0); 405*0Sstevel@tonic-gate 406*0Sstevel@tonic-gate /* do the connect */ 407*0Sstevel@tonic-gate /* XXX check for attempt to connect to self */ 408*0Sstevel@tonic-gate sctp->sctp_fport = dstport; 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate ASSERT(sctp->sctp_iphc); 411*0Sstevel@tonic-gate ASSERT(sctp->sctp_iphc6); 412*0Sstevel@tonic-gate 413*0Sstevel@tonic-gate /* 414*0Sstevel@tonic-gate * Don't allow this connection to completely duplicate 415*0Sstevel@tonic-gate * an existing connection. 416*0Sstevel@tonic-gate * 417*0Sstevel@tonic-gate * Ensure that the duplicate check and insertion is atomic. 418*0Sstevel@tonic-gate */ 419*0Sstevel@tonic-gate sctp_conn_hash_remove(sctp); 420*0Sstevel@tonic-gate tbf = &sctp_conn_fanout[SCTP_CONN_HASH(sctp->sctp_ports)]; 421*0Sstevel@tonic-gate mutex_enter(&tbf->tf_lock); 422*0Sstevel@tonic-gate lsctp = sctp_lookup(sctp, &dstaddr, tbf, &sctp->sctp_ports, 423*0Sstevel@tonic-gate SCTPS_COOKIE_WAIT); 424*0Sstevel@tonic-gate if (lsctp != NULL) { 425*0Sstevel@tonic-gate /* found a duplicate connection */ 426*0Sstevel@tonic-gate mutex_exit(&tbf->tf_lock); 427*0Sstevel@tonic-gate SCTP_REFRELE(lsctp); 428*0Sstevel@tonic-gate WAKE_SCTP(sctp); 429*0Sstevel@tonic-gate return (EADDRINUSE); 430*0Sstevel@tonic-gate } 431*0Sstevel@tonic-gate /* 432*0Sstevel@tonic-gate * OK; set up the peer addr (this may grow after we get 433*0Sstevel@tonic-gate * the INIT ACK from the peer with additional addresses). 434*0Sstevel@tonic-gate */ 435*0Sstevel@tonic-gate if (sctp_add_faddr(sctp, &dstaddr, sleep) < 0) { 436*0Sstevel@tonic-gate mutex_exit(&tbf->tf_lock); 437*0Sstevel@tonic-gate WAKE_SCTP(sctp); 438*0Sstevel@tonic-gate return (ENOMEM); 439*0Sstevel@tonic-gate } 440*0Sstevel@tonic-gate /* No valid src addr, return. */ 441*0Sstevel@tonic-gate if (sctp->sctp_faddrs->state == SCTP_FADDRS_UNREACH) { 442*0Sstevel@tonic-gate mutex_exit(&tbf->tf_lock); 443*0Sstevel@tonic-gate WAKE_SCTP(sctp); 444*0Sstevel@tonic-gate return (EADDRNOTAVAIL); 445*0Sstevel@tonic-gate } 446*0Sstevel@tonic-gate sctp->sctp_primary = sctp->sctp_faddrs; 447*0Sstevel@tonic-gate sctp->sctp_current = sctp->sctp_faddrs; 448*0Sstevel@tonic-gate cur_fp = sctp->sctp_current; 449*0Sstevel@tonic-gate sctp->sctp_mss = sctp->sctp_faddrs->sfa_pmss; 450*0Sstevel@tonic-gate sctp_conn_hash_insert(tbf, sctp, 1); 451*0Sstevel@tonic-gate mutex_exit(&tbf->tf_lock); 452*0Sstevel@tonic-gate 453*0Sstevel@tonic-gate /* initialize composite headers */ 454*0Sstevel@tonic-gate sctp_set_hdraddrs(sctp); 455*0Sstevel@tonic-gate 456*0Sstevel@tonic-gate /* 457*0Sstevel@tonic-gate * Massage a routing header (if present) putting the first hop 458*0Sstevel@tonic-gate * in ip6_dst. 459*0Sstevel@tonic-gate */ 460*0Sstevel@tonic-gate rth = ip_find_rthdr_v6(sctp->sctp_ip6h, 461*0Sstevel@tonic-gate (uint8_t *)sctp->sctp_sctph6); 462*0Sstevel@tonic-gate if (rth != NULL) 463*0Sstevel@tonic-gate (void) ip_massage_options_v6(sctp->sctp_ip6h, rth); 464*0Sstevel@tonic-gate 465*0Sstevel@tonic-gate /* 466*0Sstevel@tonic-gate * Turn off the don't fragment bit on the (only) faddr, 467*0Sstevel@tonic-gate * so that if one of the messages exchanged during the 468*0Sstevel@tonic-gate * initialization sequence exceeds the path mtu, it 469*0Sstevel@tonic-gate * at least has a chance to get there. SCTP does no 470*0Sstevel@tonic-gate * fragmentation of initialization messages. The DF bit 471*0Sstevel@tonic-gate * will be turned on again in sctp_send_cookie_echo() 472*0Sstevel@tonic-gate * (but the cookie echo will still be sent with the df bit 473*0Sstevel@tonic-gate * off). 474*0Sstevel@tonic-gate */ 475*0Sstevel@tonic-gate cur_fp->df = B_FALSE; 476*0Sstevel@tonic-gate 477*0Sstevel@tonic-gate /* Mark this address as alive */ 478*0Sstevel@tonic-gate cur_fp->state = SCTP_FADDRS_ALIVE; 479*0Sstevel@tonic-gate 480*0Sstevel@tonic-gate /* This sctp_t is fully bound now. */ 481*0Sstevel@tonic-gate sctp->sctp_connp->conn_fully_bound = B_TRUE; 482*0Sstevel@tonic-gate 483*0Sstevel@tonic-gate /* Send the INIT to the peer */ 484*0Sstevel@tonic-gate SCTP_FADDR_TIMER_RESTART(sctp, cur_fp, cur_fp->rto); 485*0Sstevel@tonic-gate initmp = sctp_init_mp(sctp); 486*0Sstevel@tonic-gate if (initmp == NULL) { 487*0Sstevel@tonic-gate WAKE_SCTP(sctp); 488*0Sstevel@tonic-gate /* let timer retry */ 489*0Sstevel@tonic-gate return (0); 490*0Sstevel@tonic-gate } 491*0Sstevel@tonic-gate sctp->sctp_state = SCTPS_COOKIE_WAIT; 492*0Sstevel@tonic-gate WAKE_SCTP(sctp); 493*0Sstevel@tonic-gate /* OK to call IP_PUT() here instead of sctp_add_sendq(). */ 494*0Sstevel@tonic-gate CONN_INC_REF(sctp->sctp_connp); 495*0Sstevel@tonic-gate initmp->b_flag |= MSGHASREF; 496*0Sstevel@tonic-gate IP_PUT(initmp, sctp->sctp_connp, sctp->sctp_current->isv4); 497*0Sstevel@tonic-gate BUMP_LOCAL(sctp->sctp_opkts); 498*0Sstevel@tonic-gate 499*0Sstevel@tonic-gate sctp->sctp_ulp_prop(sctp->sctp_ulpd, 500*0Sstevel@tonic-gate sctp_wroff_xtra + hdrlen + sizeof (sctp_data_hdr_t), 0); 501*0Sstevel@tonic-gate 502*0Sstevel@tonic-gate return (0); 503*0Sstevel@tonic-gate default: 504*0Sstevel@tonic-gate ip0dbg(("sctp_connect: invalid state. %d\n", sctp->sctp_state)); 505*0Sstevel@tonic-gate WAKE_SCTP(sctp); 506*0Sstevel@tonic-gate return (EINVAL); 507*0Sstevel@tonic-gate } 508*0Sstevel@tonic-gate } 509