3df11ba71e5db8a74fa1c61d5a841eaed2832920
[public/netxms.git] / src / agent / libnxagent / bridge.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2015 Victor Kirhenshtein
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU Lesser General Public License as published
7 ** by the Free Software Foundation; either version 3 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 Lesser 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: bridge.cpp
20 **
21 **/
22
23 #include "libnxagent.h"
24
25 /**
26 * Static data
27 */
28 static void (* s_fpWriteLog)(int, int, const TCHAR *) = NULL;
29 static void (* s_fpSendTrap1)(UINT32, const TCHAR *, const char *, va_list) = NULL;
30 static void (* s_fpSendTrap2)(UINT32, const TCHAR *, int, TCHAR **) = NULL;
31 static AbstractCommSession *(* s_fpFindServerSession)(UINT64) = NULL;
32 static bool (* s_fpEnumerateSessions)(EnumerationCallbackResult (*)(AbstractCommSession *, void *), void *) = NULL;
33 static bool (* s_fpSendFile)(void *, UINT32, const TCHAR *, long) = NULL;
34 static bool (* s_fpPushData)(const TCHAR *, const TCHAR *, UINT32, time_t) = NULL;
35 static CONDITION s_agentShutdownCondition = INVALID_CONDITION_HANDLE;
36 static const TCHAR *s_dataDirectory = NULL;
37 static DB_HANDLE (*s_fpGetLocalDatabaseHandle)() = NULL;
38
39 /**
40 * Initialize subagent API
41 */
42 void LIBNXAGENT_EXPORTABLE InitSubAgentAPI(void (* writeLog)(int, int, const TCHAR *),
43 void (* sendTrap1)(UINT32, const TCHAR *, const char *, va_list),
44 void (* sendTrap2)(UINT32, const TCHAR *, int, TCHAR **),
45 bool (* enumerateSessions)(EnumerationCallbackResult (*)(AbstractCommSession *, void *), void*),
46 AbstractCommSession *(* findServerSession)(UINT64),
47 bool (* sendFile)(void *, UINT32, const TCHAR *, long),
48 bool (* pushData)(const TCHAR *, const TCHAR *, UINT32, time_t),
49 DB_HANDLE (* getLocalDatabaseHandle)(),
50 CONDITION shutdownCondition, const TCHAR *dataDirectory)
51 {
52 s_fpWriteLog = writeLog;
53 s_fpSendTrap1 = sendTrap1;
54 s_fpSendTrap2 = sendTrap2;
55 s_fpEnumerateSessions = enumerateSessions;
56 s_fpFindServerSession = findServerSession;
57 s_fpSendFile = sendFile;
58 s_fpPushData = pushData;
59 s_agentShutdownCondition = shutdownCondition;
60 s_dataDirectory = dataDirectory;
61 s_fpGetLocalDatabaseHandle = getLocalDatabaseHandle;
62 }
63
64 /**
65 * Write message to agent's log
66 */
67 void LIBNXAGENT_EXPORTABLE AgentWriteLog(int logLevel, const TCHAR *format, ...)
68 {
69 TCHAR szBuffer[4096];
70 va_list args;
71
72 if (s_fpWriteLog != NULL)
73 {
74 va_start(args, format);
75 _vsntprintf(szBuffer, 4096, format, args);
76 va_end(args);
77 szBuffer[4095] = 0;
78 s_fpWriteLog(logLevel, 0, szBuffer);
79 }
80 }
81
82 /**
83 * Write message to agent's log
84 */
85 void LIBNXAGENT_EXPORTABLE AgentWriteLog2(int logLevel, const TCHAR *format, va_list args)
86 {
87 TCHAR szBuffer[4096];
88
89 if (s_fpWriteLog != NULL)
90 {
91 _vsntprintf(szBuffer, 4096, format, args);
92 szBuffer[4095] = 0;
93 s_fpWriteLog(logLevel, 0, szBuffer);
94 }
95 }
96
97 /**
98 * Write debug message to agent's log
99 */
100 void LIBNXAGENT_EXPORTABLE AgentWriteDebugLog(int level, const TCHAR *format, ...)
101 {
102 TCHAR szBuffer[4096];
103 va_list args;
104
105 if (s_fpWriteLog != NULL)
106 {
107 va_start(args, format);
108 _vsntprintf(szBuffer, 4096, format, args);
109 va_end(args);
110 szBuffer[4095] = 0;
111 s_fpWriteLog(EVENTLOG_DEBUG_TYPE, level, szBuffer);
112 }
113 }
114
115 /**
116 * Write debug message to agent's log
117 */
118 void LIBNXAGENT_EXPORTABLE AgentWriteDebugLog2(int level, const TCHAR *format, va_list args)
119 {
120 TCHAR szBuffer[4096];
121
122 if (s_fpWriteLog != NULL)
123 {
124 _vsntprintf(szBuffer, 4096, format, args);
125 szBuffer[4095] = 0;
126 s_fpWriteLog(EVENTLOG_DEBUG_TYPE, level, szBuffer);
127 }
128 }
129
130 /**
131 * Send trap from agent to server
132 */
133 void LIBNXAGENT_EXPORTABLE AgentSendTrap(UINT32 dwEvent, const TCHAR *eventName, const char *pszFormat, ...)
134 {
135 va_list args;
136
137 if (s_fpSendTrap1 != NULL)
138 {
139 va_start(args, pszFormat);
140 s_fpSendTrap1(dwEvent, eventName, pszFormat, args);
141 va_end(args);
142 }
143 }
144
145 /**
146 * Send trap from agent to server
147 */
148 void LIBNXAGENT_EXPORTABLE AgentSendTrap2(UINT32 dwEvent, const TCHAR *eventName, int nCount, TCHAR **ppszArgList)
149 {
150 if (s_fpSendTrap2 != NULL)
151 s_fpSendTrap2(dwEvent, eventName, nCount, ppszArgList);
152 }
153
154 /**
155 * Enumerates active agent sessions. Callback will be called for each valid session.
156 * Callback must return _STOP to stop enumeration or _CONTINUE to continue.
157 *
158 * @return true if enumeration was stopped by callback
159 */
160 bool LIBNXAGENT_EXPORTABLE AgentEnumerateSessions(EnumerationCallbackResult (* callback)(AbstractCommSession *, void *), void *data)
161 {
162 return (s_fpEnumerateSessions != NULL) ? s_fpEnumerateSessions(callback, data) : false;
163 }
164
165 /**
166 * Send file to server
167 */
168 bool LIBNXAGENT_EXPORTABLE AgentSendFileToServer(void *session, UINT32 requestId, const TCHAR *file, long offset)
169 {
170 if ((s_fpSendFile == NULL) || (session == NULL) || (file == NULL))
171 return FALSE;
172 return s_fpSendFile(session, requestId, file, offset);
173 }
174
175 /**
176 * Push parameter's value
177 */
178 bool LIBNXAGENT_EXPORTABLE AgentPushParameterData(const TCHAR *parameter, const TCHAR *value)
179 {
180 if (s_fpPushData == NULL)
181 return FALSE;
182 return s_fpPushData(parameter, value, 0, 0);
183 }
184
185 /**
186 * Push parameter's value
187 */
188 bool LIBNXAGENT_EXPORTABLE AgentPushParameterDataInt32(const TCHAR *parameter, LONG value)
189 {
190 TCHAR buffer[64];
191
192 _sntprintf(buffer, sizeof(buffer), _T("%d"), (int)value);
193 return AgentPushParameterData(parameter, buffer);
194 }
195
196 /**
197 * Push parameter's value
198 */
199 bool LIBNXAGENT_EXPORTABLE AgentPushParameterDataUInt32(const TCHAR *parameter, UINT32 value)
200 {
201 TCHAR buffer[64];
202
203 _sntprintf(buffer, sizeof(buffer), _T("%u"), (unsigned int)value);
204 return AgentPushParameterData(parameter, buffer);
205 }
206
207 /**
208 * Push parameter's value
209 */
210 bool LIBNXAGENT_EXPORTABLE AgentPushParameterDataInt64(const TCHAR *parameter, INT64 value)
211 {
212 TCHAR buffer[64];
213
214 _sntprintf(buffer, sizeof(buffer), INT64_FMT, value);
215 return AgentPushParameterData(parameter, buffer);
216 }
217
218 /**
219 * Push parameter's value
220 */
221 bool LIBNXAGENT_EXPORTABLE AgentPushParameterDataUInt64(const TCHAR *parameter, QWORD value)
222 {
223 TCHAR buffer[64];
224
225 _sntprintf(buffer, sizeof(buffer), UINT64_FMT, value);
226 return AgentPushParameterData(parameter, buffer);
227 }
228
229 /**
230 * Push parameter's value
231 */
232 bool LIBNXAGENT_EXPORTABLE AgentPushParameterDataDouble(const TCHAR *parameter, double value)
233 {
234 TCHAR buffer[64];
235
236 _sntprintf(buffer, sizeof(buffer), _T("%f"), value);
237 return AgentPushParameterData(parameter, buffer);
238 }
239
240 /**
241 * Get shutdown condition
242 */
243 CONDITION LIBNXAGENT_EXPORTABLE AgentGetShutdownCondition()
244 {
245 return s_agentShutdownCondition;
246 }
247
248 /**
249 * Sleep and check for agent shutdown
250 */
251 bool LIBNXAGENT_EXPORTABLE AgentSleepAndCheckForShutdown(UINT32 sleepTime)
252 {
253 return ConditionWait(s_agentShutdownCondition, sleepTime);
254 }
255
256 /**
257 * Get data directory
258 */
259 const TCHAR LIBNXAGENT_EXPORTABLE *AgentGetDataDirectory()
260 {
261 return s_dataDirectory;
262 }
263
264 /**
265 * Find server session. Caller must call decRefCount() for session object when finished.
266 *
267 * @param serverId server ID
268 * @return server session object or NULL
269 */
270 AbstractCommSession LIBNXAGENT_EXPORTABLE *AgentFindServerSession(UINT64 serverId)
271 {
272 return (s_fpFindServerSession != NULL) ? s_fpFindServerSession(serverId) : NULL;
273 }
274
275 /**
276 * Get handle to local database.
277 *
278 * @return database handle or NULL if not available
279 */
280 DB_HANDLE LIBNXAGENT_EXPORTABLE AgentGetLocalDatabaseHandle()
281 {
282 return (s_fpGetLocalDatabaseHandle != NULL) ? s_fpGetLocalDatabaseHandle() : NULL;
283 }
284
285 /**
286 * Read registry value as a string using provided attribute.
287 *
288 * @return attribute value or default value if no value found
289 */
290 TCHAR LIBNXAGENT_EXPORTABLE *ReadRegistryAsString(const TCHAR *attr, TCHAR *buffer, int bufSize, const TCHAR *defaultValue)
291 {
292 TCHAR *value = NULL;
293
294 DB_HANDLE hdb = AgentGetLocalDatabaseHandle();
295 if(hdb != NULL && attr != NULL)
296 {
297 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT value FROM registry WHERE attribute=?"));
298 if (hStmt != NULL)
299 {
300 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, attr, DB_BIND_STATIC);
301 DB_RESULT hResult = DBSelectPrepared(hStmt);
302 if (hResult != NULL)
303 {
304 if(DBGetNumRows(hResult) > 0)
305 value = DBGetField(hResult, 0, 0, buffer, bufSize);
306 DBFreeResult(hResult);
307 }
308 DBFreeStatement(hStmt);
309 }
310 }
311
312 if(value == NULL)
313 {
314 if(buffer == NULL)
315 {
316 value = defaultValue != NULL ? _tcsdup(defaultValue) : NULL;
317 }
318 else
319 value = defaultValue != NULL ? _tcsncpy(buffer, defaultValue, bufSize) : NULL;
320 }
321 return value;
322 }
323
324 /**
325 * Read registry value as a INT32 using provided attribute.
326 *
327 * @return attribute value or default value in no value found
328 */
329 INT32 LIBNXAGENT_EXPORTABLE ReadRegistryAsInt32(const TCHAR *attr, INT32 defaultValue)
330 {
331 TCHAR buffer[MAX_DB_STRING];
332 ReadRegistryAsString(attr, buffer, MAX_DB_STRING, NULL);
333 if(buffer == NULL)
334 {
335 return defaultValue;
336 }
337 else
338 {
339 return _tcstol(buffer, NULL, 0);
340 }
341 }
342
343 /**
344 * Read registry value as a INT32 using provided attribute.
345 *
346 * @return attribute value or default value in no value found
347 */
348 INT64 LIBNXAGENT_EXPORTABLE ReadRegistryAsInt64(const TCHAR *attr, INT64 defaultValue)
349 {
350 TCHAR buffer[MAX_DB_STRING];
351 ReadRegistryAsString(attr, buffer, MAX_DB_STRING, NULL);
352 if(buffer == NULL)
353 {
354 return defaultValue;
355 }
356 else
357 {
358 return _tcstoll(buffer, NULL, 0);
359 }
360 }
361
362 /**
363 * Write registry value as a string. This method inserts new value or update existing.
364 *
365 * @return if this update/insert was successful
366 */
367 bool LIBNXAGENT_EXPORTABLE WriteRegistry(const TCHAR *attr, const TCHAR *value)
368 {
369 DB_HANDLE hdb = AgentGetLocalDatabaseHandle();
370 if (_tcslen(attr) > 63 || hdb == NULL)
371 return false;
372
373 // Check for variable existence
374 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT value FROM registry WHERE attribute=?"));
375 if (hStmt == NULL)
376 {
377 return false;
378 }
379 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, attr, DB_BIND_STATIC);
380 DB_RESULT hResult = DBSelectPrepared(hStmt);
381 bool varExist = false;
382 if (hResult != NULL)
383 {
384 if (DBGetNumRows(hResult) > 0)
385 varExist = true;
386 DBFreeResult(hResult);
387 }
388 DBFreeStatement(hStmt);
389
390 // Create or update variable value
391 if (varExist)
392 {
393 hStmt = DBPrepare(hdb, _T("UPDATE registry SET value=? WHERE attribute=?"));
394 if (hStmt == NULL)
395 {
396 return false;
397 }
398 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, value, DB_BIND_STATIC);
399 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, attr, DB_BIND_STATIC);
400 }
401 else
402 {
403 hStmt = DBPrepare(hdb, _T("INSERT INTO registry (attribute,value) VALUES (?,?)"));
404 if (hStmt == NULL)
405 {
406 return false;
407 }
408 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, attr, DB_BIND_STATIC);
409 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, value, DB_BIND_STATIC);
410 }
411 bool success = DBExecute(hStmt);
412 DBFreeStatement(hStmt);
413 DBConnectionPoolReleaseConnection(hdb);
414 return success;
415 }
416
417 /**
418 * Write registry value as a INT32. This method inserts new value or update existing.
419 *
420 * @return if this update/insert was successful
421 */
422 bool LIBNXAGENT_EXPORTABLE WriteRegistry(const TCHAR *attr, INT32 *value)
423 {
424 TCHAR buffer[64];
425 _sntprintf(buffer, 64, _T("%d"), value);
426 return WriteRegistry(attr, buffer);
427 }
428
429 /**
430 * Write registry value as a INT64. This method inserts new value or update existing.
431 *
432 * @return if this update/insert was successful
433 */
434 bool LIBNXAGENT_EXPORTABLE WriteRegistry(const TCHAR *attr, INT64 value)
435 {
436 TCHAR buffer[64];
437 _sntprintf(buffer, 64, INT64_FMT, value);
438 return WriteRegistry(attr, buffer);
439 }
440
441 /**
442 * Delete registry entry
443 *
444 * @return if this delete was successful
445 */
446 bool LIBNXAGENT_EXPORTABLE DeleteRegistryEntry(const TCHAR *attr)
447 {
448 bool success = false;
449
450 DB_HANDLE hdb = AgentGetLocalDatabaseHandle();
451 if(hdb == NULL || attr == NULL)
452 return false;
453
454 DB_STATEMENT hStmt = DBPrepare(hdb, _T("DELETE FROM registry WHERE attribute=?"));
455 if (hStmt != NULL)
456 {
457 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, attr, DB_BIND_STATIC);
458 success = DBExecute(hStmt);
459 DBFreeStatement(hStmt);
460 }
461 return success;
462 }
463