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/smbd/conn.c | 196 ++++++++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/files.c | 20 +++--- source3/smbd/server.c | 137 +++++------------------------------ source3/smbd/uid.c | 2 +- 4 files changed, 227 insertions(+), 128 deletions(-) create mode 100644 source3/smbd/conn.c (limited to 'source3/smbd') 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