xref: /illumos-gate/usr/src/uts/common/inet/sockmods/sockmod_sctp.c (revision d496d3f8834a66aac9da86c94e941d41fdeff23b)
10f1702c5SYu Xiangning /*
20f1702c5SYu Xiangning  * CDDL HEADER START
30f1702c5SYu Xiangning  *
40f1702c5SYu Xiangning  * The contents of this file are subject to the terms of the
50f1702c5SYu Xiangning  * Common Development and Distribution License (the "License").
60f1702c5SYu Xiangning  * You may not use this file except in compliance with the License.
70f1702c5SYu Xiangning  *
80f1702c5SYu Xiangning  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90f1702c5SYu Xiangning  * or http://www.opensolaris.org/os/licensing.
100f1702c5SYu Xiangning  * See the License for the specific language governing permissions
110f1702c5SYu Xiangning  * and limitations under the License.
120f1702c5SYu Xiangning  *
130f1702c5SYu Xiangning  * When distributing Covered Code, include this CDDL HEADER in each
140f1702c5SYu Xiangning  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150f1702c5SYu Xiangning  * If applicable, add the following below this CDDL HEADER, with the
160f1702c5SYu Xiangning  * fields enclosed by brackets "[]" replaced with your own identifying
170f1702c5SYu Xiangning  * information: Portions Copyright [yyyy] [name of copyright owner]
180f1702c5SYu Xiangning  *
190f1702c5SYu Xiangning  * CDDL HEADER END
200f1702c5SYu Xiangning  */
210f1702c5SYu Xiangning 
220f1702c5SYu Xiangning /*
23*d496d3f8SErik Nordmark  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
240f1702c5SYu Xiangning  * Use is subject to license terms.
250f1702c5SYu Xiangning  */
260f1702c5SYu Xiangning 
270f1702c5SYu Xiangning #include <sys/sysmacros.h>
280f1702c5SYu Xiangning #include <sys/strsubr.h>
290f1702c5SYu Xiangning #include <sys/socket.h>
300f1702c5SYu Xiangning #include <sys/socketvar.h>
310f1702c5SYu Xiangning #include <sys/modctl.h>
320f1702c5SYu Xiangning #include <sys/cmn_err.h>
330f1702c5SYu Xiangning #include <netinet/sctp.h>
340f1702c5SYu Xiangning #include <fs/sockfs/sockcommon.h>
350f1702c5SYu Xiangning #include "socksctp.h"
360f1702c5SYu Xiangning 
370f1702c5SYu Xiangning struct sonode 	*socksctp_create(struct sockparams *, int, int, int,
380f1702c5SYu Xiangning 			    int, int, int *, cred_t *);
390f1702c5SYu Xiangning void 		socksctp_destroy(struct sonode *);
400f1702c5SYu Xiangning 
410f1702c5SYu Xiangning static int 	socksctp_constructor(void *, void *, int);
420f1702c5SYu Xiangning static void 	socksctp_destructor(void *, void *);
430f1702c5SYu Xiangning 
440f1702c5SYu Xiangning static __smod_priv_t sosctp_priv = {
450f1702c5SYu Xiangning 	socksctp_create,
460f1702c5SYu Xiangning 	socksctp_destroy,
470f1702c5SYu Xiangning 	NULL
480f1702c5SYu Xiangning };
490f1702c5SYu Xiangning 
500f1702c5SYu Xiangning static smod_reg_t sinfo = {
510f1702c5SYu Xiangning 	SOCKMOD_VERSION,
520f1702c5SYu Xiangning 	"socksctp",
530f1702c5SYu Xiangning 	SOCK_UC_VERSION,
540f1702c5SYu Xiangning 	SOCK_DC_VERSION,
550f1702c5SYu Xiangning 	NULL,
560f1702c5SYu Xiangning 	&sosctp_priv
570f1702c5SYu Xiangning };
580f1702c5SYu Xiangning 
590f1702c5SYu Xiangning kmem_cache_t *sosctp_assoccache;
600f1702c5SYu Xiangning static kmem_cache_t *sosctp_sockcache;
610f1702c5SYu Xiangning 
620f1702c5SYu Xiangning /*
630f1702c5SYu Xiangning  * Module linkage information for the kernel.
640f1702c5SYu Xiangning  */
650f1702c5SYu Xiangning static struct modlsockmod modlsockmod = {
660f1702c5SYu Xiangning 	&mod_sockmodops, "SCTP socket module", &sinfo
670f1702c5SYu Xiangning };
680f1702c5SYu Xiangning 
690f1702c5SYu Xiangning static struct modlinkage modlinkage = {
700f1702c5SYu Xiangning 	MODREV_1,
710f1702c5SYu Xiangning 	&modlsockmod,
720f1702c5SYu Xiangning 	NULL
730f1702c5SYu Xiangning };
740f1702c5SYu Xiangning 
750f1702c5SYu Xiangning static int
socksctp_init(void)760f1702c5SYu Xiangning socksctp_init(void)
770f1702c5SYu Xiangning {
780f1702c5SYu Xiangning 	sosctp_sockcache = kmem_cache_create("sctpsock",
790f1702c5SYu Xiangning 	    sizeof (struct sctp_sonode), 0, socksctp_constructor,
800f1702c5SYu Xiangning 	    socksctp_destructor, NULL, NULL, NULL, 0);
810f1702c5SYu Xiangning 	sosctp_assoccache = kmem_cache_create("sctp_assoc",
820f1702c5SYu Xiangning 	    sizeof (struct sctp_soassoc), 0, NULL, NULL, NULL, NULL, NULL, 0);
830f1702c5SYu Xiangning 	return (0);
840f1702c5SYu Xiangning }
850f1702c5SYu Xiangning 
860f1702c5SYu Xiangning static void
socksctp_fini(void)870f1702c5SYu Xiangning socksctp_fini(void)
880f1702c5SYu Xiangning {
890f1702c5SYu Xiangning 	kmem_cache_destroy(sosctp_sockcache);
900f1702c5SYu Xiangning 	kmem_cache_destroy(sosctp_assoccache);
910f1702c5SYu Xiangning }
920f1702c5SYu Xiangning 
930f1702c5SYu Xiangning /*ARGSUSED*/
940f1702c5SYu Xiangning static int
socksctp_constructor(void * buf,void * cdrarg,int kmflags)950f1702c5SYu Xiangning socksctp_constructor(void *buf, void *cdrarg, int kmflags)
960f1702c5SYu Xiangning {
970f1702c5SYu Xiangning 	struct sctp_sonode *ss = buf;
980f1702c5SYu Xiangning 	struct sonode *so = &ss->ss_so;
990f1702c5SYu Xiangning 
1000f1702c5SYu Xiangning 	ss->ss_type = SOSCTP_SOCKET;
1010f1702c5SYu Xiangning 	return (sonode_constructor((void *)so, cdrarg, kmflags));
1020f1702c5SYu Xiangning }
1030f1702c5SYu Xiangning 
1040f1702c5SYu Xiangning /*ARGSUSED*/
1050f1702c5SYu Xiangning static void
socksctp_destructor(void * buf,void * cdrarg)1060f1702c5SYu Xiangning socksctp_destructor(void *buf, void *cdrarg)
1070f1702c5SYu Xiangning {
1080f1702c5SYu Xiangning 	struct sctp_sonode *ss = buf;
1090f1702c5SYu Xiangning 	struct sonode *so = &ss->ss_so;
1100f1702c5SYu Xiangning 
1110f1702c5SYu Xiangning 	sonode_destructor((void *)so, cdrarg);
1120f1702c5SYu Xiangning }
1130f1702c5SYu Xiangning 
1140f1702c5SYu Xiangning /*
1150f1702c5SYu Xiangning  * Creates a sctp socket data structure.
1160f1702c5SYu Xiangning  */
1170f1702c5SYu Xiangning /* ARGSUSED */
1180f1702c5SYu Xiangning struct sonode *
socksctp_create(struct sockparams * sp,int family,int type,int protocol,int version,int sflags,int * errorp,cred_t * cr)1190f1702c5SYu Xiangning socksctp_create(struct sockparams *sp, int family, int type, int protocol,
1200f1702c5SYu Xiangning     int version, int sflags, int *errorp, cred_t *cr)
1210f1702c5SYu Xiangning {
1220f1702c5SYu Xiangning 	struct sctp_sonode *ss;
1230f1702c5SYu Xiangning 	struct sonode *so;
1240f1702c5SYu Xiangning 	int kmflags = (sflags & SOCKET_NOSLEEP) ? KM_NOSLEEP : KM_SLEEP;
1250f1702c5SYu Xiangning 
1260f1702c5SYu Xiangning 	if (version == SOV_STREAM) {
1270f1702c5SYu Xiangning 		*errorp = EINVAL;
1280f1702c5SYu Xiangning 		return (NULL);
1290f1702c5SYu Xiangning 	}
1300f1702c5SYu Xiangning 
1310f1702c5SYu Xiangning 	/*
1320f1702c5SYu Xiangning 	 * We only support two types of SCTP socket.  Let sotpi_create()
1330f1702c5SYu Xiangning 	 * handle all other cases, such as raw socket.
1340f1702c5SYu Xiangning 	 */
1350f1702c5SYu Xiangning 	if (!(family == AF_INET || family == AF_INET6) ||
1360f1702c5SYu Xiangning 	    !(type == SOCK_STREAM || type == SOCK_SEQPACKET)) {
1370f1702c5SYu Xiangning 		*errorp = EINVAL;
1380f1702c5SYu Xiangning 		return (NULL);
1390f1702c5SYu Xiangning 	}
1400f1702c5SYu Xiangning 
1410f1702c5SYu Xiangning 	ss = kmem_cache_alloc(sosctp_sockcache, kmflags);
1420f1702c5SYu Xiangning 	if (ss == NULL) {
1430f1702c5SYu Xiangning 		*errorp = ENOMEM;
1440f1702c5SYu Xiangning 		return (NULL);
1450f1702c5SYu Xiangning 	}
1460f1702c5SYu Xiangning 
1470f1702c5SYu Xiangning 	so = &ss->ss_so;
1480f1702c5SYu Xiangning 
1490f1702c5SYu Xiangning 	ss->ss_maxassoc	= 0;
1500f1702c5SYu Xiangning 	ss->ss_assoccnt	= 0;
1510f1702c5SYu Xiangning 	ss->ss_assocs	= NULL;
1520f1702c5SYu Xiangning 
1530f1702c5SYu Xiangning 	if (type == SOCK_STREAM) {
1540f1702c5SYu Xiangning 		sonode_init(so, sp, family, type, protocol,
1550f1702c5SYu Xiangning 		    &sosctp_sonodeops);
1560f1702c5SYu Xiangning 	} else {
1570f1702c5SYu Xiangning 		sonode_init(so, sp, family, type, protocol,
1580f1702c5SYu Xiangning 		    &sosctp_seq_sonodeops);
1590f1702c5SYu Xiangning 		ASSERT(type == SOCK_SEQPACKET);
1600f1702c5SYu Xiangning 		mutex_enter(&so->so_lock);
1610f1702c5SYu Xiangning 		(void) sosctp_aid_grow(ss, 1, kmflags);
1620f1702c5SYu Xiangning 		mutex_exit(&so->so_lock);
1630f1702c5SYu Xiangning 	}
1640f1702c5SYu Xiangning 
1650f1702c5SYu Xiangning 	if (version == SOV_DEFAULT) {
1660f1702c5SYu Xiangning 		version = so_default_version;
1670f1702c5SYu Xiangning 	}
1680f1702c5SYu Xiangning 	so->so_version = (short)version;
1690f1702c5SYu Xiangning 
1700f1702c5SYu Xiangning 	dprint(2, ("sosctp_create: %p domain %d type %d\n", (void *)so, family,
1710f1702c5SYu Xiangning 	    type));
1720f1702c5SYu Xiangning 
173*d496d3f8SErik Nordmark 	/*
174*d496d3f8SErik Nordmark 	 * set the default values to be INFPSZ
175*d496d3f8SErik Nordmark 	 * if a protocol desires it can change the value later
176*d496d3f8SErik Nordmark 	 */
177*d496d3f8SErik Nordmark 	so->so_proto_props.sopp_rxhiwat = SOCKET_RECVHIWATER;
178*d496d3f8SErik Nordmark 	so->so_proto_props.sopp_rxlowat = SOCKET_RECVLOWATER;
179*d496d3f8SErik Nordmark 	so->so_proto_props.sopp_maxpsz = INFPSZ;
180*d496d3f8SErik Nordmark 	so->so_proto_props.sopp_maxblk = INFPSZ;
181*d496d3f8SErik Nordmark 
1820f1702c5SYu Xiangning 	return (so);
1830f1702c5SYu Xiangning }
1840f1702c5SYu Xiangning 
1850f1702c5SYu Xiangning /*
1860f1702c5SYu Xiangning  * Free SCTP socket data structure.
1870f1702c5SYu Xiangning  */
1880f1702c5SYu Xiangning void
socksctp_destroy(struct sonode * so)1890f1702c5SYu Xiangning socksctp_destroy(struct sonode *so)
1900f1702c5SYu Xiangning {
1910f1702c5SYu Xiangning 	struct sctp_sonode *ss;
1920f1702c5SYu Xiangning 
1930f1702c5SYu Xiangning 	ASSERT((so->so_type == SOCK_STREAM || so->so_type == SOCK_SEQPACKET) &&
1940f1702c5SYu Xiangning 	    so->so_protocol == IPPROTO_SCTP);
1950f1702c5SYu Xiangning 
1960f1702c5SYu Xiangning 	sosctp_fini(so, CRED());
1970f1702c5SYu Xiangning 
1980f1702c5SYu Xiangning 	ss = SOTOSSO(so);
1990f1702c5SYu Xiangning 	kmem_cache_free(sosctp_sockcache, ss);
2000f1702c5SYu Xiangning }
2010f1702c5SYu Xiangning 
2020f1702c5SYu Xiangning int
_init(void)2030f1702c5SYu Xiangning _init(void)
2040f1702c5SYu Xiangning {
2050f1702c5SYu Xiangning 	int error = 0;
2060f1702c5SYu Xiangning 
2070f1702c5SYu Xiangning 	(void) socksctp_init();
2080f1702c5SYu Xiangning 
2090f1702c5SYu Xiangning 	if ((error = mod_install(&modlinkage)) != 0)
2100f1702c5SYu Xiangning 		socksctp_fini();
2110f1702c5SYu Xiangning 
2120f1702c5SYu Xiangning 	return (error);
2130f1702c5SYu Xiangning }
2140f1702c5SYu Xiangning 
2150f1702c5SYu Xiangning int
_fini(void)2160f1702c5SYu Xiangning _fini(void)
2170f1702c5SYu Xiangning {
2180f1702c5SYu Xiangning 	int error = 0;
2190f1702c5SYu Xiangning 
2200f1702c5SYu Xiangning 	if ((error = mod_remove(&modlinkage)) == 0)
2210f1702c5SYu Xiangning 		socksctp_fini();
2220f1702c5SYu Xiangning 
2230f1702c5SYu Xiangning 	return (error);
2240f1702c5SYu Xiangning }
2250f1702c5SYu Xiangning 
2260f1702c5SYu Xiangning int
_info(struct modinfo * modinfop)2270f1702c5SYu Xiangning _info(struct modinfo *modinfop)
2280f1702c5SYu Xiangning {
2290f1702c5SYu Xiangning 	return (mod_info(&modlinkage, modinfop));
2300f1702c5SYu Xiangning }
231