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, NULL }
66 };
67
68 /*
69 * Creates a sdp socket data structure.
70 */
71 /* ARGSUSED */
72 struct sonode *
73 socksdp_create(struct sockparams *sp, int family, int type, int protocol,
74 int version, int sflags, int *errorp, cred_t *cr)
75 {
76 struct sonode *so;
77 int kmflags = (sflags & SOCKET_NOSLEEP) ? KM_NOSLEEP : KM_SLEEP;
78
79 dprint(4, ("Inside sosdp_create: domain:%d proto:%d type:%d",
80 family, protocol, type));
81
82 *errorp = 0;
83 if (is_system_labeled()) {
84 *errorp = EOPNOTSUPP;
85 return (NULL);
86 }
87
88 if (version == SOV_STREAM) {
89 *errorp = EINVAL;
90 return (NULL);
91 }
92
93 /*
94 * We only support one type of SDP socket. Let sotpi_create()
95 * handle all other cases, such as raw socket.
96 */
97 if (!(family == AF_INET || family == AF_INET6) ||
98 !(type == SOCK_STREAM)) {
99 *errorp = EINVAL;
100 return (NULL);
101 }
102
103 so = kmem_cache_alloc(socket_cache, kmflags);
104 if (so == NULL) {
105 *errorp = ENOMEM;
106 return (NULL);
107 }
108
109 sonode_init(so, sp, family, type, protocol, &sosdp_sonodeops);
110 so->so_pollev |= SO_POLLEV_ALWAYS;
111
112 dprint(2, ("sosdp_create: %p domain %d type %d\n", (void *)so, family,
113 type));
114
115 if (version == SOV_DEFAULT) {
116 version = so_default_version;
117 }
118 so->so_version = (short)version;
119
120 /*
121 * set the default values to be INFPSZ
122 * if a protocol desires it can change the value later
123 */
124 so->so_proto_props.sopp_rxhiwat = SOCKET_RECVHIWATER;
125 so->so_proto_props.sopp_rxlowat = SOCKET_RECVLOWATER;
126 so->so_proto_props.sopp_maxpsz = INFPSZ;
127 so->so_proto_props.sopp_maxblk = INFPSZ;
128
129 return (so);
130 }
131
132 static void
133 socksdp_destroy(struct sonode *so)
134 {
135 ASSERT(so->so_ops == &sosdp_sonodeops);
136
137 sosdp_fini(so, CRED());
138
139 kmem_cache_free(socket_cache, so);
140 }
141
142 int
143 _init(void)
144 {
145 return (mod_install(&modlinkage));
146 }
147
148 int
149 _fini(void)
150 {
151 return (mod_remove(&modlinkage));
152 }
153
154 int
155 _info(struct modinfo *modinfop)
156 {
157 return (mod_info(&modlinkage, modinfop));
158 }