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
37struct sonode *socksdp_create(struct sockparams *, int, int, int,
38    int, int, int *, cred_t *);
39static void socksdp_destroy(struct sonode *);
40
41static __smod_priv_t sosdp_priv = {
42	socksdp_create,
43	socksdp_destroy,
44	NULL
45};
46
47static 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 */
59static struct modlsockmod modlsockmod = {
60	&mod_sockmodops, "SDP socket module", &sinfo
61};
62
63static struct modlinkage modlinkage = {
64	MODREV_1,
65	&modlsockmod,
66	NULL
67};
68
69/*
70 * Creates a sdp socket data structure.
71 */
72/* ARGSUSED */
73struct sonode *
74socksdp_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
133static void
134socksdp_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
143int
144_init(void)
145{
146	return (mod_install(&modlinkage));
147}
148
149int
150_fini(void)
151{
152	return (mod_remove(&modlinkage));
153}
154
155int
156_info(struct modinfo *modinfop)
157{
158	return (mod_info(&modlinkage, modinfop));
159}
160