*/
#include "includes.h"
+#include "smb_server/smb_server.h"
+
/* useful way of catching wct errors with file and line number */
#define REQ_CHECK_WCT(req, wcount) do { \
return; \
}} while (0)
-/* check req->async.status and if not OK then send an error reply */
+/* check req->async_states->status and if not OK then send an error reply */
#define CHECK_ASYNC_STATUS do { \
- if (!NT_STATUS_IS_OK(req->async.status)) { \
- req_reply_error(req, req->async.status); \
+ if (!NT_STATUS_IS_OK(req->async_states->status)) { \
+ req_reply_error(req, req->async_states->status); \
return; \
}} while (0)
/* useful wrapper for talloc with NO_MEMORY reply */
#define REQ_TALLOC(ptr, size) do { \
- ptr = talloc(req->mem_ctx, size); \
+ ptr = talloc(req, size); \
if (!ptr) { \
req_reply_error(req, NT_STATUS_NO_MEMORY); \
return; \
immediately
*/
#define REQ_ASYNC_TAIL do { \
- if (!(req->control_flags & REQ_CONTROL_ASYNC)) { \
- req->async.send_fn(req); \
+ if (!(req->async_states->state & NTVFS_ASYNC_STATE_ASYNC)) { \
+ req->async_states->send_fn(req); \
}} while (0)
/* zero out some reserved fields in a reply */
#define REQ_VWV_RESERVED(start, count) memset(req->out.vwv + VWV(start), 0, (count)*2)
-/*
- put a NTTIME into a packet
-*/
-void push_nttime(void *base, uint16 offset, NTTIME *t)
-{
- SIVAL(base, offset, t->low);
- SIVAL(base, offset+4, t->high);
-}
-
-/*
- pull a NTTIME from a packet
-*/
-NTTIME pull_nttime(void *base, uint16 offset)
-{
- NTTIME ret;
- ret.low = IVAL(base, offset);
- ret.high = IVAL(base, offset+4);
- return ret;
-}
-
-
/****************************************************************************
Reply to a simple request (async send)
****************************************************************************/
-static void reply_simple_send(struct request_context *req)
+static void reply_simple_send(struct smbsrv_request *req)
{
CHECK_ASYNC_STATUS;
/****************************************************************************
Reply to a tcon.
****************************************************************************/
-void reply_tcon(struct request_context *req)
+void reply_tcon(struct smbsrv_request *req)
{
union smb_tcon con;
NTSTATUS status;
- char *p;
+ uint8_t *p;
/* parse request */
REQ_CHECK_WCT(req, 0);
SSVAL(req->out.vwv, VWV(0), con.tcon.out.max_xmit);
SSVAL(req->out.vwv, VWV(1), con.tcon.out.cnum);
- SSVAL(req->out.hdr, HDR_TID, req->conn->cnum);
+ SSVAL(req->out.hdr, HDR_TID, req->tcon->cnum);
req_send_reply(req);
}
/****************************************************************************
Reply to a tcon and X.
****************************************************************************/
-void reply_tcon_and_X(struct request_context *req)
+void reply_tcon_and_X(struct smbsrv_request *req)
{
NTSTATUS status;
union smb_tcon con;
- char *p;
- uint16 passlen;
+ uint8_t *p;
+ uint16_t passlen;
con.tconx.level = RAW_TCON_TCONX;
return;
}
- /* construct reply - two varients */
- if (req->smb->negotiate.protocol < PROTOCOL_NT1) {
+ /* construct reply - two variants */
+ if (req->smb_conn->negotiate.protocol < PROTOCOL_NT1) {
req_setup_reply(req, 2, 0);
SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
/****************************************************************************
Reply to an unknown request
****************************************************************************/
-void reply_unknown(struct request_context *req)
+void reply_unknown(struct smbsrv_request *req)
{
int type;
/****************************************************************************
Reply to an ioctl (async reply)
****************************************************************************/
-static void reply_ioctl_send(struct request_context *req)
+static void reply_ioctl_send(struct smbsrv_request *req)
{
- union smb_ioctl *io = req->async.private;
+ union smb_ioctl *io = req->async_states->private_data;
CHECK_ASYNC_STATUS;
/****************************************************************************
Reply to an ioctl.
****************************************************************************/
-void reply_ioctl(struct request_context *req)
+void reply_ioctl(struct smbsrv_request *req)
{
union smb_ioctl *io;
io->ioctl.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
io->ioctl.in.request = IVAL(req->in.vwv, VWV(1));
- req->async.send_fn = reply_ioctl_send;
- req->async.private = io;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_ioctl_send;
+ req->async_states->private_data = io;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->ioctl(req, io);
+ req->async_states->status = ntvfs_ioctl(req, io);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a chkpth.
****************************************************************************/
-void reply_chkpth(struct request_context *req)
+void reply_chkpth(struct smbsrv_request *req)
{
struct smb_chkpath *io;
req_pull_ascii4(req, &io->in.path, req->in.data, STR_TERMINATE);
- req->async.send_fn = reply_simple_send;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_simple_send;
- req->async.status = req->conn->ntvfs_ops->chkpath(req, io);
+ req->async_states->status = ntvfs_chkpath(req, io);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a getatr (async reply)
****************************************************************************/
-static void reply_getatr_send(struct request_context *req)
+static void reply_getatr_send(struct smbsrv_request *req)
{
- union smb_fileinfo *st = req->async.private;
+ union smb_fileinfo *st = req->async_states->private_data;
CHECK_ASYNC_STATUS;
req_setup_reply(req, 10, 0);
SSVAL(req->out.vwv, VWV(0), st->getattr.out.attrib);
- put_dos_date3(req->out.vwv, VWV(1), st->getattr.out.write_time);
+ srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(1), st->getattr.out.write_time);
SIVAL(req->out.vwv, VWV(3), st->getattr.out.size);
REQ_VWV_RESERVED(5, 5);
/****************************************************************************
Reply to a getatr.
****************************************************************************/
-void reply_getatr(struct request_context *req)
+void reply_getatr(struct smbsrv_request *req)
{
union smb_fileinfo *st;
return;
}
- req->async.send_fn = reply_getatr_send;
- req->async.private = st;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_getatr_send;
+ req->async_states->private_data = st;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->qpathinfo(req, st);
+ req->async_states->status = ntvfs_qpathinfo(req, st);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a setatr.
****************************************************************************/
-void reply_setatr(struct request_context *req)
+void reply_setatr(struct smbsrv_request *req)
{
union smb_setfileinfo *st;
st->setattr.level = RAW_SFILEINFO_SETATTR;
st->setattr.in.attrib = SVAL(req->in.vwv, VWV(0));
- st->setattr.in.write_time = make_unix_date3(req->in.vwv + VWV(1));
+ st->setattr.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
req_pull_ascii4(req, &st->setattr.file.fname, req->in.data, STR_TERMINATE);
return;
}
- req->async.send_fn = reply_simple_send;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_simple_send;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->setpathinfo(req, st);
+ req->async_states->status = ntvfs_setpathinfo(req, st);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a dskattr (async reply)
****************************************************************************/
-static void reply_dskattr_send(struct request_context *req)
+static void reply_dskattr_send(struct smbsrv_request *req)
{
- union smb_fsinfo *fs = req->async.private;
+ union smb_fsinfo *fs = req->async_states->private_data;
CHECK_ASYNC_STATUS;
/****************************************************************************
Reply to a dskattr.
****************************************************************************/
-void reply_dskattr(struct request_context *req)
+void reply_dskattr(struct smbsrv_request *req)
{
union smb_fsinfo *fs;
fs->dskattr.level = RAW_QFS_DSKATTR;
- req->async.send_fn = reply_dskattr_send;
- req->async.private = fs;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_dskattr_send;
+ req->async_states->private_data = fs;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->fsinfo(req, fs);
+ req->async_states->status = ntvfs_fsinfo(req, fs);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to an open (async reply)
****************************************************************************/
-static void reply_open_send(struct request_context *req)
+static void reply_open_send(struct smbsrv_request *req)
{
- union smb_open *oi = req->async.private;
+ union smb_open *oi = req->async_states->private_data;
CHECK_ASYNC_STATUS;
/* construct reply */
req_setup_reply(req, 7, 0);
- SSVAL(req->out.vwv, VWV(0), oi->open.out.fnum);
- SSVAL(req->out.vwv, VWV(1), oi->open.out.attrib);
- put_dos_date3(req->out.vwv, VWV(2), oi->open.out.write_time);
- SIVAL(req->out.vwv, VWV(4), oi->open.out.size);
- SSVAL(req->out.vwv, VWV(6), oi->open.out.rmode);
+ SSVAL(req->out.vwv, VWV(0), oi->openold.out.fnum);
+ SSVAL(req->out.vwv, VWV(1), oi->openold.out.attrib);
+ srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(2), oi->openold.out.write_time);
+ SIVAL(req->out.vwv, VWV(4), oi->openold.out.size);
+ SSVAL(req->out.vwv, VWV(6), oi->openold.out.rmode);
req_send_reply(req);
}
/****************************************************************************
Reply to an open.
****************************************************************************/
-void reply_open(struct request_context *req)
+void reply_open(struct smbsrv_request *req)
{
union smb_open *oi;
REQ_CHECK_WCT(req, 2);
REQ_TALLOC(oi, sizeof(*oi));
- oi->open.level = RAW_OPEN_OPEN;
- oi->open.in.flags = SVAL(req->in.vwv, VWV(0));
- oi->open.in.search_attrs = SVAL(req->in.vwv, VWV(1));
+ oi->openold.level = RAW_OPEN_OPEN;
+ oi->openold.in.flags = SVAL(req->in.vwv, VWV(0));
+ oi->openold.in.search_attrs = SVAL(req->in.vwv, VWV(1));
- req_pull_ascii4(req, &oi->open.in.fname, req->in.data, STR_TERMINATE);
+ req_pull_ascii4(req, &oi->openold.in.fname, req->in.data, STR_TERMINATE);
- if (!oi->open.in.fname) {
+ if (!oi->openold.in.fname) {
req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
return;
}
- req->async.send_fn = reply_open_send;
- req->async.private = oi;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_open_send;
+ req->async_states->private_data = oi;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->open(req, oi);
+ req->async_states->status = ntvfs_openfile(req, oi);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to an open and X (async reply)
****************************************************************************/
-static void reply_open_and_X_send(struct request_context *req)
+static void reply_open_and_X_send(struct smbsrv_request *req)
{
- union smb_open *oi = req->async.private;
+ union smb_open *oi = req->async_states->private_data;
CHECK_ASYNC_STATUS;
SSVAL(req->out.vwv, VWV(1), 0);
SSVAL(req->out.vwv, VWV(2), oi->openx.out.fnum);
SSVAL(req->out.vwv, VWV(3), oi->openx.out.attrib);
- put_dos_date3(req->out.vwv, VWV(4), oi->openx.out.write_time);
+ srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(4), oi->openx.out.write_time);
SIVAL(req->out.vwv, VWV(6), oi->openx.out.size);
SSVAL(req->out.vwv, VWV(8), oi->openx.out.access);
SSVAL(req->out.vwv, VWV(9), oi->openx.out.ftype);
/****************************************************************************
Reply to an open and X.
****************************************************************************/
-void reply_open_and_X(struct request_context *req)
+void reply_open_and_X(struct smbsrv_request *req)
{
union smb_open *oi;
oi->openx.in.open_mode = SVAL(req->in.vwv, VWV(3));
oi->openx.in.search_attrs = SVAL(req->in.vwv, VWV(4));
oi->openx.in.file_attrs = SVAL(req->in.vwv, VWV(5));
- oi->openx.in.write_time = make_unix_date3(req->in.vwv + VWV(6));
+ oi->openx.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(6));
oi->openx.in.open_func = SVAL(req->in.vwv, VWV(8));
oi->openx.in.size = IVAL(req->in.vwv, VWV(9));
oi->openx.in.timeout = IVAL(req->in.vwv, VWV(11));
return;
}
- req->async.send_fn = reply_open_and_X_send;
- req->async.private = oi;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_open_and_X_send;
+ req->async_states->private_data = oi;
/* call the backend */
- req->async.status = req->conn->ntvfs_ops->open(req, oi);
+ req->async_states->status = ntvfs_openfile(req, oi);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a mknew or a create.
****************************************************************************/
-static void reply_mknew_send(struct request_context *req)
+static void reply_mknew_send(struct smbsrv_request *req)
{
- union smb_open *oi = req->async.private;
+ union smb_open *oi = req->async_states->private_data;
CHECK_ASYNC_STATUS;
/****************************************************************************
Reply to a mknew or a create.
****************************************************************************/
-void reply_mknew(struct request_context *req)
+void reply_mknew(struct smbsrv_request *req)
{
union smb_open *oi;
REQ_CHECK_WCT(req, 3);
REQ_TALLOC(oi, sizeof(*oi));
- oi->mknew.level = RAW_OPEN_MKNEW;
+ if (CVAL(req->in.hdr, HDR_COM) == SMBmknew) {
+ oi->mknew.level = RAW_OPEN_MKNEW;
+ } else {
+ oi->mknew.level = RAW_OPEN_CREATE;
+ }
oi->mknew.in.attrib = SVAL(req->in.vwv, VWV(0));
- oi->mknew.in.write_time = make_unix_date3(req->in.vwv + VWV(1));
+ oi->mknew.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
req_pull_ascii4(req, &oi->mknew.in.fname, req->in.data, STR_TERMINATE);
return;
}
- req->async.send_fn = reply_mknew_send;
- req->async.private = oi;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_mknew_send;
+ req->async_states->private_data = oi;
/* call the backend */
- req->async.status = req->conn->ntvfs_ops->open(req, oi);
+ req->async_states->status = ntvfs_openfile(req, oi);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a create temporary file (async reply)
****************************************************************************/
-static void reply_ctemp_send(struct request_context *req)
+static void reply_ctemp_send(struct smbsrv_request *req)
{
- union smb_open *oi = req->async.private;
+ union smb_open *oi = req->async_states->private_data;
CHECK_ASYNC_STATUS;
SSVAL(req->out.vwv, VWV(0), oi->ctemp.out.fnum);
/* the returned filename is relative to the directory */
- req_push_str(req, NULL, oi->ctemp.out.name, -1, STR_TERMINATE);
+ req_push_str(req, NULL, oi->ctemp.out.name, -1, STR_TERMINATE | STR_ASCII);
req_send_reply(req);
}
/****************************************************************************
Reply to a create temporary file.
****************************************************************************/
-void reply_ctemp(struct request_context *req)
+void reply_ctemp(struct smbsrv_request *req)
{
union smb_open *oi;
oi->ctemp.level = RAW_OPEN_CTEMP;
oi->ctemp.in.attrib = SVAL(req->in.vwv, VWV(0));
- oi->ctemp.in.write_time = make_unix_date3(req->in.vwv + VWV(1));
+ oi->ctemp.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
/* the filename is actually a directory name, the server provides a filename
in that directory */
return;
}
- req->async.send_fn = reply_ctemp_send;
- req->async.private = oi;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_ctemp_send;
+ req->async_states->private_data = oi;
/* call the backend */
- req->async.status = req->conn->ntvfs_ops->open(req, oi);
+ req->async_states->status = ntvfs_openfile(req, oi);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a unlink
****************************************************************************/
-void reply_unlink(struct request_context *req)
+void reply_unlink(struct smbsrv_request *req)
{
struct smb_unlink *unl;
req_pull_ascii4(req, &unl->in.pattern, req->in.data, STR_TERMINATE);
- req->async.send_fn = reply_simple_send;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_simple_send;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->unlink(req, unl);
+ req->async_states->status = ntvfs_unlink(req, unl);
REQ_ASYNC_TAIL;
}
only the 4 byte NBT header
This command must be replied to synchronously
****************************************************************************/
-void reply_readbraw(struct request_context *req)
+void reply_readbraw(struct smbsrv_request *req)
{
NTSTATUS status;
union smb_read io;
io.readbraw.level = RAW_READ_READBRAW;
- /* there are two varients, one with 10 and one with 8 command words */
- if (req->in.wct != 10) {
- REQ_CHECK_WCT(req, 8);
+ /* there are two variants, one with 10 and one with 8 command words */
+ if (req->in.wct < 8) {
+ goto failed;
}
io.readbraw.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
io.readbraw.in.offset = IVAL(req->in.vwv, VWV(1));
- io.readbraw.in.mincnt = SVAL(req->in.vwv, VWV(3));
- io.readbraw.in.maxcnt = SVAL(req->in.vwv, VWV(4));
+ io.readbraw.in.maxcnt = SVAL(req->in.vwv, VWV(3));
+ io.readbraw.in.mincnt = SVAL(req->in.vwv, VWV(4));
io.readbraw.in.timeout = IVAL(req->in.vwv, VWV(5));
- /* the 64 bit varient */
+ /* the 64 bit variant */
if (req->in.wct == 10) {
- uint32 offset_high = IVAL(req->in.vwv, VWV(8));
-#ifdef LARGE_SMB_OFF_T
- io.readbraw.in.offset |= (((SMB_OFF_T)offset_high) << 32);
-#else
- if (offset_high != 0) {
- goto failed;
- }
-#endif
+ uint32_t offset_high = IVAL(req->in.vwv, VWV(8));
+ io.readbraw.in.offset |= (((off_t)offset_high) << 32);
}
/* before calling the backend we setup the raw buffer. This
* saves a copy later */
req->out.size = io.readbraw.in.maxcnt + NBT_HDR_SIZE;
- req->out.buffer = talloc(req->mem_ctx, req->out.size);
+ req->out.buffer = talloc(req, req->out.size);
if (req->out.buffer == NULL) {
goto failed;
}
io.readbraw.out.data = req->out.buffer + NBT_HDR_SIZE;
/* call the backend */
- status = req->conn->ntvfs_ops->read(req, &io);
+ status = ntvfs_read(req, &io);
if (!NT_STATUS_IS_OK(status)) {
goto failed;
req->out.size = io.readbraw.out.nread + NBT_HDR_SIZE;
- req_send_reply(req);
+ req_send_reply_nosign(req);
return;
failed:
/* any failure in readbraw is equivalent to reading zero bytes */
req->out.size = 4;
- req->out.buffer = talloc(req->mem_ctx, req->out.size);
+ req->out.buffer = talloc(req, req->out.size);
SIVAL(req->out.buffer, 0, 0); /* init NBT header */
- req_send_reply(req);
+
+ req_send_reply_nosign(req);
}
/****************************************************************************
Reply to a lockread (async reply)
****************************************************************************/
-static void reply_lockread_send(struct request_context *req)
+static void reply_lockread_send(struct smbsrv_request *req)
{
- union smb_read *io = req->async.private;
+ union smb_read *io = req->async_states->private_data;
CHECK_ASYNC_STATUS;
Reply to a lockread (core+ protocol).
note that the lock is a write lock, not a read lock!
****************************************************************************/
-void reply_lockread(struct request_context *req)
+void reply_lockread(struct smbsrv_request *req)
{
union smb_read *io;
/* tell the backend where to put the data */
io->lockread.out.data = req->out.data + 3;
- req->async.send_fn = reply_lockread_send;
- req->async.private = io;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_lockread_send;
+ req->async_states->private_data = io;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->read(req, io);
+ req->async_states->status = ntvfs_read(req, io);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a read (async reply)
****************************************************************************/
-static void reply_read_send(struct request_context *req)
+static void reply_read_send(struct smbsrv_request *req)
{
- union smb_read *io = req->async.private;
+ union smb_read *io = req->async_states->private_data;
CHECK_ASYNC_STATUS;
/****************************************************************************
Reply to a read.
****************************************************************************/
-void reply_read(struct request_context *req)
+void reply_read(struct smbsrv_request *req)
{
union smb_read *io;
/* tell the backend where to put the data */
io->read.out.data = req->out.data + 3;
- req->async.send_fn = reply_read_send;
- req->async.private = io;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_read_send;
+ req->async_states->private_data = io;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->read(req, io);
+ req->async_states->status = ntvfs_read(req, io);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a read and X (async reply)
****************************************************************************/
-static void reply_read_and_X_send(struct request_context *req)
+static void reply_read_and_X_send(struct smbsrv_request *req)
{
- union smb_read *io = req->async.private;
+ union smb_read *io = req->async_states->private_data;
CHECK_ASYNC_STATUS;
/* readx reply packets can be over-sized */
req->control_flags |= REQ_CONTROL_LARGE;
- req_grow_data(req, 1 + io->readx.out.nread);
+ if (io->readx.in.maxcnt != 0xFFFF &&
+ io->readx.in.mincnt != 0xFFFF) {
+ req_grow_data(req, 1 + io->readx.out.nread);
+ SCVAL(req->out.data, 0, 0); /* padding */
+ } else {
+ req_grow_data(req, io->readx.out.nread);
+ }
/* construct reply */
SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
REQ_VWV_RESERVED(4, 1);
SSVAL(req->out.vwv, VWV(5), io->readx.out.nread);
SSVAL(req->out.vwv, VWV(6), PTR_DIFF(io->readx.out.data, req->out.hdr));
- SCVAL(req->out.data, 0, 0); /* padding */
REQ_VWV_RESERVED(7, 5);
chain_reply(req);
/****************************************************************************
Reply to a read and X.
****************************************************************************/
-void reply_read_and_X(struct request_context *req)
+void reply_read_and_X(struct smbsrv_request *req)
{
union smb_read *io;
io->readx.in.maxcnt = SVAL(req->in.vwv, VWV(5));
io->readx.in.mincnt = SVAL(req->in.vwv, VWV(6));
io->readx.in.remaining = SVAL(req->in.vwv, VWV(9));
+
+ if (req->smb_conn->negotiate.client_caps & CAP_LARGE_READX) {
+ uint32_t high_part = IVAL(req->in.vwv, VWV(7));
+ if (high_part == 1) {
+ io->readx.in.maxcnt |= high_part << 16;
+ }
+ }
- /* the 64 bit varient */
+ /* the 64 bit variant */
if (req->in.wct == 12) {
- uint32 offset_high = IVAL(req->in.vwv, VWV(10));
-#ifdef LARGE_SMB_OFF_T
- io->readx.in.offset |= (((SMB_OFF_T)offset_high) << 32);
-#else
- if (offset_high != 0) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
-#endif
+ uint32_t offset_high = IVAL(req->in.vwv, VWV(10));
+ io->readx.in.offset |= (((uint64_t)offset_high) << 32);
}
/* setup the reply packet assuming the maximum possible read */
req_setup_reply(req, 12, 1 + io->readx.in.maxcnt);
/* tell the backend where to put the data. Notice the pad byte. */
- io->readx.out.data = req->out.data + 1;
+ if (io->readx.in.maxcnt != 0xFFFF &&
+ io->readx.in.mincnt != 0xFFFF) {
+ io->readx.out.data = req->out.data + 1;
+ } else {
+ io->readx.out.data = req->out.data;
+ }
- req->async.send_fn = reply_read_and_X_send;
- req->async.private = io;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_read_and_X_send;
+ req->async_states->private_data = io;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->read(req, io);
+ req->async_states->status = ntvfs_read(req, io);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a writebraw (core+ or LANMAN1.0 protocol).
****************************************************************************/
-void reply_writebraw(struct request_context *req)
+void reply_writebraw(struct smbsrv_request *req)
{
/* this one is damn complex - put it off for now */
req_reply_error(req, NT_STATUS_FOOBAR);
/****************************************************************************
Reply to a writeunlock (async reply)
****************************************************************************/
-static void reply_writeunlock_send(struct request_context *req)
+static void reply_writeunlock_send(struct smbsrv_request *req)
{
- union smb_write *io = req->async.private;
+ union smb_write *io = req->async_states->private_data;
CHECK_ASYNC_STATUS;
/****************************************************************************
Reply to a writeunlock (core+).
****************************************************************************/
-void reply_writeunlock(struct request_context *req)
+void reply_writeunlock(struct smbsrv_request *req)
{
union smb_write *io;
return;
}
- req->async.send_fn = reply_writeunlock_send;
- req->async.private = io;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_writeunlock_send;
+ req->async_states->private_data = io;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->write(req, io);
+ req->async_states->status = ntvfs_write(req, io);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a write (async reply)
****************************************************************************/
-static void reply_write_send(struct request_context *req)
+static void reply_write_send(struct smbsrv_request *req)
{
- union smb_write *io = req->async.private;
+ union smb_write *io = req->async_states->private_data;
CHECK_ASYNC_STATUS;
/****************************************************************************
Reply to a write
****************************************************************************/
-void reply_write(struct request_context *req)
+void reply_write(struct smbsrv_request *req)
{
union smb_write *io;
return;
}
- req->async.send_fn = reply_write_send;
- req->async.private = io;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_write_send;
+ req->async_states->private_data = io;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->write(req, io);
+ req->async_states->status = ntvfs_write(req, io);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a write and X (async reply)
****************************************************************************/
-static void reply_write_and_X_send(struct request_context *req)
+static void reply_write_and_X_send(struct smbsrv_request *req)
{
- union smb_write *io = req->async.private;
+ union smb_write *io = req->async_states->private_data;
CHECK_ASYNC_STATUS;
/****************************************************************************
Reply to a write and X.
****************************************************************************/
-void reply_write_and_X(struct request_context *req)
+void reply_write_and_X(struct smbsrv_request *req)
{
union smb_write *io;
io->writex.in.data = req->in.hdr + SVAL(req->in.vwv, VWV(11));
if (req->in.wct == 14) {
- uint32 offset_high = IVAL(req->in.vwv, VWV(12));
- uint16 count_high = SVAL(req->in.vwv, VWV(9));
-#ifdef LARGE_SMB_OFF_T
- io->writex.in.offset |= (((SMB_OFF_T)offset_high) << 32);
-#else
- if (offset_high != 0) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
-#endif
- io->writex.in.count |= ((uint32)count_high) << 16;
+ uint32_t offset_high = IVAL(req->in.vwv, VWV(12));
+ uint16_t count_high = SVAL(req->in.vwv, VWV(9));
+ io->writex.in.offset |= (((uint64_t)offset_high) << 32);
+ io->writex.in.count |= ((uint32_t)count_high) << 16;
}
/* make sure the data is in bounds */
return;
}
- req->async.send_fn = reply_write_and_X_send;
- req->async.private = io;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_write_and_X_send;
+ req->async_states->private_data = io;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->write(req, io);
+ req->async_states->status = ntvfs_write(req, io);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a lseek (async reply)
****************************************************************************/
-static void reply_lseek_send(struct request_context *req)
+static void reply_lseek_send(struct smbsrv_request *req)
{
- struct smb_seek *io = req->async.private;
+ struct smb_seek *io = req->async_states->private_data;
CHECK_ASYNC_STATUS;
/****************************************************************************
Reply to a lseek.
****************************************************************************/
-void reply_lseek(struct request_context *req)
+void reply_lseek(struct smbsrv_request *req)
{
struct smb_seek *io;
io->in.mode = SVAL(req->in.vwv, VWV(1));
io->in.offset = IVALS(req->in.vwv, VWV(2));
- req->async.send_fn = reply_lseek_send;
- req->async.private = io;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_lseek_send;
+ req->async_states->private_data = io;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->seek(req, io);
+ req->async_states->status = ntvfs_seek(req, io);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a flush.
****************************************************************************/
-void reply_flush(struct request_context *req)
+void reply_flush(struct smbsrv_request *req)
{
struct smb_flush *io;
io->in.fnum = req_fnum(req, req->in.vwv, VWV(0));
- req->async.send_fn = reply_simple_send;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_simple_send;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->flush(req, io);
+ req->async_states->status = ntvfs_flush(req, io);
REQ_ASYNC_TAIL;
}
/****************************************************************************
- Reply to a exit.
+ Reply to a exit. This closes all files open by a smbpid
****************************************************************************/
-void reply_exit(struct request_context *req)
+void reply_exit(struct smbsrv_request *req)
{
+ NTSTATUS status;
+ struct smbsrv_tcon *tcon;
REQ_CHECK_WCT(req, 0);
- req->async.send_fn = reply_simple_send;
-
- if (!req->conn) {
- req_reply_error(req, NT_STATUS_INVALID_HANDLE);
- return;
+ for (tcon=req->smb_conn->tree.tcons;tcon;tcon=tcon->next) {
+ req->tcon = tcon;
+ status = ntvfs_exit(req);
+ req->tcon = NULL;
+ if (!NT_STATUS_IS_OK(status)) {
+ req_reply_error(req, status);
+ return;
+ }
}
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->exit(req);
-
- REQ_ASYNC_TAIL;
+ req_setup_reply(req, 0, 0);
+ req_send_reply(req);
}
Note that this has to deal with closing a directory opened by NT SMB's.
****************************************************************************/
-void reply_close(struct request_context *req)
+void reply_close(struct smbsrv_request *req)
{
union smb_close *io;
io->close.level = RAW_CLOSE_CLOSE;
io->close.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
- io->close.in.write_time = make_unix_date3(req->in.vwv + VWV(1));
+ io->close.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
- req->async.send_fn = reply_simple_send;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_simple_send;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->close(req, io);
+ req->async_states->status = ntvfs_close(req, io);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a writeclose (async reply)
****************************************************************************/
-static void reply_writeclose_send(struct request_context *req)
+static void reply_writeclose_send(struct smbsrv_request *req)
{
- union smb_write *io = req->async.private;
+ union smb_write *io = req->async_states->private_data;
CHECK_ASYNC_STATUS;
/****************************************************************************
Reply to a writeclose (Core+ protocol).
****************************************************************************/
-void reply_writeclose(struct request_context *req)
+void reply_writeclose(struct smbsrv_request *req)
{
union smb_write *io;
io->writeclose.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
io->writeclose.in.count = SVAL(req->in.vwv, VWV(1));
io->writeclose.in.offset = IVAL(req->in.vwv, VWV(2));
- io->writeclose.in.mtime = make_unix_date3(req->in.vwv + VWV(4));
+ io->writeclose.in.mtime = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(4));
io->writeclose.in.data = req->in.data + 1;
/* make sure they gave us the data they promised */
return;
}
- req->async.send_fn = reply_writeclose_send;
- req->async.private = io;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_writeclose_send;
+ req->async_states->private_data = io;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->write(req, io);
+ req->async_states->status = ntvfs_write(req, io);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a lock.
****************************************************************************/
-void reply_lock(struct request_context *req)
+void reply_lock(struct smbsrv_request *req)
{
union smb_lock *lck;
lck->lock.in.count = IVAL(req->in.vwv, VWV(1));
lck->lock.in.offset = IVAL(req->in.vwv, VWV(3));
- req->async.send_fn = reply_simple_send;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_simple_send;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->lock(req, lck);
+ req->async_states->status = ntvfs_lock(req, lck);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a unlock.
****************************************************************************/
-void reply_unlock(struct request_context *req)
+void reply_unlock(struct smbsrv_request *req)
{
union smb_lock *lck;
lck->unlock.in.count = IVAL(req->in.vwv, VWV(1));
lck->unlock.in.offset = IVAL(req->in.vwv, VWV(3));
- req->async.send_fn = reply_simple_send;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_simple_send;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->lock(req, lck);
+ req->async_states->status = ntvfs_lock(req, lck);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a tdis.
****************************************************************************/
-void reply_tdis(struct request_context *req)
+void reply_tdis(struct smbsrv_request *req)
{
REQ_CHECK_WCT(req, 0);
- close_cnum(req->conn);
+ close_cnum(req->tcon);
/* construct reply */
req_setup_reply(req, 0, 0);
Reply to a echo. This is one of the few calls that is handled directly (the
backends don't see it at all)
****************************************************************************/
-void reply_echo(struct request_context *req)
+void reply_echo(struct smbsrv_request *req)
{
- uint16 count;
+ uint16_t count;
int i;
REQ_CHECK_WCT(req, 0);
memcpy(req->out.data, req->in.data, req->in.data_size);
- /* we need to make sure the request isn't destroyed till the
- * last packet */
- req->control_flags |= REQ_CONTROL_PROTECTED;
-
for (i=1; i <= count;i++) {
- if (i == count) {
- req->control_flags &= ~REQ_CONTROL_PROTECTED;
+ struct smbsrv_request *this_req;
+
+ if (i != count) {
+ this_req = req_setup_secondary(req);
+ } else {
+ this_req = req;
}
- SSVAL(req->out.vwv, VWV(0), i);
- req_send_reply(req);
+ SSVAL(this_req->out.vwv, VWV(0), i);
+ req_send_reply(this_req);
}
}
/****************************************************************************
Reply to a printopen (async reply)
****************************************************************************/
-static void reply_printopen_send(struct request_context *req)
+static void reply_printopen_send(struct smbsrv_request *req)
{
- union smb_open *oi = req->async.private;
+ union smb_open *oi = req->async_states->private_data;
CHECK_ASYNC_STATUS;
/* construct reply */
req_setup_reply(req, 1, 0);
- SSVAL(req->out.vwv, VWV(0), oi->open.out.fnum);
+ SSVAL(req->out.vwv, VWV(0), oi->openold.out.fnum);
req_send_reply(req);
}
/****************************************************************************
Reply to a printopen.
****************************************************************************/
-void reply_printopen(struct request_context *req)
+void reply_printopen(struct smbsrv_request *req)
{
union smb_open *oi;
req_pull_ascii4(req, &oi->splopen.in.ident, req->in.data, STR_TERMINATE);
- req->async.send_fn = reply_printopen_send;
- req->async.private = oi;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_printopen_send;
+ req->async_states->private_data = oi;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->open(req, oi);
+ req->async_states->status = ntvfs_openfile(req, oi);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a printclose.
****************************************************************************/
-void reply_printclose(struct request_context *req)
+void reply_printclose(struct smbsrv_request *req)
{
union smb_close *io;
io->splclose.level = RAW_CLOSE_SPLCLOSE;
io->splclose.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
- req->async.send_fn = reply_simple_send;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_simple_send;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->close(req, io);
+ req->async_states->status = ntvfs_close(req, io);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a printqueue.
****************************************************************************/
-void reply_printqueue_send(struct request_context *req)
+void reply_printqueue_send(struct smbsrv_request *req)
{
- union smb_lpq *lpq = req->async.private;
+ union smb_lpq *lpq = req->async_states->private_data;
int i, maxcount;
const uint_t el_size = 28;
req->out.ptr = req->out.data + 3;
for (i=0;i<lpq->retq.out.count;i++) {
- put_dos_date2(req->out.ptr, 0 , lpq->retq.out.queue[i].time);
+ srv_push_dos_date2(req->smb_conn, req->out.ptr, 0 , lpq->retq.out.queue[i].time);
SCVAL(req->out.ptr, 4, lpq->retq.out.queue[i].status);
SSVAL(req->out.ptr, 5, lpq->retq.out.queue[i].job);
SIVAL(req->out.ptr, 7, lpq->retq.out.queue[i].size);
/****************************************************************************
Reply to a printqueue.
****************************************************************************/
-void reply_printqueue(struct request_context *req)
+void reply_printqueue(struct smbsrv_request *req)
{
union smb_lpq *lpq;
lpq->retq.in.maxcount = SVAL(req->in.vwv, VWV(0));
lpq->retq.in.startidx = SVAL(req->in.vwv, VWV(1));
- req->async.send_fn = reply_printqueue_send;
- req->async.private = lpq;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_printqueue_send;
+ req->async_states->private_data = lpq;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->lpq(req, lpq);
+ req->async_states->status = ntvfs_lpq(req, lpq);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a printwrite.
****************************************************************************/
-void reply_printwrite(struct request_context *req)
+void reply_printwrite(struct smbsrv_request *req)
{
union smb_write *io;
return;
}
- req->async.send_fn = reply_simple_send;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_simple_send;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->write(req, io);
+ req->async_states->status = ntvfs_write(req, io);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a mkdir.
****************************************************************************/
-void reply_mkdir(struct request_context *req)
+void reply_mkdir(struct smbsrv_request *req)
{
union smb_mkdir *io;
io->generic.level = RAW_MKDIR_MKDIR;
req_pull_ascii4(req, &io->mkdir.in.path, req->in.data, STR_TERMINATE);
- req->async.send_fn = reply_simple_send;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_simple_send;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->mkdir(req, io);
+ req->async_states->status = ntvfs_mkdir(req, io);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a rmdir.
****************************************************************************/
-void reply_rmdir(struct request_context *req)
+void reply_rmdir(struct smbsrv_request *req)
{
struct smb_rmdir *io;
req_pull_ascii4(req, &io->in.path, req->in.data, STR_TERMINATE);
- req->async.send_fn = reply_simple_send;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_simple_send;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->rmdir(req, io);
+ req->async_states->status = ntvfs_rmdir(req, io);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a mv.
****************************************************************************/
-void reply_mv(struct request_context *req)
+void reply_mv(struct smbsrv_request *req)
{
union smb_rename *io;
- char *p;
+ uint8_t *p;
/* parse the request */
REQ_CHECK_WCT(req, 1);
return;
}
- req->async.send_fn = reply_simple_send;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_simple_send;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->rename(req, io);
+ req->async_states->status = ntvfs_rename(req, io);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to an NT rename.
****************************************************************************/
-void reply_ntrename(struct request_context *req)
+void reply_ntrename(struct smbsrv_request *req)
{
union smb_rename *io;
- char *p;
+ uint8_t *p;
/* parse the request */
REQ_CHECK_WCT(req, 4);
return;
}
- req->async.send_fn = reply_simple_send;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_simple_send;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->rename(req, io);
+ req->async_states->status = ntvfs_rename(req, io);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a file copy (async reply)
****************************************************************************/
-static void reply_copy_send(struct request_context *req)
+static void reply_copy_send(struct smbsrv_request *req)
{
- struct smb_copy *cp = req->async.private;
+ struct smb_copy *cp = req->async_states->private_data;
CHECK_ASYNC_STATUS;
/****************************************************************************
Reply to a file copy.
****************************************************************************/
-void reply_copy(struct request_context *req)
+void reply_copy(struct smbsrv_request *req)
{
struct smb_copy *cp;
- char *p;
+ uint8_t *p;
/* parse request */
REQ_CHECK_WCT(req, 3);
return;
}
- req->async.send_fn = reply_copy_send;
- req->async.private = cp;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_copy_send;
+ req->async_states->private_data = cp;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->copy(req, cp);
+ req->async_states->status = ntvfs_copy(req, cp);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a lockingX request (async send)
****************************************************************************/
-static void reply_lockingX_send(struct request_context *req)
+static void reply_lockingX_send(struct smbsrv_request *req)
{
- union smb_lock *lck = req->async.private;
+ union smb_lock *lck = req->async_states->private_data;
CHECK_ASYNC_STATUS;
/****************************************************************************
Reply to a lockingX request.
****************************************************************************/
-void reply_lockingX(struct request_context *req)
+void reply_lockingX(struct smbsrv_request *req)
{
union smb_lock *lck;
uint_t total_locks, i;
uint_t lck_size;
- char *p;
+ uint8_t *p;
/* parse request */
REQ_CHECK_WCT(req, 8);
total_locks = lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt;
- /* there are two varients, one with 64 bit offsets and counts */
+ /* there are two variants, one with 64 bit offsets and counts */
if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
lck_size = 20;
} else {
/* construct the locks array */
for (i=0;i<total_locks;i++) {
- uint32 ofs_high=0, count_high=0;
+ uint32_t ofs_high=0, count_high=0;
lck->lockx.in.locks[i].pid = SVAL(p, 0);
lck->lockx.in.locks[i].count = IVAL(p, 6);
}
if (ofs_high != 0 || count_high != 0) {
-#ifdef LARGE_SMB_OFF_T
- lck->lockx.in.locks[i].count |= ((SMB_OFF_T)count_high) << 32;
- lck->lockx.in.locks[i].offset |= ((SMB_OFF_T)ofs_high) << 32;
-#else
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
-#endif
+ lck->lockx.in.locks[i].count |= ((uint64_t)count_high) << 32;
+ lck->lockx.in.locks[i].offset |= ((uint64_t)ofs_high) << 32;
}
p += lck_size;
}
- req->async.send_fn = reply_lockingX_send;
- req->async.private = lck;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_lockingX_send;
+ req->async_states->private_data = lck;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->lock(req, lck);
+ req->async_states->status = ntvfs_lock(req, lck);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a SMBreadbmpx (read block multiplex) request.
****************************************************************************/
-void reply_readbmpx(struct request_context *req)
+void reply_readbmpx(struct smbsrv_request *req)
{
/* tell the client to not use a multiplexed read - its too broken to use */
req_reply_dos_error(req, ERRSRV, ERRuseSTD);
/****************************************************************************
Reply to a SMBsetattrE.
****************************************************************************/
-void reply_setattrE(struct request_context *req)
+void reply_setattrE(struct smbsrv_request *req)
{
union smb_setfileinfo *info;
info->setattre.level = RAW_SFILEINFO_SETATTRE;
info->setattre.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
- info->setattre.in.create_time = make_unix_date2(req->in.vwv + VWV(1));
- info->setattre.in.access_time = make_unix_date2(req->in.vwv + VWV(3));
- info->setattre.in.write_time = make_unix_date2(req->in.vwv + VWV(5));
+ info->setattre.in.create_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(1));
+ info->setattre.in.access_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(3));
+ info->setattre.in.write_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(5));
- req->async.send_fn = reply_simple_send;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_simple_send;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->setfileinfo(req, info);
+ req->async_states->status = ntvfs_setfileinfo(req, info);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to a SMBwritebmpx (write block multiplex primary) request.
****************************************************************************/
-void reply_writebmpx(struct request_context *req)
+void reply_writebmpx(struct smbsrv_request *req)
{
- /* we will need to implement this one for OS/2, but right now I can't be bothered */
- req_reply_error(req, NT_STATUS_FOOBAR);
+ req_reply_dos_error(req, ERRSRV, ERRuseSTD);
}
/****************************************************************************
Reply to a SMBwritebs (write block multiplex secondary) request.
****************************************************************************/
-void reply_writebs(struct request_context *req)
+void reply_writebs(struct smbsrv_request *req)
{
- /* see reply_writebmpx */
- req_reply_error(req, NT_STATUS_FOOBAR);
+ req_reply_dos_error(req, ERRSRV, ERRuseSTD);
}
/****************************************************************************
Reply to a SMBgetattrE (async reply)
****************************************************************************/
-static void reply_getattrE_send(struct request_context *req)
+static void reply_getattrE_send(struct smbsrv_request *req)
{
- union smb_fileinfo *info = req->async.private;
+ union smb_fileinfo *info = req->async_states->private_data;
CHECK_ASYNC_STATUS;
/* setup reply */
req_setup_reply(req, 11, 0);
- put_dos_date2(req->out.vwv, VWV(0), info->getattre.out.create_time);
- put_dos_date2(req->out.vwv, VWV(2), info->getattre.out.access_time);
- put_dos_date2(req->out.vwv, VWV(4), info->getattre.out.write_time);
+ srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(0), info->getattre.out.create_time);
+ srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(2), info->getattre.out.access_time);
+ srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(4), info->getattre.out.write_time);
SIVAL(req->out.vwv, VWV(6), info->getattre.out.size);
SIVAL(req->out.vwv, VWV(8), info->getattre.out.alloc_size);
SSVAL(req->out.vwv, VWV(10), info->getattre.out.attrib);
/****************************************************************************
Reply to a SMBgetattrE.
****************************************************************************/
-void reply_getattrE(struct request_context *req)
+void reply_getattrE(struct smbsrv_request *req)
{
union smb_fileinfo *info;
info->getattr.level = RAW_FILEINFO_GETATTRE;
info->getattr.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
- req->async.send_fn = reply_getattrE_send;
- req->async.private = info;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_getattrE_send;
+ req->async_states->private_data = info;
/* call backend */
- req->async.status = req->conn->ntvfs_ops->qfileinfo(req, info);
+ req->async_states->status = ntvfs_qfileinfo(req, info);
REQ_ASYNC_TAIL;
}
/****************************************************************************
reply to an old style session setup command
****************************************************************************/
-static void reply_sesssetup_old(struct request_context *req)
+static void reply_sesssetup_old(struct smbsrv_request *req)
{
NTSTATUS status;
union smb_sesssetup sess;
- char *p;
- uint16 passlen;
+ uint8_t *p;
+ uint16_t passlen;
sess.old.level = RAW_SESSSETUP_OLD;
/****************************************************************************
reply to an NT1 style session setup command
****************************************************************************/
-static void reply_sesssetup_nt1(struct request_context *req)
+static void reply_sesssetup_nt1(struct smbsrv_request *req)
{
NTSTATUS status;
union smb_sesssetup sess;
- char *p;
- uint16 passlen1, passlen2;
+ uint8_t *p;
+ uint16_t passlen1, passlen2;
sess.nt1.level = RAW_SESSSETUP_NT1;
/****************************************************************************
reply to an SPNEGO style session setup command
****************************************************************************/
-static void reply_sesssetup_spnego(struct request_context *req)
+static void reply_sesssetup_spnego(struct smbsrv_request *req)
{
NTSTATUS status;
union smb_sesssetup sess;
- char *p;
- uint16 blob_len;
+ uint8_t *p;
+ uint16_t blob_len;
sess.spnego.level = RAW_SESSSETUP_SPNEGO;
/* call the generic handler */
status = sesssetup_backend(req, &sess);
- if (!NT_STATUS_IS_OK(status)) {
+ if (!NT_STATUS_IS_OK(status) &&
+ !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
req_reply_error(req, status);
return;
}
/* construct reply */
req_setup_reply(req, 4, sess.spnego.out.secblob.length);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ req_setup_error(req, status);
+ }
+
SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
SSVAL(req->out.vwv, VWV(1), 0);
SSVAL(req->out.vwv, VWV(2), sess.spnego.out.action);
memcpy(req->out.data, sess.spnego.out.secblob.data, sess.spnego.out.secblob.length);
req_push_str(req, NULL, sess.spnego.out.os, -1, STR_TERMINATE);
req_push_str(req, NULL, sess.spnego.out.lanman, -1, STR_TERMINATE);
+ req_push_str(req, NULL, sess.spnego.out.domain, -1, STR_TERMINATE);
chain_reply(req);
}
/****************************************************************************
reply to a session setup command
****************************************************************************/
-void reply_sesssetup(struct request_context *req)
+void reply_sesssetup(struct smbsrv_request *req)
{
switch (req->in.wct) {
case 10:
return;
}
- /* unsupported varient */
+ /* unsupported variant */
req_reply_error(req, NT_STATUS_FOOBAR);
}
-
/****************************************************************************
Reply to a SMBulogoffX.
****************************************************************************/
-void reply_ulogoffX(struct request_context *req)
+void reply_ulogoffX(struct smbsrv_request *req)
{
- uint16 vuid;
+ struct smbsrv_tcon *tcon;
+ uint16_t vuid;
+ NTSTATUS status;
vuid = SVAL(req->in.hdr, HDR_UID);
-
+
/* in user level security we are supposed to close any files
- open by this user */
+ open by this user on all open tree connects */
if ((vuid != 0) && (lp_security() != SEC_SHARE)) {
- DEBUG(0,("REWRITE: not closing user files\n"));
+ for (tcon=req->smb_conn->tree.tcons;tcon;tcon=tcon->next) {
+ req->tcon = tcon;
+ status = ntvfs_logoff(req);
+ req->tcon = NULL;
+ if (!NT_STATUS_IS_OK(status)) {
+ req_reply_error(req, status);
+ return;
+ }
+ }
}
- invalidate_vuid(req->smb, vuid);
+ smbsrv_invalidate_vuid(req->smb_conn, vuid);
req_setup_reply(req, 2, 0);
/****************************************************************************
Reply to an SMBfindclose request
****************************************************************************/
-void reply_findclose(struct request_context *req)
+void reply_findclose(struct smbsrv_request *req)
{
NTSTATUS status;
union smb_search_close io;
- io.findclose.level = RAW_FINDCLOSE_CLOSE;
+ io.findclose.level = RAW_FINDCLOSE_FINDCLOSE;
/* parse request */
REQ_CHECK_WCT(req, 1);
io.findclose.in.handle = SVAL(req->in.vwv, VWV(0));
/* call backend */
- status = req->conn->ntvfs_ops->search_close(req, &io);
+ status = ntvfs_search_close(req, &io);
if (!NT_STATUS_IS_OK(status)) {
req_reply_error(req, status);
/****************************************************************************
Reply to an SMBfindnclose request
****************************************************************************/
-void reply_findnclose(struct request_context *req)
+void reply_findnclose(struct smbsrv_request *req)
{
req_reply_error(req, NT_STATUS_FOOBAR);
}
/****************************************************************************
Reply to an SMBntcreateX request (async send)
****************************************************************************/
-static void reply_ntcreate_and_X_send(struct request_context *req)
+static void reply_ntcreate_and_X_send(struct smbsrv_request *req)
{
- union smb_open *io = req->async.private;
+ union smb_open *io = req->async_states->private_data;
CHECK_ASYNC_STATUS;
/* the rest of the parameters are not aligned! */
SSVAL(req->out.vwv, 5, io->ntcreatex.out.fnum);
SIVAL(req->out.vwv, 7, io->ntcreatex.out.create_action);
- push_nttime(req->out.vwv, 11, &io->ntcreatex.out.create_time);
- push_nttime(req->out.vwv, 19, &io->ntcreatex.out.access_time);
- push_nttime(req->out.vwv, 27, &io->ntcreatex.out.write_time);
- push_nttime(req->out.vwv, 35, &io->ntcreatex.out.change_time);
+ push_nttime(req->out.vwv, 11, io->ntcreatex.out.create_time);
+ push_nttime(req->out.vwv, 19, io->ntcreatex.out.access_time);
+ push_nttime(req->out.vwv, 27, io->ntcreatex.out.write_time);
+ push_nttime(req->out.vwv, 35, io->ntcreatex.out.change_time);
SIVAL(req->out.vwv, 43, io->ntcreatex.out.attrib);
SBVAL(req->out.vwv, 47, io->ntcreatex.out.alloc_size);
SBVAL(req->out.vwv, 55, io->ntcreatex.out.size);
/****************************************************************************
Reply to an SMBntcreateX request
****************************************************************************/
-void reply_ntcreate_and_X(struct request_context *req)
+void reply_ntcreate_and_X(struct smbsrv_request *req)
{
union smb_open *io;
- uint16 fname_len;
+ uint16_t fname_len;
/* parse the request */
REQ_CHECK_WCT(req, 24);
io->ntcreatex.in.create_options = IVAL(req->in.vwv, 39);
io->ntcreatex.in.impersonation = IVAL(req->in.vwv, 43);
io->ntcreatex.in.security_flags = CVAL(req->in.vwv, 47);
+ io->ntcreatex.in.ea_list = NULL;
+ io->ntcreatex.in.sec_desc = NULL;
/* we need a neater way to handle this alignment */
if ((req->flags2 & FLAGS2_UNICODE_STRINGS) &&
return;
}
- req->async.send_fn = reply_ntcreate_and_X_send;
- req->async.private = io;
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_ntcreate_and_X_send;
+ req->async_states->private_data = io;
/* call the backend */
- req->async.status = req->conn->ntvfs_ops->open(req, io);
+ req->async_states->status = ntvfs_openfile(req, io);
REQ_ASYNC_TAIL;
}
/****************************************************************************
Reply to an SMBntcancel request
****************************************************************************/
-void reply_ntcancel(struct request_context *req)
+void reply_ntcancel(struct smbsrv_request *req)
{
- req_reply_error(req, NT_STATUS_FOOBAR);
+ /* NOTE: this request does not generate a reply */
+ req_signing_no_reply(req);
+ ntvfs_cancel(req);
+ req_destroy(req);
}
/****************************************************************************
Reply to an SMBsends request
****************************************************************************/
-void reply_sends(struct request_context *req)
+void reply_sends(struct smbsrv_request *req)
{
req_reply_error(req, NT_STATUS_FOOBAR);
}
/****************************************************************************
Reply to an SMBsendstrt request
****************************************************************************/
-void reply_sendstrt(struct request_context *req)
+void reply_sendstrt(struct smbsrv_request *req)
{
req_reply_error(req, NT_STATUS_FOOBAR);
}
/****************************************************************************
Reply to an SMBsendend request
****************************************************************************/
-void reply_sendend(struct request_context *req)
+void reply_sendend(struct smbsrv_request *req)
{
req_reply_error(req, NT_STATUS_FOOBAR);
}
/****************************************************************************
Reply to an SMBsendtxt request
****************************************************************************/
-void reply_sendtxt(struct request_context *req)
+void reply_sendtxt(struct smbsrv_request *req)
{
req_reply_error(req, NT_STATUS_FOOBAR);
}
/****************************************************************************
Reply to a special message - a SMB packet with non zero NBT message type
****************************************************************************/
-void reply_special(struct request_context *req)
+void reply_special(struct smbsrv_request *req)
{
- uint8 msg_type;
- char buf[4];
+ uint8_t msg_type;
+ uint8_t *buf = talloc_zero_array_p(req, uint8_t, 4);
msg_type = CVAL(req->in.buffer,0);
switch (msg_type) {
case 0x81: /* session request */
- if (req->smb->negotiate.done_nbt_session) {
- exit_server(req->smb, "multiple session request not permitted");
+ if (req->smb_conn->negotiate.done_nbt_session) {
+ smbsrv_terminate_connection(req->smb_conn, "multiple session request not permitted");
}
SCVAL(buf,0,0x82);
SCVAL(buf,3,0);
DEBUG(0,("REWRITE: not parsing netbios names in NBT session request!\n"));
-
- req->smb->negotiate.done_nbt_session = True;
+ /* TODO: store the name for the session setup 'remote machine' code, as well as smbstatus */
+
+ req->smb_conn->negotiate.done_nbt_session = True;
req->out.buffer = buf;
req->out.size = 4;
- req_send_reply(req);
+ req_send_reply_nosign(req);
return;
case 0x89: /* session keepalive request
SCVAL(buf, 3, 0);
req->out.buffer = buf;
req->out.size = 4;
- req_send_reply(req);
+ req_send_reply_nosign(req);
return;
case SMBkeepalive: