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 /* Send no message. Useful for testing. */
130 static bool do_noop(struct tevent_context *ev_ctx,
131 struct messaging_context *msg_ctx,
132 const struct server_id pid,
133 const int argc, const char **argv)
136 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
140 /* Move along, nothing to see here */
145 /* Send a debug string */
147 static bool do_debug(struct tevent_context *ev_ctx,
148 struct messaging_context *msg_ctx,
149 const struct server_id pid,
150 const int argc, const char **argv)
153 fprintf(stderr, "Usage: smbcontrol <dest> debug "
158 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
159 strlen(argv[1]) + 1);
163 static bool do_idmap(struct tevent_context *ev,
164 struct messaging_context *msg_ctx,
165 const struct server_id pid,
166 const int argc, const char **argv)
168 static const char* usage = "Usage: "
169 "smbcontrol <dest> idmap <cmd> [arg]\n"
171 "\tdelete \"UID <uid>\"|\"GID <gid>\"|<sid>\n"
172 "\t\tkill \"UID <uid>\"|\"GID <gid>\"|<sid>\n";
173 const char* arg = NULL;
182 arglen = strlen(arg) + 1;
185 fprintf(stderr, "%s", usage);
189 if (strcmp(argv[1], "delete") == 0) {
190 msg_type = ID_CACHE_DELETE;
192 else if (strcmp(argv[1], "kill") == 0) {
193 msg_type = ID_CACHE_KILL;
195 else if (strcmp(argv[1], "help") == 0) {
196 fprintf(stdout, "%s", usage);
200 fprintf(stderr, "%s", usage);
204 return send_message(msg_ctx, pid, msg_type, arg, arglen);
208 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
210 /* Return the name of a process given it's PID. This will only work on Linux,
211 * but that's probably moot since this whole stack tracing implementation is
212 * Linux-specific anyway.
214 static const char * procname(pid_t pid, char * buf, size_t bufsz)
219 snprintf(path, sizeof(path), "/proc/%llu/cmdline",
220 (unsigned long long)pid);
221 if ((fp = fopen(path, "r")) == NULL) {
225 fgets(buf, bufsz, fp);
231 static void print_stack_trace(pid_t pid, int * count)
234 unw_addr_space_t aspace = NULL;
243 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
245 "Failed to attach to process %llu: %s\n",
246 (unsigned long long)pid, strerror(errno));
250 /* Wait until the attach is complete. */
251 waitpid(pid, NULL, 0);
253 if (((pinfo = _UPT_create(pid)) == NULL) ||
254 ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
255 /* Probably out of memory. */
257 "Unable to initialize stack unwind for process %llu\n",
258 (unsigned long long)pid);
262 if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
264 "Unable to unwind stack for process %llu: %s\n",
265 (unsigned long long)pid, unw_strerror(ret));
273 if (procname(pid, nbuf, sizeof(nbuf))) {
274 printf("Stack trace for process %llu (%s):\n",
275 (unsigned long long)pid, nbuf);
277 printf("Stack trace for process %llu:\n",
278 (unsigned long long)pid);
281 while (unw_step(&cursor) > 0) {
283 unw_get_reg(&cursor, UNW_REG_IP, &ip);
284 unw_get_reg(&cursor, UNW_REG_SP, &sp);
286 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
287 if (ret != 0 && ret != -UNW_ENOMEM) {
288 snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
290 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
291 nbuf, (long long)off, (long long)ip,
299 unw_destroy_addr_space(aspace);
306 ptrace(PTRACE_DETACH, pid, NULL, NULL);
309 static int stack_trace_server(pid_t pid, void *priv)
311 print_stack_trace(pid, (int *)priv);
315 static bool do_daemon_stack_trace(struct tevent_context *ev_ctx,
316 struct messaging_context *msg_ctx,
317 const struct server_id pid,
318 const int argc, const char **argv)
324 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
328 dest = procid_to_pid(&pid);
331 /* It would be nice to be able to make sure that this PID is
332 * the PID of a smbd/winbind/nmbd process, not some random PID
333 * the user liked the look of. It doesn't seem like it's worth
334 * the effort at the moment, however.
336 print_stack_trace(dest, &count);
338 messaging_dgm_forall(stack_trace_server, &count);
344 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
346 static bool do_daemon_stack_trace(struct tevent_context *ev_ctx,
347 struct messaging_context *msg_ctx,
348 const struct server_id pid,
349 const int argc, const char **argv)
352 "Daemon stack tracing is not supported on this platform\n");
356 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
358 /* Inject a fault (fatal signal) into a running smbd */
360 static bool do_inject_fault(struct tevent_context *ev_ctx,
361 struct messaging_context *msg_ctx,
362 const struct server_id pid,
363 const int argc, const char **argv)
366 fprintf(stderr, "Usage: smbcontrol <dest> inject "
367 "<bus|hup|term|internal|segv>\n");
371 #if !defined(DEVELOPER) && !defined(ENABLE_SELFTEST)
372 fprintf(stderr, "Fault injection is only available in "
373 "developer and self test builds\n");
375 #else /* DEVELOPER || ENABLE_SELFTEST */
379 if (strcmp(argv[1], "bus") == 0) {
381 } else if (strcmp(argv[1], "hup") == 0) {
383 } else if (strcmp(argv[1], "term") == 0) {
385 } else if (strcmp(argv[1], "segv") == 0) {
387 } else if (strcmp(argv[1], "internal") == 0) {
388 /* Force an internal error, ie. an unclean exit. */
391 fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
395 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
398 #endif /* DEVELOPER || ENABLE_SELFTEST */
401 static bool do_sleep(struct tevent_context *ev_ctx,
402 struct messaging_context *msg_ctx,
403 const struct server_id pid,
404 const int argc, const char **argv)
406 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
407 unsigned int seconds;
409 const long MAX_SLEEP = 60 * 60; /* One hour maximum sleep */
413 fprintf(stderr, "Usage: smbcontrol <dest> sleep seconds\n");
417 #if !defined(DEVELOPER) && !defined(ENABLE_SELFTEST)
418 fprintf(stderr, "Sleep is only available in "
419 "developer and self test builds\n");
421 #else /* DEVELOPER || ENABLE_SELFTEST */
423 input = atol(argv[1]);
424 if (input < 1 || input > MAX_SLEEP) {
426 "Invalid duration for sleep '%s'\n"
427 "It should be at least 1 second and no more than %ld\n",
433 return send_message(msg_ctx, pid,
436 sizeof(unsigned int));
437 #endif /* DEVELOPER || ENABLE_SELFTEST */
440 /* Force a browser election */
442 static bool do_election(struct tevent_context *ev_ctx,
443 struct messaging_context *msg_ctx,
444 const struct server_id pid,
445 const int argc, const char **argv)
448 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
452 return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
455 /* Ping a samba daemon process */
457 static void pong_cb(struct messaging_context *msg,
460 struct server_id pid,
463 struct server_id_buf src_string;
464 printf("PONG from pid %s\n", server_id_str_buf(pid, &src_string));
468 static bool do_ping(struct tevent_context *ev_ctx,
469 struct messaging_context *msg_ctx,
470 const struct server_id pid,
471 const int argc, const char **argv)
474 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
478 /* Send a message and register our interest in a reply */
480 if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
483 messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
485 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
487 /* No replies were received within the timeout period */
489 if (num_replies == 0)
490 printf("No replies received\n");
492 messaging_deregister(msg_ctx, MSG_PONG, NULL);
497 /* Set profiling options */
499 static bool do_profile(struct tevent_context *ev_ctx,
500 struct messaging_context *msg_ctx,
501 const struct server_id pid,
502 const int argc, const char **argv)
507 fprintf(stderr, "Usage: smbcontrol <dest> profile "
508 "<off|count|on|flush>\n");
512 if (strcmp(argv[1], "off") == 0) {
514 } else if (strcmp(argv[1], "count") == 0) {
516 } else if (strcmp(argv[1], "on") == 0) {
518 } else if (strcmp(argv[1], "flush") == 0) {
521 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
525 return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
528 /* Return the profiling level */
530 static void profilelevel_cb(struct messaging_context *msg_ctx,
533 struct server_id pid,
541 if (data->length != sizeof(int)) {
542 fprintf(stderr, "invalid message length %ld returned\n",
543 (unsigned long)data->length);
547 memcpy(&level, data->data, sizeof(int));
560 s = "count and time";
567 printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
570 static void profilelevel_rqst(struct messaging_context *msg_ctx,
573 struct server_id pid,
578 /* Send back a dummy reply */
580 send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
583 static bool do_profilelevel(struct tevent_context *ev_ctx,
584 struct messaging_context *msg_ctx,
585 const struct server_id pid,
586 const int argc, const char **argv)
589 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
593 /* Send a message and register our interest in a reply */
595 if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
598 messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
599 messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
602 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
604 /* No replies were received within the timeout period */
606 if (num_replies == 0)
607 printf("No replies received\n");
609 messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
614 /* Display debug level settings */
616 static bool do_debuglevel(struct tevent_context *ev_ctx,
617 struct messaging_context *msg_ctx,
618 const struct server_id pid,
619 const int argc, const char **argv)
622 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
626 /* Send a message and register our interest in a reply */
628 if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
631 messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
633 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
635 /* No replies were received within the timeout period */
637 if (num_replies == 0)
638 printf("No replies received\n");
640 messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
645 /* Send a print notify message */
647 static bool do_printnotify(struct tevent_context *ev_ctx,
648 struct messaging_context *msg_ctx,
649 const struct server_id pid,
650 const int argc, const char **argv)
654 /* Check for subcommand */
657 fprintf(stderr, "Must specify subcommand:\n");
658 fprintf(stderr, "\tqueuepause <printername>\n");
659 fprintf(stderr, "\tqueueresume <printername>\n");
660 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
661 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
662 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
663 fprintf(stderr, "\tprinter <printername> <comment|port|"
664 "driver> <value>\n");
671 if (strcmp(cmd, "queuepause") == 0) {
674 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
675 " queuepause <printername>\n");
679 notify_printer_status_byname(ev_ctx, msg_ctx, argv[2],
680 PRINTER_STATUS_PAUSED);
684 } else if (strcmp(cmd, "queueresume") == 0) {
687 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
688 " queuereume <printername>\n");
692 notify_printer_status_byname(ev_ctx, msg_ctx, argv[2],
697 } else if (strcmp(cmd, "jobpause") == 0) {
701 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
702 " jobpause <printername> <unix-jobid>\n");
706 jobid = atoi(argv[3]);
708 notify_job_status_byname(
710 argv[2], jobid, JOB_STATUS_PAUSED,
711 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
715 } else if (strcmp(cmd, "jobresume") == 0) {
719 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
720 " jobpause <printername> <unix-jobid>\n");
724 jobid = atoi(argv[3]);
726 notify_job_status_byname(
728 argv[2], jobid, JOB_STATUS_QUEUED,
729 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
733 } else if (strcmp(cmd, "jobdelete") == 0) {
737 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
738 " jobpause <printername> <unix-jobid>\n");
742 jobid = atoi(argv[3]);
744 notify_job_status_byname(
746 argv[2], jobid, JOB_STATUS_DELETING,
747 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
749 notify_job_status_byname(
751 argv[2], jobid, JOB_STATUS_DELETING|
753 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
757 } else if (strcmp(cmd, "printer") == 0) {
761 fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
762 "printer <printername> <comment|port|driver> "
767 if (strcmp(argv[3], "comment") == 0) {
768 attribute = PRINTER_NOTIFY_FIELD_COMMENT;
769 } else if (strcmp(argv[3], "port") == 0) {
770 attribute = PRINTER_NOTIFY_FIELD_PORT_NAME;
771 } else if (strcmp(argv[3], "driver") == 0) {
772 attribute = PRINTER_NOTIFY_FIELD_DRIVER_NAME;
774 fprintf(stderr, "Invalid printer command '%s'\n",
779 notify_printer_byname(ev_ctx, msg_ctx, argv[2], attribute,
780 discard_const_p(char, argv[4]));
785 fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
789 print_notify_send_messages(msg_ctx, 0);
795 static bool do_closeshare(struct tevent_context *ev_ctx,
796 struct messaging_context *msg_ctx,
797 const struct server_id pid,
798 const int argc, const char **argv)
801 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
806 return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
807 strlen(argv[1]) + 1);
811 * Close a share if access denied by now
814 static bool do_close_denied_share(
815 struct tevent_context *ev_ctx,
816 struct messaging_context *msg_ctx,
817 const struct server_id pid,
818 const int argc, const char **argv)
821 fprintf(stderr, "Usage: smbcontrol <dest> close-denied-share "
829 MSG_SMB_FORCE_TDIS_DENIED,
831 strlen(argv[1]) + 1);
834 /* Kill a client by IP address */
835 static bool do_kill_client_by_ip(struct tevent_context *ev_ctx,
836 struct messaging_context *msg_ctx,
837 const struct server_id pid,
838 const int argc, const char **argv)
841 fprintf(stderr, "Usage: smbcontrol <dest> kill-client-ip "
846 if (!is_ipaddress_v4(argv[1]) && !is_ipaddress_v6(argv[1])) {
847 fprintf(stderr, "%s is not a valid IP address!\n", argv[1]);
851 return send_message(msg_ctx, pid, MSG_SMB_KILL_CLIENT_IP,
852 argv[1], strlen(argv[1]) + 1);
855 /* Tell winbindd an IP got dropped */
857 static bool do_ip_dropped(struct tevent_context *ev_ctx,
858 struct messaging_context *msg_ctx,
859 const struct server_id pid,
860 const int argc, const char **argv)
863 fprintf(stderr, "Usage: smbcontrol <dest> ip-dropped "
868 return send_message(msg_ctx, pid, MSG_WINBIND_IP_DROPPED, argv[1],
869 strlen(argv[1]) + 1);
872 /* Display talloc pool usage */
874 static bool do_poolusage(struct tevent_context *ev_ctx,
875 struct messaging_context *msg_ctx,
876 const struct server_id dst,
877 const int argc, const char **argv)
879 pid_t pid = procid_to_pid(&dst);
883 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
888 fprintf(stderr, "Can only send to a specific PID\n");
904 /* Fetch and print the ringbuf log */
906 static void print_ringbuf_log_cb(struct messaging_context *msg,
909 struct server_id pid,
912 printf("%s", (const char *)data->data);
916 static bool do_ringbuflog(struct tevent_context *ev_ctx,
917 struct messaging_context *msg_ctx,
918 const struct server_id pid,
919 const int argc, const char **argv)
922 fprintf(stderr, "Usage: smbcontrol <dest> ringbuf-log\n");
926 messaging_register(msg_ctx, NULL, MSG_RINGBUF_LOG,
927 print_ringbuf_log_cb);
929 /* Send a message and register our interest in a reply */
931 if (!send_message(msg_ctx, pid, MSG_REQ_RINGBUF_LOG, NULL, 0)) {
935 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
937 /* No replies were received within the timeout period */
939 if (num_replies == 0) {
940 printf("No replies received\n");
943 messaging_deregister(msg_ctx, MSG_RINGBUF_LOG, NULL);
945 return num_replies != 0;
948 /* Perform a dmalloc mark */
950 static bool do_dmalloc_mark(struct tevent_context *ev_ctx,
951 struct messaging_context *msg_ctx,
952 const struct server_id pid,
953 const int argc, const char **argv)
956 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
960 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
963 /* Perform a dmalloc changed */
965 static bool do_dmalloc_changed(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> "
972 "dmalloc-log-changed\n");
976 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
980 static void print_uint32_cb(struct messaging_context *msg, void *private_data,
981 uint32_t msg_type, struct server_id pid,
984 uint32_t num_children;
986 if (data->length != sizeof(uint32_t)) {
987 printf("Invalid response: %d bytes long\n",
991 num_children = IVAL(data->data, 0);
992 printf("%u children\n", (unsigned)num_children);
997 static bool do_num_children(struct tevent_context *ev_ctx,
998 struct messaging_context *msg_ctx,
999 const struct server_id pid,
1000 const int argc, const char **argv)
1003 fprintf(stderr, "Usage: smbcontrol <dest> num-children\n");
1007 messaging_register(msg_ctx, NULL, MSG_SMB_NUM_CHILDREN,
1010 /* Send a message and register our interest in a reply */
1012 if (!send_message(msg_ctx, pid, MSG_SMB_TELL_NUM_CHILDREN, NULL, 0))
1015 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1017 /* No replies were received within the timeout period */
1019 if (num_replies == 0)
1020 printf("No replies received\n");
1022 messaging_deregister(msg_ctx, MSG_SMB_NUM_CHILDREN, NULL);
1027 static bool do_msg_cleanup(struct tevent_context *ev_ctx,
1028 struct messaging_context *msg_ctx,
1029 const struct server_id pid,
1030 const int argc, const char **argv)
1034 ret = messaging_cleanup(msg_ctx, pid.pid);
1036 printf("cleanup(%u) returned %s\n", (unsigned)pid.pid,
1037 ret ? strerror(ret) : "ok");
1042 /* Shutdown a server process */
1044 static bool do_shutdown(struct tevent_context *ev_ctx,
1045 struct messaging_context *msg_ctx,
1046 const struct server_id pid,
1047 const int argc, const char **argv)
1050 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
1054 return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
1057 /* Notify a driver upgrade */
1059 static bool do_drvupgrade(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> drvupgrade "
1070 return send_message(msg_ctx, pid, MSG_PRINTER_DRVUPGRADE, argv[1],
1071 strlen(argv[1]) + 1);
1074 static bool do_winbind_online(struct tevent_context *ev_ctx,
1075 struct messaging_context *msg_ctx,
1076 const struct server_id pid,
1077 const int argc, const char **argv)
1083 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
1087 db_path = state_path(talloc_tos(), "winbindd_cache.tdb");
1088 if (db_path == NULL) {
1092 /* Remove the entry in the winbindd_cache tdb to tell a later
1093 starting winbindd that we're online. */
1095 tdb = tdb_open_log(db_path, 0, TDB_DEFAULT, O_RDWR, 0600);
1097 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
1099 TALLOC_FREE(db_path);
1103 TALLOC_FREE(db_path);
1104 tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
1107 return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
1110 static bool do_winbind_offline(struct tevent_context *ev_ctx,
1111 struct messaging_context *msg_ctx,
1112 const struct server_id pid,
1113 const int argc, const char **argv)
1121 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
1125 db_path = state_path(talloc_tos(), "winbindd_cache.tdb");
1126 if (db_path == NULL) {
1130 /* Create an entry in the winbindd_cache tdb to tell a later
1131 starting winbindd that we're offline. We may actually create
1134 tdb = tdb_open_log(db_path,
1135 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
1136 TDB_DEFAULT|TDB_INCOMPATIBLE_HASH /* TDB_CLEAR_IF_FIRST */,
1137 O_RDWR|O_CREAT, 0600);
1140 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
1142 TALLOC_FREE(db_path);
1145 TALLOC_FREE(db_path);
1147 /* There's a potential race condition that if a child
1148 winbindd detects a domain is online at the same time
1149 we're trying to tell it to go offline that it might
1150 delete the record we add between us adding it and
1151 sending the message. Minimize this by retrying up to
1154 for (retry = 0; retry < 5; retry++) {
1156 TDB_DATA d = { .dptr = buf, .dsize = sizeof(buf) };
1158 SIVAL(buf, 0, time(NULL));
1160 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
1162 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
1165 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
1166 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
1167 if (d.dptr != NULL && d.dsize == 4) {
1173 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
1180 static bool do_winbind_onlinestatus(struct tevent_context *ev_ctx,
1181 struct messaging_context *msg_ctx,
1182 const struct server_id pid,
1183 const int argc, const char **argv)
1186 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
1190 messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
1191 print_pid_string_cb);
1193 if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, NULL, 0)) {
1197 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1199 /* No replies were received within the timeout period */
1201 if (num_replies == 0)
1202 printf("No replies received\n");
1204 messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
1209 static bool do_winbind_dump_domain_list(struct tevent_context *ev_ctx,
1210 struct messaging_context *msg_ctx,
1211 const struct server_id pid,
1212 const int argc, const char **argv)
1214 const char *domain = NULL;
1217 if (argc < 1 || argc > 2) {
1218 fprintf(stderr, "Usage: smbcontrol <dest> dump-domain-list "
1225 domain_len = strlen(argv[1]) + 1;
1228 messaging_register(msg_ctx, NULL, MSG_WINBIND_DUMP_DOMAIN_LIST,
1229 print_pid_string_cb);
1231 if (!send_message(msg_ctx, pid, MSG_WINBIND_DUMP_DOMAIN_LIST,
1232 domain, domain_len))
1237 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1239 /* No replies were received within the timeout period */
1241 if (num_replies == 0) {
1242 printf("No replies received\n");
1245 messaging_deregister(msg_ctx, MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
1250 static bool do_msg_disconnect_dc(struct tevent_context *ev_ctx,
1251 struct messaging_context *msg_ctx,
1252 const struct server_id pid,
1253 const int argc, const char **argv)
1256 fprintf(stderr, "Usage: smbcontrol <dest> disconnect-dc\n");
1260 return send_message(msg_ctx, pid, MSG_WINBIND_DISCONNECT_DC, NULL, 0);
1263 static void winbind_validate_cache_cb(struct messaging_context *msg,
1266 struct server_id pid,
1269 struct server_id_buf src_string;
1270 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1271 (*(data->data) == 0 ? "" : "NOT "),
1272 server_id_str_buf(pid, &src_string));
1276 static bool do_winbind_validate_cache(struct tevent_context *ev_ctx,
1277 struct messaging_context *msg_ctx,
1278 const struct server_id pid,
1279 const int argc, const char **argv)
1281 struct server_id myid;
1283 myid = messaging_server_id(msg_ctx);
1286 fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
1290 messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
1291 winbind_validate_cache_cb);
1293 if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
1298 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1300 if (num_replies == 0) {
1301 printf("No replies received\n");
1304 messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);
1309 static bool do_reload_config(struct tevent_context *ev_ctx,
1310 struct messaging_context *msg_ctx,
1311 const struct server_id pid,
1312 const int argc, const char **argv)
1315 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1319 return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1322 static bool do_reload_printers(struct tevent_context *ev_ctx,
1323 struct messaging_context *msg_ctx,
1324 const struct server_id pid,
1325 const int argc, const char **argv)
1328 fprintf(stderr, "Usage: smbcontrol <dest> reload-printers\n");
1332 return send_message(msg_ctx, pid, MSG_PRINTER_PCAP, NULL, 0);
1335 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1338 memset( (char *)n, '\0', sizeof(struct nmb_name) );
1339 fstrcpy(unix_name, name);
1340 (void)strupper_m(unix_name);
1341 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1342 n->name_type = (unsigned int)type & 0xFF;
1343 push_ascii(n->scope, lp_netbios_scope(), 64, STR_TERMINATE);
1346 static bool do_nodestatus(struct tevent_context *ev_ctx,
1347 struct messaging_context *msg_ctx,
1348 const struct server_id pid,
1349 const int argc, const char **argv)
1351 struct packet_struct p;
1354 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1360 p.ip = interpret_addr2(argv[1]);
1362 p.packet_type = NMB_PACKET;
1364 p.packet.nmb.header.name_trn_id = 10;
1365 p.packet.nmb.header.opcode = 0;
1366 p.packet.nmb.header.response = False;
1367 p.packet.nmb.header.nm_flags.bcast = False;
1368 p.packet.nmb.header.nm_flags.recursion_available = False;
1369 p.packet.nmb.header.nm_flags.recursion_desired = False;
1370 p.packet.nmb.header.nm_flags.trunc = False;
1371 p.packet.nmb.header.nm_flags.authoritative = False;
1372 p.packet.nmb.header.rcode = 0;
1373 p.packet.nmb.header.qdcount = 1;
1374 p.packet.nmb.header.ancount = 0;
1375 p.packet.nmb.header.nscount = 0;
1376 p.packet.nmb.header.arcount = 0;
1377 my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1378 p.packet.nmb.question.question_type = 0x21;
1379 p.packet.nmb.question.question_class = 0x1;
1381 return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1384 static bool do_notify_cleanup(struct tevent_context *ev_ctx,
1385 struct messaging_context *msg_ctx,
1386 const struct server_id pid,
1387 const int argc, const char **argv)
1390 fprintf(stderr, "Usage: smbcontrol smbd notify-cleanup\n");
1393 return send_message(msg_ctx, pid, MSG_SMB_NOTIFY_CLEANUP, NULL, 0);
1396 /* A list of message type supported */
1398 static const struct {
1399 const char *name; /* Option name */
1400 bool (*fn)(struct tevent_context *ev_ctx,
1401 struct messaging_context *msg_ctx,
1402 const struct server_id pid,
1403 const int argc, const char **argv);
1404 const char *help; /* Short help text */
1409 .help = "Set debuglevel",
1414 .help = "Manipulate idmap cache",
1417 .name = "force-election",
1419 .help = "Force a browse election",
1424 .help = "Elicit a response",
1433 .fn = do_inject_fault,
1434 .help = "Inject a fatal signal into a running smbd"},
1436 .name = "stacktrace",
1437 .fn = do_daemon_stack_trace,
1438 .help = "Display a stack trace of a daemon",
1441 .name = "profilelevel",
1442 .fn = do_profilelevel,
1446 .name = "debuglevel",
1447 .fn = do_debuglevel,
1448 .help = "Display current debuglevels",
1451 .name = "printnotify",
1452 .fn = do_printnotify,
1453 .help = "Send a print notify message",
1456 .name = "close-share",
1457 .fn = do_closeshare,
1458 .help = "Forcibly disconnect a share",
1461 .name = "close-denied-share",
1462 .fn = do_close_denied_share,
1463 .help = "Forcibly disconnect users from shares disallowed now",
1466 .name = "kill-client-ip",
1467 .fn = do_kill_client_by_ip,
1468 .help = "Forcibly disconnect a client with a specific IP address",
1471 .name = "ip-dropped",
1472 .fn = do_ip_dropped,
1473 .help = "Tell winbind that an IP got dropped",
1476 .name = "pool-usage",
1478 .help = "Display talloc memory usage",
1481 .name = "ringbuf-log",
1482 .fn = do_ringbuflog,
1483 .help = "Display ringbuf log",
1486 .name = "dmalloc-mark",
1487 .fn = do_dmalloc_mark,
1491 .name = "dmalloc-log-changed",
1492 .fn = do_dmalloc_changed,
1498 .help = "Shut down daemon",
1501 .name = "drvupgrade",
1502 .fn = do_drvupgrade,
1503 .help = "Notify a printer driver has changed",
1506 .name = "reload-config",
1507 .fn = do_reload_config,
1508 .help = "Force smbd or winbindd to reload config file"},
1510 .name = "reload-printers",
1511 .fn = do_reload_printers,
1512 .help = "Force smbd to reload printers"},
1514 .name = "nodestatus",
1515 .fn = do_nodestatus,
1516 .help = "Ask nmbd to do a node status request"},
1519 .fn = do_winbind_online,
1520 .help = "Ask winbind to go into online state"},
1523 .fn = do_winbind_offline,
1524 .help = "Ask winbind to go into offline state"},
1526 .name = "onlinestatus",
1527 .fn = do_winbind_onlinestatus,
1528 .help = "Request winbind online status"},
1530 .name = "validate-cache" ,
1531 .fn = do_winbind_validate_cache,
1532 .help = "Validate winbind's credential cache",
1535 .name = "dump-domain-list",
1536 .fn = do_winbind_dump_domain_list,
1537 .help = "Dump winbind domain list"},
1539 .name = "disconnect-dc",
1540 .fn = do_msg_disconnect_dc,
1543 .name = "notify-cleanup",
1544 .fn = do_notify_cleanup,
1547 .name = "num-children",
1548 .fn = do_num_children,
1549 .help = "Print number of smbd child processes",
1552 .name = "msg-cleanup",
1553 .fn = do_msg_cleanup,
1558 .help = "Do nothing",
1563 .help = "Cause the target process to sleep",
1568 /* Display usage information */
1570 static void usage(poptContext pc)
1574 poptPrintHelp(pc, stderr, 0);
1576 fprintf(stderr, "\n");
1577 fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1580 fprintf(stderr, "\n");
1581 fprintf(stderr, "<message-type> is one of:\n");
1583 for (i = 0; msg_types[i].name; i++) {
1584 const char *help = msg_types[i].help;
1588 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name, help);
1591 fprintf(stderr, "\n");
1596 /* Return the pid number for a string destination */
1598 static struct server_id parse_dest(struct messaging_context *msg,
1601 struct server_id result = {
1602 .pid = (uint64_t)-1,
1606 /* Zero is a special return value for broadcast to all processes */
1608 if (strequal(dest, "all")) {
1609 return interpret_pid(MSG_BROADCAST_PID_STR);
1612 /* Try self - useful for testing */
1614 if (strequal(dest, "self")) {
1615 return messaging_server_id(msg);
1618 /* Fix winbind typo. */
1619 if (strequal(dest, "winbind")) {
1623 /* Check for numeric pid number */
1624 result = interpret_pid(dest);
1626 /* Zero isn't valid if not "all". */
1627 if (result.pid && procid_valid(&result)) {
1631 /* Look up other destinations in pidfile directory */
1633 if ((pid = pidfile_pid(lp_pid_directory(), dest)) != 0) {
1634 return pid_to_procid(pid);
1637 fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1642 /* Execute smbcontrol command */
1644 static bool do_command(struct tevent_context *ev_ctx,
1645 struct messaging_context *msg_ctx,
1646 int argc, const char **argv)
1648 const char *dest = argv[0], *command = argv[1];
1649 struct server_id pid;
1652 /* Check destination */
1654 pid = parse_dest(msg_ctx, dest);
1655 if (!procid_valid(&pid)) {
1661 for (i = 0; msg_types[i].name; i++) {
1662 if (strequal(command, msg_types[i].name))
1663 return msg_types[i].fn(ev_ctx, msg_ctx, pid,
1664 argc - 1, argv + 1);
1667 fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1672 static void smbcontrol_help(poptContext pc,
1673 enum poptCallbackReason preason,
1674 struct poptOption * poption,
1678 if (poption->shortName != '?') {
1679 poptPrintUsage(pc, stdout, 0);
1687 struct poptOption help_options[] = {
1688 { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1690 { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1691 { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1697 int main(int argc, const char **argv)
1701 struct tevent_context *evt_ctx;
1702 struct messaging_context *msg_ctx;
1704 static struct poptOption long_options[] = {
1706 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1707 0, "Help options:", NULL },
1708 { "timeout", 't', POPT_ARG_INT, &timeout, 't',
1709 "Set timeout value in seconds", "TIMEOUT" },
1714 TALLOC_CTX *frame = talloc_stackframe();
1719 setup_logging(argv[0], DEBUG_STDOUT);
1720 lp_set_cmdline("log level", "0");
1722 /* Parse command line arguments using popt */
1724 pc = poptGetContext(
1725 "smbcontrol", argc, (const char **)argv, long_options, 0);
1727 poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1733 while ((opt = poptGetNextOpt(pc)) != -1) {
1735 case 't': /* --timeout */
1738 fprintf(stderr, "Invalid option\n");
1739 poptPrintHelp(pc, stderr, 0);
1744 /* We should now have the remaining command line arguments in
1745 argv. The argc parameter should have been decremented to the
1746 correct value in the above switch statement. */
1748 argv = (const char **)poptGetArgs(pc);
1751 while (argv[argc] != NULL) {
1759 msg_ctx = cmdline_messaging_context(get_dyn_CONFIGFILE());
1760 if (msg_ctx == NULL) {
1762 "Could not init messaging context, not root?\n");
1767 evt_ctx = global_event_context();
1769 lp_load_global(get_dyn_CONFIGFILE());
1771 /* Need to invert sense of return code -- samba
1772 * routines mostly return True==1 for success, but
1775 ret = !do_command(evt_ctx, msg_ctx, argc, argv);
1777 poptFreeContext(pc);