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 /* Wait for one or more reply messages */
70 static void wait_replies(struct messaging_context *msg_ctx,
71 BOOL multiple_replies)
73 time_t start_time = time(NULL);
75 /* Wait around a bit. This is pretty disgusting - we have to
76 busy-wait here as there is no nicer way to do it. */
79 message_dispatch(msg_ctx);
80 event_loop_once(messaging_event_context(msg_ctx));
81 if (num_replies > 0 && !multiple_replies)
84 } while (timeout - (time(NULL) - start_time) > 0);
87 /* Message handler callback that displays the PID and a string on stdout */
89 static void print_pid_string_cb(struct messaging_context *msg,
95 printf("PID %u: %.*s", (unsigned int)procid_to_pid(&pid),
96 (int)data->length, (const char *)data->data);
100 /* Message handler callback that displays a string on stdout */
102 static void print_string_cb(struct messaging_context *msg,
105 struct server_id pid,
108 printf("%.*s", (int)data->length, (const char *)data->data);
112 /* Send no message. Useful for testing. */
114 static BOOL do_noop(struct messaging_context *msg_ctx,
115 const struct server_id pid,
116 const int argc, const char **argv)
119 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
123 /* Move along, nothing to see here */
128 /* Send a debug string */
130 static BOOL do_debug(struct messaging_context *msg_ctx,
131 const struct server_id pid,
132 const int argc, const char **argv)
135 fprintf(stderr, "Usage: smbcontrol <dest> debug "
140 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
141 strlen(argv[1]) + 1);
144 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
146 /* Return the name of a process given it's PID. This will only work on Linux,
147 * but that's probably moot since this whole stack tracing implementatino is
148 * Linux-specific anyway.
150 static const char * procname(pid_t pid, char * buf, size_t bufsz)
155 snprintf(path, sizeof(path), "/proc/%llu/cmdline",
156 (unsigned long long)pid);
157 if ((fp = fopen(path, "r")) == NULL) {
161 fgets(buf, bufsz, fp);
167 static void print_stack_trace(pid_t pid, int * count)
170 unw_addr_space_t aspace = NULL;
179 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
181 "Failed to attach to process %llu: %s\n",
182 (unsigned long long)pid, strerror(errno));
186 /* Wait until the attach is complete. */
187 waitpid(pid, NULL, 0);
189 if (((pinfo = _UPT_create(pid)) == NULL) ||
190 ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
191 /* Probably out of memory. */
193 "Unable to initialize stack unwind for process %llu\n",
194 (unsigned long long)pid);
198 if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
200 "Unable to unwind stack for process %llu: %s\n",
201 (unsigned long long)pid, unw_strerror(ret));
209 if (procname(pid, nbuf, sizeof(nbuf))) {
210 printf("Stack trace for process %llu (%s):\n",
211 (unsigned long long)pid, nbuf);
213 printf("Stack trace for process %llu:\n",
214 (unsigned long long)pid);
217 while (unw_step(&cursor) > 0) {
219 unw_get_reg(&cursor, UNW_REG_IP, &ip);
220 unw_get_reg(&cursor, UNW_REG_SP, &sp);
222 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
223 if (ret != 0 && ret != -UNW_ENOMEM) {
224 snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
226 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
227 nbuf, (long long)off, (long long)ip,
235 unw_destroy_addr_space(aspace);
242 ptrace(PTRACE_DETACH, pid, NULL, NULL);
245 static int stack_trace_connection(struct db_record *rec,
246 const struct connections_key *key,
247 const struct connections_data *crec,
250 print_stack_trace(procid_to_pid(&conn->pid), (int *)priv);
255 static BOOL do_daemon_stack_trace(struct messaging_context *msg_ctx,
256 const struct server_id pid,
257 const int argc, const char **argv)
260 "Daemon stack tracing is not supported on this platform\n");
267 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
271 dest = procid_to_pid(&pid);
274 /* It would be nice to be able to make sure that this PID is
275 * the PID of a smbd/winbind/nmbd process, not some random PID
276 * the user liked the look of. It doesn't seem like it's worth
277 * the effort at the moment, however.
279 print_stack_trace(dest, &count);
281 connections_forall(stack_trace_connection, &count);
287 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
289 static BOOL do_daemon_stack_trace(struct messaging_context *msg_ctx,
290 const struct server_id pid,
291 const int argc, const char **argv)
294 "Daemon stack tracing is not supported on this platform\n");
298 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
300 /* Inject a fault (fatal signal) into a running smbd */
302 static BOOL do_inject_fault(struct messaging_context *msg_ctx,
303 const struct server_id pid,
304 const int argc, const char **argv)
307 fprintf(stderr, "Usage: smbcontrol <dest> inject "
308 "<bus|hup|term|internal|segv>\n");
313 fprintf(stderr, "Fault injection is only available in "
314 "developer builds\n");
316 #else /* DEVELOPER */
320 if (strcmp(argv[1], "bus") == 0) {
322 } else if (strcmp(argv[1], "hup") == 0) {
324 } else if (strcmp(argv[1], "term") == 0) {
326 } else if (strcmp(argv[1], "segv") == 0) {
328 } else if (strcmp(argv[1], "internal") == 0) {
329 /* Force an internal error, ie. an unclean exit. */
332 fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
336 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
339 #endif /* DEVELOPER */
342 /* Force a browser election */
344 static BOOL do_election(struct messaging_context *msg_ctx,
345 const struct server_id pid,
346 const int argc, const char **argv)
349 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
353 return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
356 /* Ping a samba daemon process */
358 static void pong_cb(struct messaging_context *msg,
361 struct server_id pid,
364 char *src_string = procid_str(NULL, &pid);
365 printf("PONG from pid %s\n", src_string);
366 TALLOC_FREE(src_string);
370 static BOOL do_ping(struct messaging_context *msg_ctx,
371 const struct server_id pid,
372 const int argc, const char **argv)
375 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
379 /* Send a message and register our interest in a reply */
381 if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
384 messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
386 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
388 /* No replies were received within the timeout period */
390 if (num_replies == 0)
391 printf("No replies received\n");
393 messaging_deregister(msg_ctx, MSG_PONG, NULL);
398 /* Set profiling options */
400 static BOOL do_profile(struct messaging_context *msg_ctx,
401 const struct server_id pid,
402 const int argc, const char **argv)
407 fprintf(stderr, "Usage: smbcontrol <dest> profile "
408 "<off|count|on|flush>\n");
412 if (strcmp(argv[1], "off") == 0) {
414 } else if (strcmp(argv[1], "count") == 0) {
416 } else if (strcmp(argv[1], "on") == 0) {
418 } else if (strcmp(argv[1], "flush") == 0) {
421 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
425 return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
428 /* Return the profiling level */
430 static void profilelevel_cb(struct messaging_context *msg_ctx,
433 struct server_id pid,
441 if (data->length != sizeof(int)) {
442 fprintf(stderr, "invalid message length %ld returned\n",
443 (unsigned long)data->length);
447 memcpy(&level, data->data, sizeof(int));
460 s = "count and time";
467 printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
470 static void profilelevel_rqst(struct messaging_context *msg_ctx,
473 struct server_id pid,
478 /* Send back a dummy reply */
480 send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
483 static BOOL do_profilelevel(struct messaging_context *msg_ctx,
484 const struct server_id pid,
485 const int argc, const char **argv)
488 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
492 /* Send a message and register our interest in a reply */
494 if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
497 messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
498 messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
501 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
503 /* No replies were received within the timeout period */
505 if (num_replies == 0)
506 printf("No replies received\n");
508 messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
513 /* Display debug level settings */
515 static BOOL do_debuglevel(struct messaging_context *msg_ctx,
516 const struct server_id pid,
517 const int argc, const char **argv)
520 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
524 /* Send a message and register our interest in a reply */
526 if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
529 messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
531 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
533 /* No replies were received within the timeout period */
535 if (num_replies == 0)
536 printf("No replies received\n");
538 messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
543 /* Send a print notify message */
545 static BOOL do_printnotify(struct messaging_context *msg_ctx,
546 const struct server_id pid,
547 const int argc, const char **argv)
551 /* Check for subcommand */
554 fprintf(stderr, "Must specify subcommand:\n");
555 fprintf(stderr, "\tqueuepause <printername>\n");
556 fprintf(stderr, "\tqueueresume <printername>\n");
557 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
558 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
559 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
560 fprintf(stderr, "\tprinter <printername> <comment|port|"
561 "driver> <value>\n");
568 if (strcmp(cmd, "queuepause") == 0) {
571 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
572 " queuepause <printername>\n");
576 notify_printer_status_byname(argv[2], PRINTER_STATUS_PAUSED);
580 } else if (strcmp(cmd, "queueresume") == 0) {
583 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
584 " queuereume <printername>\n");
588 notify_printer_status_byname(argv[2], PRINTER_STATUS_OK);
592 } else if (strcmp(cmd, "jobpause") == 0) {
596 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
597 " jobpause <printername> <unix-jobid>\n");
601 jobid = atoi(argv[3]);
603 notify_job_status_byname(
604 argv[2], jobid, JOB_STATUS_PAUSED,
605 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
609 } else if (strcmp(cmd, "jobresume") == 0) {
613 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
614 " jobpause <printername> <unix-jobid>\n");
618 jobid = atoi(argv[3]);
620 notify_job_status_byname(
621 argv[2], jobid, JOB_STATUS_QUEUED,
622 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
626 } else if (strcmp(cmd, "jobdelete") == 0) {
630 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
631 " jobpause <printername> <unix-jobid>\n");
635 jobid = atoi(argv[3]);
637 notify_job_status_byname(
638 argv[2], jobid, JOB_STATUS_DELETING,
639 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
641 notify_job_status_byname(
642 argv[2], jobid, JOB_STATUS_DELETING|
644 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
648 } else if (strcmp(cmd, "printer") == 0) {
652 fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
653 "printer <printername> <comment|port|driver> "
658 if (strcmp(argv[3], "comment") == 0) {
659 attribute = PRINTER_NOTIFY_COMMENT;
660 } else if (strcmp(argv[3], "port") == 0) {
661 attribute = PRINTER_NOTIFY_PORT_NAME;
662 } else if (strcmp(argv[3], "driver") == 0) {
663 attribute = PRINTER_NOTIFY_DRIVER_NAME;
665 fprintf(stderr, "Invalid printer command '%s'\n",
670 notify_printer_byname(argv[2], attribute,
671 CONST_DISCARD(char *, argv[4]));
676 fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
680 print_notify_send_messages(msg_ctx, 0);
686 static BOOL do_closeshare(struct messaging_context *msg_ctx,
687 const struct server_id pid,
688 const int argc, const char **argv)
691 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
696 return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
697 strlen(argv[1]) + 1);
700 /* force a blocking lock retry */
702 static BOOL do_lockretry(struct messaging_context *msg_ctx,
703 const struct server_id pid,
704 const int argc, const char **argv)
707 fprintf(stderr, "Usage: smbcontrol <dest> lockretry\n");
711 return send_message(msg_ctx, pid, MSG_SMB_UNLOCK, NULL, 0);
714 /* force a validation of all brl entries, including re-sends. */
716 static BOOL do_brl_revalidate(struct messaging_context *msg_ctx,
717 const struct server_id pid,
718 const int argc, const char **argv)
721 fprintf(stderr, "Usage: smbcontrol <dest> brl-revalidate\n");
725 return send_message(msg_ctx, pid, MSG_SMB_BRL_VALIDATE, NULL, 0);
728 /* Force a SAM synchronisation */
730 static BOOL do_samsync(struct messaging_context *msg_ctx,
731 const struct server_id pid,
732 const int argc, const char **argv)
735 fprintf(stderr, "Usage: smbcontrol <dest> samsync\n");
739 return send_message(msg_ctx, pid, MSG_SMB_SAM_SYNC, NULL, 0);
742 /* Force a SAM replication */
744 static BOOL do_samrepl(struct messaging_context *msg_ctx,
745 const struct server_id pid,
746 const int argc, const char **argv)
749 fprintf(stderr, "Usage: smbcontrol <dest> samrepl\n");
753 return send_message(msg_ctx, pid, MSG_SMB_SAM_REPL, NULL, 0);
756 /* Display talloc pool usage */
758 static BOOL do_poolusage(struct messaging_context *msg_ctx,
759 const struct server_id pid,
760 const int argc, const char **argv)
763 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
767 messaging_register(msg_ctx, NULL, MSG_POOL_USAGE, print_string_cb);
769 /* Send a message and register our interest in a reply */
771 if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0))
774 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
776 /* No replies were received within the timeout period */
778 if (num_replies == 0)
779 printf("No replies received\n");
781 messaging_deregister(msg_ctx, MSG_POOL_USAGE, NULL);
786 /* Perform a dmalloc mark */
788 static BOOL do_dmalloc_mark(struct messaging_context *msg_ctx,
789 const struct server_id pid,
790 const int argc, const char **argv)
793 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
797 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
800 /* Perform a dmalloc changed */
802 static BOOL do_dmalloc_changed(struct messaging_context *msg_ctx,
803 const struct server_id pid,
804 const int argc, const char **argv)
807 fprintf(stderr, "Usage: smbcontrol <dest> "
808 "dmalloc-log-changed\n");
812 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
816 /* Shutdown a server process */
818 static BOOL do_shutdown(struct messaging_context *msg_ctx,
819 const struct server_id pid,
820 const int argc, const char **argv)
823 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
827 return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
830 /* Notify a driver upgrade */
832 static BOOL do_drvupgrade(struct messaging_context *msg_ctx,
833 const struct server_id pid,
834 const int argc, const char **argv)
837 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
842 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
843 strlen(argv[1]) + 1);
846 static BOOL do_winbind_online(struct messaging_context *msg_ctx,
847 const struct server_id pid,
848 const int argc, const char **argv)
853 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
857 if (!lp_winbind_offline_logon()) {
858 fprintf(stderr, "The parameter \"winbind offline logon\" must "
859 "be set in the [global] section of smb.conf for this "
860 "command to be allowed.\n");
864 /* Remove the entry in the winbindd_cache tdb to tell a later
865 starting winbindd that we're online. */
867 tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
869 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
870 lock_path("winbindd_cache.tdb"));
874 tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
877 return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
880 static BOOL do_winbind_offline(struct messaging_context *msg_ctx,
881 const struct server_id pid,
882 const int argc, const char **argv)
889 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
893 if (!lp_winbind_offline_logon()) {
894 fprintf(stderr, "The parameter \"winbind offline logon\" must "
895 "be set in the [global] section of smb.conf for this "
896 "command to be allowed.\n");
900 /* Create an entry in the winbindd_cache tdb to tell a later
901 starting winbindd that we're offline. We may actually create
904 tdb = tdb_open_log(lock_path("winbindd_cache.tdb"),
905 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
906 TDB_DEFAULT /* TDB_CLEAR_IF_FIRST */, O_RDWR|O_CREAT, 0600);
909 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
910 lock_path("winbindd_cache.tdb"));
914 /* There's a potential race condition that if a child
915 winbindd detects a domain is online at the same time
916 we're trying to tell it to go offline that it might
917 delete the record we add between us adding it and
918 sending the message. Minimize this by retrying up to
921 for (retry = 0; retry < 5; retry++) {
927 SIVAL(buf, 0, time(NULL));
931 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
933 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
936 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
937 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
939 if (!d.dptr || d.dsize != 4) {
941 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
952 static BOOL do_winbind_onlinestatus(struct messaging_context *msg_ctx,
953 const struct server_id pid,
954 const int argc, const char **argv)
956 struct server_id myid;
958 myid = pid_to_procid(sys_getpid());
961 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
965 messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
966 print_pid_string_cb);
968 if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, &myid,
972 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
974 /* No replies were received within the timeout period */
976 if (num_replies == 0)
977 printf("No replies received\n");
979 messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
984 static BOOL do_dump_event_list(struct messaging_context *msg_ctx,
985 const struct server_id pid,
986 const int argc, const char **argv)
988 struct server_id myid;
990 myid = pid_to_procid(sys_getpid());
993 fprintf(stderr, "Usage: smbcontrol <dest> dump-event-list\n");
997 return send_message(msg_ctx, pid, MSG_DUMP_EVENT_LIST, NULL, 0);
1001 static BOOL do_reload_config(struct messaging_context *msg_ctx,
1002 const struct server_id pid,
1003 const int argc, const char **argv)
1006 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1010 return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1013 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1016 memset( (char *)n, '\0', sizeof(struct nmb_name) );
1017 fstrcpy(unix_name, name);
1018 strupper_m(unix_name);
1019 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1020 n->name_type = (unsigned int)type & 0xFF;
1021 push_ascii(n->scope, global_scope(), 64, STR_TERMINATE);
1024 static BOOL do_nodestatus(struct messaging_context *msg_ctx,
1025 const struct server_id pid,
1026 const int argc, const char **argv)
1028 struct packet_struct p;
1031 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1037 p.ip = *interpret_addr2(argv[1]);
1039 p.packet_type = NMB_PACKET;
1041 p.packet.nmb.header.name_trn_id = 10;
1042 p.packet.nmb.header.opcode = 0;
1043 p.packet.nmb.header.response = False;
1044 p.packet.nmb.header.nm_flags.bcast = False;
1045 p.packet.nmb.header.nm_flags.recursion_available = False;
1046 p.packet.nmb.header.nm_flags.recursion_desired = False;
1047 p.packet.nmb.header.nm_flags.trunc = False;
1048 p.packet.nmb.header.nm_flags.authoritative = False;
1049 p.packet.nmb.header.rcode = 0;
1050 p.packet.nmb.header.qdcount = 1;
1051 p.packet.nmb.header.ancount = 0;
1052 p.packet.nmb.header.nscount = 0;
1053 p.packet.nmb.header.arcount = 0;
1054 my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1055 p.packet.nmb.question.question_type = 0x21;
1056 p.packet.nmb.question.question_class = 0x1;
1058 return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1061 /* A list of message type supported */
1063 static const struct {
1064 const char *name; /* Option name */
1065 BOOL (*fn)(struct messaging_context *msg_ctx,
1066 const struct server_id pid,
1067 const int argc, const char **argv);
1068 const char *help; /* Short help text */
1070 { "debug", do_debug, "Set debuglevel" },
1071 { "force-election", do_election,
1072 "Force a browse election" },
1073 { "ping", do_ping, "Elicit a response" },
1074 { "profile", do_profile, "" },
1075 { "inject", do_inject_fault,
1076 "Inject a fatal signal into a running smbd"},
1077 { "stacktrace", do_daemon_stack_trace,
1078 "Display a stack trace of a daemon" },
1079 { "profilelevel", do_profilelevel, "" },
1080 { "debuglevel", do_debuglevel, "Display current debuglevels" },
1081 { "printnotify", do_printnotify, "Send a print notify message" },
1082 { "close-share", do_closeshare, "Forcibly disconnect a share" },
1083 { "lockretry", do_lockretry, "Force a blocking lock retry" },
1084 { "brl-revalidate", do_brl_revalidate, "Revalidate all brl entries" },
1085 { "samsync", do_samsync, "Initiate SAM synchronisation" },
1086 { "samrepl", do_samrepl, "Initiate SAM replication" },
1087 { "pool-usage", do_poolusage, "Display talloc memory usage" },
1088 { "dmalloc-mark", do_dmalloc_mark, "" },
1089 { "dmalloc-log-changed", do_dmalloc_changed, "" },
1090 { "shutdown", do_shutdown, "Shut down daemon" },
1091 { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
1092 { "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
1093 { "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
1094 { "online", do_winbind_online, "Ask winbind to go into online state"},
1095 { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
1096 { "onlinestatus", do_winbind_onlinestatus, "Request winbind online status"},
1097 { "dump-event-list", do_dump_event_list, "Dump event list"},
1098 { "noop", do_noop, "Do nothing" },
1102 /* Display usage information */
1104 static void usage(poptContext pc)
1108 poptPrintHelp(pc, stderr, 0);
1110 fprintf(stderr, "\n");
1111 fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1114 fprintf(stderr, "\n");
1115 fprintf(stderr, "<message-type> is one of:\n");
1117 for (i = 0; msg_types[i].name; i++)
1118 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name,
1121 fprintf(stderr, "\n");
1126 /* Return the pid number for a string destination */
1128 static struct server_id parse_dest(const char *dest)
1130 struct server_id result = {-1};
1133 /* Zero is a special return value for broadcast smbd */
1135 if (strequal(dest, "smbd")) {
1136 return interpret_pid("0");
1139 /* Try self - useful for testing */
1141 if (strequal(dest, "self")) {
1142 return pid_to_procid(sys_getpid());
1145 /* Fix winbind typo. */
1146 if (strequal(dest, "winbind")) {
1151 if (!(strequal(dest, "winbindd") || strequal(dest, "nmbd"))) {
1152 /* Check for numeric pid number */
1154 result = interpret_pid(dest);
1156 /* Zero isn't valid if not smbd. */
1157 if (result.pid && procid_valid(&result)) {
1162 /* Look up other destinations in pidfile directory */
1164 if ((pid = pidfile_pid(dest)) != 0) {
1165 return pid_to_procid(pid);
1168 fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1173 /* Execute smbcontrol command */
1175 static BOOL do_command(struct messaging_context *msg_ctx,
1176 int argc, const char **argv)
1178 const char *dest = argv[0], *command = argv[1];
1179 struct server_id pid;
1182 /* Check destination */
1184 pid = parse_dest(dest);
1185 if (!procid_valid(&pid)) {
1191 for (i = 0; msg_types[i].name; i++) {
1192 if (strequal(command, msg_types[i].name))
1193 return msg_types[i].fn(msg_ctx, pid,
1194 argc - 1, argv + 1);
1197 fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1202 static void smbcontrol_help(poptContext pc,
1203 enum poptCallbackReason preason,
1204 struct poptOption * poption,
1208 if (poption->shortName != '?') {
1209 poptPrintUsage(pc, stdout, 0);
1217 struct poptOption help_options[] = {
1218 { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1220 { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1221 { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1227 int main(int argc, const char **argv)
1231 struct event_context *evt_ctx;
1232 struct messaging_context *msg_ctx;
1234 static struct poptOption long_options[] = {
1236 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1237 0, "Help options:", NULL },
1238 { "timeout", 't', POPT_ARG_INT, &timeout, 't',
1239 "Set timeout value in seconds", "TIMEOUT" },
1247 setup_logging(argv[0],True);
1249 /* Parse command line arguments using popt */
1251 pc = poptGetContext(
1252 "smbcontrol", argc, (const char **)argv, long_options, 0);
1254 poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1260 while ((opt = poptGetNextOpt(pc)) != -1) {
1262 case 't': /* --timeout */
1265 fprintf(stderr, "Invalid option\n");
1266 poptPrintHelp(pc, stderr, 0);
1271 /* We should now have the remaining command line arguments in
1272 argv. The argc parameter should have been decremented to the
1273 correct value in the above switch statement. */
1275 argv = (const char **)poptGetArgs(pc);
1277 while (argv[argc] != NULL) {
1284 lp_load(dyn_CONFIGFILE,False,False,False,True);
1286 /* Need to invert sense of return code -- samba
1287 * routines mostly return True==1 for success, but
1290 if (!(evt_ctx = event_context_init(NULL)) ||
1291 !(msg_ctx = messaging_init(NULL, server_id_self(), evt_ctx))) {
1292 fprintf(stderr, "could not init messaging context\n");
1296 return !do_command(msg_ctx, argc, argv);