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)
57 if (procid_to_pid(&pid) != 0)
58 return NT_STATUS_IS_OK(
59 messaging_send_buf(msg_ctx, pid, msg_type,
62 ret = message_send_all(msg_ctx, msg_type, buf, len, &n_sent);
63 DEBUG(10,("smbcontrol/send_message: broadcast message to "
64 "%d processes\n", n_sent));
69 /* Wait for one or more reply messages */
71 static void wait_replies(struct messaging_context *msg_ctx,
72 BOOL multiple_replies)
74 time_t start_time = time(NULL);
76 /* Wait around a bit. This is pretty disgusting - we have to
77 busy-wait here as there is no nicer way to do it. */
80 message_dispatch(msg_ctx);
81 event_loop_once(messaging_event_context(msg_ctx));
82 if (num_replies > 0 && !multiple_replies)
85 } while (timeout - (time(NULL) - start_time) > 0);
88 /* Message handler callback that displays the PID and a string on stdout */
90 static void print_pid_string_cb(struct messaging_context *msg,
96 printf("PID %u: %.*s", (unsigned int)procid_to_pid(&pid),
97 (int)data->length, (const char *)data->data);
101 /* Message handler callback that displays a string on stdout */
103 static void print_string_cb(struct messaging_context *msg,
106 struct server_id pid,
109 printf("%.*s", (int)data->length, (const char *)data->data);
113 /* Send no message. Useful for testing. */
115 static BOOL do_noop(struct messaging_context *msg_ctx,
116 const struct server_id pid,
117 const int argc, const char **argv)
120 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
124 /* Move along, nothing to see here */
129 /* Send a debug string */
131 static BOOL do_debug(struct messaging_context *msg_ctx,
132 const struct server_id pid,
133 const int argc, const char **argv)
136 fprintf(stderr, "Usage: smbcontrol <dest> debug "
141 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
142 strlen(argv[1]) + 1);
145 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
147 /* Return the name of a process given it's PID. This will only work on Linux,
148 * but that's probably moot since this whole stack tracing implementatino is
149 * Linux-specific anyway.
151 static const char * procname(pid_t pid, char * buf, size_t bufsz)
156 snprintf(path, sizeof(path), "/proc/%llu/cmdline",
157 (unsigned long long)pid);
158 if ((fp = fopen(path, "r")) == NULL) {
162 fgets(buf, bufsz, fp);
168 static void print_stack_trace(pid_t pid, int * count)
171 unw_addr_space_t aspace = NULL;
180 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
182 "Failed to attach to process %llu: %s\n",
183 (unsigned long long)pid, strerror(errno));
187 /* Wait until the attach is complete. */
188 waitpid(pid, NULL, 0);
190 if (((pinfo = _UPT_create(pid)) == NULL) ||
191 ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
192 /* Probably out of memory. */
194 "Unable to initialize stack unwind for process %llu\n",
195 (unsigned long long)pid);
199 if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
201 "Unable to unwind stack for process %llu: %s\n",
202 (unsigned long long)pid, unw_strerror(ret));
210 if (procname(pid, nbuf, sizeof(nbuf))) {
211 printf("Stack trace for process %llu (%s):\n",
212 (unsigned long long)pid, nbuf);
214 printf("Stack trace for process %llu:\n",
215 (unsigned long long)pid);
218 while (unw_step(&cursor) > 0) {
220 unw_get_reg(&cursor, UNW_REG_IP, &ip);
221 unw_get_reg(&cursor, UNW_REG_SP, &sp);
223 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
224 if (ret != 0 && ret != -UNW_ENOMEM) {
225 snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
227 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
228 nbuf, (long long)off, (long long)ip,
236 unw_destroy_addr_space(aspace);
243 ptrace(PTRACE_DETACH, pid, NULL, NULL);
246 static int stack_trace_connection(struct db_record *rec,
247 const struct connections_key *key,
248 const struct connections_data *crec,
251 print_stack_trace(procid_to_pid(&conn->pid), (int *)priv);
256 static BOOL do_daemon_stack_trace(struct messaging_context *msg_ctx,
257 const struct server_id pid,
258 const int argc, const char **argv)
261 "Daemon stack tracing is not supported on this platform\n");
268 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
272 dest = procid_to_pid(&pid);
275 /* It would be nice to be able to make sure that this PID is
276 * the PID of a smbd/winbind/nmbd process, not some random PID
277 * the user liked the look of. It doesn't seem like it's worth
278 * the effort at the moment, however.
280 print_stack_trace(dest, &count);
282 connections_forall(stack_trace_connection, &count);
288 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
290 static BOOL do_daemon_stack_trace(struct messaging_context *msg_ctx,
291 const struct server_id pid,
292 const int argc, const char **argv)
295 "Daemon stack tracing is not supported on this platform\n");
299 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
301 /* Inject a fault (fatal signal) into a running smbd */
303 static BOOL do_inject_fault(struct messaging_context *msg_ctx,
304 const struct server_id pid,
305 const int argc, const char **argv)
308 fprintf(stderr, "Usage: smbcontrol <dest> inject "
309 "<bus|hup|term|internal|segv>\n");
314 fprintf(stderr, "Fault injection is only available in "
315 "developer builds\n");
317 #else /* DEVELOPER */
321 if (strcmp(argv[1], "bus") == 0) {
323 } else if (strcmp(argv[1], "hup") == 0) {
325 } else if (strcmp(argv[1], "term") == 0) {
327 } else if (strcmp(argv[1], "segv") == 0) {
329 } else if (strcmp(argv[1], "internal") == 0) {
330 /* Force an internal error, ie. an unclean exit. */
333 fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
337 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
340 #endif /* DEVELOPER */
343 /* Force a browser election */
345 static BOOL do_election(struct messaging_context *msg_ctx,
346 const struct server_id pid,
347 const int argc, const char **argv)
350 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
354 return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
357 /* Ping a samba daemon process */
359 static void pong_cb(struct messaging_context *msg,
362 struct server_id pid,
365 char *src_string = procid_str(NULL, &pid);
366 printf("PONG from pid %s\n", src_string);
367 TALLOC_FREE(src_string);
371 static BOOL do_ping(struct messaging_context *msg_ctx,
372 const struct server_id pid,
373 const int argc, const char **argv)
376 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
380 /* Send a message and register our interest in a reply */
382 if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
385 messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
387 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
389 /* No replies were received within the timeout period */
391 if (num_replies == 0)
392 printf("No replies received\n");
394 messaging_deregister(msg_ctx, MSG_PONG, NULL);
399 /* Set profiling options */
401 static BOOL do_profile(struct messaging_context *msg_ctx,
402 const struct server_id pid,
403 const int argc, const char **argv)
408 fprintf(stderr, "Usage: smbcontrol <dest> profile "
409 "<off|count|on|flush>\n");
413 if (strcmp(argv[1], "off") == 0) {
415 } else if (strcmp(argv[1], "count") == 0) {
417 } else if (strcmp(argv[1], "on") == 0) {
419 } else if (strcmp(argv[1], "flush") == 0) {
422 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
426 return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
429 /* Return the profiling level */
431 static void profilelevel_cb(struct messaging_context *msg_ctx,
434 struct server_id pid,
442 if (data->length != sizeof(int)) {
443 fprintf(stderr, "invalid message length %ld returned\n",
444 (unsigned long)data->length);
448 memcpy(&level, data->data, sizeof(int));
461 s = "count and time";
468 printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
471 static void profilelevel_rqst(struct messaging_context *msg_ctx,
474 struct server_id pid,
479 /* Send back a dummy reply */
481 send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
484 static BOOL do_profilelevel(struct messaging_context *msg_ctx,
485 const struct server_id pid,
486 const int argc, const char **argv)
489 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
493 /* Send a message and register our interest in a reply */
495 if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
498 messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
499 messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
502 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
504 /* No replies were received within the timeout period */
506 if (num_replies == 0)
507 printf("No replies received\n");
509 messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
514 /* Display debug level settings */
516 static BOOL do_debuglevel(struct messaging_context *msg_ctx,
517 const struct server_id pid,
518 const int argc, const char **argv)
521 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
525 /* Send a message and register our interest in a reply */
527 if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
530 messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
532 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
534 /* No replies were received within the timeout period */
536 if (num_replies == 0)
537 printf("No replies received\n");
539 messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
544 /* Send a print notify message */
546 static BOOL do_printnotify(struct messaging_context *msg_ctx,
547 const struct server_id pid,
548 const int argc, const char **argv)
552 /* Check for subcommand */
555 fprintf(stderr, "Must specify subcommand:\n");
556 fprintf(stderr, "\tqueuepause <printername>\n");
557 fprintf(stderr, "\tqueueresume <printername>\n");
558 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
559 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
560 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
561 fprintf(stderr, "\tprinter <printername> <comment|port|"
562 "driver> <value>\n");
569 if (strcmp(cmd, "queuepause") == 0) {
572 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
573 " queuepause <printername>\n");
577 notify_printer_status_byname(argv[2], PRINTER_STATUS_PAUSED);
581 } else if (strcmp(cmd, "queueresume") == 0) {
584 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
585 " queuereume <printername>\n");
589 notify_printer_status_byname(argv[2], PRINTER_STATUS_OK);
593 } else if (strcmp(cmd, "jobpause") == 0) {
597 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
598 " jobpause <printername> <unix-jobid>\n");
602 jobid = atoi(argv[3]);
604 notify_job_status_byname(
605 argv[2], jobid, JOB_STATUS_PAUSED,
606 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
610 } else if (strcmp(cmd, "jobresume") == 0) {
614 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
615 " jobpause <printername> <unix-jobid>\n");
619 jobid = atoi(argv[3]);
621 notify_job_status_byname(
622 argv[2], jobid, JOB_STATUS_QUEUED,
623 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
627 } else if (strcmp(cmd, "jobdelete") == 0) {
631 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
632 " jobpause <printername> <unix-jobid>\n");
636 jobid = atoi(argv[3]);
638 notify_job_status_byname(
639 argv[2], jobid, JOB_STATUS_DELETING,
640 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
642 notify_job_status_byname(
643 argv[2], jobid, JOB_STATUS_DELETING|
645 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
649 } else if (strcmp(cmd, "printer") == 0) {
653 fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
654 "printer <printername> <comment|port|driver> "
659 if (strcmp(argv[3], "comment") == 0) {
660 attribute = PRINTER_NOTIFY_COMMENT;
661 } else if (strcmp(argv[3], "port") == 0) {
662 attribute = PRINTER_NOTIFY_PORT_NAME;
663 } else if (strcmp(argv[3], "driver") == 0) {
664 attribute = PRINTER_NOTIFY_DRIVER_NAME;
666 fprintf(stderr, "Invalid printer command '%s'\n",
671 notify_printer_byname(argv[2], attribute,
672 CONST_DISCARD(char *, argv[4]));
677 fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
681 print_notify_send_messages(msg_ctx, 0);
687 static BOOL do_closeshare(struct messaging_context *msg_ctx,
688 const struct server_id pid,
689 const int argc, const char **argv)
692 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
697 return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
698 strlen(argv[1]) + 1);
701 /* force a blocking lock retry */
703 static BOOL do_lockretry(struct messaging_context *msg_ctx,
704 const struct server_id pid,
705 const int argc, const char **argv)
708 fprintf(stderr, "Usage: smbcontrol <dest> lockretry\n");
712 return send_message(msg_ctx, pid, MSG_SMB_UNLOCK, NULL, 0);
715 /* force a validation of all brl entries, including re-sends. */
717 static BOOL do_brl_revalidate(struct messaging_context *msg_ctx,
718 const struct server_id pid,
719 const int argc, const char **argv)
722 fprintf(stderr, "Usage: smbcontrol <dest> brl-revalidate\n");
726 return send_message(msg_ctx, pid, MSG_SMB_BRL_VALIDATE, NULL, 0);
729 /* Force a SAM synchronisation */
731 static BOOL do_samsync(struct messaging_context *msg_ctx,
732 const struct server_id pid,
733 const int argc, const char **argv)
736 fprintf(stderr, "Usage: smbcontrol <dest> samsync\n");
740 return send_message(msg_ctx, pid, MSG_SMB_SAM_SYNC, NULL, 0);
743 /* Force a SAM replication */
745 static BOOL do_samrepl(struct messaging_context *msg_ctx,
746 const struct server_id pid,
747 const int argc, const char **argv)
750 fprintf(stderr, "Usage: smbcontrol <dest> samrepl\n");
754 return send_message(msg_ctx, pid, MSG_SMB_SAM_REPL, NULL, 0);
757 /* Display talloc pool usage */
759 static BOOL do_poolusage(struct messaging_context *msg_ctx,
760 const struct server_id pid,
761 const int argc, const char **argv)
764 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
768 messaging_register(msg_ctx, NULL, MSG_POOL_USAGE, print_string_cb);
770 /* Send a message and register our interest in a reply */
772 if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0))
775 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
777 /* No replies were received within the timeout period */
779 if (num_replies == 0)
780 printf("No replies received\n");
782 messaging_deregister(msg_ctx, MSG_POOL_USAGE, NULL);
787 /* Perform a dmalloc mark */
789 static BOOL do_dmalloc_mark(struct messaging_context *msg_ctx,
790 const struct server_id pid,
791 const int argc, const char **argv)
794 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
798 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
801 /* Perform a dmalloc changed */
803 static BOOL do_dmalloc_changed(struct messaging_context *msg_ctx,
804 const struct server_id pid,
805 const int argc, const char **argv)
808 fprintf(stderr, "Usage: smbcontrol <dest> "
809 "dmalloc-log-changed\n");
813 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
817 /* Shutdown a server process */
819 static BOOL do_shutdown(struct messaging_context *msg_ctx,
820 const struct server_id pid,
821 const int argc, const char **argv)
824 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
828 return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
831 /* Notify a driver upgrade */
833 static BOOL do_drvupgrade(struct messaging_context *msg_ctx,
834 const struct server_id pid,
835 const int argc, const char **argv)
838 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
843 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
844 strlen(argv[1]) + 1);
847 static BOOL do_winbind_online(struct messaging_context *msg_ctx,
848 const struct server_id pid,
849 const int argc, const char **argv)
854 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
858 if (!lp_winbind_offline_logon()) {
859 fprintf(stderr, "The parameter \"winbind offline logon\" must "
860 "be set in the [global] section of smb.conf for this "
861 "command to be allowed.\n");
865 /* Remove the entry in the winbindd_cache tdb to tell a later
866 starting winbindd that we're online. */
868 tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
870 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
871 lock_path("winbindd_cache.tdb"));
875 tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
878 return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
881 static BOOL do_winbind_offline(struct messaging_context *msg_ctx,
882 const struct server_id pid,
883 const int argc, const char **argv)
890 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
894 if (!lp_winbind_offline_logon()) {
895 fprintf(stderr, "The parameter \"winbind offline logon\" must "
896 "be set in the [global] section of smb.conf for this "
897 "command to be allowed.\n");
901 /* Create an entry in the winbindd_cache tdb to tell a later
902 starting winbindd that we're offline. We may actually create
905 tdb = tdb_open_log(lock_path("winbindd_cache.tdb"),
906 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
907 TDB_DEFAULT /* TDB_CLEAR_IF_FIRST */, O_RDWR|O_CREAT, 0600);
910 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
911 lock_path("winbindd_cache.tdb"));
915 /* There's a potential race condition that if a child
916 winbindd detects a domain is online at the same time
917 we're trying to tell it to go offline that it might
918 delete the record we add between us adding it and
919 sending the message. Minimize this by retrying up to
922 for (retry = 0; retry < 5; retry++) {
928 SIVAL(buf, 0, time(NULL));
932 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
934 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
937 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
938 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
940 if (!d.dptr || d.dsize != 4) {
942 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
953 static BOOL do_winbind_onlinestatus(struct messaging_context *msg_ctx,
954 const struct server_id pid,
955 const int argc, const char **argv)
957 struct server_id myid;
959 myid = pid_to_procid(sys_getpid());
962 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
966 messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
967 print_pid_string_cb);
969 if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, &myid,
973 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
975 /* No replies were received within the timeout period */
977 if (num_replies == 0)
978 printf("No replies received\n");
980 messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
986 static BOOL do_reload_config(struct messaging_context *msg_ctx,
987 const struct server_id pid,
988 const int argc, const char **argv)
991 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
995 return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
998 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1001 memset( (char *)n, '\0', sizeof(struct nmb_name) );
1002 fstrcpy(unix_name, name);
1003 strupper_m(unix_name);
1004 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1005 n->name_type = (unsigned int)type & 0xFF;
1006 push_ascii(n->scope, global_scope(), 64, STR_TERMINATE);
1009 static BOOL do_nodestatus(struct messaging_context *msg_ctx,
1010 const struct server_id pid,
1011 const int argc, const char **argv)
1013 struct packet_struct p;
1016 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1022 p.ip = *interpret_addr2(argv[1]);
1024 p.packet_type = NMB_PACKET;
1026 p.packet.nmb.header.name_trn_id = 10;
1027 p.packet.nmb.header.opcode = 0;
1028 p.packet.nmb.header.response = False;
1029 p.packet.nmb.header.nm_flags.bcast = False;
1030 p.packet.nmb.header.nm_flags.recursion_available = False;
1031 p.packet.nmb.header.nm_flags.recursion_desired = False;
1032 p.packet.nmb.header.nm_flags.trunc = False;
1033 p.packet.nmb.header.nm_flags.authoritative = False;
1034 p.packet.nmb.header.rcode = 0;
1035 p.packet.nmb.header.qdcount = 1;
1036 p.packet.nmb.header.ancount = 0;
1037 p.packet.nmb.header.nscount = 0;
1038 p.packet.nmb.header.arcount = 0;
1039 my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1040 p.packet.nmb.question.question_type = 0x21;
1041 p.packet.nmb.question.question_class = 0x1;
1043 return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1046 /* A list of message type supported */
1048 static const struct {
1049 const char *name; /* Option name */
1050 BOOL (*fn)(struct messaging_context *msg_ctx,
1051 const struct server_id pid,
1052 const int argc, const char **argv);
1053 const char *help; /* Short help text */
1055 { "debug", do_debug, "Set debuglevel" },
1056 { "force-election", do_election,
1057 "Force a browse election" },
1058 { "ping", do_ping, "Elicit a response" },
1059 { "profile", do_profile, "" },
1060 { "inject", do_inject_fault,
1061 "Inject a fatal signal into a running smbd"},
1062 { "stacktrace", do_daemon_stack_trace,
1063 "Display a stack trace of a daemon" },
1064 { "profilelevel", do_profilelevel, "" },
1065 { "debuglevel", do_debuglevel, "Display current debuglevels" },
1066 { "printnotify", do_printnotify, "Send a print notify message" },
1067 { "close-share", do_closeshare, "Forcibly disconnect a share" },
1068 { "lockretry", do_lockretry, "Force a blocking lock retry" },
1069 { "brl-revalidate", do_brl_revalidate, "Revalidate all brl entries" },
1070 { "samsync", do_samsync, "Initiate SAM synchronisation" },
1071 { "samrepl", do_samrepl, "Initiate SAM replication" },
1072 { "pool-usage", do_poolusage, "Display talloc memory usage" },
1073 { "dmalloc-mark", do_dmalloc_mark, "" },
1074 { "dmalloc-log-changed", do_dmalloc_changed, "" },
1075 { "shutdown", do_shutdown, "Shut down daemon" },
1076 { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
1077 { "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
1078 { "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
1079 { "online", do_winbind_online, "Ask winbind to go into online state"},
1080 { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
1081 { "onlinestatus", do_winbind_onlinestatus, "Request winbind online status"},
1082 { "noop", do_noop, "Do nothing" },
1086 /* Display usage information */
1088 static void usage(poptContext pc)
1092 poptPrintHelp(pc, stderr, 0);
1094 fprintf(stderr, "\n");
1095 fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1098 fprintf(stderr, "\n");
1099 fprintf(stderr, "<message-type> is one of:\n");
1101 for (i = 0; msg_types[i].name; i++)
1102 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name,
1105 fprintf(stderr, "\n");
1110 /* Return the pid number for a string destination */
1112 static struct server_id parse_dest(const char *dest)
1114 struct server_id result = {-1};
1117 /* Zero is a special return value for broadcast smbd */
1119 if (strequal(dest, "smbd")) {
1120 return interpret_pid("0");
1123 /* Try self - useful for testing */
1125 if (strequal(dest, "self")) {
1126 return pid_to_procid(sys_getpid());
1129 /* Fix winbind typo. */
1130 if (strequal(dest, "winbind")) {
1135 if (!(strequal(dest, "winbindd") || strequal(dest, "nmbd"))) {
1136 /* Check for numeric pid number */
1138 result = interpret_pid(dest);
1140 /* Zero isn't valid if not smbd. */
1141 if (result.pid && procid_valid(&result)) {
1146 /* Look up other destinations in pidfile directory */
1148 if ((pid = pidfile_pid(dest)) != 0) {
1149 return pid_to_procid(pid);
1152 fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1157 /* Execute smbcontrol command */
1159 static BOOL do_command(struct messaging_context *msg_ctx,
1160 int argc, const char **argv)
1162 const char *dest = argv[0], *command = argv[1];
1163 struct server_id pid;
1166 /* Check destination */
1168 pid = parse_dest(dest);
1169 if (!procid_valid(&pid)) {
1175 for (i = 0; msg_types[i].name; i++) {
1176 if (strequal(command, msg_types[i].name))
1177 return msg_types[i].fn(msg_ctx, pid,
1178 argc - 1, argv + 1);
1181 fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1186 static void smbcontrol_help(poptContext pc,
1187 enum poptCallbackReason preason,
1188 struct poptOption * poption,
1192 if (poption->shortName != '?') {
1193 poptPrintUsage(pc, stdout, 0);
1201 struct poptOption help_options[] = {
1202 { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1204 { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1205 { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1211 int main(int argc, const char **argv)
1215 struct event_context *evt_ctx;
1216 struct messaging_context *msg_ctx;
1218 static struct poptOption long_options[] = {
1220 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1221 0, "Help options:", NULL },
1222 { "timeout", 't', POPT_ARG_INT, &timeout, 't',
1223 "Set timeout value in seconds", "TIMEOUT" },
1231 setup_logging(argv[0],True);
1233 /* Parse command line arguments using popt */
1235 pc = poptGetContext(
1236 "smbcontrol", argc, (const char **)argv, long_options, 0);
1238 poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1244 while ((opt = poptGetNextOpt(pc)) != -1) {
1246 case 't': /* --timeout */
1249 fprintf(stderr, "Invalid option\n");
1250 poptPrintHelp(pc, stderr, 0);
1255 /* We should now have the remaining command line arguments in
1256 argv. The argc parameter should have been decremented to the
1257 correct value in the above switch statement. */
1259 argv = (const char **)poptGetArgs(pc);
1261 while (argv[argc] != NULL) {
1268 lp_load(dyn_CONFIGFILE,False,False,False,True);
1270 /* Need to invert sense of return code -- samba
1271 * routines mostly return True==1 for success, but
1274 if (!(evt_ctx = event_context_init(NULL)) ||
1275 !(msg_ctx = messaging_init(NULL, server_id_self(), evt_ctx))) {
1276 fprintf(stderr, "could not init messaging context\n");
1280 return !do_command(msg_ctx, argc, argv);