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 tevent_context
*ev_ctx
,
89 struct messaging_context
*msg_ctx
,
90 bool multiple_replies
)
92 struct tevent_timer
*te
;
93 bool timed_out
= False
;
95 if (!(te
= tevent_add_timer(ev_ctx
, NULL
,
96 timeval_current_ofs(timeout
, 0),
97 smbcontrol_timeout
, (void *)&timed_out
))) {
98 DEBUG(0, ("tevent_add_timer failed\n"));
104 if (num_replies
> 0 && !multiple_replies
)
106 ret
= tevent_loop_once(ev_ctx
);
113 /* Message handler callback that displays the PID and a string on stdout */
115 static void print_pid_string_cb(struct messaging_context
*msg
,
118 struct server_id pid
,
123 pidstr
= server_id_str(talloc_tos(), &pid
);
124 printf("PID %s: %.*s", pidstr
, (int)data
->length
,
125 (const char *)data
->data
);
130 /* Message handler callback that displays a string on stdout */
132 static void print_string_cb(struct messaging_context
*msg
,
135 struct server_id pid
,
138 printf("%*s", (int)data
->length
, (const char *)data
->data
);
142 /* Send no message. Useful for testing. */
144 static bool do_noop(struct tevent_context
*ev_ctx
,
145 struct messaging_context
*msg_ctx
,
146 const struct server_id pid
,
147 const int argc
, const char **argv
)
150 fprintf(stderr
, "Usage: smbcontrol <dest> noop\n");
154 /* Move along, nothing to see here */
159 /* Send a debug string */
161 static bool do_debug(struct tevent_context
*ev_ctx
,
162 struct messaging_context
*msg_ctx
,
163 const struct server_id pid
,
164 const int argc
, const char **argv
)
167 fprintf(stderr
, "Usage: smbcontrol <dest> debug "
172 return send_message(msg_ctx
, pid
, MSG_DEBUG
, argv
[1],
173 strlen(argv
[1]) + 1);
177 static bool do_idmap(struct tevent_context
*ev
,
178 struct messaging_context
*msg_ctx
,
179 const struct server_id pid
,
180 const int argc
, const char **argv
)
182 static const char* usage
= "Usage: "
183 "smbcontrol <dest> idmap <cmd> [arg]\n"
185 "\tdelete \"UID <uid>\"|\"GID <gid>\"|<sid>\n"
186 "\t\tkill \"UID <uid>\"|\"GID <gid>\"|<sid>\n";
187 const char* arg
= NULL
;
196 arglen
= strlen(arg
) + 1;
199 fprintf(stderr
, "%s", usage
);
203 if (strcmp(argv
[1], "delete") == 0) {
204 msg_type
= ID_CACHE_DELETE
;
206 else if (strcmp(argv
[1], "kill") == 0) {
207 msg_type
= ID_CACHE_KILL
;
209 else if (strcmp(argv
[1], "help") == 0) {
210 fprintf(stdout
, "%s", usage
);
214 fprintf(stderr
, "%s", usage
);
218 return send_message(msg_ctx
, pid
, msg_type
, arg
, arglen
);
222 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
224 /* Return the name of a process given it's PID. This will only work on Linux,
225 * but that's probably moot since this whole stack tracing implementatino is
226 * Linux-specific anyway.
228 static const char * procname(pid_t pid
, char * buf
, size_t bufsz
)
233 snprintf(path
, sizeof(path
), "/proc/%llu/cmdline",
234 (unsigned long long)pid
);
235 if ((fp
= fopen(path
, "r")) == NULL
) {
239 fgets(buf
, bufsz
, fp
);
245 static void print_stack_trace(pid_t pid
, int * count
)
248 unw_addr_space_t aspace
= NULL
;
257 if (ptrace(PTRACE_ATTACH
, pid
, NULL
, NULL
) < 0) {
259 "Failed to attach to process %llu: %s\n",
260 (unsigned long long)pid
, strerror(errno
));
264 /* Wait until the attach is complete. */
265 waitpid(pid
, NULL
, 0);
267 if (((pinfo
= _UPT_create(pid
)) == NULL
) ||
268 ((aspace
= unw_create_addr_space(&_UPT_accessors
, 0)) == NULL
)) {
269 /* Probably out of memory. */
271 "Unable to initialize stack unwind for process %llu\n",
272 (unsigned long long)pid
);
276 if ((ret
= unw_init_remote(&cursor
, aspace
, pinfo
))) {
278 "Unable to unwind stack for process %llu: %s\n",
279 (unsigned long long)pid
, unw_strerror(ret
));
287 if (procname(pid
, nbuf
, sizeof(nbuf
))) {
288 printf("Stack trace for process %llu (%s):\n",
289 (unsigned long long)pid
, nbuf
);
291 printf("Stack trace for process %llu:\n",
292 (unsigned long long)pid
);
295 while (unw_step(&cursor
) > 0) {
297 unw_get_reg(&cursor
, UNW_REG_IP
, &ip
);
298 unw_get_reg(&cursor
, UNW_REG_SP
, &sp
);
300 ret
= unw_get_proc_name(&cursor
, nbuf
, sizeof(nbuf
), &off
);
301 if (ret
!= 0 && ret
!= -UNW_ENOMEM
) {
302 snprintf(nbuf
, sizeof(nbuf
), "<unknown symbol>");
304 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
305 nbuf
, (long long)off
, (long long)ip
,
313 unw_destroy_addr_space(aspace
);
320 ptrace(PTRACE_DETACH
, pid
, NULL
, NULL
);
323 static int stack_trace_connection(const struct connections_key
*key
,
324 const struct connections_data
*crec
,
327 print_stack_trace(procid_to_pid(&crec
->pid
), (int *)priv
);
332 static bool do_daemon_stack_trace(struct tevent_context
*ev_ctx
,
333 struct messaging_context
*msg_ctx
,
334 const struct server_id pid
,
335 const int argc
, const char **argv
)
341 fprintf(stderr
, "Usage: smbcontrol <dest> stacktrace\n");
345 dest
= procid_to_pid(&pid
);
348 /* It would be nice to be able to make sure that this PID is
349 * the PID of a smbd/winbind/nmbd process, not some random PID
350 * the user liked the look of. It doesn't seem like it's worth
351 * the effort at the moment, however.
353 print_stack_trace(dest
, &count
);
355 connections_forall_read(stack_trace_connection
, &count
);
361 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
363 static bool do_daemon_stack_trace(struct tevent_context
*ev_ctx
,
364 struct messaging_context
*msg_ctx
,
365 const struct server_id pid
,
366 const int argc
, const char **argv
)
369 "Daemon stack tracing is not supported on this platform\n");
373 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
375 /* Inject a fault (fatal signal) into a running smbd */
377 static bool do_inject_fault(struct tevent_context
*ev_ctx
,
378 struct messaging_context
*msg_ctx
,
379 const struct server_id pid
,
380 const int argc
, const char **argv
)
383 fprintf(stderr
, "Usage: smbcontrol <dest> inject "
384 "<bus|hup|term|internal|segv>\n");
389 fprintf(stderr
, "Fault injection is only available in "
390 "developer builds\n");
392 #else /* DEVELOPER */
396 if (strcmp(argv
[1], "bus") == 0) {
398 } else if (strcmp(argv
[1], "hup") == 0) {
400 } else if (strcmp(argv
[1], "term") == 0) {
402 } else if (strcmp(argv
[1], "segv") == 0) {
404 } else if (strcmp(argv
[1], "internal") == 0) {
405 /* Force an internal error, ie. an unclean exit. */
408 fprintf(stderr
, "Unknown signal name '%s'\n", argv
[1]);
412 return send_message(msg_ctx
, pid
, MSG_SMB_INJECT_FAULT
,
415 #endif /* DEVELOPER */
418 /* Force a browser election */
420 static bool do_election(struct tevent_context
*ev_ctx
,
421 struct messaging_context
*msg_ctx
,
422 const struct server_id pid
,
423 const int argc
, const char **argv
)
426 fprintf(stderr
, "Usage: smbcontrol <dest> force-election\n");
430 return send_message(msg_ctx
, pid
, MSG_FORCE_ELECTION
, NULL
, 0);
433 /* Ping a samba daemon process */
435 static void pong_cb(struct messaging_context
*msg
,
438 struct server_id pid
,
441 char *src_string
= server_id_str(NULL
, &pid
);
442 printf("PONG from pid %s\n", src_string
);
443 TALLOC_FREE(src_string
);
447 static bool do_ping(struct tevent_context
*ev_ctx
,
448 struct messaging_context
*msg_ctx
,
449 const struct server_id pid
,
450 const int argc
, const char **argv
)
453 fprintf(stderr
, "Usage: smbcontrol <dest> ping\n");
457 /* Send a message and register our interest in a reply */
459 if (!send_message(msg_ctx
, pid
, MSG_PING
, NULL
, 0))
462 messaging_register(msg_ctx
, NULL
, MSG_PONG
, pong_cb
);
464 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
466 /* No replies were received within the timeout period */
468 if (num_replies
== 0)
469 printf("No replies received\n");
471 messaging_deregister(msg_ctx
, MSG_PONG
, NULL
);
476 /* Set profiling options */
478 static bool do_profile(struct tevent_context
*ev_ctx
,
479 struct messaging_context
*msg_ctx
,
480 const struct server_id pid
,
481 const int argc
, const char **argv
)
486 fprintf(stderr
, "Usage: smbcontrol <dest> profile "
487 "<off|count|on|flush>\n");
491 if (strcmp(argv
[1], "off") == 0) {
493 } else if (strcmp(argv
[1], "count") == 0) {
495 } else if (strcmp(argv
[1], "on") == 0) {
497 } else if (strcmp(argv
[1], "flush") == 0) {
500 fprintf(stderr
, "Unknown profile command '%s'\n", argv
[1]);
504 return send_message(msg_ctx
, pid
, MSG_PROFILE
, &v
, sizeof(int));
507 /* Return the profiling level */
509 static void profilelevel_cb(struct messaging_context
*msg_ctx
,
512 struct server_id pid
,
520 if (data
->length
!= sizeof(int)) {
521 fprintf(stderr
, "invalid message length %ld returned\n",
522 (unsigned long)data
->length
);
526 memcpy(&level
, data
->data
, sizeof(int));
539 s
= "count and time";
546 printf("Profiling %s on pid %u\n",s
,(unsigned int)procid_to_pid(&pid
));
549 static void profilelevel_rqst(struct messaging_context
*msg_ctx
,
552 struct server_id pid
,
557 /* Send back a dummy reply */
559 send_message(msg_ctx
, pid
, MSG_PROFILELEVEL
, &v
, sizeof(int));
562 static bool do_profilelevel(struct tevent_context
*ev_ctx
,
563 struct messaging_context
*msg_ctx
,
564 const struct server_id pid
,
565 const int argc
, const char **argv
)
568 fprintf(stderr
, "Usage: smbcontrol <dest> profilelevel\n");
572 /* Send a message and register our interest in a reply */
574 if (!send_message(msg_ctx
, pid
, MSG_REQ_PROFILELEVEL
, NULL
, 0))
577 messaging_register(msg_ctx
, NULL
, MSG_PROFILELEVEL
, profilelevel_cb
);
578 messaging_register(msg_ctx
, NULL
, MSG_REQ_PROFILELEVEL
,
581 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
583 /* No replies were received within the timeout period */
585 if (num_replies
== 0)
586 printf("No replies received\n");
588 messaging_deregister(msg_ctx
, MSG_PROFILE
, NULL
);
593 /* Display debug level settings */
595 static bool do_debuglevel(struct tevent_context
*ev_ctx
,
596 struct messaging_context
*msg_ctx
,
597 const struct server_id pid
,
598 const int argc
, const char **argv
)
601 fprintf(stderr
, "Usage: smbcontrol <dest> debuglevel\n");
605 /* Send a message and register our interest in a reply */
607 if (!send_message(msg_ctx
, pid
, MSG_REQ_DEBUGLEVEL
, NULL
, 0))
610 messaging_register(msg_ctx
, NULL
, MSG_DEBUGLEVEL
, print_pid_string_cb
);
612 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
614 /* No replies were received within the timeout period */
616 if (num_replies
== 0)
617 printf("No replies received\n");
619 messaging_deregister(msg_ctx
, MSG_DEBUGLEVEL
, NULL
);
624 /* Send a print notify message */
626 static bool do_printnotify(struct tevent_context
*ev_ctx
,
627 struct messaging_context
*msg_ctx
,
628 const struct server_id pid
,
629 const int argc
, const char **argv
)
633 /* Check for subcommand */
636 fprintf(stderr
, "Must specify subcommand:\n");
637 fprintf(stderr
, "\tqueuepause <printername>\n");
638 fprintf(stderr
, "\tqueueresume <printername>\n");
639 fprintf(stderr
, "\tjobpause <printername> <unix jobid>\n");
640 fprintf(stderr
, "\tjobresume <printername> <unix jobid>\n");
641 fprintf(stderr
, "\tjobdelete <printername> <unix jobid>\n");
642 fprintf(stderr
, "\tprinter <printername> <comment|port|"
643 "driver> <value>\n");
650 if (strcmp(cmd
, "queuepause") == 0) {
653 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
654 " queuepause <printername>\n");
658 notify_printer_status_byname(ev_ctx
, msg_ctx
, argv
[2],
659 PRINTER_STATUS_PAUSED
);
663 } else if (strcmp(cmd
, "queueresume") == 0) {
666 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
667 " queuereume <printername>\n");
671 notify_printer_status_byname(ev_ctx
, msg_ctx
, argv
[2],
676 } else if (strcmp(cmd
, "jobpause") == 0) {
680 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
681 " jobpause <printername> <unix-jobid>\n");
685 jobid
= atoi(argv
[3]);
687 notify_job_status_byname(
689 argv
[2], jobid
, JOB_STATUS_PAUSED
,
690 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
694 } else if (strcmp(cmd
, "jobresume") == 0) {
698 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
699 " jobpause <printername> <unix-jobid>\n");
703 jobid
= atoi(argv
[3]);
705 notify_job_status_byname(
707 argv
[2], jobid
, JOB_STATUS_QUEUED
,
708 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
712 } else if (strcmp(cmd
, "jobdelete") == 0) {
716 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
717 " jobpause <printername> <unix-jobid>\n");
721 jobid
= atoi(argv
[3]);
723 notify_job_status_byname(
725 argv
[2], jobid
, JOB_STATUS_DELETING
,
726 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
728 notify_job_status_byname(
730 argv
[2], jobid
, JOB_STATUS_DELETING
|
732 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
736 } else if (strcmp(cmd
, "printer") == 0) {
740 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify "
741 "printer <printername> <comment|port|driver> "
746 if (strcmp(argv
[3], "comment") == 0) {
747 attribute
= PRINTER_NOTIFY_FIELD_COMMENT
;
748 } else if (strcmp(argv
[3], "port") == 0) {
749 attribute
= PRINTER_NOTIFY_FIELD_PORT_NAME
;
750 } else if (strcmp(argv
[3], "driver") == 0) {
751 attribute
= PRINTER_NOTIFY_FIELD_DRIVER_NAME
;
753 fprintf(stderr
, "Invalid printer command '%s'\n",
758 notify_printer_byname(ev_ctx
, msg_ctx
, argv
[2], attribute
,
759 discard_const_p(char, argv
[4]));
764 fprintf(stderr
, "Invalid subcommand '%s'\n", cmd
);
768 print_notify_send_messages(msg_ctx
, 0);
774 static bool do_closeshare(struct tevent_context
*ev_ctx
,
775 struct messaging_context
*msg_ctx
,
776 const struct server_id pid
,
777 const int argc
, const char **argv
)
780 fprintf(stderr
, "Usage: smbcontrol <dest> close-share "
785 return send_message(msg_ctx
, pid
, MSG_SMB_FORCE_TDIS
, argv
[1],
786 strlen(argv
[1]) + 1);
789 /* Tell winbindd an IP got dropped */
791 static bool do_ip_dropped(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> ip-dropped "
802 return send_message(msg_ctx
, pid
, MSG_WINBIND_IP_DROPPED
, argv
[1],
803 strlen(argv
[1]) + 1);
806 /* force a blocking lock retry */
808 static bool do_lockretry(struct tevent_context
*ev_ctx
,
809 struct messaging_context
*msg_ctx
,
810 const struct server_id pid
,
811 const int argc
, const char **argv
)
814 fprintf(stderr
, "Usage: smbcontrol <dest> lockretry\n");
818 return send_message(msg_ctx
, pid
, MSG_SMB_UNLOCK
, NULL
, 0);
821 /* force a validation of all brl entries, including re-sends. */
823 static bool do_brl_revalidate(struct tevent_context
*ev_ctx
,
824 struct messaging_context
*msg_ctx
,
825 const struct server_id pid
,
826 const int argc
, const char **argv
)
829 fprintf(stderr
, "Usage: smbcontrol <dest> brl-revalidate\n");
833 return send_message(msg_ctx
, pid
, MSG_SMB_BRL_VALIDATE
, NULL
, 0);
836 /* Display talloc pool usage */
838 static bool do_poolusage(struct tevent_context
*ev_ctx
,
839 struct messaging_context
*msg_ctx
,
840 const struct server_id pid
,
841 const int argc
, const char **argv
)
844 fprintf(stderr
, "Usage: smbcontrol <dest> pool-usage\n");
848 messaging_register(msg_ctx
, NULL
, MSG_POOL_USAGE
, print_string_cb
);
850 /* Send a message and register our interest in a reply */
852 if (!send_message(msg_ctx
, pid
, MSG_REQ_POOL_USAGE
, NULL
, 0))
855 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
857 /* No replies were received within the timeout period */
859 if (num_replies
== 0)
860 printf("No replies received\n");
862 messaging_deregister(msg_ctx
, MSG_POOL_USAGE
, NULL
);
867 /* Perform a dmalloc mark */
869 static bool do_dmalloc_mark(struct tevent_context
*ev_ctx
,
870 struct messaging_context
*msg_ctx
,
871 const struct server_id pid
,
872 const int argc
, const char **argv
)
875 fprintf(stderr
, "Usage: smbcontrol <dest> dmalloc-mark\n");
879 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_MARK
, NULL
, 0);
882 /* Perform a dmalloc changed */
884 static bool do_dmalloc_changed(struct tevent_context
*ev_ctx
,
885 struct messaging_context
*msg_ctx
,
886 const struct server_id pid
,
887 const int argc
, const char **argv
)
890 fprintf(stderr
, "Usage: smbcontrol <dest> "
891 "dmalloc-log-changed\n");
895 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_LOG_CHANGED
,
899 /* Shutdown a server process */
901 static bool do_shutdown(struct tevent_context
*ev_ctx
,
902 struct messaging_context
*msg_ctx
,
903 const struct server_id pid
,
904 const int argc
, const char **argv
)
907 fprintf(stderr
, "Usage: smbcontrol <dest> shutdown\n");
911 return send_message(msg_ctx
, pid
, MSG_SHUTDOWN
, NULL
, 0);
914 /* Notify a driver upgrade */
916 static bool do_drvupgrade(struct tevent_context
*ev_ctx
,
917 struct messaging_context
*msg_ctx
,
918 const struct server_id pid
,
919 const int argc
, const char **argv
)
922 fprintf(stderr
, "Usage: smbcontrol <dest> drvupgrade "
927 return send_message(msg_ctx
, pid
, MSG_DEBUG
, argv
[1],
928 strlen(argv
[1]) + 1);
931 static bool do_winbind_online(struct tevent_context
*ev_ctx
,
932 struct messaging_context
*msg_ctx
,
933 const struct server_id pid
,
934 const int argc
, const char **argv
)
939 fprintf(stderr
, "Usage: smbcontrol winbindd online\n");
943 /* Remove the entry in the winbindd_cache tdb to tell a later
944 starting winbindd that we're online. */
946 tdb
= tdb_open_log(state_path("winbindd_cache.tdb"), 0, TDB_DEFAULT
, O_RDWR
, 0600);
948 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
949 state_path("winbindd_cache.tdb"));
953 tdb_delete_bystring(tdb
, "WINBINDD_OFFLINE");
956 return send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINE
, NULL
, 0);
959 static bool do_winbind_offline(struct tevent_context
*ev_ctx
,
960 struct messaging_context
*msg_ctx
,
961 const struct server_id pid
,
962 const int argc
, const char **argv
)
969 fprintf(stderr
, "Usage: smbcontrol winbindd offline\n");
973 /* Create an entry in the winbindd_cache tdb to tell a later
974 starting winbindd that we're offline. We may actually create
977 tdb
= tdb_open_log(state_path("winbindd_cache.tdb"),
978 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE
,
979 TDB_DEFAULT
|TDB_INCOMPATIBLE_HASH
/* TDB_CLEAR_IF_FIRST */,
980 O_RDWR
|O_CREAT
, 0600);
983 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
984 state_path("winbindd_cache.tdb"));
988 /* There's a potential race condition that if a child
989 winbindd detects a domain is online at the same time
990 we're trying to tell it to go offline that it might
991 delete the record we add between us adding it and
992 sending the message. Minimize this by retrying up to
995 for (retry
= 0; retry
< 5; retry
++) {
1001 SIVAL(buf
, 0, time(NULL
));
1005 tdb_store_bystring(tdb
, "WINBINDD_OFFLINE", d
, TDB_INSERT
);
1007 ret
= send_message(msg_ctx
, pid
, MSG_WINBIND_OFFLINE
,
1010 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
1011 d
= tdb_fetch_bystring( tdb
, "WINBINDD_OFFLINE" );
1013 if (!d
.dptr
|| d
.dsize
!= 4) {
1015 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
1026 static bool do_winbind_onlinestatus(struct tevent_context
*ev_ctx
,
1027 struct messaging_context
*msg_ctx
,
1028 const struct server_id pid
,
1029 const int argc
, const char **argv
)
1031 struct server_id myid
;
1033 myid
= messaging_server_id(msg_ctx
);
1036 fprintf(stderr
, "Usage: smbcontrol winbindd onlinestatus\n");
1040 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_ONLINESTATUS
,
1041 print_pid_string_cb
);
1043 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINESTATUS
, &myid
,
1047 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
1049 /* No replies were received within the timeout period */
1051 if (num_replies
== 0)
1052 printf("No replies received\n");
1054 messaging_deregister(msg_ctx
, MSG_WINBIND_ONLINESTATUS
, NULL
);
1059 static bool do_dump_event_list(struct tevent_context
*ev_ctx
,
1060 struct messaging_context
*msg_ctx
,
1061 const struct server_id pid
,
1062 const int argc
, const char **argv
)
1065 fprintf(stderr
, "Usage: smbcontrol <dest> dump-event-list\n");
1069 return send_message(msg_ctx
, pid
, MSG_DUMP_EVENT_LIST
, NULL
, 0);
1072 static bool do_winbind_dump_domain_list(struct tevent_context
*ev_ctx
,
1073 struct messaging_context
*msg_ctx
,
1074 const struct server_id pid
,
1075 const int argc
, const char **argv
)
1077 const char *domain
= NULL
;
1079 struct server_id myid
;
1080 uint8_t *buf
= NULL
;
1083 myid
= messaging_server_id(msg_ctx
);
1085 if (argc
< 1 || argc
> 2) {
1086 fprintf(stderr
, "Usage: smbcontrol <dest> dump-domain-list "
1093 domain_len
= strlen(argv
[1]) + 1;
1096 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1097 print_pid_string_cb
);
1099 buf_len
= sizeof(myid
)+domain_len
;
1100 buf
= SMB_MALLOC_ARRAY(uint8_t, buf_len
);
1105 memcpy(buf
, &myid
, sizeof(myid
));
1106 memcpy(&buf
[sizeof(myid
)], domain
, domain_len
);
1108 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1115 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
1117 /* No replies were received within the timeout period */
1120 if (num_replies
== 0) {
1121 printf("No replies received\n");
1124 messaging_deregister(msg_ctx
, MSG_WINBIND_DUMP_DOMAIN_LIST
, NULL
);
1129 static void winbind_validate_cache_cb(struct messaging_context
*msg
,
1132 struct server_id pid
,
1135 char *src_string
= server_id_str(NULL
, &pid
);
1136 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1137 (*(data
->data
) == 0 ? "" : "NOT "), src_string
);
1138 TALLOC_FREE(src_string
);
1142 static bool do_winbind_validate_cache(struct tevent_context
*ev_ctx
,
1143 struct messaging_context
*msg_ctx
,
1144 const struct server_id pid
,
1145 const int argc
, const char **argv
)
1147 struct server_id myid
;
1149 myid
= messaging_server_id(msg_ctx
);
1152 fprintf(stderr
, "Usage: smbcontrol winbindd validate-cache\n");
1156 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_VALIDATE_CACHE
,
1157 winbind_validate_cache_cb
);
1159 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_VALIDATE_CACHE
, &myid
,
1164 wait_replies(ev_ctx
, msg_ctx
, procid_to_pid(&pid
) == 0);
1166 if (num_replies
== 0) {
1167 printf("No replies received\n");
1170 messaging_deregister(msg_ctx
, MSG_WINBIND_VALIDATE_CACHE
, NULL
);
1175 static bool do_reload_config(struct tevent_context
*ev_ctx
,
1176 struct messaging_context
*msg_ctx
,
1177 const struct server_id pid
,
1178 const int argc
, const char **argv
)
1181 fprintf(stderr
, "Usage: smbcontrol <dest> reload-config\n");
1185 return send_message(msg_ctx
, pid
, MSG_SMB_CONF_UPDATED
, NULL
, 0);
1188 static bool do_reload_printers(struct tevent_context
*ev_ctx
,
1189 struct messaging_context
*msg_ctx
,
1190 const struct server_id pid
,
1191 const int argc
, const char **argv
)
1194 fprintf(stderr
, "Usage: smbcontrol <dest> reload-printers\n");
1198 return send_message(msg_ctx
, pid
, MSG_PRINTER_PCAP
, NULL
, 0);
1201 static void my_make_nmb_name( struct nmb_name
*n
, const char *name
, int type
)
1204 memset( (char *)n
, '\0', sizeof(struct nmb_name
) );
1205 fstrcpy(unix_name
, name
);
1206 strupper_m(unix_name
);
1207 push_ascii(n
->name
, unix_name
, sizeof(n
->name
), STR_TERMINATE
);
1208 n
->name_type
= (unsigned int)type
& 0xFF;
1209 push_ascii(n
->scope
, lp_netbios_scope(), 64, STR_TERMINATE
);
1212 static bool do_nodestatus(struct tevent_context
*ev_ctx
,
1213 struct messaging_context
*msg_ctx
,
1214 const struct server_id pid
,
1215 const int argc
, const char **argv
)
1217 struct packet_struct p
;
1220 fprintf(stderr
, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1226 p
.ip
= interpret_addr2(argv
[1]);
1228 p
.packet_type
= NMB_PACKET
;
1230 p
.packet
.nmb
.header
.name_trn_id
= 10;
1231 p
.packet
.nmb
.header
.opcode
= 0;
1232 p
.packet
.nmb
.header
.response
= False
;
1233 p
.packet
.nmb
.header
.nm_flags
.bcast
= False
;
1234 p
.packet
.nmb
.header
.nm_flags
.recursion_available
= False
;
1235 p
.packet
.nmb
.header
.nm_flags
.recursion_desired
= False
;
1236 p
.packet
.nmb
.header
.nm_flags
.trunc
= False
;
1237 p
.packet
.nmb
.header
.nm_flags
.authoritative
= False
;
1238 p
.packet
.nmb
.header
.rcode
= 0;
1239 p
.packet
.nmb
.header
.qdcount
= 1;
1240 p
.packet
.nmb
.header
.ancount
= 0;
1241 p
.packet
.nmb
.header
.nscount
= 0;
1242 p
.packet
.nmb
.header
.arcount
= 0;
1243 my_make_nmb_name(&p
.packet
.nmb
.question
.question_name
, "*", 0x00);
1244 p
.packet
.nmb
.question
.question_type
= 0x21;
1245 p
.packet
.nmb
.question
.question_class
= 0x1;
1247 return send_message(msg_ctx
, pid
, MSG_SEND_PACKET
, &p
, sizeof(p
));
1250 static bool do_notify_cleanup(struct tevent_context
*ev_ctx
,
1251 struct messaging_context
*msg_ctx
,
1252 const struct server_id pid
,
1253 const int argc
, const char **argv
)
1256 fprintf(stderr
, "Usage: smbcontrol smbd notify-cleanup\n");
1259 return send_message(msg_ctx
, pid
, MSG_SMB_NOTIFY_CLEANUP
, NULL
, 0);
1262 /* A list of message type supported */
1264 static const struct {
1265 const char *name
; /* Option name */
1266 bool (*fn
)(struct tevent_context
*ev_ctx
,
1267 struct messaging_context
*msg_ctx
,
1268 const struct server_id pid
,
1269 const int argc
, const char **argv
);
1270 const char *help
; /* Short help text */
1272 { "debug", do_debug
, "Set debuglevel" },
1273 { "idmap", do_idmap
, "Manipulate idmap cache" },
1274 { "force-election", do_election
,
1275 "Force a browse election" },
1276 { "ping", do_ping
, "Elicit a response" },
1277 { "profile", do_profile
, "" },
1278 { "inject", do_inject_fault
,
1279 "Inject a fatal signal into a running smbd"},
1280 { "stacktrace", do_daemon_stack_trace
,
1281 "Display a stack trace of a daemon" },
1282 { "profilelevel", do_profilelevel
, "" },
1283 { "debuglevel", do_debuglevel
, "Display current debuglevels" },
1284 { "printnotify", do_printnotify
, "Send a print notify message" },
1285 { "close-share", do_closeshare
, "Forcibly disconnect a share" },
1286 { "ip-dropped", do_ip_dropped
, "Tell winbind that an IP got dropped" },
1287 { "lockretry", do_lockretry
, "Force a blocking lock retry" },
1288 { "brl-revalidate", do_brl_revalidate
, "Revalidate all brl entries" },
1289 { "pool-usage", do_poolusage
, "Display talloc memory usage" },
1290 { "dmalloc-mark", do_dmalloc_mark
, "" },
1291 { "dmalloc-log-changed", do_dmalloc_changed
, "" },
1292 { "shutdown", do_shutdown
, "Shut down daemon" },
1293 { "drvupgrade", do_drvupgrade
, "Notify a printer driver has changed" },
1294 { "reload-config", do_reload_config
, "Force smbd or winbindd to reload config file"},
1295 { "reload-printers", do_reload_printers
, "Force smbd to reload printers"},
1296 { "nodestatus", do_nodestatus
, "Ask nmbd to do a node status request"},
1297 { "online", do_winbind_online
, "Ask winbind to go into online state"},
1298 { "offline", do_winbind_offline
, "Ask winbind to go into offline state"},
1299 { "onlinestatus", do_winbind_onlinestatus
, "Request winbind online status"},
1300 { "dump-event-list", do_dump_event_list
, "Dump event list"},
1301 { "validate-cache" , do_winbind_validate_cache
,
1302 "Validate winbind's credential cache" },
1303 { "dump-domain-list", do_winbind_dump_domain_list
, "Dump winbind domain list"},
1304 { "notify-cleanup", do_notify_cleanup
},
1305 { "noop", do_noop
, "Do nothing" },
1309 /* Display usage information */
1311 static void usage(poptContext pc
)
1315 poptPrintHelp(pc
, stderr
, 0);
1317 fprintf(stderr
, "\n");
1318 fprintf(stderr
, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1321 fprintf(stderr
, "\n");
1322 fprintf(stderr
, "<message-type> is one of:\n");
1324 for (i
= 0; msg_types
[i
].name
; i
++)
1325 fprintf(stderr
, "\t%-30s%s\n", msg_types
[i
].name
,
1328 fprintf(stderr
, "\n");
1333 /* Return the pid number for a string destination */
1335 static struct server_id
parse_dest(struct messaging_context
*msg
,
1338 struct server_id result
= {-1};
1341 /* Zero is a special return value for broadcast to all processes */
1343 if (strequal(dest
, "all")) {
1344 return interpret_pid(MSG_BROADCAST_PID_STR
);
1347 /* Try self - useful for testing */
1349 if (strequal(dest
, "self")) {
1350 return messaging_server_id(msg
);
1353 /* Fix winbind typo. */
1354 if (strequal(dest
, "winbind")) {
1358 /* Check for numeric pid number */
1359 result
= interpret_pid(dest
);
1361 /* Zero isn't valid if not "all". */
1362 if (result
.pid
&& procid_valid(&result
)) {
1366 /* Look up other destinations in pidfile directory */
1368 if ((pid
= pidfile_pid(dest
)) != 0) {
1369 return pid_to_procid(pid
);
1372 fprintf(stderr
,"Can't find pid for destination '%s'\n", dest
);
1377 /* Execute smbcontrol command */
1379 static bool do_command(struct tevent_context
*ev_ctx
,
1380 struct messaging_context
*msg_ctx
,
1381 int argc
, const char **argv
)
1383 const char *dest
= argv
[0], *command
= argv
[1];
1384 struct server_id pid
;
1387 /* Check destination */
1389 pid
= parse_dest(msg_ctx
, dest
);
1390 if (!procid_valid(&pid
)) {
1396 for (i
= 0; msg_types
[i
].name
; i
++) {
1397 if (strequal(command
, msg_types
[i
].name
))
1398 return msg_types
[i
].fn(ev_ctx
, msg_ctx
, pid
,
1399 argc
- 1, argv
+ 1);
1402 fprintf(stderr
, "smbcontrol: unknown command '%s'\n", command
);
1407 static void smbcontrol_help(poptContext pc
,
1408 enum poptCallbackReason preason
,
1409 struct poptOption
* poption
,
1413 if (poption
->shortName
!= '?') {
1414 poptPrintUsage(pc
, stdout
, 0);
1422 struct poptOption help_options
[] = {
1423 { NULL
, '\0', POPT_ARG_CALLBACK
, (void *)&smbcontrol_help
, '\0',
1425 { "help", '?', 0, NULL
, '?', "Show this help message", NULL
},
1426 { "usage", '\0', 0, NULL
, 'u', "Display brief usage message", NULL
},
1432 int main(int argc
, const char **argv
)
1436 struct tevent_context
*evt_ctx
;
1437 struct messaging_context
*msg_ctx
;
1439 static struct poptOption long_options
[] = {
1441 { NULL
, '\0', POPT_ARG_INCLUDE_TABLE
, help_options
,
1442 0, "Help options:", NULL
},
1443 { "timeout", 't', POPT_ARG_INT
, &timeout
, 't',
1444 "Set timeout value in seconds", "TIMEOUT" },
1449 TALLOC_CTX
*frame
= talloc_stackframe();
1454 setup_logging(argv
[0], DEBUG_STDOUT
);
1456 /* Parse command line arguments using popt */
1458 pc
= poptGetContext(
1459 "smbcontrol", argc
, (const char **)argv
, long_options
, 0);
1461 poptSetOtherOptionHelp(pc
, "[OPTION...] <destination> <message-type> "
1467 while ((opt
= poptGetNextOpt(pc
)) != -1) {
1469 case 't': /* --timeout */
1472 fprintf(stderr
, "Invalid option\n");
1473 poptPrintHelp(pc
, stderr
, 0);
1478 /* We should now have the remaining command line arguments in
1479 argv. The argc parameter should have been decremented to the
1480 correct value in the above switch statement. */
1482 argv
= (const char **)poptGetArgs(pc
);
1485 while (argv
[argc
] != NULL
) {
1493 lp_load_global(get_dyn_CONFIGFILE());
1495 /* Need to invert sense of return code -- samba
1496 * routines mostly return True==1 for success, but
1499 if (!(evt_ctx
= tevent_context_init(NULL
)) ||
1500 !(msg_ctx
= messaging_init(NULL
, evt_ctx
))) {
1501 fprintf(stderr
, "could not init messaging context\n");
1506 ret
= !do_command(evt_ctx
, msg_ctx
, argc
, argv
);