1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 #include <sys/sysmacros.h>
27 #include <sys/strsubr.h>
28 #include <sys/socket.h>
29 #include <sys/socketvar.h>
30 #include <sys/modctl.h>
31 #include <sys/cmn_err.h>
32 #include <sys/vfs.h>
33 #include <inet/sdp_itf.h>
34 #include <fs/sockfs/sockcommon.h>
35 #include "socksdp.h"
36 
37 struct sonode *socksdp_create(struct sockparams *, int, int, int,
38     int, int, int *, cred_t *);
39 static void socksdp_destroy(struct sonode *);
40 
41 static __smod_priv_t sosdp_priv = {
42 	socksdp_create,
43 	socksdp_destroy,
44 	NULL
45 };
46 
47 static smod_reg_t sinfo = {
48 	SOCKMOD_VERSION,
49 	"socksdp",
50 	SOCK_UC_VERSION,
51 	SOCK_DC_VERSION,
52 	NULL,
53 	&sosdp_priv
54 };
55 
56 /*
57  * Module linkage information for the kernel
58  */
59 static struct modlsockmod modlsockmod = {
60 	&mod_sockmodops, "SDP socket module", &sinfo
61 };
62 
63 static struct modlinkage modlinkage = {
64 	MODREV_1,
65 	&modlsockmod,
66 	NULL
67 };
68 
69 /*
70  * Creates a sdp socket data structure.
71  */
72 /* ARGSUSED */
73 struct sonode *
socksdp_create(struct sockparams * sp,int family,int type,int protocol,int version,int sflags,int * errorp,cred_t * cr)74 socksdp_create(struct sockparams *sp, int family, int type, int protocol,
75 		    int version, int sflags, int *errorp, cred_t *cr)
76 {
77 	struct sonode *so;
78 	int kmflags = (sflags & SOCKET_NOSLEEP) ? KM_NOSLEEP : KM_SLEEP;
79 
80 	dprint(4, ("Inside sosdp_create: domain:%d proto:%d type:%d",
81 	    family, protocol, type));
82 
83 	*errorp = 0;
84 	if (is_system_labeled()) {
85 		*errorp = EOPNOTSUPP;
86 		return (NULL);
87 	}
88 
89 	if (version == SOV_STREAM) {
90 		*errorp = EINVAL;
91 		return (NULL);
92 	}
93 
94 	/*
95 	 * We only support one type of SDP socket.  Let sotpi_create()
96 	 * handle all other cases, such as raw socket.
97 	 */
98 	if (!(family == AF_INET || family == AF_INET6) ||
99 	    !(type == SOCK_STREAM)) {
100 		*errorp = EINVAL;
101 		return (NULL);
102 	}
103 
104 	so = kmem_cache_alloc(socket_cache, kmflags);
105 	if (so == NULL) {
106 		*errorp = ENOMEM;
107 		return (NULL);
108 	}
109 
110 	sonode_init(so, sp, family, type, protocol, &sosdp_sonodeops);
111 	so->so_pollev |= SO_POLLEV_ALWAYS;
112 
113 	dprint(2, ("sosdp_create: %p domain %d type %d\n", (void *)so, family,
114 	    type));
115 
116 	if (version == SOV_DEFAULT) {
117 		version = so_default_version;
118 	}
119 	so->so_version = (short)version;
120 
121 	/*
122 	 * set the default values to be INFPSZ
123 	 * if a protocol desires it can change the value later
124 	 */
125 	so->so_proto_props.sopp_rxhiwat = SOCKET_RECVHIWATER;
126 	so->so_proto_props.sopp_rxlowat = SOCKET_RECVLOWATER;
127 	so->so_proto_props.sopp_maxpsz = INFPSZ;
128 	so->so_proto_props.sopp_maxblk = INFPSZ;
129 
130 	return (so);
131 }
132 
133 static void
socksdp_destroy(struct sonode * so)134 socksdp_destroy(struct sonode *so)
135 {
136 	ASSERT(so->so_ops == &sosdp_sonodeops);
137 
138 	sosdp_fini(so, CRED());
139 
140 	kmem_cache_free(socket_cache, so);
141 }
142 
143 int
_init(void)144 _init(void)
145 {
146 	return (mod_install(&modlinkage));
147 }
148 
149 int
_fini(void)150 _fini(void)
151 {
152 	return (mod_remove(&modlinkage));
153 }
154 
155 int
_info(struct modinfo * modinfop)156 _info(struct modinfo *modinfop)
157 {
158 	return (mod_info(&modlinkage, modinfop));
159 }
160