fixed buffer overflow in LDAP sync
[public/netxms.git] / src / server / core / main.cpp
CommitLineData
d9177dd1 1/*
5039dede 2** NetXMS - Network Management System
43a6f3ca 3** Copyright (C) 2003-2015 NetXMS Team
5039dede
AK
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: main.cpp
20**
21**/
22
23#include "nxcore.h"
24#include <netxmsdb.h>
fdbee7f8 25#include <netxms_mt.h>
6fad8870 26#include <hdlink.h>
5039dede 27
b847803c 28#if !defined(_WIN32) && HAVE_READLINE_READLINE_H && HAVE_READLINE && !defined(UNICODE)
0322eed7
VK
29#include <readline/readline.h>
30#include <readline/history.h>
31#define USE_READLINE 1
5039dede
AK
32#endif
33
34#ifdef _WIN32
a23d8e0d
VK
35#include <errno.h>
36#include <psapi.h>
7bdb43c3 37#include <conio.h>
d717b69c
VK
38#define open _open
39#define write _write
40#define close _close
5039dede 41#else
a23d8e0d
VK
42#include <signal.h>
43#include <sys/wait.h>
5039dede
AK
44#endif
45
4ef60905
AK
46#ifdef WITH_ZMQ
47#include "zeromq.h"
48#endif
49
ea50bc33
VK
50/**
51 * Format string to show value of global flag
52 */
53#define SHOW_FLAG_VALUE(x) _T(" %-38s = %d\n"), _T(#x), (g_flags & x) ? 1 : 0
54
3a82d5ae
VK
55/**
56 * Messages generated by mc.pl (for UNIX version only)
57 */
5039dede
AK
58#ifndef _WIN32
59extern unsigned int g_dwNumMessages;
60extern const TCHAR *g_szMessages[];
61#endif
62
8f99849c
VK
63/**
64 * Shutdown reasons
65 */
030a0779
VK
66#define SHUTDOWN_DEFAULT 0
67#define SHUTDOWN_FROM_CONSOLE 1
68#define SHUTDOWN_BY_SIGNAL 2
5039dede 69
8f99849c
VK
70/**
71 * Externals
72 */
5039dede 73extern Queue g_nodePollerQueue;
d140955e
VK
74extern Queue g_dataCollectionQueue;
75extern Queue g_dciCacheLoaderQueue;
f1784ab6
VK
76extern Queue g_syslogProcessingQueue;
77extern Queue g_syslogWriteQueue;
208d7427 78extern ThreadPool *g_pollerThreadPool;
c6e191d2 79extern ThreadPool *g_schedulerThreadPool;
5039dede 80
36e44abe 81void InitClientListeners();
534e1b83 82void InitMobileDeviceListeners();
36e44abe 83void InitCertificates();
ab185583
VK
84void InitUsers();
85void CleanupUsers();
8fd95c92 86void LoadPerfDataStorageDrivers();
ec13a467
VK
87
88void ExecuteScheduledScript(const ScheduledTaskParameters *param);
89void MaintenanceModeEnter(const ScheduledTaskParameters *params);
90void MaintenanceModeLeave(const ScheduledTaskParameters *params);
058bf6fc
VK
91
92#if XMPP_SUPPORTED
098ef635 93void StartXMPPConnector();
244c65ef 94void StopXMPPConnector();
058bf6fc 95#endif
5039dede 96
af4a09df
VK
97/**
98 * Syslog server control
99 */
100void StartSyslogServer();
101void StopSyslogServer();
102
a64c346b
VK
103/**
104 * Housekeeper control
105 */
106void StartHouseKeeper();
107void StopHouseKeeper();
108void RunHouseKeeper();
109
534e1b83
VK
110/**
111 * Thread functions
112 */
534e1b83
VK
113THREAD_RESULT THREAD_CALL Syncer(void *);
114THREAD_RESULT THREAD_CALL NodePoller(void *);
115THREAD_RESULT THREAD_CALL PollManager(void *);
116THREAD_RESULT THREAD_CALL EventProcessor(void *);
117THREAD_RESULT THREAD_CALL WatchdogThread(void *);
118THREAD_RESULT THREAD_CALL ClientListener(void *);
119THREAD_RESULT THREAD_CALL ClientListenerIPv6(void *);
120THREAD_RESULT THREAD_CALL MobileDeviceListener(void *);
121THREAD_RESULT THREAD_CALL MobileDeviceListenerIPv6(void *);
122THREAD_RESULT THREAD_CALL ISCListener(void *);
123THREAD_RESULT THREAD_CALL LocalAdminListener(void *);
124THREAD_RESULT THREAD_CALL SNMPTrapReceiver(void *);
534e1b83
VK
125THREAD_RESULT THREAD_CALL BeaconPoller(void *);
126THREAD_RESULT THREAD_CALL JobManagerThread(void *);
127THREAD_RESULT THREAD_CALL UptimeCalculator(void *);
d75003e1 128THREAD_RESULT THREAD_CALL ReportingServerConnector(void *);
058bf6fc 129
534e1b83
VK
130/**
131 * Global variables
132 */
1039d7ee 133TCHAR NXCORE_EXPORTABLE g_szConfigFile[MAX_PATH] = _T("{search}");
5039dede 134TCHAR NXCORE_EXPORTABLE g_szLogFile[MAX_PATH] = DEFAULT_LOG_FILE;
967893bb
VK
135UINT32 g_dwLogRotationMode = NXLOG_ROTATION_BY_SIZE;
136UINT32 g_dwMaxLogSize = 16384 * 1024;
137UINT32 g_dwLogHistorySize = 4;
4f8998ca 138TCHAR g_szDailyLogFileSuffix[64] = _T("");
5039dede 139TCHAR NXCORE_EXPORTABLE g_szDumpDir[MAX_PATH] = DEFAULT_DUMP_DIR;
29dc8792 140char g_szCodePage[256] = ICONV_DEFAULT_CODEPAGE;
5f6e8d09 141TCHAR NXCORE_EXPORTABLE g_szListenAddress[MAX_PATH] = _T("*");
5039dede 142#ifndef _WIN32
b07c50cc 143TCHAR NXCORE_EXPORTABLE g_szPIDFile[MAX_PATH] = _T("/var/run/netxmsd.pid");
5039dede 144#endif
967893bb
VK
145UINT32 g_dwDiscoveryPollingInterval;
146UINT32 g_dwStatusPollingInterval;
147UINT32 g_dwConfigurationPollingInterval;
148UINT32 g_dwRoutingTableUpdateInterval;
149UINT32 g_dwTopologyPollingInterval;
150UINT32 g_dwConditionPollingInterval;
805171de 151UINT32 g_instancePollingInterval;
c59466d2
VK
152UINT32 g_icmpPingSize;
153UINT32 g_icmpPingTimeout = 1500; // ICMP ping timeout (milliseconds)
154UINT32 g_auditFlags;
155UINT32 g_slmPollingInterval;
db6a6b45
VK
156TCHAR NXCORE_EXPORTABLE g_netxmsdDataDir[MAX_PATH] = _T("");
157TCHAR NXCORE_EXPORTABLE g_netxmsdLibDir[MAX_PATH] = _T("");
2a964810 158int g_dbSyntax = DB_SYNTAX_UNKNOWN;
967893bb 159UINT32 NXCORE_EXPORTABLE g_processAffinityMask = DEFAULT_AFFINITY_MASK;
e9902466 160UINT64 g_serverId = 0;
5039dede 161RSA *g_pServerKey = NULL;
c59466d2
VK
162time_t g_serverStartTime = 0;
163UINT32 g_lockTimeout = 60000; // Default timeout for acquiring mutex
164UINT32 g_agentCommandTimeout = 4000; // Default timeout for requests to agent
165UINT32 g_thresholdRepeatInterval = 0; // Disabled by default
166int g_requiredPolls = 1;
b8c1ec69 167DB_DRIVER g_dbDriver = NULL;
5d3459af 168ThreadPool *g_mainThreadPool = NULL;
9708eff4 169INT16 g_defaultAgentCacheMode = AGENT_CACHE_OFF;
5039dede 170
f375019e
VK
171/**
172 * Static data
173 */
5039dede
AK
174static CONDITION m_condShutdown = INVALID_CONDITION_HANDLE;
175static THREAD m_thPollManager = INVALID_THREAD_HANDLE;
5039dede 176static THREAD m_thSyncer = INVALID_THREAD_HANDLE;
5039dede
AK
177static int m_nShutdownReason = SHUTDOWN_DEFAULT;
178
179#ifndef _WIN32
180static pthread_t m_signalHandlerThread;
181#endif
182
496390c2
VK
183/**
184 * Sleep for specified number of seconds or until system shutdown arrives
185 * Function will return TRUE if shutdown event occurs
186 *
187 * @param seconds seconds to sleep
188 * @return true if server is shutting down
189 */
400e55c4 190bool NXCORE_EXPORTABLE SleepAndCheckForShutdown(int seconds)
5039dede 191{
496390c2 192 return ConditionWait(m_condShutdown, seconds * 1000);
5039dede
AK
193}
194
496390c2
VK
195/**
196 * Disconnect from database (exportable function for startup module)
197 */
73869331 198void NXCORE_EXPORTABLE ShutdownDB()
5039dede 199{
9bd1bace 200 DBConnectionPoolShutdown();
b8c1ec69 201 DBUnloadDriver(g_dbDriver);
5039dede
AK
202}
203
496390c2
VK
204/**
205 * Check data directory for existence
206 */
35f836fe 207static BOOL CheckDataDir()
5039dede 208{
35f836fe 209 TCHAR szBuffer[MAX_PATH];
5039dede 210
db6a6b45 211 if (_tchdir(g_netxmsdDataDir) == -1)
5039dede 212 {
db6a6b45 213 nxlog_write(MSG_INVALID_DATA_DIR, EVENTLOG_ERROR_TYPE, "s", g_netxmsdDataDir);
5039dede
AK
214 return FALSE;
215 }
216
217#ifdef _WIN32
35f836fe 218#define MKDIR(name) _tmkdir(name)
5039dede 219#else
35f836fe 220#define MKDIR(name) _tmkdir(name, 0700)
5039dede
AK
221#endif
222
5039dede 223 // Create directory for package files if it doesn't exist
db6a6b45 224 _tcscpy(szBuffer, g_netxmsdDataDir);
35f836fe 225 _tcscat(szBuffer, DDIR_PACKAGES);
5039dede
AK
226 if (MKDIR(szBuffer) == -1)
227 if (errno != EEXIST)
228 {
229 nxlog_write(MSG_ERROR_CREATING_DATA_DIR, EVENTLOG_ERROR_TYPE, "s", szBuffer);
230 return FALSE;
231 }
232
4d0c32f3 233 // Create directory for map background images if it doesn't exist
db6a6b45 234 _tcscpy(szBuffer, g_netxmsdDataDir);
35f836fe 235 _tcscat(szBuffer, DDIR_BACKGROUNDS);
4d0c32f3
VK
236 if (MKDIR(szBuffer) == -1)
237 if (errno != EEXIST)
238 {
239 nxlog_write(MSG_ERROR_CREATING_DATA_DIR, EVENTLOG_ERROR_TYPE, "s", szBuffer);
240 return FALSE;
241 }
242
e6b9439a 243 // Create directory for image library is if does't exists
db6a6b45 244 _tcscpy(szBuffer, g_netxmsdDataDir);
e6b9439a
AK
245 _tcscat(szBuffer, DDIR_IMAGES);
246 if (MKDIR(szBuffer) == -1)
247 {
248 if (errno != EEXIST)
249 {
250 nxlog_write(MSG_ERROR_CREATING_DATA_DIR, EVENTLOG_ERROR_TYPE, "s", szBuffer);
251 return FALSE;
252 }
253 }
254
619e5c9b 255 // Create directory for file store if does't exists
db6a6b45 256 _tcscpy(szBuffer, g_netxmsdDataDir);
619e5c9b
VK
257 _tcscat(szBuffer, DDIR_FILES);
258 if (MKDIR(szBuffer) == -1)
57fef75c
VK
259 {
260 if (errno != EEXIST)
261 {
262 nxlog_write(MSG_ERROR_CREATING_DATA_DIR, EVENTLOG_ERROR_TYPE, "s", szBuffer);
263 return FALSE;
264 }
265 }
266
5039dede
AK
267#undef MKDIR
268
269 return TRUE;
270}
271
496390c2
VK
272/**
273 * Load global configuration parameters
274 */
5039dede
AK
275static void LoadGlobalConfig()
276{
35f836fe
VK
277 g_dwDiscoveryPollingInterval = ConfigReadInt(_T("DiscoveryPollingInterval"), 900);
278 g_dwStatusPollingInterval = ConfigReadInt(_T("StatusPollingInterval"), 60);
279 g_dwConfigurationPollingInterval = ConfigReadInt(_T("ConfigurationPollingInterval"), 3600);
805171de 280 g_instancePollingInterval = ConfigReadInt(_T("InstancePollingInterval"), 600);
35f836fe 281 g_dwRoutingTableUpdateInterval = ConfigReadInt(_T("RoutingTableUpdateInterval"), 300);
040c45fa 282 g_dwTopologyPollingInterval = ConfigReadInt(_T("TopologyPollingInterval"), 1800);
35f836fe 283 g_dwConditionPollingInterval = ConfigReadInt(_T("ConditionPollingInterval"), 60);
c59466d2 284 g_slmPollingInterval = ConfigReadInt(_T("SlmPollingInterval"), 60);
90e3031f
VK
285 DCObject::m_defaultPollingInterval = ConfigReadInt(_T("DefaultDCIPollingInterval"), 60);
286 DCObject::m_defaultRetentionTime = ConfigReadInt(_T("DefaultDCIRetentionTime"), 30);
9708eff4 287 g_defaultAgentCacheMode = (INT16)ConfigReadInt(_T("DefaultAgentCacheMode"), AGENT_CACHE_OFF);
e9902466
VK
288 if ((g_defaultAgentCacheMode != AGENT_CACHE_ON) && (g_defaultAgentCacheMode != AGENT_CACHE_OFF))
289 {
290 DbgPrintf(1, _T("Invalid value %d of DefaultAgentCacheMode: reset to %d (OFF)"), g_defaultAgentCacheMode, AGENT_CACHE_OFF);
291 ConfigWriteInt(_T("DefaultAgentCacheMode"), AGENT_CACHE_OFF, true, true, true);
c1f07289 292 g_defaultAgentCacheMode = AGENT_CACHE_OFF;
e9902466 293 }
35f836fe 294 if (ConfigReadInt(_T("DeleteEmptySubnets"), 1))
c8076b19 295 g_flags |= AF_DELETE_EMPTY_SUBNETS;
35f836fe 296 if (ConfigReadInt(_T("EnableSNMPTraps"), 1))
c8076b19
VK
297 g_flags |= AF_ENABLE_SNMP_TRAPD;
298 if (ConfigReadInt(_T("ProcessTrapsFromUnmanagedNodes"), 0))
299 g_flags |= AF_TRAPS_FROM_UNMANAGED_NODES;
35f836fe 300 if (ConfigReadInt(_T("EnableZoning"), 0))
c8076b19 301 g_flags |= AF_ENABLE_ZONING;
549f48b3 302 if (ConfigReadInt(_T("EnableObjectTransactions"), 0))
c8076b19 303 g_flags |= AF_ENABLE_OBJECT_TRANSACTIONS;
35f836fe 304 if (ConfigReadInt(_T("RunNetworkDiscovery"), 0))
c8076b19 305 g_flags |= AF_ENABLE_NETWORK_DISCOVERY;
35f836fe 306 if (ConfigReadInt(_T("ActiveNetworkDiscovery"), 0))
c8076b19 307 g_flags |= AF_ACTIVE_NETWORK_DISCOVERY;
e02953a4 308 if (ConfigReadInt(_T("UseSNMPTrapsForDiscovery"), 0))
c8076b19 309 g_flags |= AF_SNMP_TRAP_DISCOVERY;
35f836fe 310 if (ConfigReadInt(_T("ResolveNodeNames"), 1))
c8076b19 311 g_flags |= AF_RESOLVE_NODE_NAMES;
35f836fe 312 if (ConfigReadInt(_T("SyncNodeNamesWithDNS"), 0))
c8076b19 313 g_flags |= AF_SYNC_NODE_NAMES_WITH_DNS;
35f836fe 314 if (ConfigReadInt(_T("CheckTrustedNodes"), 1))
c8076b19 315 g_flags |= AF_CHECK_TRUSTED_NODES;
3bbc7435 316 if (ConfigReadInt(_T("EnableNXSLContainerFunctions"), 1))
c8076b19 317 g_flags |= AF_ENABLE_NXSL_CONTAINER_FUNCS;
f31c22b3 318 if (ConfigReadInt(_T("UseFQDNForNodeNames"), 1))
c8076b19 319 g_flags |= AF_USE_FQDN_FOR_NODE_NAMES;
098ef635 320 if (ConfigReadInt(_T("ApplyDCIFromTemplateToDisabledDCI"), 1))
c8076b19 321 g_flags |= AF_APPLY_TO_DISABLED_DCI_FROM_TEMPLATE;
4553d424 322 if (ConfigReadInt(_T("ResolveDNSToIPOnStatusPoll"), 0))
385b1f20 323 g_flags |= AF_RESOLVE_IP_FOR_EACH_STATUS_POLL;
8a1519ce
VK
324 if (ConfigReadInt(_T("CaseInsensitiveLoginNames"), 0))
325 g_flags |= AF_CASE_INSENSITIVE_LOGINS;
0eff2ce4
VK
326 if (ConfigReadInt(_T("TrapSourcesInAllZones"), 0))
327 g_flags |= AF_TRAP_SOURCES_IN_ALL_ZONES;
fc958888 328
db6a6b45 329 if (g_netxmsdDataDir[0] == 0)
f31c22b3 330 {
1039d7ee
VK
331 GetNetXMSDirectory(nxDirData, g_netxmsdDataDir);
332 DbgPrintf(1, _T("Data directory set to %s"), g_netxmsdDataDir);
f31c22b3
VK
333 }
334 else
335 {
db6a6b45 336 DbgPrintf(1, _T("Using data directory %s"), g_netxmsdDataDir);
f31c22b3 337 }
d96bd4c7 338
c59466d2
VK
339 g_icmpPingTimeout = ConfigReadInt(_T("IcmpPingTimeout"), 1500);
340 g_icmpPingSize = ConfigReadInt(_T("IcmpPingSize"), 46);
341 g_lockTimeout = ConfigReadInt(_T("LockTimeout"), 60000);
c59466d2
VK
342 g_agentCommandTimeout = ConfigReadInt(_T("AgentCommandTimeout"), 4000);
343 g_thresholdRepeatInterval = ConfigReadInt(_T("ThresholdRepeatInterval"), 0);
344 g_requiredPolls = ConfigReadInt(_T("PollCountForStatusChange"), 1);
296ae03d 345
014fbefc 346 UINT32 snmpTimeout = ConfigReadInt(_T("SNMPRequestTimeout"), 1500);
296ae03d 347 SnmpSetDefaultTimeout(snmpTimeout);
5039dede
AK
348}
349
fdbee7f8
VK
350/**
351 * Initialize cryptografic functions
352 */
73869331 353static BOOL InitCryptografy()
5039dede
AK
354{
355#ifdef _WITH_ENCRYPTION
35f836fe 356 TCHAR szKeyFile[MAX_PATH];
5039dede
AK
357 BOOL bResult = FALSE;
358 int fd, iPolicy;
967893bb 359 UINT32 dwLen;
5039dede
AK
360 BYTE *pBufPos, *pKeyBuffer, hash[SHA1_DIGEST_SIZE];
361
6468147c 362 if (!InitCryptoLib(ConfigReadULong(_T("AllowedCiphers"), 0x7F), DbgPrintf2))
5039dede 363 return FALSE;
ae5880f6 364 DbgPrintf(4, _T("Supported ciphers: %s"), (const TCHAR *)NXCPGetSupportedCiphersAsText());
5039dede 365
958a9397 366 SSL_library_init();
0fd5c0a1 367 SSL_load_error_strings();
958a9397 368
db6a6b45 369 _tcscpy(szKeyFile, g_netxmsdDataDir);
35f836fe
VK
370 _tcscat(szKeyFile, DFILE_KEYS);
371 fd = _topen(szKeyFile, O_RDONLY | O_BINARY);
5039dede
AK
372 g_pServerKey = LoadRSAKeys(szKeyFile);
373 if (g_pServerKey == NULL)
374 {
35f836fe 375 DbgPrintf(1, _T("Generating RSA key pair..."));
5039dede
AK
376 g_pServerKey = RSA_generate_key(NETXMS_RSA_KEYLEN, 17, NULL, 0);
377 if (g_pServerKey != NULL)
378 {
35f836fe 379 fd = _topen(szKeyFile, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, 0600);
5039dede
AK
380 if (fd != -1)
381 {
382 dwLen = i2d_RSAPublicKey(g_pServerKey, NULL);
383 dwLen += i2d_RSAPrivateKey(g_pServerKey, NULL);
384 pKeyBuffer = (BYTE *)malloc(dwLen);
385
386 pBufPos = pKeyBuffer;
387 i2d_RSAPublicKey(g_pServerKey, &pBufPos);
388 i2d_RSAPrivateKey(g_pServerKey, &pBufPos);
967893bb 389 write(fd, &dwLen, sizeof(UINT32));
5039dede
AK
390 write(fd, pKeyBuffer, dwLen);
391
392 CalculateSHA1Hash(pKeyBuffer, dwLen, hash);
393 write(fd, hash, SHA1_DIGEST_SIZE);
394
395 close(fd);
396 free(pKeyBuffer);
397 bResult = TRUE;
398 }
c578be51
AK
399 else
400 {
401 DbgPrintf(0, _T("Failed to open %s for writing"), szKeyFile);
402 }
5039dede 403 }
c578be51
AK
404 else
405 {
406 DbgPrintf(0, _T("Failed to generate RSA key"));
407 }
5039dede
AK
408 }
409 else
410 {
411 bResult = TRUE;
412 }
413
35f836fe 414 iPolicy = ConfigReadInt(_T("DefaultEncryptionPolicy"), 1);
5039dede
AK
415 if ((iPolicy < 0) || (iPolicy > 3))
416 iPolicy = 1;
417 SetAgentDEP(iPolicy);
418
419 return bResult;
420#else
421 return TRUE;
422#endif
423}
424
496390c2
VK
425/**
426 * Check if process with given PID exists and is a NetXMS server process
427 */
967893bb 428static BOOL IsNetxmsdProcess(UINT32 dwPID)
5039dede
AK
429{
430#ifdef _WIN32
431 HANDLE hProcess;
432 TCHAR szExtModule[MAX_PATH], szIntModule[MAX_PATH];
433 BOOL bRet = FALSE;
434
435 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwPID);
436 if (hProcess != NULL)
437 {
438 if ((GetModuleBaseName(hProcess, NULL, szExtModule, MAX_PATH) > 0) &&
439 (GetModuleBaseName(GetCurrentProcess(), NULL, szIntModule, MAX_PATH) > 0))
440 {
441 bRet = !_tcsicmp(szExtModule, szIntModule);
442 }
443 else
444 {
445 // Cannot read process name, for safety assume that it's a server process
446 bRet = TRUE;
447 }
448 CloseHandle(hProcess);
449 }
450 return bRet;
451#else
452 return (kill((pid_t)dwPID, 0) != -1);
453#endif
454}
455
496390c2
VK
456/**
457 * Database event handler
458 */
526ae8b8 459static void DBEventHandler(DWORD dwEvent, const WCHAR *pszArg1, const WCHAR *pszArg2, bool connLost, void *userArg)
5039dede 460{
c8076b19 461 if (!(g_flags & AF_SERVER_INITIALIZED))
5039dede
AK
462 return; // Don't try to do anything if server is not ready yet
463
464 switch(dwEvent)
465 {
466 case DBEVENT_CONNECTION_LOST:
467 PostEvent(EVENT_DB_CONNECTION_LOST, g_dwMgmtNode, NULL);
c8076b19 468 g_flags |= AF_DB_CONNECTION_LOST;
5039dede
AK
469 NotifyClientSessions(NX_NOTIFY_DBCONN_STATUS, FALSE);
470 break;
471 case DBEVENT_CONNECTION_RESTORED:
472 PostEvent(EVENT_DB_CONNECTION_RESTORED, g_dwMgmtNode, NULL);
c8076b19 473 g_flags &= ~AF_DB_CONNECTION_LOST;
5039dede
AK
474 NotifyClientSessions(NX_NOTIFY_DBCONN_STATUS, TRUE);
475 break;
4d0c32f3 476 case DBEVENT_QUERY_FAILED:
526ae8b8 477 PostEvent(EVENT_DB_QUERY_FAILED, g_dwMgmtNode, "uud", pszArg1, pszArg2, connLost ? 1 : 0);
4d0c32f3 478 break;
5039dede
AK
479 default:
480 break;
481 }
482}
483
496390c2
VK
484/**
485 * Send console message to session with open console
486 */
f669df41
VK
487static void SendConsoleMessage(ClientSession *session, void *arg)
488{
489 if (session->isConsoleOpen())
490 {
b368969c 491 NXCPMessage msg;
f669df41 492
b368969c
VK
493 msg.setCode(CMD_ADM_MESSAGE);
494 msg.setField(VID_MESSAGE, (TCHAR *)arg);
d3a7cf4c 495 session->postMessage(&msg);
f669df41
VK
496 }
497}
498
d6217efa
VK
499/**
500 * Console writer
501 */
f669df41
VK
502static void LogConsoleWriter(const TCHAR *format, ...)
503{
504 TCHAR buffer[8192];
505 va_list args;
506
507 va_start(args, format);
508 _vsntprintf(buffer, 8192, format, args);
509 buffer[8191] = 0;
510 va_end(args);
511
512 WriteToTerminal(buffer);
513
514 EnumerateClientSessions(SendConsoleMessage, buffer);
515}
516
b6aff59d
VK
517/**
518 * Oracle session init callback
519 */
520static void OracleSessionInitCallback(DB_HANDLE hdb)
521{
522 DBQuery(hdb, _T("ALTER SESSION SET DDL_LOCK_TIMEOUT = 60"));
523}
524
fdbee7f8
VK
525/**
526 * Server initialization
527 */
bc980b27 528BOOL NXCORE_EXPORTABLE Initialize()
5039dede
AK
529{
530 int i, iDBVersion;
35f836fe 531 TCHAR szInfo[256];
5039dede 532
c59466d2
VK
533 g_serverStartTime = time(NULL);
534 srand((unsigned int)g_serverStartTime);
4f8998ca 535
db6a6b45 536 if (g_netxmsdLibDir[0] == 0)
99ba93d1 537 {
a97f02e1
VK
538 GetNetXMSDirectory(nxDirLib, g_netxmsdLibDir);
539 DbgPrintf(1, _T("Lib directory set to %s"), g_netxmsdLibDir);
99ba93d1
VK
540 }
541
c8076b19 542 if (!(g_flags & AF_USE_SYSLOG))
4f8998ca
VK
543 {
544 if (!nxlog_set_rotation_policy((int)g_dwLogRotationMode, (int)g_dwMaxLogSize, (int)g_dwLogHistorySize, g_szDailyLogFileSuffix))
c8076b19 545 if (!(g_flags & AF_DAEMON))
4f8998ca
VK
546 _tprintf(_T("WARNING: cannot set log rotation policy; using default values\n"));
547 }
c8076b19 548 if (!nxlog_open((g_flags & AF_USE_SYSLOG) ? NETXMSD_SYSLOG_NAME : g_szLogFile,
2589cc10 549 ((g_flags & AF_USE_SYSLOG) ? NXLOG_USE_SYSLOG : 0) |
550 ((g_flags & AF_BACKGROUND_LOG_WRITER) ? NXLOG_BACKGROUND_WRITER : 0) |
4e0e77e6 551 ((g_flags & AF_DAEMON) ? 0 : NXLOG_PRINT_TO_STDOUT),
9d381279 552 _T("LIBNXSRV.DLL"),
5039dede 553#ifdef _WIN32
9d381279 554 0, NULL))
5039dede 555#else
9d381279 556 g_dwNumMessages, g_szMessages))
5039dede 557#endif
9d381279
VK
558 {
559 _ftprintf(stderr, _T("FATAL ERROR: Cannot open log file\n"));
560 return FALSE;
561 }
f669df41 562 nxlog_set_console_writer(LogConsoleWriter);
5039dede
AK
563
564 // Set code page
565#ifndef _WIN32
566 if (SetDefaultCodepage(g_szCodePage))
567 {
f5797a09 568 DbgPrintf(1, _T("Code page set to %hs"), g_szCodePage);
5039dede
AK
569 }
570 else
571 {
f375019e 572 nxlog_write(MSG_CODEPAGE_ERROR, EVENTLOG_WARNING_TYPE, "m", g_szCodePage);
5039dede
AK
573 }
574#endif
575
73869331
VK
576 // Set process affinity mask
577 if (g_processAffinityMask != DEFAULT_AFFINITY_MASK)
578 {
579#ifdef _WIN32
580 if (SetProcessAffinityMask(GetCurrentProcess(), g_processAffinityMask))
581 DbgPrintf(1, _T("Process affinity mask set to 0x%08X"), g_processAffinityMask);
582#else
583 nxlog_write(MSG_SET_PROCESS_AFFINITY_NOT_SUPPORTED, EVENTLOG_WARNING_TYPE, NULL);
584#endif
585 }
586
5039dede
AK
587#ifdef _WIN32
588 WSADATA wsaData;
1ddf3f0c
VK
589 int wrc = WSAStartup(MAKEWORD(2, 2), &wsaData);
590 if (wrc != 0)
591 {
592 nxlog_write(MSG_WSASTARTUP_FAILED, EVENTLOG_ERROR_TYPE, "e", wrc);
593 return FALSE;
594 }
5039dede
AK
595#endif
596
597 InitLocalNetInfo();
296ae03d 598 SnmpSetMessageIds(MSG_OID_PARSE_ERROR, MSG_SNMP_UNKNOWN_TYPE, MSG_SNMP_GET_ERROR);
5039dede
AK
599
600 // Create queue for delayed SQL queries
76fcb995
VK
601 g_dbWriterQueue = new Queue(256, 64);
602 g_dciDataWriterQueue = new Queue(1024, 1024);
603 g_dciRawDataWriterQueue = new Queue(1024, 1024);
5039dede
AK
604
605 // Initialize database driver and connect to database
9d88cdc9 606 DBSetDebugPrintCallback(DbgPrintf2);
c8076b19 607 if (!DBInit(MSG_OTHER, (g_flags & AF_LOG_SQL_ERRORS) ? MSG_SQL_ERROR : 0))
b8c1ec69 608 return FALSE;
ed950274 609 g_dbDriver = DBLoadDriver(g_szDbDriver, g_szDbDrvParams, (g_debugLevel >= 9), DBEventHandler, NULL);
b8c1ec69 610 if (g_dbDriver == NULL)
5039dede
AK
611 return FALSE;
612
613 // Connect to database
9bd1bace 614 DB_HANDLE hdbBootstrap = NULL;
465b3f2d 615 TCHAR errorText[DBDRV_MAX_ERROR_TEXT];
5039dede
AK
616 for(i = 0; ; i++)
617 {
9bd1bace
VK
618 hdbBootstrap = DBConnect(g_dbDriver, g_szDbServer, g_szDbName, g_szDbLogin, g_szDbPassword, g_szDbSchema, errorText);
619 if ((hdbBootstrap != NULL) || (i == 5))
5039dede
AK
620 break;
621 ThreadSleep(5);
622 }
9bd1bace 623 if (hdbBootstrap == NULL)
5039dede 624 {
465b3f2d 625 nxlog_write(MSG_DB_CONNFAIL, EVENTLOG_ERROR_TYPE, "s", errorText);
5039dede
AK
626 return FALSE;
627 }
35f836fe 628 DbgPrintf(1, _T("Successfully connected to database %s@%s"), g_szDbName, g_szDbServer);
5039dede
AK
629
630 // Check database version
9bd1bace 631 iDBVersion = DBGetSchemaVersion(hdbBootstrap);
5039dede
AK
632 if (iDBVersion != DB_FORMAT_VERSION)
633 {
634 nxlog_write(MSG_WRONG_DB_VERSION, EVENTLOG_ERROR_TYPE, "dd", iDBVersion, DB_FORMAT_VERSION);
9bd1bace 635 DBDisconnect(hdbBootstrap);
5039dede
AK
636 return FALSE;
637 }
638
b6aff59d 639 // Read database syntax
9bd1bace 640 g_dbSyntax = DBGetSyntax(hdbBootstrap);
b6aff59d
VK
641 if (g_dbSyntax == DB_SYNTAX_ORACLE)
642 {
643 DBSetSessionInitCallback(OracleSessionInitCallback);
644 }
645
9bd1bace
VK
646 int baseSize = ConfigReadIntEx(hdbBootstrap, _T("DBConnectionPoolBaseSize"), 10);
647 int maxSize = ConfigReadIntEx(hdbBootstrap, _T("DBConnectionPoolMaxSize"), 30);
648 int cooldownTime = ConfigReadIntEx(hdbBootstrap, _T("DBConnectionPoolCooldownTime"), 300);
649 int ttl = ConfigReadIntEx(hdbBootstrap, _T("DBConnectionPoolMaxLifetime"), 14400);
650
651 DBDisconnect(hdbBootstrap);
652
653 if (!DBConnectionPoolStartup(g_dbDriver, g_szDbServer, g_szDbName, g_szDbLogin, g_szDbPassword, g_szDbSchema, baseSize, maxSize, cooldownTime, ttl))
654 {
655 nxlog_write(MSG_DBCONNPOOL_INIT_FAILED, EVENTLOG_ERROR_TYPE, NULL);
656 return FALSE;
657 }
f727d089 658
58f1f627
VK
659 UINT32 lrt = ConfigReadULong(_T("LongRunningQueryThreshold"), 0);
660 if (lrt != 0)
661 DBSetLongRunningThreshold(lrt);
662
5039dede 663 // Read server ID
e9902466 664 MetaDataReadStr(_T("ServerID"), szInfo, 256, _T(""));
5039dede
AK
665 StrStrip(szInfo);
666 if (szInfo[0] != 0)
667 {
e9902466 668 g_serverId = _tcstoull(szInfo, NULL, 16);
5039dede
AK
669 }
670 else
671 {
672 // Generate new ID
e9902466
VK
673 g_serverId = ((UINT64)time(NULL) << 31) | (UINT64)((UINT32)rand() & 0x7FFFFFFF);
674 _sntprintf(szInfo, 256, UINT64X_FMT(_T("016")), g_serverId);
675 MetaDataWriteStr(_T("ServerID"), szInfo);
5039dede 676 }
e9902466 677 DbgPrintf(1, _T("Server ID ") UINT64X_FMT(_T("016")), g_serverId);
5039dede
AK
678
679 // Initialize locks
680retry_db_lock:
c30c0c0f
VK
681 InetAddress addr;
682 if (!InitLocks(&addr, szInfo))
5039dede 683 {
c30c0c0f 684 if (!addr.isValid()) // Some SQL problems
5039dede
AK
685 {
686 nxlog_write(MSG_INIT_LOCKS_FAILED, EVENTLOG_ERROR_TYPE, NULL);
687 }
688 else // Database already locked by another server instance
689 {
690 // Check for lock from crashed/terminated local process
c30c0c0f 691 if (GetLocalIpAddr().equals(addr))
5039dede 692 {
967893bb 693 UINT32 dwPID;
5039dede 694
35f836fe 695 dwPID = ConfigReadULong(_T("DBLockPID"), 0);
5039dede
AK
696 if (!IsNetxmsdProcess(dwPID) || (dwPID == GetCurrentProcessId()))
697 {
698 UnlockDB();
699 nxlog_write(MSG_DB_LOCK_REMOVED, EVENTLOG_INFORMATION_TYPE, NULL);
700 goto retry_db_lock;
701 }
702 }
c30c0c0f 703 nxlog_write(MSG_DB_LOCKED, EVENTLOG_ERROR_TYPE, "As", &addr, szInfo);
5039dede
AK
704 }
705 return FALSE;
706 }
c8076b19 707 g_flags |= AF_DB_LOCKED;
5039dede
AK
708
709 // Load global configuration parameters
710 LoadGlobalConfig();
958a9397 711 CASReadSettings();
35f836fe 712 DbgPrintf(1, _T("Global configuration loaded"));
5039dede
AK
713
714 // Check data directory
715 if (!CheckDataDir())
716 return FALSE;
717
718 // Initialize cryptografy
719 if (!InitCryptografy())
720 {
721 nxlog_write(MSG_INIT_CRYPTO_FAILED, EVENTLOG_ERROR_TYPE, NULL);
722 return FALSE;
723 }
724
725 // Initialize certificate store and CA
726 InitCertificates();
727
5039dede
AK
728 // Create synchronization stuff
729 m_condShutdown = ConditionCreate(TRUE);
730
5d3459af
VK
731 // Create thread pools
732 DbgPrintf(2, _T("Creating thread pools"));
733 ThreadPoolSetDebugCallback(DbgPrintf2);
734 g_mainThreadPool = ThreadPoolCreate(8, 256, _T("MAIN"));
1693f955 735 g_agentConnectionThreadPool = ThreadPoolCreate(4, 256, _T("AGENT"));
5d3459af 736
5039dede
AK
737 // Setup unique identifiers table
738 if (!InitIdTable())
739 return FALSE;
35f836fe 740 DbgPrintf(2, _T("ID table created"));
5039dede 741
24dc5346 742 // Update status for unfinished jobs in job history
9bd1bace
VK
743 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
744 DBQuery(hdb, _T("UPDATE job_history SET status=4,failure_message='Aborted due to server shutdown or crash' WHERE status NOT IN (3,4,5)"));
745 DBConnectionPoolReleaseConnection(hdb);
24dc5346 746
5039dede
AK
747 // Load and compile scripts
748 LoadScripts();
749
f7e4c50e
VK
750 // Initialize watchdog
751 WatchdogInit();
752
53d2de79 753 // Load modules
890478d8
VK
754 if (!LoadNetXMSModules())
755 return FALSE; // Mandatory module not loaded
53d2de79 756
5039dede
AK
757 // Initialize mailer and SMS sender
758 InitMailer();
759 InitSMSSender();
760
761 // Load users from database
ab185583 762 InitUsers();
5039dede
AK
763 if (!LoadUsers())
764 {
765 nxlog_write(MSG_ERROR_LOADING_USERS, EVENTLOG_ERROR_TYPE, NULL);
766 return FALSE;
767 }
35f836fe 768 DbgPrintf(2, _T("User accounts loaded"));
5039dede
AK
769
770 // Initialize audit
771 InitAuditLog();
772
da84c57a
VK
773 // Initialize event handling subsystem
774 if (!InitEventSubsystem())
775 return FALSE;
776
777 // Initialize alarms
778 if (!InitAlarmManager())
779 return FALSE;
780
5039dede 781 // Initialize objects infrastructure and load objects from database
9796ce45 782 LoadNetworkDeviceDrivers();
5039dede
AK
783 ObjectsInit();
784 if (!LoadObjects())
785 return FALSE;
35f836fe 786 DbgPrintf(1, _T("Objects loaded and initialized"));
d9177dd1 787
5039dede
AK
788 // Initialize situations
789 if (!SituationsInit())
790 return FALSE;
35f836fe 791 DbgPrintf(1, _T("Situations loaded and initialized"));
5039dede
AK
792
793 // Initialize and load event actions
794 if (!InitActions())
795 {
796 nxlog_write(MSG_ACTION_INIT_ERROR, EVENTLOG_ERROR_TYPE, NULL);
797 return FALSE;
798 }
799
6fad8870
VK
800 // Initialize helpdesk link
801 SetHDLinkEntryPoints(ResolveAlarmByHDRef, TerminateAlarmByHDRef);
802 LoadHelpDeskLink();
803
5039dede 804 // Initialize data collection subsystem
8fd95c92 805 LoadPerfDataStorageDrivers();
5039dede
AK
806 if (!InitDataCollector())
807 return FALSE;
808
e05b1945 809 InitLogAccess();
d77baddd 810 FileUploadJob::init();
fdbee7f8 811 InitMappingTables();
e05b1945 812
5039dede
AK
813 // Check if management node object presented in database
814 CheckForMgmtNode();
815 if (g_dwMgmtNode == 0)
816 {
817 nxlog_write(MSG_CANNOT_FIND_SELF, EVENTLOG_ERROR_TYPE, NULL);
818 return FALSE;
819 }
820
821 // Start threads
822 ThreadCreate(WatchdogThread, 0, NULL);
823 ThreadCreate(NodePoller, 0, NULL);
3929b1ca 824 ThreadCreate(JobManagerThread, 0, NULL);
5039dede 825 m_thSyncer = ThreadCreateEx(Syncer, 0, NULL);
5039dede
AK
826 m_thPollManager = ThreadCreateEx(PollManager, 0, NULL);
827
a64c346b
VK
828 StartHouseKeeper();
829
5039dede
AK
830 // Start event processor
831 ThreadCreate(EventProcessor, 0, NULL);
832
833 // Start SNMP trapper
834 InitTraps();
35f836fe 835 if (ConfigReadInt(_T("EnableSNMPTraps"), 1))
5039dede
AK
836 ThreadCreate(SNMPTrapReceiver, 0, NULL);
837
838 // Start built-in syslog daemon
35f836fe 839 if (ConfigReadInt(_T("EnableSyslogDaemon"), 0))
af4a09df 840 StartSyslogServer();
5039dede 841
35f836fe 842 // Start database _T("lazy") write thread
5039dede
AK
843 StartDBWriter();
844
845 // Start local administartive interface listener if required
35f836fe 846 if (ConfigReadInt(_T("EnableAdminInterface"), 1))
5039dede
AK
847 ThreadCreate(LocalAdminListener, 0, NULL);
848
5039dede
AK
849 // Start beacon host poller
850 ThreadCreate(BeaconPoller, 0, NULL);
851
852 // Start inter-server communication listener
35f836fe 853 if (ConfigReadInt(_T("EnableISCListener"), 0))
5039dede
AK
854 ThreadCreate(ISCListener, 0, NULL);
855
d75003e1
AK
856 // Start reporting server connector
857 if (ConfigReadInt(_T("EnableReportingServer"), 0))
858 ThreadCreate(ReportingServerConnector, 0, NULL);
859
d9177dd1 860 //Start ldap synchronization
861 if (ConfigReadInt(_T("LdapSyncInterval"), 0))
862 ThreadCreate(SyncLDAPUsers, 0, NULL);
863
ec13a467
VK
864 RegisterSchedulerTaskHandler(_T("Execute.Script"), ExecuteScheduledScript, SYSTEM_ACCESS_SCHEDULE_SCRIPT);
865 RegisterSchedulerTaskHandler(_T("Maintenance.Enter"), MaintenanceModeEnter, SYSTEM_ACCESS_SCHEDULE_MAINTENANCE);
866 RegisterSchedulerTaskHandler(_T("Maintenance.Leave"), MaintenanceModeLeave, SYSTEM_ACCESS_SCHEDULE_MAINTENANCE);
0a145c10 867 InitializeTaskScheduler();
868
5039dede 869 // Allow clients to connect
36e44abe 870 InitClientListeners();
5039dede 871 ThreadCreate(ClientListener, 0, NULL);
36e44abe
VK
872#ifdef WITH_IPV6
873 ThreadCreate(ClientListenerIPv6, 0, NULL);
874#endif
5039dede 875
534e1b83
VK
876 // Allow mobile devices to connect
877 InitMobileDeviceListeners();
878 ThreadCreate(MobileDeviceListener, 0, NULL);
879#ifdef WITH_IPV6
880 ThreadCreate(MobileDeviceListenerIPv6, 0, NULL);
881#endif
882
86457857
AK
883 // Start uptime calculator for SLM
884 ThreadCreate(UptimeCalculator, 0, NULL);
885
db6a6b45 886 DbgPrintf(2, _T("LIBDIR: %s"), g_netxmsdLibDir);
712dd47d 887
1b42a673 888 // Call startup functions for the modules
a0efa7b5 889 CALL_ALL_MODULES(pfServerStarted, ());
53d2de79 890
058bf6fc 891#if XMPP_SUPPORTED
244c65ef
VK
892 if (ConfigReadInt(_T("EnableXMPPConnector"), 1))
893 {
098ef635 894 StartXMPPConnector();
244c65ef 895 }
058bf6fc 896#endif
244c65ef 897
9df36f62
AK
898#if WITH_ZMQ
899 StartZMQConnector();
900#endif
901
c8076b19 902 g_flags |= AF_SERVER_INITIALIZED;
35f836fe 903 DbgPrintf(1, _T("Server initialization completed"));
5039dede
AK
904 return TRUE;
905}
906
371d9c60
VK
907/**
908 * Server shutdown
909 */
035a4d73 910void NXCORE_EXPORTABLE Shutdown()
5039dede 911{
5039dede
AK
912 // Notify clients
913 NotifyClientSessions(NX_NOTIFY_SHUTDOWN, 0);
914
915 nxlog_write(MSG_SERVER_STOPPED, EVENTLOG_INFORMATION_TYPE, NULL);
c8076b19 916 g_flags |= AF_SHUTDOWN; // Set shutdown flag
5039dede
AK
917 ConditionSet(m_condShutdown);
918
0a145c10 919 CloseTaskScheduler();
920
d140955e 921 // Stop DCI cache loading thread
19dbc8ef 922 g_dciCacheLoaderQueue.setShutdownMode();
d140955e 923
058bf6fc 924#if XMPP_SUPPORTED
244c65ef 925 StopXMPPConnector();
058bf6fc 926#endif
244c65ef 927
9df36f62
AK
928#if WITH_ZMQ
929 StopZMQConnector();
930#endif
931
19dbc8ef
VK
932 g_pEventQueue->clear();
933 g_pEventQueue->put(INVALID_POINTER_VALUE);
5039dede
AK
934
935 ShutdownMailer();
936 ShutdownSMSSender();
937
938 ThreadSleep(1); // Give other threads a chance to terminate in a safe way
35f836fe 939 DbgPrintf(2, _T("All threads was notified, continue with shutdown"));
5039dede 940
af4a09df 941 StopSyslogServer();
a64c346b 942 StopHouseKeeper();
af4a09df 943
5039dede 944 // Wait for critical threads
5039dede
AK
945 ThreadJoin(m_thPollManager);
946 ThreadJoin(m_thSyncer);
5039dede 947
a0efa7b5
VK
948 // Call shutdown functions for the modules
949 // CALL_ALL_MODULES cannot be used here because it checks for shutdown flag
950 for(UINT32 i = 0; i < g_dwNumModules; i++)
951 {
952 if (g_pModuleList[i].pfShutdown != NULL)
953 g_pModuleList[i].pfShutdown();
954 }
955
9bd1bace
VK
956 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
957 SaveObjects(hdb);
35f836fe 958 DbgPrintf(2, _T("All objects saved to database"));
9bd1bace 959 SaveUsers(hdb);
35f836fe 960 DbgPrintf(2, _T("All users saved to database"));
9bd1bace
VK
961 DBConnectionPoolReleaseConnection(hdb);
962
5039dede 963 StopDBWriter();
35f836fe 964 DbgPrintf(1, _T("Database writer stopped"));
5039dede 965
ab185583
VK
966 CleanupUsers();
967
5039dede
AK
968 // Remove database lock
969 UnlockDB();
970
7a7dfb3e 971 DBConnectionPoolShutdown();
b8c1ec69 972 DBUnloadDriver(g_dbDriver);
35f836fe 973 DbgPrintf(1, _T("Database driver unloaded"));
5039dede
AK
974
975 CleanupActions();
976 ShutdownEventSubsystem();
da84c57a 977 ShutdownAlarmManager();
35f836fe 978 DbgPrintf(1, _T("Event processing stopped"));
5039dede 979
1693f955 980 ThreadPoolDestroy(g_agentConnectionThreadPool);
5d3459af 981 ThreadPoolDestroy(g_mainThreadPool);
d87ddcc2 982 MsgWaitQueue::shutdown();
5d3459af 983
5039dede
AK
984 delete g_pScriptLibrary;
985
bc9263d1 986 DbgPrintf(1, _T("Server shutdown complete"));
5039dede
AK
987 nxlog_close();
988
989 // Remove PID file
990#ifndef _WIN32
dda7c270 991 _tremove(g_szPIDFile);
5039dede
AK
992#endif
993
994 // Terminate process
995#ifdef _WIN32
c8076b19 996 if (!(g_flags & AF_DAEMON))
5039dede
AK
997 ExitProcess(0);
998#else
999 exit(0);
1000#endif
1001}
1002
371d9c60
VK
1003/**
1004 * Fast server shutdown - normally called only by Windows service on system shutdown
1005 */
f669df41 1006void NXCORE_EXPORTABLE FastShutdown()
5039dede 1007{
bc9263d1
VK
1008 DbgPrintf(1, _T("Using fast shutdown procedure"));
1009
c8076b19 1010 g_flags |= AF_SHUTDOWN; // Set shutdown flag
5039dede
AK
1011 ConditionSet(m_condShutdown);
1012
9bd1bace
VK
1013 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
1014 SaveObjects(hdb);
35f836fe 1015 DbgPrintf(2, _T("All objects saved to database"));
9bd1bace 1016 SaveUsers(hdb);
35f836fe 1017 DbgPrintf(2, _T("All users saved to database"));
9bd1bace 1018 DBConnectionPoolReleaseConnection(hdb);
5039dede 1019
9bd1bace 1020 // Remove database lock first, because we have a chance to lose DB connection
5039dede
AK
1021 UnlockDB();
1022
1023 // Stop database writers
1024 StopDBWriter();
35f836fe 1025 DbgPrintf(1, _T("Database writer stopped"));
5039dede 1026
bc9263d1 1027 DbgPrintf(1, _T("Server shutdown complete"));
5039dede
AK
1028 nxlog_close();
1029}
1030
fdbee7f8
VK
1031/**
1032 * Compare given string to command template with abbreviation possibility
1033 */
ca0e18d2 1034static bool IsCommand(const TCHAR *cmdTemplate, TCHAR *pszString, int iMinChars)
5039dede
AK
1035{
1036 int i;
1037
1038 // Convert given string to uppercase
35f836fe 1039 _tcsupr(pszString);
5039dede
AK
1040
1041 for(i = 0; pszString[i] != 0; i++)
ca0e18d2 1042 if (pszString[i] != cmdTemplate[i])
fdbee7f8 1043 return false;
5039dede 1044 if (i < iMinChars)
fdbee7f8
VK
1045 return false;
1046 return true;
5039dede
AK
1047}
1048
fdbee7f8 1049/**
c75e9ee4 1050 * Dump index callback (by IP address)
fdbee7f8 1051 */
c30c0c0f 1052static void DumpIndexCallbackByInetAddr(const InetAddress& addr, NetObj *object, void *data)
5039dede 1053{
c75e9ee4 1054 TCHAR buffer[64];
c30c0c0f 1055 ConsolePrintf((CONSOLE_CTX)data, _T("%-40s %p %s [%d]\n"), addr.toString(buffer), object, object->getName(), (int)object->getId());
c75e9ee4 1056}
5039dede 1057
c75e9ee4
VK
1058/**
1059 * Dump index (by IP address)
1060 */
1061static void DumpIndex(CONSOLE_CTX pCtx, InetAddressIndex *index)
d5e19c61 1062{
c75e9ee4 1063 index->forEach(DumpIndexCallbackByInetAddr, pCtx);
d5e19c61 1064}
5039dede 1065
c75e9ee4
VK
1066/**
1067 * Dump index callback (by ID)
1068 */
1069static void DumpIndexCallbackById(NetObj *object, void *data)
1070{
1071 ConsolePrintf((CONSOLE_CTX)data, _T("%08X %p %s\n"), object->getId(), object, object->getName());
1072}
1073
1074/**
1075 * Dump index (by ID)
1076 */
1077static void DumpIndex(CONSOLE_CTX pCtx, ObjectIndex *index)
d5e19c61 1078{
c75e9ee4 1079 index->forEach(DumpIndexCallbackById, pCtx);
5039dede
AK
1080}
1081
e323047c
VK
1082/**
1083 * Process command entered from command line in standalone mode
1084 * Return TRUE if command was _T("down")
1085 */
35f836fe 1086int ProcessConsoleCommand(const TCHAR *pszCmdLine, CONSOLE_CTX pCtx)
5039dede 1087{
35f836fe 1088 const TCHAR *pArg;
48c0079d 1089 TCHAR szBuffer[256], *eptr;
5039dede
AK
1090 int nExitCode = CMD_EXIT_CONTINUE;
1091
1092 // Get command
1093 pArg = ExtractWord(pszCmdLine, szBuffer);
1094
35f836fe 1095 if (IsCommand(_T("DEBUG"), szBuffer, 2))
5039dede
AK
1096 {
1097 // Get argument
1098 pArg = ExtractWord(pArg, szBuffer);
48c0079d
VK
1099 int level = (int)_tcstol(szBuffer, &eptr, 0);
1100 if ((*eptr == 0) && (level >= 0) && (level <= 9))
5039dede 1101 {
967893bb 1102 g_debugLevel = (UINT32)level;
48c0079d 1103 ConsolePrintf(pCtx, (level == 0) ? _T("Debug mode turned off\n") : _T("Debug level set to %d\n"), level);
5039dede 1104 }
35f836fe 1105 else if (IsCommand(_T("OFF"), szBuffer, 2))
5039dede 1106 {
ed950274 1107 g_debugLevel = 0;
532990d2 1108 ConsoleWrite(pCtx, _T("Debug mode turned off\n"));
5039dede
AK
1109 }
1110 else
1111 {
1112 if (szBuffer[0] == 0)
532990d2 1113 ConsoleWrite(pCtx, _T("ERROR: Missing argument\n\n"));
5039dede 1114 else
532990d2 1115 ConsoleWrite(pCtx, _T("ERROR: Invalid debug level\n\n"));
5039dede
AK
1116 }
1117 }
35f836fe 1118 else if (IsCommand(_T("DOWN"), szBuffer, 4))
5039dede 1119 {
532990d2 1120 ConsoleWrite(pCtx, _T("Proceeding with server shutdown...\n"));
5039dede
AK
1121 nExitCode = CMD_EXIT_SHUTDOWN;
1122 }
35f836fe 1123 else if (IsCommand(_T("DUMP"), szBuffer, 4))
5039dede
AK
1124 {
1125 DumpProcess(pCtx);
1126 }
206e268e
VK
1127 else if (IsCommand(_T("GET"), szBuffer, 3))
1128 {
1129 pArg = ExtractWord(pArg, szBuffer);
1130 if (szBuffer[0] != 0)
1131 {
2589cc10 1132 TCHAR value[MAX_CONFIG_VALUE];
1133 ConfigReadStr(szBuffer, value, MAX_CONFIG_VALUE, _T(""));
206e268e
VK
1134 ConsolePrintf(pCtx, _T("%s = %s\n"), szBuffer, value);
1135 }
1136 else
1137 {
532990d2 1138 ConsoleWrite(pCtx, _T("Variable name missing\n"));
206e268e
VK
1139 }
1140 }
a64c346b
VK
1141 else if (IsCommand(_T("HKRUN"), szBuffer, 2))
1142 {
1143 ConsoleWrite(pCtx, _T("Starting housekeeper\n"));
1144 RunHouseKeeper();
1145 }
35f836fe 1146 else if (IsCommand(_T("RAISE"), szBuffer, 5))
5039dede
AK
1147 {
1148 // Get argument
1149 pArg = ExtractWord(pArg, szBuffer);
1150
35f836fe 1151 if (IsCommand(_T("ACCESS"), szBuffer, 6))
5039dede 1152 {
532990d2 1153 ConsoleWrite(pCtx, _T("Raising exception...\n"));
5039dede
AK
1154 char *p = NULL;
1155 *p = 0;
1156 }
35f836fe 1157 else if (IsCommand(_T("BREAKPOINT"), szBuffer, 5))
5039dede
AK
1158 {
1159#ifdef _WIN32
532990d2 1160 ConsoleWrite(pCtx, _T("Raising exception...\n"));
5039dede
AK
1161 RaiseException(EXCEPTION_BREAKPOINT, 0, 0, NULL);
1162#else
532990d2 1163 ConsoleWrite(pCtx, _T("ERROR: Not supported on current platform\n"));
5039dede
AK
1164#endif
1165 }
1166 else
1167 {
532990d2 1168 ConsoleWrite(pCtx, _T("Invalid exception name; possible names are:\nACCESS BREAKPOINT\n"));
5039dede
AK
1169 }
1170 }
35f836fe 1171 else if (IsCommand(_T("EXIT"), szBuffer, 4))
5039dede 1172 {
f669df41 1173 if ((pCtx->hSocket != -1) || (pCtx->session != NULL))
5039dede 1174 {
532990d2 1175 ConsoleWrite(pCtx, _T("Closing session...\n"));
5039dede
AK
1176 nExitCode = CMD_EXIT_CLOSE_SESSION;
1177 }
1178 else
1179 {
532990d2 1180 ConsoleWrite(pCtx, _T("Cannot exit from local server console\n"));
5039dede
AK
1181 }
1182 }
5d9a9c84
VK
1183 else if (IsCommand(_T("KILL"), szBuffer, 4))
1184 {
1185 pArg = ExtractWord(pArg, szBuffer);
1186 if (szBuffer[0] != 0)
1187 {
1188 int id = _tcstol(szBuffer, &eptr, 10);
1189 if (*eptr == 0)
1190 {
1191 if (KillClientSession(id))
1192 {
532990d2 1193 ConsoleWrite(pCtx, _T("Session killed\n"));
5d9a9c84
VK
1194 }
1195 else
1196 {
532990d2 1197 ConsoleWrite(pCtx, _T("Invalid session ID\n"));
5d9a9c84
VK
1198 }
1199 }
1200 else
1201 {
532990d2 1202 ConsoleWrite(pCtx, _T("Invalid session ID\n"));
5d9a9c84
VK
1203 }
1204 }
1205 else
1206 {
532990d2 1207 ConsoleWrite(pCtx, _T("Session ID missing\n"));
5d9a9c84 1208 }
84d92f02
VK
1209 }
1210 else if (IsCommand(_T("PING"), szBuffer, 4))
1211 {
1212 pArg = ExtractWord(pArg, szBuffer);
1213 if (szBuffer[0] != 0)
1214 {
1215 InetAddress addr = InetAddress::parse(szBuffer);
1216 if (addr.isValid())
1217 {
1218 UINT32 rtt;
1219 UINT32 rc = IcmpPing(addr, 1, 2000, &rtt, 128);
1220 switch(rc)
1221 {
1222 case ICMP_SUCCESS:
1223 ConsolePrintf(pCtx, _T("Success, RTT = %d ms\n"), (int)rtt);
1224 break;
1225 case ICMP_UNREACHEABLE:
1226 ConsolePrintf(pCtx, _T("Destination unreachable\n"));
1227 break;
1228 case ICMP_TIMEOUT:
1229 ConsolePrintf(pCtx, _T("Request timeout\n"));
1230 break;
1231 case ICMP_RAW_SOCK_FAILED:
1232 ConsolePrintf(pCtx, _T("Cannot create raw socket\n"));
1233 break;
1234 case ICMP_API_ERROR:
1235 ConsolePrintf(pCtx, _T("API error\n"));
1236 break;
1237 default:
1238 ConsolePrintf(pCtx, _T("ERROR %d\n"), (int)rc);
1239 break;
1240 }
1241 }
1242 else
1243 {
532990d2 1244 ConsoleWrite(pCtx, _T("Invalid IP address\n"));
84d92f02
VK
1245 }
1246 }
1247 else
1248 {
532990d2 1249 ConsoleWrite(pCtx, _T("Usage: PING <address>\n"));
84d92f02 1250 }
5d9a9c84 1251 }
f34e7a6e
VK
1252 else if (IsCommand(_T("POLL"), szBuffer, 2))
1253 {
1254 pArg = ExtractWord(pArg, szBuffer);
1255 if (szBuffer[0] != 0)
1256 {
1257 int pollType;
1258 if (IsCommand(_T("CONFIGURATION"), szBuffer, 1))
1259 {
1260 pollType = 1;
1261 }
1262 else if (IsCommand(_T("STATUS"), szBuffer, 1))
1263 {
1264 pollType = 2;
1265 }
1266 else if (IsCommand(_T("TOPOLOGY"), szBuffer, 1))
1267 {
1268 pollType = 3;
1269 }
1270 else
1271 {
1272 pollType = 0;
1273 }
1274
1275 if (pollType > 0)
1276 {
1277 pArg = ExtractWord(pArg, szBuffer);
1278 UINT32 id = _tcstoul(szBuffer, NULL, 0);
1279 if (id != 0)
1280 {
1281 Node *node = (Node *)FindObjectById(id, OBJECT_NODE);
1282 if (node != NULL)
1283 {
1284 switch(pollType)
1285 {
1286 case 1:
208d7427
VK
1287 node->lockForConfigurationPoll();
1288 ThreadPoolExecute(g_pollerThreadPool, node, &Node::configurationPoll, RegisterPoller(POLLER_TYPE_CONFIGURATION, node));
f34e7a6e
VK
1289 break;
1290 case 2:
208d7427
VK
1291 node->lockForStatusPoll();
1292 ThreadPoolExecute(g_pollerThreadPool, node, &Node::statusPoll, RegisterPoller(POLLER_TYPE_STATUS, node));
f34e7a6e
VK
1293 break;
1294 case 3:
208d7427
VK
1295 node->lockForTopologyPoll();
1296 ThreadPoolExecute(g_pollerThreadPool, node, &Node::topologyPoll, RegisterPoller(POLLER_TYPE_TOPOLOGY, node));
f34e7a6e
VK
1297 break;
1298 }
1299 }
1300 else
1301 {
1302 ConsolePrintf(pCtx, _T("ERROR: Node with ID %d does not exist\n\n"), id);
1303 }
1304 }
1305 else
1306 {
532990d2 1307 ConsoleWrite(pCtx, _T("ERROR: Invalid or missing node ID\n\n"));
f34e7a6e
VK
1308 }
1309 }
1310 else
1311 {
532990d2 1312 ConsoleWrite(pCtx, _T("Usage POLL [CONFIGURATION|STATUS|TOPOLOGY] <node>\n"));
f34e7a6e
VK
1313 }
1314 }
1315 else
1316 {
532990d2 1317 ConsoleWrite(pCtx, _T("Usage POLL [CONFIGURATION|STATUS|TOPOLOGY] <node>\n"));
f34e7a6e
VK
1318 }
1319 }
206e268e
VK
1320 else if (IsCommand(_T("SET"), szBuffer, 3))
1321 {
1322 pArg = ExtractWord(pArg, szBuffer);
1323 if (szBuffer[0] != 0)
1324 {
1325 TCHAR value[256];
1326 pArg = ExtractWord(pArg, value);
1327 if (ConfigWriteStr(szBuffer, value, TRUE, TRUE, TRUE))
1328 {
1329 ConsolePrintf(pCtx, _T("Configuration variable %s updated\n"), szBuffer);
1330 }
1331 else
1332 {
1333 ConsolePrintf(pCtx, _T("ERROR: cannot update configuration variable %s\n"), szBuffer);
1334 }
1335 }
1336 else
1337 {
1338 ConsolePrintf(pCtx, _T("Variable name missing\n"));
1339 }
1340 }
35f836fe 1341 else if (IsCommand(_T("SHOW"), szBuffer, 2))
5039dede
AK
1342 {
1343 // Get argument
1344 pArg = ExtractWord(pArg, szBuffer);
1345
50d0de67
VK
1346 if (IsCommand(_T("COMPONENTS"), szBuffer, 1))
1347 {
1348 // Get argument
1349 pArg = ExtractWord(pArg, szBuffer);
967893bb 1350 UINT32 dwNode = _tcstoul(szBuffer, NULL, 0);
50d0de67
VK
1351 if (dwNode != 0)
1352 {
1353 NetObj *pObject = FindObjectById(dwNode);
1354 if (pObject != NULL)
1355 {
c42b4551 1356 if (pObject->getObjectClass() == OBJECT_NODE)
50d0de67 1357 {
8836184f
VK
1358 ComponentTree *components = ((Node *)pObject)->getComponents();
1359 if (components != NULL)
50d0de67 1360 {
8836184f
VK
1361 components->print(pCtx);
1362 components->decRefCount();
50d0de67
VK
1363 }
1364 else
1365 {
532990d2 1366 ConsoleWrite(pCtx, _T("ERROR: Node does not have physical component information\n\n"));
50d0de67
VK
1367 }
1368 }
1369 else
1370 {
532990d2 1371 ConsoleWrite(pCtx, _T("ERROR: Object is not a node\n\n"));
50d0de67
VK
1372 }
1373 }
1374 else
1375 {
1376 ConsolePrintf(pCtx, _T("ERROR: Object with ID %d does not exist\n\n"), dwNode);
1377 }
1378 }
1379 else
1380 {
532990d2 1381 ConsoleWrite(pCtx, _T("ERROR: Invalid or missing node ID\n\n"));
50d0de67
VK
1382 }
1383 }
9c133761
VK
1384 else if (IsCommand(_T("DBCP"), szBuffer, 4))
1385 {
1386 ObjectArray<PoolConnectionInfo> *list = DBConnectionPoolGetConnectionList();
1387 for(int i = 0; i < list->size(); i++)
1388 {
1389 PoolConnectionInfo *c = list->get(i);
1390 TCHAR accessTime[64];
1391 struct tm *ltm = localtime(&c->lastAccessTime);
1392 _tcsftime(accessTime, 64, _T("%d.%b.%Y %H:%M:%S"), ltm);
1393 ConsolePrintf(pCtx, _T("%p %s %hs:%d\n"), c->handle, accessTime, c->srcFile, c->srcLine);
1394 }
1395 ConsolePrintf(pCtx, _T("%d database connections in use\n\n"), list->size());
1396 delete list;
ec5829b2
VK
1397 }
1398 else if (IsCommand(_T("DBSTATS"), szBuffer, 3))
1399 {
a4809f58
VK
1400 LIBNXDB_PERF_COUNTERS counters;
1401 DBGetPerfCounters(&counters);
1402 ConsolePrintf(pCtx, _T("SQL query counters:\n"));
1403 ConsolePrintf(pCtx, _T(" Total .......... ") INT64_FMT _T("\n"), counters.totalQueries);
1404 ConsolePrintf(pCtx, _T(" SELECT ......... ") INT64_FMT _T("\n"), counters.selectQueries);
1405 ConsolePrintf(pCtx, _T(" Non-SELECT ..... ") INT64_FMT _T("\n"), counters.nonSelectQueries);
1406 ConsolePrintf(pCtx, _T(" Long running ... ") INT64_FMT _T("\n"), counters.longRunningQueries);
1407 ConsolePrintf(pCtx, _T(" Failed ......... ") INT64_FMT _T("\n"), counters.failedQueries);
1408
ec5829b2
VK
1409 ConsolePrintf(pCtx, _T("Background writer requests:\n"));
1410 ConsolePrintf(pCtx, _T(" DCI data ....... ") INT64_FMT _T("\n"), g_idataWriteRequests);
1411 ConsolePrintf(pCtx, _T(" DCI raw data ... ") INT64_FMT _T("\n"), g_rawDataWriteRequests);
1412 ConsolePrintf(pCtx, _T(" Others ......... ") INT64_FMT _T("\n"), g_otherWriteRequests);
9c133761 1413 }
4321449e
VK
1414 else if (IsCommand(_T("FDB"), szBuffer, 3))
1415 {
1416 // Get argument
1417 pArg = ExtractWord(pArg, szBuffer);
1418 UINT32 dwNode = _tcstoul(szBuffer, NULL, 0);
1419 if (dwNode != 0)
1420 {
1421 NetObj *pObject = FindObjectById(dwNode);
1422 if (pObject != NULL)
1423 {
c42b4551 1424 if (pObject->getObjectClass() == OBJECT_NODE)
4321449e
VK
1425 {
1426 ForwardingDatabase *fdb = ((Node *)pObject)->getSwitchForwardingDatabase();
1427 if (fdb != NULL)
1428 {
1429 fdb->print(pCtx, (Node *)pObject);
1430 fdb->decRefCount();
1431 }
1432 else
1433 {
532990d2 1434 ConsoleWrite(pCtx, _T("ERROR: Node does not have forwarding database information\n\n"));
4321449e
VK
1435 }
1436 }
1437 else
1438 {
532990d2 1439 ConsoleWrite(pCtx, _T("ERROR: Object is not a node\n\n"));
4321449e
VK
1440 }
1441 }
1442 else
1443 {
1444 ConsolePrintf(pCtx, _T("ERROR: Object with ID %d does not exist\n\n"), dwNode);
1445 }
1446 }
1447 else
1448 {
532990d2 1449 ConsoleWrite(pCtx, _T("ERROR: Invalid or missing node ID\n\n"));
4321449e
VK
1450 }
1451 }
50d0de67 1452 else if (IsCommand(_T("FLAGS"), szBuffer, 1))
5039dede 1453 {
c8076b19 1454 ConsolePrintf(pCtx, _T("Flags: 0x") UINT64X_FMT(_T("016")) _T("\n"), g_flags);
5039dede
AK
1455 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_DAEMON));
1456 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_USE_SYSLOG));
1457 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_ENABLE_NETWORK_DISCOVERY));
1458 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_ACTIVE_NETWORK_DISCOVERY));
1459 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_LOG_SQL_ERRORS));
1460 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_DELETE_EMPTY_SUBNETS));
1461 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_ENABLE_SNMP_TRAPD));
1462 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_ENABLE_ZONING));
5039dede 1463 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_SYNC_NODE_NAMES_WITH_DNS));
cbc777ee 1464 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_CHECK_TRUSTED_NODES));
549f48b3
VK
1465 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_ENABLE_NXSL_CONTAINER_FUNCS));
1466 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_USE_FQDN_FOR_NODE_NAMES));
1467 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_APPLY_TO_DISABLED_DCI_FROM_TEMPLATE));
1468 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_DEBUG_CONSOLE_DISABLED));
1469 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_ENABLE_OBJECT_TRANSACTIONS));
cbc777ee
VK
1470 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_WRITE_FULL_DUMP));
1471 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_RESOLVE_NODE_NAMES));
5039dede 1472 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_CATCH_EXCEPTIONS));
d41268ba 1473 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_HELPDESK_LINK_ACTIVE));
5039dede
AK
1474 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_DB_LOCKED));
1475 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_DB_CONNECTION_LOST));
cbc777ee 1476 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_NO_NETWORK_CONNECTIVITY));
5039dede 1477 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_EVENT_STORM_DETECTED));
e02953a4 1478 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_SNMP_TRAP_DISCOVERY));
c8076b19 1479 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_TRAPS_FROM_UNMANAGED_NODES));
ea50bc33
VK
1480 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_RESOLVE_IP_FOR_EACH_STATUS_POLL));
1481 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_PERFDATA_STORAGE_DRIVER_LOADED));
4e0e77e6 1482 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_BACKGROUND_LOG_WRITER));
0eff2ce4
VK
1483 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_CASE_INSENSITIVE_LOGINS));
1484 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_TRAP_SOURCES_IN_ALL_ZONES));
5039dede
AK
1485 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_SERVER_INITIALIZED));
1486 ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_SHUTDOWN));
35f836fe 1487 ConsolePrintf(pCtx, _T("\n"));
5039dede 1488 }
5962498b
VK
1489 else if (IsCommand(_T("HEAP"), szBuffer, 1))
1490 {
1491 TCHAR *text = GetHeapInfo();
1492 if (text != NULL)
1493 {
532990d2
VK
1494 ConsoleWrite(pCtx, text);
1495 ConsoleWrite(pCtx, _T("\n"));
5962498b
VK
1496 free(text);
1497 }
1498 else
1499 {
532990d2 1500 ConsoleWrite(pCtx, _T("Error reading heap information\n"));
5962498b
VK
1501 }
1502 }
35f836fe 1503 else if (IsCommand(_T("INDEX"), szBuffer, 1))
5039dede
AK
1504 {
1505 // Get argument
1506 pArg = ExtractWord(pArg, szBuffer);
1507
35f836fe 1508 if (IsCommand(_T("CONDITION"), szBuffer, 1))
5039dede 1509 {
c75e9ee4 1510 DumpIndex(pCtx, &g_idxConditionById);
5039dede 1511 }
35f836fe 1512 else if (IsCommand(_T("ID"), szBuffer, 2))
5039dede 1513 {
c75e9ee4 1514 DumpIndex(pCtx, &g_idxObjectById);
5039dede 1515 }
35f836fe 1516 else if (IsCommand(_T("INTERFACE"), szBuffer, 2))
5039dede 1517 {
c75e9ee4 1518 DumpIndex(pCtx, &g_idxInterfaceByAddr);
6aba3998 1519 }
16d6f798
VK
1520 else if (IsCommand(_T("NODEADDR"), szBuffer, 5))
1521 {
c75e9ee4 1522 DumpIndex(pCtx, &g_idxNodeByAddr);
16d6f798
VK
1523 }
1524 else if (IsCommand(_T("NODEID"), szBuffer, 5))
6aba3998 1525 {
c75e9ee4 1526 DumpIndex(pCtx, &g_idxNodeById);
5039dede 1527 }
35f836fe 1528 else if (IsCommand(_T("SUBNET"), szBuffer, 1))
5039dede 1529 {
c75e9ee4 1530 DumpIndex(pCtx, &g_idxSubnetByAddr);
5039dede 1531 }
16d6f798
VK
1532 else if (IsCommand(_T("ZONE"), szBuffer, 1))
1533 {
c75e9ee4 1534 DumpIndex(pCtx, &g_idxZoneByGUID);
16d6f798 1535 }
5039dede
AK
1536 else
1537 {
1538 if (szBuffer[0] == 0)
532990d2
VK
1539 ConsoleWrite(pCtx, _T("ERROR: Missing index name\n")
1540 _T("Valid names are: CONDITION, ID, INTERFACE, NODEADDR, NODEID, SUBNET, ZONE\n\n"));
5039dede 1541 else
532990d2 1542 ConsoleWrite(pCtx, _T("ERROR: Invalid index name\n\n"));
5039dede
AK
1543 }
1544 }
fee245d1
VK
1545 else if (IsCommand(_T("MODULES"), szBuffer, 3))
1546 {
532990d2 1547 ConsoleWrite(pCtx, _T("Loaded server modules:\n"));
fee245d1
VK
1548 for(UINT32 i = 0; i < g_dwNumModules; i++)
1549 {
1550 ConsolePrintf(pCtx, _T(" %s\n"), g_pModuleList[i].szName);
1551 }
1552 ConsolePrintf(pCtx, _T("%d modules loaded\n"), g_dwNumModules);
5039dede 1553 }
d87ddcc2
VK
1554 else if (IsCommand(_T("MSGWQ"), szBuffer, 2))
1555 {
1556 String text = MsgWaitQueue::getDiagInfo();
1557 ConsoleWrite(pCtx, text);
1558 ConsoleWrite(pCtx, _T("\n"));
1559 }
35f836fe 1560 else if (IsCommand(_T("OBJECTS"), szBuffer, 1))
5039dede 1561 {
01ca557f
VK
1562 // Get filter
1563 pArg = ExtractWord(pArg, szBuffer);
1564 StrStrip(szBuffer);
1565 DumpObjects(pCtx, (szBuffer[0] != 0) ? szBuffer : NULL);
5039dede 1566 }
35f836fe 1567 else if (IsCommand(_T("POLLERS"), szBuffer, 1))
5039dede 1568 {
208d7427 1569 ShowPollers(pCtx);
5039dede 1570 }
35f836fe 1571 else if (IsCommand(_T("QUEUES"), szBuffer, 1))
5039dede 1572 {
d140955e
VK
1573 ShowQueueStats(pCtx, &g_dataCollectionQueue, _T("Data collector"));
1574 ShowQueueStats(pCtx, &g_dciCacheLoaderQueue, _T("DCI cache loader"));
76fcb995
VK
1575 ShowQueueStats(pCtx, g_dbWriterQueue, _T("Database writer"));
1576 ShowQueueStats(pCtx, g_dciDataWriterQueue, _T("Database writer (IData)"));
1577 ShowQueueStats(pCtx, g_dciRawDataWriterQueue, _T("Database writer (raw DCI values)"));
35f836fe 1578 ShowQueueStats(pCtx, g_pEventQueue, _T("Event processor"));
35f836fe 1579 ShowQueueStats(pCtx, &g_nodePollerQueue, _T("Node poller"));
f1784ab6
VK
1580 ShowQueueStats(pCtx, &g_syslogProcessingQueue, _T("Syslog processing"));
1581 ShowQueueStats(pCtx, &g_syslogWriteQueue, _T("Syslog writer"));
35f836fe 1582 ConsolePrintf(pCtx, _T("\n"));
5039dede 1583 }
35f836fe 1584 else if (IsCommand(_T("ROUTING-TABLE"), szBuffer, 1))
5039dede 1585 {
967893bb 1586 UINT32 dwNode;
5039dede
AK
1587 NetObj *pObject;
1588
1589 pArg = ExtractWord(pArg, szBuffer);
35f836fe 1590 dwNode = _tcstoul(szBuffer, NULL, 0);
5039dede
AK
1591 if (dwNode != 0)
1592 {
1593 pObject = FindObjectById(dwNode);
1594 if (pObject != NULL)
1595 {
c42b4551 1596 if (pObject->getObjectClass() == OBJECT_NODE)
5039dede
AK
1597 {
1598 ROUTING_TABLE *pRT;
35f836fe 1599 TCHAR szIpAddr[16];
5039dede
AK
1600 int i;
1601
c42b4551 1602 ConsolePrintf(pCtx, _T("Routing table for node %s:\n\n"), pObject->getName());
58b3e451 1603 pRT = ((Node *)pObject)->getCachedRoutingTable();
5039dede
AK
1604 if (pRT != NULL)
1605 {
1606 for(i = 0; i < pRT->iNumEntries; i++)
1607 {
35f836fe
VK
1608 _sntprintf(szBuffer, 256, _T("%s/%d"), IpToStr(pRT->pRoutes[i].dwDestAddr, szIpAddr),
1609 BitsInMask(pRT->pRoutes[i].dwDestMask));
1610 ConsolePrintf(pCtx, _T("%-18s %-15s %-6d %d\n"), szBuffer,
1611 IpToStr(pRT->pRoutes[i].dwNextHop, szIpAddr),
1612 pRT->pRoutes[i].dwIfIndex, pRT->pRoutes[i].dwRouteType);
5039dede 1613 }
532990d2 1614 ConsoleWrite(pCtx, _T("\n"));
5039dede
AK
1615 }
1616 else
1617 {
532990d2 1618 ConsoleWrite(pCtx, _T("Node doesn't have cached routing table\n\n"));
5039dede
AK
1619 }
1620 }
1621 else
1622 {
532990d2 1623 ConsoleWrite(pCtx, _T("ERROR: Object is not a node\n\n"));
5039dede
AK
1624 }
1625 }
1626 else
1627 {
35f836fe 1628 ConsolePrintf(pCtx, _T("ERROR: Object with ID %d does not exist\n\n"), dwNode);
5039dede
AK
1629 }
1630 }
1631 else
1632 {
532990d2 1633 ConsoleWrite(pCtx, _T("ERROR: Invalid or missing node ID\n\n"));
5039dede
AK
1634 }
1635 }
35f836fe 1636 else if (IsCommand(_T("SESSIONS"), szBuffer, 2))
5039dede 1637 {
532990d2 1638 ConsoleWrite(pCtx, _T("\x1b[1mCLIENT SESSIONS\x1b[0m\n============================================================\n"));
534e1b83 1639 DumpClientSessions(pCtx);
532990d2 1640 ConsoleWrite(pCtx, _T("\n\x1b[1mMOBILE DEVICE SESSIONS\x1b[0m\n============================================================\n"));
534e1b83 1641 DumpMobileDeviceSessions(pCtx);
5039dede 1642 }
35f836fe 1643 else if (IsCommand(_T("STATS"), szBuffer, 2))
5039dede
AK
1644 {
1645 ShowServerStats(pCtx);
1646 }
5d3459af
VK
1647 else if (IsCommand(_T("THREADS"), szBuffer, 2))
1648 {
1649 ShowThreadPool(pCtx, g_mainThreadPool);
ab6aa3e8 1650 ShowThreadPool(pCtx, g_pollerThreadPool);
c6e191d2 1651 ShowThreadPool(pCtx, g_schedulerThreadPool);
1693f955 1652 ShowThreadPool(pCtx, g_agentConnectionThreadPool);
5d3459af 1653 }
b833cbf5
VK
1654 else if (IsCommand(_T("TOPOLOGY"), szBuffer, 1))
1655 {
1656 pArg = ExtractWord(pArg, szBuffer);
1657 UINT32 nodeId = _tcstoul(szBuffer, NULL, 0);
1658 if (nodeId != 0)
1659 {
1660 Node *node = (Node *)FindObjectById(nodeId, OBJECT_NODE);
1661 if (node != NULL)
1662 {
1663 LinkLayerNeighbors *nbs = BuildLinkLayerNeighborList(node);
1664 if (nbs != NULL)
1665 {
1666 ConsolePrintf(pCtx, _T("Proto | PtP | ifLocal | ifRemote | Peer\n")
1667 _T("--------+-----+---------+----------+------------------------------------\n"));
1668 for(int i = 0; i < nbs->size(); i++)
1669 {
1670 LL_NEIGHBOR_INFO *ni = nbs->getConnection(i);
1671 TCHAR peer[256];
1672 if (ni->objectId != 0)
1673 {
1674 NetObj *object = FindObjectById(ni->objectId);
1675 if (object != NULL)
c42b4551 1676 _sntprintf(peer, 256, _T("%s [%d]"), object->getName(), ni->objectId);
b833cbf5
VK
1677 else
1678 _sntprintf(peer, 256, _T("[%d]"), ni->objectId);
1679 }
1680 else
1681 {
1682 peer[0] = 0;
1683 }
2589cc10 1684 ConsolePrintf(pCtx, _T("%-7s | %c | %7d | %7d | %s\n"),
b833cbf5
VK
1685 GetLinkLayerProtocolName(ni->protocol), ni->isPtToPt ? _T('Y') : _T('N'), ni->ifLocal, ni->ifRemote, peer);
1686 }
1687 nbs->decRefCount();
1688 }
1689 else
1690 {
532990d2 1691 ConsoleWrite(pCtx, _T("ERROR: call to BuildLinkLayerNeighborList failed\n\n"));
b833cbf5
VK
1692 }
1693 }
1694 else
1695 {
1696 ConsolePrintf(pCtx, _T("ERROR: Node with ID %d does not exist\n\n"), nodeId);
1697 }
1698 }
1699 else
1700 {
532990d2 1701 ConsoleWrite(pCtx, _T("ERROR: Invalid or missing node ID\n\n"));
b833cbf5
VK
1702 }
1703 }
35f836fe 1704 else if (IsCommand(_T("USERS"), szBuffer, 1))
5039dede
AK
1705 {
1706 DumpUsers(pCtx);
1707 }
b0ff1179
VK
1708 else if (IsCommand(_T("VLANS"), szBuffer, 1))
1709 {
967893bb 1710 UINT32 dwNode;
b0ff1179
VK
1711 NetObj *pObject;
1712
1713 pArg = ExtractWord(pArg, szBuffer);
1714 dwNode = _tcstoul(szBuffer, NULL, 0);
1715 if (dwNode != 0)
1716 {
1717 pObject = FindObjectById(dwNode);
1718 if (pObject != NULL)
1719 {
c42b4551 1720 if (pObject->getObjectClass() == OBJECT_NODE)
b0ff1179
VK
1721 {
1722 VlanList *vlans = ((Node *)pObject)->getVlans();
1723 if (vlans != NULL)
1724 {
532990d2
VK
1725 ConsoleWrite(pCtx, _T("\x1b[1mVLAN\x1b[0m | \x1b[1mName\x1b[0m | \x1b[1mPorts\x1b[0m\n")
1726 _T("-----+------------------+-----------------------------------------------------------------\n"));
a6312bd6 1727 for(int i = 0; i < vlans->size(); i++)
b0ff1179
VK
1728 {
1729 VlanInfo *vlan = vlans->get(i);
1730 ConsolePrintf(pCtx, _T("%4d | %-16s |"), vlan->getVlanId(), vlan->getName());
1731 for(int j = 0; j < vlan->getNumPorts(); j++)
1732 ConsolePrintf(pCtx, _T(" %d.%d"), (int)(vlan->getPorts()[j] >> 16), (int)(vlan->getPorts()[j] & 0xFFFF));
1733 ConsolePrintf(pCtx, _T("\n"));
1734 }
1735 ConsolePrintf(pCtx, _T("\n"));
1736 vlans->decRefCount();
1737 }
1738 else
1739 {
532990d2 1740 ConsoleWrite(pCtx, _T("\x1b[31mNode doesn't have VLAN information\x1b[0m\n\n"));
b0ff1179
VK
1741 }
1742 }
1743 else
1744 {
532990d2 1745 ConsoleWrite(pCtx, _T("\x1b[31mERROR: Object is not a node\x1b[0m\n\n"));
b0ff1179
VK
1746 }
1747 }
1748 else
1749 {
1750 ConsolePrintf(pCtx, _T("\x1b[31mERROR: Object with ID %d does not exist\x1b[0m\n\n"), dwNode);
1751 }
1752 }
1753 else
1754 {
532990d2 1755 ConsoleWrite(pCtx, _T("\x1b[31mERROR: Invalid or missing node ID\x1b[0m\n\n"));
b0ff1179
VK
1756 }
1757 }
35f836fe 1758 else if (IsCommand(_T("WATCHDOG"), szBuffer, 1))
5039dede
AK
1759 {
1760 WatchdogPrintStatus(pCtx);
532990d2 1761 ConsoleWrite(pCtx, _T("\n"));
5039dede
AK
1762 }
1763 else
1764 {
1765 if (szBuffer[0] == 0)
532990d2 1766 ConsoleWrite(pCtx, _T("ERROR: Missing subcommand\n\n"));
5039dede 1767 else
532990d2 1768 ConsoleWrite(pCtx, _T("ERROR: Invalid SHOW subcommand\n\n"));
5039dede
AK
1769 }
1770 }
06a8857b
AK
1771 else if (IsCommand(_T("EXEC"), szBuffer, 3))
1772 {
1773 pArg = ExtractWord(pArg, szBuffer);
35104062 1774
e323047c 1775 bool libraryLocked = true;
6b29839d 1776 bool destroyCompiledScript = false;
e323047c
VK
1777 g_pScriptLibrary->lock();
1778
35104062
VK
1779 NXSL_Program *compiledScript = g_pScriptLibrary->findScript(szBuffer);
1780 if (compiledScript == NULL)
06a8857b 1781 {
e323047c
VK
1782 g_pScriptLibrary->unlock();
1783 libraryLocked = false;
6b29839d 1784 destroyCompiledScript = true;
35104062 1785 char *script;
967893bb 1786 UINT32 fileSize;
35104062 1787 if ((script = (char *)LoadFile(szBuffer, &fileSize)) != NULL)
06a8857b 1788 {
35104062
VK
1789 const int errorMsgLen = 512;
1790 TCHAR errorMsg[errorMsgLen];
1791#ifdef UNICODE
1792 WCHAR *wscript = WideStringFromMBString(script);
d881ea08 1793 compiledScript = NXSLCompile(wscript, errorMsg, errorMsgLen, NULL);
35104062
VK
1794 free(wscript);
1795#else
d881ea08 1796 compiledScript = NXSLCompile(script, errorMsg, errorMsgLen, NULL);
35104062
VK
1797#endif
1798 free(script);
1799 if (compiledScript == NULL)
06a8857b 1800 {
35104062 1801 ConsolePrintf(pCtx, _T("ERROR: Script compilation error: %s\n\n"), errorMsg);
06a8857b
AK
1802 }
1803 }
1804 else
1805 {
35104062 1806 ConsolePrintf(pCtx, _T("ERROR: Script \"%s\" not found\n\n"), szBuffer);
06a8857b
AK
1807 }
1808 }
35104062
VK
1809
1810 if (compiledScript != NULL)
06a8857b 1811 {
35104062 1812 NXSL_ServerEnv *pEnv = new NXSL_ServerEnv;
2773ef30 1813 pEnv->setConsole(pCtx);
35104062 1814
6b29839d
VK
1815 NXSL_VM *vm = new NXSL_VM(pEnv);
1816 if (vm->load(compiledScript))
d9177dd1 1817 {
6b29839d
VK
1818 if (libraryLocked)
1819 {
1820 g_pScriptLibrary->unlock();
1821 libraryLocked = false;
1822 }
1823
1824 NXSL_Value *argv[32];
1825 int argc = 0;
1826 while(argc < 32)
1827 {
1828 pArg = ExtractWord(pArg, szBuffer);
1829 if (szBuffer[0] == 0)
1830 break;
1831 argv[argc++] = new NXSL_Value(szBuffer);
1832 }
1833
1834 if (vm->run(argc, argv))
1835 {
1836 NXSL_Value *pValue = vm->getResult();
1837 int retCode = pValue->getValueAsInt32();
1838 ConsolePrintf(pCtx, _T("INFO: Script finished with rc=%d\n\n"), retCode);
1839 }
1840 else
1841 {
1842 ConsolePrintf(pCtx, _T("ERROR: Script finished with error: %s\n\n"), vm->getErrorText());
1843 }
1844 }
1845 else
1846 {
1847 ConsolePrintf(pCtx, _T("ERROR: VM creation failed: %s\n\n"), vm->getErrorText());
1848 }
1849 delete vm;
1850 if (destroyCompiledScript)
1851 delete compiledScript;
06a8857b 1852 }
e323047c
VK
1853 if (libraryLocked)
1854 g_pScriptLibrary->unlock();
06a8857b 1855 }
35f836fe 1856 else if (IsCommand(_T("TRACE"), szBuffer, 1))
5039dede 1857 {
967893bb 1858 UINT32 dwNode1, dwNode2;
5039dede 1859 NetObj *pObject1, *pObject2;
6d069676 1860 NetworkPath *pTrace;
35f836fe 1861 TCHAR szNextHop[16];
5039dede
AK
1862 int i;
1863
1864 // Get arguments
1865 pArg = ExtractWord(pArg, szBuffer);
35f836fe 1866 dwNode1 = _tcstoul(szBuffer, NULL, 0);
5039dede
AK
1867
1868 pArg = ExtractWord(pArg, szBuffer);
35f836fe 1869 dwNode2 = _tcstoul(szBuffer, NULL, 0);
5039dede
AK
1870
1871 if ((dwNode1 != 0) && (dwNode2 != 0))
1872 {
1873 pObject1 = FindObjectById(dwNode1);
1874 if (pObject1 == NULL)
1875 {
35f836fe 1876 ConsolePrintf(pCtx, _T("ERROR: Object with ID %d does not exist\n\n"), dwNode1);
5039dede
AK
1877 }
1878 else
1879 {
1880 pObject2 = FindObjectById(dwNode2);
1881 if (pObject2 == NULL)
1882 {
35f836fe 1883 ConsolePrintf(pCtx, _T("ERROR: Object with ID %d does not exist\n\n"), dwNode2);
5039dede
AK
1884 }
1885 else
1886 {
c42b4551 1887 if ((pObject1->getObjectClass() == OBJECT_NODE) && (pObject2->getObjectClass() == OBJECT_NODE))
5039dede
AK
1888 {
1889 pTrace = TraceRoute((Node *)pObject1, (Node *)pObject2);
1890 if (pTrace != NULL)
1891 {
99c11466
VK
1892 TCHAR sourceIp[32];
1893 ConsolePrintf(pCtx, _T("Trace from %s to %s (%d hops, %s, source IP %s):\n"),
c42b4551 1894 pObject1->getName(), pObject2->getName(), pTrace->getHopCount(),
99c11466 1895 pTrace->isComplete() ? _T("complete") : _T("incomplete"),
c75e9ee4 1896 pTrace->getSourceAddress().toString(sourceIp));
99c11466 1897 for(i = 0; i < pTrace->getHopCount(); i++)
6d069676
VK
1898 {
1899 HOP_INFO *hop = pTrace->getHopInfo(i);
35f836fe 1900 ConsolePrintf(pCtx, _T("[%d] %s %s %s %d\n"),
c42b4551
VK
1901 hop->object->getId(),
1902 hop->object->getName(),
c75e9ee4 1903 hop->nextHop.toString(szNextHop),
6d069676
VK
1904 hop->isVpn ? _T("VPN Connector ID:") : _T("Interface Index: "),
1905 hop->ifIndex);
1906 }
1907 delete pTrace;
35f836fe 1908 ConsolePrintf(pCtx, _T("\n"));
5039dede
AK
1909 }
1910 else
1911 {
532990d2 1912 ConsoleWrite(pCtx, _T("ERROR: Call to TraceRoute() failed\n\n"));
5039dede
AK
1913 }
1914 }
1915 else
1916 {
532990d2 1917 ConsoleWrite(pCtx, _T("ERROR: Object is not a node\n\n"));
5039dede
AK
1918 }
1919 }
1920 }
1921 }
1922 else
1923 {
532990d2 1924 ConsoleWrite(pCtx, _T("ERROR: Invalid or missing node id(s)\n\n"));
5039dede
AK
1925 }
1926 }
d9177dd1 1927 else if (IsCommand(_T("LDAPSYNC"), szBuffer, 4))
1928 {
1929 LDAPConnection conn;
1930 conn.syncUsers();
0a145c10 1931 }
1932 else if (IsCommand(_T("AT"), szBuffer, 2))
1933 {
1934 pArg = ExtractWord(pArg, szBuffer);
c6e191d2 1935 if (szBuffer[0] == _T('+'))
0a145c10 1936 {
c6e191d2 1937 int offset = _tcstoul(&szBuffer[1], NULL, 0);
ec13a467 1938 AddOneTimeScheduledTask(_T("Execute.Script"), time(NULL) + offset, pArg, 0, 0, SYSTEM_ACCESS_FULL);//TODO: change to correct user
0a145c10 1939 }
1940 else
1941 {
ec13a467 1942 AddScheduledTask(_T("Execute.Script"), szBuffer, pArg, 0, 0, SYSTEM_ACCESS_FULL); //TODO: change to correct user
0a145c10 1943 }
d9177dd1 1944 }
35f836fe 1945 else if (IsCommand(_T("HELP"), szBuffer, 2) || IsCommand(_T("?"), szBuffer, 1))
5039dede 1946 {
2589cc10 1947 ConsoleWrite(pCtx,
532990d2 1948 _T("Valid commands are:\n")
c6e191d2
VK
1949 _T(" at +<seconds>|<schedule> <script> [<parameters>]\n")
1950 _T(" - Schedule script execution task\n")
48c0079d 1951 _T(" debug [<level>|off] - Set debug level (valid range is 0..9)\n")
48a3497b
VK
1952 _T(" down - Shutdown NetXMS server\n")
1953 _T(" exec <script> [<params>] - Executes NXSL script from script library\n")
35f836fe 1954 _T(" exit - Exit from remote session\n")
5d9a9c84 1955 _T(" kill <session> - Kill client session\n")
206e268e 1956 _T(" get <variable> - Get value of server configuration variable\n")
35f836fe 1957 _T(" help - Display this help\n")
a64c346b 1958 _T(" hkrun - Run housekeeper immediately\n")
d9177dd1 1959 _T(" ldapsync - Synchronize ldap users with local user database\n")
06b83321 1960 _T(" ping <address> - Send ICMP echo request to given IP address\n")
f34e7a6e 1961 _T(" poll <type> <node> - Initiate node poll\n")
35f836fe 1962 _T(" raise <exception> - Raise exception\n")
206e268e 1963 _T(" set <variable> <value> - Set value of server configuration variable\n")
50d0de67 1964 _T(" show components <node> - Show physical components of given node\n")
9c133761 1965 _T(" show dbcp - Show active sessions in database connection pool\n")
ec5829b2 1966 _T(" show dbstats - Show DB library statistics\n")
48a3497b 1967 _T(" show fdb <node> - Show forwarding database for node\n")
35f836fe 1968 _T(" show flags - Show internal server flags\n")
5962498b 1969 _T(" show heap - Show heap information\n")
35f836fe 1970 _T(" show index <index> - Show internal index\n")
713825d1 1971 _T(" show modules - Show loaded server modules\n")
d87ddcc2 1972 _T(" show msgwq - Show message wait queues information\n")
01ca557f 1973 _T(" show objects [<filter>] - Dump network objects to screen\n")
35f836fe
VK
1974 _T(" show pollers - Show poller threads state information\n")
1975 _T(" show queues - Show internal queues statistics\n")
1976 _T(" show routing-table <node> - Show cached routing table for node\n")
1977 _T(" show sessions - Show active client sessions\n")
1978 _T(" show stats - Show server statistics\n")
b833cbf5 1979 _T(" show topology <node> - Collect and show link layer topology for node\n")
35f836fe 1980 _T(" show users - Show users\n")
b0ff1179 1981 _T(" show vlans <node> - Show cached VLAN information for node\n")
35f836fe
VK
1982 _T(" show watchdog - Display watchdog information\n")
1983 _T(" trace <node1> <node2> - Show network path trace between two nodes\n")
1984 _T("\nAlmost all commands can be abbreviated to 2 or 3 characters\n")
1985 _T("\n"));
5039dede 1986 }
d9177dd1 1987 else
5039dede 1988 {
532990d2 1989 ConsoleWrite(pCtx, _T("UNKNOWN COMMAND\n\n"));
5039dede
AK
1990 }
1991
1992 return nExitCode;
1993}
1994
fdbee7f8
VK
1995/**
1996 * Signal handler for UNIX platforms
1997 */
5039dede
AK
1998#ifndef _WIN32
1999
2000void SignalHandlerStub(int nSignal)
2001{
2002 // should be unused, but JIC...
2003 if (nSignal == SIGCHLD)
2004 {
2005 while (waitpid(-1, NULL, WNOHANG) > 0)
2006 ;
2007 }
2008}
2009
2010THREAD_RESULT NXCORE_EXPORTABLE THREAD_CALL SignalHandler(void *pArg)
2011{
2012 sigset_t signals;
2013 int nSignal;
5039dede
AK
2014
2015 m_signalHandlerThread = pthread_self();
2016
2017 // default for SIGCHLD: ignore
2018 signal(SIGCHLD, &SignalHandlerStub);
2019
2020 sigemptyset(&signals);
2021 sigaddset(&signals, SIGTERM);
2022 sigaddset(&signals, SIGINT);
5039dede
AK
2023 sigaddset(&signals, SIGSEGV);
2024 sigaddset(&signals, SIGCHLD);
2025 sigaddset(&signals, SIGHUP);
2026 sigaddset(&signals, SIGUSR1);
2027 sigaddset(&signals, SIGUSR2);
95e2329a
VK
2028#if !defined(__sun) && !defined(_AIX) && !defined(__hpux)
2029 sigaddset(&signals, SIGPIPE);
2030#endif
5039dede
AK
2031
2032 sigprocmask(SIG_BLOCK, &signals, NULL);
2033
2034 while(1)
2035 {
2036 if (sigwait(&signals, &nSignal) == 0)
2037 {
2038 switch(nSignal)
2039 {
2040 case SIGTERM:
2041 case SIGINT:
bc9263d1
VK
2042 // avoid repeat Shutdown() call
2043 if (!(g_flags & AF_SHUTDOWN))
2044 {
2045 m_nShutdownReason = SHUTDOWN_BY_SIGNAL;
2046 if (IsStandalone())
2047 Shutdown(); // will never return
2048 else
2049 ConditionSet(m_condShutdown);
2050 }
2051 break;
5039dede
AK
2052 case SIGSEGV:
2053 abort();
2054 break;
2055 case SIGCHLD:
2056 while (waitpid(-1, NULL, WNOHANG) > 0)
2057 ;
2058 break;
2059 case SIGUSR1:
c8076b19 2060 if (g_flags & AF_SHUTDOWN)
5039dede
AK
2061 goto stop_handler;
2062 break;
2063 default:
2064 break;
2065 }
2066 }
2067 else
2068 {
2069 ThreadSleepMs(100);
2070 }
2071 }
2072
2073stop_handler:
2074 sigprocmask(SIG_UNBLOCK, &signals, NULL);
5039dede
AK
2075 return THREAD_OK;
2076}
2077
2078#endif
2079
fdbee7f8
VK
2080/**
2081 * Common main()
2082 */
5039dede
AK
2083THREAD_RESULT NXCORE_EXPORTABLE THREAD_CALL Main(void *pArg)
2084{
2085 nxlog_write(MSG_SERVER_STARTED, EVENTLOG_INFORMATION_TYPE, NULL);
2086
7bdb43c3
VK
2087 if (IsStandalone())
2088 {
c8076b19 2089 if (!(g_flags & AF_DEBUG_CONSOLE_DISABLED))
7bdb43c3
VK
2090 {
2091 char *ptr, szCommand[256];
2092 struct __console_ctx ctx;
35f836fe 2093#ifdef UNICODE
7bdb43c3 2094 WCHAR wcCommand[256];
35f836fe 2095#endif
5039dede 2096
7bdb43c3
VK
2097 ctx.hSocket = -1;
2098 ctx.socketMutex = INVALID_MUTEX_HANDLE;
2099 ctx.pMsg = NULL;
2100 ctx.session = NULL;
2101 ctx.output = NULL;
8e17001f 2102 WriteToTerminal(_T("\nNetXMS Server V") NETXMS_VERSION_STRING _T(" Build ") NETXMS_VERSION_BUILD_STRING IS_UNICODE_BUILD_STRING _T(" Ready\n")
7bdb43c3
VK
2103 _T("Enter \"\x1b[1mhelp\x1b[0m\" for command list or \"\x1b[1mdown\x1b[0m\" for server shutdown\n")
2104 _T("System Console\n\n"));
5039dede
AK
2105
2106#if USE_READLINE
7bdb43c3
VK
2107 // Initialize readline library if we use it
2108 rl_bind_key('\t', RL_INSERT_CAST rl_insert);
5039dede
AK
2109#endif
2110
7bdb43c3
VK
2111 while(1)
2112 {
5039dede 2113#if USE_READLINE
7bdb43c3 2114 ptr = readline("\x1b[33mnetxmsd:\x1b[0m ");
5039dede 2115#else
7bdb43c3
VK
2116 WriteToTerminal(_T("\x1b[33mnetxmsd:\x1b[0m "));
2117 fflush(stdout);
2118 if (fgets(szCommand, 255, stdin) == NULL)
2119 break; // Error reading stdin
2120 ptr = strchr(szCommand, '\n');
2121 if (ptr != NULL)
2122 *ptr = 0;
2123 ptr = szCommand;
5039dede
AK
2124#endif
2125
7bdb43c3
VK
2126 if (ptr != NULL)
2127 {
35f836fe 2128#ifdef UNICODE
7bdb43c3
VK
2129 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, ptr, -1, wcCommand, 256);
2130 wcCommand[255] = 0;
2131 StrStrip(wcCommand);
2132 if (wcCommand[0] != 0)
2133 {
2134 if (ProcessConsoleCommand(wcCommand, &ctx) == CMD_EXIT_SHUTDOWN)
35f836fe 2135#else
7bdb43c3
VK
2136 StrStrip(ptr);
2137 if (*ptr != 0)
2138 {
2139 if (ProcessConsoleCommand(ptr, &ctx) == CMD_EXIT_SHUTDOWN)
35f836fe 2140#endif
7bdb43c3 2141 break;
5039dede 2142#if USE_READLINE
7bdb43c3 2143 add_history(ptr);
5039dede 2144#endif
7bdb43c3 2145 }
5039dede 2146#if USE_READLINE
7bdb43c3 2147 free(ptr);
5039dede 2148#endif
7bdb43c3
VK
2149 }
2150 else
2151 {
2152 _tprintf(_T("\n"));
2153 }
2154 }
5039dede
AK
2155
2156#if USE_READLINE
7bdb43c3 2157 free(ptr);
5039dede 2158#endif
bc9263d1
VK
2159 if (!(g_flags & AF_SHUTDOWN))
2160 {
2161 m_nShutdownReason = SHUTDOWN_FROM_CONSOLE;
2162 Shutdown();
2163 }
7bdb43c3
VK
2164 }
2165 else
2166 {
2167 // standalone with debug console disabled
2168#ifdef _WIN32
2169 _tprintf(_T("Server running. Press ESC to shutdown.\n"));
2170 while(1)
2171 {
2172 if (_getch() == 27)
2173 break;
2174 }
2175 _tprintf(_T("Server shutting down...\n"));
2176 Shutdown();
2177#else
2178 _tprintf(_T("Server running. Press Ctrl+C to shutdown.\n"));
2179 // Shutdown will be called from signal handler
2180 ConditionWait(m_condShutdown, INFINITE);
2181#endif
2182 }
5039dede
AK
2183 }
2184 else
2185 {
2186 ConditionWait(m_condShutdown, INFINITE);
2187 // On Win32, Shutdown() will be called by service control handler
2188#ifndef _WIN32
2189 Shutdown();
2190#endif
2191 }
2192 return THREAD_OK;
2193}
2194
fdbee7f8
VK
2195/**
2196 * Initiate server shutdown
2197 */
035a4d73 2198void InitiateShutdown()
5039dede
AK
2199{
2200#ifdef _WIN32
2201 Shutdown();
2202#else
2203 if (IsStandalone())
2204 {
2205 Shutdown();
2206 }
2207 else
2208 {
2209 pthread_kill(m_signalHandlerThread, SIGTERM);
2210 }
2211#endif
2212}
2213
fdbee7f8
VK
2214/**
2215 *DLL Entry point
2216 */
5039dede
AK
2217#ifdef _WIN32
2218
2219BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
2220{
2221 if (dwReason == DLL_PROCESS_ATTACH)
2222 DisableThreadLibraryCalls(hInstance);
2223 return TRUE;
2224}
2225
2226#endif