diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/Makefile.in | 2 | ||||
-rw-r--r-- | source/include/local.h | 6 | ||||
-rw-r--r-- | source/include/proto.h | 12 | ||||
-rw-r--r-- | source/include/smb.h | 7 | ||||
-rw-r--r-- | source/passdb/smbpass.c | 8 | ||||
-rw-r--r-- | source/script/mkproto.awk | 2 | ||||
-rw-r--r-- | source/smbd/conn.c | 196 | ||||
-rw-r--r-- | source/smbd/files.c | 20 | ||||
-rw-r--r-- | source/smbd/server.c | 137 | ||||
-rw-r--r-- | source/smbd/uid.c | 2 |
10 files changed, 247 insertions, 145 deletions
diff --git a/source/Makefile.in b/source/Makefile.in index 677159b440d..634a37a3571 100644 --- a/source/Makefile.in +++ b/source/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/source/include/local.h b/source/include/local.h index 1db1e9d4c1a..ead97e565d8 100644 --- a/source/include/local.h +++ b/source/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/source/include/proto.h b/source/include/proto.h index 0b5067e480a..4c7c625397a 100644 --- a/source/include/proto.h +++ b/source/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/source/include/smb.h b/source/include/smb.h index 2f2363ba71d..c68f88cbdd8 100644 --- a/source/include/smb.h +++ b/source/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/source/passdb/smbpass.c b/source/passdb/smbpass.c index 268394631f4..980c54adf12 100644 --- a/source/passdb/smbpass.c +++ b/source/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/source/script/mkproto.awk b/source/script/mkproto.awk index b998de2dcce..238bd8e0f64 100644 --- a/source/script/mkproto.awk +++ b/source/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/source/smbd/conn.c b/source/smbd/conn.c new file mode 100644 index 00000000000..b110e8d0828 --- /dev/null +++ b/source/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)<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); +} diff --git a/source/smbd/files.c b/source/smbd/files.c index e66e53e6ed2..7bd5501de53 100644 --- a/source/smbd/files.c +++ b/source/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/source/smbd/server.c b/source/smbd/server.c index f160b590dcd..a2930757412 100644 --- a/source/smbd/server.c +++ b/source/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); } @@ -3250,20 +3245,6 @@ BOOL receive_next_smb(int smbfd, int oplockfd, char *inbuf, int bufsize, int tim } /**************************************************************************** -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 **************************************************************************/ BOOL reload_services(BOOL test) @@ -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]); - - if (Connections[i].num_files_open > 0 || - (t-Connections[i].lastused)<deadtime) - allidle = False; - } - } + allidle = conn_idle_all(t, deadtime); - 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(); diff --git a/source/smbd/uid.c b/source/smbd/uid.c index 08a3952b3af..4ffec90521c 100644 --- a/source/smbd/uid.c +++ b/source/smbd/uid.c @@ -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); } |