smb_smb.c revision 613a2f6ba31e891e3d947a356daf5e563d43c1ce
/*
* 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_smb.c,v 1.35.100.2 2005/06/02 00:55:39 lindak Exp $
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* various SMB requests. Most of the routines merely packs data into mbufs.
*/
#ifdef APPLE
#include <sys/smb_apple.h>
#else
#include <netsmb/smb_osdep.h>
#endif
#include <netsmb/smb_conn.h>
#include <netsmb/smb_subr.h>
#include <netsmb/smb_tran.h>
/*
* Largest size to use with LARGE_READ/LARGE_WRITE.
* Specs say up to 64k data bytes, but Windows traffic
* uses 60k... no doubt for some good reason.
* (Probably to keep 4k block alignment.)
* XXX: Move to smb.h maybe?
*/
/*
* Default timeout values, all in seconds.
* Make these tunable (only via mdb for now).
*/
int smb_timo_notice = 15;
int smb_timo_open = 45;
int smb_timo_read = 45;
int smb_timo_append = 90;
/*
* Set this to zero to skip NTLMv2
*/
int nsmb_enable_ntlmv2 = 1;
struct smb_dialect {
int d_id;
const char *d_name;
};
/*
* Number of seconds between 1970 and 1601 year
*/
void
{
/*
* XXX - what if we connected to the server when it was in
* to standard time, or vice versa, so that the time zone
* offset we got from the server is now wrong?
*/
/* - tz.tz_minuteswest * 60 - (wall_cmos_clock ? adjkerntz : 0) */
}
void
{
/*
* XXX - what if we connected to the server when it was in
* to standard time, or vice versa, so that the time zone
* offset we got from the server is now wrong?
*/
/* + tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); */
}
/*
* Time from server comes as UTC, so no need to use tz
*/
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
long seconds;
(u_int64_t)10000000;
}
#if defined(NOICONVSUPPORT) || defined(lint)
extern int iconv_close(void *handle);
#endif
/*
* Moved to user space helper:
* smb_smb_negotiate()
* smb_smb_ssnsetup()
* smb_smb_ssnclose()
* smb_share_typename()
*/
int
{
/*
* Make this a "VC-level" request, so it will have
* rqp->sr_share == NULL, and smb_iod_sendrq()
* will send it with TID = SMB_TID_UNKNOWN
*
* This also serves to bypass the wait for
* share state changes, which this call is
* trying to carry out.
*/
if (error)
return (error);
/*
* but with backslashes of course.
* size math: three slashes, one null.
*/
/*
* The password is now pre-computed in the
* user-space helper process.
*/
/*
* Build the request.
*/
mb_put_uint8(mbp, 0);
mb_put_uint16le(mbp, 0);
/* Tree connect password, if any */
if (error)
goto out;
/* UNC resource name */
if (error)
goto out;
/*
* Put the type string (always ASCII),
* including the null.
*/
if (error)
goto out;
/*
* Run the request.
*
* Using NOINTR_RECV because we don't want to risk
* missing a successful tree connect response,
* which would "leak" Tree IDs.
*/
if (error)
goto out;
/*
* Parse the TCON response
*/
if (wc != 3) {
goto out;
}
/*
* Get the returned share type string,
* i.e. "IPC" or whatever.
*/
/* Success! */
out:
if (unc_name)
return (error);
}
int
{
int error;
return (0);
/*
* Build this as a "VC-level" request, so it will
* avoid testing the _GONE flag on the share,
* which has already been set at this point.
* Add the share pointer "by hand" below, so
* smb_iod_sendrq will plug in the TID.
*/
if (error)
return (error);
/*
* Run this with a relatively short timeout. (5 sec.)
* We don't really care about the result here, but we
* do need to make sure we send this out, or we could
* "leak" active tree IDs on interrupt or timeout.
* The NOINTR_SEND flag makes this request immune to
* interrupt or timeout until the send is done.
* Also, don't reconnect for this, of course!
*/
return (error);
}
/*
* Called by netsmb smb_usr_rw,
* smbfs_readvnode, smbfs_writevnode
*/
int
{
int error = 0;
uio_t *, smb_cred_t *, int);
/*
* Determine which function to use,
* and the transfer size per call.
*/
/*
* Using NT LM 0.12, so readx, writex.
* Make sure we can represent the offset.
*/
return (EFBIG);
else
} else { /* UIO_WRITE */
else
}
} else {
/*
* Using the old SMB_READ and SMB_WRITE so
* we're limited to 32-bit offsets, etc.
* XXX: Someday, punt the old dialects.
*/
return (EFBIG);
} else { /* UIO_WRITE */
}
}
/* Lint: uio_resid may be 64-bits */
/*
* Note: the iofun called uio_update, so
* not doing that here as one might expect.
*
* Quit the loop either on error, or if we
* transferred less then requested.
*/
break;
timo = 0; /* only first I/O should wait */
}
/*
* Stopped on an error after having
* successfully transferred data.
* Suppress this error.
*/
error = 0;
}
return (error);
}
static int
{
int error;
if (error)
return (error);
/* (only indicates blocking) */
do {
if (timo == 0)
if (error)
break;
if (wc != 12) {
break;
}
/*
* Does the data offset indicate padding?
* Add up the gets above, we have:
*/
if (rlen == 0) {
break;
}
/* paranoid */
SMBSDEBUG("bad server! rlen %d, len %d\n",
}
if (error)
break;
/*LINTED*/
} while (0);
return (error);
}
static int
{
int error;
if (error)
return (error);
mb_put_uint16le(mbp, 0);
do {
if (error)
break;
if (timo == 0)
if (error)
break;
if (wc != 6) {
break;
}
/*LINTED*/
} while (0);
return (error);
}
static int
{
int error;
/* This next is an "estimate" of planned reads. */
if (error)
return (error);
do {
if (timo == 0)
if (error)
break;
if (wc != 5) {
break;
}
SMBSDEBUG("oops: dlen=%d rcnt=%d\n",
}
if (rcnt == 0) {
*lenp = 0;
break;
}
/* paranoid */
SMBSDEBUG("bad server! rcnt %d, cnt %d\n",
}
if (error)
break;
/*LINTED*/
} while (0);
return (error);
}
static int
{
int error;
/* This next is an "estimate" of planned writes. */
if (error)
return (error);
do {
if (error)
break;
if (timo == 0)
if (error)
break;
if (wc != 1) {
break;
}
/*LINTED*/
} while (0);
return (error);
}
int
{
int error;
if (error)
return (error);
/*
* Note: the IOD calls this, so
* this request must not wait for
* connection state changes, etc.
*/
return (error);
}