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 unsigned int seconds;
420 const long MAX_SLEEP = 60 * 60; /* One hour maximum sleep */
423 fprintf(stderr, "Usage: smbcontrol <dest> sleep seconds\n");
427 #if !defined(DEVELOPER) && !defined(ENABLE_SELFTEST)
428 fprintf(stderr, "Sleep is only available in "
429 "developer and self test builds\n");
431 #else /* DEVELOPER || ENABLE_SELFTEST */
433 input = atol(argv[1]);
434 if (input < 1 || input > MAX_SLEEP) {
436 "Invalid duration for sleep '%s'\n"
437 "It should be at least 1 second and no more than %ld\n",
443 return send_message(msg_ctx, pid,
446 sizeof(unsigned int));
447 #endif /* DEVELOPER || ENABLE_SELFTEST */
450 /* Force a browser election */
452 static bool do_election(struct tevent_context *ev_ctx,
453 struct messaging_context *msg_ctx,
454 const struct server_id pid,
455 const int argc, const char **argv)
458 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
462 return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
465 /* Ping a samba daemon process */
467 static void pong_cb(struct messaging_context *msg,
470 struct server_id pid,
473 struct server_id_buf src_string;
474 printf("PONG from pid %s\n", server_id_str_buf(pid, &src_string));
478 static bool do_ping(struct tevent_context *ev_ctx,
479 struct messaging_context *msg_ctx,
480 const struct server_id pid,
481 const int argc, const char **argv)
484 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
488 /* Send a message and register our interest in a reply */
490 if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
493 messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
495 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
497 /* No replies were received within the timeout period */
499 if (num_replies == 0)
500 printf("No replies received\n");
502 messaging_deregister(msg_ctx, MSG_PONG, NULL);
507 /* Set profiling options */
509 static bool do_profile(struct tevent_context *ev_ctx,
510 struct messaging_context *msg_ctx,
511 const struct server_id pid,
512 const int argc, const char **argv)
517 fprintf(stderr, "Usage: smbcontrol <dest> profile "
518 "<off|count|on|flush>\n");
522 if (strcmp(argv[1], "off") == 0) {
524 } else if (strcmp(argv[1], "count") == 0) {
526 } else if (strcmp(argv[1], "on") == 0) {
528 } else if (strcmp(argv[1], "flush") == 0) {
531 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
535 return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
538 /* Return the profiling level */
540 static void profilelevel_cb(struct messaging_context *msg_ctx,
543 struct server_id pid,
551 if (data->length != sizeof(int)) {
552 fprintf(stderr, "invalid message length %ld returned\n",
553 (unsigned long)data->length);
557 memcpy(&level, data->data, sizeof(int));
570 s = "count and time";
577 printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
580 static void profilelevel_rqst(struct messaging_context *msg_ctx,
583 struct server_id pid,
588 /* Send back a dummy reply */
590 send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
593 static bool do_profilelevel(struct tevent_context *ev_ctx,
594 struct messaging_context *msg_ctx,
595 const struct server_id pid,
596 const int argc, const char **argv)
599 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
603 /* Send a message and register our interest in a reply */
605 if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
608 messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
609 messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
612 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
614 /* No replies were received within the timeout period */
616 if (num_replies == 0)
617 printf("No replies received\n");
619 messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
624 /* Display debug level settings */
626 static bool do_debuglevel(struct tevent_context *ev_ctx,
627 struct messaging_context *msg_ctx,
628 const struct server_id pid,
629 const int argc, const char **argv)
632 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
636 /* Send a message and register our interest in a reply */
638 if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
641 messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
643 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
645 /* No replies were received within the timeout period */
647 if (num_replies == 0)
648 printf("No replies received\n");
650 messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
655 /* Send a print notify message */
657 static bool do_printnotify(struct tevent_context *ev_ctx,
658 struct messaging_context *msg_ctx,
659 const struct server_id pid,
660 const int argc, const char **argv)
664 /* Check for subcommand */
667 fprintf(stderr, "Must specify subcommand:\n");
668 fprintf(stderr, "\tqueuepause <printername>\n");
669 fprintf(stderr, "\tqueueresume <printername>\n");
670 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
671 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
672 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
673 fprintf(stderr, "\tprinter <printername> <comment|port|"
674 "driver> <value>\n");
681 if (strcmp(cmd, "queuepause") == 0) {
684 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
685 " queuepause <printername>\n");
689 notify_printer_status_byname(ev_ctx, msg_ctx, argv[2],
690 PRINTER_STATUS_PAUSED);
694 } else if (strcmp(cmd, "queueresume") == 0) {
697 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
698 " queuereume <printername>\n");
702 notify_printer_status_byname(ev_ctx, msg_ctx, argv[2],
707 } else if (strcmp(cmd, "jobpause") == 0) {
711 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
712 " jobpause <printername> <unix-jobid>\n");
716 jobid = atoi(argv[3]);
718 notify_job_status_byname(
720 argv[2], jobid, JOB_STATUS_PAUSED,
721 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
725 } else if (strcmp(cmd, "jobresume") == 0) {
729 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
730 " jobpause <printername> <unix-jobid>\n");
734 jobid = atoi(argv[3]);
736 notify_job_status_byname(
738 argv[2], jobid, JOB_STATUS_QUEUED,
739 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
743 } else if (strcmp(cmd, "jobdelete") == 0) {
747 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
748 " jobpause <printername> <unix-jobid>\n");
752 jobid = atoi(argv[3]);
754 notify_job_status_byname(
756 argv[2], jobid, JOB_STATUS_DELETING,
757 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
759 notify_job_status_byname(
761 argv[2], jobid, JOB_STATUS_DELETING|
763 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
767 } else if (strcmp(cmd, "printer") == 0) {
771 fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
772 "printer <printername> <comment|port|driver> "
777 if (strcmp(argv[3], "comment") == 0) {
778 attribute = PRINTER_NOTIFY_FIELD_COMMENT;
779 } else if (strcmp(argv[3], "port") == 0) {
780 attribute = PRINTER_NOTIFY_FIELD_PORT_NAME;
781 } else if (strcmp(argv[3], "driver") == 0) {
782 attribute = PRINTER_NOTIFY_FIELD_DRIVER_NAME;
784 fprintf(stderr, "Invalid printer command '%s'\n",
789 notify_printer_byname(ev_ctx, msg_ctx, argv[2], attribute,
790 discard_const_p(char, argv[4]));
795 fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
799 print_notify_send_messages(msg_ctx, 0);
805 static bool do_closeshare(struct tevent_context *ev_ctx,
806 struct messaging_context *msg_ctx,
807 const struct server_id pid,
808 const int argc, const char **argv)
811 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
816 return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
817 strlen(argv[1]) + 1);
820 /* Kill a client by IP address */
821 static bool do_kill_client_by_ip(struct tevent_context *ev_ctx,
822 struct messaging_context *msg_ctx,
823 const struct server_id pid,
824 const int argc, const char **argv)
827 fprintf(stderr, "Usage: smbcontrol <dest> kill-client-ip "
832 if (!is_ipaddress_v4(argv[1]) && !is_ipaddress_v6(argv[1])) {
833 fprintf(stderr, "%s is not a valid IP address!\n", argv[1]);
837 return send_message(msg_ctx, pid, MSG_SMB_KILL_CLIENT_IP,
838 argv[1], strlen(argv[1]) + 1);
841 /* Tell winbindd an IP got dropped */
843 static bool do_ip_dropped(struct tevent_context *ev_ctx,
844 struct messaging_context *msg_ctx,
845 const struct server_id pid,
846 const int argc, const char **argv)
849 fprintf(stderr, "Usage: smbcontrol <dest> ip-dropped "
854 return send_message(msg_ctx, pid, MSG_WINBIND_IP_DROPPED, argv[1],
855 strlen(argv[1]) + 1);
858 /* force a blocking lock retry */
860 static bool do_lockretry(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> lockretry\n");
870 return send_message(msg_ctx, pid, MSG_SMB_UNLOCK, NULL, 0);
873 /* force a validation of all brl entries, including re-sends. */
875 static bool do_brl_revalidate(struct tevent_context *ev_ctx,
876 struct messaging_context *msg_ctx,
877 const struct server_id pid,
878 const int argc, const char **argv)
881 fprintf(stderr, "Usage: smbcontrol <dest> brl-revalidate\n");
885 return send_message(msg_ctx, pid, MSG_SMB_BRL_VALIDATE, NULL, 0);
888 /* Display talloc pool usage */
890 static bool do_poolusage(struct tevent_context *ev_ctx,
891 struct messaging_context *msg_ctx,
892 const struct server_id pid,
893 const int argc, const char **argv)
896 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
900 messaging_register(msg_ctx, NULL, MSG_POOL_USAGE, print_string_cb);
902 /* Send a message and register our interest in a reply */
904 if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0))
907 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
909 /* No replies were received within the timeout period */
911 if (num_replies == 0)
912 printf("No replies received\n");
914 messaging_deregister(msg_ctx, MSG_POOL_USAGE, NULL);
919 /* Fetch and print the ringbuf log */
921 static void print_ringbuf_log_cb(struct messaging_context *msg,
924 struct server_id pid,
927 printf("%s", (const char *)data->data);
931 static bool do_ringbuflog(struct tevent_context *ev_ctx,
932 struct messaging_context *msg_ctx,
933 const struct server_id pid,
934 const int argc, const char **argv)
937 fprintf(stderr, "Usage: smbcontrol <dest> ringbuf-log\n");
941 messaging_register(msg_ctx, NULL, MSG_RINGBUF_LOG,
942 print_ringbuf_log_cb);
944 /* Send a message and register our interest in a reply */
946 if (!send_message(msg_ctx, pid, MSG_REQ_RINGBUF_LOG, NULL, 0)) {
950 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
952 /* No replies were received within the timeout period */
954 if (num_replies == 0) {
955 printf("No replies received\n");
958 messaging_deregister(msg_ctx, MSG_RINGBUF_LOG, NULL);
960 return num_replies != 0;
963 /* Perform a dmalloc mark */
965 static bool do_dmalloc_mark(struct tevent_context *ev_ctx,
966 struct messaging_context *msg_ctx,
967 const struct server_id pid,
968 const int argc, const char **argv)
971 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
975 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
978 /* Perform a dmalloc changed */
980 static bool do_dmalloc_changed(struct tevent_context *ev_ctx,
981 struct messaging_context *msg_ctx,
982 const struct server_id pid,
983 const int argc, const char **argv)
986 fprintf(stderr, "Usage: smbcontrol <dest> "
987 "dmalloc-log-changed\n");
991 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
995 static void print_uint32_cb(struct messaging_context *msg, void *private_data,
996 uint32_t msg_type, struct server_id pid,
999 uint32_t num_children;
1001 if (data->length != sizeof(uint32_t)) {
1002 printf("Invalid response: %d bytes long\n",
1006 num_children = IVAL(data->data, 0);
1007 printf("%u children\n", (unsigned)num_children);
1012 static bool do_num_children(struct tevent_context *ev_ctx,
1013 struct messaging_context *msg_ctx,
1014 const struct server_id pid,
1015 const int argc, const char **argv)
1018 fprintf(stderr, "Usage: smbcontrol <dest> num-children\n");
1022 messaging_register(msg_ctx, NULL, MSG_SMB_NUM_CHILDREN,
1025 /* Send a message and register our interest in a reply */
1027 if (!send_message(msg_ctx, pid, MSG_SMB_TELL_NUM_CHILDREN, NULL, 0))
1030 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1032 /* No replies were received within the timeout period */
1034 if (num_replies == 0)
1035 printf("No replies received\n");
1037 messaging_deregister(msg_ctx, MSG_SMB_NUM_CHILDREN, NULL);
1042 static bool do_msg_cleanup(struct tevent_context *ev_ctx,
1043 struct messaging_context *msg_ctx,
1044 const struct server_id pid,
1045 const int argc, const char **argv)
1049 ret = messaging_cleanup(msg_ctx, pid.pid);
1051 printf("cleanup(%u) returned %s\n", (unsigned)pid.pid,
1052 ret ? strerror(ret) : "ok");
1057 /* Shutdown a server process */
1059 static bool do_shutdown(struct tevent_context *ev_ctx,
1060 struct messaging_context *msg_ctx,
1061 const struct server_id pid,
1062 const int argc, const char **argv)
1065 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
1069 return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
1072 /* Notify a driver upgrade */
1074 static bool do_drvupgrade(struct tevent_context *ev_ctx,
1075 struct messaging_context *msg_ctx,
1076 const struct server_id pid,
1077 const int argc, const char **argv)
1080 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
1085 return send_message(msg_ctx, pid, MSG_PRINTER_DRVUPGRADE, argv[1],
1086 strlen(argv[1]) + 1);
1089 static bool do_winbind_online(struct tevent_context *ev_ctx,
1090 struct messaging_context *msg_ctx,
1091 const struct server_id pid,
1092 const int argc, const char **argv)
1098 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
1102 db_path = state_path(talloc_tos(), "winbindd_cache.tdb");
1103 if (db_path == NULL) {
1107 /* Remove the entry in the winbindd_cache tdb to tell a later
1108 starting winbindd that we're online. */
1110 tdb = tdb_open_log(db_path, 0, TDB_DEFAULT, O_RDWR, 0600);
1112 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
1114 TALLOC_FREE(db_path);
1118 TALLOC_FREE(db_path);
1119 tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
1122 return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
1125 static bool do_winbind_offline(struct tevent_context *ev_ctx,
1126 struct messaging_context *msg_ctx,
1127 const struct server_id pid,
1128 const int argc, const char **argv)
1136 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
1140 db_path = state_path(talloc_tos(), "winbindd_cache.tdb");
1141 if (db_path == NULL) {
1145 /* Create an entry in the winbindd_cache tdb to tell a later
1146 starting winbindd that we're offline. We may actually create
1149 tdb = tdb_open_log(db_path,
1150 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
1151 TDB_DEFAULT|TDB_INCOMPATIBLE_HASH /* TDB_CLEAR_IF_FIRST */,
1152 O_RDWR|O_CREAT, 0600);
1155 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
1157 TALLOC_FREE(db_path);
1160 TALLOC_FREE(db_path);
1162 /* There's a potential race condition that if a child
1163 winbindd detects a domain is online at the same time
1164 we're trying to tell it to go offline that it might
1165 delete the record we add between us adding it and
1166 sending the message. Minimize this by retrying up to
1169 for (retry = 0; retry < 5; retry++) {
1171 TDB_DATA d = { .dptr = buf, .dsize = sizeof(buf) };
1173 SIVAL(buf, 0, time(NULL));
1175 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
1177 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
1180 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
1181 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
1182 if (d.dptr != NULL && d.dsize == 4) {
1188 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
1195 static bool do_winbind_onlinestatus(struct tevent_context *ev_ctx,
1196 struct messaging_context *msg_ctx,
1197 const struct server_id pid,
1198 const int argc, const char **argv)
1201 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
1205 messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
1206 print_pid_string_cb);
1208 if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, NULL, 0)) {
1212 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1214 /* No replies were received within the timeout period */
1216 if (num_replies == 0)
1217 printf("No replies received\n");
1219 messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
1224 static bool do_winbind_dump_domain_list(struct tevent_context *ev_ctx,
1225 struct messaging_context *msg_ctx,
1226 const struct server_id pid,
1227 const int argc, const char **argv)
1229 const char *domain = NULL;
1232 if (argc < 1 || argc > 2) {
1233 fprintf(stderr, "Usage: smbcontrol <dest> dump-domain-list "
1240 domain_len = strlen(argv[1]) + 1;
1243 messaging_register(msg_ctx, NULL, MSG_WINBIND_DUMP_DOMAIN_LIST,
1244 print_pid_string_cb);
1246 if (!send_message(msg_ctx, pid, MSG_WINBIND_DUMP_DOMAIN_LIST,
1247 domain, domain_len))
1252 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1254 /* No replies were received within the timeout period */
1256 if (num_replies == 0) {
1257 printf("No replies received\n");
1260 messaging_deregister(msg_ctx, MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
1265 static bool do_msg_disconnect_dc(struct tevent_context *ev_ctx,
1266 struct messaging_context *msg_ctx,
1267 const struct server_id pid,
1268 const int argc, const char **argv)
1271 fprintf(stderr, "Usage: smbcontrol <dest> disconnect-dc\n");
1275 return send_message(msg_ctx, pid, MSG_WINBIND_DISCONNECT_DC, NULL, 0);
1278 static void winbind_validate_cache_cb(struct messaging_context *msg,
1281 struct server_id pid,
1284 struct server_id_buf src_string;
1285 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1286 (*(data->data) == 0 ? "" : "NOT "),
1287 server_id_str_buf(pid, &src_string));
1291 static bool do_winbind_validate_cache(struct tevent_context *ev_ctx,
1292 struct messaging_context *msg_ctx,
1293 const struct server_id pid,
1294 const int argc, const char **argv)
1296 struct server_id myid;
1298 myid = messaging_server_id(msg_ctx);
1301 fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
1305 messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
1306 winbind_validate_cache_cb);
1308 if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
1313 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1315 if (num_replies == 0) {
1316 printf("No replies received\n");
1319 messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);
1324 static bool do_reload_config(struct tevent_context *ev_ctx,
1325 struct messaging_context *msg_ctx,
1326 const struct server_id pid,
1327 const int argc, const char **argv)
1330 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1334 return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1337 static bool do_reload_printers(struct tevent_context *ev_ctx,
1338 struct messaging_context *msg_ctx,
1339 const struct server_id pid,
1340 const int argc, const char **argv)
1343 fprintf(stderr, "Usage: smbcontrol <dest> reload-printers\n");
1347 return send_message(msg_ctx, pid, MSG_PRINTER_PCAP, NULL, 0);
1350 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1353 memset( (char *)n, '\0', sizeof(struct nmb_name) );
1354 fstrcpy(unix_name, name);
1355 (void)strupper_m(unix_name);
1356 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1357 n->name_type = (unsigned int)type & 0xFF;
1358 push_ascii(n->scope, lp_netbios_scope(), 64, STR_TERMINATE);
1361 static bool do_nodestatus(struct tevent_context *ev_ctx,
1362 struct messaging_context *msg_ctx,
1363 const struct server_id pid,
1364 const int argc, const char **argv)
1366 struct packet_struct p;
1369 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1375 p.ip = interpret_addr2(argv[1]);
1377 p.packet_type = NMB_PACKET;
1379 p.packet.nmb.header.name_trn_id = 10;
1380 p.packet.nmb.header.opcode = 0;
1381 p.packet.nmb.header.response = False;
1382 p.packet.nmb.header.nm_flags.bcast = False;
1383 p.packet.nmb.header.nm_flags.recursion_available = False;
1384 p.packet.nmb.header.nm_flags.recursion_desired = False;
1385 p.packet.nmb.header.nm_flags.trunc = False;
1386 p.packet.nmb.header.nm_flags.authoritative = False;
1387 p.packet.nmb.header.rcode = 0;
1388 p.packet.nmb.header.qdcount = 1;
1389 p.packet.nmb.header.ancount = 0;
1390 p.packet.nmb.header.nscount = 0;
1391 p.packet.nmb.header.arcount = 0;
1392 my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1393 p.packet.nmb.question.question_type = 0x21;
1394 p.packet.nmb.question.question_class = 0x1;
1396 return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1399 static bool do_notify_cleanup(struct tevent_context *ev_ctx,
1400 struct messaging_context *msg_ctx,
1401 const struct server_id pid,
1402 const int argc, const char **argv)
1405 fprintf(stderr, "Usage: smbcontrol smbd notify-cleanup\n");
1408 return send_message(msg_ctx, pid, MSG_SMB_NOTIFY_CLEANUP, NULL, 0);
1411 /* A list of message type supported */
1413 static const struct {
1414 const char *name; /* Option name */
1415 bool (*fn)(struct tevent_context *ev_ctx,
1416 struct messaging_context *msg_ctx,
1417 const struct server_id pid,
1418 const int argc, const char **argv);
1419 const char *help; /* Short help text */
1424 .help = "Set debuglevel",
1429 .help = "Manipulate idmap cache",
1432 .name = "force-election",
1434 .help = "Force a browse election",
1439 .help = "Elicit a response",
1448 .fn = do_inject_fault,
1449 .help = "Inject a fatal signal into a running smbd"},
1451 .name = "stacktrace",
1452 .fn = do_daemon_stack_trace,
1453 .help = "Display a stack trace of a daemon",
1456 .name = "profilelevel",
1457 .fn = do_profilelevel,
1461 .name = "debuglevel",
1462 .fn = do_debuglevel,
1463 .help = "Display current debuglevels",
1466 .name = "printnotify",
1467 .fn = do_printnotify,
1468 .help = "Send a print notify message",
1471 .name = "close-share",
1472 .fn = do_closeshare,
1473 .help = "Forcibly disconnect a share",
1476 .name = "kill-client-ip",
1477 .fn = do_kill_client_by_ip,
1478 .help = "Forcibly disconnect a client with a specific IP address",
1481 .name = "ip-dropped",
1482 .fn = do_ip_dropped,
1483 .help = "Tell winbind that an IP got dropped",
1486 .name = "lockretry",
1488 .help = "Force a blocking lock retry",
1491 .name = "brl-revalidate",
1492 .fn = do_brl_revalidate,
1493 .help = "Revalidate all brl entries",
1496 .name = "pool-usage",
1498 .help = "Display talloc memory usage",
1501 .name = "ringbuf-log",
1502 .fn = do_ringbuflog,
1503 .help = "Display ringbuf log",
1506 .name = "dmalloc-mark",
1507 .fn = do_dmalloc_mark,
1511 .name = "dmalloc-log-changed",
1512 .fn = do_dmalloc_changed,
1518 .help = "Shut down daemon",
1521 .name = "drvupgrade",
1522 .fn = do_drvupgrade,
1523 .help = "Notify a printer driver has changed",
1526 .name = "reload-config",
1527 .fn = do_reload_config,
1528 .help = "Force smbd or winbindd to reload config file"},
1530 .name = "reload-printers",
1531 .fn = do_reload_printers,
1532 .help = "Force smbd to reload printers"},
1534 .name = "nodestatus",
1535 .fn = do_nodestatus,
1536 .help = "Ask nmbd to do a node status request"},
1539 .fn = do_winbind_online,
1540 .help = "Ask winbind to go into online state"},
1543 .fn = do_winbind_offline,
1544 .help = "Ask winbind to go into offline state"},
1546 .name = "onlinestatus",
1547 .fn = do_winbind_onlinestatus,
1548 .help = "Request winbind online status"},
1550 .name = "validate-cache" ,
1551 .fn = do_winbind_validate_cache,
1552 .help = "Validate winbind's credential cache",
1555 .name = "dump-domain-list",
1556 .fn = do_winbind_dump_domain_list,
1557 .help = "Dump winbind domain list"},
1559 .name = "disconnect-dc",
1560 .fn = do_msg_disconnect_dc,
1563 .name = "notify-cleanup",
1564 .fn = do_notify_cleanup,
1567 .name = "num-children",
1568 .fn = do_num_children,
1569 .help = "Print number of smbd child processes",
1572 .name = "msg-cleanup",
1573 .fn = do_msg_cleanup,
1578 .help = "Do nothing",
1583 .help = "Cause the target process to sleep",
1588 /* Display usage information */
1590 static void usage(poptContext pc)
1594 poptPrintHelp(pc, stderr, 0);
1596 fprintf(stderr, "\n");
1597 fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1600 fprintf(stderr, "\n");
1601 fprintf(stderr, "<message-type> is one of:\n");
1603 for (i = 0; msg_types[i].name; i++)
1604 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name,
1607 fprintf(stderr, "\n");
1612 /* Return the pid number for a string destination */
1614 static struct server_id parse_dest(struct messaging_context *msg,
1617 struct server_id result = {
1618 .pid = (uint64_t)-1,
1622 /* Zero is a special return value for broadcast to all processes */
1624 if (strequal(dest, "all")) {
1625 return interpret_pid(MSG_BROADCAST_PID_STR);
1628 /* Try self - useful for testing */
1630 if (strequal(dest, "self")) {
1631 return messaging_server_id(msg);
1634 /* Fix winbind typo. */
1635 if (strequal(dest, "winbind")) {
1639 /* Check for numeric pid number */
1640 result = interpret_pid(dest);
1642 /* Zero isn't valid if not "all". */
1643 if (result.pid && procid_valid(&result)) {
1647 /* Look up other destinations in pidfile directory */
1649 if ((pid = pidfile_pid(lp_pid_directory(), dest)) != 0) {
1650 return pid_to_procid(pid);
1653 fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1658 /* Execute smbcontrol command */
1660 static bool do_command(struct tevent_context *ev_ctx,
1661 struct messaging_context *msg_ctx,
1662 int argc, const char **argv)
1664 const char *dest = argv[0], *command = argv[1];
1665 struct server_id pid;
1668 /* Check destination */
1670 pid = parse_dest(msg_ctx, dest);
1671 if (!procid_valid(&pid)) {
1677 for (i = 0; msg_types[i].name; i++) {
1678 if (strequal(command, msg_types[i].name))
1679 return msg_types[i].fn(ev_ctx, msg_ctx, pid,
1680 argc - 1, argv + 1);
1683 fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1688 static void smbcontrol_help(poptContext pc,
1689 enum poptCallbackReason preason,
1690 struct poptOption * poption,
1694 if (poption->shortName != '?') {
1695 poptPrintUsage(pc, stdout, 0);
1703 struct poptOption help_options[] = {
1704 { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1706 { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1707 { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1713 int main(int argc, const char **argv)
1717 struct tevent_context *evt_ctx;
1718 struct messaging_context *msg_ctx;
1720 static struct poptOption long_options[] = {
1722 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1723 0, "Help options:", NULL },
1724 { "timeout", 't', POPT_ARG_INT, &timeout, 't',
1725 "Set timeout value in seconds", "TIMEOUT" },
1730 TALLOC_CTX *frame = talloc_stackframe();
1735 setup_logging(argv[0], DEBUG_STDOUT);
1736 lp_set_cmdline("log level", "0");
1738 /* Parse command line arguments using popt */
1740 pc = poptGetContext(
1741 "smbcontrol", argc, (const char **)argv, long_options, 0);
1743 poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1749 while ((opt = poptGetNextOpt(pc)) != -1) {
1751 case 't': /* --timeout */
1754 fprintf(stderr, "Invalid option\n");
1755 poptPrintHelp(pc, stderr, 0);
1760 /* We should now have the remaining command line arguments in
1761 argv. The argc parameter should have been decremented to the
1762 correct value in the above switch statement. */
1764 argv = (const char **)poptGetArgs(pc);
1767 while (argv[argc] != NULL) {
1775 msg_ctx = cmdline_messaging_context(get_dyn_CONFIGFILE());
1776 if (msg_ctx == NULL) {
1778 "Could not init messaging context, not root?\n");
1783 evt_ctx = global_event_context();
1785 lp_load_global(get_dyn_CONFIGFILE());
1787 /* Need to invert sense of return code -- samba
1788 * routines mostly return True==1 for success, but
1791 ret = !do_command(evt_ctx, msg_ctx, argc, argv);