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 "popt_common.h"
28 #include "librpc/gen_ndr/messaging.h"
29 #include "librpc/gen_ndr/spoolss.h"
30 #include "nt_printing.h"
33 #include <libunwind.h>
36 #if HAVE_LIBUNWIND_PTRACE_H
37 #include <libunwind-ptrace.h>
41 #include <sys/ptrace.h>
44 /* Default timeout value when waiting for replies (in seconds) */
46 #define DEFAULT_TIMEOUT 10
48 static int timeout = DEFAULT_TIMEOUT;
49 static int num_replies; /* Used by message callback fns */
51 /* Send a message to a destination pid. Zero means broadcast smbd. */
53 static bool send_message(struct messaging_context *msg_ctx,
54 struct server_id pid, int msg_type,
55 const void *buf, int len)
60 if (procid_to_pid(&pid) != 0)
61 return NT_STATUS_IS_OK(
62 messaging_send_buf(msg_ctx, pid, msg_type,
65 ret = message_send_all(msg_ctx, msg_type, buf, len, &n_sent);
66 DEBUG(10,("smbcontrol/send_message: broadcast message to "
67 "%d processes\n", n_sent));
72 static void smbcontrol_timeout(struct tevent_context *event_ctx,
73 struct tevent_timer *te,
77 bool *timed_out = (bool *)private_data;
82 /* Wait for one or more reply messages */
84 static void wait_replies(struct messaging_context *msg_ctx,
85 bool multiple_replies)
87 struct tevent_timer *te;
88 bool timed_out = False;
90 if (!(te = tevent_add_timer(messaging_event_context(msg_ctx), NULL,
91 timeval_current_ofs(timeout, 0),
92 smbcontrol_timeout, (void *)&timed_out))) {
93 DEBUG(0, ("tevent_add_timer failed\n"));
99 if (num_replies > 0 && !multiple_replies)
101 ret = tevent_loop_once(messaging_event_context(msg_ctx));
108 /* Message handler callback that displays the PID and a string on stdout */
110 static void print_pid_string_cb(struct messaging_context *msg,
113 struct server_id pid,
118 pidstr = procid_str(talloc_tos(), &pid);
119 printf("PID %s: %.*s", pidstr, (int)data->length,
120 (const char *)data->data);
125 /* Message handler callback that displays a string on stdout */
127 static void print_string_cb(struct messaging_context *msg,
130 struct server_id pid,
133 printf("%*s", (int)data->length, (const char *)data->data);
137 /* Send no message. Useful for testing. */
139 static bool do_noop(struct messaging_context *msg_ctx,
140 const struct server_id pid,
141 const int argc, const char **argv)
144 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
148 /* Move along, nothing to see here */
153 /* Send a debug string */
155 static bool do_debug(struct messaging_context *msg_ctx,
156 const struct server_id pid,
157 const int argc, const char **argv)
160 fprintf(stderr, "Usage: smbcontrol <dest> debug "
165 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
166 strlen(argv[1]) + 1);
169 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
171 /* Return the name of a process given it's PID. This will only work on Linux,
172 * but that's probably moot since this whole stack tracing implementatino is
173 * Linux-specific anyway.
175 static const char * procname(pid_t pid, char * buf, size_t bufsz)
180 snprintf(path, sizeof(path), "/proc/%llu/cmdline",
181 (unsigned long long)pid);
182 if ((fp = fopen(path, "r")) == NULL) {
186 fgets(buf, bufsz, fp);
192 static void print_stack_trace(pid_t pid, int * count)
195 unw_addr_space_t aspace = NULL;
204 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
206 "Failed to attach to process %llu: %s\n",
207 (unsigned long long)pid, strerror(errno));
211 /* Wait until the attach is complete. */
212 waitpid(pid, NULL, 0);
214 if (((pinfo = _UPT_create(pid)) == NULL) ||
215 ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
216 /* Probably out of memory. */
218 "Unable to initialize stack unwind for process %llu\n",
219 (unsigned long long)pid);
223 if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
225 "Unable to unwind stack for process %llu: %s\n",
226 (unsigned long long)pid, unw_strerror(ret));
234 if (procname(pid, nbuf, sizeof(nbuf))) {
235 printf("Stack trace for process %llu (%s):\n",
236 (unsigned long long)pid, nbuf);
238 printf("Stack trace for process %llu:\n",
239 (unsigned long long)pid);
242 while (unw_step(&cursor) > 0) {
244 unw_get_reg(&cursor, UNW_REG_IP, &ip);
245 unw_get_reg(&cursor, UNW_REG_SP, &sp);
247 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
248 if (ret != 0 && ret != -UNW_ENOMEM) {
249 snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
251 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
252 nbuf, (long long)off, (long long)ip,
260 unw_destroy_addr_space(aspace);
267 ptrace(PTRACE_DETACH, pid, NULL, NULL);
270 static int stack_trace_connection(const struct connections_key *key,
271 const struct connections_data *crec,
274 print_stack_trace(procid_to_pid(&crec->pid), (int *)priv);
279 static bool do_daemon_stack_trace(struct messaging_context *msg_ctx,
280 const struct server_id pid,
281 const int argc, const char **argv)
287 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
291 dest = procid_to_pid(&pid);
294 /* It would be nice to be able to make sure that this PID is
295 * the PID of a smbd/winbind/nmbd process, not some random PID
296 * the user liked the look of. It doesn't seem like it's worth
297 * the effort at the moment, however.
299 print_stack_trace(dest, &count);
301 connections_forall_read(stack_trace_connection, &count);
307 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
309 static bool do_daemon_stack_trace(struct messaging_context *msg_ctx,
310 const struct server_id pid,
311 const int argc, const char **argv)
314 "Daemon stack tracing is not supported on this platform\n");
318 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
320 /* Inject a fault (fatal signal) into a running smbd */
322 static bool do_inject_fault(struct messaging_context *msg_ctx,
323 const struct server_id pid,
324 const int argc, const char **argv)
327 fprintf(stderr, "Usage: smbcontrol <dest> inject "
328 "<bus|hup|term|internal|segv>\n");
333 fprintf(stderr, "Fault injection is only available in "
334 "developer builds\n");
336 #else /* DEVELOPER */
340 if (strcmp(argv[1], "bus") == 0) {
342 } else if (strcmp(argv[1], "hup") == 0) {
344 } else if (strcmp(argv[1], "term") == 0) {
346 } else if (strcmp(argv[1], "segv") == 0) {
348 } else if (strcmp(argv[1], "internal") == 0) {
349 /* Force an internal error, ie. an unclean exit. */
352 fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
356 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
359 #endif /* DEVELOPER */
362 /* Force a browser election */
364 static bool do_election(struct messaging_context *msg_ctx,
365 const struct server_id pid,
366 const int argc, const char **argv)
369 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
373 return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
376 /* Ping a samba daemon process */
378 static void pong_cb(struct messaging_context *msg,
381 struct server_id pid,
384 char *src_string = procid_str(NULL, &pid);
385 printf("PONG from pid %s\n", src_string);
386 TALLOC_FREE(src_string);
390 static bool do_ping(struct messaging_context *msg_ctx,
391 const struct server_id pid,
392 const int argc, const char **argv)
395 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
399 /* Send a message and register our interest in a reply */
401 if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
404 messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
406 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
408 /* No replies were received within the timeout period */
410 if (num_replies == 0)
411 printf("No replies received\n");
413 messaging_deregister(msg_ctx, MSG_PONG, NULL);
418 /* Set profiling options */
420 static bool do_profile(struct messaging_context *msg_ctx,
421 const struct server_id pid,
422 const int argc, const char **argv)
427 fprintf(stderr, "Usage: smbcontrol <dest> profile "
428 "<off|count|on|flush>\n");
432 if (strcmp(argv[1], "off") == 0) {
434 } else if (strcmp(argv[1], "count") == 0) {
436 } else if (strcmp(argv[1], "on") == 0) {
438 } else if (strcmp(argv[1], "flush") == 0) {
441 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
445 return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
448 /* Return the profiling level */
450 static void profilelevel_cb(struct messaging_context *msg_ctx,
453 struct server_id pid,
461 if (data->length != sizeof(int)) {
462 fprintf(stderr, "invalid message length %ld returned\n",
463 (unsigned long)data->length);
467 memcpy(&level, data->data, sizeof(int));
480 s = "count and time";
487 printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
490 static void profilelevel_rqst(struct messaging_context *msg_ctx,
493 struct server_id pid,
498 /* Send back a dummy reply */
500 send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
503 static bool do_profilelevel(struct messaging_context *msg_ctx,
504 const struct server_id pid,
505 const int argc, const char **argv)
508 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
512 /* Send a message and register our interest in a reply */
514 if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
517 messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
518 messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
521 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
523 /* No replies were received within the timeout period */
525 if (num_replies == 0)
526 printf("No replies received\n");
528 messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
533 /* Display debug level settings */
535 static bool do_debuglevel(struct messaging_context *msg_ctx,
536 const struct server_id pid,
537 const int argc, const char **argv)
540 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
544 /* Send a message and register our interest in a reply */
546 if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
549 messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
551 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
553 /* No replies were received within the timeout period */
555 if (num_replies == 0)
556 printf("No replies received\n");
558 messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
563 /* Send a print notify message */
565 static bool do_printnotify(struct messaging_context *msg_ctx,
566 const struct server_id pid,
567 const int argc, const char **argv)
571 /* Check for subcommand */
574 fprintf(stderr, "Must specify subcommand:\n");
575 fprintf(stderr, "\tqueuepause <printername>\n");
576 fprintf(stderr, "\tqueueresume <printername>\n");
577 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
578 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
579 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
580 fprintf(stderr, "\tprinter <printername> <comment|port|"
581 "driver> <value>\n");
588 if (strcmp(cmd, "queuepause") == 0) {
591 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
592 " queuepause <printername>\n");
596 notify_printer_status_byname(messaging_event_context(msg_ctx),
598 PRINTER_STATUS_PAUSED);
602 } else if (strcmp(cmd, "queueresume") == 0) {
605 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
606 " queuereume <printername>\n");
610 notify_printer_status_byname(messaging_event_context(msg_ctx),
616 } else if (strcmp(cmd, "jobpause") == 0) {
620 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
621 " jobpause <printername> <unix-jobid>\n");
625 jobid = atoi(argv[3]);
627 notify_job_status_byname(
628 messaging_event_context(msg_ctx), msg_ctx,
629 argv[2], jobid, JOB_STATUS_PAUSED,
630 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
634 } else if (strcmp(cmd, "jobresume") == 0) {
638 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
639 " jobpause <printername> <unix-jobid>\n");
643 jobid = atoi(argv[3]);
645 notify_job_status_byname(
646 messaging_event_context(msg_ctx), msg_ctx,
647 argv[2], jobid, JOB_STATUS_QUEUED,
648 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
652 } else if (strcmp(cmd, "jobdelete") == 0) {
656 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
657 " jobpause <printername> <unix-jobid>\n");
661 jobid = atoi(argv[3]);
663 notify_job_status_byname(
664 messaging_event_context(msg_ctx), msg_ctx,
665 argv[2], jobid, JOB_STATUS_DELETING,
666 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
668 notify_job_status_byname(
669 messaging_event_context(msg_ctx), msg_ctx,
670 argv[2], jobid, JOB_STATUS_DELETING|
672 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
676 } else if (strcmp(cmd, "printer") == 0) {
680 fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
681 "printer <printername> <comment|port|driver> "
686 if (strcmp(argv[3], "comment") == 0) {
687 attribute = PRINTER_NOTIFY_FIELD_COMMENT;
688 } else if (strcmp(argv[3], "port") == 0) {
689 attribute = PRINTER_NOTIFY_FIELD_PORT_NAME;
690 } else if (strcmp(argv[3], "driver") == 0) {
691 attribute = PRINTER_NOTIFY_FIELD_DRIVER_NAME;
693 fprintf(stderr, "Invalid printer command '%s'\n",
698 notify_printer_byname(messaging_event_context(msg_ctx),
699 msg_ctx, argv[2], attribute,
700 CONST_DISCARD(char *, argv[4]));
705 fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
709 print_notify_send_messages(msg_ctx, 0);
715 static bool do_closeshare(struct messaging_context *msg_ctx,
716 const struct server_id pid,
717 const int argc, const char **argv)
720 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
725 return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
726 strlen(argv[1]) + 1);
729 /* force a blocking lock retry */
731 static bool do_lockretry(struct messaging_context *msg_ctx,
732 const struct server_id pid,
733 const int argc, const char **argv)
736 fprintf(stderr, "Usage: smbcontrol <dest> lockretry\n");
740 return send_message(msg_ctx, pid, MSG_SMB_UNLOCK, NULL, 0);
743 /* force a validation of all brl entries, including re-sends. */
745 static bool do_brl_revalidate(struct messaging_context *msg_ctx,
746 const struct server_id pid,
747 const int argc, const char **argv)
750 fprintf(stderr, "Usage: smbcontrol <dest> brl-revalidate\n");
754 return send_message(msg_ctx, pid, MSG_SMB_BRL_VALIDATE, NULL, 0);
757 /* Force a SAM synchronisation */
759 static bool do_samsync(struct messaging_context *msg_ctx,
760 const struct server_id pid,
761 const int argc, const char **argv)
764 fprintf(stderr, "Usage: smbcontrol <dest> samsync\n");
768 return send_message(msg_ctx, pid, MSG_SMB_SAM_SYNC, NULL, 0);
771 /* Force a SAM replication */
773 static bool do_samrepl(struct messaging_context *msg_ctx,
774 const struct server_id pid,
775 const int argc, const char **argv)
778 fprintf(stderr, "Usage: smbcontrol <dest> samrepl\n");
782 return send_message(msg_ctx, pid, MSG_SMB_SAM_REPL, NULL, 0);
785 /* Display talloc pool usage */
787 static bool do_poolusage(struct messaging_context *msg_ctx,
788 const struct server_id pid,
789 const int argc, const char **argv)
792 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
796 messaging_register(msg_ctx, NULL, MSG_POOL_USAGE, print_string_cb);
798 /* Send a message and register our interest in a reply */
800 if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0))
803 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
805 /* No replies were received within the timeout period */
807 if (num_replies == 0)
808 printf("No replies received\n");
810 messaging_deregister(msg_ctx, MSG_POOL_USAGE, NULL);
815 /* Perform a dmalloc mark */
817 static bool do_dmalloc_mark(struct messaging_context *msg_ctx,
818 const struct server_id pid,
819 const int argc, const char **argv)
822 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
826 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
829 /* Perform a dmalloc changed */
831 static bool do_dmalloc_changed(struct messaging_context *msg_ctx,
832 const struct server_id pid,
833 const int argc, const char **argv)
836 fprintf(stderr, "Usage: smbcontrol <dest> "
837 "dmalloc-log-changed\n");
841 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
845 /* Shutdown a server process */
847 static bool do_shutdown(struct messaging_context *msg_ctx,
848 const struct server_id pid,
849 const int argc, const char **argv)
852 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
856 return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
859 /* Notify a driver upgrade */
861 static bool do_drvupgrade(struct messaging_context *msg_ctx,
862 const struct server_id pid,
863 const int argc, const char **argv)
866 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
871 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
872 strlen(argv[1]) + 1);
875 static bool do_winbind_online(struct messaging_context *msg_ctx,
876 const struct server_id pid,
877 const int argc, const char **argv)
882 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
886 /* Remove the entry in the winbindd_cache tdb to tell a later
887 starting winbindd that we're online. */
889 tdb = tdb_open_log(cache_path("winbindd_cache.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
891 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
892 cache_path("winbindd_cache.tdb"));
896 tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
899 return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
902 static bool do_winbind_offline(struct messaging_context *msg_ctx,
903 const struct server_id pid,
904 const int argc, const char **argv)
911 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
915 /* Create an entry in the winbindd_cache tdb to tell a later
916 starting winbindd that we're offline. We may actually create
919 tdb = tdb_open_log(cache_path("winbindd_cache.tdb"),
920 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
921 TDB_DEFAULT /* TDB_CLEAR_IF_FIRST */, O_RDWR|O_CREAT, 0600);
924 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
925 cache_path("winbindd_cache.tdb"));
929 /* There's a potential race condition that if a child
930 winbindd detects a domain is online at the same time
931 we're trying to tell it to go offline that it might
932 delete the record we add between us adding it and
933 sending the message. Minimize this by retrying up to
936 for (retry = 0; retry < 5; retry++) {
942 SIVAL(buf, 0, time(NULL));
946 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
948 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
951 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
952 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
954 if (!d.dptr || d.dsize != 4) {
956 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
967 static bool do_winbind_onlinestatus(struct messaging_context *msg_ctx,
968 const struct server_id pid,
969 const int argc, const char **argv)
971 struct server_id myid;
973 myid = messaging_server_id(msg_ctx);
976 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
980 messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
981 print_pid_string_cb);
983 if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, &myid,
987 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
989 /* No replies were received within the timeout period */
991 if (num_replies == 0)
992 printf("No replies received\n");
994 messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
999 static bool do_dump_event_list(struct messaging_context *msg_ctx,
1000 const struct server_id pid,
1001 const int argc, const char **argv)
1003 struct server_id myid;
1005 myid = messaging_server_id(msg_ctx);
1008 fprintf(stderr, "Usage: smbcontrol <dest> dump-event-list\n");
1012 return send_message(msg_ctx, pid, MSG_DUMP_EVENT_LIST, NULL, 0);
1015 static bool do_winbind_dump_domain_list(struct messaging_context *msg_ctx,
1016 const struct server_id pid,
1017 const int argc, const char **argv)
1019 const char *domain = NULL;
1021 struct server_id myid;
1022 uint8_t *buf = NULL;
1025 myid = messaging_server_id(msg_ctx);
1027 if (argc < 1 || argc > 2) {
1028 fprintf(stderr, "Usage: smbcontrol <dest> dump_domain_list "
1035 domain_len = strlen(argv[1]) + 1;
1038 messaging_register(msg_ctx, NULL, MSG_WINBIND_DUMP_DOMAIN_LIST,
1039 print_pid_string_cb);
1041 buf_len = sizeof(myid)+domain_len;
1042 buf = SMB_MALLOC_ARRAY(uint8_t, buf_len);
1047 memcpy(buf, &myid, sizeof(myid));
1048 memcpy(&buf[sizeof(myid)], domain, domain_len);
1050 if (!send_message(msg_ctx, pid, MSG_WINBIND_DUMP_DOMAIN_LIST,
1057 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1059 /* No replies were received within the timeout period */
1062 if (num_replies == 0) {
1063 printf("No replies received\n");
1066 messaging_deregister(msg_ctx, MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
1071 static void winbind_validate_cache_cb(struct messaging_context *msg,
1074 struct server_id pid,
1077 char *src_string = procid_str(NULL, &pid);
1078 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1079 (*(data->data) == 0 ? "" : "NOT "), src_string);
1080 TALLOC_FREE(src_string);
1084 static bool do_winbind_validate_cache(struct messaging_context *msg_ctx,
1085 const struct server_id pid,
1086 const int argc, const char **argv)
1088 struct server_id myid;
1090 myid = messaging_server_id(msg_ctx);
1093 fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
1097 messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
1098 winbind_validate_cache_cb);
1100 if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
1105 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1107 if (num_replies == 0) {
1108 printf("No replies received\n");
1111 messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);
1116 static bool do_reload_config(struct messaging_context *msg_ctx,
1117 const struct server_id pid,
1118 const int argc, const char **argv)
1121 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1125 return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1128 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1131 memset( (char *)n, '\0', sizeof(struct nmb_name) );
1132 fstrcpy(unix_name, name);
1133 strupper_m(unix_name);
1134 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1135 n->name_type = (unsigned int)type & 0xFF;
1136 push_ascii(n->scope, global_scope(), 64, STR_TERMINATE);
1139 static bool do_nodestatus(struct messaging_context *msg_ctx,
1140 const struct server_id pid,
1141 const int argc, const char **argv)
1143 struct packet_struct p;
1146 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1152 p.ip = interpret_addr2(argv[1]);
1154 p.packet_type = NMB_PACKET;
1156 p.packet.nmb.header.name_trn_id = 10;
1157 p.packet.nmb.header.opcode = 0;
1158 p.packet.nmb.header.response = False;
1159 p.packet.nmb.header.nm_flags.bcast = False;
1160 p.packet.nmb.header.nm_flags.recursion_available = False;
1161 p.packet.nmb.header.nm_flags.recursion_desired = False;
1162 p.packet.nmb.header.nm_flags.trunc = False;
1163 p.packet.nmb.header.nm_flags.authoritative = False;
1164 p.packet.nmb.header.rcode = 0;
1165 p.packet.nmb.header.qdcount = 1;
1166 p.packet.nmb.header.ancount = 0;
1167 p.packet.nmb.header.nscount = 0;
1168 p.packet.nmb.header.arcount = 0;
1169 my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1170 p.packet.nmb.question.question_type = 0x21;
1171 p.packet.nmb.question.question_class = 0x1;
1173 return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1176 /* A list of message type supported */
1178 static const struct {
1179 const char *name; /* Option name */
1180 bool (*fn)(struct messaging_context *msg_ctx,
1181 const struct server_id pid,
1182 const int argc, const char **argv);
1183 const char *help; /* Short help text */
1185 { "debug", do_debug, "Set debuglevel" },
1186 { "force-election", do_election,
1187 "Force a browse election" },
1188 { "ping", do_ping, "Elicit a response" },
1189 { "profile", do_profile, "" },
1190 { "inject", do_inject_fault,
1191 "Inject a fatal signal into a running smbd"},
1192 { "stacktrace", do_daemon_stack_trace,
1193 "Display a stack trace of a daemon" },
1194 { "profilelevel", do_profilelevel, "" },
1195 { "debuglevel", do_debuglevel, "Display current debuglevels" },
1196 { "printnotify", do_printnotify, "Send a print notify message" },
1197 { "close-share", do_closeshare, "Forcibly disconnect a share" },
1198 { "lockretry", do_lockretry, "Force a blocking lock retry" },
1199 { "brl-revalidate", do_brl_revalidate, "Revalidate all brl entries" },
1200 { "samsync", do_samsync, "Initiate SAM synchronisation" },
1201 { "samrepl", do_samrepl, "Initiate SAM replication" },
1202 { "pool-usage", do_poolusage, "Display talloc memory usage" },
1203 { "dmalloc-mark", do_dmalloc_mark, "" },
1204 { "dmalloc-log-changed", do_dmalloc_changed, "" },
1205 { "shutdown", do_shutdown, "Shut down daemon" },
1206 { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
1207 { "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
1208 { "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
1209 { "online", do_winbind_online, "Ask winbind to go into online state"},
1210 { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
1211 { "onlinestatus", do_winbind_onlinestatus, "Request winbind online status"},
1212 { "dump-event-list", do_dump_event_list, "Dump event list"},
1213 { "validate-cache" , do_winbind_validate_cache,
1214 "Validate winbind's credential cache" },
1215 { "dump-domain-list", do_winbind_dump_domain_list, "Dump winbind domain list"},
1216 { "noop", do_noop, "Do nothing" },
1220 /* Display usage information */
1222 static void usage(poptContext pc)
1226 poptPrintHelp(pc, stderr, 0);
1228 fprintf(stderr, "\n");
1229 fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1232 fprintf(stderr, "\n");
1233 fprintf(stderr, "<message-type> is one of:\n");
1235 for (i = 0; msg_types[i].name; i++)
1236 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name,
1239 fprintf(stderr, "\n");
1244 /* Return the pid number for a string destination */
1246 static struct server_id parse_dest(struct messaging_context *msg,
1249 struct server_id result = {-1};
1252 /* Zero is a special return value for broadcast to all processes */
1254 if (strequal(dest, "all")) {
1255 return interpret_pid(MSG_BROADCAST_PID_STR);
1258 /* Try self - useful for testing */
1260 if (strequal(dest, "self")) {
1261 return messaging_server_id(msg);
1264 /* Fix winbind typo. */
1265 if (strequal(dest, "winbind")) {
1269 /* Check for numeric pid number */
1270 result = interpret_pid(dest);
1272 /* Zero isn't valid if not "all". */
1273 if (result.pid && procid_valid(&result)) {
1277 /* Look up other destinations in pidfile directory */
1279 if ((pid = pidfile_pid(dest)) != 0) {
1280 return pid_to_procid(pid);
1283 fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1288 /* Execute smbcontrol command */
1290 static bool do_command(struct messaging_context *msg_ctx,
1291 int argc, const char **argv)
1293 const char *dest = argv[0], *command = argv[1];
1294 struct server_id pid;
1297 /* Check destination */
1299 pid = parse_dest(msg_ctx, dest);
1300 if (!procid_valid(&pid)) {
1306 for (i = 0; msg_types[i].name; i++) {
1307 if (strequal(command, msg_types[i].name))
1308 return msg_types[i].fn(msg_ctx, pid,
1309 argc - 1, argv + 1);
1312 fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1317 static void smbcontrol_help(poptContext pc,
1318 enum poptCallbackReason preason,
1319 struct poptOption * poption,
1323 if (poption->shortName != '?') {
1324 poptPrintUsage(pc, stdout, 0);
1332 struct poptOption help_options[] = {
1333 { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1335 { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1336 { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1342 int main(int argc, const char **argv)
1346 struct tevent_context *evt_ctx;
1347 struct messaging_context *msg_ctx;
1349 static struct poptOption long_options[] = {
1351 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1352 0, "Help options:", NULL },
1353 { "timeout", 't', POPT_ARG_INT, &timeout, 't',
1354 "Set timeout value in seconds", "TIMEOUT" },
1359 TALLOC_CTX *frame = talloc_stackframe();
1364 setup_logging(argv[0],True);
1366 /* Parse command line arguments using popt */
1368 pc = poptGetContext(
1369 "smbcontrol", argc, (const char **)argv, long_options, 0);
1371 poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1377 while ((opt = poptGetNextOpt(pc)) != -1) {
1379 case 't': /* --timeout */
1382 fprintf(stderr, "Invalid option\n");
1383 poptPrintHelp(pc, stderr, 0);
1388 /* We should now have the remaining command line arguments in
1389 argv. The argc parameter should have been decremented to the
1390 correct value in the above switch statement. */
1392 argv = (const char **)poptGetArgs(pc);
1395 while (argv[argc] != NULL) {
1403 lp_load(get_dyn_CONFIGFILE(),False,False,False,True);
1405 /* Need to invert sense of return code -- samba
1406 * routines mostly return True==1 for success, but
1409 if (!(evt_ctx = tevent_context_init(NULL)) ||
1410 !(msg_ctx = messaging_init(NULL, procid_self(), evt_ctx))) {
1411 fprintf(stderr, "could not init messaging context\n");
1416 ret = !do_command(msg_ctx, argc, argv);