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 tevent_context
*event_ctx
,
69 struct tevent_timer
*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 tevent_timer
*te
;
84 bool timed_out
= False
;
86 if (!(te
= tevent_add_timer(messaging_event_context(msg_ctx
), NULL
,
87 timeval_current_ofs(timeout
, 0),
88 smbcontrol_timeout
, (void *)&timed_out
))) {
89 DEBUG(0, ("tevent_add_timer failed\n"));
95 if (num_replies
> 0 && !multiple_replies
)
97 ret
= tevent_loop_once(messaging_event_context(msg_ctx
));
104 /* Message handler callback that displays the PID and a string on stdout */
106 static void print_pid_string_cb(struct messaging_context
*msg
,
109 struct server_id pid
,
112 printf("PID %u: %.*s", (unsigned int)procid_to_pid(&pid
),
113 (int)data
->length
, (const char *)data
->data
);
117 /* Message handler callback that displays a string on stdout */
119 static void print_string_cb(struct messaging_context
*msg
,
122 struct server_id pid
,
125 printf("%.*s", (int)data
->length
, (const char *)data
->data
);
129 /* Send no message. Useful for testing. */
131 static bool do_noop(struct messaging_context
*msg_ctx
,
132 const struct server_id pid
,
133 const int argc
, const char **argv
)
136 fprintf(stderr
, "Usage: smbcontrol <dest> noop\n");
140 /* Move along, nothing to see here */
145 /* Send a debug string */
147 static bool do_debug(struct messaging_context
*msg_ctx
,
148 const struct server_id pid
,
149 const int argc
, const char **argv
)
152 fprintf(stderr
, "Usage: smbcontrol <dest> debug "
157 return send_message(msg_ctx
, pid
, MSG_DEBUG
, argv
[1],
158 strlen(argv
[1]) + 1);
161 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
163 /* Return the name of a process given it's PID. This will only work on Linux,
164 * but that's probably moot since this whole stack tracing implementatino is
165 * Linux-specific anyway.
167 static const char * procname(pid_t pid
, char * buf
, size_t bufsz
)
172 snprintf(path
, sizeof(path
), "/proc/%llu/cmdline",
173 (unsigned long long)pid
);
174 if ((fp
= fopen(path
, "r")) == NULL
) {
178 fgets(buf
, bufsz
, fp
);
184 static void print_stack_trace(pid_t pid
, int * count
)
187 unw_addr_space_t aspace
= NULL
;
196 if (ptrace(PTRACE_ATTACH
, pid
, NULL
, NULL
) < 0) {
198 "Failed to attach to process %llu: %s\n",
199 (unsigned long long)pid
, strerror(errno
));
203 /* Wait until the attach is complete. */
204 waitpid(pid
, NULL
, 0);
206 if (((pinfo
= _UPT_create(pid
)) == NULL
) ||
207 ((aspace
= unw_create_addr_space(&_UPT_accessors
, 0)) == NULL
)) {
208 /* Probably out of memory. */
210 "Unable to initialize stack unwind for process %llu\n",
211 (unsigned long long)pid
);
215 if ((ret
= unw_init_remote(&cursor
, aspace
, pinfo
))) {
217 "Unable to unwind stack for process %llu: %s\n",
218 (unsigned long long)pid
, unw_strerror(ret
));
226 if (procname(pid
, nbuf
, sizeof(nbuf
))) {
227 printf("Stack trace for process %llu (%s):\n",
228 (unsigned long long)pid
, nbuf
);
230 printf("Stack trace for process %llu:\n",
231 (unsigned long long)pid
);
234 while (unw_step(&cursor
) > 0) {
236 unw_get_reg(&cursor
, UNW_REG_IP
, &ip
);
237 unw_get_reg(&cursor
, UNW_REG_SP
, &sp
);
239 ret
= unw_get_proc_name(&cursor
, nbuf
, sizeof(nbuf
), &off
);
240 if (ret
!= 0 && ret
!= -UNW_ENOMEM
) {
241 snprintf(nbuf
, sizeof(nbuf
), "<unknown symbol>");
243 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
244 nbuf
, (long long)off
, (long long)ip
,
252 unw_destroy_addr_space(aspace
);
259 ptrace(PTRACE_DETACH
, pid
, NULL
, NULL
);
262 static int stack_trace_connection(struct db_record
*rec
,
263 const struct connections_key
*key
,
264 const struct connections_data
*crec
,
267 print_stack_trace(procid_to_pid(&crec
->pid
), (int *)priv
);
272 static bool do_daemon_stack_trace(struct messaging_context
*msg_ctx
,
273 const struct server_id pid
,
274 const int argc
, const char **argv
)
280 fprintf(stderr
, "Usage: smbcontrol <dest> stacktrace\n");
284 dest
= procid_to_pid(&pid
);
287 /* It would be nice to be able to make sure that this PID is
288 * the PID of a smbd/winbind/nmbd process, not some random PID
289 * the user liked the look of. It doesn't seem like it's worth
290 * the effort at the moment, however.
292 print_stack_trace(dest
, &count
);
294 connections_forall(stack_trace_connection
, &count
);
300 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
302 static bool do_daemon_stack_trace(struct messaging_context
*msg_ctx
,
303 const struct server_id pid
,
304 const int argc
, const char **argv
)
307 "Daemon stack tracing is not supported on this platform\n");
311 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
313 /* Inject a fault (fatal signal) into a running smbd */
315 static bool do_inject_fault(struct messaging_context
*msg_ctx
,
316 const struct server_id pid
,
317 const int argc
, const char **argv
)
320 fprintf(stderr
, "Usage: smbcontrol <dest> inject "
321 "<bus|hup|term|internal|segv>\n");
326 fprintf(stderr
, "Fault injection is only available in "
327 "developer builds\n");
329 #else /* DEVELOPER */
333 if (strcmp(argv
[1], "bus") == 0) {
335 } else if (strcmp(argv
[1], "hup") == 0) {
337 } else if (strcmp(argv
[1], "term") == 0) {
339 } else if (strcmp(argv
[1], "segv") == 0) {
341 } else if (strcmp(argv
[1], "internal") == 0) {
342 /* Force an internal error, ie. an unclean exit. */
345 fprintf(stderr
, "Unknown signal name '%s'\n", argv
[1]);
349 return send_message(msg_ctx
, pid
, MSG_SMB_INJECT_FAULT
,
352 #endif /* DEVELOPER */
355 /* Force a browser election */
357 static bool do_election(struct messaging_context
*msg_ctx
,
358 const struct server_id pid
,
359 const int argc
, const char **argv
)
362 fprintf(stderr
, "Usage: smbcontrol <dest> force-election\n");
366 return send_message(msg_ctx
, pid
, MSG_FORCE_ELECTION
, NULL
, 0);
369 /* Ping a samba daemon process */
371 static void pong_cb(struct messaging_context
*msg
,
374 struct server_id pid
,
377 char *src_string
= procid_str(NULL
, &pid
);
378 printf("PONG from pid %s\n", src_string
);
379 TALLOC_FREE(src_string
);
383 static bool do_ping(struct messaging_context
*msg_ctx
,
384 const struct server_id pid
,
385 const int argc
, const char **argv
)
388 fprintf(stderr
, "Usage: smbcontrol <dest> ping\n");
392 /* Send a message and register our interest in a reply */
394 if (!send_message(msg_ctx
, pid
, MSG_PING
, NULL
, 0))
397 messaging_register(msg_ctx
, NULL
, MSG_PONG
, pong_cb
);
399 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
401 /* No replies were received within the timeout period */
403 if (num_replies
== 0)
404 printf("No replies received\n");
406 messaging_deregister(msg_ctx
, MSG_PONG
, NULL
);
411 /* Set profiling options */
413 static bool do_profile(struct messaging_context
*msg_ctx
,
414 const struct server_id pid
,
415 const int argc
, const char **argv
)
420 fprintf(stderr
, "Usage: smbcontrol <dest> profile "
421 "<off|count|on|flush>\n");
425 if (strcmp(argv
[1], "off") == 0) {
427 } else if (strcmp(argv
[1], "count") == 0) {
429 } else if (strcmp(argv
[1], "on") == 0) {
431 } else if (strcmp(argv
[1], "flush") == 0) {
434 fprintf(stderr
, "Unknown profile command '%s'\n", argv
[1]);
438 return send_message(msg_ctx
, pid
, MSG_PROFILE
, &v
, sizeof(int));
441 /* Return the profiling level */
443 static void profilelevel_cb(struct messaging_context
*msg_ctx
,
446 struct server_id pid
,
454 if (data
->length
!= sizeof(int)) {
455 fprintf(stderr
, "invalid message length %ld returned\n",
456 (unsigned long)data
->length
);
460 memcpy(&level
, data
->data
, sizeof(int));
473 s
= "count and time";
480 printf("Profiling %s on pid %u\n",s
,(unsigned int)procid_to_pid(&pid
));
483 static void profilelevel_rqst(struct messaging_context
*msg_ctx
,
486 struct server_id pid
,
491 /* Send back a dummy reply */
493 send_message(msg_ctx
, pid
, MSG_PROFILELEVEL
, &v
, sizeof(int));
496 static bool do_profilelevel(struct messaging_context
*msg_ctx
,
497 const struct server_id pid
,
498 const int argc
, const char **argv
)
501 fprintf(stderr
, "Usage: smbcontrol <dest> profilelevel\n");
505 /* Send a message and register our interest in a reply */
507 if (!send_message(msg_ctx
, pid
, MSG_REQ_PROFILELEVEL
, NULL
, 0))
510 messaging_register(msg_ctx
, NULL
, MSG_PROFILELEVEL
, profilelevel_cb
);
511 messaging_register(msg_ctx
, NULL
, MSG_REQ_PROFILELEVEL
,
514 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
516 /* No replies were received within the timeout period */
518 if (num_replies
== 0)
519 printf("No replies received\n");
521 messaging_deregister(msg_ctx
, MSG_PROFILE
, NULL
);
526 /* Display debug level settings */
528 static bool do_debuglevel(struct messaging_context
*msg_ctx
,
529 const struct server_id pid
,
530 const int argc
, const char **argv
)
533 fprintf(stderr
, "Usage: smbcontrol <dest> debuglevel\n");
537 /* Send a message and register our interest in a reply */
539 if (!send_message(msg_ctx
, pid
, MSG_REQ_DEBUGLEVEL
, NULL
, 0))
542 messaging_register(msg_ctx
, NULL
, MSG_DEBUGLEVEL
, print_pid_string_cb
);
544 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
546 /* No replies were received within the timeout period */
548 if (num_replies
== 0)
549 printf("No replies received\n");
551 messaging_deregister(msg_ctx
, MSG_DEBUGLEVEL
, NULL
);
556 /* Send a print notify message */
558 static bool do_printnotify(struct messaging_context
*msg_ctx
,
559 const struct server_id pid
,
560 const int argc
, const char **argv
)
564 /* Check for subcommand */
567 fprintf(stderr
, "Must specify subcommand:\n");
568 fprintf(stderr
, "\tqueuepause <printername>\n");
569 fprintf(stderr
, "\tqueueresume <printername>\n");
570 fprintf(stderr
, "\tjobpause <printername> <unix jobid>\n");
571 fprintf(stderr
, "\tjobresume <printername> <unix jobid>\n");
572 fprintf(stderr
, "\tjobdelete <printername> <unix jobid>\n");
573 fprintf(stderr
, "\tprinter <printername> <comment|port|"
574 "driver> <value>\n");
581 if (strcmp(cmd
, "queuepause") == 0) {
584 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
585 " queuepause <printername>\n");
589 notify_printer_status_byname(argv
[2], PRINTER_STATUS_PAUSED
);
593 } else if (strcmp(cmd
, "queueresume") == 0) {
596 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
597 " queuereume <printername>\n");
601 notify_printer_status_byname(argv
[2], PRINTER_STATUS_OK
);
605 } else if (strcmp(cmd
, "jobpause") == 0) {
609 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
610 " jobpause <printername> <unix-jobid>\n");
614 jobid
= atoi(argv
[3]);
616 notify_job_status_byname(
617 argv
[2], jobid
, JOB_STATUS_PAUSED
,
618 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
622 } else if (strcmp(cmd
, "jobresume") == 0) {
626 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
627 " jobpause <printername> <unix-jobid>\n");
631 jobid
= atoi(argv
[3]);
633 notify_job_status_byname(
634 argv
[2], jobid
, JOB_STATUS_QUEUED
,
635 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
639 } else if (strcmp(cmd
, "jobdelete") == 0) {
643 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
644 " jobpause <printername> <unix-jobid>\n");
648 jobid
= atoi(argv
[3]);
650 notify_job_status_byname(
651 argv
[2], jobid
, JOB_STATUS_DELETING
,
652 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
654 notify_job_status_byname(
655 argv
[2], jobid
, JOB_STATUS_DELETING
|
657 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
661 } else if (strcmp(cmd
, "printer") == 0) {
665 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify "
666 "printer <printername> <comment|port|driver> "
671 if (strcmp(argv
[3], "comment") == 0) {
672 attribute
= PRINTER_NOTIFY_FIELD_COMMENT
;
673 } else if (strcmp(argv
[3], "port") == 0) {
674 attribute
= PRINTER_NOTIFY_FIELD_PORT_NAME
;
675 } else if (strcmp(argv
[3], "driver") == 0) {
676 attribute
= PRINTER_NOTIFY_FIELD_DRIVER_NAME
;
678 fprintf(stderr
, "Invalid printer command '%s'\n",
683 notify_printer_byname(argv
[2], attribute
,
684 CONST_DISCARD(char *, argv
[4]));
689 fprintf(stderr
, "Invalid subcommand '%s'\n", cmd
);
693 print_notify_send_messages(msg_ctx
, 0);
699 static bool do_closeshare(struct messaging_context
*msg_ctx
,
700 const struct server_id pid
,
701 const int argc
, const char **argv
)
704 fprintf(stderr
, "Usage: smbcontrol <dest> close-share "
709 return send_message(msg_ctx
, pid
, MSG_SMB_FORCE_TDIS
, argv
[1],
710 strlen(argv
[1]) + 1);
713 /* force a blocking lock retry */
715 static bool do_lockretry(struct messaging_context
*msg_ctx
,
716 const struct server_id pid
,
717 const int argc
, const char **argv
)
720 fprintf(stderr
, "Usage: smbcontrol <dest> lockretry\n");
724 return send_message(msg_ctx
, pid
, MSG_SMB_UNLOCK
, NULL
, 0);
727 /* force a validation of all brl entries, including re-sends. */
729 static bool do_brl_revalidate(struct messaging_context
*msg_ctx
,
730 const struct server_id pid
,
731 const int argc
, const char **argv
)
734 fprintf(stderr
, "Usage: smbcontrol <dest> brl-revalidate\n");
738 return send_message(msg_ctx
, pid
, MSG_SMB_BRL_VALIDATE
, NULL
, 0);
741 /* Force a SAM synchronisation */
743 static bool do_samsync(struct messaging_context
*msg_ctx
,
744 const struct server_id pid
,
745 const int argc
, const char **argv
)
748 fprintf(stderr
, "Usage: smbcontrol <dest> samsync\n");
752 return send_message(msg_ctx
, pid
, MSG_SMB_SAM_SYNC
, NULL
, 0);
755 /* Force a SAM replication */
757 static bool do_samrepl(struct messaging_context
*msg_ctx
,
758 const struct server_id pid
,
759 const int argc
, const char **argv
)
762 fprintf(stderr
, "Usage: smbcontrol <dest> samrepl\n");
766 return send_message(msg_ctx
, pid
, MSG_SMB_SAM_REPL
, NULL
, 0);
769 /* Display talloc pool usage */
771 static bool do_poolusage(struct messaging_context
*msg_ctx
,
772 const struct server_id pid
,
773 const int argc
, const char **argv
)
776 fprintf(stderr
, "Usage: smbcontrol <dest> pool-usage\n");
780 messaging_register(msg_ctx
, NULL
, MSG_POOL_USAGE
, print_string_cb
);
782 /* Send a message and register our interest in a reply */
784 if (!send_message(msg_ctx
, pid
, MSG_REQ_POOL_USAGE
, NULL
, 0))
787 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
789 /* No replies were received within the timeout period */
791 if (num_replies
== 0)
792 printf("No replies received\n");
794 messaging_deregister(msg_ctx
, MSG_POOL_USAGE
, NULL
);
799 /* Perform a dmalloc mark */
801 static bool do_dmalloc_mark(struct messaging_context
*msg_ctx
,
802 const struct server_id pid
,
803 const int argc
, const char **argv
)
806 fprintf(stderr
, "Usage: smbcontrol <dest> dmalloc-mark\n");
810 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_MARK
, NULL
, 0);
813 /* Perform a dmalloc changed */
815 static bool do_dmalloc_changed(struct messaging_context
*msg_ctx
,
816 const struct server_id pid
,
817 const int argc
, const char **argv
)
820 fprintf(stderr
, "Usage: smbcontrol <dest> "
821 "dmalloc-log-changed\n");
825 return send_message(msg_ctx
, pid
, MSG_REQ_DMALLOC_LOG_CHANGED
,
829 /* Shutdown a server process */
831 static bool do_shutdown(struct messaging_context
*msg_ctx
,
832 const struct server_id pid
,
833 const int argc
, const char **argv
)
836 fprintf(stderr
, "Usage: smbcontrol <dest> shutdown\n");
840 return send_message(msg_ctx
, pid
, MSG_SHUTDOWN
, NULL
, 0);
843 /* Notify a driver upgrade */
845 static bool do_drvupgrade(struct messaging_context
*msg_ctx
,
846 const struct server_id pid
,
847 const int argc
, const char **argv
)
850 fprintf(stderr
, "Usage: smbcontrol <dest> drvupgrade "
855 return send_message(msg_ctx
, pid
, MSG_DEBUG
, argv
[1],
856 strlen(argv
[1]) + 1);
859 static bool do_winbind_online(struct messaging_context
*msg_ctx
,
860 const struct server_id pid
,
861 const int argc
, const char **argv
)
866 fprintf(stderr
, "Usage: smbcontrol winbindd online\n");
870 /* Remove the entry in the winbindd_cache tdb to tell a later
871 starting winbindd that we're online. */
873 tdb
= tdb_open_log(cache_path("winbindd_cache.tdb"), 0, TDB_DEFAULT
, O_RDWR
, 0600);
875 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
876 cache_path("winbindd_cache.tdb"));
880 tdb_delete_bystring(tdb
, "WINBINDD_OFFLINE");
883 return send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINE
, NULL
, 0);
886 static bool do_winbind_offline(struct messaging_context
*msg_ctx
,
887 const struct server_id pid
,
888 const int argc
, const char **argv
)
895 fprintf(stderr
, "Usage: smbcontrol winbindd offline\n");
899 /* Create an entry in the winbindd_cache tdb to tell a later
900 starting winbindd that we're offline. We may actually create
903 tdb
= tdb_open_log(cache_path("winbindd_cache.tdb"),
904 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE
,
905 TDB_DEFAULT
/* TDB_CLEAR_IF_FIRST */, O_RDWR
|O_CREAT
, 0600);
908 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
909 cache_path("winbindd_cache.tdb"));
913 /* There's a potential race condition that if a child
914 winbindd detects a domain is online at the same time
915 we're trying to tell it to go offline that it might
916 delete the record we add between us adding it and
917 sending the message. Minimize this by retrying up to
920 for (retry
= 0; retry
< 5; retry
++) {
926 SIVAL(buf
, 0, time(NULL
));
930 tdb_store_bystring(tdb
, "WINBINDD_OFFLINE", d
, TDB_INSERT
);
932 ret
= send_message(msg_ctx
, pid
, MSG_WINBIND_OFFLINE
,
935 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
936 d
= tdb_fetch_bystring( tdb
, "WINBINDD_OFFLINE" );
938 if (!d
.dptr
|| d
.dsize
!= 4) {
940 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
951 static bool do_winbind_onlinestatus(struct messaging_context
*msg_ctx
,
952 const struct server_id pid
,
953 const int argc
, const char **argv
)
955 struct server_id myid
;
957 myid
= pid_to_procid(sys_getpid());
960 fprintf(stderr
, "Usage: smbcontrol winbindd onlinestatus\n");
964 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_ONLINESTATUS
,
965 print_pid_string_cb
);
967 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_ONLINESTATUS
, &myid
,
971 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
973 /* No replies were received within the timeout period */
975 if (num_replies
== 0)
976 printf("No replies received\n");
978 messaging_deregister(msg_ctx
, MSG_WINBIND_ONLINESTATUS
, NULL
);
983 static bool do_dump_event_list(struct messaging_context
*msg_ctx
,
984 const struct server_id pid
,
985 const int argc
, const char **argv
)
987 struct server_id myid
;
989 myid
= pid_to_procid(sys_getpid());
992 fprintf(stderr
, "Usage: smbcontrol <dest> dump-event-list\n");
996 return send_message(msg_ctx
, pid
, MSG_DUMP_EVENT_LIST
, NULL
, 0);
999 static bool do_winbind_dump_domain_list(struct messaging_context
*msg_ctx
,
1000 const struct server_id pid
,
1001 const int argc
, const char **argv
)
1003 const char *domain
= NULL
;
1005 struct server_id myid
;
1006 uint8_t *buf
= NULL
;
1009 myid
= pid_to_procid(sys_getpid());
1011 if (argc
< 1 || argc
> 2) {
1012 fprintf(stderr
, "Usage: smbcontrol <dest> dump_domain_list "
1019 domain_len
= strlen(argv
[1]) + 1;
1022 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1023 print_pid_string_cb
);
1025 buf_len
= sizeof(myid
)+domain_len
;
1026 buf
= SMB_MALLOC_ARRAY(uint8_t, buf_len
);
1031 memcpy(buf
, &myid
, sizeof(myid
));
1032 memcpy(&buf
[sizeof(myid
)], domain
, domain_len
);
1034 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_DUMP_DOMAIN_LIST
,
1041 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
1043 /* No replies were received within the timeout period */
1046 if (num_replies
== 0) {
1047 printf("No replies received\n");
1050 messaging_deregister(msg_ctx
, MSG_WINBIND_DUMP_DOMAIN_LIST
, NULL
);
1055 static void winbind_validate_cache_cb(struct messaging_context
*msg
,
1058 struct server_id pid
,
1061 char *src_string
= procid_str(NULL
, &pid
);
1062 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1063 (*(data
->data
) == 0 ? "" : "NOT "), src_string
);
1064 TALLOC_FREE(src_string
);
1068 static bool do_winbind_validate_cache(struct messaging_context
*msg_ctx
,
1069 const struct server_id pid
,
1070 const int argc
, const char **argv
)
1072 struct server_id myid
= pid_to_procid(sys_getpid());
1075 fprintf(stderr
, "Usage: smbcontrol winbindd validate-cache\n");
1079 messaging_register(msg_ctx
, NULL
, MSG_WINBIND_VALIDATE_CACHE
,
1080 winbind_validate_cache_cb
);
1082 if (!send_message(msg_ctx
, pid
, MSG_WINBIND_VALIDATE_CACHE
, &myid
,
1087 wait_replies(msg_ctx
, procid_to_pid(&pid
) == 0);
1089 if (num_replies
== 0) {
1090 printf("No replies received\n");
1093 messaging_deregister(msg_ctx
, MSG_WINBIND_VALIDATE_CACHE
, NULL
);
1098 static bool do_reload_config(struct messaging_context
*msg_ctx
,
1099 const struct server_id pid
,
1100 const int argc
, const char **argv
)
1103 fprintf(stderr
, "Usage: smbcontrol <dest> reload-config\n");
1107 return send_message(msg_ctx
, pid
, MSG_SMB_CONF_UPDATED
, NULL
, 0);
1110 static void my_make_nmb_name( struct nmb_name
*n
, const char *name
, int type
)
1113 memset( (char *)n
, '\0', sizeof(struct nmb_name
) );
1114 fstrcpy(unix_name
, name
);
1115 strupper_m(unix_name
);
1116 push_ascii(n
->name
, unix_name
, sizeof(n
->name
), STR_TERMINATE
);
1117 n
->name_type
= (unsigned int)type
& 0xFF;
1118 push_ascii(n
->scope
, global_scope(), 64, STR_TERMINATE
);
1121 static bool do_nodestatus(struct messaging_context
*msg_ctx
,
1122 const struct server_id pid
,
1123 const int argc
, const char **argv
)
1125 struct packet_struct p
;
1128 fprintf(stderr
, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1134 p
.ip
= interpret_addr2(argv
[1]);
1136 p
.packet_type
= NMB_PACKET
;
1138 p
.packet
.nmb
.header
.name_trn_id
= 10;
1139 p
.packet
.nmb
.header
.opcode
= 0;
1140 p
.packet
.nmb
.header
.response
= False
;
1141 p
.packet
.nmb
.header
.nm_flags
.bcast
= False
;
1142 p
.packet
.nmb
.header
.nm_flags
.recursion_available
= False
;
1143 p
.packet
.nmb
.header
.nm_flags
.recursion_desired
= False
;
1144 p
.packet
.nmb
.header
.nm_flags
.trunc
= False
;
1145 p
.packet
.nmb
.header
.nm_flags
.authoritative
= False
;
1146 p
.packet
.nmb
.header
.rcode
= 0;
1147 p
.packet
.nmb
.header
.qdcount
= 1;
1148 p
.packet
.nmb
.header
.ancount
= 0;
1149 p
.packet
.nmb
.header
.nscount
= 0;
1150 p
.packet
.nmb
.header
.arcount
= 0;
1151 my_make_nmb_name(&p
.packet
.nmb
.question
.question_name
, "*", 0x00);
1152 p
.packet
.nmb
.question
.question_type
= 0x21;
1153 p
.packet
.nmb
.question
.question_class
= 0x1;
1155 return send_message(msg_ctx
, pid
, MSG_SEND_PACKET
, &p
, sizeof(p
));
1158 /* A list of message type supported */
1160 static const struct {
1161 const char *name
; /* Option name */
1162 bool (*fn
)(struct messaging_context
*msg_ctx
,
1163 const struct server_id pid
,
1164 const int argc
, const char **argv
);
1165 const char *help
; /* Short help text */
1167 { "debug", do_debug
, "Set debuglevel" },
1168 { "force-election", do_election
,
1169 "Force a browse election" },
1170 { "ping", do_ping
, "Elicit a response" },
1171 { "profile", do_profile
, "" },
1172 { "inject", do_inject_fault
,
1173 "Inject a fatal signal into a running smbd"},
1174 { "stacktrace", do_daemon_stack_trace
,
1175 "Display a stack trace of a daemon" },
1176 { "profilelevel", do_profilelevel
, "" },
1177 { "debuglevel", do_debuglevel
, "Display current debuglevels" },
1178 { "printnotify", do_printnotify
, "Send a print notify message" },
1179 { "close-share", do_closeshare
, "Forcibly disconnect a share" },
1180 { "lockretry", do_lockretry
, "Force a blocking lock retry" },
1181 { "brl-revalidate", do_brl_revalidate
, "Revalidate all brl entries" },
1182 { "samsync", do_samsync
, "Initiate SAM synchronisation" },
1183 { "samrepl", do_samrepl
, "Initiate SAM replication" },
1184 { "pool-usage", do_poolusage
, "Display talloc memory usage" },
1185 { "dmalloc-mark", do_dmalloc_mark
, "" },
1186 { "dmalloc-log-changed", do_dmalloc_changed
, "" },
1187 { "shutdown", do_shutdown
, "Shut down daemon" },
1188 { "drvupgrade", do_drvupgrade
, "Notify a printer driver has changed" },
1189 { "reload-config", do_reload_config
, "Force smbd or winbindd to reload config file"},
1190 { "nodestatus", do_nodestatus
, "Ask nmbd to do a node status request"},
1191 { "online", do_winbind_online
, "Ask winbind to go into online state"},
1192 { "offline", do_winbind_offline
, "Ask winbind to go into offline state"},
1193 { "onlinestatus", do_winbind_onlinestatus
, "Request winbind online status"},
1194 { "dump-event-list", do_dump_event_list
, "Dump event list"},
1195 { "validate-cache" , do_winbind_validate_cache
,
1196 "Validate winbind's credential cache" },
1197 { "dump-domain-list", do_winbind_dump_domain_list
, "Dump winbind domain list"},
1198 { "noop", do_noop
, "Do nothing" },
1202 /* Display usage information */
1204 static void usage(poptContext pc
)
1208 poptPrintHelp(pc
, stderr
, 0);
1210 fprintf(stderr
, "\n");
1211 fprintf(stderr
, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1214 fprintf(stderr
, "\n");
1215 fprintf(stderr
, "<message-type> is one of:\n");
1217 for (i
= 0; msg_types
[i
].name
; i
++)
1218 fprintf(stderr
, "\t%-30s%s\n", msg_types
[i
].name
,
1221 fprintf(stderr
, "\n");
1226 /* Return the pid number for a string destination */
1228 static struct server_id
parse_dest(const char *dest
)
1230 struct server_id result
= {-1};
1233 /* Zero is a special return value for broadcast to all processes */
1235 if (strequal(dest
, "all")) {
1236 return interpret_pid(MSG_BROADCAST_PID_STR
);
1239 /* Try self - useful for testing */
1241 if (strequal(dest
, "self")) {
1242 return pid_to_procid(sys_getpid());
1245 /* Fix winbind typo. */
1246 if (strequal(dest
, "winbind")) {
1250 /* Check for numeric pid number */
1251 result
= interpret_pid(dest
);
1253 /* Zero isn't valid if not "all". */
1254 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 tevent_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
= tevent_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
);