summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>1999-01-06 23:32:13 +0000
committerJeremy Allison <jra@samba.org>1999-01-06 23:32:13 +0000
commitf85f08419cd267f6d20c3ea6d072ddef49ca82c0 (patch)
tree1ec39803fed75b24e9bde4d5b6106d143ba16e4a
parent11c5fbaba4636700bb657f9d59883082be0ac625 (diff)
downloadsamba-f85f08419cd267f6d20c3ea6d072ddef49ca82c0.tar.gz
samba-f85f08419cd267f6d20c3ea6d072ddef49ca82c0.tar.xz
samba-f85f08419cd267f6d20c3ea6d072ddef49ca82c0.zip
Fixed the blocking locks and change notify code that got broken in
beta5. The problem was that I had increased the select timeout so much that the client was sending echo requests as a sort of keepalive. As smbd only did timeout processing on select timeout then not much timeout processing was being done :-). I've fixed this by moving the timeout code to a function and calling it every time we get an SMBecho request (we must have been idle at that point). Jeremy.
-rw-r--r--source/include/local.h2
-rw-r--r--source/include/proto.h13
-rw-r--r--source/smbd/process.c320
-rw-r--r--source/smbd/reply.c4
4 files changed, 184 insertions, 155 deletions
diff --git a/source/include/local.h b/source/include/local.h
index 6aef7f0b8dd..cdff63aa8e5 100644
--- a/source/include/local.h
+++ b/source/include/local.h
@@ -126,7 +126,7 @@
/* the following control timings of various actions. Don't change
them unless you know what you are doing. These are all in seconds */
#define DEFAULT_SMBD_TIMEOUT (60*60*24*7)
-#define SMBD_RELOAD_CHECK (120)
+#define SMBD_RELOAD_CHECK (180)
#define IDLE_CLOSED_TIMEOUT (60)
#define DPTR_IDLE_TIMEOUT (120)
#define SMBD_SELECT_LOOP (60)
diff --git a/source/include/proto.h b/source/include/proto.h
index 72baf1c77ec..1f4f522ac77 100644
--- a/source/include/proto.h
+++ b/source/include/proto.h
@@ -2412,6 +2412,10 @@ int reply_negprot(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size,
int dum_buffsize);
+/*The following definitions come from smbd/noquotas.c */
+
+BOOL disk_quotas(char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize);
+
/*The following definitions come from smbd/nttrans.c */
void fail_next_srvsvc_open(void);
@@ -2506,15 +2510,6 @@ void construct_reply_common(char *inbuf,char *outbuf);
int chain_reply(char *inbuf,char *outbuf,int size,int bufsize);
void smbd_process(void);
-/*The following definitions come from smbd/quotas.c */
-
-BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
-BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
-BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
-BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
-BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
-BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
-
/*The following definitions come from smbd/reply.c */
int reply_special(char *inbuf,char *outbuf);
diff --git a/source/smbd/process.c b/source/smbd/process.c
index f3d755f1060..1e263249f38 100644
--- a/source/smbd/process.c
+++ b/source/smbd/process.c
@@ -737,11 +737,167 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
}
/****************************************************************************
+ Process any timeout housekeeping. Return False if the caler should exit.
+****************************************************************************/
+
+static BOOL timeout_processing(int *counter, int deadtime,
+ int *last_keepalive, int *service_load_counter)
+{
+ extern int Client;
+
+ time_t t;
+ BOOL allidle = True;
+ extern int keepalive;
+
+ if (*counter > 365 * 3600) /* big number of seconds. */
+ {
+ *counter = 0;
+ *service_load_counter = 0;
+ }
+
+ if (smb_read_error == READ_EOF)
+ {
+ DEBUG(3,("end of file from client\n"));
+ return False;
+ }
+
+ if (smb_read_error == READ_ERROR)
+ {
+ DEBUG(3,("receive_smb error (%s) exiting\n",
+ strerror(errno)));
+ return False;
+ }
+
+ t = time(NULL);
+
+ /* become root again if waiting */
+ unbecome_user();
+
+ /* check for smb.conf reload */
+ if (*counter >= *service_load_counter + SMBD_RELOAD_CHECK)
+ {
+ *service_load_counter = *counter;
+
+ /* reload services, if files have changed. */
+ reload_services(True);
+ }
+
+ /*
+ * If reload_after_sighup == True then we got a SIGHUP
+ * and are being asked to reload. Fix from <branko.cibej@hermes.si>
+ */
+
+ if (reload_after_sighup)
+ {
+ DEBUG(0,("Reloading services after SIGHUP\n"));
+ reload_services(False);
+ reload_after_sighup = False;
+ /*
+ * Use this as an excuse to print some stats.
+ */
+ print_stat_cache_statistics();
+ }
+
+ /* automatic timeout if all connections are closed */
+ if (conn_num_open()==0 && *counter >= IDLE_CLOSED_TIMEOUT)
+ {
+ DEBUG( 2, ( "Closing idle connection\n" ) );
+ return False;
+ }
+
+ if (keepalive && (*counter-*last_keepalive)>keepalive)
+ {
+ struct cli_state *cli = server_client();
+ if (!send_keepalive(Client)) {
+ DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
+ return False;
+ }
+ /* also send a keepalive to the password server if its still
+ connected */
+ if (cli && cli->initialised)
+ send_keepalive(cli->fd);
+ *last_keepalive = *counter;
+ }
+
+ /* check for connection timeouts */
+ allidle = conn_idle_all(t, deadtime);
+
+ if (allidle && conn_num_open()>0) {
+ DEBUG(2,("Closing idle connection 2.\n"));
+ return False;
+ }
+
+ if(global_machine_password_needs_changing)
+ {
+ unsigned char trust_passwd_hash[16];
+ time_t lct;
+ pstring remote_machine_list;
+
+ /*
+ * We're in domain level security, and the code that
+ * read the machine password flagged that the machine
+ * password needs changing.
+ */
+
+ /*
+ * First, open the machine password file with an exclusive lock.
+ */
+
+ if(!trust_password_lock( global_myworkgroup, global_myname, True)) {
+ DEBUG(0,("process: unable to open the machine account password file for \
+machine %s in domain %s.\n", global_myname, global_myworkgroup ));
+ return True;
+ }
+
+ if(!get_trust_account_password( trust_passwd_hash, &lct)) {
+ DEBUG(0,("process: unable to read the machine account password for \
+machine %s in domain %s.\n", global_myname, global_myworkgroup ));
+ trust_password_unlock();
+ return True;
+ }
+
+ /*
+ * Make sure someone else hasn't already done this.
+ */
+
+ if(t < lct + lp_machine_password_timeout()) {
+ trust_password_unlock();
+ global_machine_password_needs_changing = False;
+ return True;
+ }
+
+ pstrcpy(remote_machine_list, lp_passwordserver());
+
+ change_trust_account_password( global_myworkgroup, remote_machine_list);
+ trust_password_unlock();
+ global_machine_password_needs_changing = False;
+ }
+
+ /*
+ * Check to see if we have any blocking locks
+ * outstanding on the queue.
+ */
+ process_blocking_lock_queue(t);
+
+ /*
+ * Check to see if we have any change notifies
+ * outstanding on the queue.
+ */
+ process_pending_change_notify_queue(t);
+
+ return True;
+}
+
+/****************************************************************************
process commands from the client
****************************************************************************/
+
void smbd_process(void)
{
- extern int Client;
+ extern int smb_echo_count;
+ int counter = SMBD_SELECT_LOOP;
+ int service_load_counter = 0;
+ int last_keepalive=0;
InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
@@ -771,9 +927,6 @@ void smbd_process(void)
while (True)
{
int deadtime = lp_deadtime()*60;
- int counter;
- int last_keepalive=0;
- int service_load_counter = 0;
BOOL got_smb = False;
if (deadtime <= 0)
@@ -786,154 +939,33 @@ void smbd_process(void)
errno = 0;
- for (counter=SMBD_SELECT_LOOP;
- !receive_message_or_smb(InBuffer,BUFFER_SIZE,
- SMBD_SELECT_LOOP*1000,&got_smb);
- counter += SMBD_SELECT_LOOP)
+ while(!receive_message_or_smb(InBuffer,BUFFER_SIZE,SMBD_SELECT_LOOP*1000,&got_smb))
{
- time_t t;
- BOOL allidle = True;
- extern int keepalive;
-
- if (counter > 365 * 3600) /* big number of seconds. */
- {
- counter = 0;
- service_load_counter = 0;
- }
-
- if (smb_read_error == READ_EOF)
- {
- DEBUG(3,("end of file from client\n"));
+ if(!timeout_processing(&counter, deadtime, &last_keepalive, &service_load_counter))
return;
- }
-
- if (smb_read_error == READ_ERROR)
- {
- DEBUG(3,("receive_smb error (%s) exiting\n",
- strerror(errno)));
- return;
- }
-
- t = time(NULL);
-
- /* become root again if waiting */
- unbecome_user();
-
- /* check for smb.conf reload */
- if (counter >= service_load_counter + SMBD_RELOAD_CHECK)
- {
- service_load_counter = counter;
-
- /* reload services, if files have changed. */
- reload_services(True);
- }
+ counter += SMBD_SELECT_LOOP;
+ }
+ if(got_smb) {
/*
- * If reload_after_sighup == True then we got a SIGHUP
- * and are being asked to reload. Fix from <branko.cibej@hermes.si>
- */
-
- if (reload_after_sighup)
- {
- DEBUG(0,("Reloading services after SIGHUP\n"));
- reload_services(False);
- reload_after_sighup = False;
- /*
- * Use this as an excuse to print some stats.
- */
- print_stat_cache_statistics();
- }
-
- /* automatic timeout if all connections are closed */
- if (conn_num_open()==0 && counter >= IDLE_CLOSED_TIMEOUT)
- {
- DEBUG( 2, ( "Closing idle connection\n" ) );
- return;
- }
-
- if (keepalive && (counter-last_keepalive)>keepalive)
- {
- struct cli_state *cli = server_client();
- if (!send_keepalive(Client)) {
- DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
- return;
- }
- /* also send a keepalive to the password server if its still
- connected */
- if (cli && cli->initialised)
- send_keepalive(cli->fd);
- last_keepalive = counter;
- }
-
- /* check for connection timeouts */
- allidle = conn_idle_all(t, deadtime);
-
- if (allidle && conn_num_open()>0) {
- DEBUG(2,("Closing idle connection 2.\n"));
- return;
- }
-
- if(global_machine_password_needs_changing)
- {
- unsigned char trust_passwd_hash[16];
- time_t lct;
- pstring remote_machine_list;
+ * Ensure we do timeout processing if the SMB we just got was
+ * only an echo request. This allows us to set the select
+ * timeout in 'receive_message_or_smb()' to any value we like
+ * without worrying that the client will send echo requests
+ * faster than the select timeout, thus starving out the
+ * essential processing (change notify, blocking locks) that
+ * the timeout code does. JRA.
+ */
+ int num_echos = smb_echo_count;
- /*
- * We're in domain level security, and the code that
- * read the machine password flagged that the machine
- * password needs changing.
- */
-
- /*
- * First, open the machine password file with an exclusive lock.
- */
-
- if(!trust_password_lock( global_myworkgroup, global_myname, True)) {
- DEBUG(0,("process: unable to open the machine account password file for \
-machine %s in domain %s.\n", global_myname, global_myworkgroup ));
- continue;
- }
-
- if(!get_trust_account_password( trust_passwd_hash, &lct)) {
- DEBUG(0,("process: unable to read the machine account password for \
-machine %s in domain %s.\n", global_myname, global_myworkgroup ));
- trust_password_unlock();
- continue;
- }
-
- /*
- * Make sure someone else hasn't already done this.
- */
-
- if(t < lct + lp_machine_password_timeout()) {
- trust_password_unlock();
- global_machine_password_needs_changing = False;
- continue;
- }
-
- pstrcpy(remote_machine_list, lp_passwordserver());
+ process_smb(InBuffer, OutBuffer);
- change_trust_account_password( global_myworkgroup, remote_machine_list);
- trust_password_unlock();
- global_machine_password_needs_changing = False;
+ if(smb_echo_count != num_echos) {
+ if(!timeout_processing(&counter, deadtime, &last_keepalive, &service_load_counter))
+ return;
+ counter += SMBD_SELECT_LOOP;
}
-
- /*
- * Check to see if we have any blocking locks
- * outstanding on the queue.
- */
- process_blocking_lock_queue(t);
-
- /*
- * Check to see if we have any change notifies
- * outstanding on the queue.
- */
- process_pending_change_notify_queue(t);
}
-
- if(got_smb)
- process_smb(InBuffer, OutBuffer);
else
process_local_message(InBuffer, BUFFER_SIZE);
}
diff --git a/source/smbd/reply.c b/source/smbd/reply.c
index c6ebd70c423..b13563182c9 100644
--- a/source/smbd/reply.c
+++ b/source/smbd/reply.c
@@ -42,7 +42,7 @@ extern fstring global_myworkgroup;
extern int Client;
extern int global_oplock_break;
uint32 global_client_caps = 0;
-
+unsigned int smb_echo_count = 0;
/****************************************************************************
report a possible attack via the password buffer overflow bug
@@ -2833,6 +2833,8 @@ int reply_echo(connection_struct *conn,
DEBUG(3,("echo %d times\n", smb_reverb));
+ smb_echo_count++;
+
return -1;
}