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 "lib/util/server_id.h"
29 #include "popt_common.h"
30 #include "librpc/gen_ndr/spoolss.h"
31 #include "nt_printing.h"
32 #include "printing/notify.h"
33 #include "libsmb/nmblib.h"
36 #include "../lib/util/pidfile.h"
38 #include "cmdline_contexts.h"
40 #ifdef HAVE_LIBUNWIND_H
41 #include <libunwind.h>
44 #ifdef HAVE_LIBUNWIND_PTRACE_H
45 #include <libunwind-ptrace.h>
48 #ifdef HAVE_SYS_PTRACE_H
49 #include <sys/ptrace.h>
52 /* Default timeout value when waiting for replies (in seconds) */
54 #define DEFAULT_TIMEOUT 10
56 static int timeout
= DEFAULT_TIMEOUT
;
57 static int num_replies
; /* Used by message callback fns */
59 /* Send a message to a destination pid. Zero means broadcast smbd. */
61 static bool send_message(struct messaging_context
*msg_ctx
,
62 struct server_id pid
, int msg_type
,
63 const void *buf
, int len
)
65 if (procid_to_pid(&pid
) != 0)
66 return NT_STATUS_IS_OK(
67 messaging_send_buf(msg_ctx
, pid
, msg_type
,
68 (const uint8_t *)buf
, len
));
70 messaging_send_all(msg_ctx
, msg_type
, buf
, len
);
75 static void smbcontrol_timeout(struct tevent_context
*event_ctx
,
76 struct tevent_timer
*te
,
80 bool *timed_out
= (bool *)private_data
;
85 /* Wait for one or more reply messages */
87 static void wait_replies(struct tevent_context
*ev_ctx
,
88 struct messaging_context
*msg_ctx
,
89 bool multiple_replies
)
91 struct tevent_timer
*te
;
92 bool timed_out
= False
;
94 te
= tevent_add_timer(ev_ctx
, NULL
,
95 timeval_current_ofs(timeout
, 0),
96 smbcontrol_timeout
, (void *)&timed_out
);
98 DEBUG(0, ("tevent_add_timer failed\n"));
104 if (num_replies
> 0 && !multiple_replies
)
106 ret
= tevent_loop_once(ev_ctx
);
113 /* Message handler callback that displays the PID and a string on stdout */
115 static void print_pid_string_cb(struct messaging_context
*msg
,
118 struct server_id pid
,
121 struct server_id_buf pidstr
;
123 printf("PID %s: %.*s", server_id_str_buf(pid
, &pidstr
),
124 (int)data
->length
, (const char *)data
->data
);
128 /* Message handler callback that displays a string on stdout */
130 static void print_string_cb(struct messaging_context
*msg
,
133 struct server_id pid
,
136 printf("%*s", (int)data
->length
, (const char *)data
->data
);
140 /* Send no message. Useful for testing. */
142 static bool do_noop(struct tevent_context
*ev_ctx
,
143 struct messaging_context
*msg_ctx
,
144 const struct server_id pid
,
145 const int argc
, const char **argv
)
148 fprintf(stderr
, "Usage: smbcontrol <dest> noop\n");
152 /* Move along, nothing to see here */
157 /* Send a debug string */
159 static bool do_debug(struct tevent_context
*ev_ctx
,
160 struct messaging_context
*msg_ctx
,
161 const struct server_id pid
,
162 const int argc
, const char **argv
)
165 fprintf(stderr
, "Usage: smbcontrol <dest> debug "
170 return send_message(msg_ctx
, pid
, MSG_DEBUG
, argv
[1],
171 strlen(argv
[1]) + 1);
175 static bool do_idmap(struct tevent_context
*ev
,
176 struct messaging_context
*msg_ctx
,
177 const struct server_id pid
,
178 const int argc
, const char **argv
)
180 static const char* usage
= "Usage: "
181 "smbcontrol <dest> idmap <cmd> [arg]\n"
183 "\tdelete \"UID <uid>\"|\"GID <gid>\"|<sid>\n"
184 "\t\tkill \"UID <uid>\"|\"GID <gid>\"|<sid>\n";
185 const char* arg
= NULL
;
194 arglen
= strlen(arg
) + 1;
197 fprintf(stderr
, "%s", usage
);
201 if (strcmp(argv
[1], "delete") == 0) {
202 msg_type
= ID_CACHE_DELETE
;
204 else if (strcmp(argv
[1], "kill") == 0) {
205 msg_type
= ID_CACHE_KILL
;
207 else if (strcmp(argv
[1], "help") == 0) {
208 fprintf(stdout
, "%s", usage
);
212 fprintf(stderr
, "%s", usage
);
216 return send_message(msg_ctx
, pid
, msg_type
, arg
, arglen
);
220 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
222 /* Return the name of a process given it's PID. This will only work on Linux,
223 * but that's probably moot since this whole stack tracing implementation is
224 * Linux-specific anyway.
226 static const char * procname(pid_t pid
, char * buf
, size_t bufsz
)
231 snprintf(path
, sizeof(path
), "/proc/%llu/cmdline",
232 (unsigned long long)pid
);
233 if ((fp
= fopen(path
, "r")) == NULL
) {
237 fgets(buf
, bufsz
, fp
);
243 static void print_stack_trace(pid_t pid
, int * count
)
246 unw_addr_space_t aspace
= NULL
;
255 if (ptrace(PTRACE_ATTACH
, pid
, NULL
, NULL
) < 0) {
257 "Failed to attach to process %llu: %s\n",
258 (unsigned long long)pid
, strerror(errno
));
262 /* Wait until the attach is complete. */
263 waitpid(pid
, NULL
, 0);
265 if (((pinfo
= _UPT_create(pid
)) == NULL
) ||
266 ((aspace
= unw_create_addr_space(&_UPT_accessors
, 0)) == NULL
)) {
267 /* Probably out of memory. */
269 "Unable to initialize stack unwind for process %llu\n",
270 (unsigned long long)pid
);
274 if ((ret
= unw_init_remote(&cursor
, aspace
, pinfo
))) {
276 "Unable to unwind stack for process %llu: %s\n",
277 (unsigned long long)pid
, unw_strerror(ret
));
285 if (procname(pid
, nbuf
, sizeof(nbuf
))) {
286 printf("Stack trace for process %llu (%s):\n",
287 (unsigned long long)pid
, nbuf
);
289 printf("Stack trace for process %llu:\n",
290 (unsigned long long)pid
);
293 while (unw_step(&cursor
) > 0) {
295 unw_get_reg(&cursor
, UNW_REG_IP
, &ip
);
296 unw_get_reg(&cursor
, UNW_REG_SP
, &sp
);
298 ret
= unw_get_proc_name(&cursor
, nbuf
, sizeof(nbuf
), &off
);
299 if (ret
!= 0 && ret
!= -UNW_ENOMEM
) {
300 snprintf(nbuf
, sizeof(nbuf
), "<unknown symbol>");
302 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
303 nbuf
, (long long)off
, (long long)ip
,
311 unw_destroy_addr_space(aspace
);
318 ptrace(PTRACE_DETACH
, pid
, NULL
, NULL
);
321 static int stack_trace_server(pid_t pid
, void *priv
)
323 print_stack_trace(pid
, (int *)priv
);
327 static bool do_daemon_stack_trace(struct tevent_context
*ev_ctx
,
328 struct messaging_context
*msg_ctx
,
329 const struct server_id pid
,
330 const int argc
, const char **argv
)
336 fprintf(stderr
, "Usage: smbcontrol <dest> stacktrace\n");
340 dest
= procid_to_pid(&pid
);
343 /* It would be nice to be able to make sure that this PID is
344 * the PID of a smbd/winbind/nmbd process, not some random PID
345 * the user liked the look of. It doesn't seem like it's worth
346 * the effort at the moment, however.
348 print_stack_trace(dest
, &count
);
350 messaging_dgm_forall(stack_trace_server
, &count
);
356 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
358 static bool do_daemon_stack_trace(struct tevent_context
*ev_ctx
,
359 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 tevent_context
*ev_ctx
,
373 struct messaging_context
*msg_ctx
,
374 const struct server_id pid
,
375 const int argc
, const char **argv
)
378 fprintf(stderr
, "Usage: smbcontrol <dest> inject "
379 "<bus|hup|term|internal|segv>\n");
383 #if !defined(DEVELOPER) && !defined(ENABLE_SELFTEST)
384 fprintf(stderr
, "Fault injection is only available in "
385 "developer and self test builds\n");
387 #else /* DEVELOPER || ENABLE_SELFTEST */
391 if (strcmp(argv
[1], "bus") == 0) {
393 } else if (strcmp(argv
[1], "hup") == 0) {
395 } else if (strcmp(argv
[1], "term") == 0) {
397 } else if (strcmp(argv
[1], "segv") == 0) {
399 } else if (strcmp(argv
[1], "internal") == 0) {
400 /* Force an internal error, ie. an unclean exit. */
403 fprintf(stderr
, "Unknown signal name '%s'\n", argv
[1]);
407 return send_message(msg_ctx
, pid
, MSG_SMB_INJECT_FAULT
,
410 #endif /* DEVELOPER || ENABLE_SELFTEST */
413 static bool do_sleep(struct tevent_context
*ev_ctx
,
414 struct messaging_context
*msg_ctx
,
415 const struct server_id pid
,
416 const int argc
, const char **argv
)
418 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
419 unsigned int seconds
;
421 const long MAX_SLEEP
= 60 * 60; /* One hour maximum sleep */
425 fprintf(stderr
, "Usage: smbcontrol <dest> sleep seconds\n");
429 #if !defined(DEVELOPER) && !defined(ENABLE_SELFTEST)
430 fprintf(stderr
, "Sleep is only available in "
431 "developer and self test builds\n");
433 #else /* DEVELOPER || ENABLE_SELFTEST */
435 input
= atol(argv
[1]);
436 if (input
< 1 || input
> MAX_SLEEP
) {
438 "Invalid duration for sleep '%s'\n"
439 "It should be at least 1 second and no more than %ld\n",
445 return send_message(msg_ctx
, pid
,
448 sizeof(unsigned int));
449 #endif /* DEVELOPER || ENABLE_SELFTEST */
452 /* Force a browser election */
454 static bool do_election(struct tevent_context
*ev_ctx
,
455 struct messaging_context
*msg_ctx
,
456 const struct server_id pid
,
457 const int argc
, const char **argv
)
460 fprintf(stderr
, "Usage: smbcontrol <dest> force-election\n");
464 return send_message(msg_ctx
, pid
, MSG_FORCE_ELECTION
, NULL
, 0);
467 /* Ping a samba daemon process */
469 static void pong_cb(struct messaging_context
*msg
,
472 struct server_id pid
,
475 struct server_id_buf src_string
;
476 printf("PONG from pid %s\n", server_id_str_buf(pid
, &src_string
));
480 static bool do_ping(struct tevent_context
*ev_ctx
,
481 struct messaging_context
*msg_ctx
,
482 const struct server_id pid
,
483 const int argc
, const char **argv
)
486 fprintf(stderr
, "Usage: smbcontrol <dest> ping\n");
490 /* Send a message and register our interest in a reply */
492 if (!send_message(msg_ctx
, pid
, MSG_PING
, NULL
, 0))
495 messaging_register(msg_ctx
, NULL
, MSG_PONG
, pong_cb
);
497 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
499 /* No replies were received within the timeout period */
501 if (num_replies
== 0)
502 printf("No replies received\n");
504 messaging_deregister(msg_ctx
, MSG_PONG
, NULL
);
509 /* Set profiling options */
511 static bool do_profile(struct tevent_context
*ev_ctx
,
512 struct messaging_context
*msg_ctx
,
513 const struct server_id pid
,
514 const int argc
, const char **argv
)
519 fprintf(stderr
, "Usage: smbcontrol <dest> profile "
520 "<off|count|on|flush>\n");
524 if (strcmp(argv
[1], "off") == 0) {
526 } else if (strcmp(argv
[1], "count") == 0) {
528 } else if (strcmp(argv
[1], "on") == 0) {
530 } else if (strcmp(argv
[1], "flush") == 0) {
533 fprintf(stderr
, "Unknown profile command '%s'\n", argv
[1]);
537 return send_message(msg_ctx
, pid
, MSG_PROFILE
, &v
, sizeof(int));
540 /* Return the profiling level */
542 static void profilelevel_cb(struct messaging_context
*msg_ctx
,
545 struct server_id pid
,
553 if (data
->length
!= sizeof(int)) {
554 fprintf(stderr
, "invalid message length %ld returned\n",
555 (unsigned long)data
->length
);
559 memcpy(&level
, data
->data
, sizeof(int));
572 s
= "count and time";
579 printf("Profiling %s on pid %u\n",s
,(unsigned int)procid_to_pid(&pid
));
582 static void profilelevel_rqst(struct messaging_context
*msg_ctx
,
585 struct server_id pid
,
590 /* Send back a dummy reply */
592 send_message(msg_ctx
, pid
, MSG_PROFILELEVEL
, &v
, sizeof(int));
595 static bool do_profilelevel(struct tevent_context
*ev_ctx
,
596 struct messaging_context
*msg_ctx
,
597 const struct server_id pid
,
598 const int argc
, const char **argv
)
601 fprintf(stderr
, "Usage: smbcontrol <dest> profilelevel\n");
605 /* Send a message and register our interest in a reply */
607 if (!send_message(msg_ctx
, pid
, MSG_REQ_PROFILELEVEL
, NULL
, 0))
610 messaging_register(msg_ctx
, NULL
, MSG_PROFILELEVEL
, profilelevel_cb
);
611 messaging_register(msg_ctx
, NULL
, MSG_REQ_PROFILELEVEL
,
614 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
616 /* No replies were received within the timeout period */
618 if (num_replies
== 0)
619 printf("No replies received\n");
621 messaging_deregister(msg_ctx
, MSG_PROFILE
, NULL
);
626 /* Display debug level settings */
628 static bool do_debuglevel(struct tevent_context
*ev_ctx
,
629 struct messaging_context
*msg_ctx
,
630 const struct server_id pid
,
631 const int argc
, const char **argv
)
634 fprintf(stderr
, "Usage: smbcontrol <dest> debuglevel\n");
638 /* Send a message and register our interest in a reply */
640 if (!send_message(msg_ctx
, pid
, MSG_REQ_DEBUGLEVEL
, NULL
, 0))
643 messaging_register(msg_ctx
, NULL
, MSG_DEBUGLEVEL
, print_pid_string_cb
);
645 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
647 /* No replies were received within the timeout period */
649 if (num_replies
== 0)
650 printf("No replies received\n");
652 messaging_deregister(msg_ctx
, MSG_DEBUGLEVEL
, NULL
);
657 /* Send a print notify message */
659 static bool do_printnotify(struct tevent_context
*ev_ctx
,
660 struct messaging_context
*msg_ctx
,
661 const struct server_id pid
,
662 const int argc
, const char **argv
)
666 /* Check for subcommand */
669 fprintf(stderr
, "Must specify subcommand:\n");
670 fprintf(stderr
, "\tqueuepause <printername>\n");
671 fprintf(stderr
, "\tqueueresume <printername>\n");
672 fprintf(stderr
, "\tjobpause <printername> <unix jobid>\n");
673 fprintf(stderr
, "\tjobresume <printername> <unix jobid>\n");
674 fprintf(stderr
, "\tjobdelete <printername> <unix jobid>\n");
675 fprintf(stderr
, "\tprinter <printername> <comment|port|"
676 "driver> <value>\n");
683 if (strcmp(cmd
, "queuepause") == 0) {
686 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
687 " queuepause <printername>\n");
691 notify_printer_status_byname(ev_ctx
, msg_ctx
, argv
[2],
692 PRINTER_STATUS_PAUSED
);
696 } else if (strcmp(cmd
, "queueresume") == 0) {
699 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
700 " queuereume <printername>\n");
704 notify_printer_status_byname(ev_ctx
, msg_ctx
, argv
[2],
709 } else if (strcmp(cmd
, "jobpause") == 0) {
713 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
714 " jobpause <printername> <unix-jobid>\n");
718 jobid
= atoi(argv
[3]);
720 notify_job_status_byname(
722 argv
[2], jobid
, JOB_STATUS_PAUSED
,
723 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
727 } else if (strcmp(cmd
, "jobresume") == 0) {
731 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
732 " jobpause <printername> <unix-jobid>\n");
736 jobid
= atoi(argv
[3]);
738 notify_job_status_byname(
740 argv
[2], jobid
, JOB_STATUS_QUEUED
,
741 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
745 } else if (strcmp(cmd
, "jobdelete") == 0) {
749 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
750 " jobpause <printername> <unix-jobid>\n");
754 jobid
= atoi(argv
[3]);
756 notify_job_status_byname(
758 argv
[2], jobid
, JOB_STATUS_DELETING
,
759 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
761 notify_job_status_byname(
763 argv
[2], jobid
, JOB_STATUS_DELETING
|
765 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
769 } else if (strcmp(cmd
, "printer") == 0) {
773 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify "
774 "printer <printername> <comment|port|driver> "
779 if (strcmp(argv
[3], "comment") == 0) {
780 attribute
= PRINTER_NOTIFY_FIELD_COMMENT
;
781 } else if (strcmp(argv
[3], "port") == 0) {
782 attribute
= PRINTER_NOTIFY_FIELD_PORT_NAME
;
783 } else if (strcmp(argv
[3], "driver") == 0) {
784 attribute
= PRINTER_NOTIFY_FIELD_DRIVER_NAME
;
786 fprintf(stderr
, "Invalid printer command '%s'\n",
791 notify_printer_byname(ev_ctx
, msg_ctx
, argv
[2], attribute
,
792 discard_const_p(char, argv
[4]));
797 fprintf(stderr
, "Invalid subcommand '%s'\n", cmd
);
801 print_notify_send_messages(msg_ctx
, 0);
807 static bool do_closeshare(struct tevent_context
*ev_ctx
,
808 struct messaging_context
*msg_ctx
,
809 const struct server_id pid
,
810 const int argc
, const char **argv
)
813 fprintf(stderr
, "Usage: smbcontrol <dest> close-share "
818 return send_message(msg_ctx
, pid
, MSG_SMB_FORCE_TDIS
, argv
[1],
819 strlen(argv
[1]) + 1);
822 /* Kill a client by IP address */
823 static bool do_kill_client_by_ip(struct tevent_context
*ev_ctx
,
824 struct messaging_context
*msg_ctx
,
825 const struct server_id pid
,
826 const int argc
, const char **argv
)
829 fprintf(stderr
, "Usage: smbcontrol <dest> kill-client-ip "
834 if (!is_ipaddress_v4(argv
[1]) && !is_ipaddress_v6(argv
[1])) {
835 fprintf(stderr
, "%s is not a valid IP address!\n", argv
[1]);
839 return send_message(msg_ctx
, pid
, MSG_SMB_KILL_CLIENT_IP
,
840 argv
[1], strlen(argv
[1]) + 1);
843 /* Tell winbindd an IP got dropped */
845 static bool do_ip_dropped(struct tevent_context
*ev_ctx
,
846 struct messaging_context
*msg_ctx
,
847 const struct server_id pid
,
848 const int argc
, const char **argv
)
851 fprintf(stderr
, "Usage: smbcontrol <dest> ip-dropped "
856 return send_message(msg_ctx
, pid
, MSG_WINBIND_IP_DROPPED
, argv
[1],
857 strlen(argv
[1]) + 1);
860 /* Display talloc pool usage */
862 static bool do_poolusage(struct tevent_context
*ev_ctx
,
863 struct messaging_context
*msg_ctx
,
864 const struct server_id pid
,
865 const int argc
, const char **argv
)
868 fprintf(stderr
, "Usage: smbcontrol <dest> pool-usage\n");
872 messaging_register(msg_ctx
, NULL
, MSG_POOL_USAGE
, print_string_cb
);
874 /* Send a message and register our interest in a reply */
876 if (!send_message(msg_ctx
, pid
, MSG_REQ_POOL_USAGE
, NULL
, 0))
879 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
881 /* No replies were received within the timeout period */
883 if (num_replies
== 0)
884 printf("No replies received\n");
886 messaging_deregister(msg_ctx
, MSG_POOL_USAGE
, NULL
);
891 /* Fetch and print the ringbuf log */
893 static void print_ringbuf_log_cb(struct messaging_context
*msg
,
896 struct server_id pid
,
899 printf("%s", (const char *)data
->data
);
903 static bool do_ringbuflog(struct tevent_context
*ev_ctx
,
904 struct messaging_context
*msg_ctx
,
905 const struct server_id pid
,
906 const int argc
, const char **argv
)
909 fprintf(stderr
, "Usage: smbcontrol <dest> ringbuf-log\n");
913 messaging_register(msg_ctx
, NULL
, MSG_RINGBUF_LOG
,
914 print_ringbuf_log_cb
);
916 /* Send a message and register our interest in a reply */
918 if (!send_message(msg_ctx
, pid
, MSG_REQ_RINGBUF_LOG
, NULL
, 0)) {
922 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
924 /* No replies were received within the timeout period */
926 if (num_replies
== 0) {
927 printf("No replies received\n");
930 messaging_deregister(msg_ctx
, MSG_RINGBUF_LOG
, NULL
);
932 return num_replies
!= 0;
935 /* Perform a dmalloc mark */
937 static bool do_dmalloc_mark(struct tevent_context
*ev_ctx
,
938 struct messaging_context
*msg_ctx
,
939 const struct server_id pid
,
940 const int argc
, const char **argv
)
943 fprintf(stderr
, "Usage: smbcontrol <dest> dmalloc-mark\n");
947 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_MARK
, NULL
, 0);
950 /* Perform a dmalloc changed */
952 static bool do_dmalloc_changed(struct tevent_context
*ev_ctx
,
953 struct messaging_context
*msg_ctx
,
954 const struct server_id pid
,
955 const int argc
, const char **argv
)
958 fprintf(stderr
, "Usage: smbcontrol <dest> "
959 "dmalloc-log-changed\n");
963 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_LOG_CHANGED
,
967 static void print_uint32_cb(struct messaging_context
*msg
, void *private_data
,
968 uint32_t msg_type
, struct server_id pid
,
971 uint32_t num_children
;
973 if (data
->length
!= sizeof(uint32_t)) {
974 printf("Invalid response: %d bytes long\n",
978 num_children
= IVAL(data
->data
, 0);
979 printf("%u children\n", (unsigned)num_children
);
984 static bool do_num_children(struct tevent_context
*ev_ctx
,
985 struct messaging_context
*msg_ctx
,
986 const struct server_id pid
,
987 const int argc
, const char **argv
)
990 fprintf(stderr
, "Usage: smbcontrol <dest> num-children\n");
994 messaging_register(msg_ctx
, NULL
, MSG_SMB_NUM_CHILDREN
,
997 /* Send a message and register our interest in a reply */
999 if (!send_message(msg_ctx
, pid
, MSG_SMB_TELL_NUM_CHILDREN
, NULL
, 0))
1002 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
1004 /* No replies were received within the timeout period */
1006 if (num_replies
== 0)
1007 printf("No replies received\n");
1009 messaging_deregister(msg_ctx
, MSG_SMB_NUM_CHILDREN
, NULL
);
1014 static bool do_msg_cleanup(struct tevent_context
*ev_ctx
,
1015 struct messaging_context
*msg_ctx
,
1016 const struct server_id pid
,
1017 const int argc
, const char **argv
)
1021 ret
= messaging_cleanup(msg_ctx
, pid
.pid
);
1023 printf("cleanup(%u) returned %s\n", (unsigned)pid
.pid
,
1024 ret
? strerror(ret
) : "ok");
1029 /* Shutdown a server process */
1031 static bool do_shutdown(struct tevent_context
*ev_ctx
,
1032 struct messaging_context
*msg_ctx
,
1033 const struct server_id pid
,
1034 const int argc
, const char **argv
)
1037 fprintf(stderr
, "Usage: smbcontrol <dest> shutdown\n");
1041 return send_message(msg_ctx
, pid
, MSG_SHUTDOWN
, NULL
, 0);
1044 /* Notify a driver upgrade */
1046 static bool do_drvupgrade(struct tevent_context
*ev_ctx
,
1047 struct messaging_context
*msg_ctx
,
1048 const struct server_id pid
,
1049 const int argc
, const char **argv
)
1052 fprintf(stderr
, "Usage: smbcontrol <dest> drvupgrade "
1057 return send_message(msg_ctx
, pid
, MSG_PRINTER_DRVUPGRADE
, argv
[1],
1058 strlen(argv
[1]) + 1);
1061 static bool do_winbind_online(struct tevent_context
*ev_ctx
,
1062 struct messaging_context
*msg_ctx
,
1063 const struct server_id pid
,
1064 const int argc
, const char **argv
)
1070 fprintf(stderr
, "Usage: smbcontrol winbindd online\n");
1074 db_path
= state_path(talloc_tos(), "winbindd_cache.tdb");
1075 if (db_path
== NULL
) {
1079 /* Remove the entry in the winbindd_cache tdb to tell a later
1080 starting winbindd that we're online. */
1082 tdb
= tdb_open_log(db_path
, 0, TDB_DEFAULT
, O_RDWR
, 0600);
1084 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
1086 TALLOC_FREE(db_path
);
1090 TALLOC_FREE(db_path
);
1091 tdb_delete_bystring(tdb
, "WINBINDD_OFFLINE");
1094 return send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINE
, NULL
, 0);
1097 static bool do_winbind_offline(struct tevent_context
*ev_ctx
,
1098 struct messaging_context
*msg_ctx
,
1099 const struct server_id pid
,
1100 const int argc
, const char **argv
)
1108 fprintf(stderr
, "Usage: smbcontrol winbindd offline\n");
1112 db_path
= state_path(talloc_tos(), "winbindd_cache.tdb");
1113 if (db_path
== NULL
) {
1117 /* Create an entry in the winbindd_cache tdb to tell a later
1118 starting winbindd that we're offline. We may actually create
1121 tdb
= tdb_open_log(db_path
,
1122 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE
,
1123 TDB_DEFAULT
|TDB_INCOMPATIBLE_HASH
/* TDB_CLEAR_IF_FIRST */,
1124 O_RDWR
|O_CREAT
, 0600);
1127 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
1129 TALLOC_FREE(db_path
);
1132 TALLOC_FREE(db_path
);
1134 /* There's a potential race condition that if a child
1135 winbindd detects a domain is online at the same time
1136 we're trying to tell it to go offline that it might
1137 delete the record we add between us adding it and
1138 sending the message. Minimize this by retrying up to
1141 for (retry
= 0; retry
< 5; retry
++) {
1143 TDB_DATA d
= { .dptr
= buf
, .dsize
= sizeof(buf
) };
1145 SIVAL(buf
, 0, time(NULL
));
1147 tdb_store_bystring(tdb
, "WINBINDD_OFFLINE", d
, TDB_INSERT
);
1149 ret
= send_message(msg_ctx
, pid
, MSG_WINBIND_OFFLINE
,
1152 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
1153 d
= tdb_fetch_bystring( tdb
, "WINBINDD_OFFLINE" );
1154 if (d
.dptr
!= NULL
&& d
.dsize
== 4) {
1160 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
1167 static bool do_winbind_onlinestatus(struct tevent_context
*ev_ctx
,
1168 struct messaging_context
*msg_ctx
,
1169 const struct server_id pid
,
1170 const int argc
, const char **argv
)
1173 fprintf(stderr
, "Usage: smbcontrol winbindd onlinestatus\n");
1177 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_ONLINESTATUS
,
1178 print_pid_string_cb
);
1180 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINESTATUS
, NULL
, 0)) {
1184 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
1186 /* No replies were received within the timeout period */
1188 if (num_replies
== 0)
1189 printf("No replies received\n");
1191 messaging_deregister(msg_ctx
, MSG_WINBIND_ONLINESTATUS
, NULL
);
1196 static bool do_winbind_dump_domain_list(struct tevent_context
*ev_ctx
,
1197 struct messaging_context
*msg_ctx
,
1198 const struct server_id pid
,
1199 const int argc
, const char **argv
)
1201 const char *domain
= NULL
;
1204 if (argc
< 1 || argc
> 2) {
1205 fprintf(stderr
, "Usage: smbcontrol <dest> dump-domain-list "
1212 domain_len
= strlen(argv
[1]) + 1;
1215 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1216 print_pid_string_cb
);
1218 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1219 domain
, domain_len
))
1224 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
1226 /* No replies were received within the timeout period */
1228 if (num_replies
== 0) {
1229 printf("No replies received\n");
1232 messaging_deregister(msg_ctx
, MSG_WINBIND_DUMP_DOMAIN_LIST
, NULL
);
1237 static bool do_msg_disconnect_dc(struct tevent_context
*ev_ctx
,
1238 struct messaging_context
*msg_ctx
,
1239 const struct server_id pid
,
1240 const int argc
, const char **argv
)
1243 fprintf(stderr
, "Usage: smbcontrol <dest> disconnect-dc\n");
1247 return send_message(msg_ctx
, pid
, MSG_WINBIND_DISCONNECT_DC
, NULL
, 0);
1250 static void winbind_validate_cache_cb(struct messaging_context
*msg
,
1253 struct server_id pid
,
1256 struct server_id_buf src_string
;
1257 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1258 (*(data
->data
) == 0 ? "" : "NOT "),
1259 server_id_str_buf(pid
, &src_string
));
1263 static bool do_winbind_validate_cache(struct tevent_context
*ev_ctx
,
1264 struct messaging_context
*msg_ctx
,
1265 const struct server_id pid
,
1266 const int argc
, const char **argv
)
1268 struct server_id myid
;
1270 myid
= messaging_server_id(msg_ctx
);
1273 fprintf(stderr
, "Usage: smbcontrol winbindd validate-cache\n");
1277 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_VALIDATE_CACHE
,
1278 winbind_validate_cache_cb
);
1280 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_VALIDATE_CACHE
, &myid
,
1285 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
1287 if (num_replies
== 0) {
1288 printf("No replies received\n");
1291 messaging_deregister(msg_ctx
, MSG_WINBIND_VALIDATE_CACHE
, NULL
);
1296 static bool do_reload_config(struct tevent_context
*ev_ctx
,
1297 struct messaging_context
*msg_ctx
,
1298 const struct server_id pid
,
1299 const int argc
, const char **argv
)
1302 fprintf(stderr
, "Usage: smbcontrol <dest> reload-config\n");
1306 return send_message(msg_ctx
, pid
, MSG_SMB_CONF_UPDATED
, NULL
, 0);
1309 static bool do_reload_printers(struct tevent_context
*ev_ctx
,
1310 struct messaging_context
*msg_ctx
,
1311 const struct server_id pid
,
1312 const int argc
, const char **argv
)
1315 fprintf(stderr
, "Usage: smbcontrol <dest> reload-printers\n");
1319 return send_message(msg_ctx
, pid
, MSG_PRINTER_PCAP
, NULL
, 0);
1322 static void my_make_nmb_name( struct nmb_name
*n
, const char *name
, int type
)
1325 memset( (char *)n
, '\0', sizeof(struct nmb_name
) );
1326 fstrcpy(unix_name
, name
);
1327 (void)strupper_m(unix_name
);
1328 push_ascii(n
->name
, unix_name
, sizeof(n
->name
), STR_TERMINATE
);
1329 n
->name_type
= (unsigned int)type
& 0xFF;
1330 push_ascii(n
->scope
, lp_netbios_scope(), 64, STR_TERMINATE
);
1333 static bool do_nodestatus(struct tevent_context
*ev_ctx
,
1334 struct messaging_context
*msg_ctx
,
1335 const struct server_id pid
,
1336 const int argc
, const char **argv
)
1338 struct packet_struct p
;
1341 fprintf(stderr
, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1347 p
.ip
= interpret_addr2(argv
[1]);
1349 p
.packet_type
= NMB_PACKET
;
1351 p
.packet
.nmb
.header
.name_trn_id
= 10;
1352 p
.packet
.nmb
.header
.opcode
= 0;
1353 p
.packet
.nmb
.header
.response
= False
;
1354 p
.packet
.nmb
.header
.nm_flags
.bcast
= False
;
1355 p
.packet
.nmb
.header
.nm_flags
.recursion_available
= False
;
1356 p
.packet
.nmb
.header
.nm_flags
.recursion_desired
= False
;
1357 p
.packet
.nmb
.header
.nm_flags
.trunc
= False
;
1358 p
.packet
.nmb
.header
.nm_flags
.authoritative
= False
;
1359 p
.packet
.nmb
.header
.rcode
= 0;
1360 p
.packet
.nmb
.header
.qdcount
= 1;
1361 p
.packet
.nmb
.header
.ancount
= 0;
1362 p
.packet
.nmb
.header
.nscount
= 0;
1363 p
.packet
.nmb
.header
.arcount
= 0;
1364 my_make_nmb_name(&p
.packet
.nmb
.question
.question_name
, "*", 0x00);
1365 p
.packet
.nmb
.question
.question_type
= 0x21;
1366 p
.packet
.nmb
.question
.question_class
= 0x1;
1368 return send_message(msg_ctx
, pid
, MSG_SEND_PACKET
, &p
, sizeof(p
));
1371 static bool do_notify_cleanup(struct tevent_context
*ev_ctx
,
1372 struct messaging_context
*msg_ctx
,
1373 const struct server_id pid
,
1374 const int argc
, const char **argv
)
1377 fprintf(stderr
, "Usage: smbcontrol smbd notify-cleanup\n");
1380 return send_message(msg_ctx
, pid
, MSG_SMB_NOTIFY_CLEANUP
, NULL
, 0);
1383 /* A list of message type supported */
1385 static const struct {
1386 const char *name
; /* Option name */
1387 bool (*fn
)(struct tevent_context
*ev_ctx
,
1388 struct messaging_context
*msg_ctx
,
1389 const struct server_id pid
,
1390 const int argc
, const char **argv
);
1391 const char *help
; /* Short help text */
1396 .help
= "Set debuglevel",
1401 .help
= "Manipulate idmap cache",
1404 .name
= "force-election",
1406 .help
= "Force a browse election",
1411 .help
= "Elicit a response",
1420 .fn
= do_inject_fault
,
1421 .help
= "Inject a fatal signal into a running smbd"},
1423 .name
= "stacktrace",
1424 .fn
= do_daemon_stack_trace
,
1425 .help
= "Display a stack trace of a daemon",
1428 .name
= "profilelevel",
1429 .fn
= do_profilelevel
,
1433 .name
= "debuglevel",
1434 .fn
= do_debuglevel
,
1435 .help
= "Display current debuglevels",
1438 .name
= "printnotify",
1439 .fn
= do_printnotify
,
1440 .help
= "Send a print notify message",
1443 .name
= "close-share",
1444 .fn
= do_closeshare
,
1445 .help
= "Forcibly disconnect a share",
1448 .name
= "kill-client-ip",
1449 .fn
= do_kill_client_by_ip
,
1450 .help
= "Forcibly disconnect a client with a specific IP address",
1453 .name
= "ip-dropped",
1454 .fn
= do_ip_dropped
,
1455 .help
= "Tell winbind that an IP got dropped",
1458 .name
= "pool-usage",
1460 .help
= "Display talloc memory usage",
1463 .name
= "ringbuf-log",
1464 .fn
= do_ringbuflog
,
1465 .help
= "Display ringbuf log",
1468 .name
= "dmalloc-mark",
1469 .fn
= do_dmalloc_mark
,
1473 .name
= "dmalloc-log-changed",
1474 .fn
= do_dmalloc_changed
,
1480 .help
= "Shut down daemon",
1483 .name
= "drvupgrade",
1484 .fn
= do_drvupgrade
,
1485 .help
= "Notify a printer driver has changed",
1488 .name
= "reload-config",
1489 .fn
= do_reload_config
,
1490 .help
= "Force smbd or winbindd to reload config file"},
1492 .name
= "reload-printers",
1493 .fn
= do_reload_printers
,
1494 .help
= "Force smbd to reload printers"},
1496 .name
= "nodestatus",
1497 .fn
= do_nodestatus
,
1498 .help
= "Ask nmbd to do a node status request"},
1501 .fn
= do_winbind_online
,
1502 .help
= "Ask winbind to go into online state"},
1505 .fn
= do_winbind_offline
,
1506 .help
= "Ask winbind to go into offline state"},
1508 .name
= "onlinestatus",
1509 .fn
= do_winbind_onlinestatus
,
1510 .help
= "Request winbind online status"},
1512 .name
= "validate-cache" ,
1513 .fn
= do_winbind_validate_cache
,
1514 .help
= "Validate winbind's credential cache",
1517 .name
= "dump-domain-list",
1518 .fn
= do_winbind_dump_domain_list
,
1519 .help
= "Dump winbind domain list"},
1521 .name
= "disconnect-dc",
1522 .fn
= do_msg_disconnect_dc
,
1525 .name
= "notify-cleanup",
1526 .fn
= do_notify_cleanup
,
1529 .name
= "num-children",
1530 .fn
= do_num_children
,
1531 .help
= "Print number of smbd child processes",
1534 .name
= "msg-cleanup",
1535 .fn
= do_msg_cleanup
,
1540 .help
= "Do nothing",
1545 .help
= "Cause the target process to sleep",
1550 /* Display usage information */
1552 static void usage(poptContext pc
)
1556 poptPrintHelp(pc
, stderr
, 0);
1558 fprintf(stderr
, "\n");
1559 fprintf(stderr
, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1562 fprintf(stderr
, "\n");
1563 fprintf(stderr
, "<message-type> is one of:\n");
1565 for (i
= 0; msg_types
[i
].name
; i
++)
1566 fprintf(stderr
, "\t%-30s%s\n", msg_types
[i
].name
,
1569 fprintf(stderr
, "\n");
1574 /* Return the pid number for a string destination */
1576 static struct server_id
parse_dest(struct messaging_context
*msg
,
1579 struct server_id result
= {
1580 .pid
= (uint64_t)-1,
1584 /* Zero is a special return value for broadcast to all processes */
1586 if (strequal(dest
, "all")) {
1587 return interpret_pid(MSG_BROADCAST_PID_STR
);
1590 /* Try self - useful for testing */
1592 if (strequal(dest
, "self")) {
1593 return messaging_server_id(msg
);
1596 /* Fix winbind typo. */
1597 if (strequal(dest
, "winbind")) {
1601 /* Check for numeric pid number */
1602 result
= interpret_pid(dest
);
1604 /* Zero isn't valid if not "all". */
1605 if (result
.pid
&& procid_valid(&result
)) {
1609 /* Look up other destinations in pidfile directory */
1611 if ((pid
= pidfile_pid(lp_pid_directory(), dest
)) != 0) {
1612 return pid_to_procid(pid
);
1615 fprintf(stderr
,"Can't find pid for destination '%s'\n", dest
);
1620 /* Execute smbcontrol command */
1622 static bool do_command(struct tevent_context
*ev_ctx
,
1623 struct messaging_context
*msg_ctx
,
1624 int argc
, const char **argv
)
1626 const char *dest
= argv
[0], *command
= argv
[1];
1627 struct server_id pid
;
1630 /* Check destination */
1632 pid
= parse_dest(msg_ctx
, dest
);
1633 if (!procid_valid(&pid
)) {
1639 for (i
= 0; msg_types
[i
].name
; i
++) {
1640 if (strequal(command
, msg_types
[i
].name
))
1641 return msg_types
[i
].fn(ev_ctx
, msg_ctx
, pid
,
1642 argc
- 1, argv
+ 1);
1645 fprintf(stderr
, "smbcontrol: unknown command '%s'\n", command
);
1650 static void smbcontrol_help(poptContext pc
,
1651 enum poptCallbackReason preason
,
1652 struct poptOption
* poption
,
1656 if (poption
->shortName
!= '?') {
1657 poptPrintUsage(pc
, stdout
, 0);
1665 struct poptOption help_options
[] = {
1666 { NULL
, '\0', POPT_ARG_CALLBACK
, (void *)&smbcontrol_help
, '\0',
1668 { "help", '?', 0, NULL
, '?', "Show this help message", NULL
},
1669 { "usage", '\0', 0, NULL
, 'u', "Display brief usage message", NULL
},
1675 int main(int argc
, const char **argv
)
1679 struct tevent_context
*evt_ctx
;
1680 struct messaging_context
*msg_ctx
;
1682 static struct poptOption long_options
[] = {
1684 { NULL
, '\0', POPT_ARG_INCLUDE_TABLE
, help_options
,
1685 0, "Help options:", NULL
},
1686 { "timeout", 't', POPT_ARG_INT
, &timeout
, 't',
1687 "Set timeout value in seconds", "TIMEOUT" },
1692 TALLOC_CTX
*frame
= talloc_stackframe();
1697 setup_logging(argv
[0], DEBUG_STDOUT
);
1698 lp_set_cmdline("log level", "0");
1700 /* Parse command line arguments using popt */
1702 pc
= poptGetContext(
1703 "smbcontrol", argc
, (const char **)argv
, long_options
, 0);
1705 poptSetOtherOptionHelp(pc
, "[OPTION...] <destination> <message-type> "
1711 while ((opt
= poptGetNextOpt(pc
)) != -1) {
1713 case 't': /* --timeout */
1716 fprintf(stderr
, "Invalid option\n");
1717 poptPrintHelp(pc
, stderr
, 0);
1722 /* We should now have the remaining command line arguments in
1723 argv. The argc parameter should have been decremented to the
1724 correct value in the above switch statement. */
1726 argv
= (const char **)poptGetArgs(pc
);
1729 while (argv
[argc
] != NULL
) {
1737 msg_ctx
= cmdline_messaging_context(get_dyn_CONFIGFILE());
1738 if (msg_ctx
== NULL
) {
1740 "Could not init messaging context, not root?\n");
1745 evt_ctx
= global_event_context();
1747 lp_load_global(get_dyn_CONFIGFILE());
1749 /* Need to invert sense of return code -- samba
1750 * routines mostly return True==1 for success, but
1753 ret
= !do_command(evt_ctx
, msg_ctx
, argc
, argv
);