17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
545916cd2Sjpk  * Common Development and Distribution License (the "License").
645916cd2Sjpk  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
2177c67f2fSkcpoon 
227c478bd9Sstevel@tonic-gate /*
23481845d8SGeorge Shepherd  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <sys/types.h>
277c478bd9Sstevel@tonic-gate #include <sys/systm.h>
287c478bd9Sstevel@tonic-gate #include <sys/stream.h>
297c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
307c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
317c478bd9Sstevel@tonic-gate #define	_SUN_TPI_VERSION 2
327c478bd9Sstevel@tonic-gate #include <sys/tihdr.h>
337c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
347c478bd9Sstevel@tonic-gate #include <sys/strsubr.h>
357c478bd9Sstevel@tonic-gate #include <sys/socket.h>
3645916cd2Sjpk #include <sys/tsol/tndb.h>
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate #include <netinet/in.h>
397c478bd9Sstevel@tonic-gate #include <netinet/ip6.h>
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate #include <inet/common.h>
427c478bd9Sstevel@tonic-gate #include <inet/ip.h>
437c478bd9Sstevel@tonic-gate #include <inet/ip6.h>
447c478bd9Sstevel@tonic-gate #include <inet/ipclassifier.h>
457c478bd9Sstevel@tonic-gate #include <inet/ipsec_impl.h>
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate #include "sctp_impl.h"
487c478bd9Sstevel@tonic-gate #include "sctp_addr.h"
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate /*
517c478bd9Sstevel@tonic-gate  * Common accept code.  Called by sctp_conn_request.
527c478bd9Sstevel@tonic-gate  * cr_pkt is the INIT / INIT ACK packet.
537c478bd9Sstevel@tonic-gate  */
547c478bd9Sstevel@tonic-gate static int
sctp_accept_comm(sctp_t * listener,sctp_t * acceptor,mblk_t * cr_pkt,uint_t ip_hdr_len,sctp_init_chunk_t * iack)557c478bd9Sstevel@tonic-gate sctp_accept_comm(sctp_t *listener, sctp_t *acceptor, mblk_t *cr_pkt,
567c478bd9Sstevel@tonic-gate     uint_t ip_hdr_len, sctp_init_chunk_t *iack)
577c478bd9Sstevel@tonic-gate {
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate 	sctp_hdr_t		*sctph;
607c478bd9Sstevel@tonic-gate 	sctp_chunk_hdr_t	*ich;
617c478bd9Sstevel@tonic-gate 	sctp_init_chunk_t	*init;
627c478bd9Sstevel@tonic-gate 	int			err;
637c478bd9Sstevel@tonic-gate 	uint_t			sctp_options;
64d7ab25acSkp 	conn_t			*aconnp;
6545916cd2Sjpk 	conn_t			*lconnp;
665dd46ab5SKacheong Poon 	sctp_stack_t		*sctps = listener->sctp_sctps;
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate 	sctph = (sctp_hdr_t *)(cr_pkt->b_rptr + ip_hdr_len);
697c478bd9Sstevel@tonic-gate 	ASSERT(OK_32PTR(sctph));
707c478bd9Sstevel@tonic-gate 
71bd670b35SErik Nordmark 	aconnp = acceptor->sctp_connp;
72bd670b35SErik Nordmark 	lconnp = listener->sctp_connp;
73bd670b35SErik Nordmark 	aconnp->conn_lport = lconnp->conn_lport;
74bd670b35SErik Nordmark 	aconnp->conn_fport = sctph->sh_sport;
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate 	ich = (sctp_chunk_hdr_t *)(iack + 1);
777c478bd9Sstevel@tonic-gate 	init = (sctp_init_chunk_t *)(ich + 1);
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate 	/* acceptor isn't in any fanouts yet, so don't need to hold locks */
807c478bd9Sstevel@tonic-gate 	ASSERT(acceptor->sctp_faddrs == NULL);
817c478bd9Sstevel@tonic-gate 	err = sctp_get_addrparams(acceptor, listener, cr_pkt, ich,
827c478bd9Sstevel@tonic-gate 	    &sctp_options);
837c478bd9Sstevel@tonic-gate 	if (err != 0)
847c478bd9Sstevel@tonic-gate 		return (err);
857c478bd9Sstevel@tonic-gate 
8677c67f2fSkcpoon 	if ((err = sctp_set_hdraddrs(acceptor)) != 0)
8745916cd2Sjpk 		return (err);
8845916cd2Sjpk 
89bd670b35SErik Nordmark 	if ((err = sctp_build_hdrs(acceptor, KM_NOSLEEP)) != 0)
90bd670b35SErik Nordmark 		return (err);
91bd670b35SErik Nordmark 
927c478bd9Sstevel@tonic-gate 	if ((sctp_options & SCTP_PRSCTP_OPTION) &&
93f4b3ec61Sdh 	    listener->sctp_prsctp_aware && sctps->sctps_prsctp_enabled) {
947c478bd9Sstevel@tonic-gate 		acceptor->sctp_prsctp_aware = B_TRUE;
957c478bd9Sstevel@tonic-gate 	} else {
967c478bd9Sstevel@tonic-gate 		acceptor->sctp_prsctp_aware = B_FALSE;
977c478bd9Sstevel@tonic-gate 	}
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate 	/* Get  initial TSNs */
1007c478bd9Sstevel@tonic-gate 	acceptor->sctp_ltsn = ntohl(iack->sic_inittsn);
1017c478bd9Sstevel@tonic-gate 	acceptor->sctp_recovery_tsn = acceptor->sctp_lastack_rxd =
1027c478bd9Sstevel@tonic-gate 	    acceptor->sctp_ltsn - 1;
1037c478bd9Sstevel@tonic-gate 	acceptor->sctp_adv_pap = acceptor->sctp_lastack_rxd;
1047c478bd9Sstevel@tonic-gate 	/* Serial numbers are initialized to the same value as the TSNs */
1057c478bd9Sstevel@tonic-gate 	acceptor->sctp_lcsn = acceptor->sctp_ltsn;
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate 	if (!sctp_initialize_params(acceptor, init, iack))
1087c478bd9Sstevel@tonic-gate 		return (ENOMEM);
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 	/*
1117c478bd9Sstevel@tonic-gate 	 * Copy sctp_secret from the listener in case we need to validate
1127c478bd9Sstevel@tonic-gate 	 * a possibly delayed cookie.
1137c478bd9Sstevel@tonic-gate 	 */
1147c478bd9Sstevel@tonic-gate 	bcopy(listener->sctp_secret, acceptor->sctp_secret, SCTP_SECRET_LEN);
1157c478bd9Sstevel@tonic-gate 	bcopy(listener->sctp_old_secret, acceptor->sctp_old_secret,
1167c478bd9Sstevel@tonic-gate 	    SCTP_SECRET_LEN);
117d3d50737SRafael Vanoni 	acceptor->sctp_last_secret_update = ddi_get_lbolt64();
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 	/*
1207c478bd9Sstevel@tonic-gate 	 * After acceptor is inserted in the hash list, it can be found.
1217c478bd9Sstevel@tonic-gate 	 * So we need to lock it here.
1227c478bd9Sstevel@tonic-gate 	 */
1237c478bd9Sstevel@tonic-gate 	RUN_SCTP(acceptor);
1247c478bd9Sstevel@tonic-gate 
125f4b3ec61Sdh 	sctp_conn_hash_insert(&sctps->sctps_conn_fanout[
126bd670b35SErik Nordmark 	    SCTP_CONN_HASH(sctps, aconnp->conn_ports)], acceptor, 0);
127f4b3ec61Sdh 	sctp_bind_hash_insert(&sctps->sctps_bind_fanout[
128bd670b35SErik Nordmark 	    SCTP_BIND_HASH(ntohs(aconnp->conn_lport))], acceptor, 0);
1297c478bd9Sstevel@tonic-gate 
1305dd46ab5SKacheong Poon 	SCTP_ASSOC_EST(sctps, acceptor);
1317c478bd9Sstevel@tonic-gate 	return (0);
1327c478bd9Sstevel@tonic-gate }
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate /* Process the COOKIE packet, mp, directed at the listener 'sctp' */
1357c478bd9Sstevel@tonic-gate sctp_t *
sctp_conn_request(sctp_t * sctp,mblk_t * mp,uint_t ifindex,uint_t ip_hdr_len,sctp_init_chunk_t * iack,ip_recv_attr_t * ira)1367c478bd9Sstevel@tonic-gate sctp_conn_request(sctp_t *sctp, mblk_t *mp, uint_t ifindex, uint_t ip_hdr_len,
137bd670b35SErik Nordmark     sctp_init_chunk_t *iack, ip_recv_attr_t *ira)
1387c478bd9Sstevel@tonic-gate {
1397c478bd9Sstevel@tonic-gate 	sctp_t	*eager;
1407c478bd9Sstevel@tonic-gate 	ip6_t	*ip6h;
1417c478bd9Sstevel@tonic-gate 	int	err;
1427c478bd9Sstevel@tonic-gate 	conn_t	*connp, *econnp;
143f4b3ec61Sdh 	sctp_stack_t	*sctps;
144de8c4a14SErik Nordmark 	cred_t		*cr;
145de8c4a14SErik Nordmark 	pid_t		cpid;
146bd670b35SErik Nordmark 	in6_addr_t	faddr, laddr;
147bd670b35SErik Nordmark 	ip_xmit_attr_t	*ixa;
1485dd46ab5SKacheong Poon 	sctp_listen_cnt_t *slc = sctp->sctp_listen_cnt;
1495dd46ab5SKacheong Poon 	boolean_t	slc_set = B_FALSE;
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	/*
1527c478bd9Sstevel@tonic-gate 	 * No need to check for duplicate as this is the listener
1537c478bd9Sstevel@tonic-gate 	 * and we are holding the lock.  This means that no new
1547c478bd9Sstevel@tonic-gate 	 * connection can be created out of it.  And since the
1557c478bd9Sstevel@tonic-gate 	 * fanout already done cannot find a match, it means that
1567c478bd9Sstevel@tonic-gate 	 * there is no duplicate.
1577c478bd9Sstevel@tonic-gate 	 */
1587c478bd9Sstevel@tonic-gate 	ASSERT(OK_32PTR(mp->b_rptr));
1597c478bd9Sstevel@tonic-gate 
1605dd46ab5SKacheong Poon 	connp = sctp->sctp_connp;
1615dd46ab5SKacheong Poon 	sctps = sctp->sctp_sctps;
1625dd46ab5SKacheong Poon 
1635dd46ab5SKacheong Poon 	/*
1645dd46ab5SKacheong Poon 	 * Enforce the limit set on the number of connections per listener.
1655dd46ab5SKacheong Poon 	 * Note that tlc_cnt starts with 1.  So need to add 1 to tlc_max
1665dd46ab5SKacheong Poon 	 * for comparison.
1675dd46ab5SKacheong Poon 	 */
1685dd46ab5SKacheong Poon 	if (slc != NULL) {
1695dd46ab5SKacheong Poon 		int64_t now;
1705dd46ab5SKacheong Poon 
1711a5e258fSJosef 'Jeff' Sipek 		if (atomic_inc_32_nv(&slc->slc_cnt) > slc->slc_max + 1) {
1725dd46ab5SKacheong Poon 			now = ddi_get_lbolt64();
1731a5e258fSJosef 'Jeff' Sipek 			atomic_dec_32(&slc->slc_cnt);
1745dd46ab5SKacheong Poon 			SCTP_KSTAT(sctps, sctp_listen_cnt_drop);
1755dd46ab5SKacheong Poon 			slc->slc_drop++;
1765dd46ab5SKacheong Poon 			if (now - slc->slc_report_time >
1775dd46ab5SKacheong Poon 			    MSEC_TO_TICK(SCTP_SLC_REPORT_INTERVAL)) {
1785dd46ab5SKacheong Poon 				zcmn_err(connp->conn_zoneid, CE_WARN,
1795dd46ab5SKacheong Poon 				    "SCTP listener (port %d) association max "
1805dd46ab5SKacheong Poon 				    "(%u) reached: %u attempts dropped total\n",
1815dd46ab5SKacheong Poon 				    ntohs(connp->conn_lport),
1825dd46ab5SKacheong Poon 				    slc->slc_max, slc->slc_drop);
1835dd46ab5SKacheong Poon 				slc->slc_report_time = now;
1845dd46ab5SKacheong Poon 			}
1855dd46ab5SKacheong Poon 			return (NULL);
1865dd46ab5SKacheong Poon 		}
1875dd46ab5SKacheong Poon 		slc_set = B_TRUE;
1885dd46ab5SKacheong Poon 	}
1895dd46ab5SKacheong Poon 
1907c478bd9Sstevel@tonic-gate 	if ((eager = sctp_create_eager(sctp)) == NULL) {
1915dd46ab5SKacheong Poon 		if (slc_set)
1921a5e258fSJosef 'Jeff' Sipek 			atomic_dec_32(&slc->slc_cnt);
1937c478bd9Sstevel@tonic-gate 		return (NULL);
1947c478bd9Sstevel@tonic-gate 	}
1957c478bd9Sstevel@tonic-gate 	econnp = eager->sctp_connp;
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	if (connp->conn_policy != NULL) {
198bd670b35SErik Nordmark 		/* Inherit the policy from the listener; use actions from ira */
199bd670b35SErik Nordmark 		if (!ip_ipsec_policy_inherit(econnp, connp, ira)) {
2007c478bd9Sstevel@tonic-gate 			sctp_close_eager(eager);
2015dd46ab5SKacheong Poon 			SCTPS_BUMP_MIB(sctps, sctpListenDrop);
2027c478bd9Sstevel@tonic-gate 			return (NULL);
2037c478bd9Sstevel@tonic-gate 		}
2047c478bd9Sstevel@tonic-gate 	}
2057c478bd9Sstevel@tonic-gate 
206bd670b35SErik Nordmark 	ip6h = (ip6_t *)mp->b_rptr;
207bd670b35SErik Nordmark 	if (ira->ira_flags & IXAF_IS_IPV4) {
208bd670b35SErik Nordmark 		ipha_t	*ipha;
209bd670b35SErik Nordmark 
210bd670b35SErik Nordmark 		ipha = (ipha_t *)ip6h;
211bd670b35SErik Nordmark 		IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &laddr);
212bd670b35SErik Nordmark 		IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &faddr);
213bd670b35SErik Nordmark 	} else {
214bd670b35SErik Nordmark 		laddr = ip6h->ip6_dst;
215bd670b35SErik Nordmark 		faddr = ip6h->ip6_src;
216bd670b35SErik Nordmark 	}
217bd670b35SErik Nordmark 
218bd670b35SErik Nordmark 	if (ira->ira_flags & IRAF_IPSEC_SECURE) {
2197c478bd9Sstevel@tonic-gate 		/*
2207c478bd9Sstevel@tonic-gate 		 * XXX need to fix the cached policy issue here.
221bd670b35SErik Nordmark 		 * We temporarily set the conn_laddr/conn_faddr here so
2227c478bd9Sstevel@tonic-gate 		 * that IPsec can use it for the latched policy
2237c478bd9Sstevel@tonic-gate 		 * selector.  This is obvioursly wrong as SCTP can
2247c478bd9Sstevel@tonic-gate 		 * use different addresses...
2257c478bd9Sstevel@tonic-gate 		 */
226bd670b35SErik Nordmark 		econnp->conn_laddr_v6 = laddr;
227bd670b35SErik Nordmark 		econnp->conn_faddr_v6 = faddr;
228bd670b35SErik Nordmark 		econnp->conn_saddr_v6 = laddr;
2297c478bd9Sstevel@tonic-gate 	}
230bd670b35SErik Nordmark 	if (ipsec_conn_cache_policy(econnp,
231bd670b35SErik Nordmark 	    (ira->ira_flags & IRAF_IS_IPV4) != 0) != 0) {
2327c478bd9Sstevel@tonic-gate 		sctp_close_eager(eager);
2335dd46ab5SKacheong Poon 		SCTPS_BUMP_MIB(sctps, sctpListenDrop);
2347c478bd9Sstevel@tonic-gate 		return (NULL);
2357c478bd9Sstevel@tonic-gate 	}
2367c478bd9Sstevel@tonic-gate 
237de8c4a14SErik Nordmark 	/* Save for getpeerucred */
238bd670b35SErik Nordmark 	cr = ira->ira_cred;
239bd670b35SErik Nordmark 	cpid = ira->ira_cpid;
240bd670b35SErik Nordmark 
241bd670b35SErik Nordmark 	if (is_system_labeled()) {
242bd670b35SErik Nordmark 		ip_xmit_attr_t *ixa = econnp->conn_ixa;
243bd670b35SErik Nordmark 
244bd670b35SErik Nordmark 		ASSERT(ira->ira_tsl != NULL);
245bd670b35SErik Nordmark 
246bd670b35SErik Nordmark 		/* Discard any old label */
247bd670b35SErik Nordmark 		if (ixa->ixa_free_flags & IXA_FREE_TSL) {
248