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/>.
27 #include "system/filesys.h"
28 #include "popt_common.h"
29 #include "librpc/gen_ndr/spoolss.h"
30 #include "nt_printing.h"
31 #include "printing/notify.h"
32 #include "libsmb/nmblib.h"
37 #include <libunwind.h>
40 #if HAVE_LIBUNWIND_PTRACE_H
41 #include <libunwind-ptrace.h>
45 #include <sys/ptrace.h>
48 /* Default timeout value when waiting for replies (in seconds) */
50 #define DEFAULT_TIMEOUT 10
52 static int timeout = DEFAULT_TIMEOUT;
53 static int num_replies; /* Used by message callback fns */
55 /* Send a message to a destination pid. Zero means broadcast smbd. */
57 static bool send_message(struct messaging_context *msg_ctx,
58 struct server_id pid, int msg_type,
59 const void *buf, int len)
64 if (procid_to_pid(&pid) != 0)
65 return NT_STATUS_IS_OK(
66 messaging_send_buf(msg_ctx, pid, msg_type,
67 (const uint8 *)buf, len));
69 ret = message_send_all(msg_ctx, msg_type, buf, len, &n_sent);
70 DEBUG(10,("smbcontrol/send_message: broadcast message to "
71 "%d processes\n", n_sent));
76 static void smbcontrol_timeout(struct tevent_context *event_ctx,
77 struct tevent_timer *te,
81 bool *timed_out = (bool *)private_data;
86 /* Wait for one or more reply messages */
88 static void wait_replies(struct tevent_context *ev_ctx,
89 struct messaging_context *msg_ctx,
90 bool multiple_replies)
92 struct tevent_timer *te;
93 bool timed_out = False;
95 if (!(te = tevent_add_timer(ev_ctx, NULL,
96 timeval_current_ofs(timeout, 0),
97 smbcontrol_timeout, (void *)&timed_out))) {
98 DEBUG(0, ("tevent_add_timer failed\n"));
104 if (num_replies > 0 && !multiple_replies)
106 ret = tevent_loop_once(ev_ctx);
113 /* Message handler callback that displays the PID and a string on stdout */
115 static void print_pid_string_cb(struct messaging_context *msg,
118 struct server_id pid,
123 pidstr = server_id_str(talloc_tos(), &pid);
124 printf("PID %s: %.*s", pidstr, (int)data->length,
125 (const char *)data->data);
130 /* Message handler callback that displays a string on stdout */
132 static void print_string_cb(struct messaging_context *msg,
135 struct server_id pid,
138 printf("%*s", (int)data->length, (const char *)data->data);
142 /* Send no message. Useful for testing. */
144 static bool do_noop(struct tevent_context *ev_ctx,
145 struct messaging_context *msg_ctx,
146 const struct server_id pid,
147 const int argc, const char **argv)
150 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
154 /* Move along, nothing to see here */
159 /* Send a debug string */
161 static bool do_debug(struct tevent_context *ev_ctx,
162 struct messaging_context *msg_ctx,
163 const struct server_id pid,
164 const int argc, const char **argv)
167 fprintf(stderr, "Usage: smbcontrol <dest> debug "
172 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
173 strlen(argv[1]) + 1);
177 static bool do_idmap(struct tevent_context *ev,
178 struct messaging_context *msg_ctx,
179 const struct server_id pid,
180 const int argc, const char **argv)
182 static const char* usage = "Usage: "
183 "smbcontrol <dest> idmap <cmd> [arg]\n"
184 "\tcmd:\tflush [gid|uid]\n"
185 "\t\tdelete \"UID <uid>\"|\"GID <gid>\"|<sid>\n"
186 "\t\tkill \"UID <uid>\"|\"GID <gid>\"|<sid>\n";
187 const char* arg = NULL;
196 arglen = strlen(arg) + 1;
199 fprintf(stderr, "%s", usage);
203 if (strcmp(argv[1], "flush") == 0) {
204 msg_type = ID_CACHE_FLUSH;
206 else if (strcmp(argv[1], "delete") == 0) {
207 msg_type = ID_CACHE_DELETE;
209 else if (strcmp(argv[1], "kill") == 0) {
210 msg_type = ID_CACHE_KILL;
212 else if (strcmp(argv[1], "help") == 0) {
213 fprintf(stdout, "%s", usage);
217 fprintf(stderr, "%s", usage);
221 return send_message(msg_ctx, pid, msg_type, arg, arglen);
225 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
227 /* Return the name of a process given it's PID. This will only work on Linux,
228 * but that's probably moot since this whole stack tracing implementatino is
229 * Linux-specific anyway.
231 static const char * procname(pid_t pid, char * buf, size_t bufsz)
236 snprintf(path, sizeof(path), "/proc/%llu/cmdline",
237 (unsigned long long)pid);
238 if ((fp = fopen(path, "r")) == NULL) {
242 fgets(buf, bufsz, fp);
248 static void print_stack_trace(pid_t pid, int * count)
251 unw_addr_space_t aspace = NULL;
260 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
262 "Failed to attach to process %llu: %s\n",
263 (unsigned long long)pid, strerror(errno));
267 /* Wait until the attach is complete. */
268 waitpid(pid, NULL, 0);
270 if (((pinfo = _UPT_create(pid)) == NULL) ||
271 ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
272 /* Probably out of memory. */
274 "Unable to initialize stack unwind for process %llu\n",
275 (unsigned long long)pid);
279 if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
281 "Unable to unwind stack for process %llu: %s\n",
282 (unsigned long long)pid, unw_strerror(ret));
290 if (procname(pid, nbuf, sizeof(nbuf))) {
291 printf("Stack trace for process %llu (%s):\n",
292 (unsigned long long)pid, nbuf);
294 printf("Stack trace for process %llu:\n",
295 (unsigned long long)pid);
298 while (unw_step(&cursor) > 0) {
300 unw_get_reg(&cursor, UNW_REG_IP, &ip);
301 unw_get_reg(&cursor, UNW_REG_SP, &sp);
303 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
304 if (ret != 0 && ret != -UNW_ENOMEM) {
305 snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
307 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
308 nbuf, (long long)off, (long long)ip,
316 unw_destroy_addr_space(aspace);
323 ptrace(PTRACE_DETACH, pid, NULL, NULL);
326 static int stack_trace_connection(const struct connections_key *key,
327 const struct connections_data *crec,
330 print_stack_trace(procid_to_pid(&crec->pid), (int *)priv);
335 static bool do_daemon_stack_trace(struct tevent_context *ev_ctx,
336 struct messaging_context *msg_ctx,
337 const struct server_id pid,
338 const int argc, const char **argv)
344 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
348 dest = procid_to_pid(&pid);
351 /* It would be nice to be able to make sure that this PID is
352 * the PID of a smbd/winbind/nmbd process, not some random PID
353 * the user liked the look of. It doesn't seem like it's worth
354 * the effort at the moment, however.
356 print_stack_trace(dest, &count);
358 connections_forall_read(stack_trace_connection, &count);
364 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
366 static bool do_daemon_stack_trace(struct tevent_context *ev_ctx,
367 struct messaging_context *msg_ctx,
368 const struct server_id pid,
369 const int argc, const char **argv)
372 "Daemon stack tracing is not supported on this platform\n");
376 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
378 /* Inject a fault (fatal signal) into a running smbd */
380 static bool do_inject_fault(struct tevent_context *ev_ctx,
381 struct messaging_context *msg_ctx,
382 const struct server_id pid,
383 const int argc, const char **argv)
386 fprintf(stderr, "Usage: smbcontrol <dest> inject "
387 "<bus|hup|term|internal|segv>\n");
392 fprintf(stderr, "Fault injection is only available in "
393 "developer builds\n");
395 #else /* DEVELOPER */
399 if (strcmp(argv[1], "bus") == 0) {
401 } else if (strcmp(argv[1], "hup") == 0) {
403 } else if (strcmp(argv[1], "term") == 0) {
405 } else if (strcmp(argv[1], "segv") == 0) {
407 } else if (strcmp(argv[1], "internal") == 0) {
408 /* Force an internal error, ie. an unclean exit. */
411 fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
415 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
418 #endif /* DEVELOPER */
421 /* Force a browser election */
423 static bool do_election(struct tevent_context *ev_ctx,
424 struct messaging_context *msg_ctx,
425 const struct server_id pid,
426 const int argc, const char **argv)
429 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
433 return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
436 /* Ping a samba daemon process */
438 static void pong_cb(struct messaging_context *msg,
441 struct server_id pid,
444 char *src_string = server_id_str(NULL, &pid);
445 printf("PONG from pid %s\n", src_string);
446 TALLOC_FREE(src_string);
450 static bool do_ping(struct tevent_context *ev_ctx,
451 struct messaging_context *msg_ctx,
452 const struct server_id pid,
453 const int argc, const char **argv)
456 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
460 /* Send a message and register our interest in a reply */
462 if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
465 messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
467 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
469 /* No replies were received within the timeout period */
471 if (num_replies == 0)
472 printf("No replies received\n");
474 messaging_deregister(msg_ctx, MSG_PONG, NULL);
479 /* Set profiling options */
481 static bool do_profile(struct tevent_context *ev_ctx,
482 struct messaging_context *msg_ctx,
483 const struct server_id pid,
484 const int argc, const char **argv)
489 fprintf(stderr, "Usage: smbcontrol <dest> profile "
490 "<off|count|on|flush>\n");
494 if (strcmp(argv[1], "off") == 0) {
496 } else if (strcmp(argv[1], "count") == 0) {
498 } else if (strcmp(argv[1], "on") == 0) {
500 } else if (strcmp(argv[1], "flush") == 0) {
503 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
507 return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
510 /* Return the profiling level */
512 static void profilelevel_cb(struct messaging_context *msg_ctx,
515 struct server_id pid,
523 if (data->length != sizeof(int)) {
524 fprintf(stderr, "invalid message length %ld returned\n",
525 (unsigned long)data->length);
529 memcpy(&level, data->data, sizeof(int));
542 s = "count and time";
549 printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
552 static void profilelevel_rqst(struct messaging_context *msg_ctx,
555 struct server_id pid,
560 /* Send back a dummy reply */
562 send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
565 static bool do_profilelevel(struct tevent_context *ev_ctx,
566 struct messaging_context *msg_ctx,
567 const struct server_id pid,
568 const int argc, const char **argv)
571 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
575 /* Send a message and register our interest in a reply */
577 if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
580 messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
581 messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
584 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
586 /* No replies were received within the timeout period */
588 if (num_replies == 0)
589 printf("No replies received\n");
591 messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
596 /* Display debug level settings */
598 static bool do_debuglevel(struct tevent_context *ev_ctx,
599 struct messaging_context *msg_ctx,
600 const struct server_id pid,
601 const int argc, const char **argv)
604 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
608 /* Send a message and register our interest in a reply */
610 if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
613 messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
615 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
617 /* No replies were received within the timeout period */
619 if (num_replies == 0)
620 printf("No replies received\n");
622 messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
627 /* Send a print notify message */
629 static bool do_printnotify(struct tevent_context *ev_ctx,
630 struct messaging_context *msg_ctx,
631 const struct server_id pid,
632 const int argc, const char **argv)
636 /* Check for subcommand */
639 fprintf(stderr, "Must specify subcommand:\n");
640 fprintf(stderr, "\tqueuepause <printername>\n");
641 fprintf(stderr, "\tqueueresume <printername>\n");
642 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
643 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
644 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
645 fprintf(stderr, "\tprinter <printername> <comment|port|"
646 "driver> <value>\n");
653 if (strcmp(cmd, "queuepause") == 0) {
656 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
657 " queuepause <printername>\n");
661 notify_printer_status_byname(messaging_event_context(msg_ctx),
663 PRINTER_STATUS_PAUSED);
667 } else if (strcmp(cmd, "queueresume") == 0) {
670 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
671 " queuereume <printername>\n");
675 notify_printer_status_byname(messaging_event_context(msg_ctx),
681 } else if (strcmp(cmd, "jobpause") == 0) {
685 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
686 " jobpause <printername> <unix-jobid>\n");
690 jobid = atoi(argv[3]);
692 notify_job_status_byname(
693 messaging_event_context(msg_ctx), msg_ctx,
694 argv[2], jobid, JOB_STATUS_PAUSED,
695 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
699 } else if (strcmp(cmd, "jobresume") == 0) {
703 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
704 " jobpause <printername> <unix-jobid>\n");
708 jobid = atoi(argv[3]);
710 notify_job_status_byname(
711 messaging_event_context(msg_ctx), msg_ctx,
712 argv[2], jobid, JOB_STATUS_QUEUED,
713 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
717 } else if (strcmp(cmd, "jobdelete") == 0) {
721 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
722 " jobpause <printername> <unix-jobid>\n");
726 jobid = atoi(argv[3]);
728 notify_job_status_byname(
729 messaging_event_context(msg_ctx), msg_ctx,
730 argv[2], jobid, JOB_STATUS_DELETING,
731 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
733 notify_job_status_byname(
734 messaging_event_context(msg_ctx), msg_ctx,
735 argv[2], jobid, JOB_STATUS_DELETING|
737 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
741 } else if (strcmp(cmd, "printer") == 0) {
745 fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
746 "printer <printername> <comment|port|driver> "
751 if (strcmp(argv[3], "comment") == 0) {
752 attribute = PRINTER_NOTIFY_FIELD_COMMENT;
753 } else if (strcmp(argv[3], "port") == 0) {
754 attribute = PRINTER_NOTIFY_FIELD_PORT_NAME;
755 } else if (strcmp(argv[3], "driver") == 0) {
756 attribute = PRINTER_NOTIFY_FIELD_DRIVER_NAME;
758 fprintf(stderr, "Invalid printer command '%s'\n",
763 notify_printer_byname(messaging_event_context(msg_ctx),
764 msg_ctx, argv[2], attribute,
765 discard_const_p(char, argv[4]));
770 fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
774 print_notify_send_messages(msg_ctx, 0);
780 static bool do_closeshare(struct tevent_context *ev_ctx,
781 struct messaging_context *msg_ctx,
782 const struct server_id pid,
783 const int argc, const char **argv)
786 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
791 return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
792 strlen(argv[1]) + 1);
795 /* Tell winbindd an IP got dropped */
797 static bool do_ip_dropped(struct tevent_context *ev_ctx,
798 struct messaging_context *msg_ctx,
799 const struct server_id pid,
800 const int argc, const char **argv)
803 fprintf(stderr, "Usage: smbcontrol <dest> ip-dropped "
808 return send_message(msg_ctx, pid, MSG_WINBIND_IP_DROPPED, argv[1],
809 strlen(argv[1]) + 1);
812 /* force a blocking lock retry */
814 static bool do_lockretry(struct tevent_context *ev_ctx,
815 struct messaging_context *msg_ctx,
816 const struct server_id pid,
817 const int argc, const char **argv)
820 fprintf(stderr, "Usage: smbcontrol <dest> lockretry\n");
824 return send_message(msg_ctx, pid, MSG_SMB_UNLOCK, NULL, 0);
827 /* force a validation of all brl entries, including re-sends. */
829 static bool do_brl_revalidate(struct tevent_context *ev_ctx,
830 struct messaging_context *msg_ctx,
831 const struct server_id pid,
832 const int argc, const char **argv)
835 fprintf(stderr, "Usage: smbcontrol <dest> brl-revalidate\n");
839 return send_message(msg_ctx, pid, MSG_SMB_BRL_VALIDATE, NULL, 0);
842 /* Display talloc pool usage */
844 static bool do_poolusage(struct tevent_context *ev_ctx,
845 struct messaging_context *msg_ctx,
846 const struct server_id pid,
847 const int argc, const char **argv)
850 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
854 messaging_register(msg_ctx, NULL, MSG_POOL_USAGE, print_string_cb);
856 /* Send a message and register our interest in a reply */
858 if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0))
861 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
863 /* No replies were received within the timeout period */
865 if (num_replies == 0)
866 printf("No replies received\n");
868 messaging_deregister(msg_ctx, MSG_POOL_USAGE, NULL);
873 /* Perform a dmalloc mark */
875 static bool do_dmalloc_mark(struct tevent_context *ev_ctx,
876 struct messaging_context *msg_ctx,
877 const struct server_id pid,
878 const int argc, const char **argv)
881 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
885 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
888 /* Perform a dmalloc changed */
890 static bool do_dmalloc_changed(struct tevent_context *ev_ctx,
891 struct messaging_context *msg_ctx,
892 const struct server_id pid,
893 const int argc, const char **argv)
896 fprintf(stderr, "Usage: smbcontrol <dest> "
897 "dmalloc-log-changed\n");
901 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
905 /* Shutdown a server process */
907 static bool do_shutdown(struct tevent_context *ev_ctx,
908 struct messaging_context *msg_ctx,
909 const struct server_id pid,
910 const int argc, const char **argv)
913 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
917 return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
920 /* Notify a driver upgrade */
922 static bool do_drvupgrade(struct tevent_context *ev_ctx,
923 struct messaging_context *msg_ctx,
924 const struct server_id pid,
925 const int argc, const char **argv)
928 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
933 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
934 strlen(argv[1]) + 1);
937 static bool do_winbind_online(struct tevent_context *ev_ctx,
938 struct messaging_context *msg_ctx,
939 const struct server_id pid,
940 const int argc, const char **argv)
945 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
949 /* Remove the entry in the winbindd_cache tdb to tell a later
950 starting winbindd that we're online. */
952 tdb = tdb_open_log(state_path("winbindd_cache.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
954 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
955 state_path("winbindd_cache.tdb"));
959 tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
962 return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
965 static bool do_winbind_offline(struct tevent_context *ev_ctx,
966 struct messaging_context *msg_ctx,
967 const struct server_id pid,
968 const int argc, const char **argv)
975 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
979 /* Create an entry in the winbindd_cache tdb to tell a later
980 starting winbindd that we're offline. We may actually create
983 tdb = tdb_open_log(state_path("winbindd_cache.tdb"),
984 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
985 TDB_DEFAULT|TDB_INCOMPATIBLE_HASH /* TDB_CLEAR_IF_FIRST */,
986 O_RDWR|O_CREAT, 0600);
989 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
990 state_path("winbindd_cache.tdb"));
994 /* There's a potential race condition that if a child
995 winbindd detects a domain is online at the same time
996 we're trying to tell it to go offline that it might
997 delete the record we add between us adding it and
998 sending the message. Minimize this by retrying up to
1001 for (retry = 0; retry < 5; retry++) {
1007 SIVAL(buf, 0, time(NULL));
1011 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
1013 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
1016 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
1017 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
1019 if (!d.dptr || d.dsize != 4) {
1021 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
1032 static bool do_winbind_onlinestatus(struct tevent_context *ev_ctx,
1033 struct messaging_context *msg_ctx,
1034 const struct server_id pid,
1035 const int argc, const char **argv)
1037 struct server_id myid;
1039 myid = messaging_server_id(msg_ctx);
1042 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
1046 messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
1047 print_pid_string_cb);
1049 if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, &myid,
1053 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1055 /* No replies were received within the timeout period */
1057 if (num_replies == 0)
1058 printf("No replies received\n");
1060 messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
1065 static bool do_dump_event_list(struct tevent_context *ev_ctx,
1066 struct messaging_context *msg_ctx,
1067 const struct server_id pid,
1068 const int argc, const char **argv)
1070 struct server_id myid;
1072 myid = messaging_server_id(msg_ctx);
1075 fprintf(stderr, "Usage: smbcontrol <dest> dump-event-list\n");
1079 return send_message(msg_ctx, pid, MSG_DUMP_EVENT_LIST, NULL, 0);
1082 static bool do_winbind_dump_domain_list(struct tevent_context *ev_ctx,
1083 struct messaging_context *msg_ctx,
1084 const struct server_id pid,
1085 const int argc, const char **argv)
1087 const char *domain = NULL;
1089 struct server_id myid;
1090 uint8_t *buf = NULL;
1093 myid = messaging_server_id(msg_ctx);
1095 if (argc < 1 || argc > 2) {
1096 fprintf(stderr, "Usage: smbcontrol <dest> dump-domain-list "
1103 domain_len = strlen(argv[1]) + 1;
1106 messaging_register(msg_ctx, NULL, MSG_WINBIND_DUMP_DOMAIN_LIST,
1107 print_pid_string_cb);
1109 buf_len = sizeof(myid)+domain_len;
1110 buf = SMB_MALLOC_ARRAY(uint8_t, buf_len);
1115 memcpy(buf, &myid, sizeof(myid));
1116 memcpy(&buf[sizeof(myid)], domain, domain_len);
1118 if (!send_message(msg_ctx, pid, MSG_WINBIND_DUMP_DOMAIN_LIST,
1125 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1127 /* No replies were received within the timeout period */
1130 if (num_replies == 0) {
1131 printf("No replies received\n");
1134 messaging_deregister(msg_ctx, MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
1139 static void winbind_validate_cache_cb(struct messaging_context *msg,
1142 struct server_id pid,
1145 char *src_string = server_id_str(NULL, &pid);
1146 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1147 (*(data->data) == 0 ? "" : "NOT "), src_string);
1148 TALLOC_FREE(src_string);
1152 static bool do_winbind_validate_cache(struct tevent_context *ev_ctx,
1153 struct messaging_context *msg_ctx,
1154 const struct server_id pid,
1155 const int argc, const char **argv)
1157 struct server_id myid;
1159 myid = messaging_server_id(msg_ctx);
1162 fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
1166 messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
1167 winbind_validate_cache_cb);
1169 if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
1174 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1176 if (num_replies == 0) {
1177 printf("No replies received\n");
1180 messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);
1185 static bool do_reload_config(struct tevent_context *ev_ctx,
1186 struct messaging_context *msg_ctx,
1187 const struct server_id pid,
1188 const int argc, const char **argv)
1191 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1195 return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1198 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1201 memset( (char *)n, '\0', sizeof(struct nmb_name) );
1202 fstrcpy(unix_name, name);
1203 strupper_m(unix_name);
1204 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1205 n->name_type = (unsigned int)type & 0xFF;
1206 push_ascii(n->scope, lp_netbios_scope(), 64, STR_TERMINATE);
1209 static bool do_nodestatus(struct tevent_context *ev_ctx,
1210 struct messaging_context *msg_ctx,
1211 const struct server_id pid,
1212 const int argc, const char **argv)
1214 struct packet_struct p;
1217 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1223 p.ip = interpret_addr2(argv[1]);
1225 p.packet_type = NMB_PACKET;
1227 p.packet.nmb.header.name_trn_id = 10;
1228 p.packet.nmb.header.opcode = 0;
1229 p.packet.nmb.header.response = False;
1230 p.packet.nmb.header.nm_flags.bcast = False;
1231 p.packet.nmb.header.nm_flags.recursion_available = False;
1232 p.packet.nmb.header.nm_flags.recursion_desired = False;
1233 p.packet.nmb.header.nm_flags.trunc = False;
1234 p.packet.nmb.header.nm_flags.authoritative = False;
1235 p.packet.nmb.header.rcode = 0;
1236 p.packet.nmb.header.qdcount = 1;
1237 p.packet.nmb.header.ancount = 0;
1238 p.packet.nmb.header.nscount = 0;
1239 p.packet.nmb.header.arcount = 0;
1240 my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1241 p.packet.nmb.question.question_type = 0x21;
1242 p.packet.nmb.question.question_class = 0x1;
1244 return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1247 /* A list of message type supported */
1249 static const struct {
1250 const char *name; /* Option name */
1251 bool (*fn)(struct tevent_context *ev_ctx,
1252 struct messaging_context *msg_ctx,
1253 const struct server_id pid,
1254 const int argc, const char **argv);
1255 const char *help; /* Short help text */
1257 { "debug", do_debug, "Set debuglevel" },
1258 { "idmap", do_idmap, "Manipulate idmap cache" },
1259 { "force-election", do_election,
1260 "Force a browse election" },
1261 { "ping", do_ping, "Elicit a response" },
1262 { "profile", do_profile, "" },
1263 { "inject", do_inject_fault,
1264 "Inject a fatal signal into a running smbd"},
1265 { "stacktrace", do_daemon_stack_trace,
1266 "Display a stack trace of a daemon" },
1267 { "profilelevel", do_profilelevel, "" },
1268 { "debuglevel", do_debuglevel, "Display current debuglevels" },
1269 { "printnotify", do_printnotify, "Send a print notify message" },
1270 { "close-share", do_closeshare, "Forcibly disconnect a share" },
1271 { "ip-dropped", do_ip_dropped, "Tell winbind that an IP got dropped" },
1272 { "lockretry", do_lockretry, "Force a blocking lock retry" },
1273 { "brl-revalidate", do_brl_revalidate, "Revalidate all brl entries" },
1274 { "pool-usage", do_poolusage, "Display talloc memory usage" },
1275 { "dmalloc-mark", do_dmalloc_mark, "" },
1276 { "dmalloc-log-changed", do_dmalloc_changed, "" },
1277 { "shutdown", do_shutdown, "Shut down daemon" },
1278 { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
1279 { "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
1280 { "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
1281 { "online", do_winbind_online, "Ask winbind to go into online state"},
1282 { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
1283 { "onlinestatus", do_winbind_onlinestatus, "Request winbind online status"},
1284 { "dump-event-list", do_dump_event_list, "Dump event list"},
1285 { "validate-cache" , do_winbind_validate_cache,
1286 "Validate winbind's credential cache" },
1287 { "dump-domain-list", do_winbind_dump_domain_list, "Dump winbind domain list"},
1288 { "noop", do_noop, "Do nothing" },
1292 /* Display usage information */
1294 static void usage(poptContext pc)
1298 poptPrintHelp(pc, stderr, 0);
1300 fprintf(stderr, "\n");
1301 fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1304 fprintf(stderr, "\n");
1305 fprintf(stderr, "<message-type> is one of:\n");
1307 for (i = 0; msg_types[i].name; i++)
1308 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name,
1311 fprintf(stderr, "\n");
1316 /* Return the pid number for a string destination */
1318 static struct server_id parse_dest(struct messaging_context *msg,
1321 struct server_id result = {-1};
1324 /* Zero is a special return value for broadcast to all processes */
1326 if (strequal(dest, "all")) {
1327 return interpret_pid(MSG_BROADCAST_PID_STR);
1330 /* Try self - useful for testing */
1332 if (strequal(dest, "self")) {
1333 return messaging_server_id(msg);
1336 /* Fix winbind typo. */
1337 if (strequal(dest, "winbind")) {
1341 /* Check for numeric pid number */
1342 result = interpret_pid(dest);
1344 /* Zero isn't valid if not "all". */
1345 if (result.pid && procid_valid(&result)) {
1349 /* Look up other destinations in pidfile directory */
1351 if ((pid = pidfile_pid(dest)) != 0) {
1352 return pid_to_procid(pid);
1355 fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1360 /* Execute smbcontrol command */
1362 static bool do_command(struct tevent_context *ev_ctx,
1363 struct messaging_context *msg_ctx,
1364 int argc, const char **argv)
1366 const char *dest = argv[0], *command = argv[1];
1367 struct server_id pid;
1370 /* Check destination */
1372 pid = parse_dest(msg_ctx, dest);
1373 if (!procid_valid(&pid)) {
1379 for (i = 0; msg_types[i].name; i++) {
1380 if (strequal(command, msg_types[i].name))
1381 return msg_types[i].fn(ev_ctx, msg_ctx, pid,
1382 argc - 1, argv + 1);
1385 fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1390 static void smbcontrol_help(poptContext pc,
1391 enum poptCallbackReason preason,
1392 struct poptOption * poption,
1396 if (poption->shortName != '?') {
1397 poptPrintUsage(pc, stdout, 0);
1405 struct poptOption help_options[] = {
1406 { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1408 { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1409 { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1415 int main(int argc, const char **argv)
1419 struct tevent_context *evt_ctx;
1420 struct messaging_context *msg_ctx;
1422 static struct poptOption long_options[] = {
1424 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1425 0, "Help options:", NULL },
1426 { "timeout", 't', POPT_ARG_INT, &timeout, 't',
1427 "Set timeout value in seconds", "TIMEOUT" },
1432 TALLOC_CTX *frame = talloc_stackframe();
1437 setup_logging(argv[0], DEBUG_STDOUT);
1439 /* Parse command line arguments using popt */
1441 pc = poptGetContext(
1442 "smbcontrol", argc, (const char **)argv, long_options, 0);
1444 poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1450 while ((opt = poptGetNextOpt(pc)) != -1) {
1452 case 't': /* --timeout */
1455 fprintf(stderr, "Invalid option\n");
1456 poptPrintHelp(pc, stderr, 0);
1461 /* We should now have the remaining command line arguments in
1462 argv. The argc parameter should have been decremented to the
1463 correct value in the above switch statement. */
1465 argv = (const char **)poptGetArgs(pc);
1468 while (argv[argc] != NULL) {
1476 lp_load_global(get_dyn_CONFIGFILE());
1478 /* Need to invert sense of return code -- samba
1479 * routines mostly return True==1 for success, but
1482 if (!(evt_ctx = tevent_context_init(NULL)) ||
1483 !(msg_ctx = messaging_init(NULL, evt_ctx))) {
1484 fprintf(stderr, "could not init messaging context\n");
1489 ret = !do_command(evt_ctx, msg_ctx, argc, argv);