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