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/>.
29 #include <libunwind.h>
32 #if HAVE_LIBUNWIND_PTRACE_H
33 #include <libunwind-ptrace.h>
37 #include <sys/ptrace.h>
40 /* Default timeout value when waiting for replies (in seconds) */
42 #define DEFAULT_TIMEOUT 10
44 static int timeout = DEFAULT_TIMEOUT;
45 static int num_replies; /* Used by message callback fns */
47 /* Send a message to a destination pid. Zero means broadcast smbd. */
49 static bool send_message(struct messaging_context *msg_ctx,
50 struct server_id pid, int msg_type,
51 const void *buf, int len)
56 if (procid_to_pid(&pid) != 0)
57 return NT_STATUS_IS_OK(
58 messaging_send_buf(msg_ctx, pid, msg_type,
61 ret = message_send_all(msg_ctx, msg_type, buf, len, &n_sent);
62 DEBUG(10,("smbcontrol/send_message: broadcast message to "
63 "%d processes\n", n_sent));
68 static void smbcontrol_timeout(struct tevent_context *event_ctx,
69 struct tevent_timer *te,
73 bool *timed_out = (bool *)private_data;
78 /* Wait for one or more reply messages */
80 static void wait_replies(struct messaging_context *msg_ctx,
81 bool multiple_replies)
83 struct tevent_timer *te;
84 bool timed_out = False;
86 if (!(te = tevent_add_timer(messaging_event_context(msg_ctx), NULL,
87 timeval_current_ofs(timeout, 0),
88 smbcontrol_timeout, (void *)&timed_out))) {
89 DEBUG(0, ("tevent_add_timer failed\n"));
95 if (num_replies > 0 && !multiple_replies)
97 ret = tevent_loop_once(messaging_event_context(msg_ctx));
104 /* Message handler callback that displays the PID and a string on stdout */
106 static void print_pid_string_cb(struct messaging_context *msg,
109 struct server_id pid,
114 pidstr = procid_str(talloc_tos(), &pid);
115 printf("PID %s: %.*s", pidstr, (int)data->length,
116 (const char *)data->data);
121 /* Message handler callback that displays a string on stdout */
123 static void print_string_cb(struct messaging_context *msg,
126 struct server_id pid,
129 printf("%.*s", (int)data->length, (const char *)data->data);
133 /* Send no message. Useful for testing. */
135 static bool do_noop(struct messaging_context *msg_ctx,
136 const struct server_id pid,
137 const int argc, const char **argv)
140 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
144 /* Move along, nothing to see here */
149 /* Send a debug string */
151 static bool do_debug(struct messaging_context *msg_ctx,
152 const struct server_id pid,
153 const int argc, const char **argv)
156 fprintf(stderr, "Usage: smbcontrol <dest> debug "
161 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
162 strlen(argv[1]) + 1);
165 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
167 /* Return the name of a process given it's PID. This will only work on Linux,
168 * but that's probably moot since this whole stack tracing implementatino is
169 * Linux-specific anyway.
171 static const char * procname(pid_t pid, char * buf, size_t bufsz)
176 snprintf(path, sizeof(path), "/proc/%llu/cmdline",
177 (unsigned long long)pid);
178 if ((fp = fopen(path, "r")) == NULL) {
182 fgets(buf, bufsz, fp);
188 static void print_stack_trace(pid_t pid, int * count)
191 unw_addr_space_t aspace = NULL;
200 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
202 "Failed to attach to process %llu: %s\n",
203 (unsigned long long)pid, strerror(errno));
207 /* Wait until the attach is complete. */
208 waitpid(pid, NULL, 0);
210 if (((pinfo = _UPT_create(pid)) == NULL) ||
211 ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
212 /* Probably out of memory. */
214 "Unable to initialize stack unwind for process %llu\n",
215 (unsigned long long)pid);
219 if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
221 "Unable to unwind stack for process %llu: %s\n",
222 (unsigned long long)pid, unw_strerror(ret));
230 if (procname(pid, nbuf, sizeof(nbuf))) {
231 printf("Stack trace for process %llu (%s):\n",
232 (unsigned long long)pid, nbuf);
234 printf("Stack trace for process %llu:\n",
235 (unsigned long long)pid);
238 while (unw_step(&cursor) > 0) {
240 unw_get_reg(&cursor, UNW_REG_IP, &ip);
241 unw_get_reg(&cursor, UNW_REG_SP, &sp);
243 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
244 if (ret != 0 && ret != -UNW_ENOMEM) {
245 snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
247 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
248 nbuf, (long long)off, (long long)ip,
256 unw_destroy_addr_space(aspace);
263 ptrace(PTRACE_DETACH, pid, NULL, NULL);
266 static int stack_trace_connection(struct db_record *rec,
267 const struct connections_key *key,
268 const struct connections_data *crec,
271 print_stack_trace(procid_to_pid(&crec->pid), (int *)priv);
276 static bool do_daemon_stack_trace(struct messaging_context *msg_ctx,
277 const struct server_id pid,
278 const int argc, const char **argv)
284 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
288 dest = procid_to_pid(&pid);
291 /* It would be nice to be able to make sure that this PID is
292 * the PID of a smbd/winbind/nmbd process, not some random PID
293 * the user liked the look of. It doesn't seem like it's worth
294 * the effort at the moment, however.
296 print_stack_trace(dest, &count);
298 connections_forall(stack_trace_connection, &count);
304 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
306 static bool do_daemon_stack_trace(struct messaging_context *msg_ctx,
307 const struct server_id pid,
308 const int argc, const char **argv)
311 "Daemon stack tracing is not supported on this platform\n");
315 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
317 /* Inject a fault (fatal signal) into a running smbd */
319 static bool do_inject_fault(struct messaging_context *msg_ctx,
320 const struct server_id pid,
321 const int argc, const char **argv)
324 fprintf(stderr, "Usage: smbcontrol <dest> inject "
325 "<bus|hup|term|internal|segv>\n");
330 fprintf(stderr, "Fault injection is only available in "
331 "developer builds\n");
333 #else /* DEVELOPER */
337 if (strcmp(argv[1], "bus") == 0) {
339 } else if (strcmp(argv[1], "hup") == 0) {
341 } else if (strcmp(argv[1], "term") == 0) {
343 } else if (strcmp(argv[1], "segv") == 0) {
345 } else if (strcmp(argv[1], "internal") == 0) {
346 /* Force an internal error, ie. an unclean exit. */
349 fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
353 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
356 #endif /* DEVELOPER */
359 /* Force a browser election */
361 static bool do_election(struct messaging_context *msg_ctx,
362 const struct server_id pid,
363 const int argc, const char **argv)
366 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
370 return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
373 /* Ping a samba daemon process */
375 static void pong_cb(struct messaging_context *msg,
378 struct server_id pid,
381 char *src_string = procid_str(NULL, &pid);
382 printf("PONG from pid %s\n", src_string);
383 TALLOC_FREE(src_string);
387 static bool do_ping(struct messaging_context *msg_ctx,
388 const struct server_id pid,
389 const int argc, const char **argv)
392 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
396 /* Send a message and register our interest in a reply */
398 if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
401 messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
403 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
405 /* No replies were received within the timeout period */
407 if (num_replies == 0)
408 printf("No replies received\n");
410 messaging_deregister(msg_ctx, MSG_PONG, NULL);
415 /* Set profiling options */
417 static bool do_profile(struct messaging_context *msg_ctx,
418 const struct server_id pid,
419 const int argc, const char **argv)
424 fprintf(stderr, "Usage: smbcontrol <dest> profile "
425 "<off|count|on|flush>\n");
429 if (strcmp(argv[1], "off") == 0) {
431 } else if (strcmp(argv[1], "count") == 0) {
433 } else if (strcmp(argv[1], "on") == 0) {
435 } else if (strcmp(argv[1], "flush") == 0) {
438 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
442 return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
445 /* Return the profiling level */
447 static void profilelevel_cb(struct messaging_context *msg_ctx,
450 struct server_id pid,
458 if (data->length != sizeof(int)) {
459 fprintf(stderr, "invalid message length %ld returned\n",
460 (unsigned long)data->length);
464 memcpy(&level, data->data, sizeof(int));
477 s = "count and time";
484 printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
487 static void profilelevel_rqst(struct messaging_context *msg_ctx,
490 struct server_id pid,
495 /* Send back a dummy reply */
497 send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
500 static bool do_profilelevel(struct messaging_context *msg_ctx,
501 const struct server_id pid,
502 const int argc, const char **argv)
505 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
509 /* Send a message and register our interest in a reply */
511 if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
514 messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
515 messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
518 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
520 /* No replies were received within the timeout period */
522 if (num_replies == 0)
523 printf("No replies received\n");
525 messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
530 /* Display debug level settings */
532 static bool do_debuglevel(struct messaging_context *msg_ctx,
533 const struct server_id pid,
534 const int argc, const char **argv)
537 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
541 /* Send a message and register our interest in a reply */
543 if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
546 messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
548 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
550 /* No replies were received within the timeout period */
552 if (num_replies == 0)
553 printf("No replies received\n");
555 messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
560 /* Send a print notify message */
562 static bool do_printnotify(struct messaging_context *msg_ctx,
563 const struct server_id pid,
564 const int argc, const char **argv)
568 /* Check for subcommand */
571 fprintf(stderr, "Must specify subcommand:\n");
572 fprintf(stderr, "\tqueuepause <printername>\n");
573 fprintf(stderr, "\tqueueresume <printername>\n");
574 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
575 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
576 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
577 fprintf(stderr, "\tprinter <printername> <comment|port|"
578 "driver> <value>\n");
585 if (strcmp(cmd, "queuepause") == 0) {
588 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
589 " queuepause <printername>\n");
593 notify_printer_status_byname(argv[2], PRINTER_STATUS_PAUSED);
597 } else if (strcmp(cmd, "queueresume") == 0) {
600 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
601 " queuereume <printername>\n");
605 notify_printer_status_byname(argv[2], PRINTER_STATUS_OK);
609 } else if (strcmp(cmd, "jobpause") == 0) {
613 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
614 " jobpause <printername> <unix-jobid>\n");
618 jobid = atoi(argv[3]);
620 notify_job_status_byname(
621 argv[2], jobid, JOB_STATUS_PAUSED,
622 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
626 } else if (strcmp(cmd, "jobresume") == 0) {
630 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
631 " jobpause <printername> <unix-jobid>\n");
635 jobid = atoi(argv[3]);
637 notify_job_status_byname(
638 argv[2], jobid, JOB_STATUS_QUEUED,
639 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
643 } else if (strcmp(cmd, "jobdelete") == 0) {
647 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
648 " jobpause <printername> <unix-jobid>\n");
652 jobid = atoi(argv[3]);
654 notify_job_status_byname(
655 argv[2], jobid, JOB_STATUS_DELETING,
656 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
658 notify_job_status_byname(
659 argv[2], jobid, JOB_STATUS_DELETING|
661 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
665 } else if (strcmp(cmd, "printer") == 0) {
669 fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
670 "printer <printername> <comment|port|driver> "
675 if (strcmp(argv[3], "comment") == 0) {
676 attribute = PRINTER_NOTIFY_FIELD_COMMENT;
677 } else if (strcmp(argv[3], "port") == 0) {
678 attribute = PRINTER_NOTIFY_FIELD_PORT_NAME;
679 } else if (strcmp(argv[3], "driver") == 0) {
680 attribute = PRINTER_NOTIFY_FIELD_DRIVER_NAME;
682 fprintf(stderr, "Invalid printer command '%s'\n",
687 notify_printer_byname(argv[2], attribute,
688 CONST_DISCARD(char *, argv[4]));
693 fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
697 print_notify_send_messages(msg_ctx, 0);
703 static bool do_closeshare(struct messaging_context *msg_ctx,
704 const struct server_id pid,
705 const int argc, const char **argv)
708 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
713 return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
714 strlen(argv[1]) + 1);
717 /* Tell winbindd an IP got dropped */
719 static bool do_ip_dropped(struct messaging_context *msg_ctx,
720 const struct server_id pid,
721 const int argc, const char **argv)
724 fprintf(stderr, "Usage: smbcontrol <dest> ip-dropped "
729 return send_message(msg_ctx, pid, MSG_WINBIND_IP_DROPPED, argv[1],
730 strlen(argv[1]) + 1);
733 /* force a blocking lock retry */
735 static bool do_lockretry(struct messaging_context *msg_ctx,
736 const struct server_id pid,
737 const int argc, const char **argv)
740 fprintf(stderr, "Usage: smbcontrol <dest> lockretry\n");
744 return send_message(msg_ctx, pid, MSG_SMB_UNLOCK, NULL, 0);
747 /* force a validation of all brl entries, including re-sends. */
749 static bool do_brl_revalidate(struct messaging_context *msg_ctx,
750 const struct server_id pid,
751 const int argc, const char **argv)
754 fprintf(stderr, "Usage: smbcontrol <dest> brl-revalidate\n");
758 return send_message(msg_ctx, pid, MSG_SMB_BRL_VALIDATE, NULL, 0);
761 /* Force a SAM synchronisation */
763 static bool do_samsync(struct messaging_context *msg_ctx,
764 const struct server_id pid,
765 const int argc, const char **argv)
768 fprintf(stderr, "Usage: smbcontrol <dest> samsync\n");
772 return send_message(msg_ctx, pid, MSG_SMB_SAM_SYNC, NULL, 0);
775 /* Force a SAM replication */
777 static bool do_samrepl(struct messaging_context *msg_ctx,
778 const struct server_id pid,
779 const int argc, const char **argv)
782 fprintf(stderr, "Usage: smbcontrol <dest> samrepl\n");
786 return send_message(msg_ctx, pid, MSG_SMB_SAM_REPL, NULL, 0);
789 /* Display talloc pool usage */
791 static bool do_poolusage(struct messaging_context *msg_ctx,
792 const struct server_id pid,
793 const int argc, const char **argv)
796 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
800 messaging_register(msg_ctx, NULL, MSG_POOL_USAGE, print_string_cb);
802 /* Send a message and register our interest in a reply */
804 if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0))
807 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
809 /* No replies were received within the timeout period */
811 if (num_replies == 0)
812 printf("No replies received\n");
814 messaging_deregister(msg_ctx, MSG_POOL_USAGE, NULL);
819 /* Perform a dmalloc mark */
821 static bool do_dmalloc_mark(struct messaging_context *msg_ctx,
822 const struct server_id pid,
823 const int argc, const char **argv)
826 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
830 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
833 /* Perform a dmalloc changed */
835 static bool do_dmalloc_changed(struct messaging_context *msg_ctx,
836 const struct server_id pid,
837 const int argc, const char **argv)
840 fprintf(stderr, "Usage: smbcontrol <dest> "
841 "dmalloc-log-changed\n");
845 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
849 /* Shutdown a server process */
851 static bool do_shutdown(struct messaging_context *msg_ctx,
852 const struct server_id pid,
853 const int argc, const char **argv)
856 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
860 return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
863 /* Notify a driver upgrade */
865 static bool do_drvupgrade(struct messaging_context *msg_ctx,
866 const struct server_id pid,
867 const int argc, const char **argv)
870 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
875 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
876 strlen(argv[1]) + 1);
879 static bool do_winbind_online(struct messaging_context *msg_ctx,
880 const struct server_id pid,
881 const int argc, const char **argv)
886 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
890 /* Remove the entry in the winbindd_cache tdb to tell a later
891 starting winbindd that we're online. */
893 tdb = tdb_open_log(cache_path("winbindd_cache.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
895 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
896 cache_path("winbindd_cache.tdb"));
900 tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
903 return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
906 static bool do_winbind_offline(struct messaging_context *msg_ctx,
907 const struct server_id pid,
908 const int argc, const char **argv)
915 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
919 /* Create an entry in the winbindd_cache tdb to tell a later
920 starting winbindd that we're offline. We may actually create
923 tdb = tdb_open_log(cache_path("winbindd_cache.tdb"),
924 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
925 TDB_DEFAULT /* TDB_CLEAR_IF_FIRST */, O_RDWR|O_CREAT, 0600);
928 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
929 cache_path("winbindd_cache.tdb"));
933 /* There's a potential race condition that if a child
934 winbindd detects a domain is online at the same time
935 we're trying to tell it to go offline that it might
936 delete the record we add between us adding it and
937 sending the message. Minimize this by retrying up to
940 for (retry = 0; retry < 5; retry++) {
946 SIVAL(buf, 0, time(NULL));
950 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
952 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
955 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
956 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
958 if (!d.dptr || d.dsize != 4) {
960 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
971 static bool do_winbind_onlinestatus(struct messaging_context *msg_ctx,
972 const struct server_id pid,
973 const int argc, const char **argv)
975 struct server_id myid;
977 myid = pid_to_procid(sys_getpid());
980 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
984 messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
985 print_pid_string_cb);
987 if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, &myid,
991 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
993 /* No replies were received within the timeout period */
995 if (num_replies == 0)
996 printf("No replies received\n");
998 messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
1003 static bool do_dump_event_list(struct messaging_context *msg_ctx,
1004 const struct server_id pid,
1005 const int argc, const char **argv)
1007 struct server_id myid;
1009 myid = pid_to_procid(sys_getpid());
1012 fprintf(stderr, "Usage: smbcontrol <dest> dump-event-list\n");
1016 return send_message(msg_ctx, pid, MSG_DUMP_EVENT_LIST, NULL, 0);
1019 static bool do_winbind_dump_domain_list(struct messaging_context *msg_ctx,
1020 const struct server_id pid,
1021 const int argc, const char **argv)
1023 const char *domain = NULL;
1025 struct server_id myid;
1026 uint8_t *buf = NULL;
1029 myid = pid_to_procid(sys_getpid());
1031 if (argc < 1 || argc > 2) {
1032 fprintf(stderr, "Usage: smbcontrol <dest> dump_domain_list "
1039 domain_len = strlen(argv[1]) + 1;
1042 messaging_register(msg_ctx, NULL, MSG_WINBIND_DUMP_DOMAIN_LIST,
1043 print_pid_string_cb);
1045 buf_len = sizeof(myid)+domain_len;
1046 buf = SMB_MALLOC_ARRAY(uint8_t, buf_len);
1051 memcpy(buf, &myid, sizeof(myid));
1052 memcpy(&buf[sizeof(myid)], domain, domain_len);
1054 if (!send_message(msg_ctx, pid, MSG_WINBIND_DUMP_DOMAIN_LIST,
1061 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1063 /* No replies were received within the timeout period */
1066 if (num_replies == 0) {
1067 printf("No replies received\n");
1070 messaging_deregister(msg_ctx, MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
1075 static void winbind_validate_cache_cb(struct messaging_context *msg,
1078 struct server_id pid,
1081 char *src_string = procid_str(NULL, &pid);
1082 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1083 (*(data->data) == 0 ? "" : "NOT "), src_string);
1084 TALLOC_FREE(src_string);
1088 static bool do_winbind_validate_cache(struct messaging_context *msg_ctx,
1089 const struct server_id pid,
1090 const int argc, const char **argv)
1092 struct server_id myid = pid_to_procid(sys_getpid());
1095 fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
1099 messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
1100 winbind_validate_cache_cb);
1102 if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
1107 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1109 if (num_replies == 0) {
1110 printf("No replies received\n");
1113 messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);
1118 static bool do_reload_config(struct messaging_context *msg_ctx,
1119 const struct server_id pid,
1120 const int argc, const char **argv)
1123 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1127 return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1130 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1133 memset( (char *)n, '\0', sizeof(struct nmb_name) );
1134 fstrcpy(unix_name, name);
1135 strupper_m(unix_name);
1136 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1137 n->name_type = (unsigned int)type & 0xFF;
1138 push_ascii(n->scope, global_scope(), 64, STR_TERMINATE);
1141 static bool do_nodestatus(struct messaging_context *msg_ctx,
1142 const struct server_id pid,
1143 const int argc, const char **argv)
1145 struct packet_struct p;
1148 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1154 p.ip = interpret_addr2(argv[1]);
1156 p.packet_type = NMB_PACKET;
1158 p.packet.nmb.header.name_trn_id = 10;
1159 p.packet.nmb.header.opcode = 0;
1160 p.packet.nmb.header.response = False;
1161 p.packet.nmb.header.nm_flags.bcast = False;
1162 p.packet.nmb.header.nm_flags.recursion_available = False;
1163 p.packet.nmb.header.nm_flags.recursion_desired = False;
1164 p.packet.nmb.header.nm_flags.trunc = False;
1165 p.packet.nmb.header.nm_flags.authoritative = False;
1166 p.packet.nmb.header.rcode = 0;
1167 p.packet.nmb.header.qdcount = 1;
1168 p.packet.nmb.header.ancount = 0;
1169 p.packet.nmb.header.nscount = 0;
1170 p.packet.nmb.header.arcount = 0;
1171 my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1172 p.packet.nmb.question.question_type = 0x21;
1173 p.packet.nmb.question.question_class = 0x1;
1175 return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1178 /* A list of message type supported */
1180 static const struct {
1181 const char *name; /* Option name */
1182 bool (*fn)(struct messaging_context *msg_ctx,
1183 const struct server_id pid,
1184 const int argc, const char **argv);
1185 const char *help; /* Short help text */
1187 { "debug", do_debug, "Set debuglevel" },
1188 { "force-election", do_election,
1189 "Force a browse election" },
1190 { "ping", do_ping, "Elicit a response" },
1191 { "profile", do_profile, "" },
1192 { "inject", do_inject_fault,
1193 "Inject a fatal signal into a running smbd"},
1194 { "stacktrace", do_daemon_stack_trace,
1195 "Display a stack trace of a daemon" },
1196 { "profilelevel", do_profilelevel, "" },
1197 { "debuglevel", do_debuglevel, "Display current debuglevels" },
1198 { "printnotify", do_printnotify, "Send a print notify message" },
1199 { "close-share", do_closeshare, "Forcibly disconnect a share" },
1200 { "ip-dropped", do_ip_dropped, "Tell winbind that an IP got dropped" },
1201 { "lockretry", do_lockretry, "Force a blocking lock retry" },
1202 { "brl-revalidate", do_brl_revalidate, "Revalidate all brl entries" },
1203 { "samsync", do_samsync, "Initiate SAM synchronisation" },
1204 { "samrepl", do_samrepl, "Initiate SAM replication" },
1205 { "pool-usage", do_poolusage, "Display talloc memory usage" },
1206 { "dmalloc-mark", do_dmalloc_mark, "" },
1207 { "dmalloc-log-changed", do_dmalloc_changed, "" },
1208 { "shutdown", do_shutdown, "Shut down daemon" },
1209 { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
1210 { "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
1211 { "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
1212 { "online", do_winbind_online, "Ask winbind to go into online state"},
1213 { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
1214 { "onlinestatus", do_winbind_onlinestatus, "Request winbind online status"},
1215 { "dump-event-list", do_dump_event_list, "Dump event list"},
1216 { "validate-cache" , do_winbind_validate_cache,
1217 "Validate winbind's credential cache" },
1218 { "dump-domain-list", do_winbind_dump_domain_list, "Dump winbind domain list"},
1219 { "noop", do_noop, "Do nothing" },
1223 /* Display usage information */
1225 static void usage(poptContext pc)
1229 poptPrintHelp(pc, stderr, 0);
1231 fprintf(stderr, "\n");
1232 fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1235 fprintf(stderr, "\n");
1236 fprintf(stderr, "<message-type> is one of:\n");
1238 for (i = 0; msg_types[i].name; i++)
1239 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name,
1242 fprintf(stderr, "\n");
1247 /* Return the pid number for a string destination */
1249 static struct server_id parse_dest(const char *dest)
1251 struct server_id result = {-1};
1254 /* Zero is a special return value for broadcast to all processes */
1256 if (strequal(dest, "all")) {
1257 return interpret_pid(MSG_BROADCAST_PID_STR);
1260 /* Try self - useful for testing */
1262 if (strequal(dest, "self")) {
1263 return pid_to_procid(sys_getpid());
1266 /* Fix winbind typo. */
1267 if (strequal(dest, "winbind")) {
1271 /* Check for numeric pid number */
1272 result = interpret_pid(dest);
1274 /* Zero isn't valid if not "all". */
1275 if (result.pid && procid_valid(&result)) {
1279 /* Look up other destinations in pidfile directory */
1281 if ((pid = pidfile_pid(dest)) != 0) {
1282 return pid_to_procid(pid);
1285 fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1290 /* Execute smbcontrol command */
1292 static bool do_command(struct messaging_context *msg_ctx,
1293 int argc, const char **argv)
1295 const char *dest = argv[0], *command = argv[1];
1296 struct server_id pid;
1299 /* Check destination */
1301 pid = parse_dest(dest);
1302 if (!procid_valid(&pid)) {
1308 for (i = 0; msg_types[i].name; i++) {
1309 if (strequal(command, msg_types[i].name))
1310 return msg_types[i].fn(msg_ctx, pid,
1311 argc - 1, argv + 1);
1314 fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1319 static void smbcontrol_help(poptContext pc,
1320 enum poptCallbackReason preason,
1321 struct poptOption * poption,
1325 if (poption->shortName != '?') {
1326 poptPrintUsage(pc, stdout, 0);
1334 struct poptOption help_options[] = {
1335 { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1337 { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1338 { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1344 int main(int argc, const char **argv)
1348 struct tevent_context *evt_ctx;
1349 struct messaging_context *msg_ctx;
1351 static struct poptOption long_options[] = {
1353 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1354 0, "Help options:", NULL },
1355 { "timeout", 't', POPT_ARG_INT, &timeout, 't',
1356 "Set timeout value in seconds", "TIMEOUT" },
1361 TALLOC_CTX *frame = talloc_stackframe();
1366 setup_logging(argv[0],True);
1368 /* Parse command line arguments using popt */
1370 pc = poptGetContext(
1371 "smbcontrol", argc, (const char **)argv, long_options, 0);
1373 poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1379 while ((opt = poptGetNextOpt(pc)) != -1) {
1381 case 't': /* --timeout */
1384 fprintf(stderr, "Invalid option\n");
1385 poptPrintHelp(pc, stderr, 0);
1390 /* We should now have the remaining command line arguments in
1391 argv. The argc parameter should have been decremented to the
1392 correct value in the above switch statement. */
1394 argv = (const char **)poptGetArgs(pc);
1397 while (argv[argc] != NULL) {
1405 lp_load(get_dyn_CONFIGFILE(),False,False,False,True);
1407 /* Need to invert sense of return code -- samba
1408 * routines mostly return True==1 for success, but
1411 if (!(evt_ctx = tevent_context_init(NULL)) ||
1412 !(msg_ctx = messaging_init(NULL, server_id_self(), evt_ctx))) {
1413 fprintf(stderr, "could not init messaging context\n");
1418 ret = !do_command(msg_ctx, argc, argv);