r24843: Add a "validate-cache" control message to winbindd.
[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
28 #if HAVE_LIBUNWIND_H
29 #include <libunwind.h>
30 #endif
31
32 #if HAVE_LIBUNWIND_PTRACE_H
33 #include <libunwind-ptrace.h>
34 #endif
35
36 #if HAVE_SYS_PTRACE_H
37 #include <sys/ptrace.h>
38 #endif
39
40 /* Default timeout value when waiting for replies (in seconds) */
41
42 #define DEFAULT_TIMEOUT 10
43
44 static int timeout = DEFAULT_TIMEOUT;
45 static int num_replies;         /* Used by message callback fns */
46
47 /* Send a message to a destination pid.  Zero means broadcast smbd. */
48
49 static BOOL send_message(struct messaging_context *msg_ctx,
50                          struct server_id pid, int msg_type,
51                          const void *buf, int len)
52 {
53         BOOL ret;
54         int n_sent = 0;
55
56         if (procid_to_pid(&pid) != 0)
57                 return NT_STATUS_IS_OK(
58                         messaging_send_buf(msg_ctx, pid, msg_type,
59                                            (uint8 *)buf, len));
60
61         ret = message_send_all(msg_ctx, msg_type, buf, len, &n_sent);
62         DEBUG(10,("smbcontrol/send_message: broadcast message to "
63                   "%d processes\n", n_sent));
64         
65         return ret;
66 }
67
68 static void timeout_handler(struct event_context *event_ctx,
69                             struct timed_event *te,
70                             const struct timeval *now,
71                             void *private_data)
72 {
73         BOOL *timed_out = (BOOL *)private_data;
74         TALLOC_FREE(te);
75         *timed_out = True;
76 }
77
78 /* Wait for one or more reply messages */
79
80 static void wait_replies(struct messaging_context *msg_ctx,
81                          BOOL multiple_replies)
82 {
83         struct timed_event *te;
84         BOOL timed_out = False;
85
86         if (!(te = event_add_timed(messaging_event_context(msg_ctx), NULL,
87                                    timeval_current_ofs(timeout, 0),
88                                    "smbcontrol_timeout",
89                                    timeout_handler, (void *)&timed_out))) {
90                 DEBUG(0, ("event_add_timed failed\n"));
91                 return;
92         }
93
94         while (!timed_out) {
95                 message_dispatch(msg_ctx);
96                 if (num_replies > 0 && !multiple_replies)
97                         break;
98                 event_loop_once(messaging_event_context(msg_ctx));
99         }
100 }
101
102 /* Message handler callback that displays the PID and a string on stdout */
103
104 static void print_pid_string_cb(struct messaging_context *msg,
105                                 void *private_data, 
106                                 uint32_t msg_type, 
107                                 struct server_id pid,
108                                 DATA_BLOB *data)
109 {
110         printf("PID %u: %.*s", (unsigned int)procid_to_pid(&pid),
111                (int)data->length, (const char *)data->data);
112         num_replies++;
113 }
114
115 /* Message handler callback that displays a string on stdout */
116
117 static void print_string_cb(struct messaging_context *msg,
118                             void *private_data, 
119                             uint32_t msg_type, 
120                             struct server_id pid,
121                             DATA_BLOB *data)
122 {
123         printf("%.*s", (int)data->length, (const char *)data->data);
124         num_replies++;
125 }
126
127 /* Send no message.  Useful for testing. */
128
129 static BOOL do_noop(struct messaging_context *msg_ctx,
130                     const struct server_id pid,
131                     const int argc, const char **argv)
132 {
133         if (argc != 1) {
134                 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
135                 return False;
136         }
137
138         /* Move along, nothing to see here */
139
140         return True;
141 }
142
143 /* Send a debug string */
144
145 static BOOL do_debug(struct messaging_context *msg_ctx,
146                      const struct server_id pid,
147                      const int argc, const char **argv)
148 {
149         if (argc != 2) {
150                 fprintf(stderr, "Usage: smbcontrol <dest> debug "
151                         "<debug-string>\n");
152                 return False;
153         }
154
155         return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
156                             strlen(argv[1]) + 1);
157 }
158
159 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
160
161 /* Return the name of a process given it's PID. This will only work on Linux,
162  * but that's probably moot since this whole stack tracing implementatino is
163  * Linux-specific anyway.
164  */
165 static const char * procname(pid_t pid, char * buf, size_t bufsz)
166 {
167         char path[64];
168         FILE * fp;
169
170         snprintf(path, sizeof(path), "/proc/%llu/cmdline",
171                 (unsigned long long)pid);
172         if ((fp = fopen(path, "r")) == NULL) {
173                 return NULL;
174         }
175
176         fgets(buf, bufsz, fp);
177
178         fclose(fp);
179         return buf;
180 }
181
182 static void print_stack_trace(pid_t pid, int * count)
183 {
184         void *              pinfo = NULL;
185         unw_addr_space_t    aspace = NULL;
186         unw_cursor_t        cursor;
187         unw_word_t          ip, sp;
188
189         char                nbuf[256];
190         unw_word_t          off;
191
192         int ret;
193
194         if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
195                 fprintf(stderr,
196                         "Failed to attach to process %llu: %s\n",
197                         (unsigned long long)pid, strerror(errno));
198                 return;
199         }
200
201         /* Wait until the attach is complete. */
202         waitpid(pid, NULL, 0);
203
204         if (((pinfo = _UPT_create(pid)) == NULL) ||
205             ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
206                 /* Probably out of memory. */
207                 fprintf(stderr,
208                         "Unable to initialize stack unwind for process %llu\n",
209                         (unsigned long long)pid);
210                 goto cleanup;
211         }
212
213         if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
214                 fprintf(stderr,
215                         "Unable to unwind stack for process %llu: %s\n",
216                         (unsigned long long)pid, unw_strerror(ret));
217                 goto cleanup;
218         }
219
220         if (*count > 0) {
221                 printf("\n");
222         }
223
224         if (procname(pid, nbuf, sizeof(nbuf))) {
225                 printf("Stack trace for process %llu (%s):\n",
226                         (unsigned long long)pid, nbuf);
227         } else {
228                 printf("Stack trace for process %llu:\n",
229                         (unsigned long long)pid);
230         }
231
232         while (unw_step(&cursor) > 0) {
233                 ip = sp = off = 0;
234                 unw_get_reg(&cursor, UNW_REG_IP, &ip);
235                 unw_get_reg(&cursor, UNW_REG_SP, &sp);
236
237                 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
238                 if (ret != 0 && ret != -UNW_ENOMEM) {
239                         snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
240                 }
241                 printf("    %s + %#llx [ip=%#llx] [sp=%#llx]\n",
242                         nbuf, (long long)off, (long long)ip,
243                         (long long)sp);
244         }
245
246         (*count)++;
247
248 cleanup:
249         if (aspace) {
250                 unw_destroy_addr_space(aspace);
251         }
252
253         if (pinfo) {
254                 _UPT_destroy(pinfo);
255         }
256
257         ptrace(PTRACE_DETACH, pid, NULL, NULL);
258 }
259
260 static int stack_trace_connection(struct db_record *rec,
261                                   const struct connections_key *key,
262                                   const struct connections_data *crec,
263                                   void *priv)
264 {
265         print_stack_trace(procid_to_pid(&crec->pid), (int *)priv);
266
267         return 0;
268 }
269
270 static BOOL do_daemon_stack_trace(struct messaging_context *msg_ctx,
271                                   const struct server_id pid,
272                        const int argc, const char **argv)
273 {
274         fprintf(stderr,
275                 "Daemon stack tracing is not supported on this platform\n");
276         return False;
277
278         pid_t   dest;
279         int     count = 0;
280
281         if (argc != 1) {
282                 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
283                 return False;
284         }
285
286         dest = procid_to_pid(&pid);
287
288         if (dest != 0) {
289                 /* It would be nice to be able to make sure that this PID is
290                  * the PID of a smbd/winbind/nmbd process, not some random PID
291                  * the user liked the look of. It doesn't seem like it's worth
292                  * the effort at the moment, however.
293                  */
294                 print_stack_trace(dest, &count);
295         } else {
296                 connections_forall(stack_trace_connection, &count);
297         }
298
299         return True;
300 }
301
302 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
303
304 static BOOL do_daemon_stack_trace(struct messaging_context *msg_ctx,
305                                   const struct server_id pid,
306                        const int argc, const char **argv)
307 {
308         fprintf(stderr,
309                 "Daemon stack tracing is not supported on this platform\n");
310         return False;
311 }
312
313 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
314
315 /* Inject a fault (fatal signal) into a running smbd */
316
317 static BOOL do_inject_fault(struct messaging_context *msg_ctx,
318                             const struct server_id pid,
319                        const int argc, const char **argv)
320 {
321         if (argc != 2) {
322                 fprintf(stderr, "Usage: smbcontrol <dest> inject "
323                         "<bus|hup|term|internal|segv>\n");
324                 return False;
325         }
326
327 #ifndef DEVELOPER
328         fprintf(stderr, "Fault injection is only available in "
329                 "developer builds\n");
330         return False;
331 #else /* DEVELOPER */
332         {
333                 int sig = 0;
334
335                 if (strcmp(argv[1], "bus") == 0) {
336                         sig = SIGBUS;
337                 } else if (strcmp(argv[1], "hup") == 0) {
338                         sig = SIGHUP;
339                 } else if (strcmp(argv[1], "term") == 0) {
340                         sig = SIGTERM;
341                 } else if (strcmp(argv[1], "segv") == 0) {
342                         sig = SIGSEGV;
343                 } else if (strcmp(argv[1], "internal") == 0) {
344                         /* Force an internal error, ie. an unclean exit. */
345                         sig = -1;
346                 } else {
347                         fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
348                         return False;
349                 }
350
351                 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
352                                     &sig, sizeof(int));
353         }
354 #endif /* DEVELOPER */
355 }
356
357 /* Force a browser election */
358
359 static BOOL do_election(struct messaging_context *msg_ctx,
360                         const struct server_id pid,
361                         const int argc, const char **argv)
362 {
363         if (argc != 1) {
364                 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
365                 return False;
366         }
367
368         return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
369 }
370
371 /* Ping a samba daemon process */
372
373 static void pong_cb(struct messaging_context *msg,
374                     void *private_data, 
375                     uint32_t msg_type, 
376                     struct server_id pid,
377                     DATA_BLOB *data)
378 {
379         char *src_string = procid_str(NULL, &pid);
380         printf("PONG from pid %s\n", src_string);
381         TALLOC_FREE(src_string);
382         num_replies++;
383 }
384
385 static BOOL do_ping(struct messaging_context *msg_ctx,
386                     const struct server_id pid,
387                     const int argc, const char **argv)
388 {
389         if (argc != 1) {
390                 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
391                 return False;
392         }
393
394         /* Send a message and register our interest in a reply */
395
396         if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
397                 return False;
398
399         messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
400
401         wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
402
403         /* No replies were received within the timeout period */
404
405         if (num_replies == 0)
406                 printf("No replies received\n");
407
408         messaging_deregister(msg_ctx, MSG_PONG, NULL);
409
410         return num_replies;
411 }
412
413 /* Set profiling options */
414
415 static BOOL do_profile(struct messaging_context *msg_ctx,
416                        const struct server_id pid,
417                        const int argc, const char **argv)
418 {
419         int v;
420
421         if (argc != 2) {
422                 fprintf(stderr, "Usage: smbcontrol <dest> profile "
423                         "<off|count|on|flush>\n");
424                 return False;
425         }
426
427         if (strcmp(argv[1], "off") == 0) {
428                 v = 0;
429         } else if (strcmp(argv[1], "count") == 0) {
430                 v = 1;
431         } else if (strcmp(argv[1], "on") == 0) {
432                 v = 2;
433         } else if (strcmp(argv[1], "flush") == 0) {
434                 v = 3;
435         } else {
436                 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
437                 return False;
438         }
439
440         return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
441 }
442
443 /* Return the profiling level */
444
445 static void profilelevel_cb(struct messaging_context *msg_ctx,
446                             void *private_data, 
447                             uint32_t msg_type, 
448                             struct server_id pid,
449                             DATA_BLOB *data)
450 {
451         int level;
452         const char *s;
453
454         num_replies++;
455
456         if (data->length != sizeof(int)) {
457                 fprintf(stderr, "invalid message length %ld returned\n", 
458                         (unsigned long)data->length);
459                 return;
460         }
461
462         memcpy(&level, data->data, sizeof(int));
463
464         switch (level) {
465         case 0:
466                 s = "not enabled";
467                 break;
468         case 1:
469                 s = "off";
470                 break;
471         case 3:
472                 s = "count only";
473                 break;
474         case 7:
475                 s = "count and time";
476                 break;
477         default:
478                 s = "BOGUS";
479                 break;
480         }
481         
482         printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
483 }
484
485 static void profilelevel_rqst(struct messaging_context *msg_ctx,
486                               void *private_data, 
487                               uint32_t msg_type, 
488                               struct server_id pid,
489                               DATA_BLOB *data)
490 {
491         int v = 0;
492
493         /* Send back a dummy reply */
494
495         send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
496 }
497
498 static BOOL do_profilelevel(struct messaging_context *msg_ctx,
499                             const struct server_id pid,
500                             const int argc, const char **argv)
501 {
502         if (argc != 1) {
503                 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
504                 return False;
505         }
506
507         /* Send a message and register our interest in a reply */
508
509         if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
510                 return False;
511
512         messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
513         messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
514                            profilelevel_rqst);
515
516         wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
517
518         /* No replies were received within the timeout period */
519
520         if (num_replies == 0)
521                 printf("No replies received\n");
522
523         messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
524
525         return num_replies;
526 }
527
528 /* Display debug level settings */
529
530 static BOOL do_debuglevel(struct messaging_context *msg_ctx,
531                           const struct server_id pid,
532                           const int argc, const char **argv)
533 {
534         if (argc != 1) {
535                 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
536                 return False;
537         }
538
539         /* Send a message and register our interest in a reply */
540
541         if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
542                 return False;
543
544         messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
545
546         wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
547
548         /* No replies were received within the timeout period */
549
550         if (num_replies == 0)
551                 printf("No replies received\n");
552
553         messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
554
555         return num_replies;
556 }
557
558 /* Send a print notify message */
559
560 static BOOL do_printnotify(struct messaging_context *msg_ctx,
561                            const struct server_id pid,
562                            const int argc, const char **argv)
563 {
564         const char *cmd;
565
566         /* Check for subcommand */
567
568         if (argc == 1) {
569                 fprintf(stderr, "Must specify subcommand:\n");
570                 fprintf(stderr, "\tqueuepause <printername>\n");
571                 fprintf(stderr, "\tqueueresume <printername>\n");
572                 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
573                 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
574                 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
575                 fprintf(stderr, "\tprinter <printername> <comment|port|"
576                         "driver> <value>\n");
577                 
578                 return False;
579         }
580
581         cmd = argv[1];
582
583         if (strcmp(cmd, "queuepause") == 0) {
584
585                 if (argc != 3) {
586                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
587                                 " queuepause <printername>\n");
588                         return False;
589                 }
590                 
591                 notify_printer_status_byname(argv[2], PRINTER_STATUS_PAUSED);
592
593                 goto send;
594
595         } else if (strcmp(cmd, "queueresume") == 0) {
596
597                 if (argc != 3) {
598                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
599                                 " queuereume <printername>\n");
600                         return False;
601                 }
602                 
603                 notify_printer_status_byname(argv[2], PRINTER_STATUS_OK);
604
605                 goto send;
606
607         } else if (strcmp(cmd, "jobpause") == 0) {
608                 int jobid;
609
610                 if (argc != 4) {
611                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
612                                 " jobpause <printername> <unix-jobid>\n");
613                         return False;
614                 }
615
616                 jobid = atoi(argv[3]);
617
618                 notify_job_status_byname(
619                         argv[2], jobid, JOB_STATUS_PAUSED, 
620                         SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
621
622                 goto send;
623
624         } else if (strcmp(cmd, "jobresume") == 0) {
625                 int jobid;
626
627                 if (argc != 4) {
628                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
629                                 " jobpause <printername> <unix-jobid>\n");
630                         return False;
631                 }
632
633                 jobid = atoi(argv[3]);
634
635                 notify_job_status_byname(
636                         argv[2], jobid, JOB_STATUS_QUEUED, 
637                         SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
638
639                 goto send;
640
641         } else if (strcmp(cmd, "jobdelete") == 0) {
642                 int jobid;
643
644                 if (argc != 4) {
645                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
646                                 " jobpause <printername> <unix-jobid>\n");
647                         return False;
648                 }
649
650                 jobid = atoi(argv[3]);
651
652                 notify_job_status_byname(
653                         argv[2], jobid, JOB_STATUS_DELETING,
654                         SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
655                 
656                 notify_job_status_byname(
657                         argv[2], jobid, JOB_STATUS_DELETING|
658                         JOB_STATUS_DELETED,
659                         SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
660
661                 goto send;
662
663         } else if (strcmp(cmd, "printer") == 0) {
664                 uint32 attribute;
665                 
666                 if (argc != 5) {
667                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
668                                 "printer <printername> <comment|port|driver> "
669                                 "<value>\n");
670                         return False;
671                 }
672
673                 if (strcmp(argv[3], "comment") == 0) {
674                         attribute = PRINTER_NOTIFY_COMMENT;
675                 } else if (strcmp(argv[3], "port") == 0) {
676                         attribute = PRINTER_NOTIFY_PORT_NAME;
677                 } else if (strcmp(argv[3], "driver") == 0) {
678                         attribute = PRINTER_NOTIFY_DRIVER_NAME;
679                 } else {
680                         fprintf(stderr, "Invalid printer command '%s'\n",
681                                 argv[3]);
682                         return False;
683                 }
684
685                 notify_printer_byname(argv[2], attribute,
686                                       CONST_DISCARD(char *, argv[4]));
687
688                 goto send;
689         }
690
691         fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
692         return False;
693
694 send:
695         print_notify_send_messages(msg_ctx, 0);
696         return True;
697 }
698
699 /* Close a share */
700
701 static BOOL do_closeshare(struct messaging_context *msg_ctx,
702                           const struct server_id pid,
703                           const int argc, const char **argv)
704 {
705         if (argc != 2) {
706                 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
707                         "<sharename>\n");
708                 return False;
709         }
710
711         return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
712                             strlen(argv[1]) + 1);
713 }
714
715 /* force a blocking lock retry */
716
717 static BOOL do_lockretry(struct messaging_context *msg_ctx,
718                          const struct server_id pid,
719                          const int argc, const char **argv)
720 {
721         if (argc != 1) {
722                 fprintf(stderr, "Usage: smbcontrol <dest> lockretry\n");
723                 return False;
724         }
725
726         return send_message(msg_ctx, pid, MSG_SMB_UNLOCK, NULL, 0);
727 }
728
729 /* force a validation of all brl entries, including re-sends. */
730
731 static BOOL do_brl_revalidate(struct messaging_context *msg_ctx,
732                               const struct server_id pid,
733                               const int argc, const char **argv)
734 {
735         if (argc != 1) {
736                 fprintf(stderr, "Usage: smbcontrol <dest> brl-revalidate\n");
737                 return False;
738         }
739
740         return send_message(msg_ctx, pid, MSG_SMB_BRL_VALIDATE, NULL, 0);
741 }
742
743 /* Force a SAM synchronisation */
744
745 static BOOL do_samsync(struct messaging_context *msg_ctx,
746                        const struct server_id pid,
747                        const int argc, const char **argv)
748 {
749         if (argc != 1) {
750                 fprintf(stderr, "Usage: smbcontrol <dest> samsync\n");
751                 return False;
752         }
753
754         return send_message(msg_ctx, pid, MSG_SMB_SAM_SYNC, NULL, 0);
755 }
756
757 /* Force a SAM replication */
758
759 static BOOL do_samrepl(struct messaging_context *msg_ctx,
760                        const struct server_id pid,
761                        const int argc, const char **argv)
762 {
763         if (argc != 1) {
764                 fprintf(stderr, "Usage: smbcontrol <dest> samrepl\n");
765                 return False;
766         }
767
768         return send_message(msg_ctx, pid, MSG_SMB_SAM_REPL, NULL, 0);
769 }
770
771 /* Display talloc pool usage */
772
773 static BOOL do_poolusage(struct messaging_context *msg_ctx,
774                          const struct server_id pid,
775                          const int argc, const char **argv)
776 {
777         if (argc != 1) {
778                 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
779                 return False;
780         }
781
782         messaging_register(msg_ctx, NULL, MSG_POOL_USAGE, print_string_cb);
783
784         /* Send a message and register our interest in a reply */
785
786         if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0))
787                 return False;
788
789         wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
790
791         /* No replies were received within the timeout period */
792
793         if (num_replies == 0)
794                 printf("No replies received\n");
795
796         messaging_deregister(msg_ctx, MSG_POOL_USAGE, NULL);
797
798         return num_replies;
799 }
800
801 /* Perform a dmalloc mark */
802
803 static BOOL do_dmalloc_mark(struct messaging_context *msg_ctx,
804                             const struct server_id pid,
805                             const int argc, const char **argv)
806 {
807         if (argc != 1) {
808                 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
809                 return False;
810         }
811
812         return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
813 }
814
815 /* Perform a dmalloc changed */
816
817 static BOOL do_dmalloc_changed(struct messaging_context *msg_ctx,
818                                const struct server_id pid,
819                                const int argc, const char **argv)
820 {
821         if (argc != 1) {
822                 fprintf(stderr, "Usage: smbcontrol <dest> "
823                         "dmalloc-log-changed\n");
824                 return False;
825         }
826
827         return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
828                             NULL, 0);
829 }
830
831 /* Shutdown a server process */
832
833 static BOOL do_shutdown(struct messaging_context *msg_ctx,
834                         const struct server_id pid,
835                         const int argc, const char **argv)
836 {
837         if (argc != 1) {
838                 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
839                 return False;
840         }
841
842         return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
843 }
844
845 /* Notify a driver upgrade */
846
847 static BOOL do_drvupgrade(struct messaging_context *msg_ctx,
848                           const struct server_id pid,
849                           const int argc, const char **argv)
850 {
851         if (argc != 2) {
852                 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
853                         "<driver-name>\n");
854                 return False;
855         }
856
857         return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
858                             strlen(argv[1]) + 1);
859 }
860
861 static BOOL do_winbind_online(struct messaging_context *msg_ctx,
862                               const struct server_id pid,
863                              const int argc, const char **argv)
864 {
865         TDB_CONTEXT *tdb;
866
867         if (argc != 1) {
868                 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
869                 return False;
870         }
871
872         if (!lp_winbind_offline_logon()) {
873                 fprintf(stderr, "The parameter \"winbind offline logon\" must "
874                         "be set in the [global] section of smb.conf for this "
875                         "command to be allowed.\n");
876                 return False;
877         }
878
879         /* Remove the entry in the winbindd_cache tdb to tell a later
880            starting winbindd that we're online. */
881
882         tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
883         if (!tdb) {
884                 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
885                         lock_path("winbindd_cache.tdb"));
886                 return False;
887         }
888
889         tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
890         tdb_close(tdb);
891
892         return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
893 }
894
895 static BOOL do_winbind_offline(struct messaging_context *msg_ctx,
896                                const struct server_id pid,
897                              const int argc, const char **argv)
898 {
899         TDB_CONTEXT *tdb;
900         BOOL ret = False;
901         int retry = 0;
902
903         if (argc != 1) {
904                 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
905                 return False;
906         }
907
908         if (!lp_winbind_offline_logon()) {
909                 fprintf(stderr, "The parameter \"winbind offline logon\" must "
910                         "be set in the [global] section of smb.conf for this "
911                         "command to be allowed.\n");
912                 return False;
913         }
914
915         /* Create an entry in the winbindd_cache tdb to tell a later
916            starting winbindd that we're offline. We may actually create
917            it here... */
918
919         tdb = tdb_open_log(lock_path("winbindd_cache.tdb"),
920                                 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
921                                 TDB_DEFAULT /* TDB_CLEAR_IF_FIRST */, O_RDWR|O_CREAT, 0600);
922
923         if (!tdb) {
924                 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
925                         lock_path("winbindd_cache.tdb"));
926                 return False;
927         }
928
929         /* There's a potential race condition that if a child
930            winbindd detects a domain is online at the same time
931            we're trying to tell it to go offline that it might 
932            delete the record we add between us adding it and
933            sending the message. Minimize this by retrying up to
934            5 times. */
935
936         for (retry = 0; retry < 5; retry++) {
937                 TDB_DATA d;
938                 uint8 buf[4];
939
940                 ZERO_STRUCT(d);
941
942                 SIVAL(buf, 0, time(NULL));
943                 d.dptr = buf;
944                 d.dsize = 4;
945
946                 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
947
948                 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
949                                    NULL, 0);
950
951                 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
952                 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
953         
954                 if (!d.dptr || d.dsize != 4) {
955                         SAFE_FREE(d.dptr);
956                         DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
957                 } else {
958                         SAFE_FREE(d.dptr);
959                         break;
960                 }
961         }
962
963         tdb_close(tdb);
964         return ret;
965 }
966
967 static BOOL do_winbind_onlinestatus(struct messaging_context *msg_ctx,
968                                     const struct server_id pid,
969                                     const int argc, const char **argv)
970 {
971         struct server_id myid;
972
973         myid = pid_to_procid(sys_getpid());
974
975         if (argc != 1) {
976                 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
977                 return False;
978         }
979
980         messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
981                            print_pid_string_cb);
982
983         if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, &myid,
984                           sizeof(myid)))
985                 return False;
986
987         wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
988
989         /* No replies were received within the timeout period */
990
991         if (num_replies == 0)
992                 printf("No replies received\n");
993
994         messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
995
996         return num_replies;
997 }
998
999 static BOOL do_dump_event_list(struct messaging_context *msg_ctx,
1000                                const struct server_id pid,
1001                                const int argc, const char **argv)
1002 {
1003         struct server_id myid;
1004
1005         myid = pid_to_procid(sys_getpid());
1006
1007         if (argc != 1) {
1008                 fprintf(stderr, "Usage: smbcontrol <dest> dump-event-list\n");
1009                 return False;
1010         }
1011
1012         return send_message(msg_ctx, pid, MSG_DUMP_EVENT_LIST, NULL, 0);
1013 }
1014
1015 static void winbind_validate_cache_cb(struct messaging_context *msg,
1016                                       void *private_data,
1017                                       uint32_t msg_type,
1018                                       struct server_id pid,
1019                                       DATA_BLOB *data)
1020 {
1021         char *src_string = procid_str(NULL, &pid);
1022         printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1023                (*(data->data) == 0 ? "" : "NOT "), src_string);
1024         TALLOC_FREE(src_string);
1025         num_replies++;
1026 }
1027
1028 static BOOL do_winbind_validate_cache(struct messaging_context *msg_ctx,
1029                                       const struct server_id pid,
1030                                       const int argc, const char **argv)
1031 {
1032         struct server_id myid = pid_to_procid(sys_getpid());
1033
1034         if (argc != 1) {
1035                 fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
1036                 return False;
1037         }
1038
1039         messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
1040                            winbind_validate_cache_cb);
1041
1042         if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
1043                           sizeof(myid))) {
1044                 return False;
1045         }
1046
1047         wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1048
1049         if (num_replies == 0) {
1050                 printf("No replies received\n");
1051         }
1052
1053         messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);
1054
1055         return num_replies;
1056 }
1057
1058 static BOOL do_reload_config(struct messaging_context *msg_ctx,
1059                              const struct server_id pid,
1060                              const int argc, const char **argv)
1061 {
1062         if (argc != 1) {
1063                 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1064                 return False;
1065         }
1066
1067         return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1068 }
1069
1070 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1071 {
1072         fstring unix_name;
1073         memset( (char *)n, '\0', sizeof(struct nmb_name) );
1074         fstrcpy(unix_name, name);
1075         strupper_m(unix_name);
1076         push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1077         n->name_type = (unsigned int)type & 0xFF;
1078         push_ascii(n->scope,  global_scope(), 64, STR_TERMINATE);
1079 }
1080
1081 static BOOL do_nodestatus(struct messaging_context *msg_ctx,
1082                           const struct server_id pid,
1083                           const int argc, const char **argv)
1084 {
1085         struct packet_struct p;
1086
1087         if (argc != 2) {
1088                 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1089                 return False;
1090         }
1091
1092         ZERO_STRUCT(p);
1093
1094         p.ip = *interpret_addr2(argv[1]);
1095         p.port = 137;
1096         p.packet_type = NMB_PACKET;
1097
1098         p.packet.nmb.header.name_trn_id = 10;
1099         p.packet.nmb.header.opcode = 0;
1100         p.packet.nmb.header.response = False;
1101         p.packet.nmb.header.nm_flags.bcast = False;
1102         p.packet.nmb.header.nm_flags.recursion_available = False;
1103         p.packet.nmb.header.nm_flags.recursion_desired = False;
1104         p.packet.nmb.header.nm_flags.trunc = False;
1105         p.packet.nmb.header.nm_flags.authoritative = False;
1106         p.packet.nmb.header.rcode = 0;
1107         p.packet.nmb.header.qdcount = 1;
1108         p.packet.nmb.header.ancount = 0;
1109         p.packet.nmb.header.nscount = 0;
1110         p.packet.nmb.header.arcount = 0;
1111         my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1112         p.packet.nmb.question.question_type = 0x21;
1113         p.packet.nmb.question.question_class = 0x1;
1114
1115         return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1116 }
1117
1118 /* A list of message type supported */
1119
1120 static const struct {
1121         const char *name;       /* Option name */
1122         BOOL (*fn)(struct messaging_context *msg_ctx,
1123                    const struct server_id pid,
1124                    const int argc, const char **argv);
1125         const char *help;       /* Short help text */
1126 } msg_types[] = {
1127         { "debug", do_debug, "Set debuglevel"  },
1128         { "force-election", do_election,
1129           "Force a browse election" },
1130         { "ping", do_ping, "Elicit a response" },
1131         { "profile", do_profile, "" },
1132         { "inject", do_inject_fault,
1133             "Inject a fatal signal into a running smbd"},
1134         { "stacktrace", do_daemon_stack_trace,
1135             "Display a stack trace of a daemon" },
1136         { "profilelevel", do_profilelevel, "" },
1137         { "debuglevel", do_debuglevel, "Display current debuglevels" },
1138         { "printnotify", do_printnotify, "Send a print notify message" },
1139         { "close-share", do_closeshare, "Forcibly disconnect a share" },
1140         { "lockretry", do_lockretry, "Force a blocking lock retry" },
1141         { "brl-revalidate", do_brl_revalidate, "Revalidate all brl entries" },
1142         { "samsync", do_samsync, "Initiate SAM synchronisation" },
1143         { "samrepl", do_samrepl, "Initiate SAM replication" },
1144         { "pool-usage", do_poolusage, "Display talloc memory usage" },
1145         { "dmalloc-mark", do_dmalloc_mark, "" },
1146         { "dmalloc-log-changed", do_dmalloc_changed, "" },
1147         { "shutdown", do_shutdown, "Shut down daemon" },
1148         { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
1149         { "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
1150         { "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
1151         { "online", do_winbind_online, "Ask winbind to go into online state"},
1152         { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
1153         { "onlinestatus", do_winbind_onlinestatus, "Request winbind online status"},
1154         { "dump-event-list", do_dump_event_list, "Dump event list"},
1155         { "validate-cache" , do_winbind_validate_cache,
1156           "Validate winbind's credential cache" },
1157         { "noop", do_noop, "Do nothing" },
1158         { NULL }
1159 };
1160
1161 /* Display usage information */
1162
1163 static void usage(poptContext pc)
1164 {
1165         int i;
1166
1167         poptPrintHelp(pc, stderr, 0);
1168
1169         fprintf(stderr, "\n");
1170         fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1171                 "process ID\n");
1172
1173         fprintf(stderr, "\n");
1174         fprintf(stderr, "<message-type> is one of:\n");
1175
1176         for (i = 0; msg_types[i].name; i++) 
1177             fprintf(stderr, "\t%-30s%s\n", msg_types[i].name, 
1178                     msg_types[i].help);
1179
1180         fprintf(stderr, "\n");
1181
1182         exit(1);
1183 }
1184
1185 /* Return the pid number for a string destination */
1186
1187 static struct server_id parse_dest(const char *dest)
1188 {
1189         struct server_id result = {-1};
1190         pid_t pid;
1191
1192         /* Zero is a special return value for broadcast smbd */
1193
1194         if (strequal(dest, "smbd")) {
1195                 return interpret_pid(MSG_BROADCAST_PID_STR);
1196         }
1197
1198         /* Try self - useful for testing */
1199
1200         if (strequal(dest, "self")) {
1201                 return pid_to_procid(sys_getpid());
1202         }
1203
1204         /* Fix winbind typo. */
1205         if (strequal(dest, "winbind")) {
1206                 dest = "winbindd";
1207         }
1208
1209         
1210         if (!(strequal(dest, "winbindd") || strequal(dest, "nmbd"))) {
1211                 /* Check for numeric pid number */
1212
1213                 result = interpret_pid(dest);
1214
1215                 /* Zero isn't valid if not smbd. */
1216                 if (result.pid && procid_valid(&result)) {
1217                         return result;
1218                 }
1219         }
1220
1221         /* Look up other destinations in pidfile directory */
1222
1223         if ((pid = pidfile_pid(dest)) != 0) {
1224                 return pid_to_procid(pid);
1225         }
1226
1227         fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1228
1229         return result;
1230 }       
1231
1232 /* Execute smbcontrol command */
1233
1234 static BOOL do_command(struct messaging_context *msg_ctx,
1235                        int argc, const char **argv)
1236 {
1237         const char *dest = argv[0], *command = argv[1];
1238         struct server_id pid;
1239         int i;
1240
1241         /* Check destination */
1242
1243         pid = parse_dest(dest);
1244         if (!procid_valid(&pid)) {
1245                 return False;
1246         }
1247
1248         /* Check command */
1249
1250         for (i = 0; msg_types[i].name; i++) {
1251                 if (strequal(command, msg_types[i].name))
1252                         return msg_types[i].fn(msg_ctx, pid,
1253                                                argc - 1, argv + 1);
1254         }
1255
1256         fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1257
1258         return False;
1259 }
1260
1261 static void smbcontrol_help(poptContext pc,
1262                     enum poptCallbackReason preason,
1263                     struct poptOption * poption,
1264                     const char * parg,
1265                     void * pdata)
1266 {
1267         if (poption->shortName != '?') {
1268                 poptPrintUsage(pc, stdout, 0);
1269         } else {
1270                 usage(pc);
1271         }
1272
1273         exit(0);
1274 }
1275
1276 struct poptOption help_options[] = {
1277         { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1278           NULL, NULL },
1279         { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1280         { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1281         { NULL }
1282 } ;
1283
1284 /* Main program */
1285
1286 int main(int argc, const char **argv)
1287 {
1288         poptContext pc;
1289         int opt;
1290         struct event_context *evt_ctx;
1291         struct messaging_context *msg_ctx;
1292
1293         static struct poptOption long_options[] = {
1294                 /* POPT_AUTOHELP */
1295                 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1296                                         0, "Help options:", NULL },
1297                 { "timeout", 't', POPT_ARG_INT, &timeout, 't', 
1298                   "Set timeout value in seconds", "TIMEOUT" },
1299
1300                 POPT_COMMON_SAMBA
1301                 POPT_TABLEEND
1302         };
1303         TALLOC_CTX *frame = talloc_stackframe();
1304         int ret = 0;
1305
1306         load_case_tables();
1307
1308         setup_logging(argv[0],True);
1309         
1310         /* Parse command line arguments using popt */
1311
1312         pc = poptGetContext(
1313                 "smbcontrol", argc, (const char **)argv, long_options, 0);
1314
1315         poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1316                                "<parameters>");
1317
1318         if (argc == 1)
1319                 usage(pc);
1320
1321         while ((opt = poptGetNextOpt(pc)) != -1) {
1322                 switch(opt) {
1323                 case 't':       /* --timeout */
1324                         break;
1325                 default:
1326                         fprintf(stderr, "Invalid option\n");
1327                         poptPrintHelp(pc, stderr, 0);
1328                         break;
1329                 }
1330         }
1331
1332         /* We should now have the remaining command line arguments in
1333            argv.  The argc parameter should have been decremented to the
1334            correct value in the above switch statement. */
1335
1336         argv = (const char **)poptGetArgs(pc);
1337         argc = 0;
1338         while (argv[argc] != NULL) {
1339                 argc++;
1340         }
1341
1342         if (argc == 1)
1343                 usage(pc);
1344
1345         lp_load(dyn_CONFIGFILE,False,False,False,True);
1346
1347         /* Need to invert sense of return code -- samba
1348          * routines mostly return True==1 for success, but
1349          * shell needs 0. */ 
1350         
1351         if (!(evt_ctx = event_context_init(NULL)) ||
1352             !(msg_ctx = messaging_init(NULL, server_id_self(), evt_ctx))) {
1353                 fprintf(stderr, "could not init messaging context\n");
1354                 TALLOC_FREE(frame);
1355                 exit(1);
1356         }
1357         
1358         ret = !do_command(msg_ctx, argc, argv);
1359         TALLOC_FREE(frame);
1360         return ret;
1361 }