s3:utils: Fix auth callback with smburl
[samba.git] / source3 / utils / smbcontrol.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Send messages to other Samba daemons
5
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
11
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.
16
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.
21
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/>.
24 */
25
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"
43
44 #ifdef HAVE_LIBUNWIND_H
45 #include <libunwind.h>
46 #endif
47
48 #ifdef HAVE_LIBUNWIND_PTRACE_H
49 #include <libunwind-ptrace.h>
50 #endif
51
52 #ifdef HAVE_SYS_PTRACE_H
53 #include <sys/ptrace.h>
54 #endif
55
56 /* Default timeout value when waiting for replies (in seconds) */
57
58 #define DEFAULT_TIMEOUT 10
59
60 static int timeout = DEFAULT_TIMEOUT;
61 static int num_replies;         /* Used by message callback fns */
62
63 /* Send a message to a destination pid.  Zero means broadcast smbd. */
64
65 static bool send_message(struct messaging_context *msg_ctx,
66                          struct server_id pid, int msg_type,
67                          const void *buf, int len)
68 {
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));
73
74         messaging_send_all(msg_ctx, msg_type, buf, len);
75
76         return true;
77 }
78
79 static void smbcontrol_timeout(struct tevent_context *event_ctx,
80                                struct tevent_timer *te,
81                                struct timeval now,
82                                void *private_data)
83 {
84         bool *timed_out = (bool *)private_data;
85         TALLOC_FREE(te);
86         *timed_out = True;
87 }
88
89 /* Wait for one or more reply messages */
90
91 static void wait_replies(struct tevent_context *ev_ctx,
92                          struct messaging_context *msg_ctx,
93                          bool multiple_replies)
94 {
95         struct tevent_timer *te;
96         bool timed_out = False;
97
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;
104         }
105
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;
113                 }
114         }
115 }
116
117 /* Message handler callback that displays the PID and a string on stdout */
118
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)
124 {
125         struct server_id_buf pidstr;
126
127         printf("PID %s: %.*s", server_id_str_buf(pid, &pidstr),
128                (int)data->length, (const char *)data->data);
129         num_replies++;
130 }
131
132 /* Send no message.  Useful for testing. */
133
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)
138 {
139         if (argc != 1) {
140                 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
141                 return False;
142         }
143
144         /* Move along, nothing to see here */
145
146         return True;
147 }
148
149 /* Send a debug string */
150
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)
155 {
156         if (argc != 2) {
157                 fprintf(stderr, "Usage: smbcontrol <dest> debug "
158                         "<debug-string>\n");
159                 return False;
160         }
161
162         return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
163                             strlen(argv[1]) + 1);
164 }
165
166
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)
171 {
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;
180
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;
191         }
192
193         if (strcmp(argv[1], "delete") == 0) {
194                 msg_type = ID_CACHE_DELETE;
195         }
196         else if (strcmp(argv[1], "kill") == 0) {
197                 msg_type = ID_CACHE_KILL;
198         }
199         else if (strcmp(argv[1], "help") == 0) {
200                 fprintf(stdout, "%s", usage);
201                 return true;
202         }
203         else {
204                 fprintf(stderr, "%s", usage);
205                 return false;
206         }
207
208         return send_message(msg_ctx, pid, msg_type, arg, arglen);
209 }
210
211
212 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
213
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.
217  */
218 static const char * procname(pid_t pid, char * buf, size_t bufsz)
219 {
220         char path[64];
221         FILE * fp;
222
223         snprintf(path, sizeof(path), "/proc/%llu/cmdline",
224                 (unsigned long long)pid);
225         if ((fp = fopen(path, "r")) == NULL) {
226                 return NULL;
227         }
228
229         fgets(buf, bufsz, fp);
230
231         fclose(fp);
232         return buf;
233 }
234
235 static void print_stack_trace(pid_t pid, int * count)
236 {
237         void *              pinfo = NULL;
238         unw_addr_space_t    aspace = NULL;
239         unw_cursor_t        cursor;
240         unw_word_t          ip, sp;
241
242         char                nbuf[256];
243         unw_word_t          off;
244
245         int ret;
246
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;
252         }
253
254         /* Wait until the attach is complete. */
255         waitpid(pid, NULL, 0);
256
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;
264         }
265
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;
271         }
272
273         if (*count > 0) {
274                 printf("\n");
275         }
276
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);
283         }
284
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);
289
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>");
293                 }
294                 printf("    %s + %#llx [ip=%#llx] [sp=%#llx]\n",
295                         nbuf, (long long)off, (long long)ip,
296                         (long long)sp);
297         }
298
299         (*count)++;
300
301 cleanup:
302         if (aspace) {
303                 unw_destroy_addr_space(aspace);
304         }
305
306         if (pinfo) {
307                 _UPT_destroy(pinfo);
308         }
309
310         ptrace(PTRACE_DETACH, pid, NULL, NULL);
311 }
312
313 static int stack_trace_server(pid_t pid, void *priv)
314 {
315         print_stack_trace(pid, (int *)priv);
316         return 0;
317 }
318
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)
323 {
324         pid_t   dest;
325         int     count = 0;
326
327         if (argc != 1) {
328                 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
329                 return False;
330         }
331
332         dest = procid_to_pid(&pid);
333
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.
339                  */
340                 print_stack_trace(dest, &count);
341         } else {
342                 messaging_dgm_forall(stack_trace_server, &count);
343         }
344
345         return True;
346 }
347
348 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
349
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)
354 {
355         fprintf(stderr,
356                 "Daemon stack tracing is not supported on this platform\n");
357         return False;
358 }
359
360 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
361
362 /* Inject a fault (fatal signal) into a running smbd */
363
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)
368 {
369         if (argc != 2) {
370                 fprintf(stderr, "Usage: smbcontrol <dest> inject "
371                         "<bus|hup|term|internal|segv>\n");
372                 return False;
373         }
374
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 */
380         {
381                 int sig = 0;
382
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;
397                 }
398
399                 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
400                                     &sig, sizeof(int));
401         }
402 #endif /* DEVELOPER || ENABLE_SELFTEST */
403 }
404
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)
409 {
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
415
416         if (argc != 2) {
417                 fprintf(stderr, "Usage: smbcontrol <dest> sleep seconds\n");
418                 return False;
419         }
420
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 */
426
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;
435         }
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 */
442 }
443
444 /* Force a browser election */
445
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)
450 {
451         if (argc != 1) {
452                 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
453                 return False;
454         }
455
456         return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
457 }
458
459 /* Ping a samba daemon process */
460
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)
466 {
467         struct server_id_buf src_string;
468         printf("PONG from pid %s\n", server_id_str_buf(pid, &src_string));
469         num_replies++;
470 }
471
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)
476 {
477         if (argc != 1) {
478                 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
479                 return False;
480         }
481
482         /* Send a message and register our interest in a reply */
483
484         if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
485                 return False;
486
487         messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
488
489         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
490
491         /* No replies were received within the timeout period */
492
493         if (num_replies == 0)
494                 printf("No replies received\n");
495
496         messaging_deregister(msg_ctx, MSG_PONG, NULL);
497
498         return num_replies;
499 }
500
501 /* Set profiling options */
502
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)
507 {
508         int v;
509
510         if (argc != 2) {
511                 fprintf(stderr, "Usage: smbcontrol <dest> profile "
512                         "<off|count|on|flush>\n");
513                 return False;
514         }
515
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;
527         }
528
529         return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
530 }
531
532 /* Return the profiling level */
533
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)
539 {
540         int level;
541         const char *s;
542
543         num_replies++;
544
545         if (data->length != sizeof(int)) {
546                 fprintf(stderr, "invalid message length %ld returned\n",
547                         (unsigned long)data->length);
548                 return;
549         }
550
551         memcpy(&level, data->data, sizeof(int));
552
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;
569         }
570
571         printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
572 }
573
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)
579 {
580         int v = 0;
581
582         /* Send back a dummy reply */
583
584         send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
585 }
586
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)
591 {
592         if (argc != 1) {
593                 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
594                 return False;
595         }
596
597         /* Send a message and register our interest in a reply */
598
599         if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
600                 return False;
601
602         messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
603         messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
604                            profilelevel_rqst);
605
606         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
607
608         /* No replies were received within the timeout period */
609
610         if (num_replies == 0)
611                 printf("No replies received\n");
612
613         messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
614
615         return num_replies;
616 }
617
618 /* Display debug level settings */
619
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)
624 {
625         if (argc != 1) {
626                 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
627                 return False;
628         }
629
630         /* Send a message and register our interest in a reply */
631
632         if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
633                 return False;
634
635         messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
636
637         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
638
639         /* No replies were received within the timeout period */
640
641         if (num_replies == 0)
642                 printf("No replies received\n");
643
644         messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
645
646         return num_replies;
647 }
648
649 /* Send a print notify message */
650
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)
655 {
656         const char *cmd;
657
658         /* Check for subcommand */
659
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");
669
670                 return False;
671         }
672
673         cmd = argv[1];
674
675         if (strcmp(cmd, "queuepause") == 0) {
676
677                 if (argc != 3) {
678                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
679                                 " queuepause <printername>\n");
680                         return False;
681                 }
682
683                 notify_printer_status_byname(ev_ctx, msg_ctx, argv[2],
684                                              PRINTER_STATUS_PAUSED);
685
686                 goto send;
687
688         } else if (strcmp(cmd, "queueresume") == 0) {
689
690                 if (argc != 3) {
691                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
692                                 " queuereume <printername>\n");
693                         return False;
694                 }
695
696                 notify_printer_status_byname(ev_ctx, msg_ctx, argv[2],
697                                              PRINTER_STATUS_OK);
698
699                 goto send;
700
701         } else if (strcmp(cmd, "jobpause") == 0) {
702                 int jobid;
703
704                 if (argc != 4) {
705                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
706                                 " jobpause <printername> <unix-jobid>\n");
707                         return False;
708                 }
709
710                 jobid = atoi(argv[3]);
711
712                 notify_job_status_byname(
713                         ev_ctx, msg_ctx,
714                         argv[2], jobid, JOB_STATUS_PAUSED,
715                         SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
716
717                 goto send;
718
719         } else if (strcmp(cmd, "jobresume") == 0) {
720                 int jobid;
721
722                 if (argc != 4) {
723                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
724                                 " jobpause <printername> <unix-jobid>\n");
725                         return False;
726                 }
727
728                 jobid = atoi(argv[3]);
729
730                 notify_job_status_byname(
731                         ev_ctx, msg_ctx,
732                         argv[2], jobid, JOB_STATUS_QUEUED,
733                         SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
734
735                 goto send;
736
737         } else if (strcmp(cmd, "jobdelete") == 0) {
738                 int jobid;
739
740                 if (argc != 4) {
741                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
742                                 " jobpause <printername> <unix-jobid>\n");
743                         return False;
744                 }
745
746                 jobid = atoi(argv[3]);
747
748                 notify_job_status_byname(
749                         ev_ctx, msg_ctx,
750                         argv[2], jobid, JOB_STATUS_DELETING,
751                         SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
752
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);
758
759                 goto send;
760
761         } else if (strcmp(cmd, "printer") == 0) {
762                 uint32_t attribute;
763
764                 if (argc != 5) {
765                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
766                                 "printer <printername> <comment|port|driver> "
767                                 "<value>\n");
768                         return False;
769                 }
770
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;
781                 }
782
783                 notify_printer_byname(ev_ctx, msg_ctx, argv[2], attribute,
784                                       discard_const_p(char, argv[4]));
785
786                 goto send;
787         }
788
789         fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
790         return False;
791
792 send:
793         print_notify_send_messages(msg_ctx, 0);
794         return True;
795 }
796
797 /* Close a share */
798
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)
803 {
804         if (argc != 2) {
805                 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
806                         "<sharename>\n");
807                 return False;
808         }
809
810         return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
811                             strlen(argv[1]) + 1);
812 }
813
814 /*
815  * Close a share if access denied by now
816  **/
817
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)
823 {
824         if (argc != 2) {
825                 fprintf(stderr, "Usage: smbcontrol <dest> close-denied-share "
826                         "<sharename>\n");
827                 return False;
828         }
829
830         return send_message(
831                 msg_ctx,
832                 pid,
833                 MSG_SMB_FORCE_TDIS_DENIED,
834                 argv[1],
835                 strlen(argv[1]) + 1);
836 }
837
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)
843 {
844         if (argc != 2) {
845                 fprintf(stderr, "Usage: smbcontrol <dest> kill-client-ip "
846                         "<IP address>\n");
847                 return false;
848         }
849
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;
853         }
854
855         return send_message(msg_ctx, pid, MSG_SMB_KILL_CLIENT_IP,
856                             argv[1], strlen(argv[1]) + 1);
857 }
858
859 /* Tell winbindd an IP got dropped */
860
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)
865 {
866         if (argc != 2) {
867                 fprintf(stderr, "Usage: smbcontrol <dest> ip-dropped "
868                         "<ip-address>\n");
869                 return False;
870         }
871
872         return send_message(msg_ctx, pid, MSG_WINBIND_IP_DROPPED, argv[1],
873                             strlen(argv[1]) + 1);
874 }
875
876 /* Display talloc pool usage */
877
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)
882 {
883         pid_t pid = procid_to_pid(&dst);
884         int stdout_fd = 1;
885
886         if (argc != 1) {
887                 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
888                 return False;
889         }
890
891         if (pid == 0) {
892                 fprintf(stderr, "Can only send to a specific PID\n");
893                 return false;
894         }
895
896         messaging_send_iov(
897                 msg_ctx,
898                 dst,
899                 MSG_REQ_POOL_USAGE,
900                 NULL,
901                 0,
902                 &stdout_fd,
903                 1);
904
905         return true;
906 }
907
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)
914 {
915         pid_t pid = procid_to_pid(&dst);
916         int stdout_fd = 1;
917
918         if (argc != 1) {
919                 fprintf(stderr,
920                         "Usage: smbcontrol <dest> rpc-dump-status\n");
921                 return False;
922         }
923
924         if (pid == 0) {
925                 fprintf(stderr, "Can only send to a specific PID\n");
926                 return false;
927         }
928
929         messaging_send_iov(
930                 msg_ctx,
931                 dst,
932                 MSG_RPC_DUMP_STATUS,
933                 NULL,
934                 0,
935                 &stdout_fd,
936                 1);
937
938         return true;
939 }
940
941 /* Fetch and print the ringbuf log */
942
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)
948 {
949         printf("%s", (const char *)data->data);
950         num_replies++;
951 }
952
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)
957 {
958         if (argc != 1) {
959                 fprintf(stderr, "Usage: smbcontrol <dest> ringbuf-log\n");
960                 return false;
961         }
962
963         messaging_register(msg_ctx, NULL, MSG_RINGBUF_LOG,
964                            print_ringbuf_log_cb);
965
966         /* Send a message and register our interest in a reply */
967
968         if (!send_message(msg_ctx, pid, MSG_REQ_RINGBUF_LOG, NULL, 0)) {
969                 return false;
970         }
971
972         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
973
974         /* No replies were received within the timeout period */
975
976         if (num_replies == 0) {
977                 printf("No replies received\n");
978         }
979
980         messaging_deregister(msg_ctx, MSG_RINGBUF_LOG, NULL);
981
982         return num_replies != 0;
983 }
984
985 /* Perform a dmalloc mark */
986
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)
991 {
992         if (argc != 1) {
993                 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
994                 return False;
995         }
996
997         return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
998 }
999
1000 /* Perform a dmalloc changed */
1001
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)
1006 {
1007         if (argc != 1) {
1008                 fprintf(stderr, "Usage: smbcontrol <dest> "
1009                         "dmalloc-log-changed\n");
1010                 return False;
1011         }
1012
1013         return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
1014                             NULL, 0);
1015 }
1016
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)
1020 {
1021         uint32_t num_children;
1022
1023         if (data->length != sizeof(uint32_t)) {
1024                 printf("Invalid response: %d bytes long\n",
1025                        (int)data->length);
1026                 goto done;
1027         }
1028         num_children = IVAL(data->data, 0);
1029         printf("%u children\n", (unsigned)num_children);
1030 done:
1031         num_replies++;
1032 }
1033
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)
1038 {
1039         if (argc != 1) {
1040                 fprintf(stderr, "Usage: smbcontrol <dest> num-children\n");
1041                 return False;
1042         }
1043
1044         messaging_register(msg_ctx, NULL, MSG_SMB_NUM_CHILDREN,
1045                            print_uint32_cb);
1046
1047         /* Send a message and register our interest in a reply */
1048
1049         if (!send_message(msg_ctx, pid, MSG_SMB_TELL_NUM_CHILDREN, NULL, 0))
1050                 return false;
1051
1052         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1053
1054         /* No replies were received within the timeout period */
1055
1056         if (num_replies == 0)
1057                 printf("No replies received\n");
1058
1059         messaging_deregister(msg_ctx, MSG_SMB_NUM_CHILDREN, NULL);
1060
1061         return num_replies;
1062 }
1063
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)
1068 {
1069         int ret;
1070
1071         ret = messaging_cleanup(msg_ctx, pid.pid);
1072
1073         printf("cleanup(%u) returned %s\n", (unsigned)pid.pid,
1074                ret ? strerror(ret) : "ok");
1075
1076         return (ret == 0);
1077 }
1078
1079 /* Shutdown a server process */
1080
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)
1085 {
1086         if (argc != 1) {
1087                 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
1088                 return False;
1089         }
1090
1091         return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
1092 }
1093
1094 /* Notify a driver upgrade */
1095
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)
1100 {
1101         if (argc != 2) {
1102                 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
1103                         "<driver-name>\n");
1104                 return False;
1105         }
1106
1107         return send_message(msg_ctx, pid, MSG_PRINTER_DRVUPGRADE, argv[1],
1108                             strlen(argv[1]) + 1);
1109 }
1110
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)
1115 {
1116         TDB_CONTEXT *tdb;
1117         char *db_path;
1118
1119         if (argc != 1) {
1120                 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
1121                 return False;
1122         }
1123
1124         db_path = state_path(talloc_tos(), "winbindd_cache.tdb");
1125         if (db_path == NULL) {
1126                 return false;
1127         }
1128
1129         /* Remove the entry in the winbindd_cache tdb to tell a later
1130            starting winbindd that we're online. */
1131
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;
1138         }
1139
1140         TALLOC_FREE(db_path);
1141         tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
1142         tdb_close(tdb);
1143
1144         return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
1145 }
1146
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)
1151 {
1152         TDB_CONTEXT *tdb;
1153         bool ret = False;
1154         int retry = 0;
1155         char *db_path;
1156
1157         if (argc != 1) {
1158                 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
1159                 return False;
1160         }
1161
1162         db_path = state_path(talloc_tos(), "winbindd_cache.tdb");
1163         if (db_path == NULL) {
1164                 return false;
1165         }
1166
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... */
1170
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);
1175
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;
1181         }
1182         TALLOC_FREE(db_path);
1183
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. */
1190
1191         for (retry = 0; retry < 5; retry++) {
1192                 uint8_t buf[4];
1193                 TDB_DATA d = { .dptr = buf, .dsize = sizeof(buf) };
1194
1195                 SIVAL(buf, 0, time(NULL));
1196
1197                 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
1198
1199                 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
1200                                    NULL, 0);
1201
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;
1207                 }
1208
1209                 SAFE_FREE(d.dptr);
1210                 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
1211         }
1212
1213         tdb_close(tdb);
1214         return ret;
1215 }
1216
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)
1221 {
1222         if (argc != 1) {
1223                 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
1224                 return False;
1225         }
1226
1227         messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
1228                            print_pid_string_cb);
1229
1230         if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, NULL, 0)) {
1231                 return False;
1232         }
1233
1234         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1235
1236         /* No replies were received within the timeout period */
1237
1238         if (num_replies == 0)
1239                 printf("No replies received\n");
1240
1241         messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
1242
1243         return num_replies;
1244 }
1245
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)
1250 {
1251         const char *domain = NULL;
1252         int domain_len = 0;
1253
1254         if (argc < 1 || argc > 2) {
1255                 fprintf(stderr, "Usage: smbcontrol <dest> dump-domain-list "
1256                         "<domain>\n");
1257                 return false;
1258         }
1259
1260         if (argc == 2) {
1261                 domain = argv[1];
1262                 domain_len = strlen(argv[1]) + 1;
1263         }
1264
1265         messaging_register(msg_ctx, NULL, MSG_WINBIND_DUMP_DOMAIN_LIST,
1266                            print_pid_string_cb);
1267
1268         if (!send_message(msg_ctx, pid, MSG_WINBIND_DUMP_DOMAIN_LIST,
1269                           domain, domain_len))
1270         {
1271                 return false;
1272         }
1273
1274         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1275
1276         /* No replies were received within the timeout period */
1277
1278         if (num_replies == 0) {
1279                 printf("No replies received\n");
1280         }
1281
1282         messaging_deregister(msg_ctx, MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
1283
1284         return num_replies;
1285 }
1286
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)
1291 {
1292         if (argc != 1) {
1293                 fprintf(stderr, "Usage: smbcontrol <dest> disconnect-dc\n");
1294                 return False;
1295         }
1296
1297         return send_message(msg_ctx, pid, MSG_WINBIND_DISCONNECT_DC, NULL, 0);
1298 }
1299
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)
1305 {
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++;
1311 }
1312
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)
1317 {
1318         struct server_id myid;
1319
1320         myid = messaging_server_id(msg_ctx);
1321
1322         if (argc != 1) {
1323                 fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
1324                 return False;
1325         }
1326
1327         messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
1328                            winbind_validate_cache_cb);
1329
1330         if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
1331                           sizeof(myid))) {
1332                 return False;
1333         }
1334
1335         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1336
1337         if (num_replies == 0) {
1338                 printf("No replies received\n");
1339         }
1340
1341         messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);
1342
1343         return num_replies;
1344 }
1345
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)
1350 {
1351         if (argc != 1) {
1352                 fprintf(stderr, "Usage: smbcontrol ldap_server reload-certs \n");
1353                 return false;
1354         }
1355
1356         return send_message(msg_ctx, pid, MSG_RELOAD_TLS_CERTIFICATES, NULL, 0);
1357 }
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)
1362 {
1363         if (argc != 1) {
1364                 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1365                 return False;
1366         }
1367
1368         return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1369 }
1370
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)
1375 {
1376         if (argc != 1) {
1377                 fprintf(stderr, "Usage: smbcontrol <dest> reload-printers\n");
1378                 return False;
1379         }
1380
1381         return send_message(msg_ctx, pid, MSG_PRINTER_PCAP, NULL, 0);
1382 }
1383
1384 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1385 {
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);
1393 }
1394
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)
1399 {
1400         struct packet_struct p;
1401
1402         if (argc != 2) {
1403                 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1404                 return False;
1405         }
1406
1407         ZERO_STRUCT(p);
1408
1409         p.ip = interpret_addr2(argv[1]);
1410         p.port = 137;
1411         p.packet_type = NMB_PACKET;
1412
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;
1429
1430         return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1431 }
1432
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)
1437 {
1438         if (argc != 1) {
1439                 fprintf(stderr, "Usage: smbcontrol smbd notify-cleanup\n");
1440                 return false;
1441         }
1442         return send_message(msg_ctx, pid, MSG_SMB_NOTIFY_CLEANUP, NULL, 0);
1443 }
1444
1445 /* A list of message type supported */
1446
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[] = {
1455         {
1456                 .name = "debug",
1457                 .fn   = do_debug,
1458                 .help = "Set debuglevel",
1459         },
1460         {
1461                 .name = "idmap",
1462                 .fn   = do_idmap,
1463                 .help = "Manipulate idmap cache",
1464         },
1465         {
1466                 .name = "force-election",
1467                 .fn   = do_election,
1468                 .help = "Force a browse election",
1469         },
1470         {
1471                 .name = "ping",
1472                 .fn   = do_ping,
1473                 .help = "Elicit a response",
1474         },
1475         {
1476                 .name = "profile",
1477                 .fn   = do_profile,
1478                 .help = "",
1479         },
1480         {
1481                 .name = "inject",
1482                 .fn   = do_inject_fault,
1483                 .help = "Inject a fatal signal into a running smbd"},
1484         {
1485                 .name = "stacktrace",
1486                 .fn   = do_daemon_stack_trace,
1487                 .help = "Display a stack trace of a daemon",
1488         },
1489         {
1490                 .name = "profilelevel",
1491                 .fn   = do_profilelevel,
1492                 .help = "",
1493         },
1494         {
1495                 .name = "debuglevel",
1496                 .fn   = do_debuglevel,
1497                 .help = "Display current debuglevels",
1498         },
1499         {
1500                 .name = "printnotify",
1501                 .fn   = do_printnotify,
1502                 .help = "Send a print notify message",
1503         },
1504         {
1505                 .name = "close-share",
1506                 .fn   = do_closeshare,
1507                 .help = "Forcibly disconnect a share",
1508         },
1509         {
1510                 .name = "close-denied-share",
1511                 .fn   = do_close_denied_share,
1512                 .help = "Forcibly disconnect users from shares disallowed now",
1513         },
1514         {
1515                 .name = "kill-client-ip",
1516                 .fn   = do_kill_client_by_ip,
1517                 .help = "Forcibly disconnect a client with a specific IP address",
1518         },
1519         {
1520                 .name = "ip-dropped",
1521                 .fn   = do_ip_dropped,
1522                 .help = "Tell winbind that an IP got dropped",
1523         },
1524         {
1525                 .name = "pool-usage",
1526                 .fn   = do_poolusage,
1527                 .help = "Display talloc memory usage",
1528         },
1529         {
1530                 .name = "rpc-dump-status",
1531                 .fn   = do_rpc_dump_status,
1532                 .help = "Display rpc status",
1533         },
1534         {
1535                 .name = "ringbuf-log",
1536                 .fn   = do_ringbuflog,
1537                 .help = "Display ringbuf log",
1538         },
1539         {
1540                 .name = "dmalloc-mark",
1541                 .fn   = do_dmalloc_mark,
1542                 .help = "",
1543         },
1544         {
1545                 .name = "dmalloc-log-changed",
1546                 .fn   = do_dmalloc_changed,
1547                 .help = "",
1548         },
1549         {
1550                 .name = "shutdown",
1551                 .fn   = do_shutdown,
1552                 .help = "Shut down daemon",
1553         },
1554         {
1555                 .name = "drvupgrade",
1556                 .fn   = do_drvupgrade,
1557                 .help = "Notify a printer driver has changed",
1558         },
1559         {
1560                 .name = "reload-certs",
1561                 .fn   = do_reload_certs,
1562                 .help = "Reload TLS certificates"
1563         },
1564         {
1565                 .name = "reload-config",
1566                 .fn   = do_reload_config,
1567                 .help = "Force smbd or winbindd to reload config file"},
1568         {
1569                 .name = "reload-printers",
1570                 .fn   = do_reload_printers,
1571                 .help = "Force smbd to reload printers"},
1572         {
1573                 .name = "nodestatus",
1574                 .fn   = do_nodestatus,
1575                 .help = "Ask nmbd to do a node status request"},
1576         {
1577                 .name = "online",
1578                 .fn   = do_winbind_online,
1579                 .help = "Ask winbind to go into online state"},
1580         {
1581                 .name = "offline",
1582                 .fn   = do_winbind_offline,
1583                 .help = "Ask winbind to go into offline state"},
1584         {
1585                 .name = "onlinestatus",
1586                 .fn   = do_winbind_onlinestatus,
1587                 .help = "Request winbind online status"},
1588         {
1589                 .name = "validate-cache" ,
1590                 .fn   = do_winbind_validate_cache,
1591                 .help = "Validate winbind's credential cache",
1592         },
1593         {
1594                 .name = "dump-domain-list",
1595                 .fn   = do_winbind_dump_domain_list,
1596                 .help = "Dump winbind domain list"},
1597         {
1598                 .name = "disconnect-dc",
1599                 .fn   = do_msg_disconnect_dc,
1600         },
1601         {
1602                 .name = "notify-cleanup",
1603                 .fn   = do_notify_cleanup,
1604         },
1605         {
1606                 .name = "num-children",
1607                 .fn   = do_num_children,
1608                 .help = "Print number of smbd child processes",
1609         },
1610         {
1611                 .name = "msg-cleanup",
1612                 .fn   = do_msg_cleanup,
1613         },
1614         {
1615                 .name = "noop",
1616                 .fn   = do_noop,
1617                 .help = "Do nothing",
1618         },
1619         {
1620                 .name = "sleep",
1621                 .fn   = do_sleep,
1622                 .help = "Cause the target process to sleep",
1623         },
1624         { .name = NULL, },
1625 };
1626
1627 /* Display usage information */
1628
1629 static void usage(poptContext pc)
1630 {
1631         int i;
1632
1633         poptPrintHelp(pc, stderr, 0);
1634
1635         fprintf(stderr, "\n");
1636         fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\", "
1637                 "\"ldap_server\" or a process ID\n");
1638
1639         fprintf(stderr, "\n");
1640         fprintf(stderr, "<message-type> is one of:\n");
1641
1642         for (i = 0; msg_types[i].name; i++) {
1643                 const char *help = msg_types[i].help;
1644                 if (help == NULL) {
1645                         help = "";
1646                 }
1647                 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name, help);
1648         }
1649
1650         fprintf(stderr, "\n");
1651
1652         exit(1);
1653 }
1654
1655 /* Return the pid number for a string destination */
1656
1657 static struct server_id parse_dest(struct messaging_context *msg,
1658                                    const char *dest)
1659 {
1660         struct server_id result = {
1661                 .pid = (uint64_t)-1,
1662         };
1663         pid_t pid;
1664         struct server_id_db *names_db = NULL;
1665         bool ok;
1666
1667         /* Zero is a special return value for broadcast to all processes */
1668
1669         if (strequal(dest, "all")) {
1670                 return interpret_pid(MSG_BROADCAST_PID_STR);
1671         }
1672
1673         /* Try self - useful for testing */
1674
1675         if (strequal(dest, "self")) {
1676                 return messaging_server_id(msg);
1677         }
1678
1679         /* Fix winbind typo. */
1680         if (strequal(dest, "winbind")) {
1681                 dest = "winbindd";
1682         }
1683
1684         /* Check for numeric pid number */
1685         result = interpret_pid(dest);
1686
1687         /* Zero isn't valid if not "all". */
1688         if (result.pid && procid_valid(&result)) {
1689                 return result;
1690         }
1691
1692         /* Look up other destinations in pidfile directory */
1693
1694         if ((pid = pidfile_pid(lp_pid_directory(), dest)) != 0) {
1695                 return pid_to_procid(pid);
1696         }
1697
1698         names_db = messaging_names_db(msg);
1699         if (names_db == NULL) {
1700                 goto fail;
1701         }
1702         ok = server_id_db_lookup_one(names_db, dest, &result);
1703         if (ok) {
1704                 return result;
1705         }
1706
1707 fail:
1708         fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1709
1710         return result;
1711 }
1712
1713 /* Execute smbcontrol command */
1714
1715 static bool do_command(struct tevent_context *ev_ctx,
1716                        struct messaging_context *msg_ctx,
1717                        int argc, const char **argv)
1718 {
1719         const char *dest = argv[0], *command = argv[1];
1720         struct server_id pid;
1721         int i;
1722
1723         /* Check destination */
1724
1725         pid = parse_dest(msg_ctx, dest);
1726         if (!procid_valid(&pid)) {
1727                 return False;
1728         }
1729
1730         /* Check command */
1731
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);
1736         }
1737
1738         fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1739
1740         return False;
1741 }
1742
1743 static void smbcontrol_help(poptContext pc,
1744                     enum poptCallbackReason preason,
1745                     struct poptOption * poption,
1746                     const char * parg,
1747                     void * pdata)
1748 {
1749         if (poption->shortName != '?') {
1750                 poptPrintUsage(pc, stdout, 0);
1751         } else {
1752                 usage(pc);
1753         }
1754
1755         exit(0);
1756 }
1757
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 },
1763         {0}
1764 } ;
1765
1766 /* Main program */
1767
1768 int main(int argc, const char **argv)
1769 {
1770         poptContext pc;
1771         int opt;
1772         struct tevent_context *evt_ctx;
1773         struct messaging_context *msg_ctx;
1774
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" },
1781
1782                 POPT_COMMON_SAMBA
1783                 POPT_COMMON_VERSION
1784                 POPT_TABLEEND
1785         };
1786         TALLOC_CTX *frame = talloc_stackframe();
1787         struct loadparm_context *lp_ctx = NULL;
1788         int ret = 0;
1789         bool ok;
1790
1791         smb_init_locale();
1792
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);
1800         }
1801         lp_ctx = samba_cmdline_get_lp_ctx();
1802         lpcfg_set_cmdline(lp_ctx, "log level", "0");
1803
1804         /* Parse command line arguments using popt */
1805
1806         pc = samba_popt_get_context(getprogname(),
1807                                     argc,
1808                                     argv,
1809                                     long_options,
1810                                     0);
1811         if (pc == NULL) {
1812                 DBG_ERR("Failed to setup popt context!\n");
1813                 TALLOC_FREE(frame);
1814                 exit(1);
1815         }
1816
1817         poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1818                                "<parameters>");
1819
1820         if (argc == 1)
1821                 usage(pc);
1822
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;
1831                 }
1832         }
1833
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. */
1837
1838         argv = (const char **)poptGetArgs(pc);
1839         argc = 0;
1840         if (argv != NULL) {
1841                 while (argv[argc] != NULL) {
1842                         argc++;
1843                 }
1844         }
1845
1846         if (argc <= 1)
1847                 usage(pc);
1848
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);
1855         }
1856
1857         evt_ctx = global_event_context();
1858
1859         /* Need to invert sense of return code -- samba
1860          * routines mostly return True==1 for success, but
1861          * shell needs 0. */
1862
1863         ret = !do_command(evt_ctx, msg_ctx, argc, argv);
1864
1865         cmdline_messaging_context_free();
1866         gfree_all();
1867         poptFreeContext(pc);
1868         TALLOC_FREE(frame);
1869         return ret;
1870 }