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"
37 #include <libunwind.h>
40 #if HAVE_LIBUNWIND_PTRACE_H
41 #include <libunwind-ptrace.h>
45 #include <sys/ptrace.h>
48 /* Default timeout value when waiting for replies (in seconds) */
50 #define DEFAULT_TIMEOUT 10
52 static int timeout
= DEFAULT_TIMEOUT
;
53 static int num_replies
; /* Used by message callback fns */
55 /* Send a message to a destination pid. Zero means broadcast smbd. */
57 static bool send_message(struct messaging_context
*msg_ctx
,
58 struct server_id pid
, int msg_type
,
59 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
*)buf
, len
));
69 ret
= message_send_all(msg_ctx
, msg_type
, buf
, len
, &n_sent
);
70 DEBUG(10,("smbcontrol/send_message: broadcast message to "
71 "%d processes\n", n_sent
));
76 static void smbcontrol_timeout(struct tevent_context
*event_ctx
,
77 struct tevent_timer
*te
,
81 bool *timed_out
= (bool *)private_data
;
86 /* Wait for one or more reply messages */
88 static void wait_replies(struct messaging_context
*msg_ctx
,
89 bool multiple_replies
)
91 struct tevent_timer
*te
;
92 bool timed_out
= False
;
94 if (!(te
= tevent_add_timer(messaging_event_context(msg_ctx
), NULL
,
95 timeval_current_ofs(timeout
, 0),
96 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(messaging_event_context(msg_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
,
122 pidstr
= server_id_str(talloc_tos(), &pid
);
123 printf("PID %s: %.*s", pidstr
, (int)data
->length
,
124 (const char *)data
->data
);
129 /* Message handler callback that displays a string on stdout */
131 static void print_string_cb(struct messaging_context
*msg
,
134 struct server_id pid
,
137 printf("%*s", (int)data
->length
, (const char *)data
->data
);
141 /* Send no message. Useful for testing. */
143 static bool do_noop(struct messaging_context
*msg_ctx
,
144 const struct server_id pid
,
145 const int argc
, const char **argv
)
148 fprintf(stderr
, "Usage: smbcontrol <dest> noop\n");
152 /* Move along, nothing to see here */
157 /* Send a debug string */
159 static bool do_debug(struct 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 messaging_context
*msg_ctx
,
175 const struct server_id pid
,
176 const int argc
, const char **argv
)
178 static const char* usage
= "Usage: "
179 "smbcontrol <dest> idmap <cmd> [arg]\n"
180 "\tcmd:\tflush [gid|uid]\n"
181 "\t\tdelete \"UID <uid>\"|\"GID <gid>\"|<sid>\n"
182 "\t\tkill \"UID <uid>\"|\"GID <gid>\"|<sid>\n";
183 const char* arg
= NULL
;
192 arglen
= strlen(arg
) + 1;
195 fprintf(stderr
, "%s", usage
);
199 if (strcmp(argv
[1], "flush") == 0) {
200 msg_type
= MSG_IDMAP_FLUSH
;
202 else if (strcmp(argv
[1], "delete") == 0) {
203 msg_type
= MSG_IDMAP_DELETE
;
205 else if (strcmp(argv
[1], "kill") == 0) {
206 msg_type
= MSG_IDMAP_KILL
;
208 else if (strcmp(argv
[1], "help") == 0) {
209 fprintf(stdout
, "%s", usage
);
213 fprintf(stderr
, "%s", usage
);
217 return send_message(msg_ctx
, pid
, msg_type
, arg
, arglen
);
221 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
223 /* Return the name of a process given it's PID. This will only work on Linux,
224 * but that's probably moot since this whole stack tracing implementatino is
225 * Linux-specific anyway.
227 static const char * procname(pid_t pid
, char * buf
, size_t bufsz
)
232 snprintf(path
, sizeof(path
), "/proc/%llu/cmdline",
233 (unsigned long long)pid
);
234 if ((fp
= fopen(path
, "r")) == NULL
) {
238 fgets(buf
, bufsz
, fp
);
244 static void print_stack_trace(pid_t pid
, int * count
)
247 unw_addr_space_t aspace
= NULL
;
256 if (ptrace(PTRACE_ATTACH
, pid
, NULL
, NULL
) < 0) {
258 "Failed to attach to process %llu: %s\n",
259 (unsigned long long)pid
, strerror(errno
));
263 /* Wait until the attach is complete. */
264 waitpid(pid
, NULL
, 0);
266 if (((pinfo
= _UPT_create(pid
)) == NULL
) ||
267 ((aspace
= unw_create_addr_space(&_UPT_accessors
, 0)) == NULL
)) {
268 /* Probably out of memory. */
270 "Unable to initialize stack unwind for process %llu\n",
271 (unsigned long long)pid
);
275 if ((ret
= unw_init_remote(&cursor
, aspace
, pinfo
))) {
277 "Unable to unwind stack for process %llu: %s\n",
278 (unsigned long long)pid
, unw_strerror(ret
));
286 if (procname(pid
, nbuf
, sizeof(nbuf
))) {
287 printf("Stack trace for process %llu (%s):\n",
288 (unsigned long long)pid
, nbuf
);
290 printf("Stack trace for process %llu:\n",
291 (unsigned long long)pid
);
294 while (unw_step(&cursor
) > 0) {
296 unw_get_reg(&cursor
, UNW_REG_IP
, &ip
);
297 unw_get_reg(&cursor
, UNW_REG_SP
, &sp
);
299 ret
= unw_get_proc_name(&cursor
, nbuf
, sizeof(nbuf
), &off
);
300 if (ret
!= 0 && ret
!= -UNW_ENOMEM
) {
301 snprintf(nbuf
, sizeof(nbuf
), "<unknown symbol>");
303 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
304 nbuf
, (long long)off
, (long long)ip
,
312 unw_destroy_addr_space(aspace
);
319 ptrace(PTRACE_DETACH
, pid
, NULL
, NULL
);
322 static int stack_trace_connection(const struct connections_key
*key
,
323 const struct connections_data
*crec
,
326 print_stack_trace(procid_to_pid(&crec
->pid
), (int *)priv
);
331 static bool do_daemon_stack_trace(struct messaging_context
*msg_ctx
,
332 const struct server_id pid
,
333 const int argc
, const char **argv
)
339 fprintf(stderr
, "Usage: smbcontrol <dest> stacktrace\n");
343 dest
= procid_to_pid(&pid
);
346 /* It would be nice to be able to make sure that this PID is
347 * the PID of a smbd/winbind/nmbd process, not some random PID
348 * the user liked the look of. It doesn't seem like it's worth
349 * the effort at the moment, however.
351 print_stack_trace(dest
, &count
);
353 connections_forall_read(stack_trace_connection
, &count
);
359 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
361 static bool do_daemon_stack_trace(struct messaging_context
*msg_ctx
,
362 const struct server_id pid
,
363 const int argc
, const char **argv
)
366 "Daemon stack tracing is not supported on this platform\n");
370 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
372 /* Inject a fault (fatal signal) into a running smbd */
374 static bool do_inject_fault(struct messaging_context
*msg_ctx
,
375 const struct server_id pid
,
376 const int argc
, const char **argv
)
379 fprintf(stderr
, "Usage: smbcontrol <dest> inject "
380 "<bus|hup|term|internal|segv>\n");
385 fprintf(stderr
, "Fault injection is only available in "
386 "developer builds\n");
388 #else /* DEVELOPER */
392 if (strcmp(argv
[1], "bus") == 0) {
394 } else if (strcmp(argv
[1], "hup") == 0) {
396 } else if (strcmp(argv
[1], "term") == 0) {
398 } else if (strcmp(argv
[1], "segv") == 0) {
400 } else if (strcmp(argv
[1], "internal") == 0) {
401 /* Force an internal error, ie. an unclean exit. */
404 fprintf(stderr
, "Unknown signal name '%s'\n", argv
[1]);
408 return send_message(msg_ctx
, pid
, MSG_SMB_INJECT_FAULT
,
411 #endif /* DEVELOPER */
414 /* Force a browser election */
416 static bool do_election(struct messaging_context
*msg_ctx
,
417 const struct server_id pid
,
418 const int argc
, const char **argv
)
421 fprintf(stderr
, "Usage: smbcontrol <dest> force-election\n");
425 return send_message(msg_ctx
, pid
, MSG_FORCE_ELECTION
, NULL
, 0);
428 /* Ping a samba daemon process */
430 static void pong_cb(struct messaging_context
*msg
,
433 struct server_id pid
,
436 char *src_string
= server_id_str(NULL
, &pid
);
437 printf("PONG from pid %s\n", src_string
);
438 TALLOC_FREE(src_string
);
442 static bool do_ping(struct messaging_context
*msg_ctx
,
443 const struct server_id pid
,
444 const int argc
, const char **argv
)
447 fprintf(stderr
, "Usage: smbcontrol <dest> ping\n");
451 /* Send a message and register our interest in a reply */
453 if (!send_message(msg_ctx
, pid
, MSG_PING
, NULL
, 0))
456 messaging_register(msg_ctx
, NULL
, MSG_PONG
, pong_cb
);
458 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
460 /* No replies were received within the timeout period */
462 if (num_replies
== 0)
463 printf("No replies received\n");
465 messaging_deregister(msg_ctx
, MSG_PONG
, NULL
);
470 /* Set profiling options */
472 static bool do_profile(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 messaging_context
*msg_ctx
,
556 const struct server_id pid
,
557 const int argc
, const char **argv
)
560 fprintf(stderr
, "Usage: smbcontrol <dest> profilelevel\n");
564 /* Send a message and register our interest in a reply */
566 if (!send_message(msg_ctx
, pid
, MSG_REQ_PROFILELEVEL
, NULL
, 0))
569 messaging_register(msg_ctx
, NULL
, MSG_PROFILELEVEL
, profilelevel_cb
);
570 messaging_register(msg_ctx
, NULL
, MSG_REQ_PROFILELEVEL
,
573 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
575 /* No replies were received within the timeout period */
577 if (num_replies
== 0)
578 printf("No replies received\n");
580 messaging_deregister(msg_ctx
, MSG_PROFILE
, NULL
);
585 /* Display debug level settings */
587 static bool do_debuglevel(struct messaging_context
*msg_ctx
,
588 const struct server_id pid
,
589 const int argc
, const char **argv
)
592 fprintf(stderr
, "Usage: smbcontrol <dest> debuglevel\n");
596 /* Send a message and register our interest in a reply */
598 if (!send_message(msg_ctx
, pid
, MSG_REQ_DEBUGLEVEL
, NULL
, 0))
601 messaging_register(msg_ctx
, NULL
, MSG_DEBUGLEVEL
, print_pid_string_cb
);
603 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
605 /* No replies were received within the timeout period */
607 if (num_replies
== 0)
608 printf("No replies received\n");
610 messaging_deregister(msg_ctx
, MSG_DEBUGLEVEL
, NULL
);
615 /* Send a print notify message */
617 static bool do_printnotify(struct messaging_context
*msg_ctx
,
618 const struct server_id pid
,
619 const int argc
, const char **argv
)
623 /* Check for subcommand */
626 fprintf(stderr
, "Must specify subcommand:\n");
627 fprintf(stderr
, "\tqueuepause <printername>\n");
628 fprintf(stderr
, "\tqueueresume <printername>\n");
629 fprintf(stderr
, "\tjobpause <printername> <unix jobid>\n");
630 fprintf(stderr
, "\tjobresume <printername> <unix jobid>\n");
631 fprintf(stderr
, "\tjobdelete <printername> <unix jobid>\n");
632 fprintf(stderr
, "\tprinter <printername> <comment|port|"
633 "driver> <value>\n");
640 if (strcmp(cmd
, "queuepause") == 0) {
643 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
644 " queuepause <printername>\n");
648 notify_printer_status_byname(messaging_event_context(msg_ctx
),
650 PRINTER_STATUS_PAUSED
);
654 } else if (strcmp(cmd
, "queueresume") == 0) {
657 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
658 " queuereume <printername>\n");
662 notify_printer_status_byname(messaging_event_context(msg_ctx
),
668 } else if (strcmp(cmd
, "jobpause") == 0) {
672 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
673 " jobpause <printername> <unix-jobid>\n");
677 jobid
= atoi(argv
[3]);
679 notify_job_status_byname(
680 messaging_event_context(msg_ctx
), msg_ctx
,
681 argv
[2], jobid
, JOB_STATUS_PAUSED
,
682 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
686 } else if (strcmp(cmd
, "jobresume") == 0) {
690 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
691 " jobpause <printername> <unix-jobid>\n");
695 jobid
= atoi(argv
[3]);
697 notify_job_status_byname(
698 messaging_event_context(msg_ctx
), msg_ctx
,
699 argv
[2], jobid
, JOB_STATUS_QUEUED
,
700 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
704 } else if (strcmp(cmd
, "jobdelete") == 0) {
708 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
709 " jobpause <printername> <unix-jobid>\n");
713 jobid
= atoi(argv
[3]);
715 notify_job_status_byname(
716 messaging_event_context(msg_ctx
), msg_ctx
,
717 argv
[2], jobid
, JOB_STATUS_DELETING
,
718 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
720 notify_job_status_byname(
721 messaging_event_context(msg_ctx
), msg_ctx
,
722 argv
[2], jobid
, JOB_STATUS_DELETING
|
724 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
728 } else if (strcmp(cmd
, "printer") == 0) {
732 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify "
733 "printer <printername> <comment|port|driver> "
738 if (strcmp(argv
[3], "comment") == 0) {
739 attribute
= PRINTER_NOTIFY_FIELD_COMMENT
;
740 } else if (strcmp(argv
[3], "port") == 0) {
741 attribute
= PRINTER_NOTIFY_FIELD_PORT_NAME
;
742 } else if (strcmp(argv
[3], "driver") == 0) {
743 attribute
= PRINTER_NOTIFY_FIELD_DRIVER_NAME
;
745 fprintf(stderr
, "Invalid printer command '%s'\n",
750 notify_printer_byname(messaging_event_context(msg_ctx
),
751 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 messaging_context
*msg_ctx
,
768 const struct server_id pid
,
769 const int argc
, const char **argv
)
772 fprintf(stderr
, "Usage: smbcontrol <dest> close-share "
777 return send_message(msg_ctx
, pid
, MSG_SMB_FORCE_TDIS
, argv
[1],
778 strlen(argv
[1]) + 1);
781 /* Tell winbindd an IP got dropped */
783 static bool do_ip_dropped(struct messaging_context
*msg_ctx
,
784 const struct server_id pid
,
785 const int argc
, const char **argv
)
788 fprintf(stderr
, "Usage: smbcontrol <dest> ip-dropped "
793 return send_message(msg_ctx
, pid
, MSG_WINBIND_IP_DROPPED
, argv
[1],
794 strlen(argv
[1]) + 1);
797 /* force a blocking lock retry */
799 static bool do_lockretry(struct messaging_context
*msg_ctx
,
800 const struct server_id pid
,
801 const int argc
, const char **argv
)
804 fprintf(stderr
, "Usage: smbcontrol <dest> lockretry\n");
808 return send_message(msg_ctx
, pid
, MSG_SMB_UNLOCK
, NULL
, 0);
811 /* force a validation of all brl entries, including re-sends. */
813 static bool do_brl_revalidate(struct messaging_context
*msg_ctx
,
814 const struct server_id pid
,
815 const int argc
, const char **argv
)
818 fprintf(stderr
, "Usage: smbcontrol <dest> brl-revalidate\n");
822 return send_message(msg_ctx
, pid
, MSG_SMB_BRL_VALIDATE
, NULL
, 0);
825 /* Force a SAM synchronisation */
827 static bool do_samsync(struct messaging_context
*msg_ctx
,
828 const struct server_id pid
,
829 const int argc
, const char **argv
)
832 fprintf(stderr
, "Usage: smbcontrol <dest> samsync\n");
836 return send_message(msg_ctx
, pid
, MSG_SMB_SAM_SYNC
, NULL
, 0);
839 /* Force a SAM replication */
841 static bool do_samrepl(struct messaging_context
*msg_ctx
,
842 const struct server_id pid
,
843 const int argc
, const char **argv
)
846 fprintf(stderr
, "Usage: smbcontrol <dest> samrepl\n");
850 return send_message(msg_ctx
, pid
, MSG_SMB_SAM_REPL
, NULL
, 0);
853 /* Display talloc pool usage */
855 static bool do_poolusage(struct messaging_context
*msg_ctx
,
856 const struct server_id pid
,
857 const int argc
, const char **argv
)
860 fprintf(stderr
, "Usage: smbcontrol <dest> pool-usage\n");
864 messaging_register(msg_ctx
, NULL
, MSG_POOL_USAGE
, print_string_cb
);
866 /* Send a message and register our interest in a reply */
868 if (!send_message(msg_ctx
, pid
, MSG_REQ_POOL_USAGE
, NULL
, 0))
871 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
873 /* No replies were received within the timeout period */
875 if (num_replies
== 0)
876 printf("No replies received\n");
878 messaging_deregister(msg_ctx
, MSG_POOL_USAGE
, NULL
);
883 /* Perform a dmalloc mark */
885 static bool do_dmalloc_mark(struct messaging_context
*msg_ctx
,
886 const struct server_id pid
,
887 const int argc
, const char **argv
)
890 fprintf(stderr
, "Usage: smbcontrol <dest> dmalloc-mark\n");
894 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_MARK
, NULL
, 0);
897 /* Perform a dmalloc changed */
899 static bool do_dmalloc_changed(struct messaging_context
*msg_ctx
,
900 const struct server_id pid
,
901 const int argc
, const char **argv
)
904 fprintf(stderr
, "Usage: smbcontrol <dest> "
905 "dmalloc-log-changed\n");
909 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_LOG_CHANGED
,
913 /* Shutdown a server process */
915 static bool do_shutdown(struct messaging_context
*msg_ctx
,
916 const struct server_id pid
,
917 const int argc
, const char **argv
)
920 fprintf(stderr
, "Usage: smbcontrol <dest> shutdown\n");
924 return send_message(msg_ctx
, pid
, MSG_SHUTDOWN
, NULL
, 0);
927 /* Notify a driver upgrade */
929 static bool do_drvupgrade(struct messaging_context
*msg_ctx
,
930 const struct server_id pid
,
931 const int argc
, const char **argv
)
934 fprintf(stderr
, "Usage: smbcontrol <dest> drvupgrade "
939 return send_message(msg_ctx
, pid
, MSG_DEBUG
, argv
[1],
940 strlen(argv
[1]) + 1);
943 static bool do_winbind_online(struct messaging_context
*msg_ctx
,
944 const struct server_id pid
,
945 const int argc
, const char **argv
)
950 fprintf(stderr
, "Usage: smbcontrol winbindd online\n");
954 /* Remove the entry in the winbindd_cache tdb to tell a later
955 starting winbindd that we're online. */
957 tdb
= tdb_open_log(cache_path("winbindd_cache.tdb"), 0, TDB_DEFAULT
, O_RDWR
, 0600);
959 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
960 cache_path("winbindd_cache.tdb"));
964 tdb_delete_bystring(tdb
, "WINBINDD_OFFLINE");
967 return send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINE
, NULL
, 0);
970 static bool do_winbind_offline(struct messaging_context
*msg_ctx
,
971 const struct server_id pid
,
972 const int argc
, const char **argv
)
979 fprintf(stderr
, "Usage: smbcontrol winbindd offline\n");
983 /* Create an entry in the winbindd_cache tdb to tell a later
984 starting winbindd that we're offline. We may actually create
987 tdb
= tdb_open_log(cache_path("winbindd_cache.tdb"),
988 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE
,
989 TDB_DEFAULT
|TDB_INCOMPATIBLE_HASH
/* TDB_CLEAR_IF_FIRST */,
990 O_RDWR
|O_CREAT
, 0600);
993 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
994 cache_path("winbindd_cache.tdb"));
998 /* There's a potential race condition that if a child
999 winbindd detects a domain is online at the same time
1000 we're trying to tell it to go offline that it might
1001 delete the record we add between us adding it and
1002 sending the message. Minimize this by retrying up to
1005 for (retry
= 0; retry
< 5; retry
++) {
1011 SIVAL(buf
, 0, time(NULL
));
1015 tdb_store_bystring(tdb
, "WINBINDD_OFFLINE", d
, TDB_INSERT
);
1017 ret
= send_message(msg_ctx
, pid
, MSG_WINBIND_OFFLINE
,
1020 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
1021 d
= tdb_fetch_bystring( tdb
, "WINBINDD_OFFLINE" );
1023 if (!d
.dptr
|| d
.dsize
!= 4) {
1025 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
1036 static bool do_winbind_onlinestatus(struct messaging_context
*msg_ctx
,
1037 const struct server_id pid
,
1038 const int argc
, const char **argv
)
1040 struct server_id myid
;
1042 myid
= messaging_server_id(msg_ctx
);
1045 fprintf(stderr
, "Usage: smbcontrol winbindd onlinestatus\n");
1049 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_ONLINESTATUS
,
1050 print_pid_string_cb
);
1052 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINESTATUS
, &myid
,
1056 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
1058 /* No replies were received within the timeout period */
1060 if (num_replies
== 0)
1061 printf("No replies received\n");
1063 messaging_deregister(msg_ctx
, MSG_WINBIND_ONLINESTATUS
, NULL
);
1068 static bool do_dump_event_list(struct messaging_context
*msg_ctx
,
1069 const struct server_id pid
,
1070 const int argc
, const char **argv
)
1072 struct server_id myid
;
1074 myid
= messaging_server_id(msg_ctx
);
1077 fprintf(stderr
, "Usage: smbcontrol <dest> dump-event-list\n");
1081 return send_message(msg_ctx
, pid
, MSG_DUMP_EVENT_LIST
, NULL
, 0);
1084 static bool do_winbind_dump_domain_list(struct messaging_context
*msg_ctx
,
1085 const struct server_id pid
,
1086 const int argc
, const char **argv
)
1088 const char *domain
= NULL
;
1090 struct server_id myid
;
1091 uint8_t *buf
= NULL
;
1094 myid
= messaging_server_id(msg_ctx
);
1096 if (argc
< 1 || argc
> 2) {
1097 fprintf(stderr
, "Usage: smbcontrol <dest> dump-domain-list "
1104 domain_len
= strlen(argv
[1]) + 1;
1107 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1108 print_pid_string_cb
);
1110 buf_len
= sizeof(myid
)+domain_len
;
1111 buf
= SMB_MALLOC_ARRAY(uint8_t, buf_len
);
1116 memcpy(buf
, &myid
, sizeof(myid
));
1117 memcpy(&buf
[sizeof(myid
)], domain
, domain_len
);
1119 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1126 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
1128 /* No replies were received within the timeout period */
1131 if (num_replies
== 0) {
1132 printf("No replies received\n");
1135 messaging_deregister(msg_ctx
, MSG_WINBIND_DUMP_DOMAIN_LIST
, NULL
);
1140 static void winbind_validate_cache_cb(struct messaging_context
*msg
,
1143 struct server_id pid
,
1146 char *src_string
= server_id_str(NULL
, &pid
);
1147 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1148 (*(data
->data
) == 0 ? "" : "NOT "), src_string
);
1149 TALLOC_FREE(src_string
);
1153 static bool do_winbind_validate_cache(struct messaging_context
*msg_ctx
,
1154 const struct server_id pid
,
1155 const int argc
, const char **argv
)
1157 struct server_id myid
;
1159 myid
= messaging_server_id(msg_ctx
);
1162 fprintf(stderr
, "Usage: smbcontrol winbindd validate-cache\n");
1166 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_VALIDATE_CACHE
,
1167 winbind_validate_cache_cb
);
1169 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_VALIDATE_CACHE
, &myid
,
1174 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
1176 if (num_replies
== 0) {
1177 printf("No replies received\n");
1180 messaging_deregister(msg_ctx
, MSG_WINBIND_VALIDATE_CACHE
, NULL
);
1185 static bool do_reload_config(struct messaging_context
*msg_ctx
,
1186 const struct server_id pid
,
1187 const int argc
, const char **argv
)
1190 fprintf(stderr
, "Usage: smbcontrol <dest> reload-config\n");
1194 return send_message(msg_ctx
, pid
, MSG_SMB_CONF_UPDATED
, NULL
, 0);
1197 static void my_make_nmb_name( struct nmb_name
*n
, const char *name
, int type
)
1200 memset( (char *)n
, '\0', sizeof(struct nmb_name
) );
1201 fstrcpy(unix_name
, name
);
1202 strupper_m(unix_name
);
1203 push_ascii(n
->name
, unix_name
, sizeof(n
->name
), STR_TERMINATE
);
1204 n
->name_type
= (unsigned int)type
& 0xFF;
1205 push_ascii(n
->scope
, lp_netbios_scope(), 64, STR_TERMINATE
);
1208 static bool do_nodestatus(struct messaging_context
*msg_ctx
,
1209 const struct server_id pid
,
1210 const int argc
, const char **argv
)
1212 struct packet_struct p
;
1215 fprintf(stderr
, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1221 p
.ip
= interpret_addr2(argv
[1]);
1223 p
.packet_type
= NMB_PACKET
;
1225 p
.packet
.nmb
.header
.name_trn_id
= 10;
1226 p
.packet
.nmb
.header
.opcode
= 0;
1227 p
.packet
.nmb
.header
.response
= False
;
1228 p
.packet
.nmb
.header
.nm_flags
.bcast
= False
;
1229 p
.packet
.nmb
.header
.nm_flags
.recursion_available
= False
;
1230 p
.packet
.nmb
.header
.nm_flags
.recursion_desired
= False
;
1231 p
.packet
.nmb
.header
.nm_flags
.trunc
= False
;
1232 p
.packet
.nmb
.header
.nm_flags
.authoritative
= False
;
1233 p
.packet
.nmb
.header
.rcode
= 0;
1234 p
.packet
.nmb
.header
.qdcount
= 1;
1235 p
.packet
.nmb
.header
.ancount
= 0;
1236 p
.packet
.nmb
.header
.nscount
= 0;
1237 p
.packet
.nmb
.header
.arcount
= 0;
1238 my_make_nmb_name(&p
.packet
.nmb
.question
.question_name
, "*", 0x00);
1239 p
.packet
.nmb
.question
.question_type
= 0x21;
1240 p
.packet
.nmb
.question
.question_class
= 0x1;
1242 return send_message(msg_ctx
, pid
, MSG_SEND_PACKET
, &p
, sizeof(p
));
1245 /* A list of message type supported */
1247 static const struct {
1248 const char *name
; /* Option name */
1249 bool (*fn
)(struct messaging_context
*msg_ctx
,
1250 const struct server_id pid
,
1251 const int argc
, const char **argv
);
1252 const char *help
; /* Short help text */
1254 { "debug", do_debug
, "Set debuglevel" },
1255 { "idmap", do_idmap
, "Manipulate idmap cache" },
1256 { "force-election", do_election
,
1257 "Force a browse election" },
1258 { "ping", do_ping
, "Elicit a response" },
1259 { "profile", do_profile
, "" },
1260 { "inject", do_inject_fault
,
1261 "Inject a fatal signal into a running smbd"},
1262 { "stacktrace", do_daemon_stack_trace
,
1263 "Display a stack trace of a daemon" },
1264 { "profilelevel", do_profilelevel
, "" },
1265 { "debuglevel", do_debuglevel
, "Display current debuglevels" },
1266 { "printnotify", do_printnotify
, "Send a print notify message" },
1267 { "close-share", do_closeshare
, "Forcibly disconnect a share" },
1268 { "ip-dropped", do_ip_dropped
, "Tell winbind that an IP got dropped" },
1269 { "lockretry", do_lockretry
, "Force a blocking lock retry" },
1270 { "brl-revalidate", do_brl_revalidate
, "Revalidate all brl entries" },
1271 { "samsync", do_samsync
, "Initiate SAM synchronisation" },
1272 { "samrepl", do_samrepl
, "Initiate SAM replication" },
1273 { "pool-usage", do_poolusage
, "Display talloc memory usage" },
1274 { "dmalloc-mark", do_dmalloc_mark
, "" },
1275 { "dmalloc-log-changed", do_dmalloc_changed
, "" },
1276 { "shutdown", do_shutdown
, "Shut down daemon" },
1277 { "drvupgrade", do_drvupgrade
, "Notify a printer driver has changed" },
1278 { "reload-config", do_reload_config
, "Force smbd or winbindd to reload config file"},
1279 { "nodestatus", do_nodestatus
, "Ask nmbd to do a node status request"},
1280 { "online", do_winbind_online
, "Ask winbind to go into online state"},
1281 { "offline", do_winbind_offline
, "Ask winbind to go into offline state"},
1282 { "onlinestatus", do_winbind_onlinestatus
, "Request winbind online status"},
1283 { "dump-event-list", do_dump_event_list
, "Dump event list"},
1284 { "validate-cache" , do_winbind_validate_cache
,
1285 "Validate winbind's credential cache" },
1286 { "dump-domain-list", do_winbind_dump_domain_list
, "Dump winbind domain list"},
1287 { "noop", do_noop
, "Do nothing" },
1291 /* Display usage information */
1293 static void usage(poptContext pc
)
1297 poptPrintHelp(pc
, stderr
, 0);
1299 fprintf(stderr
, "\n");
1300 fprintf(stderr
, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1303 fprintf(stderr
, "\n");
1304 fprintf(stderr
, "<message-type> is one of:\n");
1306 for (i
= 0; msg_types
[i
].name
; i
++)
1307 fprintf(stderr
, "\t%-30s%s\n", msg_types
[i
].name
,
1310 fprintf(stderr
, "\n");
1315 /* Return the pid number for a string destination */
1317 static struct server_id
parse_dest(struct messaging_context
*msg
,
1320 struct server_id result
= {-1};
1323 /* Zero is a special return value for broadcast to all processes */
1325 if (strequal(dest
, "all")) {
1326 return interpret_pid(MSG_BROADCAST_PID_STR
);
1329 /* Try self - useful for testing */
1331 if (strequal(dest
, "self")) {
1332 return messaging_server_id(msg
);
1335 /* Fix winbind typo. */
1336 if (strequal(dest
, "winbind")) {
1340 /* Check for numeric pid number */
1341 result
= interpret_pid(dest
);
1343 /* Zero isn't valid if not "all". */
1344 if (result
.pid
&& procid_valid(&result
)) {
1348 /* Look up other destinations in pidfile directory */
1350 if ((pid
= pidfile_pid(dest
)) != 0) {
1351 return pid_to_procid(pid
);
1354 fprintf(stderr
,"Can't find pid for destination '%s'\n", dest
);
1359 /* Execute smbcontrol command */
1361 static bool do_command(struct messaging_context
*msg_ctx
,
1362 int argc
, const char **argv
)
1364 const char *dest
= argv
[0], *command
= argv
[1];
1365 struct server_id pid
;
1368 /* Check destination */
1370 pid
= parse_dest(msg_ctx
, dest
);
1371 if (!procid_valid(&pid
)) {
1377 for (i
= 0; msg_types
[i
].name
; i
++) {
1378 if (strequal(command
, msg_types
[i
].name
))
1379 return msg_types
[i
].fn(msg_ctx
, pid
,
1380 argc
- 1, argv
+ 1);
1383 fprintf(stderr
, "smbcontrol: unknown command '%s'\n", command
);
1388 static void smbcontrol_help(poptContext pc
,
1389 enum poptCallbackReason preason
,
1390 struct poptOption
* poption
,
1394 if (poption
->shortName
!= '?') {
1395 poptPrintUsage(pc
, stdout
, 0);
1403 struct poptOption help_options
[] = {
1404 { NULL
, '\0', POPT_ARG_CALLBACK
, (void *)&smbcontrol_help
, '\0',
1406 { "help", '?', 0, NULL
, '?', "Show this help message", NULL
},
1407 { "usage", '\0', 0, NULL
, 'u', "Display brief usage message", NULL
},
1413 int main(int argc
, const char **argv
)
1417 struct tevent_context
*evt_ctx
;
1418 struct messaging_context
*msg_ctx
;
1420 static struct poptOption long_options
[] = {
1422 { NULL
, '\0', POPT_ARG_INCLUDE_TABLE
, help_options
,
1423 0, "Help options:", NULL
},
1424 { "timeout", 't', POPT_ARG_INT
, &timeout
, 't',
1425 "Set timeout value in seconds", "TIMEOUT" },
1430 TALLOC_CTX
*frame
= talloc_stackframe();
1435 setup_logging(argv
[0], DEBUG_STDOUT
);
1437 /* Parse command line arguments using popt */
1439 pc
= poptGetContext(
1440 "smbcontrol", argc
, (const char **)argv
, long_options
, 0);
1442 poptSetOtherOptionHelp(pc
, "[OPTION...] <destination> <message-type> "
1448 while ((opt
= poptGetNextOpt(pc
)) != -1) {
1450 case 't': /* --timeout */
1453 fprintf(stderr
, "Invalid option\n");
1454 poptPrintHelp(pc
, stderr
, 0);
1459 /* We should now have the remaining command line arguments in
1460 argv. The argc parameter should have been decremented to the
1461 correct value in the above switch statement. */
1463 argv
= (const char **)poptGetArgs(pc
);
1466 while (argv
[argc
] != NULL
) {
1474 lp_load_global(get_dyn_CONFIGFILE());
1476 /* Need to invert sense of return code -- samba
1477 * routines mostly return True==1 for success, but
1480 if (!(evt_ctx
= tevent_context_init(NULL
)) ||
1481 !(msg_ctx
= messaging_init(NULL
, procid_self(), evt_ctx
))) {
1482 fprintf(stderr
, "could not init messaging context\n");
1487 ret
= !do_command(msg_ctx
, argc
, argv
);