2002-07-13 09:13:02 +04:00
/*
Unix SMB / CIFS implementation .
SMB client library implementation ( server cache )
Copyright ( C ) Andrew Tridgell 1998
Copyright ( C ) Richard Sharpe 2000
Copyright ( C ) John Terpstra 2000
Copyright ( C ) Tom Jansen ( Ninja ISD ) 2002
2009-11-22 00:52:12 +03:00
2002-07-13 09:13:02 +04:00
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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2002-07-13 09:13:02 +04:00
( at your option ) any later version .
2009-11-22 00:52:12 +03:00
2002-07-13 09:13:02 +04:00
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 .
2009-11-22 00:52:12 +03:00
2002-07-13 09:13:02 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2002-07-13 09:13:02 +04:00
*/
# include "includes.h"
2008-02-28 19:23:20 +03:00
# include "libsmbclient.h"
# include "libsmb_internal.h"
2006-12-20 04:10:04 +03:00
2002-07-13 09:13:02 +04:00
/*
* Structure we use if internal caching mechanism is used
* nothing fancy here .
*/
struct smbc_server_cache {
char * server_name ;
char * share_name ;
char * workgroup ;
char * username ;
SMBCSRV * server ;
2009-11-22 00:52:12 +03:00
2002-07-13 09:13:02 +04:00
struct smbc_server_cache * next , * prev ;
} ;
2008-03-02 04:44:21 +03:00
2002-07-13 09:13:02 +04:00
/*
* Add a new connection to the server cache .
* This function is only used if the external cache is not enabled
*/
2008-02-28 19:23:20 +03:00
int
SMBC_add_cached_server ( SMBCCTX * context ,
SMBCSRV * newsrv ,
const char * server ,
const char * share ,
const char * workgroup ,
const char * username )
2002-07-13 09:13:02 +04:00
{
struct smbc_server_cache * srvcache = NULL ;
2009-11-22 00:52:12 +03:00
2004-12-07 21:25:53 +03:00
if ( ! ( srvcache = SMB_MALLOC_P ( struct smbc_server_cache ) ) ) {
2002-07-13 09:13:02 +04:00
errno = ENOMEM ;
DEBUG ( 3 , ( " Not enough space for server cache allocation \n " ) ) ;
return 1 ;
}
2009-11-22 00:52:12 +03:00
2002-07-13 09:13:02 +04:00
ZERO_STRUCTP ( srvcache ) ;
2009-11-22 00:52:12 +03:00
2005-06-25 00:25:18 +04:00
srvcache - > server = newsrv ;
2009-11-22 00:52:12 +03:00
2004-12-07 21:25:53 +03:00
srvcache - > server_name = SMB_STRDUP ( server ) ;
2002-07-13 09:13:02 +04:00
if ( ! srvcache - > server_name ) {
errno = ENOMEM ;
goto failed ;
}
2009-11-22 00:52:12 +03:00
2004-12-07 21:25:53 +03:00
srvcache - > share_name = SMB_STRDUP ( share ) ;
2002-07-13 09:13:02 +04:00
if ( ! srvcache - > share_name ) {
errno = ENOMEM ;
goto failed ;
}
2009-11-22 00:52:12 +03:00
2004-12-07 21:25:53 +03:00
srvcache - > workgroup = SMB_STRDUP ( workgroup ) ;
2002-07-13 09:13:02 +04:00
if ( ! srvcache - > workgroup ) {
errno = ENOMEM ;
goto failed ;
}
2009-11-22 00:52:12 +03:00
2004-12-07 21:25:53 +03:00
srvcache - > username = SMB_STRDUP ( username ) ;
2002-07-13 09:13:02 +04:00
if ( ! srvcache - > username ) {
errno = ENOMEM ;
goto failed ;
}
2009-11-22 00:52:12 +03:00
2008-03-04 02:13:33 +03:00
DLIST_ADD ( context - > internal - > server_cache , srvcache ) ;
2002-07-13 09:13:02 +04:00
return 0 ;
2009-11-22 00:52:12 +03:00
2008-03-02 04:44:21 +03:00
failed :
2002-07-13 09:13:02 +04:00
SAFE_FREE ( srvcache - > server_name ) ;
SAFE_FREE ( srvcache - > share_name ) ;
SAFE_FREE ( srvcache - > workgroup ) ;
SAFE_FREE ( srvcache - > username ) ;
2006-03-08 09:39:33 +03:00
SAFE_FREE ( srvcache ) ;
2009-11-22 00:52:12 +03:00
2002-07-13 09:13:02 +04:00
return 1 ;
}
/*
* Search the server cache for a server
2005-06-02 00:17:16 +04:00
* returns server handle on success , NULL on error ( not found )
2002-07-13 09:13:02 +04:00
* This function is only used if the external cache is not enabled
*/
2008-02-28 19:23:20 +03:00
SMBCSRV *
SMBC_get_cached_server ( SMBCCTX * context ,
const char * server ,
const char * share ,
const char * workgroup ,
const char * user )
2002-07-13 09:13:02 +04:00
{
struct smbc_server_cache * srv = NULL ;
2009-11-22 00:52:12 +03:00
2002-07-13 09:13:02 +04:00
/* Search the cache lines */
2008-03-04 02:13:33 +03:00
for ( srv = context - > internal - > server_cache ; srv ; srv = srv - > next ) {
2009-11-22 00:52:12 +03:00
2002-07-13 09:13:02 +04:00
if ( strcmp ( server , srv - > server_name ) = = 0 & &
strcmp ( workgroup , srv - > workgroup ) = = 0 & &
2005-03-11 02:41:19 +03:00
strcmp ( user , srv - > username ) = = 0 ) {
2009-11-22 00:52:12 +03:00
2005-03-11 02:41:19 +03:00
/* If the share name matches, we're cool */
if ( strcmp ( share , srv - > share_name ) = = 0 ) {
return srv - > server ;
}
2009-11-22 00:52:12 +03:00
2005-03-11 02:41:19 +03:00
/*
* We only return an empty share name or the attribute
* server on an exact match ( which would have been
* caught above ) .
*/
if ( * share = = ' \0 ' | | strcmp ( share , " *IPC$ " ) = = 0 )
continue ;
2009-11-22 00:52:12 +03:00
2005-03-11 02:41:19 +03:00
/*
* Never return an empty share name or the attribute
* server if it wasn ' t what was requested .
*/
if ( * srv - > share_name = = ' \0 ' | |
strcmp ( srv - > share_name , " *IPC$ " ) = = 0 )
continue ;
2009-11-22 00:52:12 +03:00
2005-03-11 02:41:19 +03:00
/*
* If we ' re only allowing one share per server , then
* a connection to the server ( other than the
* attribute server connection ) is cool .
*/
2008-03-04 02:13:33 +03:00
if ( smbc_getOptionOneSharePerServer ( context ) ) {
2010-01-03 20:46:57 +03:00
NTSTATUS status ;
2005-03-11 02:41:19 +03:00
/*
* The currently connected share name
* doesn ' t match the requested share , so
* disconnect from the current share .
*/
2010-01-03 20:46:57 +03:00
status = cli_tdis ( srv - > server - > cli ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2005-03-11 02:41:19 +03:00
/* Sigh. Couldn't disconnect. */
2006-07-11 22:01:26 +04:00
cli_shutdown ( srv - > server - > cli ) ;
srv - > server - > cli = NULL ;
2008-03-04 02:13:33 +03:00
smbc_getFunctionRemoveCachedServer ( context ) ( context , srv - > server ) ;
2005-03-11 02:41:19 +03:00
continue ;
}
2009-11-22 00:52:12 +03:00
2006-03-01 04:48:33 +03:00
/*
* Save the new share name . We ' ve
* disconnected from the old share , and are
* about to connect to the new one .
*/
2006-03-01 04:41:52 +03:00
SAFE_FREE ( srv - > share_name ) ;
srv - > share_name = SMB_STRDUP ( share ) ;
if ( ! srv - > share_name ) {
/* Out of memory. */
2006-07-11 22:01:26 +04:00
cli_shutdown ( srv - > server - > cli ) ;
srv - > server - > cli = NULL ;
2008-03-04 02:13:33 +03:00
smbc_getFunctionRemoveCachedServer ( context ) ( context , srv - > server ) ;
2006-03-01 04:41:52 +03:00
continue ;
}
2009-11-22 00:52:12 +03:00
2005-03-11 02:41:19 +03:00
return srv - > server ;
}
}
2002-07-13 09:13:02 +04:00
}
2009-11-22 00:52:12 +03:00
2002-07-13 09:13:02 +04:00
return NULL ;
}
/*
* Search the server cache for a server and remove it
* returns 0 on success
* This function is only used if the external cache is not enabled
*/
2008-02-28 19:23:20 +03:00
int
SMBC_remove_cached_server ( SMBCCTX * context ,
SMBCSRV * server )
2002-07-13 09:13:02 +04:00
{
struct smbc_server_cache * srv = NULL ;
2009-11-22 00:52:12 +03:00
2008-03-04 02:13:33 +03:00
for ( srv = context - > internal - > server_cache ; srv ; srv = srv - > next ) {
2002-07-13 09:13:02 +04:00
if ( server = = srv - > server ) {
2009-11-22 00:52:12 +03:00
2002-07-13 09:13:02 +04:00
/* remove this sucker */
2008-03-04 02:13:33 +03:00
DLIST_REMOVE ( context - > internal - > server_cache , srv ) ;
2002-07-13 09:13:02 +04:00
SAFE_FREE ( srv - > server_name ) ;
SAFE_FREE ( srv - > share_name ) ;
SAFE_FREE ( srv - > workgroup ) ;
SAFE_FREE ( srv - > username ) ;
SAFE_FREE ( srv ) ;
return 0 ;
}
}
/* server not found */
return 1 ;
}
/*
* Try to remove all the servers in cache
* returns 1 on failure and 0 if all servers could be removed .
*/
2008-02-28 19:23:20 +03:00
int
SMBC_purge_cached_servers ( SMBCCTX * context )
2002-07-13 09:13:02 +04:00
{
2004-03-19 19:22:47 +03:00
struct smbc_server_cache * srv ;
struct smbc_server_cache * next ;
2002-07-13 09:13:02 +04:00
int could_not_purge_all = 0 ;
2009-11-22 00:52:12 +03:00
2008-03-04 02:13:33 +03:00
for ( srv = context - > internal - > server_cache ,
2008-02-28 19:23:20 +03:00
next = ( srv ? srv - > next : NULL ) ;
2004-03-19 19:22:47 +03:00
srv ;
2008-02-28 19:23:20 +03:00
srv = next ,
next = ( srv ? srv - > next : NULL ) ) {
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
if ( SMBC_remove_unused_server ( context , srv - > server ) ) {
2002-07-13 09:13:02 +04:00
/* could not be removed */
could_not_purge_all = 1 ;
}
}
return could_not_purge_all ;
}