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 "lib/cmdline/cmdline.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 "lib/util/server_id_db.h"
39 #include "cmdline_contexts.h"
40 #include "lib/util/string_wrappers.h"
41 #include "lib/global_contexts.h"
43 #ifdef HAVE_LIBUNWIND_H
44 #include <libunwind.h>
47 #ifdef HAVE_LIBUNWIND_PTRACE_H
48 #include <libunwind-ptrace.h>
51 #ifdef HAVE_SYS_PTRACE_H
52 #include <sys/ptrace.h>
55 /* Default timeout value when waiting for replies (in seconds) */
57 #define DEFAULT_TIMEOUT 10
59 static int timeout
= DEFAULT_TIMEOUT
;
60 static int num_replies
; /* Used by message callback fns */
62 /* Send a message to a destination pid. Zero means broadcast smbd. */
64 static bool send_message(struct messaging_context
*msg_ctx
,
65 struct server_id pid
, int msg_type
,
66 const void *buf
, int len
)
68 if (procid_to_pid(&pid
) != 0)
69 return NT_STATUS_IS_OK(
70 messaging_send_buf(msg_ctx
, pid
, msg_type
,
71 (const uint8_t *)buf
, len
));
73 messaging_send_all(msg_ctx
, msg_type
, buf
, len
);
78 static void smbcontrol_timeout(struct tevent_context
*event_ctx
,
79 struct tevent_timer
*te
,
83 bool *timed_out
= (bool *)private_data
;
88 /* Wait for one or more reply messages */
90 static void wait_replies(struct tevent_context
*ev_ctx
,
91 struct messaging_context
*msg_ctx
,
92 bool multiple_replies
)
94 struct tevent_timer
*te
;
95 bool timed_out
= False
;
97 te
= tevent_add_timer(ev_ctx
, NULL
,
98 timeval_current_ofs(timeout
, 0),
99 smbcontrol_timeout
, (void *)&timed_out
);
101 DEBUG(0, ("tevent_add_timer failed\n"));
107 if (num_replies
> 0 && !multiple_replies
)
109 ret
= tevent_loop_once(ev_ctx
);
116 /* Message handler callback that displays the PID and a string on stdout */
118 static void print_pid_string_cb(struct messaging_context
*msg
,
121 struct server_id pid
,
124 struct server_id_buf pidstr
;
126 printf("PID %s: %.*s", server_id_str_buf(pid
, &pidstr
),
127 (int)data
->length
, (const char *)data
->data
);
131 /* Send no message. Useful for testing. */
133 static bool do_noop(struct tevent_context
*ev_ctx
,
134 struct messaging_context
*msg_ctx
,
135 const struct server_id pid
,
136 const int argc
, const char **argv
)
139 fprintf(stderr
, "Usage: smbcontrol <dest> noop\n");
143 /* Move along, nothing to see here */
148 /* Send a debug string */
150 static bool do_debug(struct tevent_context
*ev_ctx
,
151 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);
166 static bool do_idmap(struct tevent_context
*ev
,
167 struct messaging_context
*msg_ctx
,
168 const struct server_id pid
,
169 const int argc
, const char **argv
)
171 static const char* usage
= "Usage: "
172 "smbcontrol <dest> idmap <cmd> [arg]\n"
174 "\tdelete \"UID <uid>\"|\"GID <gid>\"|<sid>\n"
175 "\t\tkill \"UID <uid>\"|\"GID <gid>\"|<sid>\n";
176 const char* arg
= NULL
;
185 arglen
= strlen(arg
) + 1;
188 fprintf(stderr
, "%s", usage
);
192 if (strcmp(argv
[1], "delete") == 0) {
193 msg_type
= ID_CACHE_DELETE
;
195 else if (strcmp(argv
[1], "kill") == 0) {
196 msg_type
= ID_CACHE_KILL
;
198 else if (strcmp(argv
[1], "help") == 0) {
199 fprintf(stdout
, "%s", usage
);
203 fprintf(stderr
, "%s", usage
);
207 return send_message(msg_ctx
, pid
, msg_type
, arg
, arglen
);
211 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
213 /* Return the name of a process given it's PID. This will only work on Linux,
214 * but that's probably moot since this whole stack tracing implementation is
215 * Linux-specific anyway.
217 static const char * procname(pid_t pid
, char * buf
, size_t bufsz
)
222 snprintf(path
, sizeof(path
), "/proc/%llu/cmdline",
223 (unsigned long long)pid
);
224 if ((fp
= fopen(path
, "r")) == NULL
) {
228 fgets(buf
, bufsz
, fp
);
234 static void print_stack_trace(pid_t pid
, int * count
)
237 unw_addr_space_t aspace
= NULL
;
246 if (ptrace(PTRACE_ATTACH
, pid
, NULL
, NULL
) < 0) {
248 "Failed to attach to process %llu: %s\n",
249 (unsigned long long)pid
, strerror(errno
));
253 /* Wait until the attach is complete. */
254 waitpid(pid
, NULL
, 0);
256 if (((pinfo
= _UPT_create(pid
)) == NULL
) ||
257 ((aspace
= unw_create_addr_space(&_UPT_accessors
, 0)) == NULL
)) {
258 /* Probably out of memory. */
260 "Unable to initialize stack unwind for process %llu\n",
261 (unsigned long long)pid
);
265 if ((ret
= unw_init_remote(&cursor
, aspace
, pinfo
))) {
267 "Unable to unwind stack for process %llu: %s\n",
268 (unsigned long long)pid
, unw_strerror(ret
));
276 if (procname(pid
, nbuf
, sizeof(nbuf
))) {
277 printf("Stack trace for process %llu (%s):\n",
278 (unsigned long long)pid
, nbuf
);
280 printf("Stack trace for process %llu:\n",
281 (unsigned long long)pid
);
284 while (unw_step(&cursor
) > 0) {
286 unw_get_reg(&cursor
, UNW_REG_IP
, &ip
);
287 unw_get_reg(&cursor
, UNW_REG_SP
, &sp
);
289 ret
= unw_get_proc_name(&cursor
, nbuf
, sizeof(nbuf
), &off
);
290 if (ret
!= 0 && ret
!= -UNW_ENOMEM
) {
291 snprintf(nbuf
, sizeof(nbuf
), "<unknown symbol>");
293 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
294 nbuf
, (long long)off
, (long long)ip
,
302 unw_destroy_addr_space(aspace
);
309 ptrace(PTRACE_DETACH
, pid
, NULL
, NULL
);
312 static int stack_trace_server(pid_t pid
, void *priv
)
314 print_stack_trace(pid
, (int *)priv
);
318 static bool do_daemon_stack_trace(struct tevent_context
*ev_ctx
,
319 struct messaging_context
*msg_ctx
,
320 const struct server_id pid
,
321 const int argc
, const char **argv
)
327 fprintf(stderr
, "Usage: smbcontrol <dest> stacktrace\n");
331 dest
= procid_to_pid(&pid
);
334 /* It would be nice to be able to make sure that this PID is
335 * the PID of a smbd/winbind/nmbd process, not some random PID
336 * the user liked the look of. It doesn't seem like it's worth
337 * the effort at the moment, however.
339 print_stack_trace(dest
, &count
);
341 messaging_dgm_forall(stack_trace_server
, &count
);
347 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
349 static bool do_daemon_stack_trace(struct tevent_context
*ev_ctx
,
350 struct messaging_context
*msg_ctx
,
351 const struct server_id pid
,
352 const int argc
, const char **argv
)
355 "Daemon stack tracing is not supported on this platform\n");
359 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
361 /* Inject a fault (fatal signal) into a running smbd */
363 static bool do_inject_fault(struct tevent_context
*ev_ctx
,
364 struct messaging_context
*msg_ctx
,
365 const struct server_id pid
,
366 const int argc
, const char **argv
)
369 fprintf(stderr
, "Usage: smbcontrol <dest> inject "
370 "<bus|hup|term|internal|segv>\n");
374 #if !defined(DEVELOPER) && !defined(ENABLE_SELFTEST)
375 fprintf(stderr
, "Fault injection is only available in "
376 "developer and self test builds\n");
378 #else /* DEVELOPER || ENABLE_SELFTEST */
382 if (strcmp(argv
[1], "bus") == 0) {
384 } else if (strcmp(argv
[1], "hup") == 0) {
386 } else if (strcmp(argv
[1], "term") == 0) {
388 } else if (strcmp(argv
[1], "segv") == 0) {
390 } else if (strcmp(argv
[1], "internal") == 0) {
391 /* Force an internal error, ie. an unclean exit. */
394 fprintf(stderr
, "Unknown signal name '%s'\n", argv
[1]);
398 return send_message(msg_ctx
, pid
, MSG_SMB_INJECT_FAULT
,
401 #endif /* DEVELOPER || ENABLE_SELFTEST */
404 static bool do_sleep(struct tevent_context
*ev_ctx
,
405 struct messaging_context
*msg_ctx
,
406 const struct server_id pid
,
407 const int argc
, const char **argv
)
409 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
410 unsigned int seconds
;
412 const long MAX_SLEEP
= 60 * 60; /* One hour maximum sleep */
416 fprintf(stderr
, "Usage: smbcontrol <dest> sleep seconds\n");
420 #if !defined(DEVELOPER) && !defined(ENABLE_SELFTEST)
421 fprintf(stderr
, "Sleep is only available in "
422 "developer and self test builds\n");
424 #else /* DEVELOPER || ENABLE_SELFTEST */
426 input
= atol(argv
[1]);
427 if (input
< 1 || input
> MAX_SLEEP
) {
429 "Invalid duration for sleep '%s'\n"
430 "It should be at least 1 second and no more than %ld\n",
436 return send_message(msg_ctx
, pid
,
439 sizeof(unsigned int));
440 #endif /* DEVELOPER || ENABLE_SELFTEST */
443 /* Force a browser election */
445 static bool do_election(struct tevent_context
*ev_ctx
,
446 struct messaging_context
*msg_ctx
,
447 const struct server_id pid
,
448 const int argc
, const char **argv
)
451 fprintf(stderr
, "Usage: smbcontrol <dest> force-election\n");
455 return send_message(msg_ctx
, pid
, MSG_FORCE_ELECTION
, NULL
, 0);
458 /* Ping a samba daemon process */
460 static void pong_cb(struct messaging_context
*msg
,
463 struct server_id pid
,
466 struct server_id_buf src_string
;
467 printf("PONG from pid %s\n", server_id_str_buf(pid
, &src_string
));
471 static bool do_ping(struct tevent_context
*ev_ctx
,
472 struct messaging_context
*msg_ctx
,
473 const struct server_id pid
,
474 const int argc
, const char **argv
)
477 fprintf(stderr
, "Usage: smbcontrol <dest> ping\n");
481 /* Send a message and register our interest in a reply */
483 if (!send_message(msg_ctx
, pid
, MSG_PING
, NULL
, 0))
486 messaging_register(msg_ctx
, NULL
, MSG_PONG
, pong_cb
);
488 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
490 /* No replies were received within the timeout period */
492 if (num_replies
== 0)
493 printf("No replies received\n");
495 messaging_deregister(msg_ctx
, MSG_PONG
, NULL
);
500 /* Set profiling options */
502 static bool do_profile(struct tevent_context
*ev_ctx
,
503 struct messaging_context
*msg_ctx
,
504 const struct server_id pid
,
505 const int argc
, const char **argv
)
510 fprintf(stderr
, "Usage: smbcontrol <dest> profile "
511 "<off|count|on|flush>\n");
515 if (strcmp(argv
[1], "off") == 0) {
517 } else if (strcmp(argv
[1], "count") == 0) {
519 } else if (strcmp(argv
[1], "on") == 0) {
521 } else if (strcmp(argv
[1], "flush") == 0) {
524 fprintf(stderr
, "Unknown profile command '%s'\n", argv
[1]);
528 return send_message(msg_ctx
, pid
, MSG_PROFILE
, &v
, sizeof(int));
531 /* Return the profiling level */
533 static void profilelevel_cb(struct messaging_context
*msg_ctx
,
536 struct server_id pid
,
544 if (data
->length
!= sizeof(int)) {
545 fprintf(stderr
, "invalid message length %ld returned\n",
546 (unsigned long)data
->length
);
550 memcpy(&level
, data
->data
, sizeof(int));
563 s
= "count and time";
570 printf("Profiling %s on pid %u\n",s
,(unsigned int)procid_to_pid(&pid
));
573 static void profilelevel_rqst(struct messaging_context
*msg_ctx
,
576 struct server_id pid
,
581 /* Send back a dummy reply */
583 send_message(msg_ctx
, pid
, MSG_PROFILELEVEL
, &v
, sizeof(int));
586 static bool do_profilelevel(struct tevent_context
*ev_ctx
,
587 struct messaging_context
*msg_ctx
,
588 const struct server_id pid
,
589 const int argc
, const char **argv
)
592 fprintf(stderr
, "Usage: smbcontrol <dest> profilelevel\n");
596 /* Send a message and register our interest in a reply */
598 if (!send_message(msg_ctx
, pid
, MSG_REQ_PROFILELEVEL
, NULL
, 0))
601 messaging_register(msg_ctx
, NULL
, MSG_PROFILELEVEL
, profilelevel_cb
);
602 messaging_register(msg_ctx
, NULL
, MSG_REQ_PROFILELEVEL
,
605 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
607 /* No replies were received within the timeout period */
609 if (num_replies
== 0)
610 printf("No replies received\n");
612 messaging_deregister(msg_ctx
, MSG_PROFILE
, NULL
);
617 /* Display debug level settings */
619 static bool do_debuglevel(struct tevent_context
*ev_ctx
,
620 struct messaging_context
*msg_ctx
,
621 const struct server_id pid
,
622 const int argc
, const char **argv
)
625 fprintf(stderr
, "Usage: smbcontrol <dest> debuglevel\n");
629 /* Send a message and register our interest in a reply */
631 if (!send_message(msg_ctx
, pid
, MSG_REQ_DEBUGLEVEL
, NULL
, 0))
634 messaging_register(msg_ctx
, NULL
, MSG_DEBUGLEVEL
, print_pid_string_cb
);
636 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
638 /* No replies were received within the timeout period */
640 if (num_replies
== 0)
641 printf("No replies received\n");
643 messaging_deregister(msg_ctx
, MSG_DEBUGLEVEL
, NULL
);
648 /* Send a print notify message */
650 static bool do_printnotify(struct tevent_context
*ev_ctx
,
651 struct messaging_context
*msg_ctx
,
652 const struct server_id pid
,
653 const int argc
, const char **argv
)
657 /* Check for subcommand */
660 fprintf(stderr
, "Must specify subcommand:\n");
661 fprintf(stderr
, "\tqueuepause <printername>\n");
662 fprintf(stderr
, "\tqueueresume <printername>\n");
663 fprintf(stderr
, "\tjobpause <printername> <unix jobid>\n");
664 fprintf(stderr
, "\tjobresume <printername> <unix jobid>\n");
665 fprintf(stderr
, "\tjobdelete <printername> <unix jobid>\n");
666 fprintf(stderr
, "\tprinter <printername> <comment|port|"
667 "driver> <value>\n");
674 if (strcmp(cmd
, "queuepause") == 0) {
677 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
678 " queuepause <printername>\n");
682 notify_printer_status_byname(ev_ctx
, msg_ctx
, argv
[2],
683 PRINTER_STATUS_PAUSED
);
687 } else if (strcmp(cmd
, "queueresume") == 0) {
690 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
691 " queuereume <printername>\n");
695 notify_printer_status_byname(ev_ctx
, msg_ctx
, argv
[2],
700 } else if (strcmp(cmd
, "jobpause") == 0) {
704 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
705 " jobpause <printername> <unix-jobid>\n");
709 jobid
= atoi(argv
[3]);
711 notify_job_status_byname(
713 argv
[2], jobid
, JOB_STATUS_PAUSED
,
714 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
718 } else if (strcmp(cmd
, "jobresume") == 0) {
722 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
723 " jobpause <printername> <unix-jobid>\n");
727 jobid
= atoi(argv
[3]);
729 notify_job_status_byname(
731 argv
[2], jobid
, JOB_STATUS_QUEUED
,
732 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
736 } else if (strcmp(cmd
, "jobdelete") == 0) {
740 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
741 " jobpause <printername> <unix-jobid>\n");
745 jobid
= atoi(argv
[3]);
747 notify_job_status_byname(
749 argv
[2], jobid
, JOB_STATUS_DELETING
,
750 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
752 notify_job_status_byname(
754 argv
[2], jobid
, JOB_STATUS_DELETING
|
756 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
760 } else if (strcmp(cmd
, "printer") == 0) {
764 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify "
765 "printer <printername> <comment|port|driver> "
770 if (strcmp(argv
[3], "comment") == 0) {
771 attribute
= PRINTER_NOTIFY_FIELD_COMMENT
;
772 } else if (strcmp(argv
[3], "port") == 0) {
773 attribute
= PRINTER_NOTIFY_FIELD_PORT_NAME
;
774 } else if (strcmp(argv
[3], "driver") == 0) {
775 attribute
= PRINTER_NOTIFY_FIELD_DRIVER_NAME
;
777 fprintf(stderr
, "Invalid printer command '%s'\n",
782 notify_printer_byname(ev_ctx
, msg_ctx
, argv
[2], attribute
,
783 discard_const_p(char, argv
[4]));
788 fprintf(stderr
, "Invalid subcommand '%s'\n", cmd
);
792 print_notify_send_messages(msg_ctx
, 0);
798 static bool do_closeshare(struct tevent_context
*ev_ctx
,
799 struct messaging_context
*msg_ctx
,
800 const struct server_id pid
,
801 const int argc
, const char **argv
)
804 fprintf(stderr
, "Usage: smbcontrol <dest> close-share "
809 return send_message(msg_ctx
, pid
, MSG_SMB_FORCE_TDIS
, argv
[1],
810 strlen(argv
[1]) + 1);
814 * Close a share if access denied by now
817 static bool do_close_denied_share(
818 struct tevent_context
*ev_ctx
,
819 struct messaging_context
*msg_ctx
,
820 const struct server_id pid
,
821 const int argc
, const char **argv
)
824 fprintf(stderr
, "Usage: smbcontrol <dest> close-denied-share "
832 MSG_SMB_FORCE_TDIS_DENIED
,
834 strlen(argv
[1]) + 1);
837 /* Kill a client by IP address */
838 static bool do_kill_client_by_ip(struct tevent_context
*ev_ctx
,
839 struct messaging_context
*msg_ctx
,
840 const struct server_id pid
,
841 const int argc
, const char **argv
)
844 fprintf(stderr
, "Usage: smbcontrol <dest> kill-client-ip "
849 if (!is_ipaddress_v4(argv
[1]) && !is_ipaddress_v6(argv
[1])) {
850 fprintf(stderr
, "%s is not a valid IP address!\n", argv
[1]);
854 return send_message(msg_ctx
, pid
, MSG_SMB_KILL_CLIENT_IP
,
855 argv
[1], strlen(argv
[1]) + 1);
858 /* Tell winbindd an IP got dropped */
860 static bool do_ip_dropped(struct tevent_context
*ev_ctx
,
861 struct messaging_context
*msg_ctx
,
862 const struct server_id pid
,
863 const int argc
, const char **argv
)
866 fprintf(stderr
, "Usage: smbcontrol <dest> ip-dropped "
871 return send_message(msg_ctx
, pid
, MSG_WINBIND_IP_DROPPED
, argv
[1],
872 strlen(argv
[1]) + 1);
875 /* Display talloc pool usage */
877 static bool do_poolusage(struct tevent_context
*ev_ctx
,
878 struct messaging_context
*msg_ctx
,
879 const struct server_id dst
,
880 const int argc
, const char **argv
)
882 pid_t pid
= procid_to_pid(&dst
);
886 fprintf(stderr
, "Usage: smbcontrol <dest> pool-usage\n");
891 fprintf(stderr
, "Can only send to a specific PID\n");
907 static bool do_rpc_dump_status(
908 struct tevent_context
*ev_ctx
,
909 struct messaging_context
*msg_ctx
,
910 const struct server_id dst
,
914 pid_t pid
= procid_to_pid(&dst
);
919 "Usage: smbcontrol <dest> rpc-dump-status\n");
924 fprintf(stderr
, "Can only send to a specific PID\n");
940 /* Fetch and print the ringbuf log */
942 static void print_ringbuf_log_cb(struct messaging_context
*msg
,
945 struct server_id pid
,
948 printf("%s", (const char *)data
->data
);
952 static bool do_ringbuflog(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> ringbuf-log\n");
962 messaging_register(msg_ctx
, NULL
, MSG_RINGBUF_LOG
,
963 print_ringbuf_log_cb
);
965 /* Send a message and register our interest in a reply */
967 if (!send_message(msg_ctx
, pid
, MSG_REQ_RINGBUF_LOG
, NULL
, 0)) {
971 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
973 /* No replies were received within the timeout period */
975 if (num_replies
== 0) {
976 printf("No replies received\n");
979 messaging_deregister(msg_ctx
, MSG_RINGBUF_LOG
, NULL
);
981 return num_replies
!= 0;
984 /* Perform a dmalloc mark */
986 static bool do_dmalloc_mark(struct tevent_context
*ev_ctx
,
987 struct messaging_context
*msg_ctx
,
988 const struct server_id pid
,
989 const int argc
, const char **argv
)
992 fprintf(stderr
, "Usage: smbcontrol <dest> dmalloc-mark\n");
996 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_MARK
, NULL
, 0);
999 /* Perform a dmalloc changed */
1001 static bool do_dmalloc_changed(struct tevent_context
*ev_ctx
,
1002 struct messaging_context
*msg_ctx
,
1003 const struct server_id pid
,
1004 const int argc
, const char **argv
)
1007 fprintf(stderr
, "Usage: smbcontrol <dest> "
1008 "dmalloc-log-changed\n");
1012 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_LOG_CHANGED
,
1016 static void print_uint32_cb(struct messaging_context
*msg
, void *private_data
,
1017 uint32_t msg_type
, struct server_id pid
,
1020 uint32_t num_children
;
1022 if (data
->length
!= sizeof(uint32_t)) {
1023 printf("Invalid response: %d bytes long\n",
1027 num_children
= IVAL(data
->data
, 0);
1028 printf("%u children\n", (unsigned)num_children
);
1033 static bool do_num_children(struct tevent_context
*ev_ctx
,
1034 struct messaging_context
*msg_ctx
,
1035 const struct server_id pid
,
1036 const int argc
, const char **argv
)
1039 fprintf(stderr
, "Usage: smbcontrol <dest> num-children\n");
1043 messaging_register(msg_ctx
, NULL
, MSG_SMB_NUM_CHILDREN
,
1046 /* Send a message and register our interest in a reply */
1048 if (!send_message(msg_ctx
, pid
, MSG_SMB_TELL_NUM_CHILDREN
, NULL
, 0))
1051 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
1053 /* No replies were received within the timeout period */
1055 if (num_replies
== 0)
1056 printf("No replies received\n");
1058 messaging_deregister(msg_ctx
, MSG_SMB_NUM_CHILDREN
, NULL
);
1063 static bool do_msg_cleanup(struct tevent_context
*ev_ctx
,
1064 struct messaging_context
*msg_ctx
,
1065 const struct server_id pid
,
1066 const int argc
, const char **argv
)
1070 ret
= messaging_cleanup(msg_ctx
, pid
.pid
);
1072 printf("cleanup(%u) returned %s\n", (unsigned)pid
.pid
,
1073 ret
? strerror(ret
) : "ok");
1078 /* Shutdown a server process */
1080 static bool do_shutdown(struct tevent_context
*ev_ctx
,
1081 struct messaging_context
*msg_ctx
,
1082 const struct server_id pid
,
1083 const int argc
, const char **argv
)
1086 fprintf(stderr
, "Usage: smbcontrol <dest> shutdown\n");
1090 return send_message(msg_ctx
, pid
, MSG_SHUTDOWN
, NULL
, 0);
1093 /* Notify a driver upgrade */
1095 static bool do_drvupgrade(struct tevent_context
*ev_ctx
,
1096 struct messaging_context
*msg_ctx
,
1097 const struct server_id pid
,
1098 const int argc
, const char **argv
)
1101 fprintf(stderr
, "Usage: smbcontrol <dest> drvupgrade "
1106 return send_message(msg_ctx
, pid
, MSG_PRINTER_DRVUPGRADE
, argv
[1],
1107 strlen(argv
[1]) + 1);
1110 static bool do_winbind_online(struct tevent_context
*ev_ctx
,
1111 struct messaging_context
*msg_ctx
,
1112 const struct server_id pid
,
1113 const int argc
, const char **argv
)
1119 fprintf(stderr
, "Usage: smbcontrol winbindd online\n");
1123 db_path
= state_path(talloc_tos(), "winbindd_cache.tdb");
1124 if (db_path
== NULL
) {
1128 /* Remove the entry in the winbindd_cache tdb to tell a later
1129 starting winbindd that we're online. */
1131 tdb
= tdb_open_log(db_path
, 0, TDB_DEFAULT
, O_RDWR
, 0600);
1133 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
1135 TALLOC_FREE(db_path
);
1139 TALLOC_FREE(db_path
);
1140 tdb_delete_bystring(tdb
, "WINBINDD_OFFLINE");
1143 return send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINE
, NULL
, 0);
1146 static bool do_winbind_offline(struct tevent_context
*ev_ctx
,
1147 struct messaging_context
*msg_ctx
,
1148 const struct server_id pid
,
1149 const int argc
, const char **argv
)
1157 fprintf(stderr
, "Usage: smbcontrol winbindd offline\n");
1161 db_path
= state_path(talloc_tos(), "winbindd_cache.tdb");
1162 if (db_path
== NULL
) {
1166 /* Create an entry in the winbindd_cache tdb to tell a later
1167 starting winbindd that we're offline. We may actually create
1170 tdb
= tdb_open_log(db_path
,
1171 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE
,
1172 TDB_DEFAULT
|TDB_INCOMPATIBLE_HASH
/* TDB_CLEAR_IF_FIRST */,
1173 O_RDWR
|O_CREAT
, 0600);
1176 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
1178 TALLOC_FREE(db_path
);
1181 TALLOC_FREE(db_path
);
1183 /* There's a potential race condition that if a child
1184 winbindd detects a domain is online at the same time
1185 we're trying to tell it to go offline that it might
1186 delete the record we add between us adding it and
1187 sending the message. Minimize this by retrying up to
1190 for (retry
= 0; retry
< 5; retry
++) {
1192 TDB_DATA d
= { .dptr
= buf
, .dsize
= sizeof(buf
) };
1194 SIVAL(buf
, 0, time(NULL
));
1196 tdb_store_bystring(tdb
, "WINBINDD_OFFLINE", d
, TDB_INSERT
);
1198 ret
= send_message(msg_ctx
, pid
, MSG_WINBIND_OFFLINE
,
1201 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
1202 d
= tdb_fetch_bystring( tdb
, "WINBINDD_OFFLINE" );
1203 if (d
.dptr
!= NULL
&& d
.dsize
== 4) {
1209 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
1216 static bool do_winbind_onlinestatus(struct tevent_context
*ev_ctx
,
1217 struct messaging_context
*msg_ctx
,
1218 const struct server_id pid
,
1219 const int argc
, const char **argv
)
1222 fprintf(stderr
, "Usage: smbcontrol winbindd onlinestatus\n");
1226 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_ONLINESTATUS
,
1227 print_pid_string_cb
);
1229 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINESTATUS
, NULL
, 0)) {
1233 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
1235 /* No replies were received within the timeout period */
1237 if (num_replies
== 0)
1238 printf("No replies received\n");
1240 messaging_deregister(msg_ctx
, MSG_WINBIND_ONLINESTATUS
, NULL
);
1245 static bool do_winbind_dump_domain_list(struct tevent_context
*ev_ctx
,
1246 struct messaging_context
*msg_ctx
,
1247 const struct server_id pid
,
1248 const int argc
, const char **argv
)
1250 const char *domain
= NULL
;
1253 if (argc
< 1 || argc
> 2) {
1254 fprintf(stderr
, "Usage: smbcontrol <dest> dump-domain-list "
1261 domain_len
= strlen(argv
[1]) + 1;
1264 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1265 print_pid_string_cb
);
1267 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1268 domain
, domain_len
))
1273 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
1275 /* No replies were received within the timeout period */
1277 if (num_replies
== 0) {
1278 printf("No replies received\n");
1281 messaging_deregister(msg_ctx
, MSG_WINBIND_DUMP_DOMAIN_LIST
, NULL
);
1286 static bool do_msg_disconnect_dc(struct tevent_context
*ev_ctx
,
1287 struct messaging_context
*msg_ctx
,
1288 const struct server_id pid
,
1289 const int argc
, const char **argv
)
1292 fprintf(stderr
, "Usage: smbcontrol <dest> disconnect-dc\n");
1296 return send_message(msg_ctx
, pid
, MSG_WINBIND_DISCONNECT_DC
, NULL
, 0);
1299 static void winbind_validate_cache_cb(struct messaging_context
*msg
,
1302 struct server_id pid
,
1305 struct server_id_buf src_string
;
1306 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1307 (*(data
->data
) == 0 ? "" : "NOT "),
1308 server_id_str_buf(pid
, &src_string
));
1312 static bool do_winbind_validate_cache(struct tevent_context
*ev_ctx
,
1313 struct messaging_context
*msg_ctx
,
1314 const struct server_id pid
,
1315 const int argc
, const char **argv
)
1317 struct server_id myid
;
1319 myid
= messaging_server_id(msg_ctx
);
1322 fprintf(stderr
, "Usage: smbcontrol winbindd validate-cache\n");
1326 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_VALIDATE_CACHE
,
1327 winbind_validate_cache_cb
);
1329 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_VALIDATE_CACHE
, &myid
,
1334 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
1336 if (num_replies
== 0) {
1337 printf("No replies received\n");
1340 messaging_deregister(msg_ctx
, MSG_WINBIND_VALIDATE_CACHE
, NULL
);
1345 static bool do_reload_config(struct tevent_context
*ev_ctx
,
1346 struct messaging_context
*msg_ctx
,
1347 const struct server_id pid
,
1348 const int argc
, const char **argv
)
1351 fprintf(stderr
, "Usage: smbcontrol <dest> reload-config\n");
1355 return send_message(msg_ctx
, pid
, MSG_SMB_CONF_UPDATED
, NULL
, 0);
1358 static bool do_reload_printers(struct tevent_context
*ev_ctx
,
1359 struct messaging_context
*msg_ctx
,
1360 const struct server_id pid
,
1361 const int argc
, const char **argv
)
1364 fprintf(stderr
, "Usage: smbcontrol <dest> reload-printers\n");
1368 return send_message(msg_ctx
, pid
, MSG_PRINTER_PCAP
, NULL
, 0);
1371 static void my_make_nmb_name( struct nmb_name
*n
, const char *name
, int type
)
1374 memset( (char *)n
, '\0', sizeof(struct nmb_name
) );
1375 fstrcpy(unix_name
, name
);
1376 (void)strupper_m(unix_name
);
1377 push_ascii(n
->name
, unix_name
, sizeof(n
->name
), STR_TERMINATE
);
1378 n
->name_type
= (unsigned int)type
& 0xFF;
1379 push_ascii(n
->scope
, lp_netbios_scope(), 64, STR_TERMINATE
);
1382 static bool do_nodestatus(struct tevent_context
*ev_ctx
,
1383 struct messaging_context
*msg_ctx
,
1384 const struct server_id pid
,
1385 const int argc
, const char **argv
)
1387 struct packet_struct p
;
1390 fprintf(stderr
, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1396 p
.ip
= interpret_addr2(argv
[1]);
1398 p
.packet_type
= NMB_PACKET
;
1400 p
.packet
.nmb
.header
.name_trn_id
= 10;
1401 p
.packet
.nmb
.header
.opcode
= 0;
1402 p
.packet
.nmb
.header
.response
= False
;
1403 p
.packet
.nmb
.header
.nm_flags
.bcast
= False
;
1404 p
.packet
.nmb
.header
.nm_flags
.recursion_available
= False
;
1405 p
.packet
.nmb
.header
.nm_flags
.recursion_desired
= False
;
1406 p
.packet
.nmb
.header
.nm_flags
.trunc
= False
;
1407 p
.packet
.nmb
.header
.nm_flags
.authoritative
= False
;
1408 p
.packet
.nmb
.header
.rcode
= 0;
1409 p
.packet
.nmb
.header
.qdcount
= 1;
1410 p
.packet
.nmb
.header
.ancount
= 0;
1411 p
.packet
.nmb
.header
.nscount
= 0;
1412 p
.packet
.nmb
.header
.arcount
= 0;
1413 my_make_nmb_name(&p
.packet
.nmb
.question
.question_name
, "*", 0x00);
1414 p
.packet
.nmb
.question
.question_type
= 0x21;
1415 p
.packet
.nmb
.question
.question_class
= 0x1;
1417 return send_message(msg_ctx
, pid
, MSG_SEND_PACKET
, &p
, sizeof(p
));
1420 static bool do_notify_cleanup(struct tevent_context
*ev_ctx
,
1421 struct messaging_context
*msg_ctx
,
1422 const struct server_id pid
,
1423 const int argc
, const char **argv
)
1426 fprintf(stderr
, "Usage: smbcontrol smbd notify-cleanup\n");
1429 return send_message(msg_ctx
, pid
, MSG_SMB_NOTIFY_CLEANUP
, NULL
, 0);
1432 /* A list of message type supported */
1434 static const struct {
1435 const char *name
; /* Option name */
1436 bool (*fn
)(struct tevent_context
*ev_ctx
,
1437 struct messaging_context
*msg_ctx
,
1438 const struct server_id pid
,
1439 const int argc
, const char **argv
);
1440 const char *help
; /* Short help text */
1445 .help
= "Set debuglevel",
1450 .help
= "Manipulate idmap cache",
1453 .name
= "force-election",
1455 .help
= "Force a browse election",
1460 .help
= "Elicit a response",
1469 .fn
= do_inject_fault
,
1470 .help
= "Inject a fatal signal into a running smbd"},
1472 .name
= "stacktrace",
1473 .fn
= do_daemon_stack_trace
,
1474 .help
= "Display a stack trace of a daemon",
1477 .name
= "profilelevel",
1478 .fn
= do_profilelevel
,
1482 .name
= "debuglevel",
1483 .fn
= do_debuglevel
,
1484 .help
= "Display current debuglevels",
1487 .name
= "printnotify",
1488 .fn
= do_printnotify
,
1489 .help
= "Send a print notify message",
1492 .name
= "close-share",
1493 .fn
= do_closeshare
,
1494 .help
= "Forcibly disconnect a share",
1497 .name
= "close-denied-share",
1498 .fn
= do_close_denied_share
,
1499 .help
= "Forcibly disconnect users from shares disallowed now",
1502 .name
= "kill-client-ip",
1503 .fn
= do_kill_client_by_ip
,
1504 .help
= "Forcibly disconnect a client with a specific IP address",
1507 .name
= "ip-dropped",
1508 .fn
= do_ip_dropped
,
1509 .help
= "Tell winbind that an IP got dropped",
1512 .name
= "pool-usage",
1514 .help
= "Display talloc memory usage",
1517 .name
= "rpc-dump-status",
1518 .fn
= do_rpc_dump_status
,
1519 .help
= "Display rpc status",
1522 .name
= "ringbuf-log",
1523 .fn
= do_ringbuflog
,
1524 .help
= "Display ringbuf log",
1527 .name
= "dmalloc-mark",
1528 .fn
= do_dmalloc_mark
,
1532 .name
= "dmalloc-log-changed",
1533 .fn
= do_dmalloc_changed
,
1539 .help
= "Shut down daemon",
1542 .name
= "drvupgrade",
1543 .fn
= do_drvupgrade
,
1544 .help
= "Notify a printer driver has changed",
1547 .name
= "reload-config",
1548 .fn
= do_reload_config
,
1549 .help
= "Force smbd or winbindd to reload config file"},
1551 .name
= "reload-printers",
1552 .fn
= do_reload_printers
,
1553 .help
= "Force smbd to reload printers"},
1555 .name
= "nodestatus",
1556 .fn
= do_nodestatus
,
1557 .help
= "Ask nmbd to do a node status request"},
1560 .fn
= do_winbind_online
,
1561 .help
= "Ask winbind to go into online state"},
1564 .fn
= do_winbind_offline
,
1565 .help
= "Ask winbind to go into offline state"},
1567 .name
= "onlinestatus",
1568 .fn
= do_winbind_onlinestatus
,
1569 .help
= "Request winbind online status"},
1571 .name
= "validate-cache" ,
1572 .fn
= do_winbind_validate_cache
,
1573 .help
= "Validate winbind's credential cache",
1576 .name
= "dump-domain-list",
1577 .fn
= do_winbind_dump_domain_list
,
1578 .help
= "Dump winbind domain list"},
1580 .name
= "disconnect-dc",
1581 .fn
= do_msg_disconnect_dc
,
1584 .name
= "notify-cleanup",
1585 .fn
= do_notify_cleanup
,
1588 .name
= "num-children",
1589 .fn
= do_num_children
,
1590 .help
= "Print number of smbd child processes",
1593 .name
= "msg-cleanup",
1594 .fn
= do_msg_cleanup
,
1599 .help
= "Do nothing",
1604 .help
= "Cause the target process to sleep",
1609 /* Display usage information */
1611 static void usage(poptContext pc
)
1615 poptPrintHelp(pc
, stderr
, 0);
1617 fprintf(stderr
, "\n");
1618 fprintf(stderr
, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1621 fprintf(stderr
, "\n");
1622 fprintf(stderr
, "<message-type> is one of:\n");
1624 for (i
= 0; msg_types
[i
].name
; i
++) {
1625 const char *help
= msg_types
[i
].help
;
1629 fprintf(stderr
, "\t%-30s%s\n", msg_types
[i
].name
, help
);
1632 fprintf(stderr
, "\n");
1637 /* Return the pid number for a string destination */
1639 static struct server_id
parse_dest(struct messaging_context
*msg
,
1642 struct server_id result
= {
1643 .pid
= (uint64_t)-1,
1646 struct server_id_db
*names_db
= NULL
;
1649 /* Zero is a special return value for broadcast to all processes */
1651 if (strequal(dest
, "all")) {
1652 return interpret_pid(MSG_BROADCAST_PID_STR
);
1655 /* Try self - useful for testing */
1657 if (strequal(dest
, "self")) {
1658 return messaging_server_id(msg
);
1661 /* Fix winbind typo. */
1662 if (strequal(dest
, "winbind")) {
1666 /* Check for numeric pid number */
1667 result
= interpret_pid(dest
);
1669 /* Zero isn't valid if not "all". */
1670 if (result
.pid
&& procid_valid(&result
)) {
1674 /* Look up other destinations in pidfile directory */
1676 if ((pid
= pidfile_pid(lp_pid_directory(), dest
)) != 0) {
1677 return pid_to_procid(pid
);
1680 names_db
= messaging_names_db(msg
);
1681 if (names_db
== NULL
) {
1684 ok
= server_id_db_lookup_one(names_db
, dest
, &result
);
1690 fprintf(stderr
,"Can't find pid for destination '%s'\n", dest
);
1695 /* Execute smbcontrol command */
1697 static bool do_command(struct tevent_context
*ev_ctx
,
1698 struct messaging_context
*msg_ctx
,
1699 int argc
, const char **argv
)
1701 const char *dest
= argv
[0], *command
= argv
[1];
1702 struct server_id pid
;
1705 /* Check destination */
1707 pid
= parse_dest(msg_ctx
, dest
);
1708 if (!procid_valid(&pid
)) {
1714 for (i
= 0; msg_types
[i
].name
; i
++) {
1715 if (strequal(command
, msg_types
[i
].name
))
1716 return msg_types
[i
].fn(ev_ctx
, msg_ctx
, pid
,
1717 argc
- 1, argv
+ 1);
1720 fprintf(stderr
, "smbcontrol: unknown command '%s'\n", command
);
1725 static void smbcontrol_help(poptContext pc
,
1726 enum poptCallbackReason preason
,
1727 struct poptOption
* poption
,
1731 if (poption
->shortName
!= '?') {
1732 poptPrintUsage(pc
, stdout
, 0);
1740 struct poptOption help_options
[] = {
1741 { NULL
, '\0', POPT_ARG_CALLBACK
, (void *)&smbcontrol_help
, '\0',
1743 { "help", '?', 0, NULL
, '?', "Show this help message", NULL
},
1744 { "usage", '\0', 0, NULL
, 'u', "Display brief usage message", NULL
},
1750 int main(int argc
, const char **argv
)
1754 struct tevent_context
*evt_ctx
;
1755 struct messaging_context
*msg_ctx
;
1757 struct poptOption long_options
[] = {
1759 { NULL
, '\0', POPT_ARG_INCLUDE_TABLE
, help_options
,
1760 0, "Help options:", NULL
},
1761 { "timeout", 't', POPT_ARG_INT
, &timeout
, 't',
1762 "Set timeout value in seconds", "TIMEOUT" },
1768 TALLOC_CTX
*frame
= talloc_stackframe();
1774 ok
= samba_cmdline_init(frame
,
1775 SAMBA_CMDLINE_CONFIG_CLIENT
,
1776 false /* require_smbconf */);
1778 DBG_ERR("Failed to init cmdline parser!\n");
1782 lp_set_cmdline("log level", "0");
1784 /* Parse command line arguments using popt */
1786 pc
= samba_popt_get_context(getprogname(),
1792 DBG_ERR("Failed to setup popt context!\n");
1797 poptSetOtherOptionHelp(pc
, "[OPTION...] <destination> <message-type> "
1803 while ((opt
= poptGetNextOpt(pc
)) != -1) {
1805 case 't': /* --timeout */
1808 fprintf(stderr
, "Invalid option\n");
1809 poptPrintHelp(pc
, stderr
, 0);
1814 /* We should now have the remaining command line arguments in
1815 argv. The argc parameter should have been decremented to the
1816 correct value in the above switch statement. */
1818 argv
= (const char **)poptGetArgs(pc
);
1821 while (argv
[argc
] != NULL
) {
1829 msg_ctx
= cmdline_messaging_context(get_dyn_CONFIGFILE());
1830 if (msg_ctx
== NULL
) {
1832 "Could not init messaging context, not root?\n");
1837 evt_ctx
= global_event_context();
1839 /* Need to invert sense of return code -- samba
1840 * routines mostly return True==1 for success, but
1843 ret
= !do_command(evt_ctx
, msg_ctx
, argc
, argv
);
1845 cmdline_messaging_context_free();
1846 poptFreeContext(pc
);