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/>.
29 #include <libunwind.h>
32 #if HAVE_LIBUNWIND_PTRACE_H
33 #include <libunwind-ptrace.h>
37 #include <sys/ptrace.h>
40 /* Default timeout value when waiting for replies (in seconds) */
42 #define DEFAULT_TIMEOUT 10
44 static int timeout
= DEFAULT_TIMEOUT
;
45 static int num_replies
; /* Used by message callback fns */
47 /* Send a message to a destination pid. Zero means broadcast smbd. */
49 static bool send_message(struct messaging_context
*msg_ctx
,
50 struct server_id pid
, int msg_type
,
51 const void *buf
, int len
)
56 if (procid_to_pid(&pid
) != 0)
57 return NT_STATUS_IS_OK(
58 messaging_send_buf(msg_ctx
, pid
, msg_type
,
61 ret
= message_send_all(msg_ctx
, msg_type
, buf
, len
, &n_sent
);
62 DEBUG(10,("smbcontrol/send_message: broadcast message to "
63 "%d processes\n", n_sent
));
68 static void timeout_handler(struct event_context
*event_ctx
,
69 struct timed_event
*te
,
70 const struct timeval
*now
,
73 bool *timed_out
= (bool *)private_data
;
78 /* Wait for one or more reply messages */
80 static void wait_replies(struct messaging_context
*msg_ctx
,
81 bool multiple_replies
)
83 struct timed_event
*te
;
84 bool timed_out
= False
;
86 if (!(te
= event_add_timed(messaging_event_context(msg_ctx
), NULL
,
87 timeval_current_ofs(timeout
, 0),
89 timeout_handler
, (void *)&timed_out
))) {
90 DEBUG(0, ("event_add_timed failed\n"));
95 message_dispatch(msg_ctx
);
96 if (num_replies
> 0 && !multiple_replies
)
98 event_loop_once(messaging_event_context(msg_ctx
));
102 /* Message handler callback that displays the PID and a string on stdout */
104 static void print_pid_string_cb(struct messaging_context
*msg
,
107 struct server_id pid
,
110 printf("PID %u: %.*s", (unsigned int)procid_to_pid(&pid
),
111 (int)data
->length
, (const char *)data
->data
);
115 /* Message handler callback that displays a string on stdout */
117 static void print_string_cb(struct messaging_context
*msg
,
120 struct server_id pid
,
123 printf("%.*s", (int)data
->length
, (const char *)data
->data
);
127 /* Send no message. Useful for testing. */
129 static bool do_noop(struct messaging_context
*msg_ctx
,
130 const struct server_id pid
,
131 const int argc
, const char **argv
)
134 fprintf(stderr
, "Usage: smbcontrol <dest> noop\n");
138 /* Move along, nothing to see here */
143 /* Send a debug string */
145 static bool do_debug(struct messaging_context
*msg_ctx
,
146 const struct server_id pid
,
147 const int argc
, const char **argv
)
150 fprintf(stderr
, "Usage: smbcontrol <dest> debug "
155 return send_message(msg_ctx
, pid
, MSG_DEBUG
, argv
[1],
156 strlen(argv
[1]) + 1);
159 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
161 /* Return the name of a process given it's PID. This will only work on Linux,
162 * but that's probably moot since this whole stack tracing implementatino is
163 * Linux-specific anyway.
165 static const char * procname(pid_t pid
, char * buf
, size_t bufsz
)
170 snprintf(path
, sizeof(path
), "/proc/%llu/cmdline",
171 (unsigned long long)pid
);
172 if ((fp
= fopen(path
, "r")) == NULL
) {
176 fgets(buf
, bufsz
, fp
);
182 static void print_stack_trace(pid_t pid
, int * count
)
185 unw_addr_space_t aspace
= NULL
;
194 if (ptrace(PTRACE_ATTACH
, pid
, NULL
, NULL
) < 0) {
196 "Failed to attach to process %llu: %s\n",
197 (unsigned long long)pid
, strerror(errno
));
201 /* Wait until the attach is complete. */
202 waitpid(pid
, NULL
, 0);
204 if (((pinfo
= _UPT_create(pid
)) == NULL
) ||
205 ((aspace
= unw_create_addr_space(&_UPT_accessors
, 0)) == NULL
)) {
206 /* Probably out of memory. */
208 "Unable to initialize stack unwind for process %llu\n",
209 (unsigned long long)pid
);
213 if ((ret
= unw_init_remote(&cursor
, aspace
, pinfo
))) {
215 "Unable to unwind stack for process %llu: %s\n",
216 (unsigned long long)pid
, unw_strerror(ret
));
224 if (procname(pid
, nbuf
, sizeof(nbuf
))) {
225 printf("Stack trace for process %llu (%s):\n",
226 (unsigned long long)pid
, nbuf
);
228 printf("Stack trace for process %llu:\n",
229 (unsigned long long)pid
);
232 while (unw_step(&cursor
) > 0) {
234 unw_get_reg(&cursor
, UNW_REG_IP
, &ip
);
235 unw_get_reg(&cursor
, UNW_REG_SP
, &sp
);
237 ret
= unw_get_proc_name(&cursor
, nbuf
, sizeof(nbuf
), &off
);
238 if (ret
!= 0 && ret
!= -UNW_ENOMEM
) {
239 snprintf(nbuf
, sizeof(nbuf
), "<unknown symbol>");
241 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
242 nbuf
, (long long)off
, (long long)ip
,
250 unw_destroy_addr_space(aspace
);
257 ptrace(PTRACE_DETACH
, pid
, NULL
, NULL
);
260 static int stack_trace_connection(struct db_record
*rec
,
261 const struct connections_key
*key
,
262 const struct connections_data
*crec
,
265 print_stack_trace(procid_to_pid(&crec
->pid
), (int *)priv
);
270 static bool do_daemon_stack_trace(struct messaging_context
*msg_ctx
,
271 const struct server_id pid
,
272 const int argc
, const char **argv
)
278 fprintf(stderr
, "Usage: smbcontrol <dest> stacktrace\n");
282 dest
= procid_to_pid(&pid
);
285 /* It would be nice to be able to make sure that this PID is
286 * the PID of a smbd/winbind/nmbd process, not some random PID
287 * the user liked the look of. It doesn't seem like it's worth
288 * the effort at the moment, however.
290 print_stack_trace(dest
, &count
);
292 connections_forall(stack_trace_connection
, &count
);
298 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
300 static bool do_daemon_stack_trace(struct messaging_context
*msg_ctx
,
301 const struct server_id pid
,
302 const int argc
, const char **argv
)
305 "Daemon stack tracing is not supported on this platform\n");
309 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
311 /* Inject a fault (fatal signal) into a running smbd */
313 static bool do_inject_fault(struct messaging_context
*msg_ctx
,
314 const struct server_id pid
,
315 const int argc
, const char **argv
)
318 fprintf(stderr
, "Usage: smbcontrol <dest> inject "
319 "<bus|hup|term|internal|segv>\n");
324 fprintf(stderr
, "Fault injection is only available in "
325 "developer builds\n");
327 #else /* DEVELOPER */
331 if (strcmp(argv
[1], "bus") == 0) {
333 } else if (strcmp(argv
[1], "hup") == 0) {
335 } else if (strcmp(argv
[1], "term") == 0) {
337 } else if (strcmp(argv
[1], "segv") == 0) {
339 } else if (strcmp(argv
[1], "internal") == 0) {
340 /* Force an internal error, ie. an unclean exit. */
343 fprintf(stderr
, "Unknown signal name '%s'\n", argv
[1]);
347 return send_message(msg_ctx
, pid
, MSG_SMB_INJECT_FAULT
,
350 #endif /* DEVELOPER */
353 /* Force a browser election */
355 static bool do_election(struct messaging_context
*msg_ctx
,
356 const struct server_id pid
,
357 const int argc
, const char **argv
)
360 fprintf(stderr
, "Usage: smbcontrol <dest> force-election\n");
364 return send_message(msg_ctx
, pid
, MSG_FORCE_ELECTION
, NULL
, 0);
367 /* Ping a samba daemon process */
369 static void pong_cb(struct messaging_context
*msg
,
372 struct server_id pid
,
375 char *src_string
= procid_str(NULL
, &pid
);
376 printf("PONG from pid %s\n", src_string
);
377 TALLOC_FREE(src_string
);
381 static bool do_ping(struct messaging_context
*msg_ctx
,
382 const struct server_id pid
,
383 const int argc
, const char **argv
)
386 fprintf(stderr
, "Usage: smbcontrol <dest> ping\n");
390 /* Send a message and register our interest in a reply */
392 if (!send_message(msg_ctx
, pid
, MSG_PING
, NULL
, 0))
395 messaging_register(msg_ctx
, NULL
, MSG_PONG
, pong_cb
);
397 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
399 /* No replies were received within the timeout period */
401 if (num_replies
== 0)
402 printf("No replies received\n");
404 messaging_deregister(msg_ctx
, MSG_PONG
, NULL
);
409 /* Set profiling options */
411 static bool do_profile(struct messaging_context
*msg_ctx
,
412 const struct server_id pid
,
413 const int argc
, const char **argv
)
418 fprintf(stderr
, "Usage: smbcontrol <dest> profile "
419 "<off|count|on|flush>\n");
423 if (strcmp(argv
[1], "off") == 0) {
425 } else if (strcmp(argv
[1], "count") == 0) {
427 } else if (strcmp(argv
[1], "on") == 0) {
429 } else if (strcmp(argv
[1], "flush") == 0) {
432 fprintf(stderr
, "Unknown profile command '%s'\n", argv
[1]);
436 return send_message(msg_ctx
, pid
, MSG_PROFILE
, &v
, sizeof(int));
439 /* Return the profiling level */
441 static void profilelevel_cb(struct messaging_context
*msg_ctx
,
444 struct server_id pid
,
452 if (data
->length
!= sizeof(int)) {
453 fprintf(stderr
, "invalid message length %ld returned\n",
454 (unsigned long)data
->length
);
458 memcpy(&level
, data
->data
, sizeof(int));
471 s
= "count and time";
478 printf("Profiling %s on pid %u\n",s
,(unsigned int)procid_to_pid(&pid
));
481 static void profilelevel_rqst(struct messaging_context
*msg_ctx
,
484 struct server_id pid
,
489 /* Send back a dummy reply */
491 send_message(msg_ctx
, pid
, MSG_PROFILELEVEL
, &v
, sizeof(int));
494 static bool do_profilelevel(struct messaging_context
*msg_ctx
,
495 const struct server_id pid
,
496 const int argc
, const char **argv
)
499 fprintf(stderr
, "Usage: smbcontrol <dest> profilelevel\n");
503 /* Send a message and register our interest in a reply */
505 if (!send_message(msg_ctx
, pid
, MSG_REQ_PROFILELEVEL
, NULL
, 0))
508 messaging_register(msg_ctx
, NULL
, MSG_PROFILELEVEL
, profilelevel_cb
);
509 messaging_register(msg_ctx
, NULL
, MSG_REQ_PROFILELEVEL
,
512 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
514 /* No replies were received within the timeout period */
516 if (num_replies
== 0)
517 printf("No replies received\n");
519 messaging_deregister(msg_ctx
, MSG_PROFILE
, NULL
);
524 /* Display debug level settings */
526 static bool do_debuglevel(struct messaging_context
*msg_ctx
,
527 const struct server_id pid
,
528 const int argc
, const char **argv
)
531 fprintf(stderr
, "Usage: smbcontrol <dest> debuglevel\n");
535 /* Send a message and register our interest in a reply */
537 if (!send_message(msg_ctx
, pid
, MSG_REQ_DEBUGLEVEL
, NULL
, 0))
540 messaging_register(msg_ctx
, NULL
, MSG_DEBUGLEVEL
, print_pid_string_cb
);
542 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
544 /* No replies were received within the timeout period */
546 if (num_replies
== 0)
547 printf("No replies received\n");
549 messaging_deregister(msg_ctx
, MSG_DEBUGLEVEL
, NULL
);
554 /* Send a print notify message */
556 static bool do_printnotify(struct messaging_context
*msg_ctx
,
557 const struct server_id pid
,
558 const int argc
, const char **argv
)
562 /* Check for subcommand */
565 fprintf(stderr
, "Must specify subcommand:\n");
566 fprintf(stderr
, "\tqueuepause <printername>\n");
567 fprintf(stderr
, "\tqueueresume <printername>\n");
568 fprintf(stderr
, "\tjobpause <printername> <unix jobid>\n");
569 fprintf(stderr
, "\tjobresume <printername> <unix jobid>\n");
570 fprintf(stderr
, "\tjobdelete <printername> <unix jobid>\n");
571 fprintf(stderr
, "\tprinter <printername> <comment|port|"
572 "driver> <value>\n");
579 if (strcmp(cmd
, "queuepause") == 0) {
582 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
583 " queuepause <printername>\n");
587 notify_printer_status_byname(argv
[2], PRINTER_STATUS_PAUSED
);
591 } else if (strcmp(cmd
, "queueresume") == 0) {
594 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
595 " queuereume <printername>\n");
599 notify_printer_status_byname(argv
[2], PRINTER_STATUS_OK
);
603 } else if (strcmp(cmd
, "jobpause") == 0) {
607 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
608 " jobpause <printername> <unix-jobid>\n");
612 jobid
= atoi(argv
[3]);
614 notify_job_status_byname(
615 argv
[2], jobid
, JOB_STATUS_PAUSED
,
616 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
620 } else if (strcmp(cmd
, "jobresume") == 0) {
624 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
625 " jobpause <printername> <unix-jobid>\n");
629 jobid
= atoi(argv
[3]);
631 notify_job_status_byname(
632 argv
[2], jobid
, JOB_STATUS_QUEUED
,
633 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
637 } else if (strcmp(cmd
, "jobdelete") == 0) {
641 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
642 " jobpause <printername> <unix-jobid>\n");
646 jobid
= atoi(argv
[3]);
648 notify_job_status_byname(
649 argv
[2], jobid
, JOB_STATUS_DELETING
,
650 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
652 notify_job_status_byname(
653 argv
[2], jobid
, JOB_STATUS_DELETING
|
655 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
659 } else if (strcmp(cmd
, "printer") == 0) {
663 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify "
664 "printer <printername> <comment|port|driver> "
669 if (strcmp(argv
[3], "comment") == 0) {
670 attribute
= PRINTER_NOTIFY_COMMENT
;
671 } else if (strcmp(argv
[3], "port") == 0) {
672 attribute
= PRINTER_NOTIFY_PORT_NAME
;
673 } else if (strcmp(argv
[3], "driver") == 0) {
674 attribute
= PRINTER_NOTIFY_DRIVER_NAME
;
676 fprintf(stderr
, "Invalid printer command '%s'\n",
681 notify_printer_byname(argv
[2], attribute
,
682 CONST_DISCARD(char *, argv
[4]));
687 fprintf(stderr
, "Invalid subcommand '%s'\n", cmd
);
691 print_notify_send_messages(msg_ctx
, 0);
697 static bool do_closeshare(struct messaging_context
*msg_ctx
,
698 const struct server_id pid
,
699 const int argc
, const char **argv
)
702 fprintf(stderr
, "Usage: smbcontrol <dest> close-share "
707 return send_message(msg_ctx
, pid
, MSG_SMB_FORCE_TDIS
, argv
[1],
708 strlen(argv
[1]) + 1);
711 /* force a blocking lock retry */
713 static bool do_lockretry(struct messaging_context
*msg_ctx
,
714 const struct server_id pid
,
715 const int argc
, const char **argv
)
718 fprintf(stderr
, "Usage: smbcontrol <dest> lockretry\n");
722 return send_message(msg_ctx
, pid
, MSG_SMB_UNLOCK
, NULL
, 0);
725 /* force a validation of all brl entries, including re-sends. */
727 static bool do_brl_revalidate(struct messaging_context
*msg_ctx
,
728 const struct server_id pid
,
729 const int argc
, const char **argv
)
732 fprintf(stderr
, "Usage: smbcontrol <dest> brl-revalidate\n");
736 return send_message(msg_ctx
, pid
, MSG_SMB_BRL_VALIDATE
, NULL
, 0);
739 /* Force a SAM synchronisation */
741 static bool do_samsync(struct messaging_context
*msg_ctx
,
742 const struct server_id pid
,
743 const int argc
, const char **argv
)
746 fprintf(stderr
, "Usage: smbcontrol <dest> samsync\n");
750 return send_message(msg_ctx
, pid
, MSG_SMB_SAM_SYNC
, NULL
, 0);
753 /* Force a SAM replication */
755 static bool do_samrepl(struct messaging_context
*msg_ctx
,
756 const struct server_id pid
,
757 const int argc
, const char **argv
)
760 fprintf(stderr
, "Usage: smbcontrol <dest> samrepl\n");
764 return send_message(msg_ctx
, pid
, MSG_SMB_SAM_REPL
, NULL
, 0);
767 /* Display talloc pool usage */
769 static bool do_poolusage(struct messaging_context
*msg_ctx
,
770 const struct server_id pid
,
771 const int argc
, const char **argv
)
774 fprintf(stderr
, "Usage: smbcontrol <dest> pool-usage\n");
778 messaging_register(msg_ctx
, NULL
, MSG_POOL_USAGE
, print_string_cb
);
780 /* Send a message and register our interest in a reply */
782 if (!send_message(msg_ctx
, pid
, MSG_REQ_POOL_USAGE
, NULL
, 0))
785 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
787 /* No replies were received within the timeout period */
789 if (num_replies
== 0)
790 printf("No replies received\n");
792 messaging_deregister(msg_ctx
, MSG_POOL_USAGE
, NULL
);
797 /* Perform a dmalloc mark */
799 static bool do_dmalloc_mark(struct messaging_context
*msg_ctx
,
800 const struct server_id pid
,
801 const int argc
, const char **argv
)
804 fprintf(stderr
, "Usage: smbcontrol <dest> dmalloc-mark\n");
808 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_MARK
, NULL
, 0);
811 /* Perform a dmalloc changed */
813 static bool do_dmalloc_changed(struct messaging_context
*msg_ctx
,
814 const struct server_id pid
,
815 const int argc
, const char **argv
)
818 fprintf(stderr
, "Usage: smbcontrol <dest> "
819 "dmalloc-log-changed\n");
823 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_LOG_CHANGED
,
827 /* Shutdown a server process */
829 static bool do_shutdown(struct messaging_context
*msg_ctx
,
830 const struct server_id pid
,
831 const int argc
, const char **argv
)
834 fprintf(stderr
, "Usage: smbcontrol <dest> shutdown\n");
838 return send_message(msg_ctx
, pid
, MSG_SHUTDOWN
, NULL
, 0);
841 /* Notify a driver upgrade */
843 static bool do_drvupgrade(struct messaging_context
*msg_ctx
,
844 const struct server_id pid
,
845 const int argc
, const char **argv
)
848 fprintf(stderr
, "Usage: smbcontrol <dest> drvupgrade "
853 return send_message(msg_ctx
, pid
, MSG_DEBUG
, argv
[1],
854 strlen(argv
[1]) + 1);
857 static bool do_winbind_online(struct messaging_context
*msg_ctx
,
858 const struct server_id pid
,
859 const int argc
, const char **argv
)
864 fprintf(stderr
, "Usage: smbcontrol winbindd online\n");
868 if (!lp_winbind_offline_logon()) {
869 fprintf(stderr
, "The parameter \"winbind offline logon\" must "
870 "be set in the [global] section of smb.conf for this "
871 "command to be allowed.\n");
875 /* Remove the entry in the winbindd_cache tdb to tell a later
876 starting winbindd that we're online. */
878 tdb
= tdb_open_log(lock_path("winbindd_cache.tdb"), 0, TDB_DEFAULT
, O_RDWR
, 0600);
880 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
881 lock_path("winbindd_cache.tdb"));
885 tdb_delete_bystring(tdb
, "WINBINDD_OFFLINE");
888 return send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINE
, NULL
, 0);
891 static bool do_winbind_offline(struct messaging_context
*msg_ctx
,
892 const struct server_id pid
,
893 const int argc
, const char **argv
)
900 fprintf(stderr
, "Usage: smbcontrol winbindd offline\n");
904 if (!lp_winbind_offline_logon()) {
905 fprintf(stderr
, "The parameter \"winbind offline logon\" must "
906 "be set in the [global] section of smb.conf for this "
907 "command to be allowed.\n");
911 /* Create an entry in the winbindd_cache tdb to tell a later
912 starting winbindd that we're offline. We may actually create
915 tdb
= tdb_open_log(lock_path("winbindd_cache.tdb"),
916 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE
,
917 TDB_DEFAULT
/* TDB_CLEAR_IF_FIRST */, O_RDWR
|O_CREAT
, 0600);
920 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
921 lock_path("winbindd_cache.tdb"));
925 /* There's a potential race condition that if a child
926 winbindd detects a domain is online at the same time
927 we're trying to tell it to go offline that it might
928 delete the record we add between us adding it and
929 sending the message. Minimize this by retrying up to
932 for (retry
= 0; retry
< 5; retry
++) {
938 SIVAL(buf
, 0, time(NULL
));
942 tdb_store_bystring(tdb
, "WINBINDD_OFFLINE", d
, TDB_INSERT
);
944 ret
= send_message(msg_ctx
, pid
, MSG_WINBIND_OFFLINE
,
947 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
948 d
= tdb_fetch_bystring( tdb
, "WINBINDD_OFFLINE" );
950 if (!d
.dptr
|| d
.dsize
!= 4) {
952 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
963 static bool do_winbind_onlinestatus(struct messaging_context
*msg_ctx
,
964 const struct server_id pid
,
965 const int argc
, const char **argv
)
967 struct server_id myid
;
969 myid
= pid_to_procid(sys_getpid());
972 fprintf(stderr
, "Usage: smbcontrol winbindd onlinestatus\n");
976 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_ONLINESTATUS
,
977 print_pid_string_cb
);
979 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINESTATUS
, &myid
,
983 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
985 /* No replies were received within the timeout period */
987 if (num_replies
== 0)
988 printf("No replies received\n");
990 messaging_deregister(msg_ctx
, MSG_WINBIND_ONLINESTATUS
, NULL
);
995 static bool do_dump_event_list(struct messaging_context
*msg_ctx
,
996 const struct server_id pid
,
997 const int argc
, const char **argv
)
999 struct server_id myid
;
1001 myid
= pid_to_procid(sys_getpid());
1004 fprintf(stderr
, "Usage: smbcontrol <dest> dump-event-list\n");
1008 return send_message(msg_ctx
, pid
, MSG_DUMP_EVENT_LIST
, NULL
, 0);
1011 static bool do_winbind_dump_domain_list(struct messaging_context
*msg_ctx
,
1012 const struct server_id pid
,
1013 const int argc
, const char **argv
)
1015 const char *domain
= NULL
;
1017 struct server_id myid
;
1018 uint8_t *buf
= NULL
;
1021 myid
= pid_to_procid(sys_getpid());
1023 if (argc
< 1 || argc
> 2) {
1024 fprintf(stderr
, "Usage: smbcontrol <dest> dump_domain_list "
1031 domain_len
= strlen(argv
[1]) + 1;
1034 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1035 print_pid_string_cb
);
1037 buf_len
= sizeof(myid
)+domain_len
;
1038 buf
= SMB_MALLOC_ARRAY(uint8_t, buf_len
);
1043 memcpy(buf
, &myid
, sizeof(myid
));
1044 memcpy(&buf
[sizeof(myid
)], domain
, domain_len
);
1046 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1053 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
1055 /* No replies were received within the timeout period */
1058 if (num_replies
== 0) {
1059 printf("No replies received\n");
1062 messaging_deregister(msg_ctx
, MSG_WINBIND_DUMP_DOMAIN_LIST
, NULL
);
1067 static void winbind_validate_cache_cb(struct messaging_context
*msg
,
1070 struct server_id pid
,
1073 char *src_string
= procid_str(NULL
, &pid
);
1074 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1075 (*(data
->data
) == 0 ? "" : "NOT "), src_string
);
1076 TALLOC_FREE(src_string
);
1080 static bool do_winbind_validate_cache(struct messaging_context
*msg_ctx
,
1081 const struct server_id pid
,
1082 const int argc
, const char **argv
)
1084 struct server_id myid
= pid_to_procid(sys_getpid());
1087 fprintf(stderr
, "Usage: smbcontrol winbindd validate-cache\n");
1091 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_VALIDATE_CACHE
,
1092 winbind_validate_cache_cb
);
1094 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_VALIDATE_CACHE
, &myid
,
1099 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
1101 if (num_replies
== 0) {
1102 printf("No replies received\n");
1105 messaging_deregister(msg_ctx
, MSG_WINBIND_VALIDATE_CACHE
, NULL
);
1110 static bool do_reload_config(struct messaging_context
*msg_ctx
,
1111 const struct server_id pid
,
1112 const int argc
, const char **argv
)
1115 fprintf(stderr
, "Usage: smbcontrol <dest> reload-config\n");
1119 return send_message(msg_ctx
, pid
, MSG_SMB_CONF_UPDATED
, NULL
, 0);
1122 static void my_make_nmb_name( struct nmb_name
*n
, const char *name
, int type
)
1125 memset( (char *)n
, '\0', sizeof(struct nmb_name
) );
1126 fstrcpy(unix_name
, name
);
1127 strupper_m(unix_name
);
1128 push_ascii(n
->name
, unix_name
, sizeof(n
->name
), STR_TERMINATE
);
1129 n
->name_type
= (unsigned int)type
& 0xFF;
1130 push_ascii(n
->scope
, global_scope(), 64, STR_TERMINATE
);
1133 static bool do_nodestatus(struct messaging_context
*msg_ctx
,
1134 const struct server_id pid
,
1135 const int argc
, const char **argv
)
1137 struct packet_struct p
;
1140 fprintf(stderr
, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1146 (void)interpret_addr2(&p
.ip
, argv
[1]);
1148 p
.packet_type
= NMB_PACKET
;
1150 p
.packet
.nmb
.header
.name_trn_id
= 10;
1151 p
.packet
.nmb
.header
.opcode
= 0;
1152 p
.packet
.nmb
.header
.response
= False
;
1153 p
.packet
.nmb
.header
.nm_flags
.bcast
= False
;
1154 p
.packet
.nmb
.header
.nm_flags
.recursion_available
= False
;
1155 p
.packet
.nmb
.header
.nm_flags
.recursion_desired
= False
;
1156 p
.packet
.nmb
.header
.nm_flags
.trunc
= False
;
1157 p
.packet
.nmb
.header
.nm_flags
.authoritative
= False
;
1158 p
.packet
.nmb
.header
.rcode
= 0;
1159 p
.packet
.nmb
.header
.qdcount
= 1;
1160 p
.packet
.nmb
.header
.ancount
= 0;
1161 p
.packet
.nmb
.header
.nscount
= 0;
1162 p
.packet
.nmb
.header
.arcount
= 0;
1163 my_make_nmb_name(&p
.packet
.nmb
.question
.question_name
, "*", 0x00);
1164 p
.packet
.nmb
.question
.question_type
= 0x21;
1165 p
.packet
.nmb
.question
.question_class
= 0x1;
1167 return send_message(msg_ctx
, pid
, MSG_SEND_PACKET
, &p
, sizeof(p
));
1170 /* A list of message type supported */
1172 static const struct {
1173 const char *name
; /* Option name */
1174 bool (*fn
)(struct messaging_context
*msg_ctx
,
1175 const struct server_id pid
,
1176 const int argc
, const char **argv
);
1177 const char *help
; /* Short help text */
1179 { "debug", do_debug
, "Set debuglevel" },
1180 { "force-election", do_election
,
1181 "Force a browse election" },
1182 { "ping", do_ping
, "Elicit a response" },
1183 { "profile", do_profile
, "" },
1184 { "inject", do_inject_fault
,
1185 "Inject a fatal signal into a running smbd"},
1186 { "stacktrace", do_daemon_stack_trace
,
1187 "Display a stack trace of a daemon" },
1188 { "profilelevel", do_profilelevel
, "" },
1189 { "debuglevel", do_debuglevel
, "Display current debuglevels" },
1190 { "printnotify", do_printnotify
, "Send a print notify message" },
1191 { "close-share", do_closeshare
, "Forcibly disconnect a share" },
1192 { "lockretry", do_lockretry
, "Force a blocking lock retry" },
1193 { "brl-revalidate", do_brl_revalidate
, "Revalidate all brl entries" },
1194 { "samsync", do_samsync
, "Initiate SAM synchronisation" },
1195 { "samrepl", do_samrepl
, "Initiate SAM replication" },
1196 { "pool-usage", do_poolusage
, "Display talloc memory usage" },
1197 { "dmalloc-mark", do_dmalloc_mark
, "" },
1198 { "dmalloc-log-changed", do_dmalloc_changed
, "" },
1199 { "shutdown", do_shutdown
, "Shut down daemon" },
1200 { "drvupgrade", do_drvupgrade
, "Notify a printer driver has changed" },
1201 { "reload-config", do_reload_config
, "Force smbd or winbindd to reload config file"},
1202 { "nodestatus", do_nodestatus
, "Ask nmbd to do a node status request"},
1203 { "online", do_winbind_online
, "Ask winbind to go into online state"},
1204 { "offline", do_winbind_offline
, "Ask winbind to go into offline state"},
1205 { "onlinestatus", do_winbind_onlinestatus
, "Request winbind online status"},
1206 { "dump-event-list", do_dump_event_list
, "Dump event list"},
1207 { "validate-cache" , do_winbind_validate_cache
,
1208 "Validate winbind's credential cache" },
1209 { "dump-domain-list", do_winbind_dump_domain_list
, "Dump winbind domain list"},
1210 { "noop", do_noop
, "Do nothing" },
1214 /* Display usage information */
1216 static void usage(poptContext pc
)
1220 poptPrintHelp(pc
, stderr
, 0);
1222 fprintf(stderr
, "\n");
1223 fprintf(stderr
, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1226 fprintf(stderr
, "\n");
1227 fprintf(stderr
, "<message-type> is one of:\n");
1229 for (i
= 0; msg_types
[i
].name
; i
++)
1230 fprintf(stderr
, "\t%-30s%s\n", msg_types
[i
].name
,
1233 fprintf(stderr
, "\n");
1238 /* Return the pid number for a string destination */
1240 static struct server_id
parse_dest(const char *dest
)
1242 struct server_id result
= {-1};
1245 /* Zero is a special return value for broadcast smbd */
1247 if (strequal(dest
, "smbd")) {
1248 return interpret_pid(MSG_BROADCAST_PID_STR
);
1251 /* Try self - useful for testing */
1253 if (strequal(dest
, "self")) {
1254 return pid_to_procid(sys_getpid());
1257 /* Fix winbind typo. */
1258 if (strequal(dest
, "winbind")) {
1263 if (!(strequal(dest
, "winbindd") || strequal(dest
, "nmbd"))) {
1264 /* Check for numeric pid number */
1266 result
= interpret_pid(dest
);
1268 /* Zero isn't valid if not smbd. */
1269 if (result
.pid
&& procid_valid(&result
)) {
1274 /* Look up other destinations in pidfile directory */
1276 if ((pid
= pidfile_pid(dest
)) != 0) {
1277 return pid_to_procid(pid
);
1280 fprintf(stderr
,"Can't find pid for destination '%s'\n", dest
);
1285 /* Execute smbcontrol command */
1287 static bool do_command(struct messaging_context
*msg_ctx
,
1288 int argc
, const char **argv
)
1290 const char *dest
= argv
[0], *command
= argv
[1];
1291 struct server_id pid
;
1294 /* Check destination */
1296 pid
= parse_dest(dest
);
1297 if (!procid_valid(&pid
)) {
1303 for (i
= 0; msg_types
[i
].name
; i
++) {
1304 if (strequal(command
, msg_types
[i
].name
))
1305 return msg_types
[i
].fn(msg_ctx
, pid
,
1306 argc
- 1, argv
+ 1);
1309 fprintf(stderr
, "smbcontrol: unknown command '%s'\n", command
);
1314 static void smbcontrol_help(poptContext pc
,
1315 enum poptCallbackReason preason
,
1316 struct poptOption
* poption
,
1320 if (poption
->shortName
!= '?') {
1321 poptPrintUsage(pc
, stdout
, 0);
1329 struct poptOption help_options
[] = {
1330 { NULL
, '\0', POPT_ARG_CALLBACK
, (void *)&smbcontrol_help
, '\0',
1332 { "help", '?', 0, NULL
, '?', "Show this help message", NULL
},
1333 { "usage", '\0', 0, NULL
, 'u', "Display brief usage message", NULL
},
1339 int main(int argc
, const char **argv
)
1343 struct event_context
*evt_ctx
;
1344 struct messaging_context
*msg_ctx
;
1346 static struct poptOption long_options
[] = {
1348 { NULL
, '\0', POPT_ARG_INCLUDE_TABLE
, help_options
,
1349 0, "Help options:", NULL
},
1350 { "timeout", 't', POPT_ARG_INT
, &timeout
, 't',
1351 "Set timeout value in seconds", "TIMEOUT" },
1356 TALLOC_CTX
*frame
= talloc_stackframe();
1361 setup_logging(argv
[0],True
);
1363 /* Parse command line arguments using popt */
1365 pc
= poptGetContext(
1366 "smbcontrol", argc
, (const char **)argv
, long_options
, 0);
1368 poptSetOtherOptionHelp(pc
, "[OPTION...] <destination> <message-type> "
1374 while ((opt
= poptGetNextOpt(pc
)) != -1) {
1376 case 't': /* --timeout */
1379 fprintf(stderr
, "Invalid option\n");
1380 poptPrintHelp(pc
, stderr
, 0);
1385 /* We should now have the remaining command line arguments in
1386 argv. The argc parameter should have been decremented to the
1387 correct value in the above switch statement. */
1389 argv
= (const char **)poptGetArgs(pc
);
1392 while (argv
[argc
] != NULL
) {
1400 lp_load(get_dyn_CONFIGFILE(),False
,False
,False
,True
);
1402 /* Need to invert sense of return code -- samba
1403 * routines mostly return True==1 for success, but
1406 if (!(evt_ctx
= event_context_init(NULL
)) ||
1407 !(msg_ctx
= messaging_init(NULL
, server_id_self(), evt_ctx
))) {
1408 fprintf(stderr
, "could not init messaging context\n");
1413 ret
= !do_command(msg_ctx
, argc
, argv
);