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
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
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.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
static struct event_context *ctx;
if (!ctx && !(ctx = event_context_init(NULL))) {
- smb_panic("Could not init smbd event context\n");
+ smb_panic("Could not init smbd event context");
+ }
+ return ctx;
+}
+
+struct messaging_context *smbd_messaging_context(void)
+{
+ static struct messaging_context *ctx;
+
+ if (!ctx && !(ctx = messaging_init(NULL, server_id_self(),
+ smbd_event_context()))) {
+ smb_panic("Could not init smbd messaging context");
}
return ctx;
}
What to do when smb.conf is updated.
********************************************************************/
-static void smb_conf_updated(int msg_type, struct process_id src,
- void *buf, size_t len)
+static void smb_conf_updated(struct messaging_context *msg,
+ void *private_data,
+ uint32_t msg_type,
+ struct server_id server_id,
+ DATA_BLOB *data)
{
- DEBUG(10,("smb_conf_updated: Got message saying smb.conf was updated. Reloading.\n"));
+ DEBUG(10,("smb_conf_updated: Got message saying smb.conf was "
+ "updated. Reloading.\n"));
reload_services(False);
}
+/*******************************************************************
+ Delete a statcache entry.
+ ********************************************************************/
+
+static void smb_stat_cache_delete(struct messaging_context *msg,
+ void *private_data,
+ uint32_t msg_tnype,
+ struct server_id server_id,
+ DATA_BLOB *data)
+{
+ const char *name = (const char *)data->data;
+ DEBUG(10,("smb_stat_cache_delete: delete name %s\n", name));
+ stat_cache_delete(name);
+}
+
/****************************************************************************
Terminate signal.
****************************************************************************/
somewhere else.
****************************************************************************/
-static void msg_sam_sync(int UNUSED(msg_type), struct process_id UNUSED(pid),
- void *UNUSED(buf), size_t UNUSED(len))
+static void msg_sam_sync(struct messaging_context *msg,
+ void *private_data,
+ uint32_t msg_type,
+ struct server_id server_id,
+ DATA_BLOB *data)
{
DEBUG(10, ("** sam sync message received, ignoring\n"));
}
-/****************************************************************************
- Process a sam sync replicate message - not sure whether to do this here or
- somewhere else.
-****************************************************************************/
-
-static void msg_sam_repl(int msg_type, struct process_id pid,
- void *buf, size_t len)
-{
- uint32 low_serial;
-
- if (len != sizeof(uint32))
- return;
-
- low_serial = *((uint32 *)buf);
-
- DEBUG(3, ("received sam replication message, serial = 0x%04x\n",
- low_serial));
-}
/****************************************************************************
Open the socket communication - inetd.
return True;
}
-static void msg_exit_server(int msg_type, struct process_id src,
- void *buf, size_t len)
+static void msg_exit_server(struct messaging_context *msg,
+ void *private_data,
+ uint32_t msg_type,
+ struct server_id server_id,
+ DATA_BLOB *data)
{
DEBUG(3, ("got a SHUTDOWN message\n"));
exit_server_cleanly(NULL);
}
#ifdef DEVELOPER
-static void msg_inject_fault(int msg_type, struct process_id src,
- void *buf, size_t len)
+static void msg_inject_fault(struct messaging_context *msg,
+ void *private_data,
+ uint32_t msg_type,
+ struct server_id src,
+ DATA_BLOB *data)
{
int sig;
- if (len != sizeof(int)) {
+ if (data->length != sizeof(sig)) {
- DEBUG(0, ("Process %llu sent bogus signal injection request\n",
- (unsigned long long)src.pid));
+ DEBUG(0, ("Process %s sent bogus signal injection request\n",
+ procid_str_static(&src)));
return;
}
- sig = *(int *)buf;
+ sig = *(int *)data->data;
if (sig == -1) {
exit_server("internal error injected");
return;
}
#if HAVE_STRSIGNAL
- DEBUG(0, ("Process %llu requested injection of signal %d (%s)\n",
- (unsigned long long)src.pid, sig, strsignal(sig)));
+ DEBUG(0, ("Process %s requested injection of signal %d (%s)\n",
+ procid_str_static(&src), sig, strsignal(sig)));
#else
- DEBUG(0, ("Process %llu requested injection of signal %d\n",
- (unsigned long long)src.pid, sig));
+ DEBUG(0, ("Process %s requested injection of signal %d\n",
+ procid_str_static(&src), sig));
#endif
kill(sys_getpid(), sig);
for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) {
unsigned port = atoi(tok);
- if (port == 0) {
+ if (port == 0 || port > 0xffff) {
continue;
}
s = fd_listenset[num_sockets] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True);
for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) {
unsigned port = atoi(tok);
- if (port == 0) continue;
+ if (port == 0 || port > 0xffff) continue;
/* open an incoming socket */
s = open_socket_in(SOCK_STREAM, port, 0,
interpret_addr(lp_socket_address()),True);
SAFE_FREE(ports);
+
+ /* Setup the main smbd so that we can get messages. Note that
+ do this after starting listening. This is needed as when in
+ clustered mode, ctdb won't allow us to start doing database
+ operations until it has gone thru a full startup, which
+ includes checking to see that smbd is listening. */
+ claim_connection(NULL,"",FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
+
/* Listen to messages */
- message_register(MSG_SMB_SAM_SYNC, msg_sam_sync);
- message_register(MSG_SMB_SAM_REPL, msg_sam_repl);
- message_register(MSG_SHUTDOWN, msg_exit_server);
- message_register(MSG_SMB_FILE_RENAME, msg_file_was_renamed);
- message_register(MSG_SMB_CONF_UPDATED, smb_conf_updated);
+ messaging_register(smbd_messaging_context(), NULL,
+ MSG_SMB_SAM_SYNC, msg_sam_sync);
+ messaging_register(smbd_messaging_context(), NULL,
+ MSG_SHUTDOWN, msg_exit_server);
+ messaging_register(smbd_messaging_context(), NULL,
+ MSG_SMB_FILE_RENAME, msg_file_was_renamed);
+ messaging_register(smbd_messaging_context(), NULL,
+ MSG_SMB_CONF_UPDATED, smb_conf_updated);
+ messaging_register(smbd_messaging_context(), NULL,
+ MSG_SMB_STAT_CACHE_DELETE, smb_stat_cache_delete);
+ brl_register_msgs(smbd_messaging_context());
#ifdef DEVELOPER
- message_register(MSG_SMB_INJECT_FAULT, msg_inject_fault);
+ messaging_register(smbd_messaging_context(), NULL,
+ MSG_SMB_INJECT_FAULT, msg_inject_fault);
#endif
/* now accept incoming connections - forking a new process
for each incoming connection */
DEBUG(2,("waiting for a connection\n"));
while (1) {
- fd_set lfds;
+ struct timeval now, idle_timeout;
+ fd_set r_fds, w_fds;
int num;
- /* Free up temporary memory from the main smbd. */
- lp_TALLOC_FREE();
-
/* Ensure we respond to PING and DEBUG messages from the main smbd. */
- message_dispatch();
+ message_dispatch(smbd_messaging_context());
if (got_sig_cld) {
pid_t pid;
}
}
- memcpy((char *)&lfds, (char *)&listen_set,
+ idle_timeout = timeval_zero();
+
+ memcpy((char *)&r_fds, (char *)&listen_set,
sizeof(listen_set));
-
- num = sys_select(maxfd+1,&lfds,NULL,NULL,NULL);
-
+ FD_ZERO(&w_fds);
+ GetTimeOfDay(&now);
+
+ event_add_to_select_args(smbd_event_context(), &now,
+ &r_fds, &w_fds, &idle_timeout,
+ &maxfd);
+
+ num = sys_select(maxfd+1,&r_fds,&w_fds,NULL,
+ timeval_is_zero(&idle_timeout) ?
+ NULL : &idle_timeout);
+
if (num == -1 && errno == EINTR) {
if (got_sig_term) {
exit_server_cleanly(NULL);
continue;
}
+ if (run_events(smbd_event_context(), num, &r_fds, &w_fds)) {
+ continue;
+ }
+
/* check if we need to reload services */
check_reload(time(NULL));
s = -1;
for(i = 0; i < num_sockets; i++) {
- if(FD_ISSET(fd_listenset[i],&lfds)) {
+ if(FD_ISSET(fd_listenset[i],&r_fds)) {
s = fd_listenset[i];
/* Clear this so we don't look
at it again. */
- FD_CLR(fd_listenset[i],&lfds);
+ FD_CLR(fd_listenset[i],&r_fds);
break;
}
}
* CLEAR_IF_FIRST flags */
if (tdb_reopen_all(1) == -1) {
DEBUG(0,("tdb_reopen_all failed.\n"));
- smb_panic("tdb_reopen_all failed.");
+ smb_panic("tdb_reopen_all failed");
}
return True;
invalidate_all_vuids();
- print_notify_send_messages(3); /* 3 second timeout. */
+ /* 3 second timeout. */
+ print_notify_send_messages(smbd_messaging_context(), 3);
/* delete our entry in the connections database. */
yield_connection(NULL,"");
if (how != SERVER_EXIT_NORMAL) {
int oldlevel = DEBUGLEVEL;
- char *last_inbuf = get_InBuffer();
DEBUGLEVEL = 10;
DEBUGSEP(0);
log_stack_trace();
- if (last_inbuf) {
- DEBUG(0,("Last message was %s\n", LAST_MESSAGE()));
- show_msg(last_inbuf);
- }
DEBUGLEVEL = oldlevel;
dump_core();
return True;
}
+/*
+ * Send keepalive packets to our client
+ */
+static BOOL keepalive_fn(const struct timeval *now, void *private_data)
+{
+ if (!send_keepalive(smbd_server_fd())) {
+ DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
+ return False;
+ }
+ return True;
+}
+
+/*
+ * Do the recurring check if we're idle
+ */
+static BOOL deadtime_fn(const struct timeval *now, void *private_data)
+{
+ if ((conn_num_open() == 0)
+ || (conn_idle_all(now->tv_sec))) {
+ DEBUG( 2, ( "Closing idle connection\n" ) );
+ messaging_send(smbd_messaging_context(), procid_self(),
+ MSG_SHUTDOWN, &data_blob_null);
+ return False;
+ }
+
+ return True;
+}
+
+
/****************************************************************************
main program.
****************************************************************************/
static BOOL no_process_group = False;
static BOOL log_stdout = False;
static char *ports = NULL;
+ static char *profile_level = NULL;
int opt;
poptContext pc;
+ BOOL print_build_options = False;
struct poptOption long_options[] = {
POPT_AUTOHELP
{"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" },
{"build-options", 'b', POPT_ARG_NONE, NULL, 'b', "Print build options" },
{"port", 'p', POPT_ARG_STRING, &ports, 0, "Listen on the specified ports"},
+ {"profiling-level", 'P', POPT_ARG_STRING, &profile_level, 0, "Set profiling level","PROFILE_LEVEL"},
POPT_COMMON_SAMBA
POPT_COMMON_DYNCONFIG
POPT_TABLEEND
load_case_tables();
+ TimeInit();
+
#ifdef HAVE_SET_AUTH_PARAMETERS
set_auth_parameters(argc,argv);
#endif
pc = poptGetContext("smbd", argc, argv, long_options, 0);
-
while((opt = poptGetNextOpt(pc)) != -1) {
switch (opt) {
case 'b':
- build_options(True); /* Display output to screen as well as debug */
- exit(0);
+ print_build_options = True;
break;
+ default:
+ d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
+ poptBadOption(pc, 0), poptStrerror(opt));
+ poptPrintUsage(pc, stderr, 0);
+ exit(1);
}
}
-
poptFreeContext(pc);
+ if (print_build_options) {
+ build_options(True); /* Display output to screen as well as debug */
+ exit(0);
+ }
+
#ifdef HAVE_SETLUID
/* needed for SecureWare on SCO */
setluid(0);
init_structs();
#ifdef WITH_PROFILE
- if (!profile_setup(False)) {
+ if (!profile_setup(smbd_messaging_context(), False)) {
DEBUG(0,("ERROR: failed to setup profiling\n"));
return -1;
}
+ if (profile_level != NULL) {
+ int pl = atoi(profile_level);
+ struct server_id src;
+
+ DEBUG(1, ("setting profiling level: %s\n",profile_level));
+ src.pid = getpid();
+ set_profile_level(pl, src);
+ }
#endif
DEBUG(3,( "loaded services\n"));
pidfile_create("smbd");
/* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */
- if (!message_init())
+
+ if (smbd_messaging_context() == NULL)
exit(1);
/* Initialise the password backed before the global_sam_sid
to ensure that we fetch from ldap before we make a domain sid up */
- if(!initialize_password_db(False))
+ if(!initialize_password_db(False, smbd_event_context()))
exit(1);
if (!secrets_init()) {
if (!session_init())
exit(1);
- if (conn_tdb_ctx() == NULL)
+ if (!connections_init(True))
exit(1);
if (!locking_init(0))
exit(1);
#endif
- if (!print_backend_init())
+ if (!print_backend_init(smbd_messaging_context()))
exit(1);
if (!init_guest_info()) {
return -1;
}
- /* Setup the main smbd so that we can get messages. */
- /* don't worry about general printing messages here */
-
- claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
-
/* only start the background queue daemon if we are
running as a daemon -- bad things will happen if
smbd is launched via inetd and we fork a copy of
init_modules();
- /* possibly reload the services file. */
- reload_services(True);
+ /* Possibly reload the services file. Only worth doing in
+ * daemon mode. In inetd mode, we know we only just loaded this.
+ */
+ if (is_daemon) {
+ reload_services(True);
+ }
if (!init_account_policy()) {
DEBUG(0,("Could not open account policy tdb.\n"));
}
/* Setup oplocks */
- if (!init_oplocks())
+ if (!init_oplocks(smbd_messaging_context()))
exit(1);
- /* Setup change notify */
- if (!init_change_notify())
- exit(1);
-
/* Setup aio signal handler. */
initialize_async_io_handler();
- /* re-initialise the timezone */
- TimeInit();
+ /*
+ * For clustering, we need to re-init our ctdbd connection after the
+ * fork
+ */
+ if (!NT_STATUS_IS_OK(messaging_reinit(smbd_messaging_context())))
+ exit(1);
/* register our message handlers */
- message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis);
+ messaging_register(smbd_messaging_context(), NULL,
+ MSG_SMB_FORCE_TDIS, msg_force_tdis);
+
+ if ((lp_keepalive() != 0)
+ && !(event_add_idle(smbd_event_context(), NULL,
+ timeval_set(lp_keepalive(), 0),
+ "keepalive", keepalive_fn,
+ NULL))) {
+ DEBUG(0, ("Could not add keepalive event\n"));
+ exit(1);
+ }
+
+ if (!(event_add_idle(smbd_event_context(), NULL,
+ timeval_set(IDLE_CLOSED_TIMEOUT, 0),
+ "deadtime", deadtime_fn, NULL))) {
+ DEBUG(0, ("Could not add deadtime event\n"));
+ exit(1);
+ }
smbd_process();