Implemented Debug Tag functionality
[public/netxms.git] / src / server / core / console.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2017 Raden Solutions
4 **
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 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 **
19 ** File: console.cpp
20 **
21 **/
22
23 #include "nxcore.h"
24
25 /**
26 * Externals
27 */
28 extern Queue g_nodePollerQueue;
29 extern Queue g_dataCollectionQueue;
30 extern Queue g_dciCacheLoaderQueue;
31 extern Queue g_syslogProcessingQueue;
32 extern Queue g_syslogWriteQueue;
33 extern ThreadPool *g_pollerThreadPool;
34 extern ThreadPool *g_schedulerThreadPool;
35
36 void ShowPredictionEngines(CONSOLE_CTX console);
37 void ShowAgentTunnels(CONSOLE_CTX console);
38 UINT32 BindAgentTunnel(UINT32 tunnelId, UINT32 nodeId);
39 UINT32 UnbindAgentTunnel(UINT32 nodeId);
40
41 /**
42 * Format string to show value of global flag
43 */
44 #define SHOW_FLAG_VALUE(x) _T(" %-38s = %d\n"), _T(#x), (g_flags & x) ? 1 : 0
45
46 /**
47 * Compare given string to command template with abbreviation possibility
48 */
49 static bool IsCommand(const TCHAR *cmdTemplate, TCHAR *pszString, int iMinChars)
50 {
51 int i;
52
53 // Convert given string to uppercase
54 _tcsupr(pszString);
55
56 for(i = 0; pszString[i] != 0; i++)
57 if (pszString[i] != cmdTemplate[i])
58 return false;
59 if (i < iMinChars)
60 return false;
61 return true;
62 }
63
64 /**
65 * Dump index callback (by IP address)
66 */
67 static void DumpIndexCallbackByInetAddr(const InetAddress& addr, NetObj *object, void *data)
68 {
69 TCHAR buffer[64];
70 ConsolePrintf((CONSOLE_CTX)data, _T("%-40s %p %s [%d]\n"), addr.toString(buffer), object, object->getName(), (int)object->getId());
71 }
72
73 /**
74 * Dump index (by IP address)
75 */
76 void DumpIndex(CONSOLE_CTX pCtx, InetAddressIndex *index)
77 {
78 index->forEach(DumpIndexCallbackByInetAddr, pCtx);
79 }
80
81 /**
82 * Dump index callback (by ID)
83 */
84 static void DumpIndexCallbackById(NetObj *object, void *data)
85 {
86 ConsolePrintf((CONSOLE_CTX)data, _T("%08X %p %s\n"), object->getId(), object, object->getName());
87 }
88
89 /**
90 * Dump index (by ID)
91 */
92 static void DumpIndex(CONSOLE_CTX pCtx, ObjectIndex *index)
93 {
94 index->forEach(DumpIndexCallbackById, pCtx);
95 }
96
97 /**
98 * Process command entered from command line in standalone mode
99 * Return TRUE if command was _T("down")
100 */
101 int ProcessConsoleCommand(const TCHAR *pszCmdLine, CONSOLE_CTX pCtx)
102 {
103 TCHAR szBuffer[256], *eptr;
104 int nExitCode = CMD_EXIT_CONTINUE;
105
106 // Get command
107 const TCHAR *pArg = ExtractWord(pszCmdLine, szBuffer);
108
109 if (IsCommand(_T("AT"), szBuffer, 2))
110 {
111 pArg = ExtractWord(pArg, szBuffer);
112 if (szBuffer[0] == _T('+'))
113 {
114 int offset = _tcstoul(&szBuffer[1], NULL, 0);
115 AddOneTimeScheduledTask(_T("Execute.Script"), time(NULL) + offset, pArg, 0, 0, SYSTEM_ACCESS_FULL);//TODO: change to correct user
116 }
117 else
118 {
119 AddScheduledTask(_T("Execute.Script"), szBuffer, pArg, 0, 0, SYSTEM_ACCESS_FULL); //TODO: change to correct user
120 }
121 }
122 else if (IsCommand(_T("DEBUG"), szBuffer, 2))
123 {
124 StringList *list = ParseCommandLine(pArg);
125
126 int level;
127 if (list->size() == 1)
128 level = (int)_tcstol(list->get(0), &eptr, 0);
129 else if (list->size() == 2)
130 level = (int)_tcstol(list->get(1), &eptr, 0);
131
132 if ((*eptr == 0) && (level >= 0) && (level <= 9))
133 {
134 if (list->size() == 1)
135 nxlog_set_debug_level(level);
136 else if (list->size() == 2)
137 nxlog_set_debug_level_tag(list->get(1), level);
138 ConsolePrintf(pCtx, (level == 0) ? _T("Debug mode turned off\n") : _T("Debug level set to %d\n"), level);
139 }
140 else if (IsCommand(_T("OFF"), szBuffer, 2))
141 {
142 nxlog_set_debug_level(0);
143 ConsoleWrite(pCtx, _T("Debug mode turned off\n"));
144 }
145 else
146 {
147 if (szBuffer[0] == 0)
148 ConsoleWrite(pCtx, _T("ERROR: Missing argument\n\n"));
149 else
150 ConsoleWrite(pCtx, _T("ERROR: Invalid debug level\n\n"));
151 }
152 delete(list);
153 }
154 else if (IsCommand(_T("DOWN"), szBuffer, 4))
155 {
156 ConsoleWrite(pCtx, _T("Proceeding with server shutdown...\n"));
157 nExitCode = CMD_EXIT_SHUTDOWN;
158 }
159 else if (IsCommand(_T("DUMP"), szBuffer, 4))
160 {
161 DumpProcess(pCtx);
162 }
163 else if (IsCommand(_T("GET"), szBuffer, 3))
164 {
165 ExtractWord(pArg, szBuffer);
166 if (szBuffer[0] != 0)
167 {
168 TCHAR value[MAX_CONFIG_VALUE];
169 ConfigReadStr(szBuffer, value, MAX_CONFIG_VALUE, _T(""));
170 ConsolePrintf(pCtx, _T("%s = %s\n"), szBuffer, value);
171 }
172 else
173 {
174 ConsoleWrite(pCtx, _T("Variable name missing\n"));
175 }
176 }
177 else if (IsCommand(_T("HKRUN"), szBuffer, 2))
178 {
179 ConsoleWrite(pCtx, _T("Starting housekeeper\n"));
180 RunHouseKeeper();
181 }
182 else if (IsCommand(_T("LDAPSYNC"), szBuffer, 4))
183 {
184 LDAPConnection conn;
185 conn.syncUsers();
186 }
187 else if (IsCommand(_T("LOG"), szBuffer, 3))
188 {
189 while(_istspace(*pArg))
190 pArg++;
191 if (*pArg != 0)
192 DbgPrintf(0, _T("%s"), pArg);
193 }
194 else if (IsCommand(_T("LOGMARK"), szBuffer, 4))
195 {
196 DbgPrintf(0, _T("******* MARK *******"));
197 }
198 else if (IsCommand(_T("RAISE"), szBuffer, 5))
199 {
200 // Get argument
201 ExtractWord(pArg, szBuffer);
202
203 if (IsCommand(_T("ACCESS"), szBuffer, 6))
204 {
205 ConsoleWrite(pCtx, _T("Raising exception...\n"));
206 char *p = NULL;
207 *p = 0;
208 }
209 else if (IsCommand(_T("BREAKPOINT"), szBuffer, 5))
210 {
211 #ifdef _WIN32
212 ConsoleWrite(pCtx, _T("Raising exception...\n"));
213 RaiseException(EXCEPTION_BREAKPOINT, 0, 0, NULL);
214 #else
215 ConsoleWrite(pCtx, _T("ERROR: Not supported on current platform\n"));
216 #endif
217 }
218 else
219 {
220 ConsoleWrite(pCtx, _T("Invalid exception name; possible names are:\nACCESS BREAKPOINT\n"));
221 }
222 }
223 else if (IsCommand(_T("EXIT"), szBuffer, 4))
224 {
225 if ((pCtx->hSocket != -1) || (pCtx->session != NULL))
226 {
227 ConsoleWrite(pCtx, _T("Closing session...\n"));
228 nExitCode = CMD_EXIT_CLOSE_SESSION;
229 }
230 else
231 {
232 ConsoleWrite(pCtx, _T("Cannot exit from local server console\n"));
233 }
234 }
235 else if (IsCommand(_T("KILL"), szBuffer, 4))
236 {
237 ExtractWord(pArg, szBuffer);
238 if (szBuffer[0] != 0)
239 {
240 int id = _tcstol(szBuffer, &eptr, 10);
241 if (*eptr == 0)
242 {
243 if (KillClientSession(id))
244 {
245 ConsoleWrite(pCtx, _T("Session killed\n"));
246 }
247 else
248 {
249 ConsoleWrite(pCtx, _T("Invalid session ID\n"));
250 }
251 }
252 else
253 {
254 ConsoleWrite(pCtx, _T("Invalid session ID\n"));
255 }
256 }
257 else
258 {
259 ConsoleWrite(pCtx, _T("Session ID missing\n"));
260 }
261 }
262 else if (IsCommand(_T("PING"), szBuffer, 4))
263 {
264 ExtractWord(pArg, szBuffer);
265 if (szBuffer[0] != 0)
266 {
267 InetAddress addr = InetAddress::parse(szBuffer);
268 if (addr.isValid())
269 {
270 UINT32 rtt;
271 UINT32 rc = IcmpPing(addr, 1, 2000, &rtt, 128);
272 switch(rc)
273 {
274 case ICMP_SUCCESS:
275 ConsolePrintf(pCtx, _T("Success, RTT = %d ms\n"), (int)rtt);
276 break;
277 case ICMP_UNREACHEABLE:
278 ConsolePrintf(pCtx, _T("Destination unreachable\n"));
279 break;
280 case ICMP_TIMEOUT:
281 ConsolePrintf(pCtx, _T("Request timeout\n"));
282 break;
283 case ICMP_RAW_SOCK_FAILED:
284 ConsolePrintf(pCtx, _T("Cannot create raw socket\n"));
285 break;
286 case ICMP_API_ERROR:
287 ConsolePrintf(pCtx, _T("API error\n"));
288 break;
289 default:
290 ConsolePrintf(pCtx, _T("ERROR %d\n"), (int)rc);
291 break;
292 }
293 }
294 else
295 {
296 ConsoleWrite(pCtx, _T("Invalid IP address\n"));
297 }
298 }
299 else
300 {
301 ConsoleWrite(pCtx, _T("Usage: PING <address>\n"));
302 }
303 }
304 else if (IsCommand(_T("POLL"), szBuffer, 2))
305 {
306 pArg = ExtractWord(pArg, szBuffer);
307 if (szBuffer[0] != 0)
308 {
309 int pollType;
310 if (IsCommand(_T("CONFIGURATION"), szBuffer, 1))
311 {
312 pollType = 1;
313 }
314 else if (IsCommand(_T("ROUTING-TABLE"), szBuffer, 1))
315 {
316 pollType = 4;
317 }
318 else if (IsCommand(_T("STATUS"), szBuffer, 1))
319 {
320 pollType = 2;
321 }
322 else if (IsCommand(_T("TOPOLOGY"), szBuffer, 1))
323 {
324 pollType = 3;
325 }
326 else
327 {
328 pollType = 0;
329 }
330
331 if (pollType > 0)
332 {
333 ExtractWord(pArg, szBuffer);
334 UINT32 id = _tcstoul(szBuffer, NULL, 0);
335 if (id != 0)
336 {
337 Node *node = (Node *)FindObjectById(id, OBJECT_NODE);
338 if (node != NULL)
339 {
340 switch(pollType)
341 {
342 case 1:
343 node->lockForConfigurationPoll();
344 ThreadPoolExecute(g_pollerThreadPool, node, &Node::configurationPoll, RegisterPoller(POLLER_TYPE_CONFIGURATION, node));
345 break;
346 case 2:
347 node->lockForStatusPoll();
348 ThreadPoolExecute(g_pollerThreadPool, node, &Node::statusPoll, RegisterPoller(POLLER_TYPE_STATUS, node));
349 break;
350 case 3:
351 node->lockForTopologyPoll();
352 ThreadPoolExecute(g_pollerThreadPool, node, &Node::topologyPoll, RegisterPoller(POLLER_TYPE_TOPOLOGY, node));
353 break;
354 case 4:
355 node->lockForRoutePoll();
356 ThreadPoolExecute(g_pollerThreadPool, node, &Node::routingTablePoll, RegisterPoller(POLLER_TYPE_ROUTING_TABLE, node));
357 break;
358 }
359 }
360 else
361 {
362 ConsolePrintf(pCtx, _T("ERROR: Node with ID %d does not exist\n\n"), id);
363 }
364 }
365 else
366 {
367 ConsoleWrite(pCtx, _T("ERROR: Invalid or missing node ID\n\n"));
368 }
369 }
370 else
371 {
372 ConsoleWrite(pCtx, _T("Usage POLL [CONFIGURATION|STATUS|TOPOLOGY] <node>\n"));
373 }
374 }
375 else
376 {
377 ConsoleWrite(pCtx, _T("Usage POLL [CONFIGURATION|STATUS|TOPOLOGY] <node>\n"));
378 }
379 }
380 else if (IsCommand(_T("SET"), szBuffer, 3))
381 {
382 pArg = ExtractWord(pArg, szBuffer);
383 if (szBuffer[0] != 0)
384 {
385 TCHAR value[256];
386 ExtractWord(pArg, value);
387 if (ConfigWriteStr(szBuffer, value, TRUE, TRUE, TRUE))
388 {
389 ConsolePrintf(pCtx, _T("Configuration variable %s updated\n"), szBuffer);
390 }
391 else
392 {
393 ConsolePrintf(pCtx, _T("ERROR: cannot update configuration variable %s\n"), szBuffer);
394 }
395 }
396 else
397 {
398 ConsolePrintf(pCtx, _T("Variable name missing\n"));
399 }
400 }
401 else if (IsCommand(_T("SHOW"), szBuffer, 2))
402 {
403 // Get argument
404 pArg = ExtractWord(pArg, szBuffer);
405
406 if (IsCommand(_T("COMPONENTS"), szBuffer, 1))
407 {
408 // Get argument
409 ExtractWord(pArg, szBuffer);
410 UINT32 dwNode = _tcstoul(szBuffer, NULL, 0);
411 if (dwNode != 0)
412 {
413 NetObj *pObject = FindObjectById(dwNode);
414 if (pObject != NULL)
415 {
416 if (pObject->getObjectClass() == OBJECT_NODE)
417 {
418 ComponentTree *components = ((Node *)pObject)->getComponents();
419 if (components != NULL)
420 {
421 components->print(pCtx);
422 components->decRefCount();
423 }
424 else
425 {
426 ConsoleWrite(pCtx, _T("ERROR: Node does not have physical component information\n\n"));
427 }
428 }
429 else
430 {
431 ConsoleWrite(pCtx, _T("ERROR: Object is not a node\n\n"));
432 }
433 }
434 else
435 {
436 ConsolePrintf(pCtx, _T("ERROR: Object with ID %d does not exist\n\n"), dwNode);
437 }
438 }
439 else
440 {
441 ConsoleWrite(pCtx, _T("ERROR: Invalid or missing node ID\n\n"));
442 }
443 }
444 else if (IsCommand(_T("DBCP"), szBuffer, 4))
445 {
446 ObjectArray<PoolConnectionInfo> *list = DBConnectionPoolGetConnectionList();
447 for(int i = 0; i < list->size(); i++)
448 {
449 PoolConnectionInfo *c = list->get(i);
450 #if HAVE_LOCALTIME_R
451 struct tm tmbuffer;
452 struct tm *ltm = localtime_r(&c->lastAccessTime, &tmbuffer);
453 #else
454 struct tm *ltm = localtime(&c->lastAccessTime);
455 #endif
456 TCHAR accessTime[64];
457 _tcsftime(accessTime, 64, _T("%d.%b.%Y %H:%M:%S"), ltm);
458 ConsolePrintf(pCtx, _T("%p %s %hs:%d\n"), c->handle, accessTime, c->srcFile, c->srcLine);
459 }
460 ConsolePrintf(pCtx, _T("%d database connections in use\n\n"), list->size());
461 delete list;
462 }
463 else if (IsCommand(_T("DBSTATS"), szBuffer, 3))
464 {
465 LIBNXDB_PERF_COUNTERS counters;
466 DBGetPerfCounters(&counters);
467 ConsolePrintf(pCtx, _T("SQL query counters:\n"));
468 ConsolePrintf(pCtx, _T(" Total .......... ") INT64_FMT _T("\n"), counters.totalQueries);
469 ConsolePrintf(pCtx, _T(" SELECT ......... ") INT64_FMT _T("\n"), counters.selectQueries);
470 ConsolePrintf(pCtx, _T(" Non-SELECT ..... ") INT64_FMT _T("\n"), counters.nonSelectQueries);
471 ConsolePrintf(pCtx, _T(" Long running ... ") INT64_FMT _T("\n"), counters.longRunningQueries);
472 ConsolePrintf(pCtx, _T(" Failed ......... ") INT64_FMT _T("\n"), counters.failedQueries);
473
474 ConsolePrintf(pCtx, _T("Background writer requests:\n"));
475 ConsolePrintf(pCtx, _T(" DCI data ....... ") INT64_FMT _T("\n"), g_idataWriteRequests);
476 ConsolePrintf(pCtx, _T(" DCI raw data ... ") INT64_FMT _T("\n"), g_rawDataWriteRequests);
477 ConsolePrintf(pCtx, _T(" Others ......... ") INT64_FMT _T("\n"), g_otherWriteRequests);
478 }
479 else if (IsCommand(_T("FDB"), szBuffer, 3))
480 {
481 // Get argument
482 ExtractWord(pArg, szBuffer);
483 UINT32 dwNode = _tcstoul(szBuffer, NULL, 0);
484 if (dwNode != 0)
485 {
486 NetObj *pObject = FindObjectById(dwNode);
487 if (pObject != NULL)
488 {
489 if (pObject->getObjectClass() == OBJECT_NODE)
490 {
491 ForwardingDatabase *fdb = ((Node *)pObject)->getSwitchForwardingDatabase();
492 if (fdb != NULL)
493 {
494 fdb->print(pCtx, (Node *)pObject);
495 fdb->decRefCount();
496 }
497 else
498 {
499 ConsoleWrite(pCtx, _T("ERROR: Node does not have forwarding database information\n\n"));
500 }
501 }
502 else
503 {
504 ConsoleWrite(pCtx, _T("ERROR: Object is not a node\n\n"));
505 }
506 }
507 else
508 {
509 ConsolePrintf(pCtx, _T("ERROR: Object with ID %d does not exist\n\n"), dwNode);
510 }
511 }
512 else
513 {
514 ConsoleWrite(pCtx, _T("ERROR: Invalid or missing node ID\n\n"));
515 }
516 }
517 else if (IsCommand(_T("FLAGS"), szBuffer, 1))
518 {
519 ConsolePrintf(pCtx, _T("Flags: 0x") UINT64X_FMT(_T("016")) _T("\n"), g_flags);
520 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_DAEMON));
521 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_USE_SYSLOG));
522 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_ENABLE_NETWORK_DISCOVERY));
523 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_ACTIVE_NETWORK_DISCOVERY));
524 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_LOG_SQL_ERRORS));
525 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_DELETE_EMPTY_SUBNETS));
526 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_ENABLE_SNMP_TRAPD));
527 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_ENABLE_ZONING));
528 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_SYNC_NODE_NAMES_WITH_DNS));
529 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_CHECK_TRUSTED_NODES));
530 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_ENABLE_NXSL_CONTAINER_FUNCS));
531 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_USE_FQDN_FOR_NODE_NAMES));
532 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_APPLY_TO_DISABLED_DCI_FROM_TEMPLATE));
533 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_DEBUG_CONSOLE_DISABLED));
534 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_ENABLE_OBJECT_TRANSACTIONS));
535 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_WRITE_FULL_DUMP));
536 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_RESOLVE_NODE_NAMES));
537 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_CATCH_EXCEPTIONS));
538 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_HELPDESK_LINK_ACTIVE));
539 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_DB_LOCKED));
540 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_DB_CONNECTION_LOST));
541 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_NO_NETWORK_CONNECTIVITY));
542 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_EVENT_STORM_DETECTED));
543 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_SNMP_TRAP_DISCOVERY));
544 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_TRAPS_FROM_UNMANAGED_NODES));
545 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_RESOLVE_IP_FOR_EACH_STATUS_POLL));
546 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_PERFDATA_STORAGE_DRIVER_LOADED));
547 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_BACKGROUND_LOG_WRITER));
548 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_CASE_INSENSITIVE_LOGINS));
549 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_TRAP_SOURCES_IN_ALL_ZONES));
550 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_SYSLOG_DISCOVERY));
551 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_ENABLE_LOCAL_CONSOLE));
552 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_SERVER_INITIALIZED));
553 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_SHUTDOWN));
554 ConsolePrintf(pCtx, _T("\n"));
555 }
556 else if (IsCommand(_T("HEAP"), szBuffer, 1))
557 {
558 TCHAR *text = GetHeapInfo();
559 if (text != NULL)
560 {
561 ConsoleWrite(pCtx, text);
562 ConsoleWrite(pCtx, _T("\n"));
563 free(text);
564 }
565 else
566 {
567 ConsoleWrite(pCtx, _T("Error reading heap information\n"));
568 }
569 }
570 else if (IsCommand(_T("INDEX"), szBuffer, 1))
571 {
572 // Get argument
573 pArg = ExtractWord(pArg, szBuffer);
574
575 if (IsCommand(_T("CONDITION"), szBuffer, 1))
576 {
577 DumpIndex(pCtx, &g_idxConditionById);
578 }
579 else if (IsCommand(_T("ID"), szBuffer, 2))
580 {
581 DumpIndex(pCtx, &g_idxObjectById);
582 }
583 else if (IsCommand(_T("INTERFACE"), szBuffer, 2))
584 {
585 pArg = ExtractWord(pArg, szBuffer);
586 if (IsCommand(_T("ZONE"), szBuffer, 1))
587 {
588 ExtractWord(pArg, szBuffer);
589 Zone *zone = FindZoneByUIN(_tcstoul(szBuffer, NULL, 0));
590 if (zone != NULL)
591 {
592 zone->dumpInterfaceIndex(pCtx);
593 }
594 else
595 {
596 ConsoleWrite(pCtx, _T("ERROR: Invalid zone UIN\n\n"));
597 }
598 }
599 else if (szBuffer[0] == 0)
600 {
601 DumpIndex(pCtx, &g_idxInterfaceByAddr);
602 }
603 else
604 {
605 ConsoleWrite(pCtx, _T("ERROR: Invalid index modifier\n\n"));
606 }
607 }
608 else if (IsCommand(_T("NODEADDR"), szBuffer, 5))
609 {
610 pArg = ExtractWord(pArg, szBuffer);
611 if (IsCommand(_T("ZONE"), szBuffer, 1))
612 {
613 ExtractWord(pArg, szBuffer);
614 Zone *zone = FindZoneByUIN(_tcstoul(szBuffer, NULL, 0));
615 if (zone != NULL)
616 {
617 zone->dumpNodeIndex(pCtx);
618 }
619 else
620 {
621 ConsoleWrite(pCtx, _T("ERROR: Invalid zone UIN\n\n"));
622 }
623 }
624 else if (szBuffer[0] == 0)
625 {
626 DumpIndex(pCtx, &g_idxNodeByAddr);
627 }
628 else
629 {
630 ConsoleWrite(pCtx, _T("ERROR: Invalid index modifier\n\n"));
631 }
632 }
633 else if (IsCommand(_T("NODEID"), szBuffer, 5))
634 {
635 DumpIndex(pCtx, &g_idxNodeById);
636 }
637 else if (IsCommand(_T("SUBNET"), szBuffer, 1))
638 {
639 pArg = ExtractWord(pArg, szBuffer);
640 if (IsCommand(_T("ZONE"), szBuffer, 1))
641 {
642 ExtractWord(pArg, szBuffer);
643 Zone *zone = FindZoneByUIN(_tcstoul(szBuffer, NULL, 0));
644 if (zone != NULL)
645 {
646 zone->dumpSubnetIndex(pCtx);
647 }
648 else
649 {
650 ConsoleWrite(pCtx, _T("ERROR: Invalid zone UIN\n\n"));
651 }
652 }
653 else if (szBuffer[0] == 0)
654 {
655 DumpIndex(pCtx, &g_idxSubnetByAddr);
656 }
657 else
658 {
659 ConsoleWrite(pCtx, _T("ERROR: Invalid index modifier\n\n"));
660 }
661 }
662 else if (IsCommand(_T("ZONE"), szBuffer, 1))
663 {
664 DumpIndex(pCtx, &g_idxZoneByUIN);
665 }
666 else
667 {
668 if (szBuffer[0] == 0)
669 ConsoleWrite(pCtx, _T("ERROR: Missing parameters\n")
670 _T("Syntax:\n SHOW INDEX name [ZONE uin]\n")
671 _T("Valid names are: CONDITION, ID, INTERFACE, NODEADDR, NODEID, SUBNET, ZONE\n\n"));
672 else
673 ConsoleWrite(pCtx, _T("ERROR: Invalid index name\n\n"));
674 }
675 }
676 else if (IsCommand(_T("LLDP"), szBuffer, 4))
677 {
678 // Get argument
679 ExtractWord(pArg, szBuffer);
680 UINT32 dwNode = _tcstoul(szBuffer, NULL, 0);
681 if (dwNode != 0)
682 {
683 NetObj *pObject = FindObjectById(dwNode);
684 if (pObject != NULL)
685 {
686 if (pObject->getObjectClass() == OBJECT_NODE)
687 {
688 ((Node *)pObject)->showLLDPInfo(pCtx);
689 }
690 else
691 {
692 ConsoleWrite(pCtx, _T("ERROR: Object is not a node\n\n"));
693 }
694 }
695 else
696 {
697 ConsolePrintf(pCtx, _T("ERROR: Object with ID %d does not exist\n\n"), dwNode);
698 }
699 }
700 else
701 {
702 ConsoleWrite(pCtx, _T("ERROR: Invalid or missing node ID\n\n"));
703 }
704 }
705 else if (IsCommand(_T("MODULES"), szBuffer, 3))
706 {
707 ConsoleWrite(pCtx, _T("Loaded server modules:\n"));
708 for(UINT32 i = 0; i < g_dwNumModules; i++)
709 {
710 ConsolePrintf(pCtx, _T(" %s\n"), g_pModuleList[i].szName);
711 }
712 ConsolePrintf(pCtx, _T("%d modules loaded\n"), g_dwNumModules);
713 }
714 else if (IsCommand(_T("MSGWQ"), szBuffer, 2))
715 {
716 String text = MsgWaitQueue::getDiagInfo();
717 ConsoleWrite(pCtx, text);
718 ConsoleWrite(pCtx, _T("\n"));
719 }
720 else if (IsCommand(_T("OBJECTS"), szBuffer, 1))
721 {
722 // Get filter
723 ExtractWord(pArg, szBuffer);
724 StrStrip(szBuffer);
725 DumpObjects(pCtx, (szBuffer[0] != 0) ? szBuffer : NULL);
726 }
727 else if (IsCommand(_T("PE"), szBuffer, 2))
728 {
729 ShowPredictionEngines(pCtx);
730 }
731 else if (IsCommand(_T("POLLERS"), szBuffer, 2))
732 {
733 ShowPollers(pCtx);
734 }
735 else if (IsCommand(_T("QUEUES"), szBuffer, 1))
736 {
737 ShowQueueStats(pCtx, &g_dataCollectionQueue, _T("Data collector"));
738 ShowQueueStats(pCtx, &g_dciCacheLoaderQueue, _T("DCI cache loader"));
739 ShowQueueStats(pCtx, g_dbWriterQueue, _T("Database writer"));
740 ShowQueueStats(pCtx, g_dciDataWriterQueue, _T("Database writer (IData)"));
741 ShowQueueStats(pCtx, g_dciRawDataWriterQueue, _T("Database writer (raw DCI values)"));
742 ShowQueueStats(pCtx, g_pEventQueue, _T("Event processor"));
743 ShowQueueStats(pCtx, &g_nodePollerQueue, _T("Node poller"));
744 ShowQueueStats(pCtx, &g_syslogProcessingQueue, _T("Syslog processing"));
745 ShowQueueStats(pCtx, &g_syslogWriteQueue, _T("Syslog writer"));
746 ConsolePrintf(pCtx, _T("\n"));
747 }
748 else if (IsCommand(_T("ROUTING-TABLE"), szBuffer, 1))
749 {
750 UINT32 dwNode;
751 NetObj *pObject;
752
753 ExtractWord(pArg, szBuffer);
754 dwNode = _tcstoul(szBuffer, NULL, 0);
755 if (dwNode != 0)
756 {
757 pObject = FindObjectById(dwNode);
758 if (pObject != NULL)
759 {
760 if (pObject->getObjectClass() == OBJECT_NODE)
761 {
762 ROUTING_TABLE *pRT;
763 TCHAR szIpAddr[16];
764 int i;
765
766 ConsolePrintf(pCtx, _T("Routing table for node %s:\n\n"), pObject->getName());
767 pRT = ((Node *)pObject)->getCachedRoutingTable();
768 if (pRT != NULL)
769 {
770 for(i = 0; i < pRT->iNumEntries; i++)
771 {
772 _sntprintf(szBuffer, 256, _T("%s/%d"), IpToStr(pRT->pRoutes[i].dwDestAddr, szIpAddr),
773 BitsInMask(pRT->pRoutes[i].dwDestMask));
774 ConsolePrintf(pCtx, _T("%-18s %-15s %-6d %d\n"), szBuffer,
775 IpToStr(pRT->pRoutes[i].dwNextHop, szIpAddr),
776 pRT->pRoutes[i].dwIfIndex, pRT->pRoutes[i].dwRouteType);
777 }
778 ConsoleWrite(pCtx, _T("\n"));
779 }
780 else
781 {
782 ConsoleWrite(pCtx, _T("Node doesn't have cached routing table\n\n"));
783 }
784 }
785 else
786 {
787 ConsoleWrite(pCtx, _T("ERROR: Object is not a node\n\n"));
788 }
789 }
790 else
791 {
792 ConsolePrintf(pCtx, _T("ERROR: Object with ID %d does not exist\n\n"), dwNode);
793 }
794 }
795 else
796 {
797 ConsoleWrite(pCtx, _T("ERROR: Invalid or missing node ID\n\n"));
798 }
799 }
800 else if (IsCommand(_T("SESSIONS"), szBuffer, 2))
801 {
802 ConsoleWrite(pCtx, _T("\x1b[1mCLIENT SESSIONS\x1b[0m\n============================================================\n"));
803 DumpClientSessions(pCtx);
804 ConsoleWrite(pCtx, _T("\n\x1b[1mMOBILE DEVICE SESSIONS\x1b[0m\n============================================================\n"));
805 DumpMobileDeviceSessions(pCtx);
806 }
807 else if (IsCommand(_T("STATS"), szBuffer, 2))
808 {
809 ShowServerStats(pCtx);
810 }
811 else if (IsCommand(_T("THREADS"), szBuffer, 2))
812 {
813 ShowThreadPool(pCtx, g_mainThreadPool);
814 ShowThreadPool(pCtx, g_pollerThreadPool);
815 ShowThreadPool(pCtx, g_schedulerThreadPool);
816 ShowThreadPool(pCtx, g_agentConnectionThreadPool);
817 }
818 else if (IsCommand(_T("TOPOLOGY"), szBuffer, 1))
819 {
820 ExtractWord(pArg, szBuffer);
821 UINT32 nodeId = _tcstoul(szBuffer, NULL, 0);
822 if (nodeId != 0)
823 {
824 Node *node = (Node *)FindObjectById(nodeId, OBJECT_NODE);
825 if (node != NULL)
826 {
827 LinkLayerNeighbors *nbs = BuildLinkLayerNeighborList(node);
828 if (nbs != NULL)
829 {
830 ConsolePrintf(pCtx, _T("Proto | PtP | ifLocal | ifRemote | Peer\n")
831 _T("--------+-----+---------+----------+------------------------------------\n"));
832 for(int i = 0; i < nbs->size(); i++)
833 {
834 LL_NEIGHBOR_INFO *ni = nbs->getConnection(i);
835 TCHAR peer[256];
836 if (ni->objectId != 0)
837 {
838 NetObj *object = FindObjectById(ni->objectId);
839 if (object != NULL)
840 _sntprintf(peer, 256, _T("%s [%d]"), object->getName(), ni->objectId);
841 else
842 _sntprintf(peer, 256, _T("[%d]"), ni->objectId);
843 }
844 else
845 {
846 peer[0] = 0;
847 }
848 ConsolePrintf(pCtx, _T("%-7s | %c | %7d | %7d | %s\n"),
849 GetLinkLayerProtocolName(ni->protocol), ni->isPtToPt ? _T('Y') : _T('N'), ni->ifLocal, ni->ifRemote, peer);
850 }
851 nbs->decRefCount();
852 }
853 else
854 {
855 ConsoleWrite(pCtx, _T("ERROR: call to BuildLinkLayerNeighborList failed\n\n"));
856 }
857 }
858 else
859 {
860 ConsolePrintf(pCtx, _T("ERROR: Node with ID %d does not exist\n\n"), nodeId);
861 }
862 }
863 else
864 {
865 ConsoleWrite(pCtx, _T("ERROR: Invalid or missing node ID\n\n"));
866 }
867 }
868 else if (IsCommand(_T("TUNNELS"), szBuffer, 2))
869 {
870 ShowAgentTunnels(pCtx);
871 }
872 else if (IsCommand(_T("USERS"), szBuffer, 1))
873 {
874 DumpUsers(pCtx);
875 }
876 else if (IsCommand(_T("VLANS"), szBuffer, 1))
877 {
878 UINT32 dwNode;
879 NetObj *pObject;
880
881 ExtractWord(pArg, szBuffer);
882 dwNode = _tcstoul(szBuffer, NULL, 0);
883 if (dwNode != 0)
884 {
885 pObject = FindObjectById(dwNode);
886 if (pObject != NULL)
887 {
888 if (pObject->getObjectClass() == OBJECT_NODE)
889 {
890 VlanList *vlans = ((Node *)pObject)->getVlans();
891 if (vlans != NULL)
892 {
893 ConsoleWrite(pCtx, _T("\x1b[1mVLAN\x1b[0m | \x1b[1mName\x1b[0m | \x1b[1mPorts\x1b[0m\n")
894 _T("-----+------------------+-----------------------------------------------------------------\n"));
895 for(int i = 0; i < vlans->size(); i++)
896 {
897 VlanInfo *vlan = vlans->get(i);
898 ConsolePrintf(pCtx, _T("%4d | %-16s |"), vlan->getVlanId(), vlan->getName());
899 for(int j = 0; j < vlan->getNumPorts(); j++)
900 ConsolePrintf(pCtx, _T(" %d.%d"), (int)(vlan->getPorts()[j] >> 16), (int)(vlan->getPorts()[j] & 0xFFFF));
901 ConsolePrintf(pCtx, _T("\n"));
902 }
903 ConsolePrintf(pCtx, _T("\n"));
904 vlans->decRefCount();
905 }
906 else
907 {
908 ConsoleWrite(pCtx, _T("\x1b[31mNode doesn't have VLAN information\x1b[0m\n\n"));
909 }
910 }
911 else
912 {
913 ConsoleWrite(pCtx, _T("\x1b[31mERROR: Object is not a node\x1b[0m\n\n"));
914 }
915 }
916 else
917 {
918 ConsolePrintf(pCtx, _T("\x1b[31mERROR: Object with ID %d does not exist\x1b[0m\n\n"), dwNode);
919 }
920 }
921 else
922 {
923 ConsoleWrite(pCtx, _T("\x1b[31mERROR: Invalid or missing node ID\x1b[0m\n\n"));
924 }
925 }
926 else if (IsCommand(_T("WATCHDOG"), szBuffer, 1))
927 {
928 WatchdogPrintStatus(pCtx);
929 ConsoleWrite(pCtx, _T("\n"));
930 }
931 else
932 {
933 if (szBuffer[0] == 0)
934 ConsoleWrite(pCtx, _T("ERROR: Missing subcommand\n\n"));
935 else
936 ConsoleWrite(pCtx, _T("ERROR: Invalid SHOW subcommand\n\n"));
937 }
938 }
939 else if (IsCommand(_T("SNAPSHOT"), szBuffer, 4))
940 {
941 // create access snapshot
942 ExtractWord(pArg, szBuffer);
943 UINT32 userId = _tcstoul(szBuffer, NULL, 0);
944 bool success = CreateObjectAccessSnapshot(userId, OBJECT_NODE);
945 ConsolePrintf(pCtx, _T("Object access snapshot creation for user %d %s\n\n"), userId, success ? _T("successful") : _T("failed"));
946 }
947 else if (IsCommand(_T("EXEC"), szBuffer, 3))
948 {
949 pArg = ExtractWord(pArg, szBuffer);
950
951 bool libraryLocked = true;
952 bool destroyCompiledScript = false;
953 NXSL_Library *scriptLibrary = GetServerScriptLibrary();
954 scriptLibrary->lock();
955
956 NXSL_Program *compiledScript = scriptLibrary->findNxslProgram(szBuffer);
957 if (compiledScript == NULL)
958 {
959 scriptLibrary->unlock();
960 libraryLocked = false;
961 destroyCompiledScript = true;
962 char *script;
963 UINT32 fileSize;
964 if ((script = (char *)LoadFile(szBuffer, &fileSize)) != NULL)
965 {
966 const int errorMsgLen = 512;
967 TCHAR errorMsg[errorMsgLen];
968 #ifdef UNICODE
969 WCHAR *wscript = WideStringFromMBString(script);
970 compiledScript = NXSLCompile(wscript, errorMsg, errorMsgLen, NULL);
971 free(wscript);
972 #else
973 compiledScript = NXSLCompile(script, errorMsg, errorMsgLen, NULL);
974 #endif
975 free(script);
976 if (compiledScript == NULL)
977 {
978 ConsolePrintf(pCtx, _T("ERROR: Script compilation error: %s\n\n"), errorMsg);
979 }
980 }
981 else
982 {
983 ConsolePrintf(pCtx, _T("ERROR: Script \"%s\" not found\n\n"), szBuffer);
984 }
985 }
986
987 if (compiledScript != NULL)
988 {
989 NXSL_ServerEnv *pEnv = new NXSL_ServerEnv;
990 pEnv->setConsole(pCtx);
991
992 NXSL_VM *vm = new NXSL_VM(pEnv);
993 if (vm->load(compiledScript))
994 {
995 if (libraryLocked)
996 {
997 scriptLibrary->unlock();
998 libraryLocked = false;
999 }
1000
1001 NXSL_Value *argv[32];
1002 int argc = 0;
1003 while(argc < 32)
1004 {
1005 pArg = ExtractWord(pArg, szBuffer);
1006 if (szBuffer[0] == 0)
1007 break;
1008 argv[argc++] = new NXSL_Value(szBuffer);
1009 }
1010
1011 if (vm->run(argc, argv))
1012 {
1013 NXSL_Value *pValue = vm->getResult();
1014 int retCode = pValue->getValueAsInt32();
1015 ConsolePrintf(pCtx, _T("INFO: Script finished with rc=%d\n\n"), retCode);
1016 }
1017 else
1018 {
1019 ConsolePrintf(pCtx, _T("ERROR: Script finished with error: %s\n\n"), vm->getErrorText());
1020 }
1021 }
1022 else
1023 {
1024 ConsolePrintf(pCtx, _T("ERROR: VM creation failed: %s\n\n"), vm->getErrorText());
1025 }
1026 delete vm;
1027 if (destroyCompiledScript)
1028 delete compiledScript;
1029 }
1030 if (libraryLocked)
1031 scriptLibrary->unlock();
1032 }
1033 else if (IsCommand(_T("TRACE"), szBuffer, 1))
1034 {
1035 UINT32 dwNode1, dwNode2;
1036 NetObj *pObject1, *pObject2;
1037 NetworkPath *pTrace;
1038 TCHAR szNextHop[16];
1039 int i;
1040
1041 // Get arguments
1042 pArg = ExtractWord(pArg, szBuffer);
1043 dwNode1 = _tcstoul(szBuffer, NULL, 0);
1044
1045 ExtractWord(pArg, szBuffer);
1046 dwNode2 = _tcstoul(szBuffer, NULL, 0);
1047
1048 if ((dwNode1 != 0) && (dwNode2 != 0))
1049 {
1050 pObject1 = FindObjectById(dwNode1);
1051 if (pObject1 == NULL)
1052 {
1053 ConsolePrintf(pCtx, _T("ERROR: Object with ID %d does not exist\n\n"), dwNode1);
1054 }
1055 else
1056 {
1057 pObject2 = FindObjectById(dwNode2);
1058 if (pObject2 == NULL)
1059 {
1060 ConsolePrintf(pCtx, _T("ERROR: Object with ID %d does not exist\n\n"), dwNode2);
1061 }
1062 else
1063 {
1064 if ((pObject1->getObjectClass() == OBJECT_NODE) && (pObject2->getObjectClass() == OBJECT_NODE))
1065 {
1066 pTrace = TraceRoute((Node *)pObject1, (Node *)pObject2);
1067 if (pTrace != NULL)
1068 {
1069 TCHAR sourceIp[32];
1070 ConsolePrintf(pCtx, _T("Trace from %s to %s (%d hops, %s, source IP %s):\n"),
1071 pObject1->getName(), pObject2->getName(), pTrace->getHopCount(),
1072 pTrace->isComplete() ? _T("complete") : _T("incomplete"),
1073 pTrace->getSourceAddress().toString(sourceIp));
1074 for(i = 0; i < pTrace->getHopCount(); i++)
1075 {
1076 HOP_INFO *hop = pTrace->getHopInfo(i);
1077 ConsolePrintf(pCtx, _T("[%d] %s %s %s %d\n"),
1078 hop->object->getId(),
1079 hop->object->getName(),
1080 hop->nextHop.toString(szNextHop),
1081 hop->isVpn ? _T("VPN Connector ID:") : _T("Interface Index: "),
1082 hop->ifIndex);
1083 }
1084 delete pTrace;
1085 ConsolePrintf(pCtx, _T("\n"));
1086 }
1087 else
1088 {
1089 ConsoleWrite(pCtx, _T("ERROR: Call to TraceRoute() failed\n\n"));
1090 }
1091 }
1092 else
1093 {
1094 ConsoleWrite(pCtx, _T("ERROR: Object is not a node\n\n"));
1095 }
1096 }
1097 }
1098 }
1099 else
1100 {
1101 ConsoleWrite(pCtx, _T("ERROR: Invalid or missing node id(s)\n\n"));
1102 }
1103 }
1104 else if (IsCommand(_T("TUNNEL"), szBuffer, 2))
1105 {
1106 pArg = ExtractWord(pArg, szBuffer);
1107 if (IsCommand(_T("BIND"), szBuffer, 1))
1108 {
1109 pArg = ExtractWord(pArg, szBuffer);
1110 UINT32 tunnelId = _tcstoul(szBuffer, NULL, 0);
1111
1112 ExtractWord(pArg, szBuffer);
1113 UINT32 nodeId = _tcstoul(szBuffer, NULL, 0);
1114
1115 if ((tunnelId != 0) && (nodeId != 0))
1116 {
1117 UINT32 rcc = BindAgentTunnel(tunnelId, nodeId);
1118 ConsolePrintf(pCtx, _T("Bind tunnel %d to node %d: RCC = %d\n\n"), tunnelId, nodeId, rcc);
1119 }
1120 else
1121 {
1122 ConsoleWrite(pCtx, _T("ERROR: Invalid or missing argument(s)\n\n"));
1123 }
1124 }
1125 else if (IsCommand(_T("UNBIND"), szBuffer, 1))
1126 {
1127 ExtractWord(pArg, szBuffer);
1128 UINT32 nodeId = _tcstoul(szBuffer, NULL, 0);
1129
1130 if (nodeId != 0)
1131 {
1132 UINT32 rcc = UnbindAgentTunnel(nodeId);
1133 ConsolePrintf(pCtx, _T("Unbind tunnel from node %d: RCC = %d\n\n"), nodeId, rcc);
1134 }
1135 else
1136 {
1137 ConsoleWrite(pCtx, _T("ERROR: Invalid or missing argument(s)\n\n"));
1138 }
1139 }
1140 else
1141 {
1142 ConsoleWrite(pCtx, _T("ERROR: Invalid TUNNEL subcommand\n\n"));
1143 }
1144 }
1145 else if (IsCommand(_T("HELP"), szBuffer, 2) || IsCommand(_T("?"), szBuffer, 1))
1146 {
1147 ConsoleWrite(pCtx,
1148 _T("Valid commands are:\n")
1149 _T(" at +<sec> <script> [<params>] - Schedule one time script execution task\n")
1150 _T(" at <schedule> <script> [<params>] - Schedule repeated script execution task\n")
1151 _T(" debug [<level>|off] - Set debug level (valid range is 0..9)\n")
1152 _T(" down - Shutdown NetXMS server\n")
1153 _T(" exec <script> [<params>] - Executes NXSL script from script library\n")
1154 _T(" exit - Exit from remote session\n")
1155 _T(" kill <session> - Kill client session\n")
1156 _T(" get <variable> - Get value of server configuration variable\n")
1157 _T(" help - Display this help\n")
1158 _T(" hkrun - Run housekeeper immediately\n")
1159 _T(" ldapsync - Synchronize ldap users with local user database\n")
1160 _T(" log <text> - Write given text to server log file\n")
1161 _T(" logmark - Write marker ******* MARK ******* to server log file\n")
1162 _T(" ping <address> - Send ICMP echo request to given IP address\n")
1163 _T(" poll <type> <node> - Initiate node poll\n")
1164 _T(" raise <exception> - Raise exception\n")
1165 _T(" set <variable> <value> - Set value of server configuration variable\n")
1166 _T(" show components <node> - Show physical components of given node\n")
1167 _T(" show dbcp - Show active sessions in database connection pool\n")
1168 _T(" show dbstats - Show DB library statistics\n")
1169 _T(" show fdb <node> - Show forwarding database for node\n")
1170 _T(" show flags - Show internal server flags\n")
1171 _T(" show heap - Show heap information\n")
1172 _T(" show index <index> - Show internal index\n")
1173 _T(" show modules - Show loaded server modules\n")
1174 _T(" show msgwq - Show message wait queues information\n")
1175 _T(" show objects [<filter>] - Dump network objects to screen\n")
1176 _T(" show pe - Show registered prediction engines\n")
1177 _T(" show pollers - Show poller threads state information\n")
1178 _T(" show queues - Show internal queues statistics\n")
1179 _T(" show routing-table <node> - Show cached routing table for node\n")
1180 _T(" show sessions - Show active client sessions\n")
1181 _T(" show stats - Show server statistics\n")
1182 _T(" show topology <node> - Collect and show link layer topology for node\n")
1183 _T(" show tunnels - Show active agent tunnels\n")
1184 _T(" show users - Show users\n")
1185 _T(" show vlans <node> - Show cached VLAN information for node\n")
1186 _T(" show watchdog - Display watchdog information\n")
1187 _T(" trace <node1> <node2> - Show network path trace between two nodes\n")
1188 _T(" tunnel bind <tunnel> <node> - Bind agent tunnel to node\n")
1189 _T(" tunnel unbind <node> - Unbind agent tunnel from node\n")
1190 _T("\nAlmost all commands can be abbreviated to 2 or 3 characters\n")
1191 _T("\n"));
1192 }
1193 else
1194 {
1195 ConsoleWrite(pCtx, _T("UNKNOWN COMMAND\n\n"));
1196 }
1197
1198 return nExitCode;
1199 }