10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51676Sjpk * Common Development and Distribution License (the "License"). 61676Sjpk * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 211735Skcpoon 220Sstevel@tonic-gate /* 23*8348SEric.Yu@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #include <sys/types.h> 280Sstevel@tonic-gate #include <sys/systm.h> 290Sstevel@tonic-gate #include <sys/stream.h> 300Sstevel@tonic-gate #include <sys/cmn_err.h> 310Sstevel@tonic-gate #include <sys/kmem.h> 320Sstevel@tonic-gate #define _SUN_TPI_VERSION 2 330Sstevel@tonic-gate #include <sys/tihdr.h> 340Sstevel@tonic-gate #include <sys/stropts.h> 350Sstevel@tonic-gate #include <sys/strsubr.h> 360Sstevel@tonic-gate #include <sys/socket.h> 371676Sjpk #include <sys/tsol/tndb.h> 380Sstevel@tonic-gate 390Sstevel@tonic-gate #include <netinet/in.h> 400Sstevel@tonic-gate #include <netinet/ip6.h> 410Sstevel@tonic-gate 420Sstevel@tonic-gate #include <inet/common.h> 430Sstevel@tonic-gate #include <inet/ip.h> 440Sstevel@tonic-gate #include <inet/ip6.h> 450Sstevel@tonic-gate #include <inet/ipclassifier.h> 460Sstevel@tonic-gate #include <inet/ipsec_impl.h> 470Sstevel@tonic-gate 480Sstevel@tonic-gate #include "sctp_impl.h" 490Sstevel@tonic-gate #include "sctp_addr.h" 500Sstevel@tonic-gate 510Sstevel@tonic-gate /* 520Sstevel@tonic-gate * Common accept code. Called by sctp_conn_request. 530Sstevel@tonic-gate * cr_pkt is the INIT / INIT ACK packet. 540Sstevel@tonic-gate */ 550Sstevel@tonic-gate static int 560Sstevel@tonic-gate sctp_accept_comm(sctp_t *listener, sctp_t *acceptor, mblk_t *cr_pkt, 570Sstevel@tonic-gate uint_t ip_hdr_len, sctp_init_chunk_t *iack) 580Sstevel@tonic-gate { 590Sstevel@tonic-gate 600Sstevel@tonic-gate sctp_hdr_t *sctph; 610Sstevel@tonic-gate sctp_chunk_hdr_t *ich; 620Sstevel@tonic-gate sctp_init_chunk_t *init; 630Sstevel@tonic-gate int err; 640Sstevel@tonic-gate uint_t sctp_options; 652776Skp158701 conn_t *aconnp; 661676Sjpk conn_t *lconnp; 671676Sjpk cred_t *cr; 683448Sdh155122 sctp_stack_t *sctps = listener->sctp_sctps; 690Sstevel@tonic-gate 700Sstevel@tonic-gate sctph = (sctp_hdr_t *)(cr_pkt->b_rptr + ip_hdr_len); 710Sstevel@tonic-gate ASSERT(OK_32PTR(sctph)); 720Sstevel@tonic-gate 730Sstevel@tonic-gate acceptor->sctp_lport = listener->sctp_lport; 740Sstevel@tonic-gate acceptor->sctp_fport = sctph->sh_sport; 750Sstevel@tonic-gate 760Sstevel@tonic-gate ich = (sctp_chunk_hdr_t *)(iack + 1); 770Sstevel@tonic-gate init = (sctp_init_chunk_t *)(ich + 1); 780Sstevel@tonic-gate 790Sstevel@tonic-gate /* acceptor isn't in any fanouts yet, so don't need to hold locks */ 800Sstevel@tonic-gate ASSERT(acceptor->sctp_faddrs == NULL); 810Sstevel@tonic-gate err = sctp_get_addrparams(acceptor, listener, cr_pkt, ich, 820Sstevel@tonic-gate &sctp_options); 830Sstevel@tonic-gate if (err != 0) 840Sstevel@tonic-gate return (err); 850Sstevel@tonic-gate 862776Skp158701 aconnp = acceptor->sctp_connp; 871676Sjpk lconnp = listener->sctp_connp; 881676Sjpk if (lconnp->conn_mlp_type != mlptSingle) { 892776Skp158701 cr = aconnp->conn_peercred = DB_CRED(cr_pkt); 901676Sjpk if (cr != NULL) 911676Sjpk crhold(cr); 921676Sjpk } 931676Sjpk 941735Skcpoon if ((err = sctp_set_hdraddrs(acceptor)) != 0) 951676Sjpk return (err); 961676Sjpk 970Sstevel@tonic-gate if ((sctp_options & SCTP_PRSCTP_OPTION) && 983448Sdh155122 listener->sctp_prsctp_aware && sctps->sctps_prsctp_enabled) { 990Sstevel@tonic-gate acceptor->sctp_prsctp_aware = B_TRUE; 1000Sstevel@tonic-gate } else { 1010Sstevel@tonic-gate acceptor->sctp_prsctp_aware = B_FALSE; 1020Sstevel@tonic-gate } 1030Sstevel@tonic-gate /* The new sctp_t is fully bound now. */ 1040Sstevel@tonic-gate acceptor->sctp_connp->conn_fully_bound = B_TRUE; 1050Sstevel@tonic-gate 1060Sstevel@tonic-gate /* Get initial TSNs */ 1070Sstevel@tonic-gate acceptor->sctp_ltsn = ntohl(iack->sic_inittsn); 1080Sstevel@tonic-gate acceptor->sctp_recovery_tsn = acceptor->sctp_lastack_rxd = 1090Sstevel@tonic-gate acceptor->sctp_ltsn - 1; 1100Sstevel@tonic-gate acceptor->sctp_adv_pap = acceptor->sctp_lastack_rxd; 1110Sstevel@tonic-gate /* Serial numbers are initialized to the same value as the TSNs */ 1120Sstevel@tonic-gate acceptor->sctp_lcsn = acceptor->sctp_ltsn; 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate if (!sctp_initialize_params(acceptor, init, iack)) 1150Sstevel@tonic-gate return (ENOMEM); 1160Sstevel@tonic-gate 1170Sstevel@tonic-gate /* 1180Sstevel@tonic-gate * Copy sctp_secret from the listener in case we need to validate 1190Sstevel@tonic-gate * a possibly delayed cookie. 1200Sstevel@tonic-gate */ 1210Sstevel@tonic-gate bcopy(listener->sctp_secret, acceptor->sctp_secret, SCTP_SECRET_LEN); 1220Sstevel@tonic-gate bcopy(listener->sctp_old_secret, acceptor->sctp_old_secret, 1230Sstevel@tonic-gate SCTP_SECRET_LEN); 1240Sstevel@tonic-gate acceptor->sctp_last_secret_update = lbolt64; 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate /* 1270Sstevel@tonic-gate * After acceptor is inserted in the hash list, it can be found. 1280Sstevel@tonic-gate * So we need to lock it here. 1290Sstevel@tonic-gate */ 1300Sstevel@tonic-gate RUN_SCTP(acceptor); 1310Sstevel@tonic-gate 1323448Sdh155122 sctp_conn_hash_insert(&sctps->sctps_conn_fanout[ 1333448Sdh155122 SCTP_CONN_HASH(sctps, acceptor->sctp_ports)], acceptor, 0); 1343448Sdh155122 sctp_bind_hash_insert(&sctps->sctps_bind_fanout[ 1350Sstevel@tonic-gate SCTP_BIND_HASH(ntohs(acceptor->sctp_lport))], acceptor, 0); 1360Sstevel@tonic-gate 1370Sstevel@tonic-gate /* 1380Sstevel@tonic-gate * No need to check for multicast destination since ip will only pass 1390Sstevel@tonic-gate * up multicasts to those that have expressed interest 1400Sstevel@tonic-gate * TODO: what about rejecting broadcasts? 1410Sstevel@tonic-gate * Also check that source is not a multicast or broadcast address. 1420Sstevel@tonic-gate */ 1430Sstevel@tonic-gate /* XXXSCTP */ 1440Sstevel@tonic-gate acceptor->sctp_state = SCTPS_ESTABLISHED; 1450Sstevel@tonic-gate acceptor->sctp_assoc_start_time = (uint32_t)lbolt; 1460Sstevel@tonic-gate /* 1470Sstevel@tonic-gate * listener->sctp_rwnd should be the default window size or a 1480Sstevel@tonic-gate * window size changed via SO_RCVBUF option. 1490Sstevel@tonic-gate */ 150852Svi117747 acceptor->sctp_rwnd = listener->sctp_rwnd; 151852Svi117747 acceptor->sctp_irwnd = acceptor->sctp_rwnd; 1523845Svi117747 acceptor->sctp_pd_point = acceptor->sctp_rwnd; 153*8348SEric.Yu@Sun.COM acceptor->sctp_upcalls = listener->sctp_upcalls; 154*8348SEric.Yu@Sun.COM #if 0 1550Sstevel@tonic-gate bcopy(&listener->sctp_upcalls, &acceptor->sctp_upcalls, 1560Sstevel@tonic-gate sizeof (sctp_upcalls_t)); 157*8348SEric.Yu@Sun.COM #endif 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate return (0); 1600Sstevel@tonic-gate } 1610Sstevel@tonic-gate 1620Sstevel@tonic-gate /* Process the COOKIE packet, mp, directed at the listener 'sctp' */ 1630Sstevel@tonic-gate sctp_t * 1640Sstevel@tonic-gate sctp_conn_request(sctp_t *sctp, mblk_t *mp, uint_t ifindex, uint_t ip_hdr_len, 1650Sstevel@tonic-gate sctp_init_chunk_t *iack, mblk_t *ipsec_mp) 1660Sstevel@tonic-gate { 1670Sstevel@tonic-gate sctp_t *eager; 1680Sstevel@tonic-gate uint_t ipvers; 1690Sstevel@tonic-gate ip6_t *ip6h; 1700Sstevel@tonic-gate int err; 1710Sstevel@tonic-gate conn_t *connp, *econnp; 1723448Sdh155122 sctp_stack_t *sctps; 173*8348SEric.Yu@Sun.COM struct sock_proto_props sopp; 1740Sstevel@tonic-gate 1750Sstevel@tonic-gate /* 1760Sstevel@tonic-gate * No need to check for duplicate as this is the listener 1770Sstevel@tonic-gate * and we are holding the lock. This means that no new 1780Sstevel@tonic-gate * connection can be created out of it. And since the 1790Sstevel@tonic-gate * fanout already done cannot find a match, it means that 1800Sstevel@tonic-gate * there is no duplicate. 1810Sstevel@tonic-gate */ 1820Sstevel@tonic-gate ipvers = IPH_HDR_VERSION(mp->b_rptr); 1830Sstevel@tonic-gate ASSERT(ipvers == IPV6_VERSION || ipvers == IPV4_VERSION); 1840Sstevel@tonic-gate ASSERT(OK_32PTR(mp->b_rptr)); 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate if ((eager = sctp_create_eager(sctp)) == NULL) { 1870Sstevel@tonic-gate return (NULL); 1880Sstevel@tonic-gate } 1890Sstevel@tonic-gate 1900Sstevel@tonic-gate if (ipvers != IPV4_VERSION) { 1910Sstevel@tonic-gate ip6h = (ip6_t *)mp->b_rptr; 192432Svi117747 if (IN6_IS_ADDR_LINKLOCAL(&ip6h->ip6_src)) 193432Svi117747 eager->sctp_linklocal = 1; 1940Sstevel@tonic-gate /* 1950Sstevel@tonic-gate * Record ifindex (might be zero) to tie this connection to 1960Sstevel@tonic-gate * that interface if either the listener was bound or 1970Sstevel@tonic-gate * if the connection is using link-local addresses. 1980Sstevel@tonic-gate */ 1990Sstevel@tonic-gate if (sctp->sctp_bound_if == ifindex || 2000Sstevel@tonic-gate IN6_IS_ADDR_LINKLOCAL(&ip6h->ip6_src)) 2010Sstevel@tonic-gate eager->sctp_bound_if = ifindex; 2020Sstevel@tonic-gate /* 2030Sstevel@tonic-gate * XXX broken. bound_if is always overwritten by statement 2040Sstevel@tonic-gate * below. What is the right thing to do here? 2050Sstevel@tonic-gate */ 2060Sstevel@tonic-gate eager->sctp_bound_if = sctp->sctp_bound_if; 2070Sstevel@tonic-gate } 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate connp = sctp->sctp_connp; 2103448Sdh155122 sctps = sctp->sctp_sctps; 2110Sstevel@tonic-gate econnp = eager->sctp_connp; 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate if (connp->conn_policy != NULL) { 2140Sstevel@tonic-gate ipsec_in_t *ii; 2150Sstevel@tonic-gate 2160Sstevel@tonic-gate ASSERT(ipsec_mp != NULL); 2170Sstevel@tonic-gate ii = (ipsec_in_t *)(ipsec_mp->b_rptr); 2180Sstevel@tonic-gate ASSERT(ii->ipsec_in_policy == NULL); 2190Sstevel@tonic-gate IPPH_REFHOLD(connp->conn_policy); 2200Sstevel@tonic-gate ii->ipsec_in_policy = connp->conn_policy; 2210Sstevel@tonic-gate 2220Sstevel@tonic-gate ipsec_mp->b_datap->db_type = IPSEC_POLICY_SET; 2230Sstevel@tonic-gate if (!ip_bind_ipsec_policy_set(econnp, ipsec_mp)) { 2240Sstevel@tonic-gate sctp_close_eager(eager); 2253448Sdh155122 BUMP_MIB(&sctps->sctps_mib, sctpListenDrop); 2260Sstevel@tonic-gate return (NULL); 2270Sstevel@tonic-gate } 2280Sstevel@tonic-gate } 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate if (ipsec_mp != NULL) { 2310Sstevel@tonic-gate /* 2320Sstevel@tonic-gate * XXX need to fix the cached policy issue here. 2330Sstevel@tonic-gate * We temporarily set the conn_src/conn_rem here so 2340Sstevel@tonic-gate * that IPsec can use it for the latched policy 2350Sstevel@tonic-gate * selector. This is obvioursly wrong as SCTP can 2360Sstevel@tonic-gate * use different addresses... 2370Sstevel@tonic-gate */ 2380Sstevel@tonic-gate if (ipvers == IPV4_VERSION) { 2390Sstevel@tonic-gate ipha_t *ipha; 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate ipha = (ipha_t *)mp->b_rptr; 2420Sstevel@tonic-gate econnp->conn_src = ipha->ipha_dst; 2430Sstevel@tonic-gate econnp->conn_rem = ipha->ipha_src; 2440Sstevel@tonic-gate } else { 2450Sstevel@tonic-gate econnp->conn_srcv6 = ip6h->ip6_dst; 2460Sstevel@tonic-gate econnp->conn_remv6 = ip6h->ip6_src; 2470Sstevel@tonic-gate } 2480Sstevel@tonic-gate } 2490Sstevel@tonic-gate if (ipsec_conn_cache_policy(econnp, ipvers == IPV4_VERSION) != 0) { 2500Sstevel@tonic-gate sctp_close_eager(eager); 2513448Sdh155122 BUMP_MIB(&sctps->sctps_mib, sctpListenDrop); 2520Sstevel@tonic-gate return (NULL); 2530Sstevel@tonic-gate } 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate err = sctp_accept_comm(sctp, eager, mp, ip_hdr_len, iack); 2560Sstevel@tonic-gate if (err) { 2570Sstevel@tonic-gate sctp_close_eager(eager); 2583448Sdh155122 BUMP_MIB(&sctps->sctps_mib, sctpListenDrop); 2590Sstevel@tonic-gate return (NULL); 2600Sstevel@tonic-gate } 2610Sstevel@tonic-gate 262852Svi117747 /* 263852Svi117747 * On a clustered note send this notification to the clustering 264852Svi117747 * subsystem. 265852Svi117747 */ 266852Svi117747 if (cl_sctp_connect != NULL) { 267852Svi117747 uchar_t *slist; 268852Svi117747 uchar_t *flist; 269852Svi117747 size_t fsize; 270852Svi117747 size_t ssize; 271852Svi117747 272852Svi117747 fsize = sizeof (in6_addr_t) * eager->sctp_nfaddrs; 273852Svi117747 ssize = sizeof (in6_addr_t) * eager->sctp_nsaddrs; 274852Svi117747 slist = kmem_alloc(ssize, KM_NOSLEEP); 275852Svi117747 flist = kmem_alloc(fsize, KM_NOSLEEP); 276852Svi117747 if (slist == NULL || flist == NULL) { 277852Svi117747 if (slist != NULL) 278852Svi117747 kmem_free(slist, ssize); 279852Svi117747 if (flist != NULL) 280852Svi117747 kmem_free(flist, fsize); 281852Svi117747 sctp_close_eager(eager); 2823448Sdh155122 BUMP_MIB(&sctps->sctps_mib, sctpListenDrop); 2833448Sdh155122 SCTP_KSTAT(sctps, sctp_cl_connect); 284852Svi117747 return (NULL); 285852Svi117747 } 286852Svi117747 /* The clustering module frees these list */ 287852Svi117747 sctp_get_saddr_list(eager, slist, ssize); 288852Svi117747 sctp_get_faddr_list(eager, flist, fsize); 289852Svi117747 (*cl_sctp_connect)(eager->sctp_family, slist, 290852Svi117747 eager->sctp_nsaddrs, eager->sctp_lport, flist, 291852Svi117747 eager->sctp_nfaddrs, eager->sctp_fport, B_FALSE, 292852Svi117747 (cl_sctp_handle_t)eager); 293852Svi117747 } 294852Svi117747 2950Sstevel@tonic-gate /* Connection established, so send up the conn_ind */ 2960Sstevel@tonic-gate if ((eager->sctp_ulpd = sctp->sctp_ulp_newconn(sctp->sctp_ulpd, 297*8348SEric.Yu@Sun.COM (sock_lower_handle_t)eager, NULL, NULL, 0, 298*8348SEric.Yu@Sun.COM &eager->sctp_upcalls)) == NULL) { 2990Sstevel@tonic-gate sctp_close_eager(eager); 3003448Sdh155122 BUMP_MIB(&sctps->sctps_mib, sctpListenDrop); 3010Sstevel@tonic-gate return (NULL); 3020Sstevel@tonic-gate } 3030Sstevel@tonic-gate ASSERT(SCTP_IS_DETACHED(eager)); 3040Sstevel@tonic-gate eager->sctp_detached = B_FALSE; 305*8348SEric.Yu@Sun.COM bzero(&sopp, sizeof (sopp)); 306*8348SEric.Yu@Sun.COM sopp.sopp_flags = SOCKOPT_MAXBLK|SOCKOPT_WROFF; 307*8348SEric.Yu@Sun.COM sopp.sopp_maxblk = strmsgsz; 3080Sstevel@tonic-gate if (eager->sctp_family == AF_INET) { 309*8348SEric.Yu@Sun.COM sopp.sopp_wroff = sctps->sctps_wroff_xtra + 310*8348SEric.Yu@Sun.COM sizeof (sctp_data_hdr_t) + sctp->sctp_hdr_len; 3110Sstevel@tonic-gate } else { 312*8348SEric.Yu@Sun.COM sopp.sopp_wroff = sctps->sctps_wroff_xtra + 313*8348SEric.Yu@Sun.COM sizeof (sctp_data_hdr_t) + sctp->sctp_hdr6_len; 3140Sstevel@tonic-gate } 315*8348SEric.Yu@Sun.COM eager->sctp_ulp_prop(eager->sctp_ulpd, &sopp); 3160Sstevel@tonic-gate return (eager); 3170Sstevel@tonic-gate } 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate /* 3200Sstevel@tonic-gate * Connect to a peer - this function inserts the sctp in the 3210Sstevel@tonic-gate * bind and conn fanouts, sends the INIT, and replies to the client 3220Sstevel@tonic-gate * with an OK ack. 3230Sstevel@tonic-gate */ 3240Sstevel@tonic-gate int 3250Sstevel@tonic-gate sctp_connect(sctp_t *sctp, const struct sockaddr *dst, uint32_t addrlen) 3260Sstevel@tonic-gate { 3270Sstevel@tonic-gate sin_t *sin; 3280Sstevel@tonic-gate sin6_t *sin6; 3290Sstevel@tonic-gate in6_addr_t dstaddr; 3300Sstevel@tonic-gate in_port_t dstport; 3310Sstevel@tonic-gate mblk_t *initmp; 3320Sstevel@tonic-gate sctp_tf_t *tbf; 3330Sstevel@tonic-gate sctp_t *lsctp; 3340Sstevel@tonic-gate char buf[INET6_ADDRSTRLEN]; 3350Sstevel@tonic-gate int sleep = sctp->sctp_cansleep ? KM_SLEEP : KM_NOSLEEP; 3360Sstevel@tonic-gate int hdrlen; 3370Sstevel@tonic-gate ip6_rthdr_t *rth; 3381676Sjpk int err; 3390Sstevel@tonic-gate sctp_faddr_t *cur_fp; 3403448Sdh155122 sctp_stack_t *sctps = sctp->sctp_sctps; 341*8348SEric.Yu@Sun.COM struct sock_proto_props sopp; 3420Sstevel@tonic-gate 3430Sstevel@tonic-gate /* 3440Sstevel@tonic-gate * Determine packet type based on type of address passed in 3450Sstevel@tonic-gate * the request should contain an IPv4 or IPv6 address. 3460Sstevel@tonic-gate * Make sure that address family matches the type of 3470Sstevel@tonic-gate * family of the the address passed down 3480Sstevel@tonic-gate */ 3490Sstevel@tonic-gate if (addrlen < sizeof (sin_t)) { 3500Sstevel@tonic-gate return (EINVAL); 3510Sstevel@tonic-gate } 3520Sstevel@tonic-gate switch (dst->sa_family) { 3530Sstevel@tonic-gate case AF_INET: 3540Sstevel@tonic-gate sin = (sin_t *)dst; 3550Sstevel@tonic-gate 3560Sstevel@tonic-gate /* Check for attempt to connect to non-unicast */ 3575215Skcpoon if (CLASSD(sin->sin_addr.s_addr) || 3580Sstevel@tonic-gate (sin->sin_addr.s_addr == INADDR_BROADCAST)) { 3590Sstevel@tonic-gate ip0dbg(("sctp_connect: non-unicast\n")); 3600Sstevel@tonic-gate return (EINVAL); 3610Sstevel@tonic-gate } 3620Sstevel@tonic-gate if (sctp->sctp_connp->conn_ipv6_v6only) 3630Sstevel@tonic-gate return (EAFNOSUPPORT); 3640Sstevel@tonic-gate 3650Sstevel@tonic-gate /* convert to v6 mapped */ 3660Sstevel@tonic-gate /* Check for attempt to connect to INADDR_ANY */ 3670Sstevel@tonic-gate if (sin->sin_addr.s_addr == INADDR_ANY) { 3680Sstevel@tonic-gate struct in_addr v4_addr; 3690Sstevel@tonic-gate /* 3700Sstevel@tonic-gate * SunOS 4.x and 4.3 BSD allow an application 3710Sstevel@tonic-gate * to connect a TCP socket to INADDR_ANY. 3720Sstevel@tonic-gate * When they do this, the kernel picks the 3730Sstevel@tonic-gate * address of one interface and uses it 3740Sstevel@tonic-gate * instead. The kernel usually ends up 3750Sstevel@tonic-gate * picking the address of the loopback 3760Sstevel@tonic-gate * interface. This is an undocumented feature. 3770Sstevel@tonic-gate * However, we provide the same thing here 3780Sstevel@tonic-gate * in case any TCP apps that use this feature 3790Sstevel@tonic-gate * are being ported to SCTP... 3800Sstevel@tonic-gate */ 3810Sstevel@tonic-gate v4_addr.s_addr = htonl(INADDR_LOOPBACK); 3820Sstevel@tonic-gate IN6_INADDR_TO_V4MAPPED(&v4_addr, &dstaddr); 3830Sstevel@tonic-gate } else { 3840Sstevel@tonic-gate IN6_INADDR_TO_V4MAPPED(&sin->sin_addr, &dstaddr); 3850Sstevel@tonic-gate } 3860Sstevel@tonic-gate dstport = sin->sin_port; 3870Sstevel@tonic-gate if (sin->sin_family == AF_INET) { 3880Sstevel@tonic-gate hdrlen = sctp->sctp_hdr_len; 3890Sstevel@tonic-gate } else { 3900Sstevel@tonic-gate hdrlen = sctp->sctp_hdr6_len; 3910Sstevel@tonic-gate } 3920Sstevel@tonic-gate break; 3930Sstevel@tonic-gate case AF_INET6: 3940Sstevel@tonic-gate sin6 = (sin6_t *)dst; 3950Sstevel@tonic-gate /* Check for attempt to connect to non-unicast. */ 3960Sstevel@tonic-gate if ((addrlen < sizeof (sin6_t)) || 3970Sstevel@tonic-gate IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { 3980Sstevel@tonic-gate ip0dbg(("sctp_connect: non-unicast\n")); 3990Sstevel@tonic-gate return (EINVAL); 4000Sstevel@tonic-gate } 4010Sstevel@tonic-gate if (sctp->sctp_connp->conn_ipv6_v6only && 4020Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 4030Sstevel@tonic-gate return (EAFNOSUPPORT); 4040Sstevel@tonic-gate } 4050Sstevel@tonic-gate /* check for attempt to connect to unspec */ 4060Sstevel@tonic-gate if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 4070Sstevel@tonic-gate dstaddr = ipv6_loopback; 4080Sstevel@tonic-gate } else { 4090Sstevel@tonic-gate dstaddr = sin6->sin6_addr; 410432Svi117747 if (IN6_IS_ADDR_LINKLOCAL(&dstaddr)) 411432Svi117747 sctp->sctp_linklocal = 1; 4120Sstevel@tonic-gate } 4130Sstevel@tonic-gate dstport = sin6->sin6_port; 4140Sstevel@tonic-gate hdrlen = sctp->sctp_hdr6_len; 4150Sstevel@tonic-gate break; 4160Sstevel@tonic-gate default: 4170Sstevel@tonic-gate dprint(1, ("sctp_connect: unknown family %d\n", 4184505Skcpoon dst->sa_family)); 4190Sstevel@tonic-gate return (EAFNOSUPPORT); 4200Sstevel@tonic-gate } 4210Sstevel@tonic-gate 4220Sstevel@tonic-gate (void) inet_ntop(AF_INET6, &dstaddr, buf, sizeof (buf)); 4230Sstevel@tonic-gate dprint(1, ("sctp_connect: attempting connect to %s...\n", buf)); 4240Sstevel@tonic-gate 4250Sstevel@tonic-gate RUN_SCTP(sctp); 4260Sstevel@tonic-gate 4274505Skcpoon if (sctp->sctp_family != dst->sa_family || 4284505Skcpoon (sctp->sctp_connp->conn_state_flags & CONN_CLOSING)) { 4290Sstevel@tonic-gate WAKE_SCTP(sctp); 4300Sstevel@tonic-gate return (EINVAL); 4310Sstevel@tonic-gate } 4320Sstevel@tonic-gate 4330Sstevel@tonic-gate switch (sctp->sctp_state) { 4340Sstevel@tonic-gate case SCTPS_IDLE: { 435852Svi117747 struct sockaddr_storage ss; 436852Svi117747 4370Sstevel@tonic-gate /* 4380Sstevel@tonic-gate * We support a quick connect capability here, allowing 4390Sstevel@tonic-gate * clients to transition directly from IDLE to COOKIE_WAIT. 4400Sstevel@tonic-gate * sctp_bindi will pick an unused port, insert the connection 4410Sstevel@tonic-gate * in the bind hash and transition to BOUND state. SCTP 4420Sstevel@tonic-gate * picks and uses what it considers the optimal local address 4430Sstevel@tonic-gate * set (just like specifiying INADDR_ANY to bind()). 4440Sstevel@tonic-gate */ 4450Sstevel@tonic-gate dprint(1, ("sctp_connect: idle, attempting bind...\n")); 4460Sstevel@tonic-gate ASSERT(sctp->sctp_nsaddrs == 0); 4470Sstevel@tonic-gate 448852Svi117747 bzero(&ss, sizeof (ss)); 449852Svi117747 ss.ss_family = sctp->sctp_family; 450852Svi117747 WAKE_SCTP(sctp); 451852Svi117747 if ((err = sctp_bind(sctp, (struct sockaddr *)&ss, 452852Svi117747 sizeof (ss))) != 0) { 4530Sstevel@tonic-gate return (err); 4540Sstevel@tonic-gate } 455852Svi117747 RUN_SCTP(sctp); 4560Sstevel@tonic-gate /* FALLTHRU */ 4570Sstevel@tonic-gate } 4580Sstevel@tonic-gate 4590Sstevel@tonic-gate case SCTPS_BOUND: 4600Sstevel@tonic-gate ASSERT(sctp->sctp_nsaddrs > 0); 4610Sstevel@tonic-gate 4620Sstevel@tonic-gate /* do the connect */ 4630Sstevel@tonic-gate /* XXX check for attempt to connect to self */ 4640Sstevel@tonic-gate sctp->sctp_fport = dstport; 4650Sstevel@tonic-gate 4660Sstevel@tonic-gate ASSERT(sctp->sctp_iphc); 4670Sstevel@tonic-gate ASSERT(sctp->sctp_iphc6); 4680Sstevel@tonic-gate 4690Sstevel@tonic-gate /* 4700Sstevel@tonic-gate * Don't allow this connection to completely duplicate 4710Sstevel@tonic-gate * an existing connection. 4720Sstevel@tonic-gate * 4730Sstevel@tonic-gate * Ensure that the duplicate check and insertion is atomic. 4740Sstevel@tonic-gate */ 4750Sstevel@tonic-gate sctp_conn_hash_remove(sctp); 4763448Sdh155122 tbf = &sctps->sctps_conn_fanout[SCTP_CONN_HASH(sctps, 4774505Skcpoon sctp->sctp_ports)]; 4780Sstevel@tonic-gate mutex_enter(&tbf->tf_lock); 4790Sstevel@tonic-gate lsctp = sctp_lookup(sctp, &dstaddr, tbf, &sctp->sctp_ports, 4800Sstevel@tonic-gate SCTPS_COOKIE_WAIT); 4810Sstevel@tonic-gate if (lsctp != NULL) { 4820Sstevel@tonic-gate /* found a duplicate connection */ 4830Sstevel@tonic-gate mutex_exit(&tbf->tf_lock); 4840Sstevel@tonic-gate SCTP_REFRELE(lsctp); 4850Sstevel@tonic-gate WAKE_SCTP(sctp); 4860Sstevel@tonic-gate return (EADDRINUSE); 4870Sstevel@tonic-gate } 4880Sstevel@tonic-gate /* 4890Sstevel@tonic-gate * OK; set up the peer addr (this may grow after we get 4900Sstevel@tonic-gate * the INIT ACK from the peer with additional addresses). 4910Sstevel@tonic-gate */ 4921735Skcpoon if ((err = sctp_add_faddr(sctp, &dstaddr, sleep, 4931735Skcpoon B_FALSE)) != 0) { 4940Sstevel@tonic-gate mutex_exit(&tbf->tf_lock); 4950Sstevel@tonic-gate WAKE_SCTP(sctp); 4961676Sjpk return (err); 4970Sstevel@tonic-gate } 4984818Skcpoon cur_fp = sctp->sctp_faddrs; 4994818Skcpoon 5000Sstevel@tonic-gate /* No valid src addr, return. */ 5014818Skcpoon if (cur_fp->state == SCTP_FADDRS_UNREACH) { 5020Sstevel@tonic-gate mutex_exit(&tbf->tf_lock); 5030Sstevel@tonic-gate WAKE_SCTP(sctp); 5040Sstevel@tonic-gate return (EADDRNOTAVAIL); 5050Sstevel@tonic-gate } 5064818Skcpoon 5074818Skcpoon sctp->sctp_primary = cur_fp; 5084818Skcpoon sctp->sctp_current = cur_fp; 5094818Skcpoon sctp->sctp_mss = cur_fp->sfa_pmss; 5100Sstevel@tonic-gate sctp_conn_hash_insert(tbf, sctp, 1); 5110Sstevel@tonic-gate mutex_exit(&tbf->tf_lock); 5120Sstevel@tonic-gate 5130Sstevel@tonic-gate /* initialize composite headers */ 5141735Skcpoon if ((err = sctp_set_hdraddrs(sctp)) != 0) { 5151676Sjpk sctp_conn_hash_remove(sctp); 5161676Sjpk WAKE_SCTP(sctp); 5171676Sjpk return (err); 5181676Sjpk } 5190Sstevel@tonic-gate 5200Sstevel@tonic-gate /* 5210Sstevel@tonic-gate * Massage a routing header (if present) putting the first hop 5220Sstevel@tonic-gate * in ip6_dst. 5230Sstevel@tonic-gate */ 5240Sstevel@tonic-gate rth = ip_find_rthdr_v6(sctp->sctp_ip6h, 5250Sstevel@tonic-gate (uint8_t *)sctp->sctp_sctph6); 5263448Sdh155122 if (rth != NULL) { 5273448Sdh155122 (void) ip_massage_options_v6(sctp->sctp_ip6h, rth, 5283448Sdh155122 sctps->sctps_netstack); 5293448Sdh155122 } 5300Sstevel@tonic-gate 5310Sstevel@tonic-gate /* 5320Sstevel@tonic-gate * Turn off the don't fragment bit on the (only) faddr, 5330Sstevel@tonic-gate * so that if one of the messages exchanged during the 5340Sstevel@tonic-gate * initialization sequence exceeds the path mtu, it 5350Sstevel@tonic-gate * at least has a chance to get there. SCTP does no 5360Sstevel@tonic-gate * fragmentation of initialization messages. The DF bit 5370Sstevel@tonic-gate * will be turned on again in sctp_send_cookie_echo() 5380Sstevel@tonic-gate * (but the cookie echo will still be sent with the df bit 5390Sstevel@tonic-gate * off). 5400Sstevel@tonic-gate */ 5410Sstevel@tonic-gate cur_fp->df = B_FALSE; 5420Sstevel@tonic-gate 5430Sstevel@tonic-gate /* Mark this address as alive */ 5440Sstevel@tonic-gate cur_fp->state = SCTP_FADDRS_ALIVE; 5450Sstevel@tonic-gate 5460Sstevel@tonic-gate /* This sctp_t is fully bound now. */ 5470Sstevel@tonic-gate sctp->sctp_connp->conn_fully_bound = B_TRUE; 5480Sstevel@tonic-gate 5490Sstevel@tonic-gate /* Send the INIT to the peer */ 5500Sstevel@tonic-gate SCTP_FADDR_TIMER_RESTART(sctp, cur_fp, cur_fp->rto); 5514818Skcpoon sctp->sctp_state = SCTPS_COOKIE_WAIT; 552432Svi117747 /* 553432Svi117747 * sctp_init_mp() could result in modifying the source 554432Svi117747 * address list, so take the hash lock. 555432Svi117747 */ 556432Svi117747 mutex_enter(&tbf->tf_lock); 5570Sstevel@tonic-gate initmp = sctp_init_mp(sctp); 5580Sstevel@tonic-gate if (initmp == NULL) { 559432Svi117747 mutex_exit(&tbf->tf_lock); 5604818Skcpoon /* 5614818Skcpoon * It may happen that all the source addresses 5624818Skcpoon * (loopback/link local) are removed. In that case, 5634818Skcpoon * faile the connect. 5644818Skcpoon */ 5654818Skcpoon if (sctp->sctp_nsaddrs == 0) { 5664818Skcpoon sctp_conn_hash_remove(sctp); 5674818Skcpoon SCTP_FADDR_TIMER_STOP(cur_fp); 5684818Skcpoon WAKE_SCTP(sctp); 5694818Skcpoon return (EADDRNOTAVAIL); 5704818Skcpoon } 5714818Skcpoon 5724818Skcpoon /* Otherwise, let the retransmission timer retry */ 5730Sstevel@tonic-gate WAKE_SCTP(sctp); 5744818Skcpoon goto notify_ulp; 5750Sstevel@tonic-gate } 576432Svi117747 mutex_exit(&tbf->tf_lock); 5774818Skcpoon 578852Svi117747 /* 579852Svi117747 * On a clustered note send this notification to the clustering 580852Svi117747 * subsystem. 581852Svi117747 */ 582852Svi117747 if (cl_sctp_connect != NULL) { 583852Svi117747 uchar_t *slist; 584852Svi117747 uchar_t *flist; 585852Svi117747 size_t ssize; 586852Svi117747 size_t fsize; 587852Svi117747 588852Svi117747 fsize = sizeof (in6_addr_t) * sctp->sctp_nfaddrs; 589852Svi117747 ssize = sizeof (in6_addr_t) * sctp->sctp_nsaddrs; 590852Svi117747 slist = kmem_alloc(ssize, KM_SLEEP); 591852Svi117747 flist = kmem_alloc(fsize, KM_SLEEP); 592852Svi117747 /* The clustering module frees the lists */ 593852Svi117747 sctp_get_saddr_list(sctp, slist, ssize); 594852Svi117747 sctp_get_faddr_list(sctp, flist, fsize); 595852Svi117747 (*cl_sctp_connect)(sctp->sctp_family, slist, 596852Svi117747 sctp->sctp_nsaddrs, sctp->sctp_lport, 597852Svi117747 flist, sctp->sctp_nfaddrs, sctp->sctp_fport, 598852Svi117747 B_TRUE, (cl_sctp_handle_t)sctp); 599852Svi117747 } 6000Sstevel@tonic-gate WAKE_SCTP(sctp); 6010Sstevel@tonic-gate /* OK to call IP_PUT() here instead of sctp_add_sendq(). */ 6020Sstevel@tonic-gate CONN_INC_REF(sctp->sctp_connp); 6030Sstevel@tonic-gate initmp->b_flag |= MSGHASREF; 6040Sstevel@tonic-gate IP_PUT(initmp, sctp->sctp_connp, sctp->sctp_current->isv4); 6050Sstevel@tonic-gate BUMP_LOCAL(sctp->sctp_opkts); 6060Sstevel@tonic-gate 6074818Skcpoon notify_ulp: 608*8348SEric.Yu@Sun.COM bzero(&sopp, sizeof (sopp)); 609*8348SEric.Yu@Sun.COM sopp.sopp_flags = SOCKOPT_WROFF; 610*8348SEric.Yu@Sun.COM sopp.sopp_wroff = sctps->sctps_wroff_xtra + hdrlen + 611*8348SEric.Yu@Sun.COM sizeof (sctp_data_hdr_t); 612*8348SEric.Yu@Sun.COM sctp->sctp_ulp_prop(sctp->sctp_ulpd, &sopp); 6130Sstevel@tonic-gate 6140Sstevel@tonic-gate return (0); 6150Sstevel@tonic-gate default: 6160Sstevel@tonic-gate ip0dbg(("sctp_connect: invalid state. %d\n", sctp->sctp_state)); 6170Sstevel@tonic-gate WAKE_SCTP(sctp); 6180Sstevel@tonic-gate return (EINVAL); 6190Sstevel@tonic-gate } 6200Sstevel@tonic-gate } 621