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
)
64 if (procid_to_pid(&pid
) != 0)
65 return NT_STATUS_IS_OK(
66 messaging_send_buf(msg_ctx
, pid
, msg_type
,
67 (const uint8_t *)buf
, len
));
69 messaging_send_all(msg_ctx
, msg_type
, buf
, len
);
74 static void smbcontrol_timeout(struct tevent_context
*event_ctx
,
75 struct tevent_timer
*te
,
79 bool *timed_out
= (bool *)private_data
;
84 /* Wait for one or more reply messages */
86 static void wait_replies(struct tevent_context
*ev_ctx
,
87 struct messaging_context
*msg_ctx
,
88 bool multiple_replies
)
90 struct tevent_timer
*te
;
91 bool timed_out
= False
;
93 te
= tevent_add_timer(ev_ctx
, NULL
,
94 timeval_current_ofs(timeout
, 0),
95 smbcontrol_timeout
, (void *)&timed_out
);
97 DEBUG(0, ("tevent_add_timer failed\n"));
103 if (num_replies
> 0 && !multiple_replies
)
105 ret
= tevent_loop_once(ev_ctx
);
112 /* Message handler callback that displays the PID and a string on stdout */
114 static void print_pid_string_cb(struct messaging_context
*msg
,
117 struct server_id pid
,
120 struct server_id_buf pidstr
;
122 printf("PID %s: %.*s", server_id_str_buf(pid
, &pidstr
),
123 (int)data
->length
, (const char *)data
->data
);
127 /* Message handler callback that displays a string on stdout */
129 static void print_string_cb(struct messaging_context
*msg
,
132 struct server_id pid
,
135 printf("%*s", (int)data
->length
, (const char *)data
->data
);
139 /* Send no message. Useful for testing. */
141 static bool do_noop(struct tevent_context
*ev_ctx
,
142 struct messaging_context
*msg_ctx
,
143 const struct server_id pid
,
144 const int argc
, const char **argv
)
147 fprintf(stderr
, "Usage: smbcontrol <dest> noop\n");
151 /* Move along, nothing to see here */
156 /* Send a debug string */
158 static bool do_debug(struct tevent_context
*ev_ctx
,
159 struct messaging_context
*msg_ctx
,
160 const struct server_id pid
,
161 const int argc
, const char **argv
)
164 fprintf(stderr
, "Usage: smbcontrol <dest> debug "
169 return send_message(msg_ctx
, pid
, MSG_DEBUG
, argv
[1],
170 strlen(argv
[1]) + 1);
174 static bool do_idmap(struct tevent_context
*ev
,
175 struct messaging_context
*msg_ctx
,
176 const struct server_id pid
,
177 const int argc
, const char **argv
)
179 static const char* usage
= "Usage: "
180 "smbcontrol <dest> idmap <cmd> [arg]\n"
182 "\tdelete \"UID <uid>\"|\"GID <gid>\"|<sid>\n"
183 "\t\tkill \"UID <uid>\"|\"GID <gid>\"|<sid>\n";
184 const char* arg
= NULL
;
193 arglen
= strlen(arg
) + 1;
196 fprintf(stderr
, "%s", usage
);
200 if (strcmp(argv
[1], "delete") == 0) {
201 msg_type
= ID_CACHE_DELETE
;
203 else if (strcmp(argv
[1], "kill") == 0) {
204 msg_type
= ID_CACHE_KILL
;
206 else if (strcmp(argv
[1], "help") == 0) {
207 fprintf(stdout
, "%s", usage
);
211 fprintf(stderr
, "%s", usage
);
215 return send_message(msg_ctx
, pid
, msg_type
, arg
, arglen
);
219 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
221 /* Return the name of a process given it's PID. This will only work on Linux,
222 * but that's probably moot since this whole stack tracing implementation is
223 * Linux-specific anyway.
225 static const char * procname(pid_t pid
, char * buf
, size_t bufsz
)
230 snprintf(path
, sizeof(path
), "/proc/%llu/cmdline",
231 (unsigned long long)pid
);
232 if ((fp
= fopen(path
, "r")) == NULL
) {
236 fgets(buf
, bufsz
, fp
);
242 static void print_stack_trace(pid_t pid
, int * count
)
245 unw_addr_space_t aspace
= NULL
;
254 if (ptrace(PTRACE_ATTACH
, pid
, NULL
, NULL
) < 0) {
256 "Failed to attach to process %llu: %s\n",
257 (unsigned long long)pid
, strerror(errno
));
261 /* Wait until the attach is complete. */
262 waitpid(pid
, NULL
, 0);
264 if (((pinfo
= _UPT_create(pid
)) == NULL
) ||
265 ((aspace
= unw_create_addr_space(&_UPT_accessors
, 0)) == NULL
)) {
266 /* Probably out of memory. */
268 "Unable to initialize stack unwind for process %llu\n",
269 (unsigned long long)pid
);
273 if ((ret
= unw_init_remote(&cursor
, aspace
, pinfo
))) {
275 "Unable to unwind stack for process %llu: %s\n",
276 (unsigned long long)pid
, unw_strerror(ret
));
284 if (procname(pid
, nbuf
, sizeof(nbuf
))) {
285 printf("Stack trace for process %llu (%s):\n",
286 (unsigned long long)pid
, nbuf
);
288 printf("Stack trace for process %llu:\n",
289 (unsigned long long)pid
);
292 while (unw_step(&cursor
) > 0) {
294 unw_get_reg(&cursor
, UNW_REG_IP
, &ip
);
295 unw_get_reg(&cursor
, UNW_REG_SP
, &sp
);
297 ret
= unw_get_proc_name(&cursor
, nbuf
, sizeof(nbuf
), &off
);
298 if (ret
!= 0 && ret
!= -UNW_ENOMEM
) {
299 snprintf(nbuf
, sizeof(nbuf
), "<unknown symbol>");
301 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
302 nbuf
, (long long)off
, (long long)ip
,
310 unw_destroy_addr_space(aspace
);
317 ptrace(PTRACE_DETACH
, pid
, NULL
, NULL
);
320 static int stack_trace_server(pid_t pid
, void *priv
)
322 print_stack_trace(pid
, (int *)priv
);
326 static bool do_daemon_stack_trace(struct tevent_context
*ev_ctx
,
327 struct messaging_context
*msg_ctx
,
328 const struct server_id pid
,
329 const int argc
, const char **argv
)
335 fprintf(stderr
, "Usage: smbcontrol <dest> stacktrace\n");
339 dest
= procid_to_pid(&pid
);
342 /* It would be nice to be able to make sure that this PID is
343 * the PID of a smbd/winbind/nmbd process, not some random PID
344 * the user liked the look of. It doesn't seem like it's worth
345 * the effort at the moment, however.
347 print_stack_trace(dest
, &count
);
349 messaging_dgm_forall(stack_trace_server
, &count
);
355 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
357 static bool do_daemon_stack_trace(struct tevent_context
*ev_ctx
,
358 struct messaging_context
*msg_ctx
,
359 const struct server_id pid
,
360 const int argc
, const char **argv
)
363 "Daemon stack tracing is not supported on this platform\n");
367 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
369 /* Inject a fault (fatal signal) into a running smbd */
371 static bool do_inject_fault(struct tevent_context
*ev_ctx
,
372 struct messaging_context
*msg_ctx
,
373 const struct server_id pid
,
374 const int argc
, const char **argv
)
377 fprintf(stderr
, "Usage: smbcontrol <dest> inject "
378 "<bus|hup|term|internal|segv>\n");
383 fprintf(stderr
, "Fault injection is only available in "
384 "developer builds\n");
386 #else /* DEVELOPER */
390 if (strcmp(argv
[1], "bus") == 0) {
392 } else if (strcmp(argv
[1], "hup") == 0) {
394 } else if (strcmp(argv
[1], "term") == 0) {
396 } else if (strcmp(argv
[1], "segv") == 0) {
398 } else if (strcmp(argv
[1], "internal") == 0) {
399 /* Force an internal error, ie. an unclean exit. */
402 fprintf(stderr
, "Unknown signal name '%s'\n", argv
[1]);
406 return send_message(msg_ctx
, pid
, MSG_SMB_INJECT_FAULT
,
409 #endif /* DEVELOPER */
412 /* Force a browser election */
414 static bool do_election(struct tevent_context
*ev_ctx
,
415 struct messaging_context
*msg_ctx
,
416 const struct server_id pid
,
417 const int argc
, const char **argv
)
420 fprintf(stderr
, "Usage: smbcontrol <dest> force-election\n");
424 return send_message(msg_ctx
, pid
, MSG_FORCE_ELECTION
, NULL
, 0);
427 /* Ping a samba daemon process */
429 static void pong_cb(struct messaging_context
*msg
,
432 struct server_id pid
,
435 struct server_id_buf src_string
;
436 printf("PONG from pid %s\n", server_id_str_buf(pid
, &src_string
));
440 static bool do_ping(struct tevent_context
*ev_ctx
,
441 struct messaging_context
*msg_ctx
,
442 const struct server_id pid
,
443 const int argc
, const char **argv
)
446 fprintf(stderr
, "Usage: smbcontrol <dest> ping\n");
450 /* Send a message and register our interest in a reply */
452 if (!send_message(msg_ctx
, pid
, MSG_PING
, NULL
, 0))
455 messaging_register(msg_ctx
, NULL
, MSG_PONG
, pong_cb
);
457 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
459 /* No replies were received within the timeout period */
461 if (num_replies
== 0)
462 printf("No replies received\n");
464 messaging_deregister(msg_ctx
, MSG_PONG
, NULL
);
469 /* Set profiling options */
471 static bool do_profile(struct tevent_context
*ev_ctx
,
472 struct messaging_context
*msg_ctx
,
473 const struct server_id pid
,
474 const int argc
, const char **argv
)
479 fprintf(stderr
, "Usage: smbcontrol <dest> profile "
480 "<off|count|on|flush>\n");
484 if (strcmp(argv
[1], "off") == 0) {
486 } else if (strcmp(argv
[1], "count") == 0) {
488 } else if (strcmp(argv
[1], "on") == 0) {
490 } else if (strcmp(argv
[1], "flush") == 0) {
493 fprintf(stderr
, "Unknown profile command '%s'\n", argv
[1]);
497 return send_message(msg_ctx
, pid
, MSG_PROFILE
, &v
, sizeof(int));
500 /* Return the profiling level */
502 static void profilelevel_cb(struct messaging_context
*msg_ctx
,
505 struct server_id pid
,
513 if (data
->length
!= sizeof(int)) {
514 fprintf(stderr
, "invalid message length %ld returned\n",
515 (unsigned long)data
->length
);
519 memcpy(&level
, data
->data
, sizeof(int));
532 s
= "count and time";
539 printf("Profiling %s on pid %u\n",s
,(unsigned int)procid_to_pid(&pid
));
542 static void profilelevel_rqst(struct messaging_context
*msg_ctx
,
545 struct server_id pid
,
550 /* Send back a dummy reply */
552 send_message(msg_ctx
, pid
, MSG_PROFILELEVEL
, &v
, sizeof(int));
555 static bool do_profilelevel(struct tevent_context
*ev_ctx
,
556 struct messaging_context
*msg_ctx
,
557 const struct server_id pid
,
558 const int argc
, const char **argv
)
561 fprintf(stderr
, "Usage: smbcontrol <dest> profilelevel\n");
565 /* Send a message and register our interest in a reply */
567 if (!send_message(msg_ctx
, pid
, MSG_REQ_PROFILELEVEL
, NULL
, 0))
570 messaging_register(msg_ctx
, NULL
, MSG_PROFILELEVEL
, profilelevel_cb
);
571 messaging_register(msg_ctx
, NULL
, MSG_REQ_PROFILELEVEL
,
574 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
576 /* No replies were received within the timeout period */
578 if (num_replies
== 0)
579 printf("No replies received\n");
581 messaging_deregister(msg_ctx
, MSG_PROFILE
, NULL
);
586 /* Display debug level settings */
588 static bool do_debuglevel(struct tevent_context
*ev_ctx
,
589 struct messaging_context
*msg_ctx
,
590 const struct server_id pid
,
591 const int argc
, const char **argv
)
594 fprintf(stderr
, "Usage: smbcontrol <dest> debuglevel\n");
598 /* Send a message and register our interest in a reply */
600 if (!send_message(msg_ctx
, pid
, MSG_REQ_DEBUGLEVEL
, NULL
, 0))
603 messaging_register(msg_ctx
, NULL
, MSG_DEBUGLEVEL
, print_pid_string_cb
);
605 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
607 /* No replies were received within the timeout period */
609 if (num_replies
== 0)
610 printf("No replies received\n");
612 messaging_deregister(msg_ctx
, MSG_DEBUGLEVEL
, NULL
);
617 /* Send a print notify message */
619 static bool do_printnotify(struct tevent_context
*ev_ctx
,
620 struct messaging_context
*msg_ctx
,
621 const struct server_id pid
,
622 const int argc
, const char **argv
)
626 /* Check for subcommand */
629 fprintf(stderr
, "Must specify subcommand:\n");
630 fprintf(stderr
, "\tqueuepause <printername>\n");
631 fprintf(stderr
, "\tqueueresume <printername>\n");
632 fprintf(stderr
, "\tjobpause <printername> <unix jobid>\n");
633 fprintf(stderr
, "\tjobresume <printername> <unix jobid>\n");
634 fprintf(stderr
, "\tjobdelete <printername> <unix jobid>\n");
635 fprintf(stderr
, "\tprinter <printername> <comment|port|"
636 "driver> <value>\n");
643 if (strcmp(cmd
, "queuepause") == 0) {
646 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
647 " queuepause <printername>\n");
651 notify_printer_status_byname(ev_ctx
, msg_ctx
, argv
[2],
652 PRINTER_STATUS_PAUSED
);
656 } else if (strcmp(cmd
, "queueresume") == 0) {
659 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
660 " queuereume <printername>\n");
664 notify_printer_status_byname(ev_ctx
, msg_ctx
, argv
[2],
669 } else if (strcmp(cmd
, "jobpause") == 0) {
673 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
674 " jobpause <printername> <unix-jobid>\n");
678 jobid
= atoi(argv
[3]);
680 notify_job_status_byname(
682 argv
[2], jobid
, JOB_STATUS_PAUSED
,
683 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
687 } else if (strcmp(cmd
, "jobresume") == 0) {
691 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
692 " jobpause <printername> <unix-jobid>\n");
696 jobid
= atoi(argv
[3]);
698 notify_job_status_byname(
700 argv
[2], jobid
, JOB_STATUS_QUEUED
,
701 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
705 } else if (strcmp(cmd
, "jobdelete") == 0) {
709 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
710 " jobpause <printername> <unix-jobid>\n");
714 jobid
= atoi(argv
[3]);
716 notify_job_status_byname(
718 argv
[2], jobid
, JOB_STATUS_DELETING
,
719 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
721 notify_job_status_byname(
723 argv
[2], jobid
, JOB_STATUS_DELETING
|
725 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
729 } else if (strcmp(cmd
, "printer") == 0) {
733 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify "
734 "printer <printername> <comment|port|driver> "
739 if (strcmp(argv
[3], "comment") == 0) {
740 attribute
= PRINTER_NOTIFY_FIELD_COMMENT
;
741 } else if (strcmp(argv
[3], "port") == 0) {
742 attribute
= PRINTER_NOTIFY_FIELD_PORT_NAME
;
743 } else if (strcmp(argv
[3], "driver") == 0) {
744 attribute
= PRINTER_NOTIFY_FIELD_DRIVER_NAME
;
746 fprintf(stderr
, "Invalid printer command '%s'\n",
751 notify_printer_byname(ev_ctx
, msg_ctx
, argv
[2], attribute
,
752 discard_const_p(char, argv
[4]));
757 fprintf(stderr
, "Invalid subcommand '%s'\n", cmd
);
761 print_notify_send_messages(msg_ctx
, 0);
767 static bool do_closeshare(struct tevent_context
*ev_ctx
,
768 struct messaging_context
*msg_ctx
,
769 const struct server_id pid
,
770 const int argc
, const char **argv
)
773 fprintf(stderr
, "Usage: smbcontrol <dest> close-share "
778 return send_message(msg_ctx
, pid
, MSG_SMB_FORCE_TDIS
, argv
[1],
779 strlen(argv
[1]) + 1);
782 /* Kill a client by IP address */
783 static bool do_kill_client_by_ip(struct tevent_context
*ev_ctx
,
784 struct messaging_context
*msg_ctx
,
785 const struct server_id pid
,
786 const int argc
, const char **argv
)
789 fprintf(stderr
, "Usage: smbcontrol <dest> kill-client-ip "
794 if (!is_ipaddress_v4(argv
[1]) && !is_ipaddress_v6(argv
[1])) {
795 fprintf(stderr
, "%s is not a valid IP address!\n", argv
[1]);
799 return send_message(msg_ctx
, pid
, MSG_SMB_KILL_CLIENT_IP
,
800 argv
[1], strlen(argv
[1]) + 1);
803 /* Tell winbindd an IP got dropped */
805 static bool do_ip_dropped(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> ip-dropped "
816 return send_message(msg_ctx
, pid
, MSG_WINBIND_IP_DROPPED
, argv
[1],
817 strlen(argv
[1]) + 1);
820 /* force a blocking lock retry */
822 static bool do_lockretry(struct tevent_context
*ev_ctx
,
823 struct messaging_context
*msg_ctx
,
824 const struct server_id pid
,
825 const int argc
, const char **argv
)
828 fprintf(stderr
, "Usage: smbcontrol <dest> lockretry\n");
832 return send_message(msg_ctx
, pid
, MSG_SMB_UNLOCK
, NULL
, 0);
835 /* force a validation of all brl entries, including re-sends. */
837 static bool do_brl_revalidate(struct tevent_context
*ev_ctx
,
838 struct messaging_context
*msg_ctx
,
839 const struct server_id pid
,
840 const int argc
, const char **argv
)
843 fprintf(stderr
, "Usage: smbcontrol <dest> brl-revalidate\n");
847 return send_message(msg_ctx
, pid
, MSG_SMB_BRL_VALIDATE
, NULL
, 0);
850 /* Display talloc pool usage */
852 static bool do_poolusage(struct tevent_context
*ev_ctx
,
853 struct messaging_context
*msg_ctx
,
854 const struct server_id pid
,
855 const int argc
, const char **argv
)
858 fprintf(stderr
, "Usage: smbcontrol <dest> pool-usage\n");
862 messaging_register(msg_ctx
, NULL
, MSG_POOL_USAGE
, print_string_cb
);
864 /* Send a message and register our interest in a reply */
866 if (!send_message(msg_ctx
, pid
, MSG_REQ_POOL_USAGE
, NULL
, 0))
869 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
871 /* No replies were received within the timeout period */
873 if (num_replies
== 0)
874 printf("No replies received\n");
876 messaging_deregister(msg_ctx
, MSG_POOL_USAGE
, NULL
);
881 /* Fetch and print the ringbuf log */
883 static void print_ringbuf_log_cb(struct messaging_context
*msg
,
886 struct server_id pid
,
889 printf("%s", (const char *)data
->data
);
893 static bool do_ringbuflog(struct tevent_context
*ev_ctx
,
894 struct messaging_context
*msg_ctx
,
895 const struct server_id pid
,
896 const int argc
, const char **argv
)
899 fprintf(stderr
, "Usage: smbcontrol <dest> ringbuf-log\n");
903 messaging_register(msg_ctx
, NULL
, MSG_RINGBUF_LOG
,
904 print_ringbuf_log_cb
);
906 /* Send a message and register our interest in a reply */
908 if (!send_message(msg_ctx
, pid
, MSG_REQ_RINGBUF_LOG
, NULL
, 0)) {
912 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
914 /* No replies were received within the timeout period */
916 if (num_replies
== 0) {
917 printf("No replies received\n");
920 messaging_deregister(msg_ctx
, MSG_RINGBUF_LOG
, NULL
);
922 return num_replies
!= 0;
925 /* Perform a dmalloc mark */
927 static bool do_dmalloc_mark(struct tevent_context
*ev_ctx
,
928 struct messaging_context
*msg_ctx
,
929 const struct server_id pid
,
930 const int argc
, const char **argv
)
933 fprintf(stderr
, "Usage: smbcontrol <dest> dmalloc-mark\n");
937 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_MARK
, NULL
, 0);
940 /* Perform a dmalloc changed */
942 static bool do_dmalloc_changed(struct tevent_context
*ev_ctx
,
943 struct messaging_context
*msg_ctx
,
944 const struct server_id pid
,
945 const int argc
, const char **argv
)
948 fprintf(stderr
, "Usage: smbcontrol <dest> "
949 "dmalloc-log-changed\n");
953 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_LOG_CHANGED
,
957 static void print_uint32_cb(struct messaging_context
*msg
, void *private_data
,
958 uint32_t msg_type
, struct server_id pid
,
961 uint32_t num_children
;
963 if (data
->length
!= sizeof(uint32_t)) {
964 printf("Invalid response: %d bytes long\n",
968 num_children
= IVAL(data
->data
, 0);
969 printf("%u children\n", (unsigned)num_children
);
974 static bool do_num_children(struct tevent_context
*ev_ctx
,
975 struct messaging_context
*msg_ctx
,
976 const struct server_id pid
,
977 const int argc
, const char **argv
)
980 fprintf(stderr
, "Usage: smbcontrol <dest> num-children\n");
984 messaging_register(msg_ctx
, NULL
, MSG_SMB_NUM_CHILDREN
,
987 /* Send a message and register our interest in a reply */
989 if (!send_message(msg_ctx
, pid
, MSG_SMB_TELL_NUM_CHILDREN
, NULL
, 0))
992 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
994 /* No replies were received within the timeout period */
996 if (num_replies
== 0)
997 printf("No replies received\n");
999 messaging_deregister(msg_ctx
, MSG_SMB_NUM_CHILDREN
, NULL
);
1004 static bool do_msg_cleanup(struct tevent_context
*ev_ctx
,
1005 struct messaging_context
*msg_ctx
,
1006 const struct server_id pid
,
1007 const int argc
, const char **argv
)
1011 ret
= messaging_cleanup(msg_ctx
, pid
.pid
);
1013 printf("cleanup(%u) returned %s\n", (unsigned)pid
.pid
,
1014 ret
? strerror(ret
) : "ok");
1019 /* Shutdown a server process */
1021 static bool do_shutdown(struct tevent_context
*ev_ctx
,
1022 struct messaging_context
*msg_ctx
,
1023 const struct server_id pid
,
1024 const int argc
, const char **argv
)
1027 fprintf(stderr
, "Usage: smbcontrol <dest> shutdown\n");
1031 return send_message(msg_ctx
, pid
, MSG_SHUTDOWN
, NULL
, 0);
1034 /* Notify a driver upgrade */
1036 static bool do_drvupgrade(struct tevent_context
*ev_ctx
,
1037 struct messaging_context
*msg_ctx
,
1038 const struct server_id pid
,
1039 const int argc
, const char **argv
)
1042 fprintf(stderr
, "Usage: smbcontrol <dest> drvupgrade "
1047 return send_message(msg_ctx
, pid
, MSG_PRINTER_DRVUPGRADE
, argv
[1],
1048 strlen(argv
[1]) + 1);
1051 static bool do_winbind_online(struct tevent_context
*ev_ctx
,
1052 struct messaging_context
*msg_ctx
,
1053 const struct server_id pid
,
1054 const int argc
, const char **argv
)
1060 fprintf(stderr
, "Usage: smbcontrol winbindd online\n");
1064 db_path
= state_path("winbindd_cache.tdb");
1065 if (db_path
== NULL
) {
1069 /* Remove the entry in the winbindd_cache tdb to tell a later
1070 starting winbindd that we're online. */
1072 tdb
= tdb_open_log(db_path
, 0, TDB_DEFAULT
, O_RDWR
, 0600);
1074 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
1076 TALLOC_FREE(db_path
);
1080 TALLOC_FREE(db_path
);
1081 tdb_delete_bystring(tdb
, "WINBINDD_OFFLINE");
1084 return send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINE
, NULL
, 0);
1087 static bool do_winbind_offline(struct tevent_context
*ev_ctx
,
1088 struct messaging_context
*msg_ctx
,
1089 const struct server_id pid
,
1090 const int argc
, const char **argv
)
1098 fprintf(stderr
, "Usage: smbcontrol winbindd offline\n");
1102 db_path
= state_path("winbindd_cache.tdb");
1103 if (db_path
== NULL
) {
1107 /* Create an entry in the winbindd_cache tdb to tell a later
1108 starting winbindd that we're offline. We may actually create
1111 tdb
= tdb_open_log(db_path
,
1112 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE
,
1113 TDB_DEFAULT
|TDB_INCOMPATIBLE_HASH
/* TDB_CLEAR_IF_FIRST */,
1114 O_RDWR
|O_CREAT
, 0600);
1117 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
1119 TALLOC_FREE(db_path
);
1122 TALLOC_FREE(db_path
);
1124 /* There's a potential race condition that if a child
1125 winbindd detects a domain is online at the same time
1126 we're trying to tell it to go offline that it might
1127 delete the record we add between us adding it and
1128 sending the message. Minimize this by retrying up to
1131 for (retry
= 0; retry
< 5; retry
++) {
1133 TDB_DATA d
= { .dptr
= buf
, .dsize
= sizeof(buf
) };
1135 SIVAL(buf
, 0, time(NULL
));
1137 tdb_store_bystring(tdb
, "WINBINDD_OFFLINE", d
, TDB_INSERT
);
1139 ret
= send_message(msg_ctx
, pid
, MSG_WINBIND_OFFLINE
,
1142 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
1143 d
= tdb_fetch_bystring( tdb
, "WINBINDD_OFFLINE" );
1145 if (!d
.dptr
|| d
.dsize
!= 4) {
1147 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
1158 static bool do_winbind_onlinestatus(struct tevent_context
*ev_ctx
,
1159 struct messaging_context
*msg_ctx
,
1160 const struct server_id pid
,
1161 const int argc
, const char **argv
)
1164 fprintf(stderr
, "Usage: smbcontrol winbindd onlinestatus\n");
1168 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_ONLINESTATUS
,
1169 print_pid_string_cb
);
1171 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINESTATUS
, NULL
, 0)) {
1175 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
1177 /* No replies were received within the timeout period */
1179 if (num_replies
== 0)
1180 printf("No replies received\n");
1182 messaging_deregister(msg_ctx
, MSG_WINBIND_ONLINESTATUS
, NULL
);
1187 static bool do_winbind_dump_domain_list(struct tevent_context
*ev_ctx
,
1188 struct messaging_context
*msg_ctx
,
1189 const struct server_id pid
,
1190 const int argc
, const char **argv
)
1192 const char *domain
= NULL
;
1195 if (argc
< 1 || argc
> 2) {
1196 fprintf(stderr
, "Usage: smbcontrol <dest> dump-domain-list "
1203 domain_len
= strlen(argv
[1]) + 1;
1206 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1207 print_pid_string_cb
);
1209 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1210 domain
, domain_len
))
1215 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
1217 /* No replies were received within the timeout period */
1219 if (num_replies
== 0) {
1220 printf("No replies received\n");
1223 messaging_deregister(msg_ctx
, MSG_WINBIND_DUMP_DOMAIN_LIST
, NULL
);
1228 static void winbind_validate_cache_cb(struct messaging_context
*msg
,
1231 struct server_id pid
,
1234 struct server_id_buf src_string
;
1235 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1236 (*(data
->data
) == 0 ? "" : "NOT "),
1237 server_id_str_buf(pid
, &src_string
));
1241 static bool do_winbind_validate_cache(struct tevent_context
*ev_ctx
,
1242 struct messaging_context
*msg_ctx
,
1243 const struct server_id pid
,
1244 const int argc
, const char **argv
)
1246 struct server_id myid
;
1248 myid
= messaging_server_id(msg_ctx
);
1251 fprintf(stderr
, "Usage: smbcontrol winbindd validate-cache\n");
1255 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_VALIDATE_CACHE
,
1256 winbind_validate_cache_cb
);
1258 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_VALIDATE_CACHE
, &myid
,
1263 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
1265 if (num_replies
== 0) {
1266 printf("No replies received\n");
1269 messaging_deregister(msg_ctx
, MSG_WINBIND_VALIDATE_CACHE
, NULL
);
1274 static bool do_reload_config(struct tevent_context
*ev_ctx
,
1275 struct messaging_context
*msg_ctx
,
1276 const struct server_id pid
,
1277 const int argc
, const char **argv
)
1280 fprintf(stderr
, "Usage: smbcontrol <dest> reload-config\n");
1284 return send_message(msg_ctx
, pid
, MSG_SMB_CONF_UPDATED
, NULL
, 0);
1287 static bool do_reload_printers(struct tevent_context
*ev_ctx
,
1288 struct messaging_context
*msg_ctx
,
1289 const struct server_id pid
,
1290 const int argc
, const char **argv
)
1293 fprintf(stderr
, "Usage: smbcontrol <dest> reload-printers\n");
1297 return send_message(msg_ctx
, pid
, MSG_PRINTER_PCAP
, NULL
, 0);
1300 static void my_make_nmb_name( struct nmb_name
*n
, const char *name
, int type
)
1303 memset( (char *)n
, '\0', sizeof(struct nmb_name
) );
1304 fstrcpy(unix_name
, name
);
1305 (void)strupper_m(unix_name
);
1306 push_ascii(n
->name
, unix_name
, sizeof(n
->name
), STR_TERMINATE
);
1307 n
->name_type
= (unsigned int)type
& 0xFF;
1308 push_ascii(n
->scope
, lp_netbios_scope(), 64, STR_TERMINATE
);
1311 static bool do_nodestatus(struct tevent_context
*ev_ctx
,
1312 struct messaging_context
*msg_ctx
,
1313 const struct server_id pid
,
1314 const int argc
, const char **argv
)
1316 struct packet_struct p
;
1319 fprintf(stderr
, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1325 p
.ip
= interpret_addr2(argv
[1]);
1327 p
.packet_type
= NMB_PACKET
;
1329 p
.packet
.nmb
.header
.name_trn_id
= 10;
1330 p
.packet
.nmb
.header
.opcode
= 0;
1331 p
.packet
.nmb
.header
.response
= False
;
1332 p
.packet
.nmb
.header
.nm_flags
.bcast
= False
;
1333 p
.packet
.nmb
.header
.nm_flags
.recursion_available
= False
;
1334 p
.packet
.nmb
.header
.nm_flags
.recursion_desired
= False
;
1335 p
.packet
.nmb
.header
.nm_flags
.trunc
= False
;
1336 p
.packet
.nmb
.header
.nm_flags
.authoritative
= False
;
1337 p
.packet
.nmb
.header
.rcode
= 0;
1338 p
.packet
.nmb
.header
.qdcount
= 1;
1339 p
.packet
.nmb
.header
.ancount
= 0;
1340 p
.packet
.nmb
.header
.nscount
= 0;
1341 p
.packet
.nmb
.header
.arcount
= 0;
1342 my_make_nmb_name(&p
.packet
.nmb
.question
.question_name
, "*", 0x00);
1343 p
.packet
.nmb
.question
.question_type
= 0x21;
1344 p
.packet
.nmb
.question
.question_class
= 0x1;
1346 return send_message(msg_ctx
, pid
, MSG_SEND_PACKET
, &p
, sizeof(p
));
1349 static bool do_notify_cleanup(struct tevent_context
*ev_ctx
,
1350 struct messaging_context
*msg_ctx
,
1351 const struct server_id pid
,
1352 const int argc
, const char **argv
)
1355 fprintf(stderr
, "Usage: smbcontrol smbd notify-cleanup\n");
1358 return send_message(msg_ctx
, pid
, MSG_SMB_NOTIFY_CLEANUP
, NULL
, 0);
1361 /* A list of message type supported */
1363 static const struct {
1364 const char *name
; /* Option name */
1365 bool (*fn
)(struct tevent_context
*ev_ctx
,
1366 struct messaging_context
*msg_ctx
,
1367 const struct server_id pid
,
1368 const int argc
, const char **argv
);
1369 const char *help
; /* Short help text */
1371 { "debug", do_debug
, "Set debuglevel" },
1372 { "idmap", do_idmap
, "Manipulate idmap cache" },
1373 { "force-election", do_election
,
1374 "Force a browse election" },
1375 { "ping", do_ping
, "Elicit a response" },
1376 { "profile", do_profile
, "" },
1377 { "inject", do_inject_fault
,
1378 "Inject a fatal signal into a running smbd"},
1379 { "stacktrace", do_daemon_stack_trace
,
1380 "Display a stack trace of a daemon" },
1381 { "profilelevel", do_profilelevel
, "" },
1382 { "debuglevel", do_debuglevel
, "Display current debuglevels" },
1383 { "printnotify", do_printnotify
, "Send a print notify message" },
1384 { "close-share", do_closeshare
, "Forcibly disconnect a share" },
1385 { "kill-client-ip", do_kill_client_by_ip
,
1386 "Forcibly disconnect a client with a specific IP address" },
1387 { "ip-dropped", do_ip_dropped
, "Tell winbind that an IP got dropped" },
1388 { "lockretry", do_lockretry
, "Force a blocking lock retry" },
1389 { "brl-revalidate", do_brl_revalidate
, "Revalidate all brl entries" },
1390 { "pool-usage", do_poolusage
, "Display talloc memory usage" },
1391 { "ringbuf-log", do_ringbuflog
, "Display ringbuf log" },
1392 { "dmalloc-mark", do_dmalloc_mark
, "" },
1393 { "dmalloc-log-changed", do_dmalloc_changed
, "" },
1394 { "shutdown", do_shutdown
, "Shut down daemon" },
1395 { "drvupgrade", do_drvupgrade
, "Notify a printer driver has changed" },
1396 { "reload-config", do_reload_config
, "Force smbd or winbindd to reload config file"},
1397 { "reload-printers", do_reload_printers
, "Force smbd to reload printers"},
1398 { "nodestatus", do_nodestatus
, "Ask nmbd to do a node status request"},
1399 { "online", do_winbind_online
, "Ask winbind to go into online state"},
1400 { "offline", do_winbind_offline
, "Ask winbind to go into offline state"},
1401 { "onlinestatus", do_winbind_onlinestatus
, "Request winbind online status"},
1402 { "validate-cache" , do_winbind_validate_cache
,
1403 "Validate winbind's credential cache" },
1404 { "dump-domain-list", do_winbind_dump_domain_list
, "Dump winbind domain list"},
1405 { "notify-cleanup", do_notify_cleanup
},
1406 { "num-children", do_num_children
,
1407 "Print number of smbd child processes" },
1408 { "msg-cleanup", do_msg_cleanup
},
1409 { "noop", do_noop
, "Do nothing" },
1413 /* Display usage information */
1415 static void usage(poptContext pc
)
1419 poptPrintHelp(pc
, stderr
, 0);
1421 fprintf(stderr
, "\n");
1422 fprintf(stderr
, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1425 fprintf(stderr
, "\n");
1426 fprintf(stderr
, "<message-type> is one of:\n");
1428 for (i
= 0; msg_types
[i
].name
; i
++)
1429 fprintf(stderr
, "\t%-30s%s\n", msg_types
[i
].name
,
1432 fprintf(stderr
, "\n");
1437 /* Return the pid number for a string destination */
1439 static struct server_id
parse_dest(struct messaging_context
*msg
,
1442 struct server_id result
= {-1};
1445 /* Zero is a special return value for broadcast to all processes */
1447 if (strequal(dest
, "all")) {
1448 return interpret_pid(MSG_BROADCAST_PID_STR
);
1451 /* Try self - useful for testing */
1453 if (strequal(dest
, "self")) {
1454 return messaging_server_id(msg
);
1457 /* Fix winbind typo. */
1458 if (strequal(dest
, "winbind")) {
1462 /* Check for numeric pid number */
1463 result
= interpret_pid(dest
);
1465 /* Zero isn't valid if not "all". */
1466 if (result
.pid
&& procid_valid(&result
)) {
1470 /* Look up other destinations in pidfile directory */
1472 if ((pid
= pidfile_pid(lp_pid_directory(), dest
)) != 0) {
1473 return pid_to_procid(pid
);
1476 fprintf(stderr
,"Can't find pid for destination '%s'\n", dest
);
1481 /* Execute smbcontrol command */
1483 static bool do_command(struct tevent_context
*ev_ctx
,
1484 struct messaging_context
*msg_ctx
,
1485 int argc
, const char **argv
)
1487 const char *dest
= argv
[0], *command
= argv
[1];
1488 struct server_id pid
;
1491 /* Check destination */
1493 pid
= parse_dest(msg_ctx
, dest
);
1494 if (!procid_valid(&pid
)) {
1500 for (i
= 0; msg_types
[i
].name
; i
++) {
1501 if (strequal(command
, msg_types
[i
].name
))
1502 return msg_types
[i
].fn(ev_ctx
, msg_ctx
, pid
,
1503 argc
- 1, argv
+ 1);
1506 fprintf(stderr
, "smbcontrol: unknown command '%s'\n", command
);
1511 static void smbcontrol_help(poptContext pc
,
1512 enum poptCallbackReason preason
,
1513 struct poptOption
* poption
,
1517 if (poption
->shortName
!= '?') {
1518 poptPrintUsage(pc
, stdout
, 0);
1526 struct poptOption help_options
[] = {
1527 { NULL
, '\0', POPT_ARG_CALLBACK
, (void *)&smbcontrol_help
, '\0',
1529 { "help", '?', 0, NULL
, '?', "Show this help message", NULL
},
1530 { "usage", '\0', 0, NULL
, 'u', "Display brief usage message", NULL
},
1536 int main(int argc
, const char **argv
)
1540 struct tevent_context
*evt_ctx
;
1541 struct messaging_context
*msg_ctx
;
1543 static struct poptOption long_options
[] = {
1545 { NULL
, '\0', POPT_ARG_INCLUDE_TABLE
, help_options
,
1546 0, "Help options:", NULL
},
1547 { "timeout", 't', POPT_ARG_INT
, &timeout
, 't',
1548 "Set timeout value in seconds", "TIMEOUT" },
1553 TALLOC_CTX
*frame
= talloc_stackframe();
1558 setup_logging(argv
[0], DEBUG_STDOUT
);
1559 lp_set_cmdline("log level", "0");
1561 /* Parse command line arguments using popt */
1563 pc
= poptGetContext(
1564 "smbcontrol", argc
, (const char **)argv
, long_options
, 0);
1566 poptSetOtherOptionHelp(pc
, "[OPTION...] <destination> <message-type> "
1572 while ((opt
= poptGetNextOpt(pc
)) != -1) {
1574 case 't': /* --timeout */
1577 fprintf(stderr
, "Invalid option\n");
1578 poptPrintHelp(pc
, stderr
, 0);
1583 /* We should now have the remaining command line arguments in
1584 argv. The argc parameter should have been decremented to the
1585 correct value in the above switch statement. */
1587 argv
= (const char **)poptGetArgs(pc
);
1590 while (argv
[argc
] != NULL
) {
1598 lp_load_global(get_dyn_CONFIGFILE());
1600 /* Need to invert sense of return code -- samba
1601 * routines mostly return True==1 for success, but
1604 if (!(evt_ctx
= samba_tevent_context_init(NULL
)) ||
1605 !(msg_ctx
= messaging_init(NULL
, evt_ctx
))) {
1606 fprintf(stderr
, "could not init messaging context\n");
1611 ret
= !do_command(evt_ctx
, msg_ctx
, argc
, argv
);
1612 TALLOC_FREE(msg_ctx
);