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/messaging.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 <libunwind.h>
39 #if HAVE_LIBUNWIND_PTRACE_H
40 #include <libunwind-ptrace.h>
44 #include <sys/ptrace.h>
47 /* Default timeout value when waiting for replies (in seconds) */
49 #define DEFAULT_TIMEOUT 10
51 static int timeout
= DEFAULT_TIMEOUT
;
52 static int num_replies
; /* Used by message callback fns */
54 /* Send a message to a destination pid. Zero means broadcast smbd. */
56 static bool send_message(struct messaging_context
*msg_ctx
,
57 struct server_id pid
, int msg_type
,
58 const void *buf
, int len
)
63 if (procid_to_pid(&pid
) != 0)
64 return NT_STATUS_IS_OK(
65 messaging_send_buf(msg_ctx
, pid
, msg_type
,
68 ret
= message_send_all(msg_ctx
, msg_type
, buf
, len
, &n_sent
);
69 DEBUG(10,("smbcontrol/send_message: broadcast message to "
70 "%d processes\n", n_sent
));
75 static void smbcontrol_timeout(struct tevent_context
*event_ctx
,
76 struct tevent_timer
*te
,
80 bool *timed_out
= (bool *)private_data
;
85 /* Wait for one or more reply messages */
87 static void wait_replies(struct messaging_context
*msg_ctx
,
88 bool multiple_replies
)
90 struct tevent_timer
*te
;
91 bool timed_out
= False
;
93 if (!(te
= tevent_add_timer(messaging_event_context(msg_ctx
), NULL
,
94 timeval_current_ofs(timeout
, 0),
95 smbcontrol_timeout
, (void *)&timed_out
))) {
96 DEBUG(0, ("tevent_add_timer failed\n"));
102 if (num_replies
> 0 && !multiple_replies
)
104 ret
= tevent_loop_once(messaging_event_context(msg_ctx
));
111 /* Message handler callback that displays the PID and a string on stdout */
113 static void print_pid_string_cb(struct messaging_context
*msg
,
116 struct server_id pid
,
121 pidstr
= procid_str(talloc_tos(), &pid
);
122 printf("PID %s: %.*s", pidstr
, (int)data
->length
,
123 (const char *)data
->data
);
128 /* Message handler callback that displays a string on stdout */
130 static void print_string_cb(struct messaging_context
*msg
,
133 struct server_id pid
,
136 printf("%*s", (int)data
->length
, (const char *)data
->data
);
140 /* Send no message. Useful for testing. */
142 static bool do_noop(struct 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 messaging_context
*msg_ctx
,
159 const struct server_id pid
,
160 const int argc
, const char **argv
)
163 fprintf(stderr
, "Usage: smbcontrol <dest> debug "
168 return send_message(msg_ctx
, pid
, MSG_DEBUG
, argv
[1],
169 strlen(argv
[1]) + 1);
173 static bool do_idmap(struct messaging_context
*msg_ctx
,
174 const struct server_id pid
,
175 const int argc
, const char **argv
)
177 static const char* usage
= "Usage: "
178 "smbcontrol <dest> idmap <cmd> [arg]\n"
179 "\tcmd:\tflush [gid|uid]\n"
180 "\t\tdelete \"UID <uid>\"|\"GID <gid>\"|<sid>\n"
181 "\t\tkill \"UID <uid>\"|\"GID <gid>\"|<sid>\n";
182 const char* arg
= NULL
;
191 arglen
= strlen(arg
) + 1;
194 fprintf(stderr
, "%s", usage
);
198 if (strcmp(argv
[1], "flush") == 0) {
199 msg_type
= MSG_IDMAP_FLUSH
;
201 else if (strcmp(argv
[1], "delete") == 0) {
202 msg_type
= MSG_IDMAP_DELETE
;
204 else if (strcmp(argv
[1], "kill") == 0) {
205 msg_type
= MSG_IDMAP_KILL
;
207 else if (strcmp(argv
[1], "help") == 0) {
208 fprintf(stdout
, "%s", usage
);
212 fprintf(stderr
, "%s", usage
);
216 return send_message(msg_ctx
, pid
, msg_type
, arg
, arglen
);
220 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
222 /* Return the name of a process given it's PID. This will only work on Linux,
223 * but that's probably moot since this whole stack tracing implementatino is
224 * Linux-specific anyway.
226 static const char * procname(pid_t pid
, char * buf
, size_t bufsz
)
231 snprintf(path
, sizeof(path
), "/proc/%llu/cmdline",
232 (unsigned long long)pid
);
233 if ((fp
= fopen(path
, "r")) == NULL
) {
237 fgets(buf
, bufsz
, fp
);
243 static void print_stack_trace(pid_t pid
, int * count
)
246 unw_addr_space_t aspace
= NULL
;
255 if (ptrace(PTRACE_ATTACH
, pid
, NULL
, NULL
) < 0) {
257 "Failed to attach to process %llu: %s\n",
258 (unsigned long long)pid
, strerror(errno
));
262 /* Wait until the attach is complete. */
263 waitpid(pid
, NULL
, 0);
265 if (((pinfo
= _UPT_create(pid
)) == NULL
) ||
266 ((aspace
= unw_create_addr_space(&_UPT_accessors
, 0)) == NULL
)) {
267 /* Probably out of memory. */
269 "Unable to initialize stack unwind for process %llu\n",
270 (unsigned long long)pid
);
274 if ((ret
= unw_init_remote(&cursor
, aspace
, pinfo
))) {
276 "Unable to unwind stack for process %llu: %s\n",
277 (unsigned long long)pid
, unw_strerror(ret
));
285 if (procname(pid
, nbuf
, sizeof(nbuf
))) {
286 printf("Stack trace for process %llu (%s):\n",
287 (unsigned long long)pid
, nbuf
);
289 printf("Stack trace for process %llu:\n",
290 (unsigned long long)pid
);
293 while (unw_step(&cursor
) > 0) {
295 unw_get_reg(&cursor
, UNW_REG_IP
, &ip
);
296 unw_get_reg(&cursor
, UNW_REG_SP
, &sp
);
298 ret
= unw_get_proc_name(&cursor
, nbuf
, sizeof(nbuf
), &off
);
299 if (ret
!= 0 && ret
!= -UNW_ENOMEM
) {
300 snprintf(nbuf
, sizeof(nbuf
), "<unknown symbol>");
302 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
303 nbuf
, (long long)off
, (long long)ip
,
311 unw_destroy_addr_space(aspace
);
318 ptrace(PTRACE_DETACH
, pid
, NULL
, NULL
);
321 static int stack_trace_connection(const struct connections_key
*key
,
322 const struct connections_data
*crec
,
325 print_stack_trace(procid_to_pid(&crec
->pid
), (int *)priv
);
330 static bool do_daemon_stack_trace(struct messaging_context
*msg_ctx
,
331 const struct server_id pid
,
332 const int argc
, const char **argv
)
338 fprintf(stderr
, "Usage: smbcontrol <dest> stacktrace\n");
342 dest
= procid_to_pid(&pid
);
345 /* It would be nice to be able to make sure that this PID is
346 * the PID of a smbd/winbind/nmbd process, not some random PID
347 * the user liked the look of. It doesn't seem like it's worth
348 * the effort at the moment, however.
350 print_stack_trace(dest
, &count
);
352 connections_forall_read(stack_trace_connection
, &count
);
358 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
360 static bool do_daemon_stack_trace(struct messaging_context
*msg_ctx
,
361 const struct server_id pid
,
362 const int argc
, const char **argv
)
365 "Daemon stack tracing is not supported on this platform\n");
369 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
371 /* Inject a fault (fatal signal) into a running smbd */
373 static bool do_inject_fault(struct messaging_context
*msg_ctx
,
374 const struct server_id pid
,
375 const int argc
, const char **argv
)
378 fprintf(stderr
, "Usage: smbcontrol <dest> inject "
379 "<bus|hup|term|internal|segv>\n");
384 fprintf(stderr
, "Fault injection is only available in "
385 "developer builds\n");
387 #else /* DEVELOPER */
391 if (strcmp(argv
[1], "bus") == 0) {
393 } else if (strcmp(argv
[1], "hup") == 0) {
395 } else if (strcmp(argv
[1], "term") == 0) {
397 } else if (strcmp(argv
[1], "segv") == 0) {
399 } else if (strcmp(argv
[1], "internal") == 0) {
400 /* Force an internal error, ie. an unclean exit. */
403 fprintf(stderr
, "Unknown signal name '%s'\n", argv
[1]);
407 return send_message(msg_ctx
, pid
, MSG_SMB_INJECT_FAULT
,
410 #endif /* DEVELOPER */
413 /* Force a browser election */
415 static bool do_election(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 char *src_string
= procid_str(NULL
, &pid
);
436 printf("PONG from pid %s\n", src_string
);
437 TALLOC_FREE(src_string
);
441 static bool do_ping(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(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 messaging_context
*msg_ctx
,
472 const struct server_id pid
,
473 const int argc
, const char **argv
)
478 fprintf(stderr
, "Usage: smbcontrol <dest> profile "
479 "<off|count|on|flush>\n");
483 if (strcmp(argv
[1], "off") == 0) {
485 } else if (strcmp(argv
[1], "count") == 0) {
487 } else if (strcmp(argv
[1], "on") == 0) {
489 } else if (strcmp(argv
[1], "flush") == 0) {
492 fprintf(stderr
, "Unknown profile command '%s'\n", argv
[1]);
496 return send_message(msg_ctx
, pid
, MSG_PROFILE
, &v
, sizeof(int));
499 /* Return the profiling level */
501 static void profilelevel_cb(struct messaging_context
*msg_ctx
,
504 struct server_id pid
,
512 if (data
->length
!= sizeof(int)) {
513 fprintf(stderr
, "invalid message length %ld returned\n",
514 (unsigned long)data
->length
);
518 memcpy(&level
, data
->data
, sizeof(int));
531 s
= "count and time";
538 printf("Profiling %s on pid %u\n",s
,(unsigned int)procid_to_pid(&pid
));
541 static void profilelevel_rqst(struct messaging_context
*msg_ctx
,
544 struct server_id pid
,
549 /* Send back a dummy reply */
551 send_message(msg_ctx
, pid
, MSG_PROFILELEVEL
, &v
, sizeof(int));
554 static bool do_profilelevel(struct messaging_context
*msg_ctx
,
555 const struct server_id pid
,
556 const int argc
, const char **argv
)
559 fprintf(stderr
, "Usage: smbcontrol <dest> profilelevel\n");
563 /* Send a message and register our interest in a reply */
565 if (!send_message(msg_ctx
, pid
, MSG_REQ_PROFILELEVEL
, NULL
, 0))
568 messaging_register(msg_ctx
, NULL
, MSG_PROFILELEVEL
, profilelevel_cb
);
569 messaging_register(msg_ctx
, NULL
, MSG_REQ_PROFILELEVEL
,
572 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
574 /* No replies were received within the timeout period */
576 if (num_replies
== 0)
577 printf("No replies received\n");
579 messaging_deregister(msg_ctx
, MSG_PROFILE
, NULL
);
584 /* Display debug level settings */
586 static bool do_debuglevel(struct messaging_context
*msg_ctx
,
587 const struct server_id pid
,
588 const int argc
, const char **argv
)
591 fprintf(stderr
, "Usage: smbcontrol <dest> debuglevel\n");
595 /* Send a message and register our interest in a reply */
597 if (!send_message(msg_ctx
, pid
, MSG_REQ_DEBUGLEVEL
, NULL
, 0))
600 messaging_register(msg_ctx
, NULL
, MSG_DEBUGLEVEL
, print_pid_string_cb
);
602 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
604 /* No replies were received within the timeout period */
606 if (num_replies
== 0)
607 printf("No replies received\n");
609 messaging_deregister(msg_ctx
, MSG_DEBUGLEVEL
, NULL
);
614 /* Send a print notify message */
616 static bool do_printnotify(struct messaging_context
*msg_ctx
,
617 const struct server_id pid
,
618 const int argc
, const char **argv
)
622 /* Check for subcommand */
625 fprintf(stderr
, "Must specify subcommand:\n");
626 fprintf(stderr
, "\tqueuepause <printername>\n");
627 fprintf(stderr
, "\tqueueresume <printername>\n");
628 fprintf(stderr
, "\tjobpause <printername> <unix jobid>\n");
629 fprintf(stderr
, "\tjobresume <printername> <unix jobid>\n");
630 fprintf(stderr
, "\tjobdelete <printername> <unix jobid>\n");
631 fprintf(stderr
, "\tprinter <printername> <comment|port|"
632 "driver> <value>\n");
639 if (strcmp(cmd
, "queuepause") == 0) {
642 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
643 " queuepause <printername>\n");
647 notify_printer_status_byname(messaging_event_context(msg_ctx
),
649 PRINTER_STATUS_PAUSED
);
653 } else if (strcmp(cmd
, "queueresume") == 0) {
656 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
657 " queuereume <printername>\n");
661 notify_printer_status_byname(messaging_event_context(msg_ctx
),
667 } else if (strcmp(cmd
, "jobpause") == 0) {
671 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
672 " jobpause <printername> <unix-jobid>\n");
676 jobid
= atoi(argv
[3]);
678 notify_job_status_byname(
679 messaging_event_context(msg_ctx
), msg_ctx
,
680 argv
[2], jobid
, JOB_STATUS_PAUSED
,
681 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
685 } else if (strcmp(cmd
, "jobresume") == 0) {
689 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
690 " jobpause <printername> <unix-jobid>\n");
694 jobid
= atoi(argv
[3]);
696 notify_job_status_byname(
697 messaging_event_context(msg_ctx
), msg_ctx
,
698 argv
[2], jobid
, JOB_STATUS_QUEUED
,
699 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
703 } else if (strcmp(cmd
, "jobdelete") == 0) {
707 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
708 " jobpause <printername> <unix-jobid>\n");
712 jobid
= atoi(argv
[3]);
714 notify_job_status_byname(
715 messaging_event_context(msg_ctx
), msg_ctx
,
716 argv
[2], jobid
, JOB_STATUS_DELETING
,
717 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
719 notify_job_status_byname(
720 messaging_event_context(msg_ctx
), msg_ctx
,
721 argv
[2], jobid
, JOB_STATUS_DELETING
|
723 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
727 } else if (strcmp(cmd
, "printer") == 0) {
731 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify "
732 "printer <printername> <comment|port|driver> "
737 if (strcmp(argv
[3], "comment") == 0) {
738 attribute
= PRINTER_NOTIFY_FIELD_COMMENT
;
739 } else if (strcmp(argv
[3], "port") == 0) {
740 attribute
= PRINTER_NOTIFY_FIELD_PORT_NAME
;
741 } else if (strcmp(argv
[3], "driver") == 0) {
742 attribute
= PRINTER_NOTIFY_FIELD_DRIVER_NAME
;
744 fprintf(stderr
, "Invalid printer command '%s'\n",
749 notify_printer_byname(messaging_event_context(msg_ctx
),
750 msg_ctx
, argv
[2], attribute
,
751 CONST_DISCARD(char *, argv
[4]));
756 fprintf(stderr
, "Invalid subcommand '%s'\n", cmd
);
760 print_notify_send_messages(msg_ctx
, 0);
766 static bool do_closeshare(struct messaging_context
*msg_ctx
,
767 const struct server_id pid
,
768 const int argc
, const char **argv
)
771 fprintf(stderr
, "Usage: smbcontrol <dest> close-share "
776 return send_message(msg_ctx
, pid
, MSG_SMB_FORCE_TDIS
, argv
[1],
777 strlen(argv
[1]) + 1);
780 /* Tell winbindd an IP got dropped */
782 static bool do_ip_dropped(struct messaging_context
*msg_ctx
,
783 const struct server_id pid
,
784 const int argc
, const char **argv
)
787 fprintf(stderr
, "Usage: smbcontrol <dest> ip-dropped "
792 return send_message(msg_ctx
, pid
, MSG_WINBIND_IP_DROPPED
, argv
[1],
793 strlen(argv
[1]) + 1);
796 /* force a blocking lock retry */
798 static bool do_lockretry(struct messaging_context
*msg_ctx
,
799 const struct server_id pid
,
800 const int argc
, const char **argv
)
803 fprintf(stderr
, "Usage: smbcontrol <dest> lockretry\n");
807 return send_message(msg_ctx
, pid
, MSG_SMB_UNLOCK
, NULL
, 0);
810 /* force a validation of all brl entries, including re-sends. */
812 static bool do_brl_revalidate(struct messaging_context
*msg_ctx
,
813 const struct server_id pid
,
814 const int argc
, const char **argv
)
817 fprintf(stderr
, "Usage: smbcontrol <dest> brl-revalidate\n");
821 return send_message(msg_ctx
, pid
, MSG_SMB_BRL_VALIDATE
, NULL
, 0);
824 /* Force a SAM synchronisation */
826 static bool do_samsync(struct messaging_context
*msg_ctx
,
827 const struct server_id pid
,
828 const int argc
, const char **argv
)
831 fprintf(stderr
, "Usage: smbcontrol <dest> samsync\n");
835 return send_message(msg_ctx
, pid
, MSG_SMB_SAM_SYNC
, NULL
, 0);
838 /* Force a SAM replication */
840 static bool do_samrepl(struct messaging_context
*msg_ctx
,
841 const struct server_id pid
,
842 const int argc
, const char **argv
)
845 fprintf(stderr
, "Usage: smbcontrol <dest> samrepl\n");
849 return send_message(msg_ctx
, pid
, MSG_SMB_SAM_REPL
, NULL
, 0);
852 /* Display talloc pool usage */
854 static bool do_poolusage(struct messaging_context
*msg_ctx
,
855 const struct server_id pid
,
856 const int argc
, const char **argv
)
859 fprintf(stderr
, "Usage: smbcontrol <dest> pool-usage\n");
863 messaging_register(msg_ctx
, NULL
, MSG_POOL_USAGE
, print_string_cb
);
865 /* Send a message and register our interest in a reply */
867 if (!send_message(msg_ctx
, pid
, MSG_REQ_POOL_USAGE
, NULL
, 0))
870 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
872 /* No replies were received within the timeout period */
874 if (num_replies
== 0)
875 printf("No replies received\n");
877 messaging_deregister(msg_ctx
, MSG_POOL_USAGE
, NULL
);
882 /* Perform a dmalloc mark */
884 static bool do_dmalloc_mark(struct messaging_context
*msg_ctx
,
885 const struct server_id pid
,
886 const int argc
, const char **argv
)
889 fprintf(stderr
, "Usage: smbcontrol <dest> dmalloc-mark\n");
893 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_MARK
, NULL
, 0);
896 /* Perform a dmalloc changed */
898 static bool do_dmalloc_changed(struct messaging_context
*msg_ctx
,
899 const struct server_id pid
,
900 const int argc
, const char **argv
)
903 fprintf(stderr
, "Usage: smbcontrol <dest> "
904 "dmalloc-log-changed\n");
908 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_LOG_CHANGED
,
912 /* Shutdown a server process */
914 static bool do_shutdown(struct messaging_context
*msg_ctx
,
915 const struct server_id pid
,
916 const int argc
, const char **argv
)
919 fprintf(stderr
, "Usage: smbcontrol <dest> shutdown\n");
923 return send_message(msg_ctx
, pid
, MSG_SHUTDOWN
, NULL
, 0);
926 /* Notify a driver upgrade */
928 static bool do_drvupgrade(struct messaging_context
*msg_ctx
,
929 const struct server_id pid
,
930 const int argc
, const char **argv
)
933 fprintf(stderr
, "Usage: smbcontrol <dest> drvupgrade "
938 return send_message(msg_ctx
, pid
, MSG_DEBUG
, argv
[1],
939 strlen(argv
[1]) + 1);
942 static bool do_winbind_online(struct messaging_context
*msg_ctx
,
943 const struct server_id pid
,
944 const int argc
, const char **argv
)
949 fprintf(stderr
, "Usage: smbcontrol winbindd online\n");
953 /* Remove the entry in the winbindd_cache tdb to tell a later
954 starting winbindd that we're online. */
956 tdb
= tdb_open_log(cache_path("winbindd_cache.tdb"), 0, TDB_DEFAULT
, O_RDWR
, 0600);
958 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
959 cache_path("winbindd_cache.tdb"));
963 tdb_delete_bystring(tdb
, "WINBINDD_OFFLINE");
966 return send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINE
, NULL
, 0);
969 static bool do_winbind_offline(struct messaging_context
*msg_ctx
,
970 const struct server_id pid
,
971 const int argc
, const char **argv
)
978 fprintf(stderr
, "Usage: smbcontrol winbindd offline\n");
982 /* Create an entry in the winbindd_cache tdb to tell a later
983 starting winbindd that we're offline. We may actually create
986 tdb
= tdb_open_log(cache_path("winbindd_cache.tdb"),
987 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE
,
988 TDB_DEFAULT
|TDB_INCOMPATIBLE_HASH
/* TDB_CLEAR_IF_FIRST */,
989 O_RDWR
|O_CREAT
, 0600);
992 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
993 cache_path("winbindd_cache.tdb"));
997 /* There's a potential race condition that if a child
998 winbindd detects a domain is online at the same time
999 we're trying to tell it to go offline that it might
1000 delete the record we add between us adding it and
1001 sending the message. Minimize this by retrying up to
1004 for (retry
= 0; retry
< 5; retry
++) {
1010 SIVAL(buf
, 0, time(NULL
));
1014 tdb_store_bystring(tdb
, "WINBINDD_OFFLINE", d
, TDB_INSERT
);
1016 ret
= send_message(msg_ctx
, pid
, MSG_WINBIND_OFFLINE
,
1019 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
1020 d
= tdb_fetch_bystring( tdb
, "WINBINDD_OFFLINE" );
1022 if (!d
.dptr
|| d
.dsize
!= 4) {
1024 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
1035 static bool do_winbind_onlinestatus(struct messaging_context
*msg_ctx
,
1036 const struct server_id pid
,
1037 const int argc
, const char **argv
)
1039 struct server_id myid
;
1041 myid
= messaging_server_id(msg_ctx
);
1044 fprintf(stderr
, "Usage: smbcontrol winbindd onlinestatus\n");
1048 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_ONLINESTATUS
,
1049 print_pid_string_cb
);
1051 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINESTATUS
, &myid
,
1055 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
1057 /* No replies were received within the timeout period */
1059 if (num_replies
== 0)
1060 printf("No replies received\n");
1062 messaging_deregister(msg_ctx
, MSG_WINBIND_ONLINESTATUS
, NULL
);
1067 static bool do_dump_event_list(struct messaging_context
*msg_ctx
,
1068 const struct server_id pid
,
1069 const int argc
, const char **argv
)
1071 struct server_id myid
;
1073 myid
= messaging_server_id(msg_ctx
);
1076 fprintf(stderr
, "Usage: smbcontrol <dest> dump-event-list\n");
1080 return send_message(msg_ctx
, pid
, MSG_DUMP_EVENT_LIST
, NULL
, 0);
1083 static bool do_winbind_dump_domain_list(struct messaging_context
*msg_ctx
,
1084 const struct server_id pid
,
1085 const int argc
, const char **argv
)
1087 const char *domain
= NULL
;
1089 struct server_id myid
;
1090 uint8_t *buf
= NULL
;
1093 myid
= messaging_server_id(msg_ctx
);
1095 if (argc
< 1 || argc
> 2) {
1096 fprintf(stderr
, "Usage: smbcontrol <dest> dump-domain-list "
1103 domain_len
= strlen(argv
[1]) + 1;
1106 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1107 print_pid_string_cb
);
1109 buf_len
= sizeof(myid
)+domain_len
;
1110 buf
= SMB_MALLOC_ARRAY(uint8_t, buf_len
);
1115 memcpy(buf
, &myid
, sizeof(myid
));
1116 memcpy(&buf
[sizeof(myid
)], domain
, domain_len
);
1118 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1125 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
1127 /* No replies were received within the timeout period */
1130 if (num_replies
== 0) {
1131 printf("No replies received\n");
1134 messaging_deregister(msg_ctx
, MSG_WINBIND_DUMP_DOMAIN_LIST
, NULL
);
1139 static void winbind_validate_cache_cb(struct messaging_context
*msg
,
1142 struct server_id pid
,
1145 char *src_string
= procid_str(NULL
, &pid
);
1146 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1147 (*(data
->data
) == 0 ? "" : "NOT "), src_string
);
1148 TALLOC_FREE(src_string
);
1152 static bool do_winbind_validate_cache(struct messaging_context
*msg_ctx
,
1153 const struct server_id pid
,
1154 const int argc
, const char **argv
)
1156 struct server_id myid
;
1158 myid
= messaging_server_id(msg_ctx
);
1161 fprintf(stderr
, "Usage: smbcontrol winbindd validate-cache\n");
1165 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_VALIDATE_CACHE
,
1166 winbind_validate_cache_cb
);
1168 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_VALIDATE_CACHE
, &myid
,
1173 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
1175 if (num_replies
== 0) {
1176 printf("No replies received\n");
1179 messaging_deregister(msg_ctx
, MSG_WINBIND_VALIDATE_CACHE
, NULL
);
1184 static bool do_reload_config(struct messaging_context
*msg_ctx
,
1185 const struct server_id pid
,
1186 const int argc
, const char **argv
)
1189 fprintf(stderr
, "Usage: smbcontrol <dest> reload-config\n");
1193 return send_message(msg_ctx
, pid
, MSG_SMB_CONF_UPDATED
, NULL
, 0);
1196 static void my_make_nmb_name( struct nmb_name
*n
, const char *name
, int type
)
1199 memset( (char *)n
, '\0', sizeof(struct nmb_name
) );
1200 fstrcpy(unix_name
, name
);
1201 strupper_m(unix_name
);
1202 push_ascii(n
->name
, unix_name
, sizeof(n
->name
), STR_TERMINATE
);
1203 n
->name_type
= (unsigned int)type
& 0xFF;
1204 push_ascii(n
->scope
, global_scope(), 64, STR_TERMINATE
);
1207 static bool do_nodestatus(struct messaging_context
*msg_ctx
,
1208 const struct server_id pid
,
1209 const int argc
, const char **argv
)
1211 struct packet_struct p
;
1214 fprintf(stderr
, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1220 p
.ip
= interpret_addr2(argv
[1]);
1222 p
.packet_type
= NMB_PACKET
;
1224 p
.packet
.nmb
.header
.name_trn_id
= 10;
1225 p
.packet
.nmb
.header
.opcode
= 0;
1226 p
.packet
.nmb
.header
.response
= False
;
1227 p
.packet
.nmb
.header
.nm_flags
.bcast
= False
;
1228 p
.packet
.nmb
.header
.nm_flags
.recursion_available
= False
;
1229 p
.packet
.nmb
.header
.nm_flags
.recursion_desired
= False
;
1230 p
.packet
.nmb
.header
.nm_flags
.trunc
= False
;
1231 p
.packet
.nmb
.header
.nm_flags
.authoritative
= False
;
1232 p
.packet
.nmb
.header
.rcode
= 0;
1233 p
.packet
.nmb
.header
.qdcount
= 1;
1234 p
.packet
.nmb
.header
.ancount
= 0;
1235 p
.packet
.nmb
.header
.nscount
= 0;
1236 p
.packet
.nmb
.header
.arcount
= 0;
1237 my_make_nmb_name(&p
.packet
.nmb
.question
.question_name
, "*", 0x00);
1238 p
.packet
.nmb
.question
.question_type
= 0x21;
1239 p
.packet
.nmb
.question
.question_class
= 0x1;
1241 return send_message(msg_ctx
, pid
, MSG_SEND_PACKET
, &p
, sizeof(p
));
1244 /* A list of message type supported */
1246 static const struct {
1247 const char *name
; /* Option name */
1248 bool (*fn
)(struct messaging_context
*msg_ctx
,
1249 const struct server_id pid
,
1250 const int argc
, const char **argv
);
1251 const char *help
; /* Short help text */
1253 { "debug", do_debug
, "Set debuglevel" },
1254 { "idmap", do_idmap
, "Manipulate idmap cache" },
1255 { "force-election", do_election
,
1256 "Force a browse election" },
1257 { "ping", do_ping
, "Elicit a response" },
1258 { "profile", do_profile
, "" },
1259 { "inject", do_inject_fault
,
1260 "Inject a fatal signal into a running smbd"},
1261 { "stacktrace", do_daemon_stack_trace
,
1262 "Display a stack trace of a daemon" },
1263 { "profilelevel", do_profilelevel
, "" },
1264 { "debuglevel", do_debuglevel
, "Display current debuglevels" },
1265 { "printnotify", do_printnotify
, "Send a print notify message" },
1266 { "close-share", do_closeshare
, "Forcibly disconnect a share" },
1267 { "ip-dropped", do_ip_dropped
, "Tell winbind that an IP got dropped" },
1268 { "lockretry", do_lockretry
, "Force a blocking lock retry" },
1269 { "brl-revalidate", do_brl_revalidate
, "Revalidate all brl entries" },
1270 { "samsync", do_samsync
, "Initiate SAM synchronisation" },
1271 { "samrepl", do_samrepl
, "Initiate SAM replication" },
1272 { "pool-usage", do_poolusage
, "Display talloc memory usage" },
1273 { "dmalloc-mark", do_dmalloc_mark
, "" },
1274 { "dmalloc-log-changed", do_dmalloc_changed
, "" },
1275 { "shutdown", do_shutdown
, "Shut down daemon" },
1276 { "drvupgrade", do_drvupgrade
, "Notify a printer driver has changed" },
1277 { "reload-config", do_reload_config
, "Force smbd or winbindd to reload config file"},
1278 { "nodestatus", do_nodestatus
, "Ask nmbd to do a node status request"},
1279 { "online", do_winbind_online
, "Ask winbind to go into online state"},
1280 { "offline", do_winbind_offline
, "Ask winbind to go into offline state"},
1281 { "onlinestatus", do_winbind_onlinestatus
, "Request winbind online status"},
1282 { "dump-event-list", do_dump_event_list
, "Dump event list"},
1283 { "validate-cache" , do_winbind_validate_cache
,
1284 "Validate winbind's credential cache" },
1285 { "dump-domain-list", do_winbind_dump_domain_list
, "Dump winbind domain list"},
1286 { "noop", do_noop
, "Do nothing" },
1290 /* Display usage information */
1292 static void usage(poptContext pc
)
1296 poptPrintHelp(pc
, stderr
, 0);
1298 fprintf(stderr
, "\n");
1299 fprintf(stderr
, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1302 fprintf(stderr
, "\n");
1303 fprintf(stderr
, "<message-type> is one of:\n");
1305 for (i
= 0; msg_types
[i
].name
; i
++)
1306 fprintf(stderr
, "\t%-30s%s\n", msg_types
[i
].name
,
1309 fprintf(stderr
, "\n");
1314 /* Return the pid number for a string destination */
1316 static struct server_id
parse_dest(struct messaging_context
*msg
,
1319 struct server_id result
= {-1};
1322 /* Zero is a special return value for broadcast to all processes */
1324 if (strequal(dest
, "all")) {
1325 return interpret_pid(MSG_BROADCAST_PID_STR
);
1328 /* Try self - useful for testing */
1330 if (strequal(dest
, "self")) {
1331 return messaging_server_id(msg
);
1334 /* Fix winbind typo. */
1335 if (strequal(dest
, "winbind")) {
1339 /* Check for numeric pid number */
1340 result
= interpret_pid(dest
);
1342 /* Zero isn't valid if not "all". */
1343 if (result
.pid
&& procid_valid(&result
)) {
1347 /* Look up other destinations in pidfile directory */
1349 if ((pid
= pidfile_pid(dest
)) != 0) {
1350 return pid_to_procid(pid
);
1353 fprintf(stderr
,"Can't find pid for destination '%s'\n", dest
);
1358 /* Execute smbcontrol command */
1360 static bool do_command(struct messaging_context
*msg_ctx
,
1361 int argc
, const char **argv
)
1363 const char *dest
= argv
[0], *command
= argv
[1];
1364 struct server_id pid
;
1367 /* Check destination */
1369 pid
= parse_dest(msg_ctx
, dest
);
1370 if (!procid_valid(&pid
)) {
1376 for (i
= 0; msg_types
[i
].name
; i
++) {
1377 if (strequal(command
, msg_types
[i
].name
))
1378 return msg_types
[i
].fn(msg_ctx
, pid
,
1379 argc
- 1, argv
+ 1);
1382 fprintf(stderr
, "smbcontrol: unknown command '%s'\n", command
);
1387 static void smbcontrol_help(poptContext pc
,
1388 enum poptCallbackReason preason
,
1389 struct poptOption
* poption
,
1393 if (poption
->shortName
!= '?') {
1394 poptPrintUsage(pc
, stdout
, 0);
1402 struct poptOption help_options
[] = {
1403 { NULL
, '\0', POPT_ARG_CALLBACK
, (void *)&smbcontrol_help
, '\0',
1405 { "help", '?', 0, NULL
, '?', "Show this help message", NULL
},
1406 { "usage", '\0', 0, NULL
, 'u', "Display brief usage message", NULL
},
1412 int main(int argc
, const char **argv
)
1416 struct tevent_context
*evt_ctx
;
1417 struct messaging_context
*msg_ctx
;
1419 static struct poptOption long_options
[] = {
1421 { NULL
, '\0', POPT_ARG_INCLUDE_TABLE
, help_options
,
1422 0, "Help options:", NULL
},
1423 { "timeout", 't', POPT_ARG_INT
, &timeout
, 't',
1424 "Set timeout value in seconds", "TIMEOUT" },
1429 TALLOC_CTX
*frame
= talloc_stackframe();
1434 setup_logging(argv
[0], DEBUG_STDOUT
);
1436 /* Parse command line arguments using popt */
1438 pc
= poptGetContext(
1439 "smbcontrol", argc
, (const char **)argv
, long_options
, 0);
1441 poptSetOtherOptionHelp(pc
, "[OPTION...] <destination> <message-type> "
1447 while ((opt
= poptGetNextOpt(pc
)) != -1) {
1449 case 't': /* --timeout */
1452 fprintf(stderr
, "Invalid option\n");
1453 poptPrintHelp(pc
, stderr
, 0);
1458 /* We should now have the remaining command line arguments in
1459 argv. The argc parameter should have been decremented to the
1460 correct value in the above switch statement. */
1462 argv
= (const char **)poptGetArgs(pc
);
1465 while (argv
[argc
] != NULL
) {
1473 lp_load(get_dyn_CONFIGFILE(),False
,False
,False
,True
);
1475 /* Need to invert sense of return code -- samba
1476 * routines mostly return True==1 for success, but
1479 if (!(evt_ctx
= tevent_context_init(NULL
)) ||
1480 !(msg_ctx
= messaging_init(NULL
, procid_self(), evt_ctx
))) {
1481 fprintf(stderr
, "could not init messaging context\n");
1486 ret
= !do_command(msg_ctx
, argc
, argv
);