1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-02 09:47:23 +03:00

moved connection_struct handling code into smbd/conn.c and changed it

to a linked list with bitmap format.
This commit is contained in:
Andrew Tridgell -
parent 27da84b90d
commit b7aaab1b6b
10 changed files with 247 additions and 145 deletions

View File

@ -122,7 +122,7 @@ PASSDB_OBJ = passdb/passdb.o passdb/smbpassfile.o passdb/smbpass.o \
passdb/pass_check.o passdb/ldap.o passdb/nispass.o
SMBD_OBJ1 = smbd/server.o smbd/files.o smbd/chgpasswd.o smbd/connection.o \
smbd/dfree.o smbd/dir.o smbd/password.o \
smbd/dfree.o smbd/dir.o smbd/password.o smbd/conn.o \
smbd/groupname.o smbd/ipc.o smbd/mangle.o \
smbd/message.o smbd/nttrans.o smbd/pipes.o smbd/predict.o \
smbd/quotas.o smbd/reply.o smbd/ssl.o smbd/trans2.o smbd/uid.o

View File

@ -39,12 +39,6 @@
#define SYSLOG_FACILITY LOG_DAEMON
#endif
/* set these to define the limits of the server. NOTE These are on a
per-client basis. Thus any one machine can't connect to more than
MAX_CONNECTIONS services, but any number of machines may connect at
one time. */
#define MAX_CONNECTIONS 127
/* Default size of shared memory used for share mode locking */
#ifndef SHMEM_SIZE
#define SHMEM_SIZE (1024*1024)

View File

@ -1912,6 +1912,17 @@ BOOL check_oem_password(char *user, unsigned char *data,
int new_passwd_size);
BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd, BOOL override);
/*The following definitions come from smbd/conn.c */
void conn_init(void);
int conn_num_open(void);
BOOL conn_snum_used(int snum);
connection_struct *conn_find(int cnum);
connection_struct *conn_new(void);
void conn_close_all(void);
BOOL conn_idle_all(time_t t, int deadtime);
void conn_free(connection_struct *conn);
/*The following definitions come from smbd/connection.c */
BOOL yield_connection(connection_struct *conn,char *name,int max_connections);
@ -2160,7 +2171,6 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval);
BOOL request_oplock_break(share_mode_entry *share_entry,
uint32 dev, uint32 inode);
BOOL receive_next_smb(int smbfd, int oplockfd, char *inbuf, int bufsize, int timeout);
BOOL snum_used(int snum);
BOOL reload_services(BOOL test);
connection_struct *make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid, int *ecode);
BOOL attempt_close_oplocked_file(files_struct *fsp);

View File

@ -531,14 +531,14 @@ typedef struct
BOOL is_wild;
} name_compare_entry;
typedef struct
typedef struct connection_struct
{
struct connection_struct *next, *prev;
unsigned cnum; /* an index passed over the wire */
int service;
BOOL force_user;
struct uid_cache uid_cache;
void *dirptr;
BOOL open;
BOOL printer;
BOOL ipc;
BOOL read_only;
@ -865,7 +865,6 @@ struct bitmap {
/* these are useful macros for checking validity of handles */
#define OPEN_FSP(fsp) ((fsp) && (fsp)->open && !(fsp)->is_directory)
#define VALID_CNUM(cnum) (((cnum) >= 0) && ((cnum) < MAX_CONNECTIONS))
#define OPEN_CONN(conn) ((conn) && (conn)->open)
#define IS_IPC(conn) ((conn) && (conn)->ipc)
#define IS_PRINT(conn) ((conn) && (conn)->printer)
@ -888,7 +887,7 @@ struct bitmap {
#define PRINTCAP (lp_printcapname())
#define PRINTCOMMAND(snum) (lp_printcommand(snum))
#define PRINTERNAME(snum) (lp_printername(snum))
#define CAN_WRITE(conn) (OPEN_CONN(conn) && !conn->read_only)
#define CAN_WRITE(conn) (!conn->read_only)
#define VALID_SNUM(snum) (lp_snum_ok(snum))
#define GUEST_OK(snum) (VALID_SNUM(snum) && lp_guest_ok(snum))
#define GUEST_ONLY(snum) (VALID_SNUM(snum) && lp_guest_only(snum))

View File

@ -26,7 +26,7 @@ extern int DEBUGLEVEL;
extern pstring samlogon_user;
extern BOOL sam_logon_in_ssb;
static char s_readbuf[16 * 1024];
static char s_readbuf[1024];
/***************************************************************
Start to enumerate the smbpasswd list. Returns a void pointer
@ -51,7 +51,7 @@ static void *startsmbfilepwent(BOOL update)
return NULL;
}
/* Set a 16k buffer to do more efficient reads */
/* Set a buffer to do more efficient reads */
setvbuf(fp, s_readbuf, _IOFBF, sizeof(s_readbuf));
if (!pw_file_lock(fileno(fp), (update ? F_WRLCK : F_RDLCK), 5, &pw_file_lock_depth))
@ -560,7 +560,7 @@ static BOOL mod_smbfilepwd_entry(struct smb_passwd* pwd, BOOL override)
static pstring user_name;
char linebuf[256];
char readbuf[16 * 1024];
char readbuf[1024];
unsigned char c;
fstring ascii_p16;
fstring encode_bits;
@ -590,7 +590,7 @@ static BOOL mod_smbfilepwd_entry(struct smb_passwd* pwd, BOOL override)
DEBUG(0, ("mod_smbfilepwd_entry: unable to open file %s\n", pfile));
return False;
}
/* Set a 16k buffer to do more efficient reads */
/* Set a buffer to do more efficient reads */
setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf));
lockfd = fileno(fp);

View File

@ -80,7 +80,7 @@ END {
next;
}
!/^pipes_struct|^file_fd_struct|^files_struct|^connection_struct|^uid_t|^gid_t|^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^struct|^BOOL|^void|^time|^smb_shm_offset_t|^shm_offset_t|^enum remote_arch_types|^FILE/ {
!/^connection_struct|^pipes_struct|^file_fd_struct|^files_struct|^connection_struct|^uid_t|^gid_t|^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^struct|^BOOL|^void|^time|^smb_shm_offset_t|^shm_offset_t|^enum remote_arch_types|^FILE/ {
next;
}

196
source/smbd/conn.c Normal file
View File

@ -0,0 +1,196 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
Manage connections_struct structures
Copyright (C) Andrew Tridgell 1998
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
extern int DEBUGLEVEL;
/* set these to define the limits of the server. NOTE These are on a
per-client basis. Thus any one machine can't connect to more than
MAX_CONNECTIONS services, but any number of machines may connect at
one time. */
#define MAX_CONNECTIONS 128
static connection_struct *Connections;
/* number of open connections */
static struct bitmap *bmap;
static int num_open;
/****************************************************************************
init the conn structures
****************************************************************************/
void conn_init(void)
{
bmap = bitmap_allocate(MAX_CONNECTIONS);
}
/****************************************************************************
return the number of open connections
****************************************************************************/
int conn_num_open(void)
{
return num_open;
}
/****************************************************************************
check if a snum is in use
****************************************************************************/
BOOL conn_snum_used(int snum)
{
connection_struct *conn;
for (conn=Connections;conn;conn=conn->next) {
if (conn->service == snum) {
return(True);
}
}
return(False);
}
/****************************************************************************
find a conn given a cnum
****************************************************************************/
connection_struct *conn_find(int cnum)
{
connection_struct *conn;
for (conn=Connections;conn;conn=conn->next) {
if (conn->cnum == cnum) return conn;
}
return NULL;
}
/****************************************************************************
find first available connection slot, starting from a random position.
The randomisation stops problems with the server dieing and clients
thinking the server is still available.
****************************************************************************/
connection_struct *conn_new(void)
{
connection_struct *conn;
int i;
i = bitmap_find(bmap, 1);
if (i == -1) {
DEBUG(1,("ERROR! Out of connection structures\n"));
return NULL;
}
conn = (connection_struct *)malloc(sizeof(*conn));
if (!conn) return NULL;
memset(conn, 0, sizeof(*conn));
conn->cnum = i;
bitmap_set(bmap, i);
num_open++;
string_init(&conn->user,"");
string_init(&conn->dirpath,"");
string_init(&conn->connectpath,"");
string_init(&conn->origpath,"");
/* hook into the front of the list */
if (!Connections) {
Connections = conn;
} else {
Connections->prev = conn;
conn->next = Connections;
Connections = conn;
}
return conn;
}
/****************************************************************************
close all conn structures
****************************************************************************/
void conn_close_all(void)
{
connection_struct *conn, *next;
for (conn=Connections;conn;conn=next) {
next=conn->next;
close_cnum(conn, (uint16)-1);
}
}
/****************************************************************************
idle inactive connections
****************************************************************************/
BOOL conn_idle_all(time_t t, int deadtime)
{
BOOL allidle = True;
connection_struct *conn, *next;
for (conn=Connections;conn;conn=next) {
next=conn->next;
/* close dirptrs on connections that are idle */
if ((t-conn->lastused) > DPTR_IDLE_TIMEOUT)
dptr_idlecnum(conn);
if (conn->num_files_open > 0 ||
(t-conn->lastused)<deadtime)
allidle = False;
}
return allidle;
}
/****************************************************************************
free a conn structure
****************************************************************************/
void conn_free(connection_struct *conn)
{
if (conn == Connections) {
Connections = conn->next;
if (Connections) Connections->prev = NULL;
} else {
conn->prev->next = conn->next;
if (conn->next) conn->next->prev = conn->prev;
}
if (conn->ngroups && conn->groups) {
free(conn->groups);
conn->groups = NULL;
conn->ngroups = 0;
}
free_namearray(conn->veto_list);
free_namearray(conn->hide_list);
free_namearray(conn->veto_oplock_list);
string_free(&conn->user);
string_free(&conn->dirpath);
string_free(&conn->connectpath);
string_free(&conn->origpath);
bitmap_clear(bmap, conn->cnum);
num_open--;
memset(conn, 0, sizeof(*conn));
free(conn);
}

View File

@ -54,7 +54,7 @@ files_struct *file_new(void )
{
int i;
static int first_file;
files_struct *fsp;
files_struct *fsp, *next;
/* we want to give out file handles differently on each new
connection because of a common bug in MS clients where they try to
@ -76,7 +76,8 @@ files_struct *file_new(void )
* files batch oplocked for quite a long time
* after they have finished with them.
*/
for (fsp=Files;fsp;fsp=fsp->next) {
for (fsp=Files;fsp;fsp=next) {
next=fsp->next;
if (attempt_close_oplocked_file(fsp)) {
return file_new();
}
@ -200,9 +201,10 @@ close all open files for a connection
****************************************************************************/
void file_close_conn(connection_struct *conn)
{
files_struct *fsp;
files_struct *fsp, *next;
for (fsp=Files;fsp;fsp=fsp->next) {
for (fsp=Files;fsp;fsp=next) {
next = fsp->next;
if (fsp->conn == conn && fsp->open) {
if (fsp->is_directory)
close_directory(fsp);
@ -248,9 +250,10 @@ close files open by a specified vuid
****************************************************************************/
void file_close_user(int vuid)
{
files_struct *fsp;
files_struct *fsp, *next;
for (fsp=Files;fsp;fsp=fsp->next) {
for (fsp=Files;fsp;fsp=next) {
next=fsp->next;
if ((fsp->vuid == vuid) && fsp->open) {
if(!fsp->is_directory)
close_file(fsp,False);
@ -301,9 +304,10 @@ sync open files on a connection
****************************************************************************/
void file_sync_all(connection_struct *conn)
{
files_struct *fsp;
files_struct *fsp, *next;
for (fsp=Files;fsp;fsp=fsp->next) {
for (fsp=Files;fsp;fsp=next) {
next=fsp->next;
if (fsp->open && conn == fsp->conn) {
sync_file(conn,fsp);
}

View File

@ -65,8 +65,6 @@ extern int dcelogin_atmost_once;
*/
extern DOM_SID global_machine_sid;
static connection_struct Connections[MAX_CONNECTIONS];
extern int Protocol;
/*
@ -81,9 +79,6 @@ int max_send = BUFFER_SIZE;
*/
int max_recv = BUFFER_SIZE;
/* number of open connections */
static int num_connections_open = 0;
/* Oplock ipc UDP socket. */
int oplock_sock = -1;
uint16 oplock_port = 0;
@ -2094,7 +2089,7 @@ BOOL become_service(connection_struct *conn,BOOL do_chdir)
static connection_struct *last_conn;
int snum;
if (!conn || !conn->open) {
if (!conn) {
last_conn = NULL;
return(False);
}
@ -3249,20 +3244,6 @@ BOOL receive_next_smb(int smbfd, int oplockfd, char *inbuf, int bufsize, int tim
return ret;
}
/****************************************************************************
check if a snum is in use
****************************************************************************/
BOOL snum_used(int snum)
{
int i;
for (i=0;i<MAX_CONNECTIONS;i++) {
if (Connections[i].open && (Connections[i].service == snum)) {
return(True);
}
}
return(False);
}
/****************************************************************************
reload the services file
**************************************************************************/
@ -3284,7 +3265,7 @@ BOOL reload_services(BOOL test)
if (test && !lp_file_list_changed())
return(True);
lp_killunused(snum_used);
lp_killunused(conn_snum_used);
ret = lp_load(servicesf,False,False,True);
@ -3336,42 +3317,6 @@ static void sig_hup(int sig)
BlockSignals(False,SIGHUP);
}
/****************************************************************************
find first available connection slot, starting from a random position.
The randomisation stops problems with the server dieing and clients
thinking the server is still available.
****************************************************************************/
static connection_struct *find_free_connection(int hash)
{
int i;
BOOL used=False;
hash = (hash % (MAX_CONNECTIONS-2))+1;
again:
for (i=hash+1;i!=hash;) {
if (!Connections[i].open && Connections[i].used == used) {
DEBUG(3,("found free connection number %d\n",i));
memset(&Connections[i], 0, sizeof(&Connections[i]));
Connections[i].cnum = i;
return &Connections[i];
}
i++;
if (i == MAX_CONNECTIONS) {
i = 1;
}
}
if (!used) {
used = !used;
goto again;
}
DEBUG(1,("ERROR! Out of connection structures\n"));
return NULL;
}
/****************************************************************************
make a connection to a service
@ -3462,10 +3407,11 @@ connection_struct *make_connection(char *service,char *user,char *password, int
return NULL;
}
conn = find_free_connection(str_checksum(service) + str_checksum(user));
conn = conn_new();
if (!conn) {
DEBUG(0,("Couldn't find free connection.\n"));
*ecode = ERRnoresource;
conn_free(conn);
return NULL;
}
@ -3475,6 +3421,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int
if (pass == NULL) {
DEBUG(0,( "Couldn't find account %s\n",user));
*ecode = ERRbaduid;
conn_free(conn);
return NULL;
}
@ -3589,6 +3536,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int
False)) {
DEBUG(1,("too many connections - rejected\n"));
*ecode = ERRnoresource;
conn_free(conn);
return NULL;
}
@ -3597,8 +3545,6 @@ connection_struct *make_connection(char *service,char *user,char *password, int
MAXSTATUS,False);
} /* IS_IPC */
conn->open = True;
/* execute any "root preexec = " line */
if (*lp_rootpreexec(SNUM(conn))) {
pstring cmd;
@ -3610,7 +3556,6 @@ connection_struct *make_connection(char *service,char *user,char *password, int
if (!become_user(conn, conn->vuid)) {
DEBUG(0,("Can't become connected user!\n"));
conn->open = False;
if (!IS_IPC(conn)) {
yield_connection(conn,
lp_servicename(SNUM(conn)),
@ -3619,6 +3564,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int
yield_connection(conn,"STATUS.",MAXSTATUS);
}
}
conn_free(conn);
*ecode = ERRbadpw;
return NULL;
}
@ -3626,7 +3572,6 @@ connection_struct *make_connection(char *service,char *user,char *password, int
if (ChDir(conn->connectpath) != 0) {
DEBUG(0,("Can't change directory to %s (%s)\n",
conn->connectpath,strerror(errno)));
conn->open = False;
unbecome_user();
if (!IS_IPC(conn)) {
yield_connection(conn,
@ -3635,6 +3580,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int
if (lp_status(SNUM(conn)))
yield_connection(conn,"STATUS.",MAXSTATUS);
}
conn_free(conn);
*ecode = ERRinvnetname;
return NULL;
}
@ -3652,7 +3598,6 @@ connection_struct *make_connection(char *service,char *user,char *password, int
}
#endif
num_connections_open++;
add_session_user(user);
/* execute any "preexec = " line */
@ -4108,11 +4053,6 @@ void close_cnum(connection_struct *conn, uint16 vuid)
unbecome_user();
if (!conn->open) {
DEBUG(0,("cnum not open\n"));
return;
}
DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
remote_machine,client_addr(Client),
lp_servicename(SNUM(conn))));
@ -4146,21 +4086,7 @@ void close_cnum(connection_struct *conn, uint16 vuid)
smbrun(cmd,NULL,False);
}
conn->open = False;
num_connections_open--;
if (conn->ngroups && conn->groups) {
free(conn->groups);
conn->groups = NULL;
conn->ngroups = 0;
}
free_namearray(conn->veto_list);
free_namearray(conn->hide_list);
free_namearray(conn->veto_oplock_list);
string_set(&conn->user,"");
string_set(&conn->dirpath,"");
string_set(&conn->connectpath,"");
conn_free(conn);
}
@ -4208,16 +4134,15 @@ exit the server
void exit_server(char *reason)
{
static int firsttime=1;
int i;
if (!firsttime) exit(0);
firsttime = 0;
unbecome_user();
DEBUG(2,("Closing connections\n"));
for (i=0;i<MAX_CONNECTIONS;i++)
if (Connections[i].open)
close_cnum(&Connections[i],(uint16)-1);
conn_close_all();
#ifdef WITH_DFS
if (dcelogin_atmost_once) {
dfs_unlogin();
@ -4457,16 +4382,12 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize
if (smb_messages[match].fn)
{
int cnum = SVAL(inbuf,smb_tid);
int flags = smb_messages[match].flags;
static uint16 last_session_tag = UID_FIELD_INVALID;
/* In share mode security we must ignore the vuid. */
uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
connection_struct *conn = NULL;
connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
if (VALID_CNUM(cnum) && Connections[cnum].open) {
conn = &Connections[cnum];
}
/* Ensure this value is replaced in the incoming packet. */
SSVAL(inbuf,smb_uid,session_tag);
@ -4517,7 +4438,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize
}
/* load service specific parameters */
if (OPEN_CONN(conn) &&
if (conn &&
!become_service(conn,(flags & AS_USER)?True:False)) {
return(ERROR(ERRSRV,ERRaccess));
}
@ -4765,7 +4686,6 @@ static void process(void)
InBuffer,BUFFER_SIZE,SMBD_SELECT_LOOP*1000,&got_smb);
counter += SMBD_SELECT_LOOP)
{
int i;
time_t t;
BOOL allidle = True;
extern int keepalive;
@ -4816,7 +4736,7 @@ static void process(void)
}
/* automatic timeout if all connections are closed */
if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT)
if (conn_num_open()==0 && counter >= IDLE_CLOSED_TIMEOUT)
{
DEBUG( 2, ( "Closing idle connection\n" ) );
return;
@ -4837,19 +4757,9 @@ static void process(void)
}
/* check for connection timeouts */
for (i=0;i<MAX_CONNECTIONS;i++) {
if (Connections[i].open) {
/* close dirptrs on connections that are idle */
if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
dptr_idlecnum(&Connections[i]);
allidle = conn_idle_all(t, deadtime);
if (Connections[i].num_files_open > 0 ||
(t-Connections[i].lastused)<deadtime)
allidle = False;
}
}
if (allidle && num_connections_open>0) {
if (allidle && conn_num_open()>0) {
DEBUG(2,("Closing idle connection 2.\n"));
return;
}
@ -4920,7 +4830,6 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup ));
****************************************************************************/
static void init_structs(void )
{
int i;
get_myname(myhostname,NULL);
/*
@ -4938,17 +4847,7 @@ static void init_structs(void )
}
strupper( global_myname );
for (i=0;i<MAX_CONNECTIONS;i++)
{
Connections[i].open = False;
Connections[i].num_files_open=0;
Connections[i].lastused=0;
Connections[i].used=False;
string_init(&Connections[i].user,"");
string_init(&Connections[i].dirpath,"");
string_init(&Connections[i].connectpath,"");
string_init(&Connections[i].origpath,"");
}
conn_init();
file_init();

View File

@ -236,7 +236,7 @@ BOOL become_user(connection_struct *conn, uint16 vuid)
unbecome_user();
if (!(conn && conn->open)) {
if (!conn) {
DEBUG(2,("Connection not open\n"));
return(False);
}