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(BOOL multiple_replies)
75 time_t start_time = time(NULL);
77 /* Wait around a bit. This is pretty disgusting - we have to
78 busy-wait here as there is no nicer way to do it. */
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(int msg_type, struct server_id pid, void *buf,
91 size_t len, void *private_data)
93 printf("PID %u: %.*s", (unsigned int)procid_to_pid(&pid),
94 (int)len, (const char *)buf);
98 /* Message handler callback that displays a string on stdout */
100 static void print_string_cb(int msg_type, struct server_id pid,
101 void *buf, size_t len, void *private_data)
103 printf("%.*s", (int)len, (const char *)buf);
107 /* Send no message. Useful for testing. */
109 static BOOL do_noop(struct messaging_context *msg_ctx,
110 const struct server_id pid,
111 const int argc, const char **argv)
114 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
118 /* Move along, nothing to see here */
123 /* Send a debug string */
125 static BOOL do_debug(struct messaging_context *msg_ctx,
126 const struct server_id pid,
127 const int argc, const char **argv)
130 fprintf(stderr, "Usage: smbcontrol <dest> debug "
135 return send_message(msg_ctx,
136 pid, MSG_DEBUG, argv[1], strlen(argv[1]) + 1, False);
139 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
141 /* Return the name of a process given it's PID. This will only work on Linux,
142 * but that's probably moot since this whole stack tracing implementatino is
143 * Linux-specific anyway.
145 static const char * procname(pid_t pid, char * buf, size_t bufsz)
150 snprintf(path, sizeof(path), "/proc/%llu/cmdline",
151 (unsigned long long)pid);
152 if ((fp = fopen(path, "r")) == NULL) {
156 fgets(buf, bufsz, fp);
162 static void print_stack_trace(pid_t pid, int * count)
165 unw_addr_space_t aspace = NULL;
174 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
176 "Failed to attach to process %llu: %s\n",
177 (unsigned long long)pid, strerror(errno));
181 /* Wait until the attach is complete. */
182 waitpid(pid, NULL, 0);
184 if (((pinfo = _UPT_create(pid)) == NULL) ||
185 ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
186 /* Probably out of memory. */
188 "Unable to initialize stack unwind for process %llu\n",
189 (unsigned long long)pid);
193 if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
195 "Unable to unwind stack for process %llu: %s\n",
196 (unsigned long long)pid, unw_strerror(ret));
204 if (procname(pid, nbuf, sizeof(nbuf))) {
205 printf("Stack trace for process %llu (%s):\n",
206 (unsigned long long)pid, nbuf);
208 printf("Stack trace for process %llu:\n",
209 (unsigned long long)pid);
212 while (unw_step(&cursor) > 0) {
214 unw_get_reg(&cursor, UNW_REG_IP, &ip);
215 unw_get_reg(&cursor, UNW_REG_SP, &sp);
217 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
218 if (ret != 0 && ret != -UNW_ENOMEM) {
219 snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
221 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
222 nbuf, (long long)off, (long long)ip,
230 unw_destroy_addr_space(aspace);
237 ptrace(PTRACE_DETACH, pid, NULL, NULL);
240 static int stack_trace_connection(TDB_CONTEXT * tdb,
241 const struct connections_key *key,
242 const struct connections_data *conn,
244 print_stack_trace(procid_to_pid(&conn->pid), (int *)priv);
249 static BOOL do_daemon_stack_trace(struct messaging_context *msg_ctx,
250 const struct server_id pid,
251 const int argc, const char **argv)
254 "Daemon stack tracing is not supported on this platform\n");
261 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
265 dest = procid_to_pid(&pid);
268 /* It would be nice to be able to make sure that this PID is
269 * the PID of a smbd/winbind/nmbd process, not some random PID
270 * the user liked the look of. It doesn't seem like it's worth
271 * the effort at the moment, however.
273 print_stack_trace(dest, &count);
275 connections_traverse(stack_trace_connection, &count);
281 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
283 static BOOL do_daemon_stack_trace(struct messaging_context *msg_ctx,
284 const struct server_id pid,
285 const int argc, const char **argv)
288 "Daemon stack tracing is not supported on this platform\n");
292 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
294 /* Inject a fault (fatal signal) into a running smbd */
296 static BOOL do_inject_fault(struct messaging_context *msg_ctx,
297 const struct server_id pid,
298 const int argc, const char **argv)
301 fprintf(stderr, "Usage: smbcontrol <dest> inject "
302 "<bus|hup|term|internal|segv>\n");
307 fprintf(stderr, "Fault injection is only available in "
308 "developer builds\n");
310 #else /* DEVELOPER */
314 if (strcmp(argv[1], "bus") == 0) {
316 } else if (strcmp(argv[1], "hup") == 0) {
318 } else if (strcmp(argv[1], "term") == 0) {
320 } else if (strcmp(argv[1], "segv") == 0) {
322 } else if (strcmp(argv[1], "internal") == 0) {
323 /* Force an internal error, ie. an unclean exit. */
326 fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
330 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
331 &sig, sizeof(int), False);
333 #endif /* DEVELOPER */
336 /* Force a browser election */
338 static BOOL do_election(struct messaging_context *msg_ctx,
339 const struct server_id pid,
340 const int argc, const char **argv)
343 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
347 return send_message(msg_ctx,
348 pid, MSG_FORCE_ELECTION, NULL, 0, False);
351 /* Ping a samba daemon process */
353 static void pong_cb(int msg_type, struct server_id pid, void *buf,
354 size_t len, void *private_data)
356 char *src_string = procid_str(NULL, &pid);
357 printf("PONG from pid %s\n", src_string);
358 TALLOC_FREE(src_string);
362 static BOOL do_ping(struct messaging_context *msg_ctx,
363 const struct server_id pid,
364 const int argc, const char **argv)
367 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
371 /* Send a message and register our interest in a reply */
373 if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0, False))
376 message_register(MSG_PONG, pong_cb, NULL);
378 wait_replies(procid_to_pid(&pid) == 0);
380 /* No replies were received within the timeout period */
382 if (num_replies == 0)
383 printf("No replies received\n");
385 message_deregister(MSG_PONG);
390 /* Set profiling options */
392 static BOOL do_profile(struct messaging_context *msg_ctx,
393 const struct server_id pid,
394 const int argc, const char **argv)
399 fprintf(stderr, "Usage: smbcontrol <dest> profile "
400 "<off|count|on|flush>\n");
404 if (strcmp(argv[1], "off") == 0) {
406 } else if (strcmp(argv[1], "count") == 0) {
408 } else if (strcmp(argv[1], "on") == 0) {
410 } else if (strcmp(argv[1], "flush") == 0) {
413 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
417 return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int), False);
420 /* Return the profiling level */
422 static void profilelevel_cb(struct messaging_context *msg_ctx,
425 struct server_id pid,
433 if (data->length != sizeof(int)) {
434 fprintf(stderr, "invalid message length %ld returned\n",
435 (unsigned long)data->length);
439 memcpy(&level, data->data, sizeof(int));
452 s = "count and time";
459 printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
462 static void profilelevel_rqst(struct messaging_context *msg_ctx,
465 struct server_id pid,
470 /* Send back a dummy reply */
472 send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int), False);
475 static BOOL do_profilelevel(struct messaging_context *msg_ctx,
476 const struct server_id pid,
477 const int argc, const char **argv)
480 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
484 /* Send a message and register our interest in a reply */
486 if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0, False))
489 messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
490 messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
493 wait_replies(procid_to_pid(&pid) == 0);
495 /* No replies were received within the timeout period */
497 if (num_replies == 0)
498 printf("No replies received\n");
500 message_deregister(MSG_PROFILE);
505 /* Display debug level settings */
507 static BOOL do_debuglevel(struct messaging_context *msg_ctx,
508 const struct server_id pid,
509 const int argc, const char **argv)
512 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
516 /* Send a message and register our interest in a reply */
518 if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0, False))
521 message_register(MSG_DEBUGLEVEL, print_pid_string_cb, NULL);
523 wait_replies(procid_to_pid(&pid) == 0);
525 /* No replies were received within the timeout period */
527 if (num_replies == 0)
528 printf("No replies received\n");
530 message_deregister(MSG_DEBUGLEVEL);
535 /* Send a print notify message */
537 static BOOL do_printnotify(struct messaging_context *msg_ctx,
538 const struct server_id pid,
539 const int argc, const char **argv)
543 /* Check for subcommand */
546 fprintf(stderr, "Must specify subcommand:\n");
547 fprintf(stderr, "\tqueuepause <printername>\n");
548 fprintf(stderr, "\tqueueresume <printername>\n");
549 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
550 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
551 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
552 fprintf(stderr, "\tprinter <printername> <comment|port|"
553 "driver> <value>\n");
560 if (strcmp(cmd, "queuepause") == 0) {
563 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
564 " queuepause <printername>\n");
568 notify_printer_status_byname(argv[2], PRINTER_STATUS_PAUSED);
572 } else if (strcmp(cmd, "queueresume") == 0) {
575 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
576 " queuereume <printername>\n");
580 notify_printer_status_byname(argv[2], PRINTER_STATUS_OK);
584 } else if (strcmp(cmd, "jobpause") == 0) {
588 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
589 " jobpause <printername> <unix-jobid>\n");
593 jobid = atoi(argv[3]);
595 notify_job_status_byname(
596 argv[2], jobid, JOB_STATUS_PAUSED,
597 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
601 } else if (strcmp(cmd, "jobresume") == 0) {
605 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
606 " jobpause <printername> <unix-jobid>\n");
610 jobid = atoi(argv[3]);
612 notify_job_status_byname(
613 argv[2], jobid, JOB_STATUS_QUEUED,
614 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
618 } else if (strcmp(cmd, "jobdelete") == 0) {
622 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
623 " jobpause <printername> <unix-jobid>\n");
627 jobid = atoi(argv[3]);
629 notify_job_status_byname(
630 argv[2], jobid, JOB_STATUS_DELETING,
631 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
633 notify_job_status_byname(
634 argv[2], jobid, JOB_STATUS_DELETING|
636 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
640 } else if (strcmp(cmd, "printer") == 0) {
644 fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
645 "printer <printername> <comment|port|driver> "
650 if (strcmp(argv[3], "comment") == 0) {
651 attribute = PRINTER_NOTIFY_COMMENT;
652 } else if (strcmp(argv[3], "port") == 0) {
653 attribute = PRINTER_NOTIFY_PORT_NAME;
654 } else if (strcmp(argv[3], "driver") == 0) {
655 attribute = PRINTER_NOTIFY_DRIVER_NAME;
657 fprintf(stderr, "Invalid printer command '%s'\n",
662 notify_printer_byname(argv[2], attribute,
663 CONST_DISCARD(char *, argv[4]));
668 fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
672 print_notify_send_messages(msg_ctx, 0);
678 static BOOL do_closeshare(struct messaging_context *msg_ctx,
679 const struct server_id pid,
680 const int argc, const char **argv)
683 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
688 return send_message(msg_ctx,
689 pid, MSG_SMB_FORCE_TDIS, argv[1], strlen(argv[1]) + 1, False);
692 /* Force a SAM synchronisation */
694 static BOOL do_samsync(struct messaging_context *msg_ctx,
695 const struct server_id pid,
696 const int argc, const char **argv)
699 fprintf(stderr, "Usage: smbcontrol <dest> samsync\n");
703 return send_message(msg_ctx,
704 pid, MSG_SMB_SAM_SYNC, NULL, 0, False);
707 /* Force a SAM replication */
709 static BOOL do_samrepl(struct messaging_context *msg_ctx,
710 const struct server_id pid,
711 const int argc, const char **argv)
714 fprintf(stderr, "Usage: smbcontrol <dest> samrepl\n");
718 return send_message(msg_ctx,
719 pid, MSG_SMB_SAM_REPL, NULL, 0, False);
722 /* Display talloc pool usage */
724 static BOOL do_poolusage(struct messaging_context *msg_ctx,
725 const struct server_id pid,
726 const int argc, const char **argv)
729 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
733 message_register(MSG_POOL_USAGE, print_string_cb, NULL);
735 /* Send a message and register our interest in a reply */
737 if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0, False))
740 wait_replies(procid_to_pid(&pid) == 0);
742 /* No replies were received within the timeout period */
744 if (num_replies == 0)
745 printf("No replies received\n");
747 message_deregister(MSG_POOL_USAGE);
752 /* Perform a dmalloc mark */
754 static BOOL do_dmalloc_mark(struct messaging_context *msg_ctx,
755 const struct server_id pid,
756 const int argc, const char **argv)
759 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
763 return send_message(msg_ctx,
764 pid, MSG_REQ_DMALLOC_MARK, NULL, 0, False);
767 /* Perform a dmalloc changed */
769 static BOOL do_dmalloc_changed(struct messaging_context *msg_ctx,
770 const struct server_id pid,
771 const int argc, const char **argv)
774 fprintf(stderr, "Usage: smbcontrol <dest> "
775 "dmalloc-log-changed\n");
779 return send_message(msg_ctx,
780 pid, MSG_REQ_DMALLOC_LOG_CHANGED, NULL, 0, False);
783 /* Shutdown a server process */
785 static BOOL do_shutdown(struct messaging_context *msg_ctx,
786 const struct server_id pid,
787 const int argc, const char **argv)
790 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
794 return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0, False);
797 /* Notify a driver upgrade */
799 static BOOL do_drvupgrade(struct messaging_context *msg_ctx,
800 const struct server_id pid,
801 const int argc, const char **argv)
804 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
809 return send_message(msg_ctx,
810 pid, MSG_DEBUG, argv[1], strlen(argv[1]) + 1, False);
813 static BOOL do_winbind_online(struct messaging_context *msg_ctx,
814 const struct server_id pid,
815 const int argc, const char **argv)
820 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
824 if (!lp_winbind_offline_logon()) {
825 fprintf(stderr, "The parameter \"winbind offline logon\" must "
826 "be set in the [global] section of smb.conf for this "
827 "command to be allowed.\n");
831 /* Remove the entry in the winbindd_cache tdb to tell a later
832 starting winbindd that we're online. */
834 tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
836 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
837 lock_path("winbindd_cache.tdb"));
841 tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
844 return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0, False);
847 static BOOL do_winbind_offline(struct messaging_context *msg_ctx,
848 const struct server_id pid,
849 const int argc, const char **argv)
856 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
860 if (!lp_winbind_offline_logon()) {
861 fprintf(stderr, "The parameter \"winbind offline logon\" must "
862 "be set in the [global] section of smb.conf for this "
863 "command to be allowed.\n");
867 /* Create an entry in the winbindd_cache tdb to tell a later
868 starting winbindd that we're offline. We may actually create
871 tdb = tdb_open_log(lock_path("winbindd_cache.tdb"),
872 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
873 TDB_DEFAULT /* TDB_CLEAR_IF_FIRST */, O_RDWR|O_CREAT, 0600);
876 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
877 lock_path("winbindd_cache.tdb"));
881 /* There's a potential race condition that if a child
882 winbindd detects a domain is online at the same time
883 we're trying to tell it to go offline that it might
884 delete the record we add between us adding it and
885 sending the message. Minimize this by retrying up to
888 for (retry = 0; retry < 5; retry++) {
894 SIVAL(buf, 0, time(NULL));
898 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
900 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
903 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
904 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
906 if (!d.dptr || d.dsize != 4) {
908 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
919 static BOOL do_winbind_onlinestatus(struct messaging_context *msg_ctx,
920 const struct server_id pid,
921 const int argc, const char **argv)
923 struct server_id myid;
925 myid = pid_to_procid(sys_getpid());
928 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
932 message_register(MSG_WINBIND_ONLINESTATUS, print_pid_string_cb, NULL);
934 if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, &myid,
935 sizeof(myid), False))
938 wait_replies(procid_to_pid(&pid) == 0);
940 /* No replies were received within the timeout period */
942 if (num_replies == 0)
943 printf("No replies received\n");
945 message_deregister(MSG_WINBIND_ONLINESTATUS);
951 static BOOL do_reload_config(struct messaging_context *msg_ctx,
952 const struct server_id pid,
953 const int argc, const char **argv)
956 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
960 return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED,
964 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
967 memset( (char *)n, '\0', sizeof(struct nmb_name) );
968 fstrcpy(unix_name, name);
969 strupper_m(unix_name);
970 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
971 n->name_type = (unsigned int)type & 0xFF;
972 push_ascii(n->scope, global_scope(), 64, STR_TERMINATE);
975 static BOOL do_nodestatus(struct messaging_context *msg_ctx,
976 const struct server_id pid,
977 const int argc, const char **argv)
979 struct packet_struct p;
982 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
988 p.ip = *interpret_addr2(argv[1]);
990 p.packet_type = NMB_PACKET;
992 p.packet.nmb.header.name_trn_id = 10;
993 p.packet.nmb.header.opcode = 0;
994 p.packet.nmb.header.response = False;
995 p.packet.nmb.header.nm_flags.bcast = False;
996 p.packet.nmb.header.nm_flags.recursion_available = False;
997 p.packet.nmb.header.nm_flags.recursion_desired = False;
998 p.packet.nmb.header.nm_flags.trunc = False;
999 p.packet.nmb.header.nm_flags.authoritative = False;
1000 p.packet.nmb.header.rcode = 0;
1001 p.packet.nmb.header.qdcount = 1;
1002 p.packet.nmb.header.ancount = 0;
1003 p.packet.nmb.header.nscount = 0;
1004 p.packet.nmb.header.arcount = 0;
1005 my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1006 p.packet.nmb.question.question_type = 0x21;
1007 p.packet.nmb.question.question_class = 0x1;
1009 return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p),
1013 /* A list of message type supported */
1015 static const struct {
1016 const char *name; /* Option name */
1017 BOOL (*fn)(struct messaging_context *msg_ctx,
1018 const struct server_id pid,
1019 const int argc, const char **argv);
1020 const char *help; /* Short help text */
1022 { "debug", do_debug, "Set debuglevel" },
1023 { "force-election", do_election,
1024 "Force a browse election" },
1025 { "ping", do_ping, "Elicit a response" },
1026 { "profile", do_profile, "" },
1027 { "inject", do_inject_fault,
1028 "Inject a fatal signal into a running smbd"},
1029 { "stacktrace", do_daemon_stack_trace,
1030 "Display a stack trace of a daemon" },
1031 { "profilelevel", do_profilelevel, "" },
1032 { "debuglevel", do_debuglevel, "Display current debuglevels" },
1033 { "printnotify", do_printnotify, "Send a print notify message" },
1034 { "close-share", do_closeshare, "Forcibly disconnect a share" },
1035 { "samsync", do_samsync, "Initiate SAM synchronisation" },
1036 { "samrepl", do_samrepl, "Initiate SAM replication" },
1037 { "pool-usage", do_poolusage, "Display talloc memory usage" },
1038 { "dmalloc-mark", do_dmalloc_mark, "" },
1039 { "dmalloc-log-changed", do_dmalloc_changed, "" },
1040 { "shutdown", do_shutdown, "Shut down daemon" },
1041 { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
1042 { "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
1043 { "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
1044 { "online", do_winbind_online, "Ask winbind to go into online state"},
1045 { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
1046 { "onlinestatus", do_winbind_onlinestatus, "Request winbind online status"},
1047 { "noop", do_noop, "Do nothing" },
1051 /* Display usage information */
1053 static void usage(poptContext *pc)
1057 poptPrintHelp(*pc, stderr, 0);
1059 fprintf(stderr, "\n");
1060 fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1063 fprintf(stderr, "\n");
1064 fprintf(stderr, "<message-type> is one of:\n");
1066 for (i = 0; msg_types[i].name; i++)
1067 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name,
1070 fprintf(stderr, "\n");
1075 /* Return the pid number for a string destination */
1077 static struct server_id parse_dest(const char *dest)
1079 struct server_id result = {-1};
1082 /* Zero is a special return value for broadcast smbd */
1084 if (strequal(dest, "smbd")) {
1085 return interpret_pid("0");
1088 /* Try self - useful for testing */
1090 if (strequal(dest, "self")) {
1091 return pid_to_procid(sys_getpid());
1094 /* Fix winbind typo. */
1095 if (strequal(dest, "winbind")) {
1100 if (!(strequal(dest, "winbindd") || strequal(dest, "nmbd"))) {
1101 /* Check for numeric pid number */
1103 result = interpret_pid(dest);
1105 /* Zero isn't valid if not smbd. */
1106 if (result.pid && procid_valid(&result)) {
1111 /* Look up other destinations in pidfile directory */
1113 if ((pid = pidfile_pid(dest)) != 0) {
1114 return pid_to_procid(pid);
1117 fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1122 /* Execute smbcontrol command */
1124 static BOOL do_command(struct messaging_context *msg_ctx,
1125 int argc, const char **argv)
1127 const char *dest = argv[0], *command = argv[1];
1128 struct server_id pid;
1131 /* Check destination */
1133 pid = parse_dest(dest);
1134 if (!procid_valid(&pid)) {
1140 for (i = 0; msg_types[i].name; i++) {
1141 if (strequal(command, msg_types[i].name))
1142 return msg_types[i].fn(msg_ctx, pid,
1143 argc - 1, argv + 1);
1146 fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1153 int main(int argc, const char **argv)
1157 struct event_context *evt_ctx;
1158 struct messaging_context *msg_ctx;
1160 static struct poptOption long_options[] = {
1162 { "timeout", 't', POPT_ARG_INT, &timeout, 't',
1163 "Set timeout value in seconds", "TIMEOUT" },
1171 setup_logging(argv[0],True);
1173 /* Parse command line arguments using popt */
1175 pc = poptGetContext(
1176 "smbcontrol", argc, (const char **)argv, long_options, 0);
1178 poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1184 while ((opt = poptGetNextOpt(pc)) != -1) {
1186 case 't': /* --timeout */
1189 fprintf(stderr, "Invalid option\n");
1190 poptPrintHelp(pc, stderr, 0);
1195 /* We should now have the remaining command line arguments in
1196 argv. The argc parameter should have been decremented to the
1197 correct value in the above switch statement. */
1199 argv = (const char **)poptGetArgs(pc);
1201 while (argv[argc] != NULL) {
1208 lp_load(dyn_CONFIGFILE,False,False,False,True);
1210 /* Need to invert sense of return code -- samba
1211 * routines mostly return True==1 for success, but
1214 if (!(evt_ctx = event_context_init(NULL)) ||
1215 !(msg_ctx = messaging_init(NULL, server_id_self(), evt_ctx))) {
1216 fprintf(stderr, "could not init messaging context\n");
1220 return !do_command(msg_ctx, argc, argv);