diff options
33 files changed, 1060 insertions, 409 deletions
diff --git a/source4/ntvfs/cifs/vfs_cifs.c b/source4/ntvfs/cifs/vfs_cifs.c index e12fd3de2f..c669414e09 100644 --- a/source4/ntvfs/cifs/vfs_cifs.c +++ b/source4/ntvfs/cifs/vfs_cifs.c @@ -32,12 +32,19 @@ #include "ntvfs/ntvfs.h" #include "include/dlinklist.h" +struct cvfs_file { + struct cvfs_file *prev, *next; + uint16_t fnum; + struct ntvfs_handle *h; +}; + /* this is stored in ntvfs_private */ struct cvfs_private { struct smbcli_tree *tree; struct smbcli_transport *transport; struct ntvfs_module_context *ntvfs; struct async_info *pending; + struct cvfs_file *files; BOOL map_generic; BOOL map_trans2; }; @@ -49,11 +56,24 @@ struct async_info { struct cvfs_private *cvfs; struct ntvfs_request *req; struct smbcli_request *c_req; + struct cvfs_file *f; void *parms; }; #define SETUP_PID private->tree->session->pid = req->smbpid +#define SETUP_FILE do { \ + struct cvfs_file *f; \ + f = ntvfs_handle_get_backend_data(io->generic.in.file.ntvfs, ntvfs); \ + if (!f) return NT_STATUS_INVALID_HANDLE; \ + io->generic.in.file.fnum = f->fnum; \ +} while (0) + +#define SETUP_PID_AND_FILE do { \ + SETUP_PID; \ + SETUP_FILE; \ +} while (0) + /* a handler for oplock break events from the server - these need to be passed along to the client @@ -62,9 +82,22 @@ static BOOL oplock_handler(struct smbcli_transport *transport, uint16_t tid, uin { struct cvfs_private *private = p_private; NTSTATUS status; + struct ntvfs_handle *h = NULL; + struct cvfs_file *f; + + for (f=private->files; f; f=f->next) { + if (f->fnum != fnum) continue; + h = f->h; + break; + } + + if (!h) { + DEBUG(5,("vfs_cifs: ignoring oplock break level %d for fnum %d\n", level, fnum)); + return True; + } DEBUG(5,("vfs_cifs: sending oplock break level %d for fnum %d\n", level, fnum)); - status = ntvfs_send_oplock_break(private->ntvfs, fnum, level); + status = ntvfs_send_oplock_break(private->ntvfs, h, level); if (!NT_STATUS_IS_OK(status)) return False; return True; } @@ -227,7 +260,7 @@ static void async_simple(struct smbcli_request *c_req) /* save some typing for the simple functions */ -#define ASYNC_RECV_TAIL(io, async_fn) do { \ +#define ASYNC_RECV_TAIL_F(io, async_fn, file) do { \ if (!c_req) return NT_STATUS_UNSUCCESSFUL; \ { \ struct async_info *async; \ @@ -235,6 +268,7 @@ static void async_simple(struct smbcli_request *c_req) if (!async) return NT_STATUS_NO_MEMORY; \ async->parms = io; \ async->req = req; \ + async->f = file; \ async->cvfs = private; \ async->c_req = c_req; \ DLIST_ADD(private->pending, async); \ @@ -246,6 +280,8 @@ static void async_simple(struct smbcli_request *c_req) return NT_STATUS_OK; \ } while (0) +#define ASYNC_RECV_TAIL(io, async_fn) ASYNC_RECV_TAIL_F(io, async_fn, NULL) + #define SIMPLE_ASYNC_TAIL ASYNC_RECV_TAIL(NULL, async_simple) /* @@ -287,12 +323,12 @@ static void async_ioctl(struct smbcli_request *c_req) ioctl interface */ static NTSTATUS cvfs_ioctl(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_ioctl *io) + struct ntvfs_request *req, union smb_ioctl *io) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; - SETUP_PID; + SETUP_PID_AND_FILE; /* see if the front end will allow us to perform this function asynchronously. */ @@ -309,7 +345,7 @@ static NTSTATUS cvfs_ioctl(struct ntvfs_module_context *ntvfs, check if a directory exists */ static NTSTATUS cvfs_chkpath(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_chkpath *cp) + struct ntvfs_request *req, union smb_chkpath *cp) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; @@ -341,7 +377,7 @@ static void async_qpathinfo(struct smbcli_request *c_req) return info on a pathname */ static NTSTATUS cvfs_qpathinfo(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_fileinfo *info) + struct ntvfs_request *req, union smb_fileinfo *info) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; @@ -373,20 +409,20 @@ static void async_qfileinfo(struct smbcli_request *c_req) query info on a open file */ static NTSTATUS cvfs_qfileinfo(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_fileinfo *info) + struct ntvfs_request *req, union smb_fileinfo *io) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; - SETUP_PID; + SETUP_PID_AND_FILE; if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { - return smb_raw_fileinfo(private->tree, req, info); + return smb_raw_fileinfo(private->tree, req, io); } - c_req = smb_raw_fileinfo_send(private->tree, info); + c_req = smb_raw_fileinfo_send(private->tree, io); - ASYNC_RECV_TAIL(info, async_qfileinfo); + ASYNC_RECV_TAIL(io, async_qfileinfo); } @@ -394,7 +430,7 @@ static NTSTATUS cvfs_qfileinfo(struct ntvfs_module_context *ntvfs, set info on a pathname */ static NTSTATUS cvfs_setpathinfo(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_setfileinfo *st) + struct ntvfs_request *req, union smb_setfileinfo *st) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; @@ -417,9 +453,21 @@ static NTSTATUS cvfs_setpathinfo(struct ntvfs_module_context *ntvfs, static void async_open(struct smbcli_request *c_req) { struct async_info *async = c_req->async.private; + struct cvfs_private *cvfs = async->cvfs; struct ntvfs_request *req = async->req; - req->async_states->status = smb_raw_open_recv(c_req, req, async->parms); + struct cvfs_file *f = async->f; + union smb_open *io = async->parms; + union smb_handle *file; talloc_free(async); + req->async_states->status = smb_raw_open_recv(c_req, req, io); + SMB_OPEN_OUT_FILE(io, file); + f->fnum = file->fnum; + file->ntvfs = NULL; + if (!NT_STATUS_IS_OK(req->async_states->status)) goto failed; + req->async_states->status = ntvfs_handle_set_backend_data(f->h, cvfs->ntvfs, f); + if (!NT_STATUS_IS_OK(req->async_states->status)) goto failed; + file->ntvfs = f->h; +failed: req->async_states->send_fn(req); } @@ -427,10 +475,13 @@ static void async_open(struct smbcli_request *c_req) open a file */ static NTSTATUS cvfs_open(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_open *io) + struct ntvfs_request *req, union smb_open *io) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; + struct ntvfs_handle *h; + struct cvfs_file *f; + NTSTATUS status; SETUP_PID; @@ -439,20 +490,39 @@ static NTSTATUS cvfs_open(struct ntvfs_module_context *ntvfs, return ntvfs_map_open(ntvfs, req, io); } + status = ntvfs_handle_new(ntvfs, req, &h); + NT_STATUS_NOT_OK_RETURN(status); + + f = talloc_zero(h, struct cvfs_file); + NT_STATUS_HAVE_NO_MEMORY(f); + f->h = h; + if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { - return smb_raw_open(private->tree, req, io); + union smb_handle *file; + + status = smb_raw_open(private->tree, req, io); + NT_STATUS_NOT_OK_RETURN(status); + + SMB_OPEN_OUT_FILE(io, file); + f->fnum = file->fnum; + file->ntvfs = NULL; + status = ntvfs_handle_set_backend_data(f->h, private->ntvfs, f); + NT_STATUS_NOT_OK_RETURN(status); + file->ntvfs = f->h; + + return NT_STATUS_OK; } c_req = smb_raw_open_send(private->tree, io); - ASYNC_RECV_TAIL(io, async_open); + ASYNC_RECV_TAIL_F(io, async_open, f); } /* create a directory */ static NTSTATUS cvfs_mkdir(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_mkdir *md) + struct ntvfs_request *req, union smb_mkdir *md) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; @@ -472,7 +542,7 @@ static NTSTATUS cvfs_mkdir(struct ntvfs_module_context *ntvfs, remove a directory */ static NTSTATUS cvfs_rmdir(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, struct smb_rmdir *rd) + struct ntvfs_request *req, struct smb_rmdir *rd) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; @@ -491,7 +561,7 @@ static NTSTATUS cvfs_rmdir(struct ntvfs_module_context *ntvfs, rename a set of files */ static NTSTATUS cvfs_rename(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_rename *ren) + struct ntvfs_request *req, union smb_rename *ren) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; @@ -511,7 +581,7 @@ static NTSTATUS cvfs_rename(struct ntvfs_module_context *ntvfs, copy a set of files */ static NTSTATUS cvfs_copy(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, struct smb_copy *cp) + struct ntvfs_request *req, struct smb_copy *cp) { return NT_STATUS_NOT_SUPPORTED; } @@ -532,25 +602,27 @@ static void async_read(struct smbcli_request *c_req) read from a file */ static NTSTATUS cvfs_read(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_read *rd) + struct ntvfs_request *req, union smb_read *io) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; SETUP_PID; - if (rd->generic.level != RAW_READ_GENERIC && + if (io->generic.level != RAW_READ_GENERIC && private->map_generic) { - return ntvfs_map_read(ntvfs, req, rd); + return ntvfs_map_read(ntvfs, req, io); } + SETUP_FILE; + if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { - return smb_raw_read(private->tree, rd); + return smb_raw_read(private->tree, io); } - c_req = smb_raw_read_send(private->tree, rd); + c_req = smb_raw_read_send(private->tree, io); - ASYNC_RECV_TAIL(rd, async_read); + ASYNC_RECV_TAIL(io, async_read); } /* @@ -569,25 +641,26 @@ static void async_write(struct smbcli_request *c_req) write to a file */ static NTSTATUS cvfs_write(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_write *wr) + struct ntvfs_request *req, union smb_write *io) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; SETUP_PID; - if (wr->generic.level != RAW_WRITE_GENERIC && + if (io->generic.level != RAW_WRITE_GENERIC && private->map_generic) { - return ntvfs_map_write(ntvfs, req, wr); + return ntvfs_map_write(ntvfs, req, io); } + SETUP_FILE; if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { - return smb_raw_write(private->tree, wr); + return smb_raw_write(private->tree, io); } - c_req = smb_raw_write_send(private->tree, wr); + c_req = smb_raw_write_send(private->tree, io); - ASYNC_RECV_TAIL(wr, async_write); + ASYNC_RECV_TAIL(io, async_write); } /* @@ -612,7 +685,7 @@ static NTSTATUS cvfs_seek(struct ntvfs_module_context *ntvfs, struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; - SETUP_PID; + SETUP_PID_AND_FILE; if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { return smb_raw_seek(private->tree, io); @@ -634,6 +707,14 @@ static NTSTATUS cvfs_flush(struct ntvfs_module_context *ntvfs, struct smbcli_request *c_req; SETUP_PID; + switch (io->generic.level) { + case RAW_FLUSH_FLUSH: + SETUP_FILE; + break; + case RAW_FLUSH_ALL: + io->generic.in.file.fnum = 0xFFFF; + break; + } if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { return smb_raw_flush(private->tree, io); @@ -648,7 +729,7 @@ static NTSTATUS cvfs_flush(struct ntvfs_module_context *ntvfs, close a file */ static NTSTATUS cvfs_close(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_close *io) + struct ntvfs_request *req, union smb_close *io) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; @@ -659,6 +740,7 @@ static NTSTATUS cvfs_close(struct ntvfs_module_context *ntvfs, private->map_generic) { return ntvfs_map_close(ntvfs, req, io); } + SETUP_FILE; if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { return smb_raw_close(private->tree, io); @@ -673,7 +755,7 @@ static NTSTATUS cvfs_close(struct ntvfs_module_context *ntvfs, exit - closing files open by the pid */ static NTSTATUS cvfs_exit(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req) + struct ntvfs_request *req) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; @@ -693,7 +775,7 @@ static NTSTATUS cvfs_exit(struct ntvfs_module_context *ntvfs, logoff - closing files open by the user */ static NTSTATUS cvfs_logoff(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req) + struct ntvfs_request *req) { /* we can't do this right in the cifs backend .... */ return NT_STATUS_OK; @@ -736,23 +818,24 @@ static NTSTATUS cvfs_cancel(struct ntvfs_module_context *ntvfs, lock a byte range */ static NTSTATUS cvfs_lock(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_lock *lck) + struct ntvfs_request *req, union smb_lock *io) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; SETUP_PID; - if (lck->generic.level != RAW_LOCK_GENERIC && + if (io->generic.level != RAW_LOCK_GENERIC && private->map_generic) { - return ntvfs_map_lock(ntvfs, req, lck); + return ntvfs_map_lock(ntvfs, req, io); } + SETUP_FILE; if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { - return smb_raw_lock(private->tree, lck); + return smb_raw_lock(private->tree, io); } - c_req = smb_raw_lock_send(private->tree, lck); + c_req = smb_raw_lock_send(private->tree, io); SIMPLE_ASYNC_TAIL; } @@ -761,17 +844,17 @@ static NTSTATUS cvfs_lock(struct ntvfs_module_context *ntvfs, */ static NTSTATUS cvfs_setfileinfo(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, - union smb_setfileinfo *info) + union smb_setfileinfo *io) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; - SETUP_PID; + SETUP_PID_AND_FILE; if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { - return smb_raw_setfileinfo(private->tree, info); + return smb_raw_setfileinfo(private->tree, io); } - c_req = smb_raw_setfileinfo_send(private->tree, info); + c_req = smb_raw_setfileinfo_send(private->tree, io); SIMPLE_ASYNC_TAIL; } @@ -793,7 +876,7 @@ static void async_fsinfo(struct smbcli_request *c_req) return filesystem space info */ static NTSTATUS cvfs_fsinfo(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_fsinfo *fs) + struct ntvfs_request *req, union smb_fsinfo *fs) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; @@ -813,7 +896,7 @@ static NTSTATUS cvfs_fsinfo(struct ntvfs_module_context *ntvfs, return print queue info */ static NTSTATUS cvfs_lpq(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_lpq *lpq) + struct ntvfs_request *req, union smb_lpq *lpq) { return NT_STATUS_NOT_SUPPORTED; } @@ -916,14 +999,19 @@ static void async_changenotify(struct smbcli_request *c_req) /* change notify request - always async */ static NTSTATUS cvfs_notify(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, - struct smb_notify *info) + struct smb_notify *io) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; int saved_timeout = private->transport->options.request_timeout; + struct cvfs_file *f; SETUP_PID; + f = ntvfs_handle_get_backend_data(io->in.file.ntvfs, ntvfs); + if (!f) return NT_STATUS_INVALID_HANDLE; + io->in.file.fnum = f->fnum; + /* this request doesn't make sense unless its async */ if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { return NT_STATUS_INVALID_PARAMETER; @@ -933,11 +1021,11 @@ static NTSTATUS cvfs_notify(struct ntvfs_module_context *ntvfs, forever */ private->transport->options.request_timeout = 0; - c_req = smb_raw_changenotify_send(private->tree, info); + c_req = smb_raw_changenotify_send(private->tree, io); private->transport->options.request_timeout = saved_timeout; - ASYNC_RECV_TAIL(info, async_changenotify); + ASYNC_RECV_TAIL(io, async_changenotify); } /* diff --git a/source4/ntvfs/cifs_posix_cli/vfs_simple.c b/source4/ntvfs/cifs_posix_cli/vfs_simple.c index bbe52d9db1..cf28a02806 100644 --- a/source4/ntvfs/cifs_posix_cli/vfs_simple.c +++ b/source4/ntvfs/cifs_posix_cli/vfs_simple.c @@ -19,6 +19,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* this module needs to be converted to use ntvfs_handle's! */ +#define fnum _XXX_use_ntvfs_handle_not_fnum_XXX_ + /* this implements a very simple NTVFS filesystem backend. diff --git a/source4/ntvfs/common/brlock.c b/source4/ntvfs/common/brlock.c index b5df434435..2816c563b8 100644 --- a/source4/ntvfs/common/brlock.c +++ b/source4/ntvfs/common/brlock.c @@ -57,7 +57,7 @@ struct lock_context { size of the record */ struct lock_struct { struct lock_context context; - uint16_t fnum; + struct ntvfs_handle *ntvfs; uint64_t start; uint64_t size; enum brl_type lock_type; @@ -67,7 +67,7 @@ struct lock_struct { /* this struct is attached to on oprn file handle */ struct brl_handle { DATA_BLOB key; - uint16_t fnum; + struct ntvfs_handle *ntvfs; struct lock_struct last_lock; }; @@ -109,7 +109,7 @@ struct brl_context *brl_init(TALLOC_CTX *mem_ctx, uint32_t server, return brl; } -struct brl_handle *brl_create_handle(TALLOC_CTX *mem_ctx, DATA_BLOB *file_key, uint16_t fnum) +struct brl_handle *brl_create_handle(TALLOC_CTX *mem_ctx, struct ntvfs_handle *ntvfs, DATA_BLOB *file_key) { struct brl_handle *brlh; @@ -119,7 +119,7 @@ struct brl_handle *brl_create_handle(TALLOC_CTX *mem_ctx, DATA_BLOB *file_key, u } brlh->key = *file_key; - brlh->fnum = fnum; + brlh->ntvfs = ntvfs; ZERO_STRUCT(brlh->last_lock); return brlh; @@ -173,7 +173,7 @@ static BOOL brl_conflict(struct lock_struct *lck1, } if (brl_same_context(&lck1->context, &lck2->context) && - lck2->lock_type == READ_LOCK && lck1->fnum == lck2->fnum) { + lck2->lock_type == READ_LOCK && lck1->ntvfs == lck2->ntvfs) { return False; } @@ -202,7 +202,7 @@ static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck * in smbtorture. */ if (brl_same_context(&lck1->context, &lck2->context) && - lck1->fnum == lck2->fnum && + lck1->ntvfs == lck2->ntvfs && (lck2->lock_type == READ_LOCK || lck1->lock_type == WRITE_LOCK)) { return False; } @@ -251,7 +251,7 @@ static NTSTATUS brl_lock_failed(struct brl_handle *brlh, struct lock_struct *loc */ if (lock->context.server == brlh->last_lock.context.server && lock->context.ctx == brlh->last_lock.context.ctx && - lock->fnum == brlh->last_lock.fnum && + lock->ntvfs == brlh->last_lock.ntvfs && lock->start == brlh->last_lock.start) { return NT_STATUS_FILE_LOCK_CONFLICT; } @@ -310,7 +310,7 @@ NTSTATUS brl_lock(struct brl_context *brl, lock.context.smbpid = smbpid; lock.context.server = brl->server; lock.context.ctx = brl; - lock.fnum = brlh->fnum; + lock.ntvfs = brlh->ntvfs; lock.context.ctx = brl; lock.start = start; lock.size = size; @@ -454,7 +454,7 @@ NTSTATUS brl_unlock(struct brl_context *brl, struct lock_struct *lock = &locks[i]; if (brl_same_context(&lock->context, &context) && - lock->fnum == brlh->fnum && + lock->ntvfs == brlh->ntvfs && lock->start == start && lock->size == size && lock->lock_type < PENDING_READ_LOCK) { @@ -595,7 +595,7 @@ NTSTATUS brl_locktest(struct brl_context *brl, lock.context.smbpid = smbpid; lock.context.server = brl->server; lock.context.ctx = brl; - lock.fnum = brlh->fnum; + lock.ntvfs = brlh->ntvfs; lock.start = start; lock.size = size; lock.lock_type = lock_type; @@ -649,7 +649,7 @@ NTSTATUS brl_close(struct brl_context *brl, if (lock->context.ctx == brl && lock->context.server == brl->server && - lock->fnum == brlh->fnum) { + lock->ntvfs == brlh->ntvfs) { /* found it - delete it */ if (count > 1 && i < count-1) { memmove(&locks[i], &locks[i+1], diff --git a/source4/ntvfs/ipc/vfs_ipc.c b/source4/ntvfs/ipc/vfs_ipc.c index 6ef380c4eb..fdad41145b 100644 --- a/source4/ntvfs/ipc/vfs_ipc.c +++ b/source4/ntvfs/ipc/vfs_ipc.c @@ -32,16 +32,12 @@ #include "ntvfs/ipc/proto.h" #include "rpc_server/dcerpc_server.h" -#define IPC_BASE_FNUM 0x400 - /* this is the private structure used to keep the state of an open ipc$ connection. It needs to keep information about all open pipes */ struct ipc_private { struct ntvfs_module_context *ntvfs; - struct idr_context *idtree_fnum; - struct dcesrv_context *dcesrv; /* a list of open pipes */ @@ -49,41 +45,43 @@ struct ipc_private { struct pipe_state *next, *prev; struct ipc_private *private; const char *pipe_name; - uint16_t fnum; + struct ntvfs_handle *handle; struct dcesrv_connection *dce_conn; uint16_t ipc_state; - /* we need to remember the session it was opened on, - as it is illegal to operate on someone elses fnum */ - struct auth_session_info *session_info; - - /* we need to remember the client pid that - opened the file so SMBexit works */ - uint16_t smbpid; } *pipe_list; }; /* - find a open pipe give a file descriptor + find a open pipe give a file handle */ -static struct pipe_state *pipe_state_find(struct ipc_private *private, uint16_t fnum, - struct auth_session_info *session_info) +static struct pipe_state *pipe_state_find(struct ipc_private *private, struct ntvfs_handle *handle) { struct pipe_state *s; void *p; - p = idr_find(private->idtree_fnum, fnum); + p = ntvfs_handle_get_backend_data(handle, private->ntvfs); if (!p) return NULL; s = talloc_get_type(p, struct pipe_state); - - if (s->session_info != session_info) { - return NULL; - } + if (!s) return NULL; return s; } +/* + find a open pipe give a wire fnum +*/ +static struct pipe_state *pipe_state_find_key(struct ipc_private *private, struct ntvfs_request *req, const DATA_BLOB *key) +{ + struct ntvfs_handle *h; + + h = ntvfs_handle_search_by_wire_key(private->ntvfs, req, key); + if (!h) return NULL; + + return pipe_state_find(private, h); +} + /* connect to a share - always works @@ -109,9 +107,6 @@ static NTSTATUS ipc_connect(struct ntvfs_module_context *ntvfs, private->ntvfs = ntvfs; private->pipe_list = NULL; - private->idtree_fnum = idr_init(private); - NT_STATUS_HAVE_NO_MEMORY(private->idtree_fnum); - /* setup the DCERPC server subsystem */ status = dcesrv_init_ipc_context(private, &private->dcesrv); NT_STATUS_NOT_OK_RETURN(status); @@ -182,7 +177,6 @@ static NTSTATUS ipc_setpathinfo(struct ntvfs_module_context *ntvfs, static int ipc_fd_destructor(void *ptr) { struct pipe_state *p = ptr; - idr_remove(p->private->idtree_fnum, p->fnum); DLIST_REMOVE(p->private->pipe_list, p); return 0; } @@ -212,9 +206,12 @@ static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs, NTSTATUS status; struct dcerpc_binding *ep_description; struct ipc_private *private = ntvfs->private_data; - int fnum; + struct ntvfs_handle *h; + + status = ntvfs_handle_new(ntvfs, req, &h); + NT_STATUS_NOT_OK_RETURN(status); - p = talloc(req, struct pipe_state); + p = talloc(h, struct pipe_state); NT_STATUS_HAVE_NO_MEMORY(p); ep_description = talloc(req, struct dcerpc_binding); @@ -225,12 +222,7 @@ static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs, p->pipe_name = talloc_asprintf(p, "\\pipe\\%s", fname); NT_STATUS_HAVE_NO_MEMORY(p->pipe_name); - fnum = idr_get_new_above(private->idtree_fnum, p, IPC_BASE_FNUM, UINT16_MAX); - if (fnum == -1) { - return NT_STATUS_TOO_MANY_OPENED_FILES; - } - - p->fnum = fnum; + p->handle = h; p->ipc_state = 0x5ff; /* @@ -248,14 +240,11 @@ static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs, status = dcesrv_endpoint_search_connect(private->dcesrv, p, ep_description, - req->session_info, + h->session_info, ntvfs->ctx->event_ctx, 0, &p->dce_conn); - if (!NT_STATUS_IS_OK(status)) { - idr_remove(private->idtree_fnum, p->fnum); - return status; - } + NT_STATUS_NOT_OK_RETURN(status); p->dce_conn->transport.private_data = private; p->dce_conn->transport.report_output_data = NULL; @@ -264,16 +253,14 @@ static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs, DLIST_ADD(private->pipe_list, p); - p->smbpid = req->smbpid; - p->session_info = req->session_info; p->private = private; - *ps = p; - - talloc_steal(private, p); - talloc_set_destructor(p, ipc_fd_destructor); + status = ntvfs_handle_set_backend_data(h, private->ntvfs, p); + NT_STATUS_NOT_OK_RETURN(status); + + *ps = p; return NT_STATUS_OK; } @@ -292,7 +279,7 @@ static NTSTATUS ipc_open_ntcreatex(struct ntvfs_module_context *ntvfs, } ZERO_STRUCT(oi->ntcreatex.out); - oi->ntcreatex.out.file.fnum = p->fnum; + oi->ntcreatex.out.file.ntvfs= p->handle; oi->ntcreatex.out.ipc_state = p->ipc_state; oi->ntcreatex.out.file_type = FILE_TYPE_MESSAGE_MODE_PIPE; @@ -315,7 +302,7 @@ static NTSTATUS ipc_open_openx(struct ntvfs_module_context *ntvfs, } ZERO_STRUCT(oi->openx.out); - oi->openx.out.file.fnum = p->fnum; + oi->openx.out.file.ntvfs= p->handle; oi->openx.out.ftype = 2; oi->openx.out.devstate = p->ipc_state; @@ -401,7 +388,6 @@ static NTSTATUS ipc_read(struct ntvfs_module_context *ntvfs, { struct ipc_private *private = ntvfs->private_data; DATA_BLOB data; - uint16_t fnum; struct pipe_state *p; NTSTATUS status = NT_STATUS_OK; @@ -409,9 +395,7 @@ static NTSTATUS ipc_read(struct ntvfs_module_context *ntvfs, return ntvfs_map_read(ntvfs, req, rd); } - fnum = rd->readx.in.file.fnum; - - p = pipe_state_find(private, fnum, req->session_info); + p = pipe_state_find(private, rd->readx.in.file.ntvfs); if (!p) { return NT_STATUS_INVALID_HANDLE; } @@ -444,7 +428,6 @@ static NTSTATUS ipc_write(struct ntvfs_module_context *ntvfs, { struct ipc_private *private = ntvfs->private_data; DATA_BLOB data; - uint16_t fnum; struct pipe_state *p; NTSTATUS status; @@ -452,11 +435,10 @@ static NTSTATUS ipc_write(struct ntvfs_module_context *ntvfs, return ntvfs_map_write(ntvfs, req, wr); } - fnum = wr->writex.in.file.fnum; data.data = discard_const_p(void, wr->writex.in.data); data.length = wr->writex.in.count; - p = pipe_state_find(private, fnum, req->session_info); + p = pipe_state_find(private, wr->writex.in.file.ntvfs); if (!p) { return NT_STATUS_INVALID_HANDLE; } @@ -505,7 +487,7 @@ static NTSTATUS ipc_close(struct ntvfs_module_context *ntvfs, return ntvfs_map_close(ntvfs, req, io); } - p = pipe_state_find(private, io->close.in.file.fnum, req->session_info); + p = pipe_state_find(private, io->close.in.file.ntvfs); if (!p) { return NT_STATUS_INVALID_HANDLE; } @@ -526,8 +508,8 @@ static NTSTATUS ipc_exit(struct ntvfs_module_context *ntvfs, for (p=private->pipe_list; p; p=next) { next = p->next; - if (p->session_info == req->session_info && - p->smbpid == req->smbpid) { + if (p->handle->session_info == req->session_info && + p->handle->smbpid == req->smbpid) { talloc_free(p); } } @@ -546,7 +528,7 @@ static NTSTATUS ipc_logoff(struct ntvfs_module_context *ntvfs, for (p=private->pipe_list; p; p=next) { next = p->next; - if (p->session_info == req->session_info) { + if (p->handle->session_info == req->session_info) { talloc_free(p); } } @@ -674,9 +656,12 @@ static NTSTATUS ipc_dcerpc_cmd(struct ntvfs_module_context *ntvfs, struct pipe_state *p; struct ipc_private *private = ntvfs->private_data; NTSTATUS status; + DATA_BLOB fnum_key; /* the fnum is in setup[1] */ - p = pipe_state_find(private, trans->in.setup[1], req->session_info); + fnum_key = data_blob_const(&trans->in.setup[1], sizeof(trans->in.setup[1])); + + p = pipe_state_find_key(private, req, &fnum_key); if (!p) { return NT_STATUS_INVALID_HANDLE; } @@ -715,13 +700,16 @@ static NTSTATUS ipc_dcerpc_cmd(struct ntvfs_module_context *ntvfs, /* SMBtrans - set named pipe state */ static NTSTATUS ipc_set_nm_pipe_state(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, struct smb_trans2 *trans) + struct ntvfs_request *req, struct smb_trans2 *trans) { struct ipc_private *private = ntvfs->private_data; struct pipe_state *p; + DATA_BLOB fnum_key; /* the fnum is in setup[1] */ - p = pipe_state_find(private, trans->in.setup[1], req->session_info); + fnum_key = data_blob_const(&trans->in.setup[1], sizeof(trans->in.setup[1])); + + p = pipe_state_find_key(private, req, &fnum_key); if (!p) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/nbench/vfs_nbench.c b/source4/ntvfs/nbench/vfs_nbench.c index 963d422cf0..2df3b95494 100644 --- a/source4/ntvfs/nbench/vfs_nbench.c +++ b/source4/ntvfs/nbench/vfs_nbench.c @@ -54,6 +54,26 @@ static void nbench_log(struct ntvfs_request *req, free(s); } +static char *nbench_ntvfs_handle_string(struct ntvfs_request *req, struct ntvfs_handle *h) +{ + DATA_BLOB key; + uint16_t fnum = 0; + + key = ntvfs_handle_get_wire_key(h, req); + + switch (key.length) { + case 2: /* SMB fnum */ + fnum = SVAL(key.data, 0); + break; + default: + DEBUG(0,("%s: invalid wire handle size: %u\n", + __FUNCTION__, key.length)); + break; + } + + return talloc_asprintf(req, "%u", fnum); +} + /* this pass through macro operates on request contexts, and disables async calls. @@ -237,8 +257,8 @@ static void nbench_qfileinfo_send(struct ntvfs_request *req) { union smb_fileinfo *info = req->async_states->private_data; - nbench_log(req, "QUERY_FILE_INFORMATION %d %d %s\n", - info->generic.in.file.fnum, + nbench_log(req, "QUERY_FILE_INFORMATION %s %d %s\n", + nbench_ntvfs_handle_string(req, info->generic.in.file.ntvfs), info->generic.level, get_nt_error_c_code(req->async_states->status)); @@ -292,11 +312,11 @@ static void nbench_open_send(struct ntvfs_request *req) if (!NT_STATUS_IS_OK(req->async_states->status)) { ZERO_STRUCT(io->ntcreatex.out); } - nbench_log(req, "NTCreateX \"%s\" 0x%x 0x%x %d %s\n", + nbench_log(req, "NTCreateX \"%s\" 0x%x 0x%x %s %s\n", io->ntcreatex.in.fname, io->ntcreatex.in.create_options, io->ntcreatex.in.open_disposition, - io->ntcreatex.out.file.fnum, + nbench_ntvfs_handle_string(req, io->ntcreatex.out.file.ntvfs), get_nt_error_c_code(req->async_states->status)); break; @@ -430,8 +450,8 @@ static void nbench_read_send(struct ntvfs_request *req) if (!NT_STATUS_IS_OK(req->async_states->status)) { ZERO_STRUCT(rd->readx.out); } - nbench_log(req, "ReadX %d %d %d %d %s\n", - rd->readx.in.file.fnum, + nbench_log(req, "ReadX %s %d %d %d %s\n", + nbench_ntvfs_handle_string(req, rd->readx.in.file.ntvfs), (int)rd->readx.in.offset, rd->readx.in.maxcnt, rd->readx.out.nread, @@ -468,8 +488,8 @@ static void nbench_write_send(struct ntvfs_request *req) if (!NT_STATUS_IS_OK(req->async_states->status)) { ZERO_STRUCT(wr->writex.out); } - nbench_log(req, "WriteX %d %d %d %d %s\n", - wr->writex.in.file.fnum, + nbench_log(req, "WriteX %s %d %d %d %s\n", + nbench_ntvfs_handle_string(req, wr->writex.in.file.ntvfs), (int)wr->writex.in.offset, wr->writex.in.count, wr->writex.out.nwritten, @@ -480,8 +500,8 @@ static void nbench_write_send(struct ntvfs_request *req) if (!NT_STATUS_IS_OK(req->async_states->status)) { ZERO_STRUCT(wr->write.out); } - nbench_log(req, "Write %d %d %d %d %s\n", - wr->write.in.file.fnum, + nbench_log(req, "Write %s %d %d %d %s\n", + nbench_ntvfs_handle_string(req, wr->write.in.file.ntvfs), wr->write.in.offset, wr->write.in.count, wr->write.out.nwritten, @@ -534,20 +554,20 @@ static NTSTATUS nbench_seek(struct ntvfs_module_context *ntvfs, static void nbench_flush_send(struct ntvfs_request *req) { union smb_flush *io = req->async_states->private_data; - uint16_t fnum; switch (io->generic.level) { case RAW_FLUSH_FLUSH: - fnum = io->flush.in.file.fnum; + nbench_log(req, "Flush %s %s\n", + nbench_ntvfs_handle_string(req, io->flush.in.file.ntvfs), + get_nt_error_c_code(req->async_states->status)); break; case RAW_FLUSH_ALL: - fnum = 0xFFFF; + nbench_log(req, "Flush %d %s\n", + 0xFFFF, + get_nt_error_c_code(req->async_states->status)); break; } - nbench_log(req, "Flush %d %s\n", - fnum, get_nt_error_c_code(req->async_states->status)); - PASS_THRU_REP_POST(req); } @@ -571,8 +591,8 @@ static void nbench_close_send(struct ntvfs_request *req) switch (io->generic.level) { case RAW_CLOSE_CLOSE: - nbench_log(req, "Close %d %s\n", - io->close.in.file.fnum, + nbench_log(req, "Close %s %s\n", + nbench_ntvfs_handle_string(req, io->close.in.file.ntvfs), get_nt_error_c_code(req->async_states->status)); break; @@ -686,15 +706,15 @@ static void nbench_lock_send(struct ntvfs_request *req) if (lck->generic.level == RAW_LOCK_LOCKX && lck->lockx.in.lock_cnt == 1 && lck->lockx.in.ulock_cnt == 0) { - nbench_log(req, "LockX %d %d %d %s\n", - lck->lockx.in.file.fnum, + nbench_log(req, "LockX %s %d %d %s\n", + nbench_ntvfs_handle_string(req, lck->lockx.in.file.ntvfs), (int)lck->lockx.in.locks[0].offset, (int)lck->lockx.in.locks[0].count, get_nt_error_c_code(req->async_states->status)); } else if (lck->generic.level == RAW_LOCK_LOCKX && lck->lockx.in.ulock_cnt == 1) { - nbench_log(req, "UnlockX %d %d %d %s\n", - lck->lockx.in.file.fnum, + nbench_log(req, "UnlockX %s %d %d %s\n", + nbench_ntvfs_handle_string(req, lck->lockx.in.file.ntvfs), (int)lck->lockx.in.locks[0].offset, (int)lck->lockx.in.locks[0].count, get_nt_error_c_code(req->async_states->status)); @@ -722,8 +742,8 @@ static void nbench_setfileinfo_send(struct ntvfs_request *req) { union smb_setfileinfo *info = req->async_states->private_data; - nbench_log(req, "SET_FILE_INFORMATION %d %d %s\n", - info->generic.in.file.fnum, + nbench_log(req, "SET_FILE_INFORMATION %s %d %s\n", + nbench_ntvfs_handle_string(req, info->generic.in.file.ntvfs), info->generic.level, get_nt_error_c_code(req->async_states->status)); diff --git a/source4/ntvfs/ntvfs.h b/source4/ntvfs/ntvfs.h index 9069e6c2ac..cf541de81e 100644 --- a/source4/ntvfs/ntvfs.h +++ b/source4/ntvfs/ntvfs.h @@ -191,7 +191,7 @@ struct ntvfs_context { struct { void *private_data; - NTSTATUS (*handler)(void *private_data, uint16_t fnum, uint8_t level); + NTSTATUS (*handler)(void *private_data, struct ntvfs_handle *handle, uint8_t level); } oplock; struct { @@ -199,8 +199,16 @@ struct ntvfs_context { struct socket_address *(*get_my_addr)(void *private_data, TALLOC_CTX *mem_ctx); struct socket_address *(*get_peer_addr)(void *private_data, TALLOC_CTX *mem_ctx); } client; -}; + struct { + void *private_data; + NTSTATUS (*create_new)(void *private_data, struct ntvfs_request *req, struct ntvfs_handle **h); + NTSTATUS (*make_valid)(void *private_data, struct ntvfs_handle *h); + void (*destroy)(void *private_data, struct ntvfs_handle *h); + struct ntvfs_handle *(*search_by_wire_key)(void *private_data, struct ntvfs_request *req, const DATA_BLOB *key); + DATA_BLOB (*get_wire_key)(void *private_data, struct ntvfs_handle *handle, TALLOC_CTX *mem_ctx); + } handles; +}; /* a set of flags to control handling of request structures */ #define NTVFS_ASYNC_STATE_ASYNC (1<<1) /* the backend will answer this one later */ @@ -253,6 +261,28 @@ struct ntvfs_request { /* the system time when the request arrived */ struct timeval request_time; } statistics; + + struct { + void *private_data; + } frontend_data; +}; + +struct ntvfs_handle { + struct ntvfs_context *ctx; + + struct auth_session_info *session_info; + + uint16_t smbpid; + + struct ntvfs_handle_data { + struct ntvfs_handle_data *prev, *next; + struct ntvfs_module_context *owner; + void *private_data;/* this must be a valid talloc pointer */ + } *backend_data; + + struct { + void *private_data; + } frontend_data; }; /* this structure is used by backends to determine the size of some critical types */ @@ -264,6 +294,8 @@ struct ntvfs_critical_sizes { int sizeof_ntvfs_ops; int sizeof_ntvfs_async_state; int sizeof_ntvfs_request; + int sizeof_ntvfs_handle; + int sizeof_ntvfs_handle_data; }; #define NTVFS_CURRENT_CRITICAL_SIZES(c) \ @@ -275,6 +307,8 @@ struct ntvfs_critical_sizes { .sizeof_ntvfs_ops = sizeof(struct ntvfs_ops), \ .sizeof_ntvfs_async_state = sizeof(struct ntvfs_async_state), \ .sizeof_ntvfs_request = sizeof(struct ntvfs_request), \ + .sizeof_ntvfs_handle = sizeof(struct ntvfs_handle), \ + .sizeof_ntvfs_handle_data = sizeof(struct ntvfs_handle_data), \ } struct messaging_context; diff --git a/source4/ntvfs/ntvfs_generic.c b/source4/ntvfs/ntvfs_generic.c index b04a3af21e..5058225ceb 100644 --- a/source4/ntvfs/ntvfs_generic.c +++ b/source4/ntvfs/ntvfs_generic.c @@ -153,7 +153,7 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs, switch (io->generic.level) { case RAW_OPEN_OPEN: - io->openold.out.file.fnum = io2->generic.out.file.fnum; + io->openold.out.file.ntvfs = io2->generic.out.file.ntvfs; io->openold.out.attrib = io2->generic.out.attrib; io->openold.out.write_time = nt_time_to_unix(io2->generic.out.write_time); io->openold.out.size = io2->generic.out.size; @@ -161,7 +161,7 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs, break; case RAW_OPEN_OPENX: - io->openx.out.file.fnum = io2->generic.out.file.fnum; + io->openx.out.file.ntvfs = io2->generic.out.file.ntvfs; io->openx.out.attrib = io2->generic.out.attrib; io->openx.out.write_time = nt_time_to_unix(io2->generic.out.write_time); io->openx.out.size = io2->generic.out.size; @@ -181,7 +181,7 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs, break; case RAW_OPEN_T2OPEN: - io->t2open.out.file.fnum = io2->generic.out.file.fnum; + io->t2open.out.file.ntvfs = io2->generic.out.file.ntvfs; io->t2open.out.attrib = io2->generic.out.attrib; io->t2open.out.write_time = nt_time_to_unix(io2->generic.out.write_time); io->t2open.out.size = io2->generic.out.size; @@ -194,12 +194,12 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs, case RAW_OPEN_MKNEW: case RAW_OPEN_CREATE: - io->mknew.out.file.fnum = io2->generic.out.file.fnum; + io->mknew.out.file.ntvfs= io2->generic.out.file.ntvfs; write_time = io->mknew.in.write_time; break; case RAW_OPEN_CTEMP: - io->ctemp.out.file.fnum = io2->generic.out.file.fnum; + io->ctemp.out.file.ntvfs= io2->generic.out.file.ntvfs; io->ctemp.out.name = talloc_strdup(req, io2->generic.in.fname + strlen(io->ctemp.in.directory) + 1); NT_STATUS_HAVE_NO_MEMORY(io->ctemp.out.name); @@ -218,7 +218,7 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs, sf = talloc(req, union smb_setfileinfo); NT_STATUS_HAVE_NO_MEMORY(sf); sf->generic.level = RAW_SFILEINFO_STANDARD; - sf->generic.in.file.fnum = io2->generic.out.file.fnum; + sf->generic.in.file.ntvfs = io2->generic.out.file.ntvfs; sf->standard.in.create_time = 0; sf->standard.in.write_time = write_time; sf->standard.in.access_time = 0; @@ -229,7 +229,7 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs, sf = talloc(req, union smb_setfileinfo); NT_STATUS_HAVE_NO_MEMORY(sf); sf->generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION; - sf->generic.in.file.fnum = io2->generic.out.file.fnum; + sf->generic.in.file.ntvfs = io2->generic.out.file.ntvfs; sf->end_of_file_info.in.size = set_size; status = ntvfs->ops->setfileinfo(ntvfs, req, sf); if (NT_STATUS_IS_OK(status)) { @@ -859,7 +859,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_qfileinfo(struct ntvfs_module_context *ntvfs, /* ask the backend for the generic info */ info2->generic.level = RAW_FILEINFO_GENERIC; - info2->generic.in.file.fnum = info->generic.in.file.fnum; + info2->generic.in.file.ntvfs= info->generic.in.file.ntvfs; /* only used by the simple backend, which doesn't do async */ req->async_states->state &= ~NTVFS_ASYNC_STATE_MAY_ASYNC; @@ -941,7 +941,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_lock(struct ntvfs_module_context *ntvfs, } lck2->generic.level = RAW_LOCK_GENERIC; - lck2->generic.in.file.fnum = lck->lock.in.file.fnum; + lck2->generic.in.file.ntvfs= lck->lock.in.file.ntvfs; lck2->generic.in.mode = 0; lck2->generic.in.timeout = 0; lck2->generic.in.locks = locks; @@ -988,10 +988,10 @@ static NTSTATUS ntvfs_map_write_finish(struct ntvfs_module_context *ntvfs, return NT_STATUS_NO_MEMORY; } - lck->unlock.level = RAW_LOCK_UNLOCK; - lck->unlock.in.file.fnum= wr->writeunlock.in.file.fnum; - lck->unlock.in.count = wr->writeunlock.in.count; - lck->unlock.in.offset = wr->writeunlock.in.offset; + lck->unlock.level = RAW_LOCK_UNLOCK; + lck->unlock.in.file.ntvfs = wr->writeunlock.in.file.ntvfs; + lck->unlock.in.count = wr->writeunlock.in.count; + lck->unlock.in.offset = wr->writeunlock.in.offset; if (lck->unlock.in.count != 0) { /* do the lock sync for now */ @@ -1011,7 +1011,7 @@ static NTSTATUS ntvfs_map_write_finish(struct ntvfs_module_context *ntvfs, } cl->close.level = RAW_CLOSE_CLOSE; - cl->close.in.file.fnum = wr->writeclose.in.file.fnum; + cl->close.in.file.ntvfs = wr->writeclose.in.file.ntvfs; cl->close.in.write_time = wr->writeclose.in.mtime; if (wr2->generic.in.count != 0) { @@ -1062,7 +1062,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_write(struct ntvfs_module_context *ntvfs, break; case RAW_WRITE_WRITE: - wr2->writex.in.file.fnum = wr->write.in.file.fnum; + wr2->writex.in.file.ntvfs= wr->write.in.file.ntvfs; wr2->writex.in.offset = wr->write.in.offset; wr2->writex.in.wmode = 0; wr2->writex.in.remaining = wr->write.in.remaining; @@ -1072,7 +1072,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_write(struct ntvfs_module_context *ntvfs, break; case RAW_WRITE_WRITEUNLOCK: - wr2->writex.in.file.fnum = wr->writeunlock.in.file.fnum; + wr2->writex.in.file.ntvfs= wr->writeunlock.in.file.ntvfs; wr2->writex.in.offset = wr->writeunlock.in.offset; wr2->writex.in.wmode = 0; wr2->writex.in.remaining = wr->writeunlock.in.remaining; @@ -1082,7 +1082,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_write(struct ntvfs_module_context *ntvfs, break; case RAW_WRITE_WRITECLOSE: - wr2->writex.in.file.fnum = wr->writeclose.in.file.fnum; + wr2->writex.in.file.ntvfs= wr->writeclose.in.file.ntvfs; wr2->writex.in.offset = wr->writeclose.in.offset; wr2->writex.in.wmode = 0; wr2->writex.in.remaining = 0; @@ -1092,7 +1092,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_write(struct ntvfs_module_context *ntvfs, break; case RAW_WRITE_SPLWRITE: - wr2->writex.in.file.fnum = wr->splwrite.in.file.fnum; + wr2->writex.in.file.ntvfs= wr->splwrite.in.file.ntvfs; wr2->writex.in.offset = 0; wr2->writex.in.wmode = 0; wr2->writex.in.remaining = 0; @@ -1164,7 +1164,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_read(struct ntvfs_module_context *ntvfs, break; case RAW_READ_READ: - rd2->readx.in.file.fnum = rd->read.in.file.fnum; + rd2->readx.in.file.ntvfs= rd->read.in.file.ntvfs; rd2->readx.in.offset = rd->read.in.offset; rd2->readx.in.mincnt = rd->read.in.count; rd2->readx.in.maxcnt = rd->read.in.count; @@ -1174,7 +1174,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_read(struct ntvfs_module_context *ntvfs, break; case RAW_READ_READBRAW: - rd2->readx.in.file.fnum = rd->readbraw.in.file.fnum; + rd2->readx.in.file.ntvfs= rd->readbraw.in.file.ntvfs; rd2->readx.in.offset = rd->readbraw.in.offset; rd2->readx.in.mincnt = rd->readbraw.in.mincnt; rd2->readx.in.maxcnt = rd->readbraw.in.maxcnt; @@ -1194,13 +1194,13 @@ _PUBLIC_ NTSTATUS ntvfs_map_read(struct ntvfs_module_context *ntvfs, goto done; } lck->lock.level = RAW_LOCK_LOCK; - lck->lock.in.file.fnum = rd->lockread.in.file.fnum; + lck->lock.in.file.ntvfs = rd->lockread.in.file.ntvfs; lck->lock.in.count = rd->lockread.in.count; lck->lock.in.offset = rd->lockread.in.offset; status = ntvfs->ops->lock(ntvfs, req, lck); req->async_states->state = state; - rd2->readx.in.file.fnum = rd->lockread.in.file.fnum; + rd2->readx.in.file.ntvfs= rd->lockread.in.file.ntvfs; rd2->readx.in.offset = rd->lockread.in.offset; rd2->readx.in.mincnt = rd->lockread.in.count; rd2->readx.in.maxcnt = rd->lockread.in.count; @@ -1238,7 +1238,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_close(struct ntvfs_module_context *ntvfs, case RAW_CLOSE_SPLCLOSE: cl2->close.level = RAW_CLOSE_CLOSE; - cl2->close.in.file.fnum = cl->splclose.in.file.fnum; + cl2->close.in.file.ntvfs= cl->splclose.in.file.ntvfs; break; } diff --git a/source4/ntvfs/ntvfs_interface.c b/source4/ntvfs/ntvfs_interface.c index c26832d96e..67cbe8df22 100644 --- a/source4/ntvfs/ntvfs_interface.c +++ b/source4/ntvfs/ntvfs_interface.c @@ -668,7 +668,7 @@ _PUBLIC_ NTSTATUS ntvfs_next_exit(struct ntvfs_module_context *ntvfs, /* oplock helpers */ _PUBLIC_ NTSTATUS ntvfs_set_oplock_handler(struct ntvfs_context *ntvfs, - NTSTATUS (*handler)(void *private_data, uint16_t fnum, uint8_t level), + NTSTATUS (*handler)(void *private_data, struct ntvfs_handle *handle, uint8_t level), void *private_data) { ntvfs->oplock.handler = handler; @@ -677,13 +677,13 @@ _PUBLIC_ NTSTATUS ntvfs_set_oplock_handler(struct ntvfs_context *ntvfs, } _PUBLIC_ NTSTATUS ntvfs_send_oplock_break(struct ntvfs_module_context *ntvfs, - uint16_t fnum, uint8_t level) + struct ntvfs_handle *handle, uint8_t level) { if (!ntvfs->ctx->oplock.handler) { return NT_STATUS_OK; } - return ntvfs->ctx->oplock.handler(ntvfs->ctx->oplock.private_data, fnum, level); + return ntvfs->ctx->oplock.handler(ntvfs->ctx->oplock.private_data, handle, level); } /* client connection callback */ diff --git a/source4/ntvfs/ntvfs_util.c b/source4/ntvfs/ntvfs_util.c index 52f03430ce..de19a9c352 100644 --- a/source4/ntvfs/ntvfs_util.c +++ b/source4/ntvfs/ntvfs_util.c @@ -98,3 +98,100 @@ _PUBLIC_ void ntvfs_async_state_pop(struct ntvfs_request *req) talloc_free(async); } + +_PUBLIC_ NTSTATUS ntvfs_handle_new(struct ntvfs_module_context *ntvfs, + struct ntvfs_request *req, + struct ntvfs_handle **h) +{ + return ntvfs->ctx->handles.create_new(ntvfs->ctx->handles.private_data, req, h); +} + +_PUBLIC_ NTSTATUS ntvfs_handle_set_backend_data(struct ntvfs_handle *h, + struct ntvfs_module_context *ntvfs, + TALLOC_CTX *private_data) +{ + struct ntvfs_handle_data *d; + BOOL first_time = h->backend_data?False:True; + + for (d=h->backend_data; d; d = d->next) { + if (d->owner != ntvfs) continue; + d->private_data = talloc_steal(d, private_data); + return NT_STATUS_OK; + } + + d = talloc(h, struct ntvfs_handle_data); + NT_STATUS_HAVE_NO_MEMORY(d); + d->owner = ntvfs; + d->private_data = talloc_steal(d, private_data); + + DLIST_ADD(h->backend_data, d); + + if (first_time) { + NTSTATUS status; + status = h->ctx->handles.make_valid(h->ctx->handles.private_data, h); + NT_STATUS_NOT_OK_RETURN(status); + } + + return NT_STATUS_OK; +} + +_PUBLIC_ void *ntvfs_handle_get_backend_data(struct ntvfs_handle *h, + struct ntvfs_module_context *ntvfs) +{ + struct ntvfs_handle_data *d; + + for (d=h->backend_data; d; d = d->next) { + if (d->owner != ntvfs) continue; + return d->private_data; + } + + return NULL; +} + +_PUBLIC_ void ntvfs_handle_remove_backend_data(struct ntvfs_handle *h, + struct ntvfs_module_context *ntvfs) +{ + struct ntvfs_handle_data *d,*n; + + for (d=h->backend_data; d; d = n) { + n = d->next; + if (d->owner != ntvfs) continue; + DLIST_REMOVE(h->backend_data, d); + talloc_free(d); + d = NULL; + } + + if (h->backend_data) return; + + /* if there's no backend_data anymore, destroy the handle */ + h->ctx->handles.destroy(h->ctx->handles.private_data, h); +} + +_PUBLIC_ struct ntvfs_handle *ntvfs_handle_search_by_wire_key(struct ntvfs_module_context *ntvfs, + struct ntvfs_request *req, + const DATA_BLOB *key) +{ + return ntvfs->ctx->handles.search_by_wire_key(ntvfs->ctx->handles.private_data, req, key); +} + +_PUBLIC_ DATA_BLOB ntvfs_handle_get_wire_key(struct ntvfs_handle *h, TALLOC_CTX *mem_ctx) +{ + return h->ctx->handles.get_wire_key(h->ctx->handles.private_data, h, mem_ctx); +} + +_PUBLIC_ NTSTATUS ntvfs_set_handle_callbacks(struct ntvfs_context *ntvfs, + NTSTATUS (*create_new)(void *private_data, struct ntvfs_request *req, struct ntvfs_handle **h), + NTSTATUS (*make_valid)(void *private_data, struct ntvfs_handle *h), + void (*destroy)(void *private_data, struct ntvfs_handle *h), + struct ntvfs_handle *(*search_by_wire_key)(void *private_data, struct ntvfs_request *req, const DATA_BLOB *key), + DATA_BLOB (*get_wire_key)(void *private_data, struct ntvfs_handle *handle, TALLOC_CTX *mem_ctx), + void *private_data) +{ + ntvfs->handles.create_new = create_new; + ntvfs->handles.make_valid = make_valid; + ntvfs->handles.destroy = destroy; + ntvfs->handles.search_by_wire_key = search_by_wire_key; + ntvfs->handles.get_wire_key = get_wire_key; + ntvfs->handles.private_data = private_data; + return NT_STATUS_OK; +} diff --git a/source4/ntvfs/posix/pvfs_flush.c b/source4/ntvfs/posix/pvfs_flush.c index c1d8820c43..7bd973ed4e 100644 --- a/source4/ntvfs/posix/pvfs_flush.c +++ b/source4/ntvfs/posix/pvfs_flush.c @@ -48,7 +48,7 @@ NTSTATUS pvfs_flush(struct ntvfs_module_context *ntvfs, switch (io->generic.level) { case RAW_FLUSH_FLUSH: - f = pvfs_find_fd(pvfs, req, io->flush.in.file.fnum); + f = pvfs_find_fd(pvfs, req, io->flush.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/posix/pvfs_ioctl.c b/source4/ntvfs/posix/pvfs_ioctl.c index 829da47a12..417458edf0 100644 --- a/source4/ntvfs/posix/pvfs_ioctl.c +++ b/source4/ntvfs/posix/pvfs_ioctl.c @@ -42,7 +42,7 @@ static NTSTATUS pvfs_ntioctl(struct ntvfs_module_context *ntvfs, struct pvfs_state *pvfs = ntvfs->private_data; struct pvfs_file *f; - f = pvfs_find_fd(pvfs, req, io->ntioctl.in.file.fnum); + f = pvfs_find_fd(pvfs, req, io->ntioctl.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/posix/pvfs_lock.c b/source4/ntvfs/posix/pvfs_lock.c index 99b694665d..8dcee5f983 100644 --- a/source4/ntvfs/posix/pvfs_lock.c +++ b/source4/ntvfs/posix/pvfs_lock.c @@ -244,7 +244,7 @@ static NTSTATUS pvfs_lock_cancel(struct pvfs_state *pvfs, struct ntvfs_request * /* check if the lock request matches exactly - you can only cancel with exact matches */ if (p->lck->lockx.in.ulock_cnt == lck->lockx.in.ulock_cnt && p->lck->lockx.in.lock_cnt == lck->lockx.in.lock_cnt && - p->lck->lockx.in.file.fnum == lck->lockx.in.file.fnum && + p->lck->lockx.in.file.ntvfs== lck->lockx.in.file.ntvfs && p->lck->lockx.in.mode == (lck->lockx.in.mode & ~LOCKING_ANDX_CANCEL_LOCK)) { int i; @@ -286,7 +286,7 @@ NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs, return ntvfs_map_lock(ntvfs, req, lck); } - f = pvfs_find_fd(pvfs, req, lck->lockx.in.file.fnum); + f = pvfs_find_fd(pvfs, req, lck->lockx.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/posix/pvfs_notify.c b/source4/ntvfs/posix/pvfs_notify.c index ea4c0b2bc6..dfe1737060 100644 --- a/source4/ntvfs/posix/pvfs_notify.c +++ b/source4/ntvfs/posix/pvfs_notify.c @@ -203,7 +203,7 @@ NTSTATUS pvfs_notify(struct ntvfs_module_context *ntvfs, NTSTATUS status; struct notify_pending *pending; - f = pvfs_find_fd(pvfs, req, info->in.file.fnum); + f = pvfs_find_fd(pvfs, req, info->in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 3bbf840154..fd382ba1d9 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -29,39 +29,28 @@ #include "librpc/gen_ndr/xattr.h" /* - create file handles with convenient numbers for sniffers -*/ -#define PVFS_MIN_FILE_FNUM 0x100 -#define PVFS_MIN_NEW_FNUM 0x200 -#define PVFS_MIN_DIR_FNUM 0x300 - -/* find open file handle given fnum */ struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs, - struct ntvfs_request *req, uint16_t fnum) + struct ntvfs_request *req, struct ntvfs_handle *h) { + void *p; struct pvfs_file *f; - f = idr_find(pvfs->files.idtree, fnum); - if (f == NULL) { - return NULL; - } + p = ntvfs_handle_get_backend_data(h, pvfs->ntvfs); + if (!p) return NULL; - if (f->fnum != fnum) { - smb_panic("pvfs_find_fd: idtree_fnum corruption\n"); - } + f = talloc_get_type(p, struct pvfs_file); + if (!f) return NULL; if (req->session_info != f->session_info) { - DEBUG(2,("pvfs_find_fd: attempt to use wrong session for fnum %d\n", - fnum)); + DEBUG(2,("pvfs_find_fd: attempt to use wrong session for handle %p\n",h)); return NULL; } return f; } - /* cleanup a open directory handle */ @@ -114,8 +103,10 @@ static int pvfs_dir_handle_destructor(void *p) static int pvfs_dir_fnum_destructor(void *p) { struct pvfs_file *f = p; + DLIST_REMOVE(f->pvfs->files.list, f); - idr_remove(f->pvfs->files.idtree, f->fnum); + ntvfs_handle_remove_backend_data(f->ntvfs, f->pvfs->ntvfs); + return 0; } @@ -125,7 +116,7 @@ static int pvfs_dir_fnum_destructor(void *p) static NTSTATUS pvfs_open_setup_eas_acl(struct pvfs_state *pvfs, struct ntvfs_request *req, struct pvfs_filename *name, - int fd, int fnum, + int fd, struct pvfs_file *f, union smb_open *io) { NTSTATUS status; @@ -150,7 +141,7 @@ static NTSTATUS pvfs_open_setup_eas_acl(struct pvfs_state *pvfs, * but the user doesn't have SeSecurityPrivilege * - w2k3 allows it */ - set.set_secdesc.in.file.fnum = fnum; + set.set_secdesc.in.file.ntvfs = f->ntvfs; set.set_secdesc.in.secinfo_flags = SECINFO_DACL; set.set_secdesc.in.sd = io->ntcreatex.in.sec_desc; @@ -197,7 +188,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, union smb_open *io) { struct pvfs_file *f; - int fnum; + struct ntvfs_handle *h; NTSTATUS status; uint32_t create_action; uint32_t access_mask = io->generic.in.access_mask; @@ -242,7 +233,10 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_INVALID_PARAMETER; } - f = talloc(req, struct pvfs_file); + status = ntvfs_handle_new(pvfs->ntvfs, req, &h); + NT_STATUS_NOT_OK_RETURN(status); + + f = talloc(h, struct pvfs_file); if (f == NULL) { return NT_STATUS_NO_MEMORY; } @@ -252,11 +246,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_NO_MEMORY; } - fnum = idr_get_new_above(pvfs->files.idtree, f, PVFS_MIN_DIR_FNUM, UINT16_MAX); - if (fnum == -1) { - return NT_STATUS_TOO_MANY_OPENED_FILES; - } - if (name->exists) { /* check the security descriptor */ status = pvfs_access_check(pvfs, req, name, &access_mask); @@ -264,11 +253,10 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, status = pvfs_access_check_create(pvfs, req, name, &access_mask); } if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->files.idtree, fnum); return status; } - f->fnum = fnum; + f->ntvfs = h; f->session_info = req->session_info; f->smbpid = req->smbpid; f->pvfs = pvfs; @@ -297,12 +285,10 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, del_on_close = False; } - if (name->exists) { /* form the lock context used for opendb locking */ status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->files.idtree, f->fnum); return status; } @@ -313,7 +299,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, name->full_name)); /* we were supposed to do a blocking lock, so something is badly wrong! */ - idr_remove(pvfs->files.idtree, fnum); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -323,7 +308,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, name->full_name, OPLOCK_NONE, NULL); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->files.idtree, f->fnum); talloc_free(lck); return status; } @@ -342,7 +326,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, mode_t mode = pvfs_fileperms(pvfs, attrib); if (mkdir(name->full_name, mode) == -1) { - idr_remove(pvfs->files.idtree, fnum); return pvfs_map_errno(pvfs,errno); } @@ -353,7 +336,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, goto cleanup_delete; } - status = pvfs_open_setup_eas_acl(pvfs, req, name, -1, fnum, io); + status = pvfs_open_setup_eas_acl(pvfs, req, name, -1, f, io); if (!NT_STATUS_IS_OK(status)) { goto cleanup_delete; } @@ -361,7 +344,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, /* form the lock context used for opendb locking */ status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->files.idtree, f->fnum); return status; } @@ -371,7 +353,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, name->full_name)); /* we were supposed to do a blocking lock, so something is badly wrong! */ - idr_remove(pvfs->files.idtree, fnum); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -396,15 +377,17 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, } if (!name->exists) { - idr_remove(pvfs->files.idtree, fnum); return NT_STATUS_OBJECT_NAME_NOT_FOUND; } /* the open succeeded, keep this handle permanently */ - talloc_steal(pvfs, f); + status = ntvfs_handle_set_backend_data(h, pvfs->ntvfs, f); + if (!NT_STATUS_IS_OK(status)) { + goto cleanup_delete; + } io->generic.out.oplock_level = OPLOCK_NONE; - io->generic.out.file.fnum = f->fnum; + io->generic.out.file.ntvfs = h; io->generic.out.create_action = create_action; io->generic.out.create_time = name->dos.create_time; io->generic.out.access_time = name->dos.access_time; @@ -420,7 +403,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_OK; cleanup_delete: - idr_remove(pvfs->files.idtree, fnum); rmdir(name->full_name); return status; } @@ -510,11 +492,11 @@ static int pvfs_handle_destructor(void *p) */ static int pvfs_fnum_destructor(void *p) { - struct pvfs_file *f = p; + struct pvfs_file *f = talloc_get_type(p, struct pvfs_file); DLIST_REMOVE(f->pvfs->files.list, f); pvfs_lock_close(f->pvfs, f); - idr_remove(f->pvfs->files.idtree, f->fnum); + ntvfs_handle_remove_backend_data(f->ntvfs, f->pvfs->ntvfs); return 0; } @@ -527,8 +509,8 @@ static int pvfs_fnum_destructor(void *p) locking space) */ static NTSTATUS pvfs_brl_locking_handle(TALLOC_CTX *mem_ctx, - struct pvfs_filename *name, - uint16_t fnum, + struct pvfs_filename *name, + struct ntvfs_handle *ntvfs, struct brl_handle **_h) { DATA_BLOB odb_key, key; @@ -550,7 +532,7 @@ static NTSTATUS pvfs_brl_locking_handle(TALLOC_CTX *mem_ctx, data_blob_free(&odb_key); } - h = brl_create_handle(mem_ctx, &key, fnum); + h = brl_create_handle(mem_ctx, ntvfs, &key); NT_STATUS_HAVE_NO_MEMORY(h); *_h = h; @@ -567,7 +549,8 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, { struct pvfs_file *f; NTSTATUS status; - int flags, fnum, fd; + struct ntvfs_handle *h; + int flags, fd; struct odb_lock *lck; uint32_t create_options = io->generic.in.create_options; uint32_t share_access = io->generic.in.share_access; @@ -606,20 +589,14 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, flags = O_RDONLY; } - f = talloc(req, struct pvfs_file); - if (f == NULL) { - return NT_STATUS_NO_MEMORY; - } + status = ntvfs_handle_new(pvfs->ntvfs, req, &h); + NT_STATUS_NOT_OK_RETURN(status); - f->handle = talloc(f, struct pvfs_file_handle); - if (f->handle == NULL) { - return NT_STATUS_NO_MEMORY; - } + f = talloc(h, struct pvfs_file); + NT_STATUS_HAVE_NO_MEMORY(f); - fnum = idr_get_new_above(pvfs->files.idtree, f, PVFS_MIN_NEW_FNUM, UINT16_MAX); - if (fnum == -1) { - return NT_STATUS_TOO_MANY_OPENED_FILES; - } + f->handle = talloc(f, struct pvfs_file_handle); + NT_STATUS_HAVE_NO_MEMORY(f->handle); attrib = io->ntcreatex.in.file_attr | FILE_ATTRIBUTE_ARCHIVE; mode = pvfs_fileperms(pvfs, attrib); @@ -627,7 +604,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, /* create the file */ fd = open(name->full_name, flags | O_CREAT | O_EXCL, mode); if (fd == -1) { - idr_remove(pvfs->files.idtree, fnum); return pvfs_map_errno(pvfs, errno); } @@ -637,7 +613,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, if (name->stream_name) { status = pvfs_stream_create(pvfs, name, fd); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->files.idtree, fnum); close(fd); return status; } @@ -646,7 +621,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, /* re-resolve the open fd */ status = pvfs_resolve_name_fd(pvfs, fd, name); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->files.idtree, fnum); close(fd); return status; } @@ -658,7 +632,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, } - status = pvfs_open_setup_eas_acl(pvfs, req, name, fd, fnum, io); + status = pvfs_open_setup_eas_acl(pvfs, req, name, fd, f, io); if (!NT_STATUS_IS_OK(status)) { goto cleanup_delete; } @@ -670,7 +644,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, goto cleanup_delete; } - status = pvfs_brl_locking_handle(f, name, fnum, &f->brl_handle); + status = pvfs_brl_locking_handle(f, name, h, &f->brl_handle); if (!NT_STATUS_IS_OK(status)) { goto cleanup_delete; } @@ -708,7 +682,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, /* bad news, we must have hit a race - we don't delete the file here as the most likely scenario is that someone else created the file at the same time */ - idr_remove(pvfs->files.idtree, fnum); close(fd); return status; } @@ -717,7 +690,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, oplock_granted = OPLOCK_BATCH; } - f->fnum = fnum; + f->ntvfs = h; f->session_info = req->session_info; f->smbpid = req->smbpid; f->pvfs = pvfs; @@ -746,7 +719,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, talloc_set_destructor(f->handle, pvfs_handle_destructor); io->generic.out.oplock_level = oplock_granted; - io->generic.out.file.fnum = f->fnum; + io->generic.out.file.ntvfs = f->ntvfs; io->generic.out.create_action = NTCREATEX_ACTION_CREATED; io->generic.out.create_time = name->dos.create_time; io->generic.out.access_time = name->dos.access_time; @@ -760,7 +733,10 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, io->generic.out.is_directory = 0; /* success - keep the file handle */ - talloc_steal(pvfs, f); + status = ntvfs_handle_set_backend_data(h, pvfs->ntvfs, f); + if (!NT_STATUS_IS_OK(status)) { + goto cleanup_delete; + } notify_trigger(pvfs->notify_context, NOTIFY_ACTION_ADDED, @@ -770,7 +746,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return NT_STATUS_OK; cleanup_delete: - idr_remove(pvfs->files.idtree, fnum); close(fd); unlink(name->full_name); return status; @@ -873,6 +848,7 @@ static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs, struct pvfs_state *pvfs = ntvfs->private_data; struct pvfs_file *f2; struct pvfs_filename *name; + NTSTATUS status; /* search for an existing open with the right parameters. Note the magic ntcreatex options flag, which is set in the @@ -919,7 +895,7 @@ static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs, name = f->handle->name; io->generic.out.oplock_level = OPLOCK_NONE; - io->generic.out.file.fnum = f->fnum; + io->generic.out.file.ntvfs = f->ntvfs; io->generic.out.create_action = NTCREATEX_ACTION_EXISTED; io->generic.out.create_time = name->dos.create_time; io->generic.out.access_time = name->dos.access_time; @@ -931,8 +907,9 @@ static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs, io->generic.out.file_type = FILE_TYPE_DISK; io->generic.out.ipc_state = 0; io->generic.out.is_directory = 0; - - talloc_steal(f->pvfs, f); + + status = ntvfs_handle_set_backend_data(f->ntvfs, ntvfs, f); + NT_STATUS_NOT_OK_RETURN(status); return NT_STATUS_OK; } @@ -1009,8 +986,9 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, int flags; struct pvfs_filename *name; struct pvfs_file *f; + struct ntvfs_handle *h; NTSTATUS status; - int fnum, fd; + int fd; struct odb_lock *lck; uint32_t create_options; uint32_t share_access; @@ -1128,7 +1106,10 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return status; } - f = talloc(req, struct pvfs_file); + status = ntvfs_handle_new(pvfs->ntvfs, req, &h); + NT_STATUS_NOT_OK_RETURN(status); + + f = talloc(h, struct pvfs_file); if (f == NULL) { return NT_STATUS_NO_MEMORY; } @@ -1138,13 +1119,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_NO_MEMORY; } - /* allocate a fnum */ - fnum = idr_get_new_above(pvfs->files.idtree, f, PVFS_MIN_FILE_FNUM, UINT16_MAX); - if (fnum == -1) { - return NT_STATUS_TOO_MANY_OPENED_FILES; - } - - f->fnum = fnum; + f->ntvfs = h; f->session_info = req->session_info; f->smbpid = req->smbpid; f->pvfs = pvfs; @@ -1169,13 +1144,11 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, opendb locking */ status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->files.idtree, f->fnum); return status; } - status = pvfs_brl_locking_handle(f, name, f->fnum, &f->brl_handle); + status = pvfs_brl_locking_handle(f, name, h, &f->brl_handle); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->files.idtree, f->fnum); return status; } @@ -1186,7 +1159,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, name->full_name)); /* we were supposed to do a blocking lock, so something is badly wrong! */ - idr_remove(pvfs->files.idtree, fnum); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -1288,8 +1260,11 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, talloc_free(lck); + status = ntvfs_handle_set_backend_data(h, ntvfs, f); + NT_STATUS_NOT_OK_RETURN(status); + io->generic.out.oplock_level = oplock_granted; - io->generic.out.file.fnum = f->fnum; + io->generic.out.file.ntvfs = h; io->generic.out.create_action = stream_existed? NTCREATEX_ACTION_EXISTED:NTCREATEX_ACTION_CREATED; io->generic.out.create_time = name->dos.create_time; @@ -1303,9 +1278,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, io->generic.out.ipc_state = 0; io->generic.out.is_directory = 0; - /* success - keep the file handle */ - talloc_steal(f->pvfs, f); - return NT_STATUS_OK; } @@ -1328,7 +1300,7 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, return ntvfs_map_close(ntvfs, req, io); } - f = pvfs_find_fd(pvfs, req, io->close.in.file.fnum); + f = pvfs_find_fd(pvfs, req, io->close.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/posix/pvfs_qfileinfo.c b/source4/ntvfs/posix/pvfs_qfileinfo.c index e4e69a8289..2d43c5a582 100644 --- a/source4/ntvfs/posix/pvfs_qfileinfo.c +++ b/source4/ntvfs/posix/pvfs_qfileinfo.c @@ -336,7 +336,7 @@ NTSTATUS pvfs_qfileinfo(struct ntvfs_module_context *ntvfs, NTSTATUS status; uint32_t access_needed; - f = pvfs_find_fd(pvfs, req, info->generic.in.file.fnum); + f = pvfs_find_fd(pvfs, req, info->generic.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/posix/pvfs_read.c b/source4/ntvfs/posix/pvfs_read.c index 411fbd9c27..13e8264000 100644 --- a/source4/ntvfs/posix/pvfs_read.c +++ b/source4/ntvfs/posix/pvfs_read.c @@ -41,7 +41,7 @@ NTSTATUS pvfs_read(struct ntvfs_module_context *ntvfs, return ntvfs_map_read(ntvfs, req, rd); } - f = pvfs_find_fd(pvfs, req, rd->readx.in.file.fnum); + f = pvfs_find_fd(pvfs, req, rd->readx.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/posix/pvfs_seek.c b/source4/ntvfs/posix/pvfs_seek.c index dbfb4e1c3d..7365f33b15 100644 --- a/source4/ntvfs/posix/pvfs_seek.c +++ b/source4/ntvfs/posix/pvfs_seek.c @@ -35,7 +35,7 @@ NTSTATUS pvfs_seek(struct ntvfs_module_context *ntvfs, struct pvfs_file_handle *h; NTSTATUS status; - f = pvfs_find_fd(pvfs, req, io->lseek.in.file.fnum); + f = pvfs_find_fd(pvfs, req, io->lseek.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c index e85f52fc2c..2665b9e5f5 100644 --- a/source4/ntvfs/posix/pvfs_setfileinfo.c +++ b/source4/ntvfs/posix/pvfs_setfileinfo.c @@ -262,7 +262,7 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs, uint32_t access_needed; uint32_t change_mask = 0; - f = pvfs_find_fd(pvfs, req, info->generic.in.file.fnum); + f = pvfs_find_fd(pvfs, req, info->generic.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/posix/pvfs_write.c b/source4/ntvfs/posix/pvfs_write.c index 1da1985550..9f58281919 100644 --- a/source4/ntvfs/posix/pvfs_write.c +++ b/source4/ntvfs/posix/pvfs_write.c @@ -40,7 +40,7 @@ NTSTATUS pvfs_write(struct ntvfs_module_context *ntvfs, return ntvfs_map_write(ntvfs, req, wr); } - f = pvfs_find_fd(pvfs, req, wr->writex.in.file.fnum); + f = pvfs_find_fd(pvfs, req, wr->writex.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/posix/vfs_posix.c b/source4/ntvfs/posix/vfs_posix.c index eeee00313b..1682a94ac9 100644 --- a/source4/ntvfs/posix/vfs_posix.c +++ b/source4/ntvfs/posix/vfs_posix.c @@ -194,10 +194,6 @@ static NTSTATUS pvfs_connect(struct ntvfs_module_context *ntvfs, return NT_STATUS_INTERNAL_DB_CORRUPTION; } - /* allocate the fnum id -> ptr tree */ - pvfs->files.idtree = idr_init(pvfs); - NT_STATUS_HAVE_NO_MEMORY(pvfs->files.idtree); - /* allocate the search handle -> ptr tree */ pvfs->search.idtree = idr_init(pvfs); NT_STATUS_HAVE_NO_MEMORY(pvfs->search.idtree); diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h index 39481c03b1..63ee3395f8 100644 --- a/source4/ntvfs/posix/vfs_posix.h +++ b/source4/ntvfs/posix/vfs_posix.h @@ -63,9 +63,6 @@ struct pvfs_state { uint32_t alloc_size_rounding; struct { - /* an id tree mapping open file handle -> struct pvfs_file */ - struct idr_context *idtree; - /* the open files as DLINKLIST */ struct pvfs_file *list; } files; @@ -156,7 +153,7 @@ struct pvfs_file_handle { struct pvfs_file { struct pvfs_file *next, *prev; struct pvfs_file_handle *handle; - uint16_t fnum; + struct ntvfs_handle *ntvfs; struct pvfs_state *pvfs; diff --git a/source4/ntvfs/simple/svfs.h b/source4/ntvfs/simple/svfs.h index 74e7b6c452..e5ad3b95d9 100644 --- a/source4/ntvfs/simple/svfs.h +++ b/source4/ntvfs/simple/svfs.h @@ -1,5 +1,7 @@ struct svfs_private { + struct ntvfs_module_context *ntvfs; + /* the base directory */ char *connectpath; @@ -24,6 +26,7 @@ struct svfs_dir { struct svfs_file { struct svfs_file *next, *prev; int fd; + struct ntvfs_handle *handle; char *name; }; diff --git a/source4/ntvfs/simple/vfs_simple.c b/source4/ntvfs/simple/vfs_simple.c index 1698f57aee..e0f0083630 100644 --- a/source4/ntvfs/simple/vfs_simple.c +++ b/source4/ntvfs/simple/vfs_simple.c @@ -55,7 +55,8 @@ static NTSTATUS svfs_connect(struct ntvfs_module_context *ntvfs, int snum = ntvfs->ctx->config.snum; private = talloc(ntvfs, struct svfs_private); - + NT_STATUS_HAVE_NO_MEMORY(private); + private->ntvfs = ntvfs; private->next_search_handle = 0; private->connectpath = talloc_strdup(private, lp_pathname(snum)); private->open_files = NULL; @@ -91,15 +92,18 @@ static NTSTATUS svfs_disconnect(struct ntvfs_module_context *ntvfs) /* find open file handle given fd */ -static struct svfs_file *find_fd(struct svfs_private *private, int fd) +static struct svfs_file *find_fd(struct svfs_private *private, struct ntvfs_handle *handle) { struct svfs_file *f; - for (f=private->open_files;f;f=f->next) { - if (f->fd == fd) { - return f; - } - } - return NULL; + void *p; + + p = ntvfs_handle_get_backend_data(handle, private->ntvfs); + if (!p) return NULL; + + f = talloc_get_type(p, struct svfs_file); + if (!f) return NULL; + + return f; } /* @@ -282,12 +286,12 @@ static NTSTATUS svfs_qfileinfo(struct ntvfs_module_context *ntvfs, return ntvfs_map_qfileinfo(ntvfs, req, info); } - f = find_fd(private, info->generic.in.file.fnum); + f = find_fd(private, info->generic.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } - if (fstat(info->generic.in.file.fnum, &st) == -1) { + if (fstat(f->fd, &st) == -1) { return map_nt_error_from_unix(errno); } @@ -308,6 +312,8 @@ static NTSTATUS svfs_open(struct ntvfs_module_context *ntvfs, struct svfs_file *f; int create_flags, rdwr_flags; BOOL readonly; + NTSTATUS status; + struct ntvfs_handle *handle; if (io->generic.level != RAW_OPEN_GENERIC) { return ntvfs_map_open(ntvfs, req, io); @@ -379,7 +385,10 @@ do_open: return map_nt_error_from_unix(errno); } - f = talloc(ntvfs, struct svfs_file); + status = ntvfs_handle_new(ntvfs, req, &handle); + NT_STATUS_NOT_OK_RETURN(status); + + f = talloc(handle, struct svfs_file); NT_STATUS_HAVE_NO_MEMORY(f); f->fd = fd; f->name = talloc_strdup(f, unix_path); @@ -387,13 +396,16 @@ do_open: DLIST_ADD(private->open_files, f); + status = ntvfs_handle_set_backend_data(handle, ntvfs, f); + NT_STATUS_NOT_OK_RETURN(status); + ZERO_STRUCT(io->generic.out); unix_to_nt_time(&io->generic.out.create_time, st.st_ctime); unix_to_nt_time(&io->generic.out.access_time, st.st_atime); unix_to_nt_time(&io->generic.out.write_time, st.st_mtime); unix_to_nt_time(&io->generic.out.change_time, st.st_mtime); - io->generic.out.file.fnum = fd; + io->generic.out.file.ntvfs = handle; io->generic.out.alloc_size = st.st_size; io->generic.out.size = st.st_size; io->generic.out.attrib = svfs_unix_to_dos_attrib(st.st_mode); @@ -483,13 +495,20 @@ static NTSTATUS svfs_copy(struct ntvfs_module_context *ntvfs, static NTSTATUS svfs_read(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, union smb_read *rd) { + struct svfs_private *private = ntvfs->private_data; + struct svfs_file *f; ssize_t ret; if (rd->generic.level != RAW_READ_READX) { return NT_STATUS_NOT_SUPPORTED; } - ret = pread(rd->readx.in.file.fnum, + f = find_fd(private, rd->readx.in.file.ntvfs); + if (!f) { + return NT_STATUS_INVALID_HANDLE; + } + + ret = pread(f->fd, rd->readx.out.data, rd->readx.in.maxcnt, rd->readx.in.offset); @@ -510,6 +529,8 @@ static NTSTATUS svfs_read(struct ntvfs_module_context *ntvfs, static NTSTATUS svfs_write(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, union smb_write *wr) { + struct svfs_private *private = ntvfs->private_data; + struct svfs_file *f; ssize_t ret; if (wr->generic.level != RAW_WRITE_WRITEX) { @@ -518,7 +539,12 @@ static NTSTATUS svfs_write(struct ntvfs_module_context *ntvfs, CHECK_READ_ONLY(req); - ret = pwrite(wr->writex.in.file.fnum, + f = find_fd(private, wr->writex.in.file.ntvfs); + if (!f) { + return NT_STATUS_INVALID_HANDLE; + } + + ret = pwrite(f->fd, wr->writex.in.data, wr->writex.in.count, wr->writex.in.offset); @@ -554,7 +580,11 @@ static NTSTATUS svfs_flush(struct ntvfs_module_context *ntvfs, switch (io->generic.level) { case RAW_FLUSH_FLUSH: - fsync(io->flush.in.file.fnum); + f = find_fd(private, io->flush.in.file.ntvfs); + if (!f) { + return NT_STATUS_INVALID_HANDLE; + } + fsync(f->fd); return NT_STATUS_OK; case RAW_FLUSH_ALL: @@ -582,12 +612,12 @@ static NTSTATUS svfs_close(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_LEVEL; } - f = find_fd(private, io->close.in.file.fnum); + f = find_fd(private, io->close.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } - if (close(io->close.in.file.fnum) == -1) { + if (close(f->fd) == -1) { return map_nt_error_from_unix(errno); } @@ -662,15 +692,21 @@ static NTSTATUS svfs_setfileinfo(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, union smb_setfileinfo *info) { + struct svfs_private *private = ntvfs->private_data; + struct svfs_file *f; struct utimbuf unix_times; - int fd; CHECK_READ_ONLY(req); - + + f = find_fd(private, info->generic.in.file.ntvfs); + if (!f) { + return NT_STATUS_INVALID_HANDLE; + } + switch (info->generic.level) { case RAW_SFILEINFO_END_OF_FILE_INFO: case RAW_SFILEINFO_END_OF_FILE_INFORMATION: - if (ftruncate(info->end_of_file_info.in.file.fnum, + if (ftruncate(f->fd, info->end_of_file_info.in.size) == -1) { return map_nt_error_from_unix(errno); } @@ -678,8 +714,7 @@ static NTSTATUS svfs_setfileinfo(struct ntvfs_module_context *ntvfs, case RAW_SFILEINFO_SETATTRE: unix_times.actime = info->setattre.in.access_time; unix_times.modtime = info->setattre.in.write_time; - fd = info->setattre.in.file.fnum; - + if (unix_times.actime == 0 && unix_times.modtime == 0) { break; } @@ -690,7 +725,7 @@ static NTSTATUS svfs_setfileinfo(struct ntvfs_module_context *ntvfs, } /* Set the date on this file */ - if (svfs_file_utime(fd, &unix_times) != 0) { + if (svfs_file_utime(f->fd, &unix_times) != 0) { return NT_STATUS_ACCESS_DENIED; } break; diff --git a/source4/smb_server/config.mk b/source4/smb_server/config.mk index 6130d7ce9f..abcade4999 100644 --- a/source4/smb_server/config.mk +++ b/source4/smb_server/config.mk @@ -11,6 +11,7 @@ PRIVATE_DEPENDENCIES = SMB_SERVER # Start SUBSYSTEM SMB [SUBSYSTEM::SMB_SERVER] OBJ_FILES = \ + handle.o \ tcon.o \ session.o \ management.o diff --git a/source4/smb_server/handle.c b/source4/smb_server/handle.c new file mode 100644 index 0000000000..c2fea9e91c --- /dev/null +++ b/source4/smb_server/handle.c @@ -0,0 +1,137 @@ +/* + Unix SMB/CIFS implementation. + Manage smbsrv_handle structures + Copyright (C) Stefan Metzmacher 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "dlinklist.h" +#include "smb_server/smb_server.h" +#include "ntvfs/ntvfs.h" + + +/**************************************************************************** +init the handle structures +****************************************************************************/ +NTSTATUS smbsrv_init_handles(struct smbsrv_tcon *tcon, uint64_t limit) +{ + /* + * the idr_* functions take 'int' as limit, + * and only work with a max limit 0x00FFFFFF + */ + limit &= 0x00FFFFFF; + + tcon->handles.idtree_hid = idr_init(tcon); + NT_STATUS_HAVE_NO_MEMORY(tcon->handles.idtree_hid); + tcon->handles.idtree_limit = limit; + tcon->handles.list = NULL; + + return NT_STATUS_OK; +} + +/**************************************************************************** +find a handle given a handle id +****************************************************************************/ +static struct smbsrv_handle *smbsrv_handle_find(struct smbsrv_handles_context *handles_ctx, + uint64_t hid, struct timeval request_time) +{ + void *p; + struct smbsrv_handle *handle; + + if (hid == 0) return NULL; + + if (hid > handles_ctx->idtree_limit) return NULL; + + p = idr_find(handles_ctx->idtree_hid, hid); + if (!p) return NULL; + + handle = talloc_get_type(p, struct smbsrv_handle); + if (!handle) return NULL; + + /* only give it away when the ntvfs subsystem has made the handle valid */ + if (!handle->ntvfs) return NULL; + + handle->statistics.last_use_time = request_time; + + return handle; +} + +struct smbsrv_handle *smbsrv_smb_handle_find(struct smbsrv_tcon *smb_tcon, + uint16_t fnum, struct timeval request_time) +{ + return smbsrv_handle_find(&smb_tcon->handles, fnum, request_time); +} + +/* + destroy a connection structure +*/ +static int smbsrv_handle_destructor(void *ptr) +{ + struct smbsrv_handle *handle = talloc_get_type(ptr, struct smbsrv_handle); + struct smbsrv_handles_context *handles_ctx; + + handles_ctx = &handle->tcon->handles; + + idr_remove(handles_ctx->idtree_hid, handle->hid); + DLIST_REMOVE(handles_ctx->list, handle); + DLIST_REMOVE(handle->session->handles, &handle->session_item); + + /* tell the ntvfs backend that we are disconnecting */ + if (handle->ntvfs) { + talloc_free(handle->ntvfs); + handle->ntvfs = NULL; + } + + return 0; +} + +/* + find first available handle slot +*/ +struct smbsrv_handle *smbsrv_handle_new(struct smbsrv_request *req) +{ + struct smbsrv_handles_context *handles_ctx = &req->tcon->handles; + struct smbsrv_handle *handle; + int i; + + handle = talloc_zero(req, struct smbsrv_handle); + if (!handle) return NULL; + handle->tcon = req->tcon; + handle->session = req->session; + + i = idr_get_new_above(handles_ctx->idtree_hid, handle, 1, handles_ctx->idtree_limit); + if (i == -1) { + DEBUG(1,("ERROR! Out of handle structures\n")); + goto failed; + } + handle->hid = i; + handle->session_item.handle = handle; + + DLIST_ADD(handles_ctx->list, handle); + DLIST_ADD(handle->session->handles, &handle->session_item); + talloc_set_destructor(handle, smbsrv_handle_destructor); + + /* now fill in some statistics */ + handle->statistics.open_time = req->request_time; + handle->statistics.last_use_time = req->request_time; + + return handle; + +failed: + talloc_free(handle); + return NULL; +} diff --git a/source4/smb_server/smb/nttrans.c b/source4/smb_server/smb/nttrans.c index c5b950ec5b..3bc0ab69b2 100644 --- a/source4/smb_server/smb/nttrans.c +++ b/source4/smb_server/smb/nttrans.c @@ -75,7 +75,7 @@ static NTSTATUS nttrans_create_send(struct nttrans_op *op) params = op->trans->out.params.data; SSVAL(params, 0, io->ntcreatex.out.oplock_level); - SSVAL(params, 2, io->ntcreatex.out.file.fnum); + smbsrv_push_fnum(params, 2, io->ntcreatex.out.file.ntvfs); SIVAL(params, 4, io->ntcreatex.out.create_action); SIVAL(params, 8, 0); /* ea error offset */ push_nttime(params, 12, io->ntcreatex.out.create_time); @@ -230,12 +230,13 @@ static NTSTATUS nttrans_query_sec_desc(struct smbsrv_request *req, NT_STATUS_HAVE_NO_MEMORY(io); io->query_secdesc.level = RAW_FILEINFO_SEC_DESC; - io->query_secdesc.in.file.fnum = SVAL(trans->in.params.data, 0); + io->query_secdesc.in.file.ntvfs = smbsrv_pull_fnum(req, trans->in.params.data, 0); io->query_secdesc.in.secinfo_flags = IVAL(trans->in.params.data, 4); op->op_info = io; op->send_fn = nttrans_query_sec_desc_send; + SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(io->query_secdesc.in.file.ntvfs); return ntvfs_qfileinfo(req->ntvfs, io); } @@ -259,7 +260,7 @@ static NTSTATUS nttrans_set_sec_desc(struct smbsrv_request *req, NT_STATUS_HAVE_NO_MEMORY(io); io->set_secdesc.level = RAW_SFILEINFO_SEC_DESC; - io->set_secdesc.in.file.fnum = SVAL(trans->in.params.data, 0); + io->set_secdesc.in.file.ntvfs = smbsrv_pull_fnum(req, trans->in.params.data, 0); io->set_secdesc.in.secinfo_flags = IVAL(trans->in.params.data, 4); io->set_secdesc.in.sd = talloc(io, struct security_descriptor); @@ -270,6 +271,7 @@ static NTSTATUS nttrans_set_sec_desc(struct smbsrv_request *req, (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); NT_STATUS_NOT_OK_RETURN(status); + SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(io->set_secdesc.in.file.ntvfs); return ntvfs_setfileinfo(req->ntvfs, io); } @@ -304,6 +306,7 @@ static NTSTATUS nttrans_ioctl_send(struct nttrans_op *op) return NT_STATUS_OK; } + /* parse NTTRANS_IOCTL request */ @@ -323,7 +326,7 @@ static NTSTATUS nttrans_ioctl(struct smbsrv_request *req, nt->ntioctl.level = RAW_IOCTL_NTIOCTL; nt->ntioctl.in.function = IVAL(trans->in.setup, 0); - nt->ntioctl.in.file.fnum = SVAL(trans->in.setup, 4); + nt->ntioctl.in.file.ntvfs = smbsrv_pull_fnum(req, (uint8_t *)trans->in.setup, 4); nt->ntioctl.in.fsctl = CVAL(trans->in.setup, 6); nt->ntioctl.in.filter = CVAL(trans->in.setup, 7); nt->ntioctl.in.max_data = trans->in.max_data; @@ -332,6 +335,7 @@ static NTSTATUS nttrans_ioctl(struct smbsrv_request *req, op->op_info = nt; op->send_fn = nttrans_ioctl_send; + SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(nt->ntioctl.in.file.ntvfs); return ntvfs_ioctl(req->ntvfs, nt); } @@ -408,13 +412,14 @@ static NTSTATUS nttrans_notify_change(struct smbsrv_request *req, NT_STATUS_HAVE_NO_MEMORY(info); info->in.completion_filter = IVAL(trans->in.setup, 0); - info->in.file.fnum = SVAL(trans->in.setup, 4); + info->in.file.ntvfs = smbsrv_pull_fnum(req, (uint8_t *)trans->in.setup, 4); info->in.recursive = SVAL(trans->in.setup, 6); info->in.buffer_size = trans->in.max_param; op->op_info = info; op->send_fn = nttrans_notify_change_send; + SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(info->in.file.ntvfs); return ntvfs_notify(req->ntvfs, info); } diff --git a/source4/smb_server/smb/receive.c b/source4/smb_server/smb/receive.c index ee728e0ec5..a47d0a5442 100644 --- a/source4/smb_server/smb/receive.c +++ b/source4/smb_server/smb/receive.c @@ -31,7 +31,7 @@ /* send an oplock break request to a client */ -NTSTATUS smbsrv_send_oplock_break(void *p, uint16_t fnum, uint8_t level) +NTSTATUS smbsrv_send_oplock_break(void *p, struct ntvfs_handle *ntvfs, uint8_t level) { struct smbsrv_tcon *tcon = talloc_get_type(p, struct smbsrv_tcon); struct smbsrv_request *req; @@ -51,7 +51,7 @@ NTSTATUS smbsrv_send_oplock_break(void *p, uint16_t fnum, uint8_t level) SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1), 0); - SSVAL(req->out.vwv, VWV(2), fnum); + smbsrv_push_fnum(req->out.vwv, VWV(2), ntvfs); SCVAL(req->out.vwv, VWV(3), LOCKING_ANDX_OPLOCK_RELEASE); SCVAL(req->out.vwv, VWV(3)+1, level); SIVAL(req->out.vwv, VWV(4), 0); diff --git a/source4/smb_server/smb/reply.c b/source4/smb_server/smb/reply.c index 768fba1319..9abb35ad86 100644 --- a/source4/smb_server/smb/reply.c +++ b/source4/smb_server/smb/reply.c @@ -3,6 +3,7 @@ Main SMB reply routines Copyright (C) Andrew Tridgell 1992-2003 Copyright (C) James J Myers 2003 <myersjj@samba.org> + Copyright (C) Stefan Metzmacher 2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,7 +21,7 @@ */ /* This file handles most of the reply_ calls that the server - makes to handle specific protocols + makes to handle specific SMB commands */ #include "includes.h" @@ -204,10 +205,11 @@ void smbsrv_reply_ioctl(struct smbsrv_request *req) SMBSRV_SETUP_NTVFS_REQUEST(reply_ioctl_send, NTVFS_ASYNC_STATE_MAY_ASYNC); io->ioctl.level = RAW_IOCTL_IOCTL; - io->ioctl.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + io->ioctl.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); io->ioctl.in.request = IVAL(req->in.vwv, VWV(1)); - /* call backend */ + SMBSRV_CHECK_FILE_HANDLE_ERROR(io->ioctl.in.file.ntvfs, + NT_STATUS_DOS(ERRSRV, ERRerror)); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_ioctl(req->ntvfs, io)); } @@ -353,7 +355,7 @@ static void reply_open_send(struct ntvfs_request *ntvfs) /* construct reply */ smbsrv_setup_reply(req, 7, 0); - SSVAL(req->out.vwv, VWV(0), oi->openold.out.file.fnum); + smbsrv_push_fnum(req->out.vwv, VWV(0), oi->openold.out.file.ntvfs); 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); @@ -408,7 +410,7 @@ static void reply_open_and_X_send(struct ntvfs_request *ntvfs) SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1), 0); - SSVAL(req->out.vwv, VWV(2), oi->openx.out.file.fnum); + smbsrv_push_fnum(req->out.vwv, VWV(2), oi->openx.out.file.ntvfs); SSVAL(req->out.vwv, VWV(3), oi->openx.out.attrib); 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); @@ -423,7 +425,7 @@ static void reply_open_and_X_send(struct ntvfs_request *ntvfs) SMBSRV_VWV_RESERVED(17, 2); } - req->chained_fnum = oi->openx.out.file.fnum; + req->chained_fnum = SVAL(req->out.vwv, VWV(2)); smbsrv_chain_reply(req); } @@ -475,7 +477,7 @@ static void reply_mknew_send(struct ntvfs_request *ntvfs) /* build the reply */ smbsrv_setup_reply(req, 1, 0); - SSVAL(req->out.vwv, VWV(0), oi->mknew.out.file.fnum); + smbsrv_push_fnum(req->out.vwv, VWV(0), oi->mknew.out.file.ntvfs); smbsrv_send_reply(req); } @@ -524,7 +526,7 @@ static void reply_ctemp_send(struct ntvfs_request *ntvfs) /* build the reply */ smbsrv_setup_reply(req, 1, 0); - SSVAL(req->out.vwv, VWV(0), oi->ctemp.out.file.fnum); + smbsrv_push_fnum(req->out.vwv, VWV(0), oi->ctemp.out.file.ntvfs); /* the returned filename is relative to the directory */ req_push_str(req, NULL, oi->ctemp.out.name, -1, STR_TERMINATE | STR_ASCII); @@ -599,12 +601,16 @@ void smbsrv_reply_readbraw(struct smbsrv_request *req) goto failed; } - io.readbraw.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + io.readbraw.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); io.readbraw.in.offset = IVAL(req->in.vwv, VWV(1)); 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)); + if (!io.readbraw.in.file.ntvfs) { + goto failed; + } + /* the 64 bit variant */ if (req->in.wct == 10) { uint32_t offset_high = IVAL(req->in.vwv, VWV(8)); @@ -695,17 +701,18 @@ void smbsrv_reply_lockread(struct smbsrv_request *req) SMBSRV_SETUP_NTVFS_REQUEST(reply_lockread_send, NTVFS_ASYNC_STATE_MAY_ASYNC); io->lockread.level = RAW_READ_LOCKREAD; - io->lockread.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + io->lockread.in.file.ntvfs= smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); io->lockread.in.count = SVAL(req->in.vwv, VWV(1)); io->lockread.in.offset = IVAL(req->in.vwv, VWV(2)); io->lockread.in.remaining = SVAL(req->in.vwv, VWV(4)); - + /* setup the reply packet assuming the maximum possible read */ smbsrv_setup_reply(req, 5, 3 + io->lockread.in.count); /* tell the backend where to put the data */ io->lockread.out.data = req->out.data + 3; + SMBSRV_CHECK_FILE_HANDLE(io->lockread.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_read(req->ntvfs, io)); } @@ -749,17 +756,18 @@ void smbsrv_reply_read(struct smbsrv_request *req) SMBSRV_SETUP_NTVFS_REQUEST(reply_read_send, NTVFS_ASYNC_STATE_MAY_ASYNC); io->read.level = RAW_READ_READ; - io->read.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + io->read.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); io->read.in.count = SVAL(req->in.vwv, VWV(1)); io->read.in.offset = IVAL(req->in.vwv, VWV(2)); io->read.in.remaining = SVAL(req->in.vwv, VWV(4)); - + /* setup the reply packet assuming the maximum possible read */ smbsrv_setup_reply(req, 5, 3 + io->read.in.count); /* tell the backend where to put the data */ io->read.out.data = req->out.data + 3; + SMBSRV_CHECK_FILE_HANDLE(io->read.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_read(req->ntvfs, io)); } @@ -812,7 +820,7 @@ void smbsrv_reply_read_and_X(struct smbsrv_request *req) SMBSRV_SETUP_NTVFS_REQUEST(reply_read_and_X_send, NTVFS_ASYNC_STATE_MAY_ASYNC); io->readx.level = RAW_READ_READX; - io->readx.in.file.fnum = req_fnum(req, req->in.vwv, VWV(2)); + io->readx.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(2)); io->readx.in.offset = IVAL(req->in.vwv, VWV(3)); io->readx.in.maxcnt = SVAL(req->in.vwv, VWV(5)); io->readx.in.mincnt = SVAL(req->in.vwv, VWV(6)); @@ -847,6 +855,7 @@ void smbsrv_reply_read_and_X(struct smbsrv_request *req) io->readx.out.data = req->out.data; } + SMBSRV_CHECK_FILE_HANDLE(io->readx.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_read(req->ntvfs, io)); } @@ -890,7 +899,7 @@ void smbsrv_reply_writeunlock(struct smbsrv_request *req) SMBSRV_SETUP_NTVFS_REQUEST(reply_writeunlock_send, NTVFS_ASYNC_STATE_MAY_ASYNC); io->writeunlock.level = RAW_WRITE_WRITEUNLOCK; - io->writeunlock.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + io->writeunlock.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); io->writeunlock.in.count = SVAL(req->in.vwv, VWV(1)); io->writeunlock.in.offset = IVAL(req->in.vwv, VWV(2)); io->writeunlock.in.remaining = SVAL(req->in.vwv, VWV(4)); @@ -908,6 +917,7 @@ void smbsrv_reply_writeunlock(struct smbsrv_request *req) return; } + SMBSRV_CHECK_FILE_HANDLE(io->writeunlock.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io)); } @@ -943,7 +953,7 @@ void smbsrv_reply_write(struct smbsrv_request *req) SMBSRV_SETUP_NTVFS_REQUEST(reply_write_send, NTVFS_ASYNC_STATE_MAY_ASYNC); io->write.level = RAW_WRITE_WRITE; - io->write.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + io->write.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); io->write.in.count = SVAL(req->in.vwv, VWV(1)); io->write.in.offset = IVAL(req->in.vwv, VWV(2)); io->write.in.remaining = SVAL(req->in.vwv, VWV(4)); @@ -961,6 +971,7 @@ void smbsrv_reply_write(struct smbsrv_request *req) return; } + SMBSRV_CHECK_FILE_HANDLE(io->write.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io)); } @@ -1003,7 +1014,7 @@ void smbsrv_reply_write_and_X(struct smbsrv_request *req) SMBSRV_SETUP_NTVFS_REQUEST(reply_write_and_X_send, NTVFS_ASYNC_STATE_MAY_ASYNC); io->writex.level = RAW_WRITE_WRITEX; - io->writex.in.file.fnum = req_fnum(req, req->in.vwv, VWV(2)); + io->writex.in.file.ntvfs= smbsrv_pull_fnum(req, req->in.vwv, VWV(2)); io->writex.in.offset = IVAL(req->in.vwv, VWV(3)); io->writex.in.wmode = SVAL(req->in.vwv, VWV(7)); io->writex.in.remaining = SVAL(req->in.vwv, VWV(8)); @@ -1021,8 +1032,9 @@ void smbsrv_reply_write_and_X(struct smbsrv_request *req) if (req_data_oob(req, io->writex.in.data, io->writex.in.count)) { smbsrv_send_error(req, NT_STATUS_FOOBAR); return; - } + } + SMBSRV_CHECK_FILE_HANDLE(io->writex.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io)); } @@ -1056,10 +1068,11 @@ void smbsrv_reply_lseek(struct smbsrv_request *req) SMBSRV_TALLOC_IO_PTR(io, union smb_seek); SMBSRV_SETUP_NTVFS_REQUEST(reply_lseek_send, NTVFS_ASYNC_STATE_MAY_ASYNC); - io->lseek.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + io->lseek.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); io->lseek.in.mode = SVAL(req->in.vwv, VWV(1)); io->lseek.in.offset = IVALS(req->in.vwv, VWV(2)); + SMBSRV_CHECK_FILE_HANDLE(io->lseek.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_seek(req->ntvfs, io)); } @@ -1076,46 +1089,18 @@ void smbsrv_reply_flush(struct smbsrv_request *req) SMBSRV_TALLOC_IO_PTR(io, union smb_flush); SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC); - fnum = req_fnum(req, req->in.vwv, VWV(0)); - + fnum = SVAL(req->in.vwv, VWV(0)); if (fnum == 0xFFFF) { io->flush_all.level = RAW_FLUSH_ALL; } else { io->flush.level = RAW_FLUSH_FLUSH; - io->flush.in.file.fnum = fnum; + io->flush.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); + SMBSRV_CHECK_FILE_HANDLE(io->flush.in.file.ntvfs); } SMBSRV_CALL_NTVFS_BACKEND(ntvfs_flush(req->ntvfs, io)); } - -/**************************************************************************** - Reply to a exit. This closes all files open by a smbpid -****************************************************************************/ -void smbsrv_reply_exit(struct smbsrv_request *req) -{ - NTSTATUS status; - struct smbsrv_tcon *tcon; - SMBSRV_CHECK_WCT(req, 0); - - for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) { - req->tcon = tcon; - SMBSRV_SETUP_NTVFS_REQUEST(NULL,0); - status = ntvfs_exit(req->ntvfs); - talloc_free(req->ntvfs); - req->ntvfs = NULL; - req->tcon = NULL; - if (!NT_STATUS_IS_OK(status)) { - smbsrv_send_error(req, status); - return; - } - } - - smbsrv_setup_reply(req, 0, 0); - smbsrv_send_reply(req); -} - - /**************************************************************************** Reply to a close @@ -1131,9 +1116,10 @@ void smbsrv_reply_close(struct smbsrv_request *req) SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC); io->close.level = RAW_CLOSE_CLOSE; - io->close.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + io->close.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); io->close.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1)); + SMBSRV_CHECK_FILE_HANDLE(io->close.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_close(req->ntvfs, io)); } @@ -1171,12 +1157,12 @@ void smbsrv_reply_writeclose(struct smbsrv_request *req) SMBSRV_TALLOC_IO_PTR(io, union smb_write); SMBSRV_SETUP_NTVFS_REQUEST(reply_writeclose_send, NTVFS_ASYNC_STATE_MAY_ASYNC); - io->writeclose.level = RAW_WRITE_WRITECLOSE; - io->writeclose.in.file.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 = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(4)); - io->writeclose.in.data = req->in.data + 1; + io->writeclose.level = RAW_WRITE_WRITECLOSE; + io->writeclose.in.file.ntvfs = smbsrv_pull_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 = 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 */ if (req_data_oob(req, io->writeclose.in.data, io->writeclose.in.count)) { @@ -1184,6 +1170,7 @@ void smbsrv_reply_writeclose(struct smbsrv_request *req) return; } + SMBSRV_CHECK_FILE_HANDLE(io->writeclose.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io)); } @@ -1200,10 +1187,11 @@ void smbsrv_reply_lock(struct smbsrv_request *req) SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC); lck->lock.level = RAW_LOCK_LOCK; - lck->lock.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + lck->lock.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); lck->lock.in.count = IVAL(req->in.vwv, VWV(1)); lck->lock.in.offset = IVAL(req->in.vwv, VWV(3)); + SMBSRV_CHECK_FILE_HANDLE(lck->lock.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req->ntvfs, lck)); } @@ -1221,10 +1209,11 @@ void smbsrv_reply_unlock(struct smbsrv_request *req) SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC); lck->unlock.level = RAW_LOCK_UNLOCK; - lck->unlock.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + lck->unlock.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); lck->unlock.in.count = IVAL(req->in.vwv, VWV(1)); lck->unlock.in.offset = IVAL(req->in.vwv, VWV(3)); + SMBSRV_CHECK_FILE_HANDLE(lck->unlock.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req->ntvfs, lck)); } @@ -1234,14 +1223,27 @@ void smbsrv_reply_unlock(struct smbsrv_request *req) ****************************************************************************/ void smbsrv_reply_tdis(struct smbsrv_request *req) { + struct smbsrv_handle *h, *nh; + SMBSRV_CHECK_WCT(req, 0); + /* + * TODO: cancel all pending requests on this tcon + */ + + /* + * close all handles on this tcon + */ + for (h=req->tcon->handles.list; h; h=nh) { + nh = h->next; + talloc_free(h); + } + + /* finaly destroy the tcon */ talloc_free(req->tcon); req->tcon = NULL; - /* construct reply */ smbsrv_setup_reply(req, 0, 0); - smbsrv_send_reply(req); } @@ -1292,7 +1294,7 @@ static void reply_printopen_send(struct ntvfs_request *ntvfs) /* construct reply */ smbsrv_setup_reply(req, 1, 0); - SSVAL(req->out.vwv, VWV(0), oi->openold.out.file.fnum); + smbsrv_push_fnum(req->out.vwv, VWV(0), oi->openold.out.file.ntvfs); smbsrv_send_reply(req); } @@ -1330,9 +1332,10 @@ void smbsrv_reply_printclose(struct smbsrv_request *req) SMBSRV_TALLOC_IO_PTR(io, union smb_close); SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC); - io->splclose.level = RAW_CLOSE_SPLCLOSE; - io->splclose.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + io->splclose.level = RAW_CLOSE_SPLCLOSE; + io->splclose.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); + SMBSRV_CHECK_FILE_HANDLE(io->splclose.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_close(req->ntvfs, io)); } @@ -1414,16 +1417,15 @@ void smbsrv_reply_printwrite(struct smbsrv_request *req) SMBSRV_TALLOC_IO_PTR(io, union smb_write); SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC); - io->splwrite.level = RAW_WRITE_SPLWRITE; - if (req->in.data_size < 3) { smbsrv_send_error(req, NT_STATUS_FOOBAR); return; } - io->splwrite.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); - io->splwrite.in.count = SVAL(req->in.data, 1); - io->splwrite.in.data = req->in.data + 3; + io->splwrite.level = RAW_WRITE_SPLWRITE; + io->splwrite.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); + io->splwrite.in.count = SVAL(req->in.data, 1); + io->splwrite.in.data = req->in.data + 3; /* make sure they gave us the data they promised */ if (req_data_oob(req, io->splwrite.in.data, io->splwrite.in.count)) { @@ -1431,6 +1433,7 @@ void smbsrv_reply_printwrite(struct smbsrv_request *req) return; } + SMBSRV_CHECK_FILE_HANDLE(io->splwrite.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io)); } @@ -1621,7 +1624,7 @@ void smbsrv_reply_lockingX(struct smbsrv_request *req) SMBSRV_SETUP_NTVFS_REQUEST(reply_lockingX_send, NTVFS_ASYNC_STATE_MAY_ASYNC); lck->lockx.level = RAW_LOCK_LOCKX; - lck->lockx.in.file.fnum = req_fnum(req, req->in.vwv, VWV(2)); + lck->lockx.in.file.ntvfs= smbsrv_pull_fnum(req, req->in.vwv, VWV(2)); lck->lockx.in.mode = SVAL(req->in.vwv, VWV(3)); lck->lockx.in.timeout = IVAL(req->in.vwv, VWV(4)); lck->lockx.in.ulock_cnt = SVAL(req->in.vwv, VWV(6)); @@ -1676,6 +1679,7 @@ void smbsrv_reply_lockingX(struct smbsrv_request *req) p += lck_size; } + SMBSRV_CHECK_FILE_HANDLE(lck->lockx.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req->ntvfs, lck)); } @@ -1702,11 +1706,12 @@ void smbsrv_reply_setattrE(struct smbsrv_request *req) SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC); info->setattre.level = RAW_SFILEINFO_SETATTRE; - info->setattre.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + info->setattre.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); 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)); + SMBSRV_CHECK_FILE_HANDLE(info->setattre.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_setfileinfo(req->ntvfs, info)); } @@ -1765,9 +1770,10 @@ void smbsrv_reply_getattrE(struct smbsrv_request *req) SMBSRV_TALLOC_IO_PTR(info, union smb_fileinfo); SMBSRV_SETUP_NTVFS_REQUEST(reply_getattrE_send, NTVFS_ASYNC_STATE_MAY_ASYNC); - info->getattr.level = RAW_FILEINFO_GETATTRE; - info->getattr.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0)); + info->getattr.level = RAW_FILEINFO_GETATTRE; + info->getattr.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); + SMBSRV_CHECK_FILE_HANDLE(info->getattr.in.file.ntvfs); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_qfileinfo(req->ntvfs, info)); } @@ -1988,26 +1994,81 @@ void smbsrv_reply_sesssetup(struct smbsrv_request *req) } /**************************************************************************** + Reply to a exit. This closes all files open by a smbpid +****************************************************************************/ +void smbsrv_reply_exit(struct smbsrv_request *req) +{ + struct smbsrv_handle_session_item *i, *ni; + struct smbsrv_handle *h; + struct smbsrv_tcon *tcon; + uint16_t smbpid; + + SMBSRV_CHECK_WCT(req, 0); + + smbpid = SVAL(req->in.hdr,HDR_PID); + + /* first destroy all handles, which have the same PID as the request */ + for (i=req->session->handles; i; i=ni) { + ni = i->next; + h = i->handle; + if (h->smbpid != smbpid) continue; + + talloc_free(h); + } + + /* + * then let the ntvfs backends proxy the call if they want to, + * but we didn't check the return value of the backends, + * as for the SMB client the call succeed + */ + for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) { + req->tcon = tcon; + SMBSRV_SETUP_NTVFS_REQUEST(NULL,0); + ntvfs_exit(req->ntvfs); + talloc_free(req->ntvfs); + req->ntvfs = NULL; + req->tcon = NULL; + } + + smbsrv_setup_reply(req, 0, 0); + smbsrv_send_reply(req); +} + +/**************************************************************************** Reply to a SMBulogoffX. ****************************************************************************/ void smbsrv_reply_ulogoffX(struct smbsrv_request *req) { + struct smbsrv_handle_session_item *i, *ni; + struct smbsrv_handle *h; struct smbsrv_tcon *tcon; - NTSTATUS status; - /* in user level security we are supposed to close any files - open by this user on all open tree connects */ + SMBSRV_CHECK_WCT(req, 2); + + /* + * TODO: cancel all pending requests + */ + + + /* destroy all handles */ + for (i=req->session->handles; i; i=ni) { + ni = i->next; + h = i->handle; + talloc_free(h); + } + + /* + * then let the ntvfs backends proxy the call if they want to, + * but we didn't check the return value of the backends, + * as for the SMB client the call succeed + */ for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) { req->tcon = tcon; SMBSRV_SETUP_NTVFS_REQUEST(NULL,0); - status = ntvfs_logoff(req->ntvfs); + ntvfs_logoff(req->ntvfs); talloc_free(req->ntvfs); req->ntvfs = NULL; req->tcon = NULL; - if (!NT_STATUS_IS_OK(status)) { - smbsrv_send_error(req, status); - return; - } } talloc_free(req->session); @@ -2018,7 +2079,7 @@ void smbsrv_reply_ulogoffX(struct smbsrv_request *req) SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1), 0); - + smbsrv_chain_reply(req); } @@ -2067,7 +2128,7 @@ static void reply_ntcreate_and_X_send(struct ntvfs_request *ntvfs) SCVAL(req->out.vwv, VWV(2), io->ntcreatex.out.oplock_level); /* the rest of the parameters are not aligned! */ - SSVAL(req->out.vwv, 5, io->ntcreatex.out.file.fnum); + smbsrv_push_fnum(req->out.vwv, 5, io->ntcreatex.out.file.ntvfs); 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); @@ -2080,7 +2141,7 @@ static void reply_ntcreate_and_X_send(struct ntvfs_request *ntvfs) SSVAL(req->out.vwv, 65, io->ntcreatex.out.ipc_state); SCVAL(req->out.vwv, 67, io->ntcreatex.out.is_directory); - req->chained_fnum = io->ntcreatex.out.file.fnum; + req->chained_fnum = SVAL(req->out.vwv, 5); smbsrv_chain_reply(req); } diff --git a/source4/smb_server/smb/request.c b/source4/smb_server/smb/request.c index 21f89f40f9..2896a44d29 100644 --- a/source4/smb_server/smb/request.c +++ b/source4/smb_server/smb/request.c @@ -636,10 +636,100 @@ BOOL req_data_oob(struct smbsrv_request *req, const uint8_t *ptr, uint32_t count /* pull an open file handle from a packet, taking account of the chained_fnum */ -uint16_t req_fnum(struct smbsrv_request *req, const uint8_t *base, uint_t offset) +static uint16_t req_fnum(struct smbsrv_request *req, const uint8_t *base, uint_t offset) { if (req->chained_fnum != -1) { return req->chained_fnum; } return SVAL(base, offset); } + +struct ntvfs_handle *smbsrv_pull_fnum(struct smbsrv_request *req, const uint8_t *base, uint_t offset) +{ + struct smbsrv_handle *handle; + uint16_t fnum = req_fnum(req, base, offset); + + handle = smbsrv_smb_handle_find(req->tcon, fnum, req->request_time); + if (!handle) { + return NULL; + } + + return handle->ntvfs; +} + +void smbsrv_push_fnum(uint8_t *base, uint_t offset, struct ntvfs_handle *ntvfs) +{ + struct smbsrv_handle *handle = talloc_get_type(ntvfs->frontend_data.private_data, + struct smbsrv_handle); + SSVAL(base, offset, handle->hid); +} + +NTSTATUS smbsrv_handle_create_new(void *private_data, struct ntvfs_request *ntvfs, struct ntvfs_handle **_h) +{ + struct smbsrv_request *req = talloc_get_type(ntvfs->frontend_data.private_data, + struct smbsrv_request); + struct smbsrv_handle *handle; + struct ntvfs_handle *h; + + handle = smbsrv_handle_new(req); + if (!handle) return NT_STATUS_INSUFFICIENT_RESOURCES; + + h = talloc_zero(handle, struct ntvfs_handle); + if (!h) goto nomem; + + /* + * note: we don't set handle->ntvfs yet, + * this will be done by smbsrv_handle_make_valid() + * this makes sure the handle is invalid for clients + * until the ntvfs subsystem has made it valid + */ + h->ctx = ntvfs->ctx; + h->session_info = ntvfs->session_info; + h->smbpid = ntvfs->smbpid; + + h->frontend_data.private_data = handle; + + *_h = h; + return NT_STATUS_OK; +nomem: + talloc_free(handle); + return NT_STATUS_NO_MEMORY; +} + +NTSTATUS smbsrv_handle_make_valid(void *private_data, struct ntvfs_handle *h) +{ + struct smbsrv_tcon *tcon = talloc_get_type(private_data, struct smbsrv_tcon); + struct smbsrv_handle *handle = talloc_get_type(h->frontend_data.private_data, + struct smbsrv_handle); + /* this tells the frontend that the handle is valid */ + handle->ntvfs = h; + /* this moves the smbsrv_request to the smbsrv_tcon memory context */ + talloc_steal(tcon, handle); + return NT_STATUS_OK; +} + +void smbsrv_handle_destroy(void *private_data, struct ntvfs_handle *h) +{ + struct smbsrv_handle *handle = talloc_get_type(h->frontend_data.private_data, + struct smbsrv_handle); + talloc_free(handle); +} + +struct ntvfs_handle *smbsrv_handle_search_by_wire_key(void *private_data, struct ntvfs_request *ntvfs, const DATA_BLOB *key) +{ + struct smbsrv_request *req = talloc_get_type(ntvfs->frontend_data.private_data, + struct smbsrv_request); + + if (key->length != 2) return NULL; + + return smbsrv_pull_fnum(req, key->data, 0); +} + +DATA_BLOB smbsrv_handle_get_wire_key(void *private_data, struct ntvfs_handle *handle, TALLOC_CTX *mem_ctx) +{ + uint8_t key[2]; + + smbsrv_push_fnum(key, 0, handle); + + return data_blob_talloc(mem_ctx, key, sizeof(key)); +} diff --git a/source4/smb_server/smb/service.c b/source4/smb_server/smb/service.c index 13ef268a98..7c703c8920 100644 --- a/source4/smb_server/smb/service.c +++ b/source4/smb_server/smb/service.c @@ -110,7 +110,19 @@ static NTSTATUS make_connection_snum(struct smbsrv_request *req, status = ntvfs_set_addr_callbacks(tcon->ntvfs, smbsrv_get_my_addr, smbsrv_get_peer_addr, req->smb_conn); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("make_connection: NTVFS failed to set the oplock handler!\n")); + DEBUG(0,("make_connection: NTVFS failed to set the addr callbacks!\n")); + goto failed; + } + + status = ntvfs_set_handle_callbacks(tcon->ntvfs, + smbsrv_handle_create_new, + smbsrv_handle_make_valid, + smbsrv_handle_destroy, + smbsrv_handle_search_by_wire_key, + smbsrv_handle_get_wire_key, + tcon); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("make_connection: NTVFS failed to set the handle callbacks!\n")); goto failed; } diff --git a/source4/smb_server/smb/trans2.c b/source4/smb_server/smb/trans2.c index 1145a08426..69fa65010c 100644 --- a/source4/smb_server/smb/trans2.c +++ b/source4/smb_server/smb/trans2.c @@ -447,7 +447,7 @@ static NTSTATUS trans2_open_send(struct trans_op *op) trans2_setup_reply(trans, 30, 0, 0); - SSVAL(trans->out.params.data, VWV(0), io->t2open.out.file.fnum); + smbsrv_push_fnum(trans->out.params.data, VWV(0), io->t2open.out.file.ntvfs); SSVAL(trans->out.params.data, VWV(1), io->t2open.out.attrib); srv_push_dos_date3(req->smb_conn, trans->out.params.data, VWV(2), io->t2open.out.write_time); @@ -847,7 +847,8 @@ static NTSTATUS trans2_qfileinfo(struct smbsrv_request *req, struct trans_op *op struct smb_trans2 *trans = op->trans; union smb_fileinfo *st; NTSTATUS status; - uint16_t level, fnum; + uint16_t level; + struct ntvfs_handle *h; /* make sure we got enough parameters */ if (trans->in.params.length < 4) { @@ -857,10 +858,10 @@ static NTSTATUS trans2_qfileinfo(struct smbsrv_request *req, struct trans_op *op st = talloc(op, union smb_fileinfo); NT_STATUS_HAVE_NO_MEMORY(st); - fnum = SVAL(trans->in.params.data, 0); + h = smbsrv_pull_fnum(req, trans->in.params.data, 0); level = SVAL(trans->in.params.data, 2); - st->generic.in.file.fnum = fnum; + st->generic.in.file.ntvfs = h; /* work out the backend level - we make it 1-1 in the header */ st->generic.level = (enum smb_fileinfo_level)level; if (st->generic.level >= RAW_FILEINFO_GENERIC) { @@ -877,6 +878,7 @@ static NTSTATUS trans2_qfileinfo(struct smbsrv_request *req, struct trans_op *op op->op_info = st; op->send_fn = trans2_fileinfo_send; + SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(st->generic.in.file.ntvfs); return ntvfs_qfileinfo(req->ntvfs, st); } @@ -985,7 +987,8 @@ static NTSTATUS trans2_setfileinfo(struct smbsrv_request *req, struct trans_op * struct smb_trans2 *trans = op->trans; union smb_setfileinfo *st; NTSTATUS status; - uint16_t level, fnum; + uint16_t level; + struct ntvfs_handle *h; /* make sure we got enough parameters */ if (trans->in.params.length < 4) { @@ -995,10 +998,10 @@ static NTSTATUS trans2_setfileinfo(struct smbsrv_request *req, struct trans_op * st = talloc(op, union smb_setfileinfo); NT_STATUS_HAVE_NO_MEMORY(st); - fnum = SVAL(trans->in.params.data, 0); + h = smbsrv_pull_fnum(req, trans->in.params.data, 0); level = SVAL(trans->in.params.data, 2); - st->generic.in.file.fnum = fnum; + st->generic.in.file.ntvfs = h; /* work out the backend level - we make it 1-1 in the header */ st->generic.level = (enum smb_setfileinfo_level)level; if (st->generic.level >= RAW_SFILEINFO_GENERIC) { @@ -1011,6 +1014,7 @@ static NTSTATUS trans2_setfileinfo(struct smbsrv_request *req, struct trans_op * op->op_info = st; op->send_fn = trans2_simple_send; + SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(st->generic.in.file.ntvfs); return ntvfs_setfileinfo(req->ntvfs, st); } diff --git a/source4/smb_server/smb_server.h b/source4/smb_server/smb_server.h index 12b12692f3..7c9ba6dc63 100644 --- a/source4/smb_server/smb_server.h +++ b/source4/smb_server/smb_server.h @@ -57,7 +57,19 @@ struct smbsrv_sessions_context { /* also kept as a link list so it can be enumerated by the management code */ struct smbsrv_session *list; -} sessions; +}; + +struct smbsrv_handles_context { + /* an id tree used to allocate file handles */ + struct idr_context *idtree_hid; + + /* this is the limit of handle values for this context */ + uint64_t idtree_limit; + + /* also kept as a link list so it can be enumerated by + the management code */ + struct smbsrv_handle *list; +}; /* the current user context for a request */ struct smbsrv_session { @@ -65,8 +77,18 @@ struct smbsrv_session { struct smbsrv_connection *smb_conn; + /* + * in SMB2 tcons belong to just one session + * and not to the whole connection + */ struct smbsrv_tcons_context smb2_tcons; + /* + * the open file handles for this session, + * used for SMBexit, SMBulogoff and SMB2 SessionLogoff + */ + struct smbsrv_handle_session_item *handles; + /* * an index passed over the wire: * - 16 bit for smb @@ -78,7 +100,7 @@ struct smbsrv_session { struct auth_session_info *session_info; - /* some statictics for the management tools */ + /* some statistics for the management tools */ struct { /* the time when the session setup started */ struct timeval connect_time; @@ -99,6 +121,9 @@ struct smbsrv_tcon { /* the server context that this was created on */ struct smbsrv_connection *smb_conn; + /* the open file handles on this tcon */ + struct smbsrv_handles_context handles; + /* * an index passed over the wire: * - 16 bit for smb @@ -124,7 +149,7 @@ struct smbsrv_tcon { struct smbsrv_session *session; } smb2; - /* some statictics for the management tools */ + /* some statistics for the management tools */ struct { /* the time when the tree connect started */ struct timeval connect_time; @@ -133,6 +158,54 @@ struct smbsrv_tcon { } statistics; }; +struct smbsrv_handle { + struct smbsrv_handle *next, *prev; + + /* the tcon the handle belongs to */ + struct smbsrv_tcon *tcon; + + /* the session the handle was opened on */ + struct smbsrv_session *session; + + /* the smbpid used on the open, used for SMBexit */ + uint16_t smbpid; + + /* + * this is for adding the handle into a linked list + * on the smbsrv_session, we can't use *next,*prev + * for this because they're used for the linked list on the + * smbsrv_tcon + */ + struct smbsrv_handle_session_item { + struct smbsrv_handle_session_item *prev, *next; + struct smbsrv_handle *handle; + } session_item; + + /* + * the value passed over the wire + * - 16 bit for smb + * - 64 bit for smb2 + * Note: for SMB2 handles are 128 bit + * we'll fill the 2nd 64 bit with: + * - 32 bit TID + * - 32 bit 0xFFFFFFFF + */ + uint64_t hid; + + /* + * the ntvfs handle passed to the ntvfs backend + */ + struct ntvfs_handle *ntvfs; + + /* some statistics for the management tools */ + struct { + /* the time when the tree connect started */ + struct timeval open_time; + /* the time when the last request comes in */ + struct timeval last_use_time; + } statistics; +}; + /* a set of flags to control handling of request structures */ #define SMBSRV_REQ_CONTROL_LARGE (1<<1) /* allow replies larger than max_xmit */ @@ -266,7 +339,7 @@ struct smbsrv_connection { struct nbt_name *calling_name; } negotiate; - /* the context associated with open tree connects on a smb socket */ + /* the context associated with open tree connects on a smb socket, not for SMB2 */ struct smbsrv_tcons_context smb_tcons; /* context associated with currently valid session setups */ @@ -283,7 +356,7 @@ struct smbsrv_connection { } *requests; struct smb_signing_context signing; - + struct stream_connection *connection; /* this holds a partially received request */ @@ -350,6 +423,27 @@ struct smbsrv_connection { smbsrv_send_error(req, NT_STATUS_NO_MEMORY); \ return; \ } \ + req->ntvfs->frontend_data.private_data = req; \ +} while (0) + +#define SMBSRV_CHECK_FILE_HANDLE(handle) do { \ + if (!handle) { \ + smbsrv_send_error(req, NT_STATUS_INVALID_HANDLE); \ + return; \ + } \ +} while (0) + +#define SMBSRV_CHECK_FILE_HANDLE_ERROR(handle, _status) do { \ + if (!handle) { \ + smbsrv_send_error(req, _status); \ + return; \ + } \ +} while (0) + +#define SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(handle) do { \ + if (!handle) { \ + return NT_STATUS_INVALID_HANDLE; \ + } \ } while (0) /* diff --git a/source4/smb_server/tcon.c b/source4/smb_server/tcon.c index 8b100d11ce..dbd0677df1 100644 --- a/source4/smb_server/tcon.c +++ b/source4/smb_server/tcon.c @@ -3,6 +3,7 @@ Manage smbsrv_tcon structures Copyright (C) Andrew Tridgell 1998 Copyright (C) Alexander Bokovoy 2002 + Copyright (C) Stefan Metzmacher 2005-2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -109,6 +110,7 @@ static int smbsrv_tcon_destructor(void *ptr) /* tell the ntvfs backend that we are disconnecting */ if (tcon->ntvfs) { ntvfs_disconnect(tcon->ntvfs); + tcon->ntvfs = NULL; } if (tcon->smb2.session) { @@ -132,6 +134,7 @@ static struct smbsrv_tcon *smbsrv_tcon_new(struct smbsrv_connection *smb_conn, TALLOC_CTX *mem_ctx; struct smbsrv_tcons_context *tcons_ctx; struct smbsrv_tcon *tcon; + NTSTATUS status; int i; if (smb_sess) { @@ -149,6 +152,16 @@ static struct smbsrv_tcon *smbsrv_tcon_new(struct smbsrv_connection *smb_conn, tcon->share_name = talloc_strdup(tcon, share_name); if (!tcon->share_name) goto failed; + /* + * the use -1 here, because we don't want to give away the wildcard + * fnum used in SMBflush + */ + status = smbsrv_init_handles(tcon, UINT16_MAX - 1); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1,("ERROR! failed to init handles: %s\n", nt_errstr(status))); + goto failed; + } + i = idr_get_new_random(tcons_ctx->idtree_tid, tcon, tcons_ctx->idtree_limit); if (i == -1) { DEBUG(1,("ERROR! Out of connection structures\n")); |