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