fixed bugs in IntegerArray class implementation
[public/netxms.git] / src / server / core / agent.cpp
CommitLineData
9fa031cd 1/*
5039dede 2** NetXMS - Network Management System
df94e0ce 3** Copyright (C) 2003-2012 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**
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: agent.cpp
20**
21**/
22
23#include "nxcore.h"
24
d1c1c522
VK
25/**
26 * Destructor for extended agent connection class
27 */
5039dede
AK
28AgentConnectionEx::~AgentConnectionEx()
29{
30}
31
d1c1c522
VK
32/**
33 * Trap processor
34 */
f480bdd4 35void AgentConnectionEx::onTrap(CSCPMessage *pMsg)
5039dede 36{
967893bb 37 UINT32 dwEventCode;
5039dede 38 int i, iNumArgs;
d1c1c522 39 Node *pNode = NULL;
5039dede 40 TCHAR *pszArgList[32], szBuffer[32];
35f836fe 41 char szFormat[] = "ssssssssssssssssssssssssssssssss";
5039dede 42
d1c1c522
VK
43 DbgPrintf(3, _T("AgentConnectionEx::onTrap(): Received trap message from agent at %s, node ID %d"), IpToStr(getIpAddr(), szBuffer), m_nodeId);
44 if (m_nodeId != 0)
45 pNode = (Node *)FindObjectById(m_nodeId, OBJECT_NODE);
46 if (pNode == NULL)
47 pNode = FindNodeByIP(0, getIpAddr());
5039dede
AK
48 if (pNode != NULL)
49 {
fed33789
VK
50 // Check for duplicate traps - only accept traps with ID
51 // higher than last received
52 // agents prior to 1.1.6 will not send trap id
53 // we should accept trap in that case to maintain compatibility
54 bool acceptTrap;
55 QWORD trapId = pMsg->GetVariableInt64(VID_TRAP_ID);
56 if (trapId != 0)
57 {
58 acceptTrap = pNode->checkAgentTrapId(trapId);
59 DbgPrintf(5, _T("AgentConnectionEx::onTrap(): trapID is%s valid"), acceptTrap ? _T("") : _T(" not"));
60 }
61 else
62 {
63 acceptTrap = true;
64 DbgPrintf(5, _T("AgentConnectionEx::onTrap(): trap ID not provided"));
65 }
66
67 if (acceptTrap)
68 {
69 dwEventCode = pMsg->GetVariableLong(VID_EVENT_CODE);
5c44534b 70 if ((dwEventCode == 0) && pMsg->isFieldExist(VID_EVENT_NAME))
2dd24569
VK
71 {
72 TCHAR eventName[256];
73 pMsg->GetVariableStr(VID_EVENT_NAME, eventName, 256);
74 dwEventCode = EventCodeFromName(eventName, 0);
75 }
fed33789
VK
76 iNumArgs = (int)pMsg->GetVariableShort(VID_NUM_ARGS);
77 if (iNumArgs > 32)
78 iNumArgs = 32;
79 for(i = 0; i < iNumArgs; i++)
80 pszArgList[i] = pMsg->GetVariableStr(VID_EVENT_ARG_BASE + i);
81 DbgPrintf(3, _T("Event from trap: %d"), dwEventCode);
5039dede 82
fed33789
VK
83 // Following call is not very good, but I'm too lazy now
84 // to change PostEvent()
85 szFormat[iNumArgs] = 0;
86 PostEvent(dwEventCode, pNode->Id(), (iNumArgs > 0) ? szFormat : NULL,
87 pszArgList[0], pszArgList[1], pszArgList[2], pszArgList[3],
88 pszArgList[4], pszArgList[5], pszArgList[6], pszArgList[7],
89 pszArgList[8], pszArgList[9], pszArgList[10], pszArgList[11],
90 pszArgList[12], pszArgList[13], pszArgList[14], pszArgList[15],
91 pszArgList[16], pszArgList[17], pszArgList[18], pszArgList[19],
92 pszArgList[20], pszArgList[21], pszArgList[22], pszArgList[23],
93 pszArgList[24], pszArgList[25], pszArgList[26], pszArgList[27],
94 pszArgList[28], pszArgList[29], pszArgList[30], pszArgList[31]);
9fa031cd 95
fed33789
VK
96 // Cleanup
97 for(i = 0; i < iNumArgs; i++)
98 free(pszArgList[i]);
99 }
5039dede
AK
100 }
101 else
102 {
7c521895 103 DbgPrintf(3, _T("Cannot find node for IP address %s"), IpToStr(getIpAddr(), szBuffer));
5039dede
AK
104 }
105}
45d84f8a 106
d1c1c522
VK
107/**
108 * Handler for data push
109 */
f480bdd4
VK
110void AgentConnectionEx::onDataPush(CSCPMessage *msg)
111{
112 TCHAR name[MAX_PARAM_NAME], value[MAX_RESULT_LENGTH];
113
114 msg->GetVariableStr(VID_NAME, name, MAX_PARAM_NAME);
115 msg->GetVariableStr(VID_VALUE, value, MAX_RESULT_LENGTH);
116
e3ee1478 117 Node *sender = NULL;
42a3be4f
VK
118 if (m_nodeId != 0)
119 sender = (Node *)FindObjectById(m_nodeId, OBJECT_NODE);
120 if (sender == NULL)
121 sender = FindNodeByIP(0, getIpAddr());
122
4e46505f 123 if (sender != NULL)
f480bdd4 124 {
42a3be4f
VK
125 // Check for duplicate data requests - only accept requests with ID
126 // higher than last received
127 // agents prior to 1.2.10 will not send request id
128 // we should accept data in that case to maintain compatibility
129 bool acceptRequest;
130 QWORD requestId = msg->GetVariableInt64(VID_REQUEST_ID);
131 if (requestId != 0)
132 {
133 acceptRequest = sender->checkAgentPushRequestId(requestId);
134 DbgPrintf(5, _T("AgentConnectionEx::onDataPush(): requestId is%s valid"), acceptRequest ? _T("") : _T(" not"));
135 }
136 else
137 {
138 acceptRequest = true;
139 DbgPrintf(5, _T("AgentConnectionEx::onDataPush(): request ID not provided"));
140 }
141
142 if (acceptRequest)
143 {
144 Node *target;
145 UINT32 objectId = msg->GetVariableLong(VID_OBJECT_ID);
146 if (objectId != 0)
4e46505f 147 {
42a3be4f
VK
148 // push on behalf of other node
149 target = (Node *)FindObjectById(objectId, OBJECT_NODE);
150 if (target != NULL)
4e46505f 151 {
42a3be4f
VK
152 if (target->isTrustedNode(sender->Id()))
153 {
154 DbgPrintf(5, _T("%s: agent data push: target set to %s [%d]"), sender->Name(), target->Name(), target->Id());
155 }
156 else
157 {
158 DbgPrintf(5, _T("%s: agent data push: not in trusted node list for target %s [%d]"), sender->Name(), target->Name(), target->Id());
159 target = NULL;
160 }
4e46505f
VK
161 }
162 }
42a3be4f
VK
163 else
164 {
165 target = sender;
166 }
4e46505f 167
42a3be4f
VK
168 if (target != NULL)
169 {
170 DbgPrintf(5, _T("%s: agent data push: %s=%s"), target->Name(), name, value);
171 DCObject *dci = target->getDCObjectByName(name);
172 if ((dci != NULL) && (dci->getType() == DCO_TYPE_ITEM) && (dci->getDataSource() == DS_PUSH_AGENT) && (dci->getStatus() == ITEM_STATUS_ACTIVE))
173 {
174 DbgPrintf(5, _T("%s: agent data push: found DCI %d"), target->Name(), dci->getId());
175 time_t t = time(NULL);
176 target->processNewDCValue(dci, t, value);
177 dci->setLastPollTime(t);
178 }
179 else
180 {
181 DbgPrintf(5, _T("%s: agent data push: DCI not found for %s"), target->Name(), name);
182 }
183 }
184 else
185 {
186 DbgPrintf(5, _T("%s: agent data push: target node not found or not accessible"), sender->Name());
187 }
4e46505f 188 }
f480bdd4
VK
189 }
190}
191
af21affe
VK
192/**
193 * Print message.
194 */
195void AgentConnectionEx::printMsg(const TCHAR *format, ...)
196{
197 va_list args;
198
199 va_start(args, format);
200 DbgPrintf2(6, format, args);
201 va_end(args);
202}
203
76b4edb5 204/**
9fa031cd 205 * Recieve file monitoring information and resend to all required user sessions
206 */
207void AgentConnectionEx::onFileMonitoringData(CSCPMessage *pMsg)
208{
9fa031cd 209 NetObj *object = NULL;
210 if (m_nodeId != 0)
211 object = (Node *)FindObjectById(m_nodeId, OBJECT_NODE);
212 if (object != NULL)
213 {
18b237f7 214 TCHAR remoteFile[MAX_PATH];
9fa031cd 215 pMsg->GetVariableStr(VID_FILE_NAME, remoteFile, MAX_PATH);
e2338033 216 ObjectArray<ClientSession>* result = g_monitoringList.findClientByFNameAndNodeID(remoteFile, object->Id());
18b237f7 217 DbgPrintf(6, _T("AgentConnectionEx::onFileMonitoringData: found %d sessions for remote file %s on node %s [%d]"), result->size(), remoteFile, object->Name(), object->Id());
9fa031cd 218 for(int i = 0; i < result->size(); i++)
219 {
220 result->get(i)->sendMessage(pMsg);
05e3ba32 221 }
222 if(result->size() == 0)
223 {
224 DbgPrintf(6, _T("AgentConnectionEx::onFileMonitoringData: unknown subscription will be canceled."));
225 Node *node = (Node *)object;
226 AgentConnection *conn = node->createAgentConnection();
227 if(conn != NULL)
228 {
229 CSCPMessage request;
230 request.SetId(conn->generateRequestId());
231 request.SetCode(CMD_CANCEL_FILE_MONITORING);
232 request.SetVariable(VID_FILE_NAME, remoteFile);
233 request.SetVariable(VID_OBJECT_ID, node->Id());
234 CSCPMessage* response = conn->customRequest(&request);
235 delete response;
236 }
237 delete conn;
9fa031cd 238 }
ece85e30 239 delete result;
9fa031cd 240 }
241 else
242 {
243 g_monitoringList.removeDisconectedNode(m_nodeId);
18b237f7 244 DbgPrintf(6, _T("AgentConnectionEx::onFileMonitoringData: node object not found"));
9fa031cd 245 }
246}
247
d1c1c522
VK
248/**
249 * Deploy policy to agent
250 */
967893bb 251UINT32 AgentConnectionEx::deployPolicy(AgentPolicy *policy)
45d84f8a 252{
967893bb 253 UINT32 rqId, rcc;
45d84f8a
VK
254 CSCPMessage msg(getProtocolVersion());
255
256 rqId = generateRequestId();
257 msg.SetId(rqId);
258 msg.SetCode(CMD_DEPLOY_AGENT_POLICY);
8051849b
VK
259 if (policy->createDeploymentMessage(&msg))
260 {
7c521895 261 if (sendMessage(&msg))
8051849b 262 {
7c521895 263 rcc = waitForRCC(rqId, getCommandTimeout());
8051849b
VK
264 }
265 else
266 {
267 rcc = ERR_CONNECTION_BROKEN;
268 }
269 }
270 else
271 {
272 rcc = ERR_INTERNAL_ERROR;
273 }
45d84f8a
VK
274 return rcc;
275}
93599cfd 276
d1c1c522
VK
277/**
278 * Uninstall policy from agent
279 */
967893bb 280UINT32 AgentConnectionEx::uninstallPolicy(AgentPolicy *policy)
93599cfd 281{
967893bb 282 UINT32 rqId, rcc;
93599cfd
VK
283 CSCPMessage msg(getProtocolVersion());
284
285 rqId = generateRequestId();
286 msg.SetId(rqId);
287 msg.SetCode(CMD_UNINSTALL_AGENT_POLICY);
288 if (policy->createUninstallMessage(&msg))
289 {
7c521895 290 if (sendMessage(&msg))
93599cfd 291 {
7c521895 292 rcc = waitForRCC(rqId, getCommandTimeout());
93599cfd
VK
293 }
294 else
295 {
296 rcc = ERR_CONNECTION_BROKEN;
297 }
298 }
299 else
300 {
301 rcc = ERR_INTERNAL_ERROR;
302 }
303 return rcc;
304}