summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2009-03-12 17:59:24 -0700
committerJeremy Allison <jra@samba.org>2009-03-12 17:59:24 -0700
commite5136e984922570ce9992c642c340dd3e937fc4e (patch)
tree90acd50687e0adf2352eb1663b4934f01df0a9fc
parentbace42d586f2e4364e5b66ccc80a0b19749b5e1c (diff)
downloadsamba-e5136e984922570ce9992c642c340dd3e937fc4e.tar.gz
samba-e5136e984922570ce9992c642c340dd3e937fc4e.tar.bz2
samba-e5136e984922570ce9992c642c340dd3e937fc4e.zip
Remove the static "struct client_connection" mess which is part of
the problem that stops libsmbclient being thread safe. Subsidiary DFS connections are now hung off a list inside the cli_state struct. Much more to do in order to get libsmbclient to thread safety, but this is a good start. Jeremy.
-rw-r--r--source3/client/client.c22
-rw-r--r--source3/include/client.h7
-rw-r--r--source3/include/proto.h4
-rw-r--r--source3/lib/netapi/cm.c28
-rw-r--r--source3/libsmb/clidfs.c162
-rw-r--r--source3/libsmb/clientgen.c28
-rw-r--r--source3/libsmb/clilist.c5
7 files changed, 117 insertions, 139 deletions
diff --git a/source3/client/client.c b/source3/client/client.c
index aaa9e35d96..6491f39ed0 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -1419,7 +1419,7 @@ static bool do_altname(const char *name)
static int cmd_quit(void)
{
- cli_cm_shutdown();
+ cli_shutdown(cli);
exit(0);
/* NOTREACHED */
return 0;
@@ -1714,7 +1714,7 @@ static int do_put(const char *rname, const char *lname, bool reput)
}
if (f == x_stdin) {
- cli_cm_shutdown();
+ cli_shutdown(cli);
exit(0);
}
@@ -3815,7 +3815,7 @@ static int cmd_logon(void)
static int cmd_list_connect(void)
{
- cli_cm_display();
+ cli_cm_display(cli);
return 0;
}
@@ -4526,7 +4526,7 @@ static int process(const char *base_directory)
if (base_directory && *base_directory) {
rc = do_cd(base_directory);
if (rc) {
- cli_cm_shutdown();
+ cli_shutdown(cli);
return rc;
}
}
@@ -4537,7 +4537,7 @@ static int process(const char *base_directory)
process_stdin();
}
- cli_cm_shutdown();
+ cli_shutdown(cli);
return rc;
}
@@ -4568,7 +4568,7 @@ static int do_host_query(const char *query_host)
/* Workgroups simply don't make sense over anything
else but port 139... */
- cli_cm_shutdown();
+ cli_shutdown(cli);
cli = cli_cm_open(talloc_tos(), NULL,
query_host, "IPC$", true, smb_encrypt,
max_protocol, 139, name_type);
@@ -4581,7 +4581,7 @@ static int do_host_query(const char *query_host)
list_servers(lp_workgroup());
- cli_cm_shutdown();
+ cli_shutdown(cli);
return(0);
}
@@ -4609,14 +4609,14 @@ static int do_tar_op(const char *base_directory)
if (base_directory && *base_directory) {
ret = do_cd(base_directory);
if (ret) {
- cli_cm_shutdown();
+ cli_shutdown(cli);
return ret;
}
}
ret=process_tar();
- cli_cm_shutdown();
+ cli_shutdown(cli);
return(ret);
}
@@ -4663,12 +4663,12 @@ static int do_message_op(struct user_auth_info *auth_info)
if (!cli_session_request(cli, &calling, &called)) {
d_printf("session request failed\n");
- cli_cm_shutdown();
+ cli_shutdown(cli);
return 1;
}
send_message(get_cmdline_auth_info_username(auth_info));
- cli_cm_shutdown();
+ cli_shutdown(cli);
return 0;
}
diff --git a/source3/include/client.h b/source3/include/client.h
index 646d54aa05..eae22fdbce 100644
--- a/source3/include/client.h
+++ b/source3/include/client.h
@@ -167,6 +167,10 @@ struct smb_trans_enc_state {
};
struct cli_state {
+ /**
+ * A list of subsidiary connections for DFS.
+ */
+ struct cli_state *prev, *next;
int port;
int fd;
/* Last read or write error. */
@@ -276,6 +280,9 @@ struct cli_state {
* chained async_req.
*/
struct cli_request *chain_accumulator;
+
+ /* Where (if anywhere) this is mounted under DFS. */
+ char *dfs_mountpoint;
};
typedef struct file_info {
diff --git a/source3/include/proto.h b/source3/include/proto.h
index c8a066fa36..40024c5194 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -2355,7 +2355,6 @@ NTSTATUS cli_cm_force_encryption(struct cli_state *c,
const char *password,
const char *domain,
const char *sharename);
-const char *cli_cm_get_mntpoint(struct cli_state *c);
struct cli_state *cli_cm_open(TALLOC_CTX *ctx,
struct cli_state *referring_cli,
const char *server,
@@ -2365,8 +2364,7 @@ struct cli_state *cli_cm_open(TALLOC_CTX *ctx,
int max_protocol,
int port,
int name_type);
-void cli_cm_shutdown(void);
-void cli_cm_display(void);
+void cli_cm_display(const struct cli_state *c);
void cli_cm_set_credentials(struct user_auth_info *auth_info);
void cli_cm_set_port(int port_number);
void cli_cm_set_dest_name_type(int type);
diff --git a/source3/lib/netapi/cm.c b/source3/lib/netapi/cm.c
index 233255fed4..43ebed6c22 100644
--- a/source3/lib/netapi/cm.c
+++ b/source3/lib/netapi/cm.c
@@ -73,19 +73,10 @@ static WERROR libnetapi_open_ipc_connection(struct libnetapi_ctx *ctx,
/********************************************************************
********************************************************************/
-WERROR libnetapi_shutdown_cm(struct libnetapi_ctx *ctx)
-{
- cli_cm_shutdown();
-
- return WERR_OK;
-}
-
-/********************************************************************
-********************************************************************/
-
struct client_pipe_connection {
struct client_pipe_connection *prev, *next;
struct rpc_pipe_client *pipe;
+ struct cli_state *cli;
};
static struct client_pipe_connection *pipe_connections;
@@ -93,6 +84,20 @@ static struct client_pipe_connection *pipe_connections;
/********************************************************************
********************************************************************/
+WERROR libnetapi_shutdown_cm(struct libnetapi_ctx *ctx)
+{
+ struct client_pipe_connection *p;
+
+ for (p = pipe_connections; p; p = p->next) {
+ cli_shutdown(p->cli);
+ }
+
+ return WERR_OK;
+}
+
+/********************************************************************
+********************************************************************/
+
static NTSTATUS pipe_cm_find(struct cli_state *cli,
const struct ndr_syntax_id *interface,
struct rpc_pipe_client **presult)
@@ -138,6 +143,7 @@ static NTSTATUS pipe_cm_connect(TALLOC_CTX *mem_ctx,
return status;
}
+ p->cli = cli;
DLIST_ADD(pipe_connections, p);
*presult = p->pipe;
@@ -193,5 +199,3 @@ WERROR libnetapi_open_pipe(struct libnetapi_ctx *ctx,
return WERR_OK;
}
-
-
diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c
index 1153d8dc89..8544d5520e 100644
--- a/source3/libsmb/clidfs.c
+++ b/source3/libsmb/clidfs.c
@@ -3,7 +3,7 @@
client connect/disconnect routines
Copyright (C) Andrew Tridgell 1994-1998
Copyright (C) Gerald (Jerry) Carter 2004
- Copyright (C) Jeremy Allison 2007
+ Copyright (C) Jeremy Allison 2007-2009
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
@@ -32,12 +32,6 @@
as a separator when looking at the pathname part.... JRA.
********************************************************************/
-struct client_connection {
- struct client_connection *prev, *next;
- struct cli_state *cli;
- char *mount;
-};
-
static struct cm_cred_struct {
char *username;
char *password;
@@ -49,8 +43,6 @@ static struct cm_cred_struct {
static void cm_set_password(const char *newpass);
-static struct client_connection *connections;
-
static bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
struct cli_state *cli,
const char *sharename,
@@ -96,7 +88,7 @@ NTSTATUS cli_cm_force_encryption(struct cli_state *c,
return status;
}
-
+
/********************************************************************
Return a connection to a server.
********************************************************************/
@@ -301,52 +293,20 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx,
/****************************************************************************
****************************************************************************/
-static void cli_cm_set_mntpoint(struct cli_state *c, const char *mnt)
-{
- struct client_connection *p;
- int i;
-
- for (p=connections,i=0; p; p=p->next,i++) {
- if (strequal(p->cli->desthost, c->desthost) &&
- strequal(p->cli->share, c->share)) {
- break;
- }
- }
-
- if (p) {
- char *name = clean_name(NULL, mnt);
- if (!name) {
- return;
- }
- TALLOC_FREE(p->mount);
- p->mount = talloc_strdup(p, name);
- TALLOC_FREE(name);
- }
-}
-
-/****************************************************************************
-****************************************************************************/
-
-const char *cli_cm_get_mntpoint(struct cli_state *c)
+static void cli_set_mntpoint(struct cli_state *cli, const char *mnt)
{
- struct client_connection *p;
- int i;
-
- for (p=connections,i=0; p; p=p->next,i++) {
- if (strequal(p->cli->desthost, c->desthost) &&
- strequal(p->cli->share, c->share)) {
- break;
- }
- }
-
- if (p) {
- return p->mount;
+ char *name = clean_name(NULL, mnt);
+ if (!name) {
+ return;
}
- return NULL;
+ TALLOC_FREE(cli->dfs_mountpoint);
+ cli->dfs_mountpoint = talloc_strdup(cli, name);
+ TALLOC_FREE(name);
}
/********************************************************************
- Add a new connection to the list
+ Add a new connection to the list.
+ referring_cli == NULL means a new initial connection.
********************************************************************/
static struct cli_state *cli_cm_connect(TALLOC_CTX *ctx,
@@ -359,53 +319,62 @@ static struct cli_state *cli_cm_connect(TALLOC_CTX *ctx,
int port,
int name_type)
{
- struct client_connection *node;
-
- /* NB This must be the null context here... JRA. */
- node = TALLOC_ZERO_ARRAY(NULL, struct client_connection, 1);
- if (!node) {
- return NULL;
- }
+ struct cli_state *cli;
- node->cli = do_connect(ctx, server, share,
+ cli = do_connect(ctx, server, share,
show_hdr, force_encrypt, max_protocol,
port, name_type);
- if ( !node->cli ) {
- TALLOC_FREE( node );
+ if (!cli ) {
return NULL;
}
- DLIST_ADD( connections, node );
-
- cli_cm_set_mntpoint(node->cli, "");
+ /* Enter into the list. */
+ if (referring_cli) {
+ DLIST_ADD_END(referring_cli, cli, struct cli_state *);
+ }
if (referring_cli && referring_cli->posix_capabilities) {
uint16 major, minor;
uint32 caplow, caphigh;
- if (cli_unix_extensions_version(node->cli, &major,
+ if (cli_unix_extensions_version(cli, &major,
&minor, &caplow, &caphigh)) {
- cli_set_unix_extensions_capabilities(node->cli,
+ cli_set_unix_extensions_capabilities(cli,
major, minor,
caplow, caphigh);
}
}
- return node->cli;
+ return cli;
}
/********************************************************************
- Return a connection to a server.
+ Return a connection to a server on a particular share.
********************************************************************/
-static struct cli_state *cli_cm_find(const char *server, const char *share)
+static struct cli_state *cli_cm_find(struct cli_state *cli,
+ const char *server,
+ const char *share)
{
- struct client_connection *p;
+ struct cli_state *p;
- for (p=connections; p; p=p->next) {
- if ( strequal(server, p->cli->desthost) &&
- strequal(share,p->cli->share)) {
- return p->cli;
+ if (cli == NULL) {
+ return NULL;
+ }
+
+ /* Search to the start of the list. */
+ for (p = cli; p; p = p->prev) {
+ if (strequal(server, p->desthost) &&
+ strequal(share,p->share)) {
+ return p;
+ }
+ }
+
+ /* Search to the end of the list. */
+ for (p = cli->next; p; p = p->next) {
+ if (strequal(server, p->desthost) &&
+ strequal(share,p->share)) {
+ return p;
}
}
@@ -413,8 +382,7 @@ static struct cli_state *cli_cm_find(const char *server, const char *share)
}
/****************************************************************************
- Open a client connection to a \\server\share. Set's the current *cli
- global variable as a side-effect (but only if the connection is successful).
+ Open a client connection to a \\server\share.
****************************************************************************/
struct cli_state *cli_cm_open(TALLOC_CTX *ctx,
@@ -427,50 +395,28 @@ struct cli_state *cli_cm_open(TALLOC_CTX *ctx,
int port,
int name_type)
{
- struct cli_state *c;
+ /* Try to reuse an existing connection in this list. */
+ struct cli_state *c = cli_cm_find(referring_cli, server, share);
- /* try to reuse an existing connection */
+ if (c) {
+ return c;
+ }
- c = cli_cm_find(server, share);
- if (!c) {
- c = cli_cm_connect(ctx, referring_cli,
+ return cli_cm_connect(ctx, referring_cli,
server, share, show_hdr, force_encrypt,
max_protocol, port, name_type);
- }
-
- return c;
-}
-
-/****************************************************************************
-****************************************************************************/
-
-void cli_cm_shutdown(void)
-{
- struct client_connection *p, *x;
-
- for (p=connections; p;) {
- cli_shutdown(p->cli);
- x = p;
- p = p->next;
-
- TALLOC_FREE(x);
- }
-
- connections = NULL;
- return;
}
/****************************************************************************
****************************************************************************/
-void cli_cm_display(void)
+void cli_cm_display(const struct cli_state *cli)
{
- struct client_connection *p;
int i;
- for ( p=connections,i=0; p; p=p->next,i++ ) {
+ for (i=0; cli; cli = cli->next,i++ ) {
d_printf("%d:\tserver=%s, share=%s\n",
- i, p->cli->desthost, p->cli->share );
+ i, cli->desthost, cli->share );
}
}
@@ -998,7 +944,7 @@ bool cli_resolve_path(TALLOC_CTX *ctx,
return false;
}
- cli_cm_set_mntpoint(*targetcli, newmount);
+ cli_set_mntpoint(*targetcli, newmount);
/* Check for another dfs referral, note that we are not
checking for loops here. */
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index 2983f7771a..7c42da4430 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -425,7 +425,7 @@ void cli_init_creds(struct cli_state *cli, const char *username, const char *dom
}
/****************************************************************************
- Initialise a client structure. Always returns a malloc'ed struct.
+ Initialise a client structure. Always returns a talloc'ed struct.
Set the signing state (used from the command line).
****************************************************************************/
@@ -446,6 +446,11 @@ struct cli_state *cli_initialise_ex(int signing_state)
return NULL;
}
+ cli->dfs_mountpoint = talloc_strdup(cli, "");
+ if (!cli->dfs_mountpoint) {
+ TALLOC_FREE(cli);
+ return NULL;
+ }
cli->port = 0;
cli->fd = -1;
cli->cnum = -1;
@@ -550,6 +555,27 @@ void cli_nt_pipes_close(struct cli_state *cli)
void cli_shutdown(struct cli_state *cli)
{
+ if (cli->prev == NULL) {
+ /*
+ * Possible head of a DFS list,
+ * shutdown all subsidiary DFS
+ * connections.
+ */
+ struct cli_state *p, *next;
+
+ for (p = cli->next; p; p = next) {
+ next = p->next;
+ cli_shutdown(p);
+ }
+ } else {
+ /*
+ * We're a subsidiary connection.
+ * Just remove ourselves from the
+ * DFS list.
+ */
+ DLIST_REMOVE(cli->prev, cli);
+ }
+
cli_nt_pipes_close(cli);
/*
diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c
index e604725493..a84a64794b 100644
--- a/source3/libsmb/clilist.c
+++ b/source3/libsmb/clilist.c
@@ -244,7 +244,6 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
unsigned int param_len, data_len;
uint16 setup;
char *param;
- const char *mnt;
uint32 resume_key = 0;
TALLOC_CTX *frame = talloc_stackframe();
DATA_BLOB last_name_raw = data_blob(NULL, 0);
@@ -457,8 +456,6 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
First = False;
}
- mnt = cli_cm_get_mntpoint( cli );
-
/* see if the server disconnected or the connection otherwise failed */
if (cli_is_error(cli)) {
total_received = -1;
@@ -479,7 +476,7 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
info_level));
break;
}
- fn(mnt,&finfo, Mask, state);
+ fn(cli->dfs_mountpoint, &finfo, Mask, state);
}
}