18348SEric.Yu@Sun.COM /*
28348SEric.Yu@Sun.COM * CDDL HEADER START
38348SEric.Yu@Sun.COM *
48348SEric.Yu@Sun.COM * The contents of this file are subject to the terms of the
58348SEric.Yu@Sun.COM * Common Development and Distribution License (the "License").
68348SEric.Yu@Sun.COM * You may not use this file except in compliance with the License.
78348SEric.Yu@Sun.COM *
88348SEric.Yu@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98348SEric.Yu@Sun.COM * or http://www.opensolaris.org/os/licensing.
108348SEric.Yu@Sun.COM * See the License for the specific language governing permissions
118348SEric.Yu@Sun.COM * and limitations under the License.
128348SEric.Yu@Sun.COM *
138348SEric.Yu@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
148348SEric.Yu@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158348SEric.Yu@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
168348SEric.Yu@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
178348SEric.Yu@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
188348SEric.Yu@Sun.COM *
198348SEric.Yu@Sun.COM * CDDL HEADER END
208348SEric.Yu@Sun.COM */
218348SEric.Yu@Sun.COM
228348SEric.Yu@Sun.COM /*
23*9059SErik.Nordmark@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
248348SEric.Yu@Sun.COM * Use is subject to license terms.
258348SEric.Yu@Sun.COM */
268348SEric.Yu@Sun.COM
278348SEric.Yu@Sun.COM #include <sys/sysmacros.h>
288348SEric.Yu@Sun.COM #include <sys/strsubr.h>
298348SEric.Yu@Sun.COM #include <sys/socket.h>
308348SEric.Yu@Sun.COM #include <sys/socketvar.h>
318348SEric.Yu@Sun.COM #include <sys/modctl.h>
328348SEric.Yu@Sun.COM #include <sys/cmn_err.h>
338348SEric.Yu@Sun.COM #include <netinet/sctp.h>
348348SEric.Yu@Sun.COM #include <fs/sockfs/sockcommon.h>
358348SEric.Yu@Sun.COM #include "socksctp.h"
368348SEric.Yu@Sun.COM
378348SEric.Yu@Sun.COM struct sonode *socksctp_create(struct sockparams *, int, int, int,
388348SEric.Yu@Sun.COM int, int, int *, cred_t *);
398348SEric.Yu@Sun.COM void socksctp_destroy(struct sonode *);
408348SEric.Yu@Sun.COM
418348SEric.Yu@Sun.COM static int socksctp_constructor(void *, void *, int);
428348SEric.Yu@Sun.COM static void socksctp_destructor(void *, void *);
438348SEric.Yu@Sun.COM
448348SEric.Yu@Sun.COM static __smod_priv_t sosctp_priv = {
458348SEric.Yu@Sun.COM socksctp_create,
468348SEric.Yu@Sun.COM socksctp_destroy,
478348SEric.Yu@Sun.COM NULL
488348SEric.Yu@Sun.COM };
498348SEric.Yu@Sun.COM
508348SEric.Yu@Sun.COM static smod_reg_t sinfo = {
518348SEric.Yu@Sun.COM SOCKMOD_VERSION,
528348SEric.Yu@Sun.COM "socksctp",
538348SEric.Yu@Sun.COM SOCK_UC_VERSION,
548348SEric.Yu@Sun.COM SOCK_DC_VERSION,
558348SEric.Yu@Sun.COM NULL,
568348SEric.Yu@Sun.COM &sosctp_priv
578348SEric.Yu@Sun.COM };
588348SEric.Yu@Sun.COM
598348SEric.Yu@Sun.COM kmem_cache_t *sosctp_assoccache;
608348SEric.Yu@Sun.COM static kmem_cache_t *sosctp_sockcache;
618348SEric.Yu@Sun.COM
628348SEric.Yu@Sun.COM /*
638348SEric.Yu@Sun.COM * Module linkage information for the kernel.
648348SEric.Yu@Sun.COM */
658348SEric.Yu@Sun.COM static struct modlsockmod modlsockmod = {
668348SEric.Yu@Sun.COM &mod_sockmodops, "SCTP socket module", &sinfo
678348SEric.Yu@Sun.COM };
688348SEric.Yu@Sun.COM
698348SEric.Yu@Sun.COM static struct modlinkage modlinkage = {
708348SEric.Yu@Sun.COM MODREV_1,
718348SEric.Yu@Sun.COM &modlsockmod,
728348SEric.Yu@Sun.COM NULL
738348SEric.Yu@Sun.COM };
748348SEric.Yu@Sun.COM
758348SEric.Yu@Sun.COM static int
socksctp_init(void)768348SEric.Yu@Sun.COM socksctp_init(void)
778348SEric.Yu@Sun.COM {
788348SEric.Yu@Sun.COM sosctp_sockcache = kmem_cache_create("sctpsock",
798348SEric.Yu@Sun.COM sizeof (struct sctp_sonode), 0, socksctp_constructor,
808348SEric.Yu@Sun.COM socksctp_destructor, NULL, NULL, NULL, 0);
818348SEric.Yu@Sun.COM sosctp_assoccache = kmem_cache_create("sctp_assoc",
828348SEric.Yu@Sun.COM sizeof (struct sctp_soassoc), 0, NULL, NULL, NULL, NULL, NULL, 0);
838348SEric.Yu@Sun.COM return (0);
848348SEric.Yu@Sun.COM }
858348SEric.Yu@Sun.COM
868348SEric.Yu@Sun.COM static void
socksctp_fini(void)878348SEric.Yu@Sun.COM socksctp_fini(void)
888348SEric.Yu@Sun.COM {
898348SEric.Yu@Sun.COM kmem_cache_destroy(sosctp_sockcache);
908348SEric.Yu@Sun.COM kmem_cache_destroy(sosctp_assoccache);
918348SEric.Yu@Sun.COM }
928348SEric.Yu@Sun.COM
938348SEric.Yu@Sun.COM /*ARGSUSED*/
948348SEric.Yu@Sun.COM static int
socksctp_constructor(void * buf,void * cdrarg,int kmflags)958348SEric.Yu@Sun.COM socksctp_constructor(void *buf, void *cdrarg, int kmflags)
968348SEric.Yu@Sun.COM {
978348SEric.Yu@Sun.COM struct sctp_sonode *ss = buf;
988348SEric.Yu@Sun.COM struct sonode *so = &ss->ss_so;
998348SEric.Yu@Sun.COM
1008348SEric.Yu@Sun.COM ss->ss_type = SOSCTP_SOCKET;
1018348SEric.Yu@Sun.COM return (sonode_constructor((void *)so, cdrarg, kmflags));
1028348SEric.Yu@Sun.COM }
1038348SEric.Yu@Sun.COM
1048348SEric.Yu@Sun.COM /*ARGSUSED*/
1058348SEric.Yu@Sun.COM static void
socksctp_destructor(void * buf,void * cdrarg)1068348SEric.Yu@Sun.COM socksctp_destructor(void *buf, void *cdrarg)
1078348SEric.Yu@Sun.COM {
1088348SEric.Yu@Sun.COM struct sctp_sonode *ss = buf;
1098348SEric.Yu@Sun.COM struct sonode *so = &ss->ss_so;
1108348SEric.Yu@Sun.COM
1118348SEric.Yu@Sun.COM sonode_destructor((void *)so, cdrarg);
1128348SEric.Yu@Sun.COM }
1138348SEric.Yu@Sun.COM
1148348SEric.Yu@Sun.COM /*
1158348SEric.Yu@Sun.COM * Creates a sctp socket data structure.
1168348SEric.Yu@Sun.COM */
1178348SEric.Yu@Sun.COM /* ARGSUSED */
1188348SEric.Yu@Sun.COM struct sonode *
socksctp_create(struct sockparams * sp,int family,int type,int protocol,int version,int sflags,int * errorp,cred_t * cr)1198348SEric.Yu@Sun.COM socksctp_create(struct sockparams *sp, int family, int type, int protocol,
1208348SEric.Yu@Sun.COM int version, int sflags, int *errorp, cred_t *cr)
1218348SEric.Yu@Sun.COM {
1228348SEric.Yu@Sun.COM struct sctp_sonode *ss;
1238348SEric.Yu@Sun.COM struct sonode *so;
1248348SEric.Yu@Sun.COM int kmflags = (sflags & SOCKET_NOSLEEP) ? KM_NOSLEEP : KM_SLEEP;
1258348SEric.Yu@Sun.COM
1268348SEric.Yu@Sun.COM if (version == SOV_STREAM) {
1278348SEric.Yu@Sun.COM *errorp = EINVAL;
1288348SEric.Yu@Sun.COM return (NULL);
1298348SEric.Yu@Sun.COM }
1308348SEric.Yu@Sun.COM
1318348SEric.Yu@Sun.COM /*
1328348SEric.Yu@Sun.COM * We only support two types of SCTP socket. Let sotpi_create()
1338348SEric.Yu@Sun.COM * handle all other cases, such as raw socket.
1348348SEric.Yu@Sun.COM */
1358348SEric.Yu@Sun.COM if (!(family == AF_INET || family == AF_INET6) ||
1368348SEric.Yu@Sun.COM !(type == SOCK_STREAM || type == SOCK_SEQPACKET)) {
1378348SEric.Yu@Sun.COM *errorp = EINVAL;
1388348SEric.Yu@Sun.COM return (NULL);
1398348SEric.Yu@Sun.COM }
1408348SEric.Yu@Sun.COM
1418348SEric.Yu@Sun.COM ss = kmem_cache_alloc(sosctp_sockcache, kmflags);
1428348SEric.Yu@Sun.COM if (ss == NULL) {
1438348SEric.Yu@Sun.COM *errorp = ENOMEM;
1448348SEric.Yu@Sun.COM return (NULL);
1458348SEric.Yu@Sun.COM }
1468348SEric.Yu@Sun.COM
1478348SEric.Yu@Sun.COM so = &ss->ss_so;
1488348SEric.Yu@Sun.COM
1498348SEric.Yu@Sun.COM ss->ss_maxassoc = 0;
1508348SEric.Yu@Sun.COM ss->ss_assoccnt = 0;
1518348SEric.Yu@Sun.COM ss->ss_assocs = NULL;
1528348SEric.Yu@Sun.COM
1538348SEric.Yu@Sun.COM if (type == SOCK_STREAM) {
1548348SEric.Yu@Sun.COM sonode_init(so, sp, family, type, protocol,
1558348SEric.Yu@Sun.COM &sosctp_sonodeops);
1568348SEric.Yu@Sun.COM } else {
1578348SEric.Yu@Sun.COM sonode_init(so, sp, family, type, protocol,
1588348SEric.Yu@Sun.COM &sosctp_seq_sonodeops);
1598348SEric.Yu@Sun.COM ASSERT(type == SOCK_SEQPACKET);
1608348SEric.Yu@Sun.COM mutex_enter(&so->so_lock);
1618348SEric.Yu@Sun.COM (void) sosctp_aid_grow(ss, 1, kmflags);
1628348SEric.Yu@Sun.COM mutex_exit(&so->so_lock);
1638348SEric.Yu@Sun.COM }
1648348SEric.Yu@Sun.COM
1658348SEric.Yu@Sun.COM if (version == SOV_DEFAULT) {
1668348SEric.Yu@Sun.COM version = so_default_version;
1678348SEric.Yu@Sun.COM }
1688348SEric.Yu@Sun.COM so->so_version = (short)version;
1698348SEric.Yu@Sun.COM
1708348SEric.Yu@Sun.COM dprint(2, ("sosctp_create: %p domain %d type %d\n", (void *)so, family,
1718348SEric.Yu@Sun.COM type));
1728348SEric.Yu@Sun.COM
173*9059SErik.Nordmark@Sun.COM /*
174*9059SErik.Nordmark@Sun.COM * set the default values to be INFPSZ
175*9059SErik.Nordmark@Sun.COM * if a protocol desires it can change the value later
176*9059SErik.Nordmark@Sun.COM */
177*9059SErik.Nordmark@Sun.COM so->so_proto_props.sopp_rxhiwat = SOCKET_RECVHIWATER;
178*9059SErik.Nordmark@Sun.COM so->so_proto_props.sopp_rxlowat = SOCKET_RECVLOWATER;
179*9059SErik.Nordmark@Sun.COM so->so_proto_props.sopp_maxpsz = INFPSZ;
180*9059SErik.Nordmark@Sun.COM so->so_proto_props.sopp_maxblk = INFPSZ;
181*9059SErik.Nordmark@Sun.COM
1828348SEric.Yu@Sun.COM return (so);
1838348SEric.Yu@Sun.COM }
1848348SEric.Yu@Sun.COM
1858348SEric.Yu@Sun.COM /*
1868348SEric.Yu@Sun.COM * Free SCTP socket data structure.
1878348SEric.Yu@Sun.COM */
1888348SEric.Yu@Sun.COM void
socksctp_destroy(struct sonode * so)1898348SEric.Yu@Sun.COM socksctp_destroy(struct sonode *so)
1908348SEric.Yu@Sun.COM {
1918348SEric.Yu@Sun.COM struct sctp_sonode *ss;
1928348SEric.Yu@Sun.COM
1938348SEric.Yu@Sun.COM ASSERT((so->so_type == SOCK_STREAM || so->so_type == SOCK_SEQPACKET) &&
1948348SEric.Yu@Sun.COM so->so_protocol == IPPROTO_SCTP);
1958348SEric.Yu@Sun.COM
1968348SEric.Yu@Sun.COM sosctp_fini(so, CRED());
1978348SEric.Yu@Sun.COM
1988348SEric.Yu@Sun.COM ss = SOTOSSO(so);
1998348SEric.Yu@Sun.COM kmem_cache_free(sosctp_sockcache, ss);
2008348SEric.Yu@Sun.COM }
2018348SEric.Yu@Sun.COM
2028348SEric.Yu@Sun.COM int
_init(void)2038348SEric.Yu@Sun.COM _init(void)
2048348SEric.Yu@Sun.COM {
2058348SEric.Yu@Sun.COM int error = 0;
2068348SEric.Yu@Sun.COM
2078348SEric.Yu@Sun.COM (void) socksctp_init();
2088348SEric.Yu@Sun.COM
2098348SEric.Yu@Sun.COM if ((error = mod_install(&modlinkage)) != 0)
2108348SEric.Yu@Sun.COM socksctp_fini();
2118348SEric.Yu@Sun.COM
2128348SEric.Yu@Sun.COM return (error);
2138348SEric.Yu@Sun.COM }
2148348SEric.Yu@Sun.COM
2158348SEric.Yu@Sun.COM int
_fini(void)2168348SEric.Yu@Sun.COM _fini(void)
2178348SEric.Yu@Sun.COM {
2188348SEric.Yu@Sun.COM int error = 0;
2198348SEric.Yu@Sun.COM
2208348SEric.Yu@Sun.COM if ((error = mod_remove(&modlinkage)) == 0)
2218348SEric.Yu@Sun.COM socksctp_fini();
2228348SEric.Yu@Sun.COM
2238348SEric.Yu@Sun.COM return (error);
2248348SEric.Yu@Sun.COM }
2258348SEric.Yu@Sun.COM
2268348SEric.Yu@Sun.COM int
_info(struct modinfo * modinfop)2278348SEric.Yu@Sun.COM _info(struct modinfo *modinfop)
2288348SEric.Yu@Sun.COM {
2298348SEric.Yu@Sun.COM return (mod_info(&modlinkage, modinfop));
2308348SEric.Yu@Sun.COM }
231