00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "includes.h"
00028
00029 #if HAVE_LIBUNWIND_H
00030 #include <libunwind.h>
00031 #endif
00032
00033 #if HAVE_LIBUNWIND_PTRACE_H
00034 #include <libunwind-ptrace.h>
00035 #endif
00036
00037 #if HAVE_SYS_PTRACE_H
00038 #include <sys/ptrace.h>
00039 #endif
00040
00041
00042
00043 #define DEFAULT_TIMEOUT 10
00044
00045 static int timeout = DEFAULT_TIMEOUT;
00046 static int num_replies;
00047
00048
00049
00050 static BOOL send_message(struct process_id pid, int msg_type,
00051 const void *buf, int len,
00052 BOOL duplicates)
00053 {
00054 TDB_CONTEXT *tdb;
00055 BOOL ret;
00056 int n_sent = 0;
00057
00058 if (!message_init())
00059 return False;
00060
00061 if (procid_to_pid(&pid) != 0)
00062 return NT_STATUS_IS_OK(message_send_pid(pid, msg_type, buf, len,
00063 duplicates));
00064
00065 tdb = tdb_open_log(lock_path("connections.tdb"), 0,
00066 TDB_DEFAULT, O_RDWR, 0);
00067 if (!tdb) {
00068 fprintf(stderr,"Failed to open connections database"
00069 ": %s\n", strerror(errno));
00070 return False;
00071 }
00072
00073 ret = message_send_all(tdb,msg_type, buf, len, duplicates,
00074 &n_sent);
00075 DEBUG(10,("smbcontrol/send_message: broadcast message to "
00076 "%d processes\n", n_sent));
00077
00078 tdb_close(tdb);
00079
00080 return ret;
00081 }
00082
00083
00084
00085 static void wait_replies(BOOL multiple_replies)
00086 {
00087 time_t start_time = time(NULL);
00088
00089
00090
00091
00092 do {
00093 message_dispatch();
00094 if (num_replies > 0 && !multiple_replies)
00095 break;
00096 sleep(1);
00097 } while (timeout - (time(NULL) - start_time) > 0);
00098 }
00099
00100
00101
00102 static void print_pid_string_cb(int msg_type, struct process_id pid, void *buf,
00103 size_t len, void *private_data)
00104 {
00105 printf("PID %u: %.*s", (unsigned int)procid_to_pid(&pid),
00106 (int)len, (const char *)buf);
00107 num_replies++;
00108 }
00109
00110
00111
00112 static void print_string_cb(int msg_type, struct process_id pid,
00113 void *buf, size_t len, void *private_data)
00114 {
00115 printf("%.*s", (int)len, (const char *)buf);
00116 num_replies++;
00117 }
00118
00119
00120
00121 static BOOL do_noop(const struct process_id pid,
00122 const int argc, const char **argv)
00123 {
00124 if (argc != 1) {
00125 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
00126 return False;
00127 }
00128
00129
00130
00131 return True;
00132 }
00133
00134
00135
00136 static BOOL do_debug(const struct process_id pid,
00137 const int argc, const char **argv)
00138 {
00139 if (argc != 2) {
00140 fprintf(stderr, "Usage: smbcontrol <dest> debug "
00141 "<debug-string>\n");
00142 return False;
00143 }
00144
00145 return send_message(
00146 pid, MSG_DEBUG, argv[1], strlen(argv[1]) + 1, False);
00147 }
00148
00149 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
00150
00151
00152
00153
00154
00155 static const char * procname(pid_t pid, char * buf, size_t bufsz)
00156 {
00157 char path[64];
00158 FILE * fp;
00159
00160 snprintf(path, sizeof(path), "/proc/%llu/cmdline",
00161 (unsigned long long)pid);
00162 if ((fp = fopen(path, "r")) == NULL) {
00163 return NULL;
00164 }
00165
00166 fgets(buf, bufsz, fp);
00167
00168 fclose(fp);
00169 return buf;
00170 }
00171
00172 static void print_stack_trace(pid_t pid, int * count)
00173 {
00174 void * pinfo = NULL;
00175 unw_addr_space_t aspace = NULL;
00176 unw_cursor_t cursor;
00177 unw_word_t ip, sp;
00178
00179 char nbuf[256];
00180 unw_word_t off;
00181
00182 int ret;
00183
00184 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
00185 fprintf(stderr,
00186 "Failed to attach to process %llu: %s\n",
00187 (unsigned long long)pid, strerror(errno));
00188 return;
00189 }
00190
00191
00192 waitpid(pid, NULL, 0);
00193
00194 if (((pinfo = _UPT_create(pid)) == NULL) ||
00195 ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
00196
00197 fprintf(stderr,
00198 "Unable to initialize stack unwind for process %llu\n",
00199 (unsigned long long)pid);
00200 goto cleanup;
00201 }
00202
00203 if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
00204 fprintf(stderr,
00205 "Unable to unwind stack for process %llu: %s\n",
00206 (unsigned long long)pid, unw_strerror(ret));
00207 goto cleanup;
00208 }
00209
00210 if (*count > 0) {
00211 printf("\n");
00212 }
00213
00214 if (procname(pid, nbuf, sizeof(nbuf))) {
00215 printf("Stack trace for process %llu (%s):\n",
00216 (unsigned long long)pid, nbuf);
00217 } else {
00218 printf("Stack trace for process %llu:\n",
00219 (unsigned long long)pid);
00220 }
00221
00222 while (unw_step(&cursor) > 0) {
00223 ip = sp = off = 0;
00224 unw_get_reg(&cursor, UNW_REG_IP, &ip);
00225 unw_get_reg(&cursor, UNW_REG_SP, &sp);
00226
00227 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
00228 if (ret != 0 && ret != -UNW_ENOMEM) {
00229 snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
00230 }
00231 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
00232 nbuf, (long long)off, (long long)ip,
00233 (long long)sp);
00234 }
00235
00236 (*count)++;
00237
00238 cleanup:
00239 if (aspace) {
00240 unw_destroy_addr_space(aspace);
00241 }
00242
00243 if (pinfo) {
00244 _UPT_destroy(pinfo);
00245 }
00246
00247 ptrace(PTRACE_DETACH, pid, NULL, NULL);
00248 }
00249
00250 static int stack_trace_connection(TDB_CONTEXT * tdb, TDB_DATA key,
00251 TDB_DATA data, void * priv)
00252 {
00253 struct connections_data conn;
00254
00255 if (data.dsize != sizeof(conn))
00256 return 0;
00257
00258 memcpy(&conn, data.dptr, sizeof(conn));
00259 print_stack_trace(procid_to_pid(&conn.pid), (int *)priv);
00260
00261 return 0;
00262 }
00263
00264 static BOOL do_daemon_stack_trace(const struct process_id pid,
00265 const int argc, const char **argv)
00266 {
00267 fprintf(stderr,
00268 "Daemon stack tracing is not supported on this platform\n");
00269 return False;
00270
00271 pid_t dest;
00272 int count = 0;
00273
00274 if (argc != 1) {
00275 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
00276 return False;
00277 }
00278
00279 dest = procid_to_pid(&pid);
00280
00281 if (dest != 0) {
00282
00283
00284
00285
00286
00287 print_stack_trace(dest, &count);
00288 } else {
00289 TDB_CONTEXT * tdb;
00290
00291 tdb = tdb_open_log(lock_path("connections.tdb"), 0,
00292 TDB_DEFAULT, O_RDONLY, 0);
00293 if (!tdb) {
00294 fprintf(stderr,
00295 "Failed to open connections database: %s\n",
00296 strerror(errno));
00297 return False;
00298 }
00299
00300 tdb_traverse(tdb, stack_trace_connection, &count);
00301 tdb_close(tdb);
00302 }
00303
00304 return True;
00305 }
00306
00307 #else
00308
00309 static BOOL do_daemon_stack_trace(const struct process_id pid,
00310 const int argc, const char **argv)
00311 {
00312 fprintf(stderr,
00313 "Daemon stack tracing is not supported on this platform\n");
00314 return False;
00315 }
00316
00317 #endif
00318
00319
00320
00321 static BOOL do_inject_fault(const struct process_id pid,
00322 const int argc, const char **argv)
00323 {
00324 if (argc != 2) {
00325 fprintf(stderr, "Usage: smbcontrol <dest> inject "
00326 "<bus|hup|term|internal|segv>\n");
00327 return False;
00328 }
00329
00330 #ifndef DEVELOPER
00331 fprintf(stderr, "Fault injection is only available in "
00332 "developer builds\n");
00333 return False;
00334 #else
00335 {
00336 int sig = 0;
00337
00338 if (strcmp(argv[1], "bus") == 0) {
00339 sig = SIGBUS;
00340 } else if (strcmp(argv[1], "hup") == 0) {
00341 sig = SIGHUP;
00342 } else if (strcmp(argv[1], "term") == 0) {
00343 sig = SIGTERM;
00344 } else if (strcmp(argv[1], "segv") == 0) {
00345 sig = SIGSEGV;
00346 } else if (strcmp(argv[1], "internal") == 0) {
00347
00348 sig = -1;
00349 } else {
00350 fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
00351 return False;
00352 }
00353
00354 return send_message(pid, MSG_SMB_INJECT_FAULT,
00355 &sig, sizeof(int), False);
00356 }
00357 #endif
00358 }
00359
00360
00361
00362 static BOOL do_election(const struct process_id pid,
00363 const int argc, const char **argv)
00364 {
00365 if (argc != 1) {
00366 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
00367 return False;
00368 }
00369
00370 return send_message(
00371 pid, MSG_FORCE_ELECTION, NULL, 0, False);
00372 }
00373
00374
00375
00376 static void pong_cb(int msg_type, struct process_id pid, void *buf,
00377 size_t len, void *private_data)
00378 {
00379 char *src_string = procid_str(NULL, &pid);
00380 printf("PONG from pid %s\n", src_string);
00381 TALLOC_FREE(src_string);
00382 num_replies++;
00383 }
00384
00385 static BOOL do_ping(const struct process_id pid, const int argc, const char **argv)
00386 {
00387 if (argc != 1) {
00388 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
00389 return False;
00390 }
00391
00392
00393
00394 if (!send_message(pid, MSG_PING, NULL, 0, False))
00395 return False;
00396
00397 message_register(MSG_PONG, pong_cb, NULL);
00398
00399 wait_replies(procid_to_pid(&pid) == 0);
00400
00401
00402
00403 if (num_replies == 0)
00404 printf("No replies received\n");
00405
00406 message_deregister(MSG_PONG);
00407
00408 return num_replies;
00409 }
00410
00411
00412
00413 static BOOL do_profile(const struct process_id pid,
00414 const int argc, const char **argv)
00415 {
00416 int v;
00417
00418 if (argc != 2) {
00419 fprintf(stderr, "Usage: smbcontrol <dest> profile "
00420 "<off|count|on|flush>\n");
00421 return False;
00422 }
00423
00424 if (strcmp(argv[1], "off") == 0) {
00425 v = 0;
00426 } else if (strcmp(argv[1], "count") == 0) {
00427 v = 1;
00428 } else if (strcmp(argv[1], "on") == 0) {
00429 v = 2;
00430 } else if (strcmp(argv[1], "flush") == 0) {
00431 v = 3;
00432 } else {
00433 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
00434 return False;
00435 }
00436
00437 return send_message(pid, MSG_PROFILE, &v, sizeof(int), False);
00438 }
00439
00440
00441
00442 static void profilelevel_cb(int msg_type, struct process_id pid, void *buf,
00443 size_t len, void *private_data)
00444 {
00445 int level;
00446 const char *s;
00447
00448 num_replies++;
00449
00450 if (len != sizeof(int)) {
00451 fprintf(stderr, "invalid message length %ld returned\n",
00452 (unsigned long)len);
00453 return;
00454 }
00455
00456 memcpy(&level, buf, sizeof(int));
00457
00458 switch (level) {
00459 case 0:
00460 s = "not enabled";
00461 break;
00462 case 1:
00463 s = "off";
00464 break;
00465 case 3:
00466 s = "count only";
00467 break;
00468 case 7:
00469 s = "count and time";
00470 break;
00471 default:
00472 s = "BOGUS";
00473 break;
00474 }
00475
00476 printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
00477 }
00478
00479 static void profilelevel_rqst(int msg_type, struct process_id pid,
00480 void *buf, size_t len, void *private_data)
00481 {
00482 int v = 0;
00483
00484
00485
00486 send_message(pid, MSG_PROFILELEVEL, &v, sizeof(int), False);
00487 }
00488
00489 static BOOL do_profilelevel(const struct process_id pid,
00490 const int argc, const char **argv)
00491 {
00492 if (argc != 1) {
00493 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
00494 return False;
00495 }
00496
00497
00498
00499 if (!send_message(pid, MSG_REQ_PROFILELEVEL, NULL, 0, False))
00500 return False;
00501
00502 message_register(MSG_PROFILELEVEL, profilelevel_cb, NULL);
00503 message_register(MSG_REQ_PROFILELEVEL, profilelevel_rqst, NULL);
00504
00505 wait_replies(procid_to_pid(&pid) == 0);
00506
00507
00508
00509 if (num_replies == 0)
00510 printf("No replies received\n");
00511
00512 message_deregister(MSG_PROFILE);
00513
00514 return num_replies;
00515 }
00516
00517
00518
00519 static BOOL do_debuglevel(const struct process_id pid,
00520 const int argc, const char **argv)
00521 {
00522 if (argc != 1) {
00523 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
00524 return False;
00525 }
00526
00527
00528
00529 if (!send_message(pid, MSG_REQ_DEBUGLEVEL, NULL, 0, False))
00530 return False;
00531
00532 message_register(MSG_DEBUGLEVEL, print_pid_string_cb, NULL);
00533
00534 wait_replies(procid_to_pid(&pid) == 0);
00535
00536
00537
00538 if (num_replies == 0)
00539 printf("No replies received\n");
00540
00541 message_deregister(MSG_DEBUGLEVEL);
00542
00543 return num_replies;
00544 }
00545
00546
00547
00548 static BOOL do_printnotify(const struct process_id pid,
00549 const int argc, const char **argv)
00550 {
00551 const char *cmd;
00552
00553
00554
00555 if (argc == 1) {
00556 fprintf(stderr, "Must specify subcommand:\n");
00557 fprintf(stderr, "\tqueuepause <printername>\n");
00558 fprintf(stderr, "\tqueueresume <printername>\n");
00559 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
00560 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
00561 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
00562 fprintf(stderr, "\tprinter <printername> <comment|port|"
00563 "driver> <value>\n");
00564
00565 return False;
00566 }
00567
00568 cmd = argv[1];
00569
00570 if (strcmp(cmd, "queuepause") == 0) {
00571
00572 if (argc != 3) {
00573 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
00574 " queuepause <printername>\n");
00575 return False;
00576 }
00577
00578 notify_printer_status_byname(argv[2], PRINTER_STATUS_PAUSED);
00579
00580 goto send;
00581
00582 } else if (strcmp(cmd, "queueresume") == 0) {
00583
00584 if (argc != 3) {
00585 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
00586 " queuereume <printername>\n");
00587 return False;
00588 }
00589
00590 notify_printer_status_byname(argv[2], PRINTER_STATUS_OK);
00591
00592 goto send;
00593
00594 } else if (strcmp(cmd, "jobpause") == 0) {
00595 int jobid;
00596
00597 if (argc != 4) {
00598 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
00599 " jobpause <printername> <unix-jobid>\n");
00600 return False;
00601 }
00602
00603 jobid = atoi(argv[3]);
00604
00605 notify_job_status_byname(
00606 argv[2], jobid, JOB_STATUS_PAUSED,
00607 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
00608
00609 goto send;
00610
00611 } else if (strcmp(cmd, "jobresume") == 0) {
00612 int jobid;
00613
00614 if (argc != 4) {
00615 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
00616 " jobpause <printername> <unix-jobid>\n");
00617 return False;
00618 }
00619
00620 jobid = atoi(argv[3]);
00621
00622 notify_job_status_byname(
00623 argv[2], jobid, JOB_STATUS_QUEUED,
00624 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
00625
00626 goto send;
00627
00628 } else if (strcmp(cmd, "jobdelete") == 0) {
00629 int jobid;
00630
00631 if (argc != 4) {
00632 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
00633 " jobpause <printername> <unix-jobid>\n");
00634 return False;
00635 }
00636
00637 jobid = atoi(argv[3]);
00638
00639 notify_job_status_byname(
00640 argv[2], jobid, JOB_STATUS_DELETING,
00641 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
00642
00643 notify_job_status_byname(
00644 argv[2], jobid, JOB_STATUS_DELETING|
00645 JOB_STATUS_DELETED,
00646 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
00647
00648 goto send;
00649
00650 } else if (strcmp(cmd, "printer") == 0) {
00651 uint32 attribute;
00652
00653 if (argc != 5) {
00654 fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
00655 "printer <printername> <comment|port|driver> "
00656 "<value>\n");
00657 return False;
00658 }
00659
00660 if (strcmp(argv[3], "comment") == 0) {
00661 attribute = PRINTER_NOTIFY_COMMENT;
00662 } else if (strcmp(argv[3], "port") == 0) {
00663 attribute = PRINTER_NOTIFY_PORT_NAME;
00664 } else if (strcmp(argv[3], "driver") == 0) {
00665 attribute = PRINTER_NOTIFY_DRIVER_NAME;
00666 } else {
00667 fprintf(stderr, "Invalid printer command '%s'\n",
00668 argv[3]);
00669 return False;
00670 }
00671
00672 notify_printer_byname(argv[2], attribute,
00673 CONST_DISCARD(char *, argv[4]));
00674
00675 goto send;
00676 }
00677
00678 fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
00679 return False;
00680
00681 send:
00682 print_notify_send_messages(0);
00683 return True;
00684 }
00685
00686
00687
00688 static BOOL do_closeshare(const struct process_id pid,
00689 const int argc, const char **argv)
00690 {
00691 if (argc != 2) {
00692 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
00693 "<sharename>\n");
00694 return False;
00695 }
00696
00697 return send_message(
00698 pid, MSG_SMB_FORCE_TDIS, argv[1], strlen(argv[1]) + 1, False);
00699 }
00700
00701
00702
00703 static BOOL do_samsync(const struct process_id pid,
00704 const int argc, const char **argv)
00705 {
00706 if (argc != 1) {
00707 fprintf(stderr, "Usage: smbcontrol <dest> samsync\n");
00708 return False;
00709 }
00710
00711 return send_message(
00712 pid, MSG_SMB_SAM_SYNC, NULL, 0, False);
00713 }
00714
00715
00716
00717 static BOOL do_samrepl(const struct process_id pid,
00718 const int argc, const char **argv)
00719 {
00720 if (argc != 1) {
00721 fprintf(stderr, "Usage: smbcontrol <dest> samrepl\n");
00722 return False;
00723 }
00724
00725 return send_message(
00726 pid, MSG_SMB_SAM_REPL, NULL, 0, False);
00727 }
00728
00729
00730
00731 static BOOL do_poolusage(const struct process_id pid,
00732 const int argc, const char **argv)
00733 {
00734 if (argc != 1) {
00735 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
00736 return False;
00737 }
00738
00739 message_register(MSG_POOL_USAGE, print_string_cb, NULL);
00740
00741
00742
00743 if (!send_message(pid, MSG_REQ_POOL_USAGE, NULL, 0, False))
00744 return False;
00745
00746 wait_replies(procid_to_pid(&pid) == 0);
00747
00748
00749
00750 if (num_replies == 0)
00751 printf("No replies received\n");
00752
00753 message_deregister(MSG_POOL_USAGE);
00754
00755 return num_replies;
00756 }
00757
00758
00759
00760 static BOOL do_dmalloc_mark(const struct process_id pid,
00761 const int argc, const char **argv)
00762 {
00763 if (argc != 1) {
00764 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
00765 return False;
00766 }
00767
00768 return send_message(
00769 pid, MSG_REQ_DMALLOC_MARK, NULL, 0, False);
00770 }
00771
00772
00773
00774 static BOOL do_dmalloc_changed(const struct process_id pid,
00775 const int argc, const char **argv)
00776 {
00777 if (argc != 1) {
00778 fprintf(stderr, "Usage: smbcontrol <dest> "
00779 "dmalloc-log-changed\n");
00780 return False;
00781 }
00782
00783 return send_message(
00784 pid, MSG_REQ_DMALLOC_LOG_CHANGED, NULL, 0, False);
00785 }
00786
00787
00788
00789 static BOOL do_shutdown(const struct process_id pid,
00790 const int argc, const char **argv)
00791 {
00792 if (argc != 1) {
00793 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
00794 return False;
00795 }
00796
00797 return send_message(pid, MSG_SHUTDOWN, NULL, 0, False);
00798 }
00799
00800
00801
00802 static BOOL do_drvupgrade(const struct process_id pid,
00803 const int argc, const char **argv)
00804 {
00805 if (argc != 2) {
00806 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
00807 "<driver-name>\n");
00808 return False;
00809 }
00810
00811 return send_message(
00812 pid, MSG_DEBUG, argv[1], strlen(argv[1]) + 1, False);
00813 }
00814
00815 static BOOL do_winbind_online(const struct process_id pid,
00816 const int argc, const char **argv)
00817 {
00818 TDB_CONTEXT *tdb;
00819
00820 if (argc != 1) {
00821 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
00822 return False;
00823 }
00824
00825 if (!lp_winbind_offline_logon()) {
00826 fprintf(stderr, "The parameter \"winbind offline logon\" must "
00827 "be set in the [global] section of smb.conf for this "
00828 "command to be allowed.\n");
00829 return False;
00830 }
00831
00832
00833
00834
00835 tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
00836 if (!tdb) {
00837 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
00838 lock_path("winbindd_cache.tdb"));
00839 return False;
00840 }
00841
00842 tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
00843 tdb_close(tdb);
00844
00845 return send_message(pid, MSG_WINBIND_ONLINE, NULL, 0, False);
00846 }
00847
00848 static BOOL do_winbind_offline(const struct process_id pid,
00849 const int argc, const char **argv)
00850 {
00851 TDB_CONTEXT *tdb;
00852 BOOL ret = False;
00853 int retry = 0;
00854
00855 if (argc != 1) {
00856 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
00857 return False;
00858 }
00859
00860 if (!lp_winbind_offline_logon()) {
00861 fprintf(stderr, "The parameter \"winbind offline logon\" must "
00862 "be set in the [global] section of smb.conf for this "
00863 "command to be allowed.\n");
00864 return False;
00865 }
00866
00867
00868
00869
00870
00871 tdb = tdb_open_log(lock_path("winbindd_cache.tdb"),
00872 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
00873 TDB_DEFAULT , O_RDWR|O_CREAT, 0600);
00874
00875 if (!tdb) {
00876 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
00877 lock_path("winbindd_cache.tdb"));
00878 return False;
00879 }
00880
00881
00882
00883
00884
00885
00886
00887
00888 for (retry = 0; retry < 5; retry++) {
00889 TDB_DATA d;
00890 char buf[4];
00891
00892 ZERO_STRUCT(d);
00893
00894 SIVAL(buf, 0, time(NULL));
00895 d.dptr = buf;
00896 d.dsize = 4;
00897
00898 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
00899
00900 ret = send_message(pid, MSG_WINBIND_OFFLINE, NULL, 0, False);
00901
00902
00903 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
00904
00905 if (!d.dptr || d.dsize != 4) {
00906 SAFE_FREE(d.dptr);
00907 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
00908 } else {
00909 SAFE_FREE(d.dptr);
00910 break;
00911 }
00912 }
00913
00914 tdb_close(tdb);
00915 return ret;
00916 }
00917
00918 static BOOL do_winbind_onlinestatus(const struct process_id pid,
00919 const int argc, const char **argv)
00920 {
00921 struct process_id myid;
00922
00923 myid = pid_to_procid(sys_getpid());
00924
00925 if (argc != 1) {
00926 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
00927 return False;
00928 }
00929
00930 message_register(MSG_WINBIND_ONLINESTATUS, print_pid_string_cb, NULL);
00931
00932 if (!send_message(pid, MSG_WINBIND_ONLINESTATUS, &myid, sizeof(myid), False))
00933 return False;
00934
00935 wait_replies(procid_to_pid(&pid) == 0);
00936
00937
00938
00939 if (num_replies == 0)
00940 printf("No replies received\n");
00941
00942 message_deregister(MSG_WINBIND_ONLINESTATUS);
00943
00944 return num_replies;
00945 }
00946
00947
00948 static BOOL do_reload_config(const struct process_id pid,
00949 const int argc, const char **argv)
00950 {
00951 if (argc != 1) {
00952 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
00953 return False;
00954 }
00955
00956 return send_message(pid, MSG_SMB_CONF_UPDATED, NULL, 0, False);
00957 }
00958
00959 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
00960 {
00961 fstring unix_name;
00962 memset( (char *)n, '\0', sizeof(struct nmb_name) );
00963 fstrcpy(unix_name, name);
00964 strupper_m(unix_name);
00965 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
00966 n->name_type = (unsigned int)type & 0xFF;
00967 push_ascii(n->scope, global_scope(), 64, STR_TERMINATE);
00968 }
00969
00970 static BOOL do_nodestatus(const struct process_id pid,
00971 const int argc, const char **argv)
00972 {
00973 struct packet_struct p;
00974
00975 if (argc != 2) {
00976 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
00977 return False;
00978 }
00979
00980 ZERO_STRUCT(p);
00981
00982 p.ip = *interpret_addr2(argv[1]);
00983 p.port = 137;
00984 p.packet_type = NMB_PACKET;
00985
00986 p.packet.nmb.header.name_trn_id = 10;
00987 p.packet.nmb.header.opcode = 0;
00988 p.packet.nmb.header.response = False;
00989 p.packet.nmb.header.nm_flags.bcast = False;
00990 p.packet.nmb.header.nm_flags.recursion_available = False;
00991 p.packet.nmb.header.nm_flags.recursion_desired = False;
00992 p.packet.nmb.header.nm_flags.trunc = False;
00993 p.packet.nmb.header.nm_flags.authoritative = False;
00994 p.packet.nmb.header.rcode = 0;
00995 p.packet.nmb.header.qdcount = 1;
00996 p.packet.nmb.header.ancount = 0;
00997 p.packet.nmb.header.nscount = 0;
00998 p.packet.nmb.header.arcount = 0;
00999 my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
01000 p.packet.nmb.question.question_type = 0x21;
01001 p.packet.nmb.question.question_class = 0x1;
01002
01003 return send_message(pid, MSG_SEND_PACKET, &p, sizeof(p), False);
01004 }
01005
01006
01007
01008 static const struct {
01009 const char *name;
01010 BOOL (*fn)(const struct process_id pid,
01011 const int argc, const char **argv);
01012 const char *help;
01013 } msg_types[] = {
01014 { "debug", do_debug, "Set debuglevel" },
01015 { "force-election", do_election,
01016 "Force a browse election" },
01017 { "ping", do_ping, "Elicit a response" },
01018 { "profile", do_profile, "" },
01019 { "inject", do_inject_fault,
01020 "Inject a fatal signal into a running smbd"},
01021 { "stacktrace", do_daemon_stack_trace,
01022 "Display a stack trace of a daemon" },
01023 { "profilelevel", do_profilelevel, "" },
01024 { "debuglevel", do_debuglevel, "Display current debuglevels" },
01025 { "printnotify", do_printnotify, "Send a print notify message" },
01026 { "close-share", do_closeshare, "Forcibly disconnect a share" },
01027 { "samsync", do_samsync, "Initiate SAM synchronisation" },
01028 { "samrepl", do_samrepl, "Initiate SAM replication" },
01029 { "pool-usage", do_poolusage, "Display talloc memory usage" },
01030 { "dmalloc-mark", do_dmalloc_mark, "" },
01031 { "dmalloc-log-changed", do_dmalloc_changed, "" },
01032 { "shutdown", do_shutdown, "Shut down daemon" },
01033 { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
01034 { "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
01035 { "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
01036 { "online", do_winbind_online, "Ask winbind to go into online state"},
01037 { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
01038 { "onlinestatus", do_winbind_onlinestatus, "Request winbind online status"},
01039 { "noop", do_noop, "Do nothing" },
01040 { NULL }
01041 };
01042
01043
01044
01045 static void usage(poptContext *pc)
01046 {
01047 int i;
01048
01049 poptPrintHelp(*pc, stderr, 0);
01050
01051 fprintf(stderr, "\n");
01052 fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
01053 "process ID\n");
01054
01055 fprintf(stderr, "\n");
01056 fprintf(stderr, "<message-type> is one of:\n");
01057
01058 for (i = 0; msg_types[i].name; i++)
01059 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name,
01060 msg_types[i].help);
01061
01062 fprintf(stderr, "\n");
01063
01064 exit(1);
01065 }
01066
01067
01068
01069 static struct process_id parse_dest(const char *dest)
01070 {
01071 struct process_id result = {-1};
01072 pid_t pid;
01073
01074
01075
01076 if (strequal(dest, "smbd")) {
01077 return interpret_pid("0");
01078 }
01079
01080
01081
01082 if (strequal(dest, "self")) {
01083 return pid_to_procid(sys_getpid());
01084 }
01085
01086
01087 if (strequal(dest, "winbind")) {
01088 dest = "winbindd";
01089 }
01090
01091
01092 if (!(strequal(dest, "winbindd") || strequal(dest, "nmbd"))) {
01093
01094
01095 result = interpret_pid(dest);
01096
01097
01098 if (result.pid && procid_valid(&result)) {
01099 return result;
01100 }
01101 }
01102
01103
01104
01105 if ((pid = pidfile_pid(dest)) != 0) {
01106 return pid_to_procid(pid);
01107 }
01108
01109 fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
01110
01111 return result;
01112 }
01113
01114
01115
01116 static BOOL do_command(int argc, const char **argv)
01117 {
01118 const char *dest = argv[0], *command = argv[1];
01119 struct process_id pid;
01120 int i;
01121
01122
01123
01124 pid = parse_dest(dest);
01125 if (!procid_valid(&pid)) {
01126 return False;
01127 }
01128
01129
01130
01131 for (i = 0; msg_types[i].name; i++) {
01132 if (strequal(command, msg_types[i].name))
01133 return msg_types[i].fn(pid, argc - 1, argv + 1);
01134 }
01135
01136 fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
01137
01138 return False;
01139 }
01140
01141
01142
01143 int main(int argc, const char **argv)
01144 {
01145 poptContext pc;
01146 int opt;
01147
01148 static struct poptOption long_options[] = {
01149 POPT_AUTOHELP
01150 { "timeout", 't', POPT_ARG_INT, &timeout, 't',
01151 "Set timeout value in seconds", "TIMEOUT" },
01152
01153 POPT_COMMON_SAMBA
01154 POPT_TABLEEND
01155 };
01156
01157 load_case_tables();
01158
01159 setup_logging(argv[0],True);
01160
01161
01162
01163 pc = poptGetContext(
01164 "smbcontrol", argc, (const char **)argv, long_options, 0);
01165
01166 poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
01167 "<parameters>");
01168
01169 if (argc == 1)
01170 usage(&pc);
01171
01172 while ((opt = poptGetNextOpt(pc)) != -1) {
01173 switch(opt) {
01174 case 't':
01175 break;
01176 default:
01177 fprintf(stderr, "Invalid option\n");
01178 poptPrintHelp(pc, stderr, 0);
01179 break;
01180 }
01181 }
01182
01183
01184
01185
01186
01187 argv = (const char **)poptGetArgs(pc);
01188 argc = 0;
01189 while (argv[argc] != NULL) {
01190 argc++;
01191 }
01192
01193 if (argc == 1)
01194 usage(&pc);
01195
01196 lp_load(dyn_CONFIGFILE,False,False,False,True);
01197
01198
01199
01200
01201
01202 return !do_command(argc, argv);
01203 }