/*
* 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 2015 Nexenta Systems, Inc. All rights reserved.
*/
/*
* This module provides the interface to NDR RPC.
*/
#include <smbsrv/smb_kproto.h>
#include <smbsrv/winioctl.h>
/*
* Allocate a new opipe and return it, or NULL, in which case
* the caller will report "internal error".
*/
static smb_opipe_t *
{
return (NULL);
return (opipe);
}
/*
* Destroy an opipe. This is normally called from smb_ofile_delete
* when the ofile has no more references and is about to be free'd.
* This is also called here in error handling code paths, before
* the opipe is installed under an ofile.
*/
void
{
/*
* This is called in the error path when opening,
* in which case we close the socket here.
*/
}
/*
* Helper for open: build pipe name and connect.
*/
static int
{
const char *name;
int rc;
name += 4;
}
return (rc);
}
/*
* Helper for open: encode and send the user info.
*
* We send information about this client + user to the
* pipe service so it can use it for access checks.
* The service MAY deny the open based on this info,
* (i.e. anonymous session trying to open a pipe that
* requires authentication) in which case we will read
* an error status from the service and return that.
*/
static void
{
char *buf;
int rc;
/*
* Any errors building the XDR message etc.
*/
goto out;
/*
* If we fail sending the netuserinfo or recv'ing the
* status reponse, we have probably run into the limit
* on the number of open pipes. That's this status:
*/
if (rc != 0)
goto out;
goto out;
/*
* Return the status we read from the pipe service,
* normally NT_STATUS_SUCCESS, but could be something
* else like NT_STATUS_ACCESS_DENIED.
*/
out:
xdr_destroy(&xdrs);
}
/*
* smb_opipe_open
*
* Open an RPC named pipe. This routine should be called if
* a file open is requested on a share of type STYPE_IPC.
* If we recognize the pipe, we setup a new ofile.
*
* Returns 0 on success, Otherwise an NT status code.
*/
int
{
return (NT_STATUS_INTERNAL_ERROR);
return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
}
}
/*
* Note: If smb_ofile_open succeeds, the new ofile is
* in the FID lists can can be used by I/O requests.
*/
op->create_options = 0;
}
/* An "up" pointer, for debug. */
| SMB_PIPE_UNLIMITED_INSTANCES; /* 0x05ff */
return (NT_STATUS_SUCCESS);
}
/*
* smb_opipe_close
*
* Called by smb_ofile_close for pipes.
*
* Note: ksocket_close may block while waiting for
* any I/O threads with a hold to get out.
*/
void
{
}
/*
* smb_opipe_write
*
* Write RPC request data to the pipe. The client should call smb_opipe_read
* to complete the exchange and obtain the RPC response.
*
* Returns 0 on success or an errno on failure.
*/
int
{
int rc = 0;
return (EBADF);
/*
* This should block until we've sent it all,
* or given up due to errors (pipe closed).
*/
if (rc != 0)
break;
}
return (rc);
}
/*
* smb_opipe_read
*
* This interface may be called from smb_opipe_transact (write, read)
* or from smb_read / smb2_read to get the rest of an RPC response.
* The response data (and length) are returned via the uio.
*/
int
{
int rc;
return (EBADF);
/*
* This should block only if there's no data.
* A single call to recvmsg does just that.
* (Intentionaly no recv loop here.)
*/
if (rc != 0)
goto out;
if (recvcnt == 0) {
/* Other side closed. */
goto out;
}
out:
return (rc);
}
int
{
int rc;
return (EBADF);
return (rc);
}
/*
* Get the smb_attr_t for a named pipe.
* Caller has already cleared to zero.
*/
int
{
return (EINVAL);
return (0);
}
int
{
return (EINVAL);
return (0);
}
/*
* Handler for smb2_ioctl
*/
/* ARGSUSED */
{
case FSCTL_PIPE_TRANSCEIVE:
break;
case FSCTL_PIPE_PEEK:
case FSCTL_PIPE_WAIT:
/* XXX todo */
break;
default:
ASSERT(!"CtlCode");
break;
}
return (status);
}
static uint32_t
{
/*
* Caller checked that this is the IPC$ share,
* and that this call has a valid open handle.
* Just check the type.
*/
return (NT_STATUS_INVALID_HANDLE);
if (rc != 0) {
/* Not enough data sent. */
return (NT_STATUS_INVALID_PARAMETER);
}
if (rc != 0)
return (smb_errno2status(rc));
if (rc != 0) {
return (smb_errno2status(rc));
}
/*
* If the output buffer holds a partial pipe message,
* we're supposed to return NT_STATUS_BUFFER_OVERFLOW.
* As we don't have message boundary markers, the best
* we can do is return that status when we have ALL of:
* Output buffer was < SMB_PIPE_MAX_MSGSIZE
* We filled the output buffer (resid==0)
* There's more data (ioctl FIONREAD)
*/
}
return (status);
}