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