2 Unix SMB/CIFS implementation.
4 Send messages to other Samba daemons
6 Copyright (C) Tim Potter 2003
7 Copyright (C) Andrew Tridgell 1994-1998
8 Copyright (C) Martin Pool 2001-2002
9 Copyright (C) Simo Sorce 2002
10 Copyright (C) James Peach 2006
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include "system/filesys.h"
28 #include "popt_common.h"
29 #include "librpc/gen_ndr/spoolss.h"
30 #include "nt_printing.h"
31 #include "printing/notify.h"
32 #include "libsmb/nmblib.h"
37 #include <libunwind.h>
40 #if HAVE_LIBUNWIND_PTRACE_H
41 #include <libunwind-ptrace.h>
45 #include <sys/ptrace.h>
48 /* Default timeout value when waiting for replies (in seconds) */
50 #define DEFAULT_TIMEOUT 10
52 static int timeout = DEFAULT_TIMEOUT;
53 static int num_replies; /* Used by message callback fns */
55 /* Send a message to a destination pid. Zero means broadcast smbd. */
57 static bool send_message(struct messaging_context *msg_ctx,
58 struct server_id pid, int msg_type,
59 const void *buf, int len)
64 if (procid_to_pid(&pid) != 0)
65 return NT_STATUS_IS_OK(
66 messaging_send_buf(msg_ctx, pid, msg_type,
67 (const uint8 *)buf, len));
69 ret = message_send_all(msg_ctx, msg_type, buf, len, &n_sent);
70 DEBUG(10,("smbcontrol/send_message: broadcast message to "
71 "%d processes\n", n_sent));
76 static void smbcontrol_timeout(struct tevent_context *event_ctx,
77 struct tevent_timer *te,
81 bool *timed_out = (bool *)private_data;
86 /* Wait for one or more reply messages */
88 static void wait_replies(struct messaging_context *msg_ctx,
89 bool multiple_replies)
91 struct tevent_timer *te;
92 bool timed_out = False;
94 if (!(te = tevent_add_timer(messaging_event_context(msg_ctx), NULL,
95 timeval_current_ofs(timeout, 0),
96 smbcontrol_timeout, (void *)&timed_out))) {
97 DEBUG(0, ("tevent_add_timer failed\n"));
103 if (num_replies > 0 && !multiple_replies)
105 ret = tevent_loop_once(messaging_event_context(msg_ctx));
112 /* Message handler callback that displays the PID and a string on stdout */
114 static void print_pid_string_cb(struct messaging_context *msg,
117 struct server_id pid,
122 pidstr = server_id_str(talloc_tos(), &pid);
123 printf("PID %s: %.*s", pidstr, (int)data->length,
124 (const char *)data->data);
129 /* Message handler callback that displays a string on stdout */
131 static void print_string_cb(struct messaging_context *msg,
134 struct server_id pid,
137 printf("%*s", (int)data->length, (const char *)data->data);
141 /* Send no message. Useful for testing. */
143 static bool do_noop(struct tevent_context *ev_ctx,
144 struct messaging_context *msg_ctx,
145 const struct server_id pid,
146 const int argc, const char **argv)
149 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
153 /* Move along, nothing to see here */
158 /* Send a debug string */
160 static bool do_debug(struct tevent_context *ev_ctx,
161 struct messaging_context *msg_ctx,
162 const struct server_id pid,
163 const int argc, const char **argv)
166 fprintf(stderr, "Usage: smbcontrol <dest> debug "
171 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
172 strlen(argv[1]) + 1);
176 static bool do_idmap(struct tevent_context *ev,
177 struct messaging_context *msg_ctx,
178 const struct server_id pid,
179 const int argc, const char **argv)
181 static const char* usage = "Usage: "
182 "smbcontrol <dest> idmap <cmd> [arg]\n"
183 "\tcmd:\tflush [gid|uid]\n"
184 "\t\tdelete \"UID <uid>\"|\"GID <gid>\"|<sid>\n"
185 "\t\tkill \"UID <uid>\"|\"GID <gid>\"|<sid>\n";
186 const char* arg = NULL;
195 arglen = strlen(arg) + 1;
198 fprintf(stderr, "%s", usage);
202 if (strcmp(argv[1], "flush") == 0) {
203 msg_type = ID_CACHE_FLUSH;
205 else if (strcmp(argv[1], "delete") == 0) {
206 msg_type = ID_CACHE_DELETE;
208 else if (strcmp(argv[1], "kill") == 0) {
209 msg_type = ID_CACHE_KILL;
211 else if (strcmp(argv[1], "help") == 0) {
212 fprintf(stdout, "%s", usage);
216 fprintf(stderr, "%s", usage);
220 return send_message(msg_ctx, pid, msg_type, arg, arglen);
224 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
226 /* Return the name of a process given it's PID. This will only work on Linux,
227 * but that's probably moot since this whole stack tracing implementatino is
228 * Linux-specific anyway.
230 static const char * procname(pid_t pid, char * buf, size_t bufsz)
235 snprintf(path, sizeof(path), "/proc/%llu/cmdline",
236 (unsigned long long)pid);
237 if ((fp = fopen(path, "r")) == NULL) {
241 fgets(buf, bufsz, fp);
247 static void print_stack_trace(pid_t pid, int * count)
250 unw_addr_space_t aspace = NULL;
259 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
261 "Failed to attach to process %llu: %s\n",
262 (unsigned long long)pid, strerror(errno));
266 /* Wait until the attach is complete. */
267 waitpid(pid, NULL, 0);
269 if (((pinfo = _UPT_create(pid)) == NULL) ||
270 ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
271 /* Probably out of memory. */
273 "Unable to initialize stack unwind for process %llu\n",
274 (unsigned long long)pid);
278 if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
280 "Unable to unwind stack for process %llu: %s\n",
281 (unsigned long long)pid, unw_strerror(ret));
289 if (procname(pid, nbuf, sizeof(nbuf))) {
290 printf("Stack trace for process %llu (%s):\n",
291 (unsigned long long)pid, nbuf);
293 printf("Stack trace for process %llu:\n",
294 (unsigned long long)pid);
297 while (unw_step(&cursor) > 0) {
299 unw_get_reg(&cursor, UNW_REG_IP, &ip);
300 unw_get_reg(&cursor, UNW_REG_SP, &sp);
302 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
303 if (ret != 0 && ret != -UNW_ENOMEM) {
304 snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
306 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
307 nbuf, (long long)off, (long long)ip,
315 unw_destroy_addr_space(aspace);
322 ptrace(PTRACE_DETACH, pid, NULL, NULL);
325 static int stack_trace_connection(const struct connections_key *key,
326 const struct connections_data *crec,
329 print_stack_trace(procid_to_pid(&crec->pid), (int *)priv);
334 static bool do_daemon_stack_trace(struct tevent_context *ev_ctx,
335 struct messaging_context *msg_ctx,
336 const struct server_id pid,
337 const int argc, const char **argv)
343 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
347 dest = procid_to_pid(&pid);
350 /* It would be nice to be able to make sure that this PID is
351 * the PID of a smbd/winbind/nmbd process, not some random PID
352 * the user liked the look of. It doesn't seem like it's worth
353 * the effort at the moment, however.
355 print_stack_trace(dest, &count);
357 connections_forall_read(stack_trace_connection, &count);
363 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
365 static bool do_daemon_stack_trace(struct tevent_context *ev_ctx,
366 struct messaging_context *msg_ctx,
367 const struct server_id pid,
368 const int argc, const char **argv)
371 "Daemon stack tracing is not supported on this platform\n");
375 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
377 /* Inject a fault (fatal signal) into a running smbd */
379 static bool do_inject_fault(struct tevent_context *ev_ctx,
380 struct messaging_context *msg_ctx,
381 const struct server_id pid,
382 const int argc, const char **argv)
385 fprintf(stderr, "Usage: smbcontrol <dest> inject "
386 "<bus|hup|term|internal|segv>\n");
391 fprintf(stderr, "Fault injection is only available in "
392 "developer builds\n");
394 #else /* DEVELOPER */
398 if (strcmp(argv[1], "bus") == 0) {
400 } else if (strcmp(argv[1], "hup") == 0) {
402 } else if (strcmp(argv[1], "term") == 0) {
404 } else if (strcmp(argv[1], "segv") == 0) {
406 } else if (strcmp(argv[1], "internal") == 0) {
407 /* Force an internal error, ie. an unclean exit. */
410 fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
414 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
417 #endif /* DEVELOPER */
420 /* Force a browser election */
422 static bool do_election(struct tevent_context *ev_ctx,
423 struct messaging_context *msg_ctx,
424 const struct server_id pid,
425 const int argc, const char **argv)
428 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
432 return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
435 /* Ping a samba daemon process */
437 static void pong_cb(struct messaging_context *msg,
440 struct server_id pid,
443 char *src_string = server_id_str(NULL, &pid);
444 printf("PONG from pid %s\n", src_string);
445 TALLOC_FREE(src_string);
449 static bool do_ping(struct tevent_context *ev_ctx,
450 struct messaging_context *msg_ctx,
451 const struct server_id pid,
452 const int argc, const char **argv)
455 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
459 /* Send a message and register our interest in a reply */
461 if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
464 messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
466 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
468 /* No replies were received within the timeout period */
470 if (num_replies == 0)
471 printf("No replies received\n");
473 messaging_deregister(msg_ctx, MSG_PONG, NULL);
478 /* Set profiling options */
480 static bool do_profile(struct tevent_context *ev_ctx,
481 struct messaging_context *msg_ctx,
482 const struct server_id pid,
483 const int argc, const char **argv)
488 fprintf(stderr, "Usage: smbcontrol <dest> profile "
489 "<off|count|on|flush>\n");
493 if (strcmp(argv[1], "off") == 0) {
495 } else if (strcmp(argv[1], "count") == 0) {
497 } else if (strcmp(argv[1], "on") == 0) {
499 } else if (strcmp(argv[1], "flush") == 0) {
502 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
506 return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
509 /* Return the profiling level */
511 static void profilelevel_cb(struct messaging_context *msg_ctx,
514 struct server_id pid,
522 if (data->length != sizeof(int)) {
523 fprintf(stderr, "invalid message length %ld returned\n",
524 (unsigned long)data->length);
528 memcpy(&level, data->data, sizeof(int));
541 s = "count and time";
548 printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
551 static void profilelevel_rqst(struct messaging_context *msg_ctx,
554 struct server_id pid,
559 /* Send back a dummy reply */
561 send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
564 static bool do_profilelevel(struct tevent_context *ev_ctx,
565 struct messaging_context *msg_ctx,
566 const struct server_id pid,
567 const int argc, const char **argv)
570 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
574 /* Send a message and register our interest in a reply */
576 if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
579 messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
580 messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
583 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
585 /* No replies were received within the timeout period */
587 if (num_replies == 0)
588 printf("No replies received\n");
590 messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
595 /* Display debug level settings */
597 static bool do_debuglevel(struct tevent_context *ev_ctx,
598 struct messaging_context *msg_ctx,
599 const struct server_id pid,
600 const int argc, const char **argv)
603 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
607 /* Send a message and register our interest in a reply */
609 if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
612 messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
614 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
616 /* No replies were received within the timeout period */
618 if (num_replies == 0)
619 printf("No replies received\n");
621 messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
626 /* Send a print notify message */
628 static bool do_printnotify(struct tevent_context *ev_ctx,
629 struct messaging_context *msg_ctx,
630 const struct server_id pid,
631 const int argc, const char **argv)
635 /* Check for subcommand */
638 fprintf(stderr, "Must specify subcommand:\n");
639 fprintf(stderr, "\tqueuepause <printername>\n");
640 fprintf(stderr, "\tqueueresume <printername>\n");
641 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
642 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
643 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
644 fprintf(stderr, "\tprinter <printername> <comment|port|"
645 "driver> <value>\n");
652 if (strcmp(cmd, "queuepause") == 0) {
655 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
656 " queuepause <printername>\n");
660 notify_printer_status_byname(messaging_event_context(msg_ctx),
662 PRINTER_STATUS_PAUSED);
666 } else if (strcmp(cmd, "queueresume") == 0) {
669 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
670 " queuereume <printername>\n");
674 notify_printer_status_byname(messaging_event_context(msg_ctx),
680 } else if (strcmp(cmd, "jobpause") == 0) {
684 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
685 " jobpause <printername> <unix-jobid>\n");
689 jobid = atoi(argv[3]);
691 notify_job_status_byname(
692 messaging_event_context(msg_ctx), msg_ctx,
693 argv[2], jobid, JOB_STATUS_PAUSED,
694 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
698 } else if (strcmp(cmd, "jobresume") == 0) {
702 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
703 " jobpause <printername> <unix-jobid>\n");
707 jobid = atoi(argv[3]);
709 notify_job_status_byname(
710 messaging_event_context(msg_ctx), msg_ctx,
711 argv[2], jobid, JOB_STATUS_QUEUED,
712 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
716 } else if (strcmp(cmd, "jobdelete") == 0) {
720 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
721 " jobpause <printername> <unix-jobid>\n");
725 jobid = atoi(argv[3]);
727 notify_job_status_byname(
728 messaging_event_context(msg_ctx), msg_ctx,
729 argv[2], jobid, JOB_STATUS_DELETING,
730 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
732 notify_job_status_byname(
733 messaging_event_context(msg_ctx), msg_ctx,
734 argv[2], jobid, JOB_STATUS_DELETING|
736 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
740 } else if (strcmp(cmd, "printer") == 0) {
744 fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
745 "printer <printername> <comment|port|driver> "
750 if (strcmp(argv[3], "comment") == 0) {
751 attribute = PRINTER_NOTIFY_FIELD_COMMENT;
752 } else if (strcmp(argv[3], "port") == 0) {
753 attribute = PRINTER_NOTIFY_FIELD_PORT_NAME;
754 } else if (strcmp(argv[3], "driver") == 0) {
755 attribute = PRINTER_NOTIFY_FIELD_DRIVER_NAME;
757 fprintf(stderr, "Invalid printer command '%s'\n",
762 notify_printer_byname(messaging_event_context(msg_ctx),
763 msg_ctx, argv[2], attribute,
764 discard_const_p(char, argv[4]));
769 fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
773 print_notify_send_messages(msg_ctx, 0);
779 static bool do_closeshare(struct tevent_context *ev_ctx,
780 struct messaging_context *msg_ctx,
781 const struct server_id pid,
782 const int argc, const char **argv)
785 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
790 return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
791 strlen(argv[1]) + 1);
794 /* Tell winbindd an IP got dropped */
796 static bool do_ip_dropped(struct tevent_context *ev_ctx,
797 struct messaging_context *msg_ctx,
798 const struct server_id pid,
799 const int argc, const char **argv)
802 fprintf(stderr, "Usage: smbcontrol <dest> ip-dropped "
807 return send_message(msg_ctx, pid, MSG_WINBIND_IP_DROPPED, argv[1],
808 strlen(argv[1]) + 1);
811 /* force a blocking lock retry */
813 static bool do_lockretry(struct tevent_context *ev_ctx,
814 struct messaging_context *msg_ctx,
815 const struct server_id pid,
816 const int argc, const char **argv)
819 fprintf(stderr, "Usage: smbcontrol <dest> lockretry\n");
823 return send_message(msg_ctx, pid, MSG_SMB_UNLOCK, NULL, 0);
826 /* force a validation of all brl entries, including re-sends. */
828 static bool do_brl_revalidate(struct tevent_context *ev_ctx,
829 struct messaging_context *msg_ctx,
830 const struct server_id pid,
831 const int argc, const char **argv)
834 fprintf(stderr, "Usage: smbcontrol <dest> brl-revalidate\n");
838 return send_message(msg_ctx, pid, MSG_SMB_BRL_VALIDATE, NULL, 0);
841 /* Display talloc pool usage */
843 static bool do_poolusage(struct tevent_context *ev_ctx,
844 struct messaging_context *msg_ctx,
845 const struct server_id pid,
846 const int argc, const char **argv)
849 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
853 messaging_register(msg_ctx, NULL, MSG_POOL_USAGE, print_string_cb);
855 /* Send a message and register our interest in a reply */
857 if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0))
860 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
862 /* No replies were received within the timeout period */
864 if (num_replies == 0)
865 printf("No replies received\n");
867 messaging_deregister(msg_ctx, MSG_POOL_USAGE, NULL);
872 /* Perform a dmalloc mark */
874 static bool do_dmalloc_mark(struct tevent_context *ev_ctx,
875 struct messaging_context *msg_ctx,
876 const struct server_id pid,
877 const int argc, const char **argv)
880 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
884 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
887 /* Perform a dmalloc changed */
889 static bool do_dmalloc_changed(struct tevent_context *ev_ctx,
890 struct messaging_context *msg_ctx,
891 const struct server_id pid,
892 const int argc, const char **argv)
895 fprintf(stderr, "Usage: smbcontrol <dest> "
896 "dmalloc-log-changed\n");
900 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
904 /* Shutdown a server process */
906 static bool do_shutdown(struct tevent_context *ev_ctx,
907 struct messaging_context *msg_ctx,
908 const struct server_id pid,
909 const int argc, const char **argv)
912 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
916 return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
919 /* Notify a driver upgrade */
921 static bool do_drvupgrade(struct tevent_context *ev_ctx,
922 struct messaging_context *msg_ctx,
923 const struct server_id pid,
924 const int argc, const char **argv)
927 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
932 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
933 strlen(argv[1]) + 1);
936 static bool do_winbind_online(struct tevent_context *ev_ctx,
937 struct messaging_context *msg_ctx,
938 const struct server_id pid,
939 const int argc, const char **argv)
944 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
948 /* Remove the entry in the winbindd_cache tdb to tell a later
949 starting winbindd that we're online. */
951 tdb = tdb_open_log(state_path("winbindd_cache.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
953 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
954 state_path("winbindd_cache.tdb"));
958 tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
961 return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
964 static bool do_winbind_offline(struct tevent_context *ev_ctx,
965 struct messaging_context *msg_ctx,
966 const struct server_id pid,
967 const int argc, const char **argv)
974 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
978 /* Create an entry in the winbindd_cache tdb to tell a later
979 starting winbindd that we're offline. We may actually create
982 tdb = tdb_open_log(state_path("winbindd_cache.tdb"),
983 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
984 TDB_DEFAULT|TDB_INCOMPATIBLE_HASH /* TDB_CLEAR_IF_FIRST */,
985 O_RDWR|O_CREAT, 0600);
988 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
989 state_path("winbindd_cache.tdb"));
993 /* There's a potential race condition that if a child
994 winbindd detects a domain is online at the same time
995 we're trying to tell it to go offline that it might
996 delete the record we add between us adding it and
997 sending the message. Minimize this by retrying up to
1000 for (retry = 0; retry < 5; retry++) {
1006 SIVAL(buf, 0, time(NULL));
1010 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
1012 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
1015 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
1016 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
1018 if (!d.dptr || d.dsize != 4) {
1020 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
1031 static bool do_winbind_onlinestatus(struct tevent_context *ev_ctx,
1032 struct messaging_context *msg_ctx,
1033 const struct server_id pid,
1034 const int argc, const char **argv)
1036 struct server_id myid;
1038 myid = messaging_server_id(msg_ctx);
1041 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
1045 messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
1046 print_pid_string_cb);
1048 if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, &myid,
1052 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1054 /* No replies were received within the timeout period */
1056 if (num_replies == 0)
1057 printf("No replies received\n");
1059 messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
1064 static bool do_dump_event_list(struct tevent_context *ev_ctx,
1065 struct messaging_context *msg_ctx,
1066 const struct server_id pid,
1067 const int argc, const char **argv)
1069 struct server_id myid;
1071 myid = messaging_server_id(msg_ctx);
1074 fprintf(stderr, "Usage: smbcontrol <dest> dump-event-list\n");
1078 return send_message(msg_ctx, pid, MSG_DUMP_EVENT_LIST, NULL, 0);
1081 static bool do_winbind_dump_domain_list(struct tevent_context *ev_ctx,
1082 struct messaging_context *msg_ctx,
1083 const struct server_id pid,
1084 const int argc, const char **argv)
1086 const char *domain = NULL;
1088 struct server_id myid;
1089 uint8_t *buf = NULL;
1092 myid = messaging_server_id(msg_ctx);
1094 if (argc < 1 || argc > 2) {
1095 fprintf(stderr, "Usage: smbcontrol <dest> dump-domain-list "
1102 domain_len = strlen(argv[1]) + 1;
1105 messaging_register(msg_ctx, NULL, MSG_WINBIND_DUMP_DOMAIN_LIST,
1106 print_pid_string_cb);
1108 buf_len = sizeof(myid)+domain_len;
1109 buf = SMB_MALLOC_ARRAY(uint8_t, buf_len);
1114 memcpy(buf, &myid, sizeof(myid));
1115 memcpy(&buf[sizeof(myid)], domain, domain_len);
1117 if (!send_message(msg_ctx, pid, MSG_WINBIND_DUMP_DOMAIN_LIST,
1124 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1126 /* No replies were received within the timeout period */
1129 if (num_replies == 0) {
1130 printf("No replies received\n");
1133 messaging_deregister(msg_ctx, MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
1138 static void winbind_validate_cache_cb(struct messaging_context *msg,
1141 struct server_id pid,
1144 char *src_string = server_id_str(NULL, &pid);
1145 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1146 (*(data->data) == 0 ? "" : "NOT "), src_string);
1147 TALLOC_FREE(src_string);
1151 static bool do_winbind_validate_cache(struct tevent_context *ev_ctx,
1152 struct messaging_context *msg_ctx,
1153 const struct server_id pid,
1154 const int argc, const char **argv)
1156 struct server_id myid;
1158 myid = messaging_server_id(msg_ctx);
1161 fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
1165 messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
1166 winbind_validate_cache_cb);
1168 if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
1173 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1175 if (num_replies == 0) {
1176 printf("No replies received\n");
1179 messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);
1184 static bool do_reload_config(struct tevent_context *ev_ctx,
1185 struct messaging_context *msg_ctx,
1186 const struct server_id pid,
1187 const int argc, const char **argv)
1190 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1194 return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1197 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1200 memset( (char *)n, '\0', sizeof(struct nmb_name) );
1201 fstrcpy(unix_name, name);
1202 strupper_m(unix_name);
1203 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1204 n->name_type = (unsigned int)type & 0xFF;
1205 push_ascii(n->scope, lp_netbios_scope(), 64, STR_TERMINATE);
1208 static bool do_nodestatus(struct tevent_context *ev_ctx,
1209 struct messaging_context *msg_ctx,
1210 const struct server_id pid,
1211 const int argc, const char **argv)
1213 struct packet_struct p;
1216 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1222 p.ip = interpret_addr2(argv[1]);
1224 p.packet_type = NMB_PACKET;
1226 p.packet.nmb.header.name_trn_id = 10;
1227 p.packet.nmb.header.opcode = 0;
1228 p.packet.nmb.header.response = False;
1229 p.packet.nmb.header.nm_flags.bcast = False;
1230 p.packet.nmb.header.nm_flags.recursion_available = False;
1231 p.packet.nmb.header.nm_flags.recursion_desired = False;
1232 p.packet.nmb.header.nm_flags.trunc = False;
1233 p.packet.nmb.header.nm_flags.authoritative = False;
1234 p.packet.nmb.header.rcode = 0;
1235 p.packet.nmb.header.qdcount = 1;
1236 p.packet.nmb.header.ancount = 0;
1237 p.packet.nmb.header.nscount = 0;
1238 p.packet.nmb.header.arcount = 0;
1239 my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1240 p.packet.nmb.question.question_type = 0x21;
1241 p.packet.nmb.question.question_class = 0x1;
1243 return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1246 /* A list of message type supported */
1248 static const struct {
1249 const char *name; /* Option name */
1250 bool (*fn)(struct tevent_context *ev_ctx,
1251 struct messaging_context *msg_ctx,
1252 const struct server_id pid,
1253 const int argc, const char **argv);
1254 const char *help; /* Short help text */
1256 { "debug", do_debug, "Set debuglevel" },
1257 { "idmap", do_idmap, "Manipulate idmap cache" },
1258 { "force-election", do_election,
1259 "Force a browse election" },
1260 { "ping", do_ping, "Elicit a response" },
1261 { "profile", do_profile, "" },
1262 { "inject", do_inject_fault,
1263 "Inject a fatal signal into a running smbd"},
1264 { "stacktrace", do_daemon_stack_trace,
1265 "Display a stack trace of a daemon" },
1266 { "profilelevel", do_profilelevel, "" },
1267 { "debuglevel", do_debuglevel, "Display current debuglevels" },
1268 { "printnotify", do_printnotify, "Send a print notify message" },
1269 { "close-share", do_closeshare, "Forcibly disconnect a share" },
1270 { "ip-dropped", do_ip_dropped, "Tell winbind that an IP got dropped" },
1271 { "lockretry", do_lockretry, "Force a blocking lock retry" },
1272 { "brl-revalidate", do_brl_revalidate, "Revalidate all brl entries" },
1273 { "pool-usage", do_poolusage, "Display talloc memory usage" },
1274 { "dmalloc-mark", do_dmalloc_mark, "" },
1275 { "dmalloc-log-changed", do_dmalloc_changed, "" },
1276 { "shutdown", do_shutdown, "Shut down daemon" },
1277 { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
1278 { "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
1279 { "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
1280 { "online", do_winbind_online, "Ask winbind to go into online state"},
1281 { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
1282 { "onlinestatus", do_winbind_onlinestatus, "Request winbind online status"},
1283 { "dump-event-list", do_dump_event_list, "Dump event list"},
1284 { "validate-cache" , do_winbind_validate_cache,
1285 "Validate winbind's credential cache" },
1286 { "dump-domain-list", do_winbind_dump_domain_list, "Dump winbind domain list"},
1287 { "noop", do_noop, "Do nothing" },
1291 /* Display usage information */
1293 static void usage(poptContext pc)
1297 poptPrintHelp(pc, stderr, 0);
1299 fprintf(stderr, "\n");
1300 fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1303 fprintf(stderr, "\n");
1304 fprintf(stderr, "<message-type> is one of:\n");
1306 for (i = 0; msg_types[i].name; i++)
1307 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name,
1310 fprintf(stderr, "\n");
1315 /* Return the pid number for a string destination */
1317 static struct server_id parse_dest(struct messaging_context *msg,
1320 struct server_id result = {-1};
1323 /* Zero is a special return value for broadcast to all processes */
1325 if (strequal(dest, "all")) {
1326 return interpret_pid(MSG_BROADCAST_PID_STR);
1329 /* Try self - useful for testing */
1331 if (strequal(dest, "self")) {
1332 return messaging_server_id(msg);
1335 /* Fix winbind typo. */
1336 if (strequal(dest, "winbind")) {
1340 /* Check for numeric pid number */
1341 result = interpret_pid(dest);
1343 /* Zero isn't valid if not "all". */
1344 if (result.pid && procid_valid(&result)) {
1348 /* Look up other destinations in pidfile directory */
1350 if ((pid = pidfile_pid(dest)) != 0) {
1351 return pid_to_procid(pid);
1354 fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1359 /* Execute smbcontrol command */
1361 static bool do_command(struct tevent_context *ev_ctx,
1362 struct messaging_context *msg_ctx,
1363 int argc, const char **argv)
1365 const char *dest = argv[0], *command = argv[1];
1366 struct server_id pid;
1369 /* Check destination */
1371 pid = parse_dest(msg_ctx, dest);
1372 if (!procid_valid(&pid)) {
1378 for (i = 0; msg_types[i].name; i++) {
1379 if (strequal(command, msg_types[i].name))
1380 return msg_types[i].fn(ev_ctx, msg_ctx, pid,
1381 argc - 1, argv + 1);
1384 fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1389 static void smbcontrol_help(poptContext pc,
1390 enum poptCallbackReason preason,
1391 struct poptOption * poption,
1395 if (poption->shortName != '?') {
1396 poptPrintUsage(pc, stdout, 0);
1404 struct poptOption help_options[] = {
1405 { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1407 { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1408 { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1414 int main(int argc, const char **argv)
1418 struct tevent_context *evt_ctx;
1419 struct messaging_context *msg_ctx;
1421 static struct poptOption long_options[] = {
1423 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1424 0, "Help options:", NULL },
1425 { "timeout", 't', POPT_ARG_INT, &timeout, 't',
1426 "Set timeout value in seconds", "TIMEOUT" },
1431 TALLOC_CTX *frame = talloc_stackframe();
1436 setup_logging(argv[0], DEBUG_STDOUT);
1438 /* Parse command line arguments using popt */
1440 pc = poptGetContext(
1441 "smbcontrol", argc, (const char **)argv, long_options, 0);
1443 poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1449 while ((opt = poptGetNextOpt(pc)) != -1) {
1451 case 't': /* --timeout */
1454 fprintf(stderr, "Invalid option\n");
1455 poptPrintHelp(pc, stderr, 0);
1460 /* We should now have the remaining command line arguments in
1461 argv. The argc parameter should have been decremented to the
1462 correct value in the above switch statement. */
1464 argv = (const char **)poptGetArgs(pc);
1467 while (argv[argc] != NULL) {
1475 lp_load_global(get_dyn_CONFIGFILE());
1477 /* Need to invert sense of return code -- samba
1478 * routines mostly return True==1 for success, but
1481 if (!(evt_ctx = tevent_context_init(NULL)) ||
1482 !(msg_ctx = messaging_init(NULL, evt_ctx))) {
1483 fprintf(stderr, "could not init messaging context\n");
1488 ret = !do_command(evt_ctx, msg_ctx, argc, argv);