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 <[email protected]>
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 <[email protected]>
metze
Autobuild-User(master): Stefan Metzmacher <[email protected]>
Autobuild-Date(master): Fri Jun 29 21:01:11 CEST 2012 on sn-devel-104
commit f7762e2730aa4e2fe37043b56e0413983b484108
Author: Stefan Metzmacher <[email protected]>
Date: Mon Feb 6 23:06:41 2012 +0100
s3:smbd: add smbXsrv_open* infrastructure
Pair-Programmed-With: Michael Adam <[email protected]>
metze
commit 9c8e2b5af0039a8bae216781df008be10c0f0835
Author: Stefan Metzmacher <[email protected]>
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