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 NT_STATUS_IS_OK(message_send_pid(pid
, msg_type
, buf
, len
,
65 tdb
= tdb_open_log(lock_path("connections.tdb"), 0,
66 TDB_DEFAULT
, O_RDWR
, 0);
68 fprintf(stderr
,"Failed to open connections database"
69 ": %s\n", strerror(errno
));
73 ret
= message_send_all(tdb
,msg_type
, buf
, len
, duplicates
,
75 DEBUG(10,("smbcontrol/send_message: broadcast message to "
76 "%d processes\n", n_sent
));
83 /* Wait for one or more reply messages */
85 static void wait_replies(BOOL multiple_replies
)
87 time_t start_time
= time(NULL
);
89 /* Wait around a bit. This is pretty disgusting - we have to
90 busy-wait here as there is no nicer way to do it. */
94 if (num_replies
> 0 && !multiple_replies
)
97 } while (timeout
- (time(NULL
) - start_time
) > 0);
100 /* Message handler callback that displays the PID and a string on stdout */
102 static void print_pid_string_cb(int msg_type
, struct process_id pid
, void *buf
,
103 size_t len
, void *private_data
)
105 printf("PID %u: %.*s", (unsigned int)procid_to_pid(&pid
),
106 (int)len
, (const char *)buf
);
110 /* Message handler callback that displays a string on stdout */
112 static void print_string_cb(int msg_type
, struct process_id pid
,
113 void *buf
, size_t len
, void *private_data
)
115 printf("%.*s", (int)len
, (const char *)buf
);
119 /* Send no message. Useful for testing. */
121 static BOOL
do_noop(const struct process_id pid
,
122 const int argc
, const char **argv
)
125 fprintf(stderr
, "Usage: smbcontrol <dest> noop\n");
129 /* Move along, nothing to see here */
134 /* Send a debug string */
136 static BOOL
do_debug(const struct process_id pid
,
137 const int argc
, const char **argv
)
140 fprintf(stderr
, "Usage: smbcontrol <dest> debug "
146 pid
, MSG_DEBUG
, argv
[1], strlen(argv
[1]) + 1, False
);
149 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
151 /* Return the name of a process given it's PID. This will only work on Linux,
152 * but that's probably moot since this whole stack tracing implementatino is
153 * Linux-specific anyway.
155 static const char * procname(pid_t pid
, char * buf
, size_t bufsz
)
160 snprintf(path
, sizeof(path
), "/proc/%llu/cmdline",
161 (unsigned long long)pid
);
162 if ((fp
= fopen(path
, "r")) == NULL
) {
166 fgets(buf
, bufsz
, fp
);
172 static void print_stack_trace(pid_t pid
, int * count
)
175 unw_addr_space_t aspace
= NULL
;
184 if (ptrace(PTRACE_ATTACH
, pid
, NULL
, NULL
) < 0) {
186 "Failed to attach to process %llu: %s\n",
187 (unsigned long long)pid
, strerror(errno
));
191 /* Wait until the attach is complete. */
192 waitpid(pid
, NULL
, 0);
194 if (((pinfo
= _UPT_create(pid
)) == NULL
) ||
195 ((aspace
= unw_create_addr_space(&_UPT_accessors
, 0)) == NULL
)) {
196 /* Probably out of memory. */
198 "Unable to initialize stack unwind for process %llu\n",
199 (unsigned long long)pid
);
203 if ((ret
= unw_init_remote(&cursor
, aspace
, pinfo
))) {
205 "Unable to unwind stack for process %llu: %s\n",
206 (unsigned long long)pid
, unw_strerror(ret
));
214 if (procname(pid
, nbuf
, sizeof(nbuf
))) {
215 printf("Stack trace for process %llu (%s):\n",
216 (unsigned long long)pid
, nbuf
);
218 printf("Stack trace for process %llu:\n",
219 (unsigned long long)pid
);
222 while (unw_step(&cursor
) > 0) {
224 unw_get_reg(&cursor
, UNW_REG_IP
, &ip
);
225 unw_get_reg(&cursor
, UNW_REG_SP
, &sp
);
227 ret
= unw_get_proc_name(&cursor
, nbuf
, sizeof(nbuf
), &off
);
228 if (ret
!= 0 && ret
!= -UNW_ENOMEM
) {
229 snprintf(nbuf
, sizeof(nbuf
), "<unknown symbol>");
231 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
232 nbuf
, (long long)off
, (long long)ip
,
240 unw_destroy_addr_space(aspace
);
247 ptrace(PTRACE_DETACH
, pid
, NULL
, NULL
);
250 static int stack_trace_connection(TDB_CONTEXT
* tdb
, TDB_DATA key
,
251 TDB_DATA data
, void * priv
)
253 struct connections_data conn
;
255 if (data
.dsize
!= sizeof(conn
))
258 memcpy(&conn
, data
.dptr
, sizeof(conn
));
259 print_stack_trace(procid_to_pid(&conn
.pid
), (int *)priv
);
264 static BOOL
do_daemon_stack_trace(const struct process_id pid
,
265 const int argc
, const char **argv
)
268 "Daemon stack tracing is not supported on this platform\n");
275 fprintf(stderr
, "Usage: smbcontrol <dest> stacktrace\n");
279 dest
= procid_to_pid(&pid
);
282 /* It would be nice to be able to make sure that this PID is
283 * the PID of a smbd/winbind/nmbd process, not some random PID
284 * the user liked the look of. It doesn't seem like it's worth
285 * the effort at the moment, however.
287 print_stack_trace(dest
, &count
);
291 tdb
= tdb_open_log(lock_path("connections.tdb"), 0,
292 TDB_DEFAULT
, O_RDONLY
, 0);
295 "Failed to open connections database: %s\n",
300 tdb_traverse(tdb
, stack_trace_connection
, &count
);
307 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
309 static BOOL
do_daemon_stack_trace(const struct process_id pid
,
310 const int argc
, const char **argv
)
313 "Daemon stack tracing is not supported on this platform\n");
317 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
319 /* Inject a fault (fatal signal) into a running smbd */
321 static BOOL
do_inject_fault(const struct process_id pid
,
322 const int argc
, const char **argv
)
325 fprintf(stderr
, "Usage: smbcontrol <dest> inject "
326 "<bus|hup|term|internal|segv>\n");
331 fprintf(stderr
, "Fault injection is only available in "
332 "developer builds\n");
334 #else /* DEVELOPER */
338 if (strcmp(argv
[1], "bus") == 0) {
340 } else if (strcmp(argv
[1], "hup") == 0) {
342 } else if (strcmp(argv
[1], "term") == 0) {
344 } else if (strcmp(argv
[1], "segv") == 0) {
346 } else if (strcmp(argv
[1], "internal") == 0) {
347 /* Force an internal error, ie. an unclean exit. */
350 fprintf(stderr
, "Unknown signal name '%s'\n", argv
[1]);
354 return send_message(pid
, MSG_SMB_INJECT_FAULT
,
355 &sig
, sizeof(int), False
);
357 #endif /* DEVELOPER */
360 /* Force a browser election */
362 static BOOL
do_election(const struct process_id pid
,
363 const int argc
, const char **argv
)
366 fprintf(stderr
, "Usage: smbcontrol <dest> force-election\n");
371 pid
, MSG_FORCE_ELECTION
, NULL
, 0, False
);
374 /* Ping a samba daemon process */
376 static void pong_cb(int msg_type
, struct process_id pid
, void *buf
,
377 size_t len
, void *private_data
)
379 char *src_string
= procid_str(NULL
, &pid
);
380 printf("PONG from pid %s\n", src_string
);
381 TALLOC_FREE(src_string
);
385 static BOOL
do_ping(const struct process_id pid
, const int argc
, const char **argv
)
388 fprintf(stderr
, "Usage: smbcontrol <dest> ping\n");
392 /* Send a message and register our interest in a reply */
394 if (!send_message(pid
, MSG_PING
, NULL
, 0, False
))
397 message_register(MSG_PONG
, pong_cb
, NULL
);
399 wait_replies(procid_to_pid(&pid
) == 0);
401 /* No replies were received within the timeout period */
403 if (num_replies
== 0)
404 printf("No replies received\n");
406 message_deregister(MSG_PONG
);
411 /* Set profiling options */
413 static BOOL
do_profile(const struct process_id pid
,
414 const int argc
, const char **argv
)
419 fprintf(stderr
, "Usage: smbcontrol <dest> profile "
420 "<off|count|on|flush>\n");
424 if (strcmp(argv
[1], "off") == 0) {
426 } else if (strcmp(argv
[1], "count") == 0) {
428 } else if (strcmp(argv
[1], "on") == 0) {
430 } else if (strcmp(argv
[1], "flush") == 0) {
433 fprintf(stderr
, "Unknown profile command '%s'\n", argv
[1]);
437 return send_message(pid
, MSG_PROFILE
, &v
, sizeof(int), False
);
440 /* Return the profiling level */
442 static void profilelevel_cb(int msg_type
, struct process_id pid
, void *buf
,
443 size_t len
, void *private_data
)
450 if (len
!= sizeof(int)) {
451 fprintf(stderr
, "invalid message length %ld returned\n",
456 memcpy(&level
, buf
, sizeof(int));
469 s
= "count and time";
476 printf("Profiling %s on pid %u\n",s
,(unsigned int)procid_to_pid(&pid
));
479 static void profilelevel_rqst(int msg_type
, struct process_id pid
,
480 void *buf
, size_t len
, void *private_data
)
484 /* Send back a dummy reply */
486 send_message(pid
, MSG_PROFILELEVEL
, &v
, sizeof(int), False
);
489 static BOOL
do_profilelevel(const struct process_id pid
,
490 const int argc
, const char **argv
)
493 fprintf(stderr
, "Usage: smbcontrol <dest> profilelevel\n");
497 /* Send a message and register our interest in a reply */
499 if (!send_message(pid
, MSG_REQ_PROFILELEVEL
, NULL
, 0, False
))
502 message_register(MSG_PROFILELEVEL
, profilelevel_cb
, NULL
);
503 message_register(MSG_REQ_PROFILELEVEL
, profilelevel_rqst
, NULL
);
505 wait_replies(procid_to_pid(&pid
) == 0);
507 /* No replies were received within the timeout period */
509 if (num_replies
== 0)
510 printf("No replies received\n");
512 message_deregister(MSG_PROFILE
);
517 /* Display debug level settings */
519 static BOOL
do_debuglevel(const struct process_id pid
,
520 const int argc
, const char **argv
)
523 fprintf(stderr
, "Usage: smbcontrol <dest> debuglevel\n");
527 /* Send a message and register our interest in a reply */
529 if (!send_message(pid
, MSG_REQ_DEBUGLEVEL
, NULL
, 0, False
))
532 message_register(MSG_DEBUGLEVEL
, print_pid_string_cb
, NULL
);
534 wait_replies(procid_to_pid(&pid
) == 0);
536 /* No replies were received within the timeout period */
538 if (num_replies
== 0)
539 printf("No replies received\n");
541 message_deregister(MSG_DEBUGLEVEL
);
546 /* Send a print notify message */
548 static BOOL
do_printnotify(const struct process_id pid
,
549 const int argc
, const char **argv
)
553 /* Check for subcommand */
556 fprintf(stderr
, "Must specify subcommand:\n");
557 fprintf(stderr
, "\tqueuepause <printername>\n");
558 fprintf(stderr
, "\tqueueresume <printername>\n");
559 fprintf(stderr
, "\tjobpause <printername> <unix jobid>\n");
560 fprintf(stderr
, "\tjobresume <printername> <unix jobid>\n");
561 fprintf(stderr
, "\tjobdelete <printername> <unix jobid>\n");
562 fprintf(stderr
, "\tprinter <printername> <comment|port|"
563 "driver> <value>\n");
570 if (strcmp(cmd
, "queuepause") == 0) {
573 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
574 " queuepause <printername>\n");
578 notify_printer_status_byname(argv
[2], PRINTER_STATUS_PAUSED
);
582 } else if (strcmp(cmd
, "queueresume") == 0) {
585 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
586 " queuereume <printername>\n");
590 notify_printer_status_byname(argv
[2], PRINTER_STATUS_OK
);
594 } else if (strcmp(cmd
, "jobpause") == 0) {
598 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
599 " jobpause <printername> <unix-jobid>\n");
603 jobid
= atoi(argv
[3]);
605 notify_job_status_byname(
606 argv
[2], jobid
, JOB_STATUS_PAUSED
,
607 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
611 } else if (strcmp(cmd
, "jobresume") == 0) {
615 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
616 " jobpause <printername> <unix-jobid>\n");
620 jobid
= atoi(argv
[3]);
622 notify_job_status_byname(
623 argv
[2], jobid
, JOB_STATUS_QUEUED
,
624 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
628 } else if (strcmp(cmd
, "jobdelete") == 0) {
632 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify"
633 " jobpause <printername> <unix-jobid>\n");
637 jobid
= atoi(argv
[3]);
639 notify_job_status_byname(
640 argv
[2], jobid
, JOB_STATUS_DELETING
,
641 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
643 notify_job_status_byname(
644 argv
[2], jobid
, JOB_STATUS_DELETING
|
646 SPOOLSS_NOTIFY_MSG_UNIX_JOBID
);
650 } else if (strcmp(cmd
, "printer") == 0) {
654 fprintf(stderr
, "Usage: smbcontrol <dest> printnotify "
655 "printer <printername> <comment|port|driver> "
660 if (strcmp(argv
[3], "comment") == 0) {
661 attribute
= PRINTER_NOTIFY_COMMENT
;
662 } else if (strcmp(argv
[3], "port") == 0) {
663 attribute
= PRINTER_NOTIFY_PORT_NAME
;
664 } else if (strcmp(argv
[3], "driver") == 0) {
665 attribute
= PRINTER_NOTIFY_DRIVER_NAME
;
667 fprintf(stderr
, "Invalid printer command '%s'\n",
672 notify_printer_byname(argv
[2], attribute
,
673 CONST_DISCARD(char *, argv
[4]));
678 fprintf(stderr
, "Invalid subcommand '%s'\n", cmd
);
682 print_notify_send_messages(0);
688 static BOOL
do_closeshare(const struct process_id pid
,
689 const int argc
, const char **argv
)
692 fprintf(stderr
, "Usage: smbcontrol <dest> close-share "
698 pid
, MSG_SMB_FORCE_TDIS
, argv
[1], strlen(argv
[1]) + 1, False
);
701 /* Force a SAM synchronisation */
703 static BOOL
do_samsync(const struct process_id pid
,
704 const int argc
, const char **argv
)
707 fprintf(stderr
, "Usage: smbcontrol <dest> samsync\n");
712 pid
, MSG_SMB_SAM_SYNC
, NULL
, 0, False
);
715 /* Force a SAM replication */
717 static BOOL
do_samrepl(const struct process_id pid
,
718 const int argc
, const char **argv
)
721 fprintf(stderr
, "Usage: smbcontrol <dest> samrepl\n");
726 pid
, MSG_SMB_SAM_REPL
, NULL
, 0, False
);
729 /* Display talloc pool usage */
731 static BOOL
do_poolusage(const struct process_id pid
,
732 const int argc
, const char **argv
)
735 fprintf(stderr
, "Usage: smbcontrol <dest> pool-usage\n");
739 message_register(MSG_POOL_USAGE
, print_string_cb
, NULL
);
741 /* Send a message and register our interest in a reply */
743 if (!send_message(pid
, MSG_REQ_POOL_USAGE
, NULL
, 0, False
))
746 wait_replies(procid_to_pid(&pid
) == 0);
748 /* No replies were received within the timeout period */
750 if (num_replies
== 0)
751 printf("No replies received\n");
753 message_deregister(MSG_POOL_USAGE
);
758 /* Perform a dmalloc mark */
760 static BOOL
do_dmalloc_mark(const struct process_id pid
,
761 const int argc
, const char **argv
)
764 fprintf(stderr
, "Usage: smbcontrol <dest> dmalloc-mark\n");
769 pid
, MSG_REQ_DMALLOC_MARK
, NULL
, 0, False
);
772 /* Perform a dmalloc changed */
774 static BOOL
do_dmalloc_changed(const struct process_id pid
,
775 const int argc
, const char **argv
)
778 fprintf(stderr
, "Usage: smbcontrol <dest> "
779 "dmalloc-log-changed\n");
784 pid
, MSG_REQ_DMALLOC_LOG_CHANGED
, NULL
, 0, False
);
787 /* Shutdown a server process */
789 static BOOL
do_shutdown(const struct process_id pid
,
790 const int argc
, const char **argv
)
793 fprintf(stderr
, "Usage: smbcontrol <dest> shutdown\n");
797 return send_message(pid
, MSG_SHUTDOWN
, NULL
, 0, False
);
800 /* Notify a driver upgrade */
802 static BOOL
do_drvupgrade(const struct process_id pid
,
803 const int argc
, const char **argv
)
806 fprintf(stderr
, "Usage: smbcontrol <dest> drvupgrade "
812 pid
, MSG_DEBUG
, argv
[1], strlen(argv
[1]) + 1, False
);
815 static BOOL
do_winbind_online(const struct process_id pid
,
816 const int argc
, const char **argv
)
821 fprintf(stderr
, "Usage: smbcontrol winbindd online\n");
825 if (!lp_winbind_offline_logon()) {
826 fprintf(stderr
, "The parameter \"winbind offline logon\" must "
827 "be set in the [global] section of smb.conf for this "
828 "command to be allowed.\n");
832 /* Remove the entry in the winbindd_cache tdb to tell a later
833 starting winbindd that we're online. */
835 tdb
= tdb_open_log(lock_path("winbindd_cache.tdb"), 0, TDB_DEFAULT
, O_RDWR
, 0600);
837 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
838 lock_path("winbindd_cache.tdb"));
842 tdb_delete_bystring(tdb
, "WINBINDD_OFFLINE");
845 return send_message(pid
, MSG_WINBIND_ONLINE
, NULL
, 0, False
);
848 static BOOL
do_winbind_offline(const struct process_id pid
,
849 const int argc
, const char **argv
)
856 fprintf(stderr
, "Usage: smbcontrol winbindd offline\n");
860 if (!lp_winbind_offline_logon()) {
861 fprintf(stderr
, "The parameter \"winbind offline logon\" must "
862 "be set in the [global] section of smb.conf for this "
863 "command to be allowed.\n");
867 /* Create an entry in the winbindd_cache tdb to tell a later
868 starting winbindd that we're offline. We may actually create
871 tdb
= tdb_open_log(lock_path("winbindd_cache.tdb"),
872 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE
,
873 TDB_DEFAULT
/* TDB_CLEAR_IF_FIRST */, O_RDWR
|O_CREAT
, 0600);
876 fprintf(stderr
, "Cannot open the tdb %s for writing.\n",
877 lock_path("winbindd_cache.tdb"));
881 /* There's a potential race condition that if a child
882 winbindd detects a domain is online at the same time
883 we're trying to tell it to go offline that it might
884 delete the record we add between us adding it and
885 sending the message. Minimize this by retrying up to
888 for (retry
= 0; retry
< 5; retry
++) {
894 SIVAL(buf
, 0, time(NULL
));
898 tdb_store_bystring(tdb
, "WINBINDD_OFFLINE", d
, TDB_INSERT
);
900 ret
= send_message(pid
, MSG_WINBIND_OFFLINE
, NULL
, 0, False
);
902 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
903 d
= tdb_fetch_bystring( tdb
, "WINBINDD_OFFLINE" );
905 if (!d
.dptr
|| d
.dsize
!= 4) {
907 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
918 static BOOL
do_winbind_onlinestatus(const struct process_id pid
,
919 const int argc
, const char **argv
)
921 struct process_id myid
;
923 myid
= pid_to_procid(sys_getpid());
926 fprintf(stderr
, "Usage: smbcontrol winbindd onlinestatus\n");
930 message_register(MSG_WINBIND_ONLINESTATUS
, print_pid_string_cb
, NULL
);
932 if (!send_message(pid
, MSG_WINBIND_ONLINESTATUS
, &myid
, sizeof(myid
), False
))
935 wait_replies(procid_to_pid(&pid
) == 0);
937 /* No replies were received within the timeout period */
939 if (num_replies
== 0)
940 printf("No replies received\n");
942 message_deregister(MSG_WINBIND_ONLINESTATUS
);
948 static BOOL
do_reload_config(const struct process_id pid
,
949 const int argc
, const char **argv
)
952 fprintf(stderr
, "Usage: smbcontrol <dest> reload-config\n");
956 return send_message(pid
, MSG_SMB_CONF_UPDATED
, NULL
, 0, False
);
959 static void my_make_nmb_name( struct nmb_name
*n
, const char *name
, int type
)
962 memset( (char *)n
, '\0', sizeof(struct nmb_name
) );
963 fstrcpy(unix_name
, name
);
964 strupper_m(unix_name
);
965 push_ascii(n
->name
, unix_name
, sizeof(n
->name
), STR_TERMINATE
);
966 n
->name_type
= (unsigned int)type
& 0xFF;
967 push_ascii(n
->scope
, global_scope(), 64, STR_TERMINATE
);
970 static BOOL
do_nodestatus(const struct process_id pid
,
971 const int argc
, const char **argv
)
973 struct packet_struct p
;
976 fprintf(stderr
, "Usage: smbcontrol nmbd nodestatus <ip>\n");
982 p
.ip
= *interpret_addr2(argv
[1]);
984 p
.packet_type
= NMB_PACKET
;
986 p
.packet
.nmb
.header
.name_trn_id
= 10;
987 p
.packet
.nmb
.header
.opcode
= 0;
988 p
.packet
.nmb
.header
.response
= False
;
989 p
.packet
.nmb
.header
.nm_flags
.bcast
= False
;
990 p
.packet
.nmb
.header
.nm_flags
.recursion_available
= False
;
991 p
.packet
.nmb
.header
.nm_flags
.recursion_desired
= False
;
992 p
.packet
.nmb
.header
.nm_flags
.trunc
= False
;
993 p
.packet
.nmb
.header
.nm_flags
.authoritative
= False
;
994 p
.packet
.nmb
.header
.rcode
= 0;
995 p
.packet
.nmb
.header
.qdcount
= 1;
996 p
.packet
.nmb
.header
.ancount
= 0;
997 p
.packet
.nmb
.header
.nscount
= 0;
998 p
.packet
.nmb
.header
.arcount
= 0;
999 my_make_nmb_name(&p
.packet
.nmb
.question
.question_name
, "*", 0x00);
1000 p
.packet
.nmb
.question
.question_type
= 0x21;
1001 p
.packet
.nmb
.question
.question_class
= 0x1;
1003 return send_message(pid
, MSG_SEND_PACKET
, &p
, sizeof(p
), False
);
1006 /* A list of message type supported */
1008 static const struct {
1009 const char *name
; /* Option name */
1010 BOOL (*fn
)(const struct process_id pid
,
1011 const int argc
, const char **argv
);
1012 const char *help
; /* Short help text */
1014 { "debug", do_debug
, "Set debuglevel" },
1015 { "force-election", do_election
,
1016 "Force a browse election" },
1017 { "ping", do_ping
, "Elicit a response" },
1018 { "profile", do_profile
, "" },
1019 { "inject", do_inject_fault
,
1020 "Inject a fatal signal into a running smbd"},
1021 { "stacktrace", do_daemon_stack_trace
,
1022 "Display a stack trace of a daemon" },
1023 { "profilelevel", do_profilelevel
, "" },
1024 { "debuglevel", do_debuglevel
, "Display current debuglevels" },
1025 { "printnotify", do_printnotify
, "Send a print notify message" },
1026 { "close-share", do_closeshare
, "Forcibly disconnect a share" },
1027 { "samsync", do_samsync
, "Initiate SAM synchronisation" },
1028 { "samrepl", do_samrepl
, "Initiate SAM replication" },
1029 { "pool-usage", do_poolusage
, "Display talloc memory usage" },
1030 { "dmalloc-mark", do_dmalloc_mark
, "" },
1031 { "dmalloc-log-changed", do_dmalloc_changed
, "" },
1032 { "shutdown", do_shutdown
, "Shut down daemon" },
1033 { "drvupgrade", do_drvupgrade
, "Notify a printer driver has changed" },
1034 { "reload-config", do_reload_config
, "Force smbd or winbindd to reload config file"},
1035 { "nodestatus", do_nodestatus
, "Ask nmbd to do a node status request"},
1036 { "online", do_winbind_online
, "Ask winbind to go into online state"},
1037 { "offline", do_winbind_offline
, "Ask winbind to go into offline state"},
1038 { "onlinestatus", do_winbind_onlinestatus
, "Request winbind online status"},
1039 { "noop", do_noop
, "Do nothing" },
1043 /* Display usage information */
1045 static void usage(poptContext
*pc
)
1049 poptPrintHelp(*pc
, stderr
, 0);
1051 fprintf(stderr
, "\n");
1052 fprintf(stderr
, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1055 fprintf(stderr
, "\n");
1056 fprintf(stderr
, "<message-type> is one of:\n");
1058 for (i
= 0; msg_types
[i
].name
; i
++)
1059 fprintf(stderr
, "\t%-30s%s\n", msg_types
[i
].name
,
1062 fprintf(stderr
, "\n");
1067 /* Return the pid number for a string destination */
1069 static struct process_id
parse_dest(const char *dest
)
1071 struct process_id result
= {-1};
1074 /* Zero is a special return value for broadcast smbd */
1076 if (strequal(dest
, "smbd")) {
1077 return interpret_pid("0");
1080 /* Try self - useful for testing */
1082 if (strequal(dest
, "self")) {
1083 return pid_to_procid(sys_getpid());
1086 /* Fix winbind typo. */
1087 if (strequal(dest
, "winbind")) {
1092 if (!(strequal(dest
, "winbindd") || strequal(dest
, "nmbd"))) {
1093 /* Check for numeric pid number */
1095 result
= interpret_pid(dest
);
1097 /* Zero isn't valid if not smbd. */
1098 if (result
.pid
&& procid_valid(&result
)) {
1103 /* Look up other destinations in pidfile directory */
1105 if ((pid
= pidfile_pid(dest
)) != 0) {
1106 return pid_to_procid(pid
);
1109 fprintf(stderr
,"Can't find pid for destination '%s'\n", dest
);
1114 /* Execute smbcontrol command */
1116 static BOOL
do_command(int argc
, const char **argv
)
1118 const char *dest
= argv
[0], *command
= argv
[1];
1119 struct process_id pid
;
1122 /* Check destination */
1124 pid
= parse_dest(dest
);
1125 if (!procid_valid(&pid
)) {
1131 for (i
= 0; msg_types
[i
].name
; i
++) {
1132 if (strequal(command
, msg_types
[i
].name
))
1133 return msg_types
[i
].fn(pid
, argc
- 1, argv
+ 1);
1136 fprintf(stderr
, "smbcontrol: unknown command '%s'\n", command
);
1143 int main(int argc
, const char **argv
)
1148 static struct poptOption long_options
[] = {
1150 { "timeout", 't', POPT_ARG_INT
, &timeout
, 't',
1151 "Set timeout value in seconds", "TIMEOUT" },
1159 setup_logging(argv
[0],True
);
1161 /* Parse command line arguments using popt */
1163 pc
= poptGetContext(
1164 "smbcontrol", argc
, (const char **)argv
, long_options
, 0);
1166 poptSetOtherOptionHelp(pc
, "[OPTION...] <destination> <message-type> "
1172 while ((opt
= poptGetNextOpt(pc
)) != -1) {
1174 case 't': /* --timeout */
1177 fprintf(stderr
, "Invalid option\n");
1178 poptPrintHelp(pc
, stderr
, 0);
1183 /* We should now have the remaining command line arguments in
1184 argv. The argc parameter should have been decremented to the
1185 correct value in the above switch statement. */
1187 argv
= (const char **)poptGetArgs(pc
);
1189 while (argv
[argc
] != NULL
) {
1196 lp_load(dyn_CONFIGFILE
,False
,False
,False
,True
);
1198 /* Need to invert sense of return code -- samba
1199 * routines mostly return True==1 for success, but
1202 return !do_command(argc
, argv
);