More const fixes. Remove CONST_DISCARD.
[Samba/gebeck_regimport.git] / source3 / utils / smbcontrol.c
blob0c14985bada860806af91714c9bf62b72ae077b1
1 /*
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/>.
26 #include "includes.h"
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"
33 #include "messages.h"
35 #if HAVE_LIBUNWIND_H
36 #include <libunwind.h>
37 #endif
39 #if HAVE_LIBUNWIND_PTRACE_H
40 #include <libunwind-ptrace.h>
41 #endif
43 #if HAVE_SYS_PTRACE_H
44 #include <sys/ptrace.h>
45 #endif
47 /* Default timeout value when waiting for replies (in seconds) */
49 #define DEFAULT_TIMEOUT 10
51 static int timeout = DEFAULT_TIMEOUT;
52 static int num_replies; /* Used by message callback fns */
54 /* Send a message to a destination pid. Zero means broadcast smbd. */
56 static bool send_message(struct messaging_context *msg_ctx,
57 struct server_id pid, int msg_type,
58 const void *buf, int len)
60 bool ret;
61 int n_sent = 0;
63 if (procid_to_pid(&pid) != 0)
64 return NT_STATUS_IS_OK(
65 messaging_send_buf(msg_ctx, pid, msg_type,
66 (const uint8 *)buf, len));
68 ret = message_send_all(msg_ctx, msg_type, buf, len, &n_sent);
69 DEBUG(10,("smbcontrol/send_message: broadcast message to "
70 "%d processes\n", n_sent));
72 return ret;
75 static void smbcontrol_timeout(struct tevent_context *event_ctx,
76 struct tevent_timer *te,
77 struct timeval now,
78 void *private_data)
80 bool *timed_out = (bool *)private_data;
81 TALLOC_FREE(te);
82 *timed_out = True;
85 /* Wait for one or more reply messages */
87 static void wait_replies(struct messaging_context *msg_ctx,
88 bool multiple_replies)
90 struct tevent_timer *te;
91 bool timed_out = False;
93 if (!(te = tevent_add_timer(messaging_event_context(msg_ctx), NULL,
94 timeval_current_ofs(timeout, 0),
95 smbcontrol_timeout, (void *)&timed_out))) {
96 DEBUG(0, ("tevent_add_timer failed\n"));
97 return;
100 while (!timed_out) {
101 int ret;
102 if (num_replies > 0 && !multiple_replies)
103 break;
104 ret = tevent_loop_once(messaging_event_context(msg_ctx));
105 if (ret != 0) {
106 break;
111 /* Message handler callback that displays the PID and a string on stdout */
113 static void print_pid_string_cb(struct messaging_context *msg,
114 void *private_data,
115 uint32_t msg_type,
116 struct server_id pid,
117 DATA_BLOB *data)
119 char *pidstr;
121 pidstr = procid_str(talloc_tos(), &pid);
122 printf("PID %s: %.*s", pidstr, (int)data->length,
123 (const char *)data->data);
124 TALLOC_FREE(pidstr);
125 num_replies++;
128 /* Message handler callback that displays a string on stdout */
130 static void print_string_cb(struct messaging_context *msg,
131 void *private_data,
132 uint32_t msg_type,
133 struct server_id pid,
134 DATA_BLOB *data)
136 printf("%*s", (int)data->length, (const char *)data->data);
137 num_replies++;
140 /* Send no message. Useful for testing. */
142 static bool do_noop(struct messaging_context *msg_ctx,
143 const struct server_id pid,
144 const int argc, const char **argv)
146 if (argc != 1) {
147 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
148 return False;
151 /* Move along, nothing to see here */
153 return True;
156 /* Send a debug string */
158 static bool do_debug(struct messaging_context *msg_ctx,
159 const struct server_id pid,
160 const int argc, const char **argv)
162 if (argc != 2) {
163 fprintf(stderr, "Usage: smbcontrol <dest> debug "
164 "<debug-string>\n");
165 return False;
168 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
169 strlen(argv[1]) + 1);
173 static bool do_idmap(struct messaging_context *msg_ctx,
174 const struct server_id pid,
175 const int argc, const char **argv)
177 static const char* usage = "Usage: "
178 "smbcontrol <dest> idmap <cmd> [arg]\n"
179 "\tcmd:\tflush [gid|uid]\n"
180 "\t\tdelete \"UID <uid>\"|\"GID <gid>\"|<sid>\n"
181 "\t\tkill \"UID <uid>\"|\"GID <gid>\"|<sid>\n";
182 const char* arg = NULL;
183 int arglen = 0;
184 int msg_type;
186 switch (argc) {
187 case 2:
188 break;
189 case 3:
190 arg = argv[2];
191 arglen = strlen(arg) + 1;
192 break;
193 default:
194 fprintf(stderr, "%s", usage);
195 return false;
198 if (strcmp(argv[1], "flush") == 0) {
199 msg_type = MSG_IDMAP_FLUSH;
201 else if (strcmp(argv[1], "delete") == 0) {
202 msg_type = MSG_IDMAP_DELETE;
204 else if (strcmp(argv[1], "kill") == 0) {
205 msg_type = MSG_IDMAP_KILL;
207 else if (strcmp(argv[1], "help") == 0) {
208 fprintf(stdout, "%s", usage);
209 return true;
211 else {
212 fprintf(stderr, "%s", usage);
213 return false;
216 return send_message(msg_ctx, pid, msg_type, arg, arglen);
220 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
222 /* Return the name of a process given it's PID. This will only work on Linux,
223 * but that's probably moot since this whole stack tracing implementatino is
224 * Linux-specific anyway.
226 static const char * procname(pid_t pid, char * buf, size_t bufsz)
228 char path[64];
229 FILE * fp;
231 snprintf(path, sizeof(path), "/proc/%llu/cmdline",
232 (unsigned long long)pid);
233 if ((fp = fopen(path, "r")) == NULL) {
234 return NULL;
237 fgets(buf, bufsz, fp);
239 fclose(fp);
240 return buf;
243 static void print_stack_trace(pid_t pid, int * count)
245 void * pinfo = NULL;
246 unw_addr_space_t aspace = NULL;
247 unw_cursor_t cursor;
248 unw_word_t ip, sp;
250 char nbuf[256];
251 unw_word_t off;
253 int ret;
255 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
256 fprintf(stderr,
257 "Failed to attach to process %llu: %s\n",
258 (unsigned long long)pid, strerror(errno));
259 return;
262 /* Wait until the attach is complete. */
263 waitpid(pid, NULL, 0);
265 if (((pinfo = _UPT_create(pid)) == NULL) ||
266 ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
267 /* Probably out of memory. */
268 fprintf(stderr,
269 "Unable to initialize stack unwind for process %llu\n",
270 (unsigned long long)pid);
271 goto cleanup;
274 if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
275 fprintf(stderr,
276 "Unable to unwind stack for process %llu: %s\n",
277 (unsigned long long)pid, unw_strerror(ret));
278 goto cleanup;
281 if (*count > 0) {
282 printf("\n");
285 if (procname(pid, nbuf, sizeof(nbuf))) {
286 printf("Stack trace for process %llu (%s):\n",
287 (unsigned long long)pid, nbuf);
288 } else {
289 printf("Stack trace for process %llu:\n",
290 (unsigned long long)pid);
293 while (unw_step(&cursor) > 0) {
294 ip = sp = off = 0;
295 unw_get_reg(&cursor, UNW_REG_IP, &ip);
296 unw_get_reg(&cursor, UNW_REG_SP, &sp);
298 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
299 if (ret != 0 && ret != -UNW_ENOMEM) {
300 snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
302 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
303 nbuf, (long long)off, (long long)ip,
304 (long long)sp);
307 (*count)++;
309 cleanup:
310 if (aspace) {
311 unw_destroy_addr_space(aspace);
314 if (pinfo) {
315 _UPT_destroy(pinfo);
318 ptrace(PTRACE_DETACH, pid, NULL, NULL);
321 static int stack_trace_connection(const struct connections_key *key,
322 const struct connections_data *crec,
323 void *priv)
325 print_stack_trace(procid_to_pid(&crec->pid), (int *)priv);
327 return 0;
330 static bool do_daemon_stack_trace(struct messaging_context *msg_ctx,
331 const struct server_id pid,
332 const int argc, const char **argv)
334 pid_t dest;
335 int count = 0;
337 if (argc != 1) {
338 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
339 return False;
342 dest = procid_to_pid(&pid);
344 if (dest != 0) {
345 /* It would be nice to be able to make sure that this PID is
346 * the PID of a smbd/winbind/nmbd process, not some random PID
347 * the user liked the look of. It doesn't seem like it's worth
348 * the effort at the moment, however.
350 print_stack_trace(dest, &count);
351 } else {
352 connections_forall_read(stack_trace_connection, &count);
355 return True;
358 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
360 static bool do_daemon_stack_trace(struct messaging_context *msg_ctx,
361 const struct server_id pid,
362 const int argc, const char **argv)
364 fprintf(stderr,
365 "Daemon stack tracing is not supported on this platform\n");
366 return False;
369 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
371 /* Inject a fault (fatal signal) into a running smbd */
373 static bool do_inject_fault(struct messaging_context *msg_ctx,
374 const struct server_id pid,
375 const int argc, const char **argv)
377 if (argc != 2) {
378 fprintf(stderr, "Usage: smbcontrol <dest> inject "
379 "<bus|hup|term|internal|segv>\n");
380 return False;
383 #ifndef DEVELOPER
384 fprintf(stderr, "Fault injection is only available in "
385 "developer builds\n");
386 return False;
387 #else /* DEVELOPER */
389 int sig = 0;
391 if (strcmp(argv[1], "bus") == 0) {
392 sig = SIGBUS;
393 } else if (strcmp(argv[1], "hup") == 0) {
394 sig = SIGHUP;
395 } else if (strcmp(argv[1], "term") == 0) {
396 sig = SIGTERM;
397 } else if (strcmp(argv[1], "segv") == 0) {
398 sig = SIGSEGV;
399 } else if (strcmp(argv[1], "internal") == 0) {
400 /* Force an internal error, ie. an unclean exit. */
401 sig = -1;
402 } else {
403 fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
404 return False;
407 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
408 &sig, sizeof(int));
410 #endif /* DEVELOPER */
413 /* Force a browser election */
415 static bool do_election(struct messaging_context *msg_ctx,
416 const struct server_id pid,
417 const int argc, const char **argv)
419 if (argc != 1) {
420 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
421 return False;
424 return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
427 /* Ping a samba daemon process */
429 static void pong_cb(struct messaging_context *msg,
430 void *private_data,
431 uint32_t msg_type,
432 struct server_id pid,
433 DATA_BLOB *data)
435 char *src_string = procid_str(NULL, &pid);
436 printf("PONG from pid %s\n", src_string);
437 TALLOC_FREE(src_string);
438 num_replies++;
441 static bool do_ping(struct messaging_context *msg_ctx,
442 const struct server_id pid,
443 const int argc, const char **argv)
445 if (argc != 1) {
446 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
447 return False;
450 /* Send a message and register our interest in a reply */
452 if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
453 return False;
455 messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
457 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
459 /* No replies were received within the timeout period */
461 if (num_replies == 0)
462 printf("No replies received\n");
464 messaging_deregister(msg_ctx, MSG_PONG, NULL);
466 return num_replies;
469 /* Set profiling options */
471 static bool do_profile(struct messaging_context *msg_ctx,
472 const struct server_id pid,
473 const int argc, const char **argv)
475 int v;
477 if (argc != 2) {
478 fprintf(stderr, "Usage: smbcontrol <dest> profile "
479 "<off|count|on|flush>\n");
480 return False;
483 if (strcmp(argv[1], "off") == 0) {
484 v = 0;
485 } else if (strcmp(argv[1], "count") == 0) {
486 v = 1;
487 } else if (strcmp(argv[1], "on") == 0) {
488 v = 2;
489 } else if (strcmp(argv[1], "flush") == 0) {
490 v = 3;
491 } else {
492 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
493 return False;
496 return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
499 /* Return the profiling level */
501 static void profilelevel_cb(struct messaging_context *msg_ctx,
502 void *private_data,
503 uint32_t msg_type,
504 struct server_id pid,
505 DATA_BLOB *data)
507 int level;
508 const char *s;
510 num_replies++;
512 if (data->length != sizeof(int)) {
513 fprintf(stderr, "invalid message length %ld returned\n",
514 (unsigned long)data->length);
515 return;
518 memcpy(&level, data->data, sizeof(int));
520 switch (level) {
521 case 0:
522 s = "not enabled";
523 break;
524 case 1:
525 s = "off";
526 break;
527 case 3:
528 s = "count only";
529 break;
530 case 7:
531 s = "count and time";
532 break;
533 default:
534 s = "BOGUS";
535 break;
538 printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
541 static void profilelevel_rqst(struct messaging_context *msg_ctx,
542 void *private_data,
543 uint32_t msg_type,
544 struct server_id pid,
545 DATA_BLOB *data)
547 int v = 0;
549 /* Send back a dummy reply */
551 send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
554 static bool do_profilelevel(struct messaging_context *msg_ctx,
555 const struct server_id pid,
556 const int argc, const char **argv)
558 if (argc != 1) {
559 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
560 return False;
563 /* Send a message and register our interest in a reply */
565 if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
566 return False;
568 messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
569 messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
570 profilelevel_rqst);
572 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
574 /* No replies were received within the timeout period */
576 if (num_replies == 0)
577 printf("No replies received\n");
579 messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
581 return num_replies;
584 /* Display debug level settings */
586 static bool do_debuglevel(struct messaging_context *msg_ctx,
587 const struct server_id pid,
588 const int argc, const char **argv)
590 if (argc != 1) {
591 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
592 return False;
595 /* Send a message and register our interest in a reply */
597 if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
598 return False;
600 messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
602 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
604 /* No replies were received within the timeout period */
606 if (num_replies == 0)
607 printf("No replies received\n");
609 messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
611 return num_replies;
614 /* Send a print notify message */
616 static bool do_printnotify(struct messaging_context *msg_ctx,
617 const struct server_id pid,
618 const int argc, const char **argv)
620 const char *cmd;
622 /* Check for subcommand */
624 if (argc == 1) {
625 fprintf(stderr, "Must specify subcommand:\n");
626 fprintf(stderr, "\tqueuepause <printername>\n");
627 fprintf(stderr, "\tqueueresume <printername>\n");
628 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
629 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
630 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
631 fprintf(stderr, "\tprinter <printername> <comment|port|"
632 "driver> <value>\n");
634 return False;
637 cmd = argv[1];
639 if (strcmp(cmd, "queuepause") == 0) {
641 if (argc != 3) {
642 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
643 " queuepause <printername>\n");
644 return False;
647 notify_printer_status_byname(messaging_event_context(msg_ctx),
648 msg_ctx, argv[2],
649 PRINTER_STATUS_PAUSED);
651 goto send;
653 } else if (strcmp(cmd, "queueresume") == 0) {
655 if (argc != 3) {
656 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
657 " queuereume <printername>\n");
658 return False;
661 notify_printer_status_byname(messaging_event_context(msg_ctx),
662 msg_ctx, argv[2],
663 PRINTER_STATUS_OK);
665 goto send;
667 } else if (strcmp(cmd, "jobpause") == 0) {
668 int jobid;
670 if (argc != 4) {
671 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
672 " jobpause <printername> <unix-jobid>\n");
673 return False;
676 jobid = atoi(argv[3]);
678 notify_job_status_byname(
679 messaging_event_context(msg_ctx), msg_ctx,
680 argv[2], jobid, JOB_STATUS_PAUSED,
681 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
683 goto send;
685 } else if (strcmp(cmd, "jobresume") == 0) {
686 int jobid;
688 if (argc != 4) {
689 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
690 " jobpause <printername> <unix-jobid>\n");
691 return False;
694 jobid = atoi(argv[3]);
696 notify_job_status_byname(
697 messaging_event_context(msg_ctx), msg_ctx,
698 argv[2], jobid, JOB_STATUS_QUEUED,
699 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
701 goto send;
703 } else if (strcmp(cmd, "jobdelete") == 0) {
704 int jobid;
706 if (argc != 4) {
707 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
708 " jobpause <printername> <unix-jobid>\n");
709 return False;
712 jobid = atoi(argv[3]);
714 notify_job_status_byname(
715 messaging_event_context(msg_ctx), msg_ctx,
716 argv[2], jobid, JOB_STATUS_DELETING,
717 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
719 notify_job_status_byname(
720 messaging_event_context(msg_ctx), msg_ctx,
721 argv[2], jobid, JOB_STATUS_DELETING|
722 JOB_STATUS_DELETED,
723 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
725 goto send;
727 } else if (strcmp(cmd, "printer") == 0) {
728 uint32 attribute;
730 if (argc != 5) {
731 fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
732 "printer <printername> <comment|port|driver> "
733 "<value>\n");
734 return False;
737 if (strcmp(argv[3], "comment") == 0) {
738 attribute = PRINTER_NOTIFY_FIELD_COMMENT;
739 } else if (strcmp(argv[3], "port") == 0) {
740 attribute = PRINTER_NOTIFY_FIELD_PORT_NAME;
741 } else if (strcmp(argv[3], "driver") == 0) {
742 attribute = PRINTER_NOTIFY_FIELD_DRIVER_NAME;
743 } else {
744 fprintf(stderr, "Invalid printer command '%s'\n",
745 argv[3]);
746 return False;
749 notify_printer_byname(messaging_event_context(msg_ctx),
750 msg_ctx, argv[2], attribute,
751 discard_const_p(char, argv[4]));
753 goto send;
756 fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
757 return False;
759 send:
760 print_notify_send_messages(msg_ctx, 0);
761 return True;
764 /* Close a share */
766 static bool do_closeshare(struct messaging_context *msg_ctx,
767 const struct server_id pid,
768 const int argc, const char **argv)
770 if (argc != 2) {
771 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
772 "<sharename>\n");
773 return False;
776 return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
777 strlen(argv[1]) + 1);
780 /* Tell winbindd an IP got dropped */
782 static bool do_ip_dropped(struct messaging_context *msg_ctx,
783 const struct server_id pid,
784 const int argc, const char **argv)
786 if (argc != 2) {
787 fprintf(stderr, "Usage: smbcontrol <dest> ip-dropped "
788 "<ip-address>\n");
789 return False;
792 return send_message(msg_ctx, pid, MSG_WINBIND_IP_DROPPED, argv[1],
793 strlen(argv[1]) + 1);
796 /* force a blocking lock retry */
798 static bool do_lockretry(struct messaging_context *msg_ctx,
799 const struct server_id pid,
800 const int argc, const char **argv)
802 if (argc != 1) {
803 fprintf(stderr, "Usage: smbcontrol <dest> lockretry\n");
804 return False;
807 return send_message(msg_ctx, pid, MSG_SMB_UNLOCK, NULL, 0);
810 /* force a validation of all brl entries, including re-sends. */
812 static bool do_brl_revalidate(struct messaging_context *msg_ctx,
813 const struct server_id pid,
814 const int argc, const char **argv)
816 if (argc != 1) {
817 fprintf(stderr, "Usage: smbcontrol <dest> brl-revalidate\n");
818 return False;
821 return send_message(msg_ctx, pid, MSG_SMB_BRL_VALIDATE, NULL, 0);
824 /* Force a SAM synchronisation */
826 static bool do_samsync(struct messaging_context *msg_ctx,
827 const struct server_id pid,
828 const int argc, const char **argv)
830 if (argc != 1) {
831 fprintf(stderr, "Usage: smbcontrol <dest> samsync\n");
832 return False;
835 return send_message(msg_ctx, pid, MSG_SMB_SAM_SYNC, NULL, 0);
838 /* Force a SAM replication */
840 static bool do_samrepl(struct messaging_context *msg_ctx,
841 const struct server_id pid,
842 const int argc, const char **argv)
844 if (argc != 1) {
845 fprintf(stderr, "Usage: smbcontrol <dest> samrepl\n");
846 return False;
849 return send_message(msg_ctx, pid, MSG_SMB_SAM_REPL, NULL, 0);
852 /* Display talloc pool usage */
854 static bool do_poolusage(struct messaging_context *msg_ctx,
855 const struct server_id pid,
856 const int argc, const char **argv)
858 if (argc != 1) {
859 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
860 return False;
863 messaging_register(msg_ctx, NULL, MSG_POOL_USAGE, print_string_cb);
865 /* Send a message and register our interest in a reply */
867 if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0))
868 return False;
870 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
872 /* No replies were received within the timeout period */
874 if (num_replies == 0)
875 printf("No replies received\n");
877 messaging_deregister(msg_ctx, MSG_POOL_USAGE, NULL);
879 return num_replies;
882 /* Perform a dmalloc mark */
884 static bool do_dmalloc_mark(struct messaging_context *msg_ctx,
885 const struct server_id pid,
886 const int argc, const char **argv)
888 if (argc != 1) {
889 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
890 return False;
893 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
896 /* Perform a dmalloc changed */
898 static bool do_dmalloc_changed(struct messaging_context *msg_ctx,
899 const struct server_id pid,
900 const int argc, const char **argv)
902 if (argc != 1) {
903 fprintf(stderr, "Usage: smbcontrol <dest> "
904 "dmalloc-log-changed\n");
905 return False;
908 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
909 NULL, 0);
912 /* Shutdown a server process */
914 static bool do_shutdown(struct messaging_context *msg_ctx,
915 const struct server_id pid,
916 const int argc, const char **argv)
918 if (argc != 1) {
919 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
920 return False;
923 return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
926 /* Notify a driver upgrade */
928 static bool do_drvupgrade(struct messaging_context *msg_ctx,
929 const struct server_id pid,
930 const int argc, const char **argv)
932 if (argc != 2) {
933 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
934 "<driver-name>\n");
935 return False;
938 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
939 strlen(argv[1]) + 1);
942 static bool do_winbind_online(struct messaging_context *msg_ctx,
943 const struct server_id pid,
944 const int argc, const char **argv)
946 TDB_CONTEXT *tdb;
948 if (argc != 1) {
949 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
950 return False;
953 /* Remove the entry in the winbindd_cache tdb to tell a later
954 starting winbindd that we're online. */
956 tdb = tdb_open_log(cache_path("winbindd_cache.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
957 if (!tdb) {
958 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
959 cache_path("winbindd_cache.tdb"));
960 return False;
963 tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
964 tdb_close(tdb);
966 return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
969 static bool do_winbind_offline(struct messaging_context *msg_ctx,
970 const struct server_id pid,
971 const int argc, const char **argv)
973 TDB_CONTEXT *tdb;
974 bool ret = False;
975 int retry = 0;
977 if (argc != 1) {
978 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
979 return False;
982 /* Create an entry in the winbindd_cache tdb to tell a later
983 starting winbindd that we're offline. We may actually create
984 it here... */
986 tdb = tdb_open_log(cache_path("winbindd_cache.tdb"),
987 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
988 TDB_DEFAULT|TDB_INCOMPATIBLE_HASH /* TDB_CLEAR_IF_FIRST */,
989 O_RDWR|O_CREAT, 0600);
991 if (!tdb) {
992 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
993 cache_path("winbindd_cache.tdb"));
994 return False;
997 /* There's a potential race condition that if a child
998 winbindd detects a domain is online at the same time
999 we're trying to tell it to go offline that it might
1000 delete the record we add between us adding it and
1001 sending the message. Minimize this by retrying up to
1002 5 times. */
1004 for (retry = 0; retry < 5; retry++) {
1005 TDB_DATA d;
1006 uint8 buf[4];
1008 ZERO_STRUCT(d);
1010 SIVAL(buf, 0, time(NULL));
1011 d.dptr = buf;
1012 d.dsize = 4;
1014 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
1016 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
1017 NULL, 0);
1019 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
1020 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
1022 if (!d.dptr || d.dsize != 4) {
1023 SAFE_FREE(d.dptr);
1024 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
1025 } else {
1026 SAFE_FREE(d.dptr);
1027 break;
1031 tdb_close(tdb);
1032 return ret;
1035 static bool do_winbind_onlinestatus(struct messaging_context *msg_ctx,
1036 const struct server_id pid,
1037 const int argc, const char **argv)
1039 struct server_id myid;
1041 myid = messaging_server_id(msg_ctx);
1043 if (argc != 1) {
1044 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
1045 return False;
1048 messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
1049 print_pid_string_cb);
1051 if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, &myid,
1052 sizeof(myid)))
1053 return False;
1055 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1057 /* No replies were received within the timeout period */
1059 if (num_replies == 0)
1060 printf("No replies received\n");
1062 messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
1064 return num_replies;
1067 static bool do_dump_event_list(struct messaging_context *msg_ctx,
1068 const struct server_id pid,
1069 const int argc, const char **argv)
1071 struct server_id myid;
1073 myid = messaging_server_id(msg_ctx);
1075 if (argc != 1) {
1076 fprintf(stderr, "Usage: smbcontrol <dest> dump-event-list\n");
1077 return False;
1080 return send_message(msg_ctx, pid, MSG_DUMP_EVENT_LIST, NULL, 0);
1083 static bool do_winbind_dump_domain_list(struct messaging_context *msg_ctx,
1084 const struct server_id pid,
1085 const int argc, const char **argv)
1087 const char *domain = NULL;
1088 int domain_len = 0;
1089 struct server_id myid;
1090 uint8_t *buf = NULL;
1091 int buf_len = 0;
1093 myid = messaging_server_id(msg_ctx);
1095 if (argc < 1 || argc > 2) {
1096 fprintf(stderr, "Usage: smbcontrol <dest> dump-domain-list "
1097 "<domain>\n");
1098 return false;
1101 if (argc == 2) {
1102 domain = argv[1];
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);
1111 if (!buf) {
1112 return false;
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,
1119 buf, buf_len))
1121 SAFE_FREE(buf);
1122 return false;
1125 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1127 /* No replies were received within the timeout period */
1129 SAFE_FREE(buf);
1130 if (num_replies == 0) {
1131 printf("No replies received\n");
1134 messaging_deregister(msg_ctx, MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
1136 return num_replies;
1139 static void winbind_validate_cache_cb(struct messaging_context *msg,
1140 void *private_data,
1141 uint32_t msg_type,
1142 struct server_id pid,
1143 DATA_BLOB *data)
1145 char *src_string = procid_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);
1149 num_replies++;
1152 static bool do_winbind_validate_cache(struct messaging_context *msg_ctx,
1153 const struct server_id pid,
1154 const int argc, const char **argv)
1156 struct server_id myid;
1158 myid = messaging_server_id(msg_ctx);
1160 if (argc != 1) {
1161 fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
1162 return False;
1165 messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
1166 winbind_validate_cache_cb);
1168 if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
1169 sizeof(myid))) {
1170 return False;
1173 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1175 if (num_replies == 0) {
1176 printf("No replies received\n");
1179 messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);
1181 return num_replies;
1184 static bool do_reload_config(struct messaging_context *msg_ctx,
1185 const struct server_id pid,
1186 const int argc, const char **argv)
1188 if (argc != 1) {
1189 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1190 return False;
1193 return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1196 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1198 fstring unix_name;
1199 memset( (char *)n, '\0', sizeof(struct nmb_name) );
1200 fstrcpy(unix_name, name);
1201 strupper_m(unix_name);
1202 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1203 n->name_type = (unsigned int)type & 0xFF;
1204 push_ascii(n->scope, global_scope(), 64, STR_TERMINATE);
1207 static bool do_nodestatus(struct messaging_context *msg_ctx,
1208 const struct server_id pid,
1209 const int argc, const char **argv)
1211 struct packet_struct p;
1213 if (argc != 2) {
1214 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1215 return False;
1218 ZERO_STRUCT(p);
1220 p.ip = interpret_addr2(argv[1]);
1221 p.port = 137;
1222 p.packet_type = NMB_PACKET;
1224 p.packet.nmb.header.name_trn_id = 10;
1225 p.packet.nmb.header.opcode = 0;
1226 p.packet.nmb.header.response = False;
1227 p.packet.nmb.header.nm_flags.bcast = False;
1228 p.packet.nmb.header.nm_flags.recursion_available = False;
1229 p.packet.nmb.header.nm_flags.recursion_desired = False;
1230 p.packet.nmb.header.nm_flags.trunc = False;
1231 p.packet.nmb.header.nm_flags.authoritative = False;
1232 p.packet.nmb.header.rcode = 0;
1233 p.packet.nmb.header.qdcount = 1;
1234 p.packet.nmb.header.ancount = 0;
1235 p.packet.nmb.header.nscount = 0;
1236 p.packet.nmb.header.arcount = 0;
1237 my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1238 p.packet.nmb.question.question_type = 0x21;
1239 p.packet.nmb.question.question_class = 0x1;
1241 return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1244 /* A list of message type supported */
1246 static const struct {
1247 const char *name; /* Option name */
1248 bool (*fn)(struct messaging_context *msg_ctx,
1249 const struct server_id pid,
1250 const int argc, const char **argv);
1251 const char *help; /* Short help text */
1252 } msg_types[] = {
1253 { "debug", do_debug, "Set debuglevel" },
1254 { "idmap", do_idmap, "Manipulate idmap cache" },
1255 { "force-election", do_election,
1256 "Force a browse election" },
1257 { "ping", do_ping, "Elicit a response" },
1258 { "profile", do_profile, "" },
1259 { "inject", do_inject_fault,
1260 "Inject a fatal signal into a running smbd"},
1261 { "stacktrace", do_daemon_stack_trace,
1262 "Display a stack trace of a daemon" },
1263 { "profilelevel", do_profilelevel, "" },
1264 { "debuglevel", do_debuglevel, "Display current debuglevels" },
1265 { "printnotify", do_printnotify, "Send a print notify message" },
1266 { "close-share", do_closeshare, "Forcibly disconnect a share" },
1267 { "ip-dropped", do_ip_dropped, "Tell winbind that an IP got dropped" },
1268 { "lockretry", do_lockretry, "Force a blocking lock retry" },
1269 { "brl-revalidate", do_brl_revalidate, "Revalidate all brl entries" },
1270 { "samsync", do_samsync, "Initiate SAM synchronisation" },
1271 { "samrepl", do_samrepl, "Initiate SAM replication" },
1272 { "pool-usage", do_poolusage, "Display talloc memory usage" },
1273 { "dmalloc-mark", do_dmalloc_mark, "" },
1274 { "dmalloc-log-changed", do_dmalloc_changed, "" },
1275 { "shutdown", do_shutdown, "Shut down daemon" },
1276 { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
1277 { "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
1278 { "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
1279 { "online", do_winbind_online, "Ask winbind to go into online state"},
1280 { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
1281 { "onlinestatus", do_winbind_onlinestatus, "Request winbind online status"},
1282 { "dump-event-list", do_dump_event_list, "Dump event list"},
1283 { "validate-cache" , do_winbind_validate_cache,
1284 "Validate winbind's credential cache" },
1285 { "dump-domain-list", do_winbind_dump_domain_list, "Dump winbind domain list"},
1286 { "noop", do_noop, "Do nothing" },
1287 { NULL }
1290 /* Display usage information */
1292 static void usage(poptContext pc)
1294 int i;
1296 poptPrintHelp(pc, stderr, 0);
1298 fprintf(stderr, "\n");
1299 fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1300 "process ID\n");
1302 fprintf(stderr, "\n");
1303 fprintf(stderr, "<message-type> is one of:\n");
1305 for (i = 0; msg_types[i].name; i++)
1306 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name,
1307 msg_types[i].help);
1309 fprintf(stderr, "\n");
1311 exit(1);
1314 /* Return the pid number for a string destination */
1316 static struct server_id parse_dest(struct messaging_context *msg,
1317 const char *dest)
1319 struct server_id result = {-1};
1320 pid_t pid;
1322 /* Zero is a special return value for broadcast to all processes */
1324 if (strequal(dest, "all")) {
1325 return interpret_pid(MSG_BROADCAST_PID_STR);
1328 /* Try self - useful for testing */
1330 if (strequal(dest, "self")) {
1331 return messaging_server_id(msg);
1334 /* Fix winbind typo. */
1335 if (strequal(dest, "winbind")) {
1336 dest = "winbindd";
1339 /* Check for numeric pid number */
1340 result = interpret_pid(dest);
1342 /* Zero isn't valid if not "all". */
1343 if (result.pid && procid_valid(&result)) {
1344 return result;
1347 /* Look up other destinations in pidfile directory */
1349 if ((pid = pidfile_pid(dest)) != 0) {
1350 return pid_to_procid(pid);
1353 fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1355 return result;
1358 /* Execute smbcontrol command */
1360 static bool do_command(struct messaging_context *msg_ctx,
1361 int argc, const char **argv)
1363 const char *dest = argv[0], *command = argv[1];
1364 struct server_id pid;
1365 int i;
1367 /* Check destination */
1369 pid = parse_dest(msg_ctx, dest);
1370 if (!procid_valid(&pid)) {
1371 return False;
1374 /* Check command */
1376 for (i = 0; msg_types[i].name; i++) {
1377 if (strequal(command, msg_types[i].name))
1378 return msg_types[i].fn(msg_ctx, pid,
1379 argc - 1, argv + 1);
1382 fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1384 return False;
1387 static void smbcontrol_help(poptContext pc,
1388 enum poptCallbackReason preason,
1389 struct poptOption * poption,
1390 const char * parg,
1391 void * pdata)
1393 if (poption->shortName != '?') {
1394 poptPrintUsage(pc, stdout, 0);
1395 } else {
1396 usage(pc);
1399 exit(0);
1402 struct poptOption help_options[] = {
1403 { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1404 NULL, NULL },
1405 { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1406 { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1407 { NULL }
1410 /* Main program */
1412 int main(int argc, const char **argv)
1414 poptContext pc;
1415 int opt;
1416 struct tevent_context *evt_ctx;
1417 struct messaging_context *msg_ctx;
1419 static struct poptOption long_options[] = {
1420 /* POPT_AUTOHELP */
1421 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1422 0, "Help options:", NULL },
1423 { "timeout", 't', POPT_ARG_INT, &timeout, 't',
1424 "Set timeout value in seconds", "TIMEOUT" },
1426 POPT_COMMON_SAMBA
1427 POPT_TABLEEND
1429 TALLOC_CTX *frame = talloc_stackframe();
1430 int ret = 0;
1432 load_case_tables();
1434 setup_logging(argv[0], DEBUG_STDOUT);
1436 /* Parse command line arguments using popt */
1438 pc = poptGetContext(
1439 "smbcontrol", argc, (const char **)argv, long_options, 0);
1441 poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1442 "<parameters>");
1444 if (argc == 1)
1445 usage(pc);
1447 while ((opt = poptGetNextOpt(pc)) != -1) {
1448 switch(opt) {
1449 case 't': /* --timeout */
1450 break;
1451 default:
1452 fprintf(stderr, "Invalid option\n");
1453 poptPrintHelp(pc, stderr, 0);
1454 break;
1458 /* We should now have the remaining command line arguments in
1459 argv. The argc parameter should have been decremented to the
1460 correct value in the above switch statement. */
1462 argv = (const char **)poptGetArgs(pc);
1463 argc = 0;
1464 if (argv != NULL) {
1465 while (argv[argc] != NULL) {
1466 argc++;
1470 if (argc <= 1)
1471 usage(pc);
1473 lp_load(get_dyn_CONFIGFILE(),False,False,False,True);
1475 /* Need to invert sense of return code -- samba
1476 * routines mostly return True==1 for success, but
1477 * shell needs 0. */
1479 if (!(evt_ctx = tevent_context_init(NULL)) ||
1480 !(msg_ctx = messaging_init(NULL, procid_self(), evt_ctx))) {
1481 fprintf(stderr, "could not init messaging context\n");
1482 TALLOC_FREE(frame);
1483 exit(1);
1486 ret = !do_command(msg_ctx, argc, argv);
1487 TALLOC_FREE(frame);
1488 return ret;