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