2 Unix SMB/CIFS implementation.
4 Send messages to other Samba daemons
6 Copyright (C) Tim Potter 2003
7 Copyright (C) Andrew Tridgell 1994-1998
8 Copyright (C) Martin Pool 2001-2002
9 Copyright (C) Simo Sorce 2002
10 Copyright (C) James Peach 2006
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 #include <libunwind.h>
33 #if HAVE_LIBUNWIND_PTRACE_H
34 #include <libunwind-ptrace.h>
38 #include <sys/ptrace.h>
41 /* Default timeout value when waiting for replies (in seconds) */
43 #define DEFAULT_TIMEOUT 10
45 static int timeout
= DEFAULT_TIMEOUT
;
46 static int num_replies
; /* Used by message callback fns */
48 /* Send a message to a destination pid. Zero means broadcast smbd. */
50 static BOOL
send_message(struct process_id pid
, int msg_type
,
51 const void *buf
, int len
,
61 if (procid_to_pid(&pid
) != 0)
62 return message_send_pid(pid
, msg_type
, buf
, len
, duplicates
);
64 tdb
= tdb_open_log(lock_path("connections.tdb"), 0,
65 TDB_DEFAULT
, O_RDWR
, 0);
67 fprintf(stderr
,"Failed to open connections database"
68 ": %s\n", strerror(errno
));
72 ret
= message_send_all(tdb
,msg_type
, buf
, len
, duplicates
,
74 DEBUG(10,("smbcontrol/send_message: broadcast message to "
75 "%d processes\n", n_sent
));
82 /* Wait for one or more reply messages */
84 static void wait_replies(BOOL multiple_replies
)
86 time_t start_time
= time(NULL
);
88 /* Wait around a bit. This is pretty disgusting - we have to
89 busy-wait here as there is no nicer way to do it. */
93 if (num_replies
> 0 && !multiple_replies
)
96 } while (timeout
- (time(NULL
) - start_time
) > 0);
99 /* Message handler callback that displays the PID and a string on stdout */
101 static void print_pid_string_cb(int msg_type
, struct process_id pid
, void *buf
, size_t len
)
103 printf("PID %u: %.*s", (unsigned int)procid_to_pid(&pid
),
104 (int)len
, (const char *)buf
);
108 /* Message handler callback that displays a string on stdout */
110 static void print_string_cb(int msg_type
, struct process_id pid
,
111 void *buf
, size_t len
)
113 printf("%.*s", (int)len
, (const char *)buf
);
117 /* Send no message. Useful for testing. */
119 static BOOL
do_noop(const struct process_id pid
,
120 const int argc
, const char **argv
)
123 fprintf(stderr
, "Usage: smbcontrol <dest> noop\n");
127 /* Move along, nothing to see here */
132 /* Send a debug string */
134 static BOOL
do_debug(const struct process_id pid
,
135 const int argc
, const char **argv
)
138 fprintf(stderr
, "Usage: smbcontrol <dest> debug "
144 pid
, MSG_DEBUG
, argv
[1], strlen(argv
[1]) + 1, False
);
147 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
149 /* Return the name of a process given it's PID. This will only work on Linux,
150 * but that's probably moot since this whole stack tracing implementatino is
151 * Linux-specific anyway.
153 static const char * procname(pid_t pid
, char * buf
, size_t bufsz
)
158 snprintf(path
, sizeof(path
), "/proc/%llu/cmdline",
159 (unsigned long long)pid
);
160 if ((fp
= fopen(path
, "r")) == NULL
) {
164 fgets(buf
, bufsz
, fp
);
170 static void print_stack_trace(pid_t pid
, int * count
)
173 unw_addr_space_t aspace
= NULL
;
182 if (ptrace(PTRACE_ATTACH
, pid
, NULL
, NULL
) < 0) {
184 "Failed to attach to process %llu: %s\n",
185 (unsigned long long)pid
, strerror(errno
));
189 /* Wait until the attach is complete. */
190 waitpid(pid
, NULL
, 0);
192 if (((pinfo
= _UPT_create(pid
)) == NULL
) ||
193 ((aspace
= unw_create_addr_space(&_UPT_accessors
, 0)) == NULL
)) {
194 /* Probably out of memory. */
196 "Unable to initialize stack unwind for process %llu\n",
197 (unsigned long long)pid
);
201 if ((ret
= unw_init_remote(&cursor
, aspace
, pinfo
))) {
203 "Unable to unwind stack for process %llu: %s\n",
204 (unsigned long long)pid
, unw_strerror(ret
));
212 if (procname(pid
, nbuf
, sizeof(nbuf
))) {
213 printf("Stack trace for process %llu (%s):\n",
214 (unsigned long long)pid
, nbuf
);
216 printf("Stack trace for process %llu:\n",
217 (unsigned long long)pid
);
220 while (unw_step(&cursor
) > 0) {
222 unw_get_reg(&cursor
, UNW_REG_IP
, &ip
);
223 unw_get_reg(&cursor
, UNW_REG_SP
, &sp
);
225 ret
= unw_get_proc_name(&cursor
, nbuf
, sizeof(nbuf
), &off
);
226 if (ret
!= 0 && ret
!= -UNW_ENOMEM
) {
227 snprintf(nbuf
, sizeof(nbuf
), "<unknown symbol>");
229 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
230 nbuf
, (long long)off
, (long long)ip
,
238 unw_destroy_addr_space(aspace
);
245 ptrace(PTRACE_DETACH
, pid
, NULL
, NULL
);
248 static int stack_trace_connection(TDB_CONTEXT
* tdb
, TDB_DATA key
,
249 TDB_DATA data
, void * priv
)
251 struct connections_data conn
;
253 if (data
.dsize
!= sizeof(conn
))
256 memcpy(&conn
, data
.dptr
, sizeof(conn
));
257 print_stack_trace(procid_to_pid(&conn
.pid
), (int *)priv
);
262 static BOOL
do_daemon_stack_trace(const struct process_id pid
,
263 const int argc
, const char **argv
)
266 "Daemon stack tracing is not supported on this platform\n");
273 fprintf(stderr
, "Usage: smbcontrol <dest> stacktrace\n");
277 dest
= procid_to_pid(&pid
);
280 /* It would be nice to be able to make sure that this PID is
281 * the PID of a smbd/winbind/nmbd process, not some random PID
282 * the user liked the look of. It doesn't seem like it's worth
283 * the effort at the moment, however.
285 print_stack_trace(dest
, &count
);
289 tdb
= tdb_open_log(lock_path("connections.tdb"), 0,
290 TDB_DEFAULT
, O_RDONLY
, 0);
293 "Failed to open connections database: %s\n",
298 tdb_traverse(tdb
, stack_trace_connection
, &count
);
305 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
307 static BOOL
do_daemon_stack_trace(const struct process_id pid
,
308 const int argc
, const char **argv
)
311 "Daemon stack tracing is not supported on this platform\n");
315 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
317 /* Inject a fault (fatal signal) into a running smbd */
319 static BOOL
do_inject_fault(const struct process_id pid
,
320 const int argc
, const char **argv
)
323 fprintf(stderr
, "Usage: smbcontrol <dest> inject "
324 "<bus|hup|term|internal|segv>\n");
329 fprintf(stderr
, "Fault injection is only available in "
330 "developer builds\n");
332 #else /* DEVELOPER */
336 if (strcmp(argv
[1], "bus") == 0) {
338 } else if (strcmp(argv
[1], "hup") == 0) {
340 } else if (strcmp(argv
[1], "term") == 0) {
342 } else if (strcmp(argv
[1], "segv") == 0) {
344 } else if (strcmp(argv
[1], "internal") == 0) {
345 /* Force an internal error, ie. an unclean exit. */
348 fprintf(stderr
, "Unknown signal name '%s'\n", argv
[1]);
352 return send_message(pid
, MSG_SMB_INJECT_FAULT
,
353 &sig
, sizeof(int), False
);
355 #endif /* DEVELOPER */
358 /* Force a browser election */
360 static BOOL
do_election(const struct process_id pid
,
361 const int argc
, const char **argv
)
364 fprintf(stderr
, "Usage: smbcontrol <dest> force-election\n");
369 pid
, MSG_FORCE_ELECTION
, NULL
, 0, False
);
372 /* Ping a samba daemon process */
374 static void pong_cb(int msg_type
, struct process_id pid
, void *buf
, size_t len
)
376 char *src_string
= procid_str(NULL
, &pid
);
377 printf("PONG from pid %s\n", src_string
);
378 TALLOC_FREE(src_string
);
382 static BOOL
do_ping(const struct process_id pid
, const int argc
, const char **argv
)
385 fprintf(stderr
, "Usage: smbcontrol <dest> ping\n");
389 /* Send a message and register our interest in a reply */
391 if (!send_message(pid
, MSG_PING
, NULL
, 0, False
))
394 message_register(MSG_PONG
, pong_cb
);
396 wait_replies(procid_to_pid(&pid
) == 0);
398 /* No replies were received within the timeout period */
400 if (num_replies
== 0)
401 printf("No replies received\n");
403 message_deregister(MSG_PONG
);
408 /* Set profiling options */
410 static BOOL
do_profile(const struct process_id pid
,
411 const int argc
, const char **argv
)
416 fprintf(stderr
, "Usage: smbcontrol <dest> profile "
417 "<off|count|on|flush>\n");
421 if (strcmp(argv
[1], "off") == 0) {
423 } else if (strcmp(argv
[1], "count") == 0) {
425 } else if (strcmp(argv
[1], "on") == 0) {
427 } else if (strcmp(argv
[1], "flush") == 0) {
430 fprintf(stderr
, "Unknown profile command '%s'\n", argv
[1]);
434 return send_message(pid
, MSG_PROFILE
, &v
, sizeof(int), False
);
437 /* Return the profiling level */
439 static void profilelevel_cb(int msg_type
, struct process_id pid
, void *buf
, size_t len
)
446 if (len
!= sizeof(int)) {
447 fprintf(stderr
, "invalid message length %ld returned\n",
452 memcpy(&level
, buf
, sizeof(int));
465 s
= "count and time";
472 printf("Profiling %s on pid %u\n",s
,(unsigned int)procid_to_pid(&pid
));
475 static void profilelevel_rqst(int msg_type
, struct process_id pid
,
476 void *buf
, size_t len
)
480 /* Send back a dummy reply */
482 send_message(pid
, MSG_PROFILELEVEL
, &v
, sizeof(int), False
);
485 static BOOL
do_profilelevel(const struct process_id pid
,
486 const int argc
, const char **argv
)
489 fprintf(stderr
, "Usage: smbcontrol <dest> profilelevel\n");
493 /* Send a message and register our interest in a reply */
495 if (!send_message(pid
, MSG_REQ_PROFILELEVEL
, NULL
, 0, False
))
498 message_register(MSG_PROFILELEVEL
, profilelevel_cb
);
499 message_register(MSG_REQ_PROFILELEVEL
, profilelevel_rqst
);
501 wait_replies(procid_to_pid(&pid
) == 0);
503 /* No replies were received within the timeout period */
505 if (num_replies
== 0)
506 printf("No replies received\n");
508 message_deregister(MSG_PROFILE
);
513 /* Display debug level settings */
515 static BOOL
do_debuglevel(const struct process_id pid
,
516 const int argc
, const char **argv
)
519 fprintf(stderr
, "Usage: smbcontrol <dest> debuglevel\n");
523 /* Send a message and register our interest in a reply */
525 if (!send_message(pid
, MSG_REQ_DEBUGLEVEL
, NULL
, 0, False
))
528 message_register(MSG_DEBUGLEVEL
, print_pid_string_cb
);
530 wait_replies(procid_to_pid(&pid
) == 0);
532 /* No replies were received within the timeout period */
534 if (num_replies
== 0)
535 printf("No replies received\n");
537 message_deregister(MSG_DEBUGLEVEL
);
542 /* Send a print notify message */
544 static BOOL
do_printnotify(const struct process_id pid
,
545 const int argc
, const char **argv
)
549 /* Check for subcommand */
552 fprintf(stderr
, "Must specify subcommand:\n");
553 fprintf(stderr
, "\tqueuepause <printername>\n");
554 fprintf(stderr
, "\tqueueresume <printername>\n");
555 fprintf(stderr
, "\tjobpause <printername> <unix jobid>\n");
556 fprintf(stderr
, "\tjobresume <printername> <unix jobid>\n");
557 fprintf(stderr
, "\tjobdelete <printername> <unix jobid>\n");
558 fprintf(stderr
, "\tprinter <printername> <comment|port|"
559 "driver> <value>\n");
566 if (strcmp(cmd
, "queuepause") == 0) {
569 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
570 " queuepause <printername>\n");
574 notify_printer_status_byname(argv
[2], PRINTER_STATUS_PAUSED
);
578 } else if (strcmp(cmd
, "queueresume") == 0) {
581 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
582 " queuereume <printername>\n");
586 notify_printer_status_byname(argv
[2], PRINTER_STATUS_OK
);
590 } else if (strcmp(cmd
, "jobpause") == 0) {
594 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
595 " jobpause <printername> <unix-jobid>\n");
599 jobid
= atoi(argv
[3]);
601 notify_job_status_byname(
602 argv
[2], jobid
, JOB_STATUS_PAUSED
,
603 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
607 } else if (strcmp(cmd
, "jobresume") == 0) {
611 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
612 " jobpause <printername> <unix-jobid>\n");
616 jobid
= atoi(argv
[3]);
618 notify_job_status_byname(
619 argv
[2], jobid
, JOB_STATUS_QUEUED
,
620 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
624 } else if (strcmp(cmd
, "jobdelete") == 0) {
628 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
629 " jobpause <printername> <unix-jobid>\n");
633 jobid
= atoi(argv
[3]);
635 notify_job_status_byname(
636 argv
[2], jobid
, JOB_STATUS_DELETING
,
637 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
639 notify_job_status_byname(
640 argv
[2], jobid
, JOB_STATUS_DELETING
|
642 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
646 } else if (strcmp(cmd
, "printer") == 0) {
650 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify "
651 "printer <printername> <comment|port|driver> "
656 if (strcmp(argv
[3], "comment") == 0) {
657 attribute
= PRINTER_NOTIFY_COMMENT
;
658 } else if (strcmp(argv
[3], "port") == 0) {
659 attribute
= PRINTER_NOTIFY_PORT_NAME
;
660 } else if (strcmp(argv
[3], "driver") == 0) {
661 attribute
= PRINTER_NOTIFY_DRIVER_NAME
;
663 fprintf(stderr
, "Invalid printer command '%s'\n",
668 notify_printer_byname(argv
[2], attribute
,
669 CONST_DISCARD(char *, argv
[4]));
674 fprintf(stderr
, "Invalid subcommand '%s'\n", cmd
);
678 print_notify_send_messages(0);
684 static BOOL
do_closeshare(const struct process_id pid
,
685 const int argc
, const char **argv
)
688 fprintf(stderr
, "Usage: smbcontrol <dest> close-share "
694 pid
, MSG_SMB_FORCE_TDIS
, argv
[1], strlen(argv
[1]) + 1, False
);
697 /* Force a SAM synchronisation */
699 static BOOL
do_samsync(const struct process_id pid
,
700 const int argc
, const char **argv
)
703 fprintf(stderr
, "Usage: smbcontrol <dest> samsync\n");
708 pid
, MSG_SMB_SAM_SYNC
, NULL
, 0, False
);
711 /* Force a SAM replication */
713 static BOOL
do_samrepl(const struct process_id pid
,
714 const int argc
, const char **argv
)
717 fprintf(stderr
, "Usage: smbcontrol <dest> samrepl\n");
722 pid
, MSG_SMB_SAM_REPL
, NULL
, 0, False
);
725 /* Display talloc pool usage */
727 static BOOL
do_poolusage(const struct process_id pid
,
728 const int argc
, const char **argv
)
731 fprintf(stderr
, "Usage: smbcontrol <dest> pool-usage\n");
735 message_register(MSG_POOL_USAGE
, print_string_cb
);
737 /* Send a message and register our interest in a reply */
739 if (!send_message(pid
, MSG_REQ_POOL_USAGE
, NULL
, 0, False
))
742 wait_replies(procid_to_pid(&pid
) == 0);
744 /* No replies were received within the timeout period */
746 if (num_replies
== 0)
747 printf("No replies received\n");
749 message_deregister(MSG_POOL_USAGE
);
754 /* Perform a dmalloc mark */
756 static BOOL
do_dmalloc_mark(const struct process_id pid
,
757 const int argc
, const char **argv
)
760 fprintf(stderr
, "Usage: smbcontrol <dest> dmalloc-mark\n");
765 pid
, MSG_REQ_DMALLOC_MARK
, NULL
, 0, False
);
768 /* Perform a dmalloc changed */
770 static BOOL
do_dmalloc_changed(const struct process_id pid
,
771 const int argc
, const char **argv
)
774 fprintf(stderr
, "Usage: smbcontrol <dest> "
775 "dmalloc-log-changed\n");
780 pid
, MSG_REQ_DMALLOC_LOG_CHANGED
, NULL
, 0, False
);
783 /* Shutdown a server process */
785 static BOOL
do_shutdown(const struct process_id pid
,
786 const int argc
, const char **argv
)
789 fprintf(stderr
, "Usage: smbcontrol <dest> shutdown\n");
793 return send_message(pid
, MSG_SHUTDOWN
, NULL
, 0, False
);
796 /* Notify a driver upgrade */
798 static BOOL
do_drvupgrade(const struct process_id pid
,
799 const int argc
, const char **argv
)
802 fprintf(stderr
, "Usage: smbcontrol <dest> drvupgrade "
808 pid
, MSG_DEBUG
, argv
[1], strlen(argv
[1]) + 1, False
);
811 static BOOL
do_winbind_online(const struct process_id pid
,
812 const int argc
, const char **argv
)
817 fprintf(stderr
, "Usage: smbcontrol winbindd online\n");
821 if (!lp_winbind_offline_logon()) {
822 fprintf(stderr
, "The parameter \"winbind offline logon\" must "
823 "be set in the [global] section of smb.conf for this "
824 "command to be allowed.\n");
828 /* Remove the entry in the winbindd_cache tdb to tell a later
829 starting winbindd that we're online. */
831 tdb
= tdb_open_log(lock_path("winbindd_cache.tdb"), 0, TDB_DEFAULT
, O_RDWR
, 0600);
833 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
834 lock_path("winbindd_cache.tdb"));
838 tdb_delete_bystring(tdb
, "WINBINDD_OFFLINE");
841 return send_message(pid
, MSG_WINBIND_ONLINE
, NULL
, 0, False
);
844 static BOOL
do_winbind_offline(const struct process_id pid
,
845 const int argc
, const char **argv
)
852 fprintf(stderr
, "Usage: smbcontrol winbindd offline\n");
856 if (!lp_winbind_offline_logon()) {
857 fprintf(stderr
, "The parameter \"winbind offline logon\" must "
858 "be set in the [global] section of smb.conf for this "
859 "command to be allowed.\n");
863 /* Create an entry in the winbindd_cache tdb to tell a later
864 starting winbindd that we're offline. We may actually create
867 tdb
= tdb_open_log(lock_path("winbindd_cache.tdb"),
868 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE
,
869 TDB_DEFAULT
/* TDB_CLEAR_IF_FIRST */, O_RDWR
|O_CREAT
, 0600);
872 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
873 lock_path("winbindd_cache.tdb"));
877 /* There's a potential race condition that if a child
878 winbindd detects a domain is online at the same time
879 we're trying to tell it to go offline that it might
880 delete the record we add between us adding it and
881 sending the message. Minimize this by retrying up to
884 for (retry
= 0; retry
< 5; retry
++) {
888 tdb_store_bystring(tdb
, "WINBINDD_OFFLINE", d
, TDB_INSERT
);
890 ret
= send_message(pid
, MSG_WINBIND_OFFLINE
, NULL
, 0, False
);
892 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
893 tdb
->ecode
= TDB_SUCCESS
;
894 d
= tdb_fetch_bystring( tdb
, "WINBINDD_OFFLINE" );
896 /* As this is a key with no data we don't need to free, we
897 check for existence by looking at tdb_err. */
899 err
= tdb_error(tdb
);
901 if (err
== TDB_ERR_NOEXIST
) {
902 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
912 static BOOL
do_winbind_onlinestatus(const struct process_id pid
,
913 const int argc
, const char **argv
)
915 struct process_id myid
;
917 myid
= pid_to_procid(sys_getpid());
920 fprintf(stderr
, "Usage: smbcontrol winbindd onlinestatus\n");
924 message_register(MSG_WINBIND_ONLINESTATUS
, print_pid_string_cb
);
926 if (!send_message(pid
, MSG_WINBIND_ONLINESTATUS
, &myid
, sizeof(myid
), False
))
929 wait_replies(procid_to_pid(&pid
) == 0);
931 /* No replies were received within the timeout period */
933 if (num_replies
== 0)
934 printf("No replies received\n");
936 message_deregister(MSG_WINBIND_ONLINESTATUS
);
942 static BOOL
do_reload_config(const struct process_id pid
,
943 const int argc
, const char **argv
)
946 fprintf(stderr
, "Usage: smbcontrol <dest> reload-config\n");
950 return send_message(pid
, MSG_SMB_CONF_UPDATED
, NULL
, 0, False
);
953 static void my_make_nmb_name( struct nmb_name
*n
, const char *name
, int type
)
956 memset( (char *)n
, '\0', sizeof(struct nmb_name
) );
957 fstrcpy(unix_name
, name
);
958 strupper_m(unix_name
);
959 push_ascii(n
->name
, unix_name
, sizeof(n
->name
), STR_TERMINATE
);
960 n
->name_type
= (unsigned int)type
& 0xFF;
961 push_ascii(n
->scope
, global_scope(), 64, STR_TERMINATE
);
964 static BOOL
do_nodestatus(const struct process_id pid
,
965 const int argc
, const char **argv
)
967 struct packet_struct p
;
970 fprintf(stderr
, "Usage: smbcontrol nmbd nodestatus <ip>\n");
976 p
.ip
= *interpret_addr2(argv
[1]);
978 p
.packet_type
= NMB_PACKET
;
980 p
.packet
.nmb
.header
.name_trn_id
= 10;
981 p
.packet
.nmb
.header
.opcode
= 0;
982 p
.packet
.nmb
.header
.response
= False
;
983 p
.packet
.nmb
.header
.nm_flags
.bcast
= False
;
984 p
.packet
.nmb
.header
.nm_flags
.recursion_available
= False
;
985 p
.packet
.nmb
.header
.nm_flags
.recursion_desired
= False
;
986 p
.packet
.nmb
.header
.nm_flags
.trunc
= False
;
987 p
.packet
.nmb
.header
.nm_flags
.authoritative
= False
;
988 p
.packet
.nmb
.header
.rcode
= 0;
989 p
.packet
.nmb
.header
.qdcount
= 1;
990 p
.packet
.nmb
.header
.ancount
= 0;
991 p
.packet
.nmb
.header
.nscount
= 0;
992 p
.packet
.nmb
.header
.arcount
= 0;
993 my_make_nmb_name(&p
.packet
.nmb
.question
.question_name
, "*", 0x00);
994 p
.packet
.nmb
.question
.question_type
= 0x21;
995 p
.packet
.nmb
.question
.question_class
= 0x1;
997 return send_message(pid
, MSG_SEND_PACKET
, &p
, sizeof(p
), False
);
1000 /* A list of message type supported */
1002 static const struct {
1003 const char *name
; /* Option name */
1004 BOOL (*fn
)(const struct process_id pid
,
1005 const int argc
, const char **argv
);
1006 const char *help
; /* Short help text */
1008 { "debug", do_debug
, "Set debuglevel" },
1009 { "force-election", do_election
,
1010 "Force a browse election" },
1011 { "ping", do_ping
, "Elicit a response" },
1012 { "profile", do_profile
, "" },
1013 { "inject", do_inject_fault
,
1014 "Inject a fatal signal into a running smbd"},
1015 { "stacktrace", do_daemon_stack_trace
,
1016 "Display a stack trace of a daemon" },
1017 { "profilelevel", do_profilelevel
, "" },
1018 { "debuglevel", do_debuglevel
, "Display current debuglevels" },
1019 { "printnotify", do_printnotify
, "Send a print notify message" },
1020 { "close-share", do_closeshare
, "Forcibly disconnect a share" },
1021 { "samsync", do_samsync
, "Initiate SAM synchronisation" },
1022 { "samrepl", do_samrepl
, "Initiate SAM replication" },
1023 { "pool-usage", do_poolusage
, "Display talloc memory usage" },
1024 { "dmalloc-mark", do_dmalloc_mark
, "" },
1025 { "dmalloc-log-changed", do_dmalloc_changed
, "" },
1026 { "shutdown", do_shutdown
, "Shut down daemon" },
1027 { "drvupgrade", do_drvupgrade
, "Notify a printer driver has changed" },
1028 { "reload-config", do_reload_config
, "Force smbd or winbindd to reload config file"},
1029 { "nodestatus", do_nodestatus
, "Ask nmbd to do a node status request"},
1030 { "online", do_winbind_online
, "Ask winbind to go into online state"},
1031 { "offline", do_winbind_offline
, "Ask winbind to go into offline state"},
1032 { "onlinestatus", do_winbind_onlinestatus
, "Request winbind online status"},
1033 { "noop", do_noop
, "Do nothing" },
1037 /* Display usage information */
1039 static void usage(poptContext
*pc
)
1043 poptPrintHelp(*pc
, stderr
, 0);
1045 fprintf(stderr
, "\n");
1046 fprintf(stderr
, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1049 fprintf(stderr
, "\n");
1050 fprintf(stderr
, "<message-type> is one of:\n");
1052 for (i
= 0; msg_types
[i
].name
; i
++)
1053 fprintf(stderr
, "\t%-30s%s\n", msg_types
[i
].name
,
1056 fprintf(stderr
, "\n");
1061 /* Return the pid number for a string destination */
1063 static struct process_id
parse_dest(const char *dest
)
1065 struct process_id result
= {-1};
1068 /* Zero is a special return value for broadcast smbd */
1070 if (strequal(dest
, "smbd")) {
1071 return interpret_pid("0");
1074 /* Try self - useful for testing */
1076 if (strequal(dest
, "self")) {
1077 return pid_to_procid(sys_getpid());
1080 /* Fix winbind typo. */
1081 if (strequal(dest
, "winbind")) {
1086 if (!(strequal(dest
, "winbindd") || strequal(dest
, "nmbd"))) {
1087 /* Check for numeric pid number */
1089 result
= interpret_pid(dest
);
1091 /* Zero isn't valid if not smbd. */
1092 if (result
.pid
&& procid_valid(&result
)) {
1097 /* Look up other destinations in pidfile directory */
1099 if ((pid
= pidfile_pid(dest
)) != 0) {
1100 return pid_to_procid(pid
);
1103 fprintf(stderr
,"Can't find pid for destination '%s'\n", dest
);
1108 /* Execute smbcontrol command */
1110 static BOOL
do_command(int argc
, const char **argv
)
1112 const char *dest
= argv
[0], *command
= argv
[1];
1113 struct process_id pid
;
1116 /* Check destination */
1118 pid
= parse_dest(dest
);
1119 if (!procid_valid(&pid
)) {
1125 for (i
= 0; msg_types
[i
].name
; i
++) {
1126 if (strequal(command
, msg_types
[i
].name
))
1127 return msg_types
[i
].fn(pid
, argc
- 1, argv
+ 1);
1130 fprintf(stderr
, "smbcontrol: unknown command '%s'\n", command
);
1137 int main(int argc
, const char **argv
)
1142 static struct poptOption wbinfo_options
[] = {
1143 { "timeout", 't', POPT_ARG_INT
, &timeout
, 't',
1144 "Set timeout value in seconds", "TIMEOUT" },
1146 { "configfile", 's', POPT_ARG_STRING
, NULL
, 's',
1147 "Use alternative configuration file", "CONFIGFILE" },
1152 struct poptOption options
[] = {
1153 { NULL
, 0, POPT_ARG_INCLUDE_TABLE
, wbinfo_options
, 0,
1163 setup_logging(argv
[0],True
);
1165 /* Parse command line arguments using popt */
1167 pc
= poptGetContext(
1168 "smbcontrol", argc
, (const char **)argv
, options
, 0);
1170 poptSetOtherOptionHelp(pc
, "[OPTION...] <destination> <message-type> "
1176 while ((opt
= poptGetNextOpt(pc
)) != -1) {
1178 case 't': /* --timeout */
1181 case 's': /* --configfile */
1182 pstrcpy(dyn_CONFIGFILE
, poptGetOptArg(pc
));
1186 fprintf(stderr
, "Invalid option\n");
1187 poptPrintHelp(pc
, stderr
, 0);
1192 /* We should now have the remaining command line arguments in
1193 argv. The argc parameter should have been decremented to the
1194 correct value in the above switch statement. */
1196 argv
= (const char **)poptGetArgs(pc
);
1197 argc
--; /* Don't forget about argv[0] */
1202 lp_load(dyn_CONFIGFILE
,False
,False
,False
,True
);
1204 /* Need to invert sense of return code -- samba
1205 * routines mostly return True==1 for success, but
1208 return !do_command(argc
, argv
);