/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/sysmacros.h>
#include <sys/strsubr.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/modctl.h>
#include <sys/cmn_err.h>
#include <sys/vfs.h>
#include <inet/sdp_itf.h>
#include <fs/sockfs/sockcommon.h>
#include "socksdp.h"
struct sonode *socksdp_create(struct sockparams *, int, int, int,
int, int, int *, cred_t *);
static void socksdp_destroy(struct sonode *);
static __smod_priv_t sosdp_priv = {
socksdp_create,
socksdp_destroy,
NULL
};
static smod_reg_t sinfo = {
SOCKMOD_VERSION,
"socksdp",
SOCK_UC_VERSION,
SOCK_DC_VERSION,
NULL,
&sosdp_priv
};
/*
* Module linkage information for the kernel
*/
static struct modlsockmod modlsockmod = {
&mod_sockmodops, "SDP socket module", &sinfo
};
static struct modlinkage modlinkage = {
MODREV_1,
&modlsockmod,
NULL
};
/*
* Creates a sdp socket data structure.
*/
/* ARGSUSED */
struct sonode *
socksdp_create(struct sockparams *sp, int family, int type, int protocol,
int version, int sflags, int *errorp, cred_t *cr)
{
struct sonode *so;
int kmflags = (sflags & SOCKET_NOSLEEP) ? KM_NOSLEEP : KM_SLEEP;
dprint(4, ("Inside sosdp_create: domain:%d proto:%d type:%d",
family, protocol, type));
*errorp = 0;
if (is_system_labeled()) {
*errorp = EOPNOTSUPP;
return (NULL);
}
if (version == SOV_STREAM) {
*errorp = EINVAL;
return (NULL);
}
/*
* We only support one type of SDP socket. Let sotpi_create()
* handle all other cases, such as raw socket.
*/
if (!(family == AF_INET || family == AF_INET6) ||
!(type == SOCK_STREAM)) {
*errorp = EINVAL;
return (NULL);
}
so = kmem_cache_alloc(socket_cache, kmflags);
if (so == NULL) {
*errorp = ENOMEM;
return (NULL);
}
sonode_init(so, sp, family, type, protocol, &sosdp_sonodeops);
so->so_pollev |= SO_POLLEV_ALWAYS;
dprint(2, ("sosdp_create: %p domain %d type %d\n", (void *)so, family,
type));
if (version == SOV_DEFAULT) {
version = so_default_version;
}
so->so_version = (short)version;
/*
* set the default values to be INFPSZ
* if a protocol desires it can change the value later
*/
so->so_proto_props.sopp_rxhiwat = SOCKET_RECVHIWATER;
so->so_proto_props.sopp_rxlowat = SOCKET_RECVLOWATER;
so->so_proto_props.sopp_maxpsz = INFPSZ;
so->so_proto_props.sopp_maxblk = INFPSZ;
return (so);
}
static void
socksdp_destroy(struct sonode *so)
{
ASSERT(so->so_ops == &sosdp_sonodeops);
sosdp_fini(so, CRED());
kmem_cache_free(socket_cache, so);
}
int
_init(void)
{
return (mod_install(&modlinkage));
}
int
_fini(void)
{
return (mod_remove(&modlinkage));
}
int
_info(struct modinfo *modinfop)
{
return (mod_info(&modlinkage, modinfop));
}