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(const struct connections_key
*key
,
267 const struct connections_data
*crec
,
270 print_stack_trace(procid_to_pid(&crec
->pid
), (int *)priv
);
275 static bool do_daemon_stack_trace(struct messaging_context
*msg_ctx
,
276 const struct server_id pid
,
277 const int argc
, const char **argv
)
283 fprintf(stderr
, "Usage: smbcontrol <dest> stacktrace\n");
287 dest
= procid_to_pid(&pid
);
290 /* It would be nice to be able to make sure that this PID is
291 * the PID of a smbd/winbind/nmbd process, not some random PID
292 * the user liked the look of. It doesn't seem like it's worth
293 * the effort at the moment, however.
295 print_stack_trace(dest
, &count
);
297 connections_forall_read(stack_trace_connection
, &count
);
303 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
305 static bool do_daemon_stack_trace(struct messaging_context
*msg_ctx
,
306 const struct server_id pid
,
307 const int argc
, const char **argv
)
310 "Daemon stack tracing is not supported on this platform\n");
314 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
316 /* Inject a fault (fatal signal) into a running smbd */
318 static bool do_inject_fault(struct messaging_context
*msg_ctx
,
319 const struct server_id pid
,
320 const int argc
, const char **argv
)
323 fprintf(stderr
, "Usage: smbcontrol <dest> inject "
324 "<bus|hup|term|internal|segv>\n");
329 fprintf(stderr
, "Fault injection is only available in "
330 "developer builds\n");
332 #else /* DEVELOPER */
336 if (strcmp(argv
[1], "bus") == 0) {
338 } else if (strcmp(argv
[1], "hup") == 0) {
340 } else if (strcmp(argv
[1], "term") == 0) {
342 } else if (strcmp(argv
[1], "segv") == 0) {
344 } else if (strcmp(argv
[1], "internal") == 0) {
345 /* Force an internal error, ie. an unclean exit. */
348 fprintf(stderr
, "Unknown signal name '%s'\n", argv
[1]);
352 return send_message(msg_ctx
, pid
, MSG_SMB_INJECT_FAULT
,
355 #endif /* DEVELOPER */
358 /* Force a browser election */
360 static bool do_election(struct messaging_context
*msg_ctx
,
361 const struct server_id pid
,
362 const int argc
, const char **argv
)
365 fprintf(stderr
, "Usage: smbcontrol <dest> force-election\n");
369 return send_message(msg_ctx
, pid
, MSG_FORCE_ELECTION
, NULL
, 0);
372 /* Ping a samba daemon process */
374 static void pong_cb(struct messaging_context
*msg
,
377 struct server_id pid
,
380 char *src_string
= procid_str(NULL
, &pid
);
381 printf("PONG from pid %s\n", src_string
);
382 TALLOC_FREE(src_string
);
386 static bool do_ping(struct messaging_context
*msg_ctx
,
387 const struct server_id pid
,
388 const int argc
, const char **argv
)
391 fprintf(stderr
, "Usage: smbcontrol <dest> ping\n");
395 /* Send a message and register our interest in a reply */
397 if (!send_message(msg_ctx
, pid
, MSG_PING
, NULL
, 0))
400 messaging_register(msg_ctx
, NULL
, MSG_PONG
, pong_cb
);
402 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
404 /* No replies were received within the timeout period */
406 if (num_replies
== 0)
407 printf("No replies received\n");
409 messaging_deregister(msg_ctx
, MSG_PONG
, NULL
);
414 /* Set profiling options */
416 static bool do_profile(struct messaging_context
*msg_ctx
,
417 const struct server_id pid
,
418 const int argc
, const char **argv
)
423 fprintf(stderr
, "Usage: smbcontrol <dest> profile "
424 "<off|count|on|flush>\n");
428 if (strcmp(argv
[1], "off") == 0) {
430 } else if (strcmp(argv
[1], "count") == 0) {
432 } else if (strcmp(argv
[1], "on") == 0) {
434 } else if (strcmp(argv
[1], "flush") == 0) {
437 fprintf(stderr
, "Unknown profile command '%s'\n", argv
[1]);
441 return send_message(msg_ctx
, pid
, MSG_PROFILE
, &v
, sizeof(int));
444 /* Return the profiling level */
446 static void profilelevel_cb(struct messaging_context
*msg_ctx
,
449 struct server_id pid
,
457 if (data
->length
!= sizeof(int)) {
458 fprintf(stderr
, "invalid message length %ld returned\n",
459 (unsigned long)data
->length
);
463 memcpy(&level
, data
->data
, sizeof(int));
476 s
= "count and time";
483 printf("Profiling %s on pid %u\n",s
,(unsigned int)procid_to_pid(&pid
));
486 static void profilelevel_rqst(struct messaging_context
*msg_ctx
,
489 struct server_id pid
,
494 /* Send back a dummy reply */
496 send_message(msg_ctx
, pid
, MSG_PROFILELEVEL
, &v
, sizeof(int));
499 static bool do_profilelevel(struct messaging_context
*msg_ctx
,
500 const struct server_id pid
,
501 const int argc
, const char **argv
)
504 fprintf(stderr
, "Usage: smbcontrol <dest> profilelevel\n");
508 /* Send a message and register our interest in a reply */
510 if (!send_message(msg_ctx
, pid
, MSG_REQ_PROFILELEVEL
, NULL
, 0))
513 messaging_register(msg_ctx
, NULL
, MSG_PROFILELEVEL
, profilelevel_cb
);
514 messaging_register(msg_ctx
, NULL
, MSG_REQ_PROFILELEVEL
,
517 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
519 /* No replies were received within the timeout period */
521 if (num_replies
== 0)
522 printf("No replies received\n");
524 messaging_deregister(msg_ctx
, MSG_PROFILE
, NULL
);
529 /* Display debug level settings */
531 static bool do_debuglevel(struct messaging_context
*msg_ctx
,
532 const struct server_id pid
,
533 const int argc
, const char **argv
)
536 fprintf(stderr
, "Usage: smbcontrol <dest> debuglevel\n");
540 /* Send a message and register our interest in a reply */
542 if (!send_message(msg_ctx
, pid
, MSG_REQ_DEBUGLEVEL
, NULL
, 0))
545 messaging_register(msg_ctx
, NULL
, MSG_DEBUGLEVEL
, print_pid_string_cb
);
547 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
549 /* No replies were received within the timeout period */
551 if (num_replies
== 0)
552 printf("No replies received\n");
554 messaging_deregister(msg_ctx
, MSG_DEBUGLEVEL
, NULL
);
559 /* Send a print notify message */
561 static bool do_printnotify(struct messaging_context
*msg_ctx
,
562 const struct server_id pid
,
563 const int argc
, const char **argv
)
567 /* Check for subcommand */
570 fprintf(stderr
, "Must specify subcommand:\n");
571 fprintf(stderr
, "\tqueuepause <printername>\n");
572 fprintf(stderr
, "\tqueueresume <printername>\n");
573 fprintf(stderr
, "\tjobpause <printername> <unix jobid>\n");
574 fprintf(stderr
, "\tjobresume <printername> <unix jobid>\n");
575 fprintf(stderr
, "\tjobdelete <printername> <unix jobid>\n");
576 fprintf(stderr
, "\tprinter <printername> <comment|port|"
577 "driver> <value>\n");
584 if (strcmp(cmd
, "queuepause") == 0) {
587 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
588 " queuepause <printername>\n");
592 notify_printer_status_byname(argv
[2], PRINTER_STATUS_PAUSED
);
596 } else if (strcmp(cmd
, "queueresume") == 0) {
599 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
600 " queuereume <printername>\n");
604 notify_printer_status_byname(argv
[2], PRINTER_STATUS_OK
);
608 } else if (strcmp(cmd
, "jobpause") == 0) {
612 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
613 " jobpause <printername> <unix-jobid>\n");
617 jobid
= atoi(argv
[3]);
619 notify_job_status_byname(
620 argv
[2], jobid
, JOB_STATUS_PAUSED
,
621 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
625 } else if (strcmp(cmd
, "jobresume") == 0) {
629 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
630 " jobpause <printername> <unix-jobid>\n");
634 jobid
= atoi(argv
[3]);
636 notify_job_status_byname(
637 argv
[2], jobid
, JOB_STATUS_QUEUED
,
638 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
642 } else if (strcmp(cmd
, "jobdelete") == 0) {
646 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
647 " jobpause <printername> <unix-jobid>\n");
651 jobid
= atoi(argv
[3]);
653 notify_job_status_byname(
654 argv
[2], jobid
, JOB_STATUS_DELETING
,
655 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
657 notify_job_status_byname(
658 argv
[2], jobid
, JOB_STATUS_DELETING
|
660 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
664 } else if (strcmp(cmd
, "printer") == 0) {
668 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify "
669 "printer <printername> <comment|port|driver> "
674 if (strcmp(argv
[3], "comment") == 0) {
675 attribute
= PRINTER_NOTIFY_FIELD_COMMENT
;
676 } else if (strcmp(argv
[3], "port") == 0) {
677 attribute
= PRINTER_NOTIFY_FIELD_PORT_NAME
;
678 } else if (strcmp(argv
[3], "driver") == 0) {
679 attribute
= PRINTER_NOTIFY_FIELD_DRIVER_NAME
;
681 fprintf(stderr
, "Invalid printer command '%s'\n",
686 notify_printer_byname(argv
[2], attribute
,
687 CONST_DISCARD(char *, argv
[4]));
692 fprintf(stderr
, "Invalid subcommand '%s'\n", cmd
);
696 print_notify_send_messages(msg_ctx
, 0);
702 static bool do_closeshare(struct messaging_context
*msg_ctx
,
703 const struct server_id pid
,
704 const int argc
, const char **argv
)
707 fprintf(stderr
, "Usage: smbcontrol <dest> close-share "
712 return send_message(msg_ctx
, pid
, MSG_SMB_FORCE_TDIS
, argv
[1],
713 strlen(argv
[1]) + 1);
716 /* force a blocking lock retry */
718 static bool do_lockretry(struct messaging_context
*msg_ctx
,
719 const struct server_id pid
,
720 const int argc
, const char **argv
)
723 fprintf(stderr
, "Usage: smbcontrol <dest> lockretry\n");
727 return send_message(msg_ctx
, pid
, MSG_SMB_UNLOCK
, NULL
, 0);
730 /* force a validation of all brl entries, including re-sends. */
732 static bool do_brl_revalidate(struct messaging_context
*msg_ctx
,
733 const struct server_id pid
,
734 const int argc
, const char **argv
)
737 fprintf(stderr
, "Usage: smbcontrol <dest> brl-revalidate\n");
741 return send_message(msg_ctx
, pid
, MSG_SMB_BRL_VALIDATE
, NULL
, 0);
744 /* Force a SAM synchronisation */
746 static bool do_samsync(struct messaging_context
*msg_ctx
,
747 const struct server_id pid
,
748 const int argc
, const char **argv
)
751 fprintf(stderr
, "Usage: smbcontrol <dest> samsync\n");
755 return send_message(msg_ctx
, pid
, MSG_SMB_SAM_SYNC
, NULL
, 0);
758 /* Force a SAM replication */
760 static bool do_samrepl(struct messaging_context
*msg_ctx
,
761 const struct server_id pid
,
762 const int argc
, const char **argv
)
765 fprintf(stderr
, "Usage: smbcontrol <dest> samrepl\n");
769 return send_message(msg_ctx
, pid
, MSG_SMB_SAM_REPL
, NULL
, 0);
772 /* Display talloc pool usage */
774 static bool do_poolusage(struct messaging_context
*msg_ctx
,
775 const struct server_id pid
,
776 const int argc
, const char **argv
)
779 fprintf(stderr
, "Usage: smbcontrol <dest> pool-usage\n");
783 messaging_register(msg_ctx
, NULL
, MSG_POOL_USAGE
, print_string_cb
);
785 /* Send a message and register our interest in a reply */
787 if (!send_message(msg_ctx
, pid
, MSG_REQ_POOL_USAGE
, NULL
, 0))
790 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
792 /* No replies were received within the timeout period */
794 if (num_replies
== 0)
795 printf("No replies received\n");
797 messaging_deregister(msg_ctx
, MSG_POOL_USAGE
, NULL
);
802 /* Perform a dmalloc mark */
804 static bool do_dmalloc_mark(struct messaging_context
*msg_ctx
,
805 const struct server_id pid
,
806 const int argc
, const char **argv
)
809 fprintf(stderr
, "Usage: smbcontrol <dest> dmalloc-mark\n");
813 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_MARK
, NULL
, 0);
816 /* Perform a dmalloc changed */
818 static bool do_dmalloc_changed(struct messaging_context
*msg_ctx
,
819 const struct server_id pid
,
820 const int argc
, const char **argv
)
823 fprintf(stderr
, "Usage: smbcontrol <dest> "
824 "dmalloc-log-changed\n");
828 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_LOG_CHANGED
,
832 /* Shutdown a server process */
834 static bool do_shutdown(struct messaging_context
*msg_ctx
,
835 const struct server_id pid
,
836 const int argc
, const char **argv
)
839 fprintf(stderr
, "Usage: smbcontrol <dest> shutdown\n");
843 return send_message(msg_ctx
, pid
, MSG_SHUTDOWN
, NULL
, 0);
846 /* Notify a driver upgrade */
848 static bool do_drvupgrade(struct messaging_context
*msg_ctx
,
849 const struct server_id pid
,
850 const int argc
, const char **argv
)
853 fprintf(stderr
, "Usage: smbcontrol <dest> drvupgrade "
858 return send_message(msg_ctx
, pid
, MSG_DEBUG
, argv
[1],
859 strlen(argv
[1]) + 1);
862 static bool do_winbind_online(struct messaging_context
*msg_ctx
,
863 const struct server_id pid
,
864 const int argc
, const char **argv
)
869 fprintf(stderr
, "Usage: smbcontrol winbindd online\n");
873 /* Remove the entry in the winbindd_cache tdb to tell a later
874 starting winbindd that we're online. */
876 tdb
= tdb_open_log(cache_path("winbindd_cache.tdb"), 0, TDB_DEFAULT
, O_RDWR
, 0600);
878 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
879 cache_path("winbindd_cache.tdb"));
883 tdb_delete_bystring(tdb
, "WINBINDD_OFFLINE");
886 return send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINE
, NULL
, 0);
889 static bool do_winbind_offline(struct messaging_context
*msg_ctx
,
890 const struct server_id pid
,
891 const int argc
, const char **argv
)
898 fprintf(stderr
, "Usage: smbcontrol winbindd offline\n");
902 /* Create an entry in the winbindd_cache tdb to tell a later
903 starting winbindd that we're offline. We may actually create
906 tdb
= tdb_open_log(cache_path("winbindd_cache.tdb"),
907 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE
,
908 TDB_DEFAULT
/* TDB_CLEAR_IF_FIRST */, O_RDWR
|O_CREAT
, 0600);
911 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
912 cache_path("winbindd_cache.tdb"));
916 /* There's a potential race condition that if a child
917 winbindd detects a domain is online at the same time
918 we're trying to tell it to go offline that it might
919 delete the record we add between us adding it and
920 sending the message. Minimize this by retrying up to
923 for (retry
= 0; retry
< 5; retry
++) {
929 SIVAL(buf
, 0, time(NULL
));
933 tdb_store_bystring(tdb
, "WINBINDD_OFFLINE", d
, TDB_INSERT
);
935 ret
= send_message(msg_ctx
, pid
, MSG_WINBIND_OFFLINE
,
938 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
939 d
= tdb_fetch_bystring( tdb
, "WINBINDD_OFFLINE" );
941 if (!d
.dptr
|| d
.dsize
!= 4) {
943 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
954 static bool do_winbind_onlinestatus(struct messaging_context
*msg_ctx
,
955 const struct server_id pid
,
956 const int argc
, const char **argv
)
958 struct server_id myid
;
960 myid
= procid_self();
963 fprintf(stderr
, "Usage: smbcontrol winbindd onlinestatus\n");
967 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_ONLINESTATUS
,
968 print_pid_string_cb
);
970 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINESTATUS
, &myid
,
974 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
976 /* No replies were received within the timeout period */
978 if (num_replies
== 0)
979 printf("No replies received\n");
981 messaging_deregister(msg_ctx
, MSG_WINBIND_ONLINESTATUS
, NULL
);
986 static bool do_dump_event_list(struct messaging_context
*msg_ctx
,
987 const struct server_id pid
,
988 const int argc
, const char **argv
)
990 struct server_id myid
;
992 myid
= procid_self();
995 fprintf(stderr
, "Usage: smbcontrol <dest> dump-event-list\n");
999 return send_message(msg_ctx
, pid
, MSG_DUMP_EVENT_LIST
, NULL
, 0);
1002 static bool do_winbind_dump_domain_list(struct messaging_context
*msg_ctx
,
1003 const struct server_id pid
,
1004 const int argc
, const char **argv
)
1006 const char *domain
= NULL
;
1008 struct server_id myid
;
1009 uint8_t *buf
= NULL
;
1012 myid
= procid_self();
1014 if (argc
< 1 || argc
> 2) {
1015 fprintf(stderr
, "Usage: smbcontrol <dest> dump_domain_list "
1022 domain_len
= strlen(argv
[1]) + 1;
1025 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1026 print_pid_string_cb
);
1028 buf_len
= sizeof(myid
)+domain_len
;
1029 buf
= SMB_MALLOC_ARRAY(uint8_t, buf_len
);
1034 memcpy(buf
, &myid
, sizeof(myid
));
1035 memcpy(&buf
[sizeof(myid
)], domain
, domain_len
);
1037 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1044 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
1046 /* No replies were received within the timeout period */
1049 if (num_replies
== 0) {
1050 printf("No replies received\n");
1053 messaging_deregister(msg_ctx
, MSG_WINBIND_DUMP_DOMAIN_LIST
, NULL
);
1058 static void winbind_validate_cache_cb(struct messaging_context
*msg
,
1061 struct server_id pid
,
1064 char *src_string
= procid_str(NULL
, &pid
);
1065 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1066 (*(data
->data
) == 0 ? "" : "NOT "), src_string
);
1067 TALLOC_FREE(src_string
);
1071 static bool do_winbind_validate_cache(struct messaging_context
*msg_ctx
,
1072 const struct server_id pid
,
1073 const int argc
, const char **argv
)
1075 struct server_id myid
= procid_self();
1078 fprintf(stderr
, "Usage: smbcontrol winbindd validate-cache\n");
1082 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_VALIDATE_CACHE
,
1083 winbind_validate_cache_cb
);
1085 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_VALIDATE_CACHE
, &myid
,
1090 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
1092 if (num_replies
== 0) {
1093 printf("No replies received\n");
1096 messaging_deregister(msg_ctx
, MSG_WINBIND_VALIDATE_CACHE
, NULL
);
1101 static bool do_reload_config(struct messaging_context
*msg_ctx
,
1102 const struct server_id pid
,
1103 const int argc
, const char **argv
)
1106 fprintf(stderr
, "Usage: smbcontrol <dest> reload-config\n");
1110 return send_message(msg_ctx
, pid
, MSG_SMB_CONF_UPDATED
, NULL
, 0);
1113 static void my_make_nmb_name( struct nmb_name
*n
, const char *name
, int type
)
1116 memset( (char *)n
, '\0', sizeof(struct nmb_name
) );
1117 fstrcpy(unix_name
, name
);
1118 strupper_m(unix_name
);
1119 push_ascii(n
->name
, unix_name
, sizeof(n
->name
), STR_TERMINATE
);
1120 n
->name_type
= (unsigned int)type
& 0xFF;
1121 push_ascii(n
->scope
, global_scope(), 64, STR_TERMINATE
);
1124 static bool do_nodestatus(struct messaging_context
*msg_ctx
,
1125 const struct server_id pid
,
1126 const int argc
, const char **argv
)
1128 struct packet_struct p
;
1131 fprintf(stderr
, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1137 p
.ip
= interpret_addr2(argv
[1]);
1139 p
.packet_type
= NMB_PACKET
;
1141 p
.packet
.nmb
.header
.name_trn_id
= 10;
1142 p
.packet
.nmb
.header
.opcode
= 0;
1143 p
.packet
.nmb
.header
.response
= False
;
1144 p
.packet
.nmb
.header
.nm_flags
.bcast
= False
;
1145 p
.packet
.nmb
.header
.nm_flags
.recursion_available
= False
;
1146 p
.packet
.nmb
.header
.nm_flags
.recursion_desired
= False
;
1147 p
.packet
.nmb
.header
.nm_flags
.trunc
= False
;
1148 p
.packet
.nmb
.header
.nm_flags
.authoritative
= False
;
1149 p
.packet
.nmb
.header
.rcode
= 0;
1150 p
.packet
.nmb
.header
.qdcount
= 1;
1151 p
.packet
.nmb
.header
.ancount
= 0;
1152 p
.packet
.nmb
.header
.nscount
= 0;
1153 p
.packet
.nmb
.header
.arcount
= 0;
1154 my_make_nmb_name(&p
.packet
.nmb
.question
.question_name
, "*", 0x00);
1155 p
.packet
.nmb
.question
.question_type
= 0x21;
1156 p
.packet
.nmb
.question
.question_class
= 0x1;
1158 return send_message(msg_ctx
, pid
, MSG_SEND_PACKET
, &p
, sizeof(p
));
1161 /* A list of message type supported */
1163 static const struct {
1164 const char *name
; /* Option name */
1165 bool (*fn
)(struct messaging_context
*msg_ctx
,
1166 const struct server_id pid
,
1167 const int argc
, const char **argv
);
1168 const char *help
; /* Short help text */
1170 { "debug", do_debug
, "Set debuglevel" },
1171 { "force-election", do_election
,
1172 "Force a browse election" },
1173 { "ping", do_ping
, "Elicit a response" },
1174 { "profile", do_profile
, "" },
1175 { "inject", do_inject_fault
,
1176 "Inject a fatal signal into a running smbd"},
1177 { "stacktrace", do_daemon_stack_trace
,
1178 "Display a stack trace of a daemon" },
1179 { "profilelevel", do_profilelevel
, "" },
1180 { "debuglevel", do_debuglevel
, "Display current debuglevels" },
1181 { "printnotify", do_printnotify
, "Send a print notify message" },
1182 { "close-share", do_closeshare
, "Forcibly disconnect a share" },
1183 { "lockretry", do_lockretry
, "Force a blocking lock retry" },
1184 { "brl-revalidate", do_brl_revalidate
, "Revalidate all brl entries" },
1185 { "samsync", do_samsync
, "Initiate SAM synchronisation" },
1186 { "samrepl", do_samrepl
, "Initiate SAM replication" },
1187 { "pool-usage", do_poolusage
, "Display talloc memory usage" },
1188 { "dmalloc-mark", do_dmalloc_mark
, "" },
1189 { "dmalloc-log-changed", do_dmalloc_changed
, "" },
1190 { "shutdown", do_shutdown
, "Shut down daemon" },
1191 { "drvupgrade", do_drvupgrade
, "Notify a printer driver has changed" },
1192 { "reload-config", do_reload_config
, "Force smbd or winbindd to reload config file"},
1193 { "nodestatus", do_nodestatus
, "Ask nmbd to do a node status request"},
1194 { "online", do_winbind_online
, "Ask winbind to go into online state"},
1195 { "offline", do_winbind_offline
, "Ask winbind to go into offline state"},
1196 { "onlinestatus", do_winbind_onlinestatus
, "Request winbind online status"},
1197 { "dump-event-list", do_dump_event_list
, "Dump event list"},
1198 { "validate-cache" , do_winbind_validate_cache
,
1199 "Validate winbind's credential cache" },
1200 { "dump-domain-list", do_winbind_dump_domain_list
, "Dump winbind domain list"},
1201 { "noop", do_noop
, "Do nothing" },
1205 /* Display usage information */
1207 static void usage(poptContext pc
)
1211 poptPrintHelp(pc
, stderr
, 0);
1213 fprintf(stderr
, "\n");
1214 fprintf(stderr
, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1217 fprintf(stderr
, "\n");
1218 fprintf(stderr
, "<message-type> is one of:\n");
1220 for (i
= 0; msg_types
[i
].name
; i
++)
1221 fprintf(stderr
, "\t%-30s%s\n", msg_types
[i
].name
,
1224 fprintf(stderr
, "\n");
1229 /* Return the pid number for a string destination */
1231 static struct server_id
parse_dest(const char *dest
)
1233 struct server_id result
= {-1};
1236 /* Zero is a special return value for broadcast to all processes */
1238 if (strequal(dest
, "all")) {
1239 return interpret_pid(MSG_BROADCAST_PID_STR
);
1242 /* Try self - useful for testing */
1244 if (strequal(dest
, "self")) {
1245 return procid_self();
1248 /* Fix winbind typo. */
1249 if (strequal(dest
, "winbind")) {
1253 /* Check for numeric pid number */
1254 result
= interpret_pid(dest
);
1256 /* Zero isn't valid if not "all". */
1257 if (result
.pid
&& procid_valid(&result
)) {
1261 /* Look up other destinations in pidfile directory */
1263 if ((pid
= pidfile_pid(dest
)) != 0) {
1264 return pid_to_procid(pid
);
1267 fprintf(stderr
,"Can't find pid for destination '%s'\n", dest
);
1272 /* Execute smbcontrol command */
1274 static bool do_command(struct messaging_context
*msg_ctx
,
1275 int argc
, const char **argv
)
1277 const char *dest
= argv
[0], *command
= argv
[1];
1278 struct server_id pid
;
1281 /* Check destination */
1283 pid
= parse_dest(dest
);
1284 if (!procid_valid(&pid
)) {
1290 for (i
= 0; msg_types
[i
].name
; i
++) {
1291 if (strequal(command
, msg_types
[i
].name
))
1292 return msg_types
[i
].fn(msg_ctx
, pid
,
1293 argc
- 1, argv
+ 1);
1296 fprintf(stderr
, "smbcontrol: unknown command '%s'\n", command
);
1301 static void smbcontrol_help(poptContext pc
,
1302 enum poptCallbackReason preason
,
1303 struct poptOption
* poption
,
1307 if (poption
->shortName
!= '?') {
1308 poptPrintUsage(pc
, stdout
, 0);
1316 struct poptOption help_options
[] = {
1317 { NULL
, '\0', POPT_ARG_CALLBACK
, (void *)&smbcontrol_help
, '\0',
1319 { "help", '?', 0, NULL
, '?', "Show this help message", NULL
},
1320 { "usage", '\0', 0, NULL
, 'u', "Display brief usage message", NULL
},
1326 int main(int argc
, const char **argv
)
1330 struct tevent_context
*evt_ctx
;
1331 struct messaging_context
*msg_ctx
;
1333 static struct poptOption long_options
[] = {
1335 { NULL
, '\0', POPT_ARG_INCLUDE_TABLE
, help_options
,
1336 0, "Help options:", NULL
},
1337 { "timeout", 't', POPT_ARG_INT
, &timeout
, 't',
1338 "Set timeout value in seconds", "TIMEOUT" },
1343 TALLOC_CTX
*frame
= talloc_stackframe();
1348 setup_logging(argv
[0],True
);
1350 /* Parse command line arguments using popt */
1352 pc
= poptGetContext(
1353 "smbcontrol", argc
, (const char **)argv
, long_options
, 0);
1355 poptSetOtherOptionHelp(pc
, "[OPTION...] <destination> <message-type> "
1361 while ((opt
= poptGetNextOpt(pc
)) != -1) {
1363 case 't': /* --timeout */
1366 fprintf(stderr
, "Invalid option\n");
1367 poptPrintHelp(pc
, stderr
, 0);
1372 /* We should now have the remaining command line arguments in
1373 argv. The argc parameter should have been decremented to the
1374 correct value in the above switch statement. */
1376 argv
= (const char **)poptGetArgs(pc
);
1379 while (argv
[argc
] != NULL
) {
1387 lp_load(get_dyn_CONFIGFILE(),False
,False
,False
,True
);
1389 /* Need to invert sense of return code -- samba
1390 * routines mostly return True==1 for success, but
1393 if (!(evt_ctx
= tevent_context_init(NULL
)) ||
1394 !(msg_ctx
= messaging_init(NULL
, procid_self(), evt_ctx
))) {
1395 fprintf(stderr
, "could not init messaging context\n");
1400 ret
= !do_command(msg_ctx
, argc
, argv
);