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 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 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 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 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 * 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 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 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 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 2270f1702c5SYu Xiangning _info(struct modinfo *modinfop) 2280f1702c5SYu Xiangning { 2290f1702c5SYu Xiangning return (mod_info(&modlinkage, modinfop)); 2300f1702c5SYu Xiangning } 231