2 Unix SMB/CIFS implementation.
4 Send messages to other Samba daemons
6 Copyright (C) Tim Potter 2003
7 Copyright (C) Andrew Tridgell 1994-1998
8 Copyright (C) Martin Pool 2001-2002
9 Copyright (C) Simo Sorce 2002
10 Copyright (C) James Peach 2006
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include "librpc/gen_ndr/messaging.h"
30 #include <libunwind.h>
33 #if HAVE_LIBUNWIND_PTRACE_H
34 #include <libunwind-ptrace.h>
38 #include <sys/ptrace.h>
41 /* Default timeout value when waiting for replies (in seconds) */
43 #define DEFAULT_TIMEOUT 10
45 static int timeout
= DEFAULT_TIMEOUT
;
46 static int num_replies
; /* Used by message callback fns */
48 /* Send a message to a destination pid. Zero means broadcast smbd. */
50 static bool send_message(struct messaging_context
*msg_ctx
,
51 struct server_id pid
, int msg_type
,
52 const void *buf
, int len
)
57 if (procid_to_pid(&pid
) != 0)
58 return NT_STATUS_IS_OK(
59 messaging_send_buf(msg_ctx
, pid
, msg_type
,
62 ret
= message_send_all(msg_ctx
, msg_type
, buf
, len
, &n_sent
);
63 DEBUG(10,("smbcontrol/send_message: broadcast message to "
64 "%d processes\n", n_sent
));
69 static void smbcontrol_timeout(struct tevent_context
*event_ctx
,
70 struct tevent_timer
*te
,
74 bool *timed_out
= (bool *)private_data
;
79 /* Wait for one or more reply messages */
81 static void wait_replies(struct messaging_context
*msg_ctx
,
82 bool multiple_replies
)
84 struct tevent_timer
*te
;
85 bool timed_out
= False
;
87 if (!(te
= tevent_add_timer(messaging_event_context(msg_ctx
), NULL
,
88 timeval_current_ofs(timeout
, 0),
89 smbcontrol_timeout
, (void *)&timed_out
))) {
90 DEBUG(0, ("tevent_add_timer failed\n"));
96 if (num_replies
> 0 && !multiple_replies
)
98 ret
= tevent_loop_once(messaging_event_context(msg_ctx
));
105 /* Message handler callback that displays the PID and a string on stdout */
107 static void print_pid_string_cb(struct messaging_context
*msg
,
110 struct server_id pid
,
115 pidstr
= procid_str(talloc_tos(), &pid
);
116 printf("PID %s: %.*s", pidstr
, (int)data
->length
,
117 (const char *)data
->data
);
122 /* Message handler callback that displays a string on stdout */
124 static void print_string_cb(struct messaging_context
*msg
,
127 struct server_id pid
,
130 printf("%*s", (int)data
->length
, (const char *)data
->data
);
134 /* Send no message. Useful for testing. */
136 static bool do_noop(struct messaging_context
*msg_ctx
,
137 const struct server_id pid
,
138 const int argc
, const char **argv
)
141 fprintf(stderr
, "Usage: smbcontrol <dest> noop\n");
145 /* Move along, nothing to see here */
150 /* Send a debug string */
152 static bool do_debug(struct messaging_context
*msg_ctx
,
153 const struct server_id pid
,
154 const int argc
, const char **argv
)
157 fprintf(stderr
, "Usage: smbcontrol <dest> debug "
162 return send_message(msg_ctx
, pid
, MSG_DEBUG
, argv
[1],
163 strlen(argv
[1]) + 1);
166 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
168 /* Return the name of a process given it's PID. This will only work on Linux,
169 * but that's probably moot since this whole stack tracing implementatino is
170 * Linux-specific anyway.
172 static const char * procname(pid_t pid
, char * buf
, size_t bufsz
)
177 snprintf(path
, sizeof(path
), "/proc/%llu/cmdline",
178 (unsigned long long)pid
);
179 if ((fp
= fopen(path
, "r")) == NULL
) {
183 fgets(buf
, bufsz
, fp
);
189 static void print_stack_trace(pid_t pid
, int * count
)
192 unw_addr_space_t aspace
= NULL
;
201 if (ptrace(PTRACE_ATTACH
, pid
, NULL
, NULL
) < 0) {
203 "Failed to attach to process %llu: %s\n",
204 (unsigned long long)pid
, strerror(errno
));
208 /* Wait until the attach is complete. */
209 waitpid(pid
, NULL
, 0);
211 if (((pinfo
= _UPT_create(pid
)) == NULL
) ||
212 ((aspace
= unw_create_addr_space(&_UPT_accessors
, 0)) == NULL
)) {
213 /* Probably out of memory. */
215 "Unable to initialize stack unwind for process %llu\n",
216 (unsigned long long)pid
);
220 if ((ret
= unw_init_remote(&cursor
, aspace
, pinfo
))) {
222 "Unable to unwind stack for process %llu: %s\n",
223 (unsigned long long)pid
, unw_strerror(ret
));
231 if (procname(pid
, nbuf
, sizeof(nbuf
))) {
232 printf("Stack trace for process %llu (%s):\n",
233 (unsigned long long)pid
, nbuf
);
235 printf("Stack trace for process %llu:\n",
236 (unsigned long long)pid
);
239 while (unw_step(&cursor
) > 0) {
241 unw_get_reg(&cursor
, UNW_REG_IP
, &ip
);
242 unw_get_reg(&cursor
, UNW_REG_SP
, &sp
);
244 ret
= unw_get_proc_name(&cursor
, nbuf
, sizeof(nbuf
), &off
);
245 if (ret
!= 0 && ret
!= -UNW_ENOMEM
) {
246 snprintf(nbuf
, sizeof(nbuf
), "<unknown symbol>");
248 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
249 nbuf
, (long long)off
, (long long)ip
,
257 unw_destroy_addr_space(aspace
);
264 ptrace(PTRACE_DETACH
, pid
, NULL
, NULL
);
267 static int stack_trace_connection(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_read(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 /* force a blocking lock retry */
719 static bool do_lockretry(struct messaging_context
*msg_ctx
,
720 const struct server_id pid
,
721 const int argc
, const char **argv
)
724 fprintf(stderr
, "Usage: smbcontrol <dest> lockretry\n");
728 return send_message(msg_ctx
, pid
, MSG_SMB_UNLOCK
, NULL
, 0);
731 /* force a validation of all brl entries, including re-sends. */
733 static bool do_brl_revalidate(struct messaging_context
*msg_ctx
,
734 const struct server_id pid
,
735 const int argc
, const char **argv
)
738 fprintf(stderr
, "Usage: smbcontrol <dest> brl-revalidate\n");
742 return send_message(msg_ctx
, pid
, MSG_SMB_BRL_VALIDATE
, NULL
, 0);
745 /* Force a SAM synchronisation */
747 static bool do_samsync(struct messaging_context
*msg_ctx
,
748 const struct server_id pid
,
749 const int argc
, const char **argv
)
752 fprintf(stderr
, "Usage: smbcontrol <dest> samsync\n");
756 return send_message(msg_ctx
, pid
, MSG_SMB_SAM_SYNC
, NULL
, 0);
759 /* Force a SAM replication */
761 static bool do_samrepl(struct messaging_context
*msg_ctx
,
762 const struct server_id pid
,
763 const int argc
, const char **argv
)
766 fprintf(stderr
, "Usage: smbcontrol <dest> samrepl\n");
770 return send_message(msg_ctx
, pid
, MSG_SMB_SAM_REPL
, NULL
, 0);
773 /* Display talloc pool usage */
775 static bool do_poolusage(struct messaging_context
*msg_ctx
,
776 const struct server_id pid
,
777 const int argc
, const char **argv
)
780 fprintf(stderr
, "Usage: smbcontrol <dest> pool-usage\n");
784 messaging_register(msg_ctx
, NULL
, MSG_POOL_USAGE
, print_string_cb
);
786 /* Send a message and register our interest in a reply */
788 if (!send_message(msg_ctx
, pid
, MSG_REQ_POOL_USAGE
, NULL
, 0))
791 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
793 /* No replies were received within the timeout period */
795 if (num_replies
== 0)
796 printf("No replies received\n");
798 messaging_deregister(msg_ctx
, MSG_POOL_USAGE
, NULL
);
803 /* Perform a dmalloc mark */
805 static bool do_dmalloc_mark(struct messaging_context
*msg_ctx
,
806 const struct server_id pid
,
807 const int argc
, const char **argv
)
810 fprintf(stderr
, "Usage: smbcontrol <dest> dmalloc-mark\n");
814 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_MARK
, NULL
, 0);
817 /* Perform a dmalloc changed */
819 static bool do_dmalloc_changed(struct messaging_context
*msg_ctx
,
820 const struct server_id pid
,
821 const int argc
, const char **argv
)
824 fprintf(stderr
, "Usage: smbcontrol <dest> "
825 "dmalloc-log-changed\n");
829 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_LOG_CHANGED
,
833 /* Shutdown a server process */
835 static bool do_shutdown(struct messaging_context
*msg_ctx
,
836 const struct server_id pid
,
837 const int argc
, const char **argv
)
840 fprintf(stderr
, "Usage: smbcontrol <dest> shutdown\n");
844 return send_message(msg_ctx
, pid
, MSG_SHUTDOWN
, NULL
, 0);
847 /* Notify a driver upgrade */
849 static bool do_drvupgrade(struct messaging_context
*msg_ctx
,
850 const struct server_id pid
,
851 const int argc
, const char **argv
)
854 fprintf(stderr
, "Usage: smbcontrol <dest> drvupgrade "
859 return send_message(msg_ctx
, pid
, MSG_DEBUG
, argv
[1],
860 strlen(argv
[1]) + 1);
863 static bool do_winbind_online(struct messaging_context
*msg_ctx
,
864 const struct server_id pid
,
865 const int argc
, const char **argv
)
870 fprintf(stderr
, "Usage: smbcontrol winbindd online\n");
874 /* Remove the entry in the winbindd_cache tdb to tell a later
875 starting winbindd that we're online. */
877 tdb
= tdb_open_log(cache_path("winbindd_cache.tdb"), 0, TDB_DEFAULT
, O_RDWR
, 0600);
879 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
880 cache_path("winbindd_cache.tdb"));
884 tdb_delete_bystring(tdb
, "WINBINDD_OFFLINE");
887 return send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINE
, NULL
, 0);
890 static bool do_winbind_offline(struct messaging_context
*msg_ctx
,
891 const struct server_id pid
,
892 const int argc
, const char **argv
)
899 fprintf(stderr
, "Usage: smbcontrol winbindd offline\n");
903 /* Create an entry in the winbindd_cache tdb to tell a later
904 starting winbindd that we're offline. We may actually create
907 tdb
= tdb_open_log(cache_path("winbindd_cache.tdb"),
908 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE
,
909 TDB_DEFAULT
/* TDB_CLEAR_IF_FIRST */, O_RDWR
|O_CREAT
, 0600);
912 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
913 cache_path("winbindd_cache.tdb"));
917 /* There's a potential race condition that if a child
918 winbindd detects a domain is online at the same time
919 we're trying to tell it to go offline that it might
920 delete the record we add between us adding it and
921 sending the message. Minimize this by retrying up to
924 for (retry
= 0; retry
< 5; retry
++) {
930 SIVAL(buf
, 0, time(NULL
));
934 tdb_store_bystring(tdb
, "WINBINDD_OFFLINE", d
, TDB_INSERT
);
936 ret
= send_message(msg_ctx
, pid
, MSG_WINBIND_OFFLINE
,
939 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
940 d
= tdb_fetch_bystring( tdb
, "WINBINDD_OFFLINE" );
942 if (!d
.dptr
|| d
.dsize
!= 4) {
944 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
955 static bool do_winbind_onlinestatus(struct messaging_context
*msg_ctx
,
956 const struct server_id pid
,
957 const int argc
, const char **argv
)
959 struct server_id myid
;
961 myid
= procid_self();
964 fprintf(stderr
, "Usage: smbcontrol winbindd onlinestatus\n");
968 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_ONLINESTATUS
,
969 print_pid_string_cb
);
971 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINESTATUS
, &myid
,
975 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
977 /* No replies were received within the timeout period */
979 if (num_replies
== 0)
980 printf("No replies received\n");
982 messaging_deregister(msg_ctx
, MSG_WINBIND_ONLINESTATUS
, NULL
);
987 static bool do_dump_event_list(struct messaging_context
*msg_ctx
,
988 const struct server_id pid
,
989 const int argc
, const char **argv
)
991 struct server_id myid
;
993 myid
= procid_self();
996 fprintf(stderr
, "Usage: smbcontrol <dest> dump-event-list\n");
1000 return send_message(msg_ctx
, pid
, MSG_DUMP_EVENT_LIST
, NULL
, 0);
1003 static bool do_winbind_dump_domain_list(struct messaging_context
*msg_ctx
,
1004 const struct server_id pid
,
1005 const int argc
, const char **argv
)
1007 const char *domain
= NULL
;
1009 struct server_id myid
;
1010 uint8_t *buf
= NULL
;
1013 myid
= procid_self();
1015 if (argc
< 1 || argc
> 2) {
1016 fprintf(stderr
, "Usage: smbcontrol <dest> dump_domain_list "
1023 domain_len
= strlen(argv
[1]) + 1;
1026 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1027 print_pid_string_cb
);
1029 buf_len
= sizeof(myid
)+domain_len
;
1030 buf
= SMB_MALLOC_ARRAY(uint8_t, buf_len
);
1035 memcpy(buf
, &myid
, sizeof(myid
));
1036 memcpy(&buf
[sizeof(myid
)], domain
, domain_len
);
1038 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1045 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
1047 /* No replies were received within the timeout period */
1050 if (num_replies
== 0) {
1051 printf("No replies received\n");
1054 messaging_deregister(msg_ctx
, MSG_WINBIND_DUMP_DOMAIN_LIST
, NULL
);
1059 static void winbind_validate_cache_cb(struct messaging_context
*msg
,
1062 struct server_id pid
,
1065 char *src_string
= procid_str(NULL
, &pid
);
1066 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1067 (*(data
->data
) == 0 ? "" : "NOT "), src_string
);
1068 TALLOC_FREE(src_string
);
1072 static bool do_winbind_validate_cache(struct messaging_context
*msg_ctx
,
1073 const struct server_id pid
,
1074 const int argc
, const char **argv
)
1076 struct server_id myid
= procid_self();
1079 fprintf(stderr
, "Usage: smbcontrol winbindd validate-cache\n");
1083 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_VALIDATE_CACHE
,
1084 winbind_validate_cache_cb
);
1086 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_VALIDATE_CACHE
, &myid
,
1091 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
1093 if (num_replies
== 0) {
1094 printf("No replies received\n");
1097 messaging_deregister(msg_ctx
, MSG_WINBIND_VALIDATE_CACHE
, NULL
);
1102 static bool do_reload_config(struct messaging_context
*msg_ctx
,
1103 const struct server_id pid
,
1104 const int argc
, const char **argv
)
1107 fprintf(stderr
, "Usage: smbcontrol <dest> reload-config\n");
1111 return send_message(msg_ctx
, pid
, MSG_SMB_CONF_UPDATED
, NULL
, 0);
1114 static void my_make_nmb_name( struct nmb_name
*n
, const char *name
, int type
)
1117 memset( (char *)n
, '\0', sizeof(struct nmb_name
) );
1118 fstrcpy(unix_name
, name
);
1119 strupper_m(unix_name
);
1120 push_ascii(n
->name
, unix_name
, sizeof(n
->name
), STR_TERMINATE
);
1121 n
->name_type
= (unsigned int)type
& 0xFF;
1122 push_ascii(n
->scope
, global_scope(), 64, STR_TERMINATE
);
1125 static bool do_nodestatus(struct messaging_context
*msg_ctx
,
1126 const struct server_id pid
,
1127 const int argc
, const char **argv
)
1129 struct packet_struct p
;
1132 fprintf(stderr
, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1138 p
.ip
= interpret_addr2(argv
[1]);
1140 p
.packet_type
= NMB_PACKET
;
1142 p
.packet
.nmb
.header
.name_trn_id
= 10;
1143 p
.packet
.nmb
.header
.opcode
= 0;
1144 p
.packet
.nmb
.header
.response
= False
;
1145 p
.packet
.nmb
.header
.nm_flags
.bcast
= False
;
1146 p
.packet
.nmb
.header
.nm_flags
.recursion_available
= False
;
1147 p
.packet
.nmb
.header
.nm_flags
.recursion_desired
= False
;
1148 p
.packet
.nmb
.header
.nm_flags
.trunc
= False
;
1149 p
.packet
.nmb
.header
.nm_flags
.authoritative
= False
;
1150 p
.packet
.nmb
.header
.rcode
= 0;
1151 p
.packet
.nmb
.header
.qdcount
= 1;
1152 p
.packet
.nmb
.header
.ancount
= 0;
1153 p
.packet
.nmb
.header
.nscount
= 0;
1154 p
.packet
.nmb
.header
.arcount
= 0;
1155 my_make_nmb_name(&p
.packet
.nmb
.question
.question_name
, "*", 0x00);
1156 p
.packet
.nmb
.question
.question_type
= 0x21;
1157 p
.packet
.nmb
.question
.question_class
= 0x1;
1159 return send_message(msg_ctx
, pid
, MSG_SEND_PACKET
, &p
, sizeof(p
));
1162 /* A list of message type supported */
1164 static const struct {
1165 const char *name
; /* Option name */
1166 bool (*fn
)(struct messaging_context
*msg_ctx
,
1167 const struct server_id pid
,
1168 const int argc
, const char **argv
);
1169 const char *help
; /* Short help text */
1171 { "debug", do_debug
, "Set debuglevel" },
1172 { "force-election", do_election
,
1173 "Force a browse election" },
1174 { "ping", do_ping
, "Elicit a response" },
1175 { "profile", do_profile
, "" },
1176 { "inject", do_inject_fault
,
1177 "Inject a fatal signal into a running smbd"},
1178 { "stacktrace", do_daemon_stack_trace
,
1179 "Display a stack trace of a daemon" },
1180 { "profilelevel", do_profilelevel
, "" },
1181 { "debuglevel", do_debuglevel
, "Display current debuglevels" },
1182 { "printnotify", do_printnotify
, "Send a print notify message" },
1183 { "close-share", do_closeshare
, "Forcibly disconnect a share" },
1184 { "lockretry", do_lockretry
, "Force a blocking lock retry" },
1185 { "brl-revalidate", do_brl_revalidate
, "Revalidate all brl entries" },
1186 { "samsync", do_samsync
, "Initiate SAM synchronisation" },
1187 { "samrepl", do_samrepl
, "Initiate SAM replication" },
1188 { "pool-usage", do_poolusage
, "Display talloc memory usage" },
1189 { "dmalloc-mark", do_dmalloc_mark
, "" },
1190 { "dmalloc-log-changed", do_dmalloc_changed
, "" },
1191 { "shutdown", do_shutdown
, "Shut down daemon" },
1192 { "drvupgrade", do_drvupgrade
, "Notify a printer driver has changed" },
1193 { "reload-config", do_reload_config
, "Force smbd or winbindd to reload config file"},
1194 { "nodestatus", do_nodestatus
, "Ask nmbd to do a node status request"},
1195 { "online", do_winbind_online
, "Ask winbind to go into online state"},
1196 { "offline", do_winbind_offline
, "Ask winbind to go into offline state"},
1197 { "onlinestatus", do_winbind_onlinestatus
, "Request winbind online status"},
1198 { "dump-event-list", do_dump_event_list
, "Dump event list"},
1199 { "validate-cache" , do_winbind_validate_cache
,
1200 "Validate winbind's credential cache" },
1201 { "dump-domain-list", do_winbind_dump_domain_list
, "Dump winbind domain list"},
1202 { "noop", do_noop
, "Do nothing" },
1206 /* Display usage information */
1208 static void usage(poptContext pc
)
1212 poptPrintHelp(pc
, stderr
, 0);
1214 fprintf(stderr
, "\n");
1215 fprintf(stderr
, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1218 fprintf(stderr
, "\n");
1219 fprintf(stderr
, "<message-type> is one of:\n");
1221 for (i
= 0; msg_types
[i
].name
; i
++)
1222 fprintf(stderr
, "\t%-30s%s\n", msg_types
[i
].name
,
1225 fprintf(stderr
, "\n");
1230 /* Return the pid number for a string destination */
1232 static struct server_id
parse_dest(const char *dest
)
1234 struct server_id result
= {-1};
1237 /* Zero is a special return value for broadcast to all processes */
1239 if (strequal(dest
, "all")) {
1240 return interpret_pid(MSG_BROADCAST_PID_STR
);
1243 /* Try self - useful for testing */
1245 if (strequal(dest
, "self")) {
1246 return procid_self();
1249 /* Fix winbind typo. */
1250 if (strequal(dest
, "winbind")) {
1254 /* Check for numeric pid number */
1255 result
= interpret_pid(dest
);
1257 /* Zero isn't valid if not "all". */
1258 if (result
.pid
&& procid_valid(&result
)) {
1262 /* Look up other destinations in pidfile directory */
1264 if ((pid
= pidfile_pid(dest
)) != 0) {
1265 return pid_to_procid(pid
);
1268 fprintf(stderr
,"Can't find pid for destination '%s'\n", dest
);
1273 /* Execute smbcontrol command */
1275 static bool do_command(struct messaging_context
*msg_ctx
,
1276 int argc
, const char **argv
)
1278 const char *dest
= argv
[0], *command
= argv
[1];
1279 struct server_id pid
;
1282 /* Check destination */
1284 pid
= parse_dest(dest
);
1285 if (!procid_valid(&pid
)) {
1291 for (i
= 0; msg_types
[i
].name
; i
++) {
1292 if (strequal(command
, msg_types
[i
].name
))
1293 return msg_types
[i
].fn(msg_ctx
, pid
,
1294 argc
- 1, argv
+ 1);
1297 fprintf(stderr
, "smbcontrol: unknown command '%s'\n", command
);
1302 static void smbcontrol_help(poptContext pc
,
1303 enum poptCallbackReason preason
,
1304 struct poptOption
* poption
,
1308 if (poption
->shortName
!= '?') {
1309 poptPrintUsage(pc
, stdout
, 0);
1317 struct poptOption help_options
[] = {
1318 { NULL
, '\0', POPT_ARG_CALLBACK
, (void *)&smbcontrol_help
, '\0',
1320 { "help", '?', 0, NULL
, '?', "Show this help message", NULL
},
1321 { "usage", '\0', 0, NULL
, 'u', "Display brief usage message", NULL
},
1327 int main(int argc
, const char **argv
)
1331 struct tevent_context
*evt_ctx
;
1332 struct messaging_context
*msg_ctx
;
1334 static struct poptOption long_options
[] = {
1336 { NULL
, '\0', POPT_ARG_INCLUDE_TABLE
, help_options
,
1337 0, "Help options:", NULL
},
1338 { "timeout", 't', POPT_ARG_INT
, &timeout
, 't',
1339 "Set timeout value in seconds", "TIMEOUT" },
1344 TALLOC_CTX
*frame
= talloc_stackframe();
1349 setup_logging(argv
[0],True
);
1351 /* Parse command line arguments using popt */
1353 pc
= poptGetContext(
1354 "smbcontrol", argc
, (const char **)argv
, long_options
, 0);
1356 poptSetOtherOptionHelp(pc
, "[OPTION...] <destination> <message-type> "
1362 while ((opt
= poptGetNextOpt(pc
)) != -1) {
1364 case 't': /* --timeout */
1367 fprintf(stderr
, "Invalid option\n");
1368 poptPrintHelp(pc
, stderr
, 0);
1373 /* We should now have the remaining command line arguments in
1374 argv. The argc parameter should have been decremented to the
1375 correct value in the above switch statement. */
1377 argv
= (const char **)poptGetArgs(pc
);
1380 while (argv
[argc
] != NULL
) {
1388 lp_load(get_dyn_CONFIGFILE(),False
,False
,False
,True
);
1390 /* Need to invert sense of return code -- samba
1391 * routines mostly return True==1 for success, but
1394 if (!(evt_ctx
= tevent_context_init(NULL
)) ||
1395 !(msg_ctx
= messaging_init(NULL
, procid_self(), evt_ctx
))) {
1396 fprintf(stderr
, "could not init messaging context\n");
1401 ret
= !do_command(msg_ctx
, argc
, argv
);