The branch, master has been updated via 7d13955 s3:smbd: make use of smbXsrv_open for smb1/2/3 via f7762e2 s3:smbd: add smbXsrv_open* infrastructure via 9c8e2b5 s3:smbXsrv.idl: add smbXsrv_open* structures from 86d586d s3:configure: fix numerous compile warnings about implicit declaration of 'exit'
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 7d1395536bbcc937e3115aa067eed3f69f3909be Author: Stefan Metzmacher <me...@samba.org> Date: Fri Jun 8 17:51:47 2012 +0200 s3:smbd: make use of smbXsrv_open for smb1/2/3 This makes sure we generate unique persistent file ids, which are stored in smbXsrv_open_global.tdb. Pair-Programmed-With: Michael Adam <ob...@samba.org> metze Autobuild-User(master): Stefan Metzmacher <me...@samba.org> Autobuild-Date(master): Fri Jun 29 21:01:11 CEST 2012 on sn-devel-104 commit f7762e2730aa4e2fe37043b56e0413983b484108 Author: Stefan Metzmacher <me...@samba.org> Date: Mon Feb 6 23:06:41 2012 +0100 s3:smbd: add smbXsrv_open* infrastructure Pair-Programmed-With: Michael Adam <ob...@samba.org> metze commit 9c8e2b5af0039a8bae216781df008be10c0f0835 Author: Stefan Metzmacher <me...@samba.org> Date: Mon Mar 12 18:38:07 2012 +0100 s3:smbXsrv.idl: add smbXsrv_open* structures struct smbXsrv_open will represent a SMB 1 or SMB 2 open file handle, while 'files_struct' will be changed to handle just the protocol independent glue for the SMB_VFS layer. Note: the format is not stable yet, we need to add more things when we start to support durable handles. metze ----------------------------------------------------------------------- Summary of changes: source3/Makefile.in | 1 + source3/include/vfs.h | 1 + source3/librpc/idl/smbXsrv.idl | 71 +++ source3/smbd/files.c | 172 ++----- source3/smbd/globals.h | 34 +- source3/smbd/process.c | 10 + source3/smbd/proto.h | 1 - source3/smbd/server.c | 4 + source3/smbd/smb2_break.c | 5 +- source3/smbd/smb2_create.c | 4 +- source3/smbd/smb2_lock.c | 2 +- source3/smbd/smb2_read.c | 4 +- source3/smbd/smb2_write.c | 2 +- source3/smbd/{smbXsrv_tcon.c => smbXsrv_open.c} | 699 ++++++++++------------- source3/wscript_build | 2 + 15 files changed, 476 insertions(+), 536 deletions(-) copy source3/smbd/{smbXsrv_tcon.c => smbXsrv_open.c} (50%) Changeset truncated at 500 lines: diff --git a/source3/Makefile.in b/source3/Makefile.in index d9c4df3..483d0d4 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -979,6 +979,7 @@ SMBD_OBJ_SRV = smbd/server_reload.o \ smbd/smbXsrv_version.o \ smbd/smbXsrv_session.o \ smbd/smbXsrv_tcon.o \ + smbd/smbXsrv_open.o \ $(MANGLE_OBJ) @VFS_STATIC@ SMBD_OBJ_BASE = $(PARAM_WITHOUT_REG_OBJ) $(SMBD_OBJ_SRV) $(LIBSMB_OBJ) \ diff --git a/source3/include/vfs.h b/source3/include/vfs.h index bd66d34..754d4e4 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -186,6 +186,7 @@ struct fd_handle { typedef struct files_struct { struct files_struct *next, *prev; uint64_t fnum; + struct smbXsrv_open0 *op; struct connection_struct *conn; struct fd_handle *fh; unsigned int num_smb_operations; diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl index 9d9f855..be52723 100644 --- a/source3/librpc/idl/smbXsrv.idl +++ b/source3/librpc/idl/smbXsrv.idl @@ -28,6 +28,18 @@ cpp_quote("#define smbXsrv_session smbXsrv_session0") */ cpp_quote("#define smbXsrv_tcon smbXsrv_tcon0") +/* + * The main server code should just work with + * 'struct smbXsrv_open' and never use + * smbXsrv_open0, smbXsrv_openU + * and smbXsrv_openB directly. + * + * If we need to change the smbXsrv_open, + * we can just point it to smbXsrv_open1 + * and could implement transparent mapping. + */ +cpp_quote("#define smbXsrv_open smbXsrv_open0") + [ uuid("07408340-ae31-11e1-97dc-539f7fddc06f"), version(0.0), @@ -253,4 +265,63 @@ interface smbXsrv void smbXsrv_tcon_decode( [in] smbXsrv_tconB blob ); + + /* open files */ + + typedef struct { + [ignore] db_record *db_rec; + server_id server_id; + uint32 open_global_id; + hyper open_persistent_id; + hyper open_volatile_id; + dom_sid open_owner; + NTTIME open_time; + /* + * TODO: for durable/resilient/persistent handles we need more + * things here. See [MS-SMB2] 3.3.1.10 Per Open + * + * NOTE: this is still version 0, which is not a stable format! + */ + } smbXsrv_open_global0; + + typedef union { + [case(0)] smbXsrv_open_global0 *info0; + [default] hyper *dummy; + } smbXsrv_open_globalU; + + typedef [public] struct { + + smbXsrv_version_values version; + uint32 seqnum; + [switch_is(version)] smbXsrv_open_globalU info; + } smbXsrv_open_globalB; + + void smbXsrv_open_global_decode( + [in] smbXsrv_open_globalB blob + ); + + typedef struct { + [ignore] smbXsrv_open_table *table; + [ignore] db_record *db_rec; + uint32 local_id; + [ref] smbXsrv_open_global0 *global; + NTSTATUS status; + NTTIME idle_time; + [ignore] files_struct *compat; + } smbXsrv_open0; + + typedef union { + [case(0)] smbXsrv_open0 *info0; + [default] hyper *dummy; + } smbXsrv_openU; + + typedef [public] struct { + smbXsrv_version_values version; + [value(0)] uint32 reserved; + [switch_is(version)] smbXsrv_openU info; + } smbXsrv_openB; + + void smbXsrv_open_decode( + [in] smbXsrv_openB blob + ); } diff --git a/source3/smbd/files.c b/source3/smbd/files.c index b5be083..0929d99 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -27,33 +27,6 @@ #define FILE_HANDLE_OFFSET 0x1000 -/**************************************************************************** - Return a unique number identifying this fsp over the life of this pid, - and try to make it as globally unique as possible. - See bug #8995 for the details. -****************************************************************************/ - -static unsigned long get_gen_count(struct smbd_server_connection *sconn) -{ - /* - * While fsp->fh->gen_id is 'unsigned long' currently - * (which might by 8 bytes), - * there's some oplock code which truncates it to - * uint32_t(using IVAL()). - */ - if (sconn->file_gen_counter == 0) { - sconn->file_gen_counter = generate_random(); - } - sconn->file_gen_counter += 1; - if (sconn->file_gen_counter >= UINT32_MAX) { - sconn->file_gen_counter = 0; - } - if (sconn->file_gen_counter == 0) { - sconn->file_gen_counter += 1; - } - return sconn->file_gen_counter; -} - /** * create new fsp to be used for file_new or a durable handle reconnect */ @@ -110,7 +83,6 @@ NTSTATUS file_new(struct smb_request *req, connection_struct *conn, files_struct **result) { struct smbd_server_connection *sconn = conn->sconn; - int i = -1; files_struct *fsp; NTSTATUS status; @@ -121,41 +93,21 @@ NTSTATUS file_new(struct smb_request *req, connection_struct *conn, GetTimeOfDay(&fsp->open_time); - if (sconn->file_bmap != NULL) { - - /* - * we want to give out file handles differently on each new - * connection because of a common bug in MS clients where they - * try to reuse a file descriptor from an earlier smb - * connection. This code increases the chance that the errant - * client will get an error rather than causing corruption - */ - if (sconn->first_file == 0) { - sconn->first_file = (getpid() ^ (int)time(NULL)); - sconn->first_file %= sconn->real_max_open_files; - } + if (sconn->conn) { + struct smbXsrv_open *op = NULL; + NTTIME now = timeval_to_nttime(&fsp->open_time); - /* TODO: Port the id-tree implementation from Samba4 */ - - i = bitmap_find(sconn->file_bmap, sconn->first_file); - if (i == -1) { - DEBUG(0,("ERROR! Out of file structures\n")); - /* - * TODO: We have to unconditionally return a DOS error - * here, W2k3 even returns ERRDOS/ERRnofids for - * ntcreate&x with NTSTATUS negotiated - */ - return NT_STATUS_TOO_MANY_OPENED_FILES; + status = smbXsrv_open_create(sconn->conn, + conn->session_info, + now, &op); + if (!NT_STATUS_IS_OK(status)) { + file_free(NULL, fsp); + return status; } - - sconn->first_file = (i+1) % (sconn->real_max_open_files); - - bitmap_set(sconn->file_bmap, i); - - fsp->fnum = i + FILE_HANDLE_OFFSET; - SMB_ASSERT(fsp->fnum < 65536); - - fsp->fh->gen_id = get_gen_count(sconn); + fsp->op = op; + op->compat = fsp; + fsp->fnum = op->local_id; + fsp->fh->gen_id = smbXsrv_open_hash(op); } /* @@ -170,8 +122,8 @@ NTSTATUS file_new(struct smb_request *req, connection_struct *conn, return status; } - DEBUG(5,("allocated file structure %d, %s (%u used)\n", - i, fsp_fnum_dbg(fsp), (unsigned int)sconn->num_files)); + DEBUG(5,("allocated file structure %s (%u used)\n", + fsp_fnum_dbg(fsp), (unsigned int)sconn->num_files)); if (req != NULL) { req->chain_fsp = fsp; @@ -273,11 +225,6 @@ bool file_init(struct smbd_server_connection *sconn) sconn->real_max_open_files = files_max_open_fds; - sconn->file_bmap = bitmap_talloc(sconn, sconn->real_max_open_files); - if (!sconn->file_bmap) { - return false; - } - return true; } @@ -540,9 +487,10 @@ void file_free(struct smb_request *req, files_struct *fsp) /* Ensure this event will never fire. */ TALLOC_FREE(fsp->update_write_time_event); - if (sconn->file_bmap != NULL) { - bitmap_clear(sconn->file_bmap, fsp->fnum - FILE_HANDLE_OFFSET); + if (fsp->op != NULL) { + fsp->op->compat = NULL; } + TALLOC_FREE(fsp->op); if ((req != NULL) && (fsp == req->chain_fsp)) { req->chain_fsp = NULL; @@ -571,36 +519,14 @@ void file_free(struct smb_request *req, files_struct *fsp) } /**************************************************************************** - Get an fsp from a 16 bit fnum. -****************************************************************************/ - -static struct files_struct *file_fnum(struct smbd_server_connection *sconn, - uint16 fnum) -{ - files_struct *fsp; - int count=0; - - for (fsp=sconn->files; fsp; fsp=fsp->next, count++) { - if (fsp->fnum == FNUM_FIELD_INVALID) { - continue; - } - - if (fsp->fnum == fnum) { - if (count > 10) { - DLIST_PROMOTE(sconn->files, fsp); - } - return fsp; - } - } - return NULL; -} - -/**************************************************************************** Get an fsp from a packet given a 16 bit fnum. ****************************************************************************/ files_struct *file_fsp(struct smb_request *req, uint16 fid) { + struct smbXsrv_open *op; + NTSTATUS status; + NTTIME now = 0; files_struct *fsp; if (req == NULL) { @@ -620,59 +546,49 @@ files_struct *file_fsp(struct smb_request *req, uint16 fid) return req->chain_fsp; } - fsp = file_fnum(req->sconn, fid); + if (req->sconn->conn == NULL) { + return NULL; + } + + now = timeval_to_nttime(&req->request_time); + + status = smb1srv_open_lookup(req->sconn->conn, + fid, now, &op); + if (!NT_STATUS_IS_OK(status)) { + return NULL; + } + + fsp = op->compat; if (fsp != NULL) { req->chain_fsp = fsp; } return fsp; } -uint64_t fsp_persistent_id(const struct files_struct *fsp) -{ - uint64_t persistent_id; - - /* - * This calculates a number that is most likely - * globally unique. In future we will have a database - * to make it completely unique. - * - * 32-bit random gen_id - * 16-bit truncated open_time - * 16-bit fnum (valatile_id) - */ - persistent_id = fsp->fh->gen_id & UINT32_MAX; - persistent_id <<= 16; - persistent_id &= 0x0000FFFFFFFF0000LLU; - persistent_id |= fsp->open_time.tv_usec & UINT16_MAX; - persistent_id <<= 16; - persistent_id &= 0xFFFFFFFFFFFF0000LLU; - persistent_id |= fsp->fnum & UINT16_MAX; - - return persistent_id; -} - struct files_struct *file_fsp_smb2(struct smbd_smb2_request *smb2req, uint64_t persistent_id, uint64_t volatile_id) { + struct smbXsrv_open *op; + NTSTATUS status; + NTTIME now = 0; struct files_struct *fsp; - uint64_t fsp_persistent; if (smb2req->compat_chain_fsp != NULL) { return smb2req->compat_chain_fsp; } - if (volatile_id > UINT16_MAX) { - return NULL; - } + now = timeval_to_nttime(&smb2req->request_time); - fsp = file_fnum(smb2req->sconn, (uint16_t)volatile_id); - if (fsp == NULL) { + status = smb2srv_open_lookup(smb2req->sconn->conn, + persistent_id, volatile_id, + now, &op); + if (!NT_STATUS_IS_OK(status)) { return NULL; } - fsp_persistent = fsp_persistent_id(fsp); - if (persistent_id != fsp_persistent) { + fsp = op->compat; + if (fsp == NULL) { return NULL; } diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index b93b373..6c1efaf 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -354,8 +354,20 @@ struct smbXsrv_connection { uint64_t smbd_idle_profstamp; + /* + * this session_table is used for SMB1 and SMB2, + */ struct smbXsrv_session_table *session_table; + /* + * this tcon_table is only used for SMB1. + */ struct smbXsrv_tcon_table *tcon_table; + /* + * this open_table is used for SMB1 and SMB2, + * because we have a global sconn->real_max_open_files + * limit. + */ + struct smbXsrv_open_table *open_table; }; NTSTATUS smbXsrv_version_global_init(const struct server_id *server_id); @@ -407,6 +419,25 @@ NTSTATUS smb2srv_tcon_lookup(struct smbXsrv_session *session, struct smbXsrv_tcon **tcon); NTSTATUS smb2srv_tcon_disconnect_all(struct smbXsrv_session *session); +NTSTATUS smbXsrv_open_global_init(void); +NTSTATUS smbXsrv_open_create(struct smbXsrv_connection *conn, + struct auth_session_info *session_info, + NTTIME now, + struct smbXsrv_open **_open); +uint32_t smbXsrv_open_hash(struct smbXsrv_open *_open); +NTSTATUS smbXsrv_open_update(struct smbXsrv_open *_open); +NTSTATUS smbXsrv_open_close(struct smbXsrv_open *op, NTTIME now); +NTSTATUS smb1srv_open_table_init(struct smbXsrv_connection *conn); +NTSTATUS smb1srv_open_lookup(struct smbXsrv_connection *conn, + uint16_t fnum, NTTIME now, + struct smbXsrv_open **_open); +NTSTATUS smb2srv_open_table_init(struct smbXsrv_connection *conn); +NTSTATUS smb2srv_open_lookup(struct smbXsrv_connection *conn, + uint64_t persistent_id, + uint64_t volatile_id, + NTTIME now, + struct smbXsrv_open **_open); + struct smbd_smb2_request { struct smbd_smb2_request *prev, *next; @@ -532,11 +563,8 @@ struct smbd_server_connection { size_t num_files; struct files_struct *files; - struct bitmap *file_bmap; int real_max_open_files; struct fsp_singleton_cache fsp_fi_cache; - unsigned long file_gen_counter; - int first_file; struct pending_message_list *deferred_open_queue; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index a437a98..55a125f 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -3211,6 +3211,11 @@ NTSTATUS smbXsrv_connection_init_tables(struct smbXsrv_connection *conn, if (!NT_STATUS_IS_OK(status)) { return status; } + + status = smb2srv_open_table_init(conn); + if (!NT_STATUS_IS_OK(status)) { + return status; + } } else { status = smb1srv_session_table_init(conn); if (!NT_STATUS_IS_OK(status)) { @@ -3221,6 +3226,11 @@ NTSTATUS smbXsrv_connection_init_tables(struct smbXsrv_connection *conn, if (!NT_STATUS_IS_OK(status)) { return status; } + + status = smb1srv_open_table_init(conn); + if (!NT_STATUS_IS_OK(status)) { + return status; + } } return NT_STATUS_OK; diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index 3efbe8f..35a677c 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -386,7 +386,6 @@ void file_sync_all(connection_struct *conn); void fsp_free(files_struct *fsp); void file_free(struct smb_request *req, files_struct *fsp); files_struct *file_fsp(struct smb_request *req, uint16 fid); -uint64_t fsp_persistent_id(const struct files_struct *fsp); struct files_struct *file_fsp_smb2(struct smbd_smb2_request *smb2req, uint64_t persistent_id, uint64_t volatile_id); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index b4b5ae3..94a2510 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1443,6 +1443,10 @@ extern void build_options(bool screen); DEBUG(0, ("ERROR: file_init_global() failed\n")); return -1; } + status = smbXsrv_open_global_init(); + if (!NT_STATUS_IS_OK(status)) { + exit(1); + } /* This MUST be done before start_epmd() because otherwise * start_epmd() forks and races against dcesrv_ep_setup() to diff --git a/source3/smbd/smb2_break.c b/source3/smbd/smb2_break.c index 95e1d8b..77f4709 100644 --- a/source3/smbd/smb2_break.c +++ b/source3/smbd/smb2_break.c @@ -237,7 +237,6 @@ void send_break_message_smb2(files_struct *fsp, int level) SMB2_OPLOCK_LEVEL_II : SMB2_OPLOCK_LEVEL_NONE; NTSTATUS status; - uint64_t fsp_persistent = fsp_persistent_id(fsp); DEBUG(10,("send_break_message_smb2: sending oplock break " -- Samba Shared Repository