PageRenderTime 40ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/release/src/router/samba3/source/web/statuspage.c

https://gitlab.com/envieidoc/advancedtomato2
C | 470 lines | 345 code | 84 blank | 41 comment | 99 complexity | e5169b8eb2096a3e50b9248a6d34cdc0 MD5 | raw file
  1. /*
  2. Unix SMB/CIFS implementation.
  3. web status page
  4. Copyright (C) Andrew Tridgell 1997-1998
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. */
  17. #include "includes.h"
  18. #include "web/swat_proto.h"
  19. #define PIDMAP struct PidMap
  20. /* how long to wait for start/stops to take effect */
  21. #define SLEEP_TIME 3
  22. PIDMAP {
  23. PIDMAP *next, *prev;
  24. struct process_id pid;
  25. char *machine;
  26. };
  27. static PIDMAP *pidmap;
  28. static int PID_or_Machine; /* 0 = show PID, else show Machine name */
  29. static struct process_id smbd_pid;
  30. /* from 2nd call on, remove old list */
  31. static void initPid2Machine (void)
  32. {
  33. /* show machine name rather PID on table "Open Files"? */
  34. if (PID_or_Machine) {
  35. PIDMAP *p, *next;
  36. for (p = pidmap; p != NULL; p = next) {
  37. next = p->next;
  38. DLIST_REMOVE(pidmap, p);
  39. SAFE_FREE(p->machine);
  40. SAFE_FREE(p);
  41. }
  42. pidmap = NULL;
  43. }
  44. }
  45. /* add new PID <-> Machine name mapping */
  46. static void addPid2Machine (struct process_id pid, char *machine)
  47. {
  48. /* show machine name rather PID on table "Open Files"? */
  49. if (PID_or_Machine) {
  50. PIDMAP *newmap;
  51. if ((newmap = SMB_MALLOC_P(PIDMAP)) == NULL) {
  52. /* XXX need error message for this?
  53. if malloc fails, PID is always shown */
  54. return;
  55. }
  56. newmap->pid = pid;
  57. newmap->machine = SMB_STRDUP(machine);
  58. DLIST_ADD(pidmap, newmap);
  59. }
  60. }
  61. /* lookup PID <-> Machine name mapping */
  62. static char *mapPid2Machine (struct process_id pid)
  63. {
  64. static char pidbuf [64];
  65. PIDMAP *map;
  66. /* show machine name rather PID on table "Open Files"? */
  67. if (PID_or_Machine) {
  68. for (map = pidmap; map != NULL; map = map->next) {
  69. if (procid_equal(&pid, &map->pid)) {
  70. if (map->machine == NULL) /* no machine name */
  71. break; /* show PID */
  72. return map->machine;
  73. }
  74. }
  75. }
  76. /* PID not in list or machine name NULL? return pid as string */
  77. snprintf (pidbuf, sizeof (pidbuf) - 1, "%s",
  78. procid_str_static(&pid));
  79. return pidbuf;
  80. }
  81. static char *tstring(time_t t)
  82. {
  83. static pstring buf;
  84. pstrcpy(buf, time_to_asc(t));
  85. all_string_sub(buf," ","&nbsp;",sizeof(buf));
  86. return buf;
  87. }
  88. static void print_share_mode(const struct share_mode_entry *e,
  89. const char *sharepath,
  90. const char *fname,
  91. void *dummy)
  92. {
  93. char *utf8_fname;
  94. int deny_mode;
  95. if (!is_valid_share_mode_entry(e)) {
  96. return;
  97. }
  98. deny_mode = map_share_mode_to_deny_mode(e->share_access,
  99. e->private_options);
  100. printf("<tr><td>%s</td>",_(mapPid2Machine(e->pid)));
  101. printf("<td>%u</td>",(unsigned int)e->uid);
  102. printf("<td>");
  103. switch ((deny_mode>>4)&0xF) {
  104. case DENY_NONE: printf("DENY_NONE"); break;
  105. case DENY_ALL: printf("DENY_ALL "); break;
  106. case DENY_DOS: printf("DENY_DOS "); break;
  107. case DENY_FCB: printf("DENY_FCB "); break;
  108. case DENY_READ: printf("DENY_READ "); break;
  109. case DENY_WRITE:printf("DENY_WRITE "); break;
  110. }
  111. printf("</td>");
  112. printf("<td>");
  113. if (e->access_mask & (FILE_READ_DATA|FILE_WRITE_DATA)) {
  114. printf("%s", _("RDWR "));
  115. } else if (e->access_mask & FILE_WRITE_DATA) {
  116. printf("%s", _("WRONLY "));
  117. } else {
  118. printf("%s", _("RDONLY "));
  119. }
  120. printf("</td>");
  121. printf("<td>");
  122. if((e->op_type &
  123. (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) ==
  124. (EXCLUSIVE_OPLOCK|BATCH_OPLOCK))
  125. printf("EXCLUSIVE+BATCH ");
  126. else if (e->op_type & EXCLUSIVE_OPLOCK)
  127. printf("EXCLUSIVE ");
  128. else if (e->op_type & BATCH_OPLOCK)
  129. printf("BATCH ");
  130. else if (e->op_type & LEVEL_II_OPLOCK)
  131. printf("LEVEL_II ");
  132. else
  133. printf("NONE ");
  134. printf("</td>");
  135. push_utf8_allocate(&utf8_fname, fname);
  136. printf("<td>%s</td><td>%s</td></tr>\n",
  137. utf8_fname,tstring(e->time.tv_sec));
  138. SAFE_FREE(utf8_fname);
  139. }
  140. /* kill off any connections chosen by the user */
  141. static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void* state)
  142. {
  143. struct connections_data crec;
  144. if (dbuf.dsize != sizeof(crec))
  145. return 0;
  146. memcpy(&crec, dbuf.dptr, sizeof(crec));
  147. if (crec.cnum == -1 && process_exists(crec.pid)) {
  148. char buf[30];
  149. slprintf(buf,sizeof(buf)-1,"kill_%s", procid_str_static(&crec.pid));
  150. if (cgi_variable(buf)) {
  151. kill_pid(crec.pid);
  152. sleep(SLEEP_TIME);
  153. }
  154. }
  155. return 0;
  156. }
  157. /* traversal fn for showing machine connections */
  158. static int traverse_fn2(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void* state)
  159. {
  160. struct connections_data crec;
  161. if (dbuf.dsize != sizeof(crec))
  162. return 0;
  163. memcpy(&crec, dbuf.dptr, sizeof(crec));
  164. if (crec.cnum == -1 || !process_exists(crec.pid) ||
  165. procid_equal(&crec.pid, &smbd_pid))
  166. return 0;
  167. addPid2Machine (crec.pid, crec.machine);
  168. printf("<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td>\n",
  169. procid_str_static(&crec.pid),
  170. crec.machine,crec.addr,
  171. tstring(crec.start));
  172. if (geteuid() == 0) {
  173. printf("<td><input type=submit value=\"X\" name=\"kill_%s\"></td>\n",
  174. procid_str_static(&crec.pid));
  175. }
  176. printf("</tr>\n");
  177. return 0;
  178. }
  179. /* traversal fn for showing share connections */
  180. static int traverse_fn3(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void* state)
  181. {
  182. struct connections_data crec;
  183. if (dbuf.dsize != sizeof(crec))
  184. return 0;
  185. memcpy(&crec, dbuf.dptr, sizeof(crec));
  186. if (crec.cnum == -1 || !process_exists(crec.pid))
  187. return 0;
  188. printf("<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>\n",
  189. crec.servicename,uidtoname(crec.uid),
  190. gidtoname(crec.gid),procid_str_static(&crec.pid),
  191. crec.machine,
  192. tstring(crec.start));
  193. return 0;
  194. }
  195. /* show the current server status */
  196. void status_page(void)
  197. {
  198. const char *v;
  199. int autorefresh=0;
  200. int refresh_interval=30;
  201. TDB_CONTEXT *tdb;
  202. int nr_running=0;
  203. BOOL waitup = False;
  204. const char form_name[] = "status";
  205. smbd_pid = pid_to_procid(pidfile_pid("smbd"));
  206. if (!verify_xsrf_token(form_name)) {
  207. goto output_page;
  208. }
  209. if (cgi_variable("smbd_restart") || cgi_variable("all_restart")) {
  210. stop_smbd();
  211. start_smbd();
  212. waitup=True;
  213. }
  214. if (cgi_variable("smbd_start") || cgi_variable("all_start")) {
  215. start_smbd();
  216. waitup=True;
  217. }
  218. if (cgi_variable("smbd_stop") || cgi_variable("all_stop")) {
  219. stop_smbd();
  220. waitup=True;
  221. }
  222. if (cgi_variable("nmbd_restart") || cgi_variable("all_restart")) {
  223. stop_nmbd();
  224. start_nmbd();
  225. waitup=True;
  226. }
  227. if (cgi_variable("nmbd_start") || cgi_variable("all_start")) {
  228. start_nmbd();
  229. waitup=True;
  230. }
  231. if (cgi_variable("nmbd_stop")|| cgi_variable("all_stop")) {
  232. stop_nmbd();
  233. waitup=True;
  234. }
  235. #ifdef WITH_WINBIND
  236. if (cgi_variable("winbindd_restart") || cgi_variable("all_restart")) {
  237. stop_winbindd();
  238. start_winbindd();
  239. waitup=True;
  240. }
  241. if (cgi_variable("winbindd_start") || cgi_variable("all_start")) {
  242. start_winbindd();
  243. waitup=True;
  244. }
  245. if (cgi_variable("winbindd_stop") || cgi_variable("all_stop")) {
  246. stop_winbindd();
  247. waitup=True;
  248. }
  249. #endif
  250. /* wait for daemons to start/stop */
  251. if (waitup)
  252. sleep(SLEEP_TIME);
  253. if (cgi_variable("autorefresh")) {
  254. autorefresh = 1;
  255. } else if (cgi_variable("norefresh")) {
  256. autorefresh = 0;
  257. } else if (cgi_variable("refresh")) {
  258. autorefresh = 1;
  259. }
  260. if ((v=cgi_variable("refresh_interval"))) {
  261. refresh_interval = atoi(v);
  262. }
  263. if (cgi_variable("show_client_in_col_1")) {
  264. PID_or_Machine = 1;
  265. }
  266. if (cgi_variable("show_pid_in_col_1")) {
  267. PID_or_Machine = 0;
  268. }
  269. tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_DEFAULT, O_RDONLY, 0);
  270. if (tdb) tdb_traverse(tdb, traverse_fn1, NULL);
  271. initPid2Machine ();
  272. output_page:
  273. printf("<H2>%s</H2>\n", _("Server Status"));
  274. printf("<FORM method=post>\n");
  275. print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
  276. if (!autorefresh) {
  277. printf("<input type=submit value=\"%s\" name=\"autorefresh\">\n", _("Auto Refresh"));
  278. printf("<br>%s", _("Refresh Interval: "));
  279. printf("<input type=text size=2 name=\"refresh_interval\" value=\"%d\">\n",
  280. refresh_interval);
  281. } else {
  282. printf("<input type=submit value=\"%s\" name=\"norefresh\">\n", _("Stop Refreshing"));
  283. printf("<br>%s%d\n", _("Refresh Interval: "), refresh_interval);
  284. printf("<input type=hidden name=\"refresh\" value=\"1\">\n");
  285. }
  286. printf("<p>\n");
  287. if (!tdb) {
  288. /* open failure either means no connections have been
  289. made */
  290. }
  291. printf("<table>\n");
  292. printf("<tr><td>%s</td><td>%s</td></tr>", _("version:"), SAMBA_VERSION_STRING);
  293. fflush(stdout);
  294. printf("<tr><td>%s</td><td>%s</td>\n", _("smbd:"), smbd_running()?_("running"):_("not running"));
  295. if (geteuid() == 0) {
  296. if (smbd_running()) {
  297. nr_running++;
  298. printf("<td><input type=submit name=\"smbd_stop\" value=\"%s\"></td>\n", _("Stop smbd"));
  299. } else {
  300. printf("<td><input type=submit name=\"smbd_start\" value=\"%s\"></td>\n", _("Start smbd"));
  301. }
  302. printf("<td><input type=submit name=\"smbd_restart\" value=\"%s\"></td>\n", _("Restart smbd"));
  303. }
  304. printf("</tr>\n");
  305. fflush(stdout);
  306. printf("<tr><td>%s</td><td>%s</td>\n", _("nmbd:"), nmbd_running()?_("running"):_("not running"));
  307. if (geteuid() == 0) {
  308. if (nmbd_running()) {
  309. nr_running++;
  310. printf("<td><input type=submit name=\"nmbd_stop\" value=\"%s\"></td>\n", _("Stop nmbd"));
  311. } else {
  312. printf("<td><input type=submit name=\"nmbd_start\" value=\"%s\"></td>\n", _("Start nmbd"));
  313. }
  314. printf("<td><input type=submit name=\"nmbd_restart\" value=\"%s\"></td>\n", _("Restart nmbd"));
  315. }
  316. printf("</tr>\n");
  317. #ifdef WITH_WINBIND
  318. fflush(stdout);
  319. printf("<tr><td>%s</td><td>%s</td>\n", _("winbindd:"), winbindd_running()?_("running"):_("not running"));
  320. if (geteuid() == 0) {
  321. if (winbindd_running()) {
  322. nr_running++;
  323. printf("<td><input type=submit name=\"winbindd_stop\" value=\"%s\"></td>\n", _("Stop winbindd"));
  324. } else {
  325. printf("<td><input type=submit name=\"winbindd_start\" value=\"%s\"></td>\n", _("Start winbindd"));
  326. }
  327. printf("<td><input type=submit name=\"winbindd_restart\" value=\"%s\"></td>\n", _("Restart winbindd"));
  328. }
  329. printf("</tr>\n");
  330. #endif
  331. if (geteuid() == 0) {
  332. printf("<tr><td></td><td></td>\n");
  333. if (nr_running >= 1) {
  334. /* stop, restart all */
  335. printf("<td><input type=submit name=\"all_stop\" value=\"%s\"></td>\n", _("Stop All"));
  336. printf("<td><input type=submit name=\"all_restart\" value=\"%s\"></td>\n", _("Restart All"));
  337. }
  338. else if (nr_running == 0) {
  339. /* start all */
  340. printf("<td><input type=submit name=\"all_start\" value=\"%s\"></td>\n", _("Start All"));
  341. }
  342. printf("</tr>\n");
  343. }
  344. printf("</table>\n");
  345. fflush(stdout);
  346. printf("<p><h3>%s</h3>\n", _("Active Connections"));
  347. printf("<table border=1>\n");
  348. printf("<tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th>\n", _("PID"), _("Client"), _("IP address"), _("Date"));
  349. if (geteuid() == 0) {
  350. printf("<th>%s</th>\n", _("Kill"));
  351. }
  352. printf("</tr>\n");
  353. if (tdb) tdb_traverse(tdb, traverse_fn2, NULL);
  354. printf("</table><p>\n");
  355. printf("<p><h3>%s</h3>\n", _("Active Shares"));
  356. printf("<table border=1>\n");
  357. printf("<tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th></tr>\n\n",
  358. _("Share"), _("User"), _("Group"), _("PID"), _("Client"), _("Date"));
  359. if (tdb) tdb_traverse(tdb, traverse_fn3, NULL);
  360. printf("</table><p>\n");
  361. printf("<h3>%s</h3>\n", _("Open Files"));
  362. printf("<table border=1>\n");
  363. printf("<tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th></tr>\n", _("PID"), _("Sharing"), _("R/W"), _("Oplock"), _("File"), _("Date"));
  364. locking_init(1);
  365. share_mode_forall(print_share_mode, NULL);
  366. locking_end();
  367. printf("</table>\n");
  368. if (tdb) tdb_close(tdb);
  369. printf("<br><input type=submit name=\"show_client_in_col_1\" value=\"%s\">\n", _("Show Client in col 1"));
  370. printf("<input type=submit name=\"show_pid_in_col_1\" value=\"%s\">\n", _("Show PID in col 1"));
  371. printf("</FORM>\n");
  372. if (autorefresh) {
  373. /* this little JavaScript allows for automatic refresh
  374. of the page. There are other methods but this seems
  375. to be the best alternative */
  376. printf("<script language=\"JavaScript\">\n");
  377. printf("<!--\nsetTimeout('window.location.replace(\"%s/status?refresh_interval=%d&refresh=1\")', %d)\n",
  378. cgi_baseurl(),
  379. refresh_interval,
  380. refresh_interval*1000);
  381. printf("//-->\n</script>\n");
  382. }
  383. }