ksocket.c revision 3076c25a759075dcc052165713ce638ecf989184
/*
* 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
* 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 2011 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/socketvar.h>
#include <sys/sysmacros.h>
#include <sys/poll_impl.h>
#define SOCKETMOD_TCP "tcp"
#define SOCKETMOD_UDP "udp"
/*
* Kernel Sockets
*
* Mostly a wrapper around the private socket_* functions.
*/
int
{
static const int version = SOV_DEFAULT;
int error = 0;
/* All Solaris components should pass a cred for this operation. */
return (EAFNOSUPPORT);
if (error == EAFNOSUPPORT) {
/*
* Could be that root file sytem is not loaded or
* soconfig has not run yet.
*/
protocol == IPPROTO_TCP)) {
mod = SOCKETMOD_TCP;
protocol == IPPROTO_UDP)) {
mod = SOCKETMOD_UDP;
} else {
return (EAFNOSUPPORT);
}
return (error);
} else {
return (error);
}
}
return (0);
}
int
{
int error;
/* All Solaris components should pass a cred for this operation. */
if (!KSOCKET_VALID(ks))
return (ENOTSOCK);
return (error);
}
int
{
/* All Solaris components should pass a cred for this operation. */
if (!KSOCKET_VALID(ks))
return (ENOTSOCK);
}
int
{
int error;
/* All Solaris components should pass a cred for this operation. */
if (!KSOCKET_VALID(ks))
return (ENOTSOCK);
return (EFAULT);
if (error != 0)
return (error);
if (error != 0) {
}
}
return (error);
}
int
{
/* All Solaris components should pass a cred for this operation. */
if (!KSOCKET_VALID(ks))
return (ENOTSOCK);
}
int
{
int error;
/* All Solaris components should pass a cred for this operation. */
if (!KSOCKET_VALID(ks)) {
*sent = 0;
return (ENOTSOCK);
}
auio.uio_loffset = 0;
if (flags & MSG_USERSPACE)
else
msghdr.msg_namelen = 0;
msghdr.msg_controllen = 0;
if (error != 0) {
*sent = 0;
return (error);
}
return (0);
}
int
{
int error;
/* All Solaris components should pass a cred for this operation. */
if (!KSOCKET_VALID(ks)) {
*sent = 0;
return (ENOTSOCK);
}
auio.uio_loffset = 0;
if (flags & MSG_USERSPACE)
else
msghdr.msg_controllen = 0;
if (error != 0) {
*sent = 0;
return (error);
}
return (0);
}
int
{
int error;
int i;
/* All Solaris components should pass a cred for this operation. */
if (!KSOCKET_VALID(ks)) {
*sent = 0;
return (ENOTSOCK);
}
auio.uio_loffset = 0;
if (flags & MSG_USERSPACE)
else
len = 0;
for (i = 0; i < msg->msg_iovlen; i++) {
return (EINVAL);
}
if (error != 0) {
*sent = 0;
return (error);
}
return (0);
}
int
{
int error;
/* All Solaris components should pass a cred for this operation. */
if (!KSOCKET_VALID(ks)) {
*recv = 0;
return (ENOTSOCK);
}
auio.uio_loffset = 0;
if (flags & MSG_USERSPACE)
else
msghdr.msg_namelen = 0;
msghdr.msg_controllen = 0;
if (error != 0) {
*recv = 0;
return (error);
}
return (0);
}
int
{
int error;
/* All Solaris components should pass a cred for this operation. */
if (!KSOCKET_VALID(ks)) {
*recv = 0;
return (ENOTSOCK);
}
auio.uio_loffset = 0;
if (flags & MSG_USERSPACE)
else
msghdr.msg_controllen = 0;
if (error != 0) {
*recv = 0;
return (error);
}
return (0);
}
int
{
int error;
int i;
/* All Solaris components should pass a cred for this operation. */
if (!KSOCKET_VALID(ks)) {
*recv = 0;
return (ENOTSOCK);
}
auio.uio_loffset = 0;
else
len = 0;
for (i = 0; i < msg->msg_iovlen; i++) {
return (EINVAL);
}
if (error != 0) {
*recv = 0;
return (error);
}
return (0);
}
int
{
/* All Solaris components should pass a cred for this operation. */
if (!KSOCKET_VALID(ks))
return (ENOTSOCK);
}
int
{
/* All Solaris components should pass a cred for this operation. */
if (!KSOCKET_VALID(ks)) {
return (ENOTSOCK);
}
}
/* Remove callbacks, if any */
return (0);
}
int
{
/* All Solaris components should pass a cred for this operation. */
if (!KSOCKET_VALID(ks))
return (ENOTSOCK);
return (EFAULT);
}
int
{
/* All Solaris components should pass a cred for this operation. */
if (!KSOCKET_VALID(ks))
return (ENOTSOCK);
return (EFAULT);
}
int
{
/* All Solaris components should pass a cred for this operation. */
if (!KSOCKET_VALID(ks))
return (ENOTSOCK);
return (EFAULT);
if (*optlen > SO_MAXARGSIZE)
return (EINVAL);
}
int
{
/* All Solaris components should pass a cred for this operation. */
if (!KSOCKET_VALID(ks))
return (ENOTSOCK);
optlen = 0;
}
/* ARGSUSED */
int
{
/* All Solaris components should pass a cred for this operation. */
if (!KSOCKET_VALID(ks))
return (ENOTSOCK);
return (EFAULT);
} else {
}
return (0);
}
int
{
int rval;
/* All Solaris components should pass a cred for this operation. */
if (!KSOCKET_VALID(ks))
return (ENOTSOCK);
switch (cmd) {
default:
/* STREAM iotcls are not supported */
rval = EOPNOTSUPP;
} else {
}
break;
case FIOASYNC:
case SIOCSPGRP:
case FIOSETOWN:
case SIOCGPGRP:
case FIOGETOWN:
rval = EOPNOTSUPP;
break;
}
return (rval);
}
/*
* Wait for an input event, similar to t_kspoll().
* Ideas and code borrowed from ../devpoll.c
* Basically, setup just enough poll data structures so
* we can block on a CV until timeout or pollwakeup().
*/
int
{
int error;
/* All Solaris components should pass a cred for this operation. */
return (EINVAL);
if (!KSOCKET_VALID(ks))
return (ENOTSOCK);
/*
* Check if there are any events already pending.
* If we're not willing to block, (timo == 0) then
* pass "anyyet">0 to socket_poll so it can skip
* some work. Othewise pass "anyyet"=0 and if
* there are no events pending, it will fill in
* the pollhead pointer we need for pollwakeup().
*
* XXX - pollrelock() logic needs to know which
* which pollcache lock to grab. It'd be a
* cleaner solution if we could pass pcp as
* an arguement in VOP_POLL interface instead
* of implicitly passing it using thread_t
* struct. On the other hand, changing VOP_POLL
* poll routine to change. May want to revisit
* the tradeoff later.
*/
*revents = 0;
pcp = pcache_alloc();
goto out;
/*
* Need to block. Did not get *revents, so the
* php should be non-NULL, but let's verify.
* Also compute when our sleep expires.
*/
goto out;
}
if (timo > 0)
expires = ddi_get_lbolt() +
/*
* Setup: pollhead -> polldat -> pollcache
* needed for pollwakeup()
* pdp should be freed by pcache_destroy
*/
/* Ditto pcp comment above. */
break;
continue;
if (timo == -1) {
} else {
expires);
}
if (rval <= 0) {
if (rval == 0)
break;
}
}
}
/*
* pollwakeup() may still interact with this pollcache. Wait until
* it is done.
*/
out:
return (error);
}
int
{
int i_val;
int error;
/* All Solaris components should pass a cred for this operation. */
if (!KSOCKET_VALID(ks))
return (ENOTSOCK);
if (flags & MSG_MBLK_QUICKRELE) {
if (error != 0)
return (error);
/* Zero copy is not enable */
if (i_val == 0)
return (ECANCELED);
}
return (error);
}
void
{
} else
}
void
{
/*
* When so_count equals 1 means no thread working on this ksocket
*/
} else {
}
}