• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/source3/libsmb/
1/*
2   Unix SMB/CIFS implementation.
3   SMB client library implementation (server cache)
4   Copyright (C) Andrew Tridgell 1998
5   Copyright (C) Richard Sharpe 2000
6   Copyright (C) John Terpstra 2000
7   Copyright (C) Tom Jansen (Ninja ISD) 2002
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 3 of the License, or
12   (at your option) any later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program.  If not, see <http://www.gnu.org/licenses/>.
21*/
22
23#include "includes.h"
24#include "libsmbclient.h"
25#include "libsmb_internal.h"
26
27/*
28 * Structure we use if internal caching mechanism is used
29 * nothing fancy here.
30 */
31struct smbc_server_cache {
32	char *server_name;
33	char *share_name;
34	char *workgroup;
35	char *username;
36	SMBCSRV *server;
37
38	struct smbc_server_cache *next, *prev;
39};
40
41
42
43/*
44 * Add a new connection to the server cache.
45 * This function is only used if the external cache is not enabled
46 */
47int
48SMBC_add_cached_server(SMBCCTX * context,
49                       SMBCSRV * newsrv,
50                       const char * server,
51                       const char * share,
52                       const char * workgroup,
53                       const char * username)
54{
55	struct smbc_server_cache * srvcache = NULL;
56
57	if (!(srvcache = SMB_MALLOC_P(struct smbc_server_cache))) {
58		errno = ENOMEM;
59		DEBUG(3, ("Not enough space for server cache allocation\n"));
60		return 1;
61	}
62
63	ZERO_STRUCTP(srvcache);
64
65	srvcache->server = newsrv;
66
67	srvcache->server_name = SMB_STRDUP(server);
68	if (!srvcache->server_name) {
69		errno = ENOMEM;
70		goto failed;
71	}
72
73	srvcache->share_name = SMB_STRDUP(share);
74	if (!srvcache->share_name) {
75		errno = ENOMEM;
76		goto failed;
77	}
78
79	srvcache->workgroup = SMB_STRDUP(workgroup);
80	if (!srvcache->workgroup) {
81		errno = ENOMEM;
82		goto failed;
83	}
84
85	srvcache->username = SMB_STRDUP(username);
86	if (!srvcache->username) {
87		errno = ENOMEM;
88		goto failed;
89	}
90
91	DLIST_ADD(context->internal->server_cache, srvcache);
92	return 0;
93
94failed:
95	SAFE_FREE(srvcache->server_name);
96	SAFE_FREE(srvcache->share_name);
97	SAFE_FREE(srvcache->workgroup);
98	SAFE_FREE(srvcache->username);
99	SAFE_FREE(srvcache);
100
101	return 1;
102}
103
104
105
106/*
107 * Search the server cache for a server
108 * returns server handle on success, NULL on error (not found)
109 * This function is only used if the external cache is not enabled
110 */
111SMBCSRV *
112SMBC_get_cached_server(SMBCCTX * context,
113                       const char * server,
114                       const char * share,
115                       const char * workgroup,
116                       const char * user)
117{
118	struct smbc_server_cache * srv = NULL;
119
120	/* Search the cache lines */
121	for (srv = context->internal->server_cache; srv; srv = srv->next) {
122
123		if (strcmp(server,srv->server_name)  == 0 &&
124		    strcmp(workgroup,srv->workgroup) == 0 &&
125		    strcmp(user, srv->username)  == 0) {
126
127                        /* If the share name matches, we're cool */
128                        if (strcmp(share, srv->share_name) == 0) {
129                                return srv->server;
130                        }
131
132                        /*
133                         * We only return an empty share name or the attribute
134                         * server on an exact match (which would have been
135                         * caught above).
136                         */
137                        if (*share == '\0' || strcmp(share, "*IPC$") == 0)
138                                continue;
139
140                        /*
141                         * Never return an empty share name or the attribute
142                         * server if it wasn't what was requested.
143                         */
144                        if (*srv->share_name == '\0' ||
145                            strcmp(srv->share_name, "*IPC$") == 0)
146                                continue;
147
148                        /*
149                         * If we're only allowing one share per server, then
150                         * a connection to the server (other than the
151                         * attribute server connection) is cool.
152                         */
153                        if (smbc_getOptionOneSharePerServer(context)) {
154                                /*
155                                 * The currently connected share name
156                                 * doesn't match the requested share, so
157                                 * disconnect from the current share.
158                                 */
159                                if (! cli_tdis(srv->server->cli)) {
160                                        /* Sigh. Couldn't disconnect. */
161                                        cli_shutdown(srv->server->cli);
162					srv->server->cli = NULL;
163                                        smbc_getFunctionRemoveCachedServer(context)(context, srv->server);
164                                        continue;
165                                }
166
167                                /*
168                                 * Save the new share name.  We've
169                                 * disconnected from the old share, and are
170                                 * about to connect to the new one.
171                                 */
172                                SAFE_FREE(srv->share_name);
173                                srv->share_name = SMB_STRDUP(share);
174                                if (!srv->share_name) {
175                                        /* Out of memory. */
176                                        cli_shutdown(srv->server->cli);
177					srv->server->cli = NULL;
178                                        smbc_getFunctionRemoveCachedServer(context)(context, srv->server);
179                                        continue;
180                                }
181
182
183                                return srv->server;
184                        }
185                }
186	}
187
188	return NULL;
189}
190
191
192/*
193 * Search the server cache for a server and remove it
194 * returns 0 on success
195 * This function is only used if the external cache is not enabled
196 */
197int
198SMBC_remove_cached_server(SMBCCTX * context,
199                          SMBCSRV * server)
200{
201	struct smbc_server_cache * srv = NULL;
202
203	for (srv = context->internal->server_cache; srv; srv = srv->next) {
204		if (server == srv->server) {
205
206			/* remove this sucker */
207			DLIST_REMOVE(context->internal->server_cache, srv);
208			SAFE_FREE(srv->server_name);
209			SAFE_FREE(srv->share_name);
210			SAFE_FREE(srv->workgroup);
211			SAFE_FREE(srv->username);
212			SAFE_FREE(srv);
213			return 0;
214		}
215	}
216	/* server not found */
217	return 1;
218}
219
220
221/*
222 * Try to remove all the servers in cache
223 * returns 1 on failure and 0 if all servers could be removed.
224 */
225int
226SMBC_purge_cached_servers(SMBCCTX * context)
227{
228	struct smbc_server_cache * srv;
229	struct smbc_server_cache * next;
230	int could_not_purge_all = 0;
231
232	for (srv = context->internal->server_cache,
233                     next = (srv ? srv->next :NULL);
234             srv;
235             srv = next,
236                     next = (srv ? srv->next : NULL)) {
237
238		if (SMBC_remove_unused_server(context, srv->server)) {
239			/* could not be removed */
240			could_not_purge_all = 1;
241		}
242	}
243	return could_not_purge_all;
244}
245