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 /* 2312534SGeorge.Shepherd@Sun.COM * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #include <sys/types.h> 270Sstevel@tonic-gate #include <sys/systm.h> 280Sstevel@tonic-gate #include <sys/stream.h> 290Sstevel@tonic-gate #include <sys/cmn_err.h> 300Sstevel@tonic-gate #include <sys/kmem.h> 310Sstevel@tonic-gate #define _SUN_TPI_VERSION 2 320Sstevel@tonic-gate #include <sys/tihdr.h> 330Sstevel@tonic-gate #include <sys/stropts.h> 340Sstevel@tonic-gate #include <sys/strsubr.h> 350Sstevel@tonic-gate #include <sys/socket.h> 361676Sjpk #include <sys/tsol/tndb.h> 370Sstevel@tonic-gate 380Sstevel@tonic-gate #include <netinet/in.h> 390Sstevel@tonic-gate #include <netinet/ip6.h> 400Sstevel@tonic-gate 410Sstevel@tonic-gate #include <inet/common.h> 420Sstevel@tonic-gate #include <inet/ip.h> 430Sstevel@tonic-gate #include <inet/ip6.h> 440Sstevel@tonic-gate #include <inet/ipclassifier.h> 450Sstevel@tonic-gate #include <inet/ipsec_impl.h> 460Sstevel@tonic-gate 470Sstevel@tonic-gate #include "sctp_impl.h" 480Sstevel@tonic-gate #include "sctp_addr.h" 490Sstevel@tonic-gate 500Sstevel@tonic-gate /* 510Sstevel@tonic-gate * Common accept code. Called by sctp_conn_request. 520Sstevel@tonic-gate * cr_pkt is the INIT / INIT ACK packet. 530Sstevel@tonic-gate */ 540Sstevel@tonic-gate static int 550Sstevel@tonic-gate sctp_accept_comm(sctp_t *listener, sctp_t *acceptor, mblk_t *cr_pkt, 560Sstevel@tonic-gate uint_t ip_hdr_len, sctp_init_chunk_t *iack) 570Sstevel@tonic-gate { 580Sstevel@tonic-gate 590Sstevel@tonic-gate sctp_hdr_t *sctph; 600Sstevel@tonic-gate sctp_chunk_hdr_t *ich; 610Sstevel@tonic-gate sctp_init_chunk_t *init; 620Sstevel@tonic-gate int err; 630Sstevel@tonic-gate uint_t sctp_options; 642776Skp158701 conn_t *aconnp; 651676Sjpk conn_t *lconnp; 66*12869SKacheong.Poon@Sun.COM sctp_stack_t *sctps = listener->sctp_sctps; 670Sstevel@tonic-gate 680Sstevel@tonic-gate sctph = (sctp_hdr_t *)(cr_pkt->b_rptr + ip_hdr_len); 690Sstevel@tonic-gate ASSERT(OK_32PTR(sctph)); 700Sstevel@tonic-gate 7111042SErik.Nordmark@Sun.COM aconnp = acceptor->sctp_connp; 7211042SErik.Nordmark@Sun.COM lconnp = listener->sctp_connp; 7311042SErik.Nordmark@Sun.COM aconnp->conn_lport = lconnp->conn_lport; 7411042SErik.Nordmark@Sun.COM aconnp->conn_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 861735Skcpoon if ((err = sctp_set_hdraddrs(acceptor)) != 0) 871676Sjpk return (err); 881676Sjpk 8911042SErik.Nordmark@Sun.COM if ((err = sctp_build_hdrs(acceptor, KM_NOSLEEP)) != 0) 9011042SErik.Nordmark@Sun.COM return (err); 9111042SErik.Nordmark@Sun.COM 920Sstevel@tonic-gate if ((sctp_options & SCTP_PRSCTP_OPTION) && 933448Sdh155122 listener->sctp_prsctp_aware && sctps->sctps_prsctp_enabled) { 940Sstevel@tonic-gate acceptor->sctp_prsctp_aware = B_TRUE; 950Sstevel@tonic-gate } else { 960Sstevel@tonic-gate acceptor->sctp_prsctp_aware = B_FALSE; 970Sstevel@tonic-gate } 980Sstevel@tonic-gate 990Sstevel@tonic-gate /* Get initial TSNs */ 1000Sstevel@tonic-gate acceptor->sctp_ltsn = ntohl(iack->sic_inittsn); 1010Sstevel@tonic-gate acceptor->sctp_recovery_tsn = acceptor->sctp_lastack_rxd = 1020Sstevel@tonic-gate acceptor->sctp_ltsn - 1; 1030Sstevel@tonic-gate acceptor->sctp_adv_pap = acceptor->sctp_lastack_rxd; 1040Sstevel@tonic-gate /* Serial numbers are initialized to the same value as the TSNs */ 1050Sstevel@tonic-gate acceptor->sctp_lcsn = acceptor->sctp_ltsn; 1060Sstevel@tonic-gate 1070Sstevel@tonic-gate if (!sctp_initialize_params(acceptor, init, iack)) 1080Sstevel@tonic-gate return (ENOMEM); 1090Sstevel@tonic-gate 1100Sstevel@tonic-gate /* 1110Sstevel@tonic-gate * Copy sctp_secret from the listener in case we need to validate 1120Sstevel@tonic-gate * a possibly delayed cookie. 1130Sstevel@tonic-gate */ 1140Sstevel@tonic-gate bcopy(listener->sctp_secret, acceptor->sctp_secret, SCTP_SECRET_LEN); 1150Sstevel@tonic-gate bcopy(listener->sctp_old_secret, acceptor->sctp_old_secret, 1160Sstevel@tonic-gate SCTP_SECRET_LEN); 11711066Srafael.vanoni@sun.com acceptor->sctp_last_secret_update = ddi_get_lbolt64(); 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate /* 1200Sstevel@tonic-gate * After acceptor is inserted in the hash list, it can be found. 1210Sstevel@tonic-gate * So we need to lock it here. 1220Sstevel@tonic-gate */ 1230Sstevel@tonic-gate RUN_SCTP(acceptor); 1240Sstevel@tonic-gate 1253448Sdh155122 sctp_conn_hash_insert(&sctps->sctps_conn_fanout[ 12611042SErik.Nordmark@Sun.COM SCTP_CONN_HASH(sctps, aconnp->conn_ports)], acceptor, 0); 1273448Sdh155122 sctp_bind_hash_insert(&sctps->sctps_bind_fanout[ 12811042SErik.Nordmark@Sun.COM SCTP_BIND_HASH(ntohs(aconnp->conn_lport))], acceptor, 0); 1290Sstevel@tonic-gate 130*12869SKacheong.Poon@Sun.COM SCTP_ASSOC_EST(sctps, acceptor); 131*12869SKacheong.Poon@Sun.COM 1320Sstevel@tonic-gate /* 1330Sstevel@tonic-gate * listener->sctp_rwnd should be the default window size or a 1340Sstevel@tonic-gate * window size changed via SO_RCVBUF option. 1350Sstevel@tonic-gate */ 136852Svi117747 acceptor->sctp_rwnd = listener->sctp_rwnd; 137852Svi117747 acceptor->sctp_irwnd = acceptor->sctp_rwnd; 1383845Svi117747 acceptor->sctp_pd_point = acceptor->sctp_rwnd; 1398348SEric.Yu@Sun.COM acceptor->sctp_upcalls = listener->sctp_upcalls; 1400Sstevel@tonic-gate 1410Sstevel@tonic-gate return (0); 1420Sstevel@tonic-gate } 1430Sstevel@tonic-gate 1440Sstevel@tonic-gate /* Process the COOKIE packet, mp, directed at the listener 'sctp' */ 1450Sstevel@tonic-gate sctp_t * 1460Sstevel@tonic-gate sctp_conn_request(sctp_t *sctp, mblk_t *mp, uint_t ifindex, uint_t ip_hdr_len, 14711042SErik.Nordmark@Sun.COM sctp_init_chunk_t *iack, ip_recv_attr_t *ira) 1480Sstevel@tonic-gate { 1490Sstevel@tonic-gate sctp_t *eager; 1500Sstevel@tonic-gate ip6_t *ip6h; 1510Sstevel@tonic-gate int err; 1520Sstevel@tonic-gate conn_t *connp, *econnp; 1533448Sdh155122 sctp_stack_t *sctps; 1548348SEric.Yu@Sun.COM struct sock_proto_props sopp; 1558778SErik.Nordmark@Sun.COM cred_t *cr; 1568778SErik.Nordmark@Sun.COM pid_t cpid; 15711042SErik.Nordmark@Sun.COM in6_addr_t faddr, laddr; 15811042SErik.Nordmark@Sun.COM ip_xmit_attr_t *ixa; 159*12869SKacheong.Poon@Sun.COM sctp_listen_cnt_t *slc = sctp->sctp_listen_cnt; 160*12869SKacheong.Poon@Sun.COM boolean_t slc_set = B_FALSE; 1610Sstevel@tonic-gate 1620Sstevel@tonic-gate /* 1630Sstevel@tonic-gate * No need to check for duplicate as this is the listener 1640Sstevel@tonic-gate * and we are holding the lock. This means that no new 1650Sstevel@tonic-gate * connection can be created out of it. And since the 1660Sstevel@tonic-gate * fanout already done cannot find a match, it means that 1670Sstevel@tonic-gate * there is no duplicate. 1680Sstevel@tonic-gate */ 1690Sstevel@tonic-gate ASSERT(OK_32PTR(mp->b_rptr)); 1700Sstevel@tonic-gate 171*12869SKacheong.Poon@Sun.COM connp = sctp->sctp_connp; 172*12869SKacheong.Poon@Sun.COM sctps = sctp->sctp_sctps; 173*12869SKacheong.Poon@Sun.COM 174*12869SKacheong.Poon@Sun.COM /* 175*12869SKacheong.Poon@Sun.COM * Enforce the limit set on the number of connections per listener. 176*12869SKacheong.Poon@Sun.COM * Note that tlc_cnt starts with 1. So need to add 1 to tlc_max 177*12869SKacheong.Poon@Sun.COM * for comparison. 178*12869SKacheong.Poon@Sun.COM */ 179*12869SKacheong.Poon@Sun.COM if (slc != NULL) { 180*12869SKacheong.Poon@Sun.COM int64_t now; 181*12869SKacheong.Poon@Sun.COM 182*12869SKacheong.Poon@Sun.COM if (atomic_add_32_nv(&slc->slc_cnt, 1) > slc->slc_max + 1) { 183*12869SKacheong.Poon@Sun.COM now = ddi_get_lbolt64(); 184*12869SKacheong.Poon@Sun.COM atomic_add_32(&slc->slc_cnt, -1); 185*12869SKacheong.Poon@Sun.COM SCTP_KSTAT(sctps, sctp_listen_cnt_drop); 186*12869SKacheong.Poon@Sun.COM slc->slc_drop++; 187*12869SKacheong.Poon@Sun.COM if (now - slc->slc_report_time > 188*12869SKacheong.Poon@Sun.COM MSEC_TO_TICK(SCTP_SLC_REPORT_INTERVAL)) { 189*12869SKacheong.Poon@Sun.COM zcmn_err(connp->conn_zoneid, CE_WARN, 190*12869SKacheong.Poon@Sun.COM "SCTP listener (port %d) association max " 191*12869SKacheong.Poon@Sun.COM "(%u) reached: %u attempts dropped total\n", 192*12869SKacheong.Poon@Sun.COM ntohs(connp->conn_lport), 193*12869SKacheong.Poon@Sun.COM slc->slc_max, slc->slc_drop); 194*12869SKacheong.Poon@Sun.COM slc->slc_report_time = now; 195*12869SKacheong.Poon@Sun.COM } 196*12869SKacheong.Poon@Sun.COM return (NULL); 197*12869SKacheong.Poon@Sun.COM } 198*12869SKacheong.Poon@Sun.COM slc_set = B_TRUE; 199*12869SKacheong.Poon@Sun.COM } 200*12869SKacheong.Poon@Sun.COM 2010Sstevel@tonic-gate if ((eager = sctp_create_eager(sctp)) == NULL) { 202*12869SKacheong.Poon@Sun.COM if (slc_set) 203*12869SKacheong.Poon@Sun.COM atomic_add_32(&slc->slc_cnt, -1); 2040Sstevel@tonic-gate return (NULL); 2050Sstevel@tonic-gate } 2060Sstevel@tonic-gate econnp = eager->sctp_connp; 2070Sstevel@tonic-gate 2080Sstevel@tonic-gate if (connp->conn_policy != NULL) { 20911042SErik.Nordmark@Sun.COM /* Inherit the policy from the listener; use actions from ira */ 21011042SErik.Nordmark@Sun.COM if (!ip_ipsec_policy_inherit(econnp, connp, ira)) { 2110Sstevel@tonic-gate sctp_close_eager(eager); 212*12869SKacheong.Poon@Sun.COM SCTPS_BUMP_MIB(sctps, sctpListenDrop); 2130Sstevel@tonic-gate return (NULL); 2140Sstevel@tonic-gate } 2150Sstevel@tonic-gate } 2160Sstevel@tonic-gate 21711042SErik.Nordmark@Sun.COM ip6h = (ip6_t *)mp->b_rptr; 21811042SErik.Nordmark@Sun.COM if (ira->ira_flags & IXAF_IS_IPV4) { 21911042SErik.Nordmark@Sun.COM ipha_t *ipha; 22011042SErik.Nordmark@Sun.COM 22111042SErik.Nordmark@Sun.COM ipha = (ipha_t *)ip6h; 22211042SErik.Nordmark@Sun.COM IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &laddr); 22311042SErik.Nordmark@Sun.COM IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &faddr); 22411042SErik.Nordmark@Sun.COM } else { 22511042SErik.Nordmark@Sun.COM laddr = ip6h->ip6_dst; 22611042SErik.Nordmark@Sun.COM faddr = ip6h->ip6_src; 22711042SErik.Nordmark@Sun.COM } 22811042SErik.Nordmark@Sun.COM 22911042SErik.Nordmark@Sun.COM if (ira->ira_flags & IRAF_IPSEC_SECURE) { 2300Sstevel@tonic-gate /* 2310Sstevel@tonic-gate * XXX need to fix the cached policy issue here. 23211042SErik.Nordmark@Sun.COM * We temporarily set the conn_laddr/conn_faddr here so 2330Sstevel@tonic-gate * that IPsec can use it for the latched policy 2340Sstevel@tonic-gate * selector. This is obvioursly wrong as SCTP can 2350Sstevel@tonic-gate * use different addresses... 2360Sstevel@tonic-gate */ 23711042SErik.Nordmark@Sun.COM econnp->conn_laddr_v6 = laddr; 23811042SErik.Nordmark@Sun.COM econnp->conn_faddr_v6 = faddr; 23911042SErik.Nordmark@Sun.COM econnp->conn_saddr_v6 = laddr; 2400Sstevel@tonic-gate } 24111042SErik.Nordmark@Sun.COM if (ipsec_conn_cache_policy(econnp, 24211042SErik.Nordmark@Sun.COM (ira->ira_flags & IRAF_IS_IPV4) != 0) != 0) { 2430Sstevel@tonic-gate sctp_close_eager(eager); 244*12869SKacheong.Poon@Sun.COM SCTPS_BUMP_MIB(sctps, sctpListenDrop); 2450Sstevel@tonic-gate return (NULL); 2460Sstevel@tonic-gate } 2470Sstevel@tonic-gate 2488778SErik.Nordmark@Sun.COM /* Save for getpeerucred */ 24911042SErik.Nordmark@Sun.COM cr = ira->ira_cred; 25011042SErik.Nordmark@Sun.COM cpid = ira->ira_cpid; 25111042SErik.Nordmark@Sun.COM 25211042SErik.Nordmark@Sun.COM if (is_system_labeled()) { 25311042SErik.Nordmark@Sun.COM ip_xmit_attr_t *ixa = econnp->conn_ixa; 25411042SErik.Nordmark@Sun.COM 25511042SErik.Nordmark@Sun.COM ASSERT(ira->ira_tsl != NULL); 25611042SErik.Nordmark@Sun.COM 25711042SErik.Nordmark@Sun.COM /* Discard any old label */ 25811042SErik.Nordmark@Sun.COM if (ixa->ixa_free_flags & IXA_FREE_TSL) { 25911042SErik.Nordmark@Sun.COM ASSERT(ixa->ixa_tsl != NULL); 26011042SErik.Nordmark@Sun.COM label_rele(ixa->ixa_tsl); 26111042SErik.Nordmark@Sun.COM ixa->ixa_free_flags &= ~IXA_FREE_TSL; 26211042SErik.Nordmark@Sun.COM ixa->ixa_tsl = NULL; 26311042SErik.Nordmark@Sun.COM } 26411042SErik.Nordmark@Sun.COM 26511042SErik.Nordmark@Sun.COM if ((connp->conn_mlp_type != mlptSingle || 26611042SErik.Nordmark@Sun.COM connp->conn_mac_mode != CONN_MAC_DEFAULT) && 26711042SErik.Nordmark@Sun.COM ira->ira_tsl != NULL) { 26811042SErik.Nordmark@Sun.COM /* 26911042SErik.Nordmark@Sun.COM * If this is an MLP connection or a MAC-Exempt 27011042SErik.Nordmark@Sun.COM * connection with an unlabeled node, packets are to be 27111042SErik.Nordmark@Sun.COM * exchanged using the security label of the received 27211042SErik.Nordmark@Sun.COM * Cookie packet instead of the server application's 27311042SErik.Nordmark@Sun.COM * label. 27411042SErik.Nordmark@Sun.COM * tsol_check_dest called from ip_set_destination 27511042SErik.Nordmark@Sun.COM * might later update TSF_UNLABELED by replacing 27611042SErik.Nordmark@Sun.COM * ixa_tsl with a new label. 27711042SErik.Nordmark@Sun.COM */ 27811042SErik.Nordmark@Sun.COM label_hold(ira->ira_tsl); 27911042SErik.Nordmark@Sun.COM ip_xmit_attr_replace_tsl(ixa, ira->ira_tsl); 28011042SErik.Nordmark@Sun.COM } else { 28111042SErik.Nordmark@Sun.COM ixa->ixa_tsl = crgetlabel(econnp->conn_cred); 28211042SErik.Nordmark@Sun.COM } 28311042SErik.Nordmark@Sun.COM } 2848778SErik.Nordmark@Sun.COM 2850Sstevel@tonic-gate err = sctp_accept_comm(sctp, eager, mp, ip_hdr_len, iack); 28611042SErik.Nordmark@Sun.COM if (err != 0) { 2870Sstevel@tonic-gate sctp_close_eager(eager); 288*12869SKacheong.Poon@Sun.COM SCTPS_BUMP_MIB(sctps, sctpListenDrop); 2890Sstevel@tonic-gate return (NULL); 2900Sstevel@tonic-gate } 2910Sstevel@tonic-gate 29211042SErik.Nordmark@Sun.COM ASSERT(eager->sctp_current->ixa != NULL); 29311042SErik.Nordmark@Sun.COM 29411042SErik.Nordmark@Sun.COM ixa = eager->sctp_current->ixa; 29511042SErik.Nordmark@Sun.COM if (!(ira->ira_flags & IXAF_IS_IPV4)) { 29611042SErik.Nordmark@Sun.COM ASSERT(!(ixa->ixa_flags & IXAF_IS_IPV4)); 29711042SErik.Nordmark@Sun.COM 29811042SErik.Nordmark@Sun.COM if (IN6_IS_ADDR_LINKLOCAL(&ip6h->ip6_src) || 29911042SErik.Nordmark@Sun.COM IN6_IS_ADDR_LINKLOCAL(&ip6h->ip6_dst)) { 30011042SErik.Nordmark@Sun.COM eager->sctp_linklocal = 1; 30111042SErik.Nordmark@Sun.COM 30211042SErik.Nordmark@Sun.COM ixa->ixa_flags |= IXAF_SCOPEID_SET; 30311042SErik.Nordmark@Sun.COM ixa->ixa_scopeid = ifindex; 30411042SErik.Nordmark@Sun.COM econnp->conn_incoming_ifindex = ifindex; 30511042SErik.Nordmark@Sun.COM } 30611042SErik.Nordmark@Sun.COM } 30711042SErik.Nordmark@Sun.COM 308852Svi117747 /* 309852Svi117747 * On a clustered note send this notification to the clustering 310852Svi117747 * subsystem. 311852Svi117747 */ 312852Svi117747 if (cl_sctp_connect != NULL) { 313852Svi117747 uchar_t *slist; 314852Svi117747 uchar_t *flist; 315852Svi117747 size_t fsize; 316852Svi117747 size_t ssize; 317852Svi117747 318852Svi117747 fsize = sizeof (in6_addr_t) * eager->sctp_nfaddrs; 319852Svi117747 ssize = sizeof (in6_addr_t) * eager->sctp_nsaddrs; 320852Svi117747 slist = kmem_alloc(ssize, KM_NOSLEEP); 321852Svi117747 flist = kmem_alloc(fsize, KM_NOSLEEP); 322852Svi117747 if (slist == NULL || flist == NULL) { 323852Svi117747 if (slist != NULL) 324852Svi117747 kmem_free(slist, ssize); 325852Svi117747 if (flist != NULL) 326852Svi117747 kmem_free(flist, fsize); 327852Svi117747 sctp_close_eager(eager); 328*12869SKacheong.Poon@Sun.COM SCTPS_BUMP_MIB(sctps, sctpListenDrop); 3293448Sdh155122 SCTP_KSTAT(sctps, sctp_cl_connect); 330852Svi117747 return (NULL); 331852Svi117747 } 332852Svi117747 /* The clustering module frees these list */ 333852Svi117747 sctp_get_saddr_list(eager, slist, ssize); 334852Svi117747 sctp_get_faddr_list(eager, flist, fsize); 33511042SErik.Nordmark@Sun.COM (*cl_sctp_connect)(econnp->conn_family, slist, 33611042SErik.Nordmark@Sun.COM eager->sctp_nsaddrs, econnp->conn_lport, flist, 33711042SErik.Nordmark@Sun.COM eager->sctp_nfaddrs, econnp->conn_fport, B_FALSE, 338852Svi117747 (cl_sctp_handle_t)eager); 339852Svi117747 } 340852Svi117747 3410Sstevel@tonic-gate /* Connection established, so send up the conn_ind */ 3420Sstevel@tonic-gate if ((eager->sctp_ulpd = sctp->sctp_ulp_newconn(sctp->sctp_ulpd, 3438778SErik.Nordmark@Sun.COM (sock_lower_handle_t)eager, NULL, cr, cpid, 3448348SEric.Yu@Sun.COM &eager->sctp_upcalls)) == NULL) { 3450Sstevel@tonic-gate sctp_close_eager(eager); 346*12869SKacheong.Poon@Sun.COM SCTPS_BUMP_MIB(sctps, sctpListenDrop); 3470Sstevel@tonic-gate return (NULL); 3480Sstevel@tonic-gate } 3490Sstevel@tonic-gate ASSERT(SCTP_IS_DETACHED(eager)); 3500Sstevel@tonic-gate eager->sctp_detached = B_FALSE; 3518348SEric.Yu@Sun.COM bzero(&sopp, sizeof (sopp)); 3528348SEric.Yu@Sun.COM sopp.sopp_flags = SOCKOPT_MAXBLK|SOCKOPT_WROFF; 3538348SEric.Yu@Sun.COM sopp.sopp_maxblk = strmsgsz; 35411042SErik.Nordmark@Sun.COM if (econnp->conn_family == AF_INET) { 3558348SEric.Yu@Sun.COM sopp.sopp_wroff = sctps->sctps_wroff_xtra + 3568348SEric.Yu@Sun.COM sizeof (sctp_data_hdr_t) + sctp->sctp_hdr_len; 3570Sstevel@tonic-gate } else { 3588348SEric.Yu@Sun.COM sopp.sopp_wroff = sctps->sctps_wroff_xtra + 3598348SEric.Yu@Sun.COM sizeof (sctp_data_hdr_t) + sctp->sctp_hdr6_len; 3600Sstevel@tonic-gate } 3618348SEric.Yu@Sun.COM eager->sctp_ulp_prop(eager->sctp_ulpd, &sopp); 3620Sstevel@tonic-gate return (eager); 3630Sstevel@tonic-gate } 3640Sstevel@tonic-gate 3650Sstevel@tonic-gate /* 3660Sstevel@tonic-gate * Connect to a peer - this function inserts the sctp in the 3670Sstevel@tonic-gate * bind and conn fanouts, sends the INIT, and replies to the client 3680Sstevel@tonic-gate * with an OK ack. 3690Sstevel@tonic-gate */ 3700Sstevel@tonic-gate int 37111042SErik.Nordmark@Sun.COM sctp_connect(sctp_t *sctp, const struct sockaddr *dst, uint32_t addrlen, 37211042SErik.Nordmark@Sun.COM cred_t *cr, pid_t pid) 3730Sstevel@tonic-gate { 3740Sstevel@tonic-gate sin_t *sin; 3750Sstevel@tonic-gate sin6_t *sin6; 3760Sstevel@tonic-gate in6_addr_t dstaddr; 3770Sstevel@tonic-gate in_port_t dstport; 3780Sstevel@tonic-gate mblk_t *initmp; 3790Sstevel@tonic-gate sctp_tf_t *tbf; 3800Sstevel@tonic-gate sctp_t *lsctp; 3810Sstevel@tonic-gate char buf[INET6_ADDRSTRLEN]; 3820Sstevel@tonic-gate int sleep = sctp->sctp_cansleep ? KM_SLEEP : KM_NOSLEEP; 3831676Sjpk int err; 3840Sstevel@tonic-gate sctp_faddr_t *cur_fp; 3853448Sdh155122 sctp_stack_t *sctps = sctp->sctp_sctps; 38611042SErik.Nordmark@Sun.COM conn_t *connp = sctp->sctp_connp; 38711042SErik.Nordmark@Sun.COM uint_t scope_id = 0; 38811042SErik.Nordmark@Sun.COM ip_xmit_attr_t *ixa; 3890Sstevel@tonic-gate 3900Sstevel@tonic-gate /* 3910Sstevel@tonic-gate * Determine packet type based on type of address passed in 3920Sstevel@tonic-gate * the request should contain an IPv4 or IPv6 address. 3930Sstevel@tonic-gate * Make sure that address family matches the type of 39411042SErik.Nordmark@Sun.COM * family of the address passed down. 3950Sstevel@tonic-gate */ 3960Sstevel@tonic-gate if (addrlen < sizeof (sin_t)) { 3970Sstevel@tonic-gate return (EINVAL); 3980Sstevel@tonic-gate } 3990Sstevel@tonic-gate switch (dst->sa_family) { 4000Sstevel@tonic-gate case AF_INET: 4010Sstevel@tonic-gate sin = (sin_t *)dst; 4020Sstevel@tonic-gate 4030Sstevel@tonic-gate /* Check for attempt to connect to non-unicast */ 4045215Skcpoon if (CLASSD(sin->sin_addr.s_addr) || 4050Sstevel@tonic-gate (sin->sin_addr.s_addr == INADDR_BROADCAST)) { 4060Sstevel@tonic-gate ip0dbg(("sctp_connect: non-unicast\n")); 4070Sstevel@tonic-gate return (EINVAL); 4080Sstevel@tonic-gate } 40911042SErik.Nordmark@Sun.COM if (connp->conn_ipv6_v6only) 4100Sstevel@tonic-gate return (EAFNOSUPPORT); 4110Sstevel@tonic-gate 4120Sstevel@tonic-gate /* convert to v6 mapped */ 4130Sstevel@tonic-gate /* Check for attempt to connect to INADDR_ANY */ 4140Sstevel@tonic-gate if (sin->sin_addr.s_addr == INADDR_ANY) { 4150Sstevel@tonic-gate struct in_addr v4_addr; 4160Sstevel@tonic-gate /* 4170Sstevel@tonic-gate * SunOS 4.x and 4.3 BSD allow an application 4180Sstevel@tonic-gate * to connect a TCP socket to INADDR_ANY. 4190Sstevel@tonic-gate * When they do this, the kernel picks the 4200Sstevel@tonic-gate * address of one interface and uses it 4210Sstevel@tonic-gate * instead. The kernel usually ends up 4220Sstevel@tonic-gate * picking the address of the loopback 4230Sstevel@tonic-gate * interface. This is an undocumented feature. 4240Sstevel@tonic-gate * However, we provide the same thing here 4250Sstevel@tonic-gate * in case any TCP apps that use this feature 4260Sstevel@tonic-gate * are being ported to SCTP... 4270Sstevel@tonic-gate */ 4280Sstevel@tonic-gate v4_addr.s_addr = htonl(INADDR_LOOPBACK); 4290Sstevel@tonic-gate IN6_INADDR_TO_V4MAPPED(&v4_addr, &dstaddr); 4300Sstevel@tonic-gate } else { 4310Sstevel@tonic-gate IN6_INADDR_TO_V4MAPPED(&sin->sin_addr, &dstaddr); 4320Sstevel@tonic-gate } 4330Sstevel@tonic-gate dstport = sin->sin_port; 4340Sstevel@tonic-gate break; 4350Sstevel@tonic-gate case AF_INET6: 4360Sstevel@tonic-gate sin6 = (sin6_t *)dst; 4370Sstevel@tonic-gate /* Check for attempt to connect to non-unicast. */ 4380Sstevel@tonic-gate if ((addrlen < sizeof (sin6_t)) || 4390Sstevel@tonic-gate IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { 4400Sstevel@tonic-gate ip0dbg(("sctp_connect: non-unicast\n")); 4410Sstevel@tonic-gate return (EINVAL); 4420Sstevel@tonic-gate } 44311042SErik.Nordmark@Sun.COM if (connp->conn_ipv6_v6only && 4440Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 4450Sstevel@tonic-gate return (EAFNOSUPPORT); 4460Sstevel@tonic-gate } 4470Sstevel@tonic-gate /* check for attempt to connect to unspec */ 4480Sstevel@tonic-gate if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 4490Sstevel@tonic-gate dstaddr = ipv6_loopback; 4500Sstevel@tonic-gate } else { 4510Sstevel@tonic-gate dstaddr = sin6->sin6_addr; 45211042SErik.Nordmark@Sun.COM if (IN6_IS_ADDR_LINKLOCAL(&dstaddr)) { 453432Svi117747 sctp->sctp_linklocal = 1; 45411042SErik.Nordmark@Sun.COM scope_id = sin6->sin6_scope_id; 45511042SErik.Nordmark@Sun.COM } 4560Sstevel@tonic-gate } 4570Sstevel@tonic-gate dstport = sin6->sin6_port; 45811042SErik.Nordmark@Sun.COM connp->conn_flowinfo = sin6->sin6_flowinfo; 4590Sstevel@tonic-gate break; 4600Sstevel@tonic-gate default: 4610Sstevel@tonic-gate dprint(1, ("sctp_connect: unknown family %d\n", 4624505Skcpoon dst->sa_family)); 4630Sstevel@tonic-gate return (EAFNOSUPPORT); 4640Sstevel@tonic-gate } 4650Sstevel@tonic-gate 4660Sstevel@tonic-gate (void) inet_ntop(AF_INET6, &dstaddr, buf, sizeof (buf)); 4670Sstevel@tonic-gate dprint(1, ("sctp_connect: attempting connect to %s...\n", buf)); 4680Sstevel@tonic-gate 4690Sstevel@tonic-gate RUN_SCTP(sctp); 4700Sstevel@tonic-gate 47111042SErik.Nordmark@Sun.COM if (connp->conn_family != dst->sa_family || 47211042SErik.Nordmark@Sun.COM (connp->conn_state_flags & CONN_CLOSING)) { 4730Sstevel@tonic-gate WAKE_SCTP(sctp); 4740Sstevel@tonic-gate return (EINVAL); 4750Sstevel@tonic-gate } 4760Sstevel@tonic-gate 47711042SErik.Nordmark@Sun.COM /* We update our cred/cpid based on the caller of connect */ 47811042SErik.Nordmark@Sun.COM if (connp->conn_cred != cr) { 47911042SErik.Nordmark@Sun.COM crhold(cr); 48011042SErik.Nordmark@Sun.COM crfree(connp->conn_cred); 48111042SErik.Nordmark@Sun.COM connp->conn_cred = cr; 48211042SErik.Nordmark@Sun.COM } 48311042SErik.Nordmark@Sun.COM connp->conn_cpid = pid; 48411042SErik.Nordmark@Sun.COM 48511042SErik.Nordmark@Sun.COM /* Cache things in conn_ixa without any refhold */ 48611042SErik.Nordmark@Sun.COM ixa = connp->conn_ixa; 48711849SErik.Nordmark@Sun.COM ASSERT(!(ixa->ixa_free_flags & IXA_FREE_CRED)); 48811042SErik.Nordmark@Sun.COM ixa->ixa_cred = cr; 48911042SErik.Nordmark@Sun.COM ixa->ixa_cpid = pid; 49011042SErik.Nordmark@Sun.COM if (is_system_labeled()) { 49111042SErik.Nordmark@Sun.COM /* We need to restart with a label based on the cred */ 49211042SErik.Nordmark@Sun.COM ip_xmit_attr_restore_tsl(ixa, ixa->ixa_cred); 49311042SErik.Nordmark@Sun.COM } 49411042SErik.Nordmark@Sun.COM 4950Sstevel@tonic-gate switch (sctp->sctp_state) { 4960Sstevel@tonic-gate case SCTPS_IDLE: { 497852Svi117747 struct sockaddr_storage ss; 498852Svi117747 4990Sstevel@tonic-gate /* 5000Sstevel@tonic-gate * We support a quick connect capability here, allowing 5010Sstevel@tonic-gate * clients to transition directly from IDLE to COOKIE_WAIT. 5020Sstevel@tonic-gate * sctp_bindi will pick an unused port, insert the connection 5030Sstevel@tonic-gate * in the bind hash and transition to BOUND state. SCTP 5040Sstevel@tonic-gate * picks and uses what it considers the optimal local address 5050Sstevel@tonic-gate * set (just like specifiying INADDR_ANY to bind()). 5060Sstevel@tonic-gate */ 5070Sstevel@tonic-gate dprint(1, ("sctp_connect: idle, attempting bind...\n")); 5080Sstevel@tonic-gate ASSERT(sctp->sctp_nsaddrs == 0); 5090Sstevel@tonic-gate 510852Svi117747 bzero(&ss, sizeof (ss)); 51111042SErik.Nordmark@Sun.COM ss.ss_family = connp->conn_family; 512852Svi117747 WAKE_SCTP(sctp); 513852Svi117747 if ((err = sctp_bind(sctp, (struct sockaddr *)&ss, 514852Svi117747 sizeof (ss))) != 0) { 5150Sstevel@tonic-gate return (err); 5160Sstevel@tonic-gate } 517852Svi117747 RUN_SCTP(sctp); 5180Sstevel@tonic-gate /* FALLTHRU */ 5190Sstevel@tonic-gate } 5200Sstevel@tonic-gate 5210Sstevel@tonic-gate case SCTPS_BOUND: 5220Sstevel@tonic-gate ASSERT(sctp->sctp_nsaddrs > 0); 5230Sstevel@tonic-gate 5240Sstevel@tonic-gate /* do the connect */ 5250Sstevel@tonic-gate /* XXX check for attempt to connect to self */ 52611042SErik.Nordmark@Sun.COM connp->conn_fport = dstport; 5270Sstevel@tonic-gate 5280Sstevel@tonic-gate /* 5290Sstevel@tonic-gate * Don't allow this connection to completely duplicate 5300Sstevel@tonic-gate * an existing connection. 5310Sstevel@tonic-gate * 5320Sstevel@tonic-gate * Ensure that the duplicate check and insertion is atomic. 5330Sstevel@tonic-gate */ 5340Sstevel@tonic-gate sctp_conn_hash_remove(sctp); 5353448Sdh155122 tbf = &sctps->sctps_conn_fanout[SCTP_CONN_HASH(sctps, 53611042SErik.Nordmark@Sun.COM connp->conn_ports)]; 5370Sstevel@tonic-gate mutex_enter(&tbf->tf_lock); 53811042SErik.Nordmark@Sun.COM lsctp = sctp_lookup(sctp, &dstaddr, tbf, &connp->conn_ports, 5390Sstevel@tonic-gate SCTPS_COOKIE_WAIT); 5400Sstevel@tonic-gate if (lsctp != NULL) { 5410Sstevel@tonic-gate /* found a duplicate connection */ 5420Sstevel@tonic-gate mutex_exit(&tbf->tf_lock); 5430Sstevel@tonic-gate SCTP_REFRELE(lsctp); 5440Sstevel@tonic-gate WAKE_SCTP(sctp); 5450Sstevel@tonic-gate return (EADDRINUSE); 5460Sstevel@tonic-gate } 54711042SErik.Nordmark@Sun.COM 5480Sstevel@tonic-gate /* 5490Sstevel@tonic-gate * OK; set up the peer addr (this may grow after we get 5500Sstevel@tonic-gate * the INIT ACK from the peer with additional addresses). 5510Sstevel@tonic-gate */ 5521735Skcpoon if ((err = sctp_add_faddr(sctp, &dstaddr, sleep, 5531735Skcpoon B_FALSE)) != 0) { 5540Sstevel@tonic-gate mutex_exit(&tbf->tf_lock); 5550Sstevel@tonic-gate WAKE_SCTP(sctp); 5561676Sjpk return (err); 5570Sstevel@tonic-gate } 5584818Skcpoon cur_fp = sctp->sctp_faddrs; 55911042SErik.Nordmark@Sun.COM ASSERT(cur_fp->ixa != NULL); 5604818Skcpoon 5610Sstevel@tonic-gate /* No valid src addr, return. */ 5624818Skcpoon if (cur_fp->state == SCTP_FADDRS_UNREACH) { 5630Sstevel@tonic-gate mutex_exit(&tbf->tf_lock); 5640Sstevel@tonic-gate WAKE_SCTP(sctp); 5650Sstevel@tonic-gate return (EADDRNOTAVAIL); 5660Sstevel@tonic-gate } 5674818Skcpoon 5684818Skcpoon sctp->sctp_primary = cur_fp; 5694818Skcpoon sctp->sctp_current = cur_fp; 5704818Skcpoon sctp->sctp_mss = cur_fp->sfa_pmss; 5710Sstevel@tonic-gate sctp_conn_hash_insert(tbf, sctp, 1); 5720Sstevel@tonic-gate mutex_exit(&tbf->tf_lock); 5730Sstevel@tonic-gate 57411042SErik.Nordmark@Sun.COM ixa = cur_fp->ixa; 57511042SErik.Nordmark@Sun.COM ASSERT(ixa->ixa_cred != NULL); 57611042SErik.Nordmark@Sun.COM 57711042SErik.Nordmark@Sun.COM if (scope_id != 0) { 57811042SErik.Nordmark@Sun.COM ixa->ixa_flags |= IXAF_SCOPEID_SET; 57911042SErik.Nordmark@Sun.COM ixa->ixa_scopeid = scope_id; 58011042SErik.Nordmark@Sun.COM } else { 58111042SErik.Nordmark@Sun.COM ixa->ixa_flags &= ~IXAF_SCOPEID_SET; 58211042SErik.Nordmark@Sun.COM } 58311042SErik.Nordmark@Sun.COM 5840Sstevel@tonic-gate /* initialize composite headers */ 5851735Skcpoon if ((err = sctp_set_hdraddrs(sctp)) != 0) { 5861676Sjpk sctp_conn_hash_remove(sctp); 5871676Sjpk WAKE_SCTP(sctp); 5881676Sjpk return (err); 5891676Sjpk } 5900Sstevel@tonic-gate 59111042SErik.Nordmark@Sun.COM if ((err = sctp_build_hdrs(sctp, KM_SLEEP)) != 0) { 59211042SErik.Nordmark@Sun.COM sctp_conn_hash_remove(sctp); 59311042SErik.Nordmark@Sun.COM WAKE_SCTP(sctp); 59411042SErik.Nordmark@Sun.COM return (err); 5953448Sdh155122 } 5960Sstevel@tonic-gate 5970Sstevel@tonic-gate /* 5980Sstevel@tonic-gate * Turn off the don't fragment bit on the (only) faddr, 5990Sstevel@tonic-gate * so that if one of the messages exchanged during the 6000Sstevel@tonic-gate * initialization sequence exceeds the path mtu, it 6010Sstevel@tonic-gate * at least has a chance to get there. SCTP does no 6020Sstevel@tonic-gate * fragmentation of initialization messages. The DF bit 6030Sstevel@tonic-gate * will be turned on again in sctp_send_cookie_echo() 6040Sstevel@tonic-gate * (but the cookie echo will still be sent with the df bit 6050Sstevel@tonic-gate * off). 6060Sstevel@tonic-gate */ 6070Sstevel@tonic-gate cur_fp->df = B_FALSE; 6080Sstevel@tonic-gate 6090Sstevel@tonic-gate /* Mark this address as alive */ 6100Sstevel@tonic-gate cur_fp->state = SCTP_FADDRS_ALIVE; 6110Sstevel@tonic-gate 6120Sstevel@tonic-gate /* Send the INIT to the peer */ 6130Sstevel@tonic-gate SCTP_FADDR_TIMER_RESTART(sctp, cur_fp, cur_fp->rto); 6144818Skcpoon sctp->sctp_state = SCTPS_COOKIE_WAIT; 615432Svi117747 /* 616432Svi117747 * sctp_init_mp() could result in modifying the source 617432Svi117747 * address list, so take the hash lock. 618432Svi117747 */ 619432Svi117747 mutex_enter(&tbf->tf_lock); 62011042SErik.Nordmark@Sun.COM initmp = sctp_init_mp(sctp, cur_fp); 6210Sstevel@tonic-gate if (initmp == NULL) { 622432Svi117747 mutex_exit(&tbf->tf_lock); 6234818Skcpoon /* 6244818Skcpoon * It may happen that all the source addresses 6254818Skcpoon * (loopback/link local) are removed. In that case, 6264818Skcpoon * faile the connect. 6274818Skcpoon */ 6284818Skcpoon if (sctp->sctp_nsaddrs == 0) { 6294818Skcpoon sctp_conn_hash_remove(sctp); 6304818Skcpoon SCTP_FADDR_TIMER_STOP(cur_fp); 6314818Skcpoon WAKE_SCTP(sctp); 6324818Skcpoon return (EADDRNOTAVAIL); 6334818Skcpoon } 6344818Skcpoon 6354818Skcpoon /* Otherwise, let the retransmission timer retry */ 6360Sstevel@tonic-gate WAKE_SCTP(sctp); 6374818Skcpoon goto notify_ulp; 6380Sstevel@tonic-gate } 639432Svi117747 mutex_exit(&tbf->tf_lock); 6404818Skcpoon 641852Svi117747 /* 642852Svi117747 * On a clustered note send this notification to the clustering 643852Svi117747 * subsystem. 644852Svi117747 */ 645852Svi117747 if (cl_sctp_connect != NULL) { 646852Svi117747 uchar_t *slist; 647852Svi117747 uchar_t *flist; 648852Svi117747 size_t ssize; 649852Svi117747 size_t fsize; 650852Svi117747 651852Svi117747 fsize = sizeof (in6_addr_t) * sctp->sctp_nfaddrs; 652852Svi117747 ssize = sizeof (in6_addr_t) * sctp->sctp_nsaddrs; 653852Svi117747 slist = kmem_alloc(ssize, KM_SLEEP); 654852Svi117747 flist = kmem_alloc(fsize, KM_SLEEP); 655852Svi117747 /* The clustering module frees the lists */ 656852Svi117747 sctp_get_saddr_list(sctp, slist, ssize); 657852Svi117747 sctp_get_faddr_list(sctp, flist, fsize); 65811042SErik.Nordmark@Sun.COM (*cl_sctp_connect)(connp->conn_family, slist, 65911042SErik.Nordmark@Sun.COM sctp->sctp_nsaddrs, connp->conn_lport, 66011042SErik.Nordmark@Sun.COM flist, sctp->sctp_nfaddrs, connp->conn_fport, 661852Svi117747 B_TRUE, (cl_sctp_handle_t)sctp); 662852Svi117747 } 66311042SErik.Nordmark@Sun.COM ASSERT(ixa->ixa_cred != NULL); 66411042SErik.Nordmark@Sun.COM ASSERT(ixa->ixa_ire != NULL); 66511042SErik.Nordmark@Sun.COM 66611042SErik.Nordmark@Sun.COM (void) conn_ip_output(initmp, ixa); 66711042SErik.Nordmark@Sun.COM BUMP_LOCAL(sctp->sctp_opkts); 6680Sstevel@tonic-gate WAKE_SCTP(sctp); 6690Sstevel@tonic-gate 6704818Skcpoon notify_ulp: 67111042SErik.Nordmark@Sun.COM sctp_set_ulp_prop(sctp); 6720Sstevel@tonic-gate 6730Sstevel@tonic-gate return (0); 6740Sstevel@tonic-gate default: 6750Sstevel@tonic-gate ip0dbg(("sctp_connect: invalid state. %d\n", sctp->sctp_state)); 6760Sstevel@tonic-gate WAKE_SCTP(sctp); 6770Sstevel@tonic-gate return (EINVAL); 6780Sstevel@tonic-gate } 6790Sstevel@tonic-gate } 680