From 983dc71c9844675ad364f3ea59ddd04b87857b55 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 17 Aug 1998 06:13:32 +0000 Subject: moved connection_struct handling code into smbd/conn.c and changed it to a linked list with bitmap format. (This used to be commit b7aaab1b6b2d2f72b2bb7c11f5c7bf081a6093d9) --- source3/Makefile.in | 2 +- source3/include/local.h | 6 -- source3/include/proto.h | 12 ++- source3/include/smb.h | 7 +- source3/passdb/smbpass.c | 8 +- source3/script/mkproto.awk | 2 +- source3/smbd/conn.c | 196 +++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/files.c | 20 +++-- source3/smbd/server.c | 137 +++++-------------------------- source3/smbd/uid.c | 2 +- 10 files changed, 247 insertions(+), 145 deletions(-) create mode 100644 source3/smbd/conn.c (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index 677159b440..634a37a357 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -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 diff --git a/source3/include/local.h b/source3/include/local.h index 1db1e9d4c1..ead97e565d 100644 --- a/source3/include/local.h +++ b/source3/include/local.h @@ -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) diff --git a/source3/include/proto.h b/source3/include/proto.h index 0b5067e480..4c7c625397 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -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); diff --git a/source3/include/smb.h b/source3/include/smb.h index 2f2363ba71..c68f88cbdd 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -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)) diff --git a/source3/passdb/smbpass.c b/source3/passdb/smbpass.c index 268394631f..980c54adf1 100644 --- a/source3/passdb/smbpass.c +++ b/source3/passdb/smbpass.c @@ -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); diff --git a/source3/script/mkproto.awk b/source3/script/mkproto.awk index b998de2dcc..238bd8e0f6 100644 --- a/source3/script/mkproto.awk +++ b/source3/script/mkproto.awk @@ -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; } diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c new file mode 100644 index 0000000000..b110e8d082 --- /dev/null +++ b/source3/smbd/conn.c @@ -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)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); +} diff --git a/source3/smbd/files.c b/source3/smbd/files.c index e66e53e6ed..7bd5501de5 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -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); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index f160b590dc..a293075741 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -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;iopen = 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= 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;iDPTR_IDLE_TIMEOUT) - dptr_idlecnum(&Connections[i]); - - if (Connections[i].num_files_open > 0 || - (t-Connections[i].lastused)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;iopen)) { + if (!conn) { DEBUG(2,("Connection not open\n")); return(False); } -- cgit