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"
31 #include "printing/notify.h"
34 #include <libunwind.h>
37 #if HAVE_LIBUNWIND_PTRACE_H
38 #include <libunwind-ptrace.h>
42 #include <sys/ptrace.h>
45 /* Default timeout value when waiting for replies (in seconds) */
47 #define DEFAULT_TIMEOUT 10
49 static int timeout = DEFAULT_TIMEOUT;
50 static int num_replies; /* Used by message callback fns */
52 /* Send a message to a destination pid. Zero means broadcast smbd. */
54 static bool send_message(struct messaging_context *msg_ctx,
55 struct server_id pid, int msg_type,
56 const void *buf, int len)
61 if (procid_to_pid(&pid) != 0)
62 return NT_STATUS_IS_OK(
63 messaging_send_buf(msg_ctx, pid, msg_type,
66 ret = message_send_all(msg_ctx, msg_type, buf, len, &n_sent);
67 DEBUG(10,("smbcontrol/send_message: broadcast message to "
68 "%d processes\n", n_sent));
73 static void smbcontrol_timeout(struct tevent_context *event_ctx,
74 struct tevent_timer *te,
78 bool *timed_out = (bool *)private_data;
83 /* Wait for one or more reply messages */
85 static void wait_replies(struct messaging_context *msg_ctx,
86 bool multiple_replies)
88 struct tevent_timer *te;
89 bool timed_out = False;
91 if (!(te = tevent_add_timer(messaging_event_context(msg_ctx), NULL,
92 timeval_current_ofs(timeout, 0),
93 smbcontrol_timeout, (void *)&timed_out))) {
94 DEBUG(0, ("tevent_add_timer failed\n"));
100 if (num_replies > 0 && !multiple_replies)
102 ret = tevent_loop_once(messaging_event_context(msg_ctx));
109 /* Message handler callback that displays the PID and a string on stdout */
111 static void print_pid_string_cb(struct messaging_context *msg,
114 struct server_id pid,
119 pidstr = procid_str(talloc_tos(), &pid);
120 printf("PID %s: %.*s", pidstr, (int)data->length,
121 (const char *)data->data);
126 /* Message handler callback that displays a string on stdout */
128 static void print_string_cb(struct messaging_context *msg,
131 struct server_id pid,
134 printf("%*s", (int)data->length, (const char *)data->data);
138 /* Send no message. Useful for testing. */
140 static bool do_noop(struct messaging_context *msg_ctx,
141 const struct server_id pid,
142 const int argc, const char **argv)
145 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
149 /* Move along, nothing to see here */
154 /* Send a debug string */
156 static bool do_debug(struct messaging_context *msg_ctx,
157 const struct server_id pid,
158 const int argc, const char **argv)
161 fprintf(stderr, "Usage: smbcontrol <dest> debug "
166 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
167 strlen(argv[1]) + 1);
171 static bool do_idmap(struct messaging_context *msg_ctx,
172 const struct server_id pid,
173 const int argc, const char **argv)
175 static const char* usage = "Usage: "
176 "smbcontrol <dest> idmap <cmd> [arg]\n"
177 "\tcmd:\tflush [gid|uid]\n"
178 "\t\tdelete \"UID <uid>\"|\"GID <gid>\"|<sid>\n"
179 "\t\tkill \"UID <uid>\"|\"GID <gid>\"|<sid>\n";
180 const char* arg = NULL;
189 arglen = strlen(arg) + 1;
192 fprintf(stderr, "%s", usage);
196 if (strcmp(argv[1], "flush") == 0) {
197 msg_type = MSG_IDMAP_FLUSH;
199 else if (strcmp(argv[1], "delete") == 0) {
200 msg_type = MSG_IDMAP_DELETE;
202 else if (strcmp(argv[1], "kill") == 0) {
203 msg_type = MSG_IDMAP_KILL;
205 else if (strcmp(argv[1], "help") == 0) {
206 fprintf(stdout, "%s", usage);
210 fprintf(stderr, "%s", usage);
214 return send_message(msg_ctx, pid, msg_type, arg, arglen);
218 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
220 /* Return the name of a process given it's PID. This will only work on Linux,
221 * but that's probably moot since this whole stack tracing implementatino is
222 * Linux-specific anyway.
224 static const char * procname(pid_t pid, char * buf, size_t bufsz)
229 snprintf(path, sizeof(path), "/proc/%llu/cmdline",
230 (unsigned long long)pid);
231 if ((fp = fopen(path, "r")) == NULL) {
235 fgets(buf, bufsz, fp);
241 static void print_stack_trace(pid_t pid, int * count)
244 unw_addr_space_t aspace = NULL;
253 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
255 "Failed to attach to process %llu: %s\n",
256 (unsigned long long)pid, strerror(errno));
260 /* Wait until the attach is complete. */
261 waitpid(pid, NULL, 0);
263 if (((pinfo = _UPT_create(pid)) == NULL) ||
264 ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
265 /* Probably out of memory. */
267 "Unable to initialize stack unwind for process %llu\n",
268 (unsigned long long)pid);
272 if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
274 "Unable to unwind stack for process %llu: %s\n",
275 (unsigned long long)pid, unw_strerror(ret));
283 if (procname(pid, nbuf, sizeof(nbuf))) {
284 printf("Stack trace for process %llu (%s):\n",
285 (unsigned long long)pid, nbuf);
287 printf("Stack trace for process %llu:\n",
288 (unsigned long long)pid);
291 while (unw_step(&cursor) > 0) {
293 unw_get_reg(&cursor, UNW_REG_IP, &ip);
294 unw_get_reg(&cursor, UNW_REG_SP, &sp);
296 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
297 if (ret != 0 && ret != -UNW_ENOMEM) {
298 snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
300 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
301 nbuf, (long long)off, (long long)ip,
309 unw_destroy_addr_space(aspace);
316 ptrace(PTRACE_DETACH, pid, NULL, NULL);
319 static int stack_trace_connection(const struct connections_key *key,
320 const struct connections_data *crec,
323 print_stack_trace(procid_to_pid(&crec->pid), (int *)priv);
328 static bool do_daemon_stack_trace(struct messaging_context *msg_ctx,
329 const struct server_id pid,
330 const int argc, const char **argv)
336 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
340 dest = procid_to_pid(&pid);
343 /* It would be nice to be able to make sure that this PID is
344 * the PID of a smbd/winbind/nmbd process, not some random PID
345 * the user liked the look of. It doesn't seem like it's worth
346 * the effort at the moment, however.
348 print_stack_trace(dest, &count);
350 connections_forall_read(stack_trace_connection, &count);
356 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
358 static bool do_daemon_stack_trace(struct messaging_context *msg_ctx,
359 const struct server_id pid,
360 const int argc, const char **argv)
363 "Daemon stack tracing is not supported on this platform\n");
367 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
369 /* Inject a fault (fatal signal) into a running smbd */
371 static bool do_inject_fault(struct messaging_context *msg_ctx,
372 const struct server_id pid,
373 const int argc, const char **argv)
376 fprintf(stderr, "Usage: smbcontrol <dest> inject "
377 "<bus|hup|term|internal|segv>\n");
382 fprintf(stderr, "Fault injection is only available in "
383 "developer builds\n");
385 #else /* DEVELOPER */
389 if (strcmp(argv[1], "bus") == 0) {
391 } else if (strcmp(argv[1], "hup") == 0) {
393 } else if (strcmp(argv[1], "term") == 0) {
395 } else if (strcmp(argv[1], "segv") == 0) {
397 } else if (strcmp(argv[1], "internal") == 0) {
398 /* Force an internal error, ie. an unclean exit. */
401 fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
405 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
408 #endif /* DEVELOPER */
411 /* Force a browser election */
413 static bool do_election(struct messaging_context *msg_ctx,
414 const struct server_id pid,
415 const int argc, const char **argv)
418 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
422 return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
425 /* Ping a samba daemon process */
427 static void pong_cb(struct messaging_context *msg,
430 struct server_id pid,
433 char *src_string = procid_str(NULL, &pid);
434 printf("PONG from pid %s\n", src_string);
435 TALLOC_FREE(src_string);
439 static bool do_ping(struct messaging_context *msg_ctx,
440 const struct server_id pid,
441 const int argc, const char **argv)
444 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
448 /* Send a message and register our interest in a reply */
450 if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
453 messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
455 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
457 /* No replies were received within the timeout period */
459 if (num_replies == 0)
460 printf("No replies received\n");
462 messaging_deregister(msg_ctx, MSG_PONG, NULL);
467 /* Set profiling options */
469 static bool do_profile(struct messaging_context *msg_ctx,
470 const struct server_id pid,
471 const int argc, const char **argv)
476 fprintf(stderr, "Usage: smbcontrol <dest> profile "
477 "<off|count|on|flush>\n");
481 if (strcmp(argv[1], "off") == 0) {
483 } else if (strcmp(argv[1], "count") == 0) {
485 } else if (strcmp(argv[1], "on") == 0) {
487 } else if (strcmp(argv[1], "flush") == 0) {
490 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
494 return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
497 /* Return the profiling level */
499 static void profilelevel_cb(struct messaging_context *msg_ctx,
502 struct server_id pid,
510 if (data->length != sizeof(int)) {
511 fprintf(stderr, "invalid message length %ld returned\n",
512 (unsigned long)data->length);
516 memcpy(&level, data->data, sizeof(int));
529 s = "count and time";
536 printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
539 static void profilelevel_rqst(struct messaging_context *msg_ctx,
542 struct server_id pid,
547 /* Send back a dummy reply */
549 send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
552 static bool do_profilelevel(struct messaging_context *msg_ctx,
553 const struct server_id pid,
554 const int argc, const char **argv)
557 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
561 /* Send a message and register our interest in a reply */
563 if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
566 messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
567 messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
570 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
572 /* No replies were received within the timeout period */
574 if (num_replies == 0)
575 printf("No replies received\n");
577 messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
582 /* Display debug level settings */
584 static bool do_debuglevel(struct messaging_context *msg_ctx,
585 const struct server_id pid,
586 const int argc, const char **argv)
589 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
593 /* Send a message and register our interest in a reply */
595 if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
598 messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
600 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
602 /* No replies were received within the timeout period */
604 if (num_replies == 0)
605 printf("No replies received\n");
607 messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
612 /* Send a print notify message */
614 static bool do_printnotify(struct messaging_context *msg_ctx,
615 const struct server_id pid,
616 const int argc, const char **argv)
620 /* Check for subcommand */
623 fprintf(stderr, "Must specify subcommand:\n");
624 fprintf(stderr, "\tqueuepause <printername>\n");
625 fprintf(stderr, "\tqueueresume <printername>\n");
626 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
627 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
628 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
629 fprintf(stderr, "\tprinter <printername> <comment|port|"
630 "driver> <value>\n");
637 if (strcmp(cmd, "queuepause") == 0) {
640 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
641 " queuepause <printername>\n");
645 notify_printer_status_byname(messaging_event_context(msg_ctx),
647 PRINTER_STATUS_PAUSED);
651 } else if (strcmp(cmd, "queueresume") == 0) {
654 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
655 " queuereume <printername>\n");
659 notify_printer_status_byname(messaging_event_context(msg_ctx),
665 } else if (strcmp(cmd, "jobpause") == 0) {
669 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
670 " jobpause <printername> <unix-jobid>\n");
674 jobid = atoi(argv[3]);
676 notify_job_status_byname(
677 messaging_event_context(msg_ctx), msg_ctx,
678 argv[2], jobid, JOB_STATUS_PAUSED,
679 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
683 } else if (strcmp(cmd, "jobresume") == 0) {
687 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
688 " jobpause <printername> <unix-jobid>\n");
692 jobid = atoi(argv[3]);
694 notify_job_status_byname(
695 messaging_event_context(msg_ctx), msg_ctx,
696 argv[2], jobid, JOB_STATUS_QUEUED,
697 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
701 } else if (strcmp(cmd, "jobdelete") == 0) {
705 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
706 " jobpause <printername> <unix-jobid>\n");
710 jobid = atoi(argv[3]);
712 notify_job_status_byname(
713 messaging_event_context(msg_ctx), msg_ctx,
714 argv[2], jobid, JOB_STATUS_DELETING,
715 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
717 notify_job_status_byname(
718 messaging_event_context(msg_ctx), msg_ctx,
719 argv[2], jobid, JOB_STATUS_DELETING|
721 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
725 } else if (strcmp(cmd, "printer") == 0) {
729 fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
730 "printer <printername> <comment|port|driver> "
735 if (strcmp(argv[3], "comment") == 0) {
736 attribute = PRINTER_NOTIFY_FIELD_COMMENT;
737 } else if (strcmp(argv[3], "port") == 0) {
738 attribute = PRINTER_NOTIFY_FIELD_PORT_NAME;
739 } else if (strcmp(argv[3], "driver") == 0) {
740 attribute = PRINTER_NOTIFY_FIELD_DRIVER_NAME;
742 fprintf(stderr, "Invalid printer command '%s'\n",
747 notify_printer_byname(messaging_event_context(msg_ctx),
748 msg_ctx, argv[2], attribute,
749 CONST_DISCARD(char *, argv[4]));
754 fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
758 print_notify_send_messages(msg_ctx, 0);
764 static bool do_closeshare(struct messaging_context *msg_ctx,
765 const struct server_id pid,
766 const int argc, const char **argv)
769 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
774 return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
775 strlen(argv[1]) + 1);
778 /* Tell winbindd an IP got dropped */
780 static bool do_ip_dropped(struct messaging_context *msg_ctx,
781 const struct server_id pid,
782 const int argc, const char **argv)
785 fprintf(stderr, "Usage: smbcontrol <dest> ip-dropped "
790 return send_message(msg_ctx, pid, MSG_WINBIND_IP_DROPPED, argv[1],
791 strlen(argv[1]) + 1);
794 /* force a blocking lock retry */
796 static bool do_lockretry(struct messaging_context *msg_ctx,
797 const struct server_id pid,
798 const int argc, const char **argv)
801 fprintf(stderr, "Usage: smbcontrol <dest> lockretry\n");
805 return send_message(msg_ctx, pid, MSG_SMB_UNLOCK, NULL, 0);
808 /* force a validation of all brl entries, including re-sends. */
810 static bool do_brl_revalidate(struct messaging_context *msg_ctx,
811 const struct server_id pid,
812 const int argc, const char **argv)
815 fprintf(stderr, "Usage: smbcontrol <dest> brl-revalidate\n");
819 return send_message(msg_ctx, pid, MSG_SMB_BRL_VALIDATE, NULL, 0);
822 /* Force a SAM synchronisation */
824 static bool do_samsync(struct messaging_context *msg_ctx,
825 const struct server_id pid,
826 const int argc, const char **argv)
829 fprintf(stderr, "Usage: smbcontrol <dest> samsync\n");
833 return send_message(msg_ctx, pid, MSG_SMB_SAM_SYNC, NULL, 0);
836 /* Force a SAM replication */
838 static bool do_samrepl(struct messaging_context *msg_ctx,
839 const struct server_id pid,
840 const int argc, const char **argv)
843 fprintf(stderr, "Usage: smbcontrol <dest> samrepl\n");
847 return send_message(msg_ctx, pid, MSG_SMB_SAM_REPL, NULL, 0);
850 /* Display talloc pool usage */
852 static bool do_poolusage(struct messaging_context *msg_ctx,
853 const struct server_id pid,
854 const int argc, const char **argv)
857 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
861 messaging_register(msg_ctx, NULL, MSG_POOL_USAGE, print_string_cb);
863 /* Send a message and register our interest in a reply */
865 if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0))
868 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
870 /* No replies were received within the timeout period */
872 if (num_replies == 0)
873 printf("No replies received\n");
875 messaging_deregister(msg_ctx, MSG_POOL_USAGE, NULL);
880 /* Perform a dmalloc mark */
882 static bool do_dmalloc_mark(struct messaging_context *msg_ctx,
883 const struct server_id pid,
884 const int argc, const char **argv)
887 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
891 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
894 /* Perform a dmalloc changed */
896 static bool do_dmalloc_changed(struct messaging_context *msg_ctx,
897 const struct server_id pid,
898 const int argc, const char **argv)
901 fprintf(stderr, "Usage: smbcontrol <dest> "
902 "dmalloc-log-changed\n");
906 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
910 /* Shutdown a server process */
912 static bool do_shutdown(struct messaging_context *msg_ctx,
913 const struct server_id pid,
914 const int argc, const char **argv)
917 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
921 return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
924 /* Notify a driver upgrade */
926 static bool do_drvupgrade(struct messaging_context *msg_ctx,
927 const struct server_id pid,
928 const int argc, const char **argv)
931 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
936 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
937 strlen(argv[1]) + 1);
940 static bool do_winbind_online(struct messaging_context *msg_ctx,
941 const struct server_id pid,
942 const int argc, const char **argv)
947 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
951 /* Remove the entry in the winbindd_cache tdb to tell a later
952 starting winbindd that we're online. */
954 tdb = tdb_open_log(cache_path("winbindd_cache.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
956 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
957 cache_path("winbindd_cache.tdb"));
961 tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
964 return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
967 static bool do_winbind_offline(struct messaging_context *msg_ctx,
968 const struct server_id pid,
969 const int argc, const char **argv)
976 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
980 /* Create an entry in the winbindd_cache tdb to tell a later
981 starting winbindd that we're offline. We may actually create
984 tdb = tdb_open_log(cache_path("winbindd_cache.tdb"),
985 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
986 TDB_DEFAULT|TDB_INCOMPATIBLE_HASH /* TDB_CLEAR_IF_FIRST */,
987 O_RDWR|O_CREAT, 0600);
990 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
991 cache_path("winbindd_cache.tdb"));
995 /* There's a potential race condition that if a child
996 winbindd detects a domain is online at the same time
997 we're trying to tell it to go offline that it might
998 delete the record we add between us adding it and
999 sending the message. Minimize this by retrying up to
1002 for (retry = 0; retry < 5; retry++) {
1008 SIVAL(buf, 0, time(NULL));
1012 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
1014 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
1017 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
1018 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
1020 if (!d.dptr || d.dsize != 4) {
1022 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
1033 static bool do_winbind_onlinestatus(struct messaging_context *msg_ctx,
1034 const struct server_id pid,
1035 const int argc, const char **argv)
1037 struct server_id myid;
1039 myid = messaging_server_id(msg_ctx);
1042 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
1046 messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
1047 print_pid_string_cb);
1049 if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, &myid,
1053 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1055 /* No replies were received within the timeout period */
1057 if (num_replies == 0)
1058 printf("No replies received\n");
1060 messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
1065 static bool do_dump_event_list(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 messaging_context *msg_ctx,
1082 const struct server_id pid,
1083 const int argc, const char **argv)
1085 const char *domain = NULL;
1087 struct server_id myid;
1088 uint8_t *buf = NULL;
1091 myid = messaging_server_id(msg_ctx);
1093 if (argc < 1 || argc > 2) {
1094 fprintf(stderr, "Usage: smbcontrol <dest> dump-domain-list "
1101 domain_len = strlen(argv[1]) + 1;
1104 messaging_register(msg_ctx, NULL, MSG_WINBIND_DUMP_DOMAIN_LIST,
1105 print_pid_string_cb);
1107 buf_len = sizeof(myid)+domain_len;
1108 buf = SMB_MALLOC_ARRAY(uint8_t, buf_len);
1113 memcpy(buf, &myid, sizeof(myid));
1114 memcpy(&buf[sizeof(myid)], domain, domain_len);
1116 if (!send_message(msg_ctx, pid, MSG_WINBIND_DUMP_DOMAIN_LIST,
1123 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1125 /* No replies were received within the timeout period */
1128 if (num_replies == 0) {
1129 printf("No replies received\n");
1132 messaging_deregister(msg_ctx, MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
1137 static void winbind_validate_cache_cb(struct messaging_context *msg,
1140 struct server_id pid,
1143 char *src_string = procid_str(NULL, &pid);
1144 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1145 (*(data->data) == 0 ? "" : "NOT "), src_string);
1146 TALLOC_FREE(src_string);
1150 static bool do_winbind_validate_cache(struct messaging_context *msg_ctx,
1151 const struct server_id pid,
1152 const int argc, const char **argv)
1154 struct server_id myid;
1156 myid = messaging_server_id(msg_ctx);
1159 fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
1163 messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
1164 winbind_validate_cache_cb);
1166 if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
1171 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1173 if (num_replies == 0) {
1174 printf("No replies received\n");
1177 messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);
1182 static bool do_reload_config(struct messaging_context *msg_ctx,
1183 const struct server_id pid,
1184 const int argc, const char **argv)
1187 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1191 return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1194 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1197 memset( (char *)n, '\0', sizeof(struct nmb_name) );
1198 fstrcpy(unix_name, name);
1199 strupper_m(unix_name);
1200 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1201 n->name_type = (unsigned int)type & 0xFF;
1202 push_ascii(n->scope, global_scope(), 64, STR_TERMINATE);
1205 static bool do_nodestatus(struct messaging_context *msg_ctx,
1206 const struct server_id pid,
1207 const int argc, const char **argv)
1209 struct packet_struct p;
1212 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1218 p.ip = interpret_addr2(argv[1]);
1220 p.packet_type = NMB_PACKET;
1222 p.packet.nmb.header.name_trn_id = 10;
1223 p.packet.nmb.header.opcode = 0;
1224 p.packet.nmb.header.response = False;
1225 p.packet.nmb.header.nm_flags.bcast = False;
1226 p.packet.nmb.header.nm_flags.recursion_available = False;
1227 p.packet.nmb.header.nm_flags.recursion_desired = False;
1228 p.packet.nmb.header.nm_flags.trunc = False;
1229 p.packet.nmb.header.nm_flags.authoritative = False;
1230 p.packet.nmb.header.rcode = 0;
1231 p.packet.nmb.header.qdcount = 1;
1232 p.packet.nmb.header.ancount = 0;
1233 p.packet.nmb.header.nscount = 0;
1234 p.packet.nmb.header.arcount = 0;
1235 my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1236 p.packet.nmb.question.question_type = 0x21;
1237 p.packet.nmb.question.question_class = 0x1;
1239 return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1242 /* A list of message type supported */
1244 static const struct {
1245 const char *name; /* Option name */
1246 bool (*fn)(struct messaging_context *msg_ctx,
1247 const struct server_id pid,
1248 const int argc, const char **argv);
1249 const char *help; /* Short help text */
1251 { "debug", do_debug, "Set debuglevel" },
1252 { "idmap", do_idmap, "Manipulate idmap cache" },
1253 { "force-election", do_election,
1254 "Force a browse election" },
1255 { "ping", do_ping, "Elicit a response" },
1256 { "profile", do_profile, "" },
1257 { "inject", do_inject_fault,
1258 "Inject a fatal signal into a running smbd"},
1259 { "stacktrace", do_daemon_stack_trace,
1260 "Display a stack trace of a daemon" },
1261 { "profilelevel", do_profilelevel, "" },
1262 { "debuglevel", do_debuglevel, "Display current debuglevels" },
1263 { "printnotify", do_printnotify, "Send a print notify message" },
1264 { "close-share", do_closeshare, "Forcibly disconnect a share" },
1265 { "ip-dropped", do_ip_dropped, "Tell winbind that an IP got dropped" },
1266 { "lockretry", do_lockretry, "Force a blocking lock retry" },
1267 { "brl-revalidate", do_brl_revalidate, "Revalidate all brl entries" },
1268 { "samsync", do_samsync, "Initiate SAM synchronisation" },
1269 { "samrepl", do_samrepl, "Initiate SAM replication" },
1270 { "pool-usage", do_poolusage, "Display talloc memory usage" },
1271 { "dmalloc-mark", do_dmalloc_mark, "" },
1272 { "dmalloc-log-changed", do_dmalloc_changed, "" },
1273 { "shutdown", do_shutdown, "Shut down daemon" },
1274 { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
1275 { "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
1276 { "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
1277 { "online", do_winbind_online, "Ask winbind to go into online state"},
1278 { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
1279 { "onlinestatus", do_winbind_onlinestatus, "Request winbind online status"},
1280 { "dump-event-list", do_dump_event_list, "Dump event list"},
1281 { "validate-cache" , do_winbind_validate_cache,
1282 "Validate winbind's credential cache" },
1283 { "dump-domain-list", do_winbind_dump_domain_list, "Dump winbind domain list"},
1284 { "noop", do_noop, "Do nothing" },
1288 /* Display usage information */
1290 static void usage(poptContext pc)
1294 poptPrintHelp(pc, stderr, 0);
1296 fprintf(stderr, "\n");
1297 fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1300 fprintf(stderr, "\n");
1301 fprintf(stderr, "<message-type> is one of:\n");
1303 for (i = 0; msg_types[i].name; i++)
1304 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name,
1307 fprintf(stderr, "\n");
1312 /* Return the pid number for a string destination */
1314 static struct server_id parse_dest(struct messaging_context *msg,
1317 struct server_id result = {-1};
1320 /* Zero is a special return value for broadcast to all processes */
1322 if (strequal(dest, "all")) {
1323 return interpret_pid(MSG_BROADCAST_PID_STR);
1326 /* Try self - useful for testing */
1328 if (strequal(dest, "self")) {
1329 return messaging_server_id(msg);
1332 /* Fix winbind typo. */
1333 if (strequal(dest, "winbind")) {
1337 /* Check for numeric pid number */
1338 result = interpret_pid(dest);
1340 /* Zero isn't valid if not "all". */
1341 if (result.pid && procid_valid(&result)) {
1345 /* Look up other destinations in pidfile directory */
1347 if ((pid = pidfile_pid(dest)) != 0) {
1348 return pid_to_procid(pid);
1351 fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1356 /* Execute smbcontrol command */
1358 static bool do_command(struct messaging_context *msg_ctx,
1359 int argc, const char **argv)
1361 const char *dest = argv[0], *command = argv[1];
1362 struct server_id pid;
1365 /* Check destination */
1367 pid = parse_dest(msg_ctx, dest);
1368 if (!procid_valid(&pid)) {
1374 for (i = 0; msg_types[i].name; i++) {
1375 if (strequal(command, msg_types[i].name))
1376 return msg_types[i].fn(msg_ctx, pid,
1377 argc - 1, argv + 1);
1380 fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1385 static void smbcontrol_help(poptContext pc,
1386 enum poptCallbackReason preason,
1387 struct poptOption * poption,
1391 if (poption->shortName != '?') {
1392 poptPrintUsage(pc, stdout, 0);
1400 struct poptOption help_options[] = {
1401 { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1403 { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1404 { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1410 int main(int argc, const char **argv)
1414 struct tevent_context *evt_ctx;
1415 struct messaging_context *msg_ctx;
1417 static struct poptOption long_options[] = {
1419 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1420 0, "Help options:", NULL },
1421 { "timeout", 't', POPT_ARG_INT, &timeout, 't',
1422 "Set timeout value in seconds", "TIMEOUT" },
1427 TALLOC_CTX *frame = talloc_stackframe();
1432 setup_logging(argv[0], DEBUG_STDOUT);
1434 /* Parse command line arguments using popt */
1436 pc = poptGetContext(
1437 "smbcontrol", argc, (const char **)argv, long_options, 0);
1439 poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1445 while ((opt = poptGetNextOpt(pc)) != -1) {
1447 case 't': /* --timeout */
1450 fprintf(stderr, "Invalid option\n");
1451 poptPrintHelp(pc, stderr, 0);
1456 /* We should now have the remaining command line arguments in
1457 argv. The argc parameter should have been decremented to the
1458 correct value in the above switch statement. */
1460 argv = (const char **)poptGetArgs(pc);
1463 while (argv[argc] != NULL) {
1471 lp_load(get_dyn_CONFIGFILE(),False,False,False,True);
1473 /* Need to invert sense of return code -- samba
1474 * routines mostly return True==1 for success, but
1477 if (!(evt_ctx = tevent_context_init(NULL)) ||
1478 !(msg_ctx = messaging_init(NULL, procid_self(), evt_ctx))) {
1479 fprintf(stderr, "could not init messaging context\n");
1484 ret = !do_command(msg_ctx, argc, argv);