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 "popt_common.h"
29 #include "librpc/gen_ndr/spoolss.h"
30 #include "nt_printing.h"
31 #include "printing/notify.h"
32 #include "libsmb/nmblib.h"
35 #include "../lib/util/pidfile.h"
39 #include <libunwind.h>
42 #if HAVE_LIBUNWIND_PTRACE_H
43 #include <libunwind-ptrace.h>
47 #include <sys/ptrace.h>
50 /* Default timeout value when waiting for replies (in seconds) */
52 #define DEFAULT_TIMEOUT 10
54 static int timeout
= DEFAULT_TIMEOUT
;
55 static int num_replies
; /* Used by message callback fns */
57 /* Send a message to a destination pid. Zero means broadcast smbd. */
59 static bool send_message(struct messaging_context
*msg_ctx
,
60 struct server_id pid
, int msg_type
,
61 const void *buf
, int len
)
66 if (procid_to_pid(&pid
) != 0)
67 return NT_STATUS_IS_OK(
68 messaging_send_buf(msg_ctx
, pid
, msg_type
,
69 (const uint8_t *)buf
, len
));
71 ret
= message_send_all(msg_ctx
, msg_type
, buf
, len
, &n_sent
);
72 DEBUG(10,("smbcontrol/send_message: broadcast message to "
73 "%d processes\n", n_sent
));
78 static void smbcontrol_timeout(struct tevent_context
*event_ctx
,
79 struct tevent_timer
*te
,
83 bool *timed_out
= (bool *)private_data
;
88 /* Wait for one or more reply messages */
90 static void wait_replies(struct tevent_context
*ev_ctx
,
91 struct messaging_context
*msg_ctx
,
92 bool multiple_replies
)
94 struct tevent_timer
*te
;
95 bool timed_out
= False
;
97 te
= tevent_add_timer(ev_ctx
, NULL
,
98 timeval_current_ofs(timeout
, 0),
99 smbcontrol_timeout
, (void *)&timed_out
);
101 DEBUG(0, ("tevent_add_timer failed\n"));
107 if (num_replies
> 0 && !multiple_replies
)
109 ret
= tevent_loop_once(ev_ctx
);
116 /* Message handler callback that displays the PID and a string on stdout */
118 static void print_pid_string_cb(struct messaging_context
*msg
,
121 struct server_id pid
,
124 struct server_id_buf pidstr
;
126 printf("PID %s: %.*s", server_id_str_buf(pid
, &pidstr
),
127 (int)data
->length
, (const char *)data
->data
);
131 /* Message handler callback that displays a string on stdout */
133 static void print_string_cb(struct messaging_context
*msg
,
136 struct server_id pid
,
139 printf("%*s", (int)data
->length
, (const char *)data
->data
);
143 /* Send no message. Useful for testing. */
145 static bool do_noop(struct tevent_context
*ev_ctx
,
146 struct messaging_context
*msg_ctx
,
147 const struct server_id pid
,
148 const int argc
, const char **argv
)
151 fprintf(stderr
, "Usage: smbcontrol <dest> noop\n");
155 /* Move along, nothing to see here */
160 /* Send a debug string */
162 static bool do_debug(struct tevent_context
*ev_ctx
,
163 struct messaging_context
*msg_ctx
,
164 const struct server_id pid
,
165 const int argc
, const char **argv
)
168 fprintf(stderr
, "Usage: smbcontrol <dest> debug "
173 return send_message(msg_ctx
, pid
, MSG_DEBUG
, argv
[1],
174 strlen(argv
[1]) + 1);
178 static bool do_idmap(struct tevent_context
*ev
,
179 struct messaging_context
*msg_ctx
,
180 const struct server_id pid
,
181 const int argc
, const char **argv
)
183 static const char* usage
= "Usage: "
184 "smbcontrol <dest> idmap <cmd> [arg]\n"
186 "\tdelete \"UID <uid>\"|\"GID <gid>\"|<sid>\n"
187 "\t\tkill \"UID <uid>\"|\"GID <gid>\"|<sid>\n";
188 const char* arg
= NULL
;
197 arglen
= strlen(arg
) + 1;
200 fprintf(stderr
, "%s", usage
);
204 if (strcmp(argv
[1], "delete") == 0) {
205 msg_type
= ID_CACHE_DELETE
;
207 else if (strcmp(argv
[1], "kill") == 0) {
208 msg_type
= ID_CACHE_KILL
;
210 else if (strcmp(argv
[1], "help") == 0) {
211 fprintf(stdout
, "%s", usage
);
215 fprintf(stderr
, "%s", usage
);
219 return send_message(msg_ctx
, pid
, msg_type
, arg
, arglen
);
223 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
225 /* Return the name of a process given it's PID. This will only work on Linux,
226 * but that's probably moot since this whole stack tracing implementation is
227 * Linux-specific anyway.
229 static const char * procname(pid_t pid
, char * buf
, size_t bufsz
)
234 snprintf(path
, sizeof(path
), "/proc/%llu/cmdline",
235 (unsigned long long)pid
);
236 if ((fp
= fopen(path
, "r")) == NULL
) {
240 fgets(buf
, bufsz
, fp
);
246 static void print_stack_trace(pid_t pid
, int * count
)
249 unw_addr_space_t aspace
= NULL
;
258 if (ptrace(PTRACE_ATTACH
, pid
, NULL
, NULL
) < 0) {
260 "Failed to attach to process %llu: %s\n",
261 (unsigned long long)pid
, strerror(errno
));
265 /* Wait until the attach is complete. */
266 waitpid(pid
, NULL
, 0);
268 if (((pinfo
= _UPT_create(pid
)) == NULL
) ||
269 ((aspace
= unw_create_addr_space(&_UPT_accessors
, 0)) == NULL
)) {
270 /* Probably out of memory. */
272 "Unable to initialize stack unwind for process %llu\n",
273 (unsigned long long)pid
);
277 if ((ret
= unw_init_remote(&cursor
, aspace
, pinfo
))) {
279 "Unable to unwind stack for process %llu: %s\n",
280 (unsigned long long)pid
, unw_strerror(ret
));
288 if (procname(pid
, nbuf
, sizeof(nbuf
))) {
289 printf("Stack trace for process %llu (%s):\n",
290 (unsigned long long)pid
, nbuf
);
292 printf("Stack trace for process %llu:\n",
293 (unsigned long long)pid
);
296 while (unw_step(&cursor
) > 0) {
298 unw_get_reg(&cursor
, UNW_REG_IP
, &ip
);
299 unw_get_reg(&cursor
, UNW_REG_SP
, &sp
);
301 ret
= unw_get_proc_name(&cursor
, nbuf
, sizeof(nbuf
), &off
);
302 if (ret
!= 0 && ret
!= -UNW_ENOMEM
) {
303 snprintf(nbuf
, sizeof(nbuf
), "<unknown symbol>");
305 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
306 nbuf
, (long long)off
, (long long)ip
,
314 unw_destroy_addr_space(aspace
);
321 ptrace(PTRACE_DETACH
, pid
, NULL
, NULL
);
324 static int stack_trace_server(const struct server_id
*id
,
328 if (id
->vnn
== get_my_vnn()) {
329 print_stack_trace(procid_to_pid(id
), (int *)priv
);
334 static bool do_daemon_stack_trace(struct tevent_context
*ev_ctx
,
335 struct messaging_context
*msg_ctx
,
336 const struct server_id pid
,
337 const int argc
, const char **argv
)
343 fprintf(stderr
, "Usage: smbcontrol <dest> stacktrace\n");
347 dest
= procid_to_pid(&pid
);
350 /* It would be nice to be able to make sure that this PID is
351 * the PID of a smbd/winbind/nmbd process, not some random PID
352 * the user liked the look of. It doesn't seem like it's worth
353 * the effort at the moment, however.
355 print_stack_trace(dest
, &count
);
357 serverid_traverse_read(stack_trace_server
, &count
);
363 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
365 static bool do_daemon_stack_trace(struct tevent_context
*ev_ctx
,
366 struct messaging_context
*msg_ctx
,
367 const struct server_id pid
,
368 const int argc
, const char **argv
)
371 "Daemon stack tracing is not supported on this platform\n");
375 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
377 /* Inject a fault (fatal signal) into a running smbd */
379 static bool do_inject_fault(struct tevent_context
*ev_ctx
,
380 struct messaging_context
*msg_ctx
,
381 const struct server_id pid
,
382 const int argc
, const char **argv
)
385 fprintf(stderr
, "Usage: smbcontrol <dest> inject "
386 "<bus|hup|term|internal|segv>\n");
391 fprintf(stderr
, "Fault injection is only available in "
392 "developer builds\n");
394 #else /* DEVELOPER */
398 if (strcmp(argv
[1], "bus") == 0) {
400 } else if (strcmp(argv
[1], "hup") == 0) {
402 } else if (strcmp(argv
[1], "term") == 0) {
404 } else if (strcmp(argv
[1], "segv") == 0) {
406 } else if (strcmp(argv
[1], "internal") == 0) {
407 /* Force an internal error, ie. an unclean exit. */
410 fprintf(stderr
, "Unknown signal name '%s'\n", argv
[1]);
414 return send_message(msg_ctx
, pid
, MSG_SMB_INJECT_FAULT
,
417 #endif /* DEVELOPER */
420 /* Force a browser election */
422 static bool do_election(struct tevent_context
*ev_ctx
,
423 struct messaging_context
*msg_ctx
,
424 const struct server_id pid
,
425 const int argc
, const char **argv
)
428 fprintf(stderr
, "Usage: smbcontrol <dest> force-election\n");
432 return send_message(msg_ctx
, pid
, MSG_FORCE_ELECTION
, NULL
, 0);
435 /* Ping a samba daemon process */
437 static void pong_cb(struct messaging_context
*msg
,
440 struct server_id pid
,
443 struct server_id_buf src_string
;
444 printf("PONG from pid %s\n", server_id_str_buf(pid
, &src_string
));
448 static bool do_ping(struct tevent_context
*ev_ctx
,
449 struct messaging_context
*msg_ctx
,
450 const struct server_id pid
,
451 const int argc
, const char **argv
)
454 fprintf(stderr
, "Usage: smbcontrol <dest> ping\n");
458 /* Send a message and register our interest in a reply */
460 if (!send_message(msg_ctx
, pid
, MSG_PING
, NULL
, 0))
463 messaging_register(msg_ctx
, NULL
, MSG_PONG
, pong_cb
);
465 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
467 /* No replies were received within the timeout period */
469 if (num_replies
== 0)
470 printf("No replies received\n");
472 messaging_deregister(msg_ctx
, MSG_PONG
, NULL
);
477 /* Set profiling options */
479 static bool do_profile(struct tevent_context
*ev_ctx
,
480 struct messaging_context
*msg_ctx
,
481 const struct server_id pid
,
482 const int argc
, const char **argv
)
487 fprintf(stderr
, "Usage: smbcontrol <dest> profile "
488 "<off|count|on|flush>\n");
492 if (strcmp(argv
[1], "off") == 0) {
494 } else if (strcmp(argv
[1], "count") == 0) {
496 } else if (strcmp(argv
[1], "on") == 0) {
498 } else if (strcmp(argv
[1], "flush") == 0) {
501 fprintf(stderr
, "Unknown profile command '%s'\n", argv
[1]);
505 return send_message(msg_ctx
, pid
, MSG_PROFILE
, &v
, sizeof(int));
508 /* Return the profiling level */
510 static void profilelevel_cb(struct messaging_context
*msg_ctx
,
513 struct server_id pid
,
521 if (data
->length
!= sizeof(int)) {
522 fprintf(stderr
, "invalid message length %ld returned\n",
523 (unsigned long)data
->length
);
527 memcpy(&level
, data
->data
, sizeof(int));
540 s
= "count and time";
547 printf("Profiling %s on pid %u\n",s
,(unsigned int)procid_to_pid(&pid
));
550 static void profilelevel_rqst(struct messaging_context
*msg_ctx
,
553 struct server_id pid
,
558 /* Send back a dummy reply */
560 send_message(msg_ctx
, pid
, MSG_PROFILELEVEL
, &v
, sizeof(int));
563 static bool do_profilelevel(struct tevent_context
*ev_ctx
,
564 struct messaging_context
*msg_ctx
,
565 const struct server_id pid
,
566 const int argc
, const char **argv
)
569 fprintf(stderr
, "Usage: smbcontrol <dest> profilelevel\n");
573 /* Send a message and register our interest in a reply */
575 if (!send_message(msg_ctx
, pid
, MSG_REQ_PROFILELEVEL
, NULL
, 0))
578 messaging_register(msg_ctx
, NULL
, MSG_PROFILELEVEL
, profilelevel_cb
);
579 messaging_register(msg_ctx
, NULL
, MSG_REQ_PROFILELEVEL
,
582 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
584 /* No replies were received within the timeout period */
586 if (num_replies
== 0)
587 printf("No replies received\n");
589 messaging_deregister(msg_ctx
, MSG_PROFILE
, NULL
);
594 /* Display debug level settings */
596 static bool do_debuglevel(struct tevent_context
*ev_ctx
,
597 struct messaging_context
*msg_ctx
,
598 const struct server_id pid
,
599 const int argc
, const char **argv
)
602 fprintf(stderr
, "Usage: smbcontrol <dest> debuglevel\n");
606 /* Send a message and register our interest in a reply */
608 if (!send_message(msg_ctx
, pid
, MSG_REQ_DEBUGLEVEL
, NULL
, 0))
611 messaging_register(msg_ctx
, NULL
, MSG_DEBUGLEVEL
, print_pid_string_cb
);
613 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
615 /* No replies were received within the timeout period */
617 if (num_replies
== 0)
618 printf("No replies received\n");
620 messaging_deregister(msg_ctx
, MSG_DEBUGLEVEL
, NULL
);
625 /* Send a print notify message */
627 static bool do_printnotify(struct tevent_context
*ev_ctx
,
628 struct messaging_context
*msg_ctx
,
629 const struct server_id pid
,
630 const int argc
, const char **argv
)
634 /* Check for subcommand */
637 fprintf(stderr
, "Must specify subcommand:\n");
638 fprintf(stderr
, "\tqueuepause <printername>\n");
639 fprintf(stderr
, "\tqueueresume <printername>\n");
640 fprintf(stderr
, "\tjobpause <printername> <unix jobid>\n");
641 fprintf(stderr
, "\tjobresume <printername> <unix jobid>\n");
642 fprintf(stderr
, "\tjobdelete <printername> <unix jobid>\n");
643 fprintf(stderr
, "\tprinter <printername> <comment|port|"
644 "driver> <value>\n");
651 if (strcmp(cmd
, "queuepause") == 0) {
654 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
655 " queuepause <printername>\n");
659 notify_printer_status_byname(ev_ctx
, msg_ctx
, argv
[2],
660 PRINTER_STATUS_PAUSED
);
664 } else if (strcmp(cmd
, "queueresume") == 0) {
667 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
668 " queuereume <printername>\n");
672 notify_printer_status_byname(ev_ctx
, msg_ctx
, argv
[2],
677 } else if (strcmp(cmd
, "jobpause") == 0) {
681 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
682 " jobpause <printername> <unix-jobid>\n");
686 jobid
= atoi(argv
[3]);
688 notify_job_status_byname(
690 argv
[2], jobid
, JOB_STATUS_PAUSED
,
691 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
695 } else if (strcmp(cmd
, "jobresume") == 0) {
699 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
700 " jobpause <printername> <unix-jobid>\n");
704 jobid
= atoi(argv
[3]);
706 notify_job_status_byname(
708 argv
[2], jobid
, JOB_STATUS_QUEUED
,
709 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
713 } else if (strcmp(cmd
, "jobdelete") == 0) {
717 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
718 " jobpause <printername> <unix-jobid>\n");
722 jobid
= atoi(argv
[3]);
724 notify_job_status_byname(
726 argv
[2], jobid
, JOB_STATUS_DELETING
,
727 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
729 notify_job_status_byname(
731 argv
[2], jobid
, JOB_STATUS_DELETING
|
733 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
737 } else if (strcmp(cmd
, "printer") == 0) {
741 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify "
742 "printer <printername> <comment|port|driver> "
747 if (strcmp(argv
[3], "comment") == 0) {
748 attribute
= PRINTER_NOTIFY_FIELD_COMMENT
;
749 } else if (strcmp(argv
[3], "port") == 0) {
750 attribute
= PRINTER_NOTIFY_FIELD_PORT_NAME
;
751 } else if (strcmp(argv
[3], "driver") == 0) {
752 attribute
= PRINTER_NOTIFY_FIELD_DRIVER_NAME
;
754 fprintf(stderr
, "Invalid printer command '%s'\n",
759 notify_printer_byname(ev_ctx
, msg_ctx
, argv
[2], attribute
,
760 discard_const_p(char, argv
[4]));
765 fprintf(stderr
, "Invalid subcommand '%s'\n", cmd
);
769 print_notify_send_messages(msg_ctx
, 0);
775 static bool do_closeshare(struct tevent_context
*ev_ctx
,
776 struct messaging_context
*msg_ctx
,
777 const struct server_id pid
,
778 const int argc
, const char **argv
)
781 fprintf(stderr
, "Usage: smbcontrol <dest> close-share "
786 return send_message(msg_ctx
, pid
, MSG_SMB_FORCE_TDIS
, argv
[1],
787 strlen(argv
[1]) + 1);
790 /* Kill a client by IP address */
791 static bool do_kill_client_by_ip(struct tevent_context
*ev_ctx
,
792 struct messaging_context
*msg_ctx
,
793 const struct server_id pid
,
794 const int argc
, const char **argv
)
797 fprintf(stderr
, "Usage: smbcontrol <dest> kill-client-ip "
802 if (!is_ipaddress_v4(argv
[1]) && !is_ipaddress_v6(argv
[1])) {
803 fprintf(stderr
, "%s is not a valid IP address!\n", argv
[1]);
807 return send_message(msg_ctx
, pid
, MSG_SMB_KILL_CLIENT_IP
,
808 argv
[1], strlen(argv
[1]) + 1);
811 /* Tell winbindd an IP got dropped */
813 static bool do_ip_dropped(struct tevent_context
*ev_ctx
,
814 struct messaging_context
*msg_ctx
,
815 const struct server_id pid
,
816 const int argc
, const char **argv
)
819 fprintf(stderr
, "Usage: smbcontrol <dest> ip-dropped "
824 return send_message(msg_ctx
, pid
, MSG_WINBIND_IP_DROPPED
, argv
[1],
825 strlen(argv
[1]) + 1);
828 /* force a blocking lock retry */
830 static bool do_lockretry(struct tevent_context
*ev_ctx
,
831 struct messaging_context
*msg_ctx
,
832 const struct server_id pid
,
833 const int argc
, const char **argv
)
836 fprintf(stderr
, "Usage: smbcontrol <dest> lockretry\n");
840 return send_message(msg_ctx
, pid
, MSG_SMB_UNLOCK
, NULL
, 0);
843 /* force a validation of all brl entries, including re-sends. */
845 static bool do_brl_revalidate(struct tevent_context
*ev_ctx
,
846 struct messaging_context
*msg_ctx
,
847 const struct server_id pid
,
848 const int argc
, const char **argv
)
851 fprintf(stderr
, "Usage: smbcontrol <dest> brl-revalidate\n");
855 return send_message(msg_ctx
, pid
, MSG_SMB_BRL_VALIDATE
, NULL
, 0);
858 /* Display talloc pool usage */
860 static bool do_poolusage(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> pool-usage\n");
870 messaging_register(msg_ctx
, NULL
, MSG_POOL_USAGE
, print_string_cb
);
872 /* Send a message and register our interest in a reply */
874 if (!send_message(msg_ctx
, pid
, MSG_REQ_POOL_USAGE
, NULL
, 0))
877 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
879 /* No replies were received within the timeout period */
881 if (num_replies
== 0)
882 printf("No replies received\n");
884 messaging_deregister(msg_ctx
, MSG_POOL_USAGE
, NULL
);
889 /* Perform a dmalloc mark */
891 static bool do_dmalloc_mark(struct tevent_context
*ev_ctx
,
892 struct messaging_context
*msg_ctx
,
893 const struct server_id pid
,
894 const int argc
, const char **argv
)
897 fprintf(stderr
, "Usage: smbcontrol <dest> dmalloc-mark\n");
901 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_MARK
, NULL
, 0);
904 /* Perform a dmalloc changed */
906 static bool do_dmalloc_changed(struct tevent_context
*ev_ctx
,
907 struct messaging_context
*msg_ctx
,
908 const struct server_id pid
,
909 const int argc
, const char **argv
)
912 fprintf(stderr
, "Usage: smbcontrol <dest> "
913 "dmalloc-log-changed\n");
917 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_LOG_CHANGED
,
921 static void print_uint32_cb(struct messaging_context
*msg
, void *private_data
,
922 uint32_t msg_type
, struct server_id pid
,
925 uint32_t num_children
;
927 if (data
->length
!= sizeof(uint32_t)) {
928 printf("Invalid response: %d bytes long\n",
932 num_children
= IVAL(data
->data
, 0);
933 printf("%u children\n", (unsigned)num_children
);
938 static bool do_num_children(struct tevent_context
*ev_ctx
,
939 struct messaging_context
*msg_ctx
,
940 const struct server_id pid
,
941 const int argc
, const char **argv
)
944 fprintf(stderr
, "Usage: smbcontrol <dest> num-children\n");
948 messaging_register(msg_ctx
, NULL
, MSG_SMB_NUM_CHILDREN
,
951 /* Send a message and register our interest in a reply */
953 if (!send_message(msg_ctx
, pid
, MSG_SMB_TELL_NUM_CHILDREN
, NULL
, 0))
956 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
958 /* No replies were received within the timeout period */
960 if (num_replies
== 0)
961 printf("No replies received\n");
963 messaging_deregister(msg_ctx
, MSG_SMB_NUM_CHILDREN
, NULL
);
968 static bool do_msg_cleanup(struct tevent_context
*ev_ctx
,
969 struct messaging_context
*msg_ctx
,
970 const struct server_id pid
,
971 const int argc
, const char **argv
)
975 ret
= messaging_cleanup(msg_ctx
, pid
.pid
);
977 printf("cleanup(%u) returned %s\n", (unsigned)pid
.pid
,
978 ret
? strerror(ret
) : "ok");
983 /* Shutdown a server process */
985 static bool do_shutdown(struct tevent_context
*ev_ctx
,
986 struct messaging_context
*msg_ctx
,
987 const struct server_id pid
,
988 const int argc
, const char **argv
)
991 fprintf(stderr
, "Usage: smbcontrol <dest> shutdown\n");
995 return send_message(msg_ctx
, pid
, MSG_SHUTDOWN
, NULL
, 0);
998 /* Notify a driver upgrade */
1000 static bool do_drvupgrade(struct tevent_context
*ev_ctx
,
1001 struct messaging_context
*msg_ctx
,
1002 const struct server_id pid
,
1003 const int argc
, const char **argv
)
1006 fprintf(stderr
, "Usage: smbcontrol <dest> drvupgrade "
1011 return send_message(msg_ctx
, pid
, MSG_PRINTER_DRVUPGRADE
, argv
[1],
1012 strlen(argv
[1]) + 1);
1015 static bool do_winbind_online(struct tevent_context
*ev_ctx
,
1016 struct messaging_context
*msg_ctx
,
1017 const struct server_id pid
,
1018 const int argc
, const char **argv
)
1024 fprintf(stderr
, "Usage: smbcontrol winbindd online\n");
1028 db_path
= state_path("winbindd_cache.tdb");
1029 if (db_path
== NULL
) {
1033 /* Remove the entry in the winbindd_cache tdb to tell a later
1034 starting winbindd that we're online. */
1036 tdb
= tdb_open_log(db_path
, 0, TDB_DEFAULT
, O_RDWR
, 0600);
1038 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
1040 TALLOC_FREE(db_path
);
1044 TALLOC_FREE(db_path
);
1045 tdb_delete_bystring(tdb
, "WINBINDD_OFFLINE");
1048 return send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINE
, NULL
, 0);
1051 static bool do_winbind_offline(struct tevent_context
*ev_ctx
,
1052 struct messaging_context
*msg_ctx
,
1053 const struct server_id pid
,
1054 const int argc
, const char **argv
)
1062 fprintf(stderr
, "Usage: smbcontrol winbindd offline\n");
1066 db_path
= state_path("winbindd_cache.tdb");
1067 if (db_path
== NULL
) {
1071 /* Create an entry in the winbindd_cache tdb to tell a later
1072 starting winbindd that we're offline. We may actually create
1075 tdb
= tdb_open_log(db_path
,
1076 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE
,
1077 TDB_DEFAULT
|TDB_INCOMPATIBLE_HASH
/* TDB_CLEAR_IF_FIRST */,
1078 O_RDWR
|O_CREAT
, 0600);
1081 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
1083 TALLOC_FREE(db_path
);
1086 TALLOC_FREE(db_path
);
1088 /* There's a potential race condition that if a child
1089 winbindd detects a domain is online at the same time
1090 we're trying to tell it to go offline that it might
1091 delete the record we add between us adding it and
1092 sending the message. Minimize this by retrying up to
1095 for (retry
= 0; retry
< 5; retry
++) {
1097 TDB_DATA d
= { .dptr
= buf
, .dsize
= sizeof(buf
) };
1099 SIVAL(buf
, 0, time(NULL
));
1101 tdb_store_bystring(tdb
, "WINBINDD_OFFLINE", d
, TDB_INSERT
);
1103 ret
= send_message(msg_ctx
, pid
, MSG_WINBIND_OFFLINE
,
1106 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
1107 d
= tdb_fetch_bystring( tdb
, "WINBINDD_OFFLINE" );
1109 if (!d
.dptr
|| d
.dsize
!= 4) {
1111 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
1122 static bool do_winbind_onlinestatus(struct tevent_context
*ev_ctx
,
1123 struct messaging_context
*msg_ctx
,
1124 const struct server_id pid
,
1125 const int argc
, const char **argv
)
1127 struct server_id myid
;
1129 myid
= messaging_server_id(msg_ctx
);
1132 fprintf(stderr
, "Usage: smbcontrol winbindd onlinestatus\n");
1136 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_ONLINESTATUS
,
1137 print_pid_string_cb
);
1139 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINESTATUS
, &myid
,
1143 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
1145 /* No replies were received within the timeout period */
1147 if (num_replies
== 0)
1148 printf("No replies received\n");
1150 messaging_deregister(msg_ctx
, MSG_WINBIND_ONLINESTATUS
, NULL
);
1155 static bool do_dump_event_list(struct tevent_context
*ev_ctx
,
1156 struct messaging_context
*msg_ctx
,
1157 const struct server_id pid
,
1158 const int argc
, const char **argv
)
1161 fprintf(stderr
, "Usage: smbcontrol <dest> dump-event-list\n");
1165 return send_message(msg_ctx
, pid
, MSG_DUMP_EVENT_LIST
, NULL
, 0);
1168 static bool do_winbind_dump_domain_list(struct tevent_context
*ev_ctx
,
1169 struct messaging_context
*msg_ctx
,
1170 const struct server_id pid
,
1171 const int argc
, const char **argv
)
1173 const char *domain
= NULL
;
1175 struct server_id myid
;
1176 uint8_t *buf
= NULL
;
1179 myid
= messaging_server_id(msg_ctx
);
1181 if (argc
< 1 || argc
> 2) {
1182 fprintf(stderr
, "Usage: smbcontrol <dest> dump-domain-list "
1189 domain_len
= strlen(argv
[1]) + 1;
1192 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1193 print_pid_string_cb
);
1195 buf_len
= sizeof(myid
)+domain_len
;
1196 buf
= SMB_MALLOC_ARRAY(uint8_t, buf_len
);
1201 memcpy(buf
, &myid
, sizeof(myid
));
1202 memcpy(&buf
[sizeof(myid
)], domain
, domain_len
);
1204 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1211 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
1213 /* No replies were received within the timeout period */
1216 if (num_replies
== 0) {
1217 printf("No replies received\n");
1220 messaging_deregister(msg_ctx
, MSG_WINBIND_DUMP_DOMAIN_LIST
, NULL
);
1225 static void winbind_validate_cache_cb(struct messaging_context
*msg
,
1228 struct server_id pid
,
1231 struct server_id_buf src_string
;
1232 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1233 (*(data
->data
) == 0 ? "" : "NOT "),
1234 server_id_str_buf(pid
, &src_string
));
1238 static bool do_winbind_validate_cache(struct tevent_context
*ev_ctx
,
1239 struct messaging_context
*msg_ctx
,
1240 const struct server_id pid
,
1241 const int argc
, const char **argv
)
1243 struct server_id myid
;
1245 myid
= messaging_server_id(msg_ctx
);
1248 fprintf(stderr
, "Usage: smbcontrol winbindd validate-cache\n");
1252 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_VALIDATE_CACHE
,
1253 winbind_validate_cache_cb
);
1255 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_VALIDATE_CACHE
, &myid
,
1260 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
1262 if (num_replies
== 0) {
1263 printf("No replies received\n");
1266 messaging_deregister(msg_ctx
, MSG_WINBIND_VALIDATE_CACHE
, NULL
);
1271 static bool do_reload_config(struct tevent_context
*ev_ctx
,
1272 struct messaging_context
*msg_ctx
,
1273 const struct server_id pid
,
1274 const int argc
, const char **argv
)
1277 fprintf(stderr
, "Usage: smbcontrol <dest> reload-config\n");
1281 return send_message(msg_ctx
, pid
, MSG_SMB_CONF_UPDATED
, NULL
, 0);
1284 static bool do_reload_printers(struct tevent_context
*ev_ctx
,
1285 struct messaging_context
*msg_ctx
,
1286 const struct server_id pid
,
1287 const int argc
, const char **argv
)
1290 fprintf(stderr
, "Usage: smbcontrol <dest> reload-printers\n");
1294 return send_message(msg_ctx
, pid
, MSG_PRINTER_PCAP
, NULL
, 0);
1297 static void my_make_nmb_name( struct nmb_name
*n
, const char *name
, int type
)
1300 memset( (char *)n
, '\0', sizeof(struct nmb_name
) );
1301 fstrcpy(unix_name
, name
);
1302 (void)strupper_m(unix_name
);
1303 push_ascii(n
->name
, unix_name
, sizeof(n
->name
), STR_TERMINATE
);
1304 n
->name_type
= (unsigned int)type
& 0xFF;
1305 push_ascii(n
->scope
, lp_netbios_scope(), 64, STR_TERMINATE
);
1308 static bool do_nodestatus(struct tevent_context
*ev_ctx
,
1309 struct messaging_context
*msg_ctx
,
1310 const struct server_id pid
,
1311 const int argc
, const char **argv
)
1313 struct packet_struct p
;
1316 fprintf(stderr
, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1322 p
.ip
= interpret_addr2(argv
[1]);
1324 p
.packet_type
= NMB_PACKET
;
1326 p
.packet
.nmb
.header
.name_trn_id
= 10;
1327 p
.packet
.nmb
.header
.opcode
= 0;
1328 p
.packet
.nmb
.header
.response
= False
;
1329 p
.packet
.nmb
.header
.nm_flags
.bcast
= False
;
1330 p
.packet
.nmb
.header
.nm_flags
.recursion_available
= False
;
1331 p
.packet
.nmb
.header
.nm_flags
.recursion_desired
= False
;
1332 p
.packet
.nmb
.header
.nm_flags
.trunc
= False
;
1333 p
.packet
.nmb
.header
.nm_flags
.authoritative
= False
;
1334 p
.packet
.nmb
.header
.rcode
= 0;
1335 p
.packet
.nmb
.header
.qdcount
= 1;
1336 p
.packet
.nmb
.header
.ancount
= 0;
1337 p
.packet
.nmb
.header
.nscount
= 0;
1338 p
.packet
.nmb
.header
.arcount
= 0;
1339 my_make_nmb_name(&p
.packet
.nmb
.question
.question_name
, "*", 0x00);
1340 p
.packet
.nmb
.question
.question_type
= 0x21;
1341 p
.packet
.nmb
.question
.question_class
= 0x1;
1343 return send_message(msg_ctx
, pid
, MSG_SEND_PACKET
, &p
, sizeof(p
));
1346 static bool do_notify_cleanup(struct tevent_context
*ev_ctx
,
1347 struct messaging_context
*msg_ctx
,
1348 const struct server_id pid
,
1349 const int argc
, const char **argv
)
1352 fprintf(stderr
, "Usage: smbcontrol smbd notify-cleanup\n");
1355 return send_message(msg_ctx
, pid
, MSG_SMB_NOTIFY_CLEANUP
, NULL
, 0);
1358 /* A list of message type supported */
1360 static const struct {
1361 const char *name
; /* Option name */
1362 bool (*fn
)(struct tevent_context
*ev_ctx
,
1363 struct messaging_context
*msg_ctx
,
1364 const struct server_id pid
,
1365 const int argc
, const char **argv
);
1366 const char *help
; /* Short help text */
1368 { "debug", do_debug
, "Set debuglevel" },
1369 { "idmap", do_idmap
, "Manipulate idmap cache" },
1370 { "force-election", do_election
,
1371 "Force a browse election" },
1372 { "ping", do_ping
, "Elicit a response" },
1373 { "profile", do_profile
, "" },
1374 { "inject", do_inject_fault
,
1375 "Inject a fatal signal into a running smbd"},
1376 { "stacktrace", do_daemon_stack_trace
,
1377 "Display a stack trace of a daemon" },
1378 { "profilelevel", do_profilelevel
, "" },
1379 { "debuglevel", do_debuglevel
, "Display current debuglevels" },
1380 { "printnotify", do_printnotify
, "Send a print notify message" },
1381 { "close-share", do_closeshare
, "Forcibly disconnect a share" },
1382 { "kill-client-ip", do_kill_client_by_ip
,
1383 "Forcibly disconnect a client with a specific IP address" },
1384 { "ip-dropped", do_ip_dropped
, "Tell winbind that an IP got dropped" },
1385 { "lockretry", do_lockretry
, "Force a blocking lock retry" },
1386 { "brl-revalidate", do_brl_revalidate
, "Revalidate all brl entries" },
1387 { "pool-usage", do_poolusage
, "Display talloc memory usage" },
1388 { "dmalloc-mark", do_dmalloc_mark
, "" },
1389 { "dmalloc-log-changed", do_dmalloc_changed
, "" },
1390 { "shutdown", do_shutdown
, "Shut down daemon" },
1391 { "drvupgrade", do_drvupgrade
, "Notify a printer driver has changed" },
1392 { "reload-config", do_reload_config
, "Force smbd or winbindd to reload config file"},
1393 { "reload-printers", do_reload_printers
, "Force smbd to reload printers"},
1394 { "nodestatus", do_nodestatus
, "Ask nmbd to do a node status request"},
1395 { "online", do_winbind_online
, "Ask winbind to go into online state"},
1396 { "offline", do_winbind_offline
, "Ask winbind to go into offline state"},
1397 { "onlinestatus", do_winbind_onlinestatus
, "Request winbind online status"},
1398 { "dump-event-list", do_dump_event_list
, "Dump event list"},
1399 { "validate-cache" , do_winbind_validate_cache
,
1400 "Validate winbind's credential cache" },
1401 { "dump-domain-list", do_winbind_dump_domain_list
, "Dump winbind domain list"},
1402 { "notify-cleanup", do_notify_cleanup
},
1403 { "num-children", do_num_children
,
1404 "Print number of smbd child processes" },
1405 { "msg-cleanup", do_msg_cleanup
},
1406 { "noop", do_noop
, "Do nothing" },
1410 /* Display usage information */
1412 static void usage(poptContext pc
)
1416 poptPrintHelp(pc
, stderr
, 0);
1418 fprintf(stderr
, "\n");
1419 fprintf(stderr
, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1422 fprintf(stderr
, "\n");
1423 fprintf(stderr
, "<message-type> is one of:\n");
1425 for (i
= 0; msg_types
[i
].name
; i
++)
1426 fprintf(stderr
, "\t%-30s%s\n", msg_types
[i
].name
,
1429 fprintf(stderr
, "\n");
1434 /* Return the pid number for a string destination */
1436 static struct server_id
parse_dest(struct messaging_context
*msg
,
1439 struct server_id result
= {-1};
1442 /* Zero is a special return value for broadcast to all processes */
1444 if (strequal(dest
, "all")) {
1445 return interpret_pid(MSG_BROADCAST_PID_STR
);
1448 /* Try self - useful for testing */
1450 if (strequal(dest
, "self")) {
1451 return messaging_server_id(msg
);
1454 /* Fix winbind typo. */
1455 if (strequal(dest
, "winbind")) {
1459 /* Check for numeric pid number */
1460 result
= interpret_pid(dest
);
1462 /* Zero isn't valid if not "all". */
1463 if (result
.pid
&& procid_valid(&result
)) {
1467 /* Look up other destinations in pidfile directory */
1469 if ((pid
= pidfile_pid(lp_pid_directory(), dest
)) != 0) {
1470 return pid_to_procid(pid
);
1473 fprintf(stderr
,"Can't find pid for destination '%s'\n", dest
);
1478 /* Execute smbcontrol command */
1480 static bool do_command(struct tevent_context
*ev_ctx
,
1481 struct messaging_context
*msg_ctx
,
1482 int argc
, const char **argv
)
1484 const char *dest
= argv
[0], *command
= argv
[1];
1485 struct server_id pid
;
1488 /* Check destination */
1490 pid
= parse_dest(msg_ctx
, dest
);
1491 if (!procid_valid(&pid
)) {
1497 for (i
= 0; msg_types
[i
].name
; i
++) {
1498 if (strequal(command
, msg_types
[i
].name
))
1499 return msg_types
[i
].fn(ev_ctx
, msg_ctx
, pid
,
1500 argc
- 1, argv
+ 1);
1503 fprintf(stderr
, "smbcontrol: unknown command '%s'\n", command
);
1508 static void smbcontrol_help(poptContext pc
,
1509 enum poptCallbackReason preason
,
1510 struct poptOption
* poption
,
1514 if (poption
->shortName
!= '?') {
1515 poptPrintUsage(pc
, stdout
, 0);
1523 struct poptOption help_options
[] = {
1524 { NULL
, '\0', POPT_ARG_CALLBACK
, (void *)&smbcontrol_help
, '\0',
1526 { "help", '?', 0, NULL
, '?', "Show this help message", NULL
},
1527 { "usage", '\0', 0, NULL
, 'u', "Display brief usage message", NULL
},
1533 int main(int argc
, const char **argv
)
1537 struct tevent_context
*evt_ctx
;
1538 struct messaging_context
*msg_ctx
;
1540 static struct poptOption long_options
[] = {
1542 { NULL
, '\0', POPT_ARG_INCLUDE_TABLE
, help_options
,
1543 0, "Help options:", NULL
},
1544 { "timeout", 't', POPT_ARG_INT
, &timeout
, 't',
1545 "Set timeout value in seconds", "TIMEOUT" },
1550 TALLOC_CTX
*frame
= talloc_stackframe();
1555 setup_logging(argv
[0], DEBUG_STDOUT
);
1557 /* Parse command line arguments using popt */
1559 pc
= poptGetContext(
1560 "smbcontrol", argc
, (const char **)argv
, long_options
, 0);
1562 poptSetOtherOptionHelp(pc
, "[OPTION...] <destination> <message-type> "
1568 while ((opt
= poptGetNextOpt(pc
)) != -1) {
1570 case 't': /* --timeout */
1573 fprintf(stderr
, "Invalid option\n");
1574 poptPrintHelp(pc
, stderr
, 0);
1579 /* We should now have the remaining command line arguments in
1580 argv. The argc parameter should have been decremented to the
1581 correct value in the above switch statement. */
1583 argv
= (const char **)poptGetArgs(pc
);
1586 while (argv
[argc
] != NULL
) {
1594 lp_load_global(get_dyn_CONFIGFILE());
1596 /* Need to invert sense of return code -- samba
1597 * routines mostly return True==1 for success, but
1600 if (!(evt_ctx
= samba_tevent_context_init(NULL
)) ||
1601 !(msg_ctx
= messaging_init(NULL
, evt_ctx
))) {
1602 fprintf(stderr
, "could not init messaging context\n");
1607 ret
= !do_command(evt_ctx
, msg_ctx
, argc
, argv
);
1608 TALLOC_FREE(msg_ctx
);