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 "librpc/gen_ndr/messaging.h"
28 #include "librpc/gen_ndr/spoolss.h"
29 #include "nt_printing.h"
32 #include <libunwind.h>
35 #if HAVE_LIBUNWIND_PTRACE_H
36 #include <libunwind-ptrace.h>
40 #include <sys/ptrace.h>
43 /* Default timeout value when waiting for replies (in seconds) */
45 #define DEFAULT_TIMEOUT 10
47 static int timeout = DEFAULT_TIMEOUT;
48 static int num_replies; /* Used by message callback fns */
50 /* Send a message to a destination pid. Zero means broadcast smbd. */
52 static bool send_message(struct messaging_context *msg_ctx,
53 struct server_id pid, int msg_type,
54 const void *buf, int len)
59 if (procid_to_pid(&pid) != 0)
60 return NT_STATUS_IS_OK(
61 messaging_send_buf(msg_ctx, pid, msg_type,
64 ret = message_send_all(msg_ctx, msg_type, buf, len, &n_sent);
65 DEBUG(10,("smbcontrol/send_message: broadcast message to "
66 "%d processes\n", n_sent));
71 static void smbcontrol_timeout(struct tevent_context *event_ctx,
72 struct tevent_timer *te,
76 bool *timed_out = (bool *)private_data;
81 /* Wait for one or more reply messages */
83 static void wait_replies(struct messaging_context *msg_ctx,
84 bool multiple_replies)
86 struct tevent_timer *te;
87 bool timed_out = False;
89 if (!(te = tevent_add_timer(messaging_event_context(msg_ctx), NULL,
90 timeval_current_ofs(timeout, 0),
91 smbcontrol_timeout, (void *)&timed_out))) {
92 DEBUG(0, ("tevent_add_timer failed\n"));
98 if (num_replies > 0 && !multiple_replies)
100 ret = tevent_loop_once(messaging_event_context(msg_ctx));
107 /* Message handler callback that displays the PID and a string on stdout */
109 static void print_pid_string_cb(struct messaging_context *msg,
112 struct server_id pid,
117 pidstr = procid_str(talloc_tos(), &pid);
118 printf("PID %s: %.*s", pidstr, (int)data->length,
119 (const char *)data->data);
124 /* Message handler callback that displays a string on stdout */
126 static void print_string_cb(struct messaging_context *msg,
129 struct server_id pid,
132 printf("%*s", (int)data->length, (const char *)data->data);
136 /* Send no message. Useful for testing. */
138 static bool do_noop(struct messaging_context *msg_ctx,
139 const struct server_id pid,
140 const int argc, const char **argv)
143 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
147 /* Move along, nothing to see here */
152 /* Send a debug string */
154 static bool do_debug(struct messaging_context *msg_ctx,
155 const struct server_id pid,
156 const int argc, const char **argv)
159 fprintf(stderr, "Usage: smbcontrol <dest> debug "
164 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
165 strlen(argv[1]) + 1);
168 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
170 /* Return the name of a process given it's PID. This will only work on Linux,
171 * but that's probably moot since this whole stack tracing implementatino is
172 * Linux-specific anyway.
174 static const char * procname(pid_t pid, char * buf, size_t bufsz)
179 snprintf(path, sizeof(path), "/proc/%llu/cmdline",
180 (unsigned long long)pid);
181 if ((fp = fopen(path, "r")) == NULL) {
185 fgets(buf, bufsz, fp);
191 static void print_stack_trace(pid_t pid, int * count)
194 unw_addr_space_t aspace = NULL;
203 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
205 "Failed to attach to process %llu: %s\n",
206 (unsigned long long)pid, strerror(errno));
210 /* Wait until the attach is complete. */
211 waitpid(pid, NULL, 0);
213 if (((pinfo = _UPT_create(pid)) == NULL) ||
214 ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
215 /* Probably out of memory. */
217 "Unable to initialize stack unwind for process %llu\n",
218 (unsigned long long)pid);
222 if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
224 "Unable to unwind stack for process %llu: %s\n",
225 (unsigned long long)pid, unw_strerror(ret));
233 if (procname(pid, nbuf, sizeof(nbuf))) {
234 printf("Stack trace for process %llu (%s):\n",
235 (unsigned long long)pid, nbuf);
237 printf("Stack trace for process %llu:\n",
238 (unsigned long long)pid);
241 while (unw_step(&cursor) > 0) {
243 unw_get_reg(&cursor, UNW_REG_IP, &ip);
244 unw_get_reg(&cursor, UNW_REG_SP, &sp);
246 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
247 if (ret != 0 && ret != -UNW_ENOMEM) {
248 snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
250 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
251 nbuf, (long long)off, (long long)ip,
259 unw_destroy_addr_space(aspace);
266 ptrace(PTRACE_DETACH, pid, NULL, NULL);
269 static int stack_trace_connection(const struct connections_key *key,
270 const struct connections_data *crec,
273 print_stack_trace(procid_to_pid(&crec->pid), (int *)priv);
278 static bool do_daemon_stack_trace(struct messaging_context *msg_ctx,
279 const struct server_id pid,
280 const int argc, const char **argv)
286 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
290 dest = procid_to_pid(&pid);
293 /* It would be nice to be able to make sure that this PID is
294 * the PID of a smbd/winbind/nmbd process, not some random PID
295 * the user liked the look of. It doesn't seem like it's worth
296 * the effort at the moment, however.
298 print_stack_trace(dest, &count);
300 connections_forall_read(stack_trace_connection, &count);
306 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
308 static bool do_daemon_stack_trace(struct messaging_context *msg_ctx,
309 const struct server_id pid,
310 const int argc, const char **argv)
313 "Daemon stack tracing is not supported on this platform\n");
317 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
319 /* Inject a fault (fatal signal) into a running smbd */
321 static bool do_inject_fault(struct messaging_context *msg_ctx,
322 const struct server_id pid,
323 const int argc, const char **argv)
326 fprintf(stderr, "Usage: smbcontrol <dest> inject "
327 "<bus|hup|term|internal|segv>\n");
332 fprintf(stderr, "Fault injection is only available in "
333 "developer builds\n");
335 #else /* DEVELOPER */
339 if (strcmp(argv[1], "bus") == 0) {
341 } else if (strcmp(argv[1], "hup") == 0) {
343 } else if (strcmp(argv[1], "term") == 0) {
345 } else if (strcmp(argv[1], "segv") == 0) {
347 } else if (strcmp(argv[1], "internal") == 0) {
348 /* Force an internal error, ie. an unclean exit. */
351 fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
355 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
358 #endif /* DEVELOPER */
361 /* Force a browser election */
363 static bool do_election(struct messaging_context *msg_ctx,
364 const struct server_id pid,
365 const int argc, const char **argv)
368 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
372 return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
375 /* Ping a samba daemon process */
377 static void pong_cb(struct messaging_context *msg,
380 struct server_id pid,
383 char *src_string = procid_str(NULL, &pid);
384 printf("PONG from pid %s\n", src_string);
385 TALLOC_FREE(src_string);
389 static bool do_ping(struct messaging_context *msg_ctx,
390 const struct server_id pid,
391 const int argc, const char **argv)
394 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
398 /* Send a message and register our interest in a reply */
400 if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
403 messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
405 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
407 /* No replies were received within the timeout period */
409 if (num_replies == 0)
410 printf("No replies received\n");
412 messaging_deregister(msg_ctx, MSG_PONG, NULL);
417 /* Set profiling options */
419 static bool do_profile(struct messaging_context *msg_ctx,
420 const struct server_id pid,
421 const int argc, const char **argv)
426 fprintf(stderr, "Usage: smbcontrol <dest> profile "
427 "<off|count|on|flush>\n");
431 if (strcmp(argv[1], "off") == 0) {
433 } else if (strcmp(argv[1], "count") == 0) {
435 } else if (strcmp(argv[1], "on") == 0) {
437 } else if (strcmp(argv[1], "flush") == 0) {
440 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
444 return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
447 /* Return the profiling level */
449 static void profilelevel_cb(struct messaging_context *msg_ctx,
452 struct server_id pid,
460 if (data->length != sizeof(int)) {
461 fprintf(stderr, "invalid message length %ld returned\n",
462 (unsigned long)data->length);
466 memcpy(&level, data->data, sizeof(int));
479 s = "count and time";
486 printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
489 static void profilelevel_rqst(struct messaging_context *msg_ctx,
492 struct server_id pid,
497 /* Send back a dummy reply */
499 send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
502 static bool do_profilelevel(struct messaging_context *msg_ctx,
503 const struct server_id pid,
504 const int argc, const char **argv)
507 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
511 /* Send a message and register our interest in a reply */
513 if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
516 messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
517 messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
520 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
522 /* No replies were received within the timeout period */
524 if (num_replies == 0)
525 printf("No replies received\n");
527 messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
532 /* Display debug level settings */
534 static bool do_debuglevel(struct messaging_context *msg_ctx,
535 const struct server_id pid,
536 const int argc, const char **argv)
539 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
543 /* Send a message and register our interest in a reply */
545 if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
548 messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
550 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
552 /* No replies were received within the timeout period */
554 if (num_replies == 0)
555 printf("No replies received\n");
557 messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
562 /* Send a print notify message */
564 static bool do_printnotify(struct messaging_context *msg_ctx,
565 const struct server_id pid,
566 const int argc, const char **argv)
570 /* Check for subcommand */
573 fprintf(stderr, "Must specify subcommand:\n");
574 fprintf(stderr, "\tqueuepause <printername>\n");
575 fprintf(stderr, "\tqueueresume <printername>\n");
576 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
577 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
578 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
579 fprintf(stderr, "\tprinter <printername> <comment|port|"
580 "driver> <value>\n");
587 if (strcmp(cmd, "queuepause") == 0) {
590 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
591 " queuepause <printername>\n");
595 notify_printer_status_byname(argv[2], PRINTER_STATUS_PAUSED);
599 } else if (strcmp(cmd, "queueresume") == 0) {
602 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
603 " queuereume <printername>\n");
607 notify_printer_status_byname(argv[2], PRINTER_STATUS_OK);
611 } else if (strcmp(cmd, "jobpause") == 0) {
615 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
616 " jobpause <printername> <unix-jobid>\n");
620 jobid = atoi(argv[3]);
622 notify_job_status_byname(
623 argv[2], jobid, JOB_STATUS_PAUSED,
624 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
628 } else if (strcmp(cmd, "jobresume") == 0) {
632 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
633 " jobpause <printername> <unix-jobid>\n");
637 jobid = atoi(argv[3]);
639 notify_job_status_byname(
640 argv[2], jobid, JOB_STATUS_QUEUED,
641 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
645 } else if (strcmp(cmd, "jobdelete") == 0) {
649 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
650 " jobpause <printername> <unix-jobid>\n");
654 jobid = atoi(argv[3]);
656 notify_job_status_byname(
657 argv[2], jobid, JOB_STATUS_DELETING,
658 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
660 notify_job_status_byname(
661 argv[2], jobid, JOB_STATUS_DELETING|
663 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
667 } else if (strcmp(cmd, "printer") == 0) {
671 fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
672 "printer <printername> <comment|port|driver> "
677 if (strcmp(argv[3], "comment") == 0) {
678 attribute = PRINTER_NOTIFY_FIELD_COMMENT;
679 } else if (strcmp(argv[3], "port") == 0) {
680 attribute = PRINTER_NOTIFY_FIELD_PORT_NAME;
681 } else if (strcmp(argv[3], "driver") == 0) {
682 attribute = PRINTER_NOTIFY_FIELD_DRIVER_NAME;
684 fprintf(stderr, "Invalid printer command '%s'\n",
689 notify_printer_byname(argv[2], attribute,
690 CONST_DISCARD(char *, argv[4]));
695 fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
699 print_notify_send_messages(msg_ctx, 0);
705 static bool do_closeshare(struct messaging_context *msg_ctx,
706 const struct server_id pid,
707 const int argc, const char **argv)
710 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
715 return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
716 strlen(argv[1]) + 1);
719 /* force a blocking lock retry */
721 static bool do_lockretry(struct messaging_context *msg_ctx,
722 const struct server_id pid,
723 const int argc, const char **argv)
726 fprintf(stderr, "Usage: smbcontrol <dest> lockretry\n");
730 return send_message(msg_ctx, pid, MSG_SMB_UNLOCK, NULL, 0);
733 /* force a validation of all brl entries, including re-sends. */
735 static bool do_brl_revalidate(struct messaging_context *msg_ctx,
736 const struct server_id pid,
737 const int argc, const char **argv)
740 fprintf(stderr, "Usage: smbcontrol <dest> brl-revalidate\n");
744 return send_message(msg_ctx, pid, MSG_SMB_BRL_VALIDATE, NULL, 0);
747 /* Force a SAM synchronisation */
749 static bool do_samsync(struct messaging_context *msg_ctx,
750 const struct server_id pid,
751 const int argc, const char **argv)
754 fprintf(stderr, "Usage: smbcontrol <dest> samsync\n");
758 return send_message(msg_ctx, pid, MSG_SMB_SAM_SYNC, NULL, 0);
761 /* Force a SAM replication */
763 static bool do_samrepl(struct messaging_context *msg_ctx,
764 const struct server_id pid,
765 const int argc, const char **argv)
768 fprintf(stderr, "Usage: smbcontrol <dest> samrepl\n");
772 return send_message(msg_ctx, pid, MSG_SMB_SAM_REPL, NULL, 0);
775 /* Display talloc pool usage */
777 static bool do_poolusage(struct messaging_context *msg_ctx,
778 const struct server_id pid,
779 const int argc, const char **argv)
782 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
786 messaging_register(msg_ctx, NULL, MSG_POOL_USAGE, print_string_cb);
788 /* Send a message and register our interest in a reply */
790 if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0))
793 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
795 /* No replies were received within the timeout period */
797 if (num_replies == 0)
798 printf("No replies received\n");
800 messaging_deregister(msg_ctx, MSG_POOL_USAGE, NULL);
805 /* Perform a dmalloc mark */
807 static bool do_dmalloc_mark(struct messaging_context *msg_ctx,
808 const struct server_id pid,
809 const int argc, const char **argv)
812 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
816 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
819 /* Perform a dmalloc changed */
821 static bool do_dmalloc_changed(struct messaging_context *msg_ctx,
822 const struct server_id pid,
823 const int argc, const char **argv)
826 fprintf(stderr, "Usage: smbcontrol <dest> "
827 "dmalloc-log-changed\n");
831 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
835 /* Shutdown a server process */
837 static bool do_shutdown(struct messaging_context *msg_ctx,
838 const struct server_id pid,
839 const int argc, const char **argv)
842 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
846 return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
849 /* Notify a driver upgrade */
851 static bool do_drvupgrade(struct messaging_context *msg_ctx,
852 const struct server_id pid,
853 const int argc, const char **argv)
856 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
861 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
862 strlen(argv[1]) + 1);
865 static bool do_winbind_online(struct messaging_context *msg_ctx,
866 const struct server_id pid,
867 const int argc, const char **argv)
872 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
876 /* Remove the entry in the winbindd_cache tdb to tell a later
877 starting winbindd that we're online. */
879 tdb = tdb_open_log(cache_path("winbindd_cache.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
881 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
882 cache_path("winbindd_cache.tdb"));
886 tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
889 return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
892 static bool do_winbind_offline(struct messaging_context *msg_ctx,
893 const struct server_id pid,
894 const int argc, const char **argv)
901 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
905 /* Create an entry in the winbindd_cache tdb to tell a later
906 starting winbindd that we're offline. We may actually create
909 tdb = tdb_open_log(cache_path("winbindd_cache.tdb"),
910 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
911 TDB_DEFAULT /* TDB_CLEAR_IF_FIRST */, O_RDWR|O_CREAT, 0600);
914 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
915 cache_path("winbindd_cache.tdb"));
919 /* There's a potential race condition that if a child
920 winbindd detects a domain is online at the same time
921 we're trying to tell it to go offline that it might
922 delete the record we add between us adding it and
923 sending the message. Minimize this by retrying up to
926 for (retry = 0; retry < 5; retry++) {
932 SIVAL(buf, 0, time(NULL));
936 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
938 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
941 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
942 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
944 if (!d.dptr || d.dsize != 4) {
946 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
957 static bool do_winbind_onlinestatus(struct messaging_context *msg_ctx,
958 const struct server_id pid,
959 const int argc, const char **argv)
961 struct server_id myid;
963 myid = procid_self();
966 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
970 messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
971 print_pid_string_cb);
973 if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, &myid,
977 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
979 /* No replies were received within the timeout period */
981 if (num_replies == 0)
982 printf("No replies received\n");
984 messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
989 static bool do_dump_event_list(struct messaging_context *msg_ctx,
990 const struct server_id pid,
991 const int argc, const char **argv)
993 struct server_id myid;
995 myid = procid_self();
998 fprintf(stderr, "Usage: smbcontrol <dest> dump-event-list\n");
1002 return send_message(msg_ctx, pid, MSG_DUMP_EVENT_LIST, NULL, 0);
1005 static bool do_winbind_dump_domain_list(struct messaging_context *msg_ctx,
1006 const struct server_id pid,
1007 const int argc, const char **argv)
1009 const char *domain = NULL;
1011 struct server_id myid;
1012 uint8_t *buf = NULL;
1015 myid = procid_self();
1017 if (argc < 1 || argc > 2) {
1018 fprintf(stderr, "Usage: smbcontrol <dest> dump_domain_list "
1025 domain_len = strlen(argv[1]) + 1;
1028 messaging_register(msg_ctx, NULL, MSG_WINBIND_DUMP_DOMAIN_LIST,
1029 print_pid_string_cb);
1031 buf_len = sizeof(myid)+domain_len;
1032 buf = SMB_MALLOC_ARRAY(uint8_t, buf_len);
1037 memcpy(buf, &myid, sizeof(myid));
1038 memcpy(&buf[sizeof(myid)], domain, domain_len);
1040 if (!send_message(msg_ctx, pid, MSG_WINBIND_DUMP_DOMAIN_LIST,
1047 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1049 /* No replies were received within the timeout period */
1052 if (num_replies == 0) {
1053 printf("No replies received\n");
1056 messaging_deregister(msg_ctx, MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
1061 static void winbind_validate_cache_cb(struct messaging_context *msg,
1064 struct server_id pid,
1067 char *src_string = procid_str(NULL, &pid);
1068 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1069 (*(data->data) == 0 ? "" : "NOT "), src_string);
1070 TALLOC_FREE(src_string);
1074 static bool do_winbind_validate_cache(struct messaging_context *msg_ctx,
1075 const struct server_id pid,
1076 const int argc, const char **argv)
1078 struct server_id myid = procid_self();
1081 fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
1085 messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
1086 winbind_validate_cache_cb);
1088 if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
1093 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1095 if (num_replies == 0) {
1096 printf("No replies received\n");
1099 messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);
1104 static bool do_reload_config(struct messaging_context *msg_ctx,
1105 const struct server_id pid,
1106 const int argc, const char **argv)
1109 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1113 return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1116 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1119 memset( (char *)n, '\0', sizeof(struct nmb_name) );
1120 fstrcpy(unix_name, name);
1121 strupper_m(unix_name);
1122 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1123 n->name_type = (unsigned int)type & 0xFF;
1124 push_ascii(n->scope, global_scope(), 64, STR_TERMINATE);
1127 static bool do_nodestatus(struct messaging_context *msg_ctx,
1128 const struct server_id pid,
1129 const int argc, const char **argv)
1131 struct packet_struct p;
1134 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1140 p.ip = interpret_addr2(argv[1]);
1142 p.packet_type = NMB_PACKET;
1144 p.packet.nmb.header.name_trn_id = 10;
1145 p.packet.nmb.header.opcode = 0;
1146 p.packet.nmb.header.response = False;
1147 p.packet.nmb.header.nm_flags.bcast = False;
1148 p.packet.nmb.header.nm_flags.recursion_available = False;
1149 p.packet.nmb.header.nm_flags.recursion_desired = False;
1150 p.packet.nmb.header.nm_flags.trunc = False;
1151 p.packet.nmb.header.nm_flags.authoritative = False;
1152 p.packet.nmb.header.rcode = 0;
1153 p.packet.nmb.header.qdcount = 1;
1154 p.packet.nmb.header.ancount = 0;
1155 p.packet.nmb.header.nscount = 0;
1156 p.packet.nmb.header.arcount = 0;
1157 my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1158 p.packet.nmb.question.question_type = 0x21;
1159 p.packet.nmb.question.question_class = 0x1;
1161 return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1164 /* A list of message type supported */
1166 static const struct {
1167 const char *name; /* Option name */
1168 bool (*fn)(struct messaging_context *msg_ctx,
1169 const struct server_id pid,
1170 const int argc, const char **argv);
1171 const char *help; /* Short help text */
1173 { "debug", do_debug, "Set debuglevel" },
1174 { "force-election", do_election,
1175 "Force a browse election" },
1176 { "ping", do_ping, "Elicit a response" },
1177 { "profile", do_profile, "" },
1178 { "inject", do_inject_fault,
1179 "Inject a fatal signal into a running smbd"},
1180 { "stacktrace", do_daemon_stack_trace,
1181 "Display a stack trace of a daemon" },
1182 { "profilelevel", do_profilelevel, "" },
1183 { "debuglevel", do_debuglevel, "Display current debuglevels" },
1184 { "printnotify", do_printnotify, "Send a print notify message" },
1185 { "close-share", do_closeshare, "Forcibly disconnect a share" },
1186 { "lockretry", do_lockretry, "Force a blocking lock retry" },
1187 { "brl-revalidate", do_brl_revalidate, "Revalidate all brl entries" },
1188 { "samsync", do_samsync, "Initiate SAM synchronisation" },
1189 { "samrepl", do_samrepl, "Initiate SAM replication" },
1190 { "pool-usage", do_poolusage, "Display talloc memory usage" },
1191 { "dmalloc-mark", do_dmalloc_mark, "" },
1192 { "dmalloc-log-changed", do_dmalloc_changed, "" },
1193 { "shutdown", do_shutdown, "Shut down daemon" },
1194 { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
1195 { "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
1196 { "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
1197 { "online", do_winbind_online, "Ask winbind to go into online state"},
1198 { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
1199 { "onlinestatus", do_winbind_onlinestatus, "Request winbind online status"},
1200 { "dump-event-list", do_dump_event_list, "Dump event list"},
1201 { "validate-cache" , do_winbind_validate_cache,
1202 "Validate winbind's credential cache" },
1203 { "dump-domain-list", do_winbind_dump_domain_list, "Dump winbind domain list"},
1204 { "noop", do_noop, "Do nothing" },
1208 /* Display usage information */
1210 static void usage(poptContext pc)
1214 poptPrintHelp(pc, stderr, 0);
1216 fprintf(stderr, "\n");
1217 fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1220 fprintf(stderr, "\n");
1221 fprintf(stderr, "<message-type> is one of:\n");
1223 for (i = 0; msg_types[i].name; i++)
1224 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name,
1227 fprintf(stderr, "\n");
1232 /* Return the pid number for a string destination */
1234 static struct server_id parse_dest(const char *dest)
1236 struct server_id result = {-1};
1239 /* Zero is a special return value for broadcast to all processes */
1241 if (strequal(dest, "all")) {
1242 return interpret_pid(MSG_BROADCAST_PID_STR);
1245 /* Try self - useful for testing */
1247 if (strequal(dest, "self")) {
1248 return procid_self();
1251 /* Fix winbind typo. */
1252 if (strequal(dest, "winbind")) {
1256 /* Check for numeric pid number */
1257 result = interpret_pid(dest);
1259 /* Zero isn't valid if not "all". */
1260 if (result.pid && procid_valid(&result)) {
1264 /* Look up other destinations in pidfile directory */
1266 if ((pid = pidfile_pid(dest)) != 0) {
1267 return pid_to_procid(pid);
1270 fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1275 /* Execute smbcontrol command */
1277 static bool do_command(struct messaging_context *msg_ctx,
1278 int argc, const char **argv)
1280 const char *dest = argv[0], *command = argv[1];
1281 struct server_id pid;
1284 /* Check destination */
1286 pid = parse_dest(dest);
1287 if (!procid_valid(&pid)) {
1293 for (i = 0; msg_types[i].name; i++) {
1294 if (strequal(command, msg_types[i].name))
1295 return msg_types[i].fn(msg_ctx, pid,
1296 argc - 1, argv + 1);
1299 fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1304 static void smbcontrol_help(poptContext pc,
1305 enum poptCallbackReason preason,
1306 struct poptOption * poption,
1310 if (poption->shortName != '?') {
1311 poptPrintUsage(pc, stdout, 0);
1319 struct poptOption help_options[] = {
1320 { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1322 { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1323 { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1329 int main(int argc, const char **argv)
1333 struct tevent_context *evt_ctx;
1334 struct messaging_context *msg_ctx;
1336 static struct poptOption long_options[] = {
1338 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1339 0, "Help options:", NULL },
1340 { "timeout", 't', POPT_ARG_INT, &timeout, 't',
1341 "Set timeout value in seconds", "TIMEOUT" },
1346 TALLOC_CTX *frame = talloc_stackframe();
1351 setup_logging(argv[0],True);
1353 /* Parse command line arguments using popt */
1355 pc = poptGetContext(
1356 "smbcontrol", argc, (const char **)argv, long_options, 0);
1358 poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1364 while ((opt = poptGetNextOpt(pc)) != -1) {
1366 case 't': /* --timeout */
1369 fprintf(stderr, "Invalid option\n");
1370 poptPrintHelp(pc, stderr, 0);
1375 /* We should now have the remaining command line arguments in
1376 argv. The argc parameter should have been decremented to the
1377 correct value in the above switch statement. */
1379 argv = (const char **)poptGetArgs(pc);
1382 while (argv[argc] != NULL) {
1390 lp_load(get_dyn_CONFIGFILE(),False,False,False,True);
1392 /* Need to invert sense of return code -- samba
1393 * routines mostly return True==1 for success, but
1396 if (!(evt_ctx = tevent_context_init(NULL)) ||
1397 !(msg_ctx = messaging_init(NULL, procid_self(), evt_ctx))) {
1398 fprintf(stderr, "could not init messaging context\n");
1403 ret = !do_command(msg_ctx, argc, argv);