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 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 230Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include <sys/types.h> 300Sstevel@tonic-gate #include <sys/systm.h> 310Sstevel@tonic-gate #include <sys/stream.h> 320Sstevel@tonic-gate #include <sys/cmn_err.h> 330Sstevel@tonic-gate #include <sys/kmem.h> 340Sstevel@tonic-gate #define _SUN_TPI_VERSION 2 350Sstevel@tonic-gate #include <sys/tihdr.h> 360Sstevel@tonic-gate #include <sys/stropts.h> 370Sstevel@tonic-gate #include <sys/strsubr.h> 380Sstevel@tonic-gate #include <sys/socket.h> 390Sstevel@tonic-gate 400Sstevel@tonic-gate #include <netinet/in.h> 410Sstevel@tonic-gate #include <netinet/ip6.h> 420Sstevel@tonic-gate 430Sstevel@tonic-gate #include <inet/common.h> 440Sstevel@tonic-gate #include <inet/ip.h> 450Sstevel@tonic-gate #include <inet/ip6.h> 460Sstevel@tonic-gate #include <inet/ipclassifier.h> 470Sstevel@tonic-gate #include <inet/ipsec_impl.h> 480Sstevel@tonic-gate 490Sstevel@tonic-gate #include "sctp_impl.h" 500Sstevel@tonic-gate #include "sctp_addr.h" 510Sstevel@tonic-gate 520Sstevel@tonic-gate /* 530Sstevel@tonic-gate * Common accept code. Called by sctp_conn_request. 540Sstevel@tonic-gate * cr_pkt is the INIT / INIT ACK packet. 550Sstevel@tonic-gate */ 560Sstevel@tonic-gate static int 570Sstevel@tonic-gate sctp_accept_comm(sctp_t *listener, sctp_t *acceptor, mblk_t *cr_pkt, 580Sstevel@tonic-gate uint_t ip_hdr_len, sctp_init_chunk_t *iack) 590Sstevel@tonic-gate { 600Sstevel@tonic-gate 610Sstevel@tonic-gate sctp_hdr_t *sctph; 620Sstevel@tonic-gate sctp_chunk_hdr_t *ich; 630Sstevel@tonic-gate sctp_init_chunk_t *init; 640Sstevel@tonic-gate int err; 650Sstevel@tonic-gate uint_t sctp_options; 660Sstevel@tonic-gate 670Sstevel@tonic-gate sctph = (sctp_hdr_t *)(cr_pkt->b_rptr + ip_hdr_len); 680Sstevel@tonic-gate ASSERT(OK_32PTR(sctph)); 690Sstevel@tonic-gate 700Sstevel@tonic-gate acceptor->sctp_lport = listener->sctp_lport; 710Sstevel@tonic-gate acceptor->sctp_fport = sctph->sh_sport; 720Sstevel@tonic-gate 730Sstevel@tonic-gate ich = (sctp_chunk_hdr_t *)(iack + 1); 740Sstevel@tonic-gate init = (sctp_init_chunk_t *)(ich + 1); 750Sstevel@tonic-gate 760Sstevel@tonic-gate /* acceptor isn't in any fanouts yet, so don't need to hold locks */ 770Sstevel@tonic-gate ASSERT(acceptor->sctp_faddrs == NULL); 780Sstevel@tonic-gate err = sctp_get_addrparams(acceptor, listener, cr_pkt, ich, 790Sstevel@tonic-gate &sctp_options); 800Sstevel@tonic-gate if (err != 0) 810Sstevel@tonic-gate return (err); 820Sstevel@tonic-gate 830Sstevel@tonic-gate if ((sctp_options & SCTP_PRSCTP_OPTION) && 840Sstevel@tonic-gate listener->sctp_prsctp_aware && sctp_prsctp_enabled) { 850Sstevel@tonic-gate acceptor->sctp_prsctp_aware = B_TRUE; 860Sstevel@tonic-gate } else { 870Sstevel@tonic-gate acceptor->sctp_prsctp_aware = B_FALSE; 880Sstevel@tonic-gate } 890Sstevel@tonic-gate /* The new sctp_t is fully bound now. */ 900Sstevel@tonic-gate acceptor->sctp_connp->conn_fully_bound = B_TRUE; 910Sstevel@tonic-gate 920Sstevel@tonic-gate sctp_set_hdraddrs(acceptor); 930Sstevel@tonic-gate 940Sstevel@tonic-gate /* Get initial TSNs */ 950Sstevel@tonic-gate acceptor->sctp_ltsn = ntohl(iack->sic_inittsn); 960Sstevel@tonic-gate acceptor->sctp_recovery_tsn = acceptor->sctp_lastack_rxd = 970Sstevel@tonic-gate acceptor->sctp_ltsn - 1; 980Sstevel@tonic-gate acceptor->sctp_adv_pap = acceptor->sctp_lastack_rxd; 990Sstevel@tonic-gate /* Serial numbers are initialized to the same value as the TSNs */ 1000Sstevel@tonic-gate acceptor->sctp_lcsn = acceptor->sctp_ltsn; 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate if (!sctp_initialize_params(acceptor, init, iack)) 1030Sstevel@tonic-gate return (ENOMEM); 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate /* 1060Sstevel@tonic-gate * Copy sctp_secret from the listener in case we need to validate 1070Sstevel@tonic-gate * a possibly delayed cookie. 1080Sstevel@tonic-gate */ 1090Sstevel@tonic-gate bcopy(listener->sctp_secret, acceptor->sctp_secret, SCTP_SECRET_LEN); 1100Sstevel@tonic-gate bcopy(listener->sctp_old_secret, acceptor->sctp_old_secret, 1110Sstevel@tonic-gate SCTP_SECRET_LEN); 1120Sstevel@tonic-gate acceptor->sctp_last_secret_update = lbolt64; 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate /* 1150Sstevel@tonic-gate * After acceptor is inserted in the hash list, it can be found. 1160Sstevel@tonic-gate * So we need to lock it here. 1170Sstevel@tonic-gate */ 1180Sstevel@tonic-gate RUN_SCTP(acceptor); 1190Sstevel@tonic-gate 1200Sstevel@tonic-gate sctp_conn_hash_insert(&sctp_conn_fanout[ 1210Sstevel@tonic-gate SCTP_CONN_HASH(acceptor->sctp_ports)], acceptor, 0); 1220Sstevel@tonic-gate sctp_bind_hash_insert(&sctp_bind_fanout[ 1230Sstevel@tonic-gate SCTP_BIND_HASH(ntohs(acceptor->sctp_lport))], acceptor, 0); 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate /* 1260Sstevel@tonic-gate * No need to check for multicast destination since ip will only pass 1270Sstevel@tonic-gate * up multicasts to those that have expressed interest 1280Sstevel@tonic-gate * TODO: what about rejecting broadcasts? 1290Sstevel@tonic-gate * Also check that source is not a multicast or broadcast address. 1300Sstevel@tonic-gate */ 1310Sstevel@tonic-gate /* XXXSCTP */ 1320Sstevel@tonic-gate acceptor->sctp_state = SCTPS_ESTABLISHED; 1330Sstevel@tonic-gate acceptor->sctp_assoc_start_time = (uint32_t)lbolt; 1340Sstevel@tonic-gate /* 1350Sstevel@tonic-gate * listener->sctp_rwnd should be the default window size or a 1360Sstevel@tonic-gate * window size changed via SO_RCVBUF option. 1370Sstevel@tonic-gate */ 1380Sstevel@tonic-gate acceptor->sctp_rwnd = MSS_ROUNDUP(listener->sctp_rwnd, 1390Sstevel@tonic-gate (acceptor->sctp_mss - sizeof (sctp_data_hdr_t))); 1400Sstevel@tonic-gate 1410Sstevel@tonic-gate bcopy(&listener->sctp_upcalls, &acceptor->sctp_upcalls, 1420Sstevel@tonic-gate sizeof (sctp_upcalls_t)); 1430Sstevel@tonic-gate 1440Sstevel@tonic-gate return (0); 1450Sstevel@tonic-gate } 1460Sstevel@tonic-gate 1470Sstevel@tonic-gate /* Process the COOKIE packet, mp, directed at the listener 'sctp' */ 1480Sstevel@tonic-gate sctp_t * 1490Sstevel@tonic-gate sctp_conn_request(sctp_t *sctp, mblk_t *mp, uint_t ifindex, uint_t ip_hdr_len, 1500Sstevel@tonic-gate sctp_init_chunk_t *iack, mblk_t *ipsec_mp) 1510Sstevel@tonic-gate { 1520Sstevel@tonic-gate sctp_t *eager; 1530Sstevel@tonic-gate uint_t ipvers; 1540Sstevel@tonic-gate ip6_t *ip6h; 1550Sstevel@tonic-gate int err; 1560Sstevel@tonic-gate conn_t *connp, *econnp; 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate /* 1590Sstevel@tonic-gate * No need to check for duplicate as this is the listener 1600Sstevel@tonic-gate * and we are holding the lock. This means that no new 1610Sstevel@tonic-gate * connection can be created out of it. And since the 1620Sstevel@tonic-gate * fanout already done cannot find a match, it means that 1630Sstevel@tonic-gate * there is no duplicate. 1640Sstevel@tonic-gate */ 1650Sstevel@tonic-gate ipvers = IPH_HDR_VERSION(mp->b_rptr); 1660Sstevel@tonic-gate ASSERT(ipvers == IPV6_VERSION || ipvers == IPV4_VERSION); 1670Sstevel@tonic-gate ASSERT(OK_32PTR(mp->b_rptr)); 1680Sstevel@tonic-gate 1690Sstevel@tonic-gate if ((eager = sctp_create_eager(sctp)) == NULL) { 1700Sstevel@tonic-gate return (NULL); 1710Sstevel@tonic-gate } 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate if (ipvers != IPV4_VERSION) { 1740Sstevel@tonic-gate ip6h = (ip6_t *)mp->b_rptr; 175*432Svi117747 if (IN6_IS_ADDR_LINKLOCAL(&ip6h->ip6_src)) 176*432Svi117747 eager->sctp_linklocal = 1; 1770Sstevel@tonic-gate /* 1780Sstevel@tonic-gate * Record ifindex (might be zero) to tie this connection to 1790Sstevel@tonic-gate * that interface if either the listener was bound or 1800Sstevel@tonic-gate * if the connection is using link-local addresses. 1810Sstevel@tonic-gate */ 1820Sstevel@tonic-gate if (sctp->sctp_bound_if == ifindex || 1830Sstevel@tonic-gate IN6_IS_ADDR_LINKLOCAL(&ip6h->ip6_src)) 1840Sstevel@tonic-gate eager->sctp_bound_if = ifindex; 1850Sstevel@tonic-gate /* 1860Sstevel@tonic-gate * XXX broken. bound_if is always overwritten by statement 1870Sstevel@tonic-gate * below. What is the right thing to do here? 1880Sstevel@tonic-gate */ 1890Sstevel@tonic-gate eager->sctp_bound_if = sctp->sctp_bound_if; 1900Sstevel@tonic-gate } 1910Sstevel@tonic-gate 1920Sstevel@tonic-gate connp = sctp->sctp_connp; 1930Sstevel@tonic-gate econnp = eager->sctp_connp; 1940Sstevel@tonic-gate 1950Sstevel@tonic-gate if (connp->conn_policy != NULL) { 1960Sstevel@tonic-gate ipsec_in_t *ii; 1970Sstevel@tonic-gate 1980Sstevel@tonic-gate ASSERT(ipsec_mp != NULL); 1990Sstevel@tonic-gate ii = (ipsec_in_t *)(ipsec_mp->b_rptr); 2000Sstevel@tonic-gate ASSERT(ii->ipsec_in_policy == NULL); 2010Sstevel@tonic-gate IPPH_REFHOLD(connp->conn_policy); 2020Sstevel@tonic-gate ii->ipsec_in_policy = connp->conn_policy; 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate ipsec_mp->b_datap->db_type = IPSEC_POLICY_SET; 2050Sstevel@tonic-gate if (!ip_bind_ipsec_policy_set(econnp, ipsec_mp)) { 2060Sstevel@tonic-gate sctp_close_eager(eager); 2070Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpListenDrop); 2080Sstevel@tonic-gate return (NULL); 2090Sstevel@tonic-gate } 2100Sstevel@tonic-gate } 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate if (ipsec_mp != NULL) { 2130Sstevel@tonic-gate /* 2140Sstevel@tonic-gate * XXX need to fix the cached policy issue here. 2150Sstevel@tonic-gate * We temporarily set the conn_src/conn_rem here so 2160Sstevel@tonic-gate * that IPsec can use it for the latched policy 2170Sstevel@tonic-gate * selector. This is obvioursly wrong as SCTP can 2180Sstevel@tonic-gate * use different addresses... 2190Sstevel@tonic-gate */ 2200Sstevel@tonic-gate if (ipvers == IPV4_VERSION) { 2210Sstevel@tonic-gate ipha_t *ipha; 2220Sstevel@tonic-gate 2230Sstevel@tonic-gate ipha = (ipha_t *)mp->b_rptr; 2240Sstevel@tonic-gate econnp->conn_src = ipha->ipha_dst; 2250Sstevel@tonic-gate econnp->conn_rem = ipha->ipha_src; 2260Sstevel@tonic-gate } else { 2270Sstevel@tonic-gate econnp->conn_srcv6 = ip6h->ip6_dst; 2280Sstevel@tonic-gate econnp->conn_remv6 = ip6h->ip6_src; 2290Sstevel@tonic-gate } 2300Sstevel@tonic-gate } 2310Sstevel@tonic-gate if (ipsec_conn_cache_policy(econnp, ipvers == IPV4_VERSION) != 0) { 2320Sstevel@tonic-gate sctp_close_eager(eager); 2330Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpListenDrop); 2340Sstevel@tonic-gate return (NULL); 2350Sstevel@tonic-gate } 2360Sstevel@tonic-gate 2370Sstevel@tonic-gate err = sctp_accept_comm(sctp, eager, mp, ip_hdr_len, iack); 2380Sstevel@tonic-gate if (err) { 2390Sstevel@tonic-gate sctp_close_eager(eager); 2400Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpListenDrop); 2410Sstevel@tonic-gate return (NULL); 2420Sstevel@tonic-gate } 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate /* Connection established, so send up the conn_ind */ 2450Sstevel@tonic-gate if ((eager->sctp_ulpd = sctp->sctp_ulp_newconn(sctp->sctp_ulpd, 2460Sstevel@tonic-gate eager)) == NULL) { 2470Sstevel@tonic-gate sctp_close_eager(eager); 2480Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpListenDrop); 2490Sstevel@tonic-gate return (NULL); 2500Sstevel@tonic-gate } 2510Sstevel@tonic-gate ASSERT(SCTP_IS_DETACHED(eager)); 2520Sstevel@tonic-gate eager->sctp_detached = B_FALSE; 2530Sstevel@tonic-gate if (eager->sctp_family == AF_INET) { 2540Sstevel@tonic-gate eager->sctp_ulp_prop(eager->sctp_ulpd, 2550Sstevel@tonic-gate sctp_wroff_xtra + sizeof (sctp_data_hdr_t) + 2560Sstevel@tonic-gate sctp->sctp_hdr_len, strmsgsz); 2570Sstevel@tonic-gate } else { 2580Sstevel@tonic-gate eager->sctp_ulp_prop(eager->sctp_ulpd, 2590Sstevel@tonic-gate sctp_wroff_xtra + sizeof (sctp_data_hdr_t) + 2600Sstevel@tonic-gate sctp->sctp_hdr6_len, strmsgsz); 2610Sstevel@tonic-gate } 2620Sstevel@tonic-gate return (eager); 2630Sstevel@tonic-gate } 2640Sstevel@tonic-gate 2650Sstevel@tonic-gate /* 2660Sstevel@tonic-gate * Connect to a peer - this function inserts the sctp in the 2670Sstevel@tonic-gate * bind and conn fanouts, sends the INIT, and replies to the client 2680Sstevel@tonic-gate * with an OK ack. 2690Sstevel@tonic-gate */ 2700Sstevel@tonic-gate /* ARGSUSED */ 2710Sstevel@tonic-gate int 2720Sstevel@tonic-gate sctp_connect(sctp_t *sctp, const struct sockaddr *dst, uint32_t addrlen) 2730Sstevel@tonic-gate { 2740Sstevel@tonic-gate sin_t *sin; 2750Sstevel@tonic-gate sin6_t *sin6; 2760Sstevel@tonic-gate in_port_t lport; 2770Sstevel@tonic-gate in6_addr_t dstaddr; 2780Sstevel@tonic-gate in_port_t dstport; 2790Sstevel@tonic-gate mblk_t *initmp; 2800Sstevel@tonic-gate sctp_tf_t *tbf; 2810Sstevel@tonic-gate sctp_t *lsctp; 2820Sstevel@tonic-gate char buf[INET6_ADDRSTRLEN]; 2830Sstevel@tonic-gate int sleep = sctp->sctp_cansleep ? KM_SLEEP : KM_NOSLEEP; 2840Sstevel@tonic-gate int hdrlen; 2850Sstevel@tonic-gate ip6_rthdr_t *rth; 2860Sstevel@tonic-gate sctp_faddr_t *cur_fp; 2870Sstevel@tonic-gate 2880Sstevel@tonic-gate /* 2890Sstevel@tonic-gate * Determine packet type based on type of address passed in 2900Sstevel@tonic-gate * the request should contain an IPv4 or IPv6 address. 2910Sstevel@tonic-gate * Make sure that address family matches the type of 2920Sstevel@tonic-gate * family of the the address passed down 2930Sstevel@tonic-gate */ 2940Sstevel@tonic-gate if (addrlen < sizeof (sin_t)) { 2950Sstevel@tonic-gate return (EINVAL); 2960Sstevel@tonic-gate } 2970Sstevel@tonic-gate switch (dst->sa_family) { 2980Sstevel@tonic-gate case AF_INET: 2990Sstevel@tonic-gate sin = (sin_t *)dst; 3000Sstevel@tonic-gate 3010Sstevel@tonic-gate /* Check for attempt to connect to non-unicast */ 3020Sstevel@tonic-gate if (IN_MULTICAST(sin->sin_addr.s_addr) || 3030Sstevel@tonic-gate (sin->sin_addr.s_addr == INADDR_BROADCAST)) { 3040Sstevel@tonic-gate ip0dbg(("sctp_connect: non-unicast\n")); 3050Sstevel@tonic-gate return (EINVAL); 3060Sstevel@tonic-gate } 3070Sstevel@tonic-gate if (sctp->sctp_connp->conn_ipv6_v6only) 3080Sstevel@tonic-gate return (EAFNOSUPPORT); 3090Sstevel@tonic-gate 3100Sstevel@tonic-gate /* convert to v6 mapped */ 3110Sstevel@tonic-gate /* Check for attempt to connect to INADDR_ANY */ 3120Sstevel@tonic-gate if (sin->sin_addr.s_addr == INADDR_ANY) { 3130Sstevel@tonic-gate struct in_addr v4_addr; 3140Sstevel@tonic-gate /* 3150Sstevel@tonic-gate * SunOS 4.x and 4.3 BSD allow an application 3160Sstevel@tonic-gate * to connect a TCP socket to INADDR_ANY. 3170Sstevel@tonic-gate * When they do this, the kernel picks the 3180Sstevel@tonic-gate * address of one interface and uses it 3190Sstevel@tonic-gate * instead. The kernel usually ends up 3200Sstevel@tonic-gate * picking the address of the loopback 3210Sstevel@tonic-gate * interface. This is an undocumented feature. 3220Sstevel@tonic-gate * However, we provide the same thing here 3230Sstevel@tonic-gate * in case any TCP apps that use this feature 3240Sstevel@tonic-gate * are being ported to SCTP... 3250Sstevel@tonic-gate */ 3260Sstevel@tonic-gate v4_addr.s_addr = htonl(INADDR_LOOPBACK); 3270Sstevel@tonic-gate IN6_INADDR_TO_V4MAPPED(&v4_addr, &dstaddr); 3280Sstevel@tonic-gate } else { 3290Sstevel@tonic-gate IN6_INADDR_TO_V4MAPPED(&sin->sin_addr, &dstaddr); 3300Sstevel@tonic-gate } 3310Sstevel@tonic-gate dstport = sin->sin_port; 3320Sstevel@tonic-gate if (sin->sin_family == AF_INET) { 3330Sstevel@tonic-gate hdrlen = sctp->sctp_hdr_len; 3340Sstevel@tonic-gate } else { 3350Sstevel@tonic-gate hdrlen = sctp->sctp_hdr6_len; 3360Sstevel@tonic-gate } 3370Sstevel@tonic-gate break; 3380Sstevel@tonic-gate case AF_INET6: 3390Sstevel@tonic-gate sin6 = (sin6_t *)dst; 3400Sstevel@tonic-gate /* Check for attempt to connect to non-unicast. */ 3410Sstevel@tonic-gate if ((addrlen < sizeof (sin6_t)) || 3420Sstevel@tonic-gate IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { 3430Sstevel@tonic-gate ip0dbg(("sctp_connect: non-unicast\n")); 3440Sstevel@tonic-gate return (EINVAL); 3450Sstevel@tonic-gate } 3460Sstevel@tonic-gate if (sctp->sctp_connp->conn_ipv6_v6only && 3470Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 3480Sstevel@tonic-gate return (EAFNOSUPPORT); 3490Sstevel@tonic-gate } 3500Sstevel@tonic-gate /* check for attempt to connect to unspec */ 3510Sstevel@tonic-gate if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 3520Sstevel@tonic-gate dstaddr = ipv6_loopback; 3530Sstevel@tonic-gate } else { 3540Sstevel@tonic-gate dstaddr = sin6->sin6_addr; 355*432Svi117747 if (IN6_IS_ADDR_LINKLOCAL(&dstaddr)) 356*432Svi117747 sctp->sctp_linklocal = 1; 3570Sstevel@tonic-gate } 3580Sstevel@tonic-gate dstport = sin6->sin6_port; 3590Sstevel@tonic-gate hdrlen = sctp->sctp_hdr6_len; 3600Sstevel@tonic-gate break; 3610Sstevel@tonic-gate default: 3620Sstevel@tonic-gate dprint(1, ("sctp_connect: unknown family %d\n", 3630Sstevel@tonic-gate dst->sa_family)); 3640Sstevel@tonic-gate return (EAFNOSUPPORT); 3650Sstevel@tonic-gate } 3660Sstevel@tonic-gate 3670Sstevel@tonic-gate (void) inet_ntop(AF_INET6, &dstaddr, buf, sizeof (buf)); 3680Sstevel@tonic-gate dprint(1, ("sctp_connect: attempting connect to %s...\n", buf)); 3690Sstevel@tonic-gate 3700Sstevel@tonic-gate RUN_SCTP(sctp); 3710Sstevel@tonic-gate 3720Sstevel@tonic-gate if (sctp->sctp_family != dst->sa_family) { 3730Sstevel@tonic-gate WAKE_SCTP(sctp); 3740Sstevel@tonic-gate return (EINVAL); 3750Sstevel@tonic-gate } 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate switch (sctp->sctp_state) { 3780Sstevel@tonic-gate case SCTPS_IDLE: { 3790Sstevel@tonic-gate int err; 3800Sstevel@tonic-gate /* 3810Sstevel@tonic-gate * We support a quick connect capability here, allowing 3820Sstevel@tonic-gate * clients to transition directly from IDLE to COOKIE_WAIT. 3830Sstevel@tonic-gate * sctp_bindi will pick an unused port, insert the connection 3840Sstevel@tonic-gate * in the bind hash and transition to BOUND state. SCTP 3850Sstevel@tonic-gate * picks and uses what it considers the optimal local address 3860Sstevel@tonic-gate * set (just like specifiying INADDR_ANY to bind()). 3870Sstevel@tonic-gate */ 3880Sstevel@tonic-gate dprint(1, ("sctp_connect: idle, attempting bind...\n")); 3890Sstevel@tonic-gate ASSERT(sctp->sctp_nsaddrs == 0); 3900Sstevel@tonic-gate 3910Sstevel@tonic-gate err = sctp_dup_saddrs(NULL, sctp, sleep); 3920Sstevel@tonic-gate if (err != 0) { 3930Sstevel@tonic-gate WAKE_SCTP(sctp); 3940Sstevel@tonic-gate return (err); 3950Sstevel@tonic-gate } 3960Sstevel@tonic-gate lport = sctp_update_next_port(sctp_next_port_to_try); 3970Sstevel@tonic-gate lport = sctp_bindi(sctp, lport, 0, 0); 3980Sstevel@tonic-gate if (lport == 0) { 3990Sstevel@tonic-gate WAKE_SCTP(sctp); 4000Sstevel@tonic-gate sctp_free_saddrs(sctp); 4010Sstevel@tonic-gate return (EADDRNOTAVAIL); 4020Sstevel@tonic-gate } 4030Sstevel@tonic-gate sctp->sctp_bound_to_all = 1; 4040Sstevel@tonic-gate /* FALLTHRU */ 4050Sstevel@tonic-gate } 4060Sstevel@tonic-gate 4070Sstevel@tonic-gate case SCTPS_BOUND: 4080Sstevel@tonic-gate ASSERT(sctp->sctp_nsaddrs > 0); 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate /* do the connect */ 4110Sstevel@tonic-gate /* XXX check for attempt to connect to self */ 4120Sstevel@tonic-gate sctp->sctp_fport = dstport; 4130Sstevel@tonic-gate 4140Sstevel@tonic-gate ASSERT(sctp->sctp_iphc); 4150Sstevel@tonic-gate ASSERT(sctp->sctp_iphc6); 4160Sstevel@tonic-gate 4170Sstevel@tonic-gate /* 4180Sstevel@tonic-gate * Don't allow this connection to completely duplicate 4190Sstevel@tonic-gate * an existing connection. 4200Sstevel@tonic-gate * 4210Sstevel@tonic-gate * Ensure that the duplicate check and insertion is atomic. 4220Sstevel@tonic-gate */ 4230Sstevel@tonic-gate sctp_conn_hash_remove(sctp); 4240Sstevel@tonic-gate tbf = &sctp_conn_fanout[SCTP_CONN_HASH(sctp->sctp_ports)]; 4250Sstevel@tonic-gate mutex_enter(&tbf->tf_lock); 4260Sstevel@tonic-gate lsctp = sctp_lookup(sctp, &dstaddr, tbf, &sctp->sctp_ports, 4270Sstevel@tonic-gate SCTPS_COOKIE_WAIT); 4280Sstevel@tonic-gate if (lsctp != NULL) { 4290Sstevel@tonic-gate /* found a duplicate connection */ 4300Sstevel@tonic-gate mutex_exit(&tbf->tf_lock); 4310Sstevel@tonic-gate SCTP_REFRELE(lsctp); 4320Sstevel@tonic-gate WAKE_SCTP(sctp); 4330Sstevel@tonic-gate return (EADDRINUSE); 4340Sstevel@tonic-gate } 4350Sstevel@tonic-gate /* 4360Sstevel@tonic-gate * OK; set up the peer addr (this may grow after we get 4370Sstevel@tonic-gate * the INIT ACK from the peer with additional addresses). 4380Sstevel@tonic-gate */ 4390Sstevel@tonic-gate if (sctp_add_faddr(sctp, &dstaddr, sleep) < 0) { 4400Sstevel@tonic-gate mutex_exit(&tbf->tf_lock); 4410Sstevel@tonic-gate WAKE_SCTP(sctp); 4420Sstevel@tonic-gate return (ENOMEM); 4430Sstevel@tonic-gate } 4440Sstevel@tonic-gate /* No valid src addr, return. */ 4450Sstevel@tonic-gate if (sctp->sctp_faddrs->state == SCTP_FADDRS_UNREACH) { 4460Sstevel@tonic-gate mutex_exit(&tbf->tf_lock); 4470Sstevel@tonic-gate WAKE_SCTP(sctp); 4480Sstevel@tonic-gate return (EADDRNOTAVAIL); 4490Sstevel@tonic-gate } 4500Sstevel@tonic-gate sctp->sctp_primary = sctp->sctp_faddrs; 4510Sstevel@tonic-gate sctp->sctp_current = sctp->sctp_faddrs; 4520Sstevel@tonic-gate cur_fp = sctp->sctp_current; 4530Sstevel@tonic-gate sctp->sctp_mss = sctp->sctp_faddrs->sfa_pmss; 4540Sstevel@tonic-gate sctp_conn_hash_insert(tbf, sctp, 1); 4550Sstevel@tonic-gate mutex_exit(&tbf->tf_lock); 4560Sstevel@tonic-gate 4570Sstevel@tonic-gate /* initialize composite headers */ 4580Sstevel@tonic-gate sctp_set_hdraddrs(sctp); 4590Sstevel@tonic-gate 4600Sstevel@tonic-gate /* 4610Sstevel@tonic-gate * Massage a routing header (if present) putting the first hop 4620Sstevel@tonic-gate * in ip6_dst. 4630Sstevel@tonic-gate */ 4640Sstevel@tonic-gate rth = ip_find_rthdr_v6(sctp->sctp_ip6h, 4650Sstevel@tonic-gate (uint8_t *)sctp->sctp_sctph6); 4660Sstevel@tonic-gate if (rth != NULL) 4670Sstevel@tonic-gate (void) ip_massage_options_v6(sctp->sctp_ip6h, rth); 4680Sstevel@tonic-gate 4690Sstevel@tonic-gate /* 4700Sstevel@tonic-gate * Turn off the don't fragment bit on the (only) faddr, 4710Sstevel@tonic-gate * so that if one of the messages exchanged during the 4720Sstevel@tonic-gate * initialization sequence exceeds the path mtu, it 4730Sstevel@tonic-gate * at least has a chance to get there. SCTP does no 4740Sstevel@tonic-gate * fragmentation of initialization messages. The DF bit 4750Sstevel@tonic-gate * will be turned on again in sctp_send_cookie_echo() 4760Sstevel@tonic-gate * (but the cookie echo will still be sent with the df bit 4770Sstevel@tonic-gate * off). 4780Sstevel@tonic-gate */ 4790Sstevel@tonic-gate cur_fp->df = B_FALSE; 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate /* Mark this address as alive */ 4820Sstevel@tonic-gate cur_fp->state = SCTP_FADDRS_ALIVE; 4830Sstevel@tonic-gate 4840Sstevel@tonic-gate /* This sctp_t is fully bound now. */ 4850Sstevel@tonic-gate sctp->sctp_connp->conn_fully_bound = B_TRUE; 4860Sstevel@tonic-gate 4870Sstevel@tonic-gate /* Send the INIT to the peer */ 4880Sstevel@tonic-gate SCTP_FADDR_TIMER_RESTART(sctp, cur_fp, cur_fp->rto); 489*432Svi117747 /* 490*432Svi117747 * sctp_init_mp() could result in modifying the source 491*432Svi117747 * address list, so take the hash lock. 492*432Svi117747 */ 493*432Svi117747 mutex_enter(&tbf->tf_lock); 4940Sstevel@tonic-gate initmp = sctp_init_mp(sctp); 4950Sstevel@tonic-gate if (initmp == NULL) { 496*432Svi117747 mutex_exit(&tbf->tf_lock); 4970Sstevel@tonic-gate WAKE_SCTP(sctp); 4980Sstevel@tonic-gate /* let timer retry */ 4990Sstevel@tonic-gate return (0); 5000Sstevel@tonic-gate } 501*432Svi117747 mutex_exit(&tbf->tf_lock); 5020Sstevel@tonic-gate sctp->sctp_state = SCTPS_COOKIE_WAIT; 5030Sstevel@tonic-gate WAKE_SCTP(sctp); 5040Sstevel@tonic-gate /* OK to call IP_PUT() here instead of sctp_add_sendq(). */ 5050Sstevel@tonic-gate CONN_INC_REF(sctp->sctp_connp); 5060Sstevel@tonic-gate initmp->b_flag |= MSGHASREF; 5070Sstevel@tonic-gate IP_PUT(initmp, sctp->sctp_connp, sctp->sctp_current->isv4); 5080Sstevel@tonic-gate BUMP_LOCAL(sctp->sctp_opkts); 5090Sstevel@tonic-gate 5100Sstevel@tonic-gate sctp->sctp_ulp_prop(sctp->sctp_ulpd, 5110Sstevel@tonic-gate sctp_wroff_xtra + hdrlen + sizeof (sctp_data_hdr_t), 0); 5120Sstevel@tonic-gate 5130Sstevel@tonic-gate return (0); 5140Sstevel@tonic-gate default: 5150Sstevel@tonic-gate ip0dbg(("sctp_connect: invalid state. %d\n", sctp->sctp_state)); 5160Sstevel@tonic-gate WAKE_SCTP(sctp); 5170Sstevel@tonic-gate return (EINVAL); 5180Sstevel@tonic-gate } 5190Sstevel@tonic-gate } 520