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 smbcontrol_timeout(struct event_context
*event_ctx
,
69 struct timed_event
*te
,
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),
88 smbcontrol_timeout
, (void *)&timed_out
))) {
89 DEBUG(0, ("event_add_timed failed\n"));
94 message_dispatch(msg_ctx
);
95 if (num_replies
> 0 && !multiple_replies
)
97 event_loop_once(messaging_event_context(msg_ctx
));
101 /* Message handler callback that displays the PID and a string on stdout */
103 static void print_pid_string_cb(struct messaging_context
*msg
,
106 struct server_id pid
,
109 printf("PID %u: %.*s", (unsigned int)procid_to_pid(&pid
),
110 (int)data
->length
, (const char *)data
->data
);
114 /* Message handler callback that displays a string on stdout */
116 static void print_string_cb(struct messaging_context
*msg
,
119 struct server_id pid
,
122 printf("%.*s", (int)data
->length
, (const char *)data
->data
);
126 /* Send no message. Useful for testing. */
128 static bool do_noop(struct messaging_context
*msg_ctx
,
129 const struct server_id pid
,
130 const int argc
, const char **argv
)
133 fprintf(stderr
, "Usage: smbcontrol <dest> noop\n");
137 /* Move along, nothing to see here */
142 /* Send a debug string */
144 static bool do_debug(struct messaging_context
*msg_ctx
,
145 const struct server_id pid
,
146 const int argc
, const char **argv
)
149 fprintf(stderr
, "Usage: smbcontrol <dest> debug "
154 return send_message(msg_ctx
, pid
, MSG_DEBUG
, argv
[1],
155 strlen(argv
[1]) + 1);
158 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
160 /* Return the name of a process given it's PID. This will only work on Linux,
161 * but that's probably moot since this whole stack tracing implementatino is
162 * Linux-specific anyway.
164 static const char * procname(pid_t pid
, char * buf
, size_t bufsz
)
169 snprintf(path
, sizeof(path
), "/proc/%llu/cmdline",
170 (unsigned long long)pid
);
171 if ((fp
= fopen(path
, "r")) == NULL
) {
175 fgets(buf
, bufsz
, fp
);
181 static void print_stack_trace(pid_t pid
, int * count
)
184 unw_addr_space_t aspace
= NULL
;
193 if (ptrace(PTRACE_ATTACH
, pid
, NULL
, NULL
) < 0) {
195 "Failed to attach to process %llu: %s\n",
196 (unsigned long long)pid
, strerror(errno
));
200 /* Wait until the attach is complete. */
201 waitpid(pid
, NULL
, 0);
203 if (((pinfo
= _UPT_create(pid
)) == NULL
) ||
204 ((aspace
= unw_create_addr_space(&_UPT_accessors
, 0)) == NULL
)) {
205 /* Probably out of memory. */
207 "Unable to initialize stack unwind for process %llu\n",
208 (unsigned long long)pid
);
212 if ((ret
= unw_init_remote(&cursor
, aspace
, pinfo
))) {
214 "Unable to unwind stack for process %llu: %s\n",
215 (unsigned long long)pid
, unw_strerror(ret
));
223 if (procname(pid
, nbuf
, sizeof(nbuf
))) {
224 printf("Stack trace for process %llu (%s):\n",
225 (unsigned long long)pid
, nbuf
);
227 printf("Stack trace for process %llu:\n",
228 (unsigned long long)pid
);
231 while (unw_step(&cursor
) > 0) {
233 unw_get_reg(&cursor
, UNW_REG_IP
, &ip
);
234 unw_get_reg(&cursor
, UNW_REG_SP
, &sp
);
236 ret
= unw_get_proc_name(&cursor
, nbuf
, sizeof(nbuf
), &off
);
237 if (ret
!= 0 && ret
!= -UNW_ENOMEM
) {
238 snprintf(nbuf
, sizeof(nbuf
), "<unknown symbol>");
240 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
241 nbuf
, (long long)off
, (long long)ip
,
249 unw_destroy_addr_space(aspace
);
256 ptrace(PTRACE_DETACH
, pid
, NULL
, NULL
);
259 static int stack_trace_connection(struct db_record
*rec
,
260 const struct connections_key
*key
,
261 const struct connections_data
*crec
,
264 print_stack_trace(procid_to_pid(&crec
->pid
), (int *)priv
);
269 static bool do_daemon_stack_trace(struct messaging_context
*msg_ctx
,
270 const struct server_id pid
,
271 const int argc
, const char **argv
)
277 fprintf(stderr
, "Usage: smbcontrol <dest> stacktrace\n");
281 dest
= procid_to_pid(&pid
);
284 /* It would be nice to be able to make sure that this PID is
285 * the PID of a smbd/winbind/nmbd process, not some random PID
286 * the user liked the look of. It doesn't seem like it's worth
287 * the effort at the moment, however.
289 print_stack_trace(dest
, &count
);
291 connections_forall(stack_trace_connection
, &count
);
297 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
299 static bool do_daemon_stack_trace(struct messaging_context
*msg_ctx
,
300 const struct server_id pid
,
301 const int argc
, const char **argv
)
304 "Daemon stack tracing is not supported on this platform\n");
308 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
310 /* Inject a fault (fatal signal) into a running smbd */
312 static bool do_inject_fault(struct messaging_context
*msg_ctx
,
313 const struct server_id pid
,
314 const int argc
, const char **argv
)
317 fprintf(stderr
, "Usage: smbcontrol <dest> inject "
318 "<bus|hup|term|internal|segv>\n");
323 fprintf(stderr
, "Fault injection is only available in "
324 "developer builds\n");
326 #else /* DEVELOPER */
330 if (strcmp(argv
[1], "bus") == 0) {
332 } else if (strcmp(argv
[1], "hup") == 0) {
334 } else if (strcmp(argv
[1], "term") == 0) {
336 } else if (strcmp(argv
[1], "segv") == 0) {
338 } else if (strcmp(argv
[1], "internal") == 0) {
339 /* Force an internal error, ie. an unclean exit. */
342 fprintf(stderr
, "Unknown signal name '%s'\n", argv
[1]);
346 return send_message(msg_ctx
, pid
, MSG_SMB_INJECT_FAULT
,
349 #endif /* DEVELOPER */
352 /* Force a browser election */
354 static bool do_election(struct messaging_context
*msg_ctx
,
355 const struct server_id pid
,
356 const int argc
, const char **argv
)
359 fprintf(stderr
, "Usage: smbcontrol <dest> force-election\n");
363 return send_message(msg_ctx
, pid
, MSG_FORCE_ELECTION
, NULL
, 0);
366 /* Ping a samba daemon process */
368 static void pong_cb(struct messaging_context
*msg
,
371 struct server_id pid
,
374 char *src_string
= procid_str(NULL
, &pid
);
375 printf("PONG from pid %s\n", src_string
);
376 TALLOC_FREE(src_string
);
380 static bool do_ping(struct messaging_context
*msg_ctx
,
381 const struct server_id pid
,
382 const int argc
, const char **argv
)
385 fprintf(stderr
, "Usage: smbcontrol <dest> ping\n");
389 /* Send a message and register our interest in a reply */
391 if (!send_message(msg_ctx
, pid
, MSG_PING
, NULL
, 0))
394 messaging_register(msg_ctx
, NULL
, MSG_PONG
, pong_cb
);
396 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
398 /* No replies were received within the timeout period */
400 if (num_replies
== 0)
401 printf("No replies received\n");
403 messaging_deregister(msg_ctx
, MSG_PONG
, NULL
);
408 /* Set profiling options */
410 static bool do_profile(struct messaging_context
*msg_ctx
,
411 const struct server_id pid
,
412 const int argc
, const char **argv
)
417 fprintf(stderr
, "Usage: smbcontrol <dest> profile "
418 "<off|count|on|flush>\n");
422 if (strcmp(argv
[1], "off") == 0) {
424 } else if (strcmp(argv
[1], "count") == 0) {
426 } else if (strcmp(argv
[1], "on") == 0) {
428 } else if (strcmp(argv
[1], "flush") == 0) {
431 fprintf(stderr
, "Unknown profile command '%s'\n", argv
[1]);
435 return send_message(msg_ctx
, pid
, MSG_PROFILE
, &v
, sizeof(int));
438 /* Return the profiling level */
440 static void profilelevel_cb(struct messaging_context
*msg_ctx
,
443 struct server_id pid
,
451 if (data
->length
!= sizeof(int)) {
452 fprintf(stderr
, "invalid message length %ld returned\n",
453 (unsigned long)data
->length
);
457 memcpy(&level
, data
->data
, sizeof(int));
470 s
= "count and time";
477 printf("Profiling %s on pid %u\n",s
,(unsigned int)procid_to_pid(&pid
));
480 static void profilelevel_rqst(struct messaging_context
*msg_ctx
,
483 struct server_id pid
,
488 /* Send back a dummy reply */
490 send_message(msg_ctx
, pid
, MSG_PROFILELEVEL
, &v
, sizeof(int));
493 static bool do_profilelevel(struct messaging_context
*msg_ctx
,
494 const struct server_id pid
,
495 const int argc
, const char **argv
)
498 fprintf(stderr
, "Usage: smbcontrol <dest> profilelevel\n");
502 /* Send a message and register our interest in a reply */
504 if (!send_message(msg_ctx
, pid
, MSG_REQ_PROFILELEVEL
, NULL
, 0))
507 messaging_register(msg_ctx
, NULL
, MSG_PROFILELEVEL
, profilelevel_cb
);
508 messaging_register(msg_ctx
, NULL
, MSG_REQ_PROFILELEVEL
,
511 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
513 /* No replies were received within the timeout period */
515 if (num_replies
== 0)
516 printf("No replies received\n");
518 messaging_deregister(msg_ctx
, MSG_PROFILE
, NULL
);
523 /* Display debug level settings */
525 static bool do_debuglevel(struct messaging_context
*msg_ctx
,
526 const struct server_id pid
,
527 const int argc
, const char **argv
)
530 fprintf(stderr
, "Usage: smbcontrol <dest> debuglevel\n");
534 /* Send a message and register our interest in a reply */
536 if (!send_message(msg_ctx
, pid
, MSG_REQ_DEBUGLEVEL
, NULL
, 0))
539 messaging_register(msg_ctx
, NULL
, MSG_DEBUGLEVEL
, print_pid_string_cb
);
541 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
543 /* No replies were received within the timeout period */
545 if (num_replies
== 0)
546 printf("No replies received\n");
548 messaging_deregister(msg_ctx
, MSG_DEBUGLEVEL
, NULL
);
553 /* Send a print notify message */
555 static bool do_printnotify(struct messaging_context
*msg_ctx
,
556 const struct server_id pid
,
557 const int argc
, const char **argv
)
561 /* Check for subcommand */
564 fprintf(stderr
, "Must specify subcommand:\n");
565 fprintf(stderr
, "\tqueuepause <printername>\n");
566 fprintf(stderr
, "\tqueueresume <printername>\n");
567 fprintf(stderr
, "\tjobpause <printername> <unix jobid>\n");
568 fprintf(stderr
, "\tjobresume <printername> <unix jobid>\n");
569 fprintf(stderr
, "\tjobdelete <printername> <unix jobid>\n");
570 fprintf(stderr
, "\tprinter <printername> <comment|port|"
571 "driver> <value>\n");
578 if (strcmp(cmd
, "queuepause") == 0) {
581 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
582 " queuepause <printername>\n");
586 notify_printer_status_byname(argv
[2], PRINTER_STATUS_PAUSED
);
590 } else if (strcmp(cmd
, "queueresume") == 0) {
593 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
594 " queuereume <printername>\n");
598 notify_printer_status_byname(argv
[2], PRINTER_STATUS_OK
);
602 } else if (strcmp(cmd
, "jobpause") == 0) {
606 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
607 " jobpause <printername> <unix-jobid>\n");
611 jobid
= atoi(argv
[3]);
613 notify_job_status_byname(
614 argv
[2], jobid
, JOB_STATUS_PAUSED
,
615 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
619 } else if (strcmp(cmd
, "jobresume") == 0) {
623 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
624 " jobpause <printername> <unix-jobid>\n");
628 jobid
= atoi(argv
[3]);
630 notify_job_status_byname(
631 argv
[2], jobid
, JOB_STATUS_QUEUED
,
632 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
636 } else if (strcmp(cmd
, "jobdelete") == 0) {
640 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
641 " jobpause <printername> <unix-jobid>\n");
645 jobid
= atoi(argv
[3]);
647 notify_job_status_byname(
648 argv
[2], jobid
, JOB_STATUS_DELETING
,
649 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
651 notify_job_status_byname(
652 argv
[2], jobid
, JOB_STATUS_DELETING
|
654 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
658 } else if (strcmp(cmd
, "printer") == 0) {
662 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify "
663 "printer <printername> <comment|port|driver> "
668 if (strcmp(argv
[3], "comment") == 0) {
669 attribute
= PRINTER_NOTIFY_COMMENT
;
670 } else if (strcmp(argv
[3], "port") == 0) {
671 attribute
= PRINTER_NOTIFY_PORT_NAME
;
672 } else if (strcmp(argv
[3], "driver") == 0) {
673 attribute
= PRINTER_NOTIFY_DRIVER_NAME
;
675 fprintf(stderr
, "Invalid printer command '%s'\n",
680 notify_printer_byname(argv
[2], attribute
,
681 CONST_DISCARD(char *, argv
[4]));
686 fprintf(stderr
, "Invalid subcommand '%s'\n", cmd
);
690 print_notify_send_messages(msg_ctx
, 0);
696 static bool do_closeshare(struct messaging_context
*msg_ctx
,
697 const struct server_id pid
,
698 const int argc
, const char **argv
)
701 fprintf(stderr
, "Usage: smbcontrol <dest> close-share "
706 return send_message(msg_ctx
, pid
, MSG_SMB_FORCE_TDIS
, argv
[1],
707 strlen(argv
[1]) + 1);
710 /* force a blocking lock retry */
712 static bool do_lockretry(struct messaging_context
*msg_ctx
,
713 const struct server_id pid
,
714 const int argc
, const char **argv
)
717 fprintf(stderr
, "Usage: smbcontrol <dest> lockretry\n");
721 return send_message(msg_ctx
, pid
, MSG_SMB_UNLOCK
, NULL
, 0);
724 /* force a validation of all brl entries, including re-sends. */
726 static bool do_brl_revalidate(struct messaging_context
*msg_ctx
,
727 const struct server_id pid
,
728 const int argc
, const char **argv
)
731 fprintf(stderr
, "Usage: smbcontrol <dest> brl-revalidate\n");
735 return send_message(msg_ctx
, pid
, MSG_SMB_BRL_VALIDATE
, NULL
, 0);
738 /* Force a SAM synchronisation */
740 static bool do_samsync(struct messaging_context
*msg_ctx
,
741 const struct server_id pid
,
742 const int argc
, const char **argv
)
745 fprintf(stderr
, "Usage: smbcontrol <dest> samsync\n");
749 return send_message(msg_ctx
, pid
, MSG_SMB_SAM_SYNC
, NULL
, 0);
752 /* Force a SAM replication */
754 static bool do_samrepl(struct messaging_context
*msg_ctx
,
755 const struct server_id pid
,
756 const int argc
, const char **argv
)
759 fprintf(stderr
, "Usage: smbcontrol <dest> samrepl\n");
763 return send_message(msg_ctx
, pid
, MSG_SMB_SAM_REPL
, NULL
, 0);
766 /* Display talloc pool usage */
768 static bool do_poolusage(struct messaging_context
*msg_ctx
,
769 const struct server_id pid
,
770 const int argc
, const char **argv
)
773 fprintf(stderr
, "Usage: smbcontrol <dest> pool-usage\n");
777 messaging_register(msg_ctx
, NULL
, MSG_POOL_USAGE
, print_string_cb
);
779 /* Send a message and register our interest in a reply */
781 if (!send_message(msg_ctx
, pid
, MSG_REQ_POOL_USAGE
, NULL
, 0))
784 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
786 /* No replies were received within the timeout period */
788 if (num_replies
== 0)
789 printf("No replies received\n");
791 messaging_deregister(msg_ctx
, MSG_POOL_USAGE
, NULL
);
796 /* Perform a dmalloc mark */
798 static bool do_dmalloc_mark(struct messaging_context
*msg_ctx
,
799 const struct server_id pid
,
800 const int argc
, const char **argv
)
803 fprintf(stderr
, "Usage: smbcontrol <dest> dmalloc-mark\n");
807 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_MARK
, NULL
, 0);
810 /* Perform a dmalloc changed */
812 static bool do_dmalloc_changed(struct messaging_context
*msg_ctx
,
813 const struct server_id pid
,
814 const int argc
, const char **argv
)
817 fprintf(stderr
, "Usage: smbcontrol <dest> "
818 "dmalloc-log-changed\n");
822 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_LOG_CHANGED
,
826 /* Shutdown a server process */
828 static bool do_shutdown(struct messaging_context
*msg_ctx
,
829 const struct server_id pid
,
830 const int argc
, const char **argv
)
833 fprintf(stderr
, "Usage: smbcontrol <dest> shutdown\n");
837 return send_message(msg_ctx
, pid
, MSG_SHUTDOWN
, NULL
, 0);
840 /* Notify a driver upgrade */
842 static bool do_drvupgrade(struct messaging_context
*msg_ctx
,
843 const struct server_id pid
,
844 const int argc
, const char **argv
)
847 fprintf(stderr
, "Usage: smbcontrol <dest> drvupgrade "
852 return send_message(msg_ctx
, pid
, MSG_DEBUG
, argv
[1],
853 strlen(argv
[1]) + 1);
856 static bool do_winbind_online(struct messaging_context
*msg_ctx
,
857 const struct server_id pid
,
858 const int argc
, const char **argv
)
863 fprintf(stderr
, "Usage: smbcontrol winbindd online\n");
867 /* Remove the entry in the winbindd_cache tdb to tell a later
868 starting winbindd that we're online. */
870 tdb
= tdb_open_log(cache_path("winbindd_cache.tdb"), 0, TDB_DEFAULT
, O_RDWR
, 0600);
872 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
873 cache_path("winbindd_cache.tdb"));
877 tdb_delete_bystring(tdb
, "WINBINDD_OFFLINE");
880 return send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINE
, NULL
, 0);
883 static bool do_winbind_offline(struct messaging_context
*msg_ctx
,
884 const struct server_id pid
,
885 const int argc
, const char **argv
)
892 fprintf(stderr
, "Usage: smbcontrol winbindd offline\n");
896 /* Create an entry in the winbindd_cache tdb to tell a later
897 starting winbindd that we're offline. We may actually create
900 tdb
= tdb_open_log(cache_path("winbindd_cache.tdb"),
901 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE
,
902 TDB_DEFAULT
/* TDB_CLEAR_IF_FIRST */, O_RDWR
|O_CREAT
, 0600);
905 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
906 cache_path("winbindd_cache.tdb"));
910 /* There's a potential race condition that if a child
911 winbindd detects a domain is online at the same time
912 we're trying to tell it to go offline that it might
913 delete the record we add between us adding it and
914 sending the message. Minimize this by retrying up to
917 for (retry
= 0; retry
< 5; retry
++) {
923 SIVAL(buf
, 0, time(NULL
));
927 tdb_store_bystring(tdb
, "WINBINDD_OFFLINE", d
, TDB_INSERT
);
929 ret
= send_message(msg_ctx
, pid
, MSG_WINBIND_OFFLINE
,
932 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
933 d
= tdb_fetch_bystring( tdb
, "WINBINDD_OFFLINE" );
935 if (!d
.dptr
|| d
.dsize
!= 4) {
937 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
948 static bool do_winbind_onlinestatus(struct messaging_context
*msg_ctx
,
949 const struct server_id pid
,
950 const int argc
, const char **argv
)
952 struct server_id myid
;
954 myid
= pid_to_procid(sys_getpid());
957 fprintf(stderr
, "Usage: smbcontrol winbindd onlinestatus\n");
961 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_ONLINESTATUS
,
962 print_pid_string_cb
);
964 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINESTATUS
, &myid
,
968 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
970 /* No replies were received within the timeout period */
972 if (num_replies
== 0)
973 printf("No replies received\n");
975 messaging_deregister(msg_ctx
, MSG_WINBIND_ONLINESTATUS
, NULL
);
980 static bool do_dump_event_list(struct messaging_context
*msg_ctx
,
981 const struct server_id pid
,
982 const int argc
, const char **argv
)
984 struct server_id myid
;
986 myid
= pid_to_procid(sys_getpid());
989 fprintf(stderr
, "Usage: smbcontrol <dest> dump-event-list\n");
993 return send_message(msg_ctx
, pid
, MSG_DUMP_EVENT_LIST
, NULL
, 0);
996 static bool do_winbind_dump_domain_list(struct messaging_context
*msg_ctx
,
997 const struct server_id pid
,
998 const int argc
, const char **argv
)
1000 const char *domain
= NULL
;
1002 struct server_id myid
;
1003 uint8_t *buf
= NULL
;
1006 myid
= pid_to_procid(sys_getpid());
1008 if (argc
< 1 || argc
> 2) {
1009 fprintf(stderr
, "Usage: smbcontrol <dest> dump_domain_list "
1016 domain_len
= strlen(argv
[1]) + 1;
1019 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1020 print_pid_string_cb
);
1022 buf_len
= sizeof(myid
)+domain_len
;
1023 buf
= SMB_MALLOC_ARRAY(uint8_t, buf_len
);
1028 memcpy(buf
, &myid
, sizeof(myid
));
1029 memcpy(&buf
[sizeof(myid
)], domain
, domain_len
);
1031 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1038 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
1040 /* No replies were received within the timeout period */
1043 if (num_replies
== 0) {
1044 printf("No replies received\n");
1047 messaging_deregister(msg_ctx
, MSG_WINBIND_DUMP_DOMAIN_LIST
, NULL
);
1052 static void winbind_validate_cache_cb(struct messaging_context
*msg
,
1055 struct server_id pid
,
1058 char *src_string
= procid_str(NULL
, &pid
);
1059 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1060 (*(data
->data
) == 0 ? "" : "NOT "), src_string
);
1061 TALLOC_FREE(src_string
);
1065 static bool do_winbind_validate_cache(struct messaging_context
*msg_ctx
,
1066 const struct server_id pid
,
1067 const int argc
, const char **argv
)
1069 struct server_id myid
= pid_to_procid(sys_getpid());
1072 fprintf(stderr
, "Usage: smbcontrol winbindd validate-cache\n");
1076 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_VALIDATE_CACHE
,
1077 winbind_validate_cache_cb
);
1079 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_VALIDATE_CACHE
, &myid
,
1084 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
1086 if (num_replies
== 0) {
1087 printf("No replies received\n");
1090 messaging_deregister(msg_ctx
, MSG_WINBIND_VALIDATE_CACHE
, NULL
);
1095 static bool do_reload_config(struct messaging_context
*msg_ctx
,
1096 const struct server_id pid
,
1097 const int argc
, const char **argv
)
1100 fprintf(stderr
, "Usage: smbcontrol <dest> reload-config\n");
1104 return send_message(msg_ctx
, pid
, MSG_SMB_CONF_UPDATED
, NULL
, 0);
1107 static void my_make_nmb_name( struct nmb_name
*n
, const char *name
, int type
)
1110 memset( (char *)n
, '\0', sizeof(struct nmb_name
) );
1111 fstrcpy(unix_name
, name
);
1112 strupper_m(unix_name
);
1113 push_ascii(n
->name
, unix_name
, sizeof(n
->name
), STR_TERMINATE
);
1114 n
->name_type
= (unsigned int)type
& 0xFF;
1115 push_ascii(n
->scope
, global_scope(), 64, STR_TERMINATE
);
1118 static bool do_nodestatus(struct messaging_context
*msg_ctx
,
1119 const struct server_id pid
,
1120 const int argc
, const char **argv
)
1122 struct packet_struct p
;
1125 fprintf(stderr
, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1131 p
.ip
= interpret_addr2(argv
[1]);
1133 p
.packet_type
= NMB_PACKET
;
1135 p
.packet
.nmb
.header
.name_trn_id
= 10;
1136 p
.packet
.nmb
.header
.opcode
= 0;
1137 p
.packet
.nmb
.header
.response
= False
;
1138 p
.packet
.nmb
.header
.nm_flags
.bcast
= False
;
1139 p
.packet
.nmb
.header
.nm_flags
.recursion_available
= False
;
1140 p
.packet
.nmb
.header
.nm_flags
.recursion_desired
= False
;
1141 p
.packet
.nmb
.header
.nm_flags
.trunc
= False
;
1142 p
.packet
.nmb
.header
.nm_flags
.authoritative
= False
;
1143 p
.packet
.nmb
.header
.rcode
= 0;
1144 p
.packet
.nmb
.header
.qdcount
= 1;
1145 p
.packet
.nmb
.header
.ancount
= 0;
1146 p
.packet
.nmb
.header
.nscount
= 0;
1147 p
.packet
.nmb
.header
.arcount
= 0;
1148 my_make_nmb_name(&p
.packet
.nmb
.question
.question_name
, "*", 0x00);
1149 p
.packet
.nmb
.question
.question_type
= 0x21;
1150 p
.packet
.nmb
.question
.question_class
= 0x1;
1152 return send_message(msg_ctx
, pid
, MSG_SEND_PACKET
, &p
, sizeof(p
));
1155 /* A list of message type supported */
1157 static const struct {
1158 const char *name
; /* Option name */
1159 bool (*fn
)(struct messaging_context
*msg_ctx
,
1160 const struct server_id pid
,
1161 const int argc
, const char **argv
);
1162 const char *help
; /* Short help text */
1164 { "debug", do_debug
, "Set debuglevel" },
1165 { "force-election", do_election
,
1166 "Force a browse election" },
1167 { "ping", do_ping
, "Elicit a response" },
1168 { "profile", do_profile
, "" },
1169 { "inject", do_inject_fault
,
1170 "Inject a fatal signal into a running smbd"},
1171 { "stacktrace", do_daemon_stack_trace
,
1172 "Display a stack trace of a daemon" },
1173 { "profilelevel", do_profilelevel
, "" },
1174 { "debuglevel", do_debuglevel
, "Display current debuglevels" },
1175 { "printnotify", do_printnotify
, "Send a print notify message" },
1176 { "close-share", do_closeshare
, "Forcibly disconnect a share" },
1177 { "lockretry", do_lockretry
, "Force a blocking lock retry" },
1178 { "brl-revalidate", do_brl_revalidate
, "Revalidate all brl entries" },
1179 { "samsync", do_samsync
, "Initiate SAM synchronisation" },
1180 { "samrepl", do_samrepl
, "Initiate SAM replication" },
1181 { "pool-usage", do_poolusage
, "Display talloc memory usage" },
1182 { "dmalloc-mark", do_dmalloc_mark
, "" },
1183 { "dmalloc-log-changed", do_dmalloc_changed
, "" },
1184 { "shutdown", do_shutdown
, "Shut down daemon" },
1185 { "drvupgrade", do_drvupgrade
, "Notify a printer driver has changed" },
1186 { "reload-config", do_reload_config
, "Force smbd or winbindd to reload config file"},
1187 { "nodestatus", do_nodestatus
, "Ask nmbd to do a node status request"},
1188 { "online", do_winbind_online
, "Ask winbind to go into online state"},
1189 { "offline", do_winbind_offline
, "Ask winbind to go into offline state"},
1190 { "onlinestatus", do_winbind_onlinestatus
, "Request winbind online status"},
1191 { "dump-event-list", do_dump_event_list
, "Dump event list"},
1192 { "validate-cache" , do_winbind_validate_cache
,
1193 "Validate winbind's credential cache" },
1194 { "dump-domain-list", do_winbind_dump_domain_list
, "Dump winbind domain list"},
1195 { "noop", do_noop
, "Do nothing" },
1199 /* Display usage information */
1201 static void usage(poptContext pc
)
1205 poptPrintHelp(pc
, stderr
, 0);
1207 fprintf(stderr
, "\n");
1208 fprintf(stderr
, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1211 fprintf(stderr
, "\n");
1212 fprintf(stderr
, "<message-type> is one of:\n");
1214 for (i
= 0; msg_types
[i
].name
; i
++)
1215 fprintf(stderr
, "\t%-30s%s\n", msg_types
[i
].name
,
1218 fprintf(stderr
, "\n");
1223 /* Return the pid number for a string destination */
1225 static struct server_id
parse_dest(const char *dest
)
1227 struct server_id result
= {-1};
1230 /* Zero is a special return value for broadcast to all processes */
1232 if (strequal(dest
, "all")) {
1233 return interpret_pid(MSG_BROADCAST_PID_STR
);
1236 /* Try self - useful for testing */
1238 if (strequal(dest
, "self")) {
1239 return pid_to_procid(sys_getpid());
1242 /* Fix winbind typo. */
1243 if (strequal(dest
, "winbind")) {
1247 if (!(strequal(dest
, "winbindd") || strequal(dest
, "nmbd"))) {
1248 /* Check for numeric pid number */
1250 result
= interpret_pid(dest
);
1252 /* Zero isn't valid if not smbd. */
1253 if (result
.pid
&& procid_valid(&result
)) {
1258 /* Look up other destinations in pidfile directory */
1260 if ((pid
= pidfile_pid(dest
)) != 0) {
1261 return pid_to_procid(pid
);
1264 fprintf(stderr
,"Can't find pid for destination '%s'\n", dest
);
1269 /* Execute smbcontrol command */
1271 static bool do_command(struct messaging_context
*msg_ctx
,
1272 int argc
, const char **argv
)
1274 const char *dest
= argv
[0], *command
= argv
[1];
1275 struct server_id pid
;
1278 /* Check destination */
1280 pid
= parse_dest(dest
);
1281 if (!procid_valid(&pid
)) {
1287 for (i
= 0; msg_types
[i
].name
; i
++) {
1288 if (strequal(command
, msg_types
[i
].name
))
1289 return msg_types
[i
].fn(msg_ctx
, pid
,
1290 argc
- 1, argv
+ 1);
1293 fprintf(stderr
, "smbcontrol: unknown command '%s'\n", command
);
1298 static void smbcontrol_help(poptContext pc
,
1299 enum poptCallbackReason preason
,
1300 struct poptOption
* poption
,
1304 if (poption
->shortName
!= '?') {
1305 poptPrintUsage(pc
, stdout
, 0);
1313 struct poptOption help_options
[] = {
1314 { NULL
, '\0', POPT_ARG_CALLBACK
, (void *)&smbcontrol_help
, '\0',
1316 { "help", '?', 0, NULL
, '?', "Show this help message", NULL
},
1317 { "usage", '\0', 0, NULL
, 'u', "Display brief usage message", NULL
},
1323 int main(int argc
, const char **argv
)
1327 struct event_context
*evt_ctx
;
1328 struct messaging_context
*msg_ctx
;
1330 static struct poptOption long_options
[] = {
1332 { NULL
, '\0', POPT_ARG_INCLUDE_TABLE
, help_options
,
1333 0, "Help options:", NULL
},
1334 { "timeout", 't', POPT_ARG_INT
, &timeout
, 't',
1335 "Set timeout value in seconds", "TIMEOUT" },
1340 TALLOC_CTX
*frame
= talloc_stackframe();
1345 setup_logging(argv
[0],True
);
1347 /* Parse command line arguments using popt */
1349 pc
= poptGetContext(
1350 "smbcontrol", argc
, (const char **)argv
, long_options
, 0);
1352 poptSetOtherOptionHelp(pc
, "[OPTION...] <destination> <message-type> "
1358 while ((opt
= poptGetNextOpt(pc
)) != -1) {
1360 case 't': /* --timeout */
1363 fprintf(stderr
, "Invalid option\n");
1364 poptPrintHelp(pc
, stderr
, 0);
1369 /* We should now have the remaining command line arguments in
1370 argv. The argc parameter should have been decremented to the
1371 correct value in the above switch statement. */
1373 argv
= (const char **)poptGetArgs(pc
);
1376 while (argv
[argc
] != NULL
) {
1384 lp_load(get_dyn_CONFIGFILE(),False
,False
,False
,True
);
1386 /* Need to invert sense of return code -- samba
1387 * routines mostly return True==1 for success, but
1390 if (!(evt_ctx
= event_context_init(NULL
)) ||
1391 !(msg_ctx
= messaging_init(NULL
, server_id_self(), evt_ctx
))) {
1392 fprintf(stderr
, "could not init messaging context\n");
1397 ret
= !do_command(msg_ctx
, argc
, argv
);