s3:registry: extract the reg_cachehook prototypes into their own header.
[Samba/gebeck_regimport.git] / source3 / utils / smbcontrol.c
blob9ddabc87574755b030f6eac8356eef882ebc0339
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 "librpc/gen_ndr/messaging.h"
29 #if HAVE_LIBUNWIND_H
30 #include <libunwind.h>
31 #endif
33 #if HAVE_LIBUNWIND_PTRACE_H
34 #include <libunwind-ptrace.h>
35 #endif
37 #if HAVE_SYS_PTRACE_H
38 #include <sys/ptrace.h>
39 #endif
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)
54 bool ret;
55 int n_sent = 0;
57 if (procid_to_pid(&pid) != 0)
58 return NT_STATUS_IS_OK(
59 messaging_send_buf(msg_ctx, pid, msg_type,
60 (uint8 *)buf, len));
62 ret = message_send_all(msg_ctx, msg_type, buf, len, &n_sent);
63 DEBUG(10,("smbcontrol/send_message: broadcast message to "
64 "%d processes\n", n_sent));
66 return ret;
69 static void smbcontrol_timeout(struct tevent_context *event_ctx,
70 struct tevent_timer *te,
71 struct timeval now,
72 void *private_data)
74 bool *timed_out = (bool *)private_data;
75 TALLOC_FREE(te);
76 *timed_out = True;
79 /* Wait for one or more reply messages */
81 static void wait_replies(struct messaging_context *msg_ctx,
82 bool multiple_replies)
84 struct tevent_timer *te;
85 bool timed_out = False;
87 if (!(te = tevent_add_timer(messaging_event_context(msg_ctx), NULL,
88 timeval_current_ofs(timeout, 0),
89 smbcontrol_timeout, (void *)&timed_out))) {
90 DEBUG(0, ("tevent_add_timer failed\n"));
91 return;
94 while (!timed_out) {
95 int ret;
96 if (num_replies > 0 && !multiple_replies)
97 break;
98 ret = tevent_loop_once(messaging_event_context(msg_ctx));
99 if (ret != 0) {
100 break;
105 /* Message handler callback that displays the PID and a string on stdout */
107 static void print_pid_string_cb(struct messaging_context *msg,
108 void *private_data,
109 uint32_t msg_type,
110 struct server_id pid,
111 DATA_BLOB *data)
113 char *pidstr;
115 pidstr = procid_str(talloc_tos(), &pid);
116 printf("PID %s: %.*s", pidstr, (int)data->length,
117 (const char *)data->data);
118 TALLOC_FREE(pidstr);
119 num_replies++;
122 /* Message handler callback that displays a string on stdout */
124 static void print_string_cb(struct messaging_context *msg,
125 void *private_data,
126 uint32_t msg_type,
127 struct server_id pid,
128 DATA_BLOB *data)
130 printf("%*s", (int)data->length, (const char *)data->data);
131 num_replies++;
134 /* Send no message. Useful for testing. */
136 static bool do_noop(struct messaging_context *msg_ctx,
137 const struct server_id pid,
138 const int argc, const char **argv)
140 if (argc != 1) {
141 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
142 return False;
145 /* Move along, nothing to see here */
147 return True;
150 /* Send a debug string */
152 static bool do_debug(struct messaging_context *msg_ctx,
153 const struct server_id pid,
154 const int argc, const char **argv)
156 if (argc != 2) {
157 fprintf(stderr, "Usage: smbcontrol <dest> debug "
158 "<debug-string>\n");
159 return False;
162 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
163 strlen(argv[1]) + 1);
166 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
168 /* Return the name of a process given it's PID. This will only work on Linux,
169 * but that's probably moot since this whole stack tracing implementatino is
170 * Linux-specific anyway.
172 static const char * procname(pid_t pid, char * buf, size_t bufsz)
174 char path[64];
175 FILE * fp;
177 snprintf(path, sizeof(path), "/proc/%llu/cmdline",
178 (unsigned long long)pid);
179 if ((fp = fopen(path, "r")) == NULL) {
180 return NULL;
183 fgets(buf, bufsz, fp);
185 fclose(fp);
186 return buf;
189 static void print_stack_trace(pid_t pid, int * count)
191 void * pinfo = NULL;
192 unw_addr_space_t aspace = NULL;
193 unw_cursor_t cursor;
194 unw_word_t ip, sp;
196 char nbuf[256];
197 unw_word_t off;
199 int ret;
201 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
202 fprintf(stderr,
203 "Failed to attach to process %llu: %s\n",
204 (unsigned long long)pid, strerror(errno));
205 return;
208 /* Wait until the attach is complete. */
209 waitpid(pid, NULL, 0);
211 if (((pinfo = _UPT_create(pid)) == NULL) ||
212 ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
213 /* Probably out of memory. */
214 fprintf(stderr,
215 "Unable to initialize stack unwind for process %llu\n",
216 (unsigned long long)pid);
217 goto cleanup;
220 if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
221 fprintf(stderr,
222 "Unable to unwind stack for process %llu: %s\n",
223 (unsigned long long)pid, unw_strerror(ret));
224 goto cleanup;
227 if (*count > 0) {
228 printf("\n");
231 if (procname(pid, nbuf, sizeof(nbuf))) {
232 printf("Stack trace for process %llu (%s):\n",
233 (unsigned long long)pid, nbuf);
234 } else {
235 printf("Stack trace for process %llu:\n",
236 (unsigned long long)pid);
239 while (unw_step(&cursor) > 0) {
240 ip = sp = off = 0;
241 unw_get_reg(&cursor, UNW_REG_IP, &ip);
242 unw_get_reg(&cursor, UNW_REG_SP, &sp);
244 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
245 if (ret != 0 && ret != -UNW_ENOMEM) {
246 snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
248 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
249 nbuf, (long long)off, (long long)ip,
250 (long long)sp);
253 (*count)++;
255 cleanup:
256 if (aspace) {
257 unw_destroy_addr_space(aspace);
260 if (pinfo) {
261 _UPT_destroy(pinfo);
264 ptrace(PTRACE_DETACH, pid, NULL, NULL);
267 static int stack_trace_connection(const struct connections_key *key,
268 const struct connections_data *crec,
269 void *priv)
271 print_stack_trace(procid_to_pid(&crec->pid), (int *)priv);
273 return 0;
276 static bool do_daemon_stack_trace(struct messaging_context *msg_ctx,
277 const struct server_id pid,
278 const int argc, const char **argv)
280 pid_t dest;
281 int count = 0;
283 if (argc != 1) {
284 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
285 return False;
288 dest = procid_to_pid(&pid);
290 if (dest != 0) {
291 /* It would be nice to be able to make sure that this PID is
292 * the PID of a smbd/winbind/nmbd process, not some random PID
293 * the user liked the look of. It doesn't seem like it's worth
294 * the effort at the moment, however.
296 print_stack_trace(dest, &count);
297 } else {
298 connections_forall_read(stack_trace_connection, &count);
301 return True;
304 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
306 static bool do_daemon_stack_trace(struct messaging_context *msg_ctx,
307 const struct server_id pid,
308 const int argc, const char **argv)
310 fprintf(stderr,
311 "Daemon stack tracing is not supported on this platform\n");
312 return False;
315 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
317 /* Inject a fault (fatal signal) into a running smbd */
319 static bool do_inject_fault(struct messaging_context *msg_ctx,
320 const struct server_id pid,
321 const int argc, const char **argv)
323 if (argc != 2) {
324 fprintf(stderr, "Usage: smbcontrol <dest> inject "
325 "<bus|hup|term|internal|segv>\n");
326 return False;
329 #ifndef DEVELOPER
330 fprintf(stderr, "Fault injection is only available in "
331 "developer builds\n");
332 return False;
333 #else /* DEVELOPER */
335 int sig = 0;
337 if (strcmp(argv[1], "bus") == 0) {
338 sig = SIGBUS;
339 } else if (strcmp(argv[1], "hup") == 0) {
340 sig = SIGHUP;
341 } else if (strcmp(argv[1], "term") == 0) {
342 sig = SIGTERM;
343 } else if (strcmp(argv[1], "segv") == 0) {
344 sig = SIGSEGV;
345 } else if (strcmp(argv[1], "internal") == 0) {
346 /* Force an internal error, ie. an unclean exit. */
347 sig = -1;
348 } else {
349 fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
350 return False;
353 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
354 &sig, sizeof(int));
356 #endif /* DEVELOPER */
359 /* Force a browser election */
361 static bool do_election(struct messaging_context *msg_ctx,
362 const struct server_id pid,
363 const int argc, const char **argv)
365 if (argc != 1) {
366 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
367 return False;
370 return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
373 /* Ping a samba daemon process */
375 static void pong_cb(struct messaging_context *msg,
376 void *private_data,
377 uint32_t msg_type,
378 struct server_id pid,
379 DATA_BLOB *data)
381 char *src_string = procid_str(NULL, &pid);
382 printf("PONG from pid %s\n", src_string);
383 TALLOC_FREE(src_string);
384 num_replies++;
387 static bool do_ping(struct messaging_context *msg_ctx,
388 const struct server_id pid,
389 const int argc, const char **argv)
391 if (argc != 1) {
392 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
393 return False;
396 /* Send a message and register our interest in a reply */
398 if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
399 return False;
401 messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
403 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
405 /* No replies were received within the timeout period */
407 if (num_replies == 0)
408 printf("No replies received\n");
410 messaging_deregister(msg_ctx, MSG_PONG, NULL);
412 return num_replies;
415 /* Set profiling options */
417 static bool do_profile(struct messaging_context *msg_ctx,
418 const struct server_id pid,
419 const int argc, const char **argv)
421 int v;
423 if (argc != 2) {
424 fprintf(stderr, "Usage: smbcontrol <dest> profile "
425 "<off|count|on|flush>\n");
426 return False;
429 if (strcmp(argv[1], "off") == 0) {
430 v = 0;
431 } else if (strcmp(argv[1], "count") == 0) {
432 v = 1;
433 } else if (strcmp(argv[1], "on") == 0) {
434 v = 2;
435 } else if (strcmp(argv[1], "flush") == 0) {
436 v = 3;
437 } else {
438 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
439 return False;
442 return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
445 /* Return the profiling level */
447 static void profilelevel_cb(struct messaging_context *msg_ctx,
448 void *private_data,
449 uint32_t msg_type,
450 struct server_id pid,
451 DATA_BLOB *data)
453 int level;
454 const char *s;
456 num_replies++;
458 if (data->length != sizeof(int)) {
459 fprintf(stderr, "invalid message length %ld returned\n",
460 (unsigned long)data->length);
461 return;
464 memcpy(&level, data->data, sizeof(int));
466 switch (level) {
467 case 0:
468 s = "not enabled";
469 break;
470 case 1:
471 s = "off";
472 break;
473 case 3:
474 s = "count only";
475 break;
476 case 7:
477 s = "count and time";
478 break;
479 default:
480 s = "BOGUS";
481 break;
484 printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
487 static void profilelevel_rqst(struct messaging_context *msg_ctx,
488 void *private_data,
489 uint32_t msg_type,
490 struct server_id pid,
491 DATA_BLOB *data)
493 int v = 0;
495 /* Send back a dummy reply */
497 send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
500 static bool do_profilelevel(struct messaging_context *msg_ctx,
501 const struct server_id pid,
502 const int argc, const char **argv)
504 if (argc != 1) {
505 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
506 return False;
509 /* Send a message and register our interest in a reply */
511 if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
512 return False;
514 messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
515 messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
516 profilelevel_rqst);
518 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
520 /* No replies were received within the timeout period */
522 if (num_replies == 0)
523 printf("No replies received\n");
525 messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
527 return num_replies;
530 /* Display debug level settings */
532 static bool do_debuglevel(struct messaging_context *msg_ctx,
533 const struct server_id pid,
534 const int argc, const char **argv)
536 if (argc != 1) {
537 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
538 return False;
541 /* Send a message and register our interest in a reply */
543 if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
544 return False;
546 messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
548 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
550 /* No replies were received within the timeout period */
552 if (num_replies == 0)
553 printf("No replies received\n");
555 messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
557 return num_replies;
560 /* Send a print notify message */
562 static bool do_printnotify(struct messaging_context *msg_ctx,
563 const struct server_id pid,
564 const int argc, const char **argv)
566 const char *cmd;
568 /* Check for subcommand */
570 if (argc == 1) {
571 fprintf(stderr, "Must specify subcommand:\n");
572 fprintf(stderr, "\tqueuepause <printername>\n");
573 fprintf(stderr, "\tqueueresume <printername>\n");
574 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
575 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
576 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
577 fprintf(stderr, "\tprinter <printername> <comment|port|"
578 "driver> <value>\n");
580 return False;
583 cmd = argv[1];
585 if (strcmp(cmd, "queuepause") == 0) {
587 if (argc != 3) {
588 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
589 " queuepause <printername>\n");
590 return False;
593 notify_printer_status_byname(argv[2], PRINTER_STATUS_PAUSED);
595 goto send;
597 } else if (strcmp(cmd, "queueresume") == 0) {
599 if (argc != 3) {
600 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
601 " queuereume <printername>\n");
602 return False;
605 notify_printer_status_byname(argv[2], PRINTER_STATUS_OK);
607 goto send;
609 } else if (strcmp(cmd, "jobpause") == 0) {
610 int jobid;
612 if (argc != 4) {
613 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
614 " jobpause <printername> <unix-jobid>\n");
615 return False;
618 jobid = atoi(argv[3]);
620 notify_job_status_byname(
621 argv[2], jobid, JOB_STATUS_PAUSED,
622 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
624 goto send;
626 } else if (strcmp(cmd, "jobresume") == 0) {
627 int jobid;
629 if (argc != 4) {
630 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
631 " jobpause <printername> <unix-jobid>\n");
632 return False;
635 jobid = atoi(argv[3]);
637 notify_job_status_byname(
638 argv[2], jobid, JOB_STATUS_QUEUED,
639 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
641 goto send;
643 } else if (strcmp(cmd, "jobdelete") == 0) {
644 int jobid;
646 if (argc != 4) {
647 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
648 " jobpause <printername> <unix-jobid>\n");
649 return False;
652 jobid = atoi(argv[3]);
654 notify_job_status_byname(
655 argv[2], jobid, JOB_STATUS_DELETING,
656 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
658 notify_job_status_byname(
659 argv[2], jobid, JOB_STATUS_DELETING|
660 JOB_STATUS_DELETED,
661 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
663 goto send;
665 } else if (strcmp(cmd, "printer") == 0) {
666 uint32 attribute;
668 if (argc != 5) {
669 fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
670 "printer <printername> <comment|port|driver> "
671 "<value>\n");
672 return False;
675 if (strcmp(argv[3], "comment") == 0) {
676 attribute = PRINTER_NOTIFY_FIELD_COMMENT;
677 } else if (strcmp(argv[3], "port") == 0) {
678 attribute = PRINTER_NOTIFY_FIELD_PORT_NAME;
679 } else if (strcmp(argv[3], "driver") == 0) {
680 attribute = PRINTER_NOTIFY_FIELD_DRIVER_NAME;
681 } else {
682 fprintf(stderr, "Invalid printer command '%s'\n",
683 argv[3]);
684 return False;
687 notify_printer_byname(argv[2], attribute,
688 CONST_DISCARD(char *, argv[4]));
690 goto send;
693 fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
694 return False;
696 send:
697 print_notify_send_messages(msg_ctx, 0);
698 return True;
701 /* Close a share */
703 static bool do_closeshare(struct messaging_context *msg_ctx,
704 const struct server_id pid,
705 const int argc, const char **argv)
707 if (argc != 2) {
708 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
709 "<sharename>\n");
710 return False;
713 return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
714 strlen(argv[1]) + 1);
717 /* force a blocking lock retry */
719 static bool do_lockretry(struct messaging_context *msg_ctx,
720 const struct server_id pid,
721 const int argc, const char **argv)
723 if (argc != 1) {
724 fprintf(stderr, "Usage: smbcontrol <dest> lockretry\n");
725 return False;
728 return send_message(msg_ctx, pid, MSG_SMB_UNLOCK, NULL, 0);
731 /* force a validation of all brl entries, including re-sends. */
733 static bool do_brl_revalidate(struct messaging_context *msg_ctx,
734 const struct server_id pid,
735 const int argc, const char **argv)
737 if (argc != 1) {
738 fprintf(stderr, "Usage: smbcontrol <dest> brl-revalidate\n");
739 return False;
742 return send_message(msg_ctx, pid, MSG_SMB_BRL_VALIDATE, NULL, 0);
745 /* Force a SAM synchronisation */
747 static bool do_samsync(struct messaging_context *msg_ctx,
748 const struct server_id pid,
749 const int argc, const char **argv)
751 if (argc != 1) {
752 fprintf(stderr, "Usage: smbcontrol <dest> samsync\n");
753 return False;
756 return send_message(msg_ctx, pid, MSG_SMB_SAM_SYNC, NULL, 0);
759 /* Force a SAM replication */
761 static bool do_samrepl(struct messaging_context *msg_ctx,
762 const struct server_id pid,
763 const int argc, const char **argv)
765 if (argc != 1) {
766 fprintf(stderr, "Usage: smbcontrol <dest> samrepl\n");
767 return False;
770 return send_message(msg_ctx, pid, MSG_SMB_SAM_REPL, NULL, 0);
773 /* Display talloc pool usage */
775 static bool do_poolusage(struct messaging_context *msg_ctx,
776 const struct server_id pid,
777 const int argc, const char **argv)
779 if (argc != 1) {
780 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
781 return False;
784 messaging_register(msg_ctx, NULL, MSG_POOL_USAGE, print_string_cb);
786 /* Send a message and register our interest in a reply */
788 if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0))
789 return False;
791 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
793 /* No replies were received within the timeout period */
795 if (num_replies == 0)
796 printf("No replies received\n");
798 messaging_deregister(msg_ctx, MSG_POOL_USAGE, NULL);
800 return num_replies;
803 /* Perform a dmalloc mark */
805 static bool do_dmalloc_mark(struct messaging_context *msg_ctx,
806 const struct server_id pid,
807 const int argc, const char **argv)
809 if (argc != 1) {
810 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
811 return False;
814 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
817 /* Perform a dmalloc changed */
819 static bool do_dmalloc_changed(struct messaging_context *msg_ctx,
820 const struct server_id pid,
821 const int argc, const char **argv)
823 if (argc != 1) {
824 fprintf(stderr, "Usage: smbcontrol <dest> "
825 "dmalloc-log-changed\n");
826 return False;
829 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
830 NULL, 0);
833 /* Shutdown a server process */
835 static bool do_shutdown(struct messaging_context *msg_ctx,
836 const struct server_id pid,
837 const int argc, const char **argv)
839 if (argc != 1) {
840 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
841 return False;
844 return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
847 /* Notify a driver upgrade */
849 static bool do_drvupgrade(struct messaging_context *msg_ctx,
850 const struct server_id pid,
851 const int argc, const char **argv)
853 if (argc != 2) {
854 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
855 "<driver-name>\n");
856 return False;
859 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
860 strlen(argv[1]) + 1);
863 static bool do_winbind_online(struct messaging_context *msg_ctx,
864 const struct server_id pid,
865 const int argc, const char **argv)
867 TDB_CONTEXT *tdb;
869 if (argc != 1) {
870 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
871 return False;
874 /* Remove the entry in the winbindd_cache tdb to tell a later
875 starting winbindd that we're online. */
877 tdb = tdb_open_log(cache_path("winbindd_cache.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
878 if (!tdb) {
879 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
880 cache_path("winbindd_cache.tdb"));
881 return False;
884 tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
885 tdb_close(tdb);
887 return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
890 static bool do_winbind_offline(struct messaging_context *msg_ctx,
891 const struct server_id pid,
892 const int argc, const char **argv)
894 TDB_CONTEXT *tdb;
895 bool ret = False;
896 int retry = 0;
898 if (argc != 1) {
899 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
900 return False;
903 /* Create an entry in the winbindd_cache tdb to tell a later
904 starting winbindd that we're offline. We may actually create
905 it here... */
907 tdb = tdb_open_log(cache_path("winbindd_cache.tdb"),
908 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
909 TDB_DEFAULT /* TDB_CLEAR_IF_FIRST */, O_RDWR|O_CREAT, 0600);
911 if (!tdb) {
912 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
913 cache_path("winbindd_cache.tdb"));
914 return False;
917 /* There's a potential race condition that if a child
918 winbindd detects a domain is online at the same time
919 we're trying to tell it to go offline that it might
920 delete the record we add between us adding it and
921 sending the message. Minimize this by retrying up to
922 5 times. */
924 for (retry = 0; retry < 5; retry++) {
925 TDB_DATA d;
926 uint8 buf[4];
928 ZERO_STRUCT(d);
930 SIVAL(buf, 0, time(NULL));
931 d.dptr = buf;
932 d.dsize = 4;
934 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
936 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
937 NULL, 0);
939 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
940 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
942 if (!d.dptr || d.dsize != 4) {
943 SAFE_FREE(d.dptr);
944 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
945 } else {
946 SAFE_FREE(d.dptr);
947 break;
951 tdb_close(tdb);
952 return ret;
955 static bool do_winbind_onlinestatus(struct messaging_context *msg_ctx,
956 const struct server_id pid,
957 const int argc, const char **argv)
959 struct server_id myid;
961 myid = procid_self();
963 if (argc != 1) {
964 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
965 return False;
968 messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
969 print_pid_string_cb);
971 if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, &myid,
972 sizeof(myid)))
973 return False;
975 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
977 /* No replies were received within the timeout period */
979 if (num_replies == 0)
980 printf("No replies received\n");
982 messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
984 return num_replies;
987 static bool do_dump_event_list(struct messaging_context *msg_ctx,
988 const struct server_id pid,
989 const int argc, const char **argv)
991 struct server_id myid;
993 myid = procid_self();
995 if (argc != 1) {
996 fprintf(stderr, "Usage: smbcontrol <dest> dump-event-list\n");
997 return False;
1000 return send_message(msg_ctx, pid, MSG_DUMP_EVENT_LIST, NULL, 0);
1003 static bool do_winbind_dump_domain_list(struct messaging_context *msg_ctx,
1004 const struct server_id pid,
1005 const int argc, const char **argv)
1007 const char *domain = NULL;
1008 int domain_len = 0;
1009 struct server_id myid;
1010 uint8_t *buf = NULL;
1011 int buf_len = 0;
1013 myid = procid_self();
1015 if (argc < 1 || argc > 2) {
1016 fprintf(stderr, "Usage: smbcontrol <dest> dump_domain_list "
1017 "<domain>\n");
1018 return false;
1021 if (argc == 2) {
1022 domain = argv[1];
1023 domain_len = strlen(argv[1]) + 1;
1026 messaging_register(msg_ctx, NULL, MSG_WINBIND_DUMP_DOMAIN_LIST,
1027 print_pid_string_cb);
1029 buf_len = sizeof(myid)+domain_len;
1030 buf = SMB_MALLOC_ARRAY(uint8_t, buf_len);
1031 if (!buf) {
1032 return false;
1035 memcpy(buf, &myid, sizeof(myid));
1036 memcpy(&buf[sizeof(myid)], domain, domain_len);
1038 if (!send_message(msg_ctx, pid, MSG_WINBIND_DUMP_DOMAIN_LIST,
1039 buf, buf_len))
1041 SAFE_FREE(buf);
1042 return false;
1045 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1047 /* No replies were received within the timeout period */
1049 SAFE_FREE(buf);
1050 if (num_replies == 0) {
1051 printf("No replies received\n");
1054 messaging_deregister(msg_ctx, MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
1056 return num_replies;
1059 static void winbind_validate_cache_cb(struct messaging_context *msg,
1060 void *private_data,
1061 uint32_t msg_type,
1062 struct server_id pid,
1063 DATA_BLOB *data)
1065 char *src_string = procid_str(NULL, &pid);
1066 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1067 (*(data->data) == 0 ? "" : "NOT "), src_string);
1068 TALLOC_FREE(src_string);
1069 num_replies++;
1072 static bool do_winbind_validate_cache(struct messaging_context *msg_ctx,
1073 const struct server_id pid,
1074 const int argc, const char **argv)
1076 struct server_id myid = procid_self();
1078 if (argc != 1) {
1079 fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
1080 return False;
1083 messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
1084 winbind_validate_cache_cb);
1086 if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
1087 sizeof(myid))) {
1088 return False;
1091 wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1093 if (num_replies == 0) {
1094 printf("No replies received\n");
1097 messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);
1099 return num_replies;
1102 static bool do_reload_config(struct messaging_context *msg_ctx,
1103 const struct server_id pid,
1104 const int argc, const char **argv)
1106 if (argc != 1) {
1107 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1108 return False;
1111 return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1114 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1116 fstring unix_name;
1117 memset( (char *)n, '\0', sizeof(struct nmb_name) );
1118 fstrcpy(unix_name, name);
1119 strupper_m(unix_name);
1120 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1121 n->name_type = (unsigned int)type & 0xFF;
1122 push_ascii(n->scope, global_scope(), 64, STR_TERMINATE);
1125 static bool do_nodestatus(struct messaging_context *msg_ctx,
1126 const struct server_id pid,
1127 const int argc, const char **argv)
1129 struct packet_struct p;
1131 if (argc != 2) {
1132 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1133 return False;
1136 ZERO_STRUCT(p);
1138 p.ip = interpret_addr2(argv[1]);
1139 p.port = 137;
1140 p.packet_type = NMB_PACKET;
1142 p.packet.nmb.header.name_trn_id = 10;
1143 p.packet.nmb.header.opcode = 0;
1144 p.packet.nmb.header.response = False;
1145 p.packet.nmb.header.nm_flags.bcast = False;
1146 p.packet.nmb.header.nm_flags.recursion_available = False;
1147 p.packet.nmb.header.nm_flags.recursion_desired = False;
1148 p.packet.nmb.header.nm_flags.trunc = False;
1149 p.packet.nmb.header.nm_flags.authoritative = False;
1150 p.packet.nmb.header.rcode = 0;
1151 p.packet.nmb.header.qdcount = 1;
1152 p.packet.nmb.header.ancount = 0;
1153 p.packet.nmb.header.nscount = 0;
1154 p.packet.nmb.header.arcount = 0;
1155 my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1156 p.packet.nmb.question.question_type = 0x21;
1157 p.packet.nmb.question.question_class = 0x1;
1159 return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1162 /* A list of message type supported */
1164 static const struct {
1165 const char *name; /* Option name */
1166 bool (*fn)(struct messaging_context *msg_ctx,
1167 const struct server_id pid,
1168 const int argc, const char **argv);
1169 const char *help; /* Short help text */
1170 } msg_types[] = {
1171 { "debug", do_debug, "Set debuglevel" },
1172 { "force-election", do_election,
1173 "Force a browse election" },
1174 { "ping", do_ping, "Elicit a response" },
1175 { "profile", do_profile, "" },
1176 { "inject", do_inject_fault,
1177 "Inject a fatal signal into a running smbd"},
1178 { "stacktrace", do_daemon_stack_trace,
1179 "Display a stack trace of a daemon" },
1180 { "profilelevel", do_profilelevel, "" },
1181 { "debuglevel", do_debuglevel, "Display current debuglevels" },
1182 { "printnotify", do_printnotify, "Send a print notify message" },
1183 { "close-share", do_closeshare, "Forcibly disconnect a share" },
1184 { "lockretry", do_lockretry, "Force a blocking lock retry" },
1185 { "brl-revalidate", do_brl_revalidate, "Revalidate all brl entries" },
1186 { "samsync", do_samsync, "Initiate SAM synchronisation" },
1187 { "samrepl", do_samrepl, "Initiate SAM replication" },
1188 { "pool-usage", do_poolusage, "Display talloc memory usage" },
1189 { "dmalloc-mark", do_dmalloc_mark, "" },
1190 { "dmalloc-log-changed", do_dmalloc_changed, "" },
1191 { "shutdown", do_shutdown, "Shut down daemon" },
1192 { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
1193 { "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
1194 { "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
1195 { "online", do_winbind_online, "Ask winbind to go into online state"},
1196 { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
1197 { "onlinestatus", do_winbind_onlinestatus, "Request winbind online status"},
1198 { "dump-event-list", do_dump_event_list, "Dump event list"},
1199 { "validate-cache" , do_winbind_validate_cache,
1200 "Validate winbind's credential cache" },
1201 { "dump-domain-list", do_winbind_dump_domain_list, "Dump winbind domain list"},
1202 { "noop", do_noop, "Do nothing" },
1203 { NULL }
1206 /* Display usage information */
1208 static void usage(poptContext pc)
1210 int i;
1212 poptPrintHelp(pc, stderr, 0);
1214 fprintf(stderr, "\n");
1215 fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1216 "process ID\n");
1218 fprintf(stderr, "\n");
1219 fprintf(stderr, "<message-type> is one of:\n");
1221 for (i = 0; msg_types[i].name; i++)
1222 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name,
1223 msg_types[i].help);
1225 fprintf(stderr, "\n");
1227 exit(1);
1230 /* Return the pid number for a string destination */
1232 static struct server_id parse_dest(const char *dest)
1234 struct server_id result = {-1};
1235 pid_t pid;
1237 /* Zero is a special return value for broadcast to all processes */
1239 if (strequal(dest, "all")) {
1240 return interpret_pid(MSG_BROADCAST_PID_STR);
1243 /* Try self - useful for testing */
1245 if (strequal(dest, "self")) {
1246 return procid_self();
1249 /* Fix winbind typo. */
1250 if (strequal(dest, "winbind")) {
1251 dest = "winbindd";
1254 /* Check for numeric pid number */
1255 result = interpret_pid(dest);
1257 /* Zero isn't valid if not "all". */
1258 if (result.pid && procid_valid(&result)) {
1259 return result;
1262 /* Look up other destinations in pidfile directory */
1264 if ((pid = pidfile_pid(dest)) != 0) {
1265 return pid_to_procid(pid);
1268 fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1270 return result;
1273 /* Execute smbcontrol command */
1275 static bool do_command(struct messaging_context *msg_ctx,
1276 int argc, const char **argv)
1278 const char *dest = argv[0], *command = argv[1];
1279 struct server_id pid;
1280 int i;
1282 /* Check destination */
1284 pid = parse_dest(dest);
1285 if (!procid_valid(&pid)) {
1286 return False;
1289 /* Check command */
1291 for (i = 0; msg_types[i].name; i++) {
1292 if (strequal(command, msg_types[i].name))
1293 return msg_types[i].fn(msg_ctx, pid,
1294 argc - 1, argv + 1);
1297 fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1299 return False;
1302 static void smbcontrol_help(poptContext pc,
1303 enum poptCallbackReason preason,
1304 struct poptOption * poption,
1305 const char * parg,
1306 void * pdata)
1308 if (poption->shortName != '?') {
1309 poptPrintUsage(pc, stdout, 0);
1310 } else {
1311 usage(pc);
1314 exit(0);
1317 struct poptOption help_options[] = {
1318 { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1319 NULL, NULL },
1320 { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1321 { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1322 { NULL }
1325 /* Main program */
1327 int main(int argc, const char **argv)
1329 poptContext pc;
1330 int opt;
1331 struct tevent_context *evt_ctx;
1332 struct messaging_context *msg_ctx;
1334 static struct poptOption long_options[] = {
1335 /* POPT_AUTOHELP */
1336 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1337 0, "Help options:", NULL },
1338 { "timeout", 't', POPT_ARG_INT, &timeout, 't',
1339 "Set timeout value in seconds", "TIMEOUT" },
1341 POPT_COMMON_SAMBA
1342 POPT_TABLEEND
1344 TALLOC_CTX *frame = talloc_stackframe();
1345 int ret = 0;
1347 load_case_tables();
1349 setup_logging(argv[0],True);
1351 /* Parse command line arguments using popt */
1353 pc = poptGetContext(
1354 "smbcontrol", argc, (const char **)argv, long_options, 0);
1356 poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1357 "<parameters>");
1359 if (argc == 1)
1360 usage(pc);
1362 while ((opt = poptGetNextOpt(pc)) != -1) {
1363 switch(opt) {
1364 case 't': /* --timeout */
1365 break;
1366 default:
1367 fprintf(stderr, "Invalid option\n");
1368 poptPrintHelp(pc, stderr, 0);
1369 break;
1373 /* We should now have the remaining command line arguments in
1374 argv. The argc parameter should have been decremented to the
1375 correct value in the above switch statement. */
1377 argv = (const char **)poptGetArgs(pc);
1378 argc = 0;
1379 if (argv != NULL) {
1380 while (argv[argc] != NULL) {
1381 argc++;
1385 if (argc <= 1)
1386 usage(pc);
1388 lp_load(get_dyn_CONFIGFILE(),False,False,False,True);
1390 /* Need to invert sense of return code -- samba
1391 * routines mostly return True==1 for success, but
1392 * shell needs 0. */
1394 if (!(evt_ctx = tevent_context_init(NULL)) ||
1395 !(msg_ctx = messaging_init(NULL, procid_self(), evt_ctx))) {
1396 fprintf(stderr, "could not init messaging context\n");
1397 TALLOC_FREE(frame);
1398 exit(1);
1401 ret = !do_command(msg_ctx, argc, argv);
1402 TALLOC_FREE(frame);
1403 return ret;