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 2 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, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 #include <libunwind.h>
33 #if HAVE_LIBUNWIND_PTRACE_H
34 #include <libunwind-ptrace.h>
38 #include <sys/ptrace.h>
41 /* Default timeout value when waiting for replies (in seconds) */
43 #define DEFAULT_TIMEOUT 10
45 static int timeout = DEFAULT_TIMEOUT;
46 static int num_replies; /* Used by message callback fns */
48 /* Send a message to a destination pid. Zero means broadcast smbd. */
50 static BOOL send_message(struct messaging_context *msg_ctx,
51 struct server_id pid, int msg_type,
52 const void *buf, int len,
58 if (procid_to_pid(&pid) != 0)
59 return NT_STATUS_IS_OK(
60 messaging_send_buf(msg_ctx, pid, msg_type,
63 ret = message_send_all(msg_ctx, msg_type, buf, len, duplicates,
65 DEBUG(10,("smbcontrol/send_message: broadcast message to "
66 "%d processes\n", n_sent));
71 /* Wait for one or more reply messages */
73 static void wait_replies(struct messaging_context *msg_ctx,
74 BOOL multiple_replies)
76 time_t start_time = time(NULL);
78 /* Wait around a bit. This is pretty disgusting - we have to
79 busy-wait here as there is no nicer way to do it. */
83 event_loop_once(messaging_event_context(msg_ctx));
84 if (num_replies > 0 && !multiple_replies)
87 } while (timeout - (time(NULL) - start_time) > 0);
90 /* Message handler callback that displays the PID and a string on stdout */
92 static void print_pid_string_cb(struct messaging_context *msg,
98 printf("PID %u: %.*s", (unsigned int)procid_to_pid(&pid),
99 (int)data->length, (const char *)data->data);
103 /* Message handler callback that displays a string on stdout */
105 static void print_string_cb(struct messaging_context *msg,
108 struct server_id pid,
111 printf("%.*s", (int)data->length, (const char *)data->data);
115 /* Send no message. Useful for testing. */
117 static BOOL do_noop(struct messaging_context *msg_ctx,
118 const struct server_id pid,
119 const int argc, const char **argv)
122 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
126 /* Move along, nothing to see here */
131 /* Send a debug string */
133 static BOOL do_debug(struct messaging_context *msg_ctx,
134 const struct server_id pid,
135 const int argc, const char **argv)
138 fprintf(stderr, "Usage: smbcontrol <dest> debug "
143 return send_message(msg_ctx,
144 pid, MSG_DEBUG, argv[1], strlen(argv[1]) + 1, False);
147 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
149 /* Return the name of a process given it's PID. This will only work on Linux,
150 * but that's probably moot since this whole stack tracing implementatino is
151 * Linux-specific anyway.
153 static const char * procname(pid_t pid, char * buf, size_t bufsz)
158 snprintf(path, sizeof(path), "/proc/%llu/cmdline",
159 (unsigned long long)pid);
160 if ((fp = fopen(path, "r")) == NULL) {
164 fgets(buf, bufsz, fp);
170 static void print_stack_trace(pid_t pid, int * count)
173 unw_addr_space_t aspace = NULL;
182 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
184 "Failed to attach to process %llu: %s\n",
185 (unsigned long long)pid, strerror(errno));
189 /* Wait until the attach is complete. */
190 waitpid(pid, NULL, 0);
192 if (((pinfo = _UPT_create(pid)) == NULL) ||
193 ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
194 /* Probably out of memory. */
196 "Unable to initialize stack unwind for process %llu\n",
197 (unsigned long long)pid);
201 if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
203 "Unable to unwind stack for process %llu: %s\n",
204 (unsigned long long)pid, unw_strerror(ret));
212 if (procname(pid, nbuf, sizeof(nbuf))) {
213 printf("Stack trace for process %llu (%s):\n",
214 (unsigned long long)pid, nbuf);
216 printf("Stack trace for process %llu:\n",
217 (unsigned long long)pid);
220 while (unw_step(&cursor) > 0) {
222 unw_get_reg(&cursor, UNW_REG_IP, &ip);
223 unw_get_reg(&cursor, UNW_REG_SP, &sp);
225 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
226 if (ret != 0 && ret != -UNW_ENOMEM) {
227 snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
229 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
230 nbuf, (long long)off, (long long)ip,
238 unw_destroy_addr_space(aspace);
245 ptrace(PTRACE_DETACH, pid, NULL, NULL);
248 static int stack_trace_connection(TDB_CONTEXT * tdb,
249 const struct connections_key *key,
250 const struct connections_data *conn,
252 print_stack_trace(procid_to_pid(&conn->pid), (int *)priv);
257 static BOOL do_daemon_stack_trace(struct messaging_context *msg_ctx,
258 const struct server_id pid,
259 const int argc, const char **argv)
262 "Daemon stack tracing is not supported on this platform\n");
269 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
273 dest = procid_to_pid(&pid);
276 /* It would be nice to be able to make sure that this PID is
277 * the PID of a smbd/winbind/nmbd process, not some random PID
278 * the user liked the look of. It doesn't seem like it's worth
279 * the effort at the moment, however.
281 print_stack_trace(dest, &count);
283 connections_traverse(stack_trace_connection, &count);
289 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
291 static BOOL do_daemon_stack_trace(struct messaging_context *msg_ctx,
292 const struct server_id pid,
293 const int argc, const char **argv)
296 "Daemon stack tracing is not supported on this platform\n");
300 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
302 /* Inject a fault (fatal signal) into a running smbd */
304 static BOOL do_inject_fault(struct messaging_context *msg_ctx,
305 const struct server_id pid,
306 const int argc, const char **argv)
309 fprintf(stderr, "Usage: smbcontrol <dest> inject "
310 "<bus|hup|term|internal|segv>\n");
315 fprintf(stderr, "Fault injection is only available in "
316 "developer builds\n");
318 #else /* DEVELOPER */
322 if (strcmp(argv[1], "bus") == 0) {
324 } else if (strcmp(argv[1], "hup") == 0) {
326 } else if (strcmp(argv[1], "term") == 0) {
328 } else if (strcmp(argv[1], "segv") == 0) {
330 } else if (strcmp(argv[1], "internal") == 0) {
331 /* Force an internal error, ie. an unclean exit. */
334 fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
338 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
339 &sig, sizeof(int), False);
341 #endif /* DEVELOPER */
344 /* Force a browser election */
346 static BOOL do_election(struct messaging_context *msg_ctx,
347 const struct server_id pid,
348 const int argc, const char **argv)
351 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
355 return send_message(msg_ctx,
356 pid, MSG_FORCE_ELECTION, NULL, 0, False);
359 /* Ping a samba daemon process */
361 static void pong_cb(struct messaging_context *msg,
364 struct server_id pid,
367 char *src_string = procid_str(NULL, &pid);
368 printf("PONG from pid %s\n", src_string);
369 TALLOC_FREE(src_string);
373 static BOOL do_ping(struct messaging_context *msg_ctx,
374 const struct server_id pid,
375 const int argc, const char **argv)
378 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
382 /* Send a message and register our interest in a reply */
384 if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0, False))
387 messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
389 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
391 /* No replies were received within the timeout period */
393 if (num_replies == 0)
394 printf("No replies received\n");
396 messaging_deregister(msg_ctx, MSG_PONG, NULL);
401 /* Set profiling options */
403 static BOOL do_profile(struct messaging_context *msg_ctx,
404 const struct server_id pid,
405 const int argc, const char **argv)
410 fprintf(stderr, "Usage: smbcontrol <dest> profile "
411 "<off|count|on|flush>\n");
415 if (strcmp(argv[1], "off") == 0) {
417 } else if (strcmp(argv[1], "count") == 0) {
419 } else if (strcmp(argv[1], "on") == 0) {
421 } else if (strcmp(argv[1], "flush") == 0) {
424 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
428 return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int), False);
431 /* Return the profiling level */
433 static void profilelevel_cb(struct messaging_context *msg_ctx,
436 struct server_id pid,
444 if (data->length != sizeof(int)) {
445 fprintf(stderr, "invalid message length %ld returned\n",
446 (unsigned long)data->length);
450 memcpy(&level, data->data, sizeof(int));
463 s = "count and time";
470 printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
473 static void profilelevel_rqst(struct messaging_context *msg_ctx,
476 struct server_id pid,
481 /* Send back a dummy reply */
483 send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int), False);
486 static BOOL do_profilelevel(struct messaging_context *msg_ctx,
487 const struct server_id pid,
488 const int argc, const char **argv)
491 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
495 /* Send a message and register our interest in a reply */
497 if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0, False))
500 messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
501 messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
504 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
506 /* No replies were received within the timeout period */
508 if (num_replies == 0)
509 printf("No replies received\n");
511 messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
516 /* Display debug level settings */
518 static BOOL do_debuglevel(struct messaging_context *msg_ctx,
519 const struct server_id pid,
520 const int argc, const char **argv)
523 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
527 /* Send a message and register our interest in a reply */
529 if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0, False))
532 messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
534 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
536 /* No replies were received within the timeout period */
538 if (num_replies == 0)
539 printf("No replies received\n");
541 messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
546 /* Send a print notify message */
548 static BOOL do_printnotify(struct messaging_context *msg_ctx,
549 const struct server_id pid,
550 const int argc, const char **argv)
554 /* Check for subcommand */
557 fprintf(stderr, "Must specify subcommand:\n");
558 fprintf(stderr, "\tqueuepause <printername>\n");
559 fprintf(stderr, "\tqueueresume <printername>\n");
560 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
561 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
562 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
563 fprintf(stderr, "\tprinter <printername> <comment|port|"
564 "driver> <value>\n");
571 if (strcmp(cmd, "queuepause") == 0) {
574 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
575 " queuepause <printername>\n");
579 notify_printer_status_byname(argv[2], PRINTER_STATUS_PAUSED);
583 } else if (strcmp(cmd, "queueresume") == 0) {
586 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
587 " queuereume <printername>\n");
591 notify_printer_status_byname(argv[2], PRINTER_STATUS_OK);
595 } else if (strcmp(cmd, "jobpause") == 0) {
599 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
600 " jobpause <printername> <unix-jobid>\n");
604 jobid = atoi(argv[3]);
606 notify_job_status_byname(
607 argv[2], jobid, JOB_STATUS_PAUSED,
608 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
612 } else if (strcmp(cmd, "jobresume") == 0) {
616 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
617 " jobpause <printername> <unix-jobid>\n");
621 jobid = atoi(argv[3]);
623 notify_job_status_byname(
624 argv[2], jobid, JOB_STATUS_QUEUED,
625 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
629 } else if (strcmp(cmd, "jobdelete") == 0) {
633 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
634 " jobpause <printername> <unix-jobid>\n");
638 jobid = atoi(argv[3]);
640 notify_job_status_byname(
641 argv[2], jobid, JOB_STATUS_DELETING,
642 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
644 notify_job_status_byname(
645 argv[2], jobid, JOB_STATUS_DELETING|
647 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
651 } else if (strcmp(cmd, "printer") == 0) {
655 fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
656 "printer <printername> <comment|port|driver> "
661 if (strcmp(argv[3], "comment") == 0) {
662 attribute = PRINTER_NOTIFY_COMMENT;
663 } else if (strcmp(argv[3], "port") == 0) {
664 attribute = PRINTER_NOTIFY_PORT_NAME;
665 } else if (strcmp(argv[3], "driver") == 0) {
666 attribute = PRINTER_NOTIFY_DRIVER_NAME;
668 fprintf(stderr, "Invalid printer command '%s'\n",
673 notify_printer_byname(argv[2], attribute,
674 CONST_DISCARD(char *, argv[4]));
679 fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
683 print_notify_send_messages(msg_ctx, 0);
689 static BOOL do_closeshare(struct messaging_context *msg_ctx,
690 const struct server_id pid,
691 const int argc, const char **argv)
694 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
699 return send_message(msg_ctx,
700 pid, MSG_SMB_FORCE_TDIS, argv[1], strlen(argv[1]) + 1, False);
703 /* Force a SAM synchronisation */
705 static BOOL do_samsync(struct messaging_context *msg_ctx,
706 const struct server_id pid,
707 const int argc, const char **argv)
710 fprintf(stderr, "Usage: smbcontrol <dest> samsync\n");
714 return send_message(msg_ctx,
715 pid, MSG_SMB_SAM_SYNC, NULL, 0, False);
718 /* Force a SAM replication */
720 static BOOL do_samrepl(struct messaging_context *msg_ctx,
721 const struct server_id pid,
722 const int argc, const char **argv)
725 fprintf(stderr, "Usage: smbcontrol <dest> samrepl\n");
729 return send_message(msg_ctx,
730 pid, MSG_SMB_SAM_REPL, NULL, 0, False);
733 /* Display talloc pool usage */
735 static BOOL do_poolusage(struct messaging_context *msg_ctx,
736 const struct server_id pid,
737 const int argc, const char **argv)
740 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
744 messaging_register(msg_ctx, NULL, MSG_POOL_USAGE, print_string_cb);
746 /* Send a message and register our interest in a reply */
748 if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0, False))
751 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
753 /* No replies were received within the timeout period */
755 if (num_replies == 0)
756 printf("No replies received\n");
758 messaging_deregister(msg_ctx, MSG_POOL_USAGE, NULL);
763 /* Perform a dmalloc mark */
765 static BOOL do_dmalloc_mark(struct messaging_context *msg_ctx,
766 const struct server_id pid,
767 const int argc, const char **argv)
770 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
774 return send_message(msg_ctx,
775 pid, MSG_REQ_DMALLOC_MARK, NULL, 0, False);
778 /* Perform a dmalloc changed */
780 static BOOL do_dmalloc_changed(struct messaging_context *msg_ctx,
781 const struct server_id pid,
782 const int argc, const char **argv)
785 fprintf(stderr, "Usage: smbcontrol <dest> "
786 "dmalloc-log-changed\n");
790 return send_message(msg_ctx,
791 pid, MSG_REQ_DMALLOC_LOG_CHANGED, NULL, 0, False);
794 /* Shutdown a server process */
796 static BOOL do_shutdown(struct messaging_context *msg_ctx,
797 const struct server_id pid,
798 const int argc, const char **argv)
801 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
805 return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0, False);
808 /* Notify a driver upgrade */
810 static BOOL do_drvupgrade(struct messaging_context *msg_ctx,
811 const struct server_id pid,
812 const int argc, const char **argv)
815 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
820 return send_message(msg_ctx,
821 pid, MSG_DEBUG, argv[1], strlen(argv[1]) + 1, False);
824 static BOOL do_winbind_online(struct messaging_context *msg_ctx,
825 const struct server_id pid,
826 const int argc, const char **argv)
831 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
835 if (!lp_winbind_offline_logon()) {
836 fprintf(stderr, "The parameter \"winbind offline logon\" must "
837 "be set in the [global] section of smb.conf for this "
838 "command to be allowed.\n");
842 /* Remove the entry in the winbindd_cache tdb to tell a later
843 starting winbindd that we're online. */
845 tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
847 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
848 lock_path("winbindd_cache.tdb"));
852 tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
855 return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0, False);
858 static BOOL do_winbind_offline(struct messaging_context *msg_ctx,
859 const struct server_id pid,
860 const int argc, const char **argv)
867 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
871 if (!lp_winbind_offline_logon()) {
872 fprintf(stderr, "The parameter \"winbind offline logon\" must "
873 "be set in the [global] section of smb.conf for this "
874 "command to be allowed.\n");
878 /* Create an entry in the winbindd_cache tdb to tell a later
879 starting winbindd that we're offline. We may actually create
882 tdb = tdb_open_log(lock_path("winbindd_cache.tdb"),
883 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
884 TDB_DEFAULT /* TDB_CLEAR_IF_FIRST */, O_RDWR|O_CREAT, 0600);
887 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
888 lock_path("winbindd_cache.tdb"));
892 /* There's a potential race condition that if a child
893 winbindd detects a domain is online at the same time
894 we're trying to tell it to go offline that it might
895 delete the record we add between us adding it and
896 sending the message. Minimize this by retrying up to
899 for (retry = 0; retry < 5; retry++) {
905 SIVAL(buf, 0, time(NULL));
909 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
911 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
914 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
915 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
917 if (!d.dptr || d.dsize != 4) {
919 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
930 static BOOL do_winbind_onlinestatus(struct messaging_context *msg_ctx,
931 const struct server_id pid,
932 const int argc, const char **argv)
934 struct server_id myid;
936 myid = pid_to_procid(sys_getpid());
939 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
943 messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
944 print_pid_string_cb);
946 if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, &myid,
947 sizeof(myid), False))
950 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
952 /* No replies were received within the timeout period */
954 if (num_replies == 0)
955 printf("No replies received\n");
957 messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
963 static BOOL do_reload_config(struct messaging_context *msg_ctx,
964 const struct server_id pid,
965 const int argc, const char **argv)
968 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
972 return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED,
976 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
979 memset( (char *)n, '\0', sizeof(struct nmb_name) );
980 fstrcpy(unix_name, name);
981 strupper_m(unix_name);
982 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
983 n->name_type = (unsigned int)type & 0xFF;
984 push_ascii(n->scope, global_scope(), 64, STR_TERMINATE);
987 static BOOL do_nodestatus(struct messaging_context *msg_ctx,
988 const struct server_id pid,
989 const int argc, const char **argv)
991 struct packet_struct p;
994 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1000 p.ip = *interpret_addr2(argv[1]);
1002 p.packet_type = NMB_PACKET;
1004 p.packet.nmb.header.name_trn_id = 10;
1005 p.packet.nmb.header.opcode = 0;
1006 p.packet.nmb.header.response = False;
1007 p.packet.nmb.header.nm_flags.bcast = False;
1008 p.packet.nmb.header.nm_flags.recursion_available = False;
1009 p.packet.nmb.header.nm_flags.recursion_desired = False;
1010 p.packet.nmb.header.nm_flags.trunc = False;
1011 p.packet.nmb.header.nm_flags.authoritative = False;
1012 p.packet.nmb.header.rcode = 0;
1013 p.packet.nmb.header.qdcount = 1;
1014 p.packet.nmb.header.ancount = 0;
1015 p.packet.nmb.header.nscount = 0;
1016 p.packet.nmb.header.arcount = 0;
1017 my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1018 p.packet.nmb.question.question_type = 0x21;
1019 p.packet.nmb.question.question_class = 0x1;
1021 return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p),
1025 /* A list of message type supported */
1027 static const struct {
1028 const char *name; /* Option name */
1029 BOOL (*fn)(struct messaging_context *msg_ctx,
1030 const struct server_id pid,
1031 const int argc, const char **argv);
1032 const char *help; /* Short help text */
1034 { "debug", do_debug, "Set debuglevel" },
1035 { "force-election", do_election,
1036 "Force a browse election" },
1037 { "ping", do_ping, "Elicit a response" },
1038 { "profile", do_profile, "" },
1039 { "inject", do_inject_fault,
1040 "Inject a fatal signal into a running smbd"},
1041 { "stacktrace", do_daemon_stack_trace,
1042 "Display a stack trace of a daemon" },
1043 { "profilelevel", do_profilelevel, "" },
1044 { "debuglevel", do_debuglevel, "Display current debuglevels" },
1045 { "printnotify", do_printnotify, "Send a print notify message" },
1046 { "close-share", do_closeshare, "Forcibly disconnect a share" },
1047 { "samsync", do_samsync, "Initiate SAM synchronisation" },
1048 { "samrepl", do_samrepl, "Initiate SAM replication" },
1049 { "pool-usage", do_poolusage, "Display talloc memory usage" },
1050 { "dmalloc-mark", do_dmalloc_mark, "" },
1051 { "dmalloc-log-changed", do_dmalloc_changed, "" },
1052 { "shutdown", do_shutdown, "Shut down daemon" },
1053 { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
1054 { "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
1055 { "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
1056 { "online", do_winbind_online, "Ask winbind to go into online state"},
1057 { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
1058 { "onlinestatus", do_winbind_onlinestatus, "Request winbind online status"},
1059 { "noop", do_noop, "Do nothing" },
1063 /* Display usage information */
1065 static void usage(poptContext pc)
1069 poptPrintHelp(pc, stderr, 0);
1071 fprintf(stderr, "\n");
1072 fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1075 fprintf(stderr, "\n");
1076 fprintf(stderr, "<message-type> is one of:\n");
1078 for (i = 0; msg_types[i].name; i++)
1079 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name,
1082 fprintf(stderr, "\n");
1087 /* Return the pid number for a string destination */
1089 static struct server_id parse_dest(const char *dest)
1091 struct server_id result = {-1};
1094 /* Zero is a special return value for broadcast smbd */
1096 if (strequal(dest, "smbd")) {
1097 return interpret_pid("0");
1100 /* Try self - useful for testing */
1102 if (strequal(dest, "self")) {
1103 return pid_to_procid(sys_getpid());
1106 /* Fix winbind typo. */
1107 if (strequal(dest, "winbind")) {
1112 if (!(strequal(dest, "winbindd") || strequal(dest, "nmbd"))) {
1113 /* Check for numeric pid number */
1115 result = interpret_pid(dest);
1117 /* Zero isn't valid if not smbd. */
1118 if (result.pid && procid_valid(&result)) {
1123 /* Look up other destinations in pidfile directory */
1125 if ((pid = pidfile_pid(dest)) != 0) {
1126 return pid_to_procid(pid);
1129 fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1134 /* Execute smbcontrol command */
1136 static BOOL do_command(struct messaging_context *msg_ctx,
1137 int argc, const char **argv)
1139 const char *dest = argv[0], *command = argv[1];
1140 struct server_id pid;
1143 /* Check destination */
1145 pid = parse_dest(dest);
1146 if (!procid_valid(&pid)) {
1152 for (i = 0; msg_types[i].name; i++) {
1153 if (strequal(command, msg_types[i].name))
1154 return msg_types[i].fn(msg_ctx, pid,
1155 argc - 1, argv + 1);
1158 fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1163 static void smbcontrol_help(poptContext pc,
1164 enum poptCallbackReason preason,
1165 struct poptOption * poption,
1169 if (poption->shortName != '?') {
1170 poptPrintUsage(pc, stdout, 0);
1178 struct poptOption help_options[] = {
1179 { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1181 { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1182 { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1188 int main(int argc, const char **argv)
1192 struct event_context *evt_ctx;
1193 struct messaging_context *msg_ctx;
1195 static struct poptOption long_options[] = {
1197 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1198 0, "Help options:", NULL },
1199 { "timeout", 't', POPT_ARG_INT, &timeout, 't',
1200 "Set timeout value in seconds", "TIMEOUT" },
1208 setup_logging(argv[0],True);
1210 /* Parse command line arguments using popt */
1212 pc = poptGetContext(
1213 "smbcontrol", argc, (const char **)argv, long_options, 0);
1215 poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1221 while ((opt = poptGetNextOpt(pc)) != -1) {
1223 case 't': /* --timeout */
1226 fprintf(stderr, "Invalid option\n");
1227 poptPrintHelp(pc, stderr, 0);
1232 /* We should now have the remaining command line arguments in
1233 argv. The argc parameter should have been decremented to the
1234 correct value in the above switch statement. */
1236 argv = (const char **)poptGetArgs(pc);
1238 while (argv[argc] != NULL) {
1245 lp_load(dyn_CONFIGFILE,False,False,False,True);
1247 /* Need to invert sense of return code -- samba
1248 * routines mostly return True==1 for success, but
1251 if (!(evt_ctx = event_context_init(NULL)) ||
1252 !(msg_ctx = messaging_init(NULL, server_id_self(), evt_ctx))) {
1253 fprintf(stderr, "could not init messaging context\n");
1257 return !do_command(msg_ctx, argc, argv);