smbXsrv_session: Remove a "can't happen" NULL check
[Samba.git] / source3 / utils / smbcontrol.c
blobb318f5547d5dd97a0e0f6a9e3aed4cc4a23e0b77
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 "lib/util/server_id.h"
29 #include "lib/cmdline/cmdline.h"
30 #include "librpc/gen_ndr/spoolss.h"
31 #include "nt_printing.h"
32 #include "printing/notify.h"
33 #include "libsmb/nmblib.h"
34 #include "messages.h"
35 #include "util_tdb.h"
36 #include "../lib/util/pidfile.h"
37 #include "serverid.h"
38 #include "lib/util/server_id_db.h"
39 #include "cmdline_contexts.h"
40 #include "lib/util/string_wrappers.h"
41 #include "lib/global_contexts.h"
42 #include "lib/param/param.h"
44 #ifdef HAVE_LIBUNWIND_H
45 #include <libunwind.h>
46 #endif
48 #ifdef HAVE_LIBUNWIND_PTRACE_H
49 #include <libunwind-ptrace.h>
50 #endif
52 #ifdef HAVE_SYS_PTRACE_H
53 #include <sys/ptrace.h>
54 #endif
56 /* Default timeout value when waiting for replies (in seconds) */
58 #define DEFAULT_TIMEOUT 10
60 static int timeout = DEFAULT_TIMEOUT;
61 static int num_replies; /* Used by message callback fns */
63 /* Send a message to a destination pid. Zero means broadcast smbd. */
65 static bool send_message(struct messaging_context *msg_ctx,
66 struct server_id pid, int msg_type,
67 const void *buf, int len)
69 if (procid_to_pid(&pid) != 0)
70 return NT_STATUS_IS_OK(
71 messaging_send_buf(msg_ctx, pid, msg_type,
72 (const uint8_t *)buf, len));
74 messaging_send_all(msg_ctx, msg_type, buf, len);
76 return true;
79 static void smbcontrol_timeout(struct tevent_context *event_ctx,
80 struct tevent_timer *te,
81 struct timeval now,
82 void *private_data)
84 bool *timed_out = (bool *)private_data;
85 TALLOC_FREE(te);
86 *timed_out = True;
89 /* Wait for one or more reply messages */
91 static void wait_replies(struct tevent_context *ev_ctx,
92 struct messaging_context *msg_ctx,
93 bool multiple_replies)
95 struct tevent_timer *te;
96 bool timed_out = False;
98 te = tevent_add_timer(ev_ctx, NULL,
99 timeval_current_ofs(timeout, 0),
100 smbcontrol_timeout, (void *)&timed_out);
101 if (te == NULL) {
102 DEBUG(0, ("tevent_add_timer failed\n"));
103 return;
106 while (!timed_out) {
107 int ret;
108 if (num_replies > 0 && !multiple_replies)
109 break;
110 ret = tevent_loop_once(ev_ctx);
111 if (ret != 0) {
112 break;
117 /* Message handler callback that displays the PID and a string on stdout */
119 static void print_pid_string_cb(struct messaging_context *msg,
120 void *private_data,
121 uint32_t msg_type,
122 struct server_id pid,
123 DATA_BLOB *data)
125 struct server_id_buf pidstr;
127 printf("PID %s: %.*s", server_id_str_buf(pid, &pidstr),
128 (int)data->length, (const char *)data->data);
129 num_replies++;
132 /* Send no message. Useful for testing. */
134 static bool do_noop(struct tevent_context *ev_ctx,
135 struct messaging_context *msg_ctx,
136 const struct server_id pid,
137 const int argc, const char **argv)
139 if (argc != 1) {
140 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
141 return False;
144 /* Move along, nothing to see here */
146 return True;
149 /* Send a debug string */
151 static bool do_debug(struct tevent_context *ev_ctx,
152 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);
167 static bool do_idmap(struct tevent_context *ev,
168 struct messaging_context *msg_ctx,
169 const struct server_id pid,
170 const int argc, const char **argv)
172 static const char* usage = "Usage: "
173 "smbcontrol <dest> idmap <cmd> [arg]\n"
174 "\tcmd:"
175 "\tdelete \"UID <uid>\"|\"GID <gid>\"|<sid>\n"
176 "\t\tkill \"UID <uid>\"|\"GID <gid>\"|<sid>\n";
177 const char* arg = NULL;
178 int arglen = 0;
179 int msg_type;
181 switch (argc) {
182 case 2:
183 break;
184 case 3:
185 arg = argv[2];
186 arglen = strlen(arg) + 1;
187 break;
188 default:
189 fprintf(stderr, "%s", usage);
190 return false;
193 if (strcmp(argv[1], "delete") == 0) {
194 msg_type = ID_CACHE_DELETE;
196 else if (strcmp(argv[1], "kill") == 0) {
197 msg_type = ID_CACHE_KILL;
199 else if (strcmp(argv[1], "help") == 0) {
200 fprintf(stdout, "%s", usage);
201 return true;
203 else {
204 fprintf(stderr, "%s", usage);
205 return false;
208 return send_message(msg_ctx, pid, msg_type, arg, arglen);
212 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
214 /* Return the name of a process given it's PID. This will only work on Linux,
215 * but that's probably moot since this whole stack tracing implementation is
216 * Linux-specific anyway.
218 static const char * procname(pid_t pid, char * buf, size_t bufsz)
220 char path[64];
221 FILE * fp;
223 snprintf(path, sizeof(path), "/proc/%llu/cmdline",
224 (unsigned long long)pid);
225 if ((fp = fopen(path, "r")) == NULL) {
226 return NULL;
229 fgets(buf, bufsz, fp);
231 fclose(fp);
232 return buf;
235 static void print_stack_trace(pid_t pid, int * count)
237 void * pinfo = NULL;
238 unw_addr_space_t aspace = NULL;
239 unw_cursor_t cursor;
240 unw_word_t ip, sp;
242 char nbuf[256];
243 unw_word_t off;
245 int ret;
247 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
248 fprintf(stderr,
249 "Failed to attach to process %llu: %s\n",
250 (unsigned long long)pid, strerror(errno));
251 return;
254 /* Wait until the attach is complete. */
255 waitpid(pid, NULL, 0);
257 if (((pinfo = _UPT_create(pid)) == NULL) ||
258 ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
259 /* Probably out of memory. */
260 fprintf(stderr,
261 "Unable to initialize stack unwind for process %llu\n",
262 (unsigned long long)pid);
263 goto cleanup;
266 if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
267 fprintf(stderr,
268 "Unable to unwind stack for process %llu: %s\n",
269 (unsigned long long)pid, unw_strerror(ret));
270 goto cleanup;
273 if (*count > 0) {
274 printf("\n");
277 if (procname(pid, nbuf, sizeof(nbuf))) {
278 printf("Stack trace for process %llu (%s):\n",
279 (unsigned long long)pid, nbuf);
280 } else {
281 printf("Stack trace for process %llu:\n",
282 (unsigned long long)pid);
285 while (unw_step(&cursor) > 0) {
286 ip = sp = off = 0;
287 unw_get_reg(&cursor, UNW_REG_IP, &ip);
288 unw_get_reg(&cursor, UNW_REG_SP, &sp);
290 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
291 if (ret != 0 && ret != -UNW_ENOMEM) {
292 snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
294 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
295 nbuf, (long long)off, (long long)ip,
296 (long long)sp);
299 (*count)++;
301 cleanup:
302 if (aspace) {
303 unw_destroy_addr_space(aspace);
306 if (pinfo) {
307 _UPT_destroy(pinfo);
310 ptrace(PTRACE_DETACH, pid, NULL, NULL);
313 static int stack_trace_server(pid_t pid, void *priv)
315 print_stack_trace(pid, (int *)priv);
316 return 0;
319 static bool do_daemon_stack_trace(struct tevent_context *ev_ctx,
320 struct messaging_context *msg_ctx,
321 const struct server_id pid,
322 const int argc, const char **argv)
324 pid_t dest;
325 int count = 0;
327 if (argc != 1) {
328 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
329 return False;
332 dest = procid_to_pid(&pid);
334 if (dest != 0) {
335 /* It would be nice to be able to make sure that this PID is
336 * the PID of a smbd/winbind/nmbd process, not some random PID
337 * the user liked the look of. It doesn't seem like it's worth
338 * the effort at the moment, however.
340 print_stack_trace(dest, &count);
341 } else {
342 messaging_dgm_forall(stack_trace_server, &count);
345 return True;
348 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
350 static bool do_daemon_stack_trace(struct tevent_context *ev_ctx,
351 struct messaging_context *msg_ctx,
352 const struct server_id pid,
353 const int argc, const char **argv)
355 fprintf(stderr,
356 "Daemon stack tracing is not supported on this platform\n");
357 return False;
360 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
362 /* Inject a fault (fatal signal) into a running smbd */
364 static bool do_inject_fault(struct tevent_context *ev_ctx,
365 struct messaging_context *msg_ctx,
366 const struct server_id pid,
367 const int argc, const char **argv)
369 if (argc != 2) {
370 fprintf(stderr, "Usage: smbcontrol <dest> inject "
371 "<bus|hup|term|internal|segv>\n");
372 return False;
375 #if !defined(DEVELOPER) && !defined(ENABLE_SELFTEST)
376 fprintf(stderr, "Fault injection is only available in "
377 "developer and self test builds\n");
378 return False;
379 #else /* DEVELOPER || ENABLE_SELFTEST */
381 int sig = 0;
383 if (strcmp(argv[1], "bus") == 0) {
384 sig = SIGBUS;
385 } else if (strcmp(argv[1], "hup") == 0) {
386 sig = SIGHUP;
387 } else if (strcmp(argv[1], "term") == 0) {
388 sig = SIGTERM;
389 } else if (strcmp(argv[1], "segv") == 0) {
390 sig = SIGSEGV;
391 } else if (strcmp(argv[1], "internal") == 0) {
392 /* Force an internal error, ie. an unclean exit. */
393 sig = -1;
394 } else {
395 fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
396 return False;
399 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
400 &sig, sizeof(int));
402 #endif /* DEVELOPER || ENABLE_SELFTEST */
405 static bool do_sleep(struct tevent_context *ev_ctx,
406 struct messaging_context *msg_ctx,
407 const struct server_id pid,
408 const int argc, const char **argv)
410 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
411 unsigned int seconds;
412 long input;
413 const long MAX_SLEEP = 60 * 60; /* One hour maximum sleep */
414 #endif
416 if (argc != 2) {
417 fprintf(stderr, "Usage: smbcontrol <dest> sleep seconds\n");
418 return False;
421 #if !defined(DEVELOPER) && !defined(ENABLE_SELFTEST)
422 fprintf(stderr, "Sleep is only available in "
423 "developer and self test builds\n");
424 return False;
425 #else /* DEVELOPER || ENABLE_SELFTEST */
427 input = atol(argv[1]);
428 if (input < 1 || input > MAX_SLEEP) {
429 fprintf(stderr,
430 "Invalid duration for sleep '%s'\n"
431 "It should be at least 1 second and no more than %ld\n",
432 argv[1],
433 MAX_SLEEP);
434 return False;
436 seconds = input;
437 return send_message(msg_ctx, pid,
438 MSG_SMB_SLEEP,
439 &seconds,
440 sizeof(unsigned int));
441 #endif /* DEVELOPER || ENABLE_SELFTEST */
444 /* Force a browser election */
446 static bool do_election(struct tevent_context *ev_ctx,
447 struct messaging_context *msg_ctx,
448 const struct server_id pid,
449 const int argc, const char **argv)
451 if (argc != 1) {
452 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
453 return False;
456 return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
459 /* Ping a samba daemon process */
461 static void pong_cb(struct messaging_context *msg,
462 void *private_data,
463 uint32_t msg_type,
464 struct server_id pid,
465 DATA_BLOB *data)
467 struct server_id_buf src_string;
468 printf("PONG from pid %s\n", server_id_str_buf(pid, &src_string));
469 num_replies++;
472 static bool do_ping(struct tevent_context *ev_ctx,
473 struct messaging_context *msg_ctx,
474 const struct server_id pid,
475 const int argc, const char **argv)
477 if (argc != 1) {
478 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
479 return False;
482 /* Send a message and register our interest in a reply */
484 if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
485 return False;
487 messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
489 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
491 /* No replies were received within the timeout period */
493 if (num_replies == 0)
494 printf("No replies received\n");
496 messaging_deregister(msg_ctx, MSG_PONG, NULL);
498 return num_replies;
501 /* Set profiling options */
503 static bool do_profile(struct tevent_context *ev_ctx,
504 struct messaging_context *msg_ctx,
505 const struct server_id pid,
506 const int argc, const char **argv)
508 int v;
510 if (argc != 2) {
511 fprintf(stderr, "Usage: smbcontrol <dest> profile "
512 "<off|count|on|flush>\n");
513 return False;
516 if (strcmp(argv[1], "off") == 0) {
517 v = 0;
518 } else if (strcmp(argv[1], "count") == 0) {
519 v = 1;
520 } else if (strcmp(argv[1], "on") == 0) {
521 v = 2;
522 } else if (strcmp(argv[1], "flush") == 0) {
523 v = 3;
524 } else {
525 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
526 return False;
529 return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
532 /* Return the profiling level */
534 static void profilelevel_cb(struct messaging_context *msg_ctx,
535 void *private_data,
536 uint32_t msg_type,
537 struct server_id pid,
538 DATA_BLOB *data)
540 int level;
541 const char *s;
543 num_replies++;
545 if (data->length != sizeof(int)) {
546 fprintf(stderr, "invalid message length %ld returned\n",
547 (unsigned long)data->length);
548 return;
551 memcpy(&level, data->data, sizeof(int));
553 switch (level) {
554 case 0:
555 s = "not enabled";
556 break;
557 case 1:
558 s = "off";
559 break;
560 case 3:
561 s = "count only";
562 break;
563 case 7:
564 s = "count and time";
565 break;
566 default:
567 s = "BOGUS";
568 break;
571 printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
574 static void profilelevel_rqst(struct messaging_context *msg_ctx,
575 void *private_data,
576 uint32_t msg_type,
577 struct server_id pid,
578 DATA_BLOB *data)
580 int v = 0;
582 /* Send back a dummy reply */
584 send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
587 static bool do_profilelevel(struct tevent_context *ev_ctx,
588 struct messaging_context *msg_ctx,
589 const struct server_id pid,
590 const int argc, const char **argv)
592 if (argc != 1) {
593 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
594 return False;
597 /* Send a message and register our interest in a reply */
599 if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
600 return False;
602 messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
603 messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
604 profilelevel_rqst);
606 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
608 /* No replies were received within the timeout period */
610 if (num_replies == 0)
611 printf("No replies received\n");
613 messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
615 return num_replies;
618 /* Display debug level settings */
620 static bool do_debuglevel(struct tevent_context *ev_ctx,
621 struct messaging_context *msg_ctx,
622 const struct server_id pid,
623 const int argc, const char **argv)
625 if (argc != 1) {
626 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
627 return False;
630 /* Send a message and register our interest in a reply */
632 if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
633 return False;
635 messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
637 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
639 /* No replies were received within the timeout period */
641 if (num_replies == 0)
642 printf("No replies received\n");
644 messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
646 return num_replies;
649 /* Send a print notify message */
651 static bool do_printnotify(struct tevent_context *ev_ctx,
652 struct messaging_context *msg_ctx,
653 const struct server_id pid,
654 const int argc, const char **argv)
656 const char *cmd;
658 /* Check for subcommand */
660 if (argc == 1) {
661 fprintf(stderr, "Must specify subcommand:\n");
662 fprintf(stderr, "\tqueuepause <printername>\n");
663 fprintf(stderr, "\tqueueresume <printername>\n");
664 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
665 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
666 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
667 fprintf(stderr, "\tprinter <printername> <comment|port|"
668 "driver> <value>\n");
670 return False;
673 cmd = argv[1];
675 if (strcmp(cmd, "queuepause") == 0) {
677 if (argc != 3) {
678 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
679 " queuepause <printername>\n");
680 return False;
683 notify_printer_status_byname(ev_ctx, msg_ctx, argv[2],
684 PRINTER_STATUS_PAUSED);
686 goto send;
688 } else if (strcmp(cmd, "queueresume") == 0) {
690 if (argc != 3) {
691 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
692 " queuereume <printername>\n");
693 return False;
696 notify_printer_status_byname(ev_ctx, msg_ctx, argv[2],
697 PRINTER_STATUS_OK);
699 goto send;
701 } else if (strcmp(cmd, "jobpause") == 0) {
702 int jobid;
704 if (argc != 4) {
705 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
706 " jobpause <printername> <unix-jobid>\n");
707 return False;
710 jobid = atoi(argv[3]);
712 notify_job_status_byname(
713 ev_ctx, msg_ctx,
714 argv[2], jobid, JOB_STATUS_PAUSED,
715 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
717 goto send;
719 } else if (strcmp(cmd, "jobresume") == 0) {
720 int jobid;
722 if (argc != 4) {
723 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
724 " jobpause <printername> <unix-jobid>\n");
725 return False;
728 jobid = atoi(argv[3]);
730 notify_job_status_byname(
731 ev_ctx, msg_ctx,
732 argv[2], jobid, JOB_STATUS_QUEUED,
733 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
735 goto send;
737 } else if (strcmp(cmd, "jobdelete") == 0) {
738 int jobid;
740 if (argc != 4) {
741 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
742 " jobpause <printername> <unix-jobid>\n");
743 return False;
746 jobid = atoi(argv[3]);
748 notify_job_status_byname(
749 ev_ctx, msg_ctx,
750 argv[2], jobid, JOB_STATUS_DELETING,
751 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
753 notify_job_status_byname(
754 ev_ctx, msg_ctx,
755 argv[2], jobid, JOB_STATUS_DELETING|
756 JOB_STATUS_DELETED,
757 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
759 goto send;
761 } else if (strcmp(cmd, "printer") == 0) {
762 uint32_t attribute;
764 if (argc != 5) {
765 fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
766 "printer <printername> <comment|port|driver> "
767 "<value>\n");
768 return False;
771 if (strcmp(argv[3], "comment") == 0) {
772 attribute = PRINTER_NOTIFY_FIELD_COMMENT;
773 } else if (strcmp(argv[3], "port") == 0) {
774 attribute = PRINTER_NOTIFY_FIELD_PORT_NAME;
775 } else if (strcmp(argv[3], "driver") == 0) {
776 attribute = PRINTER_NOTIFY_FIELD_DRIVER_NAME;
777 } else {
778 fprintf(stderr, "Invalid printer command '%s'\n",
779 argv[3]);
780 return False;
783 notify_printer_byname(ev_ctx, msg_ctx, argv[2], attribute,
784 discard_const_p(char, argv[4]));
786 goto send;
789 fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
790 return False;
792 send:
793 print_notify_send_messages(msg_ctx, 0);
794 return True;
797 /* Close a share */
799 static bool do_closeshare(struct tevent_context *ev_ctx,
800 struct messaging_context *msg_ctx,
801 const struct server_id pid,
802 const int argc, const char **argv)
804 if (argc != 2) {
805 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
806 "<sharename>\n");
807 return False;
810 return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
811 strlen(argv[1]) + 1);
815 * Close a share if access denied by now
818 static bool do_close_denied_share(
819 struct tevent_context *ev_ctx,
820 struct messaging_context *msg_ctx,
821 const struct server_id pid,
822 const int argc, const char **argv)
824 if (argc != 2) {
825 fprintf(stderr, "Usage: smbcontrol <dest> close-denied-share "
826 "<sharename>\n");
827 return False;
830 return send_message(
831 msg_ctx,
832 pid,
833 MSG_SMB_FORCE_TDIS_DENIED,
834 argv[1],
835 strlen(argv[1]) + 1);
838 /* Kill a client by IP address */
839 static bool do_kill_client_by_ip(struct tevent_context *ev_ctx,
840 struct messaging_context *msg_ctx,
841 const struct server_id pid,
842 const int argc, const char **argv)
844 if (argc != 2) {
845 fprintf(stderr, "Usage: smbcontrol <dest> kill-client-ip "
846 "<IP address>\n");
847 return false;
850 if (!is_ipaddress_v4(argv[1]) && !is_ipaddress_v6(argv[1])) {
851 fprintf(stderr, "%s is not a valid IP address!\n", argv[1]);
852 return false;
855 return send_message(msg_ctx, pid, MSG_SMB_KILL_CLIENT_IP,
856 argv[1], strlen(argv[1]) + 1);
859 /* Tell winbindd an IP got dropped */
861 static bool do_ip_dropped(struct tevent_context *ev_ctx,
862 struct messaging_context *msg_ctx,
863 const struct server_id pid,
864 const int argc, const char **argv)
866 if (argc != 2) {
867 fprintf(stderr, "Usage: smbcontrol <dest> ip-dropped "
868 "<ip-address>\n");
869 return False;
872 return send_message(msg_ctx, pid, MSG_WINBIND_IP_DROPPED, argv[1],
873 strlen(argv[1]) + 1);
876 /* Display talloc pool usage */
878 static bool do_poolusage(struct tevent_context *ev_ctx,
879 struct messaging_context *msg_ctx,
880 const struct server_id dst,
881 const int argc, const char **argv)
883 pid_t pid = procid_to_pid(&dst);
884 int stdout_fd = 1;
886 if (argc != 1) {
887 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
888 return False;
891 if (pid == 0) {
892 fprintf(stderr, "Can only send to a specific PID\n");
893 return false;
896 messaging_send_iov(
897 msg_ctx,
898 dst,
899 MSG_REQ_POOL_USAGE,
900 NULL,
902 &stdout_fd,
905 return true;
908 static bool do_rpc_dump_status(
909 struct tevent_context *ev_ctx,
910 struct messaging_context *msg_ctx,
911 const struct server_id dst,
912 const int argc,
913 const char **argv)
915 pid_t pid = procid_to_pid(&dst);
916 int stdout_fd = 1;
918 if (argc != 1) {
919 fprintf(stderr,
920 "Usage: smbcontrol <dest> rpc-dump-status\n");
921 return False;
924 if (pid == 0) {
925 fprintf(stderr, "Can only send to a specific PID\n");
926 return false;
929 messaging_send_iov(
930 msg_ctx,
931 dst,
932 MSG_RPC_DUMP_STATUS,
933 NULL,
935 &stdout_fd,
938 return true;
941 /* Fetch and print the ringbuf log */
943 static void print_ringbuf_log_cb(struct messaging_context *msg,
944 void *private_data,
945 uint32_t msg_type,
946 struct server_id pid,
947 DATA_BLOB *data)
949 printf("%s", (const char *)data->data);
950 num_replies++;
953 static bool do_ringbuflog(struct tevent_context *ev_ctx,
954 struct messaging_context *msg_ctx,
955 const struct server_id pid,
956 const int argc, const char **argv)
958 if (argc != 1) {
959 fprintf(stderr, "Usage: smbcontrol <dest> ringbuf-log\n");
960 return false;
963 messaging_register(msg_ctx, NULL, MSG_RINGBUF_LOG,
964 print_ringbuf_log_cb);
966 /* Send a message and register our interest in a reply */
968 if (!send_message(msg_ctx, pid, MSG_REQ_RINGBUF_LOG, NULL, 0)) {
969 return false;
972 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
974 /* No replies were received within the timeout period */
976 if (num_replies == 0) {
977 printf("No replies received\n");
980 messaging_deregister(msg_ctx, MSG_RINGBUF_LOG, NULL);
982 return num_replies != 0;
985 /* Perform a dmalloc mark */
987 static bool do_dmalloc_mark(struct tevent_context *ev_ctx,
988 struct messaging_context *msg_ctx,
989 const struct server_id pid,
990 const int argc, const char **argv)
992 if (argc != 1) {
993 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
994 return False;
997 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
1000 /* Perform a dmalloc changed */
1002 static bool do_dmalloc_changed(struct tevent_context *ev_ctx,
1003 struct messaging_context *msg_ctx,
1004 const struct server_id pid,
1005 const int argc, const char **argv)
1007 if (argc != 1) {
1008 fprintf(stderr, "Usage: smbcontrol <dest> "
1009 "dmalloc-log-changed\n");
1010 return False;
1013 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
1014 NULL, 0);
1017 static void print_uint32_cb(struct messaging_context *msg, void *private_data,
1018 uint32_t msg_type, struct server_id pid,
1019 DATA_BLOB *data)
1021 uint32_t num_children;
1023 if (data->length != sizeof(uint32_t)) {
1024 printf("Invalid response: %d bytes long\n",
1025 (int)data->length);
1026 goto done;
1028 num_children = IVAL(data->data, 0);
1029 printf("%u children\n", (unsigned)num_children);
1030 done:
1031 num_replies++;
1034 static bool do_num_children(struct tevent_context *ev_ctx,
1035 struct messaging_context *msg_ctx,
1036 const struct server_id pid,
1037 const int argc, const char **argv)
1039 if (argc != 1) {
1040 fprintf(stderr, "Usage: smbcontrol <dest> num-children\n");
1041 return False;
1044 messaging_register(msg_ctx, NULL, MSG_SMB_NUM_CHILDREN,
1045 print_uint32_cb);
1047 /* Send a message and register our interest in a reply */
1049 if (!send_message(msg_ctx, pid, MSG_SMB_TELL_NUM_CHILDREN, NULL, 0))
1050 return false;
1052 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1054 /* No replies were received within the timeout period */
1056 if (num_replies == 0)
1057 printf("No replies received\n");
1059 messaging_deregister(msg_ctx, MSG_SMB_NUM_CHILDREN, NULL);
1061 return num_replies;
1064 static bool do_msg_cleanup(struct tevent_context *ev_ctx,
1065 struct messaging_context *msg_ctx,
1066 const struct server_id pid,
1067 const int argc, const char **argv)
1069 int ret;
1071 ret = messaging_cleanup(msg_ctx, pid.pid);
1073 printf("cleanup(%u) returned %s\n", (unsigned)pid.pid,
1074 ret ? strerror(ret) : "ok");
1076 return (ret == 0);
1079 /* Shutdown a server process */
1081 static bool do_shutdown(struct tevent_context *ev_ctx,
1082 struct messaging_context *msg_ctx,
1083 const struct server_id pid,
1084 const int argc, const char **argv)
1086 if (argc != 1) {
1087 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
1088 return False;
1091 return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
1094 /* Notify a driver upgrade */
1096 static bool do_drvupgrade(struct tevent_context *ev_ctx,
1097 struct messaging_context *msg_ctx,
1098 const struct server_id pid,
1099 const int argc, const char **argv)
1101 if (argc != 2) {
1102 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
1103 "<driver-name>\n");
1104 return False;
1107 return send_message(msg_ctx, pid, MSG_PRINTER_DRVUPGRADE, argv[1],
1108 strlen(argv[1]) + 1);
1111 static bool do_winbind_online(struct tevent_context *ev_ctx,
1112 struct messaging_context *msg_ctx,
1113 const struct server_id pid,
1114 const int argc, const char **argv)
1116 TDB_CONTEXT *tdb;
1117 char *db_path;
1119 if (argc != 1) {
1120 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
1121 return False;
1124 db_path = state_path(talloc_tos(), "winbindd_cache.tdb");
1125 if (db_path == NULL) {
1126 return false;
1129 /* Remove the entry in the winbindd_cache tdb to tell a later
1130 starting winbindd that we're online. */
1132 tdb = tdb_open_log(db_path, 0, TDB_DEFAULT, O_RDWR, 0600);
1133 if (!tdb) {
1134 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
1135 db_path);
1136 TALLOC_FREE(db_path);
1137 return False;
1140 TALLOC_FREE(db_path);
1141 tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
1142 tdb_close(tdb);
1144 return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
1147 static bool do_winbind_offline(struct tevent_context *ev_ctx,
1148 struct messaging_context *msg_ctx,
1149 const struct server_id pid,
1150 const int argc, const char **argv)
1152 TDB_CONTEXT *tdb;
1153 bool ret = False;
1154 int retry = 0;
1155 char *db_path;
1157 if (argc != 1) {
1158 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
1159 return False;
1162 db_path = state_path(talloc_tos(), "winbindd_cache.tdb");
1163 if (db_path == NULL) {
1164 return false;
1167 /* Create an entry in the winbindd_cache tdb to tell a later
1168 starting winbindd that we're offline. We may actually create
1169 it here... */
1171 tdb = tdb_open_log(db_path,
1172 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
1173 TDB_DEFAULT|TDB_INCOMPATIBLE_HASH /* TDB_CLEAR_IF_FIRST */,
1174 O_RDWR|O_CREAT, 0600);
1176 if (!tdb) {
1177 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
1178 db_path);
1179 TALLOC_FREE(db_path);
1180 return False;
1182 TALLOC_FREE(db_path);
1184 /* There's a potential race condition that if a child
1185 winbindd detects a domain is online at the same time
1186 we're trying to tell it to go offline that it might
1187 delete the record we add between us adding it and
1188 sending the message. Minimize this by retrying up to
1189 5 times. */
1191 for (retry = 0; retry < 5; retry++) {
1192 uint8_t buf[4];
1193 TDB_DATA d = { .dptr = buf, .dsize = sizeof(buf) };
1195 SIVAL(buf, 0, time(NULL));
1197 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
1199 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
1200 NULL, 0);
1202 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
1203 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
1204 if (d.dptr != NULL && d.dsize == 4) {
1205 SAFE_FREE(d.dptr);
1206 break;
1209 SAFE_FREE(d.dptr);
1210 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
1213 tdb_close(tdb);
1214 return ret;
1217 static bool do_winbind_onlinestatus(struct tevent_context *ev_ctx,
1218 struct messaging_context *msg_ctx,
1219 const struct server_id pid,
1220 const int argc, const char **argv)
1222 if (argc != 1) {
1223 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
1224 return False;
1227 messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
1228 print_pid_string_cb);
1230 if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, NULL, 0)) {
1231 return False;
1234 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1236 /* No replies were received within the timeout period */
1238 if (num_replies == 0)
1239 printf("No replies received\n");
1241 messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
1243 return num_replies;
1246 static bool do_winbind_dump_domain_list(struct tevent_context *ev_ctx,
1247 struct messaging_context *msg_ctx,
1248 const struct server_id pid,
1249 const int argc, const char **argv)
1251 const char *domain = NULL;
1252 int domain_len = 0;
1254 if (argc < 1 || argc > 2) {
1255 fprintf(stderr, "Usage: smbcontrol <dest> dump-domain-list "
1256 "<domain>\n");
1257 return false;
1260 if (argc == 2) {
1261 domain = argv[1];
1262 domain_len = strlen(argv[1]) + 1;
1265 messaging_register(msg_ctx, NULL, MSG_WINBIND_DUMP_DOMAIN_LIST,
1266 print_pid_string_cb);
1268 if (!send_message(msg_ctx, pid, MSG_WINBIND_DUMP_DOMAIN_LIST,
1269 domain, domain_len))
1271 return false;
1274 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1276 /* No replies were received within the timeout period */
1278 if (num_replies == 0) {
1279 printf("No replies received\n");
1282 messaging_deregister(msg_ctx, MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
1284 return num_replies;
1287 static bool do_msg_disconnect_dc(struct tevent_context *ev_ctx,
1288 struct messaging_context *msg_ctx,
1289 const struct server_id pid,
1290 const int argc, const char **argv)
1292 if (argc != 1) {
1293 fprintf(stderr, "Usage: smbcontrol <dest> disconnect-dc\n");
1294 return False;
1297 return send_message(msg_ctx, pid, MSG_WINBIND_DISCONNECT_DC, NULL, 0);
1300 static void winbind_validate_cache_cb(struct messaging_context *msg,
1301 void *private_data,
1302 uint32_t msg_type,
1303 struct server_id pid,
1304 DATA_BLOB *data)
1306 struct server_id_buf src_string;
1307 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1308 (*(data->data) == 0 ? "" : "NOT "),
1309 server_id_str_buf(pid, &src_string));
1310 num_replies++;
1313 static bool do_winbind_validate_cache(struct tevent_context *ev_ctx,
1314 struct messaging_context *msg_ctx,
1315 const struct server_id pid,
1316 const int argc, const char **argv)
1318 struct server_id myid;
1320 myid = messaging_server_id(msg_ctx);
1322 if (argc != 1) {
1323 fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
1324 return False;
1327 messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
1328 winbind_validate_cache_cb);
1330 if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
1331 sizeof(myid))) {
1332 return False;
1335 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1337 if (num_replies == 0) {
1338 printf("No replies received\n");
1341 messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);
1343 return num_replies;
1346 static bool do_reload_certs(struct tevent_context *ev_ctx,
1347 struct messaging_context *msg_ctx,
1348 const struct server_id pid,
1349 const int argc, const char **argv)
1351 if (argc != 1) {
1352 fprintf(stderr, "Usage: smbcontrol ldap_server reload-certs \n");
1353 return false;
1356 return send_message(msg_ctx, pid, MSG_RELOAD_TLS_CERTIFICATES, NULL, 0);
1358 static bool do_reload_config(struct tevent_context *ev_ctx,
1359 struct messaging_context *msg_ctx,
1360 const struct server_id pid,
1361 const int argc, const char **argv)
1363 if (argc != 1) {
1364 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1365 return False;
1368 return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1371 static bool do_reload_printers(struct tevent_context *ev_ctx,
1372 struct messaging_context *msg_ctx,
1373 const struct server_id pid,
1374 const int argc, const char **argv)
1376 if (argc != 1) {
1377 fprintf(stderr, "Usage: smbcontrol <dest> reload-printers\n");
1378 return False;
1381 return send_message(msg_ctx, pid, MSG_PRINTER_PCAP, NULL, 0);
1384 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1386 fstring unix_name;
1387 memset( (char *)n, '\0', sizeof(struct nmb_name) );
1388 fstrcpy(unix_name, name);
1389 (void)strupper_m(unix_name);
1390 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1391 n->name_type = (unsigned int)type & 0xFF;
1392 push_ascii(n->scope, lp_netbios_scope(), 64, STR_TERMINATE);
1395 static bool do_nodestatus(struct tevent_context *ev_ctx,
1396 struct messaging_context *msg_ctx,
1397 const struct server_id pid,
1398 const int argc, const char **argv)
1400 struct packet_struct p;
1402 if (argc != 2) {
1403 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1404 return False;
1407 ZERO_STRUCT(p);
1409 p.ip = interpret_addr2(argv[1]);
1410 p.port = 137;
1411 p.packet_type = NMB_PACKET;
1413 p.packet.nmb.header.name_trn_id = 10;
1414 p.packet.nmb.header.opcode = 0;
1415 p.packet.nmb.header.response = False;
1416 p.packet.nmb.header.nm_flags.bcast = False;
1417 p.packet.nmb.header.nm_flags.recursion_available = False;
1418 p.packet.nmb.header.nm_flags.recursion_desired = False;
1419 p.packet.nmb.header.nm_flags.trunc = False;
1420 p.packet.nmb.header.nm_flags.authoritative = False;
1421 p.packet.nmb.header.rcode = 0;
1422 p.packet.nmb.header.qdcount = 1;
1423 p.packet.nmb.header.ancount = 0;
1424 p.packet.nmb.header.nscount = 0;
1425 p.packet.nmb.header.arcount = 0;
1426 my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1427 p.packet.nmb.question.question_type = 0x21;
1428 p.packet.nmb.question.question_class = 0x1;
1430 return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1433 static bool do_notify_cleanup(struct tevent_context *ev_ctx,
1434 struct messaging_context *msg_ctx,
1435 const struct server_id pid,
1436 const int argc, const char **argv)
1438 if (argc != 1) {
1439 fprintf(stderr, "Usage: smbcontrol smbd notify-cleanup\n");
1440 return false;
1442 return send_message(msg_ctx, pid, MSG_SMB_NOTIFY_CLEANUP, NULL, 0);
1445 /* A list of message type supported */
1447 static const struct {
1448 const char *name; /* Option name */
1449 bool (*fn)(struct tevent_context *ev_ctx,
1450 struct messaging_context *msg_ctx,
1451 const struct server_id pid,
1452 const int argc, const char **argv);
1453 const char *help; /* Short help text */
1454 } msg_types[] = {
1456 .name = "debug",
1457 .fn = do_debug,
1458 .help = "Set debuglevel",
1461 .name = "idmap",
1462 .fn = do_idmap,
1463 .help = "Manipulate idmap cache",
1466 .name = "force-election",
1467 .fn = do_election,
1468 .help = "Force a browse election",
1471 .name = "ping",
1472 .fn = do_ping,
1473 .help = "Elicit a response",
1476 .name = "profile",
1477 .fn = do_profile,
1478 .help = "",
1481 .name = "inject",
1482 .fn = do_inject_fault,
1483 .help = "Inject a fatal signal into a running smbd"},
1485 .name = "stacktrace",
1486 .fn = do_daemon_stack_trace,
1487 .help = "Display a stack trace of a daemon",
1490 .name = "profilelevel",
1491 .fn = do_profilelevel,
1492 .help = "",
1495 .name = "debuglevel",
1496 .fn = do_debuglevel,
1497 .help = "Display current debuglevels",
1500 .name = "printnotify",
1501 .fn = do_printnotify,
1502 .help = "Send a print notify message",
1505 .name = "close-share",
1506 .fn = do_closeshare,
1507 .help = "Forcibly disconnect a share",
1510 .name = "close-denied-share",
1511 .fn = do_close_denied_share,
1512 .help = "Forcibly disconnect users from shares disallowed now",
1515 .name = "kill-client-ip",
1516 .fn = do_kill_client_by_ip,
1517 .help = "Forcibly disconnect a client with a specific IP address",
1520 .name = "ip-dropped",
1521 .fn = do_ip_dropped,
1522 .help = "Tell winbind that an IP got dropped",
1525 .name = "pool-usage",
1526 .fn = do_poolusage,
1527 .help = "Display talloc memory usage",
1530 .name = "rpc-dump-status",
1531 .fn = do_rpc_dump_status,
1532 .help = "Display rpc status",
1535 .name = "ringbuf-log",
1536 .fn = do_ringbuflog,
1537 .help = "Display ringbuf log",
1540 .name = "dmalloc-mark",
1541 .fn = do_dmalloc_mark,
1542 .help = "",
1545 .name = "dmalloc-log-changed",
1546 .fn = do_dmalloc_changed,
1547 .help = "",
1550 .name = "shutdown",
1551 .fn = do_shutdown,
1552 .help = "Shut down daemon",
1555 .name = "drvupgrade",
1556 .fn = do_drvupgrade,
1557 .help = "Notify a printer driver has changed",
1560 .name = "reload-certs",
1561 .fn = do_reload_certs,
1562 .help = "Reload TLS certificates"
1565 .name = "reload-config",
1566 .fn = do_reload_config,
1567 .help = "Force smbd or winbindd to reload config file"},
1569 .name = "reload-printers",
1570 .fn = do_reload_printers,
1571 .help = "Force smbd to reload printers"},
1573 .name = "nodestatus",
1574 .fn = do_nodestatus,
1575 .help = "Ask nmbd to do a node status request"},
1577 .name = "online",
1578 .fn = do_winbind_online,
1579 .help = "Ask winbind to go into online state"},
1581 .name = "offline",
1582 .fn = do_winbind_offline,
1583 .help = "Ask winbind to go into offline state"},
1585 .name = "onlinestatus",
1586 .fn = do_winbind_onlinestatus,
1587 .help = "Request winbind online status"},
1589 .name = "validate-cache" ,
1590 .fn = do_winbind_validate_cache,
1591 .help = "Validate winbind's credential cache",
1594 .name = "dump-domain-list",
1595 .fn = do_winbind_dump_domain_list,
1596 .help = "Dump winbind domain list"},
1598 .name = "disconnect-dc",
1599 .fn = do_msg_disconnect_dc,
1602 .name = "notify-cleanup",
1603 .fn = do_notify_cleanup,
1606 .name = "num-children",
1607 .fn = do_num_children,
1608 .help = "Print number of smbd child processes",
1611 .name = "msg-cleanup",
1612 .fn = do_msg_cleanup,
1615 .name = "noop",
1616 .fn = do_noop,
1617 .help = "Do nothing",
1620 .name = "sleep",
1621 .fn = do_sleep,
1622 .help = "Cause the target process to sleep",
1624 { .name = NULL, },
1627 /* Display usage information */
1629 static void usage(poptContext pc)
1631 int i;
1633 poptPrintHelp(pc, stderr, 0);
1635 fprintf(stderr, "\n");
1636 fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\", "
1637 "\"ldap_server\" or a process ID\n");
1639 fprintf(stderr, "\n");
1640 fprintf(stderr, "<message-type> is one of:\n");
1642 for (i = 0; msg_types[i].name; i++) {
1643 const char *help = msg_types[i].help;
1644 if (help == NULL) {
1645 help = "";
1647 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name, help);
1650 fprintf(stderr, "\n");
1652 exit(1);
1655 /* Return the pid number for a string destination */
1657 static struct server_id parse_dest(struct messaging_context *msg,
1658 const char *dest)
1660 struct server_id result = {
1661 .pid = (uint64_t)-1,
1663 pid_t pid;
1664 struct server_id_db *names_db = NULL;
1665 bool ok;
1667 /* Zero is a special return value for broadcast to all processes */
1669 if (strequal(dest, "all")) {
1670 return interpret_pid(MSG_BROADCAST_PID_STR);
1673 /* Try self - useful for testing */
1675 if (strequal(dest, "self")) {
1676 return messaging_server_id(msg);
1679 /* Fix winbind typo. */
1680 if (strequal(dest, "winbind")) {
1681 dest = "winbindd";
1684 /* Check for numeric pid number */
1685 result = interpret_pid(dest);
1687 /* Zero isn't valid if not "all". */
1688 if (result.pid && procid_valid(&result)) {
1689 return result;
1692 /* Look up other destinations in pidfile directory */
1694 if ((pid = pidfile_pid(lp_pid_directory(), dest)) != 0) {
1695 return pid_to_procid(pid);
1698 names_db = messaging_names_db(msg);
1699 if (names_db == NULL) {
1700 goto fail;
1702 ok = server_id_db_lookup_one(names_db, dest, &result);
1703 if (ok) {
1704 return result;
1707 fail:
1708 fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1710 return result;
1713 /* Execute smbcontrol command */
1715 static bool do_command(struct tevent_context *ev_ctx,
1716 struct messaging_context *msg_ctx,
1717 int argc, const char **argv)
1719 const char *dest = argv[0], *command = argv[1];
1720 struct server_id pid;
1721 int i;
1723 /* Check destination */
1725 pid = parse_dest(msg_ctx, dest);
1726 if (!procid_valid(&pid)) {
1727 return False;
1730 /* Check command */
1732 for (i = 0; msg_types[i].name; i++) {
1733 if (strequal(command, msg_types[i].name))
1734 return msg_types[i].fn(ev_ctx, msg_ctx, pid,
1735 argc - 1, argv + 1);
1738 fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1740 return False;
1743 static void smbcontrol_help(poptContext pc,
1744 enum poptCallbackReason preason,
1745 struct poptOption * poption,
1746 const char * parg,
1747 void * pdata)
1749 if (poption->shortName != '?') {
1750 poptPrintUsage(pc, stdout, 0);
1751 } else {
1752 usage(pc);
1755 exit(0);
1758 struct poptOption help_options[] = {
1759 { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1760 NULL, NULL },
1761 { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1762 { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1766 /* Main program */
1768 int main(int argc, const char **argv)
1770 poptContext pc;
1771 int opt;
1772 struct tevent_context *evt_ctx;
1773 struct messaging_context *msg_ctx;
1775 struct poptOption long_options[] = {
1776 /* POPT_AUTOHELP */
1777 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1778 0, "Help options:", NULL },
1779 { "timeout", 't', POPT_ARG_INT, &timeout, 't',
1780 "Set timeout value in seconds", "TIMEOUT" },
1782 POPT_COMMON_SAMBA
1783 POPT_COMMON_VERSION
1784 POPT_TABLEEND
1786 TALLOC_CTX *frame = talloc_stackframe();
1787 struct loadparm_context *lp_ctx = NULL;
1788 int ret = 0;
1789 bool ok;
1791 smb_init_locale();
1793 ok = samba_cmdline_init(frame,
1794 SAMBA_CMDLINE_CONFIG_CLIENT,
1795 false /* require_smbconf */);
1796 if (!ok) {
1797 DBG_ERR("Failed to init cmdline parser!\n");
1798 TALLOC_FREE(frame);
1799 exit(1);
1801 lp_ctx = samba_cmdline_get_lp_ctx();
1802 lpcfg_set_cmdline(lp_ctx, "log level", "0");
1804 /* Parse command line arguments using popt */
1806 pc = samba_popt_get_context(getprogname(),
1807 argc,
1808 argv,
1809 long_options,
1811 if (pc == NULL) {
1812 DBG_ERR("Failed to setup popt context!\n");
1813 TALLOC_FREE(frame);
1814 exit(1);
1817 poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1818 "<parameters>");
1820 if (argc == 1)
1821 usage(pc);
1823 while ((opt = poptGetNextOpt(pc)) != -1) {
1824 switch(opt) {
1825 case 't': /* --timeout */
1826 break;
1827 default:
1828 fprintf(stderr, "Invalid option\n");
1829 poptPrintHelp(pc, stderr, 0);
1830 break;
1834 /* We should now have the remaining command line arguments in
1835 argv. The argc parameter should have been decremented to the
1836 correct value in the above switch statement. */
1838 argv = (const char **)poptGetArgs(pc);
1839 argc = 0;
1840 if (argv != NULL) {
1841 while (argv[argc] != NULL) {
1842 argc++;
1846 if (argc <= 1)
1847 usage(pc);
1849 msg_ctx = cmdline_messaging_context(get_dyn_CONFIGFILE());
1850 if (msg_ctx == NULL) {
1851 fprintf(stderr,
1852 "Could not init messaging context, not root?\n");
1853 TALLOC_FREE(frame);
1854 exit(1);
1857 evt_ctx = global_event_context();
1859 /* Need to invert sense of return code -- samba
1860 * routines mostly return True==1 for success, but
1861 * shell needs 0. */
1863 ret = !do_command(evt_ctx, msg_ctx, argc, argv);
1865 cmdline_messaging_context_free();
1866 gfree_all();
1867 poptFreeContext(pc);
1868 TALLOC_FREE(frame);
1869 return ret;