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/messaging.h"
30 #include "librpc/gen_ndr/spoolss.h"
31 #include "nt_printing.h"
32 #include "printing/notify.h"
35 #include <libunwind.h>
38 #if HAVE_LIBUNWIND_PTRACE_H
39 #include <libunwind-ptrace.h>
43 #include <sys/ptrace.h>
46 /* Default timeout value when waiting for replies (in seconds) */
48 #define DEFAULT_TIMEOUT 10
50 static int timeout = DEFAULT_TIMEOUT;
51 static int num_replies; /* Used by message callback fns */
53 /* Send a message to a destination pid. Zero means broadcast smbd. */
55 static bool send_message(struct messaging_context *msg_ctx,
56 struct server_id pid, int msg_type,
57 const void *buf, int len)
62 if (procid_to_pid(&pid) != 0)
63 return NT_STATUS_IS_OK(
64 messaging_send_buf(msg_ctx, pid, msg_type,
67 ret = message_send_all(msg_ctx, msg_type, buf, len, &n_sent);
68 DEBUG(10,("smbcontrol/send_message: broadcast message to "
69 "%d processes\n", n_sent));
74 static void smbcontrol_timeout(struct tevent_context *event_ctx,
75 struct tevent_timer *te,
79 bool *timed_out = (bool *)private_data;
84 /* Wait for one or more reply messages */
86 static void wait_replies(struct messaging_context *msg_ctx,
87 bool multiple_replies)
89 struct tevent_timer *te;
90 bool timed_out = False;
92 if (!(te = tevent_add_timer(messaging_event_context(msg_ctx), NULL,
93 timeval_current_ofs(timeout, 0),
94 smbcontrol_timeout, (void *)&timed_out))) {
95 DEBUG(0, ("tevent_add_timer failed\n"));
101 if (num_replies > 0 && !multiple_replies)
103 ret = tevent_loop_once(messaging_event_context(msg_ctx));
110 /* Message handler callback that displays the PID and a string on stdout */
112 static void print_pid_string_cb(struct messaging_context *msg,
115 struct server_id pid,
120 pidstr = procid_str(talloc_tos(), &pid);
121 printf("PID %s: %.*s", pidstr, (int)data->length,
122 (const char *)data->data);
127 /* Message handler callback that displays a string on stdout */
129 static void print_string_cb(struct messaging_context *msg,
132 struct server_id pid,
135 printf("%*s", (int)data->length, (const char *)data->data);
139 /* Send no message. Useful for testing. */
141 static bool do_noop(struct messaging_context *msg_ctx,
142 const struct server_id pid,
143 const int argc, const char **argv)
146 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
150 /* Move along, nothing to see here */
155 /* Send a debug string */
157 static bool do_debug(struct messaging_context *msg_ctx,
158 const struct server_id pid,
159 const int argc, const char **argv)
162 fprintf(stderr, "Usage: smbcontrol <dest> debug "
167 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
168 strlen(argv[1]) + 1);
172 static bool do_idmap(struct messaging_context *msg_ctx,
173 const struct server_id pid,
174 const int argc, const char **argv)
176 static const char* usage = "Usage: "
177 "smbcontrol <dest> idmap <cmd> [arg]\n"
178 "\tcmd:\tflush [gid|uid]\n"
179 "\t\tdelete \"UID <uid>\"|\"GID <gid>\"|<sid>\n"
180 "\t\tkill \"UID <uid>\"|\"GID <gid>\"|<sid>\n";
181 const char* arg = NULL;
190 arglen = strlen(arg) + 1;
193 fprintf(stderr, "%s", usage);
197 if (strcmp(argv[1], "flush") == 0) {
198 msg_type = MSG_IDMAP_FLUSH;
200 else if (strcmp(argv[1], "delete") == 0) {
201 msg_type = MSG_IDMAP_DELETE;
203 else if (strcmp(argv[1], "kill") == 0) {
204 msg_type = MSG_IDMAP_KILL;
206 else if (strcmp(argv[1], "help") == 0) {
207 fprintf(stdout, "%s", usage);
211 fprintf(stderr, "%s", usage);
215 return send_message(msg_ctx, pid, msg_type, arg, arglen);
219 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
221 /* Return the name of a process given it's PID. This will only work on Linux,
222 * but that's probably moot since this whole stack tracing implementatino is
223 * Linux-specific anyway.
225 static const char * procname(pid_t pid, char * buf, size_t bufsz)
230 snprintf(path, sizeof(path), "/proc/%llu/cmdline",
231 (unsigned long long)pid);
232 if ((fp = fopen(path, "r")) == NULL) {
236 fgets(buf, bufsz, fp);
242 static void print_stack_trace(pid_t pid, int * count)
245 unw_addr_space_t aspace = NULL;
254 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
256 "Failed to attach to process %llu: %s\n",
257 (unsigned long long)pid, strerror(errno));
261 /* Wait until the attach is complete. */
262 waitpid(pid, NULL, 0);
264 if (((pinfo = _UPT_create(pid)) == NULL) ||
265 ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
266 /* Probably out of memory. */
268 "Unable to initialize stack unwind for process %llu\n",
269 (unsigned long long)pid);
273 if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
275 "Unable to unwind stack for process %llu: %s\n",
276 (unsigned long long)pid, unw_strerror(ret));
284 if (procname(pid, nbuf, sizeof(nbuf))) {
285 printf("Stack trace for process %llu (%s):\n",
286 (unsigned long long)pid, nbuf);
288 printf("Stack trace for process %llu:\n",
289 (unsigned long long)pid);
292 while (unw_step(&cursor) > 0) {
294 unw_get_reg(&cursor, UNW_REG_IP, &ip);
295 unw_get_reg(&cursor, UNW_REG_SP, &sp);
297 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
298 if (ret != 0 && ret != -UNW_ENOMEM) {
299 snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
301 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
302 nbuf, (long long)off, (long long)ip,
310 unw_destroy_addr_space(aspace);
317 ptrace(PTRACE_DETACH, pid, NULL, NULL);
320 static int stack_trace_connection(const struct connections_key *key,
321 const struct connections_data *crec,
324 print_stack_trace(procid_to_pid(&crec->pid), (int *)priv);
329 static bool do_daemon_stack_trace(struct messaging_context *msg_ctx,
330 const struct server_id pid,
331 const int argc, const char **argv)
337 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
341 dest = procid_to_pid(&pid);
344 /* It would be nice to be able to make sure that this PID is
345 * the PID of a smbd/winbind/nmbd process, not some random PID
346 * the user liked the look of. It doesn't seem like it's worth
347 * the effort at the moment, however.
349 print_stack_trace(dest, &count);
351 connections_forall_read(stack_trace_connection, &count);
357 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
359 static bool do_daemon_stack_trace(struct messaging_context *msg_ctx,
360 const struct server_id pid,
361 const int argc, const char **argv)
364 "Daemon stack tracing is not supported on this platform\n");
368 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
370 /* Inject a fault (fatal signal) into a running smbd */
372 static bool do_inject_fault(struct messaging_context *msg_ctx,
373 const struct server_id pid,
374 const int argc, const char **argv)
377 fprintf(stderr, "Usage: smbcontrol <dest> inject "
378 "<bus|hup|term|internal|segv>\n");
383 fprintf(stderr, "Fault injection is only available in "
384 "developer builds\n");
386 #else /* DEVELOPER */
390 if (strcmp(argv[1], "bus") == 0) {
392 } else if (strcmp(argv[1], "hup") == 0) {
394 } else if (strcmp(argv[1], "term") == 0) {
396 } else if (strcmp(argv[1], "segv") == 0) {
398 } else if (strcmp(argv[1], "internal") == 0) {
399 /* Force an internal error, ie. an unclean exit. */
402 fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
406 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
409 #endif /* DEVELOPER */
412 /* Force a browser election */
414 static bool do_election(struct messaging_context *msg_ctx,
415 const struct server_id pid,
416 const int argc, const char **argv)
419 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
423 return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
426 /* Ping a samba daemon process */
428 static void pong_cb(struct messaging_context *msg,
431 struct server_id pid,
434 char *src_string = procid_str(NULL, &pid);
435 printf("PONG from pid %s\n", src_string);
436 TALLOC_FREE(src_string);
440 static bool do_ping(struct messaging_context *msg_ctx,
441 const struct server_id pid,
442 const int argc, const char **argv)
445 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
449 /* Send a message and register our interest in a reply */
451 if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
454 messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
456 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
458 /* No replies were received within the timeout period */
460 if (num_replies == 0)
461 printf("No replies received\n");
463 messaging_deregister(msg_ctx, MSG_PONG, NULL);
468 /* Set profiling options */
470 static bool do_profile(struct messaging_context *msg_ctx,
471 const struct server_id pid,
472 const int argc, const char **argv)
477 fprintf(stderr, "Usage: smbcontrol <dest> profile "
478 "<off|count|on|flush>\n");
482 if (strcmp(argv[1], "off") == 0) {
484 } else if (strcmp(argv[1], "count") == 0) {
486 } else if (strcmp(argv[1], "on") == 0) {
488 } else if (strcmp(argv[1], "flush") == 0) {
491 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
495 return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
498 /* Return the profiling level */
500 static void profilelevel_cb(struct messaging_context *msg_ctx,
503 struct server_id pid,
511 if (data->length != sizeof(int)) {
512 fprintf(stderr, "invalid message length %ld returned\n",
513 (unsigned long)data->length);
517 memcpy(&level, data->data, sizeof(int));
530 s = "count and time";
537 printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
540 static void profilelevel_rqst(struct messaging_context *msg_ctx,
543 struct server_id pid,
548 /* Send back a dummy reply */
550 send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
553 static bool do_profilelevel(struct messaging_context *msg_ctx,
554 const struct server_id pid,
555 const int argc, const char **argv)
558 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
562 /* Send a message and register our interest in a reply */
564 if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
567 messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
568 messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
571 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
573 /* No replies were received within the timeout period */
575 if (num_replies == 0)
576 printf("No replies received\n");
578 messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
583 /* Display debug level settings */
585 static bool do_debuglevel(struct messaging_context *msg_ctx,
586 const struct server_id pid,
587 const int argc, const char **argv)
590 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
594 /* Send a message and register our interest in a reply */
596 if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
599 messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
601 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
603 /* No replies were received within the timeout period */
605 if (num_replies == 0)
606 printf("No replies received\n");
608 messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
613 /* Send a print notify message */
615 static bool do_printnotify(struct messaging_context *msg_ctx,
616 const struct server_id pid,
617 const int argc, const char **argv)
621 /* Check for subcommand */
624 fprintf(stderr, "Must specify subcommand:\n");
625 fprintf(stderr, "\tqueuepause <printername>\n");
626 fprintf(stderr, "\tqueueresume <printername>\n");
627 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
628 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
629 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
630 fprintf(stderr, "\tprinter <printername> <comment|port|"
631 "driver> <value>\n");
638 if (strcmp(cmd, "queuepause") == 0) {
641 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
642 " queuepause <printername>\n");
646 notify_printer_status_byname(messaging_event_context(msg_ctx),
648 PRINTER_STATUS_PAUSED);
652 } else if (strcmp(cmd, "queueresume") == 0) {
655 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
656 " queuereume <printername>\n");
660 notify_printer_status_byname(messaging_event_context(msg_ctx),
666 } else if (strcmp(cmd, "jobpause") == 0) {
670 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
671 " jobpause <printername> <unix-jobid>\n");
675 jobid = atoi(argv[3]);
677 notify_job_status_byname(
678 messaging_event_context(msg_ctx), msg_ctx,
679 argv[2], jobid, JOB_STATUS_PAUSED,
680 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
684 } else if (strcmp(cmd, "jobresume") == 0) {
688 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
689 " jobpause <printername> <unix-jobid>\n");
693 jobid = atoi(argv[3]);
695 notify_job_status_byname(
696 messaging_event_context(msg_ctx), msg_ctx,
697 argv[2], jobid, JOB_STATUS_QUEUED,
698 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
702 } else if (strcmp(cmd, "jobdelete") == 0) {
706 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
707 " jobpause <printername> <unix-jobid>\n");
711 jobid = atoi(argv[3]);
713 notify_job_status_byname(
714 messaging_event_context(msg_ctx), msg_ctx,
715 argv[2], jobid, JOB_STATUS_DELETING,
716 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
718 notify_job_status_byname(
719 messaging_event_context(msg_ctx), msg_ctx,
720 argv[2], jobid, JOB_STATUS_DELETING|
722 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
726 } else if (strcmp(cmd, "printer") == 0) {
730 fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
731 "printer <printername> <comment|port|driver> "
736 if (strcmp(argv[3], "comment") == 0) {
737 attribute = PRINTER_NOTIFY_FIELD_COMMENT;
738 } else if (strcmp(argv[3], "port") == 0) {
739 attribute = PRINTER_NOTIFY_FIELD_PORT_NAME;
740 } else if (strcmp(argv[3], "driver") == 0) {
741 attribute = PRINTER_NOTIFY_FIELD_DRIVER_NAME;
743 fprintf(stderr, "Invalid printer command '%s'\n",
748 notify_printer_byname(messaging_event_context(msg_ctx),
749 msg_ctx, argv[2], attribute,
750 CONST_DISCARD(char *, argv[4]));
755 fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
759 print_notify_send_messages(msg_ctx, 0);
765 static bool do_closeshare(struct messaging_context *msg_ctx,
766 const struct server_id pid,
767 const int argc, const char **argv)
770 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
775 return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
776 strlen(argv[1]) + 1);
779 /* Tell winbindd an IP got dropped */
781 static bool do_ip_dropped(struct messaging_context *msg_ctx,
782 const struct server_id pid,
783 const int argc, const char **argv)
786 fprintf(stderr, "Usage: smbcontrol <dest> ip-dropped "
791 return send_message(msg_ctx, pid, MSG_WINBIND_IP_DROPPED, argv[1],
792 strlen(argv[1]) + 1);
795 /* force a blocking lock retry */
797 static bool do_lockretry(struct messaging_context *msg_ctx,
798 const struct server_id pid,
799 const int argc, const char **argv)
802 fprintf(stderr, "Usage: smbcontrol <dest> lockretry\n");
806 return send_message(msg_ctx, pid, MSG_SMB_UNLOCK, NULL, 0);
809 /* force a validation of all brl entries, including re-sends. */
811 static bool do_brl_revalidate(struct messaging_context *msg_ctx,
812 const struct server_id pid,
813 const int argc, const char **argv)
816 fprintf(stderr, "Usage: smbcontrol <dest> brl-revalidate\n");
820 return send_message(msg_ctx, pid, MSG_SMB_BRL_VALIDATE, NULL, 0);
823 /* Force a SAM synchronisation */
825 static bool do_samsync(struct messaging_context *msg_ctx,
826 const struct server_id pid,
827 const int argc, const char **argv)
830 fprintf(stderr, "Usage: smbcontrol <dest> samsync\n");
834 return send_message(msg_ctx, pid, MSG_SMB_SAM_SYNC, NULL, 0);
837 /* Force a SAM replication */
839 static bool do_samrepl(struct messaging_context *msg_ctx,
840 const struct server_id pid,
841 const int argc, const char **argv)
844 fprintf(stderr, "Usage: smbcontrol <dest> samrepl\n");
848 return send_message(msg_ctx, pid, MSG_SMB_SAM_REPL, NULL, 0);
851 /* Display talloc pool usage */
853 static bool do_poolusage(struct messaging_context *msg_ctx,
854 const struct server_id pid,
855 const int argc, const char **argv)
858 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
862 messaging_register(msg_ctx, NULL, MSG_POOL_USAGE, print_string_cb);
864 /* Send a message and register our interest in a reply */
866 if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0))
869 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
871 /* No replies were received within the timeout period */
873 if (num_replies == 0)
874 printf("No replies received\n");
876 messaging_deregister(msg_ctx, MSG_POOL_USAGE, NULL);
881 /* Perform a dmalloc mark */
883 static bool do_dmalloc_mark(struct messaging_context *msg_ctx,
884 const struct server_id pid,
885 const int argc, const char **argv)
888 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
892 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
895 /* Perform a dmalloc changed */
897 static bool do_dmalloc_changed(struct messaging_context *msg_ctx,
898 const struct server_id pid,
899 const int argc, const char **argv)
902 fprintf(stderr, "Usage: smbcontrol <dest> "
903 "dmalloc-log-changed\n");
907 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
911 /* Shutdown a server process */
913 static bool do_shutdown(struct messaging_context *msg_ctx,
914 const struct server_id pid,
915 const int argc, const char **argv)
918 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
922 return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
925 /* Notify a driver upgrade */
927 static bool do_drvupgrade(struct messaging_context *msg_ctx,
928 const struct server_id pid,
929 const int argc, const char **argv)
932 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
937 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
938 strlen(argv[1]) + 1);
941 static bool do_winbind_online(struct messaging_context *msg_ctx,
942 const struct server_id pid,
943 const int argc, const char **argv)
948 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
952 /* Remove the entry in the winbindd_cache tdb to tell a later
953 starting winbindd that we're online. */
955 tdb = tdb_open_log(cache_path("winbindd_cache.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
957 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
958 cache_path("winbindd_cache.tdb"));
962 tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
965 return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
968 static bool do_winbind_offline(struct messaging_context *msg_ctx,
969 const struct server_id pid,
970 const int argc, const char **argv)
977 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
981 /* Create an entry in the winbindd_cache tdb to tell a later
982 starting winbindd that we're offline. We may actually create
985 tdb = tdb_open_log(cache_path("winbindd_cache.tdb"),
986 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
987 TDB_DEFAULT|TDB_INCOMPATIBLE_HASH /* TDB_CLEAR_IF_FIRST */,
988 O_RDWR|O_CREAT, 0600);
991 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
992 cache_path("winbindd_cache.tdb"));
996 /* There's a potential race condition that if a child
997 winbindd detects a domain is online at the same time
998 we're trying to tell it to go offline that it might
999 delete the record we add between us adding it and
1000 sending the message. Minimize this by retrying up to
1003 for (retry = 0; retry < 5; retry++) {
1009 SIVAL(buf, 0, time(NULL));
1013 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
1015 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
1018 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
1019 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
1021 if (!d.dptr || d.dsize != 4) {
1023 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
1034 static bool do_winbind_onlinestatus(struct messaging_context *msg_ctx,
1035 const struct server_id pid,
1036 const int argc, const char **argv)
1038 struct server_id myid;
1040 myid = messaging_server_id(msg_ctx);
1043 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
1047 messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
1048 print_pid_string_cb);
1050 if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, &myid,
1054 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1056 /* No replies were received within the timeout period */
1058 if (num_replies == 0)
1059 printf("No replies received\n");
1061 messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
1066 static bool do_dump_event_list(struct messaging_context *msg_ctx,
1067 const struct server_id pid,
1068 const int argc, const char **argv)
1070 struct server_id myid;
1072 myid = messaging_server_id(msg_ctx);
1075 fprintf(stderr, "Usage: smbcontrol <dest> dump-event-list\n");
1079 return send_message(msg_ctx, pid, MSG_DUMP_EVENT_LIST, NULL, 0);
1082 static bool do_winbind_dump_domain_list(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 = procid_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 messaging_context *msg_ctx,
1152 const struct server_id pid,
1153 const int argc, const char **argv)
1155 struct server_id myid;
1157 myid = messaging_server_id(msg_ctx);
1160 fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
1164 messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
1165 winbind_validate_cache_cb);
1167 if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
1172 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1174 if (num_replies == 0) {
1175 printf("No replies received\n");
1178 messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);
1183 static bool do_reload_config(struct messaging_context *msg_ctx,
1184 const struct server_id pid,
1185 const int argc, const char **argv)
1188 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1192 return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1195 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1198 memset( (char *)n, '\0', sizeof(struct nmb_name) );
1199 fstrcpy(unix_name, name);
1200 strupper_m(unix_name);
1201 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1202 n->name_type = (unsigned int)type & 0xFF;
1203 push_ascii(n->scope, global_scope(), 64, STR_TERMINATE);
1206 static bool do_nodestatus(struct messaging_context *msg_ctx,
1207 const struct server_id pid,
1208 const int argc, const char **argv)
1210 struct packet_struct p;
1213 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1219 p.ip = interpret_addr2(argv[1]);
1221 p.packet_type = NMB_PACKET;
1223 p.packet.nmb.header.name_trn_id = 10;
1224 p.packet.nmb.header.opcode = 0;
1225 p.packet.nmb.header.response = False;
1226 p.packet.nmb.header.nm_flags.bcast = False;
1227 p.packet.nmb.header.nm_flags.recursion_available = False;
1228 p.packet.nmb.header.nm_flags.recursion_desired = False;
1229 p.packet.nmb.header.nm_flags.trunc = False;
1230 p.packet.nmb.header.nm_flags.authoritative = False;
1231 p.packet.nmb.header.rcode = 0;
1232 p.packet.nmb.header.qdcount = 1;
1233 p.packet.nmb.header.ancount = 0;
1234 p.packet.nmb.header.nscount = 0;
1235 p.packet.nmb.header.arcount = 0;
1236 my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1237 p.packet.nmb.question.question_type = 0x21;
1238 p.packet.nmb.question.question_class = 0x1;
1240 return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1243 /* A list of message type supported */
1245 static const struct {
1246 const char *name; /* Option name */
1247 bool (*fn)(struct messaging_context *msg_ctx,
1248 const struct server_id pid,
1249 const int argc, const char **argv);
1250 const char *help; /* Short help text */
1252 { "debug", do_debug, "Set debuglevel" },
1253 { "idmap", do_idmap, "Manipulate idmap cache" },
1254 { "force-election", do_election,
1255 "Force a browse election" },
1256 { "ping", do_ping, "Elicit a response" },
1257 { "profile", do_profile, "" },
1258 { "inject", do_inject_fault,
1259 "Inject a fatal signal into a running smbd"},
1260 { "stacktrace", do_daemon_stack_trace,
1261 "Display a stack trace of a daemon" },
1262 { "profilelevel", do_profilelevel, "" },
1263 { "debuglevel", do_debuglevel, "Display current debuglevels" },
1264 { "printnotify", do_printnotify, "Send a print notify message" },
1265 { "close-share", do_closeshare, "Forcibly disconnect a share" },
1266 { "ip-dropped", do_ip_dropped, "Tell winbind that an IP got dropped" },
1267 { "lockretry", do_lockretry, "Force a blocking lock retry" },
1268 { "brl-revalidate", do_brl_revalidate, "Revalidate all brl entries" },
1269 { "samsync", do_samsync, "Initiate SAM synchronisation" },
1270 { "samrepl", do_samrepl, "Initiate SAM replication" },
1271 { "pool-usage", do_poolusage, "Display talloc memory usage" },
1272 { "dmalloc-mark", do_dmalloc_mark, "" },
1273 { "dmalloc-log-changed", do_dmalloc_changed, "" },
1274 { "shutdown", do_shutdown, "Shut down daemon" },
1275 { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
1276 { "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
1277 { "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
1278 { "online", do_winbind_online, "Ask winbind to go into online state"},
1279 { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
1280 { "onlinestatus", do_winbind_onlinestatus, "Request winbind online status"},
1281 { "dump-event-list", do_dump_event_list, "Dump event list"},
1282 { "validate-cache" , do_winbind_validate_cache,
1283 "Validate winbind's credential cache" },
1284 { "dump-domain-list", do_winbind_dump_domain_list, "Dump winbind domain list"},
1285 { "noop", do_noop, "Do nothing" },
1289 /* Display usage information */
1291 static void usage(poptContext pc)
1295 poptPrintHelp(pc, stderr, 0);
1297 fprintf(stderr, "\n");
1298 fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1301 fprintf(stderr, "\n");
1302 fprintf(stderr, "<message-type> is one of:\n");
1304 for (i = 0; msg_types[i].name; i++)
1305 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name,
1308 fprintf(stderr, "\n");
1313 /* Return the pid number for a string destination */
1315 static struct server_id parse_dest(struct messaging_context *msg,
1318 struct server_id result = {-1};
1321 /* Zero is a special return value for broadcast to all processes */
1323 if (strequal(dest, "all")) {
1324 return interpret_pid(MSG_BROADCAST_PID_STR);
1327 /* Try self - useful for testing */
1329 if (strequal(dest, "self")) {
1330 return messaging_server_id(msg);
1333 /* Fix winbind typo. */
1334 if (strequal(dest, "winbind")) {
1338 /* Check for numeric pid number */
1339 result = interpret_pid(dest);
1341 /* Zero isn't valid if not "all". */
1342 if (result.pid && procid_valid(&result)) {
1346 /* Look up other destinations in pidfile directory */
1348 if ((pid = pidfile_pid(dest)) != 0) {
1349 return pid_to_procid(pid);
1352 fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1357 /* Execute smbcontrol command */
1359 static bool do_command(struct messaging_context *msg_ctx,
1360 int argc, const char **argv)
1362 const char *dest = argv[0], *command = argv[1];
1363 struct server_id pid;
1366 /* Check destination */
1368 pid = parse_dest(msg_ctx, dest);
1369 if (!procid_valid(&pid)) {
1375 for (i = 0; msg_types[i].name; i++) {
1376 if (strequal(command, msg_types[i].name))
1377 return msg_types[i].fn(msg_ctx, pid,
1378 argc - 1, argv + 1);
1381 fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1386 static void smbcontrol_help(poptContext pc,
1387 enum poptCallbackReason preason,
1388 struct poptOption * poption,
1392 if (poption->shortName != '?') {
1393 poptPrintUsage(pc, stdout, 0);
1401 struct poptOption help_options[] = {
1402 { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1404 { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1405 { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1411 int main(int argc, const char **argv)
1415 struct tevent_context *evt_ctx;
1416 struct messaging_context *msg_ctx;
1418 static struct poptOption long_options[] = {
1420 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1421 0, "Help options:", NULL },
1422 { "timeout", 't', POPT_ARG_INT, &timeout, 't',
1423 "Set timeout value in seconds", "TIMEOUT" },
1428 TALLOC_CTX *frame = talloc_stackframe();
1433 setup_logging(argv[0], DEBUG_STDOUT);
1435 /* Parse command line arguments using popt */
1437 pc = poptGetContext(
1438 "smbcontrol", argc, (const char **)argv, long_options, 0);
1440 poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1446 while ((opt = poptGetNextOpt(pc)) != -1) {
1448 case 't': /* --timeout */
1451 fprintf(stderr, "Invalid option\n");
1452 poptPrintHelp(pc, stderr, 0);
1457 /* We should now have the remaining command line arguments in
1458 argv. The argc parameter should have been decremented to the
1459 correct value in the above switch statement. */
1461 argv = (const char **)poptGetArgs(pc);
1464 while (argv[argc] != NULL) {
1472 lp_load(get_dyn_CONFIGFILE(),False,False,False,True);
1474 /* Need to invert sense of return code -- samba
1475 * routines mostly return True==1 for success, but
1478 if (!(evt_ctx = tevent_context_init(NULL)) ||
1479 !(msg_ctx = messaging_init(NULL, procid_self(), evt_ctx))) {
1480 fprintf(stderr, "could not init messaging context\n");
1485 ret = !do_command(msg_ctx, argc, argv);