/*
* Copyright (c) 2000-2001 Boris Popov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Boris Popov.
* 4. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: smb_usr.c,v 1.15 2004/12/13 00:25:18 lindak Exp $
*/
/*
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <netsmb/smb_osdep.h>
#include <netsmb/smb_conn.h>
#include <netsmb/smb_subr.h>
/*
* Ioctl function for SMBIOC_FLAGS2
*/
int
{
/* This ioctl requires a session. */
return (ENOTCONN);
/*
* Return the flags2 value.
*/
return (EFAULT);
return (0);
}
/*
* Ioctl function for SMBIOC_GETSSNKEY
* Size copied out is SMBIOC_HASH_SZ.
*
* The RPC library needs this for encrypting things
* like "set password" requests. This is called
* with an active RPC binding, so the connection
* will already be active (but this checks).
*/
int
{
/* This ioctl requires an active session. */
return (ENOTCONN);
return (ENOTCONN);
/*
* Return the session key.
*/
return (EFAULT);
return (0);
}
/*
* Ioctl function for SMBIOC_REQUEST
*/
int
{
/* This ioctl requires a share. */
return (ENOTCONN);
goto out;
}
/* See ddi_copyin, ddi_copyout */
/*
* Lots of SMB commands could be safe, but
* these are the only ones used by libsmbfs.
*/
/* These are OK */
case SMB_COM_CLOSE:
case SMB_COM_FLUSH:
case SMB_COM_NT_CREATE_ANDX:
case SMB_COM_OPEN_PRINT_FILE:
case SMB_COM_CLOSE_PRINT_FILE:
break;
default:
goto out;
}
if (err)
goto out;
if (err == 0) {
/*
* This may have been an open, so save the
* generation ID of the share, which we
* check before trying read or write.
*/
/*
* Have reply data. to copyout.
* SMB header already parsed.
*/
goto out;
}
if (err)
goto out;
}
out:
return (err);
}
/*
* Ioctl function for SMBIOC_T2RQ
*/
int
{
/* This ioctl requires a share. */
return (ENOTCONN);
goto out;
}
/* See ddi_copyin, ddi_copyout */
goto out;
}
/*
* Fill in the FID for libsmbfs transact named pipe.
*/
goto out;
}
}
if (err)
goto out;
/* This ioc member is a fixed-size array. */
/* Get the name length - carefully! */
}
t2p->t2_maxscount = 0;
/* Transmit parameters */
if (err)
goto out;
/* Transmit data */
if (err)
goto out;
/* Copyout returned parameters. */
/* User's buffer large enough? */
goto out;
}
if (err)
goto out;
} else
ioc->ioc_rparamcnt = 0;
/* Copyout returned data. */
/* User's buffer large enough? */
goto out;
}
if (err)
goto out;
} else
ioc->ioc_rdatacnt = 0;
out:
/* Note: t2p->t_name no longer allocated */
}
return (err);
}
/* helper for _t2request */
static int
{
int error;
if (len == 0)
return (0);
if (error)
return (error);
}
/*
* Helper for nsmb_ioctl cases
* SMBIOC_READ, SMBIOC_WRITE
*/
int
{
int err;
/* This ioctl requires a share. */
return (ENOTCONN);
/* After reconnect, force close+reopen */
return (ESTALE);
goto out;
}
switch (cmd) {
case SMBIOC_READ:
break;
case SMBIOC_WRITE:
break;
default:
goto out;
}
/*
* If caller passes -1 in ioc_fh, then
* use the FID from SMBIOC_NTCREATE.
*/
else
/*
* On return ioc_cnt holds the
* number of bytes transferred.
*/
out:
return (err);
}
/*
* Helper for nsmb_ioctl case
* SMBIOC_NTCREATE
*/
int
{
/* This ioctl requires a share. */
return (ENOTCONN);
/* Must not be already open. */
return (EINVAL);
goto out;
}
/* Build name_mb */
SMB_CS_NONE, NULL);
if (err != 0)
goto out;
/* Do the OtW open, save the FID. */
0, /* create flags */
&scred,
&fid,
NULL,
NULL);
if (err != 0)
goto out;
out:
return (err);
}
/*
* Helper for nsmb_ioctl case
* SMBIOC_PRINTJOB
*/
int
{
int err;
/* This ioctl requires a share. */
return (ENOTCONN);
/* The share must be a print queue. */
return (EINVAL);
/* Must not be already open. */
return (EINVAL);
goto out;
}
/* Do the OtW open, save the FID. */
if (err != 0)
goto out;
out:
return (err);
}
/*
* Helper for nsmb_ioctl case
* SMBIOC_CLOSEFH
*/
int
{
int err;
/* This ioctl requires a share. */
return (ENOTCONN);
return (0);
else
return (err);
}
/*
* Ioctl functions: SMBIOC_SSN_FIND, SMBIOC_SSN_CREATE
* Find or create a session (a.k.a. "VC" in here)
*/
int
{
int error = 0;
/* Should be no VC */
return (EISCONN);
goto out;
}
/*
* Only superuser can specify a UID or GID.
*/
else {
/*
* Do we have the privilege to create with the
* specified uid? (does uid == cr->cr_uid, etc.)
*/
goto out;
}
/* ossn->ssn_owner is OK */
}
/*
* Make sure the strings are null terminated.
*/
if (cmd == SMBIOC_SSN_CREATE)
else /* FIND */
if (error)
goto out;
/*
* We have a VC, held, but not locked.
* If we're creating, mark this instance as
* an open from IOD so close can do cleanup.
*
* XXX: Would be nice to have a back pointer
* from the VC to this (IOD) sdp instance.
*/
if (cmd == SMBIOC_SSN_CREATE) {
goto out;
}
} else {
/*
* Wait for it to finish connecting
* (or reconnect) if necessary.
*/
if (error != 0)
goto out;
}
}
/*
* The VC has a hold from _findvc
* which we keep until _SSN_RELE
* or nsmb_close().
*/
out:
if (vcp) {
/* Error path: rele hold from _findcreate */
}
return (error);
}
/*
* Ioctl functions: SMBIOC_SSN_RELE, SMBIOC_SSN_KILL
* Release or kill the current session.
*/
int
{
/* Must have a VC. */
return (ENOTCONN);
/* If we have a share ref, drop it too. */
}
if (cmd == SMBIOC_SSN_KILL)
/* Drop the VC ref. */
return (0);
}
/*
* Find or create a tree (connected share)
*/
int
{
int error = 0;
/* Must have a VC. */
return (ENOTCONN);
/* Should not have a share. */
return (EISCONN);
goto out;
}
/*
* Make sure the strings are null terminated.
*/
if (cmd == SMBIOC_TREE_CONNECT)
else /* FIND */
if (error)
goto out;
/*
* We have a share, held, but not locked.
* If we're creating, do tree connect now,
* otherwise let that wait for a request.
*/
if (cmd == SMBIOC_TREE_CONNECT) {
if (error)
goto out;
}
/*
* Give caller the real share type from
* the tree connect response, so they can
* see if they got the requested type.
*/
/*
* The share has a hold from _tcon
* which we keep until nsmb_close()
* or the SMBIOC_TDIS below.
*/
out:
if (ssp) {
/* Error path: rele hold from _findcreate */
}
/*
* This structure may contain a
* cleartext password, so zap it.
*/
return (error);
}
/*
* Ioctl functions: SMBIOC_TREE_RELE, SMBIOC_TREE_KILL
* Release or kill the current tree
*/
int
{
/* Must have a VC and a share. */
return (ENOTCONN);
return (ENOTCONN);
if (cmd == SMBIOC_TREE_KILL)
/* Drop the share ref. */
return (0);
}
/*
* Ioctl function: SMBIOC_IOD_WORK
*
* Become the reader (IOD) thread, until either the connection is
* reset by the server, or until the connection is idle longer than
* some max time. (max idle time not yet implemented)
*/
int
{
int err = 0;
/* Must have a valid session. */
return (EINVAL);
return (EINVAL);
/*
* Is there already an IOD for this VC?
* (Should never happen.)
*/
else
if (err)
return (err);
/*
* Copy the "work" state, etc. into the VC
* The MAC key is copied separately.
*/
sizeof (smbioc_ssn_work_t), flags)) {
goto out;
}
if (vcp->vc_u_maclen) {
goto out;
}
}
/* Caller wants state here. */
sizeof (smbioc_ssn_work_t), flags);
out:
vcp->vc_mackeylen = 0;
}
/*
* The IOD thread is leaving the driver. Clear iod_thr,
* and wake up anybody waiting for us to quit.
*/
return (err);
}
/*
* Ioctl functions: SMBIOC_IOD_IDLE, SMBIOC_IOD_RCFAIL
*
* Wait for user-level requests to be enqueued on this session,
* and then return to the user-space helper, which will then
* initiate a reconnect, etc.
*/
int
{
int err = 0;
/* Must have a valid session. */
return (EINVAL);
return (EINVAL);
/*
* Is there already an IOD for this VC?
* (Should never happen.)
*/
else
if (err)
return (err);
/* nothing to copyin */
switch (cmd) {
case SMBIOC_IOD_IDLE:
break;
case SMBIOC_IOD_RCFAIL:
break;
default:
goto out;
}
/* Both of these ioctls copy out the new state. */
sizeof (int), flags);
out:
/*
* The IOD thread is leaving the driver. Clear iod_thr,
* and wake up anybody waiting for us to quit.
*/
return (err);
}