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 timeout_handler(struct event_context *event_ctx,
69 struct timed_event *te,
70 const struct timeval *now,
73 BOOL *timed_out = (BOOL *)private_data;
78 /* Wait for one or more reply messages */
80 static void wait_replies(struct messaging_context *msg_ctx,
81 BOOL multiple_replies)
83 struct timed_event *te;
84 BOOL timed_out = False;
86 if (!(te = event_add_timed(messaging_event_context(msg_ctx), NULL,
87 timeval_current_ofs(timeout, 0),
89 timeout_handler, (void *)&timed_out))) {
90 DEBUG(0, ("event_add_timed failed\n"));
95 message_dispatch(msg_ctx);
96 if (num_replies > 0 && !multiple_replies)
98 event_loop_once(messaging_event_context(msg_ctx));
102 /* Message handler callback that displays the PID and a string on stdout */
104 static void print_pid_string_cb(struct messaging_context *msg,
107 struct server_id pid,
110 printf("PID %u: %.*s", (unsigned int)procid_to_pid(&pid),
111 (int)data->length, (const char *)data->data);
115 /* Message handler callback that displays a string on stdout */
117 static void print_string_cb(struct messaging_context *msg,
120 struct server_id pid,
123 printf("%.*s", (int)data->length, (const char *)data->data);
127 /* Send no message. Useful for testing. */
129 static BOOL do_noop(struct messaging_context *msg_ctx,
130 const struct server_id pid,
131 const int argc, const char **argv)
134 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
138 /* Move along, nothing to see here */
143 /* Send a debug string */
145 static BOOL do_debug(struct messaging_context *msg_ctx,
146 const struct server_id pid,
147 const int argc, const char **argv)
150 fprintf(stderr, "Usage: smbcontrol <dest> debug "
155 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
156 strlen(argv[1]) + 1);
159 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
161 /* Return the name of a process given it's PID. This will only work on Linux,
162 * but that's probably moot since this whole stack tracing implementatino is
163 * Linux-specific anyway.
165 static const char * procname(pid_t pid, char * buf, size_t bufsz)
170 snprintf(path, sizeof(path), "/proc/%llu/cmdline",
171 (unsigned long long)pid);
172 if ((fp = fopen(path, "r")) == NULL) {
176 fgets(buf, bufsz, fp);
182 static void print_stack_trace(pid_t pid, int * count)
185 unw_addr_space_t aspace = NULL;
194 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
196 "Failed to attach to process %llu: %s\n",
197 (unsigned long long)pid, strerror(errno));
201 /* Wait until the attach is complete. */
202 waitpid(pid, NULL, 0);
204 if (((pinfo = _UPT_create(pid)) == NULL) ||
205 ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
206 /* Probably out of memory. */
208 "Unable to initialize stack unwind for process %llu\n",
209 (unsigned long long)pid);
213 if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
215 "Unable to unwind stack for process %llu: %s\n",
216 (unsigned long long)pid, unw_strerror(ret));
224 if (procname(pid, nbuf, sizeof(nbuf))) {
225 printf("Stack trace for process %llu (%s):\n",
226 (unsigned long long)pid, nbuf);
228 printf("Stack trace for process %llu:\n",
229 (unsigned long long)pid);
232 while (unw_step(&cursor) > 0) {
234 unw_get_reg(&cursor, UNW_REG_IP, &ip);
235 unw_get_reg(&cursor, UNW_REG_SP, &sp);
237 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
238 if (ret != 0 && ret != -UNW_ENOMEM) {
239 snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
241 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
242 nbuf, (long long)off, (long long)ip,
250 unw_destroy_addr_space(aspace);
257 ptrace(PTRACE_DETACH, pid, NULL, NULL);
260 static int stack_trace_connection(struct db_record *rec,
261 const struct connections_key *key,
262 const struct connections_data *crec,
265 print_stack_trace(procid_to_pid(&crec->pid), (int *)priv);
270 static BOOL do_daemon_stack_trace(struct messaging_context *msg_ctx,
271 const struct server_id pid,
272 const int argc, const char **argv)
275 "Daemon stack tracing is not supported on this platform\n");
282 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
286 dest = procid_to_pid(&pid);
289 /* It would be nice to be able to make sure that this PID is
290 * the PID of a smbd/winbind/nmbd process, not some random PID
291 * the user liked the look of. It doesn't seem like it's worth
292 * the effort at the moment, however.
294 print_stack_trace(dest, &count);
296 connections_forall(stack_trace_connection, &count);
302 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
304 static BOOL do_daemon_stack_trace(struct messaging_context *msg_ctx,
305 const struct server_id pid,
306 const int argc, const char **argv)
309 "Daemon stack tracing is not supported on this platform\n");
313 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
315 /* Inject a fault (fatal signal) into a running smbd */
317 static BOOL do_inject_fault(struct messaging_context *msg_ctx,
318 const struct server_id pid,
319 const int argc, const char **argv)
322 fprintf(stderr, "Usage: smbcontrol <dest> inject "
323 "<bus|hup|term|internal|segv>\n");
328 fprintf(stderr, "Fault injection is only available in "
329 "developer builds\n");
331 #else /* DEVELOPER */
335 if (strcmp(argv[1], "bus") == 0) {
337 } else if (strcmp(argv[1], "hup") == 0) {
339 } else if (strcmp(argv[1], "term") == 0) {
341 } else if (strcmp(argv[1], "segv") == 0) {
343 } else if (strcmp(argv[1], "internal") == 0) {
344 /* Force an internal error, ie. an unclean exit. */
347 fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
351 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
354 #endif /* DEVELOPER */
357 /* Force a browser election */
359 static BOOL do_election(struct messaging_context *msg_ctx,
360 const struct server_id pid,
361 const int argc, const char **argv)
364 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
368 return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
371 /* Ping a samba daemon process */
373 static void pong_cb(struct messaging_context *msg,
376 struct server_id pid,
379 char *src_string = procid_str(NULL, &pid);
380 printf("PONG from pid %s\n", src_string);
381 TALLOC_FREE(src_string);
385 static BOOL do_ping(struct messaging_context *msg_ctx,
386 const struct server_id pid,
387 const int argc, const char **argv)
390 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
394 /* Send a message and register our interest in a reply */
396 if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
399 messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
401 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
403 /* No replies were received within the timeout period */
405 if (num_replies == 0)
406 printf("No replies received\n");
408 messaging_deregister(msg_ctx, MSG_PONG, NULL);
413 /* Set profiling options */
415 static BOOL do_profile(struct messaging_context *msg_ctx,
416 const struct server_id pid,
417 const int argc, const char **argv)
422 fprintf(stderr, "Usage: smbcontrol <dest> profile "
423 "<off|count|on|flush>\n");
427 if (strcmp(argv[1], "off") == 0) {
429 } else if (strcmp(argv[1], "count") == 0) {
431 } else if (strcmp(argv[1], "on") == 0) {
433 } else if (strcmp(argv[1], "flush") == 0) {
436 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
440 return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
443 /* Return the profiling level */
445 static void profilelevel_cb(struct messaging_context *msg_ctx,
448 struct server_id pid,
456 if (data->length != sizeof(int)) {
457 fprintf(stderr, "invalid message length %ld returned\n",
458 (unsigned long)data->length);
462 memcpy(&level, data->data, sizeof(int));
475 s = "count and time";
482 printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
485 static void profilelevel_rqst(struct messaging_context *msg_ctx,
488 struct server_id pid,
493 /* Send back a dummy reply */
495 send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
498 static BOOL do_profilelevel(struct messaging_context *msg_ctx,
499 const struct server_id pid,
500 const int argc, const char **argv)
503 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
507 /* Send a message and register our interest in a reply */
509 if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
512 messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
513 messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
516 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
518 /* No replies were received within the timeout period */
520 if (num_replies == 0)
521 printf("No replies received\n");
523 messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
528 /* Display debug level settings */
530 static BOOL do_debuglevel(struct messaging_context *msg_ctx,
531 const struct server_id pid,
532 const int argc, const char **argv)
535 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
539 /* Send a message and register our interest in a reply */
541 if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
544 messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
546 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
548 /* No replies were received within the timeout period */
550 if (num_replies == 0)
551 printf("No replies received\n");
553 messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
558 /* Send a print notify message */
560 static BOOL do_printnotify(struct messaging_context *msg_ctx,
561 const struct server_id pid,
562 const int argc, const char **argv)
566 /* Check for subcommand */
569 fprintf(stderr, "Must specify subcommand:\n");
570 fprintf(stderr, "\tqueuepause <printername>\n");
571 fprintf(stderr, "\tqueueresume <printername>\n");
572 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
573 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
574 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
575 fprintf(stderr, "\tprinter <printername> <comment|port|"
576 "driver> <value>\n");
583 if (strcmp(cmd, "queuepause") == 0) {
586 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
587 " queuepause <printername>\n");
591 notify_printer_status_byname(argv[2], PRINTER_STATUS_PAUSED);
595 } else if (strcmp(cmd, "queueresume") == 0) {
598 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
599 " queuereume <printername>\n");
603 notify_printer_status_byname(argv[2], PRINTER_STATUS_OK);
607 } else if (strcmp(cmd, "jobpause") == 0) {
611 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
612 " jobpause <printername> <unix-jobid>\n");
616 jobid = atoi(argv[3]);
618 notify_job_status_byname(
619 argv[2], jobid, JOB_STATUS_PAUSED,
620 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
624 } else if (strcmp(cmd, "jobresume") == 0) {
628 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
629 " jobpause <printername> <unix-jobid>\n");
633 jobid = atoi(argv[3]);
635 notify_job_status_byname(
636 argv[2], jobid, JOB_STATUS_QUEUED,
637 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
641 } else if (strcmp(cmd, "jobdelete") == 0) {
645 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
646 " jobpause <printername> <unix-jobid>\n");
650 jobid = atoi(argv[3]);
652 notify_job_status_byname(
653 argv[2], jobid, JOB_STATUS_DELETING,
654 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
656 notify_job_status_byname(
657 argv[2], jobid, JOB_STATUS_DELETING|
659 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
663 } else if (strcmp(cmd, "printer") == 0) {
667 fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
668 "printer <printername> <comment|port|driver> "
673 if (strcmp(argv[3], "comment") == 0) {
674 attribute = PRINTER_NOTIFY_COMMENT;
675 } else if (strcmp(argv[3], "port") == 0) {
676 attribute = PRINTER_NOTIFY_PORT_NAME;
677 } else if (strcmp(argv[3], "driver") == 0) {
678 attribute = PRINTER_NOTIFY_DRIVER_NAME;
680 fprintf(stderr, "Invalid printer command '%s'\n",
685 notify_printer_byname(argv[2], attribute,
686 CONST_DISCARD(char *, argv[4]));
691 fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
695 print_notify_send_messages(msg_ctx, 0);
701 static BOOL do_closeshare(struct messaging_context *msg_ctx,
702 const struct server_id pid,
703 const int argc, const char **argv)
706 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
711 return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
712 strlen(argv[1]) + 1);
715 /* force a blocking lock retry */
717 static BOOL do_lockretry(struct messaging_context *msg_ctx,
718 const struct server_id pid,
719 const int argc, const char **argv)
722 fprintf(stderr, "Usage: smbcontrol <dest> lockretry\n");
726 return send_message(msg_ctx, pid, MSG_SMB_UNLOCK, NULL, 0);
729 /* force a validation of all brl entries, including re-sends. */
731 static BOOL do_brl_revalidate(struct messaging_context *msg_ctx,
732 const struct server_id pid,
733 const int argc, const char **argv)
736 fprintf(stderr, "Usage: smbcontrol <dest> brl-revalidate\n");
740 return send_message(msg_ctx, pid, MSG_SMB_BRL_VALIDATE, NULL, 0);
743 /* Force a SAM synchronisation */
745 static BOOL do_samsync(struct messaging_context *msg_ctx,
746 const struct server_id pid,
747 const int argc, const char **argv)
750 fprintf(stderr, "Usage: smbcontrol <dest> samsync\n");
754 return send_message(msg_ctx, pid, MSG_SMB_SAM_SYNC, NULL, 0);
757 /* Force a SAM replication */
759 static BOOL do_samrepl(struct messaging_context *msg_ctx,
760 const struct server_id pid,
761 const int argc, const char **argv)
764 fprintf(stderr, "Usage: smbcontrol <dest> samrepl\n");
768 return send_message(msg_ctx, pid, MSG_SMB_SAM_REPL, NULL, 0);
771 /* Display talloc pool usage */
773 static BOOL do_poolusage(struct messaging_context *msg_ctx,
774 const struct server_id pid,
775 const int argc, const char **argv)
778 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
782 messaging_register(msg_ctx, NULL, MSG_POOL_USAGE, print_string_cb);
784 /* Send a message and register our interest in a reply */
786 if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0))
789 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
791 /* No replies were received within the timeout period */
793 if (num_replies == 0)
794 printf("No replies received\n");
796 messaging_deregister(msg_ctx, MSG_POOL_USAGE, NULL);
801 /* Perform a dmalloc mark */
803 static BOOL do_dmalloc_mark(struct messaging_context *msg_ctx,
804 const struct server_id pid,
805 const int argc, const char **argv)
808 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
812 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
815 /* Perform a dmalloc changed */
817 static BOOL do_dmalloc_changed(struct messaging_context *msg_ctx,
818 const struct server_id pid,
819 const int argc, const char **argv)
822 fprintf(stderr, "Usage: smbcontrol <dest> "
823 "dmalloc-log-changed\n");
827 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
831 /* Shutdown a server process */
833 static BOOL do_shutdown(struct messaging_context *msg_ctx,
834 const struct server_id pid,
835 const int argc, const char **argv)
838 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
842 return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
845 /* Notify a driver upgrade */
847 static BOOL do_drvupgrade(struct messaging_context *msg_ctx,
848 const struct server_id pid,
849 const int argc, const char **argv)
852 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
857 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
858 strlen(argv[1]) + 1);
861 static BOOL do_winbind_online(struct messaging_context *msg_ctx,
862 const struct server_id pid,
863 const int argc, const char **argv)
868 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
872 if (!lp_winbind_offline_logon()) {
873 fprintf(stderr, "The parameter \"winbind offline logon\" must "
874 "be set in the [global] section of smb.conf for this "
875 "command to be allowed.\n");
879 /* Remove the entry in the winbindd_cache tdb to tell a later
880 starting winbindd that we're online. */
882 tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
884 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
885 lock_path("winbindd_cache.tdb"));
889 tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
892 return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
895 static BOOL do_winbind_offline(struct messaging_context *msg_ctx,
896 const struct server_id pid,
897 const int argc, const char **argv)
904 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
908 if (!lp_winbind_offline_logon()) {
909 fprintf(stderr, "The parameter \"winbind offline logon\" must "
910 "be set in the [global] section of smb.conf for this "
911 "command to be allowed.\n");
915 /* Create an entry in the winbindd_cache tdb to tell a later
916 starting winbindd that we're offline. We may actually create
919 tdb = tdb_open_log(lock_path("winbindd_cache.tdb"),
920 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
921 TDB_DEFAULT /* TDB_CLEAR_IF_FIRST */, O_RDWR|O_CREAT, 0600);
924 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
925 lock_path("winbindd_cache.tdb"));
929 /* There's a potential race condition that if a child
930 winbindd detects a domain is online at the same time
931 we're trying to tell it to go offline that it might
932 delete the record we add between us adding it and
933 sending the message. Minimize this by retrying up to
936 for (retry = 0; retry < 5; retry++) {
942 SIVAL(buf, 0, time(NULL));
946 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
948 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
951 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
952 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
954 if (!d.dptr || d.dsize != 4) {
956 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
967 static BOOL do_winbind_onlinestatus(struct messaging_context *msg_ctx,
968 const struct server_id pid,
969 const int argc, const char **argv)
971 struct server_id myid;
973 myid = pid_to_procid(sys_getpid());
976 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
980 messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
981 print_pid_string_cb);
983 if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, &myid,
987 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
989 /* No replies were received within the timeout period */
991 if (num_replies == 0)
992 printf("No replies received\n");
994 messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
999 static BOOL do_dump_event_list(struct messaging_context *msg_ctx,
1000 const struct server_id pid,
1001 const int argc, const char **argv)
1003 struct server_id myid;
1005 myid = pid_to_procid(sys_getpid());
1008 fprintf(stderr, "Usage: smbcontrol <dest> dump-event-list\n");
1012 return send_message(msg_ctx, pid, MSG_DUMP_EVENT_LIST, NULL, 0);
1016 static BOOL do_reload_config(struct messaging_context *msg_ctx,
1017 const struct server_id pid,
1018 const int argc, const char **argv)
1021 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1025 return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1028 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1031 memset( (char *)n, '\0', sizeof(struct nmb_name) );
1032 fstrcpy(unix_name, name);
1033 strupper_m(unix_name);
1034 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1035 n->name_type = (unsigned int)type & 0xFF;
1036 push_ascii(n->scope, global_scope(), 64, STR_TERMINATE);
1039 static BOOL do_nodestatus(struct messaging_context *msg_ctx,
1040 const struct server_id pid,
1041 const int argc, const char **argv)
1043 struct packet_struct p;
1046 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1052 p.ip = *interpret_addr2(argv[1]);
1054 p.packet_type = NMB_PACKET;
1056 p.packet.nmb.header.name_trn_id = 10;
1057 p.packet.nmb.header.opcode = 0;
1058 p.packet.nmb.header.response = False;
1059 p.packet.nmb.header.nm_flags.bcast = False;
1060 p.packet.nmb.header.nm_flags.recursion_available = False;
1061 p.packet.nmb.header.nm_flags.recursion_desired = False;
1062 p.packet.nmb.header.nm_flags.trunc = False;
1063 p.packet.nmb.header.nm_flags.authoritative = False;
1064 p.packet.nmb.header.rcode = 0;
1065 p.packet.nmb.header.qdcount = 1;
1066 p.packet.nmb.header.ancount = 0;
1067 p.packet.nmb.header.nscount = 0;
1068 p.packet.nmb.header.arcount = 0;
1069 my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1070 p.packet.nmb.question.question_type = 0x21;
1071 p.packet.nmb.question.question_class = 0x1;
1073 return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1076 /* A list of message type supported */
1078 static const struct {
1079 const char *name; /* Option name */
1080 BOOL (*fn)(struct messaging_context *msg_ctx,
1081 const struct server_id pid,
1082 const int argc, const char **argv);
1083 const char *help; /* Short help text */
1085 { "debug", do_debug, "Set debuglevel" },
1086 { "force-election", do_election,
1087 "Force a browse election" },
1088 { "ping", do_ping, "Elicit a response" },
1089 { "profile", do_profile, "" },
1090 { "inject", do_inject_fault,
1091 "Inject a fatal signal into a running smbd"},
1092 { "stacktrace", do_daemon_stack_trace,
1093 "Display a stack trace of a daemon" },
1094 { "profilelevel", do_profilelevel, "" },
1095 { "debuglevel", do_debuglevel, "Display current debuglevels" },
1096 { "printnotify", do_printnotify, "Send a print notify message" },
1097 { "close-share", do_closeshare, "Forcibly disconnect a share" },
1098 { "lockretry", do_lockretry, "Force a blocking lock retry" },
1099 { "brl-revalidate", do_brl_revalidate, "Revalidate all brl entries" },
1100 { "samsync", do_samsync, "Initiate SAM synchronisation" },
1101 { "samrepl", do_samrepl, "Initiate SAM replication" },
1102 { "pool-usage", do_poolusage, "Display talloc memory usage" },
1103 { "dmalloc-mark", do_dmalloc_mark, "" },
1104 { "dmalloc-log-changed", do_dmalloc_changed, "" },
1105 { "shutdown", do_shutdown, "Shut down daemon" },
1106 { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
1107 { "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
1108 { "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
1109 { "online", do_winbind_online, "Ask winbind to go into online state"},
1110 { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
1111 { "onlinestatus", do_winbind_onlinestatus, "Request winbind online status"},
1112 { "dump-event-list", do_dump_event_list, "Dump event list"},
1113 { "noop", do_noop, "Do nothing" },
1117 /* Display usage information */
1119 static void usage(poptContext pc)
1123 poptPrintHelp(pc, stderr, 0);
1125 fprintf(stderr, "\n");
1126 fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1129 fprintf(stderr, "\n");
1130 fprintf(stderr, "<message-type> is one of:\n");
1132 for (i = 0; msg_types[i].name; i++)
1133 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name,
1136 fprintf(stderr, "\n");
1141 /* Return the pid number for a string destination */
1143 static struct server_id parse_dest(const char *dest)
1145 struct server_id result = {-1};
1148 /* Zero is a special return value for broadcast smbd */
1150 if (strequal(dest, "smbd")) {
1151 return interpret_pid(MSG_BROADCAST_PID_STR);
1154 /* Try self - useful for testing */
1156 if (strequal(dest, "self")) {
1157 return pid_to_procid(sys_getpid());
1160 /* Fix winbind typo. */
1161 if (strequal(dest, "winbind")) {
1166 if (!(strequal(dest, "winbindd") || strequal(dest, "nmbd"))) {
1167 /* Check for numeric pid number */
1169 result = interpret_pid(dest);
1171 /* Zero isn't valid if not smbd. */
1172 if (result.pid && procid_valid(&result)) {
1177 /* Look up other destinations in pidfile directory */
1179 if ((pid = pidfile_pid(dest)) != 0) {
1180 return pid_to_procid(pid);
1183 fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1188 /* Execute smbcontrol command */
1190 static BOOL do_command(struct messaging_context *msg_ctx,
1191 int argc, const char **argv)
1193 const char *dest = argv[0], *command = argv[1];
1194 struct server_id pid;
1197 /* Check destination */
1199 pid = parse_dest(dest);
1200 if (!procid_valid(&pid)) {
1206 for (i = 0; msg_types[i].name; i++) {
1207 if (strequal(command, msg_types[i].name))
1208 return msg_types[i].fn(msg_ctx, pid,
1209 argc - 1, argv + 1);
1212 fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1217 static void smbcontrol_help(poptContext pc,
1218 enum poptCallbackReason preason,
1219 struct poptOption * poption,
1223 if (poption->shortName != '?') {
1224 poptPrintUsage(pc, stdout, 0);
1232 struct poptOption help_options[] = {
1233 { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1235 { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1236 { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1242 int main(int argc, const char **argv)
1246 struct event_context *evt_ctx;
1247 struct messaging_context *msg_ctx;
1249 static struct poptOption long_options[] = {
1251 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1252 0, "Help options:", NULL },
1253 { "timeout", 't', POPT_ARG_INT, &timeout, 't',
1254 "Set timeout value in seconds", "TIMEOUT" },
1262 setup_logging(argv[0],True);
1264 /* Parse command line arguments using popt */
1266 pc = poptGetContext(
1267 "smbcontrol", argc, (const char **)argv, long_options, 0);
1269 poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1275 while ((opt = poptGetNextOpt(pc)) != -1) {
1277 case 't': /* --timeout */
1280 fprintf(stderr, "Invalid option\n");
1281 poptPrintHelp(pc, stderr, 0);
1286 /* We should now have the remaining command line arguments in
1287 argv. The argc parameter should have been decremented to the
1288 correct value in the above switch statement. */
1290 argv = (const char **)poptGetArgs(pc);
1292 while (argv[argc] != NULL) {
1299 lp_load(dyn_CONFIGFILE,False,False,False,True);
1301 /* Need to invert sense of return code -- samba
1302 * routines mostly return True==1 for success, but
1305 if (!(evt_ctx = event_context_init(NULL)) ||
1306 !(msg_ctx = messaging_init(NULL, server_id_self(), evt_ctx))) {
1307 fprintf(stderr, "could not init messaging context\n");
1311 return !do_command(msg_ctx, argc, argv);