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