summaryrefslogtreecommitdiff
path: root/source3/utils/smbcontrol.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/utils/smbcontrol.c')
-rw-r--r--source3/utils/smbcontrol.c114
1 files changed, 112 insertions, 2 deletions
diff --git a/source3/utils/smbcontrol.c b/source3/utils/smbcontrol.c
index a4d2766b13..405e51cd25 100644
--- a/source3/utils/smbcontrol.c
+++ b/source3/utils/smbcontrol.c
@@ -584,6 +584,107 @@ static BOOL do_drvupgrade(const struct process_id pid,
pid, MSG_DEBUG, argv[1], strlen(argv[1]) + 1, False);
}
+static BOOL do_winbind_online(const struct process_id pid,
+ const int argc, const char **argv)
+{
+ TDB_CONTEXT *tdb;
+
+ if (argc != 1) {
+ fprintf(stderr, "Usage: smbcontrol winbindd online\n");
+ return False;
+ }
+
+ if (!lp_winbind_offline_logon()) {
+ fprintf(stderr, "The parameter \"winbind offline logon\" must "
+ "be set in the [global] section of smb.conf for this "
+ "command to be allowed.\n");
+ return False;
+ }
+
+ /* Remove the entry in the winbindd_cache tdb to tell a later
+ starting winbindd that we're online. */
+
+ tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
+ if (!tdb) {
+ fprintf(stderr, "Cannot open the tdb %s for writing.\n",
+ lock_path("winbindd_cache.tdb"));
+ return False;
+ }
+
+ tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
+ tdb_close(tdb);
+
+ return send_message(pid, MSG_WINBIND_ONLINE, NULL, 0, False);
+}
+
+static BOOL do_winbind_offline(const struct process_id pid,
+ const int argc, const char **argv)
+{
+ TDB_CONTEXT *tdb;
+ BOOL ret = False;
+ int retry = 0;
+
+ if (argc != 1) {
+ fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
+ return False;
+ }
+
+ if (!lp_winbind_offline_logon()) {
+ fprintf(stderr, "The parameter \"winbind offline logon\" must "
+ "be set in the [global] section of smb.conf for this "
+ "command to be allowed.\n");
+ return False;
+ }
+
+ /* Create an entry in the winbindd_cache tdb to tell a later
+ starting winbindd that we're offline. We may actually create
+ it here... */
+
+ tdb = tdb_open_log(lock_path("winbindd_cache.tdb"),
+ WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
+ TDB_DEFAULT /* TDB_CLEAR_IF_FIRST */, O_RDWR|O_CREAT, 0600);
+
+ if (!tdb) {
+ fprintf(stderr, "Cannot open the tdb %s for writing.\n",
+ lock_path("winbindd_cache.tdb"));
+ return False;
+ }
+
+ /* There's a potential race condition that if a child
+ winbindd detects a domain is online at the same time
+ we're trying to tell it to go offline that it might
+ delete the record we add between us adding it and
+ sending the message. Minimize this by retrying up to
+ 5 times. */
+
+ for (retry = 0; retry < 5; retry++) {
+ int err;
+ TDB_DATA d;
+ ZERO_STRUCT(d);
+ tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
+
+ ret = send_message(pid, MSG_WINBIND_OFFLINE, NULL, 0, False);
+
+ /* Check that the entry "WINBINDD_OFFLINE" still exists. */
+ tdb->ecode = 0;
+ d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
+
+ /* As this is a key with no data we don't need to free, we
+ check for existence by looking at tdb_err. */
+
+ err = tdb_error(tdb);
+
+ if (err == TDB_ERR_NOEXIST) {
+ DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
+ } else {
+ break;
+ }
+ }
+
+ tdb_close(tdb);
+ return ret;
+}
+
static BOOL do_reload_config(const struct process_id pid,
const int argc, const char **argv)
{
@@ -668,6 +769,8 @@ static const struct {
{ "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
{ "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
{ "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
+ { "online", do_winbind_online, "Ask winbind to go into online state"},
+ { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
{ "noop", do_noop, "Do nothing" },
{ NULL }
};
@@ -681,7 +784,7 @@ static void usage(poptContext *pc)
poptPrintHelp(*pc, stderr, 0);
fprintf(stderr, "\n");
- fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\" or a "
+ fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
"process ID\n");
fprintf(stderr, "\n");
@@ -715,10 +818,17 @@ static struct process_id parse_dest(const char *dest)
return pid_to_procid(sys_getpid());
}
+ /* Fix winbind typo. */
+ if (strequal(dest, "winbind")) {
+ dest = "winbindd";
+ }
+
/* Check for numeric pid number */
result = interpret_pid(dest);
- if (procid_valid(&result)) {
+
+ /* Zero isn't valid if not smbd. */
+ if (result.pid && procid_valid(&result)) {
return result;
}