#include "includes.h"
#include "system/filesys.h"
#include "lib/util/server_id.h"
-#include "popt_common.h"
+#include "lib/util/close_low_fd.h"
+#include "lib/cmdline/cmdline.h"
+#include "locking/share_mode_lock.h"
#include "smbd/smbd.h"
#include "smbd/globals.h"
+#include "smbd/smbXsrv_open.h"
#include "registry/reg_init_full.h"
#include "libcli/auth/schannel.h"
#include "secrets.h"
#include "../lib/util/memcache.h"
#include "ctdbd_conn.h"
+#include "lib/util/util_process.h"
#include "util_cluster.h"
#include "printing/queue_process.h"
-#include "rpc_server/rpc_service_setup.h"
#include "rpc_server/rpc_config.h"
#include "passdb.h"
#include "auth.h"
#include "lib/id_cache.h"
#include "lib/param/param.h"
#include "lib/background.h"
-#include "lib/conn_tdb.h"
#include "../lib/util/pidfile.h"
#include "lib/smbd_shim.h"
#include "scavenger.h"
#include "lib/util/sys_rw.h"
#include "cleanupdb.h"
#include "g_lock.h"
+#include "lib/global_contexts.h"
+#include "source3/lib/substitute.h"
#ifdef CLUSTER_SUPPORT
#include "ctdb_protocol.h"
pid_t pid;
};
-extern void start_epmd(struct tevent_context *ev_ctx,
- struct messaging_context *msg_ctx);
-
-extern void start_lsasd(struct tevent_context *ev_ctx,
- struct messaging_context *msg_ctx);
-
-extern void start_fssd(struct tevent_context *ev_ctx,
- struct messaging_context *msg_ctx);
-
-extern void start_mdssd(struct tevent_context *ev_ctx,
- struct messaging_context *msg_ctx);
-
/*******************************************************************
What to do when smb.conf is updated.
********************************************************************/
+static NTSTATUS messaging_send_to_children(struct messaging_context *msg_ctx,
+ uint32_t msg_type, DATA_BLOB* data);
+
static void smbd_parent_conf_updated(struct messaging_context *msg,
void *private_data,
uint32_t msg_type,
struct server_id server_id,
DATA_BLOB *data)
{
- struct tevent_context *ev_ctx =
- talloc_get_type_abort(private_data, struct tevent_context);
+ bool ok;
DEBUG(10,("smbd_parent_conf_updated: Got message saying smb.conf was "
"updated. Reloading.\n"));
change_to_root_user();
reload_services(NULL, NULL, false);
- printing_subsystem_update(ev_ctx, msg, 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);
+ ok = reinit_guest_session_info(NULL);
+ if (!ok) {
+ DBG_ERR("Failed to reinit guest info\n");
+ }
+ messaging_send_to_children(msg, MSG_SMB_CONF_UPDATED, NULL);
}
/****************************************************************************
return;
}
-#if HAVE_STRSIGNAL
+#ifdef HAVE_STRSIGNAL
DEBUG(0, ("Process %s requested injection of signal %d (%s)\n",
server_id_str_buf(src, &tmp), sig, strsignal(sig)));
#else
}
#endif /* DEVELOPER */
+#if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
+/*
+ * Sleep for the specified number of seconds.
+ */
+static void msg_sleep(struct messaging_context *msg,
+ void *private_data,
+ uint32_t msg_type,
+ struct server_id src,
+ DATA_BLOB *data)
+{
+ unsigned int seconds;
+ struct server_id_buf tmp;
+
+ if (data->length != sizeof(seconds)) {
+ DBG_ERR("Process %s sent bogus sleep request\n",
+ server_id_str_buf(src, &tmp));
+ return;
+ }
+
+ seconds = *(unsigned int *)data->data;
+ DBG_ERR("Process %s request a sleep of %u seconds\n",
+ server_id_str_buf(src, &tmp),
+ seconds);
+ sleep(seconds);
+ DBG_ERR("Restarting after %u second sleep requested by process %s\n",
+ seconds,
+ server_id_str_buf(src, &tmp));
+}
+#endif /* DEVELOPER */
+
static NTSTATUS messaging_send_to_children(struct messaging_context *msg_ctx,
uint32_t msg_type, DATA_BLOB* data)
{
messaging_send_to_children(ctx, msg_type, msg_data);
}
-#ifdef CLUSTER_SUPPORT
-static int smbd_parent_ctdb_reconfigured(
- struct tevent_context *ev,
- uint32_t src_vnn, uint32_t dst_vnn, uint64_t dst_srvid,
- const uint8_t *msg, size_t msglen, void *private_data)
-{
- struct messaging_context *msg_ctx = talloc_get_type_abort(
- private_data, struct messaging_context);
-
- DEBUG(10, ("Got %s message\n", (dst_srvid == CTDB_SRVID_RECONFIGURE)
- ? "cluster reconfigure" : "SAMBA_NOTIFY"));
-
- /*
- * Someone from the family died, validate our locks
- */
-
- if (am_parent) {
- messaging_send_buf(msg_ctx, am_parent->cleanupd,
- MSG_SMB_BRL_VALIDATE, NULL, 0);
- }
-
- return 0;
-}
-#endif
-
static void add_child_pid(struct smbd_parent_context *parent,
pid_t pid)
{
DEBUG(1, ("notifyd stopped: %s\n", strerror(ret)));
}
+static void notifyd_sig_hup_handler(struct tevent_context *ev,
+ struct tevent_signal *se,
+ int signum,
+ int count,
+ void *siginfo,
+ void *pvt)
+{
+ DBG_NOTICE("notifyd: Reloading services after SIGHUP\n");
+ reload_services(NULL, NULL, false);
+ reopen_logs();
+}
+
static bool smbd_notifyd_init(struct messaging_context *msg, bool interactive,
struct server_id *ppid)
{
struct tevent_context *ev = messaging_tevent_context(msg);
struct tevent_req *req;
+ struct tevent_signal *se = NULL;
pid_t pid;
NTSTATUS status;
bool ok;
}
if (pid != 0) {
- if (am_parent != 0) {
+ if (am_parent != NULL) {
add_child_pid(am_parent, pid);
}
*ppid = pid_to_procid(pid);
return true;
}
- status = smbd_reinit_after_fork(msg, ev, true, "smbd-notifyd");
+ status = smbd_reinit_after_fork(msg, ev, true);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("%s: reinit_after_fork failed: %s\n",
__func__, nt_errstr(status)));
exit(1);
}
+ process_set_title("smbd-notifyd", "notifyd");
+
+ reopen_logs();
+
+ /* Set up sighup handler for notifyd */
+ se = tevent_add_signal(ev,
+ ev,
+ SIGHUP, 0,
+ notifyd_sig_hup_handler,
+ NULL);
+ if (!se) {
+ DEBUG(0, ("failed to setup notifyd SIGHUP handler\n"));
+ exit(1);
+ }
+
req = notifyd_req(msg, ev);
if (req == NULL) {
exit(1);
tevent_req_set_callback(req, notifyd_stopped, msg);
/* Block those signals that we are not handling */
- BlockSignals(True, SIGHUP);
BlockSignals(True, SIGUSR1);
messaging_send(msg, pid_to_procid(getppid()), MSG_SMB_NOTIFY_STARTED,
}
}
+static void cleanupd_sig_hup_handler(struct tevent_context *ev,
+ struct tevent_signal *se,
+ int signum,
+ int count,
+ void *siginfo,
+ void *pvt)
+{
+ DBG_NOTICE("cleanupd: Reloading services after SIGHUP\n");
+ reopen_logs();
+}
+
static void cleanupd_stopped(struct tevent_req *req);
static bool cleanupd_init(struct messaging_context *msg, bool interactive,
{
struct tevent_context *ev = messaging_tevent_context(msg);
struct server_id parent_id = messaging_server_id(msg);
+ struct tevent_signal *se = NULL;
struct tevent_req *req;
pid_t pid;
NTSTATUS status;
close(up_pipe[0]);
- status = smbd_reinit_after_fork(msg, ev, true, "cleanupd");
+ status = smbd_reinit_after_fork(msg, ev, true);
if (!NT_STATUS_IS_OK(status)) {
DBG_WARNING("reinit_after_fork failed: %s\n",
nt_errstr(status));
exit(1);
}
+ process_set_title("smbd-cleanupd", "cleanupd");
+
+ se = tevent_add_signal(ev,
+ ev,
+ SIGHUP,
+ 0,
+ cleanupd_sig_hup_handler,
+ NULL);
+ if (se == NULL) {
+ DBG_ERR("Could not add SIGHUP handler\n");
+ exit(1);
+ }
+
req = smbd_cleanupd_send(msg, ev, msg, parent_id.pid);
if (req == NULL) {
DBG_WARNING("smbd_cleanupd_send failed\n");
return state->ok;
}
-/*
- at most every smbd:cleanuptime seconds (default 20), we scan the BRL
- and locking database for entries to cleanup. As a side effect this
- also cleans up dead entries in the connections database (due to the
- traversal in message_send_all()
-
- Using a timer for this prevents a flood of traversals when a large
- number of clients disconnect at the same time (perhaps due to a
- network outage).
-*/
-
-static void cleanup_timeout_fn(struct tevent_context *event_ctx,
- struct tevent_timer *te,
- struct timeval now,
- void *private_data)
-{
- struct smbd_parent_context *parent =
- talloc_get_type_abort(private_data,
- struct smbd_parent_context);
-
- parent->cleanup_te = NULL;
-
- messaging_send_buf(parent->msg_ctx, parent->cleanupd,
- MSG_SMB_BRL_VALIDATE, NULL, 0);
-}
-
static void cleanupd_started(struct tevent_req *req)
{
bool ok;
nt_errstr(status));
}
}
-
- if (unclean_shutdown) {
- /* a child terminated uncleanly so tickle all
- processes to see if they can grab any of the
- pending locks
- */
- DEBUG(3,(__location__ " Unclean shutdown of pid %u\n",
- (unsigned int)pid));
- if (parent->cleanup_te == NULL) {
- /* call the cleanup timer, but not too often */
- int cleanup_time = lp_parm_int(-1, "smbd", "cleanuptime", 20);
- parent->cleanup_te = tevent_add_timer(parent->ev_ctx,
- parent,
- timeval_current_ofs(cleanup_time, 0),
- cleanup_timeout_fn,
- parent);
- DEBUG(1,("Scheduled cleanup of brl and lock database after unclean shutdown\n"));
- }
- }
}
/****************************************************************************
smb_set_close_on_exec(fd);
if (s->parent->interactive) {
- reinit_after_fork(msg_ctx, ev, true, NULL);
+ reinit_after_fork(msg_ctx, ev, true);
smbd_process(ev, msg_ctx, fd, true);
exit_server_cleanly("end of interactive mode");
return;
pid = fork();
if (pid == 0) {
+ char addrstr[INET6_ADDRSTRLEN];
NTSTATUS status = NT_STATUS_OK;
/*
* them, counting worker smbds. */
CatchChild();
- status = smbd_reinit_after_fork(msg_ctx, ev, true, NULL);
+ status = smbd_reinit_after_fork(msg_ctx, ev, true);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,
NT_STATUS_TOO_MANY_OPENED_FILES)) {
smb_panic("reinit_after_fork() failed");
}
+ print_sockaddr(addrstr, sizeof(addrstr), &addr);
+ process_set_title("smbd[%s]", "client [%s]", addrstr);
+
smbd_process(ev, msg_ctx, fd, false);
exit:
exit_server_cleanly("end of child");
* writes only two messages for each child
* started/finished. But each child writes,
* say, 50 messages also in logserver.smb,
- * begining with the debug_count of the
+ * beginning with the debug_count of the
* parent, before the child opens its own log
* file logserver.client. In a worst case
* scenario the size of logserver.smb would be
}
s->parent = parent;
- s->fd = open_socket_in(SOCK_STREAM,
- port,
- parent->sockets == NULL ? 0 : 2,
- ifss,
- true);
- if (s->fd == -1) {
- DEBUG(0,("smbd_open_one_socket: open_socket_in: "
- "%s\n", strerror(errno)));
+
+ s->fd = open_socket_in(SOCK_STREAM, ifss, port, true);
+ if (s->fd < 0) {
+ int err = -(s->fd);
+ DBG_ERR("open_socket_in failed: %s\n", strerror(err));
TALLOC_FREE(s);
/*
* We ignore an error here, as we've done before
char *sock_tok;
const char *sock_ptr;
-#if HAVE_IPV6
+#ifdef HAVE_IPV6
sock_addr = "::,0.0.0.0";
#else
sock_addr = "0.0.0.0";
messaging_register(msg_ctx, NULL, MSG_SHUTDOWN, msg_exit_server);
messaging_register(msg_ctx, ev_ctx, MSG_SMB_CONF_UPDATED,
smbd_parent_conf_updated);
- messaging_register(msg_ctx, NULL, MSG_SMB_STAT_CACHE_DELETE,
- smb_stat_cache_delete);
messaging_register(msg_ctx, NULL, MSG_DEBUG, smbd_msg_debug);
messaging_register(msg_ctx, NULL, MSG_SMB_FORCE_TDIS,
smb_parent_send_to_children);
+ messaging_register(msg_ctx, NULL, MSG_SMB_FORCE_TDIS_DENIED,
+ smb_parent_send_to_children);
messaging_register(msg_ctx, NULL, MSG_SMB_KILL_CLIENT_IP,
smb_parent_send_to_children);
messaging_register(msg_ctx, NULL, MSG_SMB_TELL_NUM_CHILDREN,
messaging_register(msg_ctx, NULL, MSG_SMB_NOTIFY_STARTED,
smb_parent_send_to_children);
-#ifdef CLUSTER_SUPPORT
- if (lp_clustering()) {
- struct ctdbd_connection *conn = messaging_ctdb_connection();
-
- register_with_ctdbd(conn, CTDB_SRVID_RECONFIGURE,
- smbd_parent_ctdb_reconfigured, msg_ctx);
- register_with_ctdbd(conn, CTDB_SRVID_SAMBA_NOTIFY,
- smbd_parent_ctdb_reconfigured, msg_ctx);
- }
-#endif
-
#ifdef DEVELOPER
messaging_register(msg_ctx, NULL, MSG_SMB_INJECT_FAULT,
msg_inject_fault);
#endif
+#if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
+ messaging_register(msg_ctx, NULL, MSG_SMB_SLEEP, msg_sleep);
+#endif
+
if (lp_multicast_dns_register() && (dns_port != 0)) {
#ifdef WITH_DNSSD_SUPPORT
smbd_setup_mdns_registration(ev_ctx,
* set from the config file.
*/
- if (!init_names())
- return False;
-
if (!secrets_init())
return False;
void *siginfo,
void *private_data)
{
- struct smbd_parent_context *parent =
- talloc_get_type_abort(private_data,
- struct smbd_parent_context);
-
change_to_root_user();
DEBUG(1,("parent: Reloading services after SIGHUP\n"));
reload_services(NULL, NULL, false);
-
- printing_subsystem_update(parent->ev_ctx, parent->msg_ctx, true);
}
struct smbd_claim_version_state {
char *version;
};
-static void smbd_claim_version_parser(const struct g_lock_rec *locks,
- size_t num_locks,
+static void smbd_claim_version_parser(struct server_id exclusive,
+ size_t num_shared,
+ const struct server_id *shared,
const uint8_t *data,
size_t datalen,
void *private_data)
const char *version)
{
const char *name = "samba_version_string";
+ const TDB_DATA key = string_term_tdb_data(name);
struct smbd_claim_version_state state;
struct g_lock_ctx *ctx;
NTSTATUS status;
return NT_STATUS_UNSUCCESSFUL;
}
- status = g_lock_lock(ctx, string_term_tdb_data(name), G_LOCK_READ,
- (struct timeval) { .tv_sec = 60 });
+ status = g_lock_lock(ctx,
+ key,
+ G_LOCK_READ,
+ (struct timeval) { .tv_sec = 60 },
+ NULL,
+ NULL);
if (!NT_STATUS_IS_OK(status)) {
DBG_WARNING("g_lock_lock(G_LOCK_READ) failed: %s\n",
nt_errstr(status));
state = (struct smbd_claim_version_state) { .mem_ctx = ctx };
- status = g_lock_dump(ctx, string_term_tdb_data(name),
- smbd_claim_version_parser, &state);
+ status = g_lock_dump(ctx, key, smbd_claim_version_parser, &state);
if (!NT_STATUS_IS_OK(status) &&
!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
DBG_ERR("Could not read samba_version_string\n");
- g_lock_unlock(ctx, string_term_tdb_data(name));
+ g_lock_unlock(ctx, key);
TALLOC_FREE(ctx);
return status;
}
return NT_STATUS_OK;
}
- status = g_lock_lock(ctx, string_term_tdb_data(name), G_LOCK_WRITE,
- (struct timeval) { .tv_sec = 60 });
+ status = g_lock_lock(ctx,
+ key,
+ G_LOCK_UPGRADE,
+ (struct timeval) { .tv_sec = 60 },
+ NULL,
+ NULL);
if (!NT_STATUS_IS_OK(status)) {
DBG_WARNING("g_lock_lock(G_LOCK_WRITE) failed: %s\n",
nt_errstr(status));
return NT_STATUS_SXS_VERSION_CONFLICT;
}
- status = g_lock_write_data(ctx, string_term_tdb_data(name),
- (const uint8_t *)version,
- strlen(version)+1);
+ status = g_lock_write_data(
+ ctx, key, (const uint8_t *)version, strlen(version)+1);
if (!NT_STATUS_IS_OK(status)) {
DBG_WARNING("g_lock_write_data failed: %s\n",
nt_errstr(status));
return status;
}
- status = g_lock_lock(ctx, string_term_tdb_data(name), G_LOCK_READ,
- (struct timeval) { .tv_sec = 60 });
+ status = g_lock_lock(ctx,
+ key,
+ G_LOCK_DOWNGRADE,
+ (struct timeval) { .tv_sec = 60 },
+ NULL,
+ NULL);
if (!NT_STATUS_IS_OK(status)) {
DBG_WARNING("g_lock_lock(G_LOCK_READ) failed: %s\n",
nt_errstr(status));
int main(int argc,const char *argv[])
{
/* shall I run as a daemon */
- bool is_daemon = false;
- bool interactive = false;
- bool Fork = true;
- bool no_process_group = false;
+ struct samba_cmdline_daemon_cfg *cmdline_daemon_cfg = NULL;
bool log_stdout = false;
char *ports = NULL;
char *profile_level = NULL;
int opt;
poptContext pc;
- bool print_build_options = False;
struct server_id main_server_id = {0};
- enum {
- OPT_DAEMON = 1000,
- OPT_INTERACTIVE,
- OPT_FORK,
- OPT_NO_PROCESS_GROUP,
- OPT_LOG_STDOUT
- };
struct poptOption long_options[] = {
- POPT_AUTOHELP
- {"daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
- {"interactive", 'i', POPT_ARG_NONE, NULL, OPT_INTERACTIVE, "Run interactive (not a daemon) and log to stdout"},
- {"foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Run daemon in foreground (for daemontools, etc.)" },
- {"no-process-group", '\0', POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
- {"log-stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "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_TABLEEND
+ POPT_AUTOHELP
+ {
+ .longName = "build-options",
+ .shortName = 'b',
+ .argInfo = POPT_ARG_NONE,
+ .arg = NULL,
+ .val = 'b',
+ .descrip = "Print build options" ,
+ },
+ {
+ .longName = "port",
+ .shortName = 'p',
+ .argInfo = POPT_ARG_STRING,
+ .arg = &ports,
+ .val = 0,
+ .descrip = "Listen on the specified ports",
+ },
+ {
+ .longName = "profiling-level",
+ .shortName = 'P',
+ .argInfo = POPT_ARG_STRING,
+ .arg = &profile_level,
+ .val = 0,
+ .descrip = "Set profiling level","PROFILE_LEVEL",
+ },
+ POPT_COMMON_SAMBA
+ POPT_COMMON_DAEMON
+ POPT_COMMON_VERSION
+ POPT_TABLEEND
};
struct smbd_parent_context *parent = NULL;
TALLOC_CTX *frame;
struct tevent_signal *se;
int profiling_level;
char *np_dir = NULL;
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
static const struct smbd_shim smbd_shim_fns =
{
- .cancel_pending_lock_requests_by_fid = smbd_cancel_pending_lock_requests_by_fid,
- .send_stat_cache_delete_message = smbd_send_stat_cache_delete_message,
.change_to_root_user = smbd_change_to_root_user,
.become_authenticated_pipe_user = smbd_become_authenticated_pipe_user,
.unbecome_authenticated_pipe_user = smbd_unbecome_authenticated_pipe_user,
.exit_server = smbd_exit_server,
.exit_server_cleanly = smbd_exit_server_cleanly,
};
+ bool ok;
+
+ setproctitle_init(argc, discard_const(argv), environ);
/*
* Do this before any other talloc operation
talloc_enable_null_tracking();
frame = talloc_stackframe();
- setup_logging(argv[0], DEBUG_DEFAULT_STDOUT);
-
smb_init_locale();
set_smbd_shim(&smbd_shim_fns);
set_auth_parameters(argc,argv);
#endif
- pc = poptGetContext("smbd", argc, argv, long_options, 0);
+ ok = samba_cmdline_init(frame,
+ SAMBA_CMDLINE_CONFIG_SERVER,
+ true /* require_smbconf */);
+ if (!ok) {
+ DBG_ERR("Failed to setup cmdline parser!\n");
+ exit(ENOMEM);
+ }
+
+ cmdline_daemon_cfg = samba_cmdline_get_daemon_cfg();
+
+ pc = samba_popt_get_context(getprogname(),
+ argc,
+ argv,
+ long_options,
+ 0);
+ if (pc == NULL) {
+ DBG_ERR("Failed to get popt context!\n");
+ exit(ENOMEM);
+ }
+
while((opt = poptGetNextOpt(pc)) != -1) {
switch (opt) {
- case OPT_DAEMON:
- is_daemon = true;
- break;
- case OPT_INTERACTIVE:
- interactive = true;
- break;
- case OPT_FORK:
- Fork = false;
- break;
- case OPT_NO_PROCESS_GROUP:
- no_process_group = true;
- break;
- case OPT_LOG_STDOUT:
- log_stdout = true;
- break;
case 'b':
- print_build_options = True;
+ build_options(true); /* Display output to screen as well as debug */
+ exit(0);
break;
default:
d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
}
poptFreeContext(pc);
- if (interactive) {
- Fork = False;
- log_stdout = True;
- }
+ log_stdout = (debug_get_log_type() == DEBUG_STDOUT);
- if (log_stdout) {
- setup_logging(argv[0], DEBUG_STDOUT);
- } else {
- setup_logging(argv[0], DEBUG_FILE);
- }
-
- if (print_build_options) {
- build_options(True); /* Display output to screen as well as debug */
- exit(0);
+ if (cmdline_daemon_cfg->interactive) {
+ log_stdout = True;
}
#ifdef HAVE_SETLUID
set_remote_machine_name("smbd", False);
- if (interactive && (DEBUGLEVEL >= 9)) {
+ if (cmdline_daemon_cfg->interactive && (DEBUGLEVEL >= 9)) {
talloc_enable_leak_report();
}
- if (log_stdout && Fork) {
+ if (log_stdout && cmdline_daemon_cfg->fork) {
DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"));
exit(1);
}
gain_root_privilege();
gain_root_group_privilege();
- fault_setup();
- dump_core_setup("smbd", lp_logfile(talloc_tos()));
+ dump_core_setup("smbd", lp_logfile(talloc_tos(), lp_sub));
/* we are never interested in SIGPIPE */
BlockSignals(True,SIGPIPE);
BlockSignals(True,SIGUSR2);
#endif
- /* POSIX demands that signals are inherited. If the invoking process has
- * these signals masked, we will have problems, as we won't recieve them. */
+ /*
+ * POSIX demands that signals are inherited. If the invoking
+ * process has these signals masked, we will have problems, as
+ * we won't receive them.
+ */
BlockSignals(False, SIGHUP);
BlockSignals(False, SIGUSR1);
BlockSignals(False, SIGTERM);
DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
(int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid()));
- /* Output the build options to the debug log */
+ /* Output the build options to the debug log */
build_options(False);
if (sizeof(uint16_t) < 2 || sizeof(uint32_t) < 4) {
exit(1);
}
- if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
- DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
- exit(1);
- }
+ /*
+ * This calls unshare(CLONE_FS); on linux
+ * in order to check if the running kernel/container
+ * environment supports it.
+ */
+ per_thread_cwd_check();
if (!cluster_probe_ok()) {
exit(1);
* Init the messaging context
* FIXME: This should only call messaging_init()
*/
- msg_ctx = server_messaging_context();
+ msg_ctx = global_messaging_context();
if (msg_ctx == NULL) {
exit(1);
}
exit(1);
}
- if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
- && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
- DEBUG(0, ("server role = 'active directory domain controller' not compatible with running smbd standalone. \n"));
- DEBUGADD(0, ("You should start 'samba' instead, and it will control starting smbd if required\n"));
- exit(1);
+ if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
+ if (!lp_parm_bool(-1, "server role check", "inhibit", false)) {
+ DBG_ERR("server role = 'active directory domain controller' not compatible with running smbd standalone. \n");
+ DEBUGADD(0, ("You should start 'samba' instead, and it will control starting smbd if required\n"));
+ exit(1);
+ }
+ /* Main 'samba' daemon will notify */
+ daemon_sd_notifications(false);
}
/* ...NOTE... Log files are working from this point! */
main_server_id = messaging_server_id(msg_ctx);
set_profile_level(profiling_level, &main_server_id);
- if (!is_daemon && !is_a_socket(0)) {
- if (!interactive) {
+ if (!cmdline_daemon_cfg->daemon && !is_a_socket(0)) {
+ if (!cmdline_daemon_cfg->interactive) {
DEBUG(3, ("Standard input is not a socket, "
"assuming -D option\n"));
}
/*
- * Setting is_daemon here prevents us from eventually calling
+ * Setting "daemon" here prevents us from eventually calling
* the open_sockets_inetd()
*/
- is_daemon = True;
+ cmdline_daemon_cfg->daemon = true;
}
- if (is_daemon && !interactive) {
+ if (cmdline_daemon_cfg->daemon && !cmdline_daemon_cfg->interactive) {
DEBUG(3, ("Becoming a daemon.\n"));
- become_daemon(Fork, no_process_group, log_stdout);
+ become_daemon(cmdline_daemon_cfg->fork,
+ cmdline_daemon_cfg->no_process_group,
+ log_stdout);
+ } else {
+ daemon_status("smbd", "Starting process ...");
}
-#if HAVE_SETPGID
+#ifdef HAVE_SETPGID
/*
* If we're interactive we want to set our own process group for
* signal management.
*/
- if (interactive && !no_process_group)
+ if (cmdline_daemon_cfg->interactive &&
+ !cmdline_daemon_cfg->no_process_group)
+ {
setpgid( (pid_t)0, (pid_t)0);
+ }
#endif
if (!directory_exist(lp_lock_directory()))
if (!directory_exist(lp_pid_directory()))
mkdir(lp_pid_directory(), 0755);
- if (is_daemon)
+ if (cmdline_daemon_cfg->daemon)
pidfile_create(lp_pid_directory(), "smbd");
- status = reinit_after_fork(msg_ctx, ev_ctx, false, NULL);
+ status = reinit_after_fork(msg_ctx, ev_ctx, false);
if (!NT_STATUS_IS_OK(status)) {
exit_daemon("reinit_after_fork() failed", map_errno_from_nt_status(status));
}
- if (!interactive) {
+ if (!cmdline_daemon_cfg->interactive) {
/*
* Do not initialize the parent-child-pipe before becoming a
* daemon: this is used to detect a died parent in the child
if (!parent) {
exit_server("talloc(struct smbd_parent_context) failed");
}
- parent->interactive = interactive;
+ parent->interactive = cmdline_daemon_cfg->interactive;
parent->ev_ctx = ev_ctx;
parent->msg_ctx = msg_ctx;
am_parent = parent;
exit_daemon("smbd can not open secrets.tdb", EACCES);
}
- if (lp_server_role() == ROLE_DOMAIN_BDC || lp_server_role() == ROLE_DOMAIN_PDC) {
+ if (lp_server_role() == ROLE_DOMAIN_BDC || lp_server_role() == ROLE_DOMAIN_PDC || lp_server_role() == ROLE_IPA_DC) {
struct loadparm_context *lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
if (!open_schannel_session_store(NULL, lp_ctx)) {
exit_daemon("ERROR: Samba cannot open schannel store for secured NETLOGON operations.", EACCES);
exit_daemon("Samba cannot init leases", EACCES);
}
- if (!smbd_notifyd_init(msg_ctx, interactive, &parent->notifyd)) {
+ if (!smbd_notifyd_init(
+ msg_ctx,
+ cmdline_daemon_cfg->interactive,
+ &parent->notifyd)) {
exit_daemon("Samba cannot init notification", EACCES);
}
- if (!cleanupd_init(msg_ctx, interactive, &parent->cleanupd)) {
+ if (!cleanupd_init(
+ msg_ctx,
+ cmdline_daemon_cfg->interactive,
+ &parent->cleanupd)) {
exit_daemon("Samba cannot init the cleanupd", EACCES);
}
after the fork on every single connection. This is a small
performance improvment and reduces the total number of system
fds used. */
- if (!share_info_db_init()) {
+ status = share_info_db_init();
+ if (!NT_STATUS_IS_OK(status)) {
exit_daemon("ERROR: failed to load share info db.", EACCES);
}
if (lp_clustering() && !lp_allow_unsafe_cluster_upgrade()) {
status = smbd_claim_version(msg_ctx, samba_version_string());
if (!NT_STATUS_IS_OK(status)) {
- DBG_WARNING("Could not claim version: %s\n",
+ DBG_ERR("Could not claim version: %s\n",
nt_errstr(status));
return -1;
}
return -1;
}
- if (is_daemon && !interactive) {
- if (rpc_epmapper_daemon() == RPC_DAEMON_FORK) {
- start_epmd(ev_ctx, msg_ctx);
- }
- }
-
- if (!dcesrv_ep_setup(ev_ctx, msg_ctx)) {
- exit_daemon("Samba cannot setup ep pipe", EACCES);
- }
-
- if (is_daemon && !interactive) {
+ if (!cmdline_daemon_cfg->interactive) {
daemon_ready("smbd");
}
- /* only start other daemons if we are running as a daemon
- * -- bad things will happen if smbd is launched via inetd
- * and we fork a copy of ourselves here */
- if (is_daemon && !interactive) {
-
- if (rpc_lsasd_daemon() == RPC_DAEMON_FORK) {
- start_lsasd(ev_ctx, msg_ctx);
- }
-
- if (rpc_fss_daemon() == RPC_DAEMON_FORK) {
- start_fssd(ev_ctx, msg_ctx);
- }
-
- if (!lp__disable_spoolss() &&
- (rpc_spoolss_daemon() != RPC_DAEMON_DISABLED)) {
- bool bgq = lp_parm_bool(-1, "smbd", "backgroundqueue", true);
-
- if (!printing_subsystem_init(ev_ctx, msg_ctx, true, bgq)) {
- exit_daemon("Samba failed to init printing subsystem", EACCES);
- }
- }
-
-#ifdef WITH_SPOTLIGHT
- if ((rpc_mdssvc_mode() == RPC_SERVICE_MODE_EXTERNAL) &&
- (rpc_mdssd_daemon() == RPC_DAEMON_FORK)) {
- start_mdssd(ev_ctx, msg_ctx);
- }
-#endif
- } else if (!lp__disable_spoolss() &&
- (rpc_spoolss_daemon() != RPC_DAEMON_DISABLED)) {
- if (!printing_subsystem_init(ev_ctx, msg_ctx, false, false)) {
- exit(1);
- }
- }
-
- if (!is_daemon) {
- int sock;
+ if (!cmdline_daemon_cfg->daemon) {
+ int ret, sock;
/* inetd mode */
TALLOC_FREE(frame);
sock = dup(0);
/* close stdin, stdout (if not logging to it), but not stderr */
- close_low_fds(true, !debug_get_output_is_stdout(), false);
+ ret = close_low_fd(0);
+ if (ret != 0) {
+ DBG_ERR("close_low_fd(0) failed: %s\n", strerror(ret));
+ return 1;
+ }
+ if (!debug_get_output_is_stdout()) {
+ ret = close_low_fd(1);
+ if (ret != 0) {
+ DBG_ERR("close_low_fd(1) failed: %s\n",
+ strerror(ret));
+ return 1;
+ }
+ }
#ifdef HAVE_ATEXIT
atexit(killkids);
if (!open_sockets_smbd(parent, ev_ctx, msg_ctx, ports))
exit_server("open_sockets_smbd() failed");
- /* do a printer update now that all messaging has been set up,
- * before we allow clients to start connecting */
- if (!lp__disable_spoolss() &&
- (rpc_spoolss_daemon() != RPC_DAEMON_DISABLED)) {
- printing_subsystem_update(ev_ctx, msg_ctx, false);
- }
-
TALLOC_FREE(frame);
/* make sure we always have a valid stackframe */
frame = talloc_stackframe();
- if (!Fork) {
+ if (!cmdline_daemon_cfg->fork) {
/* if we are running in the foreground then look for
EOF on stdin, and exit if it happens. This allows
us to die if the parent process dies
*/
struct stat st;
if (fstat(0, &st) != 0) {
- return false;
+ return 1;
}
if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
tevent_add_fd(ev_ctx,