Commit | Line | Data |
---|---|---|
cc022855 | 1 | /* |
5039dede | 2 | ** NetXMS multiplatform core agent |
c99dbf89 | 3 | ** Copyright (C) 2003-2016 Victor Kirhenshtein |
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 | ** | |
f0c1d2a4 AK |
10 | ** This program is distributed in the hope that it will be useful, |
11 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of | |
5039dede AK |
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: nxagentd.cpp | |
20 | ** | |
21 | **/ | |
22 | ||
23 | #include "nxagentd.h" | |
24 | ||
25 | #if defined(_WIN32) | |
ed2a1152 | 26 | #include <shlobj.h> |
5039dede | 27 | #include <conio.h> |
5039dede AK |
28 | #else |
29 | #include <signal.h> | |
30 | #include <sys/wait.h> | |
31 | #endif | |
32 | ||
c1099678 VK |
33 | #if HAVE_LOCALE_H |
34 | #include <locale.h> | |
35 | #endif | |
36 | ||
5039dede AK |
37 | #if HAVE_SYS_UTSNAME_H |
38 | #include <sys/utsname.h> | |
39 | #endif | |
40 | ||
41 | #if HAVE_SYS_SYSCTL_H | |
42 | #include <sys/sysctl.h> | |
43 | #endif | |
44 | ||
01116597 VK |
45 | #ifdef _WITH_ENCRYPTION |
46 | #include <openssl/ssl.h> | |
47 | #endif | |
5039dede | 48 | |
e4ec73da VK |
49 | #if HAVE_GRP_H |
50 | #include <grp.h> | |
51 | #endif | |
52 | ||
53 | #if HAVE_PWD_H | |
54 | #include <pwd.h> | |
55 | #endif | |
56 | ||
489b117b | 57 | /** |
58 | * Externals | |
59 | */ | |
5039dede AK |
60 | THREAD_RESULT THREAD_CALL ListenerThread(void *); |
61 | THREAD_RESULT THREAD_CALL SessionWatchdog(void *); | |
62 | THREAD_RESULT THREAD_CALL TrapSender(void *); | |
0df58041 | 63 | THREAD_RESULT THREAD_CALL MasterAgentListener(void *arg); |
76b42c1e | 64 | THREAD_RESULT THREAD_CALL SNMPTrapReceiver(void *); |
489b117b | 65 | THREAD_RESULT THREAD_CALL SNMPTrapSender(void *); |
685508a7 VK |
66 | THREAD_RESULT THREAD_CALL SyslogReceiver(void *); |
67 | THREAD_RESULT THREAD_CALL SyslogSender(void *); | |
842378a4 | 68 | THREAD_RESULT THREAD_CALL TunnelManager(void *); |
5039dede AK |
69 | |
70 | void ShutdownTrapSender(); | |
489b117b | 71 | void ShutdownSNMPTrapSender(); |
5039dede | 72 | |
685508a7 VK |
73 | void ShutdownSyslogSender(); |
74 | ||
87fff547 VK |
75 | void StartLocalDataCollector(); |
76 | void ShutdownLocalDataCollector(); | |
77 | ||
9fcdfda7 VK |
78 | void StartWatchdog(); |
79 | void StopWatchdog(); | |
80 | int WatchdogMain(DWORD pid); | |
81 | ||
6aab2983 | 82 | void InitSessionList(); |
13783551 | 83 | void DestroySessionList(); |
6aab2983 | 84 | |
a854d114 VK |
85 | BOOL RegisterOnServer(const TCHAR *pszServer); |
86 | ||
b123ecb3 | 87 | void UpdatePolicyInventory(); |
88 | ||
842378a4 VK |
89 | void ParseTunnelList(TCHAR *list); |
90 | ||
968031d9 | 91 | #if !defined(_WIN32) |
203e9d8a | 92 | void InitStaticSubagents(); |
5039dede AK |
93 | #endif |
94 | ||
9f96fc88 VK |
95 | #ifdef _WIN32 |
96 | extern TCHAR g_windowsServiceName[]; | |
97 | extern TCHAR g_windowsServiceDisplayName[]; | |
98 | #endif | |
99 | ||
359784de | 100 | void LIBNXAGENT_EXPORTABLE InitSubAgentAPI(void (* writeLog)(int, int, const TCHAR *), |
6fbaa926 VK |
101 | void (* sendTrap1)(UINT32, const TCHAR *, const char *, va_list), |
102 | void (* sendTrap2)(UINT32, const TCHAR *, int, TCHAR **), | |
103 | bool (* enumerateSessions)(EnumerationCallbackResult (*)(AbstractCommSession *, void *), void*), | |
104 | AbstractCommSession *(* findServerSession)(UINT64), | |
105 | bool (* sendFile)(void *, UINT32, const TCHAR *, long), | |
106 | bool (* pushData)(const TCHAR *, const TCHAR *, UINT32, time_t), | |
7f6ecb6d TD |
107 | DB_HANDLE (* getLocalDatabaseHandle)(), |
108 | CONDITION shutdownCondition, const TCHAR *dataDirectory); | |
359784de | 109 | |
f918b160 VK |
110 | /** |
111 | * Messages generated by mc.pl (for UNIX version only) | |
112 | */ | |
5039dede AK |
113 | #ifndef _WIN32 |
114 | extern unsigned int g_dwNumMessages; | |
115 | extern const TCHAR *g_szMessages[]; | |
116 | #endif | |
117 | ||
f918b160 VK |
118 | /** |
119 | * Valid options for getopt() | |
120 | */ | |
5039dede | 121 | #if defined(_WIN32) |
f918b160 | 122 | #define VALID_OPTIONS "c:CdD:e:EfhHiIKM:n:N:P:r:RsSUvX:W:Z:" |
5039dede | 123 | #else |
e4ec73da | 124 | #define VALID_OPTIONS "c:CdD:fg:hKM:p:P:r:u:vX:W:Z:" |
5039dede AK |
125 | #endif |
126 | ||
f918b160 VK |
127 | /** |
128 | * Actions | |
129 | */ | |
5039dede AK |
130 | #define ACTION_NONE 0 |
131 | #define ACTION_RUN_AGENT 1 | |
132 | #define ACTION_INSTALL_SERVICE 2 | |
133 | #define ACTION_REMOVE_SERVICE 3 | |
134 | #define ACTION_START_SERVICE 4 | |
135 | #define ACTION_STOP_SERVICE 5 | |
136 | #define ACTION_CHECK_CONFIG 6 | |
137 | #define ACTION_INSTALL_EVENT_SOURCE 7 | |
138 | #define ACTION_REMOVE_EVENT_SOURCE 8 | |
139 | #define ACTION_CREATE_CONFIG 9 | |
140 | #define ACTION_HELP 10 | |
9fcdfda7 | 141 | #define ACTION_RUN_WATCHDOG 11 |
f918b160 | 142 | #define ACTION_SHUTDOWN_EXT_AGENTS 12 |
5039dede | 143 | |
f918b160 VK |
144 | /** |
145 | * Global variables | |
146 | */ | |
967893bb | 147 | UINT32 g_dwFlags = AF_ENABLE_ACTIONS | AF_ENABLE_AUTOLOAD; |
b123ecb3 | 148 | UINT32 g_failFlags = 0; |
bf3b7f79 VK |
149 | TCHAR g_szLogFile[MAX_PATH] = AGENT_DEFAULT_LOG; |
150 | TCHAR g_szSharedSecret[MAX_SECRET_LENGTH] = _T("admin"); | |
151 | TCHAR g_szConfigFile[MAX_PATH] = AGENT_DEFAULT_CONFIG; | |
152 | TCHAR g_szFileStore[MAX_PATH] = AGENT_DEFAULT_FILE_STORE; | |
153 | TCHAR g_szDataDirectory[MAX_PATH] = AGENT_DEFAULT_DATA_DIR; | |
154 | TCHAR g_szPlatformSuffix[MAX_PSUFFIX_LENGTH] = _T(""); | |
155 | TCHAR g_szConfigServer[MAX_DB_STRING] = _T("not_set"); | |
156 | TCHAR g_szRegistrar[MAX_DB_STRING] = _T("not_set"); | |
157 | TCHAR g_szListenAddress[MAX_PATH] = _T("*"); | |
6ca3b41c | 158 | TCHAR g_szConfigIncludeDir[MAX_PATH] = AGENT_DEFAULT_CONFIG_D; |
b123ecb3 | 159 | TCHAR g_szConfigPolicyDir[MAX_PATH] = AGENT_DEFAULT_CONFIG_D; |
169fa953 | 160 | TCHAR g_szLogParserDirectory[MAX_PATH] = _T(""); |
0df58041 | 161 | TCHAR g_masterAgent[MAX_PATH] = _T("not_set"); |
489b117b | 162 | TCHAR g_szSNMPTrapListenAddress[MAX_PATH] = _T("*"); |
9c786c0f | 163 | UINT16 g_wListenPort = AGENT_LISTEN_PORT; |
9319c166 | 164 | ObjectArray<ServerInfo> g_serverList(8, 8, true); |
967893bb VK |
165 | UINT32 g_dwServerCount = 0; |
166 | UINT32 g_dwExecTimeout = 2000; // External process execution timeout in milliseconds | |
014fbefc | 167 | UINT32 g_dwSNMPTimeout = 1500; |
5039dede | 168 | time_t g_tmAgentStartTime; |
967893bb VK |
169 | UINT32 g_dwStartupDelay = 0; |
170 | UINT32 g_dwMaxSessions = 32; | |
489b117b | 171 | UINT32 g_dwSNMPTrapPort = 162; |
89d79e7b | 172 | UINT32 g_longRunningQueryThreshold = 250; |
9cf1b53c VK |
173 | UINT32 g_dcReconciliationBlockSize = 1024; |
174 | UINT32 g_dcReconciliationTimeout = 15000; | |
1304b91d | 175 | UINT32 g_dcMaxCollectorPoolSize = 64; |
3f635e1b | 176 | UINT32 g_zoneId = 0; |
685508a7 | 177 | UINT16 g_syslogListenPort = 514; |
9c786c0f VK |
178 | #ifdef _WIN32 |
179 | UINT16 g_sessionAgentPort = 28180; | |
180 | #else | |
181 | UINT16 g_sessionAgentPort = 0; | |
182 | #endif | |
74a1472d | 183 | Config *g_config = NULL; |
5039dede | 184 | #ifdef _WIN32 |
967893bb | 185 | UINT32 g_dwIdleTimeout = 60; // Session idle timeout |
5039dede | 186 | #else |
967893bb | 187 | UINT32 g_dwIdleTimeout = 120; // Session idle timeout |
5039dede AK |
188 | #endif |
189 | ||
968031d9 | 190 | #if !defined(_WIN32) |
bf3b7f79 | 191 | TCHAR g_szPidFile[MAX_PATH] = _T("/var/run/nxagentd.pid"); |
5039dede AK |
192 | #endif |
193 | ||
8e334368 VK |
194 | /** |
195 | * Static variables | |
196 | */ | |
bf3b7f79 VK |
197 | static TCHAR *m_pszActionList = NULL; |
198 | static TCHAR *m_pszShellActionList = NULL; | |
199 | static TCHAR *m_pszServerList = NULL; | |
200 | static TCHAR *m_pszControlServerList = NULL; | |
201 | static TCHAR *m_pszMasterServerList = NULL; | |
202 | static TCHAR *m_pszSubagentList = NULL; | |
203 | static TCHAR *m_pszExtParamList = NULL; | |
b5ded63e | 204 | static TCHAR *m_pszExtListsList = NULL; |
bf3b7f79 | 205 | static TCHAR *m_pszShExtParamList = NULL; |
9795113c | 206 | static TCHAR *m_pszParamProviderList = NULL; |
204ace22 | 207 | static TCHAR *m_pszExtSubagentList = NULL; |
83b20bab | 208 | static TCHAR *m_pszAppAgentList = NULL; |
842378a4 | 209 | static TCHAR *s_serverConnectionList = NULL; |
76b42c1e VK |
210 | static UINT32 s_enabledCiphers = 0xFFFF; |
211 | static THREAD s_sessionWatchdogThread = INVALID_THREAD_HANDLE; | |
212 | static THREAD s_listenerThread = INVALID_THREAD_HANDLE; | |
213 | static THREAD s_eventSenderThread = INVALID_THREAD_HANDLE; | |
214 | static THREAD s_snmpTrapReceiverThread = INVALID_THREAD_HANDLE; | |
215 | static THREAD s_snmpTrapSenderThread = INVALID_THREAD_HANDLE; | |
685508a7 VK |
216 | static THREAD s_syslogReceiverThread = INVALID_THREAD_HANDLE; |
217 | static THREAD s_syslogSenderThread = INVALID_THREAD_HANDLE; | |
76b42c1e | 218 | static THREAD s_masterAgentListenerThread = INVALID_THREAD_HANDLE; |
842378a4 | 219 | static THREAD s_tunnelManagerThread = INVALID_THREAD_HANDLE; |
040f4cef | 220 | static TCHAR s_processToWaitFor[MAX_PATH] = _T(""); |
e5e015dd | 221 | static TCHAR s_dumpDir[MAX_PATH] = _T("C:\\"); |
458b5d2b | 222 | static UINT64 s_maxLogSize = 16384 * 1024; |
76b42c1e VK |
223 | static UINT32 s_logHistorySize = 4; |
224 | static UINT32 s_logRotationMode = NXLOG_ROTATION_BY_SIZE; | |
e5e015dd | 225 | static TCHAR s_dailyLogFileSuffix[64] = _T(""); |
5a0d14cf | 226 | static TCHAR s_executableName[MAX_PATH]; |
2df047f4 | 227 | static UINT32 s_debugLevel = (UINT32)NXCONFIG_UNINITIALIZED_VALUE; |
5039dede | 228 | |
53720bbf | 229 | static CONDITION s_subAgentsStopCondition = INVALID_CONDITION_HANDLE; |
968031d9 | 230 | #if defined(_WIN32) |
76b42c1e | 231 | static CONDITION s_shutdownCondition = INVALID_CONDITION_HANDLE; |
5039dede AK |
232 | #endif |
233 | ||
968031d9 | 234 | #if !defined(_WIN32) |
76b42c1e | 235 | static pid_t s_pid; |
5039dede AK |
236 | #endif |
237 | ||
f918b160 VK |
238 | /** |
239 | * Configuration file template | |
240 | */ | |
5039dede AK |
241 | static NX_CFG_TEMPLATE m_cfgTemplate[] = |
242 | { | |
e2e66145 VK |
243 | { _T("Action"), CT_STRING_LIST, '\n', 0, 0, 0, &m_pszActionList, NULL }, |
244 | { _T("ActionShellExec"), CT_STRING_LIST, '\n', 0, 0, 0, &m_pszShellActionList, NULL }, | |
245 | { _T("AppAgent"), CT_STRING_LIST, '\n', 0, 0, 0, &m_pszAppAgentList, NULL }, | |
4e0e77e6 | 246 | { _T("BackgroundLogWriter"), CT_BOOLEAN, 0, 0, AF_BACKGROUND_LOG_WRITER, 0, &g_dwFlags, NULL }, |
e2e66145 VK |
247 | { _T("ControlServers"), CT_STRING_LIST, ',', 0, 0, 0, &m_pszControlServerList, NULL }, |
248 | { _T("CreateCrashDumps"), CT_BOOLEAN, 0, 0, AF_CATCH_EXCEPTIONS, 0, &g_dwFlags, NULL }, | |
1304b91d | 249 | { _T("DataCollectionThreadPoolSize"), CT_LONG, 0, 0, 0, 0, &g_dcMaxCollectorPoolSize, NULL }, |
e2e66145 | 250 | { _T("DataDirectory"), CT_STRING, 0, 0, MAX_PATH, 0, g_szDataDirectory, NULL }, |
9cf1b53c VK |
251 | { _T("DataReconciliationBlockSize"), CT_LONG, 0, 0, 0, 0, &g_dcReconciliationBlockSize, NULL }, |
252 | { _T("DataReconciliationTimeout"), CT_LONG, 0, 0, 0, 0, &g_dcReconciliationTimeout, NULL }, | |
e5e015dd | 253 | { _T("DailyLogFileSuffix"), CT_STRING, 0, 0, 64, 0, s_dailyLogFileSuffix, NULL }, |
2df047f4 | 254 | { _T("DebugLevel"), CT_LONG, 0, 0, 0, 0, &s_debugLevel, &s_debugLevel }, |
6239e6a4 VK |
255 | { _T("DisableIPv4"), CT_BOOLEAN, 0, 0, AF_DISABLE_IPV4, 0, &g_dwFlags, NULL }, |
256 | { _T("DisableIPv6"), CT_BOOLEAN, 0, 0, AF_DISABLE_IPV6, 0, &g_dwFlags, NULL }, | |
e5e015dd | 257 | { _T("DumpDirectory"), CT_STRING, 0, 0, MAX_PATH, 0, s_dumpDir, NULL }, |
e2e66145 | 258 | { _T("EnableActions"), CT_BOOLEAN, 0, 0, AF_ENABLE_ACTIONS, 0, &g_dwFlags, NULL }, |
76b42c1e | 259 | { _T("EnabledCiphers"), CT_LONG, 0, 0, 0, 0, &s_enabledCiphers, NULL }, |
e2e66145 VK |
260 | { _T("EnableControlConnector"), CT_BOOLEAN, 0, 0, AF_ENABLE_CONTROL_CONNECTOR, 0, &g_dwFlags, NULL }, |
261 | { _T("EnableProxy"), CT_BOOLEAN, 0, 0, AF_ENABLE_PROXY, 0, &g_dwFlags, NULL }, | |
262 | { _T("EnableSNMPProxy"), CT_BOOLEAN, 0, 0, AF_ENABLE_SNMP_PROXY, 0, &g_dwFlags, NULL }, | |
489b117b | 263 | { _T("EnableSNMPTrapProxy"), CT_BOOLEAN, 0, 0, AF_ENABLE_SNMP_TRAP_PROXY, 0, &g_dwFlags, NULL }, |
685508a7 | 264 | { _T("EnableSyslogProxy"), CT_BOOLEAN, 0, 0, AF_ENABLE_SYSLOG_PROXY, 0, &g_dwFlags, NULL }, |
e2e66145 VK |
265 | { _T("EnableSubagentAutoload"), CT_BOOLEAN, 0, 0, AF_ENABLE_AUTOLOAD, 0, &g_dwFlags, NULL }, |
266 | { _T("EnableWatchdog"), CT_BOOLEAN, 0, 0, AF_ENABLE_WATCHDOG, 0, &g_dwFlags, NULL }, | |
07ca7d19 | 267 | { _T("EncryptedSharedSecret"), CT_STRING, 0, 0, MAX_SECRET_LENGTH, 0, g_szSharedSecret, NULL }, |
e2e66145 VK |
268 | { _T("ExecTimeout"), CT_LONG, 0, 0, 0, 0, &g_dwExecTimeout, NULL }, |
269 | { _T("ExternalMasterAgent"), CT_STRING, 0, 0, MAX_PATH, 0, g_masterAgent, NULL }, | |
270 | { _T("ExternalParameter"), CT_STRING_LIST, '\n', 0, 0, 0, &m_pszExtParamList, NULL }, | |
b5ded63e | 271 | { _T("ExternalList"), CT_STRING_LIST, '\n', 0, 0, 0, &m_pszExtListsList, NULL }, |
e2e66145 VK |
272 | { _T("ExternalParameterShellExec"), CT_STRING_LIST, '\n', 0, 0, 0, &m_pszShExtParamList, NULL }, |
273 | { _T("ExternalParametersProvider"), CT_STRING_LIST, '\n', 0, 0, 0, &m_pszParamProviderList, NULL }, | |
274 | { _T("ExternalSubagent"), CT_STRING_LIST, '\n', 0, 0, 0, &m_pszExtSubagentList, NULL }, | |
275 | { _T("FileStore"), CT_STRING, 0, 0, MAX_PATH, 0, g_szFileStore, NULL }, | |
276 | { _T("FullCrashDumps"), CT_BOOLEAN, 0, 0, AF_WRITE_FULL_DUMP, 0, &g_dwFlags, NULL }, | |
277 | { _T("ListenAddress"), CT_STRING, 0, 0, MAX_PATH, 0, g_szListenAddress, NULL }, | |
278 | { _T("ListenPort"), CT_WORD, 0, 0, 0, 0, &g_wListenPort, NULL }, | |
279 | { _T("LogFile"), CT_STRING, 0, 0, MAX_PATH, 0, g_szLogFile, NULL }, | |
76b42c1e VK |
280 | { _T("LogHistorySize"), CT_LONG, 0, 0, 0, 0, &s_logHistorySize, NULL }, |
281 | { _T("LogRotationMode"), CT_LONG, 0, 0, 0, 0, &s_logRotationMode, NULL }, | |
e2e66145 | 282 | { _T("LogUnresolvedSymbols"), CT_BOOLEAN, 0, 0, AF_LOG_UNRESOLVED_SYMBOLS, 0, &g_dwFlags, NULL }, |
89d79e7b | 283 | { _T("LongRunningQueryThreshold"), CT_LONG, 0, 0, 0, 0, &g_longRunningQueryThreshold, NULL }, |
e2e66145 | 284 | { _T("MasterServers"), CT_STRING_LIST, ',', 0, 0, 0, &m_pszMasterServerList, NULL }, |
458b5d2b | 285 | { _T("MaxLogSize"), CT_SIZE_BYTES, 0, 0, 0, 0, &s_maxLogSize, NULL }, |
e2e66145 VK |
286 | { _T("MaxSessions"), CT_LONG, 0, 0, 0, 0, &g_dwMaxSessions, NULL }, |
287 | { _T("PlatformSuffix"), CT_STRING, 0, 0, MAX_PSUFFIX_LENGTH, 0, g_szPlatformSuffix, NULL }, | |
288 | { _T("RequireAuthentication"), CT_BOOLEAN, 0, 0, AF_REQUIRE_AUTH, 0, &g_dwFlags, NULL }, | |
289 | { _T("RequireEncryption"), CT_BOOLEAN, 0, 0, AF_REQUIRE_ENCRYPTION, 0, &g_dwFlags, NULL }, | |
842378a4 | 290 | { _T("ServerConnection"), CT_STRING_LIST, '\n', 0, 0, 0, &s_serverConnectionList, NULL }, |
e2e66145 VK |
291 | { _T("Servers"), CT_STRING_LIST, ',', 0, 0, 0, &m_pszServerList, NULL }, |
292 | { _T("SessionIdleTimeout"), CT_LONG, 0, 0, 0, 0, &g_dwIdleTimeout, NULL }, | |
9c786c0f | 293 | { _T("SessionAgentPort"), CT_WORD, 0, 0, 0, 0, &g_sessionAgentPort, NULL }, |
e2e66145 VK |
294 | { _T("SharedSecret"), CT_STRING, 0, 0, MAX_SECRET_LENGTH, 0, g_szSharedSecret, NULL }, |
295 | { _T("SNMPTimeout"), CT_LONG, 0, 0, 0, 0, &g_dwSNMPTimeout, NULL }, | |
4d31be20 | 296 | { _T("SNMPTrapListenAddress"), CT_STRING, 0, 0, MAX_PATH, 0, &g_szSNMPTrapListenAddress, NULL }, |
489b117b | 297 | { _T("SNMPTrapPort"), CT_LONG, 0, 0, 0, 0, &g_dwSNMPTrapPort, NULL }, |
e2e66145 VK |
298 | { _T("StartupDelay"), CT_LONG, 0, 0, 0, 0, &g_dwStartupDelay, NULL }, |
299 | { _T("SubAgent"), CT_STRING_LIST, '\n', 0, 0, 0, &m_pszSubagentList, NULL }, | |
685508a7 | 300 | { _T("SyslogListenPort"), CT_WORD, 0, 0, 0, 0, &g_syslogListenPort, NULL }, |
e2e66145 | 301 | { _T("TimeOut"), CT_IGNORE, 0, 0, 0, 0, NULL, NULL }, |
040f4cef | 302 | { _T("WaitForProcess"), CT_STRING, 0, 0, MAX_PATH, 0, s_processToWaitFor, NULL }, |
3f635e1b | 303 | { _T("ZoneId"), CT_LONG, 0, 0, 0, 0, &g_zoneId, NULL }, |
e2e66145 | 304 | { _T(""), CT_END_OF_LIST, 0, 0, 0, 0, NULL, NULL } |
5039dede AK |
305 | }; |
306 | ||
0f506caa VK |
307 | /** |
308 | * Help text | |
309 | */ | |
f3387429 VK |
310 | static TCHAR m_szHelpText[] = |
311 | _T("Usage: nxagentd [options]\n") | |
312 | _T("Where valid options are:\n") | |
313 | _T(" -c <file> : Use configuration file <file> (default ") AGENT_DEFAULT_CONFIG _T(")\n") | |
e77b1f4e | 314 | _T(" -C : Load configuration file, dump resulting configuration, and exit\n") |
f3387429 VK |
315 | _T(" -d : Run as daemon/service\n") |
316 | _T(" -D <level> : Set debug level (0..9)\n") | |
9f96fc88 | 317 | #ifdef _WIN32 |
f3387429 | 318 | _T(" -e <name> : Windows event source name\n") |
9f96fc88 | 319 | #endif |
f3387429 | 320 | _T(" -f : Run in foreground\n") |
e4ec73da VK |
321 | #if !defined(_WIN32) |
322 | _T(" -g <gid> : Chhange group ID to <gid> after start\n") | |
323 | #endif | |
f3387429 | 324 | _T(" -h : Display help and exit\n") |
5039dede | 325 | #ifdef _WIN32 |
f3387429 VK |
326 | _T(" -H : Hide agent's window when in standalone mode\n") |
327 | _T(" -i : Installed Windows service must be interactive\n") | |
328 | _T(" -I : Install Windows service\n") | |
5039dede | 329 | #endif |
f918b160 | 330 | _T(" -K : Shutdown all connected external sub-agents\n") |
f3387429 | 331 | _T(" -M <addr> : Download config from management server <addr>\n") |
9f96fc88 | 332 | #ifdef _WIN32 |
f3387429 VK |
333 | _T(" -n <name> : Service name\n") |
334 | _T(" -N <name> : Service display name\n") | |
9f96fc88 | 335 | #endif |
968031d9 | 336 | #if !defined(_WIN32) |
f3387429 | 337 | _T(" -p : Path to pid file (default: /var/run/nxagentd.pid)\n") |
5039dede | 338 | #endif |
f3387429 VK |
339 | _T(" -P <text> : Set platform suffix to <text>\n") |
340 | _T(" -r <addr> : Register agent on management server <addr>\n") | |
5039dede | 341 | #ifdef _WIN32 |
f3387429 VK |
342 | _T(" -R : Remove Windows service\n") |
343 | _T(" -s : Start Windows servive\n") | |
344 | _T(" -S : Stop Windows service\n") | |
e4ec73da VK |
345 | #endif |
346 | #if !defined(_WIN32) | |
347 | _T(" -u <uid> : Chhange user ID to <uid> after start\n") | |
5039dede | 348 | #endif |
f3387429 VK |
349 | _T(" -v : Display version and exit\n") |
350 | _T("\n"); | |
5039dede | 351 | |
9319c166 VK |
352 | /** |
353 | * Server info: constructor | |
354 | */ | |
355 | ServerInfo::ServerInfo(const TCHAR *name, bool control, bool master) | |
356 | { | |
357 | #ifdef UNICODE | |
358 | m_name = MBStringFromWideString(name); | |
359 | #else | |
360 | m_name = strdup(name); | |
361 | #endif | |
362 | ||
363 | char *p = strchr(m_name, '/'); | |
364 | if (p != NULL) | |
365 | { | |
366 | *p = 0; | |
367 | p++; | |
368 | m_address = InetAddress::resolveHostName(m_name); | |
8c75ad41 | 369 | if (m_address.isValid()) |
9319c166 VK |
370 | { |
371 | int bits = strtol(p, NULL, 10); | |
7ff72ee9 | 372 | if ((bits >= 0) && (bits <= ((m_address.getFamily() == AF_INET) ? 32 : 128))) |
8c75ad41 | 373 | m_address.setMaskBits(bits); |
9319c166 VK |
374 | } |
375 | m_redoResolve = false; | |
376 | } | |
377 | else | |
378 | { | |
379 | m_address = InetAddress::resolveHostName(m_name); | |
380 | m_redoResolve = true; | |
381 | } | |
382 | ||
383 | m_control = control; | |
384 | m_master = master; | |
385 | m_lastResolveTime = time(NULL); | |
386 | m_mutex = MutexCreate(); | |
387 | } | |
388 | ||
389 | /** | |
390 | * Server info: destructor | |
391 | */ | |
392 | ServerInfo::~ServerInfo() | |
393 | { | |
9319c166 VK |
394 | safe_free(m_name); |
395 | MutexDestroy(m_mutex); | |
396 | } | |
397 | ||
398 | /** | |
399 | * Server info: resolve hostname if needed | |
400 | */ | |
401 | void ServerInfo::resolve() | |
402 | { | |
403 | time_t now = time(NULL); | |
404 | time_t age = now - m_lastResolveTime; | |
8c75ad41 | 405 | if ((age >= 3600) || ((age > 300) && !m_address.isValid())) |
9319c166 | 406 | { |
9319c166 VK |
407 | m_address = InetAddress::resolveHostName(m_name); |
408 | m_lastResolveTime = now; | |
409 | } | |
410 | } | |
411 | ||
412 | /** | |
413 | * Server info: match address | |
414 | */ | |
8c75ad41 | 415 | bool ServerInfo::match(const InetAddress &addr) |
9319c166 VK |
416 | { |
417 | MutexLock(m_mutex); | |
418 | if (m_redoResolve) | |
419 | resolve(); | |
8c75ad41 | 420 | bool result = m_address.isValid() ? m_address.contain(addr) : false; |
9319c166 VK |
421 | MutexUnlock(m_mutex); |
422 | return result; | |
423 | } | |
424 | ||
5039dede AK |
425 | #ifdef _WIN32 |
426 | ||
83b20bab VK |
427 | /** |
428 | * Get our own console window handle (an alternative to Microsoft's GetConsoleWindow) | |
429 | */ | |
203e9d8a | 430 | static HWND GetConsoleHWND() |
5039dede AK |
431 | { |
432 | HWND hWnd; | |
433 | DWORD wpid, cpid; | |
434 | ||
435 | cpid = GetCurrentProcessId(); | |
436 | while(1) | |
437 | { | |
438 | hWnd = FindWindowEx(NULL, NULL, _T("ConsoleWindowClass"), NULL); | |
439 | if (hWnd == NULL) | |
440 | break; | |
cc022855 | 441 | |
5039dede AK |
442 | GetWindowThreadProcessId(hWnd, &wpid); |
443 | if (cpid == wpid) | |
444 | break; | |
445 | } | |
446 | ||
447 | return hWnd; | |
448 | } | |
449 | ||
83b20bab VK |
450 | /** |
451 | * Get proc address and write log file | |
452 | */ | |
5039dede AK |
453 | static FARPROC GetProcAddressAndLog(HMODULE hModule, LPCSTR procName) |
454 | { | |
455 | FARPROC ptr; | |
456 | ||
457 | ptr = GetProcAddress(hModule, procName); | |
458 | if ((ptr == NULL) && (g_dwFlags & AF_LOG_UNRESOLVED_SYMBOLS)) | |
459 | nxlog_write(MSG_NO_FUNCTION, EVENTLOG_WARNING_TYPE, "s", procName); | |
460 | return ptr; | |
461 | } | |
462 | ||
83b20bab VK |
463 | /** |
464 | * Shutdown thread (created by H_RestartAgent) | |
465 | */ | |
5039dede AK |
466 | static THREAD_RESULT THREAD_CALL ShutdownThread(void *pArg) |
467 | { | |
8e954797 | 468 | DebugPrintf(INVALID_INDEX, 1, _T("Shutdown thread started")); |
5039dede AK |
469 | Shutdown(); |
470 | ExitProcess(0); | |
471 | return THREAD_OK; // Never reached | |
472 | } | |
473 | ||
474 | #endif /* _WIN32 */ | |
475 | ||
134c8b79 | 476 | |
acc04d96 VK |
477 | /** |
478 | * Restart agent | |
479 | */ | |
060c5a11 | 480 | static LONG H_RestartAgent(const TCHAR *action, StringList *args, const TCHAR *data, AbstractCommSession *session) |
5039dede | 481 | { |
5b2c3e2d VK |
482 | DebugPrintf(INVALID_INDEX, 1, _T("H_RestartAgent() called")); |
483 | ||
5039dede | 484 | TCHAR szCmdLine[4096], szPlatformSuffixOption[MAX_PSUFFIX_LENGTH + 16]; |
5039dede AK |
485 | |
486 | if (g_szPlatformSuffix[0] != 0) | |
487 | { | |
488 | _sntprintf(szPlatformSuffixOption, MAX_PSUFFIX_LENGTH + 16, _T("-P \"%s\" "), g_szPlatformSuffix); | |
489 | } | |
490 | else | |
491 | { | |
492 | szPlatformSuffixOption[0] = 0; | |
493 | } | |
494 | ||
495 | #ifdef _WIN32 | |
5a0d14cf | 496 | _sntprintf(szCmdLine, 4096, _T("\"%s\" -c \"%s\" -n \"%s\" -e \"%s\" %s%s%s%s%s-D %d %s-X %u"), s_executableName, |
93599cfd VK |
497 | g_szConfigFile, g_windowsServiceName, g_windowsEventSourceName, |
498 | (g_dwFlags & AF_DAEMON) ? _T("-d ") : _T(""), | |
5039dede AK |
499 | (g_dwFlags & AF_HIDE_WINDOW) ? _T("-H ") : _T(""), |
500 | (g_dwFlags & AF_CENTRAL_CONFIG) ? _T("-M ") : _T(""), | |
501 | (g_dwFlags & AF_CENTRAL_CONFIG) ? g_szConfigServer : _T(""), | |
502 | (g_dwFlags & AF_CENTRAL_CONFIG) ? _T(" ") : _T(""), | |
2df047f4 | 503 | s_debugLevel, szPlatformSuffixOption, |
5039dede | 504 | (g_dwFlags & AF_DAEMON) ? 0 : GetCurrentProcessId()); |
c303351c | 505 | DebugPrintf(INVALID_INDEX, 1, _T("Restarting agent with command line '%s'"), szCmdLine); |
5039dede | 506 | |
5a0d14cf VK |
507 | DWORD dwResult; |
508 | STARTUPINFO si; | |
509 | PROCESS_INFORMATION pi; | |
cc022855 | 510 | |
5039dede AK |
511 | // Fill in process startup info structure |
512 | memset(&si, 0, sizeof(STARTUPINFO)); | |
513 | si.cb = sizeof(STARTUPINFO); | |
514 | ||
515 | // Create new process | |
cc022855 | 516 | if (!CreateProcess(NULL, szCmdLine, NULL, NULL, FALSE, |
5039dede AK |
517 | (g_dwFlags & AF_DAEMON) ? (CREATE_NO_WINDOW | DETACHED_PROCESS) : (CREATE_NEW_CONSOLE), |
518 | NULL, NULL, &si, &pi)) | |
519 | { | |
520 | nxlog_write(MSG_CREATE_PROCESS_FAILED, EVENTLOG_ERROR_TYPE, "se", szCmdLine, GetLastError()); | |
521 | dwResult = ERR_EXEC_FAILED; | |
522 | } | |
523 | else | |
524 | { | |
525 | // Close all handles | |
526 | CloseHandle(pi.hThread); | |
527 | CloseHandle(pi.hProcess); | |
528 | dwResult = ERR_SUCCESS; | |
529 | } | |
530 | if ((dwResult == ERR_SUCCESS) && (!(g_dwFlags & AF_DAEMON))) | |
531 | { | |
532 | if (g_dwFlags & AF_HIDE_WINDOW) | |
533 | { | |
76b42c1e | 534 | ConditionSet(s_shutdownCondition); |
5039dede AK |
535 | } |
536 | else | |
537 | { | |
538 | ThreadCreate(ShutdownThread, 0, NULL); | |
539 | } | |
540 | } | |
541 | return dwResult; | |
542 | #else | |
5a0d14cf | 543 | _sntprintf(szCmdLine, 4096, _T("\"%s\" -c \"%s\" %s%s%s%s-D %d %s-X %lu"), s_executableName, |
5039dede AK |
544 | g_szConfigFile, (g_dwFlags & AF_DAEMON) ? _T("-d ") : _T(""), |
545 | (g_dwFlags & AF_CENTRAL_CONFIG) ? _T("-M ") : _T(""), | |
546 | (g_dwFlags & AF_CENTRAL_CONFIG) ? g_szConfigServer : _T(""), | |
547 | (g_dwFlags & AF_CENTRAL_CONFIG) ? _T(" ") : _T(""), | |
2df047f4 | 548 | (int)s_debugLevel, szPlatformSuffixOption, |
76b42c1e | 549 | (unsigned long)s_pid); |
5b2c3e2d | 550 | DebugPrintf(INVALID_INDEX, 1, _T("Restarting agent with command line '%s'"), szCmdLine); |
9fcdfda7 | 551 | return ExecuteCommand(szCmdLine, NULL, NULL); |
5039dede | 552 | #endif |
5039dede AK |
553 | } |
554 | ||
acc04d96 VK |
555 | /** |
556 | * This function writes message from subagent to agent's log | |
557 | */ | |
c303351c | 558 | static void WriteSubAgentMsg(int logLevel, int debugLevel, const TCHAR *pszMsg) |
5039dede | 559 | { |
c303351c | 560 | if (logLevel == EVENTLOG_DEBUG_TYPE) |
5039dede | 561 | { |
2df047f4 | 562 | if (debugLevel <= (int)s_debugLevel) |
c303351c | 563 | nxlog_write(MSG_DEBUG, EVENTLOG_DEBUG_TYPE, "s", pszMsg); |
5039dede AK |
564 | } |
565 | else | |
566 | { | |
c303351c | 567 | nxlog_write(MSG_SUBAGENT_MSG, logLevel, "s", pszMsg); |
5039dede AK |
568 | } |
569 | } | |
570 | ||
acc04d96 VK |
571 | /** |
572 | * Signal handler for UNIX platforms | |
573 | */ | |
968031d9 | 574 | #if !defined(_WIN32) |
5039dede AK |
575 | |
576 | static THREAD_RESULT THREAD_CALL SignalHandler(void *pArg) | |
577 | { | |
578 | sigset_t signals; | |
579 | int nSignal; | |
580 | ||
581 | sigemptyset(&signals); | |
582 | sigaddset(&signals, SIGTERM); | |
583 | sigaddset(&signals, SIGINT); | |
5039dede AK |
584 | sigaddset(&signals, SIGSEGV); |
585 | sigaddset(&signals, SIGHUP); | |
586 | sigaddset(&signals, SIGUSR1); | |
587 | sigaddset(&signals, SIGUSR2); | |
95e2329a VK |
588 | #if !defined(__sun) && !defined(_AIX) && !defined(__hpux) |
589 | sigaddset(&signals, SIGPIPE); | |
590 | #endif | |
5039dede AK |
591 | |
592 | sigprocmask(SIG_BLOCK, &signals, NULL); | |
593 | ||
594 | while(1) | |
595 | { | |
596 | if (sigwait(&signals, &nSignal) == 0) | |
597 | { | |
598 | switch(nSignal) | |
599 | { | |
600 | case SIGTERM: | |
601 | case SIGINT: | |
602 | goto stop_handler; | |
603 | case SIGSEGV: | |
604 | abort(); | |
605 | break; | |
606 | default: | |
607 | break; | |
608 | } | |
609 | } | |
610 | else | |
611 | { | |
612 | ThreadSleepMs(100); | |
613 | } | |
614 | } | |
615 | ||
616 | stop_handler: | |
617 | sigprocmask(SIG_UNBLOCK, &signals, NULL); | |
618 | return THREAD_OK; | |
619 | } | |
620 | ||
621 | #endif | |
622 | ||
acc04d96 VK |
623 | /** |
624 | * Load platform subagent | |
625 | */ | |
626 | static void LoadPlatformSubagent() | |
5039dede | 627 | { |
acc04d96 VK |
628 | #ifdef _WIN32 |
629 | LoadSubAgent(_T("WINNT.NSM")); | |
5039dede | 630 | #else |
968031d9 | 631 | #if HAVE_SYS_UTSNAME_H && !defined(_STATIC_AGENT) |
5039dede | 632 | struct utsname un; |
f3387429 | 633 | TCHAR szName[MAX_PATH]; |
5039dede AK |
634 | int i; |
635 | ||
636 | if (uname(&un) != -1) | |
637 | { | |
638 | // Convert system name to lowercase | |
639 | for(i = 0; un.sysname[i] != 0; i++) | |
640 | un.sysname[i] = tolower(un.sysname[i]); | |
641 | if (!strcmp(un.sysname, "hp-ux")) | |
642 | strcpy(un.sysname, "hpux"); | |
f31c22b3 | 643 | _sntprintf(szName, MAX_PATH, _T("%hs.nsm"), un.sysname); |
5039dede AK |
644 | LoadSubAgent(szName); |
645 | } | |
646 | #endif | |
5039dede | 647 | #endif |
acc04d96 | 648 | } |
5039dede | 649 | |
acc04d96 VK |
650 | /** |
651 | * Send file to server (subagent API) | |
652 | */ | |
cc022855 | 653 | static bool SendFileToServer(void *session, UINT32 requestId, const TCHAR *file, long offset) |
6173bea8 | 654 | { |
4685a2ad | 655 | if (session == NULL) |
0137b9f7 | 656 | return false; |
cc022855 | 657 | return ((CommSession *)session)->sendFile(requestId, file, offset); |
6173bea8 VK |
658 | } |
659 | ||
83b20bab VK |
660 | /** |
661 | * Parser server list | |
662 | */ | |
9319c166 | 663 | static void ParseServerList(TCHAR *serverList, bool isControl, bool isMaster) |
968031d9 VK |
664 | { |
665 | TCHAR *pItem, *pEnd; | |
666 | ||
667 | for(pItem = pEnd = serverList; pEnd != NULL && *pItem != 0; pItem = pEnd + 1) | |
668 | { | |
f3387429 | 669 | pEnd = _tcschr(pItem, _T(',')); |
968031d9 VK |
670 | if (pEnd != NULL) |
671 | *pEnd = 0; | |
672 | StrStrip(pItem); | |
673 | ||
9319c166 | 674 | g_serverList.add(new ServerInfo(pItem, isControl, isMaster)); |
968031d9 VK |
675 | } |
676 | free(serverList); | |
677 | } | |
678 | ||
ed950274 VK |
679 | /** |
680 | * Agent initialization | |
681 | */ | |
c6fbf758 | 682 | BOOL Initialize() |
5039dede | 683 | { |
bf3b7f79 | 684 | TCHAR *pItem, *pEnd; |
5039dede | 685 | |
2df047f4 VK |
686 | if (s_debugLevel == (UINT32)NXCONFIG_UNINITIALIZED_VALUE) |
687 | s_debugLevel = 0; | |
e2e66145 | 688 | |
f31c22b3 VK |
689 | if (!_tcscmp(g_szDataDirectory, _T("{default}"))) |
690 | { | |
1039d7ee | 691 | GetNetXMSDirectory(nxDirData, g_szDataDirectory); |
f31c22b3 | 692 | } |
f31c22b3 | 693 | |
b123ecb3 | 694 | //Initialize config policy folder |
695 | TCHAR tail = g_szDataDirectory[_tcslen(g_szDataDirectory) - 1]; | |
696 | _sntprintf(g_szConfigPolicyDir, MAX_PATH, _T("%s%s%s"), g_szDataDirectory, | |
697 | ((tail != '\\') && (tail != '/')) ? FS_PATH_SEPARATOR : _T(""), | |
698 | CONFIG_AP_FOLDER FS_PATH_SEPARATOR); | |
699 | CreateFolder(g_szConfigPolicyDir); | |
9cf1b53c VK |
700 | |
701 | // Load configuration | |
b123ecb3 | 702 | g_config->loadConfigDirectory(g_szConfigPolicyDir, _T("agent")); |
703 | g_config->parseTemplate(_T("agent"), m_cfgTemplate); | |
704 | ||
5039dede | 705 | // Open log file |
9fcdfda7 VK |
706 | if (!nxlog_open((g_dwFlags & AF_USE_SYSLOG) ? NXAGENTD_SYSLOG_NAME : g_szLogFile, |
707 | ((g_dwFlags & AF_USE_SYSLOG) ? NXLOG_USE_SYSLOG : 0) | | |
4e0e77e6 VK |
708 | ((g_dwFlags & AF_BACKGROUND_LOG_WRITER) ? NXLOG_BACKGROUND_WRITER : 0) | |
709 | ((g_dwFlags & AF_DAEMON) ? 0 : NXLOG_PRINT_TO_STDOUT), | |
9fcdfda7 | 710 | _T("NXAGENTD.EXE"), |
5039dede | 711 | #ifdef _WIN32 |
2df047f4 | 712 | 0, NULL, MSG_DEBUG)) |
5039dede | 713 | #else |
2df047f4 | 714 | g_dwNumMessages, g_szMessages, MSG_DEBUG)) |
5039dede | 715 | #endif |
9fcdfda7 | 716 | { |
b123ecb3 | 717 | //TODO: set flag that log have been opened with errors |
718 | s_debugLevel = 1; | |
c5459490 | 719 | g_failFlags |= FAIL_OPEN_LOG; |
b123ecb3 | 720 | nxlog_open(NXAGENTD_SYSLOG_NAME, NXLOG_USE_SYSLOG | |
721 | ((g_dwFlags & AF_BACKGROUND_LOG_WRITER) ? NXLOG_BACKGROUND_WRITER : 0) | | |
722 | ((g_dwFlags & AF_DAEMON) ? 0 : NXLOG_PRINT_TO_STDOUT), | |
723 | _T("NXAGENTD.EXE"), | |
724 | #ifdef _WIN32 | |
725 | 0, NULL, MSG_DEBUG); | |
726 | #else | |
727 | g_dwNumMessages, g_szMessages, MSG_DEBUG); | |
728 | #endif | |
729 | _ftprintf(stderr, _T("ERROR: Cannot open log file, logs will be written to syslog with debug level 1\n")); | |
730 | ||
9fcdfda7 | 731 | } |
b123ecb3 | 732 | else |
733 | { | |
734 | if (!(g_dwFlags & AF_USE_SYSLOG)) | |
735 | { | |
458b5d2b | 736 | if (!nxlog_set_rotation_policy((int)s_logRotationMode, s_maxLogSize, (int)s_logHistorySize, s_dailyLogFileSuffix)) |
b123ecb3 | 737 | if (!(g_dwFlags & AF_DAEMON)) |
738 | _tprintf(_T("WARNING: cannot set log rotation policy; using default values\n")); | |
739 | } | |
740 | } | |
203e9d8a | 741 | nxlog_write(MSG_USE_CONFIG_D, NXLOG_INFO, "s", g_szConfigIncludeDir); |
2df047f4 VK |
742 | nxlog_write(MSG_DEBUG_LEVEL, NXLOG_INFO, "d", s_debugLevel); |
743 | nxlog_set_debug_level(s_debugLevel); | |
374afd7b | 744 | |
0df58041 VK |
745 | if (_tcscmp(g_masterAgent, _T("not_set"))) |
746 | { | |
747 | g_dwFlags |= AF_SUBAGENT_LOADER; | |
748 | DebugPrintf(INVALID_INDEX, 1, _T("Switched to external subagent loader mode, master agent address is %s"), g_masterAgent); | |
749 | } | |
750 | ||
f31c22b3 | 751 | DebugPrintf(INVALID_INDEX, 1, _T("Data directory: %s"), g_szDataDirectory); |
c72b812a | 752 | CreateFolder(g_szDataDirectory); |
f31c22b3 | 753 | |
3df8bccd | 754 | //Initialize log parser policy folder |
b123ecb3 | 755 | tail = g_szDataDirectory[_tcslen(g_szDataDirectory) - 1]; |
3df8bccd Z |
756 | _sntprintf(g_szLogParserDirectory, MAX_PATH, _T("%s%s%s"), g_szDataDirectory, |
757 | ((tail != '\\') && (tail != '/')) ? FS_PATH_SEPARATOR : _T(""), | |
169fa953 | 758 | LOGPARSER_AP_FOLDER FS_PATH_SEPARATOR); |
3df8bccd Z |
759 | DebugPrintf(INVALID_INDEX, 6, _T("Log parser policy directory: %s"), g_szLogParserDirectory); |
760 | CreateFolder(g_szLogParserDirectory); | |
b123ecb3 | 761 | DebugPrintf(INVALID_INDEX, 6, _T("Configuration policy directory: %s"), g_szConfigPolicyDir); |
13276419 | 762 | CreateFolder(g_szFileStore); |
763 | ||
5039dede AK |
764 | #ifdef _WIN32 |
765 | WSADATA wsaData; | |
1ddf3f0c VK |
766 | int wrc = WSAStartup(MAKEWORD(2, 2), &wsaData); |
767 | if (wrc != 0) | |
5039dede | 768 | { |
1ddf3f0c | 769 | nxlog_write(MSG_WSASTARTUP_FAILED, NXLOG_ERROR, "e", wrc); |
5039dede AK |
770 | return FALSE; |
771 | } | |
5039dede AK |
772 | #endif |
773 | ||
5039dede | 774 | // Initialize API for subagents |
53720bbf | 775 | s_subAgentsStopCondition = ConditionCreate(TRUE); |
6fbaa926 | 776 | InitSubAgentAPI(WriteSubAgentMsg, SendTrap, SendTrap, EnumerateSessions, FindServerSession, |
7f6ecb6d | 777 | SendFileToServer, PushData, GetLocalDatabaseHandle, s_subAgentsStopCondition, g_szDataDirectory); |
bf3b7f79 | 778 | DebugPrintf(INVALID_INDEX, 1, _T("Subagent API initialized")); |
5039dede AK |
779 | |
780 | // Initialize cryptografy | |
2df047f4 | 781 | if (!InitCryptoLib(s_enabledCiphers)) |
5039dede AK |
782 | { |
783 | nxlog_write(MSG_INIT_CRYPTO_FAILED, EVENTLOG_ERROR_TYPE, "e", WSAGetLastError()); | |
784 | return FALSE; | |
785 | } | |
786 | ||
01116597 VK |
787 | // Initialize libssl - it is not used by core agent |
788 | // but may be needed by some subagents. Allowing first load of libssl by | |
789 | // subagent via dlopen() may lead to undesired side effects | |
790 | #ifdef _WITH_ENCRYPTION | |
791 | SSL_library_init(); | |
792 | SSL_load_error_strings(); | |
793 | #endif | |
794 | ||
c72b812a VK |
795 | DBInit(MSG_DB_LIBRARY, MSG_SQL_ERROR); |
796 | ||
c99dbf89 VK |
797 | if (!OpenLocalDatabase()) |
798 | { | |
799 | nxlog_write(MSG_LOCAL_DB_OPEN_FAILED, NXLOG_ERROR, NULL); | |
800 | } | |
801 | ||
0df58041 VK |
802 | if (!(g_dwFlags & AF_SUBAGENT_LOADER)) |
803 | { | |
83191808 VK |
804 | if (g_dwFlags & AF_ENABLE_SNMP_PROXY) |
805 | { | |
806 | g_snmpProxyThreadPool = ThreadPoolCreate(2, 128, _T("SNMPPROXY")); | |
807 | } | |
0df58041 VK |
808 | InitSessionList(); |
809 | ||
810 | // Initialize built-in parameters | |
811 | if (!InitParameterList()) | |
812 | return FALSE; | |
5039dede | 813 | |
842378a4 VK |
814 | // Parse outgoing server connection (tunnel) list |
815 | if (s_serverConnectionList != NULL) | |
816 | ParseTunnelList(s_serverConnectionList); | |
817 | ||
968031d9 | 818 | // Parse server lists |
968031d9 | 819 | if (m_pszMasterServerList != NULL) |
5cb555d8 VK |
820 | ParseServerList(m_pszMasterServerList, true, true); |
821 | if (m_pszControlServerList != NULL) | |
822 | ParseServerList(m_pszControlServerList, true, false); | |
823 | if (m_pszServerList != NULL) | |
824 | ParseServerList(m_pszServerList, false, false); | |
5039dede | 825 | |
0df58041 | 826 | // Add built-in actions |
f3387429 | 827 | AddAction(_T("Agent.Restart"), AGENT_ACTION_SUBAGENT, NULL, H_RestartAgent, _T("CORE"), _T("Restart agent")); |
9cf1b53c | 828 | |
0df58041 | 829 | // Load platform subagents |
968031d9 | 830 | #if !defined(_WIN32) |
0df58041 | 831 | InitStaticSubagents(); |
5039dede | 832 | #endif |
0df58041 VK |
833 | if (g_dwFlags & AF_ENABLE_AUTOLOAD) |
834 | { | |
0df58041 | 835 | LoadPlatformSubagent(); |
0df58041 VK |
836 | } |
837 | } | |
5039dede AK |
838 | |
839 | // Wait for external process if requested | |
040f4cef | 840 | if (s_processToWaitFor[0] != 0) |
5039dede | 841 | { |
040f4cef VK |
842 | DebugPrintf(INVALID_INDEX, 1, _T("Waiting for process %s"), s_processToWaitFor); |
843 | if (!WaitForProcess(s_processToWaitFor)) | |
844 | nxlog_write(MSG_WAITFORPROCESS_FAILED, EVENTLOG_ERROR_TYPE, "s", s_processToWaitFor); | |
5039dede AK |
845 | } |
846 | ||
847 | // Load other subagents | |
848 | if (m_pszSubagentList != NULL) | |
849 | { | |
e6c91aac | 850 | for(pItem = pEnd = m_pszSubagentList; pEnd != NULL && *pItem != 0; pItem = pEnd + 1) |
5039dede | 851 | { |
f3387429 | 852 | pEnd = _tcschr(pItem, _T('\n')); |
5039dede AK |
853 | if (pEnd != NULL) |
854 | *pEnd = 0; | |
855 | StrStrip(pItem); | |
856 | LoadSubAgent(pItem); | |
857 | } | |
858 | free(m_pszSubagentList); | |
859 | } | |
860 | ||
861 | // Parse action list | |
862 | if (m_pszActionList != NULL) | |
863 | { | |
e6c91aac | 864 | for(pItem = pEnd = m_pszActionList; pEnd != NULL && *pItem != 0; pItem = pEnd + 1) |
5039dede | 865 | { |
f3387429 | 866 | pEnd = _tcschr(pItem, _T('\n')); |
5039dede AK |
867 | if (pEnd != NULL) |
868 | *pEnd = 0; | |
869 | StrStrip(pItem); | |
870 | if (!AddActionFromConfig(pItem, FALSE)) | |
871 | nxlog_write(MSG_ADD_ACTION_FAILED, EVENTLOG_WARNING_TYPE, "s", pItem); | |
872 | } | |
873 | free(m_pszActionList); | |
874 | } | |
875 | if (m_pszShellActionList != NULL) | |
876 | { | |
e6c91aac | 877 | for(pItem = pEnd = m_pszShellActionList; pEnd != NULL && *pItem != 0; pItem = pEnd + 1) |
5039dede | 878 | { |
bf3b7f79 | 879 | pEnd = _tcschr(pItem, _T('\n')); |
5039dede AK |
880 | |
881 | if (pEnd != NULL) | |
882 | *pEnd = 0; | |
883 | StrStrip(pItem); | |
884 | if (!AddActionFromConfig(pItem, TRUE)) | |
885 | nxlog_write(MSG_ADD_ACTION_FAILED, EVENTLOG_WARNING_TYPE, "s", pItem); | |
886 | } | |
887 | free(m_pszShellActionList); | |
888 | } | |
889 | ||
890 | // Parse external parameters list | |
891 | if (m_pszExtParamList != NULL) | |
892 | { | |
e6c91aac | 893 | for(pItem = pEnd = m_pszExtParamList; pEnd != NULL && *pItem != 0; pItem = pEnd + 1) |
5039dede | 894 | { |
f3387429 | 895 | pEnd = _tcschr(pItem, _T('\n')); |
5039dede AK |
896 | if (pEnd != NULL) |
897 | *pEnd = 0; | |
898 | StrStrip(pItem); | |
b5ded63e | 899 | if (!AddExternalParameter(pItem, FALSE, FALSE)) |
5039dede AK |
900 | nxlog_write(MSG_ADD_EXT_PARAM_FAILED, EVENTLOG_WARNING_TYPE, "s", pItem); |
901 | } | |
902 | free(m_pszExtParamList); | |
903 | } | |
904 | if (m_pszShExtParamList != NULL) | |
905 | { | |
e6c91aac | 906 | for(pItem = pEnd = m_pszShExtParamList; pEnd != NULL && *pItem != 0; pItem = pEnd + 1) |
5039dede | 907 | { |
f3387429 | 908 | pEnd = _tcschr(pItem, _T('\n')); |
5039dede AK |
909 | if (pEnd != NULL) |
910 | *pEnd = 0; | |
911 | StrStrip(pItem); | |
b5ded63e | 912 | if (!AddExternalParameter(pItem, TRUE, FALSE)) |
5039dede AK |
913 | nxlog_write(MSG_ADD_EXT_PARAM_FAILED, EVENTLOG_WARNING_TYPE, "s", pItem); |
914 | } | |
915 | free(m_pszShExtParamList); | |
916 | } | |
917 | ||
b5ded63e AK |
918 | // Parse external lists |
919 | if (m_pszExtListsList != NULL) | |
920 | { | |
921 | for(pItem = pEnd = m_pszExtListsList; pEnd != NULL && *pItem != 0; pItem = pEnd + 1) | |
922 | { | |
923 | pEnd = _tcschr(pItem, _T('\n')); | |
924 | if (pEnd != NULL) | |
925 | *pEnd = 0; | |
926 | StrStrip(pItem); | |
927 | if (!AddExternalParameter(pItem, FALSE, TRUE)) | |
928 | nxlog_write(MSG_ADD_EXT_PARAM_FAILED, EVENTLOG_WARNING_TYPE, "s", pItem); | |
929 | } | |
930 | free(m_pszExtListsList); | |
931 | } | |
932 | ||
9795113c VK |
933 | // Parse external parameters providers list |
934 | if (m_pszParamProviderList != NULL) | |
935 | { | |
936 | for(pItem = pEnd = m_pszParamProviderList; pEnd != NULL && *pItem != 0; pItem = pEnd + 1) | |
937 | { | |
f3387429 | 938 | pEnd = _tcschr(pItem, _T('\n')); |
9795113c VK |
939 | if (pEnd != NULL) |
940 | *pEnd = 0; | |
941 | StrStrip(pItem); | |
942 | if (!AddParametersProvider(pItem)) | |
943 | nxlog_write(MSG_ADD_PARAM_PROVIDER_FAILED, EVENTLOG_WARNING_TYPE, "s", pItem); | |
944 | } | |
945 | free(m_pszParamProviderList); | |
946 | } | |
947 | ||
204ace22 | 948 | // Parse external subagents list |
0df58041 | 949 | if (!(g_dwFlags & AF_SUBAGENT_LOADER) && (m_pszExtSubagentList != NULL)) |
204ace22 VK |
950 | { |
951 | for(pItem = pEnd = m_pszExtSubagentList; pEnd != NULL && *pItem != 0; pItem = pEnd + 1) | |
952 | { | |
f3387429 | 953 | pEnd = _tcschr(pItem, _T('\n')); |
204ace22 VK |
954 | if (pEnd != NULL) |
955 | *pEnd = 0; | |
956 | StrStrip(pItem); | |
957 | if (!AddExternalSubagent(pItem)) | |
958 | nxlog_write(MSG_ADD_EXTERNAL_SUBAGENT_FAILED, EVENTLOG_WARNING_TYPE, "s", pItem); | |
959 | } | |
960 | free(m_pszExtSubagentList); | |
961 | } | |
962 | ||
83b20bab VK |
963 | // Parse application agents list |
964 | if (!(g_dwFlags & AF_SUBAGENT_LOADER) && (m_pszAppAgentList != NULL)) | |
965 | { | |
966 | for(pItem = pEnd = m_pszAppAgentList; pEnd != NULL && *pItem != 0; pItem = pEnd + 1) | |
967 | { | |
968 | pEnd = _tcschr(pItem, _T('\n')); | |
969 | if (pEnd != NULL) | |
970 | *pEnd = 0; | |
971 | StrStrip(pItem); | |
972 | RegisterApplicationAgent(pItem); | |
973 | } | |
974 | free(m_pszAppAgentList); | |
975 | } | |
976 | ||
5039dede AK |
977 | ThreadSleep(1); |
978 | ||
979 | // If StartupDelay is greater than zero, then wait | |
980 | if (g_dwStartupDelay > 0) | |
981 | { | |
982 | if (g_dwFlags & AF_DAEMON) | |
983 | { | |
984 | ThreadSleep(g_dwStartupDelay); | |
985 | } | |
986 | else | |
987 | { | |
967893bb | 988 | UINT32 i; |
5039dede | 989 | |
f3387429 | 990 | _tprintf(_T("XXXXXX%*s]\rWAIT ["), g_dwStartupDelay, _T(" ")); |
5039dede AK |
991 | fflush(stdout); |
992 | for(i = 0; i < g_dwStartupDelay; i++) | |
993 | { | |
994 | ThreadSleep(1); | |
f3387429 | 995 | _puttc(_T('.'), stdout); |
5039dede AK |
996 | fflush(stdout); |
997 | } | |
f3387429 | 998 | _tprintf(_T("\n")); |
5039dede AK |
999 | } |
1000 | } | |
1001 | ||
9795113c VK |
1002 | StartParamProvidersPoller(); |
1003 | ||
5039dede AK |
1004 | // Agent start time |
1005 | g_tmAgentStartTime = time(NULL); | |
1006 | ||
76b42c1e | 1007 | s_eventSenderThread = ThreadCreateEx(TrapSender, 0, NULL); |
489b117b | 1008 | |
685508a7 | 1009 | if (g_dwFlags & AF_ENABLE_SNMP_TRAP_PROXY) |
489b117b | 1010 | { |
76b42c1e VK |
1011 | s_snmpTrapSenderThread = ThreadCreateEx(SNMPTrapSender, 0, NULL); |
1012 | s_snmpTrapReceiverThread = ThreadCreateEx(SNMPTrapReceiver, 0, NULL); | |
489b117b | 1013 | } |
1014 | ||
685508a7 VK |
1015 | if (g_dwFlags & AF_ENABLE_SYSLOG_PROXY) |
1016 | { | |
1017 | s_syslogSenderThread = ThreadCreateEx(SyslogSender, 0, NULL); | |
1018 | s_syslogReceiverThread = ThreadCreateEx(SyslogReceiver, 0, NULL); | |
1019 | } | |
1020 | ||
0df58041 VK |
1021 | if (g_dwFlags & AF_SUBAGENT_LOADER) |
1022 | { | |
76b42c1e | 1023 | s_masterAgentListenerThread = ThreadCreateEx(MasterAgentListener, 0, NULL); |
0df58041 VK |
1024 | } |
1025 | else | |
1026 | { | |
1027 | // Start network listener and session watchdog | |
87fff547 | 1028 | StartLocalDataCollector(); |
76b42c1e VK |
1029 | s_listenerThread = ThreadCreateEx(ListenerThread, 0, NULL); |
1030 | s_sessionWatchdogThread = ThreadCreateEx(SessionWatchdog, 0, NULL); | |
0bd64860 | 1031 | StartPushConnector(); |
a2a24e9d | 1032 | StartStorageDiscoveryConnector(); |
9c786c0f | 1033 | StartSessionAgentConnector(); |
f918b160 VK |
1034 | if (g_dwFlags & AF_ENABLE_CONTROL_CONNECTOR) |
1035 | { | |
1036 | StartControlConnector(); | |
1037 | } | |
a854d114 VK |
1038 | |
1039 | if (g_dwFlags & AF_REGISTER) | |
1040 | { | |
1041 | RegisterOnServer(g_szRegistrar); | |
1042 | } | |
842378a4 VK |
1043 | |
1044 | s_tunnelManagerThread = ThreadCreateEx(TunnelManager, 0, NULL); | |
1045 | } | |
5039dede | 1046 | |
968031d9 | 1047 | #if defined(_WIN32) |
76b42c1e | 1048 | s_shutdownCondition = ConditionCreate(TRUE); |
5039dede AK |
1049 | #endif |
1050 | ThreadSleep(1); | |
1051 | ||
9fcdfda7 | 1052 | // Start watchdog process |
0df58041 VK |
1053 | if (!(g_dwFlags & AF_SUBAGENT_LOADER)) |
1054 | { | |
1055 | if (g_dwFlags & AF_ENABLE_WATCHDOG) | |
1056 | StartWatchdog(); | |
1057 | } | |
9fcdfda7 | 1058 | |
359784de | 1059 | // Delete file used for upgrade if exists |
ac7a2e92 TD |
1060 | TCHAR upgradeFileName[MAX_PATH]; |
1061 | ReadRegistryAsString(_T("upgrade.file"), upgradeFileName, MAX_PATH, _T("")); | |
1062 | if(upgradeFileName[0] != 0) | |
1063 | { | |
1064 | _tremove(upgradeFileName); | |
1065 | DeleteRegistryEntry(_T("upgrade.file")); | |
1066 | } | |
80f2318b | 1067 | |
b123ecb3 | 1068 | //Update policy inventory according to files that exist on file system |
1069 | UpdatePolicyInventory(); | |
1070 | ||
5039dede AK |
1071 | return TRUE; |
1072 | } | |
1073 | ||
605fc935 VK |
1074 | /** |
1075 | * Shutdown agent | |
1076 | */ | |
0df58041 | 1077 | void Shutdown() |
5039dede | 1078 | { |
8e954797 | 1079 | DebugPrintf(INVALID_INDEX, 2, _T("Shutdown() called")); |
9fcdfda7 VK |
1080 | if (g_dwFlags & AF_ENABLE_WATCHDOG) |
1081 | StopWatchdog(); | |
1082 | ||
5039dede | 1083 | g_dwFlags |= AF_SHUTDOWN; |
53720bbf | 1084 | ConditionSet(s_subAgentsStopCondition); |
0df58041 VK |
1085 | |
1086 | if (g_dwFlags & AF_SUBAGENT_LOADER) | |
1087 | { | |
639088d4 | 1088 | // TODO: shall we inform master agent listener about shutdown? |
76b42c1e | 1089 | //ThreadJoin(s_masterAgentListenerThread); |
0df58041 VK |
1090 | } |
1091 | else | |
1092 | { | |
87fff547 | 1093 | ShutdownLocalDataCollector(); |
0df58041 | 1094 | ShutdownTrapSender(); |
76b42c1e VK |
1095 | ThreadJoin(s_sessionWatchdogThread); |
1096 | ThreadJoin(s_listenerThread); | |
842378a4 | 1097 | ThreadJoin(s_tunnelManagerThread); |
0df58041 | 1098 | } |
76b42c1e | 1099 | ThreadJoin(s_eventSenderThread); |
685508a7 | 1100 | if (g_dwFlags & AF_ENABLE_SNMP_TRAP_PROXY) |
489b117b | 1101 | { |
1102 | ShutdownSNMPTrapSender(); | |
76b42c1e VK |
1103 | ThreadJoin(s_snmpTrapReceiverThread); |
1104 | ThreadJoin(s_snmpTrapSenderThread); | |
489b117b | 1105 | } |
685508a7 VK |
1106 | if (g_dwFlags & AF_ENABLE_SYSLOG_PROXY) |
1107 | { | |
1108 | ShutdownSyslogSender(); | |
1109 | ThreadJoin(s_syslogReceiverThread); | |
1110 | ThreadJoin(s_syslogSenderThread); | |
1111 | } | |
5039dede | 1112 | |
13783551 VK |
1113 | DestroySessionList(); |
1114 | MsgWaitQueue::shutdown(); | |
d87ddcc2 | 1115 | |
83191808 VK |
1116 | if (g_dwFlags & AF_ENABLE_SNMP_PROXY) |
1117 | { | |
1118 | ThreadPoolDestroy(g_snmpProxyThreadPool); | |
1119 | } | |
1120 | ||
5039dede | 1121 | UnloadAllSubAgents(); |
c72b812a | 1122 | CloseLocalDatabase(); |
5039dede AK |
1123 | nxlog_write(MSG_AGENT_STOPPED, EVENTLOG_INFORMATION_TYPE, NULL); |
1124 | nxlog_close(); | |
1125 | ||
74a1472d VK |
1126 | delete g_config; |
1127 | ||
5039dede AK |
1128 | // Notify main thread about shutdown |
1129 | #ifdef _WIN32 | |
76b42c1e | 1130 | ConditionSet(s_shutdownCondition); |
5039dede | 1131 | #endif |
cc022855 | 1132 | |
5039dede | 1133 | // Remove PID file |
968031d9 | 1134 | #if !defined(_WIN32) |
f3387429 | 1135 | _tremove(g_szPidFile); |
5039dede AK |
1136 | #endif |
1137 | } | |
1138 | ||
605fc935 VK |
1139 | /** |
1140 | * Common Main() | |
1141 | */ | |
8ec102ac | 1142 | void Main() |
5039dede | 1143 | { |
8ec102ac | 1144 | nxlog_write(MSG_AGENT_STARTED, NXLOG_INFO, NULL); |
5039dede AK |
1145 | |
1146 | if (g_dwFlags & AF_DAEMON) | |
1147 | { | |
968031d9 | 1148 | #if defined(_WIN32) |
76b42c1e | 1149 | ConditionWait(s_shutdownCondition, INFINITE); |
5039dede AK |
1150 | #else |
1151 | StartMainLoop(SignalHandler, NULL); | |
1152 | #endif | |
1153 | } | |
1154 | else | |
1155 | { | |
1156 | #if defined(_WIN32) | |
1157 | if (g_dwFlags & AF_HIDE_WINDOW) | |
1158 | { | |
1159 | HWND hWnd; | |
1160 | ||
1161 | hWnd = GetConsoleHWND(); | |
1162 | if (hWnd != NULL) | |
1163 | ShowWindow(hWnd, SW_HIDE); | |
76b42c1e | 1164 | ConditionWait(s_shutdownCondition, INFINITE); |
5039dede AK |
1165 | ThreadSleep(1); |
1166 | } | |
1167 | else | |
1168 | { | |
f3387429 | 1169 | _tprintf(_T("Agent running. Press ESC to shutdown.\n")); |
5039dede AK |
1170 | while(1) |
1171 | { | |
3973f74b | 1172 | if (_getch() == 27) |
5039dede AK |
1173 | break; |
1174 | } | |
f3387429 | 1175 | _tprintf(_T("Agent shutting down...\n")); |
5039dede AK |
1176 | Shutdown(); |
1177 | } | |
5039dede | 1178 | #else |
f3387429 | 1179 | _tprintf(_T("Agent running. Press Ctrl+C to shutdown.\n")); |
5039dede | 1180 | StartMainLoop(SignalHandler, NULL); |
f3387429 | 1181 | _tprintf(_T("\nStopping agent...\n")); |
5039dede AK |
1182 | #endif |
1183 | } | |
1184 | } | |
1185 | ||
605fc935 VK |
1186 | /** |
1187 | * Do necessary actions on agent restart | |
1188 | */ | |
967893bb | 1189 | static void DoRestartActions(UINT32 dwOldPID) |
5039dede AK |
1190 | { |
1191 | #if defined(_WIN32) | |
1192 | if (dwOldPID == 0) | |
1193 | { | |
1194 | // Service | |
1195 | StopAgentService(); | |
1196 | WaitForService(SERVICE_STOPPED); | |
1197 | StartAgentService(); | |
1198 | ExitProcess(0); | |
1199 | } | |
1200 | else | |
1201 | { | |
1202 | HANDLE hProcess; | |
1203 | ||
1204 | hProcess = OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE, FALSE, dwOldPID); | |
1205 | if (hProcess != NULL) | |
1206 | { | |
1207 | if (WaitForSingleObject(hProcess, 60000) == WAIT_TIMEOUT) | |
1208 | { | |
1209 | TerminateProcess(hProcess, 0); | |
1210 | } | |
1211 | CloseHandle(hProcess); | |
1212 | } | |
1213 | } | |
5039dede AK |
1214 | #else |
1215 | int i; | |
1216 | ||
1217 | kill(dwOldPID, SIGTERM); | |
1218 | for(i = 0; i < 30; i++) | |
1219 | { | |
1220 | sleep(2); | |
1221 | if (kill(dwOldPID, SIGCONT) == -1) | |
1222 | break; | |
1223 | } | |
cc022855 | 1224 | |
5039dede AK |
1225 | // Kill previous instance of agent if it's still running |
1226 | if (i == 30) | |
1227 | kill(dwOldPID, SIGKILL); | |
1228 | #endif | |
1229 | } | |
1230 | ||
605fc935 VK |
1231 | /** |
1232 | * Create configuration file | |
1233 | */ | |
f3387429 VK |
1234 | static int CreateConfig(const char *pszServer, const char *pszLogFile, const char *pszFileStore, |
1235 | const char *configIncludeDir, int iNumSubAgents, char **ppszSubAgentList) | |
5039dede AK |
1236 | { |
1237 | FILE *fp; | |
1238 | time_t currTime; | |
1239 | int i; | |
1240 | ||
1241 | if (_taccess(g_szConfigFile, 0) == 0) | |
1242 | return 0; // File already exist, we shouldn't overwrite it | |
1243 | ||
1244 | fp = _tfopen(g_szConfigFile, _T("w")); | |
1245 | if (fp != NULL) | |
1246 | { | |
1247 | currTime = time(NULL); | |
1248 | _ftprintf(fp, _T("#\n# NetXMS agent configuration file\n# Created by agent installer at %s#\n\n"), | |
1249 | _tctime(&currTime)); | |
f3387429 | 1250 | _ftprintf(fp, _T("MasterServers = %hs\nConfigIncludeDir = %hs\nLogFile = %hs\nFileStore = %hs\n"), |
48dd3c80 | 1251 | pszServer, configIncludeDir, pszLogFile, pszFileStore); |
5039dede | 1252 | for(i = 0; i < iNumSubAgents; i++) |
f3387429 | 1253 | _ftprintf(fp, _T("SubAgent = %hs\n"), ppszSubAgentList[i]); |
5039dede AK |
1254 | fclose(fp); |
1255 | } | |
1256 | return (fp != NULL) ? 0 : 2; | |
1257 | } | |
1258 | ||
ed950274 VK |
1259 | /** |
1260 | * Init config | |
1261 | */ | |
e6c91aac VK |
1262 | static void InitConfig() |
1263 | { | |
1264 | g_config = new Config(); | |
8a0dffac | 1265 | g_config->setTopLevelTag(_T("config")); |
c72b812a VK |
1266 | |
1267 | // Set default data directory on Windows | |
1268 | #ifdef _WIN32 | |
1269 | if (SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, g_szDataDirectory) == S_OK) | |
1270 | { | |
1271 | _tcscat(g_szDataDirectory, _T("\\nxagentd")); | |
1272 | } | |
1273 | #endif | |
e6c91aac VK |
1274 | } |
1275 | ||
f918b160 VK |
1276 | /** |
1277 | * Initiate shutdown of connected external subagents | |
1278 | */ | |
1279 | static void InitiateExtSubagentShutdown() | |
1280 | { | |
b368969c VK |
1281 | NXCPMessage msg; |
1282 | msg.setCode(CMD_SHUTDOWN); | |
f918b160 VK |
1283 | if (SendControlMessage(&msg)) |
1284 | _tprintf(_T("Control message sent successfully to master agent\n")); | |
1285 | else | |
1286 | _tprintf(_T("ERROR: Unable to send control message to master agent\n")); | |
1287 | } | |
1288 | ||
e4ec73da VK |
1289 | #ifndef _WIN32 |
1290 | ||
1291 | /** | |
1292 | * Get user ID | |
1293 | */ | |
1294 | static int GetUserId(char *name) | |
1295 | { | |
1296 | char *eptr; | |
1297 | int id = (int)strtol(name, &eptr, 10); | |
1298 | if (*eptr == 0) | |
1299 | return id; | |
1300 | ||
1301 | #if HAVE_GETPWNAM | |
1302 | struct passwd *p = getpwnam(name); | |
1303 | if (p == NULL) | |
1304 | { | |
1305 | _tprintf(_T("Invalid user ID \"%hs\"\n"), name); | |
1306 | return 0; | |
1307 | } | |
1308 | return p->pw_uid; | |
1309 | #else | |
1310 | _tprintf(_T("Invalid user ID \"%hs\"\n"), name); | |
1311 | return 0; | |
1312 | #endif | |
1313 | } | |
1314 | ||
1315 | /** | |
1316 | * Get group ID | |
1317 | */ | |
1318 | static int GetGroupId(char *name) | |
1319 | { | |
1320 | char *eptr; | |
1321 | int id = (int)strtol(name, &eptr, 10); | |
1322 | if (*eptr == 0) | |
1323 | return id; | |
1324 | ||
1325 | #if HAVE_GETGRNAM | |
1326 | struct group *g = getgrnam(name); | |
1327 | if (g == NULL) | |
1328 | { | |
1329 | _tprintf(_T("Invalid group ID \"%hs\"\n"), name); | |
1330 | return 0; | |
1331 | } | |
1332 | return g->gr_gid; | |
1333 | #else | |
1334 | _tprintf(_T("Invalid group ID \"%hs\"\n"), name); | |
1335 | return 0; | |
1336 | #endif | |
1337 | } | |
1338 | ||
1339 | #endif | |
1340 | ||
2295e8f5 VK |
1341 | /** |
1342 | * Application entry point | |
1343 | */ | |
5039dede AK |
1344 | int main(int argc, char *argv[]) |
1345 | { | |
1346 | int ch, iExitCode = 0, iAction = ACTION_RUN_AGENT; | |
1347 | BOOL bRestart = FALSE; | |
967893bb | 1348 | UINT32 dwOldPID, dwMainPID; |
f3387429 | 1349 | char *eptr; |
5039dede | 1350 | #ifdef _WIN32 |
bf3b7f79 | 1351 | TCHAR szModuleName[MAX_PATH]; |
1621a079 VK |
1352 | HKEY hKey; |
1353 | DWORD dwSize; | |
1354 | #else | |
f3387429 | 1355 | TCHAR *pszEnv; |
e4ec73da | 1356 | int uid = 0, gid = 0; |
5039dede AK |
1357 | #endif |
1358 | ||
fe8ea784 | 1359 | InitNetXMSProcess(); |
2295e8f5 | 1360 | |
d40b6356 | 1361 | #if defined(__sun) || defined(_AIX) || defined(__hpux) |
1685d106 VK |
1362 | signal(SIGPIPE, SIG_IGN); |
1363 | signal(SIGHUP, SIG_IGN); | |
1685d106 VK |
1364 | signal(SIGQUIT, SIG_IGN); |
1365 | signal(SIGUSR1, SIG_IGN); | |
1366 | signal(SIGUSR2, SIG_IGN); | |
1367 | #endif | |
1368 | ||
1621a079 VK |
1369 | // Check for alternate config file location |
1370 | #ifdef _WIN32 | |
1371 | if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\NetXMS\\Agent"), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) | |
1372 | { | |
1373 | dwSize = MAX_PATH * sizeof(TCHAR); | |
1374 | RegQueryValueEx(hKey, _T("ConfigFile"), NULL, NULL, (BYTE *)g_szConfigFile, &dwSize); | |
42acd918 | 1375 | dwSize = MAX_PATH * sizeof(TCHAR); |
1621a079 VK |
1376 | RegQueryValueEx(hKey, _T("ConfigIncludeDir"), NULL, NULL, (BYTE *)g_szConfigIncludeDir, &dwSize); |
1377 | RegCloseKey(hKey); | |
1378 | } | |
1379 | #else | |
1380 | pszEnv = _tgetenv(_T("NXAGENTD_CONFIG")); | |
1381 | if (pszEnv != NULL) | |
1382 | nx_strncpy(g_szConfigFile, pszEnv, MAX_PATH); | |
1383 | ||
1384 | pszEnv = _tgetenv(_T("NXAGENTD_CONFIG_D")); | |
1385 | if (pszEnv != NULL) | |
1386 | nx_strncpy(g_szConfigIncludeDir, pszEnv, MAX_PATH); | |
1387 | #endif | |
1388 | ||
5039dede AK |
1389 | // Parse command line |
1390 | if (argc == 1) | |
1391 | iAction = ACTION_HELP; | |
1392 | opterr = 1; | |
1393 | while((ch = getopt(argc, argv, VALID_OPTIONS)) != -1) | |
1394 | { | |
1395 | switch(ch) | |
1396 | { | |
e4ec73da VK |
1397 | case 'c': // Configuration file |
1398 | #ifdef UNICODE | |
1399 | MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, optarg, -1, g_szConfigFile, MAX_PATH); | |
1400 | g_szConfigFile[MAX_PATH - 1] = 0; | |
1401 | #else | |
1402 | nx_strncpy(g_szConfigFile, optarg, MAX_PATH); | |
1403 | #endif | |
5039dede | 1404 | break; |
e4ec73da VK |
1405 | case 'C': // Configuration check only |
1406 | iAction = ACTION_CHECK_CONFIG; | |
f918b160 | 1407 | break; |
5039dede AK |
1408 | case 'd': // Run as daemon |
1409 | g_dwFlags |= AF_DAEMON; | |
1410 | break; | |
5039dede | 1411 | case 'D': // Turn on debug output |
2df047f4 VK |
1412 | s_debugLevel = strtoul(optarg, &eptr, 0); |
1413 | if ((*eptr != 0) || (s_debugLevel > 9)) | |
c303351c VK |
1414 | { |
1415 | fprintf(stderr, "Invalid debug level: %s\n", optarg); | |
1416 | iAction = -1; | |
1417 | iExitCode = 1; | |
1418 | } | |
5039dede | 1419 | break; |
e4ec73da VK |
1420 | case 'f': // Run in foreground |
1421 | g_dwFlags &= ~AF_DAEMON; | |
1422 | break; | |
1423 | #ifndef _WIN32 | |
1424 | case 'g': // set group ID | |
1425 | gid = GetGroupId(optarg); | |
1426 | break; | |
f3387429 | 1427 | #endif |
e4ec73da VK |
1428 | case 'h': // Display help and exit |
1429 | iAction = ACTION_HELP; | |
5039dede | 1430 | break; |
e4ec73da VK |
1431 | #ifdef _WIN32 |
1432 | case 'H': // Hide window | |
1433 | g_dwFlags |= AF_HIDE_WINDOW; | |
1434 | break; | |
1435 | #endif | |
1436 | case 'K': // Shutdown external sub-agents | |
1437 | iAction = ACTION_SHUTDOWN_EXT_AGENTS; | |
1438 | break; | |
1439 | #ifndef _WIN32 | |
5039dede | 1440 | case 'p': // PID file |
f3387429 VK |
1441 | #ifdef UNICODE |
1442 | MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, optarg, -1, g_szPidFile, MAX_PATH); | |
1443 | g_szPidFile[MAX_PATH - 1] = 0; | |
1444 | #else | |
5039dede | 1445 | nx_strncpy(g_szPidFile, optarg, MAX_PATH); |
f3387429 | 1446 | #endif |
5039dede AK |
1447 | break; |
1448 | #endif | |
5039dede AK |
1449 | case 'M': |
1450 | g_dwFlags |= AF_CENTRAL_CONFIG; | |
f3387429 VK |
1451 | #ifdef UNICODE |
1452 | MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, optarg, -1, g_szConfigServer, MAX_DB_STRING); | |
1453 | g_szConfigServer[MAX_DB_STRING - 1] = 0; | |
1454 | #else | |
5039dede | 1455 | nx_strncpy(g_szConfigServer, optarg, MAX_DB_STRING); |
f3387429 | 1456 | #endif |
5039dede AK |
1457 | break; |
1458 | case 'r': | |
1459 | g_dwFlags |= AF_REGISTER; | |
f3387429 VK |
1460 | #ifdef UNICODE |
1461 | MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, optarg, -1, g_szRegistrar, MAX_DB_STRING); | |
1462 | g_szRegistrar[MAX_DB_STRING - 1] = 0; | |
1463 | #else | |
5039dede | 1464 | nx_strncpy(g_szRegistrar, optarg, MAX_DB_STRING); |
f3387429 | 1465 | #endif |
5039dede AK |
1466 | break; |
1467 | case 'P': // Platform suffix | |
f3387429 VK |
1468 | #ifdef UNICODE |
1469 | MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, optarg, -1, g_szPlatformSuffix, MAX_PSUFFIX_LENGTH); | |
1470 | g_szPlatformSuffix[MAX_PSUFFIX_LENGTH - 1] = 0; | |
1471 | #else | |
5039dede | 1472 | nx_strncpy(g_szPlatformSuffix, optarg, MAX_PSUFFIX_LENGTH); |
f3387429 | 1473 | #endif |
5039dede | 1474 | break; |
e4ec73da VK |
1475 | #ifndef _WIN32 |
1476 | case 'u': // set user ID | |
1477 | uid = GetUserId(optarg); | |
1478 | break; | |
1479 | #endif | |
1480 | case 'v': // Print version and exit | |
f62b7eab | 1481 | _tprintf(_T("NetXMS Core Agent Version ") AGENT_VERSION_STRING _T(" Build ") NETXMS_VERSION_BUILD_STRING _T(" (") NETXMS_BUILD_TAG _T(")") IS_UNICODE_BUILD_STRING _T("\n")); |
e4ec73da | 1482 | iAction = ACTION_NONE; |
5039dede | 1483 | break; |
9fcdfda7 VK |
1484 | case 'W': // Watchdog process |
1485 | iAction = ACTION_RUN_WATCHDOG; | |
1486 | dwMainPID = strtoul(optarg, NULL, 10); | |
1487 | break; | |
e4ec73da VK |
1488 | case 'X': // Agent is being restarted |
1489 | bRestart = TRUE; | |
1490 | dwOldPID = strtoul(optarg, NULL, 10); | |
1491 | break; | |
5039dede AK |
1492 | case 'Z': // Create configuration file |
1493 | iAction = ACTION_CREATE_CONFIG; | |
f3387429 VK |
1494 | #ifdef UNICODE |
1495 | MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, optarg, -1, g_szConfigFile, MAX_PATH); | |
1496 | g_szConfigFile[MAX_PATH - 1] = 0; | |
1497 | #else | |
5039dede | 1498 | nx_strncpy(g_szConfigFile, optarg, MAX_PATH); |
f3387429 | 1499 | #endif |
5039dede AK |
1500 | break; |
1501 | #ifdef _WIN32 | |
175bd003 VK |
1502 | case 'i': |
1503 | g_dwFlags |= AF_INTERACTIVE_SERVICE; | |
1504 | break; | |
5039dede AK |
1505 | case 'I': // Install Windows service |
1506 | iAction = ACTION_INSTALL_SERVICE; | |
1507 | break; | |
1508 | case 'R': // Remove Windows service | |
1509 | iAction = ACTION_REMOVE_SERVICE; | |
1510 | break; | |
1511 | case 's': // Start Windows service | |
1512 | iAction = ACTION_START_SERVICE; | |
1513 | break; | |
1514 | case 'S': // Stop Windows service | |
1515 | iAction = ACTION_STOP_SERVICE; | |
1516 | break; | |
1517 | case 'E': // Install Windows event source | |
1518 | iAction = ACTION_INSTALL_EVENT_SOURCE; | |
1519 | break; | |
1520 | case 'U': // Remove Windows event source | |
1521 | iAction = ACTION_REMOVE_EVENT_SOURCE; | |
1522 | break; | |
9f96fc88 | 1523 | case 'e': // Event source name |
7ee7f8bc VK |
1524 | #ifdef UNICODE |
1525 | MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, optarg, -1, g_windowsEventSourceName, MAX_PATH); | |
1526 | g_windowsEventSourceName[MAX_PATH - 1] = 0; | |
1527 | #else | |
9f96fc88 | 1528 | nx_strncpy(g_windowsEventSourceName, optarg, MAX_PATH); |
7ee7f8bc | 1529 | #endif |
9f96fc88 VK |
1530 | break; |
1531 | case 'n': // Service name | |
7ee7f8bc VK |
1532 | #ifdef UNICODE |
1533 | MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, optarg, -1, g_windowsServiceName, MAX_PATH); | |
1534 | g_windowsServiceName[MAX_PATH - 1] = 0; | |
1535 | #else | |
9f96fc88 | 1536 | nx_strncpy(g_windowsServiceName, optarg, MAX_PATH); |
7ee7f8bc | 1537 | #endif |
9f96fc88 VK |
1538 | break; |
1539 | case 'N': // Service display name | |
f3387429 VK |
1540 | #ifdef UNICODE |
1541 | MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, optarg, -1, g_windowsServiceDisplayName, MAX_PATH); | |
1542 | g_windowsServiceDisplayName[MAX_PATH - 1] = 0; | |
1543 | #else | |
9f96fc88 | 1544 | nx_strncpy(g_windowsServiceDisplayName, optarg, MAX_PATH); |
f3387429 | 1545 | #endif |
9f96fc88 | 1546 | break; |
5039dede AK |
1547 | #endif |
1548 | case '?': | |
1549 | iAction = ACTION_HELP; | |
1550 | iExitCode = 1; | |
1551 | break; | |
1552 | default: | |
1553 | break; | |
1554 | } | |
1555 | } | |
1556 | ||
968031d9 | 1557 | #if !defined(_WIN32) |
e4ec73da VK |
1558 | if (gid > 0) |
1559 | { | |
1560 | if (setgid(gid) != 0) | |
1561 | _tprintf(_T("setgid(%d) call failed (%s)\n"), gid, _tcserror(errno)); | |
1562 | } | |
1563 | if (uid > 0) | |
1564 | { | |
1565 | if (setuid(uid) != 0) | |
1566 | _tprintf(_T("setuid(%d) call failed (%s)\n"), uid, _tcserror(errno)); | |
1567 | } | |
1568 | ||
5039dede AK |
1569 | if (!_tcscmp(g_szConfigFile, _T("{search}"))) |
1570 | { | |
f31c22b3 VK |
1571 | TCHAR path[MAX_PATH] = _T(""); |
1572 | const TCHAR *homeDir = _tgetenv(_T("NETXMS_HOME")); | |
1573 | if (homeDir != NULL) | |
1574 | { | |
1575 | _sntprintf(path, MAX_PATH, _T("%s/etc/nxagentd.conf"), homeDir); | |
1576 | } | |
1577 | if ((path[0] != 0) && (_taccess(path, 4) == 0)) | |
1578 | { | |
1579 | _tcscpy(g_szConfigFile, path); | |
1580 | } | |
1581 | else if (_taccess(PREFIX _T("/etc/nxagentd.conf"), 4) == 0) | |
5039dede | 1582 | { |
f3387429 | 1583 | _tcscpy(g_szConfigFile, PREFIX _T("/etc/nxagentd.conf")); |
5039dede | 1584 | } |
a1716ea0 VK |
1585 | else if (_taccess(_T("/Database/etc/nxagentd.conf"), 4) == 0) // for ZeroShell |
1586 | { | |
1587 | _tcscpy(g_szConfigFile, _T("/Database/etc/nxagentd.conf")); | |
1588 | } | |
f3387429 | 1589 | else if (_taccess(_T("/usr/etc/nxagentd.conf"), 4) == 0) |
5039dede | 1590 | { |
f3387429 | 1591 | _tcscpy(g_szConfigFile, _T("/usr/etc/nxagentd.conf")); |
5039dede AK |
1592 | } |
1593 | else | |
1594 | { | |
f3387429 | 1595 | _tcscpy(g_szConfigFile, _T("/etc/nxagentd.conf")); |
5039dede AK |
1596 | } |
1597 | } | |
80ce37ac | 1598 | if (!_tcscmp(g_szConfigIncludeDir, _T("{search}"))) |
abf35d58 | 1599 | { |
f31c22b3 VK |
1600 | TCHAR path[MAX_PATH] = _T(""); |
1601 | const TCHAR *homeDir = _tgetenv(_T("NETXMS_HOME")); | |
1602 | if (homeDir != NULL) | |
1603 | { | |
1604 | _sntprintf(path, MAX_PATH, _T("%s/etc/nxagentd.conf.d"), homeDir); | |
1605 | } | |
1606 | if ((path[0] != 0) && (_taccess(path, 4) == 0)) | |
1607 | { | |
1608 | _tcscpy(g_szConfigIncludeDir, path); | |
1609 | } | |
1610 | else if (_taccess(PREFIX _T("/etc/nxagentd.conf.d"), 4) == 0) | |
abf35d58 | 1611 | { |
f3387429 | 1612 | _tcscpy(g_szConfigIncludeDir, PREFIX _T("/etc/nxagentd.conf.d")); |
abf35d58 | 1613 | } |
a1716ea0 VK |
1614 | else if (_taccess(_T("/Database/etc/nxagentd.conf.d"), 4) == 0) |
1615 | { | |
1616 | _tcscpy(g_szConfigIncludeDir, _T("/Database/etc/nxagentd.conf.d")); | |
1617 | } | |
f3387429 | 1618 | else if (_taccess(_T("/usr/etc/nxagentd.conf.d"), 4) == 0) |
abf35d58 | 1619 | { |
f3387429 | 1620 | _tcscpy(g_szConfigIncludeDir, _T("/usr/etc/nxagentd.conf.d")); |
abf35d58 VK |
1621 | } |
1622 | else | |
1623 | { | |
f3387429 | 1624 | _tcscpy(g_szConfigIncludeDir, _T("/etc/nxagentd.conf.d")); |
abf35d58 VK |
1625 | } |
1626 | } | |
1039d7ee VK |
1627 | #else |
1628 | if (!_tcscmp(g_szConfigFile, _T("{search}"))) | |
1629 | { | |
1630 | TCHAR path[MAX_PATH]; | |
1631 | GetNetXMSDirectory(nxDirEtc, path); | |
1632 | _tcscat(path, _T("\\nxagentd.conf")); | |
1633 | if (_taccess(path, 4) == 0) | |
1634 | { | |
1635 | _tcscpy(g_szConfigFile, path); | |
1636 | } | |
1637 | else | |
1638 | { | |
1639 | _tcscpy(g_szConfigFile, _T("C:\\nxagentd.conf")); | |
1640 | } | |
1641 | } | |
1642 | if (!_tcscmp(g_szConfigIncludeDir, _T("{search}"))) | |
1643 | { | |
1644 | TCHAR path[MAX_PATH]; | |
1645 | GetNetXMSDirectory(nxDirEtc, path); | |
1646 | _tcscat(path, _T("\\nxagentd.conf.d")); | |
1647 | if (_taccess(path, 4) == 0) | |
1648 | { | |
1649 | _tcscpy(g_szConfigIncludeDir, path); | |
1650 | } | |
1651 | else | |
1652 | { | |
1653 | _tcscpy(g_szConfigIncludeDir, _T("C:\\nxagentd.conf.d")); | |
1654 | } | |
1655 | } | |
5039dede AK |
1656 | #endif |
1657 | ||
1658 | if (bRestart) | |
1659 | DoRestartActions(dwOldPID); | |
1660 | ||
a1716ea0 | 1661 | InitConfig(); |
e6c91aac | 1662 | |
5039dede AK |
1663 | // Do requested action |
1664 | switch(iAction) | |
1665 | { | |
1666 | case ACTION_RUN_AGENT: | |
1667 | // Set default value for session idle timeout based on | |
1668 | // connect() timeout, if possible | |
1669 | #if HAVE_SYSCTLBYNAME && !defined(_IPSO) | |
1670 | { | |
1671 | LONG nVal; | |
1672 | size_t nSize; | |
1673 | ||
1674 | nSize = sizeof(nVal); | |
1675 | if (sysctlbyname("net.inet.tcp.keepinit", &nVal, &nSize, NULL, 0) == 0) | |
1676 | { | |
1677 | g_dwIdleTimeout = nVal / 1000 + 15; | |
1678 | } | |
1679 | } | |
1680 | #endif | |
1681 | ||
1682 | if (g_dwFlags & AF_CENTRAL_CONFIG) | |
1683 | { | |
2df047f4 | 1684 | if (s_debugLevel > 0) |
f3387429 | 1685 | _tprintf(_T("Downloading configuration from %s...\n"), g_szConfigServer); |
5039dede AK |
1686 | if (DownloadConfig(g_szConfigServer)) |
1687 | { | |
2df047f4 | 1688 | if (s_debugLevel > 0) |
f3387429 | 1689 | _tprintf(_T("Configuration downloaded successfully\n")); |
5039dede AK |
1690 | } |
1691 | else | |
1692 | { | |
2df047f4 | 1693 | if (s_debugLevel > 0) |
f3387429 | 1694 | _tprintf(_T("Configuration download failed\n")); |
5039dede AK |
1695 | } |
1696 | } | |
1697 | ||
abf35d58 | 1698 | if (g_config->loadConfig(g_szConfigFile, _T("agent"))) |
e6c91aac | 1699 | { |
357a2954 AK |
1700 | const TCHAR *dir = g_config->getValue(_T("/agent/ConfigIncludeDir")); |
1701 | if (dir != NULL) | |
6ca3b41c VK |
1702 | nx_strncpy(g_szConfigIncludeDir, dir, MAX_PATH); |
1703 | g_config->loadConfigDirectory(g_szConfigIncludeDir, _T("agent")); | |
abf35d58 VK |
1704 | if (g_config->parseTemplate(_T("agent"), m_cfgTemplate)) |
1705 | { | |
07ca7d19 | 1706 | DecryptPassword(_T("netxms"), g_szSharedSecret, g_szSharedSecret, MAX_SECRET_LENGTH); |
2b58ee20 | 1707 | |
134c8b79 AK |
1708 | // try to guess executable path |
1709 | #ifdef _WIN32 | |
5a0d14cf | 1710 | GetModuleFileName(GetModuleHandle(NULL), s_executableName, MAX_PATH); |
134c8b79 AK |
1711 | #else |
1712 | #ifdef UNICODE | |
1713 | char __buffer[PATH_MAX]; | |
1714 | #else | |
5a0d14cf | 1715 | #define __buffer s_executableName |
134c8b79 AK |
1716 | #endif |
1717 | if (realpath(argv[0], __buffer) == NULL) | |
1718 | { | |
1719 | // fallback | |
c5407b29 AK |
1720 | TCHAR *path = _tgetenv(_T("NETXMS_HOME")); |
1721 | if (path != NULL) | |
1722 | { | |
1723 | nx_strncpy(s_executableName, path, sizeof(s_executableName) / sizeof(s_executableName[0])); | |
1724 | } | |
1725 | else | |
1726 | { | |
1727 | nx_strncpy(s_executableName, PREFIX, sizeof(s_executableName) / sizeof(s_executableName[0])); | |
1728 | } | |
1729 | _tcsncat(s_executableName, _T("/bin/nxagentd"), sizeof(s_executableName) / sizeof(s_executableName[0])); | |
134c8b79 AK |
1730 | } |
1731 | else | |
1732 | { | |
1733 | #ifdef UNICODE | |
1734 | int len = strlen(__buffer); | |
5a0d14cf | 1735 | MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, __buffer, len, s_executableName, len); |
134c8b79 AK |
1736 | #endif |
1737 | } | |
1738 | #endif | |
1739 | ||
0bbab9d3 | 1740 | // Set exception handler |
9fcdfda7 | 1741 | #ifdef _WIN32 |
abf35d58 | 1742 | if (g_dwFlags & AF_CATCH_EXCEPTIONS) |
e5e015dd | 1743 | SetExceptionHandler(SEHServiceExceptionHandler, SEHServiceExceptionDataWriter, s_dumpDir, |
bf3b7f79 | 1744 | _T("nxagentd"), MSG_EXCEPTION, g_dwFlags & AF_WRITE_FULL_DUMP, !(g_dwFlags & AF_DAEMON)); |
abf35d58 | 1745 | __try { |
9fcdfda7 | 1746 | #endif |
cc022855 | 1747 | if ((!_tcsicmp(g_szLogFile, _T("{syslog}"))) || |
bf3b7f79 | 1748 | (!_tcsicmp(g_szLogFile, _T("{eventlog}")))) |
abf35d58 | 1749 | g_dwFlags |= AF_USE_SYSLOG; |
5039dede AK |
1750 | |
1751 | #ifdef _WIN32 | |
abf35d58 VK |
1752 | if (g_dwFlags & AF_DAEMON) |
1753 | { | |
1754 | InitService(); | |
1755 | } | |
1756 | else | |
1757 | { | |
1758 | if (Initialize()) | |
1759 | { | |
1760 | Main(); | |
1761 | } | |
1762 | else | |
1763 | { | |
bf3b7f79 | 1764 | ConsolePrintf(_T("Agent initialization failed\n")); |
abf35d58 VK |
1765 | nxlog_close(); |
1766 | iExitCode = 3; | |
1767 | } | |
1768 | } | |
5039dede | 1769 | #else /* _WIN32 */ |
abf35d58 | 1770 | if (g_dwFlags & AF_DAEMON) |
f31c22b3 | 1771 | { |
abf35d58 VK |
1772 | if (daemon(0, 0) == -1) |
1773 | { | |
1774 | perror("Unable to setup itself as a daemon"); | |
1775 | iExitCode = 4; | |
1776 | } | |
f31c22b3 | 1777 | } |
abf35d58 | 1778 | if (iExitCode == 0) |
f31c22b3 | 1779 | { |
76b42c1e | 1780 | s_pid = getpid(); |
abf35d58 VK |
1781 | if (Initialize()) |
1782 | { | |
abf35d58 VK |
1783 | FILE *fp; |
1784 | ||
1785 | // Write PID file | |
f3387429 | 1786 | fp = _tfopen(g_szPidFile, _T("w")); |
abf35d58 VK |
1787 | if (fp != NULL) |
1788 | { | |
76b42c1e | 1789 | _ftprintf(fp, _T("%d"), s_pid); |
abf35d58 | 1790 | fclose(fp); |
cc022855 | 1791 | } |
abf35d58 VK |
1792 | Main(); |
1793 | Shutdown(); | |
1794 | } | |
1795 | else | |
1796 | { | |
bf3b7f79 | 1797 | ConsolePrintf(_T("Agent initialization failed\n")); |
abf35d58 VK |
1798 | nxlog_close(); |
1799 | iExitCode = 3; | |
1800 | } | |
1801 | } | |
5039dede AK |
1802 | #endif /* _WIN32 */ |
1803 | ||
968031d9 | 1804 | #if defined(_WIN32) |
76b42c1e VK |
1805 | if (s_shutdownCondition != INVALID_CONDITION_HANDLE) |
1806 | ConditionDestroy(s_shutdownCondition); | |
9fcdfda7 VK |
1807 | #endif |
1808 | #ifdef _WIN32 | |
abf35d58 | 1809 | LIBNETXMS_EXCEPTION_HANDLER |
5039dede | 1810 | #endif |
abf35d58 VK |
1811 | } |
1812 | else | |
1813 | { | |
bf3b7f79 | 1814 | ConsolePrintf(_T("Error parsing configuration file\n")); |
abf35d58 VK |
1815 | iExitCode = 2; |
1816 | } | |
5039dede AK |
1817 | } |
1818 | else | |
1819 | { | |
bf3b7f79 | 1820 | ConsolePrintf(_T("Error loading configuration file\n")); |
5039dede AK |
1821 | iExitCode = 2; |
1822 | } | |
1823 | break; | |
1824 | case ACTION_CHECK_CONFIG: | |
5039dede | 1825 | { |
31e21b08 AK |
1826 | bool validConfig = g_config->loadConfig(g_szConfigFile, _T("agent"), false); |
1827 | if (validConfig) | |
1828 | { | |
1829 | const TCHAR *dir = g_config->getValue(_T("/agent/ConfigIncludeDir")); | |
1830 | if (dir != NULL) | |
1831 | { | |
99877e7b | 1832 | validConfig = g_config->loadConfigDirectory(dir, _T("agent"), false); |
e77b1f4e VK |
1833 | if (!validConfig) |
1834 | { | |
1835 | ConsolePrintf(_T("Error reading additional configuration files from \"%s\"\n"), dir); | |
1836 | } | |
31e21b08 AK |
1837 | } |
1838 | } | |
1839 | ||
1840 | if (validConfig) | |
1841 | { | |
e77b1f4e | 1842 | g_config->print(stdout); |
31e21b08 AK |
1843 | validConfig = g_config->parseTemplate(_T("agent"), m_cfgTemplate); |
1844 | } | |
1845 | ||
1846 | if (!validConfig) | |
1847 | { | |
1848 | ConsolePrintf(_T("Configuration file check failed\n")); | |
1849 | iExitCode = 2; | |
1850 | } | |
5039dede AK |
1851 | } |
1852 | break; | |
9fcdfda7 VK |
1853 | case ACTION_RUN_WATCHDOG: |
1854 | iExitCode = WatchdogMain(dwMainPID); | |
1855 | break; | |
5039dede | 1856 | case ACTION_CREATE_CONFIG: |
f3387429 VK |
1857 | iExitCode = CreateConfig(CHECK_NULL_A(argv[optind]), CHECK_NULL_A(argv[optind + 1]), |
1858 | CHECK_NULL_A(argv[optind + 2]), CHECK_NULL_A(argv[optind + 3]), | |
1859 | argc - optind - 4, &argv[optind + 4]); | |
5039dede | 1860 | break; |
f918b160 VK |
1861 | case ACTION_SHUTDOWN_EXT_AGENTS: |
1862 | InitiateExtSubagentShutdown(); | |
1863 | iExitCode = 0; | |
1864 | break; | |
5039dede AK |
1865 | #ifdef _WIN32 |
1866 | case ACTION_INSTALL_SERVICE: | |
1867 | GetModuleFileName(GetModuleHandle(NULL), szModuleName, MAX_PATH); | |
56ea99c3 | 1868 | InstallService(szModuleName, g_szConfigFile, s_debugLevel); |
5039dede AK |
1869 | break; |
1870 | case ACTION_REMOVE_SERVICE: | |
1871 | RemoveService(); | |
1872 | break; | |
1873 | case ACTION_INSTALL_EVENT_SOURCE: | |
1874 | GetModuleFileName(GetModuleHandle(NULL), szModuleName, MAX_PATH); | |
1875 | InstallEventSource(szModuleName); | |
1876 | break; | |
1877 | case ACTION_REMOVE_EVENT_SOURCE: | |
1878 | RemoveEventSource(); | |
1879 | break; | |
1880 | case ACTION_START_SERVICE: | |
1881 | StartAgentService(); | |
1882 | break; | |
1883 | case ACTION_STOP_SERVICE: | |
1884 | StopAgentService(); | |
1885 | break; | |
1886 | #endif | |
1887 | case ACTION_HELP: | |
f3387429 | 1888 | _fputts(m_szHelpText, stdout); |
5039dede AK |
1889 | break; |
1890 | default: | |
1891 | break; | |
1892 | } | |
1893 | ||
5039dede AK |
1894 | return iExitCode; |
1895 | } |