1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-27 22:50:26 +03:00

Simply our main loop processing. A lot :-). Correctly use events for all the previous "special" cases.

A step on the way to adding signals to the events and being able to merge the S3 event system with
the S4 one.
Jeremy.
This commit is contained in:
Jeremy Allison 2008-10-03 14:18:35 -07:00
parent 4b9cc7d478
commit f6c883b4b0
7 changed files with 148 additions and 188 deletions

View File

@ -26,6 +26,71 @@
extern bool global_machine_password_needs_changing;
static struct named_mutex *mutex;
/*
* Change machine password (called from main loop
* idle timeout. Must be done as root.
*/
void attempt_machine_password_change(void)
{
unsigned char trust_passwd_hash[16];
time_t lct;
void *lock;
if (!global_machine_password_needs_changing) {
return;
}
if (lp_security() != SEC_DOMAIN) {
return;
}
/*
* 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.
*/
lock = secrets_get_trust_account_lock(NULL, lp_workgroup());
if (lock == NULL) {
DEBUG(0,("attempt_machine_password_change: unable to lock "
"the machine account password for machine %s in "
"domain %s.\n",
global_myname(), lp_workgroup() ));
return;
}
if(!secrets_fetch_trust_account_password(lp_workgroup(),
trust_passwd_hash, &lct, NULL)) {
DEBUG(0,("attempt_machine_password_change: unable to read the "
"machine account password for %s in domain %s.\n",
global_myname(), lp_workgroup()));
TALLOC_FREE(lock);
return;
}
/*
* Make sure someone else hasn't already done this.
*/
if(time(NULL) < lct + lp_machine_password_timeout()) {
global_machine_password_needs_changing = false;
TALLOC_FREE(lock);
return;
}
/* always just contact the PDC here */
change_trust_account_password( lp_workgroup(), NULL);
global_machine_password_needs_changing = false;
TALLOC_FREE(lock);
}
/**
* Connect to a remote server for (inter)domain security authenticaion.
*

View File

@ -43,7 +43,8 @@ bool password_ok(const char *smb_name, DATA_BLOB password_blob);
/* The following definitions come from auth/auth_domain.c */
NTSTATUS auth_domain_init(void) ;
void attempt_machine_password_change(void);
NTSTATUS auth_domain_init(void);
/* The following definitions come from auth/auth_ntlmssp.c */

View File

@ -51,3 +51,18 @@ NTSTATUS can_delete_directory(struct connection_struct *conn,
{
return NT_STATUS_OK;
}
bool change_to_root_user(void)
{
return false;
}
struct event_context *smbd_event_context(void)
{
return NULL;
}
struct messaging_context *smbd_messaging_context(void)
{
return NULL;
}

View File

@ -34,6 +34,7 @@ static struct notify_queue {
size_t buflen;
} *notify_queue_head = NULL;
static struct timed_event *notify_event;
static bool create_send_ctx(void)
{
@ -214,6 +215,22 @@ void print_notify_send_messages(struct messaging_context *msg_ctx,
num_messages = 0;
}
/*******************************************************************
Event handler to send the messages.
*******************************************************************/
static void print_notify_event_send_messages(struct event_context *event_ctx,
struct timed_event *te,
const struct timeval *now,
void *private_data)
{
/* Remove this timed event handler. */
TALLOC_FREE(notify_event);
change_to_root_user();
print_notify_send_messages(smbd_messaging_context(), 0);
}
/**********************************************************************
deep copy a SPOOLSS_NOTIFY_MSG structure using a TALLOC_CTX
*********************************************************************/
@ -304,6 +321,15 @@ to notify_queue_head\n", msg->type, msg->field, msg->printer));
DLIST_ADD_END(notify_queue_head, pnqueue, struct notify_queue *);
num_messages++;
if (smbd_event_context()) {
/* Add an event for 1 second's time to send this queue. */
notify_event = event_add_timed(smbd_event_context(), NULL,
timeval_current_ofs(1,0),
"print_notify",
print_notify_event_send_messages, NULL);
}
}
static void send_notify_field_values(const char *sharename, uint32 type,

View File

@ -706,7 +706,7 @@ The timeout is in milliseconds
****************************************************************************/
static NTSTATUS receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer,
size_t *buffer_len, int timeout,
size_t *buffer_len,
size_t *p_unread, bool *p_encrypted)
{
fd_set r_fds, w_fds;
@ -720,13 +720,8 @@ static NTSTATUS receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer,
again:
if (timeout >= 0) {
to.tv_sec = timeout / 1000;
to.tv_usec = (timeout % 1000) * 1000;
} else {
to.tv_sec = SMBD_SELECT_TIMEOUT;
to.tv_usec = 0;
}
to.tv_sec = SMBD_SELECT_TIMEOUT;
to.tv_usec = 0;
/*
* Note that this call must be before processing any SMB
@ -869,7 +864,7 @@ static NTSTATUS receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer,
/* Did we timeout ? */
if (selrtn == 0) {
return NT_STATUS_IO_TIMEOUT;
goto again;
}
/*
@ -1836,23 +1831,6 @@ void chain_reply(struct smb_request *req)
return;
}
/****************************************************************************
Setup the needed select timeout in milliseconds.
****************************************************************************/
static int setup_select_timeout(void)
{
int select_timeout;
select_timeout = SMBD_SELECT_TIMEOUT*1000;
if (print_notify_messages_pending()) {
select_timeout = MIN(select_timeout, 1000);
}
return select_timeout;
}
/****************************************************************************
Check if services need reloading.
****************************************************************************/
@ -1906,114 +1884,19 @@ void check_reload(time_t t)
}
}
/****************************************************************************
Process any timeout housekeeping. Return False if the caller should exit.
****************************************************************************/
static void timeout_processing(int *select_timeout,
time_t *last_timeout_processing_time)
{
time_t t;
*last_timeout_processing_time = t = time(NULL);
/* become root again if waiting */
change_to_root_user();
/* check if we need to reload services */
check_reload(t);
if(global_machine_password_needs_changing &&
/* for ADS we need to do a regular ADS password change, not a domain
password change */
lp_security() == SEC_DOMAIN) {
unsigned char trust_passwd_hash[16];
time_t lct;
void *lock;
/*
* 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.
*/
lock = secrets_get_trust_account_lock(NULL, lp_workgroup());
if (lock == NULL) {
DEBUG(0,("process: unable to lock the machine account password for \
machine %s in domain %s.\n", global_myname(), lp_workgroup() ));
return;
}
if(!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd_hash, &lct, NULL)) {
DEBUG(0,("process: unable to read the machine account password for \
machine %s in domain %s.\n", global_myname(), lp_workgroup()));
TALLOC_FREE(lock);
return;
}
/*
* Make sure someone else hasn't already done this.
*/
if(t < lct + lp_machine_password_timeout()) {
global_machine_password_needs_changing = False;
TALLOC_FREE(lock);
return;
}
/* always just contact the PDC here */
change_trust_account_password( lp_workgroup(), NULL);
global_machine_password_needs_changing = False;
TALLOC_FREE(lock);
}
/* update printer queue caches if necessary */
update_monitored_printq_cache();
/*
* Now we are root, check if the log files need pruning.
* Force a log file check.
*/
force_check_log_size();
check_log_size();
/* Send any queued printer notify message to interested smbd's. */
print_notify_send_messages(smbd_messaging_context(), 0);
/*
* Modify the select timeout depending upon
* what we have remaining in our queues.
*/
*select_timeout = setup_select_timeout();
return;
}
/****************************************************************************
Process commands from the client
****************************************************************************/
void smbd_process(void)
{
time_t last_timeout_processing_time = time(NULL);
unsigned int num_smbs = 0;
size_t unread_bytes = 0;
max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
while (True) {
int select_timeout = setup_select_timeout();
int num_echos;
NTSTATUS status;
char *inbuf = NULL;
size_t inbuf_len = 0;
bool encrypted = false;
@ -2021,82 +1904,24 @@ void smbd_process(void)
errno = 0;
/* Did someone ask for immediate checks on things like blocking locks ? */
if (select_timeout == 0) {
timeout_processing(&select_timeout,
&last_timeout_processing_time);
num_smbs = 0; /* Reset smb counter. */
}
run_events(smbd_event_context(), 0, NULL, NULL);
while (True) {
NTSTATUS status;
status = receive_message_or_smb(
talloc_tos(), &inbuf, &inbuf_len,
select_timeout, &unread_bytes, &encrypted);
if (NT_STATUS_IS_OK(status)) {
break;
}
if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
timeout_processing(
&select_timeout,
&last_timeout_processing_time);
continue;
}
status = receive_message_or_smb(
talloc_tos(), &inbuf, &inbuf_len,
&unread_bytes, &encrypted);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3, ("receive_message_or_smb failed: %s, "
"exiting\n", nt_errstr(status)));
return;
num_smbs = 0; /* Reset smb counter. */
}
/*
* 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.
*/
num_echos = smb_echo_count;
process_smb(inbuf, inbuf_len, unread_bytes, encrypted);
TALLOC_FREE(inbuf);
if (smb_echo_count != num_echos) {
timeout_processing(&select_timeout,
&last_timeout_processing_time);
num_smbs = 0; /* Reset smb counter. */
}
num_smbs++;
/*
* If we are getting smb requests in a constant stream
* with no echos, make sure we attempt timeout processing
* every select_timeout milliseconds - but only check for this
* every 200 smb requests.
*/
if ((num_smbs % 200) == 0) {
time_t new_check_time = time(NULL);
if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) {
timeout_processing(
&select_timeout,
&last_timeout_processing_time);
num_smbs = 0; /* Reset smb counter. */
last_timeout_processing_time = new_check_time; /* Reset time. */
}
}
/* The timeout_processing function isn't run nearly
often enough to implement 'max log size' without
overrunning the size of the file by many megabytes.

View File

@ -29,7 +29,6 @@
/* look in server.c for some explanation of these variables */
extern enum protocol_types Protocol;
extern int max_recv;
unsigned int smb_echo_count = 0;
extern uint32 global_client_caps;
extern bool global_encrypted_passwords_negotiated;
@ -4611,8 +4610,6 @@ void reply_echo(struct smb_request *req)
TALLOC_FREE(req->outbuf);
smb_echo_count++;
END_PROFILE(SMBecho);
return;
}

View File

@ -1067,6 +1067,30 @@ static bool deadtime_fn(const struct timeval *now, void *private_data)
return True;
}
/*
* Do the recurring log file and smb.conf reload checks.
*/
static bool housekeeping_fn(const struct timeval *now, void *private_data)
{
change_to_root_user();
/* update printer queue caches if necessary */
update_monitored_printq_cache();
/* check if we need to reload services */
check_reload(time(NULL));
/* Change machine password if neccessary. */
attempt_machine_password_change();
/*
* Force a log file check.
*/
force_check_log_size();
check_log_size();
return true;
}
/****************************************************************************
main program.
@ -1426,6 +1450,13 @@ extern void build_options(bool screen);
exit(1);
}
if (!(event_add_idle(smbd_event_context(), NULL,
timeval_set(SMBD_SELECT_TIMEOUT, 0),
"housekeeping", housekeeping_fn, NULL))) {
DEBUG(0, ("Could not add housekeeping event\n"));
exit(1);
}
#ifdef CLUSTER_SUPPORT
if (lp_clustering()) {