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"
40 #include <libunwind.h>
43 #if HAVE_LIBUNWIND_PTRACE_H
44 #include <libunwind-ptrace.h>
48 #include <sys/ptrace.h>
51 /* Default timeout value when waiting for replies (in seconds) */
53 #define DEFAULT_TIMEOUT 10
55 static int timeout
= DEFAULT_TIMEOUT
;
56 static int num_replies
; /* Used by message callback fns */
58 /* Send a message to a destination pid. Zero means broadcast smbd. */
60 static bool send_message(struct messaging_context
*msg_ctx
,
61 struct server_id pid
, int msg_type
,
62 const void *buf
, int len
)
67 if (procid_to_pid(&pid
) != 0)
68 return NT_STATUS_IS_OK(
69 messaging_send_buf(msg_ctx
, pid
, msg_type
,
70 (const uint8_t *)buf
, len
));
72 ret
= message_send_all(msg_ctx
, msg_type
, buf
, len
, &n_sent
);
73 DEBUG(10,("smbcontrol/send_message: broadcast message to "
74 "%d processes\n", n_sent
));
79 static void smbcontrol_timeout(struct tevent_context
*event_ctx
,
80 struct tevent_timer
*te
,
84 bool *timed_out
= (bool *)private_data
;
89 /* Wait for one or more reply messages */
91 static void wait_replies(struct tevent_context
*ev_ctx
,
92 struct messaging_context
*msg_ctx
,
93 bool multiple_replies
)
95 struct tevent_timer
*te
;
96 bool timed_out
= False
;
98 te
= tevent_add_timer(ev_ctx
, NULL
,
99 timeval_current_ofs(timeout
, 0),
100 smbcontrol_timeout
, (void *)&timed_out
);
102 DEBUG(0, ("tevent_add_timer failed\n"));
108 if (num_replies
> 0 && !multiple_replies
)
110 ret
= tevent_loop_once(ev_ctx
);
117 /* Message handler callback that displays the PID and a string on stdout */
119 static void print_pid_string_cb(struct messaging_context
*msg
,
122 struct server_id pid
,
125 struct server_id_buf pidstr
;
127 printf("PID %s: %.*s", server_id_str_buf(pid
, &pidstr
),
128 (int)data
->length
, (const char *)data
->data
);
132 /* Message handler callback that displays a string on stdout */
134 static void print_string_cb(struct messaging_context
*msg
,
137 struct server_id pid
,
140 printf("%*s", (int)data
->length
, (const char *)data
->data
);
144 /* Send no message. Useful for testing. */
146 static bool do_noop(struct tevent_context
*ev_ctx
,
147 struct messaging_context
*msg_ctx
,
148 const struct server_id pid
,
149 const int argc
, const char **argv
)
152 fprintf(stderr
, "Usage: smbcontrol <dest> noop\n");
156 /* Move along, nothing to see here */
161 /* Send a debug string */
163 static bool do_debug(struct tevent_context
*ev_ctx
,
164 struct messaging_context
*msg_ctx
,
165 const struct server_id pid
,
166 const int argc
, const char **argv
)
169 fprintf(stderr
, "Usage: smbcontrol <dest> debug "
174 return send_message(msg_ctx
, pid
, MSG_DEBUG
, argv
[1],
175 strlen(argv
[1]) + 1);
179 static bool do_idmap(struct tevent_context
*ev
,
180 struct messaging_context
*msg_ctx
,
181 const struct server_id pid
,
182 const int argc
, const char **argv
)
184 static const char* usage
= "Usage: "
185 "smbcontrol <dest> idmap <cmd> [arg]\n"
187 "\tdelete \"UID <uid>\"|\"GID <gid>\"|<sid>\n"
188 "\t\tkill \"UID <uid>\"|\"GID <gid>\"|<sid>\n";
189 const char* arg
= NULL
;
198 arglen
= strlen(arg
) + 1;
201 fprintf(stderr
, "%s", usage
);
205 if (strcmp(argv
[1], "delete") == 0) {
206 msg_type
= ID_CACHE_DELETE
;
208 else if (strcmp(argv
[1], "kill") == 0) {
209 msg_type
= ID_CACHE_KILL
;
211 else if (strcmp(argv
[1], "help") == 0) {
212 fprintf(stdout
, "%s", usage
);
216 fprintf(stderr
, "%s", usage
);
220 return send_message(msg_ctx
, pid
, msg_type
, arg
, arglen
);
224 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
226 /* Return the name of a process given it's PID. This will only work on Linux,
227 * but that's probably moot since this whole stack tracing implementation is
228 * Linux-specific anyway.
230 static const char * procname(pid_t pid
, char * buf
, size_t bufsz
)
235 snprintf(path
, sizeof(path
), "/proc/%llu/cmdline",
236 (unsigned long long)pid
);
237 if ((fp
= fopen(path
, "r")) == NULL
) {
241 fgets(buf
, bufsz
, fp
);
247 static void print_stack_trace(pid_t pid
, int * count
)
250 unw_addr_space_t aspace
= NULL
;
259 if (ptrace(PTRACE_ATTACH
, pid
, NULL
, NULL
) < 0) {
261 "Failed to attach to process %llu: %s\n",
262 (unsigned long long)pid
, strerror(errno
));
266 /* Wait until the attach is complete. */
267 waitpid(pid
, NULL
, 0);
269 if (((pinfo
= _UPT_create(pid
)) == NULL
) ||
270 ((aspace
= unw_create_addr_space(&_UPT_accessors
, 0)) == NULL
)) {
271 /* Probably out of memory. */
273 "Unable to initialize stack unwind for process %llu\n",
274 (unsigned long long)pid
);
278 if ((ret
= unw_init_remote(&cursor
, aspace
, pinfo
))) {
280 "Unable to unwind stack for process %llu: %s\n",
281 (unsigned long long)pid
, unw_strerror(ret
));
289 if (procname(pid
, nbuf
, sizeof(nbuf
))) {
290 printf("Stack trace for process %llu (%s):\n",
291 (unsigned long long)pid
, nbuf
);
293 printf("Stack trace for process %llu:\n",
294 (unsigned long long)pid
);
297 while (unw_step(&cursor
) > 0) {
299 unw_get_reg(&cursor
, UNW_REG_IP
, &ip
);
300 unw_get_reg(&cursor
, UNW_REG_SP
, &sp
);
302 ret
= unw_get_proc_name(&cursor
, nbuf
, sizeof(nbuf
), &off
);
303 if (ret
!= 0 && ret
!= -UNW_ENOMEM
) {
304 snprintf(nbuf
, sizeof(nbuf
), "<unknown symbol>");
306 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
307 nbuf
, (long long)off
, (long long)ip
,
315 unw_destroy_addr_space(aspace
);
322 ptrace(PTRACE_DETACH
, pid
, NULL
, NULL
);
325 static int stack_trace_server(const struct server_id
*id
,
329 if (procid_is_local(id
)) {
330 print_stack_trace(procid_to_pid(id
), (int *)priv
);
335 static bool do_daemon_stack_trace(struct tevent_context
*ev_ctx
,
336 struct messaging_context
*msg_ctx
,
337 const struct server_id pid
,
338 const int argc
, const char **argv
)
344 fprintf(stderr
, "Usage: smbcontrol <dest> stacktrace\n");
348 dest
= procid_to_pid(&pid
);
351 /* It would be nice to be able to make sure that this PID is
352 * the PID of a smbd/winbind/nmbd process, not some random PID
353 * the user liked the look of. It doesn't seem like it's worth
354 * the effort at the moment, however.
356 print_stack_trace(dest
, &count
);
358 serverid_traverse_read(stack_trace_server
, &count
);
364 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
366 static bool do_daemon_stack_trace(struct tevent_context
*ev_ctx
,
367 struct messaging_context
*msg_ctx
,
368 const struct server_id pid
,
369 const int argc
, const char **argv
)
372 "Daemon stack tracing is not supported on this platform\n");
376 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
378 /* Inject a fault (fatal signal) into a running smbd */
380 static bool do_inject_fault(struct tevent_context
*ev_ctx
,
381 struct messaging_context
*msg_ctx
,
382 const struct server_id pid
,
383 const int argc
, const char **argv
)
386 fprintf(stderr
, "Usage: smbcontrol <dest> inject "
387 "<bus|hup|term|internal|segv>\n");
392 fprintf(stderr
, "Fault injection is only available in "
393 "developer builds\n");
395 #else /* DEVELOPER */
399 if (strcmp(argv
[1], "bus") == 0) {
401 } else if (strcmp(argv
[1], "hup") == 0) {
403 } else if (strcmp(argv
[1], "term") == 0) {
405 } else if (strcmp(argv
[1], "segv") == 0) {
407 } else if (strcmp(argv
[1], "internal") == 0) {
408 /* Force an internal error, ie. an unclean exit. */
411 fprintf(stderr
, "Unknown signal name '%s'\n", argv
[1]);
415 return send_message(msg_ctx
, pid
, MSG_SMB_INJECT_FAULT
,
418 #endif /* DEVELOPER */
421 /* Force a browser election */
423 static bool do_election(struct tevent_context
*ev_ctx
,
424 struct messaging_context
*msg_ctx
,
425 const struct server_id pid
,
426 const int argc
, const char **argv
)
429 fprintf(stderr
, "Usage: smbcontrol <dest> force-election\n");
433 return send_message(msg_ctx
, pid
, MSG_FORCE_ELECTION
, NULL
, 0);
436 /* Ping a samba daemon process */
438 static void pong_cb(struct messaging_context
*msg
,
441 struct server_id pid
,
444 struct server_id_buf src_string
;
445 printf("PONG from pid %s\n", server_id_str_buf(pid
, &src_string
));
449 static bool do_ping(struct tevent_context
*ev_ctx
,
450 struct messaging_context
*msg_ctx
,
451 const struct server_id pid
,
452 const int argc
, const char **argv
)
455 fprintf(stderr
, "Usage: smbcontrol <dest> ping\n");
459 /* Send a message and register our interest in a reply */
461 if (!send_message(msg_ctx
, pid
, MSG_PING
, NULL
, 0))
464 messaging_register(msg_ctx
, NULL
, MSG_PONG
, pong_cb
);
466 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
468 /* No replies were received within the timeout period */
470 if (num_replies
== 0)
471 printf("No replies received\n");
473 messaging_deregister(msg_ctx
, MSG_PONG
, NULL
);
478 /* Set profiling options */
480 static bool do_profile(struct tevent_context
*ev_ctx
,
481 struct messaging_context
*msg_ctx
,
482 const struct server_id pid
,
483 const int argc
, const char **argv
)
488 fprintf(stderr
, "Usage: smbcontrol <dest> profile "
489 "<off|count|on|flush>\n");
493 if (strcmp(argv
[1], "off") == 0) {
495 } else if (strcmp(argv
[1], "count") == 0) {
497 } else if (strcmp(argv
[1], "on") == 0) {
499 } else if (strcmp(argv
[1], "flush") == 0) {
502 fprintf(stderr
, "Unknown profile command '%s'\n", argv
[1]);
506 return send_message(msg_ctx
, pid
, MSG_PROFILE
, &v
, sizeof(int));
509 /* Return the profiling level */
511 static void profilelevel_cb(struct messaging_context
*msg_ctx
,
514 struct server_id pid
,
522 if (data
->length
!= sizeof(int)) {
523 fprintf(stderr
, "invalid message length %ld returned\n",
524 (unsigned long)data
->length
);
528 memcpy(&level
, data
->data
, sizeof(int));
541 s
= "count and time";
548 printf("Profiling %s on pid %u\n",s
,(unsigned int)procid_to_pid(&pid
));
551 static void profilelevel_rqst(struct messaging_context
*msg_ctx
,
554 struct server_id pid
,
559 /* Send back a dummy reply */
561 send_message(msg_ctx
, pid
, MSG_PROFILELEVEL
, &v
, sizeof(int));
564 static bool do_profilelevel(struct tevent_context
*ev_ctx
,
565 struct messaging_context
*msg_ctx
,
566 const struct server_id pid
,
567 const int argc
, const char **argv
)
570 fprintf(stderr
, "Usage: smbcontrol <dest> profilelevel\n");
574 /* Send a message and register our interest in a reply */
576 if (!send_message(msg_ctx
, pid
, MSG_REQ_PROFILELEVEL
, NULL
, 0))
579 messaging_register(msg_ctx
, NULL
, MSG_PROFILELEVEL
, profilelevel_cb
);
580 messaging_register(msg_ctx
, NULL
, MSG_REQ_PROFILELEVEL
,
583 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
585 /* No replies were received within the timeout period */
587 if (num_replies
== 0)
588 printf("No replies received\n");
590 messaging_deregister(msg_ctx
, MSG_PROFILE
, NULL
);
595 /* Display debug level settings */
597 static bool do_debuglevel(struct tevent_context
*ev_ctx
,
598 struct messaging_context
*msg_ctx
,
599 const struct server_id pid
,
600 const int argc
, const char **argv
)
603 fprintf(stderr
, "Usage: smbcontrol <dest> debuglevel\n");
607 /* Send a message and register our interest in a reply */
609 if (!send_message(msg_ctx
, pid
, MSG_REQ_DEBUGLEVEL
, NULL
, 0))
612 messaging_register(msg_ctx
, NULL
, MSG_DEBUGLEVEL
, print_pid_string_cb
);
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_DEBUGLEVEL
, NULL
);
626 /* Send a print notify message */
628 static bool do_printnotify(struct tevent_context
*ev_ctx
,
629 struct messaging_context
*msg_ctx
,
630 const struct server_id pid
,
631 const int argc
, const char **argv
)
635 /* Check for subcommand */
638 fprintf(stderr
, "Must specify subcommand:\n");
639 fprintf(stderr
, "\tqueuepause <printername>\n");
640 fprintf(stderr
, "\tqueueresume <printername>\n");
641 fprintf(stderr
, "\tjobpause <printername> <unix jobid>\n");
642 fprintf(stderr
, "\tjobresume <printername> <unix jobid>\n");
643 fprintf(stderr
, "\tjobdelete <printername> <unix jobid>\n");
644 fprintf(stderr
, "\tprinter <printername> <comment|port|"
645 "driver> <value>\n");
652 if (strcmp(cmd
, "queuepause") == 0) {
655 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
656 " queuepause <printername>\n");
660 notify_printer_status_byname(ev_ctx
, msg_ctx
, argv
[2],
661 PRINTER_STATUS_PAUSED
);
665 } else if (strcmp(cmd
, "queueresume") == 0) {
668 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
669 " queuereume <printername>\n");
673 notify_printer_status_byname(ev_ctx
, msg_ctx
, argv
[2],
678 } else if (strcmp(cmd
, "jobpause") == 0) {
682 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
683 " jobpause <printername> <unix-jobid>\n");
687 jobid
= atoi(argv
[3]);
689 notify_job_status_byname(
691 argv
[2], jobid
, JOB_STATUS_PAUSED
,
692 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
696 } else if (strcmp(cmd
, "jobresume") == 0) {
700 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
701 " jobpause <printername> <unix-jobid>\n");
705 jobid
= atoi(argv
[3]);
707 notify_job_status_byname(
709 argv
[2], jobid
, JOB_STATUS_QUEUED
,
710 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
714 } else if (strcmp(cmd
, "jobdelete") == 0) {
718 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
719 " jobpause <printername> <unix-jobid>\n");
723 jobid
= atoi(argv
[3]);
725 notify_job_status_byname(
727 argv
[2], jobid
, JOB_STATUS_DELETING
,
728 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
730 notify_job_status_byname(
732 argv
[2], jobid
, JOB_STATUS_DELETING
|
734 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
738 } else if (strcmp(cmd
, "printer") == 0) {
742 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify "
743 "printer <printername> <comment|port|driver> "
748 if (strcmp(argv
[3], "comment") == 0) {
749 attribute
= PRINTER_NOTIFY_FIELD_COMMENT
;
750 } else if (strcmp(argv
[3], "port") == 0) {
751 attribute
= PRINTER_NOTIFY_FIELD_PORT_NAME
;
752 } else if (strcmp(argv
[3], "driver") == 0) {
753 attribute
= PRINTER_NOTIFY_FIELD_DRIVER_NAME
;
755 fprintf(stderr
, "Invalid printer command '%s'\n",
760 notify_printer_byname(ev_ctx
, msg_ctx
, argv
[2], attribute
,
761 discard_const_p(char, argv
[4]));
766 fprintf(stderr
, "Invalid subcommand '%s'\n", cmd
);
770 print_notify_send_messages(msg_ctx
, 0);
776 static bool do_closeshare(struct tevent_context
*ev_ctx
,
777 struct messaging_context
*msg_ctx
,
778 const struct server_id pid
,
779 const int argc
, const char **argv
)
782 fprintf(stderr
, "Usage: smbcontrol <dest> close-share "
787 return send_message(msg_ctx
, pid
, MSG_SMB_FORCE_TDIS
, argv
[1],
788 strlen(argv
[1]) + 1);
791 /* Kill a client by IP address */
792 static bool do_kill_client_by_ip(struct tevent_context
*ev_ctx
,
793 struct messaging_context
*msg_ctx
,
794 const struct server_id pid
,
795 const int argc
, const char **argv
)
798 fprintf(stderr
, "Usage: smbcontrol <dest> kill-client-ip "
803 if (!is_ipaddress_v4(argv
[1]) && !is_ipaddress_v6(argv
[1])) {
804 fprintf(stderr
, "%s is not a valid IP address!\n", argv
[1]);
808 return send_message(msg_ctx
, pid
, MSG_SMB_KILL_CLIENT_IP
,
809 argv
[1], strlen(argv
[1]) + 1);
812 /* Tell winbindd an IP got dropped */
814 static bool do_ip_dropped(struct tevent_context
*ev_ctx
,
815 struct messaging_context
*msg_ctx
,
816 const struct server_id pid
,
817 const int argc
, const char **argv
)
820 fprintf(stderr
, "Usage: smbcontrol <dest> ip-dropped "
825 return send_message(msg_ctx
, pid
, MSG_WINBIND_IP_DROPPED
, argv
[1],
826 strlen(argv
[1]) + 1);
829 /* force a blocking lock retry */
831 static bool do_lockretry(struct tevent_context
*ev_ctx
,
832 struct messaging_context
*msg_ctx
,
833 const struct server_id pid
,
834 const int argc
, const char **argv
)
837 fprintf(stderr
, "Usage: smbcontrol <dest> lockretry\n");
841 return send_message(msg_ctx
, pid
, MSG_SMB_UNLOCK
, NULL
, 0);
844 /* force a validation of all brl entries, including re-sends. */
846 static bool do_brl_revalidate(struct tevent_context
*ev_ctx
,
847 struct messaging_context
*msg_ctx
,
848 const struct server_id pid
,
849 const int argc
, const char **argv
)
852 fprintf(stderr
, "Usage: smbcontrol <dest> brl-revalidate\n");
856 return send_message(msg_ctx
, pid
, MSG_SMB_BRL_VALIDATE
, NULL
, 0);
859 /* Display talloc pool usage */
861 static bool do_poolusage(struct tevent_context
*ev_ctx
,
862 struct messaging_context
*msg_ctx
,
863 const struct server_id pid
,
864 const int argc
, const char **argv
)
867 fprintf(stderr
, "Usage: smbcontrol <dest> pool-usage\n");
871 messaging_register(msg_ctx
, NULL
, MSG_POOL_USAGE
, print_string_cb
);
873 /* Send a message and register our interest in a reply */
875 if (!send_message(msg_ctx
, pid
, MSG_REQ_POOL_USAGE
, NULL
, 0))
878 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
880 /* No replies were received within the timeout period */
882 if (num_replies
== 0)
883 printf("No replies received\n");
885 messaging_deregister(msg_ctx
, MSG_POOL_USAGE
, NULL
);
890 /* Fetch and print the ringbuf log */
892 static void print_ringbuf_log_cb(struct messaging_context
*msg
,
895 struct server_id pid
,
898 printf("%s", (const char *)data
->data
);
902 static bool do_ringbuflog(struct tevent_context
*ev_ctx
,
903 struct messaging_context
*msg_ctx
,
904 const struct server_id pid
,
905 const int argc
, const char **argv
)
908 fprintf(stderr
, "Usage: smbcontrol <dest> ringbuf-log\n");
912 messaging_register(msg_ctx
, NULL
, MSG_RINGBUF_LOG
,
913 print_ringbuf_log_cb
);
915 /* Send a message and register our interest in a reply */
917 if (!send_message(msg_ctx
, pid
, MSG_REQ_RINGBUF_LOG
, NULL
, 0)) {
921 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
923 /* No replies were received within the timeout period */
925 if (num_replies
== 0) {
926 printf("No replies received\n");
929 messaging_deregister(msg_ctx
, MSG_RINGBUF_LOG
, NULL
);
931 return num_replies
!= 0;
934 /* Perform a dmalloc mark */
936 static bool do_dmalloc_mark(struct tevent_context
*ev_ctx
,
937 struct messaging_context
*msg_ctx
,
938 const struct server_id pid
,
939 const int argc
, const char **argv
)
942 fprintf(stderr
, "Usage: smbcontrol <dest> dmalloc-mark\n");
946 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_MARK
, NULL
, 0);
949 /* Perform a dmalloc changed */
951 static bool do_dmalloc_changed(struct tevent_context
*ev_ctx
,
952 struct messaging_context
*msg_ctx
,
953 const struct server_id pid
,
954 const int argc
, const char **argv
)
957 fprintf(stderr
, "Usage: smbcontrol <dest> "
958 "dmalloc-log-changed\n");
962 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_LOG_CHANGED
,
966 static void print_uint32_cb(struct messaging_context
*msg
, void *private_data
,
967 uint32_t msg_type
, struct server_id pid
,
970 uint32_t num_children
;
972 if (data
->length
!= sizeof(uint32_t)) {
973 printf("Invalid response: %d bytes long\n",
977 num_children
= IVAL(data
->data
, 0);
978 printf("%u children\n", (unsigned)num_children
);
983 static bool do_num_children(struct tevent_context
*ev_ctx
,
984 struct messaging_context
*msg_ctx
,
985 const struct server_id pid
,
986 const int argc
, const char **argv
)
989 fprintf(stderr
, "Usage: smbcontrol <dest> num-children\n");
993 messaging_register(msg_ctx
, NULL
, MSG_SMB_NUM_CHILDREN
,
996 /* Send a message and register our interest in a reply */
998 if (!send_message(msg_ctx
, pid
, MSG_SMB_TELL_NUM_CHILDREN
, NULL
, 0))
1001 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
1003 /* No replies were received within the timeout period */
1005 if (num_replies
== 0)
1006 printf("No replies received\n");
1008 messaging_deregister(msg_ctx
, MSG_SMB_NUM_CHILDREN
, NULL
);
1013 static bool do_msg_cleanup(struct tevent_context
*ev_ctx
,
1014 struct messaging_context
*msg_ctx
,
1015 const struct server_id pid
,
1016 const int argc
, const char **argv
)
1020 ret
= messaging_cleanup(msg_ctx
, pid
.pid
);
1022 printf("cleanup(%u) returned %s\n", (unsigned)pid
.pid
,
1023 ret
? strerror(ret
) : "ok");
1028 /* Shutdown a server process */
1030 static bool do_shutdown(struct tevent_context
*ev_ctx
,
1031 struct messaging_context
*msg_ctx
,
1032 const struct server_id pid
,
1033 const int argc
, const char **argv
)
1036 fprintf(stderr
, "Usage: smbcontrol <dest> shutdown\n");
1040 return send_message(msg_ctx
, pid
, MSG_SHUTDOWN
, NULL
, 0);
1043 /* Notify a driver upgrade */
1045 static bool do_drvupgrade(struct tevent_context
*ev_ctx
,
1046 struct messaging_context
*msg_ctx
,
1047 const struct server_id pid
,
1048 const int argc
, const char **argv
)
1051 fprintf(stderr
, "Usage: smbcontrol <dest> drvupgrade "
1056 return send_message(msg_ctx
, pid
, MSG_PRINTER_DRVUPGRADE
, argv
[1],
1057 strlen(argv
[1]) + 1);
1060 static bool do_winbind_online(struct tevent_context
*ev_ctx
,
1061 struct messaging_context
*msg_ctx
,
1062 const struct server_id pid
,
1063 const int argc
, const char **argv
)
1069 fprintf(stderr
, "Usage: smbcontrol winbindd online\n");
1073 db_path
= state_path("winbindd_cache.tdb");
1074 if (db_path
== NULL
) {
1078 /* Remove the entry in the winbindd_cache tdb to tell a later
1079 starting winbindd that we're online. */
1081 tdb
= tdb_open_log(db_path
, 0, TDB_DEFAULT
, O_RDWR
, 0600);
1083 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
1085 TALLOC_FREE(db_path
);
1089 TALLOC_FREE(db_path
);
1090 tdb_delete_bystring(tdb
, "WINBINDD_OFFLINE");
1093 return send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINE
, NULL
, 0);
1096 static bool do_winbind_offline(struct tevent_context
*ev_ctx
,
1097 struct messaging_context
*msg_ctx
,
1098 const struct server_id pid
,
1099 const int argc
, const char **argv
)
1107 fprintf(stderr
, "Usage: smbcontrol winbindd offline\n");
1111 db_path
= state_path("winbindd_cache.tdb");
1112 if (db_path
== NULL
) {
1116 /* Create an entry in the winbindd_cache tdb to tell a later
1117 starting winbindd that we're offline. We may actually create
1120 tdb
= tdb_open_log(db_path
,
1121 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE
,
1122 TDB_DEFAULT
|TDB_INCOMPATIBLE_HASH
/* TDB_CLEAR_IF_FIRST */,
1123 O_RDWR
|O_CREAT
, 0600);
1126 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
1128 TALLOC_FREE(db_path
);
1131 TALLOC_FREE(db_path
);
1133 /* There's a potential race condition that if a child
1134 winbindd detects a domain is online at the same time
1135 we're trying to tell it to go offline that it might
1136 delete the record we add between us adding it and
1137 sending the message. Minimize this by retrying up to
1140 for (retry
= 0; retry
< 5; retry
++) {
1142 TDB_DATA d
= { .dptr
= buf
, .dsize
= sizeof(buf
) };
1144 SIVAL(buf
, 0, time(NULL
));
1146 tdb_store_bystring(tdb
, "WINBINDD_OFFLINE", d
, TDB_INSERT
);
1148 ret
= send_message(msg_ctx
, pid
, MSG_WINBIND_OFFLINE
,
1151 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
1152 d
= tdb_fetch_bystring( tdb
, "WINBINDD_OFFLINE" );
1154 if (!d
.dptr
|| d
.dsize
!= 4) {
1156 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
)
1172 struct server_id myid
;
1174 myid
= messaging_server_id(msg_ctx
);
1177 fprintf(stderr
, "Usage: smbcontrol winbindd onlinestatus\n");
1181 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_ONLINESTATUS
,
1182 print_pid_string_cb
);
1184 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINESTATUS
, &myid
,
1188 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
1190 /* No replies were received within the timeout period */
1192 if (num_replies
== 0)
1193 printf("No replies received\n");
1195 messaging_deregister(msg_ctx
, MSG_WINBIND_ONLINESTATUS
, NULL
);
1200 static bool do_dump_event_list(struct tevent_context
*ev_ctx
,
1201 struct messaging_context
*msg_ctx
,
1202 const struct server_id pid
,
1203 const int argc
, const char **argv
)
1206 fprintf(stderr
, "Usage: smbcontrol <dest> dump-event-list\n");
1210 return send_message(msg_ctx
, pid
, MSG_DUMP_EVENT_LIST
, NULL
, 0);
1213 static bool do_winbind_dump_domain_list(struct tevent_context
*ev_ctx
,
1214 struct messaging_context
*msg_ctx
,
1215 const struct server_id pid
,
1216 const int argc
, const char **argv
)
1218 const char *domain
= NULL
;
1220 struct server_id myid
;
1221 uint8_t *buf
= NULL
;
1224 myid
= messaging_server_id(msg_ctx
);
1226 if (argc
< 1 || argc
> 2) {
1227 fprintf(stderr
, "Usage: smbcontrol <dest> dump-domain-list "
1234 domain_len
= strlen(argv
[1]) + 1;
1237 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1238 print_pid_string_cb
);
1240 buf_len
= sizeof(myid
)+domain_len
;
1241 buf
= SMB_MALLOC_ARRAY(uint8_t, buf_len
);
1246 memcpy(buf
, &myid
, sizeof(myid
));
1247 memcpy(&buf
[sizeof(myid
)], domain
, domain_len
);
1249 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1256 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
1258 /* No replies were received within the timeout period */
1261 if (num_replies
== 0) {
1262 printf("No replies received\n");
1265 messaging_deregister(msg_ctx
, MSG_WINBIND_DUMP_DOMAIN_LIST
, NULL
);
1270 static void winbind_validate_cache_cb(struct messaging_context
*msg
,
1273 struct server_id pid
,
1276 struct server_id_buf src_string
;
1277 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1278 (*(data
->data
) == 0 ? "" : "NOT "),
1279 server_id_str_buf(pid
, &src_string
));
1283 static bool do_winbind_validate_cache(struct tevent_context
*ev_ctx
,
1284 struct messaging_context
*msg_ctx
,
1285 const struct server_id pid
,
1286 const int argc
, const char **argv
)
1288 struct server_id myid
;
1290 myid
= messaging_server_id(msg_ctx
);
1293 fprintf(stderr
, "Usage: smbcontrol winbindd validate-cache\n");
1297 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_VALIDATE_CACHE
,
1298 winbind_validate_cache_cb
);
1300 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_VALIDATE_CACHE
, &myid
,
1305 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
1307 if (num_replies
== 0) {
1308 printf("No replies received\n");
1311 messaging_deregister(msg_ctx
, MSG_WINBIND_VALIDATE_CACHE
, NULL
);
1316 static bool do_reload_config(struct tevent_context
*ev_ctx
,
1317 struct messaging_context
*msg_ctx
,
1318 const struct server_id pid
,
1319 const int argc
, const char **argv
)
1322 fprintf(stderr
, "Usage: smbcontrol <dest> reload-config\n");
1326 return send_message(msg_ctx
, pid
, MSG_SMB_CONF_UPDATED
, NULL
, 0);
1329 static bool do_reload_printers(struct tevent_context
*ev_ctx
,
1330 struct messaging_context
*msg_ctx
,
1331 const struct server_id pid
,
1332 const int argc
, const char **argv
)
1335 fprintf(stderr
, "Usage: smbcontrol <dest> reload-printers\n");
1339 return send_message(msg_ctx
, pid
, MSG_PRINTER_PCAP
, NULL
, 0);
1342 static void my_make_nmb_name( struct nmb_name
*n
, const char *name
, int type
)
1345 memset( (char *)n
, '\0', sizeof(struct nmb_name
) );
1346 fstrcpy(unix_name
, name
);
1347 (void)strupper_m(unix_name
);
1348 push_ascii(n
->name
, unix_name
, sizeof(n
->name
), STR_TERMINATE
);
1349 n
->name_type
= (unsigned int)type
& 0xFF;
1350 push_ascii(n
->scope
, lp_netbios_scope(), 64, STR_TERMINATE
);
1353 static bool do_nodestatus(struct tevent_context
*ev_ctx
,
1354 struct messaging_context
*msg_ctx
,
1355 const struct server_id pid
,
1356 const int argc
, const char **argv
)
1358 struct packet_struct p
;
1361 fprintf(stderr
, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1367 p
.ip
= interpret_addr2(argv
[1]);
1369 p
.packet_type
= NMB_PACKET
;
1371 p
.packet
.nmb
.header
.name_trn_id
= 10;
1372 p
.packet
.nmb
.header
.opcode
= 0;
1373 p
.packet
.nmb
.header
.response
= False
;
1374 p
.packet
.nmb
.header
.nm_flags
.bcast
= False
;
1375 p
.packet
.nmb
.header
.nm_flags
.recursion_available
= False
;
1376 p
.packet
.nmb
.header
.nm_flags
.recursion_desired
= False
;
1377 p
.packet
.nmb
.header
.nm_flags
.trunc
= False
;
1378 p
.packet
.nmb
.header
.nm_flags
.authoritative
= False
;
1379 p
.packet
.nmb
.header
.rcode
= 0;
1380 p
.packet
.nmb
.header
.qdcount
= 1;
1381 p
.packet
.nmb
.header
.ancount
= 0;
1382 p
.packet
.nmb
.header
.nscount
= 0;
1383 p
.packet
.nmb
.header
.arcount
= 0;
1384 my_make_nmb_name(&p
.packet
.nmb
.question
.question_name
, "*", 0x00);
1385 p
.packet
.nmb
.question
.question_type
= 0x21;
1386 p
.packet
.nmb
.question
.question_class
= 0x1;
1388 return send_message(msg_ctx
, pid
, MSG_SEND_PACKET
, &p
, sizeof(p
));
1391 static bool do_notify_cleanup(struct tevent_context
*ev_ctx
,
1392 struct messaging_context
*msg_ctx
,
1393 const struct server_id pid
,
1394 const int argc
, const char **argv
)
1397 fprintf(stderr
, "Usage: smbcontrol smbd notify-cleanup\n");
1400 return send_message(msg_ctx
, pid
, MSG_SMB_NOTIFY_CLEANUP
, NULL
, 0);
1403 /* A list of message type supported */
1405 static const struct {
1406 const char *name
; /* Option name */
1407 bool (*fn
)(struct tevent_context
*ev_ctx
,
1408 struct messaging_context
*msg_ctx
,
1409 const struct server_id pid
,
1410 const int argc
, const char **argv
);
1411 const char *help
; /* Short help text */
1413 { "debug", do_debug
, "Set debuglevel" },
1414 { "idmap", do_idmap
, "Manipulate idmap cache" },
1415 { "force-election", do_election
,
1416 "Force a browse election" },
1417 { "ping", do_ping
, "Elicit a response" },
1418 { "profile", do_profile
, "" },
1419 { "inject", do_inject_fault
,
1420 "Inject a fatal signal into a running smbd"},
1421 { "stacktrace", do_daemon_stack_trace
,
1422 "Display a stack trace of a daemon" },
1423 { "profilelevel", do_profilelevel
, "" },
1424 { "debuglevel", do_debuglevel
, "Display current debuglevels" },
1425 { "printnotify", do_printnotify
, "Send a print notify message" },
1426 { "close-share", do_closeshare
, "Forcibly disconnect a share" },
1427 { "kill-client-ip", do_kill_client_by_ip
,
1428 "Forcibly disconnect a client with a specific IP address" },
1429 { "ip-dropped", do_ip_dropped
, "Tell winbind that an IP got dropped" },
1430 { "lockretry", do_lockretry
, "Force a blocking lock retry" },
1431 { "brl-revalidate", do_brl_revalidate
, "Revalidate all brl entries" },
1432 { "pool-usage", do_poolusage
, "Display talloc memory usage" },
1433 { "ringbuf-log", do_ringbuflog
, "Display ringbuf log" },
1434 { "dmalloc-mark", do_dmalloc_mark
, "" },
1435 { "dmalloc-log-changed", do_dmalloc_changed
, "" },
1436 { "shutdown", do_shutdown
, "Shut down daemon" },
1437 { "drvupgrade", do_drvupgrade
, "Notify a printer driver has changed" },
1438 { "reload-config", do_reload_config
, "Force smbd or winbindd to reload config file"},
1439 { "reload-printers", do_reload_printers
, "Force smbd to reload printers"},
1440 { "nodestatus", do_nodestatus
, "Ask nmbd to do a node status request"},
1441 { "online", do_winbind_online
, "Ask winbind to go into online state"},
1442 { "offline", do_winbind_offline
, "Ask winbind to go into offline state"},
1443 { "onlinestatus", do_winbind_onlinestatus
, "Request winbind online status"},
1444 { "dump-event-list", do_dump_event_list
, "Dump event list"},
1445 { "validate-cache" , do_winbind_validate_cache
,
1446 "Validate winbind's credential cache" },
1447 { "dump-domain-list", do_winbind_dump_domain_list
, "Dump winbind domain list"},
1448 { "notify-cleanup", do_notify_cleanup
},
1449 { "num-children", do_num_children
,
1450 "Print number of smbd child processes" },
1451 { "msg-cleanup", do_msg_cleanup
},
1452 { "noop", do_noop
, "Do nothing" },
1456 /* Display usage information */
1458 static void usage(poptContext pc
)
1462 poptPrintHelp(pc
, stderr
, 0);
1464 fprintf(stderr
, "\n");
1465 fprintf(stderr
, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1468 fprintf(stderr
, "\n");
1469 fprintf(stderr
, "<message-type> is one of:\n");
1471 for (i
= 0; msg_types
[i
].name
; i
++)
1472 fprintf(stderr
, "\t%-30s%s\n", msg_types
[i
].name
,
1475 fprintf(stderr
, "\n");
1480 /* Return the pid number for a string destination */
1482 static struct server_id
parse_dest(struct messaging_context
*msg
,
1485 struct server_id result
= {-1};
1488 /* Zero is a special return value for broadcast to all processes */
1490 if (strequal(dest
, "all")) {
1491 return interpret_pid(MSG_BROADCAST_PID_STR
);
1494 /* Try self - useful for testing */
1496 if (strequal(dest
, "self")) {
1497 return messaging_server_id(msg
);
1500 /* Fix winbind typo. */
1501 if (strequal(dest
, "winbind")) {
1505 /* Check for numeric pid number */
1506 result
= interpret_pid(dest
);
1508 /* Zero isn't valid if not "all". */
1509 if (result
.pid
&& procid_valid(&result
)) {
1513 /* Look up other destinations in pidfile directory */
1515 if ((pid
= pidfile_pid(lp_pid_directory(), dest
)) != 0) {
1516 return pid_to_procid(pid
);
1519 fprintf(stderr
,"Can't find pid for destination '%s'\n", dest
);
1524 /* Execute smbcontrol command */
1526 static bool do_command(struct tevent_context
*ev_ctx
,
1527 struct messaging_context
*msg_ctx
,
1528 int argc
, const char **argv
)
1530 const char *dest
= argv
[0], *command
= argv
[1];
1531 struct server_id pid
;
1534 /* Check destination */
1536 pid
= parse_dest(msg_ctx
, dest
);
1537 if (!procid_valid(&pid
)) {
1543 for (i
= 0; msg_types
[i
].name
; i
++) {
1544 if (strequal(command
, msg_types
[i
].name
))
1545 return msg_types
[i
].fn(ev_ctx
, msg_ctx
, pid
,
1546 argc
- 1, argv
+ 1);
1549 fprintf(stderr
, "smbcontrol: unknown command '%s'\n", command
);
1554 static void smbcontrol_help(poptContext pc
,
1555 enum poptCallbackReason preason
,
1556 struct poptOption
* poption
,
1560 if (poption
->shortName
!= '?') {
1561 poptPrintUsage(pc
, stdout
, 0);
1569 struct poptOption help_options
[] = {
1570 { NULL
, '\0', POPT_ARG_CALLBACK
, (void *)&smbcontrol_help
, '\0',
1572 { "help", '?', 0, NULL
, '?', "Show this help message", NULL
},
1573 { "usage", '\0', 0, NULL
, 'u', "Display brief usage message", NULL
},
1579 int main(int argc
, const char **argv
)
1583 struct tevent_context
*evt_ctx
;
1584 struct messaging_context
*msg_ctx
;
1586 static struct poptOption long_options
[] = {
1588 { NULL
, '\0', POPT_ARG_INCLUDE_TABLE
, help_options
,
1589 0, "Help options:", NULL
},
1590 { "timeout", 't', POPT_ARG_INT
, &timeout
, 't',
1591 "Set timeout value in seconds", "TIMEOUT" },
1596 TALLOC_CTX
*frame
= talloc_stackframe();
1601 setup_logging(argv
[0], DEBUG_STDOUT
);
1602 lp_set_cmdline("log level", "0");
1604 /* Parse command line arguments using popt */
1606 pc
= poptGetContext(
1607 "smbcontrol", argc
, (const char **)argv
, long_options
, 0);
1609 poptSetOtherOptionHelp(pc
, "[OPTION...] <destination> <message-type> "
1615 while ((opt
= poptGetNextOpt(pc
)) != -1) {
1617 case 't': /* --timeout */
1620 fprintf(stderr
, "Invalid option\n");
1621 poptPrintHelp(pc
, stderr
, 0);
1626 /* We should now have the remaining command line arguments in
1627 argv. The argc parameter should have been decremented to the
1628 correct value in the above switch statement. */
1630 argv
= (const char **)poptGetArgs(pc
);
1633 while (argv
[argc
] != NULL
) {
1641 lp_load_global(get_dyn_CONFIGFILE());
1643 /* Need to invert sense of return code -- samba
1644 * routines mostly return True==1 for success, but
1647 if (!(evt_ctx
= samba_tevent_context_init(NULL
)) ||
1648 !(msg_ctx
= messaging_init(NULL
, evt_ctx
))) {
1649 fprintf(stderr
, "could not init messaging context\n");
1654 ret
= !do_command(evt_ctx
, msg_ctx
, argc
, argv
);
1655 TALLOC_FREE(msg_ctx
);