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 /*
233448Sdh155122  * Copyright 2007 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>
391676Sjpk #include <sys/tsol/tndb.h>
400Sstevel@tonic-gate 
410Sstevel@tonic-gate #include <netinet/in.h>
420Sstevel@tonic-gate #include <netinet/ip6.h>
430Sstevel@tonic-gate 
440Sstevel@tonic-gate #include <inet/common.h>
450Sstevel@tonic-gate #include <inet/ip.h>
460Sstevel@tonic-gate #include <inet/ip6.h>
470Sstevel@tonic-gate #include <inet/ipclassifier.h>
480Sstevel@tonic-gate #include <inet/ipsec_impl.h>
490Sstevel@tonic-gate 
500Sstevel@tonic-gate #include "sctp_impl.h"
510Sstevel@tonic-gate #include "sctp_addr.h"
520Sstevel@tonic-gate 
530Sstevel@tonic-gate /*
540Sstevel@tonic-gate  * Common accept code.  Called by sctp_conn_request.
550Sstevel@tonic-gate  * cr_pkt is the INIT / INIT ACK packet.
560Sstevel@tonic-gate  */
570Sstevel@tonic-gate static int
580Sstevel@tonic-gate sctp_accept_comm(sctp_t *listener, sctp_t *acceptor, mblk_t *cr_pkt,
590Sstevel@tonic-gate     uint_t ip_hdr_len, sctp_init_chunk_t *iack)
600Sstevel@tonic-gate {
610Sstevel@tonic-gate 
620Sstevel@tonic-gate 	sctp_hdr_t		*sctph;
630Sstevel@tonic-gate 	sctp_chunk_hdr_t	*ich;
640Sstevel@tonic-gate 	sctp_init_chunk_t	*init;
650Sstevel@tonic-gate 	int			err;
660Sstevel@tonic-gate 	uint_t			sctp_options;
672776Skp158701 	conn_t			*aconnp;
681676Sjpk 	conn_t			*lconnp;
691676Sjpk 	cred_t			*cr;
703448Sdh155122 	sctp_stack_t	*sctps = listener->sctp_sctps;
710Sstevel@tonic-gate 
720Sstevel@tonic-gate 	sctph = (sctp_hdr_t *)(cr_pkt->b_rptr + ip_hdr_len);
730Sstevel@tonic-gate 	ASSERT(OK_32PTR(sctph));
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 	acceptor->sctp_lport = listener->sctp_lport;
760Sstevel@tonic-gate 	acceptor->sctp_fport = sctph->sh_sport;
770Sstevel@tonic-gate 
780Sstevel@tonic-gate 	ich = (sctp_chunk_hdr_t *)(iack + 1);
790Sstevel@tonic-gate 	init = (sctp_init_chunk_t *)(ich + 1);
800Sstevel@tonic-gate 
810Sstevel@tonic-gate 	/* acceptor isn't in any fanouts yet, so don't need to hold locks */
820Sstevel@tonic-gate 	ASSERT(acceptor->sctp_faddrs == NULL);
830Sstevel@tonic-gate 	err = sctp_get_addrparams(acceptor, listener, cr_pkt, ich,
840Sstevel@tonic-gate 	    &sctp_options);
850Sstevel@tonic-gate 	if (err != 0)
860Sstevel@tonic-gate 		return (err);
870Sstevel@tonic-gate 
882776Skp158701 	aconnp = acceptor->sctp_connp;
891676Sjpk 	lconnp = listener->sctp_connp;
901676Sjpk 	if (lconnp->conn_mlp_type != mlptSingle) {
912776Skp158701 		cr = aconnp->conn_peercred = DB_CRED(cr_pkt);
921676Sjpk 		if (cr != NULL)
931676Sjpk 			crhold(cr);
941676Sjpk 	}
951676Sjpk 
961735Skcpoon 	if ((err = sctp_set_hdraddrs(acceptor)) != 0)
971676Sjpk 		return (err);
981676Sjpk 
990Sstevel@tonic-gate 	if ((sctp_options & SCTP_PRSCTP_OPTION) &&
1003448Sdh155122 	    listener->sctp_prsctp_aware && sctps->sctps_prsctp_enabled) {
1010Sstevel@tonic-gate 		acceptor->sctp_prsctp_aware = B_TRUE;
1020Sstevel@tonic-gate 	} else {
1030Sstevel@tonic-gate 		acceptor->sctp_prsctp_aware = B_FALSE;
1040Sstevel@tonic-gate 	}
1050Sstevel@tonic-gate 	/* The new sctp_t is fully bound now. */
1060Sstevel@tonic-gate 	acceptor->sctp_connp->conn_fully_bound = B_TRUE;
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate 	/* Get  initial TSNs */
1090Sstevel@tonic-gate 	acceptor->sctp_ltsn = ntohl(iack->sic_inittsn);
1100Sstevel@tonic-gate 	acceptor->sctp_recovery_tsn = acceptor->sctp_lastack_rxd =
1110Sstevel@tonic-gate 	    acceptor->sctp_ltsn - 1;
1120Sstevel@tonic-gate 	acceptor->sctp_adv_pap = acceptor->sctp_lastack_rxd;
1130Sstevel@tonic-gate 	/* Serial numbers are initialized to the same value as the TSNs */
1140Sstevel@tonic-gate 	acceptor->sctp_lcsn = acceptor->sctp_ltsn;
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate 	if (!sctp_initialize_params(acceptor, init, iack))
1170Sstevel@tonic-gate 		return (ENOMEM);
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate 	/*
1200Sstevel@tonic-gate 	 * Copy sctp_secret from the listener in case we need to validate
1210Sstevel@tonic-gate 	 * a possibly delayed cookie.
1220Sstevel@tonic-gate 	 */
1230Sstevel@tonic-gate 	bcopy(listener->sctp_secret, acceptor->sctp_secret, SCTP_SECRET_LEN);
1240Sstevel@tonic-gate 	bcopy(listener->sctp_old_secret, acceptor->sctp_old_secret,
1250Sstevel@tonic-gate 	    SCTP_SECRET_LEN);
1260Sstevel@tonic-gate 	acceptor->sctp_last_secret_update = lbolt64;
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate 	/*
1290Sstevel@tonic-gate 	 * After acceptor is inserted in the hash list, it can be found.
1300Sstevel@tonic-gate 	 * So we need to lock it here.
1310Sstevel@tonic-gate 	 */
1320Sstevel@tonic-gate 	RUN_SCTP(acceptor);
1330Sstevel@tonic-gate 
1343448Sdh155122 	sctp_conn_hash_insert(&sctps->sctps_conn_fanout[
1353448Sdh155122 	    SCTP_CONN_HASH(sctps, acceptor->sctp_ports)], acceptor, 0);
1363448Sdh155122 	sctp_bind_hash_insert(&sctps->sctps_bind_fanout[
1370Sstevel@tonic-gate 	    SCTP_BIND_HASH(ntohs(acceptor->sctp_lport))], acceptor, 0);
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 	/*
1400Sstevel@tonic-gate 	 * No need to check for multicast destination since ip will only pass
1410Sstevel@tonic-gate 	 * up multicasts to those that have expressed interest
1420Sstevel@tonic-gate 	 * TODO: what about rejecting broadcasts?
1430Sstevel@tonic-gate 	 * Also check that source is not a multicast or broadcast address.
1440Sstevel@tonic-gate 	 */
1450Sstevel@tonic-gate 	/* XXXSCTP */
1460Sstevel@tonic-gate 	acceptor->sctp_state = SCTPS_ESTABLISHED;
1470Sstevel@tonic-gate 	acceptor->sctp_assoc_start_time = (uint32_t)lbolt;
1480Sstevel@tonic-gate 	/*
1490Sstevel@tonic-gate 	 * listener->sctp_rwnd should be the default window size or a
1500Sstevel@tonic-gate 	 * window size changed via SO_RCVBUF option.
1510Sstevel@tonic-gate 	 */
152852Svi117747 	acceptor->sctp_rwnd = listener->sctp_rwnd;
153852Svi117747 	acceptor->sctp_irwnd = acceptor->sctp_rwnd;
1543845Svi117747 	acceptor->sctp_pd_point = acceptor->sctp_rwnd;
1550Sstevel@tonic-gate 	bcopy(&listener->sctp_upcalls, &acceptor->sctp_upcalls,
1560Sstevel@tonic-gate 	    sizeof (sctp_upcalls_t));
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate 	return (0);
1590Sstevel@tonic-gate }
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate /* Process the COOKIE packet, mp, directed at the listener 'sctp' */
1620Sstevel@tonic-gate sctp_t *
1630Sstevel@tonic-gate sctp_conn_request(sctp_t *sctp, mblk_t *mp, uint_t ifindex, uint_t ip_hdr_len,
1640Sstevel@tonic-gate     sctp_init_chunk_t *iack, mblk_t *ipsec_mp)
1650Sstevel@tonic-gate {
1660Sstevel@tonic-gate 	sctp_t	*eager;
1670Sstevel@tonic-gate 	uint_t	ipvers;
1680Sstevel@tonic-gate 	ip6_t	*ip6h;
1690Sstevel@tonic-gate 	int	err;
1700Sstevel@tonic-gate 	conn_t	*connp, *econnp;
1713448Sdh155122 	sctp_stack_t	*sctps;
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate 	/*
1740Sstevel@tonic-gate 	 * No need to check for duplicate as this is the listener
1750Sstevel@tonic-gate 	 * and we are holding the lock.  This means that no new
1760Sstevel@tonic-gate 	 * connection can be created out of it.  And since the
1770Sstevel@tonic-gate 	 * fanout already done cannot find a match, it means that
1780Sstevel@tonic-gate 	 * there is no duplicate.
1790Sstevel@tonic-gate 	 */
1800Sstevel@tonic-gate 	ipvers = IPH_HDR_VERSION(mp->b_rptr);
1810Sstevel@tonic-gate 	ASSERT(ipvers == IPV6_VERSION || ipvers == IPV4_VERSION);
1820Sstevel@tonic-gate 	ASSERT(OK_32PTR(mp->b_rptr));
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 	if ((eager = sctp_create_eager(sctp)) == NULL) {
1850Sstevel@tonic-gate 		return (NULL);
1860Sstevel@tonic-gate 	}
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate 	if (ipvers != IPV4_VERSION) {
1890Sstevel@tonic-gate 		ip6h = (ip6_t *)mp->b_rptr;
190432Svi117747 		if (IN6_IS_ADDR_LINKLOCAL(&ip6h->ip6_src))
191432Svi117747 			eager->sctp_linklocal = 1;
1920Sstevel@tonic-gate 		/*
1930Sstevel@tonic-gate 		 * Record ifindex (might be zero) to tie this connection to
1940Sstevel@tonic-gate 		 * that interface if either the listener was bound or
1950Sstevel@tonic-gate 		 * if the connection is using link-local addresses.
1960Sstevel@tonic-gate 		 */
1970Sstevel@tonic-gate 		if (sctp->sctp_bound_if == ifindex ||
1980Sstevel@tonic-gate 		    IN6_IS_ADDR_LINKLOCAL(&ip6h->ip6_src))
1990Sstevel@tonic-gate 			eager->sctp_bound_if = ifindex;
2000Sstevel@tonic-gate 		/*
2010Sstevel@tonic-gate 		 * XXX broken. bound_if is always overwritten by statement
2020Sstevel@tonic-gate 		 * below. What is the right thing to do here?
2030Sstevel@tonic-gate 		 */
2040Sstevel@tonic-gate 		eager->sctp_bound_if = sctp->sctp_bound_if;
2050Sstevel@tonic-gate 	}
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate 	connp = sctp->sctp_connp;
2083448Sdh155122 	sctps = sctp->sctp_sctps;
2090Sstevel@tonic-gate 	econnp = eager->sctp_connp;
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate 	if (connp->conn_policy != NULL) {
2120Sstevel@tonic-gate 		ipsec_in_t *ii;
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate 		ASSERT(ipsec_mp != NULL);
2150Sstevel@tonic-gate 		ii = (ipsec_in_t *)(ipsec_mp->b_rptr);
2160Sstevel@tonic-gate 		ASSERT(ii->ipsec_in_policy == NULL);
2170Sstevel@tonic-gate 		IPPH_REFHOLD(connp->conn_policy);
2180Sstevel@tonic-gate 		ii->ipsec_in_policy = connp->conn_policy;
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 		ipsec_mp->b_datap->db_type = IPSEC_POLICY_SET;
2210Sstevel@tonic-gate 		if (!ip_bind_ipsec_policy_set(econnp, ipsec_mp)) {
2220Sstevel@tonic-gate 			sctp_close_eager(eager);
2233448Sdh155122 			BUMP_MIB(&sctps->sctps_mib, sctpListenDrop);
2240Sstevel@tonic-gate 			return (NULL);
2250Sstevel@tonic-gate 		}
2260Sstevel@tonic-gate 	}
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 	if (ipsec_mp != NULL) {
2290Sstevel@tonic-gate 		/*
2300Sstevel@tonic-gate 		 * XXX need to fix the cached policy issue here.
2310Sstevel@tonic-gate 		 * We temporarily set the conn_src/conn_rem here so
2320Sstevel@tonic-gate 		 * that IPsec can use it for the latched policy
2330Sstevel@tonic-gate 		 * selector.  This is obvioursly wrong as SCTP can
2340Sstevel@tonic-gate 		 * use different addresses...
2350Sstevel@tonic-gate 		 */
2360Sstevel@tonic-gate 		if (ipvers == IPV4_VERSION) {
2370Sstevel@tonic-gate 			ipha_t	*ipha;
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate 			ipha = (ipha_t *)mp->b_rptr;
2400Sstevel@tonic-gate 			econnp->conn_src = ipha->ipha_dst;
2410Sstevel@tonic-gate 			econnp->conn_rem = ipha->ipha_src;
2420Sstevel@tonic-gate 		} else {
2430Sstevel@tonic-gate 			econnp->conn_srcv6 = ip6h->ip6_dst;
2440Sstevel@tonic-gate 			econnp->conn_remv6 = ip6h->ip6_src;
2450Sstevel@tonic-gate 		}
2460Sstevel@tonic-gate 	}
2470Sstevel@tonic-gate 	if (ipsec_conn_cache_policy(econnp, ipvers == IPV4_VERSION) != 0) {
2480Sstevel@tonic-gate 		sctp_close_eager(eager);
2493448Sdh155122 		BUMP_MIB(&sctps->sctps_mib, sctpListenDrop);
2500Sstevel@tonic-gate 		return (NULL);
2510Sstevel@tonic-gate 	}
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 	err = sctp_accept_comm(sctp, eager, mp, ip_hdr_len, iack);
2540Sstevel@tonic-gate 	if (err) {
2550Sstevel@tonic-gate 		sctp_close_eager(eager);
2563448Sdh155122 		BUMP_MIB(&sctps->sctps_mib, sctpListenDrop);
2570Sstevel@tonic-gate 		return (NULL);
2580Sstevel@tonic-gate 	}
2590Sstevel@tonic-gate 
260852Svi117747 	/*
261852Svi117747 	 * On a clustered note send this notification to the clustering
262852Svi117747 	 * subsystem.
263852Svi117747 	 */
264852Svi117747 	if (cl_sctp_connect != NULL) {
265852Svi117747 		uchar_t	*slist;
266852Svi117747 		uchar_t	*flist;
267852Svi117747 		size_t	fsize;
268852Svi117747 		size_t	ssize;
269852Svi117747 
270852Svi117747 		fsize = sizeof (in6_addr_t) * eager->sctp_nfaddrs;
271852Svi117747 		ssize = sizeof (in6_addr_t) * eager->sctp_nsaddrs;
272852Svi117747 		slist = kmem_alloc(ssize, KM_NOSLEEP);
273852Svi117747 		flist = kmem_alloc(fsize, KM_NOSLEEP);
274852Svi117747 		if (slist == NULL || flist == NULL) {
275852Svi117747 			if (slist != NULL)
276852Svi117747 				kmem_free(slist, ssize);
277852Svi117747 			if (flist != NULL)
278852Svi117747 				kmem_free(flist, fsize);
279852Svi117747 			sctp_close_eager(eager);
2803448Sdh155122 			BUMP_MIB(&sctps->sctps_mib, sctpListenDrop);
2813448Sdh155122 			SCTP_KSTAT(sctps, sctp_cl_connect);
282852Svi117747 			return (NULL);
283852Svi117747 		}
284852Svi117747 		/* The clustering module frees these list */
285852Svi117747 		sctp_get_saddr_list(eager, slist, ssize);
286852Svi117747 		sctp_get_faddr_list(eager, flist, fsize);
287852Svi117747 		(*cl_sctp_connect)(eager->sctp_family, slist,
288852Svi117747 		    eager->sctp_nsaddrs, eager->sctp_lport, flist,
289852Svi117747 		    eager->sctp_nfaddrs, eager->sctp_fport, B_FALSE,
290852Svi117747 		    (cl_sctp_handle_t)eager);
291852Svi117747 	}
292852Svi117747 
2930Sstevel@tonic-gate 	/* Connection established, so send up the conn_ind */
2940Sstevel@tonic-gate 	if ((eager->sctp_ulpd = sctp->sctp_ulp_newconn(sctp->sctp_ulpd,
2950Sstevel@tonic-gate 	    eager)) == NULL) {
2960Sstevel@tonic-gate 		sctp_close_eager(eager);
2973448Sdh155122 		BUMP_MIB(&sctps->sctps_mib, sctpListenDrop);
2980Sstevel@tonic-gate 		return (NULL);
2990Sstevel@tonic-gate 	}
3000Sstevel@tonic-gate 	ASSERT(SCTP_IS_DETACHED(eager));
3010Sstevel@tonic-gate 	eager->sctp_detached = B_FALSE;
3020Sstevel@tonic-gate 	if (eager->sctp_family == AF_INET) {
3030Sstevel@tonic-gate 		eager->sctp_ulp_prop(eager->sctp_ulpd,
3043448Sdh155122 		    sctps->sctps_wroff_xtra + sizeof (sctp_data_hdr_t) +
3050Sstevel@tonic-gate 		    sctp->sctp_hdr_len, strmsgsz);
3060Sstevel@tonic-gate 	} else {
3070Sstevel@tonic-gate 		eager->sctp_ulp_prop(eager->sctp_ulpd,
3083448Sdh155122 		    sctps->sctps_wroff_xtra + sizeof (sctp_data_hdr_t) +
3090Sstevel@tonic-gate 		    sctp->sctp_hdr6_len, strmsgsz);
3100Sstevel@tonic-gate 	}
3110Sstevel@tonic-gate 	return (eager);
3120Sstevel@tonic-gate }
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate /*
3150Sstevel@tonic-gate  * Connect to a peer - this function inserts the sctp in the
3160Sstevel@tonic-gate  * bind and conn fanouts, sends the INIT, and replies to the client
3170Sstevel@tonic-gate  * with an OK ack.
3180Sstevel@tonic-gate  */
3190Sstevel@tonic-gate int
3200Sstevel@tonic-gate sctp_connect(sctp_t *sctp, const struct sockaddr *dst, uint32_t addrlen)
3210Sstevel@tonic-gate {
3220Sstevel@tonic-gate 	sin_t		*sin;
3230Sstevel@tonic-gate 	sin6_t		*sin6;
3240Sstevel@tonic-gate 	in6_addr_t	dstaddr;
3250Sstevel@tonic-gate 	in_port_t	dstport;
3260Sstevel@tonic-gate 	mblk_t		*initmp;
3270Sstevel@tonic-gate 	sctp_tf_t	*tbf;
3280Sstevel@tonic-gate 	sctp_t		*lsctp;
3290Sstevel@tonic-gate 	char		buf[INET6_ADDRSTRLEN];
3300Sstevel@tonic-gate 	int		sleep = sctp->sctp_cansleep ? KM_SLEEP : KM_NOSLEEP;
3310Sstevel@tonic-gate 	int 		hdrlen;
3320Sstevel@tonic-gate 	ip6_rthdr_t	*rth;
3331676Sjpk 	int		err;
3340Sstevel@tonic-gate 	sctp_faddr_t	*cur_fp;
3353448Sdh155122 	sctp_stack_t	*sctps = sctp->sctp_sctps;
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate 	/*
3380Sstevel@tonic-gate 	 * Determine packet type based on type of address passed in
3390Sstevel@tonic-gate 	 * the request should contain an IPv4 or IPv6 address.
3400Sstevel@tonic-gate 	 * Make sure that address family matches the type of
3410Sstevel@tonic-gate 	 * family of the the address passed down
3420Sstevel@tonic-gate 	 */
3430Sstevel@tonic-gate 	if (addrlen < sizeof (sin_t)) {
3440Sstevel@tonic-gate 		return (EINVAL);
3450Sstevel@tonic-gate 	}
3460Sstevel@tonic-gate 	switch (dst->sa_family) {
3470Sstevel@tonic-gate 	case AF_INET:
3480Sstevel@tonic-gate 		sin = (sin_t *)dst;
3490Sstevel@tonic-gate 
3500Sstevel@tonic-gate 		/* Check for attempt to connect to non-unicast */
351*5215Skcpoon 		if (CLASSD(sin->sin_addr.s_addr) ||
3520Sstevel@tonic-gate 		    (sin->sin_addr.s_addr == INADDR_BROADCAST)) {
3530Sstevel@tonic-gate 			ip0dbg(("sctp_connect: non-unicast\n"));
3540Sstevel@tonic-gate 			return (EINVAL);
3550Sstevel@tonic-gate 		}
3560Sstevel@tonic-gate 		if (sctp->sctp_connp->conn_ipv6_v6only)
3570Sstevel@tonic-gate 			return (EAFNOSUPPORT);
3580Sstevel@tonic-gate 
3590Sstevel@tonic-gate 		/* convert to v6 mapped */
3600Sstevel@tonic-gate 		/* Check for attempt to connect to INADDR_ANY */
3610Sstevel@tonic-gate 		if (sin->sin_addr.s_addr == INADDR_ANY)  {
3620Sstevel@tonic-gate 			struct in_addr v4_addr;
3630Sstevel@tonic-gate 			/*
3640Sstevel@tonic-gate 			 * SunOS 4.x and 4.3 BSD allow an application
3650Sstevel@tonic-gate 			 * to connect a TCP socket to INADDR_ANY.
3660Sstevel@tonic-gate 			 * When they do this, the kernel picks the
3670Sstevel@tonic-gate 			 * address of one interface and uses it
3680Sstevel@tonic-gate 			 * instead.  The kernel usually ends up
3690Sstevel@tonic-gate 			 * picking the address of the loopback
3700Sstevel@tonic-gate 			 * interface.  This is an undocumented feature.
3710Sstevel@tonic-gate 			 * However, we provide the same thing here
3720Sstevel@tonic-gate 			 * in case any TCP apps that use this feature
3730Sstevel@tonic-gate 			 * are being ported to SCTP...
3740Sstevel@tonic-gate 			 */
3750Sstevel@tonic-gate 			v4_addr.s_addr = htonl(INADDR_LOOPBACK);
3760Sstevel@tonic-gate 			IN6_INADDR_TO_V4MAPPED(&v4_addr, &dstaddr);
3770Sstevel@tonic-gate 		} else {
3780Sstevel@tonic-gate 			IN6_INADDR_TO_V4MAPPED(&sin->sin_addr, &dstaddr);
3790Sstevel@tonic-gate 		}
3800Sstevel@tonic-gate 		dstport = sin->sin_port;
3810Sstevel@tonic-gate 		if (sin->sin_family == AF_INET) {
3820Sstevel@tonic-gate 			hdrlen = sctp->sctp_hdr_len;
3830Sstevel@tonic-gate 		} else {
3840Sstevel@tonic-gate 			hdrlen = sctp->sctp_hdr6_len;
3850Sstevel@tonic-gate 		}
3860Sstevel@tonic-gate 		break;
3870Sstevel@tonic-gate 	case AF_INET6:
3880Sstevel@tonic-gate 		sin6 = (sin6_t *)dst;
3890Sstevel@tonic-gate 		/* Check for attempt to connect to non-unicast. */
3900Sstevel@tonic-gate 		if ((addrlen < sizeof (sin6_t)) ||
3910Sstevel@tonic-gate 		    IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
3920Sstevel@tonic-gate 			ip0dbg(("sctp_connect: non-unicast\n"));
3930Sstevel@tonic-gate 			return (EINVAL);
3940Sstevel@tonic-gate 		}
3950Sstevel@tonic-gate 		if (sctp->sctp_connp->conn_ipv6_v6only &&
3960Sstevel@tonic-gate 		    IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
3970Sstevel@tonic-gate 			return (EAFNOSUPPORT);
3980Sstevel@tonic-gate 		}
3990Sstevel@tonic-gate 		/* check for attempt to connect to unspec */
4000Sstevel@tonic-gate 		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
4010Sstevel@tonic-gate 			dstaddr = ipv6_loopback;
4020Sstevel@tonic-gate 		} else {
4030Sstevel@tonic-gate 			dstaddr = sin6->sin6_addr;
404432Svi117747 			if (IN6_IS_ADDR_LINKLOCAL(&dstaddr))
405432Svi117747 				sctp->sctp_linklocal = 1;
4060Sstevel@tonic-gate 		}
4070Sstevel@tonic-gate 		dstport = sin6->sin6_port;
4080Sstevel@tonic-gate 		hdrlen = sctp->sctp_hdr6_len;
4090Sstevel@tonic-gate 		break;
4100Sstevel@tonic-gate 	default:
4110Sstevel@tonic-gate 		dprint(1, ("sctp_connect: unknown family %d\n",
4124505Skcpoon 		    dst->sa_family));
4130Sstevel@tonic-gate 		return (EAFNOSUPPORT);
4140Sstevel@tonic-gate 	}
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate 	(void) inet_ntop(AF_INET6, &dstaddr, buf, sizeof (buf));
4170Sstevel@tonic-gate 	dprint(1, ("sctp_connect: attempting connect to %s...\n", buf));
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 	RUN_SCTP(sctp);
4200Sstevel@tonic-gate 
4214505Skcpoon 	if (sctp->sctp_family != dst->sa_family ||
4224505Skcpoon 	    (sctp->sctp_connp->conn_state_flags & CONN_CLOSING)) {
4230Sstevel@tonic-gate 		WAKE_SCTP(sctp);
4240Sstevel@tonic-gate 		return (EINVAL);
4250Sstevel@tonic-gate 	}
4260Sstevel@tonic-gate 
4270Sstevel@tonic-gate 	switch (sctp->sctp_state) {
4280Sstevel@tonic-gate 	case SCTPS_IDLE: {
429852Svi117747 		struct sockaddr_storage	ss;
430852Svi117747 
4310Sstevel@tonic-gate 		/*
4320Sstevel@tonic-gate 		 * We support a quick connect capability here, allowing
4330Sstevel@tonic-gate 		 * clients to transition directly from IDLE to COOKIE_WAIT.
4340Sstevel@tonic-gate 		 * sctp_bindi will pick an unused port, insert the connection
4350Sstevel@tonic-gate 		 * in the bind hash and transition to BOUND state. SCTP
4360Sstevel@tonic-gate 		 * picks and uses what it considers the optimal local address
4370Sstevel@tonic-gate 		 * set (just like specifiying INADDR_ANY to bind()).
4380Sstevel@tonic-gate 		 */
4390Sstevel@tonic-gate 		dprint(1, ("sctp_connect: idle, attempting bind...\n"));
4400Sstevel@tonic-gate 		ASSERT(sctp->sctp_nsaddrs == 0);
4410Sstevel@tonic-gate 
442852Svi117747 		bzero(&ss, sizeof (ss));
443852Svi117747 		ss.ss_family = sctp->sctp_family;
444852Svi117747 		WAKE_SCTP(sctp);
445852Svi117747 		if ((err = sctp_bind(sctp, (struct sockaddr *)&ss,
446852Svi117747 		    sizeof (ss))) != 0) {
4470Sstevel@tonic-gate 			return (err);
4480Sstevel@tonic-gate 		}
449852Svi117747 		RUN_SCTP(sctp);
4500Sstevel@tonic-gate 		/* FALLTHRU */
4510Sstevel@tonic-gate 	}
4520Sstevel@tonic-gate 
4530Sstevel@tonic-gate 	case SCTPS_BOUND:
4540Sstevel@tonic-gate 		ASSERT(sctp->sctp_nsaddrs > 0);
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate 		/* do the connect */
4570Sstevel@tonic-gate 		/* XXX check for attempt to connect to self */
4580Sstevel@tonic-gate 		sctp->sctp_fport = dstport;
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate 		ASSERT(sctp->sctp_iphc);
4610Sstevel@tonic-gate 		ASSERT(sctp->sctp_iphc6);
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate 		/*
4640Sstevel@tonic-gate 		 * Don't allow this connection to completely duplicate
4650Sstevel@tonic-gate 		 * an existing connection.
4660Sstevel@tonic-gate 		 *
4670Sstevel@tonic-gate 		 * Ensure that the duplicate check and insertion is atomic.
4680Sstevel@tonic-gate 		 */
4690Sstevel@tonic-gate 		sctp_conn_hash_remove(sctp);
4703448Sdh155122 		tbf = &sctps->sctps_conn_fanout[SCTP_CONN_HASH(sctps,
4714505Skcpoon 		    sctp->sctp_ports)];
4720Sstevel@tonic-gate 		mutex_enter(&tbf->tf_lock);
4730Sstevel@tonic-gate 		lsctp = sctp_lookup(sctp, &dstaddr, tbf, &sctp->sctp_ports,
4740Sstevel@tonic-gate 		    SCTPS_COOKIE_WAIT);
4750Sstevel@tonic-gate 		if (lsctp != NULL) {
4760Sstevel@tonic-gate 			/* found a duplicate connection */
4770Sstevel@tonic-gate 			mutex_exit(&tbf->tf_lock);
4780Sstevel@tonic-gate 			SCTP_REFRELE(lsctp);
4790Sstevel@tonic-gate 			WAKE_SCTP(sctp);
4800Sstevel@tonic-gate 			return (EADDRINUSE);
4810Sstevel@tonic-gate 		}
4820Sstevel@tonic-gate 		/*
4830Sstevel@tonic-gate 		 * OK; set up the peer addr (this may grow after we get
4840Sstevel@tonic-gate 		 * the INIT ACK from the peer with additional addresses).
4850Sstevel@tonic-gate 		 */
4861735Skcpoon 		if ((err = sctp_add_faddr(sctp, &dstaddr, sleep,
4871735Skcpoon 		    B_FALSE)) != 0) {
4880Sstevel@tonic-gate 			mutex_exit(&tbf->tf_lock);
4890Sstevel@tonic-gate 			WAKE_SCTP(sctp);
4901676Sjpk 			return (err);
4910Sstevel@tonic-gate 		}
4924818Skcpoon 		cur_fp = sctp->sctp_faddrs;
4934818Skcpoon 
4940Sstevel@tonic-gate 		/* No valid src addr, return. */
4954818Skcpoon 		if (cur_fp->state == SCTP_FADDRS_UNREACH) {
4960Sstevel@tonic-gate 			mutex_exit(&tbf->tf_lock);
4970Sstevel@tonic-gate 			WAKE_SCTP(sctp);
4980Sstevel@tonic-gate 			return (EADDRNOTAVAIL);
4990Sstevel@tonic-gate 		}
5004818Skcpoon 
5014818Skcpoon 		sctp->sctp_primary = cur_fp;
5024818Skcpoon 		sctp->sctp_current = cur_fp;
5034818Skcpoon 		sctp->sctp_mss = cur_fp->sfa_pmss;
5040Sstevel@tonic-gate 		sctp_conn_hash_insert(tbf, sctp, 1);
5050Sstevel@tonic-gate 		mutex_exit(&tbf->tf_lock);
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate 		/* initialize composite headers */
5081735Skcpoon 		if ((err = sctp_set_hdraddrs(sctp)) != 0) {
5091676Sjpk 			sctp_conn_hash_remove(sctp);
5101676Sjpk 			WAKE_SCTP(sctp);
5111676Sjpk 			return (err);
5121676Sjpk 		}
5130Sstevel@tonic-gate 
5140Sstevel@tonic-gate 		/*
5150Sstevel@tonic-gate 		 * Massage a routing header (if present) putting the first hop
5160Sstevel@tonic-gate 		 * in ip6_dst.
5170Sstevel@tonic-gate 		 */
5180Sstevel@tonic-gate 		rth = ip_find_rthdr_v6(sctp->sctp_ip6h,
5190Sstevel@tonic-gate 		    (uint8_t *)sctp->sctp_sctph6);
5203448Sdh155122 		if (rth != NULL) {
5213448Sdh155122 			(void) ip_massage_options_v6(sctp->sctp_ip6h, rth,
5223448Sdh155122 			    sctps->sctps_netstack);
5233448Sdh155122 		}
5240Sstevel@tonic-gate 
5250Sstevel@tonic-gate 		/*
5260Sstevel@tonic-gate 		 * Turn off the don't fragment bit on the (only) faddr,
5270Sstevel@tonic-gate 		 * so that if one of the messages exchanged during the
5280Sstevel@tonic-gate 		 * initialization sequence exceeds the path mtu, it
5290Sstevel@tonic-gate 		 * at least has a chance to get there. SCTP does no
5300Sstevel@tonic-gate 		 * fragmentation of initialization messages.  The DF bit
5310Sstevel@tonic-gate 		 * will be turned on again in sctp_send_cookie_echo()
5320Sstevel@tonic-gate 		 * (but the cookie echo will still be sent with the df bit
5330Sstevel@tonic-gate 		 * off).
5340Sstevel@tonic-gate 		 */
5350Sstevel@tonic-gate 		cur_fp->df = B_FALSE;
5360Sstevel@tonic-gate 
5370Sstevel@tonic-gate 		/* Mark this address as alive */
5380Sstevel@tonic-gate 		cur_fp->state = SCTP_FADDRS_ALIVE;
5390Sstevel@tonic-gate 
5400Sstevel@tonic-gate 		/* This sctp_t is fully bound now. */
5410Sstevel@tonic-gate 		sctp->sctp_connp->conn_fully_bound = B_TRUE;
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate 		/* Send the INIT to the peer */
5440Sstevel@tonic-gate 		SCTP_FADDR_TIMER_RESTART(sctp, cur_fp, cur_fp->rto);
5454818Skcpoon 		sctp->sctp_state = SCTPS_COOKIE_WAIT;
546432Svi117747 		/*
547432Svi117747 		 * sctp_init_mp() could result in modifying the source
548432Svi117747 		 * address list, so take the hash lock.
549432Svi117747 		 */
550432Svi117747 		mutex_enter(&tbf->tf_lock);
5510Sstevel@tonic-gate 		initmp = sctp_init_mp(sctp);
5520Sstevel@tonic-gate 		if (initmp == NULL) {
553432Svi117747 			mutex_exit(&tbf->tf_lock);
5544818Skcpoon 			/*
5554818Skcpoon 			 * It may happen that all the source addresses
5564818Skcpoon 			 * (loopback/link local) are removed.  In that case,
5574818Skcpoon 			 * faile the connect.
5584818Skcpoon 			 */
5594818Skcpoon 			if (sctp->sctp_nsaddrs == 0) {
5604818Skcpoon 				sctp_conn_hash_remove(sctp);
5614818Skcpoon 				SCTP_FADDR_TIMER_STOP(cur_fp);
5624818Skcpoon 				WAKE_SCTP(sctp);
5634818Skcpoon 				return (EADDRNOTAVAIL);
5644818Skcpoon 			}
5654818Skcpoon 
5664818Skcpoon 			/* Otherwise, let the retransmission timer retry */
5670Sstevel@tonic-gate 			WAKE_SCTP(sctp);
5684818Skcpoon 			goto notify_ulp;
5690Sstevel@tonic-gate 		}
570432Svi117747 		mutex_exit(&tbf->tf_lock);
5714818Skcpoon 
572852Svi117747 		/*
573852Svi117747 		 * On a clustered note send this notification to the clustering
574852Svi117747 		 * subsystem.
575852Svi117747 		 */
576852Svi117747 		if (cl_sctp_connect != NULL) {
577852Svi117747 			uchar_t		*slist;
578852Svi117747 			uchar_t		*flist;
579852Svi117747 			size_t		ssize;
580852Svi117747 			size_t		fsize;
581852Svi117747 
582852Svi117747 			fsize = sizeof (in6_addr_t) * sctp->sctp_nfaddrs;
583852Svi117747 			ssize = sizeof (in6_addr_t) * sctp->sctp_nsaddrs;
584852Svi117747 			slist = kmem_alloc(ssize, KM_SLEEP);
585852Svi117747 			flist = kmem_alloc(fsize, KM_SLEEP);
586852Svi117747 			/* The clustering module frees the lists */
587852Svi117747 			sctp_get_saddr_list(sctp, slist, ssize);
588852Svi117747 			sctp_get_faddr_list(sctp, flist, fsize);
589852Svi117747 			(*cl_sctp_connect)(sctp->sctp_family, slist,
590852Svi117747 			    sctp->sctp_nsaddrs, sctp->sctp_lport,
591852Svi117747 			    flist, sctp->sctp_nfaddrs, sctp->sctp_fport,
592852Svi117747 			    B_TRUE, (cl_sctp_handle_t)sctp);
593852Svi117747 		}
5940Sstevel@tonic-gate 		WAKE_SCTP(sctp);
5950Sstevel@tonic-gate 		/* OK to call IP_PUT() here instead of sctp_add_sendq(). */
5960Sstevel@tonic-gate 		CONN_INC_REF(sctp->sctp_connp);
5970Sstevel@tonic-gate 		initmp->b_flag |= MSGHASREF;
5980Sstevel@tonic-gate 		IP_PUT(initmp, sctp->sctp_connp, sctp->sctp_current->isv4);
5990Sstevel@tonic-gate 		BUMP_LOCAL(sctp->sctp_opkts);
6000Sstevel@tonic-gate 
6014818Skcpoon notify_ulp:
6020Sstevel@tonic-gate 		sctp->sctp_ulp_prop(sctp->sctp_ulpd,
6033448Sdh155122 		    sctps->sctps_wroff_xtra + hdrlen + sizeof (sctp_data_hdr_t),
6043448Sdh155122 		    0);
6050Sstevel@tonic-gate 
6060Sstevel@tonic-gate 		return (0);
6070Sstevel@tonic-gate 	default:
6080Sstevel@tonic-gate 		ip0dbg(("sctp_connect: invalid state. %d\n", sctp->sctp_state));
6090Sstevel@tonic-gate 		WAKE_SCTP(sctp);
6100Sstevel@tonic-gate 		return (EINVAL);
6110Sstevel@tonic-gate 	}
6120Sstevel@tonic-gate }
613